]> git.proxmox.com Git - rustc.git/commitdiff
New upstream version 1.55.0+dfsg1
authorXimin Luo <infinity0@debian.org>
Fri, 8 Oct 2021 12:53:48 +0000 (13:53 +0100)
committerXimin Luo <infinity0@debian.org>
Fri, 8 Oct 2021 12:53:48 +0000 (13:53 +0100)
4185 files changed:
Cargo.lock
Cargo.toml
README.md
RELEASES.md
compiler/rustc_apfloat/tests/ieee.rs
compiler/rustc_apfloat/tests/ppc.rs
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/entry.rs
compiler/rustc_ast/src/expand/allocator.rs
compiler/rustc_ast/src/lib.rs
compiler/rustc_ast/src/mut_visit.rs
compiler/rustc_ast/src/node_id.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_lowering/src/item.rs
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_ast_lowering/src/pat.rs
compiler/rustc_ast_lowering/src/path.rs
compiler/rustc_ast_passes/src/ast_validation.rs
compiler/rustc_ast_passes/src/feature_gate.rs
compiler/rustc_ast_pretty/src/pprust/state.rs
compiler/rustc_ast_pretty/src/pprust/tests.rs
compiler/rustc_attr/src/builtin.rs
compiler/rustc_builtin_macros/src/asm.rs
compiler/rustc_builtin_macros/src/cfg_eval.rs
compiler/rustc_builtin_macros/src/derive.rs
compiler/rustc_builtin_macros/src/deriving/clone.rs
compiler/rustc_builtin_macros/src/deriving/encodable.rs
compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
compiler/rustc_builtin_macros/src/format.rs
compiler/rustc_builtin_macros/src/lib.rs
compiler/rustc_builtin_macros/src/proc_macro_harness.rs
compiler/rustc_builtin_macros/src/source_util.rs
compiler/rustc_builtin_macros/src/standard_library_imports.rs
compiler/rustc_builtin_macros/src/test_harness.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/.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/allocator.rs
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/compiler_builtins.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/unsize.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/Cargo.toml
compiler/rustc_codegen_llvm/src/asm.rs
compiler/rustc_codegen_llvm/src/attributes.rs
compiler/rustc_codegen_llvm/src/back/archive.rs
compiler/rustc_codegen_llvm/src/builder.rs
compiler/rustc_codegen_llvm/src/common.rs
compiler/rustc_codegen_llvm/src/consts.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/debuginfo/mod.rs
compiler/rustc_codegen_llvm/src/debuginfo/namespace.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/llvm/mod.rs
compiler/rustc_codegen_llvm/src/llvm_util.rs
compiler/rustc_codegen_llvm/src/va_arg.rs
compiler/rustc_codegen_ssa/Cargo.toml
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/symbol_export.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/glue.rs
compiler/rustc_codegen_ssa/src/lib.rs
compiler/rustc_codegen_ssa/src/meth.rs
compiler/rustc_codegen_ssa/src/mir/analyze.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_codegen_ssa/src/traits/consts.rs
compiler/rustc_codegen_ssa/src/traits/misc.rs
compiler/rustc_data_structures/Cargo.toml
compiler/rustc_data_structures/src/captures.rs
compiler/rustc_data_structures/src/lib.rs
compiler/rustc_data_structures/src/obligation_forest/mod.rs
compiler/rustc_data_structures/src/profiling.rs
compiler/rustc_data_structures/src/sorted_map/index_map.rs
compiler/rustc_data_structures/src/sorted_map/tests.rs
compiler/rustc_data_structures/src/vec_map.rs
compiler/rustc_driver/Cargo.toml
compiler/rustc_driver/src/lib.rs
compiler/rustc_driver/src/pretty.rs
compiler/rustc_error_codes/src/error_codes.rs
compiler/rustc_error_codes/src/error_codes/E0094.md
compiler/rustc_error_codes/src/error_codes/E0493.md
compiler/rustc_error_codes/src/error_codes/E0508.md
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_error_codes/src/error_codes/E0632.md [new file with mode: 0644]
compiler/rustc_error_codes/src/error_codes/E0690.md
compiler/rustc_error_codes/src/error_codes/E0716.md
compiler/rustc_error_codes/src/error_codes/E0722.md [new file with mode: 0644]
compiler/rustc_error_codes/src/error_codes/E0757.md [new file with mode: 0644]
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/build.rs
compiler/rustc_expand/src/expand.rs
compiler/rustc_expand/src/mbe/macro_rules.rs
compiler/rustc_expand/src/mbe/transcribe.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/builtin_attrs.rs
compiler/rustc_feature/src/lib.rs
compiler/rustc_feature/src/removed.rs
compiler/rustc_graphviz/src/lib.rs
compiler/rustc_hir/src/definitions.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/lang_items.rs
compiler/rustc_hir/src/lib.rs
compiler/rustc_hir/src/stable_hash_impls.rs
compiler/rustc_hir/src/tests.rs
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_incremental/src/persist/fs.rs
compiler/rustc_incremental/src/persist/load.rs
compiler/rustc_infer/Cargo.toml
compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
compiler/rustc_infer/src/infer/error_reporting/mod.rs
compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs [new file with mode: 0644]
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
compiler/rustc_infer/src/infer/freshen.rs
compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_infer/src/infer/region_constraints/mod.rs
compiler/rustc_infer/src/infer/type_variable.rs
compiler/rustc_infer/src/traits/mod.rs
compiler/rustc_interface/Cargo.toml
compiler/rustc_interface/src/interface.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/queries.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_interface/src/util.rs
compiler/rustc_lexer/src/lib.rs
compiler/rustc_lint/src/array_into_iter.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/early.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/src/traits.rs
compiler/rustc_lint/src/unused.rs
compiler/rustc_lint_defs/Cargo.toml
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_lint_defs/src/lib.rs
compiler/rustc_llvm/Cargo.toml
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
compiler/rustc_macros/src/hash_stable.rs
compiler/rustc_macros/src/query.rs
compiler/rustc_macros/src/symbols.rs
compiler/rustc_metadata/Cargo.toml
compiler/rustc_metadata/src/creader.rs
compiler/rustc_metadata/src/dependency_format.rs
compiler/rustc_metadata/src/dynamic_lib.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/Cargo.toml
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/ich/impls_hir.rs
compiler/rustc_middle/src/lib.rs
compiler/rustc_middle/src/lint.rs
compiler/rustc_middle/src/middle/codegen_fn_attrs.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/abstract_const.rs
compiler/rustc_middle/src/mir/interpret/allocation.rs
compiler/rustc_middle/src/mir/interpret/error.rs
compiler/rustc_middle/src/mir/interpret/mod.rs
compiler/rustc_middle/src/mir/interpret/pointer.rs
compiler/rustc_middle/src/mir/interpret/value.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/thir.rs
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/ty/assoc.rs
compiler/rustc_middle/src/ty/closure.rs
compiler/rustc_middle/src/ty/consts/int.rs
compiler/rustc_middle/src/ty/consts/kind.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/fold.rs
compiler/rustc_middle/src/ty/instance.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/list.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/query.rs [new file with mode: 0644]
compiler/rustc_middle/src/ty/query/mod.rs [deleted file]
compiler/rustc_middle/src/ty/query/on_disk_cache.rs [deleted file]
compiler/rustc_middle/src/ty/relate.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_middle/src/ty/trait_def.rs
compiler/rustc_middle/src/ty/util.rs
compiler/rustc_middle/src/ty/vtable.rs [new file with mode: 0644]
compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs
compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
compiler/rustc_mir/src/borrow_check/member_constraints.rs
compiler/rustc_mir/src/borrow_check/region_infer/mod.rs
compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs
compiler/rustc_mir/src/borrow_check/type_check/input_output.rs
compiler/rustc_mir/src/borrow_check/type_check/mod.rs
compiler/rustc_mir/src/const_eval/error.rs
compiler/rustc_mir/src/const_eval/eval_queries.rs
compiler/rustc_mir/src/const_eval/machine.rs
compiler/rustc_mir/src/const_eval/mod.rs
compiler/rustc_mir/src/dataflow/mod.rs
compiler/rustc_mir/src/interpret/cast.rs
compiler/rustc_mir/src/interpret/eval_context.rs
compiler/rustc_mir/src/interpret/intern.rs
compiler/rustc_mir/src/interpret/intrinsics.rs
compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs
compiler/rustc_mir/src/interpret/machine.rs
compiler/rustc_mir/src/interpret/memory.rs
compiler/rustc_mir/src/interpret/operand.rs
compiler/rustc_mir/src/interpret/operator.rs
compiler/rustc_mir/src/interpret/place.rs
compiler/rustc_mir/src/interpret/step.rs
compiler/rustc_mir/src/interpret/terminator.rs
compiler/rustc_mir/src/interpret/traits.rs
compiler/rustc_mir/src/interpret/validity.rs
compiler/rustc_mir/src/interpret/visitor.rs
compiler/rustc_mir/src/lib.rs
compiler/rustc_mir/src/monomorphize/collector.rs
compiler/rustc_mir/src/monomorphize/mod.rs
compiler/rustc_mir/src/monomorphize/util.rs [new file with mode: 0644]
compiler/rustc_mir/src/transform/add_call_guards.rs
compiler/rustc_mir/src/transform/check_consts/ops.rs
compiler/rustc_mir/src/transform/check_consts/validation.rs
compiler/rustc_mir/src/transform/check_unsafety.rs
compiler/rustc_mir/src/transform/const_prop.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/src/transform/lower_slice_len.rs [new file with mode: 0644]
compiler/rustc_mir/src/transform/mod.rs
compiler/rustc_mir/src/transform/simplify_comparison_integral.rs
compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs
compiler/rustc_mir/src/util/pretty.rs
compiler/rustc_mir_build/src/build/block.rs
compiler/rustc_mir_build/src/build/expr/as_place.rs
compiler/rustc_mir_build/src/build/expr/into.rs
compiler/rustc_mir_build/src/build/expr/mod.rs
compiler/rustc_mir_build/src/build/mod.rs
compiler/rustc_mir_build/src/check_unsafety.rs
compiler/rustc_mir_build/src/thir/constant.rs
compiler/rustc_mir_build/src/thir/cx/block.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_mir_build/src/thir/cx/mod.rs
compiler/rustc_mir_build/src/thir/pattern/check_match.rs
compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
compiler/rustc_mir_build/src/thir/pattern/mod.rs
compiler/rustc_mir_build/src/thir/visit.rs
compiler/rustc_parse/Cargo.toml
compiler/rustc_parse/src/lexer/mod.rs
compiler/rustc_parse/src/lexer/unicode_chars.rs
compiler/rustc_parse/src/parser/attr.rs
compiler/rustc_parse/src/parser/expr.rs
compiler/rustc_parse/src/parser/item.rs
compiler/rustc_parse/src/parser/mod.rs
compiler/rustc_parse/src/parser/nonterminal.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/Cargo.toml
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/check_const.rs
compiler/rustc_passes/src/dead.rs
compiler/rustc_passes/src/diagnostic_items.rs
compiler/rustc_passes/src/entry.rs
compiler/rustc_passes/src/lang_items.rs
compiler/rustc_passes/src/lib.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_passes/src/weak_lang_items.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_query_impl/Cargo.toml
compiler/rustc_query_impl/src/keys.rs
compiler/rustc_query_impl/src/lib.rs
compiler/rustc_query_impl/src/on_disk_cache.rs [new file with mode: 0644]
compiler/rustc_query_impl/src/plumbing.rs
compiler/rustc_query_impl/src/stats.rs
compiler/rustc_query_system/src/dep_graph/graph.rs
compiler/rustc_query_system/src/query/config.rs
compiler/rustc_query_system/src/query/plumbing.rs
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/def_collector.rs
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/imports.rs
compiler/rustc_resolve/src/late/diagnostics.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_serialize/src/json.rs
compiler/rustc_serialize/tests/json.rs
compiler/rustc_session/Cargo.toml
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/lib.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/parse.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/Cargo.toml
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/source_map.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/Cargo.toml
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/abi/call/msp430.rs
compiler/rustc_target/src/abi/call/nvptx.rs
compiler/rustc_target/src/abi/call/nvptx64.rs
compiler/rustc_target/src/abi/call/x86.rs
compiler/rustc_target/src/abi/call/x86_64.rs
compiler/rustc_target/src/abi/mod.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/lib.rs
compiler/rustc_target/src/spec/aarch64_apple_darwin.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/apple_base.rs
compiler/rustc_target/src/spec/apple_sdk_base.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/freebsd_base.rs
compiler/rustc_target/src/spec/i686_apple_darwin.rs
compiler/rustc_target/src/spec/i686_linux_android.rs
compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs
compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs
compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs
compiler/rustc_target/src/spec/illumos_base.rs
compiler/rustc_target/src/spec/linux_kernel_base.rs
compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs
compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs
compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs
compiler/rustc_target/src/spec/mipsel_unknown_none.rs
compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs
compiler/rustc_target/src/spec/openbsd_base.rs
compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs [new file with mode: 0644]
compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.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/tests/tests_impl.rs
compiler/rustc_target/src/spec/thumb_base.rs
compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
compiler/rustc_target/src/spec/thumbv6m_none_eabi.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/thumbv7em_none_eabi.rs
compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs
compiler/rustc_target/src/spec/thumbv7m_none_eabi.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_target/src/spec/thumbv8m_base_none_eabi.rs
compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs
compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs
compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs
compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs
compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs
compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs
compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs
compiler/rustc_target/src/tests.rs [new file with mode: 0644]
compiler/rustc_trait_selection/src/autoderef.rs
compiler/rustc_trait_selection/src/infer.rs
compiler/rustc_trait_selection/src/opaque_types.rs
compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/fulfill.rs
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_trait_selection/src/traits/object_safety.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
compiler/rustc_trait_selection/src/traits/query/normalize.rs
compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
compiler/rustc_trait_selection/src/traits/select/confirmation.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_trait_selection/src/traits/structural_match.rs
compiler/rustc_trait_selection/src/traits/wf.rs
compiler/rustc_traits/src/chalk/lowering.rs
compiler/rustc_traits/src/dropck_outlives.rs
compiler/rustc_traits/src/lib.rs
compiler/rustc_traits/src/type_op.rs
compiler/rustc_ty_utils/src/instance.rs
compiler/rustc_ty_utils/src/lib.rs
compiler/rustc_ty_utils/src/needs_drop.rs
compiler/rustc_ty_utils/src/ty.rs
compiler/rustc_typeck/src/astconv/mod.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/compare_method.rs
compiler/rustc_typeck/src/check/demand.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
compiler/rustc_typeck/src/check/gather_locals.rs
compiler/rustc_typeck/src/check/inherited.rs
compiler/rustc_typeck/src/check/intrinsic.rs
compiler/rustc_typeck/src/check/method/confirm.rs
compiler/rustc_typeck/src/check/method/mod.rs
compiler/rustc_typeck/src/check/method/prelude2021.rs [new file with mode: 0644]
compiler/rustc_typeck/src/check/method/probe.rs
compiler/rustc_typeck/src/check/method/suggest.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check/pat.rs
compiler/rustc_typeck/src/check/place_op.rs
compiler/rustc_typeck/src/check/upvar.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/check/writeback.rs
compiler/rustc_typeck/src/check_unused.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect/type_of.rs
compiler/rustc_typeck/src/errors.rs
compiler/rustc_typeck/src/expr_use_visitor.rs
compiler/rustc_typeck/src/hir_wf_check.rs [new file with mode: 0644]
compiler/rustc_typeck/src/lib.rs
config.toml.example
git-commit-hash
library/alloc/benches/btree/map.rs
library/alloc/src/borrow.rs
library/alloc/src/boxed.rs
library/alloc/src/collections/binary_heap.rs
library/alloc/src/collections/btree/fix.rs
library/alloc/src/collections/btree/map.rs
library/alloc/src/collections/btree/map/entry.rs
library/alloc/src/collections/btree/navigate.rs
library/alloc/src/collections/btree/node.rs
library/alloc/src/collections/btree/set.rs
library/alloc/src/collections/linked_list.rs
library/alloc/src/collections/linked_list/tests.rs
library/alloc/src/collections/mod.rs
library/alloc/src/collections/vec_deque/iter.rs
library/alloc/src/collections/vec_deque/iter_mut.rs
library/alloc/src/collections/vec_deque/mod.rs
library/alloc/src/lib.rs
library/alloc/src/macros.rs
library/alloc/src/raw_vec.rs
library/alloc/src/rc.rs
library/alloc/src/slice.rs
library/alloc/src/str.rs
library/alloc/src/string.rs
library/alloc/src/sync.rs
library/alloc/src/vec/into_iter.rs
library/alloc/src/vec/mod.rs
library/alloc/src/vec/source_iter_marker.rs
library/alloc/src/vec/spec_extend.rs
library/alloc/tests/str.rs
library/alloc/tests/vec.rs
library/core/benches/iter.rs
library/core/src/alloc/global.rs
library/core/src/alloc/layout.rs
library/core/src/any.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/cell.rs
library/core/src/char/methods.rs
library/core/src/char/mod.rs
library/core/src/clone.rs
library/core/src/cmp.rs
library/core/src/convert/mod.rs
library/core/src/convert/num.rs
library/core/src/fmt/float.rs
library/core/src/fmt/mod.rs
library/core/src/fmt/nofloat.rs [new file with mode: 0644]
library/core/src/fmt/num.rs
library/core/src/hash/mod.rs
library/core/src/intrinsics.rs
library/core/src/iter/adapters/cloned.rs
library/core/src/iter/adapters/copied.rs
library/core/src/iter/adapters/enumerate.rs
library/core/src/iter/adapters/flatten.rs
library/core/src/iter/adapters/fuse.rs
library/core/src/iter/adapters/map.rs
library/core/src/iter/adapters/mod.rs
library/core/src/iter/adapters/peekable.rs
library/core/src/iter/adapters/zip.rs
library/core/src/iter/range.rs
library/core/src/iter/sources/repeat.rs
library/core/src/iter/traits/accum.rs
library/core/src/iter/traits/collect.rs
library/core/src/iter/traits/double_ended.rs
library/core/src/iter/traits/exact_size.rs
library/core/src/iter/traits/iterator.rs
library/core/src/lib.rs
library/core/src/macros/mod.rs
library/core/src/marker.rs
library/core/src/mem/maybe_uninit.rs
library/core/src/mem/mod.rs
library/core/src/num/dec2flt/algorithm.rs [deleted file]
library/core/src/num/dec2flt/common.rs [new file with mode: 0644]
library/core/src/num/dec2flt/decimal.rs [new file with mode: 0644]
library/core/src/num/dec2flt/float.rs [new file with mode: 0644]
library/core/src/num/dec2flt/fpu.rs [new file with mode: 0644]
library/core/src/num/dec2flt/lemire.rs [new file with mode: 0644]
library/core/src/num/dec2flt/mod.rs
library/core/src/num/dec2flt/num.rs [deleted file]
library/core/src/num/dec2flt/number.rs [new file with mode: 0644]
library/core/src/num/dec2flt/parse.rs
library/core/src/num/dec2flt/rawfp.rs [deleted file]
library/core/src/num/dec2flt/slow.rs [new file with mode: 0644]
library/core/src/num/dec2flt/table.rs
library/core/src/num/error.rs
library/core/src/num/flt2dec/decoder.rs
library/core/src/num/flt2dec/mod.rs
library/core/src/num/fmt.rs [new file with mode: 0644]
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/nonzero.rs
library/core/src/num/uint_macros.rs
library/core/src/ops/control_flow.rs
library/core/src/ops/drop.rs
library/core/src/ops/mod.rs
library/core/src/ops/range.rs
library/core/src/ops/try.rs [deleted file]
library/core/src/ops/try_trait.rs
library/core/src/option.rs
library/core/src/prelude/mod.rs
library/core/src/prelude/v1.rs
library/core/src/ptr/metadata.rs
library/core/src/ptr/mod.rs
library/core/src/ptr/mut_ptr.rs
library/core/src/ptr/non_null.rs
library/core/src/raw.rs [deleted file]
library/core/src/result.rs
library/core/src/slice/iter.rs
library/core/src/slice/mod.rs
library/core/src/slice/rotate.rs
library/core/src/slice/sort.rs
library/core/src/str/converts.rs
library/core/src/str/error.rs
library/core/src/str/iter.rs
library/core/src/str/mod.rs
library/core/src/str/traits.rs
library/core/src/sync/atomic.rs
library/core/src/task/poll.rs
library/core/src/time.rs
library/core/src/unicode/mod.rs
library/core/src/unicode/printable.py
library/core/tests/const_ptr.rs
library/core/tests/hash/mod.rs
library/core/tests/iter/adapters/flatten.rs
library/core/tests/iter/adapters/zip.rs
library/core/tests/lib.rs
library/core/tests/manually_drop.rs
library/core/tests/mem.rs
library/core/tests/num/dec2flt/float.rs [new file with mode: 0644]
library/core/tests/num/dec2flt/lemire.rs [new file with mode: 0644]
library/core/tests/num/dec2flt/mod.rs
library/core/tests/num/dec2flt/parse.rs
library/core/tests/num/dec2flt/rawfp.rs [deleted file]
library/core/tests/num/flt2dec/mod.rs
library/core/tests/num/int_log.rs [new file with mode: 0644]
library/core/tests/num/mod.rs
library/core/tests/result.rs
library/panic_unwind/src/dwarf/eh.rs
library/panic_unwind/src/gcc.rs
library/panic_unwind/src/lib.rs
library/panic_unwind/src/seh.rs
library/proc_macro/src/bridge/buffer.rs
library/proc_macro/src/bridge/mod.rs
library/proc_macro/src/bridge/rpc.rs
library/proc_macro/src/lib.rs
library/profiler_builtins/Cargo.toml
library/std/src/backtrace.rs
library/std/src/collections/hash/map.rs
library/std/src/collections/hash/set.rs
library/std/src/env.rs
library/std/src/error.rs
library/std/src/f32.rs
library/std/src/f32/tests.rs
library/std/src/f64.rs
library/std/src/f64/tests.rs
library/std/src/ffi/mod.rs
library/std/src/ffi/os_str.rs
library/std/src/fs.rs
library/std/src/fs/tests.rs
library/std/src/io/buffered/bufreader.rs
library/std/src/io/buffered/bufwriter.rs
library/std/src/io/buffered/mod.rs
library/std/src/io/cursor.rs
library/std/src/io/error.rs
library/std/src/io/mod.rs
library/std/src/io/stdio.rs
library/std/src/io/stdio/tests.rs
library/std/src/io/tests.rs
library/std/src/io/util.rs
library/std/src/keyword_docs.rs
library/std/src/lib.rs
library/std/src/macros.rs
library/std/src/net/ip.rs
library/std/src/net/ip/tests.rs
library/std/src/net/tcp/tests.rs
library/std/src/num.rs
library/std/src/os/fortanix_sgx/arch.rs
library/std/src/os/fortanix_sgx/ffi.rs
library/std/src/os/hermit/ffi.rs
library/std/src/os/unix/ffi.rs [deleted file]
library/std/src/os/unix/ffi/mod.rs [new file with mode: 0644]
library/std/src/os/unix/ffi/os_str.rs [new file with mode: 0644]
library/std/src/os/unix/fs.rs
library/std/src/os/unix/net/ancillary.rs
library/std/src/os/unix/process.rs
library/std/src/os/wasi/ffi.rs
library/std/src/os/wasi/fs.rs
library/std/src/os/wasi/io.rs
library/std/src/os/windows/process.rs
library/std/src/panic.rs
library/std/src/path.rs
library/std/src/prelude/mod.rs
library/std/src/prelude/v1.rs
library/std/src/primitive_docs.rs
library/std/src/process.rs
library/std/src/process/tests.rs
library/std/src/rt.rs
library/std/src/sync/mpsc/mod.rs
library/std/src/sync/mpsc/mpsc_queue.rs
library/std/src/sync/mpsc/spsc_queue.rs
library/std/src/sync/mutex.rs
library/std/src/sync/rwlock.rs
library/std/src/sys/hermit/args.rs
library/std/src/sys/hermit/fs.rs
library/std/src/sys/hermit/mod.rs
library/std/src/sys/hermit/mutex.rs
library/std/src/sys/hermit/net.rs
library/std/src/sys/hermit/os.rs
library/std/src/sys/hermit/stdio.rs
library/std/src/sys/hermit/thread.rs
library/std/src/sys/sgx/abi/mem.rs
library/std/src/sys/sgx/mod.rs
library/std/src/sys/sgx/net.rs
library/std/src/sys/sgx/stdio.rs
library/std/src/sys/sgx/thread.rs
library/std/src/sys/unix/android.rs
library/std/src/sys/unix/args.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/net.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/unsupported/common.rs
library/std/src/sys/unsupported/thread.rs
library/std/src/sys/wasi/fs.rs
library/std/src/sys/wasi/mod.rs
library/std/src/sys/wasi/thread.rs
library/std/src/sys/wasm/atomics/thread.rs
library/std/src/sys/windows/c.rs
library/std/src/sys/windows/c/errors.rs [new file with mode: 0644]
library/std/src/sys/windows/fs.rs
library/std/src/sys/windows/mod.rs
library/std/src/sys/windows/net.rs
library/std/src/sys/windows/process.rs
library/std/src/sys/windows/process/tests.rs
library/std/src/sys/windows/thread.rs
library/std/src/sys/windows/thread_local_key.rs
library/std/src/sys_common/bytestring.rs [deleted file]
library/std/src/sys_common/bytestring/tests.rs [deleted file]
library/std/src/sys_common/mod.rs
library/std/src/sys_common/os_str_bytes.rs
library/std/src/sys_common/os_str_bytes/tests.rs [new file with mode: 0644]
library/std/src/sys_common/process.rs
library/std/src/sys_common/wtf8.rs
library/std/src/sys_common/wtf8/tests.rs
library/std/src/thread/available_concurrency.rs [deleted file]
library/std/src/thread/local.rs
library/std/src/thread/local/tests.rs
library/std/src/thread/mod.rs
library/std/src/time.rs
library/stdarch/crates/core_arch/src/x86/bt.rs
library/stdarch/crates/core_arch/src/x86_64/bt.rs
library/term/Cargo.toml [deleted file]
library/term/src/lib.rs [deleted file]
library/term/src/terminfo/mod.rs [deleted file]
library/term/src/terminfo/parm.rs [deleted file]
library/term/src/terminfo/parm/tests.rs [deleted file]
library/term/src/terminfo/parser/compiled.rs [deleted file]
library/term/src/terminfo/parser/compiled/tests.rs [deleted file]
library/term/src/terminfo/searcher.rs [deleted file]
library/term/src/terminfo/searcher/tests.rs [deleted file]
library/term/src/win.rs [deleted file]
library/test/Cargo.toml
library/test/src/console.rs
library/test/src/formatters/junit.rs
library/test/src/formatters/pretty.rs
library/test/src/formatters/terse.rs
library/test/src/lib.rs
library/test/src/stats.rs
library/test/src/term.rs [new file with mode: 0644]
library/test/src/term/terminfo/mod.rs [new file with mode: 0644]
library/test/src/term/terminfo/parm.rs [new file with mode: 0644]
library/test/src/term/terminfo/parm/tests.rs [new file with mode: 0644]
library/test/src/term/terminfo/parser/compiled.rs [new file with mode: 0644]
library/test/src/term/terminfo/parser/compiled/tests.rs [new file with mode: 0644]
library/test/src/term/terminfo/searcher.rs [new file with mode: 0644]
library/test/src/term/terminfo/searcher/tests.rs [new file with mode: 0644]
library/test/src/term/win.rs [new file with mode: 0644]
library/test/src/tests.rs
library/test/src/types.rs
library/unwind/Cargo.toml
src/bootstrap/Cargo.toml
src/bootstrap/bootstrap.py
src/bootstrap/builder.rs
src/bootstrap/builder/tests.rs
src/bootstrap/check.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/configure.py
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/flags.rs
src/bootstrap/job.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/test.rs
src/bootstrap/tool.rs
src/build_helper/lib.rs
src/ci/cpu-usage-over-time.py
src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
src/ci/docker/host-x86_64/disabled/dist-x86_64-dragonfly/build-toolchain.sh
src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config
src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.config
src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.config
src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile
src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.config
src/ci/docker/host-x86_64/dist-various-2/Dockerfile
src/ci/docker/host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh
src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
src/ci/docker/host-x86_64/dist-x86_64-linux/build-binutils.sh
src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
src/ci/docker/host-x86_64/dist-x86_64-linux/build-cmake.sh
src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh
src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh
src/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh
src/ci/docker/host-x86_64/dist-x86_64-linux/build-python.sh
src/ci/docker/host-x86_64/mingw-check/Dockerfile
src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile
src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
src/ci/github-actions/ci.yml
src/ci/pgo.sh
src/ci/scripts/collect-cpu-stats.sh
src/ci/scripts/should-skip-this.sh
src/ci/shared.sh
src/doc/book/ferris.js
src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml
src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.toml
src/doc/book/listings/ch04-understanding-ownership/listing-04-09/src/main.rs
src/doc/book/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs
src/doc/book/listings/ch14-more-about-cargo/listing-14-03/src/lib.rs
src/doc/book/listings/ch14-more-about-cargo/no-listing-01-workspace-with-adder-crate/add/adder/Cargo.toml
src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/add-one/Cargo.toml
src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/adder/Cargo.toml
src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add-one/Cargo.toml
src/doc/book/listings/ch19-advanced-features/listing-19-14/src/main.rs
src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml
src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml
src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml
src/doc/book/nostarch/chapter02.md [new file with mode: 0644]
src/doc/book/src/appendix-02-operators.md
src/doc/book/src/appendix-06-translation.md
src/doc/book/src/ch00-00-introduction.md
src/doc/book/src/ch01-01-installation.md
src/doc/book/src/ch01-02-hello-world.md
src/doc/book/src/ch01-03-hello-cargo.md
src/doc/book/src/ch02-00-guessing-game-tutorial.md
src/doc/book/src/ch03-02-data-types.md
src/doc/book/src/ch04-03-slices.md
src/doc/book/src/ch06-01-defining-an-enum.md
src/doc/book/src/ch07-01-packages-and-crates.md
src/doc/book/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md
src/doc/book/src/ch08-02-strings.md
src/doc/book/src/ch08-03-hash-maps.md
src/doc/book/src/ch10-02-traits.md
src/doc/book/src/ch11-03-test-organization.md
src/doc/book/src/ch12-04-testing-the-librarys-functionality.md
src/doc/book/src/ch12-05-working-with-environment-variables.md
src/doc/book/src/ch13-04-performance.md
src/doc/book/src/ch14-02-publishing-to-crates-io.md
src/doc/book/src/ch15-02-deref.md
src/doc/book/src/ch15-04-rc.md
src/doc/book/src/ch17-02-trait-objects.md
src/doc/book/src/ch19-01-unsafe-rust.md
src/doc/book/src/ch19-03-advanced-traits.md
src/doc/book/src/ch19-04-advanced-types.md
src/doc/book/src/ch19-06-macros.md
src/doc/book/src/ch20-02-multithreaded.md
src/doc/book/src/img/ferris/unsafe.svg [deleted file]
src/doc/book/tools/src/bin/convert_quotes.rs
src/doc/book/tools/src/bin/link2print.rs
src/doc/book/tools/src/bin/remove_hidden_lines.rs
src/doc/book/tools/src/bin/remove_links.rs
src/doc/book/tools/src/bin/remove_markup.rs
src/doc/edition-guide/src/SUMMARY.md
src/doc/edition-guide/src/editions/advanced-migrations.md [new file with mode: 0644]
src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md
src/doc/edition-guide/src/rust-2021/IntoIterator-for-arrays.md
src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md
src/doc/edition-guide/src/rust-2021/disjoint-capture-in-closures.md
src/doc/edition-guide/src/rust-2021/or-patterns-macro-rules.md
src/doc/edition-guide/src/rust-2021/panic-macro-consistency.md
src/doc/edition-guide/src/rust-2021/prelude.md
src/doc/edition-guide/src/rust-2021/reserving-syntax.md
src/doc/edition-guide/src/rust-2021/warnings-promoted-to-error.md
src/doc/edition-guide/triagebot.toml [new file with mode: 0644]
src/doc/embedded-book/src/collections/index.md
src/doc/embedded-book/src/interoperability/c-with-rust.md
src/doc/embedded-book/src/start/hardware.md
src/doc/embedded-book/src/start/qemu.md
src/doc/embedded-book/src/start/semihosting.md
src/doc/embedded-book/src/unsorted/speed-vs-size.md
src/doc/nomicon/README.md
src/doc/nomicon/book.toml
src/doc/nomicon/src/README.md [deleted file]
src/doc/nomicon/src/SUMMARY.md
src/doc/nomicon/src/aliasing.md
src/doc/nomicon/src/arc-and-mutex.md [deleted file]
src/doc/nomicon/src/arc-base.md [deleted file]
src/doc/nomicon/src/arc-clone.md [deleted file]
src/doc/nomicon/src/arc-drop.md [deleted file]
src/doc/nomicon/src/arc-final.md [deleted file]
src/doc/nomicon/src/arc-layout.md [deleted file]
src/doc/nomicon/src/arc-mutex/arc-and-mutex.md [new file with mode: 0644]
src/doc/nomicon/src/arc-mutex/arc-base.md [new file with mode: 0644]
src/doc/nomicon/src/arc-mutex/arc-clone.md [new file with mode: 0644]
src/doc/nomicon/src/arc-mutex/arc-drop.md [new file with mode: 0644]
src/doc/nomicon/src/arc-mutex/arc-final.md [new file with mode: 0644]
src/doc/nomicon/src/arc-mutex/arc-layout.md [new file with mode: 0644]
src/doc/nomicon/src/arc-mutex/arc.md [new file with mode: 0644]
src/doc/nomicon/src/arc.md [deleted file]
src/doc/nomicon/src/atomics.md
src/doc/nomicon/src/beneath-std.md
src/doc/nomicon/src/casts.md
src/doc/nomicon/src/coercions.md
src/doc/nomicon/src/conversions.md
src/doc/nomicon/src/destructors.md
src/doc/nomicon/src/dropck.md
src/doc/nomicon/src/exception-safety.md
src/doc/nomicon/src/exotic-sizes.md
src/doc/nomicon/src/ffi.md
src/doc/nomicon/src/hrtb.md
src/doc/nomicon/src/intro.md [new file with mode: 0644]
src/doc/nomicon/src/leaking.md
src/doc/nomicon/src/lifetime-elision.md
src/doc/nomicon/src/lifetime-mismatch.md
src/doc/nomicon/src/lifetimes.md
src/doc/nomicon/src/other-reprs.md
src/doc/nomicon/src/ownership.md
src/doc/nomicon/src/panic-handler.md
src/doc/nomicon/src/phantom-data.md
src/doc/nomicon/src/repr-rust.md
src/doc/nomicon/src/subtyping.md
src/doc/nomicon/src/transmutes.md
src/doc/nomicon/src/unbounded-lifetimes.md
src/doc/nomicon/src/unchecked-uninit.md
src/doc/nomicon/src/vec-alloc.md [deleted file]
src/doc/nomicon/src/vec-dealloc.md [deleted file]
src/doc/nomicon/src/vec-deref.md [deleted file]
src/doc/nomicon/src/vec-drain.md [deleted file]
src/doc/nomicon/src/vec-final.md [deleted file]
src/doc/nomicon/src/vec-insert-remove.md [deleted file]
src/doc/nomicon/src/vec-into-iter.md [deleted file]
src/doc/nomicon/src/vec-layout.md [deleted file]
src/doc/nomicon/src/vec-push-pop.md [deleted file]
src/doc/nomicon/src/vec-raw.md [deleted file]
src/doc/nomicon/src/vec-zsts.md [deleted file]
src/doc/nomicon/src/vec.md [deleted file]
src/doc/nomicon/src/vec/vec-alloc.md [new file with mode: 0644]
src/doc/nomicon/src/vec/vec-dealloc.md [new file with mode: 0644]
src/doc/nomicon/src/vec/vec-deref.md [new file with mode: 0644]
src/doc/nomicon/src/vec/vec-drain.md [new file with mode: 0644]
src/doc/nomicon/src/vec/vec-final.md [new file with mode: 0644]
src/doc/nomicon/src/vec/vec-insert-remove.md [new file with mode: 0644]
src/doc/nomicon/src/vec/vec-into-iter.md [new file with mode: 0644]
src/doc/nomicon/src/vec/vec-layout.md [new file with mode: 0644]
src/doc/nomicon/src/vec/vec-push-pop.md [new file with mode: 0644]
src/doc/nomicon/src/vec/vec-raw.md [new file with mode: 0644]
src/doc/nomicon/src/vec/vec-zsts.md [new file with mode: 0644]
src/doc/nomicon/src/vec/vec.md [new file with mode: 0644]
src/doc/nomicon/src/what-unsafe-does.md
src/doc/nomicon/src/working-with-unsafe.md
src/doc/nomicon/theme/nomicon.css [new file with mode: 0644]
src/doc/reference.md
src/doc/reference/book.toml
src/doc/reference/src/attributes/codegen.md
src/doc/reference/src/destructors.md
src/doc/reference/src/dynamically-sized-types.md
src/doc/reference/src/expressions.md
src/doc/reference/src/expressions/array-expr.md
src/doc/reference/src/expressions/block-expr.md
src/doc/reference/src/expressions/grouped-expr.md
src/doc/reference/src/expressions/if-expr.md
src/doc/reference/src/expressions/loop-expr.md
src/doc/reference/src/expressions/match-expr.md
src/doc/reference/src/expressions/operator-expr.md
src/doc/reference/src/expressions/struct-expr.md
src/doc/reference/src/expressions/tuple-expr.md
src/doc/reference/src/introduction.md
src/doc/reference/src/items/associated-items.md
src/doc/reference/src/items/functions.md
src/doc/reference/src/items/generics.md
src/doc/reference/src/items/static-items.md
src/doc/reference/src/items/traits.md
src/doc/reference/src/items/type-aliases.md
src/doc/reference/src/items/use-declarations.md
src/doc/reference/src/macro-ambiguity.md
src/doc/reference/src/macros.md
src/doc/reference/src/names/namespaces.md
src/doc/reference/src/paths.md
src/doc/reference/src/special-types-and-traits.md
src/doc/reference/src/statements.md
src/doc/reference/src/trait-bounds.md
src/doc/reference/src/type-layout.md
src/doc/reference/src/types/closure.md
src/doc/reference/src/visibility-and-privacy.md
src/doc/rust-by-example/.github/workflows/rbe.yml [new file with mode: 0644]
src/doc/rust-by-example/src/custom_types/structs.md
src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_tuple.md
src/doc/rust-by-example/src/fn/methods.md
src/doc/rust-by-example/src/std_misc/file/create.md
src/doc/rust-by-example/src/std_misc/file/open.md
src/doc/rust-by-example/src/std_misc/path.md
src/doc/rust-by-example/src/testing/integration_testing.md
src/doc/rust-by-example/src/trait.md
src/doc/rust.css
src/doc/rustc-dev-guide/README.md
src/doc/rustc-dev-guide/src/SUMMARY.md
src/doc/rustc-dev-guide/src/about-this-guide.md
src/doc/rustc-dev-guide/src/appendix/glossary.md
src/doc/rustc-dev-guide/src/ast-validation.md
src/doc/rustc-dev-guide/src/backend/inline-asm.md
src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md
src/doc/rustc-dev-guide/src/building/suggested.md
src/doc/rustc-dev-guide/src/compiler-src.md
src/doc/rustc-dev-guide/src/contributing.md
src/doc/rustc-dev-guide/src/crates-io.md
src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md
src/doc/rustc-dev-guide/src/diagnostics.md
src/doc/rustc-dev-guide/src/diagnostics/lintstore.md
src/doc/rustc-dev-guide/src/feature-gate-ck.md
src/doc/rustc-dev-guide/src/feature-gates.md
src/doc/rustc-dev-guide/src/git.md
src/doc/rustc-dev-guide/src/hir-debugging.md
src/doc/rustc-dev-guide/src/identifiers.md
src/doc/rustc-dev-guide/src/lang-items.md [new file with mode: 0644]
src/doc/rustc-dev-guide/src/macro-expansion.md
src/doc/rustc-dev-guide/src/miri.md
src/doc/rustc-dev-guide/src/name-resolution.md
src/doc/rustc-dev-guide/src/overview.md
src/doc/rustc-dev-guide/src/parallel-rustc.md
src/doc/rustc-dev-guide/src/query.md
src/doc/rustc-dev-guide/src/salsa.md
src/doc/rustc-dev-guide/src/stability.md
src/doc/rustc-dev-guide/src/tests/running.md
src/doc/rustc-dev-guide/src/type-checking.md
src/doc/rustc-dev-guide/src/type-inference.md
src/doc/rustc-dev-guide/src/walkthrough.md
src/doc/rustc/src/platform-support.md
src/doc/rustdoc/src/SUMMARY.md
src/doc/rustdoc/src/command-line-arguments.md
src/doc/rustdoc/src/website-features.md [new file with mode: 0644]
src/doc/unstable-book/src/compiler-flags/force-warn.md [new file with mode: 0644]
src/doc/unstable-book/src/compiler-flags/force-warns.md [deleted file]
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/language-features/impl-trait-in-bindings.md [deleted file]
src/doc/unstable-book/src/library-features/asm.md
src/doc/unstable-book/src/library-features/try-trait.md [deleted file]
src/etc/dec2flt_table.py [changed mode: 0755->0644]
src/etc/gdb_lookup.py
src/etc/gdb_providers.py
src/etc/installer/README.md
src/etc/lldb_commands
src/etc/natvis/intrinsic.natvis
src/etc/natvis/liballoc.natvis
src/etc/natvis/libcore.natvis
src/etc/natvis/libstd.natvis
src/etc/rust_types.py
src/etc/test-float-parse/Cargo.toml [new file with mode: 0644]
src/etc/test-float-parse/_common.rs [deleted file]
src/etc/test-float-parse/few-ones.rs [deleted file]
src/etc/test-float-parse/huge-pow10.rs [deleted file]
src/etc/test-float-parse/long-fractions.rs [deleted file]
src/etc/test-float-parse/many-digits.rs [deleted file]
src/etc/test-float-parse/rand-f64.rs [deleted file]
src/etc/test-float-parse/runtests.py
src/etc/test-float-parse/short-decimals.rs [deleted file]
src/etc/test-float-parse/src/bin/few-ones.rs [new file with mode: 0644]
src/etc/test-float-parse/src/bin/huge-pow10.rs [new file with mode: 0644]
src/etc/test-float-parse/src/bin/long-fractions.rs [new file with mode: 0644]
src/etc/test-float-parse/src/bin/many-digits.rs [new file with mode: 0644]
src/etc/test-float-parse/src/bin/rand-f64.rs [new file with mode: 0644]
src/etc/test-float-parse/src/bin/short-decimals.rs [new file with mode: 0644]
src/etc/test-float-parse/src/bin/subnorm.rs [new file with mode: 0644]
src/etc/test-float-parse/src/bin/tiny-pow10.rs [new file with mode: 0644]
src/etc/test-float-parse/src/bin/u32-small.rs [new file with mode: 0644]
src/etc/test-float-parse/src/bin/u64-pow2.rs [new file with mode: 0644]
src/etc/test-float-parse/src/lib.rs [new file with mode: 0644]
src/etc/test-float-parse/subnorm.rs [deleted file]
src/etc/test-float-parse/tiny-pow10.rs [deleted file]
src/etc/test-float-parse/u32-small.rs [deleted file]
src/etc/test-float-parse/u64-pow2.rs [deleted file]
src/librustdoc/Cargo.toml
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/simplify.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/externalfiles.rs
src/librustdoc/formats/cache.rs
src/librustdoc/html/format.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/highlight/tests.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/markdown/tests.rs
src/librustdoc/html/render/cache.rs
src/librustdoc/html/render/context.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/render/write_shared.rs
src/librustdoc/html/sources.rs
src/librustdoc/html/static/COPYRIGHT.txt
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-LICENSE.txt [deleted file]
src/librustdoc/html/static/SourceCodePro-Regular.ttf.woff [deleted file]
src/librustdoc/html/static/SourceCodePro-Semibold.ttf.woff [deleted file]
src/librustdoc/html/static/SourceSerif4-Bold.ttf.woff [deleted file]
src/librustdoc/html/static/SourceSerif4-It.ttf.woff [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/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/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/html/templates/STYLE.md [new file with mode: 0644]
src/librustdoc/html/templates/page.html [new file with mode: 0644]
src/librustdoc/json/conversions.rs
src/librustdoc/json/mod.rs
src/librustdoc/lib.rs
src/librustdoc/lint.rs
src/librustdoc/markdown.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/stage0.txt
src/test/assembly/asm/mips-types.rs
src/test/assembly/asm/powerpc-types.rs
src/test/assembly/asm/riscv-types.rs
src/test/assembly/asm/x86-modifiers.rs
src/test/assembly/asm/x86-types.rs
src/test/assembly/static-relocation-model.rs
src/test/codegen/abi-efiapi.rs
src/test/codegen/align-fn.rs [new file with mode: 0644]
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/asm-options.rs
src/test/codegen/asm-sanitize-llvm.rs
src/test/codegen/async-fn-debug-msvc.rs
src/test/codegen/async-fn-debug.rs
src/test/codegen/consts.rs
src/test/codegen/default-requires-uwtable.rs
src/test/codegen/fn-impl-trait-self.rs
src/test/codegen/frame-pointer.rs [new file with mode: 0644]
src/test/codegen/generator-debug-msvc.rs
src/test/codegen/generator-debug.rs
src/test/codegen/i686-macosx-deployment-target.rs
src/test/codegen/i686-no-macosx-deployment-target.rs
src/test/codegen/pgo-instrumentation.rs
src/test/codegen/remap_path_prefix/main.rs
src/test/codegen/slice-ref-equality.rs
src/test/codegen/sparc-struct-abi.rs
src/test/codegen/unwind-abis/stdcall-unwind-abi.rs
src/test/codegen/unwind-abis/thiscall-unwind-abi.rs
src/test/codegen/x86_64-macosx-deployment-target.rs
src/test/codegen/x86_64-no-macosx-deployment-target.rs
src/test/debuginfo/basic-types.rs
src/test/debuginfo/duration-type.rs [new file with mode: 0644]
src/test/debuginfo/fixed-sized-array.rs [new file with mode: 0644]
src/test/debuginfo/function-names.rs [new file with mode: 0644]
src/test/debuginfo/generator-objects.rs
src/test/debuginfo/generic-struct.rs
src/test/debuginfo/issue-57822.rs
src/test/debuginfo/marker-types.rs [new file with mode: 0644]
src/test/debuginfo/msvc-pretty-enums.rs
src/test/debuginfo/mutable-locs.rs [new file with mode: 0644]
src/test/debuginfo/mutex.rs [new file with mode: 0644]
src/test/debuginfo/numeric-types.rs [new file with mode: 0644]
src/test/debuginfo/pretty-huge-vec.rs
src/test/debuginfo/pretty-slices.rs [new file with mode: 0644]
src/test/debuginfo/pretty-std-collections-hash.rs
src/test/debuginfo/pretty-std.rs
src/test/debuginfo/range-types.rs [new file with mode: 0644]
src/test/debuginfo/rc_arc.rs
src/test/debuginfo/result-types.rs [new file with mode: 0644]
src/test/debuginfo/rwlock-read.rs [new file with mode: 0644]
src/test/debuginfo/rwlock-write.rs [new file with mode: 0644]
src/test/debuginfo/simple-tuple.rs
src/test/debuginfo/thread.rs [new file with mode: 0644]
src/test/debuginfo/tuple-in-tuple.rs
src/test/debuginfo/type-names.cdb.js [new file with mode: 0644]
src/test/debuginfo/type-names.rs
src/test/debuginfo/var-captured-in-nested-closure.rs
src/test/incremental/issue-86753.rs [new file with mode: 0644]
src/test/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir
src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir
src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir
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/checked_add.main.ConstProp.diff
src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
src/test/mir-opt/const_prop/indirect.main.ConstProp.diff
src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff
src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff
src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff
src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff
src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff
src/test/mir-opt/const_prop/read_immutable_static.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/return_place.add.ConstProp.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/const_prop/tuple_literal_propagation.main.ConstProp.diff
src/test/mir-opt/deaggregator_test.bar.Deaggregator.diff
src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir
src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff
src/test/mir-opt/inline/inline_generator.main.Inline.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/lower_slice_len.bound.LowerSliceLenCalls.diff [new file with mode: 0644]
src/test/mir-opt/lower_slice_len.rs [new file with mode: 0644]
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/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff
src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir [new file with mode: 0644]
src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff [new file with mode: 0644]
src/test/mir-opt/uninhabited_enum_branching2.rs [new file with mode: 0644]
src/test/pretty/ast-stmt-expr-attr.rs
src/test/pretty/block-comment-wchar.pp
src/test/pretty/block-comment-wchar.rs
src/test/pretty/cast-lt.pp
src/test/pretty/delimited-token-groups.rs
src/test/pretty/hir-pretty-loop.pp [new file with mode: 0644]
src/test/pretty/hir-pretty-loop.rs [new file with mode: 0644]
src/test/pretty/macro.rs
src/test/pretty/macro_rules.rs
src/test/pretty/stmt_expr_attributes.rs
src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile [new file with mode: 0644]
src/test/run-make-fulldeps/coverage-reports/Makefile
src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c
src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
src/test/run-make-fulldeps/pgo-branch-weights/Makefile
src/test/run-make-fulldeps/pgo-gen-lto/Makefile
src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile
src/test/run-make-fulldeps/pgo-gen/Makefile
src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile
src/test/run-make-fulldeps/pgo-use/Makefile
src/test/run-make-fulldeps/print-cfg/Makefile
src/test/run-make-fulldeps/rustdoc-target-spec-json-path/target.json
src/test/run-make-fulldeps/rustdoc-themes/Makefile
src/test/run-make-fulldeps/target-specs/Makefile
src/test/run-make-fulldeps/target-specs/definitely-not-builtin-target.json [new file with mode: 0644]
src/test/run-make-fulldeps/target-specs/mismatching-data-layout.json [new file with mode: 0644]
src/test/run-make/emit-path-unhashed/Makefile [new file with mode: 0644]
src/test/run-make/emit-path-unhashed/foo.rs [new file with mode: 0644]
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/run-make/track-path-dep-info/Makefile [new file with mode: 0644]
src/test/run-make/track-path-dep-info/emojis.txt [new file with mode: 0644]
src/test/run-make/track-path-dep-info/macro_def.rs [new file with mode: 0644]
src/test/run-make/track-path-dep-info/macro_use.rs [new file with mode: 0644]
src/test/run-make/unstable-flag-required/Makefile
src/test/run-make/unstable-flag-required/force-warn.stderr [new file with mode: 0644]
src/test/run-make/unstable-flag-required/force-warns.stderr [deleted file]
src/test/rustdoc-gui/README.md
src/test/rustdoc-gui/auto-hide-trait-implementations.goml [new file with mode: 0644]
src/test/rustdoc-gui/ayu-code-tag-colors.goml [new file with mode: 0644]
src/test/rustdoc-gui/basic-code.goml [new file with mode: 0644]
src/test/rustdoc-gui/basic.goml [new file with mode: 0644]
src/test/rustdoc-gui/check_info_sign_position.goml [new file with mode: 0644]
src/test/rustdoc-gui/code-blocks-overflow.goml [new file with mode: 0644]
src/test/rustdoc-gui/code-sidebar-toggle.goml [new file with mode: 0644]
src/test/rustdoc-gui/default-settings.goml [new file with mode: 0644]
src/test/rustdoc-gui/docblock-table-overflow.goml [new file with mode: 0644]
src/test/rustdoc-gui/escape-key.goml [new file with mode: 0644]
src/test/rustdoc-gui/font-weight.goml [new file with mode: 0644]
src/test/rustdoc-gui/hash-item-expansion.goml [new file with mode: 0644]
src/test/rustdoc-gui/impl-default-expansion.goml [new file with mode: 0644]
src/test/rustdoc-gui/implementors.goml [new file with mode: 0644]
src/test/rustdoc-gui/item-info-width.goml [new file with mode: 0644]
src/test/rustdoc-gui/item-summary-table.goml [new file with mode: 0644]
src/test/rustdoc-gui/label-next-to-symbol.goml [new file with mode: 0644]
src/test/rustdoc-gui/list_code_block.goml [new file with mode: 0644]
src/test/rustdoc-gui/module-items-font.goml [new file with mode: 0644]
src/test/rustdoc-gui/search-filter.goml [new file with mode: 0644]
src/test/rustdoc-gui/search-input-mobile.goml [new file with mode: 0644]
src/test/rustdoc-gui/search-result-color.goml [new file with mode: 0644]
src/test/rustdoc-gui/search-result-colors.goml [new file with mode: 0644]
src/test/rustdoc-gui/search-result-description.goml [new file with mode: 0644]
src/test/rustdoc-gui/search-result-display.goml [new file with mode: 0644]
src/test/rustdoc-gui/search-result-go-to-first.goml [new file with mode: 0644]
src/test/rustdoc-gui/search-result-keyword.goml [new file with mode: 0644]
src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml [new file with mode: 0644]
src/test/rustdoc-gui/shortcuts.goml [new file with mode: 0644]
src/test/rustdoc-gui/sidebar-mobile.goml [new file with mode: 0644]
src/test/rustdoc-gui/sidebar.goml [new file with mode: 0644]
src/test/rustdoc-gui/source-code-page.goml [new file with mode: 0644]
src/test/rustdoc-gui/src/lib.rs [deleted file]
src/test/rustdoc-gui/src/lib2.rs [deleted file]
src/test/rustdoc-gui/src/lib2/Cargo.lock [new file with mode: 0644]
src/test/rustdoc-gui/src/lib2/Cargo.toml [new file with mode: 0644]
src/test/rustdoc-gui/src/lib2/implementors/Cargo.lock [new file with mode: 0644]
src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml [new file with mode: 0644]
src/test/rustdoc-gui/src/lib2/implementors/lib.rs [new file with mode: 0644]
src/test/rustdoc-gui/src/lib2/lib.rs [new file with mode: 0644]
src/test/rustdoc-gui/src/settings/.cargo/config.toml [new file with mode: 0644]
src/test/rustdoc-gui/src/settings/.package-cache [deleted file]
src/test/rustdoc-gui/src/settings/Cargo.lock [new file with mode: 0644]
src/test/rustdoc-gui/src/settings/Cargo.toml [new file with mode: 0644]
src/test/rustdoc-gui/src/settings/lib.rs [new file with mode: 0644]
src/test/rustdoc-gui/src/test_docs/Cargo.lock [new file with mode: 0644]
src/test/rustdoc-gui/src/test_docs/Cargo.toml [new file with mode: 0644]
src/test/rustdoc-gui/src/test_docs/lib.rs [new file with mode: 0644]
src/test/rustdoc-gui/theme-change.goml [new file with mode: 0644]
src/test/rustdoc-gui/toggle-docs-mobile.goml [new file with mode: 0644]
src/test/rustdoc-gui/toggle-docs.goml [new file with mode: 0644]
src/test/rustdoc-gui/toggle-implementors.goml [new file with mode: 0644]
src/test/rustdoc-gui/toggled-open-implementations.goml [new file with mode: 0644]
src/test/rustdoc-gui/trait-sidebar-item-order.goml [new file with mode: 0644]
src/test/rustdoc-gui/type-declation-overflow.goml [new file with mode: 0644]
src/test/rustdoc-gui/type-weight.rs [deleted file]
src/test/rustdoc-js-std/alias-4.js [new file with mode: 0644]
src/test/rustdoc-js-std/typed-query.js [new file with mode: 0644]
src/test/rustdoc-js/generics-trait.js [new file with mode: 0644]
src/test/rustdoc-js/generics-trait.rs [new file with mode: 0644]
src/test/rustdoc-js/generics.js [new file with mode: 0644]
src/test/rustdoc-js/generics.rs [new file with mode: 0644]
src/test/rustdoc-js/summaries.js
src/test/rustdoc-js/summaries.rs
src/test/rustdoc-ui/intra-doc/field-ice.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-doc/field-ice.stderr [new file with mode: 0644]
src/test/rustdoc-ui/nocapture-fail.rs [new file with mode: 0644]
src/test/rustdoc-ui/nocapture-fail.stderr [new file with mode: 0644]
src/test/rustdoc-ui/nocapture-fail.stdout [new file with mode: 0644]
src/test/rustdoc-ui/nocapture.rs [new file with mode: 0644]
src/test/rustdoc-ui/nocapture.stderr [new file with mode: 0644]
src/test/rustdoc-ui/nocapture.stdout [new file with mode: 0644]
src/test/rustdoc-ui/renamed-lint-still-applies.rs
src/test/rustdoc-ui/renamed-lint-still-applies.stderr
src/test/rustdoc-ui/unknown-renamed-lints.rs
src/test/rustdoc-ui/unknown-renamed-lints.stderr
src/test/rustdoc/attributes.rs
src/test/rustdoc/auxiliary/cross-crate-hidden-impl-parameter.rs [new file with mode: 0644]
src/test/rustdoc/auxiliary/issue-85454.rs [new file with mode: 0644]
src/test/rustdoc/auxiliary/issue-86620-1.rs [new file with mode: 0644]
src/test/rustdoc/auxiliary/reexports.rs [new file with mode: 0644]
src/test/rustdoc/cap-lints.rs
src/test/rustdoc/const-display.rs
src/test/rustdoc/const-generics/const-evaluatable-checked.rs [new file with mode: 0644]
src/test/rustdoc/cross-crate-hidden-impl-parameter.rs [new file with mode: 0644]
src/test/rustdoc/decl_macro.rs
src/test/rustdoc/default-theme.rs [new file with mode: 0644]
src/test/rustdoc/deprecated.rs
src/test/rustdoc/doc-cfg.rs
src/test/rustdoc/duplicate-cfg.rs
src/test/rustdoc/duplicate-flags.rs [new file with mode: 0644]
src/test/rustdoc/ensure-src-link.rs
src/test/rustdoc/extern-default-method.rs
src/test/rustdoc/for-lifetime.rs [deleted file]
src/test/rustdoc/higher-ranked-trait-bounds.rs [new file with mode: 0644]
src/test/rustdoc/inline_cross/macros.rs
src/test/rustdoc/internal.rs
src/test/rustdoc/intra-doc/macros-disambiguators.rs [new file with mode: 0644]
src/test/rustdoc/intra-doc/type-alias.rs [new file with mode: 0644]
src/test/rustdoc/issue-19055.rs [deleted file]
src/test/rustdoc/issue-32374.rs
src/test/rustdoc/issue-46377.rs
src/test/rustdoc/issue-55364.rs
src/test/rustdoc/issue-85454.rs
src/test/rustdoc/issue-86620.rs [new file with mode: 0644]
src/test/rustdoc/macro_rules-matchers.rs [new file with mode: 0644]
src/test/rustdoc/macros.rs
src/test/rustdoc/must-use.rs [deleted file]
src/test/rustdoc/recursive-deref-sidebar.rs [new file with mode: 0644]
src/test/rustdoc/recursive-deref.rs [new file with mode: 0644]
src/test/rustdoc/reexport-check.rs
src/test/rustdoc/reexports-priv.rs [new file with mode: 0644]
src/test/rustdoc/reexports.rs [new file with mode: 0644]
src/test/rustdoc/safe-intrinsic.rs [new file with mode: 0644]
src/test/rustdoc/same-crate-hidden-impl-parameter.rs [new file with mode: 0644]
src/test/rustdoc/short-docblock-codeblock.rs
src/test/rustdoc/short-docblock.rs [new file with mode: 0644]
src/test/rustdoc/short-dockblock.rs [deleted file]
src/test/rustdoc/toggle-item-contents.rs
src/test/rustdoc/trait-attributes.rs [deleted file]
src/test/rustdoc/trait-impl-items-links-and-anchors.rs
src/test/ui-fulldeps/internal-lints/default_hash_types.rs
src/test/ui-fulldeps/internal-lints/default_hash_types.stderr
src/test/ui-fulldeps/mod_dir_path_canonicalized.rs
src/test/ui-fulldeps/pprust-expr-roundtrip.rs
src/test/ui-fulldeps/session-derive-errors.stderr
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/allocator/not-an-allocator.stderr
src/test/ui/allocator/two-allocators.stderr
src/test/ui/anon-params/anon-params-deprecated.fixed
src/test/ui/anon-params/anon-params-deprecated.rs
src/test/ui/anon-params/anon-params-deprecated.stderr
src/test/ui/array-slice-vec/slice-panic-1.rs
src/test/ui/array-slice-vec/slice-panic-2.rs
src/test/ui/array-slice-vec/slice.rs
src/test/ui/asm/bad-options.stderr
src/test/ui/asm/bad-reg.rs
src/test/ui/asm/bad-reg.stderr
src/test/ui/asm/inline-syntax.arm.stderr
src/test/ui/asm/inline-syntax.rs
src/test/ui/asm/inline-syntax.x86_64.stderr
src/test/ui/asm/issue-82869.rs [new file with mode: 0644]
src/test/ui/asm/issue-82869.stderr [new file with mode: 0644]
src/test/ui/asm/parse-error.stderr
src/test/ui/associated-consts/associated-const-array-len.stderr
src/test/ui/associated-consts/associated-const-private-impl.stderr
src/test/ui/associated-consts/issue-63496.stderr
src/test/ui/associated-item/issue-48027.stderr
src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs
src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr
src/test/ui/associated-type-bounds/duplicate.full_tait.stderr
src/test/ui/associated-type-bounds/duplicate.min_tait.stderr
src/test/ui/associated-type-bounds/duplicate.rs
src/test/ui/associated-type-bounds/dyn-lcsit.rs [deleted file]
src/test/ui/associated-type-bounds/dyn-lcsit.stderr [deleted file]
src/test/ui/associated-type-bounds/lcsit.rs [deleted file]
src/test/ui/associated-type-bounds/lcsit.stderr [deleted file]
src/test/ui/associated-types/associated-types-bound-failure.stderr
src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
src/test/ui/associated-types/associated-types-no-suitable-bound.stderr
src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
src/test/ui/associated-types/associated-types-unconstrained.stderr
src/test/ui/associated-types/defaults-wf.stderr
src/test/ui/associated-types/hr-associated-type-projection-1.rs
src/test/ui/associated-types/hr-associated-type-projection-1.stderr
src/test/ui/associated-types/issue-20005.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-20005.stderr [new file with mode: 0644]
src/test/ui/associated-types/issue-44153.stderr
src/test/ui/associated-types/normalization-debruijn-1.rs [new file with mode: 0644]
src/test/ui/associated-types/normalization-debruijn-2.rs [new file with mode: 0644]
src/test/ui/associated-types/normalization-debruijn-3.rs [new file with mode: 0644]
src/test/ui/associated-types/normalization-generality.rs [new file with mode: 0644]
src/test/ui/async-await/async-fn-path-elision.stderr
src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.rs
src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr
src/test/ui/async-await/await-keyword/2015-edition-warning.fixed
src/test/ui/async-await/await-keyword/2015-edition-warning.rs
src/test/ui/async-await/await-keyword/2015-edition-warning.stderr
src/test/ui/async-await/issue-61076.stderr
src/test/ui/async-await/issue-68112.stderr
src/test/ui/async-await/issue-70594.stderr
src/test/ui/async-await/issue-84841.rs [new file with mode: 0644]
src/test/ui/async-await/issue-84841.stderr [new file with mode: 0644]
src/test/ui/async-await/issue-86507.rs [new file with mode: 0644]
src/test/ui/async-await/issue-86507.stderr [new file with mode: 0644]
src/test/ui/async-await/issues/issue-62009-1.stderr
src/test/ui/async-await/issues/issue-67893.stderr
src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr
src/test/ui/async-await/pin-needed-to-poll-2.stderr
src/test/ui/async-await/try-on-option-in-async.stderr
src/test/ui/attributes/nonterminal-expansion.rs
src/test/ui/attributes/nonterminal-expansion.stderr
src/test/ui/bastion-of-the-turbofish.rs
src/test/ui/binop/issue-77910-1.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/fsu-moves-and-copies.rs [new file with mode: 0644]
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-83760.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-83760.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-85581.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-85581.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-85765.rs
src/test/ui/borrowck/issue-85765.stderr
src/test/ui/borrowck/mutability-errors.stderr
src/test/ui/borrowck/two-phase-reservation-sharing-interference.rs
src/test/ui/bound-suggestions.stderr
src/test/ui/box/into-boxed-slice-fail.stderr
src/test/ui/c-variadic/issue-86053-1.rs [new file with mode: 0644]
src/test/ui/c-variadic/issue-86053-1.stderr [new file with mode: 0644]
src/test/ui/c-variadic/issue-86053-2.rs [new file with mode: 0644]
src/test/ui/c-variadic/issue-86053-2.stderr [new file with mode: 0644]
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/fat-ptr-cast-rpass.rs
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/cfg/cfg-target-abi.rs [new file with mode: 0644]
src/test/ui/chalkify/type_wf.stderr
src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.rs
src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr
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/capture-analysis-1.rs
src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr
src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs
src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr
src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs
src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr
src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs
src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr
src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs
src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr
src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs
src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr
src/test/ui/closures/2229_closure_analysis/capture-enums.rs
src/test/ui/closures/2229_closure_analysis/capture-enums.stderr
src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs
src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr
src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs
src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr
src/test/ui/closures/2229_closure_analysis/destructure_patterns.rs
src/test/ui/closures/2229_closure_analysis/destructure_patterns.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/box.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/box.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/diagnostics/cant-mutate-imm.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr
src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs
src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr
src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs
src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr
src/test/ui/closures/2229_closure_analysis/issue-87097.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/issue-87097.stderr [new file with mode: 0644]
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/issue-86753.rs [new file with mode: 0644]
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/multilevel-path-1.rs
src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stderr
src/test/ui/closures/2229_closure_analysis/multilevel-path-2.rs
src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stderr
src/test/ui/closures/2229_closure_analysis/nested-closure.rs
src/test/ui/closures/2229_closure_analysis/nested-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/closures/2229_closure_analysis/path-with-array-access.rs
src/test/ui/closures/2229_closure_analysis/path-with-array-access.stderr
src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs
src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr
src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs
src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr
src/test/ui/closures/2229_closure_analysis/repr_packed.rs
src/test/ui/closures/2229_closure_analysis/repr_packed.stderr
src/test/ui/closures/2229_closure_analysis/run_pass/box.rs
src/test/ui/closures/2229_closure_analysis/run_pass/box.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/by_value.rs
src/test/ui/closures/2229_closure_analysis/run_pass/by_value.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs
src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs
src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs
src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.rs
src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.rs
src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.stderr
src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.rs
src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.stderr
src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs
src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs
src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/edition.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs
src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs
src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs
src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs
src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs
src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs
src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.rs
src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.rs
src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.rs
src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs
src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs
src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.rs
src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs
src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.rs
src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs
src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr
src/test/ui/closures/2229_closure_analysis/unsafe_ptr.rs
src/test/ui/closures/2229_closure_analysis/unsafe_ptr.stderr
src/test/ui/closures/2229_closure_analysis/wild_patterns.rs
src/test/ui/closures/2229_closure_analysis/wild_patterns.stderr
src/test/ui/closures/issue-41366.stderr
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr
src/test/ui/codegen/issue-88043-bb-does-not-have-terminator.rs [new file with mode: 0644]
src/test/ui/coercion/issue-37655.rs [new file with mode: 0644]
src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr
src/test/ui/conditional-compilation/test-cfg.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/test-cfg.stderr [new file with mode: 0644]
src/test/ui/conflicting-repr-hints.rs
src/test/ui/conflicting-repr-hints.stderr
src/test/ui/const-generics/auxiliary/impl-const.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-1.rs [new file with mode: 0644]
src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.rs [new file with mode: 0644]
src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.stderr [new file with mode: 0644]
src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.rs [new file with mode: 0644]
src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.stderr [new file with mode: 0644]
src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-4.rs [new file with mode: 0644]
src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr
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-generics/defaults/default-const-param-cannot-reference-self.rs [new file with mode: 0644]
src/test/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr [new file with mode: 0644]
src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr
src/test/ui/const-generics/exhaustive-value.full.stderr
src/test/ui/const-generics/exhaustive-value.min.stderr
src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr
src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr
src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr [deleted file]
src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr [deleted file]
src/test/ui/const-generics/issue-61522-array-len-succ.rs [deleted file]
src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr [deleted file]
src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs [deleted file]
src/test/ui/const-generics/issue-67375.full.stderr [deleted file]
src/test/ui/const-generics/issue-67375.min.stderr [deleted file]
src/test/ui/const-generics/issue-67375.rs [deleted file]
src/test/ui/const-generics/issue-67945-1.full.stderr [deleted file]
src/test/ui/const-generics/issue-67945-1.min.stderr [deleted file]
src/test/ui/const-generics/issue-67945-1.rs [deleted file]
src/test/ui/const-generics/issue-67945-2.full.stderr [deleted file]
src/test/ui/const-generics/issue-67945-2.min.stderr [deleted file]
src/test/ui/const-generics/issue-67945-2.rs [deleted file]
src/test/ui/const-generics/issue-67945-3.full.stderr [deleted file]
src/test/ui/const-generics/issue-67945-3.min.stderr [deleted file]
src/test/ui/const-generics/issue-67945-3.rs [deleted file]
src/test/ui/const-generics/issue-68104-print-stack-overflow.rs [deleted file]
src/test/ui/const-generics/issue-70180-1-stalled_on.rs [deleted file]
src/test/ui/const-generics/issue-70180-2-stalled_on.rs [deleted file]
src/test/ui/const-generics/issue-71202.rs [deleted file]
src/test/ui/const-generics/issue-71986.rs [deleted file]
src/test/ui/const-generics/issue-73899.rs [deleted file]
src/test/ui/const-generics/issue-74906.rs [deleted file]
src/test/ui/const-generics/issue-75763.rs [deleted file]
src/test/ui/const-generics/issue-79518-default_trait_method_normalization.rs [deleted file]
src/test/ui/const-generics/issue-79518-default_trait_method_normalization.stderr [deleted file]
src/test/ui/const-generics/issue-80561-incorrect-param-env.rs [deleted file]
src/test/ui/const-generics/issues/auxiliary/impl-const.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-61432.rs
src/test/ui/const-generics/issues/issue-61522-array-len-succ.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-61522-array-len-succ.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-61522-array-len-succ.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67375.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67375.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67375.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-1.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-1.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-1.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-2.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-2.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-2.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-3.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-3.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-3.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-68104-print-stack-overflow.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-70180-1-stalled_on.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-70180-2-stalled_on.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-71202.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-71986.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-73899.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-74906.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-75763.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-80561-incorrect-param-env.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-83765.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-83765.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-85848.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-85848.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-86820.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-86820.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-87076.rs [new file with mode: 0644]
src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs
src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr
src/test/ui/const-generics/occurs-check/unused-substs-1.stderr
src/test/ui/const-ptr/out_of_bounds_read.rs [new file with mode: 0644]
src/test/ui/const-ptr/out_of_bounds_read.stderr [new file with mode: 0644]
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-pointer-values-in-various-types.64bit.stderr
src/test/ui/consts/const-eval/const_panic.rs
src/test/ui/consts/const-eval/const_panic.stderr
src/test/ui/consts/const-eval/const_panic_libcore_bin.rs
src/test/ui/consts/const-eval/const_panic_libcore_bin.stderr
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/dangling.rs
src/test/ui/consts/const-eval/dangling.stderr
src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs
src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr
src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr
src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr
src/test/ui/consts/const-eval/issue-49296.rs
src/test/ui/consts/const-eval/issue-49296.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/panic-assoc-never-type.rs
src/test/ui/consts/const-eval/panic-assoc-never-type.stderr
src/test/ui/consts/const-eval/panic-never-type.rs
src/test/ui/consts/const-eval/panic-never-type.stderr
src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs
src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr
src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr
src/test/ui/consts/const-eval/ub-enum.32bit.stderr
src/test/ui/consts/const-eval/ub-enum.64bit.stderr
src/test/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/ub-incorrect-vtable.rs
src/test/ui/consts/const-eval/ub-incorrect-vtable.stderr [deleted file]
src/test/ui/consts/const-eval/ub-int-array.32bit.stderr
src/test/ui/consts/const-eval/ub-int-array.64bit.stderr
src/test/ui/consts/const-eval/ub-int-array.rs
src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr
src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr
src/test/ui/consts/const-eval/ub-nonnull.rs
src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr
src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr
src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr
src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr
src/test/ui/consts/const-eval/ub-upvars.32bit.stderr
src/test/ui/consts/const-eval/ub-upvars.64bit.stderr
src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
src/test/ui/consts/const-eval/union-ice.stderr
src/test/ui/consts/const-eval/unwind-abort.rs
src/test/ui/consts/const-eval/unwind-abort.stderr
src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
src/test/ui/consts/const-eval/validate_uninhabited_zsts.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-float-classify.rs
src/test/ui/consts/const-int-unchecked.rs
src/test/ui/consts/const-int-unchecked.stderr
src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr [new file with mode: 0644]
src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr [new file with mode: 0644]
src/test/ui/consts/const-mut-refs/issue-76510.rs [new file with mode: 0644]
src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs
src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr
src/test/ui/consts/const-points-to-static.32bit.stderr
src/test/ui/consts/const-points-to-static.64bit.stderr
src/test/ui/consts/const-unwrap.rs
src/test/ui/consts/const-unwrap.stderr
src/test/ui/consts/const_unsafe_unreachable_ub.rs
src/test/ui/consts/const_unsafe_unreachable_ub.stderr
src/test/ui/consts/control-flow/assert.const_panic.stderr
src/test/ui/consts/control-flow/assert.rs
src/test/ui/consts/copy-intrinsic.rs [new file with mode: 0644]
src/test/ui/consts/copy-intrinsic.stderr [new file with mode: 0644]
src/test/ui/consts/issue-17458.rs
src/test/ui/consts/issue-17458.stderr
src/test/ui/consts/issue-17756.rs [new file with mode: 0644]
src/test/ui/consts/issue-39161-bogus-error.rs [new file with mode: 0644]
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/issue-63952.32bit.stderr
src/test/ui/consts/issue-63952.64bit.stderr
src/test/ui/consts/issue-69532.rs [new file with mode: 0644]
src/test/ui/consts/issue-79690.64bit.stderr
src/test/ui/consts/issue-83182.32bit.stderr
src/test/ui/consts/issue-83182.64bit.stderr
src/test/ui/consts/issue-83182.rs
src/test/ui/consts/issue-87046.rs [new file with mode: 0644]
src/test/ui/consts/issue-87046.stderr [new file with mode: 0644]
src/test/ui/consts/large_const_alloc.rs [new file with mode: 0644]
src/test/ui/consts/large_const_alloc.stderr [new file with mode: 0644]
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/const_refers_to_static2.32bit.stderr
src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr
src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr
src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr
src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr
src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr
src/test/ui/consts/miri_unleashed/ptr_arith.rs
src/test/ui/consts/miri_unleashed/ptr_arith.stderr
src/test/ui/consts/miri_unleashed/tls.stderr
src/test/ui/consts/offset_from_ub.rs
src/test/ui/consts/offset_from_ub.stderr
src/test/ui/consts/offset_ub.rs
src/test/ui/consts/offset_ub.stderr
src/test/ui/consts/ptr_comparisons.rs
src/test/ui/consts/ptr_comparisons.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/consts/std/alloc.32bit.stderr
src/test/ui/consts/std/alloc.64bit.stderr
src/test/ui/consts/validate_never_arrays.32bit.stderr
src/test/ui/consts/validate_never_arrays.64bit.stderr
src/test/ui/conversion-methods.rs [deleted file]
src/test/ui/conversion-methods.stderr [deleted file]
src/test/ui/crate-loading/auxiliary/proc-macro.rs [new file with mode: 0644]
src/test/ui/crate-loading/cross-compiled-proc-macro.rs [new file with mode: 0644]
src/test/ui/crate-loading/missing-std.rs
src/test/ui/crate-loading/missing-std.stderr
src/test/ui/custom_test_frameworks/mismatch.stderr
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/derives/derive-on-trait-item-or-impl-item.rs
src/test/ui/derives/derive-on-trait-item-or-impl-item.stderr
src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr
src/test/ui/derives/derives-span-Clone-enum.stderr
src/test/ui/derives/derives-span-Clone-struct.stderr
src/test/ui/derives/derives-span-Clone-tuple-struct.stderr
src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr
src/test/ui/derives/derives-span-Debug-enum.stderr
src/test/ui/derives/derives-span-Debug-struct.stderr
src/test/ui/derives/derives-span-Debug-tuple-struct.stderr
src/test/ui/derives/derives-span-Default-struct.stderr
src/test/ui/derives/derives-span-Default-tuple-struct.stderr
src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr
src/test/ui/derives/derives-span-Eq-enum.stderr
src/test/ui/derives/derives-span-Eq-struct.stderr
src/test/ui/derives/derives-span-Eq-tuple-struct.stderr
src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr
src/test/ui/derives/derives-span-Hash-enum.stderr
src/test/ui/derives/derives-span-Hash-struct.stderr
src/test/ui/derives/derives-span-Hash-tuple-struct.stderr
src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr
src/test/ui/derives/derives-span-Ord-enum.stderr
src/test/ui/derives/derives-span-Ord-struct.stderr
src/test/ui/derives/derives-span-Ord-tuple-struct.stderr
src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr
src/test/ui/derives/derives-span-PartialEq-enum.stderr
src/test/ui/derives/derives-span-PartialEq-struct.stderr
src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr
src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr
src/test/ui/derives/derives-span-PartialOrd-enum.stderr
src/test/ui/derives/derives-span-PartialOrd-struct.stderr
src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr
src/test/ui/derives/deriving-copyclone.stderr
src/test/ui/derives/deriving-no-inner-impl-error-message.stderr
src/test/ui/derives/deriving-non-type.rs
src/test/ui/derives/deriving-non-type.stderr
src/test/ui/deriving/deriving-with-helper.rs [new file with mode: 0644]
src/test/ui/did_you_mean/bad-assoc-ty.rs
src/test/ui/did_you_mean/bad-assoc-ty.stderr
src/test/ui/did_you_mean/issue-39544.rs
src/test/ui/did_you_mean/issue-39544.stderr
src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
src/test/ui/dyn-drop/dyn-drop.rs [new file with mode: 0644]
src/test/ui/dyn-drop/dyn-drop.stderr [new file with mode: 0644]
src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.fixed
src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.rs
src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr
src/test/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs
src/test/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs
src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs
src/test/ui/dyn-keyword/dyn-2018-edition-lint.rs
src/test/ui/dyn-keyword/dyn-2018-edition-lint.stderr
src/test/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs
src/test/ui/dynamically-sized-types/dst-index.rs
src/test/ui/editions/edition-feature-ok.rs
src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs
src/test/ui/editions/edition-keywords-2015-2015-expansion.rs
src/test/ui/editions/edition-keywords-2018-2015-expansion.rs
src/test/ui/editions/edition-raw-pointer-method-2015.rs
src/test/ui/editions/edition-raw-pointer-method-2015.stderr
src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs
src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr
src/test/ui/error-codes/E0038.stderr
src/test/ui/error-codes/E0121.rs
src/test/ui/error-codes/E0121.stderr
src/test/ui/error-codes/E0283.stderr
src/test/ui/error-codes/E0389.rs
src/test/ui/error-codes/E0389.stderr
src/test/ui/error-codes/E0396-fixed.rs
src/test/ui/error-codes/E0396-fixed.stderr
src/test/ui/error-codes/E0565.rs
src/test/ui/error-codes/E0565.stderr
src/test/ui/error-codes/E0624.stderr
src/test/ui/error-codes/E0777.stderr
src/test/ui/explore-issue-38412.stderr
src/test/ui/extern/extern-main-issue-86110.rs [new file with mode: 0644]
src/test/ui/extern/extern-main-issue-86110.stderr [new file with mode: 0644]
src/test/ui/extern/extern-methods.rs
src/test/ui/extern/extern-thiscall.rs
src/test/ui/extern/extern-types-distinct-types.stderr
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-associated_type_bounds.rs
src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr
src/test/ui/feature-gates/feature-gate-cfg-target-abi.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-cfg-target-abi.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-fn_align.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-fn_align.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.rs [deleted file]
src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-min_type_alias_impl_trait.stderr
src/test/ui/feature-gates/feature-gate-more-qualified-paths.stderr
src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr
src/test/ui/feature-gates/feature-gate-optimize_attribute.stderr
src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.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/feature-gates/issue-43106-gating-of-derive.rs
src/test/ui/feature-gates/issue-43106-gating-of-derive.stderr
src/test/ui/ffi_const2.stderr
src/test/ui/fmt/format-args-capture.rs
src/test/ui/fmt/format-concat-span.rs [new file with mode: 0644]
src/test/ui/fmt/format-concat-span.stderr [new file with mode: 0644]
src/test/ui/fmt/ifmt-unimpl.stderr
src/test/ui/fmt/issue-86085.rs [new file with mode: 0644]
src/test/ui/fmt/issue-86085.stderr [new file with mode: 0644]
src/test/ui/fn/issue-80179.rs
src/test/ui/fn/issue-80179.stderr
src/test/ui/for/for-c-in-str.stderr
src/test/ui/for/for-loop-bogosity.stderr
src/test/ui/fsu-moves-and-copies.rs [deleted file]
src/test/ui/function-pointer/function-pointer-comparison-issue-54685.rs [new file with mode: 0644]
src/test/ui/future-incompatible-lint-group.rs
src/test/ui/future-incompatible-lint-group.stderr
src/test/ui/generator/issue-68112.stderr
src/test/ui/generator/layout-error.full_tait.stderr
src/test/ui/generator/layout-error.min_tait.stderr
src/test/ui/generator/layout-error.rs
src/test/ui/generator/metadata-sufficient-for-layout.full_tait.stderr
src/test/ui/generator/metadata-sufficient-for-layout.min_tait.stderr
src/test/ui/generator/metadata-sufficient-for-layout.rs
src/test/ui/generator/not-send-sync.stderr
src/test/ui/generator/print/generator-print-verbose-1.stderr
src/test/ui/generator/too-live-local-in-immovable-gen.rs
src/test/ui/generator/too-live-local-in-immovable-gen.stderr
src/test/ui/generator/yield-in-initializer.rs
src/test/ui/generator/yield-outside-generator-issue-78653.stderr
src/test/ui/generic-associated-types/collections-project-default.rs
src/test/ui/generic-associated-types/collections-project-default.stderr
src/test/ui/generic-associated-types/collections.rs
src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs
src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs
src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs
src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.rs
src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr
src/test/ui/generic-associated-types/construct_with_other_type.rs
src/test/ui/generic-associated-types/empty_generics.rs
src/test/ui/generic-associated-types/empty_generics.stderr
src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs
src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr
src/test/ui/generic-associated-types/gat-in-trait-path.rs
src/test/ui/generic-associated-types/gat-in-trait-path.stderr
src/test/ui/generic-associated-types/gat-incomplete-warning.rs
src/test/ui/generic-associated-types/gat-incomplete-warning.stderr [deleted file]
src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs
src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr
src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs
src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs
src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
src/test/ui/generic-associated-types/generic-associated-type-bounds.rs
src/test/ui/generic-associated-types/generic-associated-types-where.rs
src/test/ui/generic-associated-types/generic-associated-types-where.stderr
src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs
src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr
src/test/ui/generic-associated-types/impl_bounds.rs
src/test/ui/generic-associated-types/impl_bounds.stderr
src/test/ui/generic-associated-types/impl_bounds_ok.rs
src/test/ui/generic-associated-types/issue-47206-where-clause.rs
src/test/ui/generic-associated-types/issue-47206-where-clause.stderr
src/test/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs
src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs
src/test/ui/generic-associated-types/issue-67510-pass.rs
src/test/ui/generic-associated-types/issue-67510-pass.stderr
src/test/ui/generic-associated-types/issue-67510.rs
src/test/ui/generic-associated-types/issue-67510.stderr
src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs
src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr
src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs
src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr
src/test/ui/generic-associated-types/issue-68643-broken-mir.rs
src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr
src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs
src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr
src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs
src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr
src/test/ui/generic-associated-types/issue-68648-1.rs
src/test/ui/generic-associated-types/issue-68648-1.stderr [deleted file]
src/test/ui/generic-associated-types/issue-68648-2.rs
src/test/ui/generic-associated-types/issue-68648-2.stderr
src/test/ui/generic-associated-types/issue-68649-pass.rs
src/test/ui/generic-associated-types/issue-68649-pass.stderr [deleted file]
src/test/ui/generic-associated-types/issue-68653.rs
src/test/ui/generic-associated-types/issue-68656-unsized-values.rs
src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr
src/test/ui/generic-associated-types/issue-70303.rs
src/test/ui/generic-associated-types/issue-70304.rs
src/test/ui/generic-associated-types/issue-70304.stderr
src/test/ui/generic-associated-types/issue-71176.rs
src/test/ui/generic-associated-types/issue-71176.stderr
src/test/ui/generic-associated-types/issue-74684-1.rs
src/test/ui/generic-associated-types/issue-74684-1.stderr
src/test/ui/generic-associated-types/issue-74684-2.rs
src/test/ui/generic-associated-types/issue-74684-2.stderr
src/test/ui/generic-associated-types/issue-74816.rs
src/test/ui/generic-associated-types/issue-74816.stderr
src/test/ui/generic-associated-types/issue-74824.rs
src/test/ui/generic-associated-types/issue-74824.stderr
src/test/ui/generic-associated-types/issue-76407.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-76535.rs
src/test/ui/generic-associated-types/issue-76535.stderr
src/test/ui/generic-associated-types/issue-76826.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-78671.rs
src/test/ui/generic-associated-types/issue-78671.stderr
src/test/ui/generic-associated-types/issue-79422.rs
src/test/ui/generic-associated-types/issue-79422.stderr
src/test/ui/generic-associated-types/issue-79636-1.rs
src/test/ui/generic-associated-types/issue-79636-1.stderr
src/test/ui/generic-associated-types/issue-79636-2.rs
src/test/ui/generic-associated-types/issue-79636-2.stderr
src/test/ui/generic-associated-types/issue-80433-reduced.rs
src/test/ui/generic-associated-types/issue-80433.rs
src/test/ui/generic-associated-types/issue-80433.stderr
src/test/ui/generic-associated-types/issue-81487.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-81712-cyclic-traits.rs
src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr
src/test/ui/generic-associated-types/issue-81862.rs
src/test/ui/generic-associated-types/issue-81862.stderr
src/test/ui/generic-associated-types/issue-86483.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-86483.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/iterable.rs
src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs
src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr
src/test/ui/generic-associated-types/missing_lifetime_args.rs
src/test/ui/generic-associated-types/missing_lifetime_args.stderr
src/test/ui/generic-associated-types/missing_lifetime_const.rs
src/test/ui/generic-associated-types/missing_lifetime_const.stderr
src/test/ui/generic-associated-types/parameter_number_and_kind.rs
src/test/ui/generic-associated-types/parameter_number_and_kind.stderr
src/test/ui/generic-associated-types/parameter_number_and_kind_impl.rs
src/test/ui/generic-associated-types/parameter_number_and_kind_impl.stderr
src/test/ui/generic-associated-types/parse/trait-path-expected-token.rs
src/test/ui/generic-associated-types/parse/trait-path-expected-token.stderr
src/test/ui/generic-associated-types/parse/trait-path-expressions.rs
src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr
src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs
src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr
src/test/ui/generic-associated-types/parse/trait-path-segments.rs
src/test/ui/generic-associated-types/parse/trait-path-segments.stderr
src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs
src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
src/test/ui/generic-associated-types/parse/trait-path-types.rs
src/test/ui/generic-associated-types/parse/trait-path-types.stderr
src/test/ui/generic-associated-types/pointer_family.rs
src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs
src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr
src/test/ui/generic-associated-types/projection-bound-cycle.rs
src/test/ui/generic-associated-types/projection-bound-cycle.stderr
src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs
src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr
src/test/ui/generic-associated-types/shadowing.rs
src/test/ui/generic-associated-types/shadowing.stderr
src/test/ui/generic-associated-types/streaming_iterator.rs
src/test/ui/generic-associated-types/trait-objects.rs
src/test/ui/generic-associated-types/trait-objects.stderr
src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.rs
src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr
src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs
src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr
src/test/ui/generic-associated-types/variance_constraints.rs
src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.rs
src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.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/impl-header-lifetime-elision/path-elided.stderr
src/test/ui/impl-header-lifetime-elision/trait-elided.stderr
src/test/ui/impl-trait/auto-trait-leak.rs
src/test/ui/impl-trait/auto-trait-leak.stderr
src/test/ui/impl-trait/binding-without-value.rs [deleted file]
src/test/ui/impl-trait/binding-without-value.stderr [deleted file]
src/test/ui/impl-trait/bindings-opaque.rs [deleted file]
src/test/ui/impl-trait/bindings-opaque.stderr [deleted file]
src/test/ui/impl-trait/bindings.rs [deleted file]
src/test/ui/impl-trait/bindings.stderr [deleted file]
src/test/ui/impl-trait/bound-normalization-fail.rs
src/test/ui/impl-trait/bound-normalization-fail.stderr
src/test/ui/impl-trait/bound-normalization-pass.default.stderr [deleted file]
src/test/ui/impl-trait/bound-normalization-pass.rs
src/test/ui/impl-trait/bound-normalization-pass.sa.stderr [deleted file]
src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.rs [deleted file]
src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.stderr [deleted file]
src/test/ui/impl-trait/impl-trait-in-bindings.rs [deleted file]
src/test/ui/impl-trait/impl-trait-in-bindings.stderr [deleted file]
src/test/ui/impl-trait/issue-57200.rs [deleted file]
src/test/ui/impl-trait/issue-57200.stderr [deleted file]
src/test/ui/impl-trait/issue-57201.rs [deleted file]
src/test/ui/impl-trait/issue-57201.stderr [deleted file]
src/test/ui/impl-trait/issue-60473.rs [deleted file]
src/test/ui/impl-trait/issue-60473.stderr [deleted file]
src/test/ui/impl-trait/issue-67166.rs [deleted file]
src/test/ui/impl-trait/issue-67166.stderr [deleted file]
src/test/ui/impl-trait/issue-69840.rs [deleted file]
src/test/ui/impl-trait/issue-86465.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-86465.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-54600.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-54600.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-54840.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-54840.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-58504.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-58504.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-58956.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-58956.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr
src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr
src/test/ui/impl-trait/issues/issue-70877.rs
src/test/ui/impl-trait/issues/issue-70971.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-70971.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-78721.rs [deleted file]
src/test/ui/impl-trait/issues/issue-78721.stderr [deleted file]
src/test/ui/impl-trait/issues/issue-78722.full_tait.stderr
src/test/ui/impl-trait/issues/issue-78722.min_tait.stderr
src/test/ui/impl-trait/issues/issue-78722.rs
src/test/ui/impl-trait/issues/issue-79099.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-79099.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs
src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr
src/test/ui/impl-trait/issues/issue-84919.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-84919.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-86201.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-86201.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-86642.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-86642.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-87295.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-87295.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/universal-issue-48703.stderr
src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr
src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
src/test/ui/impl-trait/nested_impl_trait.stderr
src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
src/test/ui/impl-trait/where-allowed.rs
src/test/ui/impl-trait/where-allowed.stderr
src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs [deleted file]
src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr [deleted file]
src/test/ui/inference/inference-variable-behind-raw-pointer.rs
src/test/ui/inference/inference-variable-behind-raw-pointer.stderr
src/test/ui/inference/issue-70703.rs [new file with mode: 0644]
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/intrinsics/non-integer-atomic.rs [new file with mode: 0644]
src/test/ui/intrinsics/non-integer-atomic.stderr [new file with mode: 0644]
src/test/ui/invalid-compile-flags/codegen-option-without-group.rs [new file with mode: 0644]
src/test/ui/invalid-compile-flags/codegen-option-without-group.stderr [new file with mode: 0644]
src/test/ui/invalid-compile-flags/debug-option-without-group.rs [new file with mode: 0644]
src/test/ui/invalid-compile-flags/debug-option-without-group.stderr [new file with mode: 0644]
src/test/ui/issues/issue-10412.stderr
src/test/ui/issues/issue-12997-2.stderr
src/test/ui/issues/issue-17651.stderr
src/test/ui/issues/issue-17756.rs [deleted file]
src/test/ui/issues/issue-18294.rs
src/test/ui/issues/issue-18294.stderr
src/test/ui/issues/issue-18611.stderr
src/test/ui/issues/issue-18959.stderr
src/test/ui/issues/issue-19380.stderr
src/test/ui/issues/issue-20005.rs [deleted file]
src/test/ui/issues/issue-20005.stderr [deleted file]
src/test/ui/issues/issue-20427.rs
src/test/ui/issues/issue-20605.stderr
src/test/ui/issues/issue-20644.rs
src/test/ui/issues/issue-20831-debruijn.stderr
src/test/ui/issues/issue-21160.stderr
src/test/ui/issues/issue-21202.stderr
src/test/ui/issues/issue-22992.rs
src/test/ui/issues/issue-23338-ensure-param-drop-order.rs
src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs [deleted file]
src/test/ui/issues/issue-27060-2.rs [deleted file]
src/test/ui/issues/issue-27060-2.stderr [deleted file]
src/test/ui/issues/issue-27060-rpass.rs [deleted file]
src/test/ui/issues/issue-27060.rs [deleted file]
src/test/ui/issues/issue-27060.stderr [deleted file]
src/test/ui/issues/issue-27401-dropflag-reinit.rs
src/test/ui/issues/issue-27895.rs [deleted file]
src/test/ui/issues/issue-27895.stderr [deleted file]
src/test/ui/issues/issue-28098.stderr
src/test/ui/issues/issue-29147.stderr
src/test/ui/issues/issue-31109.rs [deleted file]
src/test/ui/issues/issue-31109.stderr [deleted file]
src/test/ui/issues/issue-32709.stderr
src/test/ui/issues/issue-3290.rs
src/test/ui/issues/issue-33941.stderr
src/test/ui/issues/issue-34229.stderr
src/test/ui/issues/issue-36638.rs [deleted file]
src/test/ui/issues/issue-36638.stderr [deleted file]
src/test/ui/issues/issue-3763.stderr
src/test/ui/issues/issue-37655.rs [deleted file]
src/test/ui/issues/issue-39970.stderr
src/test/ui/issues/issue-41255.rs
src/test/ui/issues/issue-41255.stderr
src/test/ui/issues/issue-43023.rs
src/test/ui/issues/issue-43023.stderr
src/test/ui/issues/issue-43205.rs
src/test/ui/issues/issue-43623.stderr
src/test/ui/issues/issue-43988.rs
src/test/ui/issues/issue-43988.stderr
src/test/ui/issues/issue-45157.rs [deleted file]
src/test/ui/issues/issue-45157.stderr [deleted file]
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-47715.stderr
src/test/ui/issues/issue-48636.fixed [deleted file]
src/test/ui/issues/issue-48636.rs [deleted file]
src/test/ui/issues/issue-48636.stderr [deleted file]
src/test/ui/issues/issue-49934.rs
src/test/ui/issues/issue-49934.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-51714.rs
src/test/ui/issues/issue-51714.stderr
src/test/ui/issues/issue-52169.rs [deleted file]
src/test/ui/issues/issue-5280.rs
src/test/ui/issues/issue-53498.stderr
src/test/ui/issues/issue-54521-1.rs [deleted file]
src/test/ui/issues/issue-54521-2.fixed [deleted file]
src/test/ui/issues/issue-54521-2.rs [deleted file]
src/test/ui/issues/issue-54521-2.stderr [deleted file]
src/test/ui/issues/issue-54521.fixed [deleted file]
src/test/ui/issues/issue-54521.rs [deleted file]
src/test/ui/issues/issue-54521.stderr [deleted file]
src/test/ui/issues/issue-54696.rs
src/test/ui/issues/issue-58022.stderr
src/test/ui/issues/issue-59488.stderr
src/test/ui/issues/issue-60283.stderr
src/test/ui/issues/issue-66353.stderr
src/test/ui/issues/issue-6804.rs
src/test/ui/issues/issue-6804.stderr
src/test/ui/issues/issue-69396-const-no-type-in-macro.rs
src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr
src/test/ui/issues/issue-69532.rs [deleted file]
src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr
src/test/ui/issues/issue-72690.stderr
src/test/ui/issues/issue-73886.stderr
src/test/ui/issues/issue-74086.rs [deleted file]
src/test/ui/issues/issue-74086.stderr [deleted file]
src/test/ui/issues/issue-81885.rs [deleted file]
src/test/ui/issues/issue-81885.stderr [deleted file]
src/test/ui/issues/issue-82869.rs [deleted file]
src/test/ui/issues/issue-82869.stderr [deleted file]
src/test/ui/issues/issue-87199.rs [new file with mode: 0644]
src/test/ui/issues/issue-87199.stderr [new file with mode: 0644]
src/test/ui/iterators/integral.stderr
src/test/ui/iterators/into-iter-on-arrays-2018.rs
src/test/ui/iterators/into-iter-on-arrays-2018.stderr
src/test/ui/iterators/into-iter-on-arrays-lint.fixed
src/test/ui/iterators/into-iter-on-arrays-lint.rs
src/test/ui/iterators/into-iter-on-arrays-lint.stderr
src/test/ui/iterators/ranges.stderr
src/test/ui/iterators/string.stderr
src/test/ui/keyword/keyword-self-as-type-param.rs [new file with mode: 0644]
src/test/ui/keyword/keyword-self-as-type-param.stderr [new file with mode: 0644]
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/limits/issue-69485-var-size-diffs-too-large.stderr
src/test/ui/lint/bare-trait-objects-path.rs
src/test/ui/lint/bare-trait-objects-path.stderr
src/test/ui/lint/cli-lint-override.forbid_warn.stderr [new file with mode: 0644]
src/test/ui/lint/cli-lint-override.force_warn_deny.stderr [new file with mode: 0644]
src/test/ui/lint/cli-lint-override.rs [new file with mode: 0644]
src/test/ui/lint/cli-lint-override.warn_deny.stderr [new file with mode: 0644]
src/test/ui/lint/cli-unknown-force-warn.rs [new file with mode: 0644]
src/test/ui/lint/cli-unknown-force-warn.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/dead-code/self-assign.rs [new file with mode: 0644]
src/test/ui/lint/dead-code/self-assign.stderr [new file with mode: 0644]
src/test/ui/lint/force-warn/force-allowed-by-default-lint.rs
src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr
src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.rs
src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr
src/test/ui/lint/force-warn/force-allowed-warning.rs
src/test/ui/lint/force-warn/force-allowed-warning.stderr
src/test/ui/lint/force-warn/force-deny-by-default-lint.rs
src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr
src/test/ui/lint/force-warn/force-lint-allow-all-warnings.rs
src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr
src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.rs
src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr
src/test/ui/lint/force-warn/force-lint-in-allowed-group.rs
src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr
src/test/ui/lint/force-warn/force-warn-cap-lints-allow.rs [new file with mode: 0644]
src/test/ui/lint/force-warn/force-warn-cap-lints-allow.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-warn-group-allow-warning.rs
src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr
src/test/ui/lint/force-warn/force-warn-group.rs
src/test/ui/lint/force-warn/force-warn-group.stderr
src/test/ui/lint/future-incompat-test.rs [new file with mode: 0644]
src/test/ui/lint/future-incompat-test.stderr [new file with mode: 0644]
src/test/ui/lint/inclusive-range-pattern-syntax.fixed
src/test/ui/lint/inclusive-range-pattern-syntax.rs
src/test/ui/lint/inclusive-range-pattern-syntax.stderr
src/test/ui/lint/issue-78660-cap-lints-future-compat.rs [deleted file]
src/test/ui/lint/issue-78660-cap-lints-future-compat.stderr [deleted file]
src/test/ui/lint/issue-83477.rs
src/test/ui/lint/issue-83477.stderr
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/issue-87274-paren-parent.rs [new file with mode: 0644]
src/test/ui/lint/issue-87274-paren-parent.stderr [new file with mode: 0644]
src/test/ui/lint/lint-pre-expansion-extern-module.stderr
src/test/ui/lint/lint-stability-deprecated.stderr
src/test/ui/lint/lint-stability3.stderr
src/test/ui/lint/lint-unknown-lint.rs
src/test/ui/lint/lint-unknown-lint.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/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs
src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr
src/test/ui/lint/unused-borrows.rs [new file with mode: 0644]
src/test/ui/lint/unused-borrows.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/auxiliary/or-pattern.rs [new file with mode: 0644]
src/test/ui/macros/issue-52169.rs [new file with mode: 0644]
src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.rs [new file with mode: 0644]
src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr [new file with mode: 0644]
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/macros/trace_faulty_macros.rs
src/test/ui/macros/trace_faulty_macros.stderr
src/test/ui/mir/issue-75053.full_tait.stderr
src/test/ui/mir/issue-75053.in_bindings.stderr
src/test/ui/mir/issue-75053.min_tait.stderr
src/test/ui/mir/issue-75053.rs
src/test/ui/mir/issue-83499-input-output-iteration-ice.rs
src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr
src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.rs
src/test/ui/mut/mutable-class-fields-2.stderr
src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs [new file with mode: 0644]
src/test/ui/nll/issue-45157.rs [new file with mode: 0644]
src/test/ui/nll/issue-45157.stderr [new file with mode: 0644]
src/test/ui/nll/issue-47388.stderr
src/test/ui/nll/issue-50461-used-mut-from-moves.rs
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/nll/normalization-bounds-error.stderr
src/test/ui/non-constant-in-const-path.rs [deleted file]
src/test/ui/non-constant-in-const-path.stderr [deleted file]
src/test/ui/non-fmt-panic.stderr
src/test/ui/non-integer-atomic.rs [deleted file]
src/test/ui/non-integer-atomic.stderr [deleted file]
src/test/ui/nullable-pointer-iotareduction.rs
src/test/ui/on-unimplemented/multiple-impls.stderr
src/test/ui/on-unimplemented/no-debug.stderr
src/test/ui/on-unimplemented/on-impl.stderr
src/test/ui/packed/issue-27060-2.rs [new file with mode: 0644]
src/test/ui/packed/issue-27060-2.stderr [new file with mode: 0644]
src/test/ui/packed/issue-27060-rpass.rs [new file with mode: 0644]
src/test/ui/packed/issue-27060.rs [new file with mode: 0644]
src/test/ui/packed/issue-27060.stderr [new file with mode: 0644]
src/test/ui/panic-runtime/incompatible-type.rs [new file with mode: 0644]
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/expr-as-stmt.fixed
src/test/ui/parser/expr-as-stmt.rs
src/test/ui/parser/expr-as-stmt.stderr
src/test/ui/parser/float-literals.rs [new file with mode: 0644]
src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs
src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr
src/test/ui/parser/issue-48636.fixed [new file with mode: 0644]
src/test/ui/parser/issue-48636.rs [new file with mode: 0644]
src/test/ui/parser/issue-48636.stderr [new file with mode: 0644]
src/test/ui/parser/issue-54521-1.rs [new file with mode: 0644]
src/test/ui/parser/issue-54521-2.fixed [new file with mode: 0644]
src/test/ui/parser/issue-54521-2.rs [new file with mode: 0644]
src/test/ui/parser/issue-54521-2.stderr [new file with mode: 0644]
src/test/ui/parser/issue-54521-3.fixed [new file with mode: 0644]
src/test/ui/parser/issue-54521-3.rs [new file with mode: 0644]
src/test/ui/parser/issue-54521-3.stderr [new file with mode: 0644]
src/test/ui/parser/issue-68890-2.rs
src/test/ui/parser/issue-68890-2.stderr
src/test/ui/parser/issue-73568-lifetime-after-mut.rs
src/test/ui/parser/issue-73568-lifetime-after-mut.stderr
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/issue-87086-colon-path-sep.rs [new file with mode: 0644]
src/test/ui/parser/issue-87086-colon-path-sep.stderr [new file with mode: 0644]
src/test/ui/parser/macro/trait-object-macro-matcher.rs
src/test/ui/parser/macro/trait-object-macro-matcher.stderr
src/test/ui/parser/parser-unicode-whitespace.rs
src/test/ui/parser/range-inclusive-extra-equals.rs [new file with mode: 0644]
src/test/ui/parser/range-inclusive-extra-equals.stderr [new file with mode: 0644]
src/test/ui/parser/recover-range-pats.rs
src/test/ui/parser/recover-range-pats.stderr
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/parser/struct-literal-in-for.stderr
src/test/ui/parser/trait-object-trait-parens.rs
src/test/ui/parser/trait-object-trait-parens.stderr
src/test/ui/parser/variadic-ffi-semantic-restrictions.rs
src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr
src/test/ui/pattern/issue-68394-let-pat-runtime-value.rs [deleted file]
src/test/ui/pattern/issue-68394-let-pat-runtime-value.stderr [deleted file]
src/test/ui/pattern/issue-68396-let-float-bug.rs [deleted file]
src/test/ui/pattern/issue-68396-let-float-bug.stderr [deleted file]
src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.rs [deleted file]
src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.stderr [deleted file]
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/pattern/non-constant-in-const-path.rs [new file with mode: 0644]
src/test/ui/pattern/non-constant-in-const-path.stderr [new file with mode: 0644]
src/test/ui/privacy/privacy1.stderr
src/test/ui/privacy/private-impl-method.stderr
src/test/ui/privacy/private-method-cross-crate.stderr
src/test/ui/privacy/private-method-inherited.stderr
src/test/ui/privacy/private-method.stderr
src/test/ui/privacy/restricted/test.stderr
src/test/ui/proc-macro/attributes-on-modules-fail.rs
src/test/ui/proc-macro/attributes-on-modules-fail.stderr
src/test/ui/proc-macro/auxiliary/call-deprecated.rs [new file with mode: 0644]
src/test/ui/proc-macro/call-deprecated.rs [new file with mode: 0644]
src/test/ui/proc-macro/call-deprecated.stderr [new file with mode: 0644]
src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr
src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr
src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs [new file with mode: 0644]
src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr [new file with mode: 0644]
src/test/ui/proc-macro/macros-in-extern-derive.rs
src/test/ui/proc-macro/macros-in-extern-derive.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/process-termination/process-termination-blocking-io.rs
src/test/ui/range/range-1.stderr
src/test/ui/range/range-inclusive-pattern-precedence.fixed
src/test/ui/range/range-inclusive-pattern-precedence.rs
src/test/ui/range/range-inclusive-pattern-precedence.stderr
src/test/ui/range/range-inclusive-pattern-precedence2.rs
src/test/ui/range/range-inclusive-pattern-precedence2.stderr
src/test/ui/range/range_traits-1.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-83505-repr-simd.rs [new file with mode: 0644]
src/test/ui/repr/issue-83505-repr-simd.stderr [new file with mode: 0644]
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/repr/repr-disallow-on-variant.rs
src/test/ui/repr/repr-disallow-on-variant.stderr
src/test/ui/repr/repr-transparent.rs
src/test/ui/repr/repr-transparent.stderr
src/test/ui/resolve/use_suggestion_placement.fixed [new file with mode: 0644]
src/test/ui/resolve/use_suggestion_placement.rs
src/test/ui/resolve/use_suggestion_placement.stderr
src/test/ui/retslot-cast.stderr
src/test/ui/return/issue-86188-return-not-in-fn-body.rs [new file with mode: 0644]
src/test/ui/return/issue-86188-return-not-in-fn-body.stderr [new file with mode: 0644]
src/test/ui/return/return-match-array-const.rs
src/test/ui/return/return-match-array-const.stderr
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-1937-termination-trait/termination-trait-test-wrong-type.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-2361-dbg-macro/dbg-macro-requires-debug.stderr
src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs [new file with mode: 0644]
src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr [new file with mode: 0644]
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/rfc-2632-const-trait-impl/assoc-type.rs
src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/attr-misuse.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs
src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs
src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs
src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs
src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs
src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr
src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs
src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr
src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs
src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr
src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr
src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs
src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr
src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs
src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs
src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr
src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/stability.rs
src/test/ui/rfc-2632-const-trait-impl/stability.stderr
src/test/ui/rfc-2632-const-trait-impl/staged-api.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/syntax.rs
src/test/ui/rt-explody-panic-payloads.rs [new file with mode: 0644]
src/test/ui/rust-2018/async-ident-allowed.rs
src/test/ui/rust-2018/async-ident-allowed.stderr
src/test/ui/rust-2018/async-ident.fixed
src/test/ui/rust-2018/async-ident.rs
src/test/ui/rust-2018/async-ident.stderr
src/test/ui/rust-2018/dyn-keyword.fixed
src/test/ui/rust-2018/dyn-keyword.rs
src/test/ui/rust-2018/dyn-keyword.stderr
src/test/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
src/test/ui/rust-2018/edition-lint-fully-qualified-paths.rs
src/test/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
src/test/ui/rust-2018/edition-lint-nested-empty-paths.fixed
src/test/ui/rust-2018/edition-lint-nested-empty-paths.rs
src/test/ui/rust-2018/edition-lint-nested-empty-paths.stderr
src/test/ui/rust-2018/edition-lint-nested-paths.fixed
src/test/ui/rust-2018/edition-lint-nested-paths.rs
src/test/ui/rust-2018/edition-lint-nested-paths.stderr
src/test/ui/rust-2018/edition-lint-paths.fixed
src/test/ui/rust-2018/edition-lint-paths.rs
src/test/ui/rust-2018/edition-lint-paths.stderr
src/test/ui/rust-2018/extern-crate-rename.fixed
src/test/ui/rust-2018/extern-crate-rename.rs
src/test/ui/rust-2018/extern-crate-rename.stderr
src/test/ui/rust-2018/extern-crate-submod.fixed
src/test/ui/rust-2018/extern-crate-submod.rs
src/test/ui/rust-2018/extern-crate-submod.stderr
src/test/ui/rust-2018/try-ident.fixed
src/test/ui/rust-2018/try-ident.rs
src/test/ui/rust-2018/try-ident.stderr
src/test/ui/rust-2018/try-macro.fixed
src/test/ui/rust-2018/try-macro.rs
src/test/ui/rust-2018/try-macro.stderr
src/test/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs [new file with mode: 0644]
src/test/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-imported.fixed [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-imported.rs [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-imported.stderr [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-shadow.rs [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-shadow.stderr [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-unneeded.rs [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision.fixed [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision.rs [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision.stderr [new file with mode: 0644]
src/test/ui/rust-2021/generic-type-collision.fixed [new file with mode: 0644]
src/test/ui/rust-2021/generic-type-collision.rs [new file with mode: 0644]
src/test/ui/rust-2021/generic-type-collision.stderr [new file with mode: 0644]
src/test/ui/rust-2021/inherent-dyn-collision.fixed [new file with mode: 0644]
src/test/ui/rust-2021/inherent-dyn-collision.rs [new file with mode: 0644]
src/test/ui/rust-2021/inherent-dyn-collision.stderr [new file with mode: 0644]
src/test/ui/rust-2021/inherent-method-collision.rs [new file with mode: 0644]
src/test/ui/rust-2021/reserved-prefixes-migration.fixed [new file with mode: 0644]
src/test/ui/rust-2021/reserved-prefixes-migration.rs [new file with mode: 0644]
src/test/ui/rust-2021/reserved-prefixes-migration.stderr [new file with mode: 0644]
src/test/ui/rust-2021/reserved-prefixes-via-macro-2.rs [new file with mode: 0644]
src/test/ui/rust-2021/reserved-prefixes-via-macro-2.stderr [new file with mode: 0644]
src/test/ui/rust-2021/reserved-prefixes-via-macro.rs [new file with mode: 0644]
src/test/ui/rust-2021/reserved-prefixes.rs [new file with mode: 0644]
src/test/ui/rust-2021/reserved-prefixes.stderr [new file with mode: 0644]
src/test/ui/rustdoc/check-doc-alias-attr-location.rs
src/test/ui/rustdoc/check-doc-alias-attr-location.stderr
src/test/ui/rustdoc/doc_keyword.rs
src/test/ui/rustdoc/doc_keyword.stderr
src/test/ui/sanitize/crt-static.rs
src/test/ui/sanitize/incompatible.rs
src/test/ui/sanitize/unsupported-target.rs
src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr
src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr
src/test/ui/self/self-infer.rs
src/test/ui/self/self-infer.stderr
src/test/ui/self/self-re-assign.rs
src/test/ui/simd-intrinsic/issue-85855.rs [new file with mode: 0644]
src/test/ui/simd-intrinsic/issue-85855.stderr [new file with mode: 0644]
src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr
src/test/ui/span/issue-29595.stderr
src/test/ui/span/missing-unit-argument.rs
src/test/ui/span/missing-unit-argument.stderr
src/test/ui/specialization/deafult-generic-associated-type-bound.rs
src/test/ui/specialization/deafult-generic-associated-type-bound.stderr
src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
src/test/ui/stability-attribute/generics-default-stability.stderr
src/test/ui/static/static-method-privacy.stderr
src/test/ui/structs/struct-path-alias-bounds.stderr
src/test/ui/suggestions/const-no-type.rs
src/test/ui/suggestions/const-no-type.stderr
src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
src/test/ui/suggestions/issue-61963.rs
src/test/ui/suggestions/issue-61963.stderr
src/test/ui/suggestions/issue-68049-1.stderr
src/test/ui/suggestions/issue-68049-2.stderr
src/test/ui/suggestions/issue-72766.stderr
src/test/ui/suggestions/issue-84973.stderr
src/test/ui/suggestions/issue-86667.rs [new file with mode: 0644]
src/test/ui/suggestions/issue-86667.stderr [new file with mode: 0644]
src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr
src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
src/test/ui/suggestions/object-unsafe-trait-references-self.stderr
src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr
src/test/ui/suggestions/path-display.stderr
src/test/ui/suggestions/suggest-change-mut.stderr
src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.rs [new file with mode: 0644]
src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr [new file with mode: 0644]
src/test/ui/suggestions/suggest-mut-method-for-loop.stderr
src/test/ui/suggestions/suggest-ref-mut.stderr
src/test/ui/suggestions/suggest-remove-refs-1.stderr
src/test/ui/suggestions/suggest-remove-refs-2.stderr
src/test/ui/suggestions/suggest-remove-refs-3.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/suggestions/unnamable-types.rs [new file with mode: 0644]
src/test/ui/suggestions/unnamable-types.stderr [new file with mode: 0644]
src/test/ui/suggestions/use-placement-resolve.fixed [new file with mode: 0644]
src/test/ui/suggestions/use-placement-resolve.rs [new file with mode: 0644]
src/test/ui/suggestions/use-placement-resolve.stderr [new file with mode: 0644]
src/test/ui/suggestions/use-placement-typeck.fixed [new file with mode: 0644]
src/test/ui/suggestions/use-placement-typeck.rs [new file with mode: 0644]
src/test/ui/suggestions/use-placement-typeck.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/synthetic-param.stderr
src/test/ui/test-attrs/test-panic-abort-disabled.rs [new file with mode: 0644]
src/test/ui/test-attrs/test-panic-abort-disabled.stderr [new file with mode: 0644]
src/test/ui/test-attrs/test-panic-abort-nocapture.rs [new file with mode: 0644]
src/test/ui/test-attrs/test-panic-abort-nocapture.run.stderr [new file with mode: 0644]
src/test/ui/test-attrs/test-panic-abort-nocapture.run.stdout [new file with mode: 0644]
src/test/ui/test-attrs/test-panic-abort.rs [new file with mode: 0644]
src/test/ui/test-attrs/test-panic-abort.run.stdout [new file with mode: 0644]
src/test/ui/test-attrs/test-panic-while-printing.rs [new file with mode: 0644]
src/test/ui/test-attrs/test-passed-wasm.rs [new file with mode: 0644]
src/test/ui/test-attrs/test-passed-wasm.run.stdout [new file with mode: 0644]
src/test/ui/test-attrs/test-passed.rs [new file with mode: 0644]
src/test/ui/test-attrs/test-passed.run.stdout [new file with mode: 0644]
src/test/ui/test-attrs/test-thread-capture.rs [new file with mode: 0644]
src/test/ui/test-attrs/test-thread-capture.run.stdout [new file with mode: 0644]
src/test/ui/test-attrs/test-thread-nocapture.rs [new file with mode: 0644]
src/test/ui/test-attrs/test-thread-nocapture.run.stderr [new file with mode: 0644]
src/test/ui/test-attrs/test-thread-nocapture.run.stdout [new file with mode: 0644]
src/test/ui/test-cfg.rs [deleted file]
src/test/ui/test-cfg.stderr [deleted file]
src/test/ui/test-panic-abort-disabled.rs [deleted file]
src/test/ui/test-panic-abort-disabled.stderr [deleted file]
src/test/ui/test-panic-abort-nocapture.rs [deleted file]
src/test/ui/test-panic-abort-nocapture.run.stderr [deleted file]
src/test/ui/test-panic-abort-nocapture.run.stdout [deleted file]
src/test/ui/test-panic-abort.rs [deleted file]
src/test/ui/test-panic-abort.run.stdout [deleted file]
src/test/ui/test-panic-while-printing.rs [deleted file]
src/test/ui/test-passed-wasm.rs [deleted file]
src/test/ui/test-passed-wasm.run.stdout [deleted file]
src/test/ui/test-passed.rs [deleted file]
src/test/ui/test-passed.run.stdout [deleted file]
src/test/ui/test-thread-capture.rs [deleted file]
src/test/ui/test-thread-capture.run.stdout [deleted file]
src/test/ui/test-thread-nocapture.rs [deleted file]
src/test/ui/test-thread-nocapture.run.stderr [deleted file]
src/test/ui/test-thread-nocapture.run.stdout [deleted file]
src/test/ui/thir-unsafeck-issue-85871.rs [new file with mode: 0644]
src/test/ui/thread-local-static.rs
src/test/ui/thread-local-static.stderr
src/test/ui/thread-local/thread-local-issue-37508.rs [new file with mode: 0644]
src/test/ui/traits/bad-sized.stderr
src/test/ui/traits/bound/not-on-bare-trait.rs
src/test/ui/traits/bound/not-on-bare-trait.stderr
src/test/ui/traits/bound/on-structs-and-enums-locals.stderr
src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr
src/test/ui/traits/cycle-cache-err-60010.stderr
src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr
src/test/ui/traits/issue-71136.stderr
src/test/ui/traits/issue-77982.stderr
src/test/ui/traits/issue-78632.rs [new file with mode: 0644]
src/test/ui/traits/issue-79458.stderr
src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs
src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr
src/test/ui/traits/item-privacy.stderr
src/test/ui/traits/method-private.stderr
src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
src/test/ui/traits/object/issue-33140-traitobject-crate.rs
src/test/ui/traits/object/issue-33140-traitobject-crate.stderr
src/test/ui/traits/operator-overloading-issue-52025.rs [new file with mode: 0644]
src/test/ui/traits/reservation-impl/no-use.stderr
src/test/ui/traits/reservation-impl/non-lattice-ok.rs
src/test/ui/traits/static-method-generic-inference.stderr
src/test/ui/traits/suggest-where-clause.stderr
src/test/ui/trivial-bounds/trivial-bounds-leak.stderr
src/test/ui/try-block/try-block-bad-type.stderr
src/test/ui/try-block/try-block-in-while.stderr
src/test/ui/try-trait/bad-interconversion.stderr
src/test/ui/try-trait/option-to-result.stderr
src/test/ui/try-trait/try-on-option-diagnostics.stderr
src/test/ui/try-trait/try-on-option.stderr
src/test/ui/try-trait/try-operator-on-main.stderr
src/test/ui/type-alias-impl-trait/associated-type-lifetime-ice.rs [deleted file]
src/test/ui/type-alias-impl-trait/associated-type-lifetime-ice.stderr [deleted file]
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.nll.stderr
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.stderr
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.nll.stderr
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.stderr
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
src/test/ui/type-alias-impl-trait/issue-53096.full_tait.stderr
src/test/ui/type-alias-impl-trait/issue-53096.min_tait.stderr
src/test/ui/type-alias-impl-trait/issue-53096.rs
src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.full_tait.stderr
src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.min_tait.stderr
src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.nll.stderr
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.stderr
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.nll.stderr
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.stderr
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
src/test/ui/type-alias-impl-trait/issue-60371.rs
src/test/ui/type-alias-impl-trait/issue-60371.stderr
src/test/ui/type-alias-impl-trait/issue-60407.full_tait.stderr
src/test/ui/type-alias-impl-trait/issue-60407.min_tait.stderr
src/test/ui/type-alias-impl-trait/issue-60407.rs
src/test/ui/type-alias-impl-trait/issue-63355.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-63355.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-65384.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-65384.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.full_tait.stderr
src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
src/test/ui/type-alias-impl-trait/issue-69323.full.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-69323.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-74761-2.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-74761-2.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-78450.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-78450.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.full_tait.stderr
src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.min_tait.stderr
src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
src/test/ui/type-alias-impl-trait/structural-match-no-leak.full_tait.stderr
src/test/ui/type-alias-impl-trait/structural-match-no-leak.min_tait.stderr
src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs
src/test/ui/type-alias-impl-trait/structural-match.full_tait.stderr
src/test/ui/type-alias-impl-trait/structural-match.min_tait.stderr
src/test/ui/type-alias-impl-trait/structural-match.rs
src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.full_tait.stderr
src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.min_tait.stderr
src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs
src/test/ui/type/type-check-defaults.stderr
src/test/ui/type/type-params-in-different-spaces-2.stderr
src/test/ui/typeck-closure-to-unsafe-fn-ptr.rs [deleted file]
src/test/ui/typeck-fn-to-unsafe-fn-ptr.rs [deleted file]
src/test/ui/typeck/conversion-methods.rs [new file with mode: 0644]
src/test/ui/typeck/conversion-methods.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-74086.rs [new file with mode: 0644]
src/test/ui/typeck/issue-74086.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-75883.rs
src/test/ui/typeck/issue-75883.stderr
src/test/ui/typeck/issue-75889.rs [new file with mode: 0644]
src/test/ui/typeck/issue-75889.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-80779.rs
src/test/ui/typeck/issue-80779.stderr
src/test/ui/typeck/issue-81885.rs [new file with mode: 0644]
src/test/ui/typeck/issue-81885.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-83621-placeholder-static-in-extern.stderr
src/test/ui/typeck/issue-84160.rs [new file with mode: 0644]
src/test/ui/typeck/issue-84160.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-86721-return-expr-ice.rev1.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-86721-return-expr-ice.rev2.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-86721-return-expr-ice.rs [new file with mode: 0644]
src/test/ui/typeck/struct-enum-wrong-args.rs [new file with mode: 0644]
src/test/ui/typeck/struct-enum-wrong-args.stderr [new file with mode: 0644]
src/test/ui/typeck/type-placeholder-fn-in-const.rs [new file with mode: 0644]
src/test/ui/typeck/type-placeholder-fn-in-const.stderr [new file with mode: 0644]
src/test/ui/typeck/typeck-closure-to-unsafe-fn-ptr.rs [new file with mode: 0644]
src/test/ui/typeck/typeck-fn-to-unsafe-fn-ptr.rs [new file with mode: 0644]
src/test/ui/typeck/typeck_type_placeholder_1.rs [new file with mode: 0644]
src/test/ui/typeck/typeck_type_placeholder_item.full_tait.stderr
src/test/ui/typeck/typeck_type_placeholder_item.min_tait.stderr
src/test/ui/typeck/typeck_type_placeholder_item.rs
src/test/ui/typeck/typeck_type_placeholder_item_help.rs
src/test/ui/typeck/typeck_type_placeholder_item_help.stderr
src/test/ui/typeck_type_placeholder_1.rs [deleted file]
src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
src/test/ui/unevaluated_fixed_size_array_len.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/unpretty-expr-fn-arg.rs [new file with mode: 0644]
src/test/ui/unpretty-expr-fn-arg.stdout [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/ranged_ints2.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints2.rs
src/test/ui/unsafe/ranged_ints2.stderr [deleted file]
src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints2_const.rs
src/test/ui/unsafe/ranged_ints2_const.stderr [deleted file]
src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints3.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints3.rs
src/test/ui/unsafe/ranged_ints3.stderr [deleted file]
src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints3_const.rs
src/test/ui/unsafe/ranged_ints3_const.stderr [deleted file]
src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints3_match.rs [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints4.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints4.rs
src/test/ui/unsafe/ranged_ints4.stderr [deleted file]
src/test/ui/unsafe/ranged_ints4.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints4_const.rs
src/test/ui/unsafe/ranged_ints4_const.stderr [deleted file]
src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.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/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr
src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs
src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr
src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/unsafe-assign.rs [new file with mode: 0644]
src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/unsafe-borrow.rs [new file with mode: 0644]
src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsized/unsized3-rpass.rs
src/test/ui/unused/unused-doc-comments-edge-cases.rs [new file with mode: 0644]
src/test/ui/unused/unused-doc-comments-edge-cases.stderr [new file with mode: 0644]
src/test/ui/unused/useless-comment.stderr
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/test/ui/variance/variance-btree-invariant-types.nll.stderr
src/test/ui/variance/variance-btree-invariant-types.rs
src/test/ui/variance/variance-btree-invariant-types.stderr
src/test/ui/wait-forked-but-failed-child.rs
src/test/ui/wf/hir-wf-check-erase-regions.rs [new file with mode: 0644]
src/test/ui/wf/hir-wf-check-erase-regions.stderr [new file with mode: 0644]
src/test/ui/wf/wf-complex-assoc-type.rs [new file with mode: 0644]
src/test/ui/wf/wf-complex-assoc-type.stderr [new file with mode: 0644]
src/test/ui/wf/wf-foreign-fn-decl-ret.stderr
src/test/ui/wf/wf-impl-associated-type-trait.stderr
src/test/ui/wf/wf-in-fn-arg.stderr
src/test/ui/wf/wf-in-fn-type-arg.stderr
src/test/ui/wf/wf-in-fn-type-ret.stderr
src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs
src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr
src/test/ui/wf/wf-in-obj-type-trait.stderr
src/test/ui/wf/wf-trait-associated-type-trait.rs
src/test/ui/wf/wf-trait-associated-type-trait.stderr
src/test/ui/wf/wf-trait-default-fn-arg.stderr
src/test/ui/wf/wf-trait-fn-arg.stderr
src/test/ui/write-fmt-errors.rs
src/test/ui/xc-private-method.stderr
src/test/ui/xc-private-method2.stderr
src/tools/clippy/.github/workflows/clippy.yml
src/tools/clippy/.github/workflows/clippy_bors.yml
src/tools/clippy/.github/workflows/remark.yml
src/tools/clippy/.remarkrc
src/tools/clippy/CHANGELOG.md
src/tools/clippy/CONTRIBUTING.md
src/tools/clippy/Cargo.toml
src/tools/clippy/README.md
src/tools/clippy/clippy_dev/Cargo.toml
src/tools/clippy/clippy_dev/src/fmt.rs
src/tools/clippy/clippy_dev/src/ide_setup.rs [deleted file]
src/tools/clippy/clippy_dev/src/lib.rs
src/tools/clippy/clippy_dev/src/main.rs
src/tools/clippy/clippy_dev/src/setup/git_hook.rs [new file with mode: 0644]
src/tools/clippy/clippy_dev/src/setup/intellij.rs [new file with mode: 0644]
src/tools/clippy/clippy_dev/src/setup/mod.rs [new file with mode: 0644]
src/tools/clippy/clippy_dev/src/setup/vscode.rs [new file with mode: 0644]
src/tools/clippy/clippy_dev/src/update_lints.rs
src/tools/clippy/clippy_lints/Cargo.toml
src/tools/clippy/clippy_lints/src/assign_ops.rs
src/tools/clippy/clippy_lints/src/attrs.rs
src/tools/clippy/clippy_lints/src/blacklisted_name.rs
src/tools/clippy/clippy_lints/src/bytecount.rs
src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs
src/tools/clippy/clippy_lints/src/collapsible_match.rs
src/tools/clippy/clippy_lints/src/copies.rs
src/tools/clippy/clippy_lints/src/default.rs
src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
src/tools/clippy/clippy_lints/src/deprecated_lints.rs
src/tools/clippy/clippy_lints/src/dereference.rs
src/tools/clippy/clippy_lints/src/derive.rs
src/tools/clippy/clippy_lints/src/disallowed_method.rs
src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/disallowed_type.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/doc.rs
src/tools/clippy/clippy_lints/src/eq_op.rs
src/tools/clippy/clippy_lints/src/escape.rs
src/tools/clippy/clippy_lints/src/eta_reduction.rs
src/tools/clippy/clippy_lints/src/eval_order_dependence.rs
src/tools/clippy/clippy_lints/src/explicit_write.rs
src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs
src/tools/clippy/clippy_lints/src/format.rs
src/tools/clippy/clippy_lints/src/formatting.rs
src/tools/clippy/clippy_lints/src/get_last_with_len.rs
src/tools/clippy/clippy_lints/src/if_let_mutex.rs
src/tools/clippy/clippy_lints/src/implicit_hasher.rs
src/tools/clippy/clippy_lints/src/inherent_impl.rs
src/tools/clippy/clippy_lints/src/len_zero.rs
src/tools/clippy/clippy_lints/src/lib.rs
src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
src/tools/clippy/clippy_lints/src/loops/mod.rs
src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
src/tools/clippy/clippy_lints/src/manual_map.rs
src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs
src/tools/clippy/clippy_lints/src/map_identity.rs [deleted file]
src/tools/clippy/clippy_lints/src/matches.rs
src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
src/tools/clippy/clippy_lints/src/methods/extend_with_drain.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs
src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs
src/tools/clippy/clippy_lints/src/methods/map_identity.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/methods/mod.rs
src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
src/tools/clippy/clippy_lints/src/misc.rs
src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs
src/tools/clippy/clippy_lints/src/mut_key.rs
src/tools/clippy/clippy_lints/src/needless_bool.rs
src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
src/tools/clippy/clippy_lints/src/no_effect.rs
src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/option_if_let_else.rs
src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
src/tools/clippy/clippy_lints/src/ptr.rs
src/tools/clippy/clippy_lints/src/ranges.rs
src/tools/clippy/clippy_lints/src/redundant_clone.rs
src/tools/clippy/clippy_lints/src/self_named_constructors.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
src/tools/clippy/clippy_lints/src/strings.rs
src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
src/tools/clippy/clippy_lints/src/types/mod.rs
src/tools/clippy/clippy_lints/src/types/rc_mutex.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
src/tools/clippy/clippy_lints/src/unicode.rs
src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs
src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
src/tools/clippy/clippy_lints/src/unused_unit.rs
src/tools/clippy/clippy_lints/src/use_self.rs
src/tools/clippy/clippy_lints/src/useless_conversion.rs
src/tools/clippy/clippy_lints/src/utils/conf.rs
src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs
src/tools/clippy/clippy_lints/src/wildcard_imports.rs
src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
src/tools/clippy/clippy_utils/Cargo.toml
src/tools/clippy/clippy_utils/src/ast_utils.rs
src/tools/clippy/clippy_utils/src/attrs.rs
src/tools/clippy/clippy_utils/src/consts.rs
src/tools/clippy/clippy_utils/src/higher.rs
src/tools/clippy/clippy_utils/src/lib.rs
src/tools/clippy/clippy_utils/src/numeric_literal.rs
src/tools/clippy/clippy_utils/src/paths.rs
src/tools/clippy/clippy_utils/src/ptr.rs
src/tools/clippy/clippy_utils/src/sugg.rs
src/tools/clippy/clippy_utils/src/ty.rs
src/tools/clippy/clippy_utils/src/usage.rs
src/tools/clippy/doc/basics.md
src/tools/clippy/doc/common_tools_writing_lints.md
src/tools/clippy/doc/release.md
src/tools/clippy/lintcheck/README.md
src/tools/clippy/lintcheck/src/main.rs
src/tools/clippy/rust-toolchain
src/tools/clippy/src/main.rs
src/tools/clippy/tests/compile-test.rs
src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/clippy.toml [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/clippy.toml [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/toml_disallowed_method/clippy.toml
src/tools/clippy/tests/ui-toml/toml_disallowed_type/clippy.toml [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
src/tools/clippy/tests/ui/assertions_on_constants.rs
src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
src/tools/clippy/tests/ui/auxiliary/non-exhaustive-enum.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/blacklisted_name.rs
src/tools/clippy/tests/ui/branches_sharing_code/false_positives.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/bytes_nth.fixed
src/tools/clippy/tests/ui/bytes_nth.rs
src/tools/clippy/tests/ui/bytes_nth.stderr
src/tools/clippy/tests/ui/crashes/ice-3969.stderr
src/tools/clippy/tests/ui/crashes/ice-6179.rs
src/tools/clippy/tests/ui/crashes/ice-7340.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/crashes/ice-7410.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/crashes/ice-7423.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/default_numeric_fallback.rs [deleted file]
src/tools/clippy/tests/ui/default_numeric_fallback.stderr [deleted file]
src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/default_numeric_fallback_f64.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/deprecated.stderr
src/tools/clippy/tests/ui/disallowed_script_idents.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/disallowed_script_idents.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/doc.rs [deleted file]
src/tools/clippy/tests/ui/doc.stderr [deleted file]
src/tools/clippy/tests/ui/doc/doc.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/doc/doc.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/doc/unbalanced_ticks.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/eta.fixed
src/tools/clippy/tests/ui/eta.rs
src/tools/clippy/tests/ui/eta.stderr
src/tools/clippy/tests/ui/explicit_write_non_rustfix.stderr
src/tools/clippy/tests/ui/extend_with_drain.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/extend_with_drain.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/extend_with_drain.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/field_reassign_with_default.rs
src/tools/clippy/tests/ui/field_reassign_with_default.stderr
src/tools/clippy/tests/ui/filter_map_identity.fixed
src/tools/clippy/tests/ui/filter_map_identity.rs
src/tools/clippy/tests/ui/filter_map_identity.stderr
src/tools/clippy/tests/ui/flat_map_identity.fixed
src/tools/clippy/tests/ui/flat_map_identity.rs
src/tools/clippy/tests/ui/flat_map_identity.stderr
src/tools/clippy/tests/ui/format.fixed
src/tools/clippy/tests/ui/format.rs
src/tools/clippy/tests/ui/future_not_send.stderr
src/tools/clippy/tests/ui/issue-7447.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/issue_4266.rs
src/tools/clippy/tests/ui/iter_count.fixed
src/tools/clippy/tests/ui/iter_count.rs
src/tools/clippy/tests/ui/iter_count.stderr
src/tools/clippy/tests/ui/match_same_arms.stderr
src/tools/clippy/tests/ui/match_same_arms2.stderr
src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs
src/tools/clippy/tests/ui/missing-doc-impl.rs
src/tools/clippy/tests/ui/missing-doc-impl.stderr
src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs
src/tools/clippy/tests/ui/mut_key.stderr
src/tools/clippy/tests/ui/needless_bool/fixable.fixed
src/tools/clippy/tests/ui/needless_bool/fixable.rs
src/tools/clippy/tests/ui/needless_bool/fixable.stderr
src/tools/clippy/tests/ui/needless_lifetimes.rs
src/tools/clippy/tests/ui/panicking_macros.rs
src/tools/clippy/tests/ui/rc_mutex.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/rc_mutex.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_allocation.fixed [deleted file]
src/tools/clippy/tests/ui/redundant_allocation.rs
src/tools/clippy/tests/ui/redundant_allocation.stderr
src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_allocation_fixable.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_allocation_fixable.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_clone.fixed
src/tools/clippy/tests/ui/redundant_clone.rs
src/tools/clippy/tests/ui/redundant_clone.stderr
src/tools/clippy/tests/ui/self_named_constructors.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/self_named_constructors.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs
src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr
src/tools/clippy/tests/ui/strlen_on_c_strings.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/strlen_on_c_strings.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/suspicious_arithmetic_impl.stderr
src/tools/clippy/tests/ui/unit_arg.rs
src/tools/clippy/tests/ui/unit_arg.stderr
src/tools/clippy/tests/ui/unnecessary_cast_fixable.fixed
src/tools/clippy/tests/ui/unnecessary_cast_fixable.rs
src/tools/clippy/tests/ui/use_self.fixed
src/tools/clippy/tests/ui/use_self.rs
src/tools/clippy/tests/ui/use_self.stderr
src/tools/clippy/tests/ui/vec.fixed
src/tools/clippy/tests/ui/vec.rs
src/tools/clippy/tests/ui/while_let_on_iterator.fixed
src/tools/clippy/tests/ui/while_let_on_iterator.rs
src/tools/clippy/tests/ui/while_let_on_iterator.stderr
src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs
src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr
src/tools/clippy/tests/ui/zero_offset.rs
src/tools/clippy/tests/ui/zero_offset.stderr
src/tools/clippy/util/etc/pre-commit.sh [new file with mode: 0755]
src/tools/clippy/util/etc/vscode-tasks.json [new file with mode: 0644]
src/tools/clippy/util/lintlib.py
src/tools/compiletest/Cargo.toml
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/header/tests.rs
src/tools/compiletest/src/json.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs
src/tools/error_index_generator/main.rs
src/tools/html-checker/Cargo.toml [new file with mode: 0644]
src/tools/html-checker/main.rs [new file with mode: 0644]
src/tools/linkchecker/main.rs
src/tools/linkchecker/tests/broken_redir/redir-bad.html
src/tools/linkchecker/tests/checks.rs
src/tools/linkchecker/tests/redirect_loop/redir-bad.html
src/tools/linkchecker/tests/valid/inner/redir-bad.html
src/tools/linkchecker/tests/valid/inner/redir.html
src/tools/lint-docs/src/lib.rs
src/tools/rustc-workspace-hack/Cargo.toml
src/tools/rustdoc-gui/tester.js
src/tools/rustfmt/CHANGELOG.md
src/tools/rustfmt/Configurations.md
src/tools/rustfmt/Contributing.md
src/tools/rustfmt/Design.md
src/tools/rustfmt/README.md
src/tools/rustfmt/ci/integration.sh
src/tools/rustfmt/src/formatting.rs
src/tools/rustfmt/src/lib.rs
src/tools/rustfmt/src/types.rs
src/tools/rustfmt/src/utils.rs
src/tools/tidy/Cargo.toml
src/tools/tidy/src/deps.rs
src/tools/tidy/src/error_codes_check.rs
src/tools/tidy/src/features.rs
src/tools/tidy/src/lib.rs
src/tools/tidy/src/main.rs
src/tools/tidy/src/pal.rs
src/tools/tidy/src/style.rs
src/tools/tidy/src/target_specific_tests.rs [new file with mode: 0644]
src/tools/tidy/src/ui_tests.rs
src/version
vendor/anyhow/.cargo-checksum.json
vendor/anyhow/Cargo.toml
vendor/anyhow/src/error.rs
vendor/anyhow/src/lib.rs
vendor/anyhow/tests/test_boxed.rs
vendor/anyhow/tests/test_chain.rs
vendor/anyhow/tests/test_context.rs
vendor/anyhow/tests/test_convert.rs
vendor/anyhow/tests/test_downcast.rs
vendor/anyhow/tests/ui/no-impl.stderr
vendor/arrayvec/.cargo-checksum.json
vendor/arrayvec/CHANGELOG.md
vendor/arrayvec/Cargo.toml
vendor/arrayvec/src/arrayvec.rs
vendor/arrayvec/src/lib.rs
vendor/arrayvec/tests/tests.rs
vendor/byteorder/.cargo-checksum.json
vendor/byteorder/CHANGELOG.md
vendor/byteorder/Cargo.toml
vendor/byteorder/README.md
vendor/byteorder/benches/bench.rs
vendor/byteorder/build.rs [new file with mode: 0644]
vendor/byteorder/rustfmt.toml [deleted file]
vendor/byteorder/src/io.rs
vendor/byteorder/src/lib.rs
vendor/cargo_metadata-0.11.1/.cargo-checksum.json [deleted file]
vendor/cargo_metadata-0.11.1/Cargo.toml [deleted file]
vendor/cargo_metadata-0.11.1/LICENSE-MIT [deleted file]
vendor/cargo_metadata-0.11.1/README.md [deleted file]
vendor/cargo_metadata-0.11.1/src/dependency.rs [deleted file]
vendor/cargo_metadata-0.11.1/src/diagnostic.rs [deleted file]
vendor/cargo_metadata-0.11.1/src/errors.rs [deleted file]
vendor/cargo_metadata-0.11.1/src/lib.rs [deleted file]
vendor/cargo_metadata-0.11.1/src/messages.rs [deleted file]
vendor/cargo_metadata-0.11.1/tests/selftest.rs [deleted file]
vendor/cargo_metadata-0.11.1/tests/test_samples.rs [deleted file]
vendor/cc/.cargo-checksum.json
vendor/cc/Cargo.lock
vendor/cc/Cargo.toml
vendor/cc/src/lib.rs
vendor/cc/src/windows_registry.rs
vendor/compiler_builtins/.cargo-checksum.json
vendor/compiler_builtins/Cargo.lock
vendor/compiler_builtins/Cargo.toml
vendor/compiler_builtins/build.rs
vendor/compiler_builtins/libm/src/math/fma.rs
vendor/compiler_builtins/libm/src/math/pow.rs
vendor/compiler_builtins/src/int/shift.rs
vendor/globwalk/.cargo-checksum.json [new file with mode: 0644]
vendor/globwalk/Cargo.lock [new file with mode: 0644]
vendor/globwalk/Cargo.toml [new file with mode: 0644]
vendor/globwalk/LICENSE [new file with mode: 0644]
vendor/globwalk/README.md [new file with mode: 0644]
vendor/globwalk/appveyor.yml [new file with mode: 0644]
vendor/globwalk/examples/list.rs [new file with mode: 0644]
vendor/globwalk/src/doctests.rs [new file with mode: 0644]
vendor/globwalk/src/lib.rs [new file with mode: 0644]
vendor/globwalk/tests/docs.rs [new file with mode: 0644]
vendor/hashbrown-0.9.1/.cargo-checksum.json [deleted file]
vendor/hashbrown-0.9.1/CHANGELOG.md [deleted file]
vendor/hashbrown-0.9.1/Cargo.toml [deleted file]
vendor/hashbrown-0.9.1/LICENSE-APACHE [deleted file]
vendor/hashbrown-0.9.1/LICENSE-MIT [deleted file]
vendor/hashbrown-0.9.1/README.md [deleted file]
vendor/hashbrown-0.9.1/benches/bench.rs [deleted file]
vendor/hashbrown-0.9.1/clippy.toml [deleted file]
vendor/hashbrown-0.9.1/src/external_trait_impls/mod.rs [deleted file]
vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/helpers.rs [deleted file]
vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/map.rs [deleted file]
vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/mod.rs [deleted file]
vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/raw.rs [deleted file]
vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/set.rs [deleted file]
vendor/hashbrown-0.9.1/src/external_trait_impls/serde.rs [deleted file]
vendor/hashbrown-0.9.1/src/lib.rs [deleted file]
vendor/hashbrown-0.9.1/src/macros.rs [deleted file]
vendor/hashbrown-0.9.1/src/map.rs [deleted file]
vendor/hashbrown-0.9.1/src/raw/bitmask.rs [deleted file]
vendor/hashbrown-0.9.1/src/raw/generic.rs [deleted file]
vendor/hashbrown-0.9.1/src/raw/mod.rs [deleted file]
vendor/hashbrown-0.9.1/src/raw/sse2.rs [deleted file]
vendor/hashbrown-0.9.1/src/rustc_entry.rs [deleted file]
vendor/hashbrown-0.9.1/src/scopeguard.rs [deleted file]
vendor/hashbrown-0.9.1/src/set.rs [deleted file]
vendor/hashbrown-0.9.1/tests/hasher.rs [deleted file]
vendor/hashbrown-0.9.1/tests/rayon.rs [deleted file]
vendor/hashbrown-0.9.1/tests/serde.rs [deleted file]
vendor/hashbrown-0.9.1/tests/set.rs [deleted file]
vendor/hashbrown/.cargo-checksum.json
vendor/hashbrown/CHANGELOG.md
vendor/hashbrown/Cargo.toml
vendor/hashbrown/src/lib.rs
vendor/hashbrown/src/map.rs
vendor/hashbrown/src/set.rs
vendor/heck/.cargo-checksum.json
vendor/heck/Cargo.toml
vendor/heck/README.md
vendor/heck/no_step_on_snek.png [deleted file]
vendor/heck/src/camel.rs
vendor/heck/src/kebab.rs
vendor/heck/src/lib.rs
vendor/heck/src/mixed.rs
vendor/heck/src/shouty_kebab.rs
vendor/heck/src/shouty_snake.rs
vendor/heck/src/snake.rs
vendor/heck/src/title.rs
vendor/hermit-abi/.cargo-checksum.json
vendor/hermit-abi/Cargo.toml
vendor/hermit-abi/src/lib.rs
vendor/indexmap/.cargo-checksum.json
vendor/indexmap/Cargo.toml
vendor/indexmap/README.rst
vendor/indexmap/benches/bench.rs
vendor/indexmap/src/lib.rs
vendor/indexmap/src/map.rs
vendor/indexmap/src/rayon/map.rs
vendor/indexmap/src/rayon/mod.rs
vendor/indexmap/src/rayon/set.rs
vendor/indexmap/src/set.rs
vendor/indexmap/tests/quick.rs
vendor/libc/.cargo-checksum.json
vendor/libc/Cargo.toml
vendor/libc/src/fuchsia/mod.rs
vendor/libc/src/unix/bsd/apple/mod.rs
vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs
vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs
vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs
vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs
vendor/libc/src/unix/bsd/freebsdlike/freebsd/powerpc.rs [new file with mode: 0644]
vendor/libc/src/unix/bsd/freebsdlike/mod.rs
vendor/libc/src/unix/bsd/mod.rs
vendor/libc/src/unix/bsd/netbsdlike/mod.rs
vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs
vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs
vendor/libc/src/unix/linux_like/android/b32/arm.rs
vendor/libc/src/unix/linux_like/android/b32/mod.rs
vendor/libc/src/unix/linux_like/android/b64/aarch64/mod.rs
vendor/libc/src/unix/linux_like/android/b64/mod.rs
vendor/libc/src/unix/linux_like/android/b64/x86_64/mod.rs
vendor/libc/src/unix/linux_like/android/mod.rs
vendor/libc/src/unix/linux_like/emscripten/mod.rs
vendor/libc/src/unix/linux_like/linux/gnu/b32/mod.rs
vendor/libc/src/unix/linux_like/linux/gnu/b64/mod.rs
vendor/libc/src/unix/linux_like/linux/gnu/mod.rs
vendor/libc/src/unix/linux_like/linux/mod.rs
vendor/libc/src/unix/linux_like/linux/uclibc/mod.rs
vendor/libc/src/unix/linux_like/mod.rs
vendor/libc/src/unix/solarish/illumos.rs
vendor/libc/src/unix/solarish/mod.rs
vendor/libc/src/wasi.rs
vendor/libc/src/windows/mod.rs
vendor/memchr/.cargo-checksum.json
vendor/memchr/Cargo.toml
vendor/memchr/README.md
vendor/memchr/scripts/make-byte-frequency-table [new file with mode: 0755]
vendor/memchr/src/cow.rs
vendor/memchr/src/lib.rs
vendor/memchr/src/memmem/genericsimd.rs
vendor/memchr/src/memmem/prefilter/fallback.rs
vendor/memchr/src/memmem/prefilter/mod.rs
vendor/memchr/src/tests/memchr/testdata.rs
vendor/memmap2-0.2.1/.cargo-checksum.json [new file with mode: 0644]
vendor/memmap2-0.2.1/CHANGELOG.md [new file with mode: 0644]
vendor/memmap2-0.2.1/Cargo.lock [new file with mode: 0644]
vendor/memmap2-0.2.1/Cargo.toml [new file with mode: 0644]
vendor/memmap2-0.2.1/LICENSE-APACHE [new file with mode: 0644]
vendor/memmap2-0.2.1/LICENSE-MIT [new file with mode: 0644]
vendor/memmap2-0.2.1/README.md [new file with mode: 0644]
vendor/memmap2-0.2.1/examples/cat.rs [new file with mode: 0644]
vendor/memmap2-0.2.1/src/lib.rs [new file with mode: 0644]
vendor/memmap2-0.2.1/src/unix.rs [new file with mode: 0644]
vendor/memmap2-0.2.1/src/windows.rs [new file with mode: 0644]
vendor/memmap2/.cargo-checksum.json [deleted file]
vendor/memmap2/CHANGELOG.md [deleted file]
vendor/memmap2/Cargo.lock [deleted file]
vendor/memmap2/Cargo.toml [deleted file]
vendor/memmap2/LICENSE-APACHE [deleted file]
vendor/memmap2/LICENSE-MIT [deleted file]
vendor/memmap2/README.md [deleted file]
vendor/memmap2/examples/cat.rs [deleted file]
vendor/memmap2/src/lib.rs [deleted file]
vendor/memmap2/src/stub.rs [deleted file]
vendor/memmap2/src/unix.rs [deleted file]
vendor/memmap2/src/windows.rs [deleted file]
vendor/num-integer/.cargo-checksum.json
vendor/num-integer/Cargo.toml
vendor/num-integer/README.md
vendor/num-integer/RELEASES.md
vendor/num-integer/build.rs
vendor/num-traits/.cargo-checksum.json
vendor/num-traits/Cargo.toml
vendor/num-traits/README.md
vendor/num-traits/RELEASES.md
vendor/num-traits/build.rs
vendor/num-traits/src/cast.rs
vendor/num-traits/src/lib.rs
vendor/num-traits/src/ops/mod.rs
vendor/num-traits/src/ops/overflowing.rs [deleted file]
vendor/num-traits/src/sign.rs
vendor/num-traits/tests/cast.rs
vendor/object/.cargo-checksum.json
vendor/object/CHANGELOG.md
vendor/object/Cargo.lock
vendor/object/Cargo.toml
vendor/object/README.md
vendor/object/examples/readobj.rs
vendor/object/src/common.rs
vendor/object/src/elf.rs
vendor/object/src/lib.rs
vendor/object/src/pe.rs
vendor/object/src/pod.rs
vendor/object/src/read/any.rs
vendor/object/src/read/archive.rs
vendor/object/src/read/coff/file.rs
vendor/object/src/read/coff/section.rs
vendor/object/src/read/coff/symbol.rs
vendor/object/src/read/elf/file.rs
vendor/object/src/read/elf/hash.rs [new file with mode: 0644]
vendor/object/src/read/elf/mod.rs
vendor/object/src/read/elf/note.rs
vendor/object/src/read/elf/relocation.rs
vendor/object/src/read/elf/section.rs
vendor/object/src/read/elf/segment.rs
vendor/object/src/read/elf/symbol.rs
vendor/object/src/read/elf/version.rs [new file with mode: 0644]
vendor/object/src/read/macho/dyld_cache.rs
vendor/object/src/read/macho/file.rs
vendor/object/src/read/macho/load_command.rs
vendor/object/src/read/macho/symbol.rs
vendor/object/src/read/mod.rs
vendor/object/src/read/pe/file.rs
vendor/object/src/read/pe/section.rs
vendor/object/src/read/read_cache.rs
vendor/object/src/read/read_ref.rs
vendor/object/src/read/util.rs
vendor/object/src/write/coff.rs
vendor/object/src/write/elf.rs
vendor/object/src/write/macho.rs
vendor/object/src/write/mod.rs
vendor/object/src/write/util.rs
vendor/once_cell/.cargo-checksum.json
vendor/once_cell/CHANGELOG.md
vendor/once_cell/Cargo.lock
vendor/once_cell/Cargo.toml
vendor/once_cell/src/lib.rs
vendor/once_cell/src/race.rs
vendor/opener/.cargo-checksum.json
vendor/opener/Cargo.toml
vendor/opener/Drakefile.ts [new file with mode: 0755]
vendor/opener/LICENSE-APACHE [changed mode: 0644->0755]
vendor/opener/LICENSE-MIT [changed mode: 0644->0755]
vendor/opener/LICENSE-THIRD-PARTY [changed mode: 0644->0755]
vendor/opener/Makefile.toml [deleted file]
vendor/opener/release.toml [deleted file]
vendor/opener/src/lib.rs
vendor/opener/src/linux_and_more.rs [new file with mode: 0644]
vendor/opener/src/macos.rs [new file with mode: 0644]
vendor/opener/src/windows.rs [new file with mode: 0644]
vendor/opener/src/xdg-open [changed mode: 0644->0755]
vendor/opener/tests/version-numbers.rs [new file with mode: 0644]
vendor/pin-project-lite/.cargo-checksum.json
vendor/pin-project-lite/CHANGELOG.md
vendor/pin-project-lite/Cargo.toml
vendor/pin-project-lite/README.md
vendor/pin-project-lite/src/lib.rs
vendor/pin-project-lite/tests/compiletest.rs
vendor/pin-project-lite/tests/drop_order.rs
vendor/pin-project-lite/tests/expand/pinned_drop/enum.expanded.rs [new file with mode: 0644]
vendor/pin-project-lite/tests/expand/pinned_drop/enum.rs [new file with mode: 0644]
vendor/pin-project-lite/tests/expand/pinned_drop/struct.expanded.rs [new file with mode: 0644]
vendor/pin-project-lite/tests/expand/pinned_drop/struct.rs [new file with mode: 0644]
vendor/pin-project-lite/tests/expandtest.rs
vendor/pin-project-lite/tests/lint.rs
vendor/pin-project-lite/tests/test.rs
vendor/pin-project-lite/tests/ui/pin_project/conflict-drop.stderr
vendor/pin-project-lite/tests/ui/pin_project/conflict-unpin.stderr
vendor/pin-project-lite/tests/ui/pin_project/invalid-bounds.stderr
vendor/pin-project-lite/tests/ui/pin_project/invalid.stderr
vendor/pin-project-lite/tests/ui/pin_project/overlapping_lifetime_names.rs
vendor/pin-project-lite/tests/ui/pin_project/overlapping_lifetime_names.stderr
vendor/pin-project-lite/tests/ui/pin_project/overlapping_unpin_struct.rs
vendor/pin-project-lite/tests/ui/pin_project/overlapping_unpin_struct.stderr
vendor/pin-project-lite/tests/ui/pin_project/packed.rs
vendor/pin-project-lite/tests/ui/pin_project/packed.stderr
vendor/pin-project-lite/tests/ui/pin_project/unsupported.stderr
vendor/pin-project-lite/tests/ui/pinned_drop/call-drop-inner.rs [new file with mode: 0644]
vendor/pin-project-lite/tests/ui/pinned_drop/call-drop-inner.stderr [new file with mode: 0644]
vendor/pin-project-lite/tests/ui/pinned_drop/conditional-drop-impl.rs [new file with mode: 0644]
vendor/pin-project-lite/tests/ui/pinned_drop/conditional-drop-impl.stderr [new file with mode: 0644]
vendor/redox_syscall/.cargo-checksum.json
vendor/redox_syscall/Cargo.toml
vendor/redox_syscall/src/io/io.rs
vendor/redox_syscall/src/lib.rs
vendor/regex-1.4.3/.cargo-checksum.json [deleted file]
vendor/regex-1.4.3/CHANGELOG.md [deleted file]
vendor/regex-1.4.3/Cargo.lock [deleted file]
vendor/regex-1.4.3/Cargo.toml [deleted file]
vendor/regex-1.4.3/HACKING.md [deleted file]
vendor/regex-1.4.3/LICENSE-APACHE [deleted file]
vendor/regex-1.4.3/LICENSE-MIT [deleted file]
vendor/regex-1.4.3/PERFORMANCE.md [deleted file]
vendor/regex-1.4.3/README.md [deleted file]
vendor/regex-1.4.3/UNICODE.md [deleted file]
vendor/regex-1.4.3/examples/regexdna-input.txt [deleted file]
vendor/regex-1.4.3/examples/regexdna-output.txt [deleted file]
vendor/regex-1.4.3/examples/shootout-regex-dna-bytes.rs [deleted file]
vendor/regex-1.4.3/examples/shootout-regex-dna-cheat.rs [deleted file]
vendor/regex-1.4.3/examples/shootout-regex-dna-replace.rs [deleted file]
vendor/regex-1.4.3/examples/shootout-regex-dna-single-cheat.rs [deleted file]
vendor/regex-1.4.3/examples/shootout-regex-dna-single.rs [deleted file]
vendor/regex-1.4.3/examples/shootout-regex-dna.rs [deleted file]
vendor/regex-1.4.3/rustfmt.toml [deleted file]
vendor/regex-1.4.3/src/backtrack.rs [deleted file]
vendor/regex-1.4.3/src/cache.rs [deleted file]
vendor/regex-1.4.3/src/compile.rs [deleted file]
vendor/regex-1.4.3/src/dfa.rs [deleted file]
vendor/regex-1.4.3/src/error.rs [deleted file]
vendor/regex-1.4.3/src/exec.rs [deleted file]
vendor/regex-1.4.3/src/expand.rs [deleted file]
vendor/regex-1.4.3/src/find_byte.rs [deleted file]
vendor/regex-1.4.3/src/freqs.rs [deleted file]
vendor/regex-1.4.3/src/input.rs [deleted file]
vendor/regex-1.4.3/src/lib.rs [deleted file]
vendor/regex-1.4.3/src/literal/imp.rs [deleted file]
vendor/regex-1.4.3/src/literal/mod.rs [deleted file]
vendor/regex-1.4.3/src/pattern.rs [deleted file]
vendor/regex-1.4.3/src/pikevm.rs [deleted file]
vendor/regex-1.4.3/src/prog.rs [deleted file]
vendor/regex-1.4.3/src/re_builder.rs [deleted file]
vendor/regex-1.4.3/src/re_bytes.rs [deleted file]
vendor/regex-1.4.3/src/re_set.rs [deleted file]
vendor/regex-1.4.3/src/re_trait.rs [deleted file]
vendor/regex-1.4.3/src/re_unicode.rs [deleted file]
vendor/regex-1.4.3/src/sparse.rs [deleted file]
vendor/regex-1.4.3/src/testdata/LICENSE [deleted file]
vendor/regex-1.4.3/src/testdata/README [deleted file]
vendor/regex-1.4.3/src/testdata/basic.dat [deleted file]
vendor/regex-1.4.3/src/testdata/nullsubexpr.dat [deleted file]
vendor/regex-1.4.3/src/testdata/repetition.dat [deleted file]
vendor/regex-1.4.3/src/utf8.rs [deleted file]
vendor/regex-1.4.3/test [deleted file]
vendor/regex-1.4.3/tests/api.rs [deleted file]
vendor/regex-1.4.3/tests/api_str.rs [deleted file]
vendor/regex-1.4.3/tests/bytes.rs [deleted file]
vendor/regex-1.4.3/tests/consistent.rs [deleted file]
vendor/regex-1.4.3/tests/crates_regex.rs [deleted file]
vendor/regex-1.4.3/tests/crazy.rs [deleted file]
vendor/regex-1.4.3/tests/flags.rs [deleted file]
vendor/regex-1.4.3/tests/fowler.rs [deleted file]
vendor/regex-1.4.3/tests/macros.rs [deleted file]
vendor/regex-1.4.3/tests/macros_bytes.rs [deleted file]
vendor/regex-1.4.3/tests/macros_str.rs [deleted file]
vendor/regex-1.4.3/tests/misc.rs [deleted file]
vendor/regex-1.4.3/tests/multiline.rs [deleted file]
vendor/regex-1.4.3/tests/noparse.rs [deleted file]
vendor/regex-1.4.3/tests/regression.rs [deleted file]
vendor/regex-1.4.3/tests/regression_fuzz.rs [deleted file]
vendor/regex-1.4.3/tests/replace.rs [deleted file]
vendor/regex-1.4.3/tests/searcher.rs [deleted file]
vendor/regex-1.4.3/tests/set.rs [deleted file]
vendor/regex-1.4.3/tests/shortest_match.rs [deleted file]
vendor/regex-1.4.3/tests/suffix_reverse.rs [deleted file]
vendor/regex-1.4.3/tests/test_backtrack.rs [deleted file]
vendor/regex-1.4.3/tests/test_backtrack_bytes.rs [deleted file]
vendor/regex-1.4.3/tests/test_backtrack_utf8bytes.rs [deleted file]
vendor/regex-1.4.3/tests/test_crates_regex.rs [deleted file]
vendor/regex-1.4.3/tests/test_default.rs [deleted file]
vendor/regex-1.4.3/tests/test_default_bytes.rs [deleted file]
vendor/regex-1.4.3/tests/test_nfa.rs [deleted file]
vendor/regex-1.4.3/tests/test_nfa_bytes.rs [deleted file]
vendor/regex-1.4.3/tests/test_nfa_utf8bytes.rs [deleted file]
vendor/regex-1.4.3/tests/unicode.rs [deleted file]
vendor/regex-1.4.3/tests/word_boundary.rs [deleted file]
vendor/regex-1.4.3/tests/word_boundary_ascii.rs [deleted file]
vendor/regex-1.4.3/tests/word_boundary_unicode.rs [deleted file]
vendor/regex-1.4.6/.cargo-checksum.json [new file with mode: 0644]
vendor/regex-1.4.6/CHANGELOG.md [new file with mode: 0644]
vendor/regex-1.4.6/Cargo.lock [new file with mode: 0644]
vendor/regex-1.4.6/Cargo.toml [new file with mode: 0644]
vendor/regex-1.4.6/HACKING.md [new file with mode: 0644]
vendor/regex-1.4.6/LICENSE-APACHE [new file with mode: 0644]
vendor/regex-1.4.6/LICENSE-MIT [new file with mode: 0644]
vendor/regex-1.4.6/PERFORMANCE.md [new file with mode: 0644]
vendor/regex-1.4.6/README.md [new file with mode: 0644]
vendor/regex-1.4.6/UNICODE.md [new file with mode: 0644]
vendor/regex-1.4.6/examples/regexdna-input.txt [new file with mode: 0644]
vendor/regex-1.4.6/examples/regexdna-output.txt [new file with mode: 0644]
vendor/regex-1.4.6/examples/shootout-regex-dna-bytes.rs [new file with mode: 0644]
vendor/regex-1.4.6/examples/shootout-regex-dna-cheat.rs [new file with mode: 0644]
vendor/regex-1.4.6/examples/shootout-regex-dna-replace.rs [new file with mode: 0644]
vendor/regex-1.4.6/examples/shootout-regex-dna-single-cheat.rs [new file with mode: 0644]
vendor/regex-1.4.6/examples/shootout-regex-dna-single.rs [new file with mode: 0644]
vendor/regex-1.4.6/examples/shootout-regex-dna.rs [new file with mode: 0644]
vendor/regex-1.4.6/rustfmt.toml [new file with mode: 0644]
vendor/regex-1.4.6/src/backtrack.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/compile.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/dfa.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/error.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/exec.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/expand.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/find_byte.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/freqs.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/input.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/lib.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/literal/imp.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/literal/mod.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/pattern.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/pikevm.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/pool.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/prog.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/re_builder.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/re_bytes.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/re_set.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/re_trait.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/re_unicode.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/sparse.rs [new file with mode: 0644]
vendor/regex-1.4.6/src/testdata/LICENSE [new file with mode: 0644]
vendor/regex-1.4.6/src/testdata/README [new file with mode: 0644]
vendor/regex-1.4.6/src/testdata/basic.dat [new file with mode: 0644]
vendor/regex-1.4.6/src/testdata/nullsubexpr.dat [new file with mode: 0644]
vendor/regex-1.4.6/src/testdata/repetition.dat [new file with mode: 0644]
vendor/regex-1.4.6/src/utf8.rs [new file with mode: 0644]
vendor/regex-1.4.6/test [new file with mode: 0755]
vendor/regex-1.4.6/tests/api.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/api_str.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/bytes.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/consistent.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/crates_regex.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/crazy.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/flags.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/fowler.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/macros.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/macros_bytes.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/macros_str.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/misc.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/multiline.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/noparse.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/regression.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/regression_fuzz.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/replace.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/searcher.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/set.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/shortest_match.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/suffix_reverse.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/test_backtrack.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/test_backtrack_bytes.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/test_backtrack_utf8bytes.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/test_crates_regex.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/test_default.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/test_default_bytes.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/test_nfa.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/test_nfa_bytes.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/test_nfa_utf8bytes.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/unicode.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/word_boundary.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/word_boundary_ascii.rs [new file with mode: 0644]
vendor/regex-1.4.6/tests/word_boundary_unicode.rs [new file with mode: 0644]
vendor/regex-automata/.cargo-checksum.json
vendor/regex-automata/Cargo.toml
vendor/regex-automata/README.md
vendor/regex-automata/src/byteorder.rs [new file with mode: 0644]
vendor/regex-automata/src/determinize.rs
vendor/regex-automata/src/lib.rs
vendor/regex-automata/src/sparse_set.rs
vendor/rustc-demangle/.cargo-checksum.json
vendor/rustc-demangle/Cargo.toml
vendor/rustc-demangle/src/v0.rs
vendor/rustfix-0.5.1/.cargo-checksum.json [new file with mode: 0644]
vendor/rustfix-0.5.1/Cargo.toml [new file with mode: 0644]
vendor/rustfix-0.5.1/Changelog.md [new file with mode: 0644]
vendor/rustfix-0.5.1/LICENSE-APACHE [new file with mode: 0644]
vendor/rustfix-0.5.1/LICENSE-MIT [new file with mode: 0644]
vendor/rustfix-0.5.1/Readme.md [new file with mode: 0644]
vendor/rustfix-0.5.1/proptest-regressions/replace.txt [new file with mode: 0644]
vendor/rustfix-0.5.1/src/diagnostics.rs [new file with mode: 0644]
vendor/rustfix-0.5.1/src/lib.rs [new file with mode: 0644]
vendor/rustfix-0.5.1/src/replace.rs [new file with mode: 0644]
vendor/rustfix/.cargo-checksum.json
vendor/rustfix/Cargo.toml
vendor/rustfix/Readme.md
vendor/rustfix/src/lib.rs
vendor/rustfix/src/replace.rs
vendor/rustversion/.cargo-checksum.json
vendor/rustversion/Cargo.toml
vendor/rustversion/build/build.rs
vendor/rustversion/build/rustc.rs
vendor/rustversion/src/lib.rs
vendor/rustversion/src/time.rs
vendor/rustversion/tests/test_parse.rs
vendor/rustversion/tests/ui/bad-bound.stderr
vendor/rustversion/tests/ui/bad-date.stderr
vendor/semver-0.10.0/.cargo-checksum.json [deleted file]
vendor/semver-0.10.0/Cargo.toml [deleted file]
vendor/semver-0.10.0/LICENSE-APACHE [deleted file]
vendor/semver-0.10.0/LICENSE-MIT [deleted file]
vendor/semver-0.10.0/README.md [deleted file]
vendor/semver-0.10.0/src/diesel_impls.rs [deleted file]
vendor/semver-0.10.0/src/lib.rs [deleted file]
vendor/semver-0.10.0/src/version.rs [deleted file]
vendor/semver-0.10.0/src/version_req.rs [deleted file]
vendor/semver-0.10.0/tests/deprecation.rs [deleted file]
vendor/semver-0.10.0/tests/diesel.rs [deleted file]
vendor/semver-0.10.0/tests/serde.rs [deleted file]
vendor/semver-parser-0.7.0/.cargo-checksum.json [deleted file]
vendor/semver-parser-0.7.0/Cargo.toml [deleted file]
vendor/semver-parser-0.7.0/LICENSE-APACHE [deleted file]
vendor/semver-parser-0.7.0/LICENSE-MIT [deleted file]
vendor/semver-parser-0.7.0/src/common.rs [deleted file]
vendor/semver-parser-0.7.0/src/lib.rs [deleted file]
vendor/semver-parser-0.7.0/src/range.rs [deleted file]
vendor/semver-parser-0.7.0/src/recognize.rs [deleted file]
vendor/semver-parser-0.7.0/src/version.rs [deleted file]
vendor/syn/.cargo-checksum.json
vendor/syn/Cargo.toml
vendor/syn/src/attr.rs
vendor/syn/src/data.rs
vendor/syn/src/discouraged.rs
vendor/syn/src/error.rs
vendor/syn/src/expr.rs
vendor/syn/src/gen/visit.rs
vendor/syn/src/gen/visit_mut.rs
vendor/syn/src/item.rs
vendor/syn/src/lib.rs
vendor/syn/src/lifetime.rs
vendor/syn/src/lit.rs
vendor/syn/src/punctuated.rs
vendor/syn/tests/common/eq.rs
vendor/tera/.cargo-checksum.json [new file with mode: 0644]
vendor/tera/CHANGELOG.md [new file with mode: 0644]
vendor/tera/Cargo.toml [new file with mode: 0644]
vendor/tera/LICENSE [new file with mode: 0644]
vendor/tera/README.md [new file with mode: 0644]
vendor/tera/docs/README.md [new file with mode: 0644]
vendor/tera/src/builtins/filters/array.rs [new file with mode: 0644]
vendor/tera/src/builtins/filters/common.rs [new file with mode: 0644]
vendor/tera/src/builtins/filters/mod.rs [new file with mode: 0644]
vendor/tera/src/builtins/filters/number.rs [new file with mode: 0644]
vendor/tera/src/builtins/filters/object.rs [new file with mode: 0644]
vendor/tera/src/builtins/filters/string.rs [new file with mode: 0644]
vendor/tera/src/builtins/functions.rs [new file with mode: 0644]
vendor/tera/src/builtins/mod.rs [new file with mode: 0644]
vendor/tera/src/builtins/testers.rs [new file with mode: 0644]
vendor/tera/src/context.rs [new file with mode: 0644]
vendor/tera/src/errors.rs [new file with mode: 0644]
vendor/tera/src/filter_utils.rs [new file with mode: 0644]
vendor/tera/src/lib.rs [new file with mode: 0644]
vendor/tera/src/macros.rs [new file with mode: 0644]
vendor/tera/src/parser/ast.rs [new file with mode: 0644]
vendor/tera/src/parser/mod.rs [new file with mode: 0644]
vendor/tera/src/parser/tera.pest [new file with mode: 0644]
vendor/tera/src/parser/tests/errors.rs [new file with mode: 0644]
vendor/tera/src/parser/tests/lexer.rs [new file with mode: 0644]
vendor/tera/src/parser/tests/mod.rs [new file with mode: 0644]
vendor/tera/src/parser/tests/parser.rs [new file with mode: 0644]
vendor/tera/src/parser/tests/whitespace.rs [new file with mode: 0644]
vendor/tera/src/parser/whitespace.rs [new file with mode: 0644]
vendor/tera/src/renderer/call_stack.rs [new file with mode: 0644]
vendor/tera/src/renderer/for_loop.rs [new file with mode: 0644]
vendor/tera/src/renderer/macros.rs [new file with mode: 0644]
vendor/tera/src/renderer/mod.rs [new file with mode: 0644]
vendor/tera/src/renderer/processor.rs [new file with mode: 0644]
vendor/tera/src/renderer/square_brackets.rs [new file with mode: 0644]
vendor/tera/src/renderer/stack_frame.rs [new file with mode: 0644]
vendor/tera/src/renderer/tests/basic.rs [new file with mode: 0644]
vendor/tera/src/renderer/tests/errors.rs [new file with mode: 0644]
vendor/tera/src/renderer/tests/inheritance.rs [new file with mode: 0644]
vendor/tera/src/renderer/tests/macros.rs [new file with mode: 0644]
vendor/tera/src/renderer/tests/mod.rs [new file with mode: 0644]
vendor/tera/src/renderer/tests/square_brackets.rs [new file with mode: 0644]
vendor/tera/src/renderer/tests/whitespace.rs [new file with mode: 0644]
vendor/tera/src/template.rs [new file with mode: 0644]
vendor/tera/src/tera.rs [new file with mode: 0644]
vendor/tera/src/utils.rs [new file with mode: 0644]
vendor/tracing-subscriber/.cargo-checksum.json
vendor/tracing-subscriber/CHANGELOG.md
vendor/tracing-subscriber/Cargo.toml
vendor/tracing-subscriber/src/filter/env/mod.rs
vendor/tracing-subscriber/src/filter/level.rs
vendor/tracing-subscriber/src/fmt/fmt_layer.rs
vendor/tracing-subscriber/src/fmt/format/json.rs
vendor/tracing-subscriber/src/fmt/format/mod.rs
vendor/tracing-subscriber/src/fmt/format/pretty.rs
vendor/tracing-subscriber/src/fmt/mod.rs
vendor/tracing-subscriber/src/fmt/writer.rs
vendor/tracing-subscriber/src/layer.rs
vendor/tracing-subscriber/src/lib.rs
vendor/tracing-subscriber/src/prelude.rs
vendor/tracing-subscriber/src/registry/mod.rs
vendor/unicode-normalization/.cargo-checksum.json
vendor/unicode-normalization/Cargo.toml
vendor/unicode-normalization/README.md
vendor/unicode-normalization/scripts/unicode.py
vendor/unicode-normalization/src/lib.rs
vendor/unicode-normalization/src/tables.rs
vendor/unicode-script/.cargo-checksum.json
vendor/unicode-script/Cargo.toml
vendor/unicode-script/scripts/unicode.py
vendor/unicode-script/src/lib.rs
vendor/unicode-script/src/tables.rs
vendor/unicode-segmentation/.cargo-checksum.json
vendor/unicode-segmentation/Cargo.toml
vendor/unicode-segmentation/README.md
vendor/unicode-segmentation/benches/graphemes.rs
vendor/unicode-segmentation/benches/unicode_words.rs [new file with mode: 0644]
vendor/unicode-segmentation/benches/word_bounds.rs [new file with mode: 0644]
vendor/unicode-segmentation/scripts/unicode.py
vendor/unicode-segmentation/src/grapheme.rs
vendor/unicode-segmentation/src/lib.rs
vendor/unicode-segmentation/src/sentence.rs
vendor/unicode-segmentation/src/tables.rs
vendor/unicode-segmentation/src/test.rs
vendor/unicode-segmentation/src/word.rs
version

index de110c55a4b2c6e374a8fa15fd61470543846117..085aae3d0b1c006bfb0c145cfa6b6e0fe835ae42 100644 (file)
@@ -73,7 +73,7 @@ version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -82,7 +82,7 @@ version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -111,7 +111,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
 dependencies = [
  "hermit-abi",
  "libc",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -179,13 +179,14 @@ dependencies = [
  "libc",
  "merge",
  "num_cpus",
+ "once_cell",
  "opener",
  "pretty_assertions",
  "serde",
  "serde_json",
  "time",
  "toml",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -194,7 +195,9 @@ version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931"
 dependencies = [
+ "lazy_static",
  "memchr",
+ "regex-automata",
 ]
 
 [[package]]
@@ -240,9 +243,9 @@ checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
 
 [[package]]
 name = "bytes"
-version = "0.5.6"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
+checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
 
 [[package]]
 name = "bytesize"
@@ -252,7 +255,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da"
 
 [[package]]
 name = "cargo"
-version = "0.55.0"
+version = "0.56.0"
 dependencies = [
  "anyhow",
  "atty",
@@ -266,7 +269,7 @@ dependencies = [
  "crossbeam-utils 0.8.3",
  "curl",
  "curl-sys",
- "env_logger 0.8.1",
+ "env_logger 0.9.0",
  "filetime",
  "flate2",
  "fwdansi",
@@ -291,9 +294,8 @@ dependencies = [
  "openssl",
  "percent-encoding 2.1.0",
  "pretty_env_logger",
- "rand 0.8.3",
  "rustc-workspace-hack",
- "rustfix",
+ "rustfix 0.6.0",
  "semver 1.0.3",
  "serde",
  "serde_ignored",
@@ -308,7 +310,7 @@ dependencies = [
  "unicode-xid",
  "url 2.2.2",
  "walkdir",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -337,7 +339,7 @@ name = "cargo-credential-wincred"
 version = "0.1.0"
 dependencies = [
  "cargo-credential",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -374,17 +376,19 @@ dependencies = [
  "flate2",
  "git2",
  "glob",
+ "itertools 0.10.0",
  "lazy_static",
  "remove_dir_all",
  "serde_json",
  "tar",
+ "termcolor",
  "toml",
  "url 2.2.2",
 ]
 
 [[package]]
 name = "cargo-util"
-version = "0.1.0"
+version = "0.1.1"
 dependencies = [
  "anyhow",
  "core-foundation",
@@ -394,12 +398,12 @@ dependencies = [
  "jobserver",
  "libc",
  "log",
- "miow 0.3.6",
+ "miow",
  "same-file",
  "shell-escape",
  "tempfile",
  "walkdir",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -414,17 +418,6 @@ dependencies = [
  "serde_json",
 ]
 
-[[package]]
-name = "cargo_metadata"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89fec17b16f1ac67908af82e47d0a90a7afd0e1827b181cd77504323d3263d35"
-dependencies = [
- "semver 0.10.0",
- "serde",
- "serde_json",
-]
-
 [[package]]
 name = "cargo_metadata"
 version = "0.12.0"
@@ -442,9 +435,9 @@ version = "0.1.0"
 
 [[package]]
 name = "cc"
-version = "1.0.68"
+version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
+checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
 dependencies = [
  "jobserver",
 ]
@@ -528,7 +521,7 @@ dependencies = [
  "num-integer",
  "num-traits",
  "time",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -549,7 +542,7 @@ dependencies = [
 
 [[package]]
 name = "clippy"
-version = "0.1.54"
+version = "0.1.55"
 dependencies = [
  "cargo_metadata 0.12.0",
  "clippy_lints",
@@ -582,7 +575,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_lints"
-version = "0.1.54"
+version = "0.1.55"
 dependencies = [
  "cargo_metadata 0.12.0",
  "clippy_utils",
@@ -597,12 +590,13 @@ dependencies = [
  "serde_json",
  "toml",
  "unicode-normalization",
+ "unicode-script",
  "url 2.2.2",
 ]
 
 [[package]]
 name = "clippy_utils"
-version = "0.1.54"
+version = "0.1.55"
 dependencies = [
  "if_chain",
  "itertools 0.9.0",
@@ -629,7 +623,7 @@ checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd"
 dependencies = [
  "atty",
  "lazy_static",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -652,9 +646,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.45"
+version = "0.1.49"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "787187ae221adfcda34b03006f1617099e4ae26b50e5a4db282496014ab75837"
+checksum = "20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -670,16 +664,16 @@ dependencies = [
  "glob",
  "lazy_static",
  "libc",
- "miow 0.3.6",
+ "miow",
  "regex",
- "rustfix",
+ "rustfix 0.6.0",
  "serde",
  "serde_json",
  "tracing",
  "tracing-subscriber",
  "unified-diff",
  "walkdir",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -694,15 +688,15 @@ dependencies = [
  "lazy_static",
  "libc",
  "log",
- "miow 0.3.6",
+ "miow",
  "regex",
- "rustfix",
+ "rustfix 0.5.1",
  "serde",
  "serde_derive",
  "serde_json",
  "tempfile",
  "tester",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -837,7 +831,7 @@ dependencies = [
  "commoncrypto",
  "hex 0.3.2",
  "openssl",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -862,24 +856,24 @@ dependencies = [
 
 [[package]]
 name = "curl"
-version = "0.4.36"
+version = "0.4.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0bac9f84ca0977c4d9b8db998689de55b9e976656a6bc87fada2ca710d504c7"
+checksum = "003cb79c1c6d1c93344c7e1201bb51c2148f24ec2bd9c253709d6b2efb796515"
 dependencies = [
  "curl-sys",
  "libc",
  "openssl-probe",
  "openssl-sys",
  "schannel",
- "socket2 0.4.0",
- "winapi 0.3.9",
+ "socket2",
+ "winapi",
 ]
 
 [[package]]
 name = "curl-sys"
-version = "0.4.42+curl-7.76.0"
+version = "0.4.45+curl-7.78.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4636d8d6109c842707018a104051436bffb8991ea20b2d1293db70b6e0ee4c7c"
+checksum = "de9e5a72b1c744eb5dd20b2be4d7eb84625070bb5c4ab9b347b70464ab1e62eb"
 dependencies = [
  "cc",
  "libc",
@@ -888,7 +882,7 @@ dependencies = [
  "openssl-sys",
  "pkg-config",
  "vcpkg",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -986,7 +980,7 @@ checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
 dependencies = [
  "libc",
  "redox_users",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -997,7 +991,7 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
 dependencies = [
  "libc",
  "redox_users",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -1100,6 +1094,19 @@ dependencies = [
  "termcolor",
 ]
 
+[[package]]
+name = "env_logger"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
+dependencies = [
+ "atty",
+ "humantime 2.0.1",
+ "log",
+ "regex",
+ "termcolor",
+]
+
 [[package]]
 name = "error_index_generator"
 version = "0.0.0"
@@ -1141,7 +1148,7 @@ dependencies = [
  "cfg-if 1.0.0",
  "libc",
  "redox_syscall",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -1222,22 +1229,6 @@ version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d79238883cf0307100b90aba4a755d8051a3182305dfe7f649a1e9dc0517006f"
 
-[[package]]
-name = "fuchsia-zircon"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
-dependencies = [
- "bitflags",
- "fuchsia-zircon-sys",
-]
-
-[[package]]
-name = "fuchsia-zircon-sys"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
-
 [[package]]
 name = "futf"
 version = "0.1.4"
@@ -1344,7 +1335,7 @@ dependencies = [
  "futures-sink",
  "futures-task",
  "memchr",
- "pin-project-lite 0.2.4",
+ "pin-project-lite",
  "pin-utils",
  "proc-macro-hack",
  "proc-macro-nested",
@@ -1482,6 +1473,17 @@ dependencies = [
  "regex",
 ]
 
+[[package]]
+name = "globwalk"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
+dependencies = [
+ "bitflags",
+ "ignore",
+ "walkdir",
+]
+
 [[package]]
 name = "gsgdt"
 version = "0.1.2"
@@ -1505,12 +1507,6 @@ dependencies = [
  "serde_json",
 ]
 
-[[package]]
-name = "hashbrown"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
-
 [[package]]
 name = "hashbrown"
 version = "0.11.0"
@@ -1560,7 +1556,14 @@ version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
+]
+
+[[package]]
+name = "html-checker"
+version = "0.1.0"
+dependencies = [
+ "walkdir",
 ]
 
 [[package]]
@@ -1654,12 +1657,12 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "1.6.0"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
+checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
 dependencies = [
  "autocfg",
- "hashbrown 0.9.1",
+ "hashbrown",
 ]
 
 [[package]]
@@ -1675,7 +1678,7 @@ dependencies = [
  "remove_dir_all",
  "tar",
  "walkdir",
- "winapi 0.3.9",
+ "winapi",
  "xz2",
 ]
 
@@ -1685,15 +1688,6 @@ version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485"
 
-[[package]]
-name = "iovec"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
-dependencies = [
- "libc",
-]
-
 [[package]]
 name = "itertools"
 version = "0.8.2"
@@ -1770,9 +1764,9 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-client-transports"
-version = "17.0.0"
+version = "18.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15b6c6ad01c7354d60de493148c30ac8a82b759e22ae678c8705e9b8e0c566a4"
+checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a"
 dependencies = [
  "derive_more",
  "futures 0.3.12",
@@ -1789,11 +1783,13 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-core"
-version = "17.0.0"
+version = "18.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07569945133257ff557eb37b015497104cea61a2c9edaf126c1cbd6e8332397f"
+checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb"
 dependencies = [
  "futures 0.3.12",
+ "futures-executor",
+ "futures-util",
  "log",
  "serde",
  "serde_derive",
@@ -1802,9 +1798,9 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-core-client"
-version = "17.0.0"
+version = "18.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ac9d56dc729912796637c30f475bbf834594607b27740dfea6e5fa7ba40d1f1"
+checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0"
 dependencies = [
  "futures 0.3.12",
  "jsonrpc-client-transports",
@@ -1812,9 +1808,9 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-derive"
-version = "17.0.0"
+version = "18.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b68ba7e76e5c7796cfa4d2a30e83986550c34404c6d40551c902ca6f7bd4a137"
+checksum = "5b939a78fa820cdfcb7ee7484466746a7377760970f6f9c6fe19f9edcc8a38d2"
 dependencies = [
  "proc-macro-crate",
  "proc-macro2",
@@ -1824,9 +1820,9 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-ipc-server"
-version = "17.0.1"
+version = "18.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c4cd89e5ea7e7f0884e828fc35bb83591a371b92439675eae28efa66c24a97"
+checksum = "382bb0206323ca7cda3dcd7e245cea86d37d02457a02a975e3378fb149a48845"
 dependencies = [
  "futures 0.3.12",
  "jsonrpc-core",
@@ -1839,9 +1835,9 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-pubsub"
-version = "17.0.0"
+version = "18.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c48dbebce7a9c88ab272a4db7d6478aa4c6d9596e6c086366e89efc4e9ed89e"
+checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011"
 dependencies = [
  "futures 0.3.12",
  "jsonrpc-core",
@@ -1854,9 +1850,9 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-server-utils"
-version = "17.0.0"
+version = "18.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4207cce738bf713a82525065b750a008f28351324f438f56b33d698ada95bb4"
+checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4"
 dependencies = [
  "bytes",
  "futures 0.3.12",
@@ -1865,20 +1861,11 @@ dependencies = [
  "lazy_static",
  "log",
  "tokio",
+ "tokio-stream",
  "tokio-util",
  "unicase",
 ]
 
-[[package]]
-name = "kernel32-sys"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-dependencies = [
- "winapi 0.2.8",
- "winapi-build",
-]
-
 [[package]]
 name = "lazy_static"
 version = "1.4.0"
@@ -1999,9 +1986,9 @@ dependencies = [
 
 [[package]]
 name = "lsp-codec"
-version = "0.2.0"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d33c83e320715a1e7e0466a53db2238becb2e5c446deff5506abc81aeacc5ec4"
+checksum = "aa939d0b62476a5a19fb7fcb423a5c6ce8c7e09b851d37531e2fe3e0e6d9d257"
 dependencies = [
  "bytes",
  "serde_json",
@@ -2154,9 +2141,9 @@ dependencies = [
 
 [[package]]
 name = "memchr"
-version = "2.4.0"
+version = "2.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
 
 [[package]]
 name = "memmap2"
@@ -2221,66 +2208,24 @@ dependencies = [
 
 [[package]]
 name = "mio"
-version = "0.6.22"
+version = "0.7.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
+checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16"
 dependencies = [
- "cfg-if 0.1.10",
- "fuchsia-zircon",
- "fuchsia-zircon-sys",
- "iovec",
- "kernel32-sys",
  "libc",
  "log",
- "miow 0.2.2",
- "net2",
- "slab",
- "winapi 0.2.8",
-]
-
-[[package]]
-name = "mio-named-pipes"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656"
-dependencies = [
- "log",
- "mio",
- "miow 0.3.6",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "mio-uds"
-version = "0.6.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
-dependencies = [
- "iovec",
- "libc",
- "mio",
+ "miow",
+ "ntapi",
+ "winapi",
 ]
 
 [[package]]
 name = "miow"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
-dependencies = [
- "kernel32-sys",
- "net2",
- "winapi 0.2.8",
- "ws2_32-sys",
-]
-
-[[package]]
-name = "miow"
-version = "0.3.6"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897"
+checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
 dependencies = [
- "socket2 0.3.19",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -2302,23 +2247,21 @@ dependencies = [
  "smallvec",
 ]
 
-[[package]]
-name = "net2"
-version = "0.2.36"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7cf75f38f16cb05ea017784dc6dbfd354f76c223dba37701734c4f5a9337d02"
-dependencies = [
- "cfg-if 0.1.10",
- "libc",
- "winapi 0.3.9",
-]
-
 [[package]]
 name = "new_debug_unreachable"
 version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
 
+[[package]]
+name = "ntapi"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
+dependencies = [
+ "winapi",
+]
+
 [[package]]
 name = "num-integer"
 version = "0.1.43"
@@ -2361,9 +2304,9 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.25.2"
+version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8bc1d42047cf336f0f939c99e97183cf31551bf0f2865a2ec9c8d91fd4ffb5e"
+checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"
 dependencies = [
  "crc32fast",
  "indexmap",
@@ -2394,23 +2337,24 @@ version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7c283bf0114efea9e42f1a60edea9859e8c47528eae09d01df4b29c1e489cc48"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
 name = "opener"
-version = "0.4.1"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13117407ca9d0caf3a0e74f97b490a7e64c0ae3aa90a8b7085544d0c37b6f3ae"
+checksum = "4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952"
 dependencies = [
- "winapi 0.3.9",
+ "bstr",
+ "winapi",
 ]
 
 [[package]]
 name = "openssl"
-version = "0.10.33"
+version = "0.10.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a61075b62a23fef5a29815de7536d940aa35ce96d18ce0cc5076272db678a577"
+checksum = "549430950c79ae24e6d02e0b7404534ecf311d94cc9f861e9e4020187d13d885"
 dependencies = [
  "bitflags",
  "cfg-if 1.0.0",
@@ -2437,9 +2381,9 @@ dependencies = [
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.61"
+version = "0.9.65"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f"
+checksum = "7a7907e3bfa08bb85105209cdfcb6c63d109f8f6c1ed6ca318fff5c1853fbc1d"
 dependencies = [
  "autocfg",
  "cc",
@@ -2461,7 +2405,7 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -2499,18 +2443,16 @@ dependencies = [
 
 [[package]]
 name = "parity-tokio-ipc"
-version = "0.8.0"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd7f6c69d7687501b2205fe51ade1d7b8797bb3aa141fe5bf13dd78c0483bc89"
+checksum = "9981e32fb75e004cc148f5fb70342f393830e0a4aa62e3cc93b50976218d42b6"
 dependencies = [
  "futures 0.3.12",
  "libc",
  "log",
- "mio-named-pipes",
- "miow 0.3.6",
  "rand 0.7.3",
  "tokio",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -2535,7 +2477,7 @@ dependencies = [
  "libc",
  "redox_syscall",
  "smallvec",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -2656,12 +2598,6 @@ dependencies = [
  "siphasher",
 ]
 
-[[package]]
-name = "pin-project-lite"
-version = "0.1.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b"
-
 [[package]]
 name = "pin-project-lite"
 version = "0.2.4"
@@ -3038,31 +2974,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"
@@ -3078,7 +3012,7 @@ version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -3123,6 +3057,7 @@ dependencies = [
  "serde_json",
  "tempfile",
  "tokio",
+ "tokio-stream",
  "tokio-util",
  "toml",
  "url 2.2.2",
@@ -3286,7 +3221,7 @@ dependencies = [
  "stacker",
  "tempfile",
  "tracing",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -3306,7 +3241,7 @@ dependencies = [
  "termize",
  "tracing",
  "unicode-width",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -3546,6 +3481,7 @@ dependencies = [
 name = "rustc-workspace-hack"
 version = "1.0.0"
 dependencies = [
+ "bstr",
  "byteorder",
  "crossbeam-utils 0.8.3",
  "libc",
@@ -3558,7 +3494,7 @@ dependencies = [
  "smallvec",
  "syn",
  "url 2.2.2",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -3687,10 +3623,8 @@ dependencies = [
  "rustc_codegen_ssa",
  "rustc_data_structures",
  "rustc_errors",
- "rustc_feature",
  "rustc_fs_util",
  "rustc_hir",
- "rustc_incremental",
  "rustc_index",
  "rustc_llvm",
  "rustc_metadata",
@@ -3713,7 +3647,7 @@ dependencies = [
  "itertools 0.9.0",
  "jobserver",
  "libc",
- "object 0.25.2",
+ "object 0.26.2",
  "pathdiff",
  "rustc_apfloat",
  "rustc_ast",
@@ -3731,6 +3665,7 @@ dependencies = [
  "rustc_span",
  "rustc_symbol_mangling",
  "rustc_target",
+ "smallvec",
  "tempfile",
  "tracing",
 ]
@@ -3742,7 +3677,6 @@ dependencies = [
  "arrayvec",
  "bitflags",
  "cfg-if 0.1.10",
- "crossbeam-utils 0.8.3",
  "ena",
  "indexmap",
  "jobserver",
@@ -3762,7 +3696,7 @@ dependencies = [
  "stacker",
  "tempfile",
  "tracing",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -3785,7 +3719,6 @@ dependencies = [
  "rustc_metadata",
  "rustc_middle",
  "rustc_mir",
- "rustc_mir_build",
  "rustc_parse",
  "rustc_plugin_impl",
  "rustc_save_analysis",
@@ -3793,11 +3726,10 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
- "rustc_typeck",
  "tracing",
  "tracing-subscriber",
  "tracing-tree",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -3819,7 +3751,7 @@ dependencies = [
  "termize",
  "tracing",
  "unicode-width",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -3919,10 +3851,8 @@ dependencies = [
 name = "rustc_infer"
 version = "0.0.0"
 dependencies = [
- "rustc_ast",
  "rustc_data_structures",
  "rustc_errors",
- "rustc_graphviz",
  "rustc_hir",
  "rustc_index",
  "rustc_macros",
@@ -3954,7 +3884,6 @@ dependencies = [
  "rustc_expand",
  "rustc_hir",
  "rustc_incremental",
- "rustc_index",
  "rustc_lint",
  "rustc_metadata",
  "rustc_middle",
@@ -3978,7 +3907,7 @@ dependencies = [
  "smallvec",
  "tempfile",
  "tracing",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -4022,7 +3951,6 @@ dependencies = [
  "rustc_serialize",
  "rustc_span",
  "rustc_target",
- "tracing",
 ]
 
 [[package]]
@@ -4066,9 +3994,8 @@ dependencies = [
  "rustc_target",
  "smallvec",
  "snap",
- "stable_deref_trait",
  "tracing",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -4077,7 +4004,6 @@ version = "0.0.0"
 dependencies = [
  "bitflags",
  "chalk-ir",
- "measureme",
  "polonius-engine",
  "rustc-rayon-core",
  "rustc_apfloat",
@@ -4167,7 +4093,6 @@ dependencies = [
  "rustc_lexer",
  "rustc_session",
  "rustc_span",
- "smallvec",
  "tracing",
  "unicode-normalization",
 ]
@@ -4197,7 +4122,6 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
- "rustc_trait_selection",
  "tracing",
 ]
 
@@ -4238,10 +4162,8 @@ dependencies = [
  "measureme",
  "rustc-rayon-core",
  "rustc_ast",
- "rustc_attr",
  "rustc_data_structures",
  "rustc_errors",
- "rustc_feature",
  "rustc_hir",
  "rustc_index",
  "rustc_macros",
@@ -4250,7 +4172,6 @@ dependencies = [
  "rustc_serialize",
  "rustc_session",
  "rustc_span",
- "rustc_target",
  "tracing",
 ]
 
@@ -4328,7 +4249,6 @@ dependencies = [
 name = "rustc_session"
 version = "0.0.0"
 dependencies = [
- "bitflags",
  "getopts",
  "num_cpus",
  "rustc_ast",
@@ -4368,7 +4288,6 @@ version = "0.0.0"
 dependencies = [
  "punycode",
  "rustc-demangle",
- "rustc_ast",
  "rustc_data_structures",
  "rustc_hir",
  "rustc_middle",
@@ -4518,6 +4437,7 @@ dependencies = [
  "serde_json",
  "smallvec",
  "tempfile",
+ "tera",
  "tracing",
  "tracing-subscriber",
  "tracing-tree",
@@ -4554,6 +4474,18 @@ dependencies = [
  "serde_json",
 ]
 
+[[package]]
+name = "rustfix"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f0be05fc0675ef4f47119dc39cfc46636bb77d4fc4ef1bd851b9c3f7697f32a"
+dependencies = [
+ "anyhow",
+ "log",
+ "serde",
+ "serde_json",
+]
+
 [[package]]
 name = "rustfmt-config_proc_macro"
 version = "0.2.0"
@@ -4597,9 +4529,9 @@ dependencies = [
 
 [[package]]
 name = "rustversion"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd"
+checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
 
 [[package]]
 name = "ryu"
@@ -4623,7 +4555,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
 dependencies = [
  "lazy_static",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -4671,16 +4603,6 @@ dependencies = [
  "serde",
 ]
 
-[[package]]
-name = "semver"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "394cec28fa623e00903caf7ba4fa6fb9a0e260280bb8cdbbba029611108a0190"
-dependencies = [
- "semver-parser 0.7.0",
- "serde",
-]
-
 [[package]]
 name = "semver"
 version = "0.11.0"
@@ -4869,17 +4791,6 @@ version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e"
 
-[[package]]
-name = "socket2"
-version = "0.3.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
-dependencies = [
- "cfg-if 1.0.0",
- "libc",
- "winapi 0.3.9",
-]
-
 [[package]]
 name = "socket2"
 version = "0.4.0"
@@ -4887,7 +4798,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2"
 dependencies = [
  "libc",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -4906,7 +4817,7 @@ dependencies = [
  "cfg-if 0.1.10",
  "libc",
  "psm",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -4920,7 +4831,7 @@ dependencies = [
  "core",
  "dlmalloc",
  "fortanix-sgx-abi",
- "hashbrown 0.11.0",
+ "hashbrown",
  "hermit-abi",
  "libc",
  "miniz_oxide",
@@ -5073,7 +4984,7 @@ dependencies = [
  "rand 0.8.3",
  "redox_syscall",
  "remove_dir_all",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -5088,11 +4999,18 @@ dependencies = [
 ]
 
 [[package]]
-name = "term"
-version = "0.0.0"
+name = "tera"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81060acb882480c8793782eb96bc86f5c83d2fc7175ad46c375c6956ef7afa62"
 dependencies = [
- "core",
- "std",
+ "globwalk",
+ "lazy_static",
+ "pest",
+ "pest_derive",
+ "regex",
+ "serde",
+ "serde_json",
 ]
 
 [[package]]
@@ -5102,7 +5020,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5"
 dependencies = [
  "dirs",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -5113,14 +5031,14 @@ checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
 dependencies = [
  "dirs-next",
  "rustversion",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
 name = "termcolor"
-version = "1.1.0"
+version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
+checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
 dependencies = [
  "winapi-util",
 ]
@@ -5132,7 +5050,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1706be6b564323ce7092f5f7e6b118a14c8ef7ed0e69c8c5329c914a9f101295"
 dependencies = [
  "libc",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -5147,7 +5065,6 @@ dependencies = [
  "panic_unwind",
  "proc_macro",
  "std",
- "term 0.0.0",
 ]
 
 [[package]]
@@ -5205,7 +5122,7 @@ dependencies = [
 name = "tidy"
 version = "0.1.0"
 dependencies = [
- "cargo_metadata 0.11.1",
+ "cargo_metadata 0.12.0",
  "crossbeam-utils 0.8.3",
  "lazy_static",
  "regex",
@@ -5244,7 +5161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
 dependencies = [
  "libc",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -5255,49 +5172,44 @@ checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117"
 
 [[package]]
 name = "tokio"
-version = "0.2.24"
+version = "1.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "099837d3464c16a808060bb3f02263b412f6fafcb5d01c533d309985fbeebe48"
+checksum = "c2602b8af3767c285202012822834005f596c811042315fa7e9f5b12b2a43207"
 dependencies = [
+ "autocfg",
  "bytes",
- "futures-core",
- "iovec",
- "lazy_static",
  "libc",
  "memchr",
  "mio",
- "mio-named-pipes",
- "mio-uds",
  "num_cpus",
- "pin-project-lite 0.1.11",
+ "once_cell",
+ "pin-project-lite",
  "signal-hook-registry",
- "slab",
- "tokio-macros",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
-name = "tokio-macros"
-version = "0.2.6"
+name = "tokio-stream"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a"
+checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
 ]
 
 [[package]]
 name = "tokio-util"
-version = "0.3.1"
+version = "0.6.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
+checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592"
 dependencies = [
  "bytes",
  "futures-core",
  "futures-sink",
  "log",
- "pin-project-lite 0.1.11",
+ "pin-project-lite",
  "tokio",
 ]
 
@@ -5323,7 +5235,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f"
 dependencies = [
  "cfg-if 1.0.0",
- "pin-project-lite 0.2.4",
+ "pin-project-lite",
  "tracing-attributes",
  "tracing-core",
 ]
@@ -5464,9 +5376,9 @@ dependencies = [
 
 [[package]]
 name = "unicode-script"
-version = "0.5.2"
+version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79bf4d5fc96546fdb73f9827097810bbda93b11a6770ff3a54e1f445d4135787"
+checksum = "098ec66172ce21cd55f8bcc786ee209dd20e04eff70acfca30cb79924d173ae9"
 
 [[package]]
 name = "unicode-security"
@@ -5620,7 +5532,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
 dependencies = [
  "same-file",
- "winapi 0.3.9",
+ "winapi",
  "winapi-util",
 ]
 
@@ -5635,12 +5547,6 @@ dependencies = [
  "rustc-std-workspace-core",
 ]
 
-[[package]]
-name = "winapi"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
-
 [[package]]
 name = "winapi"
 version = "0.3.9"
@@ -5651,12 +5557,6 @@ dependencies = [
  "winapi-x86_64-pc-windows-gnu",
 ]
 
-[[package]]
-name = "winapi-build"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
-
 [[package]]
 name = "winapi-i686-pc-windows-gnu"
 version = "0.4.0"
@@ -5669,7 +5569,7 @@ version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -5678,16 +5578,6 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
-[[package]]
-name = "ws2_32-sys"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
-dependencies = [
- "winapi 0.2.8",
- "winapi-build",
-]
-
 [[package]]
 name = "xattr"
 version = "0.2.2"
@@ -5750,5 +5640,5 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
index 327afe35c2fb96b9107bbf5836c6d6e5ee8b8d44..dedfe45aca49bd807af07a9b573d245375e98bbd 100644 (file)
@@ -34,11 +34,13 @@ members = [
   "src/tools/unicode-table-generator",
   "src/tools/expand-yaml-anchors",
   "src/tools/jsondocck",
+  "src/tools/html-checker",
 ]
 
 exclude = [
   "build",
   "compiler/rustc_codegen_cranelift",
+  "src/test/rustdoc-gui",
   # HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`.
   "obj",
   # The `x` binary is a thin wrapper that calls `x.py`, which initializes
index af6a4090a27cb58c85b1ddd2adb6accdea2efa80..32fab9fc25de558febac046ab9b8f705e4fcd0d7 100644 (file)
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ Read ["Installation"] from [The Book].
 The Rust build system uses a Python script called `x.py` to build the compiler,
 which manages the bootstrapping process. It lives in the root of the project.
 
-The `x.py` command can be run directly on most systems in the following format: 
+The `x.py` command can be run directly on most systems in the following format:
 
 ```sh
 ./x.py <subcommand> [flags]
@@ -272,15 +272,14 @@ See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT), and
 
 ## Trademark
 
-The Rust programming language is an open source, community project governed
-by a core team. It is also sponsored by the Mozilla Foundation (“Mozilla”),
-which owns and protects the Rust and Cargo trademarks and logos
-(the “Rust Trademarks”).
+[The Rust Foundation][rust-foundation] owns and protects the Rust and Cargo
+trademarks and logos (the “Rust Trademarks”).
 
 If you want to use these names or brands, please read the [media guide][media-guide].
 
 Third-party logos may be subject to third-party copyrights and trademarks. See
 [Licenses][policies-licenses] for details.
 
+[rust-foundation]: https://foundation.rust-lang.org/
 [media-guide]: https://www.rust-lang.org/policies/media-guide
 [policies-licenses]: https://www.rust-lang.org/policies/licenses
index 36d6a5276f2274e2cde10961701e21f0a271f24c..046608ea8f0a486721520c4cfb52522a9c01a227 100644 (file)
+Version 1.55.0 (2021-09-09)
+============================
+
+Language
+--------
+- [You can now write open "from" range patterns (`X..`), which will start at `X` and
+  will end at the maximum value of the integer.][83918]
+- [You can now explicitly import the prelude of different editions
+  through `std::prelude` (e.g. `use std::prelude::rust_2021::*;`).][86294]
+
+Compiler
+--------
+- [Added tier 3\* support for `powerpc64le-unknown-freebsd`.][83572]
+
+\* Refer to Rust's [platform support page][platform-support-doc] for more
+   information on Rust's tiered platform support.
+
+Libraries
+---------
+
+- [Updated std's float parsing to use the Eisel-Lemire algorithm.][86761]
+  These improvements should in general provide faster string parsing of floats,
+  no longer reject certain valid floating point values, and reduce
+  the produced code size for non-stripped artifacts.
+- [`string::Drain` now implements `AsRef<str>` and `AsRef<[u8]>`.][86858]
+
+Stabilised APIs
+---------------
+
+- [`Bound::cloned`]
+- [`Drain::as_str`]
+- [`IntoInnerError::into_error`]
+- [`IntoInnerError::into_parts`]
+- [`MaybeUninit::assume_init_mut`]
+- [`MaybeUninit::assume_init_ref`]
+- [`MaybeUninit::write`]
+- [`array::map`]
+- [`ops::ControlFlow`]
+- [`x86::_bittest`]
+- [`x86::_bittestandcomplement`]
+- [`x86::_bittestandreset`]
+- [`x86::_bittestandset`]
+- [`x86_64::_bittest64`]
+- [`x86_64::_bittestandcomplement64`]
+- [`x86_64::_bittestandreset64`]
+- [`x86_64::_bittestandset64`]
+
+The following previously stable functions are now `const`.
+
+- [`str::from_utf8_unchecked`]
+- [`mem::transmute`]
+
+
+Cargo
+-----
+- [Cargo will now deduplicate compiler diagnostics to the terminal when invoking
+  rustc in parallel such as when using `cargo test`.][cargo/9675]
+- [The package definition in `cargo metadata` now includes the `"default_run"`
+  field from the manifest.][cargo/9550]
+- [Added `cargo d` as an alias for `cargo doc`.][cargo/9680]
+- [Added `{lib}` as formatting option for `cargo tree` to print the `"lib_name"`
+  of packages.][cargo/9663]
+
+Rustdoc
+-------
+- [Added "Go to item on exact match" search option.][85876]
+- [The "Implementors" section on traits no longer shows redundant
+  method definitions.][85970]
+- [Trait implementations are toggled open by default.][86260] This should make the
+  implementations more searchable by tools like `CTRL+F` in your browser.
+- [Intra-doc links should now correctly resolve associated items (e.g. methods)
+  through type aliases.][86334]
+- [Traits which are marked with `#[doc(hidden)]` will no longer appear in the
+  "Trait Implementations" section.][86513]
+
+
+Compatibility Notes
+-------------------
+- [std functions that return an `io::Error` will no longer use the
+  `ErrorKind::Other` variant.][85746] This is to better reflect that these
+  kinds of errors could be categorised [into newer more specific `ErrorKind`
+  variants][79965], and that they do not represent a user error.
+- [Using environment variable names with `process::Command` on Windows now
+  behaves as expected.][85270] Previously using envionment variables with
+  `Command` would cause them to be ASCII-uppercased.
+- [Rustdoc will now warn on using rustdoc lints that aren't prefixed
+  with `rustdoc::`][86849]
+
+[86849]: https://github.com/rust-lang/rust/pull/86849
+[86513]: https://github.com/rust-lang/rust/pull/86513
+[86334]: https://github.com/rust-lang/rust/pull/86334
+[86260]: https://github.com/rust-lang/rust/pull/86260
+[85970]: https://github.com/rust-lang/rust/pull/85970
+[85876]: https://github.com/rust-lang/rust/pull/85876
+[83572]: https://github.com/rust-lang/rust/pull/83572
+[86294]: https://github.com/rust-lang/rust/pull/86294
+[86858]: https://github.com/rust-lang/rust/pull/86858
+[86761]: https://github.com/rust-lang/rust/pull/86761
+[85769]: https://github.com/rust-lang/rust/pull/85769
+[85746]: https://github.com/rust-lang/rust/pull/85746
+[85305]: https://github.com/rust-lang/rust/pull/85305
+[85270]: https://github.com/rust-lang/rust/pull/85270
+[84111]: https://github.com/rust-lang/rust/pull/84111
+[83918]: https://github.com/rust-lang/rust/pull/83918
+[79965]: https://github.com/rust-lang/rust/pull/79965
+[87370]: https://github.com/rust-lang/rust/pull/87370
+[87298]: https://github.com/rust-lang/rust/pull/87298
+[cargo/9663]: https://github.com/rust-lang/cargo/pull/9663
+[cargo/9675]: https://github.com/rust-lang/cargo/pull/9675
+[cargo/9550]: https://github.com/rust-lang/cargo/pull/9550
+[cargo/9680]: https://github.com/rust-lang/cargo/pull/9680
+[cargo/9663]: https://github.com/rust-lang/cargo/pull/9663
+[`array::map`]: https://doc.rust-lang.org/stable/std/primitive.array.html#method.map
+[`Bound::cloned`]: https://doc.rust-lang.org/stable/std/ops/enum.Bound.html#method.cloned
+[`Drain::as_str`]: https://doc.rust-lang.org/stable/std/string/struct.Drain.html#method.as_str
+[`IntoInnerError::into_error`]: https://doc.rust-lang.org/stable/std/io/struct.IntoInnerError.html#method.into_error
+[`IntoInnerError::into_parts`]: https://doc.rust-lang.org/stable/std/io/struct.IntoInnerError.html#method.into_parts
+[`MaybeUninit::assume_init_mut`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_mut
+[`MaybeUninit::assume_init_ref`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_ref
+[`MaybeUninit::write`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.write
+[`Seek::rewind`]: https://doc.rust-lang.org/stable/std/io/trait.Seek.html#method.rewind
+[`mem::transmute`]: https://doc.rust-lang.org/stable/std/mem/fn.transmute.html
+[`ops::ControlFlow`]: https://doc.rust-lang.org/stable/std/ops/enum.ControlFlow.html
+[`str::from_utf8_unchecked`]: https://doc.rust-lang.org/stable/std/str/fn.from_utf8_unchecked.html
+[`x86::_bittest`]: https://doc.rust-lang.org/stable/core/arch/x86/fn._bittest.html
+[`x86::_bittestandcomplement`]: https://doc.rust-lang.org/stable/core/arch/x86/fn._bittestandcomplement.html
+[`x86::_bittestandreset`]: https://doc.rust-lang.org/stable/core/arch/x86/fn._bittestandreset.html
+[`x86::_bittestandset`]: https://doc.rust-lang.org/stable/core/arch/x86/fn._bittestandset.html
+[`x86_64::_bittest64`]: https://doc.rust-lang.org/stable/core/arch/x86_64/fn._bittest64.html
+[`x86_64::_bittestandcomplement64`]: https://doc.rust-lang.org/stable/core/arch/x86_64/fn._bittestandcomplement64.html
+[`x86_64::_bittestandreset64`]: https://doc.rust-lang.org/stable/core/arch/x86_64/fn._bittestandreset64.html
+[`x86_64::_bittestandset64`]: https://doc.rust-lang.org/stable/core/arch/x86_64/fn._bittestandset64.html
+
+
 Version 1.54.0 (2021-07-29)
 ============================
 
 Language
 -----------------------
 
-- [You can now use macros for values in built-in attribute macros.][83366]
-  While a seemingly minor addition on its own, this enables a lot of
-  powerful functionality when combined correctly. Most notably you can
-  now include external documentation in your crate by writing the following.
+- [You can now use macros for values in some built-in attributes.][83366]
+  This primarily allows you to call macros within the `#[doc]` attribute. For
+  example, to include external documentation in your crate, you can now write
+  the following:
   ```rust
   #![doc = include_str!("README.md")]
   ```
-  You can also use this to include auto-generated modules:
-  ```rust
-  #[path = concat!(env!("OUT_DIR"), "/generated.rs")]
-  mod generated;
-  ```
 
 - [You can now cast between unsized slice types (and types which contain
   unsized slices) in `const fn`.][85078]
@@ -37,6 +166,7 @@ Compiler
 - [Improved debugger output for enums on Windows MSVC platforms.][85292]
 - [Added tier 3\* support for `bpfel-unknown-none`
    and `bpfeb-unknown-none`.][79608]
+- [`-Zmutable-noalias=yes`][82834] is enabled by default when using LLVM 12 or above.
 
 \* Refer to Rust's [platform support page][platform-support-doc] for more
    information on Rust's tiered platform support.
@@ -106,6 +236,7 @@ Compatibility Notes
 [83366]: https://github.com/rust-lang/rust/pull/83366
 [83278]: https://github.com/rust-lang/rust/pull/83278
 [85292]: https://github.com/rust-lang/rust/pull/85292
+[82834]: https://github.com/rust-lang/rust/pull/82834
 [cargo/9520]: https://github.com/rust-lang/cargo/pull/9520
 [cargo/9499]: https://github.com/rust-lang/cargo/pull/9499
 [cargo/9488]: https://github.com/rust-lang/cargo/pull/9488
@@ -168,7 +299,7 @@ Libraries
 - [`leading_zeros`, and `trailing_zeros` are now available on all
   `NonZero` integer types.][84082]
 - [`{f32, f64}::from_str` now parse and print special values
-  (`NaN`, `-0`) according to IEEE RFC 754.][78618]
+  (`NaN`, `-0`) according to IEEE 754.][78618]
 - [You can now index into slices using `(Bound<usize>, Bound<usize>)`.][77704]
 - [Add the `BITS` associated constant to all numeric types.][82565]
 
index 63d925cce9ad7f6e22e55388ef772b127c57bba6..f8fac0c2358c9b2a4a19db01b93a9ad7bd8e1559 100644 (file)
@@ -552,7 +552,7 @@ fn fma() {
         assert!(f1.is_negative() && f1.is_zero());
     }
 
-    // Test x87 extended precision case from http://llvm.org/PR20728.
+    // Test x87 extended precision case from https://llvm.org/PR20728.
     {
         let mut m1 = X87DoubleExtended::from_u128(1).value;
         let m2 = X87DoubleExtended::from_u128(1).value;
@@ -1939,7 +1939,7 @@ fn add() {
         (m_smallest_normalized, m_smallest_normalized, "-0x1p-125", Status::OK, Category::Normal),
     ];
 
-    for &(x, y, e_result, e_status, e_category) in &special_cases[..] {
+    for (x, y, e_result, e_status, e_category) in special_cases {
         let status;
         let result = unpack!(status=, x + y);
         assert_eq!(status, e_status);
@@ -2262,7 +2262,7 @@ fn subtract() {
         (m_smallest_normalized, m_smallest_normalized, "0x0p+0", Status::OK, Category::Zero),
     ];
 
-    for &(x, y, e_result, e_status, e_category) in &special_cases[..] {
+    for (x, y, e_result, e_status, e_category) in special_cases {
         let status;
         let result = unpack!(status=, x - y);
         assert_eq!(status, e_status);
@@ -2538,7 +2538,7 @@ fn multiply() {
         (m_smallest_normalized, m_smallest_normalized, "0x0p+0", underflow_status, Category::Zero),
     ];
 
-    for &(x, y, e_result, e_status, e_category) in &special_cases[..] {
+    for (x, y, e_result, e_status, e_category) in special_cases {
         let status;
         let result = unpack!(status=, x * y);
         assert_eq!(status, e_status);
@@ -2814,7 +2814,7 @@ fn divide() {
         (m_smallest_normalized, m_smallest_normalized, "0x1p+0", Status::OK, Category::Normal),
     ];
 
-    for &(x, y, e_result, e_status, e_category) in &special_cases[..] {
+    for (x, y, e_result, e_status, e_category) in special_cases {
         let status;
         let result = unpack!(status=, x / y);
         assert_eq!(status, e_status);
index 5a8de71cb3490bc1fd73e6c9b912219d9ebcbdb1..c769d26543786a5ea39a637b4c512536b7c9f837 100644 (file)
@@ -64,7 +64,7 @@ fn ppc_double_double_add_special() {
         (0x7ff8000000000000, 0x3ff0000000000000, Category::NaN, Round::NearestTiesToEven),
     ];
 
-    for &(op1, op2, expected, round) in &data {
+    for (op1, op2, expected, round) in data {
         {
             let mut a1 = DoubleDouble::from_bits(op1);
             let a2 = DoubleDouble::from_bits(op2);
@@ -135,7 +135,7 @@ fn ppc_double_double_add() {
         ),
     ];
 
-    for &(op1, op2, expected, round) in &data {
+    for (op1, op2, expected, round) in data {
         {
             let mut a1 = DoubleDouble::from_bits(op1);
             let a2 = DoubleDouble::from_bits(op2);
@@ -172,7 +172,7 @@ fn ppc_double_double_subtract() {
         ),
     ];
 
-    for &(op1, op2, expected, round) in &data {
+    for (op1, op2, expected, round) in data {
         let mut a1 = DoubleDouble::from_bits(op1);
         let a2 = DoubleDouble::from_bits(op2);
         a1 = a1.sub_r(a2, round).value;
@@ -204,7 +204,7 @@ fn ppc_double_double_multiply_special() {
         (0, 0x3ff0000000000000, Category::Zero, Round::NearestTiesToEven),
     ];
 
-    for &(op1, op2, expected, round) in &data {
+    for (op1, op2, expected, round) in data {
         {
             let mut a1 = DoubleDouble::from_bits(op1);
             let a2 = DoubleDouble::from_bits(op2);
@@ -290,7 +290,7 @@ fn ppc_double_double_multiply() {
         ),
     ];
 
-    for &(op1, op2, expected, round) in &data {
+    for (op1, op2, expected, round) in data {
         {
             let mut a1 = DoubleDouble::from_bits(op1);
             let a2 = DoubleDouble::from_bits(op2);
@@ -322,7 +322,7 @@ fn ppc_double_double_divide() {
         ),
     ];
 
-    for &(op1, op2, expected, round) in &data {
+    for (op1, op2, expected, round) in data {
         let mut a1 = DoubleDouble::from_bits(op1);
         let a2 = DoubleDouble::from_bits(op2);
         a1 = a1.div_r(a2, round).value;
@@ -348,7 +348,7 @@ fn ppc_double_double_remainder() {
         ),
     ];
 
-    for &(op1, op2, expected) in &data {
+    for (op1, op2, expected) in data {
         let a1 = DoubleDouble::from_bits(op1);
         let a2 = DoubleDouble::from_bits(op2);
         let result = a1.ieee_rem(a2).value;
@@ -376,7 +376,7 @@ fn ppc_double_double_mod() {
         ),
     ];
 
-    for &(op1, op2, expected) in &data {
+    for (op1, op2, expected) in data {
         let a1 = DoubleDouble::from_bits(op1);
         let a2 = DoubleDouble::from_bits(op2);
         let r = (a1 % a2).value;
@@ -426,7 +426,7 @@ fn ppc_double_double_compare() {
         (0x7ff0000000000000, 0x7ff0000000000000, Some(Ordering::Equal)),
     ];
 
-    for &(op1, op2, expected) in &data {
+    for (op1, op2, expected) in data {
         let a1 = DoubleDouble::from_bits(op1);
         let a2 = DoubleDouble::from_bits(op2);
         assert_eq!(expected, a1.partial_cmp(&a2), "compare({:#x}, {:#x})", op1, op2,);
@@ -448,7 +448,7 @@ fn ppc_double_double_bitwise_eq() {
         (0x7ff0000000000000, 0x7ff0000000000000, true),
     ];
 
-    for &(op1, op2, expected) in &data {
+    for (op1, op2, expected) in data {
         let a1 = DoubleDouble::from_bits(op1);
         let a2 = DoubleDouble::from_bits(op2);
         assert_eq!(expected, a1.bitwise_eq(a2), "{:#x} = {:#x}", op1, op2);
index 93d7a597681339e3cfddea236667e67f4a371667..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]`.
@@ -1017,7 +1020,7 @@ pub struct Local {
 /// ```
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Arm {
-    pub attrs: Vec<Attribute>,
+    pub attrs: AttrVec,
     /// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`
     pub pat: P<Pat>,
     /// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }`
@@ -1935,6 +1938,7 @@ bitflags::bitflags! {
         const NORETURN = 1 << 4;
         const NOSTACK = 1 << 5;
         const ATT_SYNTAX = 1 << 6;
+        const RAW = 1 << 7;
     }
 }
 
@@ -2293,7 +2297,7 @@ pub struct EnumDef {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Variant {
     /// Attributes of the variant.
-    pub attrs: Vec<Attribute>,
+    pub attrs: AttrVec,
     /// Id of the variant (not the constructor, see `VariantData::ctor_id()`).
     pub id: NodeId,
     /// Span
@@ -2474,7 +2478,7 @@ impl VisibilityKind {
 /// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct FieldDef {
-    pub attrs: Vec<Attribute>,
+    pub attrs: AttrVec,
     pub id: NodeId,
     pub span: Span,
     pub vis: Visibility,
index 290f6006de0790f25cac9f7618e061f54a92e1a7..c0a837985fd62af0755fd64d73ecb9fdeccaf8cb 100644 (file)
@@ -1,3 +1,4 @@
+#[derive(Debug)]
 pub enum EntryPointType {
     None,
     MainNamed,
index cd27f958e4641868450fbd841313b0b006bc3176..1976e4ad3c9fc73e4fe06f704990a7bcebacff7c 100644 (file)
@@ -1,6 +1,6 @@
 use rustc_span::symbol::{sym, Symbol};
 
-#[derive(Clone, Copy)]
+#[derive(Clone, Debug, Copy, HashStable_Generic)]
 pub enum AllocatorKind {
     Global,
     Default,
index 7c79b4aab3cce78596397f1e56ed3f09c9d33966..3207aee6d2a97a3e21d06a7ecb6b4cd9621f90c7 100644 (file)
@@ -10,7 +10,6 @@
 )]
 #![feature(box_syntax)]
 #![feature(box_patterns)]
-#![cfg_attr(bootstrap, feature(const_fn_unsize))]
 #![feature(const_fn_transmute)]
 #![feature(crate_visibility_modifier)]
 #![feature(iter_zip)]
index 0b6099fd330dad615198553db46362b523bfe637..87950b44083efb8da969b4857759f4971e8b876d 100644 (file)
@@ -420,7 +420,7 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
 
 pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
     let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
-    visit_attrs(attrs, vis);
+    visit_thin_attrs(attrs, vis);
     vis.visit_id(id);
     vis.visit_pat(pat);
     visit_opt(guard, |guard| vis.visit_expr(guard));
@@ -504,7 +504,7 @@ pub fn noop_flat_map_variant<T: MutVisitor>(
     let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
     visitor.visit_ident(ident);
     visitor.visit_vis(vis);
-    visit_attrs(attrs, visitor);
+    visit_thin_attrs(attrs, visitor);
     visitor.visit_id(id);
     visitor.visit_variant_data(data);
     visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
@@ -918,7 +918,7 @@ pub fn noop_flat_map_field_def<T: MutVisitor>(
     visitor.visit_vis(vis);
     visitor.visit_id(id);
     visitor.visit_ty(ty);
-    visit_attrs(attrs, visitor);
+    visit_thin_attrs(attrs, visitor);
     smallvec![fd]
 }
 
@@ -1347,12 +1347,6 @@ pub fn noop_visit_expr<T: MutVisitor>(
         }
         ExprKind::Paren(expr) => {
             vis.visit_expr(expr);
-
-            // Nodes that are equal modulo `Paren` sugar no-ops should have the same IDs.
-            *id = expr.id;
-            vis.visit_span(span);
-            visit_thin_attrs(attrs, vis);
-            return;
         }
         ExprKind::Yield(expr) => {
             visit_opt(expr, |expr| vis.visit_expr(expr));
index d20bace6088826890e2ecfb23df75637ff2c209f..7f928cb5761808ff3079bdbfe999ee5ed18ff1a2 100644 (file)
@@ -1,4 +1,4 @@
-use rustc_span::ExpnId;
+use rustc_span::LocalExpnId;
 use std::fmt;
 
 rustc_index::newtype_index! {
@@ -24,12 +24,12 @@ pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0);
 pub const DUMMY_NODE_ID: NodeId = NodeId::MAX;
 
 impl NodeId {
-    pub fn placeholder_from_expn_id(expn_id: ExpnId) -> Self {
+    pub fn placeholder_from_expn_id(expn_id: LocalExpnId) -> Self {
         NodeId::from_u32(expn_id.as_u32())
     }
 
-    pub fn placeholder_to_expn_id(self) -> ExpnId {
-        ExpnId::from_u32(self.as_u32())
+    pub fn placeholder_to_expn_id(self) -> LocalExpnId {
+        LocalExpnId::from_u32(self.as_u32())
     }
 }
 
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..7fecf537cfbd3fc077008e6a2bc5ff4c38fde740 100644 (file)
@@ -1067,6 +1067,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
         eq_sign_span: Span,
         assignments: &mut Vec<hir::Stmt<'hir>>,
     ) -> &'hir hir::Pat<'hir> {
+        self.arena.alloc(self.destructure_assign_mut(lhs, eq_sign_span, assignments))
+    }
+
+    fn destructure_assign_mut(
+        &mut self,
+        lhs: &Expr,
+        eq_sign_span: Span,
+        assignments: &mut Vec<hir::Stmt<'hir>>,
+    ) -> hir::Pat<'hir> {
         match &lhs.kind {
             // Underscore pattern.
             ExprKind::Underscore => {
@@ -1080,7 +1089,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let (before, after) = pats.split_at(i);
                     hir::PatKind::Slice(
                         before,
-                        Some(self.pat_without_dbm(span, hir::PatKind::Wild)),
+                        Some(self.arena.alloc(self.pat_without_dbm(span, hir::PatKind::Wild))),
                         after,
                     )
                 } else {
@@ -1165,14 +1174,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let tuple_pat = hir::PatKind::Tuple(&[], Some(0));
                     return self.pat_without_dbm(lhs.span, tuple_pat);
                 } else {
-                    return self.destructure_assign(e, eq_sign_span, assignments);
+                    return self.destructure_assign_mut(e, eq_sign_span, assignments);
                 }
             }
             _ => {}
         }
         // Treat all other cases as normal lvalue.
         let ident = Ident::new(sym::lhs, lhs.span);
-        let (pat, binding) = self.pat_ident(lhs.span, ident);
+        let (pat, binding) = self.pat_ident_mut(lhs.span, ident);
         let ident = self.expr_ident(lhs.span, ident, binding);
         let assign = hir::ExprKind::Assign(self.lower_expr(lhs), ident, eq_sign_span);
         let expr = self.expr(lhs.span, assign, ThinVec::new());
@@ -1191,7 +1200,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         ctx: &str,
         eq_sign_span: Span,
         assignments: &mut Vec<hir::Stmt<'hir>>,
-    ) -> (&'hir [&'hir hir::Pat<'hir>], Option<(usize, Span)>) {
+    ) -> (&'hir [hir::Pat<'hir>], Option<(usize, Span)>) {
         let mut rest = None;
         let elements =
             self.arena.alloc_from_iter(elements.iter().enumerate().filter_map(|(i, e)| {
@@ -1204,7 +1213,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     }
                     None
                 } else {
-                    Some(self.destructure_assign(e, eq_sign_span, assignments))
+                    Some(self.destructure_assign_mut(e, eq_sign_span, assignments))
                 }
             }));
         (elements, rest)
@@ -1559,13 +1568,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     /// 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 292643d6d7510821cdbf653455290170dda6bd86..880692516e9ef3b5c327a8d4d2811d41ed24b619 100644 (file)
@@ -343,9 +343,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 // opaque type Foo1: Trait
                 let ty = self.lower_ty(
                     ty,
-                    ImplTraitContext::OtherOpaqueTy {
+                    ImplTraitContext::TypeAliasesOpaqueTy {
                         capturable_lifetimes: &mut FxHashSet::default(),
-                        origin: hir::OpaqueTyOrigin::TyAlias,
                     },
                 );
                 let generics = self.lower_generics(gen, ImplTraitContext::disallowed());
@@ -484,17 +483,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         span: Span,
         body: Option<&Expr>,
     ) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
-        let mut capturable_lifetimes;
-        let itctx = if self.sess.features_untracked().impl_trait_in_bindings {
-            capturable_lifetimes = FxHashSet::default();
-            ImplTraitContext::OtherOpaqueTy {
-                capturable_lifetimes: &mut capturable_lifetimes,
-                origin: hir::OpaqueTyOrigin::Misc,
-            }
-        } else {
-            ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
-        };
-        let ty = self.lower_ty(ty, itctx);
+        let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Binding));
         (ty, self.lower_const_body(span, body))
     }
 
@@ -926,9 +915,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     Some(ty) => {
                         let ty = self.lower_ty(
                             ty,
-                            ImplTraitContext::OtherOpaqueTy {
+                            ImplTraitContext::TypeAliasesOpaqueTy {
                                 capturable_lifetimes: &mut FxHashSet::default(),
-                                origin: hir::OpaqueTyOrigin::TyAlias,
                             },
                         );
                         hir::ImplItemKind::TyAlias(ty)
@@ -1385,50 +1373,34 @@ impl<'hir> LoweringContext<'_, 'hir> {
         itctx: ImplTraitContext<'_, 'hir>,
     ) -> GenericsCtor<'hir> {
         // Collect `?Trait` bounds in where clause and move them to parameter definitions.
-        // FIXME: this could probably be done with less rightward drift. It also looks like two
-        // control paths where `report_error` is called are the only paths that advance to after the
-        // match statement, so the error reporting could probably just be moved there.
         let mut add_bounds: NodeMap<Vec<_>> = Default::default();
         for pred in &generics.where_clause.predicates {
             if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
                 'next_bound: for bound in &bound_pred.bounds {
                     if let GenericBound::Trait(_, TraitBoundModifier::Maybe) = *bound {
-                        let report_error = |this: &mut Self| {
-                            this.diagnostic().span_err(
-                                bound_pred.bounded_ty.span,
-                                "`?Trait` bounds are only permitted at the \
-                                 point where a type parameter is declared",
-                            );
-                        };
                         // Check if the where clause type is a plain type parameter.
-                        match bound_pred.bounded_ty.kind {
-                            TyKind::Path(None, ref path)
-                                if path.segments.len() == 1
-                                    && bound_pred.bound_generic_params.is_empty() =>
+                        match self
+                            .resolver
+                            .get_partial_res(bound_pred.bounded_ty.id)
+                            .map(|d| (d.base_res(), d.unresolved_segments()))
+                        {
+                            Some((Res::Def(DefKind::TyParam, def_id), 0))
+                                if bound_pred.bound_generic_params.is_empty() =>
                             {
-                                if let Some(Res::Def(DefKind::TyParam, def_id)) = self
-                                    .resolver
-                                    .get_partial_res(bound_pred.bounded_ty.id)
-                                    .map(|d| d.base_res())
-                                {
-                                    if let Some(def_id) = def_id.as_local() {
-                                        for param in &generics.params {
-                                            if let GenericParamKind::Type { .. } = param.kind {
-                                                if def_id == self.resolver.local_def_id(param.id) {
-                                                    add_bounds
-                                                        .entry(param.id)
-                                                        .or_default()
-                                                        .push(bound.clone());
-                                                    continue 'next_bound;
-                                                }
-                                            }
-                                        }
+                                for param in &generics.params {
+                                    if def_id == self.resolver.local_def_id(param.id).to_def_id() {
+                                        add_bounds.entry(param.id).or_default().push(bound.clone());
+                                        continue 'next_bound;
                                     }
                                 }
-                                report_error(self)
                             }
-                            _ => report_error(self),
+                            _ => {}
                         }
+                        self.diagnostic().span_err(
+                            bound_pred.bounded_ty.span,
+                            "`?Trait` bounds are only permitted at the \
+                                 point where a type parameter is declared",
+                        );
                     }
                 }
             }
index 0ff1efd8165eae60cc5d294a41e4f95dee9a82ec..d4caba924160088c892f4e487b172ef809bd3a51 100644 (file)
@@ -48,7 +48,7 @@ use rustc_data_structures::sync::Lrc;
 use rustc_errors::{struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
-use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, CRATE_DEF_ID};
+use rustc_hir::def_id::{DefId, DefIdMap, DefPathHash, LocalDefId, CRATE_DEF_ID};
 use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
 use rustc_hir::intravisit;
 use rustc_hir::{ConstArg, GenericArg, ParamName};
@@ -59,7 +59,7 @@ use rustc_session::utils::{FlattenNonterminals, NtToTokenstream};
 use rustc_session::Session;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::ExpnId;
-use rustc_span::source_map::{respan, DesugaringKind};
+use rustc_span::source_map::{respan, CachingSourceMapView, DesugaringKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
@@ -204,6 +204,8 @@ pub trait ResolverAstLowering {
 
     fn local_def_id(&self, node: NodeId) -> LocalDefId;
 
+    fn def_path_hash(&self, def_id: DefId) -> DefPathHash;
+
     fn create_def(
         &mut self,
         parent: LocalDefId,
@@ -214,6 +216,32 @@ pub trait ResolverAstLowering {
     ) -> LocalDefId;
 }
 
+struct LoweringHasher<'a> {
+    source_map: CachingSourceMapView<'a>,
+    resolver: &'a dyn ResolverAstLowering,
+}
+
+impl<'a> rustc_span::HashStableContext for LoweringHasher<'a> {
+    #[inline]
+    fn hash_spans(&self) -> bool {
+        true
+    }
+
+    #[inline]
+    fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
+        self.resolver.def_path_hash(def_id)
+    }
+
+    #[inline]
+    fn span_data_to_lines_and_cols(
+        &mut self,
+        span: &rustc_span::SpanData,
+    ) -> Option<(Lrc<rustc_span::SourceFile>, usize, rustc_span::BytePos, usize, rustc_span::BytePos)>
+    {
+        self.source_map.span_data_to_lines_and_cols(span)
+    }
+}
+
 /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
 /// and if so, what meaning it has.
 #[derive(Debug)]
@@ -236,8 +264,8 @@ enum ImplTraitContext<'b, 'a> {
         /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
         origin: hir::OpaqueTyOrigin,
     },
-    /// Impl trait in type aliases, consts and statics.
-    OtherOpaqueTy {
+    /// Impl trait in type aliases.
+    TypeAliasesOpaqueTy {
         /// Set of lifetimes that this opaque type can capture, if it uses
         /// them. This includes lifetimes bound since we entered this context.
         /// For example:
@@ -252,8 +280,6 @@ enum ImplTraitContext<'b, 'a> {
         // FIXME(impl_trait): but `required_region_bounds` will ICE later
         // anyway.
         capturable_lifetimes: &'b mut FxHashSet<hir::LifetimeName>,
-        /// Origin: Either OpaqueTyOrigin::Misc or OpaqueTyOrigin::Binding,
-        origin: hir::OpaqueTyOrigin,
     },
     /// `impl Trait` is not accepted in this position.
     Disallowed(ImplTraitPosition),
@@ -282,8 +308,8 @@ impl<'a> ImplTraitContext<'_, 'a> {
             ReturnPositionOpaqueTy { fn_def_id, origin } => {
                 ReturnPositionOpaqueTy { fn_def_id: *fn_def_id, origin: *origin }
             }
-            OtherOpaqueTy { capturable_lifetimes, origin } => {
-                OtherOpaqueTy { capturable_lifetimes, origin: *origin }
+            TypeAliasesOpaqueTy { capturable_lifetimes } => {
+                TypeAliasesOpaqueTy { capturable_lifetimes }
             }
             Disallowed(pos) => Disallowed(*pos),
         }
@@ -296,7 +322,7 @@ pub fn lower_crate<'a, 'hir>(
     resolver: &'a mut dyn ResolverAstLowering,
     nt_to_tokenstream: NtToTokenstream,
     arena: &'hir Arena<'hir>,
-) -> hir::Crate<'hir> {
+) -> &'hir hir::Crate<'hir> {
     let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering");
 
     LoweringContext {
@@ -331,7 +357,7 @@ pub fn lower_crate<'a, 'hir>(
         lifetimes_to_define: Vec::new(),
         is_collecting_in_band_lifetimes: false,
         in_scope_lifetimes: Vec::new(),
-        allow_try_trait: Some([sym::control_flow_enum, sym::try_trait_v2][..].into()),
+        allow_try_trait: Some([sym::try_trait_v2][..].into()),
         allow_gen_future: Some([sym::gen_future][..].into()),
     }
     .lower_crate(krate)
@@ -403,7 +429,7 @@ enum AnonymousLifetimeMode {
 }
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
-    fn lower_crate(mut self, c: &Crate) -> hir::Crate<'hir> {
+    fn lower_crate(mut self, c: &Crate) -> &'hir hir::Crate<'hir> {
         /// Full-crate AST visitor that inserts into a fresh
         /// `LoweringContext` any information that may be
         /// needed from arbitrary locations in the crate,
@@ -417,7 +443,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree) {
                 match tree.kind {
                     UseTreeKind::Simple(_, id1, id2) => {
-                        for &id in &[id1, id2] {
+                        for id in [id1, id2] {
                             self.lctx.allocate_hir_id_counter(id);
                         }
                     }
@@ -530,7 +556,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             }
         }
 
-        hir::Crate {
+        let krate = hir::Crate {
             item: module,
             exported_macros: self.arena.alloc_from_iter(self.exported_macros),
             non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs),
@@ -545,7 +571,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             proc_macros,
             trait_map,
             attrs: self.attrs,
-        }
+        };
+        self.arena.alloc(krate)
     }
 
     fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId {
@@ -564,6 +591,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         lowered
     }
 
+    fn create_stable_hashing_context(&self) -> LoweringHasher<'_> {
+        LoweringHasher {
+            source_map: CachingSourceMapView::new(self.sess.source_map()),
+            resolver: self.resolver,
+        }
+    }
+
     fn lower_node_id_generic(
         &mut self,
         ast_node_id: NodeId,
@@ -683,7 +717,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         span: Span,
         allow_internal_unstable: Option<Lrc<[Symbol]>>,
     ) -> Span {
-        span.mark_with_reason(allow_internal_unstable, reason, self.sess.edition())
+        span.mark_with_reason(
+            allow_internal_unstable,
+            reason,
+            self.sess.edition(),
+            self.create_stable_hashing_context(),
+        )
     }
 
     fn with_anonymous_lifetime_mode<R>(
@@ -1085,7 +1124,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     //
                     //     fn foo() -> impl Iterator<Item = impl Debug>
                     ImplTraitContext::ReturnPositionOpaqueTy { .. }
-                    | ImplTraitContext::OtherOpaqueTy { .. } => (true, itctx),
+                    | ImplTraitContext::TypeAliasesOpaqueTy { .. } => (true, itctx),
 
                     // We are in the argument position, but within a dyn type:
                     //
@@ -1109,9 +1148,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         capturable_lifetimes = FxHashSet::default();
                         (
                             true,
-                            ImplTraitContext::OtherOpaqueTy {
+                            ImplTraitContext::TypeAliasesOpaqueTy {
                                 capturable_lifetimes: &mut capturable_lifetimes,
-                                origin: hir::OpaqueTyOrigin::Misc,
                             },
                         )
                     }
@@ -1375,18 +1413,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             None,
                             |this| this.lower_param_bounds(bounds, itctx),
                         ),
-                    ImplTraitContext::OtherOpaqueTy { ref capturable_lifetimes, origin } => {
+                    ImplTraitContext::TypeAliasesOpaqueTy { ref capturable_lifetimes } => {
                         // Reset capturable lifetimes, any nested impl trait
                         // types will inherit lifetimes from this opaque type,
                         // so don't need to capture them again.
-                        let nested_itctx = ImplTraitContext::OtherOpaqueTy {
+                        let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy {
                             capturable_lifetimes: &mut FxHashSet::default(),
-                            origin,
                         };
                         self.lower_opaque_impl_trait(
                             span,
                             None,
-                            origin,
+                            hir::OpaqueTyOrigin::TyAlias,
                             def_node_id,
                             Some(capturable_lifetimes),
                             |this| this.lower_param_bounds(bounds, nested_itctx),
@@ -1423,25 +1460,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             }),
                         ))
                     }
-                    ImplTraitContext::Disallowed(pos) => {
-                        let allowed_in = if self.sess.features_untracked().impl_trait_in_bindings {
-                            "bindings or function and inherent method return types"
-                        } else {
-                            "function and inherent method return types"
-                        };
+                    ImplTraitContext::Disallowed(_) => {
                         let mut err = struct_span_err!(
                             self.sess,
                             t.span,
                             E0562,
                             "`impl Trait` not allowed outside of {}",
-                            allowed_in,
+                            "function and method return types",
                         );
-                        if pos == ImplTraitPosition::Binding && self.sess.is_nightly_build() {
-                            err.help(
-                                "add `#![feature(impl_trait_in_bindings)]` to the crate \
-                                   attributes to enable",
-                            );
-                        }
                         err.emit();
                         hir::TyKind::Err
                     }
@@ -1726,21 +1752,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     fn lower_local(&mut self, l: &Local) -> hir::Local<'hir> {
-        let ty = l.ty.as_ref().map(|t| {
-            let mut capturable_lifetimes;
-            self.lower_ty(
-                t,
-                if self.sess.features_untracked().impl_trait_in_bindings {
-                    capturable_lifetimes = FxHashSet::default();
-                    ImplTraitContext::OtherOpaqueTy {
-                        capturable_lifetimes: &mut capturable_lifetimes,
-                        origin: hir::OpaqueTyOrigin::Binding,
-                    }
-                } else {
-                    ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
-                },
-            )
-        });
+        let ty = l
+            .ty
+            .as_ref()
+            .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Binding)));
         let init = l.init.as_ref().map(|e| self.lower_expr(e));
         let hir_id = self.lower_node_id(l.id);
         self.lower_attrs(hir_id, &l.attrs);
@@ -2291,13 +2306,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 )),
                 _ => None,
             });
-            if let ImplTraitContext::OtherOpaqueTy { ref mut capturable_lifetimes, .. } = itctx {
+            if let ImplTraitContext::TypeAliasesOpaqueTy { ref mut capturable_lifetimes, .. } =
+                itctx
+            {
                 capturable_lifetimes.extend(lt_def_names.clone());
             }
 
             let res = this.lower_trait_ref(&p.trait_ref, itctx.reborrow());
 
-            if let ImplTraitContext::OtherOpaqueTy { ref mut capturable_lifetimes, .. } = itctx {
+            if let ImplTraitContext::TypeAliasesOpaqueTy { ref mut capturable_lifetimes, .. } =
+                itctx
+            {
                 for param in lt_def_names {
                     capturable_lifetimes.remove(&param);
                 }
@@ -2536,21 +2555,35 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::Unannotated)
     }
 
+    fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, hir::HirId) {
+        self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::Unannotated)
+    }
+
     fn pat_ident_binding_mode(
         &mut self,
         span: Span,
         ident: Ident,
         bm: hir::BindingAnnotation,
     ) -> (&'hir hir::Pat<'hir>, hir::HirId) {
+        let (pat, hir_id) = self.pat_ident_binding_mode_mut(span, ident, bm);
+        (self.arena.alloc(pat), hir_id)
+    }
+
+    fn pat_ident_binding_mode_mut(
+        &mut self,
+        span: Span,
+        ident: Ident,
+        bm: hir::BindingAnnotation,
+    ) -> (hir::Pat<'hir>, hir::HirId) {
         let hir_id = self.next_id();
 
         (
-            self.arena.alloc(hir::Pat {
+            hir::Pat {
                 hir_id,
                 kind: hir::PatKind::Binding(bm, hir_id, ident.with_span_pos(span), None),
                 span,
                 default_binding_modes: true,
-            }),
+            },
             hir_id,
         )
     }
@@ -2568,13 +2601,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         })
     }
 
-    fn pat_without_dbm(&mut self, span: Span, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
-        self.arena.alloc(hir::Pat {
-            hir_id: self.next_id(),
-            kind,
-            span,
-            default_binding_modes: false,
-        })
+    fn pat_without_dbm(&mut self, span: Span, kind: hir::PatKind<'hir>) -> hir::Pat<'hir> {
+        hir::Pat { hir_id: self.next_id(), kind, span, default_binding_modes: false }
     }
 
     fn ty_path(
index 66e623528f3bd179a189e75414ae59fc0b063f6e..d81ddd2c082e7af2bc08a3aeb96a7b7f2e458b12 100644 (file)
@@ -10,7 +10,11 @@ use rustc_span::symbol::Ident;
 use rustc_span::{source_map::Spanned, Span};
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
-    crate fn lower_pat(&mut self, mut pattern: &Pat) -> &'hir hir::Pat<'hir> {
+    crate fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> {
+        self.arena.alloc(self.lower_pat_mut(pattern))
+    }
+
+    crate fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> {
         ensure_sufficient_stack(|| {
             // loop here to avoid recursion
             let node = loop {
@@ -34,7 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     }
                     PatKind::Or(ref pats) => {
                         break hir::PatKind::Or(
-                            self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat(x))),
+                            self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat_mut(x))),
                         );
                     }
                     PatKind::Path(ref qself, ref path) => {
@@ -101,7 +105,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         &mut self,
         pats: &[P<Pat>],
         ctx: &str,
-    ) -> (&'hir [&'hir hir::Pat<'hir>], Option<usize>) {
+    ) -> (&'hir [hir::Pat<'hir>], Option<usize>) {
         let mut elems = Vec::with_capacity(pats.len());
         let mut rest = None;
 
@@ -140,7 +144,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             }
 
             // It was not a sub-tuple pattern so lower it normally.
-            elems.push(self.lower_pat(pat));
+            elems.push(self.lower_pat_mut(pat));
         }
 
         for (_, pat) in iter {
@@ -149,7 +153,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 // ...but there was one again, so error.
                 self.ban_extra_rest_pat(pat.span, rest.unwrap().1, ctx);
             } else {
-                elems.push(self.lower_pat(pat));
+                elems.push(self.lower_pat_mut(pat));
             }
         }
 
@@ -189,11 +193,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 // Record, lower it to `$binding_mode $ident @ _`, and stop here.
                 PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
                     prev_rest_span = Some(sub.span);
-                    slice = Some(lower_rest_sub(self, pat, bm, ident, sub));
+                    slice = Some(self.arena.alloc(lower_rest_sub(self, pat, bm, ident, sub)));
                     break;
                 }
                 // It was not a subslice pattern so lower it normally.
-                _ => before.push(self.lower_pat(pat)),
+                _ => before.push(self.lower_pat_mut(pat)),
             }
         }
 
@@ -214,7 +218,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 self.ban_extra_rest_pat(rest_span, prev_rest_span.unwrap(), "slice");
             } else {
                 // Lower the pattern normally.
-                after.push(self.lower_pat(pat));
+                after.push(self.lower_pat_mut(pat));
             }
         }
 
@@ -268,17 +272,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
-        self.pat_with_node_id_of(p, hir::PatKind::Wild)
+        self.arena.alloc(self.pat_with_node_id_of(p, hir::PatKind::Wild))
     }
 
     /// Construct a `Pat` with the `HirId` of `p.id` lowered.
-    fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
-        self.arena.alloc(hir::Pat {
+    fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> hir::Pat<'hir> {
+        hir::Pat {
             hir_id: self.lower_node_id(p.id),
             kind,
             span: p.span,
             default_binding_modes: true,
-        })
+        }
     }
 
     /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
index fe9f1fb20f05608fe21bc43ffe957ee80a52d6ea..55173c6f8696e419545ef1e8c9a6d8f2157db138 100644 (file)
@@ -336,6 +336,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             insertion_sp,
                             suggestion,
                         );
+                        err.note("assuming a `'static` lifetime...");
                         err.emit();
                     }
                     AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => {
index 30aa51a121a80edfb2e45d05f680dfb98b750a3f..acc41d9f6443cf66a46fadbd897274d71d5e4608 100644 (file)
@@ -652,7 +652,7 @@ impl<'a> AstValidator<'a> {
                 self.err_handler()
                     .struct_span_err(
                         *span,
-                        "only foreign or `unsafe extern \"C\" functions may be C-variadic",
+                        "only foreign or `unsafe extern \"C\"` functions may be C-variadic",
                     )
                     .emit();
             }
@@ -889,35 +889,32 @@ fn validate_generic_param_order(
 ) {
     let mut max_param: Option<ParamKindOrd> = None;
     let mut out_of_order = FxHashMap::default();
-    let mut param_idents = vec![];
+    let mut param_idents = Vec::with_capacity(generics.len());
 
-    for param in generics {
-        let ident = Some(param.ident.to_string());
-        let (kind, bounds, span) = (&param.kind, Some(&*param.bounds), param.ident.span);
+    for (idx, param) in generics.iter().enumerate() {
+        let ident = param.ident;
+        let (kind, bounds, span) = (&param.kind, &param.bounds, ident.span);
         let (ord_kind, ident) = match &param.kind {
-            GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident),
-            GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
+            GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident.to_string()),
+            GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident.to_string()),
             GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
                 let ty = pprust::ty_to_string(ty);
                 let unordered = sess.features_untracked().unordered_const_ty_params();
-                (ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty)))
+                (ParamKindOrd::Const { unordered }, format!("const {}: {}", ident, ty))
             }
         };
-        if let Some(ident) = ident {
-            param_idents.push((kind, ord_kind, bounds, param_idents.len(), ident));
-        }
-        let max_param = &mut max_param;
+        param_idents.push((kind, ord_kind, bounds, idx, ident));
         match max_param {
-            Some(max_param) if *max_param > ord_kind => {
-                let entry = out_of_order.entry(ord_kind).or_insert((*max_param, vec![]));
+            Some(max_param) if max_param > ord_kind => {
+                let entry = out_of_order.entry(ord_kind).or_insert((max_param, vec![]));
                 entry.1.push(span);
             }
-            Some(_) | None => *max_param = Some(ord_kind),
+            Some(_) | None => max_param = Some(ord_kind),
         };
     }
 
-    let mut ordered_params = "<".to_string();
     if !out_of_order.is_empty() {
+        let mut ordered_params = "<".to_string();
         param_idents.sort_by_key(|&(_, po, _, i, _)| (po, i));
         let mut first = true;
         for (kind, _, bounds, _, ident) in param_idents {
@@ -925,12 +922,12 @@ fn validate_generic_param_order(
                 ordered_params += ", ";
             }
             ordered_params += &ident;
-            if let Some(bounds) = bounds {
-                if !bounds.is_empty() {
-                    ordered_params += ": ";
-                    ordered_params += &pprust::bounds_to_string(&bounds);
-                }
+
+            if !bounds.is_empty() {
+                ordered_params += ": ";
+                ordered_params += &pprust::bounds_to_string(&bounds);
             }
+
             match kind {
                 GenericParamKind::Type { default: Some(default) } => {
                     ordered_params += " = ";
@@ -946,32 +943,32 @@ fn validate_generic_param_order(
             }
             first = false;
         }
-    }
-    ordered_params += ">";
 
-    for (param_ord, (max_param, spans)) in &out_of_order {
-        let mut err =
-            handler.struct_span_err(
+        ordered_params += ">";
+
+        for (param_ord, (max_param, spans)) in &out_of_order {
+            let mut err = handler.struct_span_err(
                 spans.clone(),
                 &format!(
                     "{} parameters must be declared prior to {} parameters",
                     param_ord, max_param,
                 ),
             );
-        err.span_suggestion(
-            span,
-            &format!(
-                "reorder the parameters: lifetimes, {}",
-                if sess.features_untracked().unordered_const_ty_params() {
-                    "then consts and types"
-                } else {
-                    "then types, then consts"
-                }
-            ),
-            ordered_params.clone(),
-            Applicability::MachineApplicable,
-        );
-        err.emit();
+            err.span_suggestion(
+                span,
+                &format!(
+                    "reorder the parameters: lifetimes, {}",
+                    if sess.features_untracked().unordered_const_ty_params() {
+                        "then consts and types"
+                    } else {
+                        "then types, then consts"
+                    }
+                ),
+                ordered_params.clone(),
+                Applicability::MachineApplicable,
+            );
+            err.emit();
+        }
     }
 }
 
index 3f98944d850e7991f01393e0062da1984dcb0441..3e757e3843e38425d4d2b163b17ed13cbff31e6e 100644 (file)
@@ -565,6 +565,22 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
 
     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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                     "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 3d2785faad65e44949b160df29ab7d39b401fef9..8b7b306a54dd2bd3c003486ac15a1ec6e905e3b5 100644 (file)
@@ -136,11 +136,11 @@ pub fn print_crate<'a>(
     s.s.eof()
 }
 
-// This makes printed token streams look slightly nicer,
-// and also addresses some specific regressions described in #63896 and #73345.
+/// This makes printed token streams look slightly nicer,
+/// and also addresses some specific regressions described in #63896 and #73345.
 fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool {
     if let TokenTree::Token(token) = prev {
-        if matches!(token.kind, token::Dot) {
+        if matches!(token.kind, token::Dot | token::Dollar) {
             return false;
         }
         if let token::DocComment(comment_kind, ..) = token.kind {
@@ -1954,7 +1954,6 @@ impl<'a> State<'a> {
                     self.word_space(":");
                 }
                 self.head("loop");
-                self.s.space();
                 self.print_block_with_attrs(blk, attrs);
             }
             ast::ExprKind::Match(ref expr, ref arms) => {
@@ -2284,6 +2283,9 @@ impl<'a> State<'a> {
                 if opts.contains(InlineAsmOptions::ATT_SYNTAX) {
                     options.push("att_syntax");
                 }
+                if opts.contains(InlineAsmOptions::RAW) {
+                    options.push("raw");
+                }
                 s.commasep(Inconsistent, &options, |s, &opt| {
                     s.word(opt);
                 });
index b1a73a0bf02778ee001e706fec743a92834d91b6..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 {
@@ -49,7 +49,7 @@ fn test_variant_to_string() {
                 kind: ast::VisibilityKind::Inherited,
                 tokens: None,
             },
-            attrs: Vec::new(),
+            attrs: ast::AttrVec::new(),
             id: ast::DUMMY_NODE_ID,
             data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
             disr_expr: None,
index e58b266fdb9e19d970bd694b998ce8ae96526892..b7b053cd5ddb7a910f24f795abb0ddac2ecb1044 100644 (file)
@@ -862,18 +862,6 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
         if let Some(items) = attr.meta_item_list() {
             sess.mark_attr_used(attr);
             for item in items {
-                if !item.is_meta_item() {
-                    handle_errors(
-                        &sess.parse_sess,
-                        item.span(),
-                        AttrError::UnsupportedLiteral(
-                            "meta item in `repr` must be an identifier",
-                            false,
-                        ),
-                    );
-                    continue;
-                }
-
                 let mut recognised = false;
                 if item.is_word() {
                     let hint = match item.name_or_empty() {
@@ -882,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),
                     };
 
@@ -890,23 +895,6 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                         acc.push(h);
                     }
                 } else if let Some((name, value)) = item.name_value_literal() {
-                    let parse_alignment = |node: &ast::LitKind| -> Result<u32, &'static str> {
-                        if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
-                            if literal.is_power_of_two() {
-                                // rustc_middle::ty::layout::Align restricts align to <= 2^29
-                                if *literal <= 1 << 29 {
-                                    Ok(*literal as u32)
-                                } else {
-                                    Err("larger than 2^29")
-                                }
-                            } else {
-                                Err("not a power of two")
-                            }
-                        } else {
-                            Err("not an unsuffixed integer")
-                        }
-                    };
-
                     let mut literal_error = None;
                     if name == sym::align {
                         recognised = true;
@@ -920,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,
                                     );
                                 }
@@ -954,25 +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
-                    struct_span_err!(
-                        diagnostic,
-                        item.span(),
-                        E0552,
-                        "unrecognized representation hint"
-                    )
-                    .emit();
+                    // 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");
+                    }
                 }
             }
         }
@@ -1080,3 +1133,16 @@ fn allow_unstable<'a>(
         name
     })
 }
+
+pub fn parse_alignment(node: &ast::LitKind) -> Result<u32, &'static str> {
+    if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
+        if literal.is_power_of_two() {
+            // rustc_middle::ty::layout::Align restricts align to <= 2^29
+            if *literal <= 1 << 29 { Ok(*literal as u32) } else { Err("larger than 2^29") }
+        } else {
+            Err("not a power of two")
+        }
+    } else {
+        Err("not an unsuffixed integer")
+    }
+}
index b28c6f0d99c5e0ebb5ac2d5708d4663f5a235144..ff13f0d4e42079ee7d784a9f0f2517333ed86c10 100644 (file)
@@ -356,6 +356,8 @@ fn parse_options<'a>(
             try_set_option(p, args, sym::nostack, ast::InlineAsmOptions::NOSTACK);
         } else if p.eat_keyword(sym::att_syntax) {
             try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX);
+        } else if p.eat_keyword(kw::Raw) {
+            try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::RAW);
         } else {
             return p.unexpected();
         }
@@ -453,7 +455,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
                 ecx.parse_sess().buffer_lint(
                     lint::builtin::BAD_ASM_STYLE,
                     find_span(".intel_syntax"),
-                    ecx.resolver.lint_node_id(ecx.current_expansion.id),
+                    ecx.current_expansion.lint_node_id,
                     "avoid using `.intel_syntax`, Intel syntax is the default",
                 );
             }
@@ -461,12 +463,20 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
                 ecx.parse_sess().buffer_lint(
                     lint::builtin::BAD_ASM_STYLE,
                     find_span(".att_syntax"),
-                    ecx.resolver.lint_node_id(ecx.current_expansion.id),
+                    ecx.current_expansion.lint_node_id,
                     "avoid using `.att_syntax`, prefer using `options(att_syntax)` instead",
                 );
             }
         }
 
+        // Don't treat raw asm as a format string.
+        if args.options.contains(ast::InlineAsmOptions::RAW) {
+            template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string()));
+            let template_num_lines = 1 + template_str.matches('\n').count();
+            line_spans.extend(std::iter::repeat(template_sp).take(template_num_lines));
+            continue;
+        }
+
         let mut parser = parse::Parser::new(
             template_str,
             str_style,
index 79dc857074d5990ae1320deea5668f8db9c922eb..d7b46f282151fe32ac11e8dc1432d98f0ba58bb6 100644 (file)
@@ -24,61 +24,60 @@ crate fn expand(
     annotatable: Annotatable,
 ) -> Vec<Annotatable> {
     check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
-    cfg_eval(ecx, annotatable)
+    vec![cfg_eval(ecx, annotatable)]
 }
 
-crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Vec<Annotatable> {
-    let mut visitor = CfgEval {
+crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Annotatable {
+    CfgEval {
         cfg: &mut StripUnconfigured {
             sess: ecx.sess,
             features: ecx.ecfg.features,
             config_tokens: true,
         },
-    };
-    let annotatable = visitor.configure_annotatable(annotatable);
-    vec![annotatable]
+    }
+    .configure_annotatable(annotatable)
+    // Since the item itself has already been configured by the `InvocationCollector`,
+    // we know that fold result vector will contain exactly one element.
+    .unwrap()
 }
 
 struct CfgEval<'a, 'b> {
     cfg: &'a mut StripUnconfigured<'b>,
 }
 
-fn flat_map_annotatable(vis: &mut impl MutVisitor, annotatable: Annotatable) -> Annotatable {
-    // Since the item itself has already been configured by the InvocationCollector,
-    // we know that fold result vector will contain exactly one element
+fn flat_map_annotatable(
+    vis: &mut impl MutVisitor,
+    annotatable: Annotatable,
+) -> Option<Annotatable> {
     match annotatable {
-        Annotatable::Item(item) => Annotatable::Item(vis.flat_map_item(item).pop().unwrap()),
+        Annotatable::Item(item) => vis.flat_map_item(item).pop().map(Annotatable::Item),
         Annotatable::TraitItem(item) => {
-            Annotatable::TraitItem(vis.flat_map_trait_item(item).pop().unwrap())
+            vis.flat_map_trait_item(item).pop().map(Annotatable::TraitItem)
         }
         Annotatable::ImplItem(item) => {
-            Annotatable::ImplItem(vis.flat_map_impl_item(item).pop().unwrap())
+            vis.flat_map_impl_item(item).pop().map(Annotatable::ImplItem)
         }
         Annotatable::ForeignItem(item) => {
-            Annotatable::ForeignItem(vis.flat_map_foreign_item(item).pop().unwrap())
+            vis.flat_map_foreign_item(item).pop().map(Annotatable::ForeignItem)
         }
         Annotatable::Stmt(stmt) => {
-            Annotatable::Stmt(stmt.map(|stmt| vis.flat_map_stmt(stmt).pop().unwrap()))
+            vis.flat_map_stmt(stmt.into_inner()).pop().map(P).map(Annotatable::Stmt)
         }
-        Annotatable::Expr(mut expr) => Annotatable::Expr({
+        Annotatable::Expr(mut expr) => {
             vis.visit_expr(&mut expr);
-            expr
-        }),
-        Annotatable::Arm(arm) => Annotatable::Arm(vis.flat_map_arm(arm).pop().unwrap()),
-        Annotatable::ExprField(field) => {
-            Annotatable::ExprField(vis.flat_map_expr_field(field).pop().unwrap())
+            Some(Annotatable::Expr(expr))
         }
-        Annotatable::PatField(fp) => {
-            Annotatable::PatField(vis.flat_map_pat_field(fp).pop().unwrap())
+        Annotatable::Arm(arm) => vis.flat_map_arm(arm).pop().map(Annotatable::Arm),
+        Annotatable::ExprField(field) => {
+            vis.flat_map_expr_field(field).pop().map(Annotatable::ExprField)
         }
+        Annotatable::PatField(fp) => vis.flat_map_pat_field(fp).pop().map(Annotatable::PatField),
         Annotatable::GenericParam(param) => {
-            Annotatable::GenericParam(vis.flat_map_generic_param(param).pop().unwrap())
-        }
-        Annotatable::Param(param) => Annotatable::Param(vis.flat_map_param(param).pop().unwrap()),
-        Annotatable::FieldDef(sf) => {
-            Annotatable::FieldDef(vis.flat_map_field_def(sf).pop().unwrap())
+            vis.flat_map_generic_param(param).pop().map(Annotatable::GenericParam)
         }
-        Annotatable::Variant(v) => Annotatable::Variant(vis.flat_map_variant(v).pop().unwrap()),
+        Annotatable::Param(param) => vis.flat_map_param(param).pop().map(Annotatable::Param),
+        Annotatable::FieldDef(sf) => vis.flat_map_field_def(sf).pop().map(Annotatable::FieldDef),
+        Annotatable::Variant(v) => vis.flat_map_variant(v).pop().map(Annotatable::Variant),
     }
 }
 
@@ -123,11 +122,11 @@ impl CfgEval<'_, '_> {
         self.cfg.configure(node)
     }
 
-    pub fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Annotatable {
+    fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option<Annotatable> {
         // Tokenizing and re-parsing the `Annotatable` can have a significant
         // performance impact, so try to avoid it if possible
         if !CfgFinder::has_cfg_or_cfg_attr(&annotatable) {
-            return annotatable;
+            return Some(annotatable);
         }
 
         // The majority of parsed attribute targets will never need to have early cfg-expansion
index 1bb050a40cee23c813d617f5d024bded7b38a3e6..e0389f448ebf29abf7a48d5bc6bedbfba329fdb7 100644 (file)
@@ -26,6 +26,8 @@ impl MultiItemModifier for Expander {
             return ExpandResult::Ready(vec![item]);
         }
 
+        let item = cfg_eval(ecx, item);
+
         let result =
             ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
                 let template =
@@ -54,12 +56,12 @@ impl MultiItemModifier for Expander {
                         report_path_args(sess, &meta);
                         meta.path
                     })
-                    .map(|path| (path, None))
+                    .map(|path| (path, item.clone(), None))
                     .collect()
             });
 
         match result {
-            Ok(()) => ExpandResult::Ready(cfg_eval(ecx, item)),
+            Ok(()) => ExpandResult::Ready(vec![item]),
             Err(Indeterminate) => ExpandResult::Retry(item),
         }
     }
@@ -82,8 +84,10 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
             sess,
             span,
             E0774,
-            "`derive` may only be applied to structs, enums and unions",
+            "`derive` may only be applied to `struct`s, `enum`s and `union`s",
         )
+        .span_label(span, "not applicable here")
+        .span_label(item.span(), "not a `struct`, `enum` or `union`")
         .emit();
     }
     bad_target
@@ -97,6 +101,7 @@ fn report_unexpected_literal(sess: &Session, lit: &ast::Lit) {
         _ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(),
     };
     struct_span_err!(sess, lit.span, E0777, "expected path to a trait, found literal",)
+        .span_label(lit.span, "not a trait")
         .help(&help_msg)
         .emit();
 }
index ca1226b445d97beb94301349c1544660ea72cc1e..2e5ad66c60bb8778919d1f2429671350ef506125 100644 (file)
@@ -36,8 +36,9 @@ pub fn expand_deriving_clone(
         Annotatable::Item(ref annitem) => match annitem.kind {
             ItemKind::Struct(_, Generics { ref params, .. })
             | ItemKind::Enum(_, Generics { ref params, .. }) => {
-                let container_id = cx.current_expansion.id.expn_data().parent;
-                if cx.resolver.has_derive_copy(container_id)
+                let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
+                let has_derive_copy = cx.resolver.has_derive_copy(container_id);
+                if has_derive_copy
                     && !params
                         .iter()
                         .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
@@ -148,11 +149,7 @@ fn cs_clone_shallow(
             }
             _ => cx.span_bug(
                 trait_span,
-                &format!(
-                    "unexpected substructure in \
-                                                    shallow `derive({})`",
-                    name
-                ),
+                &format!("unexpected substructure in shallow `derive({})`", name),
             ),
         }
     }
index 01a57bea14e3b0ae4d5af5c3f9cac6cba0cbd7cb..c5f3a9d3379a7a0b6fec04f6841b303a80d450b4 100644 (file)
@@ -124,12 +124,7 @@ pub fn expand_deriving_rustc_encodable(
             explicit_self: borrowed_explicit_self(),
             args: vec![(
                 Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)),
-                // FIXME: we could use `sym::s` here, but making `s` a static
-                // symbol changes the symbol index ordering in a way that makes
-                // ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs
-                // fail. The linting code should be fixed so that its output
-                // does not depend on the symbol index ordering.
-                Symbol::intern("s"),
+                sym::s,
             )],
             ret_ty: Literal(Path::new_(
                 pathvec_std!(result::Result),
index a3decff3ae7e1892fa075881cb859a80fc41a697..417dedab60d08a0771668c7b0164d90964cc912d 100644 (file)
@@ -410,7 +410,7 @@ impl<'a> TraitDef<'a> {
                         .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })),
                     _ => unreachable!(),
                 };
-                let container_id = cx.current_expansion.id.expn_data().parent;
+                let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
                 let always_copy = has_no_type_params && cx.resolver.has_derive_copy(container_id);
                 let use_temporaries = is_packed && always_copy;
 
index 6b7d0e1f204b5f0a9712db0f32bc9efa547725ac..00d75be4399649987e9b491aa19fb81cf36e7838 100644 (file)
@@ -72,13 +72,9 @@ impl Path {
     ) -> ast::Path {
         let mut idents = self.path.iter().map(|s| Ident::new(*s, span)).collect();
         let lt = mk_lifetimes(cx, span, &self.lifetime);
-        let tys: Vec<P<ast::Ty>> =
-            self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
-        let params = lt
-            .into_iter()
-            .map(GenericArg::Lifetime)
-            .chain(tys.into_iter().map(GenericArg::Type))
-            .collect();
+        let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics));
+        let params =
+            lt.into_iter().map(GenericArg::Lifetime).chain(tys.map(GenericArg::Type)).collect();
 
         match self.kind {
             PathKind::Global => cx.path_all(span, true, idents, params),
index 7e88b58c0e29d99cecfdf21100332b4469be5112..00f2f37146db68193c08e48fbb5190fe96bed99d 100644 (file)
@@ -939,6 +939,7 @@ pub fn expand_preparsed_format_args(
 
     let msg = "format argument must be a string literal";
     let fmt_sp = efmt.span;
+    let efmt_kind_is_lit: bool = matches!(efmt.kind, ast::ExprKind::Lit(_));
     let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) {
         Ok(mut fmt) if append_newline => {
             fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
@@ -989,7 +990,19 @@ pub fn expand_preparsed_format_args(
 
     if !parser.errors.is_empty() {
         let err = parser.errors.remove(0);
-        let sp = fmt_span.from_inner(err.span);
+        let sp = if efmt_kind_is_lit {
+            fmt_span.from_inner(err.span)
+        } else {
+            // The format string could be another macro invocation, e.g.:
+            //     format!(concat!("abc", "{}"), 4);
+            // However, `err.span` is an inner span relative to the *result* of
+            // the macro invocation, which is why we would get a nonsensical
+            // result calling `fmt_span.from_inner(err.span)` as above, and
+            // might even end up inside a multibyte character (issue #86085).
+            // Therefore, we conservatively report the error for the entire
+            // argument span here.
+            fmt_span
+        };
         let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}", err.description));
         e.span_label(sp, err.label + " in format string");
         if let Some(note) = err.note {
index 2393e0b9ebfac662e8b744d9b920f1190cdc1e76..ba27f1033092807402f6a470e21efd051563cf32 100644 (file)
@@ -19,7 +19,6 @@ use crate::deriving::*;
 
 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 71bbae1161b4bebcef863c749dde5e5f53697b2b..f83329ecba8241dd0fb97dd9a1d4684ed47acd85 100644 (file)
@@ -5,7 +5,7 @@ use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, Visitor};
 use rustc_ast::{self as ast, NodeId};
 use rustc_ast_pretty::pprust;
-use rustc_expand::base::{ExtCtxt, ResolverExpand};
+use rustc_expand::base::{parse_macro_name_and_helper_attrs, ExtCtxt, ResolverExpand};
 use rustc_expand::expand::{AstFragment, ExpansionConfig};
 use rustc_session::Session;
 use rustc_span::hygiene::AstPass;
@@ -109,86 +109,17 @@ impl<'a> CollectProcMacros<'a> {
     }
 
     fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) {
-        // Once we've located the `#[proc_macro_derive]` attribute, verify
-        // that it's of the form `#[proc_macro_derive(Foo)]` or
-        // `#[proc_macro_derive(Foo, attributes(A, ..))]`
-        let list = match attr.meta_item_list() {
-            Some(list) => list,
-            None => return,
-        };
-        if list.len() != 1 && list.len() != 2 {
-            self.handler.span_err(attr.span, "attribute must have either one or two arguments");
-            return;
-        }
-        let trait_attr = match list[0].meta_item() {
-            Some(meta_item) => meta_item,
-            _ => {
-                self.handler.span_err(list[0].span(), "not a meta item");
-                return;
-            }
-        };
-        let trait_ident = match trait_attr.ident() {
-            Some(trait_ident) if trait_attr.is_word() => trait_ident,
-            _ => {
-                self.handler.span_err(trait_attr.span, "must only be one word");
-                return;
-            }
-        };
-
-        if !trait_ident.name.can_be_raw() {
-            self.handler.span_err(
-                trait_attr.span,
-                &format!("`{}` cannot be a name of derive macro", trait_ident),
-            );
-        }
-
-        let attributes_attr = list.get(1);
-        let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
-            if !attr.has_name(sym::attributes) {
-                self.handler.span_err(attr.span(), "second argument must be `attributes`")
-            }
-            attr.meta_item_list()
-                .unwrap_or_else(|| {
-                    self.handler
-                        .span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`");
-                    &[]
-                })
-                .iter()
-                .filter_map(|attr| {
-                    let attr = match attr.meta_item() {
-                        Some(meta_item) => meta_item,
-                        _ => {
-                            self.handler.span_err(attr.span(), "not a meta item");
-                            return None;
-                        }
-                    };
-
-                    let ident = match attr.ident() {
-                        Some(ident) if attr.is_word() => ident,
-                        _ => {
-                            self.handler.span_err(attr.span, "must only be one word");
-                            return None;
-                        }
-                    };
-                    if !ident.name.can_be_raw() {
-                        self.handler.span_err(
-                            attr.span,
-                            &format!("`{}` cannot be a name of derive helper attribute", ident),
-                        );
-                    }
-
-                    Some(ident.name)
-                })
-                .collect()
-        } else {
-            Vec::new()
-        };
+        let (trait_name, proc_attrs) =
+            match parse_macro_name_and_helper_attrs(self.handler, attr, "derive") {
+                Some(name_and_attrs) => name_and_attrs,
+                None => return,
+            };
 
         if self.in_root && item.vis.kind.is_pub() {
             self.macros.push(ProcMacro::Derive(ProcMacroDerive {
                 id: item.id,
                 span: item.span,
-                trait_name: trait_ident.name,
+                trait_name,
                 function_name: item.ident,
                 attrs: proc_attrs,
             }));
@@ -373,7 +304,7 @@ fn mk_decls(
         &[sym::rustc_attrs, sym::proc_macro_internals],
         None,
     );
-    let span = DUMMY_SP.with_def_site_ctxt(expn_id);
+    let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
 
     let proc_macro = Ident::new(sym::proc_macro, span);
     let krate = cx.item(span, proc_macro, Vec::new(), ast::ItemKind::ExternCrate(None));
index ccb9f15b0f50585effc0e1918fd6d718a18abcbc..1ea2c8843d6d7b3cdd4eaf7898a5fef05df98600 100644 (file)
@@ -159,7 +159,7 @@ pub fn expand_include<'cx>(
         }
     }
 
-    Box::new(ExpandResult { p, node_id: cx.resolver.lint_node_id(cx.current_expansion.id) })
+    Box::new(ExpandResult { p, node_id: cx.current_expansion.lint_node_id })
 }
 
 // include_str! : read the given file, insert it as a literal string expr
index fbd8be22a9de2391ee0138cbfab8c97054ba8c3a..e0d57267525d9e12980e44b076f81fd688095466 100644 (file)
@@ -34,8 +34,8 @@ pub fn inject(
         &[sym::prelude_import],
         None,
     );
-    let span = DUMMY_SP.with_def_site_ctxt(expn_id);
-    let call_site = DUMMY_SP.with_call_site_ctxt(expn_id);
+    let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
+    let call_site = DUMMY_SP.with_call_site_ctxt(expn_id.to_expn_id());
 
     let ecfg = ExpansionConfig::default("std_lib_injection".to_string());
     let cx = ExtCtxt::new(sess, ecfg, resolver, None);
index c8a7ff67b4d507cceaca965827ad9f9d6d860110..74a97a4058fac41dc3abef27402d7160c45f1786 100644 (file)
@@ -126,7 +126,8 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
                 for test in &mut tests {
                     // See the comment on `mk_main` for why we're using
                     // `apply_mark` directly.
-                    test.ident.span = test.ident.span.apply_mark(expn_id, Transparency::Opaque);
+                    test.ident.span =
+                        test.ident.span.apply_mark(expn_id.to_expn_id(), Transparency::Opaque);
                 }
                 self.cx.test_cases.extend(tests);
             }
@@ -223,7 +224,7 @@ fn generate_test_harness(
         &[sym::test, sym::rustc_attrs],
         None,
     );
-    let def_site = DUMMY_SP.with_def_site_ctxt(expn_id);
+    let def_site = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
 
     // Remove the entry points
     let mut cleaner = EntryPointCleaner { sess, depth: 0, def_site };
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 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 @@ fn main() {
     #[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 @@ fn main() {
     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 357a9f2daf746e67e4f9bdea0e38a37637251e27..d39486c2f1002e485f849fb0c27fb3564c384e46 100644 (file)
@@ -19,7 +19,7 @@ pub(crate) fn codegen(
     });
     if any_dynamic_crate {
         false
-    } else if let Some(kind) = tcx.allocator_kind() {
+    } else if let Some(kind) = tcx.allocator_kind(()) {
         codegen_inner(module, unwind_context, kind);
         true
     } else {
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 983839d48d2d756ab0bbf5760668eac6854d4329..a044b43b86470a3c3e83f99ea5eb0cec9d4ea92e 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(rustc_private)]
+#![feature(rustc_private, once_cell)]
 
 extern crate rustc_data_structures;
 extern crate rustc_driver;
@@ -6,12 +6,33 @@ extern crate rustc_interface;
 extern crate rustc_session;
 extern crate rustc_target;
 
+use std::lazy::SyncLazy;
+use std::panic;
+
 use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
 use rustc_interface::interface;
 use rustc_session::config::ErrorOutputType;
 use rustc_session::early_error;
 use rustc_target::spec::PanicStrategy;
 
+const BUG_REPORT_URL: &str = "https://github.com/bjorn3/rustc_codegen_cranelift/issues/new";
+
+static DEFAULT_HOOK: SyncLazy<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
+    SyncLazy::new(|| {
+        let hook = panic::take_hook();
+        panic::set_hook(Box::new(|info| {
+            // Invoke the default handler, which prints the actual panic message and optionally a backtrace
+            (*DEFAULT_HOOK)(info);
+
+            // Separate the output with an empty line
+            eprintln!();
+
+            // Print the ICE message
+            rustc_driver::report_ice(info, BUG_REPORT_URL);
+        }));
+        hook
+    });
+
 #[derive(Default)]
 pub struct CraneliftPassesCallbacks {
     time_passes: bool,
@@ -37,7 +58,7 @@ fn main() {
     let start_rss = get_resident_set_size();
     rustc_driver::init_rustc_env_logger();
     let mut callbacks = CraneliftPassesCallbacks::default();
-    rustc_driver::install_ice_hook();
+    SyncLazy::force(&DEFAULT_HOOK); // Install ice hook
     let exit_code = rustc_driver::catch_with_exit_code(|| {
         let args = std::env::args_os()
             .enumerate()
index 488ff6e134956e2d870fabf7e2ebce2327c9b5aa..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>>), DataId>,
     pub(crate) constants_cx: ConstantCx,
 
     pub(crate) instance: Instance<'tcx>,
index 177f850afb398ef6c90e8d1e161920ec56d846e0..100c3b43160bbbb3384390e4741f537db05c0e61 100644 (file)
@@ -7,7 +7,7 @@ macro builtin_functions($register:ident; $(fn $name:ident($($arg_name:ident: $ar
 
     #[cfg(feature = "jit")]
     pub(crate) fn $register(builder: &mut cranelift_jit::JITBuilder) {
-        for &(name, val) in &[$((stringify!($name), $name as *const u8)),*] {
+        for (name, val) in [$((stringify!($name), $name as *const u8)),*] {
             builder.symbol(name, val);
         }
     }
index 3ba12c4e96d6831b1c3238eb48ac158fa334a3ab..c87309e22224f8955a17c639b646e7e782fecea4 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,75 @@ 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, _size) => {
+                let (alloc_id, offset) = ptr.into_parts(); // we know the `offset` is relative
+                let alloc_kind = fx.tcx.get_global_alloc(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,
+                            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!("{:?}", 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 {:?}", alloc_id),
+                };
+                let val = if offset.bytes() != 0 {
+                    fx.bcx.ins().iadd_imm(base_addr, i64::try_from(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()),
@@ -249,12 +255,11 @@ pub(crate) fn codegen_const_value<'tcx>(
     }
 }
 
-fn pointer_for_allocation<'tcx>(
+pub(crate) fn pointer_for_allocation<'tcx>(
     fx: &mut FunctionCx<'_, '_, '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 +271,13 @@ 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 +358,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) => {
@@ -394,7 +407,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
         let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()).to_vec();
         data_ctx.define(bytes.into_boxed_slice());
 
-        for &(offset, (_tag, reloc)) in alloc.relocations().iter() {
+        for &(offset, alloc_id) in alloc.relocations().iter() {
             let addend = {
                 let endianness = tcx.data_layout.endian;
                 let offset = offset.bytes() as usize;
@@ -405,7 +418,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
                 read_target_uint(endianness, bytes).unwrap()
             };
 
-            let reloc_target_alloc = tcx.get_global_alloc(reloc).unwrap();
+            let reloc_target_alloc = tcx.get_global_alloc(alloc_id).unwrap();
             let data_id = match reloc_target_alloc {
                 GlobalAlloc::Function(instance) => {
                     assert_eq!(addend, 0);
@@ -415,8 +428,7 @@ 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)
+                    data_id_for_alloc_id(cx, module, alloc_id, target_alloc.mutability)
                 }
                 GlobalAlloc::Static(def_id) => {
                     if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL)
index 9eb067706309e12cebc5a06146d24e433da1f6e0..c7e15f81e030104c33ff6663ca8806307dcbf7ed 100644 (file)
@@ -10,7 +10,7 @@ use rustc_span::{
 };
 
 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 @@ impl<'tcx> DebugContext<'tcx> {
 
         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 @@ thread_local! {
     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 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
             );
             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 6aadaf8a7cadcea9ce47d930099a987a4c9b8d43..e32dae49131ab0487d7e0a704425f54ffc7cf6b0 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_fs_util;
 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;
@@ -98,7 +100,7 @@ mod prelude {
     pub(crate) use cranelift_codegen::isa::{self, CallConv};
     pub(crate) use cranelift_codegen::Context;
     pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
-    pub(crate) use cranelift_module::{self, DataContext, DataId, FuncId, Linkage, Module};
+    pub(crate) use cranelift_module::{self, DataContext, FuncId, Linkage, Module};
 
     pub(crate) use crate::abi::*;
     pub(crate) use crate::base::{codegen_operand, codegen_place};
@@ -219,10 +221,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
             sess,
             &codegen_results,
             outputs,
-            &codegen_results.crate_info.local_crate_name.as_str(),
-        );
-
-        Ok(())
+        )
     }
 }
 
@@ -285,10 +284,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 042583cd5720fa07b7cac71d3928a302f7d3be0b..b9d379c6117c91d846e3620649c2e40f951daf9f 100644 (file)
@@ -31,9 +31,7 @@ pub(crate) fn unsized_info<'tcx>(
             // change to the vtable.
             old_info.expect("unsized_info: missing old info for trait upcast")
         }
-        (_, &ty::Dynamic(ref data, ..)) => {
-            crate::vtable::get_vtable(fx, fx.layout_of(source), data.principal())
-        }
+        (_, &ty::Dynamic(ref data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()),
         _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target),
     }
 }
index 171f39805f8963ffaad26ce92566cb3f369111d6..ae8ccc626b47089e09a8f75672c9893659ef21fa 100644 (file)
@@ -453,6 +453,10 @@ impl<'tcx> CPlace<'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 bbf07ffc85dbdb7c2a6bd970a735ea69f180eb2b..4a5f9f133a2bbc8e2168fd4668036fb46f3d091f 100644 (file)
@@ -1,14 +1,10 @@
 //! 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::*;
 
-const DROP_FN_INDEX: usize = 0;
-const SIZE_INDEX: usize = 1;
-const ALIGN_INDEX: usize = 2;
-
 fn vtable_memflags() -> MemFlags {
     let mut flags = MemFlags::trusted(); // A vtable access is always aligned and will never trap.
     flags.set_readonly(); // A vtable is always read-only.
@@ -21,7 +17,7 @@ pub(crate) fn drop_fn_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) ->
         pointer_ty(fx.tcx),
         vtable_memflags(),
         vtable,
-        (DROP_FN_INDEX * usize_size) as i32,
+        (ty::COMMON_VTABLE_ENTRIES_DROPINPLACE * usize_size) as i32,
     )
 }
 
@@ -31,7 +27,7 @@ pub(crate) fn size_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Val
         pointer_ty(fx.tcx),
         vtable_memflags(),
         vtable,
-        (SIZE_INDEX * usize_size) as i32,
+        (ty::COMMON_VTABLE_ENTRIES_SIZE * usize_size) as i32,
     )
 }
 
@@ -41,7 +37,7 @@ pub(crate) fn min_align_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -
         pointer_ty(fx.tcx),
         vtable_memflags(),
         vtable,
-        (ALIGN_INDEX * usize_size) as i32,
+        (ty::COMMON_VTABLE_ENTRIES_ALIGN * usize_size) as i32,
     )
 }
 
@@ -62,105 +58,22 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
         pointer_ty(fx.tcx),
         vtable_memflags(),
         vtable,
-        ((idx + 3) * usize_size as usize) as i32,
+        (idx * usize_size as usize) as i32,
     );
     (ptr, func_ref)
 }
 
 pub(crate) fn get_vtable<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
-    layout: TyAndLayout<'tcx>,
+    ty: Ty<'tcx>,
     trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
 ) -> Value {
-    let data_id = if let Some(data_id) = fx.vtables.get(&(layout.ty, trait_ref)) {
-        *data_id
-    } else {
-        let data_id = build_vtable(fx, layout, trait_ref);
-        fx.vtables.insert((layout.ty, trait_ref), data_id);
-        data_id
-    };
-
+    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);
-    fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
-}
-
-fn build_vtable<'tcx>(
-    fx: &mut FunctionCx<'_, '_, 'tcx>,
-    layout: TyAndLayout<'tcx>,
-    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
-) -> DataId {
-    let tcx = fx.tcx;
-    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
-
-    let drop_in_place_fn = import_function(
-        tcx,
-        fx.module,
-        Instance::resolve_drop_in_place(tcx, layout.ty).polymorphize(fx.tcx),
-    );
-
-    let mut components: Vec<_> = vec![Some(drop_in_place_fn), None, None];
-
-    let methods_root;
-    let methods = if let Some(trait_ref) = trait_ref {
-        methods_root = tcx.vtable_methods(trait_ref.with_self_ty(tcx, layout.ty));
-        methods_root.iter()
-    } else {
-        (&[]).iter()
-    };
-    let methods = methods.cloned().map(|opt_mth| {
-        opt_mth.map(|(def_id, substs)| {
-            import_function(
-                tcx,
-                fx.module,
-                Instance::resolve_for_vtable(tcx, ParamEnv::reveal_all(), def_id, substs)
-                    .unwrap()
-                    .polymorphize(fx.tcx),
-            )
-        })
-    });
-    components.extend(methods);
-
-    let mut data_ctx = DataContext::new();
-    let mut data = ::std::iter::repeat(0u8)
-        .take(components.len() * usize_size)
-        .collect::<Vec<u8>>()
-        .into_boxed_slice();
-
-    write_usize(fx.tcx, &mut data, SIZE_INDEX, layout.size.bytes());
-    write_usize(fx.tcx, &mut data, ALIGN_INDEX, layout.align.abi.bytes());
-    data_ctx.define(data);
-
-    for (i, component) in components.into_iter().enumerate() {
-        if let Some(func_id) = component {
-            let func_ref = fx.module.declare_func_in_data(func_id, &mut data_ctx);
-            data_ctx.write_function_addr((i * usize_size) as u32, func_ref);
-        }
-    }
-
-    data_ctx.set_align(fx.tcx.data_layout.pointer_align.pref.bytes());
-
-    let data_id = fx.module.declare_anonymous_data(false, false).unwrap();
-
-    fx.module.define_data(data_id, &data_ctx).unwrap();
-
-    data_id
-}
-
-fn write_usize(tcx: TyCtxt<'_>, buf: &mut [u8], idx: usize, num: u64) {
-    let pointer_size =
-        tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.usize)).unwrap().size.bytes() as usize;
-    let target = &mut buf[idx * pointer_size..(idx + 1) * pointer_size];
-
-    match tcx.data_layout.endian {
-        rustc_target::abi::Endian::Little => match pointer_size {
-            4 => target.copy_from_slice(&(num as u32).to_le_bytes()),
-            8 => target.copy_from_slice(&(num as u64).to_le_bytes()),
-            _ => todo!("pointer size {} is not yet supported", pointer_size),
-        },
-        rustc_target::abi::Endian::Big => match pointer_size {
-            4 => target.copy_from_slice(&(num as u32).to_be_bytes()),
-            8 => target.copy_from_slice(&(num as u64).to_be_bytes()),
-            _ => todo!("pointer size {} is not yet supported", pointer_size),
-        },
+    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 d0eb6913accde06efb58127b23ca33a71673dc62..d78af9d413e6d3e25667306c452dffdec20ccf45 100644 (file)
@@ -21,10 +21,8 @@ rustc_attr = { path = "../rustc_attr" }
 rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
-rustc_feature = { path = "../rustc_feature" }
 rustc_fs_util = { path = "../rustc_fs_util" }
 rustc_hir = { path = "../rustc_hir" }
-rustc_incremental = { path = "../rustc_incremental" }
 rustc_index = { path = "../rustc_index" }
 rustc_llvm = { path = "../rustc_llvm" }
 rustc_metadata = { path = "../rustc_metadata" }
index ecf62ed213df82aec1daaf5b5b1cf958d0f9054c..7bd9397d64950d19eba45c753c9a9faa61d49294 100644 (file)
@@ -128,6 +128,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
         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 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
                     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 f1c45d8dc36475e64bd8e1a793c4346d99522de7..56b93f83466805d32302878c4fbfa5923ae71f4f 100644 (file)
@@ -12,7 +12,7 @@ use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::config::OptLevel;
 use rustc_session::Session;
 use rustc_target::spec::abi::Abi;
-use rustc_target::spec::{SanitizerSet, StackProbeType};
+use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType};
 
 use crate::attributes;
 use crate::llvm::AttributePlace::Function;
@@ -69,15 +69,25 @@ fn naked(val: &'ll Value, is_naked: bool) {
     Attribute::Naked.toggle_llfn(Function, val, is_naked);
 }
 
-pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
-    if cx.sess().must_not_eliminate_frame_pointers() {
-        llvm::AddFunctionAttrStringValue(
-            llfn,
-            llvm::AttributePlace::Function,
-            cstr!("frame-pointer"),
-            cstr!("all"),
-        );
+pub fn set_frame_pointer_type(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
+    let mut fp = cx.sess().target.frame_pointer;
+    // "mcount" function relies on stack pointer.
+    // See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
+    if cx.sess().instrument_mcount() || matches!(cx.sess().opts.cg.force_frame_pointers, Some(true))
+    {
+        fp = FramePointer::Always;
     }
+    let attr_value = match fp {
+        FramePointer::Always => cstr!("all"),
+        FramePointer::NonLeaf => cstr!("non-leaf"),
+        FramePointer::MayOmit => return,
+    };
+    llvm::AddFunctionAttrStringValue(
+        llfn,
+        llvm::AttributePlace::Function,
+        cstr!("frame-pointer"),
+        attr_value,
+    );
 }
 
 /// Tell LLVM what instrument function to insert.
@@ -254,7 +264,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
     }
 
     // FIXME: none of these three functions interact with source level attributes.
-    set_frame_pointer_elimination(cx, llfn);
+    set_frame_pointer_type(cx, llfn);
     set_instrument_function(cx, llfn);
     set_probestack(cx, llfn);
 
@@ -279,6 +289,9 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
     if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) {
         llvm::AddFunctionAttrString(llfn, Function, cstr!("cmse_nonsecure_entry"));
     }
+    if let Some(align) = codegen_fn_attrs.alignment {
+        llvm::set_alignment(llfn, align as usize);
+    }
     sanitize(cx, codegen_fn_attrs.no_sanitize, llfn);
 
     // Always annotate functions with the target-cpu they are compiled for.
index 64416bced31d024dcd8819dbeaa6f35e0f2cf8ad..6ac7093b7dee833870d4568529293b088950f62f 100644 (file)
@@ -12,7 +12,7 @@ use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
 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 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
         // 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 @@ impl<'a> LlvmArchiveBuilder<'a> {
             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 c8cf0116c641ef526a84506d039d08cd629b1d62..5675a5d9812413c7caec00ce84b083ee564a1301 100644 (file)
@@ -410,17 +410,17 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    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 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
     fn atomic_load(
         &mut self,
+        ty: &'ll Type,
         ptr: &'ll Value,
         order: rustc_codegen_ssa::common::AtomicOrdering,
         size: Size,
@@ -435,6 +436,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         unsafe {
             let load = llvm::LLVMRustBuildAtomicLoad(
                 self.llbuilder,
+                ty,
                 ptr,
                 UNNAMED,
                 AtomicOrdering::from_generic(order),
@@ -486,7 +488,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'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 @@ impl BuilderMethods<'a, 'tcx> for Builder<'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)
             };
@@ -606,7 +609,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 // According to LLVM [1] building a nontemporal store must
                 // *always* point to a metadata value of the integer 1.
                 //
-                // [1]: http://llvm.org/docs/LangRef.html#store-instruction
+                // [1]: https://llvm.org/docs/LangRef.html#store-instruction
                 let one = self.cx.const_i32(1);
                 let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1);
                 llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node);
@@ -815,13 +818,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         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 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         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());
@@ -937,8 +928,12 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         pers_fn: &'ll Value,
         num_clauses: usize,
     ) -> &'ll Value {
+        // Use LLVMSetPersonalityFn to set the personality. It supports arbitrary Consts while,
+        // LLVMBuildLandingPad requires the argument to be a Function (as of LLVM 12). The
+        // personality lives on the parent function anyway.
+        self.set_personality_fn(pers_fn);
         unsafe {
-            llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn, num_clauses as c_uint, UNNAMED)
+            llvm::LLVMBuildLandingPad(self.llbuilder, ty, None, num_clauses as c_uint, UNNAMED)
         }
     }
 
index 58af9d4cd04a9d116a1b9e1a91f9123fbb5382de..35e72621c565d6473423b398758fb201f925c8e5 100644 (file)
@@ -243,8 +243,9 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                     self.const_bitcast(llval, llty)
                 }
             }
-            Scalar::Ptr(ptr) => {
-                let (base_addr, base_addr_space) = match self.tcx.global_alloc(ptr.alloc_id) {
+            Scalar::Ptr(ptr, _size) => {
+                let (alloc_id, offset) = ptr.into_parts();
+                let (base_addr, base_addr_space) = match self.tcx.global_alloc(alloc_id) {
                     GlobalAlloc::Memory(alloc) => {
                         let init = const_alloc_to_llvm(self, alloc);
                         let value = match alloc.mutability {
@@ -252,7 +253,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                             _ => self.static_addr_of(init, alloc.align, None),
                         };
                         if !self.sess().fewer_names() {
-                            llvm::set_value_name(value, format!("{:?}", ptr.alloc_id).as_bytes());
+                            llvm::set_value_name(value, format!("{:?}", alloc_id).as_bytes());
                         }
                         (value, AddressSpace::DATA)
                     }
@@ -269,7 +270,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                 let llval = unsafe {
                     llvm::LLVMConstInBoundsGEP(
                         self.const_bitcast(base_addr, self.type_i8p_ext(base_addr_space)),
-                        &self.const_usize(ptr.offset.bytes()),
+                        &self.const_usize(offset.bytes()),
                         1,
                     )
                 };
@@ -282,6 +283,10 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         }
     }
 
+    fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value {
+        const_alloc_to_llvm(self, alloc)
+    }
+
     fn from_const_alloc(
         &self,
         layout: TyAndLayout<'tcx>,
index e50d5506e222f5794f7c9ebd194521df8d53e4b7..3ca295f4a7e89396658d0e002151e7ae6c0f8309 100644 (file)
@@ -11,7 +11,7 @@ use rustc_codegen_ssa::traits::*;
 use rustc_hir::def_id::DefId;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::interpret::{
-    read_target_uint, Allocation, ErrorHandled, GlobalAlloc, Pointer,
+    read_target_uint, Allocation, ErrorHandled, GlobalAlloc, Pointer, Scalar as InterpScalar,
 };
 use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::ty::{self, Instance, Ty};
@@ -25,7 +25,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
     let pointer_size = dl.pointer_size.bytes() as usize;
 
     let mut next_offset = 0;
-    for &(offset, ((), alloc_id)) in alloc.relocations().iter() {
+    for &(offset, alloc_id) in alloc.relocations().iter() {
         let offset = offset.bytes();
         assert_eq!(offset as usize as u64, offset);
         let offset = offset as usize;
@@ -55,7 +55,10 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
         };
 
         llvals.push(cx.scalar_to_backend(
-            Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(),
+            InterpScalar::from_pointer(
+                Pointer::new(alloc_id, Size::from_bytes(ptr_offset)),
+                &cx.tcx,
+            ),
             &Scalar { value: Primitive::Pointer, valid_range: 0..=!0 },
             cx.type_i8p_ext(address_space),
         ));
index 6aa952462fa58d50f0d20435fed58a5ba63e1c3a..59259857b4b0d8b2e73ac1859e32e8247a96418b 100644 (file)
@@ -71,7 +71,7 @@ pub struct CodegenCx<'ll, 'tcx> {
     pub statics_to_rauw: RefCell<Vec<(&'ll Value, &'ll Value)>>,
 
     /// Statics that will be placed in the llvm.used variable
-    /// See <http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable> for details
+    /// See <https://llvm.org/docs/LangRef.html#the-llvm-used-global-variable> for details
     pub used_statics: RefCell<Vec<&'ll Value>>,
 
     pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), &'ll Type>>,
@@ -149,11 +149,12 @@ pub unsafe fn create_module(
 
         if !custom_llvm_used && target_data_layout != llvm_data_layout {
             bug!(
-                "data-layout for builtin `{}` target, `{}`, \
-                  differs from LLVM default, `{}`",
-                sess.target.llvm_target,
-                target_data_layout,
-                llvm_data_layout
+                "data-layout for target `{rustc_target}`, `{rustc_layout}`, \
+                  differs from LLVM target's `{llvm_target}` default layout, `{llvm_layout}`",
+                rustc_target = sess.opts.target_triple,
+                rustc_layout = target_data_layout,
+                llvm_target = sess.target.llvm_target,
+                llvm_layout = llvm_data_layout
             );
         }
     }
@@ -385,11 +386,16 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                 } else {
                     "rust_eh_personality"
                 };
-                let fty = self.type_variadic_func(&[], self.type_i32());
-                self.declare_cfn(name, llvm::UnnamedAddr::Global, fty)
+                if let Some(llfn) = self.get_declared_value(name) {
+                    llfn
+                } else {
+                    let fty = self.type_variadic_func(&[], self.type_i32());
+                    let llfn = self.declare_cfn(name, llvm::UnnamedAddr::Global, fty);
+                    attributes::apply_target_cpu_attr(self, llfn);
+                    llfn
+                }
             }
         };
-        attributes::apply_target_cpu_attr(self, llfn);
         self.eh_personality.set(Some(llfn));
         llfn
     }
@@ -410,8 +416,8 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         &self.used_statics
     }
 
-    fn set_frame_pointer_elimination(&self, llfn: &'ll Value) {
-        attributes::set_frame_pointer_elimination(self, llfn)
+    fn set_frame_pointer_type(&self, llfn: &'ll Value) {
+        attributes::set_frame_pointer_type(self, llfn)
     }
 
     fn apply_target_cpu_attr(&self, llfn: &'ll Value) {
@@ -500,6 +506,7 @@ impl CodegenCx<'b, 'tcx> {
         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 +719,10 @@ impl CodegenCx<'b, 'tcx> {
         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 1e70664e64d707dbc3aa9af04669b0c416a68c88..7e136c1b24cb26e8a26dcdf53c2339f3f35a70b4 100644 (file)
@@ -1,4 +1,3 @@
-use self::EnumTagInfo::*;
 use self::MemberDescriptionFactory::*;
 use self::RecursiveTypeDescription::*;
 
@@ -28,7 +27,7 @@ use rustc_hir::def::CtorKind;
 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;
@@ -471,21 +470,28 @@ fn trait_pointer_metadata(
     // type is assigned the correct name, size, namespace, and source location.
     // However, it does not describe the trait's methods.
 
-    let containing_scope = match trait_type.kind() {
-        ty::Dynamic(ref data, ..) => {
-            data.principal_def_id().map(|did| get_namespace_for_item(cx, did))
-        }
-        _ => {
-            bug!(
-                "debuginfo: unexpected trait-object type in \
-                  trait_pointer_metadata(): {:?}",
-                trait_type
-            );
-        }
-    };
+    let (containing_scope, trait_type_name) = match trait_object_type {
+        Some(trait_object_type) => match trait_object_type.kind() {
+            ty::Adt(def, _) => (
+                Some(get_namespace_for_item(cx, def.did)),
+                compute_debuginfo_type_name(cx.tcx, trait_object_type, false),
+            ),
+            ty::RawPtr(_) | ty::Ref(..) => {
+                (NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_object_type, true))
+            }
+            _ => {
+                bug!(
+                    "debuginfo: unexpected trait-object type in \
+                      trait_pointer_metadata(): {:?}",
+                    trait_object_type
+                );
+            }
+        },
 
-    let trait_object_type = trait_object_type.unwrap_or(trait_type);
-    let trait_type_name = compute_debuginfo_type_name(cx.tcx, trait_object_type, false);
+        // No object type, use the trait type directly (no scope here since the type
+        // will be wrapped in the dyn$ synthetic type).
+        None => (NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_type, true)),
+    };
 
     let file_metadata = unknown_file_metadata(cx);
 
@@ -525,7 +531,7 @@ fn trait_pointer_metadata(
 
     composite_type_metadata(
         cx,
-        trait_object_type,
+        trait_object_type.unwrap_or(trait_type),
         &trait_type_name[..],
         unique_type_id,
         member_descriptions,
@@ -1181,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> {
@@ -1498,14 +1504,8 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                 }
 
                 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);
 
@@ -1517,7 +1517,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                     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,
@@ -1533,28 +1533,38 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                 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, _)| {
@@ -1564,7 +1574,6 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                             cx,
                             variant,
                             variant_info,
-                            tag_info,
                             self_metadata,
                             self.span,
                         );
@@ -1598,6 +1607,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                             source_info: variant_info.source_info(cx),
                         }
                     })
+                    .chain(fallback_discr_variant.into_iter())
                     .collect()
             }
             Variants::Multiple {
@@ -1695,7 +1705,6 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                         cx,
                         dataful_variant_layout,
                         variant_info,
-                        Some(NicheTag),
                         self_metadata,
                         self.span,
                     );
@@ -1747,7 +1756,6 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                                     cx,
                                     variant,
                                     variant_info,
-                                    Some(NicheTag),
                                     self_metadata,
                                     self.span,
                                 );
@@ -1784,39 +1792,27 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
 }
 
 // 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,
                 }
@@ -1825,12 +1821,6 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> {
     }
 }
 
-#[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),
@@ -1909,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>) {
@@ -1928,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 2b99a2ebad979227ff6b6068f6cf69da962ff8d6..8375d4c7ca561223b1c561cfd7157a4d3f95e1c7 100644 (file)
@@ -5,7 +5,6 @@ use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
 use self::metadata::{file_metadata, type_metadata, TypeMap};
 use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
 use self::namespace::mangled_name_of_instance;
-use self::type_names::compute_debuginfo_type_name;
 use self::utils::{create_DIArray, is_node_local_to_unit, DIB};
 
 use crate::abi::FnAbi;
@@ -311,10 +310,10 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
             llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), fn_signature)
         };
 
-        // Find the enclosing function, in case this is a closure.
-        let def_key = self.tcx().def_key(def_id);
-        let mut name = def_key.disambiguated_data.data.to_string();
+        let mut name = String::new();
+        type_names::push_item_name(self.tcx(), def_id, false, &mut name);
 
+        // Find the enclosing function, in case this is a closure.
         let enclosing_fn_def_id = self.tcx().closure_base_def_id(def_id);
 
         // Get_template_parameters() will append a `<...>` clause to the function
@@ -428,24 +427,16 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
             substs: SubstsRef<'tcx>,
             name_to_append_suffix_to: &mut String,
         ) -> &'ll DIArray {
+            type_names::push_generic_params(
+                cx.tcx,
+                cx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs),
+                name_to_append_suffix_to,
+            );
+
             if substs.types().next().is_none() {
                 return create_DIArray(DIB(cx), &[]);
             }
 
-            name_to_append_suffix_to.push('<');
-            for (i, actual_type) in substs.types().enumerate() {
-                if i != 0 {
-                    name_to_append_suffix_to.push(',');
-                }
-
-                let actual_type =
-                    cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), actual_type);
-                // Add actual type name to <...> clause of function name
-                let actual_type_name = compute_debuginfo_type_name(cx.tcx(), actual_type, true);
-                name_to_append_suffix_to.push_str(&actual_type_name[..]);
-            }
-            name_to_append_suffix_to.push('>');
-
             // Again, only create type information if full debuginfo is enabled
             let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full {
                 let names = get_parameter_names(cx, generics);
index 9945d4f4282597901b1f84cf2c09d9ef0c2982a3..1cbf53869960895d01b5063211c39fb13e46fc06 100644 (file)
@@ -1,13 +1,13 @@
 // Namespace Handling.
 
 use super::utils::{debug_context, DIB};
+use rustc_codegen_ssa::debuginfo::type_names;
 use rustc_middle::ty::{self, Instance};
 
 use crate::common::CodegenCx;
 use crate::llvm;
 use crate::llvm::debuginfo::DIScope;
 use rustc_hir::def_id::DefId;
-use rustc_hir::definitions::DefPathData;
 
 pub fn mangled_name_of_instance<'a, 'tcx>(
     cx: &CodegenCx<'a, 'tcx>,
@@ -27,25 +27,18 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
         .parent
         .map(|parent| item_namespace(cx, DefId { krate: def_id.krate, index: parent }));
 
-    let crate_name_as_str;
-    let name_to_string;
-    let namespace_name = match def_key.disambiguated_data.data {
-        DefPathData::CrateRoot => {
-            crate_name_as_str = cx.tcx.crate_name(def_id.krate).as_str();
-            &*crate_name_as_str
-        }
-        data => {
-            name_to_string = data.to_string();
-            &*name_to_string
-        }
+    let namespace_name_string = {
+        let mut output = String::new();
+        type_names::push_item_name(cx.tcx, def_id, false, &mut output);
+        output
     };
 
     let scope = unsafe {
         llvm::LLVMRustDIBuilderCreateNameSpace(
             DIB(cx),
             parent_scope,
-            namespace_name.as_ptr().cast(),
-            namespace_name.len(),
+            namespace_name_string.as_ptr().cast(),
+            namespace_name_string.len(),
             false, // ExportSymbols (only relevant for C++ anonymous namespaces)
         )
     };
index 22d513d66d1cc87aeb4a84abc7473ed09d7650b8..a48a694b630f001cd5c17b34d82de0234a3a0d5d 100644 (file)
@@ -162,11 +162,14 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
 
             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 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
                 }
             }
 
+            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());
 
@@ -674,7 +715,7 @@ fn gen_fn<'ll, 'tcx>(
 ) -> &'ll Value {
     let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]);
     let llfn = cx.declare_fn(name, &fn_abi);
-    cx.set_frame_pointer_elimination(llfn);
+    cx.set_frame_pointer_type(llfn);
     cx.apply_target_cpu_attr(llfn);
     // FIXME(eddyb) find a nicer way to do this.
     unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
index 776cb2ee99bcbf727f6ce65d5fa6124454eed4f6..aa4db1622b233fcac03486718649d51e7aa5fc96 100644 (file)
@@ -8,7 +8,6 @@
 #![feature(bool_to_option)]
 #![feature(const_cstr_unchecked)]
 #![feature(crate_visibility_modifier)]
-#![cfg_attr(bootstrap, feature(extended_key_value_attributes))]
 #![feature(extern_types)]
 #![feature(in_band_lifetimes)]
 #![feature(iter_zip)]
@@ -293,14 +292,7 @@ impl CodegenBackend for LlvmCodegenBackend {
 
         // 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(),
-        );
-
-        Ok(())
+        link_binary::<LlvmArchiveBuilder<'_>>(sess, &codegen_results, outputs)
     }
 }
 
index 91923251018a898671319bc486f5b3e98f651f5e..68d566cca095c3ea9faff2561310b88711eeede7 100644 (file)
@@ -1165,7 +1165,7 @@ extern "C" {
     pub fn LLVMBuildLandingPad(
         B: &Builder<'a>,
         Ty: &'a Type,
-        PersFn: &'a Value,
+        PersFn: Option<&'a Value>,
         NumClauses: c_uint,
         Name: *const c_char,
     ) -> &'a Value;
@@ -1385,7 +1385,12 @@ extern "C" {
         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 @@ extern "C" {
     // Atomic Operations
     pub fn LLVMRustBuildAtomicLoad(
         B: &Builder<'a>,
+        ElementType: &'a Type,
         PointerVal: &'a Value,
         Name: *const c_char,
         Order: AtomicOrdering,
index 38d56f872116933dccdae216c772ecb547b0aa1a..c1521a760b00205518c226ef54812e1c0646f819 100644 (file)
@@ -102,7 +102,7 @@ pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) {
 // example happen for generics when using multiple codegen units. This function simply uses the
 // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
 // function.
-// For more details on COMDAT sections see e.g., http://www.airs.com/blog/archives/52
+// For more details on COMDAT sections see e.g., https://www.airs.com/blog/archives/52
 pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) {
     unsafe {
         let name = get_value_name(val);
index 0dd3d2ae15bcae74a3c9ca974e59d021c0f75d14..cb9c6269b66bbbb37882343ded402d3141665ae3 100644 (file)
@@ -3,13 +3,17 @@ use crate::{llvm, llvm_util};
 use libc::c_int;
 use rustc_codegen_ssa::target_features::supported_target_features;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_metadata::dynamic_lib::DynamicLibrary;
 use rustc_middle::bug;
 use rustc_session::config::PrintRequest;
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{MergeFunctions, PanicStrategy};
 use std::ffi::{CStr, CString};
+use tracing::debug;
 
+use std::mem;
+use std::path::Path;
 use std::ptr;
 use std::slice;
 use std::str;
@@ -129,6 +133,16 @@ unsafe fn configure_llvm(sess: &Session) {
 
     llvm::LLVMInitializePasses();
 
+    for plugin in &sess.opts.debugging_opts.llvm_plugins {
+        let path = Path::new(plugin);
+        let res = DynamicLibrary::open(path);
+        match res {
+            Ok(_) => debug!("LLVM plugin loaded succesfully {} ({})", path.display(), plugin),
+            Err(e) => bug!("couldn't load plugin: {}", e),
+        }
+        mem::forget(res);
+    }
+
     rustc_llvm::initialize_available_targets();
 
     llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr());
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 9bd5764f0730dbff3e4772db5a50b0947b2afbe7..f1e412df86149729004e89cf9de35d2d5c497864 100644 (file)
@@ -9,13 +9,14 @@ test = false
 
 [dependencies]
 bitflags = "1.2.1"
-cc = "1.0.68"
+cc = "1.0.69"
 itertools = "0.9"
 tracing = "0.1"
 libc = "0.2.50"
 jobserver = "0.1.22"
 tempfile = "3.2"
 pathdiff = "0.2.0"
+smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
 
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_ast = { path = "../rustc_ast" }
@@ -35,6 +36,6 @@ rustc_target = { path = "../rustc_target" }
 rustc_session = { path = "../rustc_session" }
 
 [dependencies.object]
-version = "0.25.2"
+version = "0.26.2"
 default-features = false
 features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]
index 6c9ec9e7b0dae909fe262739f4c5a46892133867..ab211e9daff3e3dd8eda34b9bbec277793f45a22 100644 (file)
@@ -1,9 +1,9 @@
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_data_structures::temp_dir::MaybeTempDir;
-use rustc_errors::Handler;
+use rustc_errors::{ErrorReported, 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::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,7 +34,6 @@ use object::write::Object;
 use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, SectionKind};
 use tempfile::Builder as TempFileBuilder;
 
-use std::cmp::Ordering;
 use std::ffi::OsString;
 use std::path::{Path, PathBuf};
 use std::process::{ExitStatus, Output, Stdio};
@@ -54,8 +53,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
     sess: &'a Session,
     codegen_results: &CodegenResults,
     outputs: &OutputFilenames,
-    crate_name: &str,
-) {
+) -> Result<(), ErrorReported> {
     let _timer = sess.timer("link_binary");
     let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
     for &crate_type in sess.crate_types().iter() {
@@ -87,15 +85,26 @@ 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");
-                    link_rlib::<B>(sess, codegen_results, RlibFlavor::Normal, &out_filename, &path)
-                        .build();
+                    link_rlib::<B>(
+                        sess,
+                        codegen_results,
+                        RlibFlavor::Normal,
+                        &out_filename,
+                        &path,
+                    )?
+                    .build();
                 }
                 CrateType::Staticlib => {
-                    link_staticlib::<B>(sess, codegen_results, &out_filename, &path);
+                    link_staticlib::<B>(sess, codegen_results, &out_filename, &path)?;
                 }
                 _ => {
                     link_natively::<B>(
@@ -141,104 +150,15 @@ 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
+    Ok(())
 }
 
 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 +176,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);
     }
@@ -306,7 +227,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
     flavor: RlibFlavor,
     out_filename: &Path,
     tmpdir: &MaybeTempDir,
-) -> B {
+) -> Result<B, ErrorReported> {
     info!("preparing rlib to {:?}", out_filename);
     let mut ab = <B as ArchiveBuilder>::new(sess, out_filename, None);
 
@@ -345,7 +266,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);
     }
@@ -398,7 +319,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
             }
         }
     }
-    return ab;
+    return Ok(ab);
 
     // For rlibs we "pack" rustc metadata into a dummy object file. When rustc
     // creates a dylib crate type it will pass `--whole-archive` (or the
@@ -537,49 +458,43 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
 /// 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],
+) -> Result<Vec<(String, Vec<DllImport>)>, ErrorReported> {
+    // Use index maps to preserve original order of imports and libraries.
+    let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default();
 
     for lib in used_libraries {
         if lib.kind == NativeLibKind::RawDylib {
-            let name = lib.name.unwrap_or_else(||
-                bug!("`link` attribute with kind = \"raw-dylib\" and no name should have caused error earlier")
-            );
-            let name = if matches!(lib.verbatim, Some(true)) {
-                name.to_string()
-            } else {
-                format!("{}.dll", name)
-            };
-            dylib_table
-                .entry(name)
-                .or_default()
-                .extend(lib.dll_imports.iter().map(|import| import.name));
+            let ext = if matches!(lib.verbatim, Some(true)) { "" } else { ".dll" };
+            let name = format!("{}{}", lib.name.expect("unnamed raw-dylib library"), ext);
+            let imports = dylib_table.entry(name.clone()).or_default();
+            for import in &lib.dll_imports {
+                if let Some(old_import) = imports.insert(import.name, import) {
+                    // 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.
+                    if import.calling_convention != old_import.calling_convention {
+                        sess.span_err(
+                            import.span,
+                            &format!(
+                                "multiple declarations of external function `{}` from \
+                                 library `{}` have different calling conventions",
+                                import.name, name,
+                            ),
+                        );
+                    }
+                }
+            }
         }
     }
-
-    // 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
+    sess.compile_status()?;
+    Ok(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(|(name, imports)| {
+            (name, imports.into_iter().map(|(_, import)| import.clone()).collect())
         })
-        .collect::<Vec<_>>();
-    result.sort_unstable_by(|a: &(String, Vec<DllImport>), b: &(String, Vec<DllImport>)| {
-        a.0.cmp(&b.0)
-    });
-    result
+        .collect())
 }
 
 /// Create a static archive.
@@ -598,9 +513,9 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
     codegen_results: &CodegenResults,
     out_filename: &Path,
     tempdir: &MaybeTempDir,
-) {
+) -> Result<(), ErrorReported> {
     let mut ab =
-        link_rlib::<B>(sess, codegen_results, RlibFlavor::StaticlibBase, out_filename, tempdir);
+        link_rlib::<B>(sess, codegen_results, RlibFlavor::StaticlibBase, out_filename, tempdir)?;
     let mut all_native_libs = vec![];
 
     let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| {
@@ -648,6 +563,8 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
             print_native_static_libs(sess, &all_native_libs);
         }
     }
+
+    Ok(())
 }
 
 fn escape_stdout_stderr_string(s: &[u8]) -> String {
@@ -912,14 +829,23 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
             if !prog.status.success() {
                 let mut output = prog.stderr.clone();
                 output.extend_from_slice(&prog.stdout);
-                sess.struct_err(&format!(
+                let escaped_output = escape_stdout_stderr_string(&output);
+                let mut err = sess.struct_err(&format!(
                     "linking with `{}` failed: {}",
                     linker_path.display(),
                     prog.status
-                ))
-                .note(&format!("{:?}", &cmd))
-                .note(&escape_stdout_stderr_string(&output))
-                .emit();
+                ));
+                err.note(&format!("{:?}", &cmd)).note(&escaped_output);
+                if escaped_output.contains("undefined reference to") {
+                    err.help(
+                        "some `extern` functions couldn't be found; some native libraries may \
+                         need to be installed or have their path specified",
+                    );
+                    err.note("use the `-l` flag to specify native libraries to link");
+                    err.note("use the `cargo:rustc-link-lib` directive to specify the native \
+                              libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)");
+                }
+                err.emit();
 
                 // If MSVC's `link.exe` was expected but the return code
                 // is not a Microsoft LNK error then suggest a way to fix or
@@ -1750,8 +1676,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,
@@ -1779,11 +1716,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 ------------
@@ -1793,7 +1732,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,
@@ -1965,10 +1908,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,
@@ -1991,7 +1934,12 @@ fn add_order_independent_options(
     // Try to strip as much out of the generated object by removing unused
     // sections if possible. See more comments in linker.rs
     if !sess.link_dead_code() {
-        let keep_metadata = crate_type == CrateType::Dylib;
+        // If PGO is enabled sometimes gc_sections will remove the profile data section
+        // as it appears to be unused. This can then cause the PGO profile file to lose
+        // some functions. If we are generating a profile we shouldn't strip those metadata
+        // sections to ensure we have all the data for PGO.
+        let keep_metadata =
+            crate_type == CrateType::Dylib || sess.opts.cg.profile_generate.enabled();
         cmd.gc_sections(keep_metadata);
     }
 
@@ -2112,7 +2060,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
@@ -2140,7 +2088,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);
@@ -2167,7 +2115,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();
         }
@@ -2379,9 +2327,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::ffi::{OsStr, OsString};
 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 @@ impl dyn Linker + '_ {
 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 @@ impl<'a> GccLinker<'a> {
         };
 
         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 @@ impl<'a> Linker for GccLinker<'a> {
         }
     }
 
-    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 @@ impl<'a> Linker for GccLinker<'a> {
             // 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 @@ impl<'a> Linker for GccLinker<'a> {
                 // .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 @@ impl<'a> Linker for GccLinker<'a> {
             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 @@ impl<'a> Linker for GccLinker<'a> {
 pub struct MsvcLinker<'a> {
     cmd: Command,
     sess: &'a Session,
-    info: &'a LinkerInfo,
 }
 
 impl<'a> Linker for MsvcLinker<'a> {
@@ -887,7 +949,7 @@ impl<'a> Linker for MsvcLinker<'a> {
     // 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 @@ impl<'a> Linker for MsvcLinker<'a> {
             // 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 @@ impl<'a> Linker for MsvcLinker<'a> {
 pub struct EmLinker<'a> {
     cmd: Command,
     sess: &'a Session,
-    info: &'a LinkerInfo,
 }
 
 impl<'a> Linker for EmLinker<'a> {
@@ -1066,9 +1127,7 @@ impl<'a> Linker for EmLinker<'a> {
         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 @@ impl<'a> Linker for EmLinker<'a> {
 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 @@ impl<'a> WasmLd<'a> {
             cmd.arg("--export=__tls_align");
             cmd.arg("--export=__tls_base");
         }
-        WasmLd { cmd, sess, info }
+        WasmLd { cmd, sess }
     }
 }
 
@@ -1263,8 +1321,8 @@ impl<'a> Linker for WasmLd<'a> {
 
     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 @@ impl<'a> Linker for WasmLd<'a> {
     }
 }
 
-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 @@ impl<'a> Linker for PtxLinker<'a> {
 
     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 @@ impl<'a> Linker for PtxLinker<'a> {
 pub struct BpfLinker<'a> {
     cmd: Command,
     sess: &'a Session,
-    info: &'a LinkerInfo,
 }
 
 impl<'a> Linker for BpfLinker<'a> {
@@ -1517,11 +1574,11 @@ impl<'a> Linker for BpfLinker<'a> {
 
     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::env;
 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 b2ecc3b0f3242e33738c6255ca35e4365ff87f14..4ef21449d216e5c1771b2958fd8466a1b7aa1472 100644 (file)
@@ -180,7 +180,7 @@ fn exported_symbols_provider_local(
         symbols.push((exported_symbol, SymbolExportLevel::C));
     }
 
-    if tcx.allocator_kind().is_some() {
+    if tcx.allocator_kind(()).is_some() {
         for method in ALLOCATOR_METHODS {
             let symbol_name = format!("__rust_{}", method.name);
             let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));
@@ -277,7 +277,7 @@ fn upstream_monomorphizations_provider(
     tcx: TyCtxt<'_>,
     (): (),
 ) -> DefIdMap<FxHashMap<SubstsRef<'_>, CrateNum>> {
-    let cnums = tcx.all_crate_nums(());
+    let cnums = tcx.crates(());
 
     let mut instances: DefIdMap<FxHashMap<_, _>> = Default::default();
 
index ff4e64095714086cd4a76222786f164a2587b895..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,
@@ -994,7 +991,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
             }
             Lto::Fat | Lto::Thin => {
                 exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
-                for &cnum in tcx.crates().iter() {
+                for &cnum in tcx.crates(()).iter() {
                     exported_symbols.insert(cnum, copy_symbols(cnum));
                 }
                 Some(Arc::new(exported_symbols))
@@ -1799,7 +1796,6 @@ impl SharedEmitterMain {
 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 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
         (
             CodegenResults {
                 metadata: self.metadata,
-                linker_info: self.linker_info,
                 crate_info: self.crate_info,
 
                 modules: compiled_modules.modules,
index 38ab39febe066c4c0db3adfb8f4286d1ff0289e7..be2bf8b199724ab59a00a6c054d38034b783e914 100644 (file)
@@ -20,7 +20,6 @@ use rustc_hir::lang_items::LangItem;
 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};
@@ -406,7 +405,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         };
 
         // `main` should respect same config for frame pointer elimination as rest of code
-        cx.set_frame_pointer_elimination(llfn);
+        cx.set_frame_pointer_type(llfn);
         cx.apply_target_cpu_attr(llfn);
 
         let llbb = Bx::append_block(&cx, llfn, "top");
@@ -518,7 +517,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
     });
     let allocator_module = if any_dynamic_crate {
         None
-    } else if let Some(kind) = tcx.allocator_kind() {
+    } else if let Some(kind) = tcx.allocator_kind(()) {
         let llmod_id =
             cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
         let mut modules = backend.new_metadata(tcx, &llmod_id);
@@ -755,7 +754,13 @@ impl<B: ExtraBackendMethods> Drop for AbortCodegenOnDrop<B> {
 }
 
 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 @@ impl 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(),
@@ -789,7 +810,7 @@ impl CrateInfo {
         };
         let lang_items = tcx.lang_items();
 
-        let crates = tcx.crates();
+        let crates = tcx.crates(());
 
         let n_crates = crates.len();
         info.native_libraries.reserve(n_crates);
@@ -802,9 +823,6 @@ impl 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 7b4b0821c4be8017c75e66434cc2bed946e6bd03..81e905b1b5f578279466d7f28feb5ade52ac7147 100644 (file)
@@ -1,10 +1,27 @@
 // Type Names for Debug Info.
 
+// Notes on targetting MSVC:
+// In general, MSVC's debugger attempts to parse all arguments as C++ expressions,
+// even if the argument is explicitly a symbol name.
+// As such, there are many things that cause parsing issues:
+// * `#` is treated as a special character for macros.
+// * `{` or `<` at the beginning of a name is treated as an operator.
+// * `>>` is always treated as a right-shift.
+// * `[` in a name is treated like a regex bracket expression (match any char
+//   within the brackets).
+// * `"` is treated as the start of a string.
+
 use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty, TyCtxt};
-use rustc_target::abi::{TagEncoding, Variants};
+use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
+use rustc_middle::ich::NodeIdHashingMode;
+use rustc_middle::ty::layout::IntegerExt;
+use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
+use rustc_middle::ty::{self, AdtDef, ExistentialProjection, Ty, TyCtxt};
+use rustc_target::abi::{Integer, TagEncoding, Variants};
+use smallvec::SmallVec;
 
 use std::fmt::Write;
 
@@ -17,6 +34,8 @@ pub fn compute_debuginfo_type_name<'tcx>(
     t: Ty<'tcx>,
     qualified: bool,
 ) -> String {
+    let _prof = tcx.prof.generic_activity("compute_debuginfo_type_name");
+
     let mut result = String::with_capacity(64);
     let mut visited = FxHashSet::default();
     push_debuginfo_type_name(tcx, t, qualified, &mut result, &mut visited);
@@ -25,7 +44,7 @@ pub fn compute_debuginfo_type_name<'tcx>(
 
 // Pushes the name of the type as it should be stored in debuginfo on the
 // `output` String. See also compute_debuginfo_type_name().
-pub fn push_debuginfo_type_name<'tcx>(
+fn push_debuginfo_type_name<'tcx>(
     tcx: TyCtxt<'tcx>,
     t: Ty<'tcx>,
     qualified: bool,
@@ -34,13 +53,19 @@ pub fn push_debuginfo_type_name<'tcx>(
 ) {
     // When targeting MSVC, emit C++ style type names for compatibility with
     // .natvis visualizers (and perhaps other existing native debuggers?)
-    let cpp_like_names = tcx.sess.target.is_like_msvc;
+    let cpp_like_names = cpp_like_names(tcx);
 
     match *t.kind() {
         ty::Bool => output.push_str("bool"),
         ty::Char => output.push_str("char"),
         ty::Str => output.push_str("str"),
-        ty::Never => output.push('!'),
+        ty::Never => {
+            if cpp_like_names {
+                output.push_str("never$");
+            } else {
+                output.push('!');
+            }
+        }
         ty::Int(int_ty) => output.push_str(int_ty.name_str()),
         ty::Uint(uint_ty) => output.push_str(uint_ty.name_str()),
         ty::Float(float_ty) => output.push_str(float_ty.name_str()),
@@ -50,74 +75,98 @@ pub fn push_debuginfo_type_name<'tcx>(
                 msvc_enum_fallback(tcx, t, def, substs, output, visited);
             } else {
                 push_item_name(tcx, def.did, qualified, output);
-                push_type_params(tcx, substs, output, visited);
+                push_generic_params_internal(tcx, substs, output, visited);
             }
         }
         ty::Tuple(component_types) => {
             if cpp_like_names {
-                output.push_str("tuple<");
+                output.push_str("tuple$<");
             } else {
                 output.push('(');
             }
 
             for component_type in component_types {
                 push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited);
-                output.push_str(", ");
+                push_arg_separator(cpp_like_names, output);
             }
             if !component_types.is_empty() {
-                output.pop();
-                output.pop();
+                pop_arg_separator(output);
             }
 
             if cpp_like_names {
-                output.push('>');
+                push_close_angle_bracket(cpp_like_names, output);
             } else {
                 output.push(')');
             }
         }
         ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => {
-            if !cpp_like_names {
+            if cpp_like_names {
+                match mutbl {
+                    hir::Mutability::Not => output.push_str("ptr_const$<"),
+                    hir::Mutability::Mut => output.push_str("ptr_mut$<"),
+                }
+            } else {
                 output.push('*');
-            }
-            match mutbl {
-                hir::Mutability::Not => output.push_str("const "),
-                hir::Mutability::Mut => output.push_str("mut "),
+                match mutbl {
+                    hir::Mutability::Not => output.push_str("const "),
+                    hir::Mutability::Mut => output.push_str("mut "),
+                }
             }
 
-            push_debuginfo_type_name(tcx, inner_type, true, output, visited);
+            push_debuginfo_type_name(tcx, inner_type, qualified, output, visited);
 
             if cpp_like_names {
-                output.push('*');
+                push_close_angle_bracket(cpp_like_names, output);
             }
         }
         ty::Ref(_, inner_type, mutbl) => {
+            // Slices and `&str` are treated like C++ pointers when computing debug
+            // info for MSVC debugger. However, wrapping these types' names in a synthetic type
+            // causes the .natvis engine for WinDbg to fail to display their data, so we opt these
+            // types out to aid debugging in MSVC.
+            let is_slice_or_str = match *inner_type.kind() {
+                ty::Slice(_) | ty::Str => true,
+                _ => false,
+            };
+
             if !cpp_like_names {
                 output.push('&');
+                output.push_str(mutbl.prefix_str());
+            } else if !is_slice_or_str {
+                match mutbl {
+                    hir::Mutability::Not => output.push_str("ref$<"),
+                    hir::Mutability::Mut => output.push_str("ref_mut$<"),
+                }
             }
-            output.push_str(mutbl.prefix_str());
 
-            push_debuginfo_type_name(tcx, inner_type, true, output, visited);
+            push_debuginfo_type_name(tcx, inner_type, qualified, output, visited);
 
-            if cpp_like_names {
-                // Slices and `&str` are treated like C++ pointers when computing debug
-                // info for MSVC debugger. However, adding '*' at the end of these types' names
-                // causes the .natvis engine for WinDbg to fail to display their data, so we opt these
-                // types out to aid debugging in MSVC.
-                match *inner_type.kind() {
-                    ty::Slice(_) | ty::Str => {}
-                    _ => output.push('*'),
-                }
+            if cpp_like_names && !is_slice_or_str {
+                push_close_angle_bracket(cpp_like_names, output);
             }
         }
         ty::Array(inner_type, len) => {
-            output.push('[');
-            push_debuginfo_type_name(tcx, inner_type, true, output, visited);
-            output.push_str(&format!("; {}", len.eval_usize(tcx, ty::ParamEnv::reveal_all())));
-            output.push(']');
+            if cpp_like_names {
+                output.push_str("array$<");
+                push_debuginfo_type_name(tcx, inner_type, true, output, visited);
+                match len.val {
+                    ty::ConstKind::Param(param) => write!(output, ",{}>", param.name).unwrap(),
+                    _ => write!(output, ",{}>", len.eval_usize(tcx, ty::ParamEnv::reveal_all()))
+                        .unwrap(),
+                }
+            } else {
+                output.push('[');
+                push_debuginfo_type_name(tcx, inner_type, true, output, visited);
+                match len.val {
+                    ty::ConstKind::Param(param) => write!(output, "; {}]", param.name).unwrap(),
+                    _ => write!(output, "; {}]", len.eval_usize(tcx, ty::ParamEnv::reveal_all()))
+                        .unwrap(),
+                }
+            }
         }
         ty::Slice(inner_type) => {
             if cpp_like_names {
-                output.push_str("slice<");
+                output.push_str("slice$<");
             } else {
                 output.push('[');
             }
@@ -125,19 +174,97 @@ pub fn push_debuginfo_type_name<'tcx>(
             push_debuginfo_type_name(tcx, inner_type, true, output, visited);
 
             if cpp_like_names {
-                output.push('>');
+                push_close_angle_bracket(cpp_like_names, output);
             } else {
                 output.push(']');
             }
         }
         ty::Dynamic(ref trait_data, ..) => {
+            let auto_traits: SmallVec<[DefId; 4]> = trait_data.auto_traits().collect();
+
+            let has_enclosing_parens = if cpp_like_names {
+                output.push_str("dyn$<");
+                false
+            } else {
+                if trait_data.len() > 1 && auto_traits.len() != 0 {
+                    // We need enclosing parens because there is more than one trait
+                    output.push_str("(dyn ");
+                    true
+                } else {
+                    output.push_str("dyn ");
+                    false
+                }
+            };
+
             if let Some(principal) = trait_data.principal() {
                 let principal =
                     tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal);
-                push_item_name(tcx, principal.def_id, false, output);
-                push_type_params(tcx, principal.substs, output, visited);
-            } else {
-                output.push_str("dyn '_");
+                push_item_name(tcx, principal.def_id, qualified, output);
+                let principal_has_generic_params =
+                    push_generic_params_internal(tcx, principal.substs, output, visited);
+
+                let projection_bounds: SmallVec<[_; 4]> = trait_data
+                    .projection_bounds()
+                    .map(|bound| {
+                        let ExistentialProjection { item_def_id, ty, .. } = bound.skip_binder();
+                        (item_def_id, ty)
+                    })
+                    .collect();
+
+                if projection_bounds.len() != 0 {
+                    if principal_has_generic_params {
+                        // push_generic_params_internal() above added a `>` but we actually
+                        // want to add more items to that list, so remove that again.
+                        pop_close_angle_bracket(output);
+                    }
+
+                    for (item_def_id, ty) in projection_bounds {
+                        push_arg_separator(cpp_like_names, output);
+
+                        if cpp_like_names {
+                            output.push_str("assoc$<");
+                            push_item_name(tcx, item_def_id, false, output);
+                            push_arg_separator(cpp_like_names, output);
+                            push_debuginfo_type_name(tcx, ty, true, output, visited);
+                            push_close_angle_bracket(cpp_like_names, output);
+                        } else {
+                            push_item_name(tcx, item_def_id, false, output);
+                            output.push('=');
+                            push_debuginfo_type_name(tcx, ty, true, output, visited);
+                        }
+                    }
+
+                    push_close_angle_bracket(cpp_like_names, output);
+                }
+
+                if auto_traits.len() != 0 {
+                    push_auto_trait_separator(cpp_like_names, output);
+                }
+            }
+
+            if auto_traits.len() != 0 {
+                let mut auto_traits: SmallVec<[String; 4]> = auto_traits
+                    .into_iter()
+                    .map(|def_id| {
+                        let mut name = String::with_capacity(20);
+                        push_item_name(tcx, def_id, true, &mut name);
+                        name
+                    })
+                    .collect();
+                auto_traits.sort_unstable();
+
+                for auto_trait in auto_traits {
+                    output.push_str(&auto_trait);
+                    push_auto_trait_separator(cpp_like_names, output);
+                }
+
+                pop_auto_trait_separator(output);
+            }
+
+            if cpp_like_names {
+                push_close_angle_bracket(cpp_like_names, output);
+            } else if has_enclosing_parens {
+                output.push(')');
             }
         }
         ty::FnDef(..) | ty::FnPtr(_) => {
@@ -155,30 +282,43 @@ pub fn push_debuginfo_type_name<'tcx>(
             // use a dummy string that should make it clear
             // that something unusual is going on
             if !visited.insert(t) {
-                output.push_str("<recursive_type>");
+                output.push_str(if cpp_like_names {
+                    "recursive_type$"
+                } else {
+                    "<recursive_type>"
+                });
                 return;
             }
 
-            let sig = t.fn_sig(tcx);
-            output.push_str(sig.unsafety().prefix_str());
+            let sig =
+                tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), t.fn_sig(tcx));
 
-            let abi = sig.abi();
-            if abi != rustc_target::spec::abi::Abi::Rust {
-                output.push_str("extern \"");
-                output.push_str(abi.name());
-                output.push_str("\" ");
-            }
+            if cpp_like_names {
+                // Format as a C++ function pointer: return_type (*)(params...)
+                if sig.output().is_unit() {
+                    output.push_str("void");
+                } else {
+                    push_debuginfo_type_name(tcx, sig.output(), true, output, visited);
+                }
+                output.push_str(" (*)(");
+            } else {
+                output.push_str(sig.unsafety.prefix_str());
+
+                if sig.abi != rustc_target::spec::abi::Abi::Rust {
+                    output.push_str("extern \"");
+                    output.push_str(sig.abi.name());
+                    output.push_str("\" ");
+                }
 
-            output.push_str("fn(");
+                output.push_str("fn(");
+            }
 
-            let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
             if !sig.inputs().is_empty() {
                 for &parameter_type in sig.inputs() {
                     push_debuginfo_type_name(tcx, parameter_type, true, output, visited);
-                    output.push_str(", ");
+                    push_arg_separator(cpp_like_names, output);
                 }
-                output.pop();
-                output.pop();
+                pop_arg_separator(output);
             }
 
             if sig.c_variadic {
@@ -191,7 +331,7 @@ pub fn push_debuginfo_type_name<'tcx>(
 
             output.push(')');
 
-            if !sig.output().is_unit() {
+            if !cpp_like_names && !sig.output().is_unit() {
                 output.push_str(" -> ");
                 push_debuginfo_type_name(tcx, sig.output(), true, output, visited);
             }
@@ -207,17 +347,14 @@ pub fn push_debuginfo_type_name<'tcx>(
             // processing
             visited.remove(t);
         }
-        ty::Closure(def_id, ..) => {
-            output.push_str(&format!(
-                "closure-{}",
-                tcx.def_key(def_id).disambiguated_data.disambiguator
-            ));
-        }
-        ty::Generator(def_id, ..) => {
-            output.push_str(&format!(
-                "generator-{}",
-                tcx.def_key(def_id).disambiguated_data.disambiguator
-            ));
+        ty::Closure(def_id, ..) | ty::Generator(def_id, ..) => {
+            let key = tcx.def_key(def_id);
+            if qualified {
+                let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
+                push_item_name(tcx, parent_def_id, true, output);
+                output.push_str("::");
+            }
+            push_unqualified_item_name(tcx, def_id, key.disambiguated_data, output);
         }
         // Type parameters from polymorphized functions.
         ty::Param(_) => {
@@ -252,6 +389,10 @@ pub fn push_debuginfo_type_name<'tcx>(
     ) {
         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,
@@ -271,57 +412,217 @@ pub fn push_debuginfo_type_name<'tcx>(
             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_type_params(tcx, substs, output, visited);
-
             let dataful_variant_name = def.variants[*dataful_variant].ident.as_str();
 
-            output.push_str(&format!(", {}, {}, {}>", min, max, dataful_variant_name));
+            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(true, output);
+    }
+
+    const NON_CPP_AUTO_TRAIT_SEPARATOR: &str = " + ";
+
+    fn push_auto_trait_separator(cpp_like_names: bool, output: &mut String) {
+        if cpp_like_names {
+            push_arg_separator(cpp_like_names, output);
         } else {
-            output.push_str("enum$<");
-            push_item_name(tcx, def.did, true, output);
-            push_type_params(tcx, substs, output, visited);
-            output.push('>');
+            output.push_str(NON_CPP_AUTO_TRAIT_SEPARATOR);
         }
     }
 
-    fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) {
-        if qualified {
+    fn pop_auto_trait_separator(output: &mut String) {
+        if output.ends_with(NON_CPP_AUTO_TRAIT_SEPARATOR) {
+            output.truncate(output.len() - NON_CPP_AUTO_TRAIT_SEPARATOR.len());
+        } else {
+            pop_arg_separator(output);
+        }
+    }
+}
+
+pub fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) {
+    let def_key = tcx.def_key(def_id);
+    if qualified {
+        if let Some(parent) = def_key.parent {
+            push_item_name(tcx, DefId { krate: def_id.krate, index: parent }, true, output);
+            output.push_str("::");
+        }
+    }
+
+    push_unqualified_item_name(tcx, def_id, def_key.disambiguated_data, output);
+}
+
+fn push_unqualified_item_name(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    disambiguated_data: DisambiguatedDefPathData,
+    output: &mut String,
+) {
+    match disambiguated_data.data {
+        DefPathData::CrateRoot => {
             output.push_str(&tcx.crate_name(def_id.krate).as_str());
-            for path_element in tcx.def_path(def_id).data {
-                write!(output, "::{}", path_element.data).unwrap();
+        }
+        DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => {
+            // Generators look like closures, but we want to treat them differently
+            // in the debug info.
+            if cpp_like_names(tcx) {
+                write!(output, "generator${}", disambiguated_data.disambiguator).unwrap();
+            } else {
+                write!(output, "{{generator#{}}}", disambiguated_data.disambiguator).unwrap();
             }
-        } else {
-            output.push_str(&tcx.item_name(def_id).as_str());
         }
+        _ => match disambiguated_data.data.name() {
+            DefPathDataName::Named(name) => {
+                output.push_str(&name.as_str());
+            }
+            DefPathDataName::Anon { namespace } => {
+                if cpp_like_names(tcx) {
+                    write!(output, "{}${}", namespace, disambiguated_data.disambiguator).unwrap();
+                } else {
+                    write!(output, "{{{}#{}}}", namespace, disambiguated_data.disambiguator)
+                        .unwrap();
+                }
+            }
+        },
+    };
+}
+
+// Pushes the generic parameters in the given `InternalSubsts` to the output string.
+// This ignores region parameters, since they can't reliably be
+// reconstructed for items from non-local crates. For local crates, this
+// would be possible but with inlining and LTO we have to use the least
+// common denominator - otherwise we would run into conflicts.
+fn push_generic_params_internal<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    substs: SubstsRef<'tcx>,
+    output: &mut String,
+    visited: &mut FxHashSet<Ty<'tcx>>,
+) -> bool {
+    if substs.non_erasable_generics().next().is_none() {
+        return false;
     }
 
-    // Pushes the type parameters in the given `InternalSubsts` to the output string.
-    // This ignores region parameters, since they can't reliably be
-    // reconstructed for items from non-local crates. For local crates, this
-    // would be possible but with inlining and LTO we have to use the least
-    // common denominator - otherwise we would run into conflicts.
-    fn push_type_params<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        substs: SubstsRef<'tcx>,
-        output: &mut String,
-        visited: &mut FxHashSet<Ty<'tcx>>,
-    ) {
-        if substs.types().next().is_none() {
-            return;
+    debug_assert_eq!(substs, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs));
+
+    let cpp_like_names = cpp_like_names(tcx);
+
+    output.push('<');
+
+    for type_parameter in substs.non_erasable_generics() {
+        match type_parameter {
+            GenericArgKind::Type(type_parameter) => {
+                push_debuginfo_type_name(tcx, type_parameter, true, output, visited);
+            }
+            GenericArgKind::Const(ct) => {
+                push_const_param(tcx, ct, output);
+            }
+            other => bug!("Unexpected non-erasable generic: {:?}", other),
         }
 
-        output.push('<');
+        push_arg_separator(cpp_like_names, output);
+    }
+    pop_arg_separator(output);
+    push_close_angle_bracket(cpp_like_names, output);
+
+    true
+}
 
-        for type_parameter in substs.types() {
-            push_debuginfo_type_name(tcx, type_parameter, true, output, visited);
-            output.push_str(", ");
+fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: &'tcx ty::Const<'tcx>, output: &mut String) {
+    match ct.val {
+        ty::ConstKind::Param(param) => {
+            write!(output, "{}", param.name)
         }
+        _ => match ct.ty.kind() {
+            ty::Int(ity) => {
+                let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all(), ct.ty);
+                let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
+                write!(output, "{}", val)
+            }
+            ty::Uint(_) => {
+                let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all(), ct.ty);
+                write!(output, "{}", val)
+            }
+            ty::Bool => {
+                let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap();
+                write!(output, "{}", val)
+            }
+            _ => {
+                // If we cannot evaluate the constant to a known type, we fall back
+                // to emitting a stable hash value of the constant. This isn't very pretty
+                // but we get a deterministic, virtually unique value for the constant.
+                let hcx = &mut tcx.create_stable_hashing_context();
+                let mut hasher = StableHasher::new();
+                hcx.while_hashing_spans(false, |hcx| {
+                    hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+                        ct.val.hash_stable(hcx, &mut hasher);
+                    });
+                });
+                // Let's only emit 64 bits of the hash value. That should be plenty for
+                // avoiding collisions and will make the emitted type names shorter.
+                let hash: u64 = hasher.finish();
+
+                if cpp_like_names(tcx) {
+                    write!(output, "CONST${:x}", hash)
+                } else {
+                    write!(output, "{{CONST#{:x}}}", hash)
+                }
+            }
+        },
+    }
+    .unwrap();
+}
 
+pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, output: &mut String) {
+    let _prof = tcx.prof.generic_activity("compute_debuginfo_type_name");
+    let mut visited = FxHashSet::default();
+    push_generic_params_internal(tcx, substs, output, &mut visited);
+}
+
+fn push_close_angle_bracket(cpp_like_names: bool, output: &mut String) {
+    // MSVC debugger always treats `>>` as a shift, even when parsing templates,
+    // so add a space to avoid confusion.
+    if cpp_like_names && output.ends_with('>') {
+        output.push(' ')
+    };
+
+    output.push('>');
+}
+
+fn pop_close_angle_bracket(output: &mut String) {
+    assert!(output.ends_with('>'), "'output' does not end with '>': {}", output);
+    output.pop();
+    if output.ends_with(' ') {
         output.pop();
-        output.pop();
+    }
+}
 
-        output.push('>');
+fn push_arg_separator(cpp_like_names: bool, output: &mut String) {
+    // Natvis does not always like having spaces between parts of the type name
+    // and this causes issues when we need to write a typename in natvis, for example
+    // as part of a cast like the `HashMap` visualizer does.
+    if cpp_like_names {
+        output.push(',');
+    } else {
+        output.push_str(", ");
+    };
+}
+
+fn pop_arg_separator(output: &mut String) {
+    if output.ends_with(' ') {
+        output.pop();
     }
+
+    assert!(output.ends_with(','));
+
+    output.pop();
+}
+
+fn cpp_like_names(tcx: TyCtxt<'_>) -> bool {
+    tcx.sess.target.is_like_msvc
 }
index b88de0b2411414ca9da2dd091737f15494c202f3..cf217b52c86f483677baeb62ca470db22c61b405 100644 (file)
@@ -23,7 +23,12 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         ty::Dynamic(..) => {
             // load size/align from vtable
             let vtable = info.unwrap();
-            (meth::SIZE.get_usize(bx, vtable), meth::ALIGN.get_usize(bx, vtable))
+            (
+                meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_SIZE)
+                    .get_usize(bx, vtable),
+                meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_ALIGN)
+                    .get_usize(bx, vtable),
+            )
         }
         ty::Slice(_) | ty::Str => {
             let unit = layout.field(bx, 0);
index b6de12fa35e37ee183dcc89412d5ad2af0a08d8a..b6ee70c419b160e224a8dcb60067c8ff9e240e06 100644 (file)
@@ -24,10 +24,10 @@ use rustc_data_structures::sync::Lrc;
 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 @@ impl From<&cstore::NativeLib> for NativeLib {
 /// 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 bcc19c6a44bd829ffff227b9c606938cb26da6b5..b392b2c4ab8acfc70aa129b04767cb9efb8d9338 100644 (file)
@@ -1,18 +1,14 @@
 use crate::traits::*;
 
-use rustc_middle::ty::{self, Instance, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_target::abi::call::FnAbi;
 
 #[derive(Copy, Clone, Debug)]
 pub struct VirtualIndex(u64);
 
-pub const DESTRUCTOR: VirtualIndex = VirtualIndex(0);
-pub const SIZE: VirtualIndex = VirtualIndex(1);
-pub const ALIGN: VirtualIndex = VirtualIndex(2);
-
 impl<'a, 'tcx> VirtualIndex {
     pub fn from_index(index: usize) -> Self {
-        VirtualIndex(index as u64 + 3)
+        VirtualIndex(index as u64)
     }
 
     pub fn get_fn<Bx: BuilderMethods<'a, 'tcx>>(
@@ -24,10 +20,11 @@ impl<'a, 'tcx> VirtualIndex {
         // 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);
@@ -42,10 +39,11 @@ impl<'a, 'tcx> VirtualIndex {
         // 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
@@ -74,53 +72,13 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
         return val;
     }
 
-    // Not in the cache; build it.
-    let nullptr = cx.const_null(cx.type_i8p_ext(cx.data_layout().instruction_address_space));
-
-    let methods_root;
-    let methods = if let Some(trait_ref) = trait_ref {
-        methods_root = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty));
-        methods_root.iter()
-    } else {
-        (&[]).iter()
-    };
-
-    let methods = methods.cloned().map(|opt_mth| {
-        opt_mth.map_or(nullptr, |(def_id, substs)| {
-            cx.get_fn_addr(
-                ty::Instance::resolve_for_vtable(
-                    cx.tcx(),
-                    ty::ParamEnv::reveal_all(),
-                    def_id,
-                    substs,
-                )
-                .unwrap()
-                .polymorphize(cx.tcx()),
-            )
-        })
-    });
-
-    let layout = cx.layout_of(ty);
-    // /////////////////////////////////////////////////////////////////////////////////////////////
-    // If you touch this code, be sure to also make the corresponding changes to
-    // `get_vtable` in `rust_mir/interpret/traits.rs`.
-    // /////////////////////////////////////////////////////////////////////////////////////////////
-    let components: Vec<_> = [
-        cx.get_fn_addr(Instance::resolve_drop_in_place(cx.tcx(), ty)),
-        cx.const_usize(layout.size.bytes()),
-        cx.const_usize(layout.align.abi.bytes()),
-    ]
-    .iter()
-    .cloned()
-    .chain(methods)
-    .collect();
-
-    let vtable_const = cx.const_struct(&components, false);
+    let vtable_alloc_id = tcx.vtable_allocation(ty, trait_ref);
+    let vtable_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory();
+    let vtable_const = cx.const_data_from_alloc(vtable_allocation);
     let align = cx.data_layout().pointer_align.abi;
     let vtable = cx.static_addr_of(vtable_const, align, Some("vtable"));
 
     cx.create_vtable_metadata(ty, vtable);
-
     cx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
     vtable
 }
index 49b5e8466bef2bd3d94324cad71750b785a57a31..b6def164fac631002bc920ed071bf2fb10eba5a2 100644 (file)
@@ -5,7 +5,7 @@ use super::FunctionCx;
 use crate::traits::*;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
 use rustc_middle::mir::traversal;
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{self, Location, TerminatorKind};
@@ -16,7 +16,29 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     fx: &FunctionCx<'a, 'tcx, Bx>,
 ) -> BitSet<mir::Local> {
     let mir = fx.mir;
-    let mut analyzer = LocalAnalyzer::new(fx);
+    let dominators = mir.dominators();
+    let locals = mir
+        .local_decls
+        .iter()
+        .map(|decl| {
+            let ty = fx.monomorphize(decl.ty);
+            let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
+            if layout.is_zst() {
+                LocalKind::ZST
+            } else if fx.cx.is_backend_immediate(layout) || fx.cx.is_backend_scalar_pair(layout) {
+                LocalKind::Unused
+            } else {
+                LocalKind::Memory
+            }
+        })
+        .collect();
+
+    let mut analyzer = LocalAnalyzer { fx, dominators, locals };
+
+    // Arguments get assigned to by means of the function being called
+    for arg in mir.args_iter() {
+        analyzer.assign(arg, mir::START_BLOCK.start_location());
+    }
 
     // If there exists a local definition that dominates all uses of that local,
     // the definition should be visited first. Traverse blocks in preorder which
@@ -25,76 +47,45 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         analyzer.visit_basic_block_data(bb, data);
     }
 
-    for (local, decl) in mir.local_decls.iter_enumerated() {
-        let ty = fx.monomorphize(decl.ty);
-        debug!("local {:?} has type `{}`", local, ty);
-        let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
-        if fx.cx.is_backend_immediate(layout) {
-            // These sorts of types are immediates that we can store
-            // in an Value without an alloca.
-        } else if fx.cx.is_backend_scalar_pair(layout) {
-            // We allow pairs and uses of any of their 2 fields.
-        } else {
-            // These sorts of types require an alloca. Note that
-            // is_llvm_immediate() may *still* be true, particularly
-            // for newtypes, but we currently force some types
-            // (e.g., structs) into an alloca unconditionally, just so
-            // that we don't have to deal with having two pathways
-            // (gep vs extractvalue etc).
-            analyzer.not_ssa(local);
+    let mut non_ssa_locals = BitSet::new_empty(analyzer.locals.len());
+    for (local, kind) in analyzer.locals.iter_enumerated() {
+        if matches!(kind, LocalKind::Memory) {
+            non_ssa_locals.insert(local);
         }
     }
 
-    analyzer.non_ssa_locals
+    non_ssa_locals
+}
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+enum LocalKind {
+    ZST,
+    /// A local that requires an alloca.
+    Memory,
+    /// A scalar or a scalar pair local that is neither defined nor used.
+    Unused,
+    /// A scalar or a scalar pair local with a single definition that dominates all uses.
+    SSA(mir::Location),
 }
 
 struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
     fx: &'mir FunctionCx<'a, 'tcx, Bx>,
     dominators: Dominators<mir::BasicBlock>,
-    non_ssa_locals: BitSet<mir::Local>,
-    // The location of the first visited direct assignment to each
-    // local, or an invalid location (out of bounds `block` index).
-    first_assignment: IndexVec<mir::Local, Location>,
+    locals: IndexVec<mir::Local, LocalKind>,
 }
 
 impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
-    fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>) -> Self {
-        let invalid_location = mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location();
-        let dominators = fx.mir.dominators();
-        let mut analyzer = LocalAnalyzer {
-            fx,
-            dominators,
-            non_ssa_locals: BitSet::new_empty(fx.mir.local_decls.len()),
-            first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls),
-        };
-
-        // Arguments get assigned to by means of the function being called
-        for arg in fx.mir.args_iter() {
-            analyzer.first_assignment[arg] = mir::START_BLOCK.start_location();
-        }
-
-        analyzer
-    }
-
-    fn first_assignment(&self, local: mir::Local) -> Option<Location> {
-        let location = self.first_assignment[local];
-        if location.block.index() < self.fx.mir.basic_blocks().len() {
-            Some(location)
-        } else {
-            None
-        }
-    }
-
-    fn not_ssa(&mut self, local: mir::Local) {
-        debug!("marking {:?} as non-SSA", local);
-        self.non_ssa_locals.insert(local);
-    }
-
     fn assign(&mut self, local: mir::Local, location: Location) {
-        if self.first_assignment(local).is_some() {
-            self.not_ssa(local);
-        } else {
-            self.first_assignment[local] = location;
+        let kind = &mut self.locals[local];
+        match *kind {
+            LocalKind::ZST => {}
+            LocalKind::Memory => {}
+            LocalKind::Unused => {
+                *kind = LocalKind::SSA(location);
+            }
+            LocalKind::SSA(_) => {
+                *kind = LocalKind::Memory;
+            }
         }
     }
 
@@ -175,11 +166,13 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
     ) {
         debug!("visit_assign(place={:?}, rvalue={:?})", place, rvalue);
 
-        if let Some(index) = place.as_local() {
-            self.assign(index, location);
-            let decl_span = self.fx.mir.local_decls[index].source_info.span;
-            if !self.fx.rvalue_creates_operand(rvalue, decl_span) {
-                self.not_ssa(index);
+        if let Some(local) = place.as_local() {
+            self.assign(local, location);
+            if self.locals[local] != LocalKind::Memory {
+                let decl_span = self.fx.mir.local_decls[local].source_info.span;
+                if !self.fx.rvalue_creates_operand(rvalue, decl_span) {
+                    self.locals[local] = LocalKind::Memory;
+                }
             }
         } else {
             self.visit_place(place, PlaceContext::MutatingUse(MutatingUseContext::Store), location);
@@ -204,32 +197,18 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
 
             PlaceContext::NonMutatingUse(
                 NonMutatingUseContext::Copy | NonMutatingUseContext::Move,
-            ) => {
+            ) => match &mut self.locals[local] {
+                LocalKind::ZST => {}
+                LocalKind::Memory => {}
+                LocalKind::SSA(def) if def.dominates(location, &self.dominators) => {}
                 // Reads from uninitialized variables (e.g., in dead code, after
                 // optimizations) require locals to be in (uninitialized) memory.
                 // N.B., there can be uninitialized reads of a local visited after
                 // an assignment to that local, if they happen on disjoint paths.
-                let ssa_read = match self.first_assignment(local) {
-                    Some(assignment_location) => {
-                        assignment_location.dominates(location, &self.dominators)
-                    }
-                    None => {
-                        debug!("No first assignment found for {:?}", local);
-                        // We have not seen any assignment to the local yet,
-                        // but before marking not_ssa, check if it is a ZST,
-                        // in which case we don't need to initialize the local.
-                        let ty = self.fx.mir.local_decls[local].ty;
-                        let ty = self.fx.monomorphize(ty);
-
-                        let is_zst = self.fx.cx.layout_of(ty).is_zst();
-                        debug!("is_zst: {}", is_zst);
-                        is_zst
-                    }
-                };
-                if !ssa_read {
-                    self.not_ssa(local);
+                kind @ (LocalKind::Unused | LocalKind::SSA(_)) => {
+                    *kind = LocalKind::Memory;
                 }
-            }
+            },
 
             PlaceContext::MutatingUse(
                 MutatingUseContext::Store
@@ -246,16 +225,18 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
                 | NonMutatingUseContext::AddressOf
                 | NonMutatingUseContext::Projection,
             ) => {
-                self.not_ssa(local);
+                self.locals[local] = LocalKind::Memory;
             }
 
             PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
-                let ty = self.fx.mir.local_decls[local].ty;
-                let ty = self.fx.monomorphize(ty);
-
-                // Only need the place if we're actually dropping it.
-                if self.fx.cx.type_needs_drop(ty) {
-                    self.not_ssa(local);
+                let kind = &mut self.locals[local];
+                if *kind != LocalKind::Memory {
+                    let ty = self.fx.mir.local_decls[local].ty;
+                    let ty = self.fx.monomorphize(ty);
+                    if self.fx.cx.type_needs_drop(ty) {
+                        // Only need the place if we're actually dropping it.
+                        *kind = LocalKind::Memory;
+                    }
                 }
             }
         }
index 93200bd1f264a4465faf3e8e1366a6779f3fa1a4..b584801a62de2cb91cefe79303dae8bb58d6fb3b 100644 (file)
@@ -260,7 +260,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, 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 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, 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);
@@ -332,7 +333,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let fn_abi = FnAbi::of_instance(&bx, virtual_drop, &[]);
                 let vtable = args[1];
                 args = &args[..1];
-                (meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_abi), fn_abi)
+                (
+                    meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
+                        .get_fn(&mut bx, vtable, &fn_abi),
+                    fn_abi,
+                )
             }
             _ => (bx.get_fn_addr(drop_fn), FnAbi::of_instance(&bx, drop_fn, &[])),
         };
@@ -1082,15 +1087,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         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 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 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 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             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..3e8386bc88feda1facf37b2d13ed2765d2147f53 100644 (file)
@@ -90,10 +90,10 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                     Abi::ScalarPair(ref a, _) => a,
                     _ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout),
                 };
-                let a = Scalar::from(Pointer::new(
-                    bx.tcx().create_memory_alloc(data),
-                    Size::from_bytes(start),
-                ));
+                let a = Scalar::from_pointer(
+                    Pointer::new(bx.tcx().create_memory_alloc(data), Size::from_bytes(start)),
+                    &bx.tcx(),
+                );
                 let a_llval = bx.scalar_to_backend(
                     a,
                     a_scalar,
@@ -289,6 +289,14 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<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 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, 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 @@ pub trait BuilderMethods<'a, 'tcx>:
     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 6b58dea794bcbca7099085b56c6d5ee99af59cb7..20f6618712327870212d734e8ca15062b03aacbf 100644 (file)
@@ -26,6 +26,8 @@ pub trait ConstMethods<'tcx>: BackendTypes {
     fn const_to_opt_uint(&self, v: Self::Value) -> Option<u64>;
     fn const_to_opt_u128(&self, v: Self::Value, sign_ext: bool) -> Option<u128>;
 
+    fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value;
+
     fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: Self::Type) -> Self::Value;
     fn from_const_alloc(
         &self,
index 6fff64bfcb6c5a4bdce2848d784b39e81ce866fb..46f2adbe55209aa7aea62dbc7c8e2e13e346cf4b 100644 (file)
@@ -16,7 +16,7 @@ pub trait MiscMethods<'tcx>: BackendTypes {
     fn sess(&self) -> &Session;
     fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx>;
     fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
-    fn set_frame_pointer_elimination(&self, llfn: Self::Function);
+    fn set_frame_pointer_type(&self, llfn: Self::Function);
     fn apply_target_cpu_attr(&self, llfn: Self::Function);
     fn create_used_variable(&self);
     /// Declares the extern "C" main function for the entry point. Returns None if the symbol already exists.
index c35a164bb33423e0f34b233523d756a8aa7bcf31..112b94f6e0ebc6031d0dc62a32b37116bd199bf2 100644 (file)
@@ -17,7 +17,6 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_graphviz = { path = "../rustc_graphviz" }
 cfg-if = "0.1.2"
-crossbeam-utils = { version = "0.8", features = ["nightly"] }
 stable_deref_trait = "1.0.0"
 rayon = { version = "0.3.1", package = "rustc-rayon" }
 rayon-core = { version = "0.3.1", package = "rustc-rayon-core" }
index 26b90ebfd5f117076cd4a99d4f1c772e0e1a8e5d..677ccb31454ea83795fcb9b6a5db57bc771d40b0 100644 (file)
@@ -3,8 +3,6 @@
 /// Basically a workaround; see [this comment] for details.
 ///
 /// [this comment]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999
-// FIXME(eddyb) false positive, the lifetime parameter is "phantom" but needed.
-#[allow(unused_lifetimes)]
 pub trait Captures<'a> {}
 
 impl<'a, T: ?Sized> Captures<'a> for T {}
index 16151e9dca5e039bc832b83246e3afb2ed19642d..041d52aa20abd6cef4d45258c71f4109f262c82e 100644 (file)
@@ -7,23 +7,26 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(allow_internal_unstable)]
 #![feature(array_windows)]
+#![feature(associated_type_bounds)]
+#![feature(auto_traits)]
+#![feature(bool_to_option)]
+#![feature(const_panic)]
 #![feature(control_flow_enum)]
+#![feature(core_intrinsics)]
+#![feature(extend_one)]
+#![feature(hash_raw_entry)]
 #![feature(in_band_lifetimes)]
+#![feature(iter_map_while)]
+#![feature(maybe_uninit_uninit_array)]
 #![feature(min_specialization)]
-#![feature(auto_traits)]
+#![feature(min_type_alias_impl_trait)]
+#![feature(new_uninit)]
 #![feature(nll)]
-#![feature(allow_internal_unstable)]
-#![feature(hash_raw_entry)]
-#![feature(core_intrinsics)]
+#![feature(once_cell)]
 #![feature(test)]
-#![feature(associated_type_bounds)]
 #![feature(thread_id_value)]
-#![feature(extend_one)]
-#![feature(const_panic)]
-#![feature(new_uninit)]
-#![feature(once_cell)]
-#![feature(maybe_uninit_uninit_array)]
 #![allow(rustc::default_hash_types)]
 #![deny(unaligned_references)]
 
index 05b1a85381f454ff880d854199f102924cbe00d3..25b7a84b3a06929fa5c0df1c8f1c3f92848727e0 100644 (file)
@@ -418,6 +418,7 @@ impl<O: ForestObligation> ObligationForest<O> {
     /// be called in a loop until `outcome.stalled` is false.
     ///
     /// This _cannot_ be unrolled (presently, at least).
+    #[inline(never)]
     pub fn process_obligations<P, OUT>(&mut self, processor: &mut P) -> OUT
     where
         P: ObligationProcessor<Obligation = O>,
@@ -671,6 +672,7 @@ impl<O: ForestObligation> ObligationForest<O> {
         self.reused_node_vec = node_rewrites;
     }
 
+    #[inline(never)]
     fn apply_rewrites(&mut self, node_rewrites: &[usize]) {
         let orig_nodes_len = node_rewrites.len();
 
index 51f851dc9469fe10dc0a07fea8d21e20c8a71b4a..ef101c56ab578716525fb042b72eb0b056988728 100644 (file)
@@ -94,31 +94,34 @@ use std::process;
 use std::sync::Arc;
 use std::time::{Duration, Instant};
 
-use measureme::{EventId, EventIdBuilder, Profiler, SerializableString, StringId};
+pub use measureme::EventId;
+use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
 use parking_lot::RwLock;
 
 bitflags::bitflags! {
     struct EventFilter: u32 {
-        const GENERIC_ACTIVITIES = 1 << 0;
-        const QUERY_PROVIDERS    = 1 << 1;
-        const QUERY_CACHE_HITS   = 1 << 2;
-        const QUERY_BLOCKED      = 1 << 3;
-        const INCR_CACHE_LOADS   = 1 << 4;
+        const GENERIC_ACTIVITIES  = 1 << 0;
+        const QUERY_PROVIDERS     = 1 << 1;
+        const QUERY_CACHE_HITS    = 1 << 2;
+        const QUERY_BLOCKED       = 1 << 3;
+        const INCR_CACHE_LOADS    = 1 << 4;
 
-        const QUERY_KEYS         = 1 << 5;
-        const FUNCTION_ARGS      = 1 << 6;
-        const LLVM               = 1 << 7;
+        const QUERY_KEYS          = 1 << 5;
+        const FUNCTION_ARGS       = 1 << 6;
+        const LLVM                = 1 << 7;
+        const INCR_RESULT_HASHING = 1 << 8;
 
         const DEFAULT = Self::GENERIC_ACTIVITIES.bits |
                         Self::QUERY_PROVIDERS.bits |
                         Self::QUERY_BLOCKED.bits |
-                        Self::INCR_CACHE_LOADS.bits;
+                        Self::INCR_CACHE_LOADS.bits |
+                        Self::INCR_RESULT_HASHING.bits;
 
         const ARGS = Self::QUERY_KEYS.bits | Self::FUNCTION_ARGS.bits;
     }
 }
 
-// keep this in sync with the `-Z self-profile-events` help message in librustc_session/options.rs
+// keep this in sync with the `-Z self-profile-events` help message in rustc_session/options.rs
 const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[
     ("none", EventFilter::empty()),
     ("all", EventFilter::all()),
@@ -132,6 +135,7 @@ const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[
     ("function-args", EventFilter::FUNCTION_ARGS),
     ("args", EventFilter::ARGS),
     ("llvm", EventFilter::LLVM),
+    ("incr-result-hashing", EventFilter::INCR_RESULT_HASHING),
 ];
 
 /// Something that uniquely identifies a query invocation.
@@ -248,6 +252,15 @@ impl SelfProfilerRef {
         })
     }
 
+    /// Start profiling with some event filter for a given event. Profiling continues until the
+    /// TimingGuard returned from this call is dropped.
+    #[inline(always)]
+    pub fn generic_activity_with_event_id(&self, event_id: EventId) -> TimingGuard<'_> {
+        self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| {
+            TimingGuard::start(profiler, profiler.generic_activity_event_kind, event_id)
+        })
+    }
+
     /// Start profiling a generic activity. Profiling continues until the
     /// TimingGuard returned from this call is dropped.
     #[inline(always)]
@@ -337,6 +350,19 @@ impl SelfProfilerRef {
         })
     }
 
+    /// Start profiling how long it takes to hash query results for incremental compilation.
+    /// Profiling continues until the TimingGuard returned from this call is dropped.
+    #[inline(always)]
+    pub fn incr_result_hashing(&self) -> TimingGuard<'_> {
+        self.exec(EventFilter::INCR_RESULT_HASHING, |profiler| {
+            TimingGuard::start(
+                profiler,
+                profiler.incremental_result_hashing_event_kind,
+                EventId::INVALID,
+            )
+        })
+    }
+
     #[inline(always)]
     fn instant_query_event(
         &self,
@@ -364,6 +390,14 @@ impl SelfProfilerRef {
         }
     }
 
+    /// Gets a `StringId` for the given string. This method makes sure that
+    /// any strings going through it will only be allocated once in the
+    /// profiling data.
+    /// Returns `None` if the self-profiling is not enabled.
+    pub fn get_or_alloc_cached_string(&self, s: &str) -> Option<StringId> {
+        self.profiler.as_ref().map(|p| p.get_or_alloc_cached_string(s))
+    }
+
     #[inline]
     pub fn enabled(&self) -> bool {
         self.profiler.is_some()
@@ -388,6 +422,7 @@ pub struct SelfProfiler {
     query_event_kind: StringId,
     generic_activity_event_kind: StringId,
     incremental_load_result_event_kind: StringId,
+    incremental_result_hashing_event_kind: StringId,
     query_blocked_event_kind: StringId,
     query_cache_hit_event_kind: StringId,
 }
@@ -408,6 +443,8 @@ impl SelfProfiler {
         let query_event_kind = profiler.alloc_string("Query");
         let generic_activity_event_kind = profiler.alloc_string("GenericActivity");
         let incremental_load_result_event_kind = profiler.alloc_string("IncrementalLoadResult");
+        let incremental_result_hashing_event_kind =
+            profiler.alloc_string("IncrementalResultHashing");
         let query_blocked_event_kind = profiler.alloc_string("QueryBlocked");
         let query_cache_hit_event_kind = profiler.alloc_string("QueryCacheHit");
 
@@ -451,6 +488,7 @@ impl SelfProfiler {
             query_event_kind,
             generic_activity_event_kind,
             incremental_load_result_event_kind,
+            incremental_result_hashing_event_kind,
             query_blocked_event_kind,
             query_cache_hit_event_kind,
         })
index 01cd1cec9245563d6d1ff44c5e973d98e96fcd77..e92db9ea128057f4c82556a55ff27d3d728aafb0 100644 (file)
@@ -1,6 +1,5 @@
 //! A variant of `SortedMap` that preserves insertion order.
 
-use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
 use std::iter::FromIterator;
 
@@ -76,11 +75,7 @@ impl<I: Idx, K: Ord, V> SortedIndexMultiMap<I, K, V> {
     ///
     /// If there are multiple items that are equivalent to `key`, they will be yielded in
     /// insertion order.
-    pub fn get_by_key<Q: 'a>(&'a self, key: &Q) -> impl 'a + Iterator<Item = &'a V>
-    where
-        Q: Ord + ?Sized,
-        K: Borrow<Q>,
-    {
+    pub fn get_by_key(&'a self, key: K) -> impl 'a + Iterator<Item = &'a V> {
         self.get_by_key_enumerated(key).map(|(_, v)| v)
     }
 
@@ -89,77 +84,12 @@ impl<I: Idx, K: Ord, V> SortedIndexMultiMap<I, K, V> {
     ///
     /// If there are multiple items that are equivalent to `key`, they will be yielded in
     /// insertion order.
-    pub fn get_by_key_enumerated<Q>(&self, key: &Q) -> impl '_ + Iterator<Item = (I, &V)>
-    where
-        Q: Ord + ?Sized,
-        K: Borrow<Q>,
-    {
-        // FIXME: This should be in the standard library as `equal_range`. See rust-lang/rfcs#2184.
-        match self.binary_search_idx(key) {
-            Err(_) => self.idxs_to_items_enumerated(&[]),
-
-            Ok(idx) => {
-                let start = self.find_lower_bound(key, idx);
-                let end = self.find_upper_bound(key, idx);
-                self.idxs_to_items_enumerated(&self.idx_sorted_by_item_key[start..end])
-            }
-        }
-    }
-
-    fn binary_search_idx<Q>(&self, key: &Q) -> Result<usize, usize>
-    where
-        Q: Ord + ?Sized,
-        K: Borrow<Q>,
-    {
-        self.idx_sorted_by_item_key.binary_search_by(|&idx| self.items[idx].0.borrow().cmp(key))
-    }
-
-    /// Returns the index into the `idx_sorted_by_item_key` array of the first item equal to
-    /// `key`.
-    ///
-    /// `initial` must be an index into that same array for an item that is equal to `key`.
-    fn find_lower_bound<Q>(&self, key: &Q, initial: usize) -> usize
-    where
-        Q: Ord + ?Sized,
-        K: Borrow<Q>,
-    {
-        debug_assert!(self.items[self.idx_sorted_by_item_key[initial]].0.borrow() == key);
-
-        // FIXME: At present, this uses linear search, meaning lookup is only `O(log n)` if duplicate
-        // entries are rare. It would be better to start with a linear search for the common case but
-        // fall back to an exponential search if many duplicates are found. This applies to
-        // `upper_bound` as well.
-        let mut start = initial;
-        while start != 0 && self.items[self.idx_sorted_by_item_key[start - 1]].0.borrow() == key {
-            start -= 1;
-        }
-
-        start
-    }
-
-    /// Returns the index into the `idx_sorted_by_item_key` array of the first item greater than
-    /// `key`, or `self.len()` if no such item exists.
-    ///
-    /// `initial` must be an index into that same array for an item that is equal to `key`.
-    fn find_upper_bound<Q>(&self, key: &Q, initial: usize) -> usize
-    where
-        Q: Ord + ?Sized,
-        K: Borrow<Q>,
-    {
-        debug_assert!(self.items[self.idx_sorted_by_item_key[initial]].0.borrow() == key);
-
-        // See the FIXME for `find_lower_bound`.
-        let mut end = initial + 1;
-        let len = self.items.len();
-        while end < len && self.items[self.idx_sorted_by_item_key[end]].0.borrow() == key {
-            end += 1;
-        }
-
-        end
-    }
-
-    fn idxs_to_items_enumerated(&'a self, idxs: &'a [I]) -> impl 'a + Iterator<Item = (I, &'a V)> {
-        idxs.iter().map(move |&idx| (idx, &self.items[idx].1))
+    pub fn get_by_key_enumerated(&'a self, key: K) -> impl '_ + Iterator<Item = (I, &V)> {
+        let lower_bound = self.idx_sorted_by_item_key.partition_point(|&i| self.items[i].0 < key);
+        self.idx_sorted_by_item_key[lower_bound..].iter().map_while(move |&i| {
+            let (k, v) = &self.items[i];
+            (k == &key).then_some((i, v))
+        })
     }
 }
 
index 7d91e1fdcef6a3f1db929218752e9a8cfa316416..1e977d709f1cdae35699717160e0c29b97c973da 100644 (file)
@@ -14,11 +14,11 @@ fn test_sorted_index_multi_map() {
     }
 
     // `get_by_key` works.
-    assert_eq!(set.get_by_key(&3).copied().collect::<Vec<_>>(), vec![0]);
-    assert!(set.get_by_key(&4).next().is_none());
+    assert_eq!(set.get_by_key(3).copied().collect::<Vec<_>>(), vec![0]);
+    assert!(set.get_by_key(4).next().is_none());
 
     // `get_by_key` returns items in insertion order.
-    let twos: Vec<_> = set.get_by_key_enumerated(&2).collect();
+    let twos: Vec<_> = set.get_by_key_enumerated(2).collect();
     let idxs: Vec<usize> = twos.iter().map(|(i, _)| *i).collect();
     let values: Vec<usize> = twos.iter().map(|(_, &v)| v).collect();
 
index 73b04d3329cb8e79e9c9a3c5d63f5f178b307e27..cc7ec9432faed31803376bbc5113cebd642229ca 100644 (file)
@@ -1,6 +1,7 @@
 use std::borrow::Borrow;
+use std::fmt::Debug;
 use std::iter::FromIterator;
-use std::slice::{Iter, IterMut};
+use std::slice::Iter;
 use std::vec::IntoIter;
 
 use crate::stable_hasher::{HashStable, StableHasher};
@@ -12,7 +13,8 @@ pub struct VecMap<K, V>(Vec<(K, V)>);
 
 impl<K, V> VecMap<K, V>
 where
-    K: PartialEq,
+    K: Debug + PartialEq,
+    V: Debug,
 {
     pub fn new() -> Self {
         VecMap(Default::default())
@@ -37,14 +39,31 @@ where
         self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1)
     }
 
-    /// Returns the value corresponding to the supplied predicate filter.
+    /// Returns the any value corresponding to the supplied predicate filter.
     ///
     /// The supplied predicate will be applied to each (key, value) pair and it will return a
     /// reference to the values where the predicate returns `true`.
-    pub fn get_by(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> {
+    pub fn any_value_matching(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> {
         self.0.iter().find(|kv| predicate(kv)).map(|elem| &elem.1)
     }
 
+    /// Returns the value corresponding to the supplied predicate filter. It crashes if there's
+    /// more than one matching element.
+    ///
+    /// The supplied predicate will be applied to each (key, value) pair and it will return a
+    /// reference to the value where the predicate returns `true`.
+    pub fn get_value_matching(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> {
+        let mut filter = self.0.iter().filter(|kv| predicate(kv));
+        let (_, value) = filter.next()?;
+        // This should return just one element, otherwise it's a bug
+        assert!(
+            filter.next().is_none(),
+            "Collection {:?} should have just one matching element",
+            self
+        );
+        Some(value)
+    }
+
     /// Returns `true` if the map contains a value for the specified key.
     ///
     /// The key may be any borrowed form of the map's key type,
@@ -67,9 +86,13 @@ where
         self.into_iter()
     }
 
-    pub fn iter_mut(&mut self) -> IterMut<'_, (K, V)> {
+    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)> {
         self.into_iter()
     }
+
+    pub fn retain(&mut self, f: impl Fn(&(K, V)) -> bool) {
+        self.0.retain(f)
+    }
 }
 
 impl<K, V> Default for VecMap<K, V> {
@@ -108,12 +131,12 @@ impl<'a, K, V> IntoIterator for &'a VecMap<K, V> {
 }
 
 impl<'a, K, V> IntoIterator for &'a mut VecMap<K, V> {
-    type Item = &'a mut (K, V);
-    type IntoIter = IterMut<'a, (K, V)>;
+    type Item = (&'a K, &'a mut V);
+    type IntoIter = impl Iterator<Item = Self::Item>;
 
     #[inline]
     fn into_iter(self) -> Self::IntoIter {
-        self.0.iter_mut()
+        self.0.iter_mut().map(|(k, v)| (&*k, v))
     }
 }
 
@@ -127,13 +150,15 @@ impl<K, V> IntoIterator for VecMap<K, V> {
     }
 }
 
-impl<K, V> Extend<(K, V)> for VecMap<K, V> {
+impl<K: PartialEq + Debug, V: Debug> Extend<(K, V)> for VecMap<K, V> {
     fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
-        self.0.extend(iter);
+        for (k, v) in iter {
+            self.insert(k, v);
+        }
     }
 
-    fn extend_one(&mut self, item: (K, V)) {
-        self.0.extend_one(item);
+    fn extend_one(&mut self, (k, v): (K, V)) {
+        self.insert(k, v);
     }
 
     fn extend_reserve(&mut self, additional: usize) {
index c521f2041d8919ceadb8c84242e951c5fbc8ead0..93c6ec04e4fd676696075b83f93ff636dfff699a 100644 (file)
@@ -34,8 +34,6 @@ rustc_interface = { path = "../rustc_interface" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_span = { path = "../rustc_span" }
-rustc_mir_build = { path = "../rustc_mir_build" }
-rustc_typeck = { path = "../rustc_typeck" }
 
 [target.'cfg(windows)'.dependencies]
 winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] }
index b943977e4c2bb36c7518a4bcdae5c989a4681a49..326fefa59ab0576606321958686833549d2bd9f5 100644 (file)
@@ -29,7 +29,7 @@ use rustc_middle::middle::cstore::MetadataLoader;
 use rustc_save_analysis as save;
 use rustc_save_analysis::DumpHandler;
 use rustc_serialize::json::{self, ToJson};
-use rustc_session::config::nightly_options;
+use rustc_session::config::{nightly_options, CG_OPTIONS, DB_OPTIONS};
 use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest, TrimmedDefPaths};
 use rustc_session::getopts;
 use rustc_session::lint::{Lint, LintId};
@@ -46,7 +46,6 @@ use std::ffi::OsString;
 use std::fs;
 use std::io::{self, Read, Write};
 use std::lazy::SyncLazy;
-use std::mem;
 use std::panic::{self, catch_unwind};
 use std::path::PathBuf;
 use std::process::{self, Command, Stdio};
@@ -316,12 +315,12 @@ fn run_compiler(
 
             if let Some(ppm) = &sess.opts.pretty {
                 if ppm.needs_ast_map() {
+                    let expanded_crate = queries.expansion()?.peek().0.clone();
                     queries.global_ctxt()?.peek_mut().enter(|tcx| {
-                        let expanded_crate = queries.expansion()?.take().0;
                         pretty::print_after_hir_lowering(
                             tcx,
                             compiler.input(),
-                            &expanded_crate,
+                            &*expanded_crate,
                             *ppm,
                             compiler.output_file().as_ref().map(|p| &**p),
                         );
@@ -377,12 +376,6 @@ fn run_compiler(
 
             queries.global_ctxt()?;
 
-            // Drop AST after creating GlobalCtxt to free memory
-            {
-                let _timer = sess.prof.generic_activity("drop_ast");
-                mem::drop(queries.expansion()?.take());
-            }
-
             if sess.opts.debugging_opts.no_analysis || sess.opts.debugging_opts.ast_json {
                 return early_exit();
             }
@@ -528,8 +521,12 @@ fn stderr_isatty() -> bool {
 }
 
 fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
-    let normalised =
-        if code.starts_with('E') { code.to_string() } else { format!("E{0:0>4}", code) };
+    let upper_cased_code = code.to_ascii_uppercase();
+    let normalised = if upper_cased_code.starts_with('E') {
+        upper_cased_code
+    } else {
+        format!("E{0:0>4}", code)
+    };
     match registry.try_find_description(&normalised) {
         Ok(Some(description)) => {
             let mut is_in_code_block = false;
@@ -1013,9 +1010,18 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
     for option in config::rustc_optgroups() {
         (option.apply)(&mut options);
     }
-    let matches = options
-        .parse(args)
-        .unwrap_or_else(|f| early_error(ErrorOutputType::default(), &f.to_string()));
+    let matches = options.parse(args).unwrap_or_else(|e| {
+        let msg = match e {
+            getopts::Fail::UnrecognizedOption(ref opt) => CG_OPTIONS
+                .iter()
+                .map(|&(name, ..)| ('C', name))
+                .chain(DB_OPTIONS.iter().map(|&(name, ..)| ('Z', name)))
+                .find(|&(_, name)| *opt == name.replace("_", "-"))
+                .map(|(flag, _)| format!("{}. Did you mean `-{} {}`?", e, flag, opt)),
+            _ => None,
+        };
+        early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string()));
+    });
 
     // For all options we just parsed, we check a few aspects:
     //
@@ -1163,23 +1169,26 @@ pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
 static DEFAULT_HOOK: SyncLazy<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
     SyncLazy::new(|| {
         let hook = panic::take_hook();
-        panic::set_hook(Box::new(|info| report_ice(info, BUG_REPORT_URL)));
+        panic::set_hook(Box::new(|info| {
+            // Invoke the default handler, which prints the actual panic message and optionally a backtrace
+            (*DEFAULT_HOOK)(info);
+
+            // Separate the output with an empty line
+            eprintln!();
+
+            // Print the ICE message
+            report_ice(info, BUG_REPORT_URL);
+        }));
         hook
     });
 
-/// Prints the ICE message, including backtrace and query stack.
+/// Prints the ICE message, including query stack, but without backtrace.
 ///
 /// The message will point the user at `bug_report_url` to report the ICE.
 ///
 /// When `install_ice_hook` is called, this function will be called as the panic
 /// hook.
 pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
-    // Invoke the default handler, which prints the actual panic message and optionally a backtrace
-    (*DEFAULT_HOOK)(info);
-
-    // Separate the output with an empty line
-    eprintln!();
-
     let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
         rustc_errors::ColorConfig::Auto,
         None,
@@ -1296,10 +1305,60 @@ pub fn init_env_logger(env: &str) {
     tracing::subscriber::set_global_default(subscriber).unwrap();
 }
 
+#[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))]
+mod signal_handler {
+    extern "C" {
+        fn backtrace_symbols_fd(
+            buffer: *const *mut libc::c_void,
+            size: libc::c_int,
+            fd: libc::c_int,
+        );
+    }
+
+    extern "C" fn print_stack_trace(_: libc::c_int) {
+        const MAX_FRAMES: usize = 256;
+        static mut STACK_TRACE: [*mut libc::c_void; MAX_FRAMES] =
+            [std::ptr::null_mut(); MAX_FRAMES];
+        unsafe {
+            let depth = libc::backtrace(STACK_TRACE.as_mut_ptr(), MAX_FRAMES as i32);
+            if depth == 0 {
+                return;
+            }
+            backtrace_symbols_fd(STACK_TRACE.as_ptr(), depth, 2);
+        }
+    }
+
+    // When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
+    // process, print a stack trace and then exit.
+    pub(super) fn install() {
+        unsafe {
+            const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024;
+            let mut alt_stack: libc::stack_t = std::mem::zeroed();
+            alt_stack.ss_sp =
+                std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap())
+                    as *mut libc::c_void;
+            alt_stack.ss_size = ALT_STACK_SIZE;
+            libc::sigaltstack(&mut alt_stack, std::ptr::null_mut());
+
+            let mut sa: libc::sigaction = std::mem::zeroed();
+            sa.sa_sigaction = print_stack_trace as libc::sighandler_t;
+            sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK;
+            libc::sigemptyset(&mut sa.sa_mask);
+            libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut());
+        }
+    }
+}
+
+#[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))]
+mod signal_handler {
+    pub(super) fn install() {}
+}
+
 pub fn main() -> ! {
     let start_time = Instant::now();
     let start_rss = get_resident_set_size();
     init_rustc_env_logger();
+    signal_handler::install();
     let mut callbacks = TimePassesCallbacks::default();
     install_ice_hook();
     let exit_code = catch_with_exit_code(|| {
index a2b4f3fcf734a713756ccfabe4800e3632abd567..bf131914b97cfe7d043c702b1453594031148847 100644 (file)
@@ -293,18 +293,6 @@ struct TypedAnnotation<'tcx> {
     maybe_typeck_results: Cell<Option<&'tcx ty::TypeckResults<'tcx>>>,
 }
 
-impl<'tcx> TypedAnnotation<'tcx> {
-    /// Gets the type-checking results for the current body.
-    /// As this will ICE if called outside bodies, only call when working with
-    /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
-    #[track_caller]
-    fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> {
-        self.maybe_typeck_results
-            .get()
-            .expect("`TypedAnnotation::typeck_results` called outside of body")
-    }
-}
-
 impl<'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'tcx> {
     fn sess(&self) -> &Session {
         &self.tcx.sess
@@ -336,10 +324,20 @@ impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> {
     }
     fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
         if let pprust_hir::AnnNode::Expr(expr) = node {
-            s.s.space();
-            s.s.word("as");
-            s.s.space();
-            s.s.word(self.typeck_results().expr_ty(expr).to_string());
+            let typeck_results = self.maybe_typeck_results.get().or_else(|| {
+                self.tcx
+                    .hir()
+                    .maybe_body_owned_by(self.tcx.hir().local_def_id_to_hir_id(expr.hir_id.owner))
+                    .map(|body_id| self.tcx.typeck_body(body_id))
+            });
+
+            if let Some(typeck_results) = typeck_results {
+                s.s.space();
+                s.s.word("as");
+                s.s.space();
+                s.s.word(typeck_results.expr_ty(expr).to_string());
+            }
+
             s.pclose();
         }
     }
index f10efd832361c252715a628de77127f7f4dae5b7..1aa5f9959744d975a15b344f07eadb8fcac0060e 100644 (file)
@@ -361,6 +361,7 @@ E0626: include_str!("./error_codes/E0626.md"),
 E0627: include_str!("./error_codes/E0627.md"),
 E0628: include_str!("./error_codes/E0628.md"),
 E0631: include_str!("./error_codes/E0631.md"),
+E0632: include_str!("./error_codes/E0632.md"),
 E0633: include_str!("./error_codes/E0633.md"),
 E0634: include_str!("./error_codes/E0634.md"),
 E0635: include_str!("./error_codes/E0635.md"),
@@ -417,6 +418,7 @@ E0716: include_str!("./error_codes/E0716.md"),
 E0718: include_str!("./error_codes/E0718.md"),
 E0719: include_str!("./error_codes/E0719.md"),
 E0720: include_str!("./error_codes/E0720.md"),
+E0722: include_str!("./error_codes/E0722.md"),
 E0724: include_str!("./error_codes/E0724.md"),
 E0725: include_str!("./error_codes/E0725.md"),
 E0727: include_str!("./error_codes/E0727.md"),
@@ -448,6 +450,7 @@ E0753: include_str!("./error_codes/E0753.md"),
 E0754: include_str!("./error_codes/E0754.md"),
 E0755: include_str!("./error_codes/E0755.md"),
 E0756: include_str!("./error_codes/E0756.md"),
+E0757: include_str!("./error_codes/E0757.md"),
 E0758: include_str!("./error_codes/E0758.md"),
 E0759: include_str!("./error_codes/E0759.md"),
 E0760: include_str!("./error_codes/E0760.md"),
@@ -609,7 +612,7 @@ E0783: include_str!("./error_codes/E0783.md"),
 //  E0540, // multiple rustc_deprecated attributes
     E0544, // multiple stability levels
 //  E0548, // replaced with a generic attribute input check
-    E0553, // multiple rustc_const_unstable attributes
+//  E0553, // multiple rustc_const_unstable attributes
 //  E0555, // replaced with a generic attribute input check
 //  E0558, // replaced with a generic attribute input check
 //  E0563, // cannot determine a type for this `impl Trait` removed in 6383de15
@@ -620,12 +623,9 @@ E0783: include_str!("./error_codes/E0783.md"),
 //  E0612, // merged into E0609
 //  E0613, // Removed (merged with E0609)
     E0625, // thread-local statics cannot be accessed at compile-time
-    E0629, // missing 'feature' (rustc_const_unstable)
-    // rustc_const_unstable attribute must be paired with stable/unstable
-    // attribute
-    E0630,
-    E0632, // cannot provide explicit generic arguments when `impl Trait` is
-           // used in argument position
+//  E0629, // missing 'feature' (rustc_const_unstable)
+//  E0630, // rustc_const_unstable attribute must be paired with stable/unstable
+           // attribute
     E0640, // infer outlives requirements
 //  E0645, // trait aliases not finished
     E0667, // `impl Trait` in projections
@@ -636,10 +636,8 @@ E0783: include_str!("./error_codes/E0783.md"),
     E0711, // a feature has been declared with conflicting stability attributes
     E0717, // rustc_promotable without stability attribute
 //  E0721, // `await` keyword
-    E0722, // Malformed `#[optimize]` attribute
 //    E0723, unstable feature in `const` context
     E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
 //  E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
-    E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]`
     E0772, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
 }
index 42baa65bf9faf77782a73dde922f048c23183769..ec86ec44ece8e2e9a8a03ff23b600f21a847f710 100644 (file)
@@ -1,4 +1,4 @@
-An invalid number of type parameters was given to an intrinsic function.
+An invalid number of generic parameters was passed to an intrinsic function.
 
 Erroneous code example:
 
index 0dcc3b62b4b2f66258b154a8b443989abef6bb49..e891129efa0e7ef34ca619133537d66e8be0a3ad 100644 (file)
@@ -21,7 +21,7 @@ static FOO: Foo = Foo { field1: (DropType::A, DropType::A).1 }; // error!
 The problem here is that if the given type or one of its fields implements the
 `Drop` trait, this `Drop` implementation cannot be called within a const
 context since it may run arbitrary, non-const-checked code. To prevent this
-issue, ensure all values with custom a custom `Drop` implementation escape the
+issue, ensure all values with a custom `Drop` implementation escape the
 initializer.
 
 ```
index 33572fca6a3e8a308243444de3e7c32007f5230f..91865907bf271fdc296b706ad03783ffffc23cda 100644 (file)
@@ -39,3 +39,16 @@ fn main() {
     let _value = array[0].clone();
 }
 ```
+
+If you really want to move the value out, you can use a destructuring array
+pattern to move it:
+
+```
+struct NonCopy;
+
+fn main() {
+    let array = [NonCopy; 1];
+    // Destructuring the array
+    let [_value] = array;
+}
+```
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
diff --git a/compiler/rustc_error_codes/src/error_codes/E0632.md b/compiler/rustc_error_codes/src/error_codes/E0632.md
new file mode 100644 (file)
index 0000000..40840e8
--- /dev/null
@@ -0,0 +1,25 @@
+An explicit generic argument was provided when calling a function that
+uses `impl Trait` in argument position.
+
+Erroneous code example:
+
+```compile_fail,E0632
+fn foo<T: Copy>(a: T, b: impl Clone) {}
+
+foo::<i32>(0i32, "abc".to_string());
+```
+
+Either all generic arguments should be inferred at the call site, or
+the function definition should use an explicit generic type parameter
+instead of `impl Trait`. Example:
+
+```
+fn foo<T: Copy>(a: T, b: impl Clone) {}
+fn bar<T: Copy, U: Clone>(a: T, b: U) {}
+
+foo(0i32, "abc".to_string());
+
+bar::<i32, String>(0i32, "abc".to_string());
+bar::<_, _>(0i32, "abc".to_string());
+bar(0i32, "abc".to_string());
+```
index 1673456580a85ad33c61a5b8447ac0604e9f243e..ba706ad2b020b2108dc0594ccc752f4161dd2a25 100644 (file)
@@ -1,19 +1,19 @@
-A struct with the representation hint `repr(transparent)` had zero or more than
-one fields that were not guaranteed to be zero-sized.
+A struct with the representation hint `repr(transparent)` had two or more fields
+that were not guaranteed to be zero-sized.
 
 Erroneous code example:
 
 ```compile_fail,E0690
 #[repr(transparent)]
-struct LengthWithUnit<U> { // error: transparent struct needs exactly one
+struct LengthWithUnit<U> { // error: transparent struct needs at most one
     value: f32,            //        non-zero-sized field, but has 2
     unit: U,
 }
 ```
 
 Because transparent structs are represented exactly like one of their fields at
-run time, said field must be uniquely determined. If there is no field, or if
-there are multiple fields, it is not clear how the struct should be represented.
+run time, said field must be uniquely determined. If there are multiple fields,
+it is not clear how the struct should be represented.
 Note that fields of zero-sized types (e.g., `PhantomData`) can also exist
 alongside the field that contains the actual data, they do not count for this
 error. When generic types are involved (as in the above example), an error is
index c6d0337ddda56d0c10efa53e415cb69d9eb5b35a..c3546cd744f7b6be9527aa18cfc3eb1d0805aa74 100644 (file)
@@ -14,14 +14,16 @@ Here, the expression `&foo()` is borrowing the expression `foo()`. As `foo()` is
 a call to a function, and not the name of a variable, this creates a
 **temporary** -- that temporary stores the return value from `foo()` so that it
 can be borrowed. You could imagine that `let p = bar(&foo());` is equivalent to
-this:
+the following, which uses an explicit temporary variable.
+
+Erroneous code example:
 
 ```compile_fail,E0597
 # fn foo() -> i32 { 22 }
 # fn bar(x: &i32) -> &i32 { x }
 let p = {
   let tmp = foo(); // the temporary
-  bar(&tmp)
+  bar(&tmp) // error: `tmp` does not live long enough
 }; // <-- tmp is freed as we exit this block
 let q = p;
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0722.md b/compiler/rustc_error_codes/src/error_codes/E0722.md
new file mode 100644 (file)
index 0000000..570717a
--- /dev/null
@@ -0,0 +1,31 @@
+The `optimize` attribute was malformed.
+
+Erroneous code example:
+
+```compile_fail,E0722
+#![feature(optimize_attribute)]
+
+#[optimize(something)] // error: invalid argument
+pub fn something() {}
+```
+
+The `#[optimize]` attribute should be used as follows:
+
+- `#[optimize(size)]` -- instructs the optimization pipeline to generate code
+  that's smaller rather than faster
+
+- `#[optimize(speed)]` -- instructs the optimization pipeline to generate code
+  that's faster rather than smaller
+
+For example:
+
+```
+#![feature(optimize_attribute)]
+
+#[optimize(size)]
+pub fn something() {}
+```
+
+See [RFC 2412] for more details.
+
+[RFC 2412]: https://rust-lang.github.io/rfcs/2412-optimize-attr.html
diff --git a/compiler/rustc_error_codes/src/error_codes/E0757.md b/compiler/rustc_error_codes/src/error_codes/E0757.md
new file mode 100644 (file)
index 0000000..41b06b2
--- /dev/null
@@ -0,0 +1,33 @@
+A function was given both the `ffi_const` and `ffi_pure` attributes.
+
+Erroneous code example:
+
+```compile_fail,E0757
+#![feature(ffi_const, ffi_pure)]
+
+extern "C" {
+    #[ffi_const]
+    #[ffi_pure] // error: `#[ffi_const]` function cannot be `#[ffi_pure]`
+    pub fn square(num: i32) -> i32;
+}
+```
+
+As `ffi_const` provides stronger guarantees than `ffi_pure`, remove the
+`ffi_pure` attribute:
+
+```
+#![feature(ffi_const)]
+
+extern "C" {
+    #[ffi_const]
+    pub fn square(num: i32) -> i32;
+}
+```
+
+You can get more information about `const` and `pure` in the [GCC documentation
+on Common Function Attributes]. The unstable Rust Book has more information
+about [`ffi_const`] and [`ffi_pure`].
+
+[GCC documentation on Common Function Attributes]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
+[`ffi_const`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/ffi-const.html
+[`ffi_pure`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/ffi-pure.html
index 577baec21f064f232d96a83914619cdac7ce4004..2253007ce30276928bd9a74db9ee4a6621436dd6 100644 (file)
@@ -145,8 +145,9 @@ impl AnnotateSnippetEmitterWriter {
                 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 @@ impl Diagnostic {
         }
     }
 
+    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..87272b1605b798ce9bf5678e2b20a815e23ab2ae 100644 (file)
@@ -9,7 +9,6 @@
 
 use Destination::*;
 
-use rustc_lint_defs::FutureBreakage;
 use rustc_span::source_map::SourceMap;
 use rustc_span::{MultiSpan, SourceFile, Span};
 
@@ -193,7 +192,7 @@ pub trait Emitter {
     /// other formats can, and will, simply ignore it.
     fn emit_artifact_notification(&mut self, _path: &Path, _artifact_type: &str) {}
 
-    fn emit_future_breakage_report(&mut self, _diags: Vec<(FutureBreakage, Diagnostic)>) {}
+    fn emit_future_breakage_report(&mut self, _diags: Vec<Diagnostic>) {}
 
     /// Emit list of unused externs
     fn emit_unused_externs(&mut self, _lint_level: &str, _unused_externs: &[&str]) {}
@@ -309,9 +308,7 @@ pub trait Emitter {
                     // 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)),
                 }
             });
 
@@ -368,23 +365,11 @@ pub trait Emitter {
                     continue;
                 }
 
-                if matches!(trace.kind, ExpnKind::Inlined) {
-                    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 {
-                        ""
-                    };
-
+                if always_backtrace && !matches!(trace.kind, ExpnKind::Inlined) {
                     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,17 +395,27 @@ pub trait Emitter {
                 // 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: _ }
-                    )
-                    || always_backtrace
-                {
+                if !redundant_span || always_backtrace {
+                    let msg: Cow<'static, _> = match trace.kind {
+                        ExpnKind::Macro(MacroKind::Attr, _) => {
+                            "this procedural macro expansion".into()
+                        }
+                        ExpnKind::Macro(MacroKind::Derive, _) => {
+                            "this derive macro expansion".into()
+                        }
+                        ExpnKind::Macro(MacroKind::Bang, _) => "this macro invocation".into(),
+                        ExpnKind::Inlined => "the inlined copy of this code".into(),
+                        ExpnKind::Root => "in the crate root".into(),
+                        ExpnKind::AstPass(kind) => kind.descr().into(),
+                        ExpnKind::Desugaring(kind) => {
+                            format!("this {} desugaring", kind.descr()).into()
+                        }
+                    };
                     new_labels.push((
                         trace.call_site,
                         format!(
-                            "in this macro invocation{}",
+                            "in {}{}",
+                            msg,
                             if macro_backtrace.len() > 1 && always_backtrace {
                                 // only specify order when the macro
                                 // backtrace is multiple levels deep
index 72395bd31eca556aed999d8f7057489b6a546dca..1b6cd04cca642e213efdf22273ddb62a5cfa0d25 100644 (file)
@@ -16,7 +16,7 @@ use crate::registry::Registry;
 use crate::DiagnosticId;
 use crate::ToolMetadata;
 use crate::{CodeSuggestion, SubDiagnostic};
-use rustc_lint_defs::{Applicability, FutureBreakage};
+use rustc_lint_defs::Applicability;
 
 use rustc_data_structures::sync::Lrc;
 use rustc_span::hygiene::ExpnData;
@@ -134,17 +134,14 @@ impl Emitter for JsonEmitter {
         }
     }
 
-    fn emit_future_breakage_report(&mut self, diags: Vec<(FutureBreakage, crate::Diagnostic)>) {
+    fn emit_future_breakage_report(&mut self, diags: Vec<crate::Diagnostic>) {
         let data: Vec<FutureBreakageItem> = diags
             .into_iter()
-            .map(|(breakage, mut diag)| {
+            .map(|mut diag| {
                 if diag.level == crate::Level::Allow {
                     diag.level = crate::Level::Warning;
                 }
-                FutureBreakageItem {
-                    future_breakage_date: breakage.date,
-                    diagnostic: Diagnostic::from_errors_diagnostic(&diag, self),
-                }
+                FutureBreakageItem { diagnostic: Diagnostic::from_errors_diagnostic(&diag, self) }
             })
             .collect();
         let report = FutureIncompatReport { future_incompat_report: data };
@@ -326,7 +323,6 @@ struct ArtifactNotification<'a> {
 
 #[derive(Encodable)]
 struct FutureBreakageItem {
-    future_breakage_date: Option<&'static str>,
     diagnostic: Diagnostic,
 }
 
@@ -559,7 +555,7 @@ impl DiagnosticCode {
         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 @@ impl<T: Write> Write for Shared<T> {
     }
 }
 
-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 979f2d3b3005d3ec345cd048413fbb6b6ec6938f..993a7c2c162c6b7936f5496c1e295e50cc050160 100644 (file)
@@ -5,7 +5,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(crate_visibility_modifier)]
 #![feature(backtrace)]
-#![cfg_attr(bootstrap, feature(extended_key_value_attributes))]
 #![feature(format_args_capture)]
 #![feature(iter_zip)]
 #![feature(nll)]
@@ -24,7 +23,6 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::{self, Lock, Lrc};
 use rustc_data_structures::AtomicRef;
-use rustc_lint_defs::FutureBreakage;
 pub use rustc_lint_defs::{pluralize, Applicability};
 use rustc_serialize::json::Json;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
@@ -521,12 +519,28 @@ impl Handler {
     }
 
     /// 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,
@@ -552,6 +566,8 @@ impl Handler {
     }
 
     /// 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 {
@@ -560,6 +576,14 @@ impl Handler {
         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)
@@ -765,7 +789,7 @@ impl Handler {
         self.inner.borrow_mut().emit_artifact_notification(path, artifact_type)
     }
 
-    pub fn emit_future_breakage_report(&self, diags: Vec<(FutureBreakage, Diagnostic)>) {
+    pub fn emit_future_breakage_report(&self, diags: Vec<Diagnostic>) {
         self.inner.borrow_mut().emitter.emit_future_breakage_report(diags)
     }
 
@@ -802,7 +826,10 @@ impl HandlerInner {
             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);
             }
@@ -874,7 +901,7 @@ impl HandlerInner {
 
         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 aab2741c85240c1b4d08ffa72a7ec5a998726702..8c6aef80635cf596c26137255496d728139ef303 100644 (file)
@@ -16,7 +16,7 @@ use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
 use rustc_session::{parse::ParseSess, Limit, Session};
 use rustc_span::def_id::{CrateNum, DefId};
 use rustc_span::edition::Edition;
-use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
+use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{FileName, MultiSpan, Span, DUMMY_SP};
@@ -29,6 +29,9 @@ use std::rc::Rc;
 
 crate use rustc_span::hygiene::MacroKind;
 
+// When adding new variants, make sure to
+// adjust the `visit_*` / `flat_map_*` calls in `InvocationCollector`
+// to use `assign_id!`
 #[derive(Debug, Clone)]
 pub enum Annotatable {
     Item(P<ast::Item>),
@@ -745,9 +748,17 @@ impl SyntaxExtension {
             }
         }
 
-        let builtin_name = sess
+        let (builtin_name, helper_attrs) = sess
             .find_by_name(attrs, sym::rustc_builtin_macro)
-            .map(|a| a.value_str().unwrap_or(name));
+            .map(|attr| {
+                // Override `helper_attrs` passed above if it's a built-in macro,
+                // marking `proc_macro_derive` macros as built-in is not a realistic use case.
+                parse_macro_name_and_helper_attrs(sess.diagnostic(), attr, "built-in").map_or_else(
+                    || (Some(name), Vec::new()),
+                    |(name, helper_attrs)| (Some(name), helper_attrs),
+                )
+            })
+            .unwrap_or_else(|| (None, helper_attrs));
         let (stability, const_stability) = attr::find_stability(&sess, attrs, span);
         if let Some((_, sp)) = const_stability {
             sess.parse_sess
@@ -805,22 +816,15 @@ impl SyntaxExtension {
 
     pub fn expn_data(
         &self,
-        parent: ExpnId,
+        parent: LocalExpnId,
         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 },
-            parent,
+            ExpnKind::Macro(self.macro_kind(), descr),
+            parent.to_expn_id(),
             call_site,
             self.span,
             self.allow_internal_unstable.clone(),
@@ -828,6 +832,7 @@ impl SyntaxExtension {
             self.local_inner_macros,
             self.edition,
             macro_def_id,
+            parent_module,
         )
     }
 }
@@ -835,13 +840,17 @@ impl SyntaxExtension {
 /// Error type that denotes indeterminacy.
 pub struct Indeterminate;
 
-pub type DeriveResolutions = Vec<(ast::Path, Option<Lrc<SyntaxExtension>>)>;
+pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option<Lrc<SyntaxExtension>>)>;
 
 pub trait ResolverExpand {
     fn next_node_id(&mut self) -> NodeId;
 
     fn resolve_dollar_crates(&mut self);
-    fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment);
+    fn visit_ast_fragment_with_placeholders(
+        &mut self,
+        expn_id: LocalExpnId,
+        fragment: &AstFragment,
+    );
     fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind);
 
     fn expansion_for_ast_pass(
@@ -850,37 +859,38 @@ pub trait ResolverExpand {
         pass: AstPass,
         features: &[Symbol],
         parent_module_id: Option<NodeId>,
-    ) -> ExpnId;
+    ) -> LocalExpnId;
 
     fn resolve_imports(&mut self);
 
     fn resolve_macro_invocation(
         &mut self,
         invoc: &Invocation,
-        eager_expansion_root: ExpnId,
+        eager_expansion_root: LocalExpnId,
         force: bool,
     ) -> Result<Lrc<SyntaxExtension>, Indeterminate>;
 
     fn check_unused_macros(&mut self);
 
-    /// Some parent node that is close enough to the given macro call.
-    fn lint_node_id(&self, expn_id: ExpnId) -> NodeId;
-
     // Resolver interfaces for specific built-in macros.
     /// Does `#[derive(...)]` attribute with the given `ExpnId` have built-in `Copy` inside it?
-    fn has_derive_copy(&self, expn_id: ExpnId) -> bool;
+    fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool;
     /// Resolve paths inside the `#[derive(...)]` attribute with the given `ExpnId`.
     fn resolve_derives(
         &mut self,
-        expn_id: ExpnId,
+        expn_id: LocalExpnId,
         force: bool,
         derive_paths: &dyn Fn() -> DeriveResolutions,
     ) -> Result<(), Indeterminate>;
     /// Take resolutions for paths inside the `#[derive(...)]` attribute with the given `ExpnId`
     /// back from resolver.
-    fn take_derive_resolutions(&mut self, expn_id: ExpnId) -> Option<DeriveResolutions>;
+    fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option<DeriveResolutions>;
     /// Path resolution logic for `#[cfg_accessible(path)]`.
-    fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate>;
+    fn cfg_accessible(
+        &mut self,
+        expn_id: LocalExpnId,
+        path: &ast::Path,
+    ) -> Result<bool, Indeterminate>;
 
     /// Decodes the proc-macro quoted span in the specified crate, with the specified id.
     /// No caching is performed.
@@ -911,11 +921,13 @@ impl ModuleData {
 
 #[derive(Clone)]
 pub struct ExpansionData {
-    pub id: ExpnId,
+    pub id: LocalExpnId,
     pub depth: usize,
     pub module: Rc<ModuleData>,
     pub dir_ownership: DirOwnership,
     pub prior_type_ascription: Option<(Span, bool)>,
+    /// Some parent node that is close to this macro call
+    pub lint_node_id: NodeId,
 }
 
 type OnExternModLoaded<'a> =
@@ -956,11 +968,12 @@ impl<'a> ExtCtxt<'a> {
             extern_mod_loaded,
             root_path: PathBuf::new(),
             current_expansion: ExpansionData {
-                id: ExpnId::root(),
+                id: LocalExpnId::ROOT,
                 depth: 0,
                 module: Default::default(),
                 dir_ownership: DirOwnership::Owned { relative: None },
                 prior_type_ascription: None,
+                lint_node_id: ast::CRATE_NODE_ID,
             },
             force_mode: false,
             expansions: FxHashMap::default(),
@@ -993,19 +1006,19 @@ impl<'a> ExtCtxt<'a> {
     /// Equivalent of `Span::def_site` from the proc macro API,
     /// except that the location is taken from the span passed as an argument.
     pub fn with_def_site_ctxt(&self, span: Span) -> Span {
-        span.with_def_site_ctxt(self.current_expansion.id)
+        span.with_def_site_ctxt(self.current_expansion.id.to_expn_id())
     }
 
     /// Equivalent of `Span::call_site` from the proc macro API,
     /// except that the location is taken from the span passed as an argument.
     pub fn with_call_site_ctxt(&self, span: Span) -> Span {
-        span.with_call_site_ctxt(self.current_expansion.id)
+        span.with_call_site_ctxt(self.current_expansion.id.to_expn_id())
     }
 
     /// Equivalent of `Span::mixed_site` from the proc macro API,
     /// except that the location is taken from the span passed as an argument.
     pub fn with_mixed_site_ctxt(&self, span: Span) -> Span {
-        span.with_mixed_site_ctxt(self.current_expansion.id)
+        span.with_mixed_site_ctxt(self.current_expansion.id.to_expn_id())
     }
 
     /// Returns span for the macro which originally caused the current expansion to happen.
@@ -1219,6 +1232,88 @@ pub fn get_exprs_from_tts(
     Some(es)
 }
 
+pub fn parse_macro_name_and_helper_attrs(
+    diag: &rustc_errors::Handler,
+    attr: &Attribute,
+    descr: &str,
+) -> Option<(Symbol, Vec<Symbol>)> {
+    // Once we've located the `#[proc_macro_derive]` attribute, verify
+    // that it's of the form `#[proc_macro_derive(Foo)]` or
+    // `#[proc_macro_derive(Foo, attributes(A, ..))]`
+    let list = match attr.meta_item_list() {
+        Some(list) => list,
+        None => return None,
+    };
+    if list.len() != 1 && list.len() != 2 {
+        diag.span_err(attr.span, "attribute must have either one or two arguments");
+        return None;
+    }
+    let trait_attr = match list[0].meta_item() {
+        Some(meta_item) => meta_item,
+        _ => {
+            diag.span_err(list[0].span(), "not a meta item");
+            return None;
+        }
+    };
+    let trait_ident = match trait_attr.ident() {
+        Some(trait_ident) if trait_attr.is_word() => trait_ident,
+        _ => {
+            diag.span_err(trait_attr.span, "must only be one word");
+            return None;
+        }
+    };
+
+    if !trait_ident.name.can_be_raw() {
+        diag.span_err(
+            trait_attr.span,
+            &format!("`{}` cannot be a name of {} macro", trait_ident, descr),
+        );
+    }
+
+    let attributes_attr = list.get(1);
+    let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
+        if !attr.has_name(sym::attributes) {
+            diag.span_err(attr.span(), "second argument must be `attributes`")
+        }
+        attr.meta_item_list()
+            .unwrap_or_else(|| {
+                diag.span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`");
+                &[]
+            })
+            .iter()
+            .filter_map(|attr| {
+                let attr = match attr.meta_item() {
+                    Some(meta_item) => meta_item,
+                    _ => {
+                        diag.span_err(attr.span(), "not a meta item");
+                        return None;
+                    }
+                };
+
+                let ident = match attr.ident() {
+                    Some(ident) if attr.is_word() => ident,
+                    _ => {
+                        diag.span_err(attr.span, "must only be one word");
+                        return None;
+                    }
+                };
+                if !ident.name.can_be_raw() {
+                    diag.span_err(
+                        attr.span,
+                        &format!("`{}` cannot be a name of derive helper attribute", ident),
+                    );
+                }
+
+                Some(ident.name)
+            })
+            .collect()
+    } else {
+        Vec::new()
+    };
+
+    Some((trait_ident.name, proc_attrs))
+}
+
 /// This nonterminal looks like some specific enums from
 /// `proc-macro-hack` and `procedural-masquerade` crates.
 /// We need to maintain some special pretty-printing behavior for them due to incorrect
index ef5b97a946909707e20767b6be5921525451e85a..824df2757ea90eb2bc231a4483db31d5b695881a 100644 (file)
@@ -432,7 +432,7 @@ impl<'a> ExtCtxt<'a> {
 
     pub fn arm(&self, span: Span, pat: P<ast::Pat>, expr: P<ast::Expr>) -> ast::Arm {
         ast::Arm {
-            attrs: vec![],
+            attrs: AttrVec::new(),
             pat,
             guard: None,
             body: expr,
index 39c0447bd099eadc87a28c52c6804c623b0e396f..dcd871c9d205056d64e0ec6af3d82005542a0d27 100644 (file)
@@ -12,7 +12,7 @@ use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
-use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs};
+use rustc_ast::{AstLike, Block, Inline, ItemKind, Local, MacArgs};
 use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
 use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
 use rustc_ast_pretty::pprust;
@@ -22,14 +22,16 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, FatalError, PResult};
 use rustc_feature::Features;
-use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, Parser, RecoverComma};
+use rustc_parse::parser::{
+    AttemptLocalParseRecovery, ForceCollect, Parser, RecoverColon, RecoverComma,
+};
 use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::parse::{feature_err, ParseSess};
 use rustc_session::Limit;
 use rustc_span::symbol::{sym, Ident};
-use rustc_span::{ExpnId, FileName, Span};
+use rustc_span::{FileName, LocalExpnId, Span};
 
 use smallvec::{smallvec, SmallVec};
 use std::ops::DerefMut;
@@ -427,7 +429,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
     pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
         let orig_expansion_data = self.cx.current_expansion.clone();
         let orig_force_mode = self.cx.force_mode;
-        self.cx.current_expansion.depth = 0;
 
         // Collect all macro invocations and replace them with placeholders.
         let (mut fragment_with_placeholders, mut invocations) =
@@ -488,6 +489,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             };
 
             let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
+            let depth = depth - orig_expansion_data.depth;
             self.cx.current_expansion = invoc.expansion_data.clone();
             self.cx.force_mode = force;
 
@@ -500,42 +502,16 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                         .resolver
                         .take_derive_resolutions(expn_id)
                         .map(|derives| {
-                            enum AnnotatableRef<'a> {
-                                Item(&'a P<ast::Item>),
-                                Stmt(&'a ast::Stmt),
-                            }
-                            let item = match &fragment {
-                                AstFragment::Items(items) => match &items[..] {
-                                    [item] => AnnotatableRef::Item(item),
-                                    _ => unreachable!(),
-                                },
-                                AstFragment::Stmts(stmts) => match &stmts[..] {
-                                    [stmt] => AnnotatableRef::Stmt(stmt),
-                                    _ => unreachable!(),
-                                },
-                                _ => unreachable!(),
-                            };
-
                             derive_invocations.reserve(derives.len());
                             derives
                                 .into_iter()
-                                .map(|(path, _exts)| {
+                                .map(|(path, item, _exts)| {
                                     // FIXME: Consider using the derive resolutions (`_exts`)
                                     // instead of enqueuing the derives to be resolved again later.
-                                    let expn_id = ExpnId::fresh(None);
+                                    let expn_id = LocalExpnId::fresh_empty();
                                     derive_invocations.push((
                                         Invocation {
-                                            kind: InvocationKind::Derive {
-                                                path,
-                                                item: match item {
-                                                    AnnotatableRef::Item(item) => {
-                                                        Annotatable::Item(item.clone())
-                                                    }
-                                                    AnnotatableRef::Stmt(stmt) => {
-                                                        Annotatable::Stmt(P(stmt.clone()))
-                                                    }
-                                                },
-                                            },
+                                            kind: InvocationKind::Derive { path, item },
                                             fragment_kind,
                                             expansion_data: ExpansionData {
                                                 id: expn_id,
@@ -956,9 +932,11 @@ pub fn parse_ast_fragment<'a>(
             }
         }
         AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
-        AstFragmentKind::Pat => {
-            AstFragment::Pat(this.parse_pat_allow_top_alt(None, RecoverComma::No)?)
-        }
+        AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_alt(
+            None,
+            RecoverComma::No,
+            RecoverColon::Yes,
+        )?),
         AstFragmentKind::Arms
         | AstFragmentKind::Fields
         | AstFragmentKind::FieldPats
@@ -1015,7 +993,7 @@ struct InvocationCollector<'a, 'b> {
 
 impl<'a, 'b> InvocationCollector<'a, 'b> {
     fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
-        let expn_id = ExpnId::fresh(None);
+        let expn_id = LocalExpnId::fresh_empty();
         let vis = kind.placeholder_visibility();
         self.invocations.push((
             Invocation {
@@ -1120,6 +1098,43 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
     }
 }
 
+/// Wraps a call to `noop_visit_*` / `noop_flat_map_*`
+/// for an AST node that supports attributes
+/// (see the `Annotatable` enum)
+/// This method assigns a `NodeId`, and sets that `NodeId`
+/// as our current 'lint node id'. If a macro call is found
+/// inside this AST node, we will use this AST node's `NodeId`
+/// to emit lints associated with that macro (allowing
+/// `#[allow]` / `#[deny]` to be applied close to
+/// the macro invocation).
+///
+/// Do *not* call this for a macro AST node
+/// (e.g. `ExprKind::MacCall`) - we cannot emit lints
+/// at these AST nodes, since they are removed and
+/// replaced with the result of macro expansion.
+///
+/// All other `NodeId`s are assigned by `visit_id`.
+/// * `self` is the 'self' parameter for the current method,
+/// * `id` is a mutable reference to the `NodeId` field
+///    of the current AST node.
+/// * `closure` is a closure that executes the
+///   `noop_visit_*` / `noop_flat_map_*` method
+///   for the current AST node.
+macro_rules! assign_id {
+    ($self:ident, $id:expr, $closure:expr) => {{
+        let old_id = $self.cx.current_expansion.lint_node_id;
+        if $self.monotonic {
+            debug_assert_eq!(*$id, ast::DUMMY_NODE_ID);
+            let new_id = $self.cx.resolver.next_node_id();
+            *$id = new_id;
+            $self.cx.current_expansion.lint_node_id = new_id;
+        }
+        let ret = ($closure)();
+        $self.cx.current_expansion.lint_node_id = old_id;
+        ret
+    }};
+}
+
 impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
     fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
         self.cfg.configure_expr(expr);
@@ -1140,12 +1155,19 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 self.check_attributes(&expr.attrs);
                 self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner()
             } else {
-                ensure_sufficient_stack(|| noop_visit_expr(&mut expr, self));
+                assign_id!(self, &mut expr.id, || {
+                    ensure_sufficient_stack(|| noop_visit_expr(&mut expr, self));
+                });
                 expr
             }
         });
     }
 
+    // This is needed in order to set `lint_node_id` for `let` statements
+    fn visit_local(&mut self, local: &mut P<Local>) {
+        assign_id!(self, &mut local.id, || noop_visit_local(local, self));
+    }
+
     fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
         let mut arm = configure!(self, arm);
 
@@ -1155,7 +1177,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 .make_arms();
         }
 
-        noop_flat_map_arm(arm, self)
+        assign_id!(self, &mut arm.id, || noop_flat_map_arm(arm, self))
     }
 
     fn flat_map_expr_field(&mut self, field: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> {
@@ -1167,7 +1189,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 .make_expr_fields();
         }
 
-        noop_flat_map_expr_field(field, self)
+        assign_id!(self, &mut field.id, || noop_flat_map_expr_field(field, self))
     }
 
     fn flat_map_pat_field(&mut self, fp: ast::PatField) -> SmallVec<[ast::PatField; 1]> {
@@ -1179,7 +1201,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 .make_pat_fields();
         }
 
-        noop_flat_map_pat_field(fp, self)
+        assign_id!(self, &mut fp.id, || noop_flat_map_pat_field(fp, self))
     }
 
     fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
@@ -1191,7 +1213,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 .make_params();
         }
 
-        noop_flat_map_param(p, self)
+        assign_id!(self, &mut p.id, || noop_flat_map_param(p, self))
     }
 
     fn flat_map_field_def(&mut self, sf: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
@@ -1203,7 +1225,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 .make_field_defs();
         }
 
-        noop_flat_map_field_def(sf, self)
+        assign_id!(self, &mut sf.id, || noop_flat_map_field_def(sf, self))
     }
 
     fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
@@ -1215,7 +1237,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 .make_variants();
         }
 
-        noop_flat_map_variant(variant, self)
+        assign_id!(self, &mut variant.id, || noop_flat_map_variant(variant, self))
     }
 
     fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
@@ -1236,9 +1258,11 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                     .make_opt_expr()
                     .map(|expr| expr.into_inner())
             } else {
-                Some({
-                    noop_visit_expr(&mut expr, self);
-                    expr
+                assign_id!(self, &mut expr.id, || {
+                    Some({
+                        noop_visit_expr(&mut expr, self);
+                        expr
+                    })
                 })
             }
         })
@@ -1288,6 +1312,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         }
 
         // The placeholder expander gives ids to statements, so we avoid folding the id here.
+        // We don't use `assign_id!` - it will be called when we visit statement's contents
+        // (e.g. an expression, item, or local)
         let ast::Stmt { id, kind, span } = stmt;
         noop_flat_map_stmt_kind(kind, self)
             .into_iter()
@@ -1399,7 +1425,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 let orig_dir_ownership =
                     mem::replace(&mut self.cx.current_expansion.dir_ownership, dir_ownership);
 
-                let result = noop_flat_map_item(item, self);
+                let result = assign_id!(self, &mut item.id, || noop_flat_map_item(item, self));
 
                 // Restore the module info.
                 self.cx.current_expansion.dir_ownership = orig_dir_ownership;
@@ -1409,7 +1435,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
             }
             _ => {
                 item.attrs = attrs;
-                noop_flat_map_item(item, self)
+                // The crate root is special - don't assign an ID to it.
+                if !(matches!(item.kind, ast::ItemKind::Mod(..)) && ident == Ident::invalid()) {
+                    assign_id!(self, &mut item.id, || noop_flat_map_item(item, self))
+                } else {
+                    noop_flat_map_item(item, self)
+                }
             }
         }
     }
@@ -1433,7 +1464,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                     _ => unreachable!(),
                 })
             }
-            _ => noop_flat_map_assoc_item(item, self),
+            _ => {
+                assign_id!(self, &mut item.id, || noop_flat_map_assoc_item(item, self))
+            }
         }
     }
 
@@ -1456,7 +1489,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                     _ => unreachable!(),
                 })
             }
-            _ => noop_flat_map_assoc_item(item, self),
+            _ => {
+                assign_id!(self, &mut item.id, || noop_flat_map_assoc_item(item, self))
+            }
         }
     }
 
@@ -1500,7 +1535,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                     _ => unreachable!(),
                 })
             }
-            _ => noop_flat_map_foreign_item(foreign_item, self),
+            _ => {
+                assign_id!(self, &mut foreign_item.id, || noop_flat_map_foreign_item(
+                    foreign_item,
+                    self
+                ))
+            }
         }
     }
 
@@ -1520,13 +1560,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 .make_generic_params();
         }
 
-        noop_flat_map_generic_param(param, self)
+        assign_id!(self, &mut param.id, || noop_flat_map_generic_param(param, self))
     }
 
     fn visit_id(&mut self, id: &mut ast::NodeId) {
-        if self.monotonic {
-            debug_assert_eq!(*id, ast::DUMMY_NODE_ID);
-            *id = self.cx.resolver.next_node_id()
+        // We may have already assigned a `NodeId`
+        // by calling `assign_id`
+        if self.monotonic && *id == ast::DUMMY_NODE_ID {
+            *id = self.cx.resolver.next_node_id();
         }
     }
 }
index abad190b072ab3081cc8ce064bdd659c147e55c8..7f985af364d7dbf34369be8461e25bb690d69a91 100644 (file)
@@ -11,14 +11,16 @@ use crate::mbe::transcribe::transcribe;
 use rustc_ast as ast;
 use rustc_ast::token::{self, NonterminalKind, NtTT, Token, TokenKind::*};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream};
-use rustc_ast::NodeId;
+use rustc_ast::{NodeId, DUMMY_NODE_ID};
 use rustc_ast_pretty::pprust;
 use rustc_attr::{self as attr, TransparencyError};
 use rustc_data_structures::fx::FxHashMap;
 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;
@@ -287,7 +289,6 @@ fn generic_extension<'cx>(
 
                 let mut p = Parser::new(sess, tts, false, None);
                 p.last_type_ascription = cx.current_expansion.prior_type_ascription;
-                let lint_node_id = cx.resolver.lint_node_id(cx.current_expansion.id);
 
                 // Let the context choose how to interpret the result.
                 // Weird, but useful for X-macros.
@@ -299,7 +300,7 @@ fn generic_extension<'cx>(
                     // macro leaves unparsed tokens.
                     site_span: sp,
                     macro_ident: name,
-                    lint_node_id,
+                    lint_node_id: cx.current_expansion.lint_node_id,
                     arm_span,
                 });
             }
@@ -471,7 +472,7 @@ pub fn compile_declarative_macro(
                         )
                         .pop()
                         .unwrap();
-                        valid &= check_lhs_nt_follows(&sess.parse_sess, features, &def.attrs, &tt);
+                        valid &= check_lhs_nt_follows(&sess.parse_sess, features, &def, &tt);
                         return tt;
                     }
                 }
@@ -540,13 +541,13 @@ pub fn compile_declarative_macro(
 fn check_lhs_nt_follows(
     sess: &ParseSess,
     features: &Features,
-    attrs: &[ast::Attribute],
+    def: &ast::Item,
     lhs: &mbe::TokenTree,
 ) -> bool {
     // lhs is going to be like TokenTree::Delimited(...), where the
     // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
     if let mbe::TokenTree::Delimited(_, ref tts) = *lhs {
-        check_matcher(sess, features, attrs, &tts.tts)
+        check_matcher(sess, features, def, &tts.tts)
     } else {
         let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
         sess.span_diagnostic.span_err(lhs.span(), msg);
@@ -604,13 +605,13 @@ fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool {
 fn check_matcher(
     sess: &ParseSess,
     features: &Features,
-    attrs: &[ast::Attribute],
+    def: &ast::Item,
     matcher: &[mbe::TokenTree],
 ) -> bool {
     let first_sets = FirstSets::new(matcher);
     let empty_suffix = TokenSet::empty();
     let err = sess.span_diagnostic.err_count();
-    check_matcher_core(sess, features, attrs, &first_sets, matcher, &empty_suffix);
+    check_matcher_core(sess, features, def, &first_sets, matcher, &empty_suffix);
     err == sess.span_diagnostic.err_count()
 }
 
@@ -857,7 +858,7 @@ impl TokenSet {
 fn check_matcher_core(
     sess: &ParseSess,
     features: &Features,
-    attrs: &[ast::Attribute],
+    def: &ast::Item,
     first_sets: &FirstSets,
     matcher: &[mbe::TokenTree],
     follow: &TokenSet,
@@ -903,7 +904,7 @@ fn check_matcher_core(
             }
             TokenTree::Delimited(span, ref d) => {
                 let my_suffix = TokenSet::singleton(d.close_tt(span));
-                check_matcher_core(sess, features, attrs, first_sets, &d.tts, &my_suffix);
+                check_matcher_core(sess, features, def, first_sets, &d.tts, &my_suffix);
                 // don't track non NT tokens
                 last.replace_with_irrelevant();
 
@@ -936,7 +937,7 @@ fn check_matcher_core(
                 // `my_suffix` is some TokenSet that we can use
                 // for checking the interior of `seq_rep`.
                 let next =
-                    check_matcher_core(sess, features, attrs, first_sets, &seq_rep.tts, my_suffix);
+                    check_matcher_core(sess, features, def, first_sets, &seq_rep.tts, my_suffix);
                 if next.maybe_empty {
                     last.add_all(&next);
                 } else {
@@ -956,29 +957,31 @@ fn check_matcher_core(
         for token in &last.tokens {
             if let TokenTree::MetaVarDecl(span, name, Some(kind)) = *token {
                 for next_token in &suffix_first.tokens {
-                    // Check if the old pat is used and the next token is `|`.
-                    if let NonterminalKind::PatParam { inferred: true } = kind {
-                        if let TokenTree::Token(token) = next_token {
-                            if let BinOp(token) = token.kind {
-                                if let token::BinOpToken::Or = token {
-                                    // It is suggestion to use pat_param, for example: $x:pat -> $x:pat_param.
-                                    let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
-                                        span,
-                                        name,
-                                        Some(NonterminalKind::PatParam { inferred: false }),
-                                    ));
-                                    sess.buffer_lint_with_diagnostic(
-                                        &OR_PATTERNS_BACK_COMPAT,
-                                        span,
-                                        ast::CRATE_NODE_ID,
-                                        &*format!("the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro",),
-                                        BuiltinLintDiagnostics::OrPatternsBackCompat(
-                                            span, suggestion,
-                                        ),
-                                    );
-                                }
-                            }
-                        }
+                    // Check if the old pat is used and the next token is `|`
+                    // to warn about incompatibility with Rust 2021.
+                    // We only emit this lint if we're parsing the original
+                    // definition of this macro_rules, not while (re)parsing
+                    // the macro when compiling another crate that is using the
+                    // macro. (See #86567.)
+                    // Macros defined in the current crate have a real node id,
+                    // whereas macros from an external crate have a dummy id.
+                    if def.id != DUMMY_NODE_ID
+                        && matches!(kind, NonterminalKind::PatParam { inferred: true })
+                        && matches!(next_token, TokenTree::Token(token) if token.kind == BinOp(token::BinOpToken::Or))
+                    {
+                        // It is suggestion to use pat_param, for example: $x:pat -> $x:pat_param.
+                        let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
+                            span,
+                            name,
+                            Some(NonterminalKind::PatParam { inferred: false }),
+                        ));
+                        sess.buffer_lint_with_diagnostic(
+                            &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",
+                            BuiltinLintDiagnostics::OrPatternsBackCompat(span, suggestion),
+                        );
                     }
                     match is_in_follow(next_token, kind) {
                         IsInFollow::Yes => {}
index f9e7c4254bc495b29b08898fa1b8018f0c34ca61..9ed5c8b8ffba5c814d4177fe50772285d1f36ec8 100644 (file)
@@ -8,7 +8,7 @@ use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{pluralize, PResult};
-use rustc_span::hygiene::{ExpnId, Transparency};
+use rustc_span::hygiene::{LocalExpnId, Transparency};
 use rustc_span::symbol::MacroRulesNormalizedIdent;
 use rustc_span::Span;
 
@@ -16,7 +16,7 @@ use smallvec::{smallvec, SmallVec};
 use std::mem;
 
 // A Marker adds the given mark to the syntax context.
-struct Marker(ExpnId, Transparency);
+struct Marker(LocalExpnId, Transparency);
 
 impl MutVisitor for Marker {
     fn token_visiting_enabled(&self) -> bool {
@@ -24,7 +24,7 @@ impl MutVisitor for Marker {
     }
 
     fn visit_span(&mut self, span: &mut Span) {
-        *span = span.apply_mark(self.0, self.1)
+        *span = span.apply_mark(self.0.to_expn_id(), self.1)
     }
 }
 
index 7e7155ad27876bff0571d97c42305eb518be8ade..0068539fb3bd4b075c2176305abe776351b871a2 100644 (file)
@@ -3,8 +3,8 @@ use crate::tests::{matches_codepattern, string_to_crate};
 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 56f25ffdb0187cf7bc4ea2a8f8c3ea7c17d25898..6402a81e7c1a5dba758fff4da279b140b9015ab8 100644 (file)
@@ -10,9 +10,9 @@ use rustc_errors::PResult;
 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 get_spans_of_pat_idents(src: &str) -> Vec<Span> {
 
 #[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) {} }",
@@ -193,7 +193,7 @@ fn span_of_self_arg_pat_idents_are_correct() {
             "impl z { fn a (self: Foo, &myarg: i32) {} }",
         ];
 
-        for &src in &srcs {
+        for src in srcs {
             let spans = get_spans_of_pat_idents(src);
             let (lo, hi) = (spans[0].lo(), spans[0].hi());
             assert!(
@@ -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 @@ let mut fflags: c_int = wb();
 
 #[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 ttdelim_span() {
         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 ttdelim_span() {
 // 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_data_structures::sync::Lrc;
 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 @@ impl base::ProcMacro for BangProcMacro {
         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 @@ impl base::ProcMacro for BangProcMacro {
 
 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 @@ impl base::AttrProcMacro for AttrProcMacro {
         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 @@ impl base::AttrProcMacro for AttrProcMacro {
 
 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 @@ impl MultiItemModifier for ProcMacroDerive {
             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 92315c4d4f6c7f02e5221c2805706fe8ba12d8b6..ff135f60a822a70ab52cf5f924650793e922fc4f 100644 (file)
@@ -14,7 +14,6 @@ use rustc_parse::lexer::nfc_normalize;
 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(),
         }
     }
@@ -411,6 +404,10 @@ impl server::FreeFunctions for Rustc<'_> {
     fn track_env_var(&mut self, var: &str, value: Option<&str>) {
         self.sess.env_depinfo.borrow_mut().insert((Symbol::intern(var), value.map(Symbol::intern)));
     }
+
+    fn track_path(&mut self, path: &str) {
+        self.sess.file_depinfo.borrow_mut().insert(Symbol::intern(path));
+    }
 }
 
 impl server::TokenStream for Rustc<'_> {
@@ -778,25 +775,15 @@ impl server::Span for Rustc<'_> {
     /// 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())
         })
     }
 }
@@ -808,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 as ast;
 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 @@ impl<T: Write> Write for Shared<T> {
 }
 
 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 crate::tests::string_to_stream;
 
 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 16f67783c1e36e81c05956ba8b3be627de4d7594..a3e40daf6bf6dccaaf22787394abd7b157a5f6e5 100644 (file)
@@ -16,8 +16,14 @@ macro_rules! set {
 }
 
 macro_rules! declare_features {
+    (__status_to_bool active) => {
+        false
+    };
+    (__status_to_bool incomplete) => {
+        true
+    };
     ($(
-        $(#[doc = $doc:tt])* (active, $feature:ident, $ver:expr, $issue:expr, $edition:expr),
+        $(#[doc = $doc:tt])* ($status:ident, $feature:ident, $ver:expr, $issue:expr, $edition:expr),
     )+) => {
         /// Represents active features that are currently being implemented or
         /// currently being considered for addition/removal.
@@ -67,6 +73,21 @@ macro_rules! declare_features {
             pub fn unordered_const_ty_params(&self) -> bool {
                 self.const_generics || self.const_generics_defaults
             }
+
+            /// Some features are known to be incomplete and using them is likely to have
+            /// unanticipated results, such as compiler crashes. We warn the user about these
+            /// to alert them.
+            pub fn incomplete(&self, feature: Symbol) -> bool {
+                match feature {
+                    $(
+                        sym::$feature => declare_features!(__status_to_bool $status),
+                    )*
+                    // accepted and removed features aren't in this file but are never incomplete
+                    _ if self.declared_lang_features.iter().any(|f| f.0 == feature) => false,
+                    _ if self.declared_lib_features.iter().any(|f| f.0 == feature) => false,
+                    _ => panic!("`{}` was not listed in `declare_features`", feature),
+                }
+            }
         }
     };
 }
@@ -305,7 +326,7 @@ declare_features! (
     (active, cfg_target_thread_local, "1.7.0", Some(29594), None),
 
     /// Allows specialization of implementations (RFC 1210).
-    (active, specialization, "1.7.0", Some(31844), None),
+    (incomplete, specialization, "1.7.0", Some(31844), None),
 
     /// A minimal, sound subset of specialization intended to be used by the
     /// standard library until the soundness issues with specialization
@@ -342,7 +363,7 @@ declare_features! (
     (active, abi_ptx, "1.15.0", Some(38788), None),
 
     /// Allows the `#[repr(i128)]` attribute for enums.
-    (active, repr128, "1.16.0", Some(56071), None),
+    (incomplete, repr128, "1.16.0", Some(56071), None),
 
     /// Allows `#[link(kind="static-nobundle"...)]`.
     (active, static_nobundle, "1.16.0", Some(37403), None),
@@ -395,9 +416,6 @@ declare_features! (
     /// 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),
 
@@ -429,7 +447,7 @@ declare_features! (
     (active, proc_macro_hygiene, "1.30.0", Some(54727), None),
 
     /// Allows unsized rvalues at arguments and parameters.
-    (active, unsized_locals, "1.30.0", Some(48055), None),
+    (incomplete, unsized_locals, "1.30.0", Some(48055), None),
 
     /// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`.
     (active, custom_test_frameworks, "1.30.0", Some(50297), None),
@@ -437,9 +455,6 @@ declare_features! (
     /// Allows non-builtin attributes in inner attribute position.
     (active, custom_inner_attributes, "1.30.0", Some(54726), None),
 
-    /// Allows `impl Trait` in bindings (`let`, `const`, `static`).
-    (active, impl_trait_in_bindings, "1.30.0", Some(63065), None),
-
     /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
     (active, lint_reasons, "1.31.0", Some(54503), None),
 
@@ -450,7 +465,7 @@ declare_features! (
     (active, ffi_returns_twice, "1.34.0", Some(58314), None),
 
     /// Allows const generic types (e.g. `struct Foo<const N: usize>(...);`).
-    (active, const_generics, "1.34.0", Some(44580), None),
+    (incomplete, const_generics, "1.34.0", Some(44580), None),
 
     /// Allows using `#[optimize(X)]`.
     (active, optimize_attribute, "1.34.0", Some(54882), None),
@@ -462,7 +477,7 @@ declare_features! (
     (active, associated_type_bounds, "1.34.0", Some(52662), None),
 
     /// Allows `if/while p && let q = r && ...` chains.
-    (active, let_chains, "1.37.0", Some(53667), None),
+    (incomplete, let_chains, "1.37.0", Some(53667), None),
 
     /// Allows #[repr(transparent)] on unions (RFC 2645).
     (active, transparent_unions, "1.37.0", Some(60405), None),
@@ -474,13 +489,13 @@ declare_features! (
     (active, async_closure, "1.37.0", Some(62290), None),
 
     /// Allows `impl Trait` to be used inside type aliases (RFC 2515).
-    (active, type_alias_impl_trait, "1.38.0", Some(63063), None),
+    (incomplete, type_alias_impl_trait, "1.38.0", Some(63063), None),
 
     /// Allows the definition of `const extern fn` and `const unsafe extern fn`.
     (active, const_extern_fn, "1.40.0", Some(64926), None),
 
     /// Allows the use of raw-dylibs (RFC 2627).
-    (active, raw_dylib, "1.40.0", Some(58713), None),
+    (incomplete, raw_dylib, "1.40.0", Some(58713), None),
 
     /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe.
     /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
@@ -519,7 +534,7 @@ declare_features! (
     (active, const_trait_impl, "1.42.0", Some(67792), None),
 
     /// Allows `T: ?const Trait` syntax in bounds.
-    (active, const_trait_bound_opt_out, "1.42.0", Some(67794), None),
+    (incomplete, const_trait_bound_opt_out, "1.42.0", Some(67794), None),
 
     /// Allows the use of `no_sanitize` attribute.
     (active, no_sanitize, "1.42.0", Some(39699), None),
@@ -552,16 +567,16 @@ declare_features! (
     (active, format_args_capture, "1.46.0", Some(67984), None),
 
     /// Lazily evaluate constants. This allows constants to depend on type parameters.
-    (active, lazy_normalization_consts, "1.46.0", Some(72219), None),
+    (incomplete, lazy_normalization_consts, "1.46.0", Some(72219), None),
 
     /// Allows calling `transmute` in const fn
     (active, const_fn_transmute, "1.46.0", Some(53605), None),
 
     /// Allows `if let` guard in match arms.
-    (active, if_let_guard, "1.47.0", Some(51114), None),
+    (incomplete, if_let_guard, "1.47.0", Some(51114), None),
 
     /// Allows non-trivial generic constants which have to be manually propagated upwards.
-    (active, const_evaluatable_checked, "1.48.0", Some(76560), None),
+    (incomplete, const_evaluatable_checked, "1.48.0", Some(76560), None),
 
     /// Allows basic arithmetic on floating point types in a `const fn`.
     (active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None),
@@ -582,7 +597,7 @@ declare_features! (
     (active, isa_attribute, "1.48.0", Some(74727), None),
 
     /// Allow anonymous constants from an inline `const` block
-    (active, inline_const, "1.49.0", Some(76001), None),
+    (incomplete, inline_const, "1.49.0", Some(76001), None),
 
     /// Allows unsized fn parameters.
     (active, unsized_fn_params, "1.49.0", Some(48055), None),
@@ -594,7 +609,7 @@ declare_features! (
     (active, cfg_panic, "1.49.0", Some(77443), None),
 
     /// Allows capturing disjoint fields in a closure/generator (RFC 2229).
-    (active, capture_disjoint_fields, "1.49.0", Some(53488), None),
+    (incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None),
 
     /// Allows const generics to have default values (e.g. `struct Foo<const N: usize = 3>(...);`).
     (active, const_generics_defaults, "1.51.0", Some(44580), None),
@@ -618,7 +633,7 @@ declare_features! (
     (active, min_type_alias_impl_trait, "1.52.0", Some(63063), None),
 
     /// Allows associated types in inherent impls.
-    (active, inherent_associated_types, "1.52.0", Some(8995), None),
+    (incomplete, inherent_associated_types, "1.52.0", Some(8995), None),
 
     // Allows setting the threshold for the `large_assignments` lint.
     (active, large_assignments, "1.52.0", Some(83518), None),
@@ -626,6 +641,9 @@ declare_features! (
     /// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries.
     (active, c_unwind, "1.52.0", Some(74990), None),
 
+    /// Allows using `#[repr(align(...))]` on function items
+    (active, fn_align, "1.53.0", Some(82232), None),
+
     /// Allows `extern "wasm" fn`
     (active, wasm_abi, "1.53.0", Some(83788), None),
 
@@ -658,41 +676,19 @@ declare_features! (
     (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
 
     /// Allows unnamed fields of struct and union type
-    (active, unnamed_fields, "1.53.0", Some(49804), None),
+    (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),
+
+    /// Allows `cfg(target_abi = "...")`.
+    (active, cfg_target_abi, "1.55.0", Some(80970), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
 );
 
-/// Some features are known to be incomplete and using them is likely to have
-/// unanticipated results, such as compiler crashes. We warn the user about these
-/// to alert them.
-pub const INCOMPLETE_FEATURES: &[Symbol] = &[
-    sym::if_let_guard,
-    sym::impl_trait_in_bindings,
-    sym::generic_associated_types,
-    sym::const_generics,
-    sym::let_chains,
-    sym::raw_dylib,
-    sym::const_evaluatable_checked,
-    sym::const_trait_impl,
-    sym::const_trait_bound_opt_out,
-    sym::lazy_normalization_consts,
-    sym::specialization,
-    sym::inline_const,
-    sym::repr128,
-    sym::unsized_locals,
-    sym::capture_disjoint_fields,
-    sym::inherent_associated_types,
-    sym::type_alias_impl_trait,
-    sym::rustc_insignificant_dtor,
-    sym::unnamed_fields,
-];
-
 /// Some features are not allowed to be used together at the same time, if
 /// the two are present, produce an error.
 ///
index 259a6328a22f6832a6ae275578b532a5ba95550d..b1c725ecd85c857db40b883d631ac7b529263add 100644 (file)
@@ -23,6 +23,7 @@ pub type GatedCfg = (Symbol, Symbol, GateFn);
 /// `cfg(...)`'s that are feature gated.
 const GATED_CFGS: &[GatedCfg] = &[
     // (name in cfg, feature, function to check if the feature is enabled)
+    (sym::target_abi, sym::cfg_target_abi, cfg_fn!(cfg_target_abi)),
     (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)),
     (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
     (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
@@ -349,6 +350,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
 
     gated!(cmse_nonsecure_entry, AssumedUsed, template!(Word), experimental!(cmse_nonsecure_entry)),
+    // RFC 2632
+    gated!(
+        default_method_body_is_const, AssumedUsed, template!(Word), const_trait_impl,
+        "`default_method_body_is_const` is a temporary placeholder for declaring default bodies \
+        as `const`, which may be removed or renamed in the future."
+    ),
 
     // ==========================================================================
     // Internal attributes: Stability, deprecation, and unsafe:
@@ -441,7 +448,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // Internal attributes, Macro related:
     // ==========================================================================
 
-    rustc_attr!(rustc_builtin_macro, AssumedUsed, template!(Word, NameValueStr: "name"), IMPL_DETAIL),
+    rustc_attr!(
+        rustc_builtin_macro, AssumedUsed,
+        template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"),
+        IMPL_DETAIL,
+    ),
     rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE),
     rustc_attr!(
         rustc_macro_transparency, AssumedUsed,
index 654d2408580fe932e23195dd659267b4d9e50860..cf102aa16e0571ffbf89dbbb64ced39c99282ebf 100644 (file)
@@ -146,7 +146,7 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZeroU3
 }
 
 pub use accepted::ACCEPTED_FEATURES;
-pub use active::{Features, ACTIVE_FEATURES, INCOMPATIBLE_FEATURES, INCOMPLETE_FEATURES};
+pub use active::{Features, ACTIVE_FEATURES, INCOMPATIBLE_FEATURES};
 pub use builtin_attrs::{
     deprecated_attributes, find_gated_cfg, is_builtin_attr_name, AttributeGate, AttributeTemplate,
     AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
index 71c10eb650754699eb8d98456c7fe0a4dd2e46ca..29f4423ec85ac05e7bd7c728fe902087abe00a23 100644 (file)
@@ -144,6 +144,14 @@ 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")),
+
+    /// Allows `impl Trait` in bindings (`let`, `const`, `static`).
+    (removed, impl_trait_in_bindings, "1.55.0", Some(63065), None,
+     Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")),
+
     // -------------------------------------------------------------------------
     // feature-group-end: removed features
     // -------------------------------------------------------------------------
index db70beb59141b52682b0bbe9b3caa154472768bb..27390fd2e4d9117b784b786a7c466bdffb1d79eb 100644 (file)
@@ -1,11 +1,11 @@
-//! Generate files suitable for use with [Graphviz](http://www.graphviz.org/)
+//! Generate files suitable for use with [Graphviz](https://www.graphviz.org/)
 //!
 //! The `render` function generates output (e.g., an `output.dot` file) for
-//! use with [Graphviz](http://www.graphviz.org/) by walking a labeled
+//! use with [Graphviz](https://www.graphviz.org/) by walking a labeled
 //! graph. (Graphviz can then automatically lay out the nodes and edges
 //! of the graph, and also optionally render the graph as an image or
 //! other [output formats](
-//! http://www.graphviz.org/content/output-formats), such as SVG.)
+//! https://www.graphviz.org/content/output-formats), such as SVG.)
 //!
 //! Rather than impose some particular graph data structure on clients,
 //! this library exposes two traits that clients can implement on their
@@ -13,8 +13,8 @@
 //!
 //! Note: This library does not yet provide access to the full
 //! expressiveness of the [DOT language](
-//! http://www.graphviz.org/doc/info/lang.html). For example, there are
-//! many [attributes](http://www.graphviz.org/content/attrs) related to
+//! https://www.graphviz.org/doc/info/lang.html). For example, there are
+//! many [attributes](https://www.graphviz.org/content/attrs) related to
 //! providing layout hints (e.g., left-to-right versus top-down, which
 //! algorithm to use, etc). The current intention of this library is to
 //! emit a human-readable .dot file with very regular structure suitable
 //!
 //! # References
 //!
-//! * [Graphviz](http://www.graphviz.org/)
+//! * [Graphviz](https://www.graphviz.org/)
 //!
-//! * [DOT language](http://www.graphviz.org/doc/info/lang.html)
+//! * [DOT language](https://www.graphviz.org/doc/info/lang.html)
 
 #![doc(
     html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
@@ -292,7 +292,7 @@ pub enum LabelText<'a> {
     LabelStr(Cow<'a, str>),
 
     /// This kind of label uses the graphviz label escString type:
-    /// <http://www.graphviz.org/content/attrs#kescString>
+    /// <https://www.graphviz.org/content/attrs#kescString>
     ///
     /// Occurrences of backslashes (`\`) are not escaped; instead they
     /// are interpreted as initiating an escString escape sequence.
@@ -307,12 +307,12 @@ pub enum LabelText<'a> {
     /// printed exactly as given, but between `<` and `>`. **No
     /// escaping is performed.**
     ///
-    /// [html]: http://www.graphviz.org/content/node-shapes#html
+    /// [html]: https://www.graphviz.org/content/node-shapes#html
     HtmlStr(Cow<'a, str>),
 }
 
 /// The style for a node or edge.
-/// See <http://www.graphviz.org/doc/info/attrs.html#k:style> for descriptions.
+/// See <https://www.graphviz.org/doc/info/attrs.html#k:style> for descriptions.
 /// Note that some of these are not valid for edges.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum Style {
@@ -439,7 +439,7 @@ pub trait Labeller<'a> {
     /// Maps `n` to one of the [graphviz `shape` names][1]. If `None`
     /// is returned, no `shape` attribute is specified.
     ///
-    /// [1]: http://www.graphviz.org/content/node-shapes
+    /// [1]: https://www.graphviz.org/content/node-shapes
     fn node_shape(&'a self, _node: &Self::Node) -> Option<LabelText<'a>> {
         None
     }
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 @@ use tracing::debug;
 /// 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 @@ impl DefPathTable {
 /// 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 @@ impl Definitions {
     }
 
     /// 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 @@ impl Definitions {
             },
         };
 
-        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 @@ impl Definitions {
             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 @@ impl Definitions {
         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 577d43b1c8e5e3c1f9c19671815f682deea0cdb5..6aff2fdbd1f220e6964f2340cc371bfb5ff1bea2 100644 (file)
@@ -808,13 +808,13 @@ impl<'hir> Pat<'hir> {
         }
 
         use PatKind::*;
-        match &self.kind {
+        match self.kind {
             Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true,
             Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it),
             Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
             TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
             Slice(before, slice, after) => {
-                before.iter().chain(slice.iter()).chain(after.iter()).all(|p| p.walk_short_(it))
+                before.iter().chain(slice).chain(after.iter()).all(|p| p.walk_short_(it))
             }
         }
     }
@@ -836,13 +836,13 @@ impl<'hir> Pat<'hir> {
         }
 
         use PatKind::*;
-        match &self.kind {
+        match self.kind {
             Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {}
             Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it),
             Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
             TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
             Slice(before, slice, after) => {
-                before.iter().chain(slice.iter()).chain(after.iter()).for_each(|p| p.walk_(it))
+                before.iter().chain(slice).chain(after.iter()).for_each(|p| p.walk_(it))
             }
         }
     }
@@ -940,11 +940,11 @@ pub enum PatKind<'hir> {
     /// A tuple struct/variant pattern `Variant(x, y, .., z)`.
     /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
     /// `0 <= position <= subpats.len()`
-    TupleStruct(QPath<'hir>, &'hir [&'hir Pat<'hir>], Option<usize>),
+    TupleStruct(QPath<'hir>, &'hir [Pat<'hir>], Option<usize>),
 
     /// An or-pattern `A | B | C`.
     /// Invariant: `pats.len() >= 2`.
-    Or(&'hir [&'hir Pat<'hir>]),
+    Or(&'hir [Pat<'hir>]),
 
     /// A path pattern for an unit struct/variant or a (maybe-associated) constant.
     Path(QPath<'hir>),
@@ -952,7 +952,7 @@ pub enum PatKind<'hir> {
     /// A tuple pattern (e.g., `(a, b)`).
     /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
     /// `0 <= position <= subpats.len()`
-    Tuple(&'hir [&'hir Pat<'hir>], Option<usize>),
+    Tuple(&'hir [Pat<'hir>], Option<usize>),
 
     /// A `box` pattern.
     Box(&'hir Pat<'hir>),
@@ -975,7 +975,7 @@ pub enum PatKind<'hir> {
     /// ```
     /// PatKind::Slice([Binding(a), Binding(b)], Some(Wild), [Binding(c), Binding(d)])
     /// ```
-    Slice(&'hir [&'hir Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [&'hir Pat<'hir>]),
+    Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]),
 }
 
 #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
@@ -1205,8 +1205,6 @@ pub struct ExprField<'hir> {
 pub enum BlockCheckMode {
     DefaultBlock,
     UnsafeBlock(UnsafeSource),
-    PushUnsafeBlock(UnsafeSource),
-    PopUnsafeBlock(UnsafeSource),
 }
 
 #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
@@ -2266,18 +2264,14 @@ pub struct OpaqueTy<'hir> {
 }
 
 /// From whence the opaque type came.
-#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum OpaqueTyOrigin {
     /// `-> impl Trait`
     FnReturn,
     /// `async fn`
     AsyncFn,
-    /// `let _: impl Trait = ...`
-    Binding,
     /// type aliases: `type Foo = impl Trait;`
     TyAlias,
-    /// Impl trait consts, statics, bounds.
-    Misc,
 }
 
 /// The various kinds of types recognized by the compiler.
@@ -2817,6 +2811,27 @@ impl ItemKind<'_> {
             _ => return None,
         })
     }
+
+    pub fn descr(&self) -> &'static str {
+        match self {
+            ItemKind::ExternCrate(..) => "extern crate",
+            ItemKind::Use(..) => "`use` import",
+            ItemKind::Static(..) => "static item",
+            ItemKind::Const(..) => "constant item",
+            ItemKind::Fn(..) => "function",
+            ItemKind::Mod(..) => "module",
+            ItemKind::ForeignMod { .. } => "extern block",
+            ItemKind::GlobalAsm(..) => "global asm item",
+            ItemKind::TyAlias(..) => "type alias",
+            ItemKind::OpaqueTy(..) => "opaque type",
+            ItemKind::Enum(..) => "enum",
+            ItemKind::Struct(..) => "struct",
+            ItemKind::Union(..) => "union",
+            ItemKind::Trait(..) => "trait",
+            ItemKind::TraitAlias(..) => "trait alias",
+            ItemKind::Impl(..) => "implementation",
+        }
+    }
 }
 
 /// A reference from an trait to one of its associated items. This
@@ -3045,6 +3060,27 @@ impl<'hir> Node<'hir> {
             Node::Crate(_) | Node::Visibility(_) => None,
         }
     }
+
+    /// Returns `Constness::Const` when this node is a const fn/impl.
+    pub fn constness(&self) -> Constness {
+        match self {
+            Node::Item(Item {
+                kind: ItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..),
+                ..
+            })
+            | Node::TraitItem(TraitItem {
+                kind: TraitItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..),
+                ..
+            })
+            | Node::ImplItem(ImplItem {
+                kind: ImplItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..),
+                ..
+            })
+            | Node::Item(Item { kind: ItemKind::Impl(Impl { constness, .. }), .. }) => *constness,
+
+            _ => Constness::NotConst,
+        }
+    }
 }
 
 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
index 0b8535f8ca54968d13e37c91d127cf86fb591dd5..28ae08030e63029f34adcc4eccd8153564c7145c 100644 (file)
@@ -310,6 +310,8 @@ language_item_table! {
 
     Try,                     sym::Try,                 try_trait,                  Target::Trait;
 
+    SliceLen,                sym::slice_len_fn,        slice_len_fn,               Target::Method(MethodKind::Inherent);
+
     // Language items from AST lowering
     TryTraitFromResidual,    sym::from_residual,       from_residual_fn,           Target::Method(MethodKind::Trait { body: false });
     TryTraitFromOutput,      sym::from_output,         from_output_fn,             Target::Method(MethodKind::Trait { body: false });
@@ -346,7 +348,4 @@ language_item_table! {
     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 ad2ecae9233bcd9ea30e51e3719aadc5d33abc7d..42575273839a9760daca044dbb611125e1a6b3d2 100644 (file)
@@ -3,7 +3,6 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
 
 #![feature(crate_visibility_modifier)]
-#![cfg_attr(bootstrap, feature(extended_key_value_attributes))]
 #![feature(in_band_lifetimes)]
 #![feature(once_cell)]
 #![feature(min_specialization)]
index 0232654aaa5242c72ad8e2211f93ad6414ee6f3f..560607528330bbd04c187b67b8988567fd02dc6b 100644 (file)
@@ -5,7 +5,7 @@ use crate::hir::{
     TraitItem, TraitItemId, Ty, VisibilityKind,
 };
 use crate::hir_id::{HirId, ItemLocalId};
-use rustc_span::def_id::{DefPathHash, LocalDefId};
+use rustc_span::def_id::DefPathHash;
 
 /// Requirements for a `StableHashingContext` to be used in this crate.
 /// This is a hack to allow using the `HashStable_Generic` derive macro
@@ -21,7 +21,6 @@ pub trait HashStableContext:
     fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher);
     fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher);
     fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F);
-    fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash;
 }
 
 impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for HirId {
@@ -29,7 +28,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for HirId {
 
     #[inline]
     fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
-        let def_path_hash = hcx.local_def_path_hash(self.owner);
+        let def_path_hash = self.owner.to_stable_hash_key(hcx);
         (def_path_hash, self.local_id)
     }
 }
@@ -39,7 +38,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ItemId {
 
     #[inline]
     fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
-        hcx.local_def_path_hash(self.def_id)
+        self.def_id.to_stable_hash_key(hcx)
     }
 }
 
@@ -48,7 +47,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for TraitItemId {
 
     #[inline]
     fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
-        hcx.local_def_path_hash(self.def_id)
+        self.def_id.to_stable_hash_key(hcx)
     }
 }
 
@@ -57,7 +56,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ImplItemId {
 
     #[inline]
     fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
-        hcx.local_def_path_hash(self.def_id)
+        self.def_id.to_stable_hash_key(hcx)
     }
 }
 
@@ -66,7 +65,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ForeignItemId
 
     #[inline]
     fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
-        hcx.local_def_path_hash(self.def_id)
+        self.def_id.to_stable_hash_key(hcx)
     }
 }
 
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 2b932b7c9537ee51a7cb1d007719463707e98150..5c1739b1ab9b63a02be65fa50170dd7baf04bebc 100644 (file)
@@ -1070,8 +1070,6 @@ impl<'a> State<'a> {
     ) {
         match blk.rules {
             hir::BlockCheckMode::UnsafeBlock(..) => self.word_space("unsafe"),
-            hir::BlockCheckMode::PushUnsafeBlock(..) => self.word_space("push_unsafe"),
-            hir::BlockCheckMode::PopUnsafeBlock(..) => self.word_space("pop_unsafe"),
             hir::BlockCheckMode::DefaultBlock => (),
         }
         self.maybe_print_comment(blk.span.lo());
@@ -1446,6 +1444,9 @@ impl<'a> State<'a> {
                 if opts.contains(ast::InlineAsmOptions::ATT_SYNTAX) {
                     options.push("att_syntax");
                 }
+                if opts.contains(ast::InlineAsmOptions::RAW) {
+                    options.push("raw");
+                }
                 s.commasep(Inconsistent, &options, |s, &opt| {
                     s.word(opt);
                 });
@@ -1538,7 +1539,6 @@ impl<'a> State<'a> {
                     self.word_space(":");
                 }
                 self.head("loop");
-                self.s.space();
                 self.print_block(&blk);
             }
             hir::ExprKind::Match(ref expr, arms, _) => {
index 83e80b55daec1b3e2d9eac3bcdc9f7067550ac62..2ed0539841aa30b42f896132fbf02779b70354c6 100644 (file)
@@ -108,7 +108,7 @@ use rustc_data_structures::svh::Svh;
 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 8539cc693713952a356be917bf923b6bc909357f..437d5596447d7a050dbd9949c990298123ecd80a 100644 (file)
@@ -2,7 +2,7 @@
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId};
-use rustc_middle::ty::query::OnDiskCache;
+use rustc_middle::ty::OnDiskCache;
 use rustc_serialize::opaque::Decoder;
 use rustc_serialize::Decodable;
 use rustc_session::Session;
@@ -21,8 +21,8 @@ pub enum LoadResult<T> {
     Error { message: String },
 }
 
-impl LoadResult<(SerializedDepGraph, WorkProductMap)> {
-    pub fn open(self, sess: &Session) -> (SerializedDepGraph, WorkProductMap) {
+impl<T: Default> LoadResult<T> {
+    pub fn open(self, sess: &Session) -> T {
         match self {
             LoadResult::Error { message } => {
                 sess.warn(&message);
@@ -74,11 +74,14 @@ pub enum MaybeAsync<T> {
     Sync(T),
     Async(std::thread::JoinHandle<T>),
 }
-impl<T> MaybeAsync<T> {
-    pub fn open(self) -> std::thread::Result<T> {
+
+impl<T> MaybeAsync<LoadResult<T>> {
+    pub fn open(self) -> LoadResult<T> {
         match self {
-            MaybeAsync::Sync(result) => Ok(result),
-            MaybeAsync::Async(handle) => handle.join(),
+            MaybeAsync::Sync(result) => result,
+            MaybeAsync::Async(handle) => handle.join().unwrap_or_else(|e| LoadResult::Error {
+                message: format!("could not decode incremental cache: {:?}", e),
+            }),
         }
     }
 }
@@ -195,7 +198,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
 /// If we are not in incremental compilation mode, returns `None`.
 /// Otherwise, tries to load the query result cache from disk,
 /// creating an empty cache if it could not be loaded.
-pub fn load_query_result_cache<'a>(sess: &'a Session) -> Option<OnDiskCache<'a>> {
+pub fn load_query_result_cache<'a, C: OnDiskCache<'a>>(sess: &'a Session) -> Option<C> {
     if sess.opts.incremental.is_none() {
         return None;
     }
@@ -207,9 +210,7 @@ pub fn load_query_result_cache<'a>(sess: &'a Session) -> Option<OnDiskCache<'a>>
         &query_cache_path(sess),
         sess.is_nightly_build(),
     ) {
-        LoadResult::Ok { data: (bytes, start_pos) } => {
-            Some(OnDiskCache::new(sess, bytes, start_pos))
-        }
-        _ => Some(OnDiskCache::new_empty(sess.source_map())),
+        LoadResult::Ok { data: (bytes, start_pos) } => Some(C::new(sess, bytes, start_pos)),
+        _ => Some(C::new_empty(sess.source_map())),
     }
 }
index a75ad7b31a64e05acedb5a3141206b08dfd6b708..933373150c1b7991146e50f84e74e5255530aa5b 100644 (file)
@@ -8,7 +8,6 @@ edition = "2018"
 doctest = false
 
 [dependencies]
-rustc_graphviz = { path = "../rustc_graphviz" }
 tracing = "0.1"
 rustc_middle = { path = "../rustc_middle" }
 rustc_data_structures = { path = "../rustc_data_structures" }
@@ -21,4 +20,3 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
-rustc_ast = { path = "../rustc_ast" }
index c68705da413f829401cb03eb7b78d9346d04a16c..448dd6623482cf67f6fbddc93c5921a64b4d4d87 100644 (file)
@@ -46,13 +46,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     {
         self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed);
 
-        Canonicalizer::canonicalize(
-            value,
-            Some(self),
-            self.tcx,
-            &CanonicalizeAllFreeRegions,
-            query_state,
-        )
+        Canonicalizer::canonicalize(value, self, self.tcx, &CanonicalizeAllFreeRegions, query_state)
     }
 
     /// Canonicalizes a query *response* `V`. When we canonicalize a
@@ -87,7 +81,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         let mut query_state = OriginalQueryValues::default();
         Canonicalizer::canonicalize(
             value,
-            Some(self),
+            self,
             self.tcx,
             &CanonicalizeQueryResponse,
             &mut query_state,
@@ -101,27 +95,18 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         let mut query_state = OriginalQueryValues::default();
         Canonicalizer::canonicalize(
             value,
-            Some(self),
+            self,
             self.tcx,
             &CanonicalizeUserTypeAnnotation,
             &mut query_state,
         )
     }
 
-    /// A hacky variant of `canonicalize_query` that does not
-    /// canonicalize `'static`. Unfortunately, the existing leak
-    /// check treats `'static` differently in some cases (see also
-    /// #33684), so if we are performing an operation that may need to
-    /// prove "leak-check" related things, we leave `'static`
-    /// alone.
-    ///
-    /// `'static` is also special cased when winnowing candidates when
-    /// selecting implementation candidates, so we also have to leave `'static`
-    /// alone for queries that do selection.
-    //
-    // FIXME(#48536): once the above issues are resolved, we can remove this
-    // and just use `canonicalize_query`.
-    pub fn canonicalize_hr_query_hack<V>(
+    /// A variant of `canonicalize_query` that does not
+    /// canonicalize `'static`. This is useful when
+    /// the query implementation can perform more efficient
+    /// handling of `'static` regions (e.g. trait evaluation).
+    pub fn canonicalize_query_keep_static<V>(
         &self,
         value: V,
         query_state: &mut OriginalQueryValues<'tcx>,
@@ -133,7 +118,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
 
         Canonicalizer::canonicalize(
             value,
-            Some(self),
+            self,
             self.tcx,
             &CanonicalizeFreeRegionsOtherThanStatic,
             query_state,
@@ -275,7 +260,7 @@ impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic {
 }
 
 struct Canonicalizer<'cx, 'tcx> {
-    infcx: Option<&'cx InferCtxt<'cx, 'tcx>>,
+    infcx: &'cx InferCtxt<'cx, 'tcx>,
     tcx: TyCtxt<'tcx>,
     variables: SmallVec<[CanonicalVarInfo<'tcx>; 8]>,
     query_state: &'cx mut OriginalQueryValues<'tcx>,
@@ -316,7 +301,6 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
             ty::ReVar(vid) => {
                 let resolved_vid = self
                     .infcx
-                    .unwrap()
                     .inner
                     .borrow_mut()
                     .unwrap_region_constraints()
@@ -343,7 +327,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
         match *t.kind() {
             ty::Infer(ty::TyVar(vid)) => {
                 debug!("canonical: type var found with vid {:?}", vid);
-                match self.infcx.unwrap().probe_ty_var(vid) {
+                match self.infcx.probe_ty_var(vid) {
                     // `t` could be a float / int variable; canonicalize that instead.
                     Ok(t) => {
                         debug!("(resolved to {:?})", t);
@@ -429,7 +413,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
         match ct.val {
             ty::ConstKind::Infer(InferConst::Var(vid)) => {
                 debug!("canonical: const var found with vid {:?}", vid);
-                match self.infcx.unwrap().probe_const_var(vid) {
+                match self.infcx.probe_const_var(vid) {
                     Ok(c) => {
                         debug!("(resolved to {:?})", c);
                         return self.fold_const(c);
@@ -476,7 +460,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
     /// `canonicalize_query` and `canonicalize_response`.
     fn canonicalize<V>(
         value: V,
-        infcx: Option<&InferCtxt<'_, 'tcx>>,
+        infcx: &InferCtxt<'_, 'tcx>,
         tcx: TyCtxt<'tcx>,
         canonicalize_region_mode: &dyn CanonicalizeRegionMode,
         query_state: &mut OriginalQueryValues<'tcx>,
@@ -610,7 +594,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
 
     /// Returns the universe in which `vid` is defined.
     fn region_var_universe(&self, vid: ty::RegionVid) -> ty::UniverseIndex {
-        self.infcx.unwrap().inner.borrow_mut().unwrap_region_constraints().var_universe(vid)
+        self.infcx.inner.borrow_mut().unwrap_region_constraints().var_universe(vid)
     }
 
     /// Creates a canonical variable (with the given `info`)
@@ -631,7 +615,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
     /// *that*. Otherwise, create a new canonical variable for
     /// `ty_var`.
     fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo<'tcx>, ty_var: Ty<'tcx>) -> Ty<'tcx> {
-        let infcx = self.infcx.expect("encountered ty-var without infcx");
+        let infcx = self.infcx;
         let bound_to = infcx.shallow_resolve(ty_var);
         if bound_to != ty_var {
             self.fold_ty(bound_to)
@@ -650,7 +634,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
         info: CanonicalVarInfo<'tcx>,
         const_var: &'tcx ty::Const<'tcx>,
     ) -> &'tcx ty::Const<'tcx> {
-        let infcx = self.infcx.expect("encountered const-var without infcx");
+        let infcx = self.infcx;
         let bound_to = infcx.shallow_resolve(const_var);
         if bound_to != const_var {
             self.fold_const(bound_to)
index e3a79fe2653305da6414187b0301b48d9f660ad0..f885c0a4b87bd1f6c42312128203d18381cb6227 100644 (file)
@@ -995,7 +995,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let get_lifetimes = |sig| {
             use rustc_hir::def::Namespace;
             let mut s = String::new();
-            let (_, (sig, reg)) = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS)
+            let (_, sig, reg) = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS)
                 .name_all_regions(sig)
                 .unwrap();
             let lts: Vec<String> = reg.into_iter().map(|(_, kind)| kind.to_string()).collect();
@@ -1590,17 +1590,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             }
         };
         if let Some((expected, found)) = expected_found {
-            let expected_label = match exp_found {
-                Mismatch::Variable(ef) => ef.expected.prefix_string(self.tcx),
-                Mismatch::Fixed(s) => s.into(),
-            };
-            let found_label = match exp_found {
-                Mismatch::Variable(ef) => ef.found.prefix_string(self.tcx),
-                Mismatch::Fixed(s) => s.into(),
-            };
-            let exp_found = match exp_found {
-                Mismatch::Variable(exp_found) => Some(exp_found),
-                Mismatch::Fixed(_) => None,
+            let (expected_label, found_label, exp_found) = match exp_found {
+                Mismatch::Variable(ef) => (
+                    ef.expected.prefix_string(self.tcx),
+                    ef.found.prefix_string(self.tcx),
+                    Some(ef),
+                ),
+                Mismatch::Fixed(s) => (s.into(), s.into(), None),
             };
             match (&terr, expected == found) {
                 (TypeError::Sorts(values), extra) => {
@@ -2134,7 +2130,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let new_lt = generics
             .as_ref()
             .and_then(|(parent_g, g)| {
-                let possible: Vec<_> = (b'a'..=b'z').map(|c| format!("'{}", c as char)).collect();
+                let mut possible = (b'a'..=b'z').map(|c| format!("'{}", c as char));
                 let mut lts_names = g
                     .params
                     .iter()
@@ -2150,7 +2146,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     );
                 }
                 let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::<Vec<_>>();
-                possible.into_iter().find(|candidate| !lts.contains(&candidate.as_str()))
+                possible.find(|candidate| !lts.contains(&candidate.as_str()))
             })
             .unwrap_or("'lt".to_string());
         let add_lt_sugg = generics
index d9a1193aac4bafc0f02516e3480ea48a2f1dd3c1..9a718102cf11d8d225cab04a461eadd1ac2bebae 100644 (file)
@@ -491,11 +491,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             span
         };
 
-        let is_named_and_not_impl_trait = |ty: Ty<'_>| {
-            &ty.to_string() != "_" &&
-                // FIXME: Remove this check after `impl_trait_in_bindings` is stabilized. #63527
-                (!ty.is_impl_trait() || self.tcx.features().impl_trait_in_bindings)
-        };
+        let is_named_and_not_impl_trait =
+            |ty: Ty<'_>| &ty.to_string() != "_" && !ty.is_impl_trait();
 
         let ty_msg = match (local_visitor.found_node_ty, local_visitor.found_exact_method_call) {
             (_, Some(_)) => String::new(),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
new file mode 100644 (file)
index 0000000..cca1954
--- /dev/null
@@ -0,0 +1,103 @@
+//! Error Reporting for when the lifetime for a type doesn't match the `impl` selected for a predicate
+//! to hold.
+
+use crate::infer::error_reporting::nice_region_error::NiceRegionError;
+use crate::infer::error_reporting::note_and_explain_region;
+use crate::infer::lexical_region_resolve::RegionResolutionError;
+use crate::infer::{SubregionOrigin, TypeTrace};
+use crate::traits::ObligationCauseCode;
+use rustc_data_structures::stable_set::FxHashSet;
+use rustc_errors::{Applicability, ErrorReported};
+use rustc_hir as hir;
+use rustc_hir::intravisit::Visitor;
+use rustc_middle::ty::{self, TypeVisitor};
+use rustc_span::MultiSpan;
+
+impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
+    pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorReported> {
+        let error = self.error.as_ref()?;
+        debug!("try_report_mismatched_static_lifetime {:?}", error);
+
+        let (origin, sub, sup) = match error.clone() {
+            RegionResolutionError::ConcreteFailure(origin, sub, sup) => (origin, sub, sup),
+            _ => return None,
+        };
+        if *sub != ty::RegionKind::ReStatic {
+            return None;
+        }
+        let cause = match origin {
+            SubregionOrigin::Subtype(box TypeTrace { ref cause, .. }) => cause,
+            _ => return None,
+        };
+        let (parent, impl_def_id) = match &cause.code {
+            ObligationCauseCode::MatchImpl(parent, impl_def_id) => (parent, impl_def_id),
+            _ => return None,
+        };
+        let binding_span = match **parent {
+            ObligationCauseCode::BindingObligation(_def_id, binding_span) => binding_span,
+            _ => return None,
+        };
+        let mut err = self.tcx().sess.struct_span_err(cause.span, "incompatible lifetime on type");
+        // FIXME: we should point at the lifetime
+        let mut multi_span: MultiSpan = vec![binding_span].into();
+        multi_span
+            .push_span_label(binding_span, "introduces a `'static` lifetime requirement".into());
+        err.span_note(multi_span, "because this has an unmet lifetime requirement");
+        note_and_explain_region(self.tcx(), &mut err, "", sup, "...");
+        if let Some(impl_node) = self.tcx().hir().get_if_local(*impl_def_id) {
+            // If an impl is local, then maybe this isn't what they want. Try to
+            // be as helpful as possible with implicit lifetimes.
+
+            // First, let's get the hir self type of the impl
+            let impl_self_ty = match impl_node {
+                hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Impl(hir::Impl { self_ty, .. }),
+                    ..
+                }) => self_ty,
+                _ => bug!("Node not an impl."),
+            };
+
+            // Next, let's figure out the set of trait objects with implict static bounds
+            let ty = self.tcx().type_of(*impl_def_id);
+            let mut v = super::static_impl_trait::TraitObjectVisitor(FxHashSet::default());
+            v.visit_ty(ty);
+            let mut traits = vec![];
+            for matching_def_id in v.0 {
+                let mut hir_v =
+                    super::static_impl_trait::HirTraitObjectVisitor(&mut traits, matching_def_id);
+                hir_v.visit_ty(&impl_self_ty);
+            }
+
+            if traits.is_empty() {
+                // If there are no trait object traits to point at, either because
+                // there aren't trait objects or because none are implicit, then just
+                // write a single note on the impl itself.
+
+                let impl_span = self.tcx().def_span(*impl_def_id);
+                err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
+            } else {
+                // Otherwise, point at all implicit static lifetimes
+
+                err.note("...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
+                for span in &traits {
+                    err.span_note(*span, "this has an implicit `'static` lifetime requirement");
+                    // It would be nice to put this immediately under the above note, but they get
+                    // pushed to the end.
+                    err.span_suggestion_verbose(
+                        span.shrink_to_hi(),
+                        "consider relaxing the implicit `'static` requirement",
+                        " + '_".to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+            }
+        } else {
+            // Otherwise just point out the impl.
+
+            let impl_span = self.tcx().def_span(*impl_def_id);
+            err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
+        }
+        err.emit();
+        Some(ErrorReported)
+    }
+}
index e20436690b3aa1d42309ea097afa3fa5bc216218..3f27bf67b59a91d357eb88806d2186b881d49b9b 100644 (file)
@@ -7,6 +7,7 @@ use rustc_span::source_map::Span;
 
 mod different_lifetimes;
 pub mod find_anon_type;
+mod mismatched_static_lifetime;
 mod named_anon_conflict;
 mod placeholder_error;
 mod static_impl_trait;
@@ -58,6 +59,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
             .or_else(|| self.try_report_impl_not_conforming_to_trait())
             .or_else(|| self.try_report_anon_anon_conflict())
             .or_else(|| self.try_report_static_impl_trait())
+            .or_else(|| self.try_report_mismatched_static_lifetime())
     }
 
     pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> {
index 1e926989263c9cb66ea81f0eb7a356a6f6cbd3c4..fde4ec05ffc867f74ec0aeced86aa748bc26d07e 100644 (file)
@@ -4,6 +4,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::infer::{SubregionOrigin, TypeTrace};
 use crate::traits::{ObligationCauseCode, UnifyReceiverContext};
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor};
@@ -185,17 +186,20 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             }
         }
         if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin {
-            if let ObligationCauseCode::ItemObligation(item_def_id) = cause.code {
+            let code = match &cause.code {
+                ObligationCauseCode::MatchImpl(parent, ..) => &**parent,
+                _ => &cause.code,
+            };
+            if let ObligationCauseCode::ItemObligation(item_def_id) = *code {
                 // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static`
                 // lifetime as above, but called using a fully-qualified path to the method:
                 // `Foo::qux(bar)`.
-                let mut v = TraitObjectVisitor(vec![]);
+                let mut v = TraitObjectVisitor(FxHashSet::default());
                 v.visit_ty(param.param_ty);
                 if let Some((ident, self_ty)) =
-                    self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0[..])
+                    self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0)
                 {
-                    if self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0[..], ident, self_ty)
-                    {
+                    if self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0, ident, self_ty) {
                         override_error_code = Some(ident);
                     }
                 }
@@ -336,7 +340,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     fn get_impl_ident_and_self_ty_from_trait(
         &self,
         def_id: DefId,
-        trait_objects: &[DefId],
+        trait_objects: &FxHashSet<DefId>,
     ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
         let tcx = self.tcx();
         match tcx.hir().get_if_local(def_id) {
@@ -373,9 +377,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                                         // multiple `impl`s for the same trait like
                                         // `impl Foo for Box<dyn Bar>` and `impl Foo for dyn Bar`.
                                         // In that case, only the first one will get suggestions.
-                                        let mut hir_v = HirTraitObjectVisitor(vec![], *did);
+                                        let mut traits = vec![];
+                                        let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
                                         hir_v.visit_ty(self_ty);
-                                        !hir_v.0.is_empty()
+                                        !traits.is_empty()
                                     }) =>
                                     {
                                         Some(self_ty)
@@ -417,33 +422,34 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             _ => return false,
         };
 
-        let mut v = TraitObjectVisitor(vec![]);
+        let mut v = TraitObjectVisitor(FxHashSet::default());
         v.visit_ty(ty);
 
         // Get the `Ident` of the method being called and the corresponding `impl` (to point at
         // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called).
         let (ident, self_ty) =
-            match self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &v.0[..]) {
+            match self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &v.0) {
                 Some((ident, self_ty)) => (ident, self_ty),
                 None => return false,
             };
 
         // Find the trait object types in the argument, so we point at *only* the trait object.
-        self.suggest_constrain_dyn_trait_in_impl(err, &v.0[..], ident, self_ty)
+        self.suggest_constrain_dyn_trait_in_impl(err, &v.0, ident, self_ty)
     }
 
     fn suggest_constrain_dyn_trait_in_impl(
         &self,
         err: &mut DiagnosticBuilder<'_>,
-        found_dids: &[DefId],
+        found_dids: &FxHashSet<DefId>,
         ident: Ident,
         self_ty: &hir::Ty<'_>,
     ) -> bool {
         let mut suggested = false;
         for found_did in found_dids {
-            let mut hir_v = HirTraitObjectVisitor(vec![], *found_did);
+            let mut traits = vec![];
+            let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did);
             hir_v.visit_ty(&self_ty);
-            for span in &hir_v.0 {
+            for span in &traits {
                 let mut multi_span: MultiSpan = vec![*span].into();
                 multi_span.push_span_label(
                     *span,
@@ -468,14 +474,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
 }
 
 /// Collect all the trait objects in a type that could have received an implicit `'static` lifetime.
-struct TraitObjectVisitor(Vec<DefId>);
+pub(super) struct TraitObjectVisitor(pub(super) FxHashSet<DefId>);
 
 impl TypeVisitor<'_> for TraitObjectVisitor {
     fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> {
         match t.kind() {
             ty::Dynamic(preds, RegionKind::ReStatic) => {
                 if let Some(def_id) = preds.principal_def_id() {
-                    self.0.push(def_id);
+                    self.0.insert(def_id);
                 }
                 ControlFlow::CONTINUE
             }
@@ -485,9 +491,9 @@ impl TypeVisitor<'_> for TraitObjectVisitor {
 }
 
 /// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime.
-struct HirTraitObjectVisitor(Vec<Span>, DefId);
+pub(super) struct HirTraitObjectVisitor<'a>(pub(super) &'a mut Vec<Span>, pub(super) DefId);
 
-impl<'tcx> Visitor<'tcx> for HirTraitObjectVisitor {
+impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
     type Map = ErasedMap<'tcx>;
 
     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
index 17a56046a5cc89b39c2c2b5611f4c89655b90d70..8dcdd4b149ea6c23ebe17f76468726dc4ed92ae2 100644 (file)
@@ -56,33 +56,42 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap();
         let poly_fn_sig = self.tcx().fn_sig(id);
         let fn_sig = self.tcx().liberate_late_bound_regions(id, poly_fn_sig);
-        body.params.iter().enumerate().find_map(|(index, param)| {
-            // May return None; sometimes the tables are not yet populated.
-            let ty = fn_sig.inputs()[index];
-            let mut found_anon_region = false;
-            let new_param_ty = self.tcx().fold_regions(ty, &mut false, |r, _| {
-                if *r == *anon_region {
-                    found_anon_region = true;
-                    replace_region
+        body.params
+            .iter()
+            .take(if fn_sig.c_variadic {
+                fn_sig.inputs().len()
+            } else {
+                assert_eq!(fn_sig.inputs().len(), body.params.len());
+                body.params.len()
+            })
+            .enumerate()
+            .find_map(|(index, param)| {
+                // May return None; sometimes the tables are not yet populated.
+                let ty = fn_sig.inputs()[index];
+                let mut found_anon_region = false;
+                let new_param_ty = self.tcx().fold_regions(ty, &mut false, |r, _| {
+                    if *r == *anon_region {
+                        found_anon_region = true;
+                        replace_region
+                    } else {
+                        r
+                    }
+                });
+                if found_anon_region {
+                    let ty_hir_id = fn_decl.inputs[index].hir_id;
+                    let param_ty_span = hir.span(ty_hir_id);
+                    let is_first = index == 0;
+                    Some(AnonymousParamInfo {
+                        param,
+                        param_ty: new_param_ty,
+                        param_ty_span,
+                        bound_region,
+                        is_first,
+                    })
                 } else {
-                    r
+                    None
                 }
-            });
-            if found_anon_region {
-                let ty_hir_id = fn_decl.inputs[index].hir_id;
-                let param_ty_span = hir.span(ty_hir_id);
-                let is_first = index == 0;
-                Some(AnonymousParamInfo {
-                    param,
-                    param_ty: new_param_ty,
-                    param_ty_span,
-                    bound_region,
-                    is_first,
-                })
-            } else {
-                None
-            }
-        })
+            })
     }
 
     pub(super) fn future_return_type(
index b3d7876c6e81922c91e25ea4ea10bd911b2cdd40..4af1bdf97a773f7e9796b857d02ce31ff6f24b32 100644 (file)
@@ -47,16 +47,18 @@ pub struct TypeFreshener<'a, 'tcx> {
     const_freshen_count: u32,
     ty_freshen_map: FxHashMap<ty::InferTy, Ty<'tcx>>,
     const_freshen_map: FxHashMap<ty::InferConst<'tcx>, &'tcx ty::Const<'tcx>>,
+    keep_static: bool,
 }
 
 impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> TypeFreshener<'a, 'tcx> {
+    pub fn new(infcx: &'a InferCtxt<'a, 'tcx>, keep_static: bool) -> TypeFreshener<'a, 'tcx> {
         TypeFreshener {
             infcx,
             ty_freshen_count: 0,
             const_freshen_count: 0,
             ty_freshen_map: Default::default(),
             const_freshen_map: Default::default(),
+            keep_static,
         }
     }
 
@@ -124,8 +126,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
                 r
             }
 
-            ty::ReStatic
-            | ty::ReEarlyBound(..)
+            ty::ReEarlyBound(..)
             | ty::ReFree(_)
             | ty::ReVar(_)
             | ty::RePlaceholder(..)
@@ -134,6 +135,13 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
                 // replace all free regions with 'erased
                 self.tcx().lifetimes.re_erased
             }
+            ty::ReStatic => {
+                if self.keep_static {
+                    r
+                } else {
+                    self.tcx().lifetimes.re_erased
+                }
+            }
         }
     }
 
index ab34cda8cc18f514edec1adcd522ea453b05d3cd..869fd225d5114766625630418f73d2b61023dd1c 100644 (file)
@@ -638,6 +638,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
             let sub = var_data.normalize(self.tcx(), verify.region);
 
             let verify_kind_ty = verify.kind.to_ty(self.tcx());
+            let verify_kind_ty = var_data.normalize(self.tcx(), verify_kind_ty);
             if self.bound_is_met(&verify.bound, var_data, verify_kind_ty, sub) {
                 continue;
             }
index f39431f2494b1868f53c19f58ff893eb0c93a614..d3bfb2b2e4428090a07ea433f4f8de16598929ba 100644 (file)
@@ -646,7 +646,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
 
     pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'tcx> {
-        freshen::TypeFreshener::new(self)
+        freshen::TypeFreshener::new(self, false)
+    }
+
+    /// Like `freshener`, but does not replace `'static` regions.
+    pub fn freshener_keep_static<'b>(&'b self) -> TypeFreshener<'b, 'tcx> {
+        freshen::TypeFreshener::new(self, true)
     }
 
     pub fn type_is_unconstrained_numeric(&'a self, ty: Ty<'_>) -> UnconstrainedNumeric {
index 4935913016262bbabe29e320bba3c5072e77747b..7f4c33c5792cbb4d58438b49ca5abd96769711e5 100644 (file)
@@ -674,7 +674,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         self.combine_map(t).insert(vars, c);
         self.undo_log.push(AddCombination(t, vars));
         let new_r = tcx.mk_region(ReVar(c));
-        for &old_r in &[a, b] {
+        for old_r in [a, b] {
             match t {
                 Glb => self.make_subregion(origin.clone(), new_r, old_r),
                 Lub => self.make_subregion(origin.clone(), old_r, new_r),
index 683c1df783e63e2d85e1cb4126755bfb6f43484e..13b78b26af4244a6d1ea6803a26c2d6de4113afb 100644 (file)
@@ -400,6 +400,7 @@ impl<'tcx> From<ty::TyVid> for TyVidEqKey<'tcx> {
 
 impl<'tcx> ut::UnifyKey for TyVidEqKey<'tcx> {
     type Value = TypeVariableValue<'tcx>;
+    #[inline(always)]
     fn index(&self) -> u32 {
         self.vid.index
     }
index a33234a91faff47333f0c07dd49e7e7398d5ab52..d5c17ede2143d4b8fdbc459a399a6ac5e5351da1 100644 (file)
@@ -70,6 +70,10 @@ pub struct FulfillmentError<'tcx> {
     /// obligation error caused by a call argument. When this is the case, we also signal that in
     /// this field to ensure accuracy of suggestions.
     pub points_at_arg_span: bool,
+    /// Diagnostics only: the 'root' obligation which resulted in
+    /// the failure to process `obligation`. This is the obligation
+    /// that was initially passed to `register_predicate_obligation`
+    pub root_obligation: PredicateObligation<'tcx>,
 }
 
 #[derive(Clone)]
@@ -122,8 +126,9 @@ impl<'tcx> FulfillmentError<'tcx> {
     pub fn new(
         obligation: PredicateObligation<'tcx>,
         code: FulfillmentErrorCode<'tcx>,
+        root_obligation: PredicateObligation<'tcx>,
     ) -> FulfillmentError<'tcx> {
-        FulfillmentError { obligation, code, points_at_arg_span: false }
+        FulfillmentError { obligation, code, points_at_arg_span: false, root_obligation }
     }
 }
 
index 194464dd0bf9c974c76392cd03c100569d9eebfb..85493978d9d1eb4799e505280bed420aca659217 100644 (file)
@@ -31,7 +31,6 @@ rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
 rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
 rustc_codegen_llvm = { path = "../rustc_codegen_llvm", optional = true }
 rustc_hir = { path = "../rustc_hir" }
-rustc_index = { path = "../rustc_index" }
 rustc_metadata = { path = "../rustc_metadata" }
 rustc_mir = { path = "../rustc_mir" }
 rustc_mir_build = { path = "../rustc_mir_build" }
index a1090ee316db48881a508485b2d1f31dd052f7ba..8393826aa12855d367279be6e8613c0ad7cf050d 100644 (file)
@@ -12,6 +12,7 @@ use rustc_errors::{ErrorReported, Handler};
 use rustc_lint::LintStore;
 use rustc_middle::ty;
 use rustc_parse::new_parser_from_source_str;
+use rustc_query_impl::QueryCtxt;
 use rustc_session::config::{self, ErrorOutputType, Input, OutputFilenames};
 use rustc_session::early_error;
 use rustc_session::lint;
@@ -76,7 +77,7 @@ impl Compiler {
 
 /// 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| {
@@ -233,7 +234,7 @@ pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
     // state if it was responsible for triggering the panic.
     let i = ty::tls::with_context_opt(|icx| {
         if let Some(icx) = icx {
-            icx.tcx.queries.try_print_query_stack(icx.tcx, icx.query, handler, num_frames)
+            QueryCtxt::from_tcx(icx.tcx).try_print_query_stack(icx.query, handler, num_frames)
         } else {
             0
         }
index 9e3e96df3a7f2effe50a5f0787c95d8f5eb8e8f8..5db027fb5b4734f6ab0be6de711ed6c3abe3d8f1 100644 (file)
@@ -7,19 +7,18 @@ use rustc_ast::{self as ast, visit};
 use rustc_codegen_ssa::back::link::emit_metadata;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::parallel;
-use rustc_data_structures::steal::Steal;
 use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal};
 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;
 use rustc_middle::arena::Arena;
 use rustc_middle::dep_graph::DepGraph;
 use rustc_middle::middle;
-use rustc_middle::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn};
+use rustc_middle::middle::cstore::{MetadataLoader, MetadataLoaderDyn};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt};
 use rustc_mir as mir;
@@ -27,20 +26,20 @@ use rustc_mir_build as mir_build;
 use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
 use rustc_passes::{self, hir_stats, layout_test};
 use rustc_plugin_impl as plugin;
-use rustc_query_impl::Queries as TcxQueries;
+use rustc_query_impl::{OnDiskCache, Queries as TcxQueries};
 use rustc_resolve::{Resolver, ResolverArenas};
+use rustc_serialize::json;
 use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType, PpMode, PpSourceMode};
 use rustc_session::lint;
 use rustc_session::output::{filename_for_input, filename_for_metadata};
 use rustc_session::search_paths::PathKind;
 use rustc_session::Session;
 use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::FileName;
 use rustc_trait_selection::traits;
 use rustc_typeck as typeck;
-use tracing::{info, warn};
-
-use rustc_serialize::json;
 use tempfile::Builder as TempFileBuilder;
+use tracing::{info, warn};
 
 use std::any::Any;
 use std::cell::RefCell;
@@ -101,7 +100,7 @@ mod boxed_resolver {
     }
 
     // Note: Drop order is important to prevent dangling references. Resolver must be dropped first,
-    // then resolver_arenas and finally session.
+    // then resolver_arenas and session.
     impl Drop for BoxedResolverInner {
         fn drop(&mut self) {
             self.resolver.take();
@@ -110,13 +109,10 @@ mod boxed_resolver {
     }
 
     impl BoxedResolver {
-        pub(super) fn new<F>(session: Lrc<Session>, make_resolver: F) -> Result<(ast::Crate, Self)>
-        where
-            F: for<'a> FnOnce(
-                &'a Session,
-                &'a ResolverArenas<'a>,
-            ) -> Result<(ast::Crate, Resolver<'a>)>,
-        {
+        pub(super) fn new(
+            session: Lrc<Session>,
+            make_resolver: impl for<'a> FnOnce(&'a Session, &'a ResolverArenas<'a>) -> Resolver<'a>,
+        ) -> BoxedResolver {
             let mut boxed_resolver = Box::new(BoxedResolverInner {
                 session,
                 resolver_arenas: Some(Resolver::arenas()),
@@ -127,14 +123,14 @@ mod boxed_resolver {
             // returns a resolver with the same lifetime as the arena. We ensure that the arena
             // outlives the resolver in the drop impl and elsewhere so these transmutes are sound.
             unsafe {
-                let (crate_, resolver) = make_resolver(
+                let resolver = make_resolver(
                     std::mem::transmute::<&Session, &Session>(&boxed_resolver.session),
                     std::mem::transmute::<&ResolverArenas<'_>, &ResolverArenas<'_>>(
                         boxed_resolver.resolver_arenas.as_ref().unwrap(),
                     ),
-                )?;
+                );
                 boxed_resolver.resolver = Some(resolver);
-                Ok((crate_, BoxedResolver(Pin::new_unchecked(boxed_resolver))))
+                BoxedResolver(Pin::new_unchecked(boxed_resolver))
             }
         }
 
@@ -165,35 +161,15 @@ mod boxed_resolver {
     }
 }
 
-/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins,
-/// syntax expansion, secondary `cfg` expansion, synthesis of a test
-/// harness if one is to be provided, injection of a dependency on the
-/// standard library and prelude, and name resolution.
-///
-/// Returns [`None`] if we're aborting after handling -W help.
-pub fn configure_and_expand(
+pub fn create_resolver(
     sess: Lrc<Session>,
-    lint_store: Lrc<LintStore>,
     metadata_loader: Box<MetadataLoaderDyn>,
-    krate: ast::Crate,
+    krate: &ast::Crate,
     crate_name: &str,
-) -> Result<(ast::Crate, BoxedResolver)> {
-    tracing::trace!("configure_and_expand");
-    // Currently, we ignore the name resolution data structures for the purposes of dependency
-    // tracking. Instead we will run name resolution and include its output in the hash of each
-    // item, much like we do for macro expansion. In other words, the hash reflects not just
-    // its contents but the results of name resolution on those contents. Hopefully we'll push
-    // this back at some point.
-    let crate_name = crate_name.to_string();
+) -> BoxedResolver {
+    tracing::trace!("create_resolver");
     BoxedResolver::new(sess, move |sess, resolver_arenas| {
-        configure_and_expand_inner(
-            sess,
-            &lint_store,
-            krate,
-            &crate_name,
-            &resolver_arenas,
-            metadata_loader,
-        )
+        Resolver::new(sess, &krate, &crate_name, metadata_loader, &resolver_arenas)
     })
 }
 
@@ -219,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", || {
@@ -235,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(),
@@ -278,28 +254,24 @@ fn pre_expansion_lint(
     });
 }
 
-fn configure_and_expand_inner<'a>(
-    sess: &'a Session,
+/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins,
+/// syntax expansion, secondary `cfg` expansion, synthesis of a test
+/// harness if one is to be provided, injection of a dependency on the
+/// standard library and prelude, and name resolution.
+pub fn configure_and_expand(
+    sess: &Session,
     lint_store: &LintStore,
     mut krate: ast::Crate,
     crate_name: &str,
-    resolver_arenas: &'a ResolverArenas<'a>,
-    metadata_loader: Box<MetadataLoaderDyn>,
-) -> Result<(ast::Crate, Resolver<'a>)> {
-    tracing::trace!("configure_and_expand_inner");
+    resolver: &mut Resolver<'_>,
+) -> Result<ast::Crate> {
+    tracing::trace!("configure_and_expand");
     pre_expansion_lint(sess, lint_store, &krate, crate_name);
-
-    let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas);
-    rustc_builtin_macros::register_builtin_macros(&mut resolver);
+    rustc_builtin_macros::register_builtin_macros(resolver);
 
     krate = sess.time("crate_injection", || {
         let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s));
-        rustc_builtin_macros::standard_library_imports::inject(
-            krate,
-            &mut resolver,
-            &sess,
-            alt_std_name,
-        )
+        rustc_builtin_macros::standard_library_imports::inject(krate, resolver, &sess, alt_std_name)
     });
 
     util::check_attr_crate_type(&sess, &krate.attrs, &mut resolver.lint_buffer());
@@ -339,9 +311,11 @@ fn configure_and_expand_inner<'a>(
 
         // 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,
@@ -354,7 +328,7 @@ fn configure_and_expand_inner<'a>(
             pre_expansion_lint(sess, lint_store, &krate, &ident.name.as_str());
             (krate.attrs, krate.items)
         };
-        let mut ecx = ExtCtxt::new(&sess, cfg, &mut resolver, Some(&extern_mod_loaded));
+        let mut ecx = ExtCtxt::new(&sess, cfg, resolver, Some(&extern_mod_loaded));
 
         // Expand macros now!
         let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate));
@@ -396,16 +370,16 @@ fn configure_and_expand_inner<'a>(
     })?;
 
     sess.time("maybe_building_test_harness", || {
-        rustc_builtin_macros::test_harness::inject(&sess, &mut resolver, &mut krate)
+        rustc_builtin_macros::test_harness::inject(&sess, resolver, &mut krate)
     });
 
     if let Some(PpMode::Source(PpSourceMode::EveryBodyLoops)) = sess.opts.pretty {
         tracing::debug!("replacing bodies with loop {{}}");
-        util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate);
+        util::ReplaceBodyWithLoop::new(resolver).visit_crate(&mut krate);
     }
 
     let has_proc_macro_decls = sess.time("AST_validation", || {
-        rustc_ast_passes::ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer())
+        rustc_ast_passes::ast_validation::check_crate(sess, &krate, resolver.lint_buffer())
     });
 
     let crate_types = sess.crate_types();
@@ -431,7 +405,7 @@ fn configure_and_expand_inner<'a>(
             let is_test_crate = sess.opts.test;
             rustc_builtin_macros::proc_macro_harness::inject(
                 &sess,
-                &mut resolver,
+                resolver,
                 krate,
                 is_proc_macro_crate,
                 has_proc_macro_decls,
@@ -471,26 +445,20 @@ fn configure_and_expand_inner<'a>(
         }
     });
 
-    Ok((krate, resolver))
+    Ok(krate)
 }
 
 pub fn lower_to_hir<'res, 'tcx>(
     sess: &'tcx Session,
     lint_store: &LintStore,
     resolver: &'res mut Resolver<'_>,
-    dep_graph: &'res DepGraph,
-    krate: &'res ast::Crate,
+    krate: Rc<ast::Crate>,
     arena: &'tcx rustc_ast_lowering::Arena<'tcx>,
-) -> Crate<'tcx> {
-    // We're constructing the HIR here; we don't care what we will
-    // read, since we haven't even constructed the *input* to
-    // incr. comp. yet.
-    dep_graph.assert_ignored();
-
+) -> &'tcx Crate<'tcx> {
     // Lower AST to HIR.
     let hir_crate = rustc_ast_lowering::lower_crate(
         sess,
-        &krate,
+        &*krate,
         resolver,
         rustc_parse::nt_to_tokenstream,
         arena,
@@ -511,6 +479,9 @@ pub fn lower_to_hir<'res, 'tcx>(
         )
     });
 
+    // Drop AST to free memory
+    sess.time("drop_ast", || std::mem::drop(krate));
+
     // Discard hygiene data, which isn't required after lowering to HIR.
     if !sess.opts.debugging_opts.keep_hygiene_data {
         rustc_span::hygiene::clear_syntax_context_map();
@@ -581,7 +552,7 @@ fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<PathBuf> {
 
 fn escape_dep_filename(filename: &String) -> String {
     // Apparently clang and gcc *only* escape spaces:
-    // http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
+    // https://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
     filename.replace(" ", "\\ ")
 }
 
@@ -603,7 +574,7 @@ fn escape_dep_env(symbol: Symbol) -> String {
 
 fn write_out_deps(
     sess: &Session,
-    boxed_resolver: &Steal<Rc<RefCell<BoxedResolver>>>,
+    boxed_resolver: &RefCell<BoxedResolver>,
     outputs: &OutputFilenames,
     out_filenames: &[PathBuf],
 ) {
@@ -625,12 +596,22 @@ fn write_out_deps(
             .map(|fmap| escape_dep_filename(&fmap.name.prefer_local().to_string()))
             .collect();
 
+        // Account for explicitly marked-to-track files
+        // (e.g. accessed in proc macros).
+        let file_depinfo = sess.parse_sess.file_depinfo.borrow();
+        let extra_tracked_files = file_depinfo.iter().map(|path_sym| {
+            let path = PathBuf::from(&*path_sym.as_str());
+            let file = FileName::from(path);
+            escape_dep_filename(&file.prefer_local().to_string())
+        });
+        files.extend(extra_tracked_files);
+
         if let Some(ref backend) = sess.opts.debugging_opts.codegen_backend {
             files.push(backend.to_string());
         }
 
         if sess.binary_dep_depinfo() {
-            boxed_resolver.borrow().borrow_mut().access(|resolver| {
+            boxed_resolver.borrow_mut().access(|resolver| {
                 for cnum in resolver.cstore().crates_untracked() {
                     let source = resolver.cstore().crate_source_untracked(cnum);
                     if let Some((path, _)) = source.dylib {
@@ -699,7 +680,7 @@ pub fn prepare_outputs(
     sess: &Session,
     compiler: &Compiler,
     krate: &ast::Crate,
-    boxed_resolver: &Steal<Rc<RefCell<BoxedResolver>>>,
+    boxed_resolver: &RefCell<BoxedResolver>,
     crate_name: &str,
 ) -> Result<OutputFilenames> {
     let _timer = sess.timer("prepare_outputs");
@@ -803,16 +784,26 @@ impl<'tcx> QueryContext<'tcx> {
 pub fn create_global_ctxt<'tcx>(
     compiler: &'tcx Compiler,
     lint_store: Lrc<LintStore>,
-    krate: &'tcx Crate<'tcx>,
+    krate: Rc<ast::Crate>,
     dep_graph: DepGraph,
-    resolver_outputs: ResolverOutputs,
+    resolver: Rc<RefCell<BoxedResolver>>,
     outputs: OutputFilenames,
     crate_name: &str,
     queries: &'tcx OnceCell<TcxQueries<'tcx>>,
     global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>,
     arena: &'tcx WorkerLocal<Arena<'tcx>>,
+    hir_arena: &'tcx WorkerLocal<rustc_ast_lowering::Arena<'tcx>>,
 ) -> QueryContext<'tcx> {
+    // We're constructing the HIR here; we don't care what we will
+    // read, since we haven't even constructed the *input* to
+    // incr. comp. yet.
+    dep_graph.assert_ignored();
+
     let sess = &compiler.session();
+    let krate = resolver
+        .borrow_mut()
+        .access(|resolver| lower_to_hir(sess, &lint_store, resolver, krate, hir_arena));
+    let resolver_outputs = BoxedResolver::to_resolver_outputs(resolver);
 
     let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
 
@@ -828,10 +819,12 @@ pub fn create_global_ctxt<'tcx>(
         callback(sess, &mut local_providers, &mut extern_providers);
     }
 
-    let queries = queries.get_or_init(|| TcxQueries::new(local_providers, extern_providers));
+    let queries = queries.get_or_init(|| {
+        TcxQueries::new(local_providers, extern_providers, query_result_on_disk_cache)
+    });
 
     let gcx = sess.time("setup_global_ctxt", || {
-        global_ctxt.get_or_init(|| {
+        global_ctxt.get_or_init(move || {
             TyCtxt::create_global_ctxt(
                 sess,
                 lint_store,
@@ -839,7 +832,7 @@ pub fn create_global_ctxt<'tcx>(
                 resolver_outputs,
                 krate,
                 dep_graph,
-                query_result_on_disk_cache,
+                queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
                 queries.as_dyn(),
                 &crate_name,
                 outputs,
@@ -869,11 +862,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
                     tcx.ensure().proc_macro_decls_static(())
                 });
 
-                let cstore = tcx
-                    .cstore_as_any()
-                    .downcast_ref::<CStore>()
-                    .expect("`tcx.cstore` is not a `CStore`");
-                cstore.report_unused_deps(tcx);
+                CStore::from_tcx(tcx).report_unused_deps(tcx);
             },
             {
                 par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
@@ -883,6 +872,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 2320f0b47d27df0bb04b9a8c530ebc0d6bbfc72f..8a0964e6b9f92ba7f84259455f6cbe58c666e1a2 100644 (file)
@@ -3,17 +3,15 @@ use crate::passes::{self, BoxedResolver, QueryContext};
 
 use rustc_ast as ast;
 use rustc_codegen_ssa::traits::CodegenBackend;
-use rustc_data_structures::steal::Steal;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
 use rustc_errors::ErrorReported;
 use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_hir::Crate;
 use rustc_incremental::DepGraphFuture;
 use rustc_lint::LintStore;
 use rustc_middle::arena::Arena;
 use rustc_middle::dep_graph::DepGraph;
-use rustc_middle::ty::{GlobalCtxt, ResolverOutputs, TyCtxt};
+use rustc_middle::ty::{GlobalCtxt, TyCtxt};
 use rustc_query_impl::Queries as TcxQueries;
 use rustc_serialize::json;
 use rustc_session::config::{self, OutputFilenames, OutputType};
@@ -81,9 +79,8 @@ pub struct Queries<'tcx> {
     parse: Query<ast::Crate>,
     crate_name: Query<String>,
     register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
-    expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>,
+    expansion: Query<(Rc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>,
     dep_graph: Query<DepGraph>,
-    lower_to_hir: Query<(&'tcx Crate<'tcx>, Steal<ResolverOutputs>)>,
     prepare_outputs: Query<OutputFilenames>,
     global_ctxt: Query<QueryContext<'tcx>>,
     ongoing_codegen: Query<Box<dyn Any>>,
@@ -103,7 +100,6 @@ impl<'tcx> Queries<'tcx> {
             register_plugins: Default::default(),
             expansion: Default::default(),
             dep_graph: Default::default(),
-            lower_to_hir: Default::default(),
             prepare_outputs: Default::default(),
             global_ctxt: Default::default(),
             ongoing_codegen: Default::default(),
@@ -117,13 +113,10 @@ impl<'tcx> Queries<'tcx> {
         &self.compiler.codegen_backend()
     }
 
-    pub fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> {
+    fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> {
         self.dep_graph_future.compute(|| {
-            Ok(self
-                .session()
-                .opts
-                .build_dep_graph()
-                .then(|| rustc_incremental::load_dep_graph(self.session())))
+            let sess = self.session();
+            Ok(sess.opts.build_dep_graph().then(|| rustc_incremental::load_dep_graph(sess)))
         })
     }
 
@@ -174,83 +167,51 @@ impl<'tcx> Queries<'tcx> {
 
     pub fn expansion(
         &self,
-    ) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>> {
+    ) -> Result<&Query<(Rc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>> {
         tracing::trace!("expansion");
         self.expansion.compute(|| {
             let crate_name = self.crate_name()?.peek().clone();
             let (krate, lint_store) = self.register_plugins()?.take();
             let _timer = self.session().timer("configure_and_expand");
-            passes::configure_and_expand(
-                self.session().clone(),
-                lint_store.clone(),
+            let sess = self.session();
+            let mut resolver = passes::create_resolver(
+                sess.clone(),
                 self.codegen_backend().metadata_loader(),
-                krate,
+                &krate,
                 &crate_name,
-            )
-            .map(|(krate, resolver)| {
-                (krate, Steal::new(Rc::new(RefCell::new(resolver))), lint_store)
-            })
+            );
+            let krate = resolver.access(|resolver| {
+                passes::configure_and_expand(&sess, &lint_store, krate, &crate_name, resolver)
+            })?;
+            Ok((Rc::new(krate), Rc::new(RefCell::new(resolver)), lint_store))
         })
     }
 
-    pub fn dep_graph(&self) -> Result<&Query<DepGraph>> {
+    fn dep_graph(&self) -> Result<&Query<DepGraph>> {
         self.dep_graph.compute(|| {
-            Ok(match self.dep_graph_future()?.take() {
-                None => DepGraph::new_disabled(),
-                Some(future) => {
+            let sess = self.session();
+            let future_opt = self.dep_graph_future()?.take();
+            let dep_graph = future_opt
+                .and_then(|future| {
                     let (prev_graph, prev_work_products) =
-                        self.session().time("blocked_on_dep_graph_loading", || {
-                            future
-                                .open()
-                                .unwrap_or_else(|e| rustc_incremental::LoadResult::Error {
-                                    message: format!("could not decode incremental cache: {:?}", e),
-                                })
-                                .open(self.session())
-                        });
-
-                    rustc_incremental::build_dep_graph(
-                        self.session(),
-                        prev_graph,
-                        prev_work_products,
-                    )
-                    .unwrap_or_else(DepGraph::new_disabled)
-                }
-            })
-        })
-    }
+                        sess.time("blocked_on_dep_graph_loading", || future.open().open(sess));
 
-    pub fn lower_to_hir(&'tcx self) -> Result<&Query<(&'tcx Crate<'tcx>, Steal<ResolverOutputs>)>> {
-        self.lower_to_hir.compute(|| {
-            let expansion_result = self.expansion()?;
-            let peeked = expansion_result.peek();
-            let krate = &peeked.0;
-            let resolver = peeked.1.steal();
-            let lint_store = &peeked.2;
-            let hir = resolver.borrow_mut().access(|resolver| {
-                Ok(passes::lower_to_hir(
-                    self.session(),
-                    lint_store,
-                    resolver,
-                    &*self.dep_graph()?.peek(),
-                    &krate,
-                    &self.hir_arena,
-                ))
-            })?;
-            let hir = self.hir_arena.alloc(hir);
-            Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver))))
+                    rustc_incremental::build_dep_graph(sess, prev_graph, prev_work_products)
+                })
+                .unwrap_or_else(DepGraph::new_disabled);
+            Ok(dep_graph)
         })
     }
 
     pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
         self.prepare_outputs.compute(|| {
-            let expansion_result = self.expansion()?;
-            let (krate, boxed_resolver, _) = &*expansion_result.peek();
+            let (krate, boxed_resolver, _) = &*self.expansion()?.peek();
             let crate_name = self.crate_name()?.peek();
             passes::prepare_outputs(
                 self.session(),
                 self.compiler,
-                &krate,
-                &boxed_resolver,
+                krate,
+                &*boxed_resolver,
                 &crate_name,
             )
         })
@@ -260,22 +221,20 @@ impl<'tcx> Queries<'tcx> {
         self.global_ctxt.compute(|| {
             let crate_name = self.crate_name()?.peek().clone();
             let outputs = self.prepare_outputs()?.peek().clone();
-            let lint_store = self.expansion()?.peek().2.clone();
-            let hir = self.lower_to_hir()?.peek();
             let dep_graph = self.dep_graph()?.peek().clone();
-            let (ref krate, ref resolver_outputs) = &*hir;
-            let _timer = self.session().timer("create_global_ctxt");
+            let (krate, resolver, lint_store) = self.expansion()?.take();
             Ok(passes::create_global_ctxt(
                 self.compiler,
                 lint_store,
                 krate,
                 dep_graph,
-                resolver_outputs.steal(),
+                resolver,
                 outputs,
                 &crate_name,
                 &self.queries,
                 &self.gcx,
                 &self.arena,
+                &self.hir_arena,
             ))
         })
     }
index 5d8a6084f2e0b486809c8705314e423618cbeab3..b1e4e3ba395217fefa8917c70aaa31836f42b998 100644 (file)
@@ -96,10 +96,18 @@ fn assert_different_hash(x: &Options, y: &Options) {
     assert_same_clone(y);
 }
 
+fn assert_non_crate_hash_different(x: &Options, y: &Options) {
+    assert_eq!(x.dep_tracking_hash(true), y.dep_tracking_hash(true));
+    assert_ne!(x.dep_tracking_hash(false), y.dep_tracking_hash(false));
+    // Check clone
+    assert_same_clone(x);
+    assert_same_clone(y);
+}
+
 // 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));
@@ -110,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));
@@ -122,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());
@@ -152,9 +160,9 @@ fn test_output_types_tracking_hash_different_paths() {
     v2.output_types = OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("/some/thing")))]);
     v3.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
 
-    assert_different_hash(&v1, &v2);
-    assert_different_hash(&v1, &v3);
-    assert_different_hash(&v2, &v3);
+    assert_non_crate_hash_different(&v1, &v2);
+    assert_non_crate_hash_different(&v1, &v3);
+    assert_non_crate_hash_different(&v2, &v3);
 }
 
 #[test]
@@ -228,9 +236,9 @@ fn test_lints_tracking_hash_different_values() {
         (String::from("d"), Level::Deny),
     ];
 
-    assert_different_hash(&v1, &v2);
-    assert_different_hash(&v1, &v3);
-    assert_different_hash(&v2, &v3);
+    assert_non_crate_hash_different(&v1, &v2);
+    assert_non_crate_hash_different(&v1, &v3);
+    assert_non_crate_hash_different(&v2, &v3);
 }
 
 #[test]
@@ -253,7 +261,21 @@ fn test_lints_tracking_hash_different_construction_order() {
     ];
 
     // The hash should be order-dependent
-    assert_different_hash(&v1, &v2);
+    assert_non_crate_hash_different(&v1, &v2);
+}
+
+#[test]
+fn test_lint_cap_hash_different() {
+    let mut v1 = Options::default();
+    let mut v2 = Options::default();
+    let v3 = Options::default();
+
+    v1.lint_cap = Some(Level::Forbid);
+    v2.lint_cap = Some(Level::Allow);
+
+    assert_non_crate_hash_different(&v1, &v2);
+    assert_non_crate_hash_different(&v1, &v3);
+    assert_non_crate_hash_different(&v2, &v3);
 }
 
 #[test]
@@ -625,6 +647,7 @@ fn test_debugging_options_tracking_hash() {
     untracked!(dump_mir_graphviz, true);
     untracked!(emit_future_incompat_report, true);
     untracked!(emit_stack_sizes, true);
+    untracked!(future_incompat_test, true);
     untracked!(hir_stats, true);
     untracked!(identify_regions, true);
     untracked!(incremental_ignore_spans, true);
@@ -646,6 +669,7 @@ fn test_debugging_options_tracking_hash() {
     untracked!(perf_stats, true);
     // `pre_link_arg` is omitted because it just forwards to `pre_link_args`.
     untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]);
+    untracked!(profile_closures, true);
     untracked!(print_link_args, true);
     untracked!(print_llvm_passes, true);
     untracked!(print_mono_items, Some(String::from("abc")));
@@ -707,15 +731,14 @@ fn test_debugging_options_tracking_hash() {
     tracked!(instrument_coverage, Some(InstrumentCoverage::All));
     tracked!(instrument_mcount, true);
     tracked!(link_only, true);
+    tracked!(llvm_plugins, vec![String::from("plugin_name")]);
     tracked!(merge_functions, Some(MergeFunctions::Disabled));
     tracked!(mir_emit_retag, true);
     tracked!(mir_opt_level, Some(4));
     tracked!(mutable_noalias, Some(true));
     tracked!(new_llvm_pass_manager, Some(true));
-    tracked!(no_codegen, true);
     tracked!(no_generate_arange_section, true);
     tracked!(no_link, true);
-    tracked!(no_profiler_runtime, true);
     tracked!(osx_rpath_install_name, true);
     tracked!(panic_abort_tests, true);
     tracked!(plt, Some(true));
@@ -724,6 +747,7 @@ fn test_debugging_options_tracking_hash() {
     tracked!(print_fuel, Some("abc".to_string()));
     tracked!(profile, true);
     tracked!(profile_emit, Some(PathBuf::from("abc")));
+    tracked!(profiler_runtime, None);
     tracked!(relax_elf_relocations, Some(true));
     tracked!(relro_level, Some(RelroLevel::Full));
     tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc")));
@@ -747,6 +771,16 @@ fn test_debugging_options_tracking_hash() {
     tracked!(use_ctors_section, Some(true));
     tracked!(verify_llvm_ir, true);
     tracked!(wasi_exec_model, Some(WasiExecModel::Reactor));
+
+    macro_rules! tracked_no_crate_hash {
+        ($name: ident, $non_default_value: expr) => {
+            opts = reference.clone();
+            assert_ne!(opts.debugging_opts.$name, $non_default_value);
+            opts.debugging_opts.$name = $non_default_value;
+            assert_non_crate_hash_different(&reference, &opts);
+        };
+    }
+    tracked_no_crate_hash!(no_codegen, true);
 }
 
 #[test]
index 6485fbebd665fd028ccc35274b6fd65ef89d9648..8b41a0ff1769377376762984d9a9b15e5e9fc430 100644 (file)
@@ -2,23 +2,22 @@ use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *};
 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;
 #[cfg(parallel_compiler)]
 use rustc_middle::ty::tls;
+#[cfg(parallel_compiler)]
+use rustc_query_impl::QueryCtxt;
 use rustc_resolve::{self, Resolver};
 use rustc_session as session;
 use rustc_session::config::{self, CrateType};
 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 +152,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 +173,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| QueryCtxt::from_tcx(tcx).deadlock(&registry))
+            })
         });
     });
 }
@@ -206,13 +206,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 +487,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 b9781581ff75d2507b46bbd88c0a92bd4499f202..4cb2a6ca50f8dc1c71991c9a528802cf08940248 100644 (file)
@@ -66,6 +66,13 @@ pub enum TokenKind {
     Ident,
     /// "r#ident"
     RawIdent,
+    /// An unknown prefix like `foo#`, `foo'`, `foo"`. Note that only the
+    /// prefix (`foo`) is included in the token, not the separator (which is
+    /// lexed as its own distinct token). In Rust 2021 and later, reserved
+    /// prefixes are reported as errors; in earlier editions, they result in a
+    /// (allowed by default) lint, and are treated as regular identifier
+    /// tokens.
+    UnknownPrefix,
     /// "12_u8", "1.0e-40", "b"123"". See `LiteralKind` for more details.
     Literal { kind: LiteralKind, suffix_start: usize },
     /// "'a"
@@ -323,7 +330,7 @@ impl Cursor<'_> {
                     let kind = RawStr { n_hashes, err };
                     Literal { kind, suffix_start }
                 }
-                _ => self.ident(),
+                _ => self.ident_or_unknown_prefix(),
             },
 
             // Byte literal, byte string literal, raw byte string literal or identifier.
@@ -358,12 +365,12 @@ impl Cursor<'_> {
                     let kind = RawByteStr { n_hashes, err };
                     Literal { kind, suffix_start }
                 }
-                _ => self.ident(),
+                _ => self.ident_or_unknown_prefix(),
             },
 
             // Identifier (this should be checked after other variant that can
             // start as identifier).
-            c if is_id_start(c) => self.ident(),
+            c if is_id_start(c) => self.ident_or_unknown_prefix(),
 
             // Numeric literal.
             c @ '0'..='9' => {
@@ -487,11 +494,16 @@ impl Cursor<'_> {
         RawIdent
     }
 
-    fn ident(&mut self) -> TokenKind {
+    fn ident_or_unknown_prefix(&mut self) -> TokenKind {
         debug_assert!(is_id_start(self.prev()));
         // Start is already eaten, eat the rest of identifier.
         self.eat_while(is_id_continue);
-        Ident
+        // Known prefixes must have been handled earlier. So if
+        // we see a prefix here, it is definitely a unknown prefix.
+        match self.first() {
+            '#' | '"' | '\'' => UnknownPrefix,
+            _ => Ident,
+        }
     }
 
     fn number(&mut self, first_digit: char) -> LiteralKind {
index 0b5bd39f7f984c25e37dc5bc20c0667d9ab0cae1..77741c7240b0d100ae1749094dbdd9e780a67f90 100644 (file)
@@ -3,8 +3,10 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_middle::ty;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment};
-use rustc_session::lint::FutureBreakage;
+use rustc_session::lint::FutureIncompatibilityReason;
+use rustc_span::edition::Edition;
 use rustc_span::symbol::sym;
+use rustc_span::Span;
 
 declare_lint! {
     /// The `array_into_iter` lint detects calling `into_iter` on arrays.
@@ -20,37 +22,44 @@ declare_lint! {
     ///
     /// ### Explanation
     ///
-    /// In the future, it is planned to add an `IntoIter` implementation for
-    /// arrays such that it will iterate over *values* of the array instead of
-    /// references. Due to how method resolution works, this will change
-    /// existing code that uses `into_iter` on arrays. The solution to avoid
-    /// this warning is to use `iter()` instead of `into_iter()`.
-    ///
-    /// This is a [future-incompatible] lint to transition this to a hard error
-    /// in the future. See [issue #66145] for more details and a more thorough
-    /// description of the lint.
-    ///
-    /// [issue #66145]: https://github.com/rust-lang/rust/issues/66145
-    /// [future-incompatible]: ../index.md#future-incompatible-lints
+    /// Since Rust 1.53, arrays implement `IntoIterator`. However, to avoid
+    /// breakage, `array.into_iter()` in Rust 2015 and 2018 code will still
+    /// behave as `(&array).into_iter()`, returning an iterator over
+    /// references, just like in Rust 1.52 and earlier.
+    /// This only applies to the method call syntax `array.into_iter()`, not to
+    /// any other syntax such as `for _ in array` or `IntoIterator::into_iter(array)`.
     pub ARRAY_INTO_ITER,
     Warn,
-    "detects calling `into_iter` on arrays",
+    "detects calling `into_iter` on arrays in Rust 2015 and 2018",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #66145 <https://github.com/rust-lang/rust/issues/66145>",
-        edition: None,
-        future_breakage: Some(FutureBreakage {
-            date: None
-        })
+        reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2021),
     };
 }
 
-declare_lint_pass!(
-    /// Checks for instances of calling `into_iter` on arrays.
-    ArrayIntoIter => [ARRAY_INTO_ITER]
-);
+#[derive(Copy, Clone, Default)]
+pub struct ArrayIntoIter {
+    for_expr_span: Span,
+}
+
+impl_lint_pass!(ArrayIntoIter => [ARRAY_INTO_ITER]);
 
 impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
+        // Save the span of expressions in `for _ in expr` syntax,
+        // so we can give a better suggestion for those later.
+        if let hir::ExprKind::Match(arg, [_], hir::MatchSource::ForLoopDesugar) = &expr.kind {
+            if let hir::ExprKind::Call(path, [arg]) = &arg.kind {
+                if let hir::ExprKind::Path(hir::QPath::LangItem(
+                    hir::LangItem::IntoIterIntoIter,
+                    _,
+                )) = &path.kind
+                {
+                    self.for_expr_span = arg.span;
+                }
+            }
+        }
+
         // We only care about method call expressions.
         if let hir::ExprKind::MethodCall(call, span, args, _) = &expr.kind {
             if call.ident.name != sym::into_iter {
@@ -106,19 +115,37 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
                 _ => bug!("array type coerced to something other than array or slice"),
             };
             cx.struct_span_lint(ARRAY_INTO_ITER, *span, |lint| {
-                lint.build(&format!(
-                "this method call currently resolves to `<&{} as IntoIterator>::into_iter` (due \
-                    to autoref coercions), but that might change in the future when \
-                    `IntoIterator` impls for arrays are added.",
-                target,
-                ))
-                .span_suggestion(
+                let mut diag = lint.build(&format!(
+                    "this method call resolves to `<&{} as IntoIterator>::into_iter` \
+                    (due to backwards compatibility), \
+                    but will resolve to <{} as IntoIterator>::into_iter in Rust 2021.",
+                    target, target,
+                ));
+                diag.span_suggestion(
                     call.ident.span,
                     "use `.iter()` instead of `.into_iter()` to avoid ambiguity",
                     "iter".into(),
                     Applicability::MachineApplicable,
-                )
-                .emit();
+                );
+                if self.for_expr_span == expr.span {
+                    let expr_span = expr.span.ctxt().outer_expn_data().call_site;
+                    diag.span_suggestion(
+                        receiver_arg.span.shrink_to_hi().to(expr_span.shrink_to_hi()),
+                        "or remove `.into_iter()` to iterate by value",
+                        String::new(),
+                        Applicability::MaybeIncorrect,
+                    );
+                } else {
+                    diag.multipart_suggestion(
+                        "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value",
+                        vec![
+                            (expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()),
+                            (receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), ")".into()),
+                        ],
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                diag.emit();
             })
         }
     }
index f6a84966f7a91b9a4b5ab92d2cbf026e16101467..ccdbccae156c34cb2d2f5e6e066c8ee57dc652f4 100644 (file)
@@ -47,6 +47,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::subst::{GenericArgKind, Subst};
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt};
+use rustc_session::lint::FutureIncompatibilityReason;
 use rustc_session::Session;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
@@ -570,6 +571,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
         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 {
@@ -874,7 +881,7 @@ declare_lint! {
     "detects anonymous parameters",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #41686 <https://github.com/rust-lang/rust/issues/41686>",
-        edition: Some(Edition::Edition2018),
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018),
     };
 }
 
@@ -983,13 +990,16 @@ impl EarlyLintPass for DeprecatedAttr {
 }
 
 fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &[ast::Attribute]) {
+    use rustc_ast::token::CommentKind;
+
     let mut attrs = attrs.iter().peekable();
 
     // Accumulate a single span for sugared doc comments.
     let mut sugared_span: Option<Span> = None;
 
     while let Some(attr) = attrs.next() {
-        if attr.is_doc_comment() {
+        let is_doc_comment = attr.is_doc_comment();
+        if is_doc_comment {
             sugared_span =
                 Some(sugared_span.map_or(attr.span, |span| span.with_hi(attr.span.hi())));
         }
@@ -1000,13 +1010,21 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &
 
         let span = sugared_span.take().unwrap_or(attr.span);
 
-        if attr.is_doc_comment() || cx.sess().check_name(attr, sym::doc) {
+        if is_doc_comment || cx.sess().check_name(attr, sym::doc) {
             cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| {
                 let mut err = lint.build("unused doc comment");
                 err.span_label(
                     node_span,
                     format!("rustdoc does not generate documentation for {}", node_kind),
                 );
+                match attr.kind {
+                    AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => {
+                        err.help("use `//` for a plain comment");
+                    }
+                    AttrKind::DocComment(CommentKind::Block, _) => {
+                        err.help("use `/* */` for a plain comment");
+                    }
+                }
                 err.emit();
             });
         }
@@ -1083,7 +1101,7 @@ declare_lint! {
     ///
     /// ### Explanation
     ///
-    /// An function with generics must have its symbol mangled to accommodate
+    /// A function with generics must have its symbol mangled to accommodate
     /// the generic parameter. The [`no_mangle` attribute] has no effect in
     /// this situation, and should be removed.
     ///
@@ -1663,7 +1681,7 @@ declare_lint! {
     "`...` range patterns are deprecated",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #80165 <https://github.com/rust-lang/rust/issues/80165>",
-        edition: Some(Edition::Edition2021),
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
     };
 }
 
@@ -1891,7 +1909,7 @@ declare_lint! {
     "detects edition keywords being used as an identifier",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>",
-        edition: Some(Edition::Edition2018),
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018),
     };
 }
 
@@ -2297,7 +2315,7 @@ declare_lint! {
     /// ### Example
     ///
     /// ```rust
-    /// #![feature(generic_associated_types)]
+    /// #![feature(const_generics)]
     /// ```
     ///
     /// {{produces}}
@@ -2326,7 +2344,7 @@ impl EarlyLintPass for IncompleteFeatures {
             .iter()
             .map(|(name, span, _)| (name, span))
             .chain(features.declared_lib_features.iter().map(|(name, span)| (name, span)))
-            .filter(|(name, _)| rustc_feature::INCOMPLETE_FEATURES.iter().any(|f| name == &f))
+            .filter(|(&name, _)| features.incomplete(name))
             .for_each(|(&name, &span)| {
                 cx.struct_span_lint(INCOMPLETE_FEATURES, span, |lint| {
                     let mut builder = lint.build(&format!(
index a8df1b0952c18297e38febb48793c5ab995947ee..f448acd24fc551a3e64c0a7fd16f8902ad272f62 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>),
@@ -209,8 +211,8 @@ impl LintStore {
                 bug!("duplicate specification of lint {}", lint.name_lower())
             }
 
-            if let Some(FutureIncompatibleInfo { edition, .. }) = lint.future_incompatible {
-                if let Some(edition) = edition {
+            if let Some(FutureIncompatibleInfo { reason, .. }) = lint.future_incompatible {
+                if let Some(edition) = reason.edition() {
                     self.lint_groups
                         .entry(edition.lint_name())
                         .or_insert(LintGroup {
@@ -220,17 +222,20 @@ impl LintStore {
                         })
                         .lint_ids
                         .push(id);
+                } else {
+                    // Lints belonging to the `future_incompatible` lint group are lints where a
+                    // future version of rustc will cause existing code to stop compiling.
+                    // Lints tied to an edition don't count because they are opt-in.
+                    self.lint_groups
+                        .entry("future_incompatible")
+                        .or_insert(LintGroup {
+                            lint_ids: vec![],
+                            from_plugin: lint.is_plugin,
+                            depr: None,
+                        })
+                        .lint_ids
+                        .push(id);
                 }
-
-                self.lint_groups
-                    .entry("future_incompatible")
-                    .or_insert(LintGroup {
-                        lint_ids: vec![],
-                        from_plugin: lint.is_plugin,
-                        depr: None,
-                    })
-                    .lint_ids
-                    .push(id);
             }
         }
     }
@@ -273,22 +278,6 @@ impl LintStore {
         }
     }
 
-    /// This lint should be available with either the old or the new name.
-    ///
-    /// Using the old name will not give a warning.
-    /// You must register a lint with the new name before calling this function.
-    #[track_caller]
-    pub fn register_alias(&mut self, old_name: &str, new_name: &str) {
-        let target = match self.by_name.get(new_name) {
-            Some(&Id(lint_id)) => lint_id,
-            _ => bug!("cannot add alias {} for lint {} that does not exist", old_name, new_name),
-        };
-        match self.by_name.insert(old_name.to_string(), Id(target)) {
-            None | Some(Ignored) => {}
-            Some(x) => bug!("duplicate specification of lint {} (was {:?})", old_name, x),
-        }
-    }
-
     /// This lint should give no warning and have no effect.
     ///
     /// This is used by rustc to avoid warning about old rustdoc lints before rustdoc registers them as tool lints.
@@ -334,15 +323,17 @@ impl LintStore {
         }
     }
 
-    /// Checks the validity of lint names derived from the command line. Returns
-    /// true if the lint is valid, false otherwise.
+    /// Checks the validity of lint names derived from the command line.
     pub fn check_lint_name_cmdline(
         &self,
         sess: &Session,
         lint_name: &str,
-        level: Option<Level>,
-    ) -> bool {
-        let db = match self.check_lint_name(lint_name, None) {
+        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) => {
@@ -364,26 +355,29 @@ impl LintStore {
                 ))),
                 _ => None,
             },
+            CheckLintNameResult::NoTool => Some(struct_span_err!(
+                sess,
+                DUMMY_SP,
+                E0602,
+                "unknown lint tool: `{}`",
+                tool_name.unwrap()
+            )),
         };
 
         if let Some(mut db) = db {
-            if let Some(level) = level {
-                let msg = format!(
-                    "requested on the command line with `{} {}`",
-                    match level {
-                        Level::Allow => "-A",
-                        Level::Warn => "-W",
-                        Level::Deny => "-D",
-                        Level::Forbid => "-F",
-                    },
-                    lint_name
-                );
-                db.note(&msg);
-            }
+            let msg = format!(
+                "requested on the command line with `{} {}`",
+                match level {
+                    Level::Allow => "-A",
+                    Level::Warn => "-W",
+                    Level::ForceWarn => "--force-warn",
+                    Level::Deny => "-D",
+                    Level::Forbid => "-F",
+                },
+                lint_name
+            );
+            db.note(&msg);
             db.emit();
-            false
-        } else {
-            true
         }
     }
 
@@ -410,9 +404,17 @@ impl LintStore {
     /// 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 {
@@ -479,17 +481,17 @@ impl LintStore {
 
     fn no_lint_suggestion(&self, lint_name: &str) -> CheckLintNameResult<'_> {
         let name_lower = lint_name.to_lowercase();
-        let symbols =
-            self.get_lints().iter().map(|l| Symbol::intern(&l.name_lower())).collect::<Vec<_>>();
 
         if lint_name.chars().any(char::is_uppercase) && self.find_lints(&name_lower).is_ok() {
             // First check if the lint name is (partly) in upper case instead of lower case...
-            CheckLintNameResult::NoLint(Some(Symbol::intern(&name_lower)))
-        } else {
-            // ...if not, search for lints with a similar name
-            let suggestion = find_best_match_for_name(&symbols, Symbol::intern(&name_lower), None);
-            CheckLintNameResult::NoLint(suggestion)
+            return CheckLintNameResult::NoLint(Some(Symbol::intern(&name_lower)));
         }
+        // ...if not, search for lints with a similar name
+        let groups = self.lint_groups.keys().copied().map(Symbol::intern);
+        let lints = self.lints.iter().map(|l| Symbol::intern(&l.name_lower()));
+        let names: Vec<Symbol> = groups.chain(lints).collect();
+        let suggestion = find_best_match_for_name(&names, Symbol::intern(&name_lower), None);
+        CheckLintNameResult::NoLint(suggestion)
     }
 
     fn check_tool_name_for_backwards_compat(
@@ -723,6 +725,15 @@ pub trait LintContext: Sized {
                 BuiltinLintDiagnostics::OrPatternsBackCompat(span,suggestion) => {
                     db.span_suggestion(span, "use pat_param to preserve semantics", suggestion, Applicability::MachineApplicable);
                 }
+                BuiltinLintDiagnostics::ReservedPrefix(span) => {
+                    db.span_label(span, "unknown prefix");
+                    db.span_suggestion_verbose(
+                        span.shrink_to_hi(),
+                        "insert whitespace here to avoid this being parsed as a prefix in Rust 2021",
+                        " ".into(),
+                        Applicability::MachineApplicable,
+                    );
+                }
             }
             // Rewrap `db`, and pass control to the user.
             decorate(LintDiagnosticBuilder::new(db));
@@ -1019,3 +1030,14 @@ impl<'tcx> LayoutOf for LateContext<'tcx> {
         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 eb2e495f73d3c31a5392afe7ed590b802129c0fc..7a8b731da5c2ee5d327dd0a882371a9e2149ea93 100644 (file)
@@ -120,6 +120,12 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
         })
     }
 
+    fn visit_expr_field(&mut self, f: &'a ast::ExprField) {
+        self.with_lint_attrs(f.id, &f.attrs, |cx| {
+            ast_visit::walk_expr_field(cx, f);
+        })
+    }
+
     fn visit_stmt(&mut self, s: &'a ast::Stmt) {
         // Add the statement's lint attributes to our
         // current state when checking the statement itself.
@@ -204,8 +210,10 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
     }
 
     fn visit_arm(&mut self, a: &'a ast::Arm) {
-        run_early_pass!(self, check_arm, a);
-        ast_visit::walk_arm(self, a);
+        self.with_lint_attrs(a.id, &a.attrs, |cx| {
+            run_early_pass!(cx, check_arm, a);
+            ast_visit::walk_arm(cx, a);
+        })
     }
 
     fn visit_expr_post(&mut self, e: &'a ast::Expr) {
@@ -389,9 +397,15 @@ pub fn check_ast_crate<T: EarlyLintPass>(
     // All of the buffered lints should have been emitted at this point.
     // If not, that means that we somehow buffered a lint for a node id
     // that was not lint-checked (perhaps it doesn't exist?). This is a bug.
-    for (_id, lints) in buffered.map {
+    for (id, lints) in buffered.map {
         for early_lint in lints {
-            sess.delay_span_bug(early_lint.span, "failed to process buffered lint here");
+            sess.delay_span_bug(
+                early_lint.span,
+                &format!(
+                    "failed to process buffered lint here (dummy = {})",
+                    id == ast::DUMMY_NODE_ID
+                ),
+            );
         }
     }
 }
index 0398d4a99618a9fe1498bea256be428c69956945..8a4a70894375d2f55b0661cecf58587543957d4a 100644 (file)
@@ -2,15 +2,17 @@
 //! Clippy.
 
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
-use rustc_ast::{ImplKind, Item, ItemKind};
-use rustc_data_structures::fx::FxHashMap;
+use rustc_ast as ast;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
-use rustc_hir::{GenericArg, HirId, MutTy, Mutability, Path, PathSegment, QPath, Ty, TyKind};
+use rustc_hir::{
+    GenericArg, HirId, Item, ItemKind, MutTy, Mutability, Node, Path, PathSegment, QPath, Ty,
+    TyKind,
+};
 use rustc_middle::ty;
-use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
-use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::symbol::{kw, sym, Symbol};
 
 declare_tool_lint! {
     pub rustc::DEFAULT_HASH_TYPES,
@@ -19,43 +21,35 @@ declare_tool_lint! {
     report_in_external_macro: true
 }
 
-pub struct DefaultHashTypes {
-    map: FxHashMap<Symbol, Symbol>,
-}
-
-impl DefaultHashTypes {
-    // we are allowed to use `HashMap` and `HashSet` as identifiers for implementing the lint itself
-    #[allow(rustc::default_hash_types)]
-    pub fn new() -> Self {
-        let mut map = FxHashMap::default();
-        map.insert(sym::HashMap, sym::FxHashMap);
-        map.insert(sym::HashSet, sym::FxHashSet);
-        Self { map }
-    }
-}
+declare_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]);
 
-impl_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]);
-
-impl EarlyLintPass for DefaultHashTypes {
-    fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
-        if let Some(replace) = self.map.get(&ident.name) {
-            cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, |lint| {
-                // FIXME: We can avoid a copy here. Would require us to take String instead of &str.
-                let msg = format!("Prefer {} over {}, it has better performance", replace, ident);
-                lint.build(&msg)
-                    .span_suggestion(
-                        ident.span,
-                        "use",
-                        replace.to_string(),
-                        Applicability::MaybeIncorrect, // FxHashMap, ... needs another import
-                    )
-                    .note(&format!(
-                        "a `use rustc_data_structures::fx::{}` may be necessary",
-                        replace
-                    ))
-                    .emit();
-            });
+impl LateLintPass<'_> for DefaultHashTypes {
+    fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) {
+        let def_id = match path.res {
+            Res::Def(rustc_hir::def::DefKind::Struct, id) => id,
+            _ => return,
+        };
+        if matches!(cx.tcx.hir().get(hir_id), Node::Item(Item { kind: ItemKind::Use(..), .. })) {
+            // don't lint imports, only actual usages
+            return;
         }
+        let replace = if cx.tcx.is_diagnostic_item(sym::hashmap_type, def_id) {
+            "FxHashMap"
+        } else if cx.tcx.is_diagnostic_item(sym::hashset_type, def_id) {
+            "FxHashSet"
+        } else {
+            return;
+        };
+        cx.struct_span_lint(DEFAULT_HASH_TYPES, path.span, |lint| {
+            let msg = format!(
+                "prefer `{}` over `{}`, it has better performance",
+                replace,
+                cx.tcx.item_name(def_id)
+            );
+            lint.build(&msg)
+                .note(&format!("a `use rustc_data_structures::fx::{}` may be necessary", replace))
+                .emit();
+        });
     }
 }
 
@@ -242,27 +236,17 @@ declare_tool_lint! {
 declare_lint_pass!(LintPassImpl => [LINT_PASS_IMPL_WITHOUT_MACRO]);
 
 impl EarlyLintPass for LintPassImpl {
-    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if let ItemKind::Impl(box ImplKind { of_trait: Some(lint_pass), .. }) = &item.kind {
+    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
+        if let ast::ItemKind::Impl(box ast::ImplKind { of_trait: Some(lint_pass), .. }) = &item.kind
+        {
             if let Some(last) = lint_pass.path.segments.last() {
                 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 0ee434f5fb50bae3e359d986b90936c9027c1470..069fa41fa886ab175b09186fbbabe2a70e3e401d 100644 (file)
@@ -11,7 +11,8 @@ use rustc_middle::hir::map::Map;
 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;
@@ -25,8 +26,6 @@ use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{source_map::MultiSpan, Span, DUMMY_SP};
 use tracing::debug;
 
-use std::cmp;
-
 fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap {
     let store = unerased_lint_store(tcx);
     let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
@@ -50,15 +49,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 +71,7 @@ impl<'s> LintLevelsBuilder<'s> {
         let mut builder = LintLevelsBuilder {
             sess,
             sets: LintLevelSets::new(),
-            cur: 0,
+            cur: COMMAND_LINE,
             id_to_set: Default::default(),
             warn_about_weird_lints,
             store,
@@ -88,14 +87,8 @@ impl<'s> LintLevelsBuilder<'s> {
         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, Some(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
-            // `--cap-lints allow` but we've also got `-D foo` then we ignore
-            // this specification as the lint cap will set it to allow anyway.
-            let level = cmp::min(level, self.sets.lint_cap);
-
             let lint_flag_val = Symbol::intern(lint_name);
 
             let ids = match store.find_lints(&lint_name) {
@@ -103,23 +96,18 @@ impl<'s> LintLevelsBuilder<'s> {
                 Err(_) => continue, // errors handled in check_lint_name_cmdline above
             };
             for id in ids {
+                // ForceWarn and Forbid cannot be overriden
+                if let Some((Level::ForceWarn | Level::Forbid, _)) = specs.get(&id) {
+                    continue;
+                }
+
                 self.check_gated_lint(id, DUMMY_SP);
                 let src = LintLevelSource::CommandLine(lint_flag_val, orig_level);
                 specs.insert(id, (level, src));
             }
         }
 
-        for lint_name in &sess.opts.force_warns {
-            let valid = store.check_lint_name_cmdline(sess, lint_name, None);
-            if valid {
-                let lints = store
-                    .find_lints(lint_name)
-                    .unwrap_or_else(|_| bug!("A valid lint failed to produce a lint ids"));
-                self.sets.force_warns.extend(&lints);
-            }
-        }
-
-        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
@@ -131,6 +119,8 @@ impl<'s> LintLevelsBuilder<'s> {
         id: LintId,
         (level, src): LevelAndSource,
     ) {
+        let (old_level, old_src) =
+            self.sets.get_lint_level(id.lint, self.cur, Some(&specs), &self.sess);
         // Setting to a non-forbid level is an error if the lint previously had
         // a forbid level. Note that this is not necessarily true even with a
         // `#[forbid(..)]` attribute present, as that is overriden by `--cap-lints`.
@@ -138,9 +128,7 @@ impl<'s> LintLevelsBuilder<'s> {
         // This means that this only errors if we're truly lowering the lint
         // level from forbid.
         if level != Level::Forbid {
-            if let (Level::Forbid, old_src) =
-                self.sets.get_lint_level(id.lint, self.cur, Some(&specs), &self.sess)
-            {
+            if let Level::Forbid = old_level {
                 // Backwards compatibility check:
                 //
                 // We used to not consider `forbid(lint_group)`
@@ -152,9 +140,6 @@ impl<'s> LintLevelsBuilder<'s> {
                     LintLevelSource::Default => false,
                     LintLevelSource::Node(symbol, _, _) => self.store.is_lint_group(symbol),
                     LintLevelSource::CommandLine(symbol, _) => self.store.is_lint_group(symbol),
-                    LintLevelSource::ForceWarn(_symbol) => {
-                        bug!("forced warn lint returned a forbid lint level")
-                    }
                 };
                 debug!(
                     "fcw_warning={:?}, specs.get(&id) = {:?}, old_src={:?}, id_name={:?}",
@@ -179,7 +164,6 @@ impl<'s> LintLevelsBuilder<'s> {
                         LintLevelSource::CommandLine(_, _) => {
                             diag_builder.note("`forbid` lint level was set on command line");
                         }
-                        _ => bug!("forced warn lint returned a forbid lint level"),
                     }
                     diag_builder.emit();
                 };
@@ -216,7 +200,11 @@ impl<'s> LintLevelsBuilder<'s> {
                 }
             }
         }
-        specs.insert(id, (level, src));
+        if let Level::ForceWarn = old_level {
+            specs.insert(id, (old_level, old_src));
+        } else {
+            specs.insert(id, (level, src));
+        }
     }
 
     /// Pushes a list of AST lint attributes onto this context.
@@ -320,33 +308,14 @@ impl<'s> LintLevelsBuilder<'s> {
                         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(
@@ -363,7 +332,8 @@ impl<'s> LintLevelsBuilder<'s> {
                     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,
@@ -418,6 +388,26 @@ impl<'s> LintLevelsBuilder<'s> {
                         }
                     }
 
+                    &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) => {
@@ -449,8 +439,8 @@ impl<'s> LintLevelsBuilder<'s> {
                         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()
                             };
@@ -473,7 +463,9 @@ impl<'s> LintLevelsBuilder<'s> {
                 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);
@@ -522,8 +514,7 @@ impl<'s> LintLevelsBuilder<'s> {
 
         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 }
@@ -577,7 +568,7 @@ impl<'s> LintLevelsBuilder<'s> {
     }
 }
 
-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 4f59460aa82a4e89f0aec06da78738716715c753..c9478016140b7ad3349d2362dbb8399657d7f544 100644 (file)
@@ -163,7 +163,7 @@ macro_rules! late_lint_passes {
                 // FIXME: Turn the computation of types which implement Debug into a query
                 // and change this to a module lint pass
                 MissingDebugImplementations: MissingDebugImplementations::default(),
-                ArrayIntoIter: ArrayIntoIter,
+                ArrayIntoIter: ArrayIntoIter::default(),
                 ClashingExternDeclarations: ClashingExternDeclarations::new(),
                 DropTraitConstraints: DropTraitConstraints,
                 TemporaryCStringAsPtr: TemporaryCStringAsPtr,
@@ -325,6 +325,9 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
     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
@@ -472,10 +475,10 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
 }
 
 fn register_internals(store: &mut LintStore) {
-    store.register_lints(&DefaultHashTypes::get_lints());
-    store.register_early_pass(|| box DefaultHashTypes::new());
     store.register_lints(&LintPassImpl::get_lints());
     store.register_early_pass(|| box LintPassImpl);
+    store.register_lints(&DefaultHashTypes::get_lints());
+    store.register_late_pass(|| box DefaultHashTypes);
     store.register_lints(&ExistingDocKeyword::get_lints());
     store.register_late_pass(|| box ExistingDocKeyword);
     store.register_lints(&TyTyKind::get_lints());
@@ -494,3 +497,6 @@ fn register_internals(store: &mut LintStore) {
         ],
     );
 }
+
+#[cfg(test)]
+mod tests;
index c91dc37b374f861d221f149d5b7badd552333dce..a32caf1bc433df1cbf94ffa4f3d7322f2ff43ed5 100644 (file)
@@ -4,10 +4,12 @@ use rustc_errors::{pluralize, Applicability};
 use rustc_hir as hir;
 use rustc_middle::ty;
 use rustc_parse_format::{ParseMode, Parser, Piece};
+use rustc_session::lint::FutureIncompatibilityReason;
+use rustc_span::edition::Edition;
 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
@@ -27,13 +29,17 @@ declare_lint! {
     /// 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 {
+        reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2021),
+        explain_reason: false,
+    };
     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>) {
@@ -85,9 +91,10 @@ 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 is no longer accepted in Rust 2021");
+        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>");
         if !span.contains(arg_span) {
             // No clue where this argument is coming from.
             l.emit();
@@ -167,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",
@@ -201,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) {
@@ -249,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 e632f29e672c08126edec6d1eb02b4a75d8d15f6..e713ce7c71bec3bf4ff1fdae9a752fbb7084bc5f 100644 (file)
@@ -37,10 +37,47 @@ declare_lint! {
     "bounds of the form `T: Drop` are useless"
 }
 
+declare_lint! {
+    /// The `dyn_drop` lint checks for trait objects with `std::ops::Drop`.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// fn foo(_x: Box<dyn Drop>) {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// A trait object bound of the form `dyn Drop` is most likely misleading
+    /// and not what the programmer intended.
+    ///
+    /// `Drop` bounds do not actually indicate whether a type can be trivially
+    /// dropped or not, because a composite type containing `Drop` types does
+    /// not necessarily implement `Drop` itself. Naïvely, one might be tempted
+    /// to write a deferred drop system, to pull cleaning up memory out of a
+    /// latency-sensitive code path, using `dyn Drop` trait objects. However,
+    /// this breaks down e.g. when `T` is `String`, which does not implement
+    /// `Drop`, but should probably be accepted.
+    ///
+    /// To write a trait object bound that accepts anything, use a placeholder
+    /// trait with a blanket implementation.
+    ///
+    /// ```rust
+    /// trait Placeholder {}
+    /// impl<T> Placeholder for T {}
+    /// fn foo(_x: Box<dyn Placeholder>) {}
+    /// ```
+    pub DYN_DROP,
+    Warn,
+    "trait objects of the form `dyn Drop` are useless"
+}
+
 declare_lint_pass!(
     /// Lint for bounds of the form `T: Drop`, which usually
     /// indicate an attempt to emulate `std::mem::needs_drop`.
-    DropTraitConstraints => [DROP_BOUNDS]
+    DropTraitConstraints => [DROP_BOUNDS, DYN_DROP]
 );
 
 impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
@@ -75,4 +112,28 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
             }
         }
     }
+
+    fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
+        let bounds = match &ty.kind {
+            hir::TyKind::TraitObject(bounds, _lifetime, _syntax) => bounds,
+            _ => return,
+        };
+        for bound in &bounds[..] {
+            let def_id = bound.trait_ref.trait_def_id();
+            if cx.tcx.lang_items().drop_trait() == def_id {
+                cx.struct_span_lint(DYN_DROP, bound.span, |lint| {
+                    let needs_drop = match cx.tcx.get_diagnostic_item(sym::needs_drop) {
+                        Some(needs_drop) => needs_drop,
+                        None => return,
+                    };
+                    let msg = format!(
+                        "types that do not implement `Drop` can still have drop glue, consider \
+                        instead using `{}` to detect whether a type is trivially dropped",
+                        cx.tcx.def_path_str(needs_drop)
+                    );
+                    lint.build(&msg).emit()
+                });
+            }
+        }
+    }
 }
index 44c2a550c30e2d40af462a89bd4afda3f30c49d2..c431c048ca01c1179dbfdf976b4a982a4905de39 100644 (file)
@@ -154,6 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                 | hir::BinOpKind::Shl
                 | hir::BinOpKind::Shr => Some("bitwise operation"),
             },
+            hir::ExprKind::AddrOf(..) => Some("borrow"),
             hir::ExprKind::Unary(..) => Some("unary operation"),
             _ => None,
         };
index f909f159784cbae36ad53f04e30628c08d175559..292833843e7e8872c69fa84e303f14a8ae3aaef6 100644 (file)
@@ -5,7 +5,6 @@ version = "0.0.0"
 edition = "2018"
 
 [dependencies]
-log = { package = "tracing", version = "0.1" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_span = { path = "../rustc_span" }
index 352146d64635ad69f72e56cac4c6ac926174426a..1b416f37bde74269c45540663802fcc381353118 100644 (file)
@@ -6,7 +6,7 @@
 //! compiler code, rather than using their own custom pass. Those
 //! lints are all available in `rustc_lint::builtin`.
 
-use crate::{declare_lint, declare_lint_pass, FutureBreakage};
+use crate::{declare_lint, declare_lint_pass, FutureIncompatibilityReason};
 use rustc_span::edition::Edition;
 
 declare_lint! {
@@ -41,7 +41,6 @@ declare_lint! {
     "applying forbid to lint-groups",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #81670 <https://github.com/rust-lang/rust/issues/81670>",
-        edition: None,
     };
 }
 
@@ -77,7 +76,6 @@ declare_lint! {
     "ill-formed attribute inputs that were previously accepted and used in practice",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
-        edition: None,
     };
     crate_level_only
 }
@@ -114,7 +112,6 @@ declare_lint! {
     "conflicts between `#[repr(..)]` hints that were previously accepted and used in practice",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #68585 <https://github.com/rust-lang/rust/issues/68585>",
-        edition: None,
     };
 }
 
@@ -293,7 +290,6 @@ declare_lint! {
     "constant evaluation encountered erroneous expression",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #71800 <https://github.com/rust-lang/rust/issues/71800>",
-        edition: None,
     };
     report_in_external_macro
 }
@@ -900,7 +896,6 @@ declare_lint! {
     "detect private items in public interfaces not caught by the old implementation",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
-        edition: None,
     };
 }
 
@@ -980,7 +975,6 @@ declare_lint! {
     "detect public re-exports of private extern crates",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
-        edition: None,
     };
 }
 
@@ -1010,7 +1004,6 @@ declare_lint! {
     "type parameter default erroneously allowed in invalid location",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #36887 <https://github.com/rust-lang/rust/issues/36887>",
-        edition: None,
     };
 }
 
@@ -1078,7 +1071,6 @@ declare_lint! {
     "detects unaligned references to fields of packed structs",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #82523 <https://github.com/rust-lang/rust/issues/82523>",
-        edition: None,
     };
     report_in_external_macro
 }
@@ -1200,7 +1192,6 @@ declare_lint! {
     "patterns in functions without body were erroneously allowed",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
-        edition: None,
     };
 }
 
@@ -1244,7 +1235,6 @@ declare_lint! {
     "detects missing fragment specifiers in unused `macro_rules!` patterns",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
-        edition: None,
     };
 }
 
@@ -1286,7 +1276,6 @@ declare_lint! {
     "detects generic lifetime arguments in path segments with late bound lifetime parameters",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
-        edition: None,
     };
 }
 
@@ -1322,7 +1311,6 @@ declare_lint! {
     "trait-object types were treated as different depending on marker-trait order",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #56484 <https://github.com/rust-lang/rust/issues/56484>",
-        edition: None,
     };
 }
 
@@ -1362,7 +1350,6 @@ declare_lint! {
     "distinct impls distinguished only by the leak-check code",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #56105 <https://github.com/rust-lang/rust/issues/56105>",
-        edition: None,
     };
 }
 
@@ -1554,7 +1541,7 @@ declare_lint! {
     "raw pointer to an inference variable",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
-        edition: Some(Edition::Edition2018),
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018),
     };
 }
 
@@ -1621,7 +1608,7 @@ declare_lint! {
     "suggest using `dyn Trait` for trait objects",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #80165 <https://github.com/rust-lang/rust/issues/80165>",
-        edition: Some(Edition::Edition2021),
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
     };
 }
 
@@ -1676,7 +1663,7 @@ declare_lint! {
      instead of `crate`, `self`, or an extern crate name",
      @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #53130 <https://github.com/rust-lang/rust/issues/53130>",
-        edition: Some(Edition::Edition2018),
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018),
      };
 }
 
@@ -1725,7 +1712,6 @@ declare_lint! {
     "floating-point literals cannot be used in patterns",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
-        edition: None,
     };
 }
 
@@ -1769,7 +1755,6 @@ declare_lint! {
     "detects name collision with an existing but unstable method",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #48919 <https://github.com/rust-lang/rust/issues/48919>",
-        edition: None,
         // Note: this item represents future incompatibility of all unstable functions in the
         //       standard library, and thus should never be removed or changed to an error.
     };
@@ -1873,7 +1858,6 @@ declare_lint! {
     "checks the object safety of where clauses",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #51443 <https://github.com/rust-lang/rust/issues/51443>",
-        edition: None,
     };
 }
 
@@ -1940,7 +1924,6 @@ declare_lint! {
     "detects proc macro derives using inaccessible names from parent modules",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #83583 <https://github.com/rust-lang/rust/issues/83583>",
-        edition: None,
     };
 }
 
@@ -2043,7 +2026,6 @@ declare_lint! {
      cannot be referred to by absolute paths",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #52234 <https://github.com/rust-lang/rust/issues/52234>",
-        edition: None,
     };
     crate_level_only
 }
@@ -2134,7 +2116,6 @@ declare_lint! {
     "constant used in pattern contains value of non-structural-match type in a field or a variant",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>",
-        edition: None,
     };
 }
 
@@ -2190,7 +2171,6 @@ declare_lint! {
     "pointers are not structural-match",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #62411 <https://github.com/rust-lang/rust/issues/70861>",
-        edition: None,
     };
 }
 
@@ -2229,7 +2209,6 @@ declare_lint! {
     expression contains values of non-structural-match types",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #73448 <https://github.com/rust-lang/rust/issues/73448>",
-        edition: None,
     };
 }
 
@@ -2287,7 +2266,6 @@ declare_lint! {
     "ambiguous associated items",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #57644 <https://github.com/rust-lang/rust/issues/57644>",
-        edition: None,
     };
 }
 
@@ -2318,7 +2296,6 @@ declare_lint! {
     "reservation of a two-phased borrow conflicts with other shared borrows",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #59159 <https://github.com/rust-lang/rust/issues/59159>",
-        edition: None,
     };
 }
 
@@ -2360,7 +2337,6 @@ declare_lint! {
     "a feature gate that doesn't break dependent crates",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #64266 <https://github.com/rust-lang/rust/issues/64266>",
-        edition: None,
     };
 }
 
@@ -2589,7 +2565,6 @@ declare_lint! {
     "a C-like enum implementing Drop is cast",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #73333 <https://github.com/rust-lang/rust/issues/73333>",
-        edition: None,
     };
 }
 
@@ -2629,7 +2604,6 @@ declare_lint! {
     "detects a generic constant is used in a type without a emitting a warning",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #76200 <https://github.com/rust-lang/rust/issues/76200>",
-        edition: None,
     };
 }
 
@@ -2688,7 +2662,6 @@ declare_lint! {
     "uninhabited static",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #74840 <https://github.com/rust-lang/rust/issues/74840>",
-        edition: None,
     };
 }
 
@@ -2758,7 +2731,6 @@ declare_lint! {
     "unsupported naked function definitions",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #32408 <https://github.com/rust-lang/rust/issues/32408>",
-        edition: None,
     };
 }
 
@@ -2831,7 +2803,6 @@ declare_lint! {
     "trailing semicolon in macro body used as expression",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #79813 <https://github.com/rust-lang/rust/issues/79813>",
-        edition: None,
     };
 }
 
@@ -2996,11 +2967,14 @@ declare_lint_pass! {
         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,
+        RUST_2021_PRELUDE_COLLISIONS,
+        RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
+        UNSUPPORTED_CALLING_CONVENTIONS,
     ]
 }
 
@@ -3028,9 +3002,8 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `disjoint_capture_migration` lint detects variables that aren't completely
-    /// captured when the feature `capture_disjoint_fields` is enabled and it affects the Drop
-    /// order of at least one path starting at this variable.
+    /// 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
     /// the same trait as the root variable.
@@ -3038,7 +3011,7 @@ declare_lint! {
     /// ### Example of drop reorder
     ///
     /// ```rust,compile_fail
-    /// # #![deny(disjoint_capture_migration)]
+    /// # #![deny(rust_2021_incompatible_closure_captures)]
     /// # #![allow(unused)]
     /// struct FancyInteger(i32);
     ///
@@ -3067,16 +3040,16 @@ declare_lint! {
     ///
     /// ### Explanation
     ///
-    /// In the above example `p.y` will be dropped at the end of `f` instead of with `c` if
-    /// the feature `capture_disjoint_fields` is enabled.
+    /// In the above example, `p.y` will be dropped at the end of `f` instead of
+    /// with `c` in Rust 2021.
     ///
     /// ### Example of auto-trait
     ///
     /// ```rust,compile_fail
-    /// #![deny(disjoint_capture_migration)]
+    /// #![deny(rust_2021_incompatible_closure_captures)]
     /// use std::thread;
     ///
-    /// struct Pointer (*mut i32);
+    /// struct Pointer(*mut i32);
     /// unsafe impl Send for Pointer {}
     ///
     /// fn main() {
@@ -3092,12 +3065,16 @@ declare_lint! {
     ///
     /// ### Explanation
     ///
-    /// In the above example `fptr.0` is captured when feature `capture_disjoint_fields` is enabled.
+    /// 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,
-    "Drop reorder and auto traits error because of `capture_disjoint_fields`"
+    "detects closures affected by Rust 2021 changes",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2021),
+        explain_reason: false,
+    };
 }
 
 declare_lint_pass!(UnusedDocComment => [UNUSED_DOC_COMMENTS]);
@@ -3153,7 +3130,6 @@ declare_lint! {
     "detects invalid `#[doc(...)]` attributes",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #82730 <https://github.com/rust-lang/rust/issues/82730>",
-        edition: None,
     };
 }
 
@@ -3200,20 +3176,17 @@ declare_lint! {
     "detects usage of old versions of certain proc-macro crates",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #83125 <https://github.com/rust-lang/rust/issues/83125>",
-        edition: None,
-        future_breakage: Some(FutureBreakage {
-            date: None
-        })
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
     };
 }
 
 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 {
@@ -3236,7 +3209,142 @@ declare_lint! {
     /// ### 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 {
+        reference: "issue #84869 <https://github.com/rust-lang/rust/issues/84869>",
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
+    };
+}
+
+declare_lint! {
+    /// 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(rust_2021_prelude_collisions)]
+    ///
+    /// trait Foo {
+    ///     fn try_into(self) -> Result<String, !>;
+    /// }
+    ///
+    /// impl Foo for &str {
+    ///     fn try_into(self) -> Result<String, !> {
+    ///         Ok(String::from(self))
+    ///     }
+    /// }
+    ///
+    /// fn main() {
+    ///     let x: String = "3".try_into().unwrap();
+    ///     //                  ^^^^^^^^
+    ///     // This call to try_into matches both Foo:try_into and TryInto::try_into as
+    ///     // `TryInto` has been added to the Rust prelude in 2021 edition.
+    ///     println!("{}", x);
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// In Rust 2021, one of the important introductions is the [prelude changes], which add
+    /// `TryFrom`, `TryInto`, and `FromIterator` into the standard library's prelude. Since this
+    /// results in an ambiguity as to which method/function to call when an existing `try_into`
+    ///  method is called via dot-call syntax or a `try_from`/`from_iter` associated function
+    ///  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 RUST_2021_PRELUDE_COLLISIONS,
+    Allow,
+    "detects the usage of trait methods which are ambiguous with traits added to the \
+        prelude in future editions",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #85684 <https://github.com/rust-lang/rust/issues/85684>",
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
+    };
+}
+
+declare_lint! {
+    /// 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(rust_2021_prefixes_incompatible_syntax)]
+    ///
+    /// macro_rules! m {
+    ///     (z $x:expr) => ();
+    /// }
+    ///
+    /// m!(z"hey");
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// In Rust 2015 and 2018, `z"hey"` is two tokens: the identifier `z`
+    /// followed by the string literal `"hey"`. In Rust 2021, the `z` is
+    /// considered a prefix for `"hey"`.
+    ///
+    /// This lint suggests to add whitespace between the `z` and `"hey"` tokens
+    /// to keep them separated in Rust 2021.
+    pub RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
+    Allow,
+    "identifiers that will be parsed as a prefix in Rust 2021",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #84978 <https://github.com/rust-lang/rust/issues/84978>",
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
+    };
+    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 #87678 <https://github.com/rust-lang/rust/issues/87678>",
+    };
 }
index f1c4e5fb4a368ba1e5a7cdd596155d21157895aa..4190e769976e9bfe374b996959d5295279dddd00 100644 (file)
@@ -51,6 +51,7 @@ pub enum Applicability {
 pub enum Level {
     Allow,
     Warn,
+    ForceWarn,
     Deny,
     Forbid,
 }
@@ -63,6 +64,7 @@ impl Level {
         match self {
             Level::Allow => "allow",
             Level::Warn => "warn",
+            Level::ForceWarn => "force-warn",
             Level::Deny => "deny",
             Level::Forbid => "forbid",
         }
@@ -142,23 +144,50 @@ pub struct Lint {
 pub struct FutureIncompatibleInfo {
     /// e.g., a URL for an issue/PR/RFC or error code
     pub reference: &'static str,
-    /// If this is an edition fixing lint, the edition in which
-    /// this lint becomes obsolete
-    pub edition: Option<Edition>,
-    /// Information about a future breakage, which will
-    /// be emitted in JSON messages to be displayed by Cargo
-    /// for upstream deps
-    pub future_breakage: Option<FutureBreakage>,
+    /// The reason for the lint used by diagnostics to provide
+    /// the right help message
+    pub reason: FutureIncompatibilityReason,
+    /// Whether to explain the reason to the user.
+    ///
+    /// Set to false for lints that already include a more detailed
+    /// explanation.
+    pub explain_reason: bool,
 }
 
+/// The reason for future incompatibility
 #[derive(Copy, Clone, Debug)]
-pub struct FutureBreakage {
-    pub date: Option<&'static str>,
+pub enum FutureIncompatibilityReason {
+    /// This will be an error in a future release
+    /// for all editions
+    FutureReleaseError,
+    /// This will be an error in a future release, and
+    /// Cargo should create a report even for dependencies
+    FutureReleaseErrorReportNow,
+    /// Previously accepted code that will become an
+    /// error in the provided edition
+    EditionError(Edition),
+    /// Code that changes meaning in some way in
+    /// the provided edition
+    EditionSemanticsChange(Edition),
+}
+
+impl FutureIncompatibilityReason {
+    pub fn edition(self) -> Option<Edition> {
+        match self {
+            Self::EditionError(e) => Some(e),
+            Self::EditionSemanticsChange(e) => Some(e),
+            _ => None,
+        }
+    }
 }
 
 impl FutureIncompatibleInfo {
     pub const fn default_fields_for_macro() -> Self {
-        FutureIncompatibleInfo { reference: "", edition: None, future_breakage: None }
+        FutureIncompatibleInfo {
+            reference: "",
+            reason: FutureIncompatibilityReason::FutureReleaseError,
+            explain_reason: true,
+        }
     }
 }
 
@@ -245,7 +274,7 @@ impl<HCX> ToStableHashKey<HCX> for LintId {
 }
 
 // Duplicated from rustc_session::config::ExternDepSpec to avoid cyclic dependency
-#[derive(PartialEq)]
+#[derive(PartialEq, Debug)]
 pub enum ExternDepSpec {
     Json(Json),
     Raw(String),
@@ -253,7 +282,7 @@ pub enum ExternDepSpec {
 
 // This could be a closure, but then implementing derive trait
 // becomes hacky (and it gets allocated).
-#[derive(PartialEq)]
+#[derive(PartialEq, Debug)]
 pub enum BuiltinLintDiagnostics {
     Normal,
     BareTraitObject(Span, /* is_global */ bool),
@@ -272,6 +301,7 @@ pub enum BuiltinLintDiagnostics {
     ExternDepSpec(String, ExternDepSpec),
     ProcMacroBackCompat(String),
     OrPatternsBackCompat(Span, String),
+    ReservedPrefix(Span),
 }
 
 /// Lints that are buffered up early on in the `Session` before the
index 3fca2e1ccb97b876e04fb0d1a9a1a1fabe362668..1bfa489d39eeafc5e8d19d864c06ccbe44d7e5b3 100644 (file)
@@ -13,4 +13,4 @@ libc = "0.2.73"
 
 [build-dependencies]
 build_helper = { path = "../../src/build_helper" }
-cc = "1.0.68"
+cc = "1.0.69"
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 30569f20793fbae6431915bd63d0c43074690f39..b916113a0e551f8e50df375831751344139f0fdd 100644 (file)
@@ -54,7 +54,7 @@ pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_ma
             quote! {}
         } else if let Some(project) = attrs.project {
             quote! {
-                &#bi.#project.hash_stable(__hcx, __hasher);
+                (&#bi.#project).hash_stable(__hcx, __hasher);
             }
         } else {
             quote! {
@@ -96,7 +96,7 @@ pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::To
             quote! {}
         } else if let Some(project) = attrs.project {
             quote! {
-                &#bi.#project.hash_stable(__hcx, __hasher);
+                (&#bi.#project).hash_stable(__hcx, __hasher);
             }
         } else {
             quote! {
index 291e7ef045e4f6c9f7e390c745110dbfa8f89d43..dcd36d61bc6a0e41ea6c534657761bc9dd93ec21 100644 (file)
@@ -367,7 +367,7 @@ fn add_query_description_impl(
                     tcx: QueryCtxt<'tcx>,
                     id: SerializedDepNodeIndex
                 ) -> Option<Self::Value> {
-                    tcx.on_disk_cache.as_ref()?.try_load_query_result(*tcx, id)
+                    tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id)
                 }
             }
         };
index 5b932864dff5da7a8a547bce4a1601de9ac3cbdb..2f063f75eb0ef792634ff566eae9fbb2c5bfbf1d 100644 (file)
@@ -207,7 +207,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) {
             #keyword_stream
         }
 
-        #[allow(rustc::default_hash_types)]
+        #[cfg_attr(bootstrap, allow(rustc::default_hash_types))]
         #[allow(non_upper_case_globals)]
         #[doc(hidden)]
         pub mod sym_generated {
index 29fa0b7006992acf4d7b6295075ced47a07575fb..14b4ebf073652c26cd1ff731fc4fc1560c4cd73f 100644 (file)
@@ -23,7 +23,6 @@ rustc_target = { path = "../rustc_target" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
-stable_deref_trait = "1.0.0"
 rustc_ast = { path = "../rustc_ast" }
 rustc_expand = { path = "../rustc_expand" }
 rustc_span = { path = "../rustc_span" }
index d73cfe35dc4a13cc9c2cdd84337411027a2166b5..5373169bda7abb36cecad68419d16bf036f93452 100644 (file)
@@ -21,7 +21,7 @@ use rustc_session::config::{self, CrateType, ExternLocation};
 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,
@@ -124,8 +130,11 @@ impl<'a> std::fmt::Debug for CrateDump<'a> {
 }
 
 impl CStore {
-    crate fn from_tcx(tcx: TyCtxt<'_>) -> &CStore {
-        tcx.cstore_as_any().downcast_ref::<CStore>().expect("`tcx.cstore` is not a `CStore`")
+    pub fn from_tcx(tcx: TyCtxt<'_>) -> &CStore {
+        tcx.cstore_untracked()
+            .as_any()
+            .downcast_ref::<CStore>()
+            .expect("`tcx.cstore` is not a `CStore`")
     }
 
     fn alloc_new_crate_num(&mut self) -> CrateNum {
@@ -222,10 +231,8 @@ impl<'a> CrateLoader<'a> {
         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 +334,14 @@ impl<'a> CrateLoader<'a> {
 
     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 +415,7 @@ impl<'a> CrateLoader<'a> {
                 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
         };
@@ -598,7 +602,11 @@ impl<'a> CrateLoader<'a> {
         // don't want to match a host crate against an equivalent target one
         // already loaded.
         let root = library.metadata.get_root();
-        Ok(Some(if locator.triple == self.sess.opts.target_triple {
+        // FIXME: why is this condition necessary? It was adding in #33625 but I
+        // don't know why and the original author doesn't remember ...
+        let can_reuse_cratenum =
+            locator.triple == self.sess.opts.target_triple || locator.is_proc_macro == Some(true);
+        Ok(Some(if can_reuse_cratenum {
             let mut result = LoadResult::Loaded(library);
             self.cstore.iter_crate_data(|cnum, data| {
                 if data.name() == root.name() && root.hash() == data.hash() {
@@ -664,7 +672,7 @@ impl<'a> CrateLoader<'a> {
     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 +681,7 @@ impl<'a> CrateLoader<'a> {
             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,
@@ -769,28 +777,32 @@ impl<'a> CrateLoader<'a> {
     }
 
     fn inject_profiler_runtime(&mut self, krate: &ast::Crate) {
-        if (self.sess.instrument_coverage()
-            || self.sess.opts.debugging_opts.profile
-            || self.sess.opts.cg.profile_generate.enabled())
-            && !self.sess.opts.debugging_opts.no_profiler_runtime
+        let profiler_runtime = &self.sess.opts.debugging_opts.profiler_runtime;
+
+        if !(profiler_runtime.is_some()
+            && (self.sess.instrument_coverage()
+                || self.sess.opts.debugging_opts.profile
+                || self.sess.opts.cg.profile_generate.enabled()))
         {
-            info!("loading profiler");
+            return;
+        }
 
-            if self.sess.contains_name(&krate.attrs, sym::no_core) {
-                self.sess.err(
-                    "`profiler_builtins` crate (required by compiler options) \
-                               is not compatible with crate attribute `#![no_core]`",
-                );
-            }
+        info!("loading profiler");
+
+        let name = Symbol::intern(profiler_runtime.as_ref().unwrap());
+        if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) {
+            self.sess.err(
+                "`profiler_builtins` crate (required by compiler options) \
+                        is not compatible with crate attribute `#![no_core]`",
+            );
+        }
 
-            let name = sym::profiler_builtins;
-            let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None);
-            let data = self.cstore.get_crate_data(cnum);
+        let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None);
+        let data = self.cstore.get_crate_data(cnum);
 
-            // Sanity check the loaded crate to ensure it is indeed a profiler runtime
-            if !data.is_profiler_runtime() {
-                self.sess.err("the crate `profiler_builtins` is not a profiler runtime");
-            }
+        // Sanity check the loaded crate to ensure it is indeed a profiler runtime
+        if !data.is_profiler_runtime() {
+            self.sess.err(&format!("the crate `{}` is not a profiler runtime", name));
         }
     }
 
index c3afc9f048cf56309fb702f92a21f99f8dc3a9a1..2d4deb1d8d5da43d9a2e19bdf5d8b32aad0c2383 100644 (file)
@@ -55,8 +55,8 @@ use crate::creader::CStore;
 
 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;
@@ -129,7 +129,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
                 && sess.crt_static(Some(ty))
                 && !sess.target.crt_static_allows_dylibs)
         {
-            for &cnum in tcx.crates().iter() {
+            for &cnum in tcx.crates(()).iter() {
                 if tcx.dep_kind(cnum).macros_only() {
                     continue;
                 }
@@ -152,7 +152,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
     // Sweep all crates for found dylibs. Add all dylibs, as well as their
     // dependencies, ensuring there are no conflicts. The only valid case for a
     // dependency to be relied upon twice is for both cases to rely on a dylib.
-    for &cnum in tcx.crates().iter() {
+    for &cnum in tcx.crates(()).iter() {
         if tcx.dep_kind(cnum).macros_only() {
             continue;
         }
@@ -170,7 +170,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
     }
 
     // Collect what we've got so far in the return vector.
-    let last_crate = tcx.crates().len();
+    let last_crate = tcx.crates(()).len();
     let mut ret = (1..last_crate + 1)
         .map(|cnum| match formats.get(&CrateNum::new(cnum)) {
             Some(&RequireDynamic) => Linkage::Dynamic,
@@ -184,7 +184,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
     //
     // If the crate hasn't been included yet and it's not actually required
     // (e.g., it's an allocator) then we skip it here as well.
-    for &cnum in tcx.crates().iter() {
+    for &cnum in tcx.crates(()).iter() {
         let src = tcx.used_crate_source(cnum);
         if src.dylib.is_none()
             && !formats.contains_key(&cnum)
@@ -274,14 +274,24 @@ 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;
     }
 
     // All crates are available in an rlib format, so we're just going to link
     // everything in explicitly so long as it's actually required.
-    let last_crate = tcx.crates().len();
+    let last_crate = tcx.crates(()).len();
     let mut ret = (1..last_crate + 1)
         .map(|cnum| {
             if tcx.dep_kind(CrateNum::new(cnum)) == CrateDepKind::Explicit {
index 1a900ccbf65faeed61a07c03f4e26755eee44eeb..e8929cd5c0237b91eff421c617c40c3683e5d363 100644 (file)
@@ -70,13 +70,12 @@ mod dl {
         use std::sync::{Mutex, MutexGuard};
 
         pub fn lock() -> MutexGuard<'static, Guard> {
-            static LOCK: SyncLazy<Mutex<Guard>> = SyncLazy::new(|| Mutex::new(Guard { _priv: () }));
+            static LOCK: SyncLazy<Mutex<Guard>> = SyncLazy::new(|| Mutex::new(Guard));
             LOCK.lock().unwrap()
         }
 
-        pub struct Guard {
-            _priv: (),
-        }
+        #[non_exhaustive]
+        pub struct Guard;
 
         impl Guard {
             pub fn get(&mut self) -> Result<(), String> {
index 6e7360950908e9dbd164ff0c7f7ecfebb93f4b91..028104fd6b5057a1bef7d6f13fae94eb9dcc586b 100644 (file)
@@ -226,7 +226,7 @@ use rustc_session::config::{self, CrateType};
 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()),
@@ -1100,7 +1100,9 @@ impl CrateError {
                         if sess.is_nightly_build() && std::env::var("CARGO").is_ok() {
                             err.help("consider building the standard library from source with `cargo build -Zbuild-std`");
                         }
-                    } else if crate_name == sym::profiler_builtins {
+                    } else if Some(crate_name)
+                        == sess.opts.debugging_opts.profiler_runtime.as_deref().map(Symbol::intern)
+                    {
                         err.note(&"the compiler may have been built without the profiler runtime");
                     }
                     err.span_label(span, "can't find crate");
index cd4c394ae14ecf752d1deba6ff36927be57ca8ab..16b4d26b37b4b79879bea9822765f137946a9a39 100644 (file)
@@ -3,8 +3,8 @@ use rustc_data_structures::fx::FxHashSet;
 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 @@ impl ItemLikeVisitor<'tcx> for Collector<'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 @@ impl Collector<'tcx> {
             }
         }
     }
+
+    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 48900fecd3e1bd11df89850f72f3dbdd50e16676..8bdd4313de4c3b6329a99cd8f045cb5d75058382 100644 (file)
@@ -30,13 +30,12 @@ use rustc_middle::ty::codec::TyDecoder;
 use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
 use rustc_serialize::{opaque, Decodable, Decoder};
 use rustc_session::Session;
-use rustc_span::hygiene::ExpnDataDecodeMode;
+use rustc_span::hygiene::{ExpnIndex, MacroKind};
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{sym, Ident, Symbol};
-use rustc_span::{self, hygiene::MacroKind, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
+use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
 
 use proc_macro::bridge::client::ProcMacro;
-use std::cell::Cell;
 use std::io;
 use std::mem;
 use std::num::NonZeroUsize;
@@ -80,6 +79,8 @@ crate struct CrateMetadata {
     /// `DefIndex`. See `raw_def_id_to_def_id` for more details about how
     /// this is used.
     def_path_hash_map: OnceCell<UnhashMap<DefPathHash, DefIndex>>,
+    /// Likewise for ExpnHash.
+    expn_hash_map: OnceCell<UnhashMap<ExpnHash, ExpnIndex>>,
     /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
     alloc_decoding_state: AllocDecodingState,
     /// Caches decoded `DefKey`s.
@@ -350,6 +351,12 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefIndex {
     }
 }
 
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnIndex {
+    fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<ExpnIndex, String> {
+        Ok(ExpnIndex::from_u32(d.read_u32()?))
+    }
+}
+
 impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
     fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<SyntaxContext, String> {
         let cdata = decoder.cdata();
@@ -371,36 +378,35 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId {
     fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<ExpnId, String> {
         let local_cdata = decoder.cdata();
         let sess = decoder.sess.unwrap();
-        let expn_cnum = Cell::new(None);
-        let get_ctxt = |cnum| {
-            expn_cnum.set(Some(cnum));
-            if cnum == LOCAL_CRATE {
-                &local_cdata.hygiene_context
-            } else {
-                &local_cdata.cstore.get_crate_data(cnum).cdata.hygiene_context
-            }
-        };
 
-        rustc_span::hygiene::decode_expn_id(
-            decoder,
-            ExpnDataDecodeMode::Metadata(get_ctxt),
-            |_this, index| {
-                let cnum = expn_cnum.get().unwrap();
-                // Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s
-                // are stored in the owning crate, to avoid duplication.
-                let crate_data = if cnum == LOCAL_CRATE {
-                    local_cdata
-                } else {
-                    local_cdata.cstore.get_crate_data(cnum)
-                };
-                Ok(crate_data
-                    .root
-                    .expn_data
-                    .get(&crate_data, index)
-                    .unwrap()
-                    .decode((&crate_data, sess)))
-            },
-        )
+        let cnum = CrateNum::decode(decoder)?;
+        let index = u32::decode(decoder)?;
+
+        let expn_id = rustc_span::hygiene::decode_expn_id(cnum, index, |expn_id| {
+            let ExpnId { krate: cnum, local_id: index } = expn_id;
+            // Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s
+            // are stored in the owning crate, to avoid duplication.
+            debug_assert_ne!(cnum, LOCAL_CRATE);
+            let crate_data = if cnum == local_cdata.cnum {
+                local_cdata
+            } else {
+                local_cdata.cstore.get_crate_data(cnum)
+            };
+            let expn_data = crate_data
+                .root
+                .expn_data
+                .get(&crate_data, index)
+                .unwrap()
+                .decode((&crate_data, sess));
+            let expn_hash = crate_data
+                .root
+                .expn_hashes
+                .get(&crate_data, index)
+                .unwrap()
+                .decode((&crate_data, sess));
+            (expn_data, expn_hash)
+        });
+        Ok(expn_id)
     }
 }
 
@@ -601,10 +607,23 @@ impl MetadataBlob {
     }
 
     crate fn list_crate_metadata(&self, out: &mut dyn io::Write) -> io::Result<()> {
-        write!(out, "=External Dependencies=\n")?;
         let root = self.get_root();
+        writeln!(out, "Crate info:")?;
+        writeln!(out, "name {}{}", root.name, root.extra_filename)?;
+        writeln!(out, "hash {} stable_crate_id {:?}", root.hash, root.stable_crate_id)?;
+        writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?;
+        writeln!(out, "=External Dependencies=")?;
         for (i, dep) in root.crate_deps.decode(self).enumerate() {
-            write!(out, "{} {}{}\n", i + 1, dep.name, dep.extra_filename)?;
+            writeln!(
+                out,
+                "{} {}{} hash {} host_hash {:?} kind {:?}",
+                i + 1,
+                dep.name,
+                dep.extra_filename,
+                dep.hash,
+                dep.host_hash,
+                dep.kind
+            )?;
         }
         write!(out, "\n")?;
         Ok(())
@@ -620,10 +639,6 @@ impl CrateRoot<'_> {
         self.name
     }
 
-    crate fn disambiguator(&self) -> CrateDisambiguator {
-        self.disambiguator
-    }
-
     crate fn hash(&self) -> Svh {
         self.hash
     }
@@ -716,37 +731,30 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .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),
@@ -950,6 +958,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         self.get_impl_data(id).defaultness
     }
 
+    fn get_impl_constness(&self, id: DefIndex) -> hir::Constness {
+        self.get_impl_data(id).constness
+    }
+
     fn get_coerce_unsized_info(&self, id: DefIndex) -> Option<ty::adjustment::CoerceUnsizedInfo> {
         self.get_impl_data(id).coerce_unsized_info
     }
@@ -1609,6 +1621,41 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         self.def_path_hash_unlocked(index, &mut def_path_hashes)
     }
 
+    fn expn_hash_to_expn_id(&self, index_guess: u32, hash: ExpnHash) -> ExpnId {
+        debug_assert_eq!(ExpnId::from_hash(hash), None);
+        let index_guess = ExpnIndex::from_u32(index_guess);
+        let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self));
+
+        let index = if old_hash == Some(hash) {
+            // Fast path: the expn and its index is unchanged from the
+            // previous compilation session. There is no need to decode anything
+            // else.
+            index_guess
+        } else {
+            // Slow path: We need to find out the new `DefIndex` of the provided
+            // `DefPathHash`, if its still exists. This requires decoding every `DefPathHash`
+            // stored in this crate.
+            let map = self.cdata.expn_hash_map.get_or_init(|| {
+                let end_id = self.root.expn_hashes.size() as u32;
+                let mut map =
+                    UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default());
+                for i in 0..end_id {
+                    let i = ExpnIndex::from_u32(i);
+                    if let Some(hash) = self.root.expn_hashes.get(self, i) {
+                        map.insert(hash.decode(self), i);
+                    } else {
+                        panic!("Missing expn_hash entry for {:?}", i);
+                    }
+                }
+                map
+            });
+            map[&hash]
+        };
+
+        let data = self.root.expn_data.get(self, index).unwrap().decode(self);
+        rustc_span::hygiene::register_expn_id(self.cnum, index, data, hash)
+    }
+
     /// Imports the source_map from an external crate into the source_map of the crate
     /// currently being compiled (the "local crate").
     ///
@@ -1847,6 +1894,7 @@ impl CrateMetadata {
             raw_proc_macros,
             source_map_import_info: OnceCell::new(),
             def_path_hash_map: Default::default(),
+            expn_hash_map: Default::default(),
             alloc_decoding_state,
             cnum,
             cnum_map,
@@ -1927,8 +1975,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 9a97835d9c000e403be89c998b243b3feafb0104..41839c58021ab335c7b2e4c4391d9631544b2834 100644 (file)
@@ -4,9 +4,7 @@ use crate::native_libs;
 use crate::rmeta::encoder;
 
 use rustc_ast as ast;
-use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_data_structures::stable_map::FxHashMap;
-use rustc_data_structures::svh::Svh;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -19,12 +17,12 @@ use rustc_middle::middle::stability::DeprecationEntry;
 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::hygiene::{ExpnHash, ExpnId};
 use rustc_span::source_map::{Span, Spanned};
 use rustc_span::symbol::Symbol;
 
 use rustc_data_structures::sync::Lrc;
-use rustc_span::ExpnId;
 use smallvec::SmallVec;
 use std::any::Any;
 
@@ -169,6 +167,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     is_no_builtins => { cdata.root.no_builtins }
     symbol_mangling_version => { cdata.root.symbol_mangling_version }
     impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
+    impl_constness => { cdata.get_impl_constness(def_id.index) }
     reachable_non_generics => {
         let reachable_non_generics = tcx
             .exported_symbols(cdata.cnum)
@@ -186,7 +185,6 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     }
     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 }
@@ -242,6 +240,7 @@ pub fn provide(providers: &mut Providers) {
     // therefore no actual inputs, they're just reading tables calculated in
     // resolve! Does this work? Unsure! That's what the issue is about
     *providers = Providers {
+        allocator_kind: |tcx, ()| CStore::from_tcx(tcx).allocator_kind(),
         is_dllimport_foreign_item: |tcx, id| match tcx.native_library_kind(id) {
             Some(
                 NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified,
@@ -312,7 +311,7 @@ pub fn provide(providers: &mut Providers) {
             // which is to say, its not deterministic in general. But
             // we believe that libstd is consistently assigned crate
             // num 1, so it should be enough to resolve #46112.
-            let mut crates: Vec<CrateNum> = (*tcx.crates()).to_owned();
+            let mut crates: Vec<CrateNum> = (*tcx.crates(())).to_owned();
             crates.sort();
 
             for &cnum in crates.iter() {
@@ -369,6 +368,7 @@ pub fn provide(providers: &mut Providers) {
             tcx.arena
                 .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE))
         },
+        crates: |tcx, ()| tcx.arena.alloc_slice(&CStore::from_tcx(tcx).crates_untracked()),
 
         ..*providers
     };
@@ -412,7 +412,7 @@ impl CStore {
 
         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);
@@ -451,6 +451,16 @@ impl CStore {
         self.get_crate_data(def_id.krate).get_span(def_id.index, sess)
     }
 
+    pub fn def_kind(&self, def: DefId) -> DefKind {
+        self.get_crate_data(def.krate).def_kind(def.index)
+    }
+
+    pub fn crates_untracked(&self) -> Vec<CrateNum> {
+        let mut result = vec![];
+        self.iter_crate_data(|cnum, _| result.push(cnum));
+        result
+    }
+
     pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize {
         self.get_crate_data(def_id.krate).get_generics(def_id.index, sess).own_counts().lifetimes
     }
@@ -485,16 +495,12 @@ impl CrateStore for CStore {
         self
     }
 
-    fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol {
+    fn crate_name(&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 crate_hash_untracked(&self, cnum: CrateNum) -> Svh {
-        self.get_crate_data(cnum).root.hash
+    fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId {
+        self.get_crate_data(cnum).root.stable_crate_id
     }
 
     /// Returns the `DefKey` for a given `DefId`. This indicates the
@@ -504,10 +510,6 @@ impl CrateStore for CStore {
         self.get_crate_data(def.krate).def_key(def.index)
     }
 
-    fn def_kind(&self, def: DefId) -> DefKind {
-        self.get_crate_data(def.krate).def_kind(def.index)
-    }
-
     fn def_path(&self, def: DefId) -> DefPath {
         self.get_crate_data(def.krate).def_path(def.index)
     }
@@ -526,17 +528,11 @@ impl CrateStore for CStore {
         self.get_crate_data(cnum).def_path_hash_to_def_id(cnum, index_guess, hash)
     }
 
-    fn crates_untracked(&self) -> Vec<CrateNum> {
-        let mut result = vec![];
-        self.iter_crate_data(|cnum, _| result.push(cnum));
-        result
+    fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId {
+        self.get_crate_data(cnum).expn_hash_to_expn_id(index_guess, hash)
     }
 
     fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata {
         encoder::encode_metadata(tcx)
     }
-
-    fn allocator_kind(&self) -> Option<AllocatorKind> {
-        self.allocator_kind()
-    }
 }
index 76007398000415fa8c772be9e21e2d14b49e6579..a4913a32e81efbc7cdfa5276fff142f6e3249df2 100644 (file)
@@ -31,7 +31,7 @@ use rustc_session::config::CrateType;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext};
 use rustc_span::{
-    hygiene::{ExpnDataEncodeMode, HygieneEncodeContext, MacroKind},
+    hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind},
     RealFileName,
 };
 use rustc_target::abi::VariantIdx;
@@ -168,6 +168,12 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefIndex {
     }
 }
 
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnIndex {
+    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+        s.emit_u32(self.as_u32())
+    }
+}
+
 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SyntaxContext {
     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
         rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s)
@@ -176,12 +182,15 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SyntaxContext {
 
 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
-        rustc_span::hygiene::raw_encode_expn_id(
-            *self,
-            &s.hygiene_ctxt,
-            ExpnDataEncodeMode::Metadata,
-            s,
-        )
+        if self.krate == LOCAL_CRATE {
+            // We will only write details for local expansions.  Non-local expansions will fetch
+            // data from the corresponding crate's metadata.
+            // FIXME(#43047) FIXME(#74731) We may eventually want to avoid relying on external
+            // metadata from proc-macro crates.
+            s.hygiene_ctxt.schedule_expn_data_for_encoding(*self);
+        }
+        self.krate.encode(s)?;
+        self.local_id.encode(s)
     }
 }
 
@@ -445,7 +454,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     }
 
     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))
@@ -653,7 +662,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         // Therefore, we need to encode the hygiene data last to ensure that we encode
         // any `SyntaxContext`s that might be used.
         i = self.position();
-        let (syntax_contexts, expn_data) = self.encode_hygiene();
+        let (syntax_contexts, expn_data, expn_hashes) = self.encode_hygiene();
         let hygiene_bytes = self.position() - i;
 
         // Encode source_map. This needs to be done last,
@@ -671,7 +680,6 @@ impl<'a, 'tcx> EncodeContext<'a, '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(),
@@ -702,6 +710,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             tables,
             syntax_contexts,
             expn_data,
+            expn_hashes,
         });
 
         let total_bytes = self.position();
@@ -1061,10 +1070,7 @@ impl EncodeContext<'a, 'tcx> {
             Lazy::empty()
         };
 
-        let data = ModData {
-            reexports,
-            expansion: tcx.hir().definitions().expansion_that_defined(local_def_id),
-        };
+        let data = ModData { reexports, expansion: tcx.expn_that_defined(local_def_id) };
 
         record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data)));
         if self.is_proc_macro {
@@ -1223,7 +1229,12 @@ impl EncodeContext<'a, 'tcx> {
                 let fn_data = if let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind {
                     FnData {
                         asyncness: sig.header.asyncness,
-                        constness: sig.header.constness,
+                        // Can be inside `impl const Trait`, so using sig.header.constness is not reliable
+                        constness: if self.tcx.is_const_fn_raw(def_id) {
+                            hir::Constness::Const
+                        } else {
+                            hir::Constness::NotConst
+                        },
                         param_names: self.encode_fn_param_names_for_body(body),
                     }
                 } else {
@@ -1408,7 +1419,7 @@ impl EncodeContext<'a, 'tcx> {
                     adt_def.repr,
                 )
             }
-            hir::ItemKind::Impl(hir::Impl { defaultness, .. }) => {
+            hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => {
                 let trait_ref = self.tcx.impl_trait_ref(def_id);
                 let polarity = self.tcx.impl_polarity(def_id);
                 let parent = if let Some(trait_ref) = trait_ref {
@@ -1433,8 +1444,13 @@ impl EncodeContext<'a, 'tcx> {
                     }
                 });
 
-                let data =
-                    ImplData { polarity, defaultness, parent_impl: parent, coerce_unsized_info };
+                let data = ImplData {
+                    polarity,
+                    defaultness,
+                    constness,
+                    parent_impl: parent,
+                    coerce_unsized_info,
+                };
 
                 EntryKind::Impl(self.lazy(data))
             }
@@ -1565,7 +1581,7 @@ impl EncodeContext<'a, 'tcx> {
     fn encode_native_libraries(&mut self) -> Lazy<[NativeLib]> {
         empty_proc_macro!(self);
         let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
-        self.lazy(used_libraries.iter().cloned())
+        self.lazy(used_libraries.iter())
     }
 
     fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> {
@@ -1574,23 +1590,31 @@ impl EncodeContext<'a, 'tcx> {
         self.lazy(foreign_modules.iter().map(|(_, m)| m).cloned())
     }
 
-    fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable) {
+    fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable, ExpnHashTable) {
         let mut syntax_contexts: TableBuilder<_, _> = Default::default();
         let mut expn_data_table: TableBuilder<_, _> = Default::default();
+        let mut expn_hash_table: TableBuilder<_, _> = Default::default();
 
         let _: Result<(), !> = self.hygiene_ctxt.encode(
-            &mut (&mut *self, &mut syntax_contexts, &mut expn_data_table),
-            |(this, syntax_contexts, _), index, ctxt_data| {
+            &mut (&mut *self, &mut syntax_contexts, &mut expn_data_table, &mut expn_hash_table),
+            |(this, syntax_contexts, _, _), index, ctxt_data| {
                 syntax_contexts.set(index, this.lazy(ctxt_data));
                 Ok(())
             },
-            |(this, _, expn_data_table), index, expn_data| {
-                expn_data_table.set(index, this.lazy(expn_data));
+            |(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| {
+                if let Some(index) = index.as_local() {
+                    expn_data_table.set(index.as_raw(), this.lazy(expn_data));
+                    expn_hash_table.set(index.as_raw(), this.lazy(hash));
+                }
                 Ok(())
             },
         );
 
-        (syntax_contexts.encode(&mut self.opaque), expn_data_table.encode(&mut self.opaque))
+        (
+            syntax_contexts.encode(&mut self.opaque),
+            expn_data_table.encode(&mut self.opaque),
+            expn_hash_table.encode(&mut self.opaque),
+        )
     }
 
     fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
@@ -1668,7 +1692,7 @@ impl EncodeContext<'a, 'tcx> {
 
     fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> {
         empty_proc_macro!(self);
-        let crates = self.tcx.crates();
+        let crates = self.tcx.crates(());
 
         let mut deps = crates
             .iter()
@@ -1755,7 +1779,7 @@ impl EncodeContext<'a, 'tcx> {
             .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..a487753f4628a4548275019870d0eaf0c9336982 100644 (file)
@@ -18,11 +18,10 @@ use rustc_middle::mir;
 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::hygiene::{ExpnIndex, MacroKind};
 use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::{self, ExpnData, ExpnId, Span};
+use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Span};
 use rustc_target::spec::{PanicStrategy, TargetTriple};
 
 use std::marker::PhantomData;
@@ -171,7 +170,8 @@ macro_rules! Lazy {
 }
 
 type SyntaxContextTable = Lazy<Table<u32, Lazy<SyntaxContextData>>>;
-type ExpnDataTable = Lazy<Table<u32, Lazy<ExpnData>>>;
+type ExpnDataTable = Lazy<Table<ExpnIndex, Lazy<ExpnData>>>;
+type ExpnHashTable = Lazy<Table<ExpnIndex, Lazy<ExpnHash>>>;
 
 #[derive(MetadataEncodable, MetadataDecodable)]
 crate struct ProcMacroData {
@@ -202,7 +202,6 @@ crate struct CrateRoot<'tcx> {
     triple: TargetTriple,
     extra_filename: String,
     hash: Svh,
-    disambiguator: CrateDisambiguator,
     stable_crate_id: StableCrateId,
     panic_strategy: PanicStrategy,
     edition: Edition,
@@ -228,6 +227,7 @@ crate struct CrateRoot<'tcx> {
 
     syntax_contexts: SyntaxContextTable,
     expn_data: ExpnDataTable,
+    expn_hashes: ExpnHashTable,
 
     source_map: Lazy<[rustc_span::SourceFile]>,
 
@@ -392,6 +392,7 @@ struct TraitData {
 #[derive(TyEncodable, TyDecodable)]
 struct ImplData {
     polarity: ty::ImplPolarity,
+    constness: hir::Constness,
     defaultness: hir::Defaultness,
     parent_impl: Option<DefId>,
 
index 8cb30e72f79210bcfc396ef3d60d4759bb3e0006..90ad0256aebf049e99c0618dbcdca427e69bc999 100644 (file)
@@ -28,6 +28,5 @@ rustc_ast = { path = "../rustc_ast" }
 rustc_span = { path = "../rustc_span" }
 chalk-ir = "0.55.0"
 smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
-measureme = "9.1.0"
 rustc_session = { path = "../rustc_session" }
 rustc_type_ir = { path = "../rustc_type_ir" }
index 20bbf9097f4255c80287557d66197b27ff3d085e..392372fad531ead1f3b8c7164264e56089658d86 100644 (file)
@@ -1,7 +1,6 @@
 use self::collector::NodeCollector;
 
 use crate::hir::{AttributeMap, IndexedHir};
-use crate::middle::cstore::CrateStore;
 use crate::ty::TyCtxt;
 use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -9,15 +8,16 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 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};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
@@ -29,7 +29,10 @@ fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
         Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. })
         | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. })
         | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, _), .. }) => Some(&sig.decl),
-        Node::Expr(Expr { kind: ExprKind::Closure(_, fn_decl, ..), .. }) => Some(fn_decl),
+        Node::Expr(Expr { kind: ExprKind::Closure(_, fn_decl, ..), .. })
+        | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, ..), .. }) => {
+            Some(fn_decl)
+        }
         _ => None,
     }
 }
@@ -153,13 +156,9 @@ impl<'hir> Map<'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 +166,14 @@ impl<'hir> Map<'hir> {
     }
 
     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 +189,21 @@ impl<'hir> Map<'hir> {
 
     #[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> {
@@ -456,6 +467,9 @@ impl<'hir> Map<'hir> {
     /// Returns the `ConstContext` of the body associated with this `LocalDefId`.
     ///
     /// Panics if `LocalDefId` does not have an associated body.
+    ///
+    /// This should only be used for determining the context of a body, a return
+    /// value of `Some` does not always suggest that the owner of the body is `const`.
     pub fn body_const_context(&self, did: LocalDefId) -> Option<ConstContext> {
         let hir_id = self.local_def_id_to_hir_id(did);
         let ccx = match self.body_owner_kind(hir_id) {
@@ -464,6 +478,11 @@ impl<'hir> Map<'hir> {
 
             BodyOwnerKind::Fn if self.tcx.is_constructor(did.to_def_id()) => return None,
             BodyOwnerKind::Fn if self.tcx.is_const_fn_raw(did.to_def_id()) => ConstContext::ConstFn,
+            BodyOwnerKind::Fn
+                if self.tcx.has_attr(did.to_def_id(), sym::default_method_body_is_const) =>
+            {
+                ConstContext::ConstFn
+            }
             BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,
         };
 
@@ -931,9 +950,15 @@ impl<'hir> intravisit::Map<'hir> for Map<'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 +968,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 +976,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 +993,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);
 
     // 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 +1016,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)> {
-    let mut upstream_crates: Vec<_> = cstore
-        .crates_untracked()
+fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
+    let mut upstream_crates: Vec<_> = tcx
+        .crates(())
         .iter()
         .map(|&cnum| {
-            let name = cstore.crate_name_untracked(cnum);
-            let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint();
-            let hash = cstore.crate_hash_untracked(cnum);
-            (name, disambiguator, hash)
+            let stable_crate_id = tcx.resolutions(()).cstore.stable_crate_id(cnum);
+            let hash = tcx.crate_hash(cnum);
+            (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 b2fef731b7e2059f8bcde6c5d3db8053f71400d4..32ccdafaeb48c926a87609b2d77ae89564a19b9d 100644 (file)
@@ -14,10 +14,8 @@ use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
 use rustc_span::{BytePos, CachingSourceMapView, SourceFile, SpanData};
 
-use rustc_span::def_id::{CrateNum, CRATE_DEF_INDEX};
 use smallvec::SmallVec;
 use std::cmp::Ord;
-use std::thread::LocalKey;
 
 fn compute_ignored_attr_names() -> FxHashSet<Symbol> {
     debug_assert!(!ich::IGNORED_ATTRIBUTES.is_empty());
@@ -227,22 +225,8 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
     }
 
     #[inline]
-    fn hash_crate_num(&mut self, cnum: CrateNum, hasher: &mut StableHasher) {
-        let hcx = self;
-        hcx.def_path_hash(DefId { krate: cnum, index: CRATE_DEF_INDEX }).hash_stable(hcx, hasher);
-    }
-
-    #[inline]
-    fn hash_def_id(&mut self, def_id: DefId, hasher: &mut StableHasher) {
-        let hcx = self;
-        hcx.def_path_hash(def_id).hash_stable(hcx, hasher);
-    }
-
-    fn expn_id_cache() -> &'static LocalKey<rustc_span::ExpnIdCache> {
-        thread_local! {
-            static CACHE: rustc_span::ExpnIdCache = Default::default();
-        }
-        &CACHE
+    fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
+        self.def_path_hash(def_id)
     }
 
     fn span_data_to_lines_and_cols(
@@ -253,6 +237,8 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
     }
 }
 
+impl rustc_session::HashStableContext for StableHashingContext<'a> {}
+
 pub fn hash_stable_trait_impls<'a>(
     hcx: &mut StableHashingContext<'a>,
     hasher: &mut StableHasher,
index abf56832329b2a6c6a3380eaa1998b4ef90288a2..5dfd00bc6d42c36e372f1d0cd4a22bc806b8e3a7 100644 (file)
@@ -6,7 +6,6 @@ use rustc_attr as attr;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::definitions::DefPathHash;
 use smallvec::SmallVec;
 use std::mem;
@@ -113,46 +112,6 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
 
         self.node_id_hashing_mode = prev_hash_node_ids;
     }
-
-    #[inline]
-    fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash {
-        self.local_def_path_hash(def_id)
-    }
-}
-
-impl<'a> ToStableHashKey<StableHashingContext<'a>> for DefId {
-    type KeyType = DefPathHash;
-
-    #[inline]
-    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
-        hcx.def_path_hash(*self)
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for LocalDefId {
-    #[inline]
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        hcx.def_path_hash(self.to_def_id()).hash_stable(hcx, hasher);
-    }
-}
-
-impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalDefId {
-    type KeyType = DefPathHash;
-
-    #[inline]
-    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
-        hcx.def_path_hash(self.to_def_id())
-    }
-}
-
-impl<'a> ToStableHashKey<StableHashingContext<'a>> for CrateNum {
-    type KeyType = DefPathHash;
-
-    #[inline]
-    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
-        let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
-        def_id.to_stable_hash_key(hcx)
-    }
 }
 
 impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::ItemLocalId {
index e1d7bc4be533c467fa07a833296441957abbfd49..f2acc601d4f62dc5b2b6d79e1fa0cdb9b4ac9d43 100644 (file)
 #![feature(crate_visibility_modifier)]
 #![feature(associated_type_bounds)]
 #![feature(rustc_attrs)]
-#![feature(int_error_matching)]
 #![feature(half_open_range_patterns)]
 #![feature(exclusive_range_pattern)]
 #![feature(control_flow_enum)]
 #![feature(associated_type_defaults)]
 #![feature(iter_zip)]
 #![feature(thread_local_const_init)]
+#![feature(try_reserve)]
+#![feature(nonzero_ops)]
 #![recursion_limit = "512"]
 
 #[macro_use]
index 4c7ea937ceb7dd1d9f486b05daba3248c89674c7..6ad68877235dc7d6453c65be964d44e5b278f05a 100644 (file)
@@ -1,13 +1,14 @@
 use std::cmp;
 
 use crate::ich::StableHashingContext;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
 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},
-    Level, Lint, LintId,
+    FutureIncompatibilityReason, Level, Lint, LintId,
 };
 use rustc_session::{DiagnosticMessageId, Session};
 use rustc_span::hygiene::MacroKind;
@@ -28,9 +29,6 @@ pub enum LintLevelSource {
     /// The provided `Level` is the level specified on the command line.
     /// (The actual level may be lower due to `--cap-lints`.)
     CommandLine(Symbol, Level),
-
-    /// Lint is being forced to warn no matter what.
-    ForceWarn(Symbol),
 }
 
 impl LintLevelSource {
@@ -39,7 +37,6 @@ impl LintLevelSource {
             LintLevelSource::Default => symbol::kw::Default,
             LintLevelSource::Node(name, _, _) => name,
             LintLevelSource::CommandLine(name, _) => name,
-            LintLevelSource::ForceWarn(name) => name,
         }
     }
 
@@ -48,7 +45,6 @@ impl LintLevelSource {
             LintLevelSource::Default => DUMMY_SP,
             LintLevelSource::Node(_, span, _) => span,
             LintLevelSource::CommandLine(_, _) => DUMMY_SP,
-            LintLevelSource::ForceWarn(_) => DUMMY_SP,
         }
     }
 }
@@ -56,48 +52,40 @@ impl LintLevelSource {
 /// 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,
-    pub force_warns: FxHashSet<LintId>,
 }
 
-#[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,
-            force_warns: FxHashSet::default(),
-        }
+        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 {
-        // Check whether we should always warn
-        if self.force_warns.contains(&LintId::of(lint)) {
-            return (Level::Warn, LintLevelSource::ForceWarn(Symbol::intern(lint.name)));
-        }
-
         let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);
 
         // If `level` is none then we actually assume the default level for this
@@ -123,8 +111,13 @@ impl LintLevelSets {
             }
         }
 
-        // 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.
@@ -137,7 +130,7 @@ impl LintLevelSets {
     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 {
@@ -146,20 +139,14 @@ impl LintLevelSets {
             }
         }
         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;
         }
     }
 }
@@ -167,7 +154,7 @@ impl LintLevelSets {
 #[derive(Debug)]
 pub struct LintLevelMap {
     pub sets: LintLevelSets,
-    pub id_to_set: FxHashMap<HirId, u32>,
+    pub id_to_set: FxHashMap<HirId, LintStackIndex>,
 }
 
 impl LintLevelMap {
@@ -191,33 +178,11 @@ impl LintLevelMap {
 impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
     #[inline]
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let LintLevelMap { ref sets, ref id_to_set, .. } = *self;
+        let LintLevelMap { ref sets, ref id_to_set } = *self;
 
         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 +223,13 @@ pub fn struct_lint_level<'s, 'd>(
         let lint_id = LintId::of(lint);
         let future_incompatible = lint.future_incompatible;
 
-        let has_future_breakage =
-            future_incompatible.map_or(false, |incompat| incompat.future_breakage.is_some());
+        let has_future_breakage = future_incompatible.map_or(
+            // Default allow lints trigger too often for testing.
+            sess.opts.debugging_opts.future_incompat_test && lint.default_level != Level::Allow,
+            |incompat| {
+                matches!(incompat.reason, FutureIncompatibilityReason::FutureReleaseErrorReportNow)
+            },
+        );
 
         let mut err = match (level, span) {
             (Level::Allow, span) => {
@@ -275,6 +245,8 @@ pub fn struct_lint_level<'s, 'd>(
             }
             (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(""),
         };
@@ -292,7 +264,7 @@ pub fn struct_lint_level<'s, 'd>(
             // if this lint occurs in the expansion of a macro from an external crate,
             // allow individual lints to opt-out from being reported.
             let not_future_incompatible =
-                future_incompatible.map(|f| f.edition.is_some()).unwrap_or(true);
+                future_incompatible.map(|f| f.reason.edition().is_some()).unwrap_or(true);
             if not_future_incompatible && !lint.report_in_external_macro {
                 err.cancel();
                 // Don't continue further, since we don't want to have
@@ -316,6 +288,7 @@ pub fn struct_lint_level<'s, 'd>(
                     Level::Deny => "-D",
                     Level::Forbid => "-F",
                     Level::Allow => "-A",
+                    Level::ForceWarn => "--force-warn",
                 };
                 let hyphen_case_lint_name = name.replace("_", "-");
                 if lint_flag_val.as_str() == name {
@@ -361,21 +334,12 @@ pub fn struct_lint_level<'s, 'd>(
                     );
                 }
             }
-            LintLevelSource::ForceWarn(_) => {
-                sess.diag_note_once(
-                    &mut err,
-                    DiagnosticMessageId::from(lint),
-                    "warning forced by `force-warns` commandline option",
-                );
-            }
         }
 
-        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 {
-            const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \
-                 it will become a hard error";
-
             let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) {
                 "once this associated item is added to the standard library, the ambiguity may \
                  cause an error or change in behavior!"
@@ -384,14 +348,31 @@ pub fn struct_lint_level<'s, 'd>(
                 "this borrowing pattern was not meant to be accepted, and may become a hard error \
                  in the future"
                     .to_owned()
-            } else if let Some(edition) = future_incompatible.edition {
-                format!("{} in the {} edition!", STANDARD_MESSAGE, edition)
+            } else if let FutureIncompatibilityReason::EditionError(edition) =
+                future_incompatible.reason
+            {
+                let current_edition = sess.edition();
+                format!(
+                    "this is accepted in the current edition (Rust {}) but is a hard error in Rust {}!",
+                    current_edition, edition
+                )
+            } else if let FutureIncompatibilityReason::EditionSemanticsChange(edition) =
+                future_incompatible.reason
+            {
+                format!("this changes meaning in Rust {}", edition)
             } else {
-                format!("{} in a future release!", STANDARD_MESSAGE)
+                "this was previously accepted by the compiler but is being phased out; \
+                 it will become a hard error in a future release!"
+                    .to_owned()
             };
-            let citation = format!("for more information, see {}", future_incompatible.reference);
-            err.warn(&explanation);
-            err.note(&citation);
+            if future_incompatible.explain_reason {
+                err.warn(&explanation);
+            }
+            if !future_incompatible.reference.is_empty() {
+                let citation =
+                    format!("for more information, see {}", future_incompatible.reference);
+                err.note(&citation);
+            }
         }
 
         // Finally, run `decorate`. This function is also responsible for emitting the diagnostic.
@@ -411,7 +392,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 fc3dafe99e5ec617e4a2c969d7094e2925934e93..93e7aeaffce3771ea62e15a0a0552b8000107fd6 100644 (file)
@@ -38,6 +38,9 @@ pub struct CodegenFnAttrs {
     /// be generated against a specific instruction set. Only usable on architectures which allow
     /// switching between multiple instruction sets.
     pub instruction_set: Option<InstructionSetAttr>,
+    /// The `#[repr(align(...))]` attribute. Indicates the value of which the function should be
+    /// aligned to.
+    pub alignment: Option<u32>,
 }
 
 bitflags! {
@@ -107,6 +110,7 @@ impl CodegenFnAttrs {
             link_section: None,
             no_sanitize: SanitizerSet::empty(),
             instruction_set: None,
+            alignment: None,
         }
     }
 
index a7ab43d106c4a45d9a567435569b714876985344..8150e67929509e3f4df6d2a26758786069e59a95 100644 (file)
@@ -5,16 +5,13 @@
 use crate::ty::TyCtxt;
 
 use rustc_ast as ast;
-use rustc_ast::expand::allocator::AllocatorKind;
-use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{self, MetadataRef};
-use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, StableCrateId, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
 use rustc_macros::HashStable;
 use rustc_session::search_paths::PathKind;
 use rustc_session::utils::NativeLibKind;
-use rustc_session::CrateDisambiguator;
+use rustc_span::hygiene::{ExpnHash, ExpnId};
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use rustc_target::spec::Target;
@@ -61,33 +58,13 @@ impl CrateDepKind {
     }
 }
 
-#[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,
     RequireStatic,
 }
 
-#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
+#[derive(Debug, Encodable, Decodable, HashStable)]
 pub struct NativeLib {
     pub kind: NativeLibKind,
     pub name: Option<Symbol>,
@@ -102,6 +79,25 @@ pub struct NativeLib {
 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(Clone, PartialEq, Debug, Encodable, Decodable, HashStable)]
+pub enum DllCallingConvention {
+    C,
+    Stdcall(usize),
+    Fastcall(usize),
+    Vectorcall(usize),
 }
 
 #[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
@@ -189,75 +185,32 @@ pub type MetadataLoaderDyn = dyn MetadataLoader + Sync;
 /// 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
+    // Foreign definitions.
+    // This information is safe to access, since it's hashed as part of the DefPathHash, which incr.
+    // comp. uses to identify a DefId.
     fn def_key(&self, def: DefId) -> DefKey;
-    fn def_kind(&self, def: DefId) -> DefKind;
     fn def_path(&self, def: DefId) -> DefPath;
     fn def_path_hash(&self, def: DefId) -> DefPathHash;
+
+    // This information is safe to access, since it's hashed as part of the StableCrateId, which
+    // incr.  comp. uses to identify a CrateNum.
+    fn crate_name(&self, cnum: CrateNum) -> Symbol;
+    fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId;
+
+    /// Fetch a DefId from a DefPathHash for a foreign crate.
     fn def_path_hash_to_def_id(
         &self,
         cnum: CrateNum,
         index_guess: u32,
         hash: DefPathHash,
     ) -> Option<DefId>;
-
-    // "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 crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
-
-    // This is basically a 1-based range of ints, which is a little
-    // silly - I may fix that.
-    fn crates_untracked(&self) -> Vec<CrateNum>;
+    fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId;
 
     // utility functions
     fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata;
-    fn allocator_kind(&self) -> Option<AllocatorKind>;
 }
 
 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 @@ impl<'tcx> ExportedSymbol<'tcx> {
 
 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 mod privacy;
 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 @@ impl<'tcx> TyCtxt<'tcx> {
                     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 776a777b1bdb5844c982a84be2dd39e94dbc5a0a..1ef10241143b83ed0ca19f0c51abff8f84ff0419 100644 (file)
@@ -1,6 +1,6 @@
 //! A subset of a mir body used for const evaluatability checking.
-use crate::mir;
-use crate::ty;
+use crate::mir::{self, CastKind};
+use crate::ty::{self, Ty};
 
 rustc_index::newtype_index! {
     /// An index into an `AbstractConst`.
@@ -17,6 +17,7 @@ pub enum Node<'tcx> {
     Binop(mir::BinOp, NodeId, NodeId),
     UnaryOp(mir::UnOp, NodeId),
     FunctionCall(NodeId, &'tcx [NodeId]),
+    Cast(CastKind, NodeId, Ty<'tcx>),
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
index ee3902991e911afe5073ea1606996d3ddf2339e7..bbf792edcded9ee27cade96ed363776996ec9cb3 100644 (file)
@@ -3,17 +3,20 @@
 use std::borrow::Cow;
 use std::convert::TryFrom;
 use std::iter;
-use std::ops::{Deref, DerefMut, Range};
+use std::ops::{Deref, Range};
 use std::ptr;
 
 use rustc_ast::Mutability;
 use rustc_data_structures::sorted_map::SortedMap;
+use rustc_span::DUMMY_SP;
 use rustc_target::abi::{Align, HasDataLayout, Size};
 
 use super::{
-    read_target_uint, write_target_uint, AllocId, InterpError, Pointer, Scalar, ScalarMaybeUninit,
-    UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
+    read_target_uint, write_target_uint, AllocId, InterpError, InterpResult, Pointer,
+    ResourceExhaustionInfo, Scalar, ScalarMaybeUninit, UndefinedBehaviorInfo, UninitBytesAccess,
+    UnsupportedOpInfo,
 };
+use crate::ty;
 
 /// This type represents an Allocation in the Miri/CTFE core engine.
 ///
@@ -22,7 +25,7 @@ use super::{
 /// module provides higher-level access.
 #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
-pub struct Allocation<Tag = (), Extra = ()> {
+pub struct Allocation<Tag = AllocId, Extra = ()> {
     /// The actual bytes of the allocation.
     /// Note that the bytes of a pointer represent the offset of the pointer.
     bytes: Vec<u8>,
@@ -121,38 +124,62 @@ impl<Tag> Allocation<Tag> {
         Allocation::from_bytes(slice, Align::ONE, Mutability::Not)
     }
 
-    pub fn uninit(size: Size, align: Align) -> Self {
-        Allocation {
-            bytes: vec![0; size.bytes_usize()],
+    /// Try to create an Allocation of `size` bytes, failing if there is not enough memory
+    /// available to the compiler to do so.
+    pub fn uninit(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'static, Self> {
+        let mut bytes = Vec::new();
+        bytes.try_reserve(size.bytes_usize()).map_err(|_| {
+            // This results in an error that can happen non-deterministically, since the memory
+            // available to the compiler can change between runs. Normally queries are always
+            // deterministic. However, we can be non-determinstic here because all uses of const
+            // evaluation (including ConstProp!) will make compilation fail (via hard error
+            // or ICE) upon encountering a `MemoryExhausted` error.
+            if panic_on_fail {
+                panic!("Allocation::uninit called with panic_on_fail had allocation failure")
+            }
+            ty::tls::with(|tcx| {
+                tcx.sess.delay_span_bug(DUMMY_SP, "exhausted memory during interpreation")
+            });
+            InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
+        })?;
+        bytes.resize(size.bytes_usize(), 0);
+        Ok(Allocation {
+            bytes,
             relocations: Relocations::new(),
             init_mask: InitMask::new(size, false),
             align,
             mutability: Mutability::Mut,
             extra: (),
-        }
+        })
     }
 }
 
-impl Allocation<()> {
-    /// Add Tag and Extra fields
-    pub fn with_tags_and_extra<T, E>(
+impl Allocation {
+    /// Convert Tag and add Extra fields
+    pub fn convert_tag_add_extra<Tag, Extra>(
         self,
-        mut tagger: impl FnMut(AllocId) -> T,
-        extra: E,
-    ) -> Allocation<T, E> {
+        cx: &impl HasDataLayout,
+        extra: Extra,
+        mut tagger: impl FnMut(Pointer<AllocId>) -> Pointer<Tag>,
+    ) -> Allocation<Tag, Extra> {
+        // Compute new pointer tags, which also adjusts the bytes.
+        let mut bytes = self.bytes;
+        let mut new_relocations = Vec::with_capacity(self.relocations.0.len());
+        let ptr_size = cx.data_layout().pointer_size.bytes_usize();
+        let endian = cx.data_layout().endian;
+        for &(offset, alloc_id) in self.relocations.iter() {
+            let idx = offset.bytes_usize();
+            let ptr_bytes = &mut bytes[idx..idx + ptr_size];
+            let bits = read_target_uint(endian, ptr_bytes).unwrap();
+            let (ptr_tag, ptr_offset) =
+                tagger(Pointer::new(alloc_id, Size::from_bytes(bits))).into_parts();
+            write_target_uint(endian, ptr_bytes, ptr_offset.bytes().into()).unwrap();
+            new_relocations.push((offset, ptr_tag));
+        }
+        // Create allocation.
         Allocation {
-            bytes: self.bytes,
-            relocations: Relocations::from_presorted(
-                self.relocations
-                    .iter()
-                    // The allocations in the relocations (pointers stored *inside* this allocation)
-                    // all get the base pointer tag.
-                    .map(|&(offset, ((), alloc))| {
-                        let tag = tagger(alloc);
-                        (offset, (tag, alloc))
-                    })
-                    .collect(),
-            ),
+            bytes,
+            relocations: Relocations::from_presorted(new_relocations),
             init_mask: self.init_mask,
             align: self.align,
             mutability: self.mutability,
@@ -258,6 +285,9 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
     /// A raw pointer variant of `get_bytes_mut` that avoids invalidating existing aliases into this memory.
     pub fn get_bytes_mut_ptr(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> *mut [u8] {
         self.mark_init(range, true);
+        // This also clears relocations that just overlap with the written range. So writing to some
+        // byte can de-initialize its neighbors! See
+        // <https://github.com/rust-lang/rust/issues/87184> for details.
         self.clear_relocations(cx, range);
 
         assert!(range.end().bytes_usize() <= self.bytes.len()); // need to do our own bounds-check
@@ -300,7 +330,11 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
         cx: &impl HasDataLayout,
         range: AllocRange,
     ) -> AllocResult<ScalarMaybeUninit<Tag>> {
-        // `get_bytes_unchecked` tests relocation edges.
+        // `get_bytes_with_uninit_and_ptr` tests relocation edges.
+        // We deliberately error when loading data that partially has provenance, or partially
+        // initialized data (that's the check below), into a scalar. The LLVM semantics of this are
+        // unclear so we are conservative. See <https://github.com/rust-lang/rust/issues/69488> for
+        // further discussion.
         let bytes = self.get_bytes_with_uninit_and_ptr(cx, range)?;
         // Uninit check happens *after* we established that the alignment is correct.
         // We must not return `Ok()` for unaligned pointers!
@@ -318,9 +352,9 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
             self.check_relocations(cx, range)?;
         } else {
             // Maybe a pointer.
-            if let Some(&(tag, alloc_id)) = self.relocations.get(&range.start) {
-                let ptr = Pointer::new_with_tag(alloc_id, Size::from_bytes(bits), tag);
-                return Ok(ScalarMaybeUninit::Scalar(ptr.into()));
+            if let Some(&prov) = self.relocations.get(&range.start) {
+                let ptr = Pointer::new(prov, Size::from_bytes(bits));
+                return Ok(ScalarMaybeUninit::from_pointer(ptr, cx));
             }
         }
         // We don't. Just return the bits.
@@ -340,6 +374,8 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
         range: AllocRange,
         val: ScalarMaybeUninit<Tag>,
     ) -> AllocResult {
+        assert!(self.mutability == Mutability::Mut);
+
         let val = match val {
             ScalarMaybeUninit::Scalar(scalar) => scalar,
             ScalarMaybeUninit::Uninit => {
@@ -348,9 +384,14 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
             }
         };
 
-        let bytes = match val.to_bits_or_ptr(range.size, cx) {
-            Err(val) => u128::from(val.offset.bytes()),
-            Ok(data) => data,
+        // `to_bits_or_ptr_internal` is the right method because we just want to store this data
+        // as-is into memory.
+        let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size) {
+            Err(val) => {
+                let (provenance, offset) = val.into_parts();
+                (u128::from(offset.bytes()), Some(provenance))
+            }
+            Ok(data) => (data, None),
         };
 
         let endian = cx.data_layout().endian;
@@ -358,8 +399,8 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
         write_target_uint(endian, dst, bytes).unwrap();
 
         // See if we have to also write a relocation.
-        if let Scalar::Ptr(val) = val {
-            self.relocations.insert(range.start, (val.tag, val.alloc_id));
+        if let Some(provenance) = provenance {
+            self.relocations.0.insert(range.start, provenance);
         }
 
         Ok(())
@@ -369,11 +410,7 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
 /// Relocations.
 impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
     /// Returns all relocations overlapping with the given pointer-offset pair.
-    pub fn get_relocations(
-        &self,
-        cx: &impl HasDataLayout,
-        range: AllocRange,
-    ) -> &[(Size, (Tag, AllocId))] {
+    pub fn get_relocations(&self, cx: &impl HasDataLayout, range: AllocRange) -> &[(Size, Tag)] {
         // We have to go back `pointer_size - 1` bytes, as that one would still overlap with
         // the beginning of this range.
         let start = range.start.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1);
@@ -423,7 +460,7 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
         }
 
         // Forget all the relocations.
-        self.relocations.remove_range(first..last);
+        self.relocations.0.remove_range(first..last);
     }
 
     /// Errors if there are relocations overlapping with the edges of the
@@ -463,6 +500,7 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
         if range.size.bytes() == 0 {
             return;
         }
+        assert!(self.mutability == Mutability::Mut);
         self.init_mask.set_range(range.start, range.end(), is_init);
     }
 }
@@ -488,7 +526,7 @@ impl InitMaskCompressed {
 /// Transferring the initialization mask to other allocations.
 impl<Tag, Extra> Allocation<Tag, Extra> {
     /// Creates a run-length encoding of the initialization mask.
-    pub fn compress_uninit_range(&self, src: Pointer<Tag>, size: Size) -> InitMaskCompressed {
+    pub fn compress_uninit_range(&self, range: AllocRange) -> InitMaskCompressed {
         // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`),
         // a naive initialization mask copying algorithm would repeatedly have to read the initialization mask from
         // the source and write it to the destination. Even if we optimized the memory accesses,
@@ -502,13 +540,13 @@ impl<Tag, Extra> Allocation<Tag, Extra> {
         // where each element toggles the state.
 
         let mut ranges = smallvec::SmallVec::<[u64; 1]>::new();
-        let initial = self.init_mask.get(src.offset);
+        let initial = self.init_mask.get(range.start);
         let mut cur_len = 1;
         let mut cur = initial;
 
-        for i in 1..size.bytes() {
+        for i in 1..range.size.bytes() {
             // FIXME: optimize to bitshift the current uninitialized block's bits and read the top bit.
-            if self.init_mask.get(src.offset + Size::from_bytes(i)) == cur {
+            if self.init_mask.get(range.start + Size::from_bytes(i)) == cur {
                 cur_len += 1;
             } else {
                 ranges.push(cur_len);
@@ -526,24 +564,23 @@ impl<Tag, Extra> Allocation<Tag, Extra> {
     pub fn mark_compressed_init_range(
         &mut self,
         defined: &InitMaskCompressed,
-        dest: Pointer<Tag>,
-        size: Size,
+        range: AllocRange,
         repeat: u64,
     ) {
         // An optimization where we can just overwrite an entire range of initialization
         // bits if they are going to be uniformly `1` or `0`.
         if defined.ranges.len() <= 1 {
             self.init_mask.set_range_inbounds(
-                dest.offset,
-                dest.offset + size * repeat, // `Size` operations
+                range.start,
+                range.start + range.size * repeat, // `Size` operations
                 defined.initial,
             );
             return;
         }
 
         for mut j in 0..repeat {
-            j *= size.bytes();
-            j += dest.offset.bytes();
+            j *= range.size.bytes();
+            j += range.start.bytes();
             let mut cur = defined.initial;
             for range in &defined.ranges {
                 let old_j = j;
@@ -559,39 +596,33 @@ impl<Tag, Extra> Allocation<Tag, Extra> {
     }
 }
 
-/// Relocations.
+/// "Relocations" stores the provenance information of pointers stored in memory.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
-pub struct Relocations<Tag = (), Id = AllocId>(SortedMap<Size, (Tag, Id)>);
+pub struct Relocations<Tag = AllocId>(SortedMap<Size, Tag>);
 
-impl<Tag, Id> Relocations<Tag, Id> {
+impl<Tag> Relocations<Tag> {
     pub fn new() -> Self {
         Relocations(SortedMap::new())
     }
 
     // The caller must guarantee that the given relocations are already sorted
     // by address and contain no duplicates.
-    pub fn from_presorted(r: Vec<(Size, (Tag, Id))>) -> Self {
+    pub fn from_presorted(r: Vec<(Size, Tag)>) -> Self {
         Relocations(SortedMap::from_presorted_elements(r))
     }
 }
 
 impl<Tag> Deref for Relocations<Tag> {
-    type Target = SortedMap<Size, (Tag, AllocId)>;
+    type Target = SortedMap<Size, Tag>;
 
     fn deref(&self) -> &Self::Target {
         &self.0
     }
 }
 
-impl<Tag> DerefMut for Relocations<Tag> {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        &mut self.0
-    }
-}
-
 /// A partial, owned list of relocations to transfer into another allocation.
 pub struct AllocationRelocations<Tag> {
-    relative_relocations: Vec<(Size, (Tag, AllocId))>,
+    relative_relocations: Vec<(Size, Tag)>,
 }
 
 impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
@@ -629,7 +660,7 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
     /// The affected range, as defined in the parameters to `prepare_relocation_copy` is expected
     /// to be clear of relocations.
     pub fn mark_relocation_range(&mut self, relocations: AllocationRelocations<Tag>) {
-        self.relocations.insert_presorted(relocations.relative_relocations);
+        self.relocations.0.insert_presorted(relocations.relative_relocations);
     }
 }
 
index 65d9c1dd90efbdc76dfc8897414686d8c47366f2..94ac303b109a52011f576fdc18005eb025a85f48 100644 (file)
@@ -170,6 +170,8 @@ impl fmt::Display for InvalidProgramInfo<'_> {
 /// Details of why a pointer had to be in-bounds.
 #[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
 pub enum CheckInAllocMsg {
+    /// We are dereferencing a pointer (i.e., creating a place).
+    DerefTest,
     /// We are access memory.
     MemoryAccessTest,
     /// We are doing pointer arithmetic.
@@ -179,13 +181,14 @@ pub enum CheckInAllocMsg {
 }
 
 impl fmt::Display for CheckInAllocMsg {
-    /// When this is printed as an error the context looks like this
-    /// "{msg}pointer must be in-bounds at offset..."
+    /// When this is printed as an error the context looks like this:
+    /// "{msg}0x01 is not a valid pointer".
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(
             f,
             "{}",
             match *self {
+                CheckInAllocMsg::DerefTest => "dereferencing pointer failed: ",
                 CheckInAllocMsg::MemoryAccessTest => "memory access failed: ",
                 CheckInAllocMsg::PointerArithmeticTest => "pointer arithmetic failed: ",
                 CheckInAllocMsg::InboundsTest => "",
@@ -227,16 +230,23 @@ pub enum UndefinedBehaviorInfo<'tcx> {
     /// Invalid metadata in a wide pointer (using `str` to avoid allocations).
     InvalidMeta(&'static str),
     /// Invalid drop function in vtable.
-    InvalidDropFn(FnSig<'tcx>),
+    InvalidVtableDropFn(FnSig<'tcx>),
+    /// Invalid size in a vtable: too large.
+    InvalidVtableSize,
+    /// Invalid alignment in a vtable: too large, or not a power of 2.
+    InvalidVtableAlignment(String),
     /// Reading a C string that does not end within its allocation.
     UnterminatedCString(Pointer),
     /// Dereferencing a dangling pointer after it got freed.
     PointerUseAfterFree(AllocId),
     /// Used a pointer outside the bounds it is valid for.
+    /// (If `ptr_size > 0`, determines the size of the memory range that was expected to be in-bounds.)
     PointerOutOfBounds {
-        ptr: Pointer,
+        alloc_id: AllocId,
+        alloc_size: Size,
+        ptr_offset: i64,
+        ptr_size: Size,
         msg: CheckInAllocMsg,
-        allocation_size: Size,
     },
     /// Using an integer as a pointer in the wrong way.
     DanglingIntPointer(u64, CheckInAllocMsg),
@@ -252,7 +262,12 @@ pub enum UndefinedBehaviorInfo<'tcx> {
     /// The value validity check found a problem.
     /// Should only be thrown by `validity.rs` and always point out which part of the value
     /// is the problem.
-    ValidationFailure(String),
+    ValidationFailure {
+        /// The "path" to the value in question, e.g. `.0[5].field` for a struct
+        /// field in the 6th element of an array that is the first element of a tuple.
+        path: Option<String>,
+        msg: String,
+    },
     /// Using a non-boolean `u8` as bool.
     InvalidBool(u8),
     /// Using a non-character `u32` as character.
@@ -287,27 +302,42 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
             RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
             PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
             InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg),
-            InvalidDropFn(sig) => write!(
+            InvalidVtableDropFn(sig) => write!(
                 f,
                 "invalid drop function signature: got {}, expected exactly one argument which must be a pointer type",
                 sig
             ),
+            InvalidVtableSize => {
+                write!(f, "invalid vtable: size is bigger than largest supported object")
+            }
+            InvalidVtableAlignment(msg) => write!(f, "invalid vtable: alignment {}", msg),
             UnterminatedCString(p) => write!(
                 f,
-                "reading a null-terminated string starting at {} with no null found before end of allocation",
+                "reading a null-terminated string starting at {:?} with no null found before end of allocation",
                 p,
             ),
             PointerUseAfterFree(a) => {
                 write!(f, "pointer to {} was dereferenced after this allocation got freed", a)
             }
-            PointerOutOfBounds { ptr, msg, allocation_size } => write!(
+            PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size: Size::ZERO, msg } => {
+                write!(
+                    f,
+                    "{}{alloc_id} has size {alloc_size}, so pointer at offset {ptr_offset} is out-of-bounds",
+                    msg,
+                    alloc_id = alloc_id,
+                    alloc_size = alloc_size.bytes(),
+                    ptr_offset = ptr_offset,
+                )
+            }
+            PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => write!(
                 f,
-                "{}pointer must be in-bounds at offset {}, \
-                           but is outside bounds of {} which has size {}",
+                "{}{alloc_id} has size {alloc_size}, so pointer to {ptr_size} byte{ptr_size_p} starting at offset {ptr_offset} is out-of-bounds",
                 msg,
-                ptr.offset.bytes(),
-                ptr.alloc_id,
-                allocation_size.bytes()
+                alloc_id = alloc_id,
+                alloc_size = alloc_size.bytes(),
+                ptr_size = ptr_size.bytes(),
+                ptr_size_p = pluralize!(ptr_size.bytes()),
+                ptr_offset = ptr_offset,
             ),
             DanglingIntPointer(0, CheckInAllocMsg::InboundsTest) => {
                 write!(f, "null pointer is not a valid pointer for this operation")
@@ -323,7 +353,10 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
             ),
             WriteToReadOnly(a) => write!(f, "writing to {} which is read-only", a),
             DerefFunctionPointer(a) => write!(f, "accessing {} which contains a function", a),
-            ValidationFailure(ref err) => write!(f, "type validation failed: {}", err),
+            ValidationFailure { path: None, msg } => write!(f, "type validation failed: {}", msg),
+            ValidationFailure { path: Some(path), msg } => {
+                write!(f, "type validation failed at {}: {}", path, msg)
+            }
             InvalidBool(b) => {
                 write!(f, "interpreting an invalid 8-bit value as a bool: 0x{:02x}", b)
             }
@@ -332,13 +365,13 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
             }
             InvalidTag(val) => write!(f, "enum value has invalid tag: {}", val),
             InvalidFunctionPointer(p) => {
-                write!(f, "using {} as function pointer but it does not point to a function", p)
+                write!(f, "using {:?} as function pointer but it does not point to a function", p)
             }
             InvalidStr(err) => write!(f, "this string is not valid UTF-8: {}", err),
             InvalidUninitBytes(Some((alloc, access))) => write!(
                 f,
-                "reading {} byte{} of memory starting at {}, \
-                 but {} byte{} {} uninitialized starting at {}, \
+                "reading {} byte{} of memory starting at {:?}, \
+                 but {} byte{} {} uninitialized starting at {:?}, \
                  and this operation requires initialized memory",
                 access.access_size.bytes(),
                 pluralize!(access.access_size.bytes()),
@@ -376,8 +409,6 @@ pub enum UnsupportedOpInfo {
     //
     // The variants below are only reachable from CTFE/const prop, miri will never emit them.
     //
-    /// Encountered raw bytes where we needed a pointer.
-    ReadBytesAsPointer,
     /// Accessing thread local statics
     ThreadLocalStatic(DefId),
     /// Accessing an unsupported extern static.
@@ -392,7 +423,6 @@ impl fmt::Display for UnsupportedOpInfo {
             ReadExternStatic(did) => write!(f, "cannot read from extern static ({:?})", did),
             NoMirFor(did) => write!(f, "no MIR body is available for {:?}", did),
             ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes",),
-            ReadBytesAsPointer => write!(f, "unable to turn bytes into a pointer"),
             ThreadLocalStatic(did) => write!(f, "cannot access thread local static ({:?})", did),
         }
     }
@@ -407,6 +437,8 @@ pub enum ResourceExhaustionInfo {
     ///
     /// The exact limit is set by the `const_eval_limit` attribute.
     StepLimitReached,
+    /// There is not enough memory to perform an allocation.
+    MemoryExhausted,
 }
 
 impl fmt::Display for ResourceExhaustionInfo {
@@ -419,6 +451,9 @@ impl fmt::Display for ResourceExhaustionInfo {
             StepLimitReached => {
                 write!(f, "exceeded interpreter step limit (see `#[const_eval_limit]`)")
             }
+            MemoryExhausted => {
+                write!(f, "tried to allocate more memory than available to compiler")
+            }
         }
     }
 }
@@ -491,15 +526,27 @@ impl fmt::Debug for InterpError<'_> {
 }
 
 impl InterpError<'_> {
-    /// Some errors to string formatting even if the error is never printed.
+    /// Some errors do string formatting even if the error is never printed.
     /// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors,
     /// so this method lets us detect them and `bug!` on unexpected errors.
     pub fn formatted_string(&self) -> bool {
         match self {
             InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
-            | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_))
+            | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. })
             | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) => true,
             _ => false,
         }
     }
+
+    /// Should this error be reported as a hard error, preventing compilation, or a soft error,
+    /// causing a deny-by-default lint?
+    pub fn is_hard_err(&self) -> bool {
+        use InterpError::*;
+        match *self {
+            MachineStop(ref err) => err.is_hard_err(),
+            UndefinedBehavior(_) => true,
+            ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted) => true,
+            _ => false,
+        }
+    }
 }
index 14bdb0a5a2d506b03e1c0f91cbac59030f3e879a..dd9ac7f5c3955321c5ed8e9d7cf727a47dbd39a2 100644 (file)
@@ -99,7 +99,7 @@ use std::convert::TryFrom;
 use std::fmt;
 use std::io;
 use std::io::{Read, Write};
-use std::num::NonZeroU32;
+use std::num::{NonZeroU32, NonZeroU64};
 use std::sync::atomic::{AtomicU32, Ordering};
 
 use rustc_ast::LitKind;
@@ -127,7 +127,7 @@ pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar, ScalarMay
 
 pub use self::allocation::{alloc_range, AllocRange, Allocation, InitMask, Relocations};
 
-pub use self::pointer::{Pointer, PointerArithmetic};
+pub use self::pointer::{Pointer, PointerArithmetic, Provenance};
 
 /// Uniquely identifies one of the following:
 /// - A constant
@@ -172,12 +172,11 @@ pub enum LitToConstError {
     /// This is used for graceful error handling (`delay_span_bug`) in
     /// type checking (`Const::from_anon_const`).
     TypeError,
-    UnparseableFloat,
     Reported,
 }
 
 #[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
-pub struct AllocId(pub u64);
+pub struct AllocId(pub NonZeroU64);
 
 // We want the `Debug` output to be readable as it is used by `derive(Debug)` for
 // all the Miri types.
@@ -428,7 +427,11 @@ crate struct AllocMap<'tcx> {
 
 impl<'tcx> AllocMap<'tcx> {
     crate fn new() -> Self {
-        AllocMap { alloc_map: Default::default(), dedup: Default::default(), next_id: AllocId(0) }
+        AllocMap {
+            alloc_map: Default::default(),
+            dedup: Default::default(),
+            next_id: AllocId(NonZeroU64::new(1).unwrap()),
+        }
     }
     fn reserve(&mut self) -> AllocId {
         let next = self.next_id;
index 8774b48fb3e403665dae7b75ce9d3b96d2ff6d55..568b3f252bf5f450efa6c5ea34d4879ed5ef17e5 100644 (file)
@@ -36,6 +36,20 @@ pub trait PointerArithmetic: HasDataLayout {
         i64::try_from(max_isize_plus_1 - 1).unwrap()
     }
 
+    #[inline]
+    fn machine_usize_to_isize(&self, val: u64) -> i64 {
+        let val = val as i64;
+        // Now clamp into the machine_isize range.
+        if val > self.machine_isize_max() {
+            // This can only happen the the ptr size is < 64, so we know max_usize_plus_1 fits into
+            // i64.
+            let max_usize_plus_1 = 1u128 << self.pointer_size().bits();
+            val - i64::try_from(max_usize_plus_1).unwrap()
+        } else {
+            val
+        }
+    }
+
     /// Helper function: truncate given value-"overflowed flag" pair to pointer size and
     /// update "overflowed flag" if there was an overflow.
     /// This should be called by all the other methods before returning!
@@ -83,55 +97,77 @@ pub trait PointerArithmetic: HasDataLayout {
 
 impl<T: HasDataLayout> PointerArithmetic for T {}
 
+/// This trait abstracts over the kind of provenance that is associated with a `Pointer`. It is
+/// mostly opaque; the `Machine` trait extends it with some more operations that also have access to
+/// some global state.
+/// We don't actually care about this `Debug` bound (we use `Provenance::fmt` to format the entire
+/// pointer), but `derive` adds some unecessary bounds.
+pub trait Provenance: Copy + fmt::Debug {
+    /// Says whether the `offset` field of `Pointer`s with this provenance is the actual physical address.
+    /// If `true, ptr-to-int casts work by simply discarding the provenance.
+    /// If `false`, ptr-to-int casts are not supported. The offset *must* be relative in that case.
+    const OFFSET_IS_ADDR: bool;
+
+    /// Determines how a pointer should be printed.
+    fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result
+    where
+        Self: Sized;
+
+    /// Provenance must always be able to identify the allocation this ptr points to.
+    /// (Identifying the offset in that allocation, however, is harder -- use `Memory::ptr_get_alloc` for that.)
+    fn get_alloc_id(self) -> AllocId;
+}
+
+impl Provenance for AllocId {
+    // With the `AllocId` as provenance, the `offset` is interpreted *relative to the allocation*,
+    // so ptr-to-int casts are not possible (since we do not know the global physical offset).
+    const OFFSET_IS_ADDR: bool = false;
+
+    fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // Forward `alternate` flag to `alloc_id` printing.
+        if f.alternate() {
+            write!(f, "{:#?}", ptr.provenance)?;
+        } else {
+            write!(f, "{:?}", ptr.provenance)?;
+        }
+        // Print offset only if it is non-zero.
+        if ptr.offset.bytes() > 0 {
+            write!(f, "+0x{:x}", ptr.offset.bytes())?;
+        }
+        Ok(())
+    }
+
+    fn get_alloc_id(self) -> AllocId {
+        self
+    }
+}
+
 /// Represents a pointer in the Miri engine.
 ///
-/// `Pointer` is generic over the `Tag` associated with each pointer,
-/// which is used to do provenance tracking during execution.
+/// Pointers are "tagged" with provenance information; typically the `AllocId` they belong to.
 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, TyEncodable, TyDecodable, Hash)]
 #[derive(HashStable)]
-pub struct Pointer<Tag = ()> {
-    pub alloc_id: AllocId,
-    pub offset: Size,
-    pub tag: Tag,
+pub struct Pointer<Tag = AllocId> {
+    pub(super) offset: Size, // kept private to avoid accidental misinterpretation (meaning depends on `Tag` type)
+    pub provenance: Tag,
 }
 
 static_assert_size!(Pointer, 16);
 
-/// Print the address of a pointer (without the tag)
-fn print_ptr_addr<Tag>(ptr: &Pointer<Tag>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    // Forward `alternate` flag to `alloc_id` printing.
-    if f.alternate() {
-        write!(f, "{:#?}", ptr.alloc_id)?;
-    } else {
-        write!(f, "{:?}", ptr.alloc_id)?;
-    }
-    // Print offset only if it is non-zero.
-    if ptr.offset.bytes() > 0 {
-        write!(f, "+0x{:x}", ptr.offset.bytes())?;
-    }
-    Ok(())
-}
-
 // We want the `Debug` output to be readable as it is used by `derive(Debug)` for
 // all the Miri types.
-// We have to use `Debug` output for the tag, because `()` does not implement
-// `Display` so we cannot specialize that.
-impl<Tag: fmt::Debug> fmt::Debug for Pointer<Tag> {
-    default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        print_ptr_addr(self, f)?;
-        write!(f, "[{:?}]", self.tag)
-    }
-}
-// Specialization for no tag
-impl fmt::Debug for Pointer<()> {
+impl<Tag: Provenance> fmt::Debug for Pointer<Tag> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        print_ptr_addr(self, f)
+        Provenance::fmt(self, f)
     }
 }
 
-impl<Tag: fmt::Debug> fmt::Display for Pointer<Tag> {
+impl<Tag: Provenance> fmt::Debug for Pointer<Option<Tag>> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(self, f)
+        match self.provenance {
+            Some(tag) => Provenance::fmt(&Pointer::new(tag, self.offset), f),
+            None => write!(f, "0x{:x}", self.offset.bytes()),
+        }
     }
 }
 
@@ -143,37 +179,61 @@ impl From<AllocId> for Pointer {
     }
 }
 
-impl Pointer<()> {
+impl<Tag> From<Pointer<Tag>> for Pointer<Option<Tag>> {
     #[inline(always)]
-    pub fn new(alloc_id: AllocId, offset: Size) -> Self {
-        Pointer { alloc_id, offset, tag: () }
+    fn from(ptr: Pointer<Tag>) -> Self {
+        let (tag, offset) = ptr.into_parts();
+        Pointer::new(Some(tag), offset)
     }
+}
 
+impl<Tag> Pointer<Option<Tag>> {
+    pub fn into_pointer_or_addr(self) -> Result<Pointer<Tag>, Size> {
+        match self.provenance {
+            Some(tag) => Ok(Pointer::new(tag, self.offset)),
+            None => Err(self.offset),
+        }
+    }
+}
+
+impl<Tag> Pointer<Option<Tag>> {
     #[inline(always)]
-    pub fn with_tag<Tag>(self, tag: Tag) -> Pointer<Tag> {
-        Pointer::new_with_tag(self.alloc_id, self.offset, tag)
+    pub fn null() -> Self {
+        Pointer { provenance: None, offset: Size::ZERO }
     }
 }
 
 impl<'tcx, Tag> Pointer<Tag> {
     #[inline(always)]
-    pub fn new_with_tag(alloc_id: AllocId, offset: Size, tag: Tag) -> Self {
-        Pointer { alloc_id, offset, tag }
+    pub fn new(provenance: Tag, offset: Size) -> Self {
+        Pointer { provenance, offset }
+    }
+
+    /// Obtain the constituents of this pointer. Not that the meaning of the offset depends on the type `Tag`!
+    /// This function must only be used in the implementation of `Machine::ptr_get_alloc`,
+    /// and when a `Pointer` is taken apart to be stored efficiently in an `Allocation`.
+    #[inline(always)]
+    pub fn into_parts(self) -> (Tag, Size) {
+        (self.provenance, self.offset)
+    }
+
+    pub fn map_provenance(self, f: impl FnOnce(Tag) -> Tag) -> Self {
+        Pointer { provenance: f(self.provenance), ..self }
     }
 
     #[inline]
     pub fn offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> {
-        Ok(Pointer::new_with_tag(
-            self.alloc_id,
-            Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?),
-            self.tag,
-        ))
+        Ok(Pointer {
+            offset: Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?),
+            ..self
+        })
     }
 
     #[inline]
     pub fn overflowing_offset(self, i: Size, cx: &impl HasDataLayout) -> (Self, bool) {
         let (res, over) = cx.data_layout().overflowing_offset(self.offset.bytes(), i.bytes());
-        (Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
+        let ptr = Pointer { offset: Size::from_bytes(res), ..self };
+        (ptr, over)
     }
 
     #[inline(always)]
@@ -183,26 +243,21 @@ impl<'tcx, Tag> Pointer<Tag> {
 
     #[inline]
     pub fn signed_offset(self, i: i64, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> {
-        Ok(Pointer::new_with_tag(
-            self.alloc_id,
-            Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?),
-            self.tag,
-        ))
+        Ok(Pointer {
+            offset: Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?),
+            ..self
+        })
     }
 
     #[inline]
     pub fn overflowing_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> (Self, bool) {
         let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i);
-        (Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
+        let ptr = Pointer { offset: Size::from_bytes(res), ..self };
+        (ptr, over)
     }
 
     #[inline(always)]
     pub fn wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self {
         self.overflowing_signed_offset(i, cx).0
     }
-
-    #[inline(always)]
-    pub fn erase_tag(self) -> Pointer {
-        Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () }
-    }
 }
index 66ff6990e8cdbed6ccd0dc9d61185db968b8c1f9..62b71b10d5a1b98c7a0b94b100d46829dfac1fc7 100644 (file)
@@ -6,11 +6,13 @@ use rustc_apfloat::{
     Float,
 };
 use rustc_macros::HashStable;
-use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};
+use rustc_target::abi::{HasDataLayout, Size};
 
 use crate::ty::{Lift, ParamEnv, ScalarInt, Ty, TyCtxt};
 
-use super::{AllocId, AllocRange, Allocation, InterpResult, Pointer, PointerArithmetic};
+use super::{
+    AllocId, AllocRange, Allocation, InterpResult, Pointer, PointerArithmetic, Provenance,
+};
 
 /// Represents the result of const evaluation via the `eval_to_allocation` query.
 #[derive(Copy, Clone, HashStable, TyEncodable, TyDecodable, Debug, Hash, Eq, PartialEq)]
@@ -47,12 +49,6 @@ pub enum ConstValue<'tcx> {
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(ConstValue<'_>, 32);
 
-impl From<Scalar> for ConstValue<'tcx> {
-    fn from(s: Scalar) -> Self {
-        Self::Scalar(s)
-    }
-}
-
 impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> {
     type Lifted = ConstValue<'tcx>;
     fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ConstValue<'tcx>> {
@@ -70,7 +66,7 @@ impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> {
 
 impl<'tcx> ConstValue<'tcx> {
     #[inline]
-    pub fn try_to_scalar(&self) -> Option<Scalar> {
+    pub fn try_to_scalar(&self) -> Option<Scalar<AllocId>> {
         match *self {
             ConstValue::ByRef { .. } | ConstValue::Slice { .. } => None,
             ConstValue::Scalar(val) => Some(val),
@@ -120,16 +116,23 @@ impl<'tcx> ConstValue<'tcx> {
 /// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 16 bytes in
 /// size. Like a range of bytes in an `Allocation`, a `Scalar` can either represent the raw bytes
 /// of a simple value or a pointer into another `Allocation`
+///
+/// These variants would be private if there was a convenient way to achieve that in Rust.
+/// Do *not* match on a `Scalar`! Use the various `to_*` methods instead.
 #[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, TyEncodable, TyDecodable, Hash)]
 #[derive(HashStable)]
-pub enum Scalar<Tag = ()> {
+pub enum Scalar<Tag = AllocId> {
     /// The raw bytes of a simple value.
     Int(ScalarInt),
 
     /// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
     /// relocations, but a `Scalar` is only large enough to contain one, so we just represent the
     /// relocation and its associated offset together as a `Pointer` here.
-    Ptr(Pointer<Tag>),
+    ///
+    /// We also store the size of the pointer, such that a `Scalar` always knows how big it is.
+    /// The size is always the pointer size of the current target, but this is not information
+    /// that we always have readily available.
+    Ptr(Pointer<Tag>, u8),
 }
 
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
@@ -137,20 +140,20 @@ static_assert_size!(Scalar, 24);
 
 // We want the `Debug` output to be readable as it is used by `derive(Debug)` for
 // all the Miri types.
-impl<Tag: fmt::Debug> fmt::Debug for Scalar<Tag> {
+impl<Tag: Provenance> fmt::Debug for Scalar<Tag> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            Scalar::Ptr(ptr) => write!(f, "{:?}", ptr),
+            Scalar::Ptr(ptr, _size) => write!(f, "{:?}", ptr),
             Scalar::Int(int) => write!(f, "{:?}", int),
         }
     }
 }
 
-impl<Tag: fmt::Debug> fmt::Display for Scalar<Tag> {
+impl<Tag: Provenance> fmt::Display for Scalar<Tag> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            Scalar::Ptr(ptr) => write!(f, "pointer to {}", ptr),
-            Scalar::Int { .. } => fmt::Debug::fmt(self, f),
+            Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr),
+            Scalar::Int(int) => write!(f, "{:?}", int),
         }
     }
 }
@@ -169,83 +172,34 @@ impl<Tag> From<Double> for Scalar<Tag> {
     }
 }
 
-impl Scalar<()> {
-    /// Tag this scalar with `new_tag` if it is a pointer, leave it unchanged otherwise.
-    ///
-    /// Used by `MemPlace::replace_tag`.
-    #[inline]
-    pub fn with_tag<Tag>(self, new_tag: Tag) -> Scalar<Tag> {
-        match self {
-            Scalar::Ptr(ptr) => Scalar::Ptr(ptr.with_tag(new_tag)),
-            Scalar::Int(int) => Scalar::Int(int),
-        }
+impl<Tag> From<ScalarInt> for Scalar<Tag> {
+    #[inline(always)]
+    fn from(ptr: ScalarInt) -> Self {
+        Scalar::Int(ptr)
     }
 }
 
-impl<'tcx, Tag> Scalar<Tag> {
+impl<Tag> Scalar<Tag> {
     pub const ZST: Self = Scalar::Int(ScalarInt::ZST);
 
-    /// Erase the tag from the scalar, if any.
-    ///
-    /// Used by error reporting code to avoid having the error type depend on `Tag`.
-    #[inline]
-    pub fn erase_tag(self) -> Scalar {
-        match self {
-            Scalar::Ptr(ptr) => Scalar::Ptr(ptr.erase_tag()),
-            Scalar::Int(int) => Scalar::Int(int),
-        }
-    }
-
-    #[inline]
-    pub fn null_ptr(cx: &impl HasDataLayout) -> Self {
-        Scalar::Int(ScalarInt::null(cx.data_layout().pointer_size))
-    }
-
     #[inline(always)]
-    fn ptr_op(
-        self,
-        dl: &TargetDataLayout,
-        f_int: impl FnOnce(u64) -> InterpResult<'tcx, u64>,
-        f_ptr: impl FnOnce(Pointer<Tag>) -> InterpResult<'tcx, Pointer<Tag>>,
-    ) -> InterpResult<'tcx, Self> {
-        match self {
-            Scalar::Int(int) => Ok(Scalar::Int(int.ptr_sized_op(dl, f_int)?)),
-            Scalar::Ptr(ptr) => Ok(Scalar::Ptr(f_ptr(ptr)?)),
-        }
-    }
-
-    #[inline]
-    pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> {
-        let dl = cx.data_layout();
-        self.ptr_op(dl, |int| dl.offset(int, i.bytes()), |ptr| ptr.offset(i, dl))
+    pub fn from_pointer(ptr: Pointer<Tag>, cx: &impl HasDataLayout) -> Self {
+        Scalar::Ptr(ptr, u8::try_from(cx.pointer_size().bytes()).unwrap())
     }
 
-    #[inline]
-    pub fn ptr_wrapping_offset(self, i: Size, cx: &impl HasDataLayout) -> Self {
-        let dl = cx.data_layout();
-        self.ptr_op(
-            dl,
-            |int| Ok(dl.overflowing_offset(int, i.bytes()).0),
-            |ptr| Ok(ptr.wrapping_offset(i, dl)),
-        )
-        .unwrap()
-    }
-
-    #[inline]
-    pub fn ptr_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> {
-        let dl = cx.data_layout();
-        self.ptr_op(dl, |int| dl.signed_offset(int, i), |ptr| ptr.signed_offset(i, dl))
+    /// Create a Scalar from a pointer with an `Option<_>` tag (where `None` represents a plain integer).
+    pub fn from_maybe_pointer(ptr: Pointer<Option<Tag>>, cx: &impl HasDataLayout) -> Self {
+        match ptr.into_parts() {
+            (Some(tag), offset) => Scalar::from_pointer(Pointer::new(tag, offset), cx),
+            (None, offset) => {
+                Scalar::Int(ScalarInt::try_from_uint(offset.bytes(), cx.pointer_size()).unwrap())
+            }
+        }
     }
 
     #[inline]
-    pub fn ptr_wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self {
-        let dl = cx.data_layout();
-        self.ptr_op(
-            dl,
-            |int| Ok(dl.overflowing_signed_offset(int, i).0),
-            |ptr| Ok(ptr.wrapping_signed_offset(i, dl)),
-        )
-        .unwrap()
+    pub fn null_ptr(cx: &impl HasDataLayout) -> Self {
+        Scalar::Int(ScalarInt::null(cx.pointer_size()))
     }
 
     #[inline]
@@ -332,74 +286,71 @@ impl<'tcx, Tag> Scalar<Tag> {
         Scalar::Int(f.into())
     }
 
-    /// This is very rarely the method you want!  You should dispatch on the type
-    /// and use `force_bits`/`assert_bits`/`force_ptr`/`assert_ptr`.
-    /// This method only exists for the benefit of low-level memory operations
-    /// as well as the implementation of the `force_*` methods.
+    /// This is almost certainly not the method you want!  You should dispatch on the type
+    /// and use `to_{u8,u16,...}`/`scalar_to_ptr` to perform ptr-to-int / int-to-ptr casts as needed.
+    ///
+    /// This method only exists for the benefit of low-level operations that truly need to treat the
+    /// scalar in whatever form it is.
     #[inline]
-    pub fn to_bits_or_ptr(
-        self,
-        target_size: Size,
-        cx: &impl HasDataLayout,
-    ) -> Result<u128, Pointer<Tag>> {
+    pub fn to_bits_or_ptr_internal(self, target_size: Size) -> Result<u128, Pointer<Tag>> {
         assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
         match self {
             Scalar::Int(int) => Ok(int.assert_bits(target_size)),
-            Scalar::Ptr(ptr) => {
-                assert_eq!(target_size, cx.data_layout().pointer_size);
+            Scalar::Ptr(ptr, sz) => {
+                assert_eq!(target_size.bytes(), u64::from(sz));
                 Err(ptr)
             }
         }
     }
+}
 
-    /// This method is intentionally private!
-    /// It is just a helper for other methods in this file.
+impl<'tcx, Tag: Provenance> Scalar<Tag> {
+    /// Fundamental scalar-to-int (cast) operation. Many convenience wrappers exist below, that you
+    /// likely want to use instead.
+    ///
+    /// Will perform ptr-to-int casts if needed and possible.
+    /// If that fails, we know the offset is relative, so we return an "erased" Scalar
+    /// (which is useful for error messages but not much else).
     #[inline]
-    fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
-        assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
+    pub fn try_to_int(self) -> Result<ScalarInt, Scalar<AllocId>> {
         match self {
-            Scalar::Int(int) => int.to_bits(target_size).map_err(|size| {
-                err_ub!(ScalarSizeMismatch {
-                    target_size: target_size.bytes(),
-                    data_size: size.bytes(),
-                })
-                .into()
-            }),
-            Scalar::Ptr(_) => throw_unsup!(ReadPointerAsBytes),
+            Scalar::Int(int) => Ok(int),
+            Scalar::Ptr(ptr, sz) => {
+                if Tag::OFFSET_IS_ADDR {
+                    Ok(ScalarInt::try_from_uint(ptr.offset.bytes(), Size::from_bytes(sz)).unwrap())
+                } else {
+                    // We know `offset` is relative, since `OFFSET_IS_ADDR == false`.
+                    let (tag, offset) = ptr.into_parts();
+                    Err(Scalar::Ptr(Pointer::new(tag.get_alloc_id(), offset), sz))
+                }
+            }
         }
     }
 
     #[inline(always)]
-    pub fn assert_bits(self, target_size: Size) -> u128 {
-        self.to_bits(target_size).expect("expected Raw bits but got a Pointer")
-    }
-
-    #[inline]
     pub fn assert_int(self) -> ScalarInt {
-        match self {
-            Scalar::Ptr(_) => bug!("expected an int but got an abstract pointer"),
-            Scalar::Int(int) => int,
-        }
+        self.try_to_int().unwrap()
     }
 
+    /// This throws UB (instead of ICEing) on a size mismatch since size mismatches can arise in
+    /// Miri when someone declares a function that we shim (such as `malloc`) with a wrong type.
     #[inline]
-    pub fn assert_ptr(self) -> Pointer<Tag> {
-        match self {
-            Scalar::Ptr(p) => p,
-            Scalar::Int { .. } => bug!("expected a Pointer but got Raw bits"),
-        }
-    }
-
-    /// Do not call this method!  Dispatch based on the type instead.
-    #[inline]
-    pub fn is_bits(self) -> bool {
-        matches!(self, Scalar::Int { .. })
+    pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
+        assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
+        self.try_to_int().map_err(|_| err_unsup!(ReadPointerAsBytes))?.to_bits(target_size).map_err(
+            |size| {
+                err_ub!(ScalarSizeMismatch {
+                    target_size: target_size.bytes(),
+                    data_size: size.bytes(),
+                })
+                .into()
+            },
+        )
     }
 
-    /// Do not call this method!  Dispatch based on the type instead.
-    #[inline]
-    pub fn is_ptr(self) -> bool {
-        matches!(self, Scalar::Ptr(_))
+    #[inline(always)]
+    pub fn assert_bits(self, target_size: Size) -> u128 {
+        self.to_bits(target_size).unwrap()
     }
 
     pub fn to_bool(self) -> InterpResult<'tcx, bool> {
@@ -507,22 +458,8 @@ impl<'tcx, Tag> Scalar<Tag> {
     }
 }
 
-impl<Tag> From<Pointer<Tag>> for Scalar<Tag> {
-    #[inline(always)]
-    fn from(ptr: Pointer<Tag>) -> Self {
-        Scalar::Ptr(ptr)
-    }
-}
-
-impl<Tag> From<ScalarInt> for Scalar<Tag> {
-    #[inline(always)]
-    fn from(ptr: ScalarInt) -> Self {
-        Scalar::Int(ptr)
-    }
-}
-
 #[derive(Clone, Copy, Eq, PartialEq, TyEncodable, TyDecodable, HashStable, Hash)]
-pub enum ScalarMaybeUninit<Tag = ()> {
+pub enum ScalarMaybeUninit<Tag = AllocId> {
     Scalar(Scalar<Tag>),
     Uninit,
 }
@@ -537,16 +474,9 @@ impl<Tag> From<Scalar<Tag>> for ScalarMaybeUninit<Tag> {
     }
 }
 
-impl<Tag> From<Pointer<Tag>> for ScalarMaybeUninit<Tag> {
-    #[inline(always)]
-    fn from(s: Pointer<Tag>) -> Self {
-        ScalarMaybeUninit::Scalar(s.into())
-    }
-}
-
 // We want the `Debug` output to be readable as it is used by `derive(Debug)` for
 // all the Miri types.
-impl<Tag: fmt::Debug> fmt::Debug for ScalarMaybeUninit<Tag> {
+impl<Tag: Provenance> fmt::Debug for ScalarMaybeUninit<Tag> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             ScalarMaybeUninit::Uninit => write!(f, "<uninitialized>"),
@@ -555,7 +485,7 @@ impl<Tag: fmt::Debug> fmt::Debug for ScalarMaybeUninit<Tag> {
     }
 }
 
-impl<Tag: fmt::Debug> fmt::Display for ScalarMaybeUninit<Tag> {
+impl<Tag: Provenance> fmt::Display for ScalarMaybeUninit<Tag> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             ScalarMaybeUninit::Uninit => write!(f, "uninitialized bytes"),
@@ -564,16 +494,15 @@ impl<Tag: fmt::Debug> fmt::Display for ScalarMaybeUninit<Tag> {
     }
 }
 
-impl<'tcx, Tag> ScalarMaybeUninit<Tag> {
-    /// Erase the tag from the scalar, if any.
-    ///
-    /// Used by error reporting code to avoid having the error type depend on `Tag`.
+impl<Tag> ScalarMaybeUninit<Tag> {
     #[inline]
-    pub fn erase_tag(self) -> ScalarMaybeUninit {
-        match self {
-            ScalarMaybeUninit::Scalar(s) => ScalarMaybeUninit::Scalar(s.erase_tag()),
-            ScalarMaybeUninit::Uninit => ScalarMaybeUninit::Uninit,
-        }
+    pub fn from_pointer(ptr: Pointer<Tag>, cx: &impl HasDataLayout) -> Self {
+        ScalarMaybeUninit::Scalar(Scalar::from_pointer(ptr, cx))
+    }
+
+    #[inline]
+    pub fn from_maybe_pointer(ptr: Pointer<Option<Tag>>, cx: &impl HasDataLayout) -> Self {
+        ScalarMaybeUninit::Scalar(Scalar::from_maybe_pointer(ptr, cx))
     }
 
     #[inline]
@@ -583,7 +512,9 @@ impl<'tcx, Tag> ScalarMaybeUninit<Tag> {
             ScalarMaybeUninit::Uninit => throw_ub!(InvalidUninitBytes(None)),
         }
     }
+}
 
+impl<'tcx, Tag: Provenance> ScalarMaybeUninit<Tag> {
     #[inline(always)]
     pub fn to_bool(self) -> InterpResult<'tcx, bool> {
         self.check_init()?.to_bool()
index 7ae7eab6e5a315cda438adbea5f2007cc623b4b6..da0d2575dcbe3377663318d64b83766be84b48fe 100644 (file)
@@ -3,7 +3,7 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
 
 use crate::mir::coverage::{CodeRegion, CoverageKind};
-use crate::mir::interpret::{Allocation, GlobalAlloc, Scalar};
+use crate::mir::interpret::{Allocation, ConstValue, GlobalAlloc, Scalar};
 use crate::mir::visit::MirVisitable;
 use crate::ty::adjustment::PointerCast;
 use crate::ty::codec::{TyDecoder, TyEncoder};
@@ -494,7 +494,7 @@ impl<'tcx> Body<'tcx> {
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum Safety {
     Safe,
-    /// Unsafe because of a PushUnsafeBlock
+    /// Unsafe because of compiler-generated unsafe code, like `await` desugaring
     BuiltinUnsafe,
     /// Unsafe because of an unsafe fn
     FnUnsafe,
@@ -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; }
@@ -2095,7 +2095,7 @@ impl<'tcx> Operand<'tcx> {
         Operand::Constant(box Constant {
             span,
             user_ty: None,
-            literal: ConstantKind::Val(val.into(), ty),
+            literal: ConstantKind::Val(ConstValue::Scalar(val), ty),
         })
     }
 
@@ -2458,7 +2458,7 @@ pub enum ConstantKind<'tcx> {
 impl Constant<'tcx> {
     pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
         match self.literal.const_for_ty()?.val.try_to_scalar() {
-            Some(Scalar::Ptr(ptr)) => match tcx.global_alloc(ptr.alloc_id) {
+            Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) {
                 GlobalAlloc::Static(def_id) => {
                     assert!(!tcx.is_thread_local_static(def_id));
                     Some(def_id)
index 74650f50a1c8aa6385cc7d82fa6cba005be6ff23..776cf002c170311a3be270f90f7f53d2a3e78208 100644 (file)
@@ -490,15 +490,23 @@ impl CodegenUnitNameBuilder<'tcx> {
             // 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 0860520ef9dfe8aa1dca8fab66ba9198489a9b95..0908b6a1763d50c32129019ce2e63435908dadd5 100644 (file)
@@ -14,6 +14,12 @@ rustc_queries! {
         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.
@@ -191,10 +197,6 @@ rustc_queries! {
         desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
     }
 
-    query projection_ty_from_predicates(key: (DefId, DefId)) -> Option<ty::ProjectionTy<'tcx>> {
-        desc { |tcx| "finding projection type inside predicates of `{}`", tcx.def_path_str(key.0) }
-    }
-
     query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLib>> {
         desc { "looking up the native libraries of a linked crate" }
     }
@@ -211,6 +213,7 @@ rustc_queries! {
     }
 
     query expn_that_defined(key: DefId) -> rustc_span::ExpnId {
+        // This query reads from untracked data in definitions.
         eval_always
         desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) }
     }
@@ -721,7 +724,7 @@ rustc_queries! {
         cache_on_disk_if { true }
         load_cached(tcx, id) {
             let typeck_results: Option<ty::TypeckResults<'tcx>> = tcx
-                .on_disk_cache.as_ref()
+                .on_disk_cache().as_ref()
                 .and_then(|c| c.try_load_query_result(*tcx, id));
 
             typeck_results.map(|x| &*tcx.arena.alloc(x))
@@ -920,6 +923,10 @@ rustc_queries! {
         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) }
     }
@@ -959,9 +966,9 @@ rustc_queries! {
         desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) }
     }
 
-    query vtable_methods(key: ty::PolyTraitRef<'tcx>)
-                        -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] {
-        desc { |tcx| "finding all methods for trait {}", tcx.def_path_str(key.def_id()) }
+    query vtable_entries(key: ty::PolyTraitRef<'tcx>)
+                        -> &'tcx [ty::VtblEntry<'tcx>] {
+        desc { |tcx| "finding all vtable entries for trait {}", tcx.def_path_str(key.def_id()) }
     }
 
     query codegen_fulfill_obligation(
@@ -1133,13 +1140,16 @@ rustc_queries! {
 
     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 {
         desc { |tcx| "looking up whether `{}` is a default impl", tcx.def_path_str(def_id) }
     }
 
+    query impl_constness(def_id: DefId) -> hir::Constness {
+        desc { |tcx| "looking up whether `{}` is a const impl", tcx.def_path_str(def_id) }
+    }
+
     query check_item_well_formed(key: LocalDefId) -> () {
         desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) }
     }
@@ -1237,10 +1247,6 @@ rustc_queries! {
     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 {
@@ -1327,7 +1333,6 @@ rustc_queries! {
     }
 
     query visibility(def_id: DefId) -> ty::Visibility {
-        eval_always
         desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
     }
 
@@ -1352,8 +1357,6 @@ rustc_queries! {
         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()) }
     }
 
@@ -1420,22 +1423,22 @@ rustc_queries! {
         eval_always
         desc { "check whether crate {} is a private dependency", c }
     }
+    query allocator_kind(_: ()) -> Option<AllocatorKind> {
+        eval_always
+        desc { "allocator kind for the current crate" }
+    }
 
     query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>> {
         desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(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()) }
     }
 
@@ -1444,7 +1447,7 @@ rustc_queries! {
         eval_always
         desc { "calculating the stability index for the local crate" }
     }
-    query all_crate_nums(_: ()) -> &'tcx [CrateNum] {
+    query crates(_: ()) -> &'tcx [CrateNum] {
         eval_always
         desc { "fetching all foreign CrateNum instances" }
     }
@@ -1559,12 +1562,6 @@ rustc_queries! {
         desc { "evaluating trait selection obligation `{}`", goal.value }
     }
 
-    query type_implements_trait(
-        key: (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>, )
-    ) -> bool {
-        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>
@@ -1712,4 +1709,22 @@ rustc_queries! {
     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" }
+    }
+
+    /// Performs an HIR-based well-formed check on the item with the given `HirId`. If
+    /// we get an `Umimplemented` error that matches the provided `Predicate`, return
+    /// the cause of the newly created obligation.
+    ///
+    /// This is only used by error-reporting code to get a better cause (in particular, a better
+    /// span) for an *existing* error. Therefore, it is best-effort, and may never handle
+    /// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine,
+    /// because the `ty::Ty`-based wfcheck is always run.
+    query diagnostic_hir_wf_check(key: (ty::Predicate<'tcx>, traits::WellFormedLoc)) -> Option<traits::ObligationCause<'tcx>> {
+        eval_always
+        no_hash
+        desc { "performing HIR wf-checking for predicate {:?} at item {:?}", key.0, key.1 }
+    }
 }
index a5069113702c24db931404c2832688c587fd7a75..cdefc9effa1e9ac0ce840991ec1687486de2b35e 100644 (file)
@@ -1,3 +1,13 @@
+//! THIR datatypes and definitions. See the [rustc dev guide] for more info.
+//!
+//! If you compare the THIR [`ExprKind`] to [`hir::ExprKind`], you will see it is
+//! a good bit simpler. In fact, a number of the more straight-forward
+//! MIR simplifications are already done in the lowering to THIR. For
+//! example, method calls and overloaded operators are absent: they are
+//! expected to be converted into [`ExprKind::Call`] instances.
+//!
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html
+
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
@@ -24,6 +34,7 @@ use std::fmt;
 use std::ops::Index;
 
 newtype_index! {
+    /// An index to an [`Arm`] stored in [`Thir::arms`]
     #[derive(HashStable)]
     pub struct ArmId {
         DEBUG_FORMAT = "a{}"
@@ -31,6 +42,7 @@ newtype_index! {
 }
 
 newtype_index! {
+    /// An index to an [`Expr`] stored in [`Thir::exprs`]
     #[derive(HashStable)]
     pub struct ExprId {
         DEBUG_FORMAT = "e{}"
@@ -39,6 +51,7 @@ newtype_index! {
 
 newtype_index! {
     #[derive(HashStable)]
+    /// An index to a [`Stmt`] stored in [`Thir::stmts`]
     pub struct StmtId {
         DEBUG_FORMAT = "s{}"
     }
@@ -46,6 +59,9 @@ newtype_index! {
 
 macro_rules! thir_with_elements {
     ($($name:ident: $id:ty => $value:ty,)*) => {
+        /// A container for a THIR body.
+        ///
+        /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
         #[derive(Debug, HashStable)]
         pub struct Thir<'tcx> {
             $(
@@ -88,21 +104,47 @@ pub enum LintLevel {
 
 #[derive(Debug, HashStable)]
 pub struct Block {
+    /// Whether the block itself has a label. Used by `label: {}`
+    /// and `try` blocks.
+    ///
+    /// This does *not* include labels on loops, e.g. `'label: loop {}`.
     pub targeted_by_break: bool,
     pub region_scope: region::Scope,
     pub opt_destruction_scope: Option<region::Scope>,
+    /// The span of the block, including the opening braces,
+    /// the label, and the `unsafe` keyword, if present.
     pub span: Span,
+    /// The statements in the blocK.
     pub stmts: Box<[StmtId]>,
+    /// The trailing expression of the block, if any.
     pub expr: Option<ExprId>,
     pub safety_mode: BlockSafety,
 }
 
+#[derive(Debug, HashStable)]
+pub struct Adt<'tcx> {
+    /// The ADT we're constructing.
+    pub adt_def: &'tcx AdtDef,
+    /// The variant of the ADT.
+    pub variant_index: VariantIdx,
+    pub substs: SubstsRef<'tcx>,
+
+    /// Optional user-given substs: for something like `let x =
+    /// Bar::<T> { ... }`.
+    pub user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
+
+    pub fields: Box<[FieldExpr]>,
+    /// The base, e.g. `Foo {x: 1, .. base}`.
+    pub base: Option<FruInfo<'tcx>>,
+}
+
 #[derive(Copy, Clone, Debug, HashStable)]
 pub enum BlockSafety {
     Safe,
+    /// A compiler-generated unsafe block
+    BuiltinUnsafe,
+    /// An `unsafe` block. The `HirId` is the ID of the block.
     ExplicitUnsafe(hir::HirId),
-    PushUnsafe,
-    PopUnsafe,
 }
 
 #[derive(Debug, HashStable)]
@@ -113,61 +155,50 @@ pub struct Stmt<'tcx> {
 
 #[derive(Debug, HashStable)]
 pub enum StmtKind<'tcx> {
+    /// An expression with a trailing semicolon.
     Expr {
-        /// scope for this statement; may be used as lifetime of temporaries
+        /// The scope for this statement; may be used as lifetime of temporaries.
         scope: region::Scope,
 
-        /// expression being evaluated in this statement
+        /// The expression being evaluated in this statement.
         expr: ExprId,
     },
 
+    /// A `let` binding.
     Let {
-        /// scope for variables bound in this let; covers this and
-        /// remaining statements in block
+        /// The scope for variables bound in this `let`; it covers this and
+        /// all the remaining statements in the block.
         remainder_scope: region::Scope,
 
-        /// scope for the initialization itself; might be used as
-        /// lifetime of temporaries
+        /// The scope for the initialization itself; might be used as
+        /// lifetime of temporaries.
         init_scope: region::Scope,
 
         /// `let <PAT> = ...`
         ///
-        /// if a type is included, it is added as an ascription pattern
+        /// If a type annotation is included, it is added as an ascription pattern.
         pattern: Pat<'tcx>,
 
-        /// let pat: ty = <INIT> ...
+        /// `let pat: ty = <INIT>`
         initializer: Option<ExprId>,
 
-        /// the lint level for this let-statement
+        /// The lint level for this `let` statement.
         lint_level: LintLevel,
     },
 }
 
 // `Expr` 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!(Expr<'_>, 144);
-
-/// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`)
-/// into instances of this `Expr` enum. This lowering can be done
-/// basically as lazily or as eagerly as desired: every recursive
-/// reference to an expression in this enum is an `ExprId`, which
-/// may in turn be another instance of this enum (boxed), or else an
-/// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
-/// short-lived. They are created by `Thir::to_expr`, analyzed and
-/// converted into MIR, and then discarded.
-///
-/// If you compare `Expr` to the full compiler AST, you will see it is
-/// a good bit simpler. In fact, a number of the more straight-forward
-/// MIR simplifications are already done in the impl of `Thir`. For
-/// example, method calls and overloaded operators are absent: they are
-/// expected to be converted into `Expr::Call` instances.
+rustc_data_structures::static_assert_size!(Expr<'_>, 104);
+
+/// A THIR expression.
 #[derive(Debug, HashStable)]
 pub struct Expr<'tcx> {
-    /// type of this expression
+    /// The type of this expression
     pub ty: Ty<'tcx>,
 
-    /// lifetime of this expression if it should be spilled into a
-    /// temporary; should be None only if in a constant context
+    /// The lifetime of this expression if it should be spilled into a
+    /// temporary; should be `None` only if in a constant context
     pub temp_lifetime: Option<region::Scope>,
 
     /// span of the expression in the source
@@ -179,88 +210,120 @@ pub struct Expr<'tcx> {
 
 #[derive(Debug, HashStable)]
 pub enum ExprKind<'tcx> {
+    /// `Scope`s are used to explicitely mark destruction scopes,
+    /// and to track the `HirId` of the expressions within the scope.
     Scope {
         region_scope: region::Scope,
         lint_level: LintLevel,
         value: ExprId,
     },
+    /// A `box <value>` expression.
     Box {
         value: ExprId,
     },
+    /// An `if` expression.
     If {
         cond: ExprId,
         then: ExprId,
         else_opt: Option<ExprId>,
     },
+    /// A function call. Method calls and overloaded operators are converted to plain function calls.
     Call {
+        /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`].
+        ///
+        /// [`FnDef`]: ty::TyKind::FnDef
+        /// [`FnPtr`]: ty::TyKind::FnPtr
         ty: Ty<'tcx>,
+        /// The function itself.
         fun: ExprId,
+        /// The arguments passed to the function.
+        ///
+        /// Note: in some cases (like calling a closure), the function call `f(...args)` gets
+        /// rewritten as a call to a function trait method (e.g. `FnOnce::call_once(f, (...args))`).
         args: Box<[ExprId]>,
-        /// Whether this is from a call in HIR, rather than from an overloaded
-        /// operator. `true` for overloaded function call.
+        /// Whether this is from an overloaded operator rather than a
+        /// function call from HIR. `true` for overloaded function call.
         from_hir_call: bool,
-        /// This `Span` is the span of the function, without the dot and receiver
-        /// (e.g. `foo(a, b)` in `x.foo(a, b)`
+        /// The span of the function, without the dot and receiver
+        /// (e.g. `foo(a, b)` in `x.foo(a, b)`).
         fn_span: Span,
     },
+    /// A *non-overloaded* dereference.
     Deref {
         arg: ExprId,
-    }, // NOT overloaded!
+    },
+    /// A *non-overloaded* binary operation.
     Binary {
         op: BinOp,
         lhs: ExprId,
         rhs: ExprId,
-    }, // NOT overloaded!
+    },
+    /// A logical operation. This is distinct from `BinaryOp` because
+    /// the operands need to be lazily evaluated.
     LogicalOp {
         op: LogicalOp,
         lhs: ExprId,
         rhs: ExprId,
-    }, // NOT overloaded!
-    // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
+    },
+    /// A *non-overloaded* unary operation. Note that here the deref (`*`)
+    /// operator is represented by `ExprKind::Deref`.
     Unary {
         op: UnOp,
         arg: ExprId,
-    }, // NOT overloaded!
+    },
+    /// A cast: `<source> as <type>`. The type we cast to is the type of
+    /// the parent expression.
     Cast {
         source: ExprId,
     },
     Use {
         source: ExprId,
     }, // Use a lexpr to get a vexpr.
+    /// A coercion from `!` to any type.
     NeverToAny {
         source: ExprId,
     },
+    /// A pointer cast. More information can be found in [`PointerCast`].
     Pointer {
         cast: PointerCast,
         source: ExprId,
     },
+    /// A `loop` expression.
     Loop {
         body: ExprId,
     },
+    /// A `match` expression.
     Match {
         scrutinee: ExprId,
         arms: Box<[ArmId]>,
     },
+    /// A block.
     Block {
         body: Block,
     },
+    /// An assignment: `lhs = rhs`.
     Assign {
         lhs: ExprId,
         rhs: ExprId,
     },
+    /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`.
     AssignOp {
         op: BinOp,
         lhs: ExprId,
         rhs: ExprId,
     },
+    /// Access to a struct or tuple field.
     Field {
         lhs: ExprId,
+        /// This can be a named (`.foo`) or unnamed (`.0`) field.
         name: Field,
     },
+    /// A *non-overloaded* indexing operation.
     Index {
         lhs: ExprId,
         index: ExprId,
     },
+    /// A local variable.
     VarRef {
         id: hir::HirId,
     },
@@ -272,6 +335,7 @@ pub enum ExprKind<'tcx> {
         /// HirId of the root variable
         var_hir_id: hir::HirId,
     },
+    /// A borrow, e.g. `&arg`.
     Borrow {
         borrow_kind: BorrowKind,
         arg: ExprId,
@@ -281,51 +345,51 @@ pub enum ExprKind<'tcx> {
         mutability: hir::Mutability,
         arg: ExprId,
     },
+    /// A `break` expression.
     Break {
         label: region::Scope,
         value: Option<ExprId>,
     },
+    /// A `continue` expression.
     Continue {
         label: region::Scope,
     },
+    /// A `return` expression.
     Return {
         value: Option<ExprId>,
     },
+    /// An inline `const` block, e.g. `const {}`.
     ConstBlock {
         value: &'tcx Const<'tcx>,
     },
+    /// An array literal constructed from one repeated element, e.g. `[1; 5]`.
     Repeat {
         value: ExprId,
         count: &'tcx Const<'tcx>,
     },
+    /// An array, e.g. `[a, b, c, d]`.
     Array {
         fields: Box<[ExprId]>,
     },
+    /// A tuple, e.g. `(a, b, c, d)`.
     Tuple {
         fields: Box<[ExprId]>,
     },
-    Adt {
-        adt_def: &'tcx AdtDef,
-        variant_index: VariantIdx,
-        substs: SubstsRef<'tcx>,
-
-        /// Optional user-given substs: for something like `let x =
-        /// Bar::<T> { ... }`.
-        user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
-
-        fields: Box<[FieldExpr]>,
-        base: Option<FruInfo<'tcx>>,
-    },
+    /// An ADT constructor, e.g. `Foo {x: 1, y: 2}`.
+    Adt(Box<Adt<'tcx>>),
+    /// A type ascription on a place.
     PlaceTypeAscription {
         source: ExprId,
         /// Type that the user gave to this expression
         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
     },
+    /// A type ascription on a value, e.g. `42: i32`.
     ValueTypeAscription {
         source: ExprId,
         /// Type that the user gave to this expression
         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
     },
+    /// A closure definition.
     Closure {
         closure_id: DefId,
         substs: UpvarSubsts<'tcx>,
@@ -333,6 +397,7 @@ pub enum ExprKind<'tcx> {
         movability: Option<hir::Movability>,
         fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>,
     },
+    /// A literal.
     Literal {
         literal: &'tcx Const<'tcx>,
         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
@@ -349,6 +414,7 @@ pub enum ExprKind<'tcx> {
         literal: &'tcx Const<'tcx>,
         def_id: DefId,
     },
+    /// Inline assembly, i.e. `asm!()`.
     InlineAsm {
         template: &'tcx [InlineAsmTemplatePiece],
         operands: Box<[InlineAsmOperand<'tcx>]>,
@@ -357,16 +423,21 @@ pub enum ExprKind<'tcx> {
     },
     /// An expression taking a reference to a thread local.
     ThreadLocalRef(DefId),
+    /// Inline LLVM assembly, i.e. `llvm_asm!()`.
     LlvmInlineAsm {
         asm: &'tcx hir::LlvmInlineAsmInner,
         outputs: Box<[ExprId]>,
         inputs: Box<[ExprId]>,
     },
+    /// A `yield` expression.
     Yield {
         value: ExprId,
     },
 }
 
+/// Represents the association of a field identifier and an expression.
+///
+/// This is used in struct constructors.
 #[derive(Debug, HashStable)]
 pub struct FieldExpr {
     pub name: Field,
@@ -379,6 +450,7 @@ pub struct FruInfo<'tcx> {
     pub field_types: Box<[Ty<'tcx>]>,
 }
 
+/// A `match` arm.
 #[derive(Debug, HashStable)]
 pub struct Arm<'tcx> {
     pub pattern: Pat<'tcx>,
@@ -389,6 +461,7 @@ pub struct Arm<'tcx> {
     pub span: Span,
 }
 
+/// A `match` guard.
 #[derive(Debug, HashStable)]
 pub enum Guard<'tcx> {
     If(ExprId),
@@ -397,7 +470,9 @@ pub enum Guard<'tcx> {
 
 #[derive(Copy, Clone, Debug, HashStable)]
 pub enum LogicalOp {
+    /// The `&&` operator.
     And,
+    /// The `||` operator.
     Or,
 }
 
@@ -514,6 +589,7 @@ pub struct Ascription<'tcx> {
 
 #[derive(Clone, Debug, PartialEq, HashStable)]
 pub enum PatKind<'tcx> {
+    /// A wildward pattern: `_`.
     Wild,
 
     AscribeUserType {
index c9b73c682098b6fd728e8c388294de4774658beb..a4a2e824637570b96200cb42163fe7a60a764292 100644 (file)
@@ -13,9 +13,10 @@ use crate::mir::abstract_const::NotConstEvaluatable;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, AdtKind, Ty, TyCtxt};
 
+use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::Constness;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
@@ -24,7 +25,6 @@ use smallvec::SmallVec;
 use std::borrow::Cow;
 use std::fmt;
 use std::ops::Deref;
-use std::rc::Rc;
 
 pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
 
@@ -87,7 +87,7 @@ pub enum Reveal {
 #[derive(Clone, PartialEq, Eq, Hash, Lift)]
 pub struct ObligationCause<'tcx> {
     /// `None` for `ObligationCause::dummy`, `Some` otherwise.
-    data: Option<Rc<ObligationCauseData<'tcx>>>,
+    data: Option<Lrc<ObligationCauseData<'tcx>>>,
 }
 
 const DUMMY_OBLIGATION_CAUSE_DATA: ObligationCauseData<'static> =
@@ -131,7 +131,7 @@ impl<'tcx> ObligationCause<'tcx> {
         body_id: hir::HirId,
         code: ObligationCauseCode<'tcx>,
     ) -> ObligationCause<'tcx> {
-        ObligationCause { data: Some(Rc::new(ObligationCauseData { span, body_id, code })) }
+        ObligationCause { data: Some(Lrc::new(ObligationCauseData { span, body_id, code })) }
     }
 
     pub fn misc(span: Span, body_id: hir::HirId) -> ObligationCause<'tcx> {
@@ -148,7 +148,7 @@ impl<'tcx> ObligationCause<'tcx> {
     }
 
     pub fn make_mut(&mut self) -> &mut ObligationCauseData<'tcx> {
-        Rc::make_mut(self.data.get_or_insert_with(|| Rc::new(DUMMY_OBLIGATION_CAUSE_DATA)))
+        Lrc::make_mut(self.data.get_or_insert_with(|| Lrc::new(DUMMY_OBLIGATION_CAUSE_DATA)))
     }
 
     pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span {
@@ -326,6 +326,38 @@ pub enum ObligationCauseCode<'tcx> {
 
     /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y`
     OpaqueType,
+
+    /// Well-formed checking. If a `WellFormedLoc` is provided,
+    /// then it will be used to eprform HIR-based wf checking
+    /// after an error occurs, in order to generate a more precise error span.
+    /// This is purely for diagnostic purposes - it is always
+    /// correct to use `MiscObligation` instead, or to specify
+    /// `WellFormed(None)`
+    WellFormed(Option<WellFormedLoc>),
+
+    /// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching against.
+    MatchImpl(Lrc<ObligationCauseCode<'tcx>>, DefId),
+}
+
+/// The 'location' at which we try to perform HIR-based wf checking.
+/// This information is used to obtain an `hir::Ty`, which
+/// we can walk in order to obtain precise spans for any
+/// 'nested' types (e.g. `Foo` in `Option<Foo>`).
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+pub enum WellFormedLoc {
+    /// Use the type of the provided definition.
+    Ty(LocalDefId),
+    /// Use the type of the parameter of the provided function.
+    /// We cannot use `hir::Param`, since the function may
+    /// not have a body (e.g. a trait method definition)
+    Param {
+        /// The function to lookup the parameter in
+        function: LocalDefId,
+        /// The index of the parameter to use.
+        /// Parameters are indexed from 0, with the return type
+        /// being the last 'parameter'
+        param_idx: u16,
+    },
 }
 
 impl ObligationCauseCode<'_> {
@@ -389,7 +421,7 @@ pub struct DerivedObligationCause<'tcx> {
     pub parent_trait_ref: ty::PolyTraitRef<'tcx>,
 
     /// The parent trait had this cause.
-    pub parent_code: Rc<ObligationCauseCode<'tcx>>,
+    pub parent_code: Lrc<ObligationCauseCode<'tcx>>,
 }
 
 #[derive(Clone, Debug, TypeFoldable, Lift)]
@@ -426,10 +458,10 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, 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 d005f63ed4383b4365d9790cd715a8746000547c..2d177551664f6fa43aa22b08674b1a415a6ac65a 100644 (file)
@@ -124,7 +124,7 @@ impl<'tcx> AssocItems<'tcx> {
         &self,
         name: Symbol,
     ) -> impl '_ + Iterator<Item = &ty::AssocItem> {
-        self.items.get_by_key(&name).copied()
+        self.items.get_by_key(name).copied()
     }
 
     /// Returns an iterator over all associated items with the given name.
index 0706a057dd0c6d6d335989d6ce9663e1ab85b18d..6b51adc6aafddab3e759ac577025e7b057d7dd67 100644 (file)
@@ -281,11 +281,10 @@ pub struct CaptureInfo<'tcx> {
 }
 
 pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String {
-    let name = match place.base {
+    let mut curr_string: String = match place.base {
         HirPlaceBase::Upvar(upvar_id) => tcx.hir().name(upvar_id.var_path.hir_id).to_string(),
         _ => bug!("Capture_information should only contain upvars"),
     };
-    let mut curr_string = name;
 
     for (i, proj) in place.projections.iter().enumerate() {
         match proj.kind {
@@ -314,7 +313,7 @@ pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) ->
         }
     }
 
-    curr_string.to_string()
+    curr_string
 }
 
 #[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, TypeFoldable, Copy, HashStable)]
@@ -347,7 +346,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 8ed8ea6a0bc55b2dcbc4f73b0f8ed7e7e9d54975..8262bc261996a510b45fc83bf0d0974301057b7a 100644 (file)
@@ -1,7 +1,7 @@
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use rustc_target::abi::{Size, TargetDataLayout};
+use rustc_target::abi::Size;
 use std::convert::{TryFrom, TryInto};
 use std::fmt;
 
@@ -193,15 +193,6 @@ impl ScalarInt {
         self.data == 0
     }
 
-    pub(crate) fn ptr_sized_op<E>(
-        self,
-        dl: &TargetDataLayout,
-        f_int: impl FnOnce(u64) -> Result<u64, E>,
-    ) -> Result<Self, E> {
-        assert_eq!(u64::from(self.size), dl.pointer_size.bytes());
-        Ok(Self::try_from_uint(f_int(u64::try_from(self.data).unwrap())?, self.size()).unwrap())
-    }
-
     #[inline]
     pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
         let data = i.into();
index 875d8d00a93d32b6686f786be497cf6b6040540b..f2db95d162b888363fc7d016fe40af5c7f261e45 100644 (file)
@@ -1,7 +1,6 @@
 use std::convert::TryInto;
 
-use crate::mir::interpret::ConstValue;
-use crate::mir::interpret::Scalar;
+use crate::mir::interpret::{AllocId, ConstValue, Scalar};
 use crate::mir::Promoted;
 use crate::ty::subst::{InternalSubsts, SubstsRef};
 use crate::ty::ParamEnv;
@@ -59,7 +58,7 @@ impl<'tcx> ConstKind<'tcx> {
     }
 
     #[inline]
-    pub fn try_to_scalar(self) -> Option<Scalar> {
+    pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
         self.try_to_value()?.try_to_scalar()
     }
 
index 73991436b7b6bd834309b91bb474ef4236e66939..4ce49032398bc7877cc2438953c63fec117cfcfc 100644 (file)
@@ -1,32 +1,30 @@
 //! Type context book-keeping.
 
 use crate::arena::Arena;
-use crate::dep_graph::DepGraph;
-use crate::hir::exports::ExportMap;
+use crate::dep_graph::{DepGraph, DepNode};
 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, Allocation, ConstValue, Scalar};
+use crate::mir::interpret::{self, AllocId, Allocation, ConstValue, Scalar};
 use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted};
 use crate::thir::Thir;
 use crate::traits;
-use crate::ty::query::{self, OnDiskCache, TyCtxtAt};
+use crate::ty::query::{self, TyCtxtAt};
 use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts};
 use crate::ty::TyKind::*;
 use crate::ty::{
-    self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, 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,
+    self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
+    ClosureSizeProfileData, Const, ConstVid, DefIdTree, ExistentialPredicate, FloatTy, FloatVar,
+    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_ast::expand::allocator::AllocatorKind;
 use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::profiling::SelfProfilerRef;
@@ -39,11 +37,11 @@ use rustc_errors::ErrorReported;
 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::{
-    Constness, HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate,
+    Constness, ExprKind, HirId, ImplItemKind, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet,
+    Node, TraitCandidate, TraitItemKind,
 };
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
@@ -52,9 +50,10 @@ use rustc_middle::ty::OpaqueTypeKey;
 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;
+use rustc_span::def_id::{DefPathHash, StableCrateId};
+use rustc_span::source_map::{MultiSpan, SourceMap};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx};
@@ -72,6 +71,40 @@ use std::mem;
 use std::ops::{Bound, Deref};
 use std::sync::Arc;
 
+pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
+    /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
+    fn new(sess: &'tcx Session, data: Vec<u8>, start_pos: usize) -> Self
+    where
+        Self: Sized;
+
+    fn new_empty(source_map: &'tcx SourceMap) -> Self
+    where
+        Self: Sized;
+
+    /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
+    /// session, if it still exists. This is used during incremental compilation to
+    /// turn a deserialized `DefPathHash` into its current `DefId`.
+    fn def_path_hash_to_def_id(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        def_path_hash: DefPathHash,
+    ) -> Option<DefId>;
+
+    /// If the given `dep_node`'s hash still exists in the current compilation,
+    /// and its current `DefId` is foreign, calls `store_foreign_def_id` with it.
+    ///
+    /// Normally, `store_foreign_def_id_hash` can be called directly by
+    /// the dependency graph when we construct a `DepNode`. However,
+    /// when we re-use a deserialized `DepNode` from the previous compilation
+    /// session, we only have the `DefPathHash` available. This method is used
+    /// to that any `DepNode` that we re-use has a `DefPathHash` -> `RawId` written
+    /// out for usage in the next compilation session.
+    fn register_reused_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode);
+    fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash);
+
+    fn serialize(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileEncodeResult;
+}
+
 /// A type that is not publicly constructable. This prevents people from making [`TyKind::Error`]s
 /// except through the error-reporting functions on a [`tcx`][TyCtxt].
 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
@@ -392,6 +425,34 @@ pub struct TypeckResults<'tcx> {
     /// (including late-bound regions) are replaced with free
     /// equivalents. This table is not used in codegen (since regions
     /// are erased there) and hence is not serialized to metadata.
+    ///
+    /// This table also contains the "revealed" values for any `impl Trait`
+    /// that appear in the signature and whose values are being inferred
+    /// by this function.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// fn foo(x: &u32) -> impl Debug { *x }
+    /// ```
+    ///
+    /// The function signature here would be:
+    ///
+    /// ```
+    /// for<'a> fn(&'a u32) -> Foo
+    /// ```
+    ///
+    /// where `Foo` is an opaque type created for this function.
+    ///
+    ///
+    /// The *liberated* form of this would be
+    ///
+    /// ```
+    /// fn(&'a u32) -> u32
+    /// ```
+    ///
+    /// Note that `'a` is not bound (it would be an `ReFree`) and
+    /// that the `Foo` opaque type is replaced by its hidden type.
     liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
 
     /// For each FRU expression, record the normalized types of the fields
@@ -455,6 +516,10 @@ pub struct TypeckResults<'tcx> {
     /// This hashset records all instances where we behave
     /// like this to allow `const_to_pat` to reliably handle this situation.
     pub treat_byte_string_as_slice: ItemLocalSet,
+
+    /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
+    /// on closure size.
+    pub closure_size_eval: FxHashMap<DefId, ClosureSizeProfileData<'tcx>>,
 }
 
 impl<'tcx> TypeckResults<'tcx> {
@@ -481,6 +546,7 @@ impl<'tcx> TypeckResults<'tcx> {
             closure_fake_reads: Default::default(),
             generator_interior_types: ty::Binder::dummy(Default::default()),
             treat_byte_string_as_slice: Default::default(),
+            closure_size_eval: Default::default(),
         }
     }
 
@@ -725,6 +791,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckResults<'tcx> {
             ref closure_fake_reads,
             ref generator_interior_types,
             ref treat_byte_string_as_slice,
+            ref closure_size_eval,
         } = *self;
 
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
@@ -751,6 +818,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckResults<'tcx> {
             closure_fake_reads.hash_stable(hcx, hasher);
             generator_interior_types.hash_stable(hcx, hasher);
             treat_byte_string_as_slice.hash_stable(hcx, hasher);
+            closure_size_eval.hash_stable(hcx, hasher);
         })
     }
 }
@@ -929,8 +997,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.
@@ -952,36 +1018,20 @@ 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
     /// `DepGraph::try_mark_green()` and the query infrastructure.
     /// This is `None` if we are not incremental compilation mode
-    pub on_disk_cache: Option<OnDiskCache<'tcx>>,
+    pub on_disk_cache: Option<&'tcx dyn OnDiskCache<'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>>>,
@@ -1015,7 +1065,8 @@ 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>>,
 }
 
 impl<'tcx> TyCtxt<'tcx> {
@@ -1124,7 +1175,7 @@ impl<'tcx> TyCtxt<'tcx> {
         resolutions: ty::ResolverOutputs,
         krate: &'tcx hir::Crate<'tcx>,
         dep_graph: DepGraph,
-        on_disk_cache: Option<query::OnDiskCache<'tcx>>,
+        on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
         queries: &'tcx dyn query::QueryEngine<'tcx>,
         crate_name: &str,
         output_filenames: OutputFilenames,
@@ -1136,28 +1187,19 @@ impl<'tcx> TyCtxt<'tcx> {
         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(),
@@ -1172,7 +1214,7 @@ impl<'tcx> TyCtxt<'tcx> {
             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(),
         }
     }
 
@@ -1227,20 +1269,17 @@ impl<'tcx> TyCtxt<'tcx> {
         self.stability_index(())
     }
 
-    pub fn crates(self) -> &'tcx [CrateNum] {
-        self.all_crate_nums(())
-    }
-
-    pub fn allocator_kind(self) -> Option<AllocatorKind> {
-        self.cstore.allocator_kind()
-    }
-
     pub fn features(self) -> &'tcx rustc_feature::Features {
         self.features_query(())
     }
 
     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
@@ -1249,74 +1288,91 @@ impl<'tcx> TyCtxt<'tcx> {
     /// 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(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 {
-            (
-                self.cstore.crate_name_untracked(def_id.krate),
-                self.cstore.crate_disambiguator_untracked(def_id.krate),
-            )
+            let cstore = &self.untracked_resolutions.cstore;
+            (cstore.crate_name(def_id.krate), cstore.stable_crate_id(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()
+    /// 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_untracked(self) -> &'tcx ty::CrateStoreDyn {
+        &*self.untracked_resolutions.cstore
+    }
+
+    /// Note that this is *untracked* and should only be used within the query
+    /// system if the result is otherwise tracked through queries
+    pub fn definitions_untracked(self) -> &'tcx hir::definitions::Definitions {
+        &self.untracked_resolutions.definitions
     }
 
     #[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 {
@@ -1470,18 +1526,14 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn return_type_impl_trait(self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> {
-        // HACK: `type_of_def_id()` will fail on these (#55796), so return `None`.
+        // `type_of()` will fail on these (#55796, #86483), so only allow `fn`s or closures.
         let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
         match self.hir().get(hir_id) {
-            Node::Item(item) => {
-                match item.kind {
-                    ItemKind::Fn(..) => { /* `type_of_def_id()` will work */ }
-                    _ => {
-                        return None;
-                    }
-                }
-            }
-            _ => { /* `type_of_def_id()` will work or panic */ }
+            Node::Item(&hir::Item { kind: ItemKind::Fn(..), .. }) => {}
+            Node::TraitItem(&hir::TraitItem { kind: TraitItemKind::Fn(..), .. }) => {}
+            Node::ImplItem(&hir::ImplItem { kind: ImplItemKind::Fn(..), .. }) => {}
+            Node::Expr(&hir::Expr { kind: ExprKind::Closure(..), .. }) => {}
+            _ => return None,
         }
 
         let ret_ty = self.type_of(scope_def_id);
@@ -1541,6 +1593,22 @@ impl<'tcx> TyCtxt<'tcx> {
             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
@@ -1614,7 +1682,7 @@ nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariable
 // This is the impl for `&'a InternalSubsts<'a>`.
 nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
 
-CloneLiftImpls! { for<'tcx> { Constness, } }
+CloneLiftImpls! { for<'tcx> { Constness, traits::WellFormedLoc, } }
 
 pub mod tls {
     use super::{ptr_eq, GlobalCtxt, TyCtxt};
@@ -2772,15 +2840,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());
@@ -2794,8 +2866,8 @@ 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.all_crate_nums = |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.output_filenames = |tcx, ()| tcx.output_filenames.clone();
     providers.features_query = |tcx, ()| tcx.sess.features_untracked();
     providers.is_panic_runtime = |tcx, cnum| {
index eb6d163312c83ea1eabd89ecef365fd24c330dbf..a40210d5a3622c29f7033abfbae18cc676038252 100644 (file)
@@ -754,88 +754,6 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 }
 
-pub struct BoundVarsCollector<'tcx> {
-    binder_index: ty::DebruijnIndex,
-    vars: BTreeMap<u32, ty::BoundVariableKind>,
-    // We may encounter the same variable at different levels of binding, so
-    // this can't just be `Ty`
-    visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
-}
-
-impl<'tcx> BoundVarsCollector<'tcx> {
-    pub fn new() -> Self {
-        BoundVarsCollector {
-            binder_index: ty::INNERMOST,
-            vars: BTreeMap::new(),
-            visited: SsoHashSet::default(),
-        }
-    }
-
-    pub fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List<ty::BoundVariableKind> {
-        let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or_else(|| 0);
-        for i in 0..max {
-            if let None = self.vars.get(&i) {
-                panic!("Unknown variable: {:?}", i);
-            }
-        }
-
-        tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v))
-    }
-}
-
-impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
-    type BreakTy = ();
-
-    fn visit_binder<T: TypeFoldable<'tcx>>(
-        &mut self,
-        t: &Binder<'tcx, T>,
-    ) -> ControlFlow<Self::BreakTy> {
-        self.binder_index.shift_in(1);
-        let result = t.super_visit_with(self);
-        self.binder_index.shift_out(1);
-        result
-    }
-
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if t.outer_exclusive_binder < self.binder_index
-            || !self.visited.insert((self.binder_index, t))
-        {
-            return ControlFlow::CONTINUE;
-        }
-        use std::collections::btree_map::Entry;
-        match *t.kind() {
-            ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
-                match self.vars.entry(bound_ty.var.as_u32()) {
-                    Entry::Vacant(entry) => {
-                        entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind));
-                    }
-                    Entry::Occupied(entry) => match entry.get() {
-                        ty::BoundVariableKind::Ty(_) => {}
-                        _ => bug!("Conflicting bound vars"),
-                    },
-                }
-            }
-
-            _ => (),
-        };
-
-        t.super_visit_with(self)
-    }
-
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
-        match r {
-            ty::ReLateBound(index, _br) if *index == self.binder_index => {
-                // If you hit this, you should be using `Binder::bind_with_vars` or `Binder::rebind`
-                bug!("Trying to collect bound vars with a bound region: {:?} {:?}", index, _br)
-            }
-
-            _ => (),
-        };
-
-        r.super_visit_with(self)
-    }
-}
-
 pub struct ValidateBoundVars<'tcx> {
     bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
     binder_index: ty::DebruijnIndex,
index 41d953216e0dd1425d2b59d465c4720c2e57ebdf..261a19f862e02958b226f4e386f04c6ce17793b6 100644 (file)
@@ -227,8 +227,9 @@ impl<'tcx> InstanceDef<'tcx> {
 
     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 @@ impl<'tcx> Instance<'tcx> {
         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 @@ impl<'tcx> Instance<'tcx> {
             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 28a44b09de2b112ce0e8a366ca541b3ef51329d6..95ea38d32b69508aeb4eeaa27046bdf096c47bbb 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));
         }
 
@@ -312,7 +312,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
         let dl = self.data_layout();
         let pack = repr.pack;
         if pack.is_some() && repr.align.is_some() {
-            bug!("struct cannot be packed and aligned");
+            self.tcx.sess.delay_span_bug(DUMMY_SP, "struct cannot be packed and aligned");
+            return Err(LayoutError::Unknown(ty));
         }
 
         let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
@@ -672,6 +673,15 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
 
             // SIMD vector types.
             ty::Adt(def, substs) if def.repr.simd() => {
+                if !def.is_struct() {
+                    // Should have yielded E0517 by now.
+                    tcx.sess.delay_span_bug(
+                        DUMMY_SP,
+                        "#[repr(simd)] was applied to an ADT that is not a struct",
+                    );
+                    return Err(LayoutError::Unknown(ty));
+                }
+
                 // Supported SIMD vectors are homogeneous ADTs with at least one field:
                 //
                 // * #[repr(simd)] struct S(T, T, T, T);
@@ -799,7 +809,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
 
                 if def.is_union() {
                     if def.repr.pack.is_some() && def.repr.align.is_some() {
-                        bug!("union cannot be packed and aligned");
+                        self.tcx.sess.delay_span_bug(
+                            tcx.def_span(def.did),
+                            "union cannot be packed and aligned",
+                        );
+                        return Err(LayoutError::Unknown(ty));
                     }
 
                     let mut align =
@@ -2469,9 +2483,10 @@ impl<'tcx> ty::Instance<'tcx> {
                 // `src/test/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping
                 // track of a polymorphization `ParamEnv` to allow normalizing later.
                 let mut sig = match *ty.kind() {
-                    ty::FnDef(def_id, substs) => tcx
+                    ty::FnDef(def_id, substs) if tcx.sess.opts.debugging_opts.polymorphize => tcx
                         .normalize_erasing_regions(tcx.param_env(def_id), tcx.fn_sig(def_id))
                         .subst(tcx, substs),
+                    ty::FnDef(def_id, substs) => tcx.fn_sig(def_id).subst(tcx, substs),
                     _ => unreachable!(),
                 };
 
index 44dfcbf1866a7a402c4248fb2b1f3c4b74e17dcb..1dceda6c7aad0f9e81353601732ef047139ac2ff 100644 (file)
@@ -63,17 +63,17 @@ impl<T: Copy> List<T> {
 
         let (layout, _offset) =
             Layout::new::<usize>().extend(Layout::for_value::<[T]>(slice)).unwrap();
-        let mem = arena.dropless.alloc_raw(layout);
+        let mem = arena.dropless.alloc_raw(layout) as *mut List<T>;
         unsafe {
-            let result = &mut *(mem as *mut List<T>);
             // Write the length
-            result.len = slice.len();
+            ptr::addr_of_mut!((*mem).len).write(slice.len());
 
             // Write the elements
-            let arena_slice = slice::from_raw_parts_mut(result.data.as_mut_ptr(), result.len);
-            arena_slice.copy_from_slice(slice);
+            ptr::addr_of_mut!((*mem).data)
+                .cast::<T>()
+                .copy_from_nonoverlapping(slice.as_ptr(), slice.len());
 
-            result
+            &mut *mem
         }
     }
 
index 227aa8dc284e27dd7a0d80d6e63f9cf868bfd94c..a6aff424790695b5fe169ffa61b4a14cfb5c2726 100644 (file)
@@ -18,6 +18,7 @@ pub use adt::*;
 pub use assoc::*;
 pub use closure::*;
 pub use generics::*;
+pub use vtable::*;
 
 use crate::hir::exports::ExportMap;
 use crate::ich::StableHashingContext;
@@ -58,7 +59,7 @@ pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, Uneval
 pub use self::context::{
     tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
     CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt,
-    Lift, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex,
+    Lift, OnDiskCache, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex,
 };
 pub use self::instance::{Instance, InstanceDef};
 pub use self::list::List;
@@ -94,6 +95,7 @@ pub mod relate;
 pub mod subst;
 pub mod trait_def;
 pub mod util;
+pub mod vtable;
 pub mod walk;
 
 mod adt;
@@ -111,6 +113,7 @@ mod sty;
 
 // Data types
 
+#[derive(Debug)]
 pub struct ResolverOutputs {
     pub definitions: rustc_hir::definitions::Definitions,
     pub cstore: Box<CrateStoreDyn>,
@@ -126,7 +129,7 @@ pub struct ResolverOutputs {
     pub main_def: Option<MainDefinition>,
 }
 
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub struct MainDefinition {
     pub res: Res<ast::NodeId>,
     pub is_import: bool,
@@ -173,6 +176,25 @@ pub enum Visibility {
     Invisible,
 }
 
+#[derive(
+    Clone,
+    Debug,
+    PartialEq,
+    Eq,
+    Copy,
+    Hash,
+    TyEncodable,
+    TyDecodable,
+    HashStable,
+    TypeFoldable
+)]
+pub struct ClosureSizeProfileData<'tcx> {
+    /// Tuple containing the types of closure captures before the feature `capture_disjoint_fields`
+    pub before_feature_tys: Ty<'tcx>,
+    /// Tuple containing the types of closure captures after the feature `capture_disjoint_fields`
+    pub after_feature_tys: Ty<'tcx>,
+}
+
 pub trait DefIdTree: Copy {
     fn parent(self, id: DefId) -> Option<DefId>;
 
@@ -835,7 +857,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable, TypeFoldable)]
 pub struct OpaqueTypeKey<'tcx> {
     pub def_id: DefId,
     pub substs: SubstsRef<'tcx>,
@@ -1881,13 +1903,11 @@ impl<'tcx> TyCtxt<'tcx> {
         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)
     }
 
@@ -1966,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 a4f736654af44f5438c3bcc12fb6cb5b15b3f803..11399506b96e427373baa68ef7b1b9c53598f240 100644 (file)
@@ -88,23 +88,32 @@ struct NormalizeAfterErasingRegionsFolder<'tcx> {
     param_env: ty::ParamEnv<'tcx>,
 }
 
+impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> {
+    fn normalize_generic_arg_after_erasing_regions(
+        &self,
+        arg: ty::GenericArg<'tcx>,
+    ) -> ty::GenericArg<'tcx> {
+        let arg = self.param_env.and(arg);
+        self.tcx.normalize_generic_arg_after_erasing_regions(arg)
+    }
+}
+
 impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        let arg = self.param_env.and(ty.into());
-        self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_ty()
+        self.normalize_generic_arg_after_erasing_regions(ty.into()).expect_ty()
     }
 
     fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        let arg = self.param_env.and(c.into());
-        self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_const()
+        self.normalize_generic_arg_after_erasing_regions(c.into()).expect_const()
     }
 
     #[inline]
     fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
+        // FIXME: This *probably* needs canonicalization too!
         let arg = self.param_env.and(c);
         self.tcx.normalize_mir_const_after_erasing_regions(arg)
     }
index 25557bdd1000e7b9164a49007bc589ee64903366..b5733bd2edc2e0cc29f90f02548d8b185e24d907 100644 (file)
@@ -1,5 +1,5 @@
 use crate::middle::cstore::{ExternCrate, ExternCrateSource};
-use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Scalar};
+use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Provenance, Scalar};
 use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
 use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Ty, TyCtxt, TypeFoldable};
 use rustc_apfloat::ieee::{Double, Single};
@@ -685,10 +685,10 @@ pub trait PrettyPrinter<'tcx>:
                         self = self.comma_sep(substs.as_generator().upvar_tys())?;
                     }
                     p!(")");
-                }
 
-                if substs.as_generator().is_valid() {
-                    p!(" ", print(substs.as_generator().witness()));
+                    if substs.as_generator().is_valid() {
+                        p!(" ", print(substs.as_generator().witness()));
+                    }
                 }
 
                 p!("]")
@@ -974,7 +974,7 @@ pub trait PrettyPrinter<'tcx>:
         print_ty: bool,
     ) -> Result<Self::Const, Self::Error> {
         match scalar {
-            Scalar::Ptr(ptr) => self.pretty_print_const_scalar_ptr(ptr, ty, print_ty),
+            Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty, print_ty),
             Scalar::Int(int) => self.pretty_print_const_scalar_int(int, ty, print_ty),
         }
     }
@@ -987,6 +987,7 @@ pub trait PrettyPrinter<'tcx>:
     ) -> Result<Self::Const, Self::Error> {
         define_scoped_cx!(self);
 
+        let (alloc_id, offset) = ptr.into_parts();
         match ty.kind() {
             // Byte strings (&[u8; N])
             ty::Ref(
@@ -1002,10 +1003,10 @@ pub trait PrettyPrinter<'tcx>:
                     ..
                 },
                 _,
-            ) => match self.tcx().get_global_alloc(ptr.alloc_id) {
+            ) => match self.tcx().get_global_alloc(alloc_id) {
                 Some(GlobalAlloc::Memory(alloc)) => {
                     let len = int.assert_bits(self.tcx().data_layout.pointer_size);
-                    let range = AllocRange { start: ptr.offset, size: Size::from_bytes(len) };
+                    let range = AllocRange { start: offset, size: Size::from_bytes(len) };
                     if let Ok(byte_str) = alloc.get_bytes(&self.tcx(), range) {
                         p!(pretty_print_byte_str(byte_str))
                     } else {
@@ -1020,7 +1021,7 @@ pub trait PrettyPrinter<'tcx>:
             ty::FnPtr(_) => {
                 // FIXME: We should probably have a helper method to share code with the "Byte strings"
                 // printing above (which also has to handle pointers to all sorts of things).
-                match self.tcx().get_global_alloc(ptr.alloc_id) {
+                match self.tcx().get_global_alloc(alloc_id) {
                     Some(GlobalAlloc::Function(instance)) => {
                         self = self.typed_value(
                             |this| this.print_value_path(instance.def_id(), instance.substs),
@@ -1068,8 +1069,8 @@ pub trait PrettyPrinter<'tcx>:
             ty::Char if char::try_from(int).is_ok() => {
                 p!(write("{:?}", char::try_from(int).unwrap()))
             }
-            // Raw pointers
-            ty::RawPtr(_) | ty::FnPtr(_) => {
+            // Pointer types
+            ty::Ref(..) | ty::RawPtr(_) | ty::FnPtr(_) => {
                 let data = int.assert_bits(self.tcx().data_layout.pointer_size);
                 self = self.typed_value(
                     |mut this| {
@@ -1106,9 +1107,9 @@ pub trait PrettyPrinter<'tcx>:
 
     /// This is overridden for MIR printing because we only want to hide alloc ids from users, not
     /// from MIR where it is actually useful.
-    fn pretty_print_const_pointer(
+    fn pretty_print_const_pointer<Tag: Provenance>(
         mut self,
-        _: Pointer,
+        _: Pointer<Tag>,
         ty: Ty<'tcx>,
         print_ty: bool,
     ) -> Result<Self::Const, Self::Error> {
@@ -1437,7 +1438,7 @@ impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
     }
 
     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)
@@ -1679,9 +1680,9 @@ impl<F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
         }
     }
 
-    fn pretty_print_const_pointer(
+    fn pretty_print_const_pointer<Tag: Provenance>(
         self,
-        p: Pointer,
+        p: Pointer<Tag>,
         ty: Ty<'tcx>,
         print_ty: bool,
     ) -> Result<Self::Const, Self::Error> {
@@ -1775,13 +1776,73 @@ impl<F: fmt::Write> FmtPrinter<'_, '_, F> {
     }
 }
 
+/// Folds through bound vars and placeholders, naming them
+struct RegionFolder<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    current_index: ty::DebruijnIndex,
+    region_map: BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
+    name: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
+}
+
+impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn fold_binder<T: TypeFoldable<'tcx>>(
+        &mut self,
+        t: ty::Binder<'tcx, T>,
+    ) -> ty::Binder<'tcx, T> {
+        self.current_index.shift_in(1);
+        let t = t.super_fold_with(self);
+        self.current_index.shift_out(1);
+        t
+    }
+
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+        match *t.kind() {
+            _ if t.has_vars_bound_at_or_above(self.current_index) || t.has_placeholders() => {
+                return t.super_fold_with(self);
+            }
+            _ => {}
+        }
+        t
+    }
+
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        let name = &mut self.name;
+        let region = match *r {
+            ty::ReLateBound(_, br) => self.region_map.entry(br).or_insert_with(|| name(br)),
+            ty::RePlaceholder(ty::PlaceholderRegion { name: kind, .. }) => {
+                // If this is an anonymous placeholder, don't rename. Otherwise, in some
+                // async fns, we get a `for<'r> Send` bound
+                match kind {
+                    ty::BrAnon(_) | ty::BrEnv => r,
+                    _ => {
+                        // Index doesn't matter, since this is just for naming and these never get bound
+                        let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind };
+                        self.region_map.entry(br).or_insert_with(|| name(br))
+                    }
+                }
+            }
+            _ => return r,
+        };
+        if let ty::ReLateBound(debruijn1, br) = *region {
+            assert_eq!(debruijn1, ty::INNERMOST);
+            self.tcx.mk_region(ty::ReLateBound(self.current_index, br))
+        } else {
+            region
+        }
+    }
+}
+
 // HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`,
 // `region_index` and `used_region_names`.
 impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
     pub fn name_all_regions<T>(
         mut self,
         value: &ty::Binder<'tcx, T>,
-    ) -> Result<(Self, (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)), fmt::Error>
+    ) -> Result<(Self, T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error>
     where
         T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
     {
@@ -1804,16 +1865,16 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
 
         let mut empty = true;
         let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
-            write!(
-                cx,
-                "{}",
-                if empty {
-                    empty = false;
-                    start
-                } else {
-                    cont
-                }
-            )
+            let w = if empty {
+                empty = false;
+                start
+            } else {
+                cont
+            };
+            let _ = write!(cx, "{}", w);
+        };
+        let do_continue = |cx: &mut Self, cont: Symbol| {
+            let _ = write!(cx, "{}", cont);
         };
 
         define_scoped_cx!(self);
@@ -1823,18 +1884,18 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
         // aren't named. Eventually, we might just want this as the default, but
         // this is not *quite* right and changes the ordering of some output
         // anyways.
-        let new_value = if self.tcx().sess.verbose() {
+        let (new_value, map) = if self.tcx().sess.verbose() {
             // anon index + 1 (BrEnv takes 0) -> name
             let mut region_map: BTreeMap<u32, Symbol> = BTreeMap::default();
             let bound_vars = value.bound_vars();
             for var in bound_vars {
                 match var {
                     ty::BoundVariableKind::Region(ty::BrNamed(_, name)) => {
-                        let _ = start_or_continue(&mut self, "for<", ", ");
-                        let _ = write!(self, "{}", name);
+                        start_or_continue(&mut self, "for<", ", ");
+                        do_continue(&mut self, name);
                     }
                     ty::BoundVariableKind::Region(ty::BrAnon(i)) => {
-                        let _ = start_or_continue(&mut self, "for<", ", ");
+                        start_or_continue(&mut self, "for<", ", ");
                         let name = loop {
                             let name = name_by_region_index(region_index);
                             region_index += 1;
@@ -1842,11 +1903,11 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
                                 break name;
                             }
                         };
-                        let _ = write!(self, "{}", name);
+                        do_continue(&mut self, name);
                         region_map.insert(i + 1, name);
                     }
                     ty::BoundVariableKind::Region(ty::BrEnv) => {
-                        let _ = start_or_continue(&mut self, "for<", ", ");
+                        start_or_continue(&mut self, "for<", ", ");
                         let name = loop {
                             let name = name_by_region_index(region_index);
                             region_index += 1;
@@ -1854,13 +1915,13 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
                                 break name;
                             }
                         };
-                        let _ = write!(self, "{}", name);
+                        do_continue(&mut self, name);
                         region_map.insert(0, name);
                     }
                     _ => continue,
                 }
             }
-            start_or_continue(&mut self, "", "> ")?;
+            start_or_continue(&mut self, "", "> ");
 
             self.tcx.replace_late_bound_regions(value.clone(), |br| {
                 let kind = match br.kind {
@@ -1880,11 +1941,12 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
                 ))
             })
         } else {
-            let new_value = self.tcx.replace_late_bound_regions(value.clone(), |br| {
-                let _ = start_or_continue(&mut self, "for<", ", ");
+            let tcx = self.tcx;
+            let mut name = |br: ty::BoundRegion| {
+                start_or_continue(&mut self, "for<", ", ");
                 let kind = match br.kind {
                     ty::BrNamed(_, name) => {
-                        let _ = write!(self, "{}", name);
+                        do_continue(&mut self, name);
                         br.kind
                     }
                     ty::BrAnon(_) | ty::BrEnv => {
@@ -1895,22 +1957,27 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
                                 break name;
                             }
                         };
-                        let _ = write!(self, "{}", name);
+                        do_continue(&mut self, name);
                         ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
                     }
                 };
-                self.tcx.mk_region(ty::ReLateBound(
-                    ty::INNERMOST,
-                    ty::BoundRegion { var: br.var, kind },
-                ))
-            });
-            start_or_continue(&mut self, "", "> ")?;
-            new_value
+                tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
+            };
+            let mut folder = RegionFolder {
+                tcx,
+                current_index: ty::INNERMOST,
+                name: &mut name,
+                region_map: BTreeMap::new(),
+            };
+            let new_value = value.clone().skip_binder().fold_with(&mut folder);
+            let region_map = folder.region_map;
+            start_or_continue(&mut self, "", "> ");
+            (new_value, region_map)
         };
 
         self.binder_depth += 1;
         self.region_index = region_index;
-        Ok((self, new_value))
+        Ok((self, new_value, map))
     }
 
     pub fn pretty_in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, fmt::Error>
@@ -1918,8 +1985,8 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
         T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
     {
         let old_region_index = self.region_index;
-        let (new, new_value) = self.name_all_regions(value)?;
-        let mut inner = new_value.0.print(new)?;
+        let (new, new_value, _) = self.name_all_regions(value)?;
+        let mut inner = new_value.print(new)?;
         inner.region_index = old_region_index;
         inner.binder_depth -= 1;
         Ok(inner)
@@ -1934,8 +2001,8 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
         T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
     {
         let old_region_index = self.region_index;
-        let (new, new_value) = self.name_all_regions(value)?;
-        let mut inner = f(&new_value.0, new)?;
+        let (new, new_value, _) = self.name_all_regions(value)?;
+        let mut inner = f(&new_value, new)?;
         inner.region_index = old_region_index;
         inner.binder_depth -= 1;
         Ok(inner)
@@ -1959,6 +2026,12 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
                 debug!("LateBoundRegionNameCollector::visit_region(r: {:?}, address: {:p})", r, &r);
                 if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
                     self.used_region_names.insert(name);
+                } else if let ty::RePlaceholder(ty::PlaceholderRegion {
+                    name: ty::BrNamed(_, name),
+                    ..
+                }) = *r
+                {
+                    self.used_region_names.insert(name);
                 }
                 r.super_visit_with(self)
             }
@@ -2248,7 +2321,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
     let queue = &mut Vec::new();
     let mut seen_defs: DefIdSet = Default::default();
 
-    for &cnum in tcx.crates().iter() {
+    for &cnum in tcx.crates(()).iter() {
         let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
 
         // Ignore crates that are not direct dependencies.
@@ -2313,7 +2386,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);
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
new file mode 100644 (file)
index 0000000..15a8888
--- /dev/null
@@ -0,0 +1,307 @@
+use crate::dep_graph;
+use crate::hir::exports::Export;
+use crate::infer::canonical::{self, Canonical};
+use crate::lint::LintLevelMap;
+use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
+use crate::middle::cstore::{CrateDepKind, CrateSource};
+use crate::middle::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
+use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
+use crate::middle::lib_features::LibFeatures;
+use crate::middle::privacy::AccessLevels;
+use crate::middle::region;
+use crate::middle::resolve_lifetime::{
+    LifetimeScopeForPath, ObjectLifetimeDefault, Region, ResolveLifetimes,
+};
+use crate::middle::stability::{self, DeprecationEntry};
+use crate::mir;
+use crate::mir::interpret::GlobalId;
+use crate::mir::interpret::{ConstAlloc, LitToConstError, LitToConstInput};
+use crate::mir::interpret::{ConstValue, EvalToAllocationRawResult, EvalToConstValueResult};
+use crate::mir::mono::CodegenUnit;
+use crate::thir;
+use crate::traits::query::{
+    CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
+    CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
+    CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
+};
+use crate::traits::query::{
+    DropckOutlivesResult, DtorckConstraint, MethodAutoderefStepsResult, NormalizationResult,
+    OutlivesBound,
+};
+use crate::traits::specialization_graph;
+use crate::traits::{self, ImplSource};
+use crate::ty::subst::{GenericArg, SubstsRef};
+use crate::ty::util::AlwaysRequiresDrop;
+use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
+use rustc_ast::expand::allocator::AllocatorKind;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
+use rustc_data_structures::steal::Steal;
+use rustc_data_structures::svh::Svh;
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::ErrorReported;
+use rustc_hir as hir;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
+use rustc_hir::lang_items::{LangItem, LanguageItems};
+use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
+use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
+use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
+use rustc_session::utils::NativeLibKind;
+use rustc_session::Limits;
+use rustc_target::spec::PanicStrategy;
+
+use rustc_ast as ast;
+use rustc_attr as attr;
+use rustc_span::symbol::Symbol;
+use rustc_span::{Span, DUMMY_SP};
+use std::collections::BTreeMap;
+use std::ops::Deref;
+use std::path::PathBuf;
+use std::sync::Arc;
+
+pub(crate) use rustc_query_system::query::QueryJobId;
+use rustc_query_system::query::*;
+
+#[derive(Copy, Clone)]
+pub struct TyCtxtAt<'tcx> {
+    pub tcx: TyCtxt<'tcx>,
+    pub span: Span,
+}
+
+impl Deref for TyCtxtAt<'tcx> {
+    type Target = TyCtxt<'tcx>;
+    #[inline(always)]
+    fn deref(&self) -> &Self::Target {
+        &self.tcx
+    }
+}
+
+#[derive(Copy, Clone)]
+pub struct TyCtxtEnsure<'tcx> {
+    pub tcx: TyCtxt<'tcx>,
+}
+
+impl TyCtxt<'tcx> {
+    /// Returns a transparent wrapper for `TyCtxt`, which ensures queries
+    /// are executed instead of just returning their results.
+    #[inline(always)]
+    pub fn ensure(self) -> TyCtxtEnsure<'tcx> {
+        TyCtxtEnsure { tcx: self }
+    }
+
+    /// Returns a transparent wrapper for `TyCtxt` which uses
+    /// `span` as the location of queries performed through it.
+    #[inline(always)]
+    pub fn at(self, span: Span) -> TyCtxtAt<'tcx> {
+        TyCtxtAt { tcx: self, span }
+    }
+
+    pub fn try_mark_green(self, dep_node: &dep_graph::DepNode) -> bool {
+        self.queries.try_mark_green(self, dep_node)
+    }
+}
+
+macro_rules! query_helper_param_ty {
+    (DefId) => { impl IntoQueryParam<DefId> };
+    ($K:ty) => { $K };
+}
+
+macro_rules! query_storage {
+    ([][$K:ty, $V:ty]) => {
+        <DefaultCacheSelector as CacheSelector<$K, $V>>::Cache
+    };
+    ([storage($ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => {
+        <$ty as CacheSelector<$K, $V>>::Cache
+    };
+    ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => {
+        query_storage!([$($($modifiers)*)*][$($args)*])
+    };
+}
+
+macro_rules! define_callbacks {
+    (<$tcx:tt>
+     $($(#[$attr:meta])*
+        [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
+
+        // HACK(eddyb) this is like the `impl QueryConfig for queries::$name`
+        // below, but using type aliases instead of associated types, to bypass
+        // the limitations around normalizing under HRTB - for example, this:
+        // `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value`
+        // doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`.
+        // This is primarily used by the `provide!` macro in `rustc_metadata`.
+        #[allow(nonstandard_style, unused_lifetimes)]
+        pub mod query_keys {
+            use super::*;
+
+            $(pub type $name<$tcx> = $($K)*;)*
+        }
+        #[allow(nonstandard_style, unused_lifetimes)]
+        pub mod query_values {
+            use super::*;
+
+            $(pub type $name<$tcx> = $V;)*
+        }
+        #[allow(nonstandard_style, unused_lifetimes)]
+        pub mod query_storage {
+            use super::*;
+
+            $(pub type $name<$tcx> = query_storage!([$($modifiers)*][$($K)*, $V]);)*
+        }
+        #[allow(nonstandard_style, unused_lifetimes)]
+        pub mod query_stored {
+            use super::*;
+
+            $(pub type $name<$tcx> = <query_storage::$name<$tcx> as QueryStorage>::Stored;)*
+        }
+
+        #[derive(Default)]
+        pub struct QueryCaches<$tcx> {
+            $($(#[$attr])* pub $name: QueryCacheStore<query_storage::$name<$tcx>>,)*
+        }
+
+        impl TyCtxtEnsure<$tcx> {
+            $($(#[$attr])*
+            #[inline(always)]
+            pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
+                let key = key.into_query_param();
+                let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, |_| {});
+
+                let lookup = match cached {
+                    Ok(()) => return,
+                    Err(lookup) => lookup,
+                };
+
+                self.tcx.queries.$name(self.tcx, DUMMY_SP, key, lookup, QueryMode::Ensure);
+            })*
+        }
+
+        impl TyCtxt<$tcx> {
+            $($(#[$attr])*
+            #[inline(always)]
+            #[must_use]
+            pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx>
+            {
+                self.at(DUMMY_SP).$name(key)
+            })*
+        }
+
+        impl TyCtxtAt<$tcx> {
+            $($(#[$attr])*
+            #[inline(always)]
+            pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx>
+            {
+                let key = key.into_query_param();
+                let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, |value| {
+                    value.clone()
+                });
+
+                let lookup = match cached {
+                    Ok(value) => return value,
+                    Err(lookup) => lookup,
+                };
+
+                self.tcx.queries.$name(self.tcx, self.span, key, lookup, QueryMode::Get).unwrap()
+            })*
+        }
+
+        pub struct Providers {
+            $(pub $name: for<'tcx> fn(
+                TyCtxt<'tcx>,
+                query_keys::$name<'tcx>,
+            ) -> query_values::$name<'tcx>,)*
+        }
+
+        impl Default for Providers {
+            fn default() -> Self {
+                Providers {
+                    $($name: |_, key| bug!(
+                        "`tcx.{}({:?})` unsupported by its crate; \
+                         perhaps the `{}` query was never assigned a provider function",
+                        stringify!($name),
+                        key,
+                        stringify!($name),
+                    ),)*
+                }
+            }
+        }
+
+        impl Copy for Providers {}
+        impl Clone for Providers {
+            fn clone(&self) -> Self { *self }
+        }
+
+        pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
+            fn as_any(&'tcx self) -> &'tcx dyn std::any::Any;
+
+            fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool;
+
+            $($(#[$attr])*
+            fn $name(
+                &'tcx self,
+                tcx: TyCtxt<$tcx>,
+                span: Span,
+                key: query_keys::$name<$tcx>,
+                lookup: QueryLookup,
+                mode: QueryMode,
+            ) -> Option<query_stored::$name<$tcx>>;)*
+        }
+    };
+}
+
+// Each of these queries corresponds to a function pointer field in the
+// `Providers` struct for requesting a value of that type, and a method
+// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
+// which memoizes and does dep-graph tracking, wrapping around the actual
+// `Providers` that the driver creates (using several `rustc_*` crates).
+//
+// The result type of each query must implement `Clone`, and additionally
+// `ty::query::values::Value`, which produces an appropriate placeholder
+// (error) value if the query resulted in a query cycle.
+// Queries marked with `fatal_cycle` do not need the latter implementation,
+// as they will raise an fatal error on query cycles instead.
+
+rustc_query_append! { [define_callbacks!][<'tcx>] }
+
+mod sealed {
+    use super::{DefId, LocalDefId};
+
+    /// An analogue of the `Into` trait that's intended only for query paramaters.
+    ///
+    /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
+    /// user call `to_def_id` to convert between them everywhere else.
+    pub trait IntoQueryParam<P> {
+        fn into_query_param(self) -> P;
+    }
+
+    impl<P> IntoQueryParam<P> for P {
+        #[inline(always)]
+        fn into_query_param(self) -> P {
+            self
+        }
+    }
+
+    impl IntoQueryParam<DefId> for LocalDefId {
+        #[inline(always)]
+        fn into_query_param(self) -> DefId {
+            self.to_def_id()
+        }
+    }
+}
+
+use sealed::IntoQueryParam;
+
+impl TyCtxt<'tcx> {
+    pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
+        let def_id = def_id.into_query_param();
+        self.opt_def_kind(def_id)
+            .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
+    }
+}
+
+impl TyCtxtAt<'tcx> {
+    pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
+        let def_id = def_id.into_query_param();
+        self.opt_def_kind(def_id)
+            .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs
deleted file mode 100644 (file)
index 297110e..0000000
+++ /dev/null
@@ -1,328 +0,0 @@
-use crate::dep_graph;
-use crate::hir::exports::Export;
-use crate::infer::canonical::{self, Canonical};
-use crate::lint::LintLevelMap;
-use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
-use crate::middle::cstore::{CrateDepKind, CrateSource};
-use crate::middle::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
-use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
-use crate::middle::lib_features::LibFeatures;
-use crate::middle::privacy::AccessLevels;
-use crate::middle::region;
-use crate::middle::resolve_lifetime::{
-    LifetimeScopeForPath, ObjectLifetimeDefault, Region, ResolveLifetimes,
-};
-use crate::middle::stability::{self, DeprecationEntry};
-use crate::mir;
-use crate::mir::interpret::GlobalId;
-use crate::mir::interpret::{ConstAlloc, LitToConstError, LitToConstInput};
-use crate::mir::interpret::{ConstValue, EvalToAllocationRawResult, EvalToConstValueResult};
-use crate::mir::mono::CodegenUnit;
-use crate::thir;
-use crate::traits::query::{
-    CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
-    CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
-    CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
-};
-use crate::traits::query::{
-    DropckOutlivesResult, DtorckConstraint, MethodAutoderefStepsResult, NormalizationResult,
-    OutlivesBound,
-};
-use crate::traits::specialization_graph;
-use crate::traits::{self, ImplSource};
-use crate::ty::subst::{GenericArg, SubstsRef};
-use crate::ty::util::AlwaysRequiresDrop;
-use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
-use rustc_data_structures::steal::Steal;
-use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::Lrc;
-use rustc_errors::{ErrorReported, Handler};
-use rustc_hir as hir;
-use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
-use rustc_hir::lang_items::{LangItem, LanguageItems};
-use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
-use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
-use rustc_serialize::opaque;
-use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
-use rustc_session::utils::NativeLibKind;
-use rustc_session::CrateDisambiguator;
-use rustc_target::spec::PanicStrategy;
-
-use rustc_ast as ast;
-use rustc_attr as attr;
-use rustc_span::symbol::Symbol;
-use rustc_span::{Span, DUMMY_SP};
-use std::collections::BTreeMap;
-use std::ops::Deref;
-use std::path::PathBuf;
-use std::sync::Arc;
-
-pub(crate) use rustc_query_system::query::QueryJobId;
-use rustc_query_system::query::*;
-
-pub mod on_disk_cache;
-pub use self::on_disk_cache::OnDiskCache;
-
-#[derive(Copy, Clone)]
-pub struct TyCtxtAt<'tcx> {
-    pub tcx: TyCtxt<'tcx>,
-    pub span: Span,
-}
-
-impl Deref for TyCtxtAt<'tcx> {
-    type Target = TyCtxt<'tcx>;
-    #[inline(always)]
-    fn deref(&self) -> &Self::Target {
-        &self.tcx
-    }
-}
-
-#[derive(Copy, Clone)]
-pub struct TyCtxtEnsure<'tcx> {
-    pub tcx: TyCtxt<'tcx>,
-}
-
-impl TyCtxt<'tcx> {
-    /// Returns a transparent wrapper for `TyCtxt`, which ensures queries
-    /// are executed instead of just returning their results.
-    #[inline(always)]
-    pub fn ensure(self) -> TyCtxtEnsure<'tcx> {
-        TyCtxtEnsure { tcx: self }
-    }
-
-    /// Returns a transparent wrapper for `TyCtxt` which uses
-    /// `span` as the location of queries performed through it.
-    #[inline(always)]
-    pub fn at(self, span: Span) -> TyCtxtAt<'tcx> {
-        TyCtxtAt { tcx: self, span }
-    }
-
-    pub fn try_mark_green(self, dep_node: &dep_graph::DepNode) -> bool {
-        self.queries.try_mark_green(self, dep_node)
-    }
-}
-
-macro_rules! query_helper_param_ty {
-    (DefId) => { impl IntoQueryParam<DefId> };
-    ($K:ty) => { $K };
-}
-
-macro_rules! query_storage {
-    ([][$K:ty, $V:ty]) => {
-        <DefaultCacheSelector as CacheSelector<$K, $V>>::Cache
-    };
-    ([storage($ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => {
-        <$ty as CacheSelector<$K, $V>>::Cache
-    };
-    ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => {
-        query_storage!([$($($modifiers)*)*][$($args)*])
-    };
-}
-
-macro_rules! define_callbacks {
-    (<$tcx:tt>
-     $($(#[$attr:meta])*
-        [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
-
-        // HACK(eddyb) this is like the `impl QueryConfig for queries::$name`
-        // below, but using type aliases instead of associated types, to bypass
-        // the limitations around normalizing under HRTB - for example, this:
-        // `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value`
-        // doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`.
-        // This is primarily used by the `provide!` macro in `rustc_metadata`.
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_keys {
-            use super::*;
-
-            $(pub type $name<$tcx> = $($K)*;)*
-        }
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_values {
-            use super::*;
-
-            $(pub type $name<$tcx> = $V;)*
-        }
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_storage {
-            use super::*;
-
-            $(pub type $name<$tcx> = query_storage!([$($modifiers)*][$($K)*, $V]);)*
-        }
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_stored {
-            use super::*;
-
-            $(pub type $name<$tcx> = <query_storage::$name<$tcx> as QueryStorage>::Stored;)*
-        }
-
-        #[derive(Default)]
-        pub struct QueryCaches<$tcx> {
-            $($(#[$attr])* pub $name: QueryCacheStore<query_storage::$name<$tcx>>,)*
-        }
-
-        impl TyCtxtEnsure<$tcx> {
-            $($(#[$attr])*
-            #[inline(always)]
-            pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
-                let key = key.into_query_param();
-                let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, |_| {});
-
-                let lookup = match cached {
-                    Ok(()) => return,
-                    Err(lookup) => lookup,
-                };
-
-                self.tcx.queries.$name(self.tcx, DUMMY_SP, key, lookup, QueryMode::Ensure);
-            })*
-        }
-
-        impl TyCtxt<$tcx> {
-            $($(#[$attr])*
-            #[inline(always)]
-            #[must_use]
-            pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx>
-            {
-                self.at(DUMMY_SP).$name(key)
-            })*
-        }
-
-        impl TyCtxtAt<$tcx> {
-            $($(#[$attr])*
-            #[inline(always)]
-            pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx>
-            {
-                let key = key.into_query_param();
-                let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, |value| {
-                    value.clone()
-                });
-
-                let lookup = match cached {
-                    Ok(value) => return value,
-                    Err(lookup) => lookup,
-                };
-
-                self.tcx.queries.$name(self.tcx, self.span, key, lookup, QueryMode::Get).unwrap()
-            })*
-        }
-
-        pub struct Providers {
-            $(pub $name: for<'tcx> fn(
-                TyCtxt<'tcx>,
-                query_keys::$name<'tcx>,
-            ) -> query_values::$name<'tcx>,)*
-        }
-
-        impl Default for Providers {
-            fn default() -> Self {
-                Providers {
-                    $($name: |_, key| bug!(
-                        "`tcx.{}({:?})` unsupported by its crate; \
-                         perhaps the `{}` query was never assigned a provider function",
-                        stringify!($name),
-                        key,
-                        stringify!($name),
-                    ),)*
-                }
-            }
-        }
-
-        impl Copy for Providers {}
-        impl Clone for Providers {
-            fn clone(&self) -> Self { *self }
-        }
-
-        pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
-            #[cfg(parallel_compiler)]
-            unsafe fn deadlock(&'tcx self, tcx: TyCtxt<'tcx>, registry: &rustc_rayon_core::Registry);
-
-            fn encode_query_results(
-                &'tcx self,
-                tcx: TyCtxt<'tcx>,
-                encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>,
-                query_result_index: &mut on_disk_cache::EncodedQueryResultIndex,
-            ) -> opaque::FileEncodeResult;
-
-            fn exec_cache_promotions(&'tcx self, tcx: TyCtxt<'tcx>);
-
-            fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool;
-
-            fn try_print_query_stack(
-                &'tcx self,
-                tcx: TyCtxt<'tcx>,
-                query: Option<QueryJobId<dep_graph::DepKind>>,
-                handler: &Handler,
-                num_frames: Option<usize>,
-            ) -> usize;
-
-            $($(#[$attr])*
-            fn $name(
-                &'tcx self,
-                tcx: TyCtxt<$tcx>,
-                span: Span,
-                key: query_keys::$name<$tcx>,
-                lookup: QueryLookup,
-                mode: QueryMode,
-            ) -> Option<query_stored::$name<$tcx>>;)*
-        }
-    };
-}
-
-// Each of these queries corresponds to a function pointer field in the
-// `Providers` struct for requesting a value of that type, and a method
-// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
-// which memoizes and does dep-graph tracking, wrapping around the actual
-// `Providers` that the driver creates (using several `rustc_*` crates).
-//
-// The result type of each query must implement `Clone`, and additionally
-// `ty::query::values::Value`, which produces an appropriate placeholder
-// (error) value if the query resulted in a query cycle.
-// Queries marked with `fatal_cycle` do not need the latter implementation,
-// as they will raise an fatal error on query cycles instead.
-
-rustc_query_append! { [define_callbacks!][<'tcx>] }
-
-mod sealed {
-    use super::{DefId, LocalDefId};
-
-    /// An analogue of the `Into` trait that's intended only for query paramaters.
-    ///
-    /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
-    /// user call `to_def_id` to convert between them everywhere else.
-    pub trait IntoQueryParam<P> {
-        fn into_query_param(self) -> P;
-    }
-
-    impl<P> IntoQueryParam<P> for P {
-        #[inline(always)]
-        fn into_query_param(self) -> P {
-            self
-        }
-    }
-
-    impl IntoQueryParam<DefId> for LocalDefId {
-        #[inline(always)]
-        fn into_query_param(self) -> DefId {
-            self.to_def_id()
-        }
-    }
-}
-
-use sealed::IntoQueryParam;
-
-impl TyCtxt<'tcx> {
-    pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
-        let def_id = def_id.into_query_param();
-        self.opt_def_kind(def_id)
-            .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
-    }
-}
-
-impl TyCtxtAt<'tcx> {
-    pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
-        let def_id = def_id.into_query_param();
-        self.opt_def_kind(def_id)
-            .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
-    }
-}
diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
deleted file mode 100644 (file)
index 6df8e64..0000000
+++ /dev/null
@@ -1,1179 +0,0 @@
-use crate::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex};
-use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
-use crate::mir::{self, interpret};
-use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
-use crate::ty::context::TyCtxt;
-use crate::ty::{self, Ty};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
-use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
-use rustc_data_structures::thin_vec::ThinVec;
-use rustc_data_structures::unhash::UnhashMap;
-use rustc_errors::Diagnostic;
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE};
-use rustc_hir::definitions::DefPathHash;
-use rustc_index::vec::{Idx, IndexVec};
-use rustc_query_system::dep_graph::DepContext;
-use rustc_query_system::query::QueryContext;
-use rustc_serialize::{
-    opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize},
-    Decodable, Decoder, Encodable, Encoder,
-};
-use rustc_session::Session;
-use rustc_span::hygiene::{
-    ExpnDataDecodeMode, ExpnDataEncodeMode, ExpnId, HygieneDecodeContext, HygieneEncodeContext,
-    SyntaxContext, SyntaxContextData,
-};
-use rustc_span::source_map::{SourceMap, StableSourceFileId};
-use rustc_span::CachingSourceMapView;
-use rustc_span::{BytePos, ExpnData, SourceFile, Span, DUMMY_SP};
-use std::collections::hash_map::Entry;
-use std::mem;
-
-const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
-
-// A normal span encoded with both location information and a `SyntaxContext`
-const TAG_FULL_SPAN: u8 = 0;
-// A partial span with no location information, encoded only with a `SyntaxContext`
-const TAG_PARTIAL_SPAN: u8 = 1;
-
-const TAG_SYNTAX_CONTEXT: u8 = 0;
-const TAG_EXPN_DATA: u8 = 1;
-
-/// Provides an interface to incremental compilation data cached from the
-/// previous compilation session. This data will eventually include the results
-/// of a few selected queries (like `typeck` and `mir_optimized`) and
-/// any diagnostics that have been emitted during a query.
-pub struct OnDiskCache<'sess> {
-    // The complete cache data in serialized form.
-    serialized_data: Vec<u8>,
-
-    // Collects all `Diagnostic`s emitted during the current compilation
-    // session.
-    current_diagnostics: Lock<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,
-
-    cnum_map: OnceCell<UnhashMap<StableCrateId, CrateNum>>,
-
-    source_map: &'sess SourceMap,
-    file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
-
-    // Caches that are populated lazily during decoding.
-    file_index_to_file: Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
-
-    // A map from dep-node to the position of the cached query result in
-    // `serialized_data`.
-    query_result_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
-
-    // A map from dep-node to the position of any associated diagnostics in
-    // `serialized_data`.
-    prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
-
-    alloc_decoding_state: AllocDecodingState,
-
-    // A map from syntax context ids to the position of their associated
-    // `SyntaxContextData`. We use a `u32` instead of a `SyntaxContext`
-    // to represent the fact that we are storing *encoded* ids. When we decode
-    // a `SyntaxContext`, a new id will be allocated from the global `HygieneData`,
-    // which will almost certainly be different than the serialized id.
-    syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
-    // A map from the `DefPathHash` of an `ExpnId` to the position
-    // of their associated `ExpnData`. Ideally, we would store a `DefId`,
-    // but we need to decode this before we've constructed a `TyCtxt` (which
-    // makes it difficult to decode a `DefId`).
-
-    // Note that these `DefPathHashes` correspond to both local and foreign
-    // `ExpnData` (e.g `ExpnData.krate` may not be `LOCAL_CRATE`). Alternatively,
-    // we could look up the `ExpnData` from the metadata of foreign crates,
-    // but it seemed easier to have `OnDiskCache` be independent of the `CStore`.
-    expn_data: FxHashMap<u32, AbsoluteBytePos>,
-    // Additional information used when decoding hygiene data.
-    hygiene_context: HygieneDecodeContext,
-    // Maps `DefPathHash`es to their `RawDefId`s from the *previous*
-    // compilation session. This is used as an initial 'guess' when
-    // we try to map a `DefPathHash` to its `DefId` in the current compilation
-    // session.
-    foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
-
-    // The *next* compilation sessison's `foreign_def_path_hashes` - at
-    // the end of our current compilation session, this will get written
-    // out to the `foreign_def_path_hashes` field of the `Footer`, which
-    // will become `foreign_def_path_hashes` of the next compilation session.
-    // This stores any `DefPathHash` that we may need to map to a `DefId`
-    // during the next compilation session.
-    latest_foreign_def_path_hashes: Lock<UnhashMap<DefPathHash, RawDefId>>,
-
-    // Caches all lookups of `DefPathHashes`, both for local and foreign
-    // definitions. A definition from the previous compilation session
-    // may no longer exist in the current compilation session, so
-    // we use `Option<DefId>` so that we can cache a lookup failure.
-    def_path_hash_to_def_id_cache: Lock<UnhashMap<DefPathHash, Option<DefId>>>,
-}
-
-// This type is used only for serialization and deserialization.
-#[derive(Encodable, Decodable)]
-struct Footer {
-    file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
-    query_result_index: EncodedQueryResultIndex,
-    diagnostics_index: EncodedQueryResultIndex,
-    // The location of all allocations.
-    interpret_alloc_index: Vec<u32>,
-    // See `OnDiskCache.syntax_contexts`
-    syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
-    // See `OnDiskCache.expn_data`
-    expn_data: FxHashMap<u32, AbsoluteBytePos>,
-    foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
-}
-
-pub type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
-type EncodedDiagnosticsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
-type EncodedDiagnostics = Vec<Diagnostic>;
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
-struct SourceFileIndex(u32);
-
-#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Encodable, Decodable)]
-pub struct AbsoluteBytePos(u32);
-
-impl AbsoluteBytePos {
-    fn new(pos: usize) -> AbsoluteBytePos {
-        debug_assert!(pos <= u32::MAX as usize);
-        AbsoluteBytePos(pos as u32)
-    }
-
-    fn to_usize(self) -> usize {
-        self.0 as usize
-    }
-}
-
-/// Represents a potentially invalid `DefId`. This is used during incremental
-/// compilation to represent a `DefId` from the *previous* compilation session,
-/// which may no longer be valid. This is used to help map a `DefPathHash`
-/// to a `DefId` in the current compilation session.
-#[derive(Encodable, Decodable, Copy, Clone, Debug)]
-crate struct RawDefId {
-    // We deliberately do not use `CrateNum` and `DefIndex`
-    // here, since a crate/index from the previous compilation
-    // session may no longer exist.
-    pub krate: u32,
-    pub index: u32,
-}
-
-/// An `EncodedSourceFileId` is the same as a `StableSourceFileId` except that
-/// the source crate is represented as a [StableCrateId] instead of as a
-/// `CrateNum`. This way `EncodedSourceFileId` can be encoded and decoded
-/// without any additional context, i.e. with a simple `opaque::Decoder` (which
-/// is the only thing available when decoding the cache's [Footer].
-#[derive(Encodable, Decodable, Clone, Debug)]
-struct EncodedSourceFileId {
-    file_name_hash: u64,
-    stable_crate_id: StableCrateId,
-}
-
-impl EncodedSourceFileId {
-    fn translate(&self, cnum_map: &UnhashMap<StableCrateId, CrateNum>) -> StableSourceFileId {
-        let cnum = cnum_map[&self.stable_crate_id];
-        StableSourceFileId { file_name_hash: self.file_name_hash, cnum }
-    }
-
-    fn new(tcx: TyCtxt<'_>, file: &SourceFile) -> EncodedSourceFileId {
-        let source_file_id = StableSourceFileId::new(file);
-        EncodedSourceFileId {
-            file_name_hash: source_file_id.file_name_hash,
-            stable_crate_id: tcx.stable_crate_id(source_file_id.cnum),
-        }
-    }
-}
-
-impl<'sess> OnDiskCache<'sess> {
-    /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
-    pub fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> Self {
-        debug_assert!(sess.opts.incremental.is_some());
-
-        // Wrap in a scope so we can borrow `data`.
-        let footer: Footer = {
-            let mut decoder = opaque::Decoder::new(&data[..], start_pos);
-
-            // Decode the *position* of the footer, which can be found in the
-            // last 8 bytes of the file.
-            decoder.set_position(data.len() - IntEncodedWithFixedSize::ENCODED_SIZE);
-            let footer_pos = IntEncodedWithFixedSize::decode(&mut decoder)
-                .expect("error while trying to decode footer position")
-                .0 as usize;
-
-            // Decode the file footer, which contains all the lookup tables, etc.
-            decoder.set_position(footer_pos);
-
-            decode_tagged(&mut decoder, TAG_FILE_FOOTER)
-                .expect("error while trying to decode footer position")
-        };
-
-        Self {
-            serialized_data: data,
-            file_index_to_stable_id: footer.file_index_to_stable_id,
-            file_index_to_file: Default::default(),
-            cnum_map: OnceCell::new(),
-            source_map: sess.source_map(),
-            current_diagnostics: Default::default(),
-            query_result_index: footer.query_result_index.into_iter().collect(),
-            prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(),
-            alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index),
-            syntax_contexts: footer.syntax_contexts,
-            expn_data: footer.expn_data,
-            hygiene_context: Default::default(),
-            foreign_def_path_hashes: footer.foreign_def_path_hashes,
-            latest_foreign_def_path_hashes: Default::default(),
-            def_path_hash_to_def_id_cache: Default::default(),
-        }
-    }
-
-    pub fn new_empty(source_map: &'sess SourceMap) -> Self {
-        Self {
-            serialized_data: Vec::new(),
-            file_index_to_stable_id: Default::default(),
-            file_index_to_file: Default::default(),
-            cnum_map: OnceCell::new(),
-            source_map,
-            current_diagnostics: Default::default(),
-            query_result_index: Default::default(),
-            prev_diagnostics_index: Default::default(),
-            alloc_decoding_state: AllocDecodingState::new(Vec::new()),
-            syntax_contexts: FxHashMap::default(),
-            expn_data: FxHashMap::default(),
-            hygiene_context: Default::default(),
-            foreign_def_path_hashes: Default::default(),
-            latest_foreign_def_path_hashes: Default::default(),
-            def_path_hash_to_def_id_cache: Default::default(),
-        }
-    }
-
-    pub fn serialize<'tcx>(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        encoder: &mut FileEncoder,
-    ) -> FileEncodeResult {
-        // Serializing the `DepGraph` should not modify it.
-        tcx.dep_graph.with_ignore(|| {
-            // Allocate `SourceFileIndex`es.
-            let (file_to_file_index, file_index_to_stable_id) = {
-                let files = tcx.sess.source_map().files();
-                let mut file_to_file_index =
-                    FxHashMap::with_capacity_and_hasher(files.len(), Default::default());
-                let mut file_index_to_stable_id =
-                    FxHashMap::with_capacity_and_hasher(files.len(), Default::default());
-
-                for (index, file) in files.iter().enumerate() {
-                    let index = SourceFileIndex(index as u32);
-                    let file_ptr: *const SourceFile = &**file as *const _;
-                    file_to_file_index.insert(file_ptr, index);
-                    let source_file_id = EncodedSourceFileId::new(tcx, &file);
-                    file_index_to_stable_id.insert(index, source_file_id);
-                }
-
-                (file_to_file_index, file_index_to_stable_id)
-            };
-
-            // Register any dep nodes that we reused from the previous session,
-            // but didn't `DepNode::construct` in this session. This ensures
-            // that their `DefPathHash` to `RawDefId` mappings are registered
-            // in 'latest_foreign_def_path_hashes' if necessary, since that
-            // normally happens in `DepNode::construct`.
-            tcx.dep_graph.register_reused_dep_nodes(tcx);
-
-            // Load everything into memory so we can write it out to the on-disk
-            // cache. The vast majority of cacheable query results should already
-            // be in memory, so this should be a cheap operation.
-            // Do this *before* we clone 'latest_foreign_def_path_hashes', since
-            // loading existing queries may cause us to create new DepNodes, which
-            // may in turn end up invoking `store_foreign_def_id_hash`
-            tcx.queries.exec_cache_promotions(tcx);
-
-            let latest_foreign_def_path_hashes = self.latest_foreign_def_path_hashes.lock().clone();
-            let hygiene_encode_context = HygieneEncodeContext::default();
-
-            let mut encoder = CacheEncoder {
-                tcx,
-                encoder,
-                type_shorthands: Default::default(),
-                predicate_shorthands: Default::default(),
-                interpret_allocs: Default::default(),
-                source_map: CachingSourceMapView::new(tcx.sess.source_map()),
-                file_to_file_index,
-                hygiene_context: &hygiene_encode_context,
-                latest_foreign_def_path_hashes,
-            };
-
-            // Encode query results.
-            let mut query_result_index = EncodedQueryResultIndex::new();
-
-            tcx.sess.time("encode_query_results", || -> FileEncodeResult {
-                let enc = &mut encoder;
-                let qri = &mut query_result_index;
-                tcx.queries.encode_query_results(tcx, enc, qri)
-            })?;
-
-            // Encode diagnostics.
-            let diagnostics_index: EncodedDiagnosticsIndex = self
-                .current_diagnostics
-                .borrow()
-                .iter()
-                .map(
-                    |(dep_node_index, diagnostics)| -> Result<_, <FileEncoder as Encoder>::Error> {
-                        let pos = AbsoluteBytePos::new(encoder.position());
-                        // Let's make sure we get the expected type here.
-                        let diagnostics: &EncodedDiagnostics = diagnostics;
-                        let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
-                        encoder.encode_tagged(dep_node_index, diagnostics)?;
-
-                        Ok((dep_node_index, pos))
-                    },
-                )
-                .collect::<Result<_, _>>()?;
-
-            let interpret_alloc_index = {
-                let mut interpret_alloc_index = Vec::new();
-                let mut n = 0;
-                loop {
-                    let new_n = encoder.interpret_allocs.len();
-                    // If we have found new IDs, serialize those too.
-                    if n == new_n {
-                        // Otherwise, abort.
-                        break;
-                    }
-                    interpret_alloc_index.reserve(new_n - n);
-                    for idx in n..new_n {
-                        let id = encoder.interpret_allocs[idx];
-                        let pos = encoder.position() as u32;
-                        interpret_alloc_index.push(pos);
-                        interpret::specialized_encode_alloc_id(&mut encoder, tcx, id)?;
-                    }
-                    n = new_n;
-                }
-                interpret_alloc_index
-            };
-
-            let mut syntax_contexts = FxHashMap::default();
-            let mut expn_ids = FxHashMap::default();
-
-            // Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current
-            // session.
-
-            hygiene_encode_context.encode(
-                &mut encoder,
-                |encoder, index, ctxt_data| -> FileEncodeResult {
-                    let pos = AbsoluteBytePos::new(encoder.position());
-                    encoder.encode_tagged(TAG_SYNTAX_CONTEXT, ctxt_data)?;
-                    syntax_contexts.insert(index, pos);
-                    Ok(())
-                },
-                |encoder, index, expn_data| -> FileEncodeResult {
-                    let pos = AbsoluteBytePos::new(encoder.position());
-                    encoder.encode_tagged(TAG_EXPN_DATA, expn_data)?;
-                    expn_ids.insert(index, pos);
-                    Ok(())
-                },
-            )?;
-
-            let foreign_def_path_hashes =
-                std::mem::take(&mut encoder.latest_foreign_def_path_hashes);
-
-            // `Encode the file footer.
-            let footer_pos = encoder.position() as u64;
-            encoder.encode_tagged(
-                TAG_FILE_FOOTER,
-                &Footer {
-                    file_index_to_stable_id,
-                    query_result_index,
-                    diagnostics_index,
-                    interpret_alloc_index,
-                    syntax_contexts,
-                    expn_data: expn_ids,
-                    foreign_def_path_hashes,
-                },
-            )?;
-
-            // Encode the position of the footer as the last 8 bytes of the
-            // file so we know where to look for it.
-            IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?;
-
-            // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
-            // of the footer must be the last thing in the data stream.
-
-            Ok(())
-        })
-    }
-
-    /// Loads a diagnostic emitted during the previous compilation session.
-    pub fn load_diagnostics(
-        &self,
-        tcx: TyCtxt<'_>,
-        dep_node_index: SerializedDepNodeIndex,
-    ) -> Vec<Diagnostic> {
-        let diagnostics: Option<EncodedDiagnostics> =
-            self.load_indexed(tcx, dep_node_index, &self.prev_diagnostics_index, "diagnostics");
-
-        diagnostics.unwrap_or_default()
-    }
-
-    /// Stores a diagnostic emitted during the current compilation session.
-    /// Anything stored like this will be available via `load_diagnostics` in
-    /// the next compilation session.
-    #[inline(never)]
-    #[cold]
-    pub fn store_diagnostics(
-        &self,
-        dep_node_index: DepNodeIndex,
-        diagnostics: ThinVec<Diagnostic>,
-    ) {
-        let mut current_diagnostics = self.current_diagnostics.borrow_mut();
-        let prev = current_diagnostics.insert(dep_node_index, diagnostics.into());
-        debug_assert!(prev.is_none());
-    }
-
-    fn get_raw_def_id(&self, hash: &DefPathHash) -> Option<RawDefId> {
-        self.foreign_def_path_hashes.get(hash).copied()
-    }
-
-    fn try_remap_cnum(&self, tcx: TyCtxt<'_>, stable_crate_id: StableCrateId) -> Option<CrateNum> {
-        let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx));
-        debug!("try_remap_cnum({:?}): cnum_map={:?}", stable_crate_id, cnum_map);
-
-        cnum_map.get(&stable_crate_id).copied()
-    }
-
-    pub(crate) fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash) {
-        // We may overwrite an existing entry, but it will have the same value,
-        // so it's fine
-        self.latest_foreign_def_path_hashes
-            .lock()
-            .insert(hash, RawDefId { krate: def_id.krate.as_u32(), index: def_id.index.as_u32() });
-    }
-
-    /// If the given `dep_node`'s hash still exists in the current compilation,
-    /// and its current `DefId` is foreign, calls `store_foreign_def_id` with it.
-    ///
-    /// Normally, `store_foreign_def_id_hash` can be called directly by
-    /// the dependency graph when we construct a `DepNode`. However,
-    /// when we re-use a deserialized `DepNode` from the previous compilation
-    /// session, we only have the `DefPathHash` available. This method is used
-    /// to that any `DepNode` that we re-use has a `DefPathHash` -> `RawId` written
-    /// out for usage in the next compilation session.
-    pub fn register_reused_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode) {
-        // For reused dep nodes, we only need to store the mapping if the node
-        // is one whose query key we can reconstruct from the hash. We use the
-        // mapping to aid that reconstruction in the next session. While we also
-        // use it to decode `DefId`s we encoded in the cache as `DefPathHashes`,
-        // they're already registered during `DefId` encoding.
-        if dep_node.kind.can_reconstruct_query_key() {
-            let hash = DefPathHash(dep_node.hash.into());
-
-            // We can't simply copy the `RawDefId` from `foreign_def_path_hashes` to
-            // `latest_foreign_def_path_hashes`, since the `RawDefId` might have
-            // changed in the current compilation session (e.g. we've added/removed crates,
-            // or added/removed definitions before/after the target definition).
-            if let Some(def_id) = self.def_path_hash_to_def_id(tcx, hash) {
-                if !def_id.is_local() {
-                    self.store_foreign_def_id_hash(def_id, hash);
-                }
-            }
-        }
-    }
-
-    /// Returns the cached query result if there is something in the cache for
-    /// the given `SerializedDepNodeIndex`; otherwise returns `None`.
-    pub fn try_load_query_result<'tcx, T>(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        dep_node_index: SerializedDepNodeIndex,
-    ) -> Option<T>
-    where
-        T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
-    {
-        self.load_indexed(tcx, dep_node_index, &self.query_result_index, "query result")
-    }
-
-    /// Stores a diagnostic emitted during computation of an anonymous query.
-    /// Since many anonymous queries can share the same `DepNode`, we aggregate
-    /// them -- as opposed to regular queries where we assume that there is a
-    /// 1:1 relationship between query-key and `DepNode`.
-    #[inline(never)]
-    #[cold]
-    pub fn store_diagnostics_for_anon_node(
-        &self,
-        dep_node_index: DepNodeIndex,
-        diagnostics: ThinVec<Diagnostic>,
-    ) {
-        let mut current_diagnostics = self.current_diagnostics.borrow_mut();
-
-        let x = current_diagnostics.entry(dep_node_index).or_default();
-
-        x.extend(Into::<Vec<_>>::into(diagnostics));
-    }
-
-    fn load_indexed<'tcx, T>(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        dep_node_index: SerializedDepNodeIndex,
-        index: &FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
-        debug_tag: &'static str,
-    ) -> Option<T>
-    where
-        T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
-    {
-        let pos = index.get(&dep_node_index).cloned()?;
-
-        self.with_decoder(tcx, pos, |decoder| match decode_tagged(decoder, dep_node_index) {
-            Ok(v) => Some(v),
-            Err(e) => bug!("could not decode cached {}: {}", debug_tag, e),
-        })
-    }
-
-    fn with_decoder<'a, 'tcx, T, F: FnOnce(&mut CacheDecoder<'sess, 'tcx>) -> T>(
-        &'sess self,
-        tcx: TyCtxt<'tcx>,
-        pos: AbsoluteBytePos,
-        f: F,
-    ) -> T
-    where
-        T: Decodable<CacheDecoder<'a, 'tcx>>,
-    {
-        let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx));
-
-        let mut decoder = CacheDecoder {
-            tcx,
-            opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()),
-            source_map: self.source_map,
-            cnum_map,
-            file_index_to_file: &self.file_index_to_file,
-            file_index_to_stable_id: &self.file_index_to_stable_id,
-            alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
-            syntax_contexts: &self.syntax_contexts,
-            expn_data: &self.expn_data,
-            hygiene_context: &self.hygiene_context,
-        };
-        f(&mut decoder)
-    }
-
-    // This function builds mapping from previous-session-`CrateNum` to
-    // current-session-`CrateNum`. There might be `CrateNum`s from the previous
-    // `Session` that don't occur in the current one. For these, the mapping
-    // maps to None.
-    fn compute_cnum_map(tcx: TyCtxt<'_>) -> UnhashMap<StableCrateId, CrateNum> {
-        tcx.dep_graph.with_ignore(|| {
-            tcx.all_crate_nums(())
-                .iter()
-                .chain(std::iter::once(&LOCAL_CRATE))
-                .map(|&cnum| {
-                    let hash = tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
-                    (hash, cnum)
-                })
-                .collect()
-        })
-    }
-
-    /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
-    /// session, if it still exists. This is used during incremental compilation to
-    /// turn a deserialized `DefPathHash` into its current `DefId`.
-    pub(crate) fn def_path_hash_to_def_id(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        hash: DefPathHash,
-    ) -> Option<DefId> {
-        let mut cache = self.def_path_hash_to_def_id_cache.lock();
-        match cache.entry(hash) {
-            Entry::Occupied(e) => *e.get(),
-            Entry::Vacant(e) => {
-                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) {
-                    let def_id = def_id.to_def_id();
-                    e.insert(Some(def_id));
-                    return Some(def_id);
-                }
-                // This `raw_def_id` represents the `DefId` of this `DefPathHash` in
-                // the *previous* compliation session. The `DefPathHash` includes the
-                // owning crate, so if the corresponding definition still exists in the
-                // current compilation session, the crate is guaranteed to be the same
-                // (otherwise, we would compute a different `DefPathHash`).
-                let raw_def_id = self.get_raw_def_id(&hash)?;
-                debug!("def_path_hash_to_def_id({:?}): raw_def_id = {:?}", hash, raw_def_id);
-                // If the owning crate no longer exists, the corresponding definition definitely
-                // no longer exists.
-                let krate = self.try_remap_cnum(tcx, hash.stable_crate_id())?;
-                debug!("def_path_hash_to_def_id({:?}): krate = {:?}", hash, krate);
-                // If our `DefPathHash` corresponded to a definition in the local crate,
-                // we should have either found it in `local_def_path_hash_to_def_id`, or
-                // never attempted to load it in the first place. Any query result or `DepNode`
-                // that references a local `DefId` should depend on some HIR-related `DepNode`.
-                // If a local definition is removed/modified such that its old `DefPathHash`
-                // no longer has a corresponding definition, that HIR-related `DepNode` should
-                // end up red. This should prevent us from ever calling
-                // `tcx.def_path_hash_to_def_id`, since we'll end up recomputing any
-                // queries involved.
-                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);
-                debug!("def_path_to_def_id({:?}): opt_def_id = {:?}", hash, opt_def_id);
-                e.insert(opt_def_id);
-                opt_def_id
-            }
-        }
-    }
-}
-
-//- DECODING -------------------------------------------------------------------
-
-/// A decoder that can read from the incremental compilation cache. It is similar to the one
-/// we use for crate metadata decoding in that it can rebase spans and eventually
-/// will also handle things that contain `Ty` instances.
-pub struct CacheDecoder<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    opaque: opaque::Decoder<'a>,
-    source_map: &'a SourceMap,
-    cnum_map: &'a UnhashMap<StableCrateId, CrateNum>,
-    file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
-    file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>,
-    alloc_decoding_session: AllocDecodingSession<'a>,
-    syntax_contexts: &'a FxHashMap<u32, AbsoluteBytePos>,
-    expn_data: &'a FxHashMap<u32, AbsoluteBytePos>,
-    hygiene_context: &'a HygieneDecodeContext,
-}
-
-impl<'a, 'tcx> CacheDecoder<'a, 'tcx> {
-    fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc<SourceFile> {
-        let CacheDecoder {
-            ref file_index_to_file,
-            ref file_index_to_stable_id,
-            ref source_map,
-            ref cnum_map,
-            ..
-        } = *self;
-
-        file_index_to_file
-            .borrow_mut()
-            .entry(index)
-            .or_insert_with(|| {
-                let stable_id = file_index_to_stable_id[&index].translate(cnum_map);
-                source_map
-                    .source_file_by_stable_id(stable_id)
-                    .expect("failed to lookup `SourceFile` in new context")
-            })
-            .clone()
-    }
-}
-
-trait DecoderWithPosition: Decoder {
-    fn position(&self) -> usize;
-}
-
-impl<'a> DecoderWithPosition for opaque::Decoder<'a> {
-    fn position(&self) -> usize {
-        self.position()
-    }
-}
-
-impl<'a, 'tcx> DecoderWithPosition for CacheDecoder<'a, 'tcx> {
-    fn position(&self) -> usize {
-        self.opaque.position()
-    }
-}
-
-// Decodes something that was encoded with `encode_tagged()` and verify that the
-// tag matches and the correct amount of bytes was read.
-fn decode_tagged<D, T, V>(decoder: &mut D, expected_tag: T) -> Result<V, D::Error>
-where
-    T: Decodable<D> + Eq + std::fmt::Debug,
-    V: Decodable<D>,
-    D: DecoderWithPosition,
-{
-    let start_pos = decoder.position();
-
-    let actual_tag = T::decode(decoder)?;
-    assert_eq!(actual_tag, expected_tag);
-    let value = V::decode(decoder)?;
-    let end_pos = decoder.position();
-
-    let expected_len: u64 = Decodable::decode(decoder)?;
-    assert_eq!((end_pos - start_pos) as u64, expected_len);
-
-    Ok(value)
-}
-
-impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
-    const CLEAR_CROSS_CRATE: bool = false;
-
-    #[inline]
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    #[inline]
-    fn position(&self) -> usize {
-        self.opaque.position()
-    }
-
-    #[inline]
-    fn peek_byte(&self) -> u8 {
-        self.opaque.data[self.opaque.position()]
-    }
-
-    fn cached_ty_for_shorthand<F>(
-        &mut self,
-        shorthand: usize,
-        or_insert_with: F,
-    ) -> Result<Ty<'tcx>, Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>,
-    {
-        let tcx = self.tcx();
-
-        let cache_key = ty::CReaderCacheKey { cnum: None, pos: shorthand };
-
-        if let Some(&ty) = tcx.ty_rcache.borrow().get(&cache_key) {
-            return Ok(ty);
-        }
-
-        let ty = or_insert_with(self)?;
-        // This may overwrite the entry, but it should overwrite with the same value.
-        tcx.ty_rcache.borrow_mut().insert_same(cache_key, ty);
-        Ok(ty)
-    }
-
-    fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
-    where
-        F: FnOnce(&mut Self) -> R,
-    {
-        debug_assert!(pos < self.opaque.data.len());
-
-        let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
-        let old_opaque = mem::replace(&mut self.opaque, new_opaque);
-        let r = f(self);
-        self.opaque = old_opaque;
-        r
-    }
-
-    fn decode_alloc_id(&mut self) -> Result<interpret::AllocId, Self::Error> {
-        let alloc_decoding_session = self.alloc_decoding_session;
-        alloc_decoding_session.decode_alloc_id(self)
-    }
-}
-
-crate::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
-
-// This ensures that the `Decodable<opaque::Decoder>::decode` specialization for `Vec<u8>` is used
-// when a `CacheDecoder` is passed to `Decodable::decode`. Unfortunately, we have to manually opt
-// into specializations this way, given how `CacheDecoder` and the decoding traits currently work.
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Vec<u8> {
-    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
-        Decodable::decode(&mut d.opaque)
-    }
-}
-
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for SyntaxContext {
-    fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
-        let syntax_contexts = decoder.syntax_contexts;
-        rustc_span::hygiene::decode_syntax_context(decoder, decoder.hygiene_context, |this, id| {
-            // This closure is invoked if we haven't already decoded the data for the `SyntaxContext` we are deserializing.
-            // We look up the position of the associated `SyntaxData` and decode it.
-            let pos = syntax_contexts.get(&id).unwrap();
-            this.with_position(pos.to_usize(), |decoder| {
-                let data: SyntaxContextData = decode_tagged(decoder, TAG_SYNTAX_CONTEXT)?;
-                Ok(data)
-            })
-        })
-    }
-}
-
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
-    fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
-        let expn_data = decoder.expn_data;
-        rustc_span::hygiene::decode_expn_id(
-            decoder,
-            ExpnDataDecodeMode::incr_comp(decoder.hygiene_context),
-            |this, index| {
-                // This closure is invoked if we haven't already decoded the data for the `ExpnId` we are deserializing.
-                // We look up the position of the associated `ExpnData` and decode it.
-                let pos = expn_data
-                    .get(&index)
-                    .unwrap_or_else(|| panic!("Bad index {:?} (map {:?})", index, expn_data));
-
-                this.with_position(pos.to_usize(), |decoder| {
-                    let data: ExpnData = decode_tagged(decoder, TAG_EXPN_DATA)?;
-                    Ok(data)
-                })
-            },
-        )
-    }
-}
-
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
-    fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
-        let tag: u8 = Decodable::decode(decoder)?;
-
-        if tag == TAG_PARTIAL_SPAN {
-            let ctxt = SyntaxContext::decode(decoder)?;
-            return Ok(DUMMY_SP.with_ctxt(ctxt));
-        } else {
-            debug_assert_eq!(tag, TAG_FULL_SPAN);
-        }
-
-        let file_lo_index = SourceFileIndex::decode(decoder)?;
-        let line_lo = usize::decode(decoder)?;
-        let col_lo = BytePos::decode(decoder)?;
-        let len = BytePos::decode(decoder)?;
-        let ctxt = SyntaxContext::decode(decoder)?;
-
-        let file_lo = decoder.file_index_to_file(file_lo_index);
-        let lo = file_lo.lines[line_lo - 1] + col_lo;
-        let hi = lo + len;
-
-        Ok(Span::new(lo, hi, ctxt))
-    }
-}
-
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for CrateNum {
-    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
-        let stable_id = StableCrateId::decode(d)?;
-        let cnum = d.cnum_map[&stable_id];
-        Ok(cnum)
-    }
-}
-
-// This impl makes sure that we get a runtime error when we try decode a
-// `DefIndex` that is not contained in a `DefId`. Such a case would be problematic
-// because we would not know how to transform the `DefIndex` to the current
-// context.
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefIndex {
-    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<DefIndex, String> {
-        Err(d.error("trying to decode `DefIndex` outside the context of a `DefId`"))
-    }
-}
-
-// Both the `CrateNum` and the `DefIndex` of a `DefId` can change in between two
-// compilation sessions. We use the `DefPathHash`, which is stable across
-// sessions, to map the old `DefId` to the new one.
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefId {
-    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
-        // Load the `DefPathHash` which is was we encoded the `DefId` as.
-        let def_path_hash = DefPathHash::decode(d)?;
-
-        // Using the `DefPathHash`, we can lookup the new `DefId`.
-        // Subtle: We only encode a `DefId` as part of a query result.
-        // If we get to this point, then all of the query inputs were green,
-        // which means that the definition with this hash is guaranteed to
-        // still exist in the current compilation session.
-        Ok(d.tcx()
-            .on_disk_cache
-            .as_ref()
-            .unwrap()
-            .def_path_hash_to_def_id(d.tcx(), def_path_hash)
-            .unwrap())
-    }
-}
-
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx FxHashSet<LocalDefId> {
-    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
-        RefDecodable::decode(d)
-    }
-}
-
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
-    for &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>>
-{
-    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
-        RefDecodable::decode(d)
-    }
-}
-
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
-    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
-        RefDecodable::decode(d)
-    }
-}
-
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
-    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
-        RefDecodable::decode(d)
-    }
-}
-
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [rustc_ast::InlineAsmTemplatePiece] {
-    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
-        RefDecodable::decode(d)
-    }
-}
-
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [Span] {
-    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
-        RefDecodable::decode(d)
-    }
-}
-
-//- ENCODING -------------------------------------------------------------------
-
-pub trait OpaqueEncoder: Encoder {
-    fn position(&self) -> usize;
-}
-
-impl OpaqueEncoder for FileEncoder {
-    #[inline]
-    fn position(&self) -> usize {
-        FileEncoder::position(self)
-    }
-}
-
-/// An encoder that can write to the incremental compilation cache.
-pub struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> {
-    tcx: TyCtxt<'tcx>,
-    encoder: &'a mut E,
-    type_shorthands: FxHashMap<Ty<'tcx>, usize>,
-    predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
-    interpret_allocs: FxIndexSet<interpret::AllocId>,
-    source_map: CachingSourceMapView<'tcx>,
-    file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>,
-    hygiene_context: &'a HygieneEncodeContext,
-    latest_foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
-}
-
-impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E>
-where
-    E: 'a + OpaqueEncoder,
-{
-    fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex {
-        self.file_to_file_index[&(&*source_file as *const SourceFile)]
-    }
-
-    /// Encode something with additional information that allows to do some
-    /// sanity checks when decoding the data again. This method will first
-    /// encode the specified tag, then the given value, then the number of
-    /// bytes taken up by tag and value. On decoding, we can then verify that
-    /// we get the expected tag and read the expected number of bytes.
-    fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(
-        &mut self,
-        tag: T,
-        value: &V,
-    ) -> Result<(), E::Error> {
-        let start_pos = self.position();
-
-        tag.encode(self)?;
-        value.encode(self)?;
-
-        let end_pos = self.position();
-        ((end_pos - start_pos) as u64).encode(self)
-    }
-}
-
-impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for SyntaxContext
-where
-    E: 'a + OpaqueEncoder,
-{
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
-        rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_context, s)
-    }
-}
-
-impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for ExpnId
-where
-    E: 'a + OpaqueEncoder,
-{
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
-        rustc_span::hygiene::raw_encode_expn_id(
-            *self,
-            s.hygiene_context,
-            ExpnDataEncodeMode::IncrComp,
-            s,
-        )
-    }
-}
-
-impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for Span
-where
-    E: 'a + OpaqueEncoder,
-{
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
-        let span_data = self.data();
-        if self.is_dummy() {
-            TAG_PARTIAL_SPAN.encode(s)?;
-            return span_data.ctxt.encode(s);
-        }
-
-        let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo);
-        let partial_span = match &pos {
-            Some((file_lo, _, _)) => !file_lo.contains(span_data.hi),
-            None => true,
-        };
-
-        if partial_span {
-            TAG_PARTIAL_SPAN.encode(s)?;
-            return span_data.ctxt.encode(s);
-        }
-
-        let (file_lo, line_lo, col_lo) = pos.unwrap();
-
-        let len = span_data.hi - span_data.lo;
-
-        let source_file_index = s.source_file_index(file_lo);
-
-        TAG_FULL_SPAN.encode(s)?;
-        source_file_index.encode(s)?;
-        line_lo.encode(s)?;
-        col_lo.encode(s)?;
-        len.encode(s)?;
-        span_data.ctxt.encode(s)
-    }
-}
-
-impl<'a, 'tcx, E> TyEncoder<'tcx> for CacheEncoder<'a, 'tcx, E>
-where
-    E: 'a + OpaqueEncoder,
-{
-    const CLEAR_CROSS_CRATE: bool = false;
-
-    fn position(&self) -> usize {
-        self.encoder.position()
-    }
-    fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
-        &mut self.type_shorthands
-    }
-    fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
-        &mut self.predicate_shorthands
-    }
-    fn encode_alloc_id(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
-        let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
-
-        index.encode(self)
-    }
-}
-
-impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for CrateNum
-where
-    E: 'a + OpaqueEncoder,
-{
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
-        s.tcx.stable_crate_id(*self).encode(s)
-    }
-}
-
-impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefId
-where
-    E: 'a + OpaqueEncoder,
-{
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
-        let def_path_hash = s.tcx.def_path_hash(*self);
-        // Store additional information when we encode a foreign `DefId`,
-        // so that we can map its `DefPathHash` back to a `DefId` in the next
-        // compilation session.
-        if !self.is_local() {
-            s.latest_foreign_def_path_hashes.insert(
-                def_path_hash,
-                RawDefId { krate: self.krate.as_u32(), index: self.index.as_u32() },
-            );
-        }
-        def_path_hash.encode(s)
-    }
-}
-
-impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefIndex
-where
-    E: 'a + OpaqueEncoder,
-{
-    fn encode(&self, _: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
-        bug!("encoding `DefIndex` without context");
-    }
-}
-
-macro_rules! encoder_methods {
-    ($($name:ident($ty:ty);)*) => {
-        #[inline]
-        $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
-            self.encoder.$name(value)
-        })*
-    }
-}
-
-impl<'a, 'tcx, E> Encoder for CacheEncoder<'a, 'tcx, E>
-where
-    E: 'a + OpaqueEncoder,
-{
-    type Error = E::Error;
-
-    #[inline]
-    fn emit_unit(&mut self) -> Result<(), Self::Error> {
-        Ok(())
-    }
-
-    encoder_methods! {
-        emit_usize(usize);
-        emit_u128(u128);
-        emit_u64(u64);
-        emit_u32(u32);
-        emit_u16(u16);
-        emit_u8(u8);
-
-        emit_isize(isize);
-        emit_i128(i128);
-        emit_i64(i64);
-        emit_i32(i32);
-        emit_i16(i16);
-        emit_i8(i8);
-
-        emit_bool(bool);
-        emit_f64(f64);
-        emit_f32(f32);
-        emit_char(char);
-        emit_str(&str);
-        emit_raw_bytes(&[u8]);
-    }
-}
-
-// This ensures that the `Encodable<opaque::FileEncoder>::encode` specialization for byte slices
-// is used when a `CacheEncoder` having an `opaque::FileEncoder` is passed to `Encodable::encode`.
-// Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder`
-// and the encoding traits currently work.
-impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx, FileEncoder>> for [u8] {
-    fn encode(&self, e: &mut CacheEncoder<'a, 'tcx, FileEncoder>) -> FileEncodeResult {
-        self.encode(e.encoder)
-    }
-}
-
-pub fn encode_query_results<'a, 'tcx, CTX, Q>(
-    tcx: CTX,
-    encoder: &mut CacheEncoder<'a, 'tcx, FileEncoder>,
-    query_result_index: &mut EncodedQueryResultIndex,
-) -> FileEncodeResult
-where
-    CTX: QueryContext + 'tcx,
-    Q: super::QueryDescription<CTX> + super::QueryAccessors<CTX>,
-    Q::Value: Encodable<CacheEncoder<'a, 'tcx, FileEncoder>>,
-{
-    let _timer = tcx
-        .dep_context()
-        .profiler()
-        .extra_verbose_generic_activity("encode_query_results_for", std::any::type_name::<Q>());
-
-    assert!(Q::query_state(tcx).all_inactive());
-    let cache = Q::query_cache(tcx);
-    let mut res = Ok(());
-    cache.iter_results(&mut |key, value, dep_node| {
-        if res.is_err() {
-            return;
-        }
-        if Q::cache_on_disk(tcx, &key, Some(value)) {
-            let dep_node = SerializedDepNodeIndex::new(dep_node.index());
-
-            // Record position of the cache entry.
-            query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.encoder.position())));
-
-            // Encode the type check tables with the `SerializedDepNodeIndex`
-            // as tag.
-            match encoder.encode_tagged(dep_node, value) {
-                Ok(()) => {}
-                Err(e) => {
-                    res = Err(e);
-                }
-            }
-        }
-    });
-
-    res
-}
index 3f426b13688fe94302ca6ffd98c917d5913f0250..a4c36be21992b36b56743a1ca6a14edd7ad7180b 100644 (file)
@@ -595,9 +595,12 @@ fn check_const_value_eq<R: TypeRelation<'tcx>>(
         (ConstValue::Scalar(Scalar::Int(a_val)), ConstValue::Scalar(Scalar::Int(b_val))) => {
             a_val == b_val
         }
-        (ConstValue::Scalar(Scalar::Ptr(a_val)), ConstValue::Scalar(Scalar::Ptr(b_val))) => {
+        (
+            ConstValue::Scalar(Scalar::Ptr(a_val, _a_size)),
+            ConstValue::Scalar(Scalar::Ptr(b_val, _b_size)),
+        ) => {
             a_val == b_val
-                || match (tcx.global_alloc(a_val.alloc_id), tcx.global_alloc(b_val.alloc_id)) {
+                || match (tcx.global_alloc(a_val.provenance), tcx.global_alloc(b_val.provenance)) {
                     (GlobalAlloc::Function(a_instance), GlobalAlloc::Function(b_instance)) => {
                         a_instance == b_instance
                     }
index 1d9ff512288db9b05e140f6f4d224fa35b60f36a..6a7e349819afdc5fbf57512e2151fcb446141079 100644 (file)
@@ -5,7 +5,6 @@
 use self::TyKind::*;
 
 use crate::infer::canonical::Canonical;
-use crate::ty::fold::BoundVarsCollector;
 use crate::ty::fold::ValidateBoundVars;
 use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
 use crate::ty::InferTy::{self, *};
@@ -966,17 +965,10 @@ where
     /// binder. This is commonly used to 'inject' a value T into a
     /// different binding level.
     pub fn dummy(value: T) -> Binder<'tcx, T> {
-        debug_assert!(!value.has_escaping_bound_vars());
+        assert!(!value.has_escaping_bound_vars());
         Binder(value, ty::List::empty())
     }
 
-    /// Wraps `value` in a binder, binding higher-ranked vars (if any).
-    pub fn bind(value: T, tcx: TyCtxt<'tcx>) -> Binder<'tcx, T> {
-        let mut collector = BoundVarsCollector::new();
-        value.visit_with(&mut collector);
-        Binder(value, collector.into_vars(tcx))
-    }
-
     pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
         if cfg!(debug_assertions) {
             let mut validator = ValidateBoundVars::new(vars);
@@ -1370,8 +1362,8 @@ pub type Region<'tcx> = &'tcx RegionKind;
 /// happen, you can use `leak_check`. This is more clearly explained
 /// by the [rustc dev guide].
 ///
-/// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
-/// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
+/// [1]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
+/// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
 /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
 #[derive(Clone, PartialEq, Eq, Hash, Copy, TyEncodable, TyDecodable, PartialOrd, Ord)]
 pub enum RegionKind {
@@ -2189,7 +2181,7 @@ impl<'tcx> TyS<'tcx> {
 /// a miscompilation or unsoundness.
 ///
 /// When in doubt, use `VarianceDiagInfo::default()`
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub enum VarianceDiagInfo<'tcx> {
     /// No additional information - this is the default.
     /// We will not add any additional information to error messages.
@@ -2208,7 +2200,7 @@ pub enum VarianceDiagInfo<'tcx> {
     },
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub enum VarianceDiagMutKind {
     /// A mutable raw pointer (`*mut T`)
     RawPtr,
index 79166472acf0430955698b00aa6820e2e7e1a6b4..ae86f51e6ac3fd4bdc045e1f6df4d7e26216868f 100644 (file)
@@ -215,7 +215,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
     // Traits defined in the current crate can't have impls in upstream
     // crates, so we don't bother querying the cstore.
     if !trait_id.is_local() {
-        for &cnum in tcx.crates().iter() {
+        for &cnum in tcx.crates(()).iter() {
             for &(impl_def_id, simplified_self_ty) in
                 tcx.implementations_of_trait((cnum, trait_id)).iter()
             {
index 7bf69b9e637e9a41334728e7c2373e1d7aacca45..485be4c9987bd073a965567ae955e6e116ed8782 100644 (file)
@@ -7,7 +7,7 @@ use crate::ty::layout::IntegerExt;
 use crate::ty::query::TyCtxtAt;
 use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
 use crate::ty::TyKind::*;
-use crate::ty::{self, DefIdTree, List, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{self, DebruijnIndex, DefIdTree, List, Ty, TyCtxt, TypeFoldable};
 use rustc_apfloat::Float as _;
 use rustc_ast as ast;
 use rustc_attr::{self as attr, SignedInt, UnsignedInt};
@@ -206,8 +206,9 @@ impl<'tcx> TyCtxt<'tcx> {
         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),
@@ -816,6 +817,15 @@ impl<'tcx> ty::TyS<'tcx> {
                     [component_ty] => component_ty,
                     _ => self,
                 };
+
+                // FIXME(#86868): We should be canonicalizing, or else moving this to a method of inference
+                // context, or *something* like that, but for now just avoid passing inference
+                // variables to queries that can't cope with them. Instead, conservatively
+                // return "true" (may change drop order).
+                if query_ty.needs_infer() {
+                    return true;
+                }
+
                 // This doesn't depend on regions, so try to minimize distinct
                 // query keys used.
                 let erased = tcx.normalize_erasing_regions(param_env, query_ty);
@@ -905,6 +915,10 @@ impl<'tcx> ty::TyS<'tcx> {
         }
         ty
     }
+
+    pub fn outer_exclusive_binder(&'tcx self) -> DebruijnIndex {
+        self.outer_exclusive_binder
+    }
 }
 
 pub enum ExplicitSelf<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
new file mode 100644 (file)
index 0000000..78109fc
--- /dev/null
@@ -0,0 +1,107 @@
+use std::convert::TryFrom;
+
+use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar, ScalarMaybeUninit};
+use crate::ty::fold::TypeFoldable;
+use crate::ty::{self, DefId, SubstsRef, Ty, TyCtxt};
+use rustc_ast::Mutability;
+
+#[derive(Clone, Copy, Debug, PartialEq, HashStable)]
+pub enum VtblEntry<'tcx> {
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Vacant,
+    Method(DefId, SubstsRef<'tcx>),
+}
+
+pub const COMMON_VTABLE_ENTRIES: &[VtblEntry<'_>] =
+    &[VtblEntry::MetadataDropInPlace, VtblEntry::MetadataSize, VtblEntry::MetadataAlign];
+
+pub const COMMON_VTABLE_ENTRIES_DROPINPLACE: usize = 0;
+pub const COMMON_VTABLE_ENTRIES_SIZE: usize = 1;
+pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2;
+
+impl<'tcx> TyCtxt<'tcx> {
+    /// Retrieves an allocation that represents the contents of a vtable.
+    /// There's a cache within `TyCtxt` so it will be deduplicated.
+    pub fn vtable_allocation(
+        self,
+        ty: Ty<'tcx>,
+        poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
+    ) -> AllocId {
+        let tcx = self;
+        let vtables_cache = tcx.vtables_cache.lock();
+        if let Some(alloc_id) = vtables_cache.get(&(ty, poly_trait_ref)).cloned() {
+            return alloc_id;
+        }
+        drop(vtables_cache);
+
+        // See https://github.com/rust-lang/rust/pull/86475#discussion_r655162674
+        assert!(
+            !ty.needs_subst() && !poly_trait_ref.map_or(false, |trait_ref| trait_ref.needs_subst())
+        );
+        let param_env = ty::ParamEnv::reveal_all();
+        let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref {
+            let trait_ref = poly_trait_ref.with_self_ty(tcx, ty);
+            let trait_ref = tcx.erase_regions(trait_ref);
+
+            tcx.vtable_entries(trait_ref)
+        } else {
+            COMMON_VTABLE_ENTRIES
+        };
+
+        let layout =
+            tcx.layout_of(param_env.and(ty)).expect("failed to build vtable representation");
+        assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");
+        let size = layout.size.bytes();
+        let align = layout.align.abi.bytes();
+
+        let ptr_size = tcx.data_layout.pointer_size;
+        let ptr_align = tcx.data_layout.pointer_align.abi;
+
+        let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap();
+        let mut vtable =
+            Allocation::uninit(vtable_size, ptr_align, /* panic_on_fail */ true).unwrap();
+
+        // No need to do any alignment checks on the memory accesses below, because we know the
+        // allocation is correctly aligned as we created it above. Also we're only offsetting by
+        // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`.
+
+        for (idx, entry) in vtable_entries.iter().enumerate() {
+            let idx: u64 = u64::try_from(idx).unwrap();
+            let scalar = match entry {
+                VtblEntry::MetadataDropInPlace => {
+                    let instance = ty::Instance::resolve_drop_in_place(tcx, ty);
+                    let fn_alloc_id = tcx.create_fn_alloc(instance);
+                    let fn_ptr = Pointer::from(fn_alloc_id);
+                    ScalarMaybeUninit::from_pointer(fn_ptr, &tcx)
+                }
+                VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(),
+                VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(),
+                VtblEntry::Vacant => continue,
+                VtblEntry::Method(def_id, substs) => {
+                    // See https://github.com/rust-lang/rust/pull/86475#discussion_r655162674
+                    assert!(!substs.needs_subst());
+
+                    // Prepare the fn ptr we write into the vtable.
+                    let instance =
+                        ty::Instance::resolve_for_vtable(tcx, param_env, *def_id, substs)
+                            .expect("resolution failed during building vtable representation")
+                            .polymorphize(tcx);
+                    let fn_alloc_id = tcx.create_fn_alloc(instance);
+                    let fn_ptr = Pointer::from(fn_alloc_id);
+                    ScalarMaybeUninit::from_pointer(fn_ptr, &tcx)
+                }
+            };
+            vtable
+                .write_scalar(&tcx, alloc_range(ptr_size * idx, ptr_size), scalar)
+                .expect("failed to build vtable representation");
+        }
+
+        vtable.mutability = Mutability::Not;
+        let alloc_id = tcx.create_memory_alloc(tcx.intern_const_alloc(vtable));
+        let mut vtables_cache = self.vtables_cache.lock();
+        vtables_cache.insert((ty, poly_trait_ref), alloc_id);
+        alloc_id
+    }
+}
index 8b0761889b83453b9d205d5418a57f4e14bb01e5..2e854ea5be7df7046321a33dde452c5a84a38d30 100644 (file)
@@ -9,10 +9,11 @@ use rustc_middle::mir::{
     FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
     ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
 };
-use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TypeFoldable};
+use rustc_middle::ty::{self, suggest_constraining_type_param, Ty};
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::sym;
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::{MultiSpan, Span, DUMMY_SP};
+use rustc_trait_selection::infer::InferCtxtExt;
 
 use crate::dataflow::drop_flag_effects;
 use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex};
@@ -65,7 +66,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             self.move_spans(moved_place, location).or_else(|| self.borrow_spans(span, location));
         let span = use_spans.args_or_use();
 
-        let move_site_vec = self.get_moved_indexes(location, mpi);
+        let (move_site_vec, maybe_reinitialized_locations) = self.get_moved_indexes(location, mpi);
         debug!(
             "report_use_of_moved_or_uninitialized: move_site_vec={:?} use_spans={:?}",
             move_site_vec, use_spans
@@ -138,6 +139,32 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 self.describe_place_with_options(moved_place, IncludingDowncast(true)),
             );
 
+            let reinit_spans = maybe_reinitialized_locations
+                .iter()
+                .take(3)
+                .map(|loc| {
+                    self.move_spans(self.move_data.move_paths[mpi].place.as_ref(), *loc)
+                        .args_or_use()
+                })
+                .collect::<Vec<Span>>();
+            let reinits = maybe_reinitialized_locations.len();
+            if reinits == 1 {
+                err.span_label(reinit_spans[0], "this reinitialization might get skipped");
+            } else if reinits > 1 {
+                err.span_note(
+                    MultiSpan::from_spans(reinit_spans),
+                    &if reinits <= 3 {
+                        format!("these {} reinitializations might get skipped", reinits)
+                    } else {
+                        format!(
+                            "these 3 reinitializations and {} other{} might get skipped",
+                            reinits - 3,
+                            if reinits == 4 { "" } else { "s" }
+                        )
+                    },
+                );
+            }
+
             self.add_moved_or_invoked_closure_note(location, used_place, &mut err);
 
             let mut is_loop_move = false;
@@ -218,7 +245,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                     ),
                                 );
                             }
-                            if is_option_or_result {
+                            if is_option_or_result && maybe_reinitialized_locations.is_empty() {
                                 err.span_suggestion_verbose(
                                     fn_call_span.shrink_to_lo(),
                                     "consider calling `.as_ref()` to borrow the type's contents",
@@ -259,19 +286,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     }
                 }
 
-                if let UseSpans::PatUse(span) = move_spans {
-                    err.span_suggestion_verbose(
-                        span.shrink_to_lo(),
-                        &format!(
-                            "borrow this field in the pattern to avoid moving {}",
-                            self.describe_place(moved_place.as_ref())
-                                .map(|n| format!("`{}`", n))
-                                .unwrap_or_else(|| "the value".to_string())
-                        ),
-                        "ref ".to_string(),
-                        Applicability::MachineApplicable,
-                    );
-                    in_pattern = true;
+                if let (UseSpans::PatUse(span), []) =
+                    (move_spans, &maybe_reinitialized_locations[..])
+                {
+                    if maybe_reinitialized_locations.is_empty() {
+                        err.span_suggestion_verbose(
+                            span.shrink_to_lo(),
+                            &format!(
+                                "borrow this field in the pattern to avoid moving {}",
+                                self.describe_place(moved_place.as_ref())
+                                    .map(|n| format!("`{}`", n))
+                                    .unwrap_or_else(|| "the value".to_string())
+                            ),
+                            "ref ".to_string(),
+                            Applicability::MachineApplicable,
+                        );
+                        in_pattern = true;
+                    }
                 }
 
                 if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() {
@@ -453,6 +484,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 &mut err,
                 "",
                 Some(borrow_span),
+                None,
             );
         err.buffer(&mut self.errors_buffer);
     }
@@ -498,6 +530,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 &mut err,
                 "",
                 None,
+                None,
             );
         err
     }
@@ -718,6 +751,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             &mut err,
             first_borrow_desc,
             None,
+            Some((issued_span, span)),
         );
 
         err
@@ -1076,6 +1110,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     &mut err,
                     "",
                     None,
+                    None,
                 );
             }
         } else {
@@ -1093,6 +1128,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 &mut err,
                 "",
                 None,
+                None,
             );
         }
 
@@ -1158,6 +1194,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             &mut err,
             "",
             None,
+            None,
         );
 
         err.buffer(&mut self.errors_buffer);
@@ -1236,6 +1273,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             &mut err,
             "",
             None,
+            None,
         );
 
         let within = if borrow_spans.for_generator() { " by generator" } else { "" };
@@ -1322,18 +1360,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             let return_ty = tcx.erase_regions(return_ty);
 
             // to avoid panics
-            if !return_ty.has_infer_types() {
-                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 let Ok(snippet) = tcx.sess.source_map().span_to_snippet(return_span) {
-                            err.span_suggestion_hidden(
-                                return_span,
-                                "use `.collect()` to allocate the iterator",
-                                format!("{}{}", snippet, ".collect::<Vec<_>>()"),
-                                Applicability::MaybeIncorrect,
-                            );
-                        }
+            if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) {
+                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) {
+                        err.span_suggestion_hidden(
+                            return_span,
+                            "use `.collect()` to allocate the iterator",
+                            format!("{}{}", snippet, ".collect::<Vec<_>>()"),
+                            Applicability::MaybeIncorrect,
+                        );
                     }
                 }
             }
@@ -1456,7 +1495,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         err
     }
 
-    fn get_moved_indexes(&mut self, location: Location, mpi: MovePathIndex) -> Vec<MoveSite> {
+    fn get_moved_indexes(
+        &mut self,
+        location: Location,
+        mpi: MovePathIndex,
+    ) -> (Vec<MoveSite>, Vec<Location>) {
         fn predecessor_locations(
             body: &'a mir::Body<'tcx>,
             location: Location,
@@ -1479,6 +1522,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }));
 
         let mut visited = FxHashSet::default();
+        let mut move_locations = FxHashSet::default();
+        let mut reinits = vec![];
         let mut result = vec![];
 
         'dfs: while let Some((location, is_back_edge)) = stack.pop() {
@@ -1520,6 +1565,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             move_paths[path].place
                         );
                         result.push(MoveSite { moi: *moi, traversed_back_edge: is_back_edge });
+                        move_locations.insert(location);
 
                         // Strictly speaking, we could continue our DFS here. There may be
                         // other moves that can reach the point of error. But it is kind of
@@ -1556,6 +1602,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 },
             );
             if any_match {
+                reinits.push(location);
                 continue 'dfs;
             }
 
@@ -1565,7 +1612,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }));
         }
 
-        result
+        // Check if we can reach these reinits from a move location.
+        let reinits_reachable = reinits
+            .into_iter()
+            .filter(|reinit| {
+                let mut visited = FxHashSet::default();
+                let mut stack = vec![*reinit];
+                while let Some(location) = stack.pop() {
+                    if !visited.insert(location) {
+                        continue;
+                    }
+                    if move_locations.contains(&location) {
+                        return true;
+                    }
+                    stack.extend(predecessor_locations(self.body, location));
+                }
+                false
+            })
+            .collect::<Vec<Location>>();
+        (result, reinits_reachable)
     }
 
     pub(in crate::borrow_check) fn report_illegal_mutation_of_borrowed(
@@ -1614,6 +1679,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             &mut err,
             "",
             None,
+            None,
         );
 
         self.explain_deref_coercion(loan, &mut err);
index e9f1ecb9bbc81dec0af6123ecb6402f742d69c55..76de010d1393bbaa02ea48d9389e96c6d3875c59 100644 (file)
@@ -66,6 +66,7 @@ impl BorrowExplanation {
         err: &mut DiagnosticBuilder<'_>,
         borrow_desc: &str,
         borrow_span: Option<Span>,
+        multiple_borrow_span: Option<(Span, Span)>,
     ) {
         match *self {
             BorrowExplanation::UsedLater(later_use_kind, var_or_use_span, path_span) => {
@@ -192,14 +193,23 @@ impl BorrowExplanation {
 
                         if let Some(info) = &local_decl.is_block_tail {
                             if info.tail_result_is_ignored {
-                                err.span_suggestion_verbose(
-                                    info.span.shrink_to_hi(),
-                                    "consider adding semicolon after the expression so its \
-                                     temporaries are dropped sooner, before the local variables \
-                                     declared by the block are dropped",
-                                    ";".to_string(),
-                                    Applicability::MaybeIncorrect,
-                                );
+                                // #85581: If the first mutable borrow's scope contains
+                                // the second borrow, this suggestion isn't helpful.
+                                if !multiple_borrow_span
+                                    .map(|(old, new)| {
+                                        old.to(info.span.shrink_to_hi()).contains(new)
+                                    })
+                                    .unwrap_or(false)
+                                {
+                                    err.span_suggestion_verbose(
+                                        info.span.shrink_to_hi(),
+                                        "consider adding semicolon after the expression so its \
+                                        temporaries are dropped sooner, before the local variables \
+                                        declared by the block are dropped",
+                                        ";".to_string(),
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                }
                             } else {
                                 err.note(
                                     "the temporary is part of an expression at the end of a \
index bf5f2c0eec23edc8382fc0819410dd4811600948..671d947d1b1321f2ac7d1797e53e9914794520d3 100644 (file)
@@ -147,7 +147,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     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 feb7672f650ecdd1338e55b04693bd211db9d2b8..1460c2378d1c9bfd6b874edcfce93d92f12e2457 100644 (file)
@@ -9,7 +9,7 @@ use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, RegionVid, Ty};
 use rustc_span::symbol::{kw, sym};
-use rustc_span::Span;
+use rustc_span::{BytePos, Span};
 
 use crate::util::borrowck_errors;
 
@@ -641,12 +641,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                         } else {
                             "'_".to_string()
                         };
-                        let suggestion = if snippet.ends_with(';') {
+                        let span = if snippet.ends_with(';') {
                             // `type X = impl Trait;`
-                            format!("{} + {};", &snippet[..snippet.len() - 1], suggestable_fr_name)
+                            span.with_hi(span.hi() - BytePos(1))
                         } else {
-                            format!("{} + {}", snippet, suggestable_fr_name)
+                            span
                         };
+                        let suggestion = format!(" + {}", suggestable_fr_name);
+                        let span = span.shrink_to_hi();
                         diag.span_suggestion(
                             span,
                             &format!(
index baaf6f27ee821377069a336a1e6532723b16d209..2e2578df01146aca4fce8335ac4dc3bd10e58be3 100644 (file)
@@ -1,5 +1,4 @@
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::DefId;
 use rustc_index::vec::IndexVec;
 use rustc_middle::infer::MemberConstraint;
 use rustc_middle::ty::{self, Ty};
@@ -32,9 +31,6 @@ where
 crate struct NllMemberConstraint<'tcx> {
     next_constraint: Option<NllMemberConstraintIndex>,
 
-    /// The opaque type whose hidden type is being inferred. (Used in error reporting.)
-    crate opaque_type_def_id: DefId,
-
     /// The span where the hidden type was instantiated.
     crate definition_span: Span,
 
@@ -91,7 +87,6 @@ impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> {
         let constraint_index = self.constraints.push(NllMemberConstraint {
             next_constraint,
             member_region_vid,
-            opaque_type_def_id: m_c.opaque_type_def_id,
             definition_span: m_c.definition_span,
             hidden_ty: m_c.hidden_ty,
             start_index,
index dded7a7e3cf99e47166e2997d7c364369866490e..c40e6bf1ec33b8f6b4cae993d9828ce6910a0cc1 100644 (file)
@@ -551,7 +551,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         polonius_output: Option<Rc<PoloniusOutput>>,
     ) -> (Option<ClosureRegionRequirements<'tcx>>, RegionErrors<'tcx>) {
         let mir_def_id = body.source.def_id();
-        self.propagate_constraints(body, infcx.tcx);
+        self.propagate_constraints(body);
 
         let mut errors_buffer = RegionErrors::new();
 
@@ -599,7 +599,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// for each region variable until all the constraints are
     /// satisfied. Note that some values may grow **too** large to be
     /// feasible, but we check this later.
-    fn propagate_constraints(&mut self, _body: &Body<'tcx>, tcx: TyCtxt<'tcx>) {
+    fn propagate_constraints(&mut self, _body: &Body<'tcx>) {
         debug!("propagate_constraints()");
 
         debug!("propagate_constraints: constraints={:#?}", {
@@ -617,7 +617,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // own.
         let constraint_sccs = self.constraint_sccs.clone();
         for scc in constraint_sccs.all_sccs() {
-            self.compute_value_for_scc(scc, tcx);
+            self.compute_value_for_scc(scc);
         }
 
         // Sort the applied member constraints so we can binary search
@@ -629,7 +629,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// computed, by unioning the values of its successors.
     /// Assumes that all successors have been computed already
     /// (which is assured by iterating over SCCs in dependency order).
-    fn compute_value_for_scc(&mut self, scc_a: ConstraintSccIndex, tcx: TyCtxt<'tcx>) {
+    fn compute_value_for_scc(&mut self, scc_a: ConstraintSccIndex) {
         let constraint_sccs = self.constraint_sccs.clone();
 
         // Walk each SCC `B` such that `A: B`...
@@ -652,12 +652,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // Now take member constraints into account.
         let member_constraints = self.member_constraints.clone();
         for m_c_i in member_constraints.indices(scc_a) {
-            self.apply_member_constraint(
-                tcx,
-                scc_a,
-                m_c_i,
-                member_constraints.choice_regions(m_c_i),
-            );
+            self.apply_member_constraint(scc_a, m_c_i, member_constraints.choice_regions(m_c_i));
         }
 
         debug!(
@@ -680,31 +675,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// If we make any changes, returns true, else false.
     fn apply_member_constraint(
         &mut self,
-        tcx: TyCtxt<'tcx>,
         scc: ConstraintSccIndex,
         member_constraint_index: NllMemberConstraintIndex,
         choice_regions: &[ty::RegionVid],
     ) -> bool {
         debug!("apply_member_constraint(scc={:?}, choice_regions={:#?})", scc, choice_regions,);
 
-        if let Some(uh_oh) =
-            choice_regions.iter().find(|&&r| !self.universal_regions.is_universal_region(r))
-        {
-            // FIXME(#61773): This case can only occur with
-            // `impl_trait_in_bindings`, I believe, and we are just
-            // opting not to handle it for now. See #61773 for
-            // details.
-            tcx.sess.delay_span_bug(
-                self.member_constraints[member_constraint_index].definition_span,
-                &format!(
-                    "member constraint for `{:?}` has an option region `{:?}` \
-                     that is not a universal region",
-                    self.member_constraints[member_constraint_index].opaque_type_def_id, uh_oh,
-                ),
-            );
-            return false;
-        }
-
         // Create a mutable vector of the options. We'll try to winnow
         // them down.
         let mut choice_regions: Vec<ty::RegionVid> = choice_regions.to_vec();
@@ -1380,7 +1356,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// terms that the "longer free region" `'a` outlived the "shorter free region" `'b`.
     ///
     /// More details can be found in this blog post by Niko:
-    /// <http://smallcultfollowing.com/babysteps/blog/2019/01/17/polonius-and-region-errors/>
+    /// <https://smallcultfollowing.com/babysteps/blog/2019/01/17/polonius-and-region-errors/>
     ///
     /// In the canonical example
     ///
index 3ec24156f223717f0d63438e852fc1bfe87c35a7..12fceeff0884c92a8f4f8ada963004d36b86c8f8 100644 (file)
@@ -60,33 +60,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 debug!(?concrete_type, ?substs);
 
                 let mut subst_regions = vec![self.universal_regions.fr_static];
-                let universal_substs =
-                    infcx.tcx.fold_regions(substs, &mut false, |region, _| match *region {
-                        ty::ReVar(vid) => {
-                            subst_regions.push(vid);
-                            self.definitions[vid].external_name.unwrap_or_else(|| {
-                                infcx.tcx.sess.delay_span_bug(
-                                    span,
-                                    "opaque type with non-universal region substs",
-                                );
-                                infcx.tcx.lifetimes.re_static
-                            })
-                        }
-                        // We don't fold regions in the predicates of opaque
-                        // types to `ReVar`s. This means that in a case like
-                        //
-                        // fn f<'a: 'a>() -> impl Iterator<Item = impl Sized>
-                        //
-                        // The inner opaque type has `'static` in its substs.
-                        ty::ReStatic => region,
-                        _ => {
-                            infcx.tcx.sess.delay_span_bug(
-                                span,
-                                &format!("unexpected concrete region in borrowck: {:?}", region),
-                            );
-                            region
-                        }
-                    });
+                let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| {
+                    let vid = self.universal_regions.to_region_vid(region);
+                    subst_regions.push(vid);
+                    self.definitions[vid].external_name.unwrap_or_else(|| {
+                        infcx
+                            .tcx
+                            .sess
+                            .delay_span_bug(span, "opaque type with non-universal region substs");
+                        infcx.tcx.lifetimes.re_static
+                    })
+                });
 
                 subst_regions.sort();
                 subst_regions.dedup();
@@ -98,14 +82,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                             .find(|ur_vid| self.eval_equal(vid, **ur_vid))
                             .and_then(|ur_vid| self.definitions[*ur_vid].external_name)
                             .unwrap_or(infcx.tcx.lifetimes.re_root_empty),
-                        ty::ReLateBound(..) => region,
-                        _ => {
-                            infcx.tcx.sess.delay_span_bug(
-                                span,
-                                &format!("unexpected concrete region in borrowck: {:?}", region),
-                            );
-                            region
-                        }
+                        _ => region,
                     });
 
                 debug!(?universal_concrete_type, ?universal_substs);
index 1bb447d1057815e7764d9342d2f56311813e506e..37e0643228acc5c386ab545922bf0d82a43e46ae 100644 (file)
@@ -122,7 +122,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         if let Err(terr) = self.eq_opaque_type_and_type(
             mir_output_ty,
             normalized_output_ty,
-            mir_def_id,
             Locations::All(output_span),
             ConstraintCategory::BoringNoLocation,
         ) {
@@ -145,7 +144,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             if let Err(err) = self.eq_opaque_type_and_type(
                 mir_output_ty,
                 user_provided_output_ty,
-                mir_def_id,
                 Locations::All(output_span),
                 ConstraintCategory::BoringNoLocation,
             ) {
index 09cafddeeffde9213c4f1997e3f4fe69b6d5fdc7..3fb06cd2f5f441e1e93234fb9302d4c49d48fb63 100644 (file)
@@ -26,7 +26,7 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef, UserSubsts};
+use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
 use rustc_middle::ty::{
     self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid,
     ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness,
@@ -60,7 +60,6 @@ use crate::borrow_check::{
         LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
     },
     region_infer::{ClosureRegionRequirementsExt, TypeTest},
-    renumber,
     type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
     universal_regions::{DefiningTy, UniversalRegions},
     Upvar,
@@ -180,7 +179,54 @@ pub(crate) fn type_check<'mir, 'tcx>(
             liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table);
 
             translate_outlives_facts(&mut cx);
-            cx.opaque_type_values
+            let mut opaque_type_values = cx.opaque_type_values;
+
+            for (_, revealed_ty) in &mut opaque_type_values {
+                *revealed_ty = infcx.resolve_vars_if_possible(*revealed_ty);
+                if revealed_ty.has_infer_types_or_consts() {
+                    infcx.tcx.sess.delay_span_bug(
+                        body.span,
+                        &format!("could not resolve {:#?}", revealed_ty.kind()),
+                    );
+                    *revealed_ty = infcx.tcx.ty_error();
+                }
+            }
+
+            opaque_type_values.retain(|(opaque_type_key, resolved_ty)| {
+                let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() {
+                    *def_id == opaque_type_key.def_id
+                } else {
+                    false
+                };
+
+                if concrete_is_opaque {
+                    // We're using an opaque `impl Trait` type without
+                    // 'revealing' it. For example, code like this:
+                    //
+                    // type Foo = impl Debug;
+                    // fn foo1() -> Foo { ... }
+                    // fn foo2() -> Foo { foo1() }
+                    //
+                    // In `foo2`, we're not revealing the type of `Foo` - we're
+                    // just treating it as the opaque type.
+                    //
+                    // When this occurs, we do *not* want to try to equate
+                    // the concrete type with the underlying defining type
+                    // of the opaque type - this will always fail, since
+                    // the defining type of an opaque type is always
+                    // some other type (e.g. not itself)
+                    // Essentially, none of the normal obligations apply here -
+                    // we're just passing around some unknown opaque type,
+                    // without actually looking at the underlying type it
+                    // gets 'revealed' into
+                    debug!(
+                        "eq_opaque_type_and_type: non-defining use of {:?}",
+                        opaque_type_key.def_id,
+                    );
+                }
+                !concrete_is_opaque
+            });
+            opaque_type_values
         },
     );
 
@@ -1119,6 +1165,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         )
     }
 
+    /// Try to relate `sub <: sup`
     fn sub_types(
         &mut self,
         sub: Ty<'tcx>,
@@ -1129,32 +1176,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         self.relate_types(sub, ty::Variance::Covariant, sup, locations, category)
     }
 
-    /// Try to relate `sub <: sup`; if this fails, instantiate opaque
-    /// variables in `sub` with their inferred definitions and try
-    /// again. This is used for opaque types in places (e.g., `let x:
-    /// impl Foo = ..`).
-    fn sub_types_or_anon(
-        &mut self,
-        sub: Ty<'tcx>,
-        sup: Ty<'tcx>,
-        locations: Locations,
-        category: ConstraintCategory,
-    ) -> Fallible<()> {
-        if let Err(terr) = self.sub_types(sub, sup, locations, category) {
-            if let ty::Opaque(..) = sup.kind() {
-                // When you have `let x: impl Foo = ...` in a closure,
-                // the resulting inferend values are stored with the
-                // def-id of the base function.
-                let parent_def_id =
-                    self.tcx().closure_base_def_id(self.body.source.def_id()).expect_local();
-                return self.eq_opaque_type_and_type(sub, sup, parent_def_id, locations, category);
-            } else {
-                return Err(terr);
-            }
-        }
-        Ok(())
-    }
-
     fn eq_types(
         &mut self,
         a: Ty<'tcx>,
@@ -1206,11 +1227,39 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         Ok(())
     }
 
+    /// Equates a type `anon_ty` that may contain opaque types whose
+    /// values are to be inferred by the MIR.
+    ///
+    /// The type `revealed_ty` contains the same type as `anon_ty`, but with the
+    /// hidden types for impl traits revealed.
+    ///
+    /// # Example
+    ///
+    /// Consider a piece of code like
+    ///
+    /// ```rust
+    /// type Foo<U> = impl Debug;
+    ///
+    /// fn foo<T: Debug>(t: T) -> Box<Foo<T>> {
+    ///      Box::new((t, 22_u32))
+    /// }
+    /// ```
+    ///
+    /// Here, the function signature would be something like
+    /// `fn(T) -> Box<impl Debug>`. The MIR return slot would have
+    /// the type with the opaque type revealed, so `Box<(T, u32)>`.
+    ///
+    /// In terms of our function parameters:
+    ///
+    /// * `anon_ty` would be `Box<Foo<T>>` where `Foo<T>` is an opaque type
+    ///   scoped to this function (note that it is parameterized by the
+    ///   generics of `foo`). Note that `anon_ty` is not just the opaque type,
+    ///   but the entire return type (which may contain opaque types within it).
+    /// * `revealed_ty` would be `Box<(T, u32)>`
     fn eq_opaque_type_and_type(
         &mut self,
         revealed_ty: Ty<'tcx>,
         anon_ty: Ty<'tcx>,
-        anon_owner_def_id: LocalDefId,
         locations: Locations,
         category: ConstraintCategory,
     ) -> Fallible<()> {
@@ -1236,14 +1285,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             return Ok(());
         }
 
-        let infcx = self.infcx;
-        let tcx = infcx.tcx;
         let param_env = self.param_env;
         let body = self.body;
-        let concrete_opaque_types = &tcx.typeck(anon_owner_def_id).concrete_opaque_types;
+        let mir_def_id = body.source.def_id().expect_local();
+
         let mut opaque_type_values = VecMap::new();
 
-        debug!("eq_opaque_type_and_type: mir_def_id={:?}", body.source.def_id());
+        debug!("eq_opaque_type_and_type: mir_def_id={:?}", mir_def_id);
         let opaque_type_map = self.fully_perform_op(
             locations,
             category,
@@ -1252,9 +1300,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     let mut obligations = ObligationAccumulator::default();
 
                     let dummy_body_id = hir::CRATE_HIR_ID;
+
+                    // Replace the opaque types defined by this function with
+                    // inference variables, creating a map. In our example above,
+                    // this would transform the type `Box<Foo<T>>` (where `Foo` is an opaque type)
+                    // to `Box<?T>`, returning an `opaque_type_map` mapping `{Foo<T> -> ?T}`.
+                    // (Note that the key of the map is both the def-id of `Foo` along with
+                    // any generic parameters.)
                     let (output_ty, opaque_type_map) =
                         obligations.add(infcx.instantiate_opaque_types(
-                            anon_owner_def_id,
+                            mir_def_id,
                             dummy_body_id,
                             param_env,
                             anon_ty,
@@ -1267,6 +1322,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                          revealed_ty={:?}",
                         output_ty, opaque_type_map, revealed_ty
                     );
+
                     // Make sure that the inferred types are well-formed. I'm
                     // not entirely sure this is needed (the HIR type check
                     // didn't do this) but it seems sensible to prevent opaque
@@ -1283,74 +1339,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     );
 
                     for &(opaque_type_key, opaque_decl) in &opaque_type_map {
-                        let resolved_ty = infcx.resolve_vars_if_possible(opaque_decl.concrete_ty);
-                        let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() {
-                            *def_id == opaque_type_key.def_id
-                        } else {
-                            false
-                        };
-
-                        let concrete_ty = match concrete_opaque_types
-                            .get_by(|(key, _)| key.def_id == opaque_type_key.def_id)
-                        {
-                            None => {
-                                if !concrete_is_opaque {
-                                    tcx.sess.delay_span_bug(
-                                        body.span,
-                                        &format!(
-                                            "Non-defining use of {:?} with revealed type",
-                                            opaque_type_key.def_id,
-                                        ),
-                                    );
-                                }
-                                continue;
-                            }
-                            Some(concrete_ty) => concrete_ty,
-                        };
-                        debug!("concrete_ty = {:?}", concrete_ty);
-                        let subst_opaque_defn_ty = concrete_ty.subst(tcx, opaque_type_key.substs);
-                        let renumbered_opaque_defn_ty =
-                            renumber::renumber_regions(infcx, subst_opaque_defn_ty);
-
-                        debug!(
-                            "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}",
-                            concrete_ty, resolved_ty, renumbered_opaque_defn_ty,
-                        );
-
-                        if !concrete_is_opaque {
-                            // Equate concrete_ty (an inference variable) with
-                            // the renumbered type from typeck.
-                            obligations.add(
-                                infcx
-                                    .at(&ObligationCause::dummy(), param_env)
-                                    .eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?,
-                            );
-                            opaque_type_values.insert(opaque_type_key, renumbered_opaque_defn_ty);
-                        } else {
-                            // We're using an opaque `impl Trait` type without
-                            // 'revealing' it. For example, code like this:
-                            //
-                            // type Foo = impl Debug;
-                            // fn foo1() -> Foo { ... }
-                            // fn foo2() -> Foo { foo1() }
-                            //
-                            // In `foo2`, we're not revealing the type of `Foo` - we're
-                            // just treating it as the opaque type.
-                            //
-                            // When this occurs, we do *not* want to try to equate
-                            // the concrete type with the underlying defining type
-                            // of the opaque type - this will always fail, since
-                            // the defining type of an opaque type is always
-                            // some other type (e.g. not itself)
-                            // Essentially, none of the normal obligations apply here -
-                            // we're just passing around some unknown opaque type,
-                            // without actually looking at the underlying type it
-                            // gets 'revealed' into
-                            debug!(
-                                "eq_opaque_type_and_type: non-defining use of {:?}",
-                                opaque_type_key.def_id,
-                            );
-                        }
+                        opaque_type_values.insert(opaque_type_key, opaque_decl.concrete_ty);
                     }
 
                     debug!("eq_opaque_type_and_type: equated");
@@ -1378,7 +1367,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     locations,
                     ConstraintCategory::OpaqueType,
                     CustomTypeOp::new(
-                        |_cx| {
+                        |infcx| {
                             infcx.constrain_opaque_type(
                                 opaque_type_key,
                                 &opaque_decl,
@@ -1436,7 +1425,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 let rv_ty = rv.ty(body, tcx);
                 let rv_ty = self.normalize(rv_ty, location);
                 if let Err(terr) =
-                    self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category)
+                    self.sub_types(rv_ty, place_ty, location.to_locations(), category)
                 {
                     span_mirbug!(
                         self,
@@ -1723,9 +1712,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
                 let locations = term_location.to_locations();
 
-                if let Err(terr) =
-                    self.sub_types_or_anon(sig.output(), dest_ty, locations, category)
-                {
+                if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations, category) {
                     span_mirbug!(
                         self,
                         term,
@@ -2017,24 +2004,26 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                 debug!("check_rvalue: is_const_fn={:?}", is_const_fn);
 
                                 let def_id = body.source.def_id().expect_local();
-                                self.infcx.report_selection_error(
-                                    &traits::Obligation::new(
-                                        ObligationCause::new(
-                                            span,
-                                            self.tcx().hir().local_def_id_to_hir_id(def_id),
-                                            traits::ObligationCauseCode::RepeatVec(is_const_fn),
-                                        ),
-                                        self.param_env,
-                                        ty::Binder::dummy(ty::TraitRef::new(
-                                            self.tcx().require_lang_item(
-                                                LangItem::Copy,
-                                                Some(self.last_span),
-                                            ),
-                                            tcx.mk_substs_trait(ty, &[]),
-                                        ))
-                                        .without_const()
-                                        .to_predicate(self.tcx()),
+                                let obligation = traits::Obligation::new(
+                                    ObligationCause::new(
+                                        span,
+                                        self.tcx().hir().local_def_id_to_hir_id(def_id),
+                                        traits::ObligationCauseCode::RepeatVec(is_const_fn),
                                     ),
+                                    self.param_env,
+                                    ty::Binder::dummy(ty::TraitRef::new(
+                                        self.tcx().require_lang_item(
+                                            LangItem::Copy,
+                                            Some(self.last_span),
+                                        ),
+                                        tcx.mk_substs_trait(ty, &[]),
+                                    ))
+                                    .without_const()
+                                    .to_predicate(self.tcx()),
+                                );
+                                self.infcx.report_selection_error(
+                                    obligation.clone(),
+                                    &obligation,
                                     &traits::SelectionError::Unimplemented,
                                     false,
                                     false,
index fc21047ab72ff3a02d040a757f4f82ed1a04907a..5da1681662577648009f96b1da5b0aabfe02229d 100644 (file)
@@ -16,7 +16,6 @@ use crate::interpret::{
 #[derive(Clone, Debug)]
 pub enum ConstEvalErrKind {
     NeedsRfc(String),
-    PtrToIntCast,
     ConstAccessesStatic,
     ModifiedGlobal,
     AssertFailure(AssertKind<ConstInt>),
@@ -49,12 +48,6 @@ impl fmt::Display for ConstEvalErrKind {
             NeedsRfc(ref msg) => {
                 write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg)
             }
-            PtrToIntCast => {
-                write!(
-                    f,
-                    "cannot cast pointer to integer because it was not created by cast from integer"
-                )
-            }
             ConstAccessesStatic => write!(f, "constant accesses static"),
             ModifiedGlobal => {
                 write!(f, "modifying a static's initial value from another static's initializer")
@@ -157,7 +150,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
         tcx: TyCtxtAt<'tcx>,
         message: &str,
         emit: impl FnOnce(DiagnosticBuilder<'_>),
-        mut lint_root: Option<hir::HirId>,
+        lint_root: Option<hir::HirId>,
     ) -> ErrorHandled {
         let finish = |mut err: DiagnosticBuilder<'_>, span_msg: Option<String>| {
             trace!("reporting const eval failure at {:?}", self.span);
@@ -194,12 +187,6 @@ impl<'tcx> ConstEvalErr<'tcx> {
             _ => {}
         };
 
-        // If we have a 'hard error', then set `lint_root` to `None` so that we don't
-        // emit a lint.
-        if matches!(&self.error, InterpError::MachineStop(err) if err.is_hard_err()) {
-            lint_root = None;
-        }
-
         let err_msg = self.error.to_string();
 
         // Regular case - emit a lint.
index 460fea37461e8d998e7d447d79a0dc493cc6b715..dc6a6b0b9f3d8bca119dcd52d4dde902e5ac5a29 100644 (file)
@@ -48,7 +48,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
     );
     let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?;
     assert!(!layout.is_unsized());
-    let ret = ecx.allocate(layout, MemoryKind::Stack);
+    let ret = ecx.allocate(layout, MemoryKind::Stack)?;
 
     let name =
         with_no_trimmed_paths(|| ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id())));
@@ -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 },
     )
 }
@@ -136,19 +136,19 @@ pub(super) fn op_to_const<'tcx>(
         // by-val is if we are in destructure_const, i.e., if this is (a field of) something that we
         // "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
         // structs containing such.
-        op.try_as_mplace(ecx)
+        op.try_as_mplace()
     };
 
-    let to_const_value = |mplace: &MPlaceTy<'_>| match mplace.ptr {
-        Scalar::Ptr(ptr) => {
-            let alloc = ecx.tcx.global_alloc(ptr.alloc_id).unwrap_memory();
-            ConstValue::ByRef { alloc, offset: ptr.offset }
+    // We know `offset` is relative to the allocation, so we can use `into_parts`.
+    let to_const_value = |mplace: &MPlaceTy<'_>| match mplace.ptr.into_parts() {
+        (Some(alloc_id), offset) => {
+            let alloc = ecx.tcx.global_alloc(alloc_id).unwrap_memory();
+            ConstValue::ByRef { alloc, offset }
         }
-        Scalar::Int(int) => {
+        (None, offset) => {
             assert!(mplace.layout.is_zst());
             assert_eq!(
-                int.assert_bits(ecx.tcx.data_layout.pointer_size)
-                    % u128::from(mplace.layout.align.abi.bytes()),
+                offset.bytes() % mplace.layout.align.abi.bytes(),
                 0,
                 "this MPlaceTy must come from a validated constant, thus we can assume the \
                 alignment is correct",
@@ -162,14 +162,15 @@ pub(super) fn op_to_const<'tcx>(
         Err(imm) => match *imm {
             Immediate::Scalar(x) => match x {
                 ScalarMaybeUninit::Scalar(s) => ConstValue::Scalar(s),
-                ScalarMaybeUninit::Uninit => to_const_value(&op.assert_mem_place(ecx)),
+                ScalarMaybeUninit::Uninit => to_const_value(&op.assert_mem_place()),
             },
             Immediate::ScalarPair(a, b) => {
-                let (data, start) = match a.check_init().unwrap() {
-                    Scalar::Ptr(ptr) => {
-                        (ecx.tcx.global_alloc(ptr.alloc_id).unwrap_memory(), ptr.offset.bytes())
+                // We know `offset` is relative to the allocation, so we can use `into_parts`.
+                let (data, start) = match ecx.scalar_to_ptr(a.check_init().unwrap()).into_parts() {
+                    (Some(alloc_id), offset) => {
+                        (ecx.tcx.global_alloc(alloc_id).unwrap_memory(), offset.bytes())
                     }
-                    Scalar::Int { .. } => (
+                    (None, _offset) => (
                         ecx.tcx.intern_const_alloc(Allocation::from_bytes_byte_aligned_immutable(
                             b"" as &[u8],
                         )),
@@ -300,7 +301,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 },
@@ -312,22 +313,17 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
             let err = ConstEvalErr::new(&ecx, error, None);
             // Some CTFE errors raise just a lint, not a hard error; see
             // <https://github.com/rust-lang/rust/issues/71800>.
-            let emit_as_lint = if let Some(def) = def.as_local() {
+            let is_hard_err = if let Some(def) = def.as_local() {
                 // (Associated) consts only emit a lint, since they might be unused.
-                matches!(tcx.def_kind(def.did.to_def_id()), DefKind::Const | DefKind::AssocConst)
+                !matches!(tcx.def_kind(def.did.to_def_id()), DefKind::Const | DefKind::AssocConst)
+                    // check if the inner InterpError is hard
+                    || err.error.is_hard_err()
             } else {
                 // use of broken constant from other crate: always an error
-                false
+                true
             };
-            if emit_as_lint {
-                let hir_id = tcx.hir().local_def_id_to_hir_id(def.as_local().unwrap().did);
-                Err(err.report_as_lint(
-                    tcx.at(tcx.def_span(def.did)),
-                    "any use of this value will cause an error",
-                    hir_id,
-                    Some(err.span),
-                ))
-            } else {
+
+            if is_hard_err {
                 let msg = if is_static {
                     Cow::from("could not evaluate static initializer")
                 } else {
@@ -345,6 +341,14 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
                 };
 
                 Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), &msg))
+            } else {
+                let hir_id = tcx.hir().local_def_id_to_hir_id(def.as_local().unwrap().did);
+                Err(err.report_as_lint(
+                    tcx.at(tcx.def_span(def.did)),
+                    "any use of this value will cause an error",
+                    hir_id,
+                    Some(err.span),
+                ))
             }
         }
         Ok(mplace) => {
@@ -366,6 +370,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
                     inner = true;
                 }
             };
+            let alloc_id = mplace.ptr.provenance.unwrap();
             if let Err(error) = validation {
                 // Validation failed, report an error. This is always a hard error.
                 let err = ConstEvalErr::new(&ecx, error, None);
@@ -378,9 +383,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
                             "the raw bytes of the constant ({}",
                             display_allocation(
                                 *ecx.tcx,
-                                ecx.tcx
-                                    .global_alloc(mplace.ptr.assert_ptr().alloc_id)
-                                    .unwrap_memory()
+                                ecx.tcx.global_alloc(alloc_id).unwrap_memory()
                             )
                         ));
                         diag.emit();
@@ -388,7 +391,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
                 ))
             } else {
                 // Convert to raw constant
-                Ok(ConstAlloc { alloc_id: mplace.ptr.assert_ptr().alloc_id, ty: mplace.layout.ty })
+                Ok(ConstAlloc { alloc_id, ty: mplace.layout.ty })
             }
         }
     }
index 773df7d7b60c14f2f1142837d05aa0778fe16a50..c809f4f273aa5e059377ddb5ab9a98c29b768cc8 100644 (file)
@@ -16,8 +16,8 @@ use rustc_target::abi::{Align, Size};
 use rustc_target::spec::abi::Abi;
 
 use crate::interpret::{
-    self, compile_time_machine, AllocId, Allocation, Frame, ImmTy, InterpCx, InterpResult, Memory,
-    OpTy, PlaceTy, Pointer, Scalar, StackPopUnwind,
+    self, compile_time_machine, AllocId, Allocation, Frame, ImmTy, InterpCx, InterpResult, OpTy,
+    PlaceTy, Scalar, StackPopUnwind,
 };
 
 use super::error::*;
@@ -59,7 +59,7 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
     pub steps_remaining: usize,
 
     /// The virtual call stack.
-    pub(crate) stack: Vec<Frame<'mir, 'tcx, (), ()>>,
+    pub(crate) stack: Vec<Frame<'mir, 'tcx, AllocId, ()>>,
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -168,11 +168,11 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
             // Comparisons between integers are always known.
             (Scalar::Int { .. }, Scalar::Int { .. }) => a == b,
             // Equality with integers can never be known for sure.
-            (Scalar::Int { .. }, Scalar::Ptr(_)) | (Scalar::Ptr(_), Scalar::Int { .. }) => false,
+            (Scalar::Int { .. }, Scalar::Ptr(..)) | (Scalar::Ptr(..), Scalar::Int { .. }) => false,
             // FIXME: return `true` for when both sides are the same pointer, *except* that
             // some things (like functions and vtables) do not have stable addresses
             // so we need to be careful around them (see e.g. #73722).
-            (Scalar::Ptr(_), Scalar::Ptr(_)) => false,
+            (Scalar::Ptr(..), Scalar::Ptr(..)) => false,
         }
     }
 
@@ -183,13 +183,13 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
             // Comparisons of abstract pointers with null pointers are known if the pointer
             // is in bounds, because if they are in bounds, the pointer can't be null.
             // Inequality with integers other than null can never be known for sure.
-            (Scalar::Int(int), Scalar::Ptr(ptr)) | (Scalar::Ptr(ptr), Scalar::Int(int)) => {
-                int.is_null() && !self.memory.ptr_may_be_null(ptr)
+            (Scalar::Int(int), Scalar::Ptr(ptr, _)) | (Scalar::Ptr(ptr, _), Scalar::Int(int)) => {
+                int.is_null() && !self.memory.ptr_may_be_null(ptr.into())
             }
             // FIXME: return `true` for at least some comparisons where we can reliably
             // determine the result of runtime inequality tests at compile-time.
             // Examples include comparison of addresses in different static items.
-            (Scalar::Ptr(_), Scalar::Ptr(_)) => false,
+            (Scalar::Ptr(..), Scalar::Ptr(..)) => false,
         }
     }
 }
@@ -201,6 +201,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
 
     type MemoryExtra = MemoryExtra;
 
+    const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error
+
     fn load_mir(
         ecx: &InterpCx<'mir, 'tcx, Self>,
         instance: ty::InstanceDef<'tcx>,
@@ -233,12 +235,15 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
             // sensitive check here.  But we can at least rule out functions that are not const
             // at all.
             if !ecx.tcx.is_const_fn_raw(def.did) {
-                // Some functions we support even if they are non-const -- but avoid testing
-                // that for const fn!
-                ecx.hook_panic_fn(instance, args)?;
-                // We certainly do *not* want to actually call the fn
-                // though, so be sure we return here.
-                throw_unsup_format!("calling non-const function `{}`", instance)
+                // allow calling functions marked with #[default_method_body_is_const].
+                if !ecx.tcx.has_attr(def.did, sym::default_method_body_is_const) {
+                    // Some functions we support even if they are non-const -- but avoid testing
+                    // that for const fn!
+                    ecx.hook_panic_fn(instance, args)?;
+                    // We certainly do *not* want to actually call the fn
+                    // though, so be sure we return here.
+                    throw_unsup_format!("calling non-const function `{}`", instance)
+                }
             }
         }
         // This is a const fn. Call it.
@@ -306,8 +311,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
                     Size::from_bytes(size as u64),
                     align,
                     interpret::MemoryKind::Machine(MemoryKind::Heap),
-                );
-                ecx.write_scalar(Scalar::Ptr(ptr), dest)?;
+                )?;
+                ecx.write_pointer(ptr, dest)?;
             }
             _ => {
                 return Err(ConstEvalErrKind::NeedsRfc(format!(
@@ -351,10 +356,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         Err(ConstEvalErrKind::Abort(msg).into())
     }
 
-    fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> {
-        Err(ConstEvalErrKind::PtrToIntCast.into())
-    }
-
     fn binary_ptr_op(
         _ecx: &InterpCx<'mir, 'tcx, Self>,
         _bin_op: mir::BinOp,
@@ -391,7 +392,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         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 6a514e9f62fce655b5aa56822f1e595cc1d67df0..a334165df4cb1ff28a3747663808b2416edec18f 100644 (file)
@@ -35,7 +35,7 @@ pub(crate) fn const_caller_location(
     if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
         bug!("intern_const_alloc_recursive should not error in this case")
     }
-    ConstValue::Scalar(loc_place.ptr)
+    ConstValue::Scalar(Scalar::from_pointer(loc_place.ptr.into_pointer_or_addr().unwrap(), &tcx))
 }
 
 /// Convert an evaluated constant to a type level constant
@@ -179,9 +179,9 @@ pub(crate) fn deref_const<'tcx>(
     let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
     let op = ecx.const_to_op(val, None).unwrap();
     let mplace = ecx.deref_operand(&op).unwrap();
-    if let Scalar::Ptr(ptr) = mplace.ptr {
+    if let Some(alloc_id) = mplace.ptr.provenance {
         assert_eq!(
-            tcx.get_global_alloc(ptr.alloc_id).unwrap().unwrap_memory().mutability,
+            tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().mutability,
             Mutability::Not,
             "deref_const cannot be used with mutable allocations as \
             that could allow pattern matching to observe mutable statics",
index 5575a97982fc4e34bebb5d9db48e1754b7f208bd..03531a6b0049cab5a5fd456d9ed21cf577d48d0c 100644 (file)
@@ -7,7 +7,7 @@ pub(crate) use self::drop_flag_effects::*;
 pub use self::framework::{
     fmt, lattice, visit_results, Analysis, AnalysisDomain, Backward, BorrowckFlowState,
     BorrowckResults, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results,
-    ResultsCursor, ResultsRefCursor, ResultsVisitor,
+    ResultsCursor, ResultsRefCursor, ResultsVisitor, SwitchIntEdgeEffects,
 };
 
 use self::move_paths::MoveData;
index 848b44d13aadf7b7101aa80add0900333daf7fe0..514c1aa9646a063c28e50ac54ca11a1a8d755d01 100644 (file)
@@ -57,7 +57,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         .ok_or_else(|| err_inval!(TooGeneric))?;
 
                         let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
-                        self.write_scalar(fn_ptr, dest)?;
+                        self.write_pointer(fn_ptr, dest)?;
                     }
                     _ => span_bug!(self.cur_span(), "reify fn pointer on {:?}", src.layout.ty),
                 }
@@ -88,7 +88,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                             ty::ClosureKind::FnOnce,
                         );
                         let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
-                        self.write_scalar(fn_ptr, dest)?;
+                        self.write_pointer(fn_ptr, dest)?;
                     }
                     _ => span_bug!(self.cur_span(), "closure fn pointer on {:?}", src.layout.ty),
                 }
@@ -175,7 +175,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // (a) cast a raw ptr to usize, or
         // (b) cast from an integer-like (including bool, char, enums).
         // In both cases we want the bits.
-        let bits = self.force_bits(src.to_scalar()?, src.layout.size)?;
+        let bits = src.to_scalar()?.to_bits(src.layout.size)?;
         Ok(self.cast_from_scalar(bits, src.layout, cast_ty).into())
     }
 
@@ -280,7 +280,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // Initial cast from sized to dyn trait
                 let vtable = self.get_vtable(src_pointee_ty, data.principal())?;
                 let ptr = self.read_immediate(src)?.to_scalar()?;
-                let val = Immediate::new_dyn_trait(ptr, vtable);
+                let val = Immediate::new_dyn_trait(ptr, vtable, &*self.tcx);
                 self.write_immediate(val, dest)
             }
 
index 6f7519e61561b6acb0125ab81a8ea25782f0390d..516ef4f4e53ca8130a1c9a5d9f73b57d4c5f7982 100644 (file)
@@ -2,24 +2,24 @@ use std::cell::Cell;
 use std::fmt;
 use std::mem;
 
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
 use rustc_index::vec::IndexVec;
 use rustc_macros::HashStable;
 use rustc_middle::ich::StableHashingContext;
 use rustc_middle::mir;
-use rustc_middle::mir::interpret::{GlobalId, InterpResult, Pointer, Scalar};
 use rustc_middle::ty::layout::{self, TyAndLayout};
 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};
 
 use super::{
-    Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, Operand, Place, PlaceTy,
-    ScalarMaybeUninit, StackPopJump,
+    AllocId, GlobalId, Immediate, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory,
+    MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance, Scalar, ScalarMaybeUninit,
+    StackPopJump,
 };
 use crate::transform::validate::equal_up_to_regions;
 use crate::util::storage::AlwaysLiveLocals;
@@ -41,9 +41,8 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
     /// The virtual memory system.
     pub memory: Memory<'mir, 'tcx, M>,
 
-    /// A cache for deduplicating vtables
-    pub(super) vtables:
-        FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Pointer<M::PointerTag>>,
+    /// 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
@@ -81,7 +80,7 @@ impl Drop for SpanGuard {
 }
 
 /// A stack frame.
-pub struct Frame<'mir, 'tcx, Tag = (), Extra = ()> {
+pub struct Frame<'mir, 'tcx, Tag: Provenance = AllocId, Extra = ()> {
     ////////////////////////////////////////////////////////////////////////////////
     // Function and callsite information
     ////////////////////////////////////////////////////////////////////////////////
@@ -162,7 +161,7 @@ pub enum StackPopCleanup {
 
 /// State of a local variable including a memoized layout
 #[derive(Clone, PartialEq, Eq, HashStable)]
-pub struct LocalState<'tcx, Tag = ()> {
+pub struct LocalState<'tcx, Tag: Provenance = AllocId> {
     pub value: LocalValue<Tag>,
     /// Don't modify if `Some`, this is only used to prevent computing the layout twice
     #[stable_hasher(ignore)]
@@ -170,8 +169,8 @@ pub struct LocalState<'tcx, Tag = ()> {
 }
 
 /// Current value of a local variable
-#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable)] // Miri debug-prints these
-pub enum LocalValue<Tag = ()> {
+#[derive(Copy, Clone, PartialEq, Eq, HashStable, Debug)] // Miri debug-prints these
+pub enum LocalValue<Tag: Provenance = AllocId> {
     /// This local is not currently alive, and cannot be used at all.
     Dead,
     /// This local is alive but not yet initialized. It can be written to
@@ -187,7 +186,7 @@ pub enum LocalValue<Tag = ()> {
     Live(Operand<Tag>),
 }
 
-impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
+impl<'tcx, Tag: Provenance + 'static> LocalState<'tcx, Tag> {
     /// Read the local's value or error if the local is not yet live or not live anymore.
     ///
     /// Note: This may only be invoked from the `Machine::access_local` hook and not from
@@ -221,7 +220,7 @@ impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
     }
 }
 
-impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> {
+impl<'mir, 'tcx, Tag: Provenance> Frame<'mir, 'tcx, Tag> {
     pub fn with_extra<Extra>(self, extra: Extra) -> Frame<'mir, 'tcx, Tag, Extra> {
         Frame {
             body: self.body,
@@ -236,7 +235,7 @@ impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> {
     }
 }
 
-impl<'mir, 'tcx, Tag, Extra> Frame<'mir, 'tcx, Tag, Extra> {
+impl<'mir, 'tcx, Tag: Provenance, Extra> Frame<'mir, 'tcx, Tag, Extra> {
     /// Get the current location within the Frame.
     ///
     /// If this is `Err`, we are not currently executing any particular statement in
@@ -393,30 +392,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             tcx: tcx.at(root_span),
             param_env,
             memory: Memory::new(tcx, memory_extra),
-            vtables: FxHashMap::default(),
+            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)]
-    pub fn force_ptr(
-        &self,
-        scalar: Scalar<M::PointerTag>,
-    ) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
-        self.memory.force_ptr(scalar)
-    }
-
-    #[inline(always)]
-    pub fn force_bits(
-        &self,
-        scalar: Scalar<M::PointerTag>,
-        size: Size,
-    ) -> InterpResult<'tcx, u128> {
-        self.memory.force_bits(scalar, size)
+    pub fn scalar_to_ptr(&self, scalar: Scalar<M::PointerTag>) -> Pointer<Option<M::PointerTag>> {
+        self.memory.scalar_to_ptr(scalar)
     }
 
     /// Call this to turn untagged "global" pointers (obtained via `tcx`) into
@@ -647,7 +638,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 Ok(Some((size, align)))
             }
             ty::Dynamic(..) => {
-                let vtable = metadata.unwrap_meta();
+                let vtable = self.scalar_to_ptr(metadata.unwrap_meta());
                 // Read size and align from vtable (already checks size).
                 Ok(Some(self.read_size_and_align_from_vtable(vtable)?))
             }
@@ -894,10 +885,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     fn deallocate_local(&mut self, local: LocalValue<M::PointerTag>) -> InterpResult<'tcx> {
         if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
             // All locals have a backing allocation, even if the allocation is empty
-            // due to the local having ZST type.
-            let ptr = ptr.assert_ptr();
-            trace!("deallocating local: {:?}", self.memory.dump_alloc(ptr.alloc_id));
-            self.memory.deallocate_local(ptr)?;
+            // due to the local having ZST type. Hence we can `unwrap`.
+            trace!(
+                "deallocating local {:?}: {:?}",
+                local,
+                self.memory.dump_alloc(ptr.provenance.unwrap().get_alloc_id())
+            );
+            self.memory.deallocate(ptr, None, MemoryKind::Stack)?;
         };
         Ok(())
     }
@@ -928,7 +922,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     #[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),
@@ -967,46 +966,45 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug
                 match self.ecx.stack()[frame].locals[local].value {
                     LocalValue::Dead => write!(fmt, " is dead")?,
                     LocalValue::Uninitialized => write!(fmt, " is uninitialized")?,
-                    LocalValue::Live(Operand::Indirect(mplace)) => match mplace.ptr {
-                        Scalar::Ptr(ptr) => {
-                            write!(
-                                fmt,
-                                " by align({}){} ref:",
-                                mplace.align.bytes(),
-                                match mplace.meta {
-                                    MemPlaceMeta::Meta(meta) => format!(" meta({:?})", meta),
-                                    MemPlaceMeta::Poison | MemPlaceMeta::None => String::new(),
-                                }
-                            )?;
-                            allocs.push(ptr.alloc_id);
-                        }
-                        ptr => write!(fmt, " by integral ref: {:?}", ptr)?,
-                    },
+                    LocalValue::Live(Operand::Indirect(mplace)) => {
+                        write!(
+                            fmt,
+                            " by align({}){} ref {:?}:",
+                            mplace.align.bytes(),
+                            match mplace.meta {
+                                MemPlaceMeta::Meta(meta) => format!(" meta({:?})", meta),
+                                MemPlaceMeta::Poison | MemPlaceMeta::None => String::new(),
+                            },
+                            mplace.ptr,
+                        )?;
+                        allocs.extend(mplace.ptr.provenance.map(Provenance::get_alloc_id));
+                    }
                     LocalValue::Live(Operand::Immediate(Immediate::Scalar(val))) => {
                         write!(fmt, " {:?}", val)?;
-                        if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr)) = val {
-                            allocs.push(ptr.alloc_id);
+                        if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr, _size)) = val {
+                            allocs.push(ptr.provenance.get_alloc_id());
                         }
                     }
                     LocalValue::Live(Operand::Immediate(Immediate::ScalarPair(val1, val2))) => {
                         write!(fmt, " ({:?}, {:?})", val1, val2)?;
-                        if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr)) = val1 {
-                            allocs.push(ptr.alloc_id);
+                        if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr, _size)) = val1 {
+                            allocs.push(ptr.provenance.get_alloc_id());
                         }
-                        if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr)) = val2 {
-                            allocs.push(ptr.alloc_id);
+                        if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr, _size)) = val2 {
+                            allocs.push(ptr.provenance.get_alloc_id());
                         }
                     }
                 }
 
                 write!(fmt, ": {:?}", self.ecx.memory.dump_allocs(allocs))
             }
-            Place::Ptr(mplace) => match mplace.ptr {
-                Scalar::Ptr(ptr) => write!(
+            Place::Ptr(mplace) => match mplace.ptr.provenance.map(Provenance::get_alloc_id) {
+                Some(alloc_id) => write!(
                     fmt,
-                    "by align({}) ref: {:?}",
+                    "by align({}) ref {:?}: {:?}",
                     mplace.align.bytes(),
-                    self.ecx.memory.dump_alloc(ptr.alloc_id)
+                    mplace.ptr,
+                    self.ecx.memory.dump_alloc(alloc_id)
                 ),
                 ptr => write!(fmt, " integral by ref: {:?}", ptr),
             },
@@ -1014,7 +1012,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug
     }
 }
 
-impl<'ctx, 'mir, 'tcx, Tag, Extra> HashStable<StableHashingContext<'ctx>>
+impl<'ctx, 'mir, 'tcx, Tag: Provenance, Extra> HashStable<StableHashingContext<'ctx>>
     for Frame<'mir, 'tcx, Tag, Extra>
 where
     Extra: HashStable<StableHashingContext<'ctx>>,
index 23c0fe97c5f693b7657f316f48299063518d274d..f2457d11d9ee3cd4a19a603901813b7f02d88d7b 100644 (file)
@@ -20,18 +20,17 @@ use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_middle::mir::interpret::InterpResult;
 use rustc_middle::ty::{self, layout::TyAndLayout, Ty};
-use rustc_target::abi::Size;
 
 use rustc_ast::Mutability;
 
-use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, Scalar, ValueVisitor};
+use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy, ValueVisitor};
 use crate::const_eval;
 
 pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine<
     'mir,
     'tcx,
     MemoryKind = T,
-    PointerTag = (),
+    PointerTag = AllocId,
     ExtraFnVal = !,
     FrameExtra = (),
     AllocExtra = (),
@@ -107,7 +106,6 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval:
     match kind {
         MemoryKind::Stack
         | MemoryKind::Machine(const_eval::MemoryKind::Heap)
-        | MemoryKind::Vtable
         | MemoryKind::CallerLocation => {}
     }
     // Set allocation mutability as appropriate. This is used by LLVM to put things into
@@ -137,7 +135,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval:
     };
     // link the alloc id to the actual allocation
     let alloc = tcx.intern_const_alloc(alloc);
-    leftover_allocations.extend(alloc.relocations().iter().map(|&(_, ((), reloc))| reloc));
+    leftover_allocations.extend(alloc.relocations().iter().map(|&(_, alloc_id)| alloc_id));
     tcx.set_alloc_id_memory(alloc_id, alloc);
     None
 }
@@ -204,10 +202,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
             if let ty::Dynamic(..) =
                 tcx.struct_tail_erasing_lifetimes(referenced_ty, self.ecx.param_env).kind()
             {
-                if let Scalar::Ptr(vtable) = mplace.meta.unwrap_meta() {
+                let ptr = self.ecx.scalar_to_ptr(mplace.meta.unwrap_meta());
+                if let Some(alloc_id) = ptr.provenance {
                     // Explicitly choose const mode here, since vtables are immutable, even
                     // if the reference of the fat pointer is mutable.
-                    self.intern_shallow(vtable.alloc_id, InternMode::Const, None);
+                    self.intern_shallow(alloc_id, InternMode::Const, None);
                 } else {
                     // Validation will error (with a better message) on an invalid vtable pointer.
                     // Let validation show the error message, but make sure it *does* error.
@@ -217,7 +216,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
             }
             // Check if we have encountered this pointer+layout combination before.
             // Only recurse for allocation-backed pointers.
-            if let Scalar::Ptr(ptr) = mplace.ptr {
+            if let Some(alloc_id) = mplace.ptr.provenance {
                 // Compute the mode with which we intern this. Our goal here is to make as many
                 // statics as we can immutable so they can be placed in read-only memory by LLVM.
                 let ref_mode = match self.mode {
@@ -260,7 +259,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
                         InternMode::Const
                     }
                 };
-                match self.intern_shallow(ptr.alloc_id, ref_mode, Some(referenced_ty)) {
+                match self.intern_shallow(alloc_id, ref_mode, Some(referenced_ty)) {
                     // No need to recurse, these are interned already and statics may have
                     // cycles, so we don't want to recurse there
                     Some(IsStaticOrFn) => {}
@@ -322,7 +321,7 @@ where
         leftover_allocations,
         // The outermost allocation must exist, because we allocated it with
         // `Memory::allocate`.
-        ret.ptr.assert_ptr().alloc_id,
+        ret.ptr.provenance.unwrap(),
         base_intern_mode,
         Some(ret.layout.ty),
     );
@@ -396,9 +395,9 @@ where
             }
             let alloc = tcx.intern_const_alloc(alloc);
             tcx.set_alloc_id_memory(alloc_id, alloc);
-            for &(_, ((), reloc)) in alloc.relocations().iter() {
-                if leftover_allocations.insert(reloc) {
-                    todo.push(reloc);
+            for &(_, alloc_id) in alloc.relocations().iter() {
+                if leftover_allocations.insert(alloc_id) {
+                    todo.push(alloc_id);
                 }
             }
         } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
@@ -426,14 +425,12 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>>
         layout: TyAndLayout<'tcx>,
         f: impl FnOnce(
             &mut InterpCx<'mir, 'tcx, M>,
-            &MPlaceTy<'tcx, M::PointerTag>,
+            &PlaceTy<'tcx, M::PointerTag>,
         ) -> InterpResult<'tcx, ()>,
     ) -> InterpResult<'tcx, &'tcx Allocation> {
-        let dest = self.allocate(layout, MemoryKind::Stack);
-        f(self, &dest)?;
-        let ptr = dest.ptr.assert_ptr();
-        assert_eq!(ptr.offset, Size::ZERO);
-        let mut alloc = self.memory.alloc_map.remove(&ptr.alloc_id).unwrap().1;
+        let dest = self.allocate(layout, MemoryKind::Stack)?;
+        f(self, &dest.into())?;
+        let mut alloc = self.memory.alloc_map.remove(&dest.ptr.provenance.unwrap()).unwrap().1;
         alloc.mutability = Mutability::Not;
         Ok(self.tcx.intern_const_alloc(alloc))
     }
index 4e4166dad50e29b83c7b49c00905fe344941f659..dc1f9053b61f028fe968a3c1b31928e657a61481 100644 (file)
@@ -18,6 +18,7 @@ use rustc_target::abi::{Abi, Align, LayoutOf as _, Primitive, Size};
 
 use super::{
     util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy,
+    Pointer,
 };
 
 mod caller_location;
@@ -138,7 +139,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             sym::caller_location => {
                 let span = self.find_closest_untracked_caller_location();
                 let location = self.alloc_caller_location_for_span(span);
-                self.write_scalar(location.ptr, dest)?;
+                self.write_immediate(location.to_ref(self), dest)?;
             }
 
             sym::min_align_of_val | sym::size_of_val => {
@@ -190,7 +191,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let ty = substs.type_at(0);
                 let layout_of = self.layout_of(ty)?;
                 let val = self.read_scalar(&args[0])?.check_init()?;
-                let bits = self.force_bits(val, layout_of.size)?;
+                let bits = val.to_bits(layout_of.size)?;
                 let kind = match layout_of.abi {
                     Abi::Scalar(ref scalar) => scalar.value,
                     _ => span_bug!(
@@ -238,7 +239,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         // term since the sign of the second term can be inferred from this and
                         // the fact that the operation has overflowed (if either is 0 no
                         // overflow can occur)
-                        let first_term: u128 = self.force_bits(l.to_scalar()?, l.layout.size)?;
+                        let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
                         let first_term_positive = first_term & (1 << (num_bits - 1)) == 0;
                         if first_term_positive {
                             // Negative overflow not possible since the positive first term
@@ -298,7 +299,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let (val, overflowed, _ty) = self.overflowing_binary_op(bin_op, &l, &r)?;
                 if overflowed {
                     let layout = self.layout_of(substs.type_at(0))?;
-                    let r_val = self.force_bits(r.to_scalar()?, layout.size)?;
+                    let r_val = r.to_scalar()?.to_bits(layout.size)?;
                     if let sym::unchecked_shl | sym::unchecked_shr = intrinsic_name {
                         throw_ub_format!("overflowing shift by {} in `{}`", r_val, intrinsic_name);
                     } else {
@@ -312,9 +313,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
                 let layout = self.layout_of(substs.type_at(0))?;
                 let val = self.read_scalar(&args[0])?.check_init()?;
-                let val_bits = self.force_bits(val, layout.size)?;
+                let val_bits = val.to_bits(layout.size)?;
                 let raw_shift = self.read_scalar(&args[1])?.check_init()?;
-                let raw_shift_bits = self.force_bits(raw_shift, layout.size)?;
+                let raw_shift_bits = raw_shift.to_bits(layout.size)?;
                 let width_bits = u128::from(layout.size.bits());
                 let shift_bits = raw_shift_bits % width_bits;
                 let inv_shift_bits = (width_bits - shift_bits) % width_bits;
@@ -331,22 +332,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.copy_intrinsic(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?;
             }
             sym::offset => {
-                let ptr = self.read_scalar(&args[0])?.check_init()?;
+                let ptr = self.read_pointer(&args[0])?;
                 let offset_count = self.read_scalar(&args[1])?.to_machine_isize(self)?;
                 let pointee_ty = substs.type_at(0);
 
                 let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
-                self.write_scalar(offset_ptr, dest)?;
+                self.write_pointer(offset_ptr, dest)?;
             }
             sym::arith_offset => {
-                let ptr = self.read_scalar(&args[0])?.check_init()?;
+                let ptr = self.read_pointer(&args[0])?;
                 let offset_count = self.read_scalar(&args[1])?.to_machine_isize(self)?;
                 let pointee_ty = substs.type_at(0);
 
                 let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
                 let offset_bytes = offset_count.wrapping_mul(pointee_size);
-                let offset_ptr = ptr.ptr_wrapping_signed_offset(offset_bytes, self);
-                self.write_scalar(offset_ptr, dest)?;
+                let offset_ptr = ptr.wrapping_signed_offset(offset_bytes, self);
+                self.write_pointer(offset_ptr, dest)?;
             }
             sym::ptr_offset_from => {
                 let a = self.read_immediate(&args[0])?.to_scalar()?;
@@ -361,9 +362,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 //
                 // Control flow is weird because we cannot early-return (to reach the
                 // `go_to_block` at the end).
-                let done = if a.is_bits() && b.is_bits() {
-                    let a = a.to_machine_usize(self)?;
-                    let b = b.to_machine_usize(self)?;
+                let done = if let (Ok(a), Ok(b)) = (a.try_to_int(), b.try_to_int()) {
+                    let a = a.try_to_machine_usize(*self.tcx).unwrap();
+                    let b = b.try_to_machine_usize(*self.tcx).unwrap();
                     if a == b && a != 0 {
                         self.write_scalar(Scalar::from_machine_isize(0, self), dest)?;
                         true
@@ -376,9 +377,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
                 if !done {
                     // General case: we need two pointers.
-                    let a = self.force_ptr(a)?;
-                    let b = self.force_ptr(b)?;
-                    if a.alloc_id != b.alloc_id {
+                    let a = self.scalar_to_ptr(a);
+                    let b = self.scalar_to_ptr(b);
+                    let (a_alloc_id, a_offset, _) = self.memory.ptr_get_alloc(a)?;
+                    let (b_alloc_id, b_offset, _) = self.memory.ptr_get_alloc(b)?;
+                    if a_alloc_id != b_alloc_id {
                         throw_ub_format!(
                             "ptr_offset_from cannot compute offset of pointers into different \
                             allocations.",
@@ -386,8 +389,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     }
                     let usize_layout = self.layout_of(self.tcx.types.usize)?;
                     let isize_layout = self.layout_of(self.tcx.types.isize)?;
-                    let a_offset = ImmTy::from_uint(a.offset.bytes(), usize_layout);
-                    let b_offset = ImmTy::from_uint(b.offset.bytes(), usize_layout);
+                    let a_offset = ImmTy::from_uint(a_offset.bytes(), usize_layout);
+                    let b_offset = ImmTy::from_uint(b_offset.bytes(), usize_layout);
                     let (val, _overflowed, _ty) =
                         self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?;
                     let pointee_layout = self.layout_of(substs.type_at(0))?;
@@ -472,6 +475,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     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),
         }
 
@@ -509,10 +516,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// 0, so offset-by-0 (and only 0) is okay -- except that null cannot be offset by _any_ value.
     pub fn ptr_offset_inbounds(
         &self,
-        ptr: Scalar<M::PointerTag>,
+        ptr: Pointer<Option<M::PointerTag>>,
         pointee_ty: Ty<'tcx>,
         offset_count: i64,
-    ) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
+    ) -> InterpResult<'tcx, Pointer<Option<M::PointerTag>>> {
         // We cannot overflow i64 as a type's size must be <= isize::MAX.
         let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
         // The computed offset, in bytes, cannot overflow an isize.
@@ -520,7 +527,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             offset_count.checked_mul(pointee_size).ok_or(err_ub!(PointerArithOverflow))?;
         // The offset being in bounds cannot rely on "wrapping around" the address space.
         // So, first rule out overflows in the pointer arithmetic.
-        let offset_ptr = ptr.ptr_signed_offset(offset_bytes, self)?;
+        let offset_ptr = ptr.signed_offset(offset_bytes, self)?;
         // ptr and offset_ptr must be in bounds of the same allocated object. This means all of the
         // memory between these pointers must be accessible. Note that we do not require the
         // pointers to be properly aligned (unlike a read/write operation).
@@ -554,9 +561,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             )
         })?;
 
-        let src = self.read_scalar(&src)?.check_init()?;
-        let dst = self.read_scalar(&dst)?.check_init()?;
+        let src = self.read_pointer(&src)?;
+        let dst = self.read_pointer(&dst)?;
 
         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_pointer(lhs)?;
+        let rhs = self.read_pointer(rhs)?;
+        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 792a4749108be02132524a554174b025fcebba97..022129b2a22046a04806c4dbb893cbd4555aa5a1 100644 (file)
@@ -91,10 +91,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             .type_of(self.tcx.require_lang_item(LangItem::PanicLocation, None))
             .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter()));
         let loc_layout = self.layout_of(loc_ty).unwrap();
-        let location = self.allocate(loc_layout, MemoryKind::CallerLocation);
+        // This can fail if rustc runs out of memory right here. Trying to emit an error would be
+        // pointless, since that would require allocating more memory than a Location.
+        let location = self.allocate(loc_layout, MemoryKind::CallerLocation).unwrap();
 
         // Initialize fields.
-        self.write_immediate(file.to_ref(), &self.mplace_field(&location, 0).unwrap().into())
+        self.write_immediate(file.to_ref(self), &self.mplace_field(&location, 0).unwrap().into())
             .expect("writing to memory we just allocated cannot fail");
         self.write_scalar(line, &self.mplace_field(&location, 1).unwrap().into())
             .expect("writing to memory we just allocated cannot fail");
index 0d01dc3c219bc908931de3fc686326cb9f07aa9b..323e102b8723b904e8deadc005f055d421b139ec 100644 (file)
@@ -13,8 +13,8 @@ use rustc_target::abi::Size;
 use rustc_target::spec::abi::Abi;
 
 use super::{
-    AllocId, Allocation, CheckInAllocMsg, Frame, ImmTy, InterpCx, InterpResult, LocalValue,
-    MemPlace, Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Scalar, StackPopUnwind,
+    AllocId, AllocRange, Allocation, Frame, ImmTy, InterpCx, InterpResult, LocalValue, MemPlace,
+    Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
 };
 
 /// Data returned by Machine::stack_pop,
@@ -84,12 +84,8 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// Additional memory kinds a machine wishes to distinguish from the builtin ones
     type MemoryKind: Debug + std::fmt::Display + MayLeak + Eq + 'static;
 
-    /// Tag tracked alongside every pointer. This is used to implement "Stacked Borrows"
-    /// <https://www.ralfj.de/blog/2018/08/07/stacked-borrows.html>.
-    /// The `default()` is used for pointers to consts, statics, vtables and functions.
-    /// The `Debug` formatting is used for displaying pointers; we cannot use `Display`
-    /// as `()` does not implement that, but it should be "nice" output.
-    type PointerTag: Debug + Copy + Eq + Hash + 'static;
+    /// Pointers are "tagged" with provenance information; typically the `AllocId` they belong to.
+    type PointerTag: Provenance + Eq + Hash + 'static;
 
     /// Machines can define extra (non-instance) things that represent values of function pointers.
     /// For example, Miri uses this to return a function pointer from `dlsym`
@@ -122,6 +118,9 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// that is added to the memory so that the work is not done twice.
     const GLOBAL_KIND: Option<Self::MemoryKind>;
 
+    /// Should the machine panic on allocation failures?
+    const PANIC_ON_ALLOC_FAIL: bool;
+
     /// Whether memory accesses should be alignment-checked.
     fn enforce_alignment(memory_extra: &Self::MemoryExtra) -> bool;
 
@@ -263,28 +262,39 @@ pub trait Machine<'mir, 'tcx>: Sized {
     }
 
     /// Return the `AllocId` for the given thread-local static in the current thread.
-    fn thread_local_static_alloc_id(
+    fn thread_local_static_base_pointer(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         def_id: DefId,
-    ) -> InterpResult<'tcx, AllocId> {
+    ) -> InterpResult<'tcx, Pointer<Self::PointerTag>> {
         throw_unsup!(ThreadLocalStatic(def_id))
     }
 
-    /// Return the `AllocId` backing the given `extern static`.
-    fn extern_static_alloc_id(
+    /// Return the root pointer for the given `extern static`.
+    fn extern_static_base_pointer(
         mem: &Memory<'mir, 'tcx, Self>,
         def_id: DefId,
-    ) -> InterpResult<'tcx, AllocId> {
-        // Use the `AllocId` associated with the `DefId`. Any actual *access* will fail.
-        Ok(mem.tcx.create_static_alloc(def_id))
-    }
+    ) -> InterpResult<'tcx, Pointer<Self::PointerTag>>;
 
-    /// Return the "base" tag for the given *global* allocation: the one that is used for direct
-    /// accesses to this static/const/fn allocation. If `id` is not a global allocation,
-    /// this will return an unusable tag (i.e., accesses will be UB)!
+    /// Return a "base" pointer for the given allocation: the one that is used for direct
+    /// accesses to this static/const/fn allocation, or the one returned from the heap allocator.
     ///
-    /// Called on the id returned by `thread_local_static_alloc_id` and `extern_static_alloc_id`, if needed.
-    fn tag_global_base_pointer(memory_extra: &Self::MemoryExtra, id: AllocId) -> Self::PointerTag;
+    /// Not called on `extern` or thread-local statics (those use the methods above).
+    fn tag_alloc_base_pointer(
+        mem: &Memory<'mir, 'tcx, Self>,
+        ptr: Pointer,
+    ) -> Pointer<Self::PointerTag>;
+
+    /// "Int-to-pointer cast"
+    fn ptr_from_addr(
+        mem: &Memory<'mir, 'tcx, Self>,
+        addr: u64,
+    ) -> Pointer<Option<Self::PointerTag>>;
+
+    /// Convert a pointer with provenance into an allocation-offset pair.
+    fn ptr_get_alloc(
+        mem: &Memory<'mir, 'tcx, Self>,
+        ptr: Pointer<Self::PointerTag>,
+    ) -> (AllocId, Size);
 
     /// Called to initialize the "extra" state of an allocation and make the pointers
     /// it contains (in relocations) tagged.  The way we construct allocations is
@@ -299,16 +309,12 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// allocation (because a copy had to be done to add tags or metadata), machine memory will
     /// cache the result. (This relies on `AllocMap::get_or` being able to add the
     /// owned allocation to the map even when the map is shared.)
-    ///
-    /// Also return the "base" tag to use for this allocation: the one that is used for direct
-    /// accesses to this allocation. If `kind == STATIC_KIND`, this tag must be consistent
-    /// with `tag_global_base_pointer`.
     fn init_allocation_extra<'b>(
-        memory_extra: &Self::MemoryExtra,
+        mem: &Memory<'mir, 'tcx, Self>,
         id: AllocId,
         alloc: Cow<'b, Allocation>,
         kind: Option<MemoryKind<Self::MemoryKind>>,
-    ) -> (Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>, Self::PointerTag);
+    ) -> Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>;
 
     /// Hook for performing extra checks on a memory read access.
     ///
@@ -319,8 +325,8 @@ pub trait Machine<'mir, 'tcx>: Sized {
     fn memory_read(
         _memory_extra: &Self::MemoryExtra,
         _alloc_extra: &Self::AllocExtra,
-        _ptr: Pointer<Self::PointerTag>,
-        _size: Size,
+        _tag: Self::PointerTag,
+        _range: AllocRange,
     ) -> InterpResult<'tcx> {
         Ok(())
     }
@@ -330,8 +336,8 @@ pub trait Machine<'mir, 'tcx>: Sized {
     fn memory_written(
         _memory_extra: &mut Self::MemoryExtra,
         _alloc_extra: &mut Self::AllocExtra,
-        _ptr: Pointer<Self::PointerTag>,
-        _size: Size,
+        _tag: Self::PointerTag,
+        _range: AllocRange,
     ) -> InterpResult<'tcx> {
         Ok(())
     }
@@ -341,17 +347,8 @@ pub trait Machine<'mir, 'tcx>: Sized {
     fn memory_deallocated(
         _memory_extra: &mut Self::MemoryExtra,
         _alloc_extra: &mut Self::AllocExtra,
-        _ptr: Pointer<Self::PointerTag>,
-        _size: Size,
-    ) -> InterpResult<'tcx> {
-        Ok(())
-    }
-
-    /// Called after initializing static memory using the interpreter.
-    fn after_static_mem_initialized(
-        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        _ptr: Pointer<Self::PointerTag>,
-        _size: Size,
+        _tag: Self::PointerTag,
+        _range: AllocRange,
     ) -> InterpResult<'tcx> {
         Ok(())
     }
@@ -396,32 +393,12 @@ pub trait Machine<'mir, 'tcx>: Sized {
         // By default, we do not support unwinding from panics
         Ok(StackPopJump::Normal)
     }
-
-    fn int_to_ptr(
-        _mem: &Memory<'mir, 'tcx, Self>,
-        int: u64,
-    ) -> InterpResult<'tcx, Pointer<Self::PointerTag>> {
-        Err((if int == 0 {
-            // This is UB, seriously.
-            // (`DanglingIntPointer` with these exact arguments has special printing code.)
-            err_ub!(DanglingIntPointer(0, CheckInAllocMsg::InboundsTest))
-        } else {
-            // This is just something we cannot support during const-eval.
-            err_unsup!(ReadBytesAsPointer)
-        })
-        .into())
-    }
-
-    fn ptr_to_int(
-        _mem: &Memory<'mir, 'tcx, Self>,
-        _ptr: Pointer<Self::PointerTag>,
-    ) -> InterpResult<'tcx, u64>;
 }
 
 // A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines
 // (CTFE and ConstProp) use the same instance.  Here, we share that code.
 pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
-    type PointerTag = ();
+    type PointerTag = AllocId;
     type ExtraFnVal = !;
 
     type MemoryMap =
@@ -463,20 +440,40 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
 
     #[inline(always)]
     fn init_allocation_extra<'b>(
-        _memory_extra: &Self::MemoryExtra,
+        _mem: &Memory<$mir, $tcx, Self>,
         _id: AllocId,
         alloc: Cow<'b, Allocation>,
         _kind: Option<MemoryKind<Self::MemoryKind>>,
-    ) -> (Cow<'b, Allocation<Self::PointerTag>>, Self::PointerTag) {
+    ) -> Cow<'b, Allocation<Self::PointerTag>> {
         // We do not use a tag so we can just cheaply forward the allocation
-        (alloc, ())
+        alloc
+    }
+
+    fn extern_static_base_pointer(
+        mem: &Memory<$mir, $tcx, Self>,
+        def_id: DefId,
+    ) -> InterpResult<$tcx, Pointer> {
+        // Use the `AllocId` associated with the `DefId`. Any actual *access* will fail.
+        Ok(Pointer::new(mem.tcx.create_static_alloc(def_id), Size::ZERO))
     }
 
     #[inline(always)]
-    fn tag_global_base_pointer(
-        _memory_extra: &Self::MemoryExtra,
-        _id: AllocId,
-    ) -> Self::PointerTag {
-        ()
+    fn tag_alloc_base_pointer(
+        _mem: &Memory<$mir, $tcx, Self>,
+        ptr: Pointer<AllocId>,
+    ) -> Pointer<AllocId> {
+        ptr
+    }
+
+    #[inline(always)]
+    fn ptr_from_addr(_mem: &Memory<$mir, $tcx, Self>, addr: u64) -> Pointer<Option<AllocId>> {
+        Pointer::new(None, Size::from_bytes(addr))
+    }
+
+    #[inline(always)]
+    fn ptr_get_alloc(_mem: &Memory<$mir, $tcx, Self>, ptr: Pointer<AllocId>) -> (AllocId, Size) {
+        // We know `offset` is relative to the allocation, so we can use `into_parts`.
+        let (alloc_id, offset) = ptr.into_parts();
+        (alloc_id, offset)
     }
 }
index 76073599e22b19d7b999d93d2108e631733424e2..6dcd944a1c3f22cc7645704784c76d9b1184a771 100644 (file)
@@ -9,7 +9,7 @@
 use std::assert_matches::assert_matches;
 use std::borrow::Cow;
 use std::collections::VecDeque;
-use std::convert::{TryFrom, TryInto};
+use std::convert::TryFrom;
 use std::fmt;
 use std::ptr;
 
@@ -20,7 +20,8 @@ use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
 
 use super::{
     alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc,
-    InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Scalar, ScalarMaybeUninit,
+    InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar,
+    ScalarMaybeUninit,
 };
 use crate::util::pretty;
 
@@ -28,8 +29,6 @@ use crate::util::pretty;
 pub enum MemoryKind<T> {
     /// Stack memory. Error if deallocated except during a stack pop.
     Stack,
-    /// Memory backing vtables. Error if ever deallocated.
-    Vtable,
     /// Memory allocated by `caller_location` intrinsic. Error if ever deallocated.
     CallerLocation,
     /// Additional memory kinds a machine wishes to distinguish from the builtin ones.
@@ -41,7 +40,6 @@ impl<T: MayLeak> MayLeak for MemoryKind<T> {
     fn may_leak(self) -> bool {
         match self {
             MemoryKind::Stack => false,
-            MemoryKind::Vtable => true,
             MemoryKind::CallerLocation => true,
             MemoryKind::Machine(k) => k.may_leak(),
         }
@@ -52,7 +50,6 @@ impl<T: fmt::Display> fmt::Display for MemoryKind<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             MemoryKind::Stack => write!(f, "stack variable"),
-            MemoryKind::Vtable => write!(f, "vtable"),
             MemoryKind::CallerLocation => write!(f, "caller location"),
             MemoryKind::Machine(m) => write!(f, "{}", m),
         }
@@ -167,25 +164,22 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     #[inline]
     pub fn global_base_pointer(
         &self,
-        mut ptr: Pointer,
+        ptr: Pointer<AllocId>,
     ) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
+        // We know `offset` is relative to the allocation, so we can use `into_parts`.
+        let (alloc_id, offset) = ptr.into_parts();
         // We need to handle `extern static`.
-        let ptr = match self.tcx.get_global_alloc(ptr.alloc_id) {
+        match self.tcx.get_global_alloc(alloc_id) {
             Some(GlobalAlloc::Static(def_id)) if self.tcx.is_thread_local_static(def_id) => {
                 bug!("global memory cannot point to thread-local static")
             }
             Some(GlobalAlloc::Static(def_id)) if self.tcx.is_foreign_item(def_id) => {
-                ptr.alloc_id = M::extern_static_alloc_id(self, def_id)?;
-                ptr
-            }
-            _ => {
-                // No need to change the `AllocId`.
-                ptr
+                return M::extern_static_base_pointer(self, def_id);
             }
-        };
+            _ => {}
+        }
         // And we need to get the tag.
-        let tag = M::tag_global_base_pointer(&self.extra, ptr.alloc_id);
-        Ok(ptr.with_tag(tag))
+        Ok(M::tag_alloc_base_pointer(self, Pointer::new(alloc_id, offset)))
     }
 
     pub fn create_fn_alloc(
@@ -212,9 +206,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         size: Size,
         align: Align,
         kind: MemoryKind<M::MemoryKind>,
-    ) -> Pointer<M::PointerTag> {
-        let alloc = Allocation::uninit(size, align);
-        self.allocate_with(alloc, kind)
+    ) -> InterpResult<'static, Pointer<M::PointerTag>> {
+        let alloc = Allocation::uninit(size, align, M::PANIC_ON_ALLOC_FAIL)?;
+        Ok(self.allocate_with(alloc, kind))
     }
 
     pub fn allocate_bytes(
@@ -239,21 +233,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             M::GLOBAL_KIND.map(MemoryKind::Machine),
             "dynamically allocating global memory"
         );
-        // This is a new allocation, not a new global one, so no `global_base_ptr`.
-        let (alloc, tag) = M::init_allocation_extra(&self.extra, id, Cow::Owned(alloc), Some(kind));
+        let alloc = M::init_allocation_extra(self, id, Cow::Owned(alloc), Some(kind));
         self.alloc_map.insert(id, (kind, alloc.into_owned()));
-        Pointer::from(id).with_tag(tag)
+        M::tag_alloc_base_pointer(self, Pointer::from(id))
     }
 
     pub fn reallocate(
         &mut self,
-        ptr: Pointer<M::PointerTag>,
+        ptr: Pointer<Option<M::PointerTag>>,
         old_size_and_align: Option<(Size, Align)>,
         new_size: Size,
         new_align: Align,
         kind: MemoryKind<M::MemoryKind>,
     ) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
-        if ptr.offset.bytes() != 0 {
+        let (alloc_id, offset, ptr) = self.ptr_get_alloc(ptr)?;
+        if offset.bytes() != 0 {
             throw_ub_format!(
                 "reallocating {:?} which does not point to the beginning of an object",
                 ptr
@@ -262,10 +256,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
 
         // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc".
         // This happens so rarely, the perf advantage is outweighed by the maintenance cost.
-        let new_ptr = self.allocate(new_size, new_align, kind);
+        let new_ptr = self.allocate(new_size, new_align, kind)?;
         let old_size = match old_size_and_align {
             Some((size, _align)) => size,
-            None => self.get_raw(ptr.alloc_id)?.size(),
+            None => self.get_raw(alloc_id)?.size(),
         };
         // This will also call the access hooks.
         self.copy(
@@ -276,61 +270,51 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             old_size.min(new_size),
             /*nonoverlapping*/ true,
         )?;
-        self.deallocate(ptr, old_size_and_align, kind)?;
+        self.deallocate(ptr.into(), old_size_and_align, kind)?;
 
         Ok(new_ptr)
     }
 
-    /// Deallocate a local, or do nothing if that local has been made into a global.
-    pub fn deallocate_local(&mut self, ptr: Pointer<M::PointerTag>) -> InterpResult<'tcx> {
-        // The allocation might be already removed by global interning.
-        // This can only really happen in the CTFE instance, not in miri.
-        if self.alloc_map.contains_key(&ptr.alloc_id) {
-            self.deallocate(ptr, None, MemoryKind::Stack)
-        } else {
-            Ok(())
-        }
-    }
-
     pub fn deallocate(
         &mut self,
-        ptr: Pointer<M::PointerTag>,
+        ptr: Pointer<Option<M::PointerTag>>,
         old_size_and_align: Option<(Size, Align)>,
         kind: MemoryKind<M::MemoryKind>,
     ) -> InterpResult<'tcx> {
-        trace!("deallocating: {}", ptr.alloc_id);
+        let (alloc_id, offset, ptr) = self.ptr_get_alloc(ptr)?;
+        trace!("deallocating: {}", alloc_id);
 
-        if ptr.offset.bytes() != 0 {
+        if offset.bytes() != 0 {
             throw_ub_format!(
                 "deallocating {:?} which does not point to the beginning of an object",
                 ptr
             );
         }
 
-        let (alloc_kind, mut alloc) = match self.alloc_map.remove(&ptr.alloc_id) {
+        let (alloc_kind, mut alloc) = match self.alloc_map.remove(&alloc_id) {
             Some(alloc) => alloc,
             None => {
                 // Deallocating global memory -- always an error
-                return Err(match self.tcx.get_global_alloc(ptr.alloc_id) {
+                return Err(match self.tcx.get_global_alloc(alloc_id) {
                     Some(GlobalAlloc::Function(..)) => {
-                        err_ub_format!("deallocating {}, which is a function", ptr.alloc_id)
+                        err_ub_format!("deallocating {}, which is a function", alloc_id)
                     }
                     Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => {
-                        err_ub_format!("deallocating {}, which is static memory", ptr.alloc_id)
+                        err_ub_format!("deallocating {}, which is static memory", alloc_id)
                     }
-                    None => err_ub!(PointerUseAfterFree(ptr.alloc_id)),
+                    None => err_ub!(PointerUseAfterFree(alloc_id)),
                 }
                 .into());
             }
         };
 
         if alloc.mutability == Mutability::Not {
-            throw_ub_format!("deallocating immutable allocation {}", ptr.alloc_id);
+            throw_ub_format!("deallocating immutable allocation {}", alloc_id);
         }
         if alloc_kind != kind {
             throw_ub_format!(
                 "deallocating {}, which is {} memory, using {} deallocation operation",
-                ptr.alloc_id,
+                alloc_id,
                 alloc_kind,
                 kind
             );
@@ -339,7 +323,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             if size != alloc.size() || align != alloc.align {
                 throw_ub_format!(
                     "incorrect layout on deallocation: {} has size {} and alignment {}, but gave size {} and alignment {}",
-                    ptr.alloc_id,
+                    alloc_id,
                     alloc.size().bytes(),
                     alloc.align.bytes(),
                     size.bytes(),
@@ -350,10 +334,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
 
         // Let the machine take some extra action
         let size = alloc.size();
-        M::memory_deallocated(&mut self.extra, &mut alloc.extra, ptr, size)?;
+        M::memory_deallocated(
+            &mut self.extra,
+            &mut alloc.extra,
+            ptr.provenance,
+            alloc_range(Size::ZERO, size),
+        )?;
 
         // Don't forget to remember size and align of this now-dead allocation
-        let old = self.dead_alloc_map.insert(ptr.alloc_id, (size, alloc.align));
+        let old = self.dead_alloc_map.insert(alloc_id, (size, alloc.align));
         if old.is_some() {
             bug!("Nothing can be deallocated twice");
         }
@@ -361,52 +350,69 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         Ok(())
     }
 
-    /// Internal helper function for APIs that offer memory access based on `Scalar` pointers.
+    /// Internal helper function to determine the allocation and offset of a pointer (if any).
     #[inline(always)]
-    pub(super) fn check_ptr_access(
+    fn get_ptr_access(
         &self,
-        sptr: Scalar<M::PointerTag>,
+        ptr: Pointer<Option<M::PointerTag>>,
         size: Size,
         align: Align,
-    ) -> InterpResult<'tcx, Option<Pointer<M::PointerTag>>> {
+    ) -> InterpResult<'tcx, Option<(AllocId, Size, Pointer<M::PointerTag>)>> {
         let align = M::enforce_alignment(&self.extra).then_some(align);
-        self.check_and_deref_ptr(sptr, size, align, CheckInAllocMsg::MemoryAccessTest, |ptr| {
-            let (size, align) =
-                self.get_size_and_align(ptr.alloc_id, AllocCheck::Dereferenceable)?;
-            Ok((size, align, ptr))
-        })
+        self.check_and_deref_ptr(
+            ptr,
+            size,
+            align,
+            CheckInAllocMsg::MemoryAccessTest,
+            |alloc_id, offset, ptr| {
+                let (size, align) =
+                    self.get_size_and_align(alloc_id, AllocCheck::Dereferenceable)?;
+                Ok((size, align, (alloc_id, offset, ptr)))
+            },
+        )
     }
 
-    /// Check if the given scalar is allowed to do a memory access of given `size` and `align`
+    /// Check if the given pointer points to live memory of given `size` and `align`
     /// (ignoring `M::enforce_alignment`). The caller can control the error message for the
     /// out-of-bounds case.
     #[inline(always)]
     pub fn check_ptr_access_align(
         &self,
-        sptr: Scalar<M::PointerTag>,
+        ptr: Pointer<Option<M::PointerTag>>,
         size: Size,
         align: Align,
         msg: CheckInAllocMsg,
     ) -> InterpResult<'tcx> {
-        self.check_and_deref_ptr(sptr, size, Some(align), msg, |ptr| {
-            let (size, align) =
-                self.get_size_and_align(ptr.alloc_id, AllocCheck::Dereferenceable)?;
+        self.check_and_deref_ptr(ptr, size, Some(align), msg, |alloc_id, _, _| {
+            let check = match msg {
+                CheckInAllocMsg::DerefTest | CheckInAllocMsg::MemoryAccessTest => {
+                    AllocCheck::Dereferenceable
+                }
+                CheckInAllocMsg::PointerArithmeticTest | CheckInAllocMsg::InboundsTest => {
+                    AllocCheck::Live
+                }
+            };
+            let (size, align) = self.get_size_and_align(alloc_id, check)?;
             Ok((size, align, ()))
         })?;
         Ok(())
     }
 
     /// Low-level helper function to check if a ptr is in-bounds and potentially return a reference
-    /// to the allocation it points to. Supports both shared and mutable references, to the actual
+    /// to the allocation it points to. Supports both shared and mutable references, as the actual
     /// checking is offloaded to a helper closure. `align` defines whether and which alignment check
     /// is done. Returns `None` for size 0, and otherwise `Some` of what `alloc_size` returned.
     fn check_and_deref_ptr<T>(
         &self,
-        sptr: Scalar<M::PointerTag>,
+        ptr: Pointer<Option<M::PointerTag>>,
         size: Size,
         align: Option<Align>,
         msg: CheckInAllocMsg,
-        alloc_size: impl FnOnce(Pointer<M::PointerTag>) -> InterpResult<'tcx, (Size, Align, T)>,
+        alloc_size: impl FnOnce(
+            AllocId,
+            Size,
+            Pointer<M::PointerTag>,
+        ) -> InterpResult<'tcx, (Size, Align, T)>,
     ) -> InterpResult<'tcx, Option<T>> {
         fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
             if offset % align.bytes() == 0 {
@@ -421,53 +427,56 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             }
         }
 
-        // Normalize to a `Pointer` if we definitely need one.
-        let normalized = if size.bytes() == 0 {
-            // Can be an integer, just take what we got.  We do NOT `force_bits` here;
-            // if this is already a `Pointer` we want to do the bounds checks!
-            sptr
+        // Extract from the pointer an `Option<AllocId>` and an offset, which is relative to the
+        // allocation or (if that is `None`) an absolute address.
+        let ptr_or_addr = if size.bytes() == 0 {
+            // Let's see what we can do, but don't throw errors if there's nothing there.
+            self.ptr_try_get_alloc(ptr)
         } else {
-            // A "real" access, we must get a pointer to be able to check the bounds.
-            Scalar::from(self.force_ptr(sptr)?)
+            // A "real" access, we insist on getting an `AllocId`.
+            Ok(self.ptr_get_alloc(ptr)?)
         };
-        Ok(match normalized.to_bits_or_ptr(self.pointer_size(), self) {
-            Ok(bits) => {
-                let bits = u64::try_from(bits).unwrap(); // it's ptr-sized
-                assert!(size.bytes() == 0);
+        Ok(match ptr_or_addr {
+            Err(addr) => {
+                // No memory is actually being accessed.
+                debug_assert!(size.bytes() == 0);
                 // Must be non-null.
-                if bits == 0 {
+                if addr == 0 {
                     throw_ub!(DanglingIntPointer(0, msg))
                 }
                 // Must be aligned.
                 if let Some(align) = align {
-                    check_offset_align(bits, align)?;
+                    check_offset_align(addr, align)?;
                 }
                 None
             }
-            Err(ptr) => {
-                let (allocation_size, alloc_align, ret_val) = alloc_size(ptr)?;
+            Ok((alloc_id, offset, ptr)) => {
+                let (alloc_size, alloc_align, ret_val) = alloc_size(alloc_id, offset, ptr)?;
                 // Test bounds. This also ensures non-null.
-                // It is sufficient to check this for the end pointer. The addition
-                // checks for overflow.
-                let end_ptr = ptr.offset(size, self)?;
-                if end_ptr.offset > allocation_size {
-                    // equal is okay!
-                    throw_ub!(PointerOutOfBounds { ptr: end_ptr.erase_tag(), msg, allocation_size })
+                // It is sufficient to check this for the end pointer. Also check for overflow!
+                if offset.checked_add(size, &self.tcx).map_or(true, |end| end > alloc_size) {
+                    throw_ub!(PointerOutOfBounds {
+                        alloc_id,
+                        alloc_size,
+                        ptr_offset: self.machine_usize_to_isize(offset.bytes()),
+                        ptr_size: size,
+                        msg,
+                    })
                 }
                 // Test align. Check this last; if both bounds and alignment are violated
                 // we want the error to be about the bounds.
                 if let Some(align) = align {
                     if M::force_int_for_alignment_check(&self.extra) {
-                        let bits = self
-                            .force_bits(ptr.into(), self.pointer_size())
+                        let addr = Scalar::from_pointer(ptr, &self.tcx)
+                            .to_machine_usize(&self.tcx)
                             .expect("ptr-to-int cast for align check should never fail");
-                        check_offset_align(bits.try_into().unwrap(), align)?;
+                        check_offset_align(addr, align)?;
                     } else {
                         // Check allocation alignment and offset alignment.
                         if alloc_align.bytes() < align.bytes() {
                             throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align });
                         }
-                        check_offset_align(ptr.offset.bytes(), align)?;
+                        check_offset_align(offset.bytes(), align)?;
                     }
                 }
 
@@ -479,13 +488,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     }
 
     /// Test if the pointer might be null.
-    pub fn ptr_may_be_null(&self, ptr: Pointer<M::PointerTag>) -> bool {
-        let (size, _align) = self
-            .get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead)
-            .expect("alloc info with MaybeDead cannot fail");
-        // If the pointer is out-of-bounds, it may be null.
-        // Note that one-past-the-end (offset == size) is still inbounds, and never null.
-        ptr.offset > size
+    pub fn ptr_may_be_null(&self, ptr: Pointer<Option<M::PointerTag>>) -> bool {
+        match self.ptr_try_get_alloc(ptr) {
+            Ok((alloc_id, offset, _)) => {
+                let (size, _align) = self
+                    .get_size_and_align(alloc_id, AllocCheck::MaybeDead)
+                    .expect("alloc info with MaybeDead cannot fail");
+                // If the pointer is out-of-bounds, it may be null.
+                // Note that one-past-the-end (offset == size) is still inbounds, and never null.
+                offset > size
+            }
+            Err(offset) => offset == 0,
+        }
     }
 }
 
@@ -497,12 +511,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     /// this machine use the same pointer tag, so it is indirected through
     /// `M::tag_allocation`.
     fn get_global_alloc(
-        memory_extra: &M::MemoryExtra,
-        tcx: TyCtxt<'tcx>,
+        &self,
         id: AllocId,
         is_write: bool,
     ) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::PointerTag, M::AllocExtra>>> {
-        let (alloc, def_id) = match tcx.get_global_alloc(id) {
+        let (alloc, def_id) = match self.tcx.get_global_alloc(id) {
             Some(GlobalAlloc::Memory(mem)) => {
                 // Memory of a constant or promoted or anonymous memory referenced by a static.
                 (mem, None)
@@ -510,8 +523,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             Some(GlobalAlloc::Function(..)) => throw_ub!(DerefFunctionPointer(id)),
             None => throw_ub!(PointerUseAfterFree(id)),
             Some(GlobalAlloc::Static(def_id)) => {
-                assert!(tcx.is_static(def_id));
-                assert!(!tcx.is_thread_local_static(def_id));
+                assert!(self.tcx.is_static(def_id));
+                assert!(!self.tcx.is_thread_local_static(def_id));
                 // Notice that every static has two `AllocId` that will resolve to the same
                 // thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID,
                 // and the other one is maps to `GlobalAlloc::Memory`, this is returned by
@@ -522,24 +535,22 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                 // The `GlobalAlloc::Memory` branch here is still reachable though; when a static
                 // contains a reference to memory that was created during its evaluation (i.e., not
                 // to another static), those inner references only exist in "resolved" form.
-                if tcx.is_foreign_item(def_id) {
+                if self.tcx.is_foreign_item(def_id) {
                     throw_unsup!(ReadExternStatic(def_id));
                 }
 
-                (tcx.eval_static_initializer(def_id)?, Some(def_id))
+                (self.tcx.eval_static_initializer(def_id)?, Some(def_id))
             }
         };
-        M::before_access_global(memory_extra, id, alloc, def_id, is_write)?;
+        M::before_access_global(&self.extra, id, alloc, def_id, is_write)?;
         let alloc = Cow::Borrowed(alloc);
         // We got tcx memory. Let the machine initialize its "extra" stuff.
-        let (alloc, tag) = M::init_allocation_extra(
-            memory_extra,
+        let alloc = M::init_allocation_extra(
+            self,
             id, // always use the ID we got as input, not the "hidden" one.
             alloc,
             M::GLOBAL_KIND.map(MemoryKind::Machine),
         );
-        // Sanity check that this is the same pointer we would have gotten via `global_base_pointer`.
-        debug_assert_eq!(tag, M::tag_global_base_pointer(memory_extra, id));
         Ok(alloc)
     }
 
@@ -554,8 +565,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         // `get_global_alloc` that we can actually use directly without inserting anything anywhere.
         // So the error type is `InterpResult<'tcx, &Allocation<M::PointerTag>>`.
         let a = self.alloc_map.get_or(id, || {
-            let alloc = Self::get_global_alloc(&self.extra, self.tcx, id, /*is_write*/ false)
-                .map_err(Err)?;
+            let alloc = self.get_global_alloc(id, /*is_write*/ false).map_err(Err)?;
             match alloc {
                 Cow::Borrowed(alloc) => {
                     // We got a ref, cheaply return that as an "error" so that the
@@ -582,30 +592,30 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     /// "Safe" (bounds and align-checked) allocation access.
     pub fn get<'a>(
         &'a self,
-        sptr: Scalar<M::PointerTag>,
+        ptr: Pointer<Option<M::PointerTag>>,
         size: Size,
         align: Align,
     ) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::PointerTag, M::AllocExtra>>> {
         let align = M::enforce_alignment(&self.extra).then_some(align);
         let ptr_and_alloc = self.check_and_deref_ptr(
-            sptr,
+            ptr,
             size,
             align,
             CheckInAllocMsg::MemoryAccessTest,
-            |ptr| {
-                let alloc = self.get_raw(ptr.alloc_id)?;
-                Ok((alloc.size(), alloc.align, (ptr, alloc)))
+            |alloc_id, offset, ptr| {
+                let alloc = self.get_raw(alloc_id)?;
+                Ok((alloc.size(), alloc.align, (alloc_id, offset, ptr, alloc)))
             },
         )?;
-        if let Some((ptr, alloc)) = ptr_and_alloc {
-            M::memory_read(&self.extra, &alloc.extra, ptr, size)?;
-            let range = alloc_range(ptr.offset, size);
-            Ok(Some(AllocRef { alloc, range, tcx: self.tcx, alloc_id: ptr.alloc_id }))
+        if let Some((alloc_id, offset, ptr, alloc)) = ptr_and_alloc {
+            let range = alloc_range(offset, size);
+            M::memory_read(&self.extra, &alloc.extra, ptr.provenance, range)?;
+            Ok(Some(AllocRef { alloc, range, tcx: self.tcx, alloc_id }))
         } else {
             // Even in this branch we have to be sure that we actually access the allocation, in
             // order to ensure that `static FOO: Type = FOO;` causes a cycle error instead of
             // magically pulling *any* ZST value from the ether. However, the `get_raw` above is
-            // always called when `sptr` is truly a `Pointer`, so we are good.
+            // always called when `ptr` has an `AllocId`.
             Ok(None)
         }
     }
@@ -625,48 +635,44 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         id: AllocId,
     ) -> InterpResult<'tcx, (&mut Allocation<M::PointerTag, M::AllocExtra>, &mut M::MemoryExtra)>
     {
-        let tcx = self.tcx;
-        let memory_extra = &mut self.extra;
-        let a = self.alloc_map.get_mut_or(id, || {
-            // Need to make a copy, even if `get_global_alloc` is able
-            // to give us a cheap reference.
-            let alloc = Self::get_global_alloc(memory_extra, tcx, id, /*is_write*/ true)?;
+        // We have "NLL problem case #3" here, which cannot be worked around without loss of
+        // efficiency even for the common case where the key is in the map.
+        // <https://rust-lang.github.io/rfcs/2094-nll.html#problem-case-3-conditional-control-flow-across-functions>
+        // (Cannot use `get_mut_or` since `get_global_alloc` needs `&self`.)
+        if self.alloc_map.get_mut(id).is_none() {
+            // Slow path.
+            // Allocation not found locally, go look global.
+            let alloc = self.get_global_alloc(id, /*is_write*/ true)?;
             let kind = M::GLOBAL_KIND.expect(
                 "I got a global allocation that I have to copy but the machine does \
                     not expect that to happen",
             );
-            Ok((MemoryKind::Machine(kind), alloc.into_owned()))
-        });
-        // Unpack the error type manually because type inference doesn't
-        // work otherwise (and we cannot help it because `impl Trait`)
-        match a {
-            Err(e) => Err(e),
-            Ok(a) => {
-                let a = &mut a.1;
-                if a.mutability == Mutability::Not {
-                    throw_ub!(WriteToReadOnly(id))
-                }
-                Ok((a, memory_extra))
-            }
+            self.alloc_map.insert(id, (MemoryKind::Machine(kind), alloc.into_owned()));
+        }
+
+        let (_kind, alloc) = self.alloc_map.get_mut(id).unwrap();
+        if alloc.mutability == Mutability::Not {
+            throw_ub!(WriteToReadOnly(id))
         }
+        Ok((alloc, &mut self.extra))
     }
 
     /// "Safe" (bounds and align-checked) allocation access.
     pub fn get_mut<'a>(
         &'a mut self,
-        sptr: Scalar<M::PointerTag>,
+        ptr: Pointer<Option<M::PointerTag>>,
         size: Size,
         align: Align,
     ) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::PointerTag, M::AllocExtra>>> {
-        let ptr = self.check_ptr_access(sptr, size, align)?;
-        if let Some(ptr) = ptr {
+        let parts = self.get_ptr_access(ptr, size, align)?;
+        if let Some((alloc_id, offset, ptr)) = parts {
             let tcx = self.tcx;
             // FIXME: can we somehow avoid looking up the allocation twice here?
             // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`.
-            let (alloc, extra) = self.get_raw_mut(ptr.alloc_id)?;
-            M::memory_written(extra, &mut alloc.extra, ptr, size)?;
-            let range = alloc_range(ptr.offset, size);
-            Ok(Some(AllocRefMut { alloc, range, tcx, alloc_id: ptr.alloc_id }))
+            let (alloc, extra) = self.get_raw_mut(alloc_id)?;
+            let range = alloc_range(offset, size);
+            M::memory_written(extra, &mut alloc.extra, ptr.provenance, range)?;
+            Ok(Some(AllocRefMut { alloc, range, tcx, alloc_id }))
         } else {
             Ok(None)
         }
@@ -743,7 +749,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     }
 
     fn get_fn_alloc(&self, id: AllocId) -> Option<FnVal<'tcx, M::ExtraFnVal>> {
-        trace!("reading fn ptr: {}", id);
         if let Some(extra) = self.extra_fn_ptr_map.get(&id) {
             Some(FnVal::Other(*extra))
         } else {
@@ -756,14 +761,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
 
     pub fn get_fn(
         &self,
-        ptr: Scalar<M::PointerTag>,
+        ptr: Pointer<Option<M::PointerTag>>,
     ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
-        let ptr = self.force_ptr(ptr)?; // We definitely need a pointer value.
-        if ptr.offset.bytes() != 0 {
-            throw_ub!(InvalidFunctionPointer(ptr.erase_tag()))
+        trace!("get_fn({:?})", ptr);
+        let (alloc_id, offset, _ptr) = self.ptr_get_alloc(ptr)?;
+        if offset.bytes() != 0 {
+            throw_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset)))
         }
-        self.get_fn_alloc(ptr.alloc_id)
-            .ok_or_else(|| err_ub!(InvalidFunctionPointer(ptr.erase_tag())).into())
+        self.get_fn_alloc(alloc_id)
+            .ok_or_else(|| err_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))).into())
     }
 
     pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> {
@@ -802,7 +808,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                 if reachable.insert(id) {
                     // This is a new allocation, add its relocations to `todo`.
                     if let Some((_, alloc)) = self.alloc_map.get(id) {
-                        todo.extend(alloc.relocations().values().map(|&(_, target_id)| target_id));
+                        todo.extend(alloc.relocations().values().map(|tag| tag.get_alloc_id()));
                     }
                 }
             }
@@ -836,14 +842,14 @@ pub struct DumpAllocs<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, 'mir, 'tcx, M> {
     fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         // Cannot be a closure because it is generic in `Tag`, `Extra`.
-        fn write_allocation_track_relocs<'tcx, Tag: Copy + fmt::Debug, Extra>(
+        fn write_allocation_track_relocs<'tcx, Tag: Provenance, Extra>(
             fmt: &mut std::fmt::Formatter<'_>,
             tcx: TyCtxt<'tcx>,
             allocs_to_print: &mut VecDeque<AllocId>,
             alloc: &Allocation<Tag, Extra>,
         ) -> std::fmt::Result {
-            for &(_, target_id) in alloc.relocations().values() {
-                allocs_to_print.push_back(target_id);
+            for alloc_id in alloc.relocations().values().map(|tag| tag.get_alloc_id()) {
+                allocs_to_print.push_back(alloc_id);
             }
             write!(fmt, "{}", pretty::display_allocation(tcx, alloc))
         }
@@ -946,8 +952,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     /// Reads the given number of bytes from memory. Returns them as a slice.
     ///
     /// Performs appropriate bounds checks.
-    pub fn read_bytes(&self, sptr: Scalar<M::PointerTag>, size: Size) -> InterpResult<'tcx, &[u8]> {
-        let alloc_ref = match self.get(sptr, size, Align::ONE)? {
+    pub fn read_bytes(
+        &self,
+        ptr: Pointer<Option<M::PointerTag>>,
+        size: Size,
+    ) -> InterpResult<'tcx, &[u8]> {
+        let alloc_ref = match self.get(ptr, size, Align::ONE)? {
             Some(a) => a,
             None => return Ok(&[]), // zero-sized access
         };
@@ -964,7 +974,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     /// Performs appropriate bounds checks.
     pub fn write_bytes(
         &mut self,
-        sptr: Scalar<M::PointerTag>,
+        ptr: Pointer<Option<M::PointerTag>>,
         src: impl IntoIterator<Item = u8>,
     ) -> InterpResult<'tcx> {
         let mut src = src.into_iter();
@@ -973,7 +983,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         assert_eq!(lower, len, "can only write iterators with a precise length");
 
         let size = Size::from_bytes(len);
-        let alloc_ref = match self.get_mut(sptr, size, Align::ONE)? {
+        let alloc_ref = match self.get_mut(ptr, size, Align::ONE)? {
             Some(alloc_ref) => alloc_ref,
             None => {
                 // zero-sized access
@@ -1000,9 +1010,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
 
     pub fn copy(
         &mut self,
-        src: Scalar<M::PointerTag>,
+        src: Pointer<Option<M::PointerTag>>,
         src_align: Align,
-        dest: Scalar<M::PointerTag>,
+        dest: Pointer<Option<M::PointerTag>>,
         dest_align: Align,
         size: Size,
         nonoverlapping: bool,
@@ -1012,9 +1022,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
 
     pub fn copy_repeatedly(
         &mut self,
-        src: Scalar<M::PointerTag>,
+        src: Pointer<Option<M::PointerTag>>,
         src_align: Align,
-        dest: Scalar<M::PointerTag>,
+        dest: Pointer<Option<M::PointerTag>>,
         dest_align: Align,
         size: Size,
         num_copies: u64,
@@ -1022,22 +1032,23 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx> {
         let tcx = self.tcx;
         // We need to do our own bounds-checks.
-        let src = self.check_ptr_access(src, size, src_align)?;
-        let dest = self.check_ptr_access(dest, size * num_copies, dest_align)?; // `Size` multiplication
+        let src_parts = self.get_ptr_access(src, size, src_align)?;
+        let dest_parts = self.get_ptr_access(dest, size * num_copies, dest_align)?; // `Size` multiplication
 
         // FIXME: we look up both allocations twice here, once ebfore for the `check_ptr_access`
         // and once below to get the underlying `&[mut] Allocation`.
 
         // Source alloc preparations and access hooks.
-        let src = match src {
+        let (src_alloc_id, src_offset, src) = match src_parts {
             None => return Ok(()), // Zero-sized *source*, that means dst is also zero-sized and we have nothing to do.
             Some(src_ptr) => src_ptr,
         };
-        let src_alloc = self.get_raw(src.alloc_id)?;
-        M::memory_read(&self.extra, &src_alloc.extra, src, size)?;
+        let src_alloc = self.get_raw(src_alloc_id)?;
+        let src_range = alloc_range(src_offset, size);
+        M::memory_read(&self.extra, &src_alloc.extra, src.provenance, src_range)?;
         // We need the `dest` ptr for the next operation, so we get it now.
         // We already did the source checks and called the hooks so we are good to return early.
-        let dest = match dest {
+        let (dest_alloc_id, dest_offset, dest) = match dest_parts {
             None => return Ok(()), // Zero-sized *destiantion*.
             Some(dest_ptr) => dest_ptr,
         };
@@ -1047,26 +1058,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         // since we don't want to keep any relocations at the target.
         // (`get_bytes_with_uninit_and_ptr` below checks that there are no
         // relocations overlapping the edges; those would not be handled correctly).
-        let relocations = src_alloc.prepare_relocation_copy(
-            self,
-            alloc_range(src.offset, size),
-            dest.offset,
-            num_copies,
-        );
+        let relocations =
+            src_alloc.prepare_relocation_copy(self, src_range, dest_offset, num_copies);
         // Prepare a copy of the initialization mask.
-        let compressed = src_alloc.compress_uninit_range(src, size);
+        let compressed = src_alloc.compress_uninit_range(src_range);
         // This checks relocation edges on the src.
         let src_bytes = src_alloc
-            .get_bytes_with_uninit_and_ptr(&tcx, alloc_range(src.offset, size))
-            .map_err(|e| e.to_interp_error(src.alloc_id))?
+            .get_bytes_with_uninit_and_ptr(&tcx, src_range)
+            .map_err(|e| e.to_interp_error(src_alloc_id))?
             .as_ptr(); // raw ptr, so we can also get a ptr to the destination allocation
 
         // Destination alloc preparations and access hooks.
-        let (dest_alloc, extra) = self.get_raw_mut(dest.alloc_id)?;
-        M::memory_written(extra, &mut dest_alloc.extra, dest, size * num_copies)?;
-        let dest_bytes = dest_alloc
-            .get_bytes_mut_ptr(&tcx, alloc_range(dest.offset, size * num_copies))
-            .as_mut_ptr();
+        let (dest_alloc, extra) = self.get_raw_mut(dest_alloc_id)?;
+        let dest_range = alloc_range(dest_offset, size * num_copies);
+        M::memory_written(extra, &mut dest_alloc.extra, dest.provenance, dest_range)?;
+        let dest_bytes = dest_alloc.get_bytes_mut_ptr(&tcx, dest_range).as_mut_ptr();
 
         if compressed.no_bytes_init() {
             // Fast path: If all bytes are `uninit` then there is nothing to copy. The target range
@@ -1075,7 +1081,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             // This also avoids writing to the target bytes so that the backing allocation is never
             // touched if the bytes stay uninitialized for the whole interpreter execution. On contemporary
             // operating system this can avoid physically allocating the page.
-            dest_alloc.mark_init(alloc_range(dest.offset, size * num_copies), false); // `Size` multiplication
+            dest_alloc.mark_init(dest_range, false); // `Size` multiplication
             dest_alloc.mark_relocation_range(relocations);
             return Ok(());
         }
@@ -1086,11 +1092,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         // The pointers above remain valid even if the `HashMap` table is moved around because they
         // point into the `Vec` storing the bytes.
         unsafe {
-            if src.alloc_id == dest.alloc_id {
+            if src_alloc_id == dest_alloc_id {
                 if nonoverlapping {
                     // `Size` additions
-                    if (src.offset <= dest.offset && src.offset + size > dest.offset)
-                        || (dest.offset <= src.offset && dest.offset + size > src.offset)
+                    if (src_offset <= dest_offset && src_offset + size > dest_offset)
+                        || (dest_offset <= src_offset && dest_offset + size > src_offset)
                     {
                         throw_ub_format!("copy_nonoverlapping called on overlapping ranges")
                     }
@@ -1115,7 +1121,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         }
 
         // now fill in all the "init" data
-        dest_alloc.mark_compressed_init_range(&compressed, dest, size, num_copies);
+        dest_alloc.mark_compressed_init_range(
+            &compressed,
+            alloc_range(dest_offset, size), // just a single copy (i.e., not full `dest_range`)
+            num_copies,
+        );
         // copy the relocations to the destination
         dest_alloc.mark_relocation_range(relocations);
 
@@ -1125,24 +1135,41 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
 
 /// Machine pointer introspection.
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
-    pub fn force_ptr(
-        &self,
-        scalar: Scalar<M::PointerTag>,
-    ) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
-        match scalar {
-            Scalar::Ptr(ptr) => Ok(ptr),
-            _ => M::int_to_ptr(&self, scalar.to_machine_usize(self)?),
+    pub fn scalar_to_ptr(&self, scalar: Scalar<M::PointerTag>) -> Pointer<Option<M::PointerTag>> {
+        // We use `to_bits_or_ptr_internal` since we are just implementing the method people need to
+        // call to force getting out a pointer.
+        match scalar.to_bits_or_ptr_internal(self.pointer_size()) {
+            Err(ptr) => ptr.into(),
+            Ok(bits) => {
+                let addr = u64::try_from(bits).unwrap();
+                M::ptr_from_addr(&self, addr)
+            }
         }
     }
 
-    pub fn force_bits(
+    /// Turning a "maybe pointer" into a proper pointer (and some information
+    /// about where it points), or an absolute address.
+    pub fn ptr_try_get_alloc(
         &self,
-        scalar: Scalar<M::PointerTag>,
-        size: Size,
-    ) -> InterpResult<'tcx, u128> {
-        match scalar.to_bits_or_ptr(size, self) {
-            Ok(bits) => Ok(bits),
-            Err(ptr) => Ok(M::ptr_to_int(&self, ptr)?.into()),
+        ptr: Pointer<Option<M::PointerTag>>,
+    ) -> Result<(AllocId, Size, Pointer<M::PointerTag>), u64> {
+        match ptr.into_pointer_or_addr() {
+            Ok(ptr) => {
+                let (alloc_id, offset) = M::ptr_get_alloc(self, ptr);
+                Ok((alloc_id, offset, ptr))
+            }
+            Err(addr) => Err(addr.bytes()),
         }
     }
+
+    /// Turning a "maybe pointer" into a proper pointer (and some information about where it points).
+    #[inline(always)]
+    pub fn ptr_get_alloc(
+        &self,
+        ptr: Pointer<Option<M::PointerTag>>,
+    ) -> InterpResult<'tcx, (AllocId, Size, Pointer<M::PointerTag>)> {
+        self.ptr_try_get_alloc(ptr).map_err(|offset| {
+            err_ub!(DanglingIntPointer(offset, CheckInAllocMsg::InboundsTest)).into()
+        })
+    }
 }
index 06432a8b9024b341f7f2e42495f7510f100614bb..aba7db7816843001930e9a2f1cf58478617b1e3b 100644 (file)
@@ -15,8 +15,9 @@ use rustc_target::abi::{Abi, HasDataLayout, LayoutOf, Size, TagEncoding};
 use rustc_target::abi::{VariantIdx, Variants};
 
 use super::{
-    alloc_range, from_known_layout, mir_assign_valid_types, ConstValue, GlobalId, InterpCx,
-    InterpResult, MPlaceTy, Machine, MemPlace, Place, PlaceTy, Pointer, Scalar, ScalarMaybeUninit,
+    alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, GlobalId,
+    InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, Place, PlaceTy, Pointer, Provenance,
+    Scalar, ScalarMaybeUninit,
 };
 
 /// An `Immediate` represents a single immediate self-contained Rust value.
@@ -26,8 +27,8 @@ use super::{
 /// operations and wide pointers. This idea was taken from rustc's codegen.
 /// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely
 /// defined on `Immediate`, and do not have to work with a `Place`.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, Hash)]
-pub enum Immediate<Tag = ()> {
+#[derive(Copy, Clone, PartialEq, Eq, HashStable, Hash, Debug)]
+pub enum Immediate<Tag: Provenance = AllocId> {
     Scalar(ScalarMaybeUninit<Tag>),
     ScalarPair(ScalarMaybeUninit<Tag>, ScalarMaybeUninit<Tag>),
 }
@@ -35,34 +36,35 @@ pub enum Immediate<Tag = ()> {
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 rustc_data_structures::static_assert_size!(Immediate, 56);
 
-impl<Tag> From<ScalarMaybeUninit<Tag>> for Immediate<Tag> {
+impl<Tag: Provenance> From<ScalarMaybeUninit<Tag>> for Immediate<Tag> {
     #[inline(always)]
     fn from(val: ScalarMaybeUninit<Tag>) -> Self {
         Immediate::Scalar(val)
     }
 }
 
-impl<Tag> From<Scalar<Tag>> for Immediate<Tag> {
+impl<Tag: Provenance> From<Scalar<Tag>> for Immediate<Tag> {
     #[inline(always)]
     fn from(val: Scalar<Tag>) -> Self {
         Immediate::Scalar(val.into())
     }
 }
 
-impl<Tag> From<Pointer<Tag>> for Immediate<Tag> {
-    #[inline(always)]
-    fn from(val: Pointer<Tag>) -> Self {
-        Immediate::Scalar(Scalar::from(val).into())
+impl<'tcx, Tag: Provenance> Immediate<Tag> {
+    pub fn from_pointer(p: Pointer<Tag>, cx: &impl HasDataLayout) -> Self {
+        Immediate::Scalar(ScalarMaybeUninit::from_pointer(p, cx))
+    }
+
+    pub fn from_maybe_pointer(p: Pointer<Option<Tag>>, cx: &impl HasDataLayout) -> Self {
+        Immediate::Scalar(ScalarMaybeUninit::from_maybe_pointer(p, cx))
     }
-}
 
-impl<'tcx, Tag> Immediate<Tag> {
     pub fn new_slice(val: Scalar<Tag>, len: u64, cx: &impl HasDataLayout) -> Self {
         Immediate::ScalarPair(val.into(), Scalar::from_machine_usize(len, cx).into())
     }
 
-    pub fn new_dyn_trait(val: Scalar<Tag>, vtable: Pointer<Tag>) -> Self {
-        Immediate::ScalarPair(val.into(), vtable.into())
+    pub fn new_dyn_trait(val: Scalar<Tag>, vtable: Pointer<Tag>, cx: &impl HasDataLayout) -> Self {
+        Immediate::ScalarPair(val.into(), ScalarMaybeUninit::from_pointer(vtable, cx))
     }
 
     #[inline]
@@ -82,7 +84,7 @@ impl<'tcx, Tag> Immediate<Tag> {
 // ScalarPair needs a type to interpret, so we often have an immediate and a type together
 // as input for binary and cast operations.
 #[derive(Copy, Clone, Debug)]
-pub struct ImmTy<'tcx, Tag = ()> {
+pub struct ImmTy<'tcx, Tag: Provenance = AllocId> {
     imm: Immediate<Tag>,
     pub layout: TyAndLayout<'tcx>,
 }
@@ -90,17 +92,23 @@ pub struct ImmTy<'tcx, Tag = ()> {
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 rustc_data_structures::static_assert_size!(ImmTy<'_>, 72);
 
-impl<Tag: Copy> std::fmt::Display for ImmTy<'tcx, Tag> {
+impl<Tag: Provenance> std::fmt::Display for ImmTy<'tcx, Tag> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         /// Helper function for printing a scalar to a FmtPrinter
-        fn p<'a, 'tcx, F: std::fmt::Write, Tag>(
+        fn p<'a, 'tcx, F: std::fmt::Write, Tag: Provenance>(
             cx: FmtPrinter<'a, 'tcx, F>,
             s: ScalarMaybeUninit<Tag>,
             ty: Ty<'tcx>,
         ) -> Result<FmtPrinter<'a, 'tcx, F>, std::fmt::Error> {
             match s {
-                ScalarMaybeUninit::Scalar(s) => {
-                    cx.pretty_print_const_scalar(s.erase_tag(), ty, true)
+                ScalarMaybeUninit::Scalar(Scalar::Int(int)) => {
+                    cx.pretty_print_const_scalar_int(int, ty, true)
+                }
+                ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr, _sz)) => {
+                    // Just print the ptr value. `pretty_print_const_scalar_ptr` would also try to
+                    // print what is points to, which would fail since it has no access to the local
+                    // memory.
+                    cx.pretty_print_const_pointer(ptr, ty, true)
                 }
                 ScalarMaybeUninit::Uninit => cx.typed_value(
                     |mut this| {
@@ -120,18 +128,18 @@ impl<Tag: Copy> std::fmt::Display for ImmTy<'tcx, Tag> {
                         p(cx, s, ty)?;
                         return Ok(());
                     }
-                    write!(f, "{}: {}", s.erase_tag(), self.layout.ty)
+                    write!(f, "{}: {}", s, self.layout.ty)
                 }
                 Immediate::ScalarPair(a, b) => {
                     // FIXME(oli-obk): at least print tuples and slices nicely
-                    write!(f, "({}, {}): {}", a.erase_tag(), b.erase_tag(), self.layout.ty,)
+                    write!(f, "({}, {}): {}", a, b, self.layout.ty,)
                 }
             }
         })
     }
 }
 
-impl<'tcx, Tag> std::ops::Deref for ImmTy<'tcx, Tag> {
+impl<'tcx, Tag: Provenance> std::ops::Deref for ImmTy<'tcx, Tag> {
     type Target = Immediate<Tag>;
     #[inline(always)]
     fn deref(&self) -> &Immediate<Tag> {
@@ -142,22 +150,22 @@ impl<'tcx, Tag> std::ops::Deref for ImmTy<'tcx, Tag> {
 /// An `Operand` is the result of computing a `mir::Operand`. It can be immediate,
 /// or still in memory. The latter is an optimization, to delay reading that chunk of
 /// memory and to avoid having to store arbitrary-sized data here.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, Hash)]
-pub enum Operand<Tag = ()> {
+#[derive(Copy, Clone, PartialEq, Eq, HashStable, Hash, Debug)]
+pub enum Operand<Tag: Provenance = AllocId> {
     Immediate(Immediate<Tag>),
     Indirect(MemPlace<Tag>),
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub struct OpTy<'tcx, Tag = ()> {
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub struct OpTy<'tcx, Tag: Provenance = AllocId> {
     op: Operand<Tag>, // Keep this private; it helps enforce invariants.
     pub layout: TyAndLayout<'tcx>,
 }
 
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(OpTy<'_, ()>, 80);
+rustc_data_structures::static_assert_size!(OpTy<'_>, 80);
 
-impl<'tcx, Tag> std::ops::Deref for OpTy<'tcx, Tag> {
+impl<'tcx, Tag: Provenance> std::ops::Deref for OpTy<'tcx, Tag> {
     type Target = Operand<Tag>;
     #[inline(always)]
     fn deref(&self) -> &Operand<Tag> {
@@ -165,28 +173,28 @@ impl<'tcx, Tag> std::ops::Deref for OpTy<'tcx, Tag> {
     }
 }
 
-impl<'tcx, Tag: Copy> From<MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
+impl<'tcx, Tag: Provenance> From<MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
     #[inline(always)]
     fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self {
         OpTy { op: Operand::Indirect(*mplace), layout: mplace.layout }
     }
 }
 
-impl<'tcx, Tag: Copy> From<&'_ MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
+impl<'tcx, Tag: Provenance> From<&'_ MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
     #[inline(always)]
     fn from(mplace: &MPlaceTy<'tcx, Tag>) -> Self {
         OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout }
     }
 }
 
-impl<'tcx, Tag> From<ImmTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
+impl<'tcx, Tag: Provenance> From<ImmTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
     #[inline(always)]
     fn from(val: ImmTy<'tcx, Tag>) -> Self {
         OpTy { op: Operand::Immediate(val.imm), layout: val.layout }
     }
 }
 
-impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> {
+impl<'tcx, Tag: Provenance> ImmTy<'tcx, Tag> {
     #[inline]
     pub fn from_scalar(val: Scalar<Tag>, layout: TyAndLayout<'tcx>) -> Self {
         ImmTy { imm: val.into(), layout }
@@ -225,19 +233,6 @@ impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> {
 }
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
-    /// Normalize `place.ptr` to a `Pointer` if this is a place and not a ZST.
-    /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot.
-    #[inline]
-    pub fn force_op_ptr(
-        &self,
-        op: &OpTy<'tcx, M::PointerTag>,
-    ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        match op.try_as_mplace(self) {
-            Ok(mplace) => Ok(self.force_mplace_ptr(mplace)?.into()),
-            Err(imm) => Ok(imm.into()), // Nothing to cast/force
-        }
-    }
-
     /// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`.
     /// Returns `None` if the layout does not permit loading this as a value.
     fn try_read_immediate_from_mplace(
@@ -291,7 +286,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         &self,
         src: &OpTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx, Result<ImmTy<'tcx, M::PointerTag>, MPlaceTy<'tcx, M::PointerTag>>> {
-        Ok(match src.try_as_mplace(self) {
+        Ok(match src.try_as_mplace() {
             Ok(ref mplace) => {
                 if let Some(val) = self.try_read_immediate_from_mplace(mplace)? {
                     Ok(val)
@@ -324,6 +319,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(self.read_immediate(op)?.to_scalar_or_uninit())
     }
 
+    /// Read a pointer from a place.
+    pub fn read_pointer(
+        &self,
+        op: &OpTy<'tcx, M::PointerTag>,
+    ) -> InterpResult<'tcx, Pointer<Option<M::PointerTag>>> {
+        Ok(self.scalar_to_ptr(self.read_scalar(op)?.check_init()?))
+    }
+
     // Turn the wide MPlace into a string (must already be dereferenced!)
     pub fn read_str(&self, mplace: &MPlaceTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, &str> {
         let len = mplace.len(self)?;
@@ -338,7 +341,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         op: &OpTy<'tcx, M::PointerTag>,
         field: usize,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        let base = match op.try_as_mplace(self) {
+        let base = match op.try_as_mplace() {
             Ok(ref mplace) => {
                 // We can reuse the mplace field computation logic for indirect operands.
                 let field = self.mplace_field(mplace, field)?;
@@ -381,7 +384,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             self.operand_field(op, index)
         } else {
             // Indexing into a big array. This must be an mplace.
-            let mplace = op.assert_mem_place(self);
+            let mplace = op.assert_mem_place();
             Ok(self.mplace_index(&mplace, index)?.into())
         }
     }
@@ -392,7 +395,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         variant: VariantIdx,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         // Downcasts only change the layout
-        Ok(match op.try_as_mplace(self) {
+        Ok(match op.try_as_mplace() {
             Ok(ref mplace) => self.mplace_downcast(mplace, variant)?.into(),
             Err(..) => {
                 let layout = op.layout.for_variant(self, variant);
@@ -414,7 +417,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             Subslice { .. } | ConstantIndex { .. } | Index(_) => {
                 // The rest should only occur as mplace, we do not use Immediates for types
                 // allowing such operations.  This matches place_projection forcing an allocation.
-                let mplace = base.assert_mem_place(self);
+                let mplace = base.assert_mem_place();
                 self.mplace_projection(&mplace, proj_elem)?.into()
             }
         })
@@ -569,7 +572,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // Other cases need layout.
         let tag_scalar = |scalar| -> InterpResult<'tcx, _> {
             Ok(match scalar {
-                Scalar::Ptr(ptr) => Scalar::Ptr(self.global_base_pointer(ptr)?),
+                Scalar::Ptr(ptr, size) => Scalar::Ptr(self.global_base_pointer(ptr)?, size),
                 Scalar::Int(int) => Scalar::Int(int),
             })
         };
@@ -580,9 +583,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // We rely on mutability being set correctly in that allocation to prevent writes
                 // where none should happen.
                 let ptr = self.global_base_pointer(Pointer::new(id, offset))?;
-                Operand::Indirect(MemPlace::from_ptr(ptr, layout.align.abi))
+                Operand::Indirect(MemPlace::from_ptr(ptr.into(), layout.align.abi))
             }
-            ConstValue::Scalar(x) => Operand::Immediate(tag_scalar(x)?.into()),
+            ConstValue::Scalar(x) => Operand::Immediate(tag_scalar(x.into())?.into()),
             ConstValue::Slice { data, start, end } => {
                 // We rely on mutability being set correctly in `data` to prevent writes
                 // where none should happen.
@@ -591,7 +594,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     Size::from_bytes(start), // offset: `start`
                 );
                 Operand::Immediate(Immediate::new_slice(
-                    self.global_base_pointer(ptr)?.into(),
+                    Scalar::from_pointer(self.global_base_pointer(ptr)?, &*self.tcx),
                     u64::try_from(end.checked_sub(start).unwrap()).unwrap(), // len: `end - start`
                     self,
                 ))
@@ -658,9 +661,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // Figure out which discriminant and variant this corresponds to.
         Ok(match *tag_encoding {
             TagEncoding::Direct => {
-                let tag_bits = self
-                    .force_bits(tag_val, tag_layout.size)
-                    .map_err(|_| err_ub!(InvalidTag(tag_val.erase_tag())))?;
+                let tag_bits = tag_val
+                    .try_to_int()
+                    .map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))?
+                    .assert_bits(tag_layout.size);
                 // Cast bits from tag layout to discriminant layout.
                 let discr_val = self.cast_from_scalar(tag_bits, tag_layout, discr_layout.ty);
                 let discr_bits = discr_val.assert_bits(discr_layout.size);
@@ -677,7 +681,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     }
                     _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-generator"),
                 }
-                .ok_or_else(|| err_ub!(InvalidTag(tag_val.erase_tag())))?;
+                .ok_or_else(|| err_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size))))?;
                 // Return the cast value, and the index.
                 (discr_val, index.0)
             }
@@ -686,18 +690,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // discriminant (encoded in niche/tag) and variant index are the same.
                 let variants_start = niche_variants.start().as_u32();
                 let variants_end = niche_variants.end().as_u32();
-                let variant = match tag_val.to_bits_or_ptr(tag_layout.size, self) {
-                    Err(ptr) => {
-                        // The niche must be just 0 (which an inbounds pointer value never is)
+                let variant = match tag_val.try_to_int() {
+                    Err(dbg_val) => {
+                        // So this is a pointer then, and casting to an int failed.
+                        // Can only happen during CTFE.
+                        let ptr = self.scalar_to_ptr(tag_val);
+                        // The niche must be just 0, and the ptr not null, then we know this is
+                        // okay. Everything else, we conservatively reject.
                         let ptr_valid = niche_start == 0
                             && variants_start == variants_end
                             && !self.memory.ptr_may_be_null(ptr);
                         if !ptr_valid {
-                            throw_ub!(InvalidTag(tag_val.erase_tag()))
+                            throw_ub!(InvalidTag(dbg_val))
                         }
                         dataful_variant
                     }
                     Ok(tag_bits) => {
+                        let tag_bits = tag_bits.assert_bits(tag_layout.size);
                         // We need to use machine arithmetic to get the relative variant idx:
                         // variant_index_relative = tag_val - niche_start_val
                         let tag_val = ImmTy::from_uint(tag_bits, tag_layout);
index 3737f8781c7ae2a333dc02cfd9405717f4eeabaa..79b493d74e19b47006653f8bbd6fb0ccad7012e0 100644 (file)
@@ -318,8 +318,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     right.layout.ty
                 );
 
-                let l = self.force_bits(left.to_scalar()?, left.layout.size)?;
-                let r = self.force_bits(right.to_scalar()?, right.layout.size)?;
+                let l = left.to_scalar()?.to_bits(left.layout.size)?;
+                let r = right.to_scalar()?.to_bits(right.layout.size)?;
                 self.binary_int_op(bin_op, l, left.layout, r, right.layout)
             }
             _ if left.layout.ty.is_any_ptr() => {
@@ -386,7 +386,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
             _ => {
                 assert!(layout.ty.is_integral());
-                let val = self.force_bits(val, layout.size)?;
+                let val = val.to_bits(layout.size)?;
                 let (res, overflow) = match un_op {
                     Not => (self.truncate(!val, layout), false), // bitwise negation, then truncate
                     Neg => {
index 4c53510ed00eed86df702bad1068e68eba528c1f..91fcc3495b1c12abeaa3523d705462214f3db23d 100644 (file)
@@ -3,7 +3,6 @@
 //! All high-level functions to write to memory work on places as destinations.
 
 use std::convert::TryFrom;
-use std::fmt::Debug;
 use std::hash::Hash;
 
 use rustc_ast::Mutability;
@@ -15,14 +14,14 @@ use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding};
 use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants};
 
 use super::{
-    alloc_range, mir_assign_valid_types, AllocRef, AllocRefMut, ConstAlloc, ImmTy, Immediate,
-    InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand, Pointer,
-    PointerArithmetic, Scalar, ScalarMaybeUninit,
+    alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg,
+    ConstAlloc, ImmTy, Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy,
+    Operand, Pointer, PointerArithmetic, Provenance, Scalar, ScalarMaybeUninit,
 };
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
+#[derive(Copy, Clone, Hash, PartialEq, Eq, HashStable, Debug)]
 /// Information required for the sound usage of a `MemPlace`.
-pub enum MemPlaceMeta<Tag = ()> {
+pub enum MemPlaceMeta<Tag: Provenance = AllocId> {
     /// The unsized payload (e.g. length for slices or vtable pointer for trait objects).
     Meta(Scalar<Tag>),
     /// `Sized` types or unsized `extern type`
@@ -37,7 +36,7 @@ pub enum MemPlaceMeta<Tag = ()> {
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 rustc_data_structures::static_assert_size!(MemPlaceMeta, 24);
 
-impl<Tag> MemPlaceMeta<Tag> {
+impl<Tag: Provenance> MemPlaceMeta<Tag> {
     pub fn unwrap_meta(self) -> Scalar<Tag> {
         match self {
             Self::Meta(s) => s,
@@ -52,22 +51,12 @@ impl<Tag> MemPlaceMeta<Tag> {
             Self::None | Self::Poison => false,
         }
     }
-
-    pub fn erase_tag(self) -> MemPlaceMeta<()> {
-        match self {
-            Self::Meta(s) => MemPlaceMeta::Meta(s.erase_tag()),
-            Self::None => MemPlaceMeta::None,
-            Self::Poison => MemPlaceMeta::Poison,
-        }
-    }
 }
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
-pub struct MemPlace<Tag = ()> {
-    /// A place may have an integral pointer for ZSTs, and since it might
-    /// be turned back into a reference before ever being dereferenced.
-    /// However, it may never be uninit.
-    pub ptr: Scalar<Tag>,
+#[derive(Copy, Clone, Hash, PartialEq, Eq, HashStable, Debug)]
+pub struct MemPlace<Tag: Provenance = AllocId> {
+    /// The pointer can be a pure integer, with the `None` tag.
+    pub ptr: Pointer<Option<Tag>>,
     pub align: Align,
     /// Metadata for unsized places. Interpretation is up to the type.
     /// Must not be present for sized types, but can be missing for unsized types
@@ -76,10 +65,10 @@ pub struct MemPlace<Tag = ()> {
 }
 
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(MemPlace, 56);
+rustc_data_structures::static_assert_size!(MemPlace, 48);
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
-pub enum Place<Tag = ()> {
+#[derive(Copy, Clone, Hash, PartialEq, Eq, HashStable, Debug)]
+pub enum Place<Tag: Provenance = AllocId> {
     /// A place referring to a value allocated in the `Memory` system.
     Ptr(MemPlace<Tag>),
 
@@ -89,18 +78,18 @@ pub enum Place<Tag = ()> {
 }
 
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Place, 64);
+rustc_data_structures::static_assert_size!(Place, 56);
 
 #[derive(Copy, Clone, Debug)]
-pub struct PlaceTy<'tcx, Tag = ()> {
+pub struct PlaceTy<'tcx, Tag: Provenance = AllocId> {
     place: Place<Tag>, // Keep this private; it helps enforce invariants.
     pub layout: TyAndLayout<'tcx>,
 }
 
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(PlaceTy<'_>, 80);
+rustc_data_structures::static_assert_size!(PlaceTy<'_>, 72);
 
-impl<'tcx, Tag> std::ops::Deref for PlaceTy<'tcx, Tag> {
+impl<'tcx, Tag: Provenance> std::ops::Deref for PlaceTy<'tcx, Tag> {
     type Target = Place<Tag>;
     #[inline(always)]
     fn deref(&self) -> &Place<Tag> {
@@ -109,16 +98,16 @@ impl<'tcx, Tag> std::ops::Deref for PlaceTy<'tcx, Tag> {
 }
 
 /// A MemPlace with its layout. Constructing it is only possible in this module.
-#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
-pub struct MPlaceTy<'tcx, Tag = ()> {
+#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
+pub struct MPlaceTy<'tcx, Tag: Provenance = AllocId> {
     mplace: MemPlace<Tag>,
     pub layout: TyAndLayout<'tcx>,
 }
 
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(MPlaceTy<'_>, 72);
+rustc_data_structures::static_assert_size!(MPlaceTy<'_>, 64);
 
-impl<'tcx, Tag> std::ops::Deref for MPlaceTy<'tcx, Tag> {
+impl<'tcx, Tag: Provenance> std::ops::Deref for MPlaceTy<'tcx, Tag> {
     type Target = MemPlace<Tag>;
     #[inline(always)]
     fn deref(&self) -> &MemPlace<Tag> {
@@ -126,42 +115,33 @@ impl<'tcx, Tag> std::ops::Deref for MPlaceTy<'tcx, Tag> {
     }
 }
 
-impl<'tcx, Tag> From<MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> {
+impl<'tcx, Tag: Provenance> From<MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> {
     #[inline(always)]
     fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self {
         PlaceTy { place: Place::Ptr(mplace.mplace), layout: mplace.layout }
     }
 }
 
-impl<Tag> MemPlace<Tag> {
-    /// Replace ptr tag, maintain vtable tag (if any)
-    #[inline]
-    pub fn replace_tag(self, new_tag: Tag) -> Self {
-        MemPlace { ptr: self.ptr.erase_tag().with_tag(new_tag), align: self.align, meta: self.meta }
-    }
-
-    #[inline]
-    pub fn erase_tag(self) -> MemPlace {
-        MemPlace { ptr: self.ptr.erase_tag(), align: self.align, meta: self.meta.erase_tag() }
-    }
-
+impl<Tag: Provenance> MemPlace<Tag> {
     #[inline(always)]
-    fn from_scalar_ptr(ptr: Scalar<Tag>, align: Align) -> Self {
+    pub fn from_ptr(ptr: Pointer<Option<Tag>>, align: Align) -> Self {
         MemPlace { ptr, align, meta: MemPlaceMeta::None }
     }
 
-    #[inline(always)]
-    pub fn from_ptr(ptr: Pointer<Tag>, align: Align) -> Self {
-        Self::from_scalar_ptr(ptr.into(), align)
+    /// Adjust the provenance of the main pointer (metadata is unaffected).
+    pub fn map_provenance(self, f: impl FnOnce(Option<Tag>) -> Option<Tag>) -> Self {
+        MemPlace { ptr: self.ptr.map_provenance(f), ..self }
     }
 
     /// Turn a mplace into a (thin or wide) pointer, as a reference, pointing to the same space.
     /// This is the inverse of `ref_to_mplace`.
     #[inline(always)]
-    pub fn to_ref(self) -> Immediate<Tag> {
+    pub fn to_ref(self, cx: &impl HasDataLayout) -> Immediate<Tag> {
         match self.meta {
-            MemPlaceMeta::None => Immediate::Scalar(self.ptr.into()),
-            MemPlaceMeta::Meta(meta) => Immediate::ScalarPair(self.ptr.into(), meta.into()),
+            MemPlaceMeta::None => Immediate::from(Scalar::from_maybe_pointer(self.ptr, cx)),
+            MemPlaceMeta::Meta(meta) => {
+                Immediate::ScalarPair(Scalar::from_maybe_pointer(self.ptr, cx).into(), meta.into())
+            }
             MemPlaceMeta::Poison => bug!(
                 "MPlaceTy::dangling may never be used to produce a \
                 place that will have the address of its pointee taken"
@@ -177,29 +157,23 @@ impl<Tag> MemPlace<Tag> {
         cx: &impl HasDataLayout,
     ) -> InterpResult<'tcx, Self> {
         Ok(MemPlace {
-            ptr: self.ptr.ptr_offset(offset, cx)?,
+            ptr: self.ptr.offset(offset, cx)?,
             align: self.align.restrict_for_offset(offset),
             meta,
         })
     }
 }
 
-impl<'tcx, Tag: Copy> MPlaceTy<'tcx, Tag> {
+impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> {
     /// Produces a MemPlace that works for ZST but nothing else
     #[inline]
-    pub fn dangling(layout: TyAndLayout<'tcx>, cx: &impl HasDataLayout) -> Self {
+    pub fn dangling(layout: TyAndLayout<'tcx>) -> Self {
         let align = layout.align.abi;
-        let ptr = Scalar::from_machine_usize(align.bytes(), cx);
+        let ptr = Pointer::new(None, Size::from_bytes(align.bytes())); // no provenance, absolute address
         // `Poison` this to make sure that the pointer value `ptr` is never observable by the program.
         MPlaceTy { mplace: MemPlace { ptr, align, meta: MemPlaceMeta::Poison }, layout }
     }
 
-    /// Replace ptr tag, maintain vtable tag (if any)
-    #[inline]
-    pub fn replace_tag(&self, new_tag: Tag) -> Self {
-        MPlaceTy { mplace: self.mplace.replace_tag(new_tag), layout: self.layout }
-    }
-
     #[inline]
     pub fn offset(
         &self,
@@ -212,7 +186,7 @@ impl<'tcx, Tag: Copy> MPlaceTy<'tcx, Tag> {
     }
 
     #[inline]
-    fn from_aligned_ptr(ptr: Pointer<Tag>, layout: TyAndLayout<'tcx>) -> Self {
+    pub fn from_aligned_ptr(ptr: Pointer<Option<Tag>>, layout: TyAndLayout<'tcx>) -> Self {
         MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align.abi), layout }
     }
 
@@ -244,19 +218,14 @@ impl<'tcx, Tag: Copy> MPlaceTy<'tcx, Tag> {
 }
 
 // These are defined here because they produce a place.
-impl<'tcx, Tag: Debug + Copy> OpTy<'tcx, Tag> {
+impl<'tcx, Tag: Provenance> OpTy<'tcx, Tag> {
     #[inline(always)]
     /// Note: do not call `as_ref` on the resulting place. This function should only be used to
     /// read from the resulting mplace, not to get its address back.
-    pub fn try_as_mplace(
-        &self,
-        cx: &impl HasDataLayout,
-    ) -> Result<MPlaceTy<'tcx, Tag>, ImmTy<'tcx, Tag>> {
+    pub fn try_as_mplace(&self) -> Result<MPlaceTy<'tcx, Tag>, ImmTy<'tcx, Tag>> {
         match **self {
             Operand::Indirect(mplace) => Ok(MPlaceTy { mplace, layout: self.layout }),
-            Operand::Immediate(_) if self.layout.is_zst() => {
-                Ok(MPlaceTy::dangling(self.layout, cx))
-            }
+            Operand::Immediate(_) if self.layout.is_zst() => Ok(MPlaceTy::dangling(self.layout)),
             Operand::Immediate(imm) => Err(ImmTy::from_immediate(imm, self.layout)),
         }
     }
@@ -264,12 +233,12 @@ impl<'tcx, Tag: Debug + Copy> OpTy<'tcx, Tag> {
     #[inline(always)]
     /// Note: do not call `as_ref` on the resulting place. This function should only be used to
     /// read from the resulting mplace, not to get its address back.
-    pub fn assert_mem_place(&self, cx: &impl HasDataLayout) -> MPlaceTy<'tcx, Tag> {
-        self.try_as_mplace(cx).unwrap()
+    pub fn assert_mem_place(&self) -> MPlaceTy<'tcx, Tag> {
+        self.try_as_mplace().unwrap()
     }
 }
 
-impl<Tag: Debug> Place<Tag> {
+impl<Tag: Provenance> Place<Tag> {
     #[inline]
     pub fn assert_mem_place(self) -> MemPlace<Tag> {
         match self {
@@ -279,7 +248,7 @@ impl<Tag: Debug> Place<Tag> {
     }
 }
 
-impl<'tcx, Tag: Debug> PlaceTy<'tcx, Tag> {
+impl<'tcx, Tag: Provenance> PlaceTy<'tcx, Tag> {
     #[inline]
     pub fn assert_mem_place(self) -> MPlaceTy<'tcx, Tag> {
         MPlaceTy { mplace: self.place.assert_mem_place(), layout: self.layout }
@@ -290,7 +259,7 @@ impl<'tcx, Tag: Debug> PlaceTy<'tcx, Tag> {
 impl<'mir, 'tcx: 'mir, Tag, M> InterpCx<'mir, 'tcx, M>
 where
     // FIXME: Working around https://github.com/rust-lang/rust/issues/54385
-    Tag: Debug + Copy + Eq + Hash + 'static,
+    Tag: Provenance + Eq + Hash + 'static,
     M: Machine<'mir, 'tcx, PointerTag = Tag>,
 {
     /// Take a value, which represents a (thin or wide) reference, and make it a place.
@@ -307,14 +276,12 @@ where
             val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type").ty;
         let layout = self.layout_of(pointee_type)?;
         let (ptr, meta) = match **val {
-            Immediate::Scalar(ptr) => (ptr.check_init()?, MemPlaceMeta::None),
-            Immediate::ScalarPair(ptr, meta) => {
-                (ptr.check_init()?, MemPlaceMeta::Meta(meta.check_init()?))
-            }
+            Immediate::Scalar(ptr) => (ptr, MemPlaceMeta::None),
+            Immediate::ScalarPair(ptr, meta) => (ptr, MemPlaceMeta::Meta(meta.check_init()?)),
         };
 
         let mplace = MemPlace {
-            ptr,
+            ptr: self.scalar_to_ptr(ptr.check_init()?),
             // We could use the run-time alignment here. For now, we do not, because
             // the point of tracking the alignment here is to make sure that the *static*
             // alignment information emitted with the loads is correct. The run-time
@@ -333,8 +300,9 @@ where
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let val = self.read_immediate(src)?;
         trace!("deref to {} on {:?}", val.layout.ty, *val);
-        let place = self.ref_to_mplace(&val)?;
-        self.mplace_access_checked(place, None)
+        let mplace = self.ref_to_mplace(&val)?;
+        self.check_mplace_access(mplace, CheckInAllocMsg::DerefTest)?;
+        Ok(mplace)
     }
 
     #[inline]
@@ -359,38 +327,19 @@ where
         self.memory.get_mut(place.ptr, size, place.align)
     }
 
-    /// Return the "access-checked" version of this `MPlace`, where for non-ZST
-    /// this is definitely a `Pointer`.
-    ///
-    /// `force_align` must only be used when correct alignment does not matter,
-    /// like in Stacked Borrows.
-    pub fn mplace_access_checked(
+    /// Check if this mplace is dereferencable and sufficiently aligned.
+    fn check_mplace_access(
         &self,
-        mut place: MPlaceTy<'tcx, M::PointerTag>,
-        force_align: Option<Align>,
-    ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
+        mplace: MPlaceTy<'tcx, M::PointerTag>,
+        msg: CheckInAllocMsg,
+    ) -> InterpResult<'tcx> {
         let (size, align) = self
-            .size_and_align_of_mplace(&place)?
-            .unwrap_or((place.layout.size, place.layout.align.abi));
-        assert!(place.mplace.align <= align, "dynamic alignment less strict than static one?");
-        let align = force_align.unwrap_or(align);
-        // Record new (stricter, unless forced) alignment requirement in place.
-        place.mplace.align = align;
-        // When dereferencing a pointer, it must be non-null, aligned, and live.
-        if let Some(ptr) = self.memory.check_ptr_access(place.ptr, size, align)? {
-            place.mplace.ptr = ptr.into();
-        }
-        Ok(place)
-    }
-
-    /// Force `place.ptr` to a `Pointer`.
-    /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot.
-    pub(super) fn force_mplace_ptr(
-        &self,
-        mut place: MPlaceTy<'tcx, M::PointerTag>,
-    ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
-        place.mplace.ptr = self.force_ptr(place.mplace.ptr)?.into();
-        Ok(place)
+            .size_and_align_of_mplace(&mplace)?
+            .unwrap_or((mplace.layout.size, mplace.layout.align.abi));
+        assert!(mplace.mplace.align <= align, "dynamic alignment less strict than static one?");
+        let align = M::enforce_alignment(&self.memory.extra).then_some(align);
+        self.memory.check_ptr_access_align(mplace.ptr, size, align.unwrap_or(Align::ONE), msg)?;
+        Ok(())
     }
 
     /// Offset a pointer to project to a field of a struct/union. Unlike `place_field`, this is
@@ -558,10 +507,7 @@ where
                 let layout = self.layout_of(self.tcx.types.usize)?;
                 let n = self.access_local(self.frame(), local, Some(layout))?;
                 let n = self.read_scalar(&n)?;
-                let n = u64::try_from(
-                    self.force_bits(n.check_init()?, self.tcx.data_layout.pointer_size)?,
-                )
-                .unwrap();
+                let n = n.to_machine_usize(self)?;
                 self.mplace_index(base, n)?
             }
 
@@ -677,16 +623,6 @@ where
         Ok(place_ty)
     }
 
-    /// Write a scalar to a place
-    #[inline(always)]
-    pub fn write_scalar(
-        &mut self,
-        val: impl Into<ScalarMaybeUninit<M::PointerTag>>,
-        dest: &PlaceTy<'tcx, M::PointerTag>,
-    ) -> InterpResult<'tcx> {
-        self.write_immediate(Immediate::Scalar(val.into()), dest)
-    }
-
     /// Write an immediate to a place
     #[inline(always)]
     pub fn write_immediate(
@@ -704,21 +640,24 @@ where
         Ok(())
     }
 
-    /// Write an `Immediate` to memory.
+    /// Write a scalar to a place
     #[inline(always)]
-    pub fn write_immediate_to_mplace(
+    pub fn write_scalar(
         &mut self,
-        src: Immediate<M::PointerTag>,
-        dest: &MPlaceTy<'tcx, M::PointerTag>,
+        val: impl Into<ScalarMaybeUninit<M::PointerTag>>,
+        dest: &PlaceTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx> {
-        self.write_immediate_to_mplace_no_validate(src, dest)?;
-
-        if M::enforce_validity(self) {
-            // Data got changed, better make sure it matches the type!
-            self.validate_operand(&dest.into())?;
-        }
+        self.write_immediate(Immediate::Scalar(val.into()), dest)
+    }
 
-        Ok(())
+    /// Write a pointer to a place
+    #[inline(always)]
+    pub fn write_pointer(
+        &mut self,
+        ptr: impl Into<Pointer<Option<M::PointerTag>>>,
+        dest: &PlaceTy<'tcx, M::PointerTag>,
+    ) -> InterpResult<'tcx> {
+        self.write_scalar(Scalar::from_maybe_pointer(ptr.into(), self), dest)
     }
 
     /// Write an immediate to a place.
@@ -733,7 +672,7 @@ where
             // This is a very common path, avoid some checks in release mode
             assert!(!dest.layout.is_unsized(), "Cannot write unsized data");
             match src {
-                Immediate::Scalar(ScalarMaybeUninit::Scalar(Scalar::Ptr(_))) => assert_eq!(
+                Immediate::Scalar(ScalarMaybeUninit::Scalar(Scalar::Ptr(..))) => assert_eq!(
                     self.pointer_size(),
                     dest.layout.size,
                     "Size mismatch when writing pointer"
@@ -982,7 +921,7 @@ where
                         let (size, align) = self
                             .size_and_align_of(&meta, &local_layout)?
                             .expect("Cannot allocate for non-dyn-sized type");
-                        let ptr = self.memory.allocate(size, align, MemoryKind::Stack);
+                        let ptr = self.memory.allocate(size, align, MemoryKind::Stack)?;
                         let mplace = MemPlace { ptr: ptr.into(), align, meta };
                         if let LocalValue::Live(Operand::Immediate(value)) = local_val {
                             // Preserve old value.
@@ -1018,9 +957,9 @@ where
         &mut self,
         layout: TyAndLayout<'tcx>,
         kind: MemoryKind<M::MemoryKind>,
-    ) -> MPlaceTy<'tcx, M::PointerTag> {
-        let ptr = self.memory.allocate(layout.size, layout.align.abi, kind);
-        MPlaceTy::from_aligned_ptr(ptr, layout)
+    ) -> InterpResult<'static, MPlaceTy<'tcx, M::PointerTag>> {
+        let ptr = self.memory.allocate(layout.size, layout.align.abi, kind)?;
+        Ok(MPlaceTy::from_aligned_ptr(ptr.into(), layout))
     }
 
     /// Returns a wide MPlace of type `&'static [mut] str` to a new 1-aligned allocation.
@@ -1125,7 +1064,7 @@ where
         let _ = self.tcx.global_alloc(raw.alloc_id);
         let ptr = self.global_base_pointer(Pointer::from(raw.alloc_id))?;
         let layout = self.layout_of(raw.ty)?;
-        Ok(MPlaceTy::from_aligned_ptr(ptr, layout))
+        Ok(MPlaceTy::from_aligned_ptr(ptr.into(), layout))
     }
 
     /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type.
@@ -1134,7 +1073,7 @@ where
         &self,
         mplace: &MPlaceTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx, (ty::Instance<'tcx>, MPlaceTy<'tcx, M::PointerTag>)> {
-        let vtable = mplace.vtable(); // also sanity checks the type
+        let vtable = self.scalar_to_ptr(mplace.vtable()); // also sanity checks the type
         let (instance, ty) = self.read_drop_type_from_vtable(vtable)?;
         let layout = self.layout_of(ty)?;
 
index 129dd8f8e01255f2ed36a3415e9d888df64ea148..f2a8a067dfac2a11287515d4a2e927aec3c62946 100644 (file)
@@ -162,9 +162,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         use rustc_middle::mir::Rvalue::*;
         match *rvalue {
             ThreadLocalRef(did) => {
-                let id = M::thread_local_static_alloc_id(self, did)?;
-                let val = self.global_base_pointer(id.into())?;
-                self.write_scalar(val, &dest)?;
+                let ptr = M::thread_local_static_base_pointer(self, did)?;
+                self.write_pointer(ptr, &dest)?;
             }
 
             Use(ref operand) => {
@@ -240,7 +239,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     // of the first element.
                     let elem_size = first.layout.size;
                     let first_ptr = first.ptr;
-                    let rest_ptr = first_ptr.ptr_offset(elem_size, self)?;
+                    let rest_ptr = first_ptr.offset(elem_size, self)?;
                     self.memory.copy_repeatedly(
                         first_ptr,
                         first.align,
@@ -264,11 +263,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             AddressOf(_, place) | Ref(_, _, place) => {
                 let src = self.eval_place(place)?;
                 let place = self.force_allocation(&src)?;
-                if place.layout.size.bytes() > 0 {
-                    // definitely not a ZST
-                    assert!(place.ptr.is_ptr(), "non-ZST places should be normalized to `Pointer`");
-                }
-                self.write_immediate(place.to_ref(), &dest)?;
+                self.write_immediate(place.to_ref(self), &dest)?;
             }
 
             NullaryOp(mir::NullOp::Box, _) => {
index a5bdeb55e781402d0685a382acea085a3af67776..f369480d959fede95e17d9e7bc4c77271f8fb1a8 100644 (file)
@@ -12,8 +12,8 @@ use rustc_target::abi::{self, LayoutOf as _};
 use rustc_target::spec::abi::Abi;
 
 use super::{
-    FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, StackPopCleanup,
-    StackPopUnwind,
+    FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, Scalar,
+    StackPopCleanup, StackPopUnwind,
 };
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
@@ -72,8 +72,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let (fn_val, abi, caller_can_unwind) = match *func.layout.ty.kind() {
                     ty::FnPtr(sig) => {
                         let caller_abi = sig.abi();
-                        let fn_ptr = self.read_scalar(&func)?.check_init()?;
-                        let fn_val = self.memory.get_fn(fn_ptr)?;
+                        let fn_ptr = self.read_pointer(&func)?;
+                        let fn_val = self.memory.get_fn(fn_ptr.into())?;
                         (
                             fn_val,
                             caller_abi,
@@ -454,12 +454,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     }
                     None => {
                         // Unsized self.
-                        args[0].assert_mem_place(self)
+                        args[0].assert_mem_place()
                     }
                 };
                 // Find and consult vtable
-                let vtable = receiver_place.vtable();
-                let drop_fn = self.get_vtable_slot(vtable, u64::try_from(idx).unwrap())?;
+                let vtable = self.scalar_to_ptr(receiver_place.vtable());
+                let fn_val = self.get_vtable_slot(vtable, u64::try_from(idx).unwrap())?;
 
                 // `*mut receiver_place.layout.ty` is almost the layout that we
                 // want for args[0]: We have to project to field 0 because we want
@@ -468,11 +468,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let receiver_ptr_ty = self.tcx.mk_mut_ptr(receiver_place.layout.ty);
                 let this_receiver_ptr = self.layout_of(receiver_ptr_ty)?.field(self, 0)?;
                 // Adjust receiver argument.
-                args[0] =
-                    OpTy::from(ImmTy::from_immediate(receiver_place.ptr.into(), this_receiver_ptr));
+                args[0] = OpTy::from(ImmTy::from_immediate(
+                    Scalar::from_maybe_pointer(receiver_place.ptr, self).into(),
+                    this_receiver_ptr,
+                ));
                 trace!("Patched self operand to {:#?}", args[0]);
                 // recurse with concrete function
-                self.eval_fn_call(drop_fn, caller_abi, &args, ret, unwind)
+                self.eval_fn_call(fn_val, caller_abi, &args, ret, unwind)
             }
         }
     }
@@ -499,12 +501,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         };
 
         let arg = ImmTy::from_immediate(
-            place.to_ref(),
+            place.to_ref(self),
             self.layout_of(self.tcx.mk_mut_ptr(place.layout.ty))?,
         );
 
         let ty = self.tcx.mk_unit(); // return type is ()
-        let dest = MPlaceTy::dangling(self.layout_of(ty)?, self);
+        let dest = MPlaceTy::dangling(self.layout_of(ty)?);
 
         self.eval_fn_call(
             FnVal::Instance(instance),
index d0c04b5b414ebf3feb235ad9fb90899b4e78d35b..7a93fcee78e3389a60ff1b8ee360215ab8a03052 100644 (file)
@@ -1,11 +1,14 @@
 use std::convert::TryFrom;
 
-use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic, Scalar};
-use rustc_middle::ty::{self, Instance, Ty};
-use rustc_target::abi::{Align, LayoutOf, Size};
+use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic};
+use rustc_middle::ty::{
+    self, Ty, COMMON_VTABLE_ENTRIES, COMMON_VTABLE_ENTRIES_ALIGN,
+    COMMON_VTABLE_ENTRIES_DROPINPLACE, COMMON_VTABLE_ENTRIES_SIZE,
+};
+use rustc_target::abi::{Align, Size};
 
 use super::util::ensure_monomorphic_enough;
-use super::{FnVal, InterpCx, Machine, MemoryKind};
+use super::{FnVal, InterpCx, Machine};
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Creates a dynamic vtable for the given type and vtable origin. This is used only for
@@ -27,145 +30,94 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         ensure_monomorphic_enough(*self.tcx, ty)?;
         ensure_monomorphic_enough(*self.tcx, poly_trait_ref)?;
 
-        if let Some(&vtable) = self.vtables.get(&(ty, poly_trait_ref)) {
-            // This means we guarantee that there are no duplicate vtables, we will
-            // always use the same vtable for the same (Type, Trait) combination.
-            // That's not what happens in rustc, but emulating per-crate deduplication
-            // does not sound like it actually makes anything any better.
-            return Ok(vtable);
-        }
-
-        let methods = if let Some(poly_trait_ref) = poly_trait_ref {
-            let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty);
-            let trait_ref = self.tcx.erase_regions(trait_ref);
-
-            self.tcx.vtable_methods(trait_ref)
-        } else {
-            &[]
-        };
-
-        let layout = self.layout_of(ty)?;
-        assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");
-        let size = layout.size.bytes();
-        let align = layout.align.abi.bytes();
-
-        let tcx = *self.tcx;
-        let ptr_size = self.pointer_size();
-        let ptr_align = tcx.data_layout.pointer_align.abi;
-        // /////////////////////////////////////////////////////////////////////////////////////////
-        // If you touch this code, be sure to also make the corresponding changes to
-        // `get_vtable` in `rust_codegen_llvm/meth.rs`.
-        // /////////////////////////////////////////////////////////////////////////////////////////
-        let vtable_size = ptr_size * u64::try_from(methods.len()).unwrap().checked_add(3).unwrap();
-        let vtable = self.memory.allocate(vtable_size, ptr_align, MemoryKind::Vtable);
-
-        let drop = Instance::resolve_drop_in_place(tcx, ty);
-        let drop = self.memory.create_fn_alloc(FnVal::Instance(drop));
+        let vtable_allocation = self.tcx.vtable_allocation(ty, poly_trait_ref);
 
-        // Prepare the fn ptrs we will write into the vtable later.
-        let fn_ptrs = methods
-            .iter()
-            .enumerate() // remember the original position
-            .filter_map(|(i, method)| {
-                if let Some((def_id, substs)) = method { Some((i, def_id, substs)) } else { None }
-            })
-            .map(|(i, def_id, substs)| {
-                let instance =
-                    ty::Instance::resolve_for_vtable(tcx, self.param_env, *def_id, substs)
-                        .ok_or_else(|| err_inval!(TooGeneric))?;
-                Ok((i, self.memory.create_fn_alloc(FnVal::Instance(instance))))
-            })
-            .collect::<InterpResult<'tcx, Vec<(usize, Pointer<M::PointerTag>)>>>()?;
+        let vtable_ptr = self.memory.global_base_pointer(Pointer::from(vtable_allocation))?;
 
-        // No need to do any alignment checks on the memory accesses below, because we know the
-        // allocation is correctly aligned as we created it above. Also we're only offsetting by
-        // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`.
-        let mut vtable_alloc =
-            self.memory.get_mut(vtable.into(), vtable_size, ptr_align)?.expect("not a ZST");
-        vtable_alloc.write_ptr_sized(ptr_size * 0, drop.into())?;
-        vtable_alloc.write_ptr_sized(ptr_size * 1, Scalar::from_uint(size, ptr_size).into())?;
-        vtable_alloc.write_ptr_sized(ptr_size * 2, Scalar::from_uint(align, ptr_size).into())?;
-
-        for (i, fn_ptr) in fn_ptrs.into_iter() {
-            vtable_alloc.write_ptr_sized(ptr_size * (3 + i as u64), fn_ptr.into())?;
-        }
-
-        M::after_static_mem_initialized(self, vtable, vtable_size)?;
-
-        self.memory.mark_immutable(vtable.alloc_id)?;
-        assert!(self.vtables.insert((ty, poly_trait_ref), vtable).is_none());
-
-        Ok(vtable)
+        Ok(vtable_ptr)
     }
 
     /// Resolves the function at the specified slot in the provided
-    /// vtable. An index of '0' corresponds to the first method
-    /// declared in the trait of the provided vtable.
+    /// vtable. Currently an index of '3' (`COMMON_VTABLE_ENTRIES.len()`)
+    /// corresponds to the first method declared in the trait of the provided vtable.
     pub fn get_vtable_slot(
         &self,
-        vtable: Scalar<M::PointerTag>,
+        vtable: Pointer<Option<M::PointerTag>>,
         idx: u64,
     ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
         let ptr_size = self.pointer_size();
-        // Skip over the 'drop_ptr', 'size', and 'align' fields.
-        let vtable_slot = vtable.ptr_offset(ptr_size * idx.checked_add(3).unwrap(), self)?;
+        let vtable_slot = vtable.offset(ptr_size * idx, self)?;
         let vtable_slot = self
             .memory
             .get(vtable_slot, ptr_size, self.tcx.data_layout.pointer_align.abi)?
             .expect("cannot be a ZST");
-        let fn_ptr = vtable_slot.read_ptr_sized(Size::ZERO)?.check_init()?;
+        let fn_ptr = self.scalar_to_ptr(vtable_slot.read_ptr_sized(Size::ZERO)?.check_init()?);
         self.memory.get_fn(fn_ptr)
     }
 
     /// Returns the drop fn instance as well as the actual dynamic type.
     pub fn read_drop_type_from_vtable(
         &self,
-        vtable: Scalar<M::PointerTag>,
+        vtable: Pointer<Option<M::PointerTag>>,
     ) -> InterpResult<'tcx, (ty::Instance<'tcx>, Ty<'tcx>)> {
+        let pointer_size = self.pointer_size();
         // We don't care about the pointee type; we just want a pointer.
         let vtable = self
             .memory
-            .get(vtable, self.tcx.data_layout.pointer_size, self.tcx.data_layout.pointer_align.abi)?
+            .get(
+                vtable,
+                pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES.len()).unwrap(),
+                self.tcx.data_layout.pointer_align.abi,
+            )?
             .expect("cannot be a ZST");
-        let drop_fn = vtable.read_ptr_sized(Size::ZERO)?.check_init()?;
+        let drop_fn = vtable
+            .read_ptr_sized(
+                pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_DROPINPLACE).unwrap(),
+            )?
+            .check_init()?;
         // We *need* an instance here, no other kind of function value, to be able
         // to determine the type.
-        let drop_instance = self.memory.get_fn(drop_fn)?.as_instance()?;
+        let drop_instance = self.memory.get_fn(self.scalar_to_ptr(drop_fn))?.as_instance()?;
         trace!("Found drop fn: {:?}", drop_instance);
         let fn_sig = drop_instance.ty(*self.tcx, self.param_env).fn_sig(*self.tcx);
         let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig);
         // The drop function takes `*mut T` where `T` is the type being dropped, so get that.
         let args = fn_sig.inputs();
         if args.len() != 1 {
-            throw_ub!(InvalidDropFn(fn_sig));
+            throw_ub!(InvalidVtableDropFn(fn_sig));
         }
-        let ty = args[0].builtin_deref(true).ok_or_else(|| err_ub!(InvalidDropFn(fn_sig)))?.ty;
+        let ty =
+            args[0].builtin_deref(true).ok_or_else(|| err_ub!(InvalidVtableDropFn(fn_sig)))?.ty;
         Ok((drop_instance, ty))
     }
 
     pub fn read_size_and_align_from_vtable(
         &self,
-        vtable: Scalar<M::PointerTag>,
+        vtable: Pointer<Option<M::PointerTag>>,
     ) -> InterpResult<'tcx, (Size, Align)> {
         let pointer_size = self.pointer_size();
         // We check for `size = 3 * ptr_size`, which covers the drop fn (unused here),
         // the size, and the align (which we read below).
         let vtable = self
             .memory
-            .get(vtable, 3 * pointer_size, self.tcx.data_layout.pointer_align.abi)?
+            .get(
+                vtable,
+                pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES.len()).unwrap(),
+                self.tcx.data_layout.pointer_align.abi,
+            )?
             .expect("cannot be a ZST");
-        let size = vtable.read_ptr_sized(pointer_size)?.check_init()?;
-        let size = u64::try_from(self.force_bits(size, pointer_size)?).unwrap();
-        let align = vtable.read_ptr_sized(pointer_size * 2)?.check_init()?;
-        let align = u64::try_from(self.force_bits(align, pointer_size)?).unwrap();
-        let align = Align::from_bytes(align)
-            .map_err(|e| err_ub_format!("invalid vtable: alignment {}", e))?;
+        let size = vtable
+            .read_ptr_sized(pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_SIZE).unwrap())?
+            .check_init()?;
+        let size = size.to_machine_usize(self)?;
+        let align = vtable
+            .read_ptr_sized(pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_ALIGN).unwrap())?
+            .check_init()?;
+        let align = align.to_machine_usize(self)?;
+        let align = Align::from_bytes(align).map_err(|e| err_ub!(InvalidVtableAlignment(e)))?;
 
         if size >= self.tcx.data_layout.obj_size_bound() {
-            throw_ub_format!(
-                "invalid vtable: \
-                size is bigger than largest supported object"
-            );
+            throw_ub!(InvalidVtableSize);
         }
         Ok((Size::from_bytes(size), align))
     }
index fb165a991bceba5ae6e5cef17472e64b511162ff..0c7f89c1a36ba10ab46dac0240255cdf8d9501bd 100644 (file)
@@ -21,28 +21,29 @@ use std::hash::Hash;
 
 use super::{
     alloc_range, CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine,
-    MemPlaceMeta, OpTy, Scalar, ScalarMaybeUninit, ValueVisitor,
+    MemPlaceMeta, OpTy, ScalarMaybeUninit, ValueVisitor,
 };
 
 macro_rules! throw_validation_failure {
     ($where:expr, { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )?) => {{
-        let msg = rustc_middle::ty::print::with_no_trimmed_paths(|| {
-            let mut msg = String::new();
-            msg.push_str("encountered ");
-            write!(&mut msg, $($what_fmt),+).unwrap();
+        let mut msg = String::new();
+        msg.push_str("encountered ");
+        write!(&mut msg, $($what_fmt),+).unwrap();
+        $(
+            msg.push_str(", but expected ");
+            write!(&mut msg, $($expected_fmt),+).unwrap();
+        )?
+        let path = rustc_middle::ty::print::with_no_trimmed_paths(|| {
             let where_ = &$where;
             if !where_.is_empty() {
-                msg.push_str(" at ");
-                write_path(&mut msg, where_);
+                let mut path = String::new();
+                write_path(&mut path, where_);
+                Some(path)
+            } else {
+                None
             }
-            $(
-                msg.push_str(", but expected ");
-                write!(&mut msg, $($expected_fmt),+).unwrap();
-            )?
-
-            msg
         });
-        throw_ub!(ValidationFailure(msg))
+        throw_ub!(ValidationFailure { path, msg })
     }};
 }
 
@@ -323,7 +324,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
         let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env);
         match tail.kind() {
             ty::Dynamic(..) => {
-                let vtable = meta.unwrap_meta();
+                let vtable = self.ecx.scalar_to_ptr(meta.unwrap_meta());
                 // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines.
                 try_validation!(
                     self.ecx.memory.check_ptr_access_align(
@@ -334,8 +335,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                     ),
                     self.path,
                     err_ub!(DanglingIntPointer(..)) |
-                    err_ub!(PointerUseAfterFree(..)) |
-                    err_unsup!(ReadBytesAsPointer) =>
+                    err_ub!(PointerUseAfterFree(..)) =>
                         { "dangling vtable pointer in wide pointer" },
                     err_ub!(AlignmentCheckFailed { .. }) =>
                         { "unaligned vtable pointer in wide pointer" },
@@ -346,15 +346,18 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                     self.ecx.read_drop_type_from_vtable(vtable),
                     self.path,
                     err_ub!(DanglingIntPointer(..)) |
-                    err_ub!(InvalidFunctionPointer(..)) |
-                    err_unsup!(ReadBytesAsPointer) =>
+                    err_ub!(InvalidFunctionPointer(..)) =>
                         { "invalid drop function pointer in vtable (not pointing to a function)" },
-                    err_ub!(InvalidDropFn(..)) =>
+                    err_ub!(InvalidVtableDropFn(..)) =>
                         { "invalid drop function pointer in vtable (function has incompatible signature)" },
                 );
                 try_validation!(
                     self.ecx.read_size_and_align_from_vtable(vtable),
                     self.path,
+                    err_ub!(InvalidVtableSize) =>
+                        { "invalid vtable: size is bigger than largest supported object" },
+                    err_ub!(InvalidVtableAlignment(msg)) =>
+                        { "invalid vtable: alignment {}", msg },
                     err_unsup!(ReadPointerAsBytes) => { "invalid size or align in vtable" },
                 );
                 // FIXME: More checks for the vtable.
@@ -432,8 +435,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 { "a dangling {} (address 0x{:x} is unallocated)", kind, i },
             err_ub!(PointerOutOfBounds { .. }) =>
                 { "a dangling {} (going beyond the bounds of its allocation)", kind },
-            err_unsup!(ReadBytesAsPointer) =>
-                { "a dangling {} (created from integer)", kind },
             // This cannot happen during const-eval (because interning already detects
             // dangling pointers), but it can happen in Miri.
             err_ub!(PointerUseAfterFree(..)) =>
@@ -443,17 +444,10 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
         if let Some(ref mut ref_tracking) = self.ref_tracking {
             // Proceed recursively even for ZST, no reason to skip them!
             // `!` is a ZST and we want to validate it.
-            // Normalize before handing `place` to tracking because that will
-            // check for duplicates.
-            let place = if size.bytes() > 0 {
-                self.ecx.force_mplace_ptr(place).expect("we already bounds-checked")
-            } else {
-                place
-            };
             // Skip validation entirely for some external statics
-            if let Scalar::Ptr(ptr) = place.ptr {
+            if let Ok((alloc_id, _offset, _ptr)) = self.ecx.memory.ptr_try_get_alloc(place.ptr) {
                 // not a ZST
-                let alloc_kind = self.ecx.tcx.get_global_alloc(ptr.alloc_id);
+                let alloc_kind = self.ecx.tcx.get_global_alloc(alloc_id);
                 if let Some(GlobalAlloc::Static(did)) = alloc_kind {
                     assert!(!self.ecx.tcx.is_thread_local_static(did));
                     assert!(self.ecx.tcx.is_static(did));
@@ -541,7 +535,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 // types below!
                 if self.ctfe_mode.is_some() {
                     // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
-                    let is_bits = value.check_init().map_or(false, |v| v.is_bits());
+                    let is_bits = value.check_init().map_or(false, |v| v.try_to_int().is_ok());
                     if !is_bits {
                         throw_validation_failure!(self.path,
                             { "{}", value } expected { "initialized plain (non-pointer) bytes" }
@@ -596,12 +590,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 // message below.
                 let value = value.to_scalar_or_uninit();
                 let _fn = try_validation!(
-                    value.check_init().and_then(|ptr| self.ecx.memory.get_fn(ptr)),
+                    value.check_init().and_then(|ptr| self.ecx.memory.get_fn(self.ecx.scalar_to_ptr(ptr))),
                     self.path,
                     err_ub!(DanglingIntPointer(..)) |
                     err_ub!(InvalidFunctionPointer(..)) |
-                    err_ub!(InvalidUninitBytes(None)) |
-                    err_unsup!(ReadBytesAsPointer) =>
+                    err_ub!(InvalidUninitBytes(None)) =>
                         { "{}", value } expected { "a function pointer" },
                 );
                 // FIXME: Check if the signature matches
@@ -659,8 +652,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
             err_ub!(InvalidUninitBytes(None)) => { "{}", value }
                 expected { "something {}", wrapping_range_format(valid_range, max_hi) },
         );
-        let bits = match value.to_bits_or_ptr(op.layout.size, self.ecx) {
-            Err(ptr) => {
+        let bits = match value.try_to_int() {
+            Err(_) => {
+                // So this is a pointer then, and casting to an int failed.
+                // Can only happen during CTFE.
+                let ptr = self.ecx.scalar_to_ptr(value);
                 if lo == 1 && hi == max_hi {
                     // Only null is the niche.  So make sure the ptr is NOT null.
                     if self.ecx.memory.ptr_may_be_null(ptr) {
@@ -685,7 +681,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                     )
                 }
             }
-            Ok(data) => data,
+            Ok(int) => int.assert_bits(op.layout.size),
         };
         // Now compare. This is slightly subtle because this is a special "wrap-around" range.
         if wrapping_range_contains(&valid_range, bits) {
@@ -827,7 +823,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
     ) -> InterpResult<'tcx> {
         match op.layout.ty.kind() {
             ty::Str => {
-                let mplace = op.assert_mem_place(self.ecx); // strings are never immediate
+                let mplace = op.assert_mem_place(); // strings are never immediate
                 let len = mplace.len(self.ecx)?;
                 try_validation!(
                     self.ecx.memory.read_bytes(mplace.ptr, Size::from_bytes(len)),
@@ -848,7 +844,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                 // Optimized handling for arrays of integer/float type.
 
                 // Arrays cannot be immediate, slices are never immediate.
-                let mplace = op.assert_mem_place(self.ecx);
+                let mplace = op.assert_mem_place();
                 // This is the length of the array/slice.
                 let len = mplace.len(self.ecx)?;
                 // This is the element type size.
@@ -935,9 +931,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // Construct a visitor
         let mut visitor = ValidityVisitor { path, ref_tracking, ctfe_mode, ecx: self };
 
-        // Try to cast to ptr *once* instead of all the time.
-        let op = self.force_op_ptr(&op).unwrap_or(*op);
-
         // Run it.
         match visitor.visit_value(&op) {
             Ok(()) => Ok(()),
index 32edca6f3dff9629ce15ede2cea11c8f811a4abb..679d30227f1366cb4e89b1b25ad9e923a6efc268 100644 (file)
@@ -211,7 +211,8 @@ macro_rules! make_value_visitor {
                     // If it is a trait object, switch to the real type that was used to create it.
                     ty::Dynamic(..) => {
                         // immediate trait objects are not a thing
-                        let dest = v.to_op(self.ecx())?.assert_mem_place(self.ecx());
+                        let op = v.to_op(self.ecx())?;
+                        let dest = op.assert_mem_place();
                         let inner = self.ecx().unpack_dyn_trait(&dest)?.1;
                         trace!("walk_value: dyn object layout: {:#?}", inner.layout);
                         // recurse with the inner type
@@ -241,7 +242,8 @@ macro_rules! make_value_visitor {
                     },
                     FieldsShape::Array { .. } => {
                         // Let's get an mplace first.
-                        let mplace = v.to_op(self.ecx())?.assert_mem_place(self.ecx());
+                        let op = v.to_op(self.ecx())?;
+                        let mplace = op.assert_mem_place();
                         // Now we can go over all the fields.
                         // This uses the *run-time length*, i.e., if we are a slice,
                         // the dynamic info from the metadata is used.
index 1da17bddcb777c3b044f4160beb686b8fddf4172..a58ded9cfd3a4b77f682fe61775aa5fdabf88cdb 100644 (file)
@@ -29,6 +29,7 @@ Rust MIR: a lowered representation of Rust.
 #![feature(option_get_or_insert_default)]
 #![feature(once_cell)]
 #![feature(control_flow_enum)]
+#![feature(try_reserve)]
 #![recursion_limit = "256"]
 
 #[macro_use]
index 31cb5484bcefb3ae842bbacbeeb41a857941a3fa..2ce7cf71116bbf9125ff8ba57777fcfcb093b2c6 100644 (file)
@@ -196,10 +196,11 @@ use rustc_middle::mir::{self, Local, Location};
 use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
-use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable, VtblEntry};
 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) {
@@ -399,7 +403,7 @@ fn collect_items_rec<'tcx>(
             recursion_depth_reset = None;
 
             if let Ok(alloc) = tcx.eval_static_initializer(def_id) {
-                for &((), id) in alloc.relocations().values() {
+                for &id in alloc.relocations().values() {
                     collect_miri(tcx, id, &mut neighbors);
                 }
             }
@@ -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 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
 
     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;
         }
@@ -1071,6 +1081,13 @@ fn create_fn_mono_item<'tcx>(
     source: Span,
 ) -> Spanned<MonoItem<'tcx>> {
     debug!("create_fn_mono_item(instance={})", instance);
+
+    let def_id = instance.def_id();
+    if tcx.sess.opts.debugging_opts.profile_closures && def_id.is_local() && tcx.is_closure(def_id)
+    {
+        monomorphize::util::dump_closure_profile(tcx, instance);
+    }
+
     respan(source, MonoItem::Fn(instance.polymorphize(tcx)))
 }
 
@@ -1091,21 +1108,22 @@ fn create_mono_items_for_vtable_methods<'tcx>(
             assert!(!poly_trait_ref.has_escaping_bound_vars());
 
             // Walk all methods of the trait, including those of its supertraits
-            let methods = tcx.vtable_methods(poly_trait_ref);
-            let methods = methods
+            let entries = tcx.vtable_entries(poly_trait_ref);
+            let methods = entries
                 .iter()
-                .cloned()
-                .filter_map(|method| method)
-                .map(|(def_id, substs)| {
-                    ty::Instance::resolve_for_vtable(
+                .filter_map(|entry| match entry {
+                    VtblEntry::MetadataDropInPlace
+                    | VtblEntry::MetadataSize
+                    | VtblEntry::MetadataAlign
+                    | VtblEntry::Vacant => None,
+                    VtblEntry::Method(def_id, substs) => ty::Instance::resolve_for_vtable(
                         tcx,
                         ty::ParamEnv::reveal_all(),
-                        def_id,
+                        *def_id,
                         substs,
                     )
-                    .unwrap()
+                    .filter(|instance| should_codegen_locally(tcx, instance)),
                 })
-                .filter(|&instance| should_codegen_locally(tcx, &instance))
                 .map(|item| create_fn_mono_item(tcx, item, source));
             output.extend(methods);
         }
@@ -1351,7 +1369,7 @@ fn collect_miri<'tcx>(
         }
         GlobalAlloc::Memory(alloc) => {
             trace!("collecting {:?} with {:#?}", alloc_id, alloc);
-            for &((), inner) in alloc.relocations().values() {
+            for &inner in alloc.relocations().values() {
                 rustc_data_structures::stack::ensure_sufficient_stack(|| {
                     collect_miri(tcx, inner, output);
                 });
@@ -1384,9 +1402,9 @@ fn collect_const_value<'tcx>(
     output: &mut Vec<Spanned<MonoItem<'tcx>>>,
 ) {
     match value {
-        ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output),
+        ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => collect_miri(tcx, ptr.provenance, output),
         ConstValue::Slice { data: alloc, start: _, end: _ } | ConstValue::ByRef { alloc, .. } => {
-            for &((), id) in alloc.relocations().values() {
+            for &id in alloc.relocations().values() {
                 collect_miri(tcx, id, output);
             }
         }
index 9ca4b6687f1b54b934eaf0319653cb4c39d1c735..57d2723cf9cfdf1af30122b7fb7c64e21a67d72e 100644 (file)
@@ -7,6 +7,7 @@ use rustc_hir::lang_items::LangItem;
 pub mod collector;
 pub mod partitioning;
 pub mod polymorphize;
+pub mod util;
 
 fn custom_coerce_unsize_info<'tcx>(
     tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_mir/src/monomorphize/util.rs b/compiler/rustc_mir/src/monomorphize/util.rs
new file mode 100644 (file)
index 0000000..799b4e1
--- /dev/null
@@ -0,0 +1,73 @@
+use rustc_middle::ty::{self, ClosureSizeProfileData, Instance, TyCtxt};
+use std::fs::OpenOptions;
+use std::io::prelude::*;
+
+/// For a given closure, writes out the data for the profiling the impact of RFC 2229 on
+/// closure size into a CSV.
+///
+/// During the same compile all closures dump the information in the same file
+/// "closure_profile_XXXXX.csv", which is created in the directory where the compiler is invoked.
+crate fn dump_closure_profile(tcx: TyCtxt<'tcx>, closure_instance: Instance<'tcx>) {
+    let mut file = if let Ok(file) = OpenOptions::new()
+        .create(true)
+        .append(true)
+        .open(&format!("closure_profile_{}.csv", std::process::id()))
+    {
+        file
+    } else {
+        eprintln!("Cound't open file for writing closure profile");
+        return;
+    };
+
+    let closure_def_id = closure_instance.def_id();
+    let typeck_results = tcx.typeck(closure_def_id.expect_local());
+
+    if typeck_results.closure_size_eval.contains_key(&closure_def_id) {
+        let param_env = ty::ParamEnv::reveal_all();
+
+        let ClosureSizeProfileData { before_feature_tys, after_feature_tys } =
+            typeck_results.closure_size_eval[&closure_def_id];
+
+        let before_feature_tys = tcx.subst_and_normalize_erasing_regions(
+            closure_instance.substs,
+            param_env,
+            before_feature_tys,
+        );
+        let after_feature_tys = tcx.subst_and_normalize_erasing_regions(
+            closure_instance.substs,
+            param_env,
+            after_feature_tys,
+        );
+
+        let new_size = tcx
+            .layout_of(param_env.and(after_feature_tys))
+            .map(|l| format!("{:?}", l.size.bytes()))
+            .unwrap_or_else(|e| format!("Failed {:?}", e));
+
+        let old_size = tcx
+            .layout_of(param_env.and(before_feature_tys))
+            .map(|l| format!("{:?}", l.size.bytes()))
+            .unwrap_or_else(|e| format!("Failed {:?}", e));
+
+        let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
+        let closure_span = tcx.hir().span(closure_hir_id);
+        let src_file = tcx.sess.source_map().span_to_filename(closure_span);
+        let line_nos = tcx
+            .sess
+            .source_map()
+            .span_to_lines(closure_span)
+            .map(|l| format!("{:?} {:?}", l.lines.first(), l.lines.last()))
+            .unwrap_or_else(|e| format!("{:?}", e));
+
+        if let Err(e) = writeln!(
+            file,
+            "{}, {}, {}, {:?}",
+            old_size,
+            new_size,
+            src_file.prefer_local(),
+            line_nos
+        ) {
+            eprintln!("Error writting to file {}", e.to_string())
+        }
+    }
+}
index 1dddaeb89e684cfb1b331fb51c7bb2ff0babf404..12ee6bb4c67faae93b7a844ec018884ec5654422 100644 (file)
@@ -38,7 +38,9 @@ impl<'tcx> MirPass<'tcx> for AddCallGuards {
 
 impl AddCallGuards {
     pub fn add_call_guards(&self, body: &mut Body<'_>) {
-        let pred_count: IndexVec<_, _> = body.predecessors().iter().map(|ps| ps.len()).collect();
+        let mut pred_count: IndexVec<_, _> =
+            body.predecessors().iter().map(|ps| ps.len()).collect();
+        pred_count[START_BLOCK] += 1;
 
         // We need a place to store the new blocks generated
         let mut new_blocks = Vec::new();
index dcbc9c523dc1946f55687f59f0b8281d4f8e5d9e..fd72ec4340f9f2a7f9c462c9039f3888998e70c2 100644 (file)
@@ -397,6 +397,9 @@ impl NonConstOp for PanicNonStr {
     }
 }
 
+/// 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 @@ impl NonConstOp for RawPtrDeref {
     }
 }
 
+/// 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 4fbd27c89d9c8f6b7f0338f3d2020ad1c3db6f28..cfc538ef500a12d2e43d4846dc8d46ca23c037b7 100644 (file)
@@ -822,12 +822,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                     let obligation = Obligation::new(
                         ObligationCause::dummy(),
                         param_env,
-                        Binder::bind(
-                            TraitPredicate {
-                                trait_ref: TraitRef::from_method(tcx, trait_id, substs),
-                            },
-                            tcx,
-                        ),
+                        Binder::dummy(TraitPredicate { trait_ref }),
                     );
 
                     let implsrc = tcx.infer_ctxt().enter(|infcx| {
@@ -891,8 +886,37 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                 }
 
                 if !tcx.is_const_fn_raw(callee) {
-                    self.check_op(ops::FnCallNonConst);
-                    return;
+                    let mut permitted = false;
+
+                    let callee_trait = tcx.trait_of_item(callee);
+                    if let Some(trait_id) = callee_trait {
+                        if tcx.has_attr(caller, sym::default_method_body_is_const) {
+                            // permit call to non-const fn when caller has default_method_body_is_const..
+                            if tcx.trait_of_item(caller) == callee_trait {
+                                // ..and caller and callee are in the same trait.
+                                permitted = true;
+                            }
+                        }
+                        if !permitted {
+                            // if trait's impls are all const, permit the call.
+                            let mut const_impls = true;
+                            tcx.for_each_relevant_impl(trait_id, substs.type_at(0), |imp| {
+                                if const_impls {
+                                    if let hir::Constness::NotConst = tcx.impl_constness(imp) {
+                                        const_impls = false;
+                                    }
+                                }
+                            });
+                            if const_impls {
+                                permitted = true;
+                            }
+                        }
+                    }
+
+                    if !permitted {
+                        self.check_op(ops::FnCallNonConst);
+                        return;
+                    }
                 }
 
                 // If the `const fn` we are trying to call is not const-stable, ensure that we have
index 103ddda1a1d262c45069da1fab78d78404a7776b..1ff9bd157210874391deafc577a31eb4dd435c42 100644 (file)
@@ -7,7 +7,6 @@ use rustc_hir::intravisit;
 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 @@ use std::ops::Bound;
 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 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
         Self {
             body,
             body_did,
-            const_context,
             violations: vec![],
             source_info: SourceInfo::outermost(body.span),
             tcx,
@@ -136,25 +132,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                     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 681d63c6fc9664c7116368a79fb9b5e49ec29717..e02e41d62061a380dd70045ac07b57043f2753d2 100644 (file)
@@ -31,9 +31,8 @@ use rustc_trait_selection::traits;
 use crate::const_eval::ConstEvalErr;
 use crate::interpret::{
     self, compile_time_machine, AllocId, Allocation, ConstValue, CtfeValidationMode, Frame, ImmTy,
-    Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, Memory, MemoryKind, OpTy,
-    Operand as InterpOperand, PlaceTy, Pointer, Scalar, ScalarMaybeUninit, StackPopCleanup,
-    StackPopUnwind,
+    Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, MemoryKind, OpTy,
+    Operand as InterpOperand, PlaceTy, Scalar, ScalarMaybeUninit, StackPopCleanup, StackPopUnwind,
 };
 use crate::transform::MirPass;
 
@@ -157,7 +156,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
 
 struct ConstPropMachine<'mir, 'tcx> {
     /// The virtual call stack.
-    stack: Vec<Frame<'mir, 'tcx, (), ()>>,
+    stack: Vec<Frame<'mir, 'tcx>>,
     /// `OnlyInsideOwnBlock` locals that were written in the current block get erased at the end.
     written_only_inside_own_block_locals: FxHashSet<Local>,
     /// Locals that need to be cleared after every block terminates.
@@ -181,6 +180,7 @@ impl<'mir, 'tcx> ConstPropMachine<'mir, 'tcx> {
 
 impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> {
     compile_time_machine!(<'mir, 'tcx>);
+    const PANIC_ON_ALLOC_FAIL: bool = true; // all allocations are small (see `MAX_ALLOC_LIMIT`)
 
     type MemoryKind = !;
 
@@ -222,10 +222,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
         bug!("panics terminators are not evaluated in ConstProp")
     }
 
-    fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> {
-        throw_unsup!(ReadPointerAsBytes)
-    }
-
     fn binary_ptr_op(
         _ecx: &InterpCx<'mir, 'tcx, Self>,
         _bin_op: BinOp,
@@ -393,7 +389,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             .filter(|ret_layout| {
                 !ret_layout.is_zst() && ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT)
             })
-            .map(|ret_layout| ecx.allocate(ret_layout, MemoryKind::Stack).into());
+            .map(|ret_layout| {
+                ecx.allocate(ret_layout, MemoryKind::Stack)
+                    .expect("couldn't perform small allocation")
+                    .into()
+            });
 
         ecx.push_stack_frame(
             Instance::new(def_id, substs),
@@ -528,14 +528,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         source_info: SourceInfo,
         message: &'static str,
         panic: AssertKind<impl std::fmt::Debug>,
-    ) -> Option<()> {
-        let lint_root = self.lint_root(source_info)?;
-        self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
-            let mut err = lint.build(message);
-            err.span_label(source_info.span, format!("{:?}", panic));
-            err.emit()
-        });
-        None
+    ) {
+        if let Some(lint_root) = self.lint_root(source_info) {
+            self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
+                let mut err = lint.build(message);
+                err.span_label(source_info.span, format!("{:?}", panic));
+                err.emit()
+            });
+        }
     }
 
     fn check_unary_op(
@@ -557,7 +557,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 source_info,
                 "this arithmetic operation will overflow",
                 AssertKind::OverflowNeg(val.to_const_int()),
-            )?;
+            );
+            return None;
         }
 
         Some(())
@@ -581,8 +582,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             let left_size = self.ecx.layout_of(left_ty).ok()?.size;
             let right_size = r.layout.size;
             let r_bits = r.to_scalar().ok();
-            // This is basically `force_bits`.
-            let r_bits = r_bits.and_then(|r| r.to_bits_or_ptr(right_size, &self.tcx).ok());
+            let r_bits = r_bits.and_then(|r| r.to_bits(right_size).ok());
             if r_bits.map_or(false, |b| b >= left_size.bits() as u128) {
                 debug!("check_binary_op: reporting assert for {:?}", source_info);
                 self.report_assert_as_lint(
@@ -602,7 +602,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                         },
                         r.to_const_int(),
                     ),
-                )?;
+                );
+                return None;
             }
         }
 
@@ -617,7 +618,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     source_info,
                     "this arithmetic operation will overflow",
                     AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()),
-                )?;
+                );
+                return None;
             }
         }
         Some(())
@@ -751,8 +753,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                         }
                     };
 
-                    let arg_value =
-                        this.ecx.force_bits(const_arg.to_scalar()?, const_arg.layout.size)?;
+                    let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?;
                     let dest = this.ecx.eval_place(place)?;
 
                     match op {
@@ -868,7 +869,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                                     let alloc = this
                                         .ecx
                                         .intern_with_temp_alloc(value.layout, |ecx, dest| {
-                                            ecx.write_immediate_to_mplace(*imm, dest)
+                                            ecx.write_immediate(*imm, dest)
                                         })
                                         .unwrap();
                                     Ok(Some(alloc))
@@ -920,12 +921,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
         match **op {
             interpret::Operand::Immediate(Immediate::Scalar(ScalarMaybeUninit::Scalar(s))) => {
-                s.is_bits()
+                s.try_to_int().is_ok()
             }
             interpret::Operand::Immediate(Immediate::ScalarPair(
                 ScalarMaybeUninit::Scalar(l),
                 ScalarMaybeUninit::Scalar(r),
-            )) => l.is_bits() && r.is_bits(),
+            )) => l.try_to_int().is_ok() && r.try_to_int().is_ok(),
             _ => false,
         }
     }
@@ -1202,12 +1203,9 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                         let mut eval_to_int = |op| {
                             // This can be `None` if the lhs wasn't const propagated and we just
                             // triggered the assert on the value of the rhs.
-                            match self.eval_operand(op, source_info) {
-                                Some(op) => DbgVal::Val(
-                                    self.ecx.read_immediate(&op).unwrap().to_const_int(),
-                                ),
-                                None => DbgVal::Underscore,
-                            }
+                            self.eval_operand(op, source_info).map_or(DbgVal::Underscore, |op| {
+                                DbgVal::Val(self.ecx.read_immediate(&op).unwrap().to_const_int())
+                            })
                         };
                         let msg = match msg {
                             AssertKind::DivisionByZero(op) => {
index f62171b3c535c757fe25accb398462dfa7bce5b3..08cc87ccc349d5c51068e5203bb3b0c710c64675 100644 (file)
@@ -184,11 +184,8 @@ impl CoverageSpan {
         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..7d765cec57578afdbd03a0b0fed5bcfe8c982210 100644 (file)
@@ -284,7 +284,7 @@ impl Inliner<'tcx> {
         &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,10 +836,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
 
     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);
+        *span =
+            self.callsite_span.fresh_expansion(expn_data, self.tcx.create_stable_hashing_context());
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
index 295f3ec70dc7837ec008c85f9778d3941cba574d..c9eafafff57cd2f6f76f758dfa2d34faa483acf3 100644 (file)
@@ -5,6 +5,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 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 @@ crate fn mir_callgraph_reachable(
     );
     #[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 @@ crate fn mir_callgraph_reachable(
         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 @@ crate fn mir_callgraph_reachable(
             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 @@ crate fn mir_callgraph_reachable(
         &mut Vec::new(),
         &mut FxHashSet::default(),
         &mut FxHashMap::default(),
+        tcx.recursion_limit(),
     )
 }
 
diff --git a/compiler/rustc_mir/src/transform/lower_slice_len.rs b/compiler/rustc_mir/src/transform/lower_slice_len.rs
new file mode 100644 (file)
index 0000000..c3eb2d9
--- /dev/null
@@ -0,0 +1,100 @@
+//! This pass lowers calls to core::slice::len to just Len op.
+//! It should run before inlining!
+
+use crate::transform::MirPass;
+use rustc_hir::def_id::DefId;
+use rustc_index::vec::IndexVec;
+use rustc_middle::mir::*;
+use rustc_middle::ty::{self, TyCtxt};
+
+pub struct LowerSliceLenCalls;
+
+impl<'tcx> MirPass<'tcx> for LowerSliceLenCalls {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        lower_slice_len_calls(tcx, body)
+    }
+}
+
+pub fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+    let language_items = tcx.lang_items();
+    let slice_len_fn_item_def_id = if let Some(slice_len_fn_item) = language_items.slice_len_fn() {
+        slice_len_fn_item
+    } else {
+        // there is no language item to compare to :)
+        return;
+    };
+
+    let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
+
+    for block in basic_blocks {
+        // lower `<[_]>::len` calls
+        lower_slice_len_call(tcx, block, &*local_decls, slice_len_fn_item_def_id);
+    }
+}
+
+struct SliceLenPatchInformation<'tcx> {
+    add_statement: Statement<'tcx>,
+    new_terminator_kind: TerminatorKind<'tcx>,
+}
+
+fn lower_slice_len_call<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    block: &mut BasicBlockData<'tcx>,
+    local_decls: &IndexVec<Local, LocalDecl<'tcx>>,
+    slice_len_fn_item_def_id: DefId,
+) {
+    let mut patch_found: Option<SliceLenPatchInformation<'_>> = None;
+
+    let terminator = block.terminator();
+    match &terminator.kind {
+        TerminatorKind::Call {
+            func,
+            args,
+            destination: Some((dest, bb)),
+            cleanup: None,
+            from_hir_call: true,
+            ..
+        } => {
+            // some heuristics for fast rejection
+            if args.len() != 1 {
+                return;
+            }
+            let arg = match args[0].place() {
+                Some(arg) => arg,
+                None => return,
+            };
+            let func_ty = func.ty(local_decls, tcx);
+            match func_ty.kind() {
+                ty::FnDef(fn_def_id, _) if fn_def_id == &slice_len_fn_item_def_id => {
+                    // perform modifications
+                    // from something like `_5 = core::slice::<impl [u8]>::len(move _6) -> bb1`
+                    // into `_5 = Len(*_6)
+                    // goto bb1
+
+                    // make new RValue for Len
+                    let deref_arg = tcx.mk_place_deref(arg);
+                    let r_value = Rvalue::Len(deref_arg);
+                    let len_statement_kind = StatementKind::Assign(Box::new((*dest, r_value)));
+                    let add_statement = Statement {
+                        kind: len_statement_kind,
+                        source_info: terminator.source_info.clone(),
+                    };
+
+                    // modify terminator into simple Goto
+                    let new_terminator_kind = TerminatorKind::Goto { target: bb.clone() };
+
+                    let patch = SliceLenPatchInformation { add_statement, new_terminator_kind };
+
+                    patch_found = Some(patch);
+                }
+                _ => {}
+            }
+        }
+        _ => {}
+    }
+
+    if let Some(SliceLenPatchInformation { add_statement, new_terminator_kind }) = patch_found {
+        block.statements.push(add_statement);
+        block.terminator_mut().kind = new_terminator_kind;
+    }
+}
index 2201223e13eabd92b0314a4bd20ed5c01b3ddae0..5c201594ddd895f574f7122ea9576ffd4ee34ec7 100644 (file)
@@ -36,6 +36,7 @@ pub mod generator;
 pub mod inline;
 pub mod instcombine;
 pub mod lower_intrinsics;
+pub mod lower_slice_len;
 pub mod match_branches;
 pub mod multiple_return_terminators;
 pub mod no_landing_pads;
@@ -479,6 +480,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     // to them. We run some optimizations before that, because they may be harder to do on the state
     // machine than on MIR with async primitives.
     let optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[
+        &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first
         &unreachable_prop::UnreachablePropagation,
         &uninhabited_enum_branching::UninhabitedEnumBranching,
         &simplify::SimplifyCfg::new("after-uninhabited-enum-branching"),
index 9f473f3bae534df547064fbcb224edd2653250c3..1ddf7c9cd0c9e096c16b2fe73d9adb5d4aa762f3 100644 (file)
@@ -46,7 +46,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral {
                         .expect("if we have an evaluated constant we must know the layout");
                     int.assert_bits(layout.size)
                 }
-                Scalar::Ptr(_) => continue,
+                Scalar::Ptr(..) => continue,
             };
             const FALSE: u128 = 0;
 
@@ -211,7 +211,7 @@ fn find_branch_value_info<'tcx>(
                 return None;
             };
             let branch_value_scalar = branch_value.literal.try_to_scalar()?;
-            Some((branch_value_scalar, branch_value_ty, *to_switch_on))
+            Some((branch_value_scalar.into(), branch_value_ty, *to_switch_on))
         }
         _ => None,
     }
index 465832c89fd00871b7f7117c0d28ee196152efc4..5c6c158d46e3a702cf91bd1d8d507c31da1521c8 100644 (file)
@@ -24,6 +24,7 @@ fn get_discriminant_local(terminator: &TerminatorKind<'_>) -> Option<Local> {
 /// discriminant is read from. Otherwise, returns None.
 fn get_switched_on_type<'tcx>(
     block_data: &BasicBlockData<'tcx>,
+    tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
 ) -> Option<Ty<'tcx>> {
     let terminator = block_data.terminator();
@@ -36,12 +37,9 @@ fn get_switched_on_type<'tcx>(
         if let Some(StatementKind::Assign(box (l, Rvalue::Discriminant(place)))) = stmt_before_term
         {
             if l.as_local() == Some(local) {
-                if let Some(r_local) = place.as_local() {
-                    let ty = body.local_decls[r_local].ty;
-
-                    if ty.is_enum() {
-                        return Some(ty);
-                    }
+                let ty = place.ty(body, tcx).ty;
+                if ty.is_enum() {
+                    return Some(ty);
                 }
             }
         }
@@ -86,7 +84,7 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
             trace!("processing block {:?}", bb);
 
             let discriminant_ty =
-                if let Some(ty) = get_switched_on_type(&body.basic_blocks()[bb], body) {
+                if let Some(ty) = get_switched_on_type(&body.basic_blocks()[bb], tcx, body) {
                     ty
                 } else {
                     continue;
index c4e1e184ac52a34ebfae2e8e54baa757a3e4b8f4..d0b1bc47ea80063cf6a7ea21651653915cebfc31 100644 (file)
@@ -1,6 +1,6 @@
 use std::collections::BTreeSet;
+use std::fmt::Display;
 use std::fmt::Write as _;
-use std::fmt::{Debug, Display};
 use std::fs;
 use std::io::{self, Write};
 use std::path::{Path, PathBuf};
@@ -13,7 +13,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::Idx;
 use rustc_middle::mir::interpret::{
-    read_target_uint, AllocId, Allocation, ConstValue, GlobalAlloc, Pointer,
+    read_target_uint, AllocId, Allocation, ConstValue, GlobalAlloc, Pointer, Provenance,
 };
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
@@ -99,7 +99,10 @@ pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, def_id: DefId) ->
     });
     filters.split('|').any(|or_filter| {
         or_filter.split('&').all(|and_filter| {
-            and_filter == "all" || pass_name.contains(and_filter) || node_path.contains(and_filter)
+            let and_filter_trimmed = and_filter.trim();
+            and_filter_trimmed == "all"
+                || pass_name.contains(and_filter_trimmed)
+                || node_path.contains(and_filter_trimmed)
         })
     })
 }
@@ -423,14 +426,14 @@ impl ExtraComments<'tcx> {
     }
 }
 
-fn use_verbose(ty: &&TyS<'tcx>) -> bool {
+fn use_verbose(ty: &&TyS<'tcx>, fn_def: bool) -> bool {
     match ty.kind() {
         ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) => false,
         // Unit type
         ty::Tuple(g_args) if g_args.is_empty() => false,
-        ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(&g_arg.expect_ty())),
-        ty::Array(ty, _) => use_verbose(ty),
-        ty::FnDef(..) => false,
+        ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(&g_arg.expect_ty(), fn_def)),
+        ty::Array(ty, _) => use_verbose(ty, fn_def),
+        ty::FnDef(..) => fn_def,
         _ => true,
     }
 }
@@ -439,28 +442,20 @@ impl Visitor<'tcx> for ExtraComments<'tcx> {
     fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
         self.super_constant(constant, location);
         let Constant { span, user_ty, literal } = constant;
-        match literal.ty().kind() {
-            ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char => {}
-            // Unit type
-            ty::Tuple(tys) if tys.is_empty() => {}
-            _ => {
-                self.push("mir::Constant");
-                self.push(&format!(
-                    "+ span: {}",
-                    self.tcx.sess.source_map().span_to_embeddable_string(*span)
-                ));
-                if let Some(user_ty) = user_ty {
-                    self.push(&format!("+ user_ty: {:?}", user_ty));
-                }
-                match literal {
-                    ConstantKind::Ty(literal) => self.push(&format!("+ literal: {:?}", literal)),
-                    ConstantKind::Val(val, ty) => {
-                        // To keep the diffs small, we render this almost like we render ty::Const
-                        self.push(&format!(
-                            "+ literal: Const {{ ty: {}, val: Value({:?}) }}",
-                            ty, val
-                        ))
-                    }
+        if use_verbose(&literal.ty(), true) {
+            self.push("mir::Constant");
+            self.push(&format!(
+                "+ span: {}",
+                self.tcx.sess.source_map().span_to_embeddable_string(*span)
+            ));
+            if let Some(user_ty) = user_ty {
+                self.push(&format!("+ user_ty: {:?}", user_ty));
+            }
+            match literal {
+                ConstantKind::Ty(literal) => self.push(&format!("+ literal: {:?}", literal)),
+                ConstantKind::Val(val, ty) => {
+                    // To keep the diffs small, we render this almost like we render ty::Const
+                    self.push(&format!("+ literal: Const {{ ty: {}, val: Value({:?}) }}", ty, val))
                 }
             }
         }
@@ -469,7 +464,7 @@ impl Visitor<'tcx> for ExtraComments<'tcx> {
     fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
         self.super_const(constant);
         let ty::Const { ty, val, .. } = constant;
-        if use_verbose(ty) {
+        if use_verbose(ty, false) {
             self.push("ty::Const");
             self.push(&format!("+ ty: {:?}", ty));
             let val = match val {
@@ -670,12 +665,12 @@ pub fn write_allocations<'tcx>(
     w: &mut dyn Write,
 ) -> io::Result<()> {
     fn alloc_ids_from_alloc(alloc: &Allocation) -> impl DoubleEndedIterator<Item = AllocId> + '_ {
-        alloc.relocations().values().map(|(_, id)| *id)
+        alloc.relocations().values().map(|id| *id)
     }
     fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
         match val {
-            ConstValue::Scalar(interpret::Scalar::Ptr(ptr)) => {
-                Either::Left(Either::Left(std::iter::once(ptr.alloc_id)))
+            ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _size)) => {
+                Either::Left(Either::Left(std::iter::once(ptr.provenance)))
             }
             ConstValue::Scalar(interpret::Scalar::Int { .. }) => {
                 Either::Left(Either::Right(std::iter::empty()))
@@ -760,7 +755,7 @@ pub fn write_allocations<'tcx>(
 /// After the hex dump, an ascii dump follows, replacing all unprintable characters (control
 /// characters or characters whose value is larger than 127) with a `.`
 /// This also prints relocations adequately.
-pub fn display_allocation<Tag: Copy + Debug, Extra>(
+pub fn display_allocation<Tag, Extra>(
     tcx: TyCtxt<'tcx>,
     alloc: &'a Allocation<Tag, Extra>,
 ) -> RenderAllocation<'a, 'tcx, Tag, Extra> {
@@ -773,7 +768,7 @@ pub struct RenderAllocation<'a, 'tcx, Tag, Extra> {
     alloc: &'a Allocation<Tag, Extra>,
 }
 
-impl<Tag: Copy + Debug, Extra> std::fmt::Display for RenderAllocation<'a, 'tcx, Tag, Extra> {
+impl<Tag: Provenance, Extra> std::fmt::Display for RenderAllocation<'a, 'tcx, Tag, Extra> {
     fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         let RenderAllocation { tcx, alloc } = *self;
         write!(w, "size: {}, align: {})", alloc.size().bytes(), alloc.align.bytes())?;
@@ -816,7 +811,7 @@ fn write_allocation_newline(
 /// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there
 /// is only one line). Note that your prefix should contain a trailing space as the lines are
 /// printed directly after it.
-fn write_allocation_bytes<Tag: Copy + Debug, Extra>(
+fn write_allocation_bytes<Tag: Provenance, Extra>(
     tcx: TyCtxt<'tcx>,
     alloc: &Allocation<Tag, Extra>,
     w: &mut dyn std::fmt::Write,
@@ -824,7 +819,7 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>(
 ) -> std::fmt::Result {
     let num_lines = alloc.size().bytes_usize().saturating_sub(BYTES_PER_LINE);
     // Number of chars needed to represent all line numbers.
-    let pos_width = format!("{:x}", alloc.size().bytes()).len();
+    let pos_width = hex_number_length(alloc.size().bytes());
 
     if num_lines > 0 {
         write!(w, "{}0x{:02$x} │ ", prefix, 0, pos_width)?;
@@ -852,7 +847,7 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>(
         if i != line_start {
             write!(w, " ")?;
         }
-        if let Some(&(tag, target_id)) = alloc.relocations().get(&i) {
+        if let Some(&tag) = alloc.relocations().get(&i) {
             // Memory with a relocation must be defined
             let j = i.bytes_usize();
             let offset = alloc
@@ -860,7 +855,7 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>(
             let offset = read_target_uint(tcx.data_layout.endian, offset).unwrap();
             let offset = Size::from_bytes(offset);
             let relocation_width = |bytes| bytes * 3;
-            let ptr = Pointer::new_with_tag(target_id, offset, tag);
+            let ptr = Pointer::new(tag, offset);
             let mut target = format!("{:?}", ptr);
             if target.len() > relocation_width(ptr_size.bytes_usize() - 1) {
                 // This is too long, try to save some space.
@@ -1023,3 +1018,23 @@ pub fn dump_mir_def_ids(tcx: TyCtxt<'_>, single: Option<DefId>) -> Vec<DefId> {
         tcx.mir_keys(()).iter().map(|def_id| def_id.to_def_id()).collect()
     }
 }
+
+/// Calc converted u64 decimal into hex and return it's length in chars
+///
+/// ```ignore (cannot-test-private-function)
+/// assert_eq!(1, hex_number_length(0));
+/// assert_eq!(1, hex_number_length(1));
+/// assert_eq!(2, hex_number_length(16));
+/// ```
+fn hex_number_length(x: u64) -> usize {
+    if x == 0 {
+        return 1;
+    }
+    let mut length = 0;
+    let mut x_left = x;
+    while x_left > 0 {
+        x_left /= 16;
+        length += 1;
+    }
+    length
+}
index 8426b24270d668ab1d1ef24501cdd03fea31d286..df71379c1d88643c50813a1329565cc9c401bc90 100644 (file)
@@ -74,8 +74,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // First we build all the statements in the block.
         let mut let_scope_stack = Vec::with_capacity(8);
         let outer_source_scope = this.source_scope;
-        let outer_push_unsafe_count = this.push_unsafe_count;
-        let outer_unpushed_unsafe = this.unpushed_unsafe;
+        let outer_in_scope_unsafe = this.in_scope_unsafe;
         this.update_source_scope_for_safety_mode(span, safety_mode);
 
         let source_info = this.source_info(span);
@@ -206,8 +205,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
         // Restore the original source scope.
         this.source_scope = outer_source_scope;
-        this.push_unsafe_count = outer_push_unsafe_count;
-        this.unpushed_unsafe = outer_unpushed_unsafe;
+        this.in_scope_unsafe = outer_in_scope_unsafe;
         block.unit()
     }
 
@@ -216,9 +214,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         debug!("update_source_scope_for({:?}, {:?})", span, safety_mode);
         let new_unsafety = match safety_mode {
             BlockSafety::Safe => None,
+            BlockSafety::BuiltinUnsafe => Some(Safety::BuiltinUnsafe),
             BlockSafety::ExplicitUnsafe(hir_id) => {
-                assert_eq!(self.push_unsafe_count, 0);
-                match self.unpushed_unsafe {
+                match self.in_scope_unsafe {
                     Safety::Safe => {}
                     // no longer treat `unsafe fn`s as `unsafe` contexts (see RFC #2585)
                     Safety::FnUnsafe
@@ -226,20 +224,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             != Level::Allow => {}
                     _ => return,
                 }
-                self.unpushed_unsafe = Safety::ExplicitUnsafe(hir_id);
+                self.in_scope_unsafe = Safety::ExplicitUnsafe(hir_id);
                 Some(Safety::ExplicitUnsafe(hir_id))
             }
-            BlockSafety::PushUnsafe => {
-                self.push_unsafe_count += 1;
-                Some(Safety::BuiltinUnsafe)
-            }
-            BlockSafety::PopUnsafe => {
-                self.push_unsafe_count = self
-                    .push_unsafe_count
-                    .checked_sub(1)
-                    .unwrap_or_else(|| span_bug!(span, "unsafe count underflow"));
-                if self.push_unsafe_count == 0 { Some(self.unpushed_unsafe) } else { None }
-            }
         };
 
         if let Some(unsafety) = new_unsafety {
index 5511cd4c73b7de6d4ac8a7dccae4bc28f9cb22a0..bedb8b1c58b82c2db32a0f127b42002b0f74801f 100644 (file)
@@ -217,6 +217,10 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>(
                 ty::ClosureKind::FnOnce => {}
             }
 
+            // We won't be building MIR if the closure wasn't local
+            let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
+            let closure_span = tcx.hir().span(closure_hir_id);
+
             let (capture_index, capture) = if let Some(capture_details) =
                 find_capture_matching_projections(
                     typeck_results,
@@ -226,7 +230,7 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>(
                 ) {
                 capture_details
             } else {
-                if !tcx.features().capture_disjoint_fields {
+                if !enable_precise_capture(tcx, closure_span) {
                     bug!(
                         "No associated capture found for {:?}[{:#?}] even though \
                             capture_disjoint_fields isn't enabled",
@@ -242,8 +246,7 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>(
                 return Err(from_builder);
             };
 
-            let closure_ty = typeck_results
-                .node_type(tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local()));
+            let closure_ty = typeck_results.node_type(closure_hir_id);
 
             let substs = match closure_ty.kind() {
                 ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
@@ -780,3 +783,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 }
+
+/// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if
+/// user is using Rust Edition 2021 or higher.
+fn enable_precise_capture(tcx: TyCtxt<'_>, closure_span: Span) -> bool {
+    tcx.features().capture_disjoint_fields || closure_span.rust_2021()
+}
index f2b00f0f6edaaeb0cc8e0de0f05c21518633bb00..d7b3a85c15d8f4c339cb7a076e1b232b7e9438ba 100644 (file)
@@ -264,7 +264,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 this.cfg.push_assign(block, source_info, destination, address_of);
                 block.unit()
             }
-            ExprKind::Adt { adt_def, variant_index, substs, user_ty, ref fields, ref base } => {
+            ExprKind::Adt(box Adt {
+                adt_def,
+                variant_index,
+                substs,
+                user_ty,
+                ref fields,
+                ref base,
+            }) => {
                 // See the notes for `ExprKind::Array` in `as_rvalue` and for
                 // `ExprKind::Borrow` above.
                 let is_union = adt_def.is_union();
index 539de80cab71cae30d19ae47e07183f47ae648f4..7c1a592f5515efbc2d0a948e8bd3428d88a908c6 100644 (file)
@@ -65,6 +65,6 @@ mod as_operand;
 pub mod as_place;
 mod as_rvalue;
 mod as_temp;
-mod category;
+pub mod category;
 mod into;
 mod stmt;
index 10d6521e7debaab8ebbd11b30ff7aaa623168a16..60cfd73b19a6e8b5b04c5e64574d197aedee7cf2 100644 (file)
@@ -367,12 +367,8 @@ struct Builder<'a, 'tcx> {
     /// `{ STMTS; EXPR1 } + EXPR2`.
     block_context: BlockContext,
 
-    /// The current unsafe block in scope, even if it is hidden by
-    /// a `PushUnsafeBlock`.
-    unpushed_unsafe: Safety,
-
-    /// The number of `push_unsafe_block` levels in scope.
-    push_unsafe_count: usize,
+    /// The current unsafe block in scope
+    in_scope_unsafe: Safety,
 
     /// The vector of all scopes that we have created thus far;
     /// we track this for debuginfo later.
@@ -877,8 +873,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             source_scopes: IndexVec::new(),
             source_scope: OUTERMOST_SOURCE_SCOPE,
             guard_context: vec![],
-            push_unsafe_count: 0,
-            unpushed_unsafe: safety,
+            in_scope_unsafe: safety,
             local_decls: IndexVec::from_elem_n(LocalDecl::new(return_ty, return_span), 1),
             canonical_user_type_annotations: IndexVec::new(),
             upvar_mutbls: vec![],
@@ -1136,3 +1131,5 @@ mod expr;
 mod matches;
 mod misc;
 mod scope;
+
+pub(crate) use expr::category::Category as ExprCategory;
index 2d52577829c71829f0c2beaaa91526cfeceb3f95..82e19c0552720b8efebf8f1bce74c0ad1eba6fc3 100644 (file)
@@ -1,9 +1,11 @@
+use crate::build::ExprCategory;
 use crate::thir::visit::{self, Visitor};
 
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
+use rustc_middle::mir::BorrowKind;
 use rustc_middle::thir::*;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, ParamEnv, TyCtxt};
 use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
 use rustc_session::lint::Level;
 use rustc_span::def_id::{DefId, LocalDefId};
@@ -25,15 +27,14 @@ 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,
+    param_env: ParamEnv<'tcx>,
+    inside_adt: bool,
 }
 
 impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
-    fn in_safety_context<R>(
-        &mut self,
-        safety_context: SafetyContext,
-        f: impl FnOnce(&mut Self) -> R,
-    ) {
+    fn in_safety_context(&mut self, safety_context: SafetyContext, f: impl FnOnce(&mut Self)) {
         if let (
             SafetyContext::UnsafeBlock { span: enclosing_span, .. },
             SafetyContext::UnsafeBlock { span: block_span, hir_id, .. },
@@ -63,7 +64,6 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
                 );
             }
             self.safety_context = prev_context;
-            return;
         }
     }
 
@@ -71,6 +71,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
         let (description, note) = kind.description_and_note();
         let unsafe_op_in_unsafe_fn_allowed = self.unsafe_op_in_unsafe_fn_allowed();
         match self.safety_context {
+            SafetyContext::BuiltinUnsafeBlock => {}
             SafetyContext::UnsafeBlock { ref mut used, .. } => {
                 if !self.body_unsafety.is_unsafe() || !unsafe_op_in_unsafe_fn_allowed {
                     // Mark this block as useful
@@ -136,30 +137,207 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
     }
 }
 
+// Searches for accesses to layout constrained fields.
+struct LayoutConstrainedPlaceVisitor<'a, 'tcx> {
+    found: bool,
+    thir: &'a Thir<'tcx>,
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'a, 'tcx> LayoutConstrainedPlaceVisitor<'a, 'tcx> {
+    fn new(thir: &'a Thir<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
+        Self { found: false, thir, tcx }
+    }
+}
+
+impl<'a, 'tcx> Visitor<'a, 'tcx> for LayoutConstrainedPlaceVisitor<'a, 'tcx> {
+    fn thir(&self) -> &'a Thir<'tcx> {
+        self.thir
+    }
+
+    fn visit_expr(&mut self, expr: &Expr<'tcx>) {
+        match expr.kind {
+            ExprKind::Field { lhs, .. } => {
+                if let ty::Adt(adt_def, _) = self.thir[lhs].ty.kind() {
+                    if (Bound::Unbounded, Bound::Unbounded)
+                        != self.tcx.layout_scalar_valid_range(adt_def.did)
+                    {
+                        self.found = true;
+                    }
+                }
+                visit::walk_expr(self, expr);
+            }
+
+            // Keep walking through the expression as long as we stay in the same
+            // place, i.e. the expression is a place expression and not a dereference
+            // (since dereferencing something leads us to a different place).
+            ExprKind::Deref { .. } => {}
+            ref kind if ExprCategory::of(kind).map_or(true, |cat| cat == ExprCategory::Place) => {
+                visit::walk_expr(self, expr);
+            }
+
+            _ => {}
+        }
+    }
+}
+
 impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
     fn thir(&self) -> &'a Thir<'tcx> {
         &self.thir
     }
 
     fn visit_block(&mut self, block: &Block) {
-        if let BlockSafety::ExplicitUnsafe(hir_id) = block.safety_mode {
-            self.in_safety_context(
-                SafetyContext::UnsafeBlock { span: block.span, hir_id, used: false },
-                |this| visit::walk_block(this, block),
-            );
-        } else {
-            visit::walk_block(self, block);
+        match block.safety_mode {
+            // compiler-generated unsafe code should not count towards the usefulness of
+            // an outer unsafe block
+            BlockSafety::BuiltinUnsafe => {
+                self.in_safety_context(SafetyContext::BuiltinUnsafeBlock, |this| {
+                    visit::walk_block(this, block)
+                });
+            }
+            BlockSafety::ExplicitUnsafe(hir_id) => {
+                self.in_safety_context(
+                    SafetyContext::UnsafeBlock { span: block.span, hir_id, used: false },
+                    |this| visit::walk_block(this, block),
+                );
+            }
+            BlockSafety::Safe => {
+                visit::walk_block(self, block);
+            }
+        }
+    }
+
+    fn visit_pat(&mut self, pat: &Pat<'tcx>) {
+        if self.in_union_destructure {
+            match *pat.kind {
+                // binding to a variable allows getting stuff out of variable
+                PatKind::Binding { .. }
+                // match is conditional on having this value
+                | PatKind::Constant { .. }
+                | PatKind::Variant { .. }
+                | PatKind::Leaf { .. }
+                | PatKind::Deref { .. }
+                | PatKind::Range { .. }
+                | PatKind::Slice { .. }
+                | PatKind::Array { .. } => {
+                    self.requires_unsafe(pat.span, AccessToUnionField);
+                    return; // we can return here since this already requires unsafe
+                }
+                // wildcard doesn't take anything
+                PatKind::Wild |
+                // these just wrap other patterns
+                PatKind::Or { .. } |
+                PatKind::AscribeUserType { .. } => {}
+            }
+        };
+
+        match &*pat.kind {
+            PatKind::Leaf { .. } => {
+                if let ty::Adt(adt_def, ..) = pat.ty.kind() {
+                    if adt_def.is_union() {
+                        let old_in_union_destructure =
+                            std::mem::replace(&mut self.in_union_destructure, true);
+                        visit::walk_pat(self, pat);
+                        self.in_union_destructure = old_in_union_destructure;
+                    } else if (Bound::Unbounded, Bound::Unbounded)
+                        != self.tcx.layout_scalar_valid_range(adt_def.did)
+                    {
+                        let old_inside_adt = std::mem::replace(&mut self.inside_adt, true);
+                        visit::walk_pat(self, pat);
+                        self.inside_adt = old_inside_adt;
+                    } else {
+                        visit::walk_pat(self, pat);
+                    }
+                } else {
+                    visit::walk_pat(self, pat);
+                }
+            }
+            PatKind::Binding { mode: BindingMode::ByRef(borrow_kind), ty, .. } => {
+                if self.inside_adt {
+                    if let ty::Ref(_, ty, _) = ty.kind() {
+                        match borrow_kind {
+                            BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => {
+                                if !ty.is_freeze(self.tcx.at(pat.span), self.param_env) {
+                                    self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField);
+                                }
+                            }
+                            BorrowKind::Mut { .. } => {
+                                self.requires_unsafe(pat.span, MutationOfLayoutConstrainedField);
+                            }
+                        }
+                    } else {
+                        span_bug!(
+                            pat.span,
+                            "BindingMode::ByRef in pattern, but found non-reference type {}",
+                            ty
+                        );
+                    }
+                }
+                visit::walk_pat(self, pat);
+            }
+            PatKind::Deref { .. } => {
+                let old_inside_adt = std::mem::replace(&mut self.inside_adt, false);
+                visit::walk_pat(self, pat);
+                self.inside_adt = old_inside_adt;
+            }
+            _ => {
+                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 {
@@ -195,27 +373,17 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
             ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } => {
                 self.requires_unsafe(expr.span, UseOfInlineAssembly);
             }
-            ExprKind::Adt {
+            ExprKind::Adt(box Adt {
                 adt_def,
                 variant_index: _,
                 substs: _,
                 user_ty: _,
                 fields: _,
                 base: _,
-            } => match self.tcx.layout_scalar_valid_range(adt_def.did) {
+            }) => match self.tcx.layout_scalar_valid_range(adt_def.did) {
                 (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: _,
@@ -240,9 +408,60 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, '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);
+                        }
+                    }
+                }
+            }
+            ExprKind::Assign { lhs, rhs } | ExprKind::AssignOp { lhs, rhs, .. } => {
+                // First, check whether we are mutating a layout constrained field
+                let mut visitor = LayoutConstrainedPlaceVisitor::new(self.thir, self.tcx);
+                visit::walk_expr(&mut visitor, &self.thir[lhs]);
+                if visitor.found {
+                    self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField);
+                }
+
+                // Second, check for accesses to union fields
+                // don't have any special handling for AssignOp since it causes a read *and* write to lhs
+                if matches!(expr.kind, ExprKind::Assign { .. }) {
+                    // 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; // we have already visited everything by now
+                }
+            }
+            ExprKind::Borrow { borrow_kind, arg } => match borrow_kind {
+                BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => {
+                    if !self.thir[arg]
+                        .ty
+                        .is_freeze(self.tcx.at(self.thir[arg].span), self.param_env)
+                    {
+                        let mut visitor = LayoutConstrainedPlaceVisitor::new(self.thir, self.tcx);
+                        visit::walk_expr(&mut visitor, expr);
+                        if visitor.found {
+                            self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField);
+                        }
+                    }
+                }
+                BorrowKind::Mut { .. } => {
+                    let mut visitor = LayoutConstrainedPlaceVisitor::new(self.thir, self.tcx);
+                    visit::walk_expr(&mut visitor, expr);
+                    if visitor.found {
+                        self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField);
+                    }
+                }
+            },
             _ => {}
         }
-
         visit::walk_expr(self, expr);
     }
 }
@@ -250,6 +469,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
 #[derive(Clone, Copy)]
 enum SafetyContext {
     Safe,
+    BuiltinUnsafeBlock,
     UnsafeFn,
     UnsafeBlock { span: Span, hir_id: hir::HirId, used: bool },
 }
@@ -283,13 +503,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,
@@ -317,9 +535,6 @@ impl UnsafeOpKind {
                 "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 \
@@ -368,10 +583,15 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
         return;
     }
 
-    // Closures are handled by their parent function
+    // Closures are handled by their owner, if it has a body
     if tcx.is_closure(def.did.to_def_id()) {
-        tcx.ensure().thir_check_unsafety(tcx.hir().local_def_id_to_hir_id(def.did).owner);
-        return;
+        let owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
+        let owner_hir_id = tcx.hir().local_def_id_to_hir_id(owner);
+
+        if tcx.hir().maybe_body_owned_by(owner_hir_id).is_some() {
+            tcx.ensure().thir_check_unsafety(owner);
+            return;
+        }
     }
 
     let (thir, expr) = tcx.thir_body(def);
@@ -392,11 +612,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,
@@ -404,7 +619,10 @@ 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,
+        param_env: tcx.param_env(def.did),
+        inside_adt: false,
     };
     visitor.visit_expr(&thir[expr]);
 }
index d62fd161e2f86e0f84d7272faca42c0b52cbd6b3..f9e7b39f7049ce6ea86da0d9f73aac47fe02c62e 100644 (file)
@@ -38,7 +38,7 @@ crate fn lit_to_const<'tcx>(
         }
         (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
             let id = tcx.allocate_bytes(data);
-            ConstValue::Scalar(Scalar::Ptr(id.into()))
+            ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
         }
         (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
             ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
@@ -46,9 +46,7 @@ crate fn lit_to_const<'tcx>(
         (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
             trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
         }
-        (ast::LitKind::Float(n, _), ty::Float(fty)) => {
-            parse_float(*n, *fty, neg).map_err(|_| LitToConstError::UnparseableFloat)?
-        }
+        (ast::LitKind::Float(n, _), ty::Float(fty)) => parse_float(*n, *fty, neg),
         (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
         (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
         (ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
@@ -57,12 +55,14 @@ crate fn lit_to_const<'tcx>(
     Ok(ty::Const::from_value(tcx, lit, ty))
 }
 
-fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> Result<ConstValue<'tcx>, ()> {
+fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> ConstValue<'tcx> {
     let num = num.as_str();
     use rustc_apfloat::ieee::{Double, Single};
     let scalar = match fty {
         ty::FloatTy::F32 => {
-            let rust_f = num.parse::<f32>().map_err(|_| ())?;
+            let rust_f = num
+                .parse::<f32>()
+                .unwrap_or_else(|e| panic!("f32 failed to parse `{}`: {:?}", num, e));
             let mut f = num.parse::<Single>().unwrap_or_else(|e| {
                 panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
             });
@@ -82,7 +82,9 @@ fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> Result<ConstVa
             Scalar::from_f32(f)
         }
         ty::FloatTy::F64 => {
-            let rust_f = num.parse::<f64>().map_err(|_| ())?;
+            let rust_f = num
+                .parse::<f64>()
+                .unwrap_or_else(|e| panic!("f64 failed to parse `{}`: {:?}", num, e));
             let mut f = num.parse::<Double>().unwrap_or_else(|e| {
                 panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e)
             });
@@ -103,5 +105,5 @@ fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> Result<ConstVa
         }
     };
 
-    Ok(ConstValue::Scalar(scalar))
+    ConstValue::Scalar(scalar)
 }
index 77235fe9ab33b5f890244e5e1d55ffc79702dce5..2d9b5c1d98aab26f66c9db3f8f501e4948376455 100644 (file)
@@ -26,9 +26,12 @@ impl<'tcx> Cx<'tcx> {
             expr: block.expr.map(|expr| self.mirror_expr(expr)),
             safety_mode: match block.rules {
                 hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe,
-                hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(block.hir_id),
-                hir::BlockCheckMode::PushUnsafeBlock(..) => BlockSafety::PushUnsafe,
-                hir::BlockCheckMode::PopUnsafeBlock(..) => BlockSafety::PopUnsafe,
+                hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated) => {
+                    BlockSafety::BuiltinUnsafe
+                }
+                hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) => {
+                    BlockSafety::ExplicitUnsafe(block.hir_id)
+                }
             },
         }
     }
index aa4acfab5c81039c32df9f1b56f0dfbefe823ea8..c3908ddd4fbe85dfb2b813e1b9131a36baa7edda 100644 (file)
@@ -228,14 +228,14 @@ impl<'tcx> Cx<'tcx> {
                                 expr: self.mirror_expr(e),
                             })
                             .collect();
-                        ExprKind::Adt {
+                        ExprKind::Adt(Box::new(Adt {
                             adt_def,
                             substs,
                             variant_index: index,
                             fields: field_refs,
                             user_ty,
                             base: None,
-                        }
+                        }))
                     } else {
                         ExprKind::Call {
                             ty: self.typeck_results().node_type(fun.hir_id),
@@ -362,7 +362,7 @@ impl<'tcx> Cx<'tcx> {
                         let user_provided_types = self.typeck_results().user_provided_types();
                         let user_ty = user_provided_types.get(expr.hir_id).copied();
                         debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
-                        ExprKind::Adt {
+                        ExprKind::Adt(Box::new(Adt {
                             adt_def: adt,
                             variant_index: VariantIdx::new(0),
                             substs,
@@ -375,7 +375,7 @@ impl<'tcx> Cx<'tcx> {
                                     .copied()
                                     .collect(),
                             }),
-                        }
+                        }))
                     }
                     AdtKind::Enum => {
                         let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
@@ -388,14 +388,14 @@ impl<'tcx> Cx<'tcx> {
                                     self.typeck_results().user_provided_types();
                                 let user_ty = user_provided_types.get(expr.hir_id).copied();
                                 debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty);
-                                ExprKind::Adt {
+                                ExprKind::Adt(Box::new(Adt {
                                     adt_def: adt,
                                     variant_index: index,
                                     substs,
                                     user_ty,
                                     fields: self.field_refs(fields),
                                     base: None,
-                                }
+                                }))
                             }
                             _ => {
                                 span_bug!(expr.span, "unexpected res: {:?}", res);
@@ -906,14 +906,14 @@ impl<'tcx> Cx<'tcx> {
                 match ty.kind() {
                     // A unit struct/variant which is used as a value.
                     // We return a completely different ExprKind here to account for this special case.
-                    ty::Adt(adt_def, substs) => ExprKind::Adt {
+                    ty::Adt(adt_def, substs) => ExprKind::Adt(Box::new(Adt {
                         adt_def,
                         variant_index: adt_def.variant_index_with_ctor_id(def_id),
                         substs,
                         user_ty: user_provided_type,
                         fields: box [],
                         base: None,
-                    },
+                    })),
                     _ => bug!("unexpected ty: {:?}", ty),
                 }
             }
@@ -928,7 +928,11 @@ impl<'tcx> Cx<'tcx> {
                 } else {
                     let ptr = self.tcx.create_static_alloc(id);
                     ExprKind::StaticRef {
-                        literal: ty::Const::from_scalar(self.tcx, Scalar::Ptr(ptr.into()), ty),
+                        literal: ty::Const::from_scalar(
+                            self.tcx,
+                            Scalar::from_pointer(ptr.into(), &self.tcx),
+                            ty,
+                        ),
                         def_id: id,
                     }
                 };
index 49ba71e3520d756989fbf75b3070b17d82d68c31..604e544286aefb9fc229f76954190f3cb7cfd7fa 100644 (file)
@@ -67,12 +67,6 @@ impl<'tcx> Cx<'tcx> {
 
         match self.tcx.at(sp).lit_to_const(LitToConstInput { lit, ty, neg }) {
             Ok(c) => c,
-            Err(LitToConstError::UnparseableFloat) => {
-                // FIXME(#31407) this is only necessary because float parsing is buggy
-                self.tcx.sess.span_err(sp, "could not evaluate float literal (see issue #31407)");
-                // create a dummy value and continue compiling
-                self.tcx.const_error(ty)
-            }
             Err(LitToConstError::Reported) => {
                 // create a dummy value and continue compiling
                 self.tcx.const_error(ty)
index 389a7595315c6b2f6656768dec17afa08d4334e3..22c07fbec68279e357e3afb09b315ddbff2ad1aa 100644 (file)
@@ -84,7 +84,7 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
 }
 
 impl PatCtxt<'_, '_> {
-    fn report_inlining_errors(&self, pat_span: Span) {
+    fn report_inlining_errors(&self) {
         for error in &self.errors {
             match *error {
                 PatternError::StaticInPattern(span) => {
@@ -96,14 +96,6 @@ impl PatCtxt<'_, '_> {
                 PatternError::ConstParamInPattern(span) => {
                     self.span_e0158(span, "const parameters cannot be referenced in patterns")
                 }
-                PatternError::FloatBug => {
-                    // FIXME(#31407) this is only necessary because float parsing is buggy
-                    rustc_middle::mir::interpret::struct_error(
-                        self.tcx.at(pat_span),
-                        "could not evaluate float literal (see issue #31407)",
-                    )
-                    .emit();
-                }
                 PatternError::NonConstPath(span) => {
                     rustc_middle::mir::interpret::struct_error(
                         self.tcx.at(span),
@@ -142,7 +134,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
         let pattern: &_ = cx.pattern_arena.alloc(expand_pattern(pattern));
         if !patcx.errors.is_empty() {
             *have_errors = true;
-            patcx.report_inlining_errors(pat.span);
+            patcx.report_inlining_errors();
         }
         (pattern, pattern_ty)
     }
index 369fff00456a79421e123c81bc41ae7acaf2c9f2..926bd830da0ac470afcf1d1661569da560b1b789 100644 (file)
@@ -133,9 +133,6 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
                     traits::NonStructuralMatchTy::Generator => {
                         "generators cannot be used in patterns".to_string()
                     }
-                    traits::NonStructuralMatchTy::Closure => {
-                        "closures cannot be used in patterns".to_string()
-                    }
                     traits::NonStructuralMatchTy::Param => {
                         bug!("use of a constant whose type is a parameter inside a pattern")
                     }
@@ -272,12 +269,14 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
 
         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() => {
@@ -488,17 +487,29 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
                 // convert the dereferenced constant to a pattern that is the sub-pattern of the
                 // deref pattern.
                 _ => {
-                    let old = self.behind_reference.replace(true);
-                    // In case there are structural-match violations somewhere in this subpattern,
-                    // we fall back to a const pattern. If we do not do this, we may end up with
-                    // a !structural-match constant that is not of reference type, which makes it
-                    // very hard to invoke `PartialEq::eq` on it as a fallback.
-                    let val = match self.recur(tcx.deref_const(self.param_env.and(cv)), false) {
-                        Ok(subpattern) => PatKind::Deref { subpattern },
-                        Err(_) => PatKind::Constant { value: cv },
-                    };
-                    self.behind_reference.set(old);
-                    val
+                    if !pointee_ty.is_sized(tcx.at(span), param_env) {
+                        // `tcx.deref_const()` below will ICE with an unsized type
+                        // (except slices, which are handled in a separate arm above).
+                        let msg = format!("cannot use unsized non-slice type `{}` in constant patterns", pointee_ty);
+                        if self.include_lint_checks {
+                            tcx.sess.span_err(span, &msg);
+                        } else {
+                            tcx.sess.delay_span_bug(span, &msg);
+                        }
+                        PatKind::Wild
+                    } else {
+                        let old = self.behind_reference.replace(true);
+                        // In case there are structural-match violations somewhere in this subpattern,
+                        // we fall back to a const pattern. If we do not do this, we may end up with
+                        // a !structural-match constant that is not of reference type, which makes it
+                        // very hard to invoke `PartialEq::eq` on it as a fallback.
+                        let val = match self.recur(tcx.deref_const(self.param_env.and(cv)), false) {
+                            Ok(subpattern) => PatKind::Deref { subpattern },
+                            Err(_) => PatKind::Constant { value: cv },
+                        };
+                        self.behind_reference.set(old);
+                        val
+                    }
                 }
             },
             ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => {
index 4b5b648c5044f3b743755150c2755602279734be..ace13ea44624d627b8959b0328e7e8310d15ba68 100644 (file)
@@ -123,7 +123,7 @@ impl IntRange {
                     // straight to the result, after doing a bit of checking. (We
                     // could remove this branch and just fall through, which
                     // is more general but much slower.)
-                    if let Ok(bits) = scalar.to_bits_or_ptr(target_size, &tcx) {
+                    if let Ok(bits) = scalar.to_bits_or_ptr_internal(target_size) {
                         return Some(bits);
                     }
                 }
index 3225d302cb30c45e58440a2cdf11b21b4c10be10..dd265d881e6c40cd946f4edd74abe019c2a54329 100644 (file)
@@ -31,7 +31,6 @@ crate enum PatternError {
     AssocConstInPattern(Span),
     ConstParamInPattern(Span),
     StaticInPattern(Span),
-    FloatBug,
     NonConstPath(Span),
 }
 
@@ -325,7 +324,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
     fn lower_tuple_subpats(
         &mut self,
-        pats: &'tcx [&'tcx hir::Pat<'tcx>],
+        pats: &'tcx [hir::Pat<'tcx>],
         expected_len: usize,
         gap_pos: Option<usize>,
     ) -> Vec<FieldPat<'tcx>> {
@@ -338,7 +337,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             .collect()
     }
 
-    fn lower_patterns(&mut self, pats: &'tcx [&'tcx hir::Pat<'tcx>]) -> Vec<Pat<'tcx>> {
+    fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Vec<Pat<'tcx>> {
         pats.iter().map(|p| self.lower_pattern(p)).collect()
     }
 
@@ -350,9 +349,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         &mut self,
         span: Span,
         ty: Ty<'tcx>,
-        prefix: &'tcx [&'tcx hir::Pat<'tcx>],
+        prefix: &'tcx [hir::Pat<'tcx>],
         slice: &'tcx Option<&'tcx hir::Pat<'tcx>>,
-        suffix: &'tcx [&'tcx hir::Pat<'tcx>],
+        suffix: &'tcx [hir::Pat<'tcx>],
     ) -> PatKind<'tcx> {
         let prefix = self.lower_patterns(prefix);
         let slice = self.lower_opt_pattern(slice);
@@ -423,6 +422,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             _ => {
                 let pattern_error = match res {
                     Res::Def(DefKind::ConstParam, _) => PatternError::ConstParamInPattern(span),
+                    Res::Def(DefKind::Static, _) => PatternError::StaticInPattern(span),
                     _ => PatternError::NonConstPath(span),
                 };
                 self.errors.push(pattern_error);
@@ -468,11 +468,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) {
             Ok(Some(i)) => i,
             Ok(None) => {
-                self.errors.push(if is_associated_const {
-                    PatternError::AssocConstInPattern(span)
-                } else {
-                    PatternError::StaticInPattern(span)
-                });
+                // It should be assoc consts if there's no error but we cannot resolve it.
+                debug_assert!(is_associated_const);
+
+                self.errors.push(PatternError::AssocConstInPattern(span));
 
                 return pat_from_kind(PatKind::Wild);
             }
@@ -563,10 +562,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
             match self.tcx.at(expr.span).lit_to_const(lit_input) {
                 Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind,
-                Err(LitToConstError::UnparseableFloat) => {
-                    self.errors.push(PatternError::FloatBug);
-                    PatKind::Wild
-                }
                 Err(LitToConstError::Reported) => PatKind::Wild,
                 Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
             }
index 1a60b1de7fd984e44237ccc53cffdbf1f1230cf6..ce5d4362c086ccb9f9bee5e94683e520322c21b2 100644 (file)
@@ -1,4 +1,4 @@
-use rustc_middle::thir::*;
+use rustc_middle::thir::{self, *};
 use rustc_middle::ty::Const;
 
 pub trait Visitor<'a, 'tcx: 'a>: Sized {
@@ -20,6 +20,10 @@ pub trait Visitor<'a, 'tcx: 'a>: Sized {
         walk_arm(self, arm);
     }
 
+    fn visit_pat(&mut self, pat: &Pat<'tcx>) {
+        walk_pat(self, pat);
+    }
+
     fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {}
 }
 
@@ -94,7 +98,14 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
                 visitor.visit_expr(&visitor.thir()[field]);
             }
         }
-        Adt { ref fields, ref base, adt_def: _, variant_index: _, substs: _, user_ty: _ } => {
+        Adt(box thir::Adt {
+            ref fields,
+            ref base,
+            adt_def: _,
+            variant_index: _,
+            substs: _,
+            user_ty: _,
+        }) => {
             for field in &**fields {
                 visitor.visit_expr(&visitor.thir()[field.expr]);
             }
@@ -142,18 +153,19 @@ 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: _,
             init_scope: _,
-            pattern: _,
+            ref pattern,
             lint_level: _,
         } => {
             if let Some(init) = initializer {
-                visitor.visit_expr(&visitor.thir()[init]);
+                visitor.visit_expr(&visitor.thir()[*init]);
             }
+            visitor.visit_pat(pattern);
         }
     }
 }
@@ -170,10 +182,56 @@ pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &B
 pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
     match arm.guard {
         Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
-        Some(Guard::IfLet(ref _pat, expr)) => {
+        Some(Guard::IfLet(ref pat, expr)) => {
+            visitor.visit_pat(pat);
             visitor.visit_expr(&visitor.thir()[expr]);
         }
         None => {}
     }
+    visitor.visit_pat(&arm.pattern);
     visitor.visit_expr(&visitor.thir()[arm.body]);
 }
+
+pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) {
+    use PatKind::*;
+    match pat.kind.as_ref() {
+        AscribeUserType { subpattern, ascription: _ }
+        | Deref { subpattern }
+        | Binding {
+            subpattern: Some(subpattern),
+            mutability: _,
+            mode: _,
+            var: _,
+            ty: _,
+            is_primary: _,
+            name: _,
+        } => visitor.visit_pat(&subpattern),
+        Binding { .. } | Wild => {}
+        Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => {
+            for subpattern in subpatterns {
+                visitor.visit_pat(&subpattern.pattern);
+            }
+        }
+        Constant { value } => visitor.visit_const(value),
+        Range(range) => {
+            visitor.visit_const(range.lo);
+            visitor.visit_const(range.hi);
+        }
+        Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
+            for subpattern in prefix {
+                visitor.visit_pat(&subpattern);
+            }
+            if let Some(pat) = slice {
+                visitor.visit_pat(pat);
+            }
+            for subpattern in suffix {
+                visitor.visit_pat(&subpattern);
+            }
+        }
+        Or { pats } => {
+            for pat in pats {
+                visitor.visit_pat(&pat);
+            }
+        }
+    };
+}
index c887729c355700d5c83f60e204ec3daa84007a9a..60c217571949c624e2807b7925ea7a7f76f59626 100644 (file)
@@ -19,4 +19,3 @@ rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_ast = { path = "../rustc_ast" }
 unicode-normalization = "0.1.11"
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
index 1c2f9a9645fe0286401561f2b4ca08c0a5103a9c..98befe4066bc57a334d124bf13845855e222517a 100644 (file)
@@ -1,12 +1,14 @@
-use rustc_ast::ast::AttrStyle;
+use rustc_ast::ast::{self, AttrStyle};
 use rustc_ast::token::{self, CommentKind, Token, TokenKind};
 use rustc_ast::tokenstream::{Spacing, TokenStream};
 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::RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX;
+use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{BytePos, Pos, Span};
+use rustc_span::{edition::Edition, BytePos, Pos, Span};
 
 use tracing::debug;
 
@@ -166,12 +168,18 @@ impl<'a> StringReader<'a> {
                 self.cook_doc_comment(content_start, content, CommentKind::Block, doc_style)
             }
             rustc_lexer::TokenKind::Whitespace => return None,
-            rustc_lexer::TokenKind::Ident | rustc_lexer::TokenKind::RawIdent => {
+            rustc_lexer::TokenKind::Ident
+            | rustc_lexer::TokenKind::RawIdent
+            | rustc_lexer::TokenKind::UnknownPrefix => {
                 let is_raw_ident = token == rustc_lexer::TokenKind::RawIdent;
+                let is_unknown_prefix = token == rustc_lexer::TokenKind::UnknownPrefix;
                 let mut ident_start = start;
                 if is_raw_ident {
                     ident_start = ident_start + BytePos(2);
                 }
+                if is_unknown_prefix {
+                    self.report_unknown_prefix(start);
+                }
                 let sym = nfc_normalize(self.str_from(ident_start));
                 let span = self.mk_sp(start, self.pos);
                 self.sess.symbol_gallery.insert(sym, span);
@@ -491,6 +499,42 @@ impl<'a> StringReader<'a> {
         FatalError.raise()
     }
 
+    // RFC 3101 introduced the idea of (reserved) prefixes. As of Rust 2021,
+    // using a (unknown) prefix is an error. In earlier editions, however, they
+    // only result in a (allowed by default) lint, and are treated as regular
+    // identifier tokens.
+    fn report_unknown_prefix(&self, start: BytePos) {
+        let prefix_span = self.mk_sp(start, self.pos);
+        let msg = format!("prefix `{}` is unknown", self.str_from_to(start, self.pos));
+
+        let expn_data = prefix_span.ctxt().outer_expn_data();
+
+        if expn_data.edition >= Edition::Edition2021 {
+            // In Rust 2021, this is a hard error.
+            let mut err = self.sess.span_diagnostic.struct_span_err(prefix_span, &msg);
+            err.span_label(prefix_span, "unknown prefix");
+            if expn_data.is_root() {
+                err.span_suggestion_verbose(
+                    prefix_span.shrink_to_hi(),
+                    "consider inserting whitespace here",
+                    " ".into(),
+                    Applicability::MachineApplicable,
+                );
+            }
+            err.note("prefixed identifiers and literals are reserved since Rust 2021");
+            err.emit();
+        } else {
+            // Before Rust 2021, only emit a lint for migration.
+            self.sess.buffer_lint_with_diagnostic(
+                &RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
+                prefix_span,
+                ast::CRATE_NODE_ID,
+                &msg,
+                BuiltinLintDiagnostics::ReservedPrefix(prefix_span),
+            );
+        }
+    }
+
     /// Note: It was decided to not add a test case, because it would be too big.
     /// <https://github.com/rust-lang/rust/pull/50296#issuecomment-392135180>
     fn report_too_many_hashes(&self, start: BytePos, found: usize) -> ! {
index 40e2e34aa05892980a1ccec354932da9bb295119..3eebc088f3fb7c4bddea0e010b314163b6b21857 100644 (file)
@@ -1,5 +1,5 @@
 // Characters and their corresponding confusables were collected from
-// http://www.unicode.org/Public/security/10.0.0/confusables.txt
+// https://www.unicode.org/Public/security/10.0.0/confusables.txt
 
 use super::StringReader;
 use crate::token;
index 8b050389078a648311b408e4415fd19a42541707..e9f0038b2d65dc9d09b763c3ae596d4fb8212e6d 100644 (file)
@@ -64,7 +64,14 @@ impl<'a> Parser<'a> {
                 }
                 self.bump();
                 just_parsed_doc_comment = true;
-                Some(attr::mk_doc_comment(comment_kind, attr_style, data, self.prev_token.span))
+                // Always make an outer attribute - this allows us to recover from a misplaced
+                // inner attribute.
+                Some(attr::mk_doc_comment(
+                    comment_kind,
+                    ast::AttrStyle::Outer,
+                    data,
+                    self.prev_token.span,
+                ))
             } else {
                 None
             };
index 0c814ccfdc928ed05918aa7e49181a793f1609cc..ef05f64da94eda90c73c974dc36e864d8b6e5daa 100644 (file)
@@ -1,4 +1,4 @@
-use super::pat::{RecoverComma, PARAM_EXPECTED};
+use super::pat::{RecoverColon, RecoverComma, PARAM_EXPECTED};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{AttrWrapper, BlockMode, ForceCollect, Parser, PathStyle, Restrictions, TokenType};
 use super::{SemiColonMode, SeqSep, TokenExpectType, TrailingToken};
@@ -431,7 +431,8 @@ impl<'a> Parser<'a> {
         let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
         let limits =
             if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
-        Ok(self.mk_expr(span, self.mk_range(Some(lhs), rhs, limits), AttrVec::new()))
+        let range = self.mk_range(Some(lhs), rhs, limits);
+        Ok(self.mk_expr(span, range, AttrVec::new()))
     }
 
     fn is_at_start_of_range_notation_rhs(&self) -> bool {
@@ -479,7 +480,8 @@ impl<'a> Parser<'a> {
             } else {
                 (lo, None)
             };
-            Ok(this.mk_expr(span, this.mk_range(None, opt_end, limits), attrs.into()))
+            let range = this.mk_range(None, opt_end, limits);
+            Ok(this.mk_expr(span, range, attrs.into()))
         })
     }
 
@@ -1813,7 +1815,7 @@ impl<'a> Parser<'a> {
     /// The `let` token has already been eaten.
     fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let lo = self.prev_token.span;
-        let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes)?;
+        let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes, RecoverColon::Yes)?;
         self.expect(&token::Eq)?;
         let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| {
             this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
@@ -1876,7 +1878,7 @@ impl<'a> Parser<'a> {
             _ => None,
         };
 
-        let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes)?;
+        let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes, RecoverColon::Yes)?;
         if !self.eat_keyword(kw::In) {
             self.error_missing_in_for_loop();
         }
@@ -2083,7 +2085,7 @@ impl<'a> Parser<'a> {
         let attrs = self.parse_outer_attributes()?;
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
             let lo = this.token.span;
-            let pat = this.parse_pat_allow_top_alt(None, RecoverComma::Yes)?;
+            let pat = this.parse_pat_allow_top_alt(None, RecoverComma::Yes, RecoverColon::Yes)?;
             let guard = if this.eat_keyword(kw::If) {
                 let if_span = this.prev_token.span;
                 let cond = this.parse_expr()?;
@@ -2117,7 +2119,7 @@ impl<'a> Parser<'a> {
                     let span = body.span;
                     return Ok((
                         ast::Arm {
-                            attrs,
+                            attrs: attrs.into(),
                             pat,
                             guard,
                             body,
@@ -2171,7 +2173,7 @@ impl<'a> Parser<'a> {
 
             Ok((
                 ast::Arm {
-                    attrs,
+                    attrs: attrs.into(),
                     pat,
                     guard,
                     body: expr,
@@ -2517,13 +2519,13 @@ impl<'a> Parser<'a> {
     }
 
     fn mk_range(
-        &self,
+        &mut self,
         start: Option<P<Expr>>,
         end: Option<P<Expr>>,
         limits: RangeLimits,
     ) -> ExprKind {
         if end.is_none() && limits == RangeLimits::Closed {
-            self.error_inclusive_range_with_no_end(self.prev_token.span);
+            self.inclusive_range_with_incorrect_end(self.prev_token.span);
             ExprKind::Err
         } else {
             ExprKind::Range(start, end, limits)
index 54e6ff6272c0594cfca0861a3b827ba3505c1b82..2ce63d011f438b07467fa8726c55e02610e55e90 100644 (file)
@@ -1143,7 +1143,7 @@ impl<'a> Parser<'a> {
                     ident,
                     vis,
                     id: DUMMY_NODE_ID,
-                    attrs: variant_attrs,
+                    attrs: variant_attrs.into(),
                     data: struct_def,
                     disr_expr,
                     span: vlo.to(this.prev_token.span),
@@ -1286,7 +1286,7 @@ impl<'a> Parser<'a> {
                         ident: None,
                         id: DUMMY_NODE_ID,
                         ty,
-                        attrs,
+                        attrs: attrs.into(),
                         is_placeholder: false,
                     },
                     TrailingToken::MaybeComma,
@@ -1460,7 +1460,7 @@ impl<'a> Parser<'a> {
             vis,
             id: DUMMY_NODE_ID,
             ty,
-            attrs,
+            attrs: attrs.into(),
             is_placeholder: false,
         })
     }
@@ -1791,7 +1791,13 @@ impl<'a> Parser<'a> {
                     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 cd9f84db5e55958005bcb3284c00c4fee3f63e89..51d4e007b5984c21c7ec96e72d4740b80587a6e3 100644 (file)
@@ -14,7 +14,7 @@ use crate::lexer::UnmatchedBrace;
 pub use attr_wrapper::AttrWrapper;
 pub use diagnostics::AttemptLocalParseRecovery;
 use diagnostics::Error;
-pub use pat::RecoverComma;
+pub use pat::{RecoverColon, RecoverComma};
 pub use path::PathStyle;
 
 use rustc_ast::ptr::P;
index 30a6b61407f69a06cca09094e715dc028bed125d..313d9db58fc3febec5eb8010f23fd02cdb2f589e 100644 (file)
@@ -5,7 +5,7 @@ use rustc_ast_pretty::pprust;
 use rustc_errors::PResult;
 use rustc_span::symbol::{kw, Ident};
 
-use crate::parser::pat::RecoverComma;
+use crate::parser::pat::{RecoverColon, RecoverComma};
 use crate::parser::{FollowedByType, ForceCollect, Parser, PathStyle};
 
 impl<'a> Parser<'a> {
@@ -125,7 +125,7 @@ impl<'a> Parser<'a> {
                 token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
                     NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None),
                     NonterminalKind::PatWithOr { .. } => {
-                        this.parse_pat_allow_top_alt(None, RecoverComma::No)
+                        this.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No)
                     }
                     _ => unreachable!(),
                 })?)
index 418122202be1b187e9e356ee0f96005ae7d7f328..7219e39ea6ba004dc3379dcc6bba5d82c10207eb 100644 (file)
@@ -24,6 +24,13 @@ pub enum RecoverComma {
     No,
 }
 
+/// Whether or not to recover a `:` when parsing patterns that were meant to be paths.
+#[derive(PartialEq, Copy, Clone)]
+pub enum RecoverColon {
+    Yes,
+    No,
+}
+
 /// The result of `eat_or_separator`. We want to distinguish which case we are in to avoid
 /// emitting duplicate diagnostics.
 #[derive(Debug, Clone, Copy)]
@@ -58,8 +65,9 @@ impl<'a> Parser<'a> {
         &mut self,
         expected: Expected,
         rc: RecoverComma,
+        ra: RecoverColon,
     ) -> PResult<'a, P<Pat>> {
-        self.parse_pat_allow_top_alt_inner(expected, rc).map(|(pat, _)| pat)
+        self.parse_pat_allow_top_alt_inner(expected, rc, ra).map(|(pat, _)| pat)
     }
 
     /// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true =
@@ -68,6 +76,7 @@ impl<'a> Parser<'a> {
         &mut self,
         expected: Expected,
         rc: RecoverComma,
+        ra: RecoverColon,
     ) -> PResult<'a, (P<Pat>, bool)> {
         // Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
         // suggestions (which bothers rustfix).
@@ -89,6 +98,56 @@ impl<'a> Parser<'a> {
             // If we parsed a leading `|` which should be gated,
             // then we should really gate the leading `|`.
             // This complicated procedure is done purely for diagnostics UX.
+            let mut first_pat = first_pat;
+
+            if let (RecoverColon::Yes, token::Colon) = (ra, &self.token.kind) {
+                if matches!(
+                    first_pat.kind,
+                    PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None)
+                        | PatKind::Path(..)
+                ) && self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
+                {
+                    // The pattern looks like it might be a path with a `::` -> `:` typo:
+                    // `match foo { bar:baz => {} }`
+                    let span = self.token.span;
+                    // We only emit "unexpected `:`" error here if we can successfully parse the
+                    // whole pattern correctly in that case.
+                    let snapshot = self.clone();
+
+                    // Create error for "unexpected `:`".
+                    match self.expected_one_of_not_found(&[], &[]) {
+                        Err(mut err) => {
+                            self.bump(); // Skip the `:`.
+                            match self.parse_pat_no_top_alt(expected) {
+                                Err(mut inner_err) => {
+                                    // Carry on as if we had not done anything, callers will emit a
+                                    // reasonable error.
+                                    inner_err.cancel();
+                                    err.cancel();
+                                    *self = snapshot;
+                                }
+                                Ok(pat) => {
+                                    // We've parsed the rest of the pattern.
+                                    err.span_suggestion(
+                                        span,
+                                        "maybe write a path separator here",
+                                        "::".to_string(),
+                                        Applicability::MachineApplicable,
+                                    );
+                                    err.emit();
+                                    first_pat =
+                                        self.mk_pat(first_pat.span.to(pat.span), PatKind::Wild);
+                                }
+                            }
+                        }
+                        _ => {
+                            // Carry on as if we had not done anything. This should be unreachable.
+                            *self = snapshot;
+                        }
+                    };
+                }
+            }
+
             if let Some(leading_vert_span) = leading_vert_span {
                 // If there was a leading vert, treat this as an or-pattern. This improves
                 // diagnostics.
@@ -140,7 +199,8 @@ impl<'a> Parser<'a> {
         // We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level
         // or-patterns so that we can detect when a user tries to use it. This allows us to print a
         // better error message.
-        let (pat, trailing_vert) = self.parse_pat_allow_top_alt_inner(expected, rc)?;
+        let (pat, trailing_vert) =
+            self.parse_pat_allow_top_alt_inner(expected, rc, RecoverColon::No)?;
         let colon = self.eat(&token::Colon);
 
         if let PatKind::Or(pats) = &pat.kind {
@@ -350,7 +410,7 @@ impl<'a> Parser<'a> {
         } else if self.check(&token::OpenDelim(token::Bracket)) {
             // Parse `[pat, pat,...]` as a slice pattern.
             let (pats, _) = self.parse_delim_comma_seq(token::Bracket, |p| {
-                p.parse_pat_allow_top_alt(None, RecoverComma::No)
+                p.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No)
             })?;
             PatKind::Slice(pats)
         } else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) {
@@ -563,8 +623,9 @@ impl<'a> Parser<'a> {
 
     /// Parse a tuple or parenthesis pattern.
     fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> {
-        let (fields, trailing_comma) =
-            self.parse_paren_comma_seq(|p| p.parse_pat_allow_top_alt(None, RecoverComma::No))?;
+        let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| {
+            p.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No)
+        })?;
 
         // Here, `(pat,)` is a tuple pattern.
         // For backward compatibility, `(..)` is a tuple pattern as well.
@@ -715,7 +776,6 @@ impl<'a> Parser<'a> {
         } 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,18 +795,50 @@ impl<'a> Parser<'a> {
             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.
-                self.error_inclusive_range_with_no_end(re.span);
+                self.inclusive_range_with_incorrect_end(re.span);
             }
             None
         };
         Ok(PatKind::Range(Some(begin), end, re))
     }
 
-    pub(super) fn error_inclusive_range_with_no_end(&self, span: Span) {
+    pub(super) fn inclusive_range_with_incorrect_end(&mut self, span: Span) {
+        let tok = &self.token;
+
+        // If the user typed "..==" instead of "..=", we want to give them
+        // a specific error message telling them to use "..=".
+        // Otherwise, we assume that they meant to type a half open exclusive
+        // range and give them an error telling them to do that instead.
+        if matches!(tok.kind, token::Eq) && tok.span.lo() == span.hi() {
+            let span_with_eq = span.to(tok.span);
+
+            // Ensure the user doesn't receive unhelpful unexpected token errors
+            self.bump();
+            if self.is_pat_range_end_start(0) {
+                let _ = self.parse_pat_range_end();
+            }
+
+            self.error_inclusive_range_with_extra_equals(span_with_eq);
+        } else {
+            self.error_inclusive_range_with_no_end(span);
+        }
+    }
+
+    fn error_inclusive_range_with_extra_equals(&self, span: Span) {
+        self.struct_span_err(span, "unexpected `=` after inclusive range")
+            .span_suggestion_short(
+                span,
+                "use `..=` instead",
+                "..=".to_string(),
+                Applicability::MaybeIncorrect,
+            )
+            .note("inclusive ranges end with a single equals sign (`..=`)")
+            .emit();
+    }
+
+    fn error_inclusive_range_with_no_end(&self, span: Span) {
         struct_span_err!(self.sess.span_diagnostic, span, E0586, "inclusive range with no end")
             .span_suggestion_short(
                 span,
@@ -875,8 +967,9 @@ impl<'a> Parser<'a> {
 
     /// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
     fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
-        let (fields, _) =
-            self.parse_paren_comma_seq(|p| p.parse_pat_allow_top_alt(None, RecoverComma::No))?;
+        let (fields, _) = self.parse_paren_comma_seq(|p| {
+            p.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No)
+        })?;
         if qself.is_some() {
             self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
         }
@@ -1035,7 +1128,7 @@ impl<'a> Parser<'a> {
             // Parsing a pattern of the form `fieldname: pat`.
             let fieldname = self.parse_field_name()?;
             self.bump();
-            let pat = self.parse_pat_allow_top_alt(None, RecoverComma::No)?;
+            let pat = self.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No)?;
             hi = pat.span;
             (pat, fieldname, false)
         } else {
index de5a5632600e4ee39a1f6c0dd90d01f92fb5ed46..1fbf01b1b97d55ad5b3e300a2f1498d2fd7c3791 100644 (file)
@@ -393,7 +393,7 @@ impl<'a> Parser<'a> {
         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 @@ impl<'a> Parser<'a> {
 
                 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 4069fb2127e026a7e2c93b63efe05d5bed82018e..c69d4886bd6dd617008645b0c707d953e1a0886f 100644 (file)
@@ -17,6 +17,5 @@ rustc_target = { path = "../rustc_target" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
-rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_lexer = { path = "../rustc_lexer" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
index 9c42a42fe6024c263456a59ab0f4c8ebfd5f7aa6..71231830e99a7afe2b2746264eec5efbf97efc87 100644 (file)
@@ -97,6 +97,10 @@ impl CheckAttrVisitor<'tcx> {
                 | sym::rustc_dirty
                 | sym::rustc_if_this_changed
                 | sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr),
+                sym::cmse_nonsecure_entry => self.check_cmse_nonsecure_entry(attr, span, target),
+                sym::default_method_body_is_const => {
+                    self.check_default_method_body_is_const(attr, span, target)
+                }
                 _ => true,
             };
             // lint-only checks
@@ -234,6 +238,25 @@ impl CheckAttrVisitor<'tcx> {
         }
     }
 
+    /// Checks if `#[cmse_nonsecure_entry]` is applied to a function definition.
+    fn check_cmse_nonsecure_entry(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
+        match target {
+            Target::Fn
+            | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
+            _ => {
+                self.tcx
+                    .sess
+                    .struct_span_err(
+                        attr.span,
+                        "attribute should be applied to a function definition",
+                    )
+                    .span_label(*span, "not a function definition")
+                    .emit();
+                false
+            }
+        }
+    }
+
     /// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid.
     fn check_track_caller(
         &self,
@@ -456,6 +479,8 @@ impl CheckAttrVisitor<'tcx> {
                     _ => None,
                 }
             }
+            // we check the validity of params elsewhere
+            Target::Param => return false,
             _ => None,
         } {
             return err_fn(meta.span(), &format!("isn't allowed on {}", err));
@@ -523,8 +548,11 @@ impl CheckAttrVisitor<'tcx> {
             self.doc_attr_str_error(meta, "keyword");
             return false;
         }
-        match self.tcx.hir().expect_item(hir_id).kind {
-            ItemKind::Mod(ref module) => {
+        match self.tcx.hir().find(hir_id).and_then(|node| match node {
+            hir::Node::Item(item) => Some(&item.kind),
+            _ => None,
+        }) {
+            Some(ItemKind::Mod(ref module)) => {
                 if !module.item_ids.is_empty() {
                     self.tcx
                         .sess
@@ -1193,17 +1221,41 @@ impl CheckAttrVisitor<'tcx> {
         let mut is_transparent = false;
 
         for hint in &hints {
+            if !hint.is_meta_item() {
+                struct_span_err!(
+                    self.tcx.sess,
+                    hint.span(),
+                    E0565,
+                    "meta item in `repr` must be an identifier"
+                )
+                .emit();
+                continue;
+            }
+
             let (article, allowed_targets) = match hint.name_or_empty() {
-                _ if !matches!(target, Target::Struct | Target::Enum | Target::Union) => {
-                    ("a", "struct, enum, or union")
-                }
-                name @ sym::C | name @ sym::align => {
-                    is_c |= name == sym::C;
+                sym::C => {
+                    is_c = true;
                     match target {
                         Target::Struct | Target::Union | Target::Enum => continue,
                         _ => ("a", "struct, enum, or union"),
                     }
                 }
+                sym::align => {
+                    if let (Target::Fn, true) = (target, !self.tcx.features().fn_align) {
+                        feature_err(
+                            &self.tcx.sess.parse_sess,
+                            sym::fn_align,
+                            hint.span(),
+                            "`repr(align)` attributes on functions are unstable",
+                        )
+                        .emit();
+                    }
+
+                    match target {
+                        Target::Struct | Target::Union | Target::Enum | Target::Fn => continue,
+                        _ => ("a", "struct, enum, function, or union"),
+                    }
+                }
                 sym::packed => {
                     if target != Target::Struct && target != Target::Union {
                         ("a", "struct or union")
@@ -1260,7 +1312,17 @@ impl CheckAttrVisitor<'tcx> {
                         continue;
                     }
                 }
-                _ => continue,
+                _ => {
+                    struct_span_err!(
+                        self.tcx.sess,
+                        hint.span(),
+                        E0552,
+                        "unrecognized representation hint"
+                    )
+                    .emit();
+
+                    continue;
+                }
             };
 
             struct_span_err!(
@@ -1406,6 +1468,29 @@ impl CheckAttrVisitor<'tcx> {
             }
         }
     }
+
+    /// default_method_body_is_const should only be applied to trait methods with default bodies.
+    fn check_default_method_body_is_const(
+        &self,
+        attr: &Attribute,
+        span: &Span,
+        target: Target,
+    ) -> bool {
+        match target {
+            Target::Method(MethodKind::Trait { body: true }) => true,
+            _ => {
+                self.tcx
+                    .sess
+                    .struct_span_err(
+                        attr.span,
+                        "attribute should be applied to a trait method with body",
+                    )
+                    .span_label(*span, "not a trait method or missing a body")
+                    .emit();
+                false
+            }
+        }
+    }
 }
 
 impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
index da713566c31211e607e4f63d1af344b231611099..6ee54cfe37f306cbbc9a18cdf1885ae8b7c668dc 100644 (file)
@@ -8,11 +8,13 @@
 //! through, but errors for structured control flow in a `const` should be emitted here.
 
 use rustc_attr as attr;
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_middle::hir::map::Map;
+use rustc_middle::ty;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::feature_err;
@@ -59,12 +61,80 @@ impl NonConstExpr {
 fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     let mut vis = CheckConstVisitor::new(tcx);
     tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis.as_deep_visitor());
+    tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckConstTraitVisitor::new(tcx));
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers { check_mod_const_bodies, ..*providers };
 }
 
+struct CheckConstTraitVisitor<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> CheckConstTraitVisitor<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>) -> Self {
+        CheckConstTraitVisitor { tcx }
+    }
+}
+
+impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor<'tcx> {
+    /// check for const trait impls, and errors if the impl uses provided/default functions
+    /// of the trait being implemented; as those provided functions can be non-const.
+    fn visit_item(&mut self, item: &'hir hir::Item<'hir>) {
+        let _: Option<_> = try {
+            if let hir::ItemKind::Impl(ref imp) = item.kind {
+                if let hir::Constness::Const = imp.constness {
+                    let did = imp.of_trait.as_ref()?.trait_def_id()?;
+                    let mut to_implement = FxHashSet::default();
+
+                    for did in self.tcx.associated_item_def_ids(did) {
+                        if let ty::AssocItem {
+                            kind: ty::AssocKind::Fn, ident, defaultness, ..
+                        } = self.tcx.associated_item(*did)
+                        {
+                            // we can ignore functions that do not have default bodies:
+                            // if those are unimplemented it will be catched by typeck.
+                            if defaultness.has_value()
+                                && !self.tcx.has_attr(*did, sym::default_method_body_is_const)
+                            {
+                                to_implement.insert(ident);
+                            }
+                        }
+                    }
+
+                    for it in imp
+                        .items
+                        .iter()
+                        .filter(|it| matches!(it.kind, hir::AssocItemKind::Fn { .. }))
+                    {
+                        to_implement.remove(&it.ident);
+                    }
+
+                    // all nonconst trait functions (not marked with #[default_method_body_is_const])
+                    // must be implemented
+                    if !to_implement.is_empty() {
+                        self.tcx
+                            .sess
+                            .struct_span_err(
+                                item.span,
+                                "const trait implementations may not use non-const default functions",
+                            )
+                            .note(&format!("`{}` not implemented", to_implement.into_iter().map(|id| id.to_string()).collect::<Vec<_>>().join("`, `")))
+                            .emit();
+                    }
+                }
+            }
+        };
+    }
+
+    fn visit_trait_item(&mut self, _: &'hir hir::TraitItem<'hir>) {}
+
+    fn visit_impl_item(&mut self, _: &'hir hir::ImplItem<'hir>) {}
+
+    fn visit_foreign_item(&mut self, _: &'hir hir::ForeignItem<'hir>) {}
+}
+
 #[derive(Copy, Clone)]
 struct CheckConstVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
index c1b6da97f4dc564d1b056fcbf93db34e90e4bf4f..b71ec700f81c80b77c38f38e7b9037d3838e8a6b 100644 (file)
@@ -151,6 +151,60 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
         }
     }
 
+    #[allow(dead_code)] // FIXME(81658): should be used + lint reinstated after #83171 relands.
+    fn check_for_self_assign(&mut self, assign: &'tcx hir::Expr<'tcx>) {
+        fn check_for_self_assign_helper(
+            tcx: TyCtxt<'tcx>,
+            typeck_results: &'tcx ty::TypeckResults<'tcx>,
+            lhs: &'tcx hir::Expr<'tcx>,
+            rhs: &'tcx hir::Expr<'tcx>,
+        ) -> bool {
+            match (&lhs.kind, &rhs.kind) {
+                (hir::ExprKind::Path(ref qpath_l), hir::ExprKind::Path(ref qpath_r)) => {
+                    if let (Res::Local(id_l), Res::Local(id_r)) = (
+                        typeck_results.qpath_res(qpath_l, lhs.hir_id),
+                        typeck_results.qpath_res(qpath_r, rhs.hir_id),
+                    ) {
+                        if id_l == id_r {
+                            return true;
+                        }
+                    }
+                    return false;
+                }
+                (hir::ExprKind::Field(lhs_l, ident_l), hir::ExprKind::Field(lhs_r, ident_r)) => {
+                    if ident_l == ident_r {
+                        return check_for_self_assign_helper(tcx, typeck_results, lhs_l, lhs_r);
+                    }
+                    return false;
+                }
+                _ => {
+                    return false;
+                }
+            }
+        }
+
+        if let hir::ExprKind::Assign(lhs, rhs, _) = assign.kind {
+            if check_for_self_assign_helper(self.tcx, self.typeck_results(), lhs, rhs)
+                && !assign.span.from_expansion()
+            {
+                let is_field_assign = matches!(lhs.kind, hir::ExprKind::Field(..));
+                self.tcx.struct_span_lint_hir(
+                    lint::builtin::DEAD_CODE,
+                    assign.hir_id,
+                    assign.span,
+                    |lint| {
+                        lint.build(&format!(
+                            "useless assignment of {} of type `{}` to itself",
+                            if is_field_assign { "field" } else { "variable" },
+                            self.typeck_results().expr_ty(lhs),
+                        ))
+                        .emit();
+                    },
+                )
+            }
+        }
+    }
+
     fn handle_field_pattern_match(
         &mut self,
         lhs: &hir::Pat<'_>,
index f345d45d17808b93c49e1f4b76a8942257a1c4e7..ddcc6fc123f7bb7bb28cea10b24b481e7a3f9ebe 100644 (file)
@@ -121,7 +121,7 @@ fn all_diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashMap<Symbol, De
     let mut collector = FxHashMap::default();
 
     // Collect diagnostic items in other crates.
-    for &cnum in tcx.crates().iter().chain(std::iter::once(&LOCAL_CRATE)) {
+    for &cnum in tcx.crates(()).iter().chain(std::iter::once(&LOCAL_CRATE)) {
         for (&name, &def_id) in tcx.diagnostic_items(cnum).iter() {
             collect_item(tcx, &mut collector, name, def_id);
         }
index ca6a7561f3e7743050824efa687a101dd8d521a5..550f4f148fd24abc74d07c4280a6e1ebb044a8a4 100644 (file)
@@ -2,7 +2,7 @@ use rustc_ast::entry::EntryPointType;
 use rustc_errors::struct_span_err;
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, TraitItem, CRATE_HIR_ID};
+use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, Node, TraitItem, CRATE_HIR_ID};
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
@@ -147,19 +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()) {
-        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 {
+        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 Some((def_id, EntryFnType::Main));
+            }
+        }
         no_main_err(tcx, visitor);
         None
     }
@@ -209,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 118fcca4508eacf9af643fde1bd61d0c355b693e..3a88d1932a80a7460e29c18ffca9461ec3d98051 100644 (file)
@@ -257,9 +257,6 @@ impl LanguageItemCollector<'tcx> {
             | LangItem::Unpin
             | LangItem::Termination
             | LangItem::Try
-            | LangItem::Send
-            | LangItem::UnwindSafe
-            | LangItem::RefUnwindSafe
                 => Some(0),
 
             // Not a trait
@@ -309,7 +306,7 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
     let mut collector = LanguageItemCollector::new(tcx);
 
     // Collect lang items in other crates.
-    for &cnum in tcx.crates().iter() {
+    for &cnum in tcx.crates(()).iter() {
         for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() {
             collector.collect_item(item_index, def_id);
         }
index 28633faa205d053a056f9922f295cf0dd60e66bc..cadb8d235806082692de97bf4df7d872dd1e2293 100644 (file)
@@ -10,6 +10,7 @@
 #![feature(iter_zip)]
 #![feature(nll)]
 #![feature(min_specialization)]
+#![feature(try_blocks)]
 #![recursion_limit = "256"]
 
 #[macro_use]
index f41e0e0370680f4b3cafb8eb8c0c5ef2acadd2ee..42a4753c29c9b325b9f0a3585db951f35cff55db 100644 (file)
@@ -20,6 +20,7 @@ use rustc_session::parse::feature_err;
 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 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
         }
 
         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 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, '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 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
                     self.annotate(
                         ctor_hir_id,
                         i.span,
+                        None,
                         AnnotationKind::Required,
                         InheritDeprecation::Yes,
                         InheritConstStability::No,
@@ -395,12 +418,16 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, '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 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, '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 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, '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 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
         self.annotate(
             var.id,
             var.span,
+            None,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -453,6 +494,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
                     v.annotate(
                         ctor_hir_id,
                         var.span,
+                        None,
                         AnnotationKind::Required,
                         InheritDeprecation::Yes,
                         InheritConstStability::No,
@@ -470,6 +512,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
         self.annotate(
             s.hir_id,
             s.span,
+            None,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -484,6 +527,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
         self.annotate(
             i.hir_id(),
             i.span,
+            None,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -498,6 +542,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
         self.annotate(
             md.hir_id(),
             md.span,
+            None,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -517,6 +562,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, '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 @@ impl Visitor<'tcx> for Checker<'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)
     }
@@ -938,7 +986,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     if !remaining_lib_features.is_empty() {
         check_features(&mut remaining_lib_features, &local_defined_features);
 
-        for &cnum in &*tcx.crates() {
+        for &cnum in tcx.crates(()) {
             if remaining_lib_features.is_empty() {
                 break;
             }
@@ -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 de369ba9bbbe2fa016609f25531c14307fd9ded3..629513c7cfec9226819b994066faee42ae57c154 100644 (file)
@@ -53,7 +53,7 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
     }
 
     let mut missing = FxHashSet::default();
-    for &cnum in tcx.crates().iter() {
+    for &cnum in tcx.crates(()).iter() {
         for &item in tcx.missing_lang_items(cnum).iter() {
             missing.insert(item);
         }
index e64f12ef48f22551473317d9900fc0dccd9bc3db..d969f50c1d9185b7f5eb7af1c06e7f3450b3660a 100644 (file)
@@ -156,6 +156,7 @@ where
                 let leaf = leaf.subst(tcx, ct.substs);
                 self.visit_const(leaf)
             }
+            ACNode::Cast(_, _, ty) => self.visit_ty(ty),
             ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => {
                 ControlFlow::CONTINUE
             }
@@ -2030,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 383e30ca29fad713364fb41b13d34873e0d48171..6a1768b92dbbb33c1cf07e7614158dacff8171df 100644 (file)
@@ -12,16 +12,13 @@ measureme = "9.0.0"
 rustc-rayon-core = "0.3.1"
 tracing = "0.1"
 rustc_ast = { path = "../rustc_ast" }
-rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
-rustc_feature = { path = "../rustc_feature" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_query_system = { path = "../rustc_query_system" }
-rustc_span = { path = "../rustc_span" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
-rustc_target = { path = "../rustc_target" }
+rustc_span = { path = "../rustc_span" }
index 27a0dc47682a5532c1b9aff54beae26a1a0c8ca5..0ad360c7d89c37bdccc8997d24460b49f51f00e3 100644 (file)
@@ -3,6 +3,7 @@
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_middle::infer::canonical::Canonical;
 use rustc_middle::mir;
+use rustc_middle::traits;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::subst::{GenericArg, SubstsRef};
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -14,7 +15,7 @@ use rustc_span::{Span, DUMMY_SP};
 pub trait Key {
     /// Given an instance of this key, what crate is it referring to?
     /// This is used to find the provider.
-    fn query_crate(&self) -> CrateNum;
+    fn query_crate_is_local(&self) -> bool;
 
     /// In the event that a cycle occurs, if no explicit span has been
     /// given for a query with key `self`, what span should we use?
@@ -22,8 +23,9 @@ pub trait Key {
 }
 
 impl Key for () {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
@@ -32,8 +34,9 @@ impl Key for () {
 }
 
 impl<'tcx> Key for ty::InstanceDef<'tcx> {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
@@ -42,8 +45,9 @@ impl<'tcx> Key for ty::InstanceDef<'tcx> {
 }
 
 impl<'tcx> Key for ty::Instance<'tcx> {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
@@ -52,8 +56,9 @@ impl<'tcx> Key for ty::Instance<'tcx> {
 }
 
 impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
-    fn query_crate(&self) -> CrateNum {
-        self.instance.query_crate()
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
@@ -62,8 +67,9 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
 }
 
 impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
 
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
@@ -72,8 +78,9 @@ impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
 }
 
 impl Key for CrateNum {
-    fn query_crate(&self) -> CrateNum {
-        *self
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        *self == LOCAL_CRATE
     }
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -81,8 +88,9 @@ impl Key for CrateNum {
 }
 
 impl Key for LocalDefId {
-    fn query_crate(&self) -> CrateNum {
-        self.to_def_id().query_crate()
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.to_def_id().default_span(tcx)
@@ -90,8 +98,9 @@ impl Key for LocalDefId {
 }
 
 impl Key for DefId {
-    fn query_crate(&self) -> CrateNum {
-        self.krate
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        self.krate == LOCAL_CRATE
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(*self)
@@ -99,8 +108,9 @@ impl Key for DefId {
 }
 
 impl Key for ty::WithOptConstParam<LocalDefId> {
-    fn query_crate(&self) -> CrateNum {
-        self.did.query_crate()
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.did.default_span(tcx)
@@ -108,8 +118,9 @@ impl Key for ty::WithOptConstParam<LocalDefId> {
 }
 
 impl Key for (DefId, DefId) {
-    fn query_crate(&self) -> CrateNum {
-        self.0.krate
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        self.0.krate == LOCAL_CRATE
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.1.default_span(tcx)
@@ -117,8 +128,9 @@ impl Key for (DefId, DefId) {
 }
 
 impl Key for (ty::Instance<'tcx>, LocalDefId) {
-    fn query_crate(&self) -> CrateNum {
-        self.0.query_crate()
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.0.default_span(tcx)
@@ -126,8 +138,9 @@ impl Key for (ty::Instance<'tcx>, LocalDefId) {
 }
 
 impl Key for (DefId, LocalDefId) {
-    fn query_crate(&self) -> CrateNum {
-        self.0.krate
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        self.0.krate == LOCAL_CRATE
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.1.default_span(tcx)
@@ -135,8 +148,9 @@ impl Key for (DefId, LocalDefId) {
 }
 
 impl Key for (LocalDefId, DefId) {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.0.default_span(tcx)
@@ -144,8 +158,9 @@ impl Key for (LocalDefId, DefId) {
 }
 
 impl Key for (DefId, Option<Ident>) {
-    fn query_crate(&self) -> CrateNum {
-        self.0.krate
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        self.0.krate == LOCAL_CRATE
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(self.0)
@@ -153,8 +168,9 @@ impl Key for (DefId, Option<Ident>) {
 }
 
 impl Key for (DefId, LocalDefId, Ident) {
-    fn query_crate(&self) -> CrateNum {
-        self.0.krate
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        self.0.krate == LOCAL_CRATE
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.1.default_span(tcx)
@@ -162,8 +178,9 @@ impl Key for (DefId, LocalDefId, Ident) {
 }
 
 impl Key for (CrateNum, DefId) {
-    fn query_crate(&self) -> CrateNum {
-        self.0
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        self.0 == LOCAL_CRATE
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.1.default_span(tcx)
@@ -171,8 +188,9 @@ impl Key for (CrateNum, DefId) {
 }
 
 impl Key for (DefId, SimplifiedType) {
-    fn query_crate(&self) -> CrateNum {
-        self.0.krate
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        self.0.krate == LOCAL_CRATE
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.0.default_span(tcx)
@@ -180,8 +198,9 @@ impl Key for (DefId, SimplifiedType) {
 }
 
 impl<'tcx> Key for SubstsRef<'tcx> {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -189,8 +208,9 @@ impl<'tcx> Key for SubstsRef<'tcx> {
 }
 
 impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
-    fn query_crate(&self) -> CrateNum {
-        self.0.krate
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        self.0.krate == LOCAL_CRATE
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.0.default_span(tcx)
@@ -203,8 +223,9 @@ impl<'tcx> Key
         (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
     )
 {
-    fn query_crate(&self) -> CrateNum {
-        (self.0).0.did.krate
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        (self.0).0.did.krate == LOCAL_CRATE
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         (self.0).0.did.default_span(tcx)
@@ -212,8 +233,9 @@ impl<'tcx> Key
 }
 
 impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.0.default_span(tcx)
@@ -221,8 +243,9 @@ impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
 }
 
 impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
-    fn query_crate(&self) -> CrateNum {
-        self.1.def_id().krate
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        self.1.def_id().krate == LOCAL_CRATE
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(self.1.def_id())
@@ -230,8 +253,9 @@ impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
 }
 
 impl<'tcx> Key for (&'tcx ty::Const<'tcx>, mir::Field) {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -239,8 +263,9 @@ impl<'tcx> Key for (&'tcx ty::Const<'tcx>, mir::Field) {
 }
 
 impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -248,8 +273,9 @@ impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> {
 }
 
 impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
-    fn query_crate(&self) -> CrateNum {
-        self.def_id().krate
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        self.def_id().krate == LOCAL_CRATE
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(self.def_id())
@@ -257,8 +283,9 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
 }
 
 impl<'tcx> Key for GenericArg<'tcx> {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -266,8 +293,9 @@ impl<'tcx> Key for GenericArg<'tcx> {
 }
 
 impl<'tcx> Key for mir::ConstantKind<'tcx> {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -275,8 +303,9 @@ impl<'tcx> Key for mir::ConstantKind<'tcx> {
 }
 
 impl<'tcx> Key for &'tcx ty::Const<'tcx> {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -284,8 +313,9 @@ impl<'tcx> Key for &'tcx ty::Const<'tcx> {
 }
 
 impl<'tcx> Key for Ty<'tcx> {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -293,8 +323,9 @@ impl<'tcx> Key for Ty<'tcx> {
 }
 
 impl<'tcx> Key for &'tcx ty::List<ty::Predicate<'tcx>> {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -302,8 +333,9 @@ impl<'tcx> Key for &'tcx ty::List<ty::Predicate<'tcx>> {
 }
 
 impl<'tcx> Key for ty::ParamEnv<'tcx> {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -311,8 +343,9 @@ impl<'tcx> Key for ty::ParamEnv<'tcx> {
 }
 
 impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
-    fn query_crate(&self) -> CrateNum {
-        self.value.query_crate()
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        self.value.query_crate_is_local()
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.value.default_span(tcx)
@@ -320,8 +353,9 @@ impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
 }
 
 impl Key for Symbol {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -331,8 +365,9 @@ impl Key for Symbol {
 /// Canonical query goals correspond to abstract trait operations that
 /// are not tied to any crate in particular.
 impl<'tcx, T> Key for Canonical<'tcx, T> {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
 
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
@@ -341,8 +376,9 @@ impl<'tcx, T> Key for Canonical<'tcx, T> {
 }
 
 impl Key for (Symbol, u32, u32) {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
 
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
@@ -351,8 +387,20 @@ impl Key for (Symbol, u32, u32) {
 }
 
 impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
+    }
+
+    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
+        DUMMY_SP
+    }
+}
+
+impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
     }
 
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
index 4175fb6925ac4bab1238fdcf3b743bd2a41d1b49..5022bf265328a9a3d16d4f256c991f89dcba2a29 100644 (file)
@@ -1,12 +1,16 @@
 //! Support for serializing the dep-graph and reloading it.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(crate_visibility_modifier)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
 #![feature(min_specialization)]
+#![feature(once_cell)]
 #![feature(rustc_attrs)]
 #![recursion_limit = "256"]
 
+#[macro_use]
+extern crate rustc_macros;
 #[macro_use]
 extern crate rustc_middle;
 #[macro_use]
@@ -14,14 +18,12 @@ extern crate tracing;
 
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_errors::{DiagnosticBuilder, Handler};
-use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_errors::DiagnosticBuilder;
 use rustc_middle::dep_graph;
 use rustc_middle::ich::StableHashingContext;
 use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values};
 use rustc_middle::ty::query::{Providers, QueryEngine};
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_serialize::opaque;
 use rustc_span::Span;
 
 #[macro_use]
@@ -43,7 +45,8 @@ use rustc_query_system::query::QueryAccessors;
 pub use rustc_query_system::query::QueryConfig;
 pub(crate) use rustc_query_system::query::QueryDescription;
 
-use rustc_middle::ty::query::on_disk_cache;
+mod on_disk_cache;
+pub use on_disk_cache::OnDiskCache;
 
 mod profiling_support;
 pub use self::profiling_support::alloc_self_profile_query_strings;
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
new file mode 100644 (file)
index 0000000..b024668
--- /dev/null
@@ -0,0 +1,1195 @@
+use crate::QueryCtxt;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
+use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
+use rustc_data_structures::thin_vec::ThinVec;
+use rustc_data_structures::unhash::UnhashMap;
+use rustc_errors::Diagnostic;
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE};
+use rustc_hir::definitions::DefPathHash;
+use rustc_index::vec::{Idx, IndexVec};
+use rustc_middle::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex};
+use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
+use rustc_middle::mir::{self, interpret};
+use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_query_system::dep_graph::DepContext;
+use rustc_query_system::query::QueryContext;
+use rustc_serialize::{
+    opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize},
+    Decodable, Decoder, Encodable, Encoder,
+};
+use rustc_session::Session;
+use rustc_span::hygiene::{
+    ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData,
+};
+use rustc_span::source_map::{SourceMap, StableSourceFileId};
+use rustc_span::CachingSourceMapView;
+use rustc_span::{BytePos, ExpnData, ExpnHash, SourceFile, Span, DUMMY_SP};
+use std::collections::hash_map::Entry;
+use std::mem;
+
+const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
+
+// A normal span encoded with both location information and a `SyntaxContext`
+const TAG_FULL_SPAN: u8 = 0;
+// A partial span with no location information, encoded only with a `SyntaxContext`
+const TAG_PARTIAL_SPAN: u8 = 1;
+
+const TAG_SYNTAX_CONTEXT: u8 = 0;
+const TAG_EXPN_DATA: u8 = 1;
+
+/// Provides an interface to incremental compilation data cached from the
+/// previous compilation session. This data will eventually include the results
+/// of a few selected queries (like `typeck` and `mir_optimized`) and
+/// any diagnostics that have been emitted during a query.
+pub struct OnDiskCache<'sess> {
+    // The complete cache data in serialized form.
+    serialized_data: Vec<u8>,
+
+    // Collects all `Diagnostic`s emitted during the current compilation
+    // session.
+    current_diagnostics: Lock<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,
+
+    cnum_map: OnceCell<UnhashMap<StableCrateId, CrateNum>>,
+
+    source_map: &'sess SourceMap,
+    file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
+
+    // Caches that are populated lazily during decoding.
+    file_index_to_file: Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
+
+    // A map from dep-node to the position of the cached query result in
+    // `serialized_data`.
+    query_result_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
+
+    // A map from dep-node to the position of any associated diagnostics in
+    // `serialized_data`.
+    prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
+
+    alloc_decoding_state: AllocDecodingState,
+
+    // A map from syntax context ids to the position of their associated
+    // `SyntaxContextData`. We use a `u32` instead of a `SyntaxContext`
+    // to represent the fact that we are storing *encoded* ids. When we decode
+    // a `SyntaxContext`, a new id will be allocated from the global `HygieneData`,
+    // which will almost certainly be different than the serialized id.
+    syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
+    // A map from the `DefPathHash` of an `ExpnId` to the position
+    // of their associated `ExpnData`. Ideally, we would store a `DefId`,
+    // but we need to decode this before we've constructed a `TyCtxt` (which
+    // makes it difficult to decode a `DefId`).
+
+    // Note that these `DefPathHashes` correspond to both local and foreign
+    // `ExpnData` (e.g `ExpnData.krate` may not be `LOCAL_CRATE`). Alternatively,
+    // we could look up the `ExpnData` from the metadata of foreign crates,
+    // but it seemed easier to have `OnDiskCache` be independent of the `CStore`.
+    expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
+    // Additional information used when decoding hygiene data.
+    hygiene_context: HygieneDecodeContext,
+    // Maps `DefPathHash`es to their `RawDefId`s from the *previous*
+    // compilation session. This is used as an initial 'guess' when
+    // we try to map a `DefPathHash` to its `DefId` in the current compilation
+    // session.
+    foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
+    // Likewise for ExpnId.
+    foreign_expn_data: UnhashMap<ExpnHash, u32>,
+
+    // The *next* compilation sessison's `foreign_def_path_hashes` - at
+    // the end of our current compilation session, this will get written
+    // out to the `foreign_def_path_hashes` field of the `Footer`, which
+    // will become `foreign_def_path_hashes` of the next compilation session.
+    // This stores any `DefPathHash` that we may need to map to a `DefId`
+    // during the next compilation session.
+    latest_foreign_def_path_hashes: Lock<UnhashMap<DefPathHash, RawDefId>>,
+
+    // Caches all lookups of `DefPathHashes`, both for local and foreign
+    // definitions. A definition from the previous compilation session
+    // may no longer exist in the current compilation session, so
+    // we use `Option<DefId>` so that we can cache a lookup failure.
+    def_path_hash_to_def_id_cache: Lock<UnhashMap<DefPathHash, Option<DefId>>>,
+}
+
+// This type is used only for serialization and deserialization.
+#[derive(Encodable, Decodable)]
+struct Footer {
+    file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
+    query_result_index: EncodedQueryResultIndex,
+    diagnostics_index: EncodedQueryResultIndex,
+    // The location of all allocations.
+    interpret_alloc_index: Vec<u32>,
+    // See `OnDiskCache.syntax_contexts`
+    syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
+    // See `OnDiskCache.expn_data`
+    expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
+    foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
+    foreign_expn_data: UnhashMap<ExpnHash, u32>,
+}
+
+pub type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
+type EncodedDiagnosticsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
+type EncodedDiagnostics = Vec<Diagnostic>;
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
+struct SourceFileIndex(u32);
+
+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Encodable, Decodable)]
+pub struct AbsoluteBytePos(u32);
+
+impl AbsoluteBytePos {
+    fn new(pos: usize) -> AbsoluteBytePos {
+        debug_assert!(pos <= u32::MAX as usize);
+        AbsoluteBytePos(pos as u32)
+    }
+
+    fn to_usize(self) -> usize {
+        self.0 as usize
+    }
+}
+
+/// Represents a potentially invalid `DefId`. This is used during incremental
+/// compilation to represent a `DefId` from the *previous* compilation session,
+/// which may no longer be valid. This is used to help map a `DefPathHash`
+/// to a `DefId` in the current compilation session.
+#[derive(Encodable, Decodable, Copy, Clone, Debug)]
+crate struct RawDefId {
+    // We deliberately do not use `CrateNum` and `DefIndex`
+    // here, since a crate/index from the previous compilation
+    // session may no longer exist.
+    pub krate: u32,
+    pub index: u32,
+}
+
+/// An `EncodedSourceFileId` is the same as a `StableSourceFileId` except that
+/// the source crate is represented as a [StableCrateId] instead of as a
+/// `CrateNum`. This way `EncodedSourceFileId` can be encoded and decoded
+/// without any additional context, i.e. with a simple `opaque::Decoder` (which
+/// is the only thing available when decoding the cache's [Footer].
+#[derive(Encodable, Decodable, Clone, Debug)]
+struct EncodedSourceFileId {
+    file_name_hash: u64,
+    stable_crate_id: StableCrateId,
+}
+
+impl EncodedSourceFileId {
+    fn translate(&self, cnum_map: &UnhashMap<StableCrateId, CrateNum>) -> StableSourceFileId {
+        let cnum = cnum_map[&self.stable_crate_id];
+        StableSourceFileId { file_name_hash: self.file_name_hash, cnum }
+    }
+
+    fn new(tcx: TyCtxt<'_>, file: &SourceFile) -> EncodedSourceFileId {
+        let source_file_id = StableSourceFileId::new(file);
+        EncodedSourceFileId {
+            file_name_hash: source_file_id.file_name_hash,
+            stable_crate_id: tcx.stable_crate_id(source_file_id.cnum),
+        }
+    }
+}
+
+impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
+    fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> Self {
+        debug_assert!(sess.opts.incremental.is_some());
+
+        // Wrap in a scope so we can borrow `data`.
+        let footer: Footer = {
+            let mut decoder = opaque::Decoder::new(&data[..], start_pos);
+
+            // Decode the *position* of the footer, which can be found in the
+            // last 8 bytes of the file.
+            decoder.set_position(data.len() - IntEncodedWithFixedSize::ENCODED_SIZE);
+            let footer_pos = IntEncodedWithFixedSize::decode(&mut decoder)
+                .expect("error while trying to decode footer position")
+                .0 as usize;
+
+            // Decode the file footer, which contains all the lookup tables, etc.
+            decoder.set_position(footer_pos);
+
+            decode_tagged(&mut decoder, TAG_FILE_FOOTER)
+                .expect("error while trying to decode footer position")
+        };
+
+        Self {
+            serialized_data: data,
+            file_index_to_stable_id: footer.file_index_to_stable_id,
+            file_index_to_file: Default::default(),
+            cnum_map: OnceCell::new(),
+            source_map: sess.source_map(),
+            current_diagnostics: Default::default(),
+            query_result_index: footer.query_result_index.into_iter().collect(),
+            prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(),
+            alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index),
+            syntax_contexts: footer.syntax_contexts,
+            expn_data: footer.expn_data,
+            foreign_expn_data: footer.foreign_expn_data,
+            hygiene_context: Default::default(),
+            foreign_def_path_hashes: footer.foreign_def_path_hashes,
+            latest_foreign_def_path_hashes: Default::default(),
+            def_path_hash_to_def_id_cache: Default::default(),
+        }
+    }
+
+    fn new_empty(source_map: &'sess SourceMap) -> Self {
+        Self {
+            serialized_data: Vec::new(),
+            file_index_to_stable_id: Default::default(),
+            file_index_to_file: Default::default(),
+            cnum_map: OnceCell::new(),
+            source_map,
+            current_diagnostics: Default::default(),
+            query_result_index: Default::default(),
+            prev_diagnostics_index: Default::default(),
+            alloc_decoding_state: AllocDecodingState::new(Vec::new()),
+            syntax_contexts: FxHashMap::default(),
+            expn_data: UnhashMap::default(),
+            foreign_expn_data: UnhashMap::default(),
+            hygiene_context: Default::default(),
+            foreign_def_path_hashes: Default::default(),
+            latest_foreign_def_path_hashes: Default::default(),
+            def_path_hash_to_def_id_cache: Default::default(),
+        }
+    }
+
+    fn serialize(&self, tcx: TyCtxt<'sess>, encoder: &mut FileEncoder) -> FileEncodeResult {
+        // Serializing the `DepGraph` should not modify it.
+        tcx.dep_graph.with_ignore(|| {
+            // Allocate `SourceFileIndex`es.
+            let (file_to_file_index, file_index_to_stable_id) = {
+                let files = tcx.sess.source_map().files();
+                let mut file_to_file_index =
+                    FxHashMap::with_capacity_and_hasher(files.len(), Default::default());
+                let mut file_index_to_stable_id =
+                    FxHashMap::with_capacity_and_hasher(files.len(), Default::default());
+
+                for (index, file) in files.iter().enumerate() {
+                    let index = SourceFileIndex(index as u32);
+                    let file_ptr: *const SourceFile = &**file as *const _;
+                    file_to_file_index.insert(file_ptr, index);
+                    let source_file_id = EncodedSourceFileId::new(tcx, &file);
+                    file_index_to_stable_id.insert(index, source_file_id);
+                }
+
+                (file_to_file_index, file_index_to_stable_id)
+            };
+
+            // Register any dep nodes that we reused from the previous session,
+            // but didn't `DepNode::construct` in this session. This ensures
+            // that their `DefPathHash` to `RawDefId` mappings are registered
+            // in 'latest_foreign_def_path_hashes' if necessary, since that
+            // normally happens in `DepNode::construct`.
+            tcx.dep_graph.register_reused_dep_nodes(tcx);
+
+            // Load everything into memory so we can write it out to the on-disk
+            // cache. The vast majority of cacheable query results should already
+            // be in memory, so this should be a cheap operation.
+            // Do this *before* we clone 'latest_foreign_def_path_hashes', since
+            // loading existing queries may cause us to create new DepNodes, which
+            // may in turn end up invoking `store_foreign_def_id_hash`
+            tcx.dep_graph.exec_cache_promotions(QueryCtxt::from_tcx(tcx));
+
+            let latest_foreign_def_path_hashes = self.latest_foreign_def_path_hashes.lock().clone();
+            let hygiene_encode_context = HygieneEncodeContext::default();
+
+            let mut encoder = CacheEncoder {
+                tcx,
+                encoder,
+                type_shorthands: Default::default(),
+                predicate_shorthands: Default::default(),
+                interpret_allocs: Default::default(),
+                source_map: CachingSourceMapView::new(tcx.sess.source_map()),
+                file_to_file_index,
+                hygiene_context: &hygiene_encode_context,
+                latest_foreign_def_path_hashes,
+            };
+
+            // Encode query results.
+            let mut query_result_index = EncodedQueryResultIndex::new();
+
+            tcx.sess.time("encode_query_results", || -> FileEncodeResult {
+                let enc = &mut encoder;
+                let qri = &mut query_result_index;
+                QueryCtxt::from_tcx(tcx).encode_query_results(enc, qri)
+            })?;
+
+            // Encode diagnostics.
+            let diagnostics_index: EncodedDiagnosticsIndex = self
+                .current_diagnostics
+                .borrow()
+                .iter()
+                .map(
+                    |(dep_node_index, diagnostics)| -> Result<_, <FileEncoder as Encoder>::Error> {
+                        let pos = AbsoluteBytePos::new(encoder.position());
+                        // Let's make sure we get the expected type here.
+                        let diagnostics: &EncodedDiagnostics = diagnostics;
+                        let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
+                        encoder.encode_tagged(dep_node_index, diagnostics)?;
+
+                        Ok((dep_node_index, pos))
+                    },
+                )
+                .collect::<Result<_, _>>()?;
+
+            let interpret_alloc_index = {
+                let mut interpret_alloc_index = Vec::new();
+                let mut n = 0;
+                loop {
+                    let new_n = encoder.interpret_allocs.len();
+                    // If we have found new IDs, serialize those too.
+                    if n == new_n {
+                        // Otherwise, abort.
+                        break;
+                    }
+                    interpret_alloc_index.reserve(new_n - n);
+                    for idx in n..new_n {
+                        let id = encoder.interpret_allocs[idx];
+                        let pos = encoder.position() as u32;
+                        interpret_alloc_index.push(pos);
+                        interpret::specialized_encode_alloc_id(&mut encoder, tcx, id)?;
+                    }
+                    n = new_n;
+                }
+                interpret_alloc_index
+            };
+
+            let mut syntax_contexts = FxHashMap::default();
+            let mut expn_data = UnhashMap::default();
+            let mut foreign_expn_data = UnhashMap::default();
+
+            // Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current
+            // session.
+
+            hygiene_encode_context.encode(
+                &mut encoder,
+                |encoder, index, ctxt_data| -> FileEncodeResult {
+                    let pos = AbsoluteBytePos::new(encoder.position());
+                    encoder.encode_tagged(TAG_SYNTAX_CONTEXT, ctxt_data)?;
+                    syntax_contexts.insert(index, pos);
+                    Ok(())
+                },
+                |encoder, expn_id, data, hash| -> FileEncodeResult {
+                    if expn_id.krate == LOCAL_CRATE {
+                        let pos = AbsoluteBytePos::new(encoder.position());
+                        encoder.encode_tagged(TAG_EXPN_DATA, data)?;
+                        expn_data.insert(hash, pos);
+                    } else {
+                        foreign_expn_data.insert(hash, expn_id.local_id.as_u32());
+                    }
+                    Ok(())
+                },
+            )?;
+
+            let foreign_def_path_hashes =
+                std::mem::take(&mut encoder.latest_foreign_def_path_hashes);
+
+            // `Encode the file footer.
+            let footer_pos = encoder.position() as u64;
+            encoder.encode_tagged(
+                TAG_FILE_FOOTER,
+                &Footer {
+                    file_index_to_stable_id,
+                    query_result_index,
+                    diagnostics_index,
+                    interpret_alloc_index,
+                    syntax_contexts,
+                    expn_data,
+                    foreign_expn_data,
+                    foreign_def_path_hashes,
+                },
+            )?;
+
+            // Encode the position of the footer as the last 8 bytes of the
+            // file so we know where to look for it.
+            IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?;
+
+            // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
+            // of the footer must be the last thing in the data stream.
+
+            Ok(())
+        })
+    }
+
+    fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, hash: DefPathHash) -> Option<DefId> {
+        let mut cache = self.def_path_hash_to_def_id_cache.lock();
+        match cache.entry(hash) {
+            Entry::Occupied(e) => *e.get(),
+            Entry::Vacant(e) => {
+                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_untracked().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);
+                }
+                // This `raw_def_id` represents the `DefId` of this `DefPathHash` in
+                // the *previous* compliation session. The `DefPathHash` includes the
+                // owning crate, so if the corresponding definition still exists in the
+                // current compilation session, the crate is guaranteed to be the same
+                // (otherwise, we would compute a different `DefPathHash`).
+                let raw_def_id = self.get_raw_def_id(&hash)?;
+                debug!("def_path_hash_to_def_id({:?}): raw_def_id = {:?}", hash, raw_def_id);
+                // If the owning crate no longer exists, the corresponding definition definitely
+                // no longer exists.
+                let krate = self.try_remap_cnum(tcx, hash.stable_crate_id())?;
+                debug!("def_path_hash_to_def_id({:?}): krate = {:?}", hash, krate);
+                // If our `DefPathHash` corresponded to a definition in the local crate,
+                // we should have either found it in `local_def_path_hash_to_def_id`, or
+                // never attempted to load it in the first place. Any query result or `DepNode`
+                // that references a local `DefId` should depend on some HIR-related `DepNode`.
+                // If a local definition is removed/modified such that its old `DefPathHash`
+                // no longer has a corresponding definition, that HIR-related `DepNode` should
+                // end up red. This should prevent us from ever calling
+                // `tcx.def_path_hash_to_def_id`, since we'll end up recomputing any
+                // queries involved.
+                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_untracked().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
+            }
+        }
+    }
+
+    fn register_reused_dep_node(&self, tcx: TyCtxt<'sess>, dep_node: &DepNode) {
+        // For reused dep nodes, we only need to store the mapping if the node
+        // is one whose query key we can reconstruct from the hash. We use the
+        // mapping to aid that reconstruction in the next session. While we also
+        // use it to decode `DefId`s we encoded in the cache as `DefPathHashes`,
+        // they're already registered during `DefId` encoding.
+        if dep_node.kind.can_reconstruct_query_key() {
+            let hash = DefPathHash(dep_node.hash.into());
+
+            // We can't simply copy the `RawDefId` from `foreign_def_path_hashes` to
+            // `latest_foreign_def_path_hashes`, since the `RawDefId` might have
+            // changed in the current compilation session (e.g. we've added/removed crates,
+            // or added/removed definitions before/after the target definition).
+            if let Some(def_id) = self.def_path_hash_to_def_id(tcx, hash) {
+                if !def_id.is_local() {
+                    self.store_foreign_def_id_hash(def_id, hash);
+                }
+            }
+        }
+    }
+
+    fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash) {
+        // We may overwrite an existing entry, but it will have the same value,
+        // so it's fine
+        self.latest_foreign_def_path_hashes
+            .lock()
+            .insert(hash, RawDefId { krate: def_id.krate.as_u32(), index: def_id.index.as_u32() });
+    }
+}
+
+impl<'sess> OnDiskCache<'sess> {
+    pub fn as_dyn(&self) -> &dyn rustc_middle::ty::OnDiskCache<'sess> {
+        self as _
+    }
+
+    /// Loads a diagnostic emitted during the previous compilation session.
+    pub fn load_diagnostics(
+        &self,
+        tcx: TyCtxt<'_>,
+        dep_node_index: SerializedDepNodeIndex,
+    ) -> Vec<Diagnostic> {
+        let diagnostics: Option<EncodedDiagnostics> =
+            self.load_indexed(tcx, dep_node_index, &self.prev_diagnostics_index, "diagnostics");
+
+        diagnostics.unwrap_or_default()
+    }
+
+    /// Stores a diagnostic emitted during the current compilation session.
+    /// Anything stored like this will be available via `load_diagnostics` in
+    /// the next compilation session.
+    #[inline(never)]
+    #[cold]
+    pub fn store_diagnostics(
+        &self,
+        dep_node_index: DepNodeIndex,
+        diagnostics: ThinVec<Diagnostic>,
+    ) {
+        let mut current_diagnostics = self.current_diagnostics.borrow_mut();
+        let prev = current_diagnostics.insert(dep_node_index, diagnostics.into());
+        debug_assert!(prev.is_none());
+    }
+
+    fn get_raw_def_id(&self, hash: &DefPathHash) -> Option<RawDefId> {
+        self.foreign_def_path_hashes.get(hash).copied()
+    }
+
+    fn try_remap_cnum(&self, tcx: TyCtxt<'_>, stable_crate_id: StableCrateId) -> Option<CrateNum> {
+        let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx));
+        debug!("try_remap_cnum({:?}): cnum_map={:?}", stable_crate_id, cnum_map);
+
+        cnum_map.get(&stable_crate_id).copied()
+    }
+
+    /// Returns the cached query result if there is something in the cache for
+    /// the given `SerializedDepNodeIndex`; otherwise returns `None`.
+    pub fn try_load_query_result<'tcx, T>(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        dep_node_index: SerializedDepNodeIndex,
+    ) -> Option<T>
+    where
+        T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
+    {
+        self.load_indexed(tcx, dep_node_index, &self.query_result_index, "query result")
+    }
+
+    /// Stores a diagnostic emitted during computation of an anonymous query.
+    /// Since many anonymous queries can share the same `DepNode`, we aggregate
+    /// them -- as opposed to regular queries where we assume that there is a
+    /// 1:1 relationship between query-key and `DepNode`.
+    #[inline(never)]
+    #[cold]
+    pub fn store_diagnostics_for_anon_node(
+        &self,
+        dep_node_index: DepNodeIndex,
+        diagnostics: ThinVec<Diagnostic>,
+    ) {
+        let mut current_diagnostics = self.current_diagnostics.borrow_mut();
+
+        let x = current_diagnostics.entry(dep_node_index).or_default();
+
+        x.extend(Into::<Vec<_>>::into(diagnostics));
+    }
+
+    fn load_indexed<'tcx, T>(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        dep_node_index: SerializedDepNodeIndex,
+        index: &FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
+        debug_tag: &'static str,
+    ) -> Option<T>
+    where
+        T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
+    {
+        let pos = index.get(&dep_node_index).cloned()?;
+
+        self.with_decoder(tcx, pos, |decoder| match decode_tagged(decoder, dep_node_index) {
+            Ok(v) => Some(v),
+            Err(e) => bug!("could not decode cached {}: {}", debug_tag, e),
+        })
+    }
+
+    fn with_decoder<'a, 'tcx, T, F: FnOnce(&mut CacheDecoder<'sess, 'tcx>) -> T>(
+        &'sess self,
+        tcx: TyCtxt<'tcx>,
+        pos: AbsoluteBytePos,
+        f: F,
+    ) -> T
+    where
+        T: Decodable<CacheDecoder<'a, 'tcx>>,
+    {
+        let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx));
+
+        let mut decoder = CacheDecoder {
+            tcx,
+            opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()),
+            source_map: self.source_map,
+            cnum_map,
+            file_index_to_file: &self.file_index_to_file,
+            file_index_to_stable_id: &self.file_index_to_stable_id,
+            alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
+            syntax_contexts: &self.syntax_contexts,
+            expn_data: &self.expn_data,
+            foreign_expn_data: &self.foreign_expn_data,
+            hygiene_context: &self.hygiene_context,
+        };
+        f(&mut decoder)
+    }
+
+    // This function builds mapping from previous-session-`CrateNum` to
+    // current-session-`CrateNum`. There might be `CrateNum`s from the previous
+    // `Session` that don't occur in the current one. For these, the mapping
+    // maps to None.
+    fn compute_cnum_map(tcx: TyCtxt<'_>) -> UnhashMap<StableCrateId, CrateNum> {
+        tcx.dep_graph.with_ignore(|| {
+            tcx.crates(())
+                .iter()
+                .chain(std::iter::once(&LOCAL_CRATE))
+                .map(|&cnum| {
+                    let hash = tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
+                    (hash, cnum)
+                })
+                .collect()
+        })
+    }
+}
+
+//- DECODING -------------------------------------------------------------------
+
+/// A decoder that can read from the incremental compilation cache. It is similar to the one
+/// we use for crate metadata decoding in that it can rebase spans and eventually
+/// will also handle things that contain `Ty` instances.
+pub struct CacheDecoder<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    opaque: opaque::Decoder<'a>,
+    source_map: &'a SourceMap,
+    cnum_map: &'a UnhashMap<StableCrateId, CrateNum>,
+    file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
+    file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>,
+    alloc_decoding_session: AllocDecodingSession<'a>,
+    syntax_contexts: &'a FxHashMap<u32, AbsoluteBytePos>,
+    expn_data: &'a UnhashMap<ExpnHash, AbsoluteBytePos>,
+    foreign_expn_data: &'a UnhashMap<ExpnHash, u32>,
+    hygiene_context: &'a HygieneDecodeContext,
+}
+
+impl<'a, 'tcx> CacheDecoder<'a, 'tcx> {
+    fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc<SourceFile> {
+        let CacheDecoder {
+            ref file_index_to_file,
+            ref file_index_to_stable_id,
+            ref source_map,
+            ref cnum_map,
+            ..
+        } = *self;
+
+        file_index_to_file
+            .borrow_mut()
+            .entry(index)
+            .or_insert_with(|| {
+                let stable_id = file_index_to_stable_id[&index].translate(cnum_map);
+                source_map
+                    .source_file_by_stable_id(stable_id)
+                    .expect("failed to lookup `SourceFile` in new context")
+            })
+            .clone()
+    }
+}
+
+trait DecoderWithPosition: Decoder {
+    fn position(&self) -> usize;
+}
+
+impl<'a> DecoderWithPosition for opaque::Decoder<'a> {
+    fn position(&self) -> usize {
+        self.position()
+    }
+}
+
+impl<'a, 'tcx> DecoderWithPosition for CacheDecoder<'a, 'tcx> {
+    fn position(&self) -> usize {
+        self.opaque.position()
+    }
+}
+
+// Decodes something that was encoded with `encode_tagged()` and verify that the
+// tag matches and the correct amount of bytes was read.
+fn decode_tagged<D, T, V>(decoder: &mut D, expected_tag: T) -> Result<V, D::Error>
+where
+    T: Decodable<D> + Eq + std::fmt::Debug,
+    V: Decodable<D>,
+    D: DecoderWithPosition,
+{
+    let start_pos = decoder.position();
+
+    let actual_tag = T::decode(decoder)?;
+    assert_eq!(actual_tag, expected_tag);
+    let value = V::decode(decoder)?;
+    let end_pos = decoder.position();
+
+    let expected_len: u64 = Decodable::decode(decoder)?;
+    assert_eq!((end_pos - start_pos) as u64, expected_len);
+
+    Ok(value)
+}
+
+impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
+    const CLEAR_CROSS_CRATE: bool = false;
+
+    #[inline]
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    #[inline]
+    fn position(&self) -> usize {
+        self.opaque.position()
+    }
+
+    #[inline]
+    fn peek_byte(&self) -> u8 {
+        self.opaque.data[self.opaque.position()]
+    }
+
+    fn cached_ty_for_shorthand<F>(
+        &mut self,
+        shorthand: usize,
+        or_insert_with: F,
+    ) -> Result<Ty<'tcx>, Self::Error>
+    where
+        F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>,
+    {
+        let tcx = self.tcx();
+
+        let cache_key = ty::CReaderCacheKey { cnum: None, pos: shorthand };
+
+        if let Some(&ty) = tcx.ty_rcache.borrow().get(&cache_key) {
+            return Ok(ty);
+        }
+
+        let ty = or_insert_with(self)?;
+        // This may overwrite the entry, but it should overwrite with the same value.
+        tcx.ty_rcache.borrow_mut().insert_same(cache_key, ty);
+        Ok(ty)
+    }
+
+    fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
+    where
+        F: FnOnce(&mut Self) -> R,
+    {
+        debug_assert!(pos < self.opaque.data.len());
+
+        let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
+        let old_opaque = mem::replace(&mut self.opaque, new_opaque);
+        let r = f(self);
+        self.opaque = old_opaque;
+        r
+    }
+
+    fn decode_alloc_id(&mut self) -> Result<interpret::AllocId, Self::Error> {
+        let alloc_decoding_session = self.alloc_decoding_session;
+        alloc_decoding_session.decode_alloc_id(self)
+    }
+}
+
+rustc_middle::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
+
+// This ensures that the `Decodable<opaque::Decoder>::decode` specialization for `Vec<u8>` is used
+// when a `CacheDecoder` is passed to `Decodable::decode`. Unfortunately, we have to manually opt
+// into specializations this way, given how `CacheDecoder` and the decoding traits currently work.
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Vec<u8> {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        Decodable::decode(&mut d.opaque)
+    }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for SyntaxContext {
+    fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        let syntax_contexts = decoder.syntax_contexts;
+        rustc_span::hygiene::decode_syntax_context(decoder, decoder.hygiene_context, |this, id| {
+            // This closure is invoked if we haven't already decoded the data for the `SyntaxContext` we are deserializing.
+            // We look up the position of the associated `SyntaxData` and decode it.
+            let pos = syntax_contexts.get(&id).unwrap();
+            this.with_position(pos.to_usize(), |decoder| {
+                let data: SyntaxContextData = decode_tagged(decoder, TAG_SYNTAX_CONTEXT)?;
+                Ok(data)
+            })
+        })
+    }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
+    fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        let hash = ExpnHash::decode(decoder)?;
+        if hash.is_root() {
+            return Ok(ExpnId::root());
+        }
+
+        if let Some(expn_id) = ExpnId::from_hash(hash) {
+            return Ok(expn_id);
+        }
+
+        let krate = decoder.cnum_map[&hash.stable_crate_id()];
+
+        let expn_id = if krate == LOCAL_CRATE {
+            // We look up the position of the associated `ExpnData` and decode it.
+            let pos = decoder
+                .expn_data
+                .get(&hash)
+                .unwrap_or_else(|| panic!("Bad hash {:?} (map {:?})", hash, decoder.expn_data));
+
+            let data: ExpnData = decoder
+                .with_position(pos.to_usize(), |decoder| decode_tagged(decoder, TAG_EXPN_DATA))?;
+            rustc_span::hygiene::register_local_expn_id(data, hash)
+        } else {
+            let index_guess = decoder.foreign_expn_data[&hash];
+            decoder.tcx.cstore_untracked().expn_hash_to_expn_id(krate, index_guess, hash)
+        };
+
+        #[cfg(debug_assertions)]
+        {
+            use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+            let mut hcx = decoder.tcx.create_stable_hashing_context();
+            let mut hasher = StableHasher::new();
+            hcx.while_hashing_spans(true, |hcx| expn_id.expn_data().hash_stable(hcx, &mut hasher));
+            let local_hash: u64 = hasher.finish();
+            debug_assert_eq!(hash.local_hash(), local_hash);
+        }
+
+        Ok(expn_id)
+    }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
+    fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        let tag: u8 = Decodable::decode(decoder)?;
+
+        if tag == TAG_PARTIAL_SPAN {
+            let ctxt = SyntaxContext::decode(decoder)?;
+            return Ok(DUMMY_SP.with_ctxt(ctxt));
+        } else {
+            debug_assert_eq!(tag, TAG_FULL_SPAN);
+        }
+
+        let file_lo_index = SourceFileIndex::decode(decoder)?;
+        let line_lo = usize::decode(decoder)?;
+        let col_lo = BytePos::decode(decoder)?;
+        let len = BytePos::decode(decoder)?;
+        let ctxt = SyntaxContext::decode(decoder)?;
+
+        let file_lo = decoder.file_index_to_file(file_lo_index);
+        let lo = file_lo.lines[line_lo - 1] + col_lo;
+        let hi = lo + len;
+
+        Ok(Span::new(lo, hi, ctxt))
+    }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for CrateNum {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        let stable_id = StableCrateId::decode(d)?;
+        let cnum = d.cnum_map[&stable_id];
+        Ok(cnum)
+    }
+}
+
+// This impl makes sure that we get a runtime error when we try decode a
+// `DefIndex` that is not contained in a `DefId`. Such a case would be problematic
+// because we would not know how to transform the `DefIndex` to the current
+// context.
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefIndex {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<DefIndex, String> {
+        Err(d.error("trying to decode `DefIndex` outside the context of a `DefId`"))
+    }
+}
+
+// Both the `CrateNum` and the `DefIndex` of a `DefId` can change in between two
+// compilation sessions. We use the `DefPathHash`, which is stable across
+// sessions, to map the old `DefId` to the new one.
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefId {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        // Load the `DefPathHash` which is was we encoded the `DefId` as.
+        let def_path_hash = DefPathHash::decode(d)?;
+
+        // Using the `DefPathHash`, we can lookup the new `DefId`.
+        // Subtle: We only encode a `DefId` as part of a query result.
+        // If we get to this point, then all of the query inputs were green,
+        // which means that the definition with this hash is guaranteed to
+        // still exist in the current compilation session.
+        Ok(d.tcx()
+            .on_disk_cache
+            .as_ref()
+            .unwrap()
+            .def_path_hash_to_def_id(d.tcx(), def_path_hash)
+            .unwrap())
+    }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx FxHashSet<LocalDefId> {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        RefDecodable::decode(d)
+    }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
+    for &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>>
+{
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        RefDecodable::decode(d)
+    }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        RefDecodable::decode(d)
+    }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        RefDecodable::decode(d)
+    }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [rustc_ast::InlineAsmTemplatePiece] {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        RefDecodable::decode(d)
+    }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [Span] {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        RefDecodable::decode(d)
+    }
+}
+
+//- ENCODING -------------------------------------------------------------------
+
+pub trait OpaqueEncoder: Encoder {
+    fn position(&self) -> usize;
+}
+
+impl OpaqueEncoder for FileEncoder {
+    #[inline]
+    fn position(&self) -> usize {
+        FileEncoder::position(self)
+    }
+}
+
+/// An encoder that can write to the incremental compilation cache.
+pub struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> {
+    tcx: TyCtxt<'tcx>,
+    encoder: &'a mut E,
+    type_shorthands: FxHashMap<Ty<'tcx>, usize>,
+    predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
+    interpret_allocs: FxIndexSet<interpret::AllocId>,
+    source_map: CachingSourceMapView<'tcx>,
+    file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>,
+    hygiene_context: &'a HygieneEncodeContext,
+    latest_foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
+}
+
+impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E>
+where
+    E: 'a + OpaqueEncoder,
+{
+    fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex {
+        self.file_to_file_index[&(&*source_file as *const SourceFile)]
+    }
+
+    /// Encode something with additional information that allows to do some
+    /// sanity checks when decoding the data again. This method will first
+    /// encode the specified tag, then the given value, then the number of
+    /// bytes taken up by tag and value. On decoding, we can then verify that
+    /// we get the expected tag and read the expected number of bytes.
+    fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(
+        &mut self,
+        tag: T,
+        value: &V,
+    ) -> Result<(), E::Error> {
+        let start_pos = self.position();
+
+        tag.encode(self)?;
+        value.encode(self)?;
+
+        let end_pos = self.position();
+        ((end_pos - start_pos) as u64).encode(self)
+    }
+}
+
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for SyntaxContext
+where
+    E: 'a + OpaqueEncoder,
+{
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+        rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_context, s)
+    }
+}
+
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for ExpnId
+where
+    E: 'a + OpaqueEncoder,
+{
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+        s.hygiene_context.schedule_expn_data_for_encoding(*self);
+        self.expn_hash().encode(s)
+    }
+}
+
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for Span
+where
+    E: 'a + OpaqueEncoder,
+{
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+        let span_data = self.data();
+        if self.is_dummy() {
+            TAG_PARTIAL_SPAN.encode(s)?;
+            return span_data.ctxt.encode(s);
+        }
+
+        let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo);
+        let partial_span = match &pos {
+            Some((file_lo, _, _)) => !file_lo.contains(span_data.hi),
+            None => true,
+        };
+
+        if partial_span {
+            TAG_PARTIAL_SPAN.encode(s)?;
+            return span_data.ctxt.encode(s);
+        }
+
+        let (file_lo, line_lo, col_lo) = pos.unwrap();
+
+        let len = span_data.hi - span_data.lo;
+
+        let source_file_index = s.source_file_index(file_lo);
+
+        TAG_FULL_SPAN.encode(s)?;
+        source_file_index.encode(s)?;
+        line_lo.encode(s)?;
+        col_lo.encode(s)?;
+        len.encode(s)?;
+        span_data.ctxt.encode(s)
+    }
+}
+
+impl<'a, 'tcx, E> TyEncoder<'tcx> for CacheEncoder<'a, 'tcx, E>
+where
+    E: 'a + OpaqueEncoder,
+{
+    const CLEAR_CROSS_CRATE: bool = false;
+
+    fn position(&self) -> usize {
+        self.encoder.position()
+    }
+    fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
+        &mut self.type_shorthands
+    }
+    fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
+        &mut self.predicate_shorthands
+    }
+    fn encode_alloc_id(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
+        let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
+
+        index.encode(self)
+    }
+}
+
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for CrateNum
+where
+    E: 'a + OpaqueEncoder,
+{
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+        s.tcx.stable_crate_id(*self).encode(s)
+    }
+}
+
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefId
+where
+    E: 'a + OpaqueEncoder,
+{
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+        let def_path_hash = s.tcx.def_path_hash(*self);
+        // Store additional information when we encode a foreign `DefId`,
+        // so that we can map its `DefPathHash` back to a `DefId` in the next
+        // compilation session.
+        if !self.is_local() {
+            s.latest_foreign_def_path_hashes.insert(
+                def_path_hash,
+                RawDefId { krate: self.krate.as_u32(), index: self.index.as_u32() },
+            );
+        }
+        def_path_hash.encode(s)
+    }
+}
+
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefIndex
+where
+    E: 'a + OpaqueEncoder,
+{
+    fn encode(&self, _: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+        bug!("encoding `DefIndex` without context");
+    }
+}
+
+macro_rules! encoder_methods {
+    ($($name:ident($ty:ty);)*) => {
+        #[inline]
+        $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
+            self.encoder.$name(value)
+        })*
+    }
+}
+
+impl<'a, 'tcx, E> Encoder for CacheEncoder<'a, 'tcx, E>
+where
+    E: 'a + OpaqueEncoder,
+{
+    type Error = E::Error;
+
+    #[inline]
+    fn emit_unit(&mut self) -> Result<(), Self::Error> {
+        Ok(())
+    }
+
+    encoder_methods! {
+        emit_usize(usize);
+        emit_u128(u128);
+        emit_u64(u64);
+        emit_u32(u32);
+        emit_u16(u16);
+        emit_u8(u8);
+
+        emit_isize(isize);
+        emit_i128(i128);
+        emit_i64(i64);
+        emit_i32(i32);
+        emit_i16(i16);
+        emit_i8(i8);
+
+        emit_bool(bool);
+        emit_f64(f64);
+        emit_f32(f32);
+        emit_char(char);
+        emit_str(&str);
+        emit_raw_bytes(&[u8]);
+    }
+}
+
+// This ensures that the `Encodable<opaque::FileEncoder>::encode` specialization for byte slices
+// is used when a `CacheEncoder` having an `opaque::FileEncoder` is passed to `Encodable::encode`.
+// Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder`
+// and the encoding traits currently work.
+impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx, FileEncoder>> for [u8] {
+    fn encode(&self, e: &mut CacheEncoder<'a, 'tcx, FileEncoder>) -> FileEncodeResult {
+        self.encode(e.encoder)
+    }
+}
+
+pub fn encode_query_results<'a, 'tcx, CTX, Q>(
+    tcx: CTX,
+    encoder: &mut CacheEncoder<'a, 'tcx, FileEncoder>,
+    query_result_index: &mut EncodedQueryResultIndex,
+) -> FileEncodeResult
+where
+    CTX: QueryContext + 'tcx,
+    Q: super::QueryDescription<CTX> + super::QueryAccessors<CTX>,
+    Q::Value: Encodable<CacheEncoder<'a, 'tcx, FileEncoder>>,
+{
+    let _timer = tcx
+        .dep_context()
+        .profiler()
+        .extra_verbose_generic_activity("encode_query_results_for", std::any::type_name::<Q>());
+
+    assert!(Q::query_state(tcx).all_inactive());
+    let cache = Q::query_cache(tcx);
+    let mut res = Ok(());
+    cache.iter_results(&mut |key, value, dep_node| {
+        if res.is_err() {
+            return;
+        }
+        if Q::cache_on_disk(tcx, &key, Some(value)) {
+            let dep_node = SerializedDepNodeIndex::new(dep_node.index());
+
+            // Record position of the cache entry.
+            query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.encoder.position())));
+
+            // Encode the type check tables with the `SerializedDepNodeIndex`
+            // as tag.
+            match encoder.encode_tagged(dep_node, value) {
+                Ok(()) => {}
+                Err(e) => {
+                    res = Err(e);
+                }
+            }
+        }
+    });
+
+    res
+}
index b4191c135b4f9b425a3052b92a7b1fac7c5d8637..58c1b57dbb949fac2a7aecb6915e7bc16268c424 100644 (file)
@@ -2,9 +2,8 @@
 //! generate the actual methods on tcx which find and execute the provider,
 //! manage the caches, and so forth.
 
-use super::queries;
+use crate::{on_disk_cache, queries, Queries};
 use rustc_middle::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex};
-use rustc_middle::ty::query::on_disk_cache;
 use rustc_middle::ty::tls::{self, ImplicitCtxt};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_query_system::dep_graph::HasDepContext;
@@ -12,14 +11,16 @@ use rustc_query_system::query::{QueryContext, QueryDescription, QueryJobId, Quer
 
 use rustc_data_structures::sync::Lock;
 use rustc_data_structures::thin_vec::ThinVec;
-use rustc_errors::Diagnostic;
+use rustc_errors::{Diagnostic, Handler};
 use rustc_serialize::opaque;
 use rustc_span::def_id::LocalDefId;
 
+use std::any::Any;
+
 #[derive(Copy, Clone)]
 pub struct QueryCtxt<'tcx> {
     pub tcx: TyCtxt<'tcx>,
-    pub queries: &'tcx super::Queries<'tcx>,
+    pub queries: &'tcx Queries<'tcx>,
 }
 
 impl<'tcx> std::ops::Deref for QueryCtxt<'tcx> {
@@ -83,14 +84,15 @@ impl QueryContext for QueryCtxt<'tcx> {
 
     // Interactions with on_disk_cache
     fn load_diagnostics(&self, prev_dep_node_index: SerializedDepNodeIndex) -> Vec<Diagnostic> {
-        self.on_disk_cache
+        self.queries
+            .on_disk_cache
             .as_ref()
             .map(|c| c.load_diagnostics(**self, prev_dep_node_index))
             .unwrap_or_default()
     }
 
     fn store_diagnostics(&self, dep_node_index: DepNodeIndex, diagnostics: ThinVec<Diagnostic>) {
-        if let Some(c) = self.on_disk_cache.as_ref() {
+        if let Some(c) = self.queries.on_disk_cache.as_ref() {
             c.store_diagnostics(dep_node_index, diagnostics)
         }
     }
@@ -100,7 +102,7 @@ impl QueryContext for QueryCtxt<'tcx> {
         dep_node_index: DepNodeIndex,
         diagnostics: ThinVec<Diagnostic>,
     ) {
-        if let Some(c) = self.on_disk_cache.as_ref() {
+        if let Some(c) = self.queries.on_disk_cache.as_ref() {
             c.store_diagnostics_for_anon_node(dep_node_index, diagnostics)
         }
     }
@@ -137,6 +139,27 @@ impl QueryContext for QueryCtxt<'tcx> {
 }
 
 impl<'tcx> QueryCtxt<'tcx> {
+    #[inline]
+    pub fn from_tcx(tcx: TyCtxt<'tcx>) -> Self {
+        let queries = tcx.queries.as_any();
+        let queries = unsafe {
+            let queries = std::mem::transmute::<&dyn Any, &dyn Any>(queries);
+            let queries = queries.downcast_ref().unwrap();
+            let queries = std::mem::transmute::<&Queries<'_>, &Queries<'_>>(queries);
+            queries
+        };
+        QueryCtxt { tcx, queries }
+    }
+
+    crate fn on_disk_cache(self) -> Option<&'tcx on_disk_cache::OnDiskCache<'tcx>> {
+        self.queries.on_disk_cache.as_ref()
+    }
+
+    #[cfg(parallel_compiler)]
+    pub unsafe fn deadlock(self, registry: &rustc_rayon_core::Registry) {
+        rustc_query_system::query::deadlock(self, registry)
+    }
+
     pub(super) fn encode_query_results(
         self,
         encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>,
@@ -158,6 +181,15 @@ impl<'tcx> QueryCtxt<'tcx> {
 
         Ok(())
     }
+
+    pub fn try_print_query_stack(
+        self,
+        query: Option<QueryJobId<DepKind>>,
+        handler: &Handler,
+        num_frames: Option<usize>,
+    ) -> usize {
+        rustc_query_system::query::print_query_stack(self, query, handler, num_frames)
+    }
 }
 
 /// This struct stores metadata about each Query.
@@ -353,14 +385,14 @@ macro_rules! define_queries {
             }
 
             #[inline]
-            fn compute(tcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
-                let is_local = key.query_crate() == LOCAL_CRATE;
-                let provider = if is_local {
+            fn compute_fn(tcx: QueryCtxt<'tcx>, key: &Self::Key) ->
+                fn(TyCtxt<'tcx>, Self::Key) -> Self::Value
+            {
+                if key.query_crate_is_local() {
                     tcx.queries.local_providers.$name
                 } else {
                     tcx.queries.extern_providers.$name
-                };
-                provider(*tcx, key)
+                }
             }
 
             fn hash_result(
@@ -462,6 +494,8 @@ macro_rules! define_queries_struct {
             local_providers: Box<Providers>,
             extern_providers: Box<Providers>,
 
+            pub on_disk_cache: Option<OnDiskCache<$tcx>>,
+
             $($(#[$attr])*  $name: QueryState<
                 crate::dep_graph::DepKind,
                 query_keys::$name<$tcx>,
@@ -472,10 +506,12 @@ macro_rules! define_queries_struct {
             pub fn new(
                 local_providers: Providers,
                 extern_providers: Providers,
+                on_disk_cache: Option<OnDiskCache<$tcx>>,
             ) -> Self {
                 Queries {
                     local_providers: Box::new(local_providers),
                     extern_providers: Box::new(extern_providers),
+                    on_disk_cache,
                     $($name: Default::default()),*
                 }
             }
@@ -501,25 +537,9 @@ macro_rules! define_queries_struct {
         }
 
         impl QueryEngine<'tcx> for Queries<'tcx> {
-            #[cfg(parallel_compiler)]
-            unsafe fn deadlock(&'tcx self, tcx: TyCtxt<'tcx>, registry: &rustc_rayon_core::Registry) {
-                let tcx = QueryCtxt { tcx, queries: self };
-                rustc_query_system::query::deadlock(tcx, registry)
-            }
-
-            fn encode_query_results(
-                &'tcx self,
-                tcx: TyCtxt<'tcx>,
-                encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>,
-                query_result_index: &mut on_disk_cache::EncodedQueryResultIndex,
-            ) -> opaque::FileEncodeResult {
-                let tcx = QueryCtxt { tcx, queries: self };
-                tcx.encode_query_results(encoder, query_result_index)
-            }
-
-            fn exec_cache_promotions(&'tcx self, tcx: TyCtxt<'tcx>) {
-                let tcx = QueryCtxt { tcx, queries: self };
-                tcx.dep_graph.exec_cache_promotions(tcx)
+            fn as_any(&'tcx self) -> &'tcx dyn std::any::Any {
+                let this = unsafe { std::mem::transmute::<&Queries<'_>, &Queries<'_>>(self) };
+                this as _
             }
 
             fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool {
@@ -527,17 +547,6 @@ macro_rules! define_queries_struct {
                 tcx.dep_graph.try_mark_green(qcx, dep_node).is_some()
             }
 
-            fn try_print_query_stack(
-                &'tcx self,
-                tcx: TyCtxt<'tcx>,
-                query: Option<QueryJobId<dep_graph::DepKind>>,
-                handler: &Handler,
-                num_frames: Option<usize>,
-            ) -> usize {
-                let qcx = QueryCtxt { tcx, queries: self };
-                rustc_query_system::query::print_query_stack(qcx, query, handler, num_frames)
-            }
-
             $($(#[$attr])*
             #[inline(always)]
             fn $name(
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 71e67dfee538bdee7f553a687eb03e3aed6e8e72..c8a46e974f305e4f6f900746953e2859118c95b1 100644 (file)
@@ -1,7 +1,6 @@
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::profiling::QueryInvocationId;
-use rustc_data_structures::profiling::SelfProfilerRef;
+use rustc_data_structures::profiling::{EventId, QueryInvocationId, SelfProfilerRef};
 use rustc_data_structures::sharded::{self, Sharded};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
@@ -36,6 +35,12 @@ pub struct DepGraph<K: DepKind> {
     /// each task has a `DepNodeIndex` that uniquely identifies it. This unique
     /// ID is used for self-profiling.
     virtual_dep_node_index: Lrc<AtomicU32>,
+
+    /// The cached event id for profiling node interning. This saves us
+    /// from having to look up the event id every time we intern a node
+    /// which may incur too much overhead.
+    /// This will be None if self-profiling is disabled.
+    node_intern_event_id: Option<EventId>,
 }
 
 rustc_index::newtype_index! {
@@ -130,6 +135,10 @@ impl<K: DepKind> DepGraph<K> {
         );
         debug_assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE);
 
+        let node_intern_event_id = profiler
+            .get_or_alloc_cached_string("incr_comp_intern_dep_graph_node")
+            .map(EventId::from_label);
+
         DepGraph {
             data: Some(Lrc::new(DepGraphData {
                 previous_work_products: prev_work_products,
@@ -141,11 +150,16 @@ impl<K: DepKind> DepGraph<K> {
                 colors: DepNodeColorMap::new(prev_graph_node_count),
             })),
             virtual_dep_node_index: Lrc::new(AtomicU32::new(0)),
+            node_intern_event_id,
         }
     }
 
     pub fn new_disabled() -> DepGraph<K> {
-        DepGraph { data: None, virtual_dep_node_index: Lrc::new(AtomicU32::new(0)) }
+        DepGraph {
+            data: None,
+            virtual_dep_node_index: Lrc::new(AtomicU32::new(0)),
+            node_intern_event_id: None,
+        }
     }
 
     /// Returns `true` if we are actually building the full dep-graph, and `false` otherwise.
@@ -244,10 +258,15 @@ impl<K: DepKind> DepGraph<K> {
             let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads);
 
             let mut hcx = dcx.create_stable_hashing_context();
+            let hashing_timer = dcx.profiler().incr_result_hashing();
             let current_fingerprint = hash_result(&mut hcx, &result);
 
             let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks;
 
+            // Get timer for profiling `DepNode` interning
+            let node_intern_timer = self
+                .node_intern_event_id
+                .map(|eid| dcx.profiler().generic_activity_with_event_id(eid));
             // Intern the new `DepNode`.
             let (dep_node_index, prev_and_color) = data.current.intern_node(
                 dcx.profiler(),
@@ -257,6 +276,9 @@ impl<K: DepKind> DepGraph<K> {
                 current_fingerprint,
                 print_status,
             );
+            drop(node_intern_timer);
+
+            hashing_timer.finish_with_query_invocation_id(dep_node_index.into());
 
             if let Some((prev_index, color)) = prev_and_color {
                 debug_assert!(
index f2a6b6df4b9de3f75208a6eb5dadc5fa39a77363..d1e527dff9840e6b5fa0ab314c93083a34d36a4b 100644 (file)
@@ -23,9 +23,6 @@ pub(crate) struct QueryVtable<CTX: QueryContext, K, V> {
     pub dep_kind: CTX::DepKind,
     pub eval_always: bool,
 
-    // Don't use this method to compute query results, instead use the methods on TyCtxt
-    pub compute: fn(CTX, K) -> V,
-
     pub hash_result: fn(&mut CTX::StableHashingContext, &V) -> Option<Fingerprint>,
     pub handle_cycle_error: fn(CTX, DiagnosticBuilder<'_>) -> V,
     pub cache_on_disk: fn(CTX, &K, Option<&V>) -> bool,
@@ -40,10 +37,6 @@ impl<CTX: QueryContext, K, V> QueryVtable<CTX, K, V> {
         DepNode::construct(tcx, self.dep_kind, key)
     }
 
-    pub(crate) fn compute(&self, tcx: CTX, key: K) -> V {
-        (self.compute)(tcx, key)
-    }
-
     pub(crate) fn hash_result(
         &self,
         hcx: &mut CTX::StableHashingContext,
@@ -79,7 +72,7 @@ pub trait QueryAccessors<CTX: QueryContext>: QueryConfig {
         CTX: 'a;
 
     // Don't use this method to compute query results, instead use the methods on TyCtxt
-    fn compute(tcx: CTX, key: Self::Key) -> Self::Value;
+    fn compute_fn(tcx: CTX, key: &Self::Key) -> fn(CTX::DepContext, Self::Key) -> Self::Value;
 
     fn hash_result(
         hcx: &mut CTX::StableHashingContext,
@@ -115,7 +108,6 @@ where
         anon: Q::ANON,
         dep_kind: Q::DEP_KIND,
         eval_always: Q::EVAL_ALWAYS,
-        compute: Q::compute,
         hash_result: Q::hash_result,
         handle_cycle_error: Q::handle_cycle_error,
         cache_on_disk: Q::cache_on_disk,
index c1f9fa39e98c5cf183abc8e66fce2f6b5004c98d..c227c2aaff549164f2101449b12dac782666132e 100644 (file)
@@ -428,6 +428,7 @@ fn try_execute_query<CTX, C>(
     key: C::Key,
     lookup: QueryLookup,
     query: &QueryVtable<CTX, C::Key, C::Value>,
+    compute: fn(CTX::DepContext, C::Key) -> C::Value,
 ) -> C::Stored
 where
     C: QueryCache,
@@ -457,7 +458,7 @@ where
     // Fast path for when incr. comp. is off.
     if !dep_graph.is_fully_enabled() {
         let prof_timer = tcx.dep_context().profiler().query_provider();
-        let result = tcx.start_query(job.id, None, || query.compute(tcx, key));
+        let result = tcx.start_query(job.id, None, || compute(*tcx.dep_context(), key));
         let dep_node_index = dep_graph.next_virtual_depnode_index();
         prof_timer.finish_with_query_invocation_id(dep_node_index.into());
         return job.complete(result, dep_node_index);
@@ -468,8 +469,9 @@ where
 
         let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
             tcx.start_query(job.id, diagnostics, || {
-                dep_graph
-                    .with_anon_task(*tcx.dep_context(), query.dep_kind, || query.compute(tcx, key))
+                dep_graph.with_anon_task(*tcx.dep_context(), query.dep_kind, || {
+                    compute(*tcx.dep_context(), key)
+                })
             })
         });
 
@@ -501,6 +503,7 @@ where
                         dep_node_index,
                         &dep_node,
                         query,
+                        compute,
                     ),
                     dep_node_index,
                 )
@@ -511,7 +514,7 @@ where
         }
     }
 
-    let (result, dep_node_index) = force_query_with_job(tcx, key, job, dep_node, query);
+    let (result, dep_node_index) = force_query_with_job(tcx, key, job, dep_node, query, compute);
     dep_graph.read_index(dep_node_index);
     result
 }
@@ -523,6 +526,7 @@ fn load_from_disk_and_cache_in_memory<CTX, K, V: Debug>(
     dep_node_index: DepNodeIndex,
     dep_node: &DepNode<CTX::DepKind>,
     query: &QueryVtable<CTX, K, V>,
+    compute: fn(CTX::DepContext, K) -> V,
 ) -> V
 where
     CTX: QueryContext,
@@ -565,7 +569,7 @@ where
         let prof_timer = tcx.dep_context().profiler().query_provider();
 
         // The dep-graph for this computation is already in-place.
-        let result = tcx.dep_context().dep_graph().with_ignore(|| query.compute(tcx, key));
+        let result = tcx.dep_context().dep_graph().with_ignore(|| compute(*tcx.dep_context(), key));
 
         prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
@@ -627,6 +631,7 @@ fn force_query_with_job<C, CTX>(
     job: JobOwner<'_, CTX::DepKind, C>,
     dep_node: DepNode<CTX::DepKind>,
     query: &QueryVtable<CTX, C::Key, C::Value>,
+    compute: fn(CTX::DepContext, C::Key) -> C::Value,
 ) -> (C::Stored, DepNodeIndex)
 where
     C: QueryCache,
@@ -653,17 +658,17 @@ where
             if query.eval_always {
                 tcx.dep_context().dep_graph().with_eval_always_task(
                     dep_node,
-                    tcx,
+                    *tcx.dep_context(),
                     key,
-                    query.compute,
+                    compute,
                     query.hash_result,
                 )
             } else {
                 tcx.dep_context().dep_graph().with_task(
                     dep_node,
-                    tcx,
+                    *tcx.dep_context(),
                     key,
-                    query.compute,
+                    compute,
                     query.hash_result,
                 )
             }
@@ -690,13 +695,14 @@ fn get_query_impl<CTX, C>(
     key: C::Key,
     lookup: QueryLookup,
     query: &QueryVtable<CTX, C::Key, C::Value>,
+    compute: fn(CTX::DepContext, C::Key) -> C::Value,
 ) -> C::Stored
 where
     CTX: QueryContext,
     C: QueryCache,
     C::Key: DepNodeParams<CTX::DepContext>,
 {
-    try_execute_query(tcx, state, cache, span, key, lookup, query)
+    try_execute_query(tcx, state, cache, span, key, lookup, query, compute)
 }
 
 /// Ensure that either this query has all green inputs or been executed.
@@ -744,8 +750,10 @@ fn force_query_impl<CTX, C>(
     tcx: CTX,
     state: &QueryState<CTX::DepKind, C::Key>,
     cache: &QueryCacheStore<C>,
+    key: C::Key,
     dep_node: DepNode<CTX::DepKind>,
     query: &QueryVtable<CTX, C::Key, C::Value>,
+    compute: fn(CTX::DepContext, C::Key) -> C::Value,
 ) -> bool
 where
     C: QueryCache,
@@ -754,18 +762,6 @@ where
 {
     debug_assert!(!query.anon);
 
-    if !<C::Key as DepNodeParams<CTX::DepContext>>::can_reconstruct_query_key() {
-        return false;
-    }
-
-    let key = if let Some(key) =
-        <C::Key as DepNodeParams<CTX::DepContext>>::recover(*tcx.dep_context(), &dep_node)
-    {
-        key
-    } else {
-        return false;
-    };
-
     // We may be concurrently trying both execute and force a query.
     // Ensure that only one of them runs the query.
     let cached = cache.cache.lookup(cache, &key, |_, index| {
@@ -798,7 +794,7 @@ where
         TryGetJob::JobCompleted(_) => return true,
     };
 
-    force_query_with_job(tcx, key, job, dep_node, query);
+    force_query_with_job(tcx, key, job, dep_node, query, compute);
 
     true
 }
@@ -828,8 +824,17 @@ where
     }
 
     debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span);
-    let value =
-        get_query_impl(tcx, Q::query_state(tcx), Q::query_cache(tcx), span, key, lookup, query);
+    let compute = Q::compute_fn(tcx, &key);
+    let value = get_query_impl(
+        tcx,
+        Q::query_state(tcx),
+        Q::query_cache(tcx),
+        span,
+        key,
+        lookup,
+        query,
+        compute,
+    );
     Some(value)
 }
 
@@ -843,5 +848,26 @@ where
         return false;
     }
 
-    force_query_impl(tcx, Q::query_state(tcx), Q::query_cache(tcx), *dep_node, &Q::VTABLE)
+    if !<Q::Key as DepNodeParams<CTX::DepContext>>::can_reconstruct_query_key() {
+        return false;
+    }
+
+    let key = if let Some(key) =
+        <Q::Key as DepNodeParams<CTX::DepContext>>::recover(*tcx.dep_context(), &dep_node)
+    {
+        key
+    } else {
+        return false;
+    };
+
+    let compute = Q::compute_fn(tcx, &key);
+    force_query_impl(
+        tcx,
+        Q::query_state(tcx),
+        Q::query_cache(tcx),
+        key,
+        *dep_node,
+        &Q::VTABLE,
+        compute,
+    )
 }
index e10314a11fc1bbacd6e83a378f10aecc774fb686..178d727418d7426405a2ac8b24b09bf310ec931d 100644 (file)
@@ -31,7 +31,7 @@ use rustc_middle::bug;
 use rustc_middle::hir::exports::Export;
 use rustc_middle::middle::cstore::CrateStore;
 use rustc_middle::ty;
-use rustc_span::hygiene::{ExpnId, MacroKind};
+use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
@@ -42,7 +42,7 @@ use tracing::debug;
 
 type Res = def::Res<NodeId>;
 
-impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, ExpnId) {
+impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, LocalExpnId) {
     fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
         arenas.alloc_name_binding(NameBinding {
             kind: NameBindingKind::Module(self.0),
@@ -54,7 +54,7 @@ impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, ExpnId) {
     }
 }
 
-impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId) {
+impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, LocalExpnId) {
     fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
         arenas.alloc_name_binding(NameBinding {
             kind: NameBindingKind::Res(self.0, false),
@@ -68,7 +68,7 @@ impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId) {
 
 struct IsMacroExport;
 
-impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId, IsMacroExport) {
+impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, LocalExpnId, IsMacroExport) {
     fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
         arenas.alloc_name_binding(NameBinding {
             kind: NameBindingKind::Res(self.0, true),
@@ -128,7 +128,7 @@ impl<'a> Resolver<'a> {
 
         let (name, parent) = if def_id.index == CRATE_DEF_INDEX {
             // This is the crate root
-            (self.cstore().crate_name_untracked(def_id.krate), None)
+            (self.cstore().crate_name(def_id.krate), None)
         } else {
             let def_key = self.cstore().def_key(def_id);
             let name = def_key
@@ -157,8 +157,17 @@ impl<'a> Resolver<'a> {
     crate fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
         let def_id = match expn_id.expn_data().macro_def_id {
             Some(def_id) => def_id,
-            None => return self.ast_transform_scopes.get(&expn_id).unwrap_or(&self.graph_root),
+            None => {
+                return expn_id
+                    .as_local()
+                    .and_then(|expn_id| 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 {
@@ -735,7 +744,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 if ptr::eq(parent, self.r.graph_root) {
                     if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0())
                     {
-                        if expansion != ExpnId::root()
+                        if expansion != LocalExpnId::ROOT
                             && orig_name.is_some()
                             && entry.extern_crate_item.is_none()
                         {
@@ -765,7 +774,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                     no_implicit_prelude: parent.no_implicit_prelude || {
                         self.r.session.contains_name(&item.attrs, sym::no_implicit_prelude)
                     },
-                    ..ModuleData::new(Some(parent), module_kind, def_id, expansion, item.span)
+                    ..ModuleData::new(
+                        Some(parent),
+                        module_kind,
+                        def_id,
+                        expansion.to_expn_id(),
+                        item.span,
+                    )
                 });
                 self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
                 self.r.module_map.insert(local_def_id, module);
@@ -804,7 +819,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                     parent,
                     module_kind,
                     parent.nearest_parent_mod,
-                    expansion,
+                    expansion.to_expn_id(),
                     item.span,
                 );
                 self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
@@ -879,7 +894,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                     parent,
                     module_kind,
                     parent.nearest_parent_mod,
-                    expansion,
+                    expansion.to_expn_id(),
                     item.span,
                 );
                 self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
@@ -922,7 +937,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 parent,
                 ModuleKind::Block(block.id),
                 parent.nearest_parent_mod,
-                expansion,
+                expansion.to_expn_id(),
                 block.span,
             );
             self.r.block_map.insert(block.id, module);
@@ -942,7 +957,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                     parent,
                     ModuleKind::Def(kind, def_id, ident.name),
                     def_id,
-                    expansion,
+                    expansion.to_expn_id(),
                     span,
                 );
                 self.r.define(parent, ident, TypeNS, (module, vis, span, expansion));
@@ -1108,7 +1123,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             })
         };
 
-        let allow_shadowing = self.parent_scope.expansion == ExpnId::root();
+        let allow_shadowing = self.parent_scope.expansion == LocalExpnId::ROOT;
         if let Some(span) = import_all {
             let import = macro_use_import(self, span);
             self.r.potentially_unused_imports.push(import);
@@ -1171,7 +1186,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         false
     }
 
-    fn visit_invoc(&mut self, id: NodeId) -> ExpnId {
+    fn visit_invoc(&mut self, id: NodeId) -> LocalExpnId {
         let invoc_id = id.placeholder_to_expn_id();
         let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope);
         assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation");
index 17f0c39e39735d89f961b27ec1df9c7003a0c346..6f4f1bdaea1b7a97929bea82a63ad24c867f4637 100644 (file)
@@ -6,7 +6,7 @@ use rustc_ast_lowering::ResolverAstLowering;
 use rustc_expand::expand::AstFragment;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::definitions::*;
-use rustc_span::hygiene::ExpnId;
+use rustc_span::hygiene::LocalExpnId;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
 use tracing::debug;
@@ -14,7 +14,7 @@ use tracing::debug;
 crate fn collect_definitions(
     resolver: &mut Resolver<'_>,
     fragment: &AstFragment,
-    expansion: ExpnId,
+    expansion: LocalExpnId,
 ) {
     let (parent_def, impl_trait_context) = resolver.invocation_parents[&expansion];
     fragment.visit_with(&mut DefCollector { resolver, parent_def, expansion, impl_trait_context });
@@ -25,14 +25,14 @@ struct DefCollector<'a, 'b> {
     resolver: &'a mut Resolver<'b>,
     parent_def: LocalDefId,
     impl_trait_context: ImplTraitContext,
-    expansion: ExpnId,
+    expansion: LocalExpnId,
 }
 
 impl<'a, 'b> DefCollector<'a, 'b> {
     fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> LocalDefId {
         let parent_def = self.parent_def;
         debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
-        self.resolver.create_def(parent_def, node_id, data, self.expansion, span)
+        self.resolver.create_def(parent_def, node_id, data, self.expansion.to_expn_id(), span)
     }
 
     fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
@@ -285,7 +285,7 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
                         item_def,
                         node_id,
                         DefPathData::ImplTrait,
-                        self.expansion,
+                        self.expansion.to_expn_id(),
                         ty.span,
                     ),
                     ImplTraitContext::Existential => {
index 03d94f43897ba19fcd472316db990b0b0ec34f7b..7439cd9a0fe3dc50b99b8c4aca5ded24161db04a 100644 (file)
@@ -502,14 +502,14 @@ impl<'a> Resolver<'a> {
 
                 err
             }
-            ResolutionError::SelfInTyParamDefault => {
+            ResolutionError::SelfInGenericParamDefault => {
                 let mut err = struct_span_err!(
                     self.session,
                     span,
                     E0735,
-                    "type parameters cannot use `Self` in their defaults"
+                    "generic parameters cannot use `Self` in their defaults"
                 );
-                err.span_label(span, "`Self` in type parameter default".to_string());
+                err.span_label(span, "`Self` in generic parameter default".to_string());
                 err
             }
             ResolutionError::UnreachableLabel { name, definition_span, suggestion } => {
index 26858915f45a03978a409830d2eca01b6b2ac174..acfa389fed58abc32f6398d76b1121e642a9cc86 100644 (file)
@@ -22,7 +22,7 @@ use rustc_middle::span_bug;
 use rustc_middle::ty;
 use rustc_session::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS};
 use rustc_session::lint::BuiltinLintDiagnostics;
-use rustc_span::hygiene::ExpnId;
+use rustc_span::hygiene::LocalExpnId;
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{MultiSpan, Span};
@@ -237,8 +237,9 @@ impl<'a> Resolver<'a> {
                 if ns == TypeNS {
                     if ident.name == kw::Crate || ident.name == kw::DollarCrate {
                         let module = self.resolve_crate_root(ident);
-                        let binding = (module, ty::Visibility::Public, module.span, ExpnId::root())
-                            .to_name_binding(self.arenas);
+                        let binding =
+                            (module, ty::Visibility::Public, module.span, LocalExpnId::ROOT)
+                                .to_name_binding(self.arenas);
                         return Ok(binding);
                     } else if ident.name == kw::Super || ident.name == kw::SelfLower {
                         // FIXME: Implement these with renaming requirements so that e.g.
@@ -265,7 +266,7 @@ impl<'a> Resolver<'a> {
             self.resolution(module, key).try_borrow_mut().map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports.
 
         if let Some(binding) = resolution.binding {
-            if !restricted_shadowing && binding.expansion != ExpnId::root() {
+            if !restricted_shadowing && binding.expansion != LocalExpnId::ROOT {
                 if let NameBindingKind::Res(_, true) = binding.kind {
                     self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
                 }
@@ -307,7 +308,7 @@ impl<'a> Resolver<'a> {
                         if let Some(shadowed_glob) = resolution.shadowed_glob {
                             // Forbid expanded shadowing to avoid time travel.
                             if restricted_shadowing
-                                && binding.expansion != ExpnId::root()
+                                && binding.expansion != LocalExpnId::ROOT
                                 && binding.res() != shadowed_glob.res()
                             {
                                 self.ambiguity_errors.push(AmbiguityError {
@@ -521,7 +522,7 @@ impl<'a> Resolver<'a> {
                             if old_glob { (old_binding, binding) } else { (binding, old_binding) };
                         if glob_binding.res() != nonglob_binding.res()
                             && key.ns == MacroNS
-                            && nonglob_binding.expansion != ExpnId::root()
+                            && nonglob_binding.expansion != LocalExpnId::ROOT
                         {
                             resolution.binding = Some(this.ambiguity(
                                 AmbiguityKind::GlobVsExpanded,
@@ -1271,7 +1272,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
         target: Ident,
     ) {
         // Skip if the import was produced by a macro.
-        if import.parent_scope.expansion != ExpnId::root() {
+        if import.parent_scope.expansion != LocalExpnId::ROOT {
             return;
         }
 
index 03b578d4adeec235d60aa34654cfbdc1962c2845..76979ab50b9e6654b2778b47428670a034e2f522 100644 (file)
@@ -1962,6 +1962,8 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                                 hir::GenericParamKind::Type {
                                     synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
                                     ..
+                                } | hir::GenericParamKind::Lifetime {
+                                    kind: hir::LifetimeParamKind::Elided
                                 }
                             )
                         }) {
index 6d5531d330783257109c0fa696522b0f5a7360dc..7114fd33188d972c1fa035deb83b16ed50084987 100644 (file)
@@ -11,7 +11,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(box_patterns)]
 #![feature(bool_to_option)]
-#![feature(control_flow_enum)]
 #![feature(crate_visibility_modifier)]
 #![feature(format_args_capture)]
 #![feature(iter_zip)]
@@ -40,7 +39,7 @@ use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind};
 use rustc_hir::def::Namespace::*;
 use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefPathHash, LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
 use rustc_hir::TraitCandidate;
 use rustc_index::vec::IndexVec;
@@ -54,8 +53,8 @@ use rustc_session::lint;
 use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::Session;
 use rustc_span::edition::Edition;
-use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency};
-use rustc_span::source_map::Spanned;
+use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext, Transparency};
+use rustc_span::source_map::{CachingSourceMapView, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 
@@ -104,7 +103,7 @@ impl Determinacy {
 /// but not for late resolution yet.
 #[derive(Clone, Copy)]
 enum Scope<'a> {
-    DeriveHelpers(ExpnId),
+    DeriveHelpers(LocalExpnId),
     DeriveHelpersCompat,
     MacroRules(MacroRulesScopeRef<'a>),
     CrateRoot,
@@ -144,7 +143,7 @@ enum ScopeSet<'a> {
 #[derive(Clone, Copy, Debug)]
 pub struct ParentScope<'a> {
     module: Module<'a>,
-    expansion: ExpnId,
+    expansion: LocalExpnId,
     macro_rules: MacroRulesScopeRef<'a>,
     derives: &'a [ast::Path],
 }
@@ -155,7 +154,7 @@ impl<'a> ParentScope<'a> {
     pub fn module(module: Module<'a>, resolver: &Resolver<'a>) -> ParentScope<'a> {
         ParentScope {
             module,
-            expansion: ExpnId::root(),
+            expansion: LocalExpnId::ROOT,
             macro_rules: resolver.arenas.alloc_macro_rules_scope(MacroRulesScope::Empty),
             derives: &[],
         }
@@ -250,7 +249,7 @@ enum ResolutionError<'a> {
     /// This error is only emitted when using `min_const_generics`.
     ParamInNonTrivialAnonConst { name: Symbol, is_type: bool },
     /// Error E0735: generic parameters with a default cannot use `Self`
-    SelfInTyParamDefault,
+    SelfInGenericParamDefault,
     /// Error E0767: use of unreachable label
     UnreachableLabel { name: Symbol, definition_span: Span, suggestion: Option<LabelSuggestion> },
 }
@@ -336,15 +335,15 @@ impl UsePlacementFinder {
                     if self.span.map_or(true, |span| item.span < span)
                         && !item.span.from_expansion()
                     {
+                        self.span = Some(item.span.shrink_to_lo());
                         // don't insert between attributes and an item
-                        if item.attrs.is_empty() {
-                            self.span = Some(item.span.shrink_to_lo());
-                        } else {
-                            // find the first attribute on the item
-                            for attr in &item.attrs {
-                                if self.span.map_or(true, |span| attr.span < span) {
-                                    self.span = Some(attr.span.shrink_to_lo());
-                                }
+                        // find the first attribute on the item
+                        // FIXME: This is broken for active attributes.
+                        for attr in &item.attrs {
+                            if !attr.span.is_dummy()
+                                && self.span.map_or(true, |span| attr.span < span)
+                            {
+                                self.span = Some(attr.span.shrink_to_lo());
                             }
                         }
                     }
@@ -516,7 +515,7 @@ pub struct ModuleData<'a> {
     populate_on_access: Cell<bool>,
 
     /// Macro invocations that can expand into items in this module.
-    unexpanded_invocations: RefCell<FxHashSet<ExpnId>>,
+    unexpanded_invocations: RefCell<FxHashSet<LocalExpnId>>,
 
     /// Whether `#[no_implicit_prelude]` is active.
     no_implicit_prelude: bool,
@@ -646,7 +645,7 @@ impl<'a> fmt::Debug for ModuleData<'a> {
 pub struct NameBinding<'a> {
     kind: NameBindingKind<'a>,
     ambiguity: Option<(&'a NameBinding<'a>, AmbiguityKind)>,
-    expansion: ExpnId,
+    expansion: LocalExpnId,
     span: Span,
     vis: ty::Visibility,
 }
@@ -830,7 +829,11 @@ impl<'a> NameBinding<'a> {
     // in some later round and screw up our previously found resolution.
     // See more detailed explanation in
     // https://github.com/rust-lang/rust/pull/53778#issuecomment-419224049
-    fn may_appear_after(&self, invoc_parent_expansion: ExpnId, binding: &NameBinding<'_>) -> bool {
+    fn may_appear_after(
+        &self,
+        invoc_parent_expansion: LocalExpnId,
+        binding: &NameBinding<'_>,
+    ) -> bool {
         // self > max(invoc, binding) => !(self <= invoc || self <= binding)
         // Expansions are partially ordered, so "may appear after" is an inversion of
         // "certainly appears before or simultaneously" and includes unordered cases.
@@ -967,7 +970,7 @@ pub struct Resolver<'a> {
     dummy_ext_derive: Lrc<SyntaxExtension>,
     non_macro_attrs: [Lrc<SyntaxExtension>; 2],
     local_macro_def_scopes: FxHashMap<LocalDefId, Module<'a>>,
-    ast_transform_scopes: FxHashMap<ExpnId, Module<'a>>,
+    ast_transform_scopes: FxHashMap<LocalExpnId, Module<'a>>,
     unused_macros: FxHashMap<LocalDefId, (NodeId, Span)>,
     proc_macro_stubs: FxHashSet<LocalDefId>,
     /// Traces collected during macro resolution and validated when it's complete.
@@ -979,18 +982,18 @@ pub struct Resolver<'a> {
     /// `derive(Copy)` marks items they are applied to so they are treated specially later.
     /// Derive macros cannot modify the item themselves and have to store the markers in the global
     /// context, so they attach the markers to derive container IDs using this resolver table.
-    containers_deriving_copy: FxHashSet<ExpnId>,
+    containers_deriving_copy: FxHashSet<LocalExpnId>,
     /// Parent scopes in which the macros were invoked.
     /// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere.
-    invocation_parent_scopes: FxHashMap<ExpnId, ParentScope<'a>>,
+    invocation_parent_scopes: FxHashMap<LocalExpnId, ParentScope<'a>>,
     /// `macro_rules` scopes *produced* by expanding the macro invocations,
     /// include all the `macro_rules` items and other invocations generated by them.
-    output_macro_rules_scopes: FxHashMap<ExpnId, MacroRulesScopeRef<'a>>,
+    output_macro_rules_scopes: FxHashMap<LocalExpnId, MacroRulesScopeRef<'a>>,
     /// Helper attributes that are in scope for the given expansion.
-    helper_attrs: FxHashMap<ExpnId, Vec<Ident>>,
+    helper_attrs: FxHashMap<LocalExpnId, Vec<Ident>>,
     /// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute
     /// with the given `ExpnId`.
-    derive_data: FxHashMap<ExpnId, DeriveData>,
+    derive_data: FxHashMap<LocalExpnId, DeriveData>,
 
     /// Avoid duplicated errors for "name already defined".
     name_already_seen: FxHashMap<Symbol, Span>,
@@ -1019,7 +1022,7 @@ pub struct Resolver<'a> {
     /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId`
     /// we know what parent node that fragment should be attached to thanks to this table,
     /// and how the `impl Trait` fragments were introduced.
-    invocation_parents: FxHashMap<ExpnId, (LocalDefId, ImplTraitContext)>,
+    invocation_parents: FxHashMap<LocalExpnId, (LocalDefId, ImplTraitContext)>,
 
     next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>,
     /// Some way to know that we are in a *trait* impl in `visit_assoc_item`.
@@ -1150,6 +1153,13 @@ impl ResolverAstLowering for Resolver<'_> {
         self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node))
     }
 
+    fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
+        match def_id.as_local() {
+            Some(def_id) => self.definitions.def_path_hash(def_id),
+            None => self.cstore().def_path_hash(def_id),
+        }
+    }
+
     /// Adds a definition with a parent definition.
     fn create_def(
         &mut self,
@@ -1193,6 +1203,32 @@ impl ResolverAstLowering for Resolver<'_> {
     }
 }
 
+struct ExpandHasher<'a, 'b> {
+    source_map: CachingSourceMapView<'a>,
+    resolver: &'a Resolver<'b>,
+}
+
+impl<'a, 'b> rustc_span::HashStableContext for ExpandHasher<'a, 'b> {
+    #[inline]
+    fn hash_spans(&self) -> bool {
+        true
+    }
+
+    #[inline]
+    fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
+        self.resolver.def_path_hash(def_id)
+    }
+
+    #[inline]
+    fn span_data_to_lines_and_cols(
+        &mut self,
+        span: &rustc_span::SpanData,
+    ) -> Option<(Lrc<rustc_span::SourceFile>, usize, rustc_span::BytePos, usize, rustc_span::BytePos)>
+    {
+        self.source_map.span_data_to_lines_and_cols(span)
+    }
+}
+
 impl<'a> Resolver<'a> {
     pub fn new(
         session: &'a Session,
@@ -1222,7 +1258,7 @@ impl<'a> Resolver<'a> {
         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();
@@ -1236,7 +1272,7 @@ impl<'a> Resolver<'a> {
         node_id_to_def_id.insert(CRATE_NODE_ID, root);
 
         let mut invocation_parents = FxHashMap::default();
-        invocation_parents.insert(ExpnId::root(), (root, ImplTraitContext::Existential));
+        invocation_parents.insert(LocalExpnId::ROOT, (root, ImplTraitContext::Existential));
 
         let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = session
             .opts
@@ -1310,7 +1346,7 @@ impl<'a> Resolver<'a> {
             dummy_binding: arenas.alloc_name_binding(NameBinding {
                 kind: NameBindingKind::Res(Res::Err, false),
                 ambiguity: None,
-                expansion: ExpnId::root(),
+                expansion: LocalExpnId::ROOT,
                 span: DUMMY_SP,
                 vis: ty::Visibility::Public,
             }),
@@ -1360,11 +1396,18 @@ impl<'a> Resolver<'a> {
         };
 
         let root_parent_scope = ParentScope::module(graph_root, &resolver);
-        resolver.invocation_parent_scopes.insert(ExpnId::root(), root_parent_scope);
+        resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope);
 
         resolver
     }
 
+    fn create_stable_hashing_context(&self) -> ExpandHasher<'_, 'a> {
+        ExpandHasher {
+            source_map: CachingSourceMapView::new(self.session.source_map()),
+            resolver: self,
+        }
+    }
+
     pub fn next_node_id(&mut self) -> NodeId {
         let next = self
             .next_node_id
@@ -1771,20 +1814,18 @@ impl<'a> Resolver<'a> {
             }
 
             scope = match scope {
-                Scope::DeriveHelpers(expn_id) if expn_id != ExpnId::root() => {
+                Scope::DeriveHelpers(LocalExpnId::ROOT) => Scope::DeriveHelpersCompat,
+                Scope::DeriveHelpers(expn_id) => {
                     // Derive helpers are not visible to code generated by bang or derive macros.
                     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,
-                        _ => Scope::DeriveHelpers(expn_data.parent),
+                        | ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => {
+                            Scope::DeriveHelpersCompat
+                        }
+                        _ => Scope::DeriveHelpers(expn_data.parent.expect_local()),
                     }
                 }
-                Scope::DeriveHelpers(..) => Scope::DeriveHelpersCompat,
                 Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.macro_rules),
                 Scope::MacroRules(macro_rules_scope) => match macro_rules_scope.get() {
                     MacroRulesScope::Binding(binding) => {
@@ -2606,7 +2647,7 @@ impl<'a> Resolver<'a> {
         if let ForwardGenericParamBanRibKind = all_ribs[rib_index].kind {
             if record_used {
                 let res_error = if rib_ident.name == kw::SelfUpper {
-                    ResolutionError::SelfInTyParamDefault
+                    ResolutionError::SelfInGenericParamDefault
                 } else {
                     ResolutionError::ForwardDeclaredGenericParam
                 };
@@ -3211,7 +3252,7 @@ impl<'a> Resolver<'a> {
                 };
                 let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
                 Some(
-                    (crate_root, ty::Visibility::Public, DUMMY_SP, ExpnId::root())
+                    (crate_root, ty::Visibility::Public, DUMMY_SP, LocalExpnId::ROOT)
                         .to_name_binding(self.arenas),
                 )
             }
index 3f7db2b6962fa51bb50122e238e00c5d18795160..b2a8aa0ceccaaee3770dcad0259166f37ba7ad3f 100644 (file)
@@ -20,7 +20,7 @@ use rustc_expand::compile_declarative_macro;
 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;
@@ -30,7 +30,7 @@ use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
 use rustc_span::edition::Edition;
-use rustc_span::hygiene::{self, ExpnData, ExpnId, ExpnKind};
+use rustc_span::hygiene::{self, ExpnData, ExpnKind, LocalExpnId};
 use rustc_span::hygiene::{AstPass, MacroKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -62,7 +62,7 @@ pub enum MacroRulesScope<'a> {
     Binding(&'a MacroRulesBinding<'a>),
     /// The scope introduced by a macro invocation that can potentially
     /// create a `macro_rules!` macro definition.
-    Invocation(ExpnId),
+    Invocation(LocalExpnId),
 }
 
 /// `macro_rules!` scopes are always kept by reference and inside a cell.
@@ -190,7 +190,11 @@ impl<'a> ResolverExpand for Resolver<'a> {
         });
     }
 
-    fn visit_ast_fragment_with_placeholders(&mut self, expansion: ExpnId, fragment: &AstFragment) {
+    fn visit_ast_fragment_with_placeholders(
+        &mut self,
+        expansion: LocalExpnId,
+        fragment: &AstFragment,
+    ) {
         // Integrate the new AST fragment into all the definition and module structures.
         // We are inside the `expansion` now, but other parent scope components are still the same.
         let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] };
@@ -216,27 +220,24 @@ impl<'a> ResolverExpand for Resolver<'a> {
         pass: AstPass,
         features: &[Symbol],
         parent_module_id: Option<NodeId>,
-    ) -> ExpnId {
-        let expn_id = ExpnId::fresh(Some(ExpnData::allow_unstable(
-            ExpnKind::AstPass(pass),
-            call_site,
-            self.session.edition(),
-            features.into(),
-            None,
-        )));
-
-        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
-        };
+    ) -> LocalExpnId {
+        let parent_module = parent_module_id.map(|module_id| self.local_def_id(module_id));
+        let expn_id = LocalExpnId::fresh(
+            ExpnData::allow_unstable(
+                ExpnKind::AstPass(pass),
+                call_site,
+                self.session.edition(),
+                features.into(),
+                None,
+                parent_module.map(LocalDefId::to_def_id),
+            ),
+            self.create_stable_hashing_context(),
+        );
+
+        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
     }
 
@@ -247,7 +248,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
     fn resolve_macro_invocation(
         &mut self,
         invoc: &Invocation,
-        eager_expansion_root: ExpnId,
+        eager_expansion_root: LocalExpnId,
         force: bool,
     ) -> Result<Lrc<SyntaxExtension>, Indeterminate> {
         let invoc_id = invoc.expansion_data.id;
@@ -280,7 +281,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
         // Derives are not included when `invocations` are collected, so we have to add them here.
         let parent_scope = &ParentScope { derives, ..parent_scope };
         let supports_macro_expansion = invoc.fragment_kind.supports_macro_expansion();
-        let node_id = self.lint_node_id(eager_expansion_root);
+        let node_id = invoc.expansion_data.lint_node_id;
         let (ext, res) = self.smart_resolve_macro_path(
             path,
             kind,
@@ -293,17 +294,20 @@ impl<'a> ResolverExpand for Resolver<'a> {
         )?;
 
         let span = invoc.span();
-        invoc_id.set_expn_data(ext.expn_data(
-            parent_scope.expansion,
-            span,
-            fast_print_path(path),
-            res.opt_def_id(),
-        ));
+        invoc_id.set_expn_data(
+            ext.expn_data(
+                parent_scope.expansion,
+                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
+                }),
+            ),
+            self.create_stable_hashing_context(),
+        );
 
         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,14 +329,10 @@ impl<'a> ResolverExpand for Resolver<'a> {
                         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,
+                            _ => expn_id = expn_data.parent.expect_local(),
                         }
                     }
                 }
@@ -348,21 +348,13 @@ impl<'a> ResolverExpand for Resolver<'a> {
         }
     }
 
-    fn lint_node_id(&self, expn_id: ExpnId) -> NodeId {
-        // FIXME - make this more precise. This currently returns the NodeId of the
-        // nearest closing item - we should try to return the closest parent of the ExpnId
-        self.invocation_parents
-            .get(&expn_id)
-            .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0])
-    }
-
-    fn has_derive_copy(&self, expn_id: ExpnId) -> bool {
+    fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool {
         self.containers_deriving_copy.contains(&expn_id)
     }
 
     fn resolve_derives(
         &mut self,
-        expn_id: ExpnId,
+        expn_id: LocalExpnId,
         force: bool,
         derive_paths: &dyn Fn() -> DeriveResolutions,
     ) -> Result<(), Indeterminate> {
@@ -380,7 +372,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
             has_derive_copy: false,
         });
         let parent_scope = self.invocation_parent_scopes[&expn_id];
-        for (i, (path, opt_ext)) in entry.resolutions.iter_mut().enumerate() {
+        for (i, (path, _, opt_ext)) in entry.resolutions.iter_mut().enumerate() {
             if opt_ext.is_none() {
                 *opt_ext = Some(
                     match self.resolve_macro_path(
@@ -427,7 +419,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
         Ok(())
     }
 
-    fn take_derive_resolutions(&mut self, expn_id: ExpnId) -> Option<DeriveResolutions> {
+    fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option<DeriveResolutions> {
         self.derive_data.remove(&expn_id).map(|data| data.resolutions)
     }
 
@@ -435,7 +427,11 @@ impl<'a> ResolverExpand for Resolver<'a> {
     // Returns true if the path can certainly be resolved in one of three namespaces,
     // returns false if the path certainly cannot be resolved in any of the three namespaces.
     // Returns `Indeterminate` if we cannot give a certain answer yet.
-    fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate> {
+    fn cfg_accessible(
+        &mut self,
+        expn_id: LocalExpnId,
+        path: &ast::Path,
+    ) -> Result<bool, Indeterminate> {
         let span = path.span;
         let path = &Segment::from_path(path);
         let parent_scope = self.invocation_parent_scopes[&expn_id];
@@ -718,7 +714,8 @@ impl<'a> Resolver<'a> {
                 let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt));
                 let ok = |res, span, arenas| {
                     Ok((
-                        (res, ty::Visibility::Public, span, ExpnId::root()).to_name_binding(arenas),
+                        (res, ty::Visibility::Public, span, LocalExpnId::ROOT)
+                            .to_name_binding(arenas),
                         Flags::empty(),
                     ))
                 };
@@ -1100,9 +1097,13 @@ impl<'a> Resolver<'a> {
                     let seg = Segment::from_ident(ident);
                     check_consistency(self, &[seg], ident.span, kind, initial_res, res);
                     if res == Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat) {
+                        let node_id = self
+                            .invocation_parents
+                            .get(&parent_scope.expansion)
+                            .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0]);
                         self.lint_buffer.buffer_lint_with_diagnostic(
                             LEGACY_DERIVE_HELPERS,
-                            self.lint_node_id(parent_scope.expansion),
+                            node_id,
                             ident.span,
                             "derive helper attribute is used before it is introduced",
                             BuiltinLintDiagnostics::LegacyDeriveHelpers(binding.span),
index 54b6a1215858153f3924214e466085eff3817aae..842f7f9deee38ed3e887a922be597154188857e6 100644 (file)
@@ -142,12 +142,7 @@ impl<'tcx> DumpVisitor<'tcx> {
         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 297383bfed1faf517f919eb4a5fde32485eda55a..0a8a88132e33de65849e710a2d069da135a1c5d6 100644 (file)
@@ -109,9 +109,9 @@ impl<'tcx> SaveContext<'tcx> {
 
     // List external crates used by the current crate.
     pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
-        let mut result = Vec::with_capacity(self.tcx.crates().len());
+        let mut result = Vec::with_capacity(self.tcx.crates(()).len());
 
-        for &n in self.tcx.crates().iter() {
+        for &n in self.tcx.crates(()).iter() {
             let span = match self.tcx.extern_crate(n.as_def_id()) {
                 Some(&ExternCrate { span, .. }) => span,
                 None => {
@@ -127,7 +127,10 @@ impl<'tcx> SaveContext<'tcx> {
                 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 @@ impl<'tcx> SaveContext<'tcx> {
         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 b79adb6f7bcd92a5d2bb4287c018c3bfa84e2638..4d213207fb625265a54ea107e23eefa8bda01b80 100644 (file)
@@ -1114,6 +1114,15 @@ impl Json {
         }
     }
 
+    /// If the Json value is an Object, deletes the value associated with the
+    /// provided key from the Object and returns it. Otherwise, returns None.
+    pub fn remove_key(&mut self, key: &str) -> Option<Json> {
+        match *self {
+            Json::Object(ref mut map) => map.remove(key),
+            _ => None,
+        }
+    }
+
     /// Attempts to get a nested Json Object for each key in `keys`.
     /// If any key is found not to exist, `find_path` will return `None`.
     /// Otherwise, it will return the Json value associated with the final key.
index e3a823127d93ea60621623ec8cb51e593ed4b192..a759fa1bf1a7579f4eb11f1a3eccc44bc3c7b5a3 100644 (file)
@@ -437,7 +437,7 @@ fn test_decode_str() {
         ("\"\\uAB12\"", "\u{AB12}"),
     ];
 
-    for &(i, o) in &s {
+    for (i, o) in s {
         let v: string::String = json::decode(i).unwrap();
         assert_eq!(v, o);
     }
index 4c72920502f5fb223512b9bd9b18bea7563a69aa..571fd581d3fff3972fc4305f017753064e6d96fc 100644 (file)
@@ -5,7 +5,6 @@ version = "0.0.0"
 edition = "2018"
 
 [dependencies]
-bitflags = "1.2.1"
 getopts = "0.2"
 rustc_macros = { path = "../rustc_macros" }
 tracing = "0.1"
index 2b547f8be92286559e4d14dc2513d1b9cb3ac2df..2d7f5f9b321d1d0c99501a6b9260ac98eb47ee1b 100644 (file)
@@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::impl_stable_hash_via_hash;
 
 use rustc_target::abi::{Align, TargetDataLayout};
-use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple};
+use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple, TargetWarnings};
 
 use rustc_serialize::json;
 
@@ -31,6 +31,7 @@ use std::collections::btree_map::{
 };
 use std::collections::{BTreeMap, BTreeSet};
 use std::fmt;
+use std::hash::Hash;
 use std::iter::{self, FromIterator};
 use std::path::{Path, PathBuf};
 use std::str::{self, FromStr};
@@ -325,12 +326,11 @@ impl Default for TrimmedDefPaths {
 
 /// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
 /// *Do not* switch `BTreeMap` out for an unsorted container type! That would break
-/// dependency tracking for command-line arguments.
-#[derive(Clone, Hash, Debug)]
+/// dependency tracking for command-line arguments. Also only hash keys, since tracking
+/// should only depend on the output types, not the paths they're written to.
+#[derive(Clone, Debug, Hash)]
 pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>);
 
-impl_stable_hash_via_hash!(OutputTypes);
-
 impl OutputTypes {
     pub fn new(entries: &[(OutputType, Option<PathBuf>)]) -> OutputTypes {
         OutputTypes(BTreeMap::from_iter(entries.iter().map(|&(k, ref v)| (k, v.clone()))))
@@ -677,7 +677,6 @@ impl Default for Options {
             optimize: OptLevel::No,
             debuginfo: DebugInfo::None,
             lint_opts: Vec::new(),
-            force_warns: Vec::new(),
             lint_cap: None,
             describe_lints: false,
             output_types: OutputTypes(BTreeMap::new()),
@@ -805,6 +804,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
     let wordsz = sess.target.pointer_width.to_string();
     let os = &sess.target.os;
     let env = &sess.target.env;
+    let abi = &sess.target.abi;
     let vendor = &sess.target.vendor;
     let min_atomic_width = sess.target.min_atomic_width();
     let max_atomic_width = sess.target.max_atomic_width();
@@ -814,7 +814,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
     });
 
     let mut ret = FxHashSet::default();
-    ret.reserve(6); // the minimum number of insertions
+    ret.reserve(7); // the minimum number of insertions
     // Target bindings.
     ret.insert((sym::target_os, Some(Symbol::intern(os))));
     for fam in &sess.target.families {
@@ -829,11 +829,12 @@ fn default_configuration(sess: &Session) -> CrateConfig {
     ret.insert((sym::target_endian, Some(Symbol::intern(end.as_str()))));
     ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz))));
     ret.insert((sym::target_env, Some(Symbol::intern(env))));
+    ret.insert((sym::target_abi, Some(Symbol::intern(abi))));
     ret.insert((sym::target_vendor, Some(Symbol::intern(vendor))));
     if sess.target.has_elf_tls {
         ret.insert((sym::target_thread_local, None));
     }
-    for &(i, align) in &[
+    for (i, align) in [
         (8, layout.i8_align.abi),
         (16, layout.i16_align.abi),
         (32, layout.i32_align.abi),
@@ -899,9 +900,11 @@ pub(super) fn build_target_config(
     target_override: Option<Target>,
     sysroot: &PathBuf,
 ) -> Target {
-    let target_result =
-        target_override.map_or_else(|| Target::search(&opts.target_triple, sysroot), Ok);
-    let target = target_result.unwrap_or_else(|e| {
+    let target_result = target_override.map_or_else(
+        || Target::search(&opts.target_triple, sysroot),
+        |t| Ok((t, TargetWarnings::empty())),
+    );
+    let (target, target_warnings) = target_result.unwrap_or_else(|e| {
         early_error(
             opts.error_format,
             &format!(
@@ -911,6 +914,9 @@ pub(super) fn build_target_config(
             ),
         )
     });
+    for warning in target_warnings.warning_messages() {
+        early_warn(opts.error_format, &warning)
+    }
 
     if !matches!(target.pointer_width, 16 | 32 | 64) {
         early_error(
@@ -1095,7 +1101,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
         ),
         opt::multi_s(
             "",
-            "force-warns",
+            "force-warn",
             "Specifiy lints that should warn even if \
              they are allowed somewhere else",
             "LINT",
@@ -1165,20 +1171,20 @@ pub fn get_cmd_lint_options(
     matches: &getopts::Matches,
     error_format: ErrorOutputType,
     debugging_opts: &DebuggingOptions,
-) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>, Vec<String>) {
+) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
     let mut lint_opts_with_position = vec![];
     let mut describe_lints = false;
 
-    for &level in &[lint::Allow, lint::Warn, lint::Deny, lint::Forbid] {
-        for (passed_arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) {
-            let arg_pos = if let lint::Forbid = level {
-                // HACK: forbid is always specified last, so it can't be overridden.
-                // FIXME: remove this once <https://github.com/rust-lang/rust/issues/70819> is
-                // fixed and `forbid` works as expected.
-                usize::MAX
-            } else {
-                passed_arg_pos
-            };
+    if !debugging_opts.unstable_options && matches.opt_present("force-warn") {
+        early_error(
+            error_format,
+            "the `-Z unstable-options` flag must also be passed to enable \
+            the flag `--force-warn=lints`",
+        );
+    }
+
+    for level in [lint::Allow, lint::Warn, lint::ForceWarn, lint::Deny, lint::Forbid] {
+        for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) {
             if lint_name == "help" {
                 describe_lints = true;
             } else {
@@ -1199,17 +1205,7 @@ pub fn get_cmd_lint_options(
             .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{}`", cap)))
     });
 
-    if !debugging_opts.unstable_options && matches.opt_present("force-warns") {
-        early_error(
-            error_format,
-            "the `-Z unstable-options` flag must also be passed to enable \
-            the flag `--force-warns=lints`",
-        );
-    }
-
-    let force_warns = matches.opt_strs("force-warns");
-
-    (lint_opts, describe_lints, lint_cap, force_warns)
+    (lint_opts, describe_lints, lint_cap)
 }
 
 /// Parses the `--color` flag.
@@ -1947,7 +1943,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         .unwrap_or_else(|e| early_error(error_format, &e[..]));
 
     let mut debugging_opts = DebuggingOptions::build(matches, error_format);
-    let (lint_opts, describe_lints, lint_cap, force_warns) =
+    let (lint_opts, describe_lints, lint_cap) =
         get_cmd_lint_options(matches, error_format, &debugging_opts);
 
     check_debug_option_stability(&debugging_opts, error_format, json_rendered);
@@ -2121,7 +2117,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         optimize: opt_level,
         debuginfo,
         lint_opts,
-        force_warns,
         lint_cap,
         describe_lints,
         output_types,
@@ -2420,8 +2415,8 @@ crate mod dep_tracking {
     use super::LdImpl;
     use super::{
         CFGuard, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LinkerPluginLto,
-        LtoCli, OptLevel, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath,
-        SymbolManglingVersion, TrimmedDefPaths,
+        LtoCli, OptLevel, OutputType, OutputTypes, Passes, SourceFileHashAlgorithm,
+        SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths,
     };
     use crate::lint;
     use crate::options::WasiExecModel;
@@ -2437,13 +2432,18 @@ crate mod dep_tracking {
     use std::path::PathBuf;
 
     pub trait DepTrackingHash {
-        fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType);
+        fn hash(
+            &self,
+            hasher: &mut DefaultHasher,
+            error_format: ErrorOutputType,
+            for_crate_hash: bool,
+        );
     }
 
     macro_rules! impl_dep_tracking_hash_via_hash {
         ($($t:ty),+ $(,)?) => {$(
             impl DepTrackingHash for $t {
-                fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
+                fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType, _for_crate_hash: bool) {
                     Hash::hash(self, hasher);
                 }
             }
@@ -2451,11 +2451,16 @@ crate mod dep_tracking {
     }
 
     impl<T: DepTrackingHash> DepTrackingHash for Option<T> {
-        fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
+        fn hash(
+            &self,
+            hasher: &mut DefaultHasher,
+            error_format: ErrorOutputType,
+            for_crate_hash: bool,
+        ) {
             match self {
                 Some(x) => {
                     Hash::hash(&1, hasher);
-                    DepTrackingHash::hash(x, hasher, error_format);
+                    DepTrackingHash::hash(x, hasher, error_format, for_crate_hash);
                 }
                 None => Hash::hash(&0, hasher),
             }
@@ -2485,7 +2490,6 @@ crate mod dep_tracking {
         LtoCli,
         DebugInfo,
         UnstableFeatures,
-        OutputTypes,
         NativeLib,
         NativeLibKind,
         SanitizerSet,
@@ -2499,6 +2503,7 @@ crate mod dep_tracking {
         SourceFileHashAlgorithm,
         TrimmedDefPaths,
         Option<LdImpl>,
+        OutputType,
     );
 
     impl<T1, T2> DepTrackingHash for (T1, T2)
@@ -2506,11 +2511,16 @@ crate mod dep_tracking {
         T1: DepTrackingHash,
         T2: DepTrackingHash,
     {
-        fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
+        fn hash(
+            &self,
+            hasher: &mut DefaultHasher,
+            error_format: ErrorOutputType,
+            for_crate_hash: bool,
+        ) {
             Hash::hash(&0, hasher);
-            DepTrackingHash::hash(&self.0, hasher, error_format);
+            DepTrackingHash::hash(&self.0, hasher, error_format, for_crate_hash);
             Hash::hash(&1, hasher);
-            DepTrackingHash::hash(&self.1, hasher, error_format);
+            DepTrackingHash::hash(&self.1, hasher, error_format, for_crate_hash);
         }
     }
 
@@ -2520,22 +2530,49 @@ crate mod dep_tracking {
         T2: DepTrackingHash,
         T3: DepTrackingHash,
     {
-        fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
+        fn hash(
+            &self,
+            hasher: &mut DefaultHasher,
+            error_format: ErrorOutputType,
+            for_crate_hash: bool,
+        ) {
             Hash::hash(&0, hasher);
-            DepTrackingHash::hash(&self.0, hasher, error_format);
+            DepTrackingHash::hash(&self.0, hasher, error_format, for_crate_hash);
             Hash::hash(&1, hasher);
-            DepTrackingHash::hash(&self.1, hasher, error_format);
+            DepTrackingHash::hash(&self.1, hasher, error_format, for_crate_hash);
             Hash::hash(&2, hasher);
-            DepTrackingHash::hash(&self.2, hasher, error_format);
+            DepTrackingHash::hash(&self.2, hasher, error_format, for_crate_hash);
         }
     }
 
     impl<T: DepTrackingHash> DepTrackingHash for Vec<T> {
-        fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
+        fn hash(
+            &self,
+            hasher: &mut DefaultHasher,
+            error_format: ErrorOutputType,
+            for_crate_hash: bool,
+        ) {
             Hash::hash(&self.len(), hasher);
             for (index, elem) in self.iter().enumerate() {
                 Hash::hash(&index, hasher);
-                DepTrackingHash::hash(elem, hasher, error_format);
+                DepTrackingHash::hash(elem, hasher, error_format, for_crate_hash);
+            }
+        }
+    }
+
+    impl DepTrackingHash for OutputTypes {
+        fn hash(
+            &self,
+            hasher: &mut DefaultHasher,
+            error_format: ErrorOutputType,
+            for_crate_hash: bool,
+        ) {
+            Hash::hash(&self.0.len(), hasher);
+            for (key, val) in &self.0 {
+                DepTrackingHash::hash(key, hasher, error_format, for_crate_hash);
+                if !for_crate_hash {
+                    DepTrackingHash::hash(val, hasher, error_format, for_crate_hash);
+                }
             }
         }
     }
@@ -2545,13 +2582,14 @@ crate mod dep_tracking {
         sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>,
         hasher: &mut DefaultHasher,
         error_format: ErrorOutputType,
+        for_crate_hash: bool,
     ) {
         for (key, sub_hash) in sub_hashes {
             // Using Hash::hash() instead of DepTrackingHash::hash() is fine for
             // the keys, as they are just plain strings
             Hash::hash(&key.len(), hasher);
             Hash::hash(key, hasher);
-            sub_hash.hash(hasher, error_format);
+            sub_hash.hash(hasher, error_format, for_crate_hash);
         }
     }
 }
index 8d00a9a959e7a2c8d0577eeeba57790230ccc956..9a82ae3fc109080d4ae4c652fdd353c81ae7ce49 100644 (file)
@@ -24,3 +24,8 @@ pub use session::*;
 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 1946bfd78cc38ebab2b757616d79c7dacfe1be18..172337aca3d4bfae35f8fc872fc7d9f4a24dfb1f 100644 (file)
@@ -48,7 +48,11 @@ macro_rules! hash_substruct {
     ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [TRACKED_NO_CRATE_HASH]) => {{}};
     ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [SUBSTRUCT]) => {
         use crate::config::dep_tracking::DepTrackingHash;
-        $opt_expr.dep_tracking_hash($for_crate_hash, $error_format).hash($hasher, $error_format);
+        $opt_expr.dep_tracking_hash($for_crate_hash, $error_format).hash(
+            $hasher,
+            $error_format,
+            $for_crate_hash,
+        );
     };
 }
 
@@ -79,7 +83,8 @@ macro_rules! top_level_options {
                 let mut hasher = DefaultHasher::new();
                 dep_tracking::stable_hash(sub_hashes,
                                           &mut hasher,
-                                          self.error_format);
+                                          self.error_format,
+                                          for_crate_hash);
                 $({
                     hash_substruct!($opt,
                         &self.$opt,
@@ -128,9 +133,8 @@ top_level_options!(
         /// can influence whether overflow checks are done or not.
         debug_assertions: bool [TRACKED],
         debuginfo: DebugInfo [TRACKED],
-        lint_opts: Vec<(String, lint::Level)> [TRACKED],
-        lint_cap: Option<lint::Level> [TRACKED],
-        force_warns: Vec<String> [TRACKED],
+        lint_opts: Vec<(String, lint::Level)> [TRACKED_NO_CRATE_HASH],
+        lint_cap: Option<lint::Level> [TRACKED_NO_CRATE_HASH],
         describe_lints: bool [UNTRACKED],
         output_types: OutputTypes [TRACKED],
         search_paths: Vec<SearchPath> [UNTRACKED],
@@ -236,19 +240,21 @@ macro_rules! options {
             build_options(matches, $stat, $prefix, $outputname, error_format)
         }
 
-        fn dep_tracking_hash(&self, _for_crate_hash: bool, error_format: ErrorOutputType) -> u64 {
+        fn dep_tracking_hash(&self, for_crate_hash: bool, error_format: ErrorOutputType) -> u64 {
             let mut sub_hashes = BTreeMap::new();
             $({
                 hash_opt!($opt,
                             &self.$opt,
                             &mut sub_hashes,
-                            _for_crate_hash,
+                            for_crate_hash,
                             [$dep_tracking_marker]);
             })*
             let mut hasher = DefaultHasher::new();
             dep_tracking::stable_hash(sub_hashes,
                                         &mut hasher,
-                                        error_format);
+                                        error_format,
+                                        for_crate_hash
+                                        );
             hasher.finish()
         }
     }
@@ -1077,6 +1083,8 @@ options! {
         "set the optimization fuel quota for a crate"),
     function_sections: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "whether each function should go in its own section"),
+    future_incompat_test: bool = (false, parse_bool, [UNTRACKED],
+        "forces all lints to be future incompatible, used for internal testing (default: no)"),
     gcc_ld: Option<LdImpl> = (None, parse_gcc_ld, [TRACKED], "implementation of ld used by cc"),
     graphviz_dark_mode: bool = (false, parse_bool, [UNTRACKED],
         "use dark-themed colors in graphviz output (default: no)"),
@@ -1122,6 +1130,8 @@ options! {
         "link native libraries in the linker invocation (default: yes)"),
     link_only: bool = (false, parse_bool, [TRACKED],
         "link the `.rlink` file generated by `-Z no-link` (default: no)"),
+    llvm_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
+        "a list LLVM plugins to enable (space separated)"),
     llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],
         "generate JSON tracing data file from LLVM data (default: no)"),
     ls: bool = (false, parse_bool, [UNTRACKED],
@@ -1148,7 +1158,7 @@ options! {
         "the directory the NLL facts are dumped into (default: `nll-facts`)"),
     no_analysis: bool = (false, parse_no_flag, [UNTRACKED],
         "parse and expand the source, but run no analysis"),
-    no_codegen: bool = (false, parse_no_flag, [TRACKED],
+    no_codegen: bool = (false, parse_no_flag, [TRACKED_NO_CRATE_HASH],
         "run all passes except codegen; no output"),
     no_generate_arange_section: bool = (false, parse_no_flag, [TRACKED],
         "omit DWARF address ranges that give faster lookups"),
@@ -1160,8 +1170,6 @@ options! {
         "compile without linking"),
     no_parallel_llvm: bool = (false, parse_no_flag, [UNTRACKED],
         "run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"),
-    no_profiler_runtime: bool = (false, parse_no_flag, [TRACKED],
-        "prevent automatic injection of the profiler_builtins crate"),
     normalize_docs: bool = (false, parse_bool, [TRACKED],
         "normalize associated items in rustdoc when generating documentation"),
     osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
@@ -1202,9 +1210,13 @@ options! {
          "show backtraces for panics during proc-macro execution (default: no)"),
     profile: bool = (false, parse_bool, [TRACKED],
         "insert profiling code (default: no)"),
+    profile_closures: bool = (false, parse_no_flag, [UNTRACKED],
+        "profile size of closures"),
     profile_emit: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
         "file path to emit profiling data at runtime when using 'profile' \
         (default based on relative source path)"),
+    profiler_runtime: Option<String> = (Some(String::from("profiler_builtins")), parse_opt_string, [TRACKED],
+        "name of the profiler runtime crate to automatically inject, or None to disable"),
     query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
         "enable queries of the dependency graph for regression testing (default: no)"),
     query_stats: bool = (false, parse_bool, [UNTRACKED],
@@ -1238,7 +1250,7 @@ options! {
         "specify the events recorded by the self profiler;
         for example: `-Z self-profile-events=default,query-keys`
         all options: none, all, default, generic-activity, query-provider, query-cache-hit
-                     query-blocked, incr-cache-load, query-keys, function-args, args, llvm"),
+                     query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm"),
     share_generics: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "make the current crate share its generic instantiations"),
     show_span: Option<String> = (None, parse_opt_string, [TRACKED],
index 7b7878e9c7f4223ef501d21753524f0484e44d89..226fde2343aab1a6d757466dc234e1521fe9a489 100644 (file)
@@ -133,6 +133,8 @@ pub struct ParseSess {
     pub reached_eof: Lock<bool>,
     /// Environment variables accessed during the build and their values when they exist.
     pub env_depinfo: Lock<FxHashSet<(Symbol, Option<Symbol>)>>,
+    /// File paths accessed during the build.
+    pub file_depinfo: Lock<FxHashSet<Symbol>>,
     /// All the type ascriptions expressions that have had a suggestion for likely path typo.
     pub type_ascription_path_suggestions: Lock<FxHashSet<Span>>,
     /// Whether cfg(version) should treat the current release as incomplete
@@ -165,6 +167,7 @@ impl ParseSess {
             symbol_gallery: SymbolGallery::default(),
             reached_eof: Lock::new(false),
             env_depinfo: Default::default(),
+            file_depinfo: Default::default(),
             type_ascription_path_suggestions: Default::default(),
             assume_incomplete_release: false,
             proc_macro_quoted_spans: Default::default(),
index 86b8389a670e624e5b51d3b495ea91d87199ab74..86d495c3353b3bdfb9adf5562a06dbf0fd9f27bb 100644 (file)
@@ -1,7 +1,7 @@
 use crate::cgu_reuse_tracker::CguReuseTracker;
 use crate::code_stats::CodeStats;
 pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
-use crate::config::{self, CrateType, OutputType, PrintRequest, SwitchWithOptPath};
+use crate::config::{self, CrateType, OutputType, SwitchWithOptPath};
 use crate::filesearch;
 use crate::lint::{self, LintId};
 use crate::parse::ParseSess;
@@ -20,9 +20,9 @@ use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter;
 use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType};
 use rustc_errors::json::JsonEmitter;
 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_errors::{DiagnosticBuilder, DiagnosticId, ErrorReported};
+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 +66,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 +111,20 @@ impl Mul<usize> for Limit {
     }
 }
 
+#[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 +147,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.
@@ -316,27 +316,11 @@ impl Session {
         if diags.is_empty() {
             return;
         }
-        // If any future-breakage lints were registered, this lint store
-        // should be available
-        let lint_store = self.lint_store.get().expect("`lint_store` not initialized!");
-        let diags_and_breakage: Vec<(FutureBreakage, Diagnostic)> = diags
-            .into_iter()
-            .map(|diag| {
-                let lint_name = match &diag.code {
-                    Some(DiagnosticId::Lint { name, has_future_breakage: true }) => name,
-                    _ => panic!("Unexpected code in diagnostic {:?}", diag),
-                };
-                let lint = lint_store.name_to_lint(&lint_name);
-                let future_breakage =
-                    lint.lint.future_incompatible.unwrap().future_breakage.unwrap();
-                (future_breakage, diag)
-            })
-            .collect();
-        self.parse_sess.span_diagnostic.emit_future_breakage_report(diags_and_breakage);
+        self.parse_sess.span_diagnostic.emit_future_breakage_report(diags);
     }
 
-    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 +331,16 @@ impl Session {
         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 +352,9 @@ impl Session {
     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)
     }
@@ -792,18 +767,6 @@ impl Session {
         !self.target.is_like_windows && !self.target.is_like_osx
     }
 
-    pub fn must_not_eliminate_frame_pointers(&self) -> bool {
-        // "mcount" function relies on stack pointer.
-        // See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
-        if self.instrument_mcount() {
-            true
-        } else if let Some(x) = self.opts.cg.force_frame_pointers {
-            x
-        } else {
-            !self.target.eliminate_frame_pointer
-        }
-    }
-
     pub fn must_emit_unwind_tables(&self) -> bool {
         // This is used to control the emission of the `uwtable` attribute on
         // LLVM functions.
@@ -833,12 +796,12 @@ impl Session {
 
     /// 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<'_> {
@@ -1284,9 +1247,12 @@ pub fn build_session(
 
     let target_cfg = config::build_target_config(&sopts, target_override, &sysroot);
     let host_triple = TargetTriple::from_triple(config::host_triple());
-    let host = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
+    let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
         early_error(sopts.error_format, &format!("Error loading host specification: {}", e))
     });
+    for warning in target_warnings.warning_messages() {
+        early_warn(sopts.error_format, &warning)
+    }
 
     let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
     let hash_kind = sopts.debugging_opts.src_hash_algorithm.unwrap_or_else(|| {
@@ -1397,13 +1363,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,
@@ -1478,25 +1440,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
         }
     }
 
-    // PGO does not work reliably with panic=unwind on Windows. Let's make it
-    // an error to combine the two for now. It always runs into an assertions
-    // if LLVM is built with assertions, but without assertions it sometimes
-    // does not crash and will probably generate a corrupted binary.
-    // We should only display this error if we're actually going to run PGO.
-    // If we're just supposed to print out some data, don't show the error (#61002).
-    if sess.opts.cg.profile_generate.enabled()
-        && sess.target.is_like_msvc
-        && sess.panic_strategy() == PanicStrategy::Unwind
-        && sess.opts.prints.iter().all(|&p| p == PrintRequest::NativeStaticLibs)
-    {
-        sess.err(
-            "Profile-guided optimization does not yet work in conjunction \
-                  with `-Cpanic=unwind` on Windows when targeting MSVC. \
-                  See issue #61002 <https://github.com/rust-lang/rust/issues/61002> \
-                  for more information.",
-        );
-    }
-
     // Sanitizers can only be used on platforms that we know have working sanitizer codegen.
     let supported_sanitizers = sess.target.options.supported_sanitizers;
     let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers;
index 08645990c4870dec32420bc50a17ce56905104d8..4552f14de8b706a98292cba864c44fc2a3115da3 100644 (file)
@@ -17,6 +17,6 @@ scoped-tls = "1.0"
 unicode-width = "0.1.4"
 cfg-if = "0.1.2"
 tracing = "0.1"
-sha-1 = "0.9"
+sha1 = { package = "sha-1", version = "0.9" }
 sha2 = "0.9"
-md-5 = "0.9"
+md5 = { package = "md-5", version = "0.9" }
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 6ee75376ad5bd08384cedfdfa548eca4a8c3b234..64baf94cc00631047475a4c5443751b23d209e62 100644 (file)
@@ -1,7 +1,6 @@
-use crate::crate_disambiguator::CrateDisambiguator;
 use crate::HashStableContext;
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 use rustc_data_structures::AtomicRef;
 use rustc_index::vec::Idx;
 use rustc_macros::HashStable_Generic;
@@ -127,26 +126,51 @@ impl Borrow<Fingerprint> for DefPathHash {
     }
 }
 
-/// 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)]
-pub struct StableCrateId(u64);
+#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
+pub struct StableCrateId(pub(crate) 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())
     }
 }
@@ -308,13 +332,49 @@ impl<D: Decoder> Decodable<D> for LocalDefId {
 rustc_data_structures::define_id_collections!(LocalDefIdMap, LocalDefIdSet, LocalDefId);
 
 impl<CTX: HashStableContext> HashStable<CTX> for DefId {
+    #[inline]
     fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
-        hcx.hash_def_id(*self, hasher)
+        self.to_stable_hash_key(hcx).hash_stable(hcx, hasher);
+    }
+}
+
+impl<CTX: HashStableContext> HashStable<CTX> for LocalDefId {
+    #[inline]
+    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+        self.to_stable_hash_key(hcx).hash_stable(hcx, hasher);
     }
 }
 
 impl<CTX: HashStableContext> HashStable<CTX> for CrateNum {
+    #[inline]
     fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
-        hcx.hash_crate_num(*self, hasher)
+        self.to_stable_hash_key(hcx).hash_stable(hcx, hasher);
+    }
+}
+
+impl<CTX: HashStableContext> ToStableHashKey<CTX> for DefId {
+    type KeyType = DefPathHash;
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &CTX) -> DefPathHash {
+        hcx.def_path_hash(*self)
+    }
+}
+
+impl<CTX: HashStableContext> ToStableHashKey<CTX> for LocalDefId {
+    type KeyType = DefPathHash;
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &CTX) -> DefPathHash {
+        hcx.def_path_hash(self.to_def_id())
+    }
+}
+
+impl<CTX: HashStableContext> ToStableHashKey<CTX> for CrateNum {
+    type KeyType = DefPathHash;
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &CTX) -> DefPathHash {
+        self.as_def_id().to_stable_hash_key(hcx)
     }
 }
index 8f3b8cc2d0efce8ebec4e3061c997c2fc72b0ddc..e44a2e96598ce40401b244eeae6bfdaf1fd50854 100644 (file)
 
 use crate::edition::Edition;
 use crate::symbol::{kw, sym, Symbol};
-use crate::SESSION_GLOBALS;
-use crate::{BytePos, CachingSourceMapView, ExpnIdCache, SourceFile, Span, DUMMY_SP};
+use crate::with_session_globals;
+use crate::{HashStableContext, Span, DUMMY_SP};
 
-use crate::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{Lock, Lrc};
+use rustc_data_structures::unhash::UnhashMap;
+use rustc_index::vec::IndexVec;
 use rustc_macros::HashStable_Generic;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::fmt;
 use std::hash::Hash;
-use std::thread::LocalKey;
 use tracing::*;
 
 /// A `SyntaxContext` represents a chain of pairs `(ExpnId, Transparency)` named "marks".
@@ -58,9 +59,66 @@ pub struct SyntaxContextData {
     dollar_crate_name: Symbol,
 }
 
+rustc_index::newtype_index! {
+    /// A unique ID associated with a macro invocation and expansion.
+    pub struct ExpnIndex {
+        ENCODABLE = custom
+    }
+}
+
 /// A unique ID associated with a macro invocation and expansion.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
-pub struct ExpnId(u32);
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+pub struct ExpnId {
+    pub krate: CrateNum,
+    pub local_id: ExpnIndex,
+}
+
+impl fmt::Debug for ExpnId {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // Generate crate_::{{expn_}}.
+        write!(f, "{:?}::{{{{expn{}}}}}", self.krate, self.local_id.private)
+    }
+}
+
+rustc_index::newtype_index! {
+    /// A unique ID associated with a macro invocation and expansion.
+    pub struct LocalExpnId {
+        ENCODABLE = custom
+        DEBUG_FORMAT = "expn{}"
+    }
+}
+
+/// A unique hash value associated to an expansion.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
+pub struct ExpnHash(Fingerprint);
+
+impl ExpnHash {
+    /// Returns the [StableCrateId] identifying the crate this [ExpnHash]
+    /// originates from.
+    #[inline]
+    pub fn stable_crate_id(self) -> StableCrateId {
+        StableCrateId(self.0.as_value().0)
+    }
+
+    /// Returns the crate-local part of the [ExpnHash].
+    ///
+    /// Used for tests.
+    #[inline]
+    pub fn local_hash(self) -> u64 {
+        self.0.as_value().1
+    }
+
+    #[inline]
+    pub fn is_root(self) -> bool {
+        self.0 == Fingerprint::ZERO
+    }
+
+    /// Builds a new [ExpnHash] with the given [StableCrateId] and
+    /// `local_hash`, where `local_hash` must be unique within its crate.
+    fn new(stable_crate_id: StableCrateId, local_hash: u64) -> ExpnHash {
+        ExpnHash(Fingerprint::new(stable_crate_id.0, local_hash))
+    }
+}
 
 /// A property of a macro expansion that determines how identifiers
 /// produced by that expansion are resolved.
@@ -82,47 +140,128 @@ pub enum Transparency {
     Opaque,
 }
 
-impl ExpnId {
-    pub fn fresh(expn_data: Option<ExpnData>) -> Self {
-        let has_data = expn_data.is_some();
-        let expn_id = HygieneData::with(|data| data.fresh_expn(expn_data));
-        if has_data {
-            update_disambiguator(expn_id);
-        }
-        expn_id
+impl LocalExpnId {
+    /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST.
+    pub const ROOT: LocalExpnId = LocalExpnId::from_u32(0);
+
+    pub fn from_raw(idx: ExpnIndex) -> LocalExpnId {
+        LocalExpnId::from_u32(idx.as_u32())
     }
 
-    /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST.
-    #[inline]
-    pub fn root() -> Self {
-        ExpnId(0)
+    pub fn as_raw(self) -> ExpnIndex {
+        ExpnIndex::from_u32(self.as_u32())
     }
 
-    #[inline]
-    pub fn as_u32(self) -> u32 {
-        self.0
+    pub fn fresh_empty() -> LocalExpnId {
+        HygieneData::with(|data| {
+            let expn_id = data.local_expn_data.push(None);
+            let _eid = data.local_expn_hashes.push(ExpnHash(Fingerprint::ZERO));
+            debug_assert_eq!(expn_id, _eid);
+            expn_id
+        })
+    }
+
+    pub fn fresh(mut expn_data: ExpnData, ctx: impl HashStableContext) -> LocalExpnId {
+        debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE);
+        let expn_hash = update_disambiguator(&mut expn_data, ctx);
+        HygieneData::with(|data| {
+            let expn_id = data.local_expn_data.push(Some(expn_data));
+            let _eid = data.local_expn_hashes.push(expn_hash);
+            debug_assert_eq!(expn_id, _eid);
+            let _old_id = data.expn_hash_to_expn_id.insert(expn_hash, expn_id.to_expn_id());
+            debug_assert!(_old_id.is_none());
+            expn_id
+        })
     }
 
     #[inline]
-    pub fn from_u32(raw: u32) -> ExpnId {
-        ExpnId(raw)
+    pub fn expn_hash(self) -> ExpnHash {
+        HygieneData::with(|data| data.local_expn_hash(self))
     }
 
     #[inline]
     pub fn expn_data(self) -> ExpnData {
-        HygieneData::with(|data| data.expn_data(self).clone())
+        HygieneData::with(|data| data.local_expn_data(self).clone())
     }
 
     #[inline]
-    pub fn set_expn_data(self, mut expn_data: ExpnData) {
+    pub fn to_expn_id(self) -> ExpnId {
+        ExpnId { krate: LOCAL_CRATE, local_id: self.as_raw() }
+    }
+
+    #[inline]
+    pub fn set_expn_data(self, mut expn_data: ExpnData, ctx: impl HashStableContext) {
+        debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE);
+        let expn_hash = update_disambiguator(&mut expn_data, ctx);
         HygieneData::with(|data| {
-            let old_expn_data = &mut data.expn_data[self.0 as usize];
+            let old_expn_data = &mut data.local_expn_data[self];
             assert!(old_expn_data.is_none(), "expansion data is reset for an expansion ID");
-            assert_eq!(expn_data.orig_id, None);
-            expn_data.orig_id = Some(self.as_u32());
             *old_expn_data = Some(expn_data);
+            debug_assert_eq!(data.local_expn_hashes[self].0, Fingerprint::ZERO);
+            data.local_expn_hashes[self] = expn_hash;
+            let _old_id = data.expn_hash_to_expn_id.insert(expn_hash, self.to_expn_id());
+            debug_assert!(_old_id.is_none());
         });
-        update_disambiguator(self)
+    }
+
+    #[inline]
+    pub fn is_descendant_of(self, ancestor: LocalExpnId) -> bool {
+        self.to_expn_id().is_descendant_of(ancestor.to_expn_id())
+    }
+
+    /// `expn_id.outer_expn_is_descendant_of(ctxt)` is equivalent to but faster than
+    /// `expn_id.is_descendant_of(ctxt.outer_expn())`.
+    #[inline]
+    pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool {
+        self.to_expn_id().outer_expn_is_descendant_of(ctxt)
+    }
+
+    /// Returns span for the macro which originally caused this expansion to happen.
+    ///
+    /// Stops backtracing at include! boundary.
+    #[inline]
+    pub fn expansion_cause(self) -> Option<Span> {
+        self.to_expn_id().expansion_cause()
+    }
+
+    #[inline]
+    #[track_caller]
+    pub fn parent(self) -> LocalExpnId {
+        self.expn_data().parent.as_local().unwrap()
+    }
+}
+
+impl ExpnId {
+    /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST.
+    /// Invariant: we do not create any ExpnId with local_id == 0 and krate != 0.
+    pub const fn root() -> ExpnId {
+        ExpnId { krate: LOCAL_CRATE, local_id: ExpnIndex::from_u32(0) }
+    }
+
+    #[inline]
+    pub fn expn_hash(self) -> ExpnHash {
+        HygieneData::with(|data| data.expn_hash(self))
+    }
+
+    #[inline]
+    pub fn from_hash(hash: ExpnHash) -> Option<ExpnId> {
+        HygieneData::with(|data| data.expn_hash_to_expn_id.get(&hash).copied())
+    }
+
+    #[inline]
+    pub fn as_local(self) -> Option<LocalExpnId> {
+        if self.krate == LOCAL_CRATE { Some(LocalExpnId::from_raw(self.local_id)) } else { None }
+    }
+
+    #[inline]
+    #[track_caller]
+    pub fn expect_local(self) -> LocalExpnId {
+        self.as_local().unwrap()
+    }
+
+    #[inline]
+    pub fn expn_data(self) -> ExpnData {
+        HygieneData::with(|data| data.expn_data(self).clone())
     }
 
     pub fn is_descendant_of(self, ancestor: ExpnId) -> bool {
@@ -144,10 +283,7 @@ impl ExpnId {
             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;
             }
@@ -163,29 +299,40 @@ pub struct HygieneData {
     /// Each expansion should have an associated expansion data, but sometimes there's a delay
     /// between creation of an expansion ID and obtaining its data (e.g. macros are collected
     /// first and then resolved later), so we use an `Option` here.
-    expn_data: Vec<Option<ExpnData>>,
+    local_expn_data: IndexVec<LocalExpnId, Option<ExpnData>>,
+    local_expn_hashes: IndexVec<LocalExpnId, ExpnHash>,
+    /// Data and hash information from external crates.  We may eventually want to remove these
+    /// maps, and fetch the information directly from the other crate's metadata like DefIds do.
+    foreign_expn_data: FxHashMap<ExpnId, ExpnData>,
+    foreign_expn_hashes: FxHashMap<ExpnId, ExpnHash>,
+    expn_hash_to_expn_id: UnhashMap<ExpnHash, ExpnId>,
     syntax_context_data: Vec<SyntaxContextData>,
     syntax_context_map: FxHashMap<(SyntaxContext, ExpnId, Transparency), SyntaxContext>,
-    /// Maps the `Fingerprint` of an `ExpnData` to the next disambiguator value.
+    /// Maps the `local_hash` of an `ExpnData` to the next disambiguator value.
     /// This is used by `update_disambiguator` to keep track of which `ExpnData`s
     /// would have collisions without a disambiguator.
     /// The keys of this map are always computed with `ExpnData.disambiguator`
     /// set to 0.
-    expn_data_disambiguators: FxHashMap<Fingerprint, u32>,
+    expn_data_disambiguators: FxHashMap<u64, u32>,
 }
 
 impl HygieneData {
     crate fn new(edition: Edition) -> Self {
-        let mut root_data = ExpnData::default(
+        let root_data = ExpnData::default(
             ExpnKind::Root,
             DUMMY_SP,
             edition,
-            Some(DefId::local(CRATE_DEF_INDEX)),
+            Some(CRATE_DEF_ID.to_def_id()),
+            None,
         );
-        root_data.orig_id = Some(0);
 
         HygieneData {
-            expn_data: vec![Some(root_data)],
+            local_expn_data: IndexVec::from_elem_n(Some(root_data), 1),
+            local_expn_hashes: IndexVec::from_elem_n(ExpnHash(Fingerprint::ZERO), 1),
+            foreign_expn_data: FxHashMap::default(),
+            foreign_expn_hashes: FxHashMap::default(),
+            expn_hash_to_expn_id: std::iter::once((ExpnHash(Fingerprint::ZERO), ExpnId::root()))
+                .collect(),
             syntax_context_data: vec![SyntaxContextData {
                 outer_expn: ExpnId::root(),
                 outer_transparency: Transparency::Opaque,
@@ -200,21 +347,32 @@ 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 {
-        let raw_id = self.expn_data.len() as u32;
-        if let Some(data) = expn_data.as_mut() {
-            assert_eq!(data.orig_id, None);
-            data.orig_id = Some(raw_id);
+    #[inline]
+    fn local_expn_hash(&self, expn_id: LocalExpnId) -> ExpnHash {
+        self.local_expn_hashes[expn_id]
+    }
+
+    #[inline]
+    fn expn_hash(&self, expn_id: ExpnId) -> ExpnHash {
+        match expn_id.as_local() {
+            Some(expn_id) => self.local_expn_hashes[expn_id],
+            None => self.foreign_expn_hashes[&expn_id],
         }
-        self.expn_data.push(expn_data);
-        ExpnId(raw_id)
+    }
+
+    fn local_expn_data(&self, expn_id: LocalExpnId) -> &ExpnData {
+        self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID")
     }
 
     fn expn_data(&self, expn_id: ExpnId) -> &ExpnData {
-        self.expn_data[expn_id.0 as usize].as_ref().expect("no expansion data for an expansion ID")
+        if let Some(expn_id) = expn_id.as_local() {
+            self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID")
+        } else {
+            &self.foreign_expn_data[&expn_id]
+        }
     }
 
     fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool {
@@ -429,17 +587,21 @@ pub fn debug_hygiene_data(verbose: bool) -> String {
         } else {
             let mut s = String::from("");
             s.push_str("Expansions:");
-            data.expn_data.iter().enumerate().for_each(|(id, expn_info)| {
-                let expn_info = expn_info.as_ref().expect("no expansion data for an expansion ID");
+            let mut debug_expn_data = |(id, expn_data): (&ExpnId, &ExpnData)| {
                 s.push_str(&format!(
-                    "\n{}: parent: {:?}, call_site_ctxt: {:?}, def_site_ctxt: {:?}, kind: {:?}",
+                    "\n{:?}: parent: {:?}, call_site_ctxt: {:?}, def_site_ctxt: {:?}, kind: {:?}",
                     id,
-                    expn_info.parent,
-                    expn_info.call_site.ctxt(),
-                    expn_info.def_site.ctxt(),
-                    expn_info.kind,
-                ));
+                    expn_data.parent,
+                    expn_data.call_site.ctxt(),
+                    expn_data.def_site.ctxt(),
+                    expn_data.kind,
+                ))
+            };
+            data.local_expn_data.iter_enumerated().for_each(|(id, expn_data)| {
+                let expn_data = expn_data.as_ref().expect("no expansion data for an expansion ID");
+                debug_expn_data((&id.to_expn_id(), expn_data))
             });
+            data.foreign_expn_data.iter().for_each(debug_expn_data);
             s.push_str("\n\nSyntaxContexts:");
             data.syntax_context_data.iter().enumerate().for_each(|(id, ctxt)| {
                 s.push_str(&format!(
@@ -646,7 +808,7 @@ impl SyntaxContext {
     }
 
     pub fn edition(self) -> Edition {
-        self.outer_expn_data().edition
+        HygieneData::with(|data| data.expn_data(data.outer_expn(self)).edition)
     }
 }
 
@@ -662,16 +824,17 @@ impl Span {
     /// other compiler-generated code to set per-span properties like allowed unstable features.
     /// The returned span belongs to the created expansion and has the new properties,
     /// but its location is inherited from the current span.
-    pub fn fresh_expansion(self, expn_data: ExpnData) -> Span {
-        self.fresh_expansion_with_transparency(expn_data, Transparency::Transparent)
+    pub fn fresh_expansion(self, expn_data: ExpnData, ctx: impl HashStableContext) -> Span {
+        self.fresh_expansion_with_transparency(expn_data, Transparency::Transparent, ctx)
     }
 
     pub fn fresh_expansion_with_transparency(
         self,
         expn_data: ExpnData,
         transparency: Transparency,
+        ctx: impl HashStableContext,
     ) -> Span {
-        let expn_id = ExpnId::fresh(Some(expn_data));
+        let expn_id = LocalExpnId::fresh(expn_data, ctx).to_expn_id();
         HygieneData::with(|data| {
             self.with_ctxt(data.apply_mark(SyntaxContext::root(), expn_id, transparency))
         })
@@ -684,11 +847,13 @@ impl Span {
         allow_internal_unstable: Option<Lrc<[Symbol]>>,
         reason: DesugaringKind,
         edition: Edition,
+        ctx: impl HashStableContext,
     ) -> Span {
-        self.fresh_expansion(ExpnData {
+        let expn_data = ExpnData {
             allow_internal_unstable,
-            ..ExpnData::default(ExpnKind::Desugaring(reason), self, edition, None)
-        })
+            ..ExpnData::default(ExpnKind::Desugaring(reason), self, edition, None, None)
+        };
+        self.fresh_expansion(expn_data, ctx)
     }
 }
 
@@ -711,6 +876,17 @@ pub struct ExpnData {
     /// call_site span would have its own ExpnData, with the call_site
     /// pointing to the `foo!` invocation.
     pub call_site: Span,
+    /// 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`
+    /// - the two `ExpnId`s are not equal, but their `Fingerprint`s are equal
+    /// (since the numerical `ExpnId` value is not considered by the `HashStable`
+    /// implementation).
+    ///
+    /// The `disambiguator` field is set by `update_disambiguator` when two distinct
+    /// `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,
@@ -734,35 +910,10 @@ pub struct ExpnData {
     /// 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,
-    /// foreign `ExpnId`s will have their `ExpnData` looked up
-    /// from the crate specified by `Crate
-    krate: CrateNum,
-    /// The raw that this `ExpnData` had in its original crate.
-    /// An `ExpnData` can be created before being assigned an `ExpnId`,
-    /// so this might be `None` until `set_expn_data` is called
-    // This is used only for serialization/deserialization purposes:
-    // two `ExpnData`s that differ only in their `orig_id` should
-    // 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`
-    /// - the two `ExpnId`s are not equal, but their `Fingerprint`s are equal
-    /// (since the numerical `ExpnId` value is not considered by the `HashStable`
-    /// implementation).
-    ///
-    /// The `disambiguator` field is set by `update_disambiguator` when two distinct
-    /// `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 normal module (`mod`) in which the expanded macro was defined.
+    pub parent_module: Option<DefId>,
 }
 
-// These would require special handling of `orig_id`.
 impl !PartialEq for ExpnData {}
 impl !Hash for ExpnData {}
 
@@ -777,6 +928,7 @@ impl ExpnData {
         local_inner_macros: bool,
         edition: Edition,
         macro_def_id: Option<DefId>,
+        parent_module: Option<DefId>,
     ) -> ExpnData {
         ExpnData {
             kind,
@@ -788,8 +940,7 @@ impl ExpnData {
             local_inner_macros,
             edition,
             macro_def_id,
-            krate: LOCAL_CRATE,
-            orig_id: None,
+            parent_module,
             disambiguator: 0,
         }
     }
@@ -800,6 +951,7 @@ impl ExpnData {
         call_site: Span,
         edition: Edition,
         macro_def_id: Option<DefId>,
+        parent_module: Option<DefId>,
     ) -> ExpnData {
         ExpnData {
             kind,
@@ -811,8 +963,7 @@ impl ExpnData {
             local_inner_macros: false,
             edition,
             macro_def_id,
-            krate: LOCAL_CRATE,
-            orig_id: None,
+            parent_module,
             disambiguator: 0,
         }
     }
@@ -823,10 +974,11 @@ impl ExpnData {
         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)
         }
     }
 
@@ -834,6 +986,13 @@ impl ExpnData {
     pub fn is_root(&self) -> bool {
         matches!(self.kind, ExpnKind::Root)
     }
+
+    #[inline]
+    fn hash_expn(&self, ctx: &mut impl HashStableContext) -> u64 {
+        let mut hasher = StableHasher::new();
+        self.hash_stable(ctx, &mut hasher);
+        hasher.finish()
+    }
 }
 
 /// Expansion kind.
@@ -842,13 +1001,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 +1014,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),
@@ -918,7 +1071,7 @@ pub enum AstPass {
 }
 
 impl AstPass {
-    fn descr(self) -> &'static str {
+    pub fn descr(self) -> &'static str {
         match self {
             AstPass::StdImports => "standard library imports",
             AstPass::TestHarness => "test harness",
@@ -955,7 +1108,7 @@ pub enum ForLoopLoc {
 
 impl DesugaringKind {
     /// The description wording should combine well with "desugaring of {}".
-    fn descr(self) -> &'static str {
+    pub fn descr(self) -> &'static str {
         match self {
             DesugaringKind::CondTemporary => "`if` or `while` condition",
             DesugaringKind::Async => "`async` block or function",
@@ -986,16 +1139,18 @@ pub struct HygieneEncodeContext {
 }
 
 impl HygieneEncodeContext {
-    pub fn encode<
-        T,
-        R,
-        F: FnMut(&mut T, u32, &SyntaxContextData) -> Result<(), R>,
-        G: FnMut(&mut T, u32, &ExpnData) -> Result<(), R>,
-    >(
+    /// Record the fact that we need to serialize the corresponding `ExpnData`.
+    pub fn schedule_expn_data_for_encoding(&self, expn: ExpnId) {
+        if !self.serialized_expns.lock().contains(&expn) {
+            self.latest_expns.lock().insert(expn);
+        }
+    }
+
+    pub fn encode<T, R>(
         &self,
         encoder: &mut T,
-        mut encode_ctxt: F,
-        mut encode_expn: G,
+        mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData) -> Result<(), R>,
+        mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash) -> Result<(), R>,
     ) -> Result<(), R> {
         // When we serialize a `SyntaxContextData`, we may end up serializing
         // a `SyntaxContext` that we haven't seen before
@@ -1013,7 +1168,7 @@ impl HygieneEncodeContext {
             // It's fine to iterate over a HashMap, because the serialization
             // of the table that we insert data into doesn't depend on insertion
             // order
-            for_all_ctxts_in(latest_ctxts.into_iter(), |(index, ctxt, data)| {
+            for_all_ctxts_in(latest_ctxts.into_iter(), |index, ctxt, data| {
                 if self.serialized_ctxts.lock().insert(ctxt) {
                     encode_ctxt(encoder, index, data)?;
                 }
@@ -1022,9 +1177,9 @@ impl HygieneEncodeContext {
 
             let latest_expns = { std::mem::take(&mut *self.latest_expns.lock()) };
 
-            for_all_expns_in(latest_expns.into_iter(), |index, expn, data| {
+            for_all_expns_in(latest_expns.into_iter(), |expn, data, hash| {
                 if self.serialized_expns.lock().insert(expn) {
-                    encode_expn(encoder, index, data)?;
+                    encode_expn(encoder, expn, data, hash)?;
                 }
                 Ok(())
             })?;
@@ -1043,73 +1198,70 @@ pub struct HygieneDecodeContext {
     // so that multiple occurrences of the same serialized id are decoded to the same
     // `SyntaxContext`
     remapped_ctxts: Lock<Vec<Option<SyntaxContext>>>,
-    // The same as `remapepd_ctxts`, but for `ExpnId`s
-    remapped_expns: Lock<Vec<Option<ExpnId>>>,
 }
 
-pub fn decode_expn_id<
-    'a,
-    D: Decoder,
-    F: FnOnce(&mut D, u32) -> Result<ExpnData, D::Error>,
-    G: FnOnce(CrateNum) -> &'a HygieneDecodeContext,
->(
-    d: &mut D,
-    mode: ExpnDataDecodeMode<'a, G>,
-    decode_data: F,
-) -> Result<ExpnId, D::Error> {
-    let index = u32::decode(d)?;
-    let context = match mode {
-        ExpnDataDecodeMode::IncrComp(context) => context,
-        ExpnDataDecodeMode::Metadata(get_context) => {
-            let krate = CrateNum::decode(d)?;
-            get_context(krate)
-        }
-    };
+/// Register an expansion which has been decoded from the on-disk-cache for the local crate.
+pub fn register_local_expn_id(data: ExpnData, hash: ExpnHash) -> ExpnId {
+    HygieneData::with(|hygiene_data| {
+        let expn_id = hygiene_data.local_expn_data.next_index();
+        hygiene_data.local_expn_data.push(Some(data));
+        let _eid = hygiene_data.local_expn_hashes.push(hash);
+        debug_assert_eq!(expn_id, _eid);
+
+        let expn_id = expn_id.to_expn_id();
 
-    // Do this after decoding, so that we decode a `CrateNum`
-    // if necessary
-    if index == ExpnId::root().as_u32() {
+        let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id);
+        debug_assert!(_old_id.is_none());
+        expn_id
+    })
+}
+
+/// Register an expansion which has been decoded from the metadata of a foreign crate.
+pub fn register_expn_id(
+    krate: CrateNum,
+    local_id: ExpnIndex,
+    data: ExpnData,
+    hash: ExpnHash,
+) -> ExpnId {
+    let expn_id = ExpnId { krate, local_id };
+    HygieneData::with(|hygiene_data| {
+        let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, data);
+        debug_assert!(_old_data.is_none());
+        let _old_hash = hygiene_data.foreign_expn_hashes.insert(expn_id, hash);
+        debug_assert!(_old_hash.is_none());
+        let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id);
+        debug_assert!(_old_id.is_none());
+    });
+    expn_id
+}
+
+/// Decode an expansion from the metadata of a foreign crate.
+pub fn decode_expn_id(
+    krate: CrateNum,
+    index: u32,
+    decode_data: impl FnOnce(ExpnId) -> (ExpnData, ExpnHash),
+) -> ExpnId {
+    if index == 0 {
         debug!("decode_expn_id: deserialized root");
-        return Ok(ExpnId::root());
+        return ExpnId::root();
     }
 
-    let outer_expns = &context.remapped_expns;
+    let index = ExpnIndex::from_u32(index);
 
-    // Ensure that the lock() temporary is dropped early
-    {
-        if let Some(expn_id) = outer_expns.lock().get(index as usize).copied().flatten() {
-            return Ok(expn_id);
-        }
+    // This function is used to decode metadata, so it cannot decode information about LOCAL_CRATE.
+    debug_assert_ne!(krate, LOCAL_CRATE);
+    let expn_id = ExpnId { krate, local_id: index };
+
+    // Fast path if the expansion has already been decoded.
+    if HygieneData::with(|hygiene_data| hygiene_data.foreign_expn_data.contains_key(&expn_id)) {
+        return expn_id;
     }
 
     // Don't decode the data inside `HygieneData::with`, since we need to recursively decode
     // other ExpnIds
-    let mut expn_data = decode_data(d, index)?;
-
-    let expn_id = HygieneData::with(|hygiene_data| {
-        let expn_id = ExpnId(hygiene_data.expn_data.len() as u32);
-
-        // If we just deserialized an `ExpnData` owned by
-        // the local crate, its `orig_id` will be stale,
-        // so we need to update it to its own value.
-        // This only happens when we deserialize the incremental cache,
-        // since a crate will never decode its own metadata.
-        if expn_data.krate == LOCAL_CRATE {
-            expn_data.orig_id = Some(expn_id.0);
-        }
-
-        hygiene_data.expn_data.push(Some(expn_data));
+    let (expn_data, hash) = decode_data(expn_id);
 
-        let mut expns = outer_expns.lock();
-        let new_len = index as usize + 1;
-        if expns.len() < new_len {
-            expns.resize(new_len, None);
-        }
-        expns[index as usize] = Some(expn_id);
-        drop(expns);
-        expn_id
-    });
-    Ok(expn_id)
+    register_expn_id(krate, index, expn_data, hash)
 }
 
 // Decodes `SyntaxContext`, using the provided `HygieneDecodeContext`
@@ -1185,7 +1337,7 @@ pub fn decode_syntax_context<
     Ok(new_ctxt)
 }
 
-fn for_all_ctxts_in<E, F: FnMut((u32, SyntaxContext, &SyntaxContextData)) -> Result<(), E>>(
+fn for_all_ctxts_in<E, F: FnMut(u32, SyntaxContext, &SyntaxContextData) -> Result<(), E>>(
     ctxts: impl Iterator<Item = SyntaxContext>,
     mut f: F,
 ) -> Result<(), E> {
@@ -1193,30 +1345,44 @@ fn for_all_ctxts_in<E, F: FnMut((u32, SyntaxContext, &SyntaxContextData)) -> Res
         ctxts.map(|ctxt| (ctxt, data.syntax_context_data[ctxt.0 as usize].clone())).collect()
     });
     for (ctxt, data) in all_data.into_iter() {
-        f((ctxt.0, ctxt, &data))?;
+        f(ctxt.0, ctxt, &data)?;
     }
     Ok(())
 }
 
-fn for_all_expns_in<E, F: FnMut(u32, ExpnId, &ExpnData) -> Result<(), E>>(
+fn for_all_expns_in<E>(
     expns: impl Iterator<Item = ExpnId>,
-    mut f: F,
+    mut f: impl FnMut(ExpnId, &ExpnData, ExpnHash) -> Result<(), E>,
 ) -> Result<(), E> {
     let all_data: Vec<_> = HygieneData::with(|data| {
-        expns.map(|expn| (expn, data.expn_data[expn.0 as usize].clone())).collect()
+        expns
+            .map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn).clone()))
+            .collect()
     });
-    for (expn, data) in all_data.into_iter() {
-        f(expn.0, expn, &data.unwrap_or_else(|| panic!("Missing data for {:?}", expn)))?;
+    for (expn, data, hash) in all_data.into_iter() {
+        f(expn, &data, hash)?;
     }
     Ok(())
 }
 
+impl<E: Encoder> Encodable<E> for LocalExpnId {
+    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+        self.to_expn_id().encode(e)
+    }
+}
+
 impl<E: Encoder> Encodable<E> for ExpnId {
     default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
         panic!("cannot encode `ExpnId` with `{}`", std::any::type_name::<E>());
     }
 }
 
+impl<D: Decoder> Decodable<D> for LocalExpnId {
+    fn decode(d: &mut D) -> Result<Self, D::Error> {
+        ExpnId::decode(d).map(ExpnId::expect_local)
+    }
+}
+
 impl<D: Decoder> Decodable<D> for ExpnId {
     default fn decode(_: &mut D) -> Result<Self, D::Error> {
         panic!("cannot decode `ExpnId` with `{}`", std::any::type_name::<D>());
@@ -1234,58 +1400,6 @@ pub fn raw_encode_syntax_context<E: Encoder>(
     ctxt.0.encode(e)
 }
 
-pub fn raw_encode_expn_id<E: Encoder>(
-    expn: ExpnId,
-    context: &HygieneEncodeContext,
-    mode: ExpnDataEncodeMode,
-    e: &mut E,
-) -> Result<(), E::Error> {
-    // Record the fact that we need to serialize the corresponding
-    // `ExpnData`
-    let needs_data = || {
-        if !context.serialized_expns.lock().contains(&expn) {
-            context.latest_expns.lock().insert(expn);
-        }
-    };
-
-    match mode {
-        ExpnDataEncodeMode::IncrComp => {
-            // Always serialize the `ExpnData` in incr comp mode
-            needs_data();
-            expn.0.encode(e)
-        }
-        ExpnDataEncodeMode::Metadata => {
-            let data = expn.expn_data();
-            // We only need to serialize the ExpnData
-            // if it comes from this crate.
-            // We currently don't serialize any hygiene information data for
-            // proc-macro crates: see the `SpecializedEncoder<Span>` impl
-            // for crate metadata.
-            if data.krate == LOCAL_CRATE {
-                needs_data();
-            }
-            data.orig_id.expect("Missing orig_id").encode(e)?;
-            data.krate.encode(e)
-        }
-    }
-}
-
-pub enum ExpnDataEncodeMode {
-    IncrComp,
-    Metadata,
-}
-
-pub enum ExpnDataDecodeMode<'a, F: FnOnce(CrateNum) -> &'a HygieneDecodeContext> {
-    IncrComp(&'a HygieneDecodeContext),
-    Metadata(F),
-}
-
-impl<'a> ExpnDataDecodeMode<'a, Box<dyn FnOnce(CrateNum) -> &'a HygieneDecodeContext>> {
-    pub fn incr_comp(ctxt: &'a HygieneDecodeContext) -> Self {
-        ExpnDataDecodeMode::IncrComp(ctxt)
-    }
-}
-
 impl<E: Encoder> Encodable<E> for SyntaxContext {
     default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
         panic!("cannot encode `SyntaxContext` with `{}`", std::any::type_name::<E>());
@@ -1305,106 +1419,71 @@ impl<D: Decoder> Decodable<D> for SyntaxContext {
 /// This method is called only when an `ExpnData` is first associated
 /// with an `ExpnId` (when the `ExpnId` is initially constructed, or via
 /// `set_expn_data`). It is *not* called for foreign `ExpnId`s deserialized
-/// from another crate's metadata - since `ExpnData` includes a `krate` field,
+/// from another crate's metadata - since `ExpnHash` includes the stable crate id,
 /// collisions are only possible between `ExpnId`s within the same crate.
-fn update_disambiguator(expn_id: ExpnId) {
-    /// A `HashStableContext` which hashes the raw id values for `DefId`
-    /// and `CrateNum`, rather than using their computed stable hash.
-    ///
-    /// This allows us to use the `HashStable` implementation on `ExpnId`
-    /// early on in compilation, before we've constructed a `TyCtxt`.
-    /// The `Fingerprint`s created by this context are not 'stable', since
-    /// the raw `CrateNum` and `DefId` values for an item may change between
-    /// sessions due to unrelated changes (e.g. adding/removing an different item).
-    ///
-    /// However, this is fine for our purposes - we only need to detect
-    /// when two `ExpnData`s have the same `Fingerprint`. Since the hashes produced
-    /// by this context still obey the properties of `HashStable`, we have
-    /// that
-    /// `hash_stable(expn1, DummyHashStableContext) == hash_stable(expn2, DummyHashStableContext)`
-    /// iff `hash_stable(expn1, StableHashingContext) == hash_stable(expn2, StableHasingContext)`.
-    ///
-    /// This is sufficient for determining when we need to update the disambiguator.
-    struct DummyHashStableContext<'a> {
-        caching_source_map: CachingSourceMapView<'a>,
-    }
-
-    impl<'a> crate::HashStableContext for DummyHashStableContext<'a> {
-        fn hash_def_id(&mut self, def_id: DefId, hasher: &mut StableHasher) {
-            def_id.krate.as_u32().hash_stable(self, hasher);
-            def_id.index.as_u32().hash_stable(self, hasher);
-        }
-
-        fn expn_id_cache() -> &'static LocalKey<ExpnIdCache> {
-            // This cache is only used by `DummyHashStableContext`,
-            // so we won't pollute the cache values of the normal `StableHashingContext`
-            thread_local! {
-                static CACHE: ExpnIdCache = const { ExpnIdCache::new(Vec::new()) };
-            }
-
-            &CACHE
-        }
-
-        fn hash_crate_num(&mut self, krate: CrateNum, hasher: &mut StableHasher) {
-            krate.as_u32().hash_stable(self, hasher);
-        }
-        fn hash_spans(&self) -> bool {
-            true
-        }
-        fn span_data_to_lines_and_cols(
-            &mut self,
-            span: &crate::SpanData,
-        ) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)> {
-            self.caching_source_map.span_data_to_lines_and_cols(span)
-        }
-    }
-
-    let source_map = SESSION_GLOBALS
-        .with(|session_globals| session_globals.source_map.borrow().as_ref().unwrap().clone());
-
-    let mut ctx =
-        DummyHashStableContext { caching_source_map: CachingSourceMapView::new(&source_map) };
-
-    let mut hasher = StableHasher::new();
-
-    let expn_data = expn_id.expn_data();
+fn update_disambiguator(expn_data: &mut ExpnData, mut ctx: impl HashStableContext) -> ExpnHash {
     // This disambiguator should not have been set yet.
     assert_eq!(
         expn_data.disambiguator, 0,
         "Already set disambiguator for ExpnData: {:?}",
         expn_data
     );
-    expn_data.hash_stable(&mut ctx, &mut hasher);
-    let first_hash = hasher.finish();
+    let mut expn_hash = expn_data.hash_expn(&mut ctx);
 
-    let modified = HygieneData::with(|data| {
+    let disambiguator = HygieneData::with(|data| {
         // If this is the first ExpnData with a given hash, then keep our
         // disambiguator at 0 (the default u32 value)
-        let disambig = data.expn_data_disambiguators.entry(first_hash).or_default();
-        data.expn_data[expn_id.0 as usize].as_mut().unwrap().disambiguator = *disambig;
+        let disambig = data.expn_data_disambiguators.entry(expn_hash).or_default();
+        let disambiguator = *disambig;
         *disambig += 1;
-
-        *disambig != 1
+        disambiguator
     });
 
-    if modified {
-        debug!("Set disambiguator for {:?} (hash {:?})", expn_id, first_hash);
-        debug!("expn_data = {:?}", expn_id.expn_data());
+    if disambiguator != 0 {
+        debug!("Set disambiguator for expn_data={:?} expn_hash={:?}", expn_data, expn_hash);
+
+        expn_data.disambiguator = disambiguator;
+        expn_hash = expn_data.hash_expn(&mut ctx);
 
         // Verify that the new disambiguator makes the hash unique
         #[cfg(debug_assertions)]
-        {
-            hasher = StableHasher::new();
-            expn_id.expn_data().hash_stable(&mut ctx, &mut hasher);
-            let new_hash: Fingerprint = hasher.finish();
-
-            HygieneData::with(|data| {
-                assert_eq!(
-                    data.expn_data_disambiguators.get(&new_hash),
-                    None,
-                    "Hash collision after disambiguator update!",
-                );
-            });
+        HygieneData::with(|data| {
+            assert_eq!(
+                data.expn_data_disambiguators.get(&expn_hash),
+                None,
+                "Hash collision after disambiguator update!",
+            );
+        });
+    }
+
+    ExpnHash::new(ctx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), expn_hash)
+}
+
+impl<CTX: HashStableContext> HashStable<CTX> for SyntaxContext {
+    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
+        const TAG_EXPANSION: u8 = 0;
+        const TAG_NO_EXPANSION: u8 = 1;
+
+        if *self == SyntaxContext::root() {
+            TAG_NO_EXPANSION.hash_stable(ctx, hasher);
+        } else {
+            TAG_EXPANSION.hash_stable(ctx, hasher);
+            let (expn_id, transparency) = self.outer_mark();
+            expn_id.hash_stable(ctx, hasher);
+            transparency.hash_stable(ctx, hasher);
+        }
+    }
+}
+
+impl<CTX: HashStableContext> HashStable<CTX> for ExpnId {
+    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
+        let hash = if *self == ExpnId::root() {
+            // Avoid fetching TLS storage for a trivial often-used value.
+            Fingerprint::ZERO
+        } else {
+            self.expn_hash().0
         };
+
+        hash.hash_stable(ctx, hasher);
     }
 }
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 9cf68cbd23e6da2f7200bf2c6c477e8f6bc252df..1c95cc91208d36f2cd0a3c98e42a8e3db9027e03 100644 (file)
@@ -36,36 +36,31 @@ use source_map::SourceMap;
 pub mod edition;
 use edition::Edition;
 pub mod hygiene;
-pub use hygiene::SyntaxContext;
 use hygiene::Transparency;
-pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, ForLoopLoc, MacroKind};
+pub use hygiene::{DesugaringKind, ExpnKind, ForLoopLoc, MacroKind};
+pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext};
 pub mod def_id;
-use def_id::{CrateNum, DefId, LOCAL_CRATE};
+use def_id::{CrateNum, DefId, DefPathHash, LOCAL_CRATE};
 pub mod lev_distance;
 mod span_encoding;
 pub use span_encoding::{Span, DUMMY_SP};
 
-pub mod crate_disambiguator;
-
 pub mod symbol;
 pub use symbol::{sym, Symbol};
 
 mod analyze_source_file;
 pub mod fatal_error;
 
-use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{Lock, Lrc};
 
 use std::borrow::Cow;
-use std::cell::RefCell;
 use std::cmp::{self, Ordering};
 use std::fmt;
 use std::hash::Hash;
 use std::ops::{Add, Range, Sub};
 use std::path::{Path, PathBuf};
 use std::str::FromStr;
-use std::thread::LocalKey;
 
 use md5::Md5;
 use sha1::Digest;
@@ -99,19 +94,65 @@ impl 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 +517,7 @@ impl Span {
 
     /// 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 +895,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 +920,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 +1546,11 @@ impl SourceFile {
     /// 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,28 +1949,12 @@ impl 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
 /// instead of implementing everything in rustc_middle.
 pub trait HashStableContext {
-    fn hash_def_id(&mut self, _: DefId, hasher: &mut StableHasher);
-    /// Obtains a cache for storing the `Fingerprint` of an `ExpnId`.
-    /// This method allows us to have multiple `HashStableContext` implementations
-    /// that hash things in a different way, without the results of one polluting
-    /// the cache of the other.
-    fn expn_id_cache() -> &'static LocalKey<ExpnIdCache>;
-    fn hash_crate_num(&mut self, _: CrateNum, hasher: &mut StableHasher);
+    fn def_path_hash(&self, def_id: DefId) -> DefPathHash;
     fn hash_spans(&self) -> bool;
     fn span_data_to_lines_and_cols(
         &mut self,
@@ -2008,60 +2028,3 @@ where
         Hash::hash(&len, hasher);
     }
 }
-
-impl<CTX: HashStableContext> HashStable<CTX> for SyntaxContext {
-    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
-        const TAG_EXPANSION: u8 = 0;
-        const TAG_NO_EXPANSION: u8 = 1;
-
-        if *self == SyntaxContext::root() {
-            TAG_NO_EXPANSION.hash_stable(ctx, hasher);
-        } else {
-            TAG_EXPANSION.hash_stable(ctx, hasher);
-            let (expn_id, transparency) = self.outer_mark();
-            expn_id.hash_stable(ctx, hasher);
-            transparency.hash_stable(ctx, hasher);
-        }
-    }
-}
-
-pub type ExpnIdCache = RefCell<Vec<Option<Fingerprint>>>;
-
-impl<CTX: HashStableContext> HashStable<CTX> for ExpnId {
-    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
-        const TAG_ROOT: u8 = 0;
-        const TAG_NOT_ROOT: u8 = 1;
-
-        if *self == ExpnId::root() {
-            TAG_ROOT.hash_stable(ctx, hasher);
-            return;
-        }
-
-        // Since the same expansion context is usually referenced many
-        // times, we cache a stable hash of it and hash that instead of
-        // recursing every time.
-        let index = self.as_u32() as usize;
-        let res = CTX::expn_id_cache().with(|cache| cache.borrow().get(index).copied().flatten());
-
-        if let Some(res) = res {
-            res.hash_stable(ctx, hasher);
-        } else {
-            let new_len = index + 1;
-
-            let mut sub_hasher = StableHasher::new();
-            TAG_NOT_ROOT.hash_stable(ctx, &mut sub_hasher);
-            self.expn_data().hash_stable(ctx, &mut sub_hasher);
-            let sub_hash: Fingerprint = sub_hasher.finish();
-
-            CTX::expn_id_cache().with(|cache| {
-                let mut cache = cache.borrow_mut();
-                if cache.len() < new_len {
-                    cache.resize(new_len, None);
-                }
-                let prev = cache[index].replace(sub_hash);
-                assert_eq!(prev, None, "Cache slot was filled");
-            });
-            sub_hash.hash_stable(ctx, hasher);
-        }
-    }
-}
index 32031ac70715f9735ceff3b2f759e2824f98bde7..77a3ad931d5717343eef8355a25a6c529ff11793 100644 (file)
@@ -461,9 +461,13 @@ impl SourceMap {
     }
 
     pub fn is_multiline(&self, sp: Span) -> bool {
-        let lo = self.lookup_char_pos(sp.lo());
-        let hi = self.lookup_char_pos(sp.hi());
-        lo.line != hi.line
+        let lo = self.lookup_source_file_idx(sp.lo());
+        let hi = self.lookup_source_file_idx(sp.hi());
+        if lo != hi {
+            return true;
+        }
+        let f = (*self.files.borrow().source_files)[lo].clone();
+        f.lookup_line(sp.lo()) != f.lookup_line(sp.hi())
     }
 
     pub fn is_valid_span(&self, sp: Span) -> Result<(Loc, Loc), SpanLinesError> {
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 @@ impl SpanInterner {
 // 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 a31ab5b350e4e27d26aa335aebb8ec2beaa9cb20..a8f969782b22daeb45d5253b27fa05eff65138b1 100644 (file)
@@ -13,7 +13,7 @@ use std::fmt;
 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;
@@ -122,10 +122,14 @@ symbols! {
     // nice to have.
     Symbols {
         Alignment,
+        Any,
         Arc,
         Argument,
         ArgumentV1,
         Arguments,
+        AsMut,
+        AsRef,
+        BTreeEntry,
         BTreeMap,
         BTreeSet,
         BinaryHeap,
@@ -139,6 +143,7 @@ symbols! {
         Continue,
         Copy,
         Count,
+        Cow,
         Debug,
         DebugStruct,
         DebugTuple,
@@ -146,26 +151,35 @@ symbols! {
         Decoder,
         Default,
         Deref,
+        DirBuilder,
+        DoubleEndedIterator,
+        Duration,
         Encodable,
         Encoder,
         Eq,
         Equal,
         Err,
         Error,
+        File,
+        FileType,
         FormatSpec,
         Formatter,
         From,
+        FromIterator,
         Future,
         FxHashMap,
         FxHashSet,
         GlobalAlloc,
         Hash,
         HashMap,
+        HashMapEntry,
         HashSet,
         Hasher,
         Implied,
         Input,
         IntoIterator,
+        IoRead,
+        IoWrite,
         Is,
         ItemContext,
         Iterator,
@@ -353,6 +367,7 @@ symbols! {
         cfg_eval,
         cfg_panic,
         cfg_sanitize,
+        cfg_target_abi,
         cfg_target_feature,
         cfg_target_has_atomic,
         cfg_target_thread_local,
@@ -367,6 +382,8 @@ symbols! {
         closure,
         closure_to_fn_coercion,
         cmp,
+        cmp_max,
+        cmp_min,
         cmpxchg16b_target_feature,
         cmse_nonsecure_entry,
         coerce_unsized,
@@ -416,7 +433,6 @@ symbols! {
         constructor,
         contents,
         context,
-        control_flow_enum,
         convert,
         copy,
         copy_closures,
@@ -462,6 +478,7 @@ symbols! {
         decode,
         default_alloc_error_handler,
         default_lib_allocator,
+        default_method_body_is_const,
         default_type_parameter_fallback,
         default_type_params,
         delay_span_bug_from_inside_query,
@@ -479,6 +496,7 @@ symbols! {
         discriminant_type,
         discriminant_value,
         dispatch_from_dyn,
+        display_trait,
         div,
         div_assign,
         doc,
@@ -569,6 +587,7 @@ symbols! {
         fmt,
         fmt_internals,
         fmul_fast,
+        fn_align,
         fn_must_use,
         fn_mut,
         fn_once,
@@ -586,6 +605,7 @@ symbols! {
         from,
         from_desugaring,
         from_generator,
+        from_iter,
         from_method,
         from_output,
         from_residual,
@@ -669,6 +689,7 @@ symbols! {
         item,
         item_like_imports,
         iter,
+        iter_repeat,
         keyword,
         kind,
         kreg,
@@ -680,6 +701,7 @@ symbols! {
         lateout,
         lazy_normalization_consts,
         le,
+        len,
         let_chains,
         lhs,
         lib,
@@ -734,6 +756,12 @@ symbols! {
         maybe_uninit,
         maybe_uninit_uninit,
         maybe_uninit_zeroed,
+        mem_discriminant,
+        mem_drop,
+        mem_forget,
+        mem_replace,
+        mem_size_of,
+        mem_size_of_val,
         mem_uninitialized,
         mem_zeroed,
         member_constraints,
@@ -752,6 +780,7 @@ symbols! {
         minnumf64,
         mips_target_feature,
         misc,
+        mmx_reg,
         modifiers,
         module,
         module_path,
@@ -895,6 +924,7 @@ symbols! {
         prefetch_read_instruction,
         prefetch_write_data,
         prefetch_write_instruction,
+        preg,
         prelude,
         prelude_import,
         preserves_flags,
@@ -930,6 +960,7 @@ symbols! {
         quote,
         range_inclusive_new,
         raw_dylib,
+        raw_eq,
         raw_identifiers,
         raw_ref_op,
         re_rebalance_coherence,
@@ -944,7 +975,7 @@ symbols! {
         receiver,
         recursion_limit,
         reexport_test_harness_main,
-        ref_unwind_safe,
+        ref_unwind_safe_trait,
         reference,
         reflect,
         reg,
@@ -1062,6 +1093,7 @@ symbols! {
         rustdoc,
         rustfmt,
         rvalue_static_promotion,
+        s,
         sanitize,
         sanitizer_runtime,
         saturating_add,
@@ -1069,7 +1101,6 @@ symbols! {
         self_in_typedefs,
         self_struct_ctor,
         semitransparent,
-        send,
         send_trait,
         shl,
         shl_assign,
@@ -1146,6 +1177,7 @@ symbols! {
         skip,
         slice,
         slice_alloc,
+        slice_len_fn,
         slice_patterns,
         slice_u8,
         slice_u8_alloc,
@@ -1194,6 +1226,7 @@ symbols! {
         sync,
         sync_trait,
         t32,
+        target_abi,
         target_arch,
         target_endian,
         target_env,
@@ -1235,7 +1268,9 @@ symbols! {
         truncf32,
         truncf64,
         try_blocks,
+        try_from,
         try_from_trait,
+        try_into,
         try_into_trait,
         try_trait_v2,
         tt,
@@ -1292,7 +1327,7 @@ symbols! {
         unused_qualifications,
         unwind,
         unwind_attributes,
-        unwind_safe,
+        unwind_safe_trait,
         unwrap,
         unwrap_or,
         use_extern_macros,
@@ -1335,6 +1370,7 @@ symbols! {
         wrapping_sub,
         wreg,
         write_bytes,
+        x87_reg,
         xmm_reg,
         ymm_reg,
         zmm_reg,
@@ -1783,7 +1819,7 @@ impl Ident {
 
 #[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 @@ use super::*;
 
 #[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 3df5f16131922cfb3455d99aa19907ae1edd81cc..53d4dc2922f421c4dcef658a2a5969c14a971907 100644 (file)
@@ -12,7 +12,6 @@ tracing = "0.1"
 punycode = "0.4.0"
 rustc-demangle = "0.1.18"
 
-rustc_ast = { path = "../rustc_ast" }
 rustc_span = { path = "../rustc_span" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_hir = { path = "../rustc_hir" }
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 828f1ac0a7989a7cdbc0e3fbb4a62983b9273c2c..14442806fc0b757104c1d4fb58adae3ddf0734a0 100644 (file)
@@ -3,9 +3,11 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
+use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::print::{Print, Printer};
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
 use rustc_middle::ty::{self, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeFoldable, UintTy};
+use rustc_target::abi::Integer;
 use rustc_target::spec::abi::Abi;
 
 use std::fmt::Write;
@@ -553,11 +555,9 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
             ty::Uint(_) | ty::Bool | ty::Char => {
                 ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty)
             }
-            ty::Int(_) => {
-                let param_env = ty::ParamEnv::reveal_all();
-                ct.try_eval_bits(self.tcx, param_env, ct.ty).and_then(|b| {
-                    let sz = self.tcx.layout_of(param_env.and(ct.ty)).ok()?.size;
-                    let val = sz.sign_extend(b) as i128;
+            ty::Int(ity) => {
+                ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty).and_then(|b| {
+                    let val = Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(b) as i128;
                     if val < 0 {
                         neg = true;
                     }
@@ -592,8 +592,8 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
 
     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 3004bb9ff5d5b1e40fe0aa42c6ae6ea2dd70850e..0ba73657b5b087fa57ce3c532c10cab56e3ae6c2 100644 (file)
@@ -1,5 +1,5 @@
 // Reference: MSP430 Embedded Application Binary Interface
-// http://www.ti.com/lit/an/slaa534/slaa534.pdf
+// https://www.ti.com/lit/an/slaa534a/slaa534a.pdf
 
 use crate::abi::call::{ArgAbi, FnAbi};
 
index 693337f0e52fd4df4f634c372abc456a7dbd9a3b..428dd95bbcd65be12d69d05b56ad90119e7e5126 100644 (file)
@@ -1,5 +1,5 @@
 // Reference: PTX Writer's Guide to Interoperability
-// http://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability
+// https://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability
 
 use crate::abi::call::{ArgAbi, FnAbi};
 
index b9c9296dbacc7db10fae36c0eae224deb42e3940..16f331b16d5619b5e0c7263c99d92e8a7f8c4cc8 100644 (file)
@@ -1,5 +1,5 @@
 // Reference: PTX Writer's Guide to Interoperability
-// http://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability
+// https://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability
 
 use crate::abi::call::{ArgAbi, FnAbi};
 
index 713b4100a33351472f8a1abfc739588956617021..ff8849e1cf83beac6293f686342379d49a33d964 100644 (file)
@@ -38,7 +38,7 @@ where
             // small structs are returned as integers.
             //
             // Some links:
-            // http://www.angelcode.com/dev/callconv/callconv.html
+            // https://www.angelcode.com/dev/callconv/callconv.html
             // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
             let t = cx.target_spec();
             if t.abi_return_struct_as_int {
index 5f154dc1bc9f83ee78f4809cc3692363c21c5043..a55658b7a3ec6caf1b2c30a5785a1fe04b146ea9 100644 (file)
@@ -185,7 +185,7 @@ where
             if let Ok(cls) = cls_or_mem {
                 let mut needed_int = 0;
                 let mut needed_sse = 0;
-                for &c in &cls {
+                for c in cls {
                     match c {
                         Some(Class::Int) => needed_int += 1,
                         Some(Class::Sse) => needed_sse += 1,
index 8e71ded3d1de6a7dfbbc006d4d7e8525df3d4866..9a24edf1a42cb25f24f6c5eed27356f49f4ef157 100644 (file)
@@ -16,7 +16,7 @@ use rustc_span::Span;
 
 pub mod call;
 
-/// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout)
+/// Parsed [Data layout](https://llvm.org/docs/LangRef.html#data-layout)
 /// for a target, which contains everything needed to compute layouts.
 pub struct TargetDataLayout {
     pub endian: Endian,
@@ -590,7 +590,7 @@ impl Integer {
     pub fn for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer> {
         let dl = cx.data_layout();
 
-        for &candidate in &[I8, I16, I32, I64, I128] {
+        for candidate in [I8, I16, I32, I64, I128] {
             if wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() {
                 return Some(candidate);
             }
@@ -603,7 +603,7 @@ impl Integer {
         let dl = cx.data_layout();
 
         // FIXME(eddyb) maybe include I128 in the future, when it works everywhere.
-        for &candidate in &[I64, I32, I16] {
+        for candidate in [I64, I32, I16] {
             if wanted >= candidate.align(dl).abi && wanted.bytes() >= candidate.size().bytes() {
                 return candidate;
             }
index f180eea01a3bbe796f060b7c91be3dad3871ac41..76e50678314aedb90c3e36831a293d7f252bb174 100644 (file)
@@ -7,6 +7,7 @@ def_reg_class! {
         reg,
         vreg,
         vreg_low16,
+        preg,
     }
 }
 
@@ -15,6 +16,7 @@ impl AArch64InlineAsmRegClass {
         match self {
             Self::reg => &['w', 'x'],
             Self::vreg | Self::vreg_low16 => &['b', 'h', 's', 'd', 'q', 'v'],
+            Self::preg => &[],
         }
     }
 
@@ -40,6 +42,7 @@ impl AArch64InlineAsmRegClass {
                 128 => Some(('q', "q0")),
                 _ => None,
             },
+            Self::preg => None,
         }
     }
 
@@ -47,6 +50,7 @@ impl AArch64InlineAsmRegClass {
         match self {
             Self::reg => Some(('x', "x0")),
             Self::vreg | Self::vreg_low16 => Some(('v', "v0")),
+            Self::preg => None,
         }
     }
 
@@ -61,6 +65,7 @@ impl AArch64InlineAsmRegClass {
                     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 @@ def_regs! {
         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 @@ impl InlineAsmRegClass {
             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 @@ def_reg_class! {
     RiscV RiscVInlineAsmRegClass {
         reg,
         freg,
+        vreg,
     }
 }
 
@@ -44,6 +45,7 @@ impl RiscVInlineAsmRegClass {
                 }
             }
             Self::freg => types! { "f": F32; "d": F64; },
+            Self::vreg => &[],
         }
     }
 }
@@ -120,6 +122,38 @@ def_regs! {
         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 @@ def_reg_class! {
         ymm_reg,
         zmm_reg,
         kreg,
+        mmx_reg,
+        x87_reg,
     }
 }
 
@@ -35,6 +37,7 @@ impl X86InlineAsmRegClass {
             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 @@ impl X86InlineAsmRegClass {
                 _ => Some(('x', "xmm0")),
             },
             Self::kreg => None,
+            Self::mmx_reg | Self::x87_reg => None,
         }
     }
 
@@ -90,6 +94,7 @@ impl X86InlineAsmRegClass {
             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 @@ impl X86InlineAsmRegClass {
                 "avx512f": I8, I16;
                 "avx512bw": I32, I64;
             },
+            Self::mmx_reg | Self::x87_reg => &[],
         }
     }
 }
@@ -285,16 +291,28 @@ def_regs! {
         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 cb8f6b9656c6834fd620a2bb02c1bbb035bdb3eb..d39e5a5aa2c3f4bed54ec4272d7e50a94e808000 100644 (file)
@@ -27,6 +27,9 @@ pub mod abi;
 pub mod asm;
 pub mod spec;
 
+#[cfg(test)]
+mod tests;
+
 /// 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`.
index feadd4e891cec706e0123c5407ddf89484d117ac..bf3ec8f9160b08aac80284106fdf342b9eef2efc 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::apple_base::opts("macos");
@@ -20,6 +20,10 @@ pub fn target() -> Target {
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
         arch: arch.to_string(),
-        options: TargetOptions { mcount: "\u{1}mcount".to_string(), ..base },
+        options: TargetOptions {
+            mcount: "\u{1}mcount".to_string(),
+            frame_pointer: FramePointer::NonLeaf,
+            ..base
+        },
     }
 }
index 5682039b86512aa6b0f3feb98846aa78c6319bcf..e5805d9e691cbe3ff311db0ed4413b756c275b2a 100644 (file)
@@ -1,8 +1,7 @@
 use super::apple_sdk_base::{opts, Arch};
-use crate::spec::{Target, TargetOptions};
+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,8 +10,8 @@ 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.
             // These arguments are not actually invoked - they just have
             // to look right to pass App Store validation.
@@ -24,7 +23,7 @@ pub fn target() -> Target {
                 darwinpcs\0\
                 -Os\0"
                 .to_string(),
-            ..base
+            ..opts("ios", Arch::Arm64)
         },
     }
 }
index 8a832546d09526334877090c86a9e31cb87a1edc..d16328f00f9ab65f7137b784b009c812dcbcf690 100644 (file)
@@ -1,8 +1,7 @@
 use super::apple_sdk_base::{opts, Arch};
-use crate::spec::{Target, TargetOptions};
+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,8 +10,8 @@ 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.
             // These arguments are not actually invoked - they just have
             // to look right to pass App Store validation.
@@ -22,7 +21,7 @@ pub fn target() -> Target {
                 -disable-llvm-passes\0\
                 -Os\0"
                 .to_string(),
-            ..base
+            ..opts("ios", Arch::Arm64_macabi)
         },
     }
 }
index 2187015b627d3a19e12dde51d0f00af62bbe8381..07b3453218fee47b80e7fa3d967a9ff47e5ba6b8 100644 (file)
@@ -1,5 +1,5 @@
 use super::apple_sdk_base::{opts, Arch};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub fn target() -> Target {
     let base = opts("ios", Arch::Arm64_sim);
@@ -19,8 +19,8 @@ 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.
             // These arguments are not actually invoked - they just have
             // to look right to pass App Store validation.
index cb6c06b371183f61bcf0e5d8b3b5bda2f2c01c2e..b4bd72a082be7c544d7eaf08d7b36792aa417764 100644 (file)
@@ -1,8 +1,7 @@
 use super::apple_sdk_base::{opts, Arch};
-use crate::spec::{Target, TargetOptions};
+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,9 +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,
-            ..base
+            frame_pointer: FramePointer::NonLeaf,
+            ..opts("tvos", Arch::Arm64)
         },
     }
 }
index 192c4661c7ce6d90d420ae2b6b0f23582db17a49..71ee6deb07f903b5c64b9b46d8e5ec59e9c6c1bd 100644 (file)
@@ -2,19 +2,16 @@ use crate::abi::Endian;
 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..e05360ea45c6c5b677f07ace67752a0a11f3a31b 100644 (file)
@@ -11,7 +11,7 @@ pub fn target() -> Target {
         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(),
+            abi: "ilp32".to_string(),
             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 eaf3a2dbcf8c2cbc5d02baf99e2bc5af9ddad28a..409cab72ec2196898ba478fa53d379c6041cb51d 100644 (file)
@@ -4,17 +4,18 @@ use crate::spec::{SanitizerSet, Target, TargetOptions};
 // for target ABI requirements.
 
 pub fn target() -> Target {
-    let mut base = super::android_base::opts();
-    base.max_atomic_width = Some(128);
-    // As documented in http://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..8522405f61feb50fbb2972a9990f72994b6816f6 100644 (file)
@@ -1,18 +1,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-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(),
+            abi: "ilp32".to_string(),
+            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..fa93ca80549cf1abc5656565809334845faccc66 100644 (file)
@@ -10,6 +10,7 @@ use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOp
 
 pub fn target() -> Target {
     let opts = TargetOptions {
+        abi: "softfloat".to_string(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
         linker: Some("rust-lld".to_owned()),
         features: "+strict-align,-neon,-fp-armv8".to_string(),
@@ -18,7 +19,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 @@ mod tests;
 #[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 @@ impl Abi {
     pub fn name(self) -> &'static str {
         self.data().name
     }
-
-    pub fn generic(self) -> bool {
-        self.data().generic
-    }
 }
 
 impl fmt::Display for Abi {
index 8530db179d9919060cfc17886d3ab2726c318ffd..0c8a89210ffcdcf32a39d1eec5b6441b5fd77037 100644 (file)
@@ -1,6 +1,6 @@
 use std::env;
 
-use crate::spec::{SplitDebuginfo, TargetOptions};
+use crate::spec::{FramePointer, SplitDebuginfo, TargetOptions};
 
 pub fn opts(os: &str) -> TargetOptions {
     // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
@@ -27,7 +27,7 @@ pub fn opts(os: &str) -> TargetOptions {
         families: vec!["unix".to_string()],
         is_like_osx: true,
         dwarf_version: Some(2),
-        eliminate_frame_pointer: false,
+        frame_pointer: FramePointer::Always,
         has_rpath: true,
         dll_suffix: ".dylib".to_string(),
         archive_format: "darwin".to_string(),
index e7f7bb343d0c534541dd31261b886b7a0870efe7..39bc699eef04a366bba8d4b03e253bc9038bf34d 100644 (file)
@@ -14,6 +14,15 @@ pub enum Arch {
     Arm64_sim,
 }
 
+fn target_abi(arch: Arch) -> String {
+    match arch {
+        Armv7 | Armv7s | Arm64 | I386 | X86_64 => "",
+        X86_64_macabi | Arm64_macabi => "macabi",
+        Arm64_sim => "sim",
+    }
+    .to_string()
+}
+
 fn target_cpu(arch: Arch) -> String {
     match arch {
         Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
@@ -39,6 +48,7 @@ fn link_env_remove(arch: Arch) -> Vec<String> {
 
 pub fn opts(os: &str, arch: Arch) -> TargetOptions {
     TargetOptions {
+        abi: target_abi(arch),
         cpu: target_cpu(arch),
         dynamic_linking: false,
         executables: true,
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..9b5366c576ec6a30b54b0113d61b509a300fb841 100644 (file)
@@ -1,16 +1,17 @@
 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 {
+            abi: "eabi".to_string(),
+            // 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..442f56d4fb5de73ed6697295dca4a304646ad2da 100644 (file)
@@ -1,19 +1,17 @@
 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 {
+            abi: "eabi".to_string(),
             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..2c12a71e29fb825ee9a2a1e57dcf5cfc31da9392 100644 (file)
@@ -1,19 +1,17 @@
 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 {
+            abi: "eabihf".to_string(),
             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..d187dfd918955d0d1c717b08a5692c822daf93a7 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,13 @@ 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(),
+            abi: "eabi".to_string(),
+            // 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..3d72734f5fadc5bb8fb81cce0cd834601451d206 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,13 @@ 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(),
+            abi: "eabihf".to_string(),
+            // 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..c98a12cfc4977f7d392340ad3543193e49fac5c0 100644 (file)
@@ -10,8 +10,8 @@ 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 {
+            abi: "eabi".to_string(),
             endian: Endian::Big,
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
             executables: true,
@@ -19,7 +19,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..292635403fbd476c9d4bc12eb214a960b4fed986 100644 (file)
@@ -10,8 +10,8 @@ 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 {
+            abi: "eabihf".to_string(),
             endian: Endian::Big,
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
             executables: true,
@@ -20,7 +20,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..f1b193a384fc1bc9fc1d01d5eb454fde2ac58eb7 100644 (file)
@@ -1,21 +1,19 @@
 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 {
+            abi: "eabi".to_string(),
             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..a6c4f2304c2c12f83a6e98c904f98a5d5b69d749 100644 (file)
@@ -1,21 +1,19 @@
 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 {
+            abi: "eabi".to_string(),
             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..de2a350e23120b685ebffcfdcf04985dc7b0a6d6 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,14 @@ 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 {
+            abi: "eabi".to_string(),
             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..91b4bd27caa8124b8f56d429b3fc82ed0a322ca6 100644 (file)
@@ -7,13 +7,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 {
+            abi: "eabi".to_string(),
             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..ee2f8f6238b592165f4fce97680269b3e4ba93b3 100644 (file)
@@ -1,20 +1,19 @@
 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 {
+            abi: "eabihf".to_string(),
+            // FIXME: change env to "gnu" when cfg_target_abi becomes stable
             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..b046819d4d78442c0a0aa9e16240630fbe30e415 100644 (file)
@@ -1,20 +1,19 @@
 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 {
+            abi: "eabihf".to_string(),
+            // FIXME: remove env when cfg_target_abi becomes stable
             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 super::apple_sdk_base::{opts, Arch};
 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..55956f3bad4fa7cad5be88bb6b8c4b2aa6977ada 100644 (file)
@@ -10,15 +10,17 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 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 {
+            abi: "eabi".to_string(),
+            features: "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".to_string(),
+            max_atomic_width: Some(64),
+            ..base
+        },
     }
 }
index 6f24c6818fcd0c0df6d93ab4a1b035891b3a22a2..fbfb1c27681eaa81de06c6b5191fef2711f72637 100644 (file)
@@ -1,20 +1,19 @@
 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 {
+            abi: "eabihf".to_string(),
+            // FIXME: change env to "gnu" when cfg_target_abi becomes stable
             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..0a3b8033dd17ccd58497a497ed6619248afceb04 100644 (file)
@@ -4,19 +4,17 @@ use crate::spec::{Target, TargetOptions};
 // 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 {
+            abi: "eabi".to_string(),
             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..662b81cae3e65acbdaff42f546ac613f77e77815 100644 (file)
@@ -4,20 +4,18 @@ use crate::spec::{Target, TargetOptions};
 // 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 {
+            abi: "eabihf".to_string(),
             // 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..c0fd1de17cfdd976637d85ac763e4b0c04976a26 100644 (file)
@@ -4,7 +4,6 @@ use crate::spec::{Target, TargetOptions};
 // 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 {
@@ -17,11 +16,11 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
 
         options: TargetOptions {
+            abi: "eabi".to_string(),
             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..67ff7999dea856f51e959c434aa6bcdcc66f6853 100644 (file)
@@ -3,7 +3,6 @@ use crate::spec::{Target, TargetOptions};
 // 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
@@ -16,11 +15,11 @@ pub fn target() -> Target {
         // Most of these settings are copied from the armv7_unknown_linux_gnueabihf
         // target.
         options: TargetOptions {
+            abi: "eabihf".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}mcount".to_string(),
-            ..base
+            ..super::linux_musl_base::opts()
         },
     }
 }
index 4fae3a8d0bf45b8060554d332734960e36b40bcb..60a552b018d69fab91a9f49a0056deefd82dc842 100644 (file)
@@ -1,20 +1,19 @@
 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 {
+            abi: "eabihf".to_string(),
+            // FIXME: remove env when cfg_target_abi becomes stable
             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..27d404b101f3a4de12b5e7625a5d1cdd40c52526 100644 (file)
@@ -1,18 +1,17 @@
 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,
         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 {
+            abi: "eabihf".to_string(),
             // 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..8bff60e9ed99a64f5f4ca87f7558ac4222441b8c 100644 (file)
@@ -18,6 +18,7 @@ use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOp
 
 pub fn target() -> Target {
     let opts = TargetOptions {
+        abi: "eabi".to_string(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
         linker: Some("rust-lld".to_owned()),
         features: "+v7,+thumb2,+soft-float,-neon,+strict-align".to_string(),
@@ -26,7 +27,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..ea2751e375e0b6078145c92c34fff2e1372d50d9 100644 (file)
@@ -9,6 +9,7 @@ use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOp
 
 pub fn target() -> Target {
     let opts = TargetOptions {
+        abi: "eabihf".to_string(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
         linker: Some("rust-lld".to_owned()),
         features: "+v7,+vfp3,-d32,+thumb2,-neon,+strict-align".to_string(),
@@ -17,7 +18,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..c695542805599b00a40a63f02a2e157c6043b8f3 100644 (file)
@@ -11,13 +11,13 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
 
         options: TargetOptions {
+            abi: "eabi".to_string(),
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
             executables: true,
             linker: Some("rust-lld".to_owned()),
             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..50c37021b74e9b9b93529e15e656999741d5080f 100644 (file)
@@ -11,6 +11,7 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
 
         options: TargetOptions {
+            abi: "eabihf".to_string(),
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
             executables: true,
             linker: Some("rust-lld".to_owned()),
@@ -18,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 be74136a2d67596a577d0142d9eb7bcdf568d574..2a48e7b62143f0b4268213270488c6f3cb04eeb7 100644 (file)
@@ -2,7 +2,6 @@ use super::apple_sdk_base::{opts, Arch};
 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 bef2fce7c839bcbe357f29bfa2e83d5bee3af9c9..998d6ffe0fc668652b9a2d65ac07d93df7aba1a0 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{RelroLevel, TargetOptions};
+use crate::spec::{FramePointer, RelroLevel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
@@ -8,7 +8,7 @@ pub fn opts() -> TargetOptions {
         families: vec!["unix".to_string()],
         has_rpath: true,
         position_independent_executables: true,
-        eliminate_frame_pointer: false, // FIXME 43575
+        frame_pointer: FramePointer::Always, // FIXME 43575: should be MayOmit...
         relro_level: RelroLevel::Full,
         abi_return_struct_as_int: true,
         dwarf_version: Some(2),
index 06d71db4af2410264730ccfae91177b2ac4f4b13..f2635f0656d7a738445df4d41d1dda6302f935ed 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
+use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::apple_base::opts("macos");
@@ -8,7 +8,7 @@ pub fn target() -> Target {
     base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
-    base.eliminate_frame_pointer = false;
+    base.frame_pointer = FramePointer::Always;
 
     // Clang automatically chooses a more specific target based on
     // MACOSX_DEPLOYMENT_TARGET.  To enable cross-language LTO to work
index 19d7b3c95cf6d3d53e9bd24b697fdbf85275ad50..640f9e42f4ab1c19ea5d990e1cc8559e4bb2ee72 100644 (file)
@@ -8,7 +8,7 @@ pub fn target() -> Target {
 
     base.max_atomic_width = Some(64);
 
-    // http://developer.android.com/ndk/guides/abis.html#x86
+    // https://developer.android.com/ndk/guides/abis.html#x86
     base.cpu = "pentiumpro".to_string();
     base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".to_string();
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
index 7002d88c512d77e104e125069406c28ee88205b1..92c3a1554ac544286cfe96d423ee023b8dd1e5e4 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, LldFlavor, Target};
+use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, Target};
 
 pub fn target() -> Target {
     let mut base = super::windows_gnu_base::opts();
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     base.pre_link_args
         .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]);
     base.max_atomic_width = Some(64);
-    base.eliminate_frame_pointer = false; // Required for backtraces
+    base.frame_pointer = FramePointer::Always; // Required for backtraces
     base.linker = Some("i686-w64-mingw32-gcc".to_string());
 
     // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
index 228976779f0d438e03d6e203a4af82c199b30425..d95cb6a82d558014b7fe66c66a4743747e4a27ed 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target};
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
@@ -21,7 +21,7 @@ pub fn target() -> Target {
     //
     // This may or may not be related to this bug:
     // https://llvm.org/bugs/show_bug.cgi?id=30879
-    base.eliminate_frame_pointer = false;
+    base.frame_pointer = FramePointer::Always;
 
     Target {
         llvm_target: "i686-unknown-linux-musl".to_string(),
index 426df59882d5810d9fab2a5186c9ea8212fd1565..27a0ac585e3919d052447ae396e032537458af75 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, LldFlavor, Target};
+use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, Target};
 
 pub fn target() -> Target {
     let mut base = super::windows_uwp_gnu_base::opts();
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     base.pre_link_args
         .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]);
     base.max_atomic_width = Some(64);
-    base.eliminate_frame_pointer = false; // Required for backtraces
+    base.frame_pointer = FramePointer::Always; // Required for backtraces
 
     // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
     // space available to x86 Windows binaries on x86_64.
index 9d9da50be7a27341d843f65fd1c3d01e45b46f2c..f598f0f38f305c866948831697fcaa2a01cccb12 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
+use crate::spec::{FramePointer, LinkArgs, LinkerFlavor, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
@@ -35,7 +35,7 @@ pub fn opts() -> TargetOptions {
         is_like_solaris: true,
         linker_is_gnu: false,
         limit_rdylib_exports: false, // Linker doesn't support this
-        eliminate_frame_pointer: false,
+        frame_pointer: FramePointer::Always,
         eh_frame_header: false,
         late_link_args,
 
index 145aa4a589443f8f946f0bf55217f5b832242db8..a332e3b847a2931af37b42fdb7da436a02157b7f 100644 (file)
@@ -1,4 +1,5 @@
-use crate::spec::{PanicStrategy, RelocModel, RelroLevel, StackProbeType, TargetOptions};
+use crate::spec::TargetOptions;
+use crate::spec::{FramePointer, PanicStrategy, RelocModel, RelroLevel, StackProbeType};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
@@ -7,7 +8,7 @@ pub fn opts() -> TargetOptions {
         panic_strategy: PanicStrategy::Abort,
         // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
         stack_probes: StackProbeType::Call,
-        eliminate_frame_pointer: false,
+        frame_pointer: FramePointer::Always,
         position_independent_executables: true,
         needs_plt: true,
         relro_level: RelroLevel::Full,
index 53398539ac20f86019266c45276a8ebc3a1ef9e9..161a27ab6890b452edfe7ab5e53d0a7a626588ea 100644 (file)
@@ -8,6 +8,7 @@ pub fn target() -> Target {
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
         arch: "mips64".to_string(),
         options: TargetOptions {
+            abi: "abi64".to_string(),
             endian: Endian::Big,
             // NOTE(mips64r2) matches C toolchain
             cpu: "mips64r2".to_string(),
index 329fbd22721770d0b62560d7b4f6f0f5167f114d..a898464569813aacf43f76e8e7ed30131ec82740 100644 (file)
@@ -12,6 +12,11 @@ pub fn target() -> Target {
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
         arch: "mips64".to_string(),
-        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions {
+            abi: "abi64".to_string(),
+            endian: Endian::Big,
+            mcount: "_mcount".to_string(),
+            ..base
+        },
     }
 }
index d767705b0459b38c8b6c9c1a0c7d6359042deb4c..2f58560d45021944666871357b8fc472abe374a7 100644 (file)
@@ -7,6 +7,7 @@ pub fn target() -> Target {
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
         arch: "mips64".to_string(),
         options: TargetOptions {
+            abi: "abi64".to_string(),
             // NOTE(mips64r2) matches C toolchain
             cpu: "mips64r2".to_string(),
             features: "+mips64r2".to_string(),
index 766ed69df4bb8444ecb6ec8b4bedbcaa1ed0275b..01c34bc39924f1afdec9436a0d98f817471e2d30 100644 (file)
@@ -11,6 +11,6 @@ pub fn target() -> Target {
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
         arch: "mips64".to_string(),
-        options: TargetOptions { mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { abi: "abi64".to_string(), mcount: "_mcount".to_string(), ..base },
     }
 }
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 3bf837fbb411eff6e11ba5ad036753b865b72184..80a155a4865d7fc8b25781684e553cdc6a0bc10f 100644 (file)
@@ -8,6 +8,7 @@ pub fn target() -> Target {
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
         arch: "mips64".to_string(),
         options: TargetOptions {
+            abi: "abi64".to_string(),
             endian: Endian::Big,
             // NOTE(mips64r6) matches C toolchain
             cpu: "mips64r6".to_string(),
index 589d7acba68045f67f9d8b67b9bf52bbec49e667..58f9862715f73099b3881d86e202d756659ed3ed 100644 (file)
@@ -7,6 +7,7 @@ pub fn target() -> Target {
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
         arch: "mips64".to_string(),
         options: TargetOptions {
+            abi: "abi64".to_string(),
             // NOTE(mips64r6) matches C toolchain
             cpu: "mips64r6".to_string(),
             features: "+mips64r6".to_string(),
index 0f2aaeb533a97d3ed4b8a9d27750fdd8285ce28c..0185132ee3698efe85428487c0412ddef311ffe1 100644 (file)
@@ -25,7 +25,7 @@
 //!
 //! # Defining a new target
 //!
-//! Targets are defined using [JSON](http://json.org/). The `Target` struct in
+//! Targets are defined using [JSON](https://json.org/). The `Target` struct in
 //! this module defines the format the JSON file should take, though each
 //! underscore in the field names should be replaced with a hyphen (`-`) in the
 //! JSON file. Some fields are required in every target specification, such as
@@ -55,7 +55,6 @@ pub mod crt_objects;
 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 msvc_base;
 mod netbsd_base;
 mod openbsd_base;
 mod redox_base;
-mod riscv_base;
 mod solaris_base;
 mod thumb_base;
 mod uefi_msvc_base;
@@ -671,6 +669,42 @@ impl ToJson for SanitizerSet {
     }
 }
 
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum FramePointer {
+    /// Forces the machine code generator to always preserve the frame pointers.
+    Always,
+    /// Forces the machine code generator to preserve the frame pointers except for the leaf
+    /// functions (i.e. those that don't call other functions).
+    NonLeaf,
+    /// Allows the machine code generator to omit the frame pointers.
+    ///
+    /// This option does not guarantee that the frame pointers will be omitted.
+    MayOmit,
+}
+
+impl FromStr for FramePointer {
+    type Err = ();
+    fn from_str(s: &str) -> Result<Self, ()> {
+        Ok(match s {
+            "always" => Self::Always,
+            "non-leaf" => Self::NonLeaf,
+            "may-omit" => Self::MayOmit,
+            _ => return Err(()),
+        })
+    }
+}
+
+impl ToJson for FramePointer {
+    fn to_json(&self) -> Json {
+        match *self {
+            Self::Always => "always",
+            Self::NonLeaf => "non-leaf",
+            Self::MayOmit => "may-omit",
+        }
+        .to_json()
+    }
+}
+
 macro_rules! supported_targets {
     ( $(($( $triple:literal, )+ $module:ident ),)+ ) => {
         $(mod $module;)+
@@ -769,6 +803,7 @@ supported_targets! {
     ("armv7-unknown-freebsd", armv7_unknown_freebsd),
     ("i686-unknown-freebsd", i686_unknown_freebsd),
     ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
+    ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
     ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
 
     ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
@@ -905,6 +940,38 @@ supported_targets! {
     ("bpfel-unknown-none", bpfel_unknown_none),
 }
 
+/// Warnings encountered when parsing the target `json`.
+///
+/// Includes fields that weren't recognized and fields that don't have the expected type.
+#[derive(Debug, PartialEq)]
+pub struct TargetWarnings {
+    unused_fields: Vec<String>,
+    incorrect_type: Vec<String>,
+}
+
+impl TargetWarnings {
+    pub fn empty() -> Self {
+        Self { unused_fields: Vec::new(), incorrect_type: Vec::new() }
+    }
+
+    pub fn warning_messages(&self) -> Vec<String> {
+        let mut warnings = vec![];
+        if !self.unused_fields.is_empty() {
+            warnings.push(format!(
+                "target json file contains unused fields: {}",
+                self.unused_fields.join(", ")
+            ));
+        }
+        if !self.incorrect_type.is_empty() {
+            warnings.push(format!(
+                "target json file contains fields whose value doesn't have the correct json type: {}",
+                self.incorrect_type.join(", ")
+            ));
+        }
+        warnings
+    }
+}
+
 /// Everything `rustc` knows about how to compile for a specific target.
 ///
 /// Every field here must be specified, and has no default value.
@@ -917,7 +984,7 @@ pub struct Target {
     /// Architecture to use for ABI considerations. Valid options include: "x86",
     /// "x86_64", "arm", "aarch64", "mips", "powerpc", "powerpc64", and others.
     pub arch: String,
-    /// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
+    /// [Data layout](https://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
     pub data_layout: String,
     /// Optional settings with defaults.
     pub options: TargetOptions,
@@ -958,6 +1025,9 @@ pub struct TargetOptions {
     pub os: String,
     /// Environment name to use for conditional compilation (`target_env`). Defaults to "".
     pub env: String,
+    /// ABI name to distinguish multiple ABIs on the same OS and architecture. For instance, `"eabi"`
+    /// or `"eabihf"`. Defaults to "".
+    pub abi: String,
     /// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown".
     pub vendor: String,
     /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
@@ -1035,8 +1105,8 @@ pub struct TargetOptions {
     pub tls_model: TlsModel,
     /// Do not emit code that uses the "red zone", if the ABI has one. Defaults to false.
     pub disable_redzone: bool,
-    /// Eliminate frame pointers from stack frames if possible. Defaults to true.
-    pub eliminate_frame_pointer: bool,
+    /// Frame pointer mode for this target. Defaults to `MayOmit`.
+    pub frame_pointer: FramePointer,
     /// Emit each function in its own section. Defaults to true.
     pub function_sections: bool,
     /// String to prepend to the name of every dynamic library. Defaults to "lib".
@@ -1157,11 +1227,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.
@@ -1280,6 +1345,7 @@ impl Default for TargetOptions {
             c_int_width: "32".to_string(),
             os: "none".to_string(),
             env: String::new(),
+            abi: String::new(),
             vendor: "unknown".to_string(),
             linker_flavor: LinkerFlavor::Gcc,
             linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()),
@@ -1297,7 +1363,7 @@ impl Default for TargetOptions {
             code_model: None,
             tls_model: TlsModel::GeneralDynamic,
             disable_redzone: false,
-            eliminate_frame_pointer: true,
+            frame_pointer: FramePointer::MayOmit,
             function_sections: true,
             dll_prefix: "lib".to_string(),
             dll_suffix: ".so".to_string(),
@@ -1343,7 +1409,6 @@ impl Default for 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,
@@ -1396,40 +1461,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 {
@@ -1442,12 +1555,8 @@ impl Target {
         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(obj: Json) -> Result<Target, String> {
+    pub fn from_json(mut obj: Json) -> Result<(Target, TargetWarnings), String> {
         // While ugly, this code must remain this way to retain
         // compatibility with existing JSON fields and the internal
         // expected naming of the Target and TargetOptions structs.
@@ -1455,10 +1564,9 @@ impl Target {
         // are round-tripped through this code to catch cases where
         // the JSON parser is not updated to match the structs.
 
-        let get_req_field = |name: &str| {
-            obj.find(name)
-                .and_then(Json::as_string)
-                .map(str::to_string)
+        let mut get_req_field = |name: &str| {
+            obj.remove_key(name)
+                .and_then(|j| Json::as_string(&j).map(str::to_string))
                 .ok_or_else(|| format!("Field {} in target specification is required", name))
         };
 
@@ -1472,28 +1580,30 @@ impl Target {
             options: Default::default(),
         };
 
+        let mut incorrect_type = vec![];
+
         macro_rules! key {
             ($key_name:ident) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(s) = obj.find(&name).and_then(Json::as_string) {
-                    base.$key_name = s.to_string();
+                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_string(&j).map(str::to_string)) {
+                    base.$key_name = s;
                 }
             } );
             ($key_name:ident = $json_name:expr) => ( {
                 let name = $json_name;
-                if let Some(s) = obj.find(&name).and_then(Json::as_string) {
-                    base.$key_name = s.to_string();
+                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_string(&j).map(str::to_string)) {
+                    base.$key_name = s;
                 }
             } );
             ($key_name:ident, bool) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(s) = obj.find(&name).and_then(Json::as_boolean) {
+                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_boolean(&j)) {
                     base.$key_name = s;
                 }
             } );
             ($key_name:ident, Option<u32>) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(s) = obj.find(&name).and_then(Json::as_u64) {
+                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
                     if s < 1 || s > 5 {
                         return Err("Not a valid DWARF version number".to_string());
                     }
@@ -1502,13 +1612,13 @@ impl Target {
             } );
             ($key_name:ident, Option<u64>) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(s) = obj.find(&name).and_then(Json::as_u64) {
+                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
                     base.$key_name = Some(s);
                 }
             } );
             ($key_name:ident, MergeFunctions) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s.parse::<MergeFunctions>() {
                         Ok(mergefunc) => base.$key_name = mergefunc,
                         _ => return Some(Err(format!("'{}' is not a valid value for \
@@ -1521,7 +1631,7 @@ impl Target {
             } );
             ($key_name:ident, RelocModel) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s.parse::<RelocModel>() {
                         Ok(relocation_model) => base.$key_name = relocation_model,
                         _ => return Some(Err(format!("'{}' is not a valid relocation model. \
@@ -1533,7 +1643,7 @@ impl Target {
             } );
             ($key_name:ident, CodeModel) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s.parse::<CodeModel>() {
                         Ok(code_model) => base.$key_name = Some(code_model),
                         _ => return Some(Err(format!("'{}' is not a valid code model. \
@@ -1545,7 +1655,7 @@ impl Target {
             } );
             ($key_name:ident, TlsModel) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s.parse::<TlsModel>() {
                         Ok(tls_model) => base.$key_name = tls_model,
                         _ => return Some(Err(format!("'{}' is not a valid TLS model. \
@@ -1557,7 +1667,7 @@ impl Target {
             } );
             ($key_name:ident, PanicStrategy) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s {
                         "unwind" => base.$key_name = PanicStrategy::Unwind,
                         "abort" => base.$key_name = PanicStrategy::Abort,
@@ -1570,7 +1680,7 @@ impl Target {
             } );
             ($key_name:ident, RelroLevel) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s.parse::<RelroLevel>() {
                         Ok(level) => base.$key_name = level,
                         _ => return Some(Err(format!("'{}' is not a valid value for \
@@ -1582,7 +1692,7 @@ impl Target {
             } );
             ($key_name:ident, SplitDebuginfo) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s.parse::<SplitDebuginfo>() {
                         Ok(level) => base.$key_name = level,
                         _ => return Some(Err(format!("'{}' is not a valid value for \
@@ -1594,23 +1704,31 @@ impl Target {
             } );
             ($key_name:ident, list) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(v) = obj.find(&name).and_then(Json::as_array) {
-                    base.$key_name = v.iter()
-                        .map(|a| a.as_string().unwrap().to_string())
-                        .collect();
+                if let Some(j) = obj.remove_key(&name){
+                    if let Some(v) = Json::as_array(&j) {
+                        base.$key_name = v.iter()
+                            .map(|a| a.as_string().unwrap().to_string())
+                            .collect();
+                    } else {
+                        incorrect_type.push(name)
+                    }
                 }
             } );
             ($key_name:ident, opt_list) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(v) = obj.find(&name).and_then(Json::as_array) {
-                    base.$key_name = Some(v.iter()
-                        .map(|a| a.as_string().unwrap().to_string())
-                        .collect());
+                if let Some(j) = obj.remove_key(&name) {
+                    if let Some(v) = Json::as_array(&j) {
+                        base.$key_name = Some(v.iter()
+                            .map(|a| a.as_string().unwrap().to_string())
+                            .collect());
+                    } else {
+                        incorrect_type.push(name)
+                    }
                 }
             } );
             ($key_name:ident, optional) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(o) = obj.find(&name[..]) {
+                if let Some(o) = obj.remove_key(&name[..]) {
                     base.$key_name = o
                         .as_string()
                         .map(|s| s.to_string() );
@@ -1618,7 +1736,7 @@ impl Target {
             } );
             ($key_name:ident, LldFlavor) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     if let Some(flavor) = LldFlavor::from_str(&s) {
                         base.$key_name = flavor;
                     } else {
@@ -1632,7 +1750,7 @@ impl Target {
             } );
             ($key_name:ident, LinkerFlavor) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match LinkerFlavor::from_str(s) {
                         Some(linker_flavor) => base.$key_name = linker_flavor,
                         _ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \
@@ -1643,7 +1761,7 @@ impl Target {
             } );
             ($key_name:ident, StackProbeType) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| match StackProbeType::from_json(o) {
+                obj.remove_key(&name[..]).and_then(|o| match StackProbeType::from_json(&o) {
                     Ok(v) => {
                         base.$key_name = v;
                         Some(Ok(()))
@@ -1655,25 +1773,29 @@ impl Target {
             } );
             ($key_name:ident, SanitizerSet) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_array()).and_then(|a| {
-                    for s in a {
-                        base.$key_name |= match s.as_string() {
-                            Some("address") => SanitizerSet::ADDRESS,
-                            Some("leak") => SanitizerSet::LEAK,
-                            Some("memory") => SanitizerSet::MEMORY,
-                            Some("thread") => SanitizerSet::THREAD,
-                            Some("hwaddress") => SanitizerSet::HWADDRESS,
-                            Some(s) => return Some(Err(format!("unknown sanitizer {}", s))),
-                            _ => return Some(Err(format!("not a string: {:?}", s))),
-                        };
+                if let Some(o) = obj.remove_key(&name[..]) {
+                    if let Some(a) = o.as_array() {
+                        for s in a {
+                            base.$key_name |= match s.as_string() {
+                                Some("address") => SanitizerSet::ADDRESS,
+                                Some("leak") => SanitizerSet::LEAK,
+                                Some("memory") => SanitizerSet::MEMORY,
+                                Some("thread") => SanitizerSet::THREAD,
+                                Some("hwaddress") => SanitizerSet::HWADDRESS,
+                                Some(s) => return Err(format!("unknown sanitizer {}", s)),
+                                _ => return Err(format!("not a string: {:?}", s)),
+                            };
+                        }
+                    } else {
+                        incorrect_type.push(name)
                     }
-                    Some(Ok(()))
-                }).unwrap_or(Ok(()))
+                }
+                Ok::<(), String>(())
             } );
 
             ($key_name:ident, crt_objects_fallback) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s.parse::<CrtObjectsFallback>() {
                         Ok(fallback) => base.$key_name = Some(fallback),
                         _ => return Some(Err(format!("'{}' is not a valid CRT objects fallback. \
@@ -1684,7 +1806,7 @@ impl Target {
             } );
             ($key_name:ident, link_objects) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(val) = obj.find(&name[..]) {
+                if let Some(val) = obj.remove_key(&name[..]) {
                     let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
                         JSON object with fields per CRT object kind.", name))?;
                     let mut args = CrtObjects::new();
@@ -1712,7 +1834,7 @@ impl Target {
             } );
             ($key_name:ident, link_args) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(val) = obj.find(&name[..]) {
+                if let Some(val) = obj.remove_key(&name[..]) {
                     let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
                         JSON object with fields per linker-flavor.", name))?;
                     let mut args = LinkArgs::new();
@@ -1739,22 +1861,26 @@ impl Target {
             } );
             ($key_name:ident, env) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(a) = obj.find(&name[..]).and_then(|o| o.as_array()) {
-                    for o in a {
-                        if let Some(s) = o.as_string() {
-                            let p = s.split('=').collect::<Vec<_>>();
-                            if p.len() == 2 {
-                                let k = p[0].to_string();
-                                let v = p[1].to_string();
-                                base.$key_name.push((k, v));
+                if let Some(o) = obj.remove_key(&name[..]) {
+                    if let Some(a) = o.as_array() {
+                        for o in a {
+                            if let Some(s) = o.as_string() {
+                                let p = s.split('=').collect::<Vec<_>>();
+                                if p.len() == 2 {
+                                    let k = p[0].to_string();
+                                    let v = p[1].to_string();
+                                    base.$key_name.push((k, v));
+                                }
                             }
                         }
+                    } else {
+                        incorrect_type.push(name)
                     }
                 }
             } );
             ($key_name:ident, Option<Abi>) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match lookup_abi(s) {
                         Some(abi) => base.$key_name = Some(abi),
                         _ => return Some(Err(format!("'{}' is not a valid value for abi", s))),
@@ -1763,24 +1889,41 @@ impl Target {
                 })).unwrap_or(Ok(()))
             } );
             ($key_name:ident, TargetFamilies) => ( {
-                let value = obj.find("target-family");
-                if let Some(v) = value.and_then(Json::as_array) {
-                    base.$key_name = v.iter()
-                        .map(|a| a.as_string().unwrap().to_string())
-                        .collect();
-                } else if let Some(v) = value.and_then(Json::as_string) {
-                    base.$key_name = vec![v.to_string()];
+                if let Some(value) = obj.remove_key("target-family") {
+                    if let Some(v) = Json::as_array(&value) {
+                        base.$key_name = v.iter()
+                            .map(|a| a.as_string().unwrap().to_string())
+                            .collect();
+                    } else if let Some(v) = Json::as_string(&value) {
+                        base.$key_name = vec![v.to_string()];
+                    }
                 }
             } );
         }
 
-        if let Some(s) = obj.find("target-endian").and_then(Json::as_string) {
-            base.endian = s.parse()?;
+        if let Some(j) = obj.remove_key("target-endian") {
+            if let Some(s) = Json::as_string(&j) {
+                base.endian = s.parse()?;
+            } else {
+                incorrect_type.push("target-endian".to_string())
+            }
         }
+
+        if let Some(fp) = obj.remove_key("frame-pointer") {
+            if let Some(s) = Json::as_string(&fp) {
+                base.frame_pointer = s
+                    .parse()
+                    .map_err(|()| format!("'{}' is not a valid value for frame-pointer", s))?;
+            } else {
+                incorrect_type.push("frame-pointer".to_string())
+            }
+        }
+
         key!(is_builtin, bool);
         key!(c_int_width = "target-c-int-width");
         key!(os);
         key!(env);
+        key!(abi);
         key!(vendor);
         key!(linker_flavor, LinkerFlavor)?;
         key!(linker, optional);
@@ -1808,7 +1951,6 @@ impl Target {
         key!(code_model, CodeModel)?;
         key!(tls_model, TlsModel)?;
         key!(disable_redzone, bool);
-        key!(eliminate_frame_pointer, bool);
         key!(function_sections, bool);
         key!(dll_prefix);
         key!(dll_suffix);
@@ -1873,35 +2015,16 @@ impl Target {
         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(array) = obj.find(name).and_then(Json::as_array) {
-                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
-                            ));
-                        }
-                    }
-                }
-            }
+        if base.is_builtin {
+            // This can cause unfortunate ICEs later down the line.
+            return Err(format!("may not set is_builtin for targets not built-in"));
         }
-
-        Ok(base)
+        // 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((
+            base,
+            TargetWarnings { unused_fields: remaining_keys.cloned().collect(), incorrect_type },
+        ))
     }
 
     /// Search for a JSON file specifying the given target triple.
@@ -1913,12 +2036,15 @@ impl Target {
     ///
     /// The error string could come from any of the APIs called, including filesystem access and
     /// JSON decoding.
-    pub fn search(target_triple: &TargetTriple, sysroot: &PathBuf) -> Result<Target, String> {
+    pub fn search(
+        target_triple: &TargetTriple,
+        sysroot: &PathBuf,
+    ) -> Result<(Target, TargetWarnings), String> {
         use rustc_serialize::json;
         use std::env;
         use std::fs;
 
-        fn load_file(path: &Path) -> Result<Target, String> {
+        fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
             let contents = fs::read(path).map_err(|e| e.to_string())?;
             let obj = json::from_reader(&mut &contents[..]).map_err(|e| e.to_string())?;
             Target::from_json(obj)
@@ -1928,7 +2054,7 @@ impl Target {
             TargetTriple::TargetTriple(ref target_triple) => {
                 // check if triple is in list of built-in targets
                 if let Some(t) = load_builtin(target_triple) {
-                    return Ok(t);
+                    return Ok((t, TargetWarnings::empty()));
                 }
 
                 // search for a file named `target_triple`.json in RUST_TARGET_PATH
@@ -2035,6 +2161,7 @@ impl ToJson for Target {
         target_option_val!(c_int_width, "target-c-int-width");
         target_option_val!(os);
         target_option_val!(env);
+        target_option_val!(abi);
         target_option_val!(vendor);
         target_option_val!(linker_flavor);
         target_option_val!(linker);
@@ -2062,7 +2189,7 @@ impl ToJson for Target {
         target_option_val!(code_model);
         target_option_val!(tls_model);
         target_option_val!(disable_redzone);
-        target_option_val!(eliminate_frame_pointer);
+        target_option_val!(frame_pointer);
         target_option_val!(function_sections);
         target_option_val!(dll_prefix);
         target_option_val!(dll_suffix);
@@ -2130,17 +2257,6 @@ impl ToJson for Target {
             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 29b415e77266e24a1da42ba7cf317e5a3d3b910b..70e9e4aed92495605b2bf338b69a35099b43176e 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{RelroLevel, TargetOptions};
+use crate::spec::{FramePointer, RelroLevel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
@@ -9,7 +9,7 @@ pub fn opts() -> TargetOptions {
         has_rpath: true,
         abi_return_struct_as_int: true,
         position_independent_executables: true,
-        eliminate_frame_pointer: false, // FIXME 43575
+        frame_pointer: FramePointer::Always, // FIXME 43575: should be MayOmit...
         relro_level: RelroLevel::Full,
         dwarf_version: Some(2),
         ..Default::default()
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
new file mode 100644 (file)
index 0000000..283e9f7
--- /dev/null
@@ -0,0 +1,16 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+    let mut base = super::freebsd_base::opts();
+    base.cpu = "ppc64le".to_string();
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.max_atomic_width = Some(64);
+
+    Target {
+        llvm_target: "powerpc64le-unknown-freebsd".to_string(),
+        pointer_width: 64,
+        data_layout: "e-m:e-i64:64-n32:64".to_string(),
+        arch: "powerpc64".to_string(),
+        options: TargetOptions { mcount: "_mcount".to_string(), ..base },
+    }
+}
index 8d8f746f97f121d2f9838815ad214a385fad9606..362d8a104e448d5b89f8613167902592eff8bd32 100644 (file)
@@ -11,6 +11,11 @@ pub fn target() -> Target {
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
-        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions {
+            abi: "spe".to_string(),
+            endian: Endian::Big,
+            mcount: "_mcount".to_string(),
+            ..base
+        },
     }
 }
index 215f1a36227d79571181aa2739c3ef987d0f03f6..a2b85f7dd869afc4c4ff1b6f1b0874a17e6b49fe 100644 (file)
@@ -13,6 +13,7 @@ pub fn target() -> Target {
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
         options: TargetOptions {
+            abi: "spe".to_string(),
             endian: Endian::Big,
             // feature msync would disable instruction 'fsync' which is not supported by fsl_p1p2
             features: "+secure-plt,+msync".to_string(),
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 f4de8bc0a5803ba9596a532a47373ea09d65e4c6..6730319dcfae24bdffee5968fc43c36bebd8bd60 100644 (file)
@@ -3,7 +3,7 @@ use super::super::*;
 // Test target self-consistency and JSON encoding/decoding roundtrip.
 pub(super) fn test_target(target: Target) {
     target.check_consistency();
-    assert_eq!(Target::from_json(target.to_json()), Ok(target));
+    assert_eq!(Target::from_json(target.to_json()).map(|(j, _)| j), Ok(target));
 }
 
 impl Target {
index ec24807fec4ea407e6ef5aed01f7d6fd1d8046cf..bac1203980eb010720829fe3570be0bcb8a20497 100644 (file)
@@ -27,7 +27,8 @@
 // differentiate these targets from our other `arm(v7)-*-*-gnueabi(hf)` targets in the context of
 // build scripts / gcc flags.
 
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions};
+use crate::spec::TargetOptions;
+use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
 
 pub fn opts() -> TargetOptions {
     // See rust-lang/rfcs#1645 for a discussion about these defaults
@@ -42,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
@@ -52,7 +52,7 @@ pub fn opts() -> TargetOptions {
         emit_debug_gdb_scripts: false,
         // LLVM is eager to trash the link register when calling `noreturn` functions, which
         // breaks debugging. Preserve LR by default to prevent that from happening.
-        eliminate_frame_pointer: false,
+        frame_pointer: FramePointer::Always,
         ..Default::default()
     }
 }
index f996009f830633a15e3865641aa7a3c6b597063e..f86efd5d0f49081c7f0466f4cec7b643b0ad30e5 100644 (file)
@@ -26,6 +26,7 @@ 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(),
         options: TargetOptions {
+            abi: "eabi".to_string(),
             linker_flavor: LinkerFlavor::Ld,
             linker: Some("arm-none-eabi-ld".to_string()),
 
index 11c8bf46348738ed19fd75c389590771381b5877..40e3281060f9fa9f6608a9461cb915e33c1e8c78 100644 (file)
@@ -10,6 +10,7 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
 
         options: TargetOptions {
+            abi: "eabi".to_string(),
             // The ARMv6-M architecture doesn't support unaligned loads/stores so we disable them
             // with +strict-align.
             features: "+strict-align".to_string(),
index 1232daa577f233a3a1dfe430c108d6e105dbb3f2..369e6cd5e9326e4b85086bb0663d4e359dfea6aa 100644 (file)
@@ -2,7 +2,6 @@ use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions}
 
 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 141eb7e78b9e4902f6227273fe0db3f507448090..107474a86bbb28c496fc96d4e84afee42e0adc6c 100644 (file)
@@ -18,6 +18,10 @@ 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 { max_atomic_width: Some(32), ..super::thumb_base::opts() },
+        options: TargetOptions {
+            abi: "eabi".to_string(),
+            max_atomic_width: Some(32),
+            ..super::thumb_base::opts()
+        },
     }
 }
index f5bd054f8598ca61ba69e1a1e91b4167fe24ed0c..65fc0db65285d8b936ceea752ff0d3e5dd0f50da 100644 (file)
@@ -18,6 +18,7 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
 
         options: TargetOptions {
+            abi: "eabihf".to_string(),
             // `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the
             // Cortex-M7 (vfp5)
             // `-d32` both the Cortex-M4 and the Cortex-M7 only have 16 double-precision registers
index 7af28cd9c9f9b9a2d001a1fde3369663a8fea099..ff939348c35f3aad006c06698a350dccd2df2d04 100644 (file)
@@ -9,6 +9,10 @@ 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 { max_atomic_width: Some(32), ..super::thumb_base::opts() },
+        options: TargetOptions {
+            abi: "eabi".to_string(),
+            max_atomic_width: Some(32),
+            ..super::thumb_base::opts()
+        },
     }
 }
index 58b0a9d22027999b5ebaab29ef48df5b164ac15e..fcb7b5d718cfbc8b7406446a549be51ea75feadc 100644 (file)
@@ -10,15 +10,17 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 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 {
+            abi: "eabi".to_string(),
+            features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(),
+            max_atomic_width: Some(64),
+            ..base
+        },
     }
 }
index 12d816d095b689e1ce92db232ec7b85aa30f8d87..9d34d9ac874b0ee43d2369eb1aa0cb8a88074dba 100644 (file)
@@ -7,19 +7,17 @@ use crate::spec::{Target, TargetOptions};
 // 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 {
+            abi: "eabihf".to_string(),
             // 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..4e339cbd6be27e9a9129e2d1f3d0d36af5fe59ec 100644 (file)
@@ -7,7 +7,6 @@ use crate::spec::{Target, TargetOptions};
 // 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
@@ -20,11 +19,11 @@ pub fn target() -> Target {
         // Most of these settings are copied from the thumbv7neon_unknown_linux_gnueabihf
         // target.
         options: TargetOptions {
+            abi: "eabihf".to_string(),
             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 a2200bc64e7d1bc01972bed9928c017b4927cb71..ef0f52d21992c0fdebb2780919593102f4c5f12b 100644 (file)
@@ -10,6 +10,7 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
 
         options: TargetOptions {
+            abi: "eabi".to_string(),
             // ARMv8-M baseline doesn't support unaligned loads/stores so we disable them
             // with +strict-align.
             features: "+strict-align".to_string(),
index 67cdbab4860a3a6f469dfcbd7bb66eaaa465fd8b..dbd184debcb083f1d180b75cc8844bc64f42e0ba 100644 (file)
@@ -10,6 +10,10 @@ 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 { max_atomic_width: Some(32), ..super::thumb_base::opts() },
+        options: TargetOptions {
+            abi: "eabi".to_string(),
+            max_atomic_width: Some(32),
+            ..super::thumb_base::opts()
+        },
     }
 }
index 49748f5ec6da4e7f8091b8aeac5fed1be8774854..3caf705421c6d35d6bab3ed6499ad854a59d381a 100644 (file)
@@ -11,6 +11,7 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
 
         options: TargetOptions {
+            abi: "eabihf".to_string(),
             // If the Floating Point extension is implemented in the Cortex-M33
             // processor, the Cortex-M33 Technical Reference Manual states that
             // the FPU uses the FPv5 architecture, single-precision instructions
index 67d1be399b3f1f7141a8674f7676394f9830036a..86df816f10dc214d019700352596fdd6cef17f05 100644 (file)
@@ -25,6 +25,7 @@ pub fn opts() -> TargetOptions {
     late_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), mingw_libs);
 
     TargetOptions {
+        abi: "uwp".to_string(),
         vendor: "uwp".to_string(),
         executables: false,
         limit_rdylib_exports: false,
index b3fa5c22f98221127cf8b380e623d4eda5ce5241..7b56b468c28ed2a2050297f28775d36ba177fbea 100644 (file)
@@ -3,6 +3,7 @@ use crate::spec::{LinkerFlavor, LldFlavor, TargetOptions};
 pub fn opts() -> TargetOptions {
     let mut opts = super::windows_msvc_base::opts();
 
+    opts.abi = "uwp".to_string();
     opts.vendor = "uwp".to_string();
     let pre_link_args_msvc = vec!["/APPCONTAINER".to_string(), "mincore.lib".to_string()];
     opts.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone());
index dc7597fe7b2a15905b20421551c00a998b0344af..60fd42970c7d6c908ee152473841654081a9bf6d 100644 (file)
@@ -1,10 +1,11 @@
-use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions};
+use crate::spec::TargetOptions;
+use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, StackProbeType, Target};
 
 pub fn target() -> Target {
     let mut base = super::apple_base::opts("macos");
     base.cpu = "core2".to_string();
     base.max_atomic_width = Some(128); // core2 support cmpxchg16b
-    base.eliminate_frame_pointer = false;
+    base.frame_pointer = FramePointer::Always;
     base.pre_link_args.insert(
         LinkerFlavor::Gcc,
         vec!["-m64".to_string(), "-arch".to_string(), "x86_64".to_string()],
index 06eb33d8d82e97d1f2750c406d31ad4d8f103e1a..59cd56ebcd535eb8d0a00d2c3f99b7c4e5a87d4e 100644 (file)
@@ -55,6 +55,7 @@ pub fn target() -> Target {
         os: "unknown".into(),
         env: "sgx".into(),
         vendor: "fortanix".into(),
+        abi: "fortanix".into(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
         executables: true,
         linker: Some("rust-lld".to_owned()),
index 7b77ad668cd2ff4ec042d4e8e43839ed0f67ff65..1ffaa9b78c85ef6d7aae8e869f68d4965ef3fcb7 100644 (file)
@@ -3,6 +3,7 @@ use crate::spec::{LinkerFlavor, StackProbeType, Target};
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
     base.cpu = "x86-64".to_string();
+    base.abi = "x32".to_string();
     base.max_atomic_width = Some(64);
     base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mx32".to_string());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
index b7dcce5f895c8bd0a470b460bf47cdcd1bb495e0..be0e62bea0228055fd6be794f760415e48f4bf80 100644 (file)
@@ -5,7 +5,7 @@
 // The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with
 // LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features.
 
-use crate::spec::{CodeModel, Target};
+use crate::spec::Target;
 
 pub fn target() -> Target {
     let mut base = super::uefi_msvc_base::opts();
@@ -19,15 +19,11 @@ pub fn target() -> Target {
     // to leave these uninitialized, thus triggering exceptions if we make use of them. Which is
     // why we avoid them and instead use soft-floats. This is also what GRUB and friends did so
     // far.
+    //
     // If you initialize FP units yourself, you can override these flags with custom linker
     // arguments, thus giving you access to full MMX/SSE acceleration.
     base.features = "-mmx,-sse,+soft-float".to_string();
 
-    // UEFI systems run without a host OS, hence we cannot assume any code locality. We must tell
-    // LLVM to expect code to reference any address in the address-space. The "large" code-model
-    // places no locality-restrictions, so it fits well here.
-    base.code_model = Some(CodeModel::Large);
-
     Target {
         llvm_target: "x86_64-unknown-windows".to_string(),
         pointer_width: 64,
diff --git a/compiler/rustc_target/src/tests.rs b/compiler/rustc_target/src/tests.rs
new file mode 100644 (file)
index 0000000..3a737b3
--- /dev/null
@@ -0,0 +1,59 @@
+use crate::spec::Target;
+use rustc_serialize::json::Json;
+use std::str::FromStr;
+
+#[test]
+fn report_unused_fields() {
+    let json = Json::from_str(
+        r#"
+    {
+        "arch": "powerpc64",
+        "data-layout": "e-m:e-i64:64-n32:64",
+        "llvm-target": "powerpc64le-elf",
+        "target-pointer-width": "64",
+        "code-mode": "foo"
+    }
+    "#,
+    )
+    .unwrap();
+    let warnings = Target::from_json(json).unwrap().1;
+    assert_eq!(warnings.warning_messages().len(), 1);
+    assert!(warnings.warning_messages().join("\n").contains("code-mode"));
+}
+
+#[test]
+fn report_incorrect_json_type() {
+    let json = Json::from_str(
+        r#"
+    {
+        "arch": "powerpc64",
+        "data-layout": "e-m:e-i64:64-n32:64",
+        "llvm-target": "powerpc64le-elf",
+        "target-pointer-width": "64",
+        "link-env-remove": "foo"
+    }
+    "#,
+    )
+    .unwrap();
+    let warnings = Target::from_json(json).unwrap().1;
+    assert_eq!(warnings.warning_messages().len(), 1);
+    assert!(warnings.warning_messages().join("\n").contains("link-env-remove"));
+}
+
+#[test]
+fn no_warnings_for_valid_target() {
+    let json = Json::from_str(
+        r#"
+    {
+        "arch": "powerpc64",
+        "data-layout": "e-m:e-i64:64-n32:64",
+        "llvm-target": "powerpc64le-elf",
+        "target-pointer-width": "64",
+        "link-env-remove": ["foo"]
+    }
+    "#,
+    )
+    .unwrap();
+    let warnings = Target::from_json(json).unwrap().1;
+    assert_eq!(warnings.warning_messages().len(), 0);
+}
index ac2e0ebae32732cbe778c6e4896ffd30b5987a4c..969962e55b0df3e4fb963572e1e3e8b06b321da2 100644 (file)
@@ -53,7 +53,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
         }
 
         // 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 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
 
 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..ea074192d23b14262f97d2455e783b6978552bbb 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};
 
@@ -25,15 +30,28 @@ pub trait InferCtxtExt<'tcx> {
 
     fn partially_normalize_associated_types_in<T>(
         &self,
-        span: Span,
-        body_id: hir::HirId,
+        cause: ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         value: 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,
@@ -60,8 +78,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
     /// new obligations that must further be processed.
     fn partially_normalize_associated_types_in<T>(
         &self,
-        span: Span,
-        body_id: hir::HirId,
+        cause: ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         value: T,
     ) -> InferOk<'tcx, T>
@@ -70,7 +87,6 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
     {
         debug!("partially_normalize_associated_types_in(value={:?})", value);
         let mut selcx = traits::SelectionContext::new(self);
-        let cause = ObligationCause::misc(span, body_id);
         let traits::Normalized { value, obligations } =
             traits::normalize(&mut selcx, param_env, cause, value);
         debug!(
@@ -79,6 +95,30 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
         );
         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 89ec211f2627bcadf4ec47f8eb14e5095e71aa2b..95c81c5c729be5be29ea0fafb84f7d5c66242d19 100644 (file)
@@ -1,11 +1,10 @@
 use crate::infer::InferCtxtExt as _;
-use crate::traits::{self, PredicateObligation};
+use crate::traits::{self, ObligationCause, PredicateObligation};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::vec_map::VecMap;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::Node;
 use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
 use rustc_infer::infer::free_regions::FreeRegionRelations;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -84,6 +83,7 @@ pub struct OpaqueTypeDecl<'tcx> {
 }
 
 /// Whether member constraints should be generated for all opaque types
+#[derive(Debug)]
 pub enum GenerateMemberConstraints {
     /// The default, used by typeck
     WhenRequired,
@@ -355,8 +355,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         opaque_types: &OpaqueTypeMap<'tcx>,
         free_region_relations: &FRR,
     ) {
-        debug!("constrain_opaque_types()");
-
         for &(opaque_type_key, opaque_defn) in opaque_types {
             self.constrain_opaque_type(
                 opaque_type_key,
@@ -368,6 +366,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     }
 
     /// See `constrain_opaque_types` for documentation.
+    #[instrument(level = "debug", skip(self, free_region_relations))]
     fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
         &self,
         opaque_type_key: OpaqueTypeKey<'tcx>,
@@ -377,15 +376,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     ) {
         let def_id = opaque_type_key.def_id;
 
-        debug!("constrain_opaque_type()");
-        debug!("constrain_opaque_type: def_id={:?}", def_id);
-        debug!("constrain_opaque_type: opaque_defn={:#?}", opaque_defn);
-
         let tcx = self.tcx;
 
         let concrete_ty = self.resolve_vars_if_possible(opaque_defn.concrete_ty);
 
-        debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty);
+        debug!(?concrete_ty);
 
         let first_own_region = match opaque_defn.origin {
             hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => {
@@ -398,14 +393,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 // type foo::<'p0..'pn>::Foo<'q0..'qm>
                 // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
                 //
-                // For these types we onlt iterate over `'l0..lm` below.
+                // For these types we only iterate over `'l0..lm` below.
                 tcx.generics_of(def_id).parent_count
             }
             // These opaque type inherit all lifetime parameters from their
             // parent, so we have to check them all.
-            hir::OpaqueTyOrigin::Binding
-            | hir::OpaqueTyOrigin::TyAlias
-            | hir::OpaqueTyOrigin::Misc => 0,
+            hir::OpaqueTyOrigin::TyAlias => 0,
         };
 
         let span = tcx.def_span(def_id);
@@ -413,10 +406,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         // If there are required region bounds, we can use them.
         if opaque_defn.has_required_region_bounds {
             let bounds = tcx.explicit_item_bounds(def_id);
-            debug!("constrain_opaque_type: predicates: {:#?}", bounds);
+            debug!("{:#?}", bounds);
             let bounds: Vec<_> =
                 bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_type_key.substs)).collect();
-            debug!("constrain_opaque_type: bounds={:#?}", bounds);
+            debug!("{:#?}", bounds);
             let opaque_type = tcx.mk_opaque(def_id, opaque_type_key.substs);
 
             let required_region_bounds =
@@ -455,8 +448,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             };
 
             // Compute the least upper bound of it with the other regions.
-            debug!("constrain_opaque_types: least_region={:?}", least_region);
-            debug!("constrain_opaque_types: subst_region={:?}", subst_region);
+            debug!(?least_region);
+            debug!(?subst_region);
             match least_region {
                 None => least_region = Some(subst_region),
                 Some(lr) => {
@@ -487,7 +480,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         }
 
         let least_region = least_region.unwrap_or(tcx.lifetimes.re_static);
-        debug!("constrain_opaque_types: least_region={:?}", least_region);
+        debug!(?least_region);
 
         if let GenerateMemberConstraints::IfNoStaticBound = mode {
             if least_region != tcx.lifetimes.re_static {
@@ -569,6 +562,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     /// - `substs`, the substs  used to instantiate this opaque type
     /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
     ///   `opaque_defn.concrete_ty`
+    #[instrument(skip(self))]
     fn infer_opaque_definition_from_instantiation(
         &self,
         opaque_type_key: OpaqueTypeKey<'tcx>,
@@ -577,11 +571,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     ) -> Ty<'tcx> {
         let OpaqueTypeKey { def_id, substs } = opaque_type_key;
 
-        debug!(
-            "infer_opaque_definition_from_instantiation(def_id={:?}, instantiated_ty={:?})",
-            def_id, instantiated_ty
-        );
-
         // Use substs to build up a reverse map from regions to their
         // identity mappings. This is necessary because of `impl
         // Trait` lifetimes are computed by replacing existing
@@ -589,6 +578,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         // `impl Trait` return type, resulting in the parameters
         // shifting.
         let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
+        debug!(?id_substs);
         let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
             substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect();
 
@@ -603,7 +593,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             instantiated_ty,
             span,
         ));
-        debug!("infer_opaque_definition_from_instantiation: definition_ty={:?}", definition_ty);
+        debug!(?definition_ty);
 
         definition_ty
     }
@@ -858,7 +848,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
                 self.tcx.mk_generator(def_id, substs, movability)
             }
 
-            ty::Param(..) => {
+            ty::Param(param) => {
                 // Look it up in the substitution list.
                 match self.map.get(&ty.into()).map(|k| k.unpack()) {
                     // Found it in the substitution list; replace with the parameter from the
@@ -866,6 +856,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
                     Some(GenericArgKind::Type(t1)) => t1,
                     Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
                     None => {
+                        debug!(?param, ?self.map);
                         self.tcx
                             .sess
                             .struct_span_err(
@@ -932,8 +923,8 @@ struct Instantiator<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Instantiator<'a, 'tcx> {
+    #[instrument(skip(self))]
     fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
-        debug!("instantiate_opaque_types_in_map(value={:?})", value);
         let tcx = self.infcx.tcx;
         value.fold_with(&mut BottomUpFolder {
             tcx,
@@ -982,8 +973,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
                             let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
                             parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
                         };
-                        let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) {
-                            Some(Node::Item(item)) => match item.kind {
+                        let (in_definition_scope, origin) =
+                            match tcx.hir().expect_item(opaque_hir_id).kind {
                                 // Anonymous `impl Trait`
                                 hir::ItemKind::OpaqueTy(hir::OpaqueTy {
                                     impl_trait_fn: Some(parent),
@@ -999,13 +990,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
                                     may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id),
                                     origin,
                                 ),
-                                _ => (def_scope_default(), hir::OpaqueTyOrigin::Misc),
-                            },
-                            _ => bug!(
-                                "expected item, found {}",
-                                tcx.hir().node_to_string(opaque_hir_id),
-                            ),
-                        };
+                                _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias),
+                            };
                         if in_definition_scope {
                             let opaque_type_key =
                                 OpaqueTypeKey { def_id: def_id.to_def_id(), substs };
@@ -1057,8 +1043,11 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
             item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect();
 
         let param_env = tcx.param_env(def_id);
-        let InferOk { value: bounds, obligations } =
-            infcx.partially_normalize_associated_types_in(span, self.body_id, param_env, bounds);
+        let InferOk { value: bounds, obligations } = infcx.partially_normalize_associated_types_in(
+            ObligationCause::misc(span, self.body_id),
+            param_env,
+            bounds,
+        );
         self.obligations.extend(obligations);
 
         debug!("instantiate_opaque_types: bounds={:?}", bounds);
index 026ab414443a871677e094ee57faf397baa6b678..7a690af0cc6e5e78e49a3dfc645979438e41c6ce 100644 (file)
@@ -58,6 +58,9 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
                     obligation: obligation.clone(),
                     code: FulfillmentErrorCode::CodeAmbiguity,
                     points_at_arg_span: false,
+                    // FIXME - does Chalk have a notation of 'root obligation'?
+                    // This is just for diagnostics, so it's okay if this is wrong
+                    root_obligation: obligation.clone(),
                 })
                 .collect();
             Err(errors)
@@ -105,11 +108,14 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
                                 ),
 
                                 Err(_err) => errors.push(FulfillmentError {
-                                    obligation,
+                                    obligation: obligation.clone(),
                                     code: FulfillmentErrorCode::CodeSelectionError(
                                         SelectionError::Unimplemented,
                                     ),
                                     points_at_arg_span: false,
+                                    // FIXME - does Chalk have a notation of 'root obligation'?
+                                    // This is just for diagnostics, so it's okay if this is wrong
+                                    root_obligation: obligation,
                                 }),
                             }
                         } else {
@@ -119,11 +125,14 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
                     }
 
                     Err(NoSolution) => errors.push(FulfillmentError {
-                        obligation,
+                        obligation: obligation.clone(),
                         code: FulfillmentErrorCode::CodeSelectionError(
                             SelectionError::Unimplemented,
                         ),
                         points_at_arg_span: false,
+                        // FIXME - does Chalk have a notation of 'root obligation'?
+                        // This is just for diagnostics, so it's okay if this is wrong
+                        root_obligation: obligation,
                     }),
                 }
             }
index 8961cdaebf345eb26f497802ba12e40a8905079d..b1a938836b70ee1fff62cf28941327e124a5080e 100644 (file)
@@ -97,6 +97,16 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
 
                         ControlFlow::CONTINUE
                     }
+                    Node::Cast(_, _, ty) => {
+                        let ty = ty.subst(tcx, ct.substs);
+                        if ty.has_infer_types_or_consts() {
+                            failure_kind = FailureKind::MentionsInfer;
+                        } else if ty.has_param_types_or_consts() {
+                            failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
+                        }
+
+                        ControlFlow::CONTINUE
+                    }
                     Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => {
                         ControlFlow::CONTINUE
                     }
@@ -304,6 +314,9 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
                 self.nodes[func].used = true;
                 nodes.iter().for_each(|&n| self.nodes[n].used = true);
             }
+            Node::Cast(_, operand, _) => {
+                self.nodes[operand].used = true;
+            }
         }
 
         // Nodes start as unused.
@@ -408,11 +421,19 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
                         self.locals[local] = self.add_node(Node::UnaryOp(op, operand), span);
                         Ok(())
                     }
+                    Rvalue::Cast(cast_kind, ref operand, ty) => {
+                        let operand = self.operand_to_node(span, operand)?;
+                        self.locals[local] =
+                            self.add_node(Node::Cast(cast_kind, operand, ty), span);
+                        Ok(())
+                    }
                     _ => self.error(Some(span), "unsupported rvalue")?,
                 }
             }
             // These are not actually relevant for us here, so we can ignore them.
-            StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => Ok(()),
+            StatementKind::AscribeUserType(..)
+            | StatementKind::StorageLive(_)
+            | StatementKind::StorageDead(_) => Ok(()),
             _ => self.error(Some(stmt.source_info.span), "unsupported statement")?,
         }
     }
@@ -594,6 +615,7 @@ where
                 recurse(tcx, ct.subtree(func), f)?;
                 args.iter().try_for_each(|&arg| recurse(tcx, ct.subtree(arg), f))
             }
+            Node::Cast(_, operand, _) => recurse(tcx, ct.subtree(operand), f),
         }
     }
 
@@ -676,6 +698,11 @@ pub(super) fn try_unify<'tcx>(
                 && iter::zip(a_args, b_args)
                     .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn)))
         }
+        (Node::Cast(a_cast_kind, a_operand, a_ty), Node::Cast(b_cast_kind, b_operand, b_ty))
+            if (a_ty == b_ty) && (a_cast_kind == b_cast_kind) =>
+        {
+            try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand))
+        }
         _ => false,
     }
 }
index 19c3385dd4cbcbc119df5a9144fc0cf8a7eea2b0..713e06f91d3f934fe66d12ccb81332db8ca95359 100644 (file)
@@ -55,9 +55,13 @@ pub trait InferCtxtExt<'tcx> {
 
     fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
 
+    /// The `root_obligation` parameter should be the `root_obligation` field
+    /// from a `FulfillmentError`. If no `FulfillmentError` is available,
+    /// then it should be the same as `obligation`.
     fn report_selection_error(
         &self,
-        obligation: &PredicateObligation<'tcx>,
+        obligation: PredicateObligation<'tcx>,
+        root_obligation: &PredicateObligation<'tcx>,
         error: &SelectionError<'tcx>,
         fallback_has_occurred: bool,
         points_at_arg: bool,
@@ -225,16 +229,30 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 
     fn report_selection_error(
         &self,
-        obligation: &PredicateObligation<'tcx>,
+        mut obligation: PredicateObligation<'tcx>,
+        root_obligation: &PredicateObligation<'tcx>,
         error: &SelectionError<'tcx>,
         fallback_has_occurred: bool,
         points_at_arg: bool,
     ) {
         let tcx = self.tcx;
-        let span = obligation.cause.span;
+        let mut span = obligation.cause.span;
 
         let mut err = match *error {
             SelectionError::Unimplemented => {
+                // If this obligation was generated as a result of well-formed checking, see if we
+                // can get a better error message by performing HIR-based well formed checking.
+                if let ObligationCauseCode::WellFormed(Some(wf_loc)) =
+                    root_obligation.cause.code.peel_derives()
+                {
+                    if let Some(cause) = self.tcx.diagnostic_hir_wf_check((
+                        tcx.erase_regions(obligation.predicate),
+                        wf_loc.clone(),
+                    )) {
+                        obligation.cause = cause;
+                        span = obligation.cause.span;
+                    }
+                }
                 if let ObligationCauseCode::CompareImplMethodObligation {
                     item_name,
                     impl_item_def_id,
@@ -279,7 +297,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                             .unwrap_or_default();
 
                         let OnUnimplementedNote { message, label, note, enclosing_scope } =
-                            self.on_unimplemented_note(trait_ref, obligation);
+                            self.on_unimplemented_note(trait_ref, &obligation);
                         let have_alt_message = message.is_some() || label.is_some();
                         let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id());
                         let is_unsize =
@@ -338,7 +356,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                                     Applicability::MachineApplicable,
                                 );
                             }
-                            if let Some(ret_span) = self.return_type_span(obligation) {
+                            if let Some(ret_span) = self.return_type_span(&obligation) {
                                 err.span_label(
                                     ret_span,
                                     &format!(
@@ -368,7 +386,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                             points_at_arg,
                             have_alt_message,
                         ) {
-                            self.note_obligation_cause(&mut err, obligation);
+                            self.note_obligation_cause(&mut err, &obligation);
                             err.emit();
                             return;
                         }
@@ -514,6 +532,30 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                             }
                         }
 
+                        // Return early if the trait is Debug or Display and the invocation
+                        // originates within a standard library macro, because the output
+                        // is otherwise overwhelming and unhelpful (see #85844 for an
+                        // example).
+
+                        let trait_is_debug =
+                            self.tcx.is_diagnostic_item(sym::debug_trait, trait_ref.def_id());
+                        let trait_is_display =
+                            self.tcx.is_diagnostic_item(sym::display_trait, trait_ref.def_id());
+
+                        let in_std_macro =
+                            match obligation.cause.span.ctxt().outer_expn_data().macro_def_id {
+                                Some(macro_def_id) => {
+                                    let crate_name = tcx.crate_name(macro_def_id.krate);
+                                    crate_name == sym::std || crate_name == sym::core
+                                }
+                                None => false,
+                            };
+
+                        if in_std_macro && (trait_is_debug || trait_is_display) {
+                            err.emit();
+                            return;
+                        }
+
                         err
                     }
 
@@ -797,7 +839,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             }
         };
 
-        self.note_obligation_cause(&mut err, obligation);
+        self.note_obligation_cause(&mut err, &obligation);
         self.point_at_returns_when_relevant(&mut err, &obligation);
 
         err.emit();
@@ -1144,7 +1186,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
         match error.code {
             FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
                 self.report_selection_error(
-                    &error.obligation,
+                    error.obligation.clone(),
+                    &error.root_obligation,
                     selection_error,
                     fallback_has_occurred,
                     error.points_at_arg_span,
index 5c35b515f3d027f9ba60db1e4ab0a8e447699080..9a33875d6e493f293d9e1efb9c24004b2821681e 100644 (file)
@@ -28,6 +28,7 @@ use rustc_target::spec::abi;
 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 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             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 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 ty::TraitRef::new(trait_ref.def_id, imm_substs),
                 trait_ref,
                 false,
-                &blacklist[..],
+                &never_suggest_borrow[..],
             ) {
                 return true;
             } else {
@@ -805,7 +808,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     ty::TraitRef::new(trait_ref.def_id, mut_substs),
                     trait_ref,
                     true,
-                    &blacklist[..],
+                    &never_suggest_borrow[..],
                 );
             }
         } else {
@@ -1854,12 +1857,37 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 }
             }
             GeneratorInteriorOrUpvar::Upvar(upvar_span) => {
+                // `Some(ref_ty)` if `target_ty` is `&T` and `T` fails to impl `Sync`
+                let refers_to_non_sync = match target_ty.kind() {
+                    ty::Ref(_, ref_ty, _) => match self.evaluate_obligation(&obligation) {
+                        Ok(eval) if !eval.may_apply() => Some(ref_ty),
+                        _ => None,
+                    },
+                    _ => None,
+                };
+
+                let (span_label, span_note) = match refers_to_non_sync {
+                    // if `target_ty` is `&T` and `T` fails to impl `Sync`,
+                    // include suggestions to make `T: Sync` so that `&T: Send`
+                    Some(ref_ty) => (
+                        format!(
+                            "has type `{}` which {}, because `{}` is not `Sync`",
+                            target_ty, trait_explanation, ref_ty
+                        ),
+                        format!(
+                            "captured value {} because `&` references cannot be sent unless their referent is `Sync`",
+                            trait_explanation
+                        ),
+                    ),
+                    None => (
+                        format!("has type `{}` which {}", target_ty, trait_explanation),
+                        format!("captured value {}", trait_explanation),
+                    ),
+                };
+
                 let mut span = MultiSpan::from_span(upvar_span);
-                span.push_span_label(
-                    upvar_span,
-                    format!("has type `{}` which {}", target_ty, trait_explanation),
-                );
-                err.span_note(span, &format!("captured value {}", trait_explanation));
+                span.push_span_label(upvar_span, span_label);
+                err.span_note(span, &span_note);
             }
         }
 
@@ -1899,7 +1927,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             | ObligationCauseCode::ReturnNoExpression
             | ObligationCauseCode::UnifyReceiver(..)
             | ObligationCauseCode::OpaqueType
-            | ObligationCauseCode::MiscObligation => {}
+            | ObligationCauseCode::MiscObligation
+            | ObligationCauseCode::WellFormed(..)
+            | ObligationCauseCode::MatchImpl(..) => {}
             ObligationCauseCode::SliceOrArrayElem => {
                 err.note("slice and array elements must have `Sized` type");
             }
@@ -1924,12 +1954,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             ObligationCauseCode::ItemObligation(item_def_id) => {
                 let item_name = tcx.def_path_str(item_def_id);
                 let msg = format!("required by `{}`", item_name);
-                if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
-                    let sp = tcx.sess.source_map().guess_head_span(sp);
-                    err.span_label(sp, &msg);
-                } else {
-                    err.note(&msg);
-                }
+                let sp = tcx
+                    .hir()
+                    .span_if_local(item_def_id)
+                    .unwrap_or_else(|| tcx.def_span(item_def_id));
+                let sp = tcx.sess.source_map().guess_head_span(sp);
+                err.span_note(sp, &msg);
             }
             ObligationCauseCode::BindingObligation(item_def_id, span) => {
                 let item_name = tcx.def_path_str(item_def_id);
@@ -1948,7 +1978,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 if span != DUMMY_SP {
                     err.span_label(span, &msg);
                 } else {
-                    err.note(&msg);
+                    err.span_note(
+                        tcx.def_span(item_def_id),
+                        &format!("required by a bound in `{}`", item_name),
+                    );
                 }
             }
             ObligationCauseCode::ObjectCastObligation(object_ty) => {
@@ -1975,9 +2008,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 
                 if self.tcx.sess.is_nightly_build() && is_const_fn {
                     err.help(
-                        "create an inline `const` block, see RFC \
-                        #2920 <https://github.com/rust-lang/rfcs/pull/2920> \
-                        for more information",
+                        "create an inline `const` block, see RFC #2920 \
+                         <https://github.com/rust-lang/rfcs/pull/2920> for more information",
                     );
                 }
             }
@@ -2164,8 +2196,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 self.tcx.for_each_relevant_impl(
                     parent_def_id,
                     parent_trait_ref.self_ty().skip_binder(),
-                    |impl_def_id| {
-                        candidates.push(impl_def_id);
+                    |impl_def_id| match self.tcx.hir().get_if_local(impl_def_id) {
+                        Some(Node::Item(hir::Item {
+                            kind: hir::ItemKind::Impl(hir::Impl { .. }),
+                            ..
+                        })) => {
+                            candidates.push(impl_def_id);
+                        }
+                        _ => {}
                     },
                 );
                 match &candidates[..] {
@@ -2310,7 +2348,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     }
 
     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 +2387,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 }
                 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
@@ -2396,7 +2434,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     normalized_ty,
                 );
                 debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation);
-                if self.predicate_may_hold(&try_obligation) && impls_future {
+                if self.predicate_may_hold(&try_obligation)
+                    && impls_future.must_apply_modulo_regions()
+                {
                     if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
                         if snippet.ends_with('?') {
                             err.span_suggestion_verbose(
index 120680092baaa46f612403e394275976e535dceb..9ec1dd5c2ee3b302efd8c64613476c1c8b4a5820 100644 (file)
@@ -167,6 +167,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
     /// `SomeTrait` or a where-clause that lets us unify `$0` with
     /// something concrete. If this fails, we'll unify `$0` with
     /// `projection_ty` again.
+    #[tracing::instrument(level = "debug", skip(self, infcx, param_env, cause))]
     fn normalize_projection_type(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
@@ -174,8 +175,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
         projection_ty: ty::ProjectionTy<'tcx>,
         cause: ObligationCause<'tcx>,
     ) -> Ty<'tcx> {
-        debug!(?projection_ty, "normalize_projection_type");
-
         debug_assert!(!projection_ty.has_escaping_bound_vars());
 
         // FIXME(#20304) -- cache
@@ -366,6 +365,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
                     let project_obligation = obligation.with(binder.rebind(data));
 
                     self.process_projection_obligation(
+                        obligation,
                         project_obligation,
                         &mut pending_obligation.stalled_on,
                     )
@@ -420,6 +420,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
                     let project_obligation = obligation.with(Binder::dummy(*data));
 
                     self.process_projection_obligation(
+                        obligation,
                         project_obligation,
                         &mut pending_obligation.stalled_on,
                     )
@@ -667,10 +668,22 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
 
     fn process_projection_obligation(
         &mut self,
+        obligation: &PredicateObligation<'tcx>,
         project_obligation: PolyProjectionObligation<'tcx>,
         stalled_on: &mut Vec<TyOrConstInferVar<'tcx>>,
     ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
         let tcx = self.selcx.tcx();
+
+        if obligation.predicate.is_global() {
+            // no type variables present, can use evaluation for better caching.
+            // FIXME: consider caching errors too.
+            if self.selcx.infcx().predicate_must_hold_considering_regions(obligation) {
+                return ProcessResult::Changed(vec![]);
+            } else {
+                tracing::debug!("Does NOT hold: {:?}", obligation);
+            }
+        }
+
         match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
             Ok(Ok(Some(os))) => ProcessResult::Changed(mk_pending(os)),
             Ok(Ok(None)) => {
@@ -717,6 +730,10 @@ fn substs_infer_vars<'a, 'tcx>(
 fn to_fulfillment_error<'tcx>(
     error: Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>,
 ) -> FulfillmentError<'tcx> {
-    let obligation = error.backtrace.into_iter().next().unwrap().obligation;
-    FulfillmentError::new(obligation, error.error)
+    let mut iter = error.backtrace.into_iter();
+    let obligation = iter.next().unwrap().obligation;
+    // The root obligation is the last item in the backtrace - if there's only
+    // one item, then it's the same as the main obligation
+    let root_obligation = iter.next_back().map_or_else(|| obligation.clone(), |e| e.obligation);
+    FulfillmentError::new(obligation, error.error, root_obligation)
 }
index f26eb159105d710ee34976062a9efba1462e6607..3a80e720e8c4b8560f2aed49e13628061de01430 100644 (file)
@@ -31,7 +31,8 @@ use rustc_hir::def_id::DefId;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
 use rustc_middle::ty::{
-    self, GenericParamDefKind, ParamEnv, ToPredicate, Ty, TyCtxt, WithConstness,
+    self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness,
+    COMMON_VTABLE_ENTRIES,
 };
 use rustc_span::Span;
 
@@ -455,89 +456,89 @@ fn subst_and_check_impossible_predicates<'tcx>(
 
 /// Given a trait `trait_ref`, iterates the vtable entries
 /// that come from `trait_ref`, including its supertraits.
-fn vtable_methods<'tcx>(
+fn vtable_entries<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_ref: ty::PolyTraitRef<'tcx>,
-) -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] {
-    debug!("vtable_methods({:?})", trait_ref);
-
-    tcx.arena.alloc_from_iter(supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
-        let trait_methods = tcx
-            .associated_items(trait_ref.def_id())
-            .in_definition_order()
-            .filter(|item| item.kind == ty::AssocKind::Fn);
-
-        // Now list each method's DefId and InternalSubsts (for within its trait).
-        // If the method can never be called from this object, produce None.
-        trait_methods.map(move |trait_method| {
-            debug!("vtable_methods: trait_method={:?}", trait_method);
-            let def_id = trait_method.def_id;
-
-            // Some methods cannot be called on an object; skip those.
-            if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
-                debug!("vtable_methods: not vtable safe");
-                return None;
-            }
+) -> &'tcx [VtblEntry<'tcx>] {
+    debug!("vtable_entries({:?})", trait_ref);
+
+    let entries = COMMON_VTABLE_ENTRIES.iter().cloned().chain(
+        supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
+            let trait_methods = tcx
+                .associated_items(trait_ref.def_id())
+                .in_definition_order()
+                .filter(|item| item.kind == ty::AssocKind::Fn);
+
+            // Now list each method's DefId and InternalSubsts (for within its trait).
+            // If the method can never be called from this object, produce `Vacant`.
+            trait_methods.map(move |trait_method| {
+                debug!("vtable_entries: trait_method={:?}", trait_method);
+                let def_id = trait_method.def_id;
+
+                // Some methods cannot be called on an object; skip those.
+                if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
+                    debug!("vtable_entries: not vtable safe");
+                    return VtblEntry::Vacant;
+                }
 
-            // The method may have some early-bound lifetimes; add regions for those.
-            let substs = trait_ref.map_bound(|trait_ref| {
-                InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
-                    GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
-                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
-                        trait_ref.substs[param.index as usize]
-                    }
-                })
-            });
-
-            // The trait type may have higher-ranked lifetimes in it;
-            // erase them if they appear, so that we get the type
-            // at some particular call site.
-            let substs =
-                tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), substs);
-
-            // It's possible that the method relies on where-clauses that
-            // do not hold for this particular set of type parameters.
-            // Note that this method could then never be called, so we
-            // do not want to try and codegen it, in that case (see #23435).
-            let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
-            if impossible_predicates(tcx, predicates.predicates) {
-                debug!("vtable_methods: predicates do not hold");
-                return None;
-            }
+                // The method may have some early-bound lifetimes; add regions for those.
+                let substs = trait_ref.map_bound(|trait_ref| {
+                    InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
+                        GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
+                        GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
+                            trait_ref.substs[param.index as usize]
+                        }
+                    })
+                });
+
+                // The trait type may have higher-ranked lifetimes in it;
+                // erase them if they appear, so that we get the type
+                // at some particular call site.
+                let substs =
+                    tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), substs);
+
+                // It's possible that the method relies on where-clauses that
+                // do not hold for this particular set of type parameters.
+                // Note that this method could then never be called, so we
+                // do not want to try and codegen it, in that case (see #23435).
+                let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
+                if impossible_predicates(tcx, predicates.predicates) {
+                    debug!("vtable_entries: predicates do not hold");
+                    return VtblEntry::Vacant;
+                }
 
-            Some((def_id, substs))
-        })
-    }))
+                VtblEntry::Method(def_id, substs)
+            })
+        }),
+    );
+
+    tcx.arena.alloc_from_iter(entries)
 }
 
-/// Check whether a `ty` implements given trait(trait_def_id).
-///
-/// NOTE: Always return `false` for a type which needs inference.
-fn type_implements_trait<'tcx>(
+/// Find slot base for trait methods within vtable entries of another trait
+fn vtable_trait_first_method_offset<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: (
-        DefId,    // trait_def_id,
-        Ty<'tcx>, // type
-        SubstsRef<'tcx>,
-        ParamEnv<'tcx>,
+        ty::PolyTraitRef<'tcx>, // trait_to_be_found
+        ty::PolyTraitRef<'tcx>, // trait_owning_vtable
     ),
-) -> bool {
-    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) };
-
-    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.predicate_must_hold_modulo_regions(&obligation))
+) -> usize {
+    let (trait_to_be_found, trait_owning_vtable) = key;
+
+    let mut supertraits = util::supertraits(tcx, trait_owning_vtable);
+
+    // For each of the non-matching predicates that
+    // we pass over, we sum up the set of number of vtable
+    // entries, so that we can compute the offset for the selected
+    // trait.
+    let vtable_base = ty::COMMON_VTABLE_ENTRIES.len()
+        + supertraits
+            .by_ref()
+            .take_while(|t| *t != trait_to_be_found)
+            .map(|t| util::count_own_vtable_entries(tcx, t))
+            .sum::<usize>();
+
+    vtable_base
 }
 
 pub fn provide(providers: &mut ty::query::Providers) {
@@ -547,8 +548,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
         specialization_graph_of: specialize::specialization_graph_provider,
         specializes: specialize::specializes,
         codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
-        vtable_methods,
-        type_implements_trait,
+        vtable_entries,
         subst_and_check_impossible_predicates,
         mir_abstract_const: |tcx, def_id| {
             let def_id = def_id.expect_local();
index d5e1bd3f9ea2eec0cdb652acc564b69c047f8c4a..7ebef7f8883ae0902eca5df5eea3c5a409771b52 100644 (file)
@@ -838,6 +838,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
                         let leaf = leaf.subst(self.tcx, ct.substs);
                         self.visit_const(leaf)
                     }
+                    Node::Cast(_, _, ty) => self.visit_ty(ty),
                     Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => {
                         ControlFlow::CONTINUE
                     }
@@ -859,6 +860,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
                             let leaf = leaf.subst(self.tcx, ct.substs);
                             self.visit_const(leaf)
                         }
+                        Node::Cast(_, _, ty) => self.visit_ty(ty),
                         Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => {
                             ControlFlow::CONTINUE
                         }
index 388413ae06b5550834919ee46c914f010a45814c..d1ab9fa025ed6f5156e4e4fdcef711063971e590 100644 (file)
@@ -29,6 +29,8 @@ use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_span::symbol::sym;
 
+use std::collections::BTreeMap;
+
 pub use rustc_middle::traits::Reveal;
 
 pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;
@@ -271,7 +273,7 @@ where
     Normalized { value, obligations }
 }
 
-#[instrument(level = "debug", skip(selcx, param_env, cause, obligations))]
+#[instrument(level = "info", skip(selcx, param_env, cause, obligations))]
 pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>(
     selcx: &'a mut SelectionContext<'b, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
@@ -283,6 +285,7 @@ pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>(
 where
     T: TypeFoldable<'tcx>,
 {
+    debug!(obligations.len = obligations.len());
     let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations);
     let result = ensure_sufficient_stack(|| normalizer.fold(value));
     debug!(?result, obligations.len = normalizer.obligations.len());
@@ -290,12 +293,25 @@ where
     result
 }
 
+pub(crate) fn needs_normalization<'tcx, T: TypeFoldable<'tcx>>(value: &T, reveal: Reveal) -> bool {
+    match reveal {
+        Reveal::UserFacing => value
+            .has_type_flags(ty::TypeFlags::HAS_TY_PROJECTION | ty::TypeFlags::HAS_CT_PROJECTION),
+        Reveal::All => value.has_type_flags(
+            ty::TypeFlags::HAS_TY_PROJECTION
+                | ty::TypeFlags::HAS_TY_OPAQUE
+                | ty::TypeFlags::HAS_CT_PROJECTION,
+        ),
+    }
+}
+
 struct AssocTypeNormalizer<'a, 'b, 'tcx> {
     selcx: &'a mut SelectionContext<'b, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     cause: ObligationCause<'tcx>,
     obligations: &'a mut Vec<PredicateObligation<'tcx>>,
     depth: usize,
+    universes: Vec<Option<ty::UniverseIndex>>,
 }
 
 impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
@@ -306,13 +322,24 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
         depth: usize,
         obligations: &'a mut Vec<PredicateObligation<'tcx>>,
     ) -> AssocTypeNormalizer<'a, 'b, 'tcx> {
-        AssocTypeNormalizer { selcx, param_env, cause, obligations, depth }
+        AssocTypeNormalizer { selcx, param_env, cause, obligations, depth, universes: vec![] }
     }
 
     fn fold<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
         let value = self.selcx.infcx().resolve_vars_if_possible(value);
+        debug!(?value);
+
+        assert!(
+            !value.has_escaping_bound_vars(),
+            "Normalizing {:?} without wrapping in a `Binder`",
+            value
+        );
 
-        if !value.has_projections() { value } else { value.fold_with(self) }
+        if !needs_normalization(&value, self.param_env.reveal()) {
+            value
+        } else {
+            value.fold_with(self)
+        }
     }
 }
 
@@ -321,8 +348,18 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
         self.selcx.tcx()
     }
 
+    fn fold_binder<T: TypeFoldable<'tcx>>(
+        &mut self,
+        t: ty::Binder<'tcx, T>,
+    ) -> ty::Binder<'tcx, T> {
+        self.universes.push(None);
+        let t = t.super_fold_with(self);
+        self.universes.pop();
+        t
+    }
+
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty.has_projections() {
+        if !needs_normalization(&ty, self.param_env.reveal()) {
             return ty;
         }
         // We don't want to normalize associated types that occur inside of region
@@ -344,7 +381,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, '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(),
@@ -396,6 +433,52 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
                 normalized_ty
             }
 
+            ty::Projection(data) if !data.trait_ref(self.tcx()).has_escaping_bound_vars() => {
+                // Okay, so you thought the previous branch was hacky. Well, to
+                // extend upon this, when the *trait ref* doesn't have escaping
+                // bound vars, but the associated item *does* (can only occur
+                // with GATs), then we might still be able to project the type.
+                // For this, we temporarily replace the bound vars with
+                // placeholders. Note though, that in the case that we still
+                // can't project for whatever reason (e.g. self type isn't
+                // known enough), we *can't* register an obligation and return
+                // an inference variable (since then that obligation would have
+                // bound vars and that's a can of worms). Instead, we just
+                // give up and fall back to pretending like we never tried!
+
+                let infcx = self.selcx.infcx();
+                let (data, mapped_regions, mapped_types, mapped_consts) =
+                    BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
+                let normalized_ty = opt_normalize_projection_type(
+                    self.selcx,
+                    self.param_env,
+                    data,
+                    self.cause.clone(),
+                    self.depth,
+                    &mut self.obligations,
+                )
+                .ok()
+                .flatten()
+                .unwrap_or_else(|| ty);
+
+                let normalized_ty = PlaceholderReplacer::replace_placeholders(
+                    infcx,
+                    mapped_regions,
+                    mapped_types,
+                    mapped_consts,
+                    &self.universes,
+                    normalized_ty,
+                );
+                debug!(
+                    ?self.depth,
+                    ?ty,
+                    ?normalized_ty,
+                    obligations.len = ?self.obligations.len(),
+                    "AssocTypeNormalizer: normalized type"
+                );
+                normalized_ty
+            }
+
             _ => ty,
         }
     }
@@ -410,6 +493,279 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
     }
 }
 
+pub struct BoundVarReplacer<'me, 'tcx> {
+    infcx: &'me InferCtxt<'me, 'tcx>,
+    // These three maps track the bound variable that were replaced by placeholders. It might be
+    // nice to remove these since we already have the `kind` in the placeholder; we really just need
+    // the `var` (but we *could* bring that into scope if we were to track them as we pass them).
+    mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
+    mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
+    mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
+    // The current depth relative to *this* folding, *not* the entire normalization. In other words,
+    // the depth of binders we've passed here.
+    current_index: ty::DebruijnIndex,
+    // The `UniverseIndex` of the binding levels above us. These are optional, since we are lazy:
+    // we don't actually create a universe until we see a bound var we have to replace.
+    universe_indices: &'me mut Vec<Option<ty::UniverseIndex>>,
+}
+
+impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
+    /// Returns `Some` if we *were* able to replace bound vars. If there are any bound vars that
+    /// use a binding level above `universe_indices.len()`, we fail.
+    pub fn replace_bound_vars<T: TypeFoldable<'tcx>>(
+        infcx: &'me InferCtxt<'me, 'tcx>,
+        universe_indices: &'me mut Vec<Option<ty::UniverseIndex>>,
+        value: T,
+    ) -> (
+        T,
+        BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
+        BTreeMap<ty::PlaceholderType, ty::BoundTy>,
+        BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
+    ) {
+        let mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion> = BTreeMap::new();
+        let mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy> = BTreeMap::new();
+        let mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar> = BTreeMap::new();
+
+        let mut replacer = BoundVarReplacer {
+            infcx,
+            mapped_regions,
+            mapped_types,
+            mapped_consts,
+            current_index: ty::INNERMOST,
+            universe_indices,
+        };
+
+        let value = value.super_fold_with(&mut replacer);
+
+        (value, replacer.mapped_regions, replacer.mapped_types, replacer.mapped_consts)
+    }
+
+    fn universe_for(&mut self, debruijn: ty::DebruijnIndex) -> ty::UniverseIndex {
+        let infcx = self.infcx;
+        let index =
+            self.universe_indices.len() - debruijn.as_usize() + self.current_index.as_usize() - 1;
+        let universe = self.universe_indices[index].unwrap_or_else(|| {
+            for i in self.universe_indices.iter_mut().take(index + 1) {
+                *i = i.or_else(|| Some(infcx.create_next_universe()))
+            }
+            self.universe_indices[index].unwrap()
+        });
+        universe
+    }
+}
+
+impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+
+    fn fold_binder<T: TypeFoldable<'tcx>>(
+        &mut self,
+        t: ty::Binder<'tcx, T>,
+    ) -> ty::Binder<'tcx, T> {
+        self.current_index.shift_in(1);
+        let t = t.super_fold_with(self);
+        self.current_index.shift_out(1);
+        t
+    }
+
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        match *r {
+            ty::ReLateBound(debruijn, _)
+                if debruijn.as_usize() + 1
+                    > self.current_index.as_usize() + self.universe_indices.len() =>
+            {
+                bug!("Bound vars outside of `self.universe_indices`");
+            }
+            ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
+                let universe = self.universe_for(debruijn);
+                let p = ty::PlaceholderRegion { universe, name: br.kind };
+                self.mapped_regions.insert(p.clone(), br);
+                self.infcx.tcx.mk_region(ty::RePlaceholder(p))
+            }
+            _ => r,
+        }
+    }
+
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+        match *t.kind() {
+            ty::Bound(debruijn, _)
+                if debruijn.as_usize() + 1
+                    > self.current_index.as_usize() + self.universe_indices.len() =>
+            {
+                bug!("Bound vars outside of `self.universe_indices`");
+            }
+            ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
+                let universe = self.universe_for(debruijn);
+                let p = ty::PlaceholderType { universe, name: bound_ty.var };
+                self.mapped_types.insert(p.clone(), bound_ty);
+                self.infcx.tcx.mk_ty(ty::Placeholder(p))
+            }
+            _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
+            _ => t,
+        }
+    }
+
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+        match *ct {
+            ty::Const { val: ty::ConstKind::Bound(debruijn, _), ty: _ }
+                if debruijn.as_usize() + 1
+                    > self.current_index.as_usize() + self.universe_indices.len() =>
+            {
+                bug!("Bound vars outside of `self.universe_indices`");
+            }
+            ty::Const { val: ty::ConstKind::Bound(debruijn, bound_const), ty }
+                if debruijn >= self.current_index =>
+            {
+                let universe = self.universe_for(debruijn);
+                let p = ty::PlaceholderConst {
+                    universe,
+                    name: ty::BoundConst { var: bound_const, ty },
+                };
+                self.mapped_consts.insert(p.clone(), bound_const);
+                self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty })
+            }
+            _ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self),
+            _ => ct,
+        }
+    }
+}
+
+// The inverse of `BoundVarReplacer`: replaces placeholders with the bound vars from which they came.
+pub struct PlaceholderReplacer<'me, 'tcx> {
+    infcx: &'me InferCtxt<'me, 'tcx>,
+    mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
+    mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
+    mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
+    universe_indices: &'me Vec<Option<ty::UniverseIndex>>,
+    current_index: ty::DebruijnIndex,
+}
+
+impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> {
+    pub fn replace_placeholders<T: TypeFoldable<'tcx>>(
+        infcx: &'me InferCtxt<'me, 'tcx>,
+        mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
+        mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
+        mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
+        universe_indices: &'me Vec<Option<ty::UniverseIndex>>,
+        value: T,
+    ) -> T {
+        let mut replacer = PlaceholderReplacer {
+            infcx,
+            mapped_regions,
+            mapped_types,
+            mapped_consts,
+            universe_indices,
+            current_index: ty::INNERMOST,
+        };
+        value.super_fold_with(&mut replacer)
+    }
+}
+
+impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+
+    fn fold_binder<T: TypeFoldable<'tcx>>(
+        &mut self,
+        t: ty::Binder<'tcx, T>,
+    ) -> ty::Binder<'tcx, T> {
+        if !t.has_placeholders() && !t.has_infer_regions() {
+            return t;
+        }
+        self.current_index.shift_in(1);
+        let t = t.super_fold_with(self);
+        self.current_index.shift_out(1);
+        t
+    }
+
+    fn fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        let r1 = match r0 {
+            ty::ReVar(_) => self
+                .infcx
+                .inner
+                .borrow_mut()
+                .unwrap_region_constraints()
+                .opportunistic_resolve_region(self.infcx.tcx, r0),
+            _ => r0,
+        };
+
+        let r2 = match *r1 {
+            ty::RePlaceholder(p) => {
+                let replace_var = self.mapped_regions.get(&p);
+                match replace_var {
+                    Some(replace_var) => {
+                        let index = self
+                            .universe_indices
+                            .iter()
+                            .position(|u| matches!(u, Some(pu) if *pu == p.universe))
+                            .unwrap_or_else(|| bug!("Unexpected placeholder universe."));
+                        let db = ty::DebruijnIndex::from_usize(
+                            self.universe_indices.len() - index + self.current_index.as_usize() - 1,
+                        );
+                        self.tcx().mk_region(ty::ReLateBound(db, *replace_var))
+                    }
+                    None => r1,
+                }
+            }
+            _ => r1,
+        };
+
+        debug!(?r0, ?r1, ?r2, "fold_region");
+
+        r2
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        match *ty.kind() {
+            ty::Placeholder(p) => {
+                let replace_var = self.mapped_types.get(&p);
+                match replace_var {
+                    Some(replace_var) => {
+                        let index = self
+                            .universe_indices
+                            .iter()
+                            .position(|u| matches!(u, Some(pu) if *pu == p.universe))
+                            .unwrap_or_else(|| bug!("Unexpected placeholder universe."));
+                        let db = ty::DebruijnIndex::from_usize(
+                            self.universe_indices.len() - index + self.current_index.as_usize() - 1,
+                        );
+                        self.tcx().mk_ty(ty::Bound(db, *replace_var))
+                    }
+                    None => ty,
+                }
+            }
+
+            _ if ty.has_placeholders() || ty.has_infer_regions() => ty.super_fold_with(self),
+            _ => ty,
+        }
+    }
+
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+        if let ty::Const { val: ty::ConstKind::Placeholder(p), ty } = *ct {
+            let replace_var = self.mapped_consts.get(&p);
+            match replace_var {
+                Some(replace_var) => {
+                    let index = self
+                        .universe_indices
+                        .iter()
+                        .position(|u| matches!(u, Some(pu) if *pu == p.universe))
+                        .unwrap_or_else(|| bug!("Unexpected placeholder universe."));
+                    let db = ty::DebruijnIndex::from_usize(
+                        self.universe_indices.len() - index + self.current_index.as_usize() - 1,
+                    );
+                    self.tcx()
+                        .mk_const(ty::Const { val: ty::ConstKind::Bound(db, *replace_var), ty })
+                }
+                None => ct,
+            }
+        } else {
+            ct.super_fold_with(self)
+        }
+    }
+}
+
 /// The guts of `normalize`: normalize a specific projection like `<T
 /// as Trait>::Item`. The result is always a type (and possibly
 /// additional obligations). If ambiguity arises, which implies that
@@ -487,7 +843,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
 
     let cache_result = infcx.inner.borrow_mut().projection_cache().try_start(cache_key);
     match cache_result {
-        Ok(()) => {}
+        Ok(()) => debug!("no cache"),
         Err(ProjectionCacheEntry::Ambiguous) => {
             // If we found ambiguity the last time, that means we will continue
             // to do so until some type in the key changes (and we know it
@@ -514,6 +870,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             return Err(InProgress);
         }
         Err(ProjectionCacheEntry::Recur) => {
+            debug!("recur cache");
             return Err(InProgress);
         }
         Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
@@ -720,13 +1077,12 @@ impl<'tcx> Progress<'tcx> {
 ///
 /// IMPORTANT:
 /// - `obligation` must be fully normalized
+#[tracing::instrument(level = "info", skip(selcx))]
 fn project_type<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'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.
@@ -1301,7 +1657,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>(
         ty: self_ty.ptr_metadata_ty(tcx),
     };
 
-    confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate, tcx), false)
+    confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
 }
 
 fn confirm_fn_pointer_candidate<'cx, 'tcx>(
index b83a4cd1e5775c5af9a5195de09c37819c1669e2..2dc48e47efccdf6a9e150b8e3e88b844a82422ea 100644 (file)
@@ -64,8 +64,10 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
         obligation: &PredicateObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
         let mut _orig_values = OriginalQueryValues::default();
-        let c_pred = self
-            .canonicalize_query(obligation.param_env.and(obligation.predicate), &mut _orig_values);
+        let c_pred = self.canonicalize_query_keep_static(
+            obligation.param_env.and(obligation.predicate),
+            &mut _orig_values,
+        );
         // Run canonical query. If overflow occurs, rerun from scratch but this time
         // in standard trait query mode so that overflow is handled appropriately
         // within `SelectionContext`.
index eb7ea8715c29780aee89618bc91dad1a6de66c3b..3f6efa03b3a28b27694bab4c2743c857285f10ac 100644 (file)
@@ -6,6 +6,7 @@ use crate::infer::at::At;
 use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::{InferCtxt, InferOk};
 use crate::traits::error_reporting::InferCtxtExt;
+use crate::traits::project::needs_normalization;
 use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
 use rustc_data_structures::sso::SsoHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -49,7 +50,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
             value,
             self.param_env,
         );
-        if !value.has_projections() {
+        if !needs_normalization(&value, self.param_env.reveal()) {
             return Ok(Normalized { value, obligations: vec![] });
         }
 
@@ -61,10 +62,11 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
             error: false,
             cache: SsoHashMap::new(),
             anon_depth: 0,
+            universes: vec![],
         };
 
         let result = value.fold_with(&mut normalizer);
-        debug!(
+        info!(
             "normalize::<{}>: result={:?} with {} obligations",
             std::any::type_name::<T>(),
             result,
@@ -91,6 +93,7 @@ struct QueryNormalizer<'cx, 'tcx> {
     cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
     error: bool,
     anon_depth: usize,
+    universes: Vec<Option<ty::UniverseIndex>>,
 }
 
 impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
@@ -98,9 +101,19 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
         self.infcx.tcx
     }
 
+    fn fold_binder<T: TypeFoldable<'tcx>>(
+        &mut self,
+        t: ty::Binder<'tcx, T>,
+    ) -> ty::Binder<'tcx, T> {
+        self.universes.push(None);
+        let t = t.super_fold_with(self);
+        self.universes.pop();
+        t
+    }
+
     #[instrument(level = "debug", skip(self))]
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty.has_projections() {
+        if !needs_normalization(&ty, self.param_env.reveal()) {
             return ty;
         }
 
@@ -116,7 +129,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, '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(),
@@ -167,7 +180,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
                 // so we cannot canonicalize it.
                 let c_data = self
                     .infcx
-                    .canonicalize_hr_query_hack(self.param_env.and(data), &mut orig_values);
+                    .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
                 debug!("QueryNormalizer: c_data = {:#?}", c_data);
                 debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
                 match tcx.normalize_projection_ty(c_data) {
@@ -204,6 +217,80 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
                     }
                 }
             }
+            ty::Projection(data) if !data.trait_ref(self.infcx.tcx).has_escaping_bound_vars() => {
+                // See note in `rustc_trait_selection::traits::project`
+
+                // One other point mentioning: In `traits::project`, if a
+                // projection can't be normalized, we return an inference variable
+                // and register an obligation to later resolve that. Here, the query
+                // will just return ambiguity. In both cases, the effect is the same: we only want
+                // to return `ty` because there are bound vars that we aren't yet handling in a more
+                // complete way.
+
+                // `BoundVarReplacer` can't handle escaping bound vars. Ideally, we want this before even calling
+                // `QueryNormalizer`, but some const-generics tests pass escaping bound vars.
+                // Also, use `ty` so we get that sweet `outer_exclusive_binder` optimization
+                assert!(!ty.has_vars_bound_at_or_above(ty::DebruijnIndex::from_usize(
+                    self.universes.len()
+                )));
+
+                let tcx = self.infcx.tcx;
+                let infcx = self.infcx;
+                let (data, mapped_regions, mapped_types, mapped_consts) =
+                    crate::traits::project::BoundVarReplacer::replace_bound_vars(
+                        infcx,
+                        &mut self.universes,
+                        data,
+                    );
+                let data = data.super_fold_with(self);
+
+                let mut orig_values = OriginalQueryValues::default();
+                // HACK(matthewjasper) `'static` is special-cased in selection,
+                // so we cannot canonicalize it.
+                let c_data = self
+                    .infcx
+                    .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
+                debug!("QueryNormalizer: c_data = {:#?}", c_data);
+                debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
+                let normalized_ty = match tcx.normalize_projection_ty(c_data) {
+                    Ok(result) => {
+                        // We don't expect ambiguity.
+                        if result.is_ambiguous() {
+                            self.error = true;
+                            return ty;
+                        }
+                        match self.infcx.instantiate_query_response_and_region_obligations(
+                            self.cause,
+                            self.param_env,
+                            &orig_values,
+                            result,
+                        ) {
+                            Ok(InferOk { value: result, obligations }) => {
+                                debug!("QueryNormalizer: result = {:#?}", result);
+                                debug!("QueryNormalizer: obligations = {:#?}", obligations);
+                                self.obligations.extend(obligations);
+                                result.normalized_ty
+                            }
+                            Err(_) => {
+                                self.error = true;
+                                ty
+                            }
+                        }
+                    }
+                    Err(NoSolution) => {
+                        self.error = true;
+                        ty
+                    }
+                };
+                crate::traits::project::PlaceholderReplacer::replace_placeholders(
+                    infcx,
+                    mapped_regions,
+                    mapped_types,
+                    mapped_consts,
+                    &self.universes,
+                    normalized_ty,
+                )
+            }
 
             _ => ty,
         })();
index 130ffa1a33aebc7eb8aa89d2c2f37b13f4842371..fbff86618ade3172f15be2bbeb0259685ea84a8c 100644 (file)
@@ -77,12 +77,13 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx {
         }
 
         // FIXME(#33684) -- We need to use
-        // `canonicalize_hr_query_hack` here because of things
+        // `canonicalize_query_keep_static` here because of things
         // like the subtype query, which go awry around
         // `'static` otherwise.
         let mut canonical_var_values = OriginalQueryValues::default();
         let old_param_env = query_key.param_env;
-        let canonical_self = infcx.canonicalize_hr_query_hack(query_key, &mut canonical_var_values);
+        let canonical_self =
+            infcx.canonicalize_query_keep_static(query_key, &mut canonical_var_values);
         let canonical_result = Self::perform_query(infcx.tcx, canonical_self)?;
 
         let InferOk { value, obligations } = infcx
index e338a21b60308d43748a5a764cc92f592e33b72d..f8297ee3a071865d8e10ca9d2c75005942733a86 100644 (file)
@@ -396,19 +396,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let mut nested = vec![];
 
         let mut supertraits = util::supertraits(tcx, ty::Binder::dummy(object_trait_ref));
-
-        // For each of the non-matching predicates that
-        // we pass over, we sum up the set of number of vtable
-        // entries, so that we can compute the offset for the selected
-        // trait.
-        let vtable_base = supertraits
-            .by_ref()
-            .take(index)
-            .map(|t| super::util::count_own_vtable_entries(tcx, t))
-            .sum();
-
         let unnormalized_upcast_trait_ref =
-            supertraits.next().expect("supertraits iterator no longer has as many elements");
+            supertraits.nth(index).expect("supertraits iterator no longer has as many elements");
 
         let upcast_trait_ref = normalize_with_depth_to(
             self,
@@ -490,6 +479,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
 
         debug!(?nested, "object nested obligations");
+
+        let vtable_base = super::super::vtable_trait_first_method_offset(
+            tcx,
+            (unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)),
+        );
+
         Ok(ImplSourceObjectData { upcast_trait_ref, vtable_base, nested })
     }
 
index ea5eb2b68667f562181d3bcdce2f661d656ea9ad..95611ebc8188cfe54fc6a0258bd29d8e00ee7a35 100644 (file)
@@ -28,6 +28,7 @@ use crate::traits::error_reporting::InferCtxtExt;
 use crate::traits::project::ProjectionCacheKeyExt;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stack::ensure_sufficient_stack;
+use rustc_data_structures::sync::Lrc;
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -48,7 +49,6 @@ use std::cell::{Cell, RefCell};
 use std::cmp;
 use std::fmt::{self, Display};
 use std::iter;
-use std::rc::Rc;
 
 pub use rustc_middle::traits::select::*;
 
@@ -216,7 +216,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
         SelectionContext {
             infcx,
-            freshener: infcx.freshener(),
+            freshener: infcx.freshener_keep_static(),
             intercrate: false,
             intercrate_ambiguity_causes: None,
             allow_negative_impls: false,
@@ -227,7 +227,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
         SelectionContext {
             infcx,
-            freshener: infcx.freshener(),
+            freshener: infcx.freshener_keep_static(),
             intercrate: true,
             intercrate_ambiguity_causes: None,
             allow_negative_impls: false,
@@ -242,7 +242,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         debug!(?allow_negative_impls, "with_negative");
         SelectionContext {
             infcx,
-            freshener: infcx.freshener(),
+            freshener: infcx.freshener_keep_static(),
             intercrate: false,
             intercrate_ambiguity_causes: None,
             allow_negative_impls,
@@ -257,7 +257,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         debug!(?query_mode, "with_query_mode");
         SelectionContext {
             infcx,
-            freshener: infcx.freshener(),
+            freshener: infcx.freshener_keep_static(),
             intercrate: false,
             intercrate_ambiguity_causes: None,
             allow_negative_impls: false,
@@ -492,7 +492,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     None => Ok(EvaluatedToAmbig),
                 },
 
-                ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::RegionOutlives(..) => {
+                ty::PredicateKind::TypeOutlives(pred) => {
+                    if pred.0.is_global() {
+                        Ok(EvaluatedToOk)
+                    } else {
+                        Ok(EvaluatedToOkModuloRegions)
+                    }
+                }
+
+                ty::PredicateKind::RegionOutlives(..) => {
                     // We do not consider region relationships when evaluating trait matches.
                     Ok(EvaluatedToOkModuloRegions)
                 }
@@ -985,7 +993,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         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);
@@ -1857,12 +1865,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
     }
 
+    #[tracing::instrument(level = "debug", skip(self))]
     fn match_impl(
         &mut self,
         impl_def_id: DefId,
         obligation: &TraitObligation<'tcx>,
     ) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
-        debug!(?impl_def_id, ?obligation, "match_impl");
         let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
 
         // Before we create the substitutions and everything, first
@@ -1880,6 +1888,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs);
 
+        debug!(?impl_trait_ref);
+
         let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } =
             ensure_sufficient_stack(|| {
                 project::normalize_with_depth(
@@ -1893,9 +1903,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         debug!(?impl_trait_ref, ?placeholder_obligation_trait_ref);
 
+        let cause = ObligationCause::new(
+            obligation.cause.span,
+            obligation.cause.body_id,
+            ObligationCauseCode::MatchImpl(Lrc::new(obligation.cause.code.clone()), impl_def_id),
+        );
+
         let InferOk { obligations, .. } = self
             .infcx
-            .at(&obligation.cause, obligation.param_env)
+            .at(&cause, obligation.param_env)
             .eq(placeholder_obligation_trait_ref, impl_trait_ref)
             .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?;
         nested_obligations.extend(obligations);
@@ -1907,7 +1923,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return Err(());
         }
 
-        debug!(?impl_substs, "match_impl: success");
+        debug!(?impl_substs, ?nested_obligations, "match_impl: success");
         Ok(Normalized { value: impl_substs, obligations: nested_obligations })
     }
 
@@ -2060,6 +2076,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// impl or trait. The obligations are substituted and fully
     /// normalized. This is used when confirming an impl or default
     /// impl.
+    #[tracing::instrument(level = "debug", skip(self, cause, param_env))]
     fn impl_or_trait_obligations(
         &mut self,
         cause: ObligationCause<'tcx>,
@@ -2068,7 +2085,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         def_id: DefId,           // of impl or trait
         substs: SubstsRef<'tcx>, // for impl or trait
     ) -> Vec<PredicateObligation<'tcx>> {
-        debug!(?def_id, "impl_or_trait_obligations");
         let tcx = self.tcx();
 
         // To allow for one-pass evaluation of the nested obligation,
@@ -2086,9 +2102,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // `$1: Copy`, so we must ensure the obligations are emitted in
         // that order.
         let predicates = tcx.predicates_of(def_id);
+        debug!(?predicates);
         assert_eq!(predicates.parent, None);
         let mut obligations = Vec::with_capacity(predicates.predicates.len());
         for (predicate, _) in predicates.predicates {
+            debug!(?predicate);
             let predicate = normalize_with_depth_to(
                 self,
                 param_env,
@@ -2160,7 +2178,7 @@ impl<'tcx> TraitObligationExt<'tcx> for TraitObligation<'tcx> {
         // by using -Z verbose or just a CLI argument.
         let derived_cause = DerivedObligationCause {
             parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
-            parent_code: Rc::new(obligation.cause.code.clone()),
+            parent_code: Lrc::new(obligation.cause.code.clone()),
         };
         let derived_code = variant(derived_cause);
         ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code)
index 3d20a8d5cf336be07e4efca3b70ace80d7806f52..a6323a65aadbce9c4a451c13fc5049422a34eb9c 100644 (file)
@@ -19,7 +19,6 @@ pub enum NonStructuralMatchTy<'tcx> {
     Opaque,
     Generator,
     Projection,
-    Closure,
 }
 
 /// This method traverses the structure of `ty`, trying to find an
@@ -155,9 +154,6 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
             ty::Generator(..) | ty::GeneratorWitness(..) => {
                 return ControlFlow::Break(NonStructuralMatchTy::Generator);
             }
-            ty::Closure(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Closure);
-            }
             ty::RawPtr(..) => {
                 // structural-match ignores substructure of
                 // `*const _`/`*mut _`, so skip `super_visit_with`.
@@ -198,7 +194,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
                 // First check all contained types and then tell the caller to continue searching.
                 return ty.super_visit_with(self);
             }
-            ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => {
+            ty::Closure(..) | ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => {
                 bug!("unexpected type during structural-match checking: {:?}", ty);
             }
             ty::Error(_) => {
index f592cf1cd249d0169a63c3fa8cebdc9c931811b1..27c8e00c5596cf26f66bb649560796a75ef232ee 100644 (file)
@@ -1,6 +1,7 @@
 use crate::infer::InferCtxt;
 use crate::opaque_types::required_region_bounds;
 use crate::traits;
+use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
@@ -9,7 +10,6 @@ use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstnes
 use rustc_span::Span;
 
 use std::iter;
-use std::rc::Rc;
 /// Returns the set of obligations needed to make `arg` well-formed.
 /// If `arg` contains unresolved inference variables, this may include
 /// further WF obligations. However, if `arg` IS an unresolved
@@ -85,6 +85,7 @@ pub fn trait_obligations<'a, 'tcx>(
     let mut wf =
         WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth: 0, item };
     wf.compute_trait_ref(trait_ref, Elaborate::All);
+    debug!(obligations = ?wf.out);
     wf.normalize()
 }
 
@@ -295,7 +296,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
             if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() {
                 let derived_cause = traits::DerivedObligationCause {
                     parent_trait_ref: parent_trait_ref.value,
-                    parent_code: Rc::new(obligation.cause.code.clone()),
+                    parent_code: Lrc::new(obligation.cause.code.clone()),
                 };
                 cause.make_mut().code =
                     traits::ObligationCauseCode::DerivedObligation(derived_cause);
index 39890fd5b0574a2a0b98cb5f6393d5b3920c4e51..a838172d664c355b6a774ac70f550f252433182a 100644 (file)
@@ -8,7 +8,7 @@
 //! ## `Ty` lowering
 //! Much of the `Ty` lowering is 1:1 with Chalk. (Or will be eventually). A
 //! helpful table for what types lower to what can be found in the
-//! [Chalk book](http://rust-lang.github.io/chalk/book/types/rust_types.html).
+//! [Chalk book](https://rust-lang.github.io/chalk/book/types/rust_types.html).
 //! The most notable difference lies with `Param`s. To convert from rustc to
 //! Chalk, we eagerly and deeply convert `Param`s to placeholders (in goals) or
 //! bound variables (for clause generation through functions in `db`).
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 7b688cd3e2199375d8e71309c0e282b08713597e..d0b05beb4e63c86ee9ea23d25931a4a5c715acfc 100644 (file)
@@ -4,7 +4,6 @@
 #![feature(crate_visibility_modifier)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(control_flow_enum)]
 #![recursion_limit = "256"]
 
 #[macro_use]
index 6304f696b00fad2d02c0086618d0d46abc172197..2c55ea7f5c14ea555e71e43c53e4c16487fa72e7 100644 (file)
@@ -67,8 +67,7 @@ impl AscribeUserTypeCx<'me, 'tcx> {
     {
         self.infcx
             .partially_normalize_associated_types_in(
-                DUMMY_SP,
-                hir::CRATE_HIR_ID,
+                ObligationCause::misc(DUMMY_SP, hir::CRATE_HIR_ID),
                 self.param_env,
                 value,
             )
index 874289d02938d038817129714215a78e8453b1ef..469ac04e54515158fc9fff91fb8a245a0690fb8a 100644 (file)
@@ -2,14 +2,114 @@ use rustc_errors::ErrorReported;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, Binder, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitor};
 use rustc_span::{sym, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 use traits::{translate_substs, Reveal};
 
+use rustc_data_structures::sso::SsoHashSet;
+use std::collections::btree_map::Entry;
+use std::collections::BTreeMap;
+use std::ops::ControlFlow;
+
 use tracing::debug;
 
+// FIXME(#86795): `BoundVarsCollector` here should **NOT** be used
+// outside of `resolve_associated_item`. It's just to address #64494,
+// #83765, and #85848 which are creating bound types/regions that lose
+// their `Binder` *unintentionally*.
+// It's ideal to remove `BoundVarsCollector` and just use
+// `ty::Binder::*` methods but we use this stopgap until we figure out
+// the "real" fix.
+struct BoundVarsCollector<'tcx> {
+    binder_index: ty::DebruijnIndex,
+    vars: BTreeMap<u32, ty::BoundVariableKind>,
+    // We may encounter the same variable at different levels of binding, so
+    // this can't just be `Ty`
+    visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
+}
+
+impl<'tcx> BoundVarsCollector<'tcx> {
+    fn new() -> Self {
+        BoundVarsCollector {
+            binder_index: ty::INNERMOST,
+            vars: BTreeMap::new(),
+            visited: SsoHashSet::default(),
+        }
+    }
+
+    fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List<ty::BoundVariableKind> {
+        let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or(0);
+        for i in 0..max {
+            if let None = self.vars.get(&i) {
+                panic!("Unknown variable: {:?}", i);
+            }
+        }
+
+        tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v))
+    }
+}
+
+impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
+    type BreakTy = ();
+
+    fn visit_binder<T: TypeFoldable<'tcx>>(
+        &mut self,
+        t: &Binder<'tcx, T>,
+    ) -> ControlFlow<Self::BreakTy> {
+        self.binder_index.shift_in(1);
+        let result = t.super_visit_with(self);
+        self.binder_index.shift_out(1);
+        result
+    }
+
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        if t.outer_exclusive_binder() < self.binder_index
+            || !self.visited.insert((self.binder_index, t))
+        {
+            return ControlFlow::CONTINUE;
+        }
+        match *t.kind() {
+            ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
+                match self.vars.entry(bound_ty.var.as_u32()) {
+                    Entry::Vacant(entry) => {
+                        entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind));
+                    }
+                    Entry::Occupied(entry) => match entry.get() {
+                        ty::BoundVariableKind::Ty(_) => {}
+                        _ => bug!("Conflicting bound vars"),
+                    },
+                }
+            }
+
+            _ => (),
+        };
+
+        t.super_visit_with(self)
+    }
+
+    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+        match r {
+            ty::ReLateBound(index, br) if *index == self.binder_index => {
+                match self.vars.entry(br.var.as_u32()) {
+                    Entry::Vacant(entry) => {
+                        entry.insert(ty::BoundVariableKind::Region(br.kind));
+                    }
+                    Entry::Occupied(entry) => match entry.get() {
+                        ty::BoundVariableKind::Region(_) => {}
+                        _ => bug!("Conflicting bound vars"),
+                    },
+                }
+            }
+
+            _ => (),
+        };
+
+        r.super_visit_with(self)
+    }
+}
+
 #[instrument(level = "debug", skip(tcx))]
 fn resolve_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -115,7 +215,12 @@ fn resolve_associated_item<'tcx>(
     );
 
     let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
-    let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref, tcx)))?;
+
+    // See FIXME on `BoundVarsCollector`.
+    let mut bound_vars_collector = BoundVarsCollector::new();
+    trait_ref.visit_with(&mut bound_vars_collector);
+    let trait_binder = ty::Binder::bind_with_vars(trait_ref, bound_vars_collector.into_vars(tcx));
+    let vtbl = tcx.codegen_fulfill_obligation((param_env, trait_binder))?;
 
     // Now that we know which impl is being used, we can dispatch to
     // the actual function:
index 67a692eceacc4e99175899ae305f6be39a865709..313571274c3de7e54a6e34ae455df21658cf8f56 100644 (file)
@@ -5,6 +5,7 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(control_flow_enum)]
 #![feature(half_open_range_patterns)]
 #![feature(exclusive_range_pattern)]
 #![feature(nll)]
index bc8f10e15db8cb180ccaaf1e7898021490549763..d837af85d58ae912933b202a95a927b043026b97 100644 (file)
@@ -63,7 +63,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> {
             seen_tys,
             query_ty: ty,
             unchecked_tys: vec![(ty, 0)],
-            recursion_limit: tcx.sess.recursion_limit(),
+            recursion_limit: tcx.recursion_limit(),
             adt_components,
         }
     }
index ebc7b0d0d99cfc0eb5a8bc65e386997c2b7fdaba..b0d644ae028ce3711036c58254eea6329fef759b 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;
 
@@ -169,6 +168,16 @@ fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
     }
 }
 
+fn impl_constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness {
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+    let item = tcx.hir().expect_item(hir_id);
+    if let hir::ItemKind::Impl(impl_) = &item.kind {
+        impl_.constness
+    } else {
+        bug!("`impl_constness` called on {:?}", item);
+    }
+}
+
 /// Calculates the `Sized` constraint.
 ///
 /// In fact, there are only a few options for the types in the constraint:
@@ -388,11 +397,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>,
@@ -402,7 +406,7 @@ fn instance_def_size_estimate<'tcx>(
     match instance_def {
         InstanceDef::Item(..) | InstanceDef::DropGlue(..) => {
             let mir = tcx.instance_mir(instance_def);
-            mir.basic_blocks().iter().map(|bb| bb.statements.len()).sum()
+            mir.basic_blocks().iter().map(|bb| bb.statements.len() + 1).sum()
         }
         // Estimate the size of other compiler-generated shims to be 1.
         _ => 1,
@@ -538,10 +542,10 @@ 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,
+        impl_constness,
         conservative_is_privately_uninhabited: conservative_is_privately_uninhabited_raw,
         ..*providers
     };
index ef1956210448da19a7918c5811df632f3e62f113..f55e274ef8ea3f4a039c5e27696a0777e76aa794 100644 (file)
@@ -838,6 +838,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                              this does nothing because the given bound is not \
                              a default; only `?Sized` is supported",
                         );
+                        return false;
                     }
                 }
             }
@@ -1694,7 +1695,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 };
 
                 self.one_bound_for_assoc_type(
-                    || traits::supertraits(tcx, ty::Binder::bind(trait_ref, tcx)),
+                    || traits::supertraits(tcx, ty::Binder::dummy(trait_ref)),
                     || "Self".to_string(),
                     assoc_ident,
                     span,
@@ -2418,6 +2419,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 visitor.0,
                 true,
                 hir_ty,
+                "function",
             );
         }
 
index cb8f336721ad6a4d06c1c175e493e4575e803b32..d101551085976077688375471a3592fcfe0567f5 100644 (file)
@@ -205,7 +205,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         opt_arg_exprs: Option<&'tcx [hir::Expr<'tcx>]>,
     ) -> Option<(Option<Adjustment<'tcx>>, MethodCallee<'tcx>)> {
         // Try the options that are least restrictive on the caller first.
-        for &(opt_trait_def_id, method_name, borrow) in &[
+        for (opt_trait_def_id, method_name, borrow) in [
             (self.tcx.lang_items().fn_trait(), Ident::with_dummy_span(sym::call), true),
             (self.tcx.lang_items().fn_mut_trait(), Ident::with_dummy_span(sym::call_mut), true),
             (self.tcx.lang_items().fn_once_trait(), Ident::with_dummy_span(sym::call_once), false),
@@ -588,10 +588,17 @@ impl<'a, 'tcx> DeferredCallResolution<'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 3cbc3d231f847eda831051f4ba638dd159e0643e..b3808eae1ad1155c10af372a76d9632562b005c6 100644 (file)
@@ -45,6 +45,7 @@ use rustc_session::lint;
 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;
 
@@ -440,16 +441,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                             let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
                             let expr_ty = fcx.tcx.erase_regions(expr_ty);
                             let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]);
-                            // Check for infer types because cases like `Option<{integer}>` would
-                            // panic otherwise.
-                            if !expr_ty.has_infer_types()
-                                && !ty.has_infer_types()
-                                && fcx.tcx.type_implements_trait((
-                                    from_trait,
-                                    ty,
-                                    ty_params,
-                                    fcx.param_env,
-                                ))
+                            if fcx
+                                .infcx
+                                .type_implements_trait(from_trait, ty, ty_params, fcx.param_env)
+                                .must_apply_modulo_regions()
                             {
                                 label = false;
                                 err.span_suggestion(
index 70d85796d002e961a70149c3cb06e1d1818699d0..b5db3331d044781bca42a36d6956cd2d9ed2d39e 100644 (file)
@@ -17,7 +17,7 @@ use rustc_middle::ty::layout::MAX_SIMD_LANES;
 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
@@ -215,9 +221,7 @@ pub(super) fn check_fn<'a, 'tcx>(
         fcx.resume_yield_tys = Some((resume_ty, yield_ty));
     }
 
-    let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id).to_def_id()).expect_local();
-    let outer_hir_id = hir.local_def_id_to_hir_id(outer_def_id);
-    GatherLocalsVisitor::new(&fcx, outer_hir_id).visit_body(body);
+    GatherLocalsVisitor::new(&fcx).visit_body(body);
 
     // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
     // (as it's created inside the body itself, not passed in from outside).
@@ -659,13 +663,9 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
     span: Span,
     origin: &hir::OpaqueTyOrigin,
 ) -> Result<(), ErrorReported> {
-    if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs)
-    {
+    if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() {
         match origin {
             hir::OpaqueTyOrigin::AsyncFn => async_opaque_type_cycle_error(tcx, span),
-            hir::OpaqueTyOrigin::Binding => {
-                binding_opaque_type_cycle_error(tcx, def_id, span, partially_expanded_type)
-            }
             _ => opaque_type_cycle_error(tcx, def_id, span),
         }
         Err(ErrorReported)
@@ -698,8 +698,7 @@ fn check_opaque_meets_bounds<'tcx>(
         // Checked when type checking the function containing them.
         hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => return,
         // Can have different predicates to their defining use
-        hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias => {
-        }
+        hir::OpaqueTyOrigin::TyAlias => {}
     }
 
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
@@ -828,7 +827,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 {
@@ -1382,7 +1381,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: &'tcx ty
     let non_zst_fields =
         field_infos.clone().filter_map(|(span, zst, _align1)| if !zst { Some(span) } else { None });
     let non_zst_count = non_zst_fields.clone().count();
-    if non_zst_count != 1 {
+    if non_zst_count >= 2 {
         bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, sp);
     }
     for (span, zst, align1) in field_infos {
index 236fec94bdba79fc0e28bd9d3adc9fcade141fb0..ba76b9c8dd5a033ab083ee548ecc33b21b81a289 100644 (file)
@@ -640,7 +640,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
                 // Object safety violations or miscellaneous.
                 Err(err) => {
-                    self.report_selection_error(&obligation, &err, false, false);
+                    self.report_selection_error(
+                        obligation.clone(),
+                        &obligation,
+                        &err,
+                        false,
+                        false,
+                    );
                     // Treat this like an obligation and follow through
                     // with the unsizing - the lack of a coercion should
                     // be silent, as it causes a type mismatch later.
@@ -1456,11 +1462,15 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                 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() {
@@ -1481,6 +1491,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                     expected,
                     found,
                     can_suggest,
+                    fcx.tcx.hir().get_parent_item(id),
                 );
             }
             if !pointing_at_return_type {
index 60ca562f9920068d44fc8e5635a65b7ed0a4652b..d35868881558e31fafdbe338658060340af6035d 100644 (file)
@@ -66,6 +66,10 @@ crate fn compare_impl_method<'tcx>(
     {
         return;
     }
+
+    if let Err(ErrorReported) = compare_const_param_types(tcx, impl_m, trait_m, trait_item_span) {
+        return;
+    }
 }
 
 fn compare_predicate_entailment<'tcx>(
@@ -222,12 +226,7 @@ fn compare_predicate_entailment<'tcx>(
         let mut selcx = traits::SelectionContext::new(&infcx);
 
         let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
-        let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars(
-            impl_m_span,
-            infer::HigherRankedType,
-            ty::Binder::bind(impl_m_own_bounds.predicates, tcx),
-        );
-        for predicate in impl_m_own_bounds {
+        for predicate in impl_m_own_bounds.predicates {
             let traits::Normalized { value: predicate, obligations } =
                 traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate);
 
@@ -258,14 +257,14 @@ fn compare_predicate_entailment<'tcx>(
         );
         let impl_sig =
             inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, impl_sig);
-        let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig, tcx));
+        let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
         debug!("compare_impl_method: impl_fty={:?}", impl_fty);
 
         let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id));
         let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs);
         let trait_sig =
             inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig);
-        let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig, tcx));
+        let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
 
         debug!("compare_impl_method: trait_fty={:?}", trait_fty);
 
@@ -579,7 +578,7 @@ fn compare_number_of_generics<'tcx>(
     let item_kind = assoc_item_kind_str(impl_);
 
     let mut err_occurred = false;
-    for &(kind, trait_count, impl_count) in &matchings {
+    for (kind, trait_count, impl_count) in matchings {
         if impl_count != trait_count {
             err_occurred = true;
 
@@ -934,6 +933,68 @@ fn compare_synthetic_generics<'tcx>(
     if error_found { Err(ErrorReported) } else { Ok(()) }
 }
 
+fn compare_const_param_types<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    impl_m: &ty::AssocItem,
+    trait_m: &ty::AssocItem,
+    trait_item_span: Option<Span>,
+) -> Result<(), ErrorReported> {
+    let const_params_of = |def_id| {
+        tcx.generics_of(def_id).params.iter().filter_map(|param| match param.kind {
+            GenericParamDefKind::Const { .. } => Some(param.def_id),
+            _ => None,
+        })
+    };
+    let const_params_impl = const_params_of(impl_m.def_id);
+    let const_params_trait = const_params_of(trait_m.def_id);
+
+    for (const_param_impl, const_param_trait) in iter::zip(const_params_impl, const_params_trait) {
+        let impl_ty = tcx.type_of(const_param_impl);
+        let trait_ty = tcx.type_of(const_param_trait);
+        if impl_ty != trait_ty {
+            let (impl_span, impl_ident) = match tcx.hir().get_if_local(const_param_impl) {
+                Some(hir::Node::GenericParam(hir::GenericParam { span, name, .. })) => (
+                    span,
+                    match name {
+                        hir::ParamName::Plain(ident) => Some(ident),
+                        _ => None,
+                    },
+                ),
+                other => bug!(
+                    "expected GenericParam, found {:?}",
+                    other.map_or_else(|| "nothing".to_string(), |n| format!("{:?}", n))
+                ),
+            };
+            let trait_span = match tcx.hir().get_if_local(const_param_trait) {
+                Some(hir::Node::GenericParam(hir::GenericParam { span, .. })) => Some(span),
+                _ => None,
+            };
+            let mut err = struct_span_err!(
+                tcx.sess,
+                *impl_span,
+                E0053,
+                "method `{}` has an incompatible const parameter type for trait",
+                trait_m.ident
+            );
+            err.span_note(
+                trait_span.map_or_else(|| trait_item_span.unwrap_or(*impl_span), |span| *span),
+                &format!(
+                    "the const parameter{} has type `{}`, but the declaration \
+                              in trait `{}` has type `{}`",
+                    &impl_ident.map_or_else(|| "".to_string(), |ident| format!(" `{}`", ident)),
+                    impl_ty,
+                    tcx.def_path_str(trait_m.def_id),
+                    trait_ty
+                ),
+            );
+            err.emit();
+            return Err(ErrorReported);
+        }
+    }
+
+    Ok(())
+}
+
 crate fn compare_const_impl<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_c: &ty::AssocItem,
index 33bc25accb319dceffcf2862d321aaf476cbee1f..3ea59906d3dcd326d241ecf902912180ce41247a 100644 (file)
@@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir::{is_range_literal, Node};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
+use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
@@ -201,7 +202,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let sole_field = &variant.fields[0];
                     let sole_field_ty = sole_field.ty(self.tcx, substs);
                     if self.can_coerce(expr_ty, sole_field_ty) {
-                        let variant_path = self.tcx.def_path_str(variant.def_id);
+                        let variant_path =
+                            with_no_trimmed_paths(|| self.tcx.def_path_str(variant.def_id));
                         // FIXME #56861: DRYer prelude filtering
                         if let Some(path) = variant_path.strip_prefix("std::prelude::") {
                             if let Some((_, path)) = path.split_once("::") {
index d0cbb58fb10eb8d5cecf377d5bd4c9e652426508..cfe1d1c6871f092ab4a048c829b758f859f034b4 100644 (file)
@@ -466,7 +466,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &'tcx hir::Expr<'tcx>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
-        let (res, opt_ty, segs) = self.resolve_ty_and_res_ufcs(qpath, expr.hir_id, expr.span);
+        let (res, opt_ty, segs) =
+            self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span);
         let ty = match res {
             Res::Err => {
                 self.set_tainted_by_errors();
@@ -674,7 +675,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &'tcx hir::Expr<'tcx>,
     ) -> Ty<'tcx> {
         if self.ret_coercion.is_none() {
-            self.tcx.sess.emit_err(ReturnStmtOutsideOfFnBody { span: expr.span });
+            let mut err = ReturnStmtOutsideOfFnBody {
+                span: expr.span,
+                encl_body_span: None,
+                encl_fn_span: None,
+            };
+
+            let encl_item_id = self.tcx.hir().get_parent_item(expr.hir_id);
+
+            if let Some(hir::Node::Item(hir::Item {
+                kind: hir::ItemKind::Fn(..),
+                span: encl_fn_span,
+                ..
+            }))
+            | Some(hir::Node::TraitItem(hir::TraitItem {
+                kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
+                span: encl_fn_span,
+                ..
+            }))
+            | Some(hir::Node::ImplItem(hir::ImplItem {
+                kind: hir::ImplItemKind::Fn(..),
+                span: encl_fn_span,
+                ..
+            })) = self.tcx.hir().find(encl_item_id)
+            {
+                // We are inside a function body, so reporting "return statement
+                // outside of function body" needs an explanation.
+
+                let encl_body_owner_id = self.tcx.hir().enclosing_body_owner(expr.hir_id);
+
+                // If this didn't hold, we would not have to report an error in
+                // the first place.
+                assert_ne!(encl_item_id, encl_body_owner_id);
+
+                let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id);
+                let encl_body = self.tcx.hir().body(encl_body_id);
+
+                err.encl_body_span = Some(encl_body.value.span);
+                err.encl_fn_span = Some(*encl_fn_span);
+            }
+
+            self.tcx.sess.emit_err(err);
+
+            if let Some(e) = expr_opt {
+                // We still have to type-check `e` (issue #86188), but calling
+                // `check_return_expr` only works inside fn bodies.
+                self.check_expr(e);
+            }
         } else if let Some(e) = expr_opt {
             if self.ret_coercion_span.get().is_none() {
                 self.ret_coercion_span.set(Some(e.span));
@@ -940,7 +987,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // no need to check for bot/err -- callee does that
         let rcvr_t = self.structurally_resolved_type(args[0].span, rcvr_t);
 
-        let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr) {
+        let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) {
             Ok(method) => {
                 // We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
                 // trigger this codepath causing `structuraly_resolved_type` to emit an error.
index 96569ae0e772065b3970073611ec091125f99f7b..865e4ccc0b63f506b7c7e237e76fc764ffa20b1c 100644 (file)
@@ -39,7 +39,8 @@ use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::opaque_types::InferCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
-    self, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt,
+    self, ObligationCause, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt,
+    WellFormedLoc,
 };
 
 use std::collections::hash_map::Entry;
@@ -408,6 +409,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         value
     }
 
+    /// Convenience method which tracks extra diagnostic information for normalization
+    /// that occurs as a result of WF checking. The `hir_id` is the `HirId` of the hir item
+    /// whose type is being wf-checked - this is used to construct a more precise span if
+    /// an error occurs.
+    ///
+    /// It is never necessary to call this method - calling `normalize_associated_types_in` will
+    /// just result in a slightly worse diagnostic span, and will still be sound.
+    pub(in super::super) fn normalize_associated_types_in_wf<T>(
+        &self,
+        span: Span,
+        value: T,
+        loc: WellFormedLoc,
+    ) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        self.inh.normalize_associated_types_in_with_cause(
+            ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(Some(loc))),
+            self.param_env,
+            value,
+        )
+    }
+
     pub(in super::super) fn normalize_associated_types_in<T>(&self, span: Span, value: T) -> T
     where
         T: TypeFoldable<'tcx>,
@@ -423,7 +447,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
-        self.inh.partially_normalize_associated_types_in(span, self.body_id, self.param_env, value)
+        self.inh.partially_normalize_associated_types_in(
+            ObligationCause::misc(span, self.body_id),
+            self.param_env,
+            value,
+        )
     }
 
     pub fn require_type_meets(
@@ -906,13 +934,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// Resolves an associated value path into a base type and associated constant, or method
     /// resolution. The newly resolved definition is written into `type_dependent_defs`.
-    pub fn resolve_ty_and_res_ufcs(
+    pub fn resolve_ty_and_res_fully_qualified_call(
         &self,
         qpath: &'tcx QPath<'tcx>,
         hir_id: hir::HirId,
         span: Span,
     ) -> (Res, Option<Ty<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
-        debug!("resolve_ty_and_res_ufcs: qpath={:?} hir_id={:?} span={:?}", qpath, hir_id, span);
+        debug!(
+            "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
+            qpath, hir_id, span
+        );
         let (ty, qself, item_segment) = match *qpath {
             QPath::Resolved(ref opt_qself, ref path) => {
                 return (
@@ -922,7 +953,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
             }
             QPath::TypeRelative(ref qself, ref segment) => (self.to_ty(qself), qself, segment),
-            QPath::LangItem(..) => bug!("`resolve_ty_and_res_ufcs` called on `LangItem`"),
+            QPath::LangItem(..) => {
+                bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
+            }
         };
         if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
         {
@@ -932,25 +965,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return (def, Some(ty), slice::from_ref(&**item_segment));
         }
         let item_name = item_segment.ident;
-        let result = self.resolve_ufcs(span, item_name, ty, hir_id).or_else(|error| {
-            let result = match error {
-                method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
-                _ => Err(ErrorReported),
-            };
-            if item_name.name != kw::Empty {
-                if let Some(mut e) = self.report_method_error(
-                    span,
-                    ty,
-                    item_name,
-                    SelfSource::QPath(qself),
-                    error,
-                    None,
-                ) {
-                    e.emit();
+        let result = self
+            .resolve_fully_qualified_call(span, item_name, ty, qself.span, hir_id)
+            .or_else(|error| {
+                let result = match error {
+                    method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
+                    _ => Err(ErrorReported),
+                };
+                if item_name.name != kw::Empty {
+                    if let Some(mut e) = self.report_method_error(
+                        span,
+                        ty,
+                        item_name,
+                        SelfSource::QPath(qself),
+                        error,
+                        None,
+                    ) {
+                        e.emit();
+                    }
                 }
-            }
-            result
-        });
+                result
+            });
 
         if result.is_ok() {
             self.maybe_lint_bare_trait(qpath, hir_id);
@@ -1544,6 +1579,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     /// Add all the obligations that are required, substituting and normalized appropriately.
+    #[tracing::instrument(level = "debug", skip(self, span, def_id, substs))]
     fn add_required_obligations(&self, span: Span, def_id: DefId, substs: &SubstsRef<'tcx>) {
         let (bounds, spans) = self.instantiate_bounds(span, def_id, &substs);
 
index 49aea19c8d099970e72e2ec57fb5ddbc58478f0c..f65cc429fbd48241fdb5423ee8fa47fde73a1d38 100644 (file)
@@ -11,7 +11,7 @@ use crate::check::{
 use rustc_ast as ast;
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{ExprKind, Node, QPath};
 use rustc_middle::ty::adjustment::AllowTwoPhase;
@@ -120,8 +120,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                  error_code: &str,
                                  c_variadic: bool,
                                  sugg_unit: bool| {
-            let (span, start_span, args) = match &expr.kind {
-                hir::ExprKind::Call(hir::Expr { span, .. }, args) => (*span, *span, &args[..]),
+            let (span, start_span, args, ctor_of) = match &expr.kind {
+                hir::ExprKind::Call(
+                    hir::Expr {
+                        span,
+                        kind:
+                            hir::ExprKind::Path(hir::QPath::Resolved(
+                                _,
+                                hir::Path { res: Res::Def(DefKind::Ctor(of, _), _), .. },
+                            )),
+                        ..
+                    },
+                    args,
+                ) => (*span, *span, &args[..], Some(of)),
+                hir::ExprKind::Call(hir::Expr { span, .. }, args) => {
+                    (*span, *span, &args[..], None)
+                }
                 hir::ExprKind::MethodCall(path_segment, span, args, _) => (
                     *span,
                     // `sp` doesn't point at the whole `foo.bar()`, only at `bar`.
@@ -137,6 +151,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         })
                         .unwrap_or(*span),
                     &args[1..], // Skip the receiver.
+                    None,       // methods are never ctors
                 ),
                 k => span_bug!(sp, "checking argument types on a non-call: `{:?}`", k),
             };
@@ -157,7 +172,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let mut err = tcx.sess.struct_span_err_with_code(
                 span,
                 &format!(
-                    "this function takes {}{} but {} {} supplied",
+                    "this {} takes {}{} but {} {} supplied",
+                    match ctor_of {
+                        Some(CtorOf::Struct) => "struct",
+                        Some(CtorOf::Variant) => "enum variant",
+                        None => "function",
+                    },
                     if c_variadic { "at least " } else { "" },
                     potentially_plural_count(expected_count, "argument"),
                     potentially_plural_count(arg_count, "argument"),
@@ -291,7 +311,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // that are not closures, then we type-check the closures. This is so
         // that we have more information about the types of arguments when we
         // type-check the functions. This isn't really the right way to do this.
-        for &check_closures in &[false, true] {
+        for check_closures in [false, true] {
             debug!("check_closures={}", check_closures);
 
             // More awful hacks: before we check argument types, try to do
index 4da4835f7cfbb065ab561ea414ed95b77e2a5399..13686cfec809a8635e683129330341d1a222a62e 100644 (file)
@@ -15,7 +15,6 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use rustc_middle::hir::map::blocks::FnLikeNode;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, Const, Ty, TyCtxt};
@@ -175,13 +174,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
     }
 
     fn default_constness_for_trait_bounds(&self) -> hir::Constness {
-        // FIXME: refactor this into a method
-        let node = self.tcx.hir().get(self.body_id);
-        if let Some(fn_like) = FnLikeNode::from_node(node) {
-            fn_like.constness()
-        } else {
-            hir::Constness::NotConst
-        }
+        self.tcx.hir().get(self.body_id).constness()
     }
 
     fn get_type_parameter_bounds(
index d6b1e56316b3751d20cf1e5b07a5b33d208c9493..54aab271fdb3c767e1d68c833088e33e2be24713 100644 (file)
@@ -52,9 +52,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
         let mut pointing_at_return_type = false;
         if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
-            pointing_at_return_type =
-                self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest);
             let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap();
+            pointing_at_return_type = self.suggest_missing_return_type(
+                err,
+                &fn_decl,
+                expected,
+                found,
+                can_suggest,
+                fn_id,
+            );
             self.suggest_missing_break_or_return_expr(
                 err, expr, &fn_decl, expected, found, blk_id, fn_id,
             );
@@ -433,6 +439,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         found: Ty<'tcx>,
         can_suggest: bool,
+        fn_id: hir::HirId,
     ) -> bool {
         // Only suggest changing the return type for methods that
         // haven't set a return type at all (and aren't `fn main()` or an impl).
@@ -465,7 +472,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
                 debug!("suggest_missing_return_type: return type {:?}", ty);
                 debug!("suggest_missing_return_type: expected type {:?}", ty);
-                if ty.kind() == expected.kind() {
+                let bound_vars = self.tcx.late_bound_vars(fn_id);
+                let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
+                let ty = self.normalize_associated_types_in(sp, ty);
+                if self.can_coerce(expected, ty) {
                     err.span_label(sp, format!("expected `{}` because of return type", expected));
                     return true;
                 }
index 2683e886eeb0f1ebb6664bed44fca837cdb3d6d7..4ebfd7fd21200aad744e75699ed87959f78439e7 100644 (file)
@@ -4,12 +4,11 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::PatKind;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_middle::ty::Ty;
-use rustc_span::{sym, Span};
+use rustc_span::Span;
 use rustc_trait_selection::traits;
 
 pub(super) struct GatherLocalsVisitor<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
-    parent_id: hir::HirId,
     // parameters are special cases of patterns, but we want to handle them as
     // *distinct* cases. so track when we are hitting a pattern *within* an fn
     // parameter.
@@ -17,8 +16,8 @@ pub(super) struct GatherLocalsVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
-    pub(super) fn new(fcx: &'a FnCtxt<'a, 'tcx>, parent_id: hir::HirId) -> Self {
-        Self { fcx, parent_id, outermost_fn_param_pat: None }
+    pub(super) fn new(fcx: &'a FnCtxt<'a, 'tcx>) -> Self {
+        Self { fcx, outermost_fn_param_pat: None }
     }
 
     fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option<LocalTy<'tcx>>) -> Ty<'tcx> {
@@ -57,26 +56,15 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
             Some(ref ty) => {
                 let o_ty = self.fcx.to_ty(&ty);
 
-                let revealed_ty = self.fcx.instantiate_opaque_types_from_value(
-                    self.parent_id,
-                    o_ty,
-                    ty.span,
-                    Some(sym::impl_trait_in_bindings),
-                );
-
-                let c_ty =
-                    self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(revealed_ty));
-                debug!(
-                    "visit_local: ty.hir_id={:?} o_ty={:?} revealed_ty={:?} c_ty={:?}",
-                    ty.hir_id, o_ty, revealed_ty, c_ty
-                );
+                let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty));
+                debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty);
                 self.fcx
                     .typeck_results
                     .borrow_mut()
                     .user_provided_types_mut()
                     .insert(ty.hir_id, c_ty);
 
-                Some(LocalTy { decl_ty: o_ty, revealed_ty })
+                Some(LocalTy { decl_ty: o_ty, revealed_ty: o_ty })
             }
             None => None,
         };
index 2e9bef15f900a715fe515a9bb3e8d7db23325d84..7e43e36fe55c6e8ae64ad78f1570621f241a7d5f 100644 (file)
@@ -13,7 +13,7 @@ use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt};
 use rustc_span::{self, Span};
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::opaque_types::OpaqueTypeDecl;
-use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt};
+use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt};
 
 use std::cell::RefCell;
 use std::ops::Deref;
@@ -162,7 +162,24 @@ impl Inherited<'a, 'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
-        let ok = self.partially_normalize_associated_types_in(span, body_id, param_env, value);
+        self.normalize_associated_types_in_with_cause(
+            ObligationCause::misc(span, body_id),
+            param_env,
+            value,
+        )
+    }
+
+    pub(super) fn normalize_associated_types_in_with_cause<T>(
+        &self,
+        cause: ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        value: T,
+    ) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        let ok = self.partially_normalize_associated_types_in(cause, param_env, value);
+        debug!(?ok);
         self.register_infer_ok_obligations(ok)
     }
 }
index 5741b6824b5d70662efa746791b3f043a05aae0b..6661df21ed952cef4b2748a90e4748d75a6fd491 100644 (file)
@@ -3,11 +3,11 @@
 
 use crate::errors::{
     SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
-    WrongNumberOfTypeArgumentsToInstrinsic,
+    WrongNumberOfGenericArgumentsToIntrinsic,
 };
 use crate::require_same_types;
 
-use rustc_errors::struct_span_err;
+use rustc_errors::{pluralize, struct_span_err};
 use rustc_hir as hir;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::subst::Subst;
@@ -21,41 +21,54 @@ fn equate_intrinsic_type<'tcx>(
     tcx: TyCtxt<'tcx>,
     it: &hir::ForeignItem<'_>,
     n_tps: usize,
+    n_lts: usize,
     sig: ty::PolyFnSig<'tcx>,
 ) {
-    match it.kind {
-        hir::ForeignItemKind::Fn(..) => {}
+    let (own_counts, span) = match &it.kind {
+        hir::ForeignItemKind::Fn(.., generics) => {
+            let own_counts = tcx.generics_of(it.def_id.to_def_id()).own_counts();
+            (own_counts, generics.span)
+        }
         _ => {
             struct_span_err!(tcx.sess, it.span, E0622, "intrinsic must be a function")
                 .span_label(it.span, "expected a function")
                 .emit();
             return;
         }
-    }
+    };
 
-    let i_n_tps = tcx.generics_of(it.def_id).own_counts().types;
-    if i_n_tps != n_tps {
-        let span = match it.kind {
-            hir::ForeignItemKind::Fn(_, _, ref generics) => generics.span,
-            _ => bug!(),
-        };
+    let gen_count_ok = |found: usize, expected: usize, descr: &str| -> bool {
+        if found != expected {
+            tcx.sess.emit_err(WrongNumberOfGenericArgumentsToIntrinsic {
+                span,
+                found,
+                expected,
+                expected_pluralize: pluralize!(expected),
+                descr,
+            });
+            false
+        } else {
+            true
+        }
+    };
 
-        tcx.sess.emit_err(WrongNumberOfTypeArgumentsToInstrinsic {
-            span,
-            found: i_n_tps,
-            expected: n_tps,
-        });
-        return;
+    if gen_count_ok(own_counts.lifetimes, n_lts, "lifetime")
+        && gen_count_ok(own_counts.types, n_tps, "type")
+        && gen_count_ok(own_counts.consts, 0, "const")
+    {
+        let fty = tcx.mk_fn_ptr(sig);
+        let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType);
+        require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty);
     }
-
-    let fty = tcx.mk_fn_ptr(sig);
-    let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType);
-    require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty);
 }
 
-/// Returns `true` if the given intrinsic is unsafe to call or not.
+/// Returns the unsafety of the given intrinsic.
 pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
     match intrinsic {
+        // When adding a new intrinsic to this list,
+        // it's usually worth updating that intrinsic's documentation
+        // to note that it's safe to call, since
+        // safe extern fns are otherwise unprecedented.
         sym::abort
         | sym::size_of
         | sym::min_align_of
@@ -121,7 +134,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
         })
     };
 
-    let (n_tps, inputs, output, unsafety) = if name_str.starts_with("atomic_") {
+    let (n_tps, n_lts, inputs, output, unsafety) = if name_str.starts_with("atomic_") {
         let split: Vec<&str> = name_str.split('_').collect();
         assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format");
 
@@ -143,7 +156,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                 return;
             }
         };
-        (n_tps, inputs, output, hir::Unsafety::Unsafe)
+        (n_tps, 0, inputs, output, hir::Unsafety::Unsafe)
     } else {
         let unsafety = intrinsic_operation_unsafety(intrinsic_name);
         let (n_tps, inputs, output) = match intrinsic_name {
@@ -367,16 +380,23 @@ 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;
             }
         };
-        (n_tps, inputs, output, unsafety)
+        (n_tps, 0, inputs, output, unsafety)
     };
     let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic);
     let sig = ty::Binder::bind_with_vars(sig, bound_vars);
-    equate_intrinsic_type(tcx, it, n_tps, sig)
+    equate_intrinsic_type(tcx, it, n_tps, n_lts, sig)
 }
 
 /// Type-check `extern "platform-intrinsic" { ... }` functions.
@@ -472,5 +492,5 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
         Abi::PlatformIntrinsic,
     );
     let sig = ty::Binder::dummy(sig);
-    equate_intrinsic_type(tcx, it, n_tps, sig)
+    equate_intrinsic_type(tcx, it, n_tps, 0, sig)
 }
index f546a0d8963544883282aa0140b2783663681ee1..75299bae5ddfd01b64f5c521f944ce383831d5f3 100644 (file)
@@ -101,6 +101,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
 
         let (method_sig, method_predicates) =
             self.normalize_associated_types_in(self.span, (method_sig, method_predicates));
+        let method_sig = ty::Binder::dummy(method_sig);
 
         // Make sure nobody calls `drop()` explicitly.
         self.enforce_illegal_method_limitations(&pick);
@@ -119,12 +120,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // We won't add these if we encountered an illegal sized bound, so that we can use
         // a custom error in that case.
         if illegal_sized_bound.is_none() {
-            let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig, self.tcx));
-            self.add_obligations(method_ty, all_substs, method_predicates);
+            self.add_obligations(self.tcx.mk_fn_ptr(method_sig), all_substs, method_predicates);
         }
 
         // Create the final `MethodCallee`.
-        let callee = MethodCallee { def_id: pick.item.def_id, substs: all_substs, sig: method_sig };
+        let callee = MethodCallee {
+            def_id: pick.item.def_id,
+            substs: all_substs,
+            sig: method_sig.skip_binder(),
+        };
         ConfirmResult { callee, illegal_sized_bound }
     }
 
index 427102afee103535dcf882c84e7ac2180fefa083..2136d925423b912df2543b47aab578bd8de45022 100644 (file)
@@ -3,6 +3,7 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/method-lookup.html
 
 mod confirm;
+mod prelude2021;
 pub mod probe;
 mod suggest;
 
@@ -173,7 +174,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ///
     /// # Arguments
     ///
-    /// Given a method call like `foo.bar::<T1,...Tn>(...)`:
+    /// Given a method call like `foo.bar::<T1,...Tn>(a, b + 1, ...)`:
     ///
     /// * `self`:                  the surrounding `FnCtxt` (!)
     /// * `self_ty`:               the (unadjusted) type of the self expression (`foo`)
@@ -181,6 +182,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// * `span`:                  the span for the method call
     /// * `call_expr`:             the complete method call: (`foo.bar::<T1,...Tn>(...)`)
     /// * `self_expr`:             the self expression (`foo`)
+    /// * `args`:                  the expressions of the arguments (`a, b + 1, ...`)
     #[instrument(level = "debug", skip(self, call_expr, self_expr))]
     pub fn lookup_method(
         &self,
@@ -189,6 +191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         call_expr: &'tcx hir::Expr<'tcx>,
         self_expr: &'tcx hir::Expr<'tcx>,
+        args: &'tcx [hir::Expr<'tcx>],
     ) -> Result<MethodCallee<'tcx>, MethodError<'tcx>> {
         debug!(
             "lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
@@ -198,6 +201,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let pick =
             self.lookup_probe(span, segment.ident, self_ty, call_expr, ProbeScope::TraitsInScope)?;
 
+        self.lint_dot_call_from_2018(self_ty, segment, span, call_expr, self_expr, &pick, args);
+
         for import_id in &pick.import_ids {
             debug!("used_trait_import: {:?}", import_id);
             Lrc::get_mut(&mut self.typeck_results.borrow_mut().used_trait_imports)
@@ -399,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds));
 
         // Also add an obligation for the method type being well-formed.
-        let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig, tcx));
+        let method_ty = tcx.mk_fn_ptr(ty::Binder::dummy(fn_sig));
         debug!(
             "lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}",
             method_ty, obligation
@@ -417,16 +422,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         Some(InferOk { obligations, value: callee })
     }
 
+    /// Performs a [full-qualified function call] (formerly "universal function call") lookup. If
+    /// lookup is successful, it will return the type of definition and the [`DefId`] of the found
+    /// function definition.
+    ///
+    /// [full-qualified function call]: https://doc.rust-lang.org/reference/expressions/call-expr.html#disambiguating-function-calls
+    ///
+    /// # Arguments
+    ///
+    /// Given a function call like `Foo::bar::<T1,...Tn>(...)`:
+    ///
+    /// * `self`:                  the surrounding `FnCtxt` (!)
+    /// * `span`:                  the span of the call, excluding arguments (`Foo::bar::<T1, ...Tn>`)
+    /// * `method_name`:           the identifier of the function within the container type (`bar`)
+    /// * `self_ty`:               the type to search within (`Foo`)
+    /// * `self_ty_span`           the span for the type being searched within (span of `Foo`)
+    /// * `expr_id`:               the [`hir::HirId`] of the expression composing the entire call
     #[instrument(level = "debug", skip(self))]
-    pub fn resolve_ufcs(
+    pub fn resolve_fully_qualified_call(
         &self,
         span: Span,
         method_name: Ident,
         self_ty: Ty<'tcx>,
+        self_ty_span: Span,
         expr_id: hir::HirId,
     ) -> Result<(DefKind, DefId), MethodError<'tcx>> {
         debug!(
-            "resolve_ufcs: method_name={:?} self_ty={:?} expr_id={:?}",
+            "resolve_fully_qualified_call: method_name={:?} self_ty={:?} expr_id={:?}",
             method_name, self_ty, expr_id,
         );
 
@@ -463,18 +485,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             expr_id,
             ProbeScope::TraitsInScope,
         )?;
-        debug!("resolve_ufcs: pick={:?}", pick);
+
+        self.lint_fully_qualified_call_from_2018(
+            span,
+            method_name,
+            self_ty,
+            self_ty_span,
+            expr_id,
+            &pick,
+        );
+
+        debug!("resolve_fully_qualified_call: pick={:?}", pick);
         {
             let mut typeck_results = self.typeck_results.borrow_mut();
             let used_trait_imports = Lrc::get_mut(&mut typeck_results.used_trait_imports).unwrap();
             for import_id in pick.import_ids {
-                debug!("resolve_ufcs: used_trait_import: {:?}", import_id);
+                debug!("resolve_fully_qualified_call: used_trait_import: {:?}", import_id);
                 used_trait_imports.insert(import_id);
             }
         }
 
         let def_kind = pick.item.kind.as_def_kind();
-        debug!("resolve_ufcs: def_kind={:?}, def_id={:?}", def_kind, pick.item.def_id);
+        debug!(
+            "resolve_fully_qualified_call: def_kind={:?}, def_id={:?}",
+            def_kind, pick.item.def_id
+        );
         tcx.check_stability(pick.item.def_id, Some(expr_id), span, Some(method_name.span));
         Ok((def_kind, pick.item.def_id))
     }
diff --git a/compiler/rustc_typeck/src/check/method/prelude2021.rs b/compiler/rustc_typeck/src/check/method/prelude2021.rs
new file mode 100644 (file)
index 0000000..f13e239
--- /dev/null
@@ -0,0 +1,358 @@
+use hir::def_id::DefId;
+use hir::HirId;
+use hir::ItemKind;
+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::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},
+    FnCtxt,
+};
+
+impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+    pub(super) fn lint_dot_call_from_2018(
+        &self,
+        self_ty: Ty<'tcx>,
+        segment: &hir::PathSegment<'_>,
+        span: Span,
+        call_expr: &'tcx hir::Expr<'tcx>,
+        self_expr: &'tcx hir::Expr<'tcx>,
+        pick: &Pick<'tcx>,
+        args: &'tcx [hir::Expr<'tcx>],
+    ) {
+        debug!(
+            "lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
+            segment.ident, self_ty, call_expr, self_expr
+        );
+
+        // Rust 2021 and later is already using the new prelude
+        if span.rust_2021() {
+            return;
+        }
+
+        // These are the method names that were added to prelude in Rust 2021
+        if !matches!(segment.ident.name, sym::try_into) {
+            return;
+        }
+
+        // No need to lint if method came from std/core, as that will now be in the prelude
+        if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
+            return;
+        }
+
+        if matches!(pick.kind, probe::PickKind::InherentImplPick | probe::PickKind::ObjectPick) {
+            // avoid repeatedly adding unneeded `&*`s
+            if pick.autoderefs == 1
+                && matches!(
+                    pick.autoref_or_ptr_adjustment,
+                    Some(probe::AutorefOrPtrAdjustment::Autoref { .. })
+                )
+                && matches!(self_ty.kind(), Ref(..))
+            {
+                return;
+            }
+
+            // if it's an inherent `self` method (not `&self` or `&mut self`), it will take
+            // precedence over the `TryInto` impl, and thus won't break in 2021 edition
+            if pick.autoderefs == 0 && pick.autoref_or_ptr_adjustment.is_none() {
+                return;
+            }
+
+            // 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(
+                RUST_2021_PRELUDE_COLLISIONS,
+                self_expr.hir_id,
+                self_expr.span,
+                |lint| {
+                    let sp = self_expr.span;
+
+                    let mut lint = lint.build(&format!(
+                        "trait method `{}` will become ambiguous in Rust 2021",
+                        segment.ident.name
+                    ));
+
+                    let derefs = "*".repeat(pick.autoderefs);
+
+                    let autoref = match pick.autoref_or_ptr_adjustment {
+                        Some(probe::AutorefOrPtrAdjustment::Autoref {
+                            mutbl: Mutability::Mut,
+                            ..
+                        }) => "&mut ",
+                        Some(probe::AutorefOrPtrAdjustment::Autoref {
+                            mutbl: Mutability::Not,
+                            ..
+                        }) => "&",
+                        Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
+                    };
+                    if let Ok(self_expr) = self.sess().source_map().span_to_snippet(self_expr.span)
+                    {
+                        let self_adjusted = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
+                            pick.autoref_or_ptr_adjustment
+                        {
+                            format!("{}{} as *const _", derefs, self_expr)
+                        } else {
+                            format!("{}{}{}", autoref, derefs, self_expr)
+                        };
+
+                        lint.span_suggestion(
+                            sp,
+                            "disambiguate the method call",
+                            format!("({})", self_adjusted),
+                            Applicability::MachineApplicable,
+                        );
+                    } else {
+                        let self_adjusted = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
+                            pick.autoref_or_ptr_adjustment
+                        {
+                            format!("{}(...) as *const _", derefs)
+                        } else {
+                            format!("{}{}...", autoref, derefs)
+                        };
+                        lint.span_help(
+                            sp,
+                            &format!("disambiguate the method call with `({})`", self_adjusted,),
+                        );
+                    }
+
+                    lint.emit();
+                },
+            );
+        } else {
+            // 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(
+                RUST_2021_PRELUDE_COLLISIONS,
+                call_expr.hir_id,
+                call_expr.span,
+                |lint| {
+                    let sp = call_expr.span;
+                    let trait_name = self.trait_path_or_bare_name(
+                        span,
+                        call_expr.hir_id,
+                        pick.item.container.id(),
+                    );
+
+                    let mut lint = lint.build(&format!(
+                        "trait method `{}` will become ambiguous in Rust 2021",
+                        segment.ident.name
+                    ));
+
+                    let (self_adjusted, precise) = self.adjust_expr(pick, self_expr);
+                    if precise {
+                        let args = args
+                            .iter()
+                            .skip(1)
+                            .map(|arg| {
+                                format!(
+                                    ", {}",
+                                    self.sess().source_map().span_to_snippet(arg.span).unwrap()
+                                )
+                            })
+                            .collect::<String>();
+
+                        lint.span_suggestion(
+                            sp,
+                            "disambiguate the associated function",
+                            format!(
+                                "{}::{}({}{})",
+                                trait_name, segment.ident.name, self_adjusted, args
+                            ),
+                            Applicability::MachineApplicable,
+                        );
+                    } else {
+                        lint.span_help(
+                            sp,
+                            &format!(
+                                "disambiguate the associated function with `{}::{}(...)`",
+                                trait_name, segment.ident,
+                            ),
+                        );
+                    }
+
+                    lint.emit();
+                },
+            );
+        }
+    }
+
+    pub(super) fn lint_fully_qualified_call_from_2018(
+        &self,
+        span: Span,
+        method_name: Ident,
+        self_ty: Ty<'tcx>,
+        self_ty_span: Span,
+        expr_id: hir::HirId,
+        pick: &Pick<'tcx>,
+    ) {
+        // Rust 2021 and later is already using the new prelude
+        if span.rust_2021() {
+            return;
+        }
+
+        // These are the fully qualified methods added to prelude in Rust 2021
+        if !matches!(method_name.name, sym::try_into | sym::try_from | sym::from_iter) {
+            return;
+        }
+
+        // No need to lint if method came from std/core, as that will now be in the prelude
+        if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
+            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(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());
+            let trait_generics = self.tcx.generics_of(pick.item.container.id());
+
+            let parameter_count = trait_generics.count() - (trait_generics.has_self as usize);
+            let trait_name = if parameter_count == 0 {
+                trait_path
+            } else {
+                format!(
+                    "{}<{}>",
+                    trait_path,
+                    std::iter::repeat("_").take(parameter_count).collect::<Vec<_>>().join(", ")
+                )
+            };
+
+            let mut lint = lint.build(&format!(
+                "trait-associated function `{}` will become ambiguous in Rust 2021",
+                method_name.name
+            ));
+
+            let self_ty = self
+                .sess()
+                .source_map()
+                .span_to_snippet(self_ty_span)
+                .unwrap_or_else(|_| self_ty.to_string());
+
+            lint.span_suggestion(
+                span,
+                "disambiguate the associated function",
+                format!("<{} as {}>::{}", self_ty, trait_name, method_name.name,),
+                Applicability::MachineApplicable,
+            );
+
+            lint.emit();
+        });
+    }
+
+    fn trait_path_or_bare_name(
+        &self,
+        span: Span,
+        expr_hir_id: HirId,
+        trait_def_id: DefId,
+    ) -> String {
+        self.trait_path(span, expr_hir_id, trait_def_id).unwrap_or_else(|| {
+            let key = self.tcx.def_key(trait_def_id);
+            format!("{}", key.disambiguated_data.data)
+        })
+    }
+
+    fn trait_path(&self, span: Span, expr_hir_id: HirId, trait_def_id: DefId) -> Option<String> {
+        let applicable_traits = self.tcx.in_scope_traits(expr_hir_id)?;
+        let applicable_trait = applicable_traits.iter().find(|t| t.def_id == trait_def_id)?;
+        if applicable_trait.import_ids.is_empty() {
+            // The trait was declared within the module, we only need to use its name.
+            return None;
+        }
+
+        let import_items: Vec<_> = applicable_trait
+            .import_ids
+            .iter()
+            .map(|&import_id| {
+                let hir_id = self.tcx.hir().local_def_id_to_hir_id(import_id);
+                self.tcx.hir().expect_item(hir_id)
+            })
+            .collect();
+
+        // Find an identifier with which this trait was imported (note that `_` doesn't count).
+        let any_id = import_items
+            .iter()
+            .filter_map(|item| if item.ident.name != Underscore { Some(item.ident) } else { None })
+            .next();
+        if let Some(any_id) = any_id {
+            return Some(format!("{}", any_id));
+        }
+
+        // All that is left is `_`! We need to use the full path. It doesn't matter which one we pick,
+        // so just take the first one.
+        match import_items[0].kind {
+            ItemKind::Use(path, _) => Some(
+                path.segments
+                    .iter()
+                    .map(|segment| segment.ident.to_string())
+                    .collect::<Vec<_>>()
+                    .join("::"),
+            ),
+            _ => {
+                span_bug!(span, "unexpected item kind, expected a use: {:?}", import_items[0].kind);
+            }
+        }
+    }
+
+    /// Creates a string version of the `expr` that includes explicit adjustments.
+    /// Returns the string and also a bool indicating whther this is a *precise*
+    /// suggestion.
+    fn adjust_expr(&self, pick: &Pick<'tcx>, expr: &hir::Expr<'tcx>) -> (String, bool) {
+        let derefs = "*".repeat(pick.autoderefs);
+
+        let autoref = match pick.autoref_or_ptr_adjustment {
+            Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl: Mutability::Mut, .. }) => "&mut ",
+            Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl: Mutability::Not, .. }) => "&",
+            Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
+        };
+
+        let (expr_text, precise) =
+            if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {
+                (expr_text, true)
+            } else {
+                (format!("(..)"), false)
+            };
+
+        let adjusted_text = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
+            pick.autoref_or_ptr_adjustment
+        {
+            format!("{}{} as *const _", derefs, expr_text)
+        } else {
+            format!("{}{}{}", autoref, derefs, expr_text)
+        };
+
+        (adjusted_text, precise)
+    }
+}
index 440e0f4e1a2acfbbaf27c96a01fe94cf766a7db6..9037ffe49a9a26c2b3335926e2125d05e8968c9a 100644 (file)
@@ -668,7 +668,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::Slice(_) => {
-                for &lang_def_id in &[
+                for lang_def_id in [
                     lang_items.slice_impl(),
                     lang_items.slice_u8_impl(),
                     lang_items.slice_alloc_impl(),
index 16382c7e7a4bdce9ce540166f8416057facbc5ef..77586ce48529c897c94ad1733cc6a8927d69dceb 100644 (file)
@@ -933,6 +933,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     item_name
                 );
                 err.span_label(item_name.span, &format!("private {}", kind));
+                let sp = self
+                    .tcx
+                    .hir()
+                    .span_if_local(def_id)
+                    .unwrap_or_else(|| self.tcx.def_span(def_id));
+                err.span_label(sp, &format!("private {} defined here", kind));
                 self.suggest_valid_traits(&mut err, out_of_scope_traits);
                 err.emit();
             }
@@ -1591,7 +1597,7 @@ fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] {
             _ => {}
         }
     }
-    for &cnum in tcx.crates().iter() {
+    for &cnum in tcx.crates(()).iter() {
         let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
         handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
     }
@@ -1650,16 +1656,16 @@ impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
                 _ => {
                     if self.span.map_or(true, |span| item.span < span) {
                         if !item.span.from_expansion() {
+                            self.span = Some(item.span.shrink_to_lo());
                             // Don't insert between attributes and an item.
                             let attrs = self.tcx.hir().attrs(item.hir_id());
-                            if attrs.is_empty() {
-                                self.span = Some(item.span.shrink_to_lo());
-                            } else {
-                                // Find the first attribute on the item.
-                                for attr in attrs {
-                                    if self.span.map_or(true, |span| attr.span < span) {
-                                        self.span = Some(attr.span.shrink_to_lo());
-                                    }
+                            // Find the first attribute on the item.
+                            // FIXME: This is broken for active attributes.
+                            for attr in attrs {
+                                if !attr.span.is_dummy()
+                                    && self.span.map_or(true, |span| attr.span < span)
+                                {
+                                    self.span = Some(attr.span.shrink_to_lo());
                                 }
                             }
                         }
index ad7853b7cd0f10282626d5a4d087ca37f6ccd822..d30b057e26fe369b403258cd34610e97fc4d8680 100644 (file)
@@ -112,17 +112,15 @@ use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::Idx;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
-use rustc_middle::ty::{self, RegionKind, Ty, TyCtxt, UserType};
+use rustc_middle::ty::{self, Ty, TyCtxt, UserType};
 use rustc_session::config;
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
+use rustc_span::source_map::DUMMY_SP;
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::{self, BytePos, MultiSpan, Span};
-use rustc_span::{source_map::DUMMY_SP, sym};
 use rustc_target::abi::VariantIdx;
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
@@ -174,13 +172,12 @@ impl Needs {
 pub struct UnsafetyState {
     pub def: hir::HirId,
     pub unsafety: hir::Unsafety,
-    pub unsafe_push_count: u32,
     from_fn: bool,
 }
 
 impl UnsafetyState {
     pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
-        UnsafetyState { def, unsafety, unsafe_push_count: 0, from_fn: true }
+        UnsafetyState { def, unsafety, from_fn: true }
     }
 
     pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
@@ -193,19 +190,11 @@ impl UnsafetyState {
             hir::Unsafety::Unsafe if self.from_fn => self,
 
             unsafety => {
-                let (unsafety, def, count) = match blk.rules {
-                    BlockCheckMode::PushUnsafeBlock(..) => {
-                        (unsafety, blk.hir_id, self.unsafe_push_count.checked_add(1).unwrap())
-                    }
-                    BlockCheckMode::PopUnsafeBlock(..) => {
-                        (unsafety, blk.hir_id, self.unsafe_push_count.checked_sub(1).unwrap())
-                    }
-                    BlockCheckMode::UnsafeBlock(..) => {
-                        (hir::Unsafety::Unsafe, blk.hir_id, self.unsafe_push_count)
-                    }
-                    BlockCheckMode::DefaultBlock => (unsafety, self.def, self.unsafe_push_count),
+                let (unsafety, def) = match blk.rules {
+                    BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
+                    BlockCheckMode::DefaultBlock => (unsafety, self.def),
                 };
-                UnsafetyState { def, unsafety, unsafe_push_count: count, from_fn: false }
+                UnsafetyState { def, unsafety, from_fn: false }
             }
         }
     }
@@ -330,117 +319,6 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet<LocalDe
     &*tcx.typeck(def_id).used_trait_imports
 }
 
-/// Inspects the substs of opaque types, replacing any inference variables
-/// with proper generic parameter from the identity substs.
-///
-/// This is run after we normalize the function signature, to fix any inference
-/// variables introduced by the projection of associated types. This ensures that
-/// any opaque types used in the signature continue to refer to generic parameters,
-/// allowing them to be considered for defining uses in the function body
-///
-/// For example, consider this code.
-///
-/// ```rust
-/// trait MyTrait {
-///     type MyItem;
-///     fn use_it(self) -> Self::MyItem
-/// }
-/// impl<T, I> MyTrait for T where T: Iterator<Item = I> {
-///     type MyItem = impl Iterator<Item = I>;
-///     fn use_it(self) -> Self::MyItem {
-///         self
-///     }
-/// }
-/// ```
-///
-/// When we normalize the signature of `use_it` from the impl block,
-/// we will normalize `Self::MyItem` to the opaque type `impl Iterator<Item = I>`
-/// However, this projection result may contain inference variables, due
-/// to the way that projection works. We didn't have any inference variables
-/// in the signature to begin with - leaving them in will cause us to incorrectly
-/// conclude that we don't have a defining use of `MyItem`. By mapping inference
-/// variables back to the actual generic parameters, we will correctly see that
-/// we have a defining use of `MyItem`
-fn fixup_opaque_types<'tcx, T>(tcx: TyCtxt<'tcx>, val: T) -> T
-where
-    T: TypeFoldable<'tcx>,
-{
-    struct FixupFolder<'tcx> {
-        tcx: TyCtxt<'tcx>,
-    }
-
-    impl<'tcx> TypeFolder<'tcx> for FixupFolder<'tcx> {
-        fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
-            self.tcx
-        }
-
-        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-            match *ty.kind() {
-                ty::Opaque(def_id, substs) => {
-                    debug!("fixup_opaque_types: found type {:?}", ty);
-                    // Here, we replace any inference variables that occur within
-                    // the substs of an opaque type. By definition, any type occurring
-                    // in the substs has a corresponding generic parameter, which is what
-                    // we replace it with.
-                    // This replacement is only run on the function signature, so any
-                    // inference variables that we come across must be the rust of projection
-                    // (there's no other way for a user to get inference variables into
-                    // a function signature).
-                    if ty.needs_infer() {
-                        let new_substs = InternalSubsts::for_item(self.tcx, def_id, |param, _| {
-                            let old_param = substs[param.index as usize];
-                            match old_param.unpack() {
-                                GenericArgKind::Type(old_ty) => {
-                                    if let ty::Infer(_) = old_ty.kind() {
-                                        // Replace inference type with a generic parameter
-                                        self.tcx.mk_param_from_def(param)
-                                    } else {
-                                        old_param.fold_with(self)
-                                    }
-                                }
-                                GenericArgKind::Const(old_const) => {
-                                    if let ty::ConstKind::Infer(_) = old_const.val {
-                                        // This should never happen - we currently do not support
-                                        // 'const projections', e.g.:
-                                        // `impl<T: SomeTrait> MyTrait for T where <T as SomeTrait>::MyConst == 25`
-                                        // which should be the only way for us to end up with a const inference
-                                        // variable after projection. If Rust ever gains support for this kind
-                                        // of projection, this should *probably* be changed to
-                                        // `self.tcx.mk_param_from_def(param)`
-                                        bug!(
-                                            "Found infer const: `{:?}` in opaque type: {:?}",
-                                            old_const,
-                                            ty
-                                        );
-                                    } else {
-                                        old_param.fold_with(self)
-                                    }
-                                }
-                                GenericArgKind::Lifetime(old_region) => {
-                                    if let RegionKind::ReVar(_) = old_region {
-                                        self.tcx.mk_param_from_def(param)
-                                    } else {
-                                        old_param.fold_with(self)
-                                    }
-                                }
-                            }
-                        });
-                        let new_ty = self.tcx.mk_opaque(def_id, new_substs);
-                        debug!("fixup_opaque_types: new type: {:?}", new_ty);
-                        new_ty
-                    } else {
-                        ty
-                    }
-                }
-                _ => ty.super_fold_with(self),
-            }
-        }
-    }
-
-    debug!("fixup_opaque_types({:?})", val);
-    val.fold_with(&mut FixupFolder { tcx })
-}
-
 fn typeck_const_arg<'tcx>(
     tcx: TyCtxt<'tcx>,
     (did, param_did): (LocalDefId, DefId),
@@ -508,7 +386,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);
@@ -519,8 +397,6 @@ fn typeck_with_fallback<'tcx>(
                 fn_sig,
             );
 
-            let fn_sig = fixup_opaque_types(tcx, fn_sig);
-
             let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None).0;
             fcx
         } else {
@@ -565,19 +441,12 @@ fn typeck_with_fallback<'tcx>(
             let expected_type = fcx.normalize_associated_types_in(body.value.span, expected_type);
             fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
 
-            let revealed_ty = fcx.instantiate_opaque_types_from_value(
-                id,
-                expected_type,
-                body.value.span,
-                Some(sym::impl_trait_in_bindings),
-            );
-
             // Gather locals in statics (because of block expressions).
-            GatherLocalsVisitor::new(&fcx, id).visit_body(body);
+            GatherLocalsVisitor::new(&fcx).visit_body(body);
 
-            fcx.check_expr_coercable_to_type(&body.value, revealed_ty, None);
+            fcx.check_expr_coercable_to_type(&body.value, expected_type, None);
 
-            fcx.write_ty(id, revealed_ty);
+            fcx.write_ty(id, expected_type);
 
             fcx
         };
@@ -697,66 +566,6 @@ fn get_owner_return_paths(
         })
 }
 
-/// Emit an error for recursive opaque types in a `let` binding.
-fn binding_opaque_type_cycle_error(
-    tcx: TyCtxt<'tcx>,
-    def_id: LocalDefId,
-    span: Span,
-    partially_expanded_type: Ty<'tcx>,
-) {
-    let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
-    err.span_label(span, "cannot resolve opaque type");
-    // Find the owner that declared this `impl Trait` type.
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    let mut prev_hir_id = hir_id;
-    let mut hir_id = tcx.hir().get_parent_node(hir_id);
-    while let Some(node) = tcx.hir().find(hir_id) {
-        match node {
-            hir::Node::Local(hir::Local {
-                pat,
-                init: None,
-                ty: Some(ty),
-                source: hir::LocalSource::Normal,
-                ..
-            }) => {
-                err.span_label(pat.span, "this binding might not have a concrete type");
-                err.span_suggestion_verbose(
-                    ty.span.shrink_to_hi(),
-                    "set the binding to a value for a concrete type to be resolved",
-                    " = /* value */".to_string(),
-                    Applicability::HasPlaceholders,
-                );
-            }
-            hir::Node::Local(hir::Local {
-                init: Some(expr),
-                source: hir::LocalSource::Normal,
-                ..
-            }) => {
-                let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-                let typeck_results =
-                    tcx.typeck(tcx.hir().local_def_id(tcx.hir().get_parent_item(hir_id)));
-                if let Some(ty) = typeck_results.node_type_opt(expr.hir_id) {
-                    err.span_label(
-                        expr.span,
-                        &format!(
-                            "this is of type `{}`, which doesn't constrain \
-                             `{}` enough to arrive to a concrete type",
-                            ty, partially_expanded_type
-                        ),
-                    );
-                }
-            }
-            _ => {}
-        }
-        if prev_hir_id == hir_id {
-            break;
-        }
-        prev_hir_id = hir_id;
-        hir_id = tcx.hir().get_parent_node(hir_id);
-    }
-    err.emit();
-}
-
 // Forbid defining intrinsics in Rust code,
 // as they must always be defined by the compiler.
 fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
@@ -858,7 +667,7 @@ fn missing_items_err(
     // Obtain the level of indentation ending in `sugg_sp`.
     let indentation = tcx.sess.source_map().span_to_margin(sugg_sp).unwrap_or(0);
     // Make the whitespace that will make the suggestion have the right indentation.
-    let padding: String = std::iter::repeat(" ").take(indentation).collect();
+    let padding: String = " ".repeat(indentation);
 
     for trait_item in missing_items {
         let snippet = suggestion_signature(&trait_item, tcx);
@@ -1029,7 +838,7 @@ fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
     }
 }
 
-/// Emit an error when encountering more or less than one variant in a transparent enum.
+/// Emit an error when encountering two or more variants in a transparent enum.
 fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, did: DefId) {
     let variant_spans: Vec<_> = adt
         .variants
@@ -1048,7 +857,7 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, d
     err.emit();
 }
 
-/// Emit an error when encountering more or less than one non-zero-sized field in a transparent
+/// Emit an error when encountering two or more non-zero-sized fields in a transparent
 /// enum.
 fn bad_non_zero_sized_fields<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -1057,7 +866,7 @@ fn bad_non_zero_sized_fields<'tcx>(
     field_spans: impl Iterator<Item = Span>,
     sp: Span,
 ) {
-    let msg = format!("needs exactly one non-zero-sized field, but has {}", field_count);
+    let msg = format!("needs at most one non-zero-sized field, but has {}", field_count);
     let mut err = struct_span_err!(
         tcx.sess,
         sp,
index 3ac760e23634e33f0d57142d4148e99602b84724..981a040e66072991b67be655ec52e41b9d2ca113 100644 (file)
@@ -160,7 +160,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ti: TopInfo<'tcx>,
     ) {
         let path_res = match &pat.kind {
-            PatKind::Path(qpath) => Some(self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span)),
+            PatKind::Path(qpath) => {
+                Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span))
+            }
             _ => None,
         };
         let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
@@ -862,7 +864,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         pat: &'tcx Pat<'tcx>,
         qpath: &'tcx hir::QPath<'tcx>,
-        subpats: &'tcx [&'tcx Pat<'tcx>],
+        subpats: &'tcx [Pat<'tcx>],
         ddpos: Option<usize>,
         expected: Ty<'tcx>,
         def_bm: BindingMode,
@@ -904,7 +906,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // Resolve the path and check the definition for errors.
-        let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span);
+        let (res, opt_ty, segments) =
+            self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
         if res == Res::Err {
             self.set_tainted_by_errors();
             on_error();
@@ -979,7 +982,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat_span: Span,
         res: Res,
         qpath: &hir::QPath<'_>,
-        subpats: &'tcx [&'tcx Pat<'tcx>],
+        subpats: &'tcx [Pat<'tcx>],
         fields: &'tcx [ty::FieldDef],
         expected: Ty<'tcx>,
         had_err: bool,
@@ -1109,7 +1112,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn check_pat_tuple(
         &self,
         span: Span,
-        elements: &'tcx [&'tcx Pat<'tcx>],
+        elements: &'tcx [Pat<'tcx>],
         ddpos: Option<usize>,
         expected: Ty<'tcx>,
         def_bm: BindingMode,
@@ -1743,9 +1746,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn check_pat_slice(
         &self,
         span: Span,
-        before: &'tcx [&'tcx Pat<'tcx>],
+        before: &'tcx [Pat<'tcx>],
         slice: Option<&'tcx Pat<'tcx>>,
-        after: &'tcx [&'tcx Pat<'tcx>],
+        after: &'tcx [Pat<'tcx>],
         expected: Ty<'tcx>,
         def_bm: BindingMode,
         ti: TopInfo<'tcx>,
index 652b82f1063c9c48c60d71f2f2980e47a2c750ca..055072d3a1d9d4a9cf020d6d7f999592b7029091 100644 (file)
@@ -82,7 +82,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             expr, base_expr, adjusted_ty, index_ty
         );
 
-        for &unsize in &[false, true] {
+        for unsize in [false, true] {
             let mut self_ty = adjusted_ty;
             if unsize {
                 // We only unsize arrays here.
index 6baa185406e207f7373f23588d010bbc40aaf16a..39874f48eb014071aa5d279b5e3cf48bba7dc5e6 100644 (file)
@@ -42,12 +42,15 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_infer::infer::UpvarRegion;
 use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind};
 use rustc_middle::mir::FakeReadCause;
-use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, TypeckResults, UpvarSubsts};
+use rustc_middle::ty::{
+    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;
@@ -79,6 +82,22 @@ impl<'a, 'tcx> FnCtxt<'a, '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>,
 }
@@ -146,9 +165,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             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(),
         };
@@ -165,19 +181,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             "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, 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);
         }
 
+        let after_feature_tys = self.final_upvar_tys(closure_def_id);
+
         // We now fake capture information for all variables that are mentioned within the closure
         // We do this after handling migrations so that min_captures computes before
-        if !self.tcx.features().capture_disjoint_fields {
+        if !enable_precise_capture(self.tcx, span) {
             let mut capture_information: InferredCaptureInformation<'tcx> = Default::default();
 
             if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
@@ -203,17 +225,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.compute_min_captures(closure_def_id, capture_information);
         }
 
+        let before_feature_tys = self.final_upvar_tys(closure_def_id);
+
         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() {
-                let origin = if self.tcx.features().capture_disjoint_fields {
-                    (origin.0, restrict_capture_precision(origin.1))
+            if let Some(origin) = origin {
+                let origin = if enable_precise_capture(self.tcx, span) {
+                    (origin.0, origin.1)
                 } else {
                     (origin.0, Place { projections: vec![], ..origin.1 })
                 };
@@ -258,6 +281,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .collect();
         self.typeck_results.borrow_mut().closure_fake_reads.insert(closure_def_id, fake_reads);
 
+        if self.tcx.sess.opts.debugging_opts.profile_closures {
+            self.typeck_results.borrow_mut().closure_size_eval.insert(
+                closure_def_id,
+                ClosureSizeProfileData {
+                    before_feature_tys: self.tcx.mk_tup(before_feature_tys.into_iter()),
+                    after_feature_tys: self.tcx.mk_tup(after_feature_tys.into_iter()),
+                },
+            );
+        }
+
         // If we are also inferred the closure kind here,
         // process any deferred resolutions.
         let deferred_call_resolutions = self.remove_deferred_call_resolutions(closure_def_id);
@@ -285,17 +318,90 @@ impl<'a, 'tcx> FnCtxt<'a, '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.
@@ -385,8 +491,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 base => bug!("Expected upvar, found={:?}", base),
             };
 
-            let place = restrict_capture_precision(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);
@@ -487,18 +591,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             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!(
-                            "{} affected for closure because of `capture_disjoint_fields`",
+                            "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) =
                         match self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
@@ -544,13 +689,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         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 {
@@ -560,141 +705,121 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         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
@@ -707,8 +832,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// - 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,
@@ -716,11 +841,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         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) =
@@ -733,21 +858,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             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();
 
@@ -763,10 +896,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 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
@@ -782,15 +915,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// - 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 {
@@ -798,38 +932,79 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         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,
+            ),
         )
     }
 
@@ -943,12 +1118,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         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((
-                drop_trait,
-                ty,
-                ty_params,
-                self.tcx.param_env(closure_def_id.expect_local()),
-            ))
+            self.infcx
+                .type_implements_trait(
+                    drop_trait,
+                    ty,
+                    ty_params,
+                    self.tcx.param_env(closure_def_id.expect_local()),
+                )
+                .must_apply_modulo_regions()
         };
 
         let is_drop_defined_for_ty = is_drop_defined_for_ty(base_path_ty);
@@ -1275,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>,
 
@@ -1283,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.
     ///
@@ -1332,34 +1528,11 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
         &mut self,
         place_with_id: &PlaceWithHirId<'tcx>,
         diag_expr_id: hir::HirId,
-        mode: euv::ConsumeMode,
     ) {
         debug!(
-            "adjust_upvar_borrow_kind_for_consume(place_with_id={:?}, diag_expr_id={:?}, mode={:?})",
-            place_with_id, diag_expr_id, mode
+            "adjust_upvar_borrow_kind_for_consume(place_with_id={:?}, diag_expr_id={:?})",
+            place_with_id, diag_expr_id
         );
-
-        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) => {}
-        };
-
-        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
@@ -1371,16 +1544,6 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
 
         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),
@@ -1458,22 +1621,11 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
             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.
@@ -1512,48 +1664,6 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
         };
     }
 
-    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>,
@@ -1562,12 +1672,12 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
         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 {
@@ -1597,21 +1707,14 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
         }
     }
 
-    fn consume(
-        &mut self,
-        place_with_id: &PlaceWithHirId<'tcx>,
-        diag_expr_id: hir::HirId,
-        mode: euv::ConsumeMode,
-    ) {
-        debug!(
-            "consume(place_with_id={:?}, diag_expr_id={:?}, mode={:?})",
-            place_with_id, diag_expr_id, mode
-        );
+    fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
+        debug!("consume(place_with_id={:?}, diag_expr_id={:?})", place_with_id, diag_expr_id);
+
         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);
     }
 
     fn borrow(
@@ -1625,11 +1728,15 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
             place_with_id, diag_expr_id, bk
         );
 
+        // We only want repr packed restriction to be applied to reading references into a packed
+        // 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,
             self.fcx.param_env,
             &place_with_id.place,
         );
+
         let place_with_id = PlaceWithHirId { place, ..*place_with_id };
 
         if !self.capture_information.contains_key(&place_with_id.place) {
@@ -1696,15 +1803,65 @@ fn restrict_capture_precision<'tcx>(mut place: Place<'tcx>) -> Place<'tcx> {
     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 {
@@ -1769,8 +1926,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)
 }
@@ -1780,10 +1941,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(", ");
@@ -1924,3 +2085,55 @@ fn determine_place_ancestry_relation(
         PlaceAncestryRelation::Divergent
     }
 }
+
+/// 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.
+///
+/// `span` is the span of the closure.
+fn enable_precise_capture(tcx: TyCtxt<'_>, span: Span) -> bool {
+    // We use span here to ensure that if the closure was generated by a macro with a different
+    // edition.
+    tcx.features().capture_disjoint_fields || span.rust_2021()
+}
index 7436edccf84bb3a84361f4f34604d9f02e9ad090..e33cc603b5e543cc95cd8b3699642cb2ec2761e4 100644 (file)
@@ -22,8 +22,9 @@ use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
 use rustc_trait_selection::opaque_types::may_define_opaque_type;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
-use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, WellFormedLoc};
 
+use std::convert::TryInto;
 use std::iter;
 use std::ops::ControlFlow;
 
@@ -379,15 +380,14 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
     }
 }
 
+#[tracing::instrument(level = "debug", skip(tcx, span, sig_if_method))]
 fn check_associated_item(
     tcx: TyCtxt<'_>,
     item_id: hir::HirId,
     span: Span,
     sig_if_method: Option<&hir::FnSig<'_>>,
 ) {
-    debug!("check_associated_item: {:?}", item_id);
-
-    let code = ObligationCauseCode::MiscObligation;
+    let code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner())));
     for_id(tcx, item_id, span).with_fcx(|fcx| {
         let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id));
 
@@ -401,12 +401,15 @@ fn check_associated_item(
         match item.kind {
             ty::AssocKind::Const => {
                 let ty = fcx.tcx.type_of(item.def_id);
-                let ty = fcx.normalize_associated_types_in(span, ty);
+                let ty = fcx.normalize_associated_types_in_wf(
+                    span,
+                    ty,
+                    WellFormedLoc::Ty(item_id.expect_owner()),
+                );
                 fcx.register_wf_obligation(ty.into(), span, code.clone());
             }
             ty::AssocKind::Fn => {
                 let sig = fcx.tcx.fn_sig(item.def_id);
-                let sig = fcx.normalize_associated_types_in(span, sig);
                 let hir_sig = sig_if_method.expect("bad signature for method");
                 check_fn_or_method(
                     fcx,
@@ -424,7 +427,11 @@ fn check_associated_item(
                 }
                 if item.defaultness.has_value() {
                     let ty = fcx.tcx.type_of(item.def_id);
-                    let ty = fcx.normalize_associated_types_in(span, ty);
+                    let ty = fcx.normalize_associated_types_in_wf(
+                        span,
+                        ty,
+                        WellFormedLoc::Ty(item_id.expect_owner()),
+                    );
                     fcx.register_wf_obligation(ty.into(), span, code.clone());
                 }
             }
@@ -516,7 +523,7 @@ fn check_type_defn<'tcx, F>(
                 fcx.register_wf_obligation(
                     field.ty.into(),
                     field.span,
-                    ObligationCauseCode::MiscObligation,
+                    ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(field.def_id))),
                 )
             }
 
@@ -611,7 +618,6 @@ fn check_item_fn(
     for_id(tcx, item_id, span).with_fcx(|fcx| {
         let def_id = tcx.hir().local_def_id(item_id);
         let sig = tcx.fn_sig(def_id);
-        let sig = fcx.normalize_associated_types_in(span, sig);
         let mut implied_bounds = vec![];
         check_fn_or_method(fcx, ident.span, sig, decl, def_id.to_def_id(), &mut implied_bounds);
         implied_bounds
@@ -623,7 +629,11 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
 
     for_id(tcx, item_id, ty_span).with_fcx(|fcx| {
         let ty = tcx.type_of(tcx.hir().local_def_id(item_id));
-        let item_ty = fcx.normalize_associated_types_in(ty_span, ty);
+        let item_ty = fcx.normalize_associated_types_in_wf(
+            ty_span,
+            ty,
+            WellFormedLoc::Ty(item_id.expect_owner()),
+        );
 
         let mut forbid_unsized = true;
         if allow_foreign_ty {
@@ -633,7 +643,11 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
             }
         }
 
-        fcx.register_wf_obligation(item_ty.into(), ty_span, ObligationCauseCode::MiscObligation);
+        fcx.register_wf_obligation(
+            item_ty.into(),
+            ty_span,
+            ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner()))),
+        );
         if forbid_unsized {
             fcx.register_bound(
                 item_ty,
@@ -647,14 +661,13 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
     });
 }
 
+#[tracing::instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))]
 fn check_impl<'tcx>(
     tcx: TyCtxt<'tcx>,
     item: &'tcx hir::Item<'tcx>,
     ast_self_ty: &hir::Ty<'_>,
     ast_trait_ref: &Option<hir::TraitRef<'_>>,
 ) {
-    debug!("check_impl: {:?}", item);
-
     for_item(tcx, item).with_fcx(|fcx| {
         match *ast_trait_ref {
             Some(ref ast_trait_ref) => {
@@ -672,6 +685,7 @@ fn check_impl<'tcx>(
                     ast_trait_ref.path.span,
                     Some(item),
                 );
+                debug!(?obligations);
                 for obligation in obligations {
                     fcx.register_predicate(obligation);
                 }
@@ -682,7 +696,9 @@ fn check_impl<'tcx>(
                 fcx.register_wf_obligation(
                     self_ty.into(),
                     ast_self_ty.span,
-                    ObligationCauseCode::MiscObligation,
+                    ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(
+                        item.hir_id().expect_owner(),
+                    ))),
                 );
             }
         }
@@ -738,15 +754,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::WellFormed(None),
+                        );
+                    }
                 }
             }
             // Doesn't have defaults.
@@ -783,14 +803,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);
@@ -902,12 +914,49 @@ fn check_fn_or_method<'fcx, 'tcx>(
     def_id: DefId,
     implied_bounds: &mut Vec<Ty<'tcx>>,
 ) {
-    let sig = fcx.normalize_associated_types_in(span, sig);
     let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig);
 
-    for (&input_ty, ty) in iter::zip(sig.inputs(), hir_decl.inputs) {
-        fcx.register_wf_obligation(input_ty.into(), ty.span, ObligationCauseCode::MiscObligation);
+    // Normalize the input and output types one at a time, using a different
+    // `WellFormedLoc` for each. We cannot call `normalize_associated_types`
+    // on the entire `FnSig`, since this would use the same `WellFormedLoc`
+    // for each type, preventing the HIR wf check from generating
+    // a nice error message.
+    let ty::FnSig { mut inputs_and_output, c_variadic, unsafety, abi } = sig;
+    inputs_and_output =
+        fcx.tcx.mk_type_list(inputs_and_output.iter().enumerate().map(|(i, ty)| {
+            fcx.normalize_associated_types_in_wf(
+                span,
+                ty,
+                WellFormedLoc::Param {
+                    function: def_id.expect_local(),
+                    // Note that the `param_idx` of the output type is
+                    // one greater than the index of the last input type.
+                    param_idx: i.try_into().unwrap(),
+                },
+            )
+        }));
+    // Manually call `normalize_assocaited_types_in` on the other types
+    // in `FnSig`. This ensures that if the types of these fields
+    // ever change to include projections, we will start normalizing
+    // them automatically.
+    let sig = ty::FnSig {
+        inputs_and_output,
+        c_variadic: fcx.normalize_associated_types_in(span, c_variadic),
+        unsafety: fcx.normalize_associated_types_in(span, unsafety),
+        abi: fcx.normalize_associated_types_in(span, abi),
+    };
+
+    for (i, (&input_ty, ty)) in iter::zip(sig.inputs(), hir_decl.inputs).enumerate() {
+        fcx.register_wf_obligation(
+            input_ty.into(),
+            ty.span,
+            ObligationCauseCode::WellFormed(Some(WellFormedLoc::Param {
+                function: def_id.expect_local(),
+                param_idx: i.try_into().unwrap(),
+            })),
+        );
     }
+
     implied_bounds.extend(sig.inputs());
 
     fcx.register_wf_obligation(
@@ -1081,20 +1130,15 @@ fn check_method_receiver<'fcx, 'tcx>(
     let span = fn_sig.decl.inputs[0].span;
 
     let sig = fcx.tcx.fn_sig(method.def_id);
-    let sig = fcx.normalize_associated_types_in(span, sig);
     let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, sig);
+    let sig = fcx.normalize_associated_types_in(span, sig);
 
     debug!("check_method_receiver: sig={:?}", sig);
 
     let self_ty = fcx.normalize_associated_types_in(span, self_ty);
-    let self_ty =
-        fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(self_ty, fcx.tcx));
 
     let receiver_ty = sig.inputs()[0];
-
     let receiver_ty = fcx.normalize_associated_types_in(span, receiver_ty);
-    let receiver_ty =
-        fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(receiver_ty, fcx.tcx));
 
     if fcx.tcx.features().arbitrary_self_types {
         if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
@@ -1422,6 +1466,7 @@ struct AdtVariant<'tcx> {
 
 struct AdtField<'tcx> {
     ty: Ty<'tcx>,
+    def_id: LocalDefId,
     span: Span,
 }
 
@@ -1432,11 +1477,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .fields()
             .iter()
             .map(|field| {
-                let field_ty = self.tcx.type_of(self.tcx.hir().local_def_id(field.hir_id));
+                let def_id = self.tcx.hir().local_def_id(field.hir_id);
+                let field_ty = self.tcx.type_of(def_id);
                 let field_ty = self.normalize_associated_types_in(field.ty.span, field_ty);
                 let field_ty = self.resolve_vars_if_possible(field_ty);
                 debug!("non_enum_variant: type of field {:?} is {:?}", field, field_ty);
-                AdtField { ty: field_ty, span: field.ty.span }
+                AdtField { ty: field_ty, span: field.ty.span, def_id }
             })
             .collect();
         AdtVariant { fields, explicit_discr: None }
index 032cc7ee2334abc18a641f34cbb022dc577ee171..935bcc9f32e2bb16a5b1be3587f398ef79433064 100644 (file)
@@ -15,7 +15,7 @@ use rustc_middle::hir::place::Place as HirPlace;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_trait_selection::opaque_types::InferCtxtExt;
@@ -60,6 +60,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
         wbcx.visit_body(body);
         wbcx.visit_min_capture_map();
+        wbcx.eval_closure_size();
         wbcx.visit_fake_reads_map();
         wbcx.visit_closures();
         wbcx.visit_liberated_fn_sigs();
@@ -333,6 +334,19 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
 }
 
 impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
+    fn eval_closure_size(&mut self) {
+        let mut res: FxHashMap<DefId, ClosureSizeProfileData<'tcx>> = Default::default();
+        for (closure_def_id, data) in self.fcx.typeck_results.borrow().closure_size_eval.iter() {
+            let closure_hir_id =
+                self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local());
+
+            let data = self.resolve(*data, &closure_hir_id);
+
+            res.insert(*closure_def_id, data);
+        }
+
+        self.typeck_results.closure_size_eval = res;
+    }
     fn visit_min_capture_map(&mut self) {
         let mut min_captures_wb = ty::MinCaptureInformationMap::with_capacity_and_hasher(
             self.fcx.typeck_results.borrow().closure_min_captures.len(),
@@ -482,6 +496,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
             debug_assert!(!instantiated_ty.has_escaping_bound_vars());
 
+            let opaque_type_key = self.fcx.fully_resolve(opaque_type_key).unwrap();
+
             // Prevent:
             // * `fn foo<T>() -> Foo<T>`
             // * `fn foo<T: Bound + Other>() -> Foo<T>`
@@ -494,6 +510,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             // fn foo<U>() -> Foo<U> { .. }
             // ```
             // figures out the concrete type with `U`, but the stored type is with `T`.
+
+            // FIXME: why are we calling this here? This seems too early, and duplicated.
             let definition_ty = self.fcx.infer_opaque_definition_from_instantiation(
                 opaque_type_key,
                 instantiated_ty,
@@ -503,8 +521,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             let mut skip_add = false;
 
             if let ty::Opaque(definition_ty_def_id, _substs) = *definition_ty.kind() {
-                if let hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias = opaque_defn.origin
-                {
+                if opaque_defn.origin == hir::OpaqueTyOrigin::TyAlias {
                     if opaque_type_key.def_id == definition_ty_def_id {
                         debug!(
                             "skipping adding concrete definition for opaque type {:?} {:?}",
@@ -515,33 +532,33 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                 }
             }
 
-            if !opaque_type_key.substs.needs_infer() {
-                // We only want to add an entry into `concrete_opaque_types`
-                // if we actually found a defining usage of this opaque type.
-                // Otherwise, we do nothing - we'll either find a defining usage
-                // in some other location, or we'll end up emitting an error due
-                // to the lack of defining usage
-                if !skip_add {
-                    let old_concrete_ty = self
-                        .typeck_results
-                        .concrete_opaque_types
-                        .insert(opaque_type_key, definition_ty);
-                    if let Some(old_concrete_ty) = old_concrete_ty {
-                        if old_concrete_ty != definition_ty {
-                            span_bug!(
-                                span,
-                                "`visit_opaque_types` tried to write different types for the same \
+            if opaque_type_key.substs.needs_infer() {
+                span_bug!(span, "{:#?} has inference variables", opaque_type_key.substs)
+            }
+
+            // We only want to add an entry into `concrete_opaque_types`
+            // if we actually found a defining usage of this opaque type.
+            // Otherwise, we do nothing - we'll either find a defining usage
+            // in some other location, or we'll end up emitting an error due
+            // to the lack of defining usage
+            if !skip_add {
+                let old_concrete_ty = self
+                    .typeck_results
+                    .concrete_opaque_types
+                    .insert(opaque_type_key, definition_ty);
+                if let Some(old_concrete_ty) = old_concrete_ty {
+                    if old_concrete_ty != definition_ty {
+                        span_bug!(
+                            span,
+                            "`visit_opaque_types` tried to write different types for the same \
                                  opaque type: {:?}, {:?}, {:?}, {:?}",
-                                opaque_type_key.def_id,
-                                definition_ty,
-                                opaque_defn,
-                                old_concrete_ty,
-                            );
-                        }
+                            opaque_type_key.def_id,
+                            definition_ty,
+                            opaque_defn,
+                            old_concrete_ty,
+                        );
                     }
                 }
-            } else {
-                self.tcx().sess.delay_span_bug(span, "`opaque_defn` has inference variables");
             }
         }
     }
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 aebae0d47c9036ca0b6061dc7e7229f48425f2ff..1a4c2eb5155849168bcb719b3763737abc840ea3 100644 (file)
@@ -15,6 +15,8 @@
 //! At present, however, we do run collection across all items in the
 //! crate as a kind of pass. This should eventually be factored away.
 
+// ignore-tidy-filelength
+
 use crate::astconv::{AstConv, SizedByDefault};
 use crate::bounds::Bounds;
 use crate::check::intrinsic::intrinsic_operation_unsafety;
@@ -33,7 +35,6 @@ use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::weak_lang_items;
 use rustc_hir::{GenericParamKind, HirId, Node};
-use rustc_middle::hir::map::blocks::FnLikeNode;
 use rustc_middle::hir::map::Map;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::mono::Linkage;
@@ -75,7 +76,6 @@ pub fn provide(providers: &mut Providers) {
         generics_of,
         predicates_of,
         predicates_defined_on,
-        projection_ty_from_predicates,
         explicit_predicates_of,
         super_predicates_of,
         super_predicates_that_define_assoc_type,
@@ -91,6 +91,7 @@ pub fn provide(providers: &mut Providers) {
         generator_kind,
         codegen_fn_attrs,
         collect_mod_item_types,
+        should_inherit_track_caller,
         ..*providers
     };
 }
@@ -144,6 +145,7 @@ crate fn placeholder_type_error(
     placeholder_types: Vec<Span>,
     suggest: bool,
     hir_ty: Option<&hir::Ty<'_>>,
+    kind: &'static str,
 ) {
     if placeholder_types.is_empty() {
         return;
@@ -173,13 +175,12 @@ crate fn placeholder_type_error(
         ));
     }
 
-    let mut err = bad_placeholder_type(tcx, placeholder_types);
+    let mut err = bad_placeholder_type(tcx, placeholder_types, kind);
 
     // Suggest, but only if it is not a function in const or static
     if suggest {
         let mut is_fn = false;
-        let mut is_const = false;
-        let mut is_static = false;
+        let mut is_const_or_static = false;
 
         if let Some(hir_ty) = hir_ty {
             if let hir::TyKind::BareFn(_) = hir_ty.kind {
@@ -189,19 +190,26 @@ crate fn placeholder_type_error(
                 let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id);
                 let parent_node = tcx.hir().get(parent_id);
 
-                if let hir::Node::Item(item) = parent_node {
-                    if let hir::ItemKind::Const(_, _) = item.kind {
-                        is_const = true;
-                    } else if let hir::ItemKind::Static(_, _, _) = item.kind {
-                        is_static = true;
-                    }
-                }
+                is_const_or_static = match parent_node {
+                    Node::Item(&hir::Item {
+                        kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..),
+                        ..
+                    })
+                    | Node::TraitItem(&hir::TraitItem {
+                        kind: hir::TraitItemKind::Const(..),
+                        ..
+                    })
+                    | Node::ImplItem(&hir::ImplItem {
+                        kind: hir::ImplItemKind::Const(..), ..
+                    }) => true,
+                    _ => false,
+                };
             }
         }
 
         // if function is wrapped around a const or static,
         // then don't show the suggestion
-        if !(is_fn && (is_const || is_static)) {
+        if !(is_fn && is_const_or_static) {
             err.multipart_suggestion(
                 "use type parameters instead",
                 sugg,
@@ -229,7 +237,15 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir
     let mut visitor = PlaceholderHirTyCollector::default();
     visitor.visit_item(item);
 
-    placeholder_type_error(tcx, Some(generics.span), generics.params, visitor.0, suggest, None);
+    placeholder_type_error(
+        tcx,
+        Some(generics.span),
+        generics.params,
+        visitor.0,
+        suggest,
+        None,
+        item.kind.descr(),
+    );
 }
 
 impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
@@ -295,13 +311,17 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
 fn bad_placeholder_type(
     tcx: TyCtxt<'tcx>,
     mut spans: Vec<Span>,
+    kind: &'static str,
 ) -> rustc_errors::DiagnosticBuilder<'tcx> {
+    let kind = if kind.ends_with('s') { format!("{}es", kind) } else { format!("{}s", kind) };
+
     spans.sort();
     let mut err = struct_span_err!(
         tcx.sess,
         spans.clone(),
         E0121,
-        "the type placeholder `_` is not allowed within types on item signatures",
+        "the type placeholder `_` is not allowed within types on item signatures for {}",
+        kind
     );
     for span in spans {
         err.span_label(span, "not allowed in type signatures");
@@ -337,11 +357,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
     }
 
     fn default_constness_for_trait_bounds(&self) -> hir::Constness {
-        if let Some(fn_like) = FnLikeNode::from_node(self.node()) {
-            fn_like.constness()
-        } else {
-            hir::Constness::NotConst
-        }
+        self.node().constness()
     }
 
     fn get_type_parameter_bounds(
@@ -375,7 +391,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
         _: Option<&ty::GenericParamDef>,
         span: Span,
     ) -> &'tcx Const<'tcx> {
-        bad_placeholder_type(self.tcx(), vec![span]).emit();
+        bad_placeholder_type(self.tcx(), vec![span], "generic").emit();
         // Typeck doesn't expect erased regions to be returned from `type_of`.
         let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match r {
             ty::ReErased => self.tcx.lifetimes.re_static,
@@ -739,7 +755,15 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
                     hir::ForeignItemKind::Static(..) => {
                         let mut visitor = PlaceholderHirTyCollector::default();
                         visitor.visit_foreign_item(item);
-                        placeholder_type_error(tcx, None, &[], visitor.0, false, None);
+                        placeholder_type_error(
+                            tcx,
+                            None,
+                            &[],
+                            visitor.0,
+                            false,
+                            None,
+                            "static variable",
+                        );
                     }
                     _ => (),
                 }
@@ -806,6 +830,22 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
             match it.kind {
                 hir::ItemKind::Fn(..) => tcx.ensure().fn_sig(def_id),
                 hir::ItemKind::OpaqueTy(..) => tcx.ensure().item_bounds(def_id),
+                hir::ItemKind::Const(ty, ..) | hir::ItemKind::Static(ty, ..) => {
+                    // (#75889): Account for `const C: dyn Fn() -> _ = "";`
+                    if let hir::TyKind::TraitObject(..) = ty.kind {
+                        let mut visitor = PlaceholderHirTyCollector::default();
+                        visitor.visit_item(it);
+                        placeholder_type_error(
+                            tcx,
+                            None,
+                            &[],
+                            visitor.0,
+                            false,
+                            None,
+                            it.kind.descr(),
+                        );
+                    }
+                }
                 _ => (),
             }
         }
@@ -831,7 +871,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
             // Account for `const C: _;`.
             let mut visitor = PlaceholderHirTyCollector::default();
             visitor.visit_trait_item(trait_item);
-            placeholder_type_error(tcx, None, &[], visitor.0, false, None);
+            placeholder_type_error(tcx, None, &[], visitor.0, false, None, "constant");
         }
 
         hir::TraitItemKind::Type(_, Some(_)) => {
@@ -840,7 +880,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
             // Account for `type T = _;`.
             let mut visitor = PlaceholderHirTyCollector::default();
             visitor.visit_trait_item(trait_item);
-            placeholder_type_error(tcx, None, &[], visitor.0, false, None);
+            placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type");
         }
 
         hir::TraitItemKind::Type(_, None) => {
@@ -850,7 +890,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
             let mut visitor = PlaceholderHirTyCollector::default();
             visitor.visit_trait_item(trait_item);
 
-            placeholder_type_error(tcx, None, &[], visitor.0, false, None);
+            placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type");
         }
     };
 
@@ -872,7 +912,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
             let mut visitor = PlaceholderHirTyCollector::default();
             visitor.visit_impl_item(impl_item);
 
-            placeholder_type_error(tcx, None, &[], visitor.0, false, None);
+            placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type");
         }
         hir::ImplItemKind::Const(..) => {}
     }
@@ -1693,11 +1733,12 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
                         ty::ReErased => tcx.lifetimes.re_static,
                         _ => r,
                     });
+                    let fn_sig = ty::Binder::dummy(fn_sig);
 
                     let mut visitor = PlaceholderHirTyCollector::default();
                     visitor.visit_ty(ty);
-                    let mut diag = bad_placeholder_type(tcx, visitor.0);
-                    let ret_ty = fn_sig.output();
+                    let mut diag = bad_placeholder_type(tcx, visitor.0, "return type");
+                    let ret_ty = fn_sig.skip_binder().output();
                     if ret_ty != tcx.ty_error() {
                         if !ret_ty.is_closure() {
                             let ret_ty_str = match ret_ty.kind() {
@@ -1723,7 +1764,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
                     }
                     diag.emit();
 
-                    ty::Binder::bind(fn_sig, tcx)
+                    fn_sig
                 }
                 None => <dyn AstConv<'_>>::ty_of_fn(
                     &icx,
@@ -1767,10 +1808,13 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
             let ty = tcx.type_of(tcx.hir().get_parent_did(hir_id).to_def_id());
             let inputs =
                 data.fields().iter().map(|f| tcx.type_of(tcx.hir().local_def_id(f.hir_id)));
-            ty::Binder::bind(
-                tcx.mk_fn_sig(inputs, ty, false, hir::Unsafety::Normal, abi::Abi::Rust),
-                tcx,
-            )
+            ty::Binder::dummy(tcx.mk_fn_sig(
+                inputs,
+                ty,
+                false,
+                hir::Unsafety::Normal,
+                abi::Abi::Rust,
+            ))
         }
 
         Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
@@ -2054,7 +2098,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                 param.bounds.iter().for_each(|bound| match bound {
                     hir::GenericBound::Outlives(lt) => {
                         let bound = <dyn AstConv<'_>>::ast_region_to_region(&icx, &lt, None);
-                        let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound), tcx);
+                        let outlives = ty::Binder::dummy(ty::OutlivesPredicate(region, bound));
                         predicates.insert((outlives.to_predicate(tcx), lt.span));
                     }
                     _ => bug!(),
@@ -2260,6 +2304,16 @@ fn const_evaluatable_predicates_of<'tcx>(
                 ));
             }
         }
+
+        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);
@@ -2350,29 +2404,6 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
     }
 }
 
-fn projection_ty_from_predicates(
-    tcx: TyCtxt<'tcx>,
-    key: (
-        // ty_def_id
-        DefId,
-        // def_id of `N` in `<T as Trait>::N`
-        DefId,
-    ),
-) -> Option<ty::ProjectionTy<'tcx>> {
-    let (ty_def_id, item_def_id) = key;
-    let mut projection_ty = None;
-    for (predicate, _) in tcx.predicates_of(ty_def_id).predicates {
-        if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder()
-        {
-            if item_def_id == projection_predicate.projection_ty.item_def_id {
-                projection_ty = Some(projection_predicate.projection_ty);
-                break;
-            }
-        }
-    }
-    projection_ty
-}
-
 /// Converts a specific `GenericBound` from the AST into a set of
 /// predicates that apply to the self type. A vector is returned
 /// because this can be anywhere from zero predicates (`T: ?Sized` adds no
@@ -2651,7 +2682,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;
     }
 
@@ -2920,6 +2951,36 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                     None
                 }
             };
+        } else if tcx.sess.check_name(attr, sym::repr) {
+            codegen_fn_attrs.alignment = match attr.meta_item_list() {
+                Some(items) => match items.as_slice() {
+                    [item] => match item.name_value_literal() {
+                        Some((sym::align, literal)) => {
+                            let alignment = rustc_attr::parse_alignment(&literal.kind);
+
+                            match alignment {
+                                Ok(align) => Some(align),
+                                Err(msg) => {
+                                    struct_span_err!(
+                                        tcx.sess.diagnostic(),
+                                        attr.span,
+                                        E0589,
+                                        "invalid `repr(align)` attribute: {}",
+                                        msg
+                                    )
+                                    .emit();
+
+                                    None
+                                }
+                            }
+                        }
+                        _ => None,
+                    },
+                    [] => None,
+                    _ => None,
+                },
+                None => None,
+            };
         }
     }
 
index 29a87b18a9eb7efe5b1349649cec856e70cca496..50e4ba4fe6c3e23cd22c40c364bb2f661905a552 100644 (file)
@@ -9,7 +9,7 @@ use rustc_hir::{HirId, Node};
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder};
 use rustc_span::symbol::Ident;
 use rustc_span::{Span, DUMMY_SP};
 
@@ -285,7 +285,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
             TraitItemKind::Const(ref ty, body_id) => body_id
                 .and_then(|body_id| {
                     if is_suggestable_infer_ty(ty) {
-                        Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident))
+                        Some(infer_placeholder_type(
+                            tcx, def_id, body_id, ty.span, item.ident, "constant",
+                        ))
                     } else {
                         None
                     }
@@ -304,7 +306,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
             }
             ImplItemKind::Const(ref ty, body_id) => {
                 if is_suggestable_infer_ty(ty) {
-                    infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
+                    infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant")
                 } else {
                     icx.to_ty(ty)
                 }
@@ -320,9 +322,25 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
 
         Node::Item(item) => {
             match item.kind {
-                ItemKind::Static(ref ty, .., body_id) | ItemKind::Const(ref ty, body_id) => {
+                ItemKind::Static(ref ty, .., body_id) => {
                     if is_suggestable_infer_ty(ty) {
-                        infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
+                        infer_placeholder_type(
+                            tcx,
+                            def_id,
+                            body_id,
+                            ty.span,
+                            item.ident,
+                            "static variable",
+                        )
+                    } else {
+                        icx.to_ty(ty)
+                    }
+                }
+                ItemKind::Const(ref ty, body_id) => {
+                    if is_suggestable_infer_ty(ty) {
+                        infer_placeholder_type(
+                            tcx, def_id, body_id, ty.span, item.ident, "constant",
+                        )
                     } else {
                         icx.to_ty(ty)
                     }
@@ -338,9 +356,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
                     tcx.mk_adt(def, substs)
                 }
-                ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::Binding, .. }) => {
-                    let_position_impl_trait_type(tcx, def_id)
-                }
                 ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {
                     find_opaque_ty_constraints(tcx, def_id)
                 }
@@ -349,7 +364,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     let concrete_ty = tcx
                         .mir_borrowck(owner.expect_local())
                         .concrete_opaque_types
-                        .get_by(|(key, _)| key.def_id == def_id.to_def_id())
+                        .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id())
                         .map(|concrete_ty| *concrete_ty)
                         .unwrap_or_else(|| {
                             tcx.sess.delay_span_bug(
@@ -474,7 +489,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
 
                 x => tcx.ty_error_with_message(
                     DUMMY_SP,
-                    &format!("unexpected const parent in type_of_def_id(): {:?}", x),
+                    &format!("unexpected const parent in type_of(): {:?}", x),
                 ),
             }
         }
@@ -486,31 +501,35 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
         },
 
         x => {
-            bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
+            bug!("unexpected sort of node in type_of(): {:?}", x);
         }
     }
 }
 
+#[instrument(skip(tcx), level = "debug")]
 fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
     use rustc_hir::{Expr, ImplItem, Item, TraitItem};
 
-    debug!("find_opaque_ty_constraints({:?})", def_id);
-
     struct ConstraintLocator<'tcx> {
         tcx: TyCtxt<'tcx>,
+
+        /// def_id of the opaque type whose defining uses are being checked
         def_id: DefId,
-        // (first found type span, actual type)
+
+        /// as we walk the defining uses, we are checking that all of them
+        /// define the same hidden type. This variable is set to `Some`
+        /// with the first type that we find, and then later types are
+        /// checked against it (we also carry the span of that first
+        /// type).
         found: Option<(Span, Ty<'tcx>)>,
     }
 
     impl ConstraintLocator<'_> {
+        #[instrument(skip(self), level = "debug")]
         fn check(&mut self, def_id: LocalDefId) {
             // Don't try to check items that cannot possibly constrain the type.
             if !self.tcx.has_typeck_results(def_id) {
-                debug!(
-                    "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`: no typeck results",
-                    self.def_id, def_id,
-                );
+                debug!("no constraint: no typeck results");
                 return;
             }
             // Calling `mir_borrowck` can lead to cycle errors through
@@ -519,24 +538,22 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
                 .tcx
                 .typeck(def_id)
                 .concrete_opaque_types
-                .get_by(|(key, _)| key.def_id == self.def_id)
+                .any_value_matching(|(key, _)| key.def_id == self.def_id)
                 .is_none()
             {
-                debug!(
-                    "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`",
-                    self.def_id, def_id,
-                );
+                debug!("no constraints in typeck results");
                 return;
             }
             // Use borrowck to get the type with unerased regions.
             let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
-            if let Some((opaque_type_key, concrete_type)) =
-                concrete_opaque_types.iter().find(|(key, _)| key.def_id == self.def_id)
-            {
-                debug!(
-                    "find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}",
-                    self.def_id, def_id, concrete_type,
-                );
+            debug!(?concrete_opaque_types);
+            for (opaque_type_key, concrete_type) in concrete_opaque_types {
+                if opaque_type_key.def_id != self.def_id {
+                    // Ignore constraints for other opaque types.
+                    continue;
+                }
+
+                debug!(?concrete_type, ?opaque_type_key.substs, "found constraint");
 
                 // FIXME(oli-obk): trace the actual span from inference to improve errors.
                 let span = self.tcx.def_span(def_id);
@@ -585,7 +602,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
 
                 if let Some((prev_span, prev_ty)) = self.found {
                     if *concrete_type != prev_ty {
-                        debug!("find_opaque_ty_constraints: span={:?}", span);
+                        debug!(?span);
                         // Found different concrete types for the opaque type.
                         let mut err = self.tcx.sess.struct_span_err(
                             span,
@@ -601,11 +618,6 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
                 } else {
                     self.found = Some((span, concrete_type));
                 }
-            } else {
-                debug!(
-                    "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`",
-                    self.def_id, def_id,
-                );
             }
         }
     }
@@ -688,67 +700,48 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
     }
 }
 
-/// Retrieve the inferred concrete type for let position impl trait.
-///
-/// This is different to other kinds of impl trait because:
-///
-/// 1. We know which function contains the defining use (the function that
-///    contains the let statement)
-/// 2. We do not currently allow (free) lifetimes in the return type. `let`
-///    statements in some statically unreachable code are removed from the MIR
-///    by the time we borrow check, and it's not clear how we should handle
-///    those.
-fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty<'_> {
-    let scope = tcx.hir().get_defining_scope(tcx.hir().local_def_id_to_hir_id(opaque_ty_id));
-    let scope_def_id = tcx.hir().local_def_id(scope);
-
-    let opaque_ty_def_id = opaque_ty_id.to_def_id();
-
-    let owner_typeck_results = tcx.typeck(scope_def_id);
-    let concrete_ty = owner_typeck_results
-        .concrete_opaque_types
-        .get_by(|(key, _)| key.def_id == opaque_ty_def_id)
-        .map(|concrete_ty| *concrete_ty)
-        .unwrap_or_else(|| {
-            tcx.sess.delay_span_bug(
-                DUMMY_SP,
-                &format!(
-                    "owner {:?} has no opaque type for {:?} in its typeck results",
-                    scope_def_id, opaque_ty_id
-                ),
-            );
-            if let Some(ErrorReported) = owner_typeck_results.tainted_by_errors {
-                // Some error in the owner fn prevented us from populating the
-                // `concrete_opaque_types` table.
-                tcx.ty_error()
-            } else {
-                // We failed to resolve the opaque type or it resolves to
-                // itself. Return the non-revealed type, which should result in
-                // E0720.
-                tcx.mk_opaque(
-                    opaque_ty_def_id,
-                    InternalSubsts::identity_for_item(tcx, opaque_ty_def_id),
-                )
-            }
-        });
-    debug!("concrete_ty = {:?}", concrete_ty);
-    if concrete_ty.has_erased_regions() {
-        // FIXME(impl_trait_in_bindings) Handle this case.
-        tcx.sess.span_fatal(
-            tcx.hir().span(tcx.hir().local_def_id_to_hir_id(opaque_ty_id)),
-            "lifetimes in impl Trait types in bindings are not currently supported",
-        );
-    }
-    concrete_ty
-}
-
-fn infer_placeholder_type(
-    tcx: TyCtxt<'_>,
+fn infer_placeholder_type<'a>(
+    tcx: TyCtxt<'a>,
     def_id: LocalDefId,
     body_id: hir::BodyId,
     span: Span,
     item_ident: Ident,
-) -> Ty<'_> {
+    kind: &'static str,
+) -> Ty<'a> {
+    // Attempts to make the type nameable by turning FnDefs into FnPtrs.
+    struct MakeNameable<'tcx> {
+        success: bool,
+        tcx: TyCtxt<'tcx>,
+    }
+
+    impl<'tcx> MakeNameable<'tcx> {
+        fn new(tcx: TyCtxt<'tcx>) -> Self {
+            MakeNameable { success: true, tcx }
+        }
+    }
+
+    impl TypeFolder<'tcx> for MakeNameable<'tcx> {
+        fn tcx(&self) -> TyCtxt<'tcx> {
+            self.tcx
+        }
+
+        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+            if !self.success {
+                return ty;
+            }
+
+            match ty.kind() {
+                ty::FnDef(def_id, _) => self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id)),
+                // FIXME: non-capturing closures should also suggest a function pointer
+                ty::Closure(..) | ty::Generator(..) => {
+                    self.success = false;
+                    ty
+                }
+                _ => ty.super_fold_with(self),
+            }
+        }
+    }
+
     let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id);
 
     // If this came from a free `const` or `static mut?` item,
@@ -760,24 +753,47 @@ fn infer_placeholder_type(
             // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
             // We are typeck and have the real type, so remove that and suggest the actual type.
             err.suggestions.clear();
-            err.span_suggestion(
-                span,
-                "provide a type for the item",
-                format!("{}: {}", item_ident, ty),
-                Applicability::MachineApplicable,
-            )
-            .emit_unless(ty.references_error());
+
+            // Suggesting unnameable types won't help.
+            let mut mk_nameable = MakeNameable::new(tcx);
+            let ty = mk_nameable.fold_ty(ty);
+            let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
+            if let Some(sugg_ty) = sugg_ty {
+                err.span_suggestion(
+                    span,
+                    &format!("provide a type for the {item}", item = kind),
+                    format!("{}: {}", item_ident, sugg_ty),
+                    Applicability::MachineApplicable,
+                );
+            } else {
+                err.span_note(
+                    tcx.hir().body(body_id).value.span,
+                    &format!("however, the inferred type `{}` cannot be named", ty.to_string()),
+                );
+            }
+
+            err.emit_unless(ty.references_error());
         }
         None => {
-            let mut diag = bad_placeholder_type(tcx, vec![span]);
+            let mut diag = bad_placeholder_type(tcx, vec![span], kind);
 
             if !ty.references_error() {
-                diag.span_suggestion(
-                    span,
-                    "replace with the correct type",
-                    ty.to_string(),
-                    Applicability::MaybeIncorrect,
-                );
+                let mut mk_nameable = MakeNameable::new(tcx);
+                let ty = mk_nameable.fold_ty(ty);
+                let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
+                if let Some(sugg_ty) = sugg_ty {
+                    diag.span_suggestion(
+                        span,
+                        "replace with the correct type",
+                        sugg_ty.to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
+                } else {
+                    diag.span_note(
+                        tcx.hir().body(body_id).value.span,
+                        &format!("however, the inferred type `{}` cannot be named", ty.to_string()),
+                    );
+                }
             }
 
             diag.emit();
index 5068242692ae85d4e7677ffec6d8dbbe813c5093..1e6a240b2f86d857ce8761f7421775eca0287837 100644 (file)
@@ -24,13 +24,15 @@ pub struct UnrecognizedAtomicOperation<'a> {
 
 #[derive(SessionDiagnostic)]
 #[error = "E0094"]
-pub struct WrongNumberOfTypeArgumentsToInstrinsic {
-    #[message = "intrinsic has wrong number of type \
+pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
+    #[message = "intrinsic has wrong number of {descr} \
                          parameters: found {found}, expected {expected}"]
-    #[label = "expected {expected} type parameter"]
+    #[label = "expected {expected} {descr} parameter{expected_pluralize}"]
     pub span: Span,
     pub found: usize,
     pub expected: usize,
+    pub expected_pluralize: &'a str,
+    pub descr: &'a str,
 }
 
 #[derive(SessionDiagnostic)]
@@ -147,6 +149,10 @@ pub struct TypeofReservedKeywordUsed {
 pub struct ReturnStmtOutsideOfFnBody {
     #[message = "return statement outside of function body"]
     pub span: Span,
+    #[label = "the return is part of this body..."]
+    pub encl_body_span: Option<Span>,
+    #[label = "...not the enclosing function body"]
+    pub encl_fn_span: Option<Span>,
 }
 
 #[derive(SessionDiagnostic)]
index f17494127948414f1c363abde40bf5878701c439..806f1a2711c012b9d52d7830d5d40efd755a5b7a 100644 (file)
@@ -2,8 +2,6 @@
 //! normal visitor, which just walks the entire body in one shot, the
 //! `ExprUseVisitor` determines how expressions are being used.
 
-pub use self::ConsumeMode::*;
-
 // Export these here so that Clippy can use them.
 pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection};
 
@@ -28,19 +26,20 @@ use crate::mem_categorization as mc;
 /// This trait defines the callbacks you can expect to receive when
 /// employing the ExprUseVisitor.
 pub trait Delegate<'tcx> {
-    // The value found at `place` is either copied or moved, depending
+    // The value found at `place` is moved, depending
     // on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`.
     //
+    // Use of a `Copy` type in a ByValue context is considered a use
+    // by `ImmBorrow` and `borrow` is called instead. This is because
+    // a shared borrow is the "minimum access" that would be needed
+    // to perform a copy.
+    //
+    //
     // The parameter `diag_expr_id` indicates the HIR id that ought to be used for
     // diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic
     // id will be the id of the expression `expr` but the place itself will have
     // the id of the binding in the pattern `pat`.
-    fn consume(
-        &mut self,
-        place_with_id: &PlaceWithHirId<'tcx>,
-        diag_expr_id: hir::HirId,
-        mode: ConsumeMode,
-    );
+    fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId);
 
     // The value found at `place` is being borrowed with kind `bk`.
     // `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
@@ -60,7 +59,7 @@ pub trait Delegate<'tcx> {
 }
 
 #[derive(Copy, Clone, PartialEq, Debug)]
-pub enum ConsumeMode {
+enum ConsumeMode {
     Copy, // reference to x where x has a type that copies
     Move, // reference to x where x has a type that moves
 }
@@ -141,10 +140,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
     }
 
     fn delegate_consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
-        debug!("delegate_consume(place_with_id={:?})", place_with_id);
-
-        let mode = copy_or_move(&self.mc, place_with_id);
-        self.delegate.consume(place_with_id, diag_expr_id, mode);
+        delegate_consume(&self.mc, self.delegate, place_with_id, diag_expr_id)
     }
 
     fn consume_exprs(&mut self, exprs: &[hir::Expr<'_>]) {
@@ -256,12 +252,16 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                             | PatKind::Path(..)
                             | PatKind::Struct(..)
                             | PatKind::Tuple(..) => {
-                                // If the PatKind is a TupleStruct, Struct or Tuple then we want to check
+                                // If the PatKind is a TupleStruct, Path, Struct or Tuple then we want to check
                                 // whether the Variant is a MultiVariant or a SingleVariant. We only want
                                 // to borrow discr if it is a MultiVariant.
                                 // If it is a SingleVariant and creates a binding we will handle that when
                                 // this callback gets called again.
-                                if let ty::Adt(def, _) = place.place.base_ty.kind() {
+
+                                // Get the type of the Place after all projections have been applied
+                                let place_ty = place.place.ty();
+
+                                if let ty::Adt(def, _) = place_ty.kind() {
                                     if def.variants.len() > 1 {
                                         needs_to_be_read = true;
                                     }
@@ -653,9 +653,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                             delegate.borrow(place, discr_place.hir_id, bk);
                         }
                         ty::BindByValue(..) => {
-                            let mode = copy_or_move(mc, &place);
                             debug!("walk_pat binding consuming pat");
-                            delegate.consume(place, discr_place.hir_id, mode);
+                            delegate_consume(mc, *delegate, place, discr_place.hir_id);
                         }
                     }
                 }
@@ -773,8 +772,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
 
                     match capture_info.capture_kind {
                         ty::UpvarCapture::ByValue(_) => {
-                            let mode = copy_or_move(&self.mc, &place_with_id);
-                            self.delegate.consume(&place_with_id, place_with_id.hir_id, mode);
+                            self.delegate_consume(&place_with_id, place_with_id.hir_id);
                         }
                         ty::UpvarCapture::ByRef(upvar_borrow) => {
                             self.delegate.borrow(
@@ -798,8 +796,28 @@ fn copy_or_move<'a, 'tcx>(
         place_with_id.place.ty(),
         mc.tcx().hir().span(place_with_id.hir_id),
     ) {
-        Move
+        ConsumeMode::Move
     } else {
-        Copy
+        ConsumeMode::Copy
+    }
+}
+
+// - If a place is used in a `ByValue` context then move it if it's not a `Copy` type.
+// - If the place that is a `Copy` type consider it a `ImmBorrow`.
+fn delegate_consume<'a, 'tcx>(
+    mc: &mc::MemCategorizationContext<'a, 'tcx>,
+    delegate: &mut (dyn Delegate<'tcx> + 'a),
+    place_with_id: &PlaceWithHirId<'tcx>,
+    diag_expr_id: hir::HirId,
+) {
+    debug!("delegate_consume(place_with_id={:?})", place_with_id);
+
+    let mode = copy_or_move(&mc, place_with_id);
+
+    match mode {
+        ConsumeMode::Move => delegate.consume(place_with_id, diag_expr_id),
+        ConsumeMode::Copy => {
+            delegate.borrow(place_with_id, diag_expr_id, ty::BorrowKind::ImmBorrow)
+        }
     }
 }
diff --git a/compiler/rustc_typeck/src/hir_wf_check.rs b/compiler/rustc_typeck/src/hir_wf_check.rs
new file mode 100644 (file)
index 0000000..e7503d3
--- /dev/null
@@ -0,0 +1,185 @@
+use crate::collect::ItemCtxt;
+use rustc_hir as hir;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::HirId;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::traits::TraitEngine;
+use rustc_infer::traits::{ObligationCause, WellFormedLoc};
+use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::{self, Region, ToPredicate, TyCtxt, TypeFoldable, TypeFolder};
+use rustc_trait_selection::traits;
+
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { diagnostic_hir_wf_check, ..*providers };
+}
+
+// Ideally, this would be in `rustc_trait_selection`, but we
+// need access to `ItemCtxt`
+fn diagnostic_hir_wf_check<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    (predicate, loc): (ty::Predicate<'tcx>, WellFormedLoc),
+) -> Option<ObligationCause<'tcx>> {
+    let hir = tcx.hir();
+
+    let def_id = match loc {
+        WellFormedLoc::Ty(def_id) => def_id,
+        WellFormedLoc::Param { function, param_idx: _ } => function,
+    };
+    let hir_id = hir.local_def_id_to_hir_id(def_id);
+
+    // HIR wfcheck should only ever happen as part of improving an existing error
+    tcx.sess
+        .delay_span_bug(tcx.def_span(def_id), "Performed HIR wfcheck without an existing error!");
+
+    let icx = ItemCtxt::new(tcx, def_id.to_def_id());
+
+    // To perform HIR-based WF checking, we iterate over all HIR types
+    // that occur 'inside' the item we're checking. For example,
+    // given the type `Option<MyStruct<u8>>`, we will check
+    // `Option<MyStruct<u8>>`, `MyStruct<u8>`, and `u8`.
+    // For each type, we perform a well-formed check, and see if we get
+    // an erorr that matches our expected predicate. We keep save
+    // the `ObligationCause` corresponding to the *innermost* type,
+    // which is the most specific type that we can point to.
+    // In general, the different components of an `hir::Ty` may have
+    // completely differentr spans due to macro invocations. Pointing
+    // to the most accurate part of the type can be the difference
+    // between a useless span (e.g. the macro invocation site)
+    // and a useful span (e.g. a user-provided type passed in to the macro).
+    //
+    // This approach is quite inefficient - we redo a lot of work done
+    // by the normal WF checker. However, this code is run at most once
+    // per reported error - it will have no impact when compilation succeeds,
+    // and should only have an impact if a very large number of errors are
+    // displaydd to the user.
+    struct HirWfCheck<'tcx> {
+        tcx: TyCtxt<'tcx>,
+        predicate: ty::Predicate<'tcx>,
+        cause: Option<ObligationCause<'tcx>>,
+        cause_depth: usize,
+        icx: ItemCtxt<'tcx>,
+        hir_id: HirId,
+        param_env: ty::ParamEnv<'tcx>,
+        depth: usize,
+    }
+
+    impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
+        type Map = intravisit::ErasedMap<'tcx>;
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+            NestedVisitorMap::None
+        }
+        fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
+            self.tcx.infer_ctxt().enter(|infcx| {
+                let mut fulfill = traits::FulfillmentContext::new();
+                let tcx_ty =
+                    self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx });
+                let cause = traits::ObligationCause::new(
+                    ty.span,
+                    self.hir_id,
+                    traits::ObligationCauseCode::MiscObligation,
+                );
+                fulfill.register_predicate_obligation(
+                    &infcx,
+                    traits::Obligation::new(
+                        cause,
+                        self.param_env,
+                        ty::PredicateKind::WellFormed(tcx_ty.into()).to_predicate(self.tcx),
+                    ),
+                );
+
+                if let Err(errors) = fulfill.select_all_or_error(&infcx) {
+                    tracing::debug!("Wf-check got errors for {:?}: {:?}", ty, errors);
+                    for error in errors {
+                        if error.obligation.predicate == self.predicate {
+                            // Save the cause from the greatest depth - this corresponds
+                            // to picking more-specific types (e.g. `MyStruct<u8>`)
+                            // over less-specific types (e.g. `Option<MyStruct<u8>>`)
+                            if self.depth >= self.cause_depth {
+                                self.cause = Some(error.obligation.cause);
+                                self.cause_depth = self.depth
+                            }
+                        }
+                    }
+                }
+            });
+            self.depth += 1;
+            intravisit::walk_ty(self, ty);
+            self.depth -= 1;
+        }
+    }
+
+    let mut visitor = HirWfCheck {
+        tcx,
+        predicate,
+        cause: None,
+        cause_depth: 0,
+        icx,
+        hir_id,
+        param_env: tcx.param_env(def_id.to_def_id()),
+        depth: 0,
+    };
+
+    // Get the starting `hir::Ty` using our `WellFormedLoc`.
+    // We will walk 'into' this type to try to find
+    // a more precise span for our predicate.
+    let ty = match loc {
+        WellFormedLoc::Ty(_) => match hir.get(hir_id) {
+            hir::Node::ImplItem(item) => match item.kind {
+                hir::ImplItemKind::TyAlias(ty) => Some(ty),
+                ref item => bug!("Unexpected ImplItem {:?}", item),
+            },
+            hir::Node::TraitItem(item) => match item.kind {
+                hir::TraitItemKind::Type(_, ty) => ty,
+                ref item => bug!("Unexpected TraitItem {:?}", item),
+            },
+            hir::Node::Item(item) => match item.kind {
+                hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => Some(ty),
+                hir::ItemKind::Impl(ref impl_) => {
+                    assert!(impl_.of_trait.is_none(), "Unexpected trait impl: {:?}", impl_);
+                    Some(impl_.self_ty)
+                }
+                ref item => bug!("Unexpected item {:?}", item),
+            },
+            hir::Node::Field(field) => Some(field.ty),
+            ref node => bug!("Unexpected node {:?}", node),
+        },
+        WellFormedLoc::Param { function: _, param_idx } => {
+            let fn_decl = hir.fn_decl_by_hir_id(hir_id).unwrap();
+            // Get return type
+            if param_idx as usize == fn_decl.inputs.len() {
+                match fn_decl.output {
+                    hir::FnRetTy::Return(ty) => Some(ty),
+                    // The unit type `()` is always well-formed
+                    hir::FnRetTy::DefaultReturn(_span) => None,
+                }
+            } else {
+                Some(&fn_decl.inputs[param_idx as usize])
+            }
+        }
+    };
+    if let Some(ty) = ty {
+        visitor.visit_ty(ty);
+    }
+    visitor.cause
+}
+
+struct EraseAllBoundRegions<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+// Higher ranked regions are complicated.
+// To make matters worse, the HIR WF check can instantiate them
+// outside of a `Binder`, due to the way we (ab)use
+// `ItemCtxt::to_ty`. To make things simpler, we just erase all
+// of them, regardless of depth. At worse, this will give
+// us an inaccurate span for an error message, but cannot
+// lead to unsoundess (we call `delay_span_bug` at the start
+// of `diagnostic_hir_wf_check`).
+impl<'tcx> TypeFolder<'tcx> for EraseAllBoundRegions<'tcx> {
+    fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+    fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
+        if let ty::ReLateBound(..) = r { &ty::ReErased } else { r }
+    }
+}
index 92ef829747271fd158923fe36bbf5de42f4714ef..5b717862e020f9d2bc622b8c4a4991de85ebda03 100644 (file)
@@ -88,6 +88,7 @@ mod coherence;
 mod collect;
 mod constrained_generic_params;
 mod errors;
+pub mod hir_wf_check;
 mod impl_wf_check;
 mod mem_categorization;
 mod outlives;
@@ -462,6 +463,7 @@ pub fn provide(providers: &mut Providers) {
     variance::provide(providers);
     outlives::provide(providers);
     impl_wf_check::provide(providers);
+    hir_wf_check::provide(providers);
 }
 
 pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
index 7fa5353d09b899e7af4872bdb3ee522b41a4788c..775133f2ab3194f96dce98c507447f8617149542 100644 (file)
@@ -38,7 +38,7 @@ changelog-seen = 2
 # This is false by default so that distributions don't unexpectedly download
 # LLVM from the internet.
 #
-# All tier 1 targets are currently supported; set this to `"if-supported"` if
+# All tier 1 targets are currently supported; set this to `"if-available"` if
 # you are not sure whether you're on a tier 1 target.
 #
 # We also currently only support this when building LLVM for the build triple.
@@ -567,8 +567,8 @@ changelog-seen = 2
 # On Linux target, if crt-static is not enabled, 'no' means dynamic link to
 # `libgcc_s.so`, 'in-tree' means static link to the in-tree build of llvm libunwind
 # and 'system' means dynamic link to `libunwind.so`. If crt-static is enabled,
-# the behavior is depend on the libc. On musl target, 'no' and 'in-tree' both 
-# means static link to the in-tree build of llvm libunwind, and 'system' means 
+# the behavior is depend on the libc. On musl target, 'no' and 'in-tree' both
+# means static link to the in-tree build of llvm libunwind, and 'system' means
 # static link to `libunwind.a` provided by system. Due to the limitation of glibc,
 # it must link to `libgcc_eh.a` to get a working output, and this option have no effect.
 #llvm-libunwind = 'no'
index c7d63488d823c63bde3678749b6bdb3d67afd96d..2753057ab40429da8c3c0ad1aaf44f0914419440 100644 (file)
@@ -1 +1 @@
-a178d0322ce20e33eac124758e837cbd80a6f633
\ No newline at end of file
+c8dfcfe046a7680554bf4eb612bad840e7631c4b
\ No newline at end of file
index 21a0fb844e8c4ebff14a42ccc8351d28487b99dc..920a5ca7db067891c871adc1173f2b56254cf7ff 100644 (file)
@@ -177,7 +177,7 @@ pub fn iteration_mut_100000(b: &mut Bencher) {
     bench_iteration_mut(b, 100000);
 }
 
-fn bench_first_and_last(b: &mut Bencher, size: i32) {
+fn bench_first_and_last_nightly(b: &mut Bencher, size: i32) {
     let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
     b.iter(|| {
         for _ in 0..10 {
@@ -187,19 +187,44 @@ fn bench_first_and_last(b: &mut Bencher, size: i32) {
     });
 }
 
+fn bench_first_and_last_stable(b: &mut Bencher, size: i32) {
+    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+    b.iter(|| {
+        for _ in 0..10 {
+            black_box(map.iter().next());
+            black_box(map.iter().next_back());
+        }
+    });
+}
+
+#[bench]
+pub fn first_and_last_0_nightly(b: &mut Bencher) {
+    bench_first_and_last_nightly(b, 0);
+}
+
+#[bench]
+pub fn first_and_last_0_stable(b: &mut Bencher) {
+    bench_first_and_last_stable(b, 0);
+}
+
+#[bench]
+pub fn first_and_last_100_nightly(b: &mut Bencher) {
+    bench_first_and_last_nightly(b, 100);
+}
+
 #[bench]
-pub fn first_and_last_0(b: &mut Bencher) {
-    bench_first_and_last(b, 0);
+pub fn first_and_last_100_stable(b: &mut Bencher) {
+    bench_first_and_last_stable(b, 100);
 }
 
 #[bench]
-pub fn first_and_last_100(b: &mut Bencher) {
-    bench_first_and_last(b, 100);
+pub fn first_and_last_10k_nightly(b: &mut Bencher) {
+    bench_first_and_last_nightly(b, 10_000);
 }
 
 #[bench]
-pub fn first_and_last_10k(b: &mut Bencher) {
-    bench_first_and_last(b, 10_000);
+pub fn first_and_last_10k_stable(b: &mut Bencher) {
+    bench_first_and_last_stable(b, 10_000);
 }
 
 const BENCH_RANGE_SIZE: i32 = 145;
index 9d61b3684b82c4cd10b93ddf10e4790efd0aac07..482a497201de6d54fba41e8ce4876110ce80df0c 100644 (file)
@@ -177,6 +177,7 @@ where
 /// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "Cow")]
 pub enum Cow<'a, B: ?Sized + 'a>
 where
     B: ToOwned,
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 @@ impl<T> Box<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 @@ impl<T> BinaryHeap<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 af87a9b956a176d9bc59f5d4eb7494ce82380ce5..c4861817dd05da395b86aa137136a194cf086b27 100644 (file)
@@ -3,7 +3,7 @@ use super::node::{marker, ForceResult::*, Handle, LeftOrRight::*, NodeRef, Root}
 
 impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
     /// Stocks up a possibly underfull node by merging with or stealing from a
-    /// sibling. If succesful but at the cost of shrinking the parent node,
+    /// sibling. If successful but at the cost of shrinking the parent node,
     /// returns that shrunk parent node. Returns an `Err` if the node is
     /// an empty root.
     fn fix_node_through_parent(
index 30194aa446f4b43f089c8e61a443f5adc0d68f68..79042ab739c748a41167cd92822eb243f9ffc36c 100644 (file)
@@ -889,7 +889,6 @@ impl<K, V> BTreeMap<K, V> {
     /// 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
@@ -936,6 +935,7 @@ impl<K, V> BTreeMap<K, V> {
     /// Retains only the elements specified by the predicate.
     ///
     /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`.
+    /// The elements are visited in ascending key order.
     ///
     /// # Examples
     ///
@@ -1299,7 +1299,7 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> {
             None
         } else {
             self.length -= 1;
-            Some(unsafe { self.range.next_unchecked() })
+            Some(unsafe { self.range.inner.next_unchecked() })
         }
     }
 
@@ -1330,7 +1330,7 @@ impl<'a, K: 'a, V: 'a> DoubleEndedIterator for Iter<'a, K, V> {
             None
         } else {
             self.length -= 1;
-            Some(unsafe { self.range.next_back_unchecked() })
+            Some(unsafe { self.range.inner.next_back_unchecked() })
         }
     }
 }
@@ -1368,7 +1368,7 @@ impl<'a, K: 'a, V: 'a> Iterator for IterMut<'a, K, V> {
             None
         } else {
             self.length -= 1;
-            Some(unsafe { self.range.next_unchecked() })
+            Some(unsafe { self.range.inner.next_unchecked() })
         }
     }
 
@@ -1396,7 +1396,7 @@ impl<'a, K: 'a, V: 'a> DoubleEndedIterator for IterMut<'a, K, V> {
             None
         } else {
             self.length -= 1;
-            Some(unsafe { self.range.next_back_unchecked() })
+            Some(unsafe { self.range.inner.next_back_unchecked() })
         }
     }
 }
@@ -1475,7 +1475,7 @@ impl<K, V> Drop for Dropper<K, V> {
 #[stable(feature = "btree_drop", since = "1.7.0")]
 impl<K, V> Drop for IntoIter<K, V> {
     fn drop(&mut self) {
-        if let Some(front) = self.range.front.take() {
+        if let Some(front) = self.range.take_front() {
             Dropper { front, remaining_length: self.length };
         }
     }
@@ -1490,8 +1490,7 @@ impl<K, V> Iterator for IntoIter<K, V> {
             None
         } else {
             self.length -= 1;
-            let front = self.range.front.as_mut().unwrap();
-            let kv = unsafe { front.deallocating_next_unchecked() };
+            let kv = unsafe { self.range.deallocating_next_unchecked() };
             Some(kv.into_key_val())
         }
     }
@@ -1508,8 +1507,7 @@ impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
             None
         } else {
             self.length -= 1;
-            let back = self.range.back.as_mut().unwrap();
-            let kv = unsafe { back.deallocating_next_back_unchecked() };
+            let kv = unsafe { self.range.deallocating_next_back_unchecked() };
             Some(kv.into_key_val())
         }
     }
@@ -1727,7 +1725,7 @@ impl<'a, K, V> Iterator for Range<'a, K, V> {
     type Item = (&'a K, &'a V);
 
     fn next(&mut self) -> Option<(&'a K, &'a V)> {
-        if self.inner.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) }
+        self.inner.next_checked()
     }
 
     fn last(mut self) -> Option<(&'a K, &'a V)> {
@@ -1777,12 +1775,6 @@ impl<K, V> ExactSizeIterator for ValuesMut<'_, K, V> {
 #[stable(feature = "fused", since = "1.26.0")]
 impl<K, V> FusedIterator for ValuesMut<'_, K, V> {}
 
-impl<'a, K, V> Range<'a, K, V> {
-    unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
-        unsafe { self.inner.front.as_mut().unwrap_unchecked().next_unchecked() }
-    }
-}
-
 #[stable(feature = "map_into_keys_values", since = "1.54.0")]
 impl<K, V> Iterator for IntoKeys<K, V> {
     type Item = K;
@@ -1862,13 +1854,7 @@ impl<K, V> FusedIterator for IntoValues<K, V> {}
 #[stable(feature = "btree_range", since = "1.17.0")]
 impl<'a, K, V> DoubleEndedIterator for Range<'a, K, V> {
     fn next_back(&mut self) -> Option<(&'a K, &'a V)> {
-        if self.inner.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) }
-    }
-}
-
-impl<'a, K, V> Range<'a, K, V> {
-    unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
-        unsafe { self.inner.back.as_mut().unwrap_unchecked().next_back_unchecked() }
+        self.inner.next_back_checked()
     }
 }
 
@@ -1878,7 +1864,7 @@ impl<K, V> FusedIterator for Range<'_, K, V> {}
 #[stable(feature = "btree_range", since = "1.17.0")]
 impl<K, V> Clone for Range<'_, K, V> {
     fn clone(&self) -> Self {
-        Range { inner: LeafRange { front: self.inner.front, back: self.inner.back } }
+        Range { inner: self.inner.clone() }
     }
 }
 
@@ -1887,7 +1873,7 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> {
     type Item = (&'a K, &'a mut V);
 
     fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
-        if self.inner.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) }
+        self.inner.next_checked()
     }
 
     fn last(mut self) -> Option<(&'a K, &'a mut V)> {
@@ -1904,10 +1890,6 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> {
 }
 
 impl<'a, K, V> RangeMut<'a, K, V> {
-    unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
-        unsafe { self.inner.front.as_mut().unwrap_unchecked().next_unchecked() }
-    }
-
     /// Returns an iterator of references over the remaining items.
     #[inline]
     pub(super) fn iter(&self) -> Range<'_, K, V> {
@@ -1918,19 +1900,13 @@ impl<'a, K, V> RangeMut<'a, K, V> {
 #[stable(feature = "btree_range", since = "1.17.0")]
 impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> {
     fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> {
-        if self.inner.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) }
+        self.inner.next_back_checked()
     }
 }
 
 #[stable(feature = "fused", since = "1.26.0")]
 impl<K, V> FusedIterator for RangeMut<'_, K, V> {}
 
-impl<'a, K, V> RangeMut<'a, K, V> {
-    unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
-        unsafe { self.inner.back.as_mut().unwrap_unchecked().next_back_unchecked() }
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
     fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> BTreeMap<K, V> {
@@ -2189,7 +2165,6 @@ impl<K, V> BTreeMap<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 6b30d95977395fc9c53d7cba74d5c79a487719a1..5fec8dc2d13343a6b45730474d1105b83cd1ce3f 100644 (file)
@@ -14,6 +14,7 @@ use Entry::*;
 ///
 /// [`entry`]: BTreeMap::entry
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeEntry")]
 pub enum Entry<'a, K: 'a, V: 'a> {
     /// A vacant entry.
     #[stable(feature = "rust1", since = "1.0.0")]
index 563c070dd0f1f81cc0c38b72bbc6a3fdcbfc2cc7..bf3542b384d78715117c3094c2feae0ce41c7083 100644 (file)
@@ -4,9 +4,16 @@ use core::ptr;
 
 use super::node::{marker, ForceResult::*, Handle, NodeRef};
 
+// `front` and `back` are always both `None` or both `Some`.
 pub struct LeafRange<BorrowType, K, V> {
-    pub front: Option<Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>>,
-    pub back: Option<Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>>,
+    front: Option<Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>>,
+    back: Option<Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>>,
+}
+
+impl<'a, K: 'a, V: 'a> Clone for LeafRange<marker::Immut<'a>, K, V> {
+    fn clone(&self) -> Self {
+        LeafRange { front: self.front.clone(), back: self.back.clone() }
+    }
 }
 
 impl<BorrowType, K, V> LeafRange<BorrowType, K, V> {
@@ -14,7 +21,7 @@ impl<BorrowType, K, V> LeafRange<BorrowType, K, V> {
         LeafRange { front: None, back: None }
     }
 
-    pub fn is_empty(&self) -> bool {
+    fn is_empty(&self) -> bool {
         self.front == self.back
     }
 
@@ -27,6 +34,77 @@ impl<BorrowType, K, V> LeafRange<BorrowType, K, V> {
     }
 }
 
+impl<'a, K, V> LeafRange<marker::Immut<'a>, K, V> {
+    #[inline]
+    pub fn next_checked(&mut self) -> Option<(&'a K, &'a V)> {
+        if self.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) }
+    }
+
+    #[inline]
+    pub fn next_back_checked(&mut self) -> Option<(&'a K, &'a V)> {
+        if self.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) }
+    }
+
+    #[inline]
+    pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
+        unsafe { self.front.as_mut().unwrap().next_unchecked() }
+    }
+
+    #[inline]
+    pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
+        unsafe { self.back.as_mut().unwrap().next_back_unchecked() }
+    }
+}
+
+impl<'a, K, V> LeafRange<marker::ValMut<'a>, K, V> {
+    #[inline]
+    pub fn next_checked(&mut self) -> Option<(&'a K, &'a mut V)> {
+        if self.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) }
+    }
+
+    #[inline]
+    pub fn next_back_checked(&mut self) -> Option<(&'a K, &'a mut V)> {
+        if self.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) }
+    }
+
+    #[inline]
+    pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
+        unsafe { self.front.as_mut().unwrap().next_unchecked() }
+    }
+
+    #[inline]
+    pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
+        unsafe { self.back.as_mut().unwrap().next_back_unchecked() }
+    }
+}
+
+impl<K, V> LeafRange<marker::Dying, K, V> {
+    #[inline]
+    pub fn take_front(
+        &mut self,
+    ) -> Option<Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge>> {
+        self.front.take()
+    }
+
+    #[inline]
+    pub unsafe fn deallocating_next_unchecked(
+        &mut self,
+    ) -> Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV> {
+        debug_assert!(self.front.is_some());
+        let front = self.front.as_mut().unwrap();
+        unsafe { front.deallocating_next_unchecked() }
+    }
+
+    #[inline]
+    pub unsafe fn deallocating_next_back_unchecked(
+        &mut self,
+    ) -> Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV> {
+        debug_assert!(self.back.is_some());
+        let back = self.back.as_mut().unwrap();
+        unsafe { back.deallocating_next_back_unchecked() }
+    }
+}
+
 impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
     /// Finds the distinct leaf edges delimiting a specified range in a tree.
     ///
@@ -36,7 +114,7 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
     /// result will eventually reach the same edge.
     ///
     /// If there are no such edges, i.e., if the tree contains no key within
-    /// the range, returns a pair of empty options.
+    /// the range, returns an empty `front` and `back`.
     ///
     /// # Safety
     /// Unless `BorrowType` is `Immut`, do not use the handles to visit the same
@@ -191,7 +269,7 @@ impl<BorrowType: marker::BorrowType, K, V>
     /// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
     /// on the left side, which is either in the same leaf node or in an ancestor node.
     /// If the leaf edge is the first one in the tree, returns [`Result::Err`] with the root node.
-    pub fn next_back_kv(
+    fn next_back_kv(
         self,
     ) -> Result<
         Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::KV>,
@@ -216,7 +294,7 @@ impl<BorrowType: marker::BorrowType, K, V>
     /// Given an internal edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
     /// on the right side, which is either in the same internal node or in an ancestor node.
     /// If the internal edge is the last one in the tree, returns [`Result::Err`] with the root node.
-    pub fn next_kv(
+    fn next_kv(
         self,
     ) -> Result<
         Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::KV>,
@@ -250,7 +328,7 @@ impl<K, V> Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge> {
     /// - The returned KV handle is only valid to access the key and value,
     ///   and only valid until the next call to this method or counterpart
     ///   `deallocating_next_back`.
-    pub unsafe fn deallocating_next(
+    unsafe fn deallocating_next(
         self,
     ) -> Option<(Self, Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV>)>
     {
@@ -316,10 +394,9 @@ impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Ed
     ///
     /// # Safety
     /// There must be another KV in the direction travelled.
-    pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
+    unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
         super::mem::replace(self, |leaf_edge| {
-            let kv = leaf_edge.next_kv();
-            let kv = unsafe { kv.ok().unwrap_unchecked() };
+            let kv = leaf_edge.next_kv().ok().unwrap();
             (kv.next_leaf_edge(), kv.into_kv())
         })
     }
@@ -329,10 +406,9 @@ impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Ed
     ///
     /// # Safety
     /// There must be another KV in the direction travelled.
-    pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
+    unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
         super::mem::replace(self, |leaf_edge| {
-            let kv = leaf_edge.next_back_kv();
-            let kv = unsafe { kv.ok().unwrap_unchecked() };
+            let kv = leaf_edge.next_back_kv().ok().unwrap();
             (kv.next_back_leaf_edge(), kv.into_kv())
         })
     }
@@ -344,10 +420,9 @@ impl<'a, K, V> Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::E
     ///
     /// # Safety
     /// There must be another KV in the direction travelled.
-    pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
+    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();
-            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.
@@ -359,10 +434,9 @@ impl<'a, K, V> Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::E
     ///
     /// # Safety
     /// There must be another KV in the direction travelled.
-    pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
+    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();
-            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.
@@ -386,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
@@ -403,11 +475,11 @@ impl<K, V> Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge> {
     ///
     /// The only safe way to proceed with the updated handle is to compare it, drop it,
     /// or call this method or counterpart `deallocating_next_unchecked` again.
-    pub unsafe fn deallocating_next_back_unchecked(
+    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()
         })
     }
 }
@@ -508,9 +580,7 @@ impl<BorrowType: marker::BorrowType, K, V>
     }
 
     /// Returns the leaf edge closest to a KV for backward navigation.
-    pub fn next_back_leaf_edge(
-        self,
-    ) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
+    fn next_back_leaf_edge(self) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
         match self.force() {
             Leaf(leaf_kv) => leaf_kv.left_edge(),
             Internal(internal_kv) => {
index 3c453529ba84d3d93794c7da6602c9289955d3ec..30d237d8bbc547fa77a22c0f5b037c709958652b 100644 (file)
@@ -167,7 +167,7 @@ type BoxedNode<K, V> = NonNull<LeafNode<K, V>>;
 ///   carry a lifetime, because we want it to return `&'a` references.
 ///   Therefore, we define it only for the least powerful type `Immut<'a>`.
 /// - We cannot get implicit coercion from say `Mut<'a>` to `Immut<'a>`.
-///   Therefore, we have to explicitly call `reborrow` on a more powerfull
+///   Therefore, we have to explicitly call `reborrow` on a more powerful
 ///   `NodeRef` in order to reach a method like `into_kv`.
 ///
 /// All methods on `NodeRef` that return some kind of reference, either:
index 737932d931c0283647c3d06bc5ff5d201c299a9e..9711214aea62381204cbbece21ef3067250b809a 100644 (file)
@@ -810,7 +810,6 @@ impl<T> BTreeSet<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
@@ -847,6 +846,7 @@ impl<T> BTreeSet<T> {
     /// Retains only the elements specified by the predicate.
     ///
     /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
+    /// The elements are visited in ascending order.
     ///
     /// # Examples
     ///
@@ -904,8 +904,8 @@ impl<T> BTreeSet<T> {
         self.map.append(&mut other.map);
     }
 
-    /// Splits the collection into two at the given key. Returns everything after the given key,
-    /// including the key.
+    /// Splits the collection into two at the given value. Returns everything after the given value,
+    /// including the value.
     ///
     /// # Examples
     ///
@@ -934,25 +934,27 @@ impl<T> BTreeSet<T> {
     /// assert!(b.contains(&41));
     /// ```
     #[stable(feature = "btree_split_off", since = "1.11.0")]
-    pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self
+    pub fn split_off<Q: ?Sized + Ord>(&mut self, value: &Q) -> Self
     where
         T: Borrow<Q> + Ord,
     {
-        BTreeSet { map: self.map.split_off(key) }
+        BTreeSet { map: self.map.split_off(value) }
     }
 
-    /// 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 +1023,6 @@ impl<T> BTreeSet<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 1a58ad51f78d3e8465a41d6f5fe9518a6f62f8f5..588ba2de2209bcd32e1ae3425a48c87bc2b44e5d 100644 (file)
@@ -586,7 +586,6 @@ impl<T> LinkedList<T> {
     /// 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 {
@@ -1243,6 +1242,20 @@ impl<'a, T> Cursor<'a, T> {
             prev.map(|prev| &(*prev.as_ptr()).element)
         }
     }
+
+    /// Provides a reference to the front element of the cursor's parent list,
+    /// or None if the list is empty.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn front(&self) -> Option<&'a T> {
+        self.list.front()
+    }
+
+    /// Provides a reference to the back element of the cursor's parent list,
+    /// or None if the list is empty.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn back(&self) -> Option<&'a T> {
+        self.list.back()
+    }
 }
 
 impl<'a, T> CursorMut<'a, T> {
@@ -1506,6 +1519,135 @@ impl<'a, T> CursorMut<'a, T> {
         self.index = 0;
         unsafe { self.list.split_off_before_node(self.current, split_off_idx) }
     }
+
+    /// Appends an element to the front of the cursor's parent list. The node
+    /// that the cursor points to is unchanged, even if it is the "ghost" node.
+    ///
+    /// This operation should compute in O(1) time.
+    // `push_front` continues to point to "ghost" when it addes a node to mimic
+    // the behavior of `insert_before` on an empty list.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn push_front(&mut self, elt: T) {
+        // Safety: We know that `push_front` does not change the position in
+        // memory of other nodes. This ensures that `self.current` remains
+        // valid.
+        self.list.push_front(elt);
+        self.index += 1;
+    }
+
+    /// Appends an element to the back of the cursor's parent list. The node
+    /// that the cursor points to is unchanged, even if it is the "ghost" node.
+    ///
+    /// This operation should compute in O(1) time.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn push_back(&mut self, elt: T) {
+        // Safety: We know that `push_back` does not change the position in
+        // memory of other nodes. This ensures that `self.current` remains
+        // valid.
+        self.list.push_back(elt);
+        if self.current().is_none() {
+            // The index of "ghost" is the length of the list, so we just need
+            // to increment self.index to reflect the new length of the list.
+            self.index += 1;
+        }
+    }
+
+    /// Removes the first element from the cursor's parent list and returns it,
+    /// or None if the list is empty. The element the cursor points to remains
+    /// unchanged, unless it was pointing to the front element. In that case, it
+    /// points to the new front element.
+    ///
+    /// This operation should compute in O(1) time.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn pop_front(&mut self) -> Option<T> {
+        // We can't check if current is empty, we must check the list directly.
+        // It is possible for `self.current == None` and the list to be
+        // non-empty.
+        if self.list.is_empty() {
+            None
+        } else {
+            // We can't point to the node that we pop. Copying the behavior of
+            // `remove_current`, we move on the the next node in the sequence.
+            // If the list is of length 1 then we end pointing to the "ghost"
+            // node at index 0, which is expected.
+            if self.list.head == self.current {
+                self.move_next();
+            } else {
+                self.index -= 1;
+            }
+            self.list.pop_front()
+        }
+    }
+
+    /// Removes the last element from the cursor's parent list and returns it,
+    /// or None if the list is empty. The element the cursor points to remains
+    /// unchanged, unless it was pointing to the back element. In that case, it
+    /// points to the "ghost" element.
+    ///
+    /// This operation should compute in O(1) time.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn pop_back(&mut self) -> Option<T> {
+        if self.list.is_empty() {
+            None
+        } else {
+            if self.list.tail == self.current {
+                // The index now reflects the length of the list. It was the
+                // length of the list minus 1, but now the list is 1 smaller. No
+                // change is needed for `index`.
+                self.current = None;
+            } else if self.current.is_none() {
+                self.index = self.list.len - 1;
+            }
+            self.list.pop_back()
+        }
+    }
+
+    /// Provides a reference to the front element of the cursor's parent list,
+    /// or None if the list is empty.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn front(&self) -> Option<&T> {
+        self.list.front()
+    }
+
+    /// Provides a mutable reference to the front element of the cursor's
+    /// parent list, or None if the list is empty.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn front_mut(&mut self) -> Option<&mut T> {
+        self.list.front_mut()
+    }
+
+    /// Provides a reference to the back element of the cursor's parent list,
+    /// or None if the list is empty.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn back(&self) -> Option<&T> {
+        self.list.back()
+    }
+
+    /// Provides a mutable reference to back element of the cursor's parent
+    /// list, or `None` if the list is empty.
+    ///
+    /// # Examples
+    /// Building and mutating a list with a cursor, then getting the back element:
+    /// ```
+    /// #![feature(linked_list_cursors)]
+    /// use std::collections::LinkedList;
+    /// let mut dl = LinkedList::new();
+    /// dl.push_front(3);
+    /// dl.push_front(2);
+    /// dl.push_front(1);
+    /// let mut cursor = dl.cursor_front_mut();
+    /// *cursor.current().unwrap() = 99;
+    /// *cursor.back_mut().unwrap() = 0;
+    /// let mut contents = dl.into_iter();
+    /// assert_eq!(contents.next(), Some(99));
+    /// assert_eq!(contents.next(), Some(2));
+    /// assert_eq!(contents.next(), Some(0));
+    /// assert_eq!(contents.next(), None);
+    /// ```
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn back_mut(&mut self) -> Option<&mut T> {
+        self.list.back_mut()
+    }
 }
 
 /// An iterator produced by calling `drain_filter` on LinkedList.
index ad643a7bdf1941ad15e2c65dca218cf8e0f80a9f..5a65ed7a962e9eabdca357380e8d7da19bfbc872 100644 (file)
@@ -428,3 +428,50 @@ fn test_cursor_mut_insert() {
     check_links(&m);
     assert_eq!(m.iter().cloned().collect::<Vec<_>>(), &[200, 201, 202, 203, 1, 100, 101]);
 }
+
+#[test]
+fn test_cursor_push_front_back() {
+    let mut ll: LinkedList<u32> = LinkedList::new();
+    ll.extend(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+    let mut c = ll.cursor_front_mut();
+    assert_eq!(c.current(), Some(&mut 1));
+    assert_eq!(c.index(), Some(0));
+    c.push_front(0);
+    assert_eq!(c.current(), Some(&mut 1));
+    assert_eq!(c.peek_prev(), Some(&mut 0));
+    assert_eq!(c.index(), Some(1));
+    c.push_back(11);
+    drop(c);
+    let p = ll.cursor_back().front().unwrap();
+    assert_eq!(p, &0);
+    assert_eq!(ll, (0..12).collect());
+    check_links(&ll);
+}
+
+#[test]
+fn test_cursor_pop_front_back() {
+    let mut ll: LinkedList<u32> = LinkedList::new();
+    ll.extend(&[1, 2, 3, 4, 5, 6]);
+    let mut c = ll.cursor_back_mut();
+    assert_eq!(c.pop_front(), Some(1));
+    c.move_prev();
+    c.move_prev();
+    c.move_prev();
+    assert_eq!(c.pop_back(), Some(6));
+    let c = c.as_cursor();
+    assert_eq!(c.front(), Some(&2));
+    assert_eq!(c.back(), Some(&5));
+    assert_eq!(c.index(), Some(1));
+    drop(c);
+    assert_eq!(ll, (2..6).collect());
+    check_links(&ll);
+    let mut c = ll.cursor_back_mut();
+    assert_eq!(c.current(), Some(&mut 5));
+    assert_eq!(c.index, 3);
+    assert_eq!(c.pop_back(), Some(5));
+    assert_eq!(c.current(), None);
+    assert_eq!(c.index, 3);
+    assert_eq!(c.pop_back(), Some(4));
+    assert_eq!(c.current(), None);
+    assert_eq!(c.index, 2);
+}
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 f3eb228c9e3802dab098de5d886dc79f8e7901c1..ae1b03c9a4d2247b4a201135c4e82ac18c807e0e 100644 (file)
@@ -103,6 +103,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
     }
 
     #[inline]
+    #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
     where
         Self: TrustedRandomAccess,
index 9493676e66bc8f3232e6937aea62a6a99a47a38a..df30c38652f72ef0ea100e31ba6110883c992592 100644 (file)
@@ -89,6 +89,7 @@ impl<'a, T> Iterator for IterMut<'a, T> {
     }
 
     #[inline]
+    #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
     where
         Self: TrustedRandomAccess,
index 5d03be35e466fea7e14994ccfe7200c1d9f03c3c..461e701be054ee82b9493ef0ba0d27ec95f14668 100644 (file)
@@ -1036,7 +1036,6 @@ impl<T> VecDeque<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 a04e7c8a498daf7d6cda9dff39feee5a810d331d..fa1f361a5b6d1998e478024953a84e5803677dae 100644 (file)
 //! [`Rc`]: rc
 //! [`RefCell`]: core::cell
 
+// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be
+// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
+// rustc itself never sets the feature, so this line has no affect there.
+#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
 #![allow(unused_attributes)]
 #![stable(feature = "alloc", since = "1.36.0")]
 #![doc(
 #![feature(iter_zip)]
 #![feature(lang_items)]
 #![feature(layout_for_ptr)]
-#![feature(maybe_uninit_ref)]
 #![feature(negative_impls)]
 #![feature(never_type)]
 #![feature(nll)]
 #![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_uninit_array)]
 #![feature(alloc_layout_extra)]
 #![feature(trusted_random_access)]
-#![cfg_attr(bootstrap, feature(try_trait))]
-#![cfg_attr(not(bootstrap), feature(try_trait_v2))]
+#![feature(try_trait_v2)]
 #![feature(min_type_alias_impl_trait)]
 #![feature(associated_type_bounds)]
 #![feature(slice_group_by)]
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 2e2c9b76bd4ba6a1d74d73f6935b8961adfaad8f..d11d4031f77548e92e3b61dfe22eaffff3b03efa 100644 (file)
@@ -463,7 +463,6 @@ impl<T, A: Allocator> RawVec<T, A> {
         Ok(())
     }
 
-    #[cfg(not(no_global_oom_handling))]
     fn shrink(&mut self, amount: usize) -> Result<(), TryReserveError> {
         assert!(amount <= self.capacity(), "Tried to shrink to a larger capacity");
 
index f131182a89633939108adc060962e6653a3ac5af..e116ab6483c9b3638dc14ccf3d048a386a39e892 100644 (file)
@@ -262,6 +262,7 @@ use core::marker::{self, PhantomData, Unpin, Unsize};
 use core::mem::size_of_val;
 use core::mem::{self, align_of_val_raw, forget};
 use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver};
+#[cfg(not(no_global_oom_handling))]
 use core::pin::Pin;
 use core::ptr::{self, NonNull};
 #[cfg(not(no_global_oom_handling))]
@@ -346,6 +347,7 @@ impl<T> Rc<T> {
     ///
     /// let five = Rc::new(5);
     /// ```
+    #[cfg(not(no_global_oom_handling))]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(value: T) -> Rc<T> {
         // There is an implicit weak pointer owned by all the strong
@@ -381,6 +383,7 @@ impl<T> Rc<T> {
     ///     }
     /// }
     /// ```
+    #[cfg(not(no_global_oom_handling))]
     #[unstable(feature = "arc_new_cyclic", issue = "75861")]
     pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Rc<T> {
         // Construct the inner in the "uninitialized" state with a single
@@ -577,6 +580,7 @@ impl<T> Rc<T> {
     }
     /// Constructs a new `Pin<Rc<T>>`. If `T` does not implement `Unpin`, then
     /// `value` will be pinned in memory and unable to be moved.
+    #[cfg(not(no_global_oom_handling))]
     #[stable(feature = "pin", since = "1.33.0")]
     pub fn pin(value: T) -> Pin<Rc<T>> {
         unsafe { Pin::new_unchecked(Rc::new(value)) }
@@ -1473,6 +1477,7 @@ impl<T: ?Sized> Clone for Rc<T> {
     }
 }
 
+#[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Default> Default for Rc<T> {
     /// Creates a new `Rc<T>`, with the `Default` value for `T`.
@@ -1731,6 +1736,7 @@ impl<T: ?Sized> fmt::Pointer for Rc<T> {
     }
 }
 
+#[cfg(not(no_global_oom_handling))]
 #[stable(feature = "from_for_ptrs", since = "1.6.0")]
 impl<T> From<T> for Rc<T> {
     /// Converts a generic type `T` into a `Rc<T>`
index dcd64899204925fdaed1c9cf3618c30dd13b9a70..4c8ea6902ff14eea756de30a4f409ef97173d57f 100644 (file)
@@ -1042,7 +1042,7 @@ where
 }
 
 /// This merge sort borrows some (but not all) ideas from TimSort, which is described in detail
-/// [here](http://svn.python.org/projects/python/trunk/Objects/listsort.txt).
+/// [here](https://github.com/python/cpython/blob/main/Objects/listsort.txt).
 ///
 /// The algorithm identifies strictly descending and non-descending subsequences, which are called
 /// natural runs. There is a stack of pending runs yet to be merged. Each newly found run is pushed
index 57279e81a9578d0c16ff0c55ec7581d7923d77a6..62ba2e57655074ecc0dd613103dfb6a8bee5de62 100644 (file)
@@ -396,7 +396,7 @@ impl str {
         return s;
 
         fn map_uppercase_sigma(from: &str, i: usize, to: &mut String) {
-            // See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
+            // See https://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
             // for the definition of `Final_Sigma`.
             debug_assert!('Σ'.len_utf8() == 2);
             let is_word_final = case_ignoreable_then_cased(from[..i].chars().rev())
index 93f5fe45cd6aa28de9313f4ca0da20410800a1b1..0d8678291bef749536a7a30b003ff84aa6e9eab7 100644 (file)
@@ -419,8 +419,6 @@ impl 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) }
@@ -1451,7 +1449,7 @@ impl String {
 
         unsafe {
             ptr::copy(self.vec.as_ptr().add(idx), self.vec.as_mut_ptr().add(idx + amt), len - idx);
-            ptr::copy(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt);
+            ptr::copy_nonoverlapping(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt);
             self.vec.set_len(len + amt);
         }
     }
@@ -1534,7 +1532,6 @@ impl String {
     /// 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 {
@@ -2769,33 +2766,31 @@ impl<'a> Drain<'a> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(string_drain_as_str)]
     /// let mut s = String::from("abc");
     /// let mut drain = s.drain(..);
     /// assert_eq!(drain.as_str(), "abc");
     /// let _ = drain.next().unwrap();
     /// assert_eq!(drain.as_str(), "bc");
     /// ```
-    #[unstable(feature = "string_drain_as_str", issue = "76905")] // Note: uncomment AsRef impls below when stabilizing.
+    #[stable(feature = "string_drain_as_str", since = "1.55.0")]
     pub fn as_str(&self) -> &str {
         self.iter.as_str()
     }
 }
 
-// Uncomment when stabilizing `string_drain_as_str`.
-// #[unstable(feature = "string_drain_as_str", issue = "76905")]
-// impl<'a> AsRef<str> for Drain<'a> {
-//     fn as_ref(&self) -> &str {
-//         self.as_str()
-//     }
-// }
-//
-// #[unstable(feature = "string_drain_as_str", issue = "76905")]
-// impl<'a> AsRef<[u8]> for Drain<'a> {
-//     fn as_ref(&self) -> &[u8] {
-//         self.as_str().as_bytes()
-//     }
-// }
+#[stable(feature = "string_drain_as_str", since = "1.55.0")]
+impl<'a> AsRef<str> for Drain<'a> {
+    fn as_ref(&self) -> &str {
+        self.as_str()
+    }
+}
+
+#[stable(feature = "string_drain_as_str", since = "1.55.0")]
+impl<'a> AsRef<[u8]> for Drain<'a> {
+    fn as_ref(&self) -> &[u8] {
+        self.as_str().as_bytes()
+    }
+}
 
 #[stable(feature = "drain", since = "1.6.0")]
 impl Iterator for Drain<'_> {
index a8fa028fc9009e8a2700a500338835e936bc6c5d..d821e71562212ed86fd7d083331da0b78f4d6909 100644 (file)
@@ -332,6 +332,7 @@ impl<T> Arc<T> {
     ///
     /// let five = Arc::new(5);
     /// ```
+    #[cfg(not(no_global_oom_handling))]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(data: T) -> Arc<T> {
@@ -365,6 +366,7 @@ impl<T> Arc<T> {
     ///     me: me.clone(),
     /// });
     /// ```
+    #[cfg(not(no_global_oom_handling))]
     #[inline]
     #[unstable(feature = "arc_new_cyclic", issue = "75861")]
     pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Arc<T> {
@@ -485,11 +487,19 @@ impl<T> Arc<T> {
 
     /// Constructs a new `Pin<Arc<T>>`. If `T` does not implement `Unpin`, then
     /// `data` will be pinned in memory and unable to be moved.
+    #[cfg(not(no_global_oom_handling))]
     #[stable(feature = "pin", since = "1.33.0")]
     pub fn pin(data: T) -> Pin<Arc<T>> {
         unsafe { Pin::new_unchecked(Arc::new(data)) }
     }
 
+    /// Constructs a new `Pin<Arc<T>>`, return an error if allocation fails.
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    #[inline]
+    pub fn try_pin(data: T) -> Result<Pin<Arc<T>>, AllocError> {
+        unsafe { Ok(Pin::new_unchecked(Arc::try_new(data)?)) }
+    }
+
     /// Constructs a new `Arc<T>`, returning an error if allocation fails.
     ///
     /// # Examples
@@ -2274,6 +2284,7 @@ impl<T: ?Sized> fmt::Pointer for Arc<T> {
     }
 }
 
+#[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Default> Default for Arc<T> {
     /// Creates a new `Arc<T>`, with the `Default` value for `T`.
@@ -2298,8 +2309,23 @@ impl<T: ?Sized + Hash> Hash for Arc<T> {
     }
 }
 
+#[cfg(not(no_global_oom_handling))]
 #[stable(feature = "from_for_ptrs", since = "1.6.0")]
 impl<T> From<T> for Arc<T> {
+    /// Converts a `T` into an `Arc<T>`
+    ///
+    /// The conversion moves the value into a
+    /// newly allocated `Arc`. It is equivalent to
+    /// calling `Arc::new(t)`.
+    ///
+    /// # Example
+    /// ```rust
+    /// # use std::sync::Arc;
+    /// let x = 5;
+    /// let arc = Arc::new(5);
+    ///
+    /// assert_eq!(Arc::from(x), arc);
+    /// ```
     fn from(t: T) -> Self {
         Arc::new(t)
     }
index 8da4d995ba5c66094dbfb45a431f7bd720fc96c4..7a08f4c6cbaaceba1f983cc6be2cb116aae54c4c 100644 (file)
@@ -163,6 +163,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
         self.len()
     }
 
+    #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item
     where
         Self: TrustedRandomAccess,
index 4a1d564e2ab879547f8036133d7c0dc296c34c70..61599259735c7d5a25632b46f5c58f41227a8384 100644 (file)
@@ -459,7 +459,6 @@ impl<T> Vec<T> {
     /// ```
     #[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 @@ impl<T, A: Allocator> Vec<T, A> {
     /// 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 @@ impl<T, A: Allocator> Vec<T, A> {
     /// 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 @@ impl<T, A: Allocator> Vec<T, A> {
     /// }
     /// # 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 @@ impl<T, A: Allocator> Vec<T, A> {
     /// }
     /// # 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 @@ impl<T, A: Allocator> Vec<T, A> {
     /// 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 @@ impl<T, A: Allocator> Vec<T, A> {
     /// 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 @@ impl<T, A: Allocator> Vec<T, A> {
     /// 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 {
@@ -2407,6 +2399,18 @@ impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
     }
 }
 
+/// The hash of a vector is the same as that of the corresponding slice,
+/// as required by the `core::borrow::Borrow` implementation.
+///
+/// ```
+/// #![feature(build_hasher_simple_hash_one)]
+/// use std::hash::BuildHasher;
+///
+/// let b = std::collections::hash_map::RandomState::new();
+/// let v: Vec<u8> = vec![0xa8, 0x3c, 0x09];
+/// let s: &[u8] = &[0xa8, 0x3c, 0x09];
+/// assert_eq!(b.hash_one(v), b.hash_one(s));
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Hash, A: Allocator> Hash for Vec<T, A> {
     #[inline]
@@ -2551,6 +2555,8 @@ impl<T, A: Allocator> Vec<T, A> {
             }
             unsafe {
                 ptr::write(self.as_mut_ptr().add(len), element);
+                // Since next() executes user code which can panic we have to bump the length
+                // after each step.
                 // NB can't overflow since we would have had to alloc the address space
                 self.set_len(len + 1);
             }
index e857d284d3ab654d14710d73d08a921f96f6661e..d814d4ae355b0496eb08f08400aeb8a3bf35df83 100644 (file)
@@ -89,6 +89,8 @@ fn write_in_place_with_drop<T>(
             // all we can do is check if it's still in range
             debug_assert!(sink.dst as *const _ <= src_end, "InPlaceIterable contract violation");
             ptr::write(sink.dst, item);
+            // Since this executes user code which can panic we have to bump the pointer
+            // after each step.
             sink.dst = sink.dst.add(1);
         }
         Ok(sink)
@@ -136,6 +138,8 @@ where
                 let dst = dst_buf.offset(i as isize);
                 debug_assert!(dst as *const _ <= end, "InPlaceIterable contract violation");
                 ptr::write(dst, self.__iterator_get_unchecked(i));
+                // Since this executes user code which can panic we have to bump the pointer
+                // after each step.
                 drop_guard.dst = dst.add(1);
             }
         }
index c6f4f22a01f6e2170cb382a9ebfb633951c8ad39..c3b4534096de5f1c5a7171db69fd46f5f4bd7922 100644 (file)
@@ -40,6 +40,8 @@ where
                 iterator.for_each(move |element| {
                     ptr::write(ptr, element);
                     ptr = ptr.offset(1);
+                    // Since the loop executes user code which can panic we have to bump the pointer
+                    // after each step.
                     // NB can't overflow since we would have had to alloc the address space
                     local_len.increment_len(1);
                 });
index 6df8d8c2f354f9a6256bde30bc4e97fa9bfd68d4..a1e819cf8f9e44b1cdfb53905b3dcf92212c4661 100644 (file)
@@ -534,7 +534,7 @@ mod slice_index {
     #[test]
     #[should_panic]
     fn test_slice_fail() {
-        &"中华Việt Nam"[0..2];
+        let _ = &"中华Việt Nam"[0..2];
     }
 
     panic_cases! {
@@ -714,13 +714,13 @@ mod slice_index {
     #[test]
     #[should_panic(expected = "byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
     fn test_slice_fail_truncated_1() {
-        &LOREM_PARAGRAPH[..1024];
+        let _ = &LOREM_PARAGRAPH[..1024];
     }
     // check the truncation in the panic message
     #[test]
     #[should_panic(expected = "luctus, im`[...]")]
     fn test_slice_fail_truncated_2() {
-        &LOREM_PARAGRAPH[..1024];
+        let _ = &LOREM_PARAGRAPH[..1024];
     }
 }
 
@@ -735,7 +735,7 @@ fn test_str_slice_rangetoinclusive_ok() {
 #[should_panic]
 fn test_str_slice_rangetoinclusive_notok() {
     let s = "abcαβγ";
-    &s[..=3];
+    let _ = &s[..=3];
 }
 
 #[test]
@@ -751,7 +751,7 @@ fn test_str_slicemut_rangetoinclusive_ok() {
 fn test_str_slicemut_rangetoinclusive_notok() {
     let mut s = "abcαβγ".to_owned();
     let s: &mut str = &mut s;
-    &mut s[..=3];
+    let _ = &mut s[..=3];
 }
 
 #[test]
index c203cdafecb03dd27be6f502965adffb715b6491..3b7237016800fac107de9030ec87d79089c279b0 100644 (file)
@@ -542,35 +542,35 @@ fn test_index_out_of_bounds() {
 #[should_panic]
 fn test_slice_out_of_bounds_1() {
     let x = vec![1, 2, 3, 4, 5];
-    &x[!0..];
+    let _ = &x[!0..];
 }
 
 #[test]
 #[should_panic]
 fn test_slice_out_of_bounds_2() {
     let x = vec![1, 2, 3, 4, 5];
-    &x[..6];
+    let _ = &x[..6];
 }
 
 #[test]
 #[should_panic]
 fn test_slice_out_of_bounds_3() {
     let x = vec![1, 2, 3, 4, 5];
-    &x[!0..4];
+    let _ = &x[!0..4];
 }
 
 #[test]
 #[should_panic]
 fn test_slice_out_of_bounds_4() {
     let x = vec![1, 2, 3, 4, 5];
-    &x[1..6];
+    let _ = &x[1..6];
 }
 
 #[test]
 #[should_panic]
 fn test_slice_out_of_bounds_5() {
     let x = vec![1, 2, 3, 4, 5];
-    &x[3..2];
+    let _ = &x[3..2];
 }
 
 #[test]
index f2169914ac9dad16a355c8aebd7113c2f7e9c85f..24257ba98785d52421d6e83e8e6a5c34133740cd 100644 (file)
@@ -45,7 +45,7 @@ fn bench_max_by_key(b: &mut Bencher) {
     })
 }
 
-// http://www.reddit.com/r/rust/comments/31syce/using_iterators_to_find_the_index_of_the_min_or/
+// https://www.reddit.com/r/rust/comments/31syce/using_iterators_to_find_the_index_of_the_min_or/
 #[bench]
 fn bench_max_by_key2(b: &mut Bencher) {
     fn max_index_iter(array: &[i32]) -> usize {
index 6dcc110f1539c104ba3a560599bb47ffe7e096ca..0a098c8e2d98633d158e50f175ee7fda400e6cc7 100644 (file)
@@ -20,24 +20,69 @@ use crate::ptr;
 ///
 /// # Example
 ///
-/// ```no_run
-/// use std::alloc::{GlobalAlloc, Layout, alloc};
+/// ```
+/// use std::alloc::{GlobalAlloc, Layout};
+/// use std::cell::UnsafeCell;
 /// use std::ptr::null_mut;
+/// use std::sync::atomic::{
+///     AtomicUsize,
+///     Ordering::{Acquire, SeqCst},
+/// };
 ///
-/// struct MyAllocator;
-///
-/// unsafe impl GlobalAlloc for MyAllocator {
-///     unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() }
-///     unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
+/// const ARENA_SIZE: usize = 128 * 1024;
+/// const MAX_SUPPORTED_ALIGN: usize = 4096;
+/// #[repr(C, align(4096))] // 4096 == MAX_SUPPORTED_ALIGN
+/// struct SimpleAllocator {
+///     arena: UnsafeCell<[u8; ARENA_SIZE]>,
+///     remaining: AtomicUsize, // we allocate from the top, counting down
 /// }
 ///
 /// #[global_allocator]
-/// static A: MyAllocator = MyAllocator;
+/// static ALLOCATOR: SimpleAllocator = SimpleAllocator {
+///     arena: UnsafeCell::new([0x55; ARENA_SIZE]),
+///     remaining: AtomicUsize::new(ARENA_SIZE),
+/// };
 ///
-/// fn main() {
-///     unsafe {
-///         assert!(alloc(Layout::new::<u32>()).is_null())
+/// unsafe impl Sync for SimpleAllocator {}
+///
+/// unsafe impl GlobalAlloc for SimpleAllocator {
+///     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+///         let size = layout.size();
+///         let align = layout.align();
+///
+///         // `Layout` contract forbids making a `Layout` with align=0, or align not power of 2.
+///         // So we can safely use a mask to ensure alignment without worrying about UB.
+///         let align_mask_to_round_down = !(align - 1);
+///
+///         if align > MAX_SUPPORTED_ALIGN {
+///             return null_mut();
+///         }
+///
+///         let mut allocated = 0;
+///         if self
+///             .remaining
+///             .fetch_update(SeqCst, SeqCst, |mut remaining| {
+///                 if size > remaining {
+///                     return None;
+///                 }
+///                 remaining -= size;
+///                 remaining &= align_mask_to_round_down;
+///                 allocated = remaining;
+///                 Some(remaining)
+///             })
+///             .is_err()
+///         {
+///             return null_mut();
+///         };
+///         (self.arena.get() as *mut u8).add(allocated)
 ///     }
+///     unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
+/// }
+///
+/// fn main() {
+///     let _s = format!("allocating a string!");
+///     let currently = ALLOCATOR.remaining.load(Acquire);
+///     println!("allocated so far: {}", ARENA_SIZE - currently);
 /// }
 /// ```
 ///
index 0e7667dd89e644916228765c79ecc07d4f5f1b1b..ccf6e420de7a99579862433df772a8f72e138e5e 100644 (file)
@@ -60,7 +60,7 @@ impl Layout {
     #[inline]
     pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
         if !align.is_power_of_two() {
-            return Err(LayoutError { private: () });
+            return Err(LayoutError);
         }
 
         // (power-of-two implies align != 0.)
@@ -78,7 +78,7 @@ impl Layout {
         // Above implies that checking for summation overflow is both
         // necessary and sufficient.
         if size > usize::MAX - (align - 1) {
-            return Err(LayoutError { private: () });
+            return Err(LayoutError);
         }
 
         // SAFETY: the conditions for `from_size_align_unchecked` have been
@@ -288,7 +288,7 @@ impl Layout {
         // > must not overflow (i.e., the rounded value must be less than
         // > `usize::MAX`)
         let padded_size = self.size() + self.padding_needed_for(self.align());
-        let alloc_size = padded_size.checked_mul(n).ok_or(LayoutError { private: () })?;
+        let alloc_size = padded_size.checked_mul(n).ok_or(LayoutError)?;
 
         // SAFETY: self.align is already known to be valid and alloc_size has been
         // padded already.
@@ -346,8 +346,8 @@ impl Layout {
         let new_align = cmp::max(self.align(), next.align());
         let pad = self.padding_needed_for(next.align());
 
-        let offset = self.size().checked_add(pad).ok_or(LayoutError { private: () })?;
-        let new_size = offset.checked_add(next.size()).ok_or(LayoutError { private: () })?;
+        let offset = self.size().checked_add(pad).ok_or(LayoutError)?;
+        let new_size = offset.checked_add(next.size()).ok_or(LayoutError)?;
 
         let layout = Layout::from_size_align(new_size, new_align)?;
         Ok((layout, offset))
@@ -368,7 +368,7 @@ impl Layout {
     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
     #[inline]
     pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutError> {
-        let size = self.size().checked_mul(n).ok_or(LayoutError { private: () })?;
+        let size = self.size().checked_mul(n).ok_or(LayoutError)?;
         Layout::from_size_align(size, self.align())
     }
 
@@ -381,7 +381,7 @@ impl Layout {
     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
     #[inline]
     pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutError> {
-        let new_size = self.size().checked_add(next.size()).ok_or(LayoutError { private: () })?;
+        let new_size = self.size().checked_add(next.size()).ok_or(LayoutError)?;
         Layout::from_size_align(new_size, self.align())
     }
 
@@ -409,10 +409,9 @@ pub type LayoutErr = LayoutError;
 /// or some other `Layout` constructor
 /// do not satisfy its documented constraints.
 #[stable(feature = "alloc_layout_error", since = "1.50.0")]
+#[non_exhaustive]
 #[derive(Clone, PartialEq, Eq, Debug)]
-pub struct LayoutError {
-    private: (),
-}
+pub struct LayoutError;
 
 // (we need this for downstream impl of trait Error)
 #[stable(feature = "alloc_layout", since = "1.28.0")]
index 5e1725cfc7a6324b178740ac72a47dd9c6adca60..19652106b3d01325f5f9f9266b7932447e594cd1 100644 (file)
@@ -108,6 +108,7 @@ use crate::intrinsics;
 // unsafe traits and unsafe methods (i.e., `type_id` would still be safe to call,
 // but we would likely want to indicate as such in documentation).
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "Any")]
 pub trait Any: 'static {
     /// Gets the `TypeId` of `self`.
     ///
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 37af3557fdd51ce792459ec680f32019413bbf03..78b799cd709763a6bb8ffbd52fd8ce2ad8773143 100644 (file)
@@ -14,6 +14,7 @@ use crate::mem::{self, MaybeUninit};
 use crate::ops::{Index, IndexMut};
 use crate::slice::{Iter, IterMut};
 
+mod equality;
 mod iter;
 
 #[stable(feature = "array_value_iter", since = "1.51.0")]
@@ -139,6 +140,18 @@ impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
     }
 }
 
+/// The hash of an array is the same as that of the corresponding slice,
+/// as required by the `Borrow` implementation.
+///
+/// ```
+/// #![feature(build_hasher_simple_hash_one)]
+/// use std::hash::BuildHasher;
+///
+/// let b = std::collections::hash_map::RandomState::new();
+/// let a: [u8; 3] = [0xa8, 0x3c, 0x09];
+/// let s: &[u8] = &[0xa8, 0x3c, 0x09];
+/// assert_eq!(b.hash_one(a), b.hash_one(s));
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Hash, const N: usize> Hash for [T; N] {
     fn hash<H: hash::Hasher>(&self, state: &mut H) {
@@ -218,118 +231,6 @@ where
     }
 }
 
-#[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]
@@ -395,7 +296,6 @@ impl<T, const N: usize> [T; N] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(array_map)]
     /// let x = [1, 2, 3];
     /// let y = x.map(|v| v + 1);
     /// assert_eq!(y, [2, 3, 4]);
@@ -409,7 +309,7 @@ impl<T, const N: usize> [T; N] {
     /// let y = x.map(|v| v.len());
     /// assert_eq!(y, [6, 9, 3, 3]);
     /// ```
-    #[unstable(feature = "array_map", issue = "75243")]
+    #[stable(feature = "array_map", since = "1.55.0")]
     pub fn map<F, U>(self, f: F) -> [U; N]
     where
         F: FnMut(T) -> U,
@@ -476,7 +376,7 @@ impl<T, const N: usize> [T; N] {
     /// array if its elements are not `Copy`.
     ///
     /// ```
-    /// #![feature(array_methods, array_map)]
+    /// #![feature(array_methods)]
     ///
     /// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()];
     /// let is_ascii = strings.each_ref().map(|s| s.is_ascii());
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 f88a6e418c7c819313e069ad44a69a41f9bb2bc9..24b0797f93a50ecb84ed7eac87d32c6591004ffa 100644 (file)
@@ -488,6 +488,13 @@ impl<T: ?Sized> Cell<T> {
     /// This call borrows `Cell` mutably (at compile-time) which guarantees
     /// that we possess the only reference.
     ///
+    /// However be cautious: this method expects `self` to be mutable, which is
+    /// generally not the case when using a `Cell`. If you require interior
+    /// mutability by reference, consider using `RefCell` which provides
+    /// run-time checked mutable borrows through its [`borrow_mut`] method.
+    ///
+    /// [`borrow_mut`]: RefCell::borrow_mut()
+    ///
     /// # Examples
     ///
     /// ```
@@ -578,7 +585,7 @@ pub struct RefCell<T: ?Sized> {
     // Stores the location of the earliest currently active borrow.
     // This gets updated whenver we go from having zero borrows
     // to having a single borrow. When a borrow occurs, this gets included
-    // in the generated `BorroeError/`BorrowMutError`
+    // in the generated `BorrowError/`BorrowMutError`
     #[cfg(feature = "debug_refcell")]
     borrowed_at: Cell<Option<&'static crate::panic::Location<'static>>>,
     value: UnsafeCell<T>,
@@ -586,8 +593,8 @@ pub struct RefCell<T: ?Sized> {
 
 /// An error returned by [`RefCell::try_borrow`].
 #[stable(feature = "try_borrow", since = "1.13.0")]
+#[non_exhaustive]
 pub struct BorrowError {
-    _private: (),
     #[cfg(feature = "debug_refcell")]
     location: &'static crate::panic::Location<'static>,
 }
@@ -613,8 +620,8 @@ impl Display for BorrowError {
 
 /// An error returned by [`RefCell::try_borrow_mut`].
 #[stable(feature = "try_borrow", since = "1.13.0")]
+#[non_exhaustive]
 pub struct BorrowMutError {
-    _private: (),
     #[cfg(feature = "debug_refcell")]
     location: &'static crate::panic::Location<'static>,
 }
@@ -865,7 +872,6 @@ impl<T: ?Sized> RefCell<T> {
                 Ok(Ref { value: unsafe { &*self.value.get() }, borrow: b })
             }
             None => Err(BorrowError {
-                _private: (),
                 // If a borrow occured, then we must already have an outstanding borrow,
                 // so `borrowed_at` will be `Some`
                 #[cfg(feature = "debug_refcell")]
@@ -951,7 +957,6 @@ impl<T: ?Sized> RefCell<T> {
                 Ok(RefMut { value: unsafe { &mut *self.value.get() }, borrow: b })
             }
             None => Err(BorrowMutError {
-                _private: (),
                 // If a borrow occured, then we must already have an outstanding borrow,
                 // so `borrowed_at` will be `Some`
                 #[cfg(feature = "debug_refcell")]
@@ -1073,7 +1078,6 @@ impl<T: ?Sized> RefCell<T> {
             Ok(unsafe { &*self.value.get() })
         } else {
             Err(BorrowError {
-                _private: (),
                 // If a borrow occured, then we must already have an outstanding borrow,
                 // so `borrowed_at` will be `Some`
                 #[cfg(feature = "debug_refcell")]
index 80d0890551fd2f34e85caef419ca3982cd18c379..e5af22c8fbbef5ae04603c40e64687d73f5517e9 100644 (file)
@@ -15,8 +15,8 @@ impl char {
     /// Point], but only ones within a certain range. `MAX` is the highest valid
     /// code point that's a valid [Unicode Scalar Value].
     ///
-    /// [Unicode Scalar Value]: http://www.unicode.org/glossary/#unicode_scalar_value
-    /// [Code Point]: http://www.unicode.org/glossary/#code_point
+    /// [Unicode Scalar Value]: https://www.unicode.org/glossary/#unicode_scalar_value
+    /// [Code Point]: https://www.unicode.org/glossary/#code_point
     #[stable(feature = "assoc_char_consts", since = "1.52.0")]
     pub const MAX: char = '\u{10ffff}';
 
@@ -28,7 +28,7 @@ impl char {
     #[stable(feature = "assoc_char_consts", since = "1.52.0")]
     pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}';
 
-    /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of
+    /// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of
     /// `char` and `str` methods are based on.
     ///
     /// New versions of Unicode are released regularly and subsequently all methods
@@ -1494,8 +1494,8 @@ impl char {
     /// before using this function.
     ///
     /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
-    /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
-    /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
+    /// [pct]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
+    /// [bfs]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
     ///
     /// # Examples
     ///
index 25a7c1de9de4bddcbf7ad56918fd573990e9848b..0728523d0a413a9bb34aa057bf933de14d929cc3 100644 (file)
@@ -5,8 +5,8 @@
 //! scalar value]', which is similar to, but not the same as, a '[Unicode code
 //! point]'.
 //!
-//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
-//! [Unicode code point]: http://www.unicode.org/glossary/#code_point
+//! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
+//! [Unicode code point]: https://www.unicode.org/glossary/#code_point
 //!
 //! This module exists for technical reasons, the primary documentation for
 //! `char` is directly on [the `char` primitive type][char] itself.
@@ -95,8 +95,8 @@ const MAX_THREE_B: u32 = 0x10000;
 /// Point], but only ones within a certain range. `MAX` is the highest valid
 /// code point that's a valid [Unicode Scalar Value].
 ///
-/// [Unicode Scalar Value]: http://www.unicode.org/glossary/#unicode_scalar_value
-/// [Code Point]: http://www.unicode.org/glossary/#code_point
+/// [Unicode Scalar Value]: https://www.unicode.org/glossary/#unicode_scalar_value
+/// [Code Point]: https://www.unicode.org/glossary/#code_point
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MAX: char = char::MAX;
 
index 51a2dc03de3186668e51f942acd9cd841a0b3017..19faf9cddac6faa392a946742d00807d7441bf29 100644 (file)
@@ -38,7 +38,7 @@
 
 /// A common trait for the ability to explicitly duplicate an object.
 ///
-/// Differs from [`Copy`] in that [`Copy`] is implicit and extremely inexpensive, while
+/// Differs from [`Copy`] in that [`Copy`] is implicit and an inexpensive bit-wise copy, while
 /// `Clone` is always explicit and may or may not be expensive. In order to enforce
 /// these characteristics, Rust does not allow you to reimplement [`Copy`], but you
 /// may reimplement `Clone` and run arbitrary code.
index ecea898504dc70a7784e7b2d52db991d70d908d7..79610bb409d37c06b383ea7622452560b179ebf6 100644 (file)
@@ -27,12 +27,25 @@ use self::Ordering::*;
 /// Trait for equality comparisons which are [partial equivalence
 /// relations](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
 ///
+/// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`.
+/// We use the easier-to-read infix notation in the remainder of this documentation.
+///
 /// This trait allows for partial equality, for types that do not have a full
 /// equivalence relation. For example, in floating point numbers `NaN != NaN`,
 /// so floating point types implement `PartialEq` but not [`trait@Eq`].
 ///
-/// Formally, the equality must be (for all `a`, `b`, `c` of type `A`, `B`,
-/// `C`):
+/// Implementations must ensure that `eq` and `ne` are consistent with each other:
+///
+/// - `a != b` if and only if `!(a == b)`
+///   (ensured by the default implementation).
+///
+/// If [`PartialOrd`] or [`Ord`] are also implemented for `Self` and `Rhs`, their methods must also
+/// be consistent with `PartialEq` (see the documentation of those traits for the exact
+/// requirements). It's easy to accidentally make them disagree by deriving some of the traits and
+/// manually implementing others.
+///
+/// The equality relation `==` must satisfy the following conditions
+/// (for all `a`, `b`, `c` of type `A`, `B`, `C`):
 ///
 /// - **Symmetric**: if `A: PartialEq<B>` and `B: PartialEq<A>`, then **`a == b`
 ///   implies `b == a`**; and
@@ -53,15 +66,6 @@ use self::Ordering::*;
 ///
 /// ## How can I implement `PartialEq`?
 ///
-/// `PartialEq` only requires the [`eq`] method to be implemented; [`ne`] is defined
-/// in terms of it by default. Any manual implementation of [`ne`] *must* respect
-/// the rule that [`eq`] is a strict inverse of [`ne`]; that is, `!(a == b)` if and
-/// only if `a != b`.
-///
-/// Implementations of `PartialEq`, [`PartialOrd`], and [`Ord`] *must* agree with
-/// each other. It's easy to accidentally make them disagree by deriving some
-/// of the traits and manually implementing others.
-///
 /// An example implementation for a domain in which two books are considered
 /// the same book if their ISBN matches, even if the formats differ:
 ///
@@ -631,10 +635,25 @@ impl<T: Clone> Clone for Reverse<T> {
 
 /// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
 ///
-/// An order is a total order if it is (for all `a`, `b` and `c`):
+/// Implementations must be consistent with the [`PartialOrd`] implementation, and ensure
+/// `max`, `min`, and `clamp` are consistent with `cmp`:
+///
+/// - `partial_cmp(a, b) == Some(cmp(a, b))`.
+/// - `max(a, b) == max_by(a, b, cmp)` (ensured by the default implementation).
+/// - `min(a, b) == min_by(a, b, cmp)` (ensured by the default implementation).
+/// - For `a.clamp(min, max)`, see the [method docs](#method.clamp)
+///   (ensured by the default implementation).
+///
+/// It's easy to accidentally make `cmp` and `partial_cmp` disagree by
+/// deriving some of the traits and manually implementing others.
+///
+/// ## Corollaries
+///
+/// From the above and the requirements of `PartialOrd`, it follows that `<` defines a strict total order.
+/// This means that for all `a`, `b` and `c`:
 ///
-/// - total and asymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and
-/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
+/// - exactly one of `a < b`, `a == b` or `a > b` is true; and
+/// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
 ///
 /// ## Derivable
 ///
@@ -659,12 +678,6 @@ impl<T: Clone> Clone for Reverse<T> {
 /// Then you must define an implementation for [`cmp`]. You may find it useful to use
 /// [`cmp`] on your type's fields.
 ///
-/// Implementations of [`PartialEq`], [`PartialOrd`], and `Ord` *must*
-/// agree with each other. That is, `a.cmp(b) == Ordering::Equal` if
-/// and only if `a == b` and `Some(a.cmp(b)) == a.partial_cmp(b)` for
-/// all `a` and `b`. It's easy to accidentally make them disagree by
-/// deriving some of the traits and manually implementing others.
-///
 /// Here's an example where you want to sort people by height only, disregarding `id`
 /// and `name`:
 ///
@@ -824,15 +837,45 @@ impl PartialOrd for Ordering {
 
 /// Trait for values that can be compared for a sort-order.
 ///
+/// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using
+/// the `<`, `<=`, `>`, and `>=` operators, respectively.
+///
+/// The methods of this trait must be consistent with each other and with those of `PartialEq` in
+/// the following sense:
+///
+/// - `a == b` if and only if `partial_cmp(a, b) == Some(Equal)`.
+/// - `a < b` if and only if `partial_cmp(a, b) == Some(Less)`
+///   (ensured by the default implementation).
+/// - `a > b` if and only if `partial_cmp(a, b) == Some(Greater)`
+///   (ensured by the default implementation).
+/// - `a <= b` if and only if `a < b || a == b`
+///   (ensured by the default implementation).
+/// - `a >= b` if and only if `a > b || a == b`
+///   (ensured by the default implementation).
+/// - `a != b` if and only if `!(a == b)` (already part of `PartialEq`).
+///
+/// If [`Ord`] is also implemented for `Self` and `Rhs`, it must also be consistent with
+/// `partial_cmp` (see the documentation of that trait for the exact requirements). It's
+/// easy to accidentally make them disagree by deriving some of the traits and manually
+/// implementing others.
+///
 /// The comparison must satisfy, for all `a`, `b` and `c`:
 ///
-/// - asymmetry: if `a < b` then `!(a > b)`, as well as `a > b` implying `!(a < b)`; and
 /// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
+/// - duality: `a < b` if and only if `b > a`.
 ///
 /// Note that these requirements mean that the trait itself must be implemented symmetrically and
 /// transitively: if `T: PartialOrd<U>` and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
 /// PartialOrd<V>`.
 ///
+/// ## Corollaries
+///
+/// The following corollaries follow from the above requirements:
+///
+/// - irreflexivity of `<` and `>`: `!(a < a)`, `!(a > a)`
+/// - transitivity of `>`: if `a > b` and `b > c` then `a > c`
+/// - duality of `partial_cmp`: `partial_cmp(a, b) == partial_cmp(b, a).map(Ordering::reverse)`
+///
 /// ## Derivable
 ///
 /// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
@@ -850,10 +893,6 @@ impl PartialOrd for Ordering {
 ///
 /// `PartialOrd` requires your type to be [`PartialEq`].
 ///
-/// Implementations of [`PartialEq`], `PartialOrd`, and [`Ord`] *must* agree with each other. It's
-/// easy to accidentally make them disagree by deriving some of the traits and manually
-/// implementing others.
-///
 /// If your type is [`Ord`], you can implement [`partial_cmp`] by using [`cmp`]:
 ///
 /// ```
@@ -1065,6 +1104,7 @@ pub macro PartialOrd($item:item) {
 #[inline]
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "cmp_min")]
 pub fn min<T: Ord>(v1: T, v2: T) -> T {
     v1.min(v2)
 }
@@ -1127,6 +1167,7 @@ pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
 #[inline]
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "cmp_max")]
 pub fn max<T: Ord>(v1: T, v2: T) -> T {
     v1.max(v2)
 }
index 65af8508a6839cfcdb23a5851b84c59de03508be..1e512af48051ed9dc7c5627ed29aef8b0906506f 100644 (file)
@@ -152,6 +152,7 @@ pub const fn identity<T>(x: T) -> T {
 /// is_hello(s);
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "AsRef")]
 pub trait AsRef<T: ?Sized> {
     /// Performs the conversion.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -193,6 +194,7 @@ pub trait AsRef<T: ?Sized> {
 ///
 /// [`Box<T>`]: ../../std/boxed/struct.Box.html
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "AsMut")]
 pub trait AsMut<T: ?Sized> {
     /// Performs the conversion.
     #[stable(feature = "rust1", since = "1.0.0")]
index a522b7da3bd1c64df67e67a9e29557d5e06c85c5..1d3a12962145e44c780d568c2c67689d37e92a1a 100644 (file)
@@ -145,7 +145,7 @@ impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.2
 
 // CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize.
 // https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf
-// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf
+// https://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf
 
 // Note: integers can only be represented with full precision in a float if
 // they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
index ece3cde00158074feaaa79348a0e40a4cf51e3dd..ba65f0fadbd9d88a38ff35fb8c4fa2e1d5154b74 100644 (file)
@@ -1,6 +1,7 @@
 use crate::fmt::{Debug, Display, Formatter, LowerExp, Result, UpperExp};
 use crate::mem::MaybeUninit;
 use crate::num::flt2dec;
+use crate::num::fmt as numfmt;
 
 // Don't inline this so callers don't use the stack space this function
 // requires unless they have to.
@@ -15,7 +16,7 @@ where
     T: flt2dec::DecodableFloat,
 {
     let mut buf: [MaybeUninit<u8>; 1024] = MaybeUninit::uninit_array(); // enough for f32 and f64
-    let mut parts: [MaybeUninit<flt2dec::Part<'_>>; 4] = MaybeUninit::uninit_array();
+    let mut parts: [MaybeUninit<numfmt::Part<'_>>; 4] = MaybeUninit::uninit_array();
     let formatted = flt2dec::to_exact_fixed_str(
         flt2dec::strategy::grisu::format_exact,
         *num,
@@ -41,7 +42,7 @@ where
 {
     // enough for f32 and f64
     let mut buf: [MaybeUninit<u8>; flt2dec::MAX_SIG_DIGITS] = MaybeUninit::uninit_array();
-    let mut parts: [MaybeUninit<flt2dec::Part<'_>>; 4] = MaybeUninit::uninit_array();
+    let mut parts: [MaybeUninit<numfmt::Part<'_>>; 4] = MaybeUninit::uninit_array();
     let formatted = flt2dec::to_shortest_str(
         flt2dec::strategy::grisu::format_shortest,
         *num,
@@ -85,7 +86,7 @@ where
     T: flt2dec::DecodableFloat,
 {
     let mut buf: [MaybeUninit<u8>; 1024] = MaybeUninit::uninit_array(); // enough for f32 and f64
-    let mut parts: [MaybeUninit<flt2dec::Part<'_>>; 6] = MaybeUninit::uninit_array();
+    let mut parts: [MaybeUninit<numfmt::Part<'_>>; 6] = MaybeUninit::uninit_array();
     let formatted = flt2dec::to_exact_exp_str(
         flt2dec::strategy::grisu::format_exact,
         *num,
@@ -112,7 +113,7 @@ where
 {
     // enough for f32 and f64
     let mut buf: [MaybeUninit<u8>; flt2dec::MAX_SIG_DIGITS] = MaybeUninit::uninit_array();
-    let mut parts: [MaybeUninit<flt2dec::Part<'_>>; 6] = MaybeUninit::uninit_array();
+    let mut parts: [MaybeUninit<numfmt::Part<'_>>; 6] = MaybeUninit::uninit_array();
     let formatted = flt2dec::to_shortest_exp_str(
         flt2dec::strategy::grisu::format_shortest,
         *num,
index 02ac4fb8006556c20e140362a623f323b2e3d1e6..48142f66915bb296c91df446ce854d9a8d81d731 100644 (file)
@@ -7,13 +7,16 @@ use crate::char::EscapeDebugExtArgs;
 use crate::iter;
 use crate::marker::PhantomData;
 use crate::mem;
-use crate::num::flt2dec;
+use crate::num::fmt as numfmt;
 use crate::ops::Deref;
 use crate::result;
 use crate::str;
 
 mod builders;
+#[cfg(not(no_fp_fmt_parse))]
 mod float;
+#[cfg(no_fp_fmt_parse)]
+mod nofloat;
 mod num;
 
 #[stable(feature = "fmt_flags_align", since = "1.28.0")]
@@ -444,8 +447,9 @@ impl<'a> Arguments<'a> {
     /// assert_eq!(format_args!("{}", 1).as_str(), None);
     /// ```
     #[stable(feature = "fmt_as_str", since = "1.52.0")]
+    #[rustc_const_unstable(feature = "const_arguments_as_str", issue = "none")]
     #[inline]
-    pub fn as_str(&self) -> Option<&'static str> {
+    pub const fn as_str(&self) -> Option<&'static str> {
         match (self.pieces, self.args) {
             ([], []) => Some(""),
             ([s], []) => Some(s),
@@ -564,7 +568,7 @@ impl Display for Arguments<'_> {
     on(
         crate_local,
         label = "`{Self}` cannot be formatted using `{{:?}}`",
-        note = "add `#[derive(Debug)]` or manually implement `{Debug}`"
+        note = "add `#[derive(Debug)]` to `{Self}` or manually `impl {Debug} for {Self}`"
     ),
     message = "`{Self}` doesn't implement `{Debug}`",
     label = "`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`"
@@ -662,6 +666,7 @@ pub use macros::Debug;
     note = "in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead"
 )]
 #[doc(alias = "{}")]
+#[rustc_diagnostic_item = "display_trait"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Display {
     /// Formats the value using the given formatter.
@@ -1421,7 +1426,7 @@ impl<'a> Formatter<'a> {
     /// Takes the formatted parts and applies the padding.
     /// Assumes that the caller already has rendered the parts with required precision,
     /// so that `self.precision` can be ignored.
-    fn pad_formatted_parts(&mut self, formatted: &flt2dec::Formatted<'_>) -> Result {
+    fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
         if let Some(mut width) = self.width {
             // for the sign-aware zero padding, we render the sign first and
             // behave as if we had no sign from the beginning.
@@ -1461,14 +1466,14 @@ impl<'a> Formatter<'a> {
         }
     }
 
-    fn write_formatted_parts(&mut self, formatted: &flt2dec::Formatted<'_>) -> Result {
+    fn write_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
         fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result {
-            // SAFETY: This is used for `flt2dec::Part::Num` and `flt2dec::Part::Copy`.
-            // It's safe to use for `flt2dec::Part::Num` since every char `c` is between
+            // SAFETY: This is used for `numfmt::Part::Num` and `numfmt::Part::Copy`.
+            // It's safe to use for `numfmt::Part::Num` since every char `c` is between
             // `b'0'` and `b'9'`, which means `s` is valid UTF-8.
-            // It's also probably safe in practice to use for `flt2dec::Part::Copy(buf)`
+            // It's also probably safe in practice to use for `numfmt::Part::Copy(buf)`
             // since `buf` should be plain ASCII, but it's possible for someone to pass
-            // in a bad value for `buf` into `flt2dec::to_shortest_str` since it is a
+            // in a bad value for `buf` into `numfmt::to_shortest_str` since it is a
             // public function.
             // FIXME: Determine whether this could result in UB.
             buf.write_str(unsafe { str::from_utf8_unchecked(s) })
@@ -1479,7 +1484,7 @@ impl<'a> Formatter<'a> {
         }
         for part in formatted.parts {
             match *part {
-                flt2dec::Part::Zero(mut nzeroes) => {
+                numfmt::Part::Zero(mut nzeroes) => {
                     const ZEROES: &str = // 64 zeroes
                         "0000000000000000000000000000000000000000000000000000000000000000";
                     while nzeroes > ZEROES.len() {
@@ -1490,7 +1495,7 @@ impl<'a> Formatter<'a> {
                         self.buf.write_str(&ZEROES[..nzeroes])?;
                     }
                 }
-                flt2dec::Part::Num(mut v) => {
+                numfmt::Part::Num(mut v) => {
                     let mut s = [0; 5];
                     let len = part.len();
                     for c in s[..len].iter_mut().rev() {
@@ -1499,7 +1504,7 @@ impl<'a> Formatter<'a> {
                     }
                     write_bytes(self.buf, &s[..len])?;
                 }
-                flt2dec::Part::Copy(buf) => {
+                numfmt::Part::Copy(buf) => {
                     write_bytes(self.buf, buf)?;
                 }
             }
diff --git a/library/core/src/fmt/nofloat.rs b/library/core/src/fmt/nofloat.rs
new file mode 100644 (file)
index 0000000..cfb94cd
--- /dev/null
@@ -0,0 +1,15 @@
+use crate::fmt::{Debug, Formatter, Result};
+
+macro_rules! floating {
+    ($ty:ident) => {
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl Debug for $ty {
+            fn fmt(&self, _fmt: &mut Formatter<'_>) -> Result {
+                panic!("floating point support is turned off");
+            }
+        }
+    };
+}
+
+floating! { f32 }
+floating! { f64 }
index cdd731fdd4d4e34aa65ef93f84c86a9d6247777c..db45640df48d6b49cba7d88a2a513b89a3325f5f 100644 (file)
@@ -2,7 +2,7 @@
 
 use crate::fmt;
 use crate::mem::MaybeUninit;
-use crate::num::flt2dec;
+use crate::num::fmt as numfmt;
 use crate::ops::{Div, Rem, Sub};
 use crate::ptr;
 use crate::slice;
@@ -406,9 +406,9 @@ macro_rules! impl_Exp {
             };
 
             let parts = &[
-                flt2dec::Part::Copy(buf_slice),
-                flt2dec::Part::Zero(added_precision),
-                flt2dec::Part::Copy(exp_slice)
+                numfmt::Part::Copy(buf_slice),
+                numfmt::Part::Zero(added_precision),
+                numfmt::Part::Copy(exp_slice)
             ];
             let sign = if !is_nonnegative {
                 "-"
@@ -417,7 +417,7 @@ macro_rules! impl_Exp {
             } else {
                 ""
             };
-            let formatted = flt2dec::Formatted{sign, parts};
+            let formatted = numfmt::Formatted{sign, parts};
             f.pad_formatted_parts(&formatted)
         }
 
index 77d3a35b268226696a3fb42ad4289b85118308c8..8dec643255f64e600e93292349014a7b97e2559d 100644 (file)
@@ -481,6 +481,53 @@ pub trait BuildHasher {
     /// ```
     #[stable(since = "1.7.0", feature = "build_hasher")]
     fn build_hasher(&self) -> Self::Hasher;
+
+    /// Calculates the hash of a single value.
+    ///
+    /// This is intended as a convenience for code which *consumes* hashes, such
+    /// as the implementation of a hash table or in unit tests that check
+    /// whether a custom [`Hash`] implementation behaves as expected.
+    ///
+    /// This must not be used in any code which *creates* hashes, such as in an
+    /// implementation of [`Hash`].  The way to create a combined hash of
+    /// multiple values is to call [`Hash::hash`] multiple times using the same
+    /// [`Hasher`], not to call this method repeatedly and combine the results.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(build_hasher_simple_hash_one)]
+    ///
+    /// use std::cmp::{max, min};
+    /// use std::hash::{BuildHasher, Hash, Hasher};
+    /// struct OrderAmbivalentPair<T: Ord>(T, T);
+    /// impl<T: Ord + Hash> Hash for OrderAmbivalentPair<T> {
+    ///     fn hash<H: Hasher>(&self, hasher: &mut H) {
+    ///         min(&self.0, &self.1).hash(hasher);
+    ///         max(&self.0, &self.1).hash(hasher);
+    ///     }
+    /// }
+    ///
+    /// // Then later, in a `#[test]` for the type...
+    /// let bh = std::collections::hash_map::RandomState::new();
+    /// assert_eq!(
+    ///     bh.hash_one(OrderAmbivalentPair(1, 2)),
+    ///     bh.hash_one(OrderAmbivalentPair(2, 1))
+    /// );
+    /// assert_eq!(
+    ///     bh.hash_one(OrderAmbivalentPair(10, 2)),
+    ///     bh.hash_one(&OrderAmbivalentPair(2, 10))
+    /// );
+    /// ```
+    #[unstable(feature = "build_hasher_simple_hash_one", issue = "86161")]
+    fn hash_one<T: Hash>(&self, x: T) -> u64
+    where
+        Self: Sized,
+    {
+        let mut hasher = self.build_hasher();
+        x.hash(&mut hasher);
+        hasher.finish()
+    }
 }
 
 /// Used to create a default [`BuildHasher`] instance for types that implement
index 70ab27cbfac57172d489d784cd92268920195faa..238f00e41b3afae97c1b765cd753f197958b0dd5 100644 (file)
@@ -25,7 +25,7 @@
 //! across other volatile intrinsics. See the LLVM documentation on
 //! [[volatile]].
 //!
-//! [volatile]: http://llvm.org/docs/LangRef.html#volatile-memory-accesses
+//! [volatile]: https://llvm.org/docs/LangRef.html#volatile-memory-accesses
 //!
 //! # Atomics
 //!
@@ -33,7 +33,7 @@
 //! words, with multiple possible memory orderings. They obey the same
 //! semantics as C++11. See the LLVM documentation on [[atomics]].
 //!
-//! [atomics]: http://llvm.org/docs/Atomics.html
+//! [atomics]: https://llvm.org/docs/Atomics.html
 //!
 //! A quick refresher on memory ordering:
 //!
@@ -712,8 +712,19 @@ extern "rust-intrinsic" {
 
     /// Aborts the execution of the process.
     ///
-    /// A more user-friendly and stable version of this operation is
-    /// [`std::process::abort`](../../std/process/fn.abort.html).
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
+    /// [`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,
@@ -745,6 +756,11 @@ extern "rust-intrinsic" {
     ///
     /// Any use other than with `if` statements will probably not have an effect.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// This intrinsic does not have a stable counterpart.
     #[rustc_const_unstable(feature = "const_likely", issue = "none")]
     pub fn likely(b: bool) -> bool;
@@ -754,6 +770,11 @@ extern "rust-intrinsic" {
     ///
     /// Any use other than with `if` statements will probably not have an effect.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// This intrinsic does not have a stable counterpart.
     #[rustc_const_unstable(feature = "const_likely", issue = "none")]
     pub fn unlikely(b: bool) -> bool;
@@ -765,6 +786,11 @@ extern "rust-intrinsic" {
 
     /// The size of a type in bytes.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// More specifically, this is the offset in bytes between successive
     /// items of the same type, including alignment padding.
     ///
@@ -774,6 +800,11 @@ extern "rust-intrinsic" {
 
     /// The minimum alignment of a type.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is [`core::mem::align_of`].
     #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
     pub fn min_align_of<T>() -> usize;
@@ -796,6 +827,11 @@ extern "rust-intrinsic" {
 
     /// Gets a static string slice containing the name of a type.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is [`core::any::type_name`].
     #[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
     pub fn type_name<T: ?Sized>() -> &'static str;
@@ -804,6 +840,11 @@ extern "rust-intrinsic" {
     /// function will return the same value for a type regardless of whichever
     /// crate it is invoked in.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is [`core::any::TypeId::of`].
     #[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
     pub fn type_id<T: ?Sized + 'static>() -> u64;
@@ -829,6 +870,11 @@ extern "rust-intrinsic" {
 
     /// Gets a reference to a static `Location` indicating where it was called.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// Consider using [`core::panic::Location::caller`] instead.
     #[rustc_const_unstable(feature = "const_caller_location", issue = "76156")]
     pub fn caller_location() -> &'static crate::panic::Location<'static>;
@@ -837,6 +883,11 @@ extern "rust-intrinsic" {
     ///
     /// This exists solely for [`mem::forget_unsized`]; normal `forget` uses
     /// `ManuallyDrop` instead.
+    ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
     #[rustc_const_unstable(feature = "const_intrinsic_forget", issue = "none")]
     pub fn forget<T: ?Sized>(_: T);
 
@@ -1090,6 +1141,11 @@ extern "rust-intrinsic" {
     /// If the actual type neither requires drop glue nor implements
     /// `Copy`, then the return value of this function is unspecified.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop).
     #[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
     pub fn needs_drop<T>() -> bool;
@@ -1310,21 +1366,41 @@ extern "rust-intrinsic" {
 
     /// Returns the minimum of two `f32` values.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is
     /// [`f32::min`]
     pub fn minnumf32(x: f32, y: f32) -> f32;
     /// Returns the minimum of two `f64` values.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is
     /// [`f64::min`]
     pub fn minnumf64(x: f64, y: f64) -> f64;
     /// Returns the maximum of two `f32` values.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is
     /// [`f32::max`]
     pub fn maxnumf32(x: f32, y: f32) -> f32;
     /// Returns the maximum of two `f64` values.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is
     /// [`f64::max`]
     pub fn maxnumf64(x: f64, y: f64) -> f64;
@@ -1438,6 +1514,11 @@ extern "rust-intrinsic" {
 
     /// Returns the number of bits set in an integer type `T`
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `count_ones` method. For example,
     /// [`u32::count_ones`]
@@ -1446,6 +1527,11 @@ extern "rust-intrinsic" {
 
     /// Returns the number of leading unset bits (zeroes) in an integer type `T`.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `leading_zeros` method. For example,
     /// [`u32::leading_zeros`]
@@ -1497,6 +1583,11 @@ extern "rust-intrinsic" {
 
     /// Returns the number of trailing unset bits (zeroes) in an integer type `T`.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `trailing_zeros` method. For example,
     /// [`u32::trailing_zeros`]
@@ -1548,6 +1639,11 @@ extern "rust-intrinsic" {
 
     /// Reverses the bytes in an integer type `T`.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `swap_bytes` method. For example,
     /// [`u32::swap_bytes`]
@@ -1556,6 +1652,11 @@ extern "rust-intrinsic" {
 
     /// Reverses the bits in an integer type `T`.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `reverse_bits` method. For example,
     /// [`u32::reverse_bits`]
@@ -1564,6 +1665,11 @@ extern "rust-intrinsic" {
 
     /// Performs checked integer addition.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_add` method. For example,
     /// [`u32::overflowing_add`]
@@ -1572,6 +1678,11 @@ extern "rust-intrinsic" {
 
     /// Performs checked integer subtraction
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_sub` method. For example,
     /// [`u32::overflowing_sub`]
@@ -1580,6 +1691,11 @@ extern "rust-intrinsic" {
 
     /// Performs checked integer multiplication
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_mul` method. For example,
     /// [`u32::overflowing_mul`]
@@ -1649,6 +1765,11 @@ extern "rust-intrinsic" {
 
     /// Performs rotate left.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_left` method. For example,
     /// [`u32::rotate_left`]
@@ -1657,6 +1778,11 @@ extern "rust-intrinsic" {
 
     /// Performs rotate right.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_right` method. For example,
     /// [`u32::rotate_right`]
@@ -1665,6 +1791,11 @@ extern "rust-intrinsic" {
 
     /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_add` method. For example,
     /// [`u32::wrapping_add`]
@@ -1672,6 +1803,11 @@ extern "rust-intrinsic" {
     pub fn wrapping_add<T: Copy>(a: T, b: T) -> T;
     /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_sub` method. For example,
     /// [`u32::wrapping_sub`]
@@ -1679,6 +1815,11 @@ extern "rust-intrinsic" {
     pub fn wrapping_sub<T: Copy>(a: T, b: T) -> T;
     /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_mul` method. For example,
     /// [`u32::wrapping_mul`]
@@ -1687,6 +1828,11 @@ extern "rust-intrinsic" {
 
     /// Computes `a + b`, saturating at numeric bounds.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_add` method. For example,
     /// [`u32::saturating_add`]
@@ -1694,6 +1840,11 @@ extern "rust-intrinsic" {
     pub fn saturating_add<T: Copy>(a: T, b: T) -> T;
     /// Computes `a - b`, saturating at numeric bounds.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_sub` method. For example,
     /// [`u32::saturating_sub`]
@@ -1703,6 +1854,11 @@ extern "rust-intrinsic" {
     /// Returns the value of the discriminant for the variant in 'v';
     /// if `T` has no discriminant, returns `0`.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is [`core::mem::discriminant`].
     #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
     pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
@@ -1710,6 +1866,11 @@ extern "rust-intrinsic" {
     /// Returns the number of variants of the type `T` cast to a `usize`;
     /// if `T` has no variants, returns `0`. Uninhabited variants will be counted.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The to-be-stabilized version of this intrinsic is [`mem::variant_count`].
     #[rustc_const_unstable(feature = "variant_count", issue = "73662")]
     pub fn variant_count<T>() -> usize;
@@ -1732,16 +1893,46 @@ extern "rust-intrinsic" {
     pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
 
     /// See documentation of `<*const T>::guaranteed_eq` for details.
+    ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
     #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
     pub fn ptr_guaranteed_eq<T>(ptr: *const T, other: *const T) -> bool;
 
     /// See documentation of `<*const T>::guaranteed_ne` for details.
+    ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
     #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
     pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;
 
     /// 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 7efc155175c34f8c2d4ad0d73cc2e8654562400e..5cd65a9415fd7d2ba553488a3bcec266cedd0fae 100644 (file)
@@ -58,6 +58,7 @@ where
         self.it.map(T::clone).fold(init, f)
     }
 
+    #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
     where
         Self: TrustedRandomAccess,
index def2408927589de601c5c9e246e06e39f78b2cfd..07a3b5d245659ec18da4b5fcbcf71eb5b5a9a8f9 100644 (file)
@@ -74,6 +74,7 @@ where
         self.it.count()
     }
 
+    #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
     where
         Self: TrustedRandomAccess,
index 91722a4b62a2e86ca5c0f5712cea4a5a6caee99e..8b27bdc60a7055aff561a716c22ba9c7d77e967b 100644 (file)
@@ -111,6 +111,7 @@ where
     }
 
     #[rustc_inherit_overflow_checks]
+    #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
     where
         Self: TrustedRandomAccess,
index 3315d346596114e5e691987adee90c30c59bcc00..48880a4d91a57c9e42ca28c9d9898ba5b3062d30 100644 (file)
@@ -1,5 +1,5 @@
 use crate::fmt;
-use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map};
+use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map, TrustedLen};
 use crate::ops::Try;
 
 /// An iterator that maps each element to an iterator, and yields the elements
@@ -114,6 +114,30 @@ where
 {
 }
 
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<T, I, F, const N: usize> TrustedLen for FlatMap<I, [T; N], F>
+where
+    I: TrustedLen,
+    F: FnMut(I::Item) -> [T; N],
+{
+}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<'a, T, I, F, const N: usize> TrustedLen for FlatMap<I, &'a [T; N], F>
+where
+    I: TrustedLen,
+    F: FnMut(I::Item) -> &'a [T; N],
+{
+}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<'a, T, I, F, const N: usize> TrustedLen for FlatMap<I, &'a mut [T; N], F>
+where
+    I: TrustedLen,
+    F: FnMut(I::Item) -> &'a mut [T; N],
+{
+}
+
 /// An iterator that flattens one level of nesting in an iterator of things
 /// that can be turned into iterators.
 ///
@@ -230,6 +254,14 @@ where
 {
 }
 
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<I> TrustedLen for Flatten<I>
+where
+    I: TrustedLen,
+    <I as Iterator>::Item: TrustedConstSize,
+{
+}
+
 /// Real logic of both `Flatten` and `FlatMap` which simply delegate to
 /// this type.
 #[derive(Clone, Debug)]
@@ -282,6 +314,17 @@ where
         let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint);
         let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint);
         let lo = flo.saturating_add(blo);
+
+        if let Some(fixed_size) = <<I as Iterator>::Item as ConstSizeIntoIterator>::size() {
+            let (lower, upper) = self.iter.size_hint();
+
+            let lower = lower.saturating_mul(fixed_size).saturating_add(lo);
+            let upper =
+                try { fhi?.checked_add(bhi?)?.checked_add(fixed_size.checked_mul(upper?)?)? };
+
+            return (lower, upper);
+        }
+
         match (self.iter.size_hint(), fhi, bhi) {
             ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
             _ => (lo, None),
@@ -444,3 +487,52 @@ where
         init
     }
 }
+
+trait ConstSizeIntoIterator: IntoIterator {
+    // FIXME(#31844): convert to an associated const once specialization supports that
+    fn size() -> Option<usize>;
+}
+
+impl<T> ConstSizeIntoIterator for T
+where
+    T: IntoIterator,
+{
+    #[inline]
+    default fn size() -> Option<usize> {
+        None
+    }
+}
+
+impl<T, const N: usize> ConstSizeIntoIterator for [T; N] {
+    #[inline]
+    fn size() -> Option<usize> {
+        Some(N)
+    }
+}
+
+impl<T, const N: usize> ConstSizeIntoIterator for &[T; N] {
+    #[inline]
+    fn size() -> Option<usize> {
+        Some(N)
+    }
+}
+
+impl<T, const N: usize> ConstSizeIntoIterator for &mut [T; N] {
+    #[inline]
+    fn size() -> Option<usize> {
+        Some(N)
+    }
+}
+
+#[doc(hidden)]
+#[unstable(feature = "std_internals", issue = "none")]
+// FIXME(#20400): Instead of this helper trait there should be multiple impl TrustedLen for Flatten<>
+//   blocks with different bounds on Iterator::Item but the compiler erroneously considers them overlapping
+pub unsafe trait TrustedConstSize: IntoIterator {}
+
+#[unstable(feature = "std_internals", issue = "none")]
+unsafe impl<T, const N: usize> TrustedConstSize for [T; N] {}
+#[unstable(feature = "std_internals", issue = "none")]
+unsafe impl<T, const N: usize> TrustedConstSize for &'_ [T; N] {}
+#[unstable(feature = "std_internals", issue = "none")]
+unsafe impl<T, const N: usize> TrustedConstSize for &'_ mut [T; N] {}
index aff48b1b220c411ce645cce1aafee5d777b0af61..408328adeecf464af75a15adad50aa31e7655702 100644 (file)
@@ -1,5 +1,5 @@
 use crate::intrinsics;
-use crate::iter::adapters::{zip::try_get_unchecked, InPlaceIterable, SourceIter};
+use crate::iter::adapters::zip::try_get_unchecked;
 use crate::iter::{
     DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess,
 };
@@ -14,7 +14,9 @@ use crate::ops::Try;
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Fuse<I> {
-    // NOTE: for `I: FusedIterator`, this is always assumed `Some`!
+    // NOTE: for `I: FusedIterator`, we never bother setting `None`, but
+    // we still have to be prepared for that state due to variance.
+    // See rust-lang/rust#85863
     iter: Option<I>,
 }
 impl<I> Fuse<I> {
@@ -42,19 +44,19 @@ macro_rules! fuse {
     };
 }
 
-// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`.
-// Implementing this as a directly-expanded macro helps codegen performance.
-macro_rules! unchecked {
-    ($self:ident) => {
-        match $self {
-            Fuse { iter: Some(iter) } => iter,
-            // SAFETY: the specialized iterator never sets `None`
-            Fuse { iter: None } => unsafe { intrinsics::unreachable() },
+/// Specialized macro that doesn't check if the expression is `None`.
+/// (We trust that a `FusedIterator` will fuse itself.)
+macro_rules! spec {
+    ($self:ident . iter . $($call:tt)+) => {
+        match $self.iter {
+            Some(ref mut iter) => iter.$($call)+,
+            None => None,
         }
     };
 }
 
-// Any implementation here is made internal to avoid exposing default fns outside this trait
+// Any specialized implementation here is made internal
+// to avoid exposing default fns outside this trait.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<I> Iterator for Fuse<I>
 where
@@ -74,17 +76,26 @@ where
 
     #[inline]
     fn last(self) -> Option<Self::Item> {
-        FuseImpl::last(self)
+        match self.iter {
+            Some(iter) => iter.last(),
+            None => None,
+        }
     }
 
     #[inline]
     fn count(self) -> usize {
-        FuseImpl::count(self)
+        match self.iter {
+            Some(iter) => iter.count(),
+            None => 0,
+        }
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        FuseImpl::size_hint(self)
+        match self.iter {
+            Some(ref iter) => iter.size_hint(),
+            None => (0, Some(0)),
+        }
     }
 
     #[inline]
@@ -98,11 +109,14 @@ where
     }
 
     #[inline]
-    fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
+    fn fold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
     where
         Fold: FnMut(Acc, Self::Item) -> Acc,
     {
-        FuseImpl::fold(self, acc, fold)
+        if let Some(iter) = self.iter {
+            acc = iter.fold(acc, fold);
+        }
+        acc
     }
 
     #[inline]
@@ -114,6 +128,7 @@ where
     }
 
     #[inline]
+    #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
     where
         Self: TrustedRandomAccess,
@@ -154,11 +169,14 @@ where
     }
 
     #[inline]
-    fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
+    fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
     where
         Fold: FnMut(Acc, Self::Item) -> Acc,
     {
-        FuseImpl::rfold(self, acc, fold)
+        if let Some(iter) = self.iter {
+            acc = iter.rfold(acc, fold);
+        }
+        acc
     }
 
     #[inline]
@@ -176,11 +194,17 @@ where
     I: ExactSizeIterator,
 {
     fn len(&self) -> usize {
-        FuseImpl::len(self)
+        match self.iter {
+            Some(ref iter) => iter.len(),
+            None => 0,
+        }
     }
 
     fn is_empty(&self) -> bool {
-        FuseImpl::is_empty(self)
+        match self.iter {
+            Some(ref iter) => iter.is_empty(),
+            None => true,
+        }
     }
 }
 
@@ -204,7 +228,10 @@ where
     const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
 }
 
-// Fuse specialization trait
+/// Fuse specialization trait
+///
+/// We only need to worry about `&mut self` methods, which
+/// may exhaust the iterator without consuming it.
 #[doc(hidden)]
 trait FuseImpl<I> {
     type Item;
@@ -212,17 +239,11 @@ trait FuseImpl<I> {
     // Functions specific to any normal Iterators
     fn next(&mut self) -> Option<Self::Item>;
     fn nth(&mut self, n: usize) -> Option<Self::Item>;
-    fn last(self) -> Option<Self::Item>;
-    fn count(self) -> usize;
-    fn size_hint(&self) -> (usize, Option<usize>);
     fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
         R: Try<Output = Acc>;
-    fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc;
     fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
     where
         P: FnMut(&Self::Item) -> bool;
@@ -240,25 +261,13 @@ trait FuseImpl<I> {
         Fold: FnMut(Acc, Self::Item) -> R,
         R: Try<Output = Acc>,
         I: DoubleEndedIterator;
-    fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-        I: DoubleEndedIterator;
     fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
     where
         P: FnMut(&Self::Item) -> bool,
         I: DoubleEndedIterator;
-
-    // Functions specific to ExactSizeIterator
-    fn len(&self) -> usize
-    where
-        I: ExactSizeIterator;
-    fn is_empty(&self) -> bool
-    where
-        I: ExactSizeIterator;
 }
 
-// General Fuse impl
+/// General `Fuse` impl which sets `iter = None` when exhausted.
 #[doc(hidden)]
 impl<I> FuseImpl<I> for Fuse<I>
 where
@@ -276,30 +285,6 @@ where
         fuse!(self.iter.nth(n))
     }
 
-    #[inline]
-    default fn last(self) -> Option<I::Item> {
-        match self.iter {
-            Some(iter) => iter.last(),
-            None => None,
-        }
-    }
-
-    #[inline]
-    default fn count(self) -> usize {
-        match self.iter {
-            Some(iter) => iter.count(),
-            None => 0,
-        }
-    }
-
-    #[inline]
-    default fn size_hint(&self) -> (usize, Option<usize>) {
-        match self.iter {
-            Some(ref iter) => iter.size_hint(),
-            None => (0, Some(0)),
-        }
-    }
-
     #[inline]
     default fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
     where
@@ -314,17 +299,6 @@ where
         try { acc }
     }
 
-    #[inline]
-    default fn fold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        if let Some(iter) = self.iter {
-            acc = iter.fold(acc, fold);
-        }
-        acc
-    }
-
     #[inline]
     default fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
     where
@@ -364,18 +338,6 @@ where
         try { acc }
     }
 
-    #[inline]
-    default fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-        I: DoubleEndedIterator,
-    {
-        if let Some(iter) = self.iter {
-            acc = iter.rfold(acc, fold);
-        }
-        acc
-    }
-
     #[inline]
     default fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
     where
@@ -384,30 +346,10 @@ where
     {
         fuse!(self.iter.rfind(predicate))
     }
-
-    #[inline]
-    default fn len(&self) -> usize
-    where
-        I: ExactSizeIterator,
-    {
-        match self.iter {
-            Some(ref iter) => iter.len(),
-            None => 0,
-        }
-    }
-
-    #[inline]
-    default fn is_empty(&self) -> bool
-    where
-        I: ExactSizeIterator,
-    {
-        match self.iter {
-            Some(ref iter) => iter.is_empty(),
-            None => true,
-        }
-    }
 }
 
+/// Specialized `Fuse` impl which doesn't bother clearing `iter` when exhausted.
+/// However, we must still be prepared for the possibility that it was already cleared!
 #[doc(hidden)]
 impl<I> FuseImpl<I> for Fuse<I>
 where
@@ -415,45 +357,25 @@ where
 {
     #[inline]
     fn next(&mut self) -> Option<<I as Iterator>::Item> {
-        unchecked!(self).next()
+        spec!(self.iter.next())
     }
 
     #[inline]
     fn nth(&mut self, n: usize) -> Option<I::Item> {
-        unchecked!(self).nth(n)
-    }
-
-    #[inline]
-    fn last(self) -> Option<I::Item> {
-        unchecked!(self).last()
+        spec!(self.iter.nth(n))
     }
 
     #[inline]
-    fn count(self) -> usize {
-        unchecked!(self).count()
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        unchecked!(self).size_hint()
-    }
-
-    #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
         R: Try<Output = Acc>,
     {
-        unchecked!(self).try_fold(init, fold)
-    }
-
-    #[inline]
-    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        unchecked!(self).fold(init, fold)
+        if let Some(ref mut iter) = self.iter {
+            acc = iter.try_fold(acc, fold)?;
+        }
+        try { acc }
     }
 
     #[inline]
@@ -461,7 +383,7 @@ where
     where
         P: FnMut(&Self::Item) -> bool,
     {
-        unchecked!(self).find(predicate)
+        spec!(self.iter.find(predicate))
     }
 
     #[inline]
@@ -469,7 +391,7 @@ where
     where
         I: DoubleEndedIterator,
     {
-        unchecked!(self).next_back()
+        spec!(self.iter.next_back())
     }
 
     #[inline]
@@ -477,27 +399,21 @@ where
     where
         I: DoubleEndedIterator,
     {
-        unchecked!(self).nth_back(n)
+        spec!(self.iter.nth_back(n))
     }
 
     #[inline]
-    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    fn try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
         R: Try<Output = Acc>,
         I: DoubleEndedIterator,
     {
-        unchecked!(self).try_rfold(init, fold)
-    }
-
-    #[inline]
-    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-        I: DoubleEndedIterator,
-    {
-        unchecked!(self).rfold(init, fold)
+        if let Some(ref mut iter) = self.iter {
+            acc = iter.try_rfold(acc, fold)?;
+        }
+        try { acc }
     }
 
     #[inline]
@@ -506,43 +422,6 @@ where
         P: FnMut(&Self::Item) -> bool,
         I: DoubleEndedIterator,
     {
-        unchecked!(self).rfind(predicate)
-    }
-
-    #[inline]
-    fn len(&self) -> usize
-    where
-        I: ExactSizeIterator,
-    {
-        unchecked!(self).len()
-    }
-
-    #[inline]
-    fn is_empty(&self) -> bool
-    where
-        I: ExactSizeIterator,
-    {
-        unchecked!(self).is_empty()
+        spec!(self.iter.rfind(predicate))
     }
 }
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<S: Iterator, I: FusedIterator> SourceIter for Fuse<I>
-where
-    I: SourceIter<Source = S>,
-{
-    type Source = S;
-
-    #[inline]
-    unsafe fn as_inner(&mut self) -> &mut S {
-        match self.iter {
-            // SAFETY: unsafe function forwarding to unsafe function with the same requirements
-            Some(ref mut iter) => unsafe { SourceIter::as_inner(iter) },
-            // SAFETY: the specialized iterator never sets `None`
-            None => unsafe { intrinsics::unreachable() },
-        }
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: InPlaceIterable> InPlaceIterable for Fuse<I> {}
index 0bf9f4b0327e969cb16225a842e61ad1a3ad9b39..dc86eccfcb82f36c700936a058823a59265c15a3 100644 (file)
@@ -122,6 +122,7 @@ where
         self.iter.fold(init, map_fold(self.f, g))
     }
 
+    #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> B
     where
         Self: TrustedRandomAccess,
index 9fdd4fca04c97fd0610d31d1eaf0b8d712f49036..a3fbf4d9c38d8ceddbecd69773339ae3988f065d 100644 (file)
@@ -54,7 +54,7 @@ pub use self::zip::TrustedRandomAccess;
 #[unstable(feature = "iter_zip", issue = "83574")]
 pub use self::zip::zip;
 
-/// This trait provides transitive access to source-stage in an interator-adapter pipeline
+/// This trait provides transitive access to source-stage in an iterator-adapter pipeline
 /// under the conditions that
 /// * the iterator source `S` itself implements `SourceIter<Source = S>`
 /// * there is a delegating implementation of this trait for each adapter in the pipeline between
index 69bd2996efe73df9abc8747ad3d0602264d18fa0..91fa1a9ad351c07d7a57a50f2f166850bd1f0138 100644 (file)
@@ -130,7 +130,6 @@ where
     }
 
     #[inline]
-    #[cfg(not(bootstrap))]
     fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
     where
         Self: Sized,
@@ -150,28 +149,6 @@ where
         }
     }
 
-    #[inline]
-    #[cfg(bootstrap)]
-    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
-    where
-        Self: Sized,
-        F: FnMut(B, Self::Item) -> R,
-        R: Try<Output = B>,
-    {
-        let _use_the_import: ControlFlow<()>;
-        match self.peeked.take() {
-            Some(None) => try { init },
-            Some(Some(v)) => match self.iter.try_rfold(init, &mut f).into_result() {
-                Ok(acc) => f(acc, v),
-                Err(e) => {
-                    self.peeked = Some(Some(v));
-                    R::from_error(e)
-                }
-            },
-            None => self.iter.try_rfold(init, f),
-        }
-    }
-
     #[inline]
     fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
     where
index c95324c80ba61e14243b3fc59e8ed6c5fc2ca605..3d0401cbebcf72a0fa0ec3a45f3f891897cb0215 100644 (file)
@@ -88,6 +88,7 @@ where
     }
 
     #[inline]
+    #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
     where
         Self: TrustedRandomAccess,
@@ -226,6 +227,8 @@ where
     fn next(&mut self) -> Option<(A::Item, B::Item)> {
         if self.index < self.len {
             let i = self.index;
+            // since get_unchecked executes code which can panic we increment the counters beforehand
+            // so that the same index won't be accessed twice, as required by TrustedRandomAccess
             self.index += 1;
             // SAFETY: `i` is smaller than `self.len`, thus smaller than `self.a.len()` and `self.b.len()`
             unsafe {
@@ -233,6 +236,7 @@ where
             }
         } else if A::MAY_HAVE_SIDE_EFFECT && self.index < self.a_len {
             let i = self.index;
+            // as above, increment before executing code that may panic
             self.index += 1;
             self.len += 1;
             // match the base implementation's potential side effects
@@ -258,6 +262,8 @@ where
         let end = self.index + delta;
         while self.index < end {
             let i = self.index;
+            // since get_unchecked executes code which can panic we increment the counters beforehand
+            // so that the same index won't be accessed twice, as required by TrustedRandomAccess
             self.index += 1;
             if A::MAY_HAVE_SIDE_EFFECT {
                 // SAFETY: the usage of `cmp::min` to calculate `delta`
@@ -294,9 +300,12 @@ where
                 let sz_a = self.a.size();
                 if A::MAY_HAVE_SIDE_EFFECT && sz_a > self.len {
                     for _ in 0..sz_a - self.len {
+                        // since next_back() may panic we increment the counters beforehand
+                        // to keep Zip's state in sync with the underlying iterator source
+                        self.a_len -= 1;
                         self.a.next_back();
                     }
-                    self.a_len = self.len;
+                    debug_assert_eq!(self.a_len, self.len);
                 }
                 let sz_b = self.b.size();
                 if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len {
@@ -307,6 +316,8 @@ where
             }
         }
         if self.index < self.len {
+            // since get_unchecked executes code which can panic we increment the counters beforehand
+            // so that the same index won't be accessed twice, as required by TrustedRandomAccess
             self.len -= 1;
             self.a_len -= 1;
             let i = self.len;
index de5d77e96ee568b98be6e79864600d47ae7147ab..b9387ef49e5fb211ab343869a8a534c3c262f487 100644 (file)
@@ -30,7 +30,7 @@ pub trait Step: Clone + PartialOrd + Sized {
     /// For any `a`, `b`, and `n`:
     ///
     /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::forward_checked(&a, n) == Some(b)`
-    /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::backward_checked(&a, n) == Some(a)`
+    /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::backward_checked(&b, n) == Some(a)`
     /// * `steps_between(&a, &b) == Some(n)` only if `a <= b`
     ///   * Corollary: `steps_between(&a, &b) == Some(0)` if and only if `a == b`
     ///   * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != None`;
@@ -667,6 +667,7 @@ impl<A: Step> Iterator for ops::Range<A> {
     }
 
     #[inline]
+    #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
     where
         Self: TrustedRandomAccess,
index a9478041c69c47f9783eebb8ebf8498d0714eea2..733142ed01103ce3e41806d56fecf1561a03d00a 100644 (file)
@@ -51,6 +51,7 @@ use crate::iter::{FusedIterator, TrustedLen};
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "iter_repeat")]
 pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
     Repeat { element: elt }
 }
index 0a4210a78e3af8a35b45f921392b1ab79394ff5e..c2e837df5ff2a138b03be1d039a52b692a4820bb 100644 (file)
@@ -3,12 +3,11 @@ use crate::num::Wrapping;
 
 /// Trait to represent types that can be created by summing up an iterator.
 ///
-/// This trait is used to implement the [`sum()`] method on iterators. Types which
-/// implement the trait can be generated by the [`sum()`] method. Like
-/// [`FromIterator`] this trait should rarely be called directly and instead
-/// interacted with through [`Iterator::sum()`].
+/// This trait is used to implement [`Iterator::sum()`]. Types which implement
+/// this trait can be generated by using the [`sum()`] method on an iterator.
+/// Like [`FromIterator`], this trait should rarely be called directly.
 ///
-/// [`sum()`]: Sum::sum
+/// [`sum()`]: Iterator::sum
 /// [`FromIterator`]: iter::FromIterator
 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
 pub trait Sum<A = Self>: Sized {
@@ -21,12 +20,11 @@ pub trait Sum<A = Self>: Sized {
 /// Trait to represent types that can be created by multiplying elements of an
 /// iterator.
 ///
-/// This trait is used to implement the [`product()`] method on iterators. Types
-/// which implement the trait can be generated by the [`product()`] method. Like
-/// [`FromIterator`] this trait should rarely be called directly and instead
-/// interacted with through [`Iterator::product()`].
+/// This trait is used to implement [`Iterator::product()`]. Types which implement
+/// this trait can be generated by using the [`product()`] method on an iterator.
+/// Like [`FromIterator`], this trait should rarely be called directly.
 ///
-/// [`product()`]: Product::product
+/// [`product()`]: Iterator::product
 /// [`FromIterator`]: iter::FromIterator
 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
 pub trait Product<A = Self>: Sized {
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 c302502b3b7e6473b64b65ee2ed956550d9e5ae3..9a9cf20077096d4e50cc70664d89de32fa960aed 100644 (file)
@@ -36,6 +36,7 @@ use crate::ops::{ControlFlow, Try};
 /// assert_eq!(None, iter.next_back());
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "DoubleEndedIterator")]
 pub trait DoubleEndedIterator: Iterator {
     /// Removes and returns an element from the end of the iterator.
     ///
@@ -248,6 +249,11 @@ pub trait DoubleEndedIterator: Iterator {
     /// Folding is useful whenever you have a collection of something, and want
     /// to produce a single value from it.
     ///
+    /// Note: `rfold()` combines elements in a *right-associative* fashion. For associative
+    /// operators like `+`, the order the elements are combined in is not important, but for non-associative
+    /// operators like `-` the order will affect the final result.
+    /// For a *left-associative* version of `rfold()`, see [`Iterator::fold()`].
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -262,7 +268,8 @@ pub trait DoubleEndedIterator: Iterator {
     /// assert_eq!(sum, 6);
     /// ```
     ///
-    /// This example builds a string, starting with an initial value
+    /// This example demonstrates the right-associative nature of `rfold()`:
+    /// it builds a string, starting with an initial value
     /// and continuing with each element from the back until the front:
     ///
     /// ```
@@ -276,6 +283,7 @@ pub trait DoubleEndedIterator: Iterator {
     ///
     /// assert_eq!(result, "(1 + (2 + (3 + (4 + (5 + 0)))))");
     /// ```
+    #[doc(alias = "foldr")]
     #[inline]
     #[stable(feature = "iter_rfold", since = "1.27.0")]
     fn rfold<B, F>(mut self, init: B, mut f: F) -> B
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 11dea400a46ef6d8fa59fc8f669de85fab4901bf..16efd2f0eaff954adb1b2cf94a78b4eba725c051 100644 (file)
@@ -333,21 +333,22 @@ pub trait Iterator {
     /// regardless of the step given.
     ///
     /// Note 2: The time at which ignored elements are pulled is not fixed.
-    /// `StepBy` behaves like the sequence `next(), nth(step-1), nth(step-1), …`,
-    /// but is also free to behave like the sequence
-    /// `advance_n_and_return_first(step), advance_n_and_return_first(step), …`
+    /// `StepBy` behaves like the sequence `self.next()`, `self.nth(step-1)`,
+    /// `self.nth(step-1)`, …, but is also free to behave like the sequence
+    /// `advance_n_and_return_first(&mut self, step)`,
+    /// `advance_n_and_return_first(&mut self, step)`, …
     /// Which way is used may change for some iterators for performance reasons.
     /// The second way will advance the iterator earlier and may consume more items.
     ///
     /// `advance_n_and_return_first` is the equivalent of:
     /// ```
-    /// fn advance_n_and_return_first<I>(iter: &mut I, total_step: usize) -> Option<I::Item>
+    /// fn advance_n_and_return_first<I>(iter: &mut I, n: usize) -> Option<I::Item>
     /// where
     ///     I: Iterator,
     /// {
     ///     let next = iter.next();
-    ///     if total_step > 1 {
-    ///         iter.nth(total_step-2);
+    ///     if n > 1 {
+    ///         iter.nth(n - 2);
     ///     }
     ///     next
     /// }
@@ -1959,6 +1960,31 @@ pub trait Iterator {
     /// assert_eq!(it.len(), 2);
     /// assert_eq!(it.next(), Some(&40));
     /// ```
+    ///
+    /// While you cannot `break` from a closure, the [`crate::ops::ControlFlow`]
+    /// type allows a similar idea:
+    ///
+    /// ```
+    /// use std::ops::ControlFlow;
+    ///
+    /// let triangular = (1..30).try_fold(0_i8, |prev, x| {
+    ///     if let Some(next) = prev.checked_add(x) {
+    ///         ControlFlow::Continue(next)
+    ///     } else {
+    ///         ControlFlow::Break(prev)
+    ///     }
+    /// });
+    /// assert_eq!(triangular, ControlFlow::Break(120));
+    ///
+    /// let triangular = (1..30).try_fold(0_u64, |prev, x| {
+    ///     if let Some(next) = prev.checked_add(x) {
+    ///         ControlFlow::Continue(next)
+    ///     } else {
+    ///         ControlFlow::Break(prev)
+    ///     }
+    /// });
+    /// assert_eq!(triangular, ControlFlow::Continue(435));
+    /// ```
     #[inline]
     #[stable(feature = "iterator_try_fold", since = "1.27.0")]
     fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
@@ -2001,6 +2027,22 @@ pub trait Iterator {
     /// // It short-circuited, so the remaining items are still in the iterator:
     /// assert_eq!(it.next(), Some("stale_bread.json"));
     /// ```
+    ///
+    /// The [`crate::ops::ControlFlow`] type can be used with this method for the
+    /// situations in which you'd use `break` and `continue` in a normal loop:
+    ///
+    /// ```
+    /// use std::ops::ControlFlow;
+    ///
+    /// let r = (2..100).try_for_each(|x| {
+    ///     if 323 % x == 0 {
+    ///         return ControlFlow::Break(x)
+    ///     }
+    ///
+    ///     ControlFlow::Continue(())
+    /// });
+    /// assert_eq!(r, ControlFlow::Break(17));
+    /// ```
     #[inline]
     #[stable(feature = "iterator_try_fold", since = "1.27.0")]
     fn try_for_each<F, R>(&mut self, f: F) -> R
@@ -2042,6 +2084,11 @@ pub trait Iterator {
     /// Note: [`reduce()`] can be used to use the first element as the initial
     /// value, if the accumulator type and item type is the same.
     ///
+    /// Note: `fold()` combines elements in a *left-associative* fashion. For associative
+    /// operators like `+`, the order the elements are combined in is not important, but for non-associative
+    /// operators like `-` the order will affect the final result.
+    /// For a *right-associative* version of `fold()`, see [`DoubleEndedIterator::rfold()`].
+    ///
     /// # Note to Implementors
     ///
     /// Several of the other (forward) methods have default implementations in
@@ -2075,6 +2122,21 @@ pub trait Iterator {
     ///
     /// And so, our final result, `6`.
     ///
+    /// This example demonstrates the left-associative nature of `fold()`:
+    /// it builds a string, starting with an initial value
+    /// and continuing with each element from the front until the back:
+    ///
+    /// ```
+    /// let numbers = [1, 2, 3, 4, 5];
+    ///
+    /// let zero = "0".to_string();
+    ///
+    /// let result = numbers.iter().fold(zero, |acc, &x| {
+    ///     format!("({} + {})", acc, x)
+    /// });
+    ///
+    /// assert_eq!(result, "(((((0 + 1) + 2) + 3) + 4) + 5)");
+    /// ```
     /// It's common for people who haven't used iterators a lot to
     /// use a `for` loop with a list of things to build up a result. Those
     /// can be turned into `fold()`s:
@@ -2099,7 +2161,7 @@ pub trait Iterator {
     /// ```
     ///
     /// [`reduce()`]: Iterator::reduce
-    #[doc(alias = "inject")]
+    #[doc(alias = "inject", alias = "foldl")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn fold<B, F>(mut self, init: B, mut f: F) -> B
@@ -2193,7 +2255,6 @@ pub trait Iterator {
     /// // 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
@@ -2378,7 +2439,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[unstable(feature = "try_find", reason = "new API", issue = "63178")]
-    #[cfg(not(bootstrap))]
     fn try_find<F, R, E>(&mut self, f: F) -> Result<Option<Self::Item>, E>
     where
         Self: Sized,
@@ -2405,32 +2465,6 @@ pub trait Iterator {
         self.try_fold((), check(f)).break_value().transpose()
     }
 
-    /// We're bootstrapping.
-    #[inline]
-    #[unstable(feature = "try_find", reason = "new API", issue = "63178")]
-    #[cfg(bootstrap)]
-    fn try_find<F, R>(&mut self, f: F) -> Result<Option<Self::Item>, R::Error>
-    where
-        Self: Sized,
-        F: FnMut(&Self::Item) -> R,
-        R: Try<Output = bool>,
-    {
-        #[inline]
-        fn check<F, T, R>(mut f: F) -> impl FnMut((), T) -> ControlFlow<Result<T, R::Error>>
-        where
-            F: FnMut(&T) -> R,
-            R: Try<Output = bool>,
-        {
-            move |(), x| match f(&x).into_result() {
-                Ok(false) => ControlFlow::CONTINUE,
-                Ok(true) => ControlFlow::Break(Ok(x)),
-                Err(x) => ControlFlow::Break(Err(x)),
-            }
-        }
-
-        self.try_fold((), check(f)).break_value().transpose()
-    }
-
     /// Searches for an element in an iterator, returning its index.
     ///
     /// `position()` takes a closure that returns `true` or `false`. It applies
index 0bb0f8768a0efc6e267b28b272cb2507ad8cfed0..6d87a7ab055c2daafb22330291bd342053d776eb 100644 (file)
 //
 // This cfg won't affect doc tests.
 #![cfg(not(test))]
+// To run libcore tests without x.py without ending up with two copies of libcore, Miri needs to be
+// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
+// rustc itself never sets the feature, so this line has no affect there.
+#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
 #![stable(feature = "core", since = "1.6.0")]
 #![doc(
     html_playground_url = "https://play.rust-lang.org/",
@@ -87,7 +91,6 @@
 #![feature(const_fn_floating_point_arithmetic)]
 #![feature(const_fn_fn_ptr_basics)]
 #![feature(const_fn_trait_bound)]
-#![cfg_attr(bootstrap, feature(const_fn))]
 #![feature(const_option)]
 #![feature(const_precise_live_drops)]
 #![feature(const_ptr_offset)]
 #![feature(doc_cfg)]
 #![feature(doc_notable_trait)]
 #![feature(duration_consts_2)]
-#![cfg_attr(bootstrap, feature(extended_key_value_attributes))]
 #![feature(extern_types)]
 #![feature(fundamental)]
 #![feature(intra_doc_pointers)]
 #![feature(slice_ptr_get)]
 #![feature(no_niche)] // rust-lang/rust#68303
 #![feature(no_coverage)] // rust-lang/rust#84605
-#![feature(int_error_matching)]
-#![cfg_attr(bootstrap, feature(target_feature_11))]
 #![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)]
@@ -269,7 +270,6 @@ pub mod option;
 pub mod panic;
 pub mod panicking;
 pub mod pin;
-pub mod raw;
 pub mod result;
 #[unstable(feature = "async_stream", issue = "79024")]
 pub mod stream;
@@ -320,5 +320,35 @@ pub mod primitive;
 #[unstable(feature = "stdsimd", issue = "48556")]
 mod core_arch;
 
+#[doc = include_str!("../../stdarch/crates/core_arch/src/core_arch_docs.md")]
 #[stable(feature = "simd_arch", since = "1.27.0")]
-pub use core_arch::arch;
+pub mod arch {
+    #[stable(feature = "simd_arch", since = "1.27.0")]
+    pub use crate::core_arch::arch::*;
+
+    /// Inline assembly.
+    ///
+    /// Read the [unstable book] for the usage.
+    ///
+    /// [unstable book]: ../../unstable-book/library-features/asm.html
+    #[unstable(
+        feature = "asm",
+        issue = "72016",
+        reason = "inline assembly is not stable enough for use and is subject to change"
+    )]
+    #[rustc_builtin_macro]
+    pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) {
+        /* compiler built-in */
+    }
+
+    /// Module-level inline assembly.
+    #[unstable(
+        feature = "global_asm",
+        issue = "35119",
+        reason = "`global_asm!` is not stable enough for use and is subject to change"
+    )]
+    #[rustc_builtin_macro]
+    pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) {
+        /* compiler built-in */
+    }
+}
index 1a3c088e922a0813d79e915a974e0a79162d471b..3ca8f27c79ab7f60b11610cdb50595a1b64e2efa 100644 (file)
@@ -1,6 +1,7 @@
 #[doc = include_str!("panic.md")]
 #[macro_export]
-#[rustc_builtin_macro = "core_panic"]
+#[cfg_attr(bootstrap, rustc_builtin_macro = "core_panic")]
+#[cfg_attr(not(bootstrap), rustc_builtin_macro(core_panic))]
 #[allow_internal_unstable(edition_panic)]
 #[stable(feature = "core", since = "1.6.0")]
 #[rustc_diagnostic_item = "core_panic_macro"]
@@ -1311,27 +1312,6 @@ pub(crate) mod builtin {
         ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};
     }
 
-    /// Inline assembly.
-    ///
-    /// Read the [unstable book] for the usage.
-    ///
-    /// [unstable book]: ../unstable-book/library-features/asm.html
-    #[unstable(
-        feature = "asm",
-        issue = "72016",
-        reason = "inline assembly is not stable enough for use and is subject to change"
-    )]
-    #[rustc_builtin_macro]
-    #[macro_export]
-    macro_rules! asm {
-        ("assembly template",
-            $(operands,)*
-            $(options($(option),*))?
-        ) => {
-            /* compiler built-in */
-        };
-    }
-
     /// LLVM-style inline assembly.
     ///
     /// Read the [unstable book] for the usage.
@@ -1354,23 +1334,6 @@ pub(crate) mod builtin {
         };
     }
 
-    /// Module-level inline assembly.
-    #[unstable(
-        feature = "global_asm",
-        issue = "35119",
-        reason = "`global_asm!` is not stable enough for use and is subject to change"
-    )]
-    #[rustc_builtin_macro]
-    #[macro_export]
-    macro_rules! global_asm {
-        ("assembly template",
-            $(operands,)*
-            $(options($(option),*))?
-        ) => {
-            /* compiler built-in */
-        };
-    }
-
     /// Prints passed tokens into the standard output.
     #[unstable(
         feature = "log_syntax",
index 2b2404550433ddb6bb9eca9a1ff20d61885e5e35..fb957348bebd3837dbfc60d43efa5c389fb7fb2b 100644 (file)
@@ -31,7 +31,6 @@ use crate::hash::Hasher;
 /// [ub]: ../../reference/behavior-considered-undefined.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "send_trait")]
-#[cfg_attr(not(bootstrap), lang = "send")]
 #[rustc_on_unimplemented(
     message = "`{Self}` cannot be sent between threads safely",
     label = "`{Self}` cannot be sent between threads safely"
index 10219201a40d33131b0c6831958cfbb8fd5f4e75..5122421ea8c852fdef7afbbba7c3f58075f49a0f 100644 (file)
@@ -79,7 +79,7 @@ use crate::ptr;
 /// // 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() };
@@ -135,7 +135,7 @@ use crate::ptr;
 ///     // 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
@@ -161,7 +161,7 @@ use crate::ptr;
 /// 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;
 /// }
 ///
@@ -402,12 +402,90 @@ impl<T> MaybeUninit<T> {
         u
     }
 
-    /// Sets the value of the `MaybeUninit<T>`. This overwrites any previous value
-    /// without dropping it, so be careful not to use this twice unless you want to
-    /// skip running the destructor. For your convenience, this also returns a mutable
-    /// reference to the (now safely initialized) contents of `self`.
-    #[unstable(feature = "maybe_uninit_extra", issue = "63567")]
-    #[rustc_const_unstable(feature = "maybe_uninit_extra", issue = "63567")]
+    /// Sets the value of the `MaybeUninit<T>`.
+    ///
+    /// This overwrites any previous value without dropping it, so be careful
+    /// not to use this twice unless you want to skip running the destructor.
+    /// For your convenience, this also returns a mutable reference to the
+    /// (now safely initialized) contents of `self`.
+    ///
+    /// As the content is stored inside a `MaybeUninit`, the destructor is not
+    /// 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
+    /// usually still undesirable. This being said, the mutable reference
+    /// behaves like any other mutable reference would, so assigning a new value
+    /// to it will drop the old content.
+    ///
+    /// [`assume_init`]: Self::assume_init
+    /// [`assume_init_drop`]: Self::assume_init_drop
+    ///
+    /// # Examples
+    ///
+    /// Correct usage of this method:
+    ///
+    /// ```rust
+    /// use std::mem::MaybeUninit;
+    ///
+    /// let mut x = MaybeUninit::<Vec<u8>>::uninit();
+    ///
+    /// {
+    ///     let hello = x.write((&b"Hello, world!").to_vec());
+    ///     // Setting hello does not leak prior allocations, but drops them
+    ///     *hello = (&b"Hello").to_vec();
+    ///     hello[0] = 'h' as u8;
+    /// }
+    /// // x is initialized now:
+    /// let s = unsafe { x.assume_init() };
+    /// assert_eq!(b"hello", s.as_slice());
+    /// ```
+    ///
+    /// This usage of the method causes a leak:
+    ///
+    /// ```rust
+    /// use std::mem::MaybeUninit;
+    ///
+    /// let mut x = MaybeUninit::<String>::uninit();
+    ///
+    /// x.write("Hello".to_string());
+    /// // This leaks the contained string:
+    /// x.write("hello".to_string());
+    /// // x is initialized now:
+    /// let s = unsafe { x.assume_init() };
+    /// ```
+    ///
+    /// 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);
@@ -428,7 +506,7 @@ impl<T> MaybeUninit<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);
@@ -465,7 +543,7 @@ impl<T> MaybeUninit<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() };
@@ -524,7 +602,7 @@ impl<T> MaybeUninit<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);
     /// ```
@@ -564,9 +642,11 @@ impl<T> MaybeUninit<T> {
     /// behavior. The [type-level documentation][inv] contains more information about
     /// this initialization invariant.
     ///
-    /// Moreover, this leaves a copy of the same data behind in the `MaybeUninit<T>`. When using
-    /// multiple copies of the data (by calling `assume_init_read` multiple times, or first
-    /// calling `assume_init_read` and then [`assume_init`]), it is your responsibility
+    /// Moreover, similar to the [`ptr::read`] function, this function creates a
+    /// bitwise copy of the contents, regardless whether the contained type
+    /// implements the [`Copy`] trait or not. When using multiple copies of the
+    /// data (by calling `assume_init_read` multiple times, or first calling
+    /// `assume_init_read` and then [`assume_init`]), it is your responsibility
     /// to ensure that that data may indeed be duplicated.
     ///
     /// [inv]: #initialization-invariant
@@ -622,7 +702,8 @@ impl<T> MaybeUninit<T> {
 
     /// Drops the contained value in place.
     ///
-    /// If you have ownership of the `MaybeUninit`, you can use [`assume_init`] instead.
+    /// If you have ownership of the `MaybeUninit`, you can also use
+    /// [`assume_init`] as an alternative.
     ///
     /// # Safety
     ///
@@ -632,11 +713,12 @@ impl<T> MaybeUninit<T> {
     ///
     /// On top of that, all additional invariants of the type `T` must be
     /// satisfied, as the `Drop` implementation of `T` (or its members) may
-    /// rely on this. For example, a `1`-initialized [`Vec<T>`] is considered
-    /// initialized (under the current implementation; this does not constitute
-    /// a stable guarantee) because the only requirement the compiler knows
-    /// about it is that the data pointer must be non-null. Dropping such a
-    /// `Vec<T>` however will cause undefined behaviour.
+    /// rely on this. For example, setting a [`Vec<T>`] to an invalid but
+    /// non-null address makes it initialized (under the current implementation;
+    /// this does not constitute a stable guarantee), because the only
+    /// requirement the compiler knows about it is that the data pointer must be
+    /// non-null. Dropping such a `Vec<T>` however will cause undefined
+    /// behaviour.
     ///
     /// [`assume_init`]: MaybeUninit::assume_init
     /// [`Vec<T>`]: ../../std/vec/struct.Vec.html
@@ -665,12 +747,11 @@ impl<T> MaybeUninit<T> {
     /// ### Correct usage of this method:
     ///
     /// ```rust
-    /// #![feature(maybe_uninit_ref)]
     /// use std::mem::MaybeUninit;
     ///
     /// 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 {
@@ -683,7 +764,6 @@ impl<T> MaybeUninit<T> {
     /// ### *Incorrect* usages of this method:
     ///
     /// ```rust,no_run
-    /// #![feature(maybe_uninit_ref)]
     /// use std::mem::MaybeUninit;
     ///
     /// let x = MaybeUninit::<Vec<u32>>::uninit();
@@ -692,7 +772,6 @@ impl<T> MaybeUninit<T> {
     /// ```
     ///
     /// ```rust,no_run
-    /// #![feature(maybe_uninit_ref)]
     /// use std::{cell::Cell, mem::MaybeUninit};
     ///
     /// let b = MaybeUninit::<Cell<bool>>::uninit();
@@ -703,7 +782,7 @@ impl<T> MaybeUninit<T> {
     ///    // Reference to an uninitialized `Cell<bool>`: UB!
     /// }
     /// ```
-    #[unstable(feature = "maybe_uninit_ref", issue = "63568")]
+    #[stable(feature = "maybe_uninit_ref", since = "1.55.0")]
     #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")]
     #[inline(always)]
     pub const unsafe fn assume_init_ref(&self) -> &T {
@@ -733,7 +812,6 @@ impl<T> MaybeUninit<T> {
     /// ### Correct usage of this method:
     ///
     /// ```rust
-    /// #![feature(maybe_uninit_ref)]
     /// use std::mem::MaybeUninit;
     ///
     /// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 1024]) { *buf = [0; 1024] }
@@ -769,7 +847,6 @@ impl<T> MaybeUninit<T> {
     /// You cannot use `.assume_init_mut()` to initialize a value:
     ///
     /// ```rust,no_run
-    /// #![feature(maybe_uninit_ref)]
     /// use std::mem::MaybeUninit;
     ///
     /// let mut b = MaybeUninit::<bool>::uninit();
@@ -785,7 +862,6 @@ impl<T> MaybeUninit<T> {
     /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
     ///
     /// ```rust,no_run
-    /// #![feature(maybe_uninit_ref)]
     /// use std::{io, mem::MaybeUninit};
     ///
     /// fn read_chunk (reader: &'_ mut dyn io::Read) -> io::Result<[u8; 64]>
@@ -802,7 +878,6 @@ impl<T> MaybeUninit<T> {
     /// Nor can you use direct field access to do field-by-field gradual initialization:
     ///
     /// ```rust,no_run
-    /// #![feature(maybe_uninit_ref)]
     /// use std::{mem::MaybeUninit, ptr};
     ///
     /// struct Foo {
@@ -823,10 +898,7 @@ impl<T> MaybeUninit<T> {
     ///     foo.assume_init()
     /// };
     /// ```
-    // FIXME(#76092): We currently rely on the above being incorrect, i.e., we have references
-    // to uninitialized data (e.g., in `libcore/fmt/float.rs`).  We should make
-    // a final decision about the rules before stabilization.
-    #[unstable(feature = "maybe_uninit_ref", issue = "63568")]
+    #[stable(feature = "maybe_uninit_ref", since = "1.55.0")]
     #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")]
     #[inline(always)]
     pub const unsafe fn assume_init_mut(&mut self) -> &mut T {
@@ -853,9 +925,9 @@ impl<T> MaybeUninit<T> {
     /// 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 {
@@ -936,7 +1008,7 @@ impl<T> MaybeUninit<T> {
         this.as_mut_ptr() as *mut T
     }
 
-    /// Copies the elements from `src` to `this`, returning a mutable reference to the now initalized contents of `this`.
+    /// Copies the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`.
     ///
     /// If `T` does not implement `Copy`, use [`write_slice_cloned`]
     ///
@@ -989,12 +1061,12 @@ impl<T> MaybeUninit<T> {
 
         this.copy_from_slice(uninit_src);
 
-        // SAFETY: Valid elements have just been copied into `this` so it is initalized
+        // SAFETY: Valid elements have just been copied into `this` so it is initialized
         unsafe { MaybeUninit::slice_assume_init_mut(this) }
     }
 
-    /// Clones the elements from `src` to `this`, returning a mutable reference to the now initalized contents of `this`.
-    /// Any already initalized elements will not be dropped.
+    /// Clones the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`.
+    /// Any already initialized elements will not be dropped.
     ///
     /// If `T` implements `Copy`, use [`write_slice`]
     ///
@@ -1080,7 +1152,7 @@ impl<T> MaybeUninit<T> {
 
         super::forget(guard);
 
-        // SAFETY: Valid elements have just been written into `this` so it is initalized
+        // SAFETY: Valid elements have just been written into `this` so it is initialized
         unsafe { MaybeUninit::slice_assume_init_mut(this) }
     }
 }
index c6750c52d16c8616508247fc0a5f14cd2f9eb5ce..2c75de39ffa2fc3644cdf479786903e046788f7a 100644 (file)
@@ -140,6 +140,7 @@ pub use crate::intrinsics::transmute;
 #[inline]
 #[rustc_const_stable(feature = "const_forget", since = "1.46.0")]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "mem_forget")]
 pub const fn forget<T>(t: T) {
     let _ = ManuallyDrop::new(t);
 }
@@ -298,6 +299,7 @@ pub fn forget_unsized<T: ?Sized>(t: T) {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_promotable]
 #[rustc_const_stable(feature = "const_size_of", since = "1.24.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of")]
 pub const fn size_of<T>() -> usize {
     intrinsics::size_of::<T>()
 }
@@ -324,6 +326,7 @@ pub const fn size_of<T>() -> usize {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of_val")]
 pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
     // SAFETY: `val` is a reference, so it's a valid raw pointer
     unsafe { intrinsics::size_of_val(val) }
@@ -682,7 +685,8 @@ pub unsafe fn uninitialized<T>() -> T {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn swap<T>(x: &mut T, y: &mut T) {
+#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
+pub const fn swap<T>(x: &mut T, y: &mut T) {
     // SAFETY: the raw pointers have been created from safe mutable references satisfying all the
     // constraints on `ptr::swap_nonoverlapping_one`
     unsafe {
@@ -812,7 +816,9 @@ pub fn take<T: Default>(dest: &mut T) -> T {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[must_use = "if you don't need the old value, you can just assign the new value directly"]
-pub fn replace<T>(dest: &mut T, src: T) -> T {
+#[rustc_const_unstable(feature = "const_replace", issue = "83164")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")]
+pub const fn replace<T>(dest: &mut T, src: T) -> T {
     // SAFETY: We read from `dest` but directly write `src` into it afterwards,
     // such that the old value is not duplicated. Nothing is dropped and
     // nothing here can panic.
@@ -886,6 +892,7 @@ pub fn replace<T>(dest: &mut T, src: T) -> T {
 /// [`RefCell`]: crate::cell::RefCell
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "mem_drop")]
 pub fn drop<T>(_x: T) {}
 
 /// Interprets `src` as having type `&U`, and then reads `src` without moving
@@ -1013,6 +1020,7 @@ impl<T> fmt::Debug for Discriminant<T> {
 /// ```
 #[stable(feature = "discriminant_value", since = "1.21.0")]
 #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "mem_discriminant")]
 pub const fn discriminant<T>(v: &T) -> Discriminant<T> {
     Discriminant(intrinsics::discriminant_value(v))
 }
diff --git a/library/core/src/num/dec2flt/algorithm.rs b/library/core/src/num/dec2flt/algorithm.rs
deleted file mode 100644 (file)
index 313b687..0000000
+++ /dev/null
@@ -1,429 +0,0 @@
-//! The various algorithms from the paper.
-
-use crate::cmp::min;
-use crate::cmp::Ordering::{Equal, Greater, Less};
-use crate::num::dec2flt::num::{self, Big};
-use crate::num::dec2flt::rawfp::{self, fp_to_float, next_float, prev_float, RawFloat, Unpacked};
-use crate::num::dec2flt::table;
-use crate::num::diy_float::Fp;
-
-/// Number of significand bits in Fp
-const P: u32 = 64;
-
-// We simply store the best approximation for *all* exponents, so the variable "h" and the
-// associated conditions can be omitted. This trades performance for a couple kilobytes of space.
-
-fn power_of_ten(e: i16) -> Fp {
-    assert!(e >= table::MIN_E);
-    let i = e - table::MIN_E;
-    let sig = table::POWERS.0[i as usize];
-    let exp = table::POWERS.1[i as usize];
-    Fp { f: sig, e: exp }
-}
-
-// In most architectures, floating point operations have an explicit bit size, therefore the
-// precision of the computation is determined on a per-operation basis.
-#[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))]
-mod fpu_precision {
-    pub fn set_precision<T>() {}
-}
-
-// On x86, the x87 FPU is used for float operations if the SSE/SSE2 extensions are not available.
-// The x87 FPU operates with 80 bits of precision by default, which means that operations will
-// round to 80 bits causing double rounding to happen when values are eventually represented as
-// 32/64 bit float values. To overcome this, the FPU control word can be set so that the
-// computations are performed in the desired precision.
-#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
-mod fpu_precision {
-    use crate::mem::size_of;
-
-    /// A structure used to preserve the original value of the FPU control word, so that it can be
-    /// restored when the structure is dropped.
-    ///
-    /// The x87 FPU is a 16-bits register whose fields are as follows:
-    ///
-    /// | 12-15 | 10-11 | 8-9 | 6-7 |  5 |  4 |  3 |  2 |  1 |  0 |
-    /// |------:|------:|----:|----:|---:|---:|---:|---:|---:|---:|
-    /// |       | RC    | PC  |     | PM | UM | OM | ZM | DM | IM |
-    ///
-    /// The documentation for all of the fields is available in the IA-32 Architectures Software
-    /// Developer's Manual (Volume 1).
-    ///
-    /// The only field which is relevant for the following code is PC, Precision Control. This
-    /// field determines the precision of the operations performed by the  FPU. It can be set to:
-    ///  - 0b00, single precision i.e., 32-bits
-    ///  - 0b10, double precision i.e., 64-bits
-    ///  - 0b11, double extended precision i.e., 80-bits (default state)
-    /// The 0b01 value is reserved and should not be used.
-    pub struct FPUControlWord(u16);
-
-    fn set_cw(cw: u16) {
-        // SAFETY: the `fldcw` instruction has been audited to be able to work correctly with
-        // any `u16`
-        unsafe {
-            asm!(
-                "fldcw word ptr [{}]",
-                in(reg) &cw,
-                options(nostack),
-            )
-        }
-    }
-
-    /// Sets the precision field of the FPU to `T` and returns a `FPUControlWord`.
-    pub fn set_precision<T>() -> FPUControlWord {
-        let mut cw = 0_u16;
-
-        // Compute the value for the Precision Control field that is appropriate for `T`.
-        let cw_precision = match size_of::<T>() {
-            4 => 0x0000, // 32 bits
-            8 => 0x0200, // 64 bits
-            _ => 0x0300, // default, 80 bits
-        };
-
-        // Get the original value of the control word to restore it later, when the
-        // `FPUControlWord` structure is dropped
-        // SAFETY: the `fnstcw` instruction has been audited to be able to work correctly with
-        // any `u16`
-        unsafe {
-            asm!(
-                "fnstcw word ptr [{}]",
-                in(reg) &mut cw,
-                options(nostack),
-            )
-        }
-
-        // Set the control word to the desired precision. This is achieved by masking away the old
-        // precision (bits 8 and 9, 0x300) and replacing it with the precision flag computed above.
-        set_cw((cw & 0xFCFF) | cw_precision);
-
-        FPUControlWord(cw)
-    }
-
-    impl Drop for FPUControlWord {
-        fn drop(&mut self) {
-            set_cw(self.0)
-        }
-    }
-}
-
-/// The fast path of Bellerophon using machine-sized integers and floats.
-///
-/// This is extracted into a separate function so that it can be attempted before constructing
-/// a bignum.
-pub fn fast_path<T: RawFloat>(integral: &[u8], fractional: &[u8], e: i64) -> Option<T> {
-    let num_digits = integral.len() + fractional.len();
-    // log_10(f64::MAX_SIG) ~ 15.95. We compare the exact value to MAX_SIG near the end,
-    // this is just a quick, cheap rejection (and also frees the rest of the code from
-    // worrying about underflow).
-    if num_digits > 16 {
-        return None;
-    }
-    if e.abs() >= T::CEIL_LOG5_OF_MAX_SIG as i64 {
-        return None;
-    }
-    let f = num::from_str_unchecked(integral.iter().chain(fractional.iter()));
-    if f > T::MAX_SIG {
-        return None;
-    }
-
-    // The fast path crucially depends on arithmetic being rounded to the correct number of bits
-    // without any intermediate rounding. On x86 (without SSE or SSE2) this requires the precision
-    // of the x87 FPU stack to be changed so that it directly rounds to 64/32 bit.
-    // The `set_precision` function takes care of setting the precision on architectures which
-    // require setting it by changing the global state (like the control word of the x87 FPU).
-    let _cw = fpu_precision::set_precision::<T>();
-
-    // The case e < 0 cannot be folded into the other branch. Negative powers result in
-    // a repeating fractional part in binary, which are rounded, which causes real
-    // (and occasionally quite significant!) errors in the final result.
-    if e >= 0 {
-        Some(T::from_int(f) * T::short_fast_pow10(e as usize))
-    } else {
-        Some(T::from_int(f) / T::short_fast_pow10(e.abs() as usize))
-    }
-}
-
-/// Algorithm Bellerophon is trivial code justified by non-trivial numeric analysis.
-///
-/// It rounds ``f`` to a float with 64 bit significand and multiplies it by the best approximation
-/// of `10^e` (in the same floating point format). This is often enough to get the correct result.
-/// However, when the result is close to halfway between two adjacent (ordinary) floats, the
-/// compound rounding error from multiplying two approximation means the result may be off by a
-/// few bits. When this happens, the iterative Algorithm R fixes things up.
-///
-/// The hand-wavy "close to halfway" is made precise by the numeric analysis in the paper.
-/// In the words of Clinger:
-///
-/// > Slop, expressed in units of the least significant bit, is an inclusive bound for the error
-/// > accumulated during the floating point calculation of the approximation to f * 10^e. (Slop is
-/// > not a bound for the true error, but bounds the difference between the approximation z and
-/// > the best possible approximation that uses p bits of significand.)
-pub fn bellerophon<T: RawFloat>(f: &Big, e: i16) -> T {
-    let slop = if f <= &Big::from_u64(T::MAX_SIG) {
-        // The cases abs(e) < log5(2^N) are in fast_path()
-        if e >= 0 { 0 } else { 3 }
-    } else {
-        if e >= 0 { 1 } else { 4 }
-    };
-    let z = rawfp::big_to_fp(f).mul(&power_of_ten(e)).normalize();
-    let exp_p_n = 1 << (P - T::SIG_BITS as u32);
-    let lowbits: i64 = (z.f % exp_p_n) as i64;
-    // Is the slop large enough to make a difference when
-    // rounding to n bits?
-    if (lowbits - exp_p_n as i64 / 2).abs() <= slop {
-        algorithm_r(f, e, fp_to_float(z))
-    } else {
-        fp_to_float(z)
-    }
-}
-
-/// An iterative algorithm that improves a floating point approximation of `f * 10^e`.
-///
-/// Each iteration gets one unit in the last place closer, which of course takes terribly long to
-/// converge if `z0` is even mildly off. Luckily, when used as fallback for Bellerophon, the
-/// starting approximation is off by at most one ULP.
-fn algorithm_r<T: RawFloat>(f: &Big, e: i16, z0: T) -> T {
-    let mut z = z0;
-    loop {
-        let raw = z.unpack();
-        let (m, k) = (raw.sig, raw.k);
-        let mut x = f.clone();
-        let mut y = Big::from_u64(m);
-
-        // Find positive integers `x`, `y` such that `x / y` is exactly `(f * 10^e) / (m * 2^k)`.
-        // This not only avoids dealing with the signs of `e` and `k`, we also eliminate the
-        // power of two common to `10^e` and `2^k` to make the numbers smaller.
-        make_ratio(&mut x, &mut y, e, k);
-
-        let m_digits = [(m & 0xFF_FF_FF_FF) as u32, (m >> 32) as u32];
-        // This is written a bit awkwardly because our bignums don't support
-        // negative numbers, so we use the absolute value + sign information.
-        // The multiplication with m_digits can't overflow. If `x` or `y` are large enough that
-        // we need to worry about overflow, then they are also large enough that `make_ratio` has
-        // reduced the fraction by a factor of 2^64 or more.
-        let (d2, d_negative) = if x >= y {
-            // Don't need x any more, save a clone().
-            x.sub(&y).mul_pow2(1).mul_digits(&m_digits);
-            (x, false)
-        } else {
-            // Still need y - make a copy.
-            let mut y = y.clone();
-            y.sub(&x).mul_pow2(1).mul_digits(&m_digits);
-            (y, true)
-        };
-
-        if d2 < y {
-            let mut d2_double = d2;
-            d2_double.mul_pow2(1);
-            if m == T::MIN_SIG && d_negative && d2_double > y {
-                z = prev_float(z);
-            } else {
-                return z;
-            }
-        } else if d2 == y {
-            if m % 2 == 0 {
-                if m == T::MIN_SIG && d_negative {
-                    z = prev_float(z);
-                } else {
-                    return z;
-                }
-            } else if d_negative {
-                z = prev_float(z);
-            } else {
-                z = next_float(z);
-            }
-        } else if d_negative {
-            z = prev_float(z);
-        } else {
-            z = next_float(z);
-        }
-    }
-}
-
-/// Given `x = f` and `y = m` where `f` represent input decimal digits as usual and `m` is the
-/// significand of a floating point approximation, make the ratio `x / y` equal to
-/// `(f * 10^e) / (m * 2^k)`, possibly reduced by a power of two both have in common.
-fn make_ratio(x: &mut Big, y: &mut Big, e: i16, k: i16) {
-    let (e_abs, k_abs) = (e.abs() as usize, k.abs() as usize);
-    if e >= 0 {
-        if k >= 0 {
-            // x = f * 10^e, y = m * 2^k, except that we reduce the fraction by some power of two.
-            let common = min(e_abs, k_abs);
-            x.mul_pow5(e_abs).mul_pow2(e_abs - common);
-            y.mul_pow2(k_abs - common);
-        } else {
-            // x = f * 10^e * 2^abs(k), y = m
-            // This can't overflow because it requires positive `e` and negative `k`, which can
-            // only happen for values extremely close to 1, which means that `e` and `k` will be
-            // comparatively tiny.
-            x.mul_pow5(e_abs).mul_pow2(e_abs + k_abs);
-        }
-    } else {
-        if k >= 0 {
-            // x = f, y = m * 10^abs(e) * 2^k
-            // This can't overflow either, see above.
-            y.mul_pow5(e_abs).mul_pow2(k_abs + e_abs);
-        } else {
-            // x = f * 2^abs(k), y = m * 10^abs(e), again reducing by a common power of two.
-            let common = min(e_abs, k_abs);
-            x.mul_pow2(k_abs - common);
-            y.mul_pow5(e_abs).mul_pow2(e_abs - common);
-        }
-    }
-}
-
-/// Conceptually, Algorithm M is the simplest way to convert a decimal to a float.
-///
-/// We form a ratio that is equal to `f * 10^e`, then throwing in powers of two until it gives
-/// a valid float significand. The binary exponent `k` is the number of times we multiplied
-/// numerator or denominator by two, i.e., at all times `f * 10^e` equals `(u / v) * 2^k`.
-/// When we have found out significand, we only need to round by inspecting the remainder of the
-/// division, which is done in helper functions further below.
-///
-/// This algorithm is super slow, even with the optimization described in `quick_start()`.
-/// However, it's the simplest of the algorithms to adapt for overflow, underflow, and subnormal
-/// results. This implementation takes over when Bellerophon and Algorithm R are overwhelmed.
-/// Detecting underflow and overflow is easy: The ratio still isn't an in-range significand,
-/// yet the minimum/maximum exponent has been reached. In the case of overflow, we simply return
-/// infinity.
-///
-/// Handling underflow and subnormals is trickier. One big problem is that, with the minimum
-/// exponent, the ratio might still be too large for a significand. See underflow() for details.
-pub fn algorithm_m<T: RawFloat>(f: &Big, e: i16) -> T {
-    let mut u;
-    let mut v;
-    let e_abs = e.abs() as usize;
-    let mut k = 0;
-    if e < 0 {
-        u = f.clone();
-        v = Big::from_small(1);
-        v.mul_pow5(e_abs).mul_pow2(e_abs);
-    } else {
-        // FIXME possible optimization: generalize big_to_fp so that we can do the equivalent of
-        // fp_to_float(big_to_fp(u)) here, only without the double rounding.
-        u = f.clone();
-        u.mul_pow5(e_abs).mul_pow2(e_abs);
-        v = Big::from_small(1);
-    }
-    quick_start::<T>(&mut u, &mut v, &mut k);
-    let mut rem = Big::from_small(0);
-    let mut x = Big::from_small(0);
-    let min_sig = Big::from_u64(T::MIN_SIG);
-    let max_sig = Big::from_u64(T::MAX_SIG);
-    loop {
-        u.div_rem(&v, &mut x, &mut rem);
-        if k == T::MIN_EXP_INT {
-            // We have to stop at the minimum exponent, if we wait until `k < T::MIN_EXP_INT`,
-            // then we'd be off by a factor of two. Unfortunately this means we have to special-
-            // case normal numbers with the minimum exponent.
-            // FIXME find a more elegant formulation, but run the `tiny-pow10` test to make sure
-            // that it's actually correct!
-            if x >= min_sig && x <= max_sig {
-                break;
-            }
-            return underflow(x, v, rem);
-        }
-        if k > T::MAX_EXP_INT {
-            return T::INFINITY;
-        }
-        if x < min_sig {
-            u.mul_pow2(1);
-            k -= 1;
-        } else if x > max_sig {
-            v.mul_pow2(1);
-            k += 1;
-        } else {
-            break;
-        }
-    }
-    let q = num::to_u64(&x);
-    let z = rawfp::encode_normal(Unpacked::new(q, k));
-    round_by_remainder(v, rem, q, z)
-}
-
-/// Skips over most Algorithm M iterations by checking the bit length.
-fn quick_start<T: RawFloat>(u: &mut Big, v: &mut Big, k: &mut i16) {
-    // The bit length is an estimate of the base two logarithm, and log(u / v) = log(u) - log(v).
-    // The estimate is off by at most 1, but always an under-estimate, so the error on log(u)
-    // and log(v) are of the same sign and cancel out (if both are large). Therefore the error
-    // for log(u / v) is at most one as well.
-    // The target ratio is one where u/v is in an in-range significand. Thus our termination
-    // condition is log2(u / v) being the significand bits, plus/minus one.
-    // FIXME Looking at the second bit could improve the estimate and avoid some more divisions.
-    let target_ratio = T::SIG_BITS as i16;
-    let log2_u = u.bit_length() as i16;
-    let log2_v = v.bit_length() as i16;
-    let mut u_shift: i16 = 0;
-    let mut v_shift: i16 = 0;
-    assert!(*k == 0);
-    loop {
-        if *k == T::MIN_EXP_INT {
-            // Underflow or subnormal. Leave it to the main function.
-            break;
-        }
-        if *k == T::MAX_EXP_INT {
-            // Overflow. Leave it to the main function.
-            break;
-        }
-        let log2_ratio = (log2_u + u_shift) - (log2_v + v_shift);
-        if log2_ratio < target_ratio - 1 {
-            u_shift += 1;
-            *k -= 1;
-        } else if log2_ratio > target_ratio + 1 {
-            v_shift += 1;
-            *k += 1;
-        } else {
-            break;
-        }
-    }
-    u.mul_pow2(u_shift as usize);
-    v.mul_pow2(v_shift as usize);
-}
-
-fn underflow<T: RawFloat>(x: Big, v: Big, rem: Big) -> T {
-    if x < Big::from_u64(T::MIN_SIG) {
-        let q = num::to_u64(&x);
-        let z = rawfp::encode_subnormal(q);
-        return round_by_remainder(v, rem, q, z);
-    }
-    // Ratio isn't an in-range significand with the minimum exponent, so we need to round off
-    // excess bits and adjust the exponent accordingly. The real value now looks like this:
-    //
-    //        x        lsb
-    // /--------------\/
-    // 1010101010101010.10101010101010 * 2^k
-    // \-----/\-------/ \------------/
-    //    q     trunc.    (represented by rem)
-    //
-    // Therefore, when the rounded-off bits are != 0.5 ULP, they decide the rounding
-    // on their own. When they are equal and the remainder is non-zero, the value still
-    // needs to be rounded up. Only when the rounded off bits are 1/2 and the remainder
-    // is zero, we have a half-to-even situation.
-    let bits = x.bit_length();
-    let lsb = bits - T::SIG_BITS as usize;
-    let q = num::get_bits(&x, lsb, bits);
-    let k = T::MIN_EXP_INT + lsb as i16;
-    let z = rawfp::encode_normal(Unpacked::new(q, k));
-    let q_even = q % 2 == 0;
-    match num::compare_with_half_ulp(&x, lsb) {
-        Greater => next_float(z),
-        Less => z,
-        Equal if rem.is_zero() && q_even => z,
-        Equal => next_float(z),
-    }
-}
-
-/// Ordinary round-to-even, obfuscated by having to round based on the remainder of a division.
-fn round_by_remainder<T: RawFloat>(v: Big, r: Big, q: u64, z: T) -> T {
-    let mut v_minus_r = v;
-    v_minus_r.sub(&r);
-    if r < v_minus_r {
-        z
-    } else if r > v_minus_r {
-        next_float(z)
-    } else if q % 2 == 0 {
-        z
-    } else {
-        next_float(z)
-    }
-}
diff --git a/library/core/src/num/dec2flt/common.rs b/library/core/src/num/dec2flt/common.rs
new file mode 100644 (file)
index 0000000..2471237
--- /dev/null
@@ -0,0 +1,198 @@
+//! Common utilities, for internal use only.
+
+use crate::ptr;
+
+/// Helper methods to process immutable bytes.
+pub(crate) trait ByteSlice: AsRef<[u8]> {
+    unsafe fn first_unchecked(&self) -> u8 {
+        debug_assert!(!self.is_empty());
+        // SAFETY: safe as long as self is not empty
+        unsafe { *self.as_ref().get_unchecked(0) }
+    }
+
+    /// Get if the slice contains no elements.
+    fn is_empty(&self) -> bool {
+        self.as_ref().is_empty()
+    }
+
+    /// Check if the slice at least `n` length.
+    fn check_len(&self, n: usize) -> bool {
+        n <= self.as_ref().len()
+    }
+
+    /// Check if the first character in the slice is equal to c.
+    fn first_is(&self, c: u8) -> bool {
+        self.as_ref().first() == Some(&c)
+    }
+
+    /// Check if the first character in the slice is equal to c1 or c2.
+    fn first_is2(&self, c1: u8, c2: u8) -> bool {
+        if let Some(&c) = self.as_ref().first() { c == c1 || c == c2 } else { false }
+    }
+
+    /// Bounds-checked test if the first character in the slice is a digit.
+    fn first_isdigit(&self) -> bool {
+        if let Some(&c) = self.as_ref().first() { c.is_ascii_digit() } else { false }
+    }
+
+    /// Check if self starts with u with a case-insensitive comparison.
+    fn eq_ignore_case(&self, u: &[u8]) -> bool {
+        debug_assert!(self.as_ref().len() >= u.len());
+        let iter = self.as_ref().iter().zip(u.iter());
+        let d = iter.fold(0, |i, (&x, &y)| i | (x ^ y));
+        d == 0 || d == 32
+    }
+
+    /// Get the remaining slice after the first N elements.
+    fn advance(&self, n: usize) -> &[u8] {
+        &self.as_ref()[n..]
+    }
+
+    /// Get the slice after skipping all leading characters equal c.
+    fn skip_chars(&self, c: u8) -> &[u8] {
+        let mut s = self.as_ref();
+        while s.first_is(c) {
+            s = s.advance(1);
+        }
+        s
+    }
+
+    /// Get the slice after skipping all leading characters equal c1 or c2.
+    fn skip_chars2(&self, c1: u8, c2: u8) -> &[u8] {
+        let mut s = self.as_ref();
+        while s.first_is2(c1, c2) {
+            s = s.advance(1);
+        }
+        s
+    }
+
+    /// Read 8 bytes as a 64-bit integer in little-endian order.
+    unsafe fn read_u64_unchecked(&self) -> u64 {
+        debug_assert!(self.check_len(8));
+        let src = self.as_ref().as_ptr() as *const u64;
+        // SAFETY: safe as long as self is at least 8 bytes
+        u64::from_le(unsafe { ptr::read_unaligned(src) })
+    }
+
+    /// Try to read the next 8 bytes from the slice.
+    fn read_u64(&self) -> Option<u64> {
+        if self.check_len(8) {
+            // SAFETY: self must be at least 8 bytes.
+            Some(unsafe { self.read_u64_unchecked() })
+        } else {
+            None
+        }
+    }
+
+    /// Calculate the offset of slice from another.
+    fn offset_from(&self, other: &Self) -> isize {
+        other.as_ref().len() as isize - self.as_ref().len() as isize
+    }
+}
+
+impl ByteSlice for [u8] {}
+
+/// Helper methods to process mutable bytes.
+pub(crate) trait ByteSliceMut: AsMut<[u8]> {
+    /// Write a 64-bit integer as 8 bytes in little-endian order.
+    unsafe fn write_u64_unchecked(&mut self, value: u64) {
+        debug_assert!(self.as_mut().len() >= 8);
+        let dst = self.as_mut().as_mut_ptr() as *mut u64;
+        // NOTE: we must use `write_unaligned`, since dst is not
+        // guaranteed to be properly aligned. Miri will warn us
+        // if we use `write` instead of `write_unaligned`, as expected.
+        // SAFETY: safe as long as self is at least 8 bytes
+        unsafe {
+            ptr::write_unaligned(dst, u64::to_le(value));
+        }
+    }
+}
+
+impl ByteSliceMut for [u8] {}
+
+/// Bytes wrapper with specialized methods for ASCII characters.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub(crate) struct AsciiStr<'a> {
+    slc: &'a [u8],
+}
+
+impl<'a> AsciiStr<'a> {
+    pub fn new(slc: &'a [u8]) -> Self {
+        Self { slc }
+    }
+
+    /// Advance the view by n, advancing it in-place to (n..).
+    pub unsafe fn step_by(&mut self, n: usize) -> &mut Self {
+        // SAFETY: safe as long n is less than the buffer length
+        self.slc = unsafe { self.slc.get_unchecked(n..) };
+        self
+    }
+
+    /// Advance the view by n, advancing it in-place to (1..).
+    pub unsafe fn step(&mut self) -> &mut Self {
+        // SAFETY: safe as long as self is not empty
+        unsafe { self.step_by(1) }
+    }
+
+    /// Iteratively parse and consume digits from bytes.
+    pub fn parse_digits(&mut self, mut func: impl FnMut(u8)) {
+        while let Some(&c) = self.as_ref().first() {
+            let c = c.wrapping_sub(b'0');
+            if c < 10 {
+                func(c);
+                // SAFETY: self cannot be empty
+                unsafe {
+                    self.step();
+                }
+            } else {
+                break;
+            }
+        }
+    }
+}
+
+impl<'a> AsRef<[u8]> for AsciiStr<'a> {
+    #[inline]
+    fn as_ref(&self) -> &[u8] {
+        self.slc
+    }
+}
+
+impl<'a> ByteSlice for AsciiStr<'a> {}
+
+/// Determine if 8 bytes are all decimal digits.
+/// This does not care about the order in which the bytes were loaded.
+pub(crate) fn is_8digits(v: u64) -> bool {
+    let a = v.wrapping_add(0x4646_4646_4646_4646);
+    let b = v.wrapping_sub(0x3030_3030_3030_3030);
+    (a | b) & 0x8080_8080_8080_8080 == 0
+}
+
+/// Iteratively parse and consume digits from bytes.
+pub(crate) fn parse_digits(s: &mut &[u8], mut f: impl FnMut(u8)) {
+    while let Some(&c) = s.get(0) {
+        let c = c.wrapping_sub(b'0');
+        if c < 10 {
+            f(c);
+            *s = s.advance(1);
+        } else {
+            break;
+        }
+    }
+}
+
+/// A custom 64-bit floating point type, representing `f * 2^e`.
+/// e is biased, so it be directly shifted into the exponent bits.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
+pub struct BiasedFp {
+    /// The significant digits.
+    pub f: u64,
+    /// The biased, binary exponent.
+    pub e: i32,
+}
+
+impl BiasedFp {
+    pub const fn zero_pow2(e: i32) -> Self {
+        Self { f: 0, e }
+    }
+}
diff --git a/library/core/src/num/dec2flt/decimal.rs b/library/core/src/num/dec2flt/decimal.rs
new file mode 100644 (file)
index 0000000..f8edc36
--- /dev/null
@@ -0,0 +1,351 @@
+//! Arbitrary-precision decimal class for fallback algorithms.
+//!
+//! This is only used if the fast-path (native floats) and
+//! the Eisel-Lemire algorithm are unable to unambiguously
+//! determine the float.
+//!
+//! The technique used is "Simple Decimal Conversion", developed
+//! by Nigel Tao and Ken Thompson. A detailed description of the
+//! algorithm can be found in "ParseNumberF64 by Simple Decimal Conversion",
+//! available online: <https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html>.
+
+use crate::num::dec2flt::common::{is_8digits, parse_digits, ByteSlice, ByteSliceMut};
+
+#[derive(Clone)]
+pub struct Decimal {
+    /// The number of significant digits in the decimal.
+    pub num_digits: usize,
+    /// The offset of the decimal point in the significant digits.
+    pub decimal_point: i32,
+    /// If the number of significant digits stored in the decimal is truncated.
+    pub truncated: bool,
+    /// Buffer of the raw digits, in the range [0, 9].
+    pub digits: [u8; Self::MAX_DIGITS],
+}
+
+impl Default for Decimal {
+    fn default() -> Self {
+        Self { num_digits: 0, decimal_point: 0, truncated: false, digits: [0; Self::MAX_DIGITS] }
+    }
+}
+
+impl Decimal {
+    /// The maximum number of digits required to unambiguously round a float.
+    ///
+    /// For a double-precision IEEE-754 float, this required 767 digits,
+    /// so we store the max digits + 1.
+    ///
+    /// We can exactly represent a float in radix `b` from radix 2 if
+    /// `b` is divisible by 2. This function calculates the exact number of
+    /// digits required to exactly represent that float.
+    ///
+    /// According to the "Handbook of Floating Point Arithmetic",
+    /// for IEEE754, with emin being the min exponent, p2 being the
+    /// precision, and b being the radix, the number of digits follows as:
+    ///
+    /// `−emin + p2 + ⌊(emin + 1) log(2, b) − log(1 − 2^(−p2), b)⌋`
+    ///
+    /// For f32, this follows as:
+    ///     emin = -126
+    ///     p2 = 24
+    ///
+    /// For f64, this follows as:
+    ///     emin = -1022
+    ///     p2 = 53
+    ///
+    /// In Python:
+    ///     `-emin + p2 + math.floor((emin+ 1)*math.log(2, b)-math.log(1-2**(-p2), b))`
+    pub const MAX_DIGITS: usize = 768;
+    /// The max digits that can be exactly represented in a 64-bit integer.
+    pub const MAX_DIGITS_WITHOUT_OVERFLOW: usize = 19;
+    pub const DECIMAL_POINT_RANGE: i32 = 2047;
+
+    /// Append a digit to the buffer.
+    pub fn try_add_digit(&mut self, digit: u8) {
+        if self.num_digits < Self::MAX_DIGITS {
+            self.digits[self.num_digits] = digit;
+        }
+        self.num_digits += 1;
+    }
+
+    /// Trim trailing zeros from the buffer.
+    pub fn trim(&mut self) {
+        // All of the following calls to `Decimal::trim` can't panic because:
+        //
+        //  1. `parse_decimal` sets `num_digits` to a max of `Decimal::MAX_DIGITS`.
+        //  2. `right_shift` sets `num_digits` to `write_index`, which is bounded by `num_digits`.
+        //  3. `left_shift` `num_digits` to a max of `Decimal::MAX_DIGITS`.
+        //
+        // Trim is only called in `right_shift` and `left_shift`.
+        debug_assert!(self.num_digits <= Self::MAX_DIGITS);
+        while self.num_digits != 0 && self.digits[self.num_digits - 1] == 0 {
+            self.num_digits -= 1;
+        }
+    }
+
+    pub fn round(&self) -> u64 {
+        if self.num_digits == 0 || self.decimal_point < 0 {
+            return 0;
+        } else if self.decimal_point > 18 {
+            return 0xFFFF_FFFF_FFFF_FFFF_u64;
+        }
+        let dp = self.decimal_point as usize;
+        let mut n = 0_u64;
+        for i in 0..dp {
+            n *= 10;
+            if i < self.num_digits {
+                n += self.digits[i] as u64;
+            }
+        }
+        let mut round_up = false;
+        if dp < self.num_digits {
+            round_up = self.digits[dp] >= 5;
+            if self.digits[dp] == 5 && dp + 1 == self.num_digits {
+                round_up = self.truncated || ((dp != 0) && (1 & self.digits[dp - 1] != 0))
+            }
+        }
+        if round_up {
+            n += 1;
+        }
+        n
+    }
+
+    /// Computes decimal * 2^shift.
+    pub fn left_shift(&mut self, shift: usize) {
+        if self.num_digits == 0 {
+            return;
+        }
+        let num_new_digits = number_of_digits_decimal_left_shift(self, shift);
+        let mut read_index = self.num_digits;
+        let mut write_index = self.num_digits + num_new_digits;
+        let mut n = 0_u64;
+        while read_index != 0 {
+            read_index -= 1;
+            write_index -= 1;
+            n += (self.digits[read_index] as u64) << shift;
+            let quotient = n / 10;
+            let remainder = n - (10 * quotient);
+            if write_index < Self::MAX_DIGITS {
+                self.digits[write_index] = remainder as u8;
+            } else if remainder > 0 {
+                self.truncated = true;
+            }
+            n = quotient;
+        }
+        while n > 0 {
+            write_index -= 1;
+            let quotient = n / 10;
+            let remainder = n - (10 * quotient);
+            if write_index < Self::MAX_DIGITS {
+                self.digits[write_index] = remainder as u8;
+            } else if remainder > 0 {
+                self.truncated = true;
+            }
+            n = quotient;
+        }
+        self.num_digits += num_new_digits;
+        if self.num_digits > Self::MAX_DIGITS {
+            self.num_digits = Self::MAX_DIGITS;
+        }
+        self.decimal_point += num_new_digits as i32;
+        self.trim();
+    }
+
+    /// Computes decimal * 2^-shift.
+    pub fn right_shift(&mut self, shift: usize) {
+        let mut read_index = 0;
+        let mut write_index = 0;
+        let mut n = 0_u64;
+        while (n >> shift) == 0 {
+            if read_index < self.num_digits {
+                n = (10 * n) + self.digits[read_index] as u64;
+                read_index += 1;
+            } else if n == 0 {
+                return;
+            } else {
+                while (n >> shift) == 0 {
+                    n *= 10;
+                    read_index += 1;
+                }
+                break;
+            }
+        }
+        self.decimal_point -= read_index as i32 - 1;
+        if self.decimal_point < -Self::DECIMAL_POINT_RANGE {
+            // `self = Self::Default()`, but without the overhead of clearing `digits`.
+            self.num_digits = 0;
+            self.decimal_point = 0;
+            self.truncated = false;
+            return;
+        }
+        let mask = (1_u64 << shift) - 1;
+        while read_index < self.num_digits {
+            let new_digit = (n >> shift) as u8;
+            n = (10 * (n & mask)) + self.digits[read_index] as u64;
+            read_index += 1;
+            self.digits[write_index] = new_digit;
+            write_index += 1;
+        }
+        while n > 0 {
+            let new_digit = (n >> shift) as u8;
+            n = 10 * (n & mask);
+            if write_index < Self::MAX_DIGITS {
+                self.digits[write_index] = new_digit;
+                write_index += 1;
+            } else if new_digit > 0 {
+                self.truncated = true;
+            }
+        }
+        self.num_digits = write_index;
+        self.trim();
+    }
+}
+
+/// Parse a big integer representation of the float as a decimal.
+pub fn parse_decimal(mut s: &[u8]) -> Decimal {
+    let mut d = Decimal::default();
+    let start = s;
+    s = s.skip_chars(b'0');
+    parse_digits(&mut s, |digit| d.try_add_digit(digit));
+    if s.first_is(b'.') {
+        s = s.advance(1);
+        let first = s;
+        // Skip leading zeros.
+        if d.num_digits == 0 {
+            s = s.skip_chars(b'0');
+        }
+        while s.len() >= 8 && d.num_digits + 8 < Decimal::MAX_DIGITS {
+            // SAFETY: s is at least 8 bytes.
+            let v = unsafe { s.read_u64_unchecked() };
+            if !is_8digits(v) {
+                break;
+            }
+            // SAFETY: d.num_digits + 8 is less than d.digits.len()
+            unsafe {
+                d.digits[d.num_digits..].write_u64_unchecked(v - 0x3030_3030_3030_3030);
+            }
+            d.num_digits += 8;
+            s = s.advance(8);
+        }
+        parse_digits(&mut s, |digit| d.try_add_digit(digit));
+        d.decimal_point = s.len() as i32 - first.len() as i32;
+    }
+    if d.num_digits != 0 {
+        // Ignore the trailing zeros if there are any
+        let mut n_trailing_zeros = 0;
+        for &c in start[..(start.len() - s.len())].iter().rev() {
+            if c == b'0' {
+                n_trailing_zeros += 1;
+            } else if c != b'.' {
+                break;
+            }
+        }
+        d.decimal_point += n_trailing_zeros as i32;
+        d.num_digits -= n_trailing_zeros;
+        d.decimal_point += d.num_digits as i32;
+        if d.num_digits > Decimal::MAX_DIGITS {
+            d.truncated = true;
+            d.num_digits = Decimal::MAX_DIGITS;
+        }
+    }
+    if s.first_is2(b'e', b'E') {
+        s = s.advance(1);
+        let mut neg_exp = false;
+        if s.first_is(b'-') {
+            neg_exp = true;
+            s = s.advance(1);
+        } else if s.first_is(b'+') {
+            s = s.advance(1);
+        }
+        let mut exp_num = 0_i32;
+        parse_digits(&mut s, |digit| {
+            if exp_num < 0x10000 {
+                exp_num = 10 * exp_num + digit as i32;
+            }
+        });
+        d.decimal_point += if neg_exp { -exp_num } else { exp_num };
+    }
+    for i in d.num_digits..Decimal::MAX_DIGITS_WITHOUT_OVERFLOW {
+        d.digits[i] = 0;
+    }
+    d
+}
+
+fn number_of_digits_decimal_left_shift(d: &Decimal, mut shift: usize) -> usize {
+    #[rustfmt::skip]
+    const TABLE: [u16; 65] = [
+        0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817, 0x181D, 0x2024,
+        0x202B, 0x2033, 0x203C, 0x2846, 0x2850, 0x285B, 0x3067, 0x3073, 0x3080, 0x388E, 0x389C,
+        0x38AB, 0x38BB, 0x40CC, 0x40DD, 0x40EF, 0x4902, 0x4915, 0x4929, 0x513E, 0x5153, 0x5169,
+        0x5180, 0x5998, 0x59B0, 0x59C9, 0x61E3, 0x61FD, 0x6218, 0x6A34, 0x6A50, 0x6A6D, 0x6A8B,
+        0x72AA, 0x72C9, 0x72E9, 0x7B0A, 0x7B2B, 0x7B4D, 0x8370, 0x8393, 0x83B7, 0x83DC, 0x8C02,
+        0x8C28, 0x8C4F, 0x9477, 0x949F, 0x94C8, 0x9CF2, 0x051C, 0x051C, 0x051C, 0x051C,
+    ];
+    #[rustfmt::skip]
+    const TABLE_POW5: [u8; 0x051C] = [
+        5, 2, 5, 1, 2, 5, 6, 2, 5, 3, 1, 2, 5, 1, 5, 6, 2, 5, 7, 8, 1, 2, 5, 3, 9, 0, 6, 2, 5, 1,
+        9, 5, 3, 1, 2, 5, 9, 7, 6, 5, 6, 2, 5, 4, 8, 8, 2, 8, 1, 2, 5, 2, 4, 4, 1, 4, 0, 6, 2, 5,
+        1, 2, 2, 0, 7, 0, 3, 1, 2, 5, 6, 1, 0, 3, 5, 1, 5, 6, 2, 5, 3, 0, 5, 1, 7, 5, 7, 8, 1, 2,
+        5, 1, 5, 2, 5, 8, 7, 8, 9, 0, 6, 2, 5, 7, 6, 2, 9, 3, 9, 4, 5, 3, 1, 2, 5, 3, 8, 1, 4, 6,
+        9, 7, 2, 6, 5, 6, 2, 5, 1, 9, 0, 7, 3, 4, 8, 6, 3, 2, 8, 1, 2, 5, 9, 5, 3, 6, 7, 4, 3, 1,
+        6, 4, 0, 6, 2, 5, 4, 7, 6, 8, 3, 7, 1, 5, 8, 2, 0, 3, 1, 2, 5, 2, 3, 8, 4, 1, 8, 5, 7, 9,
+        1, 0, 1, 5, 6, 2, 5, 1, 1, 9, 2, 0, 9, 2, 8, 9, 5, 5, 0, 7, 8, 1, 2, 5, 5, 9, 6, 0, 4, 6,
+        4, 4, 7, 7, 5, 3, 9, 0, 6, 2, 5, 2, 9, 8, 0, 2, 3, 2, 2, 3, 8, 7, 6, 9, 5, 3, 1, 2, 5, 1,
+        4, 9, 0, 1, 1, 6, 1, 1, 9, 3, 8, 4, 7, 6, 5, 6, 2, 5, 7, 4, 5, 0, 5, 8, 0, 5, 9, 6, 9, 2,
+        3, 8, 2, 8, 1, 2, 5, 3, 7, 2, 5, 2, 9, 0, 2, 9, 8, 4, 6, 1, 9, 1, 4, 0, 6, 2, 5, 1, 8, 6,
+        2, 6, 4, 5, 1, 4, 9, 2, 3, 0, 9, 5, 7, 0, 3, 1, 2, 5, 9, 3, 1, 3, 2, 2, 5, 7, 4, 6, 1, 5,
+        4, 7, 8, 5, 1, 5, 6, 2, 5, 4, 6, 5, 6, 6, 1, 2, 8, 7, 3, 0, 7, 7, 3, 9, 2, 5, 7, 8, 1, 2,
+        5, 2, 3, 2, 8, 3, 0, 6, 4, 3, 6, 5, 3, 8, 6, 9, 6, 2, 8, 9, 0, 6, 2, 5, 1, 1, 6, 4, 1, 5,
+        3, 2, 1, 8, 2, 6, 9, 3, 4, 8, 1, 4, 4, 5, 3, 1, 2, 5, 5, 8, 2, 0, 7, 6, 6, 0, 9, 1, 3, 4,
+        6, 7, 4, 0, 7, 2, 2, 6, 5, 6, 2, 5, 2, 9, 1, 0, 3, 8, 3, 0, 4, 5, 6, 7, 3, 3, 7, 0, 3, 6,
+        1, 3, 2, 8, 1, 2, 5, 1, 4, 5, 5, 1, 9, 1, 5, 2, 2, 8, 3, 6, 6, 8, 5, 1, 8, 0, 6, 6, 4, 0,
+        6, 2, 5, 7, 2, 7, 5, 9, 5, 7, 6, 1, 4, 1, 8, 3, 4, 2, 5, 9, 0, 3, 3, 2, 0, 3, 1, 2, 5, 3,
+        6, 3, 7, 9, 7, 8, 8, 0, 7, 0, 9, 1, 7, 1, 2, 9, 5, 1, 6, 6, 0, 1, 5, 6, 2, 5, 1, 8, 1, 8,
+        9, 8, 9, 4, 0, 3, 5, 4, 5, 8, 5, 6, 4, 7, 5, 8, 3, 0, 0, 7, 8, 1, 2, 5, 9, 0, 9, 4, 9, 4,
+        7, 0, 1, 7, 7, 2, 9, 2, 8, 2, 3, 7, 9, 1, 5, 0, 3, 9, 0, 6, 2, 5, 4, 5, 4, 7, 4, 7, 3, 5,
+        0, 8, 8, 6, 4, 6, 4, 1, 1, 8, 9, 5, 7, 5, 1, 9, 5, 3, 1, 2, 5, 2, 2, 7, 3, 7, 3, 6, 7, 5,
+        4, 4, 3, 2, 3, 2, 0, 5, 9, 4, 7, 8, 7, 5, 9, 7, 6, 5, 6, 2, 5, 1, 1, 3, 6, 8, 6, 8, 3, 7,
+        7, 2, 1, 6, 1, 6, 0, 2, 9, 7, 3, 9, 3, 7, 9, 8, 8, 2, 8, 1, 2, 5, 5, 6, 8, 4, 3, 4, 1, 8,
+        8, 6, 0, 8, 0, 8, 0, 1, 4, 8, 6, 9, 6, 8, 9, 9, 4, 1, 4, 0, 6, 2, 5, 2, 8, 4, 2, 1, 7, 0,
+        9, 4, 3, 0, 4, 0, 4, 0, 0, 7, 4, 3, 4, 8, 4, 4, 9, 7, 0, 7, 0, 3, 1, 2, 5, 1, 4, 2, 1, 0,
+        8, 5, 4, 7, 1, 5, 2, 0, 2, 0, 0, 3, 7, 1, 7, 4, 2, 2, 4, 8, 5, 3, 5, 1, 5, 6, 2, 5, 7, 1,
+        0, 5, 4, 2, 7, 3, 5, 7, 6, 0, 1, 0, 0, 1, 8, 5, 8, 7, 1, 1, 2, 4, 2, 6, 7, 5, 7, 8, 1, 2,
+        5, 3, 5, 5, 2, 7, 1, 3, 6, 7, 8, 8, 0, 0, 5, 0, 0, 9, 2, 9, 3, 5, 5, 6, 2, 1, 3, 3, 7, 8,
+        9, 0, 6, 2, 5, 1, 7, 7, 6, 3, 5, 6, 8, 3, 9, 4, 0, 0, 2, 5, 0, 4, 6, 4, 6, 7, 7, 8, 1, 0,
+        6, 6, 8, 9, 4, 5, 3, 1, 2, 5, 8, 8, 8, 1, 7, 8, 4, 1, 9, 7, 0, 0, 1, 2, 5, 2, 3, 2, 3, 3,
+        8, 9, 0, 5, 3, 3, 4, 4, 7, 2, 6, 5, 6, 2, 5, 4, 4, 4, 0, 8, 9, 2, 0, 9, 8, 5, 0, 0, 6, 2,
+        6, 1, 6, 1, 6, 9, 4, 5, 2, 6, 6, 7, 2, 3, 6, 3, 2, 8, 1, 2, 5, 2, 2, 2, 0, 4, 4, 6, 0, 4,
+        9, 2, 5, 0, 3, 1, 3, 0, 8, 0, 8, 4, 7, 2, 6, 3, 3, 3, 6, 1, 8, 1, 6, 4, 0, 6, 2, 5, 1, 1,
+        1, 0, 2, 2, 3, 0, 2, 4, 6, 2, 5, 1, 5, 6, 5, 4, 0, 4, 2, 3, 6, 3, 1, 6, 6, 8, 0, 9, 0, 8,
+        2, 0, 3, 1, 2, 5, 5, 5, 5, 1, 1, 1, 5, 1, 2, 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5,
+        8, 3, 4, 0, 4, 5, 4, 1, 0, 1, 5, 6, 2, 5, 2, 7, 7, 5, 5, 5, 7, 5, 6, 1, 5, 6, 2, 8, 9, 1,
+        3, 5, 1, 0, 5, 9, 0, 7, 9, 1, 7, 0, 2, 2, 7, 0, 5, 0, 7, 8, 1, 2, 5, 1, 3, 8, 7, 7, 7, 8,
+        7, 8, 0, 7, 8, 1, 4, 4, 5, 6, 7, 5, 5, 2, 9, 5, 3, 9, 5, 8, 5, 1, 1, 3, 5, 2, 5, 3, 9, 0,
+        6, 2, 5, 6, 9, 3, 8, 8, 9, 3, 9, 0, 3, 9, 0, 7, 2, 2, 8, 3, 7, 7, 6, 4, 7, 6, 9, 7, 9, 2,
+        5, 5, 6, 7, 6, 2, 6, 9, 5, 3, 1, 2, 5, 3, 4, 6, 9, 4, 4, 6, 9, 5, 1, 9, 5, 3, 6, 1, 4, 1,
+        8, 8, 8, 2, 3, 8, 4, 8, 9, 6, 2, 7, 8, 3, 8, 1, 3, 4, 7, 6, 5, 6, 2, 5, 1, 7, 3, 4, 7, 2,
+        3, 4, 7, 5, 9, 7, 6, 8, 0, 7, 0, 9, 4, 4, 1, 1, 9, 2, 4, 4, 8, 1, 3, 9, 1, 9, 0, 6, 7, 3,
+        8, 2, 8, 1, 2, 5, 8, 6, 7, 3, 6, 1, 7, 3, 7, 9, 8, 8, 4, 0, 3, 5, 4, 7, 2, 0, 5, 9, 6, 2,
+        2, 4, 0, 6, 9, 5, 9, 5, 3, 3, 6, 9, 1, 4, 0, 6, 2, 5,
+    ];
+
+    shift &= 63;
+    let x_a = TABLE[shift];
+    let x_b = TABLE[shift + 1];
+    let num_new_digits = (x_a >> 11) as _;
+    let pow5_a = (0x7FF & x_a) as usize;
+    let pow5_b = (0x7FF & x_b) as usize;
+    let pow5 = &TABLE_POW5[pow5_a..];
+    for (i, &p5) in pow5.iter().enumerate().take(pow5_b - pow5_a) {
+        if i >= d.num_digits {
+            return num_new_digits - 1;
+        } else if d.digits[i] == p5 {
+            continue;
+        } else if d.digits[i] < p5 {
+            return num_new_digits - 1;
+        } else {
+            return num_new_digits;
+        }
+    }
+    num_new_digits
+}
diff --git a/library/core/src/num/dec2flt/float.rs b/library/core/src/num/dec2flt/float.rs
new file mode 100644 (file)
index 0000000..5921c5e
--- /dev/null
@@ -0,0 +1,207 @@
+//! Helper trait for generic float types.
+
+use crate::fmt::{Debug, LowerExp};
+use crate::num::FpCategory;
+use crate::ops::{Add, Div, Mul, Neg};
+
+/// A helper trait to avoid duplicating basically all the conversion code for `f32` and `f64`.
+///
+/// See the parent module's doc comment for why this is necessary.
+///
+/// Should **never ever** be implemented for other types or be used outside the dec2flt module.
+#[doc(hidden)]
+pub trait RawFloat:
+    Sized
+    + Div<Output = Self>
+    + Neg<Output = Self>
+    + Mul<Output = Self>
+    + Add<Output = Self>
+    + LowerExp
+    + PartialEq
+    + PartialOrd
+    + Default
+    + Clone
+    + Copy
+    + Debug
+{
+    const INFINITY: Self;
+    const NEG_INFINITY: Self;
+    const NAN: Self;
+    const NEG_NAN: Self;
+
+    /// The number of bits in the significand, *excluding* the hidden bit.
+    const MANTISSA_EXPLICIT_BITS: usize;
+
+    // Round-to-even only happens for negative values of q
+    // when q ≥ −4 in the 64-bit case and when q ≥ −17 in
+    // the 32-bitcase.
+    //
+    // When q ≥ 0,we have that 5^q ≤ 2m+1. In the 64-bit case,we
+    // have 5^q ≤ 2m+1 ≤ 2^54 or q ≤ 23. In the 32-bit case,we have
+    // 5^q ≤ 2m+1 ≤ 2^25 or q ≤ 10.
+    //
+    // When q < 0, we have w ≥ (2m+1)×5^−q. We must have that w < 2^64
+    // so (2m+1)×5^−q < 2^64. We have that 2m+1 > 2^53 (64-bit case)
+    // or 2m+1 > 2^24 (32-bit case). Hence,we must have 2^53×5^−q < 2^64
+    // (64-bit) and 2^24×5^−q < 2^64 (32-bit). Hence we have 5^−q < 2^11
+    // or q ≥ −4 (64-bit case) and 5^−q < 2^40 or q ≥ −17 (32-bitcase).
+    //
+    // Thus we have that we only need to round ties to even when
+    // we have that q ∈ [−4,23](in the 64-bit case) or q∈[−17,10]
+    // (in the 32-bit case). In both cases,the power of five(5^|q|)
+    // fits in a 64-bit word.
+    const MIN_EXPONENT_ROUND_TO_EVEN: i32;
+    const MAX_EXPONENT_ROUND_TO_EVEN: i32;
+
+    // Minimum exponent that for a fast path case, or `-⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋`
+    const MIN_EXPONENT_FAST_PATH: i64;
+
+    // Maximum exponent that for a fast path case, or `⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋`
+    const MAX_EXPONENT_FAST_PATH: i64;
+
+    // Maximum exponent that can be represented for a disguised-fast path case.
+    // This is `MAX_EXPONENT_FAST_PATH + ⌊(MANTISSA_EXPLICIT_BITS+1)/log2(10)⌋`
+    const MAX_EXPONENT_DISGUISED_FAST_PATH: i64;
+
+    // Minimum exponent value `-(1 << (EXP_BITS - 1)) + 1`.
+    const MINIMUM_EXPONENT: i32;
+
+    // Largest exponent value `(1 << EXP_BITS) - 1`.
+    const INFINITE_POWER: i32;
+
+    // Index (in bits) of the sign.
+    const SIGN_INDEX: usize;
+
+    // Smallest decimal exponent for a non-zero value.
+    const SMALLEST_POWER_OF_TEN: i32;
+
+    // Largest decimal exponent for a non-infinite value.
+    const LARGEST_POWER_OF_TEN: i32;
+
+    // Maximum mantissa for the fast-path (`1 << 53` for f64).
+    const MAX_MANTISSA_FAST_PATH: u64 = 2_u64 << Self::MANTISSA_EXPLICIT_BITS;
+
+    /// Convert integer into float through an as cast.
+    /// This is only called in the fast-path algorithm, and therefore
+    /// will not lose precision, since the value will always have
+    /// only if the value is <= Self::MAX_MANTISSA_FAST_PATH.
+    fn from_u64(v: u64) -> Self;
+
+    /// Performs a raw transmutation from an integer.
+    fn from_u64_bits(v: u64) -> Self;
+
+    /// Get a small power-of-ten for fast-path multiplication.
+    fn pow10_fast_path(exponent: usize) -> Self;
+
+    /// Returns the category that this number falls into.
+    fn classify(self) -> FpCategory;
+
+    /// Returns the mantissa, exponent and sign as integers.
+    fn integer_decode(self) -> (u64, i16, i8);
+}
+
+impl RawFloat for f32 {
+    const INFINITY: Self = f32::INFINITY;
+    const NEG_INFINITY: Self = f32::NEG_INFINITY;
+    const NAN: Self = f32::NAN;
+    const NEG_NAN: Self = -f32::NAN;
+
+    const MANTISSA_EXPLICIT_BITS: usize = 23;
+    const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -17;
+    const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 10;
+    const MIN_EXPONENT_FAST_PATH: i64 = -10; // assuming FLT_EVAL_METHOD = 0
+    const MAX_EXPONENT_FAST_PATH: i64 = 10;
+    const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 = 17;
+    const MINIMUM_EXPONENT: i32 = -127;
+    const INFINITE_POWER: i32 = 0xFF;
+    const SIGN_INDEX: usize = 31;
+    const SMALLEST_POWER_OF_TEN: i32 = -65;
+    const LARGEST_POWER_OF_TEN: i32 = 38;
+
+    fn from_u64(v: u64) -> Self {
+        debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
+        v as _
+    }
+
+    fn from_u64_bits(v: u64) -> Self {
+        f32::from_bits((v & 0xFFFFFFFF) as u32)
+    }
+
+    fn pow10_fast_path(exponent: usize) -> Self {
+        #[allow(clippy::use_self)]
+        const TABLE: [f32; 16] =
+            [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.];
+        TABLE[exponent & 15]
+    }
+
+    /// Returns the mantissa, exponent and sign as integers.
+    fn integer_decode(self) -> (u64, i16, i8) {
+        let bits = self.to_bits();
+        let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
+        let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
+        let mantissa =
+            if exponent == 0 { (bits & 0x7fffff) << 1 } else { (bits & 0x7fffff) | 0x800000 };
+        // Exponent bias + mantissa shift
+        exponent -= 127 + 23;
+        (mantissa as u64, exponent, sign)
+    }
+
+    fn classify(self) -> FpCategory {
+        self.classify()
+    }
+}
+
+impl RawFloat for f64 {
+    const INFINITY: Self = f64::INFINITY;
+    const NEG_INFINITY: Self = f64::NEG_INFINITY;
+    const NAN: Self = f64::NAN;
+    const NEG_NAN: Self = -f64::NAN;
+
+    const MANTISSA_EXPLICIT_BITS: usize = 52;
+    const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -4;
+    const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 23;
+    const MIN_EXPONENT_FAST_PATH: i64 = -22; // assuming FLT_EVAL_METHOD = 0
+    const MAX_EXPONENT_FAST_PATH: i64 = 22;
+    const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 = 37;
+    const MINIMUM_EXPONENT: i32 = -1023;
+    const INFINITE_POWER: i32 = 0x7FF;
+    const SIGN_INDEX: usize = 63;
+    const SMALLEST_POWER_OF_TEN: i32 = -342;
+    const LARGEST_POWER_OF_TEN: i32 = 308;
+
+    fn from_u64(v: u64) -> Self {
+        debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
+        v as _
+    }
+
+    fn from_u64_bits(v: u64) -> Self {
+        f64::from_bits(v)
+    }
+
+    fn pow10_fast_path(exponent: usize) -> Self {
+        const TABLE: [f64; 32] = [
+            1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
+            1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 0., 0., 0., 0., 0., 0., 0., 0., 0.,
+        ];
+        TABLE[exponent & 31]
+    }
+
+    /// Returns the mantissa, exponent and sign as integers.
+    fn integer_decode(self) -> (u64, i16, i8) {
+        let bits = self.to_bits();
+        let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
+        let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
+        let mantissa = if exponent == 0 {
+            (bits & 0xfffffffffffff) << 1
+        } else {
+            (bits & 0xfffffffffffff) | 0x10000000000000
+        };
+        // Exponent bias + mantissa shift
+        exponent -= 1023 + 52;
+        (mantissa, exponent, sign)
+    }
+
+    fn classify(self) -> FpCategory {
+        self.classify()
+    }
+}
diff --git a/library/core/src/num/dec2flt/fpu.rs b/library/core/src/num/dec2flt/fpu.rs
new file mode 100644 (file)
index 0000000..24492d9
--- /dev/null
@@ -0,0 +1,89 @@
+//! Platform-specific, assembly instructions to avoid
+//! intermediate rounding on architectures with FPUs.
+
+pub use fpu_precision::set_precision;
+
+// On x86, the x87 FPU is used for float operations if the SSE/SSE2 extensions are not available.
+// The x87 FPU operates with 80 bits of precision by default, which means that operations will
+// round to 80 bits causing double rounding to happen when values are eventually represented as
+// 32/64 bit float values. To overcome this, the FPU control word can be set so that the
+// computations are performed in the desired precision.
+#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
+mod fpu_precision {
+    use core::mem::size_of;
+
+    /// A structure used to preserve the original value of the FPU control word, so that it can be
+    /// restored when the structure is dropped.
+    ///
+    /// The x87 FPU is a 16-bits register whose fields are as follows:
+    ///
+    /// | 12-15 | 10-11 | 8-9 | 6-7 |  5 |  4 |  3 |  2 |  1 |  0 |
+    /// |------:|------:|----:|----:|---:|---:|---:|---:|---:|---:|
+    /// |       | RC    | PC  |     | PM | UM | OM | ZM | DM | IM |
+    ///
+    /// The documentation for all of the fields is available in the IA-32 Architectures Software
+    /// Developer's Manual (Volume 1).
+    ///
+    /// The only field which is relevant for the following code is PC, Precision Control. This
+    /// field determines the precision of the operations performed by the  FPU. It can be set to:
+    ///  - 0b00, single precision i.e., 32-bits
+    ///  - 0b10, double precision i.e., 64-bits
+    ///  - 0b11, double extended precision i.e., 80-bits (default state)
+    /// The 0b01 value is reserved and should not be used.
+    pub struct FPUControlWord(u16);
+
+    fn set_cw(cw: u16) {
+        // SAFETY: the `fldcw` instruction has been audited to be able to work correctly with
+        // any `u16`
+        unsafe {
+            asm!(
+                "fldcw word ptr [{}]",
+                in(reg) &cw,
+                options(nostack),
+            )
+        }
+    }
+
+    /// Sets the precision field of the FPU to `T` and returns a `FPUControlWord`.
+    pub fn set_precision<T>() -> FPUControlWord {
+        let mut cw = 0_u16;
+
+        // Compute the value for the Precision Control field that is appropriate for `T`.
+        let cw_precision = match size_of::<T>() {
+            4 => 0x0000, // 32 bits
+            8 => 0x0200, // 64 bits
+            _ => 0x0300, // default, 80 bits
+        };
+
+        // Get the original value of the control word to restore it later, when the
+        // `FPUControlWord` structure is dropped
+        // SAFETY: the `fnstcw` instruction has been audited to be able to work correctly with
+        // any `u16`
+        unsafe {
+            asm!(
+                "fnstcw word ptr [{}]",
+                in(reg) &mut cw,
+                options(nostack),
+            )
+        }
+
+        // Set the control word to the desired precision. This is achieved by masking away the old
+        // precision (bits 8 and 9, 0x300) and replacing it with the precision flag computed above.
+        set_cw((cw & 0xFCFF) | cw_precision);
+
+        FPUControlWord(cw)
+    }
+
+    impl Drop for FPUControlWord {
+        fn drop(&mut self) {
+            set_cw(self.0)
+        }
+    }
+}
+
+// In most architectures, floating point operations have an explicit bit size, therefore the
+// precision of the computation is determined on a per-operation basis.
+#[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))]
+mod fpu_precision {
+    pub fn set_precision<T>() {}
+}
diff --git a/library/core/src/num/dec2flt/lemire.rs b/library/core/src/num/dec2flt/lemire.rs
new file mode 100644 (file)
index 0000000..9b7efc3
--- /dev/null
@@ -0,0 +1,166 @@
+//! Implementation of the Eisel-Lemire algorithm.
+
+use crate::num::dec2flt::common::BiasedFp;
+use crate::num::dec2flt::float::RawFloat;
+use crate::num::dec2flt::table::{
+    LARGEST_POWER_OF_FIVE, POWER_OF_FIVE_128, SMALLEST_POWER_OF_FIVE,
+};
+
+/// Compute a float using an extended-precision representation.
+///
+/// Fast conversion of a the significant digits and decimal exponent
+/// a float to a extended representation with a binary float. This
+/// algorithm will accurately parse the vast majority of cases,
+/// and uses a 128-bit representation (with a fallback 192-bit
+/// representation).
+///
+/// This algorithm scales the exponent by the decimal exponent
+/// using pre-computed powers-of-5, and calculates if the
+/// representation can be unambiguously rounded to the nearest
+/// machine float. Near-halfway cases are not handled here,
+/// and are represented by a negative, biased binary exponent.
+///
+/// The algorithm is described in detail in "Daniel Lemire, Number Parsing
+/// at a Gigabyte per Second" in section 5, "Fast Algorithm", and
+/// section 6, "Exact Numbers And Ties", available online:
+/// <https://arxiv.org/abs/2101.11408.pdf>.
+pub fn compute_float<F: RawFloat>(q: i64, mut w: u64) -> BiasedFp {
+    let fp_zero = BiasedFp::zero_pow2(0);
+    let fp_inf = BiasedFp::zero_pow2(F::INFINITE_POWER);
+    let fp_error = BiasedFp::zero_pow2(-1);
+
+    // Short-circuit if the value can only be a literal 0 or infinity.
+    if w == 0 || q < F::SMALLEST_POWER_OF_TEN as i64 {
+        return fp_zero;
+    } else if q > F::LARGEST_POWER_OF_TEN as i64 {
+        return fp_inf;
+    }
+    // Normalize our significant digits, so the most-significant bit is set.
+    let lz = w.leading_zeros();
+    w <<= lz;
+    let (lo, hi) = compute_product_approx(q, w, F::MANTISSA_EXPLICIT_BITS + 3);
+    if lo == 0xFFFF_FFFF_FFFF_FFFF {
+        // If we have failed to approximate w x 5^-q with our 128-bit value.
+        // Since the addition of 1 could lead to an overflow which could then
+        // round up over the half-way point, this can lead to improper rounding
+        // of a float.
+        //
+        // However, this can only occur if q ∈ [-27, 55]. The upper bound of q
+        // is 55 because 5^55 < 2^128, however, this can only happen if 5^q > 2^64,
+        // since otherwise the product can be represented in 64-bits, producing
+        // an exact result. For negative exponents, rounding-to-even can
+        // only occur if 5^-q < 2^64.
+        //
+        // For detailed explanations of rounding for negative exponents, see
+        // <https://arxiv.org/pdf/2101.11408.pdf#section.9.1>. For detailed
+        // explanations of rounding for positive exponents, see
+        // <https://arxiv.org/pdf/2101.11408.pdf#section.8>.
+        let inside_safe_exponent = (q >= -27) && (q <= 55);
+        if !inside_safe_exponent {
+            return fp_error;
+        }
+    }
+    let upperbit = (hi >> 63) as i32;
+    let mut mantissa = hi >> (upperbit + 64 - F::MANTISSA_EXPLICIT_BITS as i32 - 3);
+    let mut power2 = power(q as i32) + upperbit - lz as i32 - F::MINIMUM_EXPONENT;
+    if power2 <= 0 {
+        if -power2 + 1 >= 64 {
+            // Have more than 64 bits below the minimum exponent, must be 0.
+            return fp_zero;
+        }
+        // Have a subnormal value.
+        mantissa >>= -power2 + 1;
+        mantissa += mantissa & 1;
+        mantissa >>= 1;
+        power2 = (mantissa >= (1_u64 << F::MANTISSA_EXPLICIT_BITS)) as i32;
+        return BiasedFp { f: mantissa, e: power2 };
+    }
+    // Need to handle rounding ties. Normally, we need to round up,
+    // but if we fall right in between and and we have an even basis, we
+    // need to round down.
+    //
+    // This will only occur if:
+    //  1. The lower 64 bits of the 128-bit representation is 0.
+    //      IE, 5^q fits in single 64-bit word.
+    //  2. The least-significant bit prior to truncated mantissa is odd.
+    //  3. All the bits truncated when shifting to mantissa bits + 1 are 0.
+    //
+    // Or, we may fall between two floats: we are exactly halfway.
+    if lo <= 1
+        && q >= F::MIN_EXPONENT_ROUND_TO_EVEN as i64
+        && q <= F::MAX_EXPONENT_ROUND_TO_EVEN as i64
+        && mantissa & 3 == 1
+        && (mantissa << (upperbit + 64 - F::MANTISSA_EXPLICIT_BITS as i32 - 3)) == hi
+    {
+        // Zero the lowest bit, so we don't round up.
+        mantissa &= !1_u64;
+    }
+    // Round-to-even, then shift the significant digits into place.
+    mantissa += mantissa & 1;
+    mantissa >>= 1;
+    if mantissa >= (2_u64 << F::MANTISSA_EXPLICIT_BITS) {
+        // Rounding up overflowed, so the carry bit is set. Set the
+        // mantissa to 1 (only the implicit, hidden bit is set) and
+        // increase the exponent.
+        mantissa = 1_u64 << F::MANTISSA_EXPLICIT_BITS;
+        power2 += 1;
+    }
+    // Zero out the hidden bit.
+    mantissa &= !(1_u64 << F::MANTISSA_EXPLICIT_BITS);
+    if power2 >= F::INFINITE_POWER {
+        // Exponent is above largest normal value, must be infinite.
+        return fp_inf;
+    }
+    BiasedFp { f: mantissa, e: power2 }
+}
+
+/// Calculate a base 2 exponent from a decimal exponent.
+/// This uses a pre-computed integer approximation for
+/// log2(10), where 217706 / 2^16 is accurate for the
+/// entire range of non-finite decimal exponents.
+fn power(q: i32) -> i32 {
+    (q.wrapping_mul(152_170 + 65536) >> 16) + 63
+}
+
+fn full_multiplication(a: u64, b: u64) -> (u64, u64) {
+    let r = (a as u128) * (b as u128);
+    (r as u64, (r >> 64) as u64)
+}
+
+// This will compute or rather approximate w * 5**q and return a pair of 64-bit words
+// approximating the result, with the "high" part corresponding to the most significant
+// bits and the low part corresponding to the least significant bits.
+fn compute_product_approx(q: i64, w: u64, precision: usize) -> (u64, u64) {
+    debug_assert!(q >= SMALLEST_POWER_OF_FIVE as i64);
+    debug_assert!(q <= LARGEST_POWER_OF_FIVE as i64);
+    debug_assert!(precision <= 64);
+
+    let mask = if precision < 64 {
+        0xFFFF_FFFF_FFFF_FFFF_u64 >> precision
+    } else {
+        0xFFFF_FFFF_FFFF_FFFF_u64
+    };
+
+    // 5^q < 2^64, then the multiplication always provides an exact value.
+    // That means whenever we need to round ties to even, we always have
+    // an exact value.
+    let index = (q - SMALLEST_POWER_OF_FIVE as i64) as usize;
+    let (lo5, hi5) = POWER_OF_FIVE_128[index];
+    // Only need one multiplication as long as there is 1 zero but
+    // in the explicit mantissa bits, +1 for the hidden bit, +1 to
+    // determine the rounding direction, +1 for if the computed
+    // product has a leading zero.
+    let (mut first_lo, mut first_hi) = full_multiplication(w, lo5);
+    if first_hi & mask == mask {
+        // Need to do a second multiplication to get better precision
+        // for the lower product. This will always be exact
+        // where q is < 55, since 5^55 < 2^128. If this wraps,
+        // then we need to need to round up the hi product.
+        let (_, second_hi) = full_multiplication(w, hi5);
+        first_lo = first_lo.wrapping_add(second_hi);
+        if second_hi > first_lo {
+            first_hi += 1;
+        }
+    }
+    (first_lo, first_hi)
+}
index f008a64ffe653a6bf687cba4d0047da8bed45336..c78492f5ae2c9ae0702f5ac06ac3c7de0647456b 100644 (file)
 //!
 //! We then try a long chain of progressively more general and expensive special cases using
 //! machine-sized integers and small, fixed-sized floating point numbers (first `f32`/`f64`, then
-//! a type with 64 bit significand, `Fp`). When all these fail, we bite the bullet and resort to a
-//! simple but very slow algorithm that involved computing `f * 10^e` fully and doing an iterative
-//! search for the best approximation.
-//!
-//! Primarily, this module and its children implement the algorithms described in:
-//! "How to Read Floating Point Numbers Accurately" by William D. Clinger,
-//! available online: <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.45.4152>
-//!
-//! In addition, there are numerous helper functions that are used in the paper but not available
-//! in Rust (or at least in core). Our version is additionally complicated by the need to handle
-//! overflow and underflow and the desire to handle subnormal numbers. Bellerophon and
-//! Algorithm R have trouble with overflow, subnormals, and underflow. We conservatively switch to
-//! Algorithm M (with the modifications described in section 8 of the paper) well before the
-//! inputs get into the critical region.
+//! a type with 64 bit significand). The extended-precision algorithm
+//! uses the Eisel-Lemire algorithm, which uses a 128-bit (or 192-bit)
+//! representation that can accurately and quickly compute the vast majority
+//! of floats. When all these fail, we bite the bullet and resort to using
+//! a large-decimal representation, shifting the digits into range, calculating
+//! the upper significant bits and exactly round to the nearest representation.
 //!
 //! Another aspect that needs attention is the ``RawFloat`` trait by which almost all functions
 //! are parametrized. One might think that it's enough to parse to `f64` and cast the result to
 //! operations as well, if you want 0.5 ULP accuracy you need to do *everything* in full precision
 //! and round *exactly once, at the end*, by considering all truncated bits at once.
 //!
-//! FIXME: Although some code duplication is necessary, perhaps parts of the code could be shuffled
-//! around such that less code is duplicated. Large parts of the algorithms are independent of the
-//! float type to output, or only needs access to a few constants, which could be passed in as
-//! parameters.
+//! Primarily, this module and its children implement the algorithms described in:
+//! "Number Parsing at a Gigabyte per Second", available online:
+//! <https://arxiv.org/abs/2101.11408>.
 //!
 //! # Other
 //!
 use crate::fmt;
 use crate::str::FromStr;
 
-use self::num::digits_to_big;
-use self::parse::{parse_decimal, Decimal, ParseResult, Sign};
-use self::rawfp::RawFloat;
+use self::common::{BiasedFp, ByteSlice};
+use self::float::RawFloat;
+use self::lemire::compute_float;
+use self::parse::{parse_inf_nan, parse_number};
+use self::slow::parse_long_mantissa;
 
-mod algorithm;
-mod num;
+mod common;
+mod decimal;
+mod fpu;
+mod slow;
 mod table;
-// These two have their own tests.
+// float is used in flt2dec, and all are used in unit tests.
+pub mod float;
+pub mod lemire;
+pub mod number;
 pub mod parse;
-pub mod rawfp;
 
 macro_rules! from_str_float_impl {
     ($t:ty) => {
@@ -136,13 +133,6 @@ macro_rules! from_str_float_impl {
             ///
             /// [EBNF]: https://www.w3.org/TR/REC-xml/#sec-notation
             ///
-            /// # Known bugs
-            ///
-            /// In some situations, some strings that should create a valid float
-            /// instead return an error. See [issue #31407] for details.
-            ///
-            /// [issue #31407]: https://github.com/rust-lang/rust/issues/31407
-            ///
             /// # Arguments
             ///
             /// * src - A string
@@ -211,148 +201,70 @@ impl fmt::Display for ParseFloatError {
     }
 }
 
-fn pfe_empty() -> ParseFloatError {
+pub(super) fn pfe_empty() -> ParseFloatError {
     ParseFloatError { kind: FloatErrorKind::Empty }
 }
 
-fn pfe_invalid() -> ParseFloatError {
+// Used in unit tests, keep public.
+// This is much better than making FloatErrorKind and ParseFloatError::kind public.
+pub fn pfe_invalid() -> ParseFloatError {
     ParseFloatError { kind: FloatErrorKind::Invalid }
 }
 
-/// Splits a decimal string into sign and the rest, without inspecting or validating the rest.
-fn extract_sign(s: &str) -> (Sign, &str) {
-    match s.as_bytes()[0] {
-        b'+' => (Sign::Positive, &s[1..]),
-        b'-' => (Sign::Negative, &s[1..]),
-        // If the string is invalid, we never use the sign, so we don't need to validate here.
-        _ => (Sign::Positive, s),
-    }
+/// Converts a `BiasedFp` to the closest machine float type.
+fn biased_fp_to_float<T: RawFloat>(x: BiasedFp) -> T {
+    let mut word = x.f;
+    word |= (x.e as u64) << T::MANTISSA_EXPLICIT_BITS;
+    T::from_u64_bits(word)
 }
 
 /// Converts a decimal string into a floating point number.
-fn dec2flt<T: RawFloat>(s: &str) -> Result<T, ParseFloatError> {
-    if s.is_empty() {
+pub fn dec2flt<F: RawFloat>(s: &str) -> Result<F, ParseFloatError> {
+    let mut s = s.as_bytes();
+    let c = if let Some(&c) = s.first() {
+        c
+    } else {
         return Err(pfe_empty());
+    };
+    let negative = c == b'-';
+    if c == b'-' || c == b'+' {
+        s = s.advance(1);
+    }
+    if s.is_empty() {
+        return Err(pfe_invalid());
     }
-    let (sign, s) = extract_sign(s);
-    let flt = match parse_decimal(s) {
-        ParseResult::Valid(decimal) => convert(decimal)?,
-        ParseResult::ShortcutToInf => T::INFINITY,
-        ParseResult::ShortcutToZero => T::ZERO,
-        ParseResult::Invalid => {
-            if s.eq_ignore_ascii_case("nan") {
-                T::NAN
-            } else if s.eq_ignore_ascii_case("inf") || s.eq_ignore_ascii_case("infinity") {
-                T::INFINITY
+
+    let num = match parse_number(s, negative) {
+        Some(r) => r,
+        None => {
+            if let Some(value) = parse_inf_nan(s, negative) {
+                return Ok(value);
             } else {
                 return Err(pfe_invalid());
             }
         }
     };
-
-    match sign {
-        Sign::Positive => Ok(flt),
-        Sign::Negative => Ok(-flt),
+    if let Some(value) = num.try_fast_path::<F>() {
+        return Ok(value);
     }
-}
-
-/// The main workhorse for the decimal-to-float conversion: Orchestrate all the preprocessing
-/// and figure out which algorithm should do the actual conversion.
-fn convert<T: RawFloat>(mut decimal: Decimal<'_>) -> Result<T, ParseFloatError> {
-    simplify(&mut decimal);
-    if let Some(x) = trivial_cases(&decimal) {
-        return Ok(x);
-    }
-    // Remove/shift out the decimal point.
-    let e = decimal.exp - decimal.fractional.len() as i64;
-    if let Some(x) = algorithm::fast_path(decimal.integral, decimal.fractional, e) {
-        return Ok(x);
-    }
-    // Big32x40 is limited to 1280 bits, which translates to about 385 decimal digits.
-    // If we exceed this, we'll crash, so we error out before getting too close (within 10^10).
-    let upper_bound = bound_intermediate_digits(&decimal, e);
-    if upper_bound > 375 {
-        return Err(pfe_invalid());
-    }
-    let f = digits_to_big(decimal.integral, decimal.fractional);
-
-    // Now the exponent certainly fits in 16 bit, which is used throughout the main algorithms.
-    let e = e as i16;
-    // FIXME These bounds are rather conservative. A more careful analysis of the failure modes
-    // of Bellerophon could allow using it in more cases for a massive speed up.
-    let exponent_in_range = table::MIN_E <= e && e <= table::MAX_E;
-    let value_in_range = upper_bound <= T::MAX_NORMAL_DIGITS as u64;
-    if exponent_in_range && value_in_range {
-        Ok(algorithm::bellerophon(&f, e))
-    } else {
-        Ok(algorithm::algorithm_m(&f, e))
-    }
-}
 
-// As written, this optimizes badly (see #27130, though it refers to an old version of the code).
-// `inline(always)` is a workaround for that. There are only two call sites overall and it doesn't
-// make code size worse.
-
-/// Strip zeros where possible, even when this requires changing the exponent
-#[inline(always)]
-fn simplify(decimal: &mut Decimal<'_>) {
-    let is_zero = &|&&d: &&u8| -> bool { d == b'0' };
-    // Trimming these zeros does not change anything but may enable the fast path (< 15 digits).
-    let leading_zeros = decimal.integral.iter().take_while(is_zero).count();
-    decimal.integral = &decimal.integral[leading_zeros..];
-    let trailing_zeros = decimal.fractional.iter().rev().take_while(is_zero).count();
-    let end = decimal.fractional.len() - trailing_zeros;
-    decimal.fractional = &decimal.fractional[..end];
-    // Simplify numbers of the form 0.0...x and x...0.0, adjusting the exponent accordingly.
-    // This may not always be a win (possibly pushes some numbers out of the fast path), but it
-    // simplifies other parts significantly (notably, approximating the magnitude of the value).
-    if decimal.integral.is_empty() {
-        let leading_zeros = decimal.fractional.iter().take_while(is_zero).count();
-        decimal.fractional = &decimal.fractional[leading_zeros..];
-        decimal.exp -= leading_zeros as i64;
-    } else if decimal.fractional.is_empty() {
-        let trailing_zeros = decimal.integral.iter().rev().take_while(is_zero).count();
-        let end = decimal.integral.len() - trailing_zeros;
-        decimal.integral = &decimal.integral[..end];
-        decimal.exp += trailing_zeros as i64;
+    // If significant digits were truncated, then we can have rounding error
+    // only if `mantissa + 1` produces a different result. We also avoid
+    // redundantly using the Eisel-Lemire algorithm if it was unable to
+    // correctly round on the first pass.
+    let mut fp = compute_float::<F>(num.exponent, num.mantissa);
+    if num.many_digits && fp.e >= 0 && fp != compute_float::<F>(num.exponent, num.mantissa + 1) {
+        fp.e = -1;
     }
-}
-
-/// Returns a quick-an-dirty upper bound on the size (log10) of the largest value that Algorithm R
-/// and Algorithm M will compute while working on the given decimal.
-fn bound_intermediate_digits(decimal: &Decimal<'_>, e: i64) -> u64 {
-    // We don't need to worry too much about overflow here thanks to trivial_cases() and the
-    // parser, which filter out the most extreme inputs for us.
-    let f_len: u64 = decimal.integral.len() as u64 + decimal.fractional.len() as u64;
-    if e >= 0 {
-        // In the case e >= 0, both algorithms compute about `f * 10^e`. Algorithm R proceeds to
-        // do some complicated calculations with this but we can ignore that for the upper bound
-        // because it also reduces the fraction beforehand, so we have plenty of buffer there.
-        f_len + (e as u64)
-    } else {
-        // If e < 0, Algorithm R does roughly the same thing, but Algorithm M differs:
-        // It tries to find a positive number k such that `f << k / 10^e` is an in-range
-        // significand. This will result in about `2^53 * f * 10^e` < `10^17 * f * 10^e`.
-        // One input that triggers this is 0.33...33 (375 x 3).
-        f_len + e.unsigned_abs() + 17
+    // Unable to correctly round the float using the Eisel-Lemire algorithm.
+    // Fallback to a slower, but always correct algorithm.
+    if fp.e < 0 {
+        fp = parse_long_mantissa::<F>(s);
     }
-}
 
-/// Detects obvious overflows and underflows without even looking at the decimal digits.
-fn trivial_cases<T: RawFloat>(decimal: &Decimal<'_>) -> Option<T> {
-    // There were zeros but they were stripped by simplify()
-    if decimal.integral.is_empty() && decimal.fractional.is_empty() {
-        return Some(T::ZERO);
-    }
-    // This is a crude approximation of ceil(log10(the real value)). We don't need to worry too
-    // much about overflow here because the input length is tiny (at least compared to 2^64) and
-    // the parser already handles exponents whose absolute value is greater than 10^18
-    // (which is still 10^19 short of 2^64).
-    let max_place = decimal.exp + decimal.integral.len() as i64;
-    if max_place > T::INF_CUTOFF {
-        return Some(T::INFINITY);
-    } else if max_place < T::ZERO_CUTOFF {
-        return Some(T::ZERO);
+    let mut float = biased_fp_to_float::<F>(fp);
+    if num.negative {
+        float = -float;
     }
-    None
+    Ok(float)
 }
diff --git a/library/core/src/num/dec2flt/num.rs b/library/core/src/num/dec2flt/num.rs
deleted file mode 100644 (file)
index 208783d..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-//! Utility functions for bignums that don't make too much sense to turn into methods.
-
-// FIXME This module's name is a bit unfortunate, since other modules also import `core::num`.
-
-use crate::cmp::Ordering::{self, Equal, Greater, Less};
-
-pub use crate::num::bignum::Big32x40 as Big;
-
-/// Test whether truncating all bits less significant than `ones_place` introduces
-/// a relative error less, equal, or greater than 0.5 ULP.
-pub fn compare_with_half_ulp(f: &Big, ones_place: usize) -> Ordering {
-    if ones_place == 0 {
-        return Less;
-    }
-    let half_bit = ones_place - 1;
-    if f.get_bit(half_bit) == 0 {
-        // < 0.5 ULP
-        return Less;
-    }
-    // If all remaining bits are zero, it's = 0.5 ULP, otherwise > 0.5
-    // If there are no more bits (half_bit == 0), the below also correctly returns Equal.
-    for i in 0..half_bit {
-        if f.get_bit(i) == 1 {
-            return Greater;
-        }
-    }
-    Equal
-}
-
-/// Converts an ASCII string containing only decimal digits to a `u64`.
-///
-/// Does not perform checks for overflow or invalid characters, so if the caller is not careful,
-/// the result is bogus and can panic (though it won't be `unsafe`). Additionally, empty strings
-/// are treated as zero. This function exists because
-///
-/// 1. using `FromStr` on `&[u8]` requires `from_utf8_unchecked`, which is bad, and
-/// 2. piecing together the results of `integral.parse()` and `fractional.parse()` is
-///    more complicated than this entire function.
-pub fn from_str_unchecked<'a, T>(bytes: T) -> u64
-where
-    T: IntoIterator<Item = &'a u8>,
-{
-    let mut result = 0;
-    for &c in bytes {
-        result = result * 10 + (c - b'0') as u64;
-    }
-    result
-}
-
-/// Converts a string of ASCII digits into a bignum.
-///
-/// Like `from_str_unchecked`, this function relies on the parser to weed out non-digits.
-pub fn digits_to_big(integral: &[u8], fractional: &[u8]) -> Big {
-    let mut f = Big::from_small(0);
-    for &c in integral.iter().chain(fractional) {
-        let n = (c - b'0') as u32;
-        f.mul_small(10);
-        f.add_small(n);
-    }
-    f
-}
-
-/// Unwraps a bignum into a 64 bit integer. Panics if the number is too large.
-pub fn to_u64(x: &Big) -> u64 {
-    assert!(x.bit_length() < 64);
-    let d = x.digits();
-    if d.len() < 2 { d[0] as u64 } else { (d[1] as u64) << 32 | d[0] as u64 }
-}
-
-/// Extracts a range of bits.
-
-/// Index 0 is the least significant bit and the range is half-open as usual.
-/// Panics if asked to extract more bits than fit into the return type.
-pub fn get_bits(x: &Big, start: usize, end: usize) -> u64 {
-    assert!(end - start <= 64);
-    let mut result: u64 = 0;
-    for i in (start..end).rev() {
-        result = result << 1 | x.get_bit(i) as u64;
-    }
-    result
-}
diff --git a/library/core/src/num/dec2flt/number.rs b/library/core/src/num/dec2flt/number.rs
new file mode 100644 (file)
index 0000000..3643271
--- /dev/null
@@ -0,0 +1,86 @@
+//! Representation of a float as the significant digits and exponent.
+
+use crate::num::dec2flt::float::RawFloat;
+use crate::num::dec2flt::fpu::set_precision;
+
+#[rustfmt::skip]
+const INT_POW10: [u64; 16] = [
+    1,
+    10,
+    100,
+    1000,
+    10000,
+    100000,
+    1000000,
+    10000000,
+    100000000,
+    1000000000,
+    10000000000,
+    100000000000,
+    1000000000000,
+    10000000000000,
+    100000000000000,
+    1000000000000000,
+];
+
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
+pub struct Number {
+    pub exponent: i64,
+    pub mantissa: u64,
+    pub negative: bool,
+    pub many_digits: bool,
+}
+
+impl Number {
+    /// Detect if the float can be accurately reconstructed from native floats.
+    fn is_fast_path<F: RawFloat>(&self) -> bool {
+        F::MIN_EXPONENT_FAST_PATH <= self.exponent
+            && self.exponent <= F::MAX_EXPONENT_DISGUISED_FAST_PATH
+            && self.mantissa <= F::MAX_MANTISSA_FAST_PATH
+            && !self.many_digits
+    }
+
+    /// The fast path algorithmn using machine-sized integers and floats.
+    ///
+    /// This is extracted into a separate function so that it can be attempted before constructing
+    /// a Decimal. This only works if both the mantissa and the exponent
+    /// can be exactly represented as a machine float, since IEE-754 guarantees
+    /// no rounding will occur.
+    ///
+    /// There is an exception: disguised fast-path cases, where we can shift
+    /// powers-of-10 from the exponent to the significant digits.
+    pub fn try_fast_path<F: RawFloat>(&self) -> Option<F> {
+        // The fast path crucially depends on arithmetic being rounded to the correct number of bits
+        // without any intermediate rounding. On x86 (without SSE or SSE2) this requires the precision
+        // of the x87 FPU stack to be changed so that it directly rounds to 64/32 bit.
+        // The `set_precision` function takes care of setting the precision on architectures which
+        // require setting it by changing the global state (like the control word of the x87 FPU).
+        let _cw = set_precision::<F>();
+
+        if self.is_fast_path::<F>() {
+            let mut value = if self.exponent <= F::MAX_EXPONENT_FAST_PATH {
+                // normal fast path
+                let value = F::from_u64(self.mantissa);
+                if self.exponent < 0 {
+                    value / F::pow10_fast_path((-self.exponent) as _)
+                } else {
+                    value * F::pow10_fast_path(self.exponent as _)
+                }
+            } else {
+                // disguised fast path
+                let shift = self.exponent - F::MAX_EXPONENT_FAST_PATH;
+                let mantissa = self.mantissa.checked_mul(INT_POW10[shift as usize])?;
+                if mantissa > F::MAX_MANTISSA_FAST_PATH {
+                    return None;
+                }
+                F::from_u64(mantissa) * F::pow10_fast_path(F::MAX_EXPONENT_FAST_PATH as _)
+            };
+            if self.negative {
+                value = -value;
+            }
+            Some(value)
+        } else {
+            None
+        }
+    }
+}
index 858cc3c9b014693998d9f5fc7dc47bf90cb26328..fa677bf5123959820054064cf58abb580dcfd3f1 100644 (file)
-//! Validating and decomposing a decimal string of the form:
-//!
-//! `(digits | digits? '.'? digits?) (('e' | 'E') ('+' | '-')? digits)?`
-//!
-//! In other words, standard floating-point syntax, with two exceptions: No sign, and no
-//! handling of "inf" and "NaN". These are handled by the driver function (super::dec2flt).
-//!
-//! Although recognizing valid inputs is relatively easy, this module also has to reject the
-//! countless invalid variations, never panic, and perform numerous checks that the other
-//! modules rely on to not panic (or overflow) in turn.
-//! To make matters worse, all that happens in a single pass over the input.
-//! So, be careful when modifying anything, and double-check with the other modules.
-use self::ParseResult::{Invalid, ShortcutToInf, ShortcutToZero, Valid};
-use super::num;
-
-#[derive(Debug)]
-pub enum Sign {
-    Positive,
-    Negative,
+//! Functions to parse floating-point numbers.
+
+use crate::num::dec2flt::common::{is_8digits, AsciiStr, ByteSlice};
+use crate::num::dec2flt::float::RawFloat;
+use crate::num::dec2flt::number::Number;
+
+const MIN_19DIGIT_INT: u64 = 100_0000_0000_0000_0000;
+
+/// Parse 8 digits, loaded as bytes in little-endian order.
+///
+/// This uses the trick where every digit is in [0x030, 0x39],
+/// and therefore can be parsed in 3 multiplications, much
+/// faster than the normal 8.
+///
+/// This is based off the algorithm described in "Fast numeric string to
+/// int", available here: <https://johnnylee-sde.github.io/Fast-numeric-string-to-int/>.
+fn parse_8digits(mut v: u64) -> u64 {
+    const MASK: u64 = 0x0000_00FF_0000_00FF;
+    const MUL1: u64 = 0x000F_4240_0000_0064;
+    const MUL2: u64 = 0x0000_2710_0000_0001;
+    v -= 0x3030_3030_3030_3030;
+    v = (v * 10) + (v >> 8); // will not overflow, fits in 63 bits
+    let v1 = (v & MASK).wrapping_mul(MUL1);
+    let v2 = ((v >> 16) & MASK).wrapping_mul(MUL2);
+    ((v1.wrapping_add(v2) >> 32) as u32) as u64
 }
 
-#[derive(Debug, PartialEq, Eq)]
-/// The interesting parts of a decimal string.
-pub struct Decimal<'a> {
-    pub integral: &'a [u8],
-    pub fractional: &'a [u8],
-    /// The decimal exponent, guaranteed to have fewer than 18 decimal digits.
-    pub exp: i64,
+/// Parse digits until a non-digit character is found.
+fn try_parse_digits(s: &mut AsciiStr<'_>, x: &mut u64) {
+    // may cause overflows, to be handled later
+    s.parse_digits(|digit| {
+        *x = x.wrapping_mul(10).wrapping_add(digit as _);
+    });
 }
 
-impl<'a> Decimal<'a> {
-    pub fn new(integral: &'a [u8], fractional: &'a [u8], exp: i64) -> Decimal<'a> {
-        Decimal { integral, fractional, exp }
+/// Parse up to 19 digits (the max that can be stored in a 64-bit integer).
+fn try_parse_19digits(s: &mut AsciiStr<'_>, x: &mut u64) {
+    while *x < MIN_19DIGIT_INT {
+        if let Some(&c) = s.as_ref().first() {
+            let digit = c.wrapping_sub(b'0');
+            if digit < 10 {
+                *x = (*x * 10) + digit as u64; // no overflows here
+                // SAFETY: cannot be empty
+                unsafe {
+                    s.step();
+                }
+            } else {
+                break;
+            }
+        } else {
+            break;
+        }
     }
 }
 
-#[derive(Debug, PartialEq, Eq)]
-pub enum ParseResult<'a> {
-    Valid(Decimal<'a>),
-    ShortcutToInf,
-    ShortcutToZero,
-    Invalid,
+/// Try to parse 8 digits at a time, using an optimized algorithm.
+fn try_parse_8digits(s: &mut AsciiStr<'_>, x: &mut u64) {
+    // may cause overflows, to be handled later
+    if let Some(v) = s.read_u64() {
+        if is_8digits(v) {
+            *x = x.wrapping_mul(1_0000_0000).wrapping_add(parse_8digits(v));
+            // SAFETY: already ensured the buffer was >= 8 bytes in read_u64.
+            unsafe {
+                s.step_by(8);
+            }
+            if let Some(v) = s.read_u64() {
+                if is_8digits(v) {
+                    *x = x.wrapping_mul(1_0000_0000).wrapping_add(parse_8digits(v));
+                    // SAFETY: already ensured the buffer was >= 8 bytes in try_read_u64.
+                    unsafe {
+                        s.step_by(8);
+                    }
+                }
+            }
+        }
+    }
 }
 
-/// Checks if the input string is a valid floating point number and if so, locate the integral
-/// part, the fractional part, and the exponent in it. Does not handle signs.
-pub fn parse_decimal(s: &str) -> ParseResult<'_> {
-    if s.is_empty() {
-        return Invalid;
+/// Parse the scientific notation component of a float.
+fn parse_scientific(s: &mut AsciiStr<'_>) -> Option<i64> {
+    let mut exponent = 0_i64;
+    let mut negative = false;
+    if let Some(&c) = s.as_ref().get(0) {
+        negative = c == b'-';
+        if c == b'-' || c == b'+' {
+            // SAFETY: s cannot be empty
+            unsafe {
+                s.step();
+            }
+        }
     }
+    if s.first_isdigit() {
+        s.parse_digits(|digit| {
+            // no overflows here, saturate well before overflow
+            if exponent < 0x10000 {
+                exponent = 10 * exponent + digit as i64;
+            }
+        });
+        if negative { Some(-exponent) } else { Some(exponent) }
+    } else {
+        None
+    }
+}
 
-    let s = s.as_bytes();
-    let (integral, s) = eat_digits(s);
+/// Parse a partial, non-special floating point number.
+///
+/// This creates a representation of the float as the
+/// significant digits and the decimal exponent.
+fn parse_partial_number(s: &[u8], negative: bool) -> Option<(Number, usize)> {
+    let mut s = AsciiStr::new(s);
+    let start = s;
+    debug_assert!(!s.is_empty());
 
-    match s.first() {
-        None => Valid(Decimal::new(integral, b"", 0)),
-        Some(&b'e' | &b'E') => {
-            if integral.is_empty() {
-                return Invalid; // No digits before 'e'
-            }
+    // parse initial digits before dot
+    let mut mantissa = 0_u64;
+    let digits_start = s;
+    try_parse_digits(&mut s, &mut mantissa);
+    let mut n_digits = s.offset_from(&digits_start);
+
+    // handle dot with the following digits
+    let mut n_after_dot = 0;
+    let mut exponent = 0_i64;
+    let int_end = s;
+    if s.first_is(b'.') {
+        // SAFETY: s cannot be empty due to first_is
+        unsafe { s.step() };
+        let before = s;
+        try_parse_8digits(&mut s, &mut mantissa);
+        try_parse_digits(&mut s, &mut mantissa);
+        n_after_dot = s.offset_from(&before);
+        exponent = -n_after_dot as i64;
+    }
 
-            parse_exp(integral, b"", &s[1..])
+    n_digits += n_after_dot;
+    if n_digits == 0 {
+        return None;
+    }
+
+    // handle scientific format
+    let mut exp_number = 0_i64;
+    if s.first_is2(b'e', b'E') {
+        // SAFETY: s cannot be empty
+        unsafe {
+            s.step();
         }
-        Some(&b'.') => {
-            let (fractional, s) = eat_digits(&s[1..]);
-            if integral.is_empty() && fractional.is_empty() {
-                // We require at least a single digit before or after the point.
-                return Invalid;
-            }
+        // If None, we have no trailing digits after exponent, or an invalid float.
+        exp_number = parse_scientific(&mut s)?;
+        exponent += exp_number;
+    }
 
-            match s.first() {
-                None => Valid(Decimal::new(integral, fractional, 0)),
-                Some(&b'e' | &b'E') => parse_exp(integral, fractional, &s[1..]),
-                _ => Invalid, // Trailing junk after fractional part
-            }
+    let len = s.offset_from(&start) as _;
+
+    // handle uncommon case with many digits
+    if n_digits <= 19 {
+        return Some((Number { exponent, mantissa, negative, many_digits: false }, len));
+    }
+
+    n_digits -= 19;
+    let mut many_digits = false;
+    let mut p = digits_start;
+    while p.first_is2(b'0', b'.') {
+        // SAFETY: p cannot be empty due to first_is2
+        unsafe {
+            // '0' = b'.' + 2
+            n_digits -= p.first_unchecked().saturating_sub(b'0' - 1) as isize;
+            p.step();
         }
-        _ => Invalid, // Trailing junk after first digit string
     }
-}
+    if n_digits > 0 {
+        // at this point we have more than 19 significant digits, let's try again
+        many_digits = true;
+        mantissa = 0;
+        let mut s = digits_start;
+        try_parse_19digits(&mut s, &mut mantissa);
+        exponent = if mantissa >= MIN_19DIGIT_INT {
+            // big int
+            int_end.offset_from(&s)
+        } else {
+            // SAFETY: the next byte must be present and be '.'
+            // We know this is true because we had more than 19
+            // digits previously, so we overflowed a 64-bit integer,
+            // but parsing only the integral digits produced less
+            // than 19 digits. That means we must have a decimal
+            // point, and at least 1 fractional digit.
+            unsafe { s.step() };
+            let before = s;
+            try_parse_19digits(&mut s, &mut mantissa);
+            -s.offset_from(&before)
+        } as i64;
+        // add back the explicit part
+        exponent += exp_number;
+    }
 
-/// Carves off decimal digits up to the first non-digit character.
-fn eat_digits(s: &[u8]) -> (&[u8], &[u8]) {
-    let pos = s.iter().position(|c| !c.is_ascii_digit()).unwrap_or(s.len());
-    s.split_at(pos)
+    Some((Number { exponent, mantissa, negative, many_digits }, len))
 }
 
-/// Exponent extraction and error checking.
-fn parse_exp<'a>(integral: &'a [u8], fractional: &'a [u8], rest: &'a [u8]) -> ParseResult<'a> {
-    let (sign, rest) = match rest.first() {
-        Some(&b'-') => (Sign::Negative, &rest[1..]),
-        Some(&b'+') => (Sign::Positive, &rest[1..]),
-        _ => (Sign::Positive, rest),
-    };
-    let (mut number, trailing) = eat_digits(rest);
-    if !trailing.is_empty() {
-        return Invalid; // Trailing junk after exponent
+/// Try to parse a non-special floating point number.
+pub fn parse_number(s: &[u8], negative: bool) -> Option<Number> {
+    if let Some((float, rest)) = parse_partial_number(s, negative) {
+        if rest == s.len() {
+            return Some(float);
+        }
     }
-    if number.is_empty() {
-        return Invalid; // Empty exponent
+    None
+}
+
+/// Parse a partial representation of a special, non-finite float.
+fn parse_partial_inf_nan<F: RawFloat>(s: &[u8]) -> Option<(F, usize)> {
+    fn parse_inf_rest(s: &[u8]) -> usize {
+        if s.len() >= 8 && s[3..].as_ref().eq_ignore_case(b"inity") { 8 } else { 3 }
     }
-    // At this point, we certainly have a valid string of digits. It may be too long to put into
-    // an `i64`, but if it's that huge, the input is certainly zero or infinity. Since each zero
-    // in the decimal digits only adjusts the exponent by +/- 1, at exp = 10^18 the input would
-    // have to be 17 exabyte (!) of zeros to get even remotely close to being finite.
-    // This is not exactly a use case we need to cater to.
-    while number.first() == Some(&b'0') {
-        number = &number[1..];
+    if s.len() >= 3 {
+        if s.eq_ignore_case(b"nan") {
+            return Some((F::NAN, 3));
+        } else if s.eq_ignore_case(b"inf") {
+            return Some((F::INFINITY, parse_inf_rest(s)));
+        }
     }
-    if number.len() >= 18 {
-        return match sign {
-            Sign::Positive => ShortcutToInf,
-            Sign::Negative => ShortcutToZero,
-        };
+    None
+}
+
+/// Try to parse a special, non-finite float.
+pub fn parse_inf_nan<F: RawFloat>(s: &[u8], negative: bool) -> Option<F> {
+    if let Some((mut float, rest)) = parse_partial_inf_nan::<F>(s) {
+        if rest == s.len() {
+            if negative {
+                float = -float;
+            }
+            return Some(float);
+        }
     }
-    let abs_exp = num::from_str_unchecked(number);
-    let e = match sign {
-        Sign::Positive => abs_exp as i64,
-        Sign::Negative => -(abs_exp as i64),
-    };
-    Valid(Decimal::new(integral, fractional, e))
+    None
 }
diff --git a/library/core/src/num/dec2flt/rawfp.rs b/library/core/src/num/dec2flt/rawfp.rs
deleted file mode 100644 (file)
index 0ab15b2..0000000
+++ /dev/null
@@ -1,363 +0,0 @@
-//! Bit fiddling on positive IEEE 754 floats. Negative numbers aren't and needn't be handled.
-//! Normal floating point numbers have a canonical representation as (frac, exp) such that the
-//! value is 2<sup>exp</sup> * (1 + sum(frac[N-i] / 2<sup>i</sup>)) where N is the number of bits.
-//! Subnormals are slightly different and weird, but the same principle applies.
-//!
-//! Here, however, we represent them as (sig, k) with f positive, such that the value is f *
-//! 2<sup>e</sup>. Besides making the "hidden bit" explicit, this changes the exponent by the
-//! so-called mantissa shift.
-//!
-//! Put another way, normally floats are written as (1) but here they are written as (2):
-//!
-//! 1. `1.101100...11 * 2^m`
-//! 2. `1101100...11 * 2^n`
-//!
-//! We call (1) the **fractional representation** and (2) the **integral representation**.
-//!
-//! Many functions in this module only handle normal numbers. The dec2flt routines conservatively
-//! take the universally-correct slow path (Algorithm M) for very small and very large numbers.
-//! That algorithm needs only next_float() which does handle subnormals and zeros.
-use crate::cmp::Ordering::{Equal, Greater, Less};
-use crate::convert::{TryFrom, TryInto};
-use crate::fmt::{Debug, LowerExp};
-use crate::num::dec2flt::num::{self, Big};
-use crate::num::dec2flt::table;
-use crate::num::diy_float::Fp;
-use crate::num::FpCategory;
-use crate::num::FpCategory::{Infinite, Nan, Normal, Subnormal, Zero};
-use crate::ops::{Add, Div, Mul, Neg};
-
-#[derive(Copy, Clone, Debug)]
-pub struct Unpacked {
-    pub sig: u64,
-    pub k: i16,
-}
-
-impl Unpacked {
-    pub fn new(sig: u64, k: i16) -> Self {
-        Unpacked { sig, k }
-    }
-}
-
-/// A helper trait to avoid duplicating basically all the conversion code for `f32` and `f64`.
-///
-/// See the parent module's doc comment for why this is necessary.
-///
-/// Should **never ever** be implemented for other types or be used outside the dec2flt module.
-pub trait RawFloat:
-    Copy + Debug + LowerExp + Mul<Output = Self> + Div<Output = Self> + Neg<Output = Self>
-{
-    const INFINITY: Self;
-    const NAN: Self;
-    const ZERO: Self;
-
-    /// Type used by `to_bits` and `from_bits`.
-    type Bits: Add<Output = Self::Bits> + From<u8> + TryFrom<u64>;
-
-    /// Performs a raw transmutation to an integer.
-    fn to_bits(self) -> Self::Bits;
-
-    /// Performs a raw transmutation from an integer.
-    fn from_bits(v: Self::Bits) -> Self;
-
-    /// Returns the category that this number falls into.
-    fn classify(self) -> FpCategory;
-
-    /// Returns the mantissa, exponent and sign as integers.
-    fn integer_decode(self) -> (u64, i16, i8);
-
-    /// Decodes the float.
-    fn unpack(self) -> Unpacked;
-
-    /// Casts from a small integer that can be represented exactly. Panic if the integer can't be
-    /// represented, the other code in this module makes sure to never let that happen.
-    fn from_int(x: u64) -> Self;
-
-    /// Gets the value 10<sup>e</sup> from a pre-computed table.
-    /// Panics for `e >= CEIL_LOG5_OF_MAX_SIG`.
-    fn short_fast_pow10(e: usize) -> Self;
-
-    /// What the name says. It's easier to hard code than juggling intrinsics and
-    /// hoping LLVM constant folds it.
-    const CEIL_LOG5_OF_MAX_SIG: i16;
-
-    // A conservative bound on the decimal digits of inputs that can't produce overflow or zero or
-    /// subnormals. Probably the decimal exponent of the maximum normal value, hence the name.
-    const MAX_NORMAL_DIGITS: usize;
-
-    /// When the most significant decimal digit has a place value greater than this, the number
-    /// is certainly rounded to infinity.
-    const INF_CUTOFF: i64;
-
-    /// When the most significant decimal digit has a place value less than this, the number
-    /// is certainly rounded to zero.
-    const ZERO_CUTOFF: i64;
-
-    /// The number of bits in the exponent.
-    const EXP_BITS: u8;
-
-    /// The number of bits in the significand, *including* the hidden bit.
-    const SIG_BITS: u8;
-
-    /// The number of bits in the significand, *excluding* the hidden bit.
-    const EXPLICIT_SIG_BITS: u8;
-
-    /// The maximum legal exponent in fractional representation.
-    const MAX_EXP: i16;
-
-    /// The minimum legal exponent in fractional representation, excluding subnormals.
-    const MIN_EXP: i16;
-
-    /// `MAX_EXP` for integral representation, i.e., with the shift applied.
-    const MAX_EXP_INT: i16;
-
-    /// `MAX_EXP` encoded (i.e., with offset bias)
-    const MAX_ENCODED_EXP: i16;
-
-    /// `MIN_EXP` for integral representation, i.e., with the shift applied.
-    const MIN_EXP_INT: i16;
-
-    /// The maximum normalized significand in integral representation.
-    const MAX_SIG: u64;
-
-    /// The minimal normalized significand in integral representation.
-    const MIN_SIG: u64;
-}
-
-// Mostly a workaround for #34344.
-macro_rules! other_constants {
-    ($type: ident) => {
-        const EXPLICIT_SIG_BITS: u8 = Self::SIG_BITS - 1;
-        const MAX_EXP: i16 = (1 << (Self::EXP_BITS - 1)) - 1;
-        const MIN_EXP: i16 = -<Self as RawFloat>::MAX_EXP + 1;
-        const MAX_EXP_INT: i16 = <Self as RawFloat>::MAX_EXP - (Self::SIG_BITS as i16 - 1);
-        const MAX_ENCODED_EXP: i16 = (1 << Self::EXP_BITS) - 1;
-        const MIN_EXP_INT: i16 = <Self as RawFloat>::MIN_EXP - (Self::SIG_BITS as i16 - 1);
-        const MAX_SIG: u64 = (1 << Self::SIG_BITS) - 1;
-        const MIN_SIG: u64 = 1 << (Self::SIG_BITS - 1);
-
-        const INFINITY: Self = $type::INFINITY;
-        const NAN: Self = $type::NAN;
-        const ZERO: Self = 0.0;
-    };
-}
-
-impl RawFloat for f32 {
-    type Bits = u32;
-
-    const SIG_BITS: u8 = 24;
-    const EXP_BITS: u8 = 8;
-    const CEIL_LOG5_OF_MAX_SIG: i16 = 11;
-    const MAX_NORMAL_DIGITS: usize = 35;
-    const INF_CUTOFF: i64 = 40;
-    const ZERO_CUTOFF: i64 = -48;
-    other_constants!(f32);
-
-    /// Returns the mantissa, exponent and sign as integers.
-    fn integer_decode(self) -> (u64, i16, i8) {
-        let bits = self.to_bits();
-        let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
-        let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
-        let mantissa =
-            if exponent == 0 { (bits & 0x7fffff) << 1 } else { (bits & 0x7fffff) | 0x800000 };
-        // Exponent bias + mantissa shift
-        exponent -= 127 + 23;
-        (mantissa as u64, exponent, sign)
-    }
-
-    fn unpack(self) -> Unpacked {
-        let (sig, exp, _sig) = self.integer_decode();
-        Unpacked::new(sig, exp)
-    }
-
-    fn from_int(x: u64) -> f32 {
-        // rkruppe is uncertain whether `as` rounds correctly on all platforms.
-        debug_assert!(x as f32 == fp_to_float(Fp { f: x, e: 0 }));
-        x as f32
-    }
-
-    fn short_fast_pow10(e: usize) -> Self {
-        table::F32_SHORT_POWERS[e]
-    }
-
-    fn classify(self) -> FpCategory {
-        self.classify()
-    }
-    fn to_bits(self) -> Self::Bits {
-        self.to_bits()
-    }
-    fn from_bits(v: Self::Bits) -> Self {
-        Self::from_bits(v)
-    }
-}
-
-impl RawFloat for f64 {
-    type Bits = u64;
-
-    const SIG_BITS: u8 = 53;
-    const EXP_BITS: u8 = 11;
-    const CEIL_LOG5_OF_MAX_SIG: i16 = 23;
-    const MAX_NORMAL_DIGITS: usize = 305;
-    const INF_CUTOFF: i64 = 310;
-    const ZERO_CUTOFF: i64 = -326;
-    other_constants!(f64);
-
-    /// Returns the mantissa, exponent and sign as integers.
-    fn integer_decode(self) -> (u64, i16, i8) {
-        let bits = self.to_bits();
-        let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
-        let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
-        let mantissa = if exponent == 0 {
-            (bits & 0xfffffffffffff) << 1
-        } else {
-            (bits & 0xfffffffffffff) | 0x10000000000000
-        };
-        // Exponent bias + mantissa shift
-        exponent -= 1023 + 52;
-        (mantissa, exponent, sign)
-    }
-
-    fn unpack(self) -> Unpacked {
-        let (sig, exp, _sig) = self.integer_decode();
-        Unpacked::new(sig, exp)
-    }
-
-    fn from_int(x: u64) -> f64 {
-        // rkruppe is uncertain whether `as` rounds correctly on all platforms.
-        debug_assert!(x as f64 == fp_to_float(Fp { f: x, e: 0 }));
-        x as f64
-    }
-
-    fn short_fast_pow10(e: usize) -> Self {
-        table::F64_SHORT_POWERS[e]
-    }
-
-    fn classify(self) -> FpCategory {
-        self.classify()
-    }
-    fn to_bits(self) -> Self::Bits {
-        self.to_bits()
-    }
-    fn from_bits(v: Self::Bits) -> Self {
-        Self::from_bits(v)
-    }
-}
-
-/// Converts an `Fp` to the closest machine float type.
-/// Does not handle subnormal results.
-pub fn fp_to_float<T: RawFloat>(x: Fp) -> T {
-    let x = x.normalize();
-    // x.f is 64 bit, so x.e has a mantissa shift of 63
-    let e = x.e + 63;
-    if e > T::MAX_EXP {
-        panic!("fp_to_float: exponent {} too large", e)
-    } else if e > T::MIN_EXP {
-        encode_normal(round_normal::<T>(x))
-    } else {
-        panic!("fp_to_float: exponent {} too small", e)
-    }
-}
-
-/// Round the 64-bit significand to T::SIG_BITS bits with half-to-even.
-/// Does not handle exponent overflow.
-pub fn round_normal<T: RawFloat>(x: Fp) -> Unpacked {
-    let excess = 64 - T::SIG_BITS as i16;
-    let half: u64 = 1 << (excess - 1);
-    let (q, rem) = (x.f >> excess, x.f & ((1 << excess) - 1));
-    assert_eq!(q << excess | rem, x.f);
-    // Adjust mantissa shift
-    let k = x.e + excess;
-    if rem < half {
-        Unpacked::new(q, k)
-    } else if rem == half && (q % 2) == 0 {
-        Unpacked::new(q, k)
-    } else if q == T::MAX_SIG {
-        Unpacked::new(T::MIN_SIG, k + 1)
-    } else {
-        Unpacked::new(q + 1, k)
-    }
-}
-
-/// Inverse of `RawFloat::unpack()` for normalized numbers.
-/// Panics if the significand or exponent are not valid for normalized numbers.
-pub fn encode_normal<T: RawFloat>(x: Unpacked) -> T {
-    debug_assert!(
-        T::MIN_SIG <= x.sig && x.sig <= T::MAX_SIG,
-        "encode_normal: significand not normalized"
-    );
-    // Remove the hidden bit
-    let sig_enc = x.sig & !(1 << T::EXPLICIT_SIG_BITS);
-    // Adjust the exponent for exponent bias and mantissa shift
-    let k_enc = x.k + T::MAX_EXP + T::EXPLICIT_SIG_BITS as i16;
-    debug_assert!(k_enc != 0 && k_enc < T::MAX_ENCODED_EXP, "encode_normal: exponent out of range");
-    // Leave sign bit at 0 ("+"), our numbers are all positive
-    let bits = (k_enc as u64) << T::EXPLICIT_SIG_BITS | sig_enc;
-    T::from_bits(bits.try_into().unwrap_or_else(|_| unreachable!()))
-}
-
-/// Construct a subnormal. A mantissa of 0 is allowed and constructs zero.
-pub fn encode_subnormal<T: RawFloat>(significand: u64) -> T {
-    assert!(significand < T::MIN_SIG, "encode_subnormal: not actually subnormal");
-    // Encoded exponent is 0, the sign bit is 0, so we just have to reinterpret the bits.
-    T::from_bits(significand.try_into().unwrap_or_else(|_| unreachable!()))
-}
-
-/// Approximate a bignum with an Fp. Rounds within 0.5 ULP with half-to-even.
-pub fn big_to_fp(f: &Big) -> Fp {
-    let end = f.bit_length();
-    assert!(end != 0, "big_to_fp: unexpectedly, input is zero");
-    let start = end.saturating_sub(64);
-    let leading = num::get_bits(f, start, end);
-    // We cut off all bits prior to the index `start`, i.e., we effectively right-shift by
-    // an amount of `start`, so this is also the exponent we need.
-    let e = start as i16;
-    let rounded_down = Fp { f: leading, e }.normalize();
-    // Round (half-to-even) depending on the truncated bits.
-    match num::compare_with_half_ulp(f, start) {
-        Less => rounded_down,
-        Equal if leading % 2 == 0 => rounded_down,
-        Equal | Greater => match leading.checked_add(1) {
-            Some(f) => Fp { f, e }.normalize(),
-            None => Fp { f: 1 << 63, e: e + 1 },
-        },
-    }
-}
-
-/// Finds the largest floating point number strictly smaller than the argument.
-/// Does not handle subnormals, zero, or exponent underflow.
-pub fn prev_float<T: RawFloat>(x: T) -> T {
-    match x.classify() {
-        Infinite => panic!("prev_float: argument is infinite"),
-        Nan => panic!("prev_float: argument is NaN"),
-        Subnormal => panic!("prev_float: argument is subnormal"),
-        Zero => panic!("prev_float: argument is zero"),
-        Normal => {
-            let Unpacked { sig, k } = x.unpack();
-            if sig == T::MIN_SIG {
-                encode_normal(Unpacked::new(T::MAX_SIG, k - 1))
-            } else {
-                encode_normal(Unpacked::new(sig - 1, k))
-            }
-        }
-    }
-}
-
-// Find the smallest floating point number strictly larger than the argument.
-// This operation is saturating, i.e., next_float(inf) == inf.
-// Unlike most code in this module, this function does handle zero, subnormals, and infinities.
-// However, like all other code here, it does not deal with NaN and negative numbers.
-pub fn next_float<T: RawFloat>(x: T) -> T {
-    match x.classify() {
-        Nan => panic!("next_float: argument is NaN"),
-        Infinite => T::INFINITY,
-        // This seems too good to be true, but it works.
-        // 0.0 is encoded as the all-zero word. Subnormals are 0x000m...m where m is the mantissa.
-        // In particular, the smallest subnormal is 0x0...01 and the largest is 0x000F...F.
-        // The smallest normal number is 0x0010...0, so this corner case works as well.
-        // If the increment overflows the mantissa, the carry bit increments the exponent as we
-        // want, and the mantissa bits become zero. Because of the hidden bit convention, this
-        // too is exactly what we want!
-        // Finally, f64::MAX + 1 = 7eff...f + 1 = 7ff0...0 = f64::INFINITY.
-        Zero | Subnormal | Normal => T::from_bits(x.to_bits() + T::Bits::from(1u8)),
-    }
-}
diff --git a/library/core/src/num/dec2flt/slow.rs b/library/core/src/num/dec2flt/slow.rs
new file mode 100644 (file)
index 0000000..bf10440
--- /dev/null
@@ -0,0 +1,109 @@
+//! Slow, fallback algorithm for cases the Eisel-Lemire algorithm cannot round.
+
+use crate::num::dec2flt::common::BiasedFp;
+use crate::num::dec2flt::decimal::{parse_decimal, Decimal};
+use crate::num::dec2flt::float::RawFloat;
+
+/// Parse the significant digits and biased, binary exponent of a float.
+///
+/// This is a fallback algorithm that uses a big-integer representation
+/// of the float, and therefore is considerably slower than faster
+/// approximations. However, it will always determine how to round
+/// the significant digits to the nearest machine float, allowing
+/// use to handle near half-way cases.
+///
+/// Near half-way cases are halfway between two consecutive machine floats.
+/// For example, the float `16777217.0` has a bitwise representation of
+/// `100000000000000000000000 1`. Rounding to a single-precision float,
+/// the trailing `1` is truncated. Using round-nearest, tie-even, any
+/// value above `16777217.0` must be rounded up to `16777218.0`, while
+/// any value before or equal to `16777217.0` must be rounded down
+/// to `16777216.0`. These near-halfway conversions therefore may require
+/// a large number of digits to unambiguously determine how to round.
+///
+/// The algorithms described here are based on "Processing Long Numbers Quickly",
+/// available here: <https://arxiv.org/pdf/2101.11408.pdf#section.11>.
+pub(crate) fn parse_long_mantissa<F: RawFloat>(s: &[u8]) -> BiasedFp {
+    const MAX_SHIFT: usize = 60;
+    const NUM_POWERS: usize = 19;
+    const POWERS: [u8; 19] =
+        [0, 3, 6, 9, 13, 16, 19, 23, 26, 29, 33, 36, 39, 43, 46, 49, 53, 56, 59];
+
+    let get_shift = |n| {
+        if n < NUM_POWERS { POWERS[n] as usize } else { MAX_SHIFT }
+    };
+
+    let fp_zero = BiasedFp::zero_pow2(0);
+    let fp_inf = BiasedFp::zero_pow2(F::INFINITE_POWER);
+
+    let mut d = parse_decimal(s);
+
+    // Short-circuit if the value can only be a literal 0 or infinity.
+    if d.num_digits == 0 || d.decimal_point < -324 {
+        return fp_zero;
+    } else if d.decimal_point >= 310 {
+        return fp_inf;
+    }
+    let mut exp2 = 0_i32;
+    // Shift right toward (1/2 ... 1].
+    while d.decimal_point > 0 {
+        let n = d.decimal_point as usize;
+        let shift = get_shift(n);
+        d.right_shift(shift);
+        if d.decimal_point < -Decimal::DECIMAL_POINT_RANGE {
+            return fp_zero;
+        }
+        exp2 += shift as i32;
+    }
+    // Shift left toward (1/2 ... 1].
+    while d.decimal_point <= 0 {
+        let shift = if d.decimal_point == 0 {
+            match d.digits[0] {
+                digit if digit >= 5 => break,
+                0 | 1 => 2,
+                _ => 1,
+            }
+        } else {
+            get_shift((-d.decimal_point) as _)
+        };
+        d.left_shift(shift);
+        if d.decimal_point > Decimal::DECIMAL_POINT_RANGE {
+            return fp_inf;
+        }
+        exp2 -= shift as i32;
+    }
+    // We are now in the range [1/2 ... 1] but the binary format uses [1 ... 2].
+    exp2 -= 1;
+    while (F::MINIMUM_EXPONENT + 1) > exp2 {
+        let mut n = ((F::MINIMUM_EXPONENT + 1) - exp2) as usize;
+        if n > MAX_SHIFT {
+            n = MAX_SHIFT;
+        }
+        d.right_shift(n);
+        exp2 += n as i32;
+    }
+    if (exp2 - F::MINIMUM_EXPONENT) >= F::INFINITE_POWER {
+        return fp_inf;
+    }
+    // Shift the decimal to the hidden bit, and then round the value
+    // to get the high mantissa+1 bits.
+    d.left_shift(F::MANTISSA_EXPLICIT_BITS + 1);
+    let mut mantissa = d.round();
+    if mantissa >= (1_u64 << (F::MANTISSA_EXPLICIT_BITS + 1)) {
+        // Rounding up overflowed to the carry bit, need to
+        // shift back to the hidden bit.
+        d.right_shift(1);
+        exp2 += 1;
+        mantissa = d.round();
+        if (exp2 - F::MINIMUM_EXPONENT) >= F::INFINITE_POWER {
+            return fp_inf;
+        }
+    }
+    let mut power2 = exp2 - F::MINIMUM_EXPONENT;
+    if mantissa < (1_u64 << F::MANTISSA_EXPLICIT_BITS) {
+        power2 -= 1;
+    }
+    // Zero out all the bits above the explicit mantissa bits.
+    mantissa &= (1_u64 << F::MANTISSA_EXPLICIT_BITS) - 1;
+    BiasedFp { f: mantissa, e: power2 }
+}
index 97b497e81e0700d4d6fa1cdec19d99386bb841f2..4856074a62bd01d0824226e28fc7341285f2d1a5 100644 (file)
-//! Tables of approximations of powers of ten.
+//! Pre-computed tables powers-of-5 for extended-precision representations.
+//!
+//! These tables enable fast scaling of the significant digits
+//! of a float to the decimal exponent, with minimal rounding
+//! errors, in a 128 or 192-bit representation.
+//!
 //! DO NOT MODIFY: Generated by `src/etc/dec2flt_table.py`
 
-pub const MIN_E: i16 = -305;
-pub const MAX_E: i16 = 305;
+pub const SMALLEST_POWER_OF_FIVE: i32 = -342;
+pub const LARGEST_POWER_OF_FIVE: i32 = 308;
+pub const N_POWERS_OF_FIVE: usize = (LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize;
 
+// Use static to avoid long compile times: Rust compiler errors
+// can have the entire table compiled multiple times, and then
+// emit code multiple times, even if it's stripped out in
+// the final binary.
 #[rustfmt::skip]
-pub static POWERS: ([u64; 611], [i16; 611]) = (
-    [
-        0xe0b62e2929aba83c,
-        0x8c71dcd9ba0b4926,
-        0xaf8e5410288e1b6f,
-        0xdb71e91432b1a24b,
-        0x892731ac9faf056f,
-        0xab70fe17c79ac6ca,
-        0xd64d3d9db981787d,
-        0x85f0468293f0eb4e,
-        0xa76c582338ed2622,
-        0xd1476e2c07286faa,
-        0x82cca4db847945ca,
-        0xa37fce126597973d,
-        0xcc5fc196fefd7d0c,
-        0xff77b1fcbebcdc4f,
-        0x9faacf3df73609b1,
-        0xc795830d75038c1e,
-        0xf97ae3d0d2446f25,
-        0x9becce62836ac577,
-        0xc2e801fb244576d5,
-        0xf3a20279ed56d48a,
-        0x9845418c345644d7,
-        0xbe5691ef416bd60c,
-        0xedec366b11c6cb8f,
-        0x94b3a202eb1c3f39,
-        0xb9e08a83a5e34f08,
-        0xe858ad248f5c22ca,
-        0x91376c36d99995be,
-        0xb58547448ffffb2e,
-        0xe2e69915b3fff9f9,
-        0x8dd01fad907ffc3c,
-        0xb1442798f49ffb4b,
-        0xdd95317f31c7fa1d,
-        0x8a7d3eef7f1cfc52,
-        0xad1c8eab5ee43b67,
-        0xd863b256369d4a41,
-        0x873e4f75e2224e68,
-        0xa90de3535aaae202,
-        0xd3515c2831559a83,
-        0x8412d9991ed58092,
-        0xa5178fff668ae0b6,
-        0xce5d73ff402d98e4,
-        0x80fa687f881c7f8e,
-        0xa139029f6a239f72,
-        0xc987434744ac874f,
-        0xfbe9141915d7a922,
-        0x9d71ac8fada6c9b5,
-        0xc4ce17b399107c23,
-        0xf6019da07f549b2b,
-        0x99c102844f94e0fb,
-        0xc0314325637a193a,
-        0xf03d93eebc589f88,
-        0x96267c7535b763b5,
-        0xbbb01b9283253ca3,
-        0xea9c227723ee8bcb,
-        0x92a1958a7675175f,
-        0xb749faed14125d37,
-        0xe51c79a85916f485,
-        0x8f31cc0937ae58d3,
-        0xb2fe3f0b8599ef08,
-        0xdfbdcece67006ac9,
-        0x8bd6a141006042be,
-        0xaecc49914078536d,
-        0xda7f5bf590966849,
-        0x888f99797a5e012d,
-        0xaab37fd7d8f58179,
-        0xd5605fcdcf32e1d7,
-        0x855c3be0a17fcd26,
-        0xa6b34ad8c9dfc070,
-        0xd0601d8efc57b08c,
-        0x823c12795db6ce57,
-        0xa2cb1717b52481ed,
-        0xcb7ddcdda26da269,
-        0xfe5d54150b090b03,
-        0x9efa548d26e5a6e2,
-        0xc6b8e9b0709f109a,
-        0xf867241c8cc6d4c1,
-        0x9b407691d7fc44f8,
-        0xc21094364dfb5637,
-        0xf294b943e17a2bc4,
-        0x979cf3ca6cec5b5b,
-        0xbd8430bd08277231,
-        0xece53cec4a314ebe,
-        0x940f4613ae5ed137,
-        0xb913179899f68584,
-        0xe757dd7ec07426e5,
-        0x9096ea6f3848984f,
-        0xb4bca50b065abe63,
-        0xe1ebce4dc7f16dfc,
-        0x8d3360f09cf6e4bd,
-        0xb080392cc4349ded,
-        0xdca04777f541c568,
-        0x89e42caaf9491b61,
-        0xac5d37d5b79b6239,
-        0xd77485cb25823ac7,
-        0x86a8d39ef77164bd,
-        0xa8530886b54dbdec,
-        0xd267caa862a12d67,
-        0x8380dea93da4bc60,
-        0xa46116538d0deb78,
-        0xcd795be870516656,
-        0x806bd9714632dff6,
-        0xa086cfcd97bf97f4,
-        0xc8a883c0fdaf7df0,
-        0xfad2a4b13d1b5d6c,
-        0x9cc3a6eec6311a64,
-        0xc3f490aa77bd60fd,
-        0xf4f1b4d515acb93c,
-        0x991711052d8bf3c5,
-        0xbf5cd54678eef0b7,
-        0xef340a98172aace5,
-        0x9580869f0e7aac0f,
-        0xbae0a846d2195713,
-        0xe998d258869facd7,
-        0x91ff83775423cc06,
-        0xb67f6455292cbf08,
-        0xe41f3d6a7377eeca,
-        0x8e938662882af53e,
-        0xb23867fb2a35b28e,
-        0xdec681f9f4c31f31,
-        0x8b3c113c38f9f37f,
-        0xae0b158b4738705f,
-        0xd98ddaee19068c76,
-        0x87f8a8d4cfa417ca,
-        0xa9f6d30a038d1dbc,
-        0xd47487cc8470652b,
-        0x84c8d4dfd2c63f3b,
-        0xa5fb0a17c777cf0a,
-        0xcf79cc9db955c2cc,
-        0x81ac1fe293d599c0,
-        0xa21727db38cb0030,
-        0xca9cf1d206fdc03c,
-        0xfd442e4688bd304b,
-        0x9e4a9cec15763e2f,
-        0xc5dd44271ad3cdba,
-        0xf7549530e188c129,
-        0x9a94dd3e8cf578ba,
-        0xc13a148e3032d6e8,
-        0xf18899b1bc3f8ca2,
-        0x96f5600f15a7b7e5,
-        0xbcb2b812db11a5de,
-        0xebdf661791d60f56,
-        0x936b9fcebb25c996,
-        0xb84687c269ef3bfb,
-        0xe65829b3046b0afa,
-        0x8ff71a0fe2c2e6dc,
-        0xb3f4e093db73a093,
-        0xe0f218b8d25088b8,
-        0x8c974f7383725573,
-        0xafbd2350644eead0,
-        0xdbac6c247d62a584,
-        0x894bc396ce5da772,
-        0xab9eb47c81f5114f,
-        0xd686619ba27255a3,
-        0x8613fd0145877586,
-        0xa798fc4196e952e7,
-        0xd17f3b51fca3a7a1,
-        0x82ef85133de648c5,
-        0xa3ab66580d5fdaf6,
-        0xcc963fee10b7d1b3,
-        0xffbbcfe994e5c620,
-        0x9fd561f1fd0f9bd4,
-        0xc7caba6e7c5382c9,
-        0xf9bd690a1b68637b,
-        0x9c1661a651213e2d,
-        0xc31bfa0fe5698db8,
-        0xf3e2f893dec3f126,
-        0x986ddb5c6b3a76b8,
-        0xbe89523386091466,
-        0xee2ba6c0678b597f,
-        0x94db483840b717f0,
-        0xba121a4650e4ddec,
-        0xe896a0d7e51e1566,
-        0x915e2486ef32cd60,
-        0xb5b5ada8aaff80b8,
-        0xe3231912d5bf60e6,
-        0x8df5efabc5979c90,
-        0xb1736b96b6fd83b4,
-        0xddd0467c64bce4a1,
-        0x8aa22c0dbef60ee4,
-        0xad4ab7112eb3929e,
-        0xd89d64d57a607745,
-        0x87625f056c7c4a8b,
-        0xa93af6c6c79b5d2e,
-        0xd389b47879823479,
-        0x843610cb4bf160cc,
-        0xa54394fe1eedb8ff,
-        0xce947a3da6a9273e,
-        0x811ccc668829b887,
-        0xa163ff802a3426a9,
-        0xc9bcff6034c13053,
-        0xfc2c3f3841f17c68,
-        0x9d9ba7832936edc1,
-        0xc5029163f384a931,
-        0xf64335bcf065d37d,
-        0x99ea0196163fa42e,
-        0xc06481fb9bcf8d3a,
-        0xf07da27a82c37088,
-        0x964e858c91ba2655,
-        0xbbe226efb628afeb,
-        0xeadab0aba3b2dbe5,
-        0x92c8ae6b464fc96f,
-        0xb77ada0617e3bbcb,
-        0xe55990879ddcaabe,
-        0x8f57fa54c2a9eab7,
-        0xb32df8e9f3546564,
-        0xdff9772470297ebd,
-        0x8bfbea76c619ef36,
-        0xaefae51477a06b04,
-        0xdab99e59958885c5,
-        0x88b402f7fd75539b,
-        0xaae103b5fcd2a882,
-        0xd59944a37c0752a2,
-        0x857fcae62d8493a5,
-        0xa6dfbd9fb8e5b88f,
-        0xd097ad07a71f26b2,
-        0x825ecc24c8737830,
-        0xa2f67f2dfa90563b,
-        0xcbb41ef979346bca,
-        0xfea126b7d78186bd,
-        0x9f24b832e6b0f436,
-        0xc6ede63fa05d3144,
-        0xf8a95fcf88747d94,
-        0x9b69dbe1b548ce7d,
-        0xc24452da229b021c,
-        0xf2d56790ab41c2a3,
-        0x97c560ba6b0919a6,
-        0xbdb6b8e905cb600f,
-        0xed246723473e3813,
-        0x9436c0760c86e30c,
-        0xb94470938fa89bcf,
-        0xe7958cb87392c2c3,
-        0x90bd77f3483bb9ba,
-        0xb4ecd5f01a4aa828,
-        0xe2280b6c20dd5232,
-        0x8d590723948a535f,
-        0xb0af48ec79ace837,
-        0xdcdb1b2798182245,
-        0x8a08f0f8bf0f156b,
-        0xac8b2d36eed2dac6,
-        0xd7adf884aa879177,
-        0x86ccbb52ea94baeb,
-        0xa87fea27a539e9a5,
-        0xd29fe4b18e88640f,
-        0x83a3eeeef9153e89,
-        0xa48ceaaab75a8e2b,
-        0xcdb02555653131b6,
-        0x808e17555f3ebf12,
-        0xa0b19d2ab70e6ed6,
-        0xc8de047564d20a8c,
-        0xfb158592be068d2f,
-        0x9ced737bb6c4183d,
-        0xc428d05aa4751e4d,
-        0xf53304714d9265e0,
-        0x993fe2c6d07b7fac,
-        0xbf8fdb78849a5f97,
-        0xef73d256a5c0f77d,
-        0x95a8637627989aae,
-        0xbb127c53b17ec159,
-        0xe9d71b689dde71b0,
-        0x9226712162ab070e,
-        0xb6b00d69bb55c8d1,
-        0xe45c10c42a2b3b06,
-        0x8eb98a7a9a5b04e3,
-        0xb267ed1940f1c61c,
-        0xdf01e85f912e37a3,
-        0x8b61313bbabce2c6,
-        0xae397d8aa96c1b78,
-        0xd9c7dced53c72256,
-        0x881cea14545c7575,
-        0xaa242499697392d3,
-        0xd4ad2dbfc3d07788,
-        0x84ec3c97da624ab5,
-        0xa6274bbdd0fadd62,
-        0xcfb11ead453994ba,
-        0x81ceb32c4b43fcf5,
-        0xa2425ff75e14fc32,
-        0xcad2f7f5359a3b3e,
-        0xfd87b5f28300ca0e,
-        0x9e74d1b791e07e48,
-        0xc612062576589ddb,
-        0xf79687aed3eec551,
-        0x9abe14cd44753b53,
-        0xc16d9a0095928a27,
-        0xf1c90080baf72cb1,
-        0x971da05074da7bef,
-        0xbce5086492111aeb,
-        0xec1e4a7db69561a5,
-        0x9392ee8e921d5d07,
-        0xb877aa3236a4b449,
-        0xe69594bec44de15b,
-        0x901d7cf73ab0acd9,
-        0xb424dc35095cd80f,
-        0xe12e13424bb40e13,
-        0x8cbccc096f5088cc,
-        0xafebff0bcb24aaff,
-        0xdbe6fecebdedd5bf,
-        0x89705f4136b4a597,
-        0xabcc77118461cefd,
-        0xd6bf94d5e57a42bc,
-        0x8637bd05af6c69b6,
-        0xa7c5ac471b478423,
-        0xd1b71758e219652c,
-        0x83126e978d4fdf3b,
-        0xa3d70a3d70a3d70a,
-        0xcccccccccccccccd,
-        0x8000000000000000,
-        0xa000000000000000,
-        0xc800000000000000,
-        0xfa00000000000000,
-        0x9c40000000000000,
-        0xc350000000000000,
-        0xf424000000000000,
-        0x9896800000000000,
-        0xbebc200000000000,
-        0xee6b280000000000,
-        0x9502f90000000000,
-        0xba43b74000000000,
-        0xe8d4a51000000000,
-        0x9184e72a00000000,
-        0xb5e620f480000000,
-        0xe35fa931a0000000,
-        0x8e1bc9bf04000000,
-        0xb1a2bc2ec5000000,
-        0xde0b6b3a76400000,
-        0x8ac7230489e80000,
-        0xad78ebc5ac620000,
-        0xd8d726b7177a8000,
-        0x878678326eac9000,
-        0xa968163f0a57b400,
-        0xd3c21bcecceda100,
-        0x84595161401484a0,
-        0xa56fa5b99019a5c8,
-        0xcecb8f27f4200f3a,
-        0x813f3978f8940984,
-        0xa18f07d736b90be5,
-        0xc9f2c9cd04674edf,
-        0xfc6f7c4045812296,
-        0x9dc5ada82b70b59e,
-        0xc5371912364ce305,
-        0xf684df56c3e01bc7,
-        0x9a130b963a6c115c,
-        0xc097ce7bc90715b3,
-        0xf0bdc21abb48db20,
-        0x96769950b50d88f4,
-        0xbc143fa4e250eb31,
-        0xeb194f8e1ae525fd,
-        0x92efd1b8d0cf37be,
-        0xb7abc627050305ae,
-        0xe596b7b0c643c719,
-        0x8f7e32ce7bea5c70,
-        0xb35dbf821ae4f38c,
-        0xe0352f62a19e306f,
-        0x8c213d9da502de45,
-        0xaf298d050e4395d7,
-        0xdaf3f04651d47b4c,
-        0x88d8762bf324cd10,
-        0xab0e93b6efee0054,
-        0xd5d238a4abe98068,
-        0x85a36366eb71f041,
-        0xa70c3c40a64e6c52,
-        0xd0cf4b50cfe20766,
-        0x82818f1281ed44a0,
-        0xa321f2d7226895c8,
-        0xcbea6f8ceb02bb3a,
-        0xfee50b7025c36a08,
-        0x9f4f2726179a2245,
-        0xc722f0ef9d80aad6,
-        0xf8ebad2b84e0d58c,
-        0x9b934c3b330c8577,
-        0xc2781f49ffcfa6d5,
-        0xf316271c7fc3908b,
-        0x97edd871cfda3a57,
-        0xbde94e8e43d0c8ec,
-        0xed63a231d4c4fb27,
-        0x945e455f24fb1cf9,
-        0xb975d6b6ee39e437,
-        0xe7d34c64a9c85d44,
-        0x90e40fbeea1d3a4b,
-        0xb51d13aea4a488dd,
-        0xe264589a4dcdab15,
-        0x8d7eb76070a08aed,
-        0xb0de65388cc8ada8,
-        0xdd15fe86affad912,
-        0x8a2dbf142dfcc7ab,
-        0xacb92ed9397bf996,
-        0xd7e77a8f87daf7fc,
-        0x86f0ac99b4e8dafd,
-        0xa8acd7c0222311bd,
-        0xd2d80db02aabd62c,
-        0x83c7088e1aab65db,
-        0xa4b8cab1a1563f52,
-        0xcde6fd5e09abcf27,
-        0x80b05e5ac60b6178,
-        0xa0dc75f1778e39d6,
-        0xc913936dd571c84c,
-        0xfb5878494ace3a5f,
-        0x9d174b2dcec0e47b,
-        0xc45d1df942711d9a,
-        0xf5746577930d6501,
-        0x9968bf6abbe85f20,
-        0xbfc2ef456ae276e9,
-        0xefb3ab16c59b14a3,
-        0x95d04aee3b80ece6,
-        0xbb445da9ca61281f,
-        0xea1575143cf97227,
-        0x924d692ca61be758,
-        0xb6e0c377cfa2e12e,
-        0xe498f455c38b997a,
-        0x8edf98b59a373fec,
-        0xb2977ee300c50fe7,
-        0xdf3d5e9bc0f653e1,
-        0x8b865b215899f46d,
-        0xae67f1e9aec07188,
-        0xda01ee641a708dea,
-        0x884134fe908658b2,
-        0xaa51823e34a7eedf,
-        0xd4e5e2cdc1d1ea96,
-        0x850fadc09923329e,
-        0xa6539930bf6bff46,
-        0xcfe87f7cef46ff17,
-        0x81f14fae158c5f6e,
-        0xa26da3999aef774a,
-        0xcb090c8001ab551c,
-        0xfdcb4fa002162a63,
-        0x9e9f11c4014dda7e,
-        0xc646d63501a1511e,
-        0xf7d88bc24209a565,
-        0x9ae757596946075f,
-        0xc1a12d2fc3978937,
-        0xf209787bb47d6b85,
-        0x9745eb4d50ce6333,
-        0xbd176620a501fc00,
-        0xec5d3fa8ce427b00,
-        0x93ba47c980e98ce0,
-        0xb8a8d9bbe123f018,
-        0xe6d3102ad96cec1e,
-        0x9043ea1ac7e41393,
-        0xb454e4a179dd1877,
-        0xe16a1dc9d8545e95,
-        0x8ce2529e2734bb1d,
-        0xb01ae745b101e9e4,
-        0xdc21a1171d42645d,
-        0x899504ae72497eba,
-        0xabfa45da0edbde69,
-        0xd6f8d7509292d603,
-        0x865b86925b9bc5c2,
-        0xa7f26836f282b733,
-        0xd1ef0244af2364ff,
-        0x8335616aed761f1f,
-        0xa402b9c5a8d3a6e7,
-        0xcd036837130890a1,
-        0x802221226be55a65,
-        0xa02aa96b06deb0fe,
-        0xc83553c5c8965d3d,
-        0xfa42a8b73abbf48d,
-        0x9c69a97284b578d8,
-        0xc38413cf25e2d70e,
-        0xf46518c2ef5b8cd1,
-        0x98bf2f79d5993803,
-        0xbeeefb584aff8604,
-        0xeeaaba2e5dbf6785,
-        0x952ab45cfa97a0b3,
-        0xba756174393d88e0,
-        0xe912b9d1478ceb17,
-        0x91abb422ccb812ef,
-        0xb616a12b7fe617aa,
-        0xe39c49765fdf9d95,
-        0x8e41ade9fbebc27d,
-        0xb1d219647ae6b31c,
-        0xde469fbd99a05fe3,
-        0x8aec23d680043bee,
-        0xada72ccc20054aea,
-        0xd910f7ff28069da4,
-        0x87aa9aff79042287,
-        0xa99541bf57452b28,
-        0xd3fa922f2d1675f2,
-        0x847c9b5d7c2e09b7,
-        0xa59bc234db398c25,
-        0xcf02b2c21207ef2f,
-        0x8161afb94b44f57d,
-        0xa1ba1ba79e1632dc,
-        0xca28a291859bbf93,
-        0xfcb2cb35e702af78,
-        0x9defbf01b061adab,
-        0xc56baec21c7a1916,
-        0xf6c69a72a3989f5c,
-        0x9a3c2087a63f6399,
-        0xc0cb28a98fcf3c80,
-        0xf0fdf2d3f3c30b9f,
-        0x969eb7c47859e744,
-        0xbc4665b596706115,
-        0xeb57ff22fc0c795a,
-        0x9316ff75dd87cbd8,
-        0xb7dcbf5354e9bece,
-        0xe5d3ef282a242e82,
-        0x8fa475791a569d11,
-        0xb38d92d760ec4455,
-        0xe070f78d3927556b,
-        0x8c469ab843b89563,
-        0xaf58416654a6babb,
-        0xdb2e51bfe9d0696a,
-        0x88fcf317f22241e2,
-        0xab3c2fddeeaad25b,
-        0xd60b3bd56a5586f2,
-        0x85c7056562757457,
-        0xa738c6bebb12d16d,
-        0xd106f86e69d785c8,
-        0x82a45b450226b39d,
-        0xa34d721642b06084,
-        0xcc20ce9bd35c78a5,
-        0xff290242c83396ce,
-        0x9f79a169bd203e41,
-        0xc75809c42c684dd1,
-        0xf92e0c3537826146,
-        0x9bbcc7a142b17ccc,
-        0xc2abf989935ddbfe,
-        0xf356f7ebf83552fe,
-        0x98165af37b2153df,
-        0xbe1bf1b059e9a8d6,
-        0xeda2ee1c7064130c,
-        0x9485d4d1c63e8be8,
-        0xb9a74a0637ce2ee1,
-        0xe8111c87c5c1ba9a,
-        0x910ab1d4db9914a0,
-        0xb54d5e4a127f59c8,
-        0xe2a0b5dc971f303a,
-        0x8da471a9de737e24,
-        0xb10d8e1456105dad,
-        0xdd50f1996b947519,
-        0x8a5296ffe33cc930,
-        0xace73cbfdc0bfb7b,
-        0xd8210befd30efa5a,
-        0x8714a775e3e95c78,
-        0xa8d9d1535ce3b396,
-        0xd31045a8341ca07c,
-        0x83ea2b892091e44e,
-        0xa4e4b66b68b65d61,
-        0xce1de40642e3f4b9,
-        0x80d2ae83e9ce78f4,
-        0xa1075a24e4421731,
-        0xc94930ae1d529cfd,
-        0xfb9b7cd9a4a7443c,
-        0x9d412e0806e88aa6,
-        0xc491798a08a2ad4f,
-        0xf5b5d7ec8acb58a3,
-        0x9991a6f3d6bf1766,
-        0xbff610b0cc6edd3f,
-        0xeff394dcff8a948f,
-        0x95f83d0a1fb69cd9,
-        0xbb764c4ca7a44410,
-        0xea53df5fd18d5514,
-        0x92746b9be2f8552c,
-        0xb7118682dbb66a77,
-        0xe4d5e82392a40515,
-        0x8f05b1163ba6832d,
-        0xb2c71d5bca9023f8,
-        0xdf78e4b2bd342cf7,
-        0x8bab8eefb6409c1a,
-        0xae9672aba3d0c321,
-        0xda3c0f568cc4f3e9,
-        0x8865899617fb1871,
-        0xaa7eebfb9df9de8e,
-        0xd51ea6fa85785631,
-        0x8533285c936b35df,
-        0xa67ff273b8460357,
-        0xd01fef10a657842c,
-        0x8213f56a67f6b29c,
-        0xa298f2c501f45f43,
-        0xcb3f2f7642717713,
-        0xfe0efb53d30dd4d8,
-        0x9ec95d1463e8a507,
-        0xc67bb4597ce2ce49,
-        0xf81aa16fdc1b81db,
-        0x9b10a4e5e9913129,
-        0xc1d4ce1f63f57d73,
-        0xf24a01a73cf2dcd0,
-        0x976e41088617ca02,
-        0xbd49d14aa79dbc82,
-        0xec9c459d51852ba3,
-        0x93e1ab8252f33b46,
-        0xb8da1662e7b00a17,
-        0xe7109bfba19c0c9d,
-        0x906a617d450187e2,
-        0xb484f9dc9641e9db,
-        0xe1a63853bbd26451,
-        0x8d07e33455637eb3,
-        0xb049dc016abc5e60,
-        0xdc5c5301c56b75f7,
-        0x89b9b3e11b6329bb,
-        0xac2820d9623bf429,
-        0xd732290fbacaf134,
-        0x867f59a9d4bed6c0,
-        0xa81f301449ee8c70,
-        0xd226fc195c6a2f8c,
-        0x83585d8fd9c25db8,
-        0xa42e74f3d032f526,
-        0xcd3a1230c43fb26f,
-        0x80444b5e7aa7cf85,
-        0xa0555e361951c367,
-        0xc86ab5c39fa63441,
-        0xfa856334878fc151,
-        0x9c935e00d4b9d8d2,
-        0xc3b8358109e84f07,
-        0xf4a642e14c6262c9,
-        0x98e7e9cccfbd7dbe,
-        0xbf21e44003acdd2d,
-        0xeeea5d5004981478,
-        0x95527a5202df0ccb,
-        0xbaa718e68396cffe,
-        0xe950df20247c83fd,
-        0x91d28b7416cdd27e,
-    ],
-    [
-        -1077,
-        -1073,
-        -1070,
-        -1067,
-        -1063,
-        -1060,
-        -1057,
-        -1053,
-        -1050,
-        -1047,
-        -1043,
-        -1040,
-        -1037,
-        -1034,
-        -1030,
-        -1027,
-        -1024,
-        -1020,
-        -1017,
-        -1014,
-        -1010,
-        -1007,
-        -1004,
-        -1000,
-        -997,
-        -994,
-        -990,
-        -987,
-        -984,
-        -980,
-        -977,
-        -974,
-        -970,
-        -967,
-        -964,
-        -960,
-        -957,
-        -954,
-        -950,
-        -947,
-        -944,
-        -940,
-        -937,
-        -934,
-        -931,
-        -927,
-        -924,
-        -921,
-        -917,
-        -914,
-        -911,
-        -907,
-        -904,
-        -901,
-        -897,
-        -894,
-        -891,
-        -887,
-        -884,
-        -881,
-        -877,
-        -874,
-        -871,
-        -867,
-        -864,
-        -861,
-        -857,
-        -854,
-        -851,
-        -847,
-        -844,
-        -841,
-        -838,
-        -834,
-        -831,
-        -828,
-        -824,
-        -821,
-        -818,
-        -814,
-        -811,
-        -808,
-        -804,
-        -801,
-        -798,
-        -794,
-        -791,
-        -788,
-        -784,
-        -781,
-        -778,
-        -774,
-        -771,
-        -768,
-        -764,
-        -761,
-        -758,
-        -754,
-        -751,
-        -748,
-        -744,
-        -741,
-        -738,
-        -735,
-        -731,
-        -728,
-        -725,
-        -721,
-        -718,
-        -715,
-        -711,
-        -708,
-        -705,
-        -701,
-        -698,
-        -695,
-        -691,
-        -688,
-        -685,
-        -681,
-        -678,
-        -675,
-        -671,
-        -668,
-        -665,
-        -661,
-        -658,
-        -655,
-        -651,
-        -648,
-        -645,
-        -642,
-        -638,
-        -635,
-        -632,
-        -628,
-        -625,
-        -622,
-        -618,
-        -615,
-        -612,
-        -608,
-        -605,
-        -602,
-        -598,
-        -595,
-        -592,
-        -588,
-        -585,
-        -582,
-        -578,
-        -575,
-        -572,
-        -568,
-        -565,
-        -562,
-        -558,
-        -555,
-        -552,
-        -549,
-        -545,
-        -542,
-        -539,
-        -535,
-        -532,
-        -529,
-        -525,
-        -522,
-        -519,
-        -515,
-        -512,
-        -509,
-        -505,
-        -502,
-        -499,
-        -495,
-        -492,
-        -489,
-        -485,
-        -482,
-        -479,
-        -475,
-        -472,
-        -469,
-        -465,
-        -462,
-        -459,
-        -455,
-        -452,
-        -449,
-        -446,
-        -442,
-        -439,
-        -436,
-        -432,
-        -429,
-        -426,
-        -422,
-        -419,
-        -416,
-        -412,
-        -409,
-        -406,
-        -402,
-        -399,
-        -396,
-        -392,
-        -389,
-        -386,
-        -382,
-        -379,
-        -376,
-        -372,
-        -369,
-        -366,
-        -362,
-        -359,
-        -356,
-        -353,
-        -349,
-        -346,
-        -343,
-        -339,
-        -336,
-        -333,
-        -329,
-        -326,
-        -323,
-        -319,
-        -316,
-        -313,
-        -309,
-        -306,
-        -303,
-        -299,
-        -296,
-        -293,
-        -289,
-        -286,
-        -283,
-        -279,
-        -276,
-        -273,
-        -269,
-        -266,
-        -263,
-        -259,
-        -256,
-        -253,
-        -250,
-        -246,
-        -243,
-        -240,
-        -236,
-        -233,
-        -230,
-        -226,
-        -223,
-        -220,
-        -216,
-        -213,
-        -210,
-        -206,
-        -203,
-        -200,
-        -196,
-        -193,
-        -190,
-        -186,
-        -183,
-        -180,
-        -176,
-        -173,
-        -170,
-        -166,
-        -163,
-        -160,
-        -157,
-        -153,
-        -150,
-        -147,
-        -143,
-        -140,
-        -137,
-        -133,
-        -130,
-        -127,
-        -123,
-        -120,
-        -117,
-        -113,
-        -110,
-        -107,
-        -103,
-        -100,
-        -97,
-        -93,
-        -90,
-        -87,
-        -83,
-        -80,
-        -77,
-        -73,
-        -70,
-        -67,
-        -63,
-        -60,
-        -57,
-        -54,
-        -50,
-        -47,
-        -44,
-        -40,
-        -37,
-        -34,
-        -30,
-        -27,
-        -24,
-        -20,
-        -17,
-        -14,
-        -10,
-        -7,
-        -4,
-        0,
-        3,
-        6,
-        10,
-        13,
-        16,
-        20,
-        23,
-        26,
-        30,
-        33,
-        36,
-        39,
-        43,
-        46,
-        49,
-        53,
-        56,
-        59,
-        63,
-        66,
-        69,
-        73,
-        76,
-        79,
-        83,
-        86,
-        89,
-        93,
-        96,
-        99,
-        103,
-        106,
-        109,
-        113,
-        116,
-        119,
-        123,
-        126,
-        129,
-        132,
-        136,
-        139,
-        142,
-        146,
-        149,
-        152,
-        156,
-        159,
-        162,
-        166,
-        169,
-        172,
-        176,
-        179,
-        182,
-        186,
-        189,
-        192,
-        196,
-        199,
-        202,
-        206,
-        209,
-        212,
-        216,
-        219,
-        222,
-        226,
-        229,
-        232,
-        235,
-        239,
-        242,
-        245,
-        249,
-        252,
-        255,
-        259,
-        262,
-        265,
-        269,
-        272,
-        275,
-        279,
-        282,
-        285,
-        289,
-        292,
-        295,
-        299,
-        302,
-        305,
-        309,
-        312,
-        315,
-        319,
-        322,
-        325,
-        328,
-        332,
-        335,
-        338,
-        342,
-        345,
-        348,
-        352,
-        355,
-        358,
-        362,
-        365,
-        368,
-        372,
-        375,
-        378,
-        382,
-        385,
-        388,
-        392,
-        395,
-        398,
-        402,
-        405,
-        408,
-        412,
-        415,
-        418,
-        422,
-        425,
-        428,
-        431,
-        435,
-        438,
-        441,
-        445,
-        448,
-        451,
-        455,
-        458,
-        461,
-        465,
-        468,
-        471,
-        475,
-        478,
-        481,
-        485,
-        488,
-        491,
-        495,
-        498,
-        501,
-        505,
-        508,
-        511,
-        515,
-        518,
-        521,
-        524,
-        528,
-        531,
-        534,
-        538,
-        541,
-        544,
-        548,
-        551,
-        554,
-        558,
-        561,
-        564,
-        568,
-        571,
-        574,
-        578,
-        581,
-        584,
-        588,
-        591,
-        594,
-        598,
-        601,
-        604,
-        608,
-        611,
-        614,
-        617,
-        621,
-        624,
-        627,
-        631,
-        634,
-        637,
-        641,
-        644,
-        647,
-        651,
-        654,
-        657,
-        661,
-        664,
-        667,
-        671,
-        674,
-        677,
-        681,
-        684,
-        687,
-        691,
-        694,
-        697,
-        701,
-        704,
-        707,
-        711,
-        714,
-        717,
-        720,
-        724,
-        727,
-        730,
-        734,
-        737,
-        740,
-        744,
-        747,
-        750,
-        754,
-        757,
-        760,
-        764,
-        767,
-        770,
-        774,
-        777,
-        780,
-        784,
-        787,
-        790,
-        794,
-        797,
-        800,
-        804,
-        807,
-        810,
-        813,
-        817,
-        820,
-        823,
-        827,
-        830,
-        833,
-        837,
-        840,
-        843,
-        847,
-        850,
-        853,
-        857,
-        860,
-        863,
-        867,
-        870,
-        873,
-        877,
-        880,
-        883,
-        887,
-        890,
-        893,
-        897,
-        900,
-        903,
-        907,
-        910,
-        913,
-        916,
-        920,
-        923,
-        926,
-        930,
-        933,
-        936,
-        940,
-        943,
-        946,
-        950,
-    ],
-);
-
-#[rustfmt::skip]
-pub const F32_SHORT_POWERS: [f32; 11] = [
-    1e0,
-    1e1,
-    1e2,
-    1e3,
-    1e4,
-    1e5,
-    1e6,
-    1e7,
-    1e8,
-    1e9,
-    1e10,
-];
-
-#[rustfmt::skip]
-pub const F64_SHORT_POWERS: [f64; 23] = [
-    1e0,
-    1e1,
-    1e2,
-    1e3,
-    1e4,
-    1e5,
-    1e6,
-    1e7,
-    1e8,
-    1e9,
-    1e10,
-    1e11,
-    1e12,
-    1e13,
-    1e14,
-    1e15,
-    1e16,
-    1e17,
-    1e18,
-    1e19,
-    1e20,
-    1e21,
-    1e22,
+pub static POWER_OF_FIVE_128: [(u64, u64); N_POWERS_OF_FIVE] = [
+    (0xeef453d6923bd65a, 0x113faa2906a13b3f), // 5^-342
+    (0x9558b4661b6565f8, 0x4ac7ca59a424c507), // 5^-341
+    (0xbaaee17fa23ebf76, 0x5d79bcf00d2df649), // 5^-340
+    (0xe95a99df8ace6f53, 0xf4d82c2c107973dc), // 5^-339
+    (0x91d8a02bb6c10594, 0x79071b9b8a4be869), // 5^-338
+    (0xb64ec836a47146f9, 0x9748e2826cdee284), // 5^-337
+    (0xe3e27a444d8d98b7, 0xfd1b1b2308169b25), // 5^-336
+    (0x8e6d8c6ab0787f72, 0xfe30f0f5e50e20f7), // 5^-335
+    (0xb208ef855c969f4f, 0xbdbd2d335e51a935), // 5^-334
+    (0xde8b2b66b3bc4723, 0xad2c788035e61382), // 5^-333
+    (0x8b16fb203055ac76, 0x4c3bcb5021afcc31), // 5^-332
+    (0xaddcb9e83c6b1793, 0xdf4abe242a1bbf3d), // 5^-331
+    (0xd953e8624b85dd78, 0xd71d6dad34a2af0d), // 5^-330
+    (0x87d4713d6f33aa6b, 0x8672648c40e5ad68), // 5^-329
+    (0xa9c98d8ccb009506, 0x680efdaf511f18c2), // 5^-328
+    (0xd43bf0effdc0ba48, 0x212bd1b2566def2),  // 5^-327
+    (0x84a57695fe98746d, 0x14bb630f7604b57),  // 5^-326
+    (0xa5ced43b7e3e9188, 0x419ea3bd35385e2d), // 5^-325
+    (0xcf42894a5dce35ea, 0x52064cac828675b9), // 5^-324
+    (0x818995ce7aa0e1b2, 0x7343efebd1940993), // 5^-323
+    (0xa1ebfb4219491a1f, 0x1014ebe6c5f90bf8), // 5^-322
+    (0xca66fa129f9b60a6, 0xd41a26e077774ef6), // 5^-321
+    (0xfd00b897478238d0, 0x8920b098955522b4), // 5^-320
+    (0x9e20735e8cb16382, 0x55b46e5f5d5535b0), // 5^-319
+    (0xc5a890362fddbc62, 0xeb2189f734aa831d), // 5^-318
+    (0xf712b443bbd52b7b, 0xa5e9ec7501d523e4), // 5^-317
+    (0x9a6bb0aa55653b2d, 0x47b233c92125366e), // 5^-316
+    (0xc1069cd4eabe89f8, 0x999ec0bb696e840a), // 5^-315
+    (0xf148440a256e2c76, 0xc00670ea43ca250d), // 5^-314
+    (0x96cd2a865764dbca, 0x380406926a5e5728), // 5^-313
+    (0xbc807527ed3e12bc, 0xc605083704f5ecf2), // 5^-312
+    (0xeba09271e88d976b, 0xf7864a44c633682e), // 5^-311
+    (0x93445b8731587ea3, 0x7ab3ee6afbe0211d), // 5^-310
+    (0xb8157268fdae9e4c, 0x5960ea05bad82964), // 5^-309
+    (0xe61acf033d1a45df, 0x6fb92487298e33bd), // 5^-308
+    (0x8fd0c16206306bab, 0xa5d3b6d479f8e056), // 5^-307
+    (0xb3c4f1ba87bc8696, 0x8f48a4899877186c), // 5^-306
+    (0xe0b62e2929aba83c, 0x331acdabfe94de87), // 5^-305
+    (0x8c71dcd9ba0b4925, 0x9ff0c08b7f1d0b14), // 5^-304
+    (0xaf8e5410288e1b6f, 0x7ecf0ae5ee44dd9),  // 5^-303
+    (0xdb71e91432b1a24a, 0xc9e82cd9f69d6150), // 5^-302
+    (0x892731ac9faf056e, 0xbe311c083a225cd2), // 5^-301
+    (0xab70fe17c79ac6ca, 0x6dbd630a48aaf406), // 5^-300
+    (0xd64d3d9db981787d, 0x92cbbccdad5b108),  // 5^-299
+    (0x85f0468293f0eb4e, 0x25bbf56008c58ea5), // 5^-298
+    (0xa76c582338ed2621, 0xaf2af2b80af6f24e), // 5^-297
+    (0xd1476e2c07286faa, 0x1af5af660db4aee1), // 5^-296
+    (0x82cca4db847945ca, 0x50d98d9fc890ed4d), // 5^-295
+    (0xa37fce126597973c, 0xe50ff107bab528a0), // 5^-294
+    (0xcc5fc196fefd7d0c, 0x1e53ed49a96272c8), // 5^-293
+    (0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7a), // 5^-292
+    (0x9faacf3df73609b1, 0x77b191618c54e9ac), // 5^-291
+    (0xc795830d75038c1d, 0xd59df5b9ef6a2417), // 5^-290
+    (0xf97ae3d0d2446f25, 0x4b0573286b44ad1d), // 5^-289
+    (0x9becce62836ac577, 0x4ee367f9430aec32), // 5^-288
+    (0xc2e801fb244576d5, 0x229c41f793cda73f), // 5^-287
+    (0xf3a20279ed56d48a, 0x6b43527578c1110f), // 5^-286
+    (0x9845418c345644d6, 0x830a13896b78aaa9), // 5^-285
+    (0xbe5691ef416bd60c, 0x23cc986bc656d553), // 5^-284
+    (0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa8), // 5^-283
+    (0x94b3a202eb1c3f39, 0x7bf7d71432f3d6a9), // 5^-282
+    (0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc53), // 5^-281
+    (0xe858ad248f5c22c9, 0xd1b3400f8f9cff68), // 5^-280
+    (0x91376c36d99995be, 0x23100809b9c21fa1), // 5^-279
+    (0xb58547448ffffb2d, 0xabd40a0c2832a78a), // 5^-278
+    (0xe2e69915b3fff9f9, 0x16c90c8f323f516c), // 5^-277
+    (0x8dd01fad907ffc3b, 0xae3da7d97f6792e3), // 5^-276
+    (0xb1442798f49ffb4a, 0x99cd11cfdf41779c), // 5^-275
+    (0xdd95317f31c7fa1d, 0x40405643d711d583), // 5^-274
+    (0x8a7d3eef7f1cfc52, 0x482835ea666b2572), // 5^-273
+    (0xad1c8eab5ee43b66, 0xda3243650005eecf), // 5^-272
+    (0xd863b256369d4a40, 0x90bed43e40076a82), // 5^-271
+    (0x873e4f75e2224e68, 0x5a7744a6e804a291), // 5^-270
+    (0xa90de3535aaae202, 0x711515d0a205cb36), // 5^-269
+    (0xd3515c2831559a83, 0xd5a5b44ca873e03),  // 5^-268
+    (0x8412d9991ed58091, 0xe858790afe9486c2), // 5^-267
+    (0xa5178fff668ae0b6, 0x626e974dbe39a872), // 5^-266
+    (0xce5d73ff402d98e3, 0xfb0a3d212dc8128f), // 5^-265
+    (0x80fa687f881c7f8e, 0x7ce66634bc9d0b99), // 5^-264
+    (0xa139029f6a239f72, 0x1c1fffc1ebc44e80), // 5^-263
+    (0xc987434744ac874e, 0xa327ffb266b56220), // 5^-262
+    (0xfbe9141915d7a922, 0x4bf1ff9f0062baa8), // 5^-261
+    (0x9d71ac8fada6c9b5, 0x6f773fc3603db4a9), // 5^-260
+    (0xc4ce17b399107c22, 0xcb550fb4384d21d3), // 5^-259
+    (0xf6019da07f549b2b, 0x7e2a53a146606a48), // 5^-258
+    (0x99c102844f94e0fb, 0x2eda7444cbfc426d), // 5^-257
+    (0xc0314325637a1939, 0xfa911155fefb5308), // 5^-256
+    (0xf03d93eebc589f88, 0x793555ab7eba27ca), // 5^-255
+    (0x96267c7535b763b5, 0x4bc1558b2f3458de), // 5^-254
+    (0xbbb01b9283253ca2, 0x9eb1aaedfb016f16), // 5^-253
+    (0xea9c227723ee8bcb, 0x465e15a979c1cadc), // 5^-252
+    (0x92a1958a7675175f, 0xbfacd89ec191ec9),  // 5^-251
+    (0xb749faed14125d36, 0xcef980ec671f667b), // 5^-250
+    (0xe51c79a85916f484, 0x82b7e12780e7401a), // 5^-249
+    (0x8f31cc0937ae58d2, 0xd1b2ecb8b0908810), // 5^-248
+    (0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa15), // 5^-247
+    (0xdfbdcece67006ac9, 0x67a791e093e1d49a), // 5^-246
+    (0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e0), // 5^-245
+    (0xaecc49914078536d, 0x58fae9f773886e18), // 5^-244
+    (0xda7f5bf590966848, 0xaf39a475506a899e), // 5^-243
+    (0x888f99797a5e012d, 0x6d8406c952429603), // 5^-242
+    (0xaab37fd7d8f58178, 0xc8e5087ba6d33b83), // 5^-241
+    (0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a64), // 5^-240
+    (0x855c3be0a17fcd26, 0x5cf2eea09a55067f), // 5^-239
+    (0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481e), // 5^-238
+    (0xd0601d8efc57b08b, 0xf13b94daf124da26), // 5^-237
+    (0x823c12795db6ce57, 0x76c53d08d6b70858), // 5^-236
+    (0xa2cb1717b52481ed, 0x54768c4b0c64ca6e), // 5^-235
+    (0xcb7ddcdda26da268, 0xa9942f5dcf7dfd09), // 5^-234
+    (0xfe5d54150b090b02, 0xd3f93b35435d7c4c), // 5^-233
+    (0x9efa548d26e5a6e1, 0xc47bc5014a1a6daf), // 5^-232
+    (0xc6b8e9b0709f109a, 0x359ab6419ca1091b), // 5^-231
+    (0xf867241c8cc6d4c0, 0xc30163d203c94b62), // 5^-230
+    (0x9b407691d7fc44f8, 0x79e0de63425dcf1d), // 5^-229
+    (0xc21094364dfb5636, 0x985915fc12f542e4), // 5^-228
+    (0xf294b943e17a2bc4, 0x3e6f5b7b17b2939d), // 5^-227
+    (0x979cf3ca6cec5b5a, 0xa705992ceecf9c42), // 5^-226
+    (0xbd8430bd08277231, 0x50c6ff782a838353), // 5^-225
+    (0xece53cec4a314ebd, 0xa4f8bf5635246428), // 5^-224
+    (0x940f4613ae5ed136, 0x871b7795e136be99), // 5^-223
+    (0xb913179899f68584, 0x28e2557b59846e3f), // 5^-222
+    (0xe757dd7ec07426e5, 0x331aeada2fe589cf), // 5^-221
+    (0x9096ea6f3848984f, 0x3ff0d2c85def7621), // 5^-220
+    (0xb4bca50b065abe63, 0xfed077a756b53a9),  // 5^-219
+    (0xe1ebce4dc7f16dfb, 0xd3e8495912c62894), // 5^-218
+    (0x8d3360f09cf6e4bd, 0x64712dd7abbbd95c), // 5^-217
+    (0xb080392cc4349dec, 0xbd8d794d96aacfb3), // 5^-216
+    (0xdca04777f541c567, 0xecf0d7a0fc5583a0), // 5^-215
+    (0x89e42caaf9491b60, 0xf41686c49db57244), // 5^-214
+    (0xac5d37d5b79b6239, 0x311c2875c522ced5), // 5^-213
+    (0xd77485cb25823ac7, 0x7d633293366b828b), // 5^-212
+    (0x86a8d39ef77164bc, 0xae5dff9c02033197), // 5^-211
+    (0xa8530886b54dbdeb, 0xd9f57f830283fdfc), // 5^-210
+    (0xd267caa862a12d66, 0xd072df63c324fd7b), // 5^-209
+    (0x8380dea93da4bc60, 0x4247cb9e59f71e6d), // 5^-208
+    (0xa46116538d0deb78, 0x52d9be85f074e608), // 5^-207
+    (0xcd795be870516656, 0x67902e276c921f8b), // 5^-206
+    (0x806bd9714632dff6, 0xba1cd8a3db53b6),   // 5^-205
+    (0xa086cfcd97bf97f3, 0x80e8a40eccd228a4), // 5^-204
+    (0xc8a883c0fdaf7df0, 0x6122cd128006b2cd), // 5^-203
+    (0xfad2a4b13d1b5d6c, 0x796b805720085f81), // 5^-202
+    (0x9cc3a6eec6311a63, 0xcbe3303674053bb0), // 5^-201
+    (0xc3f490aa77bd60fc, 0xbedbfc4411068a9c), // 5^-200
+    (0xf4f1b4d515acb93b, 0xee92fb5515482d44), // 5^-199
+    (0x991711052d8bf3c5, 0x751bdd152d4d1c4a), // 5^-198
+    (0xbf5cd54678eef0b6, 0xd262d45a78a0635d), // 5^-197
+    (0xef340a98172aace4, 0x86fb897116c87c34), // 5^-196
+    (0x9580869f0e7aac0e, 0xd45d35e6ae3d4da0), // 5^-195
+    (0xbae0a846d2195712, 0x8974836059cca109), // 5^-194
+    (0xe998d258869facd7, 0x2bd1a438703fc94b), // 5^-193
+    (0x91ff83775423cc06, 0x7b6306a34627ddcf), // 5^-192
+    (0xb67f6455292cbf08, 0x1a3bc84c17b1d542), // 5^-191
+    (0xe41f3d6a7377eeca, 0x20caba5f1d9e4a93), // 5^-190
+    (0x8e938662882af53e, 0x547eb47b7282ee9c), // 5^-189
+    (0xb23867fb2a35b28d, 0xe99e619a4f23aa43), // 5^-188
+    (0xdec681f9f4c31f31, 0x6405fa00e2ec94d4), // 5^-187
+    (0x8b3c113c38f9f37e, 0xde83bc408dd3dd04), // 5^-186
+    (0xae0b158b4738705e, 0x9624ab50b148d445), // 5^-185
+    (0xd98ddaee19068c76, 0x3badd624dd9b0957), // 5^-184
+    (0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d6), // 5^-183
+    (0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4c), // 5^-182
+    (0xd47487cc8470652b, 0x7647c3200069671f), // 5^-181
+    (0x84c8d4dfd2c63f3b, 0x29ecd9f40041e073), // 5^-180
+    (0xa5fb0a17c777cf09, 0xf468107100525890), // 5^-179
+    (0xcf79cc9db955c2cc, 0x7182148d4066eeb4), // 5^-178
+    (0x81ac1fe293d599bf, 0xc6f14cd848405530), // 5^-177
+    (0xa21727db38cb002f, 0xb8ada00e5a506a7c), // 5^-176
+    (0xca9cf1d206fdc03b, 0xa6d90811f0e4851c), // 5^-175
+    (0xfd442e4688bd304a, 0x908f4a166d1da663), // 5^-174
+    (0x9e4a9cec15763e2e, 0x9a598e4e043287fe), // 5^-173
+    (0xc5dd44271ad3cdba, 0x40eff1e1853f29fd), // 5^-172
+    (0xf7549530e188c128, 0xd12bee59e68ef47c), // 5^-171
+    (0x9a94dd3e8cf578b9, 0x82bb74f8301958ce), // 5^-170
+    (0xc13a148e3032d6e7, 0xe36a52363c1faf01), // 5^-169
+    (0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac1), // 5^-168
+    (0x96f5600f15a7b7e5, 0x29ab103a5ef8c0b9), // 5^-167
+    (0xbcb2b812db11a5de, 0x7415d448f6b6f0e7), // 5^-166
+    (0xebdf661791d60f56, 0x111b495b3464ad21), // 5^-165
+    (0x936b9fcebb25c995, 0xcab10dd900beec34), // 5^-164
+    (0xb84687c269ef3bfb, 0x3d5d514f40eea742), // 5^-163
+    (0xe65829b3046b0afa, 0xcb4a5a3112a5112),  // 5^-162
+    (0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ab), // 5^-161
+    (0xb3f4e093db73a093, 0x59ed216765690f56), // 5^-160
+    (0xe0f218b8d25088b8, 0x306869c13ec3532c), // 5^-159
+    (0x8c974f7383725573, 0x1e414218c73a13fb), // 5^-158
+    (0xafbd2350644eeacf, 0xe5d1929ef90898fa), // 5^-157
+    (0xdbac6c247d62a583, 0xdf45f746b74abf39), // 5^-156
+    (0x894bc396ce5da772, 0x6b8bba8c328eb783), // 5^-155
+    (0xab9eb47c81f5114f, 0x66ea92f3f326564),  // 5^-154
+    (0xd686619ba27255a2, 0xc80a537b0efefebd), // 5^-153
+    (0x8613fd0145877585, 0xbd06742ce95f5f36), // 5^-152
+    (0xa798fc4196e952e7, 0x2c48113823b73704), // 5^-151
+    (0xd17f3b51fca3a7a0, 0xf75a15862ca504c5), // 5^-150
+    (0x82ef85133de648c4, 0x9a984d73dbe722fb), // 5^-149
+    (0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebba), // 5^-148
+    (0xcc963fee10b7d1b3, 0x318df905079926a8), // 5^-147
+    (0xffbbcfe994e5c61f, 0xfdf17746497f7052), // 5^-146
+    (0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa633), // 5^-145
+    (0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc0), // 5^-144
+    (0xf9bd690a1b68637b, 0x3dfdce7aa3c673b0), // 5^-143
+    (0x9c1661a651213e2d, 0x6bea10ca65c084e),  // 5^-142
+    (0xc31bfa0fe5698db8, 0x486e494fcff30a62), // 5^-141
+    (0xf3e2f893dec3f126, 0x5a89dba3c3efccfa), // 5^-140
+    (0x986ddb5c6b3a76b7, 0xf89629465a75e01c), // 5^-139
+    (0xbe89523386091465, 0xf6bbb397f1135823), // 5^-138
+    (0xee2ba6c0678b597f, 0x746aa07ded582e2c), // 5^-137
+    (0x94db483840b717ef, 0xa8c2a44eb4571cdc), // 5^-136
+    (0xba121a4650e4ddeb, 0x92f34d62616ce413), // 5^-135
+    (0xe896a0d7e51e1566, 0x77b020baf9c81d17), // 5^-134
+    (0x915e2486ef32cd60, 0xace1474dc1d122e),  // 5^-133
+    (0xb5b5ada8aaff80b8, 0xd819992132456ba),  // 5^-132
+    (0xe3231912d5bf60e6, 0x10e1fff697ed6c69), // 5^-131
+    (0x8df5efabc5979c8f, 0xca8d3ffa1ef463c1), // 5^-130
+    (0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb2), // 5^-129
+    (0xddd0467c64bce4a0, 0xac7cb3f6d05ddbde), // 5^-128
+    (0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96b), // 5^-127
+    (0xad4ab7112eb3929d, 0x86c16c98d2c953c6), // 5^-126
+    (0xd89d64d57a607744, 0xe871c7bf077ba8b7), // 5^-125
+    (0x87625f056c7c4a8b, 0x11471cd764ad4972), // 5^-124
+    (0xa93af6c6c79b5d2d, 0xd598e40d3dd89bcf), // 5^-123
+    (0xd389b47879823479, 0x4aff1d108d4ec2c3), // 5^-122
+    (0x843610cb4bf160cb, 0xcedf722a585139ba), // 5^-121
+    (0xa54394fe1eedb8fe, 0xc2974eb4ee658828), // 5^-120
+    (0xce947a3da6a9273e, 0x733d226229feea32), // 5^-119
+    (0x811ccc668829b887, 0x806357d5a3f525f),  // 5^-118
+    (0xa163ff802a3426a8, 0xca07c2dcb0cf26f7), // 5^-117
+    (0xc9bcff6034c13052, 0xfc89b393dd02f0b5), // 5^-116
+    (0xfc2c3f3841f17c67, 0xbbac2078d443ace2), // 5^-115
+    (0x9d9ba7832936edc0, 0xd54b944b84aa4c0d), // 5^-114
+    (0xc5029163f384a931, 0xa9e795e65d4df11),  // 5^-113
+    (0xf64335bcf065d37d, 0x4d4617b5ff4a16d5), // 5^-112
+    (0x99ea0196163fa42e, 0x504bced1bf8e4e45), // 5^-111
+    (0xc06481fb9bcf8d39, 0xe45ec2862f71e1d6), // 5^-110
+    (0xf07da27a82c37088, 0x5d767327bb4e5a4c), // 5^-109
+    (0x964e858c91ba2655, 0x3a6a07f8d510f86f), // 5^-108
+    (0xbbe226efb628afea, 0x890489f70a55368b), // 5^-107
+    (0xeadab0aba3b2dbe5, 0x2b45ac74ccea842e), // 5^-106
+    (0x92c8ae6b464fc96f, 0x3b0b8bc90012929d), // 5^-105
+    (0xb77ada0617e3bbcb, 0x9ce6ebb40173744),  // 5^-104
+    (0xe55990879ddcaabd, 0xcc420a6a101d0515), // 5^-103
+    (0x8f57fa54c2a9eab6, 0x9fa946824a12232d), // 5^-102
+    (0xb32df8e9f3546564, 0x47939822dc96abf9), // 5^-101
+    (0xdff9772470297ebd, 0x59787e2b93bc56f7), // 5^-100
+    (0x8bfbea76c619ef36, 0x57eb4edb3c55b65a), // 5^-99
+    (0xaefae51477a06b03, 0xede622920b6b23f1), // 5^-98
+    (0xdab99e59958885c4, 0xe95fab368e45eced), // 5^-97
+    (0x88b402f7fd75539b, 0x11dbcb0218ebb414), // 5^-96
+    (0xaae103b5fcd2a881, 0xd652bdc29f26a119), // 5^-95
+    (0xd59944a37c0752a2, 0x4be76d3346f0495f), // 5^-94
+    (0x857fcae62d8493a5, 0x6f70a4400c562ddb), // 5^-93
+    (0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb952), // 5^-92
+    (0xd097ad07a71f26b2, 0x7e2000a41346a7a7), // 5^-91
+    (0x825ecc24c873782f, 0x8ed400668c0c28c8), // 5^-90
+    (0xa2f67f2dfa90563b, 0x728900802f0f32fa), // 5^-89
+    (0xcbb41ef979346bca, 0x4f2b40a03ad2ffb9), // 5^-88
+    (0xfea126b7d78186bc, 0xe2f610c84987bfa8), // 5^-87
+    (0x9f24b832e6b0f436, 0xdd9ca7d2df4d7c9),  // 5^-86
+    (0xc6ede63fa05d3143, 0x91503d1c79720dbb), // 5^-85
+    (0xf8a95fcf88747d94, 0x75a44c6397ce912a), // 5^-84
+    (0x9b69dbe1b548ce7c, 0xc986afbe3ee11aba), // 5^-83
+    (0xc24452da229b021b, 0xfbe85badce996168), // 5^-82
+    (0xf2d56790ab41c2a2, 0xfae27299423fb9c3), // 5^-81
+    (0x97c560ba6b0919a5, 0xdccd879fc967d41a), // 5^-80
+    (0xbdb6b8e905cb600f, 0x5400e987bbc1c920), // 5^-79
+    (0xed246723473e3813, 0x290123e9aab23b68), // 5^-78
+    (0x9436c0760c86e30b, 0xf9a0b6720aaf6521), // 5^-77
+    (0xb94470938fa89bce, 0xf808e40e8d5b3e69), // 5^-76
+    (0xe7958cb87392c2c2, 0xb60b1d1230b20e04), // 5^-75
+    (0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c2), // 5^-74
+    (0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af3), // 5^-73
+    (0xe2280b6c20dd5232, 0x25c6da63c38de1b0), // 5^-72
+    (0x8d590723948a535f, 0x579c487e5a38ad0e), // 5^-71
+    (0xb0af48ec79ace837, 0x2d835a9df0c6d851), // 5^-70
+    (0xdcdb1b2798182244, 0xf8e431456cf88e65), // 5^-69
+    (0x8a08f0f8bf0f156b, 0x1b8e9ecb641b58ff), // 5^-68
+    (0xac8b2d36eed2dac5, 0xe272467e3d222f3f), // 5^-67
+    (0xd7adf884aa879177, 0x5b0ed81dcc6abb0f), // 5^-66
+    (0x86ccbb52ea94baea, 0x98e947129fc2b4e9), // 5^-65
+    (0xa87fea27a539e9a5, 0x3f2398d747b36224), // 5^-64
+    (0xd29fe4b18e88640e, 0x8eec7f0d19a03aad), // 5^-63
+    (0x83a3eeeef9153e89, 0x1953cf68300424ac), // 5^-62
+    (0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd7), // 5^-61
+    (0xcdb02555653131b6, 0x3792f412cb06794d), // 5^-60
+    (0x808e17555f3ebf11, 0xe2bbd88bbee40bd0), // 5^-59
+    (0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec4), // 5^-58
+    (0xc8de047564d20a8b, 0xf245825a5a445275), // 5^-57
+    (0xfb158592be068d2e, 0xeed6e2f0f0d56712), // 5^-56
+    (0x9ced737bb6c4183d, 0x55464dd69685606b), // 5^-55
+    (0xc428d05aa4751e4c, 0xaa97e14c3c26b886), // 5^-54
+    (0xf53304714d9265df, 0xd53dd99f4b3066a8), // 5^-53
+    (0x993fe2c6d07b7fab, 0xe546a8038efe4029), // 5^-52
+    (0xbf8fdb78849a5f96, 0xde98520472bdd033), // 5^-51
+    (0xef73d256a5c0f77c, 0x963e66858f6d4440), // 5^-50
+    (0x95a8637627989aad, 0xdde7001379a44aa8), // 5^-49
+    (0xbb127c53b17ec159, 0x5560c018580d5d52), // 5^-48
+    (0xe9d71b689dde71af, 0xaab8f01e6e10b4a6), // 5^-47
+    (0x9226712162ab070d, 0xcab3961304ca70e8), // 5^-46
+    (0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d22), // 5^-45
+    (0xe45c10c42a2b3b05, 0x8cb89a7db77c506a), // 5^-44
+    (0x8eb98a7a9a5b04e3, 0x77f3608e92adb242), // 5^-43
+    (0xb267ed1940f1c61c, 0x55f038b237591ed3), // 5^-42
+    (0xdf01e85f912e37a3, 0x6b6c46dec52f6688), // 5^-41
+    (0x8b61313bbabce2c6, 0x2323ac4b3b3da015), // 5^-40
+    (0xae397d8aa96c1b77, 0xabec975e0a0d081a), // 5^-39
+    (0xd9c7dced53c72255, 0x96e7bd358c904a21), // 5^-38
+    (0x881cea14545c7575, 0x7e50d64177da2e54), // 5^-37
+    (0xaa242499697392d2, 0xdde50bd1d5d0b9e9), // 5^-36
+    (0xd4ad2dbfc3d07787, 0x955e4ec64b44e864), // 5^-35
+    (0x84ec3c97da624ab4, 0xbd5af13bef0b113e), // 5^-34
+    (0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58e), // 5^-33
+    (0xcfb11ead453994ba, 0x67de18eda5814af2), // 5^-32
+    (0x81ceb32c4b43fcf4, 0x80eacf948770ced7), // 5^-31
+    (0xa2425ff75e14fc31, 0xa1258379a94d028d), // 5^-30
+    (0xcad2f7f5359a3b3e, 0x96ee45813a04330),  // 5^-29
+    (0xfd87b5f28300ca0d, 0x8bca9d6e188853fc), // 5^-28
+    (0x9e74d1b791e07e48, 0x775ea264cf55347e), // 5^-27
+    (0xc612062576589dda, 0x95364afe032a819e), // 5^-26
+    (0xf79687aed3eec551, 0x3a83ddbd83f52205), // 5^-25
+    (0x9abe14cd44753b52, 0xc4926a9672793543), // 5^-24
+    (0xc16d9a0095928a27, 0x75b7053c0f178294), // 5^-23
+    (0xf1c90080baf72cb1, 0x5324c68b12dd6339), // 5^-22
+    (0x971da05074da7bee, 0xd3f6fc16ebca5e04), // 5^-21
+    (0xbce5086492111aea, 0x88f4bb1ca6bcf585), // 5^-20
+    (0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6), // 5^-19
+    (0x9392ee8e921d5d07, 0x3aff322e62439fd0), // 5^-18
+    (0xb877aa3236a4b449, 0x9befeb9fad487c3),  // 5^-17
+    (0xe69594bec44de15b, 0x4c2ebe687989a9b4), // 5^-16
+    (0x901d7cf73ab0acd9, 0xf9d37014bf60a11),  // 5^-15
+    (0xb424dc35095cd80f, 0x538484c19ef38c95), // 5^-14
+    (0xe12e13424bb40e13, 0x2865a5f206b06fba), // 5^-13
+    (0x8cbccc096f5088cb, 0xf93f87b7442e45d4), // 5^-12
+    (0xafebff0bcb24aafe, 0xf78f69a51539d749), // 5^-11
+    (0xdbe6fecebdedd5be, 0xb573440e5a884d1c), // 5^-10
+    (0x89705f4136b4a597, 0x31680a88f8953031), // 5^-9
+    (0xabcc77118461cefc, 0xfdc20d2b36ba7c3e), // 5^-8
+    (0xd6bf94d5e57a42bc, 0x3d32907604691b4d), // 5^-7
+    (0x8637bd05af6c69b5, 0xa63f9a49c2c1b110), // 5^-6
+    (0xa7c5ac471b478423, 0xfcf80dc33721d54),  // 5^-5
+    (0xd1b71758e219652b, 0xd3c36113404ea4a9), // 5^-4
+    (0x83126e978d4fdf3b, 0x645a1cac083126ea), // 5^-3
+    (0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4), // 5^-2
+    (0xcccccccccccccccc, 0xcccccccccccccccd), // 5^-1
+    (0x8000000000000000, 0x0),                // 5^0
+    (0xa000000000000000, 0x0),                // 5^1
+    (0xc800000000000000, 0x0),                // 5^2
+    (0xfa00000000000000, 0x0),                // 5^3
+    (0x9c40000000000000, 0x0),                // 5^4
+    (0xc350000000000000, 0x0),                // 5^5
+    (0xf424000000000000, 0x0),                // 5^6
+    (0x9896800000000000, 0x0),                // 5^7
+    (0xbebc200000000000, 0x0),                // 5^8
+    (0xee6b280000000000, 0x0),                // 5^9
+    (0x9502f90000000000, 0x0),                // 5^10
+    (0xba43b74000000000, 0x0),                // 5^11
+    (0xe8d4a51000000000, 0x0),                // 5^12
+    (0x9184e72a00000000, 0x0),                // 5^13
+    (0xb5e620f480000000, 0x0),                // 5^14
+    (0xe35fa931a0000000, 0x0),                // 5^15
+    (0x8e1bc9bf04000000, 0x0),                // 5^16
+    (0xb1a2bc2ec5000000, 0x0),                // 5^17
+    (0xde0b6b3a76400000, 0x0),                // 5^18
+    (0x8ac7230489e80000, 0x0),                // 5^19
+    (0xad78ebc5ac620000, 0x0),                // 5^20
+    (0xd8d726b7177a8000, 0x0),                // 5^21
+    (0x878678326eac9000, 0x0),                // 5^22
+    (0xa968163f0a57b400, 0x0),                // 5^23
+    (0xd3c21bcecceda100, 0x0),                // 5^24
+    (0x84595161401484a0, 0x0),                // 5^25
+    (0xa56fa5b99019a5c8, 0x0),                // 5^26
+    (0xcecb8f27f4200f3a, 0x0),                // 5^27
+    (0x813f3978f8940984, 0x4000000000000000), // 5^28
+    (0xa18f07d736b90be5, 0x5000000000000000), // 5^29
+    (0xc9f2c9cd04674ede, 0xa400000000000000), // 5^30
+    (0xfc6f7c4045812296, 0x4d00000000000000), // 5^31
+    (0x9dc5ada82b70b59d, 0xf020000000000000), // 5^32
+    (0xc5371912364ce305, 0x6c28000000000000), // 5^33
+    (0xf684df56c3e01bc6, 0xc732000000000000), // 5^34
+    (0x9a130b963a6c115c, 0x3c7f400000000000), // 5^35
+    (0xc097ce7bc90715b3, 0x4b9f100000000000), // 5^36
+    (0xf0bdc21abb48db20, 0x1e86d40000000000), // 5^37
+    (0x96769950b50d88f4, 0x1314448000000000), // 5^38
+    (0xbc143fa4e250eb31, 0x17d955a000000000), // 5^39
+    (0xeb194f8e1ae525fd, 0x5dcfab0800000000), // 5^40
+    (0x92efd1b8d0cf37be, 0x5aa1cae500000000), // 5^41
+    (0xb7abc627050305ad, 0xf14a3d9e40000000), // 5^42
+    (0xe596b7b0c643c719, 0x6d9ccd05d0000000), // 5^43
+    (0x8f7e32ce7bea5c6f, 0xe4820023a2000000), // 5^44
+    (0xb35dbf821ae4f38b, 0xdda2802c8a800000), // 5^45
+    (0xe0352f62a19e306e, 0xd50b2037ad200000), // 5^46
+    (0x8c213d9da502de45, 0x4526f422cc340000), // 5^47
+    (0xaf298d050e4395d6, 0x9670b12b7f410000), // 5^48
+    (0xdaf3f04651d47b4c, 0x3c0cdd765f114000), // 5^49
+    (0x88d8762bf324cd0f, 0xa5880a69fb6ac800), // 5^50
+    (0xab0e93b6efee0053, 0x8eea0d047a457a00), // 5^51
+    (0xd5d238a4abe98068, 0x72a4904598d6d880), // 5^52
+    (0x85a36366eb71f041, 0x47a6da2b7f864750), // 5^53
+    (0xa70c3c40a64e6c51, 0x999090b65f67d924), // 5^54
+    (0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d), // 5^55
+    (0x82818f1281ed449f, 0xbff8f10e7a8921a4), // 5^56
+    (0xa321f2d7226895c7, 0xaff72d52192b6a0d), // 5^57
+    (0xcbea6f8ceb02bb39, 0x9bf4f8a69f764490), // 5^58
+    (0xfee50b7025c36a08, 0x2f236d04753d5b4),  // 5^59
+    (0x9f4f2726179a2245, 0x1d762422c946590),  // 5^60
+    (0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef5), // 5^61
+    (0xf8ebad2b84e0d58b, 0xd2e0898765a7deb2), // 5^62
+    (0x9b934c3b330c8577, 0x63cc55f49f88eb2f), // 5^63
+    (0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fb), // 5^64
+    (0xf316271c7fc3908a, 0x8bef464e3945ef7a), // 5^65
+    (0x97edd871cfda3a56, 0x97758bf0e3cbb5ac), // 5^66
+    (0xbde94e8e43d0c8ec, 0x3d52eeed1cbea317), // 5^67
+    (0xed63a231d4c4fb27, 0x4ca7aaa863ee4bdd), // 5^68
+    (0x945e455f24fb1cf8, 0x8fe8caa93e74ef6a), // 5^69
+    (0xb975d6b6ee39e436, 0xb3e2fd538e122b44), // 5^70
+    (0xe7d34c64a9c85d44, 0x60dbbca87196b616), // 5^71
+    (0x90e40fbeea1d3a4a, 0xbc8955e946fe31cd), // 5^72
+    (0xb51d13aea4a488dd, 0x6babab6398bdbe41), // 5^73
+    (0xe264589a4dcdab14, 0xc696963c7eed2dd1), // 5^74
+    (0x8d7eb76070a08aec, 0xfc1e1de5cf543ca2), // 5^75
+    (0xb0de65388cc8ada8, 0x3b25a55f43294bcb), // 5^76
+    (0xdd15fe86affad912, 0x49ef0eb713f39ebe), // 5^77
+    (0x8a2dbf142dfcc7ab, 0x6e3569326c784337), // 5^78
+    (0xacb92ed9397bf996, 0x49c2c37f07965404), // 5^79
+    (0xd7e77a8f87daf7fb, 0xdc33745ec97be906), // 5^80
+    (0x86f0ac99b4e8dafd, 0x69a028bb3ded71a3), // 5^81
+    (0xa8acd7c0222311bc, 0xc40832ea0d68ce0c), // 5^82
+    (0xd2d80db02aabd62b, 0xf50a3fa490c30190), // 5^83
+    (0x83c7088e1aab65db, 0x792667c6da79e0fa), // 5^84
+    (0xa4b8cab1a1563f52, 0x577001b891185938), // 5^85
+    (0xcde6fd5e09abcf26, 0xed4c0226b55e6f86), // 5^86
+    (0x80b05e5ac60b6178, 0x544f8158315b05b4), // 5^87
+    (0xa0dc75f1778e39d6, 0x696361ae3db1c721), // 5^88
+    (0xc913936dd571c84c, 0x3bc3a19cd1e38e9),  // 5^89
+    (0xfb5878494ace3a5f, 0x4ab48a04065c723),  // 5^90
+    (0x9d174b2dcec0e47b, 0x62eb0d64283f9c76), // 5^91
+    (0xc45d1df942711d9a, 0x3ba5d0bd324f8394), // 5^92
+    (0xf5746577930d6500, 0xca8f44ec7ee36479), // 5^93
+    (0x9968bf6abbe85f20, 0x7e998b13cf4e1ecb), // 5^94
+    (0xbfc2ef456ae276e8, 0x9e3fedd8c321a67e), // 5^95
+    (0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101e), // 5^96
+    (0x95d04aee3b80ece5, 0xbba1f1d158724a12), // 5^97
+    (0xbb445da9ca61281f, 0x2a8a6e45ae8edc97), // 5^98
+    (0xea1575143cf97226, 0xf52d09d71a3293bd), // 5^99
+    (0x924d692ca61be758, 0x593c2626705f9c56), // 5^100
+    (0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836c), // 5^101
+    (0xe498f455c38b997a, 0xb6dfb9c0f956447),  // 5^102
+    (0x8edf98b59a373fec, 0x4724bd4189bd5eac), // 5^103
+    (0xb2977ee300c50fe7, 0x58edec91ec2cb657), // 5^104
+    (0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ed), // 5^105
+    (0x8b865b215899f46c, 0xbd79e0d20082ee74), // 5^106
+    (0xae67f1e9aec07187, 0xecd8590680a3aa11), // 5^107
+    (0xda01ee641a708de9, 0xe80e6f4820cc9495), // 5^108
+    (0x884134fe908658b2, 0x3109058d147fdcdd), // 5^109
+    (0xaa51823e34a7eede, 0xbd4b46f0599fd415), // 5^110
+    (0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91a), // 5^111
+    (0x850fadc09923329e, 0x3e2cf6bc604ddb0),  // 5^112
+    (0xa6539930bf6bff45, 0x84db8346b786151c), // 5^113
+    (0xcfe87f7cef46ff16, 0xe612641865679a63), // 5^114
+    (0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07e), // 5^115
+    (0xa26da3999aef7749, 0xe3be5e330f38f09d), // 5^116
+    (0xcb090c8001ab551c, 0x5cadf5bfd3072cc5), // 5^117
+    (0xfdcb4fa002162a63, 0x73d9732fc7c8f7f6), // 5^118
+    (0x9e9f11c4014dda7e, 0x2867e7fddcdd9afa), // 5^119
+    (0xc646d63501a1511d, 0xb281e1fd541501b8), // 5^120
+    (0xf7d88bc24209a565, 0x1f225a7ca91a4226), // 5^121
+    (0x9ae757596946075f, 0x3375788de9b06958), // 5^122
+    (0xc1a12d2fc3978937, 0x52d6b1641c83ae),   // 5^123
+    (0xf209787bb47d6b84, 0xc0678c5dbd23a49a), // 5^124
+    (0x9745eb4d50ce6332, 0xf840b7ba963646e0), // 5^125
+    (0xbd176620a501fbff, 0xb650e5a93bc3d898), // 5^126
+    (0xec5d3fa8ce427aff, 0xa3e51f138ab4cebe), // 5^127
+    (0x93ba47c980e98cdf, 0xc66f336c36b10137), // 5^128
+    (0xb8a8d9bbe123f017, 0xb80b0047445d4184), // 5^129
+    (0xe6d3102ad96cec1d, 0xa60dc059157491e5), // 5^130
+    (0x9043ea1ac7e41392, 0x87c89837ad68db2f), // 5^131
+    (0xb454e4a179dd1877, 0x29babe4598c311fb), // 5^132
+    (0xe16a1dc9d8545e94, 0xf4296dd6fef3d67a), // 5^133
+    (0x8ce2529e2734bb1d, 0x1899e4a65f58660c), // 5^134
+    (0xb01ae745b101e9e4, 0x5ec05dcff72e7f8f), // 5^135
+    (0xdc21a1171d42645d, 0x76707543f4fa1f73), // 5^136
+    (0x899504ae72497eba, 0x6a06494a791c53a8), // 5^137
+    (0xabfa45da0edbde69, 0x487db9d17636892),  // 5^138
+    (0xd6f8d7509292d603, 0x45a9d2845d3c42b6), // 5^139
+    (0x865b86925b9bc5c2, 0xb8a2392ba45a9b2),  // 5^140
+    (0xa7f26836f282b732, 0x8e6cac7768d7141e), // 5^141
+    (0xd1ef0244af2364ff, 0x3207d795430cd926), // 5^142
+    (0x8335616aed761f1f, 0x7f44e6bd49e807b8), // 5^143
+    (0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a6), // 5^144
+    (0xcd036837130890a1, 0x36dba887c37a8c0f), // 5^145
+    (0x802221226be55a64, 0xc2494954da2c9789), // 5^146
+    (0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6c), // 5^147
+    (0xc83553c5c8965d3d, 0x6f92829494e5acc7), // 5^148
+    (0xfa42a8b73abbf48c, 0xcb772339ba1f17f9), // 5^149
+    (0x9c69a97284b578d7, 0xff2a760414536efb), // 5^150
+    (0xc38413cf25e2d70d, 0xfef5138519684aba), // 5^151
+    (0xf46518c2ef5b8cd1, 0x7eb258665fc25d69), // 5^152
+    (0x98bf2f79d5993802, 0xef2f773ffbd97a61), // 5^153
+    (0xbeeefb584aff8603, 0xaafb550ffacfd8fa), // 5^154
+    (0xeeaaba2e5dbf6784, 0x95ba2a53f983cf38), // 5^155
+    (0x952ab45cfa97a0b2, 0xdd945a747bf26183), // 5^156
+    (0xba756174393d88df, 0x94f971119aeef9e4), // 5^157
+    (0xe912b9d1478ceb17, 0x7a37cd5601aab85d), // 5^158
+    (0x91abb422ccb812ee, 0xac62e055c10ab33a), // 5^159
+    (0xb616a12b7fe617aa, 0x577b986b314d6009), // 5^160
+    (0xe39c49765fdf9d94, 0xed5a7e85fda0b80b), // 5^161
+    (0x8e41ade9fbebc27d, 0x14588f13be847307), // 5^162
+    (0xb1d219647ae6b31c, 0x596eb2d8ae258fc8), // 5^163
+    (0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bb), // 5^164
+    (0x8aec23d680043bee, 0x25de7bb9480d5854), // 5^165
+    (0xada72ccc20054ae9, 0xaf561aa79a10ae6a), // 5^166
+    (0xd910f7ff28069da4, 0x1b2ba1518094da04), // 5^167
+    (0x87aa9aff79042286, 0x90fb44d2f05d0842), // 5^168
+    (0xa99541bf57452b28, 0x353a1607ac744a53), // 5^169
+    (0xd3fa922f2d1675f2, 0x42889b8997915ce8), // 5^170
+    (0x847c9b5d7c2e09b7, 0x69956135febada11), // 5^171
+    (0xa59bc234db398c25, 0x43fab9837e699095), // 5^172
+    (0xcf02b2c21207ef2e, 0x94f967e45e03f4bb), // 5^173
+    (0x8161afb94b44f57d, 0x1d1be0eebac278f5), // 5^174
+    (0xa1ba1ba79e1632dc, 0x6462d92a69731732), // 5^175
+    (0xca28a291859bbf93, 0x7d7b8f7503cfdcfe), // 5^176
+    (0xfcb2cb35e702af78, 0x5cda735244c3d43e), // 5^177
+    (0x9defbf01b061adab, 0x3a0888136afa64a7), // 5^178
+    (0xc56baec21c7a1916, 0x88aaa1845b8fdd0),  // 5^179
+    (0xf6c69a72a3989f5b, 0x8aad549e57273d45), // 5^180
+    (0x9a3c2087a63f6399, 0x36ac54e2f678864b), // 5^181
+    (0xc0cb28a98fcf3c7f, 0x84576a1bb416a7dd), // 5^182
+    (0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d5), // 5^183
+    (0x969eb7c47859e743, 0x9f644ae5a4b1b325), // 5^184
+    (0xbc4665b596706114, 0x873d5d9f0dde1fee), // 5^185
+    (0xeb57ff22fc0c7959, 0xa90cb506d155a7ea), // 5^186
+    (0x9316ff75dd87cbd8, 0x9a7f12442d588f2),  // 5^187
+    (0xb7dcbf5354e9bece, 0xc11ed6d538aeb2f),  // 5^188
+    (0xe5d3ef282a242e81, 0x8f1668c8a86da5fa), // 5^189
+    (0x8fa475791a569d10, 0xf96e017d694487bc), // 5^190
+    (0xb38d92d760ec4455, 0x37c981dcc395a9ac), // 5^191
+    (0xe070f78d3927556a, 0x85bbe253f47b1417), // 5^192
+    (0x8c469ab843b89562, 0x93956d7478ccec8e), // 5^193
+    (0xaf58416654a6babb, 0x387ac8d1970027b2), // 5^194
+    (0xdb2e51bfe9d0696a, 0x6997b05fcc0319e),  // 5^195
+    (0x88fcf317f22241e2, 0x441fece3bdf81f03), // 5^196
+    (0xab3c2fddeeaad25a, 0xd527e81cad7626c3), // 5^197
+    (0xd60b3bd56a5586f1, 0x8a71e223d8d3b074), // 5^198
+    (0x85c7056562757456, 0xf6872d5667844e49), // 5^199
+    (0xa738c6bebb12d16c, 0xb428f8ac016561db), // 5^200
+    (0xd106f86e69d785c7, 0xe13336d701beba52), // 5^201
+    (0x82a45b450226b39c, 0xecc0024661173473), // 5^202
+    (0xa34d721642b06084, 0x27f002d7f95d0190), // 5^203
+    (0xcc20ce9bd35c78a5, 0x31ec038df7b441f4), // 5^204
+    (0xff290242c83396ce, 0x7e67047175a15271), // 5^205
+    (0x9f79a169bd203e41, 0xf0062c6e984d386),  // 5^206
+    (0xc75809c42c684dd1, 0x52c07b78a3e60868), // 5^207
+    (0xf92e0c3537826145, 0xa7709a56ccdf8a82), // 5^208
+    (0x9bbcc7a142b17ccb, 0x88a66076400bb691), // 5^209
+    (0xc2abf989935ddbfe, 0x6acff893d00ea435), // 5^210
+    (0xf356f7ebf83552fe, 0x583f6b8c4124d43),  // 5^211
+    (0x98165af37b2153de, 0xc3727a337a8b704a), // 5^212
+    (0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5c), // 5^213
+    (0xeda2ee1c7064130c, 0x1162def06f79df73), // 5^214
+    (0x9485d4d1c63e8be7, 0x8addcb5645ac2ba8), // 5^215
+    (0xb9a74a0637ce2ee1, 0x6d953e2bd7173692), // 5^216
+    (0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0437), // 5^217
+    (0x910ab1d4db9914a0, 0x1d9c9892400a22a2), // 5^218
+    (0xb54d5e4a127f59c8, 0x2503beb6d00cab4b), // 5^219
+    (0xe2a0b5dc971f303a, 0x2e44ae64840fd61d), // 5^220
+    (0x8da471a9de737e24, 0x5ceaecfed289e5d2), // 5^221
+    (0xb10d8e1456105dad, 0x7425a83e872c5f47), // 5^222
+    (0xdd50f1996b947518, 0xd12f124e28f77719), // 5^223
+    (0x8a5296ffe33cc92f, 0x82bd6b70d99aaa6f), // 5^224
+    (0xace73cbfdc0bfb7b, 0x636cc64d1001550b), // 5^225
+    (0xd8210befd30efa5a, 0x3c47f7e05401aa4e), // 5^226
+    (0x8714a775e3e95c78, 0x65acfaec34810a71), // 5^227
+    (0xa8d9d1535ce3b396, 0x7f1839a741a14d0d), // 5^228
+    (0xd31045a8341ca07c, 0x1ede48111209a050), // 5^229
+    (0x83ea2b892091e44d, 0x934aed0aab460432), // 5^230
+    (0xa4e4b66b68b65d60, 0xf81da84d5617853f), // 5^231
+    (0xce1de40642e3f4b9, 0x36251260ab9d668e), // 5^232
+    (0x80d2ae83e9ce78f3, 0xc1d72b7c6b426019), // 5^233
+    (0xa1075a24e4421730, 0xb24cf65b8612f81f), // 5^234
+    (0xc94930ae1d529cfc, 0xdee033f26797b627), // 5^235
+    (0xfb9b7cd9a4a7443c, 0x169840ef017da3b1), // 5^236
+    (0x9d412e0806e88aa5, 0x8e1f289560ee864e), // 5^237
+    (0xc491798a08a2ad4e, 0xf1a6f2bab92a27e2), // 5^238
+    (0xf5b5d7ec8acb58a2, 0xae10af696774b1db), // 5^239
+    (0x9991a6f3d6bf1765, 0xacca6da1e0a8ef29), // 5^240
+    (0xbff610b0cc6edd3f, 0x17fd090a58d32af3), // 5^241
+    (0xeff394dcff8a948e, 0xddfc4b4cef07f5b0), // 5^242
+    (0x95f83d0a1fb69cd9, 0x4abdaf101564f98e), // 5^243
+    (0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f1), // 5^244
+    (0xea53df5fd18d5513, 0x84c86189216dc5ed), // 5^245
+    (0x92746b9be2f8552c, 0x32fd3cf5b4e49bb4), // 5^246
+    (0xb7118682dbb66a77, 0x3fbc8c33221dc2a1), // 5^247
+    (0xe4d5e82392a40515, 0xfabaf3feaa5334a),  // 5^248
+    (0x8f05b1163ba6832d, 0x29cb4d87f2a7400e), // 5^249
+    (0xb2c71d5bca9023f8, 0x743e20e9ef511012), // 5^250
+    (0xdf78e4b2bd342cf6, 0x914da9246b255416), // 5^251
+    (0x8bab8eefb6409c1a, 0x1ad089b6c2f7548e), // 5^252
+    (0xae9672aba3d0c320, 0xa184ac2473b529b1), // 5^253
+    (0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741e), // 5^254
+    (0x8865899617fb1871, 0x7e2fa67c7a658892), // 5^255
+    (0xaa7eebfb9df9de8d, 0xddbb901b98feeab7), // 5^256
+    (0xd51ea6fa85785631, 0x552a74227f3ea565), // 5^257
+    (0x8533285c936b35de, 0xd53a88958f87275f), // 5^258
+    (0xa67ff273b8460356, 0x8a892abaf368f137), // 5^259
+    (0xd01fef10a657842c, 0x2d2b7569b0432d85), // 5^260
+    (0x8213f56a67f6b29b, 0x9c3b29620e29fc73), // 5^261
+    (0xa298f2c501f45f42, 0x8349f3ba91b47b8f), // 5^262
+    (0xcb3f2f7642717713, 0x241c70a936219a73), // 5^263
+    (0xfe0efb53d30dd4d7, 0xed238cd383aa0110), // 5^264
+    (0x9ec95d1463e8a506, 0xf4363804324a40aa), // 5^265
+    (0xc67bb4597ce2ce48, 0xb143c6053edcd0d5), // 5^266
+    (0xf81aa16fdc1b81da, 0xdd94b7868e94050a), // 5^267
+    (0x9b10a4e5e9913128, 0xca7cf2b4191c8326), // 5^268
+    (0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f0), // 5^269
+    (0xf24a01a73cf2dccf, 0xbc633b39673c8cec), // 5^270
+    (0x976e41088617ca01, 0xd5be0503e085d813), // 5^271
+    (0xbd49d14aa79dbc82, 0x4b2d8644d8a74e18), // 5^272
+    (0xec9c459d51852ba2, 0xddf8e7d60ed1219e), // 5^273
+    (0x93e1ab8252f33b45, 0xcabb90e5c942b503), // 5^274
+    (0xb8da1662e7b00a17, 0x3d6a751f3b936243), // 5^275
+    (0xe7109bfba19c0c9d, 0xcc512670a783ad4),  // 5^276
+    (0x906a617d450187e2, 0x27fb2b80668b24c5), // 5^277
+    (0xb484f9dc9641e9da, 0xb1f9f660802dedf6), // 5^278
+    (0xe1a63853bbd26451, 0x5e7873f8a0396973), // 5^279
+    (0x8d07e33455637eb2, 0xdb0b487b6423e1e8), // 5^280
+    (0xb049dc016abc5e5f, 0x91ce1a9a3d2cda62), // 5^281
+    (0xdc5c5301c56b75f7, 0x7641a140cc7810fb), // 5^282
+    (0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9d), // 5^283
+    (0xac2820d9623bf429, 0x546345fa9fbdcd44), // 5^284
+    (0xd732290fbacaf133, 0xa97c177947ad4095), // 5^285
+    (0x867f59a9d4bed6c0, 0x49ed8eabcccc485d), // 5^286
+    (0xa81f301449ee8c70, 0x5c68f256bfff5a74), // 5^287
+    (0xd226fc195c6a2f8c, 0x73832eec6fff3111), // 5^288
+    (0x83585d8fd9c25db7, 0xc831fd53c5ff7eab), // 5^289
+    (0xa42e74f3d032f525, 0xba3e7ca8b77f5e55), // 5^290
+    (0xcd3a1230c43fb26f, 0x28ce1bd2e55f35eb), // 5^291
+    (0x80444b5e7aa7cf85, 0x7980d163cf5b81b3), // 5^292
+    (0xa0555e361951c366, 0xd7e105bcc332621f), // 5^293
+    (0xc86ab5c39fa63440, 0x8dd9472bf3fefaa7), // 5^294
+    (0xfa856334878fc150, 0xb14f98f6f0feb951), // 5^295
+    (0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d3), // 5^296
+    (0xc3b8358109e84f07, 0xa862f80ec4700c8),  // 5^297
+    (0xf4a642e14c6262c8, 0xcd27bb612758c0fa), // 5^298
+    (0x98e7e9cccfbd7dbd, 0x8038d51cb897789c), // 5^299
+    (0xbf21e44003acdd2c, 0xe0470a63e6bd56c3), // 5^300
+    (0xeeea5d5004981478, 0x1858ccfce06cac74), // 5^301
+    (0x95527a5202df0ccb, 0xf37801e0c43ebc8),  // 5^302
+    (0xbaa718e68396cffd, 0xd30560258f54e6ba), // 5^303
+    (0xe950df20247c83fd, 0x47c6b82ef32a2069), // 5^304
+    (0x91d28b7416cdd27e, 0x4cdc331d57fa5441), // 5^305
+    (0xb6472e511c81471d, 0xe0133fe4adf8e952), // 5^306
+    (0xe3d8f9e563a198e5, 0x58180fddd97723a6), // 5^307
+    (0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648), // 5^308
 ];
index e2cc8faf8547d18157550b5621440060e38933fe..cdeba9c0792738be5fb55ebe76cf8f9f604172f5 100644 (file)
@@ -74,26 +74,20 @@ pub struct ParseIntError {
 /// # Example
 ///
 /// ```
-/// #![feature(int_error_matching)]
-///
 /// # fn main() {
 /// if let Err(e) = i32::from_str_radix("a12", 10) {
 ///     println!("Failed conversion to i32: {:?}", e.kind());
 /// }
 /// # }
 /// ```
-#[unstable(
-    feature = "int_error_matching",
-    reason = "it can be useful to match errors when making error messages \
-              for integer parsing",
-    issue = "22639"
-)]
+#[stable(feature = "int_error_matching", since = "1.55.0")]
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[non_exhaustive]
 pub enum IntErrorKind {
     /// Value being parsed is empty.
     ///
-    /// Among other causes, this variant will be constructed when parsing an empty string.
+    /// This variant will be constructed when parsing an empty string.
+    #[stable(feature = "int_error_matching", since = "1.55.0")]
     Empty,
     /// Contains an invalid digit in its context.
     ///
@@ -102,26 +96,25 @@ pub enum IntErrorKind {
     ///
     /// This variant is also constructed when a `+` or `-` is misplaced within a string
     /// either on its own or in the middle of a number.
+    #[stable(feature = "int_error_matching", since = "1.55.0")]
     InvalidDigit,
     /// Integer is too large to store in target integer type.
+    #[stable(feature = "int_error_matching", since = "1.55.0")]
     PosOverflow,
     /// Integer is too small to store in target integer type.
+    #[stable(feature = "int_error_matching", since = "1.55.0")]
     NegOverflow,
     /// Value was Zero
     ///
     /// This variant will be emitted when the parsing string has a value of zero, which
     /// would be illegal for non-zero types.
+    #[stable(feature = "int_error_matching", since = "1.55.0")]
     Zero,
 }
 
 impl ParseIntError {
     /// Outputs the detailed cause of parsing an integer failing.
-    #[unstable(
-        feature = "int_error_matching",
-        reason = "it can be useful to match errors when making error messages \
-              for integer parsing",
-        issue = "22639"
-    )]
+    #[stable(feature = "int_error_matching", since = "1.55.0")]
     pub fn kind(&self) -> &IntErrorKind {
         &self.kind
     }
index c43536c6fcca86585db29821f1772c2f3fbc94dc..5763860540aa49511951ec2b661afc1bbeb1a7f2 100644 (file)
@@ -1,6 +1,6 @@
 //! Decodes a floating-point value into individual parts and error ranges.
 
-use crate::num::dec2flt::rawfp::RawFloat;
+use crate::num::dec2flt::float::RawFloat;
 use crate::num::FpCategory;
 
 /// Decoded unsigned finite value, such that:
index 93bdf5040e08b52f54e31365aa2e05e9d61bed6a..1ff2e8c8228c98122be1a2b35349f7b2b647bc6a 100644 (file)
@@ -49,7 +49,7 @@ the supplied buffer and let the algorithm to return.
 # Implementation overview
 
 It is easy to get the floating point printing correct but slow (Russ Cox has
-[demonstrated](http://research.swtch.com/ftoa) how it's easy), or incorrect but
+[demonstrated](https://research.swtch.com/ftoa) how it's easy), or incorrect but
 fast (naïve division and modulo). But it is surprisingly hard to print
 floating point numbers correctly *and* efficiently.
 
@@ -124,6 +124,7 @@ functions.
 
 pub use self::decoder::{decode, DecodableFloat, Decoded, FullDecoded};
 
+use super::fmt::{Formatted, Part};
 use crate::mem::MaybeUninit;
 
 pub mod decoder;
@@ -170,107 +171,6 @@ pub fn round_up(d: &mut [u8]) -> Option<u8> {
     }
 }
 
-/// Formatted parts.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum Part<'a> {
-    /// Given number of zero digits.
-    Zero(usize),
-    /// A literal number up to 5 digits.
-    Num(u16),
-    /// A verbatim copy of given bytes.
-    Copy(&'a [u8]),
-}
-
-impl<'a> Part<'a> {
-    /// Returns the exact byte length of given part.
-    pub fn len(&self) -> usize {
-        match *self {
-            Part::Zero(nzeroes) => nzeroes,
-            Part::Num(v) => {
-                if v < 1_000 {
-                    if v < 10 {
-                        1
-                    } else if v < 100 {
-                        2
-                    } else {
-                        3
-                    }
-                } else {
-                    if v < 10_000 { 4 } else { 5 }
-                }
-            }
-            Part::Copy(buf) => buf.len(),
-        }
-    }
-
-    /// Writes a part into the supplied buffer.
-    /// Returns the number of written bytes, or `None` if the buffer is not enough.
-    /// (It may still leave partially written bytes in the buffer; do not rely on that.)
-    pub fn write(&self, out: &mut [u8]) -> Option<usize> {
-        let len = self.len();
-        if out.len() >= len {
-            match *self {
-                Part::Zero(nzeroes) => {
-                    for c in &mut out[..nzeroes] {
-                        *c = b'0';
-                    }
-                }
-                Part::Num(mut v) => {
-                    for c in out[..len].iter_mut().rev() {
-                        *c = b'0' + (v % 10) as u8;
-                        v /= 10;
-                    }
-                }
-                Part::Copy(buf) => {
-                    out[..buf.len()].copy_from_slice(buf);
-                }
-            }
-            Some(len)
-        } else {
-            None
-        }
-    }
-}
-
-/// Formatted result containing one or more parts.
-/// This can be written to the byte buffer or converted to the allocated string.
-#[allow(missing_debug_implementations)]
-#[derive(Clone)]
-pub struct Formatted<'a> {
-    /// A byte slice representing a sign, either `""`, `"-"` or `"+"`.
-    pub sign: &'static str,
-    /// Formatted parts to be rendered after a sign and optional zero padding.
-    pub parts: &'a [Part<'a>],
-}
-
-impl<'a> Formatted<'a> {
-    /// Returns the exact byte length of combined formatted result.
-    pub fn len(&self) -> usize {
-        let mut len = self.sign.len();
-        for part in self.parts {
-            len += part.len();
-        }
-        len
-    }
-
-    /// Writes all formatted parts into the supplied buffer.
-    /// Returns the number of written bytes, or `None` if the buffer is not enough.
-    /// (It may still leave partially written bytes in the buffer; do not rely on that.)
-    pub fn write(&self, out: &mut [u8]) -> Option<usize> {
-        if out.len() < self.sign.len() {
-            return None;
-        }
-        out[..self.sign.len()].copy_from_slice(self.sign.as_bytes());
-
-        let mut written = self.sign.len();
-        for part in self.parts {
-            let len = part.write(&mut out[written..])?;
-            written += len;
-        }
-        Some(written)
-    }
-}
-
 /// Formats given decimal digits `0.<...buf...> * 10^exp` into the decimal form
 /// with at least given number of fractional digits. The result is stored to
 /// the supplied parts array and a slice of written parts is returned.
diff --git a/library/core/src/num/fmt.rs b/library/core/src/num/fmt.rs
new file mode 100644 (file)
index 0000000..578288b
--- /dev/null
@@ -0,0 +1,108 @@
+//! Shared utilties used by both float and integer formatting.
+#![doc(hidden)]
+#![unstable(
+    feature = "numfmt",
+    reason = "internal routines only exposed for testing",
+    issue = "none"
+)]
+
+/// Formatted parts.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum Part<'a> {
+    /// Given number of zero digits.
+    Zero(usize),
+    /// A literal number up to 5 digits.
+    Num(u16),
+    /// A verbatim copy of given bytes.
+    Copy(&'a [u8]),
+}
+
+impl<'a> Part<'a> {
+    /// Returns the exact byte length of given part.
+    pub fn len(&self) -> usize {
+        match *self {
+            Part::Zero(nzeroes) => nzeroes,
+            Part::Num(v) => {
+                if v < 1_000 {
+                    if v < 10 {
+                        1
+                    } else if v < 100 {
+                        2
+                    } else {
+                        3
+                    }
+                } else {
+                    if v < 10_000 { 4 } else { 5 }
+                }
+            }
+            Part::Copy(buf) => buf.len(),
+        }
+    }
+
+    /// Writes a part into the supplied buffer.
+    /// Returns the number of written bytes, or `None` if the buffer is not enough.
+    /// (It may still leave partially written bytes in the buffer; do not rely on that.)
+    pub fn write(&self, out: &mut [u8]) -> Option<usize> {
+        let len = self.len();
+        if out.len() >= len {
+            match *self {
+                Part::Zero(nzeroes) => {
+                    for c in &mut out[..nzeroes] {
+                        *c = b'0';
+                    }
+                }
+                Part::Num(mut v) => {
+                    for c in out[..len].iter_mut().rev() {
+                        *c = b'0' + (v % 10) as u8;
+                        v /= 10;
+                    }
+                }
+                Part::Copy(buf) => {
+                    out[..buf.len()].copy_from_slice(buf);
+                }
+            }
+            Some(len)
+        } else {
+            None
+        }
+    }
+}
+
+/// Formatted result containing one or more parts.
+/// This can be written to the byte buffer or converted to the allocated string.
+#[allow(missing_debug_implementations)]
+#[derive(Clone)]
+pub struct Formatted<'a> {
+    /// A byte slice representing a sign, either `""`, `"-"` or `"+"`.
+    pub sign: &'static str,
+    /// Formatted parts to be rendered after a sign and optional zero padding.
+    pub parts: &'a [Part<'a>],
+}
+
+impl<'a> Formatted<'a> {
+    /// Returns the exact byte length of combined formatted result.
+    pub fn len(&self) -> usize {
+        let mut len = self.sign.len();
+        for part in self.parts {
+            len += part.len();
+        }
+        len
+    }
+
+    /// Writes all formatted parts into the supplied buffer.
+    /// Returns the number of written bytes, or `None` if the buffer is not enough.
+    /// (It may still leave partially written bytes in the buffer; do not rely on that.)
+    pub fn write(&self, out: &mut [u8]) -> Option<usize> {
+        if out.len() < self.sign.len() {
+            return None;
+        }
+        out[..self.sign.len()].copy_from_slice(self.sign.as_bytes());
+
+        let mut written = self.sign.len();
+        for part in self.parts {
+            let len = part.write(&mut out[written..])?;
+            written += len;
+        }
+        Some(written)
+    }
+}
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 a0efe681285b46b5256f08348e7f5739b7cb3381..982729388c87dc6ebbf918bbdd03685849c0abb0 100644 (file)
@@ -1744,6 +1744,197 @@ macro_rules! int_impl {
             }
         }
 
+        /// 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
@@ -1772,9 +1963,9 @@ macro_rules! int_impl {
         #[inline]
         #[rustc_inherit_overflow_checks]
         pub const fn abs(self) -> Self {
-            // Note that the #[inline] above means that the overflow
-            // semantics of the subtraction depend on the crate we're being
-            // inlined into.
+            // Note that the #[rustc_inherit_overflow_checks] and #[inline]
+            // above mean that the overflow semantics of the subtraction
+            // depend on the crate we're being called from.
             if self.is_negative() {
                 -self
             } else {
index 6032dc9a2d371c610829b79f2a4c748cee1a9c15..26d84a60702c56b30dfd8f8918021627d9882b18 100644 (file)
@@ -25,10 +25,15 @@ macro_rules! unlikely {
 }
 
 // All these modules are technically private and only exposed for coretests:
+#[cfg(not(no_fp_fmt_parse))]
 pub mod bignum;
+#[cfg(not(no_fp_fmt_parse))]
 pub mod dec2flt;
+#[cfg(not(no_fp_fmt_parse))]
 pub mod diy_float;
+#[cfg(not(no_fp_fmt_parse))]
 pub mod flt2dec;
+pub mod fmt;
 
 #[macro_use]
 mod int_macros; // import int_impl!
@@ -36,6 +41,7 @@ mod int_macros; // import int_impl!
 mod uint_macros; // import uint_impl!
 
 mod error;
+mod int_log10;
 mod nonzero;
 mod wrapping;
 
@@ -43,6 +49,7 @@ mod wrapping;
 pub use wrapping::Wrapping;
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(no_fp_fmt_parse))]
 pub use dec2flt::ParseFloatError;
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -57,12 +64,7 @@ pub use nonzero::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, No
 #[stable(feature = "try_from", since = "1.34.0")]
 pub use error::TryFromIntError;
 
-#[unstable(
-    feature = "int_error_matching",
-    reason = "it can be useful to match errors when making error messages \
-              for integer parsing",
-    issue = "22639"
-)]
+#[stable(feature = "int_error_matching", since = "1.55.0")]
 pub use error::IntErrorKind;
 
 macro_rules! usize_isize_to_xe_bytes_doc {
@@ -595,8 +597,8 @@ impl u8 {
     /// before using this function.
     ///
     /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
-    /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
-    /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
+    /// [pct]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
+    /// [bfs]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
     ///
     /// # Examples
     ///
index 6b9b435d47fe9994d5998b228983d050a17a0b96..dd9b9330aee2b5ed466c0e5e9f42323190eeedc2 100644 (file)
@@ -42,7 +42,8 @@ macro_rules! nonzero_integers {
             pub struct $Ty($Int);
 
             impl $Ty {
-                /// Creates a non-zero without checking the value.
+                /// Creates a non-zero without checking whether the value is non-zero.
+                /// This results in undefined behaviour if the value is zero.
                 ///
                 /// # Safety
                 ///
@@ -285,6 +286,576 @@ nonzero_integers_div! {
     NonZeroUsize(usize);
 }
 
+// A bunch of methods for unsigned nonzero types only.
+macro_rules! nonzero_unsigned_operations {
+    ( $( $Ty: ident($Int: ty); )+ ) => {
+        $(
+            impl $Ty {
+                /// Add an unsigned integer to a non-zero value.
+                /// Check for overflow and return [`None`] on overflow
+                /// As a consequence, the result cannot wrap to zero.
+                ///
+                ///
+                /// # Examples
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
+                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MAX)?;")]
+                ///
+                /// assert_eq!(Some(two), one.checked_add(1));
+                /// assert_eq!(None, max.checked_add(1));
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub const fn checked_add(self, other: $Int) -> Option<$Ty> {
+                    if let Some(result) = self.get().checked_add(other) {
+                        // SAFETY: $Int::checked_add returns None on overflow
+                        // so the result cannot be zero.
+                        Some(unsafe { $Ty::new_unchecked(result) })
+                    } else {
+                        None
+                    }
+                }
+
+                /// Add an unsigned integer to a non-zero value.
+                #[doc = concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")]
+                ///
+                /// # Examples
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
+                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MAX)?;")]
+                ///
+                /// assert_eq!(two, one.saturating_add(1));
+                /// assert_eq!(max, max.saturating_add(1));
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub const fn saturating_add(self, other: $Int) -> $Ty {
+                    // SAFETY: $Int::saturating_add returns $Int::MAX on overflow
+                    // so the result cannot be zero.
+                    unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) }
+                }
+
+                /// Add an unsigned integer to a non-zero value,
+                /// assuming overflow cannot occur.
+                /// Overflow is unchecked, and it is undefined behaviour to overflow
+                /// *even if the result would wrap to a non-zero value*.
+                /// The behaviour is undefined as soon as
+                #[doc = concat!("`self + rhs > ", stringify!($Int), "::MAX`.")]
+                ///
+                /// # Examples
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
+                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+                ///
+                /// assert_eq!(two, unsafe { one.unchecked_add(1) });
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub unsafe fn unchecked_add(self, other: $Int) -> $Ty {
+                    // SAFETY: The caller ensures there is no overflow.
+                    unsafe { $Ty::new_unchecked(self.get().unchecked_add(other)) }
+                }
+
+                /// Returns the smallest power of two greater than or equal to n.
+                /// Check for overflow and return [`None`]
+                /// if the next power of two is greater than the type’s maximum value.
+                /// As a consequence, the result cannot wrap to zero.
+                ///
+                /// # Examples
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+                #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")]
+                #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
+                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MAX)?;")]
+                ///
+                /// assert_eq!(Some(two), two.checked_next_power_of_two() );
+                /// assert_eq!(Some(four), three.checked_next_power_of_two() );
+                /// assert_eq!(None, max.checked_next_power_of_two() );
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub const fn checked_next_power_of_two(self) -> Option<$Ty> {
+                    if let Some(nz) = self.get().checked_next_power_of_two() {
+                        // SAFETY: The next power of two is positive
+                        // and overflow is checked.
+                        Some(unsafe { $Ty::new_unchecked(nz) })
+                    } else {
+                        None
+                    }
+                }
+            }
+        )+
+    }
+}
+
+nonzero_unsigned_operations! {
+    NonZeroU8(u8);
+    NonZeroU16(u16);
+    NonZeroU32(u32);
+    NonZeroU64(u64);
+    NonZeroU128(u128);
+    NonZeroUsize(usize);
+}
+
+// A bunch of methods for signed nonzero types only.
+macro_rules! nonzero_signed_operations {
+    ( $( $Ty: ident($Int: ty) -> $Uty: ident($Uint: ty); )+ ) => {
+        $(
+            impl $Ty {
+                /// Computes the absolute value of self.
+                #[doc = concat!("See [`", stringify!($Int), "::abs`]")]
+                /// for documentation on overflow behaviour.
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
+                #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
+                ///
+                /// assert_eq!(pos, pos.abs());
+                /// assert_eq!(pos, neg.abs());
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub const fn abs(self) -> $Ty {
+                    // SAFETY: This cannot overflow to zero.
+                    unsafe { $Ty::new_unchecked(self.get().abs()) }
+                }
+
+                /// Checked absolute value.
+                /// Check for overflow and returns [`None`] if
+                #[doc = concat!("`self == ", stringify!($Int), "::MIN`.")]
+                /// The result cannot be zero.
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
+                #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
+                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN)?;")]
+                ///
+                /// assert_eq!(Some(pos), neg.checked_abs());
+                /// assert_eq!(None, min.checked_abs());
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub const fn checked_abs(self) -> Option<$Ty> {
+                    if let Some(nz) = self.get().checked_abs() {
+                        // SAFETY: absolute value of nonzero cannot yield zero values.
+                        Some(unsafe { $Ty::new_unchecked(nz) })
+                    } else {
+                        None
+                    }
+                }
+
+                /// Computes the absolute value of self,
+                /// with overflow information, see
+                #[doc = concat!("[`", stringify!($Int), "::overflowing_abs`].")]
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
+                #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
+                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN)?;")]
+                ///
+                /// assert_eq!((pos, false), pos.overflowing_abs());
+                /// assert_eq!((pos, false), neg.overflowing_abs());
+                /// assert_eq!((min, true), min.overflowing_abs());
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub const fn overflowing_abs(self) -> ($Ty, bool) {
+                    let (nz, flag) = self.get().overflowing_abs();
+                    (
+                        // SAFETY: absolute value of nonzero cannot yield zero values.
+                        unsafe { $Ty::new_unchecked(nz) },
+                        flag,
+                    )
+                }
+
+                /// Saturating absolute value, see
+                #[doc = concat!("[`", stringify!($Int), "::saturating_abs`].")]
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
+                #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
+                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN)?;")]
+                #[doc = concat!("let min_plus = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN + 1)?;")]
+                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MAX)?;")]
+                ///
+                /// assert_eq!(pos, pos.saturating_abs());
+                /// assert_eq!(pos, neg.saturating_abs());
+                /// assert_eq!(max, min.saturating_abs());
+                /// assert_eq!(max, min_plus.saturating_abs());
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub const fn saturating_abs(self) -> $Ty {
+                    // SAFETY: absolute value of nonzero cannot yield zero values.
+                    unsafe { $Ty::new_unchecked(self.get().saturating_abs()) }
+                }
+
+                /// Wrapping absolute value, see
+                #[doc = concat!("[`", stringify!($Int), "::wrapping_abs`].")]
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
+                #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
+                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN)?;")]
+                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MAX)?;")]
+                ///
+                /// assert_eq!(pos, pos.wrapping_abs());
+                /// assert_eq!(pos, neg.wrapping_abs());
+                /// assert_eq!(min, min.wrapping_abs());
+                /// # // FIXME: add once Neg is implemented?
+                /// # // assert_eq!(max, (-max).wrapping_abs());
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub const fn wrapping_abs(self) -> $Ty {
+                    // SAFETY: absolute value of nonzero cannot yield zero values.
+                    unsafe { $Ty::new_unchecked(self.get().wrapping_abs()) }
+                }
+
+                /// Computes the absolute value of self
+                /// without any wrapping or panicking.
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                #[doc = concat!("# use std::num::", stringify!($Uty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let u_pos = ", stringify!($Uty), "::new(1)?;")]
+                #[doc = concat!("let i_pos = ", stringify!($Ty), "::new(1)?;")]
+                #[doc = concat!("let i_neg = ", stringify!($Ty), "::new(-1)?;")]
+                #[doc = concat!("let i_min = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN)?;")]
+                #[doc = concat!("let u_max = ", stringify!($Uty), "::new(",
+                                stringify!($Uint), "::MAX / 2 + 1)?;")]
+                ///
+                /// assert_eq!(u_pos, i_pos.unsigned_abs());
+                /// assert_eq!(u_pos, i_neg.unsigned_abs());
+                /// assert_eq!(u_max, i_min.unsigned_abs());
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub const fn unsigned_abs(self) -> $Uty {
+                    // SAFETY: absolute value of nonzero cannot yield zero values.
+                    unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) }
+                }
+            }
+        )+
+    }
+}
+
+nonzero_signed_operations! {
+    NonZeroI8(i8) -> NonZeroU8(u8);
+    NonZeroI16(i16) -> NonZeroU16(u16);
+    NonZeroI32(i32) -> NonZeroU32(u32);
+    NonZeroI64(i64) -> NonZeroU64(u64);
+    NonZeroI128(i128) -> NonZeroU128(u128);
+    NonZeroIsize(isize) -> NonZeroUsize(usize);
+}
+
+// A bunch of methods for both signed and unsigned nonzero types.
+macro_rules! nonzero_unsigned_signed_operations {
+    ( $( $signedness:ident $Ty: ident($Int: ty); )+ ) => {
+        $(
+            impl $Ty {
+                /// Multiply two non-zero integers together.
+                /// Check for overflow and return [`None`] on overflow.
+                /// As a consequence, the result cannot wrap to zero.
+                ///
+                /// # Examples
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+                #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
+                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MAX)?;")]
+                ///
+                /// assert_eq!(Some(four), two.checked_mul(two));
+                /// assert_eq!(None, max.checked_mul(two));
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub const fn checked_mul(self, other: $Ty) -> Option<$Ty> {
+                    if let Some(result) = self.get().checked_mul(other.get()) {
+                        // SAFETY: checked_mul returns None on overflow
+                        // and `other` is also non-null
+                        // so the result cannot be zero.
+                        Some(unsafe { $Ty::new_unchecked(result) })
+                    } else {
+                        None
+                    }
+                }
+
+                /// Multiply two non-zero integers together.
+                #[doc = concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")]
+                ///
+                /// # Examples
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+                #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
+                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MAX)?;")]
+                ///
+                /// assert_eq!(four, two.saturating_mul(two));
+                /// assert_eq!(max, four.saturating_mul(max));
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub const fn saturating_mul(self, other: $Ty) -> $Ty {
+                    // SAFETY: saturating_mul returns u*::MAX on overflow
+                    // and `other` is also non-null
+                    // so the result cannot be zero.
+                    unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) }
+                }
+
+                /// Multiply two non-zero integers together,
+                /// assuming overflow cannot occur.
+                /// Overflow is unchecked, and it is undefined behaviour to overflow
+                /// *even if the result would wrap to a non-zero value*.
+                /// The behaviour is undefined as soon as
+                #[doc = sign_dependent_expr!{
+                    $signedness ?
+                    if signed {
+                        concat!("`self * rhs > ", stringify!($Int), "::MAX`, ",
+                                "or `self * rhs < ", stringify!($Int), "::MIN`.")
+                    }
+                    if unsigned {
+                        concat!("`self * rhs > ", stringify!($Int), "::MAX`.")
+                    }
+                }]
+                ///
+                /// # Examples
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+                #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
+                ///
+                /// assert_eq!(four, unsafe { two.unchecked_mul(two) });
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub unsafe fn unchecked_mul(self, other: $Ty) -> $Ty {
+                    // SAFETY: The caller ensures there is no overflow.
+                    unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.get())) }
+                }
+
+                /// Raise non-zero value to an integer power.
+                /// Check for overflow and return [`None`] on overflow.
+                /// As a consequence, the result cannot wrap to zero.
+                ///
+                /// # Examples
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")]
+                #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")]
+                #[doc = concat!("let half_max = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MAX / 2)?;")]
+                ///
+                /// assert_eq!(Some(twenty_seven), three.checked_pow(3));
+                /// assert_eq!(None, half_max.checked_pow(3));
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub const fn checked_pow(self, other: u32) -> Option<$Ty> {
+                    if let Some(result) = self.get().checked_pow(other) {
+                        // SAFETY: checked_pow returns None on overflow
+                        // so the result cannot be zero.
+                        Some(unsafe { $Ty::new_unchecked(result) })
+                    } else {
+                        None
+                    }
+                }
+
+                /// Raise non-zero value to an integer power.
+                #[doc = sign_dependent_expr!{
+                    $signedness ?
+                    if signed {
+                        concat!("Return [`", stringify!($Int), "::MIN`] ",
+                                    "or [`", stringify!($Int), "::MAX`] on overflow.")
+                    }
+                    if unsigned {
+                        concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")
+                    }
+                }]
+                ///
+                /// # Examples
+                ///
+                /// ```
+                /// #![feature(nonzero_ops)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")]
+                #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")]
+                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MAX)?;")]
+                ///
+                /// assert_eq!(twenty_seven, three.saturating_pow(3));
+                /// assert_eq!(max, max.saturating_pow(3));
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[inline]
+                pub const fn saturating_pow(self, other: u32) -> $Ty {
+                    // SAFETY: saturating_pow returns u*::MAX on overflow
+                    // so the result cannot be zero.
+                    unsafe { $Ty::new_unchecked(self.get().saturating_pow(other)) }
+                }
+            }
+        )+
+    }
+}
+
+// Use this when the generated code should differ between signed and unsigned types.
+macro_rules! sign_dependent_expr {
+    (signed ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => {
+        $signed_case
+    };
+    (unsigned ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => {
+        $unsigned_case
+    };
+}
+
+nonzero_unsigned_signed_operations! {
+    unsigned NonZeroU8(u8);
+    unsigned NonZeroU16(u16);
+    unsigned NonZeroU32(u32);
+    unsigned NonZeroU64(u64);
+    unsigned NonZeroU128(u128);
+    unsigned NonZeroUsize(usize);
+    signed NonZeroI8(i8);
+    signed NonZeroI16(i16);
+    signed NonZeroI32(i32);
+    signed NonZeroI64(i64);
+    signed NonZeroI128(i128);
+    signed NonZeroIsize(isize);
+}
+
 macro_rules! nonzero_unsigned_is_power_of_two {
     ( $( $Ty: ident )+ ) => {
         $(
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 @@ macro_rules! uint_impl {
             }
         }
 
+        /// 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 9d9398fb56d8a46d61a6f43b6fd7bcb6f899c11d..c2270c864dfae26b5fe20333a66e8eee22238cf5 100644 (file)
@@ -11,7 +11,6 @@ use crate::{convert, ops};
 ///
 /// Early-exiting from [`Iterator::try_for_each`]:
 /// ```
-/// #![feature(control_flow_enum)]
 /// use std::ops::ControlFlow;
 ///
 /// let r = (2..100).try_for_each(|x| {
@@ -26,7 +25,6 @@ use crate::{convert, ops};
 ///
 /// A basic tree traversal:
 /// ```no_run
-/// #![feature(control_flow_enum)]
 /// use std::ops::ControlFlow;
 ///
 /// pub struct TreeNode<T> {
@@ -48,42 +46,22 @@ use crate::{convert, ops};
 ///     }
 /// }
 /// ```
-#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
+#[stable(feature = "control_flow_enum_type", since = "1.55.0")]
 #[derive(Debug, Clone, Copy, PartialEq)]
 pub enum ControlFlow<B, C = ()> {
     /// Move on to the next phase of the operation as normal.
-    #[cfg_attr(not(bootstrap), lang = "Continue")]
+    #[stable(feature = "control_flow_enum_type", since = "1.55.0")]
+    #[lang = "Continue"]
     Continue(C),
     /// Exit the operation without running subsequent phases.
-    #[cfg_attr(not(bootstrap), lang = "Break")]
+    #[stable(feature = "control_flow_enum_type", since = "1.55.0")]
+    #[lang = "Break"]
     Break(B),
     // Yes, the order of the variants doesn't match the type parameters.
     // They're in this order so that `ControlFlow<A, B>` <-> `Result<B, A>`
     // is a no-op conversion in the `Try` implementation.
 }
 
-#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
-#[cfg(bootstrap)]
-impl<B, C> ops::TryV1 for ControlFlow<B, C> {
-    type Output = C;
-    type Error = B;
-    #[inline]
-    fn into_result(self) -> Result<Self::Output, Self::Error> {
-        match self {
-            ControlFlow::Continue(y) => Ok(y),
-            ControlFlow::Break(x) => Err(x),
-        }
-    }
-    #[inline]
-    fn from_error(v: Self::Error) -> Self {
-        ControlFlow::Break(v)
-    }
-    #[inline]
-    fn from_ok(v: Self::Output) -> Self {
-        ControlFlow::Continue(v)
-    }
-}
-
 #[unstable(feature = "try_trait_v2", issue = "84277")]
 impl<B, C> ops::TryV2 for ControlFlow<B, C> {
     type Output = C;
@@ -184,31 +162,9 @@ impl<B, C> ControlFlow<B, C> {
     }
 }
 
-#[cfg(bootstrap)]
-impl<R: ops::TryV1> ControlFlow<R, R::Output> {
-    /// Create a `ControlFlow` from any type implementing `Try`.
-    #[inline]
-    pub(crate) fn from_try(r: R) -> Self {
-        match R::into_result(r) {
-            Ok(v) => ControlFlow::Continue(v),
-            Err(v) => ControlFlow::Break(R::from_error(v)),
-        }
-    }
-
-    /// Convert a `ControlFlow` into any type implementing `Try`;
-    #[inline]
-    pub(crate) fn into_try(self) -> R {
-        match self {
-            ControlFlow::Continue(v) => R::from_ok(v),
-            ControlFlow::Break(v) => v,
-        }
-    }
-}
-
 /// These are used only as part of implementing the iterator adapters.
 /// They have mediocre names and non-obvious semantics, so aren't
 /// currently on a path to potential stabilization.
-#[cfg(not(bootstrap))]
 impl<R: ops::TryV2> ControlFlow<R, R::Output> {
     /// Create a `ControlFlow` from any type implementing `Try`.
     #[inline]
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 139a8c0eec9cb9da438da6bba1d5f7d09e926f62..85e04740d96a4836001e6e427de2d3213ed9db9d 100644 (file)
@@ -147,8 +147,6 @@ mod function;
 mod generator;
 mod index;
 mod range;
-#[cfg(bootstrap)]
-mod r#try;
 mod try_trait;
 mod unsize;
 
@@ -183,19 +181,10 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
 
-#[unstable(feature = "try_trait", issue = "42327")]
-#[cfg(bootstrap)]
-pub use self::r#try::Try;
-
-#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
-#[cfg(bootstrap)]
-pub(crate) use self::r#try::Try as TryV1;
-
 #[unstable(feature = "try_trait_v2", issue = "84277")]
 pub use self::try_trait::FromResidual;
 
 #[unstable(feature = "try_trait_v2", issue = "84277")]
-#[cfg(not(bootstrap))]
 pub use self::try_trait::Try;
 
 #[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
index bb948376bc7c7715d005f05a7add1f6dd26e7732..9bf0382312e989ece3f4ee28215ff56e9e5f0361 100644 (file)
@@ -737,14 +737,13 @@ impl<T: Clone> Bound<&T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(bound_cloned)]
     /// use std::ops::Bound::*;
     /// use std::ops::RangeBounds;
     ///
     /// assert_eq!((1..12).start_bound(), Included(&1));
     /// assert_eq!((1..12).start_bound().cloned(), Included(1));
     /// ```
-    #[unstable(feature = "bound_cloned", issue = "61356")]
+    #[stable(feature = "bound_cloned", since = "1.55.0")]
     pub fn cloned(self) -> Bound<T> {
         match self {
             Bound::Unbounded => Bound::Unbounded,
diff --git a/library/core/src/ops/try.rs b/library/core/src/ops/try.rs
deleted file mode 100644 (file)
index 9d659e7..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/// A trait for customizing the behavior of the `?` operator.
-///
-/// A type implementing `Try` is one that has a canonical way to view it
-/// in terms of a success/failure dichotomy. This trait allows both
-/// extracting those success or failure values from an existing instance and
-/// creating a new instance from a success or failure value.
-#[unstable(feature = "try_trait", issue = "42327")]
-#[rustc_on_unimplemented(
-    on(
-        all(
-            any(from_method = "from_error", from_method = "from_ok"),
-            from_desugaring = "QuestionMark"
-        ),
-        message = "the `?` operator can only be used in {ItemContext} \
-                    that returns `Result` or `Option` \
-                    (or another type that implements `{Try}`)",
-        label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
-        enclosing_scope = "this function should return `Result` or `Option` to accept `?`"
-    ),
-    on(
-        all(from_method = "into_result", from_desugaring = "QuestionMark"),
-        message = "the `?` operator can only be applied to values \
-                    that implement `{Try}`",
-        label = "the `?` operator cannot be applied to type `{Self}`"
-    )
-)]
-#[doc(alias = "?")]
-#[cfg_attr(bootstrap, lang = "try")]
-pub trait Try {
-    /// The type of this value when viewed as successful.
-    #[unstable(feature = "try_trait", issue = "42327")]
-    type Output; // This no longer follows its RFC, but is only used in bootstrap.
-    /// The type of this value when viewed as failed.
-    #[unstable(feature = "try_trait", issue = "42327")]
-    type Error;
-
-    /// Applies the "?" operator. A return of `Ok(t)` means that the
-    /// execution should continue normally, and the result of `?` is the
-    /// value `t`. A return of `Err(e)` means that execution should branch
-    /// to the innermost enclosing `catch`, or return from the function.
-    ///
-    /// If an `Err(e)` result is returned, the value `e` will be "wrapped"
-    /// in the return type of the enclosing scope (which must itself implement
-    /// `Try`). Specifically, the value `X::from_error(From::from(e))`
-    /// is returned, where `X` is the return type of the enclosing function.
-    #[cfg_attr(bootstrap, lang = "into_result")]
-    #[unstable(feature = "try_trait", issue = "42327")]
-    fn into_result(self) -> Result<Self::Output, Self::Error>;
-
-    /// Wrap an error value to construct the composite result. For example,
-    /// `Result::Err(x)` and `Result::from_error(x)` are equivalent.
-    #[cfg_attr(bootstrap, lang = "from_error")]
-    #[unstable(feature = "try_trait", issue = "42327")]
-    fn from_error(v: Self::Error) -> Self;
-
-    /// Wrap an OK value to construct the composite result. For example,
-    /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent.
-    #[cfg_attr(bootstrap, lang = "from_ok")]
-    #[unstable(feature = "try_trait", issue = "42327")]
-    fn from_ok(v: Self::Output) -> Self;
-}
index 1d9bc452618e2db93b5c551da8fe3e24d1181d7f..bd46fb6f2cfce5c1eb6872db0371eef9e223abfd 100644 (file)
@@ -55,7 +55,6 @@ use crate::ops::ControlFlow;
 /// into the return type using [`Try::from_output`]:
 /// ```
 /// # #![feature(try_trait_v2)]
-/// # #![feature(control_flow_enum)]
 /// # use std::ops::{ControlFlow, Try};
 /// fn simple_try_fold_2<A, T, R: Try<Output = A>>(
 ///     iter: impl Iterator<Item = T>,
@@ -79,7 +78,6 @@ use crate::ops::ControlFlow;
 /// recreated from their corresponding residual, so we'll just call it:
 /// ```
 /// # #![feature(try_trait_v2)]
-/// # #![feature(control_flow_enum)]
 /// # use std::ops::{ControlFlow, Try};
 /// pub fn simple_try_fold_3<A, T, R: Try<Output = A>>(
 ///     iter: impl Iterator<Item = T>,
@@ -130,7 +128,7 @@ use crate::ops::ControlFlow;
     )
 )]
 #[doc(alias = "?")]
-#[cfg_attr(not(bootstrap), lang = "Try")]
+#[lang = "Try"]
 pub trait Try: FromResidual {
     /// The type of the value produced by `?` when *not* short-circuiting.
     #[unstable(feature = "try_trait_v2", issue = "84277")]
@@ -170,7 +168,6 @@ pub trait Try: FromResidual {
     ///
     /// ```
     /// #![feature(try_trait_v2)]
-    /// #![feature(control_flow_enum)]
     /// use std::ops::Try;
     ///
     /// assert_eq!(<Result<_, String> as Try>::from_output(3), Ok(3));
@@ -189,7 +186,7 @@ pub trait Try: FromResidual {
     /// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() });
     /// assert_eq!(r, Some(4));
     /// ```
-    #[cfg_attr(not(bootstrap), lang = "from_output")]
+    #[lang = "from_output"]
     #[unstable(feature = "try_trait_v2", issue = "84277")]
     fn from_output(output: Self::Output) -> Self;
 
@@ -202,7 +199,6 @@ pub trait Try: FromResidual {
     ///
     /// ```
     /// #![feature(try_trait_v2)]
-    /// #![feature(control_flow_enum)]
     /// use std::ops::{ControlFlow, Try};
     ///
     /// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3));
@@ -217,7 +213,7 @@ pub trait Try: FromResidual {
     ///     ControlFlow::Break(ControlFlow::Break(3)),
     /// );
     /// ```
-    #[cfg_attr(not(bootstrap), lang = "branch")]
+    #[lang = "branch"]
     #[unstable(feature = "try_trait_v2", issue = "84277")]
     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
 }
@@ -329,7 +325,6 @@ pub trait FromResidual<R = <Self as Try>::Residual> {
     ///
     /// ```
     /// #![feature(try_trait_v2)]
-    /// #![feature(control_flow_enum)]
     /// use std::ops::{ControlFlow, FromResidual};
     ///
     /// assert_eq!(Result::<String, i64>::from_residual(Err(3_u8)), Err(3));
@@ -339,7 +334,7 @@ pub trait FromResidual<R = <Self as Try>::Residual> {
     ///     ControlFlow::Break(5),
     /// );
     /// ```
-    #[cfg_attr(not(bootstrap), lang = "from_residual")]
+    #[lang = "from_residual"]
     #[unstable(feature = "try_trait_v2", issue = "84277")]
     fn from_residual(residual: R) -> Self;
 }
index 4e7afca6a4930e3115136e678e875108dc951968..8057ff0759107a14d339a028972c4077017b7858 100644 (file)
 //! no "null" references. Instead, Rust has *optional* pointers, like
 //! the optional owned box, [`Option`]`<`[`Box<T>`]`>`.
 //!
+//! [`Box<T>`]: ../../std/boxed/struct.Box.html
+//!
 //! The following example uses [`Option`] to create an optional box of
-//! [`i32`]. Notice that in order to use the inner [`i32`] value first, the
-//! `check_optional` function needs to use pattern matching to
+//! [`i32`]. Notice that in order to use the inner [`i32`] value, the
+//! `check_optional` function first needs to use pattern matching to
 //! determine whether the box has a value (i.e., it is [`Some(...)`][`Some`]) or
 //! not ([`None`]).
 //!
 //! * [`ptr::NonNull<U>`]
 //! * `#[repr(transparent)]` struct around one of the types in this list.
 //!
+//! [`Box<U>`]: ../../std/boxed/struct.Box.html
+//! [`num::NonZero*`]: crate::num
+//! [`ptr::NonNull<U>`]: crate::ptr::NonNull
+//!
 //! This is called the "null pointer optimization" or NPO.
 //!
 //! It is further guaranteed that, for the cases above, one can
 //! from `Some::<T>(_)` to `T` (but transmuting `None::<T>` to `T`
 //! is undefined behaviour).
 //!
+//! # Method overview
+//!
+//! In addition to working with pattern matching, [`Option`] provides a wide
+//! variety of different methods.
+//!
+//! ## Querying the variant
+//!
+//! The [`is_some`] and [`is_none`] methods return [`true`] if the [`Option`]
+//! is [`Some`] or [`None`], respectively.
+//!
+//! [`is_none`]: Option::is_none
+//! [`is_some`]: Option::is_some
+//!
+//! ## Adapters for working with references
+//!
+//! * [`as_ref`] converts from `&Option<T>` to `Option<&T>`
+//! * [`as_mut`] converts from `&mut Option<T>` to `Option<&mut T>`
+//! * [`as_deref`] converts from `&Option<T>` to `Option<&T::Target>`
+//! * [`as_deref_mut`] converts from `&mut Option<T>` to
+//!   `Option<&mut T::Target>`
+//! * [`as_pin_ref`] converts from [`Pin`]`<&Option<T>>` to
+//!   `Option<`[`Pin`]`<&T>>`
+//! * [`as_pin_mut`] converts from [`Pin`]`<&mut Option<T>>` to
+//!   `Option<`[`Pin`]`<&mut T>>`
+//!
+//! [`as_deref`]: Option::as_deref
+//! [`as_deref_mut`]: Option::as_deref_mut
+//! [`as_mut`]: Option::as_mut
+//! [`as_pin_mut`]: Option::as_pin_mut
+//! [`as_pin_ref`]: Option::as_pin_ref
+//! [`as_ref`]: Option::as_ref
+//!
+//! ## Extracting the contained value
+//!
+//! These methods extract the contained value in an [`Option<T>`] when it
+//! is the [`Some`] variant. If the [`Option`] is [`None`]:
+//!
+//! * [`expect`] panics with a provided custom message
+//! * [`unwrap`] panics with a generic message
+//! * [`unwrap_or`] returns the provided default value
+//! * [`unwrap_or_default`] returns the default value of the type `T`
+//!   (which must implement the [`Default`] trait)
+//! * [`unwrap_or_else`] returns the result of evaluating the provided
+//!   function
+//!
+//! [`expect`]: Option::expect
+//! [`unwrap`]: Option::unwrap
+//! [`unwrap_or`]: Option::unwrap_or
+//! [`unwrap_or_default`]: Option::unwrap_or_default
+//! [`unwrap_or_else`]: Option::unwrap_or_else
+//!
+//! ## Transforming contained values
+//!
+//! These methods transform [`Option`] to [`Result`]:
+//!
+//! * [`ok_or`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to
+//!   [`Err(err)`] using the provided default `err` value
+//! * [`ok_or_else`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to
+//!   a value of [`Err`] using the provided function
+//! * [`transpose`] transposes an [`Option`] of a [`Result`] into a
+//!   [`Result`] of an [`Option`]
+//!
+//! [`Err(err)`]: Err
+//! [`Ok(v)`]: Ok
+//! [`Some(v)`]: Some
+//! [`ok_or`]: Option::ok_or
+//! [`ok_or_else`]: Option::ok_or_else
+//! [`transpose`]: Option::transpose
+//!
+//! These methods transform the [`Some`] variant:
+//!
+//! * [`filter`] calls the provided predicate function on the contained
+//!   value `t` if the [`Option`] is [`Some(t)`], and returns [`Some(t)`]
+//!   if the function returns `true`; otherwise, returns [`None`]
+//! * [`flatten`] removes one level of nesting from an
+//!   [`Option<Option<T>>`]
+//! * [`map`] transforms [`Option<T>`] to [`Option<U>`] by applying the
+//!   provided function to the contained value of [`Some`] and leaving
+//!   [`None`] values unchanged
+//!
+//! [`Some(t)`]: Some
+//! [`filter`]: Option::filter
+//! [`flatten`]: Option::flatten
+//! [`map`]: Option::map
+//!
+//! These methods transform [`Option<T>`] to a value of a possibly
+//! different type `U`:
+//!
+//! * [`map_or`] applies the provided function to the contained value of
+//!   [`Some`], or returns the provided default value if the [`Option`] is
+//!   [`None`]
+//! * [`map_or_else`] applies the provided function to the contained value
+//!   of [`Some`], or returns the result of evaluating the provided
+//!   fallback function if the [`Option`] is [`None`]
+//!
+//! [`map_or`]: Option::map_or
+//! [`map_or_else`]: Option::map_or_else
+//!
+//! These methods combine the [`Some`] variants of two [`Option`] values:
+//!
+//! * [`zip`] returns [`Some((s, o))`] if `self` is [`Some(s)`] and the
+//!   provided [`Option`] value is [`Some(o)`]; otherwise, returns [`None`]
+//! * [`zip_with`] calls the provided function `f` and returns
+//!   [`Some(f(s, o))`] if `self` is [`Some(s)`] and the provided
+//!   [`Option`] value is [`Some(o)`]; otherwise, returns [`None`]
+//!
+//! [`Some(f(s, o))`]: Some
+//! [`Some(o)`]: Some
+//! [`Some(s)`]: Some
+//! [`Some((s, o))`]: Some
+//! [`zip`]: Option::zip
+//! [`zip_with`]: Option::zip_with
+//!
+//! ## Boolean operators
+//!
+//! These methods treat the [`Option`] as a boolean value, where [`Some`]
+//! acts like [`true`] and [`None`] acts like [`false`]. There are two
+//! categories of these methods: ones that take an [`Option`] as input, and
+//! ones that take a function as input (to be lazily evaluated).
+//!
+//! The [`and`], [`or`], and [`xor`] methods take another [`Option`] as
+//! input, and produce an [`Option`] as output. Only the [`and`] method can
+//! produce an [`Option<U>`] value having a different inner type `U` than
+//! [`Option<T>`].
+//!
+//! | method  | self      | input     | output    |
+//! |---------|-----------|-----------|-----------|
+//! | [`and`] | `None`    | (ignored) | `None`    |
+//! | [`and`] | `Some(x)` | `None`    | `None`    |
+//! | [`and`] | `Some(x)` | `Some(y)` | `Some(y)` |
+//! | [`or`]  | `None`    | `None`    | `None`    |
+//! | [`or`]  | `None`    | `Some(y)` | `Some(y)` |
+//! | [`or`]  | `Some(x)` | (ignored) | `Some(x)` |
+//! | [`xor`] | `None`    | `None`    | `None`    |
+//! | [`xor`] | `None`    | `Some(y)` | `Some(y)` |
+//! | [`xor`] | `Some(x)` | `None`    | `Some(x)` |
+//! | [`xor`] | `Some(x)` | `Some(y)` | `None`    |
+//!
+//! [`and`]: Option::and
+//! [`or`]: Option::or
+//! [`xor`]: Option::xor
+//!
+//! The [`and_then`] and [`or_else`] methods take a function as input, and
+//! only evaluate the function when they need to produce a new value. Only
+//! the [`and_then`] method can produce an [`Option<U>`] value having a
+//! different inner type `U` than [`Option<T>`].
+//!
+//! | method       | self      | function input | function result | output    |
+//! |--------------|-----------|----------------|-----------------|-----------|
+//! | [`and_then`] | `None`    | (not provided) | (not evaluated) | `None`    |
+//! | [`and_then`] | `Some(x)` | `x`            | `None`          | `None`    |
+//! | [`and_then`] | `Some(x)` | `x`            | `Some(y)`       | `Some(y)` |
+//! | [`or_else`]  | `None`    | (not provided) | `None`          | `None`    |
+//! | [`or_else`]  | `None`    | (not provided) | `Some(y)`       | `Some(y)` |
+//! | [`or_else`]  | `Some(x)` | (not provided) | (not evaluated) | `Some(x)` |
+//!
+//! [`and_then`]: Option::and_then
+//! [`or_else`]: Option::or_else
+//!
+//! This is an example of using methods like [`and_then`] and [`or`] in a
+//! pipeline of method calls. Early stages of the pipeline pass failure
+//! values ([`None`]) through unchanged, and continue processing on
+//! success values ([`Some`]). Toward the end, [`or`] substitutes an error
+//! message if it receives [`None`].
+//!
+//! ```
+//! # use std::collections::BTreeMap;
+//! let mut bt = BTreeMap::new();
+//! bt.insert(20u8, "foo");
+//! bt.insert(42u8, "bar");
+//! let res = vec![0u8, 1, 11, 200, 22]
+//!     .into_iter()
+//!     .map(|x| {
+//!         // `checked_sub()` returns `None` on error
+//!         x.checked_sub(1)
+//!             // same with `checked_mul()`
+//!             .and_then(|x| x.checked_mul(2))
+//!             // `BTreeMap::get` returns `None` on error
+//!             .and_then(|x| bt.get(&x))
+//!             // Substitute an error message if we have `None` so far
+//!             .or(Some(&"error!"))
+//!             .copied()
+//!             // Won't panic because we unconditionally used `Some` above
+//!             .unwrap()
+//!     })
+//!     .collect::<Vec<_>>();
+//! assert_eq!(res, ["error!", "error!", "foo", "error!", "bar"]);
+//! ```
+//!
+//! ## Iterating over `Option`
+//!
+//! An [`Option`] can be iterated over. This can be helpful if you need an
+//! iterator that is conditionally empty. The iterator will either produce
+//! a single value (when the [`Option`] is [`Some`]), or produce no values
+//! (when the [`Option`] is [`None`]). For example, [`into_iter`] acts like
+//! [`once(v)`] if the [`Option`] is [`Some(v)`], and like [`empty()`] if
+//! the [`Option`] is [`None`].
+//!
+//! [`Some(v)`]: Some
+//! [`empty()`]: crate::iter::empty
+//! [`once(v)`]: crate::iter::once
+//!
+//! Iterators over [`Option<T>`] come in three types:
+//!
+//! * [`into_iter`] consumes the [`Option`] and produces the contained
+//!   value
+//! * [`iter`] produces an immutable reference of type `&T` to the
+//!   contained value
+//! * [`iter_mut`] produces a mutable reference of type `&mut T` to the
+//!   contained value
+//!
+//! [`into_iter`]: Option::into_iter
+//! [`iter`]: Option::iter
+//! [`iter_mut`]: Option::iter_mut
+//!
+//! An iterator over [`Option`] can be useful when chaining iterators, for
+//! example, to conditionally insert items. (It's not always necessary to
+//! explicitly call an iterator constructor: many [`Iterator`] methods that
+//! accept other iterators will also accept iterable types that implement
+//! [`IntoIterator`], which includes [`Option`].)
+//!
+//! ```
+//! let yep = Some(42);
+//! let nope = None;
+//! // chain() already calls into_iter(), so we don't have to do so
+//! let nums: Vec<i32> = (0..4).chain(yep).chain(4..8).collect();
+//! assert_eq!(nums, [0, 1, 2, 3, 42, 4, 5, 6, 7]);
+//! let nums: Vec<i32> = (0..4).chain(nope).chain(4..8).collect();
+//! assert_eq!(nums, [0, 1, 2, 3, 4, 5, 6, 7]);
+//! ```
+//!
+//! One reason to chain iterators in this way is that a function returning
+//! `impl Iterator` must have all possible return values be of the same
+//! concrete type. Chaining an iterated [`Option`] can help with that.
+//!
+//! ```
+//! fn make_iter(do_insert: bool) -> impl Iterator<Item = i32> {
+//!     // Explicit returns to illustrate return types matching
+//!     match do_insert {
+//!         true => return (0..4).chain(Some(42)).chain(4..8),
+//!         false => return (0..4).chain(None).chain(4..8),
+//!     }
+//! }
+//! println!("{:?}", make_iter(true).collect::<Vec<_>>());
+//! println!("{:?}", make_iter(false).collect::<Vec<_>>());
+//! ```
+//!
+//! If we try to do the same thing, but using [`once()`] and [`empty()`],
+//! we can't return `impl Iterator` anymore because the concrete types of
+//! the return values differ.
+//!
+//! [`empty()`]: crate::iter::empty
+//! [`once()`]: crate::iter::once
+//!
+//! ```compile_fail,E0308
+//! # use std::iter::{empty, once};
+//! // This won't compile because all possible returns from the function
+//! // must have the same concrete type.
+//! fn make_iter(do_insert: bool) -> impl Iterator<Item = i32> {
+//!     // Explicit returns to illustrate return types not matching
+//!     match do_insert {
+//!         true => return (0..4).chain(once(42)).chain(4..8),
+//!         false => return (0..4).chain(empty()).chain(4..8),
+//!     }
+//! }
+//! ```
+//!
+//! ## Collecting into `Option`
+//!
+//! [`Option`] implements the [`FromIterator`][impl-FromIterator] trait,
+//! which allows an iterator over [`Option`] values to be collected into an
+//! [`Option`] of a collection of each contained value of the original
+//! [`Option`] values, or [`None`] if any of the elements was [`None`].
+//!
+//! [impl-FromIterator]: Option#impl-FromIterator%3COption%3CA%3E%3E
+//!
+//! ```
+//! let v = vec![Some(2), Some(4), None, Some(8)];
+//! let res: Option<Vec<_>> = v.into_iter().collect();
+//! assert_eq!(res, None);
+//! let v = vec![Some(2), Some(4), Some(8)];
+//! let res: Option<Vec<_>> = v.into_iter().collect();
+//! assert_eq!(res, Some(vec![2, 4, 8]));
+//! ```
+//!
+//! [`Option`] also implements the [`Product`][impl-Product] and
+//! [`Sum`][impl-Sum] traits, allowing an iterator over [`Option`] values
+//! to provide the [`product`][Iterator::product] and
+//! [`sum`][Iterator::sum] methods.
+//!
+//! [impl-Product]: Option#impl-Product%3COption%3CU%3E%3E
+//! [impl-Sum]: Option#impl-Sum%3COption%3CU%3E%3E
+//!
+//! ```
+//! let v = vec![None, Some(1), Some(2), Some(3)];
+//! let res: Option<i32> = v.into_iter().sum();
+//! assert_eq!(res, None);
+//! let v = vec![Some(1), Some(2), Some(21)];
+//! let res: Option<i32> = v.into_iter().product();
+//! assert_eq!(res, Some(42));
+//! ```
+//!
+//! ## Modifying an [`Option`] in-place
+//!
+//! These methods return a mutable reference to the contained value of an
+//! [`Option<T>`]:
+//!
+//! * [`insert`] inserts a value, dropping any old contents
+//! * [`get_or_insert`] gets the current value, inserting a provided
+//!   default value if it is [`None`]
+//! * [`get_or_insert_default`] gets the current value, inserting the
+//!   default value of type `T` (which must implement [`Default`]) if it is
+//!   [`None`]
+//! * [`get_or_insert_with`] gets the current value, inserting a default
+//!   computed by the provided function if it is [`None`]
+//!
+//! [`get_or_insert`]: Option::get_or_insert
+//! [`get_or_insert_default`]: Option::get_or_insert_default
+//! [`get_or_insert_with`]: Option::get_or_insert_with
+//! [`insert`]: Option::insert
+//!
+//! These methods transfer ownership of the contained value of an
+//! [`Option`]:
+//!
+//! * [`take`] takes ownership of the contained value of an [`Option`], if
+//!   any, replacing the [`Option`] with [`None`]
+//! * [`replace`] takes ownership of the contained value of an [`Option`],
+//!   if any, replacing the [`Option`] with a [`Some`] containing the
+//!   provided value
+//!
+//! [`replace`]: Option::replace
+//! [`take`]: Option::take
+//!
 //! # Examples
 //!
 //! Basic pattern matching on [`Option`]:
 //!     None => println!("there are no animals :("),
 //! }
 //! ```
-//!
-//! [`Box<T>`]: ../../std/boxed/struct.Box.html
-//! [`Box<U>`]: ../../std/boxed/struct.Box.html
-//! [`num::NonZero*`]: crate::num
-//! [`ptr::NonNull<U>`]: crate::ptr::NonNull
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -845,6 +1179,7 @@ impl<T> Option<T> {
     /// *val = 3;
     /// assert_eq!(opt.unwrap(), 3);
     /// ```
+    #[must_use = "if you intended to set a value, consider assignment instead"]
     #[inline]
     #[stable(feature = "option_insert", since = "1.53.0")]
     pub fn insert(&mut self, value: T) -> &mut T {
@@ -1350,7 +1685,7 @@ impl<'a, T> From<&'a Option<T>> for Option<&'a T> {
     ///
     /// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, preserving the original.
     /// The [`map`] method takes the `self` argument by value, consuming the original,
-    /// so this technique uses `as_ref` to first take an `Option` to a reference
+    /// so this technique uses `from` to first take an `Option` to a reference
     /// to the value inside the original.
     ///
     /// [`map`]: Option::map
@@ -1636,38 +1971,6 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
     }
 }
 
-/// The error type that results from applying the try operator (`?`) to a `None` value. If you wish
-/// to allow `x?` (where `x` is an `Option<T>`) to be converted into your error type, you can
-/// implement `impl From<NoneError>` for `YourErrorType`. In that case, `x?` within a function that
-/// returns `Result<_, YourErrorType>` will translate a `None` value into an `Err` result.
-#[rustc_diagnostic_item = "none_error"]
-#[unstable(feature = "try_trait", issue = "42327")]
-#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
-#[cfg(bootstrap)]
-pub struct NoneError;
-
-#[unstable(feature = "try_trait", issue = "42327")]
-#[cfg(bootstrap)]
-impl<T> ops::TryV1 for Option<T> {
-    type Output = T;
-    type Error = NoneError;
-
-    #[inline]
-    fn into_result(self) -> Result<T, NoneError> {
-        self.ok_or(NoneError)
-    }
-
-    #[inline]
-    fn from_ok(v: T) -> Self {
-        Some(v)
-    }
-
-    #[inline]
-    fn from_error(_: NoneError) -> Self {
-        None
-    }
-}
-
 #[unstable(feature = "try_trait_v2", issue = "84277")]
 impl<T> ops::TryV2 for Option<T> {
     type Output = T;
index 79753c1fb66871fc47ada3b4258c03f17cc2b70c..ccd36a428e29679bc766ff5008bc8c8d6d32919e 100644 (file)
@@ -11,9 +11,9 @@ pub mod v1;
 /// The 2015 version of the core prelude.
 ///
 /// See the [module-level documentation](self) for more.
-#[unstable(feature = "prelude_2015", issue = "85684")]
+#[stable(feature = "prelude_2015", since = "1.55.0")]
 pub mod rust_2015 {
-    #[unstable(feature = "prelude_2015", issue = "85684")]
+    #[stable(feature = "prelude_2015", since = "1.55.0")]
     #[doc(no_inline)]
     pub use super::v1::*;
 }
@@ -21,9 +21,9 @@ pub mod rust_2015 {
 /// The 2018 version of the core prelude.
 ///
 /// See the [module-level documentation](self) for more.
-#[unstable(feature = "prelude_2018", issue = "85684")]
+#[stable(feature = "prelude_2018", since = "1.55.0")]
 pub mod rust_2018 {
-    #[unstable(feature = "prelude_2018", issue = "85684")]
+    #[stable(feature = "prelude_2018", since = "1.55.0")]
     #[doc(no_inline)]
     pub use super::v1::*;
 }
@@ -31,17 +31,17 @@ pub mod rust_2018 {
 /// The 2021 version of the core prelude.
 ///
 /// See the [module-level documentation](self) for more.
-#[unstable(feature = "prelude_2021", issue = "85684")]
+#[stable(feature = "prelude_2021", since = "1.55.0")]
 pub mod rust_2021 {
-    #[unstable(feature = "prelude_2021", issue = "85684")]
+    #[stable(feature = "prelude_2021", since = "1.55.0")]
     #[doc(no_inline)]
     pub use super::v1::*;
 
-    #[unstable(feature = "prelude_2021", issue = "85684")]
+    #[stable(feature = "prelude_2021", since = "1.55.0")]
     #[doc(no_inline)]
     pub use crate::iter::FromIterator;
 
-    #[unstable(feature = "prelude_2021", issue = "85684")]
+    #[stable(feature = "prelude_2021", since = "1.55.0")]
     #[doc(no_inline)]
     pub use crate::convert::{TryFrom, TryInto};
 }
index c89fe57cb05cee4e8497d8f98934cc497a1133fd..6b51ef5b0122d5ccbd89dcce30732a4e23b8a0b2 100644 (file)
@@ -55,11 +55,27 @@ pub use crate::hash::macros::Hash;
 #[allow(deprecated)]
 #[doc(no_inline)]
 pub use crate::{
-    asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
-    format_args_nl, global_asm, include, include_bytes, include_str, line, llvm_asm, log_syntax,
-    module_path, option_env, stringify, trace_macros,
+    assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
+    format_args_nl, include, include_bytes, include_str, line, llvm_asm, log_syntax, module_path,
+    option_env, stringify, trace_macros,
 };
 
+#[unstable(
+    feature = "asm",
+    issue = "72016",
+    reason = "inline assembly is not stable enough for use and is subject to change"
+)]
+#[doc(no_inline)]
+pub use crate::arch::asm;
+
+#[unstable(
+    feature = "global_asm",
+    issue = "35119",
+    reason = "`global_asm!` is not stable enough for use and is subject to change"
+)]
+#[doc(no_inline)]
+pub use crate::arch::global_asm;
+
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow(deprecated, deprecated_in_future)]
 #[doc(no_inline)]
index 7c7dce0ce74e2ba0f7ffb87017cdd1121f48c337..287ae69acd198984683a34e89241d6221c2a3ce2 100644 (file)
@@ -101,7 +101,7 @@ pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
 ///
 /// This function is safe but the returned pointer is not necessarily safe to dereference.
 /// For slices, see the documentation of [`slice::from_raw_parts`] for safety requirements.
-/// For trait objects, the metadata must come from a pointer to the same underlying ereased type.
+/// For trait objects, the metadata must come from a pointer to the same underlying erased type.
 ///
 /// [`slice::from_raw_parts`]: crate::slice::from_raw_parts
 #[unstable(feature = "ptr_metadata", issue = "81513")]
index 6a6cee0911feacf5253d08294e70d0773646cbe0..4b81c39ea1d1b5e9ef181d18c9e0e2a1482ad202 100644 (file)
@@ -430,7 +430,8 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
 }
 
 #[inline]
-pub(crate) unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
+#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
+pub(crate) const unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
     // NOTE(eddyb) SPIR-V's Logical addressing model doesn't allow for arbitrary
     // reinterpretation of values as (chunkable) byte arrays, and the loop in the
     // block optimization in `swap_nonoverlapping_bytes` is hard to rewrite back
@@ -563,7 +564,8 @@ const unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
+#[rustc_const_unstable(feature = "const_replace", issue = "83164")]
+pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
     // SAFETY: the caller must guarantee that `dst` is valid to be
     // cast to a mutable reference (valid for writes, aligned, initialized),
     // and cannot overlap `src` since `dst` must point to a distinct
@@ -869,10 +871,12 @@ pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn write<T>(dst: *mut T, src: T) {
+#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+pub const unsafe fn write<T>(dst: *mut T, src: T) {
     // We are calling the intrinsics directly to avoid function calls in the generated code
     // as `intrinsics::copy_nonoverlapping` is a wrapper function.
     extern "rust-intrinsic" {
+        #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
         fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
     }
 
@@ -964,7 +968,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
 /// ```
 #[inline]
 #[stable(feature = "ptr_unaligned", since = "1.17.0")]
-#[rustc_const_unstable(feature = "const_ptr_write", issue = "none")]
+#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
 pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
     // SAFETY: the caller must guarantee that `dst` is valid for writes.
     // `dst` cannot overlap `src` because the caller has mutable access
index a6424041542d9054c79e060f23772de186088cc3..93ee74719ffa37f2aa0369097c6d32bc3d4a5e01 100644 (file)
@@ -1002,8 +1002,9 @@ impl<T: ?Sized> *mut T {
     ///
     /// [`ptr::write`]: crate::ptr::write()
     #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
     #[inline(always)]
-    pub unsafe fn write(self, val: T)
+    pub const unsafe fn write(self, val: T)
     where
         T: Sized,
     {
@@ -1056,7 +1057,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned()
     #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[rustc_const_unstable(feature = "const_ptr_write", issue = "none")]
+    #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
     #[inline(always)]
     pub const unsafe fn write_unaligned(self, val: T)
     where
index 1c65518af04f56090efd7b6859268b5389584695..3ab40f1faa1d6a2bad27b7dba6a02f5b7f8b4136 100644 (file)
@@ -194,7 +194,7 @@ impl<T: ?Sized> NonNull<T> {
         }
     }
 
-    /// Decompose a (possibly wide) pointer into is address and metadata components.
+    /// Decompose a (possibly wide) pointer into its address and metadata components.
     ///
     /// The pointer can be later reconstructed with [`NonNull::from_raw_parts`].
     #[unstable(feature = "ptr_metadata", issue = "81513")]
diff --git a/library/core/src/raw.rs b/library/core/src/raw.rs
deleted file mode 100644 (file)
index 6d1e28f..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#![allow(missing_docs)]
-#![unstable(feature = "raw", issue = "27751")]
-#![rustc_deprecated(
-    since = "1.53.0",
-    reason = "use pointer metadata APIs instead https://github.com/rust-lang/rust/issues/81513"
-)]
-
-//! Contains struct definitions for the layout of compiler built-in types.
-//!
-//! They can be used as targets of transmutes in unsafe code for manipulating
-//! the raw representations directly.
-//!
-//! Their definition should always match the ABI defined in
-//! `rustc_middle::ty::layout`.
-
-/// The representation of a trait object like `&dyn SomeTrait`.
-///
-/// This struct has the same layout as types like `&dyn SomeTrait` and
-/// `Box<dyn AnotherTrait>`.
-///
-/// `TraitObject` is guaranteed to match layouts, but it is not the
-/// type of trait objects (e.g., the fields are not directly accessible
-/// on a `&dyn SomeTrait`) nor does it control that layout (changing the
-/// definition will not change the layout of a `&dyn SomeTrait`). It is
-/// only designed to be used by unsafe code that needs to manipulate
-/// the low-level details.
-///
-/// There is no way to refer to all trait objects generically, so the only
-/// way to create values of this type is with functions like
-/// [`std::mem::transmute`][transmute]. Similarly, the only way to create a true
-/// trait object from a `TraitObject` value is with `transmute`.
-///
-/// [transmute]: crate::intrinsics::transmute
-///
-/// Synthesizing a trait object with mismatched types—one where the
-/// vtable does not correspond to the type of the value to which the
-/// data pointer points—is highly likely to lead to undefined
-/// behavior.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(raw)]
-///
-/// use std::{mem, raw};
-///
-/// // an example trait
-/// trait Foo {
-///     fn bar(&self) -> i32;
-/// }
-///
-/// impl Foo for i32 {
-///     fn bar(&self) -> i32 {
-///          *self + 1
-///     }
-/// }
-///
-/// let value: i32 = 123;
-///
-/// // let the compiler make a trait object
-/// let object: &dyn Foo = &value;
-///
-/// // look at the raw representation
-/// let raw_object: raw::TraitObject = unsafe { mem::transmute(object) };
-///
-/// // the data pointer is the address of `value`
-/// assert_eq!(raw_object.data as *const i32, &value as *const _);
-///
-/// let other_value: i32 = 456;
-///
-/// // construct a new object, pointing to a different `i32`, being
-/// // careful to use the `i32` vtable from `object`
-/// let synthesized: &dyn Foo = unsafe {
-///      mem::transmute(raw::TraitObject {
-///          data: &other_value as *const _ as *mut (),
-///          vtable: raw_object.vtable,
-///      })
-/// };
-///
-/// // it should work just as if we had constructed a trait object out of
-/// // `other_value` directly
-/// assert_eq!(synthesized.bar(), 457);
-/// ```
-#[repr(C)]
-#[derive(Copy, Clone)]
-#[allow(missing_debug_implementations)]
-pub struct TraitObject {
-    pub data: *mut (),
-    pub vtable: *mut (),
-}
index babd0a0b5528ee3f5fd1495ebc28570eaa990a39..53aaa5219b1d4c0b3b8c6f219f85723dcccc35b5 100644 (file)
 //! [`Ok(T)`]: Ok
 //! [`Err(E)`]: Err
 //! [`io::Error`]: ../../std/io/struct.Error.html
+//!
+//! # Method overview
+//!
+//! In addition to working with pattern matching, [`Result`] provides a
+//! wide variety of different methods.
+//!
+//! ## Querying the variant
+//!
+//! The [`is_ok`] and [`is_err`] methods return [`true`] if the [`Result`]
+//! is [`Ok`] or [`Err`], respectively.
+//!
+//! [`is_err`]: Result::is_err
+//! [`is_ok`]: Result::is_ok
+//!
+//! ## Adapters for working with references
+//!
+//! * [`as_ref`] converts from `&Result<T, E>` to `Result<&T, &E>`
+//! * [`as_mut`] converts from `&mut Result<T, E>` to `Result<&mut T, &mut E>`
+//! * [`as_deref`] converts from `&Result<T, E>` to `Result<&T::Target, &E>`
+//! * [`as_deref_mut`] converts from `&mut Result<T, E>` to
+//!   `Result<&mut T::Target, &mut E>`
+//!
+//! [`as_deref`]: Result::as_deref
+//! [`as_deref_mut`]: Result::as_deref_mut
+//! [`as_mut`]: Result::as_mut
+//! [`as_ref`]: Result::as_ref
+//!
+//! ## Extracting contained values
+//!
+//! These methods extract the contained value in a [`Result<T, E>`] when it
+//! is the [`Ok`] variant. If the [`Result`] is [`Err`]:
+//!
+//! * [`expect`] panics with a provided custom message
+//! * [`unwrap`] panics with a generic message
+//! * [`unwrap_or`] returns the provided default value
+//! * [`unwrap_or_default`] returns the default value of the type `T`
+//!   (which must implement the [`Default`] trait)
+//! * [`unwrap_or_else`] returns the result of evaluating the provided
+//!   function
+//!
+//! The panicking methods [`expect`] and [`unwrap`] require `E` to
+//! implement the [`Debug`] trait.
+//!
+//! [`Debug`]: crate::fmt::Debug
+//! [`expect`]: Result::expect
+//! [`unwrap`]: Result::unwrap
+//! [`unwrap_or`]: Result::unwrap_or
+//! [`unwrap_or_default`]: Result::unwrap_or_default
+//! [`unwrap_or_else`]: Result::unwrap_or_else
+//!
+//! These methods extract the contained value in a [`Result<T, E>`] when it
+//! is the [`Err`] variant. They require `T` to implement the [`Debug`]
+//! trait. If the [`Result`] is [`Ok`]:
+//!
+//! * [`expect_err`] panics with a provided custom message
+//! * [`unwrap_err`] panics with a generic message
+//!
+//! [`Debug`]: crate::fmt::Debug
+//! [`expect_err`]: Result::expect_err
+//! [`unwrap_err`]: Result::unwrap_err
+//!
+//! ## Transforming contained values
+//!
+//! These methods transform [`Result`] to [`Option`]:
+//!
+//! * [`err`][Result::err] transforms [`Result<T, E>`] into [`Option<E>`],
+//!   mapping [`Err(e)`] to [`Some(e)`] and [`Ok(v)`] to [`None`]
+//! * [`ok`][Result::ok] transforms [`Result<T, E>`] into [`Option<T>`],
+//!   mapping [`Ok(v)`] to [`Some(v)`] and [`Err(e)`] to [`None`]
+//! * [`transpose`] transposes a [`Result`] of an [`Option`] into an
+//!   [`Option`] of a [`Result`]
+//!
+// Do NOT add link reference definitions for `err` or `ok`, because they
+// will generate numerous incorrect URLs for `Err` and `Ok` elsewhere, due
+// to case folding.
+//!
+//! [`Err(e)`]: Err
+//! [`Ok(v)`]: Ok
+//! [`Some(e)`]: Option::Some
+//! [`Some(v)`]: Option::Some
+//! [`transpose`]: Result::transpose
+//!
+//! This method transforms the contained value of the [`Ok`] variant:
+//!
+//! * [`map`] transforms [`Result<T, E>`] into [`Result<U, E>`] by applying
+//!   the provided function to the contained value of [`Ok`] and leaving
+//!   [`Err`] values unchanged
+//!
+//! [`map`]: Result::map
+//!
+//! This method transforms the contained value of the [`Err`] variant:
+//!
+//! * [`map_err`] transforms [`Result<T, E>`] into [`Result<T, F>`] by
+//!   applying the provided function to the contained value of [`Err`] and
+//!   leaving [`Ok`] values unchanged
+//!
+//! [`map_err`]: Result::map_err
+//!
+//! These methods transform a [`Result<T, E>`] into a value of a possibly
+//! different type `U`:
+//!
+//! * [`map_or`] applies the provided function to the contained value of
+//!   [`Ok`], or returns the provided default value if the [`Result`] is
+//!   [`Err`]
+//! * [`map_or_else`] applies the provided function to the contained value
+//!   of [`Ok`], or applies the provided fallback function to the contained
+//!   value of [`Err`]
+//!
+//! [`map_or`]: Result::map_or
+//! [`map_or_else`]: Result::map_or_else
+//!
+//! ## Boolean operators
+//!
+//! These methods treat the [`Result`] as a boolean value, where [`Ok`]
+//! acts like [`true`] and [`Err`] acts like [`false`]. There are two
+//! categories of these methods: ones that take a [`Result`] as input, and
+//! ones that take a function as input (to be lazily evaluated).
+//!
+//! The [`and`] and [`or`] methods take another [`Result`] as input, and
+//! produce a [`Result`] as output. The [`and`] method can produce a
+//! [`Result<U, E>`] value having a different inner type `U` than
+//! [`Result<T, E>`]. The [`or`] method can produce a [`Result<T, F>`]
+//! value having a different error type `F` than [`Result<T, E>`].
+//!
+//! | method  | self     | input     | output   |
+//! |---------|----------|-----------|----------|
+//! | [`and`] | `Err(e)` | (ignored) | `Err(e)` |
+//! | [`and`] | `Ok(x)`  | `Err(d)`  | `Err(d)` |
+//! | [`and`] | `Ok(x)`  | `Ok(y)`   | `Ok(y)`  |
+//! | [`or`]  | `Err(e)` | `Err(d)`  | `Err(d)` |
+//! | [`or`]  | `Err(e)` | `Ok(y)`   | `Ok(y)`  |
+//! | [`or`]  | `Ok(x)`  | (ignored) | `Ok(x)`  |
+//!
+//! [`and`]: Result::and
+//! [`or`]: Result::or
+//!
+//! The [`and_then`] and [`or_else`] methods take a function as input, and
+//! only evaluate the function when they need to produce a new value. The
+//! [`and_then`] method can produce a [`Result<U, E>`] value having a
+//! different inner type `U` than [`Result<T, E>`]. The [`or_else`] method
+//! can produce a [`Result<T, F>`] value having a different error type `F`
+//! than [`Result<T, E>`].
+//!
+//! | method       | self     | function input | function result | output   |
+//! |--------------|----------|----------------|-----------------|----------|
+//! | [`and_then`] | `Err(e)` | (not provided) | (not evaluated) | `Err(e)` |
+//! | [`and_then`] | `Ok(x)`  | `x`            | `Err(d)`        | `Err(d)` |
+//! | [`and_then`] | `Ok(x)`  | `x`            | `Ok(y)`         | `Ok(y)`  |
+//! | [`or_else`]  | `Err(e)` | `e`            | `Err(d)`        | `Err(d)` |
+//! | [`or_else`]  | `Err(e)` | `e`            | `Ok(y)`         | `Ok(y)`  |
+//! | [`or_else`]  | `Ok(x)`  | (not provided) | (not evaluated) | `Ok(x)`  |
+//!
+//! [`and_then`]: Result::and_then
+//! [`or_else`]: Result::or_else
+//!
+//! ## Iterating over `Result`
+//!
+//! A [`Result`] can be iterated over. This can be helpful if you need an
+//! iterator that is conditionally empty. The iterator will either produce
+//! a single value (when the [`Result`] is [`Ok`]), or produce no values
+//! (when the [`Result`] is [`Err`]). For example, [`into_iter`] acts like
+//! [`once(v)`] if the [`Result`] is [`Ok(v)`], and like [`empty()`] if the
+//! [`Result`] is [`Err`].
+//!
+//! [`Ok(v)`]: Ok
+//! [`empty()`]: crate::iter::empty
+//! [`once(v)`]: crate::iter::once
+//!
+//! Iterators over [`Result<T, E>`] come in three types:
+//!
+//! * [`into_iter`] consumes the [`Result`] and produces the contained
+//!   value
+//! * [`iter`] produces an immutable reference of type `&T` to the
+//!   contained value
+//! * [`iter_mut`] produces a mutable reference of type `&mut T` to the
+//!   contained value
+//!
+//! See [Iterating over `Option`] for examples of how this can be useful.
+//!
+//! [Iterating over `Option`]: crate::option#iterating-over-option
+//! [`into_iter`]: Result::into_iter
+//! [`iter`]: Result::iter
+//! [`iter_mut`]: Result::iter_mut
+//!
+//! You might want to use an iterator chain to do multiple instances of an
+//! operation that can fail, but would like to ignore failures while
+//! continuing to process the successful results. In this example, we take
+//! advantage of the iterable nature of [`Result`] to select only the
+//! [`Ok`] values using [`flatten`][Iterator::flatten].
+//!
+//! ```
+//! # use std::str::FromStr;
+//! let mut results = vec![];
+//! let mut errs = vec![];
+//! let nums: Vec<_> = vec!["17", "not a number", "99", "-27", "768"]
+//!    .into_iter()
+//!    .map(u8::from_str)
+//!    // Save clones of the raw `Result` values to inspect
+//!    .inspect(|x| results.push(x.clone()))
+//!    // Challenge: explain how this captures only the `Err` values
+//!    .inspect(|x| errs.extend(x.clone().err()))
+//!    .flatten()
+//!    .collect();
+//! assert_eq!(errs.len(), 3);
+//! assert_eq!(nums, [17, 99]);
+//! println!("results {:?}", results);
+//! println!("errs {:?}", errs);
+//! println!("nums {:?}", nums);
+//! ```
+//!
+//! ## Collecting into `Result`
+//!
+//! [`Result`] implements the [`FromIterator`][impl-FromIterator] trait,
+//! which allows an iterator over [`Result`] values to be collected into a
+//! [`Result`] of a collection of each contained value of the original
+//! [`Result`] values, or [`Err`] if any of the elements was [`Err`].
+//!
+//! [impl-FromIterator]: Result#impl-FromIterator%3CResult%3CA%2C%20E%3E%3E
+//!
+//! ```
+//! let v = vec![Ok(2), Ok(4), Err("err!"), Ok(8)];
+//! let res: Result<Vec<_>, &str> = v.into_iter().collect();
+//! assert_eq!(res, Err("err!"));
+//! let v = vec![Ok(2), Ok(4), Ok(8)];
+//! let res: Result<Vec<_>, &str> = v.into_iter().collect();
+//! assert_eq!(res, Ok(vec![2, 4, 8]));
+//! ```
+//!
+//! [`Result`] also implements the [`Product`][impl-Product] and
+//! [`Sum`][impl-Sum] traits, allowing an iterator over [`Result`] values
+//! to provide the [`product`][Iterator::product] and
+//! [`sum`][Iterator::sum] methods.
+//!
+//! [impl-Product]: Result#impl-Product%3CResult%3CU%2C%20E%3E%3E
+//! [impl-Sum]: Result#impl-Sum%3CResult%3CU%2C%20E%3E%3E
+//!
+//! ```
+//! let v = vec![Err("error!"), Ok(1), Ok(2), Ok(3), Err("foo")];
+//! let res: Result<i32, &str> = v.into_iter().sum();
+//! assert_eq!(res, Err("error!"));
+//! let v: Vec<Result<i32, &str>> = vec![Ok(1), Ok(2), Ok(21)];
+//! let res: Result<i32, &str> = v.into_iter().product();
+//! assert_eq!(res, Ok(42));
+//! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -1626,28 +1870,6 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
     }
 }
 
-#[unstable(feature = "try_trait", issue = "42327")]
-#[cfg(bootstrap)]
-impl<T, E> ops::TryV1 for Result<T, E> {
-    type Output = T;
-    type Error = E;
-
-    #[inline]
-    fn into_result(self) -> Self {
-        self
-    }
-
-    #[inline]
-    fn from_ok(v: T) -> Self {
-        Ok(v)
-    }
-
-    #[inline]
-    fn from_error(v: E) -> Self {
-        Err(v)
-    }
-}
-
 #[unstable(feature = "try_trait_v2", issue = "84277")]
 impl<T, E> ops::TryV2 for Result<T, E> {
     type Output = T;
index 1ee662c6c8e3cc60938552e7bd71913abe91e833..5cbc6343e3a77424a85696d80abfe1941bd5211f 100644 (file)
@@ -1418,18 +1418,17 @@ impl<'a, T> Iterator for Chunks<'a, T> {
     #[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 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
         } 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 @@ impl<'a, T> Iterator for ChunksMut<'a, T> {
     #[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 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
         } 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);
@@ -2148,6 +2146,7 @@ impl<'a, T, const N: usize> Iterator for ArrayChunks<'a, T, N> {
         self.iter.last()
     }
 
+    #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> &'a [T; N] {
         // SAFETY: The safety guarantees of `__iterator_get_unchecked` are
         // transferred to the caller.
@@ -2260,6 +2259,7 @@ impl<'a, T, const N: usize> Iterator for ArrayChunksMut<'a, T, N> {
         self.iter.last()
     }
 
+    #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> &'a mut [T; N] {
         // SAFETY: The safety guarantees of `__iterator_get_unchecked` are transferred to
         // the caller.
index 0e5c5ee726e54f4ca07d734a330cd95653287a6d..de25c984abf90fd729c1ce2556d469e2a7cf0ec7 100644 (file)
@@ -95,7 +95,7 @@ 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")]
     #[inline]
@@ -3468,27 +3468,7 @@ impl<T> [T] {
     where
         P: FnMut(&T) -> bool,
     {
-        let mut left = 0;
-        let mut right = self.len();
-
-        while left != right {
-            let mid = left + (right - left) / 2;
-            // SAFETY: When `left < right`, `left <= mid < right`.
-            // Therefore `left` always increases and `right` always decreases,
-            // and either of them is selected. In both cases `left <= right` is
-            // satisfied. Therefore if `left < right` in a step, `left <= right`
-            // is satisfied in the next step. Therefore as long as `left != right`,
-            // `0 <= left < right <= len` is satisfied and if this case
-            // `0 <= mid < len` is satisfied too.
-            let value = unsafe { self.get_unchecked(mid) };
-            if pred(value) {
-                left = mid + 1;
-            } else {
-                right = mid;
-            }
-        }
-
-        left
+        self.binary_search_by(|x| if pred(x) { Less } else { Greater }).unwrap_or_else(|i| i)
     }
 }
 
index a89596b15ef94c31122c845e3f6041449f6018e8..7528927ef33b9a57297f8330e323856cd518a5bb 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-tidy-undocumented-unsafe
-
 use crate::cmp;
 use crate::mem::{self, MaybeUninit};
 use crate::ptr;
@@ -79,8 +77,10 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize)
             // the way until about `left + right == 32`, but the worst case performance breaks even
             // around 16. 24 was chosen as middle ground. If the size of `T` is larger than 4
             // `usize`s, this algorithm also outperforms other algorithms.
+            // SAFETY: callers must ensure `mid - left` is valid for reading and writing.
             let x = unsafe { mid.sub(left) };
             // beginning of first round
+            // SAFETY: see previous comment.
             let mut tmp: T = unsafe { x.read() };
             let mut i = right;
             // `gcd` can be found before hand by calculating `gcd(left + right, right)`,
@@ -92,6 +92,21 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize)
             // the very end. This is possibly due to the fact that swapping or replacing temporaries
             // uses only one memory address in the loop instead of needing to manage two.
             loop {
+                // [long-safety-expl]
+                // SAFETY: callers must ensure `[left, left+mid+right)` are all valid for reading and
+                // writing.
+                //
+                // - `i` start with `right` so `mid-left <= x+i = x+right = mid-left+right < mid+right`
+                // - `i <= left+right-1` is always true
+                //   - if `i < left`, `right` is added so `i < left+right` and on the next
+                //     iteration `left` is removed from `i` so it doesn't go further
+                //   - if `i >= left`, `left` is removed immediately and so it doesn't go further.
+                // - overflows cannot happen for `i` since the function's safety contract ask for
+                //   `mid+right-1 = x+left+right` to be valid for writing
+                // - underflows cannot happen because `i` must be bigger or equal to `left` for
+                //   a substraction of `left` to happen.
+                //
+                // So `x+i` is valid for reading and writing if the caller respected the contract
                 tmp = unsafe { x.add(i).replace(tmp) };
                 // instead of incrementing `i` and then checking if it is outside the bounds, we
                 // check if `i` will go outside the bounds on the next increment. This prevents
@@ -100,6 +115,8 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize)
                     i -= left;
                     if i == 0 {
                         // end of first round
+                        // SAFETY: tmp has been read from a valid source and x is valid for writing
+                        // according to the caller.
                         unsafe { x.write(tmp) };
                         break;
                     }
@@ -113,13 +130,24 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize)
             }
             // finish the chunk with more rounds
             for start in 1..gcd {
+                // SAFETY: `gcd` is at most equal to `right` so all values in `1..gcd` are valid for
+                // reading and writing as per the function's safety contract, see [long-safety-expl]
+                // above
                 tmp = unsafe { x.add(start).read() };
+                // [safety-expl-addition]
+                //
+                // Here `start < gcd` so `start < right` so `i < right+right`: `right` being the
+                // greatest common divisor of `(left+right, right)` means that `left = right` so
+                // `i < left+right` so `x+i = mid-left+i` is always valid for reading and writing
+                // according to the function's safety contract.
                 i = start + right;
                 loop {
+                    // SAFETY: see [long-safety-expl] and [safety-expl-addition]
                     tmp = unsafe { x.add(i).replace(tmp) };
                     if i >= left {
                         i -= left;
                         if i == start {
+                            // SAFETY: see [long-safety-expl] and [safety-expl-addition]
                             unsafe { x.add(start).write(tmp) };
                             break;
                         }
@@ -135,14 +163,30 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize)
             // The `[T; 0]` here is to ensure this is appropriately aligned for T
             let mut rawarray = MaybeUninit::<(BufType, [T; 0])>::uninit();
             let buf = rawarray.as_mut_ptr() as *mut T;
+            // SAFETY: `mid-left <= mid-left+right < mid+right`
             let dim = unsafe { mid.sub(left).add(right) };
             if left <= right {
+                // SAFETY:
+                //
+                // 1) The `else if` condition about the sizes ensures `[mid-left; left]` will fit in
+                //    `buf` without overflow and `buf` was created just above and so cannot be
+                //    overlapped with any value of `[mid-left; left]`
+                // 2) [mid-left, mid+right) are all valid for reading and writing and we don't care
+                //    about overlaps here.
+                // 3) The `if` condition about `left <= right` ensures writing `left` elements to
+                //    `dim = mid-left+right` is valid because:
+                //    - `buf` is valid and `left` elements were written in it in 1)
+                //    - `dim+left = mid-left+right+left = mid+right` and we write `[dim, dim+left)`
                 unsafe {
+                    // 1)
                     ptr::copy_nonoverlapping(mid.sub(left), buf, left);
+                    // 2)
                     ptr::copy(mid, mid.sub(left), right);
+                    // 3)
                     ptr::copy_nonoverlapping(buf, dim, left);
                 }
             } else {
+                // SAFETY: same reasoning as above but with `left` and `right` reversed
                 unsafe {
                     ptr::copy_nonoverlapping(mid, buf, right);
                     ptr::copy(mid.sub(left), dim, left);
@@ -156,6 +200,10 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize)
             // of this algorithm would be, and swapping using that last chunk instead of swapping
             // adjacent chunks like this algorithm is doing, but this way is still faster.
             loop {
+                // SAFETY:
+                // `left >= right` so `[mid-right, mid+right)` is valid for reading and writing
+                // Substracting `right` from `mid` each turn is counterbalanced by the addition and
+                // check after it.
                 unsafe {
                     ptr::swap_nonoverlapping(mid.sub(right), mid, right);
                     mid = mid.sub(right);
@@ -168,6 +216,10 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize)
         } else {
             // Algorithm 3, `left < right`
             loop {
+                // SAFETY: `[mid-left, mid+left)` is valid for reading and writing because
+                // `left < right` so `mid+left < mid+right`.
+                // Adding `left` to `mid` each turn is counterbalanced by the substraction and check
+                // after it.
                 unsafe {
                     ptr::swap_nonoverlapping(mid.sub(left), mid, left);
                     mid = mid.add(left);
index 2a7693d27efa2d9649ec667b6a71d4f5a28514b7..36c2c4abdb4c5b0611e0b489e703bd1a71c3d785 100644 (file)
@@ -227,7 +227,7 @@ where
 /// Partitioning is performed block-by-block in order to minimize the cost of branching operations.
 /// This idea is presented in the [BlockQuicksort][pdf] paper.
 ///
-/// [pdf]: http://drops.dagstuhl.de/opus/volltexte/2016/6389/pdf/LIPIcs-ESA-2016-38.pdf
+/// [pdf]: https://drops.dagstuhl.de/opus/volltexte/2016/6389/pdf/LIPIcs-ESA-2016-38.pdf
 fn partition_in_blocks<T, F>(v: &mut [T], pivot: &T, is_less: &mut F) -> usize
 where
     F: FnMut(&T, &T) -> bool,
index 05ff7bb120daeba91080321a8cd4fe0752e9817d..a51d14207482265fe6c9c4ad472dfa8172ce78bf 100644 (file)
@@ -156,7 +156,7 @@ pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_str_from_utf8_unchecked", issue = "75196")]
+#[rustc_const_stable(feature = "const_str_from_utf8_unchecked", since = "1.55.0")]
 #[rustc_allow_const_fn_unstable(const_fn_transmute)]
 pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
     // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8.
index ccf7b20285cb36615fe229386de0f0b32f453bc4..aa735a14cbd8fff3cab848c8a9340a0ee8243f3a 100644 (file)
@@ -118,10 +118,9 @@ impl fmt::Display for Utf8Error {
 ///
 /// [`from_str`]: super::FromStr::from_str
 #[derive(Debug, Clone, PartialEq, Eq)]
+#[non_exhaustive]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct ParseBoolError {
-    pub(super) _priv: (),
-}
+pub struct ParseBoolError;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for ParseBoolError {
index 6ec6b70b57119b863e3788ef107705f3b8d54c75..a5774764573be4143193b4e4d994379da39bc8fe 100644 (file)
@@ -295,6 +295,7 @@ impl Iterator for Bytes<'_> {
     }
 
     #[inline]
+    #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> u8 {
         // SAFETY: the caller must uphold the safety contract
         // for `Iterator::__iterator_get_unchecked`.
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 0a2743b1c31e5b106c282a58f4a341614cc515dd..12d79a56a527c02765f228a7de187f07865454c5 100644 (file)
@@ -585,7 +585,7 @@ impl FromStr for bool {
         match s {
             "true" => Ok(true),
             "false" => Ok(false),
-            _ => Err(ParseBoolError { _priv: () }),
+            _ => Err(ParseBoolError),
         }
     }
 }
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 9cf89623d888e2d30227f0d8185837157bef6478..fc0a4e747973a15c48299b5b5b8d7548d8d61edb 100644 (file)
@@ -26,7 +26,21 @@ pub enum Poll<T> {
 }
 
 impl<T> Poll<T> {
-    /// Changes the ready value of this `Poll` with the closure provided.
+    /// Maps a `Poll<T>` to `Poll<U>` by applying a function to a contained value.
+    ///
+    /// # Examples
+    ///
+    /// Converts a `Poll<`[`String`]`>` into an `Poll<`[`usize`]`>`, consuming the original:
+    ///
+    /// [`String`]: ../../std/string/struct.String.html
+    /// ```
+    /// # use core::task::Poll;
+    /// let poll_some_string = Poll::Ready(String::from("Hello, World!"));
+    /// // `Poll::map` takes self *by value*, consuming `poll_some_string`
+    /// let poll_some_len = poll_some_string.map(|s| s.len());
+    ///
+    /// assert_eq!(poll_some_len, Poll::Ready(13));
+    /// ```
     #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn map<U, F>(self, f: F) -> Poll<U>
     where
@@ -38,7 +52,18 @@ impl<T> Poll<T> {
         }
     }
 
-    /// Returns `true` if this is `Poll::Ready`
+    /// Returns `true` if the poll is a [`Poll::Ready`] value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use core::task::Poll;
+    /// let x: Poll<u32> = Poll::Ready(2);
+    /// assert_eq!(x.is_ready(), true);
+    ///
+    /// let x: Poll<u32> = Poll::Pending;
+    /// assert_eq!(x.is_ready(), false);
+    /// ```
     #[inline]
     #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
     #[stable(feature = "futures_api", since = "1.36.0")]
@@ -46,7 +71,20 @@ impl<T> Poll<T> {
         matches!(*self, Poll::Ready(_))
     }
 
-    /// Returns `true` if this is `Poll::Pending`
+    /// Returns `true` if the poll is a [`Pending`] value.
+    ///
+    /// [`Pending`]: Poll::Pending
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use core::task::Poll;
+    /// let x: Poll<u32> = Poll::Ready(2);
+    /// assert_eq!(x.is_pending(), false);
+    ///
+    /// let x: Poll<u32> = Poll::Pending;
+    /// assert_eq!(x.is_pending(), true);
+    /// ```
     #[inline]
     #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
     #[stable(feature = "futures_api", since = "1.36.0")]
@@ -56,7 +94,20 @@ impl<T> Poll<T> {
 }
 
 impl<T, E> Poll<Result<T, E>> {
-    /// Changes the success value of this `Poll` with the closure provided.
+    /// Maps a `Poll<Result<T, E>>` to `Poll<Result<U, E>>` by applying a
+    /// function to a contained `Poll::Ready(Ok)` value, leaving all other
+    /// variants untouched.
+    ///
+    /// This function can be used to compose the results of two functions.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use core::task::Poll;
+    /// let res: Poll<Result<u8, _>> = Poll::Ready("12".parse());
+    /// let squared = res.map_ok(|n| n * n);
+    /// assert_eq!(squared, Poll::Ready(Ok(144)));
+    /// ```
     #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
     where
@@ -69,7 +120,21 @@ impl<T, E> Poll<Result<T, E>> {
         }
     }
 
-    /// Changes the error value of this `Poll` with the closure provided.
+    /// Maps a `Poll::Ready<Result<T, E>>` to `Poll::Ready<Result<T, F>>` by
+    /// applying a function to a contained `Poll::Ready(Err)` value, leaving all other
+    /// variants untouched.
+    ///
+    /// This function can be used to pass through a successful result while handling
+    /// an error.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use core::task::Poll;
+    /// let res: Poll<Result<u8, _>> = Poll::Ready("oops".parse());
+    /// let res = res.map_err(|_| 0_u8);
+    /// assert_eq!(res, Poll::Ready(Err(0)));
+    /// ```
     #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
     where
@@ -84,7 +149,20 @@ impl<T, E> Poll<Result<T, E>> {
 }
 
 impl<T, E> Poll<Option<Result<T, E>>> {
-    /// Changes the success value of this `Poll` with the closure provided.
+    /// Maps a `Poll<Option<Result<T, E>>>` to `Poll<Option<Result<U, E>>>` by
+    /// applying a function to a contained `Poll::Ready(Some(Ok))` value,
+    /// leaving all other variants untouched.
+    ///
+    /// This function can be used to compose the results of two functions.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use core::task::Poll;
+    /// let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("12".parse()));
+    /// let squared = res.map_ok(|n| n * n);
+    /// assert_eq!(squared, Poll::Ready(Some(Ok(144))));
+    /// ```
     #[stable(feature = "poll_map", since = "1.51.0")]
     pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
     where
@@ -98,7 +176,22 @@ impl<T, E> Poll<Option<Result<T, E>>> {
         }
     }
 
-    /// Changes the error value of this `Poll` with the closure provided.
+    /// Maps a `Poll::Ready<Option<Result<T, E>>>` to
+    /// `Poll::Ready<Option<Result<T, F>>>` by applying a function to a
+    /// contained `Poll::Ready(Some(Err))` value, leaving all other variants
+    /// untouched.
+    ///
+    /// This function can be used to pass through a successful result while handling
+    /// an error.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use core::task::Poll;
+    /// let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("oops".parse()));
+    /// let res = res.map_err(|_| 0_u8);
+    /// assert_eq!(res, Poll::Ready(Some(Err(0))));
+    /// ```
     #[stable(feature = "poll_map", since = "1.51.0")]
     pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
     where
@@ -128,32 +221,6 @@ impl<T> From<T> for Poll<T> {
     }
 }
 
-#[stable(feature = "futures_api", since = "1.36.0")]
-#[cfg(bootstrap)]
-impl<T, E> ops::TryV1 for Poll<Result<T, E>> {
-    type Output = Poll<T>;
-    type Error = E;
-
-    #[inline]
-    fn into_result(self) -> Result<Self::Output, Self::Error> {
-        match self {
-            Poll::Ready(Ok(x)) => Ok(Poll::Ready(x)),
-            Poll::Ready(Err(e)) => Err(e),
-            Poll::Pending => Ok(Poll::Pending),
-        }
-    }
-
-    #[inline]
-    fn from_error(e: Self::Error) -> Self {
-        Poll::Ready(Err(e))
-    }
-
-    #[inline]
-    fn from_ok(x: Self::Output) -> Self {
-        x.map(Ok)
-    }
-}
-
 #[unstable(feature = "try_trait_v2", issue = "84277")]
 impl<T, E> ops::TryV2 for Poll<Result<T, E>> {
     type Output = Poll<T>;
@@ -184,33 +251,6 @@ impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Pol
     }
 }
 
-#[stable(feature = "futures_api", since = "1.36.0")]
-#[cfg(bootstrap)]
-impl<T, E> ops::TryV1 for Poll<Option<Result<T, E>>> {
-    type Output = Poll<Option<T>>;
-    type Error = E;
-
-    #[inline]
-    fn into_result(self) -> Result<Self::Output, Self::Error> {
-        match self {
-            Poll::Ready(Some(Ok(x))) => Ok(Poll::Ready(Some(x))),
-            Poll::Ready(Some(Err(e))) => Err(e),
-            Poll::Ready(None) => Ok(Poll::Ready(None)),
-            Poll::Pending => Ok(Poll::Pending),
-        }
-    }
-
-    #[inline]
-    fn from_error(e: Self::Error) -> Self {
-        Poll::Ready(Some(Err(e)))
-    }
-
-    #[inline]
-    fn from_ok(x: Self::Output) -> Self {
-        x.map(|x| x.map(Ok))
-    }
-}
-
 #[unstable(feature = "try_trait_v2", issue = "84277")]
 impl<T, E> ops::TryV2 for Poll<Option<Result<T, E>>> {
     type Output = Poll<Option<T>>;
index 489b722440362fcbc11a173013f96eef17eb3861..2d8a1cb1ab01639757cc0efc20ed062da46cdb7c 100644 (file)
@@ -61,6 +61,7 @@ const MICROS_PER_SEC: u64 = 1_000_000;
 /// crate to do so.
 #[stable(feature = "duration", since = "1.3.0")]
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
+#[cfg_attr(not(test), rustc_diagnostic_item = "Duration")]
 pub struct Duration {
     secs: u64,
     nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC
@@ -687,21 +688,47 @@ impl Duration {
     #[inline]
     #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
     pub const fn from_secs_f64(secs: f64) -> Duration {
+        match Duration::try_from_secs_f64(secs) {
+            Ok(v) => v,
+            Err(e) => crate::panicking::panic(e.description()),
+        }
+    }
+
+    /// The checked version of [`from_secs_f64`].
+    ///
+    /// [`from_secs_f64`]: Duration::from_secs_f64
+    ///
+    /// This constructor will return an `Err` if `secs` is not finite, negative or overflows `Duration`.
+    ///
+    /// # Examples
+    /// ```
+    /// #![feature(duration_checked_float)]
+    ///
+    /// use std::time::Duration;
+    ///
+    /// let dur = Duration::try_from_secs_f64(2.7);
+    /// assert_eq!(dur, Ok(Duration::new(2, 700_000_000)));
+    ///
+    /// let negative = Duration::try_from_secs_f64(-5.0);
+    /// assert!(negative.is_err());
+    /// ```
+    #[unstable(feature = "duration_checked_float", issue = "83400")]
+    #[inline]
+    pub const fn try_from_secs_f64(secs: f64) -> Result<Duration, FromSecsError> {
         const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f64;
         let nanos = secs * (NANOS_PER_SEC as f64);
         if !nanos.is_finite() {
-            panic!("got non-finite value when converting float to duration");
-        }
-        if nanos >= MAX_NANOS_F64 {
-            panic!("overflow when converting float to duration");
-        }
-        if nanos < 0.0 {
-            panic!("underflow when converting float to duration");
-        }
-        let nanos = nanos as u128;
-        Duration {
-            secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
-            nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
+            Err(FromSecsError { kind: FromSecsErrorKind::NonFinite })
+        } else if nanos >= MAX_NANOS_F64 {
+            Err(FromSecsError { kind: FromSecsErrorKind::Overflow })
+        } else if nanos < 0.0 {
+            Err(FromSecsError { kind: FromSecsErrorKind::Underflow })
+        } else {
+            let nanos = nanos as u128;
+            Ok(Duration {
+                secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
+                nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
+            })
         }
     }
 
@@ -722,21 +749,47 @@ impl Duration {
     #[inline]
     #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
     pub const fn from_secs_f32(secs: f32) -> Duration {
+        match Duration::try_from_secs_f32(secs) {
+            Ok(v) => v,
+            Err(e) => crate::panicking::panic(e.description()),
+        }
+    }
+
+    /// The checked version of [`from_secs_f32`].
+    ///
+    /// [`from_secs_f32`]: Duration::from_secs_f32
+    ///
+    /// This constructor will return an `Err` if `secs` is not finite, negative or overflows `Duration`.
+    ///
+    /// # Examples
+    /// ```
+    /// #![feature(duration_checked_float)]
+    ///
+    /// use std::time::Duration;
+    ///
+    /// let dur = Duration::try_from_secs_f32(2.7);
+    /// assert_eq!(dur, Ok(Duration::new(2, 700_000_000)));
+    ///
+    /// let negative = Duration::try_from_secs_f32(-5.0);
+    /// assert!(negative.is_err());
+    /// ```
+    #[unstable(feature = "duration_checked_float", issue = "83400")]
+    #[inline]
+    pub const fn try_from_secs_f32(secs: f32) -> Result<Duration, FromSecsError> {
         const MAX_NANOS_F32: f32 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f32;
         let nanos = secs * (NANOS_PER_SEC as f32);
         if !nanos.is_finite() {
-            panic!("got non-finite value when converting float to duration");
-        }
-        if nanos >= MAX_NANOS_F32 {
-            panic!("overflow when converting float to duration");
-        }
-        if nanos < 0.0 {
-            panic!("underflow when converting float to duration");
-        }
-        let nanos = nanos as u128;
-        Duration {
-            secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
-            nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
+            Err(FromSecsError { kind: FromSecsErrorKind::NonFinite })
+        } else if nanos >= MAX_NANOS_F32 {
+            Err(FromSecsError { kind: FromSecsErrorKind::Overflow })
+        } else if nanos < 0.0 {
+            Err(FromSecsError { kind: FromSecsErrorKind::Underflow })
+        } else {
+            let nanos = nanos as u128;
+            Ok(Duration {
+                secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
+                nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
+            })
         }
     }
 
@@ -1099,3 +1152,55 @@ impl fmt::Debug for Duration {
         }
     }
 }
+
+/// An error which can be returned when converting a floating-point value of seconds
+/// into a [`Duration`].
+///
+/// This error is used as the error type for [`Duration::try_from_secs_f32`] and
+/// [`Duration::try_from_secs_f64`].
+///
+/// # Example
+///
+/// ```
+/// #![feature(duration_checked_float)]
+///
+/// use std::time::Duration;
+///
+/// if let Err(e) = Duration::try_from_secs_f32(-1.0) {
+///     println!("Failed conversion to Duration: {}", e);
+/// }
+/// ```
+#[derive(Debug, Clone, PartialEq, Eq)]
+#[unstable(feature = "duration_checked_float", issue = "83400")]
+pub struct FromSecsError {
+    kind: FromSecsErrorKind,
+}
+
+impl FromSecsError {
+    const fn description(&self) -> &'static str {
+        match self.kind {
+            FromSecsErrorKind::NonFinite => {
+                "got non-finite value when converting float to duration"
+            }
+            FromSecsErrorKind::Overflow => "overflow when converting float to duration",
+            FromSecsErrorKind::Underflow => "underflow when converting float to duration",
+        }
+    }
+}
+
+#[unstable(feature = "duration_checked_float", issue = "83400")]
+impl fmt::Display for FromSecsError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self.description(), f)
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+enum FromSecsErrorKind {
+    // Value is not a finite value (either infinity or NaN).
+    NonFinite,
+    // Value is too large to store in a `Duration`.
+    Overflow,
+    // Value is less than `0.0`.
+    Underflow,
+}
index 37ca0a0779b178e7565a6b198ec691300a5a743d..72fa059b787df48bf7c67dea1964c3696038be5b 100644 (file)
@@ -4,7 +4,7 @@
 pub(crate) mod printable;
 mod unicode_data;
 
-/// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of
+/// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of
 /// `char` and `str` methods are based on.
 ///
 /// New versions of Unicode are released regularly and subsequently all methods
index 91db6381c9b6670ccc5a69e29feeac257cb017c5..c42850d2324134acf5f4baa5c5a7f27c0f86e25e 100755 (executable)
@@ -130,7 +130,7 @@ def print_normal(normal, normalname):
     print("];")
 
 def main():
-    file = get_file("http://www.unicode.org/Public/UNIDATA/UnicodeData.txt")
+    file = get_file("https://www.unicode.org/Public/UNIDATA/UnicodeData.txt")
 
     codepoints = get_codepoints(file)
 
index 4acd059ab03dfeaab4b80dd7338e3c5330e9eced..152fed803ecdb751167ccbb31a3155958920523a 100644 (file)
@@ -49,3 +49,53 @@ fn mut_ptr_read() {
     const UNALIGNED: u16 = unsafe { UNALIGNED_PTR.read_unaligned() };
     assert_eq!(UNALIGNED, u16::from_ne_bytes([0x23, 0x45]));
 }
+
+#[test]
+fn write() {
+    use core::ptr;
+
+    const fn write_aligned() -> i32 {
+        let mut res = 0;
+        unsafe {
+            ptr::write(&mut res as *mut _, 42);
+        }
+        res
+    }
+    const ALIGNED: i32 = write_aligned();
+    assert_eq!(ALIGNED, 42);
+
+    const fn write_unaligned() -> [u16; 2] {
+        let mut two_aligned = [0u16; 2];
+        unsafe {
+            let unaligned_ptr = (two_aligned.as_mut_ptr() as *mut u8).add(1) as *mut u16;
+            ptr::write_unaligned(unaligned_ptr, u16::from_ne_bytes([0x23, 0x45]));
+        }
+        two_aligned
+    }
+    const UNALIGNED: [u16; 2] = write_unaligned();
+    assert_eq!(UNALIGNED, [u16::from_ne_bytes([0x00, 0x23]), u16::from_ne_bytes([0x45, 0x00])]);
+}
+
+#[test]
+fn mut_ptr_write() {
+    const fn aligned() -> i32 {
+        let mut res = 0;
+        unsafe {
+            (&mut res as *mut i32).write(42);
+        }
+        res
+    }
+    const ALIGNED: i32 = aligned();
+    assert_eq!(ALIGNED, 42);
+
+    const fn write_unaligned() -> [u16; 2] {
+        let mut two_aligned = [0u16; 2];
+        unsafe {
+            let unaligned_ptr = (two_aligned.as_mut_ptr() as *mut u8).add(1) as *mut u16;
+            unaligned_ptr.write_unaligned(u16::from_ne_bytes([0x23, 0x45]));
+        }
+        two_aligned
+    }
+    const UNALIGNED: [u16; 2] = write_unaligned();
+    assert_eq!(UNALIGNED, [u16::from_ne_bytes([0x00, 0x23]), u16::from_ne_bytes([0x45, 0x00])]);
+}
index 1566d35749017c99b2d8df5a0be2805abd739cd4..72ccdd4848a47ec4979c12744f3173b3ca286b84 100644 (file)
@@ -1,7 +1,7 @@
 mod sip;
 
 use std::default::Default;
-use std::hash::{Hash, Hasher};
+use std::hash::{BuildHasher, Hash, Hasher};
 use std::rc::Rc;
 
 struct MyHasher {
@@ -139,3 +139,10 @@ fn test_indirect_hasher() {
     }
     assert_eq!(hasher.hash, 5);
 }
+
+#[test]
+fn test_build_hasher_object_safe() {
+    use std::collections::hash_map::{DefaultHasher, RandomState};
+
+    let _: &dyn BuildHasher<Hasher = DefaultHasher> = &RandomState::new();
+}
index 4bbae6947bf66ed9b90a0f42b0cf541fff1158b4..aaac39c297933f240d386f9e5123e9bfcd9da815 100644 (file)
@@ -1,4 +1,5 @@
 use super::*;
+use core::array;
 use core::iter::*;
 
 #[test]
@@ -109,3 +110,42 @@ fn test_double_ended_flatten() {
     assert_eq!(it.next(), None);
     assert_eq!(it.next_back(), None);
 }
+
+#[test]
+fn test_trusted_len_flatten() {
+    fn assert_trusted_len<T: TrustedLen>(_: &T) {}
+    let mut iter = array::IntoIter::new([[0; 3]; 4]).flatten();
+    assert_trusted_len(&iter);
+
+    assert_eq!(iter.size_hint(), (12, Some(12)));
+    iter.next();
+    assert_eq!(iter.size_hint(), (11, Some(11)));
+    iter.next_back();
+    assert_eq!(iter.size_hint(), (10, Some(10)));
+
+    let iter = array::IntoIter::new([[(); usize::MAX]; 1]).flatten();
+    assert_eq!(iter.size_hint(), (usize::MAX, Some(usize::MAX)));
+
+    let iter = array::IntoIter::new([[(); usize::MAX]; 2]).flatten();
+    assert_eq!(iter.size_hint(), (usize::MAX, None));
+
+    let mut a = [(); 10];
+    let mut b = [(); 10];
+
+    let iter = array::IntoIter::new([&mut a, &mut b]).flatten();
+    assert_trusted_len(&iter);
+    assert_eq!(iter.size_hint(), (20, Some(20)));
+    core::mem::drop(iter);
+
+    let iter = array::IntoIter::new([&a, &b]).flatten();
+    assert_trusted_len(&iter);
+    assert_eq!(iter.size_hint(), (20, Some(20)));
+
+    let iter = [(), (), ()].iter().flat_map(|_| [(); 1000]);
+    assert_trusted_len(&iter);
+    assert_eq!(iter.size_hint(), (3000, Some(3000)));
+
+    let iter = [(), ()].iter().flat_map(|_| &a);
+    assert_trusted_len(&iter);
+    assert_eq!(iter.size_hint(), (20, Some(20)));
+}
index 797bfd957f906ec2cc4c28632cc621e0b3f1fcc2..585cfbb90e40c1d3cfcd5d1718b0f77d7765d1c3 100644 (file)
@@ -232,6 +232,33 @@ fn test_zip_trusted_random_access_composition() {
     assert_eq!(z2.next().unwrap(), ((1, 1), 1));
 }
 
+#[test]
+#[cfg(panic = "unwind")]
+fn test_zip_trusted_random_access_next_back_drop() {
+    use std::panic::catch_unwind;
+    use std::panic::AssertUnwindSafe;
+
+    let mut counter = 0;
+
+    let it = [42].iter().map(|e| {
+        let c = counter;
+        counter += 1;
+        if c == 0 {
+            panic!("bomb");
+        }
+
+        e
+    });
+    let it2 = [(); 0].iter();
+    let mut zip = it.zip(it2);
+    catch_unwind(AssertUnwindSafe(|| {
+        zip.next_back();
+    }))
+    .unwrap_err();
+    assert!(zip.next().is_none());
+    assert_eq!(counter, 1);
+}
+
 #[test]
 fn test_double_ended_zip() {
     let xs = [1, 2, 3, 4, 5, 6];
index 16051b3bc36c72701cf83546a8f60cac73b5fb21..c7756a503c3e9956d7f1ba1089655fd631b4e25c 100644 (file)
@@ -1,10 +1,8 @@
 #![feature(alloc_layout_extra)]
 #![feature(array_chunks)]
 #![feature(array_methods)]
-#![feature(array_map)]
 #![feature(array_windows)]
 #![feature(bool_to_option)]
-#![feature(bound_cloned)]
 #![feature(box_syntax)]
 #![feature(cell_update)]
 #![feature(cfg_panic)]
@@ -15,7 +13,6 @@
 #![feature(const_ptr_read)]
 #![feature(const_ptr_write)]
 #![feature(const_ptr_offset)]
-#![feature(control_flow_enum)]
 #![feature(core_intrinsics)]
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
@@ -31,7 +28,6 @@
 #![feature(try_find)]
 #![feature(is_sorted)]
 #![feature(pattern)]
-#![feature(raw)]
 #![feature(sort_internals)]
 #![feature(slice_partition_at_index)]
 #![feature(maybe_uninit_uninit_array)]
@@ -39,6 +35,7 @@
 #![feature(maybe_uninit_extra)]
 #![feature(maybe_uninit_write_slice)]
 #![feature(min_specialization)]
+#![feature(numfmt)]
 #![feature(step_trait)]
 #![feature(str_internals)]
 #![feature(test)]
@@ -46,7 +43,7 @@
 #![feature(try_trait_v2)]
 #![feature(slice_internals)]
 #![feature(slice_partition_dedup)]
-#![feature(int_error_matching)]
+#![feature(int_log)]
 #![feature(iter_advance_by)]
 #![feature(iter_partition_in_place)]
 #![feature(iter_intersperse)]
index 77a338daf7dcb45b60708d2c47d8013f92fc29ee..9eac279733af902a334f42184e7bb22d520675fa 100644 (file)
@@ -2,6 +2,7 @@ use core::mem::ManuallyDrop;
 
 #[test]
 fn smoke() {
+    #[derive(Clone)]
     struct TypeWithDrop;
     impl Drop for TypeWithDrop {
         fn drop(&mut self) {
@@ -16,4 +17,11 @@ fn smoke() {
     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);
 }
index dfdbc9305d2a360e56262aa10d14578ae817651f..c780bb32ca96d89d818ead5eec654d592aedc00a 100644 (file)
@@ -97,28 +97,6 @@ fn test_transmute_copy() {
     assert_eq!(1, unsafe { transmute_copy(&1) });
 }
 
-// Remove this test when `std::raw` is removed.
-// The replacement pointer metadata APIs are tested in library/core/tests/ptr.rs
-#[allow(deprecated)]
-#[test]
-fn test_transmute() {
-    trait Foo {
-        fn dummy(&self) {}
-    }
-    impl Foo for isize {}
-
-    let a = box 100isize as Box<dyn Foo>;
-    unsafe {
-        let x: ::core::raw::TraitObject = transmute(a);
-        assert!(*(x.data as *const isize) == 100);
-        let _x: Box<dyn Foo> = transmute(x);
-    }
-
-    unsafe {
-        assert_eq!(transmute::<_, Vec<u8>>("L".to_string()), [76]);
-    }
-}
-
 #[test]
 #[allow(dead_code)]
 fn test_discriminant_send_sync() {
diff --git a/library/core/tests/num/dec2flt/float.rs b/library/core/tests/num/dec2flt/float.rs
new file mode 100644 (file)
index 0000000..7a9587a
--- /dev/null
@@ -0,0 +1,33 @@
+use core::num::dec2flt::float::RawFloat;
+
+#[test]
+fn test_f32_integer_decode() {
+    assert_eq!(3.14159265359f32.integer_decode(), (13176795, -22, 1));
+    assert_eq!((-8573.5918555f32).integer_decode(), (8779358, -10, -1));
+    assert_eq!(2f32.powf(100.0).integer_decode(), (8388608, 77, 1));
+    assert_eq!(0f32.integer_decode(), (0, -150, 1));
+    assert_eq!((-0f32).integer_decode(), (0, -150, -1));
+    assert_eq!(f32::INFINITY.integer_decode(), (8388608, 105, 1));
+    assert_eq!(f32::NEG_INFINITY.integer_decode(), (8388608, 105, -1));
+
+    // Ignore the "sign" (quiet / signalling flag) of NAN.
+    // It can vary between runtime operations and LLVM folding.
+    let (nan_m, nan_e, _nan_s) = f32::NAN.integer_decode();
+    assert_eq!((nan_m, nan_e), (12582912, 105));
+}
+
+#[test]
+fn test_f64_integer_decode() {
+    assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906, -51, 1));
+    assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931, -39, -1));
+    assert_eq!(2f64.powf(100.0).integer_decode(), (4503599627370496, 48, 1));
+    assert_eq!(0f64.integer_decode(), (0, -1075, 1));
+    assert_eq!((-0f64).integer_decode(), (0, -1075, -1));
+    assert_eq!(f64::INFINITY.integer_decode(), (4503599627370496, 972, 1));
+    assert_eq!(f64::NEG_INFINITY.integer_decode(), (4503599627370496, 972, -1));
+
+    // Ignore the "sign" (quiet / signalling flag) of NAN.
+    // It can vary between runtime operations and LLVM folding.
+    let (nan_m, nan_e, _nan_s) = f64::NAN.integer_decode();
+    assert_eq!((nan_m, nan_e), (6755399441055744, 972));
+}
diff --git a/library/core/tests/num/dec2flt/lemire.rs b/library/core/tests/num/dec2flt/lemire.rs
new file mode 100644 (file)
index 0000000..f71bbb7
--- /dev/null
@@ -0,0 +1,53 @@
+use core::num::dec2flt::lemire::compute_float;
+
+fn compute_float32(q: i64, w: u64) -> (i32, u64) {
+    let fp = compute_float::<f32>(q, w);
+    (fp.e, fp.f)
+}
+
+fn compute_float64(q: i64, w: u64) -> (i32, u64) {
+    let fp = compute_float::<f64>(q, w);
+    (fp.e, fp.f)
+}
+
+#[test]
+fn compute_float_f32_rounding() {
+    // These test near-halfway cases for single-precision floats.
+    assert_eq!(compute_float32(0, 16777216), (151, 0));
+    assert_eq!(compute_float32(0, 16777217), (151, 0));
+    assert_eq!(compute_float32(0, 16777218), (151, 1));
+    assert_eq!(compute_float32(0, 16777219), (151, 2));
+    assert_eq!(compute_float32(0, 16777220), (151, 2));
+
+    // These are examples of the above tests, with
+    // digits from the exponent shifted to the mantissa.
+    assert_eq!(compute_float32(-10, 167772160000000000), (151, 0));
+    assert_eq!(compute_float32(-10, 167772170000000000), (151, 0));
+    assert_eq!(compute_float32(-10, 167772180000000000), (151, 1));
+    // Let's check the lines to see if anything is different in table...
+    assert_eq!(compute_float32(-10, 167772190000000000), (151, 2));
+    assert_eq!(compute_float32(-10, 167772200000000000), (151, 2));
+}
+
+#[test]
+fn compute_float_f64_rounding() {
+    // These test near-halfway cases for double-precision floats.
+    assert_eq!(compute_float64(0, 9007199254740992), (1076, 0));
+    assert_eq!(compute_float64(0, 9007199254740993), (1076, 0));
+    assert_eq!(compute_float64(0, 9007199254740994), (1076, 1));
+    assert_eq!(compute_float64(0, 9007199254740995), (1076, 2));
+    assert_eq!(compute_float64(0, 9007199254740996), (1076, 2));
+    assert_eq!(compute_float64(0, 18014398509481984), (1077, 0));
+    assert_eq!(compute_float64(0, 18014398509481986), (1077, 0));
+    assert_eq!(compute_float64(0, 18014398509481988), (1077, 1));
+    assert_eq!(compute_float64(0, 18014398509481990), (1077, 2));
+    assert_eq!(compute_float64(0, 18014398509481992), (1077, 2));
+
+    // These are examples of the above tests, with
+    // digits from the exponent shifted to the mantissa.
+    assert_eq!(compute_float64(-3, 9007199254740992000), (1076, 0));
+    assert_eq!(compute_float64(-3, 9007199254740993000), (1076, 0));
+    assert_eq!(compute_float64(-3, 9007199254740994000), (1076, 1));
+    assert_eq!(compute_float64(-3, 9007199254740995000), (1076, 2));
+    assert_eq!(compute_float64(-3, 9007199254740996000), (1076, 2));
+}
index 32f05d1def50a961f2cde604b7271c6e967c09ec..4990d4a083df62e5faa3b01979f74b4ee8654915 100644 (file)
@@ -1,7 +1,8 @@
 #![allow(overflowing_literals)]
 
+mod float;
+mod lemire;
 mod parse;
-mod rawfp;
 
 // Take a float literal, turn it into a string in various ways (that are all trusted
 // to be correct) and see if those strings are parsed back to the value of the literal.
@@ -28,12 +29,6 @@ fn ordinary() {
     test_literal!(0.1);
     test_literal!(12345.);
     test_literal!(0.9999999);
-
-    if cfg!(miri) {
-        // Miri is too slow
-        return;
-    }
-
     test_literal!(2.2250738585072014e-308);
 }
 
@@ -54,7 +49,6 @@ fn large() {
 }
 
 #[test]
-#[cfg_attr(miri, ignore)] // Miri is too slow
 fn subnormals() {
     test_literal!(5e-324);
     test_literal!(91e-324);
@@ -66,7 +60,6 @@ fn subnormals() {
 }
 
 #[test]
-#[cfg_attr(miri, ignore)] // Miri is too slow
 fn infinity() {
     test_literal!(1e400);
     test_literal!(1e309);
@@ -78,12 +71,6 @@ fn infinity() {
 fn zero() {
     test_literal!(0.0);
     test_literal!(1e-325);
-
-    if cfg!(miri) {
-        // Miri is too slow
-        return;
-    }
-
     test_literal!(1e-326);
     test_literal!(1e-500);
 }
index bb7e51d30026ad1ed087a2196dfc6d29db43e62c..473feacc91fa95eb48fb8b32ee468ab7c87cedfb 100644 (file)
@@ -1,17 +1,23 @@
-use core::num::dec2flt::parse::ParseResult::{Invalid, Valid};
-use core::num::dec2flt::parse::{parse_decimal, Decimal};
+use core::num::dec2flt::number::Number;
+use core::num::dec2flt::parse::parse_number;
+use core::num::dec2flt::{dec2flt, pfe_invalid};
+
+fn new_number(e: i64, m: u64) -> Number {
+    Number { exponent: e, mantissa: m, negative: false, many_digits: false }
+}
 
 #[test]
 fn missing_pieces() {
     let permutations = &[".e", "1e", "e4", "e", ".12e", "321.e", "32.12e+", "12.32e-"];
     for &s in permutations {
-        assert_eq!(parse_decimal(s), Invalid);
+        assert_eq!(dec2flt::<f64>(s), Err(pfe_invalid()));
     }
 }
 
 #[test]
 fn invalid_chars() {
     let invalid = "r,?<j";
+    let error = Err(pfe_invalid());
     let valid_strings = &["123", "666.", ".1", "5e1", "7e-3", "0.0e+1"];
     for c in invalid.chars() {
         for s in valid_strings {
@@ -19,23 +25,153 @@ fn invalid_chars() {
                 let mut input = String::new();
                 input.push_str(s);
                 input.insert(i, c);
-                assert!(parse_decimal(&input) == Invalid, "did not reject invalid {:?}", input);
+                assert!(dec2flt::<f64>(&input) == error, "did not reject invalid {:?}", input);
             }
         }
     }
 }
 
+fn parse_positive(s: &[u8]) -> Option<Number> {
+    parse_number(s, false)
+}
+
 #[test]
 fn valid() {
-    assert_eq!(parse_decimal("123.456e789"), Valid(Decimal::new(b"123", b"456", 789)));
-    assert_eq!(parse_decimal("123.456e+789"), Valid(Decimal::new(b"123", b"456", 789)));
-    assert_eq!(parse_decimal("123.456e-789"), Valid(Decimal::new(b"123", b"456", -789)));
-    assert_eq!(parse_decimal(".050"), Valid(Decimal::new(b"", b"050", 0)));
-    assert_eq!(parse_decimal("999"), Valid(Decimal::new(b"999", b"", 0)));
-    assert_eq!(parse_decimal("1.e300"), Valid(Decimal::new(b"1", b"", 300)));
-    assert_eq!(parse_decimal(".1e300"), Valid(Decimal::new(b"", b"1", 300)));
-    assert_eq!(parse_decimal("101e-33"), Valid(Decimal::new(b"101", b"", -33)));
+    assert_eq!(parse_positive(b"123.456e789"), Some(new_number(786, 123456)));
+    assert_eq!(parse_positive(b"123.456e+789"), Some(new_number(786, 123456)));
+    assert_eq!(parse_positive(b"123.456e-789"), Some(new_number(-792, 123456)));
+    assert_eq!(parse_positive(b".050"), Some(new_number(-3, 50)));
+    assert_eq!(parse_positive(b"999"), Some(new_number(0, 999)));
+    assert_eq!(parse_positive(b"1.e300"), Some(new_number(300, 1)));
+    assert_eq!(parse_positive(b".1e300"), Some(new_number(299, 1)));
+    assert_eq!(parse_positive(b"101e-33"), Some(new_number(-33, 101)));
     let zeros = "0".repeat(25);
     let s = format!("1.5e{}", zeros);
-    assert_eq!(parse_decimal(&s), Valid(Decimal::new(b"1", b"5", 0)));
+    assert_eq!(parse_positive(s.as_bytes()), Some(new_number(-1, 15)));
+}
+
+macro_rules! assert_float_result_bits_eq {
+    ($bits:literal, $ty:ty, $str:literal) => {{
+        let p = dec2flt::<$ty>($str);
+        assert_eq!(p.map(|x| x.to_bits()), Ok($bits));
+    }};
+}
+
+#[test]
+fn issue31109() {
+    // Regression test for #31109.
+    // Ensure the test produces a valid float with the expected bit pattern.
+    assert_float_result_bits_eq!(
+        0x3fd5555555555555,
+        f64,
+        "0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333"
+    );
+}
+
+#[test]
+fn issue31407() {
+    // Regression test for #31407.
+    // Ensure the test produces a valid float with the expected bit pattern.
+    assert_float_result_bits_eq!(
+        0x1752a64e34ba0d3,
+        f64,
+        "1234567890123456789012345678901234567890e-340"
+    );
+    assert_float_result_bits_eq!(
+        0xfffffffffffff,
+        f64,
+        "2.225073858507201136057409796709131975934819546351645648023426109724822222021076945516529523908135087914149158913039621106870086438694594645527657207407820621743379988141063267329253552286881372149012981122451451889849057222307285255133155755015914397476397983411801999323962548289017107081850690630666655994938275772572015763062690663332647565300009245888316433037779791869612049497390377829704905051080609940730262937128958950003583799967207254304360284078895771796150945516748243471030702609144621572289880258182545180325707018860872113128079512233426288368622321503775666622503982534335974568884423900265498198385487948292206894721689831099698365846814022854243330660339850886445804001034933970427567186443383770486037861622771738545623065874679014086723327636718749999999999999999999999999999999999999e-308"
+    );
+    assert_float_result_bits_eq!(
+        0x10000000000000,
+        f64,
+        "2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508791414915891303962110687008643869459464552765720740782062174337998814106326732925355228688137214901298112245145188984905722230728525513315575501591439747639798341180199932396254828901710708185069063066665599493827577257201576306269066333264756530000924588831643303777979186961204949739037782970490505108060994073026293712895895000358379996720725430436028407889577179615094551674824347103070260914462157228988025818254518032570701886087211312807951223342628836862232150377566662250398253433597456888442390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042756718644338377048603786162277173854562306587467901408672332763671875e-308"
+    );
+    assert_float_result_bits_eq!(
+        0x10000000000000,
+        f64,
+        "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000222507385850720138309023271733240406421921598046233183055332741688720443481391819585428315901251102056406733973103581100515243416155346010885601238537771882113077799353200233047961014744258363607192156504694250373420837525080665061665815894872049117996859163964850063590877011830487479978088775374994945158045160505091539985658247081864511353793580499211598108576605199243335211435239014879569960959128889160299264151106346631339366347758651302937176204732563178148566435087212282863764204484681140761391147706280168985324411002416144742161856716615054015428508471675290190316132277889672970737312333408698898317506783884692609277397797285865965494109136909540613646756870239867831529068098461721092462539672851562500000000000000001"
+    );
+    assert_float_result_bits_eq!(
+        0x7fefffffffffffff,
+        f64,
+        "179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.9999999999999999999999999999999999999999999999999999999999999999999999"
+    );
+    assert_float_result_bits_eq!(0x0, f64, "2.47032822920623272e-324");
+    assert_float_result_bits_eq!(
+        0x8000000,
+        f64,
+        "6.631236871469758276785396630275967243399099947355303144249971758736286630139265439618068200788048744105960420552601852889715006376325666595539603330361800519107591783233358492337208057849499360899425128640718856616503093444922854759159988160304439909868291973931426625698663157749836252274523485312442358651207051292453083278116143932569727918709786004497872322193856150225415211997283078496319412124640111777216148110752815101775295719811974338451936095907419622417538473679495148632480391435931767981122396703443803335529756003353209830071832230689201383015598792184172909927924176339315507402234836120730914783168400715462440053817592702766213559042115986763819482654128770595766806872783349146967171293949598850675682115696218943412532098591327667236328125E-316"
+    );
+    assert_float_result_bits_eq!(
+        0x10000,
+        f64,
+        "3.237883913302901289588352412501532174863037669423108059901297049552301970670676565786835742587799557860615776559838283435514391084153169252689190564396459577394618038928365305143463955100356696665629202017331344031730044369360205258345803431471660032699580731300954848363975548690010751530018881758184174569652173110473696022749934638425380623369774736560008997404060967498028389191878963968575439222206416981462690113342524002724385941651051293552601421155333430225237291523843322331326138431477823591142408800030775170625915670728657003151953664260769822494937951845801530895238439819708403389937873241463484205608000027270531106827387907791444918534771598750162812548862768493201518991668028251730299953143924168545708663913273994694463908672332763671875E-319"
+    );
+    assert_float_result_bits_eq!(
+        0x800000000100,
+        f64,
+        "6.953355807847677105972805215521891690222119817145950754416205607980030131549636688806115726399441880065386399864028691275539539414652831584795668560082999889551357784961446896042113198284213107935110217162654939802416034676213829409720583759540476786936413816541621287843248433202369209916612249676005573022703244799714622116542188837770376022371172079559125853382801396219552418839469770514904192657627060319372847562301074140442660237844114174497210955449896389180395827191602886654488182452409583981389442783377001505462015745017848754574668342161759496661766020028752888783387074850773192997102997936619876226688096314989645766000479009083731736585750335262099860150896718774401964796827166283225641992040747894382698751809812609536720628966577351093292236328125E-310"
+    );
+    assert_float_result_bits_eq!(
+        0x10800,
+        f64,
+        "3.339068557571188581835713701280943911923401916998521771655656997328440314559615318168849149074662609099998113009465566426808170378434065722991659642619467706034884424989741080790766778456332168200464651593995817371782125010668346652995912233993254584461125868481633343674905074271064409763090708017856584019776878812425312008812326260363035474811532236853359905334625575404216060622858633280744301892470300555678734689978476870369853549413277156622170245846166991655321535529623870646888786637528995592800436177901746286272273374471701452991433047257863864601424252024791567368195056077320885329384322332391564645264143400798619665040608077549162173963649264049738362290606875883456826586710961041737908872035803481241600376705491726170293986797332763671875E-319"
+    );
+    assert_float_result_bits_eq!(
+        0x0,
+        f64,
+        "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999e-324"
+    );
+    assert_float_result_bits_eq!(
+        0x0,
+        f64,
+        "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125e-324"
+    );
+    assert_float_result_bits_eq!(
+        0x1,
+        f64,
+        "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125001e-324"
+    );
+    assert_float_result_bits_eq!(
+        0x1,
+        f64,
+        "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984374999e-324"
+    );
+    assert_float_result_bits_eq!(
+        0x2,
+        f64,
+        "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375e-324"
+    );
+    assert_float_result_bits_eq!(
+        0x2,
+        f64,
+        "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375001e-324"
+    );
+    assert_float_result_bits_eq!(
+        0x6c9a143590c14,
+        f64,
+        "94393431193180696942841837085033647913224148539854e-358"
+    );
+    assert_float_result_bits_eq!(
+        0x7802665fd9600,
+        f64,
+        "104308485241983990666713401708072175773165034278685682646111762292409330928739751702404658197872319129036519947435319418387839758990478549477777586673075945844895981012024387992135617064532141489278815239849108105951619997829153633535314849999674266169258928940692239684771590065027025835804863585454872499320500023126142553932654370362024104462255244034053203998964360882487378334860197725139151265590832887433736189468858614521708567646743455601905935595381852723723645799866672558576993978025033590728687206296379801363024094048327273913079612469982585674824156000783167963081616214710691759864332339239688734656548790656486646106983450809073750535624894296242072010195710276073042036425579852459556183541199012652571123898996574563824424330960027873516082763671875e-1075"
+    );
+}
+
+#[test]
+fn many_digits() {
+    // Check large numbers of digits to ensure we have cases where significant
+    // digits (above Decimal::MAX_DIGITS) occurs.
+    assert_float_result_bits_eq!(
+        0x7ffffe,
+        f32,
+        "1.175494140627517859246175898662808184331245864732796240031385942718174675986064769972472277004271745681762695312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-38"
+    );
+    assert_float_result_bits_eq!(
+        0x7ffffe,
+        f32,
+        "1.175494140627517859246175898662808184331245864732796240031385942718174675986064769972472277004271745681762695312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-38"
+    );
 }
diff --git a/library/core/tests/num/dec2flt/rawfp.rs b/library/core/tests/num/dec2flt/rawfp.rs
deleted file mode 100644 (file)
index 34a3720..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-use core::num::dec2flt::rawfp::RawFloat;
-use core::num::dec2flt::rawfp::{fp_to_float, next_float, prev_float, round_normal};
-use core::num::diy_float::Fp;
-
-fn integer_decode(f: f64) -> (u64, i16, i8) {
-    RawFloat::integer_decode(f)
-}
-
-#[test]
-fn fp_to_float_half_to_even() {
-    fn is_normalized(sig: u64) -> bool {
-        // intentionally written without {min,max}_sig() as a sanity check
-        sig >> 52 == 1 && sig >> 53 == 0
-    }
-
-    fn conv(sig: u64) -> u64 {
-        // The significands are perfectly in range, so the exponent should not matter
-        let (m1, e1, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: 0 }));
-        assert_eq!(e1, 0 + 64 - 53);
-        let (m2, e2, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: 55 }));
-        assert_eq!(e2, 55 + 64 - 53);
-        assert_eq!(m2, m1);
-        let (m3, e3, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: -78 }));
-        assert_eq!(e3, -78 + 64 - 53);
-        assert_eq!(m3, m2);
-        m3
-    }
-
-    let odd = 0x1F_EDCB_A012_345F;
-    let even = odd - 1;
-    assert!(is_normalized(odd));
-    assert!(is_normalized(even));
-    assert_eq!(conv(odd << 11), odd);
-    assert_eq!(conv(even << 11), even);
-    assert_eq!(conv(odd << 11 | 1 << 10), odd + 1);
-    assert_eq!(conv(even << 11 | 1 << 10), even);
-    assert_eq!(conv(even << 11 | 1 << 10 | 1), even + 1);
-    assert_eq!(conv(odd << 11 | 1 << 9), odd);
-    assert_eq!(conv(even << 11 | 1 << 9), even);
-    assert_eq!(conv(odd << 11 | 0x7FF), odd + 1);
-    assert_eq!(conv(even << 11 | 0x7FF), even + 1);
-    assert_eq!(conv(odd << 11 | 0x3FF), odd);
-    assert_eq!(conv(even << 11 | 0x3FF), even);
-}
-
-#[test]
-fn integers_to_f64() {
-    assert_eq!(fp_to_float::<f64>(Fp { f: 1, e: 0 }), 1.0);
-    assert_eq!(fp_to_float::<f64>(Fp { f: 42, e: 7 }), (42 << 7) as f64);
-    assert_eq!(fp_to_float::<f64>(Fp { f: 1 << 20, e: 30 }), (1u64 << 50) as f64);
-    assert_eq!(fp_to_float::<f64>(Fp { f: 4, e: -3 }), 0.5);
-}
-
-const SOME_FLOATS: [f64; 9] = [
-    0.1f64,
-    33.568,
-    42.1e-5,
-    777.0e9,
-    1.1111,
-    0.347997,
-    9843579834.35892,
-    12456.0e-150,
-    54389573.0e-150,
-];
-
-#[test]
-fn human_f64_roundtrip() {
-    for &x in &SOME_FLOATS {
-        let (f, e, _) = integer_decode(x);
-        let fp = Fp { f: f, e: e };
-        assert_eq!(fp_to_float::<f64>(fp), x);
-    }
-}
-
-#[test]
-fn rounding_overflow() {
-    let x = Fp { f: 0xFF_FF_FF_FF_FF_FF_FF_00u64, e: 42 };
-    let rounded = round_normal::<f64>(x);
-    let adjusted_k = x.e + 64 - 53;
-    assert_eq!(rounded.sig, 1 << 52);
-    assert_eq!(rounded.k, adjusted_k + 1);
-}
-
-#[test]
-fn prev_float_monotonic() {
-    let mut x = 1.0;
-    for _ in 0..100 {
-        let x1 = prev_float(x);
-        assert!(x1 < x);
-        assert!(x - x1 < 1e-15);
-        x = x1;
-    }
-}
-
-const MIN_SUBNORMAL: f64 = 5e-324;
-
-#[test]
-fn next_float_zero() {
-    let tiny = next_float(0.0);
-    assert_eq!(tiny, MIN_SUBNORMAL);
-    assert!(tiny != 0.0);
-}
-
-#[test]
-fn next_float_subnormal() {
-    let second = next_float(MIN_SUBNORMAL);
-    // For subnormals, MIN_SUBNORMAL is the ULP
-    assert!(second != MIN_SUBNORMAL);
-    assert!(second > 0.0);
-    assert_eq!(second - MIN_SUBNORMAL, MIN_SUBNORMAL);
-}
-
-#[test]
-fn next_float_inf() {
-    assert_eq!(next_float(f64::MAX), f64::INFINITY);
-    assert_eq!(next_float(f64::INFINITY), f64::INFINITY);
-}
-
-#[test]
-fn next_prev_identity() {
-    for &x in &SOME_FLOATS {
-        assert_eq!(prev_float(next_float(x)), x);
-        assert_eq!(prev_float(prev_float(next_float(next_float(x)))), x);
-        assert_eq!(next_float(prev_float(x)), x);
-        assert_eq!(next_float(next_float(prev_float(prev_float(x)))), x);
-    }
-}
-
-#[test]
-fn next_float_monotonic() {
-    let mut x = 0.49999999999999;
-    assert!(x < 0.5);
-    for _ in 0..200 {
-        let x1 = next_float(x);
-        assert!(x1 > x);
-        assert!(x1 - x < 1e-15, "next_float_monotonic: delta = {:?}", x1 - x);
-        x = x1;
-    }
-    assert!(x > 0.5);
-}
-
-#[test]
-fn test_f32_integer_decode() {
-    assert_eq!(3.14159265359f32.integer_decode(), (13176795, -22, 1));
-    assert_eq!((-8573.5918555f32).integer_decode(), (8779358, -10, -1));
-    assert_eq!(2f32.powf(100.0).integer_decode(), (8388608, 77, 1));
-    assert_eq!(0f32.integer_decode(), (0, -150, 1));
-    assert_eq!((-0f32).integer_decode(), (0, -150, -1));
-    assert_eq!(f32::INFINITY.integer_decode(), (8388608, 105, 1));
-    assert_eq!(f32::NEG_INFINITY.integer_decode(), (8388608, 105, -1));
-
-    // Ignore the "sign" (quiet / signalling flag) of NAN.
-    // It can vary between runtime operations and LLVM folding.
-    let (nan_m, nan_e, _nan_s) = f32::NAN.integer_decode();
-    assert_eq!((nan_m, nan_e), (12582912, 105));
-}
-
-#[test]
-fn test_f64_integer_decode() {
-    assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906, -51, 1));
-    assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931, -39, -1));
-    assert_eq!(2f64.powf(100.0).integer_decode(), (4503599627370496, 48, 1));
-    assert_eq!(0f64.integer_decode(), (0, -1075, 1));
-    assert_eq!((-0f64).integer_decode(), (0, -1075, -1));
-    assert_eq!(f64::INFINITY.integer_decode(), (4503599627370496, 972, 1));
-    assert_eq!(f64::NEG_INFINITY.integer_decode(), (4503599627370496, 972, -1));
-
-    // Ignore the "sign" (quiet / signalling flag) of NAN.
-    // It can vary between runtime operations and LLVM folding.
-    let (nan_m, nan_e, _nan_s) = f64::NAN.integer_decode();
-    assert_eq!((nan_m, nan_e), (6755399441055744, 972));
-}
index 960a7ca5ff5086cacc2089e8ea7a7d86513c52d6..4874e8ec09f8cfa4910f334158b431baa735f1c4 100644 (file)
@@ -2,10 +2,11 @@ use std::mem::MaybeUninit;
 use std::{fmt, str};
 
 use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded};
-use core::num::flt2dec::{round_up, Formatted, Part, Sign, MAX_SIG_DIGITS};
+use core::num::flt2dec::{round_up, Sign, MAX_SIG_DIGITS};
 use core::num::flt2dec::{
     to_exact_exp_str, to_exact_fixed_str, to_shortest_exp_str, to_shortest_str,
 };
+use core::num::fmt::{Formatted, Part};
 
 pub use test::Bencher;
 
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 u8;
 mod bignum;
 mod dec2flt;
 mod flt2dec;
+mod int_log;
 mod ops;
 mod wrapping;
 
index f4e5e7751b8e3f603129fc5f714c2b1b1478e903..612f083a5c17820e2ab5e0df1e494db8816cbc5c 100644 (file)
@@ -391,7 +391,6 @@ fn result_opt_conversions() {
 }
 
 #[test]
-#[cfg(not(bootstrap))] // Needs the V2 trait
 fn result_try_trait_v2_branch() {
     use core::num::NonZeroU32;
     use core::ops::{ControlFlow::*, Try};
index 6dbf7c11b4c4ec87b53c90da40a0d61b2031ef87..7394feab82f223c7161bdcd8ebe475eda730ebe9 100644 (file)
@@ -1,9 +1,9 @@
 //! Parsing of GCC-style Language-Specific Data Area (LSDA)
 //! For details see:
-//!  * <http://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html>
-//!  * <http://mentorembedded.github.io/cxx-abi/exceptions.pdf>
-//!  * <http://www.airs.com/blog/archives/460>
-//!  * <http://www.airs.com/blog/archives/464>
+//!  * <https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html>
+//!  * <https://itanium-cxx-abi.github.io/cxx-abi/exceptions.pdf>
+//!  * <https://www.airs.com/blog/archives/460>
+//!  * <https://www.airs.com/blog/archives/464>
 //!
 //! A reference implementation may be found in the GCC source tree
 //! (`<root>/libgcc/unwind-c.c` as of this writing).
index 14f49bbf483373f7f12aa7dfa89cfc8df2e787a2..9d6ede73e3db12e8ae137464e8d21f9bee1611fb 100644 (file)
@@ -5,8 +5,8 @@
 //! documents linked from it.
 //! These are also good reads:
 //!  * <https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html>
-//!  * <http://monoinfinito.wordpress.com/series/exception-handling-in-c/>
-//!  * <http://www.airs.com/blog/index.php?s=exception+frames>
+//!  * <https://monoinfinito.wordpress.com/series/exception-handling-in-c/>
+//!  * <https://www.airs.com/blog/index.php?s=exception+frames>
 //!
 //! ## A brief summary
 //!
@@ -94,7 +94,7 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
 // and TargetLowering::getExceptionSelectorRegister() for each architecture,
 // then mapped to DWARF register numbers via register definition tables
 // (typically <arch>RegisterInfo.td, search for "DwarfRegNum").
-// See also http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register.
+// See also https://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register.
 
 #[cfg(target_arch = "x86")]
 const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX
@@ -130,7 +130,7 @@ const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11
 cfg_if::cfg_if! {
     if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "netbsd")))] {
         // ARM EHABI personality routine.
-        // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
+        // https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
         //
         // iOS uses the default routine instead since it uses SjLj unwinding.
         #[lang = "eh_personality"]
index d32a3f1f8322c79aa190f62b30e7f4dd0b5c64ff..3622bc8294b0829bc10790e11e102987d5246bcb 100644 (file)
@@ -23,7 +23,6 @@
 #![feature(unwind_attributes)]
 #![feature(abi_thiscall)]
 #![feature(rustc_attrs)]
-#![feature(raw)]
 #![panic_runtime]
 #![feature(panic_runtime)]
 // `real_imp` is unused with Miri, so silence warnings.
index 58028d40576470685145943ee1982d6bbdc7eb7b..754dbb77af6ca42d71ce2ad89b607c7cc04c5760 100644 (file)
@@ -42,7 +42,7 @@
 //!   of the `try` intrinsic.
 //!
 //! [win64]: https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64
-//! [llvm]: http://llvm.org/docs/ExceptionHandling.html#background-on-windows-exceptions
+//! [llvm]: https://llvm.org/docs/ExceptionHandling.html#background-on-windows-exceptions
 
 #![allow(nonstandard_style)]
 
@@ -100,7 +100,7 @@ struct Exception {
 // In any case, these structures are all constructed in a similar manner, and
 // it's just somewhat verbose for us.
 //
-// [1]: http://www.geoffchappell.com/studies/msvc/language/predefined/
+// [1]: https://www.geoffchappell.com/studies/msvc/language/predefined/
 
 #[cfg(target_arch = "x86")]
 #[macro_use]
index 717201aef102bf60a78b61837adca7d8961f7e25..d82669d3e2336622942d127aaf5ca0c2ad501e9e 100644 (file)
@@ -5,35 +5,6 @@ use std::mem;
 use std::ops::{Deref, DerefMut};
 use std::slice;
 
-#[repr(C)]
-struct Slice<'a, T> {
-    data: &'a [T; 0],
-    len: usize,
-}
-
-unsafe impl<'a, T: Sync> Sync for Slice<'a, T> {}
-unsafe impl<'a, T: Sync> Send for Slice<'a, T> {}
-
-impl<T> Copy for Slice<'a, T> {}
-impl<T> Clone for Slice<'a, T> {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
-
-impl<T> From<&'a [T]> for Slice<'a, T> {
-    fn from(xs: &'a [T]) -> Self {
-        Slice { data: unsafe { &*(xs.as_ptr() as *const [T; 0]) }, len: xs.len() }
-    }
-}
-
-impl<T> Deref for Slice<'a, T> {
-    type Target = [T];
-    fn deref(&self) -> &[T] {
-        unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) }
-    }
-}
-
 #[repr(C)]
 pub struct Buffer<T: Copy> {
     data: *mut T,
index a2953b68564a89bcddb92552e527f0241fa9f18b..b968d44fe488d4d573b021d54f7c2bb57dac428c 100644 (file)
@@ -55,6 +55,7 @@ macro_rules! with_api {
             FreeFunctions {
                 fn drop($self: $S::FreeFunctions);
                 fn track_env_var(var: &str, value: Option<&str>);
+                fn track_path(path: &str);
             },
             TokenStream {
                 fn drop($self: $S::TokenStream);
index 588e6ded0f48068f937b697b1d206ab3f5046113..42432563faf33bb9b4df0e66cee8ad56b990ec1b 100644 (file)
@@ -246,7 +246,7 @@ impl<S> DecodeMut<'_, '_, S> for String {
     }
 }
 
-/// Simplied version of panic payloads, ignoring
+/// Simplified version of panic payloads, ignoring
 /// types other than `&'static str` and `String`.
 pub enum PanicMessage {
     StaticStr(&'static str),
index 26fbf50e2dfdf903f940495dc28a30d3adddc774..53fd58a29d877b72a81a8861efd23d81753d3e47 100644 (file)
@@ -31,7 +31,6 @@
 #![feature(restricted_std)]
 #![feature(rustc_attrs)]
 #![feature(min_specialization)]
-#![feature(bound_cloned)]
 #![recursion_limit = "256"]
 
 #[unstable(feature = "proc_macro_internals", issue = "27812")]
@@ -85,14 +84,13 @@ impl !Sync for TokenStream {}
 
 /// Error returned from `TokenStream::from_str`.
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
+#[non_exhaustive]
 #[derive(Debug)]
-pub struct LexError {
-    _inner: (),
-}
+pub struct LexError;
 
 impl LexError {
     fn new() -> Self {
-        LexError { _inner: () }
+        LexError
     }
 }
 
@@ -708,7 +706,7 @@ impl Group {
     /// pub fn span_open(&self) -> Span {
     ///                 ^
     /// ```
-    #[unstable(feature = "proc_macro_span", issue = "54725")]
+    #[stable(feature = "proc_macro_group_span", since = "1.55.0")]
     pub fn span_open(&self) -> Span {
         Span(self.0.span_open())
     }
@@ -719,7 +717,7 @@ impl Group {
     /// pub fn span_close(&self) -> Span {
     ///                        ^
     /// ```
-    #[unstable(feature = "proc_macro_span", issue = "54725")]
+    #[stable(feature = "proc_macro_group_span", since = "1.55.0")]
     pub fn span_close(&self) -> Span {
         Span(self.0.span_close())
     }
@@ -766,7 +764,7 @@ impl fmt::Debug for Group {
     }
 }
 
-/// An `Punct` is an single punctuation character like `+`, `-` or `#`.
+/// A `Punct` is a single punctuation character such as `+`, `-` or `#`.
 ///
 /// Multi-character operators like `+=` are represented as two instances of `Punct` with different
 /// forms of `Spacing` returned.
@@ -779,16 +777,19 @@ impl !Send for Punct {}
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 impl !Sync for Punct {}
 
-/// Whether an `Punct` is followed immediately by another `Punct` or
-/// followed by another token or whitespace.
+/// Describes whether a `Punct` is followed immediately by another `Punct` ([`Spacing::Joint`]) or
+/// by a different token or whitespace ([`Spacing::Alone`]).
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 pub enum Spacing {
-    /// e.g., `+` is `Alone` in `+ =`, `+ident` or `+()`.
+    /// A `Punct` is not immediately followed by another `Punct`.
+    /// E.g. `+` is `Alone` in `+ =`, `+ident` and `+()`.
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
     Alone,
-    /// e.g., `+` is `Joint` in `+=` or `'#`.
-    /// Additionally, single quote `'` can join with identifiers to form lifetimes `'ident`.
+    /// A `Punct` is immediately followed by another `Punct`.
+    /// E.g. `+` is `Joint` in `+=` and `++`.
+    ///
+    /// Additionally, single quote `'` can join with identifiers to form lifetimes: `'ident`.
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
     Joint,
 }
@@ -1233,3 +1234,17 @@ pub mod tracked_env {
         value
     }
 }
+
+/// Tracked access to additional files.
+#[unstable(feature = "track_path", issue = "73921")]
+pub mod tracked_path {
+
+    /// Track a file explicitly.
+    ///
+    /// Commonly used for tracking asset preprocessing.
+    #[unstable(feature = "track_path", issue = "73921")]
+    pub fn path<P: AsRef<str>>(path: P) {
+        let path: &str = path.as_ref();
+        crate::bridge::client::FreeFunctions::track_path(path);
+    }
+}
index 7b7ca8029b49dafbebc0a0062c0ec8ede0bbb2a8..b7ab4f19f0ad9ea8d828afa3a0f5f52ac4d7e0df 100644 (file)
@@ -14,4 +14,4 @@ core = { path = "../core" }
 compiler_builtins = { version = "0.1.0", features = ['rustc-dep-of-std'] }
 
 [build-dependencies]
-cc = "1.0.68"
+cc = "1.0.69"
index 0aae4674b29423c763025113ecf236b8591f4dd4..f8884523cf446a6422b2d3985285667f6958e62e 100644 (file)
@@ -399,12 +399,11 @@ impl fmt::Display for Backtrace {
         let mut f = backtrace_rs::BacktraceFmt::new(fmt, style, &mut print_path);
         f.add_context()?;
         for frame in frames {
-            let mut f = f.frame();
             if frame.symbols.is_empty() {
-                f.print_raw(frame.frame.ip(), None, None, None)?;
+                f.frame().print_raw(frame.frame.ip(), None, None, None)?;
             } else {
                 for symbol in frame.symbols.iter() {
-                    f.print_raw_with_column(
+                    f.frame().print_raw_with_column(
                         frame.frame.ip(),
                         symbol.name.as_ref().map(|b| backtrace_rs::SymbolName::new(b)),
                         symbol.filename.as_ref().map(|b| match b {
index a1f52a9c2e88019534c64fe6355dfb791d1ad9c0..4a5efab9055b3c33ac62424efbbc178d3f7daaa2 100644 (file)
@@ -454,7 +454,6 @@ impl<K, V, S> HashMap<K, V, S> {
     /// 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 @@ where
     /// 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>
@@ -936,6 +934,7 @@ where
     /// Retains only the elements specified by the predicate.
     ///
     /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`.
+    /// The elements are visited in unsorted (and unspecified) order.
     ///
     /// # Examples
     ///
@@ -1831,6 +1830,7 @@ impl<K, V, S> Debug for RawEntryBuilder<'_, K, V, S> {
 ///
 /// [`entry`]: HashMap::entry
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "HashMapEntry")]
 pub enum Entry<'a, K: 'a, V: 'a> {
     /// An occupied entry.
     #[stable(feature = "rust1", since = "1.0.0")]
index 5220c8ad70977657a13778eb4a16c174af444417..1a2a8afac8bed6568e82960fcd21da0df86cd984 100644 (file)
@@ -202,7 +202,6 @@ impl<T, S> HashSet<T, S> {
     /// 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 @@ where
     /// 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
@@ -914,6 +912,7 @@ where
     /// Retains only the elements specified by the predicate.
     ///
     /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
+    /// The elements are visited in unsorted (and unspecified) order.
     ///
     /// # Examples
     ///
index 4403280efc11b9f6f0d93f96800c8ee8acd4cc70..64f88c1aba68e602e336408d95d1a5aed18ac7bb 100644 (file)
@@ -305,7 +305,7 @@ impl Error for VarError {
 ///
 /// Discussion of this unsafety on Unix may be found in:
 ///
-///  - [Austin Group Bugzilla](http://austingroupbugs.net/view.php?id=188)
+///  - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188)
 ///  - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
 ///
 /// # Panics
@@ -344,7 +344,7 @@ fn _set_var(key: &OsStr, value: &OsStr) {
 ///
 /// Discussion of this unsafety on Unix may be found in:
 ///
-///  - [Austin Group Bugzilla](http://austingroupbugs.net/view.php?id=188)
+///  - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188)
 ///  - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
 ///
 /// # Panics
index 14c2f961d32619a4422f8ea7af162cb84cf1ec61..ec9f012295000902e044f21c4ef7900d52adf4e0 100644 (file)
@@ -597,6 +597,9 @@ impl Error for char::ParseCharError {
 #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
 impl Error for alloc::collections::TryReserveError {}
 
+#[unstable(feature = "duration_checked_float", issue = "83400")]
+impl Error for core::time::FromSecsError {}
+
 // Copied from `any.rs`.
 impl dyn Error + 'static {
     /// Returns `true` if the boxed type is the same as `T`
index c16d27fa1f58c15de7834b4637cf3a6e4cbadfe8..e0cc6ad1d4231731b75470337b2c02260944d980 100644 (file)
@@ -324,18 +324,20 @@ impl 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")]
@@ -876,4 +878,40 @@ impl f32 {
     pub fn atanh(self) -> f32 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
+
+    /// Linear interpolation between `start` and `end`.
+    ///
+    /// This enables linear interpolation between `start` and `end`, where start is represented by
+    /// `self == 0.0` and `end` is represented by `self == 1.0`. This is the basis of all
+    /// "transition", "easing", or "step" functions; if you change `self` from 0.0 to 1.0
+    /// at a given rate, the result will change from `start` to `end` at a similar rate.
+    ///
+    /// Values below 0.0 or above 1.0 are allowed, allowing you to extrapolate values outside the
+    /// range from `start` to `end`. This also is useful for transition functions which might
+    /// move slightly past the end or start for a desired effect. Mathematically, the values
+    /// returned are equivalent to `start + self * (end - start)`, although we make a few specific
+    /// guarantees that are useful specifically to linear interpolation.
+    ///
+    /// These guarantees are:
+    ///
+    /// * If `start` and `end` are [finite], the value at 0.0 is always `start` and the
+    ///   value at 1.0 is always `end`. (exactness)
+    /// * If `start` and `end` are [finite], the values will always move in the direction from
+    ///   `start` to `end` (monotonicity)
+    /// * If `self` is [finite] and `start == end`, the value at any point will always be
+    ///   `start == end`. (consistency)
+    ///
+    /// [finite]: #method.is_finite
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "float_interpolation", issue = "86269")]
+    pub fn lerp(self, start: f32, end: f32) -> f32 {
+        // consistent
+        if start == end {
+            start
+
+        // exact/monotonic
+        } else {
+            self.mul_add(end, (-self).mul_add(start, start))
+        }
+    }
 }
index 0d4b865f3392a66304e13e47e9fa652099428534..fe66a73afd63ab7ef6d55f5dfe708640e22cde46 100644 (file)
@@ -757,3 +757,66 @@ fn test_total_cmp() {
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::INFINITY));
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
 }
+
+#[test]
+fn test_lerp_exact() {
+    // simple values
+    assert_eq!(f32::lerp(0.0, 2.0, 4.0), 2.0);
+    assert_eq!(f32::lerp(1.0, 2.0, 4.0), 4.0);
+
+    // boundary values
+    assert_eq!(f32::lerp(0.0, f32::MIN, f32::MAX), f32::MIN);
+    assert_eq!(f32::lerp(1.0, f32::MIN, f32::MAX), f32::MAX);
+}
+
+#[test]
+fn test_lerp_consistent() {
+    assert_eq!(f32::lerp(f32::MAX, f32::MIN, f32::MIN), f32::MIN);
+    assert_eq!(f32::lerp(f32::MIN, f32::MAX, f32::MAX), f32::MAX);
+
+    // as long as t is finite, a/b can be infinite
+    assert_eq!(f32::lerp(f32::MAX, f32::NEG_INFINITY, f32::NEG_INFINITY), f32::NEG_INFINITY);
+    assert_eq!(f32::lerp(f32::MIN, f32::INFINITY, f32::INFINITY), f32::INFINITY);
+}
+
+#[test]
+fn test_lerp_nan_infinite() {
+    // non-finite t is not NaN if a/b different
+    assert!(!f32::lerp(f32::INFINITY, f32::MIN, f32::MAX).is_nan());
+    assert!(!f32::lerp(f32::NEG_INFINITY, f32::MIN, f32::MAX).is_nan());
+}
+
+#[test]
+fn test_lerp_values() {
+    // just a few basic values
+    assert_eq!(f32::lerp(0.25, 1.0, 2.0), 1.25);
+    assert_eq!(f32::lerp(0.50, 1.0, 2.0), 1.50);
+    assert_eq!(f32::lerp(0.75, 1.0, 2.0), 1.75);
+}
+
+#[test]
+fn test_lerp_monotonic() {
+    // near 0
+    let below_zero = f32::lerp(-f32::EPSILON, f32::MIN, f32::MAX);
+    let zero = f32::lerp(0.0, f32::MIN, f32::MAX);
+    let above_zero = f32::lerp(f32::EPSILON, f32::MIN, f32::MAX);
+    assert!(below_zero <= zero);
+    assert!(zero <= above_zero);
+    assert!(below_zero <= above_zero);
+
+    // near 0.5
+    let below_half = f32::lerp(0.5 - f32::EPSILON, f32::MIN, f32::MAX);
+    let half = f32::lerp(0.5, f32::MIN, f32::MAX);
+    let above_half = f32::lerp(0.5 + f32::EPSILON, f32::MIN, f32::MAX);
+    assert!(below_half <= half);
+    assert!(half <= above_half);
+    assert!(below_half <= above_half);
+
+    // near 1
+    let below_one = f32::lerp(1.0 - f32::EPSILON, f32::MIN, f32::MAX);
+    let one = f32::lerp(1.0, f32::MIN, f32::MAX);
+    let above_one = f32::lerp(1.0 + f32::EPSILON, f32::MIN, f32::MAX);
+    assert!(below_one <= one);
+    assert!(one <= above_one);
+    assert!(below_one <= above_one);
+}
index 4c95df5ffe04a95be8a56d8fa261379d81da3e2d..7ed65b7dafec5ccb2c8d7214bf27c37e6c87c916 100644 (file)
@@ -324,18 +324,20 @@ impl 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")]
@@ -879,6 +881,42 @@ impl f64 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
 
+    /// Linear interpolation between `start` and `end`.
+    ///
+    /// This enables linear interpolation between `start` and `end`, where start is represented by
+    /// `self == 0.0` and `end` is represented by `self == 1.0`. This is the basis of all
+    /// "transition", "easing", or "step" functions; if you change `self` from 0.0 to 1.0
+    /// at a given rate, the result will change from `start` to `end` at a similar rate.
+    ///
+    /// Values below 0.0 or above 1.0 are allowed, allowing you to extrapolate values outside the
+    /// range from `start` to `end`. This also is useful for transition functions which might
+    /// move slightly past the end or start for a desired effect. Mathematically, the values
+    /// returned are equivalent to `start + self * (end - start)`, although we make a few specific
+    /// guarantees that are useful specifically to linear interpolation.
+    ///
+    /// These guarantees are:
+    ///
+    /// * If `start` and `end` are [finite], the value at 0.0 is always `start` and the
+    ///   value at 1.0 is always `end`. (exactness)
+    /// * If `start` and `end` are [finite], the values will always move in the direction from
+    ///   `start` to `end` (monotonicity)
+    /// * If `self` is [finite] and `start == end`, the value at any point will always be
+    ///   `start == end`. (consistency)
+    ///
+    /// [finite]: #method.is_finite
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "float_interpolation", issue = "86269")]
+    pub fn lerp(self, start: f64, end: f64) -> f64 {
+        // consistent
+        if start == end {
+            start
+
+        // exact/monotonic
+        } else {
+            self.mul_add(end, (-self).mul_add(start, start))
+        }
+    }
+
     // Solaris/Illumos requires a wrapper around log, log2, and log10 functions
     // because of their non-standard behavior (e.g., log(-n) returns -Inf instead
     // of expected NaN).
index 5c163cfe90e0b2eff9030bc80dd0cfeb4c71532c..04cb0109261a48068d54261a7c3cb381ed458220 100644 (file)
@@ -753,3 +753,58 @@ fn test_total_cmp() {
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::INFINITY));
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
 }
+
+#[test]
+fn test_lerp_exact() {
+    // simple values
+    assert_eq!(f64::lerp(0.0, 2.0, 4.0), 2.0);
+    assert_eq!(f64::lerp(1.0, 2.0, 4.0), 4.0);
+
+    // boundary values
+    assert_eq!(f64::lerp(0.0, f64::MIN, f64::MAX), f64::MIN);
+    assert_eq!(f64::lerp(1.0, f64::MIN, f64::MAX), f64::MAX);
+}
+
+#[test]
+fn test_lerp_consistent() {
+    assert_eq!(f64::lerp(f64::MAX, f64::MIN, f64::MIN), f64::MIN);
+    assert_eq!(f64::lerp(f64::MIN, f64::MAX, f64::MAX), f64::MAX);
+
+    // as long as t is finite, a/b can be infinite
+    assert_eq!(f64::lerp(f64::MAX, f64::NEG_INFINITY, f64::NEG_INFINITY), f64::NEG_INFINITY);
+    assert_eq!(f64::lerp(f64::MIN, f64::INFINITY, f64::INFINITY), f64::INFINITY);
+}
+
+#[test]
+fn test_lerp_nan_infinite() {
+    // non-finite t is not NaN if a/b different
+    assert!(!f64::lerp(f64::INFINITY, f64::MIN, f64::MAX).is_nan());
+    assert!(!f64::lerp(f64::NEG_INFINITY, f64::MIN, f64::MAX).is_nan());
+}
+
+#[test]
+fn test_lerp_values() {
+    // just a few basic values
+    assert_eq!(f64::lerp(0.25, 1.0, 2.0), 1.25);
+    assert_eq!(f64::lerp(0.50, 1.0, 2.0), 1.50);
+    assert_eq!(f64::lerp(0.75, 1.0, 2.0), 1.75);
+}
+
+#[test]
+fn test_lerp_monotonic() {
+    // near 0
+    let below_zero = f64::lerp(-f64::EPSILON, f64::MIN, f64::MAX);
+    let zero = f64::lerp(0.0, f64::MIN, f64::MAX);
+    let above_zero = f64::lerp(f64::EPSILON, f64::MIN, f64::MAX);
+    assert!(below_zero <= zero);
+    assert!(zero <= above_zero);
+    assert!(below_zero <= above_zero);
+
+    // near 1
+    let below_one = f64::lerp(1.0 - f64::EPSILON, f64::MIN, f64::MAX);
+    let one = f64::lerp(1.0, f64::MIN, f64::MAX);
+    let above_one = f64::lerp(1.0 + f64::EPSILON, f64::MIN, f64::MAX);
+    assert!(below_one <= one);
+    assert!(one <= above_one);
+    assert!(below_one <= above_one);
+}
index 0184495eecf09ffdf59ca11148b34f41f974acd1..0b7dc256db8f4913886a5b31a4f106f0ab4cf9a3 100644 (file)
 //! method is an [`OsString`] which can be round-tripped to a Windows
 //! string losslessly.
 //!
-//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
-//! [Unicode code point]: http://www.unicode.org/glossary/#code_point
+//! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
+//! [Unicode code point]: https://www.unicode.org/glossary/#code_point
 //! [`env::set_var()`]: crate::env::set_var
 //! [`env::var_os()`]: crate::env::var_os
 //! [unix.OsStringExt]: crate::os::unix::ffi::OsStringExt
index ca391ffb3d56c489bd6735c3ccc8dfb5c6b0bacd..2a85f375ae2790250a74d9d72e823df4c04caefc 100644 (file)
@@ -694,7 +694,6 @@ impl OsStr {
     /// 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 a1636e2f604cf772a547048a2f3ac7903de09031..bbe1ab40537f220b8c821a8211a6edce9b632a87 100644 (file)
@@ -88,6 +88,7 @@ use crate::time::SystemTime;
 /// [`BufReader<R>`]: io::BufReader
 /// [`sync_all`]: File::sync_all
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "File")]
 pub struct File {
     inner: fs_imp::File,
 }
@@ -183,12 +184,14 @@ pub struct Permissions(fs_imp::FilePermissions);
 /// It is returned by [`Metadata::file_type`] method.
 #[stable(feature = "file_type", since = "1.1.0")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[cfg_attr(not(test), rustc_diagnostic_item = "FileType")]
 pub struct FileType(fs_imp::FileType);
 
 /// A builder used to create directories in various manners.
 ///
 /// This builder also supports platform-specific options.
 #[stable(feature = "dir_builder", since = "1.6.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "DirBuilder")]
 #[derive(Debug)]
 pub struct DirBuilder {
     inner: fs_imp::DirBuilder,
@@ -880,8 +883,7 @@ impl OpenOptions {
     /// This function will return an error under a number of different
     /// circumstances. Some of these error conditions are listed here, together
     /// with their [`io::ErrorKind`]. The mapping to [`io::ErrorKind`]s is not
-    /// part of the compatibility contract of the function, especially the
-    /// [`Other`] kind might change to more specific kinds in the future.
+    /// part of the compatibility contract of the function.
     ///
     /// * [`NotFound`]: The specified file does not exist and neither `create`
     ///   or `create_new` is set.
@@ -895,9 +897,11 @@ impl OpenOptions {
     ///   exists.
     /// * [`InvalidInput`]: Invalid combinations of open options (truncate
     ///   without write access, no access mode set, etc.).
-    /// * [`Other`]: One of the directory components of the specified file path
+    ///
+    /// The following errors don't match any existing [`io::ErrorKind`] at the moment:
+    /// * One of the directory components of the specified file path
     ///   was not, in fact, a directory.
-    /// * [`Other`]: Filesystem-level errors: full disk, write permission
+    /// * Filesystem-level errors: full disk, write permission
     ///   requested on a read-only file system, exceeded disk quota, too many
     ///   open files, too long filename, too many symbolic links in the
     ///   specified path (Unix-like systems only), etc.
@@ -913,7 +917,6 @@ impl OpenOptions {
     /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists
     /// [`InvalidInput`]: io::ErrorKind::InvalidInput
     /// [`NotFound`]: io::ErrorKind::NotFound
-    /// [`Other`]: io::ErrorKind::Other
     /// [`PermissionDenied`]: io::ErrorKind::PermissionDenied
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
@@ -1007,6 +1010,32 @@ impl Metadata {
         self.file_type().is_file()
     }
 
+    /// Returns `true` if this metadata is for a symbolic link.
+    ///
+    /// # Examples
+    ///
+    #[cfg_attr(unix, doc = "```no_run")]
+    #[cfg_attr(not(unix), doc = "```ignore")]
+    /// #![feature(is_symlink)]
+    /// use std::fs;
+    /// use std::path::Path;
+    /// use std::os::unix::fs::symlink;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let link_path = Path::new("link");
+    ///     symlink("/origin_does_not_exists/", link_path)?;
+    ///
+    ///     let metadata = fs::symlink_metadata(link_path)?;
+    ///
+    ///     assert!(metadata.is_symlink());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "is_symlink", issue = "85748")]
+    pub fn is_symlink(&self) -> bool {
+        self.file_type().is_symlink()
+    }
+
     /// Returns the size of the file, in bytes, this metadata is for.
     ///
     /// # Examples
@@ -1525,7 +1554,6 @@ impl AsInner<fs_imp::DirEntry> for 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())
@@ -1711,8 +1739,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
@@ -1960,7 +1991,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())
@@ -1998,7 +2028,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())
@@ -2190,7 +2219,7 @@ impl DirBuilder {
             Some(p) => self.create_dir_all(p)?,
             None => {
                 return Err(io::Error::new_const(
-                    io::ErrorKind::Other,
+                    io::ErrorKind::Uncategorized,
                     &"failed to create whole tree",
                 ));
             }
index ce8d3a56f7af4bff6e395c39a4075b49d9562747..080b4b5d87f266fb77b0027465f93854012a57c9 100644 (file)
@@ -19,6 +19,10 @@ use crate::os::unix::fs::symlink as symlink_junction;
 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";
@@ -1329,7 +1344,8 @@ fn metadata_access_times() {
         match (a.created(), b.created()) {
             (Ok(t1), Ok(t2)) => assert!(t1 <= t2),
             (Err(e1), Err(e2))
-                if e1.kind() == ErrorKind::Other && e2.kind() == ErrorKind::Other
+                if e1.kind() == ErrorKind::Uncategorized
+                    && e2.kind() == ErrorKind::Uncategorized
                     || e1.kind() == ErrorKind::Unsupported
                         && e2.kind() == ErrorKind::Unsupported => {}
             (a, b) => {
@@ -1346,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 d8021d3e99a70b8c62625dd616e24f8ad752bfd5..32d194d9616523c6ae46a426acf602139ade7fbe 100644 (file)
@@ -438,7 +438,13 @@ impl<R: Seek> Seek for BufReader<R> {
 }
 
 impl<T> SizeHint for BufReader<T> {
+    #[inline]
     fn lower_bound(&self) -> usize {
-        self.buffer().len()
+        SizeHint::lower_bound(self.get_ref()) + self.buffer().len()
+    }
+
+    #[inline]
+    fn upper_bound(&self) -> Option<usize> {
+        SizeHint::upper_bound(self.get_ref()).and_then(|up| self.buffer().len().checked_add(up))
     }
 }
index ef2769d431fbbbd9bba5246059d3d3918cc7303d..c98244132befd62e3be3eb547b7feb841a3c1b18 100644 (file)
@@ -68,7 +68,7 @@ use crate::ptr;
 /// [`flush`]: BufWriter::flush
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct BufWriter<W: Write> {
-    inner: Option<W>,
+    inner: W,
     // The buffer. Avoid using this like a normal `Vec` in common code paths.
     // That is, don't use `buf.push`, `buf.extend_from_slice`, or any other
     // methods that require bounds checking or the like. This makes an enormous
@@ -112,7 +112,7 @@ impl<W: Write> BufWriter<W> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(capacity: usize, inner: W) -> BufWriter<W> {
-        BufWriter { inner: Some(inner), buf: Vec::with_capacity(capacity), panicked: false }
+        BufWriter { inner, buf: Vec::with_capacity(capacity), panicked: false }
     }
 
     /// Send data in our local buffer into the inner writer, looping as
@@ -161,10 +161,9 @@ impl<W: Write> BufWriter<W> {
         }
 
         let mut guard = BufGuard::new(&mut self.buf);
-        let inner = self.inner.as_mut().unwrap();
         while !guard.done() {
             self.panicked = true;
-            let r = inner.write(guard.remaining());
+            let r = self.inner.write(guard.remaining());
             self.panicked = false;
 
             match r {
@@ -212,7 +211,7 @@ impl<W: Write> BufWriter<W> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_ref(&self) -> &W {
-        self.inner.as_ref().unwrap()
+        &self.inner
     }
 
     /// Gets a mutable reference to the underlying writer.
@@ -232,7 +231,7 @@ impl<W: Write> BufWriter<W> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut W {
-        self.inner.as_mut().unwrap()
+        &mut self.inner
     }
 
     /// Returns a reference to the internally buffered data.
@@ -308,7 +307,7 @@ impl<W: Write> BufWriter<W> {
     pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
         match self.flush_buf() {
             Err(e) => Err(IntoInnerError::new(self, e)),
-            Ok(()) => Ok(self.inner.take().unwrap()),
+            Ok(()) => Ok(self.into_raw_parts().0),
         }
     }
 
@@ -339,7 +338,12 @@ impl<W: Write> BufWriter<W> {
     pub fn into_raw_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
         let buf = mem::take(&mut self.buf);
         let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
-        (self.inner.take().unwrap(), buf)
+
+        // SAFETY: forget(self) prevents double dropping inner
+        let inner = unsafe { ptr::read(&mut self.inner) };
+        mem::forget(self);
+
+        (inner, buf)
     }
 
     // Ensure this function does not get inlined into `write`, so that it
@@ -643,7 +647,7 @@ where
 {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt.debug_struct("BufWriter")
-            .field("writer", &self.inner.as_ref().unwrap())
+            .field("writer", &self.inner)
             .field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
             .finish()
     }
@@ -663,7 +667,7 @@ impl<W: Write + Seek> Seek for BufWriter<W> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<W: Write> Drop for BufWriter<W> {
     fn drop(&mut self) {
-        if self.inner.is_some() && !self.panicked {
+        if !self.panicked {
             // dtors should not panic, so we ignore a failed flush
             let _r = self.flush_buf();
         }
index 65497817f8160d55c688275fbd19763cbbe1dd02..38076ab3a2b7bc04255d7848e0c3e71af9c23c2b 100644 (file)
@@ -133,7 +133,6 @@ impl<W> IntoInnerError<W> {
     ///
     /// # Example
     /// ```
-    /// #![feature(io_into_inner_error_parts)]
     /// use std::io::{BufWriter, ErrorKind, Write};
     ///
     /// let mut not_enough_space = [0u8; 10];
@@ -143,7 +142,7 @@ impl<W> IntoInnerError<W> {
     /// let err = into_inner_err.into_error();
     /// assert_eq!(err.kind(), ErrorKind::WriteZero);
     /// ```
-    #[unstable(feature = "io_into_inner_error_parts", issue = "79704")]
+    #[stable(feature = "io_into_inner_error_parts", since = "1.55.0")]
     pub fn into_error(self) -> Error {
         self.1
     }
@@ -156,7 +155,6 @@ impl<W> IntoInnerError<W> {
     ///
     /// # Example
     /// ```
-    /// #![feature(io_into_inner_error_parts)]
     /// use std::io::{BufWriter, ErrorKind, Write};
     ///
     /// let mut not_enough_space = [0u8; 10];
@@ -167,7 +165,7 @@ impl<W> IntoInnerError<W> {
     /// assert_eq!(err.kind(), ErrorKind::WriteZero);
     /// assert_eq!(recovered_writer.buffer(), b"t be actually written");
     /// ```
-    #[unstable(feature = "io_into_inner_error_parts", issue = "79704")]
+    #[stable(feature = "io_into_inner_error_parts", since = "1.55.0")]
     pub fn into_parts(self) -> (Error, W) {
         (self.1, self.0)
     }
index 9527254c947938644417ac5ccaa0c8041301ae56..ae0cea985d77c9b8314044d7eaad75e2e07581a1 100644 (file)
@@ -205,6 +205,62 @@ impl<T> Cursor<T> {
     }
 }
 
+impl<T> Cursor<T>
+where
+    T: AsRef<[u8]>,
+{
+    /// Returns the remaining slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cursor_remaining)]
+    /// use std::io::Cursor;
+    ///
+    /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
+    ///
+    /// assert_eq!(buff.remaining_slice(), &[1, 2, 3, 4, 5]);
+    ///
+    /// buff.set_position(2);
+    /// assert_eq!(buff.remaining_slice(), &[3, 4, 5]);
+    ///
+    /// buff.set_position(4);
+    /// assert_eq!(buff.remaining_slice(), &[5]);
+    ///
+    /// buff.set_position(6);
+    /// assert_eq!(buff.remaining_slice(), &[]);
+    /// ```
+    #[unstable(feature = "cursor_remaining", issue = "86369")]
+    pub fn remaining_slice(&self) -> &[u8] {
+        let len = self.pos.min(self.inner.as_ref().len() as u64);
+        &self.inner.as_ref()[(len as usize)..]
+    }
+
+    /// Returns `true` if the remaining slice is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cursor_remaining)]
+    /// use std::io::Cursor;
+    ///
+    /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
+    ///
+    /// buff.set_position(2);
+    /// assert!(!buff.is_empty());
+    ///
+    /// buff.set_position(5);
+    /// assert!(buff.is_empty());
+    ///
+    /// buff.set_position(10);
+    /// assert!(buff.is_empty());
+    /// ```
+    #[unstable(feature = "cursor_remaining", issue = "86369")]
+    pub fn is_empty(&self) -> bool {
+        self.pos >= self.inner.as_ref().len() as u64
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Clone for Cursor<T>
 where
@@ -268,7 +324,7 @@ where
     T: AsRef<[u8]>,
 {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        let n = Read::read(&mut self.fill_buf()?, buf)?;
+        let n = Read::read(&mut self.remaining_slice(), buf)?;
         self.pos += n as u64;
         Ok(n)
     }
@@ -291,7 +347,7 @@ where
 
     fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
         let n = buf.len();
-        Read::read_exact(&mut self.fill_buf()?, buf)?;
+        Read::read_exact(&mut self.remaining_slice(), buf)?;
         self.pos += n as u64;
         Ok(())
     }
@@ -308,8 +364,7 @@ where
     T: AsRef<[u8]>,
 {
     fn fill_buf(&mut self) -> io::Result<&[u8]> {
-        let amt = cmp::min(self.pos, self.inner.as_ref().len() as u64);
-        Ok(&self.inner.as_ref()[(amt as usize)..])
+        Ok(self.remaining_slice())
     }
     fn consume(&mut self, amt: usize) {
         self.pos += amt as u64;
index 56e6f08268ca37b380b39d52c84ebba0bc1008a5..829ef3d98bbc92b5dd690476dbcb57c7a86f8851 100644 (file)
@@ -105,6 +105,12 @@ pub enum ErrorKind {
     /// The connection was reset by the remote server.
     #[stable(feature = "rust1", since = "1.0.0")]
     ConnectionReset,
+    /// The remote host is not reachable.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    HostUnreachable,
+    /// The network containing the remote host is not reachable.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    NetworkUnreachable,
     /// The connection was aborted (terminated) by the remote server.
     #[stable(feature = "rust1", since = "1.0.0")]
     ConnectionAborted,
@@ -119,6 +125,9 @@ pub enum ErrorKind {
     /// local.
     #[stable(feature = "rust1", since = "1.0.0")]
     AddrNotAvailable,
+    /// The system's networking is down.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    NetworkDown,
     /// The operation failed because a pipe was closed.
     #[stable(feature = "rust1", since = "1.0.0")]
     BrokenPipe,
@@ -129,6 +138,38 @@ pub enum ErrorKind {
     /// requested to not occur.
     #[stable(feature = "rust1", since = "1.0.0")]
     WouldBlock,
+    /// A filesystem object is, unexpectedly, not a directory.
+    ///
+    /// For example, a filesystem path was specified where one of the intermediate directory
+    /// components was, in fact, a plain file.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    NotADirectory,
+    /// The filesystem object is, unexpectedly, a directory.
+    ///
+    /// A directory was specified when a non-directory was expected.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    IsADirectory,
+    /// A non-empty directory was specified where an empty directory was expected.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    DirectoryNotEmpty,
+    /// The filesystem or storage medium is read-only, but a write operation was attempted.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    ReadOnlyFilesystem,
+    /// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links.
+    ///
+    /// There was a loop (or excessively long chain) resolving a filesystem object
+    /// or file IO object.
+    ///
+    /// On Unix this is usually the result of a symbolic link loop; or, of exceeding the
+    /// system-specific limit on the depth of symlink traversal.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    FilesystemLoop,
+    /// Stale network file handle.
+    ///
+    /// With some network filesystems, notably NFS, an open file (or directory) can be invalidated
+    /// by problems with the network or server.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    StaleNetworkFileHandle,
     /// A parameter was incorrect.
     #[stable(feature = "rust1", since = "1.0.0")]
     InvalidInput,
@@ -158,17 +199,78 @@ pub enum ErrorKind {
     /// [`Ok(0)`]: Ok
     #[stable(feature = "rust1", since = "1.0.0")]
     WriteZero,
+    /// The underlying storage (typically, a filesystem) is full.
+    ///
+    /// This does not include out of quota errors.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    StorageFull,
+    /// Seek on unseekable file.
+    ///
+    /// Seeking was attempted on an open file handle which is not suitable for seeking - for
+    /// example, on Unix, a named pipe opened with `File::open`.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    NotSeekable,
+    /// Filesystem quota was exceeded.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    FilesystemQuotaExceeded,
+    /// File larger than allowed or supported.
+    ///
+    /// This might arise from a hard limit of the underlying filesystem or file access API, or from
+    /// an administratively imposed resource limitation.  Simple disk full, and out of quota, have
+    /// their own errors.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    FileTooLarge,
+    /// Resource is busy.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    ResourceBusy,
+    /// Executable file is busy.
+    ///
+    /// An attempt was made to write to a file which is also in use as a running program.  (Not all
+    /// operating systems detect this situation.)
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    ExecutableFileBusy,
+    /// Deadlock (avoided).
+    ///
+    /// A file locking operation would result in deadlock.  This situation is typically detected, if
+    /// at all, on a best-effort basis.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    Deadlock,
+    /// Cross-device or cross-filesystem (hard) link or rename.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    CrossesDevices,
+    /// Too many (hard) links to the same filesystem object.
+    ///
+    /// The filesystem does not support making so many hardlinks to the same file.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    TooManyLinks,
+    /// Filename too long.
+    ///
+    /// The limit might be from the underlying filesystem or API, or an administratively imposed
+    /// resource limit.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    FilenameTooLong,
+    /// Program argument list too long.
+    ///
+    /// When trying to run an external program, a system or process limit on the size of the
+    /// arguments would have been exceeded.
+    #[unstable(feature = "io_error_more", issue = "86442")]
+    ArgumentListTooLong,
     /// This operation was interrupted.
     ///
     /// Interrupted operations can typically be retried.
     #[stable(feature = "rust1", since = "1.0.0")]
     Interrupted,
-    /// Any I/O error not part of this list.
+
+    /// A custom error that does not fall under any other I/O error kind.
     ///
-    /// Errors that are `Other` now may move to a different or a new
-    /// [`ErrorKind`] variant in the future. It is not recommended to match
-    /// an error against `Other` and to expect any additional characteristics,
-    /// e.g., a specific [`Error::raw_os_error`] return value.
+    /// This can be used to construct your own [`Error`]s that do not match any
+    /// [`ErrorKind`].
+    ///
+    /// This [`ErrorKind`] is not used by the standard library.
+    ///
+    /// Errors from the standard library that do not fall under any of the I/O
+    /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern.
+    /// New [`ErrorKind`]s might be added in the future for some of those.
     #[stable(feature = "rust1", since = "1.0.0")]
     Other,
 
@@ -191,31 +293,62 @@ pub enum ErrorKind {
     /// to allocate enough memory.
     #[stable(feature = "out_of_memory_error", since = "1.54.0")]
     OutOfMemory,
+
+    /// Any I/O error from the standard library that's not part of this list.
+    ///
+    /// Errors that are `Uncategorized` now may move to a different or a new
+    /// [`ErrorKind`] variant in the future. It is not recommended to match
+    /// an error against `Uncategorized`; use a wildcard match (`_`) instead.
+    #[unstable(feature = "io_error_uncategorized", issue = "none")]
+    #[doc(hidden)]
+    Uncategorized,
 }
 
 impl ErrorKind {
     pub(crate) fn as_str(&self) -> &'static str {
+        use ErrorKind::*;
         match *self {
-            ErrorKind::NotFound => "entity not found",
-            ErrorKind::PermissionDenied => "permission denied",
-            ErrorKind::ConnectionRefused => "connection refused",
-            ErrorKind::ConnectionReset => "connection reset",
-            ErrorKind::ConnectionAborted => "connection aborted",
-            ErrorKind::NotConnected => "not connected",
-            ErrorKind::AddrInUse => "address in use",
-            ErrorKind::AddrNotAvailable => "address not available",
-            ErrorKind::BrokenPipe => "broken pipe",
-            ErrorKind::AlreadyExists => "entity already exists",
-            ErrorKind::WouldBlock => "operation would block",
-            ErrorKind::InvalidInput => "invalid input parameter",
-            ErrorKind::InvalidData => "invalid data",
-            ErrorKind::TimedOut => "timed out",
-            ErrorKind::WriteZero => "write zero",
-            ErrorKind::Interrupted => "operation interrupted",
-            ErrorKind::Other => "other os error",
-            ErrorKind::UnexpectedEof => "unexpected end of file",
-            ErrorKind::Unsupported => "unsupported",
-            ErrorKind::OutOfMemory => "out of memory",
+            AddrInUse => "address in use",
+            AddrNotAvailable => "address not available",
+            AlreadyExists => "entity already exists",
+            ArgumentListTooLong => "argument list too long",
+            BrokenPipe => "broken pipe",
+            ResourceBusy => "resource busy",
+            ConnectionAborted => "connection aborted",
+            ConnectionRefused => "connection refused",
+            ConnectionReset => "connection reset",
+            CrossesDevices => "cross-device link or rename",
+            Deadlock => "deadlock",
+            DirectoryNotEmpty => "directory not empty",
+            ExecutableFileBusy => "executable file busy",
+            FilenameTooLong => "filename too long",
+            FilesystemQuotaExceeded => "filesystem quota exceeded",
+            FileTooLarge => "file too large",
+            HostUnreachable => "host unreachable",
+            Interrupted => "operation interrupted",
+            InvalidData => "invalid data",
+            InvalidInput => "invalid input parameter",
+            IsADirectory => "is a directory",
+            NetworkDown => "network down",
+            NetworkUnreachable => "network unreachable",
+            NotADirectory => "not a directory",
+            StorageFull => "no storage space",
+            NotConnected => "not connected",
+            NotFound => "entity not found",
+            Other => "other error",
+            OutOfMemory => "out of memory",
+            PermissionDenied => "permission denied",
+            ReadOnlyFilesystem => "read-only filesystem or storage medium",
+            StaleNetworkFileHandle => "stale network file handle",
+            FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
+            NotSeekable => "seek on unseekable file",
+            TimedOut => "timed out",
+            TooManyLinks => "too many links",
+            Uncategorized => "uncategorized error",
+            UnexpectedEof => "unexpected end of file",
+            Unsupported => "unsupported",
+            WouldBlock => "operation would block",
+            WriteZero => "write zero",
         }
     }
 }
@@ -538,7 +671,7 @@ impl Error {
     /// }
     ///
     /// fn main() {
-    ///     // Will print "Other".
+    ///     // Will print "Uncategorized".
     ///     print_error(Error::last_os_error());
     ///     // Will print "AddrInUse".
     ///     print_error(Error::new(ErrorKind::AddrInUse, "oh no!"));
index 4c154dbe01a5aa22835f4ee48c8e2f88ea1142aa..cc615b95f8625eec22a447b9b35033ce565304e9 100644 (file)
 mod tests;
 
 use crate::cmp;
+use crate::convert::TryInto;
 use crate::fmt;
+use crate::mem::replace;
 use crate::ops::{Deref, DerefMut};
 use crate::ptr;
 use crate::slice;
@@ -275,6 +277,8 @@ pub use self::error::{Error, ErrorKind, Result};
 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 = "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};
 #[unstable(feature = "print_internals", issue = "none")]
@@ -510,6 +514,7 @@ pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [
 /// [`File`]: crate::fs::File
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(notable_trait)]
+#[cfg_attr(not(test), rustc_diagnostic_item = "IoRead")]
 pub trait Read {
     /// Pull some bytes from this source into the specified buffer, returning
     /// how many bytes were read.
@@ -1044,6 +1049,32 @@ impl<'a> IoSliceMut<'a> {
 
     /// Advance the internal cursor of the slice.
     ///
+    /// Also see [`IoSliceMut::advance_slices`] to advance the cursors of
+    /// multiple buffers.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(io_slice_advance)]
+    ///
+    /// use std::io::IoSliceMut;
+    /// use std::ops::Deref;
+    ///
+    /// let mut data = [1; 8];
+    /// let mut buf = IoSliceMut::new(&mut data);
+    ///
+    /// // Mark 3 bytes as read.
+    /// buf.advance(3);
+    /// assert_eq!(buf.deref(), [1; 5].as_ref());
+    /// ```
+    #[unstable(feature = "io_slice_advance", issue = "62726")]
+    #[inline]
+    pub fn advance(&mut self, n: usize) {
+        self.0.advance(n)
+    }
+
+    /// Advance the internal cursor of the slices.
+    ///
     /// # Notes
     ///
     /// Elements in the slice may be modified if the cursor is not advanced to
@@ -1070,13 +1101,13 @@ impl<'a> IoSliceMut<'a> {
     /// ][..];
     ///
     /// // Mark 10 bytes as read.
-    /// bufs = IoSliceMut::advance(bufs, 10);
+    /// IoSliceMut::advance_slices(&mut bufs, 10);
     /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
     /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
     /// ```
     #[unstable(feature = "io_slice_advance", issue = "62726")]
     #[inline]
-    pub fn advance<'b>(bufs: &'b mut [IoSliceMut<'a>], n: usize) -> &'b mut [IoSliceMut<'a>] {
+    pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) {
         // Number of buffers to remove.
         let mut remove = 0;
         // Total length of all the to be removed buffers.
@@ -1090,11 +1121,10 @@ impl<'a> IoSliceMut<'a> {
             }
         }
 
-        let bufs = &mut bufs[remove..];
+        *bufs = &mut replace(bufs, &mut [])[remove..];
         if !bufs.is_empty() {
-            bufs[0].0.advance(n - accumulated_len)
+            bufs[0].advance(n - accumulated_len)
         }
-        bufs
     }
 }
 
@@ -1153,6 +1183,32 @@ impl<'a> IoSlice<'a> {
 
     /// Advance the internal cursor of the slice.
     ///
+    /// Also see [`IoSlice::advance_slices`] to advance the cursors of multiple
+    /// buffers.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(io_slice_advance)]
+    ///
+    /// use std::io::IoSlice;
+    /// use std::ops::Deref;
+    ///
+    /// let mut data = [1; 8];
+    /// let mut buf = IoSlice::new(&mut data);
+    ///
+    /// // Mark 3 bytes as read.
+    /// buf.advance(3);
+    /// assert_eq!(buf.deref(), [1; 5].as_ref());
+    /// ```
+    #[unstable(feature = "io_slice_advance", issue = "62726")]
+    #[inline]
+    pub fn advance(&mut self, n: usize) {
+        self.0.advance(n)
+    }
+
+    /// Advance the internal cursor of the slices.
+    ///
     /// # Notes
     ///
     /// Elements in the slice may be modified if the cursor is not advanced to
@@ -1179,12 +1235,12 @@ impl<'a> IoSlice<'a> {
     /// ][..];
     ///
     /// // Mark 10 bytes as written.
-    /// bufs = IoSlice::advance(bufs, 10);
+    /// IoSlice::advance_slices(&mut bufs, 10);
     /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
     /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
     #[unstable(feature = "io_slice_advance", issue = "62726")]
     #[inline]
-    pub fn advance<'b>(bufs: &'b mut [IoSlice<'a>], n: usize) -> &'b mut [IoSlice<'a>] {
+    pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) {
         // Number of buffers to remove.
         let mut remove = 0;
         // Total length of all the to be removed buffers.
@@ -1198,11 +1254,10 @@ impl<'a> IoSlice<'a> {
             }
         }
 
-        let bufs = &mut bufs[remove..];
+        *bufs = &mut replace(bufs, &mut [])[remove..];
         if !bufs.is_empty() {
-            bufs[0].0.advance(n - accumulated_len)
+            bufs[0].advance(n - accumulated_len)
         }
-        bufs
     }
 }
 
@@ -1307,6 +1362,7 @@ impl Initializer {
 /// [`write_all`]: Write::write_all
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(notable_trait)]
+#[cfg_attr(not(test), rustc_diagnostic_item = "IoWrite")]
 pub trait Write {
     /// Write a buffer into this writer, returning how many bytes were written.
     ///
@@ -1364,6 +1420,27 @@ pub trait Write {
     /// The default implementation calls [`write`] with either the first nonempty
     /// buffer provided, or an empty one if none exists.
     ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::IoSlice;
+    /// use std::io::prelude::*;
+    /// use std::fs::File;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut data1 = [1; 8];
+    ///     let mut data2 = [15; 8];
+    ///     let io_slice1 = IoSlice::new(&mut data1);
+    ///     let io_slice2 = IoSlice::new(&mut data2);
+    ///
+    ///     let mut buffer = File::create("foo.txt")?;
+    ///
+    ///     // Writes some prefix of the byte string, not necessarily all of it.
+    ///     buffer.write_vectored(&[io_slice1, io_slice2])?;
+    ///     Ok(())
+    /// }
+    /// ```
+    ///
     /// [`write`]: Write::write
     #[stable(feature = "iovec", since = "1.36.0")]
     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {
@@ -1511,7 +1588,7 @@ pub trait Write {
     fn write_all_vectored(&mut self, mut bufs: &mut [IoSlice<'_>]) -> Result<()> {
         // Guarantee that bufs is empty if it contains no data,
         // to avoid calling write_vectored if there is no data to be written.
-        bufs = IoSlice::advance(bufs, 0);
+        IoSlice::advance_slices(&mut bufs, 0);
         while !bufs.is_empty() {
             match self.write_vectored(bufs) {
                 Ok(0) => {
@@ -1520,7 +1597,7 @@ pub trait Write {
                         &"failed to write whole buffer",
                     ));
                 }
-                Ok(n) => bufs = IoSlice::advance(bufs, n),
+                Ok(n) => IoSlice::advance_slices(&mut bufs, n),
                 Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
                 Err(e) => return Err(e),
             }
@@ -1592,7 +1669,7 @@ pub trait Write {
                 if output.error.is_err() {
                     output.error
                 } else {
-                    Err(Error::new_const(ErrorKind::Other, &"formatter error"))
+                    Err(Error::new_const(ErrorKind::Uncategorized, &"formatter error"))
                 }
             }
         }
@@ -1684,7 +1761,6 @@ pub trait Seek {
     /// # Example
     ///
     /// ```no_run
-    /// #![feature(seek_rewind)]
     /// use std::io::{Read, Seek, Write};
     /// use std::fs::OpenOptions;
     ///
@@ -1702,7 +1778,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(())
@@ -1953,6 +2029,37 @@ pub trait BufRead: Read {
     #[stable(feature = "rust1", since = "1.0.0")]
     fn consume(&mut self, amt: usize);
 
+    /// Check if the underlying `Read` has any data left to be read.
+    ///
+    /// This function may fill the buffer to check for data,
+    /// so this functions returns `Result<bool>`, not `bool`.
+    ///
+    /// Default implementation calls `fill_buf` and checks that
+    /// returned slice is empty (which means that there is no data left,
+    /// since EOF is reached).
+    ///
+    /// Examples
+    ///
+    /// ```
+    /// #![feature(buf_read_has_data_left)]
+    /// use std::io;
+    /// use std::io::prelude::*;
+    ///
+    /// let stdin = io::stdin();
+    /// let mut stdin = stdin.lock();
+    ///
+    /// while stdin.has_data_left().unwrap() {
+    ///     let mut line = String::new();
+    ///     stdin.read_line(&mut line).unwrap();
+    ///     // work with line
+    ///     println!("{:?}", line);
+    /// }
+    /// ```
+    #[unstable(feature = "buf_read_has_data_left", reason = "recently added", issue = "86423")]
+    fn has_data_left(&mut self) -> Result<bool> {
+        self.fill_buf().map(|b| !b.is_empty())
+    }
+
     /// Read all bytes into `buf` until the delimiter `byte` or EOF is reached.
     ///
     /// This function will read bytes from the underlying stream until the
@@ -2291,13 +2398,15 @@ impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
 }
 
 impl<T, U> SizeHint for Chain<T, U> {
+    #[inline]
     fn lower_bound(&self) -> usize {
         SizeHint::lower_bound(&self.first) + SizeHint::lower_bound(&self.second)
     }
 
+    #[inline]
     fn upper_bound(&self) -> Option<usize> {
         match (SizeHint::upper_bound(&self.first), SizeHint::upper_bound(&self.second)) {
-            (Some(first), Some(second)) => Some(first + second),
+            (Some(first), Some(second)) => first.checked_add(second),
             _ => None,
         }
     }
@@ -2502,6 +2611,21 @@ impl<T: BufRead> BufRead for Take<T> {
     }
 }
 
+impl<T> SizeHint for Take<T> {
+    #[inline]
+    fn lower_bound(&self) -> usize {
+        cmp::min(SizeHint::lower_bound(&self.inner) as u64, self.limit) as usize
+    }
+
+    #[inline]
+    fn upper_bound(&self) -> Option<usize> {
+        match SizeHint::upper_bound(&self.inner) {
+            Some(upper_bound) => Some(cmp::min(upper_bound as u64, self.limit) as usize),
+            None => self.limit.try_into().ok(),
+        }
+    }
+}
+
 /// An iterator over `u8` values of a reader.
 ///
 /// This struct is generally created by calling [`bytes`] on a reader.
@@ -2546,15 +2670,53 @@ trait SizeHint {
 }
 
 impl<T> SizeHint for T {
+    #[inline]
     default fn lower_bound(&self) -> usize {
         0
     }
 
+    #[inline]
     default fn upper_bound(&self) -> Option<usize> {
         None
     }
 }
 
+impl<T> SizeHint for &mut T {
+    #[inline]
+    fn lower_bound(&self) -> usize {
+        SizeHint::lower_bound(*self)
+    }
+
+    #[inline]
+    fn upper_bound(&self) -> Option<usize> {
+        SizeHint::upper_bound(*self)
+    }
+}
+
+impl<T> SizeHint for Box<T> {
+    #[inline]
+    fn lower_bound(&self) -> usize {
+        SizeHint::lower_bound(&**self)
+    }
+
+    #[inline]
+    fn upper_bound(&self) -> Option<usize> {
+        SizeHint::upper_bound(&**self)
+    }
+}
+
+impl SizeHint for &[u8] {
+    #[inline]
+    fn lower_bound(&self) -> usize {
+        self.len()
+    }
+
+    #[inline]
+    fn upper_bound(&self) -> Option<usize> {
+        Some(self.len())
+    }
+}
+
 /// An iterator over the contents of an instance of `BufRead` split on a
 /// particular byte.
 ///
index 2b0d2b7e0be23e87e3a674591c78d535c699589e..65ad7d88e22d5dbe5066c232e5043c5d65828cae 100644 (file)
@@ -7,7 +7,7 @@ use crate::io::prelude::*;
 
 use crate::cell::{Cell, RefCell};
 use crate::fmt;
-use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter};
+use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter, Lines, Split};
 use crate::lazy::SyncOnceCell;
 use crate::pin::Pin;
 use crate::sync::atomic::{AtomicBool, Ordering};
@@ -310,6 +310,48 @@ pub fn stdin() -> Stdin {
     }
 }
 
+/// Constructs a new locked handle to the standard input of the current
+/// process.
+///
+/// Each handle returned is a guard granting locked access to a shared
+/// global buffer whose access is synchronized via a mutex. If you need
+/// more explicit control over locking, for example, in a multi-threaded
+/// program, use the [`io::stdin`] function to obtain an unlocked handle,
+/// along with the [`Stdin::lock`] method.
+///
+/// The lock is released when the returned guard goes out of scope. The
+/// returned guard also implements the [`Read`] and [`BufRead`] traits for
+/// accessing the underlying data.
+///
+/// **Note**: The mutex locked by this handle is not reentrant. Even in a
+/// single-threaded program, calling other code that accesses [`Stdin`]
+/// could cause a deadlock or panic, if this locked handle is held across
+/// that call.
+///
+/// ### Note: Windows Portability Consideration
+/// When operating in a console, the Windows implementation of this stream does not support
+/// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
+/// an error.
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(stdio_locked)]
+/// use std::io::{self, Read};
+///
+/// fn main() -> io::Result<()> {
+///     let mut buffer = String::new();
+///     let mut handle = io::stdin_locked();
+///
+///     handle.read_to_string(&mut buffer)?;
+///     Ok(())
+/// }
+/// ```
+#[unstable(feature = "stdio_locked", issue = "86845")]
+pub fn stdin_locked() -> StdinLock<'static> {
+    stdin().into_locked()
+}
+
 impl Stdin {
     /// Locks this handle to the standard input stream, returning a readable
     /// guard.
@@ -334,7 +376,7 @@ impl Stdin {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn lock(&self) -> StdinLock<'_> {
-        StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
+        self.lock_any()
     }
 
     /// Locks this handle and reads a line of input, appending it to the specified buffer.
@@ -367,6 +409,86 @@ impl Stdin {
     pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
         self.lock().read_line(buf)
     }
+
+    // Locks this handle with any lifetime. This depends on the
+    // implementation detail that the underlying `Mutex` is static.
+    fn lock_any<'a>(&self) -> StdinLock<'a> {
+        StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
+    }
+
+    /// Consumes this handle to the standard input stream, locking the
+    /// shared global buffer associated with the stream and returning a
+    /// readable guard.
+    ///
+    /// The lock is released when the returned guard goes out of scope. The
+    /// returned guard also implements the [`Read`] and [`BufRead`] traits
+    /// for accessing the underlying data.
+    ///
+    /// It is often simpler to directly get a locked handle using the
+    /// [`stdin_locked`] function instead, unless nearby code also needs to
+    /// use an unlocked handle.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(stdio_locked)]
+    /// use std::io::{self, Read};
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut buffer = String::new();
+    ///     let mut handle = io::stdin().into_locked();
+    ///
+    ///     handle.read_to_string(&mut buffer)?;
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "stdio_locked", issue = "86845")]
+    pub fn into_locked(self) -> StdinLock<'static> {
+        self.lock_any()
+    }
+
+    /// Consumes this handle and returns an iterator over input lines.
+    ///
+    /// For detailed semantics of this method, see the documentation on
+    /// [`BufRead::lines`].
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(stdin_forwarders)]
+    /// use std::io;
+    ///
+    /// let lines = io::stdin().lines();
+    /// for line in lines {
+    ///     println!("got a line: {}", line.unwrap());
+    /// }
+    /// ```
+    #[unstable(feature = "stdin_forwarders", issue = "87096")]
+    pub fn lines(self) -> Lines<StdinLock<'static>> {
+        self.into_locked().lines()
+    }
+
+    /// Consumes this handle and returns an iterator over input bytes,
+    /// split at the specified byte value.
+    ///
+    /// For detailed semantics of this method, see the documentation on
+    /// [`BufRead::split`].
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(stdin_forwarders)]
+    /// use std::io;
+    ///
+    /// let splits = io::stdin().split(b'-');
+    /// for split in splits {
+    ///     println!("got a chunk: {}", String::from_utf8_lossy(&split.unwrap()));
+    /// }
+    /// ```
+    #[unstable(feature = "stdin_forwarders", issue = "87096")]
+    pub fn split(self, byte: u8) -> Split<StdinLock<'static>> {
+        self.into_locked().split(byte)
+    }
 }
 
 #[stable(feature = "std_debug", since = "1.16.0")]
@@ -558,6 +680,42 @@ pub fn stdout() -> Stdout {
     }
 }
 
+/// Constructs a new locked handle to the standard output of the current
+/// process.
+///
+/// Each handle returned is a guard granting locked access to a shared
+/// global buffer whose access is synchronized via a mutex. If you need
+/// more explicit control over locking, for example, in a multi-threaded
+/// program, use the [`io::stdout`] function to obtain an unlocked handle,
+/// along with the [`Stdout::lock`] method.
+///
+/// The lock is released when the returned guard goes out of scope. The
+/// returned guard also implements the [`Write`] trait for writing data.
+///
+/// ### Note: Windows Portability Consideration
+/// When operating in a console, the Windows implementation of this stream does not support
+/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
+/// an error.
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(stdio_locked)]
+/// use std::io::{self, Write};
+///
+/// fn main() -> io::Result<()> {
+///     let mut handle = io::stdout_locked();
+///
+///     handle.write_all(b"hello world")?;
+///
+///     Ok(())
+/// }
+/// ```
+#[unstable(feature = "stdio_locked", issue = "86845")]
+pub fn stdout_locked() -> StdoutLock<'static> {
+    stdout().into_locked()
+}
+
 pub fn cleanup() {
     if let Some(instance) = STDOUT.get() {
         // Flush the data and disable buffering during shutdown
@@ -595,8 +753,45 @@ impl Stdout {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn lock(&self) -> StdoutLock<'_> {
+        self.lock_any()
+    }
+
+    // Locks this handle with any lifetime. This depends on the
+    // implementation detail that the underlying `ReentrantMutex` is
+    // static.
+    fn lock_any<'a>(&self) -> StdoutLock<'a> {
         StdoutLock { inner: self.inner.lock() }
     }
+
+    /// Consumes this handle to the standard output stream, locking the
+    /// shared global buffer associated with the stream and returning a
+    /// writable guard.
+    ///
+    /// The lock is released when the returned lock goes out of scope. The
+    /// returned guard also implements the [`Write`] trait for writing data.
+    ///
+    /// It is often simpler to directly get a locked handle using the
+    /// [`io::stdout_locked`] function instead, unless nearby code also
+    /// needs to use an unlocked handle.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(stdio_locked)]
+    /// use std::io::{self, Write};
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut handle = io::stdout().into_locked();
+    ///
+    ///     handle.write_all(b"hello world")?;
+    ///
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "stdio_locked", issue = "86845")]
+    pub fn into_locked(self) -> StdoutLock<'static> {
+        self.lock_any()
+    }
 }
 
 #[stable(feature = "std_debug", since = "1.16.0")]
@@ -769,6 +964,35 @@ pub fn stderr() -> Stderr {
     }
 }
 
+/// Constructs a new locked handle to the standard error of the current
+/// process.
+///
+/// This handle is not buffered.
+///
+/// ### Note: Windows Portability Consideration
+/// When operating in a console, the Windows implementation of this stream does not support
+/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
+/// an error.
+///
+/// # Example
+///
+/// ```no_run
+/// #![feature(stdio_locked)]
+/// use std::io::{self, Write};
+///
+/// fn main() -> io::Result<()> {
+///     let mut handle = io::stderr_locked();
+///
+///     handle.write_all(b"hello world")?;
+///
+///     Ok(())
+/// }
+/// ```
+#[unstable(feature = "stdio_locked", issue = "86845")]
+pub fn stderr_locked() -> StderrLock<'static> {
+    stderr().into_locked()
+}
+
 impl Stderr {
     /// Locks this handle to the standard error stream, returning a writable
     /// guard.
@@ -792,8 +1016,42 @@ impl Stderr {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn lock(&self) -> StderrLock<'_> {
+        self.lock_any()
+    }
+
+    // Locks this handle with any lifetime. This depends on the
+    // implementation detail that the underlying `ReentrantMutex` is
+    // static.
+    fn lock_any<'a>(&self) -> StderrLock<'a> {
         StderrLock { inner: self.inner.lock() }
     }
+
+    /// Locks and consumes this handle to the standard error stream,
+    /// returning a writable guard.
+    ///
+    /// The lock is released when the returned guard goes out of scope. The
+    /// returned guard also implements the [`Write`] trait for writing
+    /// data.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(stdio_locked)]
+    /// use std::io::{self, Write};
+    ///
+    /// fn foo() -> io::Result<()> {
+    ///     let stderr = io::stderr();
+    ///     let mut handle = stderr.into_locked();
+    ///
+    ///     handle.write_all(b"hello world")?;
+    ///
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "stdio_locked", issue = "86845")]
+    pub fn into_locked(self) -> StderrLock<'static> {
+        self.lock_any()
+    }
 }
 
 #[stable(feature = "std_debug", since = "1.16.0")]
index 04af500268f97ec8d38a570b1da2574774d5f982..b1df6b7131c8779f0fe2a3da9a51faedc9b36807 100644 (file)
@@ -1,5 +1,6 @@
 use super::*;
 use crate::panic::{RefUnwindSafe, UnwindSafe};
+use crate::sync::mpsc::sync_channel;
 use crate::thread;
 
 #[test]
@@ -45,3 +46,121 @@ fn panic_doesnt_poison() {
     let _a = stderr();
     let _a = _a.lock();
 }
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn test_lock_stderr() {
+    test_lock(stderr, stderr_locked);
+}
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn test_lock_stdin() {
+    test_lock(stdin, stdin_locked);
+}
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn test_lock_stdout() {
+    test_lock(stdout, stdout_locked);
+}
+
+// Helper trait to make lock testing function generic.
+trait Stdio<'a>: 'static
+where
+    Self::Lock: 'a,
+{
+    type Lock;
+    fn lock(&'a self) -> Self::Lock;
+}
+impl<'a> Stdio<'a> for Stderr {
+    type Lock = StderrLock<'a>;
+    fn lock(&'a self) -> StderrLock<'a> {
+        self.lock()
+    }
+}
+impl<'a> Stdio<'a> for Stdin {
+    type Lock = StdinLock<'a>;
+    fn lock(&'a self) -> StdinLock<'a> {
+        self.lock()
+    }
+}
+impl<'a> Stdio<'a> for Stdout {
+    type Lock = StdoutLock<'a>;
+    fn lock(&'a self) -> StdoutLock<'a> {
+        self.lock()
+    }
+}
+
+// Helper trait to make lock testing function generic.
+trait StdioOwnedLock: 'static {}
+impl StdioOwnedLock for StderrLock<'static> {}
+impl StdioOwnedLock for StdinLock<'static> {}
+impl StdioOwnedLock for StdoutLock<'static> {}
+
+// Tests locking on stdio handles by starting two threads and checking that
+// they block each other appropriately.
+fn test_lock<T, U>(get_handle: fn() -> T, get_locked: fn() -> U)
+where
+    T: for<'a> Stdio<'a>,
+    U: StdioOwnedLock,
+{
+    // State enum to track different phases of the test, primarily when
+    // each lock is acquired and released.
+    #[derive(Debug, PartialEq)]
+    enum State {
+        Start1,
+        Acquire1,
+        Start2,
+        Release1,
+        Acquire2,
+        Release2,
+    }
+    use State::*;
+    // Logging vector to be checked to make sure lock acquisitions and
+    // releases happened in the correct order.
+    let log = Arc::new(Mutex::new(Vec::new()));
+    let ((tx1, rx1), (tx2, rx2)) = (sync_channel(0), sync_channel(0));
+    let th1 = {
+        let (log, tx) = (Arc::clone(&log), tx1);
+        thread::spawn(move || {
+            log.lock().unwrap().push(Start1);
+            let handle = get_handle();
+            {
+                let locked = handle.lock();
+                log.lock().unwrap().push(Acquire1);
+                tx.send(Acquire1).unwrap(); // notify of acquisition
+                tx.send(Release1).unwrap(); // wait for release command
+                log.lock().unwrap().push(Release1);
+            }
+            tx.send(Acquire1).unwrap(); // wait for th2 acquire
+            {
+                let locked = handle.lock();
+                log.lock().unwrap().push(Acquire1);
+            }
+            log.lock().unwrap().push(Release1);
+        })
+    };
+    let th2 = {
+        let (log, tx) = (Arc::clone(&log), tx2);
+        thread::spawn(move || {
+            tx.send(Start2).unwrap(); // wait for start command
+            let locked = get_locked();
+            log.lock().unwrap().push(Acquire2);
+            tx.send(Acquire2).unwrap(); // notify of acquisition
+            tx.send(Release2).unwrap(); // wait for release command
+            log.lock().unwrap().push(Release2);
+        })
+    };
+    assert_eq!(rx1.recv().unwrap(), Acquire1); // wait for th1 acquire
+    log.lock().unwrap().push(Start2);
+    assert_eq!(rx2.recv().unwrap(), Start2); // block th2
+    assert_eq!(rx1.recv().unwrap(), Release1); // release th1
+    assert_eq!(rx2.recv().unwrap(), Acquire2); // wait for th2 acquire
+    assert_eq!(rx1.recv().unwrap(), Acquire1); // block th1
+    assert_eq!(rx2.recv().unwrap(), Release2); // release th2
+    th2.join().unwrap();
+    th1.join().unwrap();
+    assert_eq!(
+        *log.lock().unwrap(),
+        [Start1, Acquire1, Start2, Release1, Acquire2, Release2, Acquire1, Release1]
+    );
+}
index 2b14e16150317f3be9c5c0a2c6576e83b6fddf87..1beb72a9a5072344a696c13eca99646ea5d0e65d 100644 (file)
@@ -71,6 +71,16 @@ fn lines() {
     assert!(s.next().is_none());
 }
 
+#[test]
+fn buf_read_has_data_left() {
+    let mut buf = Cursor::new(&b"abcd"[..]);
+    assert!(buf.has_data_left().unwrap());
+    buf.read_exact(&mut [0; 2]).unwrap();
+    assert!(buf.has_data_left().unwrap());
+    buf.read_exact(&mut [0; 2]).unwrap();
+    assert!(!buf.has_data_left().unwrap());
+}
+
 #[test]
 fn read_to_end() {
     let mut c = Cursor::new(&b""[..]);
@@ -224,6 +234,24 @@ fn empty_size_hint() {
     assert_eq!(size_hint, (0, Some(0)));
 }
 
+#[test]
+fn slice_size_hint() {
+    let size_hint = (&[1, 2, 3]).bytes().size_hint();
+    assert_eq!(size_hint, (3, Some(3)));
+}
+
+#[test]
+fn take_size_hint() {
+    let size_hint = (&[1, 2, 3]).take(2).bytes().size_hint();
+    assert_eq!(size_hint, (2, Some(2)));
+
+    let size_hint = (&[1, 2, 3]).take(4).bytes().size_hint();
+    assert_eq!(size_hint, (3, Some(3)));
+
+    let size_hint = io::repeat(0).take(3).bytes().size_hint();
+    assert_eq!(size_hint, (3, Some(3)));
+}
+
 #[test]
 fn chain_empty_size_hint() {
     let chain = io::empty().chain(io::empty());
@@ -242,7 +270,7 @@ fn chain_size_hint() {
 
     let chain = buf_reader_1.chain(buf_reader_2);
     let size_hint = chain.bytes().size_hint();
-    assert_eq!(size_hint, (testdata.len(), None));
+    assert_eq!(size_hint, (testdata.len(), Some(testdata.len())));
 }
 
 #[test]
@@ -308,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(())
 }
 
@@ -353,7 +385,7 @@ fn test_read_to_end_capacity() -> io::Result<()> {
 }
 
 #[test]
-fn io_slice_mut_advance() {
+fn io_slice_mut_advance_slices() {
     let mut buf1 = [1; 8];
     let mut buf2 = [2; 16];
     let mut buf3 = [3; 8];
@@ -364,75 +396,75 @@ fn io_slice_mut_advance() {
     ][..];
 
     // Only in a single buffer..
-    bufs = IoSliceMut::advance(bufs, 1);
+    IoSliceMut::advance_slices(&mut bufs, 1);
     assert_eq!(bufs[0].deref(), [1; 7].as_ref());
     assert_eq!(bufs[1].deref(), [2; 16].as_ref());
     assert_eq!(bufs[2].deref(), [3; 8].as_ref());
 
     // Removing a buffer, leaving others as is.
-    bufs = IoSliceMut::advance(bufs, 7);
+    IoSliceMut::advance_slices(&mut bufs, 7);
     assert_eq!(bufs[0].deref(), [2; 16].as_ref());
     assert_eq!(bufs[1].deref(), [3; 8].as_ref());
 
     // Removing a buffer and removing from the next buffer.
-    bufs = IoSliceMut::advance(bufs, 18);
+    IoSliceMut::advance_slices(&mut bufs, 18);
     assert_eq!(bufs[0].deref(), [3; 6].as_ref());
 }
 
 #[test]
-fn io_slice_mut_advance_empty_slice() {
-    let empty_bufs = &mut [][..];
+fn io_slice_mut_advance_slices_empty_slice() {
+    let mut empty_bufs = &mut [][..];
     // Shouldn't panic.
-    IoSliceMut::advance(empty_bufs, 1);
+    IoSliceMut::advance_slices(&mut empty_bufs, 1);
 }
 
 #[test]
-fn io_slice_mut_advance_beyond_total_length() {
+fn io_slice_mut_advance_slices_beyond_total_length() {
     let mut buf1 = [1; 8];
     let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..];
 
     // Going beyond the total length should be ok.
-    bufs = IoSliceMut::advance(bufs, 9);
+    IoSliceMut::advance_slices(&mut bufs, 9);
     assert!(bufs.is_empty());
 }
 
 #[test]
-fn io_slice_advance() {
+fn io_slice_advance_slices() {
     let buf1 = [1; 8];
     let buf2 = [2; 16];
     let buf3 = [3; 8];
     let mut bufs = &mut [IoSlice::new(&buf1), IoSlice::new(&buf2), IoSlice::new(&buf3)][..];
 
     // Only in a single buffer..
-    bufs = IoSlice::advance(bufs, 1);
+    IoSlice::advance_slices(&mut bufs, 1);
     assert_eq!(bufs[0].deref(), [1; 7].as_ref());
     assert_eq!(bufs[1].deref(), [2; 16].as_ref());
     assert_eq!(bufs[2].deref(), [3; 8].as_ref());
 
     // Removing a buffer, leaving others as is.
-    bufs = IoSlice::advance(bufs, 7);
+    IoSlice::advance_slices(&mut bufs, 7);
     assert_eq!(bufs[0].deref(), [2; 16].as_ref());
     assert_eq!(bufs[1].deref(), [3; 8].as_ref());
 
     // Removing a buffer and removing from the next buffer.
-    bufs = IoSlice::advance(bufs, 18);
+    IoSlice::advance_slices(&mut bufs, 18);
     assert_eq!(bufs[0].deref(), [3; 6].as_ref());
 }
 
 #[test]
-fn io_slice_advance_empty_slice() {
-    let empty_bufs = &mut [][..];
+fn io_slice_advance_slices_empty_slice() {
+    let mut empty_bufs = &mut [][..];
     // Shouldn't panic.
-    IoSlice::advance(empty_bufs, 1);
+    IoSlice::advance_slices(&mut empty_bufs, 1);
 }
 
 #[test]
-fn io_slice_advance_beyond_total_length() {
+fn io_slice_advance_slices_beyond_total_length() {
     let buf1 = [1; 8];
     let mut bufs = &mut [IoSlice::new(&buf1)][..];
 
     // Going beyond the total length should be ok.
-    bufs = IoSlice::advance(bufs, 9);
+    IoSlice::advance_slices(&mut bufs, 9);
     assert!(bufs.is_empty());
 }
 
index 73f2f3eb3f5dc9ec50265a782b9a93836c0a2072..fd52de7430a203af9bf247211756b528af5da5e5 100644 (file)
@@ -13,9 +13,8 @@ use crate::io::{
 /// This struct is generally created by calling [`empty()`]. Please see
 /// the documentation of [`empty()`] for more details.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Empty {
-    _priv: (),
-}
+#[non_exhaustive]
+pub struct Empty;
 
 /// Constructs a new handle to an empty reader.
 ///
@@ -35,7 +34,7 @@ pub struct Empty {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")]
 pub const fn empty() -> Empty {
-    Empty { _priv: () }
+    Empty
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -83,6 +82,7 @@ impl fmt::Debug for Empty {
 }
 
 impl SizeHint for Empty {
+    #[inline]
     fn upper_bound(&self) -> Option<usize> {
         Some(0)
     }
@@ -147,6 +147,18 @@ impl Read for Repeat {
     }
 }
 
+impl SizeHint for Repeat {
+    #[inline]
+    fn lower_bound(&self) -> usize {
+        usize::MAX
+    }
+
+    #[inline]
+    fn upper_bound(&self) -> Option<usize> {
+        None
+    }
+}
+
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Repeat {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -159,9 +171,8 @@ impl fmt::Debug for Repeat {
 /// This struct is generally created by calling [`sink`]. Please
 /// see the documentation of [`sink()`] for more details.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Sink {
-    _priv: (),
-}
+#[non_exhaustive]
+pub struct Sink;
 
 /// Creates an instance of a writer which will successfully consume all data.
 ///
@@ -182,7 +193,7 @@ pub struct Sink {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")]
 pub const fn sink() -> Sink {
-    Sink { _priv: () }
+    Sink
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index 5b8e83766f0e846444405df1aacf15c96a5cde6b..605bd33a4bf22f9e7546d3cc88f8d673064173c5 100644 (file)
@@ -971,7 +971,7 @@ mod match_keyword {}
 /// ```
 ///
 /// Like [`struct`]s and [`enum`]s, a module and its content are private by
-/// default, unaccessible to code outside of the module.
+/// default, inaccessible to code outside of the module.
 ///
 /// To learn more about allowing access, see the documentation for the [`pub`]
 /// keyword.
@@ -1092,8 +1092,7 @@ mod move_keyword {}
 /// Mutable raw pointers work much like mutable references, with the added
 /// possibility of not pointing to a valid object. The syntax is `*mut Type`.
 ///
-/// More information on mutable references and pointers can be found in```
-/// [Reference].
+/// More information on mutable references and pointers can be found in the [Reference].
 ///
 /// [Reference]: ../reference/types/pointer.html#mutable-references-mut
 mod mut_keyword {}
@@ -2257,6 +2256,9 @@ mod await_keyword {}
 /// At run-time, when a method needs to be called on the `dyn Trait`, the vtable is consulted to get
 /// the function pointer and then that function pointer is called.
 ///
+/// See the Reference for more information on [trait objects][ref-trait-obj]
+/// and [object safety][ref-obj-safety].
+///
 /// ## Trade-offs
 ///
 /// The above indirection is the additional runtime cost of calling a function on a `dyn Trait`.
@@ -2265,9 +2267,9 @@ mod await_keyword {}
 /// However, `dyn Trait` is likely to produce smaller code than `impl Trait` / generic parameters as
 /// the method won't be duplicated for each concrete type.
 ///
-/// Read more about `object safety` and [trait object]s.
-///
 /// [trait object]: ../book/ch17-02-trait-objects.html
+/// [ref-trait-obj]: ../reference/types/trait-object.html
+/// [ref-obj-safety]: ../reference/items/traits.html#object-safety
 /// [erased]: https://en.wikipedia.org/wiki/Type_erasure
 mod dyn_keyword {}
 
index 31dcd9546bc8acd0baea5874c75dc09599b0af38..cfbfe7cc191605497cfb9bf0302d9b6ac7a7c159 100644 (file)
 #![feature(allocator_internals)]
 #![feature(allow_internal_unsafe)]
 #![feature(allow_internal_unstable)]
-#![feature(async_stream)]
 #![feature(arbitrary_self_types)]
 #![feature(array_error_internals)]
 #![feature(asm)]
 #![feature(assert_matches)]
 #![feature(associated_type_bounds)]
+#![feature(async_stream)]
 #![feature(atomic_mut_ptr)]
+#![feature(auto_traits)]
 #![feature(bench_black_box)]
 #![feature(box_syntax)]
 #![feature(c_variadic)]
 #![feature(concat_idents)]
 #![feature(const_cstr_unchecked)]
 #![feature(const_fn_floating_point_arithmetic)]
-#![feature(const_fn_transmute)]
 #![feature(const_fn_fn_ptr_basics)]
+#![feature(const_fn_transmute)]
 #![feature(const_io_structs)]
 #![feature(const_ip)]
+#![feature(const_ipv4)]
 #![feature(const_ipv6)]
 #![feature(const_raw_ptr_deref)]
 #![feature(const_socketaddr)]
-#![feature(const_ipv4)]
 #![feature(container_error_extra)]
 #![feature(core_intrinsics)]
 #![feature(custom_test_frameworks)]
 #![feature(doc_masked)]
 #![feature(doc_notable_trait)]
 #![feature(dropck_eyepatch)]
+#![feature(duration_checked_float)]
 #![feature(duration_constants)]
 #![feature(edition_panic)]
 #![feature(exact_size_is_empty)]
 #![feature(exhaustive_patterns)]
 #![feature(extend_one)]
-#![cfg_attr(bootstrap, feature(extended_key_value_attributes))]
+#![feature(float_interpolation)]
 #![feature(fn_traits)]
 #![feature(format_args_nl)]
 #![feature(gen_future)]
 #![feature(global_asm)]
 #![feature(hashmap_internals)]
 #![feature(int_error_internals)]
-#![feature(int_error_matching)]
 #![feature(integer_atomics)]
+#![feature(int_log)]
 #![feature(into_future)]
 #![feature(intra_doc_pointers)]
 #![feature(iter_zip)]
 #![feature(log_syntax)]
 #![feature(map_try_insert)]
 #![feature(maybe_uninit_extra)]
-#![feature(maybe_uninit_ref)]
 #![feature(maybe_uninit_slice)]
 #![feature(maybe_uninit_uninit_array)]
 #![feature(min_specialization)]
 #![feature(nll)]
 #![feature(nonnull_slice_from_raw_parts)]
 #![feature(once_cell)]
-#![feature(auto_traits)]
 #![feature(panic_info_message)]
 #![feature(panic_internals)]
 #![feature(panic_unwind)]
 #![feature(pin_static_ref)]
-#![feature(prelude_2021)]
 #![feature(prelude_import)]
 #![feature(ptr_internals)]
-#![feature(raw)]
 #![feature(ready_macro)]
 #![feature(rustc_attrs)]
 #![feature(rustc_private)]
 #![feature(unboxed_closures)]
 #![feature(unsafe_cell_raw_get)]
 #![feature(unwind_attributes)]
+#![feature(unwrap_infallible)]
 #![feature(vec_into_raw_parts)]
 #![feature(vec_spare_capacity)]
 // NB: the above list is sorted to minimize merge conflicts.
@@ -456,9 +455,6 @@ pub use core::pin;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::ptr;
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated, deprecated_in_future)]
-pub use core::raw;
-#[stable(feature = "rust1", since = "1.0.0")]
 pub use core::result;
 #[unstable(feature = "async_stream", issue = "79024")]
 pub use core::stream;
@@ -560,9 +556,9 @@ pub use core::{
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow(deprecated)]
 pub use core::{
-    asm, assert, assert_matches, cfg, column, compile_error, concat, concat_idents, env, file,
-    format_args, format_args_nl, global_asm, include, include_bytes, include_str, line, llvm_asm,
-    log_syntax, module_path, option_env, stringify, trace_macros,
+    assert, assert_matches, cfg, column, compile_error, concat, concat_idents, env, file,
+    format_args, format_args_nl, include, include_bytes, include_str, line, llvm_asm, log_syntax,
+    module_path, option_env, stringify, trace_macros,
 };
 
 #[stable(feature = "core_primitive", since = "1.43.0")]
index b2c5df5410dcab9fa484fc654722a5241a1c9315..7afe52a3fd693ccf2cec1d69901eb4ba3df56135 100644 (file)
@@ -6,7 +6,8 @@
 
 #[doc = include_str!("../../core/src/macros/panic.md")]
 #[macro_export]
-#[rustc_builtin_macro = "std_panic"]
+#[cfg_attr(bootstrap, rustc_builtin_macro = "std_panic")]
+#[cfg_attr(not(bootstrap), rustc_builtin_macro(std_panic))]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable(edition_panic)]
 #[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_macro")]
index 2b6d0d7d5daa74aa2fb5694913ad3a53c222ccb7..4b6d60d121e13538e1c74c72ca3fcec0bb03f47f 100644 (file)
@@ -379,7 +379,7 @@ impl Ipv4Addr {
     /// This property is defined in _UNIX Network Programming, Second Edition_,
     /// W. Richard Stevens, p. 891; see also [ip7].
     ///
-    /// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html
+    /// [ip7]: https://man7.org/linux/man-pages/man7/ip.7.html
     ///
     /// # Examples
     ///
@@ -1346,47 +1346,6 @@ impl Ipv6Addr {
         (self.segments()[0] & 0xffc0) == 0xfe80
     }
 
-    /// Returns [`true`] if this is a deprecated unicast site-local address (`fec0::/10`). The
-    /// unicast site-local address format is defined in [RFC 4291 section 2.5.7] as:
-    ///
-    /// ```no_rust
-    /// |   10     |
-    /// |  bits    |         54 bits         |         64 bits            |
-    /// +----------+-------------------------+----------------------------+
-    /// |1111111011|        subnet ID        |       interface ID         |
-    /// +----------+-------------------------+----------------------------+
-    /// ```
-    ///
-    /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    ///
-    /// use std::net::Ipv6Addr;
-    ///
-    /// assert_eq!(
-    ///     Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(),
-    ///     false
-    /// );
-    /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true);
-    /// ```
-    ///
-    /// # Warning
-    ///
-    /// As per [RFC 3879], the whole `fec0::/10` prefix is
-    /// deprecated. New software must not support site-local
-    /// addresses.
-    ///
-    /// [RFC 3879]: https://tools.ietf.org/html/rfc3879
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[inline]
-    pub const fn is_unicast_site_local(&self) -> bool {
-        (self.segments()[0] & 0xffc0) == 0xfec0
-    }
-
     /// Returns [`true`] if this is an address reserved for documentation
     /// (`2001:db8::/32`).
     ///
index 05f8dea0b7cb1436f2ea924441dd556856b6c98d..2109980ad058d848970ee351c4ef74a22967a6a8 100644 (file)
@@ -480,7 +480,6 @@ fn ipv6_properties() {
             let unique_local: u16 = 1 << 2;
             let global: u16 = 1 << 3;
             let unicast_link_local: u16 = 1 << 4;
-            let unicast_site_local: u16 = 1 << 6;
             let unicast_global: u16 = 1 << 7;
             let documentation: u16 = 1 << 8;
             let multicast_interface_local: u16 = 1 << 9;
@@ -523,11 +522,6 @@ fn ipv6_properties() {
             } else {
                 assert!(!ip!($s).is_unicast_link_local());
             }
-            if ($mask & unicast_site_local) == unicast_site_local {
-                assert!(ip!($s).is_unicast_site_local());
-            } else {
-                assert!(!ip!($s).is_unicast_site_local());
-            }
             if ($mask & unicast_global) == unicast_global {
                 assert!(ip!($s).is_unicast_global());
             } else {
@@ -581,7 +575,6 @@ fn ipv6_properties() {
     let unique_local: u16 = 1 << 2;
     let global: u16 = 1 << 3;
     let unicast_link_local: u16 = 1 << 4;
-    let unicast_site_local: u16 = 1 << 6;
     let unicast_global: u16 = 1 << 7;
     let documentation: u16 = 1 << 8;
     let multicast_interface_local: u16 = 1 << 9;
@@ -651,7 +644,7 @@ fn ipv6_properties() {
     check!(
         "fec0::",
         &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        unicast_site_local | unicast_global | global
+        unicast_global | global
     );
 
     check!(
@@ -889,9 +882,6 @@ fn ipv6_const() {
     const IS_UNICAST_LINK_LOCAL: bool = IP_ADDRESS.is_unicast_link_local();
     assert!(!IS_UNICAST_LINK_LOCAL);
 
-    const IS_UNICAST_SITE_LOCAL: bool = IP_ADDRESS.is_unicast_site_local();
-    assert!(!IS_UNICAST_SITE_LOCAL);
-
     const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation();
     assert!(!IS_DOCUMENTATION);
 
index abe9bc24cecb061fe571131575d8af206ddbe970..387a3617e5e9a9de55bc567d5d8c74acef196e27 100644 (file)
@@ -342,7 +342,7 @@ fn double_bind() {
             Err(e) => {
                 assert!(
                     e.kind() == ErrorKind::ConnectionRefused
-                        || e.kind() == ErrorKind::Other
+                        || e.kind() == ErrorKind::Uncategorized
                         || e.kind() == ErrorKind::AddrInUse,
                     "unknown error: {} {:?}",
                     e,
index 0f1c59626859411ee501d47abe7715d19c63ff02..e7051f0ce95b24e2610fd14a92c31b7fb6b3bdb5 100644 (file)
@@ -22,12 +22,7 @@ pub use core::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8,
 #[stable(feature = "nonzero", since = "1.28.0")]
 pub use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
 
-#[unstable(
-    feature = "int_error_matching",
-    reason = "it can be useful to match errors when making error messages \
-              for integer parsing",
-    issue = "22639"
-)]
+#[stable(feature = "int_error_matching", since = "1.55.0")]
 pub use core::num::IntErrorKind;
 
 #[cfg(test)]
index b0170e67446db4c5cb659c39bfa5ba9468aed2c7..4ce482e23cbfb98e80f1d256b08994a7b69babe1 100644 (file)
@@ -33,13 +33,13 @@ pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32>
 
         asm!(
             // rbx is reserved by LLVM
-            "xchg {0}, rbx",
+            "xchg %rbx, {0}",
             "enclu",
-            "mov rbx, {0}",
+            "mov {0}, %rbx",
             inout(reg) request => _,
             inlateout("eax") ENCLU_EGETKEY => error,
             in("rcx") out.as_mut_ptr(),
-            options(nostack),
+            options(att_syntax, nostack),
         );
 
         match error {
@@ -64,14 +64,14 @@ pub fn ereport(
 
         asm!(
             // rbx is reserved by LLVM
-            "xchg {0}, rbx",
+            "xchg %rbx, {0}",
             "enclu",
-            "mov rbx, {0}",
+            "mov {0}, %rbx",
             inout(reg) targetinfo => _,
             in("eax") ENCLU_EREPORT,
             in("rcx") reportdata,
             in("rdx") report.as_mut_ptr(),
-            options(preserves_flags, nostack),
+            options(att_syntax, preserves_flags, nostack),
         );
 
         report.assume_init()
index 63fc5ff2866a81c1b7f3e0de1d0c4d259199ef25..ac1db0e5e39cc2edb181fb70fc5bcadfe7ec532a 100644 (file)
@@ -34,5 +34,8 @@
 
 #![unstable(feature = "sgx_platform", issue = "56975")]
 
+#[path = "../unix/ffi/os_str.rs"]
+mod os_str;
+
 #[unstable(feature = "sgx_platform", issue = "56975")]
-pub use crate::sys_common::os_str_bytes::*;
+pub use self::os_str::{OsStrExt, OsStringExt};
index 07b59a02556d9f3e8ea80c4b941c593219c5b2af..19761fd99b400f3cee75b55c855bc5b5e567757f 100644 (file)
@@ -34,5 +34,8 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+#[path = "../unix/ffi/os_str.rs"]
+mod os_str;
+
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::sys_common::os_str_bytes::*;
+pub use self::os_str::{OsStrExt, OsStringExt};
diff --git a/library/std/src/os/unix/ffi.rs b/library/std/src/os/unix/ffi.rs
deleted file mode 100644 (file)
index 123f85d..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-//! Unix-specific extension to the primitives in the `std::ffi` module.
-//!
-//! # Examples
-//!
-//! ```
-//! use std::ffi::OsString;
-//! use std::os::unix::ffi::OsStringExt;
-//!
-//! let bytes = b"foo".to_vec();
-//!
-//! // OsStringExt::from_vec
-//! let os_string = OsString::from_vec(bytes);
-//! assert_eq!(os_string.to_str(), Some("foo"));
-//!
-//! // OsStringExt::into_vec
-//! let bytes = os_string.into_vec();
-//! assert_eq!(bytes, b"foo");
-//! ```
-//!
-//! ```
-//! use std::ffi::OsStr;
-//! use std::os::unix::ffi::OsStrExt;
-//!
-//! let bytes = b"foo";
-//!
-//! // OsStrExt::from_bytes
-//! let os_str = OsStr::from_bytes(bytes);
-//! assert_eq!(os_str.to_str(), Some("foo"));
-//!
-//! // OsStrExt::as_bytes
-//! let bytes = os_str.as_bytes();
-//! assert_eq!(bytes, b"foo");
-//! ```
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::sys_common::os_str_bytes::*;
diff --git a/library/std/src/os/unix/ffi/mod.rs b/library/std/src/os/unix/ffi/mod.rs
new file mode 100644 (file)
index 0000000..c29df65
--- /dev/null
@@ -0,0 +1,40 @@
+//! Unix-specific extension to the primitives in the `std::ffi` module.
+//!
+//! # Examples
+//!
+//! ```
+//! use std::ffi::OsString;
+//! use std::os::unix::ffi::OsStringExt;
+//!
+//! let bytes = b"foo".to_vec();
+//!
+//! // OsStringExt::from_vec
+//! let os_string = OsString::from_vec(bytes);
+//! assert_eq!(os_string.to_str(), Some("foo"));
+//!
+//! // OsStringExt::into_vec
+//! let bytes = os_string.into_vec();
+//! assert_eq!(bytes, b"foo");
+//! ```
+//!
+//! ```
+//! use std::ffi::OsStr;
+//! use std::os::unix::ffi::OsStrExt;
+//!
+//! let bytes = b"foo";
+//!
+//! // OsStrExt::from_bytes
+//! let os_str = OsStr::from_bytes(bytes);
+//! assert_eq!(os_str.to_str(), Some("foo"));
+//!
+//! // OsStrExt::as_bytes
+//! let bytes = os_str.as_bytes();
+//! assert_eq!(bytes, b"foo");
+//! ```
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+mod os_str;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::os_str::{OsStrExt, OsStringExt};
diff --git a/library/std/src/os/unix/ffi/os_str.rs b/library/std/src/os/unix/ffi/os_str.rs
new file mode 100644 (file)
index 0000000..54c9a93
--- /dev/null
@@ -0,0 +1,68 @@
+use crate::ffi::{OsStr, OsString};
+use crate::mem;
+use crate::sealed::Sealed;
+use crate::sys::os_str::Buf;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+
+// Note: this file is currently reused in other `std::os::{platform}::ffi` modules to reduce duplication.
+// Keep this in mind when applying changes to this file that only apply to `unix`.
+
+/// Platform-specific extensions to [`OsString`].
+///
+/// This trait is sealed: it cannot be implemented outside the standard library.
+/// This is so that future additional methods are not breaking changes.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait OsStringExt: Sealed {
+    /// Creates an [`OsString`] from a byte vector.
+    ///
+    /// See the module documentation for an example.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn from_vec(vec: Vec<u8>) -> Self;
+
+    /// Yields the underlying byte vector of this [`OsString`].
+    ///
+    /// See the module documentation for an example.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn into_vec(self) -> Vec<u8>;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl OsStringExt for OsString {
+    fn from_vec(vec: Vec<u8>) -> OsString {
+        FromInner::from_inner(Buf { inner: vec })
+    }
+    fn into_vec(self) -> Vec<u8> {
+        self.into_inner().inner
+    }
+}
+
+/// Platform-specific extensions to [`OsStr`].
+///
+/// This trait is sealed: it cannot be implemented outside the standard library.
+/// This is so that future additional methods are not breaking changes.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait OsStrExt: Sealed {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    /// Creates an [`OsStr`] from a byte slice.
+    ///
+    /// See the module documentation for an example.
+    fn from_bytes(slice: &[u8]) -> &Self;
+
+    /// Gets the underlying byte view of the [`OsStr`] slice.
+    ///
+    /// See the module documentation for an example.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn as_bytes(&self) -> &[u8];
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl OsStrExt for OsStr {
+    #[inline]
+    fn from_bytes(slice: &[u8]) -> &OsStr {
+        unsafe { mem::transmute(slice) }
+    }
+    #[inline]
+    fn as_bytes(&self) -> &[u8] {
+        &self.as_inner().inner
+    }
+}
index 913c71d41087951b5d2ef41079fec089a6ebe821..e4ce788f74195cbcdf843367709412004dd4c2c5 100644 (file)
@@ -9,6 +9,8 @@ use crate::path::Path;
 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 @@ impl DirEntryExt for fs::DirEntry {
     }
 }
 
+/// 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 15ce7056fea3489a5a6ee789d8127a3e7222e659..cd429d1426937e60dff18ce8ad96af2e5ac27fed 100644 (file)
@@ -32,23 +32,8 @@ pub(super) fn recv_vectored_with_ancillary_from(
         msg.msg_name = &mut msg_name as *mut _ as *mut _;
         msg.msg_namelen = size_of::<libc::sockaddr_un>() as libc::socklen_t;
         msg.msg_iov = bufs.as_mut_ptr().cast();
-        cfg_if::cfg_if! {
-            if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
-                msg.msg_iovlen = bufs.len() as libc::size_t;
-                msg.msg_controllen = ancillary.buffer.len() as libc::size_t;
-            } else if #[cfg(any(
-                          target_os = "dragonfly",
-                          target_os = "emscripten",
-                          target_os = "freebsd",
-                          all(target_os = "linux", target_env = "musl",),
-                          target_os = "macos",
-                          target_os = "netbsd",
-                          target_os = "openbsd",
-                      ))] {
-                msg.msg_iovlen = bufs.len() as libc::c_int;
-                msg.msg_controllen = ancillary.buffer.len() as libc::socklen_t;
-            }
-        }
+        msg.msg_iovlen = bufs.len() as _;
+        msg.msg_controllen = ancillary.buffer.len() as _;
         // macos requires that the control pointer is null when the len is 0.
         if msg.msg_controllen > 0 {
             msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
@@ -80,23 +65,8 @@ pub(super) fn send_vectored_with_ancillary_to(
         msg.msg_name = &mut msg_name as *mut _ as *mut _;
         msg.msg_namelen = msg_namelen;
         msg.msg_iov = bufs.as_ptr() as *mut _;
-        cfg_if::cfg_if! {
-            if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
-                msg.msg_iovlen = bufs.len() as libc::size_t;
-                msg.msg_controllen = ancillary.length as libc::size_t;
-            } else if #[cfg(any(
-                          target_os = "dragonfly",
-                          target_os = "emscripten",
-                          target_os = "freebsd",
-                          all(target_os = "linux", target_env = "musl",),
-                          target_os = "macos",
-                          target_os = "netbsd",
-                          target_os = "openbsd",
-                      ))] {
-                msg.msg_iovlen = bufs.len() as libc::c_int;
-                msg.msg_controllen = ancillary.length as libc::socklen_t;
-            }
-        }
+        msg.msg_iovlen = bufs.len() as _;
+        msg.msg_controllen = ancillary.length as _;
         // macos requires that the control pointer is null when the len is 0.
         if msg.msg_controllen > 0 {
             msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
@@ -144,21 +114,7 @@ fn add_to_ancillary_data<T>(
 
         let mut msg: libc::msghdr = zeroed();
         msg.msg_control = buffer.as_mut_ptr().cast();
-        cfg_if::cfg_if! {
-            if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
-                msg.msg_controllen = *length as libc::size_t;
-            } else if #[cfg(any(
-                          target_os = "dragonfly",
-                          target_os = "emscripten",
-                          target_os = "freebsd",
-                          all(target_os = "linux", target_env = "musl",),
-                          target_os = "macos",
-                          target_os = "netbsd",
-                          target_os = "openbsd",
-                      ))] {
-                msg.msg_controllen = *length as libc::socklen_t;
-            }
-        }
+        msg.msg_controllen = *length as _;
 
         let mut cmsg = libc::CMSG_FIRSTHDR(&msg);
         let mut previous_cmsg = cmsg;
@@ -180,21 +136,7 @@ fn add_to_ancillary_data<T>(
 
         (*previous_cmsg).cmsg_level = cmsg_level;
         (*previous_cmsg).cmsg_type = cmsg_type;
-        cfg_if::cfg_if! {
-            if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
-                (*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as libc::size_t;
-            } else if #[cfg(any(
-                          target_os = "dragonfly",
-                          target_os = "emscripten",
-                          target_os = "freebsd",
-                          all(target_os = "linux", target_env = "musl",),
-                          target_os = "macos",
-                          target_os = "netbsd",
-                          target_os = "openbsd",
-                      ))] {
-                (*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as libc::socklen_t;
-            }
-        }
+        (*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as _;
 
         let data = libc::CMSG_DATA(previous_cmsg).cast();
 
@@ -364,28 +306,10 @@ impl<'a> AncillaryData<'a> {
 
     fn try_from_cmsghdr(cmsg: &'a libc::cmsghdr) -> Result<Self, AncillaryError> {
         unsafe {
-            cfg_if::cfg_if! {
-                if #[cfg(any(
-                        target_os = "android",
-                        all(target_os = "linux", target_env = "gnu"),
-                        all(target_os = "linux", target_env = "uclibc"),
-                   ))] {
-                    let cmsg_len_zero = libc::CMSG_LEN(0) as libc::size_t;
-                } else if #[cfg(any(
-                              target_os = "dragonfly",
-                              target_os = "emscripten",
-                              target_os = "freebsd",
-                              all(target_os = "linux", target_env = "musl",),
-                              target_os = "macos",
-                              target_os = "netbsd",
-                              target_os = "openbsd",
-                          ))] {
-                    let cmsg_len_zero = libc::CMSG_LEN(0) as libc::socklen_t;
-                }
-            }
-            let data_len = (*cmsg).cmsg_len - cmsg_len_zero;
+            let cmsg_len_zero = libc::CMSG_LEN(0) as usize;
+            let data_len = (*cmsg).cmsg_len as usize - cmsg_len_zero;
             let data = libc::CMSG_DATA(cmsg).cast();
-            let data = from_raw_parts(data, data_len as usize);
+            let data = from_raw_parts(data, data_len);
 
             match (*cmsg).cmsg_level {
                 libc::SOL_SOCKET => match (*cmsg).cmsg_type {
@@ -419,21 +343,7 @@ impl<'a> Iterator for Messages<'a> {
         unsafe {
             let mut msg: libc::msghdr = zeroed();
             msg.msg_control = self.buffer.as_ptr() as *mut _;
-            cfg_if::cfg_if! {
-                if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
-                    msg.msg_controllen = self.buffer.len() as libc::size_t;
-                } else if #[cfg(any(
-                              target_os = "dragonfly",
-                              target_os = "emscripten",
-                              target_os = "freebsd",
-                              all(target_os = "linux", target_env = "musl",),
-                              target_os = "macos",
-                              target_os = "netbsd",
-                              target_os = "openbsd",
-                          ))] {
-                    msg.msg_controllen = self.buffer.len() as libc::socklen_t;
-                }
-            }
+            msg.msg_controllen = self.buffer.len() as _;
 
             let cmsg = if let Some(current) = self.current {
                 libc::CMSG_NXTHDR(&msg, current)
index 3dc389b7582f702a4f5b1aea51eea6f93c93a0a7..f3b5227df869df2f17644767897383282d89959a 100644 (file)
@@ -226,7 +226,7 @@ pub trait ExitStatusExt: Sealed {
     ///
     /// Panics on an attempt to make an `ExitStatusError` from a wait status of `0`.
     ///
-    /// Making an `ExitStatus` always succeds and never panics.
+    /// Making an `ExitStatus` always succeeds and never panics.
     #[stable(feature = "exit_status_from", since = "1.12.0")]
     fn from_raw(raw: i32) -> Self;
 
index f71f316d1ba1088b8667d495bfe401f674badde7..17e12a395a67047529abcaafb412c76fa556911c 100644 (file)
@@ -2,5 +2,8 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+#[path = "../unix/ffi/os_str.rs"]
+mod os_str;
+
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::sys_common::os_str_bytes::*;
+pub use self::os_str::{OsStrExt, OsStringExt};
index ba4057bd34ca2c13881a888d2ebebe16deaefa35..bd30d6ae3f333daa87cff4d7270ad7d1a02a0bd9 100644 (file)
@@ -1,7 +1,7 @@
 //! WASI-specific extensions to primitives in the `std::fs` module.
 
 #![deny(unsafe_op_in_unsafe_fn)]
-#![unstable(feature = "wasi_ext", issue = "none")]
+#![unstable(feature = "wasi_ext", issue = "71213")]
 
 use crate::ffi::OsStr;
 use crate::fs::{self, File, Metadata, OpenOptions};
@@ -532,5 +532,6 @@ pub fn symlink_path<P: AsRef<Path>, U: AsRef<Path>>(old_path: P, new_path: U) ->
 }
 
 fn osstr2str(f: &OsStr) -> io::Result<&str> {
-    f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8"))
+    f.to_str()
+        .ok_or_else(|| io::Error::new_const(io::ErrorKind::Uncategorized, &"input must be utf-8"))
 }
index b2e79cc1b4a9d59c59d680e2f22aa038c0f1d97f..cf4501b98cbd42eb43a4e0c1ce098fcc2ecb9cd7 100644 (file)
@@ -1,7 +1,7 @@
 //! WASI-specific extensions to general I/O primitives
 
 #![deny(unsafe_op_in_unsafe_fn)]
-#![unstable(feature = "wasi_ext", issue = "none")]
+#![unstable(feature = "wasi_ext", issue = "71213")]
 
 use crate::fs;
 use crate::io;
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 @@ impl CommandExt for 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 9e3880dfd4105caf2579086bbceecc49df7d95e4..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(all(not(bootstrap), 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 auto trait UnwindSafe {}
 /// 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(all(not(bootstrap), 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 ede147aca12e006769c35469b2c1b25690217de9..c71751efb9f9aa3a9e421b3163e8c36195bf6103 100644 (file)
@@ -951,7 +951,7 @@ impl FusedIterator for Components<'_> {}
 impl<'a> cmp::PartialEq for Components<'a> {
     #[inline]
     fn eq(&self, other: &Components<'a>) -> bool {
-        Iterator::eq(self.clone(), other.clone())
+        Iterator::eq(self.clone().rev(), other.clone().rev())
     }
 }
 
@@ -2592,6 +2592,32 @@ impl Path {
         fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
     }
 
+    /// Returns true if the path exists on disk and is pointing at a symbolic link.
+    ///
+    /// This function will not traverse symbolic links.
+    /// In case of a broken symbolic link this will also return true.
+    ///
+    /// If you cannot access the directory containing the file, e.g., because of a
+    /// permission error, this will return false.
+    ///
+    /// # Examples
+    ///
+    #[cfg_attr(unix, doc = "```no_run")]
+    #[cfg_attr(not(unix), doc = "```ignore")]
+    /// #![feature(is_symlink)]
+    /// use std::path::Path;
+    /// use std::os::unix::fs::symlink;
+    ///
+    /// let link_path = Path::new("link");
+    /// symlink("/origin_does_not_exists/", link_path).unwrap();
+    /// assert_eq!(link_path.is_symlink(), true);
+    /// assert_eq!(link_path.exists(), false);
+    /// ```
+    #[unstable(feature = "is_symlink", issue = "85748")]
+    pub fn is_symlink(&self) -> bool {
+        fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false)
+    }
+
     /// Converts a [`Box<Path>`](Box) into a [`PathBuf`] without copying or
     /// allocating.
     #[stable(feature = "into_boxed_path", since = "1.20.0")]
index 12d52cc8e0b223cb916920ae0ee3e8eef86b24e8..d4bf6aeefee57279bdf2375969bab5efd6949bdf 100644 (file)
 //!
 //! # Prelude contents
 //!
-//! The current version of the prelude (version 1) lives in
-//! [`std::prelude::v1`], and re-exports the following:
+//! The first version of the prelude is used in Rust 2015 and Rust 2018,
+//! and lives in [`std::prelude::v1`].
+//! [`std::prelude::rust_2015`] and [`std::prelude::rust_2018`] re-export this prelude.
+//! It re-exports the following:
 //!
 //! * <code>[std::marker]::{[Copy], [Send], [Sized], [Sync], [Unpin]}</code>,
 //!   marker traits that indicate fundamental properties of types.
 //! * <code>[std::string]::{[String], [ToString]}</code>, heap-allocated strings.
 //! * <code>[std::vec]::[Vec]</code>, a growable, heap-allocated vector.
 //!
+//! The prelude used in Rust 2021, [`std::prelude::rust_2021`], includes all of the above,
+//! and in addition re-exports:
+//!
+//! * <code>[std::convert]::{[TryFrom], [TryInto]}</code>,
+//! * <code>[std::iter]::[FromIterator]</code>.
+//!
 //! [mem::drop]: crate::mem::drop
 //! [std::borrow]: crate::borrow
 //! [std::boxed]: crate::boxed
 //! [std::ops]: crate::ops
 //! [std::option]: crate::option
 //! [`std::prelude::v1`]: v1
+//! [`std::prelude::rust_2015`]: rust_2015
+//! [`std::prelude::rust_2018`]: rust_2018
+//! [`std::prelude::rust_2021`]: rust_2021
 //! [std::result]: crate::result
 //! [std::slice]: crate::slice
 //! [std::string]: crate::string
 //! [std::vec]: mod@crate::vec
+//! [TryFrom]: crate::convert::TryFrom
+//! [TryInto]: crate::convert::TryInto
+//! [FromIterator]: crate::iter::FromIterator
 //! [`to_owned`]: crate::borrow::ToOwned::to_owned
 //! [book-closures]: ../../book/ch13-01-closures.html
 //! [book-dtor]: ../../book/ch15-03-drop.html
@@ -88,9 +102,9 @@ pub mod v1;
 /// The 2015 version of the prelude of The Rust Standard Library.
 ///
 /// See the [module-level documentation](self) for more.
-#[unstable(feature = "prelude_2015", issue = "85684")]
+#[stable(feature = "prelude_2015", since = "1.55.0")]
 pub mod rust_2015 {
-    #[unstable(feature = "prelude_2015", issue = "85684")]
+    #[stable(feature = "prelude_2015", since = "1.55.0")]
     #[doc(no_inline)]
     pub use super::v1::*;
 }
@@ -98,9 +112,9 @@ pub mod rust_2015 {
 /// The 2018 version of the prelude of The Rust Standard Library.
 ///
 /// See the [module-level documentation](self) for more.
-#[unstable(feature = "prelude_2018", issue = "85684")]
+#[stable(feature = "prelude_2018", since = "1.55.0")]
 pub mod rust_2018 {
-    #[unstable(feature = "prelude_2018", issue = "85684")]
+    #[stable(feature = "prelude_2018", since = "1.55.0")]
     #[doc(no_inline)]
     pub use super::v1::*;
 }
@@ -108,13 +122,13 @@ pub mod rust_2018 {
 /// The 2021 version of the prelude of The Rust Standard Library.
 ///
 /// See the [module-level documentation](self) for more.
-#[unstable(feature = "prelude_2021", issue = "85684")]
+#[stable(feature = "prelude_2021", since = "1.55.0")]
 pub mod rust_2021 {
-    #[unstable(feature = "prelude_2021", issue = "85684")]
+    #[stable(feature = "prelude_2021", since = "1.55.0")]
     #[doc(no_inline)]
     pub use super::v1::*;
 
-    #[unstable(feature = "prelude_2021", issue = "85684")]
+    #[stable(feature = "prelude_2021", since = "1.55.0")]
     #[doc(no_inline)]
     pub use core::prelude::rust_2021::*;
 }
index 4a3c3ba163598b364d0a9da52a58420653c4c277..772044f0149200684a69855dce455d52a8c8c187 100644 (file)
@@ -39,12 +39,28 @@ pub use crate::result::Result::{self, Err, Ok};
 #[allow(deprecated)]
 #[doc(no_inline)]
 pub use core::prelude::v1::{
-    asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
-    format_args_nl, global_asm, include, include_bytes, include_str, line, llvm_asm, log_syntax,
-    module_path, option_env, stringify, trace_macros, Clone, Copy, Debug, Default, Eq, Hash, Ord,
-    PartialEq, PartialOrd,
+    assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
+    format_args_nl, include, include_bytes, include_str, line, llvm_asm, log_syntax, module_path,
+    option_env, stringify, trace_macros, Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq,
+    PartialOrd,
 };
 
+#[unstable(
+    feature = "asm",
+    issue = "72016",
+    reason = "inline assembly is not stable enough for use and is subject to change"
+)]
+#[doc(no_inline)]
+pub use core::prelude::v1::asm;
+
+#[unstable(
+    feature = "global_asm",
+    issue = "35119",
+    reason = "`global_asm!` is not stable enough for use and is subject to change"
+)]
+#[doc(no_inline)]
+pub use core::prelude::v1::global_asm;
+
 // FIXME: Attribute and internal derive macros are not documented because for them rustdoc generates
 // dead links which fail link checker testing.
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
index 8a3e425350a681a87292485e565640c49df87e8a..7bc1f5e918ec9ab08712c5a047b3df94793f195c 100644 (file)
@@ -277,8 +277,8 @@ mod prim_never {}
 /// scalar value]', which is similar to, but not the same as, a '[Unicode code
 /// point]'.
 ///
-/// [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
-/// [Unicode code point]: http://www.unicode.org/glossary/#code_point
+/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
+/// [Unicode code point]: https://www.unicode.org/glossary/#code_point
 ///
 /// This documentation describes a number of methods and trait implementations on the
 /// `char` type. For technical reasons, there is additional, separate
index 6903ba9056089fba54d1af9c0df9da20740cb2d4..11a0432ce27a1ebb91e8f90724cfe87fd694a783 100644 (file)
@@ -452,7 +452,7 @@ impl fmt::Debug for ChildStderr {
 ///
 /// let output = if cfg!(target_os = "windows") {
 ///     Command::new("cmd")
-///             .args(&["/C", "echo hello"])
+///             .args(["/C", "echo hello"])
 ///             .output()
 ///             .expect("failed to execute process")
 /// } else {
@@ -609,7 +609,7 @@ impl Command {
     /// use std::process::Command;
     ///
     /// Command::new("ls")
-    ///         .args(&["-l", "-a"])
+    ///         .args(["-l", "-a"])
     ///         .spawn()
     ///         .expect("ls command failed to start");
     /// ```
@@ -1568,7 +1568,7 @@ impl ExitStatusError {
 
     /// Reports the exit code, if applicable, from an `ExitStatusError`, as a `NonZero`
     ///
-    /// This is exaclty like [`code()`](Self::code), except that it returns a `NonZeroI32`.
+    /// This is exactly like [`code()`](Self::code), except that it returns a `NonZeroI32`.
     ///
     /// Plain `code`, returning a plain integer, is provided because is is often more convenient.
     /// The returned value from `code()` is indeed also nonzero; use `code_nonzero()` when you want
@@ -1658,8 +1658,7 @@ impl Child {
     /// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
     /// error is returned.
     ///
-    /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function,
-    /// especially the [`Other`] kind might change to more specific kinds in the future.
+    /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function.
     ///
     /// This is equivalent to sending a SIGKILL on Unix platforms.
     ///
@@ -1680,7 +1679,6 @@ impl Child {
     ///
     /// [`ErrorKind`]: io::ErrorKind
     /// [`InvalidInput`]: io::ErrorKind::InvalidInput
-    /// [`Other`]: io::ErrorKind::Other
     #[stable(feature = "process", since = "1.0.0")]
     pub fn kill(&mut self) -> io::Result<()> {
         self.handle.kill()
@@ -1900,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
@@ -1910,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 05e093434be1bf57f306e34bdbd96b5a76bad9df..bc71c150550a4080a0ad6f51e945a7cef6698460 100644 (file)
@@ -399,3 +399,12 @@ fn test_command_implements_send_sync() {
     fn take_send_sync_type<T: Send + Sync>(_: T) {}
     take_send_sync_type(Command::new(""))
 }
+
+// Ensure that starting a process with no environment variables works on Windows.
+// This will fail if the environment block is ill-formed.
+#[test]
+#[cfg(windows)]
+fn env_empty() {
+    let p = Command::new("cmd").args(&["/C", "exit 0"]).env_clear().spawn();
+    assert!(p.is_ok());
+}
index 1e19aff51f8d6bb8054298096333b013590490f1..72e6c23ee49907a5b1b760577518ead2d7680ffb 100644 (file)
@@ -24,18 +24,32 @@ fn lang_start_internal(
     main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe),
     argc: isize,
     argv: *const *const u8,
-) -> isize {
-    use crate::panic;
-    use crate::sys_common;
-
+) -> Result<isize, !> {
+    use crate::{mem, panic, sys, sys_common};
+    let rt_abort = move |e| {
+        mem::forget(e);
+        rtabort!("initialization or cleanup bug");
+    };
+    // Guard against the code called by this function from unwinding outside of the Rust-controlled
+    // code, which is UB. This is a requirement imposed by a combination of how the
+    // `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking
+    // mechanism itself.
+    //
+    // There are a couple of instances where unwinding can begin. First is inside of the
+    // `rt::init`, `rt::cleanup` and similar functions controlled by libstd. In those instances a
+    // panic is a libstd implementation bug. A quite likely one too, as there isn't any way to
+    // prevent libstd from accidentally introducing a panic to these functions. Another is from
+    // user code from `main` or, more nefariously, as described in e.g. issue #86030.
     // SAFETY: Only called once during runtime initialization.
-    unsafe { sys_common::rt::init(argc, argv) };
-
-    let exit_code = panic::catch_unwind(main);
-
-    sys_common::rt::cleanup();
-
-    exit_code.unwrap_or(101) as isize
+    panic::catch_unwind(move || unsafe { sys_common::rt::init(argc, argv) }).map_err(rt_abort)?;
+    let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize)
+        .map_err(move |e| {
+            mem::forget(e);
+            rtprintpanic!("drop of the panic payload panicked");
+            sys::abort_internal()
+        });
+    panic::catch_unwind(sys_common::rt::cleanup).map_err(rt_abort)?;
+    ret_code
 }
 
 #[cfg(not(test))]
@@ -50,4 +64,5 @@ fn lang_start<T: crate::process::Termination + 'static>(
         argc,
         argv,
     )
+    .into_ok()
 }
index ea1d598d26461b4b10f1f3058f150b2e506c2bd9..b4f4456537b9693f41b56df9208e5588ce4f88ab 100644 (file)
 //! });
 //! rx.recv().unwrap();
 //! ```
+//!
+//! Unbounded receive loop:
+//!
+//! ```
+//! use std::sync::mpsc::sync_channel;
+//! use std::thread;
+//!
+//! let (tx, rx) = sync_channel(3);
+//!
+//! for _ in 0..3 {
+//!     // It would be the same without thread and clone here
+//!     // since there will still be one `tx` left.
+//!     let tx = tx.clone();
+//!     // cloned tx dropped within thread
+//!     thread::spawn(move || tx.send("ok").unwrap());
+//! }
+//!
+//! // Drop the last sender to stop `rx` waiting for message.
+//! // The program will not complete if we comment this out.
+//! // **All** `tx` needs to be dropped for `rx` to have `Err`.
+//! drop(tx);
+//!
+//! // Unbounded receiver waiting for all senders to complete.
+//! while let Ok(msg) = rx.recv() {
+//!     println!("{}", msg);
+//! }
+//!
+//! println!("completed");
+//! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -437,6 +466,9 @@ pub struct IntoIter<T> {
 ///
 /// Messages can be sent through this channel with [`send`].
 ///
+/// Note: all senders (the original and the clones) need to be dropped for the receiver
+/// to stop blocking to receive messages with [`Receiver::recv`].
+///
 /// [`send`]: Sender::send
 ///
 /// # Examples
@@ -643,7 +675,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
 /// the same order as it was sent, and no [`send`] will block the calling thread
 /// (this channel has an "infinite buffer", unlike [`sync_channel`], which will
 /// block after its buffer limit is reached). [`recv`] will block until a message
-/// is available.
+/// is available while there is at least one [`Sender`] alive (including clones).
 ///
 /// The [`Sender`] can be cloned to [`send`] to the same channel multiple times, but
 /// only one [`Receiver`] is supported.
@@ -806,6 +838,11 @@ impl<T> Sender<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Clone for Sender<T> {
+    /// Clone a sender to send to other threads.
+    ///
+    /// Note, be aware of the lifetime of the sender because all senders
+    /// (including the original) need to be dropped in order for
+    /// [`Receiver::recv`] to stop blocking.
     fn clone(&self) -> Sender<T> {
         let packet = match *unsafe { self.inner() } {
             Flavor::Oneshot(ref p) => {
@@ -1064,9 +1101,10 @@ impl<T> Receiver<T> {
     /// corresponding channel has hung up.
     ///
     /// This function will always block the current thread if there is no data
-    /// available and it's possible for more data to be sent. Once a message is
-    /// sent to the corresponding [`Sender`] (or [`SyncSender`]), then this
-    /// receiver will wake up and return that message.
+    /// available and it's possible for more data to be sent (at least one sender
+    /// still exists). Once a message is sent to the corresponding [`Sender`]
+    /// (or [`SyncSender`]), this receiver will wake up and return that
+    /// message.
     ///
     /// If the corresponding [`Sender`] has disconnected, or it disconnects while
     /// this call is blocking, this call will wake up and return [`Err`] to
@@ -1146,9 +1184,10 @@ impl<T> Receiver<T> {
     /// corresponding channel has hung up, or if it waits more than `timeout`.
     ///
     /// This function will always block the current thread if there is no data
-    /// available and it's possible for more data to be sent. Once a message is
-    /// sent to the corresponding [`Sender`] (or [`SyncSender`]), then this
-    /// receiver will wake up and return that message.
+    /// available and it's possible for more data to be sent (at least one sender
+    /// still exists). Once a message is sent to the corresponding [`Sender`]
+    /// (or [`SyncSender`]), this receiver will wake up and return that
+    /// message.
     ///
     /// If the corresponding [`Sender`] has disconnected, or it disconnects while
     /// this call is blocking, this call will wake up and return [`Err`] to
index 42bc639dc252784fc8f864bafa91696c2cb82af8..b93eb056da4f6cbf7e92ade8dd27d4d073c35c94 100644 (file)
@@ -8,8 +8,8 @@
 //! method, and see the method for more information about it. Due to this
 //! caveat, this queue may not be appropriate for all use-cases.
 
-// http://www.1024cores.net/home/lock-free-algorithms
-//                         /queues/non-intrusive-mpsc-node-based-queue
+// https://www.1024cores.net/home/lock-free-algorithms
+//                          /queues/non-intrusive-mpsc-node-based-queue
 
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
index 9bf99f193ca3ae0707212defb1d0a241de1c04bd..7e745eb31de60d61fe6edada4dd1a508e29549f3 100644 (file)
@@ -4,7 +4,7 @@
 //! concurrently between two threads. This data structure is safe to use and
 //! enforces the semantics that there is one pusher and one popper.
 
-// http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
+// https://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
 
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
index e7c5479ab9bb6fa59fd621adab13c5b0ddbc0de5..e1d6324c17e336e021714b71f5ae6bd34cfb7784 100644 (file)
@@ -217,26 +217,6 @@ impl<T> Mutex<T> {
             data: UnsafeCell::new(t),
         }
     }
-
-    /// Immediately drops the guard, and consequently unlocks the mutex.
-    ///
-    /// This function is equivalent to calling [`drop`] on the guard but is more self-documenting.
-    /// Alternately, the guard will be automatically dropped when it goes out of scope.
-    ///
-    /// ```
-    /// #![feature(mutex_unlock)]
-    ///
-    /// use std::sync::Mutex;
-    /// let mutex = Mutex::new(0);
-    ///
-    /// let mut guard = mutex.lock().unwrap();
-    /// *guard += 20;
-    /// Mutex::unlock(guard);
-    /// ```
-    #[unstable(feature = "mutex_unlock", issue = "81872")]
-    pub fn unlock(guard: MutexGuard<'_, T>) {
-        drop(guard);
-    }
 }
 
 impl<T: ?Sized> Mutex<T> {
@@ -333,6 +313,26 @@ impl<T: ?Sized> Mutex<T> {
         }
     }
 
+    /// Immediately drops the guard, and consequently unlocks the mutex.
+    ///
+    /// This function is equivalent to calling [`drop`] on the guard but is more self-documenting.
+    /// Alternately, the guard will be automatically dropped when it goes out of scope.
+    ///
+    /// ```
+    /// #![feature(mutex_unlock)]
+    ///
+    /// use std::sync::Mutex;
+    /// let mutex = Mutex::new(0);
+    ///
+    /// let mut guard = mutex.lock().unwrap();
+    /// *guard += 20;
+    /// Mutex::unlock(guard);
+    /// ```
+    #[unstable(feature = "mutex_unlock", issue = "81872")]
+    pub fn unlock(guard: MutexGuard<'_, T>) {
+        drop(guard);
+    }
+
     /// Determines whether the mutex is poisoned.
     ///
     /// If another thread is active, the mutex can still become poisoned at any
index 0d00f74eaa1ec839e9356bd729fe7a42b6641ed1..e50d62d8173766fa8fa7a8551c34ccde4f7ec70b 100644 (file)
@@ -23,7 +23,19 @@ use crate::sys_common::rwlock as sys;
 /// system's implementation, and this type does not guarantee that any
 /// particular policy will be used. In particular, a writer which is waiting to
 /// acquire the lock in `write` might or might not block concurrent calls to
-/// `read`.
+/// `read`, e.g.:
+///
+/// <details><summary>Potential deadlock example</summary>
+///
+/// ```text
+/// // Thread 1             |  // Thread 2
+/// let _rg = lock.read();  |
+///                         |  // will block
+///                         |  let _wg = lock.write();
+/// // may deadlock         |
+/// let _rg = lock.read();  |
+/// ```
+/// </details>
 ///
 /// The type parameter `T` represents the data that this lock protects. It is
 /// required that `T` satisfies [`Send`] to be shared across threads and
index 4eb0d8437ba5f5f7ef8ab050689853d5d5738fdb..1c7e1dd8d57787f53747468b8277e7047f522ce3 100644 (file)
@@ -55,8 +55,8 @@ impl DoubleEndedIterator for Args {
 mod imp {
     use super::Args;
     use crate::ffi::{CStr, OsString};
+    use crate::os::unix::ffi::OsStringExt;
     use crate::ptr;
-    use crate::sys_common::os_str_bytes::*;
 
     use crate::sys_common::mutex::StaticMutex;
 
index 76ea70d997f5d7044ed0479354142d45def9b956..be019d4435db59a28e57369d650056818816587f 100644 (file)
@@ -3,6 +3,7 @@ use crate::fmt;
 use crate::hash::{Hash, Hasher};
 use crate::io::{self, Error, ErrorKind};
 use crate::io::{IoSlice, IoSliceMut, SeekFrom};
+use crate::os::unix::ffi::OsStrExt;
 use crate::path::{Path, PathBuf};
 use crate::sys::cvt;
 use crate::sys::hermit::abi;
@@ -10,7 +11,6 @@ use crate::sys::hermit::abi::{O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRU
 use crate::sys::hermit::fd::FileDesc;
 use crate::sys::time::SystemTime;
 use crate::sys::unsupported;
-use crate::sys_common::os_str_bytes::OsStrExt;
 
 pub use crate::sys_common::fs::{copy, try_exists};
 //pub use crate::sys_common::fs::remove_dir_all;
index 15a76bbd2c9e018d4139b3ee9043d0b74c00a16d..10c19424953d2af7b7d20db0ef4d183f33472aed 100644 (file)
@@ -149,7 +149,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
         x if x == 1 as i32 => ErrorKind::PermissionDenied,
         x if x == 32 as i32 => ErrorKind::BrokenPipe,
         x if x == 110 as i32 => ErrorKind::TimedOut,
-        _ => ErrorKind::Other,
+        _ => ErrorKind::Uncategorized,
     }
 }
 
index 885389ca54cd42c1df5390f7b27a8baf02ae6d28..4221799114b533e6db3617ff06c7477eede151cf 100644 (file)
@@ -14,7 +14,7 @@ use crate::sys::hermit::abi;
 /// This structure behaves a lot like a common mutex. There are some differences:
 ///
 /// - By using busy waiting, it can be used outside the runtime.
-/// - It is a so called ticket lock and is completly fair.
+/// - It is a so called ticket lock and is completely fair.
 #[cfg_attr(target_arch = "x86_64", repr(align(128)))]
 #[cfg_attr(not(target_arch = "x86_64"), repr(align(64)))]
 struct Spinlock<T: ?Sized> {
index 5f8839157eafc0b5b6af665cc6f6a4a7d7379747..3f0c99cf74289c639a6934bff9ab194ca471ee38 100644 (file)
@@ -15,7 +15,7 @@ use crate::time::Duration;
 pub fn init() -> io::Result<()> {
     if abi::network_init() < 0 {
         return Err(io::Error::new_const(
-            ErrorKind::Other,
+            ErrorKind::Uncategorized,
             &"Unable to initialize network interface",
         ));
     }
@@ -51,7 +51,7 @@ impl TcpStream {
         match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) {
             Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
             _ => Err(io::Error::new_const(
-                ErrorKind::Other,
+                ErrorKind::Uncategorized,
                 &"Unable to initiate a connection on a socket",
             )),
         }
@@ -65,7 +65,7 @@ impl TcpStream {
         ) {
             Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
             _ => Err(io::Error::new_const(
-                ErrorKind::Other,
+                ErrorKind::Uncategorized,
                 &"Unable to initiate a connection on a socket",
             )),
         }
@@ -73,7 +73,9 @@ impl TcpStream {
 
     pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
         abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64))
-            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to set timeout value"))
+            .map_err(|_| {
+                io::Error::new_const(ErrorKind::Uncategorized, &"Unable to set timeout value")
+            })
     }
 
     pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
@@ -81,12 +83,12 @@ impl TcpStream {
             *self.0.as_inner(),
             duration.map(|d| d.as_millis() as u64),
         )
-        .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to set timeout value"))
+        .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"Unable to set timeout value"))
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
         let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner()).map_err(|_| {
-            io::Error::new_const(ErrorKind::Other, &"Unable to determine timeout value")
+            io::Error::new_const(ErrorKind::Uncategorized, &"Unable to determine timeout value")
         })?;
 
         Ok(duration.map(|d| Duration::from_millis(d)))
@@ -94,7 +96,7 @@ impl TcpStream {
 
     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
         let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner()).map_err(|_| {
-            io::Error::new_const(ErrorKind::Other, &"Unable to determine timeout value")
+            io::Error::new_const(ErrorKind::Uncategorized, &"Unable to determine timeout value")
         })?;
 
         Ok(duration.map(|d| Duration::from_millis(d)))
@@ -102,7 +104,7 @@ impl TcpStream {
 
     pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
         abi::tcpstream::peek(*self.0.as_inner(), buf)
-            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"set_nodelay failed"))
+            .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"peek failed"))
     }
 
     pub fn read(&self, buffer: &mut [u8]) -> io::Result<usize> {
@@ -113,8 +115,9 @@ impl TcpStream {
         let mut size: usize = 0;
 
         for i in ioslice.iter_mut() {
-            let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..])
-                .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to read on socket"))?;
+            let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..]).map_err(|_| {
+                io::Error::new_const(ErrorKind::Uncategorized, &"Unable to read on socket")
+            })?;
 
             if ret != 0 {
                 size += ret;
@@ -138,7 +141,7 @@ impl TcpStream {
 
         for i in ioslice.iter() {
             size += abi::tcpstream::write(*self.0.as_inner(), i).map_err(|_| {
-                io::Error::new_const(ErrorKind::Other, &"Unable to write on socket")
+                io::Error::new_const(ErrorKind::Uncategorized, &"Unable to write on socket")
             })?;
         }
 
@@ -152,13 +155,13 @@ impl TcpStream {
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
         let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner())
-            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"peer_addr failed"))?;
+            .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"peer_addr failed"))?;
 
         let saddr = match ipaddr {
             Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port),
             Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
             _ => {
-                return Err(io::Error::new_const(ErrorKind::Other, &"peer_addr failed"));
+                return Err(io::Error::new_const(ErrorKind::Uncategorized, &"peer_addr failed"));
             }
         };
 
@@ -170,8 +173,9 @@ impl TcpStream {
     }
 
     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
-        abi::tcpstream::shutdown(*self.0.as_inner(), how as i32)
-            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to shutdown socket"))
+        abi::tcpstream::shutdown(*self.0.as_inner(), how as i32).map_err(|_| {
+            io::Error::new_const(ErrorKind::Uncategorized, &"unable to shutdown socket")
+        })
     }
 
     pub fn duplicate(&self) -> io::Result<TcpStream> {
@@ -180,22 +184,22 @@ impl TcpStream {
 
     pub fn set_nodelay(&self, mode: bool) -> io::Result<()> {
         abi::tcpstream::set_nodelay(*self.0.as_inner(), mode)
-            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"set_nodelay failed"))
+            .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"set_nodelay failed"))
     }
 
     pub fn nodelay(&self) -> io::Result<bool> {
         abi::tcpstream::nodelay(*self.0.as_inner())
-            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"nodelay failed"))
+            .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"nodelay failed"))
     }
 
     pub fn set_ttl(&self, tll: u32) -> io::Result<()> {
         abi::tcpstream::set_tll(*self.0.as_inner(), tll)
-            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set TTL"))
+            .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"unable to set TTL"))
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
         abi::tcpstream::get_tll(*self.0.as_inner())
-            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to get TTL"))
+            .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"unable to get TTL"))
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
@@ -203,8 +207,9 @@ impl TcpStream {
     }
 
     pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> {
-        abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode)
-            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set blocking mode"))
+        abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode).map_err(|_| {
+            io::Error::new_const(ErrorKind::Uncategorized, &"unable to set blocking mode")
+        })
     }
 }
 
@@ -230,12 +235,12 @@ impl TcpListener {
 
     pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
         let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port())
-            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"accept failed"))?;
+            .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"accept failed"))?;
         let saddr = match ipaddr {
             Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port),
             Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
             _ => {
-                return Err(io::Error::new_const(ErrorKind::Other, &"accept failed"));
+                return Err(io::Error::new_const(ErrorKind::Uncategorized, &"accept failed"));
             }
         };
 
index 40bd393098f5731d37db8127529f36883105d884..eeb30a578c05be476216eec5147af764c10253c9 100644 (file)
@@ -4,13 +4,13 @@ use crate::ffi::{CStr, OsStr, OsString};
 use crate::fmt;
 use crate::io;
 use crate::marker::PhantomData;
+use crate::os::unix::ffi::OsStringExt;
 use crate::path::{self, PathBuf};
 use crate::str;
 use crate::sync::Mutex;
 use crate::sys::hermit::abi;
 use crate::sys::memchr;
 use crate::sys::unsupported;
-use crate::sys_common::os_str_bytes::*;
 use crate::vec;
 
 pub fn errno() -> i32 {
index 6bff13ca92ccac65a5056d7799624ca2f674ade2..33b8390431f6d5327fa57abf590016ca4713dc78 100644 (file)
@@ -40,7 +40,7 @@ impl io::Write for Stdout {
         unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
-            Err(io::Error::new_const(io::ErrorKind::Other, &"Stdout is not able to print"))
+            Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stdout is not able to print"))
         } else {
             Ok(len as usize)
         }
@@ -52,7 +52,7 @@ impl io::Write for Stdout {
         unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
-            Err(io::Error::new_const(io::ErrorKind::Other, &"Stdout is not able to print"))
+            Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stdout is not able to print"))
         } else {
             Ok(len as usize)
         }
@@ -81,7 +81,7 @@ impl io::Write for Stderr {
         unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
-            Err(io::Error::new_const(io::ErrorKind::Other, &"Stderr is not able to print"))
+            Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stderr is not able to print"))
         } else {
             Ok(len as usize)
         }
@@ -93,7 +93,7 @@ impl io::Write for Stderr {
         unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
-            Err(io::Error::new_const(io::ErrorKind::Other, &"Stderr is not able to print"))
+            Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stderr is not able to print"))
         } else {
             Ok(len as usize)
         }
index f35a3a8a80fc5757e44dcc7a058966f8d95e9d0c..8be25f84999d2e7b9d3bf4052cfc0f884e212b19 100644 (file)
@@ -1,8 +1,10 @@
 #![allow(dead_code)]
 
+use super::unsupported;
 use crate::ffi::CStr;
 use crate::io;
 use crate::mem;
+use crate::num::NonZeroUsize;
 use crate::sys::hermit::abi;
 use crate::sys::hermit::thread_local_dtor::run_dtors;
 use crate::time::Duration;
@@ -37,7 +39,7 @@ impl Thread {
             // The thread failed to start and as a result p was not consumed. Therefore, it is
             // safe to reconstruct the box so that it gets deallocated.
             drop(Box::from_raw(p));
-            Err(io::Error::new_const(io::ErrorKind::Other, &"Unable to create thread!"))
+            Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Unable to create thread!"))
         } else {
             Ok(Thread { tid: tid })
         };
@@ -95,6 +97,10 @@ impl Thread {
     }
 }
 
+pub fn available_concurrency() -> io::Result<NonZeroUsize> {
+    unsupported()
+}
+
 pub mod guard {
     pub type Guard = !;
     pub unsafe fn current() -> Option<Guard> {
index 1e743894a9fea3444fbc1a71213354b5acee4248..52e8bec937c79b917e9533a9d9ff758539dfc377 100644 (file)
@@ -36,9 +36,9 @@ pub fn image_base() -> u64 {
     let base: u64;
     unsafe {
         asm!(
-            "lea {}, qword ptr [rip + IMAGE_BASE]",
+            "lea IMAGE_BASE(%rip), {}",
             lateout(reg) base,
-            options(nostack, preserves_flags, nomem, pure),
+            options(att_syntax, nostack, preserves_flags, nomem, pure),
         )
     };
     base
index cdfceca19fcdc7cd1837db254ff1632b27b45a06..fce6b4207328b7677901c4079fd6042b28e039c6 100644 (file)
@@ -70,7 +70,7 @@ pub fn sgx_ineffective<T>(v: T) -> crate::io::Result<T> {
     static SGX_INEFFECTIVE_ERROR: AtomicBool = AtomicBool::new(false);
     if SGX_INEFFECTIVE_ERROR.load(Ordering::Relaxed) {
         Err(crate::io::Error::new_const(
-            ErrorKind::Other,
+            ErrorKind::Uncategorized,
             &"operation can't be trusted to have any effect on SGX",
         ))
     } else {
@@ -115,11 +115,11 @@ pub fn decode_error_kind(code: i32) -> ErrorKind {
     } else if code == Error::Interrupted as _ {
         ErrorKind::Interrupted
     } else if code == Error::Other as _ {
-        ErrorKind::Other
+        ErrorKind::Uncategorized
     } else if code == Error::UnexpectedEof as _ {
         ErrorKind::UnexpectedEof
     } else {
-        ErrorKind::Other
+        ErrorKind::Uncategorized
     }
 }
 
index 5ccedece0f84b78eeeb07025b373a629515759af..3a69aa039ef2e703e087245eb37fe21dd8eafcbe 100644 (file)
@@ -466,7 +466,7 @@ pub struct LookupHost(!);
 
 impl LookupHost {
     fn new(host: String) -> io::Result<LookupHost> {
-        Err(io::Error::new(io::ErrorKind::Other, NonIpSockAddr { host }))
+        Err(io::Error::new(io::ErrorKind::Uncategorized, NonIpSockAddr { host }))
     }
 
     pub fn port(&self) -> u16 {
index 548e28a43d646281c0b2ef65742cedc17d2b0980..8ccf043b5b57f00cbb64df58a6ac85833e5e2230 100644 (file)
@@ -65,7 +65,7 @@ impl io::Write for Stderr {
 pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
 
 pub fn is_ebadf(err: &io::Error) -> bool {
-    // FIXME: Rust normally maps Unix EBADF to `Other`
+    // FIXME: Rust normally maps Unix EBADF to `Uncategorized`
     err.raw_os_error() == Some(abi::Error::BrokenPipe as _)
 }
 
index 67e2e8b59d397d8e14ce783c414fff0d39b8f07c..cbb8ba964018a687d7f07c76c5e5305f82faeaa1 100644 (file)
@@ -1,6 +1,8 @@
 #![cfg_attr(test, allow(dead_code))] // why is this necessary?
+use super::unsupported;
 use crate::ffi::CStr;
 use crate::io;
+use crate::num::NonZeroUsize;
 use crate::time::Duration;
 
 use super::abi::usercalls;
@@ -135,6 +137,10 @@ impl Thread {
     }
 }
 
+pub fn available_concurrency() -> io::Result<NonZeroUsize> {
+    unsupported()
+}
+
 pub mod guard {
     pub type Guard = !;
     pub unsafe fn current() -> Option<Guard> {
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 fc423e393d4a4b8e823ba74772ba556c5c899240..0bd1ea645779f6d524e1cb9e27156bcfe3f82b38 100644 (file)
@@ -14,11 +14,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
     imp::init(argc, argv)
 }
 
-/// One-time global cleanup.
-pub unsafe fn cleanup() {
-    imp::cleanup()
-}
-
 /// Returns the command line arguments
 pub fn args() -> Args {
     imp::args()
@@ -82,16 +77,18 @@ mod imp {
     use crate::ptr;
     use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering};
 
-    use crate::sys_common::mutex::StaticMutex;
-
+    // The system-provided argc and argv, which we store in static memory
+    // here so that we can defer the work of parsing them until its actually
+    // needed.
+    //
+    // Note that we never mutate argv/argc, the argv array, or the argv
+    // strings, which allows the code in this file to be very simple.
     static ARGC: AtomicIsize = AtomicIsize::new(0);
     static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
-    // We never call `ENV_LOCK.init()`, so it is UB to attempt to
-    // acquire this mutex reentrantly!
-    static LOCK: StaticMutex = StaticMutex::new();
 
     unsafe fn really_init(argc: isize, argv: *const *const u8) {
-        let _guard = LOCK.lock();
+        // These don't need to be ordered with each other or other stores,
+        // because they only hold the unmodified system-provide argv/argc.
         ARGC.store(argc, Ordering::Relaxed);
         ARGV.store(argv as *mut _, Ordering::Relaxed);
     }
@@ -127,21 +124,22 @@ mod imp {
         init_wrapper
     };
 
-    pub unsafe fn cleanup() {
-        let _guard = LOCK.lock();
-        ARGC.store(0, Ordering::Relaxed);
-        ARGV.store(ptr::null_mut(), Ordering::Relaxed);
-    }
-
     pub fn args() -> Args {
         Args { iter: clone().into_iter() }
     }
 
     fn clone() -> Vec<OsString> {
         unsafe {
-            let _guard = LOCK.lock();
-            let argc = ARGC.load(Ordering::Relaxed);
+            // Load ARGC and ARGV, which hold the unmodified system-provided
+            // argc/argv, so we can read the pointed-to memory without atomics
+            // or synchronization.
+            //
+            // If either ARGC or ARGV is still zero or null, then either there
+            // really are no arguments, or someone is asking for `args()`
+            // before initialization has completed, and we return an empty
+            // list.
             let argv = ARGV.load(Ordering::Relaxed);
+            let argc = if argv.is_null() { 0 } else { ARGC.load(Ordering::Relaxed) };
             (0..argc)
                 .map(|i| {
                     let cstr = CStr::from_ptr(*argv.offset(i) as *const libc::c_char);
@@ -159,8 +157,6 @@ mod imp {
 
     pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
 
-    pub fn cleanup() {}
-
     #[cfg(target_os = "macos")]
     pub fn args() -> Args {
         use crate::os::unix::prelude::*;
index f8ca67c844c91bac327797d454eaf7ab4b7ea603..5c8c94971c33c0de8d4ad71d9f30910528eac37c 100644 (file)
@@ -12,8 +12,23 @@ use crate::sys::time::SystemTime;
 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 @@ cfg_has_statx! {{
     // 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 @@ cfg_has_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
@@ -358,7 +373,7 @@ impl FileAttr {
                     }))
                 } else {
                     Err(io::Error::new_const(
-                        io::ErrorKind::Other,
+                        io::ErrorKind::Uncategorized,
                         &"creation time is not available for the filesystem",
                     ))
                 };
@@ -647,6 +662,10 @@ impl DirEntry {
     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 @@ impl File {
         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 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
         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::process::{ChildStderr, ChildStdin, ChildStdout};
 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 ca9cc8ca7ba391259529d6c9c4c7b7ccc35ab235..9e553ec7682b1a3b82a98f8636232ddcb35501fd 100644 (file)
@@ -123,7 +123,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
 // SAFETY: must be called only once during runtime cleanup.
 // NOTE: this is not guaranteed to run, for example when the program aborts.
 pub unsafe fn cleanup() {
-    args::cleanup();
     stack_overflow::cleanup();
 }
 
@@ -133,29 +132,51 @@ pub use crate::sys::android::signal;
 pub use libc::signal;
 
 pub fn decode_error_kind(errno: i32) -> ErrorKind {
+    use ErrorKind::*;
     match errno as libc::c_int {
-        libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
-        libc::ECONNRESET => ErrorKind::ConnectionReset,
-        libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied,
-        libc::EPIPE => ErrorKind::BrokenPipe,
-        libc::ENOTCONN => ErrorKind::NotConnected,
-        libc::ECONNABORTED => ErrorKind::ConnectionAborted,
-        libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
-        libc::EADDRINUSE => ErrorKind::AddrInUse,
-        libc::ENOENT => ErrorKind::NotFound,
-        libc::EINTR => ErrorKind::Interrupted,
-        libc::EINVAL => ErrorKind::InvalidInput,
-        libc::ETIMEDOUT => ErrorKind::TimedOut,
-        libc::EEXIST => ErrorKind::AlreadyExists,
-        libc::ENOSYS => ErrorKind::Unsupported,
-        libc::ENOMEM => ErrorKind::OutOfMemory,
+        libc::E2BIG => ArgumentListTooLong,
+        libc::EADDRINUSE => AddrInUse,
+        libc::EADDRNOTAVAIL => AddrNotAvailable,
+        libc::EBUSY => ResourceBusy,
+        libc::ECONNABORTED => ConnectionAborted,
+        libc::ECONNREFUSED => ConnectionRefused,
+        libc::ECONNRESET => ConnectionReset,
+        libc::EDEADLK => Deadlock,
+        libc::EDQUOT => FilesystemQuotaExceeded,
+        libc::EEXIST => AlreadyExists,
+        libc::EFBIG => FileTooLarge,
+        libc::EHOSTUNREACH => HostUnreachable,
+        libc::EINTR => Interrupted,
+        libc::EINVAL => InvalidInput,
+        libc::EISDIR => IsADirectory,
+        libc::ELOOP => FilesystemLoop,
+        libc::ENOENT => NotFound,
+        libc::ENOMEM => OutOfMemory,
+        libc::ENOSPC => StorageFull,
+        libc::ENOSYS => Unsupported,
+        libc::EMLINK => TooManyLinks,
+        libc::ENAMETOOLONG => FilenameTooLong,
+        libc::ENETDOWN => NetworkDown,
+        libc::ENETUNREACH => NetworkUnreachable,
+        libc::ENOTCONN => NotConnected,
+        libc::ENOTDIR => NotADirectory,
+        libc::ENOTEMPTY => DirectoryNotEmpty,
+        libc::EPIPE => BrokenPipe,
+        libc::EROFS => ReadOnlyFilesystem,
+        libc::ESPIPE => NotSeekable,
+        libc::ESTALE => StaleNetworkFileHandle,
+        libc::ETIMEDOUT => TimedOut,
+        libc::ETXTBSY => ExecutableFileBusy,
+        libc::EXDEV => CrossesDevices,
+
+        libc::EACCES | libc::EPERM => PermissionDenied,
 
         // These two constants can have the same value on some systems,
         // but different values on others, so we can't use a match
         // clause
-        x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => ErrorKind::WouldBlock,
+        x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock,
 
-        _ => ErrorKind::Other,
+        _ => Uncategorized,
     }
 }
 
@@ -195,13 +216,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() }
 }
@@ -240,7 +289,7 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_os = "macos")] {
         #[link(name = "System")]
         // res_init and friends require -lresolv on macOS/iOS.
-        // See #41582 and http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html
+        // See #41582 and https://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html
         #[link(name = "resolv")]
         extern "C" {}
     } else if #[cfg(target_os = "ios")] {
index d5a15964c089d267c440016cd5b3b232546e2556..753cad55ce74546805385f7e48e9adbe3890580d 100644 (file)
@@ -38,7 +38,7 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
         str::from_utf8(CStr::from_ptr(libc::gai_strerror(err)).to_bytes()).unwrap().to_owned()
     };
     Err(io::Error::new(
-        io::ErrorKind::Other,
+        io::ErrorKind::Uncategorized,
         &format!("failed to lookup address information: {}", detail)[..],
     ))
 }
@@ -178,7 +178,7 @@ impl Socket {
                     if pollfd.revents & libc::POLLHUP != 0 {
                         let e = self.take_error()?.unwrap_or_else(|| {
                             io::Error::new_const(
-                                io::ErrorKind::Other,
+                                io::ErrorKind::Uncategorized,
                                 &"no error set after POLLHUP",
                             )
                         });
index 41ca9762390c6f4a5f0cc32c89b4e13d52a5d5e3..d3c874edf2dc472c9cb9edae7e0a716cec95a3e4 100644 (file)
@@ -23,6 +23,9 @@ use crate::sys::memchr;
 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;
@@ -279,7 +282,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
             ))?;
             if path_len <= 1 {
                 return Err(io::Error::new_const(
-                    io::ErrorKind::Other,
+                    io::ErrorKind::Uncategorized,
                     &"KERN_PROC_PATHNAME sysctl returned zero-length string",
                 ));
             }
@@ -302,7 +305,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
             return crate::fs::read_link(curproc_exe);
         }
         Err(io::Error::new_const(
-            io::ErrorKind::Other,
+            io::ErrorKind::Uncategorized,
             &"/proc/curproc/exe doesn't point to regular file.",
         ))
     }
@@ -320,7 +323,10 @@ pub fn current_exe() -> io::Result<PathBuf> {
         cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _, &mut argv_len, ptr::null_mut(), 0))?;
         argv.set_len(argv_len as usize);
         if argv[0].is_null() {
-            return Err(io::Error::new_const(io::ErrorKind::Other, &"no current exe available"));
+            return Err(io::Error::new_const(
+                io::ErrorKind::Uncategorized,
+                &"no current exe available",
+            ));
         }
         let argv0 = CStr::from_ptr(argv[0]).to_bytes();
         if argv0[0] == b'.' || argv0.iter().any(|b| *b == b'/') {
@@ -335,7 +341,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
 pub fn current_exe() -> io::Result<PathBuf> {
     match crate::fs::read_link("/proc/self/exe") {
         Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new_const(
-            io::ErrorKind::Other,
+            io::ErrorKind::Uncategorized,
             &"no /proc/self/exe available. Is /proc mounted?",
         )),
         other => other,
@@ -422,7 +428,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
             _get_next_image_info(0, &mut cookie, &mut info, mem::size_of::<image_info>() as i32);
         if result != 0 {
             use crate::io::ErrorKind;
-            Err(io::Error::new_const(ErrorKind::Other, &"Error getting executable path"))
+            Err(io::Error::new_const(ErrorKind::Uncategorized, &"Error getting executable path"))
         } else {
             let name = CStr::from_ptr(info.name.as_ptr()).to_bytes();
             Ok(PathBuf::from(OsStr::from_bytes(name)))
index ed55e1aa715ae5ac5cea3b99fdce5b0d3614f4ee..c888dd0d87d8e296b76601ec6aa043ea2ef73520 100644 (file)
@@ -9,6 +9,14 @@ use crate::sys;
 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 b8f43caec32a3962e219cd6bbc0c7521a9bde4fc..879d716052497f626ce5cb41c946251300ab70fa 100644 (file)
@@ -2,10 +2,13 @@ use crate::cmp;
 use crate::ffi::CStr;
 use crate::io;
 use crate::mem;
+use crate::num::NonZeroUsize;
 use crate::ptr;
 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")]
@@ -198,6 +201,88 @@ impl Drop for Thread {
     }
 }
 
+pub fn available_concurrency() -> io::Result<NonZeroUsize> {
+    cfg_if::cfg_if! {
+        if #[cfg(any(
+            target_os = "android",
+            target_os = "emscripten",
+            target_os = "fuchsia",
+            target_os = "ios",
+            target_os = "linux",
+            target_os = "macos",
+            target_os = "solaris",
+            target_os = "illumos",
+        ))] {
+            match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } {
+                -1 => Err(io::Error::last_os_error()),
+                0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")),
+                cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }),
+            }
+        } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] {
+            use crate::ptr;
+
+            let mut cpus: libc::c_uint = 0;
+            let mut cpus_size = crate::mem::size_of_val(&cpus);
+
+            unsafe {
+                cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
+            }
+
+            // Fallback approach in case of errors or no hardware threads.
+            if cpus < 1 {
+                let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
+                let res = unsafe {
+                    libc::sysctl(
+                        mib.as_mut_ptr(),
+                        2,
+                        &mut cpus as *mut _ as *mut _,
+                        &mut cpus_size as *mut _ as *mut _,
+                        ptr::null_mut(),
+                        0,
+                    )
+                };
+
+                // Handle errors if any.
+                if res == -1 {
+                    return Err(io::Error::last_os_error());
+                } else if cpus == 0 {
+                    return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform"));
+                }
+            }
+            Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) })
+        } else if #[cfg(target_os = "openbsd")] {
+            use crate::ptr;
+
+            let mut cpus: libc::c_uint = 0;
+            let mut cpus_size = crate::mem::size_of_val(&cpus);
+            let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
+
+            let res = unsafe {
+                libc::sysctl(
+                    mib.as_mut_ptr(),
+                    2,
+                    &mut cpus as *mut _ as *mut _,
+                    &mut cpus_size as *mut _ as *mut _,
+                    ptr::null_mut(),
+                    0,
+                )
+            };
+
+            // Handle errors if any.
+            if res == -1 {
+                return Err(io::Error::last_os_error());
+            } else if cpus == 0 {
+                return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform"));
+            }
+
+            Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) })
+        } else {
+            // FIXME: implement on vxWorks, Redox, Haiku, l4re
+            Err(io::Error::new_const(io::ErrorKind::Unsupported, &"Getting the number of hardware threads is not supported on the target platform"))
+        }
+    }
+}
+
 #[cfg(all(
     not(target_os = "linux"),
     not(target_os = "freebsd"),
index 432fe4c33bcc461b40ce2a54a3a2f927fbc5479b..cad8be6d289ee166dc111013d85521d38b42de20 100644 (file)
@@ -26,8 +26,11 @@ use crate::marker;
 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 @@ macro_rules! syscall {
     )
 }
 
+#[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 6e72a7c632ed0b4755d3f56034a75c0296e9f31d..4e6c301d29f5470fdc85d0492fe1ed06d094a083 100644 (file)
@@ -30,7 +30,7 @@ pub fn unsupported_err() -> std_io::Error {
 }
 
 pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
-    crate::io::ErrorKind::Other
+    crate::io::ErrorKind::Uncategorized
 }
 
 pub fn abort_internal() -> ! {
index cda8510e1baebe1316cd57b8bb0c01e35a1fb145..dc75d4ee6725ce997761e7c4b38462ae17be7fd6 100644 (file)
@@ -1,6 +1,7 @@
 use super::unsupported;
 use crate::ffi::CStr;
 use crate::io;
+use crate::num::NonZeroUsize;
 use crate::time::Duration;
 
 pub struct Thread(!);
@@ -30,6 +31,10 @@ impl Thread {
     }
 }
 
+pub fn available_concurrency() -> io::Result<NonZeroUsize> {
+    unsupported()
+}
+
 pub mod guard {
     pub type Guard = !;
     pub unsafe fn current() -> Option<Guard> {
index 45e38f68b8c37882bcb49e2ae8f3e81df7dcab7d..8ffa1c88d88e75f89a1cd4c4ee18d86c36b6357b 100644 (file)
@@ -648,7 +648,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
                      through which {:?} could be opened",
                     p
                 );
-                return Err(io::Error::new(io::ErrorKind::Other, msg));
+                return Err(io::Error::new(io::ErrorKind::Uncategorized, msg));
             }
             let relative = CStr::from_ptr(relative_path).to_bytes().to_vec();
 
@@ -670,7 +670,8 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
 }
 
 pub fn osstr2str(f: &OsStr) -> io::Result<&str> {
-    f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8"))
+    f.to_str()
+        .ok_or_else(|| io::Error::new_const(io::ErrorKind::Uncategorized, &"input must be utf-8"))
 }
 
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
index 45a829c0cd212c90f04edd3ce9e44aeecf3d9c3c..4af99bfa464781d59aa7fbe79e97ce90d87ea855 100644 (file)
@@ -58,7 +58,7 @@ pub use common::*;
 pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
     use std_io::ErrorKind::*;
     if errno > u16::MAX as i32 || errno < 0 {
-        return Other;
+        return Uncategorized;
     }
     match errno as u16 {
         wasi::ERRNO_CONNREFUSED => ConnectionRefused,
@@ -77,7 +77,7 @@ pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
         wasi::ERRNO_AGAIN => WouldBlock,
         wasi::ERRNO_NOSYS => Unsupported,
         wasi::ERRNO_NOMEM => OutOfMemory,
-        _ => Other,
+        _ => Uncategorized,
     }
 }
 
index 74515553a82182d7e8521fb49a6bc5105c154f63..9ec02bbec2644f53a6a4a6f721d113b1254661f4 100644 (file)
@@ -3,6 +3,7 @@
 use crate::ffi::CStr;
 use crate::io;
 use crate::mem;
+use crate::num::NonZeroUsize;
 use crate::sys::unsupported;
 use crate::time::Duration;
 
@@ -63,6 +64,10 @@ impl Thread {
     }
 }
 
+pub fn available_concurrency() -> io::Result<NonZeroUsize> {
+    unsupported()
+}
+
 pub mod guard {
     pub type Guard = !;
     pub unsafe fn current() -> Option<Guard> {
index 54bc877aa7de720cbaeddd21b977f3bc804db777..a66ab0837570d59db4b152288d0d195349efac16 100644 (file)
@@ -1,5 +1,6 @@
 use crate::ffi::CStr;
 use crate::io;
+use crate::num::NonZeroUsize;
 use crate::sys::unsupported;
 use crate::time::Duration;
 
@@ -39,6 +40,10 @@ impl Thread {
     pub fn join(self) {}
 }
 
+pub fn available_concurrency() -> io::Result<NonZeroUsize> {
+    unsupported()
+}
+
 pub mod guard {
     pub type Guard = !;
     pub unsafe fn current() -> Option<Guard> {
index b7efc884473b417715ebb46142e94acef7e4ba3d..63f9be7b7e350d18d1e0a546868a19fdb974fe80 100644 (file)
@@ -10,9 +10,14 @@ use crate::ptr;
 
 use libc::{c_void, size_t, wchar_t};
 
+#[path = "c/errors.rs"] // c.rs is included from two places so we need to specify this
+mod errors;
+pub use errors::*;
+
 pub use self::EXCEPTION_DISPOSITION::*;
 pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
 
+pub type DWORD_PTR = ULONG_PTR;
 pub type DWORD = c_ulong;
 pub type NonZeroDWORD = NonZero_c_ulong;
 pub type HANDLE = LPVOID;
@@ -53,6 +58,7 @@ pub type LPWSADATA = *mut WSADATA;
 pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
 pub type LPWSTR = *mut WCHAR;
 pub type LPFILETIME = *mut FILETIME;
+pub type LPSYSTEM_INFO = *mut SYSTEM_INFO;
 pub type LPWSABUF = *mut WSABUF;
 pub type LPWSAOVERLAPPED = *mut c_void;
 pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void;
@@ -68,6 +74,10 @@ pub type ADDRESS_FAMILY = USHORT;
 pub const TRUE: BOOL = 1;
 pub const FALSE: BOOL = 0;
 
+pub const CSTR_LESS_THAN: c_int = 1;
+pub const CSTR_EQUAL: c_int = 2;
+pub const CSTR_GREATER_THAN: c_int = 3;
+
 pub const FILE_ATTRIBUTE_READONLY: DWORD = 0x1;
 pub const FILE_ATTRIBUTE_DIRECTORY: DWORD = 0x10;
 pub const FILE_ATTRIBUTE_REPARSE_POINT: DWORD = 0x400;
@@ -132,19 +142,6 @@ pub const WSASYS_STATUS_LEN: usize = 128;
 pub const WSAPROTOCOL_LEN: DWORD = 255;
 pub const INVALID_SOCKET: SOCKET = !0;
 
-pub const WSAEACCES: c_int = 10013;
-pub const WSAEINVAL: c_int = 10022;
-pub const WSAEWOULDBLOCK: c_int = 10035;
-pub const WSAEPROTOTYPE: c_int = 10041;
-pub const WSAEADDRINUSE: c_int = 10048;
-pub const WSAEADDRNOTAVAIL: c_int = 10049;
-pub const WSAECONNABORTED: c_int = 10053;
-pub const WSAECONNRESET: c_int = 10054;
-pub const WSAENOTCONN: c_int = 10057;
-pub const WSAESHUTDOWN: c_int = 10058;
-pub const WSAETIMEDOUT: c_int = 10060;
-pub const WSAECONNREFUSED: c_int = 10061;
-
 pub const MAX_PROTOCOL_CHAIN: DWORD = 7;
 
 pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024;
@@ -164,42 +161,6 @@ pub const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
 
 pub const PROGRESS_CONTINUE: DWORD = 0;
 
-// List of Windows system error codes with descriptions:
-// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes
-pub const ERROR_FILE_NOT_FOUND: DWORD = 2;
-pub const ERROR_PATH_NOT_FOUND: DWORD = 3;
-pub const ERROR_ACCESS_DENIED: DWORD = 5;
-pub const ERROR_INVALID_HANDLE: DWORD = 6;
-pub const ERROR_NOT_ENOUGH_MEMORY: DWORD = 8;
-pub const ERROR_OUTOFMEMORY: DWORD = 14;
-pub const ERROR_NO_MORE_FILES: DWORD = 18;
-pub const ERROR_SHARING_VIOLATION: u32 = 32;
-pub const ERROR_HANDLE_EOF: DWORD = 38;
-pub const ERROR_FILE_EXISTS: DWORD = 80;
-pub const ERROR_INVALID_PARAMETER: DWORD = 87;
-pub const ERROR_BROKEN_PIPE: DWORD = 109;
-pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120;
-pub const ERROR_SEM_TIMEOUT: DWORD = 121;
-pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122;
-pub const ERROR_ALREADY_EXISTS: DWORD = 183;
-pub const ERROR_ENVVAR_NOT_FOUND: DWORD = 203;
-pub const ERROR_NO_DATA: DWORD = 232;
-pub const ERROR_DRIVER_CANCEL_TIMEOUT: DWORD = 594;
-pub const ERROR_OPERATION_ABORTED: DWORD = 995;
-pub const ERROR_IO_PENDING: DWORD = 997;
-pub const ERROR_SERVICE_REQUEST_TIMEOUT: DWORD = 1053;
-pub const ERROR_COUNTER_TIMEOUT: DWORD = 1121;
-pub const ERROR_TIMEOUT: DWORD = 1460;
-pub const ERROR_RESOURCE_CALL_TIMED_OUT: DWORD = 5910;
-pub const ERROR_CTX_MODEM_RESPONSE_TIMEOUT: DWORD = 7012;
-pub const ERROR_CTX_CLIENT_QUERY_TIMEOUT: DWORD = 7040;
-pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: DWORD = 8014;
-pub const ERROR_DS_TIMELIMIT_EXCEEDED: DWORD = 8226;
-pub const DNS_ERROR_RECORD_TIMED_OUT: DWORD = 9705;
-pub const ERROR_IPSEC_IKE_TIMED_OUT: DWORD = 13805;
-pub const ERROR_RUNLEVEL_SWITCH_TIMEOUT: DWORD = 15402;
-pub const ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT: DWORD = 15403;
-
 pub const E_NOTIMPL: HRESULT = 0x80004001u32 as HRESULT;
 
 pub const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE;
@@ -234,6 +195,7 @@ pub const SD_RECEIVE: c_int = 0;
 pub const SD_SEND: c_int = 1;
 pub const SOCK_DGRAM: c_int = 2;
 pub const SOCK_STREAM: c_int = 1;
+pub const SOCKET_ERROR: c_int = -1;
 pub const SOL_SOCKET: c_int = 0xffff;
 pub const SO_RCVTIMEO: c_int = 0x1006;
 pub const SO_SNDTIMEO: c_int = 0x1005;
@@ -532,6 +494,21 @@ pub struct FILETIME {
     pub dwHighDateTime: DWORD,
 }
 
+#[repr(C)]
+pub struct SYSTEM_INFO {
+    pub wProcessorArchitecture: WORD,
+    pub wReserved: WORD,
+    pub dwPageSize: DWORD,
+    pub lpMinimumApplicationAddress: LPVOID,
+    pub lpMaximumApplicationAddress: LPVOID,
+    pub dwActiveProcessorMask: DWORD_PTR,
+    pub dwNumberOfProcessors: DWORD,
+    pub dwProcessorType: DWORD,
+    pub dwAllocationGranularity: DWORD,
+    pub wProcessorLevel: WORD,
+    pub wProcessorRevision: WORD,
+}
+
 #[repr(C)]
 pub struct OVERLAPPED {
     pub Internal: *mut c_ulong,
@@ -933,6 +910,7 @@ extern "system" {
     pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
 
     pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME);
+    pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO);
 
     pub fn CreateEventW(
         lpEventAttributes: LPSECURITY_ATTRIBUTES,
@@ -996,6 +974,14 @@ extern "system" {
     pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK);
     pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN;
     pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN;
+
+    pub fn CompareStringOrdinal(
+        lpString1: LPCWSTR,
+        cchCount1: c_int,
+        lpString2: LPCWSTR,
+        cchCount2: c_int,
+        bIgnoreCase: BOOL,
+    ) -> c_int;
 }
 
 #[link(name = "ws2_32")]
diff --git a/library/std/src/sys/windows/c/errors.rs b/library/std/src/sys/windows/c/errors.rs
new file mode 100644 (file)
index 0000000..23dcc11
--- /dev/null
@@ -0,0 +1,1883 @@
+// List of Windows system error codes with descriptions:
+// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes
+
+#![allow(dead_code)]
+
+use super::{c_int, DWORD};
+
+pub const ERROR_DIRECTORY_NOT_SUPPORTED: DWORD = 336;
+pub const ERROR_DRIVER_CANCEL_TIMEOUT: DWORD = 594;
+pub const ERROR_DISK_QUOTA_EXCEEDED: DWORD = 1295;
+pub const ERROR_RESOURCE_CALL_TIMED_OUT: DWORD = 5910;
+pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: DWORD = 8014;
+pub const DNS_ERROR_RECORD_TIMED_OUT: DWORD = 9705;
+
+// The followiung list was obtained from
+//   `/usr/x86_64-w64-mingw32/include/winerror.h`
+// in the Debian package
+//   mingw-w64_6.0.0-3_all.deb
+//
+// The header of that file says:
+//   * This file has no copyright assigned and is placed in the Public Domain.
+//   * This file is part of the mingw-w64 runtime package.
+//   * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+//
+// The text here is the result of the following rune:
+//   grep -P '#define ERROR' /usr/x86_64-w64-mingw32/include/winerror.h >>library/std/src/sys/windows/c/errors.rs
+//   grep -P '#define WSA' /usr/x86_64-w64-mingw32/include/winerror.h >>library/std/src/sys/windows/c/errors.rs
+// and then using some manually-invented but rather obvious editor search-and-replace
+// invocations, plus some straightforward manual fixups, to turn it into Rust syntax
+// and remove all the duplicates from the manual table above.
+
+pub const ERROR_SUCCESS: DWORD = 0;
+pub const ERROR_INVALID_FUNCTION: DWORD = 1;
+pub const ERROR_FILE_NOT_FOUND: DWORD = 2;
+pub const ERROR_PATH_NOT_FOUND: DWORD = 3;
+pub const ERROR_TOO_MANY_OPEN_FILES: DWORD = 4;
+pub const ERROR_ACCESS_DENIED: DWORD = 5;
+pub const ERROR_INVALID_HANDLE: DWORD = 6;
+pub const ERROR_ARENA_TRASHED: DWORD = 7;
+pub const ERROR_NOT_ENOUGH_MEMORY: DWORD = 8;
+pub const ERROR_INVALID_BLOCK: DWORD = 9;
+pub const ERROR_BAD_ENVIRONMENT: DWORD = 10;
+pub const ERROR_BAD_FORMAT: DWORD = 11;
+pub const ERROR_INVALID_ACCESS: DWORD = 12;
+pub const ERROR_INVALID_DATA: DWORD = 13;
+pub const ERROR_OUTOFMEMORY: DWORD = 14;
+pub const ERROR_INVALID_DRIVE: DWORD = 15;
+pub const ERROR_CURRENT_DIRECTORY: DWORD = 16;
+pub const ERROR_NOT_SAME_DEVICE: DWORD = 17;
+pub const ERROR_NO_MORE_FILES: DWORD = 18;
+pub const ERROR_WRITE_PROTECT: DWORD = 19;
+pub const ERROR_BAD_UNIT: DWORD = 20;
+pub const ERROR_NOT_READY: DWORD = 21;
+pub const ERROR_BAD_COMMAND: DWORD = 22;
+pub const ERROR_CRC: DWORD = 23;
+pub const ERROR_BAD_LENGTH: DWORD = 24;
+pub const ERROR_SEEK: DWORD = 25;
+pub const ERROR_NOT_DOS_DISK: DWORD = 26;
+pub const ERROR_SECTOR_NOT_FOUND: DWORD = 27;
+pub const ERROR_OUT_OF_PAPER: DWORD = 28;
+pub const ERROR_WRITE_FAULT: DWORD = 29;
+pub const ERROR_READ_FAULT: DWORD = 30;
+pub const ERROR_GEN_FAILURE: DWORD = 31;
+pub const ERROR_SHARING_VIOLATION: DWORD = 32;
+pub const ERROR_LOCK_VIOLATION: DWORD = 33;
+pub const ERROR_WRONG_DISK: DWORD = 34;
+pub const ERROR_SHARING_BUFFER_EXCEEDED: DWORD = 36;
+pub const ERROR_HANDLE_EOF: DWORD = 38;
+pub const ERROR_HANDLE_DISK_FULL: DWORD = 39;
+pub const ERROR_NOT_SUPPORTED: DWORD = 50;
+pub const ERROR_REM_NOT_LIST: DWORD = 51;
+pub const ERROR_DUP_NAME: DWORD = 52;
+pub const ERROR_BAD_NETPATH: DWORD = 53;
+pub const ERROR_NETWORK_BUSY: DWORD = 54;
+pub const ERROR_DEV_NOT_EXIST: DWORD = 55;
+pub const ERROR_TOO_MANY_CMDS: DWORD = 56;
+pub const ERROR_ADAP_HDW_ERR: DWORD = 57;
+pub const ERROR_BAD_NET_RESP: DWORD = 58;
+pub const ERROR_UNEXP_NET_ERR: DWORD = 59;
+pub const ERROR_BAD_REM_ADAP: DWORD = 60;
+pub const ERROR_PRINTQ_FULL: DWORD = 61;
+pub const ERROR_NO_SPOOL_SPACE: DWORD = 62;
+pub const ERROR_PRINT_CANCELLED: DWORD = 63;
+pub const ERROR_NETNAME_DELETED: DWORD = 64;
+pub const ERROR_NETWORK_ACCESS_DENIED: DWORD = 65;
+pub const ERROR_BAD_DEV_TYPE: DWORD = 66;
+pub const ERROR_BAD_NET_NAME: DWORD = 67;
+pub const ERROR_TOO_MANY_NAMES: DWORD = 68;
+pub const ERROR_TOO_MANY_SESS: DWORD = 69;
+pub const ERROR_SHARING_PAUSED: DWORD = 70;
+pub const ERROR_REQ_NOT_ACCEP: DWORD = 71;
+pub const ERROR_REDIR_PAUSED: DWORD = 72;
+pub const ERROR_FILE_EXISTS: DWORD = 80;
+pub const ERROR_CANNOT_MAKE: DWORD = 82;
+pub const ERROR_FAIL_I24: DWORD = 83;
+pub const ERROR_OUT_OF_STRUCTURES: DWORD = 84;
+pub const ERROR_ALREADY_ASSIGNED: DWORD = 85;
+pub const ERROR_INVALID_PASSWORD: DWORD = 86;
+pub const ERROR_INVALID_PARAMETER: DWORD = 87;
+pub const ERROR_NET_WRITE_FAULT: DWORD = 88;
+pub const ERROR_NO_PROC_SLOTS: DWORD = 89;
+pub const ERROR_TOO_MANY_SEMAPHORES: DWORD = 100;
+pub const ERROR_EXCL_SEM_ALREADY_OWNED: DWORD = 101;
+pub const ERROR_SEM_IS_SET: DWORD = 102;
+pub const ERROR_TOO_MANY_SEM_REQUESTS: DWORD = 103;
+pub const ERROR_INVALID_AT_INTERRUPT_TIME: DWORD = 104;
+pub const ERROR_SEM_OWNER_DIED: DWORD = 105;
+pub const ERROR_SEM_USER_LIMIT: DWORD = 106;
+pub const ERROR_DISK_CHANGE: DWORD = 107;
+pub const ERROR_DRIVE_LOCKED: DWORD = 108;
+pub const ERROR_BROKEN_PIPE: DWORD = 109;
+pub const ERROR_OPEN_FAILED: DWORD = 110;
+pub const ERROR_BUFFER_OVERFLOW: DWORD = 111;
+pub const ERROR_DISK_FULL: DWORD = 112;
+pub const ERROR_NO_MORE_SEARCH_HANDLES: DWORD = 113;
+pub const ERROR_INVALID_TARGET_HANDLE: DWORD = 114;
+pub const ERROR_INVALID_CATEGORY: DWORD = 117;
+pub const ERROR_INVALID_VERIFY_SWITCH: DWORD = 118;
+pub const ERROR_BAD_DRIVER_LEVEL: DWORD = 119;
+pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120;
+pub const ERROR_SEM_TIMEOUT: DWORD = 121;
+pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122;
+pub const ERROR_INVALID_NAME: DWORD = 123;
+pub const ERROR_INVALID_LEVEL: DWORD = 124;
+pub const ERROR_NO_VOLUME_LABEL: DWORD = 125;
+pub const ERROR_MOD_NOT_FOUND: DWORD = 126;
+pub const ERROR_PROC_NOT_FOUND: DWORD = 127;
+pub const ERROR_WAIT_NO_CHILDREN: DWORD = 128;
+pub const ERROR_CHILD_NOT_COMPLETE: DWORD = 129;
+pub const ERROR_DIRECT_ACCESS_HANDLE: DWORD = 130;
+pub const ERROR_NEGATIVE_SEEK: DWORD = 131;
+pub const ERROR_SEEK_ON_DEVICE: DWORD = 132;
+pub const ERROR_IS_JOIN_TARGET: DWORD = 133;
+pub const ERROR_IS_JOINED: DWORD = 134;
+pub const ERROR_IS_SUBSTED: DWORD = 135;
+pub const ERROR_NOT_JOINED: DWORD = 136;
+pub const ERROR_NOT_SUBSTED: DWORD = 137;
+pub const ERROR_JOIN_TO_JOIN: DWORD = 138;
+pub const ERROR_SUBST_TO_SUBST: DWORD = 139;
+pub const ERROR_JOIN_TO_SUBST: DWORD = 140;
+pub const ERROR_SUBST_TO_JOIN: DWORD = 141;
+pub const ERROR_BUSY_DRIVE: DWORD = 142;
+pub const ERROR_SAME_DRIVE: DWORD = 143;
+pub const ERROR_DIR_NOT_ROOT: DWORD = 144;
+pub const ERROR_DIR_NOT_EMPTY: DWORD = 145;
+pub const ERROR_IS_SUBST_PATH: DWORD = 146;
+pub const ERROR_IS_JOIN_PATH: DWORD = 147;
+pub const ERROR_PATH_BUSY: DWORD = 148;
+pub const ERROR_IS_SUBST_TARGET: DWORD = 149;
+pub const ERROR_SYSTEM_TRACE: DWORD = 150;
+pub const ERROR_INVALID_EVENT_COUNT: DWORD = 151;
+pub const ERROR_TOO_MANY_MUXWAITERS: DWORD = 152;
+pub const ERROR_INVALID_LIST_FORMAT: DWORD = 153;
+pub const ERROR_LABEL_TOO_LONG: DWORD = 154;
+pub const ERROR_TOO_MANY_TCBS: DWORD = 155;
+pub const ERROR_SIGNAL_REFUSED: DWORD = 156;
+pub const ERROR_DISCARDED: DWORD = 157;
+pub const ERROR_NOT_LOCKED: DWORD = 158;
+pub const ERROR_BAD_THREADID_ADDR: DWORD = 159;
+pub const ERROR_BAD_ARGUMENTS: DWORD = 160;
+pub const ERROR_BAD_PATHNAME: DWORD = 161;
+pub const ERROR_SIGNAL_PENDING: DWORD = 162;
+pub const ERROR_MAX_THRDS_REACHED: DWORD = 164;
+pub const ERROR_LOCK_FAILED: DWORD = 167;
+pub const ERROR_BUSY: DWORD = 170;
+pub const ERROR_CANCEL_VIOLATION: DWORD = 173;
+pub const ERROR_ATOMIC_LOCKS_NOT_SUPPORTED: DWORD = 174;
+pub const ERROR_INVALID_SEGMENT_NUMBER: DWORD = 180;
+pub const ERROR_INVALID_ORDINAL: DWORD = 182;
+pub const ERROR_ALREADY_EXISTS: DWORD = 183;
+pub const ERROR_INVALID_FLAG_NUMBER: DWORD = 186;
+pub const ERROR_SEM_NOT_FOUND: DWORD = 187;
+pub const ERROR_INVALID_STARTING_CODESEG: DWORD = 188;
+pub const ERROR_INVALID_STACKSEG: DWORD = 189;
+pub const ERROR_INVALID_MODULETYPE: DWORD = 190;
+pub const ERROR_INVALID_EXE_SIGNATURE: DWORD = 191;
+pub const ERROR_EXE_MARKED_INVALID: DWORD = 192;
+pub const ERROR_BAD_EXE_FORMAT: DWORD = 193;
+pub const ERROR_ITERATED_DATA_EXCEEDS_64k: DWORD = 194;
+pub const ERROR_INVALID_MINALLOCSIZE: DWORD = 195;
+pub const ERROR_DYNLINK_FROM_INVALID_RING: DWORD = 196;
+pub const ERROR_IOPL_NOT_ENABLED: DWORD = 197;
+pub const ERROR_INVALID_SEGDPL: DWORD = 198;
+pub const ERROR_AUTODATASEG_EXCEEDS_64k: DWORD = 199;
+pub const ERROR_RING2SEG_MUST_BE_MOVABLE: DWORD = 200;
+pub const ERROR_RELOC_CHAIN_XEEDS_SEGLIM: DWORD = 201;
+pub const ERROR_INFLOOP_IN_RELOC_CHAIN: DWORD = 202;
+pub const ERROR_ENVVAR_NOT_FOUND: DWORD = 203;
+pub const ERROR_NO_SIGNAL_SENT: DWORD = 205;
+pub const ERROR_FILENAME_EXCED_RANGE: DWORD = 206;
+pub const ERROR_RING2_STACK_IN_USE: DWORD = 207;
+pub const ERROR_META_EXPANSION_TOO_LONG: DWORD = 208;
+pub const ERROR_INVALID_SIGNAL_NUMBER: DWORD = 209;
+pub const ERROR_THREAD_1_INACTIVE: DWORD = 210;
+pub const ERROR_LOCKED: DWORD = 212;
+pub const ERROR_TOO_MANY_MODULES: DWORD = 214;
+pub const ERROR_NESTING_NOT_ALLOWED: DWORD = 215;
+pub const ERROR_EXE_MACHINE_TYPE_MISMATCH: DWORD = 216;
+pub const ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY: DWORD = 217;
+pub const ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY: DWORD = 218;
+pub const ERROR_FILE_CHECKED_OUT: DWORD = 220;
+pub const ERROR_CHECKOUT_REQUIRED: DWORD = 221;
+pub const ERROR_BAD_FILE_TYPE: DWORD = 222;
+pub const ERROR_FILE_TOO_LARGE: DWORD = 223;
+pub const ERROR_FORMS_AUTH_REQUIRED: DWORD = 224;
+pub const ERROR_PIPE_LOCAL: DWORD = 229;
+pub const ERROR_BAD_PIPE: DWORD = 230;
+pub const ERROR_PIPE_BUSY: DWORD = 231;
+pub const ERROR_NO_DATA: DWORD = 232;
+pub const ERROR_PIPE_NOT_CONNECTED: DWORD = 233;
+pub const ERROR_MORE_DATA: DWORD = 234;
+pub const ERROR_VC_DISCONNECTED: DWORD = 240;
+pub const ERROR_INVALID_EA_NAME: DWORD = 254;
+pub const ERROR_EA_LIST_INCONSISTENT: DWORD = 255;
+pub const ERROR_NO_MORE_ITEMS: DWORD = 259;
+pub const ERROR_CANNOT_COPY: DWORD = 266;
+pub const ERROR_DIRECTORY: DWORD = 267;
+pub const ERROR_EAS_DIDNT_FIT: DWORD = 275;
+pub const ERROR_EA_FILE_CORRUPT: DWORD = 276;
+pub const ERROR_EA_TABLE_FULL: DWORD = 277;
+pub const ERROR_INVALID_EA_HANDLE: DWORD = 278;
+pub const ERROR_EAS_NOT_SUPPORTED: DWORD = 282;
+pub const ERROR_NOT_OWNER: DWORD = 288;
+pub const ERROR_TOO_MANY_POSTS: DWORD = 298;
+pub const ERROR_PARTIAL_COPY: DWORD = 299;
+pub const ERROR_OPLOCK_NOT_GRANTED: DWORD = 300;
+pub const ERROR_INVALID_OPLOCK_PROTOCOL: DWORD = 301;
+pub const ERROR_DISK_TOO_FRAGMENTED: DWORD = 302;
+pub const ERROR_DELETE_PENDING: DWORD = 303;
+pub const ERROR_INVALID_TOKEN: DWORD = 315;
+pub const ERROR_MR_MID_NOT_FOUND: DWORD = 317;
+pub const ERROR_SCOPE_NOT_FOUND: DWORD = 318;
+pub const ERROR_INVALID_ADDRESS: DWORD = 487;
+pub const ERROR_ARITHMETIC_OVERFLOW: DWORD = 534;
+pub const ERROR_PIPE_CONNECTED: DWORD = 535;
+pub const ERROR_PIPE_LISTENING: DWORD = 536;
+pub const ERROR_WAKE_SYSTEM: DWORD = 730;
+pub const ERROR_WAIT_1: DWORD = 731;
+pub const ERROR_WAIT_2: DWORD = 732;
+pub const ERROR_WAIT_3: DWORD = 733;
+pub const ERROR_WAIT_63: DWORD = 734;
+pub const ERROR_ABANDONED_WAIT_0: DWORD = 735;
+pub const ERROR_ABANDONED_WAIT_63: DWORD = 736;
+pub const ERROR_USER_APC: DWORD = 737;
+pub const ERROR_KERNEL_APC: DWORD = 738;
+pub const ERROR_ALERTED: DWORD = 739;
+pub const ERROR_EA_ACCESS_DENIED: DWORD = 994;
+pub const ERROR_OPERATION_ABORTED: DWORD = 995;
+pub const ERROR_IO_INCOMPLETE: DWORD = 996;
+pub const ERROR_IO_PENDING: DWORD = 997;
+pub const ERROR_NOACCESS: DWORD = 998;
+pub const ERROR_SWAPERROR: DWORD = 999;
+pub const ERROR_STACK_OVERFLOW: DWORD = 1001;
+pub const ERROR_INVALID_MESSAGE: DWORD = 1002;
+pub const ERROR_CAN_NOT_COMPLETE: DWORD = 1003;
+pub const ERROR_INVALID_FLAGS: DWORD = 1004;
+pub const ERROR_UNRECOGNIZED_VOLUME: DWORD = 1005;
+pub const ERROR_FILE_INVALID: DWORD = 1006;
+pub const ERROR_FULLSCREEN_MODE: DWORD = 1007;
+pub const ERROR_NO_TOKEN: DWORD = 1008;
+pub const ERROR_BADDB: DWORD = 1009;
+pub const ERROR_BADKEY: DWORD = 1010;
+pub const ERROR_CANTOPEN: DWORD = 1011;
+pub const ERROR_CANTREAD: DWORD = 1012;
+pub const ERROR_CANTWRITE: DWORD = 1013;
+pub const ERROR_REGISTRY_RECOVERED: DWORD = 1014;
+pub const ERROR_REGISTRY_CORRUPT: DWORD = 1015;
+pub const ERROR_REGISTRY_IO_FAILED: DWORD = 1016;
+pub const ERROR_NOT_REGISTRY_FILE: DWORD = 1017;
+pub const ERROR_KEY_DELETED: DWORD = 1018;
+pub const ERROR_NO_LOG_SPACE: DWORD = 1019;
+pub const ERROR_KEY_HAS_CHILDREN: DWORD = 1020;
+pub const ERROR_CHILD_MUST_BE_VOLATILE: DWORD = 1021;
+pub const ERROR_NOTIFY_ENUM_DIR: DWORD = 1022;
+pub const ERROR_DEPENDENT_SERVICES_RUNNING: DWORD = 1051;
+pub const ERROR_INVALID_SERVICE_CONTROL: DWORD = 1052;
+pub const ERROR_SERVICE_REQUEST_TIMEOUT: DWORD = 1053;
+pub const ERROR_SERVICE_NO_THREAD: DWORD = 1054;
+pub const ERROR_SERVICE_DATABASE_LOCKED: DWORD = 1055;
+pub const ERROR_SERVICE_ALREADY_RUNNING: DWORD = 1056;
+pub const ERROR_INVALID_SERVICE_ACCOUNT: DWORD = 1057;
+pub const ERROR_SERVICE_DISABLED: DWORD = 1058;
+pub const ERROR_CIRCULAR_DEPENDENCY: DWORD = 1059;
+pub const ERROR_SERVICE_DOES_NOT_EXIST: DWORD = 1060;
+pub const ERROR_SERVICE_CANNOT_ACCEPT_CTRL: DWORD = 1061;
+pub const ERROR_SERVICE_NOT_ACTIVE: DWORD = 1062;
+pub const ERROR_FAILED_SERVICE_CONTROLLER_CONNECT: DWORD = 1063;
+pub const ERROR_EXCEPTION_IN_SERVICE: DWORD = 1064;
+pub const ERROR_DATABASE_DOES_NOT_EXIST: DWORD = 1065;
+pub const ERROR_SERVICE_SPECIFIC_ERROR: DWORD = 1066;
+pub const ERROR_PROCESS_ABORTED: DWORD = 1067;
+pub const ERROR_SERVICE_DEPENDENCY_FAIL: DWORD = 1068;
+pub const ERROR_SERVICE_LOGON_FAILED: DWORD = 1069;
+pub const ERROR_SERVICE_START_HANG: DWORD = 1070;
+pub const ERROR_INVALID_SERVICE_LOCK: DWORD = 1071;
+pub const ERROR_SERVICE_MARKED_FOR_DELETE: DWORD = 1072;
+pub const ERROR_SERVICE_EXISTS: DWORD = 1073;
+pub const ERROR_ALREADY_RUNNING_LKG: DWORD = 1074;
+pub const ERROR_SERVICE_DEPENDENCY_DELETED: DWORD = 1075;
+pub const ERROR_BOOT_ALREADY_ACCEPTED: DWORD = 1076;
+pub const ERROR_SERVICE_NEVER_STARTED: DWORD = 1077;
+pub const ERROR_DUPLICATE_SERVICE_NAME: DWORD = 1078;
+pub const ERROR_DIFFERENT_SERVICE_ACCOUNT: DWORD = 1079;
+pub const ERROR_CANNOT_DETECT_DRIVER_FAILURE: DWORD = 1080;
+pub const ERROR_CANNOT_DETECT_PROCESS_ABORT: DWORD = 1081;
+pub const ERROR_NO_RECOVERY_PROGRAM: DWORD = 1082;
+pub const ERROR_SERVICE_NOT_IN_EXE: DWORD = 1083;
+pub const ERROR_NOT_SAFEBOOT_SERVICE: DWORD = 1084;
+pub const ERROR_END_OF_MEDIA: DWORD = 1100;
+pub const ERROR_FILEMARK_DETECTED: DWORD = 1101;
+pub const ERROR_BEGINNING_OF_MEDIA: DWORD = 1102;
+pub const ERROR_SETMARK_DETECTED: DWORD = 1103;
+pub const ERROR_NO_DATA_DETECTED: DWORD = 1104;
+pub const ERROR_PARTITION_FAILURE: DWORD = 1105;
+pub const ERROR_INVALID_BLOCK_LENGTH: DWORD = 1106;
+pub const ERROR_DEVICE_NOT_PARTITIONED: DWORD = 1107;
+pub const ERROR_UNABLE_TO_LOCK_MEDIA: DWORD = 1108;
+pub const ERROR_UNABLE_TO_UNLOAD_MEDIA: DWORD = 1109;
+pub const ERROR_MEDIA_CHANGED: DWORD = 1110;
+pub const ERROR_BUS_RESET: DWORD = 1111;
+pub const ERROR_NO_MEDIA_IN_DRIVE: DWORD = 1112;
+pub const ERROR_NO_UNICODE_TRANSLATION: DWORD = 1113;
+pub const ERROR_DLL_INIT_FAILED: DWORD = 1114;
+pub const ERROR_SHUTDOWN_IN_PROGRESS: DWORD = 1115;
+pub const ERROR_NO_SHUTDOWN_IN_PROGRESS: DWORD = 1116;
+pub const ERROR_IO_DEVICE: DWORD = 1117;
+pub const ERROR_SERIAL_NO_DEVICE: DWORD = 1118;
+pub const ERROR_IRQ_BUSY: DWORD = 1119;
+pub const ERROR_MORE_WRITES: DWORD = 1120;
+pub const ERROR_COUNTER_TIMEOUT: DWORD = 1121;
+pub const ERROR_FLOPPY_ID_MARK_NOT_FOUND: DWORD = 1122;
+pub const ERROR_FLOPPY_WRONG_CYLINDER: DWORD = 1123;
+pub const ERROR_FLOPPY_UNKNOWN_ERROR: DWORD = 1124;
+pub const ERROR_FLOPPY_BAD_REGISTERS: DWORD = 1125;
+pub const ERROR_DISK_RECALIBRATE_FAILED: DWORD = 1126;
+pub const ERROR_DISK_OPERATION_FAILED: DWORD = 1127;
+pub const ERROR_DISK_RESET_FAILED: DWORD = 1128;
+pub const ERROR_EOM_OVERFLOW: DWORD = 1129;
+pub const ERROR_NOT_ENOUGH_SERVER_MEMORY: DWORD = 1130;
+pub const ERROR_POSSIBLE_DEADLOCK: DWORD = 1131;
+pub const ERROR_MAPPED_ALIGNMENT: DWORD = 1132;
+pub const ERROR_SET_POWER_STATE_VETOED: DWORD = 1140;
+pub const ERROR_SET_POWER_STATE_FAILED: DWORD = 1141;
+pub const ERROR_TOO_MANY_LINKS: DWORD = 1142;
+pub const ERROR_OLD_WIN_VERSION: DWORD = 1150;
+pub const ERROR_APP_WRONG_OS: DWORD = 1151;
+pub const ERROR_SINGLE_INSTANCE_APP: DWORD = 1152;
+pub const ERROR_RMODE_APP: DWORD = 1153;
+pub const ERROR_INVALID_DLL: DWORD = 1154;
+pub const ERROR_NO_ASSOCIATION: DWORD = 1155;
+pub const ERROR_DDE_FAIL: DWORD = 1156;
+pub const ERROR_DLL_NOT_FOUND: DWORD = 1157;
+pub const ERROR_NO_MORE_USER_HANDLES: DWORD = 1158;
+pub const ERROR_MESSAGE_SYNC_ONLY: DWORD = 1159;
+pub const ERROR_SOURCE_ELEMENT_EMPTY: DWORD = 1160;
+pub const ERROR_DESTINATION_ELEMENT_FULL: DWORD = 1161;
+pub const ERROR_ILLEGAL_ELEMENT_ADDRESS: DWORD = 1162;
+pub const ERROR_MAGAZINE_NOT_PRESENT: DWORD = 1163;
+pub const ERROR_DEVICE_REINITIALIZATION_NEEDED: DWORD = 1164;
+pub const ERROR_DEVICE_REQUIRES_CLEANING: DWORD = 1165;
+pub const ERROR_DEVICE_DOOR_OPEN: DWORD = 1166;
+pub const ERROR_DEVICE_NOT_CONNECTED: DWORD = 1167;
+pub const ERROR_NOT_FOUND: DWORD = 1168;
+pub const ERROR_NO_MATCH: DWORD = 1169;
+pub const ERROR_SET_NOT_FOUND: DWORD = 1170;
+pub const ERROR_POINT_NOT_FOUND: DWORD = 1171;
+pub const ERROR_NO_TRACKING_SERVICE: DWORD = 1172;
+pub const ERROR_NO_VOLUME_ID: DWORD = 1173;
+pub const ERROR_UNABLE_TO_REMOVE_REPLACED: DWORD = 1175;
+pub const ERROR_UNABLE_TO_MOVE_REPLACEMENT: DWORD = 1176;
+pub const ERROR_UNABLE_TO_MOVE_REPLACEMENT_2: DWORD = 1177;
+pub const ERROR_JOURNAL_DELETE_IN_PROGRESS: DWORD = 1178;
+pub const ERROR_JOURNAL_NOT_ACTIVE: DWORD = 1179;
+pub const ERROR_POTENTIAL_FILE_FOUND: DWORD = 1180;
+pub const ERROR_JOURNAL_ENTRY_DELETED: DWORD = 1181;
+pub const ERROR_BAD_DEVICE: DWORD = 1200;
+pub const ERROR_CONNECTION_UNAVAIL: DWORD = 1201;
+pub const ERROR_DEVICE_ALREADY_REMEMBERED: DWORD = 1202;
+pub const ERROR_NO_NET_OR_BAD_PATH: DWORD = 1203;
+pub const ERROR_BAD_PROVIDER: DWORD = 1204;
+pub const ERROR_CANNOT_OPEN_PROFILE: DWORD = 1205;
+pub const ERROR_BAD_PROFILE: DWORD = 1206;
+pub const ERROR_NOT_CONTAINER: DWORD = 1207;
+pub const ERROR_EXTENDED_ERROR: DWORD = 1208;
+pub const ERROR_INVALID_GROUPNAME: DWORD = 1209;
+pub const ERROR_INVALID_COMPUTERNAME: DWORD = 1210;
+pub const ERROR_INVALID_EVENTNAME: DWORD = 1211;
+pub const ERROR_INVALID_DOMAINNAME: DWORD = 1212;
+pub const ERROR_INVALID_SERVICENAME: DWORD = 1213;
+pub const ERROR_INVALID_NETNAME: DWORD = 1214;
+pub const ERROR_INVALID_SHARENAME: DWORD = 1215;
+pub const ERROR_INVALID_PASSWORDNAME: DWORD = 1216;
+pub const ERROR_INVALID_MESSAGENAME: DWORD = 1217;
+pub const ERROR_INVALID_MESSAGEDEST: DWORD = 1218;
+pub const ERROR_SESSION_CREDENTIAL_CONFLICT: DWORD = 1219;
+pub const ERROR_REMOTE_SESSION_LIMIT_EXCEEDED: DWORD = 1220;
+pub const ERROR_DUP_DOMAINNAME: DWORD = 1221;
+pub const ERROR_NO_NETWORK: DWORD = 1222;
+pub const ERROR_CANCELLED: DWORD = 1223;
+pub const ERROR_USER_MAPPED_FILE: DWORD = 1224;
+pub const ERROR_CONNECTION_REFUSED: DWORD = 1225;
+pub const ERROR_GRACEFUL_DISCONNECT: DWORD = 1226;
+pub const ERROR_ADDRESS_ALREADY_ASSOCIATED: DWORD = 1227;
+pub const ERROR_ADDRESS_NOT_ASSOCIATED: DWORD = 1228;
+pub const ERROR_CONNECTION_INVALID: DWORD = 1229;
+pub const ERROR_CONNECTION_ACTIVE: DWORD = 1230;
+pub const ERROR_NETWORK_UNREACHABLE: DWORD = 1231;
+pub const ERROR_HOST_UNREACHABLE: DWORD = 1232;
+pub const ERROR_PROTOCOL_UNREACHABLE: DWORD = 1233;
+pub const ERROR_PORT_UNREACHABLE: DWORD = 1234;
+pub const ERROR_REQUEST_ABORTED: DWORD = 1235;
+pub const ERROR_CONNECTION_ABORTED: DWORD = 1236;
+pub const ERROR_RETRY: DWORD = 1237;
+pub const ERROR_CONNECTION_COUNT_LIMIT: DWORD = 1238;
+pub const ERROR_LOGIN_TIME_RESTRICTION: DWORD = 1239;
+pub const ERROR_LOGIN_WKSTA_RESTRICTION: DWORD = 1240;
+pub const ERROR_INCORRECT_ADDRESS: DWORD = 1241;
+pub const ERROR_ALREADY_REGISTERED: DWORD = 1242;
+pub const ERROR_SERVICE_NOT_FOUND: DWORD = 1243;
+pub const ERROR_NOT_AUTHENTICATED: DWORD = 1244;
+pub const ERROR_NOT_LOGGED_ON: DWORD = 1245;
+pub const ERROR_CONTINUE: DWORD = 1246;
+pub const ERROR_ALREADY_INITIALIZED: DWORD = 1247;
+pub const ERROR_NO_MORE_DEVICES: DWORD = 1248;
+pub const ERROR_NO_SUCH_SITE: DWORD = 1249;
+pub const ERROR_DOMAIN_CONTROLLER_EXISTS: DWORD = 1250;
+pub const ERROR_ONLY_IF_CONNECTED: DWORD = 1251;
+pub const ERROR_OVERRIDE_NOCHANGES: DWORD = 1252;
+pub const ERROR_BAD_USER_PROFILE: DWORD = 1253;
+pub const ERROR_NOT_SUPPORTED_ON_SBS: DWORD = 1254;
+pub const ERROR_SERVER_SHUTDOWN_IN_PROGRESS: DWORD = 1255;
+pub const ERROR_HOST_DOWN: DWORD = 1256;
+pub const ERROR_NON_ACCOUNT_SID: DWORD = 1257;
+pub const ERROR_NON_DOMAIN_SID: DWORD = 1258;
+pub const ERROR_APPHELP_BLOCK: DWORD = 1259;
+pub const ERROR_ACCESS_DISABLED_BY_POLICY: DWORD = 1260;
+pub const ERROR_REG_NAT_CONSUMPTION: DWORD = 1261;
+pub const ERROR_CSCSHARE_OFFLINE: DWORD = 1262;
+pub const ERROR_PKINIT_FAILURE: DWORD = 1263;
+pub const ERROR_SMARTCARD_SUBSYSTEM_FAILURE: DWORD = 1264;
+pub const ERROR_DOWNGRADE_DETECTED: DWORD = 1265;
+pub const ERROR_MACHINE_LOCKED: DWORD = 1271;
+pub const ERROR_CALLBACK_SUPPLIED_INVALID_DATA: DWORD = 1273;
+pub const ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED: DWORD = 1274;
+pub const ERROR_DRIVER_BLOCKED: DWORD = 1275;
+pub const ERROR_INVALID_IMPORT_OF_NON_DLL: DWORD = 1276;
+pub const ERROR_ACCESS_DISABLED_WEBBLADE: DWORD = 1277;
+pub const ERROR_ACCESS_DISABLED_WEBBLADE_TAMPER: DWORD = 1278;
+pub const ERROR_RECOVERY_FAILURE: DWORD = 1279;
+pub const ERROR_ALREADY_FIBER: DWORD = 1280;
+pub const ERROR_ALREADY_THREAD: DWORD = 1281;
+pub const ERROR_STACK_BUFFER_OVERRUN: DWORD = 1282;
+pub const ERROR_PARAMETER_QUOTA_EXCEEDED: DWORD = 1283;
+pub const ERROR_DEBUGGER_INACTIVE: DWORD = 1284;
+pub const ERROR_DELAY_LOAD_FAILED: DWORD = 1285;
+pub const ERROR_VDM_DISALLOWED: DWORD = 1286;
+pub const ERROR_UNIDENTIFIED_ERROR: DWORD = 1287;
+pub const ERROR_NOT_ALL_ASSIGNED: DWORD = 1300;
+pub const ERROR_SOME_NOT_MAPPED: DWORD = 1301;
+pub const ERROR_NO_QUOTAS_FOR_ACCOUNT: DWORD = 1302;
+pub const ERROR_LOCAL_USER_SESSION_KEY: DWORD = 1303;
+pub const ERROR_NULL_LM_PASSWORD: DWORD = 1304;
+pub const ERROR_UNKNOWN_REVISION: DWORD = 1305;
+pub const ERROR_REVISION_MISMATCH: DWORD = 1306;
+pub const ERROR_INVALID_OWNER: DWORD = 1307;
+pub const ERROR_INVALID_PRIMARY_GROUP: DWORD = 1308;
+pub const ERROR_NO_IMPERSONATION_TOKEN: DWORD = 1309;
+pub const ERROR_CANT_DISABLE_MANDATORY: DWORD = 1310;
+pub const ERROR_NO_LOGON_SERVERS: DWORD = 1311;
+pub const ERROR_NO_SUCH_LOGON_SESSION: DWORD = 1312;
+pub const ERROR_NO_SUCH_PRIVILEGE: DWORD = 1313;
+pub const ERROR_PRIVILEGE_NOT_HELD: DWORD = 1314;
+pub const ERROR_INVALID_ACCOUNT_NAME: DWORD = 1315;
+pub const ERROR_USER_EXISTS: DWORD = 1316;
+pub const ERROR_NO_SUCH_USER: DWORD = 1317;
+pub const ERROR_GROUP_EXISTS: DWORD = 1318;
+pub const ERROR_NO_SUCH_GROUP: DWORD = 1319;
+pub const ERROR_MEMBER_IN_GROUP: DWORD = 1320;
+pub const ERROR_MEMBER_NOT_IN_GROUP: DWORD = 1321;
+pub const ERROR_LAST_ADMIN: DWORD = 1322;
+pub const ERROR_WRONG_PASSWORD: DWORD = 1323;
+pub const ERROR_ILL_FORMED_PASSWORD: DWORD = 1324;
+pub const ERROR_PASSWORD_RESTRICTION: DWORD = 1325;
+pub const ERROR_LOGON_FAILURE: DWORD = 1326;
+pub const ERROR_ACCOUNT_RESTRICTION: DWORD = 1327;
+pub const ERROR_INVALID_LOGON_HOURS: DWORD = 1328;
+pub const ERROR_INVALID_WORKSTATION: DWORD = 1329;
+pub const ERROR_PASSWORD_EXPIRED: DWORD = 1330;
+pub const ERROR_ACCOUNT_DISABLED: DWORD = 1331;
+pub const ERROR_NONE_MAPPED: DWORD = 1332;
+pub const ERROR_TOO_MANY_LUIDS_REQUESTED: DWORD = 1333;
+pub const ERROR_LUIDS_EXHAUSTED: DWORD = 1334;
+pub const ERROR_INVALID_SUB_AUTHORITY: DWORD = 1335;
+pub const ERROR_INVALID_ACL: DWORD = 1336;
+pub const ERROR_INVALID_SID: DWORD = 1337;
+pub const ERROR_INVALID_SECURITY_DESCR: DWORD = 1338;
+pub const ERROR_BAD_INHERITANCE_ACL: DWORD = 1340;
+pub const ERROR_SERVER_DISABLED: DWORD = 1341;
+pub const ERROR_SERVER_NOT_DISABLED: DWORD = 1342;
+pub const ERROR_INVALID_ID_AUTHORITY: DWORD = 1343;
+pub const ERROR_ALLOTTED_SPACE_EXCEEDED: DWORD = 1344;
+pub const ERROR_INVALID_GROUP_ATTRIBUTES: DWORD = 1345;
+pub const ERROR_BAD_IMPERSONATION_LEVEL: DWORD = 1346;
+pub const ERROR_CANT_OPEN_ANONYMOUS: DWORD = 1347;
+pub const ERROR_BAD_VALIDATION_CLASS: DWORD = 1348;
+pub const ERROR_BAD_TOKEN_TYPE: DWORD = 1349;
+pub const ERROR_NO_SECURITY_ON_OBJECT: DWORD = 1350;
+pub const ERROR_CANT_ACCESS_DOMAIN_INFO: DWORD = 1351;
+pub const ERROR_INVALID_SERVER_STATE: DWORD = 1352;
+pub const ERROR_INVALID_DOMAIN_STATE: DWORD = 1353;
+pub const ERROR_INVALID_DOMAIN_ROLE: DWORD = 1354;
+pub const ERROR_NO_SUCH_DOMAIN: DWORD = 1355;
+pub const ERROR_DOMAIN_EXISTS: DWORD = 1356;
+pub const ERROR_DOMAIN_LIMIT_EXCEEDED: DWORD = 1357;
+pub const ERROR_INTERNAL_DB_CORRUPTION: DWORD = 1358;
+pub const ERROR_INTERNAL_ERROR: DWORD = 1359;
+pub const ERROR_GENERIC_NOT_MAPPED: DWORD = 1360;
+pub const ERROR_BAD_DESCRIPTOR_FORMAT: DWORD = 1361;
+pub const ERROR_NOT_LOGON_PROCESS: DWORD = 1362;
+pub const ERROR_LOGON_SESSION_EXISTS: DWORD = 1363;
+pub const ERROR_NO_SUCH_PACKAGE: DWORD = 1364;
+pub const ERROR_BAD_LOGON_SESSION_STATE: DWORD = 1365;
+pub const ERROR_LOGON_SESSION_COLLISION: DWORD = 1366;
+pub const ERROR_INVALID_LOGON_TYPE: DWORD = 1367;
+pub const ERROR_CANNOT_IMPERSONATE: DWORD = 1368;
+pub const ERROR_RXACT_INVALID_STATE: DWORD = 1369;
+pub const ERROR_RXACT_COMMIT_FAILURE: DWORD = 1370;
+pub const ERROR_SPECIAL_ACCOUNT: DWORD = 1371;
+pub const ERROR_SPECIAL_GROUP: DWORD = 1372;
+pub const ERROR_SPECIAL_USER: DWORD = 1373;
+pub const ERROR_MEMBERS_PRIMARY_GROUP: DWORD = 1374;
+pub const ERROR_TOKEN_ALREADY_IN_USE: DWORD = 1375;
+pub const ERROR_NO_SUCH_ALIAS: DWORD = 1376;
+pub const ERROR_MEMBER_NOT_IN_ALIAS: DWORD = 1377;
+pub const ERROR_MEMBER_IN_ALIAS: DWORD = 1378;
+pub const ERROR_ALIAS_EXISTS: DWORD = 1379;
+pub const ERROR_LOGON_NOT_GRANTED: DWORD = 1380;
+pub const ERROR_TOO_MANY_SECRETS: DWORD = 1381;
+pub const ERROR_SECRET_TOO_LONG: DWORD = 1382;
+pub const ERROR_INTERNAL_DB_ERROR: DWORD = 1383;
+pub const ERROR_TOO_MANY_CONTEXT_IDS: DWORD = 1384;
+pub const ERROR_LOGON_TYPE_NOT_GRANTED: DWORD = 1385;
+pub const ERROR_NT_CROSS_ENCRYPTION_REQUIRED: DWORD = 1386;
+pub const ERROR_NO_SUCH_MEMBER: DWORD = 1387;
+pub const ERROR_INVALID_MEMBER: DWORD = 1388;
+pub const ERROR_TOO_MANY_SIDS: DWORD = 1389;
+pub const ERROR_LM_CROSS_ENCRYPTION_REQUIRED: DWORD = 1390;
+pub const ERROR_NO_INHERITANCE: DWORD = 1391;
+pub const ERROR_FILE_CORRUPT: DWORD = 1392;
+pub const ERROR_DISK_CORRUPT: DWORD = 1393;
+pub const ERROR_NO_USER_SESSION_KEY: DWORD = 1394;
+pub const ERROR_LICENSE_QUOTA_EXCEEDED: DWORD = 1395;
+pub const ERROR_WRONG_TARGET_NAME: DWORD = 1396;
+pub const ERROR_MUTUAL_AUTH_FAILED: DWORD = 1397;
+pub const ERROR_TIME_SKEW: DWORD = 1398;
+pub const ERROR_CURRENT_DOMAIN_NOT_ALLOWED: DWORD = 1399;
+pub const ERROR_INVALID_WINDOW_HANDLE: DWORD = 1400;
+pub const ERROR_INVALID_MENU_HANDLE: DWORD = 1401;
+pub const ERROR_INVALID_CURSOR_HANDLE: DWORD = 1402;
+pub const ERROR_INVALID_ACCEL_HANDLE: DWORD = 1403;
+pub const ERROR_INVALID_HOOK_HANDLE: DWORD = 1404;
+pub const ERROR_INVALID_DWP_HANDLE: DWORD = 1405;
+pub const ERROR_TLW_WITH_WSCHILD: DWORD = 1406;
+pub const ERROR_CANNOT_FIND_WND_CLASS: DWORD = 1407;
+pub const ERROR_WINDOW_OF_OTHER_THREAD: DWORD = 1408;
+pub const ERROR_HOTKEY_ALREADY_REGISTERED: DWORD = 1409;
+pub const ERROR_CLASS_ALREADY_EXISTS: DWORD = 1410;
+pub const ERROR_CLASS_DOES_NOT_EXIST: DWORD = 1411;
+pub const ERROR_CLASS_HAS_WINDOWS: DWORD = 1412;
+pub const ERROR_INVALID_INDEX: DWORD = 1413;
+pub const ERROR_INVALID_ICON_HANDLE: DWORD = 1414;
+pub const ERROR_PRIVATE_DIALOG_INDEX: DWORD = 1415;
+pub const ERROR_LISTBOX_ID_NOT_FOUND: DWORD = 1416;
+pub const ERROR_NO_WILDCARD_CHARACTERS: DWORD = 1417;
+pub const ERROR_CLIPBOARD_NOT_OPEN: DWORD = 1418;
+pub const ERROR_HOTKEY_NOT_REGISTERED: DWORD = 1419;
+pub const ERROR_WINDOW_NOT_DIALOG: DWORD = 1420;
+pub const ERROR_CONTROL_ID_NOT_FOUND: DWORD = 1421;
+pub const ERROR_INVALID_COMBOBOX_MESSAGE: DWORD = 1422;
+pub const ERROR_WINDOW_NOT_COMBOBOX: DWORD = 1423;
+pub const ERROR_INVALID_EDIT_HEIGHT: DWORD = 1424;
+pub const ERROR_DC_NOT_FOUND: DWORD = 1425;
+pub const ERROR_INVALID_HOOK_FILTER: DWORD = 1426;
+pub const ERROR_INVALID_FILTER_PROC: DWORD = 1427;
+pub const ERROR_HOOK_NEEDS_HMOD: DWORD = 1428;
+pub const ERROR_GLOBAL_ONLY_HOOK: DWORD = 1429;
+pub const ERROR_JOURNAL_HOOK_SET: DWORD = 1430;
+pub const ERROR_HOOK_NOT_INSTALLED: DWORD = 1431;
+pub const ERROR_INVALID_LB_MESSAGE: DWORD = 1432;
+pub const ERROR_SETCOUNT_ON_BAD_LB: DWORD = 1433;
+pub const ERROR_LB_WITHOUT_TABSTOPS: DWORD = 1434;
+pub const ERROR_DESTROY_OBJECT_OF_OTHER_THREAD: DWORD = 1435;
+pub const ERROR_CHILD_WINDOW_MENU: DWORD = 1436;
+pub const ERROR_NO_SYSTEM_MENU: DWORD = 1437;
+pub const ERROR_INVALID_MSGBOX_STYLE: DWORD = 1438;
+pub const ERROR_INVALID_SPI_VALUE: DWORD = 1439;
+pub const ERROR_SCREEN_ALREADY_LOCKED: DWORD = 1440;
+pub const ERROR_HWNDS_HAVE_DIFF_PARENT: DWORD = 1441;
+pub const ERROR_NOT_CHILD_WINDOW: DWORD = 1442;
+pub const ERROR_INVALID_GW_COMMAND: DWORD = 1443;
+pub const ERROR_INVALID_THREAD_ID: DWORD = 1444;
+pub const ERROR_NON_MDICHILD_WINDOW: DWORD = 1445;
+pub const ERROR_POPUP_ALREADY_ACTIVE: DWORD = 1446;
+pub const ERROR_NO_SCROLLBARS: DWORD = 1447;
+pub const ERROR_INVALID_SCROLLBAR_RANGE: DWORD = 1448;
+pub const ERROR_INVALID_SHOWWIN_COMMAND: DWORD = 1449;
+pub const ERROR_NO_SYSTEM_RESOURCES: DWORD = 1450;
+pub const ERROR_NONPAGED_SYSTEM_RESOURCES: DWORD = 1451;
+pub const ERROR_PAGED_SYSTEM_RESOURCES: DWORD = 1452;
+pub const ERROR_WORKING_SET_QUOTA: DWORD = 1453;
+pub const ERROR_PAGEFILE_QUOTA: DWORD = 1454;
+pub const ERROR_COMMITMENT_LIMIT: DWORD = 1455;
+pub const ERROR_MENU_ITEM_NOT_FOUND: DWORD = 1456;
+pub const ERROR_INVALID_KEYBOARD_HANDLE: DWORD = 1457;
+pub const ERROR_HOOK_TYPE_NOT_ALLOWED: DWORD = 1458;
+pub const ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION: DWORD = 1459;
+pub const ERROR_TIMEOUT: DWORD = 1460;
+pub const ERROR_INVALID_MONITOR_HANDLE: DWORD = 1461;
+pub const ERROR_INCORRECT_SIZE: DWORD = 1462;
+pub const ERROR_SYMLINK_CLASS_DISABLED: DWORD = 1463;
+pub const ERROR_SYMLINK_NOT_SUPPORTED: DWORD = 1464;
+pub const ERROR_XML_PARSE_ERROR: DWORD = 1465;
+pub const ERROR_XMLDSIG_ERROR: DWORD = 1466;
+pub const ERROR_RESTART_APPLICATION: DWORD = 1467;
+pub const ERROR_WRONG_COMPARTMENT: DWORD = 1468;
+pub const ERROR_AUTHIP_FAILURE: DWORD = 1469;
+pub const ERROR_NO_NVRAM_RESOURCES: DWORD = 1470;
+pub const ERROR_NOT_GUI_PROCESS: DWORD = 1471;
+pub const ERROR_EVENTLOG_FILE_CORRUPT: DWORD = 1500;
+pub const ERROR_EVENTLOG_CANT_START: DWORD = 1501;
+pub const ERROR_LOG_FILE_FULL: DWORD = 1502;
+pub const ERROR_EVENTLOG_FILE_CHANGED: DWORD = 1503;
+pub const ERROR_INSTALL_SERVICE_FAILURE: DWORD = 1601;
+pub const ERROR_INSTALL_USEREXIT: DWORD = 1602;
+pub const ERROR_INSTALL_FAILURE: DWORD = 1603;
+pub const ERROR_INSTALL_SUSPEND: DWORD = 1604;
+pub const ERROR_UNKNOWN_PRODUCT: DWORD = 1605;
+pub const ERROR_UNKNOWN_FEATURE: DWORD = 1606;
+pub const ERROR_UNKNOWN_COMPONENT: DWORD = 1607;
+pub const ERROR_UNKNOWN_PROPERTY: DWORD = 1608;
+pub const ERROR_INVALID_HANDLE_STATE: DWORD = 1609;
+pub const ERROR_BAD_CONFIGURATION: DWORD = 1610;
+pub const ERROR_INDEX_ABSENT: DWORD = 1611;
+pub const ERROR_INSTALL_SOURCE_ABSENT: DWORD = 1612;
+pub const ERROR_INSTALL_PACKAGE_VERSION: DWORD = 1613;
+pub const ERROR_PRODUCT_UNINSTALLED: DWORD = 1614;
+pub const ERROR_BAD_QUERY_SYNTAX: DWORD = 1615;
+pub const ERROR_INVALID_FIELD: DWORD = 1616;
+pub const ERROR_DEVICE_REMOVED: DWORD = 1617;
+pub const ERROR_INSTALL_ALREADY_RUNNING: DWORD = 1618;
+pub const ERROR_INSTALL_PACKAGE_OPEN_FAILED: DWORD = 1619;
+pub const ERROR_INSTALL_PACKAGE_INVALID: DWORD = 1620;
+pub const ERROR_INSTALL_UI_FAILURE: DWORD = 1621;
+pub const ERROR_INSTALL_LOG_FAILURE: DWORD = 1622;
+pub const ERROR_INSTALL_LANGUAGE_UNSUPPORTED: DWORD = 1623;
+pub const ERROR_INSTALL_TRANSFORM_FAILURE: DWORD = 1624;
+pub const ERROR_INSTALL_PACKAGE_REJECTED: DWORD = 1625;
+pub const ERROR_FUNCTION_NOT_CALLED: DWORD = 1626;
+pub const ERROR_FUNCTION_FAILED: DWORD = 1627;
+pub const ERROR_INVALID_TABLE: DWORD = 1628;
+pub const ERROR_DATATYPE_MISMATCH: DWORD = 1629;
+pub const ERROR_UNSUPPORTED_TYPE: DWORD = 1630;
+pub const ERROR_CREATE_FAILED: DWORD = 1631;
+pub const ERROR_INSTALL_TEMP_UNWRITABLE: DWORD = 1632;
+pub const ERROR_INSTALL_PLATFORM_UNSUPPORTED: DWORD = 1633;
+pub const ERROR_INSTALL_NOTUSED: DWORD = 1634;
+pub const ERROR_PATCH_PACKAGE_OPEN_FAILED: DWORD = 1635;
+pub const ERROR_PATCH_PACKAGE_INVALID: DWORD = 1636;
+pub const ERROR_PATCH_PACKAGE_UNSUPPORTED: DWORD = 1637;
+pub const ERROR_PRODUCT_VERSION: DWORD = 1638;
+pub const ERROR_INVALID_COMMAND_LINE: DWORD = 1639;
+pub const ERROR_INSTALL_REMOTE_DISALLOWED: DWORD = 1640;
+pub const ERROR_SUCCESS_REBOOT_INITIATED: DWORD = 1641;
+pub const ERROR_PATCH_TARGET_NOT_FOUND: DWORD = 1642;
+pub const ERROR_PATCH_PACKAGE_REJECTED: DWORD = 1643;
+pub const ERROR_INSTALL_TRANSFORM_REJECTED: DWORD = 1644;
+pub const ERROR_INSTALL_REMOTE_PROHIBITED: DWORD = 1645;
+pub const ERROR_INVALID_USER_BUFFER: DWORD = 1784;
+pub const ERROR_UNRECOGNIZED_MEDIA: DWORD = 1785;
+pub const ERROR_NO_TRUST_LSA_SECRET: DWORD = 1786;
+pub const ERROR_NO_TRUST_SAM_ACCOUNT: DWORD = 1787;
+pub const ERROR_TRUSTED_DOMAIN_FAILURE: DWORD = 1788;
+pub const ERROR_TRUSTED_RELATIONSHIP_FAILURE: DWORD = 1789;
+pub const ERROR_TRUST_FAILURE: DWORD = 1790;
+pub const ERROR_NETLOGON_NOT_STARTED: DWORD = 1792;
+pub const ERROR_ACCOUNT_EXPIRED: DWORD = 1793;
+pub const ERROR_REDIRECTOR_HAS_OPEN_HANDLES: DWORD = 1794;
+pub const ERROR_PRINTER_DRIVER_ALREADY_INSTALLED: DWORD = 1795;
+pub const ERROR_UNKNOWN_PORT: DWORD = 1796;
+pub const ERROR_UNKNOWN_PRINTER_DRIVER: DWORD = 1797;
+pub const ERROR_UNKNOWN_PRINTPROCESSOR: DWORD = 1798;
+pub const ERROR_INVALID_SEPARATOR_FILE: DWORD = 1799;
+pub const ERROR_INVALID_PRIORITY: DWORD = 1800;
+pub const ERROR_INVALID_PRINTER_NAME: DWORD = 1801;
+pub const ERROR_PRINTER_ALREADY_EXISTS: DWORD = 1802;
+pub const ERROR_INVALID_PRINTER_COMMAND: DWORD = 1803;
+pub const ERROR_INVALID_DATATYPE: DWORD = 1804;
+pub const ERROR_INVALID_ENVIRONMENT: DWORD = 1805;
+pub const ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT: DWORD = 1807;
+pub const ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT: DWORD = 1808;
+pub const ERROR_NOLOGON_SERVER_TRUST_ACCOUNT: DWORD = 1809;
+pub const ERROR_DOMAIN_TRUST_INCONSISTENT: DWORD = 1810;
+pub const ERROR_SERVER_HAS_OPEN_HANDLES: DWORD = 1811;
+pub const ERROR_RESOURCE_DATA_NOT_FOUND: DWORD = 1812;
+pub const ERROR_RESOURCE_TYPE_NOT_FOUND: DWORD = 1813;
+pub const ERROR_RESOURCE_NAME_NOT_FOUND: DWORD = 1814;
+pub const ERROR_RESOURCE_LANG_NOT_FOUND: DWORD = 1815;
+pub const ERROR_NOT_ENOUGH_QUOTA: DWORD = 1816;
+pub const ERROR_INVALID_TIME: DWORD = 1901;
+pub const ERROR_INVALID_FORM_NAME: DWORD = 1902;
+pub const ERROR_INVALID_FORM_SIZE: DWORD = 1903;
+pub const ERROR_ALREADY_WAITING: DWORD = 1904;
+pub const ERROR_PRINTER_DELETED: DWORD = 1905;
+pub const ERROR_INVALID_PRINTER_STATE: DWORD = 1906;
+pub const ERROR_PASSWORD_MUST_CHANGE: DWORD = 1907;
+pub const ERROR_DOMAIN_CONTROLLER_NOT_FOUND: DWORD = 1908;
+pub const ERROR_ACCOUNT_LOCKED_OUT: DWORD = 1909;
+pub const ERROR_NO_SITENAME: DWORD = 1919;
+pub const ERROR_CANT_ACCESS_FILE: DWORD = 1920;
+pub const ERROR_CANT_RESOLVE_FILENAME: DWORD = 1921;
+pub const ERROR_KM_DRIVER_BLOCKED: DWORD = 1930;
+pub const ERROR_CONTEXT_EXPIRED: DWORD = 1931;
+pub const ERROR_PER_USER_TRUST_QUOTA_EXCEEDED: DWORD = 1932;
+pub const ERROR_ALL_USER_TRUST_QUOTA_EXCEEDED: DWORD = 1933;
+pub const ERROR_USER_DELETE_TRUST_QUOTA_EXCEEDED: DWORD = 1934;
+pub const ERROR_AUTHENTICATION_FIREWALL_FAILED: DWORD = 1935;
+pub const ERROR_REMOTE_PRINT_CONNECTIONS_BLOCKED: DWORD = 1936;
+pub const ERROR_INVALID_PIXEL_FORMAT: DWORD = 2000;
+pub const ERROR_BAD_DRIVER: DWORD = 2001;
+pub const ERROR_INVALID_WINDOW_STYLE: DWORD = 2002;
+pub const ERROR_METAFILE_NOT_SUPPORTED: DWORD = 2003;
+pub const ERROR_TRANSFORM_NOT_SUPPORTED: DWORD = 2004;
+pub const ERROR_CLIPPING_NOT_SUPPORTED: DWORD = 2005;
+pub const ERROR_INVALID_CMM: DWORD = 2010;
+pub const ERROR_INVALID_PROFILE: DWORD = 2011;
+pub const ERROR_TAG_NOT_FOUND: DWORD = 2012;
+pub const ERROR_TAG_NOT_PRESENT: DWORD = 2013;
+pub const ERROR_DUPLICATE_TAG: DWORD = 2014;
+pub const ERROR_PROFILE_NOT_ASSOCIATED_WITH_DEVICE: DWORD = 2015;
+pub const ERROR_PROFILE_NOT_FOUND: DWORD = 2016;
+pub const ERROR_INVALID_COLORSPACE: DWORD = 2017;
+pub const ERROR_ICM_NOT_ENABLED: DWORD = 2018;
+pub const ERROR_DELETING_ICM_XFORM: DWORD = 2019;
+pub const ERROR_INVALID_TRANSFORM: DWORD = 2020;
+pub const ERROR_COLORSPACE_MISMATCH: DWORD = 2021;
+pub const ERROR_INVALID_COLORINDEX: DWORD = 2022;
+pub const ERROR_CONNECTED_OTHER_PASSWORD: DWORD = 2108;
+pub const ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT: DWORD = 2109;
+pub const ERROR_BAD_USERNAME: DWORD = 2202;
+pub const ERROR_NOT_CONNECTED: DWORD = 2250;
+pub const ERROR_OPEN_FILES: DWORD = 2401;
+pub const ERROR_ACTIVE_CONNECTIONS: DWORD = 2402;
+pub const ERROR_DEVICE_IN_USE: DWORD = 2404;
+pub const ERROR_UNKNOWN_PRINT_MONITOR: DWORD = 3000;
+pub const ERROR_PRINTER_DRIVER_IN_USE: DWORD = 3001;
+pub const ERROR_SPOOL_FILE_NOT_FOUND: DWORD = 3002;
+pub const ERROR_SPL_NO_STARTDOC: DWORD = 3003;
+pub const ERROR_SPL_NO_ADDJOB: DWORD = 3004;
+pub const ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED: DWORD = 3005;
+pub const ERROR_PRINT_MONITOR_ALREADY_INSTALLED: DWORD = 3006;
+pub const ERROR_INVALID_PRINT_MONITOR: DWORD = 3007;
+pub const ERROR_PRINT_MONITOR_IN_USE: DWORD = 3008;
+pub const ERROR_PRINTER_HAS_JOBS_QUEUED: DWORD = 3009;
+pub const ERROR_SUCCESS_REBOOT_REQUIRED: DWORD = 3010;
+pub const ERROR_SUCCESS_RESTART_REQUIRED: DWORD = 3011;
+pub const ERROR_PRINTER_NOT_FOUND: DWORD = 3012;
+pub const ERROR_PRINTER_DRIVER_WARNED: DWORD = 3013;
+pub const ERROR_PRINTER_DRIVER_BLOCKED: DWORD = 3014;
+pub const ERROR_WINS_INTERNAL: DWORD = 4000;
+pub const ERROR_CAN_NOT_DEL_LOCAL_WINS: DWORD = 4001;
+pub const ERROR_STATIC_INIT: DWORD = 4002;
+pub const ERROR_INC_BACKUP: DWORD = 4003;
+pub const ERROR_FULL_BACKUP: DWORD = 4004;
+pub const ERROR_REC_NON_EXISTENT: DWORD = 4005;
+pub const ERROR_RPL_NOT_ALLOWED: DWORD = 4006;
+pub const ERROR_DHCP_ADDRESS_CONFLICT: DWORD = 4100;
+pub const ERROR_WMI_GUID_NOT_FOUND: DWORD = 4200;
+pub const ERROR_WMI_INSTANCE_NOT_FOUND: DWORD = 4201;
+pub const ERROR_WMI_ITEMID_NOT_FOUND: DWORD = 4202;
+pub const ERROR_WMI_TRY_AGAIN: DWORD = 4203;
+pub const ERROR_WMI_DP_NOT_FOUND: DWORD = 4204;
+pub const ERROR_WMI_UNRESOLVED_INSTANCE_REF: DWORD = 4205;
+pub const ERROR_WMI_ALREADY_ENABLED: DWORD = 4206;
+pub const ERROR_WMI_GUID_DISCONNECTED: DWORD = 4207;
+pub const ERROR_WMI_SERVER_UNAVAILABLE: DWORD = 4208;
+pub const ERROR_WMI_DP_FAILED: DWORD = 4209;
+pub const ERROR_WMI_INVALID_MOF: DWORD = 4210;
+pub const ERROR_WMI_INVALID_REGINFO: DWORD = 4211;
+pub const ERROR_WMI_ALREADY_DISABLED: DWORD = 4212;
+pub const ERROR_WMI_READ_ONLY: DWORD = 4213;
+pub const ERROR_WMI_SET_FAILURE: DWORD = 4214;
+pub const ERROR_INVALID_MEDIA: DWORD = 4300;
+pub const ERROR_INVALID_LIBRARY: DWORD = 4301;
+pub const ERROR_INVALID_MEDIA_POOL: DWORD = 4302;
+pub const ERROR_DRIVE_MEDIA_MISMATCH: DWORD = 4303;
+pub const ERROR_MEDIA_OFFLINE: DWORD = 4304;
+pub const ERROR_LIBRARY_OFFLINE: DWORD = 4305;
+pub const ERROR_EMPTY: DWORD = 4306;
+pub const ERROR_NOT_EMPTY: DWORD = 4307;
+pub const ERROR_MEDIA_UNAVAILABLE: DWORD = 4308;
+pub const ERROR_RESOURCE_DISABLED: DWORD = 4309;
+pub const ERROR_INVALID_CLEANER: DWORD = 4310;
+pub const ERROR_UNABLE_TO_CLEAN: DWORD = 4311;
+pub const ERROR_OBJECT_NOT_FOUND: DWORD = 4312;
+pub const ERROR_DATABASE_FAILURE: DWORD = 4313;
+pub const ERROR_DATABASE_FULL: DWORD = 4314;
+pub const ERROR_MEDIA_INCOMPATIBLE: DWORD = 4315;
+pub const ERROR_RESOURCE_NOT_PRESENT: DWORD = 4316;
+pub const ERROR_INVALID_OPERATION: DWORD = 4317;
+pub const ERROR_MEDIA_NOT_AVAILABLE: DWORD = 4318;
+pub const ERROR_DEVICE_NOT_AVAILABLE: DWORD = 4319;
+pub const ERROR_REQUEST_REFUSED: DWORD = 4320;
+pub const ERROR_INVALID_DRIVE_OBJECT: DWORD = 4321;
+pub const ERROR_LIBRARY_FULL: DWORD = 4322;
+pub const ERROR_MEDIUM_NOT_ACCESSIBLE: DWORD = 4323;
+pub const ERROR_UNABLE_TO_LOAD_MEDIUM: DWORD = 4324;
+pub const ERROR_UNABLE_TO_INVENTORY_DRIVE: DWORD = 4325;
+pub const ERROR_UNABLE_TO_INVENTORY_SLOT: DWORD = 4326;
+pub const ERROR_UNABLE_TO_INVENTORY_TRANSPORT: DWORD = 4327;
+pub const ERROR_TRANSPORT_FULL: DWORD = 4328;
+pub const ERROR_CONTROLLING_IEPORT: DWORD = 4329;
+pub const ERROR_UNABLE_TO_EJECT_MOUNTED_MEDIA: DWORD = 4330;
+pub const ERROR_CLEANER_SLOT_SET: DWORD = 4331;
+pub const ERROR_CLEANER_SLOT_NOT_SET: DWORD = 4332;
+pub const ERROR_CLEANER_CARTRIDGE_SPENT: DWORD = 4333;
+pub const ERROR_UNEXPECTED_OMID: DWORD = 4334;
+pub const ERROR_CANT_DELETE_LAST_ITEM: DWORD = 4335;
+pub const ERROR_MESSAGE_EXCEEDS_MAX_SIZE: DWORD = 4336;
+pub const ERROR_VOLUME_CONTAINS_SYS_FILES: DWORD = 4337;
+pub const ERROR_INDIGENOUS_TYPE: DWORD = 4338;
+pub const ERROR_NO_SUPPORTING_DRIVES: DWORD = 4339;
+pub const ERROR_CLEANER_CARTRIDGE_INSTALLED: DWORD = 4340;
+pub const ERROR_IEPORT_FULL: DWORD = 4341;
+pub const ERROR_FILE_OFFLINE: DWORD = 4350;
+pub const ERROR_REMOTE_STORAGE_NOT_ACTIVE: DWORD = 4351;
+pub const ERROR_REMOTE_STORAGE_MEDIA_ERROR: DWORD = 4352;
+pub const ERROR_NOT_A_REPARSE_POINT: DWORD = 4390;
+pub const ERROR_REPARSE_ATTRIBUTE_CONFLICT: DWORD = 4391;
+pub const ERROR_INVALID_REPARSE_DATA: DWORD = 4392;
+pub const ERROR_REPARSE_TAG_INVALID: DWORD = 4393;
+pub const ERROR_REPARSE_TAG_MISMATCH: DWORD = 4394;
+pub const ERROR_VOLUME_NOT_SIS_ENABLED: DWORD = 4500;
+pub const ERROR_DEPENDENT_RESOURCE_EXISTS: DWORD = 5001;
+pub const ERROR_DEPENDENCY_NOT_FOUND: DWORD = 5002;
+pub const ERROR_DEPENDENCY_ALREADY_EXISTS: DWORD = 5003;
+pub const ERROR_RESOURCE_NOT_ONLINE: DWORD = 5004;
+pub const ERROR_HOST_NODE_NOT_AVAILABLE: DWORD = 5005;
+pub const ERROR_RESOURCE_NOT_AVAILABLE: DWORD = 5006;
+pub const ERROR_RESOURCE_NOT_FOUND: DWORD = 5007;
+pub const ERROR_SHUTDOWN_CLUSTER: DWORD = 5008;
+pub const ERROR_CANT_EVICT_ACTIVE_NODE: DWORD = 5009;
+pub const ERROR_OBJECT_ALREADY_EXISTS: DWORD = 5010;
+pub const ERROR_OBJECT_IN_LIST: DWORD = 5011;
+pub const ERROR_GROUP_NOT_AVAILABLE: DWORD = 5012;
+pub const ERROR_GROUP_NOT_FOUND: DWORD = 5013;
+pub const ERROR_GROUP_NOT_ONLINE: DWORD = 5014;
+pub const ERROR_HOST_NODE_NOT_RESOURCE_OWNER: DWORD = 5015;
+pub const ERROR_HOST_NODE_NOT_GROUP_OWNER: DWORD = 5016;
+pub const ERROR_RESMON_CREATE_FAILED: DWORD = 5017;
+pub const ERROR_RESMON_ONLINE_FAILED: DWORD = 5018;
+pub const ERROR_RESOURCE_ONLINE: DWORD = 5019;
+pub const ERROR_QUORUM_RESOURCE: DWORD = 5020;
+pub const ERROR_NOT_QUORUM_CAPABLE: DWORD = 5021;
+pub const ERROR_CLUSTER_SHUTTING_DOWN: DWORD = 5022;
+pub const ERROR_INVALID_STATE: DWORD = 5023;
+pub const ERROR_RESOURCE_PROPERTIES_STORED: DWORD = 5024;
+pub const ERROR_NOT_QUORUM_CLASS: DWORD = 5025;
+pub const ERROR_CORE_RESOURCE: DWORD = 5026;
+pub const ERROR_QUORUM_RESOURCE_ONLINE_FAILED: DWORD = 5027;
+pub const ERROR_QUORUMLOG_OPEN_FAILED: DWORD = 5028;
+pub const ERROR_CLUSTERLOG_CORRUPT: DWORD = 5029;
+pub const ERROR_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE: DWORD = 5030;
+pub const ERROR_CLUSTERLOG_EXCEEDS_MAXSIZE: DWORD = 5031;
+pub const ERROR_CLUSTERLOG_CHKPOINT_NOT_FOUND: DWORD = 5032;
+pub const ERROR_CLUSTERLOG_NOT_ENOUGH_SPACE: DWORD = 5033;
+pub const ERROR_QUORUM_OWNER_ALIVE: DWORD = 5034;
+pub const ERROR_NETWORK_NOT_AVAILABLE: DWORD = 5035;
+pub const ERROR_NODE_NOT_AVAILABLE: DWORD = 5036;
+pub const ERROR_ALL_NODES_NOT_AVAILABLE: DWORD = 5037;
+pub const ERROR_RESOURCE_FAILED: DWORD = 5038;
+pub const ERROR_CLUSTER_INVALID_NODE: DWORD = 5039;
+pub const ERROR_CLUSTER_NODE_EXISTS: DWORD = 5040;
+pub const ERROR_CLUSTER_JOIN_IN_PROGRESS: DWORD = 5041;
+pub const ERROR_CLUSTER_NODE_NOT_FOUND: DWORD = 5042;
+pub const ERROR_CLUSTER_LOCAL_NODE_NOT_FOUND: DWORD = 5043;
+pub const ERROR_CLUSTER_NETWORK_EXISTS: DWORD = 5044;
+pub const ERROR_CLUSTER_NETWORK_NOT_FOUND: DWORD = 5045;
+pub const ERROR_CLUSTER_NETINTERFACE_EXISTS: DWORD = 5046;
+pub const ERROR_CLUSTER_NETINTERFACE_NOT_FOUND: DWORD = 5047;
+pub const ERROR_CLUSTER_INVALID_REQUEST: DWORD = 5048;
+pub const ERROR_CLUSTER_INVALID_NETWORK_PROVIDER: DWORD = 5049;
+pub const ERROR_CLUSTER_NODE_DOWN: DWORD = 5050;
+pub const ERROR_CLUSTER_NODE_UNREACHABLE: DWORD = 5051;
+pub const ERROR_CLUSTER_NODE_NOT_MEMBER: DWORD = 5052;
+pub const ERROR_CLUSTER_JOIN_NOT_IN_PROGRESS: DWORD = 5053;
+pub const ERROR_CLUSTER_INVALID_NETWORK: DWORD = 5054;
+pub const ERROR_CLUSTER_NODE_UP: DWORD = 5056;
+pub const ERROR_CLUSTER_IPADDR_IN_USE: DWORD = 5057;
+pub const ERROR_CLUSTER_NODE_NOT_PAUSED: DWORD = 5058;
+pub const ERROR_CLUSTER_NO_SECURITY_CONTEXT: DWORD = 5059;
+pub const ERROR_CLUSTER_NETWORK_NOT_INTERNAL: DWORD = 5060;
+pub const ERROR_CLUSTER_NODE_ALREADY_UP: DWORD = 5061;
+pub const ERROR_CLUSTER_NODE_ALREADY_DOWN: DWORD = 5062;
+pub const ERROR_CLUSTER_NETWORK_ALREADY_ONLINE: DWORD = 5063;
+pub const ERROR_CLUSTER_NETWORK_ALREADY_OFFLINE: DWORD = 5064;
+pub const ERROR_CLUSTER_NODE_ALREADY_MEMBER: DWORD = 5065;
+pub const ERROR_CLUSTER_LAST_INTERNAL_NETWORK: DWORD = 5066;
+pub const ERROR_CLUSTER_NETWORK_HAS_DEPENDENTS: DWORD = 5067;
+pub const ERROR_INVALID_OPERATION_ON_QUORUM: DWORD = 5068;
+pub const ERROR_DEPENDENCY_NOT_ALLOWED: DWORD = 5069;
+pub const ERROR_CLUSTER_NODE_PAUSED: DWORD = 5070;
+pub const ERROR_NODE_CANT_HOST_RESOURCE: DWORD = 5071;
+pub const ERROR_CLUSTER_NODE_NOT_READY: DWORD = 5072;
+pub const ERROR_CLUSTER_NODE_SHUTTING_DOWN: DWORD = 5073;
+pub const ERROR_CLUSTER_JOIN_ABORTED: DWORD = 5074;
+pub const ERROR_CLUSTER_INCOMPATIBLE_VERSIONS: DWORD = 5075;
+pub const ERROR_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED: DWORD = 5076;
+pub const ERROR_CLUSTER_SYSTEM_CONFIG_CHANGED: DWORD = 5077;
+pub const ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND: DWORD = 5078;
+pub const ERROR_CLUSTER_RESTYPE_NOT_SUPPORTED: DWORD = 5079;
+pub const ERROR_CLUSTER_RESNAME_NOT_FOUND: DWORD = 5080;
+pub const ERROR_CLUSTER_NO_RPC_PACKAGES_REGISTERED: DWORD = 5081;
+pub const ERROR_CLUSTER_OWNER_NOT_IN_PREFLIST: DWORD = 5082;
+pub const ERROR_CLUSTER_DATABASE_SEQMISMATCH: DWORD = 5083;
+pub const ERROR_RESMON_INVALID_STATE: DWORD = 5084;
+pub const ERROR_CLUSTER_GUM_NOT_LOCKER: DWORD = 5085;
+pub const ERROR_QUORUM_DISK_NOT_FOUND: DWORD = 5086;
+pub const ERROR_DATABASE_BACKUP_CORRUPT: DWORD = 5087;
+pub const ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT: DWORD = 5088;
+pub const ERROR_RESOURCE_PROPERTY_UNCHANGEABLE: DWORD = 5089;
+pub const ERROR_CLUSTER_MEMBERSHIP_INVALID_STATE: DWORD = 5890;
+pub const ERROR_CLUSTER_QUORUMLOG_NOT_FOUND: DWORD = 5891;
+pub const ERROR_CLUSTER_MEMBERSHIP_HALT: DWORD = 5892;
+pub const ERROR_CLUSTER_INSTANCE_ID_MISMATCH: DWORD = 5893;
+pub const ERROR_CLUSTER_NETWORK_NOT_FOUND_FOR_IP: DWORD = 5894;
+pub const ERROR_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH: DWORD = 5895;
+pub const ERROR_CLUSTER_EVICT_WITHOUT_CLEANUP: DWORD = 5896;
+pub const ERROR_CLUSTER_PARAMETER_MISMATCH: DWORD = 5897;
+pub const ERROR_NODE_CANNOT_BE_CLUSTERED: DWORD = 5898;
+pub const ERROR_CLUSTER_WRONG_OS_VERSION: DWORD = 5899;
+pub const ERROR_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME: DWORD = 5900;
+pub const ERROR_CLUSCFG_ALREADY_COMMITTED: DWORD = 5901;
+pub const ERROR_CLUSCFG_ROLLBACK_FAILED: DWORD = 5902;
+pub const ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT: DWORD = 5903;
+pub const ERROR_CLUSTER_OLD_VERSION: DWORD = 5904;
+pub const ERROR_CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME: DWORD = 5905;
+pub const ERROR_ENCRYPTION_FAILED: DWORD = 6000;
+pub const ERROR_DECRYPTION_FAILED: DWORD = 6001;
+pub const ERROR_FILE_ENCRYPTED: DWORD = 6002;
+pub const ERROR_NO_RECOVERY_POLICY: DWORD = 6003;
+pub const ERROR_NO_EFS: DWORD = 6004;
+pub const ERROR_WRONG_EFS: DWORD = 6005;
+pub const ERROR_NO_USER_KEYS: DWORD = 6006;
+pub const ERROR_FILE_NOT_ENCRYPTED: DWORD = 6007;
+pub const ERROR_NOT_EXPORT_FORMAT: DWORD = 6008;
+pub const ERROR_FILE_READ_ONLY: DWORD = 6009;
+pub const ERROR_DIR_EFS_DISALLOWED: DWORD = 6010;
+pub const ERROR_EFS_SERVER_NOT_TRUSTED: DWORD = 6011;
+pub const ERROR_BAD_RECOVERY_POLICY: DWORD = 6012;
+pub const ERROR_EFS_ALG_BLOB_TOO_BIG: DWORD = 6013;
+pub const ERROR_VOLUME_NOT_SUPPORT_EFS: DWORD = 6014;
+pub const ERROR_EFS_DISABLED: DWORD = 6015;
+pub const ERROR_EFS_VERSION_NOT_SUPPORT: DWORD = 6016;
+pub const ERROR_NO_BROWSER_SERVERS_FOUND: DWORD = 6118;
+pub const ERROR_CTX_WINSTATION_NAME_INVALID: DWORD = 7001;
+pub const ERROR_CTX_INVALID_PD: DWORD = 7002;
+pub const ERROR_CTX_PD_NOT_FOUND: DWORD = 7003;
+pub const ERROR_CTX_WD_NOT_FOUND: DWORD = 7004;
+pub const ERROR_CTX_CANNOT_MAKE_EVENTLOG_ENTRY: DWORD = 7005;
+pub const ERROR_CTX_SERVICE_NAME_COLLISION: DWORD = 7006;
+pub const ERROR_CTX_CLOSE_PENDING: DWORD = 7007;
+pub const ERROR_CTX_NO_OUTBUF: DWORD = 7008;
+pub const ERROR_CTX_MODEM_INF_NOT_FOUND: DWORD = 7009;
+pub const ERROR_CTX_INVALID_MODEMNAME: DWORD = 7010;
+pub const ERROR_CTX_MODEM_RESPONSE_ERROR: DWORD = 7011;
+pub const ERROR_CTX_MODEM_RESPONSE_TIMEOUT: DWORD = 7012;
+pub const ERROR_CTX_MODEM_RESPONSE_NO_CARRIER: DWORD = 7013;
+pub const ERROR_CTX_MODEM_RESPONSE_NO_DIALTONE: DWORD = 7014;
+pub const ERROR_CTX_MODEM_RESPONSE_BUSY: DWORD = 7015;
+pub const ERROR_CTX_MODEM_RESPONSE_VOICE: DWORD = 7016;
+pub const ERROR_CTX_TD_ERROR: DWORD = 7017;
+pub const ERROR_CTX_WINSTATION_NOT_FOUND: DWORD = 7022;
+pub const ERROR_CTX_WINSTATION_ALREADY_EXISTS: DWORD = 7023;
+pub const ERROR_CTX_WINSTATION_BUSY: DWORD = 7024;
+pub const ERROR_CTX_BAD_VIDEO_MODE: DWORD = 7025;
+pub const ERROR_CTX_GRAPHICS_INVALID: DWORD = 7035;
+pub const ERROR_CTX_LOGON_DISABLED: DWORD = 7037;
+pub const ERROR_CTX_NOT_CONSOLE: DWORD = 7038;
+pub const ERROR_CTX_CLIENT_QUERY_TIMEOUT: DWORD = 7040;
+pub const ERROR_CTX_CONSOLE_DISCONNECT: DWORD = 7041;
+pub const ERROR_CTX_CONSOLE_CONNECT: DWORD = 7042;
+pub const ERROR_CTX_SHADOW_DENIED: DWORD = 7044;
+pub const ERROR_CTX_WINSTATION_ACCESS_DENIED: DWORD = 7045;
+pub const ERROR_CTX_INVALID_WD: DWORD = 7049;
+pub const ERROR_CTX_SHADOW_INVALID: DWORD = 7050;
+pub const ERROR_CTX_SHADOW_DISABLED: DWORD = 7051;
+pub const ERROR_CTX_CLIENT_LICENSE_IN_USE: DWORD = 7052;
+pub const ERROR_CTX_CLIENT_LICENSE_NOT_SET: DWORD = 7053;
+pub const ERROR_CTX_LICENSE_NOT_AVAILABLE: DWORD = 7054;
+pub const ERROR_CTX_LICENSE_CLIENT_INVALID: DWORD = 7055;
+pub const ERROR_CTX_LICENSE_EXPIRED: DWORD = 7056;
+pub const ERROR_CTX_SHADOW_NOT_RUNNING: DWORD = 7057;
+pub const ERROR_CTX_SHADOW_ENDED_BY_MODE_CHANGE: DWORD = 7058;
+pub const ERROR_ACTIVATION_COUNT_EXCEEDED: DWORD = 7059;
+pub const ERROR_DS_NOT_INSTALLED: DWORD = 8200;
+pub const ERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY: DWORD = 8201;
+pub const ERROR_DS_NO_ATTRIBUTE_OR_VALUE: DWORD = 8202;
+pub const ERROR_DS_INVALID_ATTRIBUTE_SYNTAX: DWORD = 8203;
+pub const ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED: DWORD = 8204;
+pub const ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS: DWORD = 8205;
+pub const ERROR_DS_BUSY: DWORD = 8206;
+pub const ERROR_DS_UNAVAILABLE: DWORD = 8207;
+pub const ERROR_DS_NO_RIDS_ALLOCATED: DWORD = 8208;
+pub const ERROR_DS_NO_MORE_RIDS: DWORD = 8209;
+pub const ERROR_DS_INCORRECT_ROLE_OWNER: DWORD = 8210;
+pub const ERROR_DS_RIDMGR_INIT_ERROR: DWORD = 8211;
+pub const ERROR_DS_OBJ_CLASS_VIOLATION: DWORD = 8212;
+pub const ERROR_DS_CANT_ON_NON_LEAF: DWORD = 8213;
+pub const ERROR_DS_CANT_ON_RDN: DWORD = 8214;
+pub const ERROR_DS_CANT_MOD_OBJ_CLASS: DWORD = 8215;
+pub const ERROR_DS_CROSS_DOM_MOVE_ERROR: DWORD = 8216;
+pub const ERROR_DS_GC_NOT_AVAILABLE: DWORD = 8217;
+pub const ERROR_SHARED_POLICY: DWORD = 8218;
+pub const ERROR_POLICY_OBJECT_NOT_FOUND: DWORD = 8219;
+pub const ERROR_POLICY_ONLY_IN_DS: DWORD = 8220;
+pub const ERROR_PROMOTION_ACTIVE: DWORD = 8221;
+pub const ERROR_NO_PROMOTION_ACTIVE: DWORD = 8222;
+pub const ERROR_DS_OPERATIONS_ERROR: DWORD = 8224;
+pub const ERROR_DS_PROTOCOL_ERROR: DWORD = 8225;
+pub const ERROR_DS_TIMELIMIT_EXCEEDED: DWORD = 8226;
+pub const ERROR_DS_SIZELIMIT_EXCEEDED: DWORD = 8227;
+pub const ERROR_DS_ADMIN_LIMIT_EXCEEDED: DWORD = 8228;
+pub const ERROR_DS_COMPARE_FALSE: DWORD = 8229;
+pub const ERROR_DS_COMPARE_TRUE: DWORD = 8230;
+pub const ERROR_DS_AUTH_METHOD_NOT_SUPPORTED: DWORD = 8231;
+pub const ERROR_DS_STRONG_AUTH_REQUIRED: DWORD = 8232;
+pub const ERROR_DS_INAPPROPRIATE_AUTH: DWORD = 8233;
+pub const ERROR_DS_AUTH_UNKNOWN: DWORD = 8234;
+pub const ERROR_DS_REFERRAL: DWORD = 8235;
+pub const ERROR_DS_UNAVAILABLE_CRIT_EXTENSION: DWORD = 8236;
+pub const ERROR_DS_CONFIDENTIALITY_REQUIRED: DWORD = 8237;
+pub const ERROR_DS_INAPPROPRIATE_MATCHING: DWORD = 8238;
+pub const ERROR_DS_CONSTRAINT_VIOLATION: DWORD = 8239;
+pub const ERROR_DS_NO_SUCH_OBJECT: DWORD = 8240;
+pub const ERROR_DS_ALIAS_PROBLEM: DWORD = 8241;
+pub const ERROR_DS_INVALID_DN_SYNTAX: DWORD = 8242;
+pub const ERROR_DS_IS_LEAF: DWORD = 8243;
+pub const ERROR_DS_ALIAS_DEREF_PROBLEM: DWORD = 8244;
+pub const ERROR_DS_UNWILLING_TO_PERFORM: DWORD = 8245;
+pub const ERROR_DS_LOOP_DETECT: DWORD = 8246;
+pub const ERROR_DS_NAMING_VIOLATION: DWORD = 8247;
+pub const ERROR_DS_OBJECT_RESULTS_TOO_LARGE: DWORD = 8248;
+pub const ERROR_DS_AFFECTS_MULTIPLE_DSAS: DWORD = 8249;
+pub const ERROR_DS_SERVER_DOWN: DWORD = 8250;
+pub const ERROR_DS_LOCAL_ERROR: DWORD = 8251;
+pub const ERROR_DS_ENCODING_ERROR: DWORD = 8252;
+pub const ERROR_DS_DECODING_ERROR: DWORD = 8253;
+pub const ERROR_DS_FILTER_UNKNOWN: DWORD = 8254;
+pub const ERROR_DS_PARAM_ERROR: DWORD = 8255;
+pub const ERROR_DS_NOT_SUPPORTED: DWORD = 8256;
+pub const ERROR_DS_NO_RESULTS_RETURNED: DWORD = 8257;
+pub const ERROR_DS_CONTROL_NOT_FOUND: DWORD = 8258;
+pub const ERROR_DS_CLIENT_LOOP: DWORD = 8259;
+pub const ERROR_DS_REFERRAL_LIMIT_EXCEEDED: DWORD = 8260;
+pub const ERROR_DS_SORT_CONTROL_MISSING: DWORD = 8261;
+pub const ERROR_DS_OFFSET_RANGE_ERROR: DWORD = 8262;
+pub const ERROR_DS_ROOT_MUST_BE_NC: DWORD = 8301;
+pub const ERROR_DS_ADD_REPLICA_INHIBITED: DWORD = 8302;
+pub const ERROR_DS_ATT_NOT_DEF_IN_SCHEMA: DWORD = 8303;
+pub const ERROR_DS_MAX_OBJ_SIZE_EXCEEDED: DWORD = 8304;
+pub const ERROR_DS_OBJ_STRING_NAME_EXISTS: DWORD = 8305;
+pub const ERROR_DS_NO_RDN_DEFINED_IN_SCHEMA: DWORD = 8306;
+pub const ERROR_DS_RDN_DOESNT_MATCH_SCHEMA: DWORD = 8307;
+pub const ERROR_DS_NO_REQUESTED_ATTS_FOUND: DWORD = 8308;
+pub const ERROR_DS_USER_BUFFER_TO_SMALL: DWORD = 8309;
+pub const ERROR_DS_ATT_IS_NOT_ON_OBJ: DWORD = 8310;
+pub const ERROR_DS_ILLEGAL_MOD_OPERATION: DWORD = 8311;
+pub const ERROR_DS_OBJ_TOO_LARGE: DWORD = 8312;
+pub const ERROR_DS_BAD_INSTANCE_TYPE: DWORD = 8313;
+pub const ERROR_DS_MASTERDSA_REQUIRED: DWORD = 8314;
+pub const ERROR_DS_OBJECT_CLASS_REQUIRED: DWORD = 8315;
+pub const ERROR_DS_MISSING_REQUIRED_ATT: DWORD = 8316;
+pub const ERROR_DS_ATT_NOT_DEF_FOR_CLASS: DWORD = 8317;
+pub const ERROR_DS_ATT_ALREADY_EXISTS: DWORD = 8318;
+pub const ERROR_DS_CANT_ADD_ATT_VALUES: DWORD = 8320;
+pub const ERROR_DS_SINGLE_VALUE_CONSTRAINT: DWORD = 8321;
+pub const ERROR_DS_RANGE_CONSTRAINT: DWORD = 8322;
+pub const ERROR_DS_ATT_VAL_ALREADY_EXISTS: DWORD = 8323;
+pub const ERROR_DS_CANT_REM_MISSING_ATT: DWORD = 8324;
+pub const ERROR_DS_CANT_REM_MISSING_ATT_VAL: DWORD = 8325;
+pub const ERROR_DS_ROOT_CANT_BE_SUBREF: DWORD = 8326;
+pub const ERROR_DS_NO_CHAINING: DWORD = 8327;
+pub const ERROR_DS_NO_CHAINED_EVAL: DWORD = 8328;
+pub const ERROR_DS_NO_PARENT_OBJECT: DWORD = 8329;
+pub const ERROR_DS_PARENT_IS_AN_ALIAS: DWORD = 8330;
+pub const ERROR_DS_CANT_MIX_MASTER_AND_REPS: DWORD = 8331;
+pub const ERROR_DS_CHILDREN_EXIST: DWORD = 8332;
+pub const ERROR_DS_OBJ_NOT_FOUND: DWORD = 8333;
+pub const ERROR_DS_ALIASED_OBJ_MISSING: DWORD = 8334;
+pub const ERROR_DS_BAD_NAME_SYNTAX: DWORD = 8335;
+pub const ERROR_DS_ALIAS_POINTS_TO_ALIAS: DWORD = 8336;
+pub const ERROR_DS_CANT_DEREF_ALIAS: DWORD = 8337;
+pub const ERROR_DS_OUT_OF_SCOPE: DWORD = 8338;
+pub const ERROR_DS_OBJECT_BEING_REMOVED: DWORD = 8339;
+pub const ERROR_DS_CANT_DELETE_DSA_OBJ: DWORD = 8340;
+pub const ERROR_DS_GENERIC_ERROR: DWORD = 8341;
+pub const ERROR_DS_DSA_MUST_BE_INT_MASTER: DWORD = 8342;
+pub const ERROR_DS_CLASS_NOT_DSA: DWORD = 8343;
+pub const ERROR_DS_INSUFF_ACCESS_RIGHTS: DWORD = 8344;
+pub const ERROR_DS_ILLEGAL_SUPERIOR: DWORD = 8345;
+pub const ERROR_DS_ATTRIBUTE_OWNED_BY_SAM: DWORD = 8346;
+pub const ERROR_DS_NAME_TOO_MANY_PARTS: DWORD = 8347;
+pub const ERROR_DS_NAME_TOO_LONG: DWORD = 8348;
+pub const ERROR_DS_NAME_VALUE_TOO_LONG: DWORD = 8349;
+pub const ERROR_DS_NAME_UNPARSEABLE: DWORD = 8350;
+pub const ERROR_DS_NAME_TYPE_UNKNOWN: DWORD = 8351;
+pub const ERROR_DS_NOT_AN_OBJECT: DWORD = 8352;
+pub const ERROR_DS_SEC_DESC_TOO_SHORT: DWORD = 8353;
+pub const ERROR_DS_SEC_DESC_INVALID: DWORD = 8354;
+pub const ERROR_DS_NO_DELETED_NAME: DWORD = 8355;
+pub const ERROR_DS_SUBREF_MUST_HAVE_PARENT: DWORD = 8356;
+pub const ERROR_DS_NCNAME_MUST_BE_NC: DWORD = 8357;
+pub const ERROR_DS_CANT_ADD_SYSTEM_ONLY: DWORD = 8358;
+pub const ERROR_DS_CLASS_MUST_BE_CONCRETE: DWORD = 8359;
+pub const ERROR_DS_INVALID_DMD: DWORD = 8360;
+pub const ERROR_DS_OBJ_GUID_EXISTS: DWORD = 8361;
+pub const ERROR_DS_NOT_ON_BACKLINK: DWORD = 8362;
+pub const ERROR_DS_NO_CROSSREF_FOR_NC: DWORD = 8363;
+pub const ERROR_DS_SHUTTING_DOWN: DWORD = 8364;
+pub const ERROR_DS_UNKNOWN_OPERATION: DWORD = 8365;
+pub const ERROR_DS_INVALID_ROLE_OWNER: DWORD = 8366;
+pub const ERROR_DS_COULDNT_CONTACT_FSMO: DWORD = 8367;
+pub const ERROR_DS_CROSS_NC_DN_RENAME: DWORD = 8368;
+pub const ERROR_DS_CANT_MOD_SYSTEM_ONLY: DWORD = 8369;
+pub const ERROR_DS_REPLICATOR_ONLY: DWORD = 8370;
+pub const ERROR_DS_OBJ_CLASS_NOT_DEFINED: DWORD = 8371;
+pub const ERROR_DS_OBJ_CLASS_NOT_SUBCLASS: DWORD = 8372;
+pub const ERROR_DS_NAME_REFERENCE_INVALID: DWORD = 8373;
+pub const ERROR_DS_CROSS_REF_EXISTS: DWORD = 8374;
+pub const ERROR_DS_CANT_DEL_MASTER_CROSSREF: DWORD = 8375;
+pub const ERROR_DS_SUBTREE_NOTIFY_NOT_NC_HEAD: DWORD = 8376;
+pub const ERROR_DS_NOTIFY_FILTER_TOO_COMPLEX: DWORD = 8377;
+pub const ERROR_DS_DUP_RDN: DWORD = 8378;
+pub const ERROR_DS_DUP_OID: DWORD = 8379;
+pub const ERROR_DS_DUP_MAPI_ID: DWORD = 8380;
+pub const ERROR_DS_DUP_SCHEMA_ID_GUID: DWORD = 8381;
+pub const ERROR_DS_DUP_LDAP_DISPLAY_NAME: DWORD = 8382;
+pub const ERROR_DS_SEMANTIC_ATT_TEST: DWORD = 8383;
+pub const ERROR_DS_SYNTAX_MISMATCH: DWORD = 8384;
+pub const ERROR_DS_EXISTS_IN_MUST_HAVE: DWORD = 8385;
+pub const ERROR_DS_EXISTS_IN_MAY_HAVE: DWORD = 8386;
+pub const ERROR_DS_NONEXISTENT_MAY_HAVE: DWORD = 8387;
+pub const ERROR_DS_NONEXISTENT_MUST_HAVE: DWORD = 8388;
+pub const ERROR_DS_AUX_CLS_TEST_FAIL: DWORD = 8389;
+pub const ERROR_DS_NONEXISTENT_POSS_SUP: DWORD = 8390;
+pub const ERROR_DS_SUB_CLS_TEST_FAIL: DWORD = 8391;
+pub const ERROR_DS_BAD_RDN_ATT_ID_SYNTAX: DWORD = 8392;
+pub const ERROR_DS_EXISTS_IN_AUX_CLS: DWORD = 8393;
+pub const ERROR_DS_EXISTS_IN_SUB_CLS: DWORD = 8394;
+pub const ERROR_DS_EXISTS_IN_POSS_SUP: DWORD = 8395;
+pub const ERROR_DS_RECALCSCHEMA_FAILED: DWORD = 8396;
+pub const ERROR_DS_TREE_DELETE_NOT_FINISHED: DWORD = 8397;
+pub const ERROR_DS_CANT_DELETE: DWORD = 8398;
+pub const ERROR_DS_ATT_SCHEMA_REQ_ID: DWORD = 8399;
+pub const ERROR_DS_BAD_ATT_SCHEMA_SYNTAX: DWORD = 8400;
+pub const ERROR_DS_CANT_CACHE_ATT: DWORD = 8401;
+pub const ERROR_DS_CANT_CACHE_CLASS: DWORD = 8402;
+pub const ERROR_DS_CANT_REMOVE_ATT_CACHE: DWORD = 8403;
+pub const ERROR_DS_CANT_REMOVE_CLASS_CACHE: DWORD = 8404;
+pub const ERROR_DS_CANT_RETRIEVE_DN: DWORD = 8405;
+pub const ERROR_DS_MISSING_SUPREF: DWORD = 8406;
+pub const ERROR_DS_CANT_RETRIEVE_INSTANCE: DWORD = 8407;
+pub const ERROR_DS_CODE_INCONSISTENCY: DWORD = 8408;
+pub const ERROR_DS_DATABASE_ERROR: DWORD = 8409;
+pub const ERROR_DS_GOVERNSID_MISSING: DWORD = 8410;
+pub const ERROR_DS_MISSING_EXPECTED_ATT: DWORD = 8411;
+pub const ERROR_DS_NCNAME_MISSING_CR_REF: DWORD = 8412;
+pub const ERROR_DS_SECURITY_CHECKING_ERROR: DWORD = 8413;
+pub const ERROR_DS_SCHEMA_NOT_LOADED: DWORD = 8414;
+pub const ERROR_DS_SCHEMA_ALLOC_FAILED: DWORD = 8415;
+pub const ERROR_DS_ATT_SCHEMA_REQ_SYNTAX: DWORD = 8416;
+pub const ERROR_DS_GCVERIFY_ERROR: DWORD = 8417;
+pub const ERROR_DS_DRA_SCHEMA_MISMATCH: DWORD = 8418;
+pub const ERROR_DS_CANT_FIND_DSA_OBJ: DWORD = 8419;
+pub const ERROR_DS_CANT_FIND_EXPECTED_NC: DWORD = 8420;
+pub const ERROR_DS_CANT_FIND_NC_IN_CACHE: DWORD = 8421;
+pub const ERROR_DS_CANT_RETRIEVE_CHILD: DWORD = 8422;
+pub const ERROR_DS_SECURITY_ILLEGAL_MODIFY: DWORD = 8423;
+pub const ERROR_DS_CANT_REPLACE_HIDDEN_REC: DWORD = 8424;
+pub const ERROR_DS_BAD_HIERARCHY_FILE: DWORD = 8425;
+pub const ERROR_DS_BUILD_HIERARCHY_TABLE_FAILED: DWORD = 8426;
+pub const ERROR_DS_CONFIG_PARAM_MISSING: DWORD = 8427;
+pub const ERROR_DS_COUNTING_AB_INDICES_FAILED: DWORD = 8428;
+pub const ERROR_DS_HIERARCHY_TABLE_MALLOC_FAILED: DWORD = 8429;
+pub const ERROR_DS_INTERNAL_FAILURE: DWORD = 8430;
+pub const ERROR_DS_UNKNOWN_ERROR: DWORD = 8431;
+pub const ERROR_DS_ROOT_REQUIRES_CLASS_TOP: DWORD = 8432;
+pub const ERROR_DS_REFUSING_FSMO_ROLES: DWORD = 8433;
+pub const ERROR_DS_MISSING_FSMO_SETTINGS: DWORD = 8434;
+pub const ERROR_DS_UNABLE_TO_SURRENDER_ROLES: DWORD = 8435;
+pub const ERROR_DS_DRA_GENERIC: DWORD = 8436;
+pub const ERROR_DS_DRA_INVALID_PARAMETER: DWORD = 8437;
+pub const ERROR_DS_DRA_BUSY: DWORD = 8438;
+pub const ERROR_DS_DRA_BAD_DN: DWORD = 8439;
+pub const ERROR_DS_DRA_BAD_NC: DWORD = 8440;
+pub const ERROR_DS_DRA_DN_EXISTS: DWORD = 8441;
+pub const ERROR_DS_DRA_INTERNAL_ERROR: DWORD = 8442;
+pub const ERROR_DS_DRA_INCONSISTENT_DIT: DWORD = 8443;
+pub const ERROR_DS_DRA_CONNECTION_FAILED: DWORD = 8444;
+pub const ERROR_DS_DRA_BAD_INSTANCE_TYPE: DWORD = 8445;
+pub const ERROR_DS_DRA_OUT_OF_MEM: DWORD = 8446;
+pub const ERROR_DS_DRA_MAIL_PROBLEM: DWORD = 8447;
+pub const ERROR_DS_DRA_REF_ALREADY_EXISTS: DWORD = 8448;
+pub const ERROR_DS_DRA_REF_NOT_FOUND: DWORD = 8449;
+pub const ERROR_DS_DRA_OBJ_IS_REP_SOURCE: DWORD = 8450;
+pub const ERROR_DS_DRA_DB_ERROR: DWORD = 8451;
+pub const ERROR_DS_DRA_NO_REPLICA: DWORD = 8452;
+pub const ERROR_DS_DRA_ACCESS_DENIED: DWORD = 8453;
+pub const ERROR_DS_DRA_NOT_SUPPORTED: DWORD = 8454;
+pub const ERROR_DS_DRA_RPC_CANCELLED: DWORD = 8455;
+pub const ERROR_DS_DRA_SOURCE_DISABLED: DWORD = 8456;
+pub const ERROR_DS_DRA_SINK_DISABLED: DWORD = 8457;
+pub const ERROR_DS_DRA_NAME_COLLISION: DWORD = 8458;
+pub const ERROR_DS_DRA_SOURCE_REINSTALLED: DWORD = 8459;
+pub const ERROR_DS_DRA_MISSING_PARENT: DWORD = 8460;
+pub const ERROR_DS_DRA_PREEMPTED: DWORD = 8461;
+pub const ERROR_DS_DRA_ABANDON_SYNC: DWORD = 8462;
+pub const ERROR_DS_DRA_SHUTDOWN: DWORD = 8463;
+pub const ERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET: DWORD = 8464;
+pub const ERROR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA: DWORD = 8465;
+pub const ERROR_DS_DRA_EXTN_CONNECTION_FAILED: DWORD = 8466;
+pub const ERROR_DS_INSTALL_SCHEMA_MISMATCH: DWORD = 8467;
+pub const ERROR_DS_DUP_LINK_ID: DWORD = 8468;
+pub const ERROR_DS_NAME_ERROR_RESOLVING: DWORD = 8469;
+pub const ERROR_DS_NAME_ERROR_NOT_FOUND: DWORD = 8470;
+pub const ERROR_DS_NAME_ERROR_NOT_UNIQUE: DWORD = 8471;
+pub const ERROR_DS_NAME_ERROR_NO_MAPPING: DWORD = 8472;
+pub const ERROR_DS_NAME_ERROR_DOMAIN_ONLY: DWORD = 8473;
+pub const ERROR_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING: DWORD = 8474;
+pub const ERROR_DS_CONSTRUCTED_ATT_MOD: DWORD = 8475;
+pub const ERROR_DS_WRONG_OM_OBJ_CLASS: DWORD = 8476;
+pub const ERROR_DS_DRA_REPL_PENDING: DWORD = 8477;
+pub const ERROR_DS_DS_REQUIRED: DWORD = 8478;
+pub const ERROR_DS_INVALID_LDAP_DISPLAY_NAME: DWORD = 8479;
+pub const ERROR_DS_NON_BASE_SEARCH: DWORD = 8480;
+pub const ERROR_DS_CANT_RETRIEVE_ATTS: DWORD = 8481;
+pub const ERROR_DS_BACKLINK_WITHOUT_LINK: DWORD = 8482;
+pub const ERROR_DS_EPOCH_MISMATCH: DWORD = 8483;
+pub const ERROR_DS_SRC_NAME_MISMATCH: DWORD = 8484;
+pub const ERROR_DS_SRC_AND_DST_NC_IDENTICAL: DWORD = 8485;
+pub const ERROR_DS_DST_NC_MISMATCH: DWORD = 8486;
+pub const ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC: DWORD = 8487;
+pub const ERROR_DS_SRC_GUID_MISMATCH: DWORD = 8488;
+pub const ERROR_DS_CANT_MOVE_DELETED_OBJECT: DWORD = 8489;
+pub const ERROR_DS_PDC_OPERATION_IN_PROGRESS: DWORD = 8490;
+pub const ERROR_DS_CROSS_DOMAIN_CLEANUP_REQD: DWORD = 8491;
+pub const ERROR_DS_ILLEGAL_XDOM_MOVE_OPERATION: DWORD = 8492;
+pub const ERROR_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS: DWORD = 8493;
+pub const ERROR_DS_NC_MUST_HAVE_NC_PARENT: DWORD = 8494;
+pub const ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE: DWORD = 8495;
+pub const ERROR_DS_DST_DOMAIN_NOT_NATIVE: DWORD = 8496;
+pub const ERROR_DS_MISSING_INFRASTRUCTURE_CONTAINER: DWORD = 8497;
+pub const ERROR_DS_CANT_MOVE_ACCOUNT_GROUP: DWORD = 8498;
+pub const ERROR_DS_CANT_MOVE_RESOURCE_GROUP: DWORD = 8499;
+pub const ERROR_DS_INVALID_SEARCH_FLAG: DWORD = 8500;
+pub const ERROR_DS_NO_TREE_DELETE_ABOVE_NC: DWORD = 8501;
+pub const ERROR_DS_COULDNT_LOCK_TREE_FOR_DELETE: DWORD = 8502;
+pub const ERROR_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE: DWORD = 8503;
+pub const ERROR_DS_SAM_INIT_FAILURE: DWORD = 8504;
+pub const ERROR_DS_SENSITIVE_GROUP_VIOLATION: DWORD = 8505;
+pub const ERROR_DS_CANT_MOD_PRIMARYGROUPID: DWORD = 8506;
+pub const ERROR_DS_ILLEGAL_BASE_SCHEMA_MOD: DWORD = 8507;
+pub const ERROR_DS_NONSAFE_SCHEMA_CHANGE: DWORD = 8508;
+pub const ERROR_DS_SCHEMA_UPDATE_DISALLOWED: DWORD = 8509;
+pub const ERROR_DS_CANT_CREATE_UNDER_SCHEMA: DWORD = 8510;
+pub const ERROR_DS_INSTALL_NO_SRC_SCH_VERSION: DWORD = 8511;
+pub const ERROR_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE: DWORD = 8512;
+pub const ERROR_DS_INVALID_GROUP_TYPE: DWORD = 8513;
+pub const ERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN: DWORD = 8514;
+pub const ERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN: DWORD = 8515;
+pub const ERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER: DWORD = 8516;
+pub const ERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER: DWORD = 8517;
+pub const ERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER: DWORD = 8518;
+pub const ERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER: DWORD = 8519;
+pub const ERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER: DWORD = 8520;
+pub const ERROR_DS_HAVE_PRIMARY_MEMBERS: DWORD = 8521;
+pub const ERROR_DS_STRING_SD_CONVERSION_FAILED: DWORD = 8522;
+pub const ERROR_DS_NAMING_MASTER_GC: DWORD = 8523;
+pub const ERROR_DS_DNS_LOOKUP_FAILURE: DWORD = 8524;
+pub const ERROR_DS_COULDNT_UPDATE_SPNS: DWORD = 8525;
+pub const ERROR_DS_CANT_RETRIEVE_SD: DWORD = 8526;
+pub const ERROR_DS_KEY_NOT_UNIQUE: DWORD = 8527;
+pub const ERROR_DS_WRONG_LINKED_ATT_SYNTAX: DWORD = 8528;
+pub const ERROR_DS_SAM_NEED_BOOTKEY_PASSWORD: DWORD = 8529;
+pub const ERROR_DS_SAM_NEED_BOOTKEY_FLOPPY: DWORD = 8530;
+pub const ERROR_DS_CANT_START: DWORD = 8531;
+pub const ERROR_DS_INIT_FAILURE: DWORD = 8532;
+pub const ERROR_DS_NO_PKT_PRIVACY_ON_CONNECTION: DWORD = 8533;
+pub const ERROR_DS_SOURCE_DOMAIN_IN_FOREST: DWORD = 8534;
+pub const ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST: DWORD = 8535;
+pub const ERROR_DS_DESTINATION_AUDITING_NOT_ENABLED: DWORD = 8536;
+pub const ERROR_DS_CANT_FIND_DC_FOR_SRC_DOMAIN: DWORD = 8537;
+pub const ERROR_DS_SRC_OBJ_NOT_GROUP_OR_USER: DWORD = 8538;
+pub const ERROR_DS_SRC_SID_EXISTS_IN_FOREST: DWORD = 8539;
+pub const ERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH: DWORD = 8540;
+pub const ERROR_SAM_INIT_FAILURE: DWORD = 8541;
+pub const ERROR_DS_DRA_SCHEMA_INFO_SHIP: DWORD = 8542;
+pub const ERROR_DS_DRA_SCHEMA_CONFLICT: DWORD = 8543;
+pub const ERROR_DS_DRA_EARLIER_SCHEMA_CONFLICT: DWORD = 8544;
+pub const ERROR_DS_DRA_OBJ_NC_MISMATCH: DWORD = 8545;
+pub const ERROR_DS_NC_STILL_HAS_DSAS: DWORD = 8546;
+pub const ERROR_DS_GC_REQUIRED: DWORD = 8547;
+pub const ERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY: DWORD = 8548;
+pub const ERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS: DWORD = 8549;
+pub const ERROR_DS_CANT_ADD_TO_GC: DWORD = 8550;
+pub const ERROR_DS_NO_CHECKPOINT_WITH_PDC: DWORD = 8551;
+pub const ERROR_DS_SOURCE_AUDITING_NOT_ENABLED: DWORD = 8552;
+pub const ERROR_DS_CANT_CREATE_IN_NONDOMAIN_NC: DWORD = 8553;
+pub const ERROR_DS_INVALID_NAME_FOR_SPN: DWORD = 8554;
+pub const ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS: DWORD = 8555;
+pub const ERROR_DS_UNICODEPWD_NOT_IN_QUOTES: DWORD = 8556;
+pub const ERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED: DWORD = 8557;
+pub const ERROR_DS_MUST_BE_RUN_ON_DST_DC: DWORD = 8558;
+pub const ERROR_DS_SRC_DC_MUST_BE_SP4_OR_GREATER: DWORD = 8559;
+pub const ERROR_DS_CANT_TREE_DELETE_CRITICAL_OBJ: DWORD = 8560;
+pub const ERROR_DS_INIT_FAILURE_CONSOLE: DWORD = 8561;
+pub const ERROR_DS_SAM_INIT_FAILURE_CONSOLE: DWORD = 8562;
+pub const ERROR_DS_FOREST_VERSION_TOO_HIGH: DWORD = 8563;
+pub const ERROR_DS_DOMAIN_VERSION_TOO_HIGH: DWORD = 8564;
+pub const ERROR_DS_FOREST_VERSION_TOO_LOW: DWORD = 8565;
+pub const ERROR_DS_DOMAIN_VERSION_TOO_LOW: DWORD = 8566;
+pub const ERROR_DS_INCOMPATIBLE_VERSION: DWORD = 8567;
+pub const ERROR_DS_LOW_DSA_VERSION: DWORD = 8568;
+pub const ERROR_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN: DWORD = 8569;
+pub const ERROR_DS_NOT_SUPPORTED_SORT_ORDER: DWORD = 8570;
+pub const ERROR_DS_NAME_NOT_UNIQUE: DWORD = 8571;
+pub const ERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4: DWORD = 8572;
+pub const ERROR_DS_OUT_OF_VERSION_STORE: DWORD = 8573;
+pub const ERROR_DS_INCOMPATIBLE_CONTROLS_USED: DWORD = 8574;
+pub const ERROR_DS_NO_REF_DOMAIN: DWORD = 8575;
+pub const ERROR_DS_RESERVED_LINK_ID: DWORD = 8576;
+pub const ERROR_DS_LINK_ID_NOT_AVAILABLE: DWORD = 8577;
+pub const ERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER: DWORD = 8578;
+pub const ERROR_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE: DWORD = 8579;
+pub const ERROR_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC: DWORD = 8580;
+pub const ERROR_DS_MODIFYDN_DISALLOWED_BY_FLAG: DWORD = 8581;
+pub const ERROR_DS_MODIFYDN_WRONG_GRANDPARENT: DWORD = 8582;
+pub const ERROR_DS_NAME_ERROR_TRUST_REFERRAL: DWORD = 8583;
+pub const ERROR_NOT_SUPPORTED_ON_STANDARD_SERVER: DWORD = 8584;
+pub const ERROR_DS_CANT_ACCESS_REMOTE_PART_OF_AD: DWORD = 8585;
+pub const ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2: DWORD = 8586;
+pub const ERROR_DS_THREAD_LIMIT_EXCEEDED: DWORD = 8587;
+pub const ERROR_DS_NOT_CLOSEST: DWORD = 8588;
+pub const ERROR_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF: DWORD = 8589;
+pub const ERROR_DS_SINGLE_USER_MODE_FAILED: DWORD = 8590;
+pub const ERROR_DS_NTDSCRIPT_SYNTAX_ERROR: DWORD = 8591;
+pub const ERROR_DS_NTDSCRIPT_PROCESS_ERROR: DWORD = 8592;
+pub const ERROR_DS_DIFFERENT_REPL_EPOCHS: DWORD = 8593;
+pub const ERROR_DS_DRS_EXTENSIONS_CHANGED: DWORD = 8594;
+pub const ERROR_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR: DWORD = 8595;
+pub const ERROR_DS_NO_MSDS_INTID: DWORD = 8596;
+pub const ERROR_DS_DUP_MSDS_INTID: DWORD = 8597;
+pub const ERROR_DS_EXISTS_IN_RDNATTID: DWORD = 8598;
+pub const ERROR_DS_AUTHORIZATION_FAILED: DWORD = 8599;
+pub const ERROR_DS_INVALID_SCRIPT: DWORD = 8600;
+pub const ERROR_DS_REMOTE_CROSSREF_OP_FAILED: DWORD = 8601;
+pub const ERROR_DS_CROSS_REF_BUSY: DWORD = 8602;
+pub const ERROR_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN: DWORD = 8603;
+pub const ERROR_DS_CANT_DEMOTE_WITH_WRITEABLE_NC: DWORD = 8604;
+pub const ERROR_DS_DUPLICATE_ID_FOUND: DWORD = 8605;
+pub const ERROR_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT: DWORD = 8606;
+pub const ERROR_DS_GROUP_CONVERSION_ERROR: DWORD = 8607;
+pub const ERROR_DS_CANT_MOVE_APP_BASIC_GROUP: DWORD = 8608;
+pub const ERROR_DS_CANT_MOVE_APP_QUERY_GROUP: DWORD = 8609;
+pub const ERROR_DS_ROLE_NOT_VERIFIED: DWORD = 8610;
+pub const ERROR_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL: DWORD = 8611;
+pub const ERROR_DS_DOMAIN_RENAME_IN_PROGRESS: DWORD = 8612;
+pub const ERROR_DS_EXISTING_AD_CHILD_NC: DWORD = 8613;
+pub const ERROR_DS_REPL_LIFETIME_EXCEEDED: DWORD = 8614;
+pub const ERROR_DS_DISALLOWED_IN_SYSTEM_CONTAINER: DWORD = 8615;
+pub const ERROR_DS_LDAP_SEND_QUEUE_FULL: DWORD = 8616;
+pub const ERROR_DS_DRA_OUT_SCHEDULE_WINDOW: DWORD = 8617;
+pub const ERROR_SXS_SECTION_NOT_FOUND: DWORD = 14000;
+pub const ERROR_SXS_CANT_GEN_ACTCTX: DWORD = 14001;
+pub const ERROR_SXS_INVALID_ACTCTXDATA_FORMAT: DWORD = 14002;
+pub const ERROR_SXS_ASSEMBLY_NOT_FOUND: DWORD = 14003;
+pub const ERROR_SXS_MANIFEST_FORMAT_ERROR: DWORD = 14004;
+pub const ERROR_SXS_MANIFEST_PARSE_ERROR: DWORD = 14005;
+pub const ERROR_SXS_ACTIVATION_CONTEXT_DISABLED: DWORD = 14006;
+pub const ERROR_SXS_KEY_NOT_FOUND: DWORD = 14007;
+pub const ERROR_SXS_VERSION_CONFLICT: DWORD = 14008;
+pub const ERROR_SXS_WRONG_SECTION_TYPE: DWORD = 14009;
+pub const ERROR_SXS_THREAD_QUERIES_DISABLED: DWORD = 14010;
+pub const ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET: DWORD = 14011;
+pub const ERROR_SXS_UNKNOWN_ENCODING_GROUP: DWORD = 14012;
+pub const ERROR_SXS_UNKNOWN_ENCODING: DWORD = 14013;
+pub const ERROR_SXS_INVALID_XML_NAMESPACE_URI: DWORD = 14014;
+pub const ERROR_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED: DWORD = 14015;
+pub const ERROR_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED: DWORD = 14016;
+pub const ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE: DWORD = 14017;
+pub const ERROR_SXS_MANIFEST_MISSING_REQUIRED_DEFAULT_NAMESPACE: DWORD = 14018;
+pub const ERROR_SXS_MANIFEST_INVALID_REQUIRED_DEFAULT_NAMESPACE: DWORD = 14019;
+pub const ERROR_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT: DWORD = 14020;
+pub const ERROR_SXS_DUPLICATE_DLL_NAME: DWORD = 14021;
+pub const ERROR_SXS_DUPLICATE_WINDOWCLASS_NAME: DWORD = 14022;
+pub const ERROR_SXS_DUPLICATE_CLSID: DWORD = 14023;
+pub const ERROR_SXS_DUPLICATE_IID: DWORD = 14024;
+pub const ERROR_SXS_DUPLICATE_TLBID: DWORD = 14025;
+pub const ERROR_SXS_DUPLICATE_PROGID: DWORD = 14026;
+pub const ERROR_SXS_DUPLICATE_ASSEMBLY_NAME: DWORD = 14027;
+pub const ERROR_SXS_FILE_HASH_MISMATCH: DWORD = 14028;
+pub const ERROR_SXS_POLICY_PARSE_ERROR: DWORD = 14029;
+pub const ERROR_SXS_XML_E_MISSINGQUOTE: DWORD = 14030;
+pub const ERROR_SXS_XML_E_COMMENTSYNTAX: DWORD = 14031;
+pub const ERROR_SXS_XML_E_BADSTARTNAMECHAR: DWORD = 14032;
+pub const ERROR_SXS_XML_E_BADNAMECHAR: DWORD = 14033;
+pub const ERROR_SXS_XML_E_BADCHARINSTRING: DWORD = 14034;
+pub const ERROR_SXS_XML_E_XMLDECLSYNTAX: DWORD = 14035;
+pub const ERROR_SXS_XML_E_BADCHARDATA: DWORD = 14036;
+pub const ERROR_SXS_XML_E_MISSINGWHITESPACE: DWORD = 14037;
+pub const ERROR_SXS_XML_E_EXPECTINGTAGEND: DWORD = 14038;
+pub const ERROR_SXS_XML_E_MISSINGSEMICOLON: DWORD = 14039;
+pub const ERROR_SXS_XML_E_UNBALANCEDPAREN: DWORD = 14040;
+pub const ERROR_SXS_XML_E_INTERNALERROR: DWORD = 14041;
+pub const ERROR_SXS_XML_E_UNEXPECTED_WHITESPACE: DWORD = 14042;
+pub const ERROR_SXS_XML_E_INCOMPLETE_ENCODING: DWORD = 14043;
+pub const ERROR_SXS_XML_E_MISSING_PAREN: DWORD = 14044;
+pub const ERROR_SXS_XML_E_EXPECTINGCLOSEQUOTE: DWORD = 14045;
+pub const ERROR_SXS_XML_E_MULTIPLE_COLONS: DWORD = 14046;
+pub const ERROR_SXS_XML_E_INVALID_DECIMAL: DWORD = 14047;
+pub const ERROR_SXS_XML_E_INVALID_HEXIDECIMAL: DWORD = 14048;
+pub const ERROR_SXS_XML_E_INVALID_UNICODE: DWORD = 14049;
+pub const ERROR_SXS_XML_E_WHITESPACEORQUESTIONMARK: DWORD = 14050;
+pub const ERROR_SXS_XML_E_UNEXPECTEDENDTAG: DWORD = 14051;
+pub const ERROR_SXS_XML_E_UNCLOSEDTAG: DWORD = 14052;
+pub const ERROR_SXS_XML_E_DUPLICATEATTRIBUTE: DWORD = 14053;
+pub const ERROR_SXS_XML_E_MULTIPLEROOTS: DWORD = 14054;
+pub const ERROR_SXS_XML_E_INVALIDATROOTLEVEL: DWORD = 14055;
+pub const ERROR_SXS_XML_E_BADXMLDECL: DWORD = 14056;
+pub const ERROR_SXS_XML_E_MISSINGROOT: DWORD = 14057;
+pub const ERROR_SXS_XML_E_UNEXPECTEDEOF: DWORD = 14058;
+pub const ERROR_SXS_XML_E_BADPEREFINSUBSET: DWORD = 14059;
+pub const ERROR_SXS_XML_E_UNCLOSEDSTARTTAG: DWORD = 14060;
+pub const ERROR_SXS_XML_E_UNCLOSEDENDTAG: DWORD = 14061;
+pub const ERROR_SXS_XML_E_UNCLOSEDSTRING: DWORD = 14062;
+pub const ERROR_SXS_XML_E_UNCLOSEDCOMMENT: DWORD = 14063;
+pub const ERROR_SXS_XML_E_UNCLOSEDDECL: DWORD = 14064;
+pub const ERROR_SXS_XML_E_UNCLOSEDCDATA: DWORD = 14065;
+pub const ERROR_SXS_XML_E_RESERVEDNAMESPACE: DWORD = 14066;
+pub const ERROR_SXS_XML_E_INVALIDENCODING: DWORD = 14067;
+pub const ERROR_SXS_XML_E_INVALIDSWITCH: DWORD = 14068;
+pub const ERROR_SXS_XML_E_BADXMLCASE: DWORD = 14069;
+pub const ERROR_SXS_XML_E_INVALID_STANDALONE: DWORD = 14070;
+pub const ERROR_SXS_XML_E_UNEXPECTED_STANDALONE: DWORD = 14071;
+pub const ERROR_SXS_XML_E_INVALID_VERSION: DWORD = 14072;
+pub const ERROR_SXS_XML_E_MISSINGEQUALS: DWORD = 14073;
+pub const ERROR_SXS_PROTECTION_RECOVERY_FAILED: DWORD = 14074;
+pub const ERROR_SXS_PROTECTION_PUBLIC_KEY_TOO_SHORT: DWORD = 14075;
+pub const ERROR_SXS_PROTECTION_CATALOG_NOT_VALID: DWORD = 14076;
+pub const ERROR_SXS_UNTRANSLATABLE_HRESULT: DWORD = 14077;
+pub const ERROR_SXS_PROTECTION_CATALOG_FILE_MISSING: DWORD = 14078;
+pub const ERROR_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE: DWORD = 14079;
+pub const ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME: DWORD = 14080;
+pub const ERROR_SXS_ASSEMBLY_MISSING: DWORD = 14081;
+pub const ERROR_SXS_CORRUPT_ACTIVATION_STACK: DWORD = 14082;
+pub const ERROR_SXS_CORRUPTION: DWORD = 14083;
+pub const ERROR_SXS_EARLY_DEACTIVATION: DWORD = 14084;
+pub const ERROR_SXS_INVALID_DEACTIVATION: DWORD = 14085;
+pub const ERROR_SXS_MULTIPLE_DEACTIVATION: DWORD = 14086;
+pub const ERROR_SXS_PROCESS_TERMINATION_REQUESTED: DWORD = 14087;
+pub const ERROR_SXS_RELEASE_ACTIVATION_CONTEXT: DWORD = 14088;
+pub const ERROR_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY: DWORD = 14089;
+pub const ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE: DWORD = 14090;
+pub const ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME: DWORD = 14091;
+pub const ERROR_SXS_IDENTITY_DUPLICATE_ATTRIBUTE: DWORD = 14092;
+pub const ERROR_SXS_IDENTITY_PARSE_ERROR: DWORD = 14093;
+pub const ERROR_MALFORMED_SUBSTITUTION_STRING: DWORD = 14094;
+pub const ERROR_SXS_INCORRECT_PUBLIC_KEY_TOKEN: DWORD = 14095;
+pub const ERROR_UNMAPPED_SUBSTITUTION_STRING: DWORD = 14096;
+pub const ERROR_SXS_ASSEMBLY_NOT_LOCKED: DWORD = 14097;
+pub const ERROR_SXS_COMPONENT_STORE_CORRUPT: DWORD = 14098;
+pub const ERROR_ADVANCED_INSTALLER_FAILED: DWORD = 14099;
+pub const ERROR_XML_ENCODING_MISMATCH: DWORD = 14100;
+pub const ERROR_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT: DWORD = 14101;
+pub const ERROR_SXS_IDENTITIES_DIFFERENT: DWORD = 14102;
+pub const ERROR_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT: DWORD = 14103;
+pub const ERROR_SXS_FILE_NOT_PART_OF_ASSEMBLY: DWORD = 14104;
+pub const ERROR_SXS_MANIFEST_TOO_BIG: DWORD = 14105;
+pub const ERROR_SXS_SETTING_NOT_REGISTERED: DWORD = 14106;
+pub const ERROR_SXS_TRANSACTION_CLOSURE_INCOMPLETE: DWORD = 14107;
+pub const ERROR_SMI_PRIMITIVE_INSTALLER_FAILED: DWORD = 14108;
+pub const ERROR_GENERIC_COMMAND_FAILED: DWORD = 14109;
+pub const ERROR_SXS_FILE_HASH_MISSING: DWORD = 14110;
+pub const ERROR_IPSEC_QM_POLICY_EXISTS: DWORD = 13000;
+pub const ERROR_IPSEC_QM_POLICY_NOT_FOUND: DWORD = 13001;
+pub const ERROR_IPSEC_QM_POLICY_IN_USE: DWORD = 13002;
+pub const ERROR_IPSEC_MM_POLICY_EXISTS: DWORD = 13003;
+pub const ERROR_IPSEC_MM_POLICY_NOT_FOUND: DWORD = 13004;
+pub const ERROR_IPSEC_MM_POLICY_IN_USE: DWORD = 13005;
+pub const ERROR_IPSEC_MM_FILTER_EXISTS: DWORD = 13006;
+pub const ERROR_IPSEC_MM_FILTER_NOT_FOUND: DWORD = 13007;
+pub const ERROR_IPSEC_TRANSPORT_FILTER_EXISTS: DWORD = 13008;
+pub const ERROR_IPSEC_TRANSPORT_FILTER_NOT_FOUND: DWORD = 13009;
+pub const ERROR_IPSEC_MM_AUTH_EXISTS: DWORD = 13010;
+pub const ERROR_IPSEC_MM_AUTH_NOT_FOUND: DWORD = 13011;
+pub const ERROR_IPSEC_MM_AUTH_IN_USE: DWORD = 13012;
+pub const ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND: DWORD = 13013;
+pub const ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND: DWORD = 13014;
+pub const ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND: DWORD = 13015;
+pub const ERROR_IPSEC_TUNNEL_FILTER_EXISTS: DWORD = 13016;
+pub const ERROR_IPSEC_TUNNEL_FILTER_NOT_FOUND: DWORD = 13017;
+pub const ERROR_IPSEC_MM_FILTER_PENDING_DELETION: DWORD = 13018;
+pub const ERROR_IPSEC_TRANSPORT_FILTER_PENDING_DELETION: DWORD = 13019;
+pub const ERROR_IPSEC_TUNNEL_FILTER_PENDING_DELETION: DWORD = 13020;
+pub const ERROR_IPSEC_MM_POLICY_PENDING_DELETION: DWORD = 13021;
+pub const ERROR_IPSEC_MM_AUTH_PENDING_DELETION: DWORD = 13022;
+pub const ERROR_IPSEC_QM_POLICY_PENDING_DELETION: DWORD = 13023;
+pub const ERROR_IPSEC_IKE_NEG_STATUS_BEGIN: DWORD = 13800;
+pub const ERROR_IPSEC_IKE_AUTH_FAIL: DWORD = 13801;
+pub const ERROR_IPSEC_IKE_ATTRIB_FAIL: DWORD = 13802;
+pub const ERROR_IPSEC_IKE_NEGOTIATION_PENDING: DWORD = 13803;
+pub const ERROR_IPSEC_IKE_GENERAL_PROCESSING_ERROR: DWORD = 13804;
+pub const ERROR_IPSEC_IKE_TIMED_OUT: DWORD = 13805;
+pub const ERROR_IPSEC_IKE_NO_CERT: DWORD = 13806;
+pub const ERROR_IPSEC_IKE_SA_DELETED: DWORD = 13807;
+pub const ERROR_IPSEC_IKE_SA_REAPED: DWORD = 13808;
+pub const ERROR_IPSEC_IKE_MM_ACQUIRE_DROP: DWORD = 13809;
+pub const ERROR_IPSEC_IKE_QM_ACQUIRE_DROP: DWORD = 13810;
+pub const ERROR_IPSEC_IKE_QUEUE_DROP_MM: DWORD = 13811;
+pub const ERROR_IPSEC_IKE_QUEUE_DROP_NO_MM: DWORD = 13812;
+pub const ERROR_IPSEC_IKE_DROP_NO_RESPONSE: DWORD = 13813;
+pub const ERROR_IPSEC_IKE_MM_DELAY_DROP: DWORD = 13814;
+pub const ERROR_IPSEC_IKE_QM_DELAY_DROP: DWORD = 13815;
+pub const ERROR_IPSEC_IKE_ERROR: DWORD = 13816;
+pub const ERROR_IPSEC_IKE_CRL_FAILED: DWORD = 13817;
+pub const ERROR_IPSEC_IKE_INVALID_KEY_USAGE: DWORD = 13818;
+pub const ERROR_IPSEC_IKE_INVALID_CERT_TYPE: DWORD = 13819;
+pub const ERROR_IPSEC_IKE_NO_PRIVATE_KEY: DWORD = 13820;
+pub const ERROR_IPSEC_IKE_DH_FAIL: DWORD = 13822;
+pub const ERROR_IPSEC_IKE_INVALID_HEADER: DWORD = 13824;
+pub const ERROR_IPSEC_IKE_NO_POLICY: DWORD = 13825;
+pub const ERROR_IPSEC_IKE_INVALID_SIGNATURE: DWORD = 13826;
+pub const ERROR_IPSEC_IKE_KERBEROS_ERROR: DWORD = 13827;
+pub const ERROR_IPSEC_IKE_NO_PUBLIC_KEY: DWORD = 13828;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR: DWORD = 13829;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR_SA: DWORD = 13830;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR_PROP: DWORD = 13831;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR_TRANS: DWORD = 13832;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR_KE: DWORD = 13833;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR_ID: DWORD = 13834;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR_CERT: DWORD = 13835;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR_CERT_REQ: DWORD = 13836;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR_HASH: DWORD = 13837;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR_SIG: DWORD = 13838;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR_NONCE: DWORD = 13839;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR_NOTIFY: DWORD = 13840;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR_DELETE: DWORD = 13841;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR_VENDOR: DWORD = 13842;
+pub const ERROR_IPSEC_IKE_INVALID_PAYLOAD: DWORD = 13843;
+pub const ERROR_IPSEC_IKE_LOAD_SOFT_SA: DWORD = 13844;
+pub const ERROR_IPSEC_IKE_SOFT_SA_TORN_DOWN: DWORD = 13845;
+pub const ERROR_IPSEC_IKE_INVALID_COOKIE: DWORD = 13846;
+pub const ERROR_IPSEC_IKE_NO_PEER_CERT: DWORD = 13847;
+pub const ERROR_IPSEC_IKE_PEER_CRL_FAILED: DWORD = 13848;
+pub const ERROR_IPSEC_IKE_POLICY_CHANGE: DWORD = 13849;
+pub const ERROR_IPSEC_IKE_NO_MM_POLICY: DWORD = 13850;
+pub const ERROR_IPSEC_IKE_NOTCBPRIV: DWORD = 13851;
+pub const ERROR_IPSEC_IKE_SECLOADFAIL: DWORD = 13852;
+pub const ERROR_IPSEC_IKE_FAILSSPINIT: DWORD = 13853;
+pub const ERROR_IPSEC_IKE_FAILQUERYSSP: DWORD = 13854;
+pub const ERROR_IPSEC_IKE_SRVACQFAIL: DWORD = 13855;
+pub const ERROR_IPSEC_IKE_SRVQUERYCRED: DWORD = 13856;
+pub const ERROR_IPSEC_IKE_GETSPIFAIL: DWORD = 13857;
+pub const ERROR_IPSEC_IKE_INVALID_FILTER: DWORD = 13858;
+pub const ERROR_IPSEC_IKE_OUT_OF_MEMORY: DWORD = 13859;
+pub const ERROR_IPSEC_IKE_ADD_UPDATE_KEY_FAILED: DWORD = 13860;
+pub const ERROR_IPSEC_IKE_INVALID_POLICY: DWORD = 13861;
+pub const ERROR_IPSEC_IKE_UNKNOWN_DOI: DWORD = 13862;
+pub const ERROR_IPSEC_IKE_INVALID_SITUATION: DWORD = 13863;
+pub const ERROR_IPSEC_IKE_DH_FAILURE: DWORD = 13864;
+pub const ERROR_IPSEC_IKE_INVALID_GROUP: DWORD = 13865;
+pub const ERROR_IPSEC_IKE_ENCRYPT: DWORD = 13866;
+pub const ERROR_IPSEC_IKE_DECRYPT: DWORD = 13867;
+pub const ERROR_IPSEC_IKE_POLICY_MATCH: DWORD = 13868;
+pub const ERROR_IPSEC_IKE_UNSUPPORTED_ID: DWORD = 13869;
+pub const ERROR_IPSEC_IKE_INVALID_HASH: DWORD = 13870;
+pub const ERROR_IPSEC_IKE_INVALID_HASH_ALG: DWORD = 13871;
+pub const ERROR_IPSEC_IKE_INVALID_HASH_SIZE: DWORD = 13872;
+pub const ERROR_IPSEC_IKE_INVALID_ENCRYPT_ALG: DWORD = 13873;
+pub const ERROR_IPSEC_IKE_INVALID_AUTH_ALG: DWORD = 13874;
+pub const ERROR_IPSEC_IKE_INVALID_SIG: DWORD = 13875;
+pub const ERROR_IPSEC_IKE_LOAD_FAILED: DWORD = 13876;
+pub const ERROR_IPSEC_IKE_RPC_DELETE: DWORD = 13877;
+pub const ERROR_IPSEC_IKE_BENIGN_REINIT: DWORD = 13878;
+pub const ERROR_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY: DWORD = 13879;
+pub const ERROR_IPSEC_IKE_INVALID_CERT_KEYLEN: DWORD = 13881;
+pub const ERROR_IPSEC_IKE_MM_LIMIT: DWORD = 13882;
+pub const ERROR_IPSEC_IKE_NEGOTIATION_DISABLED: DWORD = 13883;
+/*pub const ERROR_IPSEC_IKE_NEG_STATUS_END: DWORD = 13884)*/
+pub const ERROR_IPSEC_IKE_QM_LIMIT: DWORD = 13884;
+pub const ERROR_IPSEC_IKE_MM_EXPIRED: DWORD = 13885;
+pub const ERROR_IPSEC_IKE_PEER_MM_ASSUMED_INVALID: DWORD = 13886;
+pub const ERROR_IPSEC_IKE_CERT_CHAIN_POLICY_MISMATCH: DWORD = 13887;
+pub const ERROR_IPSEC_IKE_UNEXPECTED_MESSAGE_ID: DWORD = 13888;
+pub const ERROR_IPSEC_IKE_INVALID_AUTH_PAYLOAD: DWORD = 13889;
+pub const ERROR_IPSEC_IKE_DOS_COOKIE_SENT: DWORD = 13890;
+pub const ERROR_IPSEC_IKE_SHUTTING_DOWN: DWORD = 13891;
+pub const ERROR_IPSEC_IKE_CGA_AUTH_FAILED: DWORD = 13892;
+pub const ERROR_IPSEC_IKE_PROCESS_ERR_NATOA: DWORD = 13893;
+pub const ERROR_IPSEC_IKE_INVALID_MM_FOR_QM: DWORD = 13894;
+pub const ERROR_IPSEC_IKE_QM_EXPIRED: DWORD = 13895;
+pub const ERROR_IPSEC_IKE_TOO_MANY_FILTERS: DWORD = 13896;
+pub const ERROR_IPSEC_IKE_NEG_STATUS_END: DWORD = 13897;
+pub const ERROR_IPSEC_IKE_KILL_DUMMY_NAP_TUNNEL: DWORD = 13898;
+pub const ERROR_IPSEC_IKE_INNER_IP_ASSIGNMENT_FAILURE: DWORD = 13899;
+pub const ERROR_IPSEC_IKE_REQUIRE_CP_PAYLOAD_MISSING: DWORD = 13900;
+pub const ERROR_IPSEC_KEY_MODULE_IMPERSONATION_NEGOTIATION_PENDING: DWORD = 13901;
+pub const ERROR_IPSEC_IKE_COEXISTENCE_SUPPRESS: DWORD = 13902;
+pub const ERROR_IPSEC_IKE_RATELIMIT_DROP: DWORD = 13903;
+pub const ERROR_IPSEC_IKE_PEER_DOESNT_SUPPORT_MOBIKE: DWORD = 13904;
+pub const ERROR_IPSEC_IKE_AUTHORIZATION_FAILURE: DWORD = 13905;
+pub const ERROR_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_FAILURE: DWORD = 13906;
+pub const ERROR_IPSEC_IKE_AUTHORIZATION_FAILURE_WITH_OPTIONAL_RETRY: DWORD = 13907;
+pub const ERROR_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_AND_CERTMAP_FAILURE: DWORD = 13908;
+pub const ERROR_IPSEC_IKE_NEG_STATUS_EXTENDED_END: DWORD = 13909;
+pub const ERROR_IPSEC_BAD_SPI: DWORD = 13910;
+pub const ERROR_IPSEC_SA_LIFETIME_EXPIRED: DWORD = 13911;
+pub const ERROR_IPSEC_WRONG_SA: DWORD = 13912;
+pub const ERROR_IPSEC_REPLAY_CHECK_FAILED: DWORD = 13913;
+pub const ERROR_IPSEC_INVALID_PACKET: DWORD = 13914;
+pub const ERROR_IPSEC_INTEGRITY_CHECK_FAILED: DWORD = 13915;
+pub const ERROR_IPSEC_CLEAR_TEXT_DROP: DWORD = 13916;
+pub const ERROR_IPSEC_AUTH_FIREWALL_DROP: DWORD = 13917;
+pub const ERROR_IPSEC_THROTTLE_DROP: DWORD = 13918;
+pub const ERROR_IPSEC_DOSP_BLOCK: DWORD = 13925;
+pub const ERROR_IPSEC_DOSP_RECEIVED_MULTICAST: DWORD = 13926;
+pub const ERROR_IPSEC_DOSP_INVALID_PACKET: DWORD = 13927;
+pub const ERROR_IPSEC_DOSP_STATE_LOOKUP_FAILED: DWORD = 13928;
+pub const ERROR_IPSEC_DOSP_MAX_ENTRIES: DWORD = 13929;
+pub const ERROR_IPSEC_DOSP_KEYMOD_NOT_ALLOWED: DWORD = 13930;
+pub const ERROR_IPSEC_DOSP_NOT_INSTALLED: DWORD = 13931;
+pub const ERROR_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES: DWORD = 13932;
+pub const ERROR_EVT_INVALID_CHANNEL_PATH: DWORD = 15000;
+pub const ERROR_EVT_INVALID_QUERY: DWORD = 15001;
+pub const ERROR_EVT_PUBLISHER_METADATA_NOT_FOUND: DWORD = 15002;
+pub const ERROR_EVT_EVENT_TEMPLATE_NOT_FOUND: DWORD = 15003;
+pub const ERROR_EVT_INVALID_PUBLISHER_NAME: DWORD = 15004;
+pub const ERROR_EVT_INVALID_EVENT_DATA: DWORD = 15005;
+pub const ERROR_EVT_CHANNEL_NOT_FOUND: DWORD = 15007;
+pub const ERROR_EVT_MALFORMED_XML_TEXT: DWORD = 15008;
+pub const ERROR_EVT_SUBSCRIPTION_TO_DIRECT_CHANNEL: DWORD = 15009;
+pub const ERROR_EVT_CONFIGURATION_ERROR: DWORD = 15010;
+pub const ERROR_EVT_QUERY_RESULT_STALE: DWORD = 15011;
+pub const ERROR_EVT_QUERY_RESULT_INVALID_POSITION: DWORD = 15012;
+pub const ERROR_EVT_NON_VALIDATING_MSXML: DWORD = 15013;
+pub const ERROR_EVT_FILTER_ALREADYSCOPED: DWORD = 15014;
+pub const ERROR_EVT_FILTER_NOTELTSET: DWORD = 15015;
+pub const ERROR_EVT_FILTER_INVARG: DWORD = 15016;
+pub const ERROR_EVT_FILTER_INVTEST: DWORD = 15017;
+pub const ERROR_EVT_FILTER_INVTYPE: DWORD = 15018;
+pub const ERROR_EVT_FILTER_PARSEERR: DWORD = 15019;
+pub const ERROR_EVT_FILTER_UNSUPPORTEDOP: DWORD = 15020;
+pub const ERROR_EVT_FILTER_UNEXPECTEDTOKEN: DWORD = 15021;
+pub const ERROR_EVT_INVALID_OPERATION_OVER_ENABLED_DIRECT_CHANNEL: DWORD = 15022;
+pub const ERROR_EVT_INVALID_CHANNEL_PROPERTY_VALUE: DWORD = 15023;
+pub const ERROR_EVT_INVALID_PUBLISHER_PROPERTY_VALUE: DWORD = 15024;
+pub const ERROR_EVT_CHANNEL_CANNOT_ACTIVATE: DWORD = 15025;
+pub const ERROR_EVT_FILTER_TOO_COMPLEX: DWORD = 15026;
+pub const ERROR_EVT_MESSAGE_NOT_FOUND: DWORD = 15027;
+pub const ERROR_EVT_MESSAGE_ID_NOT_FOUND: DWORD = 15028;
+pub const ERROR_EVT_UNRESOLVED_VALUE_INSERT: DWORD = 15029;
+pub const ERROR_EVT_UNRESOLVED_PARAMETER_INSERT: DWORD = 15030;
+pub const ERROR_EVT_MAX_INSERTS_REACHED: DWORD = 15031;
+pub const ERROR_EVT_EVENT_DEFINITION_NOT_FOUND: DWORD = 15032;
+pub const ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND: DWORD = 15033;
+pub const ERROR_EVT_VERSION_TOO_OLD: DWORD = 15034;
+pub const ERROR_EVT_VERSION_TOO_NEW: DWORD = 15035;
+pub const ERROR_EVT_CANNOT_OPEN_CHANNEL_OF_QUERY: DWORD = 15036;
+pub const ERROR_EVT_PUBLISHER_DISABLED: DWORD = 15037;
+pub const ERROR_EVT_FILTER_OUT_OF_RANGE: DWORD = 15038;
+pub const ERROR_EC_SUBSCRIPTION_CANNOT_ACTIVATE: DWORD = 15080;
+pub const ERROR_EC_LOG_DISABLED: DWORD = 15081;
+pub const ERROR_EC_CIRCULAR_FORWARDING: DWORD = 15082;
+pub const ERROR_EC_CREDSTORE_FULL: DWORD = 15083;
+pub const ERROR_EC_CRED_NOT_FOUND: DWORD = 15084;
+pub const ERROR_EC_NO_ACTIVE_CHANNEL: DWORD = 15085;
+pub const ERROR_MUI_FILE_NOT_FOUND: DWORD = 15100;
+pub const ERROR_MUI_INVALID_FILE: DWORD = 15101;
+pub const ERROR_MUI_INVALID_RC_CONFIG: DWORD = 15102;
+pub const ERROR_MUI_INVALID_LOCALE_NAME: DWORD = 15103;
+pub const ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME: DWORD = 15104;
+pub const ERROR_MUI_FILE_NOT_LOADED: DWORD = 15105;
+pub const ERROR_RESOURCE_ENUM_USER_STOP: DWORD = 15106;
+pub const ERROR_MUI_INTLSETTINGS_UILANG_NOT_INSTALLED: DWORD = 15107;
+pub const ERROR_MUI_INTLSETTINGS_INVALID_LOCALE_NAME: DWORD = 15108;
+pub const ERROR_MRM_RUNTIME_NO_DEFAULT_OR_NEUTRAL_RESOURCE: DWORD = 15110;
+pub const ERROR_MRM_INVALID_PRICONFIG: DWORD = 15111;
+pub const ERROR_MRM_INVALID_FILE_TYPE: DWORD = 15112;
+pub const ERROR_MRM_UNKNOWN_QUALIFIER: DWORD = 15113;
+pub const ERROR_MRM_INVALID_QUALIFIER_VALUE: DWORD = 15114;
+pub const ERROR_MRM_NO_CANDIDATE: DWORD = 15115;
+pub const ERROR_MRM_NO_MATCH_OR_DEFAULT_CANDIDATE: DWORD = 15116;
+pub const ERROR_MRM_RESOURCE_TYPE_MISMATCH: DWORD = 15117;
+pub const ERROR_MRM_DUPLICATE_MAP_NAME: DWORD = 15118;
+pub const ERROR_MRM_DUPLICATE_ENTRY: DWORD = 15119;
+pub const ERROR_MRM_INVALID_RESOURCE_IDENTIFIER: DWORD = 15120;
+pub const ERROR_MRM_FILEPATH_TOO_LONG: DWORD = 15121;
+pub const ERROR_MRM_UNSUPPORTED_DIRECTORY_TYPE: DWORD = 15122;
+pub const ERROR_MRM_INVALID_PRI_FILE: DWORD = 15126;
+pub const ERROR_MRM_NAMED_RESOURCE_NOT_FOUND: DWORD = 15127;
+pub const ERROR_MRM_MAP_NOT_FOUND: DWORD = 15135;
+pub const ERROR_MRM_UNSUPPORTED_PROFILE_TYPE: DWORD = 15136;
+pub const ERROR_MRM_INVALID_QUALIFIER_OPERATOR: DWORD = 15137;
+pub const ERROR_MRM_INDETERMINATE_QUALIFIER_VALUE: DWORD = 15138;
+pub const ERROR_MRM_AUTOMERGE_ENABLED: DWORD = 15139;
+pub const ERROR_MRM_TOO_MANY_RESOURCES: DWORD = 15140;
+pub const ERROR_MCA_INVALID_CAPABILITIES_STRING: DWORD = 15200;
+pub const ERROR_MCA_INVALID_VCP_VERSION: DWORD = 15201;
+pub const ERROR_MCA_MONITOR_VIOLATES_MCCS_SPECIFICATION: DWORD = 15202;
+pub const ERROR_MCA_MCCS_VERSION_MISMATCH: DWORD = 15203;
+pub const ERROR_MCA_UNSUPPORTED_MCCS_VERSION: DWORD = 15204;
+pub const ERROR_MCA_INTERNAL_ERROR: DWORD = 15205;
+pub const ERROR_MCA_INVALID_TECHNOLOGY_TYPE_RETURNED: DWORD = 15206;
+pub const ERROR_MCA_UNSUPPORTED_COLOR_TEMPERATURE: DWORD = 15207;
+pub const ERROR_AMBIGUOUS_SYSTEM_DEVICE: DWORD = 15250;
+pub const ERROR_SYSTEM_DEVICE_NOT_FOUND: DWORD = 15299;
+pub const ERROR_HASH_NOT_SUPPORTED: DWORD = 15300;
+pub const ERROR_HASH_NOT_PRESENT: DWORD = 15301;
+pub const ERROR_SECONDARY_IC_PROVIDER_NOT_REGISTERED: DWORD = 15321;
+pub const ERROR_GPIO_CLIENT_INFORMATION_INVALID: DWORD = 15322;
+pub const ERROR_GPIO_VERSION_NOT_SUPPORTED: DWORD = 15323;
+pub const ERROR_GPIO_INVALID_REGISTRATION_PACKET: DWORD = 15324;
+pub const ERROR_GPIO_OPERATION_DENIED: DWORD = 15325;
+pub const ERROR_GPIO_INCOMPATIBLE_CONNECT_MODE: DWORD = 15326;
+pub const ERROR_GPIO_INTERRUPT_ALREADY_UNMASKED: DWORD = 15327;
+pub const ERROR_CANNOT_SWITCH_RUNLEVEL: DWORD = 15400;
+pub const ERROR_INVALID_RUNLEVEL_SETTING: DWORD = 15401;
+pub const ERROR_RUNLEVEL_SWITCH_TIMEOUT: DWORD = 15402;
+pub const ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT: DWORD = 15403;
+pub const ERROR_RUNLEVEL_SWITCH_IN_PROGRESS: DWORD = 15404;
+pub const ERROR_SERVICES_FAILED_AUTOSTART: DWORD = 15405;
+pub const ERROR_COM_TASK_STOP_PENDING: DWORD = 15501;
+pub const ERROR_INSTALL_OPEN_PACKAGE_FAILED: DWORD = 15600;
+pub const ERROR_INSTALL_PACKAGE_NOT_FOUND: DWORD = 15601;
+pub const ERROR_INSTALL_INVALID_PACKAGE: DWORD = 15602;
+pub const ERROR_INSTALL_RESOLVE_DEPENDENCY_FAILED: DWORD = 15603;
+pub const ERROR_INSTALL_OUT_OF_DISK_SPACE: DWORD = 15604;
+pub const ERROR_INSTALL_NETWORK_FAILURE: DWORD = 15605;
+pub const ERROR_INSTALL_REGISTRATION_FAILURE: DWORD = 15606;
+pub const ERROR_INSTALL_DEREGISTRATION_FAILURE: DWORD = 15607;
+pub const ERROR_INSTALL_CANCEL: DWORD = 15608;
+pub const ERROR_INSTALL_FAILED: DWORD = 15609;
+pub const ERROR_REMOVE_FAILED: DWORD = 15610;
+pub const ERROR_PACKAGE_ALREADY_EXISTS: DWORD = 15611;
+pub const ERROR_NEEDS_REMEDIATION: DWORD = 15612;
+pub const ERROR_INSTALL_PREREQUISITE_FAILED: DWORD = 15613;
+pub const ERROR_PACKAGE_REPOSITORY_CORRUPTED: DWORD = 15614;
+pub const ERROR_INSTALL_POLICY_FAILURE: DWORD = 15615;
+pub const ERROR_PACKAGE_UPDATING: DWORD = 15616;
+pub const ERROR_DEPLOYMENT_BLOCKED_BY_POLICY: DWORD = 15617;
+pub const ERROR_PACKAGES_IN_USE: DWORD = 15618;
+pub const ERROR_RECOVERY_FILE_CORRUPT: DWORD = 15619;
+pub const ERROR_INVALID_STAGED_SIGNATURE: DWORD = 15620;
+pub const ERROR_DELETING_EXISTING_APPLICATIONDATA_STORE_FAILED: DWORD = 15621;
+pub const ERROR_INSTALL_PACKAGE_DOWNGRADE: DWORD = 15622;
+pub const ERROR_SYSTEM_NEEDS_REMEDIATION: DWORD = 15623;
+pub const ERROR_APPX_INTEGRITY_FAILURE_CLR_NGEN: DWORD = 15624;
+pub const ERROR_RESILIENCY_FILE_CORRUPT: DWORD = 15625;
+pub const ERROR_INSTALL_FIREWALL_SERVICE_NOT_RUNNING: DWORD = 15626;
+pub const ERROR_STATE_LOAD_STORE_FAILED: DWORD = 15800;
+pub const ERROR_STATE_GET_VERSION_FAILED: DWORD = 15801;
+pub const ERROR_STATE_SET_VERSION_FAILED: DWORD = 15802;
+pub const ERROR_STATE_STRUCTURED_RESET_FAILED: DWORD = 15803;
+pub const ERROR_STATE_OPEN_CONTAINER_FAILED: DWORD = 15804;
+pub const ERROR_STATE_CREATE_CONTAINER_FAILED: DWORD = 15805;
+pub const ERROR_STATE_DELETE_CONTAINER_FAILED: DWORD = 15806;
+pub const ERROR_STATE_READ_SETTING_FAILED: DWORD = 15807;
+pub const ERROR_STATE_WRITE_SETTING_FAILED: DWORD = 15808;
+pub const ERROR_STATE_DELETE_SETTING_FAILED: DWORD = 15809;
+pub const ERROR_STATE_QUERY_SETTING_FAILED: DWORD = 15810;
+pub const ERROR_STATE_READ_COMPOSITE_SETTING_FAILED: DWORD = 15811;
+pub const ERROR_STATE_WRITE_COMPOSITE_SETTING_FAILED: DWORD = 15812;
+pub const ERROR_STATE_ENUMERATE_CONTAINER_FAILED: DWORD = 15813;
+pub const ERROR_STATE_ENUMERATE_SETTINGS_FAILED: DWORD = 15814;
+pub const ERROR_STATE_COMPOSITE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED: DWORD = 15815;
+pub const ERROR_STATE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED: DWORD = 15816;
+pub const ERROR_STATE_SETTING_NAME_SIZE_LIMIT_EXCEEDED: DWORD = 15817;
+pub const ERROR_STATE_CONTAINER_NAME_SIZE_LIMIT_EXCEEDED: DWORD = 15818;
+pub const ERROR_API_UNAVAILABLE: DWORD = 15841;
+pub const ERROR_AUDITING_DISABLED: DWORD = 0xC0090001;
+pub const ERROR_ALL_SIDS_FILTERED: DWORD = 0xC0090002;
+
+pub const WSABASEERR: c_int = 10000;
+pub const WSAEINTR: c_int = WSABASEERR + 4;
+pub const WSAEBADF: c_int = WSABASEERR + 9;
+pub const WSAEACCES: c_int = WSABASEERR + 13;
+pub const WSAEFAULT: c_int = WSABASEERR + 14;
+pub const WSAEINVAL: c_int = WSABASEERR + 22;
+pub const WSAEMFILE: c_int = WSABASEERR + 24;
+pub const WSAEWOULDBLOCK: c_int = WSABASEERR + 35;
+pub const WSAEINPROGRESS: c_int = WSABASEERR + 36;
+pub const WSAEALREADY: c_int = WSABASEERR + 37;
+pub const WSAENOTSOCK: c_int = WSABASEERR + 38;
+pub const WSAEDESTADDRREQ: c_int = WSABASEERR + 39;
+pub const WSAEMSGSIZE: c_int = WSABASEERR + 40;
+pub const WSAEPROTOTYPE: c_int = WSABASEERR + 41;
+pub const WSAENOPROTOOPT: c_int = WSABASEERR + 42;
+pub const WSAEPROTONOSUPPORT: c_int = WSABASEERR + 43;
+pub const WSAESOCKTNOSUPPORT: c_int = WSABASEERR + 44;
+pub const WSAEOPNOTSUPP: c_int = WSABASEERR + 45;
+pub const WSAEPFNOSUPPORT: c_int = WSABASEERR + 46;
+pub const WSAEAFNOSUPPORT: c_int = WSABASEERR + 47;
+pub const WSAEADDRINUSE: c_int = WSABASEERR + 48;
+pub const WSAEADDRNOTAVAIL: c_int = WSABASEERR + 49;
+pub const WSAENETDOWN: c_int = WSABASEERR + 50;
+pub const WSAENETUNREACH: c_int = WSABASEERR + 51;
+pub const WSAENETRESET: c_int = WSABASEERR + 52;
+pub const WSAECONNABORTED: c_int = WSABASEERR + 53;
+pub const WSAECONNRESET: c_int = WSABASEERR + 54;
+pub const WSAENOBUFS: c_int = WSABASEERR + 55;
+pub const WSAEISCONN: c_int = WSABASEERR + 56;
+pub const WSAENOTCONN: c_int = WSABASEERR + 57;
+pub const WSAESHUTDOWN: c_int = WSABASEERR + 58;
+pub const WSAETOOMANYREFS: c_int = WSABASEERR + 59;
+pub const WSAETIMEDOUT: c_int = WSABASEERR + 60;
+pub const WSAECONNREFUSED: c_int = WSABASEERR + 61;
+pub const WSAELOOP: c_int = WSABASEERR + 62;
+pub const WSAENAMETOOLONG: c_int = WSABASEERR + 63;
+pub const WSAEHOSTDOWN: c_int = WSABASEERR + 64;
+pub const WSAEHOSTUNREACH: c_int = WSABASEERR + 65;
+pub const WSAENOTEMPTY: c_int = WSABASEERR + 66;
+pub const WSAEPROCLIM: c_int = WSABASEERR + 67;
+pub const WSAEUSERS: c_int = WSABASEERR + 68;
+pub const WSAEDQUOT: c_int = WSABASEERR + 69;
+pub const WSAESTALE: c_int = WSABASEERR + 70;
+pub const WSAEREMOTE: c_int = WSABASEERR + 71;
+pub const WSASYSNOTREADY: c_int = WSABASEERR + 91;
+pub const WSAVERNOTSUPPORTED: c_int = WSABASEERR + 92;
+pub const WSANOTINITIALISED: c_int = WSABASEERR + 93;
+pub const WSAEDISCON: c_int = WSABASEERR + 101;
+pub const WSAENOMORE: c_int = WSABASEERR + 102;
+pub const WSAECANCELLED: c_int = WSABASEERR + 103;
+pub const WSAEINVALIDPROCTABLE: c_int = WSABASEERR + 104;
+pub const WSAEINVALIDPROVIDER: c_int = WSABASEERR + 105;
+pub const WSAEPROVIDERFAILEDINIT: c_int = WSABASEERR + 106;
+pub const WSASYSCALLFAILURE: c_int = WSABASEERR + 107;
+pub const WSASERVICE_NOT_FOUND: c_int = WSABASEERR + 108;
+pub const WSATYPE_NOT_FOUND: c_int = WSABASEERR + 109;
+pub const WSA_E_NO_MORE: c_int = WSABASEERR + 110;
+pub const WSA_E_CANCELLED: c_int = WSABASEERR + 111;
+pub const WSAEREFUSED: c_int = WSABASEERR + 112;
+pub const WSAHOST_NOT_FOUND: c_int = WSABASEERR + 1001;
+pub const WSATRY_AGAIN: c_int = WSABASEERR + 1002;
+pub const WSANO_RECOVERY: c_int = WSABASEERR + 1003;
+pub const WSANO_DATA: c_int = WSABASEERR + 1004;
+pub const WSA_QOS_RECEIVERS: c_int = WSABASEERR + 1005;
+pub const WSA_QOS_SENDERS: c_int = WSABASEERR + 1006;
+pub const WSA_QOS_NO_SENDERS: c_int = WSABASEERR + 1007;
+pub const WSA_QOS_NO_RECEIVERS: c_int = WSABASEERR + 1008;
+pub const WSA_QOS_REQUEST_CONFIRMED: c_int = WSABASEERR + 1009;
+pub const WSA_QOS_ADMISSION_FAILURE: c_int = WSABASEERR + 1010;
+pub const WSA_QOS_POLICY_FAILURE: c_int = WSABASEERR + 1011;
+pub const WSA_QOS_BAD_STYLE: c_int = WSABASEERR + 1012;
+pub const WSA_QOS_BAD_OBJECT: c_int = WSABASEERR + 1013;
+pub const WSA_QOS_TRAFFIC_CTRL_ERROR: c_int = WSABASEERR + 1014;
+pub const WSA_QOS_GENERIC_ERROR: c_int = WSABASEERR + 1015;
+pub const WSA_QOS_ESERVICETYPE: c_int = WSABASEERR + 1016;
+pub const WSA_QOS_EFLOWSPEC: c_int = WSABASEERR + 1017;
+pub const WSA_QOS_EPROVSPECBUF: c_int = WSABASEERR + 1018;
+pub const WSA_QOS_EFILTERSTYLE: c_int = WSABASEERR + 1019;
+pub const WSA_QOS_EFILTERTYPE: c_int = WSABASEERR + 1020;
+pub const WSA_QOS_EFILTERCOUNT: c_int = WSABASEERR + 1021;
+pub const WSA_QOS_EOBJLENGTH: c_int = WSABASEERR + 1022;
+pub const WSA_QOS_EFLOWCOUNT: c_int = WSABASEERR + 1023;
+pub const WSA_QOS_EUNKNOWNPSOBJ: c_int = WSABASEERR + 1024;
+pub const WSA_QOS_EUNKOWNPSOBJ: c_int = WSA_QOS_EUNKNOWNPSOBJ;
+pub const WSA_QOS_EPOLICYOBJ: c_int = WSABASEERR + 1025;
+pub const WSA_QOS_EFLOWDESC: c_int = WSABASEERR + 1026;
+pub const WSA_QOS_EPSFLOWSPEC: c_int = WSABASEERR + 1027;
+pub const WSA_QOS_EPSFILTERSPEC: c_int = WSABASEERR + 1028;
+pub const WSA_QOS_ESDMODEOBJ: c_int = WSABASEERR + 1029;
+pub const WSA_QOS_ESHAPERATEOBJ: c_int = WSABASEERR + 1030;
+pub const WSA_QOS_RESERVED_PETYPE: c_int = WSABASEERR + 1031;
index 2b6143de96056f44d8ebdb09457366c892430267..c677adae6888e0c30e24e182539584bef1873784 100644 (file)
@@ -514,7 +514,7 @@ impl File {
                 }
                 _ => {
                     return Err(io::Error::new_const(
-                        io::ErrorKind::Other,
+                        io::ErrorKind::Uncategorized,
                         &"Unsupported reparse point type",
                     ));
                 }
@@ -961,9 +961,8 @@ pub fn try_exists(path: &Path) -> io::Result<bool> {
             // `ERROR_SHARING_VIOLATION` means that the file has been locked by
             // another process. This is often temporary so we simply report it
             // as the file existing.
-            io::ErrorKind::Other if e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as i32) => {
-                Ok(true)
-            }
+            _ if e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as i32) => Ok(true),
+
             // Other errors such as `ERROR_ACCESS_DENIED` may indicate that the
             // file exists. However, these types of errors are usually more
             // permanent so we report them here.
index f23e874f249054df88c85c792f9ec37704ef9612..28fec817f86232328e2471ebe6f6410266b29970 100644 (file)
@@ -61,16 +61,18 @@ pub unsafe fn cleanup() {
 }
 
 pub fn decode_error_kind(errno: i32) -> ErrorKind {
+    use ErrorKind::*;
+
     match errno as c::DWORD {
-        c::ERROR_ACCESS_DENIED => return ErrorKind::PermissionDenied,
-        c::ERROR_ALREADY_EXISTS => return ErrorKind::AlreadyExists,
-        c::ERROR_FILE_EXISTS => return ErrorKind::AlreadyExists,
-        c::ERROR_BROKEN_PIPE => return ErrorKind::BrokenPipe,
-        c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound,
-        c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound,
-        c::ERROR_NO_DATA => return ErrorKind::BrokenPipe,
-        c::ERROR_INVALID_PARAMETER => return ErrorKind::InvalidInput,
-        c::ERROR_NOT_ENOUGH_MEMORY | c::ERROR_OUTOFMEMORY => return ErrorKind::OutOfMemory,
+        c::ERROR_ACCESS_DENIED => return PermissionDenied,
+        c::ERROR_ALREADY_EXISTS => return AlreadyExists,
+        c::ERROR_FILE_EXISTS => return AlreadyExists,
+        c::ERROR_BROKEN_PIPE => return BrokenPipe,
+        c::ERROR_FILE_NOT_FOUND => return NotFound,
+        c::ERROR_PATH_NOT_FOUND => return NotFound,
+        c::ERROR_NO_DATA => return BrokenPipe,
+        c::ERROR_INVALID_PARAMETER => return InvalidInput,
+        c::ERROR_NOT_ENOUGH_MEMORY | c::ERROR_OUTOFMEMORY => return OutOfMemory,
         c::ERROR_SEM_TIMEOUT
         | c::WAIT_TIMEOUT
         | c::ERROR_DRIVER_CANCEL_TIMEOUT
@@ -86,24 +88,42 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
         | c::DNS_ERROR_RECORD_TIMED_OUT
         | c::ERROR_IPSEC_IKE_TIMED_OUT
         | c::ERROR_RUNLEVEL_SWITCH_TIMEOUT
-        | c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return ErrorKind::TimedOut,
-        c::ERROR_CALL_NOT_IMPLEMENTED => return ErrorKind::Unsupported,
+        | c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return TimedOut,
+        c::ERROR_CALL_NOT_IMPLEMENTED => return Unsupported,
+        c::ERROR_HOST_UNREACHABLE => return HostUnreachable,
+        c::ERROR_NETWORK_UNREACHABLE => return NetworkUnreachable,
+        c::ERROR_DIRECTORY => return NotADirectory,
+        c::ERROR_DIRECTORY_NOT_SUPPORTED => return IsADirectory,
+        c::ERROR_DIR_NOT_EMPTY => return DirectoryNotEmpty,
+        c::ERROR_WRITE_PROTECT => return ReadOnlyFilesystem,
+        c::ERROR_DISK_FULL | c::ERROR_HANDLE_DISK_FULL => return StorageFull,
+        c::ERROR_SEEK_ON_DEVICE => return NotSeekable,
+        c::ERROR_DISK_QUOTA_EXCEEDED => return FilesystemQuotaExceeded,
+        c::ERROR_FILE_TOO_LARGE => return FileTooLarge,
+        c::ERROR_BUSY => return ResourceBusy,
+        c::ERROR_POSSIBLE_DEADLOCK => return Deadlock,
+        c::ERROR_NOT_SAME_DEVICE => return CrossesDevices,
+        c::ERROR_TOO_MANY_LINKS => return TooManyLinks,
+        c::ERROR_FILENAME_EXCED_RANGE => return FilenameTooLong,
         _ => {}
     }
 
     match errno {
-        c::WSAEACCES => ErrorKind::PermissionDenied,
-        c::WSAEADDRINUSE => ErrorKind::AddrInUse,
-        c::WSAEADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
-        c::WSAECONNABORTED => ErrorKind::ConnectionAborted,
-        c::WSAECONNREFUSED => ErrorKind::ConnectionRefused,
-        c::WSAECONNRESET => ErrorKind::ConnectionReset,
-        c::WSAEINVAL => ErrorKind::InvalidInput,
-        c::WSAENOTCONN => ErrorKind::NotConnected,
-        c::WSAEWOULDBLOCK => ErrorKind::WouldBlock,
-        c::WSAETIMEDOUT => ErrorKind::TimedOut,
+        c::WSAEACCES => PermissionDenied,
+        c::WSAEADDRINUSE => AddrInUse,
+        c::WSAEADDRNOTAVAIL => AddrNotAvailable,
+        c::WSAECONNABORTED => ConnectionAborted,
+        c::WSAECONNREFUSED => ConnectionRefused,
+        c::WSAECONNRESET => ConnectionReset,
+        c::WSAEINVAL => InvalidInput,
+        c::WSAENOTCONN => NotConnected,
+        c::WSAEWOULDBLOCK => WouldBlock,
+        c::WSAETIMEDOUT => TimedOut,
+        c::WSAEHOSTUNREACH => HostUnreachable,
+        c::WSAENETDOWN => NetworkDown,
+        c::WSAENETUNREACH => NetworkUnreachable,
 
-        _ => ErrorKind::Other,
+        _ => Uncategorized,
     }
 }
 
index 1ad13254c0846f2e27bfd0a4793b906211ef991f..9cea5c5e63a2df56ec4caed7be741e70c785570f 100644 (file)
@@ -12,7 +12,7 @@ use crate::sys_common::net;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::time::Duration;
 
-use libc::{c_int, c_long, c_ulong, c_void};
+use libc::{c_int, c_long, c_ulong};
 
 pub type wrlen_t = i32;
 
@@ -93,153 +93,177 @@ where
 
 impl Socket {
     pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
-        let fam = match *addr {
+        let family = match *addr {
             SocketAddr::V4(..) => c::AF_INET,
             SocketAddr::V6(..) => c::AF_INET6,
         };
         let socket = unsafe {
-            match c::WSASocketW(
-                fam,
+            c::WSASocketW(
+                family,
                 ty,
                 0,
                 ptr::null_mut(),
                 0,
                 c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT,
-            ) {
-                c::INVALID_SOCKET => match c::WSAGetLastError() {
-                    c::WSAEPROTOTYPE | c::WSAEINVAL => {
-                        match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0, c::WSA_FLAG_OVERLAPPED)
-                        {
-                            c::INVALID_SOCKET => Err(last_error()),
-                            n => {
-                                let s = Socket(n);
-                                s.set_no_inherit()?;
-                                Ok(s)
-                            }
-                        }
-                    }
-                    n => Err(io::Error::from_raw_os_error(n)),
-                },
-                n => Ok(Socket(n)),
+            )
+        };
+
+        if socket != c::INVALID_SOCKET {
+            Ok(Self(socket))
+        } else {
+            let error = unsafe { c::WSAGetLastError() };
+
+            if error != c::WSAEPROTOTYPE && error != c::WSAEINVAL {
+                return Err(io::Error::from_raw_os_error(error));
+            }
+
+            let socket =
+                unsafe { c::WSASocketW(family, ty, 0, ptr::null_mut(), 0, c::WSA_FLAG_OVERLAPPED) };
+
+            if socket == c::INVALID_SOCKET {
+                return Err(last_error());
             }
-        }?;
-        Ok(socket)
+
+            let socket = Self(socket);
+            socket.set_no_inherit()?;
+            Ok(socket)
+        }
     }
 
     pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
         self.set_nonblocking(true)?;
-        let r = unsafe {
+        let result = {
             let (addrp, len) = addr.into_inner();
-            cvt(c::connect(self.0, addrp, len))
+            let result = unsafe { c::connect(self.0, addrp, len) };
+            cvt(result).map(drop)
         };
         self.set_nonblocking(false)?;
 
-        match r {
-            Ok(_) => return Ok(()),
-            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
-            Err(e) => return Err(e),
-        }
-
-        if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
-            return Err(io::Error::new_const(
-                io::ErrorKind::InvalidInput,
-                &"cannot set a 0 duration timeout",
-            ));
-        }
-
-        let mut timeout = c::timeval {
-            tv_sec: timeout.as_secs() as c_long,
-            tv_usec: (timeout.subsec_nanos() / 1000) as c_long,
-        };
-        if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
-            timeout.tv_usec = 1;
-        }
+        match result {
+            Err(ref error) if error.kind() == io::ErrorKind::WouldBlock => {
+                if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
+                    return Err(io::Error::new_const(
+                        io::ErrorKind::InvalidInput,
+                        &"cannot set a 0 duration timeout",
+                    ));
+                }
 
-        let fds = unsafe {
-            let mut fds = mem::zeroed::<c::fd_set>();
-            fds.fd_count = 1;
-            fds.fd_array[0] = self.0;
-            fds
-        };
+                let mut timeout = c::timeval {
+                    tv_sec: timeout.as_secs() as c_long,
+                    tv_usec: (timeout.subsec_nanos() / 1000) as c_long,
+                };
 
-        let mut writefds = fds;
-        let mut errorfds = fds;
+                if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
+                    timeout.tv_usec = 1;
+                }
 
-        let n =
-            unsafe { cvt(c::select(1, ptr::null_mut(), &mut writefds, &mut errorfds, &timeout))? };
+                let fds = {
+                    let mut fds = unsafe { mem::zeroed::<c::fd_set>() };
+                    fds.fd_count = 1;
+                    fds.fd_array[0] = self.0;
+                    fds
+                };
+
+                let mut writefds = fds;
+                let mut errorfds = fds;
+
+                let count = {
+                    let result = unsafe {
+                        c::select(1, ptr::null_mut(), &mut writefds, &mut errorfds, &timeout)
+                    };
+                    cvt(result)?
+                };
+
+                match count {
+                    0 => {
+                        Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out"))
+                    }
+                    _ => {
+                        if writefds.fd_count != 1 {
+                            if let Some(e) = self.take_error()? {
+                                return Err(e);
+                            }
+                        }
 
-        match n {
-            0 => Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out")),
-            _ => {
-                if writefds.fd_count != 1 {
-                    if let Some(e) = self.take_error()? {
-                        return Err(e);
+                        Ok(())
                     }
                 }
-                Ok(())
             }
+            _ => result,
         }
     }
 
     pub fn accept(&self, storage: *mut c::SOCKADDR, len: *mut c_int) -> io::Result<Socket> {
-        let socket = unsafe {
-            match c::accept(self.0, storage, len) {
-                c::INVALID_SOCKET => Err(last_error()),
-                n => Ok(Socket(n)),
-            }
-        }?;
-        Ok(socket)
+        let socket = unsafe { c::accept(self.0, storage, len) };
+
+        match socket {
+            c::INVALID_SOCKET => Err(last_error()),
+            _ => Ok(Self(socket)),
+        }
     }
 
     pub fn duplicate(&self) -> io::Result<Socket> {
+        let mut info = unsafe { mem::zeroed::<c::WSAPROTOCOL_INFO>() };
+        let result = unsafe { c::WSADuplicateSocketW(self.0, c::GetCurrentProcessId(), &mut info) };
+        cvt(result)?;
         let socket = unsafe {
-            let mut info: c::WSAPROTOCOL_INFO = mem::zeroed();
-            cvt(c::WSADuplicateSocketW(self.0, c::GetCurrentProcessId(), &mut info))?;
-
-            match c::WSASocketW(
+            c::WSASocketW(
                 info.iAddressFamily,
                 info.iSocketType,
                 info.iProtocol,
                 &mut info,
                 0,
                 c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT,
-            ) {
-                c::INVALID_SOCKET => match c::WSAGetLastError() {
-                    c::WSAEPROTOTYPE | c::WSAEINVAL => {
-                        match c::WSASocketW(
-                            info.iAddressFamily,
-                            info.iSocketType,
-                            info.iProtocol,
-                            &mut info,
-                            0,
-                            c::WSA_FLAG_OVERLAPPED,
-                        ) {
-                            c::INVALID_SOCKET => Err(last_error()),
-                            n => {
-                                let s = Socket(n);
-                                s.set_no_inherit()?;
-                                Ok(s)
-                            }
-                        }
-                    }
-                    n => Err(io::Error::from_raw_os_error(n)),
-                },
-                n => Ok(Socket(n)),
+            )
+        };
+
+        if socket != c::INVALID_SOCKET {
+            Ok(Self(socket))
+        } else {
+            let error = unsafe { c::WSAGetLastError() };
+
+            if error != c::WSAEPROTOTYPE && error != c::WSAEINVAL {
+                return Err(io::Error::from_raw_os_error(error));
+            }
+
+            let socket = unsafe {
+                c::WSASocketW(
+                    info.iAddressFamily,
+                    info.iSocketType,
+                    info.iProtocol,
+                    &mut info,
+                    0,
+                    c::WSA_FLAG_OVERLAPPED,
+                )
+            };
+
+            if socket == c::INVALID_SOCKET {
+                return Err(last_error());
             }
-        }?;
-        Ok(socket)
+
+            let socket = Self(socket);
+            socket.set_no_inherit()?;
+            Ok(socket)
+        }
     }
 
     fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> {
         // On unix when a socket is shut down all further reads return 0, so we
         // do the same on windows to map a shut down socket to returning EOF.
-        let len = cmp::min(buf.len(), i32::MAX as usize) as i32;
-        unsafe {
-            match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, flags) {
-                -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0),
-                -1 => Err(last_error()),
-                n => Ok(n as usize),
+        let length = cmp::min(buf.len(), i32::MAX as usize) as i32;
+        let result = unsafe { c::recv(self.0, buf.as_mut_ptr() as *mut _, length, flags) };
+
+        match result {
+            c::SOCKET_ERROR => {
+                let error = unsafe { c::WSAGetLastError() };
+
+                if error == c::WSAESHUTDOWN {
+                    Ok(0)
+                } else {
+                    Err(io::Error::from_raw_os_error(error))
+                }
             }
+            _ => Ok(result as usize),
         }
     }
 
@@ -250,23 +274,31 @@ impl Socket {
     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         // On unix when a socket is shut down all further reads return 0, so we
         // do the same on windows to map a shut down socket to returning EOF.
-        let len = cmp::min(bufs.len(), c::DWORD::MAX as usize) as c::DWORD;
+        let length = cmp::min(bufs.len(), c::DWORD::MAX as usize) as c::DWORD;
         let mut nread = 0;
         let mut flags = 0;
-        unsafe {
-            let ret = c::WSARecv(
+        let result = unsafe {
+            c::WSARecv(
                 self.0,
                 bufs.as_mut_ptr() as *mut c::WSABUF,
-                len,
+                length,
                 &mut nread,
                 &mut flags,
                 ptr::null_mut(),
                 ptr::null_mut(),
-            );
-            match ret {
-                0 => Ok(nread as usize),
-                _ if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0),
-                _ => Err(last_error()),
+            )
+        };
+
+        match result {
+            0 => Ok(nread as usize),
+            _ => {
+                let error = unsafe { c::WSAGetLastError() };
+
+                if error == c::WSAESHUTDOWN {
+                    Ok(0)
+                } else {
+                    Err(io::Error::from_raw_os_error(error))
+                }
             }
         }
     }
@@ -285,27 +317,34 @@ impl Socket {
         buf: &mut [u8],
         flags: c_int,
     ) -> io::Result<(usize, SocketAddr)> {
-        let mut storage: c::SOCKADDR_STORAGE_LH = unsafe { mem::zeroed() };
+        let mut storage = unsafe { mem::zeroed::<c::SOCKADDR_STORAGE_LH>() };
         let mut addrlen = mem::size_of_val(&storage) as c::socklen_t;
-        let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
+        let length = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
 
         // On unix when a socket is shut down all further reads return 0, so we
         // do the same on windows to map a shut down socket to returning EOF.
-        unsafe {
-            match c::recvfrom(
+        let result = unsafe {
+            c::recvfrom(
                 self.0,
-                buf.as_mut_ptr() as *mut c_void,
-                len,
+                buf.as_mut_ptr() as *mut _,
+                length,
                 flags,
                 &mut storage as *mut _ as *mut _,
                 &mut addrlen,
-            ) {
-                -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => {
+            )
+        };
+
+        match result {
+            c::SOCKET_ERROR => {
+                let error = unsafe { c::WSAGetLastError() };
+
+                if error == c::WSAESHUTDOWN {
                     Ok((0, net::sockaddr_to_addr(&storage, addrlen as usize)?))
+                } else {
+                    Err(io::Error::from_raw_os_error(error))
                 }
-                -1 => Err(last_error()),
-                n => Ok((n as usize, net::sockaddr_to_addr(&storage, addrlen as usize)?)),
             }
+            _ => Ok((result as usize, net::sockaddr_to_addr(&storage, addrlen as usize)?)),
         }
     }
 
@@ -318,20 +357,20 @@ impl Socket {
     }
 
     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        let len = cmp::min(bufs.len(), c::DWORD::MAX as usize) as c::DWORD;
+        let length = cmp::min(bufs.len(), c::DWORD::MAX as usize) as c::DWORD;
         let mut nwritten = 0;
-        unsafe {
-            cvt(c::WSASend(
+        let result = unsafe {
+            c::WSASend(
                 self.0,
-                bufs.as_ptr() as *const c::WSABUF as *mut c::WSABUF,
-                len,
+                bufs.as_ptr() as *const c::WSABUF as *mut _,
+                length,
                 &mut nwritten,
                 0,
                 ptr::null_mut(),
                 ptr::null_mut(),
-            ))?;
-        }
-        Ok(nwritten as usize)
+            )
+        };
+        cvt(result).map(|_| nwritten as usize)
     }
 
     #[inline]
@@ -384,14 +423,14 @@ impl Socket {
             Shutdown::Read => c::SD_RECEIVE,
             Shutdown::Both => c::SD_BOTH,
         };
-        cvt(unsafe { c::shutdown(self.0, how) })?;
-        Ok(())
+        let result = unsafe { c::shutdown(self.0, how) };
+        cvt(result).map(drop)
     }
 
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         let mut nonblocking = nonblocking as c_ulong;
-        let r = unsafe { c::ioctlsocket(self.0, c::FIONBIO as c_int, &mut nonblocking) };
-        if r == 0 { Ok(()) } else { Err(io::Error::last_os_error()) }
+        let result = unsafe { c::ioctlsocket(self.0, c::FIONBIO as c_int, &mut nonblocking) };
+        cvt(result).map(drop)
     }
 
     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
index 81dbea4a067399755a1fd029fc3ed514c6c44e05..ae193b82e91bb4ce67631babc0ff1c67a6f2e583 100644 (file)
@@ -3,7 +3,7 @@
 #[cfg(test)]
 mod tests;
 
-use crate::borrow::Borrow;
+use crate::cmp;
 use crate::collections::BTreeMap;
 use crate::convert::{TryFrom, TryInto};
 use crate::env;
@@ -34,32 +34,115 @@ use libc::{c_void, EXIT_FAILURE, EXIT_SUCCESS};
 // Command
 ////////////////////////////////////////////////////////////////////////////////
 
-#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Clone, Debug, Eq)]
 #[doc(hidden)]
-pub struct EnvKey(OsString);
+pub struct EnvKey {
+    os_string: OsString,
+    // This stores a UTF-16 encoded string to workaround the mismatch between
+    // Rust's OsString (WTF-8) and the Windows API string type (UTF-16).
+    // Normally converting on every API call is acceptable but here
+    // `c::CompareStringOrdinal` will be called for every use of `==`.
+    utf16: Vec<u16>,
+}
+
+impl EnvKey {
+    fn new<T: Into<OsString>>(key: T) -> Self {
+        EnvKey::from(key.into())
+    }
+}
+
+// Comparing Windows environment variable keys[1] are behaviourally the
+// composition of two operations[2]:
+//
+// 1. Case-fold both strings. This is done using a language-independent
+// uppercase mapping that's unique to Windows (albeit based on data from an
+// older Unicode spec). It only operates on individual UTF-16 code units so
+// surrogates are left unchanged. This uppercase mapping can potentially change
+// between Windows versions.
+//
+// 2. Perform an ordinal comparison of the strings. A comparison using ordinal
+// is just a comparison based on the numerical value of each UTF-16 code unit[3].
+//
+// Because the case-folding mapping is unique to Windows and not guaranteed to
+// be stable, we ask the OS to compare the strings for us. This is done by
+// calling `CompareStringOrdinal`[4] with `bIgnoreCase` set to `TRUE`.
+//
+// [1] https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings#choosing-a-stringcomparison-member-for-your-method-call
+// [2] https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings#stringtoupper-and-stringtolower
+// [3] https://docs.microsoft.com/en-us/dotnet/api/system.stringcomparison?view=net-5.0#System_StringComparison_Ordinal
+// [4] https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-comparestringordinal
+impl Ord for EnvKey {
+    fn cmp(&self, other: &Self) -> cmp::Ordering {
+        unsafe {
+            let result = c::CompareStringOrdinal(
+                self.utf16.as_ptr(),
+                self.utf16.len() as _,
+                other.utf16.as_ptr(),
+                other.utf16.len() as _,
+                c::TRUE,
+            );
+            match result {
+                c::CSTR_LESS_THAN => cmp::Ordering::Less,
+                c::CSTR_EQUAL => cmp::Ordering::Equal,
+                c::CSTR_GREATER_THAN => cmp::Ordering::Greater,
+                // `CompareStringOrdinal` should never fail so long as the parameters are correct.
+                _ => panic!("comparing environment keys failed: {}", Error::last_os_error()),
+            }
+        }
+    }
+}
+impl PartialOrd for EnvKey {
+    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
+        Some(self.cmp(other))
+    }
+}
+impl PartialEq for EnvKey {
+    fn eq(&self, other: &Self) -> bool {
+        if self.utf16.len() != other.utf16.len() {
+            false
+        } else {
+            self.cmp(other) == cmp::Ordering::Equal
+        }
+    }
+}
+impl PartialOrd<str> for EnvKey {
+    fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
+        Some(self.cmp(&EnvKey::new(other)))
+    }
+}
+impl PartialEq<str> for EnvKey {
+    fn eq(&self, other: &str) -> bool {
+        if self.os_string.len() != other.len() {
+            false
+        } else {
+            self.cmp(&EnvKey::new(other)) == cmp::Ordering::Equal
+        }
+    }
+}
 
+// Environment variable keys should preserve their original case even though
+// they are compared using a caseless string mapping.
 impl From<OsString> for EnvKey {
-    fn from(mut k: OsString) -> Self {
-        k.make_ascii_uppercase();
-        EnvKey(k)
+    fn from(k: OsString) -> Self {
+        EnvKey { utf16: k.encode_wide().collect(), os_string: k }
     }
 }
 
 impl From<EnvKey> for OsString {
     fn from(k: EnvKey) -> Self {
-        k.0
+        k.os_string
     }
 }
 
-impl Borrow<OsStr> for EnvKey {
-    fn borrow(&self) -> &OsStr {
-        &self.0
+impl From<&OsStr> for EnvKey {
+    fn from(k: &OsStr) -> Self {
+        Self::from(k.to_os_string())
     }
 }
 
 impl AsRef<OsStr> for EnvKey {
     fn as_ref(&self) -> &OsStr {
-        &self.0
+        &self.os_string
     }
 }
 
@@ -73,7 +156,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,
@@ -97,6 +180,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 {
@@ -114,7 +205,7 @@ impl 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
@@ -139,6 +230,10 @@ impl Command {
         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
     }
@@ -166,7 +261,7 @@ impl Command {
         // to read the *child's* PATH if one is provided. See #15149 for more
         // details.
         let program = maybe_env.as_ref().and_then(|env| {
-            if let Some(v) = env.get(OsStr::new("PATH")) {
+            if let Some(v) = env.get(&EnvKey::new("PATH")) {
                 // Split the value and test each path to see if the
                 // program exists.
                 for path in split_paths(&v) {
@@ -207,7 +302,7 @@ impl Command {
         // the remaining portion of this spawn in a mutex.
         //
         // For more information, msdn also has an article about this race:
-        // http://support.microsoft.com/kb/315939
+        // https://support.microsoft.com/kb/315939
         static CREATE_PROCESS_LOCK: StaticMutex = StaticMutex::new();
 
         let _guard = unsafe { CREATE_PROCESS_LOCK.lock() };
@@ -251,9 +346,13 @@ impl Command {
 
 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(())
     }
@@ -472,44 +571,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);
         }
@@ -530,8 +648,15 @@ fn make_envp(maybe_env: Option<BTreeMap<EnvKey, OsString>>) -> io::Result<(*mut
     if let Some(env) = maybe_env {
         let mut blk = Vec::new();
 
+        // If there are no environment variables to set then signal this by
+        // pushing a null.
+        if env.is_empty() {
+            blk.push(0);
+        }
+
         for (k, v) in env {
-            blk.extend(ensure_no_nuls(k.0)?.encode_wide());
+            ensure_no_nuls(k.os_string)?;
+            blk.extend(k.utf16);
             blk.push('=' as u16);
             blk.extend(ensure_no_nuls(v)?.encode_wide());
             blk.push(0);
@@ -555,13 +680,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 8830ae049c65d8b10e690ab770b1ba78debb827d..3b65856dcaca6d4f3e017a2ba97fccf2cf8f339c 100644 (file)
@@ -1,12 +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();
@@ -15,6 +38,11 @@ fn test_make_command_line() {
 
     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"
@@ -41,3 +69,62 @@ fn test_make_command_line() {
         "\"\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}\""
     );
 }
+
+// On Windows, environment args are case preserving but comparisons are case-insensitive.
+// See: #85242
+#[test]
+fn windows_env_unicode_case() {
+    let test_cases = [
+        ("ä", "Ä"),
+        ("ß", "SS"),
+        ("Ä", "Ö"),
+        ("Ä", "Ö"),
+        ("I", "İ"),
+        ("I", "i"),
+        ("I", "ı"),
+        ("i", "I"),
+        ("i", "İ"),
+        ("i", "ı"),
+        ("İ", "I"),
+        ("İ", "i"),
+        ("İ", "ı"),
+        ("ı", "I"),
+        ("ı", "i"),
+        ("ı", "İ"),
+        ("ä", "Ä"),
+        ("ß", "SS"),
+        ("Ä", "Ö"),
+        ("Ä", "Ö"),
+        ("I", "İ"),
+        ("I", "i"),
+        ("I", "ı"),
+        ("i", "I"),
+        ("i", "İ"),
+        ("i", "ı"),
+        ("İ", "I"),
+        ("İ", "i"),
+        ("İ", "ı"),
+        ("ı", "I"),
+        ("ı", "i"),
+        ("ı", "İ"),
+    ];
+    // Test that `cmd.env` matches `env::set_var` when setting two strings that
+    // may (or may not) be case-folded when compared.
+    for (a, b) in test_cases.iter() {
+        let mut cmd = Command::new("cmd");
+        cmd.env(a, "1");
+        cmd.env(b, "2");
+        env::set_var(a, "1");
+        env::set_var(b, "2");
+
+        for (key, value) in cmd.get_envs() {
+            assert_eq!(
+                env::var(key).ok(),
+                value.map(|s| s.to_string_lossy().into_owned()),
+                "command environment mismatch: {} {}",
+                a,
+                b
+            );
+        }
+    }
+}
index 38839ea5e90ed3a729d1830dbe19a5f8c3ebe830..ef7a9733fd880e19d8eff8383fa5fe7ae654e732 100644 (file)
@@ -1,5 +1,6 @@
 use crate::ffi::CStr;
 use crate::io;
+use crate::num::NonZeroUsize;
 use crate::ptr;
 use crate::sys::c;
 use crate::sys::handle::Handle;
@@ -98,6 +99,21 @@ impl Thread {
     }
 }
 
+pub fn available_concurrency() -> io::Result<NonZeroUsize> {
+    let res = unsafe {
+        let mut sysinfo: c::SYSTEM_INFO = crate::mem::zeroed();
+        c::GetSystemInfo(&mut sysinfo);
+        sysinfo.dwNumberOfProcessors as usize
+    };
+    match res {
+        0 => Err(io::Error::new_const(
+            io::ErrorKind::NotFound,
+            &"The number of hardware threads is not known for the target platform",
+        )),
+        cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus) }),
+    }
+}
+
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
     pub type Guard = !;
index 065365e5572f2be8f319b0eee0f8d7df558ec974..0bc511146654b790fbbd6807c29d7ba266e84aa9 100644 (file)
@@ -35,7 +35,7 @@ pub type Dtor = unsafe extern "C" fn(*mut u8);
 //
 // For more details and nitty-gritty, see the code sections below!
 //
-// [1]: http://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way
+// [1]: https://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way
 // [2]: https://github.com/ChromiumWebApps/chromium/blob/master/base
 //                        /threading/thread_local_storage_win.cc#L42
 
diff --git a/library/std/src/sys_common/bytestring.rs b/library/std/src/sys_common/bytestring.rs
deleted file mode 100644 (file)
index 97fba60..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#![allow(dead_code)]
-
-#[cfg(test)]
-mod tests;
-
-use crate::fmt::{Formatter, Result, Write};
-use core::str::lossy::{Utf8Lossy, Utf8LossyChunk};
-
-pub fn debug_fmt_bytestring(slice: &[u8], f: &mut Formatter<'_>) -> Result {
-    // Writes out a valid unicode string with the correct escape sequences
-    fn write_str_escaped(f: &mut Formatter<'_>, s: &str) -> Result {
-        for c in s.chars().flat_map(|c| c.escape_debug()) {
-            f.write_char(c)?
-        }
-        Ok(())
-    }
-
-    f.write_str("\"")?;
-    for Utf8LossyChunk { valid, broken } in Utf8Lossy::from_bytes(slice).chunks() {
-        write_str_escaped(f, valid)?;
-        for b in broken {
-            write!(f, "\\x{:02X}", b)?;
-        }
-    }
-    f.write_str("\"")
-}
diff --git a/library/std/src/sys_common/bytestring/tests.rs b/library/std/src/sys_common/bytestring/tests.rs
deleted file mode 100644 (file)
index 1685f08..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-use super::*;
-use crate::fmt::{Debug, Formatter, Result};
-
-#[test]
-fn smoke() {
-    struct Helper<'a>(&'a [u8]);
-
-    impl Debug for Helper<'_> {
-        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
-            debug_fmt_bytestring(self.0, f)
-        }
-    }
-
-    let input = b"\xF0hello,\tworld";
-    let expected = r#""\xF0hello,\tworld""#;
-    let output = format!("{:?}", Helper(input));
-
-    assert!(output == expected);
-}
index 1a9caa22c92434a4b6a8d415003bbccdaa310173..db83bad60d84ccc7da38e5af755dbb37ab076022 100644 (file)
@@ -21,7 +21,6 @@
 mod tests;
 
 pub mod backtrace;
-pub mod bytestring;
 pub mod condvar;
 pub mod fs;
 pub mod io;
index 32705c432fa8a2d5e6f1b518ecd8624b035d71f8..569600470db77a22126e835facb44f913d85c17b 100644 (file)
@@ -2,36 +2,45 @@
 //! systems: just a `Vec<u8>`/`[u8]`.
 
 use crate::borrow::Cow;
-use crate::ffi::{OsStr, OsString};
 use crate::fmt;
+use crate::fmt::Write;
 use crate::mem;
 use crate::rc::Rc;
-use crate::sealed::Sealed;
 use crate::str;
 use crate::sync::Arc;
-use crate::sys_common::bytestring::debug_fmt_bytestring;
-use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::sys_common::{AsInner, IntoInner};
 
-use core::str::lossy::Utf8Lossy;
+use core::str::lossy::{Utf8Lossy, Utf8LossyChunk};
+
+#[cfg(test)]
+mod tests;
 
 #[derive(Hash)]
-pub(crate) struct Buf {
+#[repr(transparent)]
+pub struct Buf {
     pub inner: Vec<u8>,
 }
 
-// FIXME:
-// `Buf::as_slice` current implementation relies
-// on `Slice` being layout-compatible with `[u8]`.
-// When attribute privacy is implemented, `Slice` should be annotated as `#[repr(transparent)]`.
-// Anyway, `Slice` representation and layout are considered implementation detail, are
-// not documented and must not be relied upon.
-pub(crate) struct Slice {
+#[repr(transparent)]
+pub struct Slice {
     pub inner: [u8],
 }
 
 impl fmt::Debug for Slice {
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        debug_fmt_bytestring(&self.inner, formatter)
+        // Writes out a valid unicode string with the correct escape sequences
+
+        formatter.write_str("\"")?;
+        for Utf8LossyChunk { valid, broken } in Utf8Lossy::from_bytes(&self.inner).chunks() {
+            for c in valid.chars().flat_map(|c| c.escape_debug()) {
+                formatter.write_char(c)?
+            }
+
+            for b in broken {
+                write!(formatter, "\\x{:02X}", b)?;
+            }
+        }
+        formatter.write_str("\"")
     }
 }
 
@@ -243,63 +252,3 @@ impl Slice {
         self.inner.eq_ignore_ascii_case(&other.inner)
     }
 }
-
-/// Platform-specific extensions to [`OsString`].
-///
-/// This trait is sealed: it cannot be implemented outside the standard library.
-/// This is so that future additional methods are not breaking changes.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait OsStringExt: Sealed {
-    /// Creates an [`OsString`] from a byte vector.
-    ///
-    /// See the module documentation for an example.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn from_vec(vec: Vec<u8>) -> Self;
-
-    /// Yields the underlying byte vector of this [`OsString`].
-    ///
-    /// See the module documentation for an example.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn into_vec(self) -> Vec<u8>;
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl OsStringExt for OsString {
-    fn from_vec(vec: Vec<u8>) -> OsString {
-        FromInner::from_inner(Buf { inner: vec })
-    }
-    fn into_vec(self) -> Vec<u8> {
-        self.into_inner().inner
-    }
-}
-
-/// Platform-specific extensions to [`OsStr`].
-///
-/// This trait is sealed: it cannot be implemented outside the standard library.
-/// This is so that future additional methods are not breaking changes.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait OsStrExt: Sealed {
-    #[stable(feature = "rust1", since = "1.0.0")]
-    /// Creates an [`OsStr`] from a byte slice.
-    ///
-    /// See the module documentation for an example.
-    fn from_bytes(slice: &[u8]) -> &Self;
-
-    /// Gets the underlying byte view of the [`OsStr`] slice.
-    ///
-    /// See the module documentation for an example.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn as_bytes(&self) -> &[u8];
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl OsStrExt for OsStr {
-    #[inline]
-    fn from_bytes(slice: &[u8]) -> &OsStr {
-        unsafe { mem::transmute(slice) }
-    }
-    #[inline]
-    fn as_bytes(&self) -> &[u8] {
-        &self.as_inner().inner
-    }
-}
diff --git a/library/std/src/sys_common/os_str_bytes/tests.rs b/library/std/src/sys_common/os_str_bytes/tests.rs
new file mode 100644 (file)
index 0000000..3796737
--- /dev/null
@@ -0,0 +1,10 @@
+use super::*;
+
+#[test]
+fn slice_debug_output() {
+    let input = Slice::from_u8_slice(b"\xF0hello,\tworld");
+    let expected = r#""\xF0hello,\tworld""#;
+    let output = format!("{:?}", input);
+
+    assert_eq!(output, expected);
+}
index fe89b11043c0ff879703925a2f4307030f157971..38007d5c414ecd42bd97456334005c4231756bd9 100644 (file)
@@ -65,16 +65,18 @@ impl CommandEnv {
 
     // The following functions build up changes
     pub fn set(&mut self, key: &OsStr, value: &OsStr) {
+        let key = EnvKey::from(key);
         self.maybe_saw_path(&key);
-        self.vars.insert(key.to_owned().into(), Some(value.to_owned()));
+        self.vars.insert(key, Some(value.to_owned()));
     }
 
     pub fn remove(&mut self, key: &OsStr) {
+        let key = EnvKey::from(key);
         self.maybe_saw_path(&key);
         if self.clear {
-            self.vars.remove(key);
+            self.vars.remove(&key);
         } else {
-            self.vars.insert(key.to_owned().into(), None);
+            self.vars.insert(key, None);
         }
     }
 
@@ -87,7 +89,7 @@ impl CommandEnv {
         self.saw_path || self.clear
     }
 
-    fn maybe_saw_path(&mut self, key: &OsStr) {
+    fn maybe_saw_path(&mut self, key: &EnvKey) {
         if !self.saw_path && key == "PATH" {
             self.saw_path = true;
         }
index 7d4b0d5283199012a23425cd3afd50d7591e0ba7..1bd3cfd2200ffb2935882acbe213c4d298aced38 100644 (file)
@@ -853,10 +853,11 @@ impl<'a> Iterator for EncodeWide<'a> {
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         let (low, high) = self.code_points.size_hint();
+        let ext = (self.extra != 0) as usize;
         // every code point gets either one u16 or two u16,
         // so this iterator is between 1 or 2 times as
         // long as the underlying iterator.
-        (low, high.and_then(|n| n.checked_mul(2)))
+        (low + ext, high.and_then(|n| n.checked_mul(2)).and_then(|n| n.checked_add(ext)))
     }
 }
 
index 385e01f92fa14388af2a3f874dd015b28d20c49b..1bafbaa69392222d97666bf7b0ff5973ea350543 100644 (file)
@@ -301,7 +301,7 @@ fn wtf8_slice() {
 #[test]
 #[should_panic]
 fn wtf8_slice_not_code_point_boundary() {
-    &Wtf8::from_str("aé 💩")[2..4];
+    let _ = &Wtf8::from_str("aé 💩")[2..4];
 }
 
 #[test]
@@ -312,7 +312,7 @@ fn wtf8_slice_from() {
 #[test]
 #[should_panic]
 fn wtf8_slice_from_not_code_point_boundary() {
-    &Wtf8::from_str("aé 💩")[2..];
+    let _ = &Wtf8::from_str("aé 💩")[2..];
 }
 
 #[test]
@@ -323,7 +323,7 @@ fn wtf8_slice_to() {
 #[test]
 #[should_panic]
 fn wtf8_slice_to_not_code_point_boundary() {
-    &Wtf8::from_str("aé 💩")[5..];
+    let _ = &Wtf8::from_str("aé 💩")[5..];
 }
 
 #[test]
@@ -395,3 +395,15 @@ fn wtf8_encode_wide() {
         vec![0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]
     );
 }
+
+#[test]
+fn wtf8_encode_wide_size_hint() {
+    let string = Wtf8Buf::from_str("\u{12345}");
+    let mut iter = string.encode_wide();
+    assert_eq!((1, Some(8)), iter.size_hint());
+    iter.next().unwrap();
+    assert_eq!((1, Some(1)), iter.size_hint());
+    iter.next().unwrap();
+    assert_eq!((0, Some(0)), iter.size_hint());
+    assert!(iter.next().is_none());
+}
diff --git a/library/std/src/thread/available_concurrency.rs b/library/std/src/thread/available_concurrency.rs
deleted file mode 100644 (file)
index e8cdde8..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-use crate::io;
-use crate::num::NonZeroUsize;
-
-/// Returns the number of hardware threads available to the program.
-///
-/// This value should be considered only a hint.
-///
-/// # Platform-specific behavior
-///
-/// If interpreted as the number of actual hardware threads, it may undercount on
-/// Windows systems with more than 64 hardware threads. If interpreted as the
-/// available concurrency for that process, it may overcount on Windows systems
-/// when limited by a process wide affinity mask or job object limitations, and
-/// it may overcount on Linux systems when limited by a process wide affinity
-/// mask or affected by cgroups limits.
-///
-/// # Errors
-///
-/// This function will return an error in the following situations, but is not
-/// limited to just these cases:
-///
-/// - If the number of hardware threads is not known for the target platform.
-/// - The process lacks permissions to view the number of hardware threads
-///   available.
-///
-/// # Examples
-///
-/// ```
-/// # #![allow(dead_code)]
-/// #![feature(available_concurrency)]
-/// use std::thread;
-///
-/// let count = thread::available_concurrency().map(|n| n.get()).unwrap_or(1);
-/// ```
-#[unstable(feature = "available_concurrency", issue = "74479")]
-pub fn available_concurrency() -> io::Result<NonZeroUsize> {
-    available_concurrency_internal()
-}
-
-cfg_if::cfg_if! {
-    if #[cfg(windows)] {
-        #[allow(nonstandard_style)]
-        fn available_concurrency_internal() -> io::Result<NonZeroUsize> {
-            #[repr(C)]
-            struct SYSTEM_INFO {
-                wProcessorArchitecture: u16,
-                wReserved: u16,
-                dwPageSize: u32,
-                lpMinimumApplicationAddress: *mut u8,
-                lpMaximumApplicationAddress: *mut u8,
-                dwActiveProcessorMask: *mut u8,
-                dwNumberOfProcessors: u32,
-                dwProcessorType: u32,
-                dwAllocationGranularity: u32,
-                wProcessorLevel: u16,
-                wProcessorRevision: u16,
-            }
-            extern "system" {
-                fn GetSystemInfo(info: *mut SYSTEM_INFO) -> i32;
-            }
-            let res = unsafe {
-                let mut sysinfo = crate::mem::zeroed();
-                GetSystemInfo(&mut sysinfo);
-                sysinfo.dwNumberOfProcessors as usize
-            };
-            match res {
-                0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")),
-                cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus) }),
-            }
-        }
-    } else if #[cfg(any(
-        target_os = "android",
-        target_os = "emscripten",
-        target_os = "fuchsia",
-        target_os = "ios",
-        target_os = "linux",
-        target_os = "macos",
-        target_os = "solaris",
-        target_os = "illumos",
-    ))] {
-        fn available_concurrency_internal() -> io::Result<NonZeroUsize> {
-            match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } {
-                -1 => Err(io::Error::last_os_error()),
-                0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")),
-                cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }),
-            }
-        }
-    } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] {
-        fn available_concurrency_internal() -> io::Result<NonZeroUsize> {
-            use crate::ptr;
-
-            let mut cpus: libc::c_uint = 0;
-            let mut cpus_size = crate::mem::size_of_val(&cpus);
-
-            unsafe {
-                cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
-            }
-
-            // Fallback approach in case of errors or no hardware threads.
-            if cpus < 1 {
-                let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
-                let res = unsafe {
-                    libc::sysctl(
-                        mib.as_mut_ptr(),
-                        2,
-                        &mut cpus as *mut _ as *mut _,
-                        &mut cpus_size as *mut _ as *mut _,
-                        ptr::null_mut(),
-                        0,
-                    )
-                };
-
-                // Handle errors if any.
-                if res == -1 {
-                    return Err(io::Error::last_os_error());
-                } else if cpus == 0 {
-                    return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform"));
-                }
-            }
-            Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) })
-        }
-    } else if #[cfg(target_os = "openbsd")] {
-        fn available_concurrency_internal() -> io::Result<NonZeroUsize> {
-            use crate::ptr;
-
-            let mut cpus: libc::c_uint = 0;
-            let mut cpus_size = crate::mem::size_of_val(&cpus);
-            let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
-
-            let res = unsafe {
-                libc::sysctl(
-                    mib.as_mut_ptr(),
-                    2,
-                    &mut cpus as *mut _ as *mut _,
-                    &mut cpus_size as *mut _ as *mut _,
-                    ptr::null_mut(),
-                    0,
-                )
-            };
-
-            // Handle errors if any.
-            if res == -1 {
-                return Err(io::Error::last_os_error());
-            } else if cpus == 0 {
-                return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform"));
-            }
-
-            Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) })
-        }
-    } else {
-        // FIXME: implement on vxWorks, Redox, HermitCore, Haiku, l4re
-        fn available_concurrency_internal() -> io::Result<NonZeroUsize> {
-            Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform"))
-        }
-    }
-}
index e62f4440b369c7ebec1f144aa459f2f48a92a9c4..c53290ec0c7d0c117df53b147f34b0796dc93959 100644 (file)
@@ -324,10 +324,9 @@ macro_rules! __thread_local_inner {
 
 /// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with).
 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
+#[non_exhaustive]
 #[derive(Clone, Copy, Eq, PartialEq)]
-pub struct AccessError {
-    _private: (),
-}
+pub struct AccessError;
 
 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
 impl fmt::Debug for AccessError {
@@ -396,7 +395,7 @@ impl<T: 'static> LocalKey<T> {
         F: FnOnce(&T) -> R,
     {
         unsafe {
-            let thread_local = (self.inner)().ok_or(AccessError { _private: () })?;
+            let thread_local = (self.inner)().ok_or(AccessError)?;
             Ok(f(thread_local))
         }
     }
index f33d6129619318e8774303d9b77b930de34093f5..1df1ca758c054d10516cce9c215dd08977036be3 100644 (file)
@@ -297,7 +297,7 @@ fn join_orders_after_tls_destructors() {
             .unwrap();
 
         loop {
-            match SYNC_STATE.compare_exchange_weak(
+            match SYNC_STATE.compare_exchange(
                 THREAD1_WAITING,
                 MAIN_THREAD_RENDEZVOUS,
                 Ordering::SeqCst,
index 30d8c2a1b6fa01eff5308567e268043647dd471c..9f7e6b95dfb90c0d496eb88ead3679226ed02379 100644 (file)
@@ -155,6 +155,7 @@ use crate::fmt;
 use crate::io;
 use crate::mem;
 use crate::num::NonZeroU64;
+use crate::num::NonZeroUsize;
 use crate::panic;
 use crate::panicking;
 use crate::str;
@@ -174,15 +175,9 @@ use crate::time::Duration;
 #[macro_use]
 mod local;
 
-#[unstable(feature = "available_concurrency", issue = "74479")]
-mod available_concurrency;
-
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::local::{AccessError, LocalKey};
 
-#[unstable(feature = "available_concurrency", issue = "74479")]
-pub use available_concurrency::available_concurrency;
-
 // The types used by the thread_local! macro to access TLS keys. Note that there
 // are two types, the "OS" type and the "fast" type. The OS thread local key
 // type is accessed via platform-specific API calls and is slow, while the fast
@@ -656,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.
-///
-/// 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.
+/// 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.
 ///
-/// Thus the pattern of `yield`ing after a failed poll is rather common when
-/// implementing low-level shared resources or synchronization primitives.
+/// 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.
 ///
-/// 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.
+/// 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.
 ///
-/// 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
 ///
@@ -1003,11 +999,12 @@ impl 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");
             }
 
@@ -1422,3 +1419,39 @@ fn _assert_sync_and_send() {
     _assert_both::<JoinHandle<()>>();
     _assert_both::<Thread>();
 }
+
+/// Returns the number of hardware threads available to the program.
+///
+/// This value should be considered only a hint.
+///
+/// # Platform-specific behavior
+///
+/// If interpreted as the number of actual hardware threads, it may undercount on
+/// Windows systems with more than 64 hardware threads. If interpreted as the
+/// available concurrency for that process, it may overcount on Windows systems
+/// when limited by a process wide affinity mask or job object limitations, and
+/// it may overcount on Linux systems when limited by a process wide affinity
+/// mask or affected by cgroups limits.
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not
+/// limited to just these cases:
+///
+/// - If the number of hardware threads is not known for the target platform.
+/// - The process lacks permissions to view the number of hardware threads
+///   available.
+///
+/// # Examples
+///
+/// ```
+/// # #![allow(dead_code)]
+/// #![feature(available_concurrency)]
+/// use std::thread;
+///
+/// let count = thread::available_concurrency().map(|n| n.get()).unwrap_or(1);
+/// ```
+#[unstable(feature = "available_concurrency", issue = "74479")]
+pub fn available_concurrency() -> io::Result<NonZeroUsize> {
+    imp::available_concurrency()
+}
index 899cf6841ee1f4300da07f31f40023b123ada175..003069b338ef2c777b5200f3cda7f9a565c7e4cd 100644 (file)
@@ -168,7 +168,7 @@ pub struct Instant(time::Instant);
 ///
 /// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time
 /// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode
-/// [gettimeofday]: http://man7.org/linux/man-pages/man2/gettimeofday.2.html
+/// [gettimeofday]: https://man7.org/linux/man-pages/man2/gettimeofday.2.html
 /// [clock_gettime (Realtime Clock)]: https://linux.die.net/man/3/clock_gettime
 /// [__wasi_clock_time_get (Realtime Clock)]: https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md#clock_time_get
 /// [GetSystemTimePreciseAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
index 278ddf9543352bcec54d98f689ea8e9510dbf359..37429d3db0b307c18e427ca00ab6032a52ca7700 100644 (file)
@@ -20,7 +20,7 @@ macro_rules! bt {
 /// Returns the bit in position `b` of the memory addressed by `p`.
 #[inline]
 #[cfg_attr(test, assert_instr(bt))]
-#[unstable(feature = "simd_x86_bittest", issue = "59414")]
+#[stable(feature = "simd_x86_bittest", since = "1.55.0")]
 pub unsafe fn _bittest(p: *const i32, b: i32) -> u8 {
     let r: u8;
     asm!(
@@ -37,7 +37,7 @@ pub unsafe fn _bittest(p: *const i32, b: i32) -> u8 {
 /// Returns the bit in position `b` of the memory addressed by `p`, then sets the bit to `1`.
 #[inline]
 #[cfg_attr(test, assert_instr(bts))]
-#[unstable(feature = "simd_x86_bittest", issue = "59414")]
+#[stable(feature = "simd_x86_bittest", since = "1.55.0")]
 pub unsafe fn _bittestandset(p: *mut i32, b: i32) -> u8 {
     let r: u8;
     asm!(
@@ -54,7 +54,7 @@ pub unsafe fn _bittestandset(p: *mut i32, b: i32) -> u8 {
 /// Returns the bit in position `b` of the memory addressed by `p`, then resets that bit to `0`.
 #[inline]
 #[cfg_attr(test, assert_instr(btr))]
-#[unstable(feature = "simd_x86_bittest", issue = "59414")]
+#[stable(feature = "simd_x86_bittest", since = "1.55.0")]
 pub unsafe fn _bittestandreset(p: *mut i32, b: i32) -> u8 {
     let r: u8;
     asm!(
@@ -71,7 +71,7 @@ pub unsafe fn _bittestandreset(p: *mut i32, b: i32) -> u8 {
 /// Returns the bit in position `b` of the memory addressed by `p`, then inverts that bit.
 #[inline]
 #[cfg_attr(test, assert_instr(btc))]
-#[unstable(feature = "simd_x86_bittest", issue = "59414")]
+#[stable(feature = "simd_x86_bittest", since = "1.55.0")]
 pub unsafe fn _bittestandcomplement(p: *mut i32, b: i32) -> u8 {
     let r: u8;
     asm!(
index 6e8579fa252db911ff625bf64c5aa8d599891d5a..f2aa45d8ea153c7ba9008e1c32b0d9256f8e7630 100644 (file)
@@ -20,7 +20,7 @@ macro_rules! bt {
 /// Returns the bit in position `b` of the memory addressed by `p`.
 #[inline]
 #[cfg_attr(test, assert_instr(bt))]
-#[unstable(feature = "simd_x86_bittest", issue = "59414")]
+#[stable(feature = "simd_x86_bittest", since = "1.55.0")]
 pub unsafe fn _bittest64(p: *const i64, b: i64) -> u8 {
     let r: u8;
     asm!(
@@ -37,7 +37,7 @@ pub unsafe fn _bittest64(p: *const i64, b: i64) -> u8 {
 /// Returns the bit in position `b` of the memory addressed by `p`, then sets the bit to `1`.
 #[inline]
 #[cfg_attr(test, assert_instr(bts))]
-#[unstable(feature = "simd_x86_bittest", issue = "59414")]
+#[stable(feature = "simd_x86_bittest", since = "1.55.0")]
 pub unsafe fn _bittestandset64(p: *mut i64, b: i64) -> u8 {
     let r: u8;
     asm!(
@@ -54,7 +54,7 @@ pub unsafe fn _bittestandset64(p: *mut i64, b: i64) -> u8 {
 /// Returns the bit in position `b` of the memory addressed by `p`, then resets that bit to `0`.
 #[inline]
 #[cfg_attr(test, assert_instr(btr))]
-#[unstable(feature = "simd_x86_bittest", issue = "59414")]
+#[stable(feature = "simd_x86_bittest", since = "1.55.0")]
 pub unsafe fn _bittestandreset64(p: *mut i64, b: i64) -> u8 {
     let r: u8;
     asm!(
@@ -71,7 +71,7 @@ pub unsafe fn _bittestandreset64(p: *mut i64, b: i64) -> u8 {
 /// Returns the bit in position `b` of the memory addressed by `p`, then inverts that bit.
 #[inline]
 #[cfg_attr(test, assert_instr(btc))]
-#[unstable(feature = "simd_x86_bittest", issue = "59414")]
+#[stable(feature = "simd_x86_bittest", since = "1.55.0")]
 pub unsafe fn _bittestandcomplement64(p: *mut i64, b: i64) -> u8 {
     let r: u8;
     asm!(
diff --git a/library/term/Cargo.toml b/library/term/Cargo.toml
deleted file mode 100644 (file)
index ddf85b5..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-name = "term"
-version = "0.0.0"
-edition = "2018"
-
-[dependencies]
-core = { path = "../core" }
-std = { path = "../std" }
diff --git a/library/term/src/lib.rs b/library/term/src/lib.rs
deleted file mode 100644 (file)
index 943b276..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-//! Terminal formatting library.
-//!
-//! This crate provides the `Terminal` trait, which abstracts over an [ANSI
-//! Terminal][ansi] to provide color printing, among other things. There are two
-//! implementations, the `TerminfoTerminal`, which uses control characters from
-//! a [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console
-//! API][win].
-//!
-//! # Examples
-//!
-//! ```no_run
-//! # #![feature(rustc_private)]
-//! extern crate term;
-//! use std::io::prelude::*;
-//!
-//! fn main() {
-//!     let mut t = term::stdout().unwrap();
-//!
-//!     t.fg(term::color::GREEN).unwrap();
-//!     write!(t, "hello, ").unwrap();
-//!
-//!     t.fg(term::color::RED).unwrap();
-//!     writeln!(t, "world!").unwrap();
-//!
-//!     assert!(t.reset().unwrap());
-//! }
-//! ```
-//!
-//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code
-//! [win]: https://docs.microsoft.com/en-us/windows/console/character-mode-applications
-//! [ti]: https://en.wikipedia.org/wiki/Terminfo
-
-#![doc(html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))))]
-#![deny(missing_docs)]
-#![cfg_attr(windows, feature(libc))]
-
-use std::io::prelude::*;
-use std::io::{self, Stderr, Stdout};
-
-pub use terminfo::TerminfoTerminal;
-#[cfg(windows)]
-pub use win::WinConsole;
-
-pub mod terminfo;
-
-#[cfg(windows)]
-mod win;
-
-/// Alias for stdout terminals.
-pub type StdoutTerminal = dyn Terminal<Output = Stdout> + Send;
-/// Alias for stderr terminals.
-pub type StderrTerminal = dyn Terminal<Output = Stderr> + Send;
-
-#[cfg(not(windows))]
-/// Returns a Terminal wrapping stdout, or None if a terminal couldn't be
-/// opened.
-pub fn stdout() -> Option<Box<StdoutTerminal>> {
-    TerminfoTerminal::new(io::stdout()).map(|t| Box::new(t) as Box<StdoutTerminal>)
-}
-
-#[cfg(windows)]
-/// Returns a Terminal wrapping stdout, or None if a terminal couldn't be
-/// opened.
-pub fn stdout() -> Option<Box<StdoutTerminal>> {
-    TerminfoTerminal::new(io::stdout())
-        .map(|t| Box::new(t) as Box<StdoutTerminal>)
-        .or_else(|| WinConsole::new(io::stdout()).ok().map(|t| Box::new(t) as Box<StdoutTerminal>))
-}
-
-#[cfg(not(windows))]
-/// Returns a Terminal wrapping stderr, or None if a terminal couldn't be
-/// opened.
-pub fn stderr() -> Option<Box<StderrTerminal>> {
-    TerminfoTerminal::new(io::stderr()).map(|t| Box::new(t) as Box<StderrTerminal>)
-}
-
-#[cfg(windows)]
-/// Returns a Terminal wrapping stderr, or None if a terminal couldn't be
-/// opened.
-pub fn stderr() -> Option<Box<StderrTerminal>> {
-    TerminfoTerminal::new(io::stderr())
-        .map(|t| Box::new(t) as Box<StderrTerminal>)
-        .or_else(|| WinConsole::new(io::stderr()).ok().map(|t| Box::new(t) as Box<StderrTerminal>))
-}
-
-/// Terminal color definitions
-#[allow(missing_docs)]
-pub mod color {
-    /// Number for a terminal color
-    pub type Color = u32;
-
-    pub const BLACK: Color = 0;
-    pub const RED: Color = 1;
-    pub const GREEN: Color = 2;
-    pub const YELLOW: Color = 3;
-    pub const BLUE: Color = 4;
-    pub const MAGENTA: Color = 5;
-    pub const CYAN: Color = 6;
-    pub const WHITE: Color = 7;
-
-    pub const BRIGHT_BLACK: Color = 8;
-    pub const BRIGHT_RED: Color = 9;
-    pub const BRIGHT_GREEN: Color = 10;
-    pub const BRIGHT_YELLOW: Color = 11;
-    pub const BRIGHT_BLUE: Color = 12;
-    pub const BRIGHT_MAGENTA: Color = 13;
-    pub const BRIGHT_CYAN: Color = 14;
-    pub const BRIGHT_WHITE: Color = 15;
-}
-
-/// Terminal attributes for use with term.attr().
-///
-/// Most attributes can only be turned on and must be turned off with term.reset().
-/// The ones that can be turned off explicitly take a boolean value.
-/// Color is also represented as an attribute for convenience.
-#[derive(Debug, PartialEq, Eq, Copy, Clone)]
-pub enum Attr {
-    /// Bold (or possibly bright) mode
-    Bold,
-    /// Dim mode, also called faint or half-bright. Often not supported
-    Dim,
-    /// Italics mode. Often not supported
-    Italic(bool),
-    /// Underline mode
-    Underline(bool),
-    /// Blink mode
-    Blink,
-    /// Standout mode. Often implemented as Reverse, sometimes coupled with Bold
-    Standout(bool),
-    /// Reverse mode, inverts the foreground and background colors
-    Reverse,
-    /// Secure mode, also called invis mode. Hides the printed text
-    Secure,
-    /// Convenience attribute to set the foreground color
-    ForegroundColor(color::Color),
-    /// Convenience attribute to set the background color
-    BackgroundColor(color::Color),
-}
-
-/// A terminal with similar capabilities to an ANSI Terminal
-/// (foreground/background colors etc).
-pub trait Terminal: Write {
-    /// The terminal's output writer type.
-    type Output: Write;
-
-    /// Sets the foreground color to the given color.
-    ///
-    /// If the color is a bright color, but the terminal only supports 8 colors,
-    /// the corresponding normal color will be used instead.
-    ///
-    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
-    /// if there was an I/O error.
-    fn fg(&mut self, color: color::Color) -> io::Result<bool>;
-
-    /// Sets the background color to the given color.
-    ///
-    /// If the color is a bright color, but the terminal only supports 8 colors,
-    /// the corresponding normal color will be used instead.
-    ///
-    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
-    /// if there was an I/O error.
-    fn bg(&mut self, color: color::Color) -> io::Result<bool>;
-
-    /// Sets the given terminal attribute, if supported. Returns `Ok(true)`
-    /// if the attribute was supported, `Ok(false)` otherwise, and `Err(e)` if
-    /// there was an I/O error.
-    fn attr(&mut self, attr: Attr) -> io::Result<bool>;
-
-    /// Returns `true` if the given terminal attribute is supported.
-    fn supports_attr(&self, attr: Attr) -> bool;
-
-    /// Resets all terminal attributes and colors to their defaults.
-    ///
-    /// Returns `Ok(true)` if the terminal was reset, `Ok(false)` otherwise, and `Err(e)` if there
-    /// was an I/O error.
-    ///
-    /// *Note: This does not flush.*
-    ///
-    /// That means the reset command may get buffered so, if you aren't planning on doing anything
-    /// else that might flush stdout's buffer (e.g., writing a line of text), you should flush after
-    /// calling reset.
-    fn reset(&mut self) -> io::Result<bool>;
-
-    /// Gets an immutable reference to the stream inside
-    fn get_ref(&self) -> &Self::Output;
-
-    /// Gets a mutable reference to the stream inside
-    fn get_mut(&mut self) -> &mut Self::Output;
-
-    /// Returns the contained stream, destroying the `Terminal`
-    fn into_inner(self) -> Self::Output
-    where
-        Self: Sized;
-}
diff --git a/library/term/src/terminfo/mod.rs b/library/term/src/terminfo/mod.rs
deleted file mode 100644 (file)
index fec59aa..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-//! Terminfo database interface.
-
-use std::collections::HashMap;
-use std::env;
-use std::error;
-use std::fmt;
-use std::fs::File;
-use std::io::{self, prelude::*, BufReader};
-use std::path::Path;
-
-use crate::color;
-use crate::Attr;
-use crate::Terminal;
-
-use parm::{expand, Param, Variables};
-use parser::compiled::{msys_terminfo, parse};
-use searcher::get_dbpath_for_term;
-
-/// A parsed terminfo database entry.
-#[derive(Debug)]
-pub struct TermInfo {
-    /// Names for the terminal
-    pub names: Vec<String>,
-    /// Map of capability name to boolean value
-    pub bools: HashMap<String, bool>,
-    /// Map of capability name to numeric value
-    pub numbers: HashMap<String, u32>,
-    /// Map of capability name to raw (unexpanded) string
-    pub strings: HashMap<String, Vec<u8>>,
-}
-
-/// A terminfo creation error.
-#[derive(Debug)]
-pub enum Error {
-    /// TermUnset Indicates that the environment doesn't include enough information to find
-    /// the terminfo entry.
-    TermUnset,
-    /// MalformedTerminfo indicates that parsing the terminfo entry failed.
-    MalformedTerminfo(String),
-    /// io::Error forwards any io::Errors encountered when finding or reading the terminfo entry.
-    IoError(io::Error),
-}
-
-impl error::Error for Error {
-    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
-        use Error::*;
-        match self {
-            IoError(e) => Some(e),
-            _ => None,
-        }
-    }
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use Error::*;
-        match *self {
-            TermUnset => Ok(()),
-            MalformedTerminfo(ref e) => e.fmt(f),
-            IoError(ref e) => e.fmt(f),
-        }
-    }
-}
-
-impl TermInfo {
-    /// Creates a TermInfo based on current environment.
-    pub fn from_env() -> Result<TermInfo, Error> {
-        let term = match env::var("TERM") {
-            Ok(name) => TermInfo::from_name(&name),
-            Err(..) => return Err(Error::TermUnset),
-        };
-
-        if term.is_err() && env::var("MSYSCON").map_or(false, |s| "mintty.exe" == s) {
-            // msys terminal
-            Ok(msys_terminfo())
-        } else {
-            term
-        }
-    }
-
-    /// Creates a TermInfo for the named terminal.
-    pub fn from_name(name: &str) -> Result<TermInfo, Error> {
-        get_dbpath_for_term(name)
-            .ok_or_else(|| {
-                Error::IoError(io::Error::new(io::ErrorKind::NotFound, "terminfo file not found"))
-            })
-            .and_then(|p| TermInfo::from_path(&(*p)))
-    }
-
-    /// Parse the given TermInfo.
-    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<TermInfo, Error> {
-        Self::_from_path(path.as_ref())
-    }
-    // Keep the metadata small
-    fn _from_path(path: &Path) -> Result<TermInfo, Error> {
-        let file = File::open(path).map_err(Error::IoError)?;
-        let mut reader = BufReader::new(file);
-        parse(&mut reader, false).map_err(Error::MalformedTerminfo)
-    }
-}
-
-pub mod searcher;
-
-/// TermInfo format parsing.
-pub mod parser {
-    //! ncurses-compatible compiled terminfo format parsing (term(5))
-    pub mod compiled;
-}
-pub mod parm;
-
-fn cap_for_attr(attr: Attr) -> &'static str {
-    match attr {
-        Attr::Bold => "bold",
-        Attr::Dim => "dim",
-        Attr::Italic(true) => "sitm",
-        Attr::Italic(false) => "ritm",
-        Attr::Underline(true) => "smul",
-        Attr::Underline(false) => "rmul",
-        Attr::Blink => "blink",
-        Attr::Standout(true) => "smso",
-        Attr::Standout(false) => "rmso",
-        Attr::Reverse => "rev",
-        Attr::Secure => "invis",
-        Attr::ForegroundColor(_) => "setaf",
-        Attr::BackgroundColor(_) => "setab",
-    }
-}
-
-/// A Terminal that knows how many colors it supports, with a reference to its
-/// parsed Terminfo database record.
-pub struct TerminfoTerminal<T> {
-    num_colors: u32,
-    out: T,
-    ti: TermInfo,
-}
-
-impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
-    type Output = T;
-    fn fg(&mut self, color: color::Color) -> io::Result<bool> {
-        let color = self.dim_if_necessary(color);
-        if self.num_colors > color {
-            return self.apply_cap("setaf", &[Param::Number(color as i32)]);
-        }
-        Ok(false)
-    }
-
-    fn bg(&mut self, color: color::Color) -> io::Result<bool> {
-        let color = self.dim_if_necessary(color);
-        if self.num_colors > color {
-            return self.apply_cap("setab", &[Param::Number(color as i32)]);
-        }
-        Ok(false)
-    }
-
-    fn attr(&mut self, attr: Attr) -> io::Result<bool> {
-        match attr {
-            Attr::ForegroundColor(c) => self.fg(c),
-            Attr::BackgroundColor(c) => self.bg(c),
-            _ => self.apply_cap(cap_for_attr(attr), &[]),
-        }
-    }
-
-    fn supports_attr(&self, attr: Attr) -> bool {
-        match attr {
-            Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => self.num_colors > 0,
-            _ => {
-                let cap = cap_for_attr(attr);
-                self.ti.strings.get(cap).is_some()
-            }
-        }
-    }
-
-    fn reset(&mut self) -> io::Result<bool> {
-        // are there any terminals that have color/attrs and not sgr0?
-        // Try falling back to sgr, then op
-        let cmd = match ["sgr0", "sgr", "op"].iter().find_map(|cap| self.ti.strings.get(*cap)) {
-            Some(op) => match expand(&op, &[], &mut Variables::new()) {
-                Ok(cmd) => cmd,
-                Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)),
-            },
-            None => return Ok(false),
-        };
-        self.out.write_all(&cmd).and(Ok(true))
-    }
-
-    fn get_ref(&self) -> &T {
-        &self.out
-    }
-
-    fn get_mut(&mut self) -> &mut T {
-        &mut self.out
-    }
-
-    fn into_inner(self) -> T
-    where
-        Self: Sized,
-    {
-        self.out
-    }
-}
-
-impl<T: Write + Send> TerminfoTerminal<T> {
-    /// Creates a new TerminfoTerminal with the given TermInfo and Write.
-    pub fn new_with_terminfo(out: T, terminfo: TermInfo) -> TerminfoTerminal<T> {
-        let nc = if terminfo.strings.contains_key("setaf") && terminfo.strings.contains_key("setab")
-        {
-            terminfo.numbers.get("colors").map_or(0, |&n| n)
-        } else {
-            0
-        };
-
-        TerminfoTerminal { out, ti: terminfo, num_colors: nc }
-    }
-
-    /// Creates a new TerminfoTerminal for the current environment with the given Write.
-    ///
-    /// Returns `None` when the terminfo cannot be found or parsed.
-    pub fn new(out: T) -> Option<TerminfoTerminal<T>> {
-        TermInfo::from_env().map(move |ti| TerminfoTerminal::new_with_terminfo(out, ti)).ok()
-    }
-
-    fn dim_if_necessary(&self, color: color::Color) -> color::Color {
-        if color >= self.num_colors && color >= 8 && color < 16 { color - 8 } else { color }
-    }
-
-    fn apply_cap(&mut self, cmd: &str, params: &[Param]) -> io::Result<bool> {
-        match self.ti.strings.get(cmd) {
-            Some(cmd) => match expand(&cmd, params, &mut Variables::new()) {
-                Ok(s) => self.out.write_all(&s).and(Ok(true)),
-                Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e)),
-            },
-            None => Ok(false),
-        }
-    }
-}
-
-impl<T: Write> Write for TerminfoTerminal<T> {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.out.write(buf)
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        self.out.flush()
-    }
-}
diff --git a/library/term/src/terminfo/parm.rs b/library/term/src/terminfo/parm.rs
deleted file mode 100644 (file)
index 2e4e917..0000000
+++ /dev/null
@@ -1,559 +0,0 @@
-//! Parameterized string expansion
-
-use self::Param::*;
-use self::States::*;
-
-use std::iter::repeat;
-
-#[cfg(test)]
-mod tests;
-
-#[derive(Clone, Copy, PartialEq)]
-enum States {
-    Nothing,
-    Percent,
-    SetVar,
-    GetVar,
-    PushParam,
-    CharConstant,
-    CharClose,
-    IntConstant(i32),
-    FormatPattern(Flags, FormatState),
-    SeekIfElse(usize),
-    SeekIfElsePercent(usize),
-    SeekIfEnd(usize),
-    SeekIfEndPercent(usize),
-}
-
-#[derive(Copy, PartialEq, Clone)]
-enum FormatState {
-    Flags,
-    Width,
-    Precision,
-}
-
-/// Types of parameters a capability can use
-#[allow(missing_docs)]
-#[derive(Clone)]
-pub enum Param {
-    Words(String),
-    Number(i32),
-}
-
-/// Container for static and dynamic variable arrays
-pub struct Variables {
-    /// Static variables A-Z
-    sta_va: [Param; 26],
-    /// Dynamic variables a-z
-    dyn_va: [Param; 26],
-}
-
-impl Variables {
-    /// Returns a new zero-initialized Variables
-    pub fn new() -> Variables {
-        Variables {
-            sta_va: [
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-            ],
-            dyn_va: [
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-                Number(0),
-            ],
-        }
-    }
-}
-
-/// Expand a parameterized capability
-///
-/// # Arguments
-/// * `cap`    - string to expand
-/// * `params` - vector of params for %p1 etc
-/// * `vars`   - Variables struct for %Pa etc
-///
-/// To be compatible with ncurses, `vars` should be the same between calls to `expand` for
-/// multiple capabilities for the same terminal.
-pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result<Vec<u8>, String> {
-    let mut state = Nothing;
-
-    // expanded cap will only rarely be larger than the cap itself
-    let mut output = Vec::with_capacity(cap.len());
-
-    let mut stack: Vec<Param> = Vec::new();
-
-    // Copy parameters into a local vector for mutability
-    let mut mparams = [
-        Number(0),
-        Number(0),
-        Number(0),
-        Number(0),
-        Number(0),
-        Number(0),
-        Number(0),
-        Number(0),
-        Number(0),
-    ];
-    for (dst, src) in mparams.iter_mut().zip(params.iter()) {
-        *dst = (*src).clone();
-    }
-
-    for &c in cap.iter() {
-        let cur = c as char;
-        let mut old_state = state;
-        match state {
-            Nothing => {
-                if cur == '%' {
-                    state = Percent;
-                } else {
-                    output.push(c);
-                }
-            }
-            Percent => {
-                match cur {
-                    '%' => {
-                        output.push(c);
-                        state = Nothing
-                    }
-                    'c' => {
-                        match stack.pop() {
-                            // if c is 0, use 0200 (128) for ncurses compatibility
-                            Some(Number(0)) => output.push(128u8),
-                            // Don't check bounds. ncurses just casts and truncates.
-                            Some(Number(c)) => output.push(c as u8),
-                            Some(_) => return Err("a non-char was used with %c".to_string()),
-                            None => return Err("stack is empty".to_string()),
-                        }
-                    }
-                    'p' => state = PushParam,
-                    'P' => state = SetVar,
-                    'g' => state = GetVar,
-                    '\'' => state = CharConstant,
-                    '{' => state = IntConstant(0),
-                    'l' => match stack.pop() {
-                        Some(Words(s)) => stack.push(Number(s.len() as i32)),
-                        Some(_) => return Err("a non-str was used with %l".to_string()),
-                        None => return Err("stack is empty".to_string()),
-                    },
-                    '+' | '-' | '/' | '*' | '^' | '&' | '|' | 'm' => {
-                        match (stack.pop(), stack.pop()) {
-                            (Some(Number(y)), Some(Number(x))) => stack.push(Number(match cur {
-                                '+' => x + y,
-                                '-' => x - y,
-                                '*' => x * y,
-                                '/' => x / y,
-                                '|' => x | y,
-                                '&' => x & y,
-                                '^' => x ^ y,
-                                'm' => x % y,
-                                _ => unreachable!("All cases handled"),
-                            })),
-                            (Some(_), Some(_)) => {
-                                return Err(format!("non-numbers on stack with {}", cur));
-                            }
-                            _ => return Err("stack is empty".to_string()),
-                        }
-                    }
-                    '=' | '>' | '<' | 'A' | 'O' => match (stack.pop(), stack.pop()) {
-                        (Some(Number(y)), Some(Number(x))) => stack.push(Number(
-                            if match cur {
-                                '=' => x == y,
-                                '<' => x < y,
-                                '>' => x > y,
-                                'A' => x > 0 && y > 0,
-                                'O' => x > 0 || y > 0,
-                                _ => unreachable!(),
-                            } {
-                                1
-                            } else {
-                                0
-                            },
-                        )),
-                        (Some(_), Some(_)) => {
-                            return Err(format!("non-numbers on stack with {}", cur));
-                        }
-                        _ => return Err("stack is empty".to_string()),
-                    },
-                    '!' | '~' => match stack.pop() {
-                        Some(Number(x)) => stack.push(Number(match cur {
-                            '!' if x > 0 => 0,
-                            '!' => 1,
-                            '~' => !x,
-                            _ => unreachable!(),
-                        })),
-                        Some(_) => return Err(format!("non-numbers on stack with {}", cur)),
-                        None => return Err("stack is empty".to_string()),
-                    },
-                    'i' => match (&mparams[0], &mparams[1]) {
-                        (&Number(x), &Number(y)) => {
-                            mparams[0] = Number(x + 1);
-                            mparams[1] = Number(y + 1);
-                        }
-                        _ => return Err("first two params not numbers with %i".to_string()),
-                    },
-
-                    // printf-style support for %doxXs
-                    'd' | 'o' | 'x' | 'X' | 's' => {
-                        if let Some(arg) = stack.pop() {
-                            let flags = Flags::new();
-                            let res = format(arg, FormatOp::from_char(cur), flags)?;
-                            output.extend(res.iter().cloned());
-                        } else {
-                            return Err("stack is empty".to_string());
-                        }
-                    }
-                    ':' | '#' | ' ' | '.' | '0'..='9' => {
-                        let mut flags = Flags::new();
-                        let mut fstate = FormatState::Flags;
-                        match cur {
-                            ':' => (),
-                            '#' => flags.alternate = true,
-                            ' ' => flags.space = true,
-                            '.' => fstate = FormatState::Precision,
-                            '0'..='9' => {
-                                flags.width = cur as usize - '0' as usize;
-                                fstate = FormatState::Width;
-                            }
-                            _ => unreachable!(),
-                        }
-                        state = FormatPattern(flags, fstate);
-                    }
-
-                    // conditionals
-                    '?' => (),
-                    't' => match stack.pop() {
-                        Some(Number(0)) => state = SeekIfElse(0),
-                        Some(Number(_)) => (),
-                        Some(_) => return Err("non-number on stack with conditional".to_string()),
-                        None => return Err("stack is empty".to_string()),
-                    },
-                    'e' => state = SeekIfEnd(0),
-                    ';' => (),
-                    _ => return Err(format!("unrecognized format option {}", cur)),
-                }
-            }
-            PushParam => {
-                // params are 1-indexed
-                stack.push(
-                    mparams[match cur.to_digit(10) {
-                        Some(d) => d as usize - 1,
-                        None => return Err("bad param number".to_string()),
-                    }]
-                    .clone(),
-                );
-            }
-            SetVar => {
-                if cur >= 'A' && cur <= 'Z' {
-                    if let Some(arg) = stack.pop() {
-                        let idx = (cur as u8) - b'A';
-                        vars.sta_va[idx as usize] = arg;
-                    } else {
-                        return Err("stack is empty".to_string());
-                    }
-                } else if cur >= 'a' && cur <= 'z' {
-                    if let Some(arg) = stack.pop() {
-                        let idx = (cur as u8) - b'a';
-                        vars.dyn_va[idx as usize] = arg;
-                    } else {
-                        return Err("stack is empty".to_string());
-                    }
-                } else {
-                    return Err("bad variable name in %P".to_string());
-                }
-            }
-            GetVar => {
-                if cur >= 'A' && cur <= 'Z' {
-                    let idx = (cur as u8) - b'A';
-                    stack.push(vars.sta_va[idx as usize].clone());
-                } else if cur >= 'a' && cur <= 'z' {
-                    let idx = (cur as u8) - b'a';
-                    stack.push(vars.dyn_va[idx as usize].clone());
-                } else {
-                    return Err("bad variable name in %g".to_string());
-                }
-            }
-            CharConstant => {
-                stack.push(Number(c as i32));
-                state = CharClose;
-            }
-            CharClose => {
-                if cur != '\'' {
-                    return Err("malformed character constant".to_string());
-                }
-            }
-            IntConstant(i) => {
-                if cur == '}' {
-                    stack.push(Number(i));
-                    state = Nothing;
-                } else if let Some(digit) = cur.to_digit(10) {
-                    match i.checked_mul(10).and_then(|i_ten| i_ten.checked_add(digit as i32)) {
-                        Some(i) => {
-                            state = IntConstant(i);
-                            old_state = Nothing;
-                        }
-                        None => return Err("int constant too large".to_string()),
-                    }
-                } else {
-                    return Err("bad int constant".to_string());
-                }
-            }
-            FormatPattern(ref mut flags, ref mut fstate) => {
-                old_state = Nothing;
-                match (*fstate, cur) {
-                    (_, 'd') | (_, 'o') | (_, 'x') | (_, 'X') | (_, 's') => {
-                        if let Some(arg) = stack.pop() {
-                            let res = format(arg, FormatOp::from_char(cur), *flags)?;
-                            output.extend(res.iter().cloned());
-                            // will cause state to go to Nothing
-                            old_state = FormatPattern(*flags, *fstate);
-                        } else {
-                            return Err("stack is empty".to_string());
-                        }
-                    }
-                    (FormatState::Flags, '#') => {
-                        flags.alternate = true;
-                    }
-                    (FormatState::Flags, '-') => {
-                        flags.left = true;
-                    }
-                    (FormatState::Flags, '+') => {
-                        flags.sign = true;
-                    }
-                    (FormatState::Flags, ' ') => {
-                        flags.space = true;
-                    }
-                    (FormatState::Flags, '0'..='9') => {
-                        flags.width = cur as usize - '0' as usize;
-                        *fstate = FormatState::Width;
-                    }
-                    (FormatState::Flags, '.') => {
-                        *fstate = FormatState::Precision;
-                    }
-                    (FormatState::Width, '0'..='9') => {
-                        let old = flags.width;
-                        flags.width = flags.width * 10 + (cur as usize - '0' as usize);
-                        if flags.width < old {
-                            return Err("format width overflow".to_string());
-                        }
-                    }
-                    (FormatState::Width, '.') => {
-                        *fstate = FormatState::Precision;
-                    }
-                    (FormatState::Precision, '0'..='9') => {
-                        let old = flags.precision;
-                        flags.precision = flags.precision * 10 + (cur as usize - '0' as usize);
-                        if flags.precision < old {
-                            return Err("format precision overflow".to_string());
-                        }
-                    }
-                    _ => return Err("invalid format specifier".to_string()),
-                }
-            }
-            SeekIfElse(level) => {
-                if cur == '%' {
-                    state = SeekIfElsePercent(level);
-                }
-                old_state = Nothing;
-            }
-            SeekIfElsePercent(level) => {
-                if cur == ';' {
-                    if level == 0 {
-                        state = Nothing;
-                    } else {
-                        state = SeekIfElse(level - 1);
-                    }
-                } else if cur == 'e' && level == 0 {
-                    state = Nothing;
-                } else if cur == '?' {
-                    state = SeekIfElse(level + 1);
-                } else {
-                    state = SeekIfElse(level);
-                }
-            }
-            SeekIfEnd(level) => {
-                if cur == '%' {
-                    state = SeekIfEndPercent(level);
-                }
-                old_state = Nothing;
-            }
-            SeekIfEndPercent(level) => {
-                if cur == ';' {
-                    if level == 0 {
-                        state = Nothing;
-                    } else {
-                        state = SeekIfEnd(level - 1);
-                    }
-                } else if cur == '?' {
-                    state = SeekIfEnd(level + 1);
-                } else {
-                    state = SeekIfEnd(level);
-                }
-            }
-        }
-        if state == old_state {
-            state = Nothing;
-        }
-    }
-    Ok(output)
-}
-
-#[derive(Copy, PartialEq, Clone)]
-struct Flags {
-    width: usize,
-    precision: usize,
-    alternate: bool,
-    left: bool,
-    sign: bool,
-    space: bool,
-}
-
-impl Flags {
-    fn new() -> Flags {
-        Flags { width: 0, precision: 0, alternate: false, left: false, sign: false, space: false }
-    }
-}
-
-#[derive(Copy, Clone)]
-enum FormatOp {
-    Digit,
-    Octal,
-    LowerHex,
-    UpperHex,
-    String,
-}
-
-impl FormatOp {
-    fn from_char(c: char) -> FormatOp {
-        match c {
-            'd' => FormatOp::Digit,
-            'o' => FormatOp::Octal,
-            'x' => FormatOp::LowerHex,
-            'X' => FormatOp::UpperHex,
-            's' => FormatOp::String,
-            _ => panic!("bad FormatOp char"),
-        }
-    }
-    fn to_char(self) -> char {
-        match self {
-            FormatOp::Digit => 'd',
-            FormatOp::Octal => 'o',
-            FormatOp::LowerHex => 'x',
-            FormatOp::UpperHex => 'X',
-            FormatOp::String => 's',
-        }
-    }
-}
-
-fn format(val: Param, op: FormatOp, flags: Flags) -> Result<Vec<u8>, String> {
-    let mut s = match val {
-        Number(d) => {
-            match op {
-                FormatOp::Digit => {
-                    if flags.sign {
-                        format!("{:+01$}", d, flags.precision)
-                    } else if d < 0 {
-                        // C doesn't take sign into account in precision calculation.
-                        format!("{:01$}", d, flags.precision + 1)
-                    } else if flags.space {
-                        format!(" {:01$}", d, flags.precision)
-                    } else {
-                        format!("{:01$}", d, flags.precision)
-                    }
-                }
-                FormatOp::Octal => {
-                    if flags.alternate {
-                        // Leading octal zero counts against precision.
-                        format!("0{:01$o}", d, flags.precision.saturating_sub(1))
-                    } else {
-                        format!("{:01$o}", d, flags.precision)
-                    }
-                }
-                FormatOp::LowerHex => {
-                    if flags.alternate && d != 0 {
-                        format!("0x{:01$x}", d, flags.precision)
-                    } else {
-                        format!("{:01$x}", d, flags.precision)
-                    }
-                }
-                FormatOp::UpperHex => {
-                    if flags.alternate && d != 0 {
-                        format!("0X{:01$X}", d, flags.precision)
-                    } else {
-                        format!("{:01$X}", d, flags.precision)
-                    }
-                }
-                FormatOp::String => return Err("non-number on stack with %s".to_string()),
-            }
-            .into_bytes()
-        }
-        Words(s) => match op {
-            FormatOp::String => {
-                let mut s = s.into_bytes();
-                if flags.precision > 0 && flags.precision < s.len() {
-                    s.truncate(flags.precision);
-                }
-                s
-            }
-            _ => return Err(format!("non-string on stack with %{}", op.to_char())),
-        },
-    };
-    if flags.width > s.len() {
-        let n = flags.width - s.len();
-        if flags.left {
-            s.extend(repeat(b' ').take(n));
-        } else {
-            let mut s_ = Vec::with_capacity(flags.width);
-            s_.extend(repeat(b' ').take(n));
-            s_.extend(s.into_iter());
-            s = s_;
-        }
-    }
-    Ok(s)
-}
diff --git a/library/term/src/terminfo/parm/tests.rs b/library/term/src/terminfo/parm/tests.rs
deleted file mode 100644 (file)
index 1cc0967..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-use super::*;
-
-use std::result::Result::Ok;
-
-#[test]
-fn test_basic_setabf() {
-    let s = b"\\E[48;5;%p1%dm";
-    assert_eq!(
-        expand(s, &[Number(1)], &mut Variables::new()).unwrap(),
-        "\\E[48;5;1m".bytes().collect::<Vec<_>>()
-    );
-}
-
-#[test]
-fn test_multiple_int_constants() {
-    assert_eq!(
-        expand(b"%{1}%{2}%d%d", &[], &mut Variables::new()).unwrap(),
-        "21".bytes().collect::<Vec<_>>()
-    );
-}
-
-#[test]
-fn test_op_i() {
-    let mut vars = Variables::new();
-    assert_eq!(
-        expand(b"%p1%d%p2%d%p3%d%i%p1%d%p2%d%p3%d", &[Number(1), Number(2), Number(3)], &mut vars),
-        Ok("123233".bytes().collect::<Vec<_>>())
-    );
-    assert_eq!(
-        expand(b"%p1%d%p2%d%i%p1%d%p2%d", &[], &mut vars),
-        Ok("0011".bytes().collect::<Vec<_>>())
-    );
-}
-
-#[test]
-fn test_param_stack_failure_conditions() {
-    let mut varstruct = Variables::new();
-    let vars = &mut varstruct;
-    fn get_res(
-        fmt: &str,
-        cap: &str,
-        params: &[Param],
-        vars: &mut Variables,
-    ) -> Result<Vec<u8>, String> {
-        let mut u8v: Vec<_> = fmt.bytes().collect();
-        u8v.extend(cap.as_bytes().iter().map(|&b| b));
-        expand(&u8v, params, vars)
-    }
-
-    let caps = ["%d", "%c", "%s", "%Pa", "%l", "%!", "%~"];
-    for &cap in caps.iter() {
-        let res = get_res("", cap, &[], vars);
-        assert!(res.is_err(), "Op {} succeeded incorrectly with 0 stack entries", cap);
-        let p = if cap == "%s" || cap == "%l" { Words("foo".to_string()) } else { Number(97) };
-        let res = get_res("%p1", cap, &[p], vars);
-        assert!(res.is_ok(), "Op {} failed with 1 stack entry: {}", cap, res.unwrap_err());
-    }
-    let caps = ["%+", "%-", "%*", "%/", "%m", "%&", "%|", "%A", "%O"];
-    for &cap in caps.iter() {
-        let res = expand(cap.as_bytes(), &[], vars);
-        assert!(res.is_err(), "Binop {} succeeded incorrectly with 0 stack entries", cap);
-        let res = get_res("%{1}", cap, &[], vars);
-        assert!(res.is_err(), "Binop {} succeeded incorrectly with 1 stack entry", cap);
-        let res = get_res("%{1}%{2}", cap, &[], vars);
-        assert!(res.is_ok(), "Binop {} failed with 2 stack entries: {}", cap, res.unwrap_err());
-    }
-}
-
-#[test]
-fn test_push_bad_param() {
-    assert!(expand(b"%pa", &[], &mut Variables::new()).is_err());
-}
-
-#[test]
-fn test_comparison_ops() {
-    let v = [('<', [1u8, 0u8, 0u8]), ('=', [0u8, 1u8, 0u8]), ('>', [0u8, 0u8, 1u8])];
-    for &(op, bs) in v.iter() {
-        let s = format!("%{{1}}%{{2}}%{}%d", op);
-        let res = expand(s.as_bytes(), &[], &mut Variables::new());
-        assert!(res.is_ok(), "{}", res.unwrap_err());
-        assert_eq!(res.unwrap(), vec![b'0' + bs[0]]);
-        let s = format!("%{{1}}%{{1}}%{}%d", op);
-        let res = expand(s.as_bytes(), &[], &mut Variables::new());
-        assert!(res.is_ok(), "{}", res.unwrap_err());
-        assert_eq!(res.unwrap(), vec![b'0' + bs[1]]);
-        let s = format!("%{{2}}%{{1}}%{}%d", op);
-        let res = expand(s.as_bytes(), &[], &mut Variables::new());
-        assert!(res.is_ok(), "{}", res.unwrap_err());
-        assert_eq!(res.unwrap(), vec![b'0' + bs[2]]);
-    }
-}
-
-#[test]
-fn test_conditionals() {
-    let mut vars = Variables::new();
-    let s = b"\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m";
-    let res = expand(s, &[Number(1)], &mut vars);
-    assert!(res.is_ok(), "{}", res.unwrap_err());
-    assert_eq!(res.unwrap(), "\\E[31m".bytes().collect::<Vec<_>>());
-    let res = expand(s, &[Number(8)], &mut vars);
-    assert!(res.is_ok(), "{}", res.unwrap_err());
-    assert_eq!(res.unwrap(), "\\E[90m".bytes().collect::<Vec<_>>());
-    let res = expand(s, &[Number(42)], &mut vars);
-    assert!(res.is_ok(), "{}", res.unwrap_err());
-    assert_eq!(res.unwrap(), "\\E[38;5;42m".bytes().collect::<Vec<_>>());
-}
-
-#[test]
-fn test_format() {
-    let mut varstruct = Variables::new();
-    let vars = &mut varstruct;
-    assert_eq!(
-        expand(
-            b"%p1%s%p2%2s%p3%2s%p4%.2s",
-            &[
-                Words("foo".to_string()),
-                Words("foo".to_string()),
-                Words("f".to_string()),
-                Words("foo".to_string())
-            ],
-            vars
-        ),
-        Ok("foofoo ffo".bytes().collect::<Vec<_>>())
-    );
-    assert_eq!(
-        expand(b"%p1%:-4.2s", &[Words("foo".to_string())], vars),
-        Ok("fo  ".bytes().collect::<Vec<_>>())
-    );
-
-    assert_eq!(
-        expand(b"%p1%d%p1%.3d%p1%5d%p1%:+d", &[Number(1)], vars),
-        Ok("1001    1+1".bytes().collect::<Vec<_>>())
-    );
-    assert_eq!(
-        expand(b"%p1%o%p1%#o%p2%6.4x%p2%#6.4X", &[Number(15), Number(27)], vars),
-        Ok("17017  001b0X001B".bytes().collect::<Vec<_>>())
-    );
-}
diff --git a/library/term/src/terminfo/parser/compiled.rs b/library/term/src/terminfo/parser/compiled.rs
deleted file mode 100644 (file)
index fbc5aeb..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-#![allow(non_upper_case_globals, missing_docs)]
-
-//! ncurses-compatible compiled terminfo format parsing (term(5))
-
-use super::super::TermInfo;
-use std::collections::HashMap;
-use std::io;
-use std::io::prelude::*;
-
-#[cfg(test)]
-mod tests;
-
-// These are the orders ncurses uses in its compiled format (as of 5.9). Not sure if portable.
-
-#[rustfmt::skip]
-pub static boolfnames: &[&str] = &["auto_left_margin", "auto_right_margin",
-    "no_esc_ctlc", "ceol_standout_glitch", "eat_newline_glitch", "erase_overstrike", "generic_type",
-    "hard_copy", "has_meta_key", "has_status_line", "insert_null_glitch", "memory_above",
-    "memory_below", "move_insert_mode", "move_standout_mode", "over_strike", "status_line_esc_ok",
-    "dest_tabs_magic_smso", "tilde_glitch", "transparent_underline", "xon_xoff", "needs_xon_xoff",
-    "prtr_silent", "hard_cursor", "non_rev_rmcup", "no_pad_char", "non_dest_scroll_region",
-    "can_change", "back_color_erase", "hue_lightness_saturation", "col_addr_glitch",
-    "cr_cancels_micro_mode", "has_print_wheel", "row_addr_glitch", "semi_auto_right_margin",
-    "cpi_changes_res", "lpi_changes_res", "backspaces_with_bs", "crt_no_scrolling",
-    "no_correctly_working_cr", "gnu_has_meta_key", "linefeed_is_newline", "has_hardware_tabs",
-    "return_does_clr_eol"];
-
-#[rustfmt::skip]
-pub static boolnames: &[&str] = &["bw", "am", "xsb", "xhp", "xenl", "eo",
-    "gn", "hc", "km", "hs", "in", "db", "da", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon",
-    "nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy",
-    "xvpa", "sam", "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"];
-
-#[rustfmt::skip]
-pub static numfnames: &[&str] = &[ "columns", "init_tabs", "lines",
-    "lines_of_memory", "magic_cookie_glitch", "padding_baud_rate", "virtual_terminal",
-    "width_status_line", "num_labels", "label_height", "label_width", "max_attributes",
-    "maximum_windows", "max_colors", "max_pairs", "no_color_video", "buffer_capacity",
-    "dot_vert_spacing", "dot_horz_spacing", "max_micro_address", "max_micro_jump", "micro_col_size",
-    "micro_line_size", "number_of_pins", "output_res_char", "output_res_line",
-    "output_res_horz_inch", "output_res_vert_inch", "print_rate", "wide_char_size", "buttons",
-    "bit_image_entwining", "bit_image_type", "magic_cookie_glitch_ul", "carriage_return_delay",
-    "new_line_delay", "backspace_delay", "horizontal_tab_delay", "number_of_function_keys"];
-
-#[rustfmt::skip]
-pub static numnames: &[&str] = &[ "cols", "it", "lines", "lm", "xmc", "pb",
-    "vt", "wsl", "nlab", "lh", "lw", "ma", "wnum", "colors", "pairs", "ncv", "bufsz", "spinv",
-    "spinh", "maddr", "mjump", "mcs", "mls", "npins", "orc", "orl", "orhi", "orvi", "cps", "widcs",
-    "btns", "bitwin", "bitype", "UTug", "OTdC", "OTdN", "OTdB", "OTdT", "OTkn"];
-
-#[rustfmt::skip]
-pub static stringfnames: &[&str] = &[ "back_tab", "bell", "carriage_return",
-    "change_scroll_region", "clear_all_tabs", "clear_screen", "clr_eol", "clr_eos",
-    "column_address", "command_character", "cursor_address", "cursor_down", "cursor_home",
-    "cursor_invisible", "cursor_left", "cursor_mem_address", "cursor_normal", "cursor_right",
-    "cursor_to_ll", "cursor_up", "cursor_visible", "delete_character", "delete_line",
-    "dis_status_line", "down_half_line", "enter_alt_charset_mode", "enter_blink_mode",
-    "enter_bold_mode", "enter_ca_mode", "enter_delete_mode", "enter_dim_mode", "enter_insert_mode",
-    "enter_secure_mode", "enter_protected_mode", "enter_reverse_mode", "enter_standout_mode",
-    "enter_underline_mode", "erase_chars", "exit_alt_charset_mode", "exit_attribute_mode",
-    "exit_ca_mode", "exit_delete_mode", "exit_insert_mode", "exit_standout_mode",
-    "exit_underline_mode", "flash_screen", "form_feed", "from_status_line", "init_1string",
-    "init_2string", "init_3string", "init_file", "insert_character", "insert_line",
-    "insert_padding", "key_backspace", "key_catab", "key_clear", "key_ctab", "key_dc", "key_dl",
-    "key_down", "key_eic", "key_eol", "key_eos", "key_f0", "key_f1", "key_f10", "key_f2", "key_f3",
-    "key_f4", "key_f5", "key_f6", "key_f7", "key_f8", "key_f9", "key_home", "key_ic", "key_il",
-    "key_left", "key_ll", "key_npage", "key_ppage", "key_right", "key_sf", "key_sr", "key_stab",
-    "key_up", "keypad_local", "keypad_xmit", "lab_f0", "lab_f1", "lab_f10", "lab_f2", "lab_f3",
-    "lab_f4", "lab_f5", "lab_f6", "lab_f7", "lab_f8", "lab_f9", "meta_off", "meta_on", "newline",
-    "pad_char", "parm_dch", "parm_delete_line", "parm_down_cursor", "parm_ich", "parm_index",
-    "parm_insert_line", "parm_left_cursor", "parm_right_cursor", "parm_rindex", "parm_up_cursor",
-    "pkey_key", "pkey_local", "pkey_xmit", "print_screen", "prtr_off", "prtr_on", "repeat_char",
-    "reset_1string", "reset_2string", "reset_3string", "reset_file", "restore_cursor",
-    "row_address", "save_cursor", "scroll_forward", "scroll_reverse", "set_attributes", "set_tab",
-    "set_window", "tab", "to_status_line", "underline_char", "up_half_line", "init_prog", "key_a1",
-    "key_a3", "key_b2", "key_c1", "key_c3", "prtr_non", "char_padding", "acs_chars", "plab_norm",
-    "key_btab", "enter_xon_mode", "exit_xon_mode", "enter_am_mode", "exit_am_mode", "xon_character",
-    "xoff_character", "ena_acs", "label_on", "label_off", "key_beg", "key_cancel", "key_close",
-    "key_command", "key_copy", "key_create", "key_end", "key_enter", "key_exit", "key_find",
-    "key_help", "key_mark", "key_message", "key_move", "key_next", "key_open", "key_options",
-    "key_previous", "key_print", "key_redo", "key_reference", "key_refresh", "key_replace",
-    "key_restart", "key_resume", "key_save", "key_suspend", "key_undo", "key_sbeg", "key_scancel",
-    "key_scommand", "key_scopy", "key_screate", "key_sdc", "key_sdl", "key_select", "key_send",
-    "key_seol", "key_sexit", "key_sfind", "key_shelp", "key_shome", "key_sic", "key_sleft",
-    "key_smessage", "key_smove", "key_snext", "key_soptions", "key_sprevious", "key_sprint",
-    "key_sredo", "key_sreplace", "key_sright", "key_srsume", "key_ssave", "key_ssuspend",
-    "key_sundo", "req_for_input", "key_f11", "key_f12", "key_f13", "key_f14", "key_f15", "key_f16",
-    "key_f17", "key_f18", "key_f19", "key_f20", "key_f21", "key_f22", "key_f23", "key_f24",
-    "key_f25", "key_f26", "key_f27", "key_f28", "key_f29", "key_f30", "key_f31", "key_f32",
-    "key_f33", "key_f34", "key_f35", "key_f36", "key_f37", "key_f38", "key_f39", "key_f40",
-    "key_f41", "key_f42", "key_f43", "key_f44", "key_f45", "key_f46", "key_f47", "key_f48",
-    "key_f49", "key_f50", "key_f51", "key_f52", "key_f53", "key_f54", "key_f55", "key_f56",
-    "key_f57", "key_f58", "key_f59", "key_f60", "key_f61", "key_f62", "key_f63", "clr_bol",
-    "clear_margins", "set_left_margin", "set_right_margin", "label_format", "set_clock",
-    "display_clock", "remove_clock", "create_window", "goto_window", "hangup", "dial_phone",
-    "quick_dial", "tone", "pulse", "flash_hook", "fixed_pause", "wait_tone", "user0", "user1",
-    "user2", "user3", "user4", "user5", "user6", "user7", "user8", "user9", "orig_pair",
-    "orig_colors", "initialize_color", "initialize_pair", "set_color_pair", "set_foreground",
-    "set_background", "change_char_pitch", "change_line_pitch", "change_res_horz",
-    "change_res_vert", "define_char", "enter_doublewide_mode", "enter_draft_quality",
-    "enter_italics_mode", "enter_leftward_mode", "enter_micro_mode", "enter_near_letter_quality",
-    "enter_normal_quality", "enter_shadow_mode", "enter_subscript_mode", "enter_superscript_mode",
-    "enter_upward_mode", "exit_doublewide_mode", "exit_italics_mode", "exit_leftward_mode",
-    "exit_micro_mode", "exit_shadow_mode", "exit_subscript_mode", "exit_superscript_mode",
-    "exit_upward_mode", "micro_column_address", "micro_down", "micro_left", "micro_right",
-    "micro_row_address", "micro_up", "order_of_pins", "parm_down_micro", "parm_left_micro",
-    "parm_right_micro", "parm_up_micro", "select_char_set", "set_bottom_margin",
-    "set_bottom_margin_parm", "set_left_margin_parm", "set_right_margin_parm", "set_top_margin",
-    "set_top_margin_parm", "start_bit_image", "start_char_set_def", "stop_bit_image",
-    "stop_char_set_def", "subscript_characters", "superscript_characters", "these_cause_cr",
-    "zero_motion", "char_set_names", "key_mouse", "mouse_info", "req_mouse_pos", "get_mouse",
-    "set_a_foreground", "set_a_background", "pkey_plab", "device_type", "code_set_init",
-    "set0_des_seq", "set1_des_seq", "set2_des_seq", "set3_des_seq", "set_lr_margin",
-    "set_tb_margin", "bit_image_repeat", "bit_image_newline", "bit_image_carriage_return",
-    "color_names", "define_bit_image_region", "end_bit_image_region", "set_color_band",
-    "set_page_length", "display_pc_char", "enter_pc_charset_mode", "exit_pc_charset_mode",
-    "enter_scancode_mode", "exit_scancode_mode", "pc_term_options", "scancode_escape",
-    "alt_scancode_esc", "enter_horizontal_hl_mode", "enter_left_hl_mode", "enter_low_hl_mode",
-    "enter_right_hl_mode", "enter_top_hl_mode", "enter_vertical_hl_mode", "set_a_attributes",
-    "set_pglen_inch", "termcap_init2", "termcap_reset", "linefeed_if_not_lf", "backspace_if_not_bs",
-    "other_non_function_keys", "arrow_key_map", "acs_ulcorner", "acs_llcorner", "acs_urcorner",
-    "acs_lrcorner", "acs_ltee", "acs_rtee", "acs_btee", "acs_ttee", "acs_hline", "acs_vline",
-    "acs_plus", "memory_lock", "memory_unlock", "box_chars_1"];
-
-#[rustfmt::skip]
-pub static stringnames: &[&str] = &[ "cbt", "_", "cr", "csr", "tbc", "clear",
-    "_", "_", "hpa", "cmdch", "cup", "cud1", "home", "civis", "cub1", "mrcup", "cnorm", "cuf1",
-    "ll", "cuu1", "cvvis", "dch1", "dl1", "dsl", "hd", "smacs", "blink", "bold", "smcup", "smdc",
-    "dim", "smir", "invis", "prot", "rev", "smso", "smul", "ech", "rmacs", "sgr0", "rmcup", "rmdc",
-    "rmir", "rmso", "rmul", "flash", "ff", "fsl", "is1", "is2", "is3", "if", "ich1", "il1", "ip",
-    "kbs", "ktbc", "kclr", "kctab", "_", "_", "kcud1", "_", "_", "_", "_", "_", "_", "_", "_", "_",
-    "_", "_", "_", "_", "_", "khome", "_", "_", "kcub1", "_", "knp", "kpp", "kcuf1", "_", "_",
-    "khts", "_", "rmkx", "smkx", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "rmm", "_",
-    "_", "pad", "dch", "dl", "cud", "ich", "indn", "il", "cub", "cuf", "rin", "cuu", "pfkey",
-    "pfloc", "pfx", "mc0", "mc4", "_", "rep", "rs1", "rs2", "rs3", "rf", "rc", "vpa", "sc", "ind",
-    "ri", "sgr", "_", "wind", "_", "tsl", "uc", "hu", "iprog", "_", "_", "_", "_", "_", "mc5p",
-    "rmp", "acsc", "pln", "kcbt", "smxon", "rmxon", "smam", "rmam", "xonc", "xoffc", "_", "smln",
-    "rmln", "_", "kcan", "kclo", "kcmd", "kcpy", "kcrt", "_", "kent", "kext", "kfnd", "khlp",
-    "kmrk", "kmsg", "kmov", "knxt", "kopn", "kopt", "kprv", "kprt", "krdo", "kref", "krfr", "krpl",
-    "krst", "kres", "ksav", "kspd", "kund", "kBEG", "kCAN", "kCMD", "kCPY", "kCRT", "_", "_",
-    "kslt", "kEND", "kEOL", "kEXT", "kFND", "kHLP", "kHOM", "_", "kLFT", "kMSG", "kMOV", "kNXT",
-    "kOPT", "kPRV", "kPRT", "kRDO", "kRPL", "kRIT", "kRES", "kSAV", "kSPD", "kUND", "rfi", "_", "_",
-    "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_",
-    "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_",
-    "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_",
-    "dclk", "rmclk", "cwin", "wingo", "_", "dial", "qdial", "_", "_", "hook", "pause", "wait", "_",
-    "_", "_", "_", "_", "_", "_", "_", "_", "_", "op", "oc", "initc", "initp", "scp", "setf",
-    "setb", "cpi", "lpi", "chr", "cvr", "defc", "swidm", "sdrfq", "sitm", "slm", "smicm", "snlq",
-    "snrmq", "sshm", "ssubm", "ssupm", "sum", "rwidm", "ritm", "rlm", "rmicm", "rshm", "rsubm",
-    "rsupm", "rum", "mhpa", "mcud1", "mcub1", "mcuf1", "mvpa", "mcuu1", "porder", "mcud", "mcub",
-    "mcuf", "mcuu", "scs", "smgb", "smgbp", "smglp", "smgrp", "smgt", "smgtp", "sbim", "scsd",
-    "rbim", "rcsd", "subcs", "supcs", "docr", "zerom", "csnm", "kmous", "minfo", "reqmp", "getm",
-    "setaf", "setab", "pfxl", "devt", "csin", "s0ds", "s1ds", "s2ds", "s3ds", "smglr", "smgtb",
-    "birep", "binel", "bicr", "colornm", "defbi", "endbi", "setcolor", "slines", "dispc", "smpch",
-    "rmpch", "smsc", "rmsc", "pctrm", "scesc", "scesa", "ehhlm", "elhlm", "elohlm", "erhlm",
-    "ethlm", "evhlm", "sgr1", "slength", "OTi2", "OTrs", "OTnl", "OTbs", "OTko", "OTma", "OTG2",
-    "OTG3", "OTG1", "OTG4", "OTGR", "OTGL", "OTGU", "OTGD", "OTGH", "OTGV", "OTGC", "meml", "memu",
-    "box1"];
-
-fn read_le_u16(r: &mut dyn io::Read) -> io::Result<u16> {
-    let mut b = [0; 2];
-    r.read_exact(&mut b)?;
-    Ok((b[0] as u16) | ((b[1] as u16) << 8))
-}
-
-fn read_le_u32(r: &mut dyn io::Read) -> io::Result<u32> {
-    let mut b = [0; 4];
-    r.read_exact(&mut b)?;
-    Ok((b[0] as u32) | ((b[1] as u32) << 8) | ((b[2] as u32) << 16) | ((b[3] as u32) << 24))
-}
-
-fn read_byte(r: &mut dyn io::Read) -> io::Result<u8> {
-    match r.bytes().next() {
-        Some(s) => s,
-        None => Err(io::Error::new(io::ErrorKind::Other, "end of file")),
-    }
-}
-
-/// Parse a compiled terminfo entry, using long capability names if `longnames`
-/// is true
-pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result<TermInfo, String> {
-    macro_rules! t( ($e:expr) => (
-        match $e {
-            Ok(e) => e,
-            Err(e) => return Err(e.to_string())
-        }
-    ) );
-
-    let (bnames, snames, nnames) = if longnames {
-        (boolfnames, stringfnames, numfnames)
-    } else {
-        (boolnames, stringnames, numnames)
-    };
-
-    // Check magic number
-    let magic = t!(read_le_u16(file));
-
-    let extended = match magic {
-        0o0432 => false,
-        0o01036 => true,
-        _ => return Err(format!("invalid magic number, found {:o}", magic)),
-    };
-
-    // According to the spec, these fields must be >= -1 where -1 means that the feature is not
-    // supported. Using 0 instead of -1 works because we skip sections with length 0.
-    macro_rules! read_nonneg {
-        () => {{
-            match t!(read_le_u16(file)) as i16 {
-                n if n >= 0 => n as usize,
-                -1 => 0,
-                _ => return Err("incompatible file: length fields must be  >= -1".to_string()),
-            }
-        }};
-    }
-
-    let names_bytes = read_nonneg!();
-    let bools_bytes = read_nonneg!();
-    let numbers_count = read_nonneg!();
-    let string_offsets_count = read_nonneg!();
-    let string_table_bytes = read_nonneg!();
-
-    if names_bytes == 0 {
-        return Err("incompatible file: names field must be at least 1 byte wide".to_string());
-    }
-
-    if bools_bytes > boolnames.len() {
-        return Err("incompatible file: more booleans than expected".to_string());
-    }
-
-    if numbers_count > numnames.len() {
-        return Err("incompatible file: more numbers than expected".to_string());
-    }
-
-    if string_offsets_count > stringnames.len() {
-        return Err("incompatible file: more string offsets than expected".to_string());
-    }
-
-    // don't read NUL
-    let mut bytes = Vec::new();
-    t!(file.take((names_bytes - 1) as u64).read_to_end(&mut bytes));
-    let names_str = match String::from_utf8(bytes) {
-        Ok(s) => s,
-        Err(_) => return Err("input not utf-8".to_string()),
-    };
-
-    let term_names: Vec<String> = names_str.split('|').map(|s| s.to_string()).collect();
-    // consume NUL
-    if t!(read_byte(file)) != b'\0' {
-        return Err("incompatible file: missing null terminator for names section".to_string());
-    }
-
-    let bools_map: HashMap<String, bool> = t! {
-        (0..bools_bytes).filter_map(|i| match read_byte(file) {
-            Err(e) => Some(Err(e)),
-            Ok(1) => Some(Ok((bnames[i].to_string(), true))),
-            Ok(_) => None
-        }).collect()
-    };
-
-    if (bools_bytes + names_bytes) % 2 == 1 {
-        t!(read_byte(file)); // compensate for padding
-    }
-
-    let numbers_map: HashMap<String, u32> = t! {
-        (0..numbers_count).filter_map(|i| {
-            let number = if extended { read_le_u32(file) } else { read_le_u16(file).map(Into::into) };
-
-            match number {
-                Ok(0xFFFF) => None,
-                Ok(n) => Some(Ok((nnames[i].to_string(), n))),
-                Err(e) => Some(Err(e))
-            }
-        }).collect()
-    };
-
-    let string_map: HashMap<String, Vec<u8>> = if string_offsets_count > 0 {
-        let string_offsets: Vec<u16> =
-            t!((0..string_offsets_count).map(|_| read_le_u16(file)).collect());
-
-        let mut string_table = Vec::new();
-        t!(file.take(string_table_bytes as u64).read_to_end(&mut string_table));
-
-        t!(string_offsets
-            .into_iter()
-            .enumerate()
-            .filter(|&(_, offset)| {
-                // non-entry
-                offset != 0xFFFF
-            })
-            .map(|(i, offset)| {
-                let offset = offset as usize;
-
-                let name = if snames[i] == "_" { stringfnames[i] } else { snames[i] };
-
-                if offset == 0xFFFE {
-                    // undocumented: FFFE indicates cap@, which means the capability is not present
-                    // unsure if the handling for this is correct
-                    return Ok((name.to_string(), Vec::new()));
-                }
-
-                // Find the offset of the NUL we want to go to
-                let nulpos = string_table[offset..string_table_bytes].iter().position(|&b| b == 0);
-                match nulpos {
-                    Some(len) => {
-                        Ok((name.to_string(), string_table[offset..offset + len].to_vec()))
-                    }
-                    None => Err("invalid file: missing NUL in string_table".to_string()),
-                }
-            })
-            .collect())
-    } else {
-        HashMap::new()
-    };
-
-    // And that's all there is to it
-    Ok(TermInfo { names: term_names, bools: bools_map, numbers: numbers_map, strings: string_map })
-}
-
-/// Creates a dummy TermInfo struct for msys terminals
-pub fn msys_terminfo() -> TermInfo {
-    let mut strings = HashMap::new();
-    strings.insert("sgr0".to_string(), b"\x1B[0m".to_vec());
-    strings.insert("bold".to_string(), b"\x1B[1m".to_vec());
-    strings.insert("setaf".to_string(), b"\x1B[3%p1%dm".to_vec());
-    strings.insert("setab".to_string(), b"\x1B[4%p1%dm".to_vec());
-
-    let mut numbers = HashMap::new();
-    numbers.insert("colors".to_string(), 8);
-
-    TermInfo {
-        names: vec!["cygwin".to_string()], // msys is a fork of an older cygwin version
-        bools: HashMap::new(),
-        numbers,
-        strings,
-    }
-}
diff --git a/library/term/src/terminfo/parser/compiled/tests.rs b/library/term/src/terminfo/parser/compiled/tests.rs
deleted file mode 100644 (file)
index 8a9187b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-use super::*;
-
-#[test]
-fn test_veclens() {
-    assert_eq!(boolfnames.len(), boolnames.len());
-    assert_eq!(numfnames.len(), numnames.len());
-    assert_eq!(stringfnames.len(), stringnames.len());
-}
diff --git a/library/term/src/terminfo/searcher.rs b/library/term/src/terminfo/searcher.rs
deleted file mode 100644 (file)
index 5499e24..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-//! ncurses-compatible database discovery.
-//!
-//! Does not support hashed database, only filesystem!
-
-use std::env;
-use std::fs;
-use std::path::PathBuf;
-
-#[cfg(test)]
-mod tests;
-
-/// Return path to database entry for `term`
-#[allow(deprecated)]
-pub fn get_dbpath_for_term(term: &str) -> Option<PathBuf> {
-    let mut dirs_to_search = Vec::new();
-    let first_char = term.chars().next()?;
-
-    // Find search directory
-    if let Some(dir) = env::var_os("TERMINFO") {
-        dirs_to_search.push(PathBuf::from(dir));
-    }
-
-    if let Ok(dirs) = env::var("TERMINFO_DIRS") {
-        for i in dirs.split(':') {
-            if i == "" {
-                dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
-            } else {
-                dirs_to_search.push(PathBuf::from(i));
-            }
-        }
-    } else {
-        // Found nothing in TERMINFO_DIRS, use the default paths:
-        // According to  /etc/terminfo/README, after looking at
-        // ~/.terminfo, ncurses will search /etc/terminfo, then
-        // /lib/terminfo, and eventually /usr/share/terminfo.
-        // On Haiku the database can be found at /boot/system/data/terminfo
-        if let Some(mut homedir) = env::home_dir() {
-            homedir.push(".terminfo");
-            dirs_to_search.push(homedir)
-        }
-
-        dirs_to_search.push(PathBuf::from("/etc/terminfo"));
-        dirs_to_search.push(PathBuf::from("/lib/terminfo"));
-        dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
-        dirs_to_search.push(PathBuf::from("/boot/system/data/terminfo"));
-    }
-
-    // Look for the terminal in all of the search directories
-    for mut p in dirs_to_search {
-        if fs::metadata(&p).is_ok() {
-            p.push(&first_char.to_string());
-            p.push(&term);
-            if fs::metadata(&p).is_ok() {
-                return Some(p);
-            }
-            p.pop();
-            p.pop();
-
-            // on some installations the dir is named after the hex of the char
-            // (e.g., macOS)
-            p.push(&format!("{:x}", first_char as usize));
-            p.push(term);
-            if fs::metadata(&p).is_ok() {
-                return Some(p);
-            }
-        }
-    }
-    None
-}
diff --git a/library/term/src/terminfo/searcher/tests.rs b/library/term/src/terminfo/searcher/tests.rs
deleted file mode 100644 (file)
index 4227a58..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-use super::*;
-
-#[test]
-#[ignore = "buildbots don't have ncurses installed and I can't mock everything I need"]
-fn test_get_dbpath_for_term() {
-    // woefully inadequate test coverage
-    // note: current tests won't work with non-standard terminfo hierarchies (e.g., macOS's)
-    use std::env;
-    // FIXME (#9639): This needs to handle non-utf8 paths
-    fn x(t: &str) -> String {
-        let p = get_dbpath_for_term(t).expect("no terminfo entry found");
-        p.to_str().unwrap().to_string()
-    }
-    assert!(x("screen") == "/usr/share/terminfo/s/screen");
-    assert!(get_dbpath_for_term("") == None);
-    env::set_var("TERMINFO_DIRS", ":");
-    assert!(x("screen") == "/usr/share/terminfo/s/screen");
-    env::remove_var("TERMINFO_DIRS");
-}
diff --git a/library/term/src/win.rs b/library/term/src/win.rs
deleted file mode 100644 (file)
index c24cf95..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-//! Windows console handling
-
-// FIXME (#13400): this is only a tiny fraction of the Windows console api
-
-use std::io;
-use std::io::prelude::*;
-
-use crate::color;
-use crate::Attr;
-use crate::Terminal;
-
-/// A Terminal implementation that uses the Win32 Console API.
-pub struct WinConsole<T> {
-    buf: T,
-    def_foreground: color::Color,
-    def_background: color::Color,
-    foreground: color::Color,
-    background: color::Color,
-}
-
-type SHORT = i16;
-type WORD = u16;
-type DWORD = u32;
-type BOOL = i32;
-type HANDLE = *mut u8;
-
-#[allow(non_snake_case)]
-#[repr(C)]
-struct SMALL_RECT {
-    Left: SHORT,
-    Top: SHORT,
-    Right: SHORT,
-    Bottom: SHORT,
-}
-
-#[allow(non_snake_case)]
-#[repr(C)]
-struct COORD {
-    X: SHORT,
-    Y: SHORT,
-}
-
-#[allow(non_snake_case)]
-#[repr(C)]
-struct CONSOLE_SCREEN_BUFFER_INFO {
-    dwSize: COORD,
-    dwCursorPosition: COORD,
-    wAttributes: WORD,
-    srWindow: SMALL_RECT,
-    dwMaximumWindowSize: COORD,
-}
-
-#[allow(non_snake_case)]
-#[link(name = "kernel32")]
-extern "system" {
-    fn SetConsoleTextAttribute(handle: HANDLE, attr: WORD) -> BOOL;
-    fn GetStdHandle(which: DWORD) -> HANDLE;
-    fn GetConsoleScreenBufferInfo(handle: HANDLE, info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> BOOL;
-}
-
-fn color_to_bits(color: color::Color) -> u16 {
-    // magic numbers from mingw-w64's wincon.h
-
-    let bits = match color % 8 {
-        color::BLACK => 0,
-        color::BLUE => 0x1,
-        color::GREEN => 0x2,
-        color::RED => 0x4,
-        color::YELLOW => 0x2 | 0x4,
-        color::MAGENTA => 0x1 | 0x4,
-        color::CYAN => 0x1 | 0x2,
-        color::WHITE => 0x1 | 0x2 | 0x4,
-        _ => unreachable!(),
-    };
-
-    if color >= 8 { bits | 0x8 } else { bits }
-}
-
-fn bits_to_color(bits: u16) -> color::Color {
-    let color = match bits & 0x7 {
-        0 => color::BLACK,
-        0x1 => color::BLUE,
-        0x2 => color::GREEN,
-        0x4 => color::RED,
-        0x6 => color::YELLOW,
-        0x5 => color::MAGENTA,
-        0x3 => color::CYAN,
-        0x7 => color::WHITE,
-        _ => unreachable!(),
-    };
-
-    color | (u32::from(bits) & 0x8) // copy the hi-intensity bit
-}
-
-impl<T: Write + Send + 'static> WinConsole<T> {
-    fn apply(&mut self) {
-        let _unused = self.buf.flush();
-        let mut accum: WORD = 0;
-        accum |= color_to_bits(self.foreground);
-        accum |= color_to_bits(self.background) << 4;
-
-        unsafe {
-            // Magic -11 means stdout, from
-            // https://docs.microsoft.com/en-us/windows/console/getstdhandle
-            //
-            // You may be wondering, "but what about stderr?", and the answer
-            // to that is that setting terminal attributes on the stdout
-            // handle also sets them for stderr, since they go to the same
-            // terminal! Admittedly, this is fragile, since stderr could be
-            // redirected to a different console. This is good enough for
-            // rustc though. See #13400.
-            let out = GetStdHandle(-11i32 as DWORD);
-            SetConsoleTextAttribute(out, accum);
-        }
-    }
-
-    /// Returns `None` whenever the terminal cannot be created for some reason.
-    pub fn new(out: T) -> io::Result<WinConsole<T>> {
-        use std::mem::MaybeUninit;
-
-        let fg;
-        let bg;
-        unsafe {
-            let mut buffer_info = MaybeUninit::<CONSOLE_SCREEN_BUFFER_INFO>::uninit();
-            if GetConsoleScreenBufferInfo(GetStdHandle(-11i32 as DWORD), buffer_info.as_mut_ptr())
-                != 0
-            {
-                let buffer_info = buffer_info.assume_init();
-                fg = bits_to_color(buffer_info.wAttributes);
-                bg = bits_to_color(buffer_info.wAttributes >> 4);
-            } else {
-                fg = color::WHITE;
-                bg = color::BLACK;
-            }
-        }
-        Ok(WinConsole {
-            buf: out,
-            def_foreground: fg,
-            def_background: bg,
-            foreground: fg,
-            background: bg,
-        })
-    }
-}
-
-impl<T: Write> Write for WinConsole<T> {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.buf.write(buf)
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        self.buf.flush()
-    }
-}
-
-impl<T: Write + Send + 'static> Terminal for WinConsole<T> {
-    type Output = T;
-
-    fn fg(&mut self, color: color::Color) -> io::Result<bool> {
-        self.foreground = color;
-        self.apply();
-
-        Ok(true)
-    }
-
-    fn bg(&mut self, color: color::Color) -> io::Result<bool> {
-        self.background = color;
-        self.apply();
-
-        Ok(true)
-    }
-
-    fn attr(&mut self, attr: Attr) -> io::Result<bool> {
-        match attr {
-            Attr::ForegroundColor(f) => {
-                self.foreground = f;
-                self.apply();
-                Ok(true)
-            }
-            Attr::BackgroundColor(b) => {
-                self.background = b;
-                self.apply();
-                Ok(true)
-            }
-            _ => Ok(false),
-        }
-    }
-
-    fn supports_attr(&self, attr: Attr) -> bool {
-        // it claims support for underscore and reverse video, but I can't get
-        // it to do anything -cmr
-        match attr {
-            Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => true,
-            _ => false,
-        }
-    }
-
-    fn reset(&mut self) -> io::Result<bool> {
-        self.foreground = self.def_foreground;
-        self.background = self.def_background;
-        self.apply();
-
-        Ok(true)
-    }
-
-    fn get_ref(&self) -> &T {
-        &self.buf
-    }
-
-    fn get_mut(&mut self) -> &mut T {
-        &mut self.buf
-    }
-
-    fn into_inner(self) -> T
-    where
-        Self: Sized,
-    {
-        self.buf
-    }
-}
index 226557430df210a23a1b24d309aa81a8d316ab41..479d86354c04cd24f84bcb938183e6630c31bd7a 100644 (file)
@@ -10,7 +10,6 @@ crate-type = ["dylib", "rlib"]
 [dependencies]
 cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
 getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] }
-term = { path = "../term" }
 std = { path = "../std" }
 core = { path = "../core" }
 libc = { version = "0.2", default-features = false }
index 9cfc7eaf4bcf459af5f471f963e1fa4b27bfd1ab..54e30a1fcd070424475b0dcdc661f29053bab207 100644 (file)
@@ -13,7 +13,7 @@ use super::{
     formatters::{JsonFormatter, JunitFormatter, OutputFormatter, PrettyFormatter, TerseFormatter},
     helpers::{concurrency::get_concurrency, metrics::MetricMap},
     options::{Options, OutputFormat},
-    run_tests,
+    run_tests, term,
     test_result::TestResult,
     time::{TestExecTime, TestSuiteExecTime},
     types::{NamePadding, TestDesc, TestDescAndFn},
index ec66fc1219ff7fd4df997f8209432f658abb882b..c4b0e1e5c23392f00a4eaada6a288fb53a03df11 100644 (file)
@@ -79,7 +79,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
                          name=\"{}\" time=\"{}\">",
                         class_name,
                         test_name,
-                        duration.as_secs()
+                        duration.as_secs_f64()
                     ))?;
                     self.write_message("<failure type=\"assert\"/>")?;
                     self.write_message("</testcase>")?;
@@ -91,7 +91,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
                          name=\"{}\" time=\"{}\">",
                         class_name,
                         test_name,
-                        duration.as_secs()
+                        duration.as_secs_f64()
                     ))?;
                     self.write_message(&*format!("<failure message=\"{}\" type=\"assert\"/>", m))?;
                     self.write_message("</testcase>")?;
@@ -103,7 +103,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
                          name=\"{}\" time=\"{}\">",
                         class_name,
                         test_name,
-                        duration.as_secs()
+                        duration.as_secs_f64()
                     ))?;
                     self.write_message("<failure type=\"timeout\"/>")?;
                     self.write_message("</testcase>")?;
@@ -123,7 +123,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
                          name=\"{}\" time=\"{}\"/>",
                         class_name,
                         test_name,
-                        duration.as_secs()
+                        duration.as_secs_f64()
                     ))?;
                 }
             }
index e17fc08a9ae993b0a65eb150bf6d43308d145500..9cad71e30bddb85e8d78b798c70b8d32543339ca 100644 (file)
@@ -4,6 +4,7 @@ use super::OutputFormatter;
 use crate::{
     bench::fmt_bench_samples,
     console::{ConsoleTestState, OutputLocation},
+    term,
     test_result::TestResult,
     time,
     types::TestDesc,
index a2c223c494c293dca5c9ef13bb82269a47d1dded..0c8215c5daca165b71975d777ab1393a2aeeb700 100644 (file)
@@ -4,6 +4,7 @@ use super::OutputFormatter;
 use crate::{
     bench::fmt_bench_samples,
     console::{ConsoleTestState, OutputLocation},
+    term,
     test_result::TestResult,
     time,
     types::NamePadding,
index 3da4d434f48f23843e3ac3b2f588a51f94cae487..251f099f28af47e399640842f01c05fa4038837a 100644 (file)
@@ -20,7 +20,7 @@
 #![crate_name = "test"]
 #![unstable(feature = "test", issue = "50297")]
 #![doc(test(attr(deny(warnings))))]
-#![cfg_attr(unix, feature(libc))]
+#![feature(libc)]
 #![feature(rustc_private)]
 #![feature(nll)]
 #![feature(available_concurrency)]
@@ -80,6 +80,7 @@ mod formatters;
 mod helpers;
 mod options;
 pub mod stats;
+mod term;
 mod test_result;
 mod time;
 mod types;
index 53f3889447453fa810126ed8dd78f1de9e74fca3..45fae9c76b44d1972a5009bb7cc6486f54513bd3 100644 (file)
@@ -19,7 +19,7 @@ pub trait Stats {
     /// ["Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric
     /// Predicates"][paper]
     ///
-    /// [paper]: http://www.cs.cmu.edu/~quake-papers/robust-arithmetic.ps
+    /// [paper]: https://www.cs.cmu.edu/~quake-papers/robust-arithmetic.ps
     fn sum(&self) -> f64;
 
     /// Minimum value of the samples.
diff --git a/library/test/src/term.rs b/library/test/src/term.rs
new file mode 100644 (file)
index 0000000..b256ab7
--- /dev/null
@@ -0,0 +1,85 @@
+//! Terminal formatting module.
+//!
+//! This module provides the `Terminal` trait, which abstracts over an [ANSI
+//! Terminal][ansi] to provide color printing, among other things. There are two
+//! implementations, the `TerminfoTerminal`, which uses control characters from
+//! a [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console
+//! API][win].
+//!
+//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code
+//! [win]: https://docs.microsoft.com/en-us/windows/console/character-mode-applications
+//! [ti]: https://en.wikipedia.org/wiki/Terminfo
+
+#![deny(missing_docs)]
+
+use std::io::{self, prelude::*};
+
+pub(crate) use terminfo::TerminfoTerminal;
+#[cfg(windows)]
+pub(crate) use win::WinConsole;
+
+pub(crate) mod terminfo;
+
+#[cfg(windows)]
+mod win;
+
+/// Alias for stdout terminals.
+pub(crate) type StdoutTerminal = dyn Terminal + Send;
+
+#[cfg(not(windows))]
+/// Returns a Terminal wrapping stdout, or None if a terminal couldn't be
+/// opened.
+pub(crate) fn stdout() -> Option<Box<StdoutTerminal>> {
+    TerminfoTerminal::new(io::stdout()).map(|t| Box::new(t) as Box<StdoutTerminal>)
+}
+
+#[cfg(windows)]
+/// Returns a Terminal wrapping stdout, or None if a terminal couldn't be
+/// opened.
+pub(crate) fn stdout() -> Option<Box<StdoutTerminal>> {
+    TerminfoTerminal::new(io::stdout())
+        .map(|t| Box::new(t) as Box<StdoutTerminal>)
+        .or_else(|| WinConsole::new(io::stdout()).ok().map(|t| Box::new(t) as Box<StdoutTerminal>))
+}
+
+/// Terminal color definitions
+#[allow(missing_docs)]
+#[cfg_attr(not(windows), allow(dead_code))]
+pub(crate) mod color {
+    /// Number for a terminal color
+    pub(crate) type Color = u32;
+
+    pub(crate) const BLACK: Color = 0;
+    pub(crate) const RED: Color = 1;
+    pub(crate) const GREEN: Color = 2;
+    pub(crate) const YELLOW: Color = 3;
+    pub(crate) const BLUE: Color = 4;
+    pub(crate) const MAGENTA: Color = 5;
+    pub(crate) const CYAN: Color = 6;
+    pub(crate) const WHITE: Color = 7;
+}
+
+/// A terminal with similar capabilities to an ANSI Terminal
+/// (foreground/background colors etc).
+pub trait Terminal: Write {
+    /// Sets the foreground color to the given color.
+    ///
+    /// If the color is a bright color, but the terminal only supports 8 colors,
+    /// the corresponding normal color will be used instead.
+    ///
+    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
+    /// if there was an I/O error.
+    fn fg(&mut self, color: color::Color) -> io::Result<bool>;
+
+    /// Resets all terminal attributes and colors to their defaults.
+    ///
+    /// Returns `Ok(true)` if the terminal was reset, `Ok(false)` otherwise, and `Err(e)` if there
+    /// was an I/O error.
+    ///
+    /// *Note: This does not flush.*
+    ///
+    /// That means the reset command may get buffered so, if you aren't planning on doing anything
+    /// else that might flush stdout's buffer (e.g., writing a line of text), you should flush after
+    /// calling reset.
+    fn reset(&mut self) -> io::Result<bool>;
+}
diff --git a/library/test/src/term/terminfo/mod.rs b/library/test/src/term/terminfo/mod.rs
new file mode 100644 (file)
index 0000000..f4c5a05
--- /dev/null
@@ -0,0 +1,184 @@
+//! Terminfo database interface.
+
+use std::collections::HashMap;
+use std::env;
+use std::error;
+use std::fmt;
+use std::fs::File;
+use std::io::{self, prelude::*, BufReader};
+use std::path::Path;
+
+use super::color;
+use super::Terminal;
+
+use parm::{expand, Param, Variables};
+use parser::compiled::{msys_terminfo, parse};
+use searcher::get_dbpath_for_term;
+
+/// A parsed terminfo database entry.
+#[derive(Debug)]
+pub(crate) struct TermInfo {
+    /// Names for the terminal
+    pub(crate) names: Vec<String>,
+    /// Map of capability name to boolean value
+    pub(crate) bools: HashMap<String, bool>,
+    /// Map of capability name to numeric value
+    pub(crate) numbers: HashMap<String, u32>,
+    /// Map of capability name to raw (unexpanded) string
+    pub(crate) strings: HashMap<String, Vec<u8>>,
+}
+
+/// A terminfo creation error.
+#[derive(Debug)]
+pub(crate) enum Error {
+    /// TermUnset Indicates that the environment doesn't include enough information to find
+    /// the terminfo entry.
+    TermUnset,
+    /// MalformedTerminfo indicates that parsing the terminfo entry failed.
+    MalformedTerminfo(String),
+    /// io::Error forwards any io::Errors encountered when finding or reading the terminfo entry.
+    IoError(io::Error),
+}
+
+impl error::Error for Error {
+    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
+        use Error::*;
+        match self {
+            IoError(e) => Some(e),
+            _ => None,
+        }
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use Error::*;
+        match *self {
+            TermUnset => Ok(()),
+            MalformedTerminfo(ref e) => e.fmt(f),
+            IoError(ref e) => e.fmt(f),
+        }
+    }
+}
+
+impl TermInfo {
+    /// Creates a TermInfo based on current environment.
+    pub(crate) fn from_env() -> Result<TermInfo, Error> {
+        let term = match env::var("TERM") {
+            Ok(name) => TermInfo::from_name(&name),
+            Err(..) => return Err(Error::TermUnset),
+        };
+
+        if term.is_err() && env::var("MSYSCON").map_or(false, |s| "mintty.exe" == s) {
+            // msys terminal
+            Ok(msys_terminfo())
+        } else {
+            term
+        }
+    }
+
+    /// Creates a TermInfo for the named terminal.
+    pub(crate) fn from_name(name: &str) -> Result<TermInfo, Error> {
+        get_dbpath_for_term(name)
+            .ok_or_else(|| {
+                Error::IoError(io::Error::new(io::ErrorKind::NotFound, "terminfo file not found"))
+            })
+            .and_then(|p| TermInfo::from_path(&(*p)))
+    }
+
+    /// Parse the given TermInfo.
+    pub(crate) fn from_path<P: AsRef<Path>>(path: P) -> Result<TermInfo, Error> {
+        Self::_from_path(path.as_ref())
+    }
+    // Keep the metadata small
+    fn _from_path(path: &Path) -> Result<TermInfo, Error> {
+        let file = File::open(path).map_err(Error::IoError)?;
+        let mut reader = BufReader::new(file);
+        parse(&mut reader, false).map_err(Error::MalformedTerminfo)
+    }
+}
+
+pub(crate) mod searcher;
+
+/// TermInfo format parsing.
+pub(crate) mod parser {
+    //! ncurses-compatible compiled terminfo format parsing (term(5))
+    pub(crate) mod compiled;
+}
+pub(crate) mod parm;
+
+/// A Terminal that knows how many colors it supports, with a reference to its
+/// parsed Terminfo database record.
+pub(crate) struct TerminfoTerminal<T> {
+    num_colors: u32,
+    out: T,
+    ti: TermInfo,
+}
+
+impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
+    fn fg(&mut self, color: color::Color) -> io::Result<bool> {
+        let color = self.dim_if_necessary(color);
+        if self.num_colors > color {
+            return self.apply_cap("setaf", &[Param::Number(color as i32)]);
+        }
+        Ok(false)
+    }
+
+    fn reset(&mut self) -> io::Result<bool> {
+        // are there any terminals that have color/attrs and not sgr0?
+        // Try falling back to sgr, then op
+        let cmd = match ["sgr0", "sgr", "op"].iter().find_map(|cap| self.ti.strings.get(*cap)) {
+            Some(op) => match expand(&op, &[], &mut Variables::new()) {
+                Ok(cmd) => cmd,
+                Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)),
+            },
+            None => return Ok(false),
+        };
+        self.out.write_all(&cmd).and(Ok(true))
+    }
+}
+
+impl<T: Write + Send> TerminfoTerminal<T> {
+    /// Creates a new TerminfoTerminal with the given TermInfo and Write.
+    pub(crate) fn new_with_terminfo(out: T, terminfo: TermInfo) -> TerminfoTerminal<T> {
+        let nc = if terminfo.strings.contains_key("setaf") && terminfo.strings.contains_key("setab")
+        {
+            terminfo.numbers.get("colors").map_or(0, |&n| n)
+        } else {
+            0
+        };
+
+        TerminfoTerminal { out, ti: terminfo, num_colors: nc }
+    }
+
+    /// Creates a new TerminfoTerminal for the current environment with the given Write.
+    ///
+    /// Returns `None` when the terminfo cannot be found or parsed.
+    pub(crate) fn new(out: T) -> Option<TerminfoTerminal<T>> {
+        TermInfo::from_env().map(move |ti| TerminfoTerminal::new_with_terminfo(out, ti)).ok()
+    }
+
+    fn dim_if_necessary(&self, color: color::Color) -> color::Color {
+        if color >= self.num_colors && color >= 8 && color < 16 { color - 8 } else { color }
+    }
+
+    fn apply_cap(&mut self, cmd: &str, params: &[Param]) -> io::Result<bool> {
+        match self.ti.strings.get(cmd) {
+            Some(cmd) => match expand(&cmd, params, &mut Variables::new()) {
+                Ok(s) => self.out.write_all(&s).and(Ok(true)),
+                Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e)),
+            },
+            None => Ok(false),
+        }
+    }
+}
+
+impl<T: Write> Write for TerminfoTerminal<T> {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.out.write(buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        self.out.flush()
+    }
+}
diff --git a/library/test/src/term/terminfo/parm.rs b/library/test/src/term/terminfo/parm.rs
new file mode 100644 (file)
index 0000000..0d37eb7
--- /dev/null
@@ -0,0 +1,532 @@
+//! Parameterized string expansion
+
+use self::Param::*;
+use self::States::*;
+
+use std::iter::repeat;
+
+#[cfg(test)]
+mod tests;
+
+#[derive(Clone, Copy, PartialEq)]
+enum States {
+    Nothing,
+    Percent,
+    SetVar,
+    GetVar,
+    PushParam,
+    CharConstant,
+    CharClose,
+    IntConstant(i32),
+    FormatPattern(Flags, FormatState),
+    SeekIfElse(usize),
+    SeekIfElsePercent(usize),
+    SeekIfEnd(usize),
+    SeekIfEndPercent(usize),
+}
+
+#[derive(Copy, PartialEq, Clone)]
+enum FormatState {
+    Flags,
+    Width,
+    Precision,
+}
+
+/// Types of parameters a capability can use
+#[allow(missing_docs)]
+#[derive(Clone)]
+pub(crate) enum Param {
+    Number(i32),
+}
+
+/// Container for static and dynamic variable arrays
+pub(crate) struct Variables {
+    /// Static variables A-Z
+    sta_va: [Param; 26],
+    /// Dynamic variables a-z
+    dyn_va: [Param; 26],
+}
+
+impl Variables {
+    /// Returns a new zero-initialized Variables
+    pub(crate) fn new() -> Variables {
+        Variables {
+            sta_va: [
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+            ],
+            dyn_va: [
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+            ],
+        }
+    }
+}
+
+/// Expand a parameterized capability
+///
+/// # Arguments
+/// * `cap`    - string to expand
+/// * `params` - vector of params for %p1 etc
+/// * `vars`   - Variables struct for %Pa etc
+///
+/// To be compatible with ncurses, `vars` should be the same between calls to `expand` for
+/// multiple capabilities for the same terminal.
+pub(crate) fn expand(
+    cap: &[u8],
+    params: &[Param],
+    vars: &mut Variables,
+) -> Result<Vec<u8>, String> {
+    let mut state = Nothing;
+
+    // expanded cap will only rarely be larger than the cap itself
+    let mut output = Vec::with_capacity(cap.len());
+
+    let mut stack: Vec<Param> = Vec::new();
+
+    // Copy parameters into a local vector for mutability
+    let mut mparams = [
+        Number(0),
+        Number(0),
+        Number(0),
+        Number(0),
+        Number(0),
+        Number(0),
+        Number(0),
+        Number(0),
+        Number(0),
+    ];
+    for (dst, src) in mparams.iter_mut().zip(params.iter()) {
+        *dst = (*src).clone();
+    }
+
+    for &c in cap.iter() {
+        let cur = c as char;
+        let mut old_state = state;
+        match state {
+            Nothing => {
+                if cur == '%' {
+                    state = Percent;
+                } else {
+                    output.push(c);
+                }
+            }
+            Percent => {
+                match cur {
+                    '%' => {
+                        output.push(c);
+                        state = Nothing
+                    }
+                    'c' => {
+                        match stack.pop() {
+                            // if c is 0, use 0200 (128) for ncurses compatibility
+                            Some(Number(0)) => output.push(128u8),
+                            // Don't check bounds. ncurses just casts and truncates.
+                            Some(Number(c)) => output.push(c as u8),
+                            None => return Err("stack is empty".to_string()),
+                        }
+                    }
+                    'p' => state = PushParam,
+                    'P' => state = SetVar,
+                    'g' => state = GetVar,
+                    '\'' => state = CharConstant,
+                    '{' => state = IntConstant(0),
+                    'l' => match stack.pop() {
+                        Some(_) => return Err("a non-str was used with %l".to_string()),
+                        None => return Err("stack is empty".to_string()),
+                    },
+                    '+' | '-' | '/' | '*' | '^' | '&' | '|' | 'm' => {
+                        match (stack.pop(), stack.pop()) {
+                            (Some(Number(y)), Some(Number(x))) => stack.push(Number(match cur {
+                                '+' => x + y,
+                                '-' => x - y,
+                                '*' => x * y,
+                                '/' => x / y,
+                                '|' => x | y,
+                                '&' => x & y,
+                                '^' => x ^ y,
+                                'm' => x % y,
+                                _ => unreachable!("All cases handled"),
+                            })),
+                            _ => return Err("stack is empty".to_string()),
+                        }
+                    }
+                    '=' | '>' | '<' | 'A' | 'O' => match (stack.pop(), stack.pop()) {
+                        (Some(Number(y)), Some(Number(x))) => stack.push(Number(
+                            if match cur {
+                                '=' => x == y,
+                                '<' => x < y,
+                                '>' => x > y,
+                                'A' => x > 0 && y > 0,
+                                'O' => x > 0 || y > 0,
+                                _ => unreachable!(),
+                            } {
+                                1
+                            } else {
+                                0
+                            },
+                        )),
+                        _ => return Err("stack is empty".to_string()),
+                    },
+                    '!' | '~' => match stack.pop() {
+                        Some(Number(x)) => stack.push(Number(match cur {
+                            '!' if x > 0 => 0,
+                            '!' => 1,
+                            '~' => !x,
+                            _ => unreachable!(),
+                        })),
+                        None => return Err("stack is empty".to_string()),
+                    },
+                    'i' => match (&mparams[0], &mparams[1]) {
+                        (&Number(x), &Number(y)) => {
+                            mparams[0] = Number(x + 1);
+                            mparams[1] = Number(y + 1);
+                        }
+                    },
+
+                    // printf-style support for %doxXs
+                    'd' | 'o' | 'x' | 'X' | 's' => {
+                        if let Some(arg) = stack.pop() {
+                            let flags = Flags::new();
+                            let res = format(arg, FormatOp::from_char(cur), flags)?;
+                            output.extend(res.iter().cloned());
+                        } else {
+                            return Err("stack is empty".to_string());
+                        }
+                    }
+                    ':' | '#' | ' ' | '.' | '0'..='9' => {
+                        let mut flags = Flags::new();
+                        let mut fstate = FormatState::Flags;
+                        match cur {
+                            ':' => (),
+                            '#' => flags.alternate = true,
+                            ' ' => flags.space = true,
+                            '.' => fstate = FormatState::Precision,
+                            '0'..='9' => {
+                                flags.width = cur as usize - '0' as usize;
+                                fstate = FormatState::Width;
+                            }
+                            _ => unreachable!(),
+                        }
+                        state = FormatPattern(flags, fstate);
+                    }
+
+                    // conditionals
+                    '?' => (),
+                    't' => match stack.pop() {
+                        Some(Number(0)) => state = SeekIfElse(0),
+                        Some(Number(_)) => (),
+                        None => return Err("stack is empty".to_string()),
+                    },
+                    'e' => state = SeekIfEnd(0),
+                    ';' => (),
+                    _ => return Err(format!("unrecognized format option {}", cur)),
+                }
+            }
+            PushParam => {
+                // params are 1-indexed
+                stack.push(
+                    mparams[match cur.to_digit(10) {
+                        Some(d) => d as usize - 1,
+                        None => return Err("bad param number".to_string()),
+                    }]
+                    .clone(),
+                );
+            }
+            SetVar => {
+                if cur >= 'A' && cur <= 'Z' {
+                    if let Some(arg) = stack.pop() {
+                        let idx = (cur as u8) - b'A';
+                        vars.sta_va[idx as usize] = arg;
+                    } else {
+                        return Err("stack is empty".to_string());
+                    }
+                } else if cur >= 'a' && cur <= 'z' {
+                    if let Some(arg) = stack.pop() {
+                        let idx = (cur as u8) - b'a';
+                        vars.dyn_va[idx as usize] = arg;
+                    } else {
+                        return Err("stack is empty".to_string());
+                    }
+                } else {
+                    return Err("bad variable name in %P".to_string());
+                }
+            }
+            GetVar => {
+                if cur >= 'A' && cur <= 'Z' {
+                    let idx = (cur as u8) - b'A';
+                    stack.push(vars.sta_va[idx as usize].clone());
+                } else if cur >= 'a' && cur <= 'z' {
+                    let idx = (cur as u8) - b'a';
+                    stack.push(vars.dyn_va[idx as usize].clone());
+                } else {
+                    return Err("bad variable name in %g".to_string());
+                }
+            }
+            CharConstant => {
+                stack.push(Number(c as i32));
+                state = CharClose;
+            }
+            CharClose => {
+                if cur != '\'' {
+                    return Err("malformed character constant".to_string());
+                }
+            }
+            IntConstant(i) => {
+                if cur == '}' {
+                    stack.push(Number(i));
+                    state = Nothing;
+                } else if let Some(digit) = cur.to_digit(10) {
+                    match i.checked_mul(10).and_then(|i_ten| i_ten.checked_add(digit as i32)) {
+                        Some(i) => {
+                            state = IntConstant(i);
+                            old_state = Nothing;
+                        }
+                        None => return Err("int constant too large".to_string()),
+                    }
+                } else {
+                    return Err("bad int constant".to_string());
+                }
+            }
+            FormatPattern(ref mut flags, ref mut fstate) => {
+                old_state = Nothing;
+                match (*fstate, cur) {
+                    (_, 'd') | (_, 'o') | (_, 'x') | (_, 'X') | (_, 's') => {
+                        if let Some(arg) = stack.pop() {
+                            let res = format(arg, FormatOp::from_char(cur), *flags)?;
+                            output.extend(res.iter().cloned());
+                            // will cause state to go to Nothing
+                            old_state = FormatPattern(*flags, *fstate);
+                        } else {
+                            return Err("stack is empty".to_string());
+                        }
+                    }
+                    (FormatState::Flags, '#') => {
+                        flags.alternate = true;
+                    }
+                    (FormatState::Flags, '-') => {
+                        flags.left = true;
+                    }
+                    (FormatState::Flags, '+') => {
+                        flags.sign = true;
+                    }
+                    (FormatState::Flags, ' ') => {
+                        flags.space = true;
+                    }
+                    (FormatState::Flags, '0'..='9') => {
+                        flags.width = cur as usize - '0' as usize;
+                        *fstate = FormatState::Width;
+                    }
+                    (FormatState::Flags, '.') => {
+                        *fstate = FormatState::Precision;
+                    }
+                    (FormatState::Width, '0'..='9') => {
+                        let old = flags.width;
+                        flags.width = flags.width * 10 + (cur as usize - '0' as usize);
+                        if flags.width < old {
+                            return Err("format width overflow".to_string());
+                        }
+                    }
+                    (FormatState::Width, '.') => {
+                        *fstate = FormatState::Precision;
+                    }
+                    (FormatState::Precision, '0'..='9') => {
+                        let old = flags.precision;
+                        flags.precision = flags.precision * 10 + (cur as usize - '0' as usize);
+                        if flags.precision < old {
+                            return Err("format precision overflow".to_string());
+                        }
+                    }
+                    _ => return Err("invalid format specifier".to_string()),
+                }
+            }
+            SeekIfElse(level) => {
+                if cur == '%' {
+                    state = SeekIfElsePercent(level);
+                }
+                old_state = Nothing;
+            }
+            SeekIfElsePercent(level) => {
+                if cur == ';' {
+                    if level == 0 {
+                        state = Nothing;
+                    } else {
+                        state = SeekIfElse(level - 1);
+                    }
+                } else if cur == 'e' && level == 0 {
+                    state = Nothing;
+                } else if cur == '?' {
+                    state = SeekIfElse(level + 1);
+                } else {
+                    state = SeekIfElse(level);
+                }
+            }
+            SeekIfEnd(level) => {
+                if cur == '%' {
+                    state = SeekIfEndPercent(level);
+                }
+                old_state = Nothing;
+            }
+            SeekIfEndPercent(level) => {
+                if cur == ';' {
+                    if level == 0 {
+                        state = Nothing;
+                    } else {
+                        state = SeekIfEnd(level - 1);
+                    }
+                } else if cur == '?' {
+                    state = SeekIfEnd(level + 1);
+                } else {
+                    state = SeekIfEnd(level);
+                }
+            }
+        }
+        if state == old_state {
+            state = Nothing;
+        }
+    }
+    Ok(output)
+}
+
+#[derive(Copy, PartialEq, Clone)]
+struct Flags {
+    width: usize,
+    precision: usize,
+    alternate: bool,
+    left: bool,
+    sign: bool,
+    space: bool,
+}
+
+impl Flags {
+    fn new() -> Flags {
+        Flags { width: 0, precision: 0, alternate: false, left: false, sign: false, space: false }
+    }
+}
+
+#[derive(Copy, Clone)]
+enum FormatOp {
+    Digit,
+    Octal,
+    LowerHex,
+    UpperHex,
+    String,
+}
+
+impl FormatOp {
+    fn from_char(c: char) -> FormatOp {
+        match c {
+            'd' => FormatOp::Digit,
+            'o' => FormatOp::Octal,
+            'x' => FormatOp::LowerHex,
+            'X' => FormatOp::UpperHex,
+            's' => FormatOp::String,
+            _ => panic!("bad FormatOp char"),
+        }
+    }
+}
+
+fn format(val: Param, op: FormatOp, flags: Flags) -> Result<Vec<u8>, String> {
+    let mut s = match val {
+        Number(d) => {
+            match op {
+                FormatOp::Digit => {
+                    if flags.sign {
+                        format!("{:+01$}", d, flags.precision)
+                    } else if d < 0 {
+                        // C doesn't take sign into account in precision calculation.
+                        format!("{:01$}", d, flags.precision + 1)
+                    } else if flags.space {
+                        format!(" {:01$}", d, flags.precision)
+                    } else {
+                        format!("{:01$}", d, flags.precision)
+                    }
+                }
+                FormatOp::Octal => {
+                    if flags.alternate {
+                        // Leading octal zero counts against precision.
+                        format!("0{:01$o}", d, flags.precision.saturating_sub(1))
+                    } else {
+                        format!("{:01$o}", d, flags.precision)
+                    }
+                }
+                FormatOp::LowerHex => {
+                    if flags.alternate && d != 0 {
+                        format!("0x{:01$x}", d, flags.precision)
+                    } else {
+                        format!("{:01$x}", d, flags.precision)
+                    }
+                }
+                FormatOp::UpperHex => {
+                    if flags.alternate && d != 0 {
+                        format!("0X{:01$X}", d, flags.precision)
+                    } else {
+                        format!("{:01$X}", d, flags.precision)
+                    }
+                }
+                FormatOp::String => return Err("non-number on stack with %s".to_string()),
+            }
+            .into_bytes()
+        }
+    };
+    if flags.width > s.len() {
+        let n = flags.width - s.len();
+        if flags.left {
+            s.extend(repeat(b' ').take(n));
+        } else {
+            let mut s_ = Vec::with_capacity(flags.width);
+            s_.extend(repeat(b' ').take(n));
+            s_.extend(s.into_iter());
+            s = s_;
+        }
+    }
+    Ok(s)
+}
diff --git a/library/test/src/term/terminfo/parm/tests.rs b/library/test/src/term/terminfo/parm/tests.rs
new file mode 100644 (file)
index 0000000..256d1aa
--- /dev/null
@@ -0,0 +1,124 @@
+use super::*;
+
+use std::result::Result::Ok;
+
+#[test]
+fn test_basic_setabf() {
+    let s = b"\\E[48;5;%p1%dm";
+    assert_eq!(
+        expand(s, &[Number(1)], &mut Variables::new()).unwrap(),
+        "\\E[48;5;1m".bytes().collect::<Vec<_>>()
+    );
+}
+
+#[test]
+fn test_multiple_int_constants() {
+    assert_eq!(
+        expand(b"%{1}%{2}%d%d", &[], &mut Variables::new()).unwrap(),
+        "21".bytes().collect::<Vec<_>>()
+    );
+}
+
+#[test]
+fn test_op_i() {
+    let mut vars = Variables::new();
+    assert_eq!(
+        expand(b"%p1%d%p2%d%p3%d%i%p1%d%p2%d%p3%d", &[Number(1), Number(2), Number(3)], &mut vars),
+        Ok("123233".bytes().collect::<Vec<_>>())
+    );
+    assert_eq!(
+        expand(b"%p1%d%p2%d%i%p1%d%p2%d", &[], &mut vars),
+        Ok("0011".bytes().collect::<Vec<_>>())
+    );
+}
+
+#[test]
+fn test_param_stack_failure_conditions() {
+    let mut varstruct = Variables::new();
+    let vars = &mut varstruct;
+    fn get_res(
+        fmt: &str,
+        cap: &str,
+        params: &[Param],
+        vars: &mut Variables,
+    ) -> Result<Vec<u8>, String> {
+        let mut u8v: Vec<_> = fmt.bytes().collect();
+        u8v.extend(cap.as_bytes().iter().map(|&b| b));
+        expand(&u8v, params, vars)
+    }
+
+    let caps = ["%d", "%c", "%s", "%Pa", "%l", "%!", "%~"];
+    for &cap in caps.iter() {
+        let res = get_res("", cap, &[], vars);
+        assert!(res.is_err(), "Op {} succeeded incorrectly with 0 stack entries", cap);
+        if cap == "%s" || cap == "%l" {
+            continue;
+        }
+        let p = Number(97);
+        let res = get_res("%p1", cap, &[p], vars);
+        assert!(res.is_ok(), "Op {} failed with 1 stack entry: {}", cap, res.unwrap_err());
+    }
+    let caps = ["%+", "%-", "%*", "%/", "%m", "%&", "%|", "%A", "%O"];
+    for &cap in caps.iter() {
+        let res = expand(cap.as_bytes(), &[], vars);
+        assert!(res.is_err(), "Binop {} succeeded incorrectly with 0 stack entries", cap);
+        let res = get_res("%{1}", cap, &[], vars);
+        assert!(res.is_err(), "Binop {} succeeded incorrectly with 1 stack entry", cap);
+        let res = get_res("%{1}%{2}", cap, &[], vars);
+        assert!(res.is_ok(), "Binop {} failed with 2 stack entries: {}", cap, res.unwrap_err());
+    }
+}
+
+#[test]
+fn test_push_bad_param() {
+    assert!(expand(b"%pa", &[], &mut Variables::new()).is_err());
+}
+
+#[test]
+fn test_comparison_ops() {
+    let v = [('<', [1u8, 0u8, 0u8]), ('=', [0u8, 1u8, 0u8]), ('>', [0u8, 0u8, 1u8])];
+    for &(op, bs) in v.iter() {
+        let s = format!("%{{1}}%{{2}}%{}%d", op);
+        let res = expand(s.as_bytes(), &[], &mut Variables::new());
+        assert!(res.is_ok(), "{}", res.unwrap_err());
+        assert_eq!(res.unwrap(), vec![b'0' + bs[0]]);
+        let s = format!("%{{1}}%{{1}}%{}%d", op);
+        let res = expand(s.as_bytes(), &[], &mut Variables::new());
+        assert!(res.is_ok(), "{}", res.unwrap_err());
+        assert_eq!(res.unwrap(), vec![b'0' + bs[1]]);
+        let s = format!("%{{2}}%{{1}}%{}%d", op);
+        let res = expand(s.as_bytes(), &[], &mut Variables::new());
+        assert!(res.is_ok(), "{}", res.unwrap_err());
+        assert_eq!(res.unwrap(), vec![b'0' + bs[2]]);
+    }
+}
+
+#[test]
+fn test_conditionals() {
+    let mut vars = Variables::new();
+    let s = b"\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m";
+    let res = expand(s, &[Number(1)], &mut vars);
+    assert!(res.is_ok(), "{}", res.unwrap_err());
+    assert_eq!(res.unwrap(), "\\E[31m".bytes().collect::<Vec<_>>());
+    let res = expand(s, &[Number(8)], &mut vars);
+    assert!(res.is_ok(), "{}", res.unwrap_err());
+    assert_eq!(res.unwrap(), "\\E[90m".bytes().collect::<Vec<_>>());
+    let res = expand(s, &[Number(42)], &mut vars);
+    assert!(res.is_ok(), "{}", res.unwrap_err());
+    assert_eq!(res.unwrap(), "\\E[38;5;42m".bytes().collect::<Vec<_>>());
+}
+
+#[test]
+fn test_format() {
+    let mut varstruct = Variables::new();
+    let vars = &mut varstruct;
+
+    assert_eq!(
+        expand(b"%p1%d%p1%.3d%p1%5d%p1%:+d", &[Number(1)], vars),
+        Ok("1001    1+1".bytes().collect::<Vec<_>>())
+    );
+    assert_eq!(
+        expand(b"%p1%o%p1%#o%p2%6.4x%p2%#6.4X", &[Number(15), Number(27)], vars),
+        Ok("17017  001b0X001B".bytes().collect::<Vec<_>>())
+    );
+}
diff --git a/library/test/src/term/terminfo/parser/compiled.rs b/library/test/src/term/terminfo/parser/compiled.rs
new file mode 100644 (file)
index 0000000..b24f3f8
--- /dev/null
@@ -0,0 +1,336 @@
+#![allow(non_upper_case_globals, missing_docs)]
+
+//! ncurses-compatible compiled terminfo format parsing (term(5))
+
+use super::super::TermInfo;
+use std::collections::HashMap;
+use std::io;
+use std::io::prelude::*;
+
+#[cfg(test)]
+mod tests;
+
+// These are the orders ncurses uses in its compiled format (as of 5.9). Not sure if portable.
+
+#[rustfmt::skip]
+pub(crate) static boolfnames: &[&str] = &["auto_left_margin", "auto_right_margin",
+    "no_esc_ctlc", "ceol_standout_glitch", "eat_newline_glitch", "erase_overstrike", "generic_type",
+    "hard_copy", "has_meta_key", "has_status_line", "insert_null_glitch", "memory_above",
+    "memory_below", "move_insert_mode", "move_standout_mode", "over_strike", "status_line_esc_ok",
+    "dest_tabs_magic_smso", "tilde_glitch", "transparent_underline", "xon_xoff", "needs_xon_xoff",
+    "prtr_silent", "hard_cursor", "non_rev_rmcup", "no_pad_char", "non_dest_scroll_region",
+    "can_change", "back_color_erase", "hue_lightness_saturation", "col_addr_glitch",
+    "cr_cancels_micro_mode", "has_print_wheel", "row_addr_glitch", "semi_auto_right_margin",
+    "cpi_changes_res", "lpi_changes_res", "backspaces_with_bs", "crt_no_scrolling",
+    "no_correctly_working_cr", "gnu_has_meta_key", "linefeed_is_newline", "has_hardware_tabs",
+    "return_does_clr_eol"];
+
+#[rustfmt::skip]
+pub(crate) static boolnames: &[&str] = &["bw", "am", "xsb", "xhp", "xenl", "eo",
+    "gn", "hc", "km", "hs", "in", "db", "da", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon",
+    "nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy",
+    "xvpa", "sam", "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"];
+
+#[rustfmt::skip]
+pub(crate) static numfnames: &[&str] = &[ "columns", "init_tabs", "lines",
+    "lines_of_memory", "magic_cookie_glitch", "padding_baud_rate", "virtual_terminal",
+    "width_status_line", "num_labels", "label_height", "label_width", "max_attributes",
+    "maximum_windows", "max_colors", "max_pairs", "no_color_video", "buffer_capacity",
+    "dot_vert_spacing", "dot_horz_spacing", "max_micro_address", "max_micro_jump", "micro_col_size",
+    "micro_line_size", "number_of_pins", "output_res_char", "output_res_line",
+    "output_res_horz_inch", "output_res_vert_inch", "print_rate", "wide_char_size", "buttons",
+    "bit_image_entwining", "bit_image_type", "magic_cookie_glitch_ul", "carriage_return_delay",
+    "new_line_delay", "backspace_delay", "horizontal_tab_delay", "number_of_function_keys"];
+
+#[rustfmt::skip]
+pub(crate) static numnames: &[&str] = &[ "cols", "it", "lines", "lm", "xmc", "pb",
+    "vt", "wsl", "nlab", "lh", "lw", "ma", "wnum", "colors", "pairs", "ncv", "bufsz", "spinv",
+    "spinh", "maddr", "mjump", "mcs", "mls", "npins", "orc", "orl", "orhi", "orvi", "cps", "widcs",
+    "btns", "bitwin", "bitype", "UTug", "OTdC", "OTdN", "OTdB", "OTdT", "OTkn"];
+
+#[rustfmt::skip]
+pub(crate) static stringfnames: &[&str] = &[ "back_tab", "bell", "carriage_return",
+    "change_scroll_region", "clear_all_tabs", "clear_screen", "clr_eol", "clr_eos",
+    "column_address", "command_character", "cursor_address", "cursor_down", "cursor_home",
+    "cursor_invisible", "cursor_left", "cursor_mem_address", "cursor_normal", "cursor_right",
+    "cursor_to_ll", "cursor_up", "cursor_visible", "delete_character", "delete_line",
+    "dis_status_line", "down_half_line", "enter_alt_charset_mode", "enter_blink_mode",
+    "enter_bold_mode", "enter_ca_mode", "enter_delete_mode", "enter_dim_mode", "enter_insert_mode",
+    "enter_secure_mode", "enter_protected_mode", "enter_reverse_mode", "enter_standout_mode",
+    "enter_underline_mode", "erase_chars", "exit_alt_charset_mode", "exit_attribute_mode",
+    "exit_ca_mode", "exit_delete_mode", "exit_insert_mode", "exit_standout_mode",
+    "exit_underline_mode", "flash_screen", "form_feed", "from_status_line", "init_1string",
+    "init_2string", "init_3string", "init_file", "insert_character", "insert_line",
+    "insert_padding", "key_backspace", "key_catab", "key_clear", "key_ctab", "key_dc", "key_dl",
+    "key_down", "key_eic", "key_eol", "key_eos", "key_f0", "key_f1", "key_f10", "key_f2", "key_f3",
+    "key_f4", "key_f5", "key_f6", "key_f7", "key_f8", "key_f9", "key_home", "key_ic", "key_il",
+    "key_left", "key_ll", "key_npage", "key_ppage", "key_right", "key_sf", "key_sr", "key_stab",
+    "key_up", "keypad_local", "keypad_xmit", "lab_f0", "lab_f1", "lab_f10", "lab_f2", "lab_f3",
+    "lab_f4", "lab_f5", "lab_f6", "lab_f7", "lab_f8", "lab_f9", "meta_off", "meta_on", "newline",
+    "pad_char", "parm_dch", "parm_delete_line", "parm_down_cursor", "parm_ich", "parm_index",
+    "parm_insert_line", "parm_left_cursor", "parm_right_cursor", "parm_rindex", "parm_up_cursor",
+    "pkey_key", "pkey_local", "pkey_xmit", "print_screen", "prtr_off", "prtr_on", "repeat_char",
+    "reset_1string", "reset_2string", "reset_3string", "reset_file", "restore_cursor",
+    "row_address", "save_cursor", "scroll_forward", "scroll_reverse", "set_attributes", "set_tab",
+    "set_window", "tab", "to_status_line", "underline_char", "up_half_line", "init_prog", "key_a1",
+    "key_a3", "key_b2", "key_c1", "key_c3", "prtr_non", "char_padding", "acs_chars", "plab_norm",
+    "key_btab", "enter_xon_mode", "exit_xon_mode", "enter_am_mode", "exit_am_mode", "xon_character",
+    "xoff_character", "ena_acs", "label_on", "label_off", "key_beg", "key_cancel", "key_close",
+    "key_command", "key_copy", "key_create", "key_end", "key_enter", "key_exit", "key_find",
+    "key_help", "key_mark", "key_message", "key_move", "key_next", "key_open", "key_options",
+    "key_previous", "key_print", "key_redo", "key_reference", "key_refresh", "key_replace",
+    "key_restart", "key_resume", "key_save", "key_suspend", "key_undo", "key_sbeg", "key_scancel",
+    "key_scommand", "key_scopy", "key_screate", "key_sdc", "key_sdl", "key_select", "key_send",
+    "key_seol", "key_sexit", "key_sfind", "key_shelp", "key_shome", "key_sic", "key_sleft",
+    "key_smessage", "key_smove", "key_snext", "key_soptions", "key_sprevious", "key_sprint",
+    "key_sredo", "key_sreplace", "key_sright", "key_srsume", "key_ssave", "key_ssuspend",
+    "key_sundo", "req_for_input", "key_f11", "key_f12", "key_f13", "key_f14", "key_f15", "key_f16",
+    "key_f17", "key_f18", "key_f19", "key_f20", "key_f21", "key_f22", "key_f23", "key_f24",
+    "key_f25", "key_f26", "key_f27", "key_f28", "key_f29", "key_f30", "key_f31", "key_f32",
+    "key_f33", "key_f34", "key_f35", "key_f36", "key_f37", "key_f38", "key_f39", "key_f40",
+    "key_f41", "key_f42", "key_f43", "key_f44", "key_f45", "key_f46", "key_f47", "key_f48",
+    "key_f49", "key_f50", "key_f51", "key_f52", "key_f53", "key_f54", "key_f55", "key_f56",
+    "key_f57", "key_f58", "key_f59", "key_f60", "key_f61", "key_f62", "key_f63", "clr_bol",
+    "clear_margins", "set_left_margin", "set_right_margin", "label_format", "set_clock",
+    "display_clock", "remove_clock", "create_window", "goto_window", "hangup", "dial_phone",
+    "quick_dial", "tone", "pulse", "flash_hook", "fixed_pause", "wait_tone", "user0", "user1",
+    "user2", "user3", "user4", "user5", "user6", "user7", "user8", "user9", "orig_pair",
+    "orig_colors", "initialize_color", "initialize_pair", "set_color_pair", "set_foreground",
+    "set_background", "change_char_pitch", "change_line_pitch", "change_res_horz",
+    "change_res_vert", "define_char", "enter_doublewide_mode", "enter_draft_quality",
+    "enter_italics_mode", "enter_leftward_mode", "enter_micro_mode", "enter_near_letter_quality",
+    "enter_normal_quality", "enter_shadow_mode", "enter_subscript_mode", "enter_superscript_mode",
+    "enter_upward_mode", "exit_doublewide_mode", "exit_italics_mode", "exit_leftward_mode",
+    "exit_micro_mode", "exit_shadow_mode", "exit_subscript_mode", "exit_superscript_mode",
+    "exit_upward_mode", "micro_column_address", "micro_down", "micro_left", "micro_right",
+    "micro_row_address", "micro_up", "order_of_pins", "parm_down_micro", "parm_left_micro",
+    "parm_right_micro", "parm_up_micro", "select_char_set", "set_bottom_margin",
+    "set_bottom_margin_parm", "set_left_margin_parm", "set_right_margin_parm", "set_top_margin",
+    "set_top_margin_parm", "start_bit_image", "start_char_set_def", "stop_bit_image",
+    "stop_char_set_def", "subscript_characters", "superscript_characters", "these_cause_cr",
+    "zero_motion", "char_set_names", "key_mouse", "mouse_info", "req_mouse_pos", "get_mouse",
+    "set_a_foreground", "set_a_background", "pkey_plab", "device_type", "code_set_init",
+    "set0_des_seq", "set1_des_seq", "set2_des_seq", "set3_des_seq", "set_lr_margin",
+    "set_tb_margin", "bit_image_repeat", "bit_image_newline", "bit_image_carriage_return",
+    "color_names", "define_bit_image_region", "end_bit_image_region", "set_color_band",
+    "set_page_length", "display_pc_char", "enter_pc_charset_mode", "exit_pc_charset_mode",
+    "enter_scancode_mode", "exit_scancode_mode", "pc_term_options", "scancode_escape",
+    "alt_scancode_esc", "enter_horizontal_hl_mode", "enter_left_hl_mode", "enter_low_hl_mode",
+    "enter_right_hl_mode", "enter_top_hl_mode", "enter_vertical_hl_mode", "set_a_attributes",
+    "set_pglen_inch", "termcap_init2", "termcap_reset", "linefeed_if_not_lf", "backspace_if_not_bs",
+    "other_non_function_keys", "arrow_key_map", "acs_ulcorner", "acs_llcorner", "acs_urcorner",
+    "acs_lrcorner", "acs_ltee", "acs_rtee", "acs_btee", "acs_ttee", "acs_hline", "acs_vline",
+    "acs_plus", "memory_lock", "memory_unlock", "box_chars_1"];
+
+#[rustfmt::skip]
+pub(crate) static stringnames: &[&str] = &[ "cbt", "_", "cr", "csr", "tbc", "clear",
+    "_", "_", "hpa", "cmdch", "cup", "cud1", "home", "civis", "cub1", "mrcup", "cnorm", "cuf1",
+    "ll", "cuu1", "cvvis", "dch1", "dl1", "dsl", "hd", "smacs", "blink", "bold", "smcup", "smdc",
+    "dim", "smir", "invis", "prot", "rev", "smso", "smul", "ech", "rmacs", "sgr0", "rmcup", "rmdc",
+    "rmir", "rmso", "rmul", "flash", "ff", "fsl", "is1", "is2", "is3", "if", "ich1", "il1", "ip",
+    "kbs", "ktbc", "kclr", "kctab", "_", "_", "kcud1", "_", "_", "_", "_", "_", "_", "_", "_", "_",
+    "_", "_", "_", "_", "_", "khome", "_", "_", "kcub1", "_", "knp", "kpp", "kcuf1", "_", "_",
+    "khts", "_", "rmkx", "smkx", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "rmm", "_",
+    "_", "pad", "dch", "dl", "cud", "ich", "indn", "il", "cub", "cuf", "rin", "cuu", "pfkey",
+    "pfloc", "pfx", "mc0", "mc4", "_", "rep", "rs1", "rs2", "rs3", "rf", "rc", "vpa", "sc", "ind",
+    "ri", "sgr", "_", "wind", "_", "tsl", "uc", "hu", "iprog", "_", "_", "_", "_", "_", "mc5p",
+    "rmp", "acsc", "pln", "kcbt", "smxon", "rmxon", "smam", "rmam", "xonc", "xoffc", "_", "smln",
+    "rmln", "_", "kcan", "kclo", "kcmd", "kcpy", "kcrt", "_", "kent", "kext", "kfnd", "khlp",
+    "kmrk", "kmsg", "kmov", "knxt", "kopn", "kopt", "kprv", "kprt", "krdo", "kref", "krfr", "krpl",
+    "krst", "kres", "ksav", "kspd", "kund", "kBEG", "kCAN", "kCMD", "kCPY", "kCRT", "_", "_",
+    "kslt", "kEND", "kEOL", "kEXT", "kFND", "kHLP", "kHOM", "_", "kLFT", "kMSG", "kMOV", "kNXT",
+    "kOPT", "kPRV", "kPRT", "kRDO", "kRPL", "kRIT", "kRES", "kSAV", "kSPD", "kUND", "rfi", "_", "_",
+    "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_",
+    "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_",
+    "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_",
+    "dclk", "rmclk", "cwin", "wingo", "_", "dial", "qdial", "_", "_", "hook", "pause", "wait", "_",
+    "_", "_", "_", "_", "_", "_", "_", "_", "_", "op", "oc", "initc", "initp", "scp", "setf",
+    "setb", "cpi", "lpi", "chr", "cvr", "defc", "swidm", "sdrfq", "sitm", "slm", "smicm", "snlq",
+    "snrmq", "sshm", "ssubm", "ssupm", "sum", "rwidm", "ritm", "rlm", "rmicm", "rshm", "rsubm",
+    "rsupm", "rum", "mhpa", "mcud1", "mcub1", "mcuf1", "mvpa", "mcuu1", "porder", "mcud", "mcub",
+    "mcuf", "mcuu", "scs", "smgb", "smgbp", "smglp", "smgrp", "smgt", "smgtp", "sbim", "scsd",
+    "rbim", "rcsd", "subcs", "supcs", "docr", "zerom", "csnm", "kmous", "minfo", "reqmp", "getm",
+    "setaf", "setab", "pfxl", "devt", "csin", "s0ds", "s1ds", "s2ds", "s3ds", "smglr", "smgtb",
+    "birep", "binel", "bicr", "colornm", "defbi", "endbi", "setcolor", "slines", "dispc", "smpch",
+    "rmpch", "smsc", "rmsc", "pctrm", "scesc", "scesa", "ehhlm", "elhlm", "elohlm", "erhlm",
+    "ethlm", "evhlm", "sgr1", "slength", "OTi2", "OTrs", "OTnl", "OTbs", "OTko", "OTma", "OTG2",
+    "OTG3", "OTG1", "OTG4", "OTGR", "OTGL", "OTGU", "OTGD", "OTGH", "OTGV", "OTGC", "meml", "memu",
+    "box1"];
+
+fn read_le_u16(r: &mut dyn io::Read) -> io::Result<u16> {
+    let mut b = [0; 2];
+    r.read_exact(&mut b)?;
+    Ok((b[0] as u16) | ((b[1] as u16) << 8))
+}
+
+fn read_le_u32(r: &mut dyn io::Read) -> io::Result<u32> {
+    let mut b = [0; 4];
+    r.read_exact(&mut b)?;
+    Ok((b[0] as u32) | ((b[1] as u32) << 8) | ((b[2] as u32) << 16) | ((b[3] as u32) << 24))
+}
+
+fn read_byte(r: &mut dyn io::Read) -> io::Result<u8> {
+    match r.bytes().next() {
+        Some(s) => s,
+        None => Err(io::Error::new(io::ErrorKind::Other, "end of file")),
+    }
+}
+
+/// Parse a compiled terminfo entry, using long capability names if `longnames`
+/// is true
+pub(crate) fn parse(file: &mut dyn io::Read, longnames: bool) -> Result<TermInfo, String> {
+    macro_rules! t( ($e:expr) => (
+        match $e {
+            Ok(e) => e,
+            Err(e) => return Err(e.to_string())
+        }
+    ) );
+
+    let (bnames, snames, nnames) = if longnames {
+        (boolfnames, stringfnames, numfnames)
+    } else {
+        (boolnames, stringnames, numnames)
+    };
+
+    // Check magic number
+    let magic = t!(read_le_u16(file));
+
+    let extended = match magic {
+        0o0432 => false,
+        0o01036 => true,
+        _ => return Err(format!("invalid magic number, found {:o}", magic)),
+    };
+
+    // According to the spec, these fields must be >= -1 where -1 means that the feature is not
+    // supported. Using 0 instead of -1 works because we skip sections with length 0.
+    macro_rules! read_nonneg {
+        () => {{
+            match t!(read_le_u16(file)) as i16 {
+                n if n >= 0 => n as usize,
+                -1 => 0,
+                _ => return Err("incompatible file: length fields must be  >= -1".to_string()),
+            }
+        }};
+    }
+
+    let names_bytes = read_nonneg!();
+    let bools_bytes = read_nonneg!();
+    let numbers_count = read_nonneg!();
+    let string_offsets_count = read_nonneg!();
+    let string_table_bytes = read_nonneg!();
+
+    if names_bytes == 0 {
+        return Err("incompatible file: names field must be at least 1 byte wide".to_string());
+    }
+
+    if bools_bytes > boolnames.len() {
+        return Err("incompatible file: more booleans than expected".to_string());
+    }
+
+    if numbers_count > numnames.len() {
+        return Err("incompatible file: more numbers than expected".to_string());
+    }
+
+    if string_offsets_count > stringnames.len() {
+        return Err("incompatible file: more string offsets than expected".to_string());
+    }
+
+    // don't read NUL
+    let mut bytes = Vec::new();
+    t!(file.take((names_bytes - 1) as u64).read_to_end(&mut bytes));
+    let names_str = match String::from_utf8(bytes) {
+        Ok(s) => s,
+        Err(_) => return Err("input not utf-8".to_string()),
+    };
+
+    let term_names: Vec<String> = names_str.split('|').map(|s| s.to_string()).collect();
+    // consume NUL
+    if t!(read_byte(file)) != b'\0' {
+        return Err("incompatible file: missing null terminator for names section".to_string());
+    }
+
+    let bools_map: HashMap<String, bool> = t! {
+        (0..bools_bytes).filter_map(|i| match read_byte(file) {
+            Err(e) => Some(Err(e)),
+            Ok(1) => Some(Ok((bnames[i].to_string(), true))),
+            Ok(_) => None
+        }).collect()
+    };
+
+    if (bools_bytes + names_bytes) % 2 == 1 {
+        t!(read_byte(file)); // compensate for padding
+    }
+
+    let numbers_map: HashMap<String, u32> = t! {
+        (0..numbers_count).filter_map(|i| {
+            let number = if extended { read_le_u32(file) } else { read_le_u16(file).map(Into::into) };
+
+            match number {
+                Ok(0xFFFF) => None,
+                Ok(n) => Some(Ok((nnames[i].to_string(), n))),
+                Err(e) => Some(Err(e))
+            }
+        }).collect()
+    };
+
+    let string_map: HashMap<String, Vec<u8>> = if string_offsets_count > 0 {
+        let string_offsets: Vec<u16> =
+            t!((0..string_offsets_count).map(|_| read_le_u16(file)).collect());
+
+        let mut string_table = Vec::new();
+        t!(file.take(string_table_bytes as u64).read_to_end(&mut string_table));
+
+        t!(string_offsets
+            .into_iter()
+            .enumerate()
+            .filter(|&(_, offset)| {
+                // non-entry
+                offset != 0xFFFF
+            })
+            .map(|(i, offset)| {
+                let offset = offset as usize;
+
+                let name = if snames[i] == "_" { stringfnames[i] } else { snames[i] };
+
+                if offset == 0xFFFE {
+                    // undocumented: FFFE indicates cap@, which means the capability is not present
+                    // unsure if the handling for this is correct
+                    return Ok((name.to_string(), Vec::new()));
+                }
+
+                // Find the offset of the NUL we want to go to
+                let nulpos = string_table[offset..string_table_bytes].iter().position(|&b| b == 0);
+                match nulpos {
+                    Some(len) => {
+                        Ok((name.to_string(), string_table[offset..offset + len].to_vec()))
+                    }
+                    None => Err("invalid file: missing NUL in string_table".to_string()),
+                }
+            })
+            .collect())
+    } else {
+        HashMap::new()
+    };
+
+    // And that's all there is to it
+    Ok(TermInfo { names: term_names, bools: bools_map, numbers: numbers_map, strings: string_map })
+}
+
+/// Creates a dummy TermInfo struct for msys terminals
+pub(crate) fn msys_terminfo() -> TermInfo {
+    let mut strings = HashMap::new();
+    strings.insert("sgr0".to_string(), b"\x1B[0m".to_vec());
+    strings.insert("bold".to_string(), b"\x1B[1m".to_vec());
+    strings.insert("setaf".to_string(), b"\x1B[3%p1%dm".to_vec());
+    strings.insert("setab".to_string(), b"\x1B[4%p1%dm".to_vec());
+
+    let mut numbers = HashMap::new();
+    numbers.insert("colors".to_string(), 8);
+
+    TermInfo {
+        names: vec!["cygwin".to_string()], // msys is a fork of an older cygwin version
+        bools: HashMap::new(),
+        numbers,
+        strings,
+    }
+}
diff --git a/library/test/src/term/terminfo/parser/compiled/tests.rs b/library/test/src/term/terminfo/parser/compiled/tests.rs
new file mode 100644 (file)
index 0000000..8a9187b
--- /dev/null
@@ -0,0 +1,8 @@
+use super::*;
+
+#[test]
+fn test_veclens() {
+    assert_eq!(boolfnames.len(), boolnames.len());
+    assert_eq!(numfnames.len(), numnames.len());
+    assert_eq!(stringfnames.len(), stringnames.len());
+}
diff --git a/library/test/src/term/terminfo/searcher.rs b/library/test/src/term/terminfo/searcher.rs
new file mode 100644 (file)
index 0000000..68e181a
--- /dev/null
@@ -0,0 +1,69 @@
+//! ncurses-compatible database discovery.
+//!
+//! Does not support hashed database, only filesystem!
+
+use std::env;
+use std::fs;
+use std::path::PathBuf;
+
+#[cfg(test)]
+mod tests;
+
+/// Return path to database entry for `term`
+#[allow(deprecated)]
+pub(crate) fn get_dbpath_for_term(term: &str) -> Option<PathBuf> {
+    let mut dirs_to_search = Vec::new();
+    let first_char = term.chars().next()?;
+
+    // Find search directory
+    if let Some(dir) = env::var_os("TERMINFO") {
+        dirs_to_search.push(PathBuf::from(dir));
+    }
+
+    if let Ok(dirs) = env::var("TERMINFO_DIRS") {
+        for i in dirs.split(':') {
+            if i == "" {
+                dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
+            } else {
+                dirs_to_search.push(PathBuf::from(i));
+            }
+        }
+    } else {
+        // Found nothing in TERMINFO_DIRS, use the default paths:
+        // According to  /etc/terminfo/README, after looking at
+        // ~/.terminfo, ncurses will search /etc/terminfo, then
+        // /lib/terminfo, and eventually /usr/share/terminfo.
+        // On Haiku the database can be found at /boot/system/data/terminfo
+        if let Some(mut homedir) = env::home_dir() {
+            homedir.push(".terminfo");
+            dirs_to_search.push(homedir)
+        }
+
+        dirs_to_search.push(PathBuf::from("/etc/terminfo"));
+        dirs_to_search.push(PathBuf::from("/lib/terminfo"));
+        dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
+        dirs_to_search.push(PathBuf::from("/boot/system/data/terminfo"));
+    }
+
+    // Look for the terminal in all of the search directories
+    for mut p in dirs_to_search {
+        if fs::metadata(&p).is_ok() {
+            p.push(&first_char.to_string());
+            p.push(&term);
+            if fs::metadata(&p).is_ok() {
+                return Some(p);
+            }
+            p.pop();
+            p.pop();
+
+            // on some installations the dir is named after the hex of the char
+            // (e.g., macOS)
+            p.push(&format!("{:x}", first_char as usize));
+            p.push(term);
+            if fs::metadata(&p).is_ok() {
+                return Some(p);
+            }
+        }
+    }
+    None
+}
diff --git a/library/test/src/term/terminfo/searcher/tests.rs b/library/test/src/term/terminfo/searcher/tests.rs
new file mode 100644 (file)
index 0000000..4227a58
--- /dev/null
@@ -0,0 +1,19 @@
+use super::*;
+
+#[test]
+#[ignore = "buildbots don't have ncurses installed and I can't mock everything I need"]
+fn test_get_dbpath_for_term() {
+    // woefully inadequate test coverage
+    // note: current tests won't work with non-standard terminfo hierarchies (e.g., macOS's)
+    use std::env;
+    // FIXME (#9639): This needs to handle non-utf8 paths
+    fn x(t: &str) -> String {
+        let p = get_dbpath_for_term(t).expect("no terminfo entry found");
+        p.to_str().unwrap().to_string()
+    }
+    assert!(x("screen") == "/usr/share/terminfo/s/screen");
+    assert!(get_dbpath_for_term("") == None);
+    env::set_var("TERMINFO_DIRS", ":");
+    assert!(x("screen") == "/usr/share/terminfo/s/screen");
+    env::remove_var("TERMINFO_DIRS");
+}
diff --git a/library/test/src/term/win.rs b/library/test/src/term/win.rs
new file mode 100644 (file)
index 0000000..4bdbd6e
--- /dev/null
@@ -0,0 +1,170 @@
+//! Windows console handling
+
+// FIXME (#13400): this is only a tiny fraction of the Windows console api
+
+use std::io;
+use std::io::prelude::*;
+
+use super::color;
+use super::Terminal;
+
+/// A Terminal implementation that uses the Win32 Console API.
+pub(crate) struct WinConsole<T> {
+    buf: T,
+    def_foreground: color::Color,
+    def_background: color::Color,
+    foreground: color::Color,
+    background: color::Color,
+}
+
+type SHORT = i16;
+type WORD = u16;
+type DWORD = u32;
+type BOOL = i32;
+type HANDLE = *mut u8;
+
+#[allow(non_snake_case)]
+#[repr(C)]
+struct SMALL_RECT {
+    Left: SHORT,
+    Top: SHORT,
+    Right: SHORT,
+    Bottom: SHORT,
+}
+
+#[allow(non_snake_case)]
+#[repr(C)]
+struct COORD {
+    X: SHORT,
+    Y: SHORT,
+}
+
+#[allow(non_snake_case)]
+#[repr(C)]
+struct CONSOLE_SCREEN_BUFFER_INFO {
+    dwSize: COORD,
+    dwCursorPosition: COORD,
+    wAttributes: WORD,
+    srWindow: SMALL_RECT,
+    dwMaximumWindowSize: COORD,
+}
+
+#[allow(non_snake_case)]
+#[link(name = "kernel32")]
+extern "system" {
+    fn SetConsoleTextAttribute(handle: HANDLE, attr: WORD) -> BOOL;
+    fn GetStdHandle(which: DWORD) -> HANDLE;
+    fn GetConsoleScreenBufferInfo(handle: HANDLE, info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> BOOL;
+}
+
+fn color_to_bits(color: color::Color) -> u16 {
+    // magic numbers from mingw-w64's wincon.h
+
+    let bits = match color % 8 {
+        color::BLACK => 0,
+        color::BLUE => 0x1,
+        color::GREEN => 0x2,
+        color::RED => 0x4,
+        color::YELLOW => 0x2 | 0x4,
+        color::MAGENTA => 0x1 | 0x4,
+        color::CYAN => 0x1 | 0x2,
+        color::WHITE => 0x1 | 0x2 | 0x4,
+        _ => unreachable!(),
+    };
+
+    if color >= 8 { bits | 0x8 } else { bits }
+}
+
+fn bits_to_color(bits: u16) -> color::Color {
+    let color = match bits & 0x7 {
+        0 => color::BLACK,
+        0x1 => color::BLUE,
+        0x2 => color::GREEN,
+        0x4 => color::RED,
+        0x6 => color::YELLOW,
+        0x5 => color::MAGENTA,
+        0x3 => color::CYAN,
+        0x7 => color::WHITE,
+        _ => unreachable!(),
+    };
+
+    color | (u32::from(bits) & 0x8) // copy the hi-intensity bit
+}
+
+impl<T: Write + Send + 'static> WinConsole<T> {
+    fn apply(&mut self) {
+        let _unused = self.buf.flush();
+        let mut accum: WORD = 0;
+        accum |= color_to_bits(self.foreground);
+        accum |= color_to_bits(self.background) << 4;
+
+        unsafe {
+            // Magic -11 means stdout, from
+            // https://docs.microsoft.com/en-us/windows/console/getstdhandle
+            //
+            // You may be wondering, "but what about stderr?", and the answer
+            // to that is that setting terminal attributes on the stdout
+            // handle also sets them for stderr, since they go to the same
+            // terminal! Admittedly, this is fragile, since stderr could be
+            // redirected to a different console. This is good enough for
+            // rustc though. See #13400.
+            let out = GetStdHandle(-11i32 as DWORD);
+            SetConsoleTextAttribute(out, accum);
+        }
+    }
+
+    /// Returns `None` whenever the terminal cannot be created for some reason.
+    pub(crate) fn new(out: T) -> io::Result<WinConsole<T>> {
+        use std::mem::MaybeUninit;
+
+        let fg;
+        let bg;
+        unsafe {
+            let mut buffer_info = MaybeUninit::<CONSOLE_SCREEN_BUFFER_INFO>::uninit();
+            if GetConsoleScreenBufferInfo(GetStdHandle(-11i32 as DWORD), buffer_info.as_mut_ptr())
+                != 0
+            {
+                let buffer_info = buffer_info.assume_init();
+                fg = bits_to_color(buffer_info.wAttributes);
+                bg = bits_to_color(buffer_info.wAttributes >> 4);
+            } else {
+                fg = color::WHITE;
+                bg = color::BLACK;
+            }
+        }
+        Ok(WinConsole {
+            buf: out,
+            def_foreground: fg,
+            def_background: bg,
+            foreground: fg,
+            background: bg,
+        })
+    }
+}
+
+impl<T: Write> Write for WinConsole<T> {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.buf.write(buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        self.buf.flush()
+    }
+}
+
+impl<T: Write + Send + 'static> Terminal for WinConsole<T> {
+    fn fg(&mut self, color: color::Color) -> io::Result<bool> {
+        self.foreground = color;
+        self.apply();
+
+        Ok(true)
+    }
+
+    fn reset(&mut self) -> io::Result<bool> {
+        self.foreground = self.def_foreground;
+        self.background = self.def_background;
+        self.apply();
+
+        Ok(true)
+    }
+}
index 5a4a540b04eb04c92eb2a0b4b8c092194ac65770..794f72770047646780b7478956dd2e74979f8c4c 100644 (file)
@@ -61,9 +61,7 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
                 ignore: true,
                 should_panic: ShouldPanic::No,
                 allow_fail: false,
-                #[cfg(not(bootstrap))]
                 compile_fail: false,
-                #[cfg(not(bootstrap))]
                 no_run: false,
                 test_type: TestType::Unknown,
             },
@@ -75,9 +73,7 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
                 ignore: false,
                 should_panic: ShouldPanic::No,
                 allow_fail: false,
-                #[cfg(not(bootstrap))]
                 compile_fail: false,
-                #[cfg(not(bootstrap))]
                 no_run: false,
                 test_type: TestType::Unknown,
             },
@@ -97,9 +93,7 @@ pub fn do_not_run_ignored_tests() {
             ignore: true,
             should_panic: ShouldPanic::No,
             allow_fail: false,
-            #[cfg(not(bootstrap))]
             compile_fail: false,
-            #[cfg(not(bootstrap))]
             no_run: false,
             test_type: TestType::Unknown,
         },
@@ -120,9 +114,7 @@ pub fn ignored_tests_result_in_ignored() {
             ignore: true,
             should_panic: ShouldPanic::No,
             allow_fail: false,
-            #[cfg(not(bootstrap))]
             compile_fail: false,
-            #[cfg(not(bootstrap))]
             no_run: false,
             test_type: TestType::Unknown,
         },
@@ -147,9 +139,7 @@ fn test_should_panic() {
             ignore: false,
             should_panic: ShouldPanic::Yes,
             allow_fail: false,
-            #[cfg(not(bootstrap))]
             compile_fail: false,
-            #[cfg(not(bootstrap))]
             no_run: false,
             test_type: TestType::Unknown,
         },
@@ -174,9 +164,7 @@ fn test_should_panic_good_message() {
             ignore: false,
             should_panic: ShouldPanic::YesWithMessage("error message"),
             allow_fail: false,
-            #[cfg(not(bootstrap))]
             compile_fail: false,
-            #[cfg(not(bootstrap))]
             no_run: false,
             test_type: TestType::Unknown,
         },
@@ -206,9 +194,7 @@ fn test_should_panic_bad_message() {
             ignore: false,
             should_panic: ShouldPanic::YesWithMessage(expected),
             allow_fail: false,
-            #[cfg(not(bootstrap))]
             compile_fail: false,
-            #[cfg(not(bootstrap))]
             no_run: false,
             test_type: TestType::Unknown,
         },
@@ -242,9 +228,7 @@ fn test_should_panic_non_string_message_type() {
             ignore: false,
             should_panic: ShouldPanic::YesWithMessage(expected),
             allow_fail: false,
-            #[cfg(not(bootstrap))]
             compile_fail: false,
-            #[cfg(not(bootstrap))]
             no_run: false,
             test_type: TestType::Unknown,
         },
@@ -270,9 +254,7 @@ fn test_should_panic_but_succeeds() {
                 ignore: false,
                 should_panic,
                 allow_fail: false,
-                #[cfg(not(bootstrap))]
                 compile_fail: false,
-                #[cfg(not(bootstrap))]
                 no_run: false,
                 test_type: TestType::Unknown,
             },
@@ -306,9 +288,7 @@ fn report_time_test_template(report_time: bool) -> Option<TestExecTime> {
             ignore: false,
             should_panic: ShouldPanic::No,
             allow_fail: false,
-            #[cfg(not(bootstrap))]
             compile_fail: false,
-            #[cfg(not(bootstrap))]
             no_run: false,
             test_type: TestType::Unknown,
         },
@@ -343,9 +323,7 @@ fn time_test_failure_template(test_type: TestType) -> TestResult {
             ignore: false,
             should_panic: ShouldPanic::No,
             allow_fail: false,
-            #[cfg(not(bootstrap))]
             compile_fail: false,
-            #[cfg(not(bootstrap))]
             no_run: false,
             test_type,
         },
@@ -384,9 +362,7 @@ fn typed_test_desc(test_type: TestType) -> TestDesc {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
-        #[cfg(not(bootstrap))]
         compile_fail: false,
-        #[cfg(not(bootstrap))]
         no_run: false,
         test_type,
     }
@@ -499,9 +475,7 @@ pub fn exclude_should_panic_option() {
             ignore: false,
             should_panic: ShouldPanic::Yes,
             allow_fail: false,
-            #[cfg(not(bootstrap))]
             compile_fail: false,
-            #[cfg(not(bootstrap))]
             no_run: false,
             test_type: TestType::Unknown,
         },
@@ -525,9 +499,7 @@ pub fn exact_filter_match() {
                     ignore: false,
                     should_panic: ShouldPanic::No,
                     allow_fail: false,
-                    #[cfg(not(bootstrap))]
                     compile_fail: false,
-                    #[cfg(not(bootstrap))]
                     no_run: false,
                     test_type: TestType::Unknown,
                 },
@@ -621,9 +593,7 @@ pub fn sort_tests() {
                     ignore: false,
                     should_panic: ShouldPanic::No,
                     allow_fail: false,
-                    #[cfg(not(bootstrap))]
                     compile_fail: false,
-                    #[cfg(not(bootstrap))]
                     no_run: false,
                     test_type: TestType::Unknown,
                 },
@@ -702,9 +672,7 @@ pub fn test_bench_no_iter() {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
-        #[cfg(not(bootstrap))]
         compile_fail: false,
-        #[cfg(not(bootstrap))]
         no_run: false,
         test_type: TestType::Unknown,
     };
@@ -726,9 +694,7 @@ pub fn test_bench_iter() {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
-        #[cfg(not(bootstrap))]
         compile_fail: false,
-        #[cfg(not(bootstrap))]
         no_run: false,
         test_type: TestType::Unknown,
     };
@@ -744,9 +710,7 @@ fn should_sort_failures_before_printing_them() {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
-        #[cfg(not(bootstrap))]
         compile_fail: false,
-        #[cfg(not(bootstrap))]
         no_run: false,
         test_type: TestType::Unknown,
     };
@@ -756,9 +720,7 @@ fn should_sort_failures_before_printing_them() {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
-        #[cfg(not(bootstrap))]
         compile_fail: false,
-        #[cfg(not(bootstrap))]
         no_run: false,
         test_type: TestType::Unknown,
     };
index 63907c71ea7cc618b9d08602d4a51c41f32d6b66..3512a57e8e4ae59254e5c5b6fed3c7303bf925ed 100644 (file)
@@ -124,9 +124,7 @@ pub struct TestDesc {
     pub ignore: bool,
     pub should_panic: options::ShouldPanic,
     pub allow_fail: bool,
-    #[cfg(not(bootstrap))]
     pub compile_fail: bool,
-    #[cfg(not(bootstrap))]
     pub no_run: bool,
     pub test_type: TestType,
 }
@@ -147,7 +145,6 @@ impl TestDesc {
 
     /// Returns None for ignored test or that that are just run, otherwise give a description of the type of test.
     /// Descriptions include "should panic", "compile fail" and "compile".
-    #[cfg(not(bootstrap))]
     pub fn test_mode(&self) -> Option<&'static str> {
         if self.ignore {
             return None;
@@ -169,11 +166,6 @@ impl TestDesc {
         }
         None
     }
-
-    #[cfg(bootstrap)]
-    pub fn test_mode(&self) -> Option<&'static str> {
-        None
-    }
 }
 
 #[derive(Debug)]
index c76ba7667d4e67d874414b7fc1e58d7eb9063869..031d2942c51adf9a8287494ee9aa24bda33f3058 100644 (file)
@@ -21,7 +21,7 @@ compiler_builtins = "0.1.0"
 cfg-if = "0.1.8"
 
 [build-dependencies]
-cc = "1.0.68"
+cc = "1.0.69"
 
 [features]
 
index 8445d811e0f393f2f26d7a7757968cbbb10ae842..64f022b4e8daec7b00395b5475311658dd8c1418 100644 (file)
@@ -40,7 +40,7 @@ cmake = "0.1.38"
 filetime = "0.2"
 num_cpus = "1.0"
 getopts = "0.2.19"
-cc = "1.0.68"
+cc = "1.0.69"
 libc = "0.2"
 serde = { version = "1.0.8", features = ["derive"] }
 serde_json = "1.0.2"
@@ -48,8 +48,9 @@ toml = "0.5"
 lazy_static = "1.3.0"
 time = "0.1"
 ignore = "0.4.10"
-opener = "0.4"
+opener = "0.5"
 merge = "0.1.0"
+once_cell = "1.7.2"
 
 [target.'cfg(windows)'.dependencies.winapi]
 version = "0.3"
index 7c7f162b82c04b43c586df3849d552d32471764a..d2cf929aa266f82a0b9618b68aa528a92a7de65c 100644 (file)
@@ -77,7 +77,7 @@ def download(path, url, probably_big, verbose):
 def _download(path, url, probably_big, verbose, exception):
     if probably_big or verbose:
         print("downloading {}".format(url))
-    # see http://serverfault.com/questions/301128/how-to-download
+    # see https://serverfault.com/questions/301128/how-to-download
     if sys.platform == 'win32':
         run(["PowerShell.exe", "/nologo", "-Command",
              "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;",
@@ -138,7 +138,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None):
     shutil.rmtree(os.path.join(dst, fname))
 
 
-def run(args, verbose=False, exception=False, **kwargs):
+def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs):
     """Run a child program in a new process"""
     if verbose:
         print("running: " + ' '.join(args))
@@ -151,7 +151,14 @@ def run(args, verbose=False, exception=False, **kwargs):
         err = "failed to run: " + ' '.join(args)
         if verbose or exception:
             raise RuntimeError(err)
-        sys.exit(err)
+        # For most failures, we definitely do want to print this error, or the user will have no
+        # idea what went wrong. But when we've successfully built bootstrap and it failed, it will
+        # have already printed an error above, so there's no need to print the exact command we're
+        # running.
+        if is_bootstrap:
+            sys.exit(1)
+        else:
+            sys.exit(err)
 
 
 def require(cmd, exit=True):
@@ -573,7 +580,13 @@ class RustBuild(object):
         if ostype != "Linux":
             return
 
-        if not os.path.exists("/etc/NIXOS"):
+        # Use `/etc/os-release` instead of `/etc/NIXOS`.
+        # The latter one does not exist on NixOS when using tmpfs as root.
+        try:
+            with open("/etc/os-release", "r") as f:
+                if not any(line.strip() == "ID=nixos" for line in f):
+                    return
+        except FileNotFoundError:
             return
         if os.path.exists("/lib"):
             return
@@ -982,39 +995,40 @@ class RustBuild(object):
         slow_submodules = self.get_toml('fast-submodules') == "false"
         start_time = time()
         if slow_submodules:
-            print('Unconditionally updating all submodules')
+            print('Unconditionally updating submodules')
         else:
             print('Updating only changed submodules')
         default_encoding = sys.getdefaultencoding()
-        submodules = [s.split(' ', 1)[1] for s in subprocess.check_output(
-            ["git", "config", "--file",
-             os.path.join(self.rust_root, ".gitmodules"),
-             "--get-regexp", "path"]
-        ).decode(default_encoding).splitlines()]
+        # Only update submodules that are needed to build bootstrap.  These are needed because Cargo
+        # currently requires everything in a workspace to be "locally present" when starting a
+        # build, and will give a hard error if any Cargo.toml files are missing.
+        # FIXME: Is there a way to avoid cloning these eagerly? Bootstrap itself doesn't need to
+        #   share a workspace with any tools - maybe it could be excluded from the workspace?
+        #   That will still require cloning the submodules the second you check the standard
+        #   library, though...
+        # FIXME: Is there a way to avoid hard-coding the submodules required?
+        # WARNING: keep this in sync with the submodules hard-coded in bootstrap/lib.rs
+        submodules = [
+            "src/tools/rust-installer",
+            "src/tools/cargo",
+            "src/tools/rls",
+            "src/tools/miri",
+            "library/backtrace",
+            "library/stdarch"
+        ]
         filtered_submodules = []
         submodules_names = []
-        llvm_checked_out = os.path.exists(os.path.join(self.rust_root, "src/llvm-project/.git"))
-        external_llvm_provided = self.get_toml('llvm-config') or self.downloading_llvm()
-        llvm_needed = not self.get_toml('codegen-backends', 'rust') \
-            or "llvm" in self.get_toml('codegen-backends', 'rust')
         for module in submodules:
-            if module.endswith("llvm-project"):
-                # Don't sync the llvm-project submodule if an external LLVM was
-                # provided, if we are downloading LLVM or if the LLVM backend is
-                # not being built. Also, if the submodule has been initialized
-                # already, sync it anyways so that it doesn't mess up contributor
-                # pull requests.
-                if external_llvm_provided or not llvm_needed:
-                    if self.get_toml('lld') != 'true' and not llvm_checked_out:
-                        continue
             check = self.check_submodule(module, slow_submodules)
             filtered_submodules.append((module, check))
             submodules_names.append(module)
         recorded = subprocess.Popen(["git", "ls-tree", "HEAD"] + submodules_names,
                                     cwd=self.rust_root, stdout=subprocess.PIPE)
         recorded = recorded.communicate()[0].decode(default_encoding).strip().splitlines()
+        # { filename: hash }
         recorded_submodules = {}
         for data in recorded:
+            # [mode, kind, hash, filename]
             data = data.split()
             recorded_submodules[data[3]] = data[2]
         for module in filtered_submodules:
@@ -1178,7 +1192,7 @@ def bootstrap(help_triggered):
         env["BOOTSTRAP_CONFIG"] = toml_path
     if build.rustc_commit is not None:
         env["BOOTSTRAP_DOWNLOAD_RUSTC"] = '1'
-    run(args, env=env, verbose=build.verbose)
+    run(args, env=env, verbose=build.verbose, is_bootstrap=True)
 
 
 def main():
index bc499fdba5996379d74b4926102d371705d77684..56ecc6e68a98c8af8f1f233985b06ab89c84ab5f 100644 (file)
@@ -29,6 +29,8 @@ use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir};
 use crate::{Build, DocTests, GitRepo, Mode};
 
 pub use crate::Compiler;
+// FIXME: replace with std::lazy after it gets stabilized and reaches beta
+use once_cell::sync::Lazy;
 
 pub struct Builder<'a> {
     pub build: &'a Build,
@@ -195,7 +197,7 @@ impl StepDescription {
 
         if paths.is_empty() || builder.config.include_default_paths {
             for (desc, should_run) in v.iter().zip(&should_runs) {
-                if desc.default && should_run.is_really_default {
+                if desc.default && should_run.is_really_default() {
                     for pathset in &should_run.paths {
                         desc.maybe_run(builder, pathset);
                     }
@@ -228,7 +230,11 @@ impl StepDescription {
     }
 }
 
-#[derive(Clone)]
+enum ReallyDefault<'a> {
+    Bool(bool),
+    Lazy(Lazy<bool, Box<dyn Fn() -> bool + 'a>>),
+}
+
 pub struct ShouldRun<'a> {
     pub builder: &'a Builder<'a>,
     // use a BTreeSet to maintain sort order
@@ -236,7 +242,7 @@ pub struct ShouldRun<'a> {
 
     // If this is a default rule, this is an additional constraint placed on
     // its run. Generally something like compiler docs being enabled.
-    is_really_default: bool,
+    is_really_default: ReallyDefault<'a>,
 }
 
 impl<'a> ShouldRun<'a> {
@@ -244,15 +250,27 @@ impl<'a> ShouldRun<'a> {
         ShouldRun {
             builder,
             paths: BTreeSet::new(),
-            is_really_default: true, // by default no additional conditions
+            is_really_default: ReallyDefault::Bool(true), // by default no additional conditions
         }
     }
 
     pub fn default_condition(mut self, cond: bool) -> Self {
-        self.is_really_default = cond;
+        self.is_really_default = ReallyDefault::Bool(cond);
+        self
+    }
+
+    pub fn lazy_default_condition(mut self, lazy_cond: Box<dyn Fn() -> bool + 'a>) -> Self {
+        self.is_really_default = ReallyDefault::Lazy(Lazy::new(lazy_cond));
         self
     }
 
+    pub fn is_really_default(&self) -> bool {
+        match &self.is_really_default {
+            ReallyDefault::Bool(val) => *val,
+            ReallyDefault::Lazy(lazy) => *lazy.deref(),
+        }
+    }
+
     /// Indicates it should run if the command-line selects the given crate or
     /// any of its (local) dependencies.
     ///
@@ -432,6 +450,7 @@ impl<'a> Builder<'a> {
                 test::RustdocTheme,
                 test::RustdocUi,
                 test::RustdocJson,
+                test::HtmlCheck,
                 // Run bootstrap close to the end as it's unlikely to fail
                 test::Bootstrap,
                 // Run run-make last, since these won't pass without make on Windows
@@ -446,6 +465,7 @@ impl<'a> Builder<'a> {
                 doc::Std,
                 doc::Rustc,
                 doc::Rustdoc,
+                doc::Rustfmt,
                 doc::ErrorIndex,
                 doc::Nomicon,
                 doc::Reference,
index 4d7c207e3ab8b3cfe60b8c33b52e8e1c3101531b..e7fb8c0d4d5d20357d85afdb462ad3dbc69c7d39 100644 (file)
@@ -613,9 +613,14 @@ mod dist {
         // Note that the stages here are +1 than what they actually are because
         // Rustdoc::run swaps out the compiler with stage minus 1 if --stage is
         // not 0.
+        //
+        // The stage 0 copy is the one downloaded for bootstrapping. It is
+        // (currently) needed to run "cargo test" on the linkchecker, and
+        // should be relatively "free".
         assert_eq!(
             first(builder.cache.all::<tool::Rustdoc>()),
             &[
+                tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } },
                 tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } },
                 tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },
             ]
index 5003d6693f72cf77c8175813c381c3df95080d5c..bc106746e57e06e0302fcbcce54988a11c407501 100644 (file)
@@ -7,7 +7,7 @@ use crate::config::TargetSelection;
 use crate::tool::{prepare_tool_cargo, SourceType};
 use crate::INTERNER;
 use crate::{Compiler, Mode, Subcommand};
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Std {
@@ -72,6 +72,8 @@ impl Step for Std {
     }
 
     fn run(self, builder: &Builder<'_>) {
+        builder.update_submodule(&Path::new("library").join("stdarch"));
+
         let target = self.target;
         let compiler = builder.compiler(builder.top_stage, builder.config.build);
 
index 112a6ea939869a47b34435c6e9d2e755999da2a5..78c9a25262243bca4be37e44f3aa990d26d5696f 100644 (file)
@@ -2,8 +2,8 @@
 //! library.
 //!
 //! This module contains some of the real meat in the rustbuild build system
-//! which is where Cargo is used to compiler the standard library, libtest, and
-//! compiler. This module is also responsible for assembling the sysroot as it
+//! which is where Cargo is used to compile the standard library, libtest, and
+//! the compiler. This module is also responsible for assembling the sysroot as it
 //! goes along from the output of the previous stage.
 
 use std::borrow::Cow;
@@ -79,6 +79,8 @@ impl Step for Std {
             return;
         }
 
+        builder.update_submodule(&Path::new("library").join("stdarch"));
+
         let mut target_deps = builder.ensure(StartupObjects { compiler, target });
 
         let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
@@ -1366,7 +1368,7 @@ pub fn stream_cargo(
 
     // Make sure Cargo actually succeeded after we read all of its stdout.
     let status = t!(child.wait());
-    if !status.success() {
+    if builder.is_verbose() && !status.success() {
         eprintln!(
             "command did not execute successfully: {:?}\n\
                   expected success, got: {}",
index 483816b98d689e34594df52e9a688017d4c2706b..4b3c25b02c2789ca327b318a6688e566e222b08c 100644 (file)
@@ -13,6 +13,7 @@ use std::path::{Path, PathBuf};
 use std::str::FromStr;
 
 use crate::cache::{Interned, INTERNER};
+use crate::channel::GitInfo;
 pub use crate::flags::Subcommand;
 use crate::flags::{Color, Flags};
 use crate::util::exe;
@@ -48,7 +49,7 @@ pub struct Config {
     /// Call Build::ninja() instead of this.
     pub ninja_in_file: bool,
     pub verbose: usize,
-    pub submodules: bool,
+    pub submodules: Option<bool>,
     pub fast_submodules: bool,
     pub compiler_docs: bool,
     pub docs_minification: bool,
@@ -552,7 +553,7 @@ impl Config {
         config.backtrace = true;
         config.rust_optimize = true;
         config.rust_optimize_tests = true;
-        config.submodules = true;
+        config.submodules = None;
         config.fast_submodules = true;
         config.docs = true;
         config.docs_minification = true;
@@ -658,11 +659,11 @@ impl Config {
         config.npm = build.npm.map(PathBuf::from);
         config.gdb = build.gdb.map(PathBuf::from);
         config.python = build.python.map(PathBuf::from);
+        config.submodules = build.submodules;
         set(&mut config.low_priority, build.low_priority);
         set(&mut config.compiler_docs, build.compiler_docs);
         set(&mut config.docs_minification, build.docs_minification);
         set(&mut config.docs, build.docs);
-        set(&mut config.submodules, build.submodules);
         set(&mut config.fast_submodules, build.fast_submodules);
         set(&mut config.locked_deps, build.locked_deps);
         set(&mut config.vendor, build.vendor);
@@ -792,8 +793,16 @@ impl Config {
 
                 // CI-built LLVM can be either dynamic or static.
                 let ci_llvm = config.out.join(&*config.build.triple).join("ci-llvm");
-                let link_type = t!(std::fs::read_to_string(ci_llvm.join("link-type.txt")));
-                config.llvm_link_shared = link_type == "dynamic";
+                config.llvm_link_shared = if config.dry_run {
+                    // just assume dynamic for now
+                    true
+                } else {
+                    let link_type = t!(
+                        std::fs::read_to_string(ci_llvm.join("link-type.txt")),
+                        format!("CI llvm missing: {}", ci_llvm.display())
+                    );
+                    link_type == "dynamic"
+                };
             }
 
             if config.llvm_thin_lto {
@@ -1075,6 +1084,10 @@ impl Config {
     pub fn llvm_enabled(&self) -> bool {
         self.rust_codegen_backends.contains(&INTERNER.intern_str("llvm"))
     }
+
+    pub fn submodules(&self, rust_info: &GitInfo) -> bool {
+        self.submodules.unwrap_or(rust_info.is_git())
+    }
 }
 
 fn set<T>(field: &mut T, val: Option<T>) {
index 999882a1c04b0526525c21f4600e3dc0830868fc..8d9f169e6c50d495f6ffa7461ec05fea57b9a559 100755 (executable)
@@ -160,6 +160,7 @@ o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of tw
 o("extended", "build.extended", "build an extended rust tool set")
 
 v("tools", None, "List of extended tools will be installed")
+v("codegen-backends", None, "List of codegen backends to build")
 v("build", "build.build", "GNUs ./configure syntax LLVM build triple")
 v("host", None, "GNUs ./configure syntax LLVM host triples")
 v("target", None, "GNUs ./configure syntax LLVM target triples")
@@ -339,6 +340,8 @@ for key in known_args:
         set('target.{}.llvm-filecheck'.format(build()), value)
     elif option.name == 'tools':
         set('build.tools', value.split(','))
+    elif option.name == 'codegen-backends':
+        set('rust.codegen-backends', value.split(','))
     elif option.name == 'host':
         set('build.host', value.split(','))
     elif option.name == 'target':
index 16d148db61814f3f14e104ad66f621fb1e4d6944..c37763243c0a55ab118318e3f8506f6decbcb568 100644 (file)
@@ -400,12 +400,12 @@ impl Step for Rustc {
 
             // Copy over lld if it's there
             if builder.config.lld_enabled {
-                let exe = exe("rust-lld", compiler.host);
-                builder.copy(&src_dir.join(&exe), &dst_dir.join(&exe));
+                let rust_lld = exe("rust-lld", compiler.host);
+                builder.copy(&src_dir.join(&rust_lld), &dst_dir.join(&rust_lld));
                 // for `-Z gcc-ld=lld`
                 let gcc_lld_dir = dst_dir.join("gcc-ld");
                 t!(fs::create_dir(&gcc_lld_dir));
-                builder.copy(&src_dir.join(&exe), &gcc_lld_dir.join(&exe));
+                builder.copy(&src_dir.join(&rust_lld), &gcc_lld_dir.join(exe("ld", compiler.host)));
             }
 
             // Copy over llvm-dwp if it's there
@@ -1033,13 +1033,7 @@ impl Step for Rls {
         let rls = builder
             .ensure(tool::Rls { compiler, target, extra_features: Vec::new() })
             .or_else(|| {
-                // We ignore failure on aarch64 Windows because RLS currently
-                // fails to build, due to winapi 0.2 not supporting aarch64.
-                missing_tool(
-                    "RLS",
-                    builder.build.config.missing_tools
-                        || (target.triple.contains("aarch64") && target.triple.contains("windows")),
-                );
+                missing_tool("RLS", builder.build.config.missing_tools);
                 None
             })?;
 
@@ -1961,8 +1955,16 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir
         cmd.arg("--libfiles");
         builder.verbose(&format!("running {:?}", cmd));
         let files = output(&mut cmd);
+        let build_llvm_out = &builder.llvm_out(builder.config.build);
+        let target_llvm_out = &builder.llvm_out(target);
         for file in files.trim_end().split(' ') {
-            builder.install(Path::new(file), dst_libdir, 0o644);
+            // If we're not using a custom LLVM, make sure we package for the target.
+            let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
+                target_llvm_out.join(relative_path)
+            } else {
+                PathBuf::from(file)
+            };
+            builder.install(&file, dst_libdir, 0o644);
         }
         !builder.config.dry_run
     } else {
index d2fabf9967f2fd654158fae1278eb0ab157ad626..9ec5d4d8ccdb49bcdde2f685177add55aa45642f 100644 (file)
@@ -22,8 +22,17 @@ use crate::config::{Config, TargetSelection};
 use crate::tool::{self, prepare_tool_cargo, SourceType, Tool};
 use crate::util::symlink_dir;
 
+macro_rules! submodule_helper {
+    ($path:expr, submodule) => {
+        $path
+    };
+    ($path:expr, submodule = $submodule:literal) => {
+        $submodule
+    };
+}
+
 macro_rules! book {
-    ($($name:ident, $path:expr, $book_name:expr;)+) => {
+    ($($name:ident, $path:expr, $book_name:expr $(, submodule $(= $submodule:literal)? )? ;)+) => {
         $(
             #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
         pub struct $name {
@@ -46,6 +55,10 @@ macro_rules! book {
             }
 
             fn run(self, builder: &Builder<'_>) {
+                $(
+                    let path = Path::new(submodule_helper!( $path, submodule $( = $submodule )? ));
+                    builder.update_submodule(&path);
+                )?
                 builder.ensure(RustbookSrc {
                     target: self.target,
                     name: INTERNER.intern_str($book_name),
@@ -59,13 +72,16 @@ macro_rules! book {
 
 // NOTE: When adding a book here, make sure to ALSO build the book by
 // adding a build step in `src/bootstrap/builder.rs`!
+// NOTE: Make sure to add the corresponding submodule when adding a new book.
+// FIXME: Make checking for a submodule automatic somehow (maybe by having a list of all submodules
+// and checking against it?).
 book!(
-    CargoBook, "src/tools/cargo/src/doc", "cargo";
-    EditionGuide, "src/doc/edition-guide", "edition-guide";
-    EmbeddedBook, "src/doc/embedded-book", "embedded-book";
-    Nomicon, "src/doc/nomicon", "nomicon";
-    Reference, "src/doc/reference", "reference";
-    RustByExample, "src/doc/rust-by-example", "rust-by-example";
+    CargoBook, "src/tools/cargo/src/doc", "cargo", submodule = "src/tools/cargo";
+    EditionGuide, "src/doc/edition-guide", "edition-guide", submodule;
+    EmbeddedBook, "src/doc/embedded-book", "embedded-book", submodule;
+    Nomicon, "src/doc/nomicon", "nomicon", submodule;
+    Reference, "src/doc/reference", "reference", submodule;
+    RustByExample, "src/doc/rust-by-example", "rust-by-example", submodule;
     RustdocBook, "src/doc/rustdoc", "rustdoc";
 );
 
@@ -197,6 +213,9 @@ impl Step for TheBook {
     /// * Index page
     /// * Redirect pages
     fn run(self, builder: &Builder<'_>) {
+        let relative_path = Path::new("src").join("doc").join("book");
+        builder.update_submodule(&relative_path);
+
         let compiler = self.compiler;
         let target = self.target;
 
@@ -204,7 +223,7 @@ impl Step for TheBook {
         builder.ensure(RustbookSrc {
             target,
             name: INTERNER.intern_str("book"),
-            src: INTERNER.intern_path(builder.src.join("src/doc/book")),
+            src: INTERNER.intern_path(builder.src.join(&relative_path)),
         });
 
         // building older edition redirects
@@ -212,7 +231,7 @@ impl Step for TheBook {
             builder.ensure(RustbookSrc {
                 target,
                 name: INTERNER.intern_string(format!("book/{}", edition)),
-                src: INTERNER.intern_path(builder.src.join("src/doc/book").join(edition)),
+                src: INTERNER.intern_path(builder.src.join(&relative_path).join(edition)),
             });
         }
 
@@ -221,7 +240,7 @@ impl Step for TheBook {
 
         // build the redirect pages
         builder.info(&format!("Documenting book redirect pages ({})", target));
-        for file in t!(fs::read_dir(builder.src.join("src/doc/book/redirects"))) {
+        for file in t!(fs::read_dir(builder.src.join(&relative_path).join("redirects"))) {
             let file = t!(file);
             let path = file.path();
             let path = path.to_str().unwrap();
@@ -374,9 +393,15 @@ impl Step for Standalone {
             }
 
             if filename == "not_found.md" {
-                cmd.arg("--markdown-css").arg("https://doc.rust-lang.org/rust.css");
+                cmd.arg("--markdown-css")
+                    .arg(format!("https://doc.rust-lang.org/rustdoc{}.css", &builder.version))
+                    .arg("--markdown-css")
+                    .arg("https://doc.rust-lang.org/rust.css");
             } else {
-                cmd.arg("--markdown-css").arg("rust.css");
+                cmd.arg("--markdown-css")
+                    .arg(format!("rustdoc{}.css", &builder.version))
+                    .arg("--markdown-css")
+                    .arg("rust.css");
             }
             builder.run(&mut cmd);
         }
@@ -501,8 +526,8 @@ impl Step for Std {
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct Rustc {
-    stage: u32,
-    target: TargetSelection,
+    pub stage: u32,
+    pub target: TargetSelection,
 }
 
 impl Step for Rustc {
@@ -593,84 +618,103 @@ impl Step for Rustc {
     }
 }
 
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
-pub struct Rustdoc {
-    stage: u32,
-    target: TargetSelection,
-}
-
-impl Step for Rustdoc {
-    type Output = ();
-    const DEFAULT: bool = true;
-    const ONLY_HOSTS: bool = true;
-
-    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.krate("rustdoc-tool")
-    }
-
-    fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Rustdoc { stage: run.builder.top_stage, target: run.target });
-    }
-
-    /// Generates compiler documentation.
-    ///
-    /// This will generate all documentation for compiler and dependencies.
-    /// Compiler documentation is distributed separately, so we make sure
-    /// we do not merge it with the other documentation from std, test and
-    /// proc_macros. This is largely just a wrapper around `cargo doc`.
-    fn run(self, builder: &Builder<'_>) {
-        let stage = self.stage;
-        let target = self.target;
-        builder.info(&format!("Documenting stage{} rustdoc ({})", stage, target));
-
-        // This is the intended out directory for compiler documentation.
-        let out = builder.compiler_doc_out(target);
-        t!(fs::create_dir_all(&out));
+macro_rules! tool_doc {
+    ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?], binary=$bin:expr) => {
+        #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+        pub struct $tool {
+            stage: u32,
+            target: TargetSelection,
+        }
 
-        let compiler = builder.compiler(stage, builder.config.build);
+        impl Step for $tool {
+            type Output = ();
+            const DEFAULT: bool = true;
+            const ONLY_HOSTS: bool = true;
 
-        if !builder.config.compiler_docs {
-            builder.info("\tskipping - compiler/librustdoc docs disabled");
-            return;
-        }
+            fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+                run.krate($should_run)
+            }
 
-        // Build rustc docs so that we generate relative links.
-        builder.ensure(Rustc { stage, target });
+            fn make_run(run: RunConfig<'_>) {
+                run.builder.ensure($tool { stage: run.builder.top_stage, target: run.target });
+            }
 
-        // Build rustdoc.
-        builder.ensure(tool::Rustdoc { compiler });
+            /// Generates compiler documentation.
+            ///
+            /// This will generate all documentation for compiler and dependencies.
+            /// Compiler documentation is distributed separately, so we make sure
+            /// we do not merge it with the other documentation from std, test and
+            /// proc_macros. This is largely just a wrapper around `cargo doc`.
+            fn run(self, builder: &Builder<'_>) {
+                let stage = self.stage;
+                let target = self.target;
+                builder.info(&format!("Documenting stage{} {} ({})", stage, stringify!($tool).to_lowercase(), target));
 
-        // Symlink compiler docs to the output directory of rustdoc documentation.
-        let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc");
-        t!(fs::create_dir_all(&out_dir));
-        t!(symlink_dir_force(&builder.config, &out, &out_dir));
+                // This is the intended out directory for compiler documentation.
+                let out = builder.compiler_doc_out(target);
+                t!(fs::create_dir_all(&out));
 
-        // Build cargo command.
-        let mut cargo = prepare_tool_cargo(
-            builder,
-            compiler,
-            Mode::ToolRustc,
-            target,
-            "doc",
-            "src/tools/rustdoc",
-            SourceType::InTree,
-            &[],
-        );
+                let compiler = builder.compiler(stage, builder.config.build);
 
-        cargo.arg("-Zskip-rustdoc-fingerprint");
-        // Only include compiler crates, no dependencies of those, such as `libc`.
-        cargo.arg("--no-deps");
-        cargo.arg("-p").arg("rustdoc");
-        cargo.arg("-p").arg("rustdoc-json-types");
+                if !builder.config.compiler_docs {
+                    builder.info("\tskipping - compiler/tool docs disabled");
+                    return;
+                }
 
-        cargo.rustdocflag("--document-private-items");
-        cargo.rustdocflag("--enable-index-page");
-        cargo.rustdocflag("--show-type-layout");
-        cargo.rustdocflag("-Zunstable-options");
-        builder.run(&mut cargo.into());
+                // Build rustc docs so that we generate relative links.
+                builder.ensure(Rustc { stage, target });
+
+                // Symlink compiler docs to the output directory of rustdoc documentation.
+                let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc");
+                t!(fs::create_dir_all(&out_dir));
+                t!(symlink_dir_force(&builder.config, &out, &out_dir));
+
+                // Build cargo command.
+                let mut cargo = prepare_tool_cargo(
+                    builder,
+                    compiler,
+                    Mode::ToolRustc,
+                    target,
+                    "doc",
+                    $path,
+                    SourceType::InTree,
+                    &[],
+                );
+
+                cargo.arg("-Zskip-rustdoc-fingerprint");
+                // Only include compiler crates, no dependencies of those, such as `libc`.
+                cargo.arg("--no-deps");
+                $(
+                    cargo.arg("-p").arg($krate);
+                )+
+
+                if !$bin {
+                    cargo.rustdocflag("--document-private-items");
+                }
+                cargo.rustdocflag("--enable-index-page");
+                cargo.rustdocflag("--show-type-layout");
+                cargo.rustdocflag("-Zunstable-options");
+                builder.run(&mut cargo.into());
+            }
+        }
     }
 }
 
+tool_doc!(
+    Rustdoc,
+    "rustdoc-tool",
+    "src/tools/rustdoc",
+    ["rustdoc", "rustdoc-json-types"],
+    binary = false
+);
+tool_doc!(
+    Rustfmt,
+    "rustfmt-nightly",
+    "src/tools/rustfmt",
+    ["rustfmt-nightly", "rustfmt-config_proc_macro"],
+    binary = true
+);
+
 #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct ErrorIndex {
     pub target: TargetSelection,
index 80a60c79edfe4c0801e54eb59a6fd2ce8d3e8d5c..1b7614b29896f39cac308d5ceb613b689ac7bc59 100644 (file)
@@ -152,7 +152,7 @@ Subcommands:
     fmt         Run rustfmt
     test, t     Build and run some test suites
     bench       Build and run some benchmarks
-    doc         Build documentation
+    doc, d      Build documentation
     clean       Clean out build directories
     dist        Build distribution artifacts
     install     Install distribution artifacts
@@ -244,6 +244,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
                 || (s == "t")
                 || (s == "bench")
                 || (s == "doc")
+                || (s == "d")
                 || (s == "clean")
                 || (s == "dist")
                 || (s == "install")
@@ -312,7 +313,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
             "clippy" => {
                 opts.optflag("", "fix", "automatically apply lint suggestions");
             }
-            "doc" => {
+            "doc" | "d" => {
                 opts.optflag("", "open", "open the docs in a browser");
             }
             "clean" => {
@@ -487,7 +488,7 @@ Arguments:
         ./x.py test --stage 1",
                 );
             }
-            "doc" => {
+            "doc" | "d" => {
                 subcommand_help.push_str(
                     "\n
 Arguments:
@@ -573,7 +574,7 @@ Arguments:
                 },
             },
             "bench" => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
-            "doc" => Subcommand::Doc { paths, open: matches.opt_present("open") },
+            "doc" | "d" => Subcommand::Doc { paths, open: matches.opt_present("open") },
             "clean" => {
                 if !paths.is_empty() {
                     println!("\nclean does not take a path argument\n");
index 2fe9b06e42643916d84a2c59f52f34b28cae789a..5c0322e18a4ab9fff09fa2b62be5592c546aa08d 100644 (file)
@@ -103,12 +103,20 @@ pub unsafe fn setup(build: &mut Build) {
     };
 
     let parent = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid.parse().unwrap());
-    assert!(
-        !parent.is_null(),
-        "PID `{}` doesn't seem to exist: {}",
-        pid,
-        io::Error::last_os_error()
-    );
+
+    // If we get a null parent pointer here, it is possible that either
+    // we have got an invalid pid or the parent process has been closed.
+    // Since the first case rarely happens
+    // (only when wrongly setting the environmental variable),
+    // so it might be better to improve the experience of the second case
+    // when users have interrupted the parent process and we don't finish
+    // duplicating the handle yet.
+    // We just need close the job object if that occurs.
+    if parent.is_null() {
+        CloseHandle(job);
+        return;
+    }
+
     let mut parent_handle = ptr::null_mut();
     let r = DuplicateHandle(
         GetCurrentProcess(),
index 347236c655a02d90a3af1740b308d4d6fc226453..245f3eada2af7719d6ab33a61912ed15b3257883 100644 (file)
@@ -477,12 +477,121 @@ impl Build {
         slice::from_ref(&self.build.triple)
     }
 
+    // modified from `check_submodule` and `update_submodule` in bootstrap.py
+    /// Given a path to the directory of a submodule, update it.
+    ///
+    /// `relative_path` should be relative to the root of the git repository, not an absolute path.
+    pub(crate) fn update_submodule(&self, relative_path: &Path) {
+        fn dir_is_empty(dir: &Path) -> bool {
+            t!(std::fs::read_dir(dir)).next().is_none()
+        }
+
+        if !self.config.submodules(&self.rust_info) {
+            return;
+        }
+
+        let absolute_path = self.config.src.join(relative_path);
+
+        // NOTE: The check for the empty directory is here because when running x.py the first time,
+        // the submodule won't be checked out. Check it out now so we can build it.
+        if !channel::GitInfo::new(false, relative_path).is_git() && !dir_is_empty(&absolute_path) {
+            return;
+        }
+
+        // check_submodule
+        if self.config.fast_submodules {
+            let checked_out_hash = output(
+                Command::new("git").args(&["rev-parse", "HEAD"]).current_dir(&absolute_path),
+            );
+            // update_submodules
+            let recorded = output(
+                Command::new("git")
+                    .args(&["ls-tree", "HEAD"])
+                    .arg(relative_path)
+                    .current_dir(&self.config.src),
+            );
+            let actual_hash = recorded
+                .split_whitespace()
+                .nth(2)
+                .unwrap_or_else(|| panic!("unexpected output `{}`", recorded));
+
+            // update_submodule
+            if actual_hash == checked_out_hash.trim_end() {
+                // already checked out
+                return;
+            }
+        }
+
+        println!("Updating submodule {}", relative_path.display());
+        self.run(
+            Command::new("git")
+                .args(&["submodule", "-q", "sync"])
+                .arg(relative_path)
+                .current_dir(&self.config.src),
+        );
+
+        // Try passing `--progress` to start, then run git again without if that fails.
+        let update = |progress: bool| {
+            let mut git = Command::new("git");
+            git.args(&["submodule", "update", "--init", "--recursive"]);
+            if progress {
+                git.arg("--progress");
+            }
+            git.arg(relative_path).current_dir(&self.config.src);
+            git
+        };
+        // NOTE: doesn't use `try_run` because this shouldn't print an error if it fails.
+        if !update(true).status().map_or(false, |status| status.success()) {
+            self.run(&mut update(false));
+        }
+
+        self.run(Command::new("git").args(&["reset", "-q", "--hard"]).current_dir(&absolute_path));
+        self.run(Command::new("git").args(&["clean", "-qdfx"]).current_dir(absolute_path));
+    }
+
+    /// If any submodule has been initialized already, sync it unconditionally.
+    /// This avoids contributors checking in a submodule change by accident.
+    pub fn maybe_update_submodules(&self) {
+        // WARNING: keep this in sync with the submodules hard-coded in bootstrap.py
+        const BOOTSTRAP_SUBMODULES: &[&str] = &[
+            "src/tools/rust-installer",
+            "src/tools/cargo",
+            "src/tools/rls",
+            "src/tools/miri",
+            "library/backtrace",
+            "library/stdarch",
+        ];
+        // Avoid running git when there isn't a git checkout.
+        if !self.config.submodules(&self.rust_info) {
+            return;
+        }
+        let output = output(
+            Command::new("git")
+                .args(&["config", "--file"])
+                .arg(&self.config.src.join(".gitmodules"))
+                .args(&["--get-regexp", "path"]),
+        );
+        for line in output.lines() {
+            // Look for `submodule.$name.path = $path`
+            // Sample output: `submodule.src/rust-installer.path src/tools/rust-installer`
+            let submodule = Path::new(line.splitn(2, ' ').nth(1).unwrap());
+            // avoid updating submodules twice
+            if !BOOTSTRAP_SUBMODULES.iter().any(|&p| Path::new(p) == submodule)
+                && channel::GitInfo::new(false, submodule).is_git()
+            {
+                self.update_submodule(submodule);
+            }
+        }
+    }
+
     /// Executes the entire build, as configured by the flags and configuration.
     pub fn build(&mut self) {
         unsafe {
             job::setup(self);
         }
 
+        self.maybe_update_submodules();
+
         if let Subcommand::Format { check, paths } = &self.config.cmd {
             return format::format(self, *check, &paths);
         }
@@ -857,7 +966,7 @@ impl Build {
         }
 
         // Work around an apparently bad MinGW / GCC optimization,
-        // See: http://lists.llvm.org/pipermail/cfe-dev/2016-December/051980.html
+        // See: https://lists.llvm.org/pipermail/cfe-dev/2016-December/051980.html
         // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78936
         if &*target.triple == "i686-pc-windows-gnu" {
             base.push("-fno-omit-frame-pointer".into());
index 449fdb87b0224bdc18e2d1a18fa6fac3c7740c67..1be414b29a1aec2ebf195cdd4055e11f56b1ee39 100644 (file)
@@ -128,6 +128,7 @@ impl Step for Llvm {
                 Err(m) => m,
             };
 
+        builder.update_submodule(&Path::new("src").join("llvm-project"));
         if builder.config.llvm_link_shared
             && (target.contains("windows") || target.contains("apple-darwin"))
         {
@@ -139,7 +140,7 @@ impl Step for Llvm {
         let _time = util::timeit(&builder);
         t!(fs::create_dir_all(&out_dir));
 
-        // http://llvm.org/docs/CMake.html
+        // https://llvm.org/docs/CMake.html
         let mut cfg = cmake::Config::new(builder.src.join(root));
 
         let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) {
@@ -276,7 +277,7 @@ impl Step for Llvm {
             }
         }
 
-        // http://llvm.org/docs/HowToCrossCompileLLVM.html
+        // https://llvm.org/docs/HowToCrossCompileLLVM.html
         if target != builder.config.build {
             builder.ensure(Llvm { target: builder.config.build });
             // FIXME: if the llvm root for the build triple is overridden then we
index fe4666effe6228aa3482fe7e9bc1d84b5d79fbfd..31f18d81c7c0fb403892b9eebdde35e19699e406 100644 (file)
@@ -9,7 +9,7 @@ use std::fmt;
 use std::fs;
 use std::iter;
 use std::path::{Path, PathBuf};
-use std::process::Command;
+use std::process::{Command, Stdio};
 
 use build_helper::{self, output, t};
 
@@ -124,8 +124,25 @@ You can skip linkcheck with --exclude src/tools/linkchecker"
 
         builder.info(&format!("Linkcheck ({})", host));
 
+        // Test the linkchecker itself.
+        let bootstrap_host = builder.config.build;
+        let compiler = builder.compiler(0, bootstrap_host);
+        let cargo = tool::prepare_tool_cargo(
+            builder,
+            compiler,
+            Mode::ToolBootstrap,
+            bootstrap_host,
+            "test",
+            "src/tools/linkchecker",
+            SourceType::InTree,
+            &[],
+        );
+        try_run(builder, &mut cargo.into());
+
+        // Build all the default documentation.
         builder.default_doc(&[]);
 
+        // Run the linkchecker.
         let _time = util::timeit(&builder);
         try_run(
             builder,
@@ -144,6 +161,49 @@ You can skip linkcheck with --exclude src/tools/linkchecker"
     }
 }
 
+fn check_if_tidy_is_installed() -> bool {
+    Command::new("tidy")
+        .arg("--version")
+        .stdout(Stdio::null())
+        .status()
+        .map_or(false, |status| status.success())
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct HtmlCheck {
+    target: TargetSelection,
+}
+
+impl Step for HtmlCheck {
+    type Output = ();
+    const DEFAULT: bool = true;
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        let run = run.path("src/tools/html-checker");
+        run.lazy_default_condition(Box::new(check_if_tidy_is_installed))
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(HtmlCheck { target: run.target });
+    }
+
+    fn run(self, builder: &Builder<'_>) {
+        if !check_if_tidy_is_installed() {
+            eprintln!("not running HTML-check tool because `tidy` is missing");
+            eprintln!(
+                "Note that `tidy` is not the in-tree `src/tools/tidy` but needs to be installed"
+            );
+            panic!("Cannot run html-check tests");
+        }
+        // Ensure that a few different kinds of documentation are available.
+        builder.default_doc(&[]);
+        builder.ensure(crate::doc::Rustc { target: self.target, stage: builder.top_stage });
+
+        try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)));
+    }
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Cargotest {
     stage: u32,
@@ -682,7 +742,7 @@ impl Step for RustdocTheme {
         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))
@@ -805,16 +865,16 @@ impl Step for RustdocGUI {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        let run = run.path("src/test/rustdoc-gui");
-        run.default_condition(
+        let run = run.suite_path("src/test/rustdoc-gui");
+        run.lazy_default_condition(Box::new(move || {
             builder.config.nodejs.is_some()
                 && builder
                     .config
                     .npm
                     .as_ref()
                     .map(|p| check_if_browser_ui_test_is_installed(p))
-                    .unwrap_or(false),
-        )
+                    .unwrap_or(false)
+        }))
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -847,29 +907,46 @@ impl Step for RustdocGUI {
         // We remove existing folder to be sure there won't be artifacts remaining.
         let _ = fs::remove_dir_all(&out_dir);
 
-        let mut nb_generated = 0;
+        let src_path = builder.build.src.join("src/test/rustdoc-gui/src");
         // We generate docs for the libraries present in the rustdoc-gui's src folder.
-        let libs_dir = builder.build.src.join("src/test/rustdoc-gui/src");
-        for entry in libs_dir.read_dir().expect("read_dir call failed") {
-            let entry = entry.expect("invalid entry");
-            let path = entry.path();
-            if path.extension().map(|e| e == "rs").unwrap_or(false) {
-                let mut command = builder.rustdoc_cmd(self.compiler);
-                command.arg(path).arg("-o").arg(&out_dir);
-                builder.run(&mut command);
-                nb_generated += 1;
+        for entry in src_path.read_dir().expect("read_dir call failed") {
+            if let Ok(entry) = entry {
+                let path = entry.path();
+
+                if !path.is_dir() {
+                    continue;
+                }
+
+                let mut cargo = Command::new(&builder.initial_cargo);
+                cargo
+                    .arg("doc")
+                    .arg("--target-dir")
+                    .arg(&out_dir)
+                    .env("RUSTDOC", builder.rustdoc(self.compiler))
+                    .env("RUSTC", builder.rustc(self.compiler))
+                    .current_dir(path);
+                builder.run(&mut cargo);
             }
         }
-        assert!(nb_generated > 0, "no documentation was generated...");
 
         // We now run GUI tests.
         let mut command = Command::new(&nodejs);
         command
             .arg(builder.build.src.join("src/tools/rustdoc-gui/tester.js"))
             .arg("--doc-folder")
-            .arg(out_dir)
+            .arg(out_dir.join("doc"))
             .arg("--tests-folder")
             .arg(builder.build.src.join("src/test/rustdoc-gui"));
+        for path in &builder.paths {
+            if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
+                if name.ends_with(".goml") {
+                    command.arg("--file").arg(name);
+                }
+            }
+        }
+        for test_arg in builder.config.cmd.test_args() {
+            command.arg(test_arg);
+        }
         builder.run(&mut command);
     }
 }
@@ -1765,7 +1842,10 @@ impl Step for RustcGuide {
     }
 
     fn run(self, builder: &Builder<'_>) {
-        let src = builder.src.join("src/doc/rustc-dev-guide");
+        let relative_path = Path::new("src").join("doc").join("rustc-dev-guide");
+        builder.update_submodule(&relative_path);
+
+        let src = builder.src.join(relative_path);
         let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
         let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)) {
             ToolState::TestPass
index 9d75ad0918a79186b5092b60b728c90c1018c628..f5e3f61dcc88f6fb5827382bd8dcef13780dc8b2 100644 (file)
@@ -1,7 +1,7 @@
 use std::collections::HashSet;
 use std::env;
 use std::fs;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::process::{exit, Command};
 
 use build_helper::t;
@@ -376,6 +376,7 @@ bootstrap_tool!(
     ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors";
     LintDocs, "src/tools/lint-docs", "lint-docs";
     JsonDocCk, "src/tools/jsondocck", "jsondocck";
+    HtmlChecker, "src/tools/html-checker", "html-checker";
 );
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
@@ -669,7 +670,8 @@ macro_rules! tool_extended {
        $path:expr,
        $tool_name:expr,
        stable = $stable:expr,
-       $(in_tree = $in_tree:expr,)*
+       $(in_tree = $in_tree:expr,)?
+       $(submodule = $submodule:literal,)?
        $extra_deps:block;)+) => {
         $(
             #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -713,6 +715,7 @@ macro_rules! tool_extended {
             #[allow(unused_mut)]
             fn run(mut $sel, $builder: &Builder<'_>) -> Option<PathBuf> {
                 $extra_deps
+                $( $builder.update_submodule(&Path::new("src").join("tools").join($submodule)); )?
                 $builder.ensure(ToolBuild {
                     compiler: $sel.compiler,
                     target: $sel.target,
@@ -735,6 +738,8 @@ macro_rules! tool_extended {
 
 // Note: tools need to be also added to `Builder::get_step_descriptions` in `builder.rs`
 // to make `./x.py build <tool>` work.
+// Note: Most submodule updates for tools are handled by bootstrap.py, since they're needed just to
+// invoke Cargo to build bootstrap. See the comment there for more details.
 tool_extended!((self, builder),
     Cargofmt, rustfmt, "src/tools/rustfmt", "cargo-fmt", stable=true, in_tree=true, {};
     CargoClippy, clippy, "src/tools/clippy", "cargo-clippy", stable=true, in_tree=true, {};
@@ -751,7 +756,7 @@ tool_extended!((self, builder),
     };
     RustDemangler, rust_demangler, "src/tools/rust-demangler", "rust-demangler", stable=false, in_tree=true, {};
     Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, in_tree=true, {};
-    RustAnalyzer, rust_analyzer, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable=false, {};
+    RustAnalyzer, rust_analyzer, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable=false, submodule="rust-analyzer", {};
 );
 
 impl<'a> Builder<'a> {
index 80f804174ed082e20527f8206cd6aef5bbf5eb19..b1ec072f3f8aae7da31f1d171b770bf097948197 100644 (file)
@@ -130,6 +130,7 @@ pub fn make(host: &str) -> PathBuf {
     }
 }
 
+#[track_caller]
 pub fn output(cmd: &mut Command) -> String {
     let output = match cmd.stderr(Stdio::inherit()).output() {
         Ok(status) => status,
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 8a91859379b33af3c08301f4ccee277959055c56..e2dbc7cfd7c640890eede20363468a4414d987f6 100644 (file)
@@ -58,7 +58,7 @@ RUN curl https://www.busybox.net/downloads/busybox-1.32.1.tar.bz2 | tar xjf - &&
 # Download the ubuntu rootfs, which we'll use as a chroot for all our tests.
 WORKDIR /tmp
 RUN mkdir rootfs/ubuntu
-RUN curl http://cdimage.ubuntu.com/ubuntu-base/releases/20.04/release/ubuntu-base-20.04.1-base-armhf.tar.gz | \
+RUN curl https://cdimage.ubuntu.com/ubuntu-base/releases/20.04/release/ubuntu-base-20.04.1-base-armhf.tar.gz | \
       tar xzf - -C rootfs/ubuntu && \
       cd rootfs && mkdir proc sys dev etc etc/init.d
 
index 409bca45c94dd5c22abc8a90e9a5b9e75cf0e243..b305f358c5a76a43e0c075e22c8f157922f495e4 100755 (executable)
@@ -39,7 +39,7 @@ rm -rf binutils
 
 # Next, download the DragonFly libc and relevant header files
 
-URL=http://mirror-master.dragonflybsd.org/iso-images/dfly-x86_64-5.0.0_REL.iso.bz2
+URL=https://mirror-master.dragonflybsd.org/iso-images/dfly-x86_64-5.0.0_REL.iso.bz2
 mkdir dragonfly
 curl $URL | bzcat | bsdtar xf - -C dragonfly ./usr/include ./usr/lib ./lib
 
index 66709a4004cafbbbe59b90fda81aa621a0ca8459..acdf9a0e04185f3211d445a02829affa7f42c7bc 100644 (file)
@@ -711,7 +711,7 @@ CT_ZLIB_PATCH_ORDER="global"
 CT_ZLIB_V_1_2_11=y
 # CT_ZLIB_NO_VERSIONS is not set
 CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_MIRRORS="https://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
 CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
 CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
 CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
index a3dcff1c9363538d11ca2ad8967d948405d998eb..69f86663ec21bd47f04572a1b2b79d269173d8f4 100644 (file)
@@ -725,7 +725,7 @@ CT_ZLIB_PATCH_ORDER="global"
 CT_ZLIB_V_1_2_11=y
 # CT_ZLIB_NO_VERSIONS is not set
 CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_MIRRORS="https://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
 CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
 CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
 CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
index 81b3d7477ec8d1537a5a9d787ca2bc6dc947a949..e3d032fc7e8fc246c27ca3e04ee078164becc5c2 100644 (file)
@@ -671,7 +671,7 @@ CT_MPFR_PATCH_ORDER="global"
 CT_MPFR_V_3_1=y
 # CT_MPFR_NO_VERSIONS is not set
 CT_MPFR_VERSION="3.1.6"
-CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
+CT_MPFR_MIRRORS="https://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
 CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
 CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
 CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
@@ -711,7 +711,7 @@ CT_ZLIB_PATCH_ORDER="global"
 CT_ZLIB_V_1_2_11=y
 # CT_ZLIB_NO_VERSIONS is not set
 CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_MIRRORS="https://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
 CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
 CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
 CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
index 247b539652b15971a49fff3ab396142fb1418319..42fda98bc7a4b1a9e02e9c665d155bb60bd6f4cb 100644 (file)
@@ -69,8 +69,6 @@ COPY host-x86_64/dist-x86_64-linux/build-gcc.sh /tmp/
 RUN ./build-gcc.sh && apt-get remove -y gcc g++
 
 COPY host-x86_64/dist-x86_64-linux/build-python.sh /tmp/
-# Build Python 2.7 needed for Clang 10.
-RUN ./build-python.sh 2.7.12
 # Build Python 3 needed for LLVM 12.
 RUN ./build-python.sh 3.9.1
 
@@ -97,7 +95,7 @@ ENV RUST_CONFIGURE_ARGS \
       --build=i686-unknown-linux-gnu \
       --set llvm.ninja=false \
       --set rust.jemalloc
-ENV SCRIPT python2.7 ../x.py dist --build $HOSTS --host $HOSTS --target $HOSTS
+ENV SCRIPT python3 ../x.py dist --build $HOSTS --host $HOSTS --target $HOSTS
 ENV CARGO_TARGET_I686_UNKNOWN_LINUX_GNU_LINKER=clang
 
 # This was added when we switched from gcc to clang. It's not clear why this is
index ffb2e9195b116fb28ddfeedd0a5ba1434f0a3d49..45d5ff756cdca3920f4a7fd62d0e8fe0c5901834 100644 (file)
@@ -645,7 +645,8 @@ CT_EXPAT_PATCH_ORDER="global"
 CT_EXPAT_V_2_2=y
 # CT_EXPAT_NO_VERSIONS is not set
 CT_EXPAT_VERSION="2.4.1"
-CT_EXPAT_MIRRORS="http://downloads.sourceforge.net/project/expat/expat/${CT_EXPAT_VERSION}"
+CT_EXPAT_VERSION_TAG="2_4_1"
+CT_EXPAT_MIRRORS="https://github.com/libexpat/libexpat/releases/download/R_${CT_EXPAT_VERSION_TAG}"
 CT_EXPAT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
 CT_EXPAT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
 CT_EXPAT_ARCHIVE_FORMATS=".tar.bz2"
@@ -862,7 +863,7 @@ CT_ZLIB_PATCH_ORDER="global"
 CT_ZLIB_V_1_2_11=y
 # CT_ZLIB_NO_VERSIONS is not set
 CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_MIRRORS="https://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
 CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
 CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
 CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
index b7f181adf2a09375b574806d310bb1787a5be322..e363c4f79f9cf30a384f8ce3bfeea9a6d49b7d93 100644 (file)
@@ -27,7 +27,7 @@ RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y --no
   g++-8-arm-linux-gnueabi
 
 RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7924C5513486
-RUN add-apt-repository -y 'deb http://apt.dilos.org/dilos dilos2 main'
+RUN add-apt-repository -y 'deb https://apt.dilos.org/dilos dilos2 main'
 
 ENV \
     AR_x86_64_fuchsia=x86_64-fuchsia-ar \
index f7acedcfb4758e4500efe549e5a569fd0e720f5a..eabff87284dc1c54736ed0ecc348c1c436bfb524 100755 (executable)
@@ -7,7 +7,7 @@ target="x86_64-fortanix-unknown-sgx"
 
 install_prereq() {
     curl https://apt.llvm.org/llvm-snapshot.gpg.key|apt-key add -
-    add-apt-repository -y 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-11 main'
+    add-apt-repository -y 'deb https://apt.llvm.org/focal/ llvm-toolchain-focal-11 main'
     apt-get update
     apt-get install -y --no-install-recommends \
             build-essential \
index 4dd4378f196922bbb97ebf809e61cfd869cb976d..8242e091cd4c7890999140b6762762cb81f40cff 100644 (file)
@@ -69,8 +69,6 @@ COPY host-x86_64/dist-x86_64-linux/build-gcc.sh /tmp/
 RUN ./build-gcc.sh && apt-get remove -y gcc g++
 
 COPY host-x86_64/dist-x86_64-linux/build-python.sh /tmp/
-# Build Python 2.7 needed for Clang 10.
-RUN ./build-python.sh 2.7.12
 # Build Python 3 needed for LLVM 12.
 RUN ./build-python.sh 3.9.1
 
@@ -102,7 +100,7 @@ ENV RUST_CONFIGURE_ARGS \
       --set llvm.thin-lto=true \
       --set llvm.ninja=false \
       --set rust.jemalloc
-ENV SCRIPT ../src/ci/pgo.sh python2.7 ../x.py dist \
+ENV SCRIPT ../src/ci/pgo.sh python3 ../x.py dist \
     --host $HOSTS --target $HOSTS \
     --include-default-paths \
     src/tools/build-manifest
index ed0b5c85f7ca9e9706c0b4a376d4c516d79112da..b5378244b793c6cd559b159c19241fed823f8c62 100755 (executable)
@@ -4,14 +4,16 @@ set -ex
 
 source shared.sh
 
-curl https://ftp.gnu.org/gnu/binutils/binutils-2.25.1.tar.bz2 | tar xfj -
+VERSION=2.26.1
+
+curl https://ftp.gnu.org/gnu/binutils/binutils-$VERSION.tar.bz2 | tar xfj -
 
 mkdir binutils-build
 cd binutils-build
-hide_output ../binutils-2.25.1/configure --prefix=/rustroot
-hide_output make -j10
+hide_output ../binutils-$VERSION/configure --prefix=/rustroot
+hide_output make -j$(nproc)
 hide_output make install
 
 cd ..
 rm -rf binutils-build
-rm -rf binutils-2.25.1
+rm -rf binutils-$VERSION
index 969443ac0949bf6ab837373bccc03dea2bb6de58..40a637616d35f1fe434bac93a88a19f3a68b382a 100755 (executable)
@@ -4,7 +4,7 @@ set -ex
 
 source shared.sh
 
-LLVM=llvmorg-10.0.0
+LLVM=llvmorg-12.0.1
 
 mkdir llvm-project
 cd llvm-project
@@ -30,7 +30,7 @@ hide_output \
       -DLLVM_ENABLE_PROJECTS="clang;lld" \
       -DC_INCLUDE_DIRS="$INC"
 
-hide_output make -j10
+hide_output make -j$(nproc)
 hide_output make install
 
 cd ../..
index e17831a1afee56da93229799ff3ac6ae2113c005..2f6b1fa9b8e3e657c344943d2adb07e1fac28ead 100755 (executable)
@@ -9,7 +9,7 @@ curl -L https://github.com/Kitware/CMake/releases/download/v$CMAKE/cmake-$CMAKE.
 mkdir cmake-build
 cd cmake-build
 hide_output ../cmake-$CMAKE/configure --prefix=/rustroot
-hide_output make -j10
+hide_output make -j$(nproc)
 hide_output make install
 
 cd ..
index a60c6be9f322211ad3be6371c2809dc1169236cc..6efa789756619fcaf3e318159da75bf2a1051c9b 100755 (executable)
@@ -30,7 +30,7 @@ hide_output ../curl-$VERSION/configure \
       --disable-rtsp \
       --disable-ldaps \
       --disable-ldap
-hide_output make -j10
+hide_output make -j$(nproc)
 hide_output make install
 
 cd ..
index fcf869b68be7100c10401accceb73eb60e438291..3a03eb2bdc8384557067160e5ece530535a21f0d 100755 (executable)
@@ -22,6 +22,7 @@ cd gcc-$GCC
 # latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server
 # instead here.
 #
+# FIXME: use HTTPS (see https://github.com/rust-lang/rust/pull/86586#issuecomment-868355356)
 sed -i'' 's|ftp://gcc\.gnu\.org/|http://gcc.gnu.org/|g' ./contrib/download_prerequisites
 
 ./contrib/download_prerequisites
@@ -31,7 +32,7 @@ hide_output ../gcc-$GCC/configure \
     --prefix=/rustroot \
     --enable-languages=c,c++ \
     --disable-gnu-unique-object
-hide_output make -j10
+hide_output make -j$(nproc)
 hide_output make install
 ln -s gcc /rustroot/bin/cc
 
index d8f6bdb51b8d5bad24e0995de30e5babde6d0fa9..34bbe19d2fac331cec92db088c24190512273174 100755 (executable)
@@ -14,7 +14,7 @@ curl $URL | tar xzf -
 
 cd openssl-$VERSION
 hide_output ./config --prefix=/rustroot shared -fPIC
-hide_output make -j10
+hide_output make -j$(nproc)
 hide_output make install
 cd ..
 rm -rf openssl-$VERSION
index 970d67b6db3ddc495ef6923411348eb8d045da42..9a203beadd1033ef903be18f94af77839bc923ad 100755 (executable)
@@ -14,7 +14,7 @@ cd python-build
 # than that fairly normal.
 CFLAGS='-I /rustroot/include' LDFLAGS='-L /rustroot/lib -L /rustroot/lib64' \
     hide_output ../Python-$VERSION/configure --prefix=/rustroot
-hide_output make -j10
+hide_output make -j$(nproc)
 hide_output make install
 
 cd ..
index 66afe84be4a27cb9d5feb4c50fab247cf7d01f39..eeabee5b4a801f8d99d773a6340e438d1eb5025d 100644 (file)
@@ -38,5 +38,5 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \
            python3 ../x.py doc --stage 0 library/test && \
            /scripts/validate-toolstate.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 7f1a5820e22610c9c5cd6390a8dc857752e9b579..ee3cd092f4cdbcec937c6e4ec8f913883cab2708 100644 (file)
@@ -17,7 +17,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libgl1-mesa-dev \
   llvm-dev \
   libfreetype6-dev \
-  libexpat1-dev
+  libexpat1-dev \
+  tidy
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
index ee7c223ba578bbee2414c5309534975e47af97f8..779b301ff618fa6ed583949def93385171d5853b 100644 (file)
@@ -12,7 +12,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   cmake \
   libssl-dev \
   sudo \
-  xz-utils
+  xz-utils \
+  tidy
 
 # Install dependencies for chromium browser
 RUN apt-get install -y \
index e704071e401b77398b291b7334258a9cce8aeb06..128897e580b68603dfe63be00b8d69ba8ce6b7bc 100644 (file)
@@ -416,6 +416,10 @@ jobs:
             env:
               IMAGE: x86_64-gnu
               RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable
+              # Only run this job on the nightly channel. Running this on beta
+              # could cause failures when `dev: 1` in `stage0.txt`, and running
+              # this on stable is useless.
+              CI_ONLY_WHEN_CHANNEL: nightly
             <<: *job-linux-xl
 
           - name: x86_64-gnu-aux
index c3c717266db4564c673325d7e8ace9d9b19cd3e0..aa009a4eac6af877e4e4dc005a2fd9abd19d2f2b 100755 (executable)
@@ -4,7 +4,7 @@ set -euxo pipefail
 
 rm -rf /tmp/rustc-pgo
 
-python2.7 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \
+python3 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \
     --stage 2 library/std --rust-profile-generate=/tmp/rustc-pgo
 
 RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \
@@ -15,14 +15,16 @@ function pgo_perf_benchmark {
     local PERF=1e19fc4c6168d2f7596e512f42f358f245d8f09d
     local github_prefix=https://raw.githubusercontent.com/rust-lang/rustc-perf/$PERF
     local name=$1
+    local edition=$2
     curl -o /tmp/$name.rs $github_prefix/collector/benchmarks/$name/src/lib.rs
 
-    RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \
+    RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=$edition \
         --crate-type=lib /tmp/$name.rs
 }
 
-pgo_perf_benchmark externs
-pgo_perf_benchmark ctfe-stress-4
+pgo_perf_benchmark externs 2018
+pgo_perf_benchmark ctfe-stress-4 2018
+pgo_perf_benchmark inflate 2015
 
 cp -pri ../src/tools/cargo /tmp/cargo
 
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 fa738fe70c8e2f7b414da8431883f110f7abcf02..bb48fcb5a216eaaef3da799ed4865186a2b3f6d1 100755 (executable)
@@ -8,31 +8,43 @@ IFS=$'\n\t'
 
 source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
 
-if [[ -z "${CI_ONLY_WHEN_SUBMODULES_CHANGED+x}" ]]; then
-    echo "Executing the job since there is no skip rule in effect"
-    exit 0
+if [[ -n "${CI_ONLY_WHEN_SUBMODULES_CHANGED-}" ]]; then
+    git fetch "https://github.com/$GITHUB_REPOSITORY" "$GITHUB_BASE_REF"
+    BASE_COMMIT="$(git merge-base FETCH_HEAD HEAD)"
+
+    echo "Searching for toolstate changes between $BASE_COMMIT and $(git rev-parse HEAD)"
+
+    if git diff "$BASE_COMMIT" | grep --quiet "^index .* 160000"; then
+        # Submodules pseudo-files inside git have the 160000 permissions, so when
+        # those files are present in the diff a submodule was updated.
+        echo "Submodules were updated"
+    elif ! git diff --quiet "$BASE_COMMIT" -- src/tools/clippy src/tools/rustfmt; then
+        # There is not an easy blanket search for subtrees. For now, manually list
+        # the subtrees.
+        echo "Clippy or rustfmt subtrees were updated"
+    elif ! (git diff --quiet "$BASE_COMMIT" -- \
+             src/test/rustdoc-gui \
+             src/librustdoc \
+             src/tools/rustdoc-gui); then
+        # There was a change in either rustdoc or in its GUI tests.
+        echo "Rustdoc was updated"
+    else
+        echo "Not executing this job since no submodules nor subtrees were updated"
+        ciCommandSetEnv SKIP_JOB 1
+        exit 0
+    fi
 fi
 
-git fetch "https://github.com/$GITHUB_REPOSITORY" "$GITHUB_BASE_REF"
-BASE_COMMIT="$(git merge-base FETCH_HEAD HEAD)"
-
-echo "Searching for toolstate changes between $BASE_COMMIT and $(git rev-parse HEAD)"
-
-if git diff "$BASE_COMMIT" | grep --quiet "^index .* 160000"; then
-    # Submodules pseudo-files inside git have the 160000 permissions, so when
-    # those files are present in the diff a submodule was updated.
-    echo "Executing the job since submodules are updated"
-elif ! git diff --quiet "$BASE_COMMIT" -- src/tools/clippy src/tools/rustfmt; then
-    # There is not an easy blanket search for subtrees. For now, manually list
-    # the subtrees.
-    echo "Executing the job since clippy or rustfmt subtree was updated"
-elif ! (git diff --quiet "$BASE_COMMIT" -- \
-         src/test/rustdoc-gui \
-         src/librustdoc \
-         src/tools/rustdoc-gui); then
-    # There was a change in either rustdoc or in its GUI tests.
-    echo "Executing the job since rustdoc was updated"
-else
-    echo "Not executing this job since no submodules nor subtrees were updated"
-    ciCommandSetEnv SKIP_JOB 1
+if [[ -n "${CI_ONLY_WHEN_CHANNEL-}" ]]; then
+    if [[ "${CI_ONLY_WHEN_CHANNEL}" = "$(cat src/ci/channel)" ]]; then
+        echo "The channel is the expected one"
+    else
+        echo "Not executing this job as the channel is not the expected one"
+        ciCommandSetEnv SKIP_JOB 1
+        exit 0
+    fi
 fi
+
+
+echo "Executing the job since there is no skip rule preventing the execution"
+exit 0
index b095afb542d83da4dfa114d371fcce8288a819d1..1f218bc834608325883ff198edbff566df015aad 100644 (file)
@@ -7,7 +7,7 @@
 
 export MIRRORS_BASE="https://ci-mirrors.rust-lang.org/rustc"
 
-# See http://unix.stackexchange.com/questions/82598
+# See https://unix.stackexchange.com/questions/82598
 # Duplicated in docker/dist-various-2/shared.sh
 function retry {
   echo "Attempting with retry:" "$@"
index 5e79b3c7110624a54374bcd80de34aab35ae319a..879799c717b668e7a6ef68d647cb67acbf6b01a6 100644 (file)
@@ -7,10 +7,6 @@ var ferrisTypes = [
     attr: 'panics',
     title: 'This code panics!'
   },
-  {
-    attr: 'unsafe',
-    title: 'This code block contains unsafe code.'
-  },
   {
     attr: 'not_desired_behavior',
     title: 'This code does not produce the desired behavior.'
index 930a7d95184dace75326b73065547291c43852a6..172ae61641c90d60802ca9ec89fca0907348cf9f 100644 (file)
@@ -1,7 +1,6 @@
 [package]
 name = "guessing_game"
 version = "0.1.0"
-authors = ["Your Name <you@example.com>"]
 edition = "2018"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
index e3091e7da88c67e3ac0fa0462bef2d50c4fbf617..242309f93b4d8ec7ebe932af4d1b9f7bd376f867 100644 (file)
@@ -1,7 +1,6 @@
 [package]
 name = "guessing_game"
 version = "0.1.0"
-authors = ["Your Name <you@example.com>"]
 edition = "2018"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
index 19a9cc74b6ef1931e78e0aeace291c33d8a92dac..c31ebd1dfd5ec46cf015e20b4107086cfcc0d9f2 100644 (file)
@@ -16,12 +16,17 @@ fn first_word(s: &str) -> &str {
 fn main() {
     let my_string = String::from("hello world");
 
-    // first_word works on slices of `String`s
+    // `first_word` works on slices of `String`s, whether partial or whole
+    let word = first_word(&my_string[0..6]);
     let word = first_word(&my_string[..]);
+    // `first_word` also works on references to `String`s, which is equivalent
+    // to a slice of the whole `String`
+    let word = first_word(&my_string);
 
     let my_string_literal = "hello world";
 
-    // first_word works on slices of string literals
+    // `first_word` works on slices of string literals, whether partial or whole
+    let word = first_word(&my_string_literal[0..6]);
     let word = first_word(&my_string_literal[..]);
 
     // Because string literals *are* string slices already,
index 3b0a7da6590ea736c7681faa172b9eaebeefafa9..8619449669d8c47fcf617132b27bfb1b05849ce3 100644 (file)
@@ -5,7 +5,7 @@ fn main() {
     let r1 = &s; // no problem
     let r2 = &s; // no problem
     println!("{} and {}", r1, r2);
-    // r1 and r2 are no longer used after this point
+    // variables r1 and r2 will not be used after this point
 
     let r3 = &mut s; // no problem
     println!("{}", r3);
index 09c043bad6ff249d8c896af312a828204d592360..bffbe058d2561d8927d14be6e0c4e860307a4407 100644 (file)
@@ -1,3 +1,4 @@
+// ANCHOR: here
 //! # Art
 //!
 //! A library for modeling artistic concepts.
@@ -26,7 +27,8 @@ pub mod utils {
     pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
         // --snip--
         // ANCHOR_END: here
-        SecondaryColor::Orange
+        unimplemented!();
         // ANCHOR: here
     }
 }
+// ANCHOR_END: here
index 7dea568d9233177ca751b42f0e508ba7c19d2cee..9111fbc55c08454f77913cdc586cbf94e4d9eda4 100644 (file)
@@ -1,6 +1,6 @@
 use std::ops::Add;
 
-#[derive(Debug, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq)]
 struct Point {
     x: i32,
     y: i32,
index 5a93a685c080bab351330bd7055a444fe73251d9..4c4e6f898b64546578548556d756c0639621a041 100644 (file)
@@ -1,7 +1,6 @@
 [package]
 name = "hello_macro"
 version = "0.1.0"
-authors = ["Your Name <you@example.com>"]
 edition = "2018"
 
 [dependencies]
index 168cbae53c792382eac7dc1449da5e0b09e2f9c7..80cada3ef02e640beac0ae3133e0c2dc51566aa9 100644 (file)
@@ -1,7 +1,6 @@
 [package]
 name = "hello_macro_derive"
 version = "0.1.0"
-authors = ["Your Name <you@example.com>"]
 edition = "2018"
 
 [lib]
index cc0addaa4a7c1862d3d5e88efb4c84c4db43e26c..f150aec0aaeeb478e9dfa62a2958765123bc8550 100644 (file)
@@ -1,7 +1,6 @@
 [package]
 name = "pancakes"
 version = "0.1.0"
-authors = ["Your Name <you@example.com>"]
 edition = "2018"
 
 [dependencies]
diff --git a/src/doc/book/nostarch/chapter02.md b/src/doc/book/nostarch/chapter02.md
new file mode 100644 (file)
index 0000000..c3b6584
--- /dev/null
@@ -0,0 +1,1008 @@
+
+[TOC]
+
+# Programming a Guessing Game
+
+Let’s jump into Rust by working through a hands-on project together! This
+chapter introduces you to a few common Rust concepts by showing you how to use
+them in a real program. You’ll learn about `let`, `match`, methods, associated
+functions, using external crates, and more! The following chapters will explore
+these ideas in more detail. In this chapter, you’ll practice the fundamentals.
+
+We’ll implement a classic beginner programming problem: a guessing game. Here’s
+how it works: the program will generate a random integer between 1 and 100. It
+will then prompt the player to enter a guess. After a guess is entered, the
+program will indicate whether the guess is too low or too high. If the guess is
+correct, the game will print a congratulatory message and exit.
+
+## Setting Up a New Project
+
+To set up a new project, go to the *projects* directory that you created in
+Chapter 1 and make a new project using Cargo, like so:
+
+```
+$ cargo new guessing_game
+$ cd guessing_game
+```
+
+The first command, `cargo new`, takes the name of the project (`guessing_game`)
+as the first argument. The second command changes to the new project’s
+directory.
+
+Look at the generated *Cargo.toml* file:
+
+Filename: Cargo.toml
+
+```
+[package]
+name = "guessing_game"
+version = "0.1.0"
+edition = "2018"
+
+
+[dependencies]
+```
+
+As you saw in Chapter 1, `cargo new` generates a “Hello, world!” program for
+you. Check out the *src/main.rs* file:
+
+Filename: src/main.rs
+
+```
+fn main() {
+    println!("Hello, world!");
+}
+```
+
+Now let’s compile this “Hello, world!” program and run it in the same step
+using the `cargo run` command:
+
+```
+$ cargo run
+   Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
+    Finished dev [unoptimized + debuginfo] target(s) in 1.50s
+     Running `target/debug/guessing_game`
+Hello, world!
+```
+
+The `run` command comes in handy when you need to rapidly iterate on a project,
+as we’ll do in this game, quickly testing each iteration before moving on to
+the next one.
+
+Reopen the *src/main.rs* file. You’ll be writing all the code in this file.
+
+## Processing a Guess
+
+The first part of the guessing game program will ask for user input, process
+that input, and check that the input is in the expected form. To start, we’ll
+allow the player to input a guess. Enter the code in Listing 2-1 into
+*src/main.rs*.
+
+Filename: src/main.rs
+
+```
+use std::io;
+
+fn main() {
+    println!("Guess the number!");
+
+    println!("Please input your guess.");
+
+    let mut guess = String::new();
+
+    io::stdin()
+        .read_line(&mut guess)
+        .expect("Failed to read line");
+
+    println!("You guessed: {}", guess);
+}
+```
+
+Listing 2-1: Code that gets a guess from the user and prints it
+
+This code contains a lot of information, so let’s go over it line by line. To
+obtain user input and then print the result as output, we need to bring the
+`io` (input/output) library into scope. The `io` library comes from the
+standard library (which is known as `std`):
+
+```
+use std::io;
+```
+
+By default, Rust brings only a few types into the scope of every program in the
+*prelude*. If a type you want to use isn’t in the prelude, you have to bring
+that type into scope explicitly with a `use` statement. Using the `std::io`
+library provides you with a number of useful features, including the ability to
+accept user input.
+
+As you saw in Chapter 1, the `main` function is the entry point into the
+program:
+
+```
+fn main() {
+```
+
+The `fn` syntax declares a new function, the parentheses, `()`, indicate there
+are no parameters, and the curly bracket, `{`, starts the body of the function.
+
+As you also learned in Chapter 1, `println!` is a macro that prints a string to
+the screen:
+
+```
+    println!("Guess the number!");
+
+    println!("Please input your guess.");
+```
+
+This code is printing a prompt stating what the game is and requesting input
+from the user.
+
+### Storing Values with Variables
+
+Next, we’ll create a place to store the user input, like this:
+
+```
+    let mut guess = String::new();
+```
+
+Now the program is getting interesting! There’s a lot going on in this little
+line. Notice that this is a `let` statement, which is used to create a
+*variable*. Here’s another example:
+
+```
+let apples = 5;
+```
+
+This line creates a new variable named `apples` and binds it to the value 5. In
+Rust, variables are immutable by default. We’ll be discussing this concept in
+detail in the “Variables and Mutability” section in Chapter 3. The following
+example shows how to use `mut` before the variable name to make a variable
+mutable:
+
+```
+let apples = 5; // immutable
+let mut bananas = 5; // mutable
+```
+
+> Note: The `//` syntax starts a comment that continues until the end of the
+> line. Rust ignores everything in comments, which are discussed in more detail
+> in Chapter 3.
+
+Let’s return to the guessing game program. You now know that `let mut guess`
+will introduce a mutable variable named `guess`. On the other side of the equal
+sign (`=`) is the value that `guess` is bound to, which is the result of
+calling `String::new`, a function that returns a new instance of a `String`.
+`String` is a string type provided by the standard library that is a growable,
+UTF-8 encoded bit of text.
+
+The `::` syntax in the `::new` line indicates that `new` is an *associated
+function* of the `String` type. An associated function is implemented on a
+type, in this case `String`.
+
+This `new` function creates a new, empty string. You’ll find a `new` function
+on many types, because it’s a common name for a function that makes a new value
+of some kind.
+
+To summarize, the `let mut guess = String::new();` line has created a mutable
+variable that is currently bound to a new, empty instance of a `String`. Whew!
+
+Recall that we included the input/output functionality from the standard
+library with `use std::io;` on the first line of the program. Now we’ll call
+the `stdin` function from the `io` module:
+
+```
+    io::stdin()
+        .read_line(&mut guess)
+```
+
+If we hadn’t put the `use std::io` line at the beginning of the program, we
+could have written this function call as `std::io::stdin`. The `stdin` function
+returns an instance of `std::io::Stdin`, which is a type that represents a
+handle to the standard input for your terminal.
+
+The next part of the code, `.read_line(&mut guess)`, calls the `read_line`
+method on the standard input handle to get input from the user. We’re also
+passing one argument to `read_line`: `&mut guess`.
+
+The job of `read_line` is to take whatever the user types into standard input
+and append that into a string (without overwriting its contents), so it takes
+that string as an argument. The string argument needs to be mutable so the
+method can change the string’s content by adding the user input.
+
+The `&` indicates that this argument is a *reference*, which gives you a way to
+let multiple parts of your code access one piece of data without needing to
+copy that data into memory multiple times. References are a complex feature,
+and one of Rust’s major advantages is how safe and easy it is to use
+references. You don’t need to know a lot of those details to finish this
+program. For now, all you need to know is that like variables, references are
+immutable by default. Hence, you need to write `&mut guess` rather than
+`&guess` to make it mutable. (Chapter 4 will explain references more
+thoroughly.)
+
+### Handling Potential Failure with the `Result` Type
+
+We’re still working on this line of code. Although we’re now discussing a third
+line of text, it’s still part of a single logical line of code. The next part
+is this method:
+
+```
+        .expect("Failed to read line");
+```
+
+When you call a method with the `.method_name()` syntax, it’s often wise to
+introduce a newline and other whitespace to help break up long lines. We could
+have written this code as:
+
+```
+io::stdin().read_line(&mut guess).expect("Failed to read line");
+```
+
+However, one long line is difficult to read, so it’s best to divide it. Now
+let’s discuss what this line does.
+
+As mentioned earlier, `read_line` puts what the user types into the string
+we’re passing it, but it also returns a value—in this case, an `io::Result`.
+Rust has a number of types named `Result` in its standard library: a generic
+`Result` as well as specific versions for submodules, such as `io::Result`.
+
+The `Result` types are *enumerations*, often referred to as *enums*. An
+enumeration is a type that can have a fixed set of values, and those values are
+called the enum’s *variants*. Chapter 6 will cover enums in more detail.
+
+For `Result`, the variants are `Ok` or `Err`. The `Ok` variant indicates the
+operation was successful, and inside `Ok` is the successfully generated value.
+The `Err` variant means the operation failed, and `Err` contains information
+about how or why the operation failed.
+
+The purpose of these `Result` types is to encode error-handling information.
+Values of the `Result` type, like values of any type, have methods defined on
+them. An instance of `io::Result` has an `expect` method that you can call. If
+this instance of `io::Result` is an `Err` value, `expect` will cause the
+program to crash and display the message that you passed as an argument to
+`expect`. If the `read_line` method returns an `Err`, it would likely be the
+result of an error coming from the underlying operating system. If this
+instance of `io::Result` is an `Ok` value, `expect` will take the return value
+that `Ok` is holding and return just that value to you so you can use it. In
+this case, that value is the number of bytes in what the user entered into
+standard input.
+
+If you don’t call `expect`, the program will compile, but you’ll get a warning:
+
+```
+$ cargo build
+   Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
+warning: unused `Result` that must be used
+  --> src/main.rs:10:5
+   |
+10 |     io::stdin().read_line(&mut guess);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: this `Result` may be an `Err` variant, which should be handled
+
+warning: 1 warning emitted
+
+    Finished dev [unoptimized + debuginfo] target(s) in 0.59s
+```
+
+Rust warns that you haven’t used the `Result` value returned from `read_line`,
+indicating that the program hasn’t handled a possible error.
+
+The right way to suppress the warning is to actually write error handling, but
+because you just want to crash this program when a problem occurs, you can use
+`expect`. You’ll learn about recovering from errors in Chapter 9.
+
+### Printing Values with `println!` Placeholders
+
+Aside from the closing curly bracket, there’s only one more line to discuss in
+the code added so far, which is the following:
+
+```
+    println!("You guessed: {}", guess);
+```
+
+This line prints the string we saved the user’s input in. The set of curly
+brackets, `{}`, is a placeholder: think of `{}` as little crab pincers that
+hold a value in place. You can print more than one value using curly brackets:
+the first set of curly brackets holds the first value listed after the format
+string, the second set holds the second value, and so on. Printing multiple
+values in one call to `println!` would look like this:
+
+```
+let x = 5;
+let y = 10;
+
+println!("x = {} and y = {}", x, y);
+```
+
+This code would print `x = 5 and y = 10`.
+
+### Testing the First Part
+
+Let’s test the first part of the guessing game. Run it using `cargo run`:
+
+```
+$ cargo run
+   Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
+    Finished dev [unoptimized + debuginfo] target(s) in 6.44s
+     Running `target/debug/guessing_game`
+Guess the number!
+Please input your guess.
+6
+You guessed: 6
+```
+
+At this point, the first part of the game is done: we’re getting input from the
+keyboard and then printing it.
+
+## Generating a Secret Number
+
+Next, we need to generate a secret number that the user will try to guess. The
+secret number should be different every time so the game is fun to play more
+than once. Let’s use a random number between 1 and 100 so the game isn’t too
+difficult. Rust doesn’t yet include random number functionality in its standard
+library. However, the Rust team does provide a `rand` crate at
+*https://crates.io/crates/rand*.
+
+### Using a Crate to Get More Functionality
+
+Remember that a crate is a collection of Rust source code files. The project
+we’ve been building is a *binary crate*, which is an executable. The `rand`
+crate is a *library crate*, which contains code intended to be used in other
+programs.
+
+Cargo’s coordination of external crates is where Cargo really shines. Before we
+can write code that uses `rand`, we need to modify the *Cargo.toml* file to
+include the `rand` crate as a dependency. Open that file now and add the
+following line to the bottom beneath the `[dependencies]` section header that
+Cargo created for you. Be sure to specify `rand` exactly as we have here, or
+the code examples in this tutorial may not work.
+
+Filename: Cargo.toml
+
+```
+rand = "0.8.3"
+```
+
+In the *Cargo.toml* file, everything that follows a header is part of a section
+that continues until another section starts. The `[dependencies]` section is
+where you tell Cargo which external crates your project depends on and which
+versions of those crates you require. In this case, we’ll specify the `rand`
+crate with the semantic version specifier `0.8.3`. Cargo understands Semantic
+Versioning (sometimes called *SemVer*), which is a standard for writing version
+numbers. The number `0.8.3` is actually shorthand for `^0.8.3`, which means any
+version that is at least `0.8.3` but below `0.9.0`. Cargo considers these
+versions to have public APIs compatible with version `0.8.3`, and this
+specification ensures you'll get the latest patch release that will still
+compile with the code in this chapter. Any version `0.9.0` or greater is not
+guaranteed to have the same API as what the following examples use.
+
+Now, without changing any of the code, let’s build the project, as shown in
+Listing 2-2.
+
+```
+$ cargo build
+    Updating crates.io index
+  Downloaded rand v0.8.3
+  Downloaded libc v0.2.86
+  Downloaded getrandom v0.2.2
+  Downloaded cfg-if v1.0.0
+  Downloaded ppv-lite86 v0.2.10
+  Downloaded rand_chacha v0.3.0
+  Downloaded rand_core v0.6.2
+   Compiling rand_core v0.6.2
+   Compiling libc v0.2.86
+   Compiling getrandom v0.2.2
+   Compiling cfg-if v1.0.0
+   Compiling ppv-lite86 v0.2.10
+   Compiling rand_chacha v0.3.0
+   Compiling rand v0.8.3
+   Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
+    Finished dev [unoptimized + debuginfo] target(s) in 2.53s
+```
+
+Listing 2-2: The output from running `cargo build` after adding the rand crate
+as a dependency
+
+You may see different version numbers (but they will all be compatible with the
+code, thanks to SemVer!), different lines (depending on the operating system),
+and the lines may be in a different order.
+
+Now that we have an external dependency, Cargo fetches the latest versions of
+everything from the *registry*, which is a copy of data from Crates.io at
+*https://crates.io/*. Crates.io is where people in the Rust ecosystem post
+their open source Rust projects for others to use.
+
+After updating the registry, Cargo checks the `[dependencies]` section and
+downloads any crates you don’t have yet. In this case, although we only listed
+`rand` as a dependency, Cargo also grabbed other crates that `rand` depends on
+to work. After downloading the crates, Rust compiles them and then compiles the
+project with the dependencies available.
+
+If you immediately run `cargo build` again without making any changes, you
+won’t get any output aside from the `Finished` line. Cargo knows it has already
+downloaded and compiled the dependencies, and you haven’t changed anything
+about them in your *Cargo.toml* file. Cargo also knows that you haven’t changed
+anything about your code, so it doesn’t recompile that either. With nothing to
+do, it simply exits.
+
+If you open up the *src/main.rs* file, make a trivial change, and then save it
+and build again, you’ll only see two lines of output:
+
+```
+$ cargo build
+   Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
+    Finished dev [unoptimized + debuginfo] target(s) in 2.53 secs
+```
+
+These lines show Cargo only updates the build with your tiny change to the
+*src/main.rs* file. Your dependencies haven’t changed, so Cargo knows it can
+reuse what it has already downloaded and compiled for those. It just rebuilds
+your part of the code.
+
+#### Ensuring Reproducible Builds with the *Cargo.lock* File
+
+Cargo has a mechanism that ensures you can rebuild the same artifact every time
+you or anyone else builds your code: Cargo will use only the versions of the
+dependencies you specified until you indicate otherwise. For example, what
+happens if next week version 0.8.4 of the `rand` crate comes out, and that
+version contains an important bug fix, but it also contains a regression that
+will break your code?
+
+The answer to this problem is the *Cargo.lock* file, which was created the
+first time you ran `cargo build` and is now in your *guessing_game* directory.
+When you build a project for the first time, Cargo figures out all the
+versions of the dependencies that fit the criteria and then writes them to
+the *Cargo.lock* file. When you build your project in the future, Cargo will
+see that the *Cargo.lock* file exists and use the versions specified there
+rather than doing all the work of figuring out versions again. This lets you
+have a reproducible build automatically. In other words, your project will
+remain at `0.8.3` until you explicitly upgrade, thanks to the *Cargo.lock*
+file.
+
+#### Updating a Crate to Get a New Version
+
+When you *do* want to update a crate, Cargo provides another command, `update`,
+which will ignore the *Cargo.lock* file and figure out all the latest versions
+that fit your specifications in *Cargo.toml*. If that works, Cargo will write
+those versions to the *Cargo.lock* file.
+
+But by default, Cargo will only look for versions greater than `0.8.3` and less
+than `0.9.0`. If the `rand` crate has released two new versions, `0.8.4` and
+`0.9.0`, you would see the following if you ran `cargo update`:
+
+```
+$ cargo update
+    Updating crates.io index
+    Updating rand v0.8.3 -> v0.8.4
+```
+
+At this point, you would also notice a change in your *Cargo.lock* file noting
+that the version of the `rand` crate you are now using is `0.8.4`.
+
+If you wanted to use `rand` version `0.9.0` or any version in the `0.9.x`
+series, you’d have to update the *Cargo.toml* file to look like this instead:
+
+```
+[dependencies]
+rand = "0.9.0"
+```
+
+The next time you run `cargo build`, Cargo will update the registry of crates
+available and reevaluate your `rand` requirements according to the new version
+you have specified.
+
+There’s a lot more to say about Cargo and its ecosystem which we’ll discuss in
+Chapter 14, but for now, that’s all you need to know. Cargo makes it very easy
+to reuse libraries, so Rustaceans are able to write smaller projects that are
+assembled from a number of packages.
+
+### Generating a Random Number
+
+Now that you’ve added the `rand` crate to *Cargo.toml*, let’s start using
+`rand`. The next step is to update *src/main.rs*, as shown in Listing 2-3.
+
+Filename: src/main.rs
+
+```
+use std::io;
+use rand::Rng;
+
+fn main() {
+    println!("Guess the number!");
+
+    let secret_number = rand::thread_rng().gen_range(1..101);
+
+    println!("The secret number is: {}", secret_number);
+
+    println!("Please input your guess.");
+
+    let mut guess = String::new();
+
+    io::stdin()
+        .read_line(&mut guess)
+        .expect("Failed to read line");
+
+    println!("You guessed: {}", guess);
+}
+```
+
+Listing 2-3: Adding code to generate a random number
+
+First, we add a `use` line: `use rand::Rng`. The `Rng` trait defines
+methods that random number generators implement, and this trait must be in
+scope for us to use those methods. Chapter 10 will cover traits in detail.
+
+Next, we’re adding two lines in the middle. The `rand::thread_rng` function
+will give us the particular random number generator that we’re going to use:
+one that is local to the current thread of execution and seeded by the
+operating system. Then we call the `gen_range` method on the random number
+generator. This method is defined by the `Rng` trait that we brought into scope
+with the `use rand::Rng` statement. The `gen_range` method takes a range
+expression as an argument and generates a random number in the range. The kind
+of range expression we’re using here takes the form `start..end`. It’s
+inclusive on the lower bound but exclusive on the upper bound, so we need to
+specify `1..101` to request a number between 1 and 100. Alternatively, we could
+pass the range `1..=100`, which is equivalent.
+
+> Note: You won’t just know which traits to use and which methods and functions
+> to call from a crate. Instructions for using a crate are in each crate’s
+> documentation. Another neat feature of Cargo is that you can run the `cargo
+> doc --open` command, which will build documentation provided by all of your
+> dependencies locally and open it in your browser. If you’re interested in
+> other functionality in the `rand` crate, for example, run `cargo doc --open`
+> and click `rand` in the sidebar on the left.
+
+The second line that we added to the middle of the code prints the secret
+number. This is useful while we’re developing the program to be able to test
+it, but we’ll delete it from the final version. It’s not much of a game if the
+program prints the answer as soon as it starts!
+
+Try running the program a few times:
+
+```
+$ cargo run
+   Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
+    Finished dev [unoptimized + debuginfo] target(s) in 2.53s
+     Running `target/debug/guessing_game`
+Guess the number!
+The secret number is: 7
+Please input your guess.
+4
+You guessed: 4
+
+$ cargo run
+    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
+     Running `target/debug/guessing_game`
+Guess the number!
+The secret number is: 83
+Please input your guess.
+5
+You guessed: 5
+```
+
+You should get different random numbers, and they should all be numbers between
+1 and 100. Great job!
+
+## Comparing the Guess to the Secret Number
+
+Now that we have user input and a random number, we can compare them. That step
+is shown in Listing 2-4. Note that this code won’t compile quite yet, as we
+will explain.
+
+Filename: src/main.rs
+
+```
+use rand::Rng;
+use std::cmp::Ordering;
+use std::io;
+
+fn main() {
+    // --snip--
+
+    println!("You guessed: {}", guess);
+
+    match guess.cmp(&secret_number) {
+        Ordering::Less => println!("Too small!"),
+        Ordering::Greater => println!("Too big!"),
+        Ordering::Equal => println!("You win!"),
+    }
+}
+```
+
+Listing 2-4: Handling the possible return values of
+comparing two numbers
+
+The first new bit here is another `use` statement, bringing a type called
+`std::cmp::Ordering` into scope from the standard library. Like `Result`,
+`Ordering` is another enum, but the variants for `Ordering` are `Less`,
+`Greater`, and `Equal`. These are the three outcomes that are possible when you
+compare two values.
+
+Then we add five new lines at the bottom that use the `Ordering` type. The
+`cmp` method compares two values and can be called on anything that can be
+compared. It takes a reference to whatever you want to compare with: here it’s
+comparing the `guess` to the `secret_number`. Then it returns a variant of the
+`Ordering` enum we brought into scope with the `use` statement. We use a
+`match` expression to decide what to do next based on which variant of
+`Ordering` was returned from the call to `cmp` with the values in `guess` and
+`secret_number`.
+
+A `match` expression is made up of *arms*. An arm consists of a *pattern* and
+the code that should be run if the value given to the beginning of the `match`
+expression fits that arm’s pattern. Rust takes the value given to `match` and
+looks through each arm’s pattern in turn. The `match` construct and patterns
+are powerful features in Rust that let you express a variety of situations your
+code might encounter and make sure that you handle them all. These features
+will be covered in detail in Chapter 6 and Chapter 18, respectively.
+
+Let’s walk through an example of what would happen with the `match` expression
+used here. Say that the user has guessed 50 and the randomly generated secret
+number this time is 38. When the code compares 50 to 38, the `cmp` method will
+return `Ordering::Greater`, because 50 is greater than 38. The `match`
+expression gets the `Ordering::Greater` value and starts checking each arm’s
+pattern. It looks at the first arm’s pattern, `Ordering::Less`, and sees that
+the value `Ordering::Greater` does not match `Ordering::Less`, so it ignores
+the code in that arm and moves to the next arm. The next arm’s pattern,
+`Ordering::Greater`, *does* match `Ordering::Greater`! The associated code in
+that arm will execute and print `Too big!` to the screen. The `match`
+expression ends because it has no need to look at the last arm in this scenario.
+
+However, the code in Listing 2-4 won’t compile yet. Let’s try it:
+
+```
+$ cargo build
+   Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
+error[E0308]: mismatched types
+  --> src/main.rs:22:21
+   |
+22 |     match guess.cmp(&secret_number) {
+   |                     ^^^^^^^^^^^^^^ expected struct `String`, found integer
+   |
+   = note: expected reference `&String`
+              found reference `&{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
+error: could not compile `guessing_game`
+
+To learn more, run the command again with --verbose.
+```
+
+The core of the error states that there are *mismatched types*. Rust has a
+strong, static type system. However, it also has type inference. When we wrote
+`let mut guess = String::new()`, Rust was able to infer that `guess` should be
+a `String` and didn’t make us write the type. The `secret_number`, on the other
+hand, is a number type. A few number types can have a value between 1 and 100:
+`i32`, a 32-bit number; `u32`, an unsigned 32-bit number; `i64`, a 64-bit
+number; as well as others. Rust defaults to an `i32`, which is the type of
+`secret_number` unless you add type information elsewhere that would cause Rust
+to infer a different numerical type. The reason for the error is that Rust
+cannot compare a string and a number type.
+
+Ultimately, we want to convert the `String` the program reads as input into a
+real number type so we can compare it numerically to the secret number. We can
+do that by adding another line to the `main` function body:
+
+Filename: src/main.rs
+
+```
+    // --snip--
+
+    let mut guess = String::new();
+
+    io::stdin()
+        .read_line(&mut guess)
+        .expect("Failed to read line");
+
+    let guess: u32 = guess.trim().parse().expect("Please type a number!");
+
+    println!("You guessed: {}", guess);
+
+    match guess.cmp(&secret_number) {
+        Ordering::Less => println!("Too small!"),
+        Ordering::Greater => println!("Too big!"),
+        Ordering::Equal => println!("You win!"),
+    }
+```
+
+The line is:
+
+```
+let guess: u32 = guess.trim().parse().expect("Please type a number!");
+```
+
+We create a variable named `guess`. But wait, doesn’t the program already have
+a variable named `guess`? It does, but Rust allows us to *shadow* the previous
+value of `guess` with a new one. This feature is often used in situations in
+which you want to convert a value from one type to another type. Shadowing lets
+us reuse the `guess` variable name rather than forcing us to create two unique
+variables, such as `guess_str` and `guess` for example. (Chapter 3 covers
+shadowing in more detail.)
+
+We bind `guess` to the expression `guess.trim().parse()`. The `guess` in the
+expression refers to the original `guess` that was a `String` with the input in
+it. The `trim` method on a `String` instance will eliminate any whitespace at
+the beginning and end. Although `u32` can contain only numerical characters,
+the user must press <span class="keystroke">enter</span> to satisfy
+`read_line`. When the user presses <span class="keystroke">enter</span>, a
+newline character is added to the string. For example, if the user types <span
+class="keystroke">5</span> and presses <span class="keystroke">enter</span>,
+`guess` looks like this: `5\n`. The `\n` represents “newline,” the result of
+pressing <span class="keystroke">enter</span> (On Windows, pressing <span
+class="keystroke">enter</span> results in a carriage return and a newline,
+`\r\n`). The `trim` method eliminates `\n` or `\r\n`, resulting in just `5`.
+
+The `parse` method on strings parses a string into some kind of number. Because
+this method can parse a variety of number types, we need to tell Rust the exact
+number type we want by using `let guess: u32`. The colon (`:`) after `guess`
+tells Rust we’ll annotate the variable’s type. Rust has a few built-in number
+types; the `u32` seen here is an unsigned, 32-bit integer. It’s a good default
+choice for a small positive number. You’ll learn about other number types in
+Chapter 3. Additionally, the `u32` annotation in this example program and the
+comparison with `secret_number` means that Rust will infer that `secret_number`
+should be a `u32` as well. So now the comparison will be between two values of
+the same type!
+
+The call to `parse` could easily cause an error. If, for example, the string
+contained `A👍%`, there would be no way to convert that to a number. Because it
+might fail, the `parse` method returns a `Result` type, much as the `read_line`
+method does (discussed earlier in “Handling Potential Failure with the `Result`
+Type”). We’ll treat this `Result` the same way by using the `expect` method
+again. If `parse` returns an `Err` `Result` variant because it couldn’t create
+a number from the string, the `expect` call will crash the game and print the
+message we give it. If `parse` can successfully convert the string to a number,
+it will return the `Ok` variant of `Result`, and `expect` will return the
+number that we want from the `Ok` value.
+
+Let’s run the program now!
+
+```
+$ cargo run
+   Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
+    Finished dev [unoptimized + debuginfo] target(s) in 0.43s
+     Running `target/debug/guessing_game`
+Guess the number!
+The secret number is: 58
+Please input your guess.
+  76
+You guessed: 76
+Too big!
+```
+
+Nice! Even though spaces were added before the guess, the program still figured
+out that the user guessed 76. Run the program a few times to verify the
+different behavior with different kinds of input: guess the number correctly,
+guess a number that is too high, and guess a number that is too low.
+
+We have most of the game working now, but the user can make only one guess.
+Let’s change that by adding a loop!
+
+## Allowing Multiple Guesses with Looping
+
+The `loop` keyword creates an infinite loop. We’ll add that now to give users
+more chances at guessing the number:
+
+Filename: src/main.rs
+
+```
+    // --snip--
+
+    println!("The secret number is: {}", secret_number);
+
+    loop {
+        println!("Please input your guess.");
+
+        // --snip--
+
+        match guess.cmp(&secret_number) {
+            Ordering::Less => println!("Too small!"),
+            Ordering::Greater => println!("Too big!"),
+            Ordering::Equal => println!("You win!"),
+        }
+    }
+}
+```
+
+As you can see, we’ve moved everything into a loop from the guess input prompt
+onward. Be sure to indent the lines inside the loop another four spaces each
+and run the program again. Notice that there is a new problem because the
+program is doing exactly what we told it to do: ask for another guess forever!
+It doesn’t seem like the user can quit!
+
+The user could always interrupt the program by using the keyboard shortcut
+<span class="keystroke">ctrl-c</span>. But there’s another way to escape this
+insatiable monster, as mentioned in the `parse` discussion in “Comparing the
+Guess to the Secret Number”: if the user enters a non-number answer, the
+program will crash. The user can take advantage of that in order to quit, as
+shown here:
+
+```
+$ cargo run
+   Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
+    Finished dev [unoptimized + debuginfo] target(s) in 1.50s
+     Running `target/debug/guessing_game`
+Guess the number!
+The secret number is: 59
+Please input your guess.
+45
+You guessed: 45
+Too small!
+Please input your guess.
+60
+You guessed: 60
+Too big!
+Please input your guess.
+59
+You guessed: 59
+You win!
+Please input your guess.
+quit
+thread 'main' panicked at 'Please type a number!: ParseIntError { kind: InvalidDigit }', src/main.rs:28:47
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+```
+
+Typing `quit` actually quits the game, but so will any other non-number input.
+However, this is suboptimal to say the least. We want the game to automatically
+stop when the correct number is guessed.
+
+### Quitting After a Correct Guess
+
+Let’s program the game to quit when the user wins by adding a `break` statement:
+
+Filename: src/main.rs
+
+```
+        // --snip--
+
+        match guess.cmp(&secret_number) {
+            Ordering::Less => println!("Too small!"),
+            Ordering::Greater => println!("Too big!"),
+            Ordering::Equal => {
+                println!("You win!");
+                break;
+            }
+        }
+    }
+}
+```
+
+Adding the `break` line after `You win!` makes the program exit the loop when
+the user guesses the secret number correctly. Exiting the loop also means
+exiting the program, because the loop is the last part of `main`.
+
+### Handling Invalid Input
+
+To further refine the game’s behavior, rather than crashing the program when
+the user inputs a non-number, let’s make the game ignore a non-number so the
+user can continue guessing. We can do that by altering the line where `guess`
+is converted from a `String` to a `u32`, as shown in Listing 2-5.
+
+Filename: src/main.rs
+
+```
+        // --snip--
+
+        io::stdin()
+            .read_line(&mut guess)
+            .expect("Failed to read line");
+
+        let guess: u32 = match guess.trim().parse() {
+            Ok(num) => num,
+            Err(_) => continue,
+        };
+
+        println!("You guessed: {}", guess);
+
+        // --snip--
+```
+
+Listing 2-5: Ignoring a non-number guess and asking for another guess instead
+of crashing the program
+
+Switching from an `expect` call to a `match` expression is one way of moving
+from crashing on an error to handling the error. Remember that `parse` returns
+a `Result` type and `Result` is an enum that has the variants `Ok` or `Err`.
+We’re using a `match` expression here, as we did with the `Ordering` result of
+the `cmp` method.
+
+If `parse` is able to successfully turn the string into a number, it will
+return an `Ok` value that contains the resulting number. That `Ok` value will
+match the first arm’s pattern, and the `match` expression will just return the
+`num` value that `parse` produced and put inside the `Ok` value. That number
+will end up right where we want it in the new `guess` variable we’re creating.
+
+If `parse` is *not* able to turn the string into a number, it will return an
+`Err` value that contains more information about the error. The `Err` value
+does not match the `Ok(num)` pattern in the first `match` arm, but it does
+match the `Err(_)` pattern in the second arm. The underscore, `_`, is a
+catchall value; in this example, we’re saying we want to match all `Err`
+values, no matter what information they have inside them. So the program will
+execute the second arm’s code, `continue`, which tells the program to go to the
+next iteration of the `loop` and ask for another guess. So, effectively, the
+program ignores all errors that `parse` might encounter!
+
+Now everything in the program should work as expected. Let’s try it:
+
+```
+$ cargo run
+   Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
+    Finished dev [unoptimized + debuginfo] target(s) in 4.45s
+     Running `target/debug/guessing_game`
+Guess the number!
+The secret number is: 61
+Please input your guess.
+10
+You guessed: 10
+Too small!
+Please input your guess.
+99
+You guessed: 99
+Too big!
+Please input your guess.
+foo
+Please input your guess.
+61
+You guessed: 61
+You win!
+```
+
+Awesome! With one tiny final tweak, we will finish the guessing game. Recall
+that the program is still printing the secret number. That worked well for
+testing, but it ruins the game. Let’s delete the `println!` that outputs the
+secret number. Listing 2-6 shows the final code.
+
+Filename: src/main.rs
+
+```
+use rand::Rng;
+use std::cmp::Ordering;
+use std::io;
+
+fn main() {
+    println!("Guess the number!");
+
+    let secret_number = rand::thread_rng().gen_range(1..101);
+
+    loop {
+        println!("Please input your guess.");
+
+        let mut guess = String::new();
+
+        io::stdin()
+            .read_line(&mut guess)
+            .expect("Failed to read line");
+
+        let guess: u32 = match guess.trim().parse() {
+            Ok(num) => num,
+            Err(_) => continue,
+        };
+
+        println!("You guessed: {}", guess);
+
+        match guess.cmp(&secret_number) {
+            Ordering::Less => println!("Too small!"),
+            Ordering::Greater => println!("Too big!"),
+            Ordering::Equal => {
+                println!("You win!");
+                break;
+            }
+        }
+    }
+}
+```
+
+Listing 2-6: Complete guessing game code
+
+## Summary
+
+At this point, you’ve successfully built the guessing game. Congratulations!
+
+This project was a hands-on way to introduce you to many new Rust concepts:
+`let`, `match`, functions, the use of external crates, and more. In the next
+few chapters, you’ll learn about these concepts in more detail. Chapter 3
+covers concepts that most programming languages have, such as variables, data
+types, and functions, and shows how to use them in Rust. Chapter 4 explores
+ownership, a feature that makes Rust different from other languages. Chapter 5
+discusses structs and method syntax, and Chapter 6 explains how enums work.
index 965b2371f54032b186c0be5dbc051ba288dcca14..925862916eefc7a5b5c60964dae370068ca8ea95 100644 (file)
@@ -27,7 +27,7 @@ overload that operator is listed.
 | `&&` | `expr && expr` | Short-circuiting logical AND | |
 | `*` | `expr * expr` | Arithmetic multiplication | `Mul` |
 | `*=` | `var *= expr` | Arithmetic multiplication and assignment | `MulAssign` |
-| `*` | `*expr` | Dereference | |
+| `*` | `*expr` | Dereference | `Deref` |
 | `*` | `*const type`, `*mut type` | Raw pointer | |
 | `+` | `trait + trait`, `'a + trait` | Compound type constraint | |
 | `+` | `expr + expr` | Arithmetic addition | `Add` |
@@ -38,11 +38,11 @@ overload that operator is listed.
 | `-=` | `var -= expr` | Arithmetic subtraction and assignment | `SubAssign` |
 | `->` | `fn(...) -> type`, <code>&vert;...&vert; -> type</code> | Function and closure return type | |
 | `.` | `expr.ident` | Member access | |
-| `..` | `..`, `expr..`, `..expr`, `expr..expr` | Right-exclusive range literal | |
-| `..=` | `..=expr`, `expr..=expr` | Right-inclusive range literal | |
+| `..` | `..`, `expr..`, `..expr`, `expr..expr` | Right-exclusive range literal | `PartialOrd` |
+| `..=` | `..=expr`, `expr..=expr` | Right-inclusive range literal | `PartialOrd` |
 | `..` | `..expr` | Struct literal update syntax | |
 | `..` | `variant(x, ..)`, `struct_type { x, .. }` | “And the rest” pattern binding | |
-| `...` | `expr...expr` | In a pattern: inclusive range pattern | |
+| `...` | `expr...expr` | (Deprecated, use `..=` instead) In a pattern: inclusive range pattern | |
 | `/` | `expr / expr` | Arithmetic division | `Div` |
 | `/=` | `var /= expr` | Arithmetic division and assignment | `DivAssign` |
 | `:` | `pat: type`, `ident: type` | Constraints | |
index cbd39743c903a26da6900a503925c241d94fb3dd..d95ea675e0b3434cc453c89401c8893f90ee654f 100644 (file)
@@ -8,6 +8,7 @@ For resources in languages other than English. Most are still in progress; see
 - [Português](https://github.com/rust-br/rust-book-pt-br) (BR)
 - [Português](https://github.com/nunojesus/rust-book-pt-pt) (PT)
 - [简体中文](https://github.com/KaiserY/trpl-zh-cn)
+- [正體中文](https://github.com/rust-tw/book-tw)
 - [Українська](https://github.com/pavloslav/rust-book-uk-ua)
 - [Español](https://github.com/thecodix/book), [alternate](https://github.com/ManRR/rust-book-es)
 - [Italiano](https://github.com/AgeOfWar/rust-book-it)
@@ -25,3 +26,5 @@ For resources in languages other than English. Most are still in progress; see
 - [Farsi](https://github.com/pomokhtari/rust-book-fa)
 - [Deutsch](https://github.com/rust-lang-de/rustbook-de)
 - [Turkish](https://github.com/RustDili/dokuman/tree/master/ceviriler), [online](https://rustdili.github.io/)
+- [हिंदी](https://github.com/venkatarun95/rust-book-hindi)
+- [ไทย](https://github.com/rust-lang-th/book-th)
index c3d7c4a6e5d5e649927b284a037c8815ea3f6cf3..2a1b7745c003965ccf45c0b001423f92950e4319 100644 (file)
@@ -173,12 +173,11 @@ and run a random example, it may not compile! Make sure you read the
 surrounding text to see whether the example you’re trying to run is meant to
 error. Ferris will also help you distinguish code that isn’t meant to work:
 
-| Ferris                                                                 | Meaning                                          |
-|------------------------------------------------------------------------|--------------------------------------------------|
-| <img src="img/ferris/does_not_compile.svg" class="ferris-explain"/>    | This code does not compile!                      |
-| <img src="img/ferris/panics.svg" class="ferris-explain"/>              | This code panics!                                |
-| <img src="img/ferris/unsafe.svg" class="ferris-explain"/>              | This code block contains unsafe code.            |
-| <img src="img/ferris/not_desired_behavior.svg" class="ferris-explain"/>| This code does not produce the desired behavior. |
+| Ferris                                                                                                           | Meaning                                          |
+|------------------------------------------------------------------------------------------------------------------|--------------------------------------------------|
+| <img src="img/ferris/does_not_compile.svg" class="ferris-explain" alt="Ferris with a question mark"/>            | This code does not compile!                      |
+| <img src="img/ferris/panics.svg" class="ferris-explain" alt="Ferris throwing up their hands"/>                   | This code panics!                                |
+| <img src="img/ferris/not_desired_behavior.svg" class="ferris-explain" alt="Ferris with one claw up, shrugging"/> | This code does not produce the desired behavior. |
 
 In most situations, we’ll lead you to the correct version of any code that
 doesn’t compile.
index f343d5009413ae184f7b9c4225970f7f5fb1f700..96e45aebd0f7266e906b99dfee814a09f7a0ebed 100644 (file)
@@ -39,13 +39,21 @@ for your password. If the install is successful, the following line will appear:
 Rust is installed now. Great!
 ```
 
-Additionally, you’ll need a linker of some kind. It’s likely one is already
-installed, but when you try to compile a Rust program and get errors indicating
-that a linker could not execute, that means a linker isn’t installed on your
-system and you’ll need to install one manually. C compilers usually come with
-the correct linker. Check your platform’s documentation for how to install a C
-compiler. Also, some common Rust packages depend on C code and will need a C
-compiler. Therefore, it might be worth installing one now.
+You will also need a linker, which is a program that Rust uses to join its
+compiled outputs into one file. It is likely you already have one. If you get
+linker errors, you should install a C compiler, which will typically include a
+linker. A C compiler is also useful because some common Rust packages depend on
+C code and will need a C compiler.
+
+On macOS, you can get a C compiler by running:
+
+```console
+$ xcode-select --install
+```
+
+Linux users should generally install GCC or Clang, according to their
+distribution's documentation. For example, if you use Ubuntu, you can install
+the `build-essential` package.
 
 ### Installing `rustup` on Windows
 
index 69f59dfc9836aeacec93f0671a8da507e1d3a6d9..98ba8807153a698e2629638b044376a3ac7b70d5 100644 (file)
@@ -125,7 +125,8 @@ First, Rust style is to indent with four spaces, not a tab.
 Second, `println!` calls a Rust macro. If it called a function instead, it
 would be entered as `println` (without the `!`). We’ll discuss Rust macros in
 more detail in Chapter 19. For now, you just need to know that using a `!`
-means that you’re calling a macro instead of a normal function.
+means that you’re calling a macro instead of a normal function, and that macros
+don't always follow the same rules as functions.
 
 Third, you see the `"Hello, world!"` string. We pass this string as an argument
 to `println!`, and the string is printed to the screen.
index 0f11be8ade2bba93fca52697d57d321c3cb11e29..2c018a04daa3c6770b3e0c20d70b092b15ca484a 100644 (file)
@@ -3,7 +3,8 @@
 Cargo is Rust’s build system and package manager. Most Rustaceans use this tool
 to manage their Rust projects because Cargo handles a lot of tasks for you,
 such as building your code, downloading the libraries your code depends on, and
-building those libraries. (We call libraries your code needs *dependencies*.)
+building those libraries. (We call the libraries that your code needs
+*dependencies*.)
 
 The simplest Rust programs, like the one we’ve written so far, don’t have any
 dependencies. So if we had built the “Hello, world!” project with Cargo, it
@@ -63,7 +64,6 @@ code in Listing 1-2.
 [package]
 name = "hello_cargo"
 version = "0.1.0"
-authors = ["Your Name <you@example.com>"]
 edition = "2018"
 
 [dependencies]
@@ -79,11 +79,9 @@ The first line, `[package]`, is a section heading that indicates that the
 following statements are configuring a package. As we add more information to
 this file, we’ll add other sections.
 
-The next four lines set the configuration information Cargo needs to compile
-your program: the name, the version, who wrote it, and the edition of Rust to
-use. Cargo gets your name and email information from your environment, so if
-that information is not correct, fix the information now and then save the
-file. We’ll talk about the `edition` key in Appendix E.
+The next three lines set the configuration information Cargo needs to compile
+your program: the name, the version, and the edition of Rust to use. We’ll talk
+about the `edition` key in [Appendix E][appendix-e]<!-- ignore -->.
 
 The last line, `[dependencies]`, is the start of a section for you to list any
 of your project’s dependencies. In Rust, packages of code are referred to as
@@ -249,3 +247,4 @@ If you would rather start by learning how common programming concepts work in
 Rust, see Chapter 3 and then return to Chapter 2.
 
 [installation]: ch01-01-installation.html#installation
+[appendix-e]: appendix-05-editions.html
index ba494eb944d91c105100782c9c79b4036b7649c7..761dc218a9731bcb1355e21fcecb415476af312d 100644 (file)
@@ -34,9 +34,6 @@ Look at the generated *Cargo.toml* file:
 {{#include ../listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.toml}}
 ```
 
-If the author information that Cargo obtained from your environment is not
-correct, fix that in the file and save it again.
-
 As you saw in Chapter 1, `cargo new` generates a “Hello, world!” program for
 you. Check out the *src/main.rs* file:
 
@@ -125,19 +122,18 @@ line. Notice that this is a `let` statement, which is used to create a
 *variable*. Here’s another example:
 
 ```rust,ignore
-let foo = bar;
+let apples = 5;
 ```
 
-This line creates a new variable named `foo` and binds it to the value of the
-`bar` variable. In Rust, variables are immutable by default. We’ll be
-discussing this concept in detail in the [“Variables and
-Mutability”][variables-and-mutability]<!-- ignore --> section in Chapter 3.
-The following example shows how to use `mut` before the variable name to make
-a variable mutable:
+This line creates a new variable named `apples` and binds it to the value 5. In
+Rust, variables are immutable by default. We’ll be discussing this concept in
+detail in the [“Variables and Mutability”][variables-and-mutability]<!-- ignore
+--> section in Chapter 3. The following example shows how to use `mut` before
+the variable name to make a variable mutable:
 
 ```rust,ignore
-let foo = 5; // immutable
-let mut bar = 5; // mutable
+let apples = 5; // immutable
+let mut bananas = 5; // mutable
 ```
 
 > Note: The `//` syntax starts a comment that continues until the end of the
@@ -154,9 +150,8 @@ library that is a growable, UTF-8 encoded bit of text.
 [string]: ../std/string/struct.String.html
 
 The `::` syntax in the `::new` line indicates that `new` is an *associated
-function* of the `String` type. An associated function is implemented on a type,
-in this case `String`, rather than on a particular instance of a `String`. Some
-languages call this a *static method*.
+function* of the `String` type. An associated function is implemented on a
+type, in this case `String`.
 
 This `new` function creates a new, empty string. You’ll find a `new` function
 on many types, because it’s a common name for a function that makes a new value
@@ -212,9 +207,9 @@ is this method:
 {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:expect}}
 ```
 
-When you call a method with the `.foo()` syntax, it’s often wise to introduce a
-newline and other whitespace to help break up long lines. We could have
-written this code as:
+When you call a method with the `.method_name()` syntax, it’s often wise to
+introduce a newline and other whitespace to help break up long lines. We could
+have written this code as:
 
 ```rust,ignore
 io::stdin().read_line(&mut guess).expect("Failed to read line");
@@ -332,17 +327,17 @@ library. However, the Rust team does provide a [`rand` crate][randcrate].
 
 ### Using a Crate to Get More Functionality
 
-Remember that a crate is a collection of Rust source code files.
-The project we’ve been building is a *binary crate*, which is an executable.
-The `rand` crate is a *library crate*, which contains code intended to be
-used in other programs.
+Remember that a crate is a collection of Rust source code files. The project
+we’ve been building is a *binary crate*, which is an executable. The `rand`
+crate is a *library crate*, which contains code intended to be used in other
+programs.
 
-Cargo’s use of external crates is where it really shines. Before we can write
-code that uses `rand`, we need to modify the *Cargo.toml* file to include the
-`rand` crate as a dependency. Open that file now and add the following line to
-the bottom beneath the `[dependencies]` section header that Cargo created for
-you. Be sure to specify `rand` exactly as we have here, or the code examples in
-this tutorial may not work.
+Cargo’s coordination of external crates is where Cargo really shines. Before we
+can write code that uses `rand`, we need to modify the *Cargo.toml* file to
+include the `rand` crate as a dependency. Open that file now and add the
+following line to the bottom beneath the `[dependencies]` section header that
+Cargo created for you. Be sure to specify `rand` exactly as we have here, or
+the code examples in this tutorial may not work.
 
 <!-- When updating the version of `rand` used, also update the version of
 `rand` used in these files so they all match:
@@ -452,9 +447,9 @@ your part of the code.
 Cargo has a mechanism that ensures you can rebuild the same artifact every time
 you or anyone else builds your code: Cargo will use only the versions of the
 dependencies you specified until you indicate otherwise. For example, what
-happens if next week version 0.8.4 of the `rand` crate comes out and
-contains an important bug fix but also contains a regression that will break
-your code?
+happens if next week version 0.8.4 of the `rand` crate comes out, and that
+version contains an important bug fix, but it also contains a regression that
+will break your code?
 
 The answer to this problem is the *Cargo.lock* file, which was created the
 first time you ran `cargo build` and is now in your *guessing_game* directory.
@@ -843,11 +838,11 @@ is converted from a `String` to a `u32`, as shown in Listing 2-5.
 <span class="caption">Listing 2-5: Ignoring a non-number guess and asking for
 another guess instead of crashing the program</span>
 
-Switching from an `expect` call to a `match` expression is how you generally
-move from crashing on an error to handling the error. Remember that `parse`
-returns a `Result` type and `Result` is an enum that has the variants `Ok` or
-`Err`. We’re using a `match` expression here, as we did with the `Ordering`
-result of the `cmp` method.
+Switching from an `expect` call to a `match` expression is one way of moving
+from crashing on an error to handling the error. Remember that `parse` returns
+a `Result` type and `Result` is an enum that has the variants `Ok` or `Err`.
+We’re using a `match` expression here, as we did with the `Ordering` result of
+the `cmp` method.
 
 If `parse` is able to successfully turn the string into a number, it will
 return an `Ok` value that contains the resulting number. That `Ok` value will
@@ -917,13 +912,12 @@ secret number. Listing 2-6 shows the final code.
 At this point, you’ve successfully built the guessing game. Congratulations!
 
 This project was a hands-on way to introduce you to many new Rust concepts:
-`let`, `match`, methods, associated functions, the use of external crates, and
-more. In the next few chapters, you’ll learn about these concepts in more
-detail. Chapter 3 covers concepts that most programming languages have, such as
-variables, data types, and functions, and shows how to use them in Rust.
-Chapter 4 explores ownership, a feature that makes Rust different from other
-languages. Chapter 5 discusses structs and method syntax, and Chapter 6
-explains how enums work.
+`let`, `match`, functions, the use of external crates, and more. In the next
+few chapters, you’ll learn about these concepts in more detail. Chapter 3
+covers concepts that most programming languages have, such as variables, data
+types, and functions, and shows how to use them in Rust. Chapter 4 explores
+ownership, a feature that makes Rust different from other languages. Chapter 5
+discusses structs and method syntax, and Chapter 6 explains how enums work.
 
 [variables-and-mutability]:
 ch03-01-variables-and-mutability.html#variables-and-mutability
index 65df18b8e1e587ff6d23d8538b0137e046af241e..b97713b35ae724eef2bd40be8ae0bd184b3aff8b 100644 (file)
@@ -73,8 +73,10 @@ program is running on: 64 bits if you’re on a 64-bit architecture and 32 bits
 if you’re on a 32-bit architecture.
 
 You can write integer literals in any of the forms shown in Table 3-2. Note
-that all number literals except the byte literal allow a type suffix, such as
-`57u8`, and `_` as a visual separator, such as `1_000`.
+that number literals that can be multiple numeric types allow a type suffix,
+such as `57u8`, to designate the type. Number literals can also use `_` as a
+visual separator to make the number easier to read, such as `1_000`, which will
+have the same value as if you had specified `1000`.
 
 <span class="caption">Table 3-2: Integer Literals in Rust</span>
 
@@ -87,9 +89,9 @@ that all number literals except the byte literal allow a type suffix, such as
 | Byte (`u8` only) | `b'A'`        |
 
 So how do you know which type of integer to use? If you’re unsure, Rust’s
-defaults are generally good choices, and integer types default to `i32`: this
-type is generally the fastest, even on 64-bit systems. The primary situation in
-which you’d use `isize` or `usize` is when indexing some sort of collection.
+defaults are generally good places to start: integer types default to `i32`.
+The primary situation in which you’d use `isize` or `usize` is when indexing
+some sort of collection.
 
 > ##### Integer Overflow
 >
index a6008f4b3a1ffec0d25b87807be8c5f5759ead2c..a6b464439103ffc9fc783912ee5abe4cca2bfe6c 100644 (file)
@@ -119,17 +119,18 @@ in the slice and `ending_index` is one more than the last position in the
 slice. Internally, the slice data structure stores the starting position and
 the length of the slice, which corresponds to `ending_index` minus
 `starting_index`. So in the case of `let world = &s[6..11];`, `world` would be
-a slice that contains a pointer to the 7th byte (counting from 1) of `s` with a length value of 5.
+a slice that contains a pointer to the byte at index 6 of `s` with a length
+value of 5.
 
 Figure 4-6 shows this in a diagram.
 
-<img alt="world containing a pointer to the 6th byte of String s and a length 5" src="img/trpl04-06.svg" class="center" style="width: 50%;" />
+<img alt="world containing a pointer to the byte at index 6 of String s and a length 5" src="img/trpl04-06.svg" class="center" style="width: 50%;" />
 
 <span class="caption">Figure 4-6: String slice referring to part of a
 `String`</span>
 
-With Rust’s `..` range syntax, if you want to start at the first index (zero),
-you can drop the value before the two periods. In other words, these are equal:
+With Rust’s `..` range syntax, if you want to start at index zero, you can drop
+the value before the two periods. In other words, these are equal:
 
 ```rust
 let s = String::from("hello");
@@ -255,9 +256,12 @@ and `&str` values.
 a string slice for the type of the `s` parameter</span>
 
 If we have a string slice, we can pass that directly. If we have a `String`, we
-can pass a slice of the entire `String`. Defining a function to take a string
-slice instead of a reference to a `String` makes our API more general and useful
-without losing any functionality:
+can pass a slice of the `String` or a reference to the `String`. This
+flexibility takes advantage of *deref coercions*, a feature we will cover in
+the [“Implicit Deref Coercions with Functions and
+Methods”][deref-coercions]<!--ignore--> section of Chapter 15. Defining a
+function to take a string slice instead of a reference to a `String` makes our
+API more general and useful without losing any functionality:
 
 <span class="filename">Filename: src/main.rs</span>
 
@@ -303,3 +307,4 @@ these concepts further throughout the rest of the book. Let’s move on to
 Chapter 5 and look at grouping pieces of data together in a `struct`.
 
 [strings]: ch08-02-strings.html#storing-utf-8-encoded-text-with-strings
+[deref-coercions]: ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods
index be794ce5b50042917025981861f722d173cf630a..24b2130ba34834bb758ed441a24469ec6612ad5d 100644 (file)
@@ -141,7 +141,7 @@ different amounts and types of values</span>
 This enum has four variants with different types:
 
 * `Quit` has no data associated with it at all.
-* `Move` includes an anonymous struct inside it.
+* `Move` has named fields like a struct does.
 * `Write` includes a single `String`.
 * `ChangeColor` includes three `i32` values.
 
@@ -222,8 +222,8 @@ as follows:
 
 ```rust
 enum Option<T> {
-    Some(T),
     None,
+    Some(T),
 }
 ```
 
index a24b608f48a6eb2ce11924b427642a8087983a80..7292726128ca3e2b09d9fb66238dca831f4fb034 100644 (file)
@@ -8,8 +8,8 @@ Privacy”][modules]<!-- ignore --> section). A *package* is one or more crates
 that provide a set of functionality. A package contains a *Cargo.toml* file
 that describes how to build those crates.
 
-Several rules determine what a package can contain. A package *must* contain
-zero or one library crates, and no more. It can contain as many binary crates
+Several rules determine what a package can contain. A package can contain
+at most one library crate. It can contain as many binary crates
 as you’d like, but it must contain at least one crate (either library or
 binary).
 
index 3e4f1aa69b0ee05924467bdc09ddac0f148cc359..dd59ae6061f5ce7707280b2b3310592c7293c737 100644 (file)
@@ -59,10 +59,11 @@ into scope with `use`, which is unidiomatic</span>
 
 Although both Listing 7-11 and 7-13 accomplish the same task, Listing 7-11 is
 the idiomatic way to bring a function into scope with `use`. Bringing the
-function’s parent module into scope with `use` so we have to specify the parent
-module when calling the function makes it clear that the function isn’t locally
-defined while still minimizing repetition of the full path. The code in Listing
-7-13 is unclear as to where `add_to_waitlist` is defined.
+function’s parent module into scope with `use` means we have to specify the
+parent module when calling the function. Specifying the parent module when
+calling the function makes it clear that the function isn’t locally defined
+while still minimizing repetition of the full path. The code in Listing 7-13 is
+unclear as to where `add_to_waitlist` is defined.
 
 On the other hand, when bringing in structs, enums, and other items with `use`,
 it’s idiomatic to specify the full path. Listing 7-14 shows the idiomatic way
index 18314e9bbff1a3875e22dabd00dadcd8eb123c6c..9daefa91aa940e507236b331289214fdd8c026a7 100644 (file)
@@ -211,7 +211,8 @@ combining, we can use the `format!` macro:
 This code also sets `s` to `tic-tac-toe`. The `format!` macro works in the same
 way as `println!`, but instead of printing the output to the screen, it returns
 a `String` with the contents. The version of the code using `format!` is much
-easier to read and doesn’t take ownership of any of its parameters.
+easier to read, and the code generated by the `format!` macro uses references
+so that this call doesn’t take ownership of any of its parameters.
 
 ### Indexing into Strings
 
index 12f6b6e3208ec16d4e075873946e3d283e1f738e..2708f1179029e6a8d670d99179d7fd41d5842660 100644 (file)
@@ -49,9 +49,9 @@ the [”Processing a Series of Items with Iterators” section of Chapter
 13][iterators]<!-- ignore -->. The `collect` method gathers data into a number
 of collection types, including `HashMap`. For example, if we had the team names
 and initial scores in two separate vectors, we could use the `zip` method to
-create a vector of tuples where “Blue” is paired with 10, and so forth. Then we
-could use the `collect` method to turn that vector of tuples into a hash map,
-as shown in Listing 8-21.
+create an iterator of tuples where “Blue” is paired with 10, and so forth. Then
+we could use the `collect` method to turn that iterator of tuples into a hash
+map, as shown in Listing 8-21.
 
 ```rust
 {{#rustdoc_include ../listings/ch08-common-collections/listing-08-21/src/main.rs:here}}
@@ -207,7 +207,7 @@ loop, so all of these changes are safe and allowed by the borrowing rules.
 
 ### Hashing Functions
 
-By default, `HashMap` uses a hashing function called SipHash that can provide 
+By default, `HashMap` uses a hashing function called SipHash that can provide
 resistance to Denial of Service (DoS) attacks involving hash tables[^siphash]. This
 is not the fastest hashing algorithm available, but the trade-off for better
 security that comes with the drop in performance is worth it. If you profile
index abfc001a104ef06c7ef52fd4aaa3683850ad7b7d..083b767f599400f9517182a47e2d1872c0e6364e 100644 (file)
@@ -2,8 +2,8 @@
 
 A *trait* tells the Rust compiler about functionality a particular type has and
 can share with other types. We can use traits to define shared behavior in an
-abstract way. We can use trait bounds to specify that a generic can be any type
-that has certain behavior.
+abstract way. We can use trait bounds to specify that a generic type can be any
+type that has certain behavior.
 
 > Note: Traits are similar to a feature often called *interfaces* in other
 > languages, although with some differences.
@@ -404,6 +404,9 @@ reference to a `T` value in the slice. If we change the return type to `&T`
 instead of `T`, thereby changing the body of the function to return a
 reference, we wouldn’t need the `Clone` or `Copy` trait bounds and we could
 avoid heap allocations. Try implementing these alternate solutions on your own!
+If you get stuck with errors having to do with lifetimes, keep reading: the
+“Validating References with Lifetimes” section coming up will explain, but
+lifetimes aren't required to solve these challenges.
 
 ### Using Trait Bounds to Conditionally Implement Methods
 
index 2110ff14c1181baf37e8638e6b4c8d4429d9216b..ea4c142426428539cec215a615368d79257f550f 100644 (file)
@@ -66,9 +66,12 @@ Consider the code in Listing 11-12 with the private function `internal_adder`.
 
 <span class="caption">Listing 11-12: Testing a private function</span>
 
-Note that the `internal_adder` function is not marked as `pub`, but because
-tests are just Rust code and the `tests` module is just another module, you can
-bring `internal_adder` into a test’s scope and call it. If you don’t think
+Note that the `internal_adder` function is not marked as `pub`. Tests are just
+Rust code, and the `tests` module is just another module. As we discussed in
+the [“Paths for Referring to an Item in the Module Tree”][paths]<!-- ignore -->
+section, items in child modules can use the items in their ancestor modules. In
+this test, we bring all of the `test` module’s parent’s items into scope with
+`use super::*`, and then the test can call `internal_adder`. If you don’t think
 private functions should be tested, there’s nothing in Rust that will compel
 you to do so.
 
@@ -235,5 +238,6 @@ reduce logic bugs having to do with how your code is expected to behave.
 Let’s combine the knowledge you learned in this chapter and in previous
 chapters to work on a project!
 
+[paths]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html
 [separating-modules-into-files]:
 ch07-05-separating-modules-into-different-files.html
index d079439c67e5afe4646772287fca985cd38fbf22..bf3e4f1f52bb642beb87159e737c57c4fa0e26c2 100644 (file)
@@ -48,8 +48,10 @@ yet.
 function we wish we had</span>
 
 This test searches for the string `"duct"`. The text we’re searching is three
-lines, only one of which contains `"duct"`. We assert that the value returned
-from the `search` function contains only the line we expect.
+lines, only one of which contains `"duct"` (Note that the backslash after the
+opening double quote tells Rust not to put a newline character at the beginning
+of the contents of this string literal). We assert that the value returned from
+the `search` function contains only the line we expect.
 
 We aren’t able to run this test and watch it fail because the test doesn’t even
 compile: the `search` function doesn’t exist yet! So now we’ll add just enough
index 86457e83854e049688a01daab1aab43dbc58edfc..6554df4dfa92d3acac1f7f8543a35da4048d096d 100644 (file)
@@ -18,7 +18,7 @@ tests, as shown in Listing 12-20.
 
 <span class="filename">Filename: src/lib.rs</span>
 
-```rust,noplayground
+```rust,ignore,does_not_compile
 {{#rustdoc_include ../listings/ch12-an-io-project/listing-12-20/src/lib.rs:here}}
 ```
 
index eacb1ba80b9f0e685017b870adadb4c5951dc130..5d09bf2940f937d6d5bcfa9953f7103fa797f3fd 100644 (file)
@@ -1,8 +1,8 @@
 ## Comparing Performance: Loops vs. Iterators
 
-To determine whether to use loops or iterators, you need to know which version
-of our `search` functions is faster: the version with an explicit `for` loop or
-the version with iterators.
+To determine whether to use loops or iterators, you need to know which
+implementation is faster: the version of the `search` function with an explicit
+`for` loop or the version with iterators.
 
 We ran a benchmark by loading the entire contents of *The Adventures of
 Sherlock Holmes* by Sir Arthur Conan Doyle into a `String` and looking for the
index b9f43fb0bc9aa52801b81bf60b1747c44794b2ba..4fde74a2ace770d5511558e2444ca8b820085ac5 100644 (file)
@@ -177,7 +177,7 @@ function named `mix`, as shown in Listing 14-3:
 <span class="filename">Filename: src/lib.rs</span>
 
 ```rust,noplayground,test_harness
-{{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-03/src/lib.rs}}
+{{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-03/src/lib.rs:here}}
 ```
 
 <span class="caption">Listing 14-3: An `art` library with items organized into
@@ -360,8 +360,7 @@ same way as Rust by using a dual license of `MIT OR Apache-2.0`. This practice
 demonstrates that you can also specify multiple license identifiers separated
 by `OR` to have multiple licenses for your project.
 
-With a unique name, the version, the author details that `cargo new` added
-when you created the crate, your description, and a license added, the
+With a unique name, the version, your description, and a license added, the
 *Cargo.toml* file for a project that is ready to publish might look like this:
 
 <span class="filename">Filename: Cargo.toml</span>
@@ -370,7 +369,6 @@ when you created the crate, your description, and a license added, the
 [package]
 name = "guessing_game"
 version = "0.1.0"
-authors = ["Your Name <you@example.com>"]
 edition = "2018"
 description = "A fun game where you guess what number the computer has chosen."
 license = "MIT OR Apache-2.0"
index 9030df02b209bd1b7bcd4862e600fee4dba9e3f9..1daa39ddb70bcb58b77fc3ad8441285bf9d2a019 100644 (file)
@@ -185,7 +185,7 @@ Listing 15-9.
 and methods. Deref coercion works only on types that implement the `Deref`
 trait. Deref coercion converts such a type into a reference to another type.
 For example, deref coercion can convert `&String` to `&str` because `String`
-implements the `Deref` trait such that it returns `str`. Deref coercion happens
+implements the `Deref` trait such that it returns `&str`. Deref coercion happens
 automatically when we pass a reference to a particular type’s value as an
 argument to a function or method that doesn’t match the parameter type in the
 function or method definition. A sequence of calls to the `deref` method
index fb685bc5e99c1ee376d1023c8506a6b04e38e3b0..6b753b5e41ac213d7d99ee1695e1b0b31406d759 100644 (file)
@@ -9,9 +9,9 @@ edges pointing to it.
 
 To enable multiple ownership, Rust has a type called `Rc<T>`, which is an
 abbreviation for *reference counting*. The `Rc<T>` type keeps track of the
-number of references to a value which determines whether or not a value is
-still in use. If there are zero references to a value, the value can be cleaned
-up without any references becoming invalid.
+number of references to a value to determine whether or not the value is still
+in use. If there are zero references to a value, the value can be cleaned up
+without any references becoming invalid.
 
 Imagine `Rc<T>` as a TV in a family room. When one person enters to watch TV,
 they turn it on. Others can come into the room and watch the TV. When the last
index 90535ddfa71dc7411f3abd9b358bbf9de5672522..4f774fea8c3b7ba046443a70ed0bcd6975a19487 100644 (file)
@@ -305,10 +305,12 @@ We would get this error:
 ```
 
 This error means you can’t use this trait as a trait object in this way. If
-you’re interested in more details on object safety, see [Rust RFC 255].
+you’re interested in more details on object safety, see [Rust RFC 255] or check the
+object safety section in the [Rust Reference][object-safety-reference].
 
 [Rust RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md
 
 [performance-of-code-using-generics]:
 ch10-01-syntax.html#performance-of-code-using-generics
 [dynamically-sized]: ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
+[object-safety-reference]: ../reference/items/traits.html#object-safety
index 5dc2f81cee87f501db68442667c18e19cd7fc648..4eb5f3af98ebaeab1b27a83b8d6cba28053004b9 100644 (file)
@@ -125,7 +125,7 @@ Recall that we can create raw pointers in safe code, but we can’t *dereference
 raw pointers and read the data being pointed to. In Listing 19-3, we use the
 dereference operator `*` on a raw pointer that requires an `unsafe` block.
 
-```rust,unsafe
+```rust
 {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-03/src/main.rs:here}}
 ```
 
@@ -166,7 +166,7 @@ responsibility for upholding the function’s contracts.
 Here is an unsafe function named `dangerous` that doesn’t do anything in its
 body:
 
-```rust,unsafe
+```rust
 {{#rustdoc_include ../listings/ch19-advanced-features/no-listing-01-unsafe-fn/src/main.rs:here}}
 ```
 
@@ -240,7 +240,7 @@ know code is okay, but Rust doesn’t, it’s time to reach for unsafe code.
 Listing 19-6 shows how to use an `unsafe` block, a raw pointer, and some calls
 to unsafe functions to make the implementation of `split_at_mut` work.
 
-```rust,unsafe
+```rust
 {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-06/src/main.rs:here}}
 ```
 
@@ -282,7 +282,7 @@ In contrast, the use of `slice::from_raw_parts_mut` in Listing 19-7 would
 likely crash when the slice is used. This code takes an arbitrary memory
 location and creates a slice 10,000 items long.
 
-```rust,unsafe
+```rust
 {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-07/src/main.rs:here}}
 ```
 
@@ -309,7 +309,7 @@ responsibility falls on the programmer to ensure safety.
 
 <span class="filename">Filename: src/main.rs</span>
 
-```rust,unsafe
+```rust
 {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-08/src/main.rs}}
 ```
 
@@ -370,11 +370,10 @@ Static variables are similar to constants, which we discussed in the
 [“Differences Between Variables and
 Constants”][differences-between-variables-and-constants]<!-- ignore -->
 section in Chapter 3. The names of static variables are in
-`SCREAMING_SNAKE_CASE` by convention, and we *must* annotate the variable’s
-type, which is `&'static str` in this example. Static variables can only store
+`SCREAMING_SNAKE_CASE` by convention. Static variables can only store
 references with the `'static` lifetime, which means the Rust compiler can
-figure out the lifetime; we don’t need to annotate it explicitly. Accessing an
-immutable static variable is safe.
+figure out the lifetime and we aren’t required to annotate it explicitly.
+Accessing an immutable static variable is safe.
 
 Constants and immutable static variables might seem similar, but a subtle
 difference is that values in a static variable have a fixed address in memory.
@@ -388,7 +387,7 @@ static variable named `COUNTER`.
 
 <span class="filename">Filename: src/main.rs</span>
 
-```rust,unsafe
+```rust
 {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-10/src/main.rs}}
 ```
 
@@ -415,7 +414,7 @@ can’t verify. We can declare that a trait is `unsafe` by adding the `unsafe`
 keyword before `trait` and marking the implementation of the trait as `unsafe`
 too, as shown in Listing 19-11.
 
-```rust,unsafe
+```rust
 {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-11/src/main.rs}}
 ```
 
index 1d396463ec53df204c4eb2beed00f2836040b388..79b2e42d90cefae23dc075201eb00c4544717382 100644 (file)
@@ -137,9 +137,12 @@ the `Add` trait where we want to customize the `Rhs` type rather than using the
 default.
 
 We have two structs, `Millimeters` and `Meters`, holding values in different
-units. We want to add values in millimeters to values in meters and have the
-implementation of `Add` do the conversion correctly. We can implement `Add` for
-`Millimeters` with `Meters` as the `Rhs`, as shown in Listing 19-15.
+units. This thin wrapping of an existing type in another struct is known as the
+*newtype pattern*, which we describe in more detail in the [“Using the Newtype
+Pattern to Implement External Traits on External Types”][newtype]<!-- ignore
+--> section. We want to add values in millimeters to values in meters and have
+the implementation of `Add` do the conversion correctly. We can implement `Add`
+for `Millimeters` with `Meters` as the `Rhs`, as shown in Listing 19-15.
 
 <span class="filename">Filename: src/lib.rs</span>
 
@@ -451,6 +454,7 @@ Now you know how the newtype pattern is used in relation to traits; it’s also
 useful pattern even when traits are not involved. Let’s switch focus and look
 at some advanced ways to interact with Rust’s type system.
 
+[newtype]: ch19-04-advanced-types.html#using-the-newtype-pattern-for-type-safety-and-abstraction
 [implementing-a-trait-on-a-type]:
 ch10-02-traits.html#implementing-a-trait-on-a-type
 [the-iterator-trait-and-the-next-method]:
index a4b1d1d3c215825b1d5120b6c3fda9c7d1776934..bfc77c9e484de74ddcd844288fc785bb9879eda5 100644 (file)
@@ -6,12 +6,12 @@ examine why newtypes are useful as types. Then we’ll move on to type aliases,
 feature similar to newtypes but with slightly different semantics. We’ll also
 discuss the `!` type and dynamically sized types.
 
-> Note: The next section assumes you’ve read the earlier section [“Using the
+### Using the Newtype Pattern for Type Safety and Abstraction
+
+> Note: This section assumes you’ve read the earlier section [“Using the
 > Newtype Pattern to Implement External Traits on External
 > Types.”][using-the-newtype-pattern]<!-- ignore -->
 
-### Using the Newtype Pattern for Type Safety and Abstraction
-
 The newtype pattern is useful for tasks beyond those we’ve discussed so far,
 including statically enforcing that values are never confused and indicating
 the units of a value. You saw an example of using newtypes to indicate units in
@@ -274,8 +274,9 @@ restriction:
 {{#rustdoc_include ../listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/src/lib.rs}}
 ```
 
-A trait bound on `?Sized` is the opposite of a trait bound on `Sized`: we would
-read this as “`T` may or may not be `Sized`.” This syntax is only available for
+A trait bound on `?Sized` means “`T` may or may not be `Sized`” and this
+notation overrides the default that generic types must have a known size at
+compile time. The `?Trait` syntax with this meaning is only available for
 `Sized`, not any other traits.
 
 Also note that we switched the type of the `t` parameter from `T` to `&T`.
index a714413b6f32a9075cf12133227154bdda5d24d3..fe2605fd81d23281f79ca91586ec3b480ab7182b 100644 (file)
@@ -151,9 +151,9 @@ effectively deprecated. With this in mind, as well as the fact that most Rust
 programmers will *use* macros more than *write* macros, we won’t discuss
 `macro_rules!` any further. To learn more about how to write macros, consult
 the online documentation or other resources, such as [“The Little Book of Rust
-Macros”][tlborm].
+Macros”][tlborm] started by Daniel Keep and continued by Lukas Wirth.
 
-[tlborm]: https://danielkeep.github.io/tlborm/book/index.html
+[tlborm]: https://veykril.github.io/tlborm/
 
 ### Procedural Macros for Generating Code from Attributes
 
index 24c7206979ca9a26642ff5b0b044bdc0e785c1c3..244f8e53fb53fa8d99783daa41726de0b9baef7d 100644 (file)
@@ -226,8 +226,9 @@ shows us the following:
 ```rust,ignore
 pub fn spawn<F, T>(f: F) -> JoinHandle<T>
     where
-        F: FnOnce() -> T + Send + 'static,
-        T: Send + 'static
+        F: FnOnce() -> T,
+        F: Send + 'static,
+        T: Send + 'static,
 ```
 
 The `F` type parameter is the one we’re concerned with here; the `T` type
@@ -321,8 +322,9 @@ the `thread::spawn` signature:
 ```rust,ignore
 pub fn spawn<F, T>(f: F) -> JoinHandle<T>
     where
-        F: FnOnce() -> T + Send + 'static,
-        T: Send + 'static
+        F: FnOnce() -> T,
+        F: Send + 'static,
+        T: Send + 'static,
 ```
 
 The `spawn` function returns a `JoinHandle<T>`, where `T` is the type that the
diff --git a/src/doc/book/src/img/ferris/unsafe.svg b/src/doc/book/src/img/ferris/unsafe.svg
deleted file mode 100644 (file)
index d4fdc08..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-        width="1240.298px" height="811.376px" viewBox="0 0 1240.298 811.376" enable-background="new 0 0 1240.298 811.376"
-        xml:space="preserve">
-<!--<rect fill="#FFFFFF" width="1240.298" height="811.376"/>-->
-<rect x="303.062" y="408.688" fill="#E33D27" width="440" height="322.312"/>
-<polygon fill="#F37056" points="548.062,459 543.062,491 595.48,475 631.558,487 620.149,516.493 673.576,524.134 713.745,584
-       700.062,644.844 753.914,671 780.201,542.318 678.062,433.837 "/>
-<ellipse fill="#FFFFFF" cx="456.505" cy="603.308" rx="20.83" ry="41.536"/>
-<ellipse fill="#FFFFFF" cx="613.519" cy="599.293" rx="18.039" ry="25.608"/>
-<path d="M426.848,565.302c76.475-36.052,82.274,92.731,23.019,92.075C407.91,656.909,399.502,592.939,426.848,565.302z
-        M472.886,588.319c-3.647-13.308-14.517-15.274-25.896-8.632C411.107,600.633,485.029,632.633,472.886,588.319z"/>
-<path d="M593.734,565.302c63.543-6.768,43.711,98.739,0,97.828C549.726,662.215,539.183,571.111,593.734,565.302z M616.753,614.216
-       c8.869-6.019,6.418-24.879,0-31.65C586.653,575.41,587.316,620.858,616.753,614.216z"/>
-<path fill="#E33D27" d="M1218.119,680.395c7.154,1.962-4.255,8.762-5.754,11.51c-40.783-1.407-71.586-8.146-97.83,5.754
-       c-14.517-1.252-39.852-13.043-46.037,2.878c14.931,25.351,67.049,13.519,89.197,31.651c-12.87,18.54-39.345,5.012-57.547,5.754
-       c-10.099,0.416-19.838,5.935-28.774,5.755c-49.039-0.988-101.843-22.372-152.498-23.019c42.625,23.559,115.104,17.253,155.376,43.16
-       c-67.472,4.49-120.696-26.278-187.028-17.264c-6.34,0.861-6.592,6.33-11.509,5.754c-13.465-1.579-23.525-15.382-40.283-5.754
-       c-6.26,5.23,6.261,17.787,0,23.018c-15.253-0.503-14.684-1.859-28.772,0c8.165-6.89,2.844-10.598,2.877-23.018
-       c-13.752,2.551-9.706,22.902-25.896,23.018c-10.812-10.287-27.408-14.791-37.405-25.896c-12.972,3.333-5.671,26.937-17.265,31.65
-       c-14.173-3.091-17.477-17.048-23.019-28.772c-3.136,10.441-20.8,16.528-28.773,5.754c-2.085,8.801,4.968,8.464,2.878,17.264
-       c-18.137,3.755-22.952-5.821-37.406-5.754c0.949-12.456-3.963-19.055-11.51-23.019c4.176,9.359,9.97,28.835,2.877,40.283
-       c58.823,6.435-102.298,3.786-184.15,5.755c-4.103-3.839-4.103-16.305,0-20.142c-3.242-3.983-16.786,6.063-25.896,5.754
-       c-3.692-3.776-3.692-10.61,0-14.387c-22.912,6.714-41.991-16.95-51.792,2.878c-22.355-21.002-38.624,9.456-63.301,11.509
-       c-0.208-9.795,8.463-10.717,14.387-14.387c-1.225-5.487-8.217-5.209-5.754-14.387c-21.833-0.735-30.381,11.819-48.916,14.387
-       c-6.676-6.637,5.328-9.278,2.878-20.142c-14.78-4.791-23.536,24.911-43.161,14.387c2.484-8.068,14.983-6.119,20.142-11.509
-       c-4.107-7.834-13.948-3.709-28.773-5.756c5.839-11.424,18.647-15.887,28.773-23.018c-16.19-14.891-50.252,8.151-86.32,0
-       c-5.632-5.376-0.888-10.538,0-17.264c-26.711,2.744-56.57-2.806-92.075,0c2.416-3.342,3.799-7.716,2.877-14.388
-       c21.001-2.978,57.323,9.365,57.547-14.387c13.15,2.023,39.985,15.118,48.916,2.878c-41.733-18.691-93.205-27.639-132.358-48.915
-       c46.858-1.271,84.578,2.139,123.726-2.877c-14.836-7.225-29.161-14.957-51.792-14.387c-1.995-9.515-8.025-14.992-14.387-20.142
-       c14.393,0.544,26.632,3.115,37.406-11.511c-28.684-5.917-66.629-11.896-103.584-17.264c-0.489-8.162,9.733-5.614,5.754-17.264
-       c44.335,1.66,97.286,27.155,149.623,20.142c-19.613-10.115-54.625-4.845-74.811-14.387c8.817-3.917,31.875,2.574,48.915,0
-       c-28.055-9.265-51.18-14.974-74.811-23.02c-1.147-10.739,2.299-16.882,11.509-17.264c-27.891-14.312-72.805-11.593-92.075-34.528
-       c67.275,12.083,131.448,13.792,198.537,25.897c-37.895-23.488-109.193-13.576-135.235-48.916
-       c17.298,3.808,38.108,4.095,51.792,11.509c5.26-4.333,6.772-12.414,11.51-17.263c-8.29-12.375-29.769-25.14-28.774-37.406
-       c-10.126,8.26-21.226,0.57-11.509-8.633c-6.558-0.802-10.812,0.695-11.509,5.755c-11.38-14.192-41.548-24.578-69.057-37.406
-       c13.712-22.602,48.516,23.597,60.424-8.632c37.523,18.628,73.715,39.315,117.971,57.547c7.57,0.851,2.265-11.164,11.509-8.631
-       c-30.864-42.024-97.425-48.358-123.726-94.953c55.422,11.463,96.745,35.034,138.113,48.915
-       c-18.522-26.558-67.382-47.704-100.707-69.056c16.719-7.501,46.628,10.534,66.179,25.896c17.062,0.757,22.496-4.753,28.773,5.755
-       c3.467-3.249,5.215-8.211,14.387-5.755c-2.417-17.223-41.047-27.381-34.528-34.528c-2.821-5.753-23.592,3.166-17.264-5.753
-       c17.021-8.622,52.713,19.045,71.934,34.528c8.856,2.143,5.53-7.898,14.386-5.755c-17.477-41.028-62.902-54.108-94.952-80.565
-       c16.101-2.625,34.859,16.896,48.915,25.896c-13.454-30.673-60.846-52.319-83.443-83.443c14.331-9.428,31.427,3.026,34.529,14.387
-       c41.625-17.209,41.851,53.044,83.443,54.67c0.135-9.789-20.698-23.374-23.019-40.283c55.417,21.313,74.771,78.69,120.848,109.339
-       c-9.694-14.366-16-28.587-25.896-40.283c-2.906-3.435-12.078-6.455-14.387-11.509c-5.181-11.351,2.501-24.23,0-37.405
-       c-8.834-46.596-59.648-77.024-71.934-126.604c60.424,23.635,64.139,87.271,120.849,112.217c3.502,9.927,9.508,17.348,17.264,23.019
-       c-6.501-27.068-24.469-42.668-31.65-69.057c13.105,16.627,22.53,36.939,34.528,54.669c7.923-3.45,12.021-6.249,20.142-2.877
-       c14.933,25.514,12.746,62.473,31.65,77.688c1.545-27.312-19.079-81.817-48.914-103.585c4.917-13.311,16.061,0.944,23.018,2.877
-       c-2.382-36.073-48.858-95.548-25.896-138.113c33.685,45.919,52.119,107.102,80.565,158.254c18.647-22.846-6.754-63.077-5.753-77.689
-       c24.345-6.629,23.125,36.008,34.528,51.793c-11.323,15.779-18.107,69.924,0,80.566c6.732-22.835,27.025-70.625,2.877-89.198
-       c11.532-27.307-11.375-85.412,5.754-115.095c2.333,0.547,2.873,2.886,5.755,2.878c11.375,8.951,6.991,52.885,14.387,74.811
-       c15.883-26.322,11.335-73.067,43.161-83.443c40.395,56.191,5.844,157.535,17.264,230.188c16.882-26.091,6.238-92.451,8.633-123.726
-       c12.835,6.351,2.354,36.013,5.753,51.792c9.999-29.156,17.749-76.621,8.633-100.707c31.206-12.896,6.732-68.573,40.283-74.811
-       c20.208,50.773-20.771,115.566,0,158.254c28.183-15.123,24.883-76.587,63.301-71.935c17.348-27.735,18.337-71.821,40.283-94.952
-       c11.599,6.23,6.939,20.636,5.755,28.774c-5.469,37.506-37.496,79.328-28.774,129.48c16.079,3.051,12.233-12.965,17.264-20.141
-       c22.969-32.747,53.524-54.615,63.303-97.83c9.093-4.339,13.37-13.492,23.02-17.264c2.972,30.808-14.271,66.28-31.652,86.321
-       c20.782,9.806,6.621,42.072,8.633,66.179c27.801-28.788,45.97-67.206,69.056-100.707c0.631-10.526,3.957-11.038,0-20.142
-       c9.694-4.023,12.285-19.592,25.896-11.51c-3.187,35.176-19.389,57.343-31.651,83.443c19.602,34.369-25.643,69.83-37.405,100.707
-       c36.49-22.017,56.587-60.427,83.443-92.075c15.522-3.715,22.333-31.311,37.406-25.896c10.121,10.746-15.416,33.993-28.774,40.283
-       c-15.814,24.466-37.271,43.289-54.67,66.18c20.4,0.253,19.901-20.384,34.528-25.897c-12.431,22.11-46.615,47.365-60.424,77.689
-       c19.49-10.264,44.7-39.687,60.424-63.302c5.48-5.392,7.232-0.313,14.388,0c31.863-23.788,69.443-45.422,60.423-94.952
-       c14.787-1.359,17.266,9.59,17.266,23.019c15.977-2.248,21.776-14.675,34.528-20.142c3.883,23.099-35.67,27.604-40.283,51.792
-       c7.024,7.731,17.86-5.038,23.019,5.755c-7.003,16.976-35.265,12.69-37.405,34.528c24.951,8.02,57.99-55.858,74.812-20.141
-       c-44.948,23.148-94.257,41.938-112.217,92.075c20.916,4.567,33.337-24.18,57.547-25.896c-15.781,11.964-9.128,30.528-25.896,43.16
-       c26.053-8.69,38.445-45.669,66.179-43.16c-21.068,16.015-36.569,16.525-51.792,48.915c22.496-2.73,53.81-20.786,80.566-28.773
-       c8.664,33.895-29.656,44.938-48.916,60.423c15.141,15.86,42.425,2.503,48.916-14.386c30.661,0.964,54.5-11.661,83.442-20.142
-       c-10.476,28.857-79.555,24.02-86.32,66.18c-17.449,3.649-25.379,16.821-43.161,20.142c22.188,0.098,49.978-19.061,77.689-23.019
-       c-21.384,16.979-53.405,23.318-74.812,40.283c4.153,13.752,14.089,3.931,23.02,0c18.343,0.12,34.905-1.545,43.159-11.51
-       c16.557,5.654,32.235-1.677,43.16-5.754c20.85,6.545,35.652,3.21,60.425,2.876c-9.054,14.494-47.628,12.643-51.792,40.283
-       c-15.404-1.017-20.782,7.991-31.651,11.509c-11.448-10.902-70.523-0.736-77.688,11.51c20.973,8.533,70.854-24.019,83.442,2.878
-       c-2.158,15.103-23.418,11.11-34.528,17.264c-0.917,7.632,16.124-2.691,11.509,8.632c-37.73-11.667-80.526,5.513-117.971,11.51
-       c54.85,5.668,118.797-17.455,166.887-11.51c-0.691,5.061-4.951,6.559-11.51,5.755c-1.102,9.736,12.739,4.527,8.633,17.264
-       c21.59,0.281,47.278-13.782,60.423,2.878c0.013,17.277-34.746-0.219-28.772,23.02c-36.653,4.706-80.122-7.428-103.584,14.386
-       c23.209,21.063,84.387-7.378,112.217,8.633c-10.348,14.589-38.198,11.672-60.425,14.387c-12.038,20.624-38.479,13.604-63.303,17.264
-       c16.473,25.356,71.062,17.585,94.953,20.142c3.191,5.446,3.67,13.594,5.755,20.141c-27.801,2.769-47.735,0.492-69.057,5.755
-       c37.866,18.388,83.977,14.851,135.235,28.774C1214.787,675.751,1214.787,688.616,1218.119,680.395z M550.575,202.755
-       c-2.799-24.018,5.136-64.358-2.877-74.811C546.247,154.524,529.809,185.218,550.575,202.755z M320.386,191.246
-       c-1,14.109,7.149,22.259,17.264,17.264C336.083,198.98,328.187,185.549,320.386,191.246z M662.79,266.057
-       c12.775-7.608,29.892-34.197,17.266-48.915C675.722,234.869,668.423,249.626,662.79,266.057z M349.16,243.038
-       c-8.98-2.527,0.106-23.126-11.51-23.019C336.487,230.921,344.479,247.532,349.16,243.038z M795.148,251.67
-       c3.984-9.588,28.605-22.207,14.388-31.651C805.719,229.717,784.224,236.792,795.148,251.67z M947.648,225.773
-       c-30.661,17.531-60.307,50.434-83.442,74.811c-7.183,7.567-21.355,17.894-17.266,25.897c33.73-34.37,81.348-54.849,106.463-97.831
-       C952.769,226.41,950.992,225.304,947.648,225.773z M524.678,300.584c-0.634-10.877,2.928-25.946-8.631-25.896
-       C510.319,282.514,512.819,301.348,524.678,300.584z M380.811,306.34c-8.363-6.98-10.779-19.912-20.142-25.896
-       C363.551,291.078,372.235,310.964,380.811,306.34z M766.376,355.254c11.79-17.008,36.512-36.346,37.405-54.67
-       C788.394,313.993,771.743,341.409,766.376,355.254z M228.311,335.113c-0.893-9.655-9.621-11.475-17.264-14.387
-       C208.473,333.853,220.511,332.365,228.311,335.113z M881.47,375.396c27.255-1.815,43.564-28.929,63.301-28.773
-       c-5.726-10.979,16.68-14.906,8.633-25.897C933.627,343.149,899.886,351.612,881.47,375.396z M950.526,340.868
-       c10.267-2.201,17.517-7.421,23.019-14.386C963.276,328.683,956.028,333.901,950.526,340.868z M832.554,366.763
-       c7.29-8.131,29.083-16.858,23.02-28.773C848.684,346.513,827.743,356.104,832.554,366.763z M513.169,378.273
-       c6.395-9.208,0.152-25.671-8.633-28.774C495.556,361.294,510.111,369.446,513.169,378.273z M259.962,407.046
-       c-0.961-12.467-15.933-10.918-23.019-17.264C239.416,400.739,247.216,406.369,259.962,407.046z M406.706,407.046
-       c-4.265-2.445-6.186-7.242-5.754-14.387C380.946,392.85,404.992,412.555,406.706,407.046z M1091.516,427.188
-       c18.889,1.254,40.199,5.823,51.792-5.755C1125.139,417.853,1105.779,418.069,1091.516,427.188z M861.328,467.471
-       c-4.401,8.843,18.793,8.843,14.387,0C874.979,460.736,863.076,465.812,861.328,467.471z M553.451,484.735
-       c9.801,0.208,10.718-8.465,14.388-14.387c-3.676-0.158-3.984-3.69-8.633-2.878C560.589,476.523,555.109,478.72,553.451,484.735z
-        M510.292,484.735c-7.593,9.672-6.013,28.515-25.897,25.896c-3.776-8.931,0.782-8.211,0-20.142
-       c-7.199,0.358-9.008,5.49-11.509-2.878c8.092-0.539,12.262-5.004,11.509-14.386c-10.543-0.954-15.988,3.191-23.019,5.753
-       c0.934,17.233,0.995,33.607-17.264,31.652c-5.686-6.537,3.063-16.076,0-28.774c-15.24-4.692-12.396,8.7-17.264,14.387
-       c-3.395-4.271-2.49-12.855-11.509-11.509c0,7.673,0,15.345,0,23.019c8.081,3.429,18.343,4.676,17.264,17.265
-       c-9.845-5.036-17.826,1.259-28.772,2.877c-0.647,5.439,3.242,6.348,2.876,11.509c-20.781,5.638-38.186-2.139-57.546-5.755
-       c8.283,14.739,31.661,14.379,37.406,31.652c-13.758,2.137-24.104-14.115-31.652-8.633c6.193,2.438,10.178,7.086,8.633,17.264
-       c-3.839,4.105-16.303,4.105-20.142,0c0.674,11.893,17.865,8.978,8.631,23.02c4.182,1.572,14.877-3.364,14.388,2.877
-       c-2.182,13.162-31.05-0.356-37.406,8.632c6.896,11.329,28.565,7.881,37.406,17.264c-1.878,14.427-12.533,20.074-25.897,23.02
-       c1.326,9.228,13.067,8.036,14.387,17.264c14.871,0.481,13.296-15.479,28.774-14.387c0.54,14.764-11.595,19.113,2.877,25.897
-       c-10.492,13.175-11.23,19.033-23.019,28.772c22.805,2.664,28.874-11.409,40.283-20.142c-2.058,7.814,13.571-2.061,11.509,5.755
-       c-4.952,7.767,3.175,22.35,5.755,31.65c7.086-14.639,24.575-52.949,43.159-28.772c2.435,10.239-8.327,17.241,2.878,20.14
-       c2.192-22.945,23.323-8.991,34.528-2.876c4.166-5.435,6.43-12.758,17.264-11.51c5.384,4.21,3.394,15.786,14.388,14.386
-       c3.618-14.832,3.551-27.433,14.387-28.772c4.794,3.839,0.961,16.303,5.753,20.142c16.855-0.546,24.453,8.159,31.652,17.264
-       c2.821-3.894,9.7-3.729,11.509-8.633c2.332-13.834-12.622-10.39-8.631-25.895c9.053-1.377,11.25,4.096,17.264,5.755
-       c4.94-10.819,8.486-8.065,14.387-14.388c23.979,18.039,41.816,11.808,71.934,17.264c-1.113-10.39-15.786-7.231-11.509-23.018
-       c-8.464-3.046-19.064-3.957-25.897-8.633c1.4-3.4,3.068-6.524,5.755-8.631c13.47,3.31,44.986,19.467,46.037-5.756
-       c-11.807,0.298-23.492,0.473-28.773-5.755c2.439-10.267,7.086-0.345,17.265-2.878c-9.649-13.283,1.758-10.46,2.877-25.895
-       c-6.166-9.521-26.475-2.203-31.652-5.756c9.24-13.779,34.226-11.812,43.161-25.896c-16.157-11.033-31.026-7.625-40.283,5.755
-       c-19.838-8.728,13.825-22.618,8.633-34.527c-14.173,4.068-22.277-8.931-40.283,0c-1.231-5.479-6.198-7.233-5.755-14.387
-       c1.288-8.303,12.381-6.804,14.386-14.387c-16.583-9.897-36.613,11.937-63.301,2.876c8.783-16.153,25.53-24.347,34.528-40.281
-       c-15.843,5.749-25.424,31.454-43.161,25.896c10.914-8.452,5.266-19.028,14.388-31.65c-17.888,18.046-29.702,12.679-51.794,17.264
-       c0.013-2.885-2.332-3.422-2.876-5.755c-1.933-10.729,11.671-20.717,5.754-25.896C532.046,477.715,525.325,485.381,510.292,484.735z
-        M631.14,510.632c14.477,0.96,28.762-13.325,23.019-23.02C649.742,498.537,634.281,498.427,631.14,510.632z M1028.215,527.896
-       c25.193,7.943,70.354,6.553,80.564-17.264C1089.977,513.287,1039.848,508.571,1028.215,527.896z M717.46,576.811
-       c9.773-4.619,26.661-2.113,31.651-11.509C737.562,568.133,719.702,564.66,717.46,576.811z M705.951,640.111
-       C728.937,657.017,720.579,623.069,705.951,640.111L705.951,640.111z M1056.987,651.621c1.242-6.434,14.185-1.166,20.142-2.877
-       C1071.016,638.734,1006.465,648.215,1056.987,651.621z M1005.195,697.658c3.08,7.52,25.159,3.198,37.406,0
-       C1032.368,694.931,1003.976,694.675,1005.195,697.658z M544.819,769.592c-5.058-0.693-6.558-4.95-5.755-11.509
-       c-19.191,0.495-6.963,14.534-20.142,20.142c15.348,0,30.695,0,46.038,0c0.989-12.499-2.175-20.844-11.51-23.02
-       C554.02,763.444,553.811,770.91,544.819,769.592z M593.734,781.103c10.633-1.839,28.667,3.726,34.528-2.878
-       c-10.676-3.709-10.682-18.09-25.895-17.264C605.396,773.579,592.638,770.41,593.734,781.103z M484.395,781.103
-       c9.594,0,19.187,0,28.774,0C511.691,769.374,485.497,769.412,484.395,781.103z"/>
-<rect x="477.335" y="335.988" fill="#E33D27" width="60.604" height="58.978"/>
-<rect x="346.712" y="365.477" fill="#E33D27" width="64.323" height="59.871"/>
-<rect x="841.76" y="436.07" fill="#E33D27" width="55.402" height="80.423"/>
-<rect x="490.15" y="254.548" fill="#E33D27" width="47.789" height="54.634"/>
-<rect x="221.61" y="365.477" fill="#E33D27" width="37.53" height="50.935"/>
-<g>
-       <path fill="#F37056" d="M960.874,342.508c-7.183,7.57-21.354,17.894-17.264,25.897c23.211-23.649,52.995-40.722,77.5-63.077
-               c-13.034,5.459-25.59,10.327-36.366,12.113C976.251,326.146,968.231,334.759,960.874,342.508z"/>
-       <path fill="#F37056" d="M982.291,286.56c2.111-6.42,4.772-12.605,11.396-17.626c-4.429,0.314-8.461,1.536-12.223,3.29
-               c-15.054,16.66-34.13,35.084-43.608,55.898C951.605,320.884,968.188,304.103,982.291,286.56z"/>
-       <path fill="#F37056" d="M1032.808,336.755c0.142,0.03,0.276,0.044,0.414,0.069c16.913-10.348,33.999-22.228,30.24-44.329
-               C1050.207,304.209,1039.396,318.372,1032.808,336.755z"/>
-       <path fill="#F37056" d="M1189.346,404.169c-9.241,0.124-17.092,0.667-24.393,0.958c-3.92,4.524-6.771,9.897-8.097,16.427
-               C1169.379,415.4,1184.175,412.447,1189.346,404.169z"/>
-       <path fill="#F37056" d="M1093.542,331.732c-5.376,1.275-10.857,2.256-16.521,2.836c-2.233,6.923-5.04,13.786-12.562,19.45
-               C1075.991,350.17,1084.845,340.787,1093.542,331.732z"/>
-       <path fill="#F37056" d="M929.224,408.688c7.288-8.133,29.083-16.855,23.02-28.774C945.354,388.439,924.413,398.027,929.224,408.688
-               z"/>
-       <path fill="#F37056" d="M503.376,448.97c-4.265-2.443-6.188-7.237-5.755-14.386C477.616,434.775,501.662,454.479,503.376,448.97z"
-               />
-       <path fill="#F37056" d="M759.46,307.98c12.773-7.604,29.892-34.197,17.264-48.915C772.392,276.796,765.091,291.553,759.46,307.98z"
-               />
-       <path fill="#F37056" d="M890.099,290.81c0.45,0.896,1.015,1.823,1.72,2.784c1.44-3.468,5.58-7.331,9.607-11.299
-               C897.672,285.156,893.89,287.984,890.099,290.81z"/>
-       <path fill="#F37056" d="M863.046,397.178c4.893-7.058,12.008-14.521,18.729-22.142c1.233-1.57,2.54-3.068,3.899-4.512
-               c7.834-9.309,14.325-18.791,14.776-28.016C885.063,355.918,868.411,383.337,863.046,397.178z"/>
-       <path fill="#F37056" d="M1048.356,202.755c-2.375-5.043-5.084-8.048-8.039-9.602c-6.688,7.37-15.63,14.047-21.896,16.997
-               c-2.716,4.204-5.642,8.197-8.64,12.116C1022.446,215.568,1035.576,209.336,1048.356,202.755z"/>
-       <path fill="#F37056" d="M900.451,236.047c4.218-4.366,8.189-8.975,12.015-13.735c-4.415-1.273-6.41-3.791-10.855,0.584
-               c-0.362,0.545-0.758,1.11-1.132,1.661C900.215,228.505,900.145,232.372,900.451,236.047z"/>
-       <path fill="#F37056" d="M609.837,420.197c6.396-9.205,0.152-25.672-8.631-28.773C592.226,403.22,606.78,411.374,609.837,420.197z"
-               />
-       <path fill="#F37056" d="M1194.9,524.134c-7.083,1.752-15.417,2.252-21.102,5.402c-0.141,1.167,0.173,1.88,0.733,2.349
-               C1182.579,530.562,1193.381,531.989,1194.9,524.134z"/>
-       <path fill="#F37056" d="M1139.644,437.292c2.543-5.611,6.859-9.652,11.949-12.835c-14.169,4.826-22.213,15.774-38.219,18.758
-               C1121.475,443.252,1130.327,440.713,1139.644,437.292z"/>
-       <path fill="#F37056" d="M1127.288,506.742c-1.045,0.868-1.879,1.754-2.405,2.652c2.51,1.021,5.441,1.441,8.66,1.458
-               C1131.681,509.263,1128.91,508.577,1127.288,506.742z"/>
-       <path fill="#F37056" d="M1047.196,382.792c5.236-1.121,9.68-3.037,13.516-5.561c0.651-2.398,1.516-4.628,2.575-6.71
-               C1056.552,373.24,1051.367,377.512,1047.196,382.792z"/>
-       <path fill="#F37056" d="M978.138,417.319c27.257-1.815,43.566-28.924,63.303-28.772c-5.726-10.976,16.68-14.905,8.631-25.897
-               C1030.297,385.073,996.555,393.537,978.138,417.319z"/>
-       <path fill="#F37056" d="M957.997,509.395c-4.4,8.846,18.792,8.846,14.388,0c-0.067-0.618-0.256-1.104-0.495-1.534
-               c-0.405-0.039-0.817-0.064-1.223-0.106c0.352-0.057,0.709-0.121,1.062-0.181C969.09,503.774,959.548,507.923,957.997,509.395z"/>
-       <path fill="#F37056" d="M1174.96,568.179c-11.15-6.416-27.655-5.69-44.926-3.878c-2.112,1.585-3.874,3.4-5.151,5.519
-               c12.32,3.887,29.403,5.526,44.851,3.417C1171.755,571.834,1173.537,570.185,1174.96,568.179z"/>
-       <path fill="#F37056" d="M1078.151,550.431c16.431-5.851,37.288-4.484,58.229-4.133c9.858-1.38,19.687-2.915,29.369-4.328
-               c-0.368-3.449,0.435-5.734,1.99-7.261c-33.084-3.223-68.665,9.885-100.404,14.969
-               C1070.905,550.046,1074.514,550.288,1078.151,550.431z"/>
-       <path fill="#F37056" d="M519.384,275.245c-5.662-14.417-13.493-28.914-22.875-40.615c-0.964,3.086-1.932,6.056-2.847,8.863
-               c1.231,0.242,2.518,0.587,3.958,1.187c14.932,25.513,12.746,62.474,31.652,77.687c0.477-8.462-1.174-19.539-4.568-31.442
-               c-0.057,3.267-0.203,6.626-0.026,9.66c-11.858,0.762-14.358-18.07-8.631-25.896C517.35,274.683,518.437,274.894,519.384,275.245z"
-               />
-       <path fill="#F37056" d="M267.434,218.783c1.495-0.619,2.919-1.093,4.31-1.493c-11.518-10.683-24.522-19.877-40.555-26.044
-               c0.562,4.085,2.214,7.972,4.381,11.664C249.279,196.5,264.522,208.122,267.434,218.783z"/>
-       <path fill="#F37056" d="M208.169,401.292c-6.071-1.665-5.877,2.939-7.165,6.057c28.852,14.916,58.187,30.438,92.325,44.498
-               c7.57,0.854,2.265-11.161,11.509-8.632c-11.596-15.786-28.231-26.537-45.874-36.275c-9.229-0.704-15.755-4.112-19.403-10.394
-               c-23.185-12.392-45.614-25.54-58.449-48.283c55.423,11.464,96.746,35.034,138.113,48.914
-               c-16.806-24.092-58.581-43.732-91.072-63.115c0.056,0.345,0.123,0.682,0.157,1.05c-7.8-2.748-19.838-1.262-17.264-14.387
-               c4.555,1.734,9.483,3.094,12.92,5.942c17.211-2.379,43.146,13.536,60.73,27.35c17.062,0.757,22.497-4.75,28.774,5.754
-               c3.467-3.249,5.214-8.21,14.386-5.754c-2.416-17.22-41.047-27.381-34.528-34.529c-2.821-5.754-23.592,3.17-17.264-5.754
-               c17.022-8.621,52.714,19.045,71.935,34.528c8.856,2.146,5.53-7.896,14.386-5.755c-17.479-41.024-62.903-54.107-94.953-80.565
-               c16.1-2.625,34.86,16.897,48.915,25.896c-10.372-23.648-40.91-41.933-64.713-63.33c1.58,2.518,2.603,4.867,2.571,7.02
-               c-41.592-1.626-41.817-71.881-83.443-54.67c-3.102-11.36-20.198-23.813-34.529-14.387c22.598,31.125,69.99,52.771,83.443,83.443
-               c-14.055-9-32.814-28.521-48.915-25.896c32.05,26.456,77.475,39.538,94.952,80.565c-8.856-2.143-5.53,7.898-14.386,5.755
-               c-19.22-15.482-54.912-43.15-71.934-34.528c-6.329,8.921,14.442,0,17.264,5.753c-6.519,7.146,32.111,17.307,34.528,34.528
-               c-9.172-2.458-10.919,2.506-14.387,5.755c-6.278-10.506-11.712-5-28.773-5.755c-19.551-15.362-49.46-33.396-66.179-25.896
-               c33.325,21.353,82.185,42.5,100.707,69.056c-41.368-13.88-82.69-37.453-138.113-48.915
-               C110.744,352.937,177.305,359.27,208.169,401.292z"/>
-       <path fill="#F37056" d="M309.93,240.203c3.794,5.699,7.626,11.627,11.979,16.89c1.75,1.079,3.316,2.125,4.232,3.209
-               c1.371,1.622,2.664,3.302,3.917,5.013c5.709,4.648,12.412,7.81,20.818,8.138c0.135-9.784-20.697-23.373-23.019-40.283
-               c5.356,2.061,10.369,4.466,15.109,7.143c-3.299-4.795-6.03-13.607-5.317-20.292c11.616-0.107,2.53,20.492,11.51,23.019
-               c-0.256,0.247-0.529,0.405-0.802,0.529c40.576,25.857,60.456,72.41,100.348,98.942c-9.693-14.363-15.999-28.583-25.895-40.283
-               c-2.907-3.433-12.078-6.451-14.388-11.509c-5.18-11.346,2.502-24.227,0-37.406c-3.431-18.093-13.198-33.747-24.575-49.033
-               c-0.958,0.433-1.958,0.885-3.037,1.354c-5.465-8.079-10.4-16.69-15.39-25.247c-6.822-8.953-13.355-18.146-18.698-27.976
-               c7.436,25.506,24.83,41.049,31.21,67.609c-7.756-5.673-13.762-13.092-17.264-23.019c-56.71-24.946-60.425-88.582-120.849-112.217
-               c12.285,49.581,63.099,80.007,71.934,126.604C313.643,221.337,309.731,231.121,309.93,240.203z M320.386,191.246
-               c7.801-5.695,15.697,7.736,17.264,17.264C327.535,213.503,319.386,205.354,320.386,191.246z"/>
-       <path fill="#F37056" d="M390.342,171.301c18.823,25.289,33.874,53.051,66.997,67.624c3.5,9.93,9.508,17.348,17.264,23.019
-               c-6.502-27.065-24.469-42.667-31.652-69.057c13.106,16.628,22.53,36.938,34.529,54.669c1.955-0.851,3.672-1.661,5.28-2.349
-               c-7.824-18.554-2.404-55.13,6.276-69.523c-5.993-14.727-12.288-30.299-15.581-45.543c-3.897-6.521-9.289-10.278-17.834-7.952
-               c-1.001,14.612,24.4,54.842,5.753,77.689c-28.446-51.154-46.88-112.335-80.565-158.254
-               c-22.962,42.564,23.513,102.04,25.896,138.113C402.079,178.449,395.608,171.753,390.342,171.301z"/>
-       <path fill="#F37056" d="M307.717,362.65c-2.574,13.127,9.463,11.639,17.264,14.386C324.087,367.382,315.359,365.561,307.717,362.65
-               z"/>
-       <path fill="#F37056" d="M422.181,231.992c2.706,6.736,4.949,13.468,6.649,19.912c1.728-0.054,3.573-0.523,5.49-1.47
-               C433.1,243.018,428.039,233.279,422.181,231.992z"/>
-       <path fill="#F37056" d="M445.829,284.961c-8.981-2.523,0.107-23.125-11.509-23.018
-               C433.156,272.845,441.148,289.458,445.829,284.961z"/>
-       <path fill="#F37056" d="M258.801,736.706c-4.395,0.452-8.885,0.662-13.462,0.742c1.256,0.752,2.302,1.819,3.113,3.371
-               c-5.159,5.39-17.657,3.44-20.142,11.509c12.687,6.804,20.833-3.199,28.999-9.835C257.897,740.678,258.528,738.765,258.801,736.706z
-               "/>
-       <path fill="#F37056" d="M266.762,755.276c0.264,0.874,0.81,1.79,1.832,2.807c3.484-0.483,6.612-1.317,9.545-2.352
-               C274.396,755.826,270.598,755.697,266.762,755.276z"/>
-       <path fill="#F37056" d="M87.321,398.415c0.697-5.061,4.951-6.556,11.509-5.755c-9.717,9.203,1.383,16.893,11.509,8.633
-               c-0.995,12.268,20.484,25.031,28.774,37.406c-4.737,4.849-6.25,12.93-11.51,17.263c-13.684-7.414-34.494-7.701-51.792-11.509
-               c25.82,35.04,96.11,25.613,134.24,48.339c5.202,1.239,10.045,2.832,14.222,5.095c5.26-4.334,6.771-12.415,11.509-17.264
-               c-8.289-12.375-29.768-25.138-28.773-37.406c-10.127,8.261-21.226,0.574-11.509-8.632c-6.559-0.797-10.813,0.698-11.51,5.755
-               c-11.38-14.19-41.547-24.576-69.056-37.406c12.836-21.153,44.149,17.963,57.867-3.383c-33.871-15.463-63.552-32.002-94.112-47.173
-               c-11.909,32.229-46.712-13.968-60.424,8.632C45.773,373.837,75.941,384.222,87.321,398.415z"/>
-       <path fill="#F37056" d="M558.045,241.802c18.647-22.845-6.755-63.077-5.755-77.688c16.821-4.578,21.438,14.355,26.444,31.704
-               c3.859-55.909,10.377-113.72-16.651-151.317c-31.825,10.377-27.278,57.123-43.161,83.443c-7.396-21.926-3.011-65.862-14.387-74.811
-               c-2.882,0.008-3.421-2.33-5.755-2.878c-8.584,14.876-7.112,36.892-4.959,58.59C517.875,150.519,534.557,199.568,558.045,241.802z
-                M547.697,127.944c8.013,10.453,0.078,50.795,2.877,74.811C529.809,185.218,546.247,154.523,547.697,127.944z"/>
-       <path fill="#F37056" d="M345.122,753.97c-6.598-6.066-16.163-5.833-27.619-3.981c1.346,3.273,4.917,4.318,5.761,8.095
-               c-5.923,3.67-14.595,4.592-14.387,14.387c5.249-0.438,10.112-2.163,14.741-4.403C329.979,762.56,338.159,758.873,345.122,753.97z"
-               />
-       <path fill="#F37056" d="M248.452,712.046c-0.542,0.382-1.118,0.733-1.677,1.101c11.644,3.148,23.822,5.156,29.29-2.338
-               c-32.949-14.757-71.948-23.459-106.184-36.933c-11.934,1.41-29.524-6.348-39.401-7.868c-0.224,23.752-36.545,11.409-57.547,14.387
-               c0.922,6.672-0.461,11.046-2.877,14.388c35.505-2.806,65.364,2.744,92.075,0c-0.888,6.726-5.632,11.888,0,17.264
-               C198.2,720.197,232.262,697.155,248.452,712.046z"/>
-       <path fill="#F37056" d="M93.076,519.263c23.631,8.046,46.756,13.755,74.811,23.02c-17.04,2.574-40.098-3.917-48.915,0
-               c18.857,8.913,50.641,4.909,70.734,12.585c0.714-6.782,4.347-10.647,11.549-10.944c-27.892-14.313-72.805-11.594-92.075-34.528
-               c67.275,12.082,131.448,13.792,198.538,25.896c-37.479-23.228-107.606-13.814-134.334-47.8
-               c-53.725-7.24-106.279-10.213-160.873-20.021c19.271,22.936,64.184,20.216,92.075,34.528
-               C95.375,502.381,91.929,508.523,93.076,519.263z"/>
-       <path fill="#F37056" d="M47.038,619.971c33.711,18.32,76.542,27.512,114.439,41.641c38.881-0.242,71.881,1.775,105.957-2.594
-               c-14.836-7.222-29.162-14.954-51.792-14.387c-1.996-9.515-8.026-14.989-14.387-20.142c14.393,0.546,26.632,3.118,37.405-11.511
-               c-28.683-5.918-66.628-11.896-103.584-17.264c-0.488-8.159,9.733-5.614,5.755-17.264c44.334,1.663,97.285,27.155,149.622,20.141
-               c-19.612-10.115-54.624-4.844-74.81-14.386c8.817-3.917,31.875,2.574,48.914,0c-28.054-9.262-51.179-14.971-74.811-23.02
-               c-0.152-1.431-0.21-2.767-0.196-4.032c-50.952,5.159-102.247-19.012-145.388-20.627c3.979,11.649-6.243,9.102-5.754,17.264
-               c36.956,5.367,74.9,11.347,103.584,17.264c-10.773,14.626-23.013,12.055-37.406,11.511c6.362,5.149,12.392,10.627,14.387,20.142
-               c22.631-0.57,36.957,7.162,51.792,14.387C131.616,622.109,93.896,618.7,47.038,619.971z"/>
-       <path fill="#F37056" d="M1083.058,351.613c23.241-13.143,56.156-17.439,63.128-36.642c-15.511,4.544-29.56,10.265-43.976,14.46
-               C1095.478,334.435,1089.207,340.808,1083.058,351.613z"/>
-       <path fill="#F37056" d="M503.376,221.66c-0.172-2.607-0.598-5.354-1.188-8.191c-0.486,2.327-1.028,4.651-1.613,6.958
-               C501.561,220.979,502.502,221.418,503.376,221.66z"/>
-       <path fill="#F37056" d="M333.613,431.706c2.473,10.96,10.272,16.589,23.018,17.264C355.67,436.506,340.699,438.051,333.613,431.706
-               z"/>
-       <path fill="#F37056" d="M457.339,322.367c2.882,10.638,11.565,30.522,20.142,25.897
-               C469.118,341.283,466.702,328.352,457.339,322.367z"/>
-       <path fill="#F37056" d="M612.715,316.613c-5.726,7.828-3.226,26.66,8.633,25.895C620.713,331.634,624.276,316.567,612.715,316.613z
-               "/>
-       <path fill="#F37056" d="M675.856,231.276c1.558-4.553,2.999-9.222,4.199-14.134c8.91,10.386,3.006,26.675-5.728,38.041
-               c-1.132,21.552-1.289,42.471,1.689,61.431c16.882-26.089,6.238-92.453,8.631-123.727c12.837,6.35,2.355,36.018,5.755,51.793
-               c9.998-29.156,17.747-76.622,8.632-100.708c31.207-12.892,6.733-68.573,40.283-74.812c1.399,3.519,2.481,7.109,3.336,10.751
-               c4.207-11.24,7.807-22.055,9.335-32.533c1.185-8.138,5.844-22.544-5.755-28.774c-21.946,23.131-22.936,67.216-40.283,94.952
-               c-14.696-1.781-23.28,6.128-29.863,17.402C681.301,161.274,678.35,196.469,675.856,231.276z"/>
-       <path fill="#F37056" d="M579.348,274.688c-1.434-9.114-2.142-18.679-2.366-28.551c-3.036,20.503-1.369,43.75,9.838,50.334
-               c6.732-22.834,27.025-70.625,2.876-89.199c5.542-13.125,3.13-33.365,1.032-54.141c-0.779-0.859-1.652-1.627-2.747-2.169
-               C585.586,182.237,596.23,248.598,579.348,274.688z"/>
-       <path fill="#F37056" d="M642.368,184.844c-4.242,22.451-12.071,45.527,4.875,59.835c-2.124-18.231,1.93-45.861,0.506-62.69
-               c-1.584,1.338-3.273,2.521-5.099,3.502C642.546,185.28,642.469,185.058,642.368,184.844z"/>
-       <path fill="#F37056" d="M735.584,171.567c-3.144,20.468-4.104,39.732,3.734,55.847c28.184-15.123,24.885-76.587,63.302-71.934
-               c1.431-2.284,2.714-4.715,3.945-7.202c-0.443-9.034-3.183-16.45-11.417-20.335c17.382-20.041,34.624-55.513,31.652-86.321
-               c-9.649,3.774-13.927,12.925-23.02,17.264c-9.778,43.213-40.334,65.083-63.303,97.83
-               C737.782,160.567,737.619,166.937,735.584,171.567z"/>
-       <path fill="#F37056" d="M615.593,169.868c13.074-21.664,12.321-57.153,29.395-74.822c3.894-23.297,6.041-46.757-2.338-67.809
-               c-32.509,6.044-10.543,58.502-37.533,73.487C611.578,115.878,609.23,151.007,615.593,169.868z"/>
-       <path fill="#F37056" d="M989.466,132.274c-6.629,20.231-17.129,36.588-25.714,54.857c19.602,34.371-25.643,69.833-37.405,100.708
-               c8.093-4.883,15.348-10.604,22.084-16.849c5.897-8.486,12.911-15.855,20.705-22.443c7.69-9.467,14.92-19.396,22.237-29.24
-               c-6.167,3.535-12.203,5.396-17.828,3.588c2.141-21.838,30.402-17.553,37.405-34.528c-5.158-10.793-15.994,1.975-23.019-5.755
-               c4.613-24.188,44.166-28.692,40.283-51.792c-12.752,5.465-18.552,17.894-34.528,20.142
-               C993.687,143.325,992.877,136.5,989.466,132.274z"/>
-       <path fill="#F37056" d="M913.12,153.84c-5.465,6.44-10.646,13.165-15.746,19.968c4.431,4.585,5.854,11.127,5.926,18.638
-               c6.564-7.66,12.868-15.579,18.452-24.219c13.358-6.291,38.896-29.535,28.774-40.283C935.453,122.529,928.643,150.125,913.12,153.84
-               z"/>
-       <path fill="#F37056" d="M822.007,172.346c-3.472,14.691-4.96,30.12-2.122,46.437c16.079,3.051,12.233-12.965,17.264-20.142
-               c10.699-15.258,23.033-28.164,34.16-41.958c-0.713-3.833-2.051-7.663-4.227-11.476c12.263-26.102,28.465-48.266,31.651-83.443
-               c-13.611-8.084-16.202,7.488-25.896,11.51c3.957,9.104,0.631,9.615,0,20.142C855.191,119.025,840.405,147.489,822.007,172.346z"/>
-</g>
-</svg>
index e548c5e07562c3394868a038cbbd0a49255459f3..c8cfd456d1353bfcfb3112fce2676784f4eb6ef8 100644 (file)
@@ -8,7 +8,7 @@ fn main() {
 
     let mut buffer = String::new();
     if let Err(e) = io::stdin().read_to_string(&mut buffer) {
-        panic!(e);
+        panic!("{}", e);
     }
 
     for line in buffer.lines() {
index 33d90ec240352eb87c03afdc76d598f2811f7086..9688d10bf5594a3e6b5e0f9228302c52c70d1db0 100644 (file)
@@ -14,7 +14,7 @@ fn read_md() -> String {
     let mut buffer = String::new();
     match io::stdin().read_to_string(&mut buffer) {
         Ok(_) => buffer,
-        Err(error) => panic!(error),
+        Err(error) => panic!("{}", error),
     }
 }
 
@@ -27,14 +27,18 @@ fn parse_references(buffer: String) -> (String, HashMap<String, String>) {
     // FIXME: currently doesn't handle "title" in following line.
     let re = Regex::new(r###"(?m)\n?^ {0,3}\[([^]]+)\]:[[:blank:]]*(.*)$"###)
         .unwrap();
-    let output = re.replace_all(&buffer, |caps: &Captures<'_>| {
-        let key = caps.get(1).unwrap().as_str().to_uppercase();
-        let val = caps.get(2).unwrap().as_str().to_string();
-        if ref_map.insert(key, val).is_some() {
-            panic!("Did not expect markdown page to have duplicate reference");
-        }
-        "".to_string()
-    }).to_string();
+    let output = re
+        .replace_all(&buffer, |caps: &Captures<'_>| {
+            let key = caps.get(1).unwrap().as_str().to_uppercase();
+            let val = caps.get(2).unwrap().as_str().to_string();
+            if ref_map.insert(key, val).is_some() {
+                panic!(
+                    "Did not expect markdown page to have duplicate reference"
+                );
+            }
+            "".to_string()
+        })
+        .to_string();
     (output, ref_map)
 }
 
@@ -196,8 +200,7 @@ more text"
     #[test]
     fn parses_name_with_utf8() {
         let source = r###"[user’s forum](the user’s forum)"###.to_string();
-        let target =
-            r###"user’s forum at *the user’s forum*"###.to_string();
+        let target = r###"user’s forum at *the user’s forum*"###.to_string();
         assert_eq!(parse(source), target);
     }
 
@@ -251,7 +254,6 @@ more text"
 [package]
 name = "hello_cargo"
 version = "0.1.0"
-authors = ["Your Name <you@example.com>"]
 
 [dependencies]
 ```
@@ -284,7 +286,6 @@ is still here` link at *ref*"
 [package]
 name = "hello_cargo"
 version = "0.1.0"
-authors = ["Your Name <you@example.com>"]
 
 [dependencies]
 ```
@@ -297,7 +298,6 @@ more text
 [package]
 name = "hello_cargo"
 version = "0.1.0"
-authors = ["Your Name <you@example.com>"]
 
 [dependencies]
 ```
index fa3b705210752f4f7e574defd33c46741812c45e..45ce031aa3a73ec36fafae4584d34294fc87b75d 100644 (file)
@@ -9,7 +9,7 @@ fn read_md() -> String {
     let mut buffer = String::new();
     match io::stdin().read_to_string(&mut buffer) {
         Ok(_) => buffer,
-        Err(error) => panic!(error),
+        Err(error) => panic!("{}", error),
     }
 }
 
index a096389b83ad8aca0cbe57928f0e8f2c8a36f844..edccc53c1a5b5ebfee9a835a54bbd66666cfe39d 100644 (file)
@@ -8,7 +8,7 @@ use std::io::{Read, Write};
 fn main() {
     let mut buffer = String::new();
     if let Err(e) = io::stdin().read_to_string(&mut buffer) {
-        panic!(e);
+        panic!("{}", e);
     }
 
     let mut refs = HashSet::new();
index 8877e038f788c06928f67e1ec8e7bbee1aa3022c..06f6a6ba985023f3335d150cfeea9dc2818ef359 100644 (file)
@@ -12,7 +12,7 @@ fn read_md() -> String {
     let mut buffer = String::new();
     match io::stdin().read_to_string(&mut buffer) {
         Ok(_) => buffer,
-        Err(error) => panic!(error),
+        Err(error) => panic!("{}", error),
     }
 }
 
@@ -39,9 +39,11 @@ fn remove_markup(input: String) -> String {
             } else {
                 let result =
                     regexen.iter().fold(line.to_string(), |result, regex| {
-                        regex.replace_all(&result, |caps: &Captures<'_>| {
-                            caps.get(1).unwrap().as_str().to_string()
-                        }).to_string()
+                        regex
+                            .replace_all(&result, |caps: &Captures<'_>| {
+                                caps.get(1).unwrap().as_str().to_string()
+                            })
+                            .to_string()
                     });
                 Some(result)
             }
index 2eae013202eda65caed4d57cf830f55a3b0fde20..6804ac2d68f5e886e0e27f52aaefcc085b684f7b 100644 (file)
@@ -7,6 +7,7 @@
 - [What are editions?](editions/index.md)
   - [Creating a new project](editions/creating-a-new-project.md)
   - [Transitioning an existing project to a new edition](editions/transitioning-an-existing-project-to-a-new-edition.md)
+  - [Advanced migrations](editions/advanced-migrations.md)
 
 ## Rust 2015
 
diff --git a/src/doc/edition-guide/src/editions/advanced-migrations.md b/src/doc/edition-guide/src/editions/advanced-migrations.md
new file mode 100644 (file)
index 0000000..b804ae6
--- /dev/null
@@ -0,0 +1,210 @@
+# Advanced migration strategies
+
+## How migrations work
+
+[`cargo fix --edition`][`cargo fix`] works by running the equivalent of [`cargo check`] on your project with special [lints] enabled which will detect code that may not compile in the next edition.
+These lints include instructions on how to modify the code to make it compatible on both the current and the next edition.
+`cargo fix` applies these changes to the source code, and then runs `cargo check` again to verify that the fixes work.
+If the fixes fail, then it will back out the changes and display a warning.
+
+Changing the code to be simultaneously compatible with both the current and next edition makes it easier to incrementally migrate the code.
+If the automated migration does not completely succeed, or requires manual help, you can iterate while staying on the original edition before changing `Cargo.toml` to use the next edition.
+
+The lints that `cargo fix --edition` apply are part of a [lint group].
+For example, when migrating from 2018 to 2021, Cargo uses the `rust-2021-compatibility` group of lints to fix the code.
+Check the [Partial migration](#partial-migration-with-broken-code) section below for tips on using individual lints to help with migration.
+
+`cargo fix` may run `cargo check` multiple times.
+For example, after applying one set of fixes, this may trigger new warnings which require further fixes.
+Cargo repeats this until no new warnings are generated.
+
+## Migrating multiple configurations
+
+`cargo fix` can only work with a single configuration at a time.
+If you use [Cargo features] or [conditional compilation], then you may need to run `cargo fix` multiple times with different flags.
+
+For example, if you have code that uses `#[cfg]` attributes to include different code for different platforms, you may need to run `cargo fix` with the `--target` option to fix for different targets.
+This may require moving your code between machines if you don't have cross-compiling available.
+
+Similarly, if you have conditions on Cargo features, like `#[cfg(feature = "my-optional-thing")]`, it is recommended to use the `--all-features` flag to allow `cargo fix` to migrate all the code behind those feature gates.
+If you want to migrate feature code individually, you can use the `--features` flag to migrate one at a time.
+
+## Migrating a large project or workspace
+
+You can migrate a large project incrementally to make the process easier if you run into problems.
+
+In a [Cargo workspace], each package defines its own edition, so the process naturally involves migrating one package at a time.
+
+Within a [Cargo package], you can either migrate the entire package at once, or migrate individual [Cargo targets] one at a time.
+For example, if you have multiple binaries, tests, and examples, you can use specific target selection flags with `cargo fix --edition` to migrate just that one target.
+By default, `cargo fix` uses `--all-targets`.
+
+For even more advanced cases, you can specify the edition for each individual target in `Cargo.toml` like this:
+
+```toml
+[[bin]]
+name = "my-binary"
+edition = "2018"
+```
+
+This usually should not be required, but is an option if you have a lot of targets and are having difficulty migrating them all together.
+
+## Partial migration with broken code
+
+Sometimes the fixes suggested by the compiler may fail to work.
+When this happens, Cargo will report a warning indicating what happened and what the error was.
+However, by default it will automatically back out the changes it made.
+It can be helpful to keep the code in the broken state and manually resolve the issue.
+Some of the fixes may have been correct, and the broken fix maybe be *mostly* correct, but just need minor tweaking.
+
+In this situation, use the `--broken-code` option with `cargo fix` to tell Cargo not to back out the changes.
+Then, you can go manually inspect the error and investigate what is needed to fix it.
+
+Another option to incrementally migrate a project is to apply individual fixes separately, one at a time.
+You can do this by adding the individual lints as warnings, and then either running `cargo fix` (without the `--edition` flag) or using your editor or IDE to apply its suggestions if it supports "Quick Fixes".
+
+For example, the 2018 edition uses the [`keyword-idents`] lint to fix any conflicting keywords.
+You can add `#![warn(keyword_idents)]` to the top of each crate (like at the top of `src/lib.rs` or `src/main.rs`).
+Then, running `cargo fix` will apply just the suggestions for that lint.
+
+You can see the list of lints enabled for each edition in the [lint group] page, or run the `rustc -Whelp` command.
+
+## Migrating macros
+
+Some macros may require manual work to fix them for the next edition.
+For example, `cargo fix --edition` may not be able to automatically fix a macro that generates syntax that does not work in the next edition.
+
+This may be a problem for both [proc macros] and `macro_rules`-style macros.
+`macro_rules` macros can sometimes be automatically updated if the macro is used within the same crate, but there are several situations where it cannot.
+Proc macros in general cannot be automatically fixed at all.
+
+For example, if we migrate a crate containing this (contrived) macro `foo` from 2015 to 2018, `foo` would not be automatically fixed.
+
+```rust
+#[macro_export]
+macro_rules! foo {
+    () => {
+        let dyn = 1;
+        println!("it is {}", dyn);
+    };
+}
+```
+
+When this macro is defined in a 2015 crate, it can be used from a crate of any other edition due to macro hygiene (discussed below).
+In 2015, `dyn` is a normal identifier and can be used without restriction.
+
+However, in 2018, `dyn` is no longer a valid identifier.
+When using `cargo fix --edition` to migrate to 2018, Cargo won't display any warnings or errors at all.
+However, `foo` won't work when called from any crate.
+
+If you have macros, you are encouraged to make sure you have tests that fully cover the macro's syntax.
+You may also want to test the macros by importing and using them in crates from multiple editions, just to ensure it works correctly everywhere.
+If you run into issues, you'll need to read through the chapters of this guide to understand how the code can be changed to work across all editions.
+
+### Macro hygiene
+
+Macros use a system called "edition hygiene" where the tokens within a macro are marked with which edition they come from.
+This allows external macros to be called from crates of varying editions without needing to worry about which edition it is called from.
+
+Let's take a closer look at the example above that defines a `macro_rules` macro using `dyn` as an identifier.
+If that macro was defined in a crate using the 2015 edition, then that macro works fine, even if it were called from a 2018 crate where `dyn` is a keyword and that would normally be a syntax error.
+The `let dyn = 1;` tokens are marked as being from 2015, and the compiler will remember that wherever that code gets expanded.
+The parser looks at the edition of the tokens to know how to interpret it.
+
+The problem arises when changing the edition to 2018 in the crate where it is defined.
+Now, those tokens are tagged with the 2018 edition, and those will fail to parse.
+However, since we never called the macro from our crate, `cargo fix --edition` never had a chance to inspect the macro and fix it.
+
+<!-- TODO: hopefully someday, the reference will have chapters on how expansion works, and this can link there for actual details. -->
+
+## Documentation tests
+
+At this time, `cargo fix` is not able to update [documentation tests].
+After updating the edition in `Cargo.toml`, you should run `cargo test` to ensure everything still passes.
+If your documentation tests use syntax that is not supported in the new edition, you will need to update them manually.
+
+In rare cases, you can manually set the edition for each test.
+For example, you can use the [`edition2018` annotation][rustdoc-annotation] on the triple backticks to tell `rustdoc` which edition to use.
+
+## Generated code
+
+Another area where the automated fixes cannot apply is if you have a build script which generates Rust code at compile time (see [Code generation] for an example).
+In this situation, if you end up with code that doesn't work in the next edition, you will need to manually change the build script to generate code that is compatible.
+
+## Migrating non-Cargo projects
+
+If your project is not using Cargo as a build system, it may still be possible to make use of the automated lints to assist migrating to the next edition.
+You can enable the migration lints as described above by enabling the appropriate [lint group].
+For example, you can use the `#![warn(rust_2021_compatibility)]` attribute or the `-Wrust-2021-compatibility` or `--force-warns=rust-2021-compatibility` [CLI flag].
+
+The next step is to apply those lints to your code.
+There are several options here:
+
+* Manually read the warnings and apply the suggestions recommended by the compiler.
+* Use an editor or IDE that supports automatically applying suggestions.
+  For example, [Visual Studio Code] with the [Rust Analyzer extension] has the ability to use the "Quick Fix" links to automatically apply suggestions.
+  Many other editors and IDEs have similar functionality.
+* Write a migration tool using the [`rustfix`] library.
+  This is the library that Cargo uses internally to take the [JSON messages] from the compiler and modify the source code.
+  Check the [`examples` directory][rustfix-examples] for examples of how to use the library.
+
+## Writing idiomatic code in a new edition
+
+Editions are not only about new features and removing old ones.
+In any programming language, idioms change over time, and Rust is no exception.
+While old code will continue to compile, it might be written with different idioms today.
+
+For example, in Rust 2015, external crates must be listed with `extern crate` like this:
+
+```rust,ignore
+// src/lib.rs
+extern crate rand;
+```
+
+In Rust 2018, it is [no longer necessary](../rust-2018/path-changes.md#no-more-extern-crate) to include these items.
+
+`cargo fix` has the `--edition-idioms` option to automatically transition some of these idioms to the new syntax.
+
+> **Warning**: The current *"idiom lints"* are known to have some problems.
+> They may make incorrect suggestions which may fail to compile.
+> The current lints are:
+> * Edition 2018:
+>     * [`unused-extern-crates`]
+>     * [`explicit-outlives-requirements`]
+> * Edition 2021 does not have any idiom lints.
+>
+> The following instructions are recommended only for the intrepid who are willing to work through a few compiler/Cargo bugs!
+> If you run into problems, you can try the `--broken-code` option [described above](#partial-migration-with-broken-code) to make as much progress as possible, and then resolve the remaining issues manually.
+
+With that out of the way, we can instruct Cargo to fix our code snippet with:
+
+```console
+cargo fix --edition-idioms
+```
+
+Afterwards, the line with `extern crate rand;` in `src/lib.rs` will be removed.
+
+We're now more idiomatic, and we didn't have to fix our code manually!
+
+[`cargo check`]: ../../cargo/commands/cargo-check.html
+[`cargo fix`]: ../../cargo/commands/cargo-fix.html
+[`explicit-outlives-requirements`]:  ../../rustc/lints/listing/allowed-by-default.html#explicit-outlives-requirements
+[`keyword-idents`]: ../../rustc/lints/listing/allowed-by-default.html#keyword-idents
+[`rustfix`]: https://github.com/rust-lang/rustfix
+[`unused-extern-crates`]: ../../rustc/lints/listing/allowed-by-default.html#unused-extern-crates
+[Cargo features]: ../../cargo/reference/features.html
+[Cargo package]: ../../cargo/reference/manifest.html#the-package-section
+[Cargo targets]: ../../cargo/reference/cargo-targets.html
+[Cargo workspace]: ../../cargo/reference/workspaces.html
+[CLI flag]: ../../rustc/lints/levels.html#via-compiler-flag
+[Code generation]: ../../cargo/reference/build-script-examples.html#code-generation
+[conditional compilation]: ../../reference/conditional-compilation.html
+[documentation tests]: ../../rustdoc/documentation-tests.html
+[JSON messages]: ../../rustc/json.html
+[lint group]: ../../rustc/lints/groups.html
+[lints]: ../../rustc/lints/index.html
+[proc macros]: ../../reference/procedural-macros.html
+[Rust Analyzer extension]: https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer
+[rustdoc-annotation]: ../../rustdoc/documentation-tests.html#attributes
+[rustfix-examples]: https://github.com/rust-lang/rustfix/tree/master/examples
+[Visual Studio Code]: https://code.visualstudio.com/
index beb2360435daa9bdfdbb2b800b02ebcf3297cd69..6732837e82df42d9ff2a240e0ea4766e513ebeb1 100644 (file)
@@ -1,37 +1,54 @@
 # Transitioning an existing project to a new edition
 
-New editions might change the way you write Rust – they add new syntax,
-language, and library features, and also remove features. For example, `try`,
-`async`, and `await` are keywords in Rust 2018, but not Rust 2015. If you
-have a project that's using Rust 2015, and you'd like to use Rust 2018 for it
-instead, there's a few steps that you need to take.
+Rust includes tooling to automatically transition a project from one edition to the next.
+It will update your source code so that it is compatible with the next edition.
+Briefly, the steps to update to the next edition are:
+
+1. Run `cargo fix --edition`
+2. Edit `Cargo.toml` and set the `edition` field to the next edition, for example `edition = "2021"`
+3. Run `cargo build` or `cargo test` to verify the fixes worked.
+
+<!-- remove this when 2021 is stabilized -->
+> If you are migrating from 2018 to 2021, the steps are slightly different because 2021 is not yet stabilized, and is only available on the [nightly channel].
+> The steps to follow are:
+>
+> 1. Install the most recent nightly: `rustup update nightly`.
+> 2. Run `cargo +nightly fix --edition`.
+> 3. Edit `Cargo.toml` and place `cargo-features = ["edition2021"]` at the top (above `[package]`), and change the edition field to say `edition = "2021"`.
+> 4. Run `cargo +nightly check` to verify it now works in the new edition.
+
+The following sections dig into the details of these steps, and some of the issues you may encounter along the way.
 
 > It's our intention that the migration to new editions is as smooth an
 > experience as possible. If it's difficult for you to upgrade to the latest edition,
 > we consider that a bug. If you run into problems with this process, please
-> [file a bug](https://github.com/rust-lang/rust/issues/new). Thank you!
+> [file a bug](https://github.com/rust-lang/rust/issues/new/choose). Thank you!
+
+## Starting the migration
+
+As an example, let's take a look at transitioning from the 2015 edition to the 2018 edition.
+The steps are essentially the same when transitioning to other editions like 2021.
 
-Here's an example. Imagine we have a crate that has this code in
-`src/lib.rs`:
+Imagine we have a crate that has this code in `src/lib.rs`:
 
 ```rust
 trait Foo {
-    fn foo(&self, Box<Foo>);
+    fn foo(&self, i32);
 }
 ```
 
-This code uses an anonymous parameter, that `Box<Foo>`. This is [not
+This code uses an anonymous parameter, that `i32`. This is [not
 supported in Rust 2018](../rust-2018/trait-system/no-anon-params.md), and
 so this would fail to compile. Let's get this code up to date!
 
 ## Updating your code to be compatible with the new edition
 
-Your code may or may not use features that are incompatible with the new
-edition. In order to help transition to Rust 2018, we've included a new
-subcommand with Cargo. To start, let's run it:
+Your code may or may not use features that are incompatible with the new edition.
+In order to help transition to the next edition, Cargo includes the [`cargo fix`] subcommand to automatically update your source code.
+To start, let's run it:
 
 ```console
-cargo fix --edition
+cargo fix --edition
 ```
 
 This will check your code, and automatically fix any issues that it can.
@@ -39,106 +56,43 @@ Let's look at `src/lib.rs` again:
 
 ```rust
 trait Foo {
-    fn foo(&self, _: Box<Foo>);
+    fn foo(&self, _: i32);
 }
 ```
 
-It's re-written our code to introduce a parameter name for that trait object.
+It's re-written our code to introduce a parameter name for that `i32` value.
 In this case, since it had no name, `cargo fix` will replace it with `_`,
 which is conventional for unused variables.
 
 `cargo fix` can't always fix your code automatically.
 If `cargo fix` can't fix something, it will print the warning that it cannot fix
-to the console. If you see one of these warnings, you'll have to update your code
-manually. See the corresponding section of this guide for help, and if you have
-problems, please seek help at the [user's forums](https://users.rust-lang.org/).
-
-Keep running `cargo fix --edition` until you have no more warnings.
-
-Congrats! Your code is now valid in both Rust 2015 and Rust 2018!
+to the console. If you see one of these warnings, you'll have to update your code manually.
+See the [Advanced migration strategies] chapter for more on working with the migration process, and read the chapters in this guide which explain which changes are needed.
+If you have problems, please seek help at the [user's forums](https://users.rust-lang.org/).
 
 ## Enabling the new edition to use new features
 
 In order to use some new features, you must explicitly opt in to the new
-edition. Once you're ready to commit, change your `Cargo.toml` to add the new
+edition. Once you're ready to continue, change your `Cargo.toml` to add the new
 `edition` key/value pair. For example:
 
 ```toml
 [package]
 name = "foo"
 version = "0.1.0"
-authors = ["Your Name <you@example.com>"]
 edition = "2018"
 ```
 
 If there's no `edition` key, Cargo will default to Rust 2015. But in this case,
-we've chosen `2018`, and so our code is compiling with Rust 2018!
-
-## Writing idiomatic code in a new edition
-
-Editions are not only about new features and removing old ones. In any programming
-language, idioms change over time, and Rust is no exception. While old code
-will continue to compile, it might be written with different idioms today.
-
-Our sample code contains an outdated idiom. Here it is again:
-
-```rust
-trait Foo {
-    fn foo(&self, _: Box<Foo>);
-}
-```
-
-In Rust 2018, it's considered idiomatic to use the [`dyn`
-keyword](../rust-2018/trait-system/dyn-trait-for-trait-objects.md) for
-trait objects.
-
-Eventually, we want `cargo fix` to fix all these idioms automatically in the same
-manner we did for upgrading to the 2018 edition. **Currently,
-though, the *"idiom lints"* are not ready for widespread automatic fixing.** The
-compiler isn't making `cargo fix`-compatible suggestions in many cases right
-now, and it is making incorrect suggestions in others. Enabling the idiom lints,
-even with `cargo fix`, is likely to leave your crate either broken or with many
-warnings still remaining.
+we've chosen `2018`, and so our code will compile with Rust 2018!
 
-We have plans to make these idiom migrations a seamless part of the Rust 2018
-experience, but we're not there yet. As a result the following instructions are
-recommended only for the intrepid who are willing to work through a few
-compiler/Cargo bugs!
+The next step is to test your project on the new edition.
+Run your project tests to verify that everything still works, such as running [`cargo test`].
+If new warnings are issued, you may want to consider running `cargo fix` again (without the `--edition` flag) to apply any suggestions given by the compiler.
 
-With that out of the way, we can instruct Cargo to fix our code snippet with:
-
-```console
-$ cargo fix --edition-idioms
-```
-
-Afterwards, `src/lib.rs` looks like this:
-
-```rust
-trait Foo {
-    fn foo(&self, _: Box<dyn Foo>);
-}
-```
-
-We're now more idiomatic, and we didn't have to fix our code manually!
-
-Note that `cargo fix` may still not be able to automatically update our code.
-If `cargo fix` can't fix something, it will print a warning to the console, and
-you'll have to fix it manually.
-
-As mentioned before, there are known bugs around the idiom lints which
-means they're not all ready for prime time yet. You may get a scary-looking
-warning to report a bug to Cargo, which happens whenever a fix proposed by
-`rustc` actually caused code to stop compiling by accident. If you'd like `cargo
-fix` to make as much progress as possible, even if it causes code to stop
-compiling, you can execute:
-
-```console
-$ cargo fix --edition-idioms --broken-code
-```
-
-This will instruct `cargo fix` to apply automatic suggestions regardless of
-whether they work or not. Like usual, you'll see the compilation result after
-all fixes are applied. If you notice anything wrong or unusual, please feel free
-to report an issue to Cargo and we'll help prioritize and fix it.
+Congrats! Your code is now valid in both Rust 2015 and Rust 2018!
 
-Enjoy the new edition!
+[`cargo fix`]: ../../cargo/commands/cargo-fix.html
+[`cargo test`]: ../../cargo/commands/cargo-test.html
+[Advanced migration strategies]: advanced-migrations.md
+[nightly channel]: ../../book/appendix-07-nightly-rust.html
index e26e7fbfeb76f332ddfba1e62fd2e960b890ae23..acdb2282dd02b0a2ec29de8e83fe8bbc607d3b30 100644 (file)
@@ -2,6 +2,12 @@
 
 ## Summary
 
+- Arrays implement `IntoIterator` in *all* editions.
+- Calls to `IntoIterator::into_iter` are *hidden* in Rust 2015 and Rust 2018 when using method call syntax
+  (i.e., `array.into_iter()`). So, `array.into_iter()` still resolves to `(&array).into_iter()` as it
+  has before.
+- `array.into_iter()` changes meaning to be the call to `IntoIterator::into_inter` in Rust 2021.
+
 ## Details
 
 Until Rust 1.53, only *references* to arrays implement `IntoIterator`.
@@ -20,8 +26,7 @@ Just [adding the trait implementation][20] would break existing code.
 `(&array).into_iter()` due to [how method call syntax works][22].
 Adding the trait implementation would change the meaning.
 
-Usually we categorize this type of breakage
-(adding a trait implementation) 'minor' and acceptable.
+Usually this type of breakage (adding a trait implementation) is categorized as 'minor' and acceptable.
 But in this case there is too much code that would be broken by it.
 
 It has been suggested many times to "only implement `IntoIterator` for arrays in Rust 2021".
@@ -29,8 +34,8 @@ However, this is simply not possible.
 You can't have a trait implementation exist in one edition and not in another,
 since editions can be mixed.
 
-Instead, we decided to add the trait implementation in *all* editions (starting in Rust 1.53.0),
-but add a small hack to avoid breakage until Rust 2021.
+Instead, the trait implementation was added in *all* editions (starting in Rust 1.53.0)
+but with a small hack to avoid breakage until Rust 2021.
 In Rust 2015 and 2018 code, the compiler will still resolve `array.into_iter()`
 to `(&array).into_iter()` like before, as if the trait implementation does not exist.
 This *only* applies to the `.into_iter()` method call syntax.
@@ -39,11 +44,55 @@ It does not affect any other syntax such as `for e in [1, 2, 3]`, `iter.zip([1,
 Those will start to work in *all* editions.
 
 While it's a shame that this required a small hack to avoid breakage,
-we're very happy with how this solution keeps the difference between
-the editions to an absolute minimum.
-Since the hack is only present in the older editions,
-there is no added complexity in the new edition.
+this solution keeps the difference between the editions to an absolute minimum.
 
 [25]: https://github.com/rust-lang/rust/issues/25725
 [20]: https://github.com/rust-lang/rust/pull/65819
-[22]: https://doc.rust-lang.org/book/ch05-03-method-syntax.html#wheres-the---operator
\ No newline at end of file
+[22]: https://doc.rust-lang.org/book/ch05-03-method-syntax.html#wheres-the---operator
+
+## Migration
+
+A lint, `array_into_iter`, gets triggered whenever there is some call to `into_iter()` that will change
+meaning in Rust 2021. The `array_into_iter` lint has already been a warning by default on all editions 
+since the 1.41 release (with several enhancements made in 1.55). If your code is already warning free, 
+then it should already be ready to go for Rust 2021!
+
+You can automatically migrate your code to be Rust 2021 Edition compatible or ensure it is already compatible by
+running:
+
+```sh
+cargo fix --edition
+```
+
+Because the difference between editions is small, the migration to Rust 2021 is fairly straight-forward.
+
+For method calls of `into_iter` on arrays, the elements being implemented will change from references to owned values.
+
+For example:
+
+```rust
+fn main() {
+  let array = [1u8, 2, 3];
+  for x in array.into_iter() {
+    // x is a `&u8` in Rust 2015 and Rust 2018
+    // x is a `u8` in Rust 2021
+  }
+}
+```
+
+The most straightforward way to migrate in Rust 2021, is by keeping the exact behavior from previous editions
+by calling `iter()` which also iterates over owned arrays by reference:
+
+```rust
+fn main() {
+  let array = [1u8, 2, 3];
+  for x in array.iter() { // <- This line changed
+    // x is a `&u8` in all editions
+  }
+}
+```
+
+### Optional migration
+
+If you are using fully qualified method syntax (i.e., `IntoIterator::into_iter(array)`) in a previous edition,
+this can be upgraded to method call syntax (i.e., `array.into_iter()`).
\ No newline at end of file
index a798b873fdf19e790a37cc3c54d3a5bc8ba3ad66..aae3f39897f50cf9544d87417f0a6c0abcdc8ba4 100644 (file)
@@ -2,6 +2,8 @@
 
 ## Summary
 
+- `edition = "2021"` implies `resolver = "2"` in `Cargo.toml`.
+
 ## Details
 
 Since Rust 1.51.0, Cargo has opt-in support for a [new feature resolver][4]
@@ -14,5 +16,156 @@ The new feature resolver no longer merges all requested features for
 crates that are depended on in multiple ways.
 See [the announcement of Rust 1.51][5] for details.
 
-[4]: https://doc.rust-lang.org/cargo/reference/resolver.html#feature-resolver-version-2
-[5]: https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#cargos-new-feature-resolver
\ No newline at end of file
+[4]: ../../cargo/reference/resolver.html#feature-resolver-version-2
+[5]: https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#cargos-new-feature-resolver
+
+## Migration
+
+There are no automated migration tools for updating for the new resolver.
+For most projects, there are usually few or no changes as a result of updating.
+
+When updating with `cargo fix --edition`, Cargo will display a report if the new resolver will build dependencies with different features.
+It may look something like this:
+
+> note: Switching to Edition 2021 will enable the use of the version 2 feature resolver in Cargo.
+> This may cause some dependencies to be built with fewer features enabled than previously.
+> More information about the resolver changes may be found at <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/default-cargo-resolver.html><br>
+> When building the following dependencies, the given features will no longer be used:
+>
+> ```text
+>   bstr v0.2.16: default, lazy_static, regex-automata, unicode
+>   libz-sys v1.1.3 (as host dependency): libc
+> ```
+
+This lets you know that certain dependencies will no longer be built with the given features.
+
+### Build failures
+
+There may be some circumstances where your project may not build correctly after the change.
+If a dependency declaration in one package assumes that certain features are enabled in another, and those features are now disabled, it may fail to compile.
+
+For example, let's say we have a dependency like this:
+
+```toml
+# Cargo.toml
+
+[dependencies]
+bstr = { version = "0.2.16", default-features = false }
+# ...
+```
+
+And somewhere in our dependency tree, another package has this:
+
+```toml
+# Another package's Cargo.toml
+
+[build-dependencies]
+bstr = "0.2.16"
+```
+
+In our package, we've been using the [`words_with_breaks`](https://docs.rs/bstr/0.2.16/bstr/trait.ByteSlice.html#method.words_with_breaks) method from `bstr`, which requires `bstr`'s  "unicode" feature to be enabled.
+This has historically worked because Cargo unified the features of `bstr` between the two packages.
+However, after updating to Rust 2021, the new resolver will build `bstr` twice, once with the default features (as a build dependency), and once with no features (as our normal dependency).
+Since `bstr` is now being built without the "unicode" feature, the `words_with_breaks` method doesn't exist, and the build will fail with an error that the method is missing.
+
+The solution here is to ensure that the dependency is declared with the features you are actually using.
+For example:
+
+```toml
+[dependencies]
+bstr = { version = "0.2.16", default-features = false, features = ["unicode"] }
+```
+
+In some cases, this may be a problem with a third-party dependency that you don't have direct control over.
+You can consider submitting a patch to that project to try to declare the correct set of features for the problematic dependency.
+Alternatively, you can add features to any dependency from within your own `Cargo.toml` file.
+For example, if the `bstr` example given above was declared in some third-party dependency, you can just copy the correct dependency declaration into your own project.
+The features will be unified, as long as they match the unification rules of the new resolver. Those are:
+
+* Features enabled on platform-specific dependencies for targets not currently being built are ignored.
+* Build-dependencies and proc-macros do not share features with normal dependencies.
+* Dev-dependencies do not activate features unless building a target that needs them (like tests or examples).
+
+A real-world example is using [`diesel`](https://crates.io/crates/diesel) and [`diesel_migrations`](https://crates.io/crates/diesel_migrations).
+These packages provide database support, and the database is selected using a feature, like this:
+
+```toml
+[dependencies]
+diesel = { version = "1.4.7", features = ["postgres"] }
+diesel_migrations = "1.4.0"
+```
+
+The problem is that `diesel_migrations` has an internal proc-macro which itself depends on `diesel`, and the proc-macro assumes its own copy of `diesel` has the same features enabled as the rest of the dependency graph.
+After updating to the new resolver, it fails to build because now there are two copies of `diesel`, and the one built for the proc-macro is missing the "postgres" feature.
+
+A solution here is to add `diesel` as a build-dependency with the required features, for example:
+
+```toml
+[build-dependencies]
+diesel = { version = "1.4.7", features = ["postgres"] }
+```
+
+This causes Cargo to add "postgres" as a feature for host dependencies (proc-macros and build-dependencies).
+Now, the `diesel_migrations` proc-macro will get the "postgres" feature enabled, and it will build correctly.
+
+The 2.0 release of `diesel` (currently in development) does not have this problem as it has been restructured to not have this dependency requirement.
+
+### Exploring features
+
+The [`cargo tree`] command has had substantial improvements to help with the migration to the new resolver.
+`cargo tree` can be used to explore the dependency graph, and to see which features are being enabled, and importantly *why* they are being enabled.
+
+One option is to use the `--duplicates` flag (`-d` for short), which will tell you when a package is being built multiple times.
+Taking the `bstr` example from earlier, we might see:
+
+```console
+> cargo tree -d
+bstr v0.2.16
+└── foo v0.1.0 (/MyProjects/foo)
+
+bstr v0.2.16
+[build-dependencies]
+└── bar v0.1.0
+    └── foo v0.1.0 (/MyProjects/foo)
+
+```
+
+This output tells us that `bstr` is built twice, and shows the chain of dependencies that led to its inclusion in both cases.
+
+You can print which features each package is using with the `-f` flag, like this:
+
+```console
+cargo tree -f '{p} {f}'
+```
+
+This tells Cargo to change the "format" of the output, where it will print both the package and the enabled features.
+
+You can also use the `-e` flag to tell it which "edges" to display.
+For example, `cargo tree -e features` will show in-between each dependency which features are being added by each dependency.
+This option becomes more useful with the `-i` flag which can be used to "invert" the tree.
+This allows you to see how features *flow* into a given dependency.
+For example, let's say the dependency graph is large, and we're not quite sure who is depending on `bstr`, the following command will show that:
+
+```console
+> cargo tree -e features -i bstr
+bstr v0.2.16
+├── bstr feature "default"
+│   [build-dependencies]
+│   └── bar v0.1.0
+│       └── bar feature "default"
+│           └── foo v0.1.0 (/MyProjects/foo)
+├── bstr feature "lazy_static"
+│   └── bstr feature "unicode"
+│       └── bstr feature "default" (*)
+├── bstr feature "regex-automata"
+│   └── bstr feature "unicode" (*)
+├── bstr feature "std"
+│   └── bstr feature "default" (*)
+└── bstr feature "unicode" (*)
+```
+
+This snippet of output shows that the project `foo` depends on `bar` with the "default" feature.
+Then, `bar` depends on `bstr` as a build-dependency with the "default" feature
+We can further see that `bstr`'s  "default" feature enables "unicode" (among other features).
+
+[`cargo tree`]: ../../cargo/commands/cargo-tree.html
index 4e47fd452dfcca03c4f22d47c98dd2d9cbedf90b..f82b486ac95d971a71cf33979cbde750c6399e17 100644 (file)
 
 ## Summary
 
+- `|| a.x + 1` now captures only `a.x` instead of `a`.
+- This can cause things to be dropped at different times or affect whether closures implement traits like `Send` or `Clone`.
+  - If possible changes are detected, `cargo fix` will insert statements like `let _ = &a` to force a closure to capture the entire variable.
+
 ## Details
 
 [Closures](https://doc.rust-lang.org/book/ch13-01-closures.html)
 automatically capture anything that you refer to from within their body.
 For example, `|| a + 1` automatically captures a reference to `a` from the surrounding context.
 
-Currently, this applies to whole structs, even when only using one field.
+In Rust 2018 and before, closures capture entire variables, even if the closure only uses one field.
 For example, `|| a.x + 1` captures a reference to `a` and not just `a.x`.
-In some situations, this is a problem.
-When a field of the struct is already borrowed (mutably) or moved out of,
-the other fields can no longer be used in a closure,
-since that would capture the whole struct, which is no longer available.
+Capturing `a` in its entirety prevents mutation or moves from other fields of `a`, so that code like this does not compile:
 
 ```rust,ignore
 let a = SomeStruct::new();
-
 drop(a.x); // Move out of one field of the struct
-
 println!("{}", a.y); // Ok: Still use another field of the struct
-
 let c = || println!("{}", a.y); // Error: Tries to capture all of `a`
 c();
 ```
 
-Starting in Rust 2021, closures will only capture the fields that they use.
-So, the above example will compile fine in Rust 2021.
+Starting in Rust 2021, closures captures are more precise. Typically they will only capture the fields they use (in some cases, they might capture more than just what they use, see the Rust reference for full details). Therefore, the above example will compile fine in Rust 2021.
+
+Disjoint capture was proposed as part of [RFC 2229](https://github.com/rust-lang/rfcs/blob/master/text/2229-capture-disjoint-fields.md) and the RFC contains details about the motivation.
+
+## Migrating to Rust 2021
+
+Changing the variables captured by a closure can cause programs to change behavior or to stop compiling in two cases:
+
+- changes to drop order, or when destructors run ([details](#drop-order));
+- changes to which traits a closure implements ([details](#trait-implementations)).
+
+Whenever any of the scenarios below are detected, `cargo fix` will insert a "dummy let" into your closure to force it to capture the entire variable:
+
+```rust
+let x = (vec![22], vec![23]);
+let c = move || {
+    // "Dummy let" that forces `x` to be captured in its entirety
+    let _ = &x;
+
+    // Otherwise, only `x.0` would be captured here
+    println!("{:?}", x.0);
+};
+```
+
+This is a conservative analysis: in many cases, these dummy lets can be safely removed and your program will work fine.
+
+### Wild Card Patterns
+
+Closures now only capture data that needs to be read, which means the following closures will not capture `x`:
+
+```rust
+let x = 10;
+let c = || {
+    let _ = x; // no-op
+};
+
+let c = || match x {
+    _ => println!("Hello World!")
+};
+```
+
+The `let _ = x` statement here is a no-op, since the `_` pattern completely ignores the right-hand side, and `x` is a reference to a place in memory (in this case, a variable).
+
+This change by itself (capturing fewer values) doesn't trigger any suggestions, but it may do so in conjunction with the "drop order" change below.
+
+**Subtle:** There are other similar expressions, such as the "dummy lets" `let _ = &x` that we insert, which are not no-ops. This is because the right-hand side (`&x`) is not a reference to a place in memory, but rather an expression that must first be evaluated (and whose result is then discarded).
+
+### Drop Order
+
+When a closure takes ownership of a value from a variable `t`, that value is then dropped when the closure is dropped, and not when the variable `t` goes out of scope:
 
-This new behavior is only activated in the new edition,
-since it can change the order in which fields are dropped.
-As for all edition changes, an automatic migration is available,
-which will update your closures for which this matters.
-It can insert `let _ = &a;` inside the closure to force the entire
-struct to be captured as before.
+```rust
+# fn move_value<T>(_: T){}
+{
+    let t = (vec![0], vec![0]);
+
+    {
+        let c = || move_value(t); // t is moved here
+    } // c is dropped, which drops the tuple `t` as well
+} // t goes out of scope here
+```
+
+The above code will run the same in both Rust 2018 and Rust 2021. However, in cases where the closure only takes ownership of _part_ of a variable, there can be differences:
+
+```rust
+# fn move_value<T>(_: T){}
+{
+    let t = (vec![0], vec![0]);
+
+    {
+        let c = || {
+            // In Rust 2018, captures all of `t`.
+            // In Rust 2021, captures only `t.0`
+            move_value(t.0);
+        };
+
+        // In Rust 2018, `c` (and `t`) are both dropped when we
+        // exit this block.
+        //
+        // In Rust 2021, `c` and `t.0` are both dropped when we
+        // exit this block.
+    }
+
+// In Rust 2018, the value from `t` has been moved and is
+// not dropped.
+//
+// In Rust 2021, the value from `t.0` has been moved, but `t.1`
+// remains, so it will be dropped here.
+}
+```
+
+In most cases, dropping values at different times just affects when memory is freed and is not important. However, some `Drop` impls (aka, destructors) have side-effects, and changing the drop order in those cases can alter the semantics of your program. In such cases, the compiler will suggest inserting a dummy `let` to force the entire variable to be captured.
+
+### Trait implementations
+
+Closures automatically implement the following traits based on what values they capture:
+
+- [`Clone`]: if all captured values are [`Clone`].
+- [Auto traits] like [`Send`], [`Sync`], and [`UnwindSafe`]: if all captured values implement the given trait.
+
+[auto traits]: https://doc.rust-lang.org/nightly/reference/special-types-and-traits.html#auto-traits
+[`clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
+[`send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
+[`sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
+[`unwindsafe`]: https://doc.rust-lang.org/std/marker/trait.UnwindSafe.html
+
+In Rust 2021, since different values are being captured, this can affect what traits a closure will implement. The migration lints test each closure to see whether it would have implemented a given trait before and whether it still implements it now; if they find that a trait used to be implemented but no longer is, then "dummy lets" are inserted.
+
+For instance, a common way to allow passing around raw pointers between threads is to wrap them in a struct and then implement `Send`/`Sync` auto trait for the wrapper. The closure that is passed to `thread::spawn` uses the specific fields within the wrapper but the entire wrapper is captured regardless. Since the wrapper is `Send`/`Sync`, the code is considered safe and therefore compiles successfully.
+
+With disjoint captures, only the specific field mentioned in the closure gets captured, which wasn't originally `Send`/`Sync` defeating the purpose of the wrapper.
+
+```rust
+use std::thread;
+
+struct Ptr(*mut i32);
+unsafe impl Send for Ptr {}
+
+
+let mut x = 5;
+let px = Ptr(&mut x as *mut i32);
+
+let c = thread::spawn(move || {
+    unsafe {
+        *(px.0) += 10;
+    }
+}); // Closure captured px.0 which is not Send
+```
index 451b0e5f6425937881f5a04e36f0b378134f22b3..58d6d5517e63c25081f5077c26b0cede51c9ce6b 100644 (file)
@@ -2,6 +2,11 @@
 
 ## Summary
 
+- How patterns work in `macro_rules` macros changes slightly:
+       - `$_:pat` in `macro_rules` now matches usage of `|` too: e.g. `A | B`.
+       - The new `$_:pat_param` behaves like `$_:pat` did before; it does not match (top level) `|`.
+       - `$_:pat_param` is available in all editions.
+
 ## Details
 
 Starting in Rust 1.53.0, [patterns](https://doc.rust-lang.org/stable/reference/patterns.html)
@@ -11,18 +16,57 @@ Since this was simply not allowed before, this is not a breaking change.
 
 However, this change also affects [`macro_rules` macros](https://doc.rust-lang.org/stable/reference/macros-by-example.html).
 Such macros can accept patterns using the `:pat` fragment specifier.
-Currently, `:pat` does *not* match `|`, since before Rust 1.53,
+Currently, `:pat` does *not* match top level `|`, since before Rust 1.53,
 not all patterns (at all nested levels) could contain a `|`.
 Macros that accept patterns like `A | B`,
 such as [`matches!()`](https://doc.rust-lang.org/1.51.0/std/macro.matches.html)
-use something like `$($_:pat)|+`.
-Because we don't want to break any existing macros,
-we did *not* change the meaning of `:pat` in Rust 1.53.0 to include `|`.
+use something like `$($_:pat)|+`. 
 
-Instead, we will make that change as part of Rust 2021.
+Because this would potentially break existing macros, the meaning of `:pat` did 
+not change in Rust 1.53.0 to include `|`. Instead, that change happens in Rust 2021. 
 In the new edition, the `:pat` fragment specifier *will* match `A | B`.
 
-Since there are times that one still wishes to match a single pattern
-variant without `|`, the fragment specified `:pat_param` has been added
-to retain the older behavior.
-The name refers to its main use case: a pattern in a closure parameter.
+`$_:pat` fragments in Rust 2021 cannot be followed by an explicit `|`. Since there are times 
+that one still wishes to match pattern fragments followed by a `|`, the fragment specified `:pat_param` 
+has been added to retain the older behavior.
+
+It's important to remember that editions are _per crate_, so the only relevant edition is the edition
+of the crate where the macro is defined. The edition of the crate where the macro is used does not 
+change how the macro works.
+
+## Migration to Rust 2021
+
+A lint, `rust_2021_incompatible_or_patterns`, gets triggered whenever there is a use `$:_pat` which
+will change meaning in Rust 2021. 
+
+You can automatically migrate your code to be Rust 2021 Edition compatible or ensure it is already compatible by
+running:
+
+```sh
+cargo fix --edition
+```
+
+If you have a macro which relies on `$_:pat` not matching the top level use of `|` in patterns, 
+you'll need to change each occurrence of `$_:pat` to `$_:pat_param`.
+
+For example:
+
+```rust
+macro_rules! my_macro { 
+       ($x:pat | $y:pat) => {
+               // TODO: implementation
+       } 
+}
+
+// This macro works in Rust 2018 since `$x:pat` does not match against `|`:
+my_macro!(1 | 2);
+
+// In Rust 2021 however, the `$_:pat` fragment matches `|` and is not allowed
+// to be followed by a `|`. To make sure this macro still works in Rust 2021
+// change the macro to the following:
+macro_rules! my_macro { 
+       ($x:pat_param | $y:pat) => { // <- this line is different
+               // TODO: implementation
+       } 
+}
+```
\ No newline at end of file
index cf4265bcc575a25397432013c5b6380e3e1eeb18..0e3295186eab340399207144ece96ab383fc1f7a 100644 (file)
@@ -2,14 +2,21 @@
 
 ## Summary
 
-## Details
+- `panic!(..)` now always uses `format_args!(..)`, just like `println!()`.
+- `panic!("{")` is no longer accepted, without escaping the `{` as `{{`.
+- `panic!(x)` is no longer accepted if `x` is not a string literal.
+  - Use `std::panic::panic_any(x)` to panic with a non-string payload.
+  - Or use `panic!("{}", x)` to use `x`'s `Display` implementation.
+- The same applies to `assert!(expr, ..)`.
 
+## Details
 
 The `panic!()` macro is one of Rust's most well known macros.
 However, it has [some subtle surprises](https://github.com/rust-lang/rfcs/blob/master/text/3007-panic-plan.md)
 that we can't just change due to backwards compatibility.
 
 ```rust,ignore
+// Rust 2018
 panic!("{}", 1); // Ok, panics with the message "1"
 panic!("{}"); // Ok, panics with the message "{}"
 ```
@@ -18,12 +25,14 @@ The `panic!()` macro only uses string formatting when it's invoked with more tha
 When invoked with a single argument, it doesn't even look at that argument.
 
 ```rust,ignore
+// Rust 2018
 let a = "{";
 println!(a); // Error: First argument must be a format string literal
 panic!(a); // Ok: The panic macro doesn't care
 ```
 
-(It even accepts non-strings such as `panic!(123)`, which is uncommon and rarely useful.)
+It even accepts non-strings such as `panic!(123)`, which is uncommon and rarely useful since it
+produces a surprisingly unhelpful message: `panicked at 'Box<Any>'`.
 
 This will especially be a problem once
 [implicit format arguments](https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html)
@@ -39,6 +48,37 @@ Since `panic!()` will no longer accept arbitrary payloads,
 [`panic_any()`](https://doc.rust-lang.org/stable/std/panic/fn.panic_any.html)
 will be the only way to panic with something other than a formatted string.
 
+```rust,ignore
+// Rust 2021
+panic!("{}", 1); // Ok, panics with the message "1"
+panic!("{}"); // Error, missing argument
+panic!(a); // Error, must be a string literal
+```
+
 In addition, `core::panic!()` and `std::panic!()` will be identical in Rust 2021.
 Currently, there are some historical differences between those two,
-which can be noticable when switching `#![no_std]` on or off.
\ No newline at end of file
+which can be noticeable when switching `#![no_std]` on or off.
+
+## Migration
+
+A lint, `non_fmt_panics`, gets triggered whenever there is some call to `panic` that uses some 
+deprecated behavior that will error in Rust 2021. The `non_fmt_panics` lint has already been a warning 
+by default on all editions since the 1.50 release (with several enhancements made in later releases). 
+If your code is already warning free, then it should already be ready to go for Rust 2021!
+
+You can automatically migrate your code to be Rust 2021 Edition compatible or ensure it is already compatible by
+running:
+
+```sh
+cargo fix --edition
+```
+
+Should you choose or need to manually migrate, you'll need to update all panic invocations to either use the same 
+formatting as `println` or use `std::panic::panic_any` to panic with non-string data.
+
+For example, in the case of `panic!(MyStruct)`, you'll need to convert to using `std::panic::panic_any` (note
+that this is a function not a macro): `std::panic::panic_any(MyStruct)`.
+
+In the case of panic messages that include curly braces but the wrong number of arguments (e.g., `panic!("Some curlies: {}")`), 
+you can panic with the string literal by either using the same syntax as `println!` (i.e., `panic!("{}", "Some curlies: {}")`) 
+or by escaping the curly braces (i.e., `panic!("Some curlies: {{}}")`).
\ No newline at end of file
index 2d182066f08726496412c1b00e7d74ade50bcd12..97e6df865d82955d2989eb3ea4cdfa6e2a2af59b 100644 (file)
@@ -2,6 +2,9 @@
 
 ## Summary
 
+- The `TryInto`, `TryFrom` and `FromIterator` traits are now part of the prelude.
+- This might make calls to trait methods ambiguous which could make some code fail to compile.
+
 ## Details
 
 The [prelude of the standard library](https://doc.rust-lang.org/stable/std/prelude/index.html)
@@ -14,12 +17,11 @@ For example, if you have a crate or module called `example` containing a `pub st
 then `use example::*;` will make `Option` unambiguously refer to the one from `example`;
 not the one from the standard library.
 
-However, adding a *trait* to the prelude can break existing code in a subtle way.
-A call to `x.try_into()` using a `MyTryInto` trait might become ambiguous and
-fail to compile if `std`'s `TryInto` is also imported,
-since it provides a method with the same name.
-This is the reason we haven't added `TryInto` to the prelude yet,
-since there is a lot of code that would break this way.
+However, adding a _trait_ to the prelude can break existing code in a subtle way.
+For example, a call to `x.try_into()` which comes from a `MyTryInto` trait might fail 
+to compile if `std`'s `TryInto` is also imported, because the call to `try_into` is now 
+ambiguous and could come from either trait. This is the reason we haven't added `TryInto` 
+to the prelude yet, since there is a lot of code that would break this way.
 
 As a solution, Rust 2021 will use a new prelude.
 It's identical to the current one, except for three new additions:
@@ -28,5 +30,130 @@ It's identical to the current one, except for three new additions:
 - [`std::convert::TryFrom`](https://doc.rust-lang.org/stable/std/convert/trait.TryFrom.html)
 - [`std::iter::FromIterator`](https://doc.rust-lang.org/stable/std/iter/trait.FromIterator.html)
 
-The library team still needs to formally approve these, which will likely happen soon.
-<!-- TODO: hopefully this happens before we publish this -->
+The tracking issue [can be found here](https://github.com/rust-lang/rust/issues/85684).
+
+## Migration to Rust 2021
+
+As a part of the 2021 edition a migration lint, `rust_2021_prelude_collisions`, has been added in order to aid in automatic migration of Rust 2018 codebases to Rust 2021.
+
+In order to have `rustfix` migrate your code to be Rust 2021 Edition compatible, run:
+
+```sh
+cargo fix --edition
+```
+
+The lint detects cases where functions or methods are called that have the same name as the methods defined in one of the new prelude traits. In some cases, it may rewrite your calls in various ways to ensure that you continue to call the same function you did before.
+
+If you'd like to migrate your code manually or better understand what `rustfix` is doing, below we've outlined the situations where a migration is needed along with a counter example of when it's not needed.
+
+### Migration needed
+
+#### Conflicting trait methods
+
+When two traits that are in scope have the same method name, it is ambiguous which trait method should be used. For example:
+
+```rust
+trait MyTrait<A> {
+  // This name is the same as the `from_iter` method on the `FromIterator` trait from `std`.  
+  fn from_iter(x: Option<A>);
+}
+
+impl<T> MyTrait<()> for Vec<T> {
+  fn from_iter(_: Option<()>) {}
+}
+
+fn main() {
+  // Vec<T> implements both `std::iter::FromIterator` and `MyTrait` 
+  // If both traits are in scope (as would be the case in Rust 2021),
+  // then it becomes ambiguous which `from_iter` method to call
+  <Vec<i32>>::from_iter(None);
+}
+```
+
+We can fix this by using fully qualified syntax:
+
+```rust,ignore
+fn main() {
+  // Now it is clear which trait method we're referring to
+  <Vec<i32> as MyTrait<i32>>::from_iter(None);
+}
+```
+
+#### Inherent methods on `dyn Trait` objects
+
+Some users invoke methods on a `dyn Trait` value where the method name overlaps with a new prelude trait:
+
+```rust
+mod submodule {
+  pub trait MyTrait {
+    // This has the same name as `TryInto::try_into`
+    fn try_into(&self) -> Result<u32, ()>;
+  }
+}
+
+// `MyTrait` isn't in scope here and can only be referred to through the path `submodule::MyTrait`
+fn bar(f: Box<dyn submodule::MyTrait>) {
+  // If `std::convert::TryInto` is in scope (as would be the case in Rust 2021),
+  // then it becomes ambiguous which `try_into` method to call
+  f.try_into();
+}
+```
+
+Unlike with static dispatch methods, calling a trait method on a trait object does not require that the trait be in scope. The code above works 
+as long as there is no trait in scope with a conflicting method name. When the `TryInto` trait is in scope (which is the case in Rust 2021),
+this causes an ambiguity. Should the call be to `MyTrait::try_into` or `std::convert::TryInto::try_into`?
+
+In these cases, we can fix this by adding an additional dereferences or otherwise clarify the type of the method receiver. This ensures that 
+the `dyn Trait` method is chosen, versus the methods from the prelude trait. For example, turning `f.try_into()` above into `(&*f).try_into()` 
+ensures that we're calling `try_into` on the `dyn MyTrait` which can only refer to the `MyTrait::try_into` method.
+
+### No migration needed
+
+####  Inherent methods
+
+Many types define their own inherent methods with the same name as a trait method. For instance, below the struct `MyStruct` implements `from_iter` which shares the same name with the method from the trait `FromIterator` found in the standard library:
+
+```rust
+use std::iter::IntoIterator;
+
+struct MyStruct {
+  data: Vec<u32>
+}
+
+impl MyStruct {
+  // This has the same name as `std::iter::FromIterator::from_iter`
+  fn from_iter(iter: impl IntoIterator<Item = u32>) -> Self {
+    Self {
+      data: iter.into_iter().collect()
+    }
+  }
+}
+
+impl std::iter::FromIterator<u32> for MyStruct {
+    fn from_iter<I: IntoIterator<Item = u32>>(iter: I) -> Self {
+      Self {
+        data: iter.into_iter().collect()
+      }
+    }
+}
+```
+
+Inherent methods always take precedent over trait methods so there's no need for any migration.
+
+### Implementation Reference
+
+The lint needs to take a couple of factors into account when determining whether or not introducing 2021 Edition to a codebase will cause a name resolution collision (thus breaking the code after changing edition). These factors include:
+
+- Is the call a [fully-qualified call] or does it use [dot-call method syntax]?
+  - This will affect how the name is resolved due to auto-reference and auto-dereferencing on method call syntax. Manually dereferencing/referencing will allow specifying priority in the case of dot-call method syntax, while fully-qualified call requires specification of the type and the trait name in the method path (e.g. `<Type as Trait>::method`)
+- Is this an [inherent method] or [a trait method]?
+  - Inherent methods that take `self` will take priority over `TryInto::try_into` as inherent methods take priority over trait methods, but inherent methods that take `&self` or `&mut self` won't take priority due to requiring a auto-reference (while `TryInto::try_into` does not, as it takes `self`)
+- Is the origin of this method from `core`/`std`? (As the traits can't have a collision with themselves)
+- Does the given type implement the trait it could have a collision against?
+- Is the method being called via dynamic dispatch? (i.e. is the `self` type `dyn Trait`)
+  - If so, trait imports don't affect resolution, and no migration lint needs to occur
+
+[fully-qualified call]: https://doc.rust-lang.org/reference/expressions/call-expr.html#disambiguating-function-calls
+[dot-call method syntax]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html
+[inherent method]: https://doc.rust-lang.org/reference/items/implementations.html#inherent-implementations
+[a trait method]: https://doc.rust-lang.org/reference/items/implementations.html#trait-implementations
index 315954be53fc128847e7de741b30a95eb6095b70..52f8e1221a30e4a40c2edba8dd53179d7cbdda33 100644 (file)
@@ -2,6 +2,11 @@
 
 ## Summary
 
+- `any_prefix#..`, `any_prefix".."`, and `any_prefix'..'` are reserved syntax, and no longer tokenize.
+- This is mostly relevant to macros. E.g. `quote!{ #a#b }` is no longer accepted.
+- It doesn't treat keywords specially, so e.g. `match".." {}` is no longer accepted.
+- Insert whitespace to avoid errors.
+
 ## Details
 
 To make space for some new syntax in the future,
@@ -37,4 +42,4 @@ These are some new prefixes you might see in the future:
   this prefix would've allowed us to accept `k#async` in edition 2015
   without having to wait for edition 2018 to reserve `async` as a keyword.
 
-[10]: https://github.com/rust-lang/rfcs/pull/3101
\ No newline at end of file
+[10]: https://github.com/rust-lang/rfcs/pull/3101
index 5c20246d187d2b11a0c45237c4ee73b2510700d9..f17e2b2b26ffda80a47e8ab35f4697cc54495568 100644 (file)
@@ -2,16 +2,48 @@
 
 ## Summary
 
+- Code that triggered the `bare_trait_objects` and `ellipsis_inclusive_range_patterns` lints will error in Rust 2021.
+
 ## Details
 
-Two existing lints are becoming hard errors in Rust 2021.
-These lints will remain warnings in older editions.
+Two existing lints are becoming hard errors in Rust 2021, but these lints will remain warnings in older editions.
+
+### `bare_trait_objects`:
+
+The use of the `dyn` keyword to identify [trait objects](https://doc.rust-lang.org/book/ch17-02-trait-objects.html)
+will be mandatory in Rust 2021.
+
+For example, the following code which does not include the `dyn` keyword in `&MyTrait`
+will produce an error instead of just a lint in Rust 2021:
+
+```rust
+pub trait MyTrait {}
+
+pub fn my_function(_trait_object: &MyTrait) { // should be `&dyn MyTrait`
+  unimplemented!()
+}
+```
+
+### `ellipsis_inclusive_range_patterns`:
+
+The [deprecated `...` syntax](https://doc.rust-lang.org/stable/reference/patterns.html#range-patterns)
+for inclusive range patterns (i.e., ranges where the end value is *included* in the range) is no longer 
+accepted in Rust 2021. It has been superseded by `..=`, which is consistent with expressions.
+
+For example, the following code which uses `...` in a pattern will produce an error instead of 
+just a lint in Rust 2021:
+
+```rust
+pub fn less_or_eq_to_100(n: u8) -> bool {
+  matches!(n, 0...100) // should be `0..=100`
+}
+```
+
+## Migrations 
 
-* `bare-trait-objects`:
-  The use of the `dyn` keyword to identify [trait objects](https://doc.rust-lang.org/book/ch17-02-trait-objects.html)
-  will be mandatory in Rust 2021.
+If your Rust 2015 or 2018 code does not produce any warnings for `bare_trait_objects` 
+or `ellipsis_inclusive_range_patterns` and you've not allowed these lints through the 
+use of `#![allow()]` or some other mechanism, then there's no need to migrate.
 
-* `ellipsis-inclusive-range-patterns`:
-  The [deprecated `...` syntax](https://doc.rust-lang.org/stable/reference/patterns.html#range-patterns)
-  for inclusive range patterns is no longer accepted in Rust 2021.
-  It has been superseded by `..=`, which is consistent with expressions.
\ No newline at end of file
+To automatically migrate any crate that uses `...` in patterns or does not use `dyn` with
+trait objects, you can run `cargo fix --edition`.
\ No newline at end of file
diff --git a/src/doc/edition-guide/triagebot.toml b/src/doc/edition-guide/triagebot.toml
new file mode 100644 (file)
index 0000000..5648018
--- /dev/null
@@ -0,0 +1,4 @@
+[assign]
+
+[relabel]
+
index 5f5a09808e61f05de657a16b15342c1925d5766f..7319a397aca912f4671ade56b153c93fbcd7ce92 100644 (file)
@@ -10,7 +10,7 @@ memory allocator (AKA the heap).
 [`HashMap`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html
 
 As `core` is, by definition, free of memory allocations these implementations
-are not available there, but they can be found in the *unstable* `alloc` crate
+are not available there, but they can be found in the `alloc` crate
 that's shipped with the compiler.
 
 If you need collections, a heap allocated implementation is not your only
index 3de7c49e36bbd9df36650f95ca519104bddc494d..f7cfb959cc4bedda5fcae3d6ae83cba2601dbef1 100644 (file)
@@ -58,7 +58,7 @@ pub x: cty::c_int,
 pub y: cty::c_int,
 ```
 
-Due to the flexibility of how C or C++ defines an `int` or `char`, it is recommended to use primitive data types defined in `cty`, which will map types from C to types in Rust
+Due to the flexibility of how C or C++ defines an `int` or `char`, it is recommended to use primitive data types defined in `cty`, which will map types from C to types in Rust.
 
 ```rust,ignore
 pub extern "C" fn cool_function( ... );
@@ -80,8 +80,8 @@ We have one new type here, `*mut CoolStruct`. As C does not have a concept of Ru
 
 Rather than manually generating these interfaces, which may be tedious and error prone, there is a tool called [bindgen] which will perform these conversions automatically. For instructions of the usage of [bindgen], please refer to the [bindgen user's manual], however the typical process consists of the following:
 
-1. Gather all C or C++ headers defining interfaces or datatypes you would like to use with Rust
-2. Write a `bindings.h` file, which `#include "..."`'s each of the files you gathered in step one
+1. Gather all C or C++ headers defining interfaces or datatypes you would like to use with Rust.
+2. Write a `bindings.h` file, which `#include "..."`'s each of the files you gathered in step one.
 3. Feed this `bindings.h` file, along with any compilation flags used to compile
   your code into `bindgen`. Tip: use `Builder.ctypes_prefix("cty")` /
   `--ctypes-prefix=cty` and `Builder.use_core()` / `--use-core` to make the generated code `#![no_std]` compatible.
@@ -104,7 +104,7 @@ If your code exists as a source project, it will be necessary to compile your C/
 
 A `build.rs` script is a file written in Rust syntax, that is executed on your compilation machine, AFTER dependencies of your project have been built, but BEFORE your project is built.
 
-The full reference may be found [here](https://doc.rust-lang.org/cargo/reference/build-scripts.html). `build.rs` scripts are useful for generating code (such as via [bindgen]), calling out to external build systems such as `Make`, or directly compiling C/C++ through use of the `cc` crate
+The full reference may be found [here](https://doc.rust-lang.org/cargo/reference/build-scripts.html). `build.rs` scripts are useful for generating code (such as via [bindgen]), calling out to external build systems such as `Make`, or directly compiling C/C++ through use of the `cc` crate.
 
 ### Triggering external build systems
 
index 94221e4274a926abbc9673a5f0a3eaf3327539eb..5af7804a6462a86632e5b100adb9eb11653b4b15 100644 (file)
@@ -49,10 +49,10 @@ $ cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart
 $ cd app
 ```
 
-Step number one is to set a default compilation target in `.cargo/config`.
+Step number one is to set a default compilation target in `.cargo/config.toml`.
 
 ``` console
-tail -n5 .cargo/config
+tail -n5 .cargo/config.toml
 ```
 
 ``` toml
@@ -320,10 +320,10 @@ OpenOCD, enable semihosting, load the program and start the process.
 
 Alternatively, you can turn `<gdb> -x openocd.gdb` into a custom runner to make
 `cargo run` build a program *and* start a GDB session. This runner is included
-in `.cargo/config` but it's commented out.
+in `.cargo/config.toml` but it's commented out.
 
 ``` console
-head -n10 .cargo/config
+head -n10 .cargo/config.toml
 ```
 
 ``` toml
index 69866569c36b940a3182420e7f80aad71e921368..a56f7394c64cdbbf9e4da4a4a56c419fec798c3e 100644 (file)
@@ -137,11 +137,11 @@ bit in the function signature) to ensure at compile time that'll be the case.
 
 The next step is to *cross* compile the program for the Cortex-M3 architecture.
 That's as simple as running `cargo build --target $TRIPLE` if you know what the
-compilation target (`$TRIPLE`) should be. Luckily, the `.cargo/config` in the
+compilation target (`$TRIPLE`) should be. Luckily, the `.cargo/config.toml` in the
 template has the answer:
 
 ```console
-tail -n6 .cargo/config
+tail -n6 .cargo/config.toml
 ```
 
 ```toml
@@ -161,7 +161,7 @@ if you haven't done it yet:
 rustup target add thumbv7m-none-eabi
 ```
  Since the `thumbv7m-none-eabi` compilation target has been set as the default in 
- your `.cargo/config` file, the two commands below do the same:
+ your `.cargo/config.toml` file, the two commands below do the same:
 
 ```console
 cargo build --target thumbv7m-none-eabi
@@ -401,11 +401,11 @@ Let's break down that QEMU command:
   machine.
 
 Typing out that long QEMU command is too much work! We can set a custom runner
-to simplify the process. `.cargo/config` has a commented out runner that invokes
+to simplify the process. `.cargo/config.toml` has a commented out runner that invokes
 QEMU; let's uncomment it:
 
 ```console
-head -n3 .cargo/config
+head -n3 .cargo/config.toml
 ```
 
 ```toml
index feae1a0725429525eae99d1ea7639db0ae10bb19..cf4626f44b206214e953dc099a0582c4a5fef2d5 100644 (file)
@@ -48,7 +48,7 @@ semihosting is enabled
 QEMU understands semihosting operations so the above program will also work with
 `qemu-system-arm` without having to start a debug session. Note that you'll
 need to pass the `-semihosting-config` flag to QEMU to enable semihosting
-support; these flags are already included in the `.cargo/config` file of the
+support; these flags are already included in the `.cargo/config.toml` file of the
 template.
 
 ``` text
index da914e6ab94ef09443356b736a26b69344f53b97..6538d94ba476d5a031c8f6ae5796fdd69652357d 100644 (file)
@@ -148,10 +148,10 @@ closures).
 When optimizing for size you may want to try increasing the inline threshold to
 see if that has any effect on the binary size. The recommended way to change the
 inline threshold is to append the `-C inline-threshold` flag to the other
-rustflags in `.cargo/config`.
+rustflags in `.cargo/config.toml`.
 
 ``` toml
-# .cargo/config
+# .cargo/config.toml
 # this assumes that you are using the cortex-m-quickstart template
 [target.'cfg(all(target_arch = "arm", target_os = "none"))']
 rustflags = [
index 9e511a2b117e87172dcca7935560cf1e8e926c1e..8b61a3de6dd619fa3a259fc9c7aa1f7aea0eacf9 100644 (file)
@@ -19,14 +19,14 @@ order to write correct Unsafe Rust programs. Due to the nature of this problem,
 it may lead to unleashing untold horrors that shatter your psyche into a billion
 infinitesimal fragments of despair.
 
-### Requirements
+## Requirements
 
 Building the Nomicon requires [mdBook]. To get it:
 
 [mdBook]: https://github.com/rust-lang/mdBook
 
 ```bash
-cargo install mdbook
+cargo install mdbook
 ```
 
 ### `mdbook` usage
@@ -34,7 +34,7 @@ $ cargo install mdbook
 To build the Nomicon use the `build` sub-command:
 
 ```bash
-mdbook build
+mdbook build
 ```
 
 The output will be placed in the `book` subdirectory. To check it out, open the
@@ -43,13 +43,23 @@ build` and it'll open the index page in your default browser (if the process is
 successful) just like with `cargo doc --open`:
 
 ```bash
-mdbook build --open
+mdbook build --open
 ```
 
 There is also a `test` sub-command to test all code samples contained in the book:
 
 ```bash
-$ mdbook test
+mdbook test
+```
+
+### `linkcheck`
+
+We use the `linkcheck` tool to find broken links.
+To run it locally:
+
+```sh
+curl -sSLo linkcheck.sh https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh
+sh linkcheck.sh --all nomicon
 ```
 
 ## Contributing
index 37984f1300a80e7b0fe890499d066aa59be2c38a..a2011c61f9313ef3e67d7220c375029514bdd09a 100644 (file)
@@ -4,4 +4,32 @@ title = "The Rustonomicon"
 description = "The Dark Arts of Advanced and Unsafe Rust Programming"
 
 [output.html]
+additional-css = ["theme/nomicon.css"]
 git-repository-url = "https://github.com/rust-lang/nomicon"
+
+[output.html.redirect]
+# Vec-related chapters.
+"./vec-alloc.html" = "./vec/vec-alloc.html"
+"./vec-dealloc.html" = "./vec/vec-dealloc.html"
+"./vec-deref.html" = "./vec/vec-deref.html"
+"./vec-drain.html" = "./vec/vec-drain.html"
+"./vec-final.html" = "./vec/vec-final.html"
+"./vec-insert-remove.html" = "./vec/vec-insert-remove.html"
+"./vec-into-iter.html" = "./vec/vec-into-iter.html"
+"./vec-layout.html" = "./vec/vec-layout.html"
+"./vec-push-pop.html" = "./vec/vec-push-pop.html"
+"./vec-raw.html" = "./vec/vec-raw.html"
+"./vec-zsts.html" = "./vec/vec-zsts.html"
+"./vec.html" = "./vec/vec.html"
+
+# Arc and Mutex related chapters.
+"./arc-and-mutex.html" = "./arc-mutex/arc-and-mutex.html"
+"./arc-base.html" = "./arc-mutex/arc-base.html"
+"./arc-clone.html" = "./arc-mutex/arc-clone.html"
+"./arc-drop.html" = "./arc-mutex/arc-drop.html"
+"./arc-final.html" = "./arc-mutex/arc-final.html"
+"./arc-layout.html" = "./arc-mutex/arc-layout.html"
+"./arc.html" = "./arc-mutex/arc.html"
+
+[rust]
+edition = "2018"
diff --git a/src/doc/nomicon/src/README.md b/src/doc/nomicon/src/README.md
deleted file mode 100644 (file)
index cc50b5f..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-# The Rustonomicon
-
-#### The Dark Arts of Unsafe Rust
-
-> THE KNOWLEDGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF UNLEASHING INDESCRIBABLE HORRORS THAT
-SHATTER YOUR PSYCHE AND SET YOUR MIND ADRIFT IN THE UNKNOWABLY INFINITE COSMOS.
-
-The Rustonomicon digs into all the awful details that you need to understand when
-writing Unsafe Rust programs.
-
-Should you wish a long and happy career of writing Rust programs, you should
-turn back now and forget you ever saw this book. It is not necessary. However
-if you intend to write unsafe code — or just want to dig into the guts of the
-language — this book contains lots of useful information.
-
-Unlike *[The Rust Programming Language][trpl]*, we will be assuming considerable
-prior knowledge. In particular, you should be comfortable with basic systems
-programming and Rust. If you don't feel comfortable with these topics, you
-should consider reading [The Book][trpl] first. That said, we won't assume you
-have read it, and we will take care to occasionally give a refresher on the
-basics where appropriate. You can skip straight to this book if you want;
-just know that we won't be explaining everything from the ground up.
-
-This book exists primarily as a high-level companion to [The Reference][ref].
-Where The Reference exists to detail the syntax and semantics of every part of
-the language, The Rustonomicon exists to describe how to use those pieces together,
-and the issues that you will have in doing so.
-
-The Reference will tell you the syntax and semantics of references, destructors, and
-unwinding, but it won't tell you how combining them can lead to exception-safety
-issues, or how to deal with those issues.
-
-It should be noted that when The Rustonomicon was originally written, The
-Reference was in a state of complete disrepair, and so many things that should
-have been covered by The Reference were originally only documented here. Since
-then, The Reference has been revitalized and is properly maintained, although
-it is still far from complete. In general, if the two documents disagree, The
-Reference should be assumed to be correct (it isn't yet considered normative,
-it's just better maintained).
-
-Topics that are within the scope of this book include: the meaning of (un)safety,
-unsafe primitives provided by the language and standard library, techniques for
-creating safe abstractions with those unsafe primitives, subtyping and variance,
-exception-safety (panic/unwind-safety), working with uninitialized memory,
-type punning, concurrency, interoperating with other languages (FFI),
-optimization tricks, how constructs lower to compiler/OS/hardware primitives,
-how to **not** make the memory model people angry, how you're **going** to make the
-memory model people angry, and more.
-
-The Rustonomicon is not a place to exhaustively describe the semantics and guarantees
-of every single API in the standard library, nor is it a place to exhaustively describe
-every feature of Rust.
-
-[trpl]: ../book/index.html
-[ref]: ../reference/index.html
index fbd9cc0b5db6381088555ccb9d1e0a615dea80c9..f1d15a71dd835212ee2a55e20b1a05a8a677db2d 100644 (file)
@@ -1,66 +1,66 @@
 # Summary
 
-[Introduction](README.md)
+[Introduction](intro.md)
 
 * [Meet Safe and Unsafe](meet-safe-and-unsafe.md)
-    * [How Safe and Unsafe Interact](safe-unsafe-meaning.md)
-    * [What Unsafe Can Do](what-unsafe-does.md)
-    * [Working with Unsafe](working-with-unsafe.md)
+  * [How Safe and Unsafe Interact](safe-unsafe-meaning.md)
+  * [What Unsafe Can Do](what-unsafe-does.md)
+  * [Working with Unsafe](working-with-unsafe.md)
 * [Data Layout](data.md)
-    * [repr(Rust)](repr-rust.md)
-    * [Exotically Sized Types](exotic-sizes.md)
-    * [Other reprs](other-reprs.md)
+  * [repr(Rust)](repr-rust.md)
+  * [Exotically Sized Types](exotic-sizes.md)
+  * [Other reprs](other-reprs.md)
 * [Ownership](ownership.md)
-    * [References](references.md)
-    * [Aliasing](aliasing.md)
-    * [Lifetimes](lifetimes.md)
-    * [Limits of Lifetimes](lifetime-mismatch.md)
-    * [Lifetime Elision](lifetime-elision.md)
-    * [Unbounded Lifetimes](unbounded-lifetimes.md)
-    * [Higher-Rank Trait Bounds](hrtb.md)
-    * [Subtyping and Variance](subtyping.md)
-    * [Drop Check](dropck.md)
-    * [PhantomData](phantom-data.md)
-    * [Splitting Borrows](borrow-splitting.md)
+  * [References](references.md)
+  * [Aliasing](aliasing.md)
+  * [Lifetimes](lifetimes.md)
+  * [Limits of Lifetimes](lifetime-mismatch.md)
+  * [Lifetime Elision](lifetime-elision.md)
+  * [Unbounded Lifetimes](unbounded-lifetimes.md)
+  * [Higher-Rank Trait Bounds](hrtb.md)
+  * [Subtyping and Variance](subtyping.md)
+  * [Drop Check](dropck.md)
+  * [PhantomData](phantom-data.md)
+  * [Splitting Borrows](borrow-splitting.md)
 * [Type Conversions](conversions.md)
-    * [Coercions](coercions.md)
-    * [The Dot Operator](dot-operator.md)
-    * [Casts](casts.md)
-    * [Transmutes](transmutes.md)
+  * [Coercions](coercions.md)
+  * [The Dot Operator](dot-operator.md)
+  * [Casts](casts.md)
+  * [Transmutes](transmutes.md)
 * [Uninitialized Memory](uninitialized.md)
-    * [Checked](checked-uninit.md)
-    * [Drop Flags](drop-flags.md)
-    * [Unchecked](unchecked-uninit.md)
+  * [Checked](checked-uninit.md)
+  * [Drop Flags](drop-flags.md)
+  * [Unchecked](unchecked-uninit.md)
 * [Ownership Based Resource Management](obrm.md)
-    * [Constructors](constructors.md)
-    * [Destructors](destructors.md)
-    * [Leaking](leaking.md)
+  * [Constructors](constructors.md)
+  * [Destructors](destructors.md)
+  * [Leaking](leaking.md)
 * [Unwinding](unwinding.md)
-    * [Exception Safety](exception-safety.md)
-    * [Poisoning](poisoning.md)
+  * [Exception Safety](exception-safety.md)
+  * [Poisoning](poisoning.md)
 * [Concurrency](concurrency.md)
-    * [Races](races.md)
-    * [Send and Sync](send-and-sync.md)
-    * [Atomics](atomics.md)
-* [Implementing Vec](vec.md)
-    * [Layout](vec-layout.md)
-    * [Allocating](vec-alloc.md)
-    * [Push and Pop](vec-push-pop.md)
-    * [Deallocating](vec-dealloc.md)
-    * [Deref](vec-deref.md)
-    * [Insert and Remove](vec-insert-remove.md)
-    * [IntoIter](vec-into-iter.md)
-    * [RawVec](vec-raw.md)
-    * [Drain](vec-drain.md)
-    * [Handling Zero-Sized Types](vec-zsts.md)
-    * [Final Code](vec-final.md)
-* [Implementing Arc and Mutex](arc-and-mutex.md)
-    * [Arc](arc.md)
-      * [Layout](arc-layout.md)
-      * [Base Code](arc-base.md)
-      * [Cloning](arc-clone.md)
-      * [Dropping](arc-drop.md)
-      * [Final Code](arc-final.md)
+  * [Races](races.md)
+  * [Send and Sync](send-and-sync.md)
+  * [Atomics](atomics.md)
+* [Implementing Vec](./vec/vec.md)
+  * [Layout](./vec/vec-layout.md)
+  * [Allocating](./vec/vec-alloc.md)
+  * [Push and Pop](./vec/vec-push-pop.md)
+  * [Deallocating](./vec/vec-dealloc.md)
+  * [Deref](./vec/vec-deref.md)
+  * [Insert and Remove](./vec/vec-insert-remove.md)
+  * [IntoIter](./vec/vec-into-iter.md)
+  * [RawVec](./vec/vec-raw.md)
+  * [Drain](./vec/vec-drain.md)
+  * [Handling Zero-Sized Types](./vec/vec-zsts.md)
+  * [Final Code](./vec/vec-final.md)
+* [Implementing Arc and Mutex](./arc-mutex/arc-and-mutex.md)
+  * [Arc](./arc-mutex/arc.md)
+    * [Layout](./arc-mutex/arc-layout.md)
+    * [Base Code](./arc-mutex/arc-base.md)
+    * [Cloning](./arc-mutex/arc-clone.md)
+    * [Dropping](./arc-mutex/arc-drop.md)
+    * [Final Code](./arc-mutex/arc-final.md)
 * [FFI](ffi.md)
 * [Beneath `std`](beneath-std.md)
-    * [#[panic_handler]](panic-handler.md)
+  * [#[panic_handler]](panic-handler.md)
index ebdec9ab216c8195b7cb5a97a4226ef0f204a6a0..993afbaa6320d0040680178208c465be9a029826 100644 (file)
@@ -14,10 +14,7 @@ don't happen unless you tell it otherwise. For more details, see the
 With that said, here's our working definition: variables and pointers *alias*
 if they refer to overlapping regions of memory.
 
-
-
-
-# Why Aliasing Matters
+## Why Aliasing Matters
 
 So why should we care about aliasing?
 
@@ -31,6 +28,7 @@ fn compute(input: &u32, output: &mut u32) {
     if *input > 5 {
         *output *= 2;
     }
+    // remember that `output` will be `2` if `input > 10`
 }
 ```
 
@@ -38,9 +36,12 @@ We would *like* to be able to optimize it to the following function:
 
 ```rust
 fn compute(input: &u32, output: &mut u32) {
-    let cached_input = *input; // keep *input in a register
+    let cached_input = *input; // keep `*input` in a register
     if cached_input > 10 {
-        *output = 2;  // x > 10 implies x > 5, so double and exit immediately
+        // If the input is greater than 10, the previous code would set the output to 1 and then double it,
+        // resulting in an output of 2 (because `>10` implies `>5`).
+        // Here, we avoid the double assignment and just set it directly to 2.
+        *output = 2;
     } else if cached_input > 5 {
         *output *= 2;
     }
@@ -55,6 +56,7 @@ and `output` overlap, such as `compute(&x, &mut x)`.
 
 With that input, we could get this execution:
 
+<!-- ignore: expanded code -->
 ```rust,ignore
                     //  input ==  output == 0xabad1dea
                     // *input == *output == 20
@@ -130,6 +132,3 @@ Of course, a full aliasing model for Rust must also take into consideration thin
 function calls (which may mutate things we don't see), raw pointers (which have
 no aliasing requirements on their own), and UnsafeCell (which lets the referent
 of an `&` be mutated).
-
-
-
diff --git a/src/doc/nomicon/src/arc-and-mutex.md b/src/doc/nomicon/src/arc-and-mutex.md
deleted file mode 100644 (file)
index f6c1583..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# Implementing Arc and Mutex
-
-Knowing the theory is all fine and good, but the *best* way to understand
-something is to use it. To better understand atomics and interior mutability,
-we'll be implementing versions of the standard library's Arc and Mutex types.
-
-TODO: Mutex
diff --git a/src/doc/nomicon/src/arc-base.md b/src/doc/nomicon/src/arc-base.md
deleted file mode 100644 (file)
index 7dd6bae..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-# Base Code
-
-Now that we've decided the layout for our implementation of `Arc`, let's create
-some basic code.
-
-## Constructing the Arc
-
-We'll first need a way to construct an `Arc<T>`.
-
-This is pretty simple, as we just need to box the `ArcInner<T>` and get a
-`NonNull<T>` pointer to it.
-
-```rust,ignore
-impl<T> Arc<T> {
-    pub fn new(data: T) -> Arc<T> {
-        // We start the reference count at 1, as that first reference is the
-        // current pointer.
-        let boxed = Box::new(ArcInner {
-            rc: AtomicUsize::new(1),
-            data,
-        });
-        Arc {
-            // It is okay to call `.unwrap()` here as we get a pointer from
-            // `Box::into_raw` which is guaranteed to not be null.
-            ptr: NonNull::new(Box::into_raw(boxed)).unwrap(),
-            phantom: PhantomData,
-        }
-    }
-}
-```
-
-## Send and Sync
-
-Since we're building a concurrency primitive, we'll need to be able to send it
-across threads. Thus, we can implement the `Send` and `Sync` marker traits. For
-more information on these, see [the section on `Send` and
-`Sync`](send-and-sync.md).
-
-This is okay because:
-* You can only get a mutable reference to the value inside an `Arc` if and only
-  if it is the only `Arc` referencing that data (which only happens in `Drop`)
-* We use atomics for the shared mutable reference counting
-
-```rust,ignore
-unsafe impl<T: Sync + Send> Send for Arc<T> {}
-unsafe impl<T: Sync + Send> Sync for Arc<T> {}
-```
-
-We need to have the bound `T: Sync + Send` because if we did not provide those
-bounds, it would be possible to share values that are thread-unsafe across a
-thread boundary via an `Arc`, which could possibly cause data races or
-unsoundness.
-
-For example, if those bounds were not present, `Arc<Rc<u32>>` would be `Sync` or
-`Send`, meaning that you could clone the `Rc` out of the `Arc` to send it across
-a thread (without creating an entirely new `Rc`), which would create data races
-as `Rc` is not thread-safe.
-
-## Getting the `ArcInner`
-
-To dereference the `NonNull<T>` pointer into a `&T`, we can call
-`NonNull::as_ref`. This is unsafe, unlike the typical `as_ref` function, so we
-must call it like this:
-```rust,ignore
-unsafe { self.ptr.as_ref() }
-```
-
-We'll be using this snippet a few times in this code (usually with an associated
-`let` binding).
-
-This unsafety is okay because while this `Arc` is alive, we're guaranteed that
-the inner pointer is valid.
-
-## Deref
-
-Alright. Now we can make `Arc`s (and soon will be able to clone and destroy them correctly), but how do we get
-to the data inside?
-
-What we need now is an implementation of `Deref`.
-
-We'll need to import the trait:
-```rust,ignore
-use std::ops::Deref;
-```
-
-And here's the implementation:
-```rust,ignore
-impl<T> Deref for Arc<T> {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        let inner = unsafe { self.ptr.as_ref() };
-        &inner.data
-    }
-}
-```
-
-Pretty simple, eh? This simply dereferences the `NonNull` pointer to the
-`ArcInner<T>`, then gets a reference to the data inside.
-
-## Code
-
-Here's all the code from this section:
-```rust,ignore
-use std::ops::Deref;
-
-impl<T> Arc<T> {
-    pub fn new(data: T) -> Arc<T> {
-        // We start the reference count at 1, as that first reference is the
-        // current pointer.
-        let boxed = Box::new(ArcInner {
-            rc: AtomicUsize::new(1),
-            data,
-        });
-        Arc {
-            // It is okay to call `.unwrap()` here as we get a pointer from
-            // `Box::into_raw` which is guaranteed to not be null.
-            ptr: NonNull::new(Box::into_raw(boxed)).unwrap(),
-            phantom: PhantomData,
-        }
-    }
-}
-
-unsafe impl<T: Sync + Send> Send for Arc<T> {}
-unsafe impl<T: Sync + Send> Sync for Arc<T> {}
-
-
-impl<T> Deref for Arc<T> {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        let inner = unsafe { self.ptr.as_ref() };
-        &inner.data
-    }
-}
-```
diff --git a/src/doc/nomicon/src/arc-clone.md b/src/doc/nomicon/src/arc-clone.md
deleted file mode 100644 (file)
index ad98800..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-# Cloning
-
-Now that we've got some basic code set up, we'll need a way to clone the `Arc`.
-
-Basically, we need to:
-1. Increment the atomic reference count
-2. Construct a new instance of the `Arc` from the inner pointer
-
-First, we need to get access to the `ArcInner`:
-```rust,ignore
-let inner = unsafe { self.ptr.as_ref() };
-```
-
-We can update the atomic reference count as follows:
-```rust,ignore
-let old_rc = inner.rc.fetch_add(1, Ordering::???);
-```
-
-But what ordering should we use here? We don't really have any code that will
-need atomic synchronization when cloning, as we do not modify the internal value
-while cloning. Thus, we can use a Relaxed ordering here, which implies no
-happens-before relationship but is atomic. When `Drop`ping the Arc, however,
-we'll need to atomically synchronize when decrementing the reference count. This
-is described more in [the section on the `Drop` implementation for
-`Arc`](arc-drop.md). For more information on atomic relationships and Relaxed
-ordering, see [the section on atomics](atomics.md).
-
-Thus, the code becomes this:
-```rust,ignore
-let old_rc = inner.rc.fetch_add(1, Ordering::Relaxed);
-```
-
-We'll need to add another import to use `Ordering`:
-```rust,ignore
-use std::sync::atomic::Ordering;
-```
-
-However, we have one problem with this implementation right now. What if someone
-decides to `mem::forget` a bunch of Arcs? The code we have written so far (and
-will write) assumes that the reference count accurately portrays how many Arcs
-are in memory, but with `mem::forget` this is false. Thus, when more and more
-Arcs are cloned from this one without them being `Drop`ped and the reference
-count being decremented, we can overflow! This will cause use-after-free which
-is **INCREDIBLY BAD!**
-
-To handle this, we need to check that the reference count does not go over some
-arbitrary value (below `usize::MAX`, as we're storing the reference count as an
-`AtomicUsize`), and do *something*.
-
-The standard library's implementation decides to just abort the program (as it
-is an incredibly unlikely case in normal code and if it happens, the program is
-probably incredibly degenerate) if the reference count reaches `isize::MAX`
-(about half of `usize::MAX`) on any thread, on the assumption that there are
-probably not about 2 billion threads (or about **9 quintillion** on some 64-bit
-machines) incrementing the reference count at once. This is what we'll do.
-
-It's pretty simple to implement this behaviour:
-```rust,ignore
-if old_rc >= isize::MAX as usize {
-    std::process::abort();
-}
-```
-
-Then, we need to return a new instance of the `Arc`:
-```rust,ignore
-Self {
-    ptr: self.ptr,
-    phantom: PhantomData
-}
-```
-
-Now, let's wrap this all up inside the `Clone` implementation:
-```rust,ignore
-use std::sync::atomic::Ordering;
-
-impl<T> Clone for Arc<T> {
-    fn clone(&self) -> Arc<T> {
-        let inner = unsafe { self.ptr.as_ref() };
-        // Using a relaxed ordering is alright here as we don't need any atomic
-        // synchronization here as we're not modifying or accessing the inner
-        // data.
-        let old_rc = inner.rc.fetch_add(1, Ordering::Relaxed);
-
-        if old_rc >= isize::MAX as usize {
-            std::process::abort();
-        }
-
-        Self {
-            ptr: self.ptr,
-            phantom: PhantomData,
-        }
-    }
-}
-```
diff --git a/src/doc/nomicon/src/arc-drop.md b/src/doc/nomicon/src/arc-drop.md
deleted file mode 100644 (file)
index 0b3cfe5..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-# Dropping
-
-We now need a way to decrease the reference count and drop the data once it is
-low enough, otherwise the data will live forever on the heap.
-
-To do this, we can implement `Drop`.
-
-Basically, we need to:
-1. Decrement the reference count
-2. If there is only one reference remaining to the data, then:
-3. Atomically fence the data to prevent reordering of the use and deletion of
-   the data
-4. Drop the inner data 
-
-First, we'll need to get access to the `ArcInner`:
-```rust,ignore
-let inner = unsafe { self.ptr.as_ref() };
-```
-
-Now, we need to decrement the reference count. To streamline our code, we can
-also return if the returned value from `fetch_sub` (the value of the reference
-count before decrementing it) is not equal to `1` (which happens when we are not
-the last reference to the data).
-```rust,ignore
-if inner.rc.fetch_sub(1, Ordering::Relaxed) != 1 {
-    return;
-}
-```
-
-We then need to create an atomic fence to prevent reordering of the use of the
-data and deletion of the data. As described in [the standard library's
-implementation of `Arc`][3]:
-> This fence is needed to prevent reordering of use of the data and deletion of
-> the data. Because it is marked `Release`, the decreasing of the reference
-> count synchronizes with this `Acquire` fence. This means that use of the data
-> happens before decreasing the reference count, which happens before this
-> fence, which happens before the deletion of the data.
->
-> As explained in the [Boost documentation][1],
->
-> > It is important to enforce any possible access to the object in one
-> > thread (through an existing reference) to *happen before* deleting
-> > the object in a different thread. This is achieved by a "release"
-> > operation after dropping a reference (any access to the object
-> > through this reference must obviously happened before), and an
-> > "acquire" operation before deleting the object.
->
-> In particular, while the contents of an Arc are usually immutable, it's
-> possible to have interior writes to something like a Mutex<T>. Since a Mutex
-> is not acquired when it is deleted, we can't rely on its synchronization logic
-> to make writes in thread A visible to a destructor running in thread B.
->
-> Also note that the Acquire fence here could probably be replaced with an
-> Acquire load, which could improve performance in highly-contended situations.
-> See [2].
-> 
-> [1]: https://www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html
-> [2]: https://github.com/rust-lang/rust/pull/41714
-[3]: https://github.com/rust-lang/rust/blob/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/alloc/src/sync.rs#L1440-L1467
-
-To do this, we do the following:
-```rust,ignore
-atomic::fence(Ordering::Acquire);
-```
-
-We'll need to import `std::sync::atomic` itself:
-```rust,ignore
-use std::sync::atomic;
-```
-
-Finally, we can drop the data itself. We use `Box::from_raw` to drop the boxed
-`ArcInner<T>` and its data. This takes a `*mut T` and not a `NonNull<T>`, so we
-must convert using `NonNull::as_ptr`.
-
-```rust,ignore
-unsafe { Box::from_raw(self.ptr.as_ptr()); }
-```
-
-This is safe as we know we have the last pointer to the `ArcInner` and that its
-pointer is valid.
-
-Now, let's wrap this all up inside the `Drop` implementation:
-```rust,ignore
-impl<T> Drop for Arc<T> {
-    fn drop(&mut self) {
-        let inner = unsafe { self.ptr.as_ref() };
-        if inner.rc.fetch_sub(1, Ordering::Release) != 1 {
-            return;
-        }
-        // This fence is needed to prevent reordering of the use and deletion
-        // of the data.
-        atomic::fence(Ordering::Acquire);
-        // This is safe as we know we have the last pointer to the `ArcInner`
-        // and that its pointer is valid.
-        unsafe { Box::from_raw(self.ptr.as_ptr()); }
-    }
-}
-```
diff --git a/src/doc/nomicon/src/arc-final.md b/src/doc/nomicon/src/arc-final.md
deleted file mode 100644 (file)
index 4fcc274..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-# Final Code
-
-Here's the final code, with some added comments and re-ordered imports:
-```rust
-use std::marker::PhantomData;
-use std::ops::Deref;
-use std::ptr::NonNull;
-use std::sync::atomic::{self, AtomicUsize, Ordering};
-
-pub struct Arc<T> {
-    ptr: NonNull<ArcInner<T>>,
-    phantom: PhantomData<ArcInner<T>>,
-}
-
-pub struct ArcInner<T> {
-    rc: AtomicUsize,
-    data: T,
-}
-
-impl<T> Arc<T> {
-    pub fn new(data: T) -> Arc<T> {
-        // We start the reference count at 1, as that first reference is the
-        // current pointer.
-        let boxed = Box::new(ArcInner {
-            rc: AtomicUsize::new(1),
-            data,
-        });
-        Arc {
-            // It is okay to call `.unwrap()` here as we get a pointer from
-            // `Box::into_raw` which is guaranteed to not be null.
-            ptr: NonNull::new(Box::into_raw(boxed)).unwrap(),
-            phantom: PhantomData,
-        }
-    }
-}
-
-unsafe impl<T: Sync + Send> Send for Arc<T> {}
-unsafe impl<T: Sync + Send> Sync for Arc<T> {}
-
-impl<T> Deref for Arc<T> {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        let inner = unsafe { self.ptr.as_ref() };
-        &inner.data
-    }
-}
-
-impl<T> Clone for Arc<T> {
-    fn clone(&self) -> Arc<T> {
-        let inner = unsafe { self.ptr.as_ref() };
-        // Using a relaxed ordering is alright here as we don't need any atomic
-        // synchronization here as we're not modifying or accessing the inner
-        // data.
-        let old_rc = inner.rc.fetch_add(1, Ordering::Relaxed);
-
-        if old_rc >= isize::MAX as usize {
-            std::process::abort();
-        }
-
-        Self {
-            ptr: self.ptr,
-            phantom: PhantomData,
-        }
-    }
-}
-
-impl<T> Drop for Arc<T> {
-    fn drop(&mut self) {
-        let inner = unsafe { self.ptr.as_ref() };
-        if inner.rc.fetch_sub(1, Ordering::Release) != 1 {
-            return;
-        }
-        // This fence is needed to prevent reordering of the use and deletion
-        // of the data.
-        atomic::fence(Ordering::Acquire);
-        // This is safe as we know we have the last pointer to the `ArcInner`
-        // and that its pointer is valid.
-        unsafe { Box::from_raw(self.ptr.as_ptr()); }
-    }
-}
-```
diff --git a/src/doc/nomicon/src/arc-layout.md b/src/doc/nomicon/src/arc-layout.md
deleted file mode 100644 (file)
index 55d4793..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-# Layout
-
-Let's start by making the layout for our implementation of `Arc`.
-
-An `Arc<T>` provides thread-safe shared ownership of a value of type `T`,
-allocated in the heap. Sharing implies immutability in Rust, so we don't need to
-design anything that manages access to that value, right? Although interior
-mutability types like Mutex allow Arc's users to create shared mutability, Arc
-itself doesn't need to concern itself with these issues.
-
-However there _is_ one place where Arc needs to concern itself with mutation:
-destruction. When all the owners of the Arc go away, we need to be able to
-`drop` its contents and free its allocation. So we need a way for an owner to
-know if it's the _last_ owner, and the simplest way to do that is with a count
-of the owners -- Reference Counting.
-
-Unfortunately, this reference count is inherently shared mutable state, so Arc
-_does_ need to think about synchronization. We _could_ use a Mutex for this, but
-that's overkill. Instead, we'll use atomics. And since everyone already needs a
-pointer to the T's allocation, we might as well put the reference count in that
-same allocation.
-
-Naively, it would look something like this:
-```rust,ignore
-use std::sync::atomic;
-
-pub struct Arc<T> {
-    ptr: *mut ArcInner<T>,
-}
-
-pub struct ArcInner<T> {
-    rc: atomic::AtomicUsize,
-    data: T
-}
-```
-
-This would compile, however it would be incorrect. First of all, the compiler
-will give us too strict variance. For example, an `Arc<&'static str>` couldn't
-be used where an `Arc<&'a str>` was expected. More importantly, it will give
-incorrect ownership information to the drop checker, as it will assume we don't
-own any values of type `T`. As this is a structure providing shared ownership of
-a value, at some point there will be an instance of this structure that entirely
-owns its data. See [the chapter on ownership and lifetimes](ownership.md) for
-all the details on variance and drop check.
-
-To fix the first problem, we can use `NonNull<T>`. Note that `NonNull<T>` is a
-wrapper around a raw pointer that declares that:
-* We are variant over `T`
-* Our pointer is never null
-
-To fix the second problem, we can include a `PhantomData` marker containing an
-`ArcInner<T>`. This will tell the drop checker that we have some notion of
-ownership of a value of `ArcInner<T>` (which itself contains some `T`).
-
-With these changes we get our final structure:
-```rust,ignore
-use std::marker::PhantomData;
-use std::ptr::NonNull;
-use std::sync::atomic::AtomicUsize;
-
-pub struct Arc<T> {
-    ptr: NonNull<ArcInner<T>>,
-    phantom: PhantomData<ArcInner<T>>
-}
-
-pub struct ArcInner<T> {
-    rc: AtomicUsize,
-    data: T
-}
-```
diff --git a/src/doc/nomicon/src/arc-mutex/arc-and-mutex.md b/src/doc/nomicon/src/arc-mutex/arc-and-mutex.md
new file mode 100644 (file)
index 0000000..41a4d7c
--- /dev/null
@@ -0,0 +1,7 @@
+# Implementing Arc and Mutex
+
+Knowing the theory is all fine and good, but the *best* way to understand
+something is to use it. To better understand atomics and interior mutability,
+we'll be implementing versions of the standard library's `Arc` and `Mutex` types.
+
+TODO: Write `Mutex` chapters.
diff --git a/src/doc/nomicon/src/arc-mutex/arc-base.md b/src/doc/nomicon/src/arc-mutex/arc-base.md
new file mode 100644 (file)
index 0000000..ee35d86
--- /dev/null
@@ -0,0 +1,146 @@
+# Base Code
+
+Now that we've decided the layout for our implementation of `Arc`, let's create
+some basic code.
+
+## Constructing the Arc
+
+We'll first need a way to construct an `Arc<T>`.
+
+This is pretty simple, as we just need to box the `ArcInner<T>` and get a
+`NonNull<T>` pointer to it.
+
+<!-- ignore: simplified code -->
+```rust,ignore
+impl<T> Arc<T> {
+    pub fn new(data: T) -> Arc<T> {
+        // We start the reference count at 1, as that first reference is the
+        // current pointer.
+        let boxed = Box::new(ArcInner {
+            rc: AtomicUsize::new(1),
+            data,
+        });
+        Arc {
+            // It is okay to call `.unwrap()` here as we get a pointer from
+            // `Box::into_raw` which is guaranteed to not be null.
+            ptr: NonNull::new(Box::into_raw(boxed)).unwrap(),
+            phantom: PhantomData,
+        }
+    }
+}
+```
+
+## Send and Sync
+
+Since we're building a concurrency primitive, we'll need to be able to send it
+across threads. Thus, we can implement the `Send` and `Sync` marker traits. For
+more information on these, see [the section on `Send` and
+`Sync`](../send-and-sync.md).
+
+This is okay because:
+* You can only get a mutable reference to the value inside an `Arc` if and only
+  if it is the only `Arc` referencing that data (which only happens in `Drop`)
+* We use atomics for the shared mutable reference counting
+
+<!-- ignore: simplified code -->
+```rust,ignore
+unsafe impl<T: Sync + Send> Send for Arc<T> {}
+unsafe impl<T: Sync + Send> Sync for Arc<T> {}
+```
+
+We need to have the bound `T: Sync + Send` because if we did not provide those
+bounds, it would be possible to share values that are thread-unsafe across a
+thread boundary via an `Arc`, which could possibly cause data races or
+unsoundness.
+
+For example, if those bounds were not present, `Arc<Rc<u32>>` would be `Sync` or
+`Send`, meaning that you could clone the `Rc` out of the `Arc` to send it across
+a thread (without creating an entirely new `Rc`), which would create data races
+as `Rc` is not thread-safe.
+
+## Getting the `ArcInner`
+
+To dereference the `NonNull<T>` pointer into a `&T`, we can call
+`NonNull::as_ref`. This is unsafe, unlike the typical `as_ref` function, so we
+must call it like this:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+unsafe { self.ptr.as_ref() }
+```
+
+We'll be using this snippet a few times in this code (usually with an associated
+`let` binding).
+
+This unsafety is okay because while this `Arc` is alive, we're guaranteed that
+the inner pointer is valid.
+
+## Deref
+
+Alright. Now we can make `Arc`s (and soon will be able to clone and destroy them correctly), but how do we get
+to the data inside?
+
+What we need now is an implementation of `Deref`.
+
+We'll need to import the trait:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+use std::ops::Deref;
+```
+
+And here's the implementation:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+impl<T> Deref for Arc<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        let inner = unsafe { self.ptr.as_ref() };
+        &inner.data
+    }
+}
+```
+
+Pretty simple, eh? This simply dereferences the `NonNull` pointer to the
+`ArcInner<T>`, then gets a reference to the data inside.
+
+## Code
+
+Here's all the code from this section:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+use std::ops::Deref;
+
+impl<T> Arc<T> {
+    pub fn new(data: T) -> Arc<T> {
+        // We start the reference count at 1, as that first reference is the
+        // current pointer.
+        let boxed = Box::new(ArcInner {
+            rc: AtomicUsize::new(1),
+            data,
+        });
+        Arc {
+            // It is okay to call `.unwrap()` here as we get a pointer from
+            // `Box::into_raw` which is guaranteed to not be null.
+            ptr: NonNull::new(Box::into_raw(boxed)).unwrap(),
+            phantom: PhantomData,
+        }
+    }
+}
+
+unsafe impl<T: Sync + Send> Send for Arc<T> {}
+unsafe impl<T: Sync + Send> Sync for Arc<T> {}
+
+
+impl<T> Deref for Arc<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        let inner = unsafe { self.ptr.as_ref() };
+        &inner.data
+    }
+}
+```
diff --git a/src/doc/nomicon/src/arc-mutex/arc-clone.md b/src/doc/nomicon/src/arc-mutex/arc-clone.md
new file mode 100644 (file)
index 0000000..1adc6c9
--- /dev/null
@@ -0,0 +1,108 @@
+# Cloning
+
+Now that we've got some basic code set up, we'll need a way to clone the `Arc`.
+
+Basically, we need to:
+
+1. Increment the atomic reference count
+2. Construct a new instance of the `Arc` from the inner pointer
+
+First, we need to get access to the `ArcInner`:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+let inner = unsafe { self.ptr.as_ref() };
+```
+
+We can update the atomic reference count as follows:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+let old_rc = inner.rc.fetch_add(1, Ordering::???);
+```
+
+But what ordering should we use here? We don't really have any code that will
+need atomic synchronization when cloning, as we do not modify the internal value
+while cloning. Thus, we can use a Relaxed ordering here, which implies no
+happens-before relationship but is atomic. When `Drop`ping the Arc, however,
+we'll need to atomically synchronize when decrementing the reference count. This
+is described more in [the section on the `Drop` implementation for
+`Arc`](arc-drop.md). For more information on atomic relationships and Relaxed
+ordering, see [the section on atomics](../atomics.md).
+
+Thus, the code becomes this:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+let old_rc = inner.rc.fetch_add(1, Ordering::Relaxed);
+```
+
+We'll need to add another import to use `Ordering`:
+
+```rust
+use std::sync::atomic::Ordering;
+```
+
+However, we have one problem with this implementation right now. What if someone
+decides to `mem::forget` a bunch of Arcs? The code we have written so far (and
+will write) assumes that the reference count accurately portrays how many Arcs
+are in memory, but with `mem::forget` this is false. Thus, when more and more
+Arcs are cloned from this one without them being `Drop`ped and the reference
+count being decremented, we can overflow! This will cause use-after-free which
+is **INCREDIBLY BAD!**
+
+To handle this, we need to check that the reference count does not go over some
+arbitrary value (below `usize::MAX`, as we're storing the reference count as an
+`AtomicUsize`), and do *something*.
+
+The standard library's implementation decides to just abort the program (as it
+is an incredibly unlikely case in normal code and if it happens, the program is
+probably incredibly degenerate) if the reference count reaches `isize::MAX`
+(about half of `usize::MAX`) on any thread, on the assumption that there are
+probably not about 2 billion threads (or about **9 quintillion** on some 64-bit
+machines) incrementing the reference count at once. This is what we'll do.
+
+It's pretty simple to implement this behavior:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+if old_rc >= isize::MAX as usize {
+    std::process::abort();
+}
+```
+
+Then, we need to return a new instance of the `Arc`:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+Self {
+    ptr: self.ptr,
+    phantom: PhantomData
+}
+```
+
+Now, let's wrap this all up inside the `Clone` implementation:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+use std::sync::atomic::Ordering;
+
+impl<T> Clone for Arc<T> {
+    fn clone(&self) -> Arc<T> {
+        let inner = unsafe { self.ptr.as_ref() };
+        // Using a relaxed ordering is alright here as we don't need any atomic
+        // synchronization here as we're not modifying or accessing the inner
+        // data.
+        let old_rc = inner.rc.fetch_add(1, Ordering::Relaxed);
+
+        if old_rc >= isize::MAX as usize {
+            std::process::abort();
+        }
+
+        Self {
+            ptr: self.ptr,
+            phantom: PhantomData,
+        }
+    }
+}
+```
diff --git a/src/doc/nomicon/src/arc-mutex/arc-drop.md b/src/doc/nomicon/src/arc-mutex/arc-drop.md
new file mode 100644 (file)
index 0000000..4ed371f
--- /dev/null
@@ -0,0 +1,104 @@
+# Dropping
+
+We now need a way to decrease the reference count and drop the data once it is
+low enough, otherwise the data will live forever on the heap.
+
+To do this, we can implement `Drop`.
+
+Basically, we need to:
+
+1. Decrement the reference count
+2. If there is only one reference remaining to the data, then:
+3. Atomically fence the data to prevent reordering of the use and deletion of
+   the data
+4. Drop the inner data
+
+First, we'll need to get access to the `ArcInner`:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+let inner = unsafe { self.ptr.as_ref() };
+```
+
+Now, we need to decrement the reference count. To streamline our code, we can
+also return if the returned value from `fetch_sub` (the value of the reference
+count before decrementing it) is not equal to `1` (which happens when we are not
+the last reference to the data).
+
+<!-- ignore: simplified code -->
+```rust,ignore
+if inner.rc.fetch_sub(1, Ordering::Relaxed) != 1 {
+    return;
+}
+```
+
+We then need to create an atomic fence to prevent reordering of the use of the
+data and deletion of the data. As described in [the standard library's
+implementation of `Arc`][3]:
+> This fence is needed to prevent reordering of use of the data and deletion of
+> the data. Because it is marked `Release`, the decreasing of the reference
+> count synchronizes with this `Acquire` fence. This means that use of the data
+> happens before decreasing the reference count, which happens before this
+> fence, which happens before the deletion of the data.
+>
+> As explained in the [Boost documentation][1],
+>
+> > It is important to enforce any possible access to the object in one
+> > thread (through an existing reference) to *happen before* deleting
+> > the object in a different thread. This is achieved by a "release"
+> > operation after dropping a reference (any access to the object
+> > through this reference must obviously happened before), and an
+> > "acquire" operation before deleting the object.
+>
+> In particular, while the contents of an Arc are usually immutable, it's
+> possible to have interior writes to something like a Mutex<T>. Since a Mutex
+> is not acquired when it is deleted, we can't rely on its synchronization logic
+> to make writes in thread A visible to a destructor running in thread B.
+>
+> Also note that the Acquire fence here could probably be replaced with an
+> Acquire load, which could improve performance in highly-contended situations.
+> See [2].
+>
+> [1]: https://www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html
+> [2]: https://github.com/rust-lang/rust/pull/41714
+[3]: https://github.com/rust-lang/rust/blob/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/alloc/src/sync.rs#L1440-L1467
+
+To do this, we do the following:
+
+```rust
+# use std::sync::atomic::Ordering;
+use std::sync::atomic;
+atomic::fence(Ordering::Acquire);
+```
+
+Finally, we can drop the data itself. We use `Box::from_raw` to drop the boxed
+`ArcInner<T>` and its data. This takes a `*mut T` and not a `NonNull<T>`, so we
+must convert using `NonNull::as_ptr`.
+
+<!-- ignore: simplified code -->
+```rust,ignore
+unsafe { Box::from_raw(self.ptr.as_ptr()); }
+```
+
+This is safe as we know we have the last pointer to the `ArcInner` and that its
+pointer is valid.
+
+Now, let's wrap this all up inside the `Drop` implementation:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+impl<T> Drop for Arc<T> {
+    fn drop(&mut self) {
+        let inner = unsafe { self.ptr.as_ref() };
+        if inner.rc.fetch_sub(1, Ordering::Release) != 1 {
+            return;
+        }
+        // This fence is needed to prevent reordering of the use and deletion
+        // of the data.
+        atomic::fence(Ordering::Acquire);
+        // This is safe as we know we have the last pointer to the `ArcInner`
+        // and that its pointer is valid.
+        unsafe { Box::from_raw(self.ptr.as_ptr()); }
+    }
+}
+```
diff --git a/src/doc/nomicon/src/arc-mutex/arc-final.md b/src/doc/nomicon/src/arc-mutex/arc-final.md
new file mode 100644 (file)
index 0000000..b9c362d
--- /dev/null
@@ -0,0 +1,83 @@
+# Final Code
+
+Here's the final code, with some added comments and re-ordered imports:
+
+```rust
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::ptr::NonNull;
+use std::sync::atomic::{self, AtomicUsize, Ordering};
+
+pub struct Arc<T> {
+    ptr: NonNull<ArcInner<T>>,
+    phantom: PhantomData<ArcInner<T>>,
+}
+
+pub struct ArcInner<T> {
+    rc: AtomicUsize,
+    data: T,
+}
+
+impl<T> Arc<T> {
+    pub fn new(data: T) -> Arc<T> {
+        // We start the reference count at 1, as that first reference is the
+        // current pointer.
+        let boxed = Box::new(ArcInner {
+            rc: AtomicUsize::new(1),
+            data,
+        });
+        Arc {
+            // It is okay to call `.unwrap()` here as we get a pointer from
+            // `Box::into_raw` which is guaranteed to not be null.
+            ptr: NonNull::new(Box::into_raw(boxed)).unwrap(),
+            phantom: PhantomData,
+        }
+    }
+}
+
+unsafe impl<T: Sync + Send> Send for Arc<T> {}
+unsafe impl<T: Sync + Send> Sync for Arc<T> {}
+
+impl<T> Deref for Arc<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        let inner = unsafe { self.ptr.as_ref() };
+        &inner.data
+    }
+}
+
+impl<T> Clone for Arc<T> {
+    fn clone(&self) -> Arc<T> {
+        let inner = unsafe { self.ptr.as_ref() };
+        // Using a relaxed ordering is alright here as we don't need any atomic
+        // synchronization here as we're not modifying or accessing the inner
+        // data.
+        let old_rc = inner.rc.fetch_add(1, Ordering::Relaxed);
+
+        if old_rc >= isize::MAX as usize {
+            std::process::abort();
+        }
+
+        Self {
+            ptr: self.ptr,
+            phantom: PhantomData,
+        }
+    }
+}
+
+impl<T> Drop for Arc<T> {
+    fn drop(&mut self) {
+        let inner = unsafe { self.ptr.as_ref() };
+        if inner.rc.fetch_sub(1, Ordering::Release) != 1 {
+            return;
+        }
+        // This fence is needed to prevent reordering of the use and deletion
+        // of the data.
+        atomic::fence(Ordering::Acquire);
+        // This is safe as we know we have the last pointer to the `ArcInner`
+        // and that its pointer is valid.
+        unsafe { Box::from_raw(self.ptr.as_ptr()); }
+    }
+}
+```
diff --git a/src/doc/nomicon/src/arc-mutex/arc-layout.md b/src/doc/nomicon/src/arc-mutex/arc-layout.md
new file mode 100644 (file)
index 0000000..3dae2cd
--- /dev/null
@@ -0,0 +1,73 @@
+# Layout
+
+Let's start by making the layout for our implementation of `Arc`.
+
+An `Arc<T>` provides thread-safe shared ownership of a value of type `T`,
+allocated in the heap. Sharing implies immutability in Rust, so we don't need to
+design anything that manages access to that value, right? Although interior
+mutability types like Mutex allow Arc's users to create shared mutability, Arc
+itself doesn't need to concern itself with these issues.
+
+However there _is_ one place where Arc needs to concern itself with mutation:
+destruction. When all the owners of the Arc go away, we need to be able to
+`drop` its contents and free its allocation. So we need a way for an owner to
+know if it's the _last_ owner, and the simplest way to do that is with a count
+of the owners -- Reference Counting.
+
+Unfortunately, this reference count is inherently shared mutable state, so Arc
+_does_ need to think about synchronization. We _could_ use a Mutex for this, but
+that's overkill. Instead, we'll use atomics. And since everyone already needs a
+pointer to the T's allocation, we might as well put the reference count in that
+same allocation.
+
+Naively, it would look something like this:
+
+```rust
+use std::sync::atomic;
+
+pub struct Arc<T> {
+    ptr: *mut ArcInner<T>,
+}
+
+pub struct ArcInner<T> {
+    rc: atomic::AtomicUsize,
+    data: T,
+}
+```
+
+This would compile, however it would be incorrect. First of all, the compiler
+will give us too strict variance. For example, an `Arc<&'static str>` couldn't
+be used where an `Arc<&'a str>` was expected. More importantly, it will give
+incorrect ownership information to the drop checker, as it will assume we don't
+own any values of type `T`. As this is a structure providing shared ownership of
+a value, at some point there will be an instance of this structure that entirely
+owns its data. See [the chapter on ownership and lifetimes](../ownership.md) for
+all the details on variance and drop check.
+
+To fix the first problem, we can use `NonNull<T>`. Note that `NonNull<T>` is a
+wrapper around a raw pointer that declares that:
+
+* We are variant over `T`
+* Our pointer is never null
+
+To fix the second problem, we can include a `PhantomData` marker containing an
+`ArcInner<T>`. This will tell the drop checker that we have some notion of
+ownership of a value of `ArcInner<T>` (which itself contains some `T`).
+
+With these changes we get our final structure:
+
+```rust
+use std::marker::PhantomData;
+use std::ptr::NonNull;
+use std::sync::atomic::AtomicUsize;
+
+pub struct Arc<T> {
+    ptr: NonNull<ArcInner<T>>,
+    phantom: PhantomData<ArcInner<T>>,
+}
+
+pub struct ArcInner<T> {
+    rc: AtomicUsize,
+    data: T,
+}
+```
diff --git a/src/doc/nomicon/src/arc-mutex/arc.md b/src/doc/nomicon/src/arc-mutex/arc.md
new file mode 100644 (file)
index 0000000..fd7800f
--- /dev/null
@@ -0,0 +1,13 @@
+# Implementing Arc
+
+In this section, we'll be implementing a simpler version of `std::sync::Arc`.
+Similarly to [the implementation of `Vec` we made earlier](../vec/vec.md), we won't be
+taking advantage of as many optimizations, intrinsics, or unstable code as the
+standard library may.
+
+This implementation is loosely based on the standard library's implementation
+(technically taken from `alloc::sync` in 1.49, as that's where it's actually
+implemented), but it will not support weak references at the moment as they
+make the implementation slightly more complex.
+
+Please note that this section is very work-in-progress at the moment.
diff --git a/src/doc/nomicon/src/arc.md b/src/doc/nomicon/src/arc.md
deleted file mode 100644 (file)
index 580e662..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# Implementing Arc
-
-In this section, we'll be implementing a simpler version of `std::sync::Arc`.
-Similarly to [the implementation of `Vec` we made earlier](vec.md), we won't be
-taking advantage of as many optimizations, intrinsics, or unstable code as the
-standard library may.
-
-This implementation is loosely based on the standard library's implementation
-(technically taken from `alloc::sync` in 1.49, as that's where it's actually
-implemented), but it will not support weak references at the moment as they
-make the implementation slightly more complex.
-
-Please note that this section is very work-in-progress at the moment.
index 288310747406d2da90ed7deef12bcee6b932ed1d..6aef6aee6d01624b5defa39f382da9bc23ff5a6a 100644 (file)
@@ -22,24 +22,23 @@ semantics we want, the optimizations compilers want, and the inconsistent chaos
 our hardware wants. *We* would like to just write programs and have them do
 exactly what we said but, you know, fast. Wouldn't that be great?
 
-
-
-
-# Compiler Reordering
+## Compiler Reordering
 
 Compilers fundamentally want to be able to do all sorts of complicated
 transformations to reduce data dependencies and eliminate dead code. In
 particular, they may radically change the actual order of events, or make events
-never occur! If we write something like
+never occur! If we write something like:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 x = 1;
 y = 3;
 x = 2;
 ```
 
-The compiler may conclude that it would be best if your program did
+The compiler may conclude that it would be best if your program did:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 x = 2;
 y = 3;
@@ -54,10 +53,7 @@ able to make these kinds of optimizations, because they can seriously improve
 performance. On the other hand, we'd also like to be able to depend on our
 program *doing the thing we said*.
 
-
-
-
-# Hardware Reordering
+## Hardware Reordering
 
 On the other hand, even if the compiler totally understood what we wanted and
 respected our wishes, our hardware might instead get us in trouble. Trouble
@@ -110,11 +106,7 @@ programming:
   incorrect. If possible, concurrent algorithms should be tested on
   weakly-ordered hardware.
 
-
-
-
-
-# Data Accesses
+## Data Accesses
 
 The C++ memory model attempts to bridge the gap by allowing us to talk about the
 *causality* of our program. Generally, this is by establishing a *happens
@@ -156,9 +148,7 @@ propagated to other threads. The set of orderings Rust exposes are:
 TODO: negative reasoning vs positive reasoning? TODO: "can't forget to
 synchronize"
 
-
-
-# Sequentially Consistent
+## Sequentially Consistent
 
 Sequentially Consistent is the most powerful of all, implying the restrictions
 of all other orderings. Intuitively, a sequentially consistent operation
@@ -182,10 +172,7 @@ mechanically trivial to downgrade atomic operations to have a weaker
 consistency later on. Just change `SeqCst` to `Relaxed` and you're done! Of
 course, proving that this transformation is *correct* is a whole other matter.
 
-
-
-
-# Acquire-Release
+## Acquire-Release
 
 Acquire and Release are largely intended to be paired. Their names hint at their
 use case: they're perfectly suited for acquiring and releasing locks, and
@@ -200,8 +187,8 @@ reordered to occur before it.
 When thread A releases a location in memory and then thread B subsequently
 acquires *the same* location in memory, causality is established. Every write
 (including non-atomic and relaxed atomic writes) that happened before A's
-release will be observed by B after its acquisition. However no causality is 
-established with any other threads. Similarly, no causality is established 
+release will be observed by B after its acquisition. However no causality is
+established with any other threads. Similarly, no causality is established
 if A and B access *different* locations in memory.
 
 Basic use of release-acquire is therefore simple: you acquire a location of
@@ -233,10 +220,7 @@ On strongly-ordered platforms most accesses have release or acquire semantics,
 making release and acquire often totally free. This is not the case on
 weakly-ordered platforms.
 
-
-
-
-# Relaxed
+## Relaxed
 
 Relaxed accesses are the absolute weakest. They can be freely re-ordered and
 provide no happens-before relationship. Still, relaxed operations are still
@@ -251,9 +235,5 @@ There's rarely a benefit in making an operation relaxed on strongly-ordered
 platforms, since they usually provide release-acquire semantics anyway. However
 relaxed operations can be cheaper on weakly-ordered platforms.
 
-
-
-
-
 [C11-busted]: http://plv.mpi-sws.org/c11comp/popl15.pdf
 [C++-model]: https://en.cppreference.com/w/cpp/atomic/memory_order
index 2c759f0c194efe68922855dcc3ba98acfe7c4156..6f05182b254b8b00657173c7df73daec590c3a7a 100644 (file)
@@ -4,7 +4,7 @@ This section documents (or will document) features that are provided by the stan
 that `#![no_std]` developers have to deal with (i.e. provide) to build `#![no_std]` binary crates. A
 (likely incomplete) list of such features is shown below:
 
-- #[lang = "eh_personality"]
-- #[lang = "start"]
-- #[lang = "termination"]
-- #[panic_implementation]
+- `#[lang = "eh_personality"]`
+- `#[lang = "start"]`
+- `#[lang = "termination"]`
+- `#[panic_implementation]`
index 014c100c9f58392b7e90986af044191908036e30..e944809cc12fd2e0972271fe4856e2c231f34d9d 100644 (file)
@@ -1,64 +1,34 @@
 # Casts
 
-Casts are a superset of coercions: every coercion can be explicitly
-invoked via a cast. However some conversions require a cast.
-While coercions are pervasive and largely harmless, these "true casts"
-are rare and potentially dangerous. As such, casts must be explicitly invoked
-using the `as` keyword: `expr as Type`.
+Casts are a superset of coercions: every coercion can be explicitly invoked via a cast.
+However some conversions require a cast.
+While coercions are pervasive and largely harmless, these "true casts" are rare and potentially dangerous.
+As such, casts must be explicitly invoked using the `as` keyword: `expr as Type`.
 
-True casts generally revolve around raw pointers and the primitive numeric
-types. Even though they're dangerous, these casts are infallible at runtime.
-If a cast triggers some subtle corner case no indication will be given that
-this occurred. The cast will simply succeed. That said, casts must be valid
-at the type level, or else they will be prevented statically. For instance,
-`7u8 as bool` will not compile.
+You can find an exhaustive list of [all the true casts][cast list] and [casting semantics][semantics list] on the reference.
 
-That said, casts aren't `unsafe` because they generally can't violate memory
-safety *on their own*. For instance, converting an integer to a raw pointer can
-very easily lead to terrible things. However the act of creating the pointer
-itself is safe, because actually using a raw pointer is already marked as
-`unsafe`.
+## Safety of casting
 
-Here's an exhaustive list of all the true casts. For brevity, we will use `*`
-to denote either a `*const` or `*mut`, and `integer` to denote any integral
-primitive:
+True casts generally revolve around raw pointers and the primitive numeric types.
+Even though they're dangerous, these casts are infallible at runtime.
+If a cast triggers some subtle corner case no indication will be given that this occurred.
+The cast will simply succeed.
+That said, casts must be valid at the type level, or else they will be prevented statically.
+For instance, `7u8 as bool` will not compile.
 
- * `*T as *U` where `T, U: Sized`
- * `*T as *U` TODO: explain unsized situation
- * `*T as integer`
- * `integer as *T`
- * `number as number`
- * `field-less enum as integer`
- * `bool as integer`
- * `char as integer`
- * `u8 as char`
- * `&[T; n] as *const T`
- * `fn as *T` where `T: Sized`
- * `fn as integer`
+That said, casts aren't `unsafe` because they generally can't violate memory safety *on their own*.
+For instance, converting an integer to a raw pointer can very easily lead to terrible things.
+However the act of creating the pointer itself is safe, because actually using a raw pointer is already marked as `unsafe`.
 
-Note that lengths are not adjusted when casting raw slices -
-`*const [u16] as *const [u8]` creates a slice that only includes
-half of the original memory.
+## Some notes about casting
 
-Casting is not transitive, that is, even if `e as U1 as U2` is a valid
-expression, `e as U2` is not necessarily so.
+### Lengths when casting raw slices
 
-For numeric casts, there are quite a few cases to consider:
+Note that lengths are not adjusted when casting raw slices; `*const [u16] as *const [u8]` creates a slice that only includes half of the original memory.
 
-* casting between two integers of the same size (e.g. i32 -> u32) is a no-op
-* casting from a larger integer to a smaller integer (e.g. u32 -> u8) will
-  truncate
-* casting from a smaller integer to a larger integer (e.g. u8 -> u32) will
-    * zero-extend if the source is unsigned
-    * sign-extend if the source is signed
-* casting from a float to an integer will round the float towards zero and
-  produces a "saturating cast" when the float is outside the integer's range
-    * floats that are too big turn into the largest possible integer
-    * floats that are too small produce the smallest possible integer
-    * NaN produces zero
-* casting from an integer to float will produce the floating point
-  representation of the integer, rounded if necessary (rounding to
-  nearest, ties to even)
-* casting from an f32 to an f64 is perfect and lossless
-* casting from an f64 to an f32 will produce the closest possible value
-  (rounding to nearest, ties to even)
+### Transitivity
+
+Casting is not transitive, that is, even if `e as U1 as U2` is a valid expression, `e as U2` is not necessarily so.
+
+[cast list]: ../reference/expressions/operator-expr.html#type-cast-expressions
+[semantics list]: ../reference/expressions/operator-expr.html#semantics
index 065a9e1ba27fee7748b68f4c5038a0f083dc3826..ffff83f8ec209ffed9e7ae8a805550dfe3045e36 100644 (file)
@@ -1,58 +1,14 @@
 # Coercions
 
-Types can implicitly be coerced to change in certain contexts. These changes are
-generally just *weakening* of types, largely focused around pointers and
-lifetimes. They mostly exist to make Rust "just work" in more cases, and are
-largely harmless.
+Types can implicitly be coerced to change in certain contexts.
+These changes are generally just *weakening* of types, largely focused around pointers and lifetimes.
+They mostly exist to make Rust "just work" in more cases, and are largely harmless.
 
-Here's all the kinds of coercion:
+For an exhaustive list of all the types of coercions, see the [Coercion types] section on the reference.
 
-Coercion is allowed between the following types:
-
-* Transitivity: `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to
-  `T_3`
-* Pointer Weakening:
-    * `&mut T` to `&T`
-    * `*mut T` to `*const T`
-    * `&T` to `*const T`
-    * `&mut T` to `*mut T`
-* Unsizing: `T` to `U` if `T` implements `CoerceUnsized<U>`
-* Deref coercion: Expression `&x` of type `&T` to `&*x` of type `&U` if `T` derefs to `U` (i.e. `T: Deref<Target=U>`)
-* Non-capturing closure to a function pointer ([RFC 1558], e.g. `|| 8usize` to `fn() -> usize`)
-
-[RFC 1558]: https://rust-lang.github.io/rfcs/1558-closure-to-fn-coercion.html
-
-`CoerceUnsized<Pointer<U>> for Pointer<T> where T: Unsize<U>` is implemented
-for all pointer types (including smart pointers like Box and Rc). Unsize is
-only implemented automatically, and enables the following transformations:
-
-* `[T; n]` => `[T]`
-* `T` => `dyn Trait` where `T: Trait`
-* `Foo<..., T, ...>` => `Foo<..., U, ...>` where:
-    * `T: Unsize<U>`
-    * `Foo` is a struct
-    * Only the last field of `Foo` has type involving `T`
-    * `T` is not part of the type of any other fields
-    * `Bar<T>: Unsize<Bar<U>>`, if the last field of `Foo` has type `Bar<T>`
-
-Coercions occur at a *coercion site*. Any location that is explicitly typed
-will cause a coercion to its type. If inference is necessary, the coercion will
-not be performed. Exhaustively, the coercion sites for an expression `e` to
-type `U` are:
-
-* let statements, statics, and consts: `let x: U = e`
-* Arguments to functions: `takes_a_U(e)`
-* Any expression that will be returned: `fn foo() -> U { e }`
-* Struct literals: `Foo { some_u: e }`
-* Array literals: `let x: [U; 10] = [e, ..]`
-* Tuple literals: `let x: (U, ..) = (e, ..)`
-* The last expression in a block: `let x: U = { ..; e }`
-
-Note that we do not perform coercions when matching traits (except for
-receivers, see below). If there is an impl for some type `U` and `T` coerces to
-`U`, that does not constitute an implementation for `T`. For example, the
-following will not type check, even though it is OK to coerce `t` to `&T` and
-there is an impl for `&T`:
+Note that we do not perform coercions when matching traits (except for receivers, see the [next page][dot-operator]).
+If there is an `impl` for some type `U` and `T` coerces to `U`, that does not constitute an implementation for `T`.
+For example, the following will not type check, even though it is OK to coerce `t` to `&T` and there is an `impl` for `&T`:
 
 ```rust,compile_fail
 trait Trait {}
@@ -67,20 +23,22 @@ fn main() {
 }
 ```
 
+which fails like as follows:
+
 ```text
 error[E0277]: the trait bound `&mut i32: Trait` is not satisfied
- --> src/main.rs:9:5
+ --> src/main.rs:9:9
   |
+3 | fn foo<X: Trait>(t: X) {}
+  |           ----- required by this bound in `foo`
+...
 9 |     foo(t);
-  |     ^^^ the trait `Trait` is not implemented for `&mut i32`
+  |         ^ the trait `Trait` is not implemented for `&mut i32`
   |
   = help: the following implementations were found:
             <&'a i32 as Trait>
-note: required by `foo`
- --> src/main.rs:3:1
-  |
-3 | fn foo<X: Trait>(t: X) {}
-  | ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
+  = note: `Trait` is implemented for `&i32`, but not for `&mut i32`
 ```
+
+[Coercion types]: ../reference/type-coercions.html#coercion-types
+[dot-operator]: ./dot-operator.html
index 388d003d9b6c21d10adb3d9ee1a127c133f1e874..4c29fd8b26f294b6f4f3f9ab1e204ad285ceb039 100644 (file)
@@ -31,4 +31,3 @@ fn reinterpret(foo: Foo) -> Bar {
 
 But this is, at best, annoying. For common conversions, Rust provides
 more ergonomic alternatives.
-
index 524c401f82349f819908a408fba36c0619814a3e..3d999613895890e6340965361ca21af6266f33c5 100644 (file)
@@ -3,6 +3,7 @@
 What the language *does* provide is full-blown automatic destructors through the
 `Drop` trait, which provides the following method:
 
+<!-- ignore: function header -->
 ```rust,ignore
 fn drop(&mut self);
 ```
index 41c5afc3c2628e4ad8c1b651061dc719b7f5a50d..28b65c1d3e951849669de2868eccd2fb29a1a8d0 100644 (file)
@@ -8,11 +8,15 @@ when we talked about `'a: 'b`, it was ok for `'a` to live _exactly_ as long as
 gets dropped at the same time as another, right? This is why we used the
 following desugaring of `let` statements:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 let x;
 let y;
 ```
 
+desugaring to:
+
+<!-- ignore: desugared code -->
 ```rust,ignore
 {
     let x;
@@ -29,6 +33,7 @@ definition. There are some more details about order of drop in [RFC 1857][rfc185
 
 Let's do this:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 let tuple = (vec![], vec![]);
 ```
@@ -203,7 +208,7 @@ of an inspector's destructor might access that borrowed data.
 Therefore, the drop checker forces all borrowed data in a value to
 strictly outlive that value.
 
-# An Escape Hatch
+## An Escape Hatch
 
 The precise rules that govern drop checking may be less restrictive in
 the future.
@@ -259,7 +264,8 @@ lifetime `'b` and that the only uses of `T` will be moves or drops, but omit
 the attribute from `'a` and `U`, because we do access data with that lifetime
 and that type:
 
-```rust,ignore
+```rust
+#![feature(dropck_eyepatch)]
 use std::fmt::Display;
 
 struct Inspector<'a, 'b, T, U: Display>(&'a u8, &'b u8, T, U);
@@ -283,7 +289,7 @@ other avenues for such indirect access.)
 
 Here is an example of invoking a callback:
 
-```rust,ignore
+```rust
 struct Inspector<T>(T, &'static str, Box<for <'r> fn(&'r T) -> String>);
 
 impl<T> Drop for Inspector<T> {
@@ -297,7 +303,7 @@ impl<T> Drop for Inspector<T> {
 
 Here is an example of a trait method call:
 
-```rust,ignore
+```rust
 use std::fmt;
 
 struct Inspector<T: fmt::Display>(T, &'static str);
@@ -318,17 +324,17 @@ directly within it.
 
 In all of the above cases where the `&'a u8` is accessed in the
 destructor, adding the `#[may_dangle]`
-attribute makes the type vulnerable to misuse that the borrower
+attribute makes the type vulnerable to misuse that the borrow
 checker will not catch, inviting havoc. It is better to avoid adding
 the attribute.
 
-# A related side note about drop order
+## A related side note about drop order
 
 While the drop order of fields inside a struct is defined, relying on it is
 fragile and subtle. When the order matters, it is better to use the
 [`ManuallyDrop`] wrapper.
 
-# Is that all about drop checker?
+## Is that all about drop checker?
 
 It turns out that when writing unsafe code, we generally don't need to
 worry at all about doing the right thing for the drop checker. However there
index 0a63764aafd9c4455033944c60546f6bb9fc6c58..3f92e641085040fee86ff13d9e4d6b59e842b152 100644 (file)
@@ -30,15 +30,12 @@ it is not uncommon for Unsafe code to work with arrays of temporarily
 uninitialized data while repeatedly invoking caller-provided code. Such code
 needs to be careful and consider exception safety.
 
-
-
-
-
 ## Vec::push_all
 
 `Vec::push_all` is a temporary hack to get extending a Vec by a slice reliably
 efficient without specialization. Here's a simple implementation:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 impl<T: Clone> Vec<T> {
     fn push_all(&mut self, to_push: &[T]) {
@@ -69,10 +66,6 @@ we *did* clone are dropped, we can set the `len` every loop iteration. If we
 just want to guarantee that uninitialized memory can't be observed, we can set
 the `len` after the loop.
 
-
-
-
-
 ## BinaryHeap::sift_up
 
 Bubbling an element up a heap is a bit more complicated than extending a Vec.
@@ -83,7 +76,6 @@ bubble_up(heap, index):
     while index != 0 && heap[index] < heap[parent(index)]:
         heap.swap(index, parent(index))
         index = parent(index)
-
 ```
 
 A literal transcription of this code to Rust is totally fine, but has an annoying
@@ -155,6 +147,7 @@ way to do this is to store the algorithm's state in a separate struct with a
 destructor for the "finally" logic. Whether we panic or not, that destructor
 will run and clean up after us.
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 struct Hole<'a, T: 'a> {
     data: &'a mut [T],
index fa997c0e13cb443f91f1157c1a64f51664591a6c..8ada0fb7c7fd1a4f777ba6089569fa6ba8262341 100644 (file)
@@ -3,11 +3,7 @@
 Most of the time, we expect types to have a statically known and positive size.
 This isn't always the case in Rust.
 
-
-
-
-
-# Dynamically Sized Types (DSTs)
+## Dynamically Sized Types (DSTs)
 
 Rust supports Dynamically Sized Types (DSTs): types without a statically
 known size or alignment. On the surface, this is a bit nonsensical: Rust *must*
@@ -69,11 +65,7 @@ fn main() {
 
 (Yes, custom DSTs are a largely half-baked feature for now.)
 
-
-
-
-
-# Zero Sized Types (ZSTs)
+## Zero Sized Types (ZSTs)
 
 Rust also allows types to be specified that occupy no space:
 
@@ -121,9 +113,7 @@ type.
 [alloc]: ../std/alloc/trait.GlobalAlloc.html#tymethod.alloc
 [ub]: what-unsafe-does.html
 
-
-
-# Empty Types
+## Empty Types
 
 Rust also enables types to be declared that *cannot even be instantiated*. These
 types can only be talked about at the type level, and never at the value level.
@@ -149,7 +139,7 @@ other is still UB).
 
 The following *could* also compile:
 
-```rust,ignore
+```rust,compile_fail
 enum Void {}
 
 let res: Result<u32, Void> = Ok(0);
@@ -177,22 +167,15 @@ into a reference without any safety problems. It still doesn't prevent you from
 trying to read or write values, but at least it compiles to a no-op instead
 of UB.
 
-
-
-
-
-# Extern Types
+## Extern Types
 
 There is [an accepted RFC][extern-types] to add proper types with an unknown size,
 called *extern types*, which would let Rust developers model things like C's `void*`
 and other "declared but never defined" types more accurately. However as of
-Rust 2018, the feature is stuck in limbo over how `size_of::<MyExternType>()`
-should behave.
-
-
-
+Rust 2018, [the feature is stuck in limbo over how `size_of_val::<MyExternType>()`
+should behave][extern-types-issue].
 
-[dst-issue]: https://github.com/rust-lang/rust/issues/26403
 [extern-types]: https://github.com/rust-lang/rfcs/blob/master/text/1861-extern-types.md
+[extern-types-issue]: https://github.com/rust-lang/rust/issues/43467
 [`str`]: ../std/primitive.str.html
 [slice]: ../std/primitive.slice.html
index a8383d6300a81bd05c4dc536d62117f39fb472f7..8012bbc4c6f3c5057bbe805b360f3b119394f177 100644 (file)
@@ -1,6 +1,6 @@
 # Foreign Function Interface
 
-# Introduction
+## Introduction
 
 This guide will use the [snappy](https://github.com/google/snappy)
 compression/decompression library as an introduction to writing bindings for
@@ -28,6 +28,7 @@ and add `extern crate libc;` to your crate root.
 The following is a minimal example of calling a foreign function which will
 compile if snappy is installed:
 
+<!-- ignore: requires libc crate -->
 ```rust,ignore
 extern crate libc;
 use libc::size_t;
@@ -61,6 +62,7 @@ of keeping the binding correct at runtime.
 
 The `extern` block can be extended to cover the entire snappy API:
 
+<!-- ignore: requires libc crate -->
 ```rust,ignore
 extern crate libc;
 use libc::{c_int, size_t};
@@ -85,7 +87,7 @@ extern {
 # fn main() {}
 ```
 
-# Creating a safe interface
+## Creating a safe interface
 
 The raw C API needs to be wrapped to provide memory safety and make use of higher-level concepts
 like vectors. A library can choose to expose only the safe, high-level interface and hide the unsafe
@@ -96,6 +98,7 @@ vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous
 length is the number of elements currently contained, and the capacity is the total size in elements of
 the allocated memory. The length is less than or equal to the capacity.
 
+<!-- ignore: requires libc crate -->
 ```rust,ignore
 # extern crate libc;
 # use libc::{c_int, size_t};
@@ -120,6 +123,7 @@ required capacity to hold the compressed output. The vector can then be passed t
 `snappy_compress` function as an output parameter. An output parameter is also passed to retrieve
 the true length after compression for setting the length.
 
+<!-- ignore: requires libc crate -->
 ```rust,ignore
 # extern crate libc;
 # use libc::{size_t, c_int};
@@ -146,6 +150,7 @@ pub fn compress(src: &[u8]) -> Vec<u8> {
 Decompression is similar, because snappy stores the uncompressed size as part of the compression
 format and `snappy_uncompressed_length` will retrieve the exact buffer size required.
 
+<!-- ignore: requires libc crate -->
 ```rust,ignore
 # extern crate libc;
 # use libc::{size_t, c_int};
@@ -180,6 +185,7 @@ pub fn uncompress(src: &[u8]) -> Option<Vec<u8>> {
 
 Then, we can add some tests to show how to use them.
 
+<!-- ignore: requires libc crate -->
 ```rust,ignore
 # extern crate libc;
 # use libc::{c_int, size_t};
@@ -234,7 +240,7 @@ mod tests {
 }
 ```
 
-# Destructors
+## Destructors
 
 Foreign libraries often hand off ownership of resources to the calling code.
 When this occurs, we must use Rust's destructors to provide safety and guarantee
@@ -242,7 +248,7 @@ the release of these resources (especially in the case of panic).
 
 For more about destructors, see the [Drop trait](../std/ops/trait.Drop.html).
 
-# Callbacks from C code to Rust functions
+## Callbacks from C code to Rust functions
 
 Some external libraries require the usage of callbacks to report back their
 current state or intermediate data to the caller.
@@ -295,7 +301,6 @@ void trigger_callback() {
 In this example Rust's `main()` will call `trigger_callback()` in C,
 which would, in turn, call back to `callback()` in Rust.
 
-
 ## Targeting callbacks to Rust objects
 
 The former example showed how a global function can be called from C code.
@@ -311,7 +316,6 @@ referenced Rust object.
 Rust code:
 
 ```rust,no_run
-#[repr(C)]
 struct RustObject {
     a: i32,
     // Other members...
@@ -384,7 +388,7 @@ This can be achieved by unregistering the callback in the object's
 destructor and designing the library in a way that guarantees that no
 callback will be performed after deregistration.
 
-# Linking
+## Linking
 
 The `link` attribute on `extern` blocks provides the basic building block for
 instructing rustc how it will link to native libraries. There are two accepted
@@ -433,7 +437,7 @@ A few examples of how this model can be used are:
 
 On macOS, frameworks behave with the same semantics as a dynamic library.
 
-# Unsafe blocks
+## Unsafe blocks
 
 Some operations, like dereferencing raw pointers or calling functions that have been marked
 unsafe are only allowed inside unsafe blocks. Unsafe blocks isolate unsafety and are a promise to
@@ -448,12 +452,13 @@ unsafe fn kaboom(ptr: *const i32) -> i32 { *ptr }
 
 This function can only be called from an `unsafe` block or another `unsafe` function.
 
-# Accessing foreign globals
+## Accessing foreign globals
 
 Foreign APIs often export a global variable which could do something like track
 global state. In order to access these variables, you declare them in `extern`
 blocks with the `static` keyword:
 
+<!-- ignore: requires libc crate -->
 ```rust,ignore
 extern crate libc;
 
@@ -472,6 +477,7 @@ Alternatively, you may need to alter global state provided by a foreign
 interface. To do this, statics can be declared with `mut` so we can mutate
 them.
 
+<!-- ignore: requires libc crate -->
 ```rust,ignore
 extern crate libc;
 
@@ -498,12 +504,13 @@ fn main() {
 Note that all interaction with a `static mut` is unsafe, both reading and
 writing. Dealing with global mutable state requires a great deal of care.
 
-# Foreign calling conventions
+## Foreign calling conventions
 
 Most foreign code exposes a C ABI, and Rust uses the platform's C calling convention by default when
 calling foreign functions. Some foreign functions, most notably the Windows API, use other calling
 conventions. Rust provides a way to tell the compiler which convention to use:
 
+<!-- ignore: requires libc crate -->
 ```rust,ignore
 extern crate libc;
 
@@ -540,7 +547,7 @@ however, windows uses the `C` calling convention, so `C` would be used. This
 means that in our previous example, we could have used `extern "system" { ... }`
 to define a block for all windows systems, not only x86 ones.
 
-# Interoperability with foreign code
+## Interoperability with foreign code
 
 Rust guarantees that the layout of a `struct` is compatible with the platform's
 representation in C only if the `#[repr(C)]` attribute is applied to it.
@@ -565,7 +572,7 @@ The [`libc` crate on crates.io][libc] includes type aliases and function
 definitions for the C standard library in the `libc` module, and Rust links
 against `libc` and `libm` by default.
 
-# Variadic functions
+## Variadic functions
 
 In C, functions can be 'variadic', meaning they accept a variable number of arguments. This can
 be achieved in Rust by specifying `...` within the argument list of a foreign function declaration:
@@ -584,13 +591,13 @@ fn main() {
 
 Normal Rust functions can *not* be variadic:
 
-```ignore
+```rust,compile_fail
 // This will not compile
 
-fn foo(x: i32, ...) { }
+fn foo(x: i32, ...) {}
 ```
 
-# The "nullable pointer optimization"
+## The "nullable pointer optimization"
 
 Certain Rust types are defined to never be `null`. This includes references (`&T`,
 `&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`). When
@@ -615,6 +622,7 @@ callback, which gets called in certain situations. The callback is passed a func
 and an integer and it is supposed to run the function with the integer as a parameter. So
 we have function pointers flying across the FFI boundary in both directions.
 
+<!-- ignore: requires libc crate -->
 ```rust,ignore
 extern crate libc;
 use libc::c_int;
@@ -655,7 +663,7 @@ void register(void (*f)(int (*)(int), int)) {
 
 No `transmute` required!
 
-# Calling Rust code from C
+## Calling Rust code from C
 
 You may wish to compile Rust code in a way so that it can be called from C. This is
 fairly easy, but requires a few things:
@@ -673,7 +681,7 @@ discussed above in "[Foreign Calling
 Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle`
 attribute turns off Rust's name mangling, so that it is easier to link to.
 
-# FFI and panics
+## FFI and panics
 
 It’s important to be mindful of `panic!`s when working with FFI. A `panic!`
 across an FFI boundary is undefined behavior. If you’re writing code that may
@@ -702,11 +710,10 @@ for more information.
 
 [`catch_unwind`]: ../std/panic/fn.catch_unwind.html
 
-# Representing opaque structs
+## Representing opaque structs
 
-Sometimes, a C library wants to provide a pointer to something, but not let you
-know the internal details of the thing it wants. The simplest way is to use a
-`void *` argument:
+Sometimes, a C library wants to provide a pointer to something, but not let you know the internal details of the thing it wants.
+A stable and simple way is to use a `void *` argument:
 
 ```c
 void foo(void *arg);
@@ -715,6 +722,7 @@ void bar(void *arg);
 
 We can represent this in Rust with the `c_void` type:
 
+<!-- ignore: requires libc crate -->
 ```rust,ignore
 extern crate libc;
 
@@ -775,3 +783,9 @@ Notice that it is a really bad idea to use an empty enum as FFI type.
 The compiler relies on empty enums being uninhabited, so handling values of type
 `&Empty` is a huge footgun and can lead to buggy program behavior (by triggering
 undefined behavior).
+
+> **NOTE:** The simplest way would use "extern types".
+But it's currently (as of June 2021) unstable and has some unresolved questions, see the [RFC page][extern-type-rfc] and the [tracking issue][extern-type-issue] for more details.
+
+[extern-type-issue]: https://github.com/rust-lang/rust/issues/43467
+[extern-type-rfc]: https://rust-lang.github.io/rfcs/1861-extern-types.html
index 645986af13ace5aae29aa8bf5f1c7a1607a8dfa0..be5a55bbe6bb4678be4e20f461e2c4a81fcd3e4e 100644 (file)
@@ -28,6 +28,7 @@ fn main() {
 If we try to naively desugar this code in the same way that we did in the
 lifetimes section, we run into some trouble:
 
+<!-- ignore: desugared code -->
 ```rust,ignore
 struct Closure<F> {
     data: (u8, u16),
@@ -60,6 +61,7 @@ named until we enter the body of `call`! Also, that isn't some fixed lifetime;
 This job requires The Magic of Higher-Rank Trait Bounds (HRTBs). The way we
 desugar this is as follows:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8,
 ```
diff --git a/src/doc/nomicon/src/intro.md b/src/doc/nomicon/src/intro.md
new file mode 100644 (file)
index 0000000..5ada80e
--- /dev/null
@@ -0,0 +1,43 @@
+# The Rustonomicon
+
+<div class="warning">
+
+Warning:
+This book is incomplete.
+Documenting everything and rewriting outdated parts take a while.
+See the [issue tracker] to check what's missing/outdated, and if there are any mistakes or ideas that haven't been reported, feel free to open a new issue there.
+
+</div>
+
+[issue tracker]: https://github.com/rust-lang/nomicon/issues
+
+## The Dark Arts of Unsafe Rust
+
+> THE KNOWLEDGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF UNLEASHING INDESCRIBABLE HORRORS THAT SHATTER YOUR PSYCHE AND SET YOUR MIND ADRIFT IN THE UNKNOWABLY INFINITE COSMOS.
+
+The Rustonomicon digs into all the awful details that you need to understand when writing Unsafe Rust programs.
+
+Should you wish a long and happy career of writing Rust programs, you should turn back now and forget you ever saw this book.
+It is not necessary.
+However if you intend to write unsafe code — or just want to dig into the guts of the language — this book contains lots of useful information.
+
+Unlike *[The Rust Programming Language][trpl]*, we will be assuming considerable prior knowledge.
+In particular, you should be comfortable with basic systems programming and Rust.
+If you don't feel comfortable with these topics, you should consider reading [The Book][trpl] first.
+That said, we won't assume you have read it, and we will take care to occasionally give a refresher on the basics where appropriate.
+You can skip straight to this book if you want; just know that we won't be explaining everything from the ground up.
+
+This book exists primarily as a high-level companion to [The Reference][ref].
+Where The Reference exists to detail the syntax and semantics of every part of the language, The Rustonomicon exists to describe how to use those pieces together, and the issues that you will have in doing so.
+
+The Reference will tell you the syntax and semantics of references, destructors, and unwinding, but it won't tell you how combining them can lead to exception-safety issues, or how to deal with those issues.
+
+It should be noted that we haven't synced The Rustnomicon and The Reference well, so they may have a duplicate content.
+In general, if the two documents disagree, The Reference should be assumed to be correct (it isn't yet considered normative, it's just better maintained).
+
+Topics that are within the scope of this book include: the meaning of (un)safety, unsafe primitives provided by the language and standard library, techniques for creating safe abstractions with those unsafe primitives, subtyping and variance, exception-safety (panic/unwind-safety), working with uninitialized memory, type punning, concurrency, interoperating with other languages (FFI), optimization tricks, how constructs lower to compiler/OS/hardware primitives, how to **not** make the memory model people angry, how you're **going** to make the memory model people angry, and more.
+
+The Rustonomicon is not a place to exhaustively describe the semantics and guarantees of every single API in the standard library, nor is it a place to exhaustively describe every feature of Rust.
+
+[trpl]: ../book/index.html
+[ref]: ../reference/index.html
index 3b04e2833cbca69c0ed7a64d94977809ee4f20d2..e46be7dfcfc478a627024e0e827d1999595bb8a6 100644 (file)
@@ -49,8 +49,6 @@ library:
 * `Rc`
 * `thread::scoped::JoinGuard`
 
-
-
 ## Drain
 
 `drain` is a collections API that moves data out of the container without
@@ -71,6 +69,7 @@ unwinding-safe! Easy!
 
 Now consider the following:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 let mut vec = vec![Box::new(0); 4];
 
@@ -105,9 +104,6 @@ mem::forget us in the middle of the iteration, all that does is *leak even more*
 Since we've accepted that mem::forget is safe, this is definitely safe. We call
 leaks causing more leaks a *leak amplification*.
 
-
-
-
 ## Rc
 
 Rc is an interesting case because at first glance it doesn't appear to be a
@@ -121,6 +117,7 @@ Nope.
 
 Let's consider a simplified implementation of Rc:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 struct Rc<T> {
     ptr: *mut RcBox<T>,
@@ -177,9 +174,6 @@ This can be solved by just checking the `ref_count` and doing *something*. The
 standard library's stance is to just abort, because your program has become
 horribly degenerate. Also *oh my gosh* it's such a ridiculous corner case.
 
-
-
-
 ## thread::scoped::JoinGuard
 
 The thread::scoped API intended to allow threads to be spawned that reference
@@ -187,6 +181,7 @@ data on their parent's stack without any synchronization over that data by
 ensuring the parent joins the thread before any of the shared data goes out
 of scope.
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 pub fn scoped<'a, F>(f: F) -> JoinGuard<'a>
     where F: FnOnce() + Send + 'a
@@ -204,6 +199,7 @@ of the closed-over data goes out of scope in the parent.
 
 Usage looked like:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 {
@@ -232,6 +228,7 @@ let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 In principle, this totally works! Rust's ownership system perfectly ensures it!
 ...except it relies on a destructor being called to be safe.
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 let mut data = Box::new(0);
 {
index 76283516ce123ed84563a4eec8beb5eacd7d36bd..c65a15759b9164fc50e3edc2a4eef07480eb060a 100644 (file)
@@ -5,6 +5,7 @@ In order to make common patterns more ergonomic, Rust allows lifetimes to be
 
 A *lifetime position* is anywhere you can write a lifetime in a type:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 &'a T
 &'a mut T
@@ -38,6 +39,7 @@ Elision rules are as follows:
 
 Examples:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 fn print(s: &str);                                      // elided
 fn print<'a>(s: &'a str);                               // expanded
@@ -60,5 +62,4 @@ fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // ex
 
 fn new(buf: &mut [u8]) -> BufWriter;                    // elided
 fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>          // expanded
-
 ```
index c53648c53f2c4d108677592661c1fe7e0f574932..18082a4345ce2055cc217672b08f023f1c490c11 100644 (file)
@@ -2,7 +2,7 @@
 
 Given the following code:
 
-```rust,edition2018,compile_fail
+```rust,compile_fail
 #[derive(Debug)]
 struct Foo;
 
@@ -40,6 +40,7 @@ What happened? Well, we got the exact same reasoning as we did for
 [Example 2 in the previous section][ex2]. We desugar the program and we get
 the following:
 
+<!-- ignore: desugared code -->
 ```rust,ignore
 struct Foo;
 
@@ -70,15 +71,13 @@ blows up in our face!
 This program is clearly correct according to the reference semantics we actually
 care about, but the lifetime system is too coarse-grained to handle that.
 
-
-
-# Improperly reduced borrows
+## Improperly reduced borrows
 
 The following code fails to compile, because Rust doesn't understand that the borrow
 is no longer needed and conservatively falls back to using a whole scope for it.
 This will eventually get fixed.
 
-```rust,edition2018,compile_fail
+```rust,compile_fail
 # use std::collections::HashMap;
 # use std::hash::Hash;
 fn get_default<'m, K, V>(map: &'m mut HashMap<K, V>, key: K) -> &'m mut V
@@ -120,5 +119,4 @@ error[E0499]: cannot borrow `*map` as mutable more than once at a time
    | |_____- returning this value requires that `*map` is borrowed for `'m`
 ```
 
-
 [ex2]: lifetimes.html#example-aliasing-a-mutable-reference
index c6c0e8462fdd9bdbac6cca79ae783a87787c5566..0a68a28739ba6a03ef7d2592ec7dd2dceac717e7 100644 (file)
@@ -45,6 +45,7 @@ let z = &y;
 The borrow checker always tries to minimize the extent of a lifetime, so it will
 likely desugar to the following:
 
+<!-- ignore: desugared code -->
 ```rust,ignore
 // NOTE: `'a: {` and `&'b x` is not valid syntax!
 'a: {
@@ -72,6 +73,7 @@ let y = &x;
 z = y;
 ```
 
+<!-- ignore: desugared code -->
 ```rust,ignore
 'a: {
     let x: i32 = 0;
@@ -87,9 +89,7 @@ z = y;
 }
 ```
 
-
-
-# Example: references that outlive referents
+## Example: references that outlive referents
 
 Alright, let's look at some of those examples from before:
 
@@ -102,6 +102,7 @@ fn as_str(data: &u32) -> &str {
 
 desugars to:
 
+<!-- ignore: desugared code -->
 ```rust,ignore
 fn as_str<'a>(data: &'a u32) -> &'a str {
     'b: {
@@ -129,6 +130,7 @@ up in our face.
 
 To make this more clear, we can expand the example:
 
+<!-- ignore: desugared code -->
 ```rust,ignore
 fn as_str<'a>(data: &'a u32) -> &'a str {
     'b: {
@@ -169,11 +171,7 @@ we could have returned an `&'a str` would have been if it was in a field of the
 can be considered to reside at the bottom of the stack; though this limits
 our implementation *just a bit*.)
 
-
-
-
-
-# Example: aliasing a mutable reference
+## Example: aliasing a mutable reference
 
 How about the other example:
 
@@ -184,6 +182,7 @@ data.push(4);
 println!("{}", x);
 ```
 
+<!-- ignore: desugared code -->
 ```rust,ignore
 'a: {
     let mut data: Vec<i32> = vec![1, 2, 3];
@@ -222,11 +221,9 @@ to the compiler. However it does mean that several programs that are totally
 correct with respect to Rust's *true* semantics are rejected because lifetimes
 are too dumb.
 
+## The area covered by a lifetime
 
-
-# The area covered by a lifetime
-
-The lifetime (sometimes called a *borrow*) is *alive* from the place it is
+A reference (sometimes called a *borrow*) is *alive* from the place it is
 created to its last use. The borrowed thing needs to outlive only borrows that
 are alive. This looks simple, but there are few subtleties.
 
@@ -234,7 +231,7 @@ The following snippet compiles, because after printing `x`, it is no longer
 needed, so it doesn't matter if it is dangling or aliased (even though the
 variable `x` *technically* exists to the very end of the scope).
 
-```rust,edition2018
+```rust
 let mut data = vec![1, 2, 3];
 let x = &data[0];
 println!("{}", x);
@@ -246,7 +243,7 @@ However, if the value has a destructor, the destructor is run at the end of the
 scope. And running the destructor is considered a use ‒ obviously the last one.
 So, this will *not* compile.
 
-```rust,edition2018,compile_fail
+```rust,compile_fail
 #[derive(Debug)]
 struct X<'a>(&'a i32);
 
@@ -266,7 +263,7 @@ One way to convince the compiler that `x` is no longer valid is by using `drop(x
 Furthermore, there might be multiple possible last uses of the borrow, for
 example in each branch of a condition.
 
-```rust,edition2018
+```rust
 # fn some_condition() -> bool { true }
 let mut data = vec![1, 2, 3];
 let x = &data[0];
@@ -286,7 +283,7 @@ borrows just being tied to the same local variable. This often happens around
 loops (writing a new value of a variable at the end of the loop and using it for
 the last time at the top of the next iteration).
 
-```rust,edition2018
+```rust
 let mut data = vec![1, 2, 3];
 // This mut allows us to change where the reference points to
 let mut x = &data[0];
index a7cc675c1b496b102ea2743cdb602f0a7d2632d3..2b5a430405f243124a2704e712b11c93cdbbc6fe 100644 (file)
@@ -3,10 +3,7 @@
 Rust allows you to specify alternative data layout strategies from the default.
 There's also the [unsafe code guidelines] (note that it's **NOT** normative).
 
-
-
-
-# repr(C)
+## repr(C)
 
 This is the most important `repr`. It has fairly simple intent: do what C does.
 The order, size, and alignment of fields is exactly what you would expect from C
@@ -15,10 +12,10 @@ or C++. Any type you expect to pass through an FFI boundary should have
 necessary to soundly do more elaborate tricks with data layout such as
 reinterpreting values as a different type.
 
-We strongly recommend using [rust-bindgen][] and/or [cbindgen][] to manage your FFI
+We strongly recommend using [rust-bindgen] and/or [cbindgen] to manage your FFI
 boundaries for you. The Rust team works closely with those projects to ensure
 that they work robustly and are compatible with current and future guarantees
-about type layouts and reprs.
+about type layouts and `repr`s.
 
 The interaction of `repr(C)` with Rust's more exotic data layout features must be
 kept in mind. Due to its dual purpose as "for FFI" and "for layout control",
@@ -57,9 +54,7 @@ construct an instance of an enum that does not match one of its
 variants. (This allows exhaustive matches to continue to be written and
 compiled as normal.)
 
-
-
-# repr(transparent)
+## repr(transparent)
 
 This can only be used on structs with a single non-zero-sized field (there may
 be additional zero-sized fields). The effect is that the layout and ABI of the
@@ -75,9 +70,7 @@ Foo(f32)` to always have the same ABI as `f32`.
 
 More details are in the [RFC][rfc-transparent].
 
-
-
-# repr(u*), repr(i*)
+## repr(u*), repr(i*)
 
 These specify the size to make a fieldless enum. If the discriminant overflows
 the integer it has to fit in, it will produce a compile-time error. You can
@@ -96,15 +89,28 @@ in that there is a defined layout of the type. This makes it possible to
 pass the enum to C code, or access the type's raw representation and directly
 manipulate its tag and fields. See [the RFC][really-tagged] for details.
 
-Adding an explicit `repr` to an enum suppresses the null-pointer
-optimization.
+These `repr`s have no effect on a struct.
 
-These reprs have no effect on a struct.
+Adding an explicit `repr(u*)`, `repr(i*)`, or `repr(C)` to an enum suppresses the null-pointer optimization, like:
 
+```rust
+# use std::mem::size_of;
+enum MyOption<T> {
+    Some(T),
+    None,
+}
 
+#[repr(u8)]
+enum MyReprOption<T> {
+    Some(T),
+    None,
+}
 
+assert_eq!(8, size_of::<MyOption<&u16>>());
+assert_eq!(16, size_of::<MyReprOption<&u16>>());
+```
 
-# repr(packed)
+## repr(packed)
 
 `repr(packed)` forces Rust to strip any padding, and only align the type to a
 byte. This may improve the memory footprint, but will likely have other negative
@@ -117,17 +123,15 @@ compiler might be able to paper over alignment issues with shifts and masks.
 However if you take a reference to a packed field, it's unlikely that the
 compiler will be able to emit code to avoid an unaligned load.
 
-**[As of Rust 2018, this still can cause undefined behavior.][ub loads]**
+[As this can cause undefined behavior][ub loads], the lint has been implemented
+and it will become a hard error.
 
 `repr(packed)` is not to be used lightly. Unless you have extreme requirements,
 this should not be used.
 
 This repr is a modifier on `repr(C)` and `repr(Rust)`.
 
-
-
-
-# repr(align(n))
+## repr(align(n))
 
 `repr(align(n))` (where `n` is a power of two) forces the type to have an
 alignment of *at least* n.
@@ -139,10 +143,6 @@ kinds of concurrent code).
 This is a modifier on `repr(C)` and `repr(Rust)`. It is incompatible with
 `repr(packed)`.
 
-
-
-
-
 [unsafe code guidelines]: https://rust-lang.github.io/unsafe-code-guidelines/layout.html
 [drop flags]: drop-flags.html
 [ub loads]: https://github.com/rust-lang/rust/issues/27060
index dd9e9db244a8161a2c8b59555cad56c1efe944b0..4cfac68c43d90cd116043dd1c445b25401bbff5b 100644 (file)
@@ -17,7 +17,7 @@ issue...). This is a pervasive problem that C and C++ programs need to deal
 with. Consider this simple mistake that all of us who have used a non-GC'd
 language have made at one point:
 
-```rust,ignore
+```rust,compile_fail
 fn as_str(data: &u32) -> &str {
     // compute the string
     let s = format!("{}", data);
@@ -46,7 +46,7 @@ verifying that references don't escape the scope of their referent. That's
 because ensuring pointers are always valid is much more complicated than this.
 For instance in this code,
 
-```rust,ignore
+```rust,compile_fail
 let mut data = vec![1, 2, 3];
 // get an internal reference
 let x = &data[0];
@@ -63,4 +63,3 @@ naive scope analysis would be insufficient to prevent this bug, because `data`
 does in fact live as long as we needed. However it was *changed* while we had
 a reference into it. This is why Rust requires any references to freeze the
 referent and its owners.
-
index b06707bf35cc0396235a4cd37c11fbe48ef79037..3b48dba7ae58ab6ff59c8d74d634fe50aa0fb008 100644 (file)
@@ -1,4 +1,4 @@
-## #[panic_handler]
+# #[panic_handler]
 
 `#[panic_handler]` is used to define the behavior of `panic!` in `#![no_std]` applications.
 The `#[panic_handler]` attribute must be applied to a function with signature `fn(&PanicInfo)
@@ -17,9 +17,10 @@ Below is shown an example where an application has a different panicking behavio
 whether is compiled using the dev profile (`cargo build`) or using the release profile (`cargo build
 --release`).
 
-``` rust, ignore
-// crate: panic-semihosting -- log panic messages to the host stderr using semihosting
+`panic-semihosting` crate -- log panic messages to the host stderr using semihosting:
 
+<!-- ignore: simplified code -->
+```rust,ignore
 #![no_std]
 
 use core::fmt::{Write, self};
@@ -49,8 +50,10 @@ fn panic(info: &PanicInfo) -> ! {
 }
 ```
 
-``` rust, ignore
-// crate: panic-halt -- halt the thread on panic; messages are discarded
+`panic-halt` crate -- halt the thread on panic; messages are discarded:
+
+<!-- ignore: simplified code -->
+```rust,ignore
 
 #![no_std]
 
@@ -62,8 +65,10 @@ fn panic(_info: &PanicInfo) -> ! {
 }
 ```
 
-``` rust, ignore
-// crate: app
+`app` crate:
+
+<!-- ignore: requires external crate -->
+```rust,ignore
 
 #![no_std]
 
index 4c9a88052003ed24f8781a50716df639ce28a7a3..68ddb8f06f90c089e691fdf43fc79bee616f53f8 100644 (file)
@@ -13,10 +13,12 @@ struct Iter<'a, T: 'a> {
 ```
 
 However because `'a` is unused within the struct's body, it's *unbounded*.
-Because of the troubles this has historically caused, unbounded lifetimes and
-types are *forbidden* in struct definitions. Therefore we must somehow refer
-to these types in the body. Correctly doing this is necessary to have
-correct variance and drop checking.
+[Because of the troubles this has historically caused][unused-param],
+unbounded lifetimes and types are *forbidden* in struct definitions.
+Therefore we must somehow refer to these types in the body.
+Correctly doing this is necessary to have correct variance and drop checking.
+
+[unused-param]: https://rust-lang.github.io/rfcs/0738-variance.html#the-corner-case-unused-parameters-and-parameters-that-are-only-used-unsafely
 
 We do this using `PhantomData`, which is a special marker type. `PhantomData`
 consumes no space, but simulates a field of the given type for the purpose of
@@ -25,7 +27,7 @@ the type-system the kind of variance that you want, while also providing other
 useful things such as the information needed by drop check.
 
 Iter logically contains a bunch of `&'a T`s, so this is exactly what we tell
-the PhantomData to simulate:
+the `PhantomData` to simulate:
 
 ```rust
 use std::marker;
@@ -63,7 +65,7 @@ soundness. This will in turn allow people to create unsoundness using
 Vec's destructor.
 
 In order to tell dropck that we *do* own values of type T, and therefore may
-drop some T's when *we* drop, we must add an extra PhantomData saying exactly
+drop some T's when *we* drop, we must add an extra `PhantomData` saying exactly
 that:
 
 ```rust
index 7baed6ee695822a47978be9db35c7a3e4a425a4e..5275b2327fb0514b5cb7ac9bcdc8bb0744c47078 100644 (file)
@@ -104,6 +104,7 @@ Rust lays out the fields in the order specified, we expect it to pad the
 values in the struct to satisfy their alignment requirements. So if Rust
 didn't reorder fields, we would expect it to produce the following:
 
+<!-- ignore: explanation code -->
 ```rust,ignore
 struct Foo<u16, u32> {
     count: u16,
index 79b640835016a5e8465b5837f8e52dc73a1bd258..8ac7c1ab510a74ec60e6612c4b19a16eeae92981 100644 (file)
@@ -15,7 +15,6 @@ we will then relate it back to how subtyping actually occurs in Rust.
 
 So here's our simple extension, *Objective Rust*, featuring three new types:
 
-
 ```rust
 trait Animal {
     fn snuggle(&self);
@@ -35,6 +34,7 @@ But unlike normal traits, we can use them as concrete and sized types, just like
 
 Now, say we have a very simple function that takes an Animal, like this:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 fn love(pet: Animal) {
     pet.snuggle();
@@ -44,6 +44,7 @@ fn love(pet: Animal) {
 By default, static types must match *exactly* for a program to compile. As such,
 this code won't compile:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 let mr_snuggles: Cat = ...;
 love(mr_snuggles);         // ERROR: expected Animal, found Cat
@@ -79,6 +80,7 @@ of our static type system, making it worse than useless (and leading to Undefine
 Here's a simple example of this happening when we apply subtyping in a completely naive
 "find and replace" way.
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 fn evil_feeder(pet: &mut Animal) {
     let spike: Dog = ...;
@@ -133,10 +135,7 @@ because nothing ever has type `'a`. Lifetimes only occur as part of some larger
 like `&'a u32` or `IterMut<'a, u32>`. To apply lifetime subtyping, we need to know
 how to compose subtyping. Once again, we need *variance*.
 
-
-
-
-# Variance
+## Variance
 
 Variance is where things get a bit complicated.
 
@@ -188,6 +187,10 @@ some sense "fundamental". All the others can be understood by analogy to the oth
 * `*const T` follows the logic of `&T`
 * `*mut T` follows the logic of `&mut T` (or `UnsafeCell<T>`)
 
+For more types, see the ["Variance" section][variance-table] on the reference.
+
+[variance-table]: ../reference/subtyping.html#variance
+
 > NOTE: the *only* source of contravariance in the language is the arguments to
 > a function, which is why it really doesn't come up much in practice. Invoking
 > contravariance involves higher-order programming with function pointers that
@@ -199,6 +202,7 @@ and look at some examples.
 
 First off, let's revisit the meowing dog example:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 fn evil_feeder(pet: &mut Animal) {
     let spike: Dog = ...;
@@ -265,7 +269,7 @@ enough into the place expecting something long-lived.
 
 Here it is:
 
-```rust,ignore
+```rust,compile_fail
 fn evil_feeder<T>(input: &mut T, val: T) {
     *input = val;
 }
@@ -285,15 +289,16 @@ And what do we get when we run this?
 
 ```text
 error[E0597]: `spike` does not live long enough
-  --> src/main.rs:9:32
+  --> src/main.rs:9:31
    |
-9  |         let spike_str: &str = &spike;
-   |                                ^^^^^ borrowed value does not live long enough
-10 |         evil_feeder(&mut mr_snuggles, spike_str);
+6  |     let mut mr_snuggles: &'static str = "meow! :3";  // mr. snuggles forever!!
+   |                          ------------ type annotation requires that `spike` is borrowed for `'static`
+...
+9  |         let spike_str: &str = &spike;                // Only lives for the block
+   |                               ^^^^^^ borrowed value does not live long enough
+10 |         evil_feeder(&mut mr_snuggles, spike_str);    // EVIL!
 11 |     }
-   |     - borrowed value only lives until here
-   |
-   = note: borrowed value must be valid for the static lifetime...
+   |     - `spike` dropped here while still borrowed
 ```
 
 Good, it doesn't compile! Let's break down what's happening here in detail.
@@ -343,6 +348,7 @@ are guaranteed to be the only one with access to it.
 
 Consider the following code:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 let mr_snuggles: Box<Cat> = ..;
 let spike: Box<Dog> = ..;
@@ -368,6 +374,7 @@ Only one thing left to explain: function pointers.
 
 To see why `fn(T) -> U` should be covariant over `U`, consider the following signature:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 fn get_animal() -> Animal;
 ```
@@ -375,6 +382,7 @@ fn get_animal() -> Animal;
 This function claims to produce an Animal. As such, it is perfectly valid to
 provide a function with the following signature instead:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 fn get_animal() -> Cat;
 ```
@@ -387,12 +395,14 @@ just forget that fact.
 
 However, the same logic does not apply to *arguments*. Consider trying to satisfy:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 fn handle_animal(Animal);
 ```
 
-with
+with:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 fn handle_animal(Cat);
 ```
@@ -442,4 +452,3 @@ struct MyType<'a, 'b, A: 'a, B: 'b, C, D, E, F, G, H, In, Out, Mixed> {
     k2: Mixed,              // invariant over Mixed, because invariance wins all conflicts
 }
 ```
-
index 3733c137960f9188735a6fda0ebd339a25aaefe6..1b2d6997bd1d9605076b54ef6e0ca7641e79daf3 100644 (file)
@@ -20,9 +20,9 @@ boggling.
   it may produce a surprising type to satisfy inference.
 
 * Transmuting an `&` to `&mut` is UB.
-    * Transmuting an `&` to `&mut` is *always* UB.
-    * No you can't do it.
-    * No you're not special.
+  * Transmuting an `&` to `&mut` is *always* UB.
+  * No you can't do it.
+  * No you're not special.
 
 * Transmuting to a reference without an explicitly provided lifetime
   produces an [unbounded lifetime].
@@ -50,7 +50,6 @@ Also of course you can get all of the functionality of these functions using raw
 pointer casts or `union`s, but without any of the lints or other basic sanity
 checks. Raw pointer casts and `union`s do not magically avoid the above rules.
 
-
 [unbounded lifetime]: ./unbounded-lifetimes.md
 [transmute]: ../std/mem/fn.transmute.html
 [transmute_copy]: ../std/mem/fn.transmute_copy.html
index b41cf8b4ed91490f6726dfee1e786d328037cd74..03febd6ad5c09cb170ff5787d8ee96112e8c4bdb 100644 (file)
@@ -17,6 +17,7 @@ boundaries.
 Given a function, any output lifetimes that don't derive from inputs are
 unbounded. For instance:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 fn get_str<'a>() -> &'a str;
 ```
@@ -33,4 +34,3 @@ way to bound a lifetime is to return it from a function with a bound lifetime.
 However if this is unacceptable, the reference can be placed in a location with
 a specific lifetime. Unfortunately it's impossible to name all lifetimes involved
 in a function.
-
index 29e1b6a360624c3dd4ae111d2b04fd0724c323bd..7c075213295cf9cb06c5970996446951f53c7a95 100644 (file)
@@ -79,11 +79,14 @@ This code proceeds in three steps:
    acknowledge that by providing appropriate methods).
 
 It's worth spending a bit more time on the loop in the middle, and in particular
-the assignment operator and its interaction with `drop`.  If we would have
-written something like
+the assignment operator and its interaction with `drop`. If we would have
+written something like:
+
+<!-- ignore: simplified code -->
 ```rust,ignore
 *x[i].as_mut_ptr() = Box::new(i as u32); // WRONG!
 ```
+
 we would actually overwrite a `Box<u32>`, leading to `drop` of uninitialized
 data, which will cause much sadness and pain.
 
@@ -126,6 +129,7 @@ Note that, to use the `ptr` methods, you need to first obtain a *raw pointer* to
 the data you want to initialize. It is illegal to construct a *reference* to
 uninitialized data, which implies that you have to be careful when obtaining
 said raw pointer:
+
 * For an array of `T`, you can use `base_ptr.add(idx)` where `base_ptr: *mut T`
 to compute the address of array index `idx`. This relies on
 how arrays are laid out in memory.
@@ -133,9 +137,9 @@ how arrays are laid out in memory.
 also cannot use `&mut base_ptr.field` as that would be creating a
 reference. Thus, it is currently not possible to create a raw pointer to a field
 of a partially initialized struct, and also not possible to initialize a single
-field of a partially initialized struct.  (A
-[solution to this problem](https://github.com/rust-lang/rfcs/pull/2582) is being
-worked on.)
+field of a partially initialized struct. (a
+[solution to this problem](https://github.com/rust-lang/rust/issues/64490) is being
+worked on).
 
 One last remark: when reading old Rust code, you might stumble upon the
 deprecated `mem::uninitialized` function.  That function used to be the only way
diff --git a/src/doc/nomicon/src/vec-alloc.md b/src/doc/nomicon/src/vec-alloc.md
deleted file mode 100644 (file)
index cf3844b..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-# Allocating Memory
-
-Using `NonNull` throws a wrench in an important feature of Vec (and indeed all of
-the std collections): creating an empty Vec doesn't actually allocate at all. This
-is not the same as allocating a zero-sized memory block, which is not allowed by
-the global allocator (it results in undefined behavior!). So if we can't allocate,
-but also can't put a null pointer in `ptr`, what do we do in `Vec::new`? Well, we
-just put some other garbage in there!
-
-This is perfectly fine because we already have `cap == 0` as our sentinel for no
-allocation. We don't even need to handle it specially in almost any code because
-we usually need to check if `cap > len` or `len > 0` anyway. The recommended
-Rust value to put here is `mem::align_of::<T>()`. `NonNull` provides a convenience
-for this: `NonNull::dangling()`. There are quite a few places where we'll
-want to use `dangling` because there's no real allocation to talk about but
-`null` would make the compiler do bad things.
-
-So:
-
-```rust,ignore
-use std::mem;
-
-impl<T> Vec<T> {
-    fn new() -> Self {
-        assert!(mem::size_of::<T>() != 0, "We're not ready to handle ZSTs");
-        Vec {
-            ptr: NonNull::dangling(),
-            len: 0,
-            cap: 0,
-            _marker: PhantomData,
-        }
-    }
-}
-# fn main() {}
-```
-
-I slipped in that assert there because zero-sized types will require some
-special handling throughout our code, and I want to defer the issue for now.
-Without this assert, some of our early drafts will do some Very Bad Things.
-
-Next we need to figure out what to actually do when we *do* want space. For that, 
-we use the global allocation functions [`alloc`][alloc], [`realloc`][realloc], 
-and [`dealloc`][dealloc] which are available in stable Rust in 
-[`std::alloc`][std_alloc]. These functions are expected to become deprecated in 
-favor of the methods of [`std::alloc::Global`][Global] after this type is stabilized. 
-
-We'll also need a way to handle out-of-memory (OOM) conditions. The standard
-library provides a function [`alloc::handle_alloc_error`][handle_alloc_error],
-which will abort the program in a platform-specific manner.
-The reason we abort and don't panic is because unwinding can cause allocations
-to happen, and that seems like a bad thing to do when your allocator just came
-back with "hey I don't have any more memory".
-
-Of course, this is a bit silly since most platforms don't actually run out of
-memory in a conventional way. Your operating system will probably kill the
-application by another means if you legitimately start using up all the memory.
-The most likely way we'll trigger OOM is by just asking for ludicrous quantities
-of memory at once (e.g. half the theoretical address space). As such it's
-*probably* fine to panic and nothing bad will happen. Still, we're trying to be
-like the standard library as much as possible, so we'll just kill the whole
-program.
-
-Okay, now we can write growing. Roughly, we want to have this logic:
-
-```text
-if cap == 0:
-    allocate()
-    cap = 1
-else:
-    reallocate()
-    cap *= 2
-```
-
-But Rust's only supported allocator API is so low level that we'll need to do a
-fair bit of extra work. We also need to guard against some special
-conditions that can occur with really large allocations or empty allocations.
-
-In particular, `ptr::offset` will cause us a lot of trouble, because it has
-the semantics of LLVM's GEP inbounds instruction. If you're fortunate enough to
-not have dealt with this instruction, here's the basic story with GEP: alias
-analysis, alias analysis, alias analysis. It's super important to an optimizing
-compiler to be able to reason about data dependencies and aliasing.
-
-As a simple example, consider the following fragment of code:
-
-```rust,ignore
-*x *= 7;
-*y *= 3;
-```
-
-If the compiler can prove that `x` and `y` point to different locations in
-memory, the two operations can in theory be executed in parallel (by e.g.
-loading them into different registers and working on them independently).
-However the compiler can't do this in general because if x and y point to
-the same location in memory, the operations need to be done to the same value,
-and they can't just be merged afterwards.
-
-When you use GEP inbounds, you are specifically telling LLVM that the offsets
-you're about to do are within the bounds of a single "allocated" entity. The
-ultimate payoff being that LLVM can assume that if two pointers are known to
-point to two disjoint objects, all the offsets of those pointers are *also*
-known to not alias (because you won't just end up in some random place in
-memory). LLVM is heavily optimized to work with GEP offsets, and inbounds
-offsets are the best of all, so it's important that we use them as much as
-possible.
-
-So that's what GEP's about, how can it cause us trouble?
-
-The first problem is that we index into arrays with unsigned integers, but
-GEP (and as a consequence `ptr::offset`) takes a signed integer. This means
-that half of the seemingly valid indices into an array will overflow GEP and
-actually go in the wrong direction! As such we must limit all allocations to
-`isize::MAX` elements. This actually means we only need to worry about
-byte-sized objects, because e.g. `> isize::MAX` `u16`s will truly exhaust all of
-the system's memory. However in order to avoid subtle corner cases where someone
-reinterprets some array of `< isize::MAX` objects as bytes, std limits all
-allocations to `isize::MAX` bytes.
-
-On all 64-bit targets that Rust currently supports we're artificially limited
-to significantly less than all 64 bits of the address space (modern x64
-platforms only expose 48-bit addressing), so we can rely on just running out of
-memory first. However on 32-bit targets, particularly those with extensions to
-use more of the address space (PAE x86 or x32), it's theoretically possible to
-successfully allocate more than `isize::MAX` bytes of memory.
-
-However since this is a tutorial, we're not going to be particularly optimal
-here, and just unconditionally check, rather than use clever platform-specific
-`cfg`s.
-
-The other corner-case we need to worry about is empty allocations. There will
-be two kinds of empty allocations we need to worry about: `cap = 0` for all T,
-and `cap > 0` for zero-sized types.
-
-These cases are tricky because they come
-down to what LLVM means by "allocated". LLVM's notion of an
-allocation is significantly more abstract than how we usually use it. Because
-LLVM needs to work with different languages' semantics and custom allocators,
-it can't really intimately understand allocation. Instead, the main idea behind
-allocation is "doesn't overlap with other stuff". That is, heap allocations,
-stack allocations, and globals don't randomly overlap. Yep, it's about alias
-analysis. As such, Rust can technically play a bit fast and loose with the notion of
-an allocation as long as it's *consistent*.
-
-Getting back to the empty allocation case, there are a couple of places where
-we want to offset by 0 as a consequence of generic code. The question is then:
-is it consistent to do so? For zero-sized types, we have concluded that it is
-indeed consistent to do a GEP inbounds offset by an arbitrary number of
-elements. This is a runtime no-op because every element takes up no space,
-and it's fine to pretend that there's infinite zero-sized types allocated
-at `0x01`. No allocator will ever allocate that address, because they won't
-allocate `0x00` and they generally allocate to some minimal alignment higher
-than a byte. Also generally the whole first page of memory is
-protected from being allocated anyway (a whole 4k, on many platforms).
-
-However what about for positive-sized types? That one's a bit trickier. In
-principle, you can argue that offsetting by 0 gives LLVM no information: either
-there's an element before the address or after it, but it can't know which.
-However we've chosen to conservatively assume that it may do bad things. As
-such we will guard against this case explicitly.
-
-*Phew*
-
-Ok with all the nonsense out of the way, let's actually allocate some memory:
-
-```rust,ignore
-use std::alloc::{self, Layout};
-
-impl<T> Vec<T> {
-    fn grow(&mut self) {
-        let (new_cap, new_layout) = if self.cap == 0 {
-            (1, Layout::array::<T>(1).unwrap())
-        } else {
-            // This can't overflow since self.cap <= isize::MAX.
-            let new_cap = 2 * self.cap;
-
-            // `Layout::array` checks that the number of bytes is <= usize::MAX,
-            // but this is redundant since old_layout.size() <= isize::MAX,
-            // so the `unwrap` should never fail.
-            let new_layout = Layout::array::<T>(new_cap).unwrap();
-            (new_cap, new_layout)
-        };
-
-        // Ensure that the new allocation doesn't exceed `isize::MAX` bytes.
-        assert!(new_layout.size() <= isize::MAX as usize, "Allocation too large");
-
-        let new_ptr = if self.cap == 0 {
-            unsafe { alloc::alloc(new_layout) }
-        } else {
-            let old_layout = Layout::array::<T>(self.cap).unwrap();
-            let old_ptr = self.ptr.as_ptr() as *mut u8;
-            unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) }
-        };
-
-        // If allocation fails, `new_ptr` will be null, in which case we abort.
-        self.ptr = match NonNull::new(new_ptr as *mut T) {
-            Some(p) => p,
-            None => alloc::handle_alloc_error(new_layout),
-        };
-        self.cap = new_cap;
-    }
-}
-# fn main() {}
-```
-
-[Global]: ../std/alloc/struct.Global.html
-[handle_alloc_error]: ../alloc/alloc/fn.handle_alloc_error.html
-[alloc]: ../alloc/alloc/fn.alloc.html
-[realloc]: ../alloc/alloc/fn.realloc.html
-[dealloc]: ../alloc/alloc/fn.dealloc.html
-[std_alloc]: ../alloc/alloc/index.html
diff --git a/src/doc/nomicon/src/vec-dealloc.md b/src/doc/nomicon/src/vec-dealloc.md
deleted file mode 100644 (file)
index 45fe941..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-# Deallocating
-
-Next we should implement Drop so that we don't massively leak tons of resources.
-The easiest way is to just call `pop` until it yields None, and then deallocate
-our buffer. Note that calling `pop` is unneeded if `T: !Drop`. In theory we can
-ask Rust if `T` `needs_drop` and omit the calls to `pop`. However in practice
-LLVM is *really* good at removing simple side-effect free code like this, so I
-wouldn't bother unless you notice it's not being stripped (in this case it is).
-
-We must not call `alloc::dealloc` when `self.cap == 0`, as in this case we
-haven't actually allocated any memory.
-
-```rust,ignore
-impl<T> Drop for Vec<T> {
-    fn drop(&mut self) {
-        if self.cap != 0 {
-            while let Some(_) = self.pop() { }
-            let layout = Layout::array::<T>(self.cap).unwrap();
-            unsafe {
-                alloc::dealloc(self.ptr.as_ptr() as *mut u8, layout);
-            }
-        }
-    }
-}
-```
diff --git a/src/doc/nomicon/src/vec-deref.md b/src/doc/nomicon/src/vec-deref.md
deleted file mode 100644 (file)
index 68d64f7..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-# Deref
-
-Alright! We've got a decent minimal stack implemented. We can push, we can
-pop, and we can clean up after ourselves. However there's a whole mess of
-functionality we'd reasonably want. In particular, we have a proper array, but
-none of the slice functionality. That's actually pretty easy to solve: we can
-implement `Deref<Target=[T]>`. This will magically make our Vec coerce to, and
-behave like, a slice in all sorts of conditions.
-
-All we need is `slice::from_raw_parts`. It will correctly handle empty slices
-for us. Later once we set up zero-sized type support it will also Just Work
-for those too.
-
-```rust,ignore
-use std::ops::Deref;
-
-impl<T> Deref for Vec<T> {
-    type Target = [T];
-    fn deref(&self) -> &[T] {
-        unsafe {
-            std::slice::from_raw_parts(self.ptr.as_ptr(), self.len)
-        }
-    }
-}
-```
-
-And let's do DerefMut too:
-
-```rust,ignore
-use std::ops::DerefMut;
-
-impl<T> DerefMut for Vec<T> {
-    fn deref_mut(&mut self) -> &mut [T] {
-        unsafe {
-            std::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len)
-        }
-    }
-}
-```
-
-Now we have `len`, `first`, `last`, indexing, slicing, sorting, `iter`,
-`iter_mut`, and all other sorts of bells and whistles provided by slice. Sweet!
diff --git a/src/doc/nomicon/src/vec-drain.md b/src/doc/nomicon/src/vec-drain.md
deleted file mode 100644 (file)
index 9b38dff..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-# Drain
-
-Let's move on to Drain. Drain is largely the same as IntoIter, except that
-instead of consuming the Vec, it borrows the Vec and leaves its allocation
-untouched. For now we'll only implement the "basic" full-range version.
-
-```rust,ignore
-use std::marker::PhantomData;
-
-struct Drain<'a, T: 'a> {
-    // Need to bound the lifetime here, so we do it with `&'a mut Vec<T>`
-    // because that's semantically what we contain. We're "just" calling
-    // `pop()` and `remove(0)`.
-    vec: PhantomData<&'a mut Vec<T>>,
-    start: *const T,
-    end: *const T,
-}
-
-impl<'a, T> Iterator for Drain<'a, T> {
-    type Item = T;
-    fn next(&mut self) -> Option<T> {
-        if self.start == self.end {
-            None
-```
-
--- wait, this is seeming familiar. Let's do some more compression. Both
-IntoIter and Drain have the exact same structure, let's just factor it out.
-
-```rust,ignore
-struct RawValIter<T> {
-    start: *const T,
-    end: *const T,
-}
-
-impl<T> RawValIter<T> {
-    // unsafe to construct because it has no associated lifetimes.
-    // This is necessary to store a RawValIter in the same struct as
-    // its actual allocation. OK since it's a private implementation
-    // detail.
-    unsafe fn new(slice: &[T]) -> Self {
-        RawValIter {
-            start: slice.as_ptr(),
-            end: if slice.len() == 0 {
-                // if `len = 0`, then this is not actually allocated memory.
-                // Need to avoid offsetting because that will give wrong
-                // information to LLVM via GEP.
-                slice.as_ptr()
-            } else {
-                slice.as_ptr().add(slice.len())
-            }
-        }
-    }
-}
-
-// Iterator and DoubleEndedIterator impls identical to IntoIter.
-```
-
-And IntoIter becomes the following:
-
-```rust,ignore
-pub struct IntoIter<T> {
-    _buf: RawVec<T>, // we don't actually care about this. Just need it to live.
-    iter: RawValIter<T>,
-}
-
-impl<T> Iterator for IntoIter<T> {
-    type Item = T;
-    fn next(&mut self) -> Option<T> { self.iter.next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
-}
-
-impl<T> DoubleEndedIterator for IntoIter<T> {
-    fn next_back(&mut self) -> Option<T> { self.iter.next_back() }
-}
-
-impl<T> Drop for IntoIter<T> {
-    fn drop(&mut self) {
-        for _ in &mut *self {}
-    }
-}
-
-impl<T> Vec<T> {
-    pub fn into_iter(self) -> IntoIter<T> {
-        unsafe {
-            let iter = RawValIter::new(&self);
-
-            let buf = ptr::read(&self.buf);
-            mem::forget(self);
-
-            IntoIter {
-                iter: iter,
-                _buf: buf,
-            }
-        }
-    }
-}
-```
-
-Note that I've left a few quirks in this design to make upgrading Drain to work
-with arbitrary subranges a bit easier. In particular we *could* have RawValIter
-drain itself on drop, but that won't work right for a more complex Drain.
-We also take a slice to simplify Drain initialization.
-
-Alright, now Drain is really easy:
-
-```rust,ignore
-use std::marker::PhantomData;
-
-pub struct Drain<'a, T: 'a> {
-    vec: PhantomData<&'a mut Vec<T>>,
-    iter: RawValIter<T>,
-}
-
-impl<'a, T> Iterator for Drain<'a, T> {
-    type Item = T;
-    fn next(&mut self) -> Option<T> { self.iter.next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
-}
-
-impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
-    fn next_back(&mut self) -> Option<T> { self.iter.next_back() }
-}
-
-impl<'a, T> Drop for Drain<'a, T> {
-    fn drop(&mut self) {
-        for _ in &mut *self {}
-    }
-}
-
-impl<T> Vec<T> {
-    pub fn drain(&mut self) -> Drain<T> {
-        unsafe {
-            let iter = RawValIter::new(&self);
-
-            // this is a mem::forget safety thing. If Drain is forgotten, we just
-            // leak the whole Vec's contents. Also we need to do this *eventually*
-            // anyway, so why not do it now?
-            self.len = 0;
-
-            Drain {
-                iter: iter,
-                vec: PhantomData,
-            }
-        }
-    }
-}
-```
-
-For more details on the `mem::forget` problem, see the
-[section on leaks][leaks].
-
-[leaks]: leaking.html
diff --git a/src/doc/nomicon/src/vec-final.md b/src/doc/nomicon/src/vec-final.md
deleted file mode 100644 (file)
index 786cfab..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
-# The Final Code
-
-```rust
-use std::alloc::{self, Layout};
-use std::marker::PhantomData;
-use std::mem;
-use std::ops::{Deref, DerefMut};
-use std::ptr::{self, NonNull};
-
-struct RawVec<T> {
-    ptr: NonNull<T>,
-    cap: usize,
-    _marker: PhantomData<T>,
-}
-
-unsafe impl<T: Send> Send for RawVec<T> {}
-unsafe impl<T: Sync> Sync for RawVec<T> {}
-
-impl<T> RawVec<T> {
-    fn new() -> Self {
-        // !0 is usize::MAX. This branch should be stripped at compile time.
-        let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
-
-        // `NonNull::dangling()` doubles as "unallocated" and "zero-sized allocation"
-        RawVec {
-            ptr: NonNull::dangling(),
-            cap: cap,
-            _marker: PhantomData,
-        }
-    }
-
-    fn grow(&mut self) {
-        // since we set the capacity to usize::MAX when T has size 0,
-        // getting to here necessarily means the Vec is overfull.
-        assert!(mem::size_of::<T>() != 0, "capacity overflow");
-
-        let (new_cap, new_layout) = if self.cap == 0 {
-            (1, Layout::array::<T>(1).unwrap())
-        } else {
-            // This can't overflow because we ensure self.cap <= isize::MAX.
-            let new_cap = 2 * self.cap;
-
-            // `Layout::array` checks that the number of bytes is <= usize::MAX,
-            // but this is redundant since old_layout.size() <= isize::MAX,
-            // so the `unwrap` should never fail.
-            let new_layout = Layout::array::<T>(new_cap).unwrap();
-            (new_cap, new_layout)
-        };
-
-        // Ensure that the new allocation doesn't exceed `isize::MAX` bytes.
-        assert!(
-            new_layout.size() <= isize::MAX as usize,
-            "Allocation too large"
-        );
-
-        let new_ptr = if self.cap == 0 {
-            unsafe { alloc::alloc(new_layout) }
-        } else {
-            let old_layout = Layout::array::<T>(self.cap).unwrap();
-            let old_ptr = self.ptr.as_ptr() as *mut u8;
-            unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) }
-        };
-
-        // If allocation fails, `new_ptr` will be null, in which case we abort.
-        self.ptr = match NonNull::new(new_ptr as *mut T) {
-            Some(p) => p,
-            None => alloc::handle_alloc_error(new_layout),
-        };
-        self.cap = new_cap;
-    }
-}
-
-impl<T> Drop for RawVec<T> {
-    fn drop(&mut self) {
-        let elem_size = mem::size_of::<T>();
-
-        if self.cap != 0 && elem_size != 0 {
-            unsafe {
-                alloc::dealloc(
-                    self.ptr.as_ptr() as *mut u8,
-                    Layout::array::<T>(self.cap).unwrap(),
-                );
-            }
-        }
-    }
-}
-
-pub struct Vec<T> {
-    buf: RawVec<T>,
-    len: usize,
-}
-
-impl<T> Vec<T> {
-    fn ptr(&self) -> *mut T {
-        self.buf.ptr.as_ptr()
-    }
-
-    fn cap(&self) -> usize {
-        self.buf.cap
-    }
-
-    pub fn new() -> Self {
-        Vec {
-            buf: RawVec::new(),
-            len: 0,
-        }
-    }
-    pub fn push(&mut self, elem: T) {
-        if self.len == self.cap() {
-            self.buf.grow();
-        }
-
-        unsafe {
-            ptr::write(self.ptr().add(self.len), elem);
-        }
-
-        // Can't overflow, we'll OOM first.
-        self.len += 1;
-    }
-
-    pub fn pop(&mut self) -> Option<T> {
-        if self.len == 0 {
-            None
-        } else {
-            self.len -= 1;
-            unsafe { Some(ptr::read(self.ptr().add(self.len))) }
-        }
-    }
-
-    pub fn insert(&mut self, index: usize, elem: T) {
-        assert!(index <= self.len, "index out of bounds");
-        if self.cap() == self.len {
-            self.buf.grow();
-        }
-
-        unsafe {
-            ptr::copy(
-                self.ptr().add(index),
-                self.ptr().add(index + 1),
-                self.len - index,
-            );
-            ptr::write(self.ptr().add(index), elem);
-            self.len += 1;
-        }
-    }
-
-    pub fn remove(&mut self, index: usize) -> T {
-        assert!(index < self.len, "index out of bounds");
-        unsafe {
-            self.len -= 1;
-            let result = ptr::read(self.ptr().add(index));
-            ptr::copy(
-                self.ptr().add(index + 1),
-                self.ptr().add(index),
-                self.len - index,
-            );
-            result
-        }
-    }
-
-    pub fn into_iter(self) -> IntoIter<T> {
-        unsafe {
-            let iter = RawValIter::new(&self);
-            let buf = ptr::read(&self.buf);
-            mem::forget(self);
-
-            IntoIter {
-                iter: iter,
-                _buf: buf,
-            }
-        }
-    }
-
-    pub fn drain(&mut self) -> Drain<T> {
-        unsafe {
-            let iter = RawValIter::new(&self);
-
-            // this is a mem::forget safety thing. If Drain is forgotten, we just
-            // leak the whole Vec's contents. Also we need to do this *eventually*
-            // anyway, so why not do it now?
-            self.len = 0;
-
-            Drain {
-                iter: iter,
-                vec: PhantomData,
-            }
-        }
-    }
-}
-
-impl<T> Drop for Vec<T> {
-    fn drop(&mut self) {
-        while let Some(_) = self.pop() {}
-        // deallocation is handled by RawVec
-    }
-}
-
-impl<T> Deref for Vec<T> {
-    type Target = [T];
-    fn deref(&self) -> &[T] {
-        unsafe { std::slice::from_raw_parts(self.ptr(), self.len) }
-    }
-}
-
-impl<T> DerefMut for Vec<T> {
-    fn deref_mut(&mut self) -> &mut [T] {
-        unsafe { std::slice::from_raw_parts_mut(self.ptr(), self.len) }
-    }
-}
-
-struct RawValIter<T> {
-    start: *const T,
-    end: *const T,
-}
-
-impl<T> RawValIter<T> {
-    unsafe fn new(slice: &[T]) -> Self {
-        RawValIter {
-            start: slice.as_ptr(),
-            end: if mem::size_of::<T>() == 0 {
-                ((slice.as_ptr() as usize) + slice.len()) as *const _
-            } else if slice.len() == 0 {
-                slice.as_ptr()
-            } else {
-                slice.as_ptr().add(slice.len())
-            },
-        }
-    }
-}
-
-impl<T> Iterator for RawValIter<T> {
-    type Item = T;
-    fn next(&mut self) -> Option<T> {
-        if self.start == self.end {
-            None
-        } else {
-            unsafe {
-                let result = ptr::read(self.start);
-                self.start = if mem::size_of::<T>() == 0 {
-                    (self.start as usize + 1) as *const _
-                } else {
-                    self.start.offset(1)
-                };
-                Some(result)
-            }
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let elem_size = mem::size_of::<T>();
-        let len = (self.end as usize - self.start as usize) /
-                  if elem_size == 0 { 1 } else { elem_size };
-        (len, Some(len))
-    }
-}
-
-impl<T> DoubleEndedIterator for RawValIter<T> {
-    fn next_back(&mut self) -> Option<T> {
-        if self.start == self.end {
-            None
-        } else {
-            unsafe {
-                self.end = if mem::size_of::<T>() == 0 {
-                    (self.end as usize - 1) as *const _
-                } else {
-                    self.end.offset(-1)
-                };
-                Some(ptr::read(self.end))
-            }
-        }
-    }
-}
-
-pub struct IntoIter<T> {
-    _buf: RawVec<T>, // we don't actually care about this. Just need it to live.
-    iter: RawValIter<T>,
-}
-
-impl<T> Iterator for IntoIter<T> {
-    type Item = T;
-    fn next(&mut self) -> Option<T> {
-        self.iter.next()
-    }
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-impl<T> DoubleEndedIterator for IntoIter<T> {
-    fn next_back(&mut self) -> Option<T> {
-        self.iter.next_back()
-    }
-}
-
-impl<T> Drop for IntoIter<T> {
-    fn drop(&mut self) {
-        for _ in &mut *self {}
-    }
-}
-
-pub struct Drain<'a, T: 'a> {
-    vec: PhantomData<&'a mut Vec<T>>,
-    iter: RawValIter<T>,
-}
-
-impl<'a, T> Iterator for Drain<'a, T> {
-    type Item = T;
-    fn next(&mut self) -> Option<T> {
-        self.iter.next()
-    }
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
-    fn next_back(&mut self) -> Option<T> {
-        self.iter.next_back()
-    }
-}
-
-impl<'a, T> Drop for Drain<'a, T> {
-    fn drop(&mut self) {
-        // pre-drain the iter
-        for _ in &mut *self {}
-    }
-}
-#
-# fn main() {
-#     tests::create_push_pop();
-#     tests::iter_test();
-#     tests::test_drain();
-#     tests::test_zst();
-#     println!("All tests finished OK");
-# }
-#
-# mod tests {
-#     use super::*;
-#
-#     pub fn create_push_pop() {
-#         let mut v = Vec::new();
-#         v.push(1);
-#         assert_eq!(1, v.len());
-#         assert_eq!(1, v[0]);
-#         for i in v.iter_mut() {
-#             *i += 1;
-#         }
-#         v.insert(0, 5);
-#         let x = v.pop();
-#         assert_eq!(Some(2), x);
-#         assert_eq!(1, v.len());
-#         v.push(10);
-#         let x = v.remove(0);
-#         assert_eq!(5, x);
-#         assert_eq!(1, v.len());
-#     }
-#
-#     pub fn iter_test() {
-#         let mut v = Vec::new();
-#         for i in 0..10 {
-#             v.push(Box::new(i))
-#         }
-#         let mut iter = v.into_iter();
-#         let first = iter.next().unwrap();
-#         let last = iter.next_back().unwrap();
-#         drop(iter);
-#         assert_eq!(0, *first);
-#         assert_eq!(9, *last);
-#     }
-#
-#     pub fn test_drain() {
-#         let mut v = Vec::new();
-#         for i in 0..10 {
-#             v.push(Box::new(i))
-#         }
-#         {
-#             let mut drain = v.drain();
-#             let first = drain.next().unwrap();
-#             let last = drain.next_back().unwrap();
-#             assert_eq!(0, *first);
-#             assert_eq!(9, *last);
-#         }
-#         assert_eq!(0, v.len());
-#         v.push(Box::new(1));
-#         assert_eq!(1, *v.pop().unwrap());
-#     }
-#
-#     pub fn test_zst() {
-#         let mut v = Vec::new();
-#         for _i in 0..10 {
-#             v.push(())
-#         }
-#
-#         let mut count = 0;
-#
-#         for _ in v.into_iter() {
-#             count += 1
-#         }
-#
-#         assert_eq!(10, count);
-#     }
-# }
-```
diff --git a/src/doc/nomicon/src/vec-insert-remove.md b/src/doc/nomicon/src/vec-insert-remove.md
deleted file mode 100644 (file)
index 9138b3e..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-# Insert and Remove
-
-Something *not* provided by slice is `insert` and `remove`, so let's do those
-next.
-
-Insert needs to shift all the elements at the target index to the right by one.
-To do this we need to use `ptr::copy`, which is our version of C's `memmove`.
-This copies some chunk of memory from one location to another, correctly
-handling the case where the source and destination overlap (which will
-definitely happen here).
-
-If we insert at index `i`, we want to shift the `[i .. len]` to `[i+1 .. len+1]`
-using the old len.
-
-```rust,ignore
-pub fn insert(&mut self, index: usize, elem: T) {
-    // Note: `<=` because it's valid to insert after everything
-    // which would be equivalent to push.
-    assert!(index <= self.len, "index out of bounds");
-    if self.cap == self.len { self.grow(); }
-
-    unsafe {
-        // ptr::copy(src, dest, len): "copy from src to dest len elems"
-        ptr::copy(self.ptr.as_ptr().add(index),
-                  self.ptr.as_ptr().add(index + 1),
-                  self.len - index);
-        ptr::write(self.ptr.as_ptr().add(index), elem);
-        self.len += 1;
-    }
-}
-```
-
-Remove behaves in the opposite manner. We need to shift all the elements from
-`[i+1 .. len + 1]` to `[i .. len]` using the *new* len.
-
-```rust,ignore
-pub fn remove(&mut self, index: usize) -> T {
-    // Note: `<` because it's *not* valid to remove after everything
-    assert!(index < self.len, "index out of bounds");
-    unsafe {
-        self.len -= 1;
-        let result = ptr::read(self.ptr.as_ptr().add(index));
-        ptr::copy(self.ptr.as_ptr().add(index + 1),
-                  self.ptr.as_ptr().add(index),
-                  self.len - index);
-        result
-    }
-}
-```
diff --git a/src/doc/nomicon/src/vec-into-iter.md b/src/doc/nomicon/src/vec-into-iter.md
deleted file mode 100644 (file)
index 03c2a9d..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-# IntoIter
-
-Let's move on to writing iterators. `iter` and `iter_mut` have already been
-written for us thanks to The Magic of Deref. However there's two interesting
-iterators that Vec provides that slices can't: `into_iter` and `drain`.
-
-IntoIter consumes the Vec by-value, and can consequently yield its elements
-by-value. In order to enable this, IntoIter needs to take control of Vec's
-allocation.
-
-IntoIter needs to be DoubleEnded as well, to enable reading from both ends.
-Reading from the back could just be implemented as calling `pop`, but reading
-from the front is harder. We could call `remove(0)` but that would be insanely
-expensive. Instead we're going to just use ptr::read to copy values out of
-either end of the Vec without mutating the buffer at all.
-
-To do this we're going to use a very common C idiom for array iteration. We'll
-make two pointers; one that points to the start of the array, and one that
-points to one-element past the end. When we want an element from one end, we'll
-read out the value pointed to at that end and move the pointer over by one. When
-the two pointers are equal, we know we're done.
-
-Note that the order of read and offset are reversed for `next` and `next_back`
-For `next_back` the pointer is always after the element it wants to read next,
-while for `next` the pointer is always at the element it wants to read next.
-To see why this is, consider the case where every element but one has been
-yielded.
-
-The array looks like this:
-
-```text
-          S  E
-[X, X, X, O, X, X, X]
-```
-
-If E pointed directly at the element it wanted to yield next, it would be
-indistinguishable from the case where there are no more elements to yield.
-
-Although we don't actually care about it during iteration, we also need to hold
-onto the Vec's allocation information in order to free it once IntoIter is
-dropped.
-
-So we're going to use the following struct:
-
-```rust,ignore
-pub struct IntoIter<T> {
-    buf: NonNull<T>,
-    cap: usize,
-    start: *const T,
-    end: *const T,
-    _marker: PhantomData<T>,
-}
-```
-
-And this is what we end up with for initialization:
-
-```rust,ignore
-impl<T> Vec<T> {
-    pub fn into_iter(self) -> IntoIter<T> {
-        // Can't destructure Vec since it's Drop
-        let ptr = self.ptr;
-        let cap = self.cap;
-        let len = self.len;
-
-        // Make sure not to drop Vec since that will free the buffer
-        mem::forget(self);
-
-        unsafe {
-            IntoIter {
-                buf: ptr,
-                cap: cap,
-                start: ptr.as_ptr(),
-                end: if cap == 0 {
-                    // can't offset off this pointer, it's not allocated!
-                    ptr.as_ptr()
-                } else {
-                    ptr.as_ptr().add(len)
-                },
-                _marker: PhantomData,
-            }
-        }
-    }
-}
-```
-
-Here's iterating forward:
-
-```rust,ignore
-impl<T> Iterator for IntoIter<T> {
-    type Item = T;
-    fn next(&mut self) -> Option<T> {
-        if self.start == self.end {
-            None
-        } else {
-            unsafe {
-                let result = ptr::read(self.start);
-                self.start = self.start.offset(1);
-                Some(result)
-            }
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let len = (self.end as usize - self.start as usize)
-                  / mem::size_of::<T>();
-        (len, Some(len))
-    }
-}
-```
-
-And here's iterating backwards.
-
-```rust,ignore
-impl<T> DoubleEndedIterator for IntoIter<T> {
-    fn next_back(&mut self) -> Option<T> {
-        if self.start == self.end {
-            None
-        } else {
-            unsafe {
-                self.end = self.end.offset(-1);
-                Some(ptr::read(self.end))
-            }
-        }
-    }
-}
-```
-
-Because IntoIter takes ownership of its allocation, it needs to implement Drop
-to free it. However it also wants to implement Drop to drop any elements it
-contains that weren't yielded.
-
-
-```rust,ignore
-impl<T> Drop for IntoIter<T> {
-    fn drop(&mut self) {
-        if self.cap != 0 {
-            // drop any remaining elements
-            for _ in &mut *self {}
-            let layout = Layout::array::<T>(self.cap).unwrap();
-            unsafe {
-                alloc::dealloc(self.buf.as_ptr() as *mut u8, layout);
-            }
-        }
-    }
-}
-```
diff --git a/src/doc/nomicon/src/vec-layout.md b/src/doc/nomicon/src/vec-layout.md
deleted file mode 100644 (file)
index 20e2306..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-# Layout
-
-First off, we need to come up with the struct layout. A Vec has three parts:
-a pointer to the allocation, the size of the allocation, and the number of
-elements that have been initialized.
-
-Naively, this means we just want this design:
-
-```rust,ignore
-pub struct Vec<T> {
-    ptr: *mut T,
-    cap: usize,
-    len: usize,
-}
-```
-
-And indeed this would compile. Unfortunately, it would be incorrect. First, the
-compiler will give us too strict variance. So a `&Vec<&'static str>`
-couldn't be used where an `&Vec<&'a str>` was expected. More importantly, it
-will give incorrect ownership information to the drop checker, as it will
-conservatively assume we don't own any values of type `T`. See [the chapter
-on ownership and lifetimes][ownership] for all the details on variance and
-drop check.
-
-As we saw in the ownership chapter, the standard library uses `Unique<T>` in place of
-`*mut T` when it has a raw pointer to an allocation that it owns. Unique is unstable,
-so we'd like to not use it if possible, though.
-
-As a recap, Unique is a wrapper around a raw pointer that declares that:
-
-* We are covariant over `T`
-* We may own a value of type `T` (for drop check)
-* We are Send/Sync if `T` is Send/Sync
-* Our pointer is never null (so `Option<Vec<T>>` is null-pointer-optimized)
-
-We can implement all of the above requirements in stable Rust. To do this, instead
-of using `Unique<T>` we will use [`NonNull<T>`][NonNull], another wrapper around a
-raw pointer, which gives us two of the above properties, namely it is covariant
-over `T` and is declared to never be null. By adding a `PhantomData<T>` (for drop
-check) and implementing Send/Sync if `T` is, we get the same results as using
-`Unique<T>`:
-
-```rust
-use std::ptr::NonNull;
-use std::marker::PhantomData;
-
-pub struct Vec<T> {
-    ptr: NonNull<T>,
-    cap: usize,
-    len: usize,
-    _marker: PhantomData<T>,
-}
-
-unsafe impl<T: Send> Send for Vec<T> {}
-unsafe impl<T: Sync> Sync for Vec<T> {}
-# fn main() {}
-```
-
-[ownership]: ownership.html
-[NonNull]: ../std/ptr/struct.NonNull.html
diff --git a/src/doc/nomicon/src/vec-push-pop.md b/src/doc/nomicon/src/vec-push-pop.md
deleted file mode 100644 (file)
index 2366e36..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-# Push and Pop
-
-Alright. We can initialize. We can allocate. Let's actually implement some
-functionality! Let's start with `push`. All it needs to do is check if we're
-full to grow, unconditionally write to the next index, and then increment our
-length.
-
-To do the write we have to be careful not to evaluate the memory we want to write
-to. At worst, it's truly uninitialized memory from the allocator. At best it's the
-bits of some old value we popped off. Either way, we can't just index to the memory
-and dereference it, because that will evaluate the memory as a valid instance of
-T. Worse, `foo[idx] = x` will try to call `drop` on the old value of `foo[idx]`!
-
-The correct way to do this is with `ptr::write`, which just blindly overwrites the
-target address with the bits of the value we provide. No evaluation involved.
-
-For `push`, if the old len (before push was called) is 0, then we want to write
-to the 0th index. So we should offset by the old len.
-
-```rust,ignore
-pub fn push(&mut self, elem: T) {
-    if self.len == self.cap { self.grow(); }
-
-    unsafe {
-        ptr::write(self.ptr.as_ptr().add(self.len), elem);
-    }
-
-    // Can't fail, we'll OOM first.
-    self.len += 1;
-}
-```
-
-Easy! How about `pop`? Although this time the index we want to access is
-initialized, Rust won't just let us dereference the location of memory to move
-the value out, because that would leave the memory uninitialized! For this we
-need `ptr::read`, which just copies out the bits from the target address and
-interprets it as a value of type T. This will leave the memory at this address
-logically uninitialized, even though there is in fact a perfectly good instance
-of T there.
-
-For `pop`, if the old len is 1, we want to read out of the 0th index. So we
-should offset by the new len.
-
-```rust,ignore
-pub fn pop(&mut self) -> Option<T> {
-    if self.len == 0 {
-        None
-    } else {
-        self.len -= 1;
-        unsafe {
-            Some(ptr::read(self.ptr.as_ptr().add(self.len)))
-        }
-    }
-}
-```
diff --git a/src/doc/nomicon/src/vec-raw.md b/src/doc/nomicon/src/vec-raw.md
deleted file mode 100644 (file)
index 3fb62b7..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-# RawVec
-
-We've actually reached an interesting situation here: we've duplicated the logic
-for specifying a buffer and freeing its memory in Vec and IntoIter. Now that
-we've implemented it and identified *actual* logic duplication, this is a good
-time to perform some logic compression.
-
-We're going to abstract out the `(ptr, cap)` pair and give them the logic for
-allocating, growing, and freeing:
-
-```rust,ignore
-struct RawVec<T> {
-    ptr: NonNull<T>,
-    cap: usize,
-    _marker: PhantomData<T>,
-}
-
-unsafe impl<T: Send> Send for RawVec<T> {}
-unsafe impl<T: Sync> Sync for RawVec<T> {}
-
-impl<T> RawVec<T> {
-    fn new() -> Self {
-        assert!(mem::size_of::<T>() != 0, "TODO: implement ZST support");
-        RawVec {
-            ptr: NonNull::dangling(),
-            cap: 0,
-            _marker: PhantomData,
-        }
-    }
-
-    fn grow(&mut self) {
-        let (new_cap, new_layout) = if self.cap == 0 {
-            (1, Layout::array::<T>(1).unwrap())
-        } else {
-            // This can't overflow because we ensure self.cap <= isize::MAX.
-            let new_cap = 2 * self.cap;
-
-            // Layout::array checks that the number of bytes is <= usize::MAX,
-            // but this is redundant since old_layout.size() <= isize::MAX,
-            // so the `unwrap` should never fail.
-            let new_layout = Layout::array::<T>(new_cap).unwrap();
-            (new_cap, new_layout)
-        };
-
-        // Ensure that the new allocation doesn't exceed `isize::MAX` bytes.
-        assert!(new_layout.size() <= isize::MAX as usize, "Allocation too large");
-
-        let new_ptr = if self.cap == 0 {
-            unsafe { alloc::alloc(new_layout) }
-        } else {
-            let old_layout = Layout::array::<T>(self.cap).unwrap();
-            let old_ptr = self.ptr.as_ptr() as *mut u8;
-            unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) }
-        };
-
-        // If allocation fails, `new_ptr` will be null, in which case we abort.
-        self.ptr = match NonNull::new(new_ptr as *mut T) {
-            Some(p) => p,
-            None => alloc::handle_alloc_error(new_layout),
-        };
-        self.cap = new_cap;
-    }
-}
-
-impl<T> Drop for RawVec<T> {
-    fn drop(&mut self) {
-        if self.cap != 0 {
-            let layout = Layout::array::<T>(self.cap).unwrap();
-            unsafe {
-                alloc::dealloc(self.ptr.as_ptr() as *mut u8, layout);
-            }
-        }
-    }
-}
-```
-
-And change Vec as follows:
-
-```rust,ignore
-pub struct Vec<T> {
-    buf: RawVec<T>,
-    len: usize,
-}
-
-impl<T> Vec<T> {
-    fn ptr(&self) -> *mut T {
-        self.buf.ptr.as_ptr()
-    }
-
-    fn cap(&self) -> usize {
-        self.buf.cap
-    }
-
-    pub fn new() -> Self {
-        Vec {
-            buf: RawVec::new(),
-            len: 0,
-        }
-    }
-
-    // push/pop/insert/remove largely unchanged:
-    // * `self.ptr.as_ptr() -> self.ptr()`
-    // * `self.cap -> self.cap()`
-    // * `self.grow() -> self.buf.grow()`
-}
-
-impl<T> Drop for Vec<T> {
-    fn drop(&mut self) {
-        while let Some(_) = self.pop() {}
-        // deallocation is handled by RawVec
-    }
-}
-```
-
-And finally we can really simplify IntoIter:
-
-```rust,ignore
-pub struct IntoIter<T> {
-    _buf: RawVec<T>, // we don't actually care about this. Just need it to live.
-    start: *const T,
-    end: *const T,
-}
-
-// next and next_back literally unchanged since they never referred to the buf
-
-impl<T> Drop for IntoIter<T> {
-    fn drop(&mut self) {
-        // only need to ensure all our elements are read;
-        // buffer will clean itself up afterwards.
-        for _ in &mut *self {}
-    }
-}
-
-impl<T> Vec<T> {
-    pub fn into_iter(self) -> IntoIter<T> {
-        unsafe {
-            // need to use ptr::read to unsafely move the buf out since it's
-            // not Copy, and Vec implements Drop (so we can't destructure it).
-            let buf = ptr::read(&self.buf);
-            let len = self.len;
-            mem::forget(self);
-
-            IntoIter {
-                start: buf.ptr.as_ptr(),
-                end: buf.ptr.as_ptr().add(len),
-                _buf: buf,
-            }
-        }
-    }
-}
-```
-
-Much better.
diff --git a/src/doc/nomicon/src/vec-zsts.md b/src/doc/nomicon/src/vec-zsts.md
deleted file mode 100644 (file)
index d1b8fe8..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-# Handling Zero-Sized Types
-
-It's time. We're going to fight the specter that is zero-sized types. Safe Rust
-*never* needs to care about this, but Vec is very intensive on raw pointers and
-raw allocations, which are exactly the two things that care about
-zero-sized types. We need to be careful of two things:
-
-* The raw allocator API has undefined behavior if you pass in 0 for an
-  allocation size.
-* raw pointer offsets are no-ops for zero-sized types, which will break our
-  C-style pointer iterator.
-
-Thankfully we abstracted out pointer-iterators and allocating handling into
-`RawValIter` and `RawVec` respectively. How mysteriously convenient.
-
-
-
-
-## Allocating Zero-Sized Types
-
-So if the allocator API doesn't support zero-sized allocations, what on earth
-do we store as our allocation? `NonNull::dangling()` of course! Almost every operation
-with a ZST is a no-op since ZSTs have exactly one value, and therefore no state needs
-to be considered to store or load them. This actually extends to `ptr::read` and
-`ptr::write`: they won't actually look at the pointer at all. As such we never need
-to change the pointer.
-
-Note however that our previous reliance on running out of memory before overflow is
-no longer valid with zero-sized types. We must explicitly guard against capacity
-overflow for zero-sized types.
-
-Due to our current architecture, all this means is writing 3 guards, one in each
-method of `RawVec`.
-
-```rust,ignore
-impl<T> RawVec<T> {
-    fn new() -> Self {
-        // !0 is usize::MAX. This branch should be stripped at compile time.
-        let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
-
-        // `NonNull::dangling()` doubles as "unallocated" and "zero-sized allocation"
-        RawVec {
-            ptr: NonNull::dangling(),
-            cap: cap,
-            _marker: PhantomData,
-        }
-    }
-
-    fn grow(&mut self) {
-        // since we set the capacity to usize::MAX when T has size 0,
-        // getting to here necessarily means the Vec is overfull.
-        assert!(mem::size_of::<T>() != 0, "capacity overflow");
-
-        let (new_cap, new_layout) = if self.cap == 0 {
-            (1, Layout::array::<T>(1).unwrap())
-        } else {
-            // This can't overflow because we ensure self.cap <= isize::MAX.
-            let new_cap = 2 * self.cap;
-
-            // `Layout::array` checks that the number of bytes is <= usize::MAX,
-            // but this is redundant since old_layout.size() <= isize::MAX,
-            // so the `unwrap` should never fail.
-            let new_layout = Layout::array::<T>(new_cap).unwrap();
-            (new_cap, new_layout)
-        };
-
-        // Ensure that the new allocation doesn't exceed `isize::MAX` bytes.
-        assert!(new_layout.size() <= isize::MAX as usize, "Allocation too large");
-
-        let new_ptr = if self.cap == 0 {
-            unsafe { alloc::alloc(new_layout) }
-        } else {
-            let old_layout = Layout::array::<T>(self.cap).unwrap();
-            let old_ptr = self.ptr.as_ptr() as *mut u8;
-            unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) }
-        };
-
-        // If allocation fails, `new_ptr` will be null, in which case we abort.
-        self.ptr = match NonNull::new(new_ptr as *mut T) {
-            Some(p) => p,
-            None => alloc::handle_alloc_error(new_layout),
-        };
-        self.cap = new_cap;
-    }
-}
-
-impl<T> Drop for RawVec<T> {
-    fn drop(&mut self) {
-        let elem_size = mem::size_of::<T>();
-
-        if self.cap != 0 && elem_size != 0 {
-            unsafe {
-                alloc::dealloc(
-                    self.ptr.as_ptr() as *mut u8,
-                    Layout::array::<T>(self.cap).unwrap(),
-                );
-            }
-        }
-    }
-}
-```
-
-That's it. We support pushing and popping zero-sized types now. Our iterators
-(that aren't provided by slice Deref) are still busted, though.
-
-
-
-
-## Iterating Zero-Sized Types
-
-Zero-sized offsets are no-ops. This means that our current design will always
-initialize `start` and `end` as the same value, and our iterators will yield
-nothing. The current solution to this is to cast the pointers to integers,
-increment, and then cast them back:
-
-```rust,ignore
-impl<T> RawValIter<T> {
-    unsafe fn new(slice: &[T]) -> Self {
-        RawValIter {
-            start: slice.as_ptr(),
-            end: if mem::size_of::<T>() == 0 {
-                ((slice.as_ptr() as usize) + slice.len()) as *const _
-            } else if slice.len() == 0 {
-                slice.as_ptr()
-            } else {
-                slice.as_ptr().add(slice.len())
-            },
-        }
-    }
-}
-```
-
-Now we have a different bug. Instead of our iterators not running at all, our
-iterators now run *forever*. We need to do the same trick in our iterator impls.
-Also, our size_hint computation code will divide by 0 for ZSTs. Since we'll
-basically be treating the two pointers as if they point to bytes, we'll just
-map size 0 to divide by 1.
-
-```rust,ignore
-impl<T> Iterator for RawValIter<T> {
-    type Item = T;
-    fn next(&mut self) -> Option<T> {
-        if self.start == self.end {
-            None
-        } else {
-            unsafe {
-                let result = ptr::read(self.start);
-                self.start = if mem::size_of::<T>() == 0 {
-                    (self.start as usize + 1) as *const _
-                } else {
-                    self.start.offset(1)
-                };
-                Some(result)
-            }
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let elem_size = mem::size_of::<T>();
-        let len = (self.end as usize - self.start as usize)
-                  / if elem_size == 0 { 1 } else { elem_size };
-        (len, Some(len))
-    }
-}
-
-impl<T> DoubleEndedIterator for RawValIter<T> {
-    fn next_back(&mut self) -> Option<T> {
-        if self.start == self.end {
-            None
-        } else {
-            unsafe {
-                self.end = if mem::size_of::<T>() == 0 {
-                    (self.end as usize - 1) as *const _
-                } else {
-                    self.end.offset(-1)
-                };
-                Some(ptr::read(self.end))
-            }
-        }
-    }
-}
-```
-
-And that's it. Iteration works!
diff --git a/src/doc/nomicon/src/vec.md b/src/doc/nomicon/src/vec.md
deleted file mode 100644 (file)
index b033863..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-# Example: Implementing Vec
-
-To bring everything together, we're going to write `std::Vec` from scratch.
-We will limit ourselves to stable Rust. In particular we won't use any
-intrinsics that could make our code a little bit nicer or efficient because
-intrinsics are permanently unstable. Although many intrinsics *do* become
-stabilized elsewhere (`std::ptr` and `std::mem` consist of many intrinsics).
-
-Ultimately this means our implementation may not take advantage of all
-possible optimizations, though it will be by no means *naive*. We will
-definitely get into the weeds over nitty-gritty details, even
-when the problem doesn't *really* merit it.
-
-You wanted advanced. We're gonna go advanced.
diff --git a/src/doc/nomicon/src/vec/vec-alloc.md b/src/doc/nomicon/src/vec/vec-alloc.md
new file mode 100644 (file)
index 0000000..b301fc6
--- /dev/null
@@ -0,0 +1,213 @@
+# Allocating Memory
+
+Using `NonNull` throws a wrench in an important feature of Vec (and indeed all of
+the std collections): creating an empty Vec doesn't actually allocate at all. This
+is not the same as allocating a zero-sized memory block, which is not allowed by
+the global allocator (it results in undefined behavior!). So if we can't allocate,
+but also can't put a null pointer in `ptr`, what do we do in `Vec::new`? Well, we
+just put some other garbage in there!
+
+This is perfectly fine because we already have `cap == 0` as our sentinel for no
+allocation. We don't even need to handle it specially in almost any code because
+we usually need to check if `cap > len` or `len > 0` anyway. The recommended
+Rust value to put here is `mem::align_of::<T>()`. `NonNull` provides a convenience
+for this: `NonNull::dangling()`. There are quite a few places where we'll
+want to use `dangling` because there's no real allocation to talk about but
+`null` would make the compiler do bad things.
+
+So:
+
+<!-- ignore: explanation code -->
+```rust,ignore
+use std::mem;
+
+impl<T> Vec<T> {
+    fn new() -> Self {
+        assert!(mem::size_of::<T>() != 0, "We're not ready to handle ZSTs");
+        Vec {
+            ptr: NonNull::dangling(),
+            len: 0,
+            cap: 0,
+            _marker: PhantomData,
+        }
+    }
+}
+# fn main() {}
+```
+
+I slipped in that assert there because zero-sized types will require some
+special handling throughout our code, and I want to defer the issue for now.
+Without this assert, some of our early drafts will do some Very Bad Things.
+
+Next we need to figure out what to actually do when we *do* want space. For that, 
+we use the global allocation functions [`alloc`][alloc], [`realloc`][realloc], 
+and [`dealloc`][dealloc] which are available in stable Rust in 
+[`std::alloc`][std_alloc]. These functions are expected to become deprecated in 
+favor of the methods of [`std::alloc::Global`][Global] after this type is stabilized. 
+
+We'll also need a way to handle out-of-memory (OOM) conditions. The standard
+library provides a function [`alloc::handle_alloc_error`][handle_alloc_error],
+which will abort the program in a platform-specific manner.
+The reason we abort and don't panic is because unwinding can cause allocations
+to happen, and that seems like a bad thing to do when your allocator just came
+back with "hey I don't have any more memory".
+
+Of course, this is a bit silly since most platforms don't actually run out of
+memory in a conventional way. Your operating system will probably kill the
+application by another means if you legitimately start using up all the memory.
+The most likely way we'll trigger OOM is by just asking for ludicrous quantities
+of memory at once (e.g. half the theoretical address space). As such it's
+*probably* fine to panic and nothing bad will happen. Still, we're trying to be
+like the standard library as much as possible, so we'll just kill the whole
+program.
+
+Okay, now we can write growing. Roughly, we want to have this logic:
+
+```text
+if cap == 0:
+    allocate()
+    cap = 1
+else:
+    reallocate()
+    cap *= 2
+```
+
+But Rust's only supported allocator API is so low level that we'll need to do a
+fair bit of extra work. We also need to guard against some special
+conditions that can occur with really large allocations or empty allocations.
+
+In particular, `ptr::offset` will cause us a lot of trouble, because it has
+the semantics of LLVM's GEP inbounds instruction. If you're fortunate enough to
+not have dealt with this instruction, here's the basic story with GEP: alias
+analysis, alias analysis, alias analysis. It's super important to an optimizing
+compiler to be able to reason about data dependencies and aliasing.
+
+As a simple example, consider the following fragment of code:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+*x *= 7;
+*y *= 3;
+```
+
+If the compiler can prove that `x` and `y` point to different locations in
+memory, the two operations can in theory be executed in parallel (by e.g.
+loading them into different registers and working on them independently).
+However the compiler can't do this in general because if x and y point to
+the same location in memory, the operations need to be done to the same value,
+and they can't just be merged afterwards.
+
+When you use GEP inbounds, you are specifically telling LLVM that the offsets
+you're about to do are within the bounds of a single "allocated" entity. The
+ultimate payoff being that LLVM can assume that if two pointers are known to
+point to two disjoint objects, all the offsets of those pointers are *also*
+known to not alias (because you won't just end up in some random place in
+memory). LLVM is heavily optimized to work with GEP offsets, and inbounds
+offsets are the best of all, so it's important that we use them as much as
+possible.
+
+So that's what GEP's about, how can it cause us trouble?
+
+The first problem is that we index into arrays with unsigned integers, but
+GEP (and as a consequence `ptr::offset`) takes a signed integer. This means
+that half of the seemingly valid indices into an array will overflow GEP and
+actually go in the wrong direction! As such we must limit all allocations to
+`isize::MAX` elements. This actually means we only need to worry about
+byte-sized objects, because e.g. `> isize::MAX` `u16`s will truly exhaust all of
+the system's memory. However in order to avoid subtle corner cases where someone
+reinterprets some array of `< isize::MAX` objects as bytes, std limits all
+allocations to `isize::MAX` bytes.
+
+On all 64-bit targets that Rust currently supports we're artificially limited
+to significantly less than all 64 bits of the address space (modern x64
+platforms only expose 48-bit addressing), so we can rely on just running out of
+memory first. However on 32-bit targets, particularly those with extensions to
+use more of the address space (PAE x86 or x32), it's theoretically possible to
+successfully allocate more than `isize::MAX` bytes of memory.
+
+However since this is a tutorial, we're not going to be particularly optimal
+here, and just unconditionally check, rather than use clever platform-specific
+`cfg`s.
+
+The other corner-case we need to worry about is empty allocations. There will
+be two kinds of empty allocations we need to worry about: `cap = 0` for all T,
+and `cap > 0` for zero-sized types.
+
+These cases are tricky because they come
+down to what LLVM means by "allocated". LLVM's notion of an
+allocation is significantly more abstract than how we usually use it. Because
+LLVM needs to work with different languages' semantics and custom allocators,
+it can't really intimately understand allocation. Instead, the main idea behind
+allocation is "doesn't overlap with other stuff". That is, heap allocations,
+stack allocations, and globals don't randomly overlap. Yep, it's about alias
+analysis. As such, Rust can technically play a bit fast and loose with the notion of
+an allocation as long as it's *consistent*.
+
+Getting back to the empty allocation case, there are a couple of places where
+we want to offset by 0 as a consequence of generic code. The question is then:
+is it consistent to do so? For zero-sized types, we have concluded that it is
+indeed consistent to do a GEP inbounds offset by an arbitrary number of
+elements. This is a runtime no-op because every element takes up no space,
+and it's fine to pretend that there's infinite zero-sized types allocated
+at `0x01`. No allocator will ever allocate that address, because they won't
+allocate `0x00` and they generally allocate to some minimal alignment higher
+than a byte. Also generally the whole first page of memory is
+protected from being allocated anyway (a whole 4k, on many platforms).
+
+However what about for positive-sized types? That one's a bit trickier. In
+principle, you can argue that offsetting by 0 gives LLVM no information: either
+there's an element before the address or after it, but it can't know which.
+However we've chosen to conservatively assume that it may do bad things. As
+such we will guard against this case explicitly.
+
+*Phew*
+
+Ok with all the nonsense out of the way, let's actually allocate some memory:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+use std::alloc::{self, Layout};
+
+impl<T> Vec<T> {
+    fn grow(&mut self) {
+        let (new_cap, new_layout) = if self.cap == 0 {
+            (1, Layout::array::<T>(1).unwrap())
+        } else {
+            // This can't overflow since self.cap <= isize::MAX.
+            let new_cap = 2 * self.cap;
+
+            // `Layout::array` checks that the number of bytes is <= usize::MAX,
+            // but this is redundant since old_layout.size() <= isize::MAX,
+            // so the `unwrap` should never fail.
+            let new_layout = Layout::array::<T>(new_cap).unwrap();
+            (new_cap, new_layout)
+        };
+
+        // Ensure that the new allocation doesn't exceed `isize::MAX` bytes.
+        assert!(new_layout.size() <= isize::MAX as usize, "Allocation too large");
+
+        let new_ptr = if self.cap == 0 {
+            unsafe { alloc::alloc(new_layout) }
+        } else {
+            let old_layout = Layout::array::<T>(self.cap).unwrap();
+            let old_ptr = self.ptr.as_ptr() as *mut u8;
+            unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) }
+        };
+
+        // If allocation fails, `new_ptr` will be null, in which case we abort.
+        self.ptr = match NonNull::new(new_ptr as *mut T) {
+            Some(p) => p,
+            None => alloc::handle_alloc_error(new_layout),
+        };
+        self.cap = new_cap;
+    }
+}
+# fn main() {}
+```
+
+[Global]: ../../std/alloc/struct.Global.html
+[handle_alloc_error]: ../../alloc/alloc/fn.handle_alloc_error.html
+[alloc]: ../../alloc/alloc/fn.alloc.html
+[realloc]: ../../alloc/alloc/fn.realloc.html
+[dealloc]: ../../alloc/alloc/fn.dealloc.html
+[std_alloc]: ../../alloc/alloc/index.html
diff --git a/src/doc/nomicon/src/vec/vec-dealloc.md b/src/doc/nomicon/src/vec/vec-dealloc.md
new file mode 100644 (file)
index 0000000..d403f92
--- /dev/null
@@ -0,0 +1,26 @@
+# Deallocating
+
+Next we should implement Drop so that we don't massively leak tons of resources.
+The easiest way is to just call `pop` until it yields None, and then deallocate
+our buffer. Note that calling `pop` is unneeded if `T: !Drop`. In theory we can
+ask Rust if `T` `needs_drop` and omit the calls to `pop`. However in practice
+LLVM is *really* good at removing simple side-effect free code like this, so I
+wouldn't bother unless you notice it's not being stripped (in this case it is).
+
+We must not call `alloc::dealloc` when `self.cap == 0`, as in this case we
+haven't actually allocated any memory.
+
+<!-- ignore: simplified code -->
+```rust,ignore
+impl<T> Drop for Vec<T> {
+    fn drop(&mut self) {
+        if self.cap != 0 {
+            while let Some(_) = self.pop() { }
+            let layout = Layout::array::<T>(self.cap).unwrap();
+            unsafe {
+                alloc::dealloc(self.ptr.as_ptr() as *mut u8, layout);
+            }
+        }
+    }
+}
+```
diff --git a/src/doc/nomicon/src/vec/vec-deref.md b/src/doc/nomicon/src/vec/vec-deref.md
new file mode 100644 (file)
index 0000000..3021cb0
--- /dev/null
@@ -0,0 +1,44 @@
+# Deref
+
+Alright! We've got a decent minimal stack implemented. We can push, we can
+pop, and we can clean up after ourselves. However there's a whole mess of
+functionality we'd reasonably want. In particular, we have a proper array, but
+none of the slice functionality. That's actually pretty easy to solve: we can
+implement `Deref<Target=[T]>`. This will magically make our Vec coerce to, and
+behave like, a slice in all sorts of conditions.
+
+All we need is `slice::from_raw_parts`. It will correctly handle empty slices
+for us. Later once we set up zero-sized type support it will also Just Work
+for those too.
+
+<!-- ignore: simplified code -->
+```rust,ignore
+use std::ops::Deref;
+
+impl<T> Deref for Vec<T> {
+    type Target = [T];
+    fn deref(&self) -> &[T] {
+        unsafe {
+            std::slice::from_raw_parts(self.ptr.as_ptr(), self.len)
+        }
+    }
+}
+```
+
+And let's do DerefMut too:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+use std::ops::DerefMut;
+
+impl<T> DerefMut for Vec<T> {
+    fn deref_mut(&mut self) -> &mut [T] {
+        unsafe {
+            std::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len)
+        }
+    }
+}
+```
+
+Now we have `len`, `first`, `last`, indexing, slicing, sorting, `iter`,
+`iter_mut`, and all other sorts of bells and whistles provided by slice. Sweet!
diff --git a/src/doc/nomicon/src/vec/vec-drain.md b/src/doc/nomicon/src/vec/vec-drain.md
new file mode 100644 (file)
index 0000000..fbc8edd
--- /dev/null
@@ -0,0 +1,156 @@
+# Drain
+
+Let's move on to Drain. Drain is largely the same as IntoIter, except that
+instead of consuming the Vec, it borrows the Vec and leaves its allocation
+untouched. For now we'll only implement the "basic" full-range version.
+
+<!-- ignore: simplified code -->
+```rust,ignore
+use std::marker::PhantomData;
+
+struct Drain<'a, T: 'a> {
+    // Need to bound the lifetime here, so we do it with `&'a mut Vec<T>`
+    // because that's semantically what we contain. We're "just" calling
+    // `pop()` and `remove(0)`.
+    vec: PhantomData<&'a mut Vec<T>>,
+    start: *const T,
+    end: *const T,
+}
+
+impl<'a, T> Iterator for Drain<'a, T> {
+    type Item = T;
+    fn next(&mut self) -> Option<T> {
+        if self.start == self.end {
+            None
+```
+
+-- wait, this is seeming familiar. Let's do some more compression. Both
+IntoIter and Drain have the exact same structure, let's just factor it out.
+
+<!-- ignore: simplified code -->
+```rust,ignore
+struct RawValIter<T> {
+    start: *const T,
+    end: *const T,
+}
+
+impl<T> RawValIter<T> {
+    // unsafe to construct because it has no associated lifetimes.
+    // This is necessary to store a RawValIter in the same struct as
+    // its actual allocation. OK since it's a private implementation
+    // detail.
+    unsafe fn new(slice: &[T]) -> Self {
+        RawValIter {
+            start: slice.as_ptr(),
+            end: if slice.len() == 0 {
+                // if `len = 0`, then this is not actually allocated memory.
+                // Need to avoid offsetting because that will give wrong
+                // information to LLVM via GEP.
+                slice.as_ptr()
+            } else {
+                slice.as_ptr().add(slice.len())
+            }
+        }
+    }
+}
+
+// Iterator and DoubleEndedIterator impls identical to IntoIter.
+```
+
+And IntoIter becomes the following:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+pub struct IntoIter<T> {
+    _buf: RawVec<T>, // we don't actually care about this. Just need it to live.
+    iter: RawValIter<T>,
+}
+
+impl<T> Iterator for IntoIter<T> {
+    type Item = T;
+    fn next(&mut self) -> Option<T> { self.iter.next() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+
+impl<T> DoubleEndedIterator for IntoIter<T> {
+    fn next_back(&mut self) -> Option<T> { self.iter.next_back() }
+}
+
+impl<T> Drop for IntoIter<T> {
+    fn drop(&mut self) {
+        for _ in &mut *self {}
+    }
+}
+
+impl<T> Vec<T> {
+    pub fn into_iter(self) -> IntoIter<T> {
+        unsafe {
+            let iter = RawValIter::new(&self);
+
+            let buf = ptr::read(&self.buf);
+            mem::forget(self);
+
+            IntoIter {
+                iter: iter,
+                _buf: buf,
+            }
+        }
+    }
+}
+```
+
+Note that I've left a few quirks in this design to make upgrading Drain to work
+with arbitrary subranges a bit easier. In particular we *could* have RawValIter
+drain itself on drop, but that won't work right for a more complex Drain.
+We also take a slice to simplify Drain initialization.
+
+Alright, now Drain is really easy:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+use std::marker::PhantomData;
+
+pub struct Drain<'a, T: 'a> {
+    vec: PhantomData<&'a mut Vec<T>>,
+    iter: RawValIter<T>,
+}
+
+impl<'a, T> Iterator for Drain<'a, T> {
+    type Item = T;
+    fn next(&mut self) -> Option<T> { self.iter.next() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+
+impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
+    fn next_back(&mut self) -> Option<T> { self.iter.next_back() }
+}
+
+impl<'a, T> Drop for Drain<'a, T> {
+    fn drop(&mut self) {
+        for _ in &mut *self {}
+    }
+}
+
+impl<T> Vec<T> {
+    pub fn drain(&mut self) -> Drain<T> {
+        unsafe {
+            let iter = RawValIter::new(&self);
+
+            // this is a mem::forget safety thing. If Drain is forgotten, we just
+            // leak the whole Vec's contents. Also we need to do this *eventually*
+            // anyway, so why not do it now?
+            self.len = 0;
+
+            Drain {
+                iter: iter,
+                vec: PhantomData,
+            }
+        }
+    }
+}
+```
+
+For more details on the `mem::forget` problem, see the
+[section on leaks][leaks].
+
+[leaks]: ../leaking.html
diff --git a/src/doc/nomicon/src/vec/vec-final.md b/src/doc/nomicon/src/vec/vec-final.md
new file mode 100644 (file)
index 0000000..786cfab
--- /dev/null
@@ -0,0 +1,403 @@
+# The Final Code
+
+```rust
+use std::alloc::{self, Layout};
+use std::marker::PhantomData;
+use std::mem;
+use std::ops::{Deref, DerefMut};
+use std::ptr::{self, NonNull};
+
+struct RawVec<T> {
+    ptr: NonNull<T>,
+    cap: usize,
+    _marker: PhantomData<T>,
+}
+
+unsafe impl<T: Send> Send for RawVec<T> {}
+unsafe impl<T: Sync> Sync for RawVec<T> {}
+
+impl<T> RawVec<T> {
+    fn new() -> Self {
+        // !0 is usize::MAX. This branch should be stripped at compile time.
+        let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
+
+        // `NonNull::dangling()` doubles as "unallocated" and "zero-sized allocation"
+        RawVec {
+            ptr: NonNull::dangling(),
+            cap: cap,
+            _marker: PhantomData,
+        }
+    }
+
+    fn grow(&mut self) {
+        // since we set the capacity to usize::MAX when T has size 0,
+        // getting to here necessarily means the Vec is overfull.
+        assert!(mem::size_of::<T>() != 0, "capacity overflow");
+
+        let (new_cap, new_layout) = if self.cap == 0 {
+            (1, Layout::array::<T>(1).unwrap())
+        } else {
+            // This can't overflow because we ensure self.cap <= isize::MAX.
+            let new_cap = 2 * self.cap;
+
+            // `Layout::array` checks that the number of bytes is <= usize::MAX,
+            // but this is redundant since old_layout.size() <= isize::MAX,
+            // so the `unwrap` should never fail.
+            let new_layout = Layout::array::<T>(new_cap).unwrap();
+            (new_cap, new_layout)
+        };
+
+        // Ensure that the new allocation doesn't exceed `isize::MAX` bytes.
+        assert!(
+            new_layout.size() <= isize::MAX as usize,
+            "Allocation too large"
+        );
+
+        let new_ptr = if self.cap == 0 {
+            unsafe { alloc::alloc(new_layout) }
+        } else {
+            let old_layout = Layout::array::<T>(self.cap).unwrap();
+            let old_ptr = self.ptr.as_ptr() as *mut u8;
+            unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) }
+        };
+
+        // If allocation fails, `new_ptr` will be null, in which case we abort.
+        self.ptr = match NonNull::new(new_ptr as *mut T) {
+            Some(p) => p,
+            None => alloc::handle_alloc_error(new_layout),
+        };
+        self.cap = new_cap;
+    }
+}
+
+impl<T> Drop for RawVec<T> {
+    fn drop(&mut self) {
+        let elem_size = mem::size_of::<T>();
+
+        if self.cap != 0 && elem_size != 0 {
+            unsafe {
+                alloc::dealloc(
+                    self.ptr.as_ptr() as *mut u8,
+                    Layout::array::<T>(self.cap).unwrap(),
+                );
+            }
+        }
+    }
+}
+
+pub struct Vec<T> {
+    buf: RawVec<T>,
+    len: usize,
+}
+
+impl<T> Vec<T> {
+    fn ptr(&self) -> *mut T {
+        self.buf.ptr.as_ptr()
+    }
+
+    fn cap(&self) -> usize {
+        self.buf.cap
+    }
+
+    pub fn new() -> Self {
+        Vec {
+            buf: RawVec::new(),
+            len: 0,
+        }
+    }
+    pub fn push(&mut self, elem: T) {
+        if self.len == self.cap() {
+            self.buf.grow();
+        }
+
+        unsafe {
+            ptr::write(self.ptr().add(self.len), elem);
+        }
+
+        // Can't overflow, we'll OOM first.
+        self.len += 1;
+    }
+
+    pub fn pop(&mut self) -> Option<T> {
+        if self.len == 0 {
+            None
+        } else {
+            self.len -= 1;
+            unsafe { Some(ptr::read(self.ptr().add(self.len))) }
+        }
+    }
+
+    pub fn insert(&mut self, index: usize, elem: T) {
+        assert!(index <= self.len, "index out of bounds");
+        if self.cap() == self.len {
+            self.buf.grow();
+        }
+
+        unsafe {
+            ptr::copy(
+                self.ptr().add(index),
+                self.ptr().add(index + 1),
+                self.len - index,
+            );
+            ptr::write(self.ptr().add(index), elem);
+            self.len += 1;
+        }
+    }
+
+    pub fn remove(&mut self, index: usize) -> T {
+        assert!(index < self.len, "index out of bounds");
+        unsafe {
+            self.len -= 1;
+            let result = ptr::read(self.ptr().add(index));
+            ptr::copy(
+                self.ptr().add(index + 1),
+                self.ptr().add(index),
+                self.len - index,
+            );
+            result
+        }
+    }
+
+    pub fn into_iter(self) -> IntoIter<T> {
+        unsafe {
+            let iter = RawValIter::new(&self);
+            let buf = ptr::read(&self.buf);
+            mem::forget(self);
+
+            IntoIter {
+                iter: iter,
+                _buf: buf,
+            }
+        }
+    }
+
+    pub fn drain(&mut self) -> Drain<T> {
+        unsafe {
+            let iter = RawValIter::new(&self);
+
+            // this is a mem::forget safety thing. If Drain is forgotten, we just
+            // leak the whole Vec's contents. Also we need to do this *eventually*
+            // anyway, so why not do it now?
+            self.len = 0;
+
+            Drain {
+                iter: iter,
+                vec: PhantomData,
+            }
+        }
+    }
+}
+
+impl<T> Drop for Vec<T> {
+    fn drop(&mut self) {
+        while let Some(_) = self.pop() {}
+        // deallocation is handled by RawVec
+    }
+}
+
+impl<T> Deref for Vec<T> {
+    type Target = [T];
+    fn deref(&self) -> &[T] {
+        unsafe { std::slice::from_raw_parts(self.ptr(), self.len) }
+    }
+}
+
+impl<T> DerefMut for Vec<T> {
+    fn deref_mut(&mut self) -> &mut [T] {
+        unsafe { std::slice::from_raw_parts_mut(self.ptr(), self.len) }
+    }
+}
+
+struct RawValIter<T> {
+    start: *const T,
+    end: *const T,
+}
+
+impl<T> RawValIter<T> {
+    unsafe fn new(slice: &[T]) -> Self {
+        RawValIter {
+            start: slice.as_ptr(),
+            end: if mem::size_of::<T>() == 0 {
+                ((slice.as_ptr() as usize) + slice.len()) as *const _
+            } else if slice.len() == 0 {
+                slice.as_ptr()
+            } else {
+                slice.as_ptr().add(slice.len())
+            },
+        }
+    }
+}
+
+impl<T> Iterator for RawValIter<T> {
+    type Item = T;
+    fn next(&mut self) -> Option<T> {
+        if self.start == self.end {
+            None
+        } else {
+            unsafe {
+                let result = ptr::read(self.start);
+                self.start = if mem::size_of::<T>() == 0 {
+                    (self.start as usize + 1) as *const _
+                } else {
+                    self.start.offset(1)
+                };
+                Some(result)
+            }
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let elem_size = mem::size_of::<T>();
+        let len = (self.end as usize - self.start as usize) /
+                  if elem_size == 0 { 1 } else { elem_size };
+        (len, Some(len))
+    }
+}
+
+impl<T> DoubleEndedIterator for RawValIter<T> {
+    fn next_back(&mut self) -> Option<T> {
+        if self.start == self.end {
+            None
+        } else {
+            unsafe {
+                self.end = if mem::size_of::<T>() == 0 {
+                    (self.end as usize - 1) as *const _
+                } else {
+                    self.end.offset(-1)
+                };
+                Some(ptr::read(self.end))
+            }
+        }
+    }
+}
+
+pub struct IntoIter<T> {
+    _buf: RawVec<T>, // we don't actually care about this. Just need it to live.
+    iter: RawValIter<T>,
+}
+
+impl<T> Iterator for IntoIter<T> {
+    type Item = T;
+    fn next(&mut self) -> Option<T> {
+        self.iter.next()
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+}
+
+impl<T> DoubleEndedIterator for IntoIter<T> {
+    fn next_back(&mut self) -> Option<T> {
+        self.iter.next_back()
+    }
+}
+
+impl<T> Drop for IntoIter<T> {
+    fn drop(&mut self) {
+        for _ in &mut *self {}
+    }
+}
+
+pub struct Drain<'a, T: 'a> {
+    vec: PhantomData<&'a mut Vec<T>>,
+    iter: RawValIter<T>,
+}
+
+impl<'a, T> Iterator for Drain<'a, T> {
+    type Item = T;
+    fn next(&mut self) -> Option<T> {
+        self.iter.next()
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+}
+
+impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
+    fn next_back(&mut self) -> Option<T> {
+        self.iter.next_back()
+    }
+}
+
+impl<'a, T> Drop for Drain<'a, T> {
+    fn drop(&mut self) {
+        // pre-drain the iter
+        for _ in &mut *self {}
+    }
+}
+#
+# fn main() {
+#     tests::create_push_pop();
+#     tests::iter_test();
+#     tests::test_drain();
+#     tests::test_zst();
+#     println!("All tests finished OK");
+# }
+#
+# mod tests {
+#     use super::*;
+#
+#     pub fn create_push_pop() {
+#         let mut v = Vec::new();
+#         v.push(1);
+#         assert_eq!(1, v.len());
+#         assert_eq!(1, v[0]);
+#         for i in v.iter_mut() {
+#             *i += 1;
+#         }
+#         v.insert(0, 5);
+#         let x = v.pop();
+#         assert_eq!(Some(2), x);
+#         assert_eq!(1, v.len());
+#         v.push(10);
+#         let x = v.remove(0);
+#         assert_eq!(5, x);
+#         assert_eq!(1, v.len());
+#     }
+#
+#     pub fn iter_test() {
+#         let mut v = Vec::new();
+#         for i in 0..10 {
+#             v.push(Box::new(i))
+#         }
+#         let mut iter = v.into_iter();
+#         let first = iter.next().unwrap();
+#         let last = iter.next_back().unwrap();
+#         drop(iter);
+#         assert_eq!(0, *first);
+#         assert_eq!(9, *last);
+#     }
+#
+#     pub fn test_drain() {
+#         let mut v = Vec::new();
+#         for i in 0..10 {
+#             v.push(Box::new(i))
+#         }
+#         {
+#             let mut drain = v.drain();
+#             let first = drain.next().unwrap();
+#             let last = drain.next_back().unwrap();
+#             assert_eq!(0, *first);
+#             assert_eq!(9, *last);
+#         }
+#         assert_eq!(0, v.len());
+#         v.push(Box::new(1));
+#         assert_eq!(1, *v.pop().unwrap());
+#     }
+#
+#     pub fn test_zst() {
+#         let mut v = Vec::new();
+#         for _i in 0..10 {
+#             v.push(())
+#         }
+#
+#         let mut count = 0;
+#
+#         for _ in v.into_iter() {
+#             count += 1
+#         }
+#
+#         assert_eq!(10, count);
+#     }
+# }
+```
diff --git a/src/doc/nomicon/src/vec/vec-insert-remove.md b/src/doc/nomicon/src/vec/vec-insert-remove.md
new file mode 100644 (file)
index 0000000..57283f9
--- /dev/null
@@ -0,0 +1,51 @@
+# Insert and Remove
+
+Something *not* provided by slice is `insert` and `remove`, so let's do those
+next.
+
+Insert needs to shift all the elements at the target index to the right by one.
+To do this we need to use `ptr::copy`, which is our version of C's `memmove`.
+This copies some chunk of memory from one location to another, correctly
+handling the case where the source and destination overlap (which will
+definitely happen here).
+
+If we insert at index `i`, we want to shift the `[i .. len]` to `[i+1 .. len+1]`
+using the old len.
+
+<!-- ignore: simplified code -->
+```rust,ignore
+pub fn insert(&mut self, index: usize, elem: T) {
+    // Note: `<=` because it's valid to insert after everything
+    // which would be equivalent to push.
+    assert!(index <= self.len, "index out of bounds");
+    if self.cap == self.len { self.grow(); }
+
+    unsafe {
+        // ptr::copy(src, dest, len): "copy from src to dest len elems"
+        ptr::copy(self.ptr.as_ptr().add(index),
+                  self.ptr.as_ptr().add(index + 1),
+                  self.len - index);
+        ptr::write(self.ptr.as_ptr().add(index), elem);
+        self.len += 1;
+    }
+}
+```
+
+Remove behaves in the opposite manner. We need to shift all the elements from
+`[i+1 .. len + 1]` to `[i .. len]` using the *new* len.
+
+<!-- ignore: simplified code -->
+```rust,ignore
+pub fn remove(&mut self, index: usize) -> T {
+    // Note: `<` because it's *not* valid to remove after everything
+    assert!(index < self.len, "index out of bounds");
+    unsafe {
+        self.len -= 1;
+        let result = ptr::read(self.ptr.as_ptr().add(index));
+        ptr::copy(self.ptr.as_ptr().add(index + 1),
+                  self.ptr.as_ptr().add(index),
+                  self.len - index);
+        result
+    }
+}
+```
diff --git a/src/doc/nomicon/src/vec/vec-into-iter.md b/src/doc/nomicon/src/vec/vec-into-iter.md
new file mode 100644 (file)
index 0000000..33327e8
--- /dev/null
@@ -0,0 +1,150 @@
+# IntoIter
+
+Let's move on to writing iterators. `iter` and `iter_mut` have already been
+written for us thanks to The Magic of Deref. However there's two interesting
+iterators that Vec provides that slices can't: `into_iter` and `drain`.
+
+IntoIter consumes the Vec by-value, and can consequently yield its elements
+by-value. In order to enable this, IntoIter needs to take control of Vec's
+allocation.
+
+IntoIter needs to be DoubleEnded as well, to enable reading from both ends.
+Reading from the back could just be implemented as calling `pop`, but reading
+from the front is harder. We could call `remove(0)` but that would be insanely
+expensive. Instead we're going to just use ptr::read to copy values out of
+either end of the Vec without mutating the buffer at all.
+
+To do this we're going to use a very common C idiom for array iteration. We'll
+make two pointers; one that points to the start of the array, and one that
+points to one-element past the end. When we want an element from one end, we'll
+read out the value pointed to at that end and move the pointer over by one. When
+the two pointers are equal, we know we're done.
+
+Note that the order of read and offset are reversed for `next` and `next_back`
+For `next_back` the pointer is always after the element it wants to read next,
+while for `next` the pointer is always at the element it wants to read next.
+To see why this is, consider the case where every element but one has been
+yielded.
+
+The array looks like this:
+
+```text
+          S  E
+[X, X, X, O, X, X, X]
+```
+
+If E pointed directly at the element it wanted to yield next, it would be
+indistinguishable from the case where there are no more elements to yield.
+
+Although we don't actually care about it during iteration, we also need to hold
+onto the Vec's allocation information in order to free it once IntoIter is
+dropped.
+
+So we're going to use the following struct:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+pub struct IntoIter<T> {
+    buf: NonNull<T>,
+    cap: usize,
+    start: *const T,
+    end: *const T,
+    _marker: PhantomData<T>,
+}
+```
+
+And this is what we end up with for initialization:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+impl<T> Vec<T> {
+    pub fn into_iter(self) -> IntoIter<T> {
+        // Can't destructure Vec since it's Drop
+        let ptr = self.ptr;
+        let cap = self.cap;
+        let len = self.len;
+
+        // Make sure not to drop Vec since that will free the buffer
+        mem::forget(self);
+
+        unsafe {
+            IntoIter {
+                buf: ptr,
+                cap: cap,
+                start: ptr.as_ptr(),
+                end: if cap == 0 {
+                    // can't offset off this pointer, it's not allocated!
+                    ptr.as_ptr()
+                } else {
+                    ptr.as_ptr().add(len)
+                },
+                _marker: PhantomData,
+            }
+        }
+    }
+}
+```
+
+Here's iterating forward:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+impl<T> Iterator for IntoIter<T> {
+    type Item = T;
+    fn next(&mut self) -> Option<T> {
+        if self.start == self.end {
+            None
+        } else {
+            unsafe {
+                let result = ptr::read(self.start);
+                self.start = self.start.offset(1);
+                Some(result)
+            }
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let len = (self.end as usize - self.start as usize)
+                  / mem::size_of::<T>();
+        (len, Some(len))
+    }
+}
+```
+
+And here's iterating backwards.
+
+<!-- ignore: simplified code -->
+```rust,ignore
+impl<T> DoubleEndedIterator for IntoIter<T> {
+    fn next_back(&mut self) -> Option<T> {
+        if self.start == self.end {
+            None
+        } else {
+            unsafe {
+                self.end = self.end.offset(-1);
+                Some(ptr::read(self.end))
+            }
+        }
+    }
+}
+```
+
+Because IntoIter takes ownership of its allocation, it needs to implement Drop
+to free it. However it also wants to implement Drop to drop any elements it
+contains that weren't yielded.
+
+<!-- ignore: simplified code -->
+```rust,ignore
+impl<T> Drop for IntoIter<T> {
+    fn drop(&mut self) {
+        if self.cap != 0 {
+            // drop any remaining elements
+            for _ in &mut *self {}
+            let layout = Layout::array::<T>(self.cap).unwrap();
+            unsafe {
+                alloc::dealloc(self.buf.as_ptr() as *mut u8, layout);
+            }
+        }
+    }
+}
+```
diff --git a/src/doc/nomicon/src/vec/vec-layout.md b/src/doc/nomicon/src/vec/vec-layout.md
new file mode 100644 (file)
index 0000000..c1c1afc
--- /dev/null
@@ -0,0 +1,61 @@
+# Layout
+
+First off, we need to come up with the struct layout. A Vec has three parts:
+a pointer to the allocation, the size of the allocation, and the number of
+elements that have been initialized.
+
+Naively, this means we just want this design:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+pub struct Vec<T> {
+    ptr: *mut T,
+    cap: usize,
+    len: usize,
+}
+```
+
+And indeed this would compile. Unfortunately, it would be incorrect. First, the
+compiler will give us too strict variance. So a `&Vec<&'static str>`
+couldn't be used where an `&Vec<&'a str>` was expected. More importantly, it
+will give incorrect ownership information to the drop checker, as it will
+conservatively assume we don't own any values of type `T`. See [the chapter
+on ownership and lifetimes][ownership] for all the details on variance and
+drop check.
+
+As we saw in the ownership chapter, the standard library uses `Unique<T>` in place of
+`*mut T` when it has a raw pointer to an allocation that it owns. Unique is unstable,
+so we'd like to not use it if possible, though.
+
+As a recap, Unique is a wrapper around a raw pointer that declares that:
+
+* We are covariant over `T`
+* We may own a value of type `T` (for drop check)
+* We are Send/Sync if `T` is Send/Sync
+* Our pointer is never null (so `Option<Vec<T>>` is null-pointer-optimized)
+
+We can implement all of the above requirements in stable Rust. To do this, instead
+of using `Unique<T>` we will use [`NonNull<T>`][NonNull], another wrapper around a
+raw pointer, which gives us two of the above properties, namely it is covariant
+over `T` and is declared to never be null. By adding a `PhantomData<T>` (for drop
+check) and implementing Send/Sync if `T` is, we get the same results as using
+`Unique<T>`:
+
+```rust
+use std::ptr::NonNull;
+use std::marker::PhantomData;
+
+pub struct Vec<T> {
+    ptr: NonNull<T>,
+    cap: usize,
+    len: usize,
+    _marker: PhantomData<T>,
+}
+
+unsafe impl<T: Send> Send for Vec<T> {}
+unsafe impl<T: Sync> Sync for Vec<T> {}
+# fn main() {}
+```
+
+[ownership]: ../ownership.html
+[NonNull]: ../../std/ptr/struct.NonNull.html
diff --git a/src/doc/nomicon/src/vec/vec-push-pop.md b/src/doc/nomicon/src/vec/vec-push-pop.md
new file mode 100644 (file)
index 0000000..2a4e016
--- /dev/null
@@ -0,0 +1,57 @@
+# Push and Pop
+
+Alright. We can initialize. We can allocate. Let's actually implement some
+functionality! Let's start with `push`. All it needs to do is check if we're
+full to grow, unconditionally write to the next index, and then increment our
+length.
+
+To do the write we have to be careful not to evaluate the memory we want to write
+to. At worst, it's truly uninitialized memory from the allocator. At best it's the
+bits of some old value we popped off. Either way, we can't just index to the memory
+and dereference it, because that will evaluate the memory as a valid instance of
+T. Worse, `foo[idx] = x` will try to call `drop` on the old value of `foo[idx]`!
+
+The correct way to do this is with `ptr::write`, which just blindly overwrites the
+target address with the bits of the value we provide. No evaluation involved.
+
+For `push`, if the old len (before push was called) is 0, then we want to write
+to the 0th index. So we should offset by the old len.
+
+<!-- ignore: simplified code -->
+```rust,ignore
+pub fn push(&mut self, elem: T) {
+    if self.len == self.cap { self.grow(); }
+
+    unsafe {
+        ptr::write(self.ptr.as_ptr().add(self.len), elem);
+    }
+
+    // Can't fail, we'll OOM first.
+    self.len += 1;
+}
+```
+
+Easy! How about `pop`? Although this time the index we want to access is
+initialized, Rust won't just let us dereference the location of memory to move
+the value out, because that would leave the memory uninitialized! For this we
+need `ptr::read`, which just copies out the bits from the target address and
+interprets it as a value of type T. This will leave the memory at this address
+logically uninitialized, even though there is in fact a perfectly good instance
+of T there.
+
+For `pop`, if the old len is 1, we want to read out of the 0th index. So we
+should offset by the new len.
+
+<!-- ignore: simplified code -->
+```rust,ignore
+pub fn pop(&mut self) -> Option<T> {
+    if self.len == 0 {
+        None
+    } else {
+        self.len -= 1;
+        unsafe {
+            Some(ptr::read(self.ptr.as_ptr().add(self.len)))
+        }
+    }
+}
+```
diff --git a/src/doc/nomicon/src/vec/vec-raw.md b/src/doc/nomicon/src/vec/vec-raw.md
new file mode 100644 (file)
index 0000000..f4421db
--- /dev/null
@@ -0,0 +1,156 @@
+# RawVec
+
+We've actually reached an interesting situation here: we've duplicated the logic
+for specifying a buffer and freeing its memory in Vec and IntoIter. Now that
+we've implemented it and identified *actual* logic duplication, this is a good
+time to perform some logic compression.
+
+We're going to abstract out the `(ptr, cap)` pair and give them the logic for
+allocating, growing, and freeing:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+struct RawVec<T> {
+    ptr: NonNull<T>,
+    cap: usize,
+    _marker: PhantomData<T>,
+}
+
+unsafe impl<T: Send> Send for RawVec<T> {}
+unsafe impl<T: Sync> Sync for RawVec<T> {}
+
+impl<T> RawVec<T> {
+    fn new() -> Self {
+        assert!(mem::size_of::<T>() != 0, "TODO: implement ZST support");
+        RawVec {
+            ptr: NonNull::dangling(),
+            cap: 0,
+            _marker: PhantomData,
+        }
+    }
+
+    fn grow(&mut self) {
+        let (new_cap, new_layout) = if self.cap == 0 {
+            (1, Layout::array::<T>(1).unwrap())
+        } else {
+            // This can't overflow because we ensure self.cap <= isize::MAX.
+            let new_cap = 2 * self.cap;
+
+            // Layout::array checks that the number of bytes is <= usize::MAX,
+            // but this is redundant since old_layout.size() <= isize::MAX,
+            // so the `unwrap` should never fail.
+            let new_layout = Layout::array::<T>(new_cap).unwrap();
+            (new_cap, new_layout)
+        };
+
+        // Ensure that the new allocation doesn't exceed `isize::MAX` bytes.
+        assert!(new_layout.size() <= isize::MAX as usize, "Allocation too large");
+
+        let new_ptr = if self.cap == 0 {
+            unsafe { alloc::alloc(new_layout) }
+        } else {
+            let old_layout = Layout::array::<T>(self.cap).unwrap();
+            let old_ptr = self.ptr.as_ptr() as *mut u8;
+            unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) }
+        };
+
+        // If allocation fails, `new_ptr` will be null, in which case we abort.
+        self.ptr = match NonNull::new(new_ptr as *mut T) {
+            Some(p) => p,
+            None => alloc::handle_alloc_error(new_layout),
+        };
+        self.cap = new_cap;
+    }
+}
+
+impl<T> Drop for RawVec<T> {
+    fn drop(&mut self) {
+        if self.cap != 0 {
+            let layout = Layout::array::<T>(self.cap).unwrap();
+            unsafe {
+                alloc::dealloc(self.ptr.as_ptr() as *mut u8, layout);
+            }
+        }
+    }
+}
+```
+
+And change Vec as follows:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+pub struct Vec<T> {
+    buf: RawVec<T>,
+    len: usize,
+}
+
+impl<T> Vec<T> {
+    fn ptr(&self) -> *mut T {
+        self.buf.ptr.as_ptr()
+    }
+
+    fn cap(&self) -> usize {
+        self.buf.cap
+    }
+
+    pub fn new() -> Self {
+        Vec {
+            buf: RawVec::new(),
+            len: 0,
+        }
+    }
+
+    // push/pop/insert/remove largely unchanged:
+    // * `self.ptr.as_ptr() -> self.ptr()`
+    // * `self.cap -> self.cap()`
+    // * `self.grow() -> self.buf.grow()`
+}
+
+impl<T> Drop for Vec<T> {
+    fn drop(&mut self) {
+        while let Some(_) = self.pop() {}
+        // deallocation is handled by RawVec
+    }
+}
+```
+
+And finally we can really simplify IntoIter:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+pub struct IntoIter<T> {
+    _buf: RawVec<T>, // we don't actually care about this. Just need it to live.
+    start: *const T,
+    end: *const T,
+}
+
+// next and next_back literally unchanged since they never referred to the buf
+
+impl<T> Drop for IntoIter<T> {
+    fn drop(&mut self) {
+        // only need to ensure all our elements are read;
+        // buffer will clean itself up afterwards.
+        for _ in &mut *self {}
+    }
+}
+
+impl<T> Vec<T> {
+    pub fn into_iter(self) -> IntoIter<T> {
+        unsafe {
+            // need to use ptr::read to unsafely move the buf out since it's
+            // not Copy, and Vec implements Drop (so we can't destructure it).
+            let buf = ptr::read(&self.buf);
+            let len = self.len;
+            mem::forget(self);
+
+            IntoIter {
+                start: buf.ptr.as_ptr(),
+                end: buf.ptr.as_ptr().add(len),
+                _buf: buf,
+            }
+        }
+    }
+}
+```
+
+Much better.
diff --git a/src/doc/nomicon/src/vec/vec-zsts.md b/src/doc/nomicon/src/vec/vec-zsts.md
new file mode 100644 (file)
index 0000000..3469f0c
--- /dev/null
@@ -0,0 +1,181 @@
+# Handling Zero-Sized Types
+
+It's time. We're going to fight the specter that is zero-sized types. Safe Rust
+*never* needs to care about this, but Vec is very intensive on raw pointers and
+raw allocations, which are exactly the two things that care about
+zero-sized types. We need to be careful of two things:
+
+* The raw allocator API has undefined behavior if you pass in 0 for an
+  allocation size.
+* raw pointer offsets are no-ops for zero-sized types, which will break our
+  C-style pointer iterator.
+
+Thankfully we abstracted out pointer-iterators and allocating handling into
+`RawValIter` and `RawVec` respectively. How mysteriously convenient.
+
+## Allocating Zero-Sized Types
+
+So if the allocator API doesn't support zero-sized allocations, what on earth
+do we store as our allocation? `NonNull::dangling()` of course! Almost every operation
+with a ZST is a no-op since ZSTs have exactly one value, and therefore no state needs
+to be considered to store or load them. This actually extends to `ptr::read` and
+`ptr::write`: they won't actually look at the pointer at all. As such we never need
+to change the pointer.
+
+Note however that our previous reliance on running out of memory before overflow is
+no longer valid with zero-sized types. We must explicitly guard against capacity
+overflow for zero-sized types.
+
+Due to our current architecture, all this means is writing 3 guards, one in each
+method of `RawVec`.
+
+<!-- ignore: simplified code -->
+```rust,ignore
+impl<T> RawVec<T> {
+    fn new() -> Self {
+        // !0 is usize::MAX. This branch should be stripped at compile time.
+        let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
+
+        // `NonNull::dangling()` doubles as "unallocated" and "zero-sized allocation"
+        RawVec {
+            ptr: NonNull::dangling(),
+            cap: cap,
+            _marker: PhantomData,
+        }
+    }
+
+    fn grow(&mut self) {
+        // since we set the capacity to usize::MAX when T has size 0,
+        // getting to here necessarily means the Vec is overfull.
+        assert!(mem::size_of::<T>() != 0, "capacity overflow");
+
+        let (new_cap, new_layout) = if self.cap == 0 {
+            (1, Layout::array::<T>(1).unwrap())
+        } else {
+            // This can't overflow because we ensure self.cap <= isize::MAX.
+            let new_cap = 2 * self.cap;
+
+            // `Layout::array` checks that the number of bytes is <= usize::MAX,
+            // but this is redundant since old_layout.size() <= isize::MAX,
+            // so the `unwrap` should never fail.
+            let new_layout = Layout::array::<T>(new_cap).unwrap();
+            (new_cap, new_layout)
+        };
+
+        // Ensure that the new allocation doesn't exceed `isize::MAX` bytes.
+        assert!(new_layout.size() <= isize::MAX as usize, "Allocation too large");
+
+        let new_ptr = if self.cap == 0 {
+            unsafe { alloc::alloc(new_layout) }
+        } else {
+            let old_layout = Layout::array::<T>(self.cap).unwrap();
+            let old_ptr = self.ptr.as_ptr() as *mut u8;
+            unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) }
+        };
+
+        // If allocation fails, `new_ptr` will be null, in which case we abort.
+        self.ptr = match NonNull::new(new_ptr as *mut T) {
+            Some(p) => p,
+            None => alloc::handle_alloc_error(new_layout),
+        };
+        self.cap = new_cap;
+    }
+}
+
+impl<T> Drop for RawVec<T> {
+    fn drop(&mut self) {
+        let elem_size = mem::size_of::<T>();
+
+        if self.cap != 0 && elem_size != 0 {
+            unsafe {
+                alloc::dealloc(
+                    self.ptr.as_ptr() as *mut u8,
+                    Layout::array::<T>(self.cap).unwrap(),
+                );
+            }
+        }
+    }
+}
+```
+
+That's it. We support pushing and popping zero-sized types now. Our iterators
+(that aren't provided by slice Deref) are still busted, though.
+
+## Iterating Zero-Sized Types
+
+Zero-sized offsets are no-ops. This means that our current design will always
+initialize `start` and `end` as the same value, and our iterators will yield
+nothing. The current solution to this is to cast the pointers to integers,
+increment, and then cast them back:
+
+<!-- ignore: simplified code -->
+```rust,ignore
+impl<T> RawValIter<T> {
+    unsafe fn new(slice: &[T]) -> Self {
+        RawValIter {
+            start: slice.as_ptr(),
+            end: if mem::size_of::<T>() == 0 {
+                ((slice.as_ptr() as usize) + slice.len()) as *const _
+            } else if slice.len() == 0 {
+                slice.as_ptr()
+            } else {
+                slice.as_ptr().add(slice.len())
+            },
+        }
+    }
+}
+```
+
+Now we have a different bug. Instead of our iterators not running at all, our
+iterators now run *forever*. We need to do the same trick in our iterator impls.
+Also, our size_hint computation code will divide by 0 for ZSTs. Since we'll
+basically be treating the two pointers as if they point to bytes, we'll just
+map size 0 to divide by 1.
+
+<!-- ignore: simplified code -->
+```rust,ignore
+impl<T> Iterator for RawValIter<T> {
+    type Item = T;
+    fn next(&mut self) -> Option<T> {
+        if self.start == self.end {
+            None
+        } else {
+            unsafe {
+                let result = ptr::read(self.start);
+                self.start = if mem::size_of::<T>() == 0 {
+                    (self.start as usize + 1) as *const _
+                } else {
+                    self.start.offset(1)
+                };
+                Some(result)
+            }
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let elem_size = mem::size_of::<T>();
+        let len = (self.end as usize - self.start as usize)
+                  / if elem_size == 0 { 1 } else { elem_size };
+        (len, Some(len))
+    }
+}
+
+impl<T> DoubleEndedIterator for RawValIter<T> {
+    fn next_back(&mut self) -> Option<T> {
+        if self.start == self.end {
+            None
+        } else {
+            unsafe {
+                self.end = if mem::size_of::<T>() == 0 {
+                    (self.end as usize - 1) as *const _
+                } else {
+                    self.end.offset(-1)
+                };
+                Some(ptr::read(self.end))
+            }
+        }
+    }
+}
+```
+
+And that's it. Iteration works!
diff --git a/src/doc/nomicon/src/vec/vec.md b/src/doc/nomicon/src/vec/vec.md
new file mode 100644 (file)
index 0000000..b033863
--- /dev/null
@@ -0,0 +1,14 @@
+# Example: Implementing Vec
+
+To bring everything together, we're going to write `std::Vec` from scratch.
+We will limit ourselves to stable Rust. In particular we won't use any
+intrinsics that could make our code a little bit nicer or efficient because
+intrinsics are permanently unstable. Although many intrinsics *do* become
+stabilized elsewhere (`std::ptr` and `std::mem` consist of many intrinsics).
+
+Ultimately this means our implementation may not take advantage of all
+possible optimizations, though it will be by no means *naive*. We will
+definitely get into the weeds over nitty-gritty details, even
+when the problem doesn't *really* merit it.
+
+You wanted advanced. We're gonna go advanced.
index c82c70c678f016744fdd57aceaa4136eb7564b22..6a3c79f3e7882a51f2470b5ec423b1faa46f624e 100644 (file)
@@ -24,22 +24,22 @@ language cares about is preventing the following things:
   not support
 * Producing invalid values (either alone or as a field of a compound type such
   as `enum`/`struct`/array/tuple):
-    * a `bool` that isn't 0 or 1
-    * an `enum` with an invalid discriminant
-    * a null `fn` pointer
-    * a `char` outside the ranges [0x0, 0xD7FF] and [0xE000, 0x10FFFF]
-    * a `!` (all values are invalid for this type)
-    * an integer (`i*`/`u*`), floating point value (`f*`), or raw pointer read from
-      [uninitialized memory][], or uninitialized memory in a `str`.
-    * a reference/`Box` that is dangling, unaligned, or points to an invalid value.
-    * a wide reference, `Box`, or raw pointer that has invalid metadata:
-        * `dyn Trait` metadata is invalid if it is not a pointer to a vtable for
-          `Trait` that matches the actual dynamic trait the pointer or reference points to
-        * slice metadata is invalid if the length is not a valid `usize`
-          (i.e., it must not be read from uninitialized memory)
-    * a type with custom invalid values that is one of those values, such as a
-      [`NonNull`] that is null. (Requesting custom invalid values is an unstable
-      feature, but some stable libstd types, like `NonNull`, make use of it.)
+  * a `bool` that isn't 0 or 1
+  * an `enum` with an invalid discriminant
+  * a null `fn` pointer
+  * a `char` outside the ranges [0x0, 0xD7FF] and [0xE000, 0x10FFFF]
+  * a `!` (all values are invalid for this type)
+  * an integer (`i*`/`u*`), floating point value (`f*`), or raw pointer read from
+    [uninitialized memory][], or uninitialized memory in a `str`.
+  * a reference/`Box` that is dangling, unaligned, or points to an invalid value.
+  * a wide reference, `Box`, or raw pointer that has invalid metadata:
+    * `dyn Trait` metadata is invalid if it is not a pointer to a vtable for
+      `Trait` that matches the actual dynamic trait the pointer or reference points to
+    * slice metadata is invalid if the length is not a valid `usize`
+      (i.e., it must not be read from uninitialized memory)
+  * a type with custom invalid values that is one of those values, such as a
+    [`NonNull`] that is null. (Requesting custom invalid values is an unstable
+    feature, but some stable libstd types, like `NonNull`, make use of it.)
 
 "Producing" a value happens any time a value is assigned, passed to a
 function/primitive operation or returned from a function/primitive operation.
index 935ce580c23049346206914d174bc08899082747..b4b47a172913063edb3e4e5efa2475e201cdc814 100644 (file)
@@ -84,6 +84,7 @@ impl<T> Vec<T> {
 This code is simple enough to reasonably audit and informally verify. Now consider
 adding the following method:
 
+<!-- ignore: simplified code -->
 ```rust,ignore
 fn make_room(&mut self) {
     // grow the capacity
@@ -117,4 +118,3 @@ it prevents us from having to trust all the safe code in the universe from messi
 with our trusted state.
 
 Safety lives!
-
diff --git a/src/doc/nomicon/theme/nomicon.css b/src/doc/nomicon/theme/nomicon.css
new file mode 100644 (file)
index 0000000..1b8c77f
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+Taken from the reference.
+Warnings and notes:
+Write the <div>s on their own line. E.g.
+<div class="warning">
+Warning: This is bad!
+</div>
+*/
+main .warning p {
+    padding: 10px 20px;
+    margin: 20px 0;
+}
+
+main .warning p::before {
+    content: "⚠️ ";
+}
+
+.light main .warning p,
+.rust main .warning p {
+    border: 2px solid red;
+    background: #ffcece;
+}
+
+.rust main .warning p {
+    /* overrides previous declaration */
+    border-color: #961717;
+}
+
+.coal main .warning p,
+.navy main .warning p,
+.ayu main .warning p {
+    background: #542626
+}
+
+/* Make the links higher contrast on dark themes */
+.coal main .warning p a,
+.navy main .warning p a,
+.ayu main .warning p a {
+    color: #80d0d0
+}
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 d57c9a1707bd20f997335ddc09331f6228f836c6..b2def92d5ca58cf21a8d3dda7e719e65d01346a6 100644 (file)
@@ -8,4 +8,7 @@ additional-css = ["theme/reference.css"]
 git-repository-url = "https://github.com/rust-lang/reference/"
 
 [output.html.redirect]
-"/expressions/enum-variant-expr.html" = "struct-expr.html"
\ No newline at end of file
+"/expressions/enum-variant-expr.html" = "struct-expr.html"
+
+[rust]
+edition = "2018"
index a68e4662625a518cf7b3df92b4f9b586e1d613e2..37713c0c9614cd6438174bfee369f6852f650a6e 100644 (file)
@@ -47,7 +47,7 @@ assumed to exist.
 
 ## The `target_feature` attribute
 
-The *`target_feature` [attribute]* may be applied to an [unsafe function] to
+The *`target_feature` [attribute]* may be applied to a function to
 enable code generation of that function for specific platform architecture
 features. It uses the [_MetaListNameValueStr_] syntax with a single key of
 `enable` whose value is a string of comma-separated feature names to enable.
@@ -75,6 +75,9 @@ The following is a list of the available feature names.
 
 #### `x86` or `x86_64`
 
+This platform requires that `#[target_feature]` is only applied to [`unsafe`
+functions][unsafe function].
+
 Feature     | Implicitly Enables | Description
 ------------|--------------------|-------------------
 `aes`       | `sse2`   | [AES] — Advanced Encryption Standard
@@ -128,6 +131,17 @@ Feature     | Implicitly Enables | Description
 [`xsaveopt`]: https://www.felixcloutier.com/x86/xsaveopt
 [`xsaves`]: https://www.felixcloutier.com/x86/xsaves
 
+#### `wasm32` or `wasm64`
+
+This platform allows `#[target_feature]` to be applied to both safe and
+[`unsafe` functions][unsafe function].
+
+Feature     | Description
+------------|-------------------
+`simd128`   | [WebAssembly simd proposal][simd128]
+
+[simd128]: https://github.com/webassembly/simd
+
 ### Additional information
 
 See the [`target_feature` conditional compilation option] for selectively
index 89f3dfd65d12a485a2b79522bd13cdb194b07121..82ca73cddcf5d30b856bb01729ceb58303be06f6 100644 (file)
@@ -110,7 +110,7 @@ dropped after any bindings introduced in that parameter's pattern.
 #         println!("drop({})", self.0);
 #     }
 # }
-// Drops the second parameter, then `y`, then the first parameter, then `x`
+// Drops `y`, then the second parameter, then `x`, then the first parameter
 fn patterns_in_parameters(
     (x, _): (PrintOnDrop, PrintOnDrop),
     (_, y): (PrintOnDrop, PrintOnDrop),
index ca40dfec4626109d9075180f880086c30d467de3..1a5fae7270d1fdbf239f285ad0ed9a9f88688de3 100644 (file)
@@ -11,11 +11,12 @@ types">DSTs</abbr>. Such types can only be used in certain cases:
     * Pointers to slices also store the number of elements of the slice.
     * Pointers to trait objects also store a pointer to a vtable.
 * <abbr title="dynamically sized types">DSTs</abbr> can be provided as
-  type arguments when a bound of `?Sized`. By default any type parameter
-  has a `Sized` bound.
+  type arguments to generic type parameters having the special `?Sized` bound.
+  They can also be used for associated type definitions when the corresponding associated type declaration has a `?Sized` bound.
+  By default, any type parameter or associated type has a `Sized` bound, unless it is relaxed using `?Sized`.
 * Traits may be implemented for <abbr title="dynamically sized
-  types">DSTs</abbr>. Unlike type parameters `Self: ?Sized` by default in trait
-  definitions.
+  types">DSTs</abbr>.
+  Unlike with generic type parameters, `Self: ?Sized` is the default in trait definitions.
 * Structs may contain a <abbr title="dynamically sized type">DST</abbr> as the
   last field, this makes the struct itself a
   <abbr title="dynamically sized type">DST</abbr>.
index aaa25af037311596e554ae336e7df61e98c0b0c3..35e79161497a76cba8857a1fc888505fb486a26a 100644 (file)
@@ -140,7 +140,7 @@ assert_eq!(
 ## Place Expressions and Value Expressions
 
 Expressions are divided into two main categories: place expressions and
-value expressions. Likewise within each expression, operands may occur
+value expressions. Likewise, within each expression, operands may occur
 in either place context or value context. The evaluation of an expression
 depends both on its own category and the context it occurs within.
 
@@ -173,7 +173,7 @@ The following contexts are *place expression* contexts:
 When a place expression is evaluated in a value expression context, or is bound
 by value in a pattern, it denotes the value held _in_ that memory location. If
 the type of that value implements [`Copy`], then the value will be copied. In
-the remaining situations if that type is [`Sized`], then it may be possible to
+the remaining situations, if that type is [`Sized`], then it may be possible to
 move the value. Only the following place expressions may be moved out of:
 
 * [Variables] which are not currently borrowed.
@@ -183,7 +183,7 @@ move the value. Only the following place expressions may be moved out of:
 * The result of [dereferencing][deref] an expression with type [`Box<T>`] and
   that can also be moved out of.
 
-Moving out of a place expression that evaluates to a local variable, the
+When moving out of a place expression that evaluates to a local variable, the
 location is deinitialized and cannot be read from again until it is
 reinitialized. In all other cases, trying to use a place expression in a value
 expression context is an error.
@@ -191,30 +191,30 @@ expression context is an error.
 ### Mutability
 
 For a place expression to be [assigned][assign] to, mutably [borrowed][borrow],
-[implicitly mutably borrowed], or bound to a pattern containing `ref mut` it
+[implicitly mutably borrowed], or bound to a pattern containing `ref mut`, it
 must be _mutable_. We call these *mutable place expressions*. In contrast,
 other place expressions are called *immutable place expressions*.
 
 The following expressions can be mutable place expression contexts:
 
-* Mutable [variables], which are not currently borrowed.
+* Mutable [variables] which are not currently borrowed.
 * [Mutable `static` items].
 * [Temporary values].
-* [Fields][field], this evaluates the subexpression in a mutable place
+* [Fields][field]: this evaluates the subexpression in a mutable place
   expression context.
 * [Dereferences][deref] of a `*mut T` pointer.
 * Dereference of a variable, or field of a variable, with type `&mut T`. Note:
   This is an exception to the requirement of the next rule.
-* Dereferences of a type that implements `DerefMut`, this then requires that
+* Dereferences of a type that implements `DerefMut`: this then requires that
   the value being dereferenced is evaluated is a mutable place expression context.
-* [Array indexing] of a type that implements `IndexMut`, this
+* [Array indexing] of a type that implements `IndexMut`: this
   then evaluates the value being indexed, but not the index, in mutable place
   expression context.
 
 ### Temporaries
 
 When using a value expression in most place expression contexts, a temporary
-unnamed memory location is created initialized to that value and the expression
+unnamed memory location is created and initialized to that value. The expression
 evaluates to that location instead, except if [promoted] to a `static`. The
 [drop scope] of the temporary is usually the end of the enclosing statement.
 
@@ -222,7 +222,7 @@ evaluates to that location instead, except if [promoted] to a `static`. The
 
 Certain expressions will treat an expression as a place expression by implicitly
 borrowing it. For example, it is possible to compare two unsized [slices][slice] for
-equality directly, because the `==` operator implicitly borrows it's operands:
+equality directly, because the `==` operator implicitly borrows its operands:
 
 ```rust
 # let c = [1, 2, 3];
index 5f50f09cb476049fe38bf7572076b1a7cfb5f128..65b3e24917f3b0f13e05fa31c1bb1a1fee8c10fb 100644 (file)
@@ -4,7 +4,7 @@
 
 > **<sup>Syntax</sup>**\
 > _ArrayExpression_ :\
-> &nbsp;&nbsp; `[` [_InnerAttribute_]<sup>\*</sup> _ArrayElements_<sup>?</sup> `]`
+> &nbsp;&nbsp; `[` _ArrayElements_<sup>?</sup> `]`
 >
 > _ArrayElements_ :\
 > &nbsp;&nbsp; &nbsp;&nbsp; [_Expression_] ( `,` [_Expression_] )<sup>\*</sup> `,`<sup>?</sup>\
@@ -46,10 +46,6 @@ const EMPTY: Vec<i32> = Vec::new();
 [EMPTY; 2];
 ```
 
-### Array expression attributes
-
-[Inner attributes] are allowed directly after the opening bracket of an array expression in the same expression contexts as [attributes on block expressions].
-
 ## Array and slice indexing expressions
 
 > **<sup>Syntax</sup>**\
@@ -89,11 +85,8 @@ The array index expression can be implemented for types other than arrays and sl
 [`Copy`]: ../special-types-and-traits.md#copy
 [IndexMut]: ../../std/ops/trait.IndexMut.html
 [Index]: ../../std/ops/trait.Index.html
-[Inner attributes]: ../attributes.md
 [_Expression_]: ../expressions.md
-[_InnerAttribute_]: ../attributes.md
 [array]: ../types/array.md
-[attributes on block expressions]: block-expr.md#attributes-on-block-expressions
 [constant expression]: ../const_eval.md#constant-expressions
 [constant item]: ../items/constant-items.md
 [literal]: ../tokens.md#literals
index deece94cafe736b201209d51ed77a332ec725eb8..a68b27e56961b5a4f7af315e17a9ffa94291b53e 100644 (file)
@@ -109,7 +109,7 @@ Similarly, if `<expr>?` propagates an error, that error is propagated as the res
 Finally, the `break` and `continue` keywords cannot be used to branch out from an async block.
 Therefore the following is illegal:
 
-```rust,edition2018,compile_fail
+```rust,compile_fail
 loop {
     async move {
         break; // This would break out of the loop.
index d76e9a1e070b9bc834f19255a2ae66fbff05a4c9..0ff7e2c90bbe7b2257b1b38be9176637307ad3fa 100644 (file)
@@ -2,7 +2,7 @@
 
 > **<sup>Syntax</sup>**\
 > _GroupedExpression_ :\
-> &nbsp;&nbsp; `(` [_InnerAttribute_]<sup>\*</sup> [_Expression_] `)`
+> &nbsp;&nbsp; `(` [_Expression_] `)`
 
 A *parenthesized expression* wraps a single expression, evaluating to that expression.
 The syntax for a parenthesized expression is a `(`, then an expression, called the *enclosed operand*, and then a `)`.
@@ -39,12 +39,5 @@ assert_eq!( a.f (), "The method f");
 assert_eq!((a.f)(), "The field f");
 ```
 
-## Group expression attributes
-
-[Inner attributes] are allowed directly after the opening parenthesis of a group expression in the same expression contexts as [attributes on block expressions].
-
-[Inner attributes]: ../attributes.md
 [_Expression_]: ../expressions.md
-[_InnerAttribute_]: ../attributes.md
-[attributes on block expressions]: block-expr.md#attributes-on-block-expressions
 [place]: ../expressions.md#place-expressions-and-value-expressions
index 87b088f784291935b7e702358c0766a6ca7c3fbc..591437fc98fcf6f575c5780a045f169cbf50247e 100644 (file)
@@ -41,7 +41,7 @@ assert_eq!(y, "Bigger");
 
 > **<sup>Syntax</sup>**\
 > _IfLetExpression_ :\
-> &nbsp;&nbsp; `if` `let` [_Pattern_] `=` [_Expression_]<sub>_except struct or lazy boolean operator expression_</sub>
+> &nbsp;&nbsp; `if` `let` [_Pattern_] `=` [_Scrutinee_]<sub>_except lazy boolean operator expression_</sub>
 >              [_BlockExpression_]\
 > &nbsp;&nbsp; (`else` (
 >   [_BlockExpression_]
@@ -148,6 +148,7 @@ if let PAT = ( EXPR || EXPR ) { .. }
 [_Expression_]: ../expressions.md
 [_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators
 [_Pattern_]: ../patterns.md
+[_Scrutinee_]: match-expr.md
 [_eRFCIfLetChain_]: https://github.com/rust-lang/rfcs/blob/master/text/2497-if-let-chains.md#rollout-plan-and-transitioning-to-rust-2018
 [`match` expression]: match-expr.md
 [boolean type]: ../types/boolean.md
index 8c9ad2802461eab35b74f95d5d62fb53eab67a34..1ca62095c4b3e465092df3fe8d65e5876a3b4ae7 100644 (file)
@@ -62,9 +62,10 @@ while i < 10 {
 
 > **<sup>Syntax</sup>**\
 > [_PredicatePatternLoopExpression_] :\
-> &nbsp;&nbsp; `while` `let` [_Pattern_] `=` [_Expression_]<sub>_except struct or lazy boolean operator expression_</sub>
+> &nbsp;&nbsp; `while` `let` [_Pattern_] `=` [_Scrutinee_]<sub>_except lazy boolean operator expression_</sub>
 >              [_BlockExpression_]
 
+
 A `while let` loop is semantically similar to a `while` loop but in place of a condition expression it expects the keyword `let` followed by a pattern, an `=`, a [scrutinee] expression and a block expression.
 If the value of the scrutinee matches the pattern, the loop body block executes then control returns to the pattern matching statement.
 Otherwise, the while expression completes.
@@ -264,6 +265,7 @@ In the case a `loop` has an associated `break`, it is not considered diverging,
 [_BlockExpression_]: block-expr.md
 [_Expression_]: ../expressions.md
 [_Pattern_]: ../patterns.md
+[_Scrutinee_]: match-expr.md
 [`match` expression]: match-expr.md
 [boolean]: ../types/boolean.md
 [scrutinee]: ../glossary.md#scrutinee
index 53455fa9ace6f97482e766f1dba0fe7ad108c5fa..febf60cc3769de4498e42bba926ed5bfcf90f2b7 100644 (file)
@@ -2,11 +2,14 @@
 
 > **<sup>Syntax</sup>**\
 > _MatchExpression_ :\
-> &nbsp;&nbsp; `match` [_Expression_]<sub>_except struct expression_</sub> `{`\
+> &nbsp;&nbsp; `match` _Scrutinee_ `{`\
 > &nbsp;&nbsp; &nbsp;&nbsp; [_InnerAttribute_]<sup>\*</sup>\
 > &nbsp;&nbsp; &nbsp;&nbsp; _MatchArms_<sup>?</sup>\
 > &nbsp;&nbsp; `}`
 >
+>_Scrutinee_ :\
+> &nbsp;&nbsp; [_Expression_]<sub>_except struct expression_</sub>
+>
 > _MatchArms_ :\
 > &nbsp;&nbsp; ( _MatchArm_ `=>`
 >                             ( [_ExpressionWithoutBlock_][_Expression_] `,`
index be7c5f12e5ac8bdbbb4faf01aa69cf8620f168d0..61df3bd64d351b063f498463eeaf7155069320d0 100644 (file)
@@ -25,6 +25,7 @@ The following things are considered to be overflow:
 * When `+`, `*` or `-` create a value greater than the maximum value, or less than the minimum value that can be stored.
   This includes unary `-` on the smallest value of any signed integer type.
 * Using `/` or `%`, where the left-hand argument is the smallest integer of a signed integer type and the right-hand argument is `-1`.
+  These checks occur even when `-C overflow-checks` is disabled, for legacy reasons.
 * Using `<<` or `>>` where the right-hand argument is greater than or equal to the number of bits in the type of the left-hand argument, or is negative.
 
 ## Borrow operators
@@ -191,16 +192,18 @@ The operands of all of these operators are evaluated in [value expression contex
 | `-`    | Subtraction             |               | Subtraction    | `std::ops::Sub`    | `std::ops::SubAssign`                 |
 | `*`    | Multiplication          |               | Multiplication | `std::ops::Mul`    | `std::ops::MulAssign`                 |
 | `/`    | Division*               |               | Division       | `std::ops::Div`    | `std::ops::DivAssign`                 |
-| `%`    | Remainder               |               | Remainder      | `std::ops::Rem`    | `std::ops::RemAssign`                 |
+| `%`    | Remainder**             |               | Remainder      | `std::ops::Rem`    | `std::ops::RemAssign`                 |
 | `&`    | Bitwise AND             | [Logical AND] |                | `std::ops::BitAnd` | `std::ops::BitAndAssign`              |
 | <code>&#124;</code> | Bitwise OR | [Logical OR]  |                | `std::ops::BitOr`  | `std::ops::BitOrAssign`               |
 | `^`    | Bitwise XOR             | [Logical XOR] |                | `std::ops::BitXor` | `std::ops::BitXorAssign`              |
 | `<<`   | Left Shift              |               |                | `std::ops::Shl`    | `std::ops::ShlAssign`                 |
-| `>>`   | Right Shift**           |               |                | `std::ops::Shr`    |  `std::ops::ShrAssign`                |
+| `>>`   | Right Shift***          |               |                | `std::ops::Shr`    |  `std::ops::ShrAssign`                |
 
 \* Integer division rounds towards zero.
 
-\*\* Arithmetic right shift on signed integer types, logical right shift on
+\*\* Rust uses a remainder defined with [truncating division](https://en.wikipedia.org/wiki/Modulo_operation#Variants_of_the_definition). Given `remainder = dividend % divisor`, the remainder will have the same sign as the dividend.
+
+\*\*\* Arithmetic right shift on signed integer types, logical right shift on
 unsigned integer types.
 
 Here are examples of these operators being used.
@@ -340,6 +343,7 @@ reference types and `mut` or `const` in pointer types.
 #### Numeric cast
 
 * Casting between two integers of the same size (e.g. i32 -> u32) is a no-op
+  (Rust uses 2's complement for negative values of fixed integers)
 * Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will
   truncate
 * Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will
@@ -347,10 +351,8 @@ reference types and `mut` or `const` in pointer types.
     * sign-extend if the source is signed
 * Casting from a float to an integer will round the float towards zero
     * `NaN` will return `0`
-    * Values larger than the maximum integer value will saturate to the
-      maximum value of the integer type.
-    * Values smaller than the minimum integer value will saturate to the
-      minimum value of the integer type.
+    * Values larger than the maximum integer value, including `INFINITY`, will saturate to the maximum value of the integer type.
+    * Values smaller than the minimum integer value, including `NEG_INFINITY`, will saturate to the minimum value of the integer type.
 * Casting from an integer to float will produce the closest possible float \*
     * if necessary, rounding is according to `roundTiesToEven` mode \*\*\*
     * on overflow, infinity (of the same sign as the input) is produced
index ad9fb76f8e134b3a8be36883d65a82000ecb493d..a6958e1f007ccf199072d74dde04fa3615945fec 100644 (file)
@@ -7,7 +7,7 @@
 > &nbsp;&nbsp; | _StructExprUnit_
 >
 > _StructExprStruct_ :\
-> &nbsp;&nbsp; [_PathInExpression_] `{` [_InnerAttribute_]<sup>\*</sup> (_StructExprFields_ | _StructBase_)<sup>?</sup> `}`
+> &nbsp;&nbsp; [_PathInExpression_] `{` (_StructExprFields_ | _StructBase_)<sup>?</sup> `}`
 >
 > _StructExprFields_ :\
 > &nbsp;&nbsp; _StructExprField_ (`,` _StructExprField_)<sup>\*</sup> (`,` _StructBase_ | `,`<sup>?</sup>)
@@ -21,7 +21,6 @@
 >
 > _StructExprTuple_ :\
 > &nbsp;&nbsp; [_PathInExpression_] `(`\
-> &nbsp;&nbsp; &nbsp;&nbsp; [_InnerAttribute_]<sup>\*</sup>\
 > &nbsp;&nbsp; &nbsp;&nbsp; ( [_Expression_] (`,` [_Expression_])<sup>\*</sup> `,`<sup>?</sup> )<sup>?</sup>\
 > &nbsp;&nbsp; `)`
 >
@@ -122,17 +121,10 @@ let a = Gamma;  // Gamma unit value.
 let b = Gamma{};  // Exact same value as `a`.
 ```
 
-## Struct expression attributes
-
-[Inner attributes] are allowed directly after the opening brace or parenthesis of a struct expression in the same expression contexts as [attributes on block expressions].
-
 [IDENTIFIER]: ../identifiers.md
-[Inner attributes]: ../attributes.md
 [TUPLE_INDEX]: ../tokens.md#tuple-index
 [_Expression_]: ../expressions.md
-[_InnerAttribute_]: ../attributes.md
 [_PathInExpression_]: ../paths.md#paths-in-expressions
-[attributes on block expressions]: block-expr.md#attributes-on-block-expressions
 [call expression]: call-expr.md
 [enum variant]: ../items/enumerations.md
 [if let]: if-expr.md#if-let-expressions
index e9b1654c27fcd46359ca475d92769bb0f363d483..a6ac1c96286c1428389c7e6488d9880140c41d36 100644 (file)
@@ -4,7 +4,7 @@
 
 > **<sup>Syntax</sup>**\
 > _TupleExpression_ :\
-> &nbsp;&nbsp; `(` [_InnerAttribute_]<sup>\*</sup> _TupleElements_<sup>?</sup> `)`
+> &nbsp;&nbsp; `(` _TupleElements_<sup>?</sup> `)`
 >
 > _TupleElements_ :\
 > &nbsp;&nbsp; ( [_Expression_] `,` )<sup>+</sup> [_Expression_]<sup>?</sup>
@@ -29,10 +29,6 @@ Examples of tuple expressions and their types:
 | `("x".to_string(), )` | `(String, )`  |
 | `("a", 4usize, true)`| `(&'static str, usize, bool)` |
 
-### Tuple expression attributes
-
-[Inner attributes] are allowed directly after the opening parenthesis of a tuple expression in the same expression contexts as [attributes on block expressions].
-
 ## Tuple indexing expressions
 
 > **<sup>Syntax</sup>**\
@@ -70,13 +66,10 @@ assert_eq!(point.1, 0.0);
 > **Note**: Although arrays and slices also have elements, you must use an [array or slice indexing expression] or a [slice pattern] to access their elements.
 
 [_Expression_]: ../expressions.md
-[_InnerAttribute_]: ../attributes.md
 [array or slice indexing expression]: array-expr.md#array-and-slice-indexing-expressions
-[attributes on block expressions]: block-expr.md#attributes-on-block-expressions
 [call expression]: ./call-expr.md
 [decimal literal]: ../tokens.md#integer-literals
 [field access expressions]: ./field-expr.html#field-access-expressions
-[inner attributes]: ../attributes.md
 [operands]: ../expressions.md
 [parenthetical expression]: grouped-expr.md
 [place expression]: ../expressions.md#place-expressions-and-value-expressions
index d794ab876c59b92c96cc5c33be840c3b869673f5..9038efd8d57e4931d2b5a797e6e6dc36d04c6ffd 100644 (file)
@@ -109,6 +109,8 @@ These conventions are documented here.
   }
   ```
 
+  All examples are written for the latest edition unless otherwise stated.
+
 * The grammar and lexical structure is in blockquotes with either "Lexer" or "Syntax" in <sup>**bold superscript**</sup> as the first line.
 
   > **<sup>Syntax</sup>**\
index 0bd9a43fbd59407f103f529a295edc56fcf8db72..afbcb5cd57d12a7a8f3b2e7dc6b118707f7afbe7 100644 (file)
@@ -210,6 +210,7 @@ finally an optional list of trait bounds.
 
 The identifier is the name of the declared type alias. The optional trait bounds
 must be fulfilled by the implementations of the type alias.
+There is an implicit [`Sized`] bound on associated types that can be relaxed using the special `?Sized` bound.
 
 An *associated type definition* defines a type alias on another type. It is
 written as `type`, then an [identifier], then an `=`, and finally a [type].
@@ -344,6 +345,7 @@ fn main() {
 [`Box<Self>`]: ../special-types-and-traits.md#boxt
 [`Pin<P>`]: ../special-types-and-traits.md#pinp
 [`Rc<Self>`]: ../special-types-and-traits.md#rct
+[`Sized`]: ../special-types-and-traits.md#sized
 [traits]: traits.md
 [type aliases]: type-aliases.md
 [inherent implementations]: implementations.md#inherent-implementations
index 9d6ebcde345fc823257391f2d3ef80186e87f1de..f882a24634c6f5e4fead20434c59509fffdf4c89 100644 (file)
@@ -227,7 +227,7 @@ use the [`extern` function qualifier](#extern-function-qualifier).
 Functions may be qualified as async, and this can also be combined with the
 `unsafe` qualifier:
 
-```rust,edition2018
+```rust
 async fn regular_example() { }
 async unsafe fn unsafe_example() { }
 ```
@@ -240,7 +240,7 @@ An async function is roughly equivalent to a function
 that returns [`impl Future`] and with an [`async move` block][async-blocks] as
 its body:
 
-```rust,edition2018
+```rust
 // Source
 async fn example(x: &str) -> usize {
     x.len()
@@ -249,7 +249,7 @@ async fn example(x: &str) -> usize {
 
 is roughly equivalent to:
 
-```rust,edition2018
+```rust
 # use std::future::Future;
 // Desugared
 fn example<'a>(x: &'a str) -> impl Future<Output = usize> + 'a {
@@ -285,7 +285,7 @@ resulting function is unsafe to call and (like any async function)
 returns a future. This future is just an ordinary future and thus an
 `unsafe` context is not required to "await" it:
 
-```rust,edition2018
+```rust
 // Returns a future that, when awaited, dereferences `x`.
 //
 // Soundness condition: `x` must be safe to dereference until
index 686b6661dd4be0d7acc6c7a4e65c7fad975a97b1..e9c11ffcfa0f62c96ec797318739e648fe8b7036 100644 (file)
@@ -230,23 +230,13 @@ parameters.
 The `for` keyword can be used to introduce [higher-ranked lifetimes]. It only
 allows [_LifetimeParam_] parameters.
 
-Bounds that don't use the item's parameters or [higher-ranked lifetimes] are
-checked when the item is defined. It is an error for such a bound to be false.
-
-[`Copy`], [`Clone`], and [`Sized`] bounds are also checked for certain generic
-types when defining the item. It is an error to have `Copy` or `Clone` as a
-bound on a mutable reference, [trait object] or [slice][arrays] or `Sized` as a
-bound on a trait object or slice.
-
-```rust,compile_fail
+```rust
 struct A<T>
 where
     T: Iterator,            // Could use A<T: Iterator> instead
-    T::Item: Copy,
-    String: PartialEq<T>,
+    T::Item: Copy,          // Bound on an associated type
+    String: PartialEq<T>,   // Bound on `String`, using the type parameter
     i32: Default,           // Allowed, but not useful
-    i32: Iterator,          // Error: the trait bound is not satisfied
-    [T]: Copy,              // Error: the trait bound is not satisfied
 {
     f: T,
 }
@@ -303,9 +293,6 @@ struct Foo<#[my_flexible_clone(unbounded)] H> {
 [path expression]: ../expressions/path-expr.md
 [raw pointers]: ../types/pointer.md#raw-pointers-const-and-mut
 [references]: ../types/pointer.md#shared-references-
-[`Clone`]: ../special-types-and-traits.md#clone
-[`Copy`]: ../special-types-and-traits.md#copy
-[`Sized`]: ../special-types-and-traits.md#sized
 [structs]: structs.md
 [tuples]: ../types/tuple.md
 [trait object]: ../types/trait-object.md
index 284e78e281fed8b1a09307cde0e9a5d0d814380f..e543b4fa63cab17b988a382a288e37990eabf65d 100644 (file)
@@ -26,6 +26,54 @@ statics:
 The initializer expression must be omitted in an [external block], and must be
 provided for free static items.
 
+## Statics & generics
+
+A static item defined in a generic scope (for example in a blanket or default
+implementation) will result in exactly one static item being defined, as if
+the static definition was pulled out of the current scope into the module.
+There will *not* be one item per monomorphization.
+
+This code:
+
+```rust
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+trait Tr {
+    fn default_impl() {
+        static COUNTER: AtomicUsize = AtomicUsize::new(0);
+        println!("default_impl: counter was {}", COUNTER.fetch_add(1, Ordering::Relaxed));
+    }
+
+    fn blanket_impl();
+}
+
+struct Ty1 {}
+struct Ty2 {}
+
+impl<T> Tr for T {
+    fn blanket_impl() {
+        static COUNTER: AtomicUsize = AtomicUsize::new(0);
+        println!("blanket_impl: counter was {}", COUNTER.fetch_add(1, Ordering::Relaxed));
+    }
+}
+
+fn main() {
+    <Ty1 as Tr>::default_impl();
+    <Ty2 as Tr>::default_impl();
+    <Ty1 as Tr>::blanket_impl();
+    <Ty2 as Tr>::blanket_impl();
+}
+```
+
+prints
+
+```text
+default_impl: counter was 0
+default_impl: counter was 1
+blanket_impl: counter was 0
+blanket_impl: counter was 1
+```
+
 ## Mutable statics
 
 If a static item is declared with the `mut` keyword, then it is allowed to be
index a4b68815b086f9b7403fd7508a9f3bbedd651e92..26870a0fc341e91fb14268dcd7cc362d216dd217 100644 (file)
@@ -251,7 +251,8 @@ allowed, but it is deprecated and will become a hard error in the future.
 In the 2015 edition, the pattern for a trait function or method parameter is
 optional:
 
-```rust
+```rust,edition2015
+// 2015 Edition
 trait T {
     fn f(i32);  // Parameter identifiers are not required.
 }
@@ -269,7 +270,7 @@ Beginning in the 2018 edition, function or method parameter patterns are no
 longer optional. Also, all irrefutable patterns are allowed as long as there
 is a body. Without a body, the limitations listed above are still in effect.
 
-```rust,edition2018
+```rust
 trait T {
     fn f1((a, b): (i32, i32)) {}
     fn f2(_: (i32, i32));  // Cannot use tuple pattern without a body.
index 3d555d5630259c2e73d5e03aa7b7468796a70bdc..ff0cc75f7b64dd81cd47cfb8c27a0eff65c4c2f4 100644 (file)
@@ -3,6 +3,7 @@
 > **<sup>Syntax</sup>**\
 > _TypeAlias_ :\
 > &nbsp;&nbsp; `type` [IDENTIFIER]&nbsp;[_GenericParams_]<sup>?</sup>
+>              ( `:` [_TypeParamBounds_] )<sup>?</sup>
 >              [_WhereClause_]<sup>?</sup> ( `=` [_Type_] )<sup>?</sup> `;`
 
 A _type alias_ defines a new name for an existing [type]. Type aliases are
@@ -20,7 +21,7 @@ let p: Point = (41, 68);
 
 A type alias to a tuple-struct or unit-struct cannot be used to qualify that type's constructor:
 
-```rust,edition2018,compile_fail
+```rust,compile_fail
 struct MyStruct(u32);
 
 use MyStruct as UseAlias;
@@ -33,8 +34,12 @@ let _ = TypeAlias(5); // Doesn't work
 A type alias without the [_Type_] specification may only appear as an
 [associated type] in a [trait].
 
+A type alias with [_TypeParamBounds_] may only specified when used as
+an [associated type] in a [trait].
+
 [IDENTIFIER]: ../identifiers.md
 [_GenericParams_]: generics.md
+[_TypeParamBounds_]: ../trait-bounds.md
 [_WhereClause_]: generics.md#where-clauses
 [_Type_]: ../types.md#type-expressions
 [associated type]: associated-items.md#associated-types
index b29ddcb183bb865aadac6e3d9586e18d1ed0e971..f9695f5a299e8f8f24227e4129a215f507baac48 100644 (file)
@@ -144,7 +144,7 @@ fn main() {}
 > unambiguously select the crate name. This is to retain compatibility with
 > potential future changes. <!-- uniform_paths future-proofing -->
 >
-> ```rust,edition2018
+> ```rust
 > // use std::fs; // Error, this is ambiguous.
 > use ::std::fs;  // Imports from the `std` crate, not the module below.
 > use self::std::fs as self_fs;  // Imports the module below.
index 52dc17d88fcbdc589ad04c4935ec03c55eb60fe5..01ae288a33cd34e24fc763f56b1f2bf9cdc0b12f 100644 (file)
@@ -20,7 +20,7 @@ of this text is copied, and expanded upon in subsequent RFCs.
     character.
   - `simple NT`: a "meta-variable" non-terminal (further discussion below).
   - `complex NT`: a repetition matching non-terminal, specified via repetition
-    operators (`\*`, `+`, `?`).
+    operators (`*`, `+`, `?`).
   - `token`: an atomic element of a matcher; i.e. identifiers, operators,
     open/close delimiters, *and* simple NT's.
   - `token tree`: a tree structure formed from tokens (the leaves), complex
@@ -46,12 +46,12 @@ macro_rules! i_am_an_mbe {
 }
 ```
 
-`(start $foo:expr $($i:ident),\* end)` is a matcher. The whole matcher is a
+`(start $foo:expr $($i:ident),* end)` is a matcher. The whole matcher is a
 delimited sequence (with open- and close-delimiters `(` and `)`), and `$foo`
 and `$i` are simple NT's with `expr` and `ident` as their respective fragment
 specifiers.
 
-`$(i:ident),\*` is *also* an NT; it is a complex NT that matches a
+`$(i:ident),*` is *also* an NT; it is a complex NT that matches a
 comma-separated repetition of identifiers. The `,` is the separator token for
 the complex NT; it occurs in between each pair of elements (if any) of the
 matched fragment.
@@ -72,7 +72,7 @@ its additional role as a fragment specifier; but it will be clear from context
 which interpretation is meant.)
 
 "SEP" will range over separator tokens, "OP" over the repetition operators
-`\*`, `+`, and `?`, "OPEN"/"CLOSE" over matching token pairs surrounding a
+`*`, `+`, and `?`, "OPEN"/"CLOSE" over matching token pairs surrounding a
 delimited sequence (e.g. `[` and `]`).
 
 Greek letters "α" "β" "γ" "δ"  stand for potentially empty token-tree sequences.
@@ -110,7 +110,7 @@ of FIRST and FOLLOW are described later.
 1.  For any separated complex NT in a matcher, `M = ... $(tt ...) SEP OP ...`,
     we must have `SEP` ∈ FOLLOW(`tt ...`).
 1.  For an unseparated complex NT in a matcher, `M = ... $(tt ...) OP ...`, if
-    OP = `\*` or `+`, we must have FOLLOW(`tt ...`) ⊇ FIRST(`tt ...`).
+    OP = `*` or `+`, we must have FOLLOW(`tt ...`) ⊇ FIRST(`tt ...`).
 
 The first invariant says that whatever actual token that comes after a matcher,
 if any, must be somewhere in the predetermined follow set.  This ensures that a
@@ -202,7 +202,7 @@ first token-tree (if any):
       * Let SEP\_SET(M) = { SEP } if SEP is present and ε ∈ FIRST(`tt ...`);
         otherwise SEP\_SET(M) = {}.
 
-  * Let ALPHA\_SET(M) = FIRST(`α`) if OP = `\*` or `?` and ALPHA\_SET(M) = {} if
+  * Let ALPHA\_SET(M) = FIRST(`α`) if OP = `*` or `?` and ALPHA\_SET(M) = {} if
     OP = `+`.
   * FIRST(M) = (FIRST(`tt ...`) \\ {ε}) ∪ SEP\_SET(M) ∪ ALPHA\_SET(M).
 
@@ -211,7 +211,7 @@ the possibility that the separator could be a valid first token for M, which
 happens when there is a separator defined and the repeated fragment could be
 empty. ALPHA\_SET(M) defines the possibility that the complex NT could be empty,
 meaning that M's valid first tokens are those of the following token-tree
-sequences `α`. This occurs when either `\*` or `?` is used, in which case there
+sequences `α`. This occurs when either `*` or `?` is used, in which case there
 could be zero repetitions. In theory, this could also occur if `+` was used with
 a potentially-empty repeating fragment, but this is forbidden by the third
 invariant.
@@ -339,7 +339,7 @@ represent simple nonterminals with the given fragment specifier.
   * FOLLOW(M), for any other M, is defined as the intersection, as t ranges over
     (LAST(M) \ {ε}), of FOLLOW(t).
 
-The tokens that can begin a type are, as of this writing, {`(`, `[`, `!`, `\*`,
+The tokens that can begin a type are, as of this writing, {`(`, `[`, `!`, `*`,
 `&`, `&&`, `?`, lifetimes, `>`, `>>`, `::`, any non-keyword identifier, `super`,
 `self`, `Self`, `extern`, `crate`, `$crate`, `_`, `for`, `impl`, `fn`, `unsafe`,
 `typeof`, `dyn`}, although this list may not be complete because people won't
@@ -347,9 +347,9 @@ always remember to update the appendix when new ones are added.
 
 Examples of FOLLOW for complex M:
 
- * FOLLOW(`$( $d:ident $e:expr )\*`) = FOLLOW(`$e:expr`)
- * FOLLOW(`$( $d:ident $e:expr )\* $(;)\*`) = FOLLOW(`$e:expr`) ∩ ANYTOKEN = FOLLOW(`$e:expr`)
- * FOLLOW(`$( $d:ident $e:expr )\* $(;)\* $( f |)+`) = ANYTOKEN
+ * FOLLOW(`$( $d:ident $e:expr )*`) = FOLLOW(`$e:expr`)
+ * FOLLOW(`$( $d:ident $e:expr )* $(;)*`) = FOLLOW(`$e:expr`) ∩ ANYTOKEN = FOLLOW(`$e:expr`)
+ * FOLLOW(`$( $d:ident $e:expr )* $(;)* $( f |)+`) = ANYTOKEN
 
 ### Examples of valid and invalid matchers
 
index 65e43330d829362d56e12f48546080b7bf498e9e..719b9afbcd90b01650a2700b063cd2cb164ef2c8 100644 (file)
@@ -7,7 +7,8 @@ syntax: `some_extension!(...)`.
 There are two ways to define new macros:
 
 * [Macros by Example] define new syntax in a higher-level, declarative way.
-* [Procedural Macros] can be used to implement custom derive.
+* [Procedural Macros] define function-like macros, custom derives, and custom
+  attributes using functions that operate on input tokens.
 
 ## Macro Invocation
 
@@ -28,7 +29,7 @@ There are two ways to define new macros:
 > &nbsp;&nbsp; | [_SimplePath_] `!` `[` _TokenTree_<sup>\*</sup> `]` `;`\
 > &nbsp;&nbsp; | [_SimplePath_] `!` `{` _TokenTree_<sup>\*</sup> `}`
 
-A macro invocation executes a macro at compile time and replaces the
+A macro invocation expands a macro at compile time and replaces the
 invocation with the result of the macro. Macros may be invoked in the
 following situations:
 
index 8d2419b39f057e6c314d58ef4fe0aa4f47041eab..1b07d9ffdccceff6dcc67678427d46d47c8acee6 100644 (file)
@@ -104,12 +104,25 @@ imported.
 
 <!-- TODO: describe how `use` works on the use-declarations page, and link to it here. -->
 
+## Sub-namespaces
+
+The macro namespace is split into two sub-namespaces: one for [bang-style macros] and one for [attributes].
+When an attribute is resolved, any bang-style macros in scope will be ignored.
+And conversely resolving a bang-style macro will ignore attribute macros in scope.
+This prevents one style from shadowing another.
+
+For example, the [`cfg` attribute] and the [`cfg` macro] are two different entities with the same name in the macro namespace, but they can still be used in their respective context.
+
+It is still an error for a [`use` import] to shadow another macro, regardless of their sub-namespaces.
+
 [^rustc-lifetime-shadow]: `rustc` currently warns about shadowing when using
     the same name for a label and lifetime in the same scope, but it still
     treats them independently. This is intended as a future-compatibility
     warning about a possible extension to the language. See [PR
     #24162](https://github.com/rust-lang/rust/pull/24162).
 
+[`cfg` attribute]: ../conditional-compilation.md#the-cfg-attribute
+[`cfg` macro]: ../conditional-compilation.md#the-cfg-macro
 [`for`]: ../expressions/loop-expr.md#iterator-loops
 [`if let`]: ../expressions/if-expr.md#if-let-expressions
 [`let`]: ../statements.md#let-statements
@@ -117,11 +130,14 @@ imported.
 [`match`]: ../expressions/match-expr.md
 [`Self` constructors]: ../paths.md#self-1
 [`Self` type]: ../paths.md#self-1
+[`use` import]: ../items/use-declarations.md
 [`while let`]: ../expressions/loop-expr.md#predicate-pattern-loops
 [Associated const declarations]: ../items/associated-items.md#associated-constants
 [Associated function declarations]: ../items/associated-items.md#associated-functions-and-methods
 [Associated type declarations]: ../items/associated-items.md#associated-types
 [Attribute macros]: ../procedural-macros.md#attribute-macros
+[attributes]: ../attributes.md
+[bang-style macros]: ../macros.md
 [boolean]: ../types/boolean.md
 [Built-in attributes]: ../attributes.md#built-in-attributes-index
 [closure parameters]: ../expressions/closure-expr.md
index 2bf921c8d5b956668dbfb29501ed77af62c2a2b3..695252f5faa32fff7491a7b30ca2dd8bb60d5203 100644 (file)
@@ -172,6 +172,16 @@ the path must resolve to an item.
 > crates in the [extern prelude]. That is, they must be followed by the name of a crate.
 
 ```rust
+pub fn foo() {
+    // In the 2018 edition, this accesses `std` via the extern prelude.
+    // In the 2015 edition, this accesses `std` via the crate root.
+    let now = ::std::time::Instant::now();
+    println!("{:?}", now);
+}
+```
+
+```rust,edition2015
+// 2015 Edition
 mod a {
     pub fn foo() {}
 }
@@ -353,11 +363,11 @@ mod without { // ::without
             fn g(&self) {} // None
         }
 
-        impl OtherTrait for ::a::Struct {
+        impl OtherTrait for crate::a::Struct {
             fn g(&self) {} // None
         }
 
-        impl ::a::Trait for OtherStruct {
+        impl crate::a::Trait for OtherStruct {
             fn f(&self) {} // None
         }
     }
index 810be000585cea60e890bc8a679a52da385b0c50..6d054aae2c1b8b143e02513949f18e07da1ebee7 100644 (file)
@@ -134,10 +134,10 @@ UnwindSafe>` is a valid type.
 
 ## `Sized`
 
-The [`Sized`] trait indicates that the size of this type is known at
-compile-time; that is, it's not a [dynamically sized type]. [Type parameters]
-are `Sized` by default. `Sized` is always implemented automatically by the
-compiler, not by [implementation items].
+The [`Sized`] trait indicates that the size of this type is known at compile-time; that is, it's not a [dynamically sized type].
+[Type parameters] are `Sized` by default, as are [associated types].
+`Sized` is always implemented automatically by the compiler, not by [implementation items].
+These implicit `Sized` bounds may be relaxed by using the special `?Sized` bound.
 
 [`Arc<Self>`]: ../std/sync/struct.Arc.html
 [`Box<T>`]: ../std/boxed/struct.Box.html
@@ -160,6 +160,7 @@ compiler, not by [implementation items].
 [`Unpin`]: ../std/marker/trait.Unpin.html
 
 [Arrays]: types/array.md
+[associated types]: items/associated-items.md#associated-types
 [call expressions]: expressions/call-expr.md
 [deref coercions]: type-coercions.md#coercion-types
 [dereference operator]: expressions/operator-expr.md#the-dereference-operator
index 06cd9513e50c4f6a6681cf10ca5e3f4c23fb0fe2..8d9c21d7db69f684c4aec79eb60d9f7075bd920d 100644 (file)
@@ -62,7 +62,8 @@ annotation and then optionally by an initializer expression. When no
 type annotation is given, the compiler will infer the type, or signal
 an error if insufficient type information is available for definite
 inference. Any variables introduced by a variable declaration are visible
-from the point of declaration until the end of the enclosing block scope.
+from the point of declaration until the end of the enclosing block scope,
+except when they are shadowed by another variable declaration.
 
 ## Expression statements
 
index 4d1d5d345cfcce4bbdb1688b804471c3ef567519..cc3f4a1bde1363cedb66d2f7f76c3738d65b69f0 100644 (file)
@@ -47,7 +47,7 @@ trait is implemented for a type. For example, given `Ty: Trait`
 ```rust
 # type Surface = i32;
 trait Shape {
-    fn draw(&self, Surface);
+    fn draw(&self, surface: Surface);
     fn name() -> &'static str;
 }
 
@@ -73,19 +73,38 @@ fn name_figure<U: Shape>(
 }
 ```
 
+Bounds that don't use the item's parameters or [higher-ranked lifetimes] are checked when the item is defined.
+It is an error for such a bound to be false.
+
+[`Copy`], [`Clone`], and [`Sized`] bounds are also checked for certain generic types when using the item, even if the use does not provide a concrete type.
+It is an error to have `Copy` or `Clone` as a bound on a mutable reference, [trait object], or [slice].
+It is an error to have `Sized` as a bound on a trait object or slice.
+
+```rust,compile_fail
+struct A<'a, T>
+where
+    i32: Default,           // Allowed, but not useful
+    i32: Iterator,          // Error: `i32` is not an iterator
+    &'a mut T: Copy,        // (at use) Error: the trait bound is not satisfied
+    [T]: Sized,             // (at use) Error: size cannot be known at compilation
+{
+    f: &'a T,
+}
+struct UsesA<'a, T>(A<'a, T>);
+```
+
 Trait and lifetime bounds are also used to name [trait objects].
 
 ## `?Sized`
 
-`?` is only used to declare that the [`Sized`] trait may not be
-implemented for a type parameter or associated type. `?Sized` may
-not be used as a bound for other types.
+`?` is only used to relax the implicit [`Sized`] trait bound for [type parameters] or [associated types].
+`?Sized` may not be used as a bound for other types.
 
 ## Lifetime bounds
 
-Lifetime bounds can be applied to types or other lifetimes. The bound `'a: 'b`
-is usually read as `'a` *outlives* `'b`. `'a: 'b` means that `'a` lasts longer
-than `'b`, so a reference `&'a ()` is valid whenever `&'b ()` is valid.
+Lifetime bounds can be applied to types or to other lifetimes.
+The bound `'a: 'b` is usually read as `'a` *outlives* `'b`.
+`'a: 'b` means that `'a` lasts at least as long as `'b`, so a reference `&'a ()` is valid whenever `&'b ()` is valid.
 
 ```rust
 fn f<'a, 'b>(x: &'a i32, mut y: &'b i32) where 'a: 'b {
@@ -94,9 +113,8 @@ fn f<'a, 'b>(x: &'a i32, mut y: &'b i32) where 'a: 'b {
 }
 ```
 
-`T: 'a` means that all lifetime parameters of `T` outlive `'a`. For example if
-`'a` is an unconstrained lifetime parameter then `i32: 'static` and
-`&'static str: 'a` are satisfied but `Vec<&'a ()>: 'static` is not.
+`T: 'a` means that all lifetime parameters of `T` outlive `'a`.
+For example, if `'a` is an unconstrained lifetime parameter, then `i32: 'static` and `&'static str: 'a` are satisfied, but `Vec<&'a ()>: 'static` is not.
 
 ## Higher-ranked trait bounds
 
@@ -117,8 +135,7 @@ impl<'a> PartialEq<i32> for &'a T {
 
 and could then be used to compare a `&'a T` with any lifetime to an `i32`.
 
-Only a higher-ranked bound can be used here as the lifetime of the reference is
-shorter than a lifetime parameter on the function:
+Only a higher-ranked bound can be used here, because the lifetime of the reference is shorter than any possible lifetime parameter on the function:
 
 ```rust
 fn call_on_ref_zero<F>(f: F) where for<'a> F: Fn(&'a i32) {
@@ -127,7 +144,7 @@ fn call_on_ref_zero<F>(f: F) where for<'a> F: Fn(&'a i32) {
 }
 ```
 
-Higher-ranked lifetimes may also be specified just before the trait, the only
+Higher-ranked lifetimes may also be specified just before the trait: the only
 difference is the scope of the lifetime parameter, which extends only to the
 end of the following trait instead of the whole bound. This function is
 equivalent to the last one.
@@ -142,11 +159,18 @@ fn call_on_ref_zero<F>(f: F) where F: for<'a> Fn(&'a i32) {
 [LIFETIME_OR_LABEL]: tokens.md#lifetimes-and-loop-labels
 [_GenericParams_]: items/generics.md
 [_TypePath_]: paths.md#paths-in-types
+[`Clone`]: special-types-and-traits.md#clone
+[`Copy`]: special-types-and-traits.md#copy
 [`Sized`]: special-types-and-traits.md#sized
 
+[arrays]: types/array.md
 [associated types]: items/associated-items.md#associated-types
 [supertraits]: items/traits.md#supertraits
 [generic]: items/generics.md
+[higher-ranked lifetimes]: #higher-ranked-trait-bounds
+[slice]: types/slice.md
 [Trait]: items/traits.md#trait-bounds
+[trait object]: types/trait-object.md
 [trait objects]: types/trait-object.md
+[type parameters]: types/parameters.md
 [where clause]: items/generics.md#where-clauses
index bacd478e3cb4638976bdf0fe02600af9a7d7da75..22b5752bb5ca7821ba9cce698b9d3ec20e816ebe 100644 (file)
@@ -70,9 +70,9 @@ at least equal to the size and alignment of a pointer.
 
 ## Array Layout
 
-Arrays are laid out so that the `nth` element of the array is offset from the
-start of the array by `n * the size of the type` bytes. An array of `[T; n]`
-has a size of `size_of::<T>() * n` and the same alignment of `T`.
+An array of `[T; N]` has a size of `size_of::<T>() * N` and the same alignment
+of `T`. Arrays are laid out so that the zero-based `nth` element of the array
+is offset from the start of the array by `n * size_of::<T>()` bytes.
 
 ## Slice Layout
 
index dfdd4ea57f42362032d2b5a46297c255f382537c..7cfb3b059f18913f8ae6ace715b3886890c1ae75 100644 (file)
@@ -49,10 +49,10 @@ f(Closure{s: s, t: &t});
 
 The compiler prefers to capture a closed-over variable by immutable borrow,
 followed by unique immutable borrow (see below), by mutable borrow, and finally
-by move. It will pick the first choice of these that allows the closure to
-compile. The choice is made only with regards to the contents of the closure
-expression; the compiler does not take into account surrounding code, such as
-the lifetimes of involved variables.
+by move. It will pick the first choice of these that is compatible with how the
+captured variable is used inside the closure body. The compiler does not take
+surrounding code into account, such as the lifetimes of involved variables, or
+of the closure itself.
 
 If the `move` keyword is used, then all captures are by move or, for `Copy`
 types, by copy, regardless of whether a borrow would work. The `move` keyword is
index 84bb4fb86cb7103973474667022802e44cd5dcd3..209b9bcf69852db6afbee327ea67d418d107f5b0 100644 (file)
@@ -110,7 +110,7 @@ pub fn public_api() {}
 // Similarly to 'public_api', this module is public so external crates may look
 // inside of it.
 pub mod submodule {
-    use crate_helper_module;
+    use crate::crate_helper_module;
 
     pub fn my_method() {
         // Any item in the local crate may invoke the helper module's public
@@ -161,7 +161,7 @@ to `pub(in self)` or not using `pub` at all.
 
 Here's an example:
 
-```rust
+```rust,edition2015
 pub mod outer_mod {
     pub mod inner_mod {
         // This function is visible within `outer_mod`
diff --git a/src/doc/rust-by-example/.github/workflows/rbe.yml b/src/doc/rust-by-example/.github/workflows/rbe.yml
new file mode 100644 (file)
index 0000000..7d3b19c
--- /dev/null
@@ -0,0 +1,42 @@
+name: CI
+on: [push, pull_request]
+
+jobs:
+  test:
+    name: Run tests
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@master
+
+    - name: Update rustup
+      run: rustup self update
+
+    - name: Install Rust
+      run: |
+        rustup set profile minimal
+        rustup toolchain install stable -c rust-docs
+        rustup default stable
+
+    - name: Install mdbook
+      run: |
+        mkdir bin
+        curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.5/mdbook-v0.4.5-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin
+        echo "$(pwd)/bin" >> ${GITHUB_PATH}
+
+    - name: Report versions
+      run: |
+        rustup --version
+        rustc -Vv
+        mdbook --version
+
+    - name: Run tests
+      run: mdbook test
+
+    - name: Build HTML
+      run: mdbook build
+
+    - name: Upload Artifact
+      uses: actions/upload-artifact@v1
+      with:
+        name: rust-by-example
+        path: book
index 90dac52b6faaae833822544390b47d1f96e2753a..508cff231441a0c25d3ef6a10b0ac5b82d68e612 100644 (file)
@@ -3,7 +3,8 @@
 There are three types of structures ("structs") that can be created using the
 `struct` keyword:
 
-* Tuple structs, which are, basically, named tuples. The classic [C structs][c_struct]
+* Tuple structs, which are, basically, named tuples.
+* The classic [C structs][c_struct]
 * Unit structs, which are field-less, are useful for generics.
 
 ```rust,editable
index 30ae68f95c7376a6a344fd2877d43187dd2de433..03f81427bdaa10c262d90f7c90ca6b361798f648 100644 (file)
@@ -13,7 +13,7 @@ fn main() {
         // Destructure the second and third elements
         (0, y, z) => println!("First is `0`, `y` is {:?}, and `z` is {:?}", y, z),
         (1, ..)  => println!("First is `1` and the rest doesn't matter"),
-        // `..` can be the used ignore the rest of the tuple
+        // `..` can be used to ignore the rest of the tuple
         _      => println!("It doesn't matter what they are"),
         // `_` means don't bind the value to a variable
     }
index 8e8c10ced4ae4d3d4d508539b6f339bc8ec97abf..bd5d997f0d1446adb8cb84b819d5085cf34b9097 100644 (file)
@@ -1,8 +1,9 @@
-# Methods
+# Associated functions & Methods
 
-Methods are functions attached to objects. These methods have access to the
-data of the object and its other methods via the `self` keyword. Methods are
-defined under an `impl` block.
+Some functions are connected to a particular type. These come in two forms:
+associated functions, and methods. Associated functions are functions that
+are defined on a type generally, while methods are associated functions that are
+called on a particular instance of a type.
 
 ```rust,editable
 struct Point {
@@ -10,16 +11,18 @@ struct Point {
     y: f64,
 }
 
-// Implementation block, all `Point` methods go in here
+// Implementation block, all `Point` associated functions & methods go in here
 impl Point {
-    // This is a static method
-    // Static methods don't need to be called by an instance
-    // These methods are generally used as constructors
+    // This is an "associated function" because this function is associated with
+    // a particular type, that is, Point.
+    //
+    // Associated functions don't need to be called with an instance.
+    // These functions are generally used like constructors.
     fn origin() -> Point {
         Point { x: 0.0, y: 0.0 }
     }
 
-    // Another static method, taking two arguments:
+    // Another associated function, taking two arguments:
     fn new(x: f64, y: f64) -> Point {
         Point { x: x, y: y }
     }
@@ -31,7 +34,7 @@ struct Rectangle {
 }
 
 impl Rectangle {
-    // This is an instance method
+    // This is a method
     // `&self` is sugar for `self: &Self`, where `Self` is the type of the
     // caller object. In this case `Self` = `Rectangle`
     fn area(&self) -> f64 {
@@ -80,12 +83,12 @@ impl Pair {
 
 fn main() {
     let rectangle = Rectangle {
-        // Static methods are called using double colons
+        // Associated functions are called using double colons
         p1: Point::origin(),
         p2: Point::new(3.0, 4.0),
     };
 
-    // Instance methods are called using the dot operator
+    // Methods are called using the dot operator
     // Note that the first argument `&self` is implicitly passed, i.e.
     // `rectangle.perimeter()` === `Rectangle::perimeter(&rectangle)`
     println!("Rectangle perimeter: {}", rectangle.perimeter());
@@ -112,4 +115,4 @@ fn main() {
     //pair.destroy();
     // TODO ^ Try uncommenting this line
 }
-```
\ No newline at end of file
+```
index 16eba89747596e0e24ccfe4dc6c965ddeb16d5ac..709213c9dfcfc01a4b1b0d1b6f73d8d929454577 100644 (file)
@@ -1,6 +1,6 @@
 # `create`
 
-The `create` static method opens a file in write-only mode. If the file
+The `create` function opens a file in write-only mode. If the file
 already existed, the old content is destroyed. Otherwise, a new file is
 created.
 
index 16fdb2c91c196bbabbf6ecbaaa0de323962bb8d2..77a5470fa3022aae7f567ce55794d5ccf85a511a 100644 (file)
@@ -1,6 +1,6 @@
 # `open`
 
-The `open` static method can be used to open a file in read-only mode.
+The `open` function can be used to open a file in read-only mode.
 
 A `File` owns a resource, the file descriptor and takes care of closing the
 file when it is `drop`ed.
index eb83df8e10b2966621d108e476c4bd537d603648..4b10cfa899f4449afb65f66f61e8be4d6c6ad593 100644 (file)
@@ -19,7 +19,7 @@ fn main() {
     // Create a `Path` from an `&'static str`
     let path = Path::new(".");
 
-    // The `display` method returns a `Show`able structure
+    // The `display` method returns a `Display`able structure
     let _display = path.display();
 
     // `join` merges a path with a byte container using the OS specific
index a4345ae9458366f1b982fe5639acaf345bc7f004..0ac77588c3547962abd104c128a07e259a4b3562 100644 (file)
@@ -47,8 +47,8 @@ running 0 tests
 test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
 ```
 
-Each Rust source file in `tests` directory is compiled as a separate crate. One
-way of sharing some code between integration tests is making module with public
+Each Rust source file in the `tests` directory is compiled as a separate crate. One
+way of sharing some code between integration tests is making module with public
 functions, importing and using it within tests.
 
 File `tests/common.rs`:
index 7878d4742b01edf1f9d2609ed6c7b0810b368f91..d4d4094683e6fee6eb20991521b6494470ec133d 100644 (file)
@@ -12,10 +12,10 @@ methods from `Animal` with a `Sheep`.
 struct Sheep { naked: bool, name: &'static str }
 
 trait Animal {
-    // Static method signature; `Self` refers to the implementor type.
+    // Associated function signature; `Self` refers to the implementor type.
     fn new(name: &'static str) -> Self;
 
-    // Instance method signatures; these will return a string.
+    // Method signatures; these will return a string.
     fn name(&self) -> &'static str;
     fn noise(&self) -> &'static str;
 
@@ -77,4 +77,4 @@ fn main() {
     dolly.shear();
     dolly.talk();
 }
-```
\ No newline at end of file
+```
index 06f4df9a9b6da258f666727b441ed61b8e2814ab..d33ab0326031f84febab82ab42c0800ccce76c68 100644 (file)
@@ -1,68 +1,15 @@
-@font-face {
-       font-family: 'Fira Sans';
-       font-style: normal;
-       font-weight: 400;
-       src: local('Fira Sans'), 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.woff") format('woff');
-       font-display: swap;
-}
-@font-face {
-       font-family: 'Source Serif Pro';
-       font-style: normal;
-       font-weight: 400;
-       src: local('Source Serif Pro'), url("SourceSerifPro-Regular.ttf.woff") format('woff');
-       font-display: swap;
-}
-@font-face {
-       font-family: 'Source Serif Pro';
-       font-style: italic;
-       font-weight: 400;
-       src: url("SourceSerifPro-It.ttf.woff") format('woff');
-       font-display: swap;
-}
-@font-face {
-       font-family: 'Source Serif Pro';
-       font-style: normal;
-       font-weight: 700;
-       src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.ttf.woff") format('woff');
-       font-display: swap;
-}
-@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.woff") format('woff');
-       font-display: swap;
-}
-
-*:not(body) {
-  -webkit-box-sizing: border-box;
-        -moz-box-sizing: border-box;
-                 box-sizing: border-box;
-}
-
 /* General structure */
 
 body {
-       background-color: white;
        margin: 0 auto;
        padding: 0 15px;
-       font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif;
        font-size: 18px;
        color: #333;
        line-height: 1.428571429;
 
-       -webkit-font-feature-settings: "kern", "liga";
-       -moz-font-feature-settings: "kern", "liga";
-       font-feature-settings: "kern", "liga";
+       -webkit-box-sizing: unset;
+       -moz-box-sizing: unset;
+       box-sizing: unset;
 }
 @media (min-width: 768px) {
        body {
@@ -70,11 +17,7 @@ body {
        }
 }
 
-h1, h2, h3, h4, h5, h6, nav, #versioninfo {
-       font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
-}
-h1, h2, h3, h4, h5, h6 {
-       color: black;
+h2, h3, h4, h5, h6 {
        font-weight: 400;
        line-height: 1.1;
 }
@@ -84,6 +27,7 @@ h1, h2, h3 {
 }
 h1 {
        margin-bottom: 20px;
+       line-height: 1.1;
 }
 h4, h5, h6 {
        margin-top: 12px;
@@ -91,6 +35,7 @@ h4, h5, h6 {
        padding: 5px 10px;
 }
 h5, h6 {
+       color: black;
        text-decoration: underline;
 }
 
@@ -115,6 +60,7 @@ h3 {
 }
 h4 {
        font-size: 22px;
+       border-bottom: none;
 }
 h5 {
        font-size: 20px;
@@ -185,19 +131,15 @@ a:hover, a:active {
 h1 a:link, h1 a:visited, h2 a:link, h2 a:visited,
 h3 a:link, h3 a:visited, h4 a:link, h4 a:visited,
 h5 a:link, h5 a:visited {color: black;}
-h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover,
-h5 a:hover {text-decoration: none;}
 
 /* Code */
 
 pre, code {
-       font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", monospace;
        word-wrap: break-word;
 }
 pre {
        border-left: 2px solid #eee;
        white-space: pre-wrap;
-       padding: 14px;
        padding-right: 0;
        margin: 20px 0;
        font-size: 15px;
@@ -221,19 +163,6 @@ a > code {
        color: #8D1A38;
 }
 
-/* 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; }
-
-/* The rest */
-
 #versioninfo {
        text-align: center;
        margin: 0.5em;
@@ -275,9 +204,6 @@ blockquote p:last-child {
        margin-bottom: 0;
 }
 
-ul, ol {
-       padding-left: 25px;
-}
 ul ul, ol ul, ul ol, ol ol {
        margin-bottom: 0;
 }
@@ -332,22 +258,8 @@ table th {
 
 /* Code snippets */
 
-.example-wrap { position: relative; }
-pre.rust { position: relative; }
 a.test-arrow {
-       background-color: rgba(78, 139, 202, 0.2);
-       display: inline-block;
-       position: absolute;
-       color: #f5f5f5;
-       padding: 5px 10px 5px 10px;
-       border-radius: 5px;
-       font-size: 130%;
-       top: 5px;
-       right: 5px;
-}
-a.test-arrow:hover{
-       background-color: #4e8bca;
-       text-decoration: none;
+       color: #f5f5f5
 }
 
 .unstable-feature {
@@ -416,19 +328,6 @@ a.test-arrow:hover{
        position: relative;
 }
 
-.information {
-       position: absolute;
-       left: -25px;
-       margin-top: 7px;
-       z-index: 1;
-}
-
-.tooltip {
-       position: relative;
-       display: inline-block;
-       cursor: pointer;
-}
-
 .tooltip .tooltiptext {
        width: 120px;
        display: none;
index 99502bcc66f708d051cf86eae15dcdc2e409c3b4..006ea3231bd3be060aa7ae26ea451971efef5520 100644 (file)
@@ -14,6 +14,9 @@ for the docs you're looking for instead of reading them top to bottom.
 
 [rustdocs]: https://doc.rust-lang.org/nightly/nightly-rustc
 
+For documentation on developing the standard library, see
+[`std-dev-guide`](https://std-dev-guide.rust-lang.org/).
+
 ### Contributing to the guide
 
 The guide is useful today, but it has a lot of work still to go.
index 3f14c2642173e46b60ca714752b597c5ae77a48e..5fa267601241b685614ecb3a5be62bf7b75d172d 100644 (file)
@@ -81,6 +81,7 @@
     - [Panic Implementation](./panic-implementation.md)
     - [AST Validation](./ast-validation.md)
     - [Feature Gate Checking](./feature-gate-ck.md)
+    - [Lang Items](./lang-items.md)
 - [The HIR (High-level IR)](./hir.md)
     - [Lowering AST to HIR](./lowering.md)
     - [Debugging](./hir-debugging.md)
index d12f5a7a34a23f3a071b8a34ef3b0300d0585e78..3fa397ae4082ace329a1282cb0d853385aa87a8b 100644 (file)
@@ -4,31 +4,31 @@ This guide is meant to help document how rustc – the Rust compiler –
 works, as well as to help new contributors get involved in rustc
 development.
 
-There are six parts to this guide:
+There are seven parts to this guide:
 
 1. [Building and debugging `rustc`][p1]: Contains information that should be
    useful no matter how you are contributing, about building, debugging,
    profiling, etc.
-2. [Contributing to `rustc`][p1-5]: Contains information that should be useful
-   no matter how you are contributing, about procedures for contribution,
-   stabilizing features, etc.
-2. [High-Level Compiler Architecture][p2]: Discusses the high-level
+2. [Contributing to `rustc`][p2]: Contains information that should be useful
+   no matter how you are contributing, about procedures for contribution, using git
+   and Github, stabilizing features, etc.
+3. [High-Level Compiler Architecture][p3]: Discusses the high-level
    architecture of the compiler and stages of the compile process.
-3. [Source Code Representation][p3]: Describes the process of taking raw source code from the user and
+4. [Source Code Representation][p4]: Describes the process of taking raw source code from the user and
    transforming it into various forms that the compiler can work with easily.
-4. [Analysis][p4]: discusses the analyses that the compiler uses to check various
+5. [Analysis][p5]: discusses the analyses that the compiler uses to check various
    properties of the code and inform later stages of the compile process (e.g., type checking).
-5. [From MIR to Binaries][p5]: How linked executable machine code is generated.
-6. [Appendices][app] at the end with useful reference information. There are a
+6. [From MIR to Binaries][p6]: How linked executable machine code is generated.
+7. [Appendices][p7] at the end with useful reference information. There are a
    few of these with different information, including a glossary.
 
 [p1]: ./getting-started.md
-[p1-5]: ./compiler-team.md
-[p2]: ./part-2-intro.md
-[p3]: ./part-3-intro.md
-[p4]: ./part-4-intro.md
-[p5]: ./part-5-intro.md
-[app]: ./appendix/background.md
+[p2]: ./contributing.md
+[p3]: ./part-2-intro.md
+[p4]: ./part-3-intro.md
+[p5]: ./part-4-intro.md
+[p6]: ./part-5-intro.md
+[p7]: ./appendix/background.md
 
 ### Constant change
 
@@ -60,8 +60,10 @@ You might also find the following sites useful:
 - [Forge] -- contains documentation about rust infrastructure, team procedures, and more
 - [compiler-team] -- the home-base for the rust compiler team, with description
   of the team procedures, active working groups, and the team calendar.
+- [std-dev-guide] -- a similar guide for developing the standard library.
 
 [GitHub repository]: https://github.com/rust-lang/rustc-dev-guide/
 [rustc API docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/
 [Forge]: https://forge.rust-lang.org/
 [compiler-team]: https://github.com/rust-lang/compiler-team/
+[std-dev-guide]: https://std-dev-guide.rust-lang.org/
index eae5758f43e2cd46605586f6ab3e71dd3440df72..8e5d5b3947386bf4a4d2187a3b8879f499cbd401 100644 (file)
@@ -1,94 +1,95 @@
 # Glossary
 
-Term                                           | Meaning
------------------------------------------------|--------
-<span id="arena">arena/arena allocation</span> |  An _arena_ is a large memory buffer from which other memory allocations are made. This style of allocation is called _arena allocation_. See [this chapter](../memory.md) for more info.
-<span id="ast">AST</span>                      |  The abstract syntax tree produced by the `rustc_ast` crate; reflects user syntax very closely.
-<span id="binder">binder</span>                |  A "binder" is a place where a variable or type is declared; for example, the `<T>` is a binder for the generic type parameter `T` in `fn foo<T>(..)`, and \|`a`\|` ...` is a binder for the parameter `a`. See [the background chapter for more](./background.md#free-vs-bound).
-<span id="body-id">BodyId</span>               |  An identifier that refers to a specific body (definition of a function or constant) in the crate. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir).
-<span id="bound-var">bound variable</span>     |  A "bound variable" is one that is declared within an expression/term. For example, the variable `a` is bound within the closure expression \|`a`\|` a * 2`. See [the background chapter for more](./background.md#free-vs-bound)
-<span id="codegen">codegen</span>              |  The code to translate MIR into LLVM IR.
-<span id="codegen-unit">codegen unit</span>    |  When we produce LLVM IR, we group the Rust code into a number of codegen units (sometimes abbreviated as CGUs). Each of these units is processed by LLVM independently from one another, enabling parallelism. They are also the unit of incremental re-use. ([see more](../backend/codegen.md))
-<span id="completeness">completeness</span>    |  A technical term in type theory, it means that every type-safe program also type-checks. Having both soundness and completeness is very hard, and usually soundness is more important. (see "soundness").
-<span id="cfg">control-flow graph</span>       |  A representation of the control-flow of a program; see [the background chapter for more](./background.md#cfg)
-<span id="ctfe">CTFE</span>                    |  Short for Compile-Time Function Evaluation, this is the ability of the compiler to evaluate `const fn`s at compile time. This is part of the compiler's constant evaluation system. ([see more](../const-eval.md))
-<span id="cx">cx</span>                        |  We tend to use "cx" as an abbreviation for context. See also `tcx`, `infcx`, etc.
-<span id="ctxt">ctxt</span>                    |  We also use "ctxt" as an abbreviation for context, e.g. [`TyCtxt`](#TyCtxt). See also [cx](#cx) or [tcx](#tcx).
-<span id="dag">DAG</span>                      |  A directed acyclic graph is used during compilation to keep track of dependencies between queries. ([see more](../queries/incremental-compilation.md))
-<span id="data-flow">data-flow analysis</span> |  A static analysis that figures out what properties are true at each point in the control-flow of a program; see [the background chapter for more](./background.md#dataflow).
-<span id="debruijn">DeBruijn Index</span>      |  A technique for describing which binder a variable is bound by using only integers. It has the benefit that it is invariant under variable renaming. ([see more](./background.md#what-is-a-debruijn-index))
-<span id="def-id">DefId</span>                 |  An index identifying a definition (see `rustc_middle/src/hir/def_id.rs`). Uniquely identifies a `DefPath`. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir).
-<span id="discriminant">discriminant</span>    |  The underlying value associated with an enum variant or generator state to indicate it as "active" (but not to be confused with its ["variant index"](#variant-idx)). At runtime, the discriminant of the active variant is encoded in the [tag](#tag).
-<span id="double-ptr">double pointer</span>    |  A pointer with additional metadata. See "fat pointer" for more.
-<span id="drop-glue">drop glue</span>          |  (internal) compiler-generated instructions that handle calling the destructors (`Drop`) for data types.
-<span id="dst">DST</span>                      |  Short for Dynamically-Sized Type, this is a type for which the compiler cannot statically know the size in memory (e.g. `str` or `[u8]`). Such types don't implement `Sized` and cannot be allocated on the stack. They can only occur as the last field in a struct. They can only be used behind a pointer (e.g. `&str` or `&[u8]`).
-<span id="ebl">early-bound lifetime</span>     |  A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted using a `Substs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html#bound-regions))
-<span id="empty-type">empty type</span>        |  see "uninhabited type".
-<span id="fat-ptr">fat pointer</span>          |  A two word value carrying the address of some value, along with some further information necessary to put the value to use. Rust includes two kinds of "fat pointers": references to slices, and trait objects. A reference to a slice carries the starting address of the slice and its length. A trait object carries a value's address and a pointer to the trait's implementation appropriate to that value. "Fat pointers" are also known as "wide pointers", and "double pointers".
-<span id="free-var">free variable</span>       |  A "free variable" is one that is not bound within an expression or term; see [the background chapter for more](./background.md#free-vs-bound)
-<span id="generics">generics</span>            |  The set of generic type parameters defined on a type or item.
-<span id="hir">HIR</span>                      |  The High-level IR, created by lowering and desugaring the AST. ([see more](../hir.md))
-<span id="hir-id">HirId</span>                 |  Identifies a particular node in the HIR by combining a def-id with an "intra-definition offset". See [the HIR chapter for more](../hir.md#identifiers-in-the-hir).
-<span id="hir-map">HIR map</span>              |  The HIR map, accessible via `tcx.hir()`, allows you to quickly navigate the HIR and convert between various forms of identifiers.
-<span id="ice">ICE</span>                      |  Short for internal compiler error, this is when the compiler crashes.
-<span id="ich">ICH</span>                      |  Short for incremental compilation hash, these are used as fingerprints for things such as HIR and crate metadata, to check if changes have been made. This is useful in incremental compilation to see if part of a crate has changed and should be recompiled.
-<span id="infcx">infcx</span>                  |  The type inference context (`InferCtxt`). (see `rustc_middle::infer`)
-<span id="inf-var">inference variable</span>   |  When doing type or region inference, an "inference variable" is a kind of special type/region that represents what you are trying to infer. Think of X in algebra. For example, if we are trying to infer the type of a variable in a program, we create an inference variable to represent that unknown type.
-<span id="intern">intern</span>                |  Interning refers to storing certain frequently-used constant data, such as strings, and then referring to the data by an identifier (e.g. a `Symbol`) rather than the data itself, to reduce memory usage and number of allocations. See [this chapter](../memory.md) for more info.
-<span id="intrinsic">intrinsic</span>          |  Intrinsics are special functions that are implemented in the compiler itself but exposed (often unstably) to users. They do magical and dangerous things. (See [`std::intrinsics`](https://doc.rust-lang.org/std/intrinsics/index.html))
-<span id="ir">IR</span>                        |  Short for Intermediate Representation, a general term in compilers. During compilation, the code is transformed from raw source (ASCII text) to various IRs. In Rust, these are primarily HIR, MIR, and LLVM IR. Each IR is well-suited for some set of computations. For example, MIR is well-suited for the borrow checker, and LLVM IR is well-suited for codegen because LLVM accepts it.
-<span id="irlo">IRLO</span>                    |  `IRLO` or `irlo` is sometimes used as an abbreviation for [internals.rust-lang.org](https://internals.rust-lang.org).
-<span id="item">item</span>                    |  A kind of "definition" in the language, such as a static, const, use statement, module, struct, etc. Concretely, this corresponds to the `Item` type.
-<span id="lang-item">lang item</span>          |  Items that represent concepts intrinsic to the language itself, such as special built-in traits like `Sync` and `Send`; or traits representing operations such as `Add`; or functions that are called by the compiler. ([see more](https://doc.rust-lang.org/1.9.0/book/lang-items.html))
-<span id="lbl">late-bound lifetime</span>      |  A lifetime region that is substituted at its call site. Bound in a HRTB and substituted by specific functions in the compiler, such as `liberate_late_bound_regions`. Contrast with **early-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html#bound-regions))
-<span id="local-crate">local crate</span>      |  The crate currently being compiled. This is in contrast to "upstream crates" which refer to dependencies of the local crate.
-<span id="lto">LTO</span>                      |  Short for Link-Time Optimizations, this is a set of optimizations offered by LLVM that occur just before the final binary is linked. These include optimizations like removing functions that are never used in the final program, for example. _ThinLTO_ is a variant of LTO that aims to be a bit more scalable and efficient, but possibly sacrifices some optimizations. You may also read issues in the Rust repo about "FatLTO", which is the loving nickname given to non-Thin LTO. LLVM documentation: [here][lto] and [here][thinlto].
-<span id="llvm">[LLVM]</span>                  |  (actually not an acronym :P) an open-source compiler backend. It accepts LLVM IR and outputs native binaries. Various languages (e.g. Rust) can then implement a compiler front-end that outputs LLVM IR and use LLVM to compile to all the platforms LLVM supports.
-<span id="memoization">memoization</span>      |  The process of storing the results of (pure) computations (such as pure function calls) to avoid having to repeat them in the future. This is typically a trade-off between execution speed and memory usage.
-<span id="mir">MIR</span>                      |  The Mid-level IR that is created after type-checking for use by borrowck and codegen. ([see more](../mir/index.md))
-<span id="miri">miri</span>                    |  An interpreter for MIR used for constant evaluation. ([see more](../miri.md))
-<span id="mono">monomorphization</span>        |  The process of taking generic implementations of types and functions and instantiating them with concrete types. For example, in the code we might have `Vec<T>`, but in the final executable, we will have a copy of the `Vec` code for every concrete type used in the program (e.g. a copy for `Vec<usize>`, a copy for `Vec<MyStruct>`, etc).
-<span id="normalize">normalize</span>          |  A general term for converting to a more canonical form, but in the case of rustc typically refers to [associated type normalization](../traits/goals-and-clauses.md#normalizeprojection---type).
-<span id="newtype">newtype</span>              |  A wrapper around some other type (e.g., `struct Foo(T)` is a "newtype" for `T`). This is commonly used in Rust to give a stronger type for indices.
-<span id="niche">niche</span>                  |  Invalid bit patterns for a type *that can be used* for layout optimizations. Some types cannot have certain bit patterns. For example, the `NonZero*` integers or the reference `&T` cannot be represented by a 0 bitstring. This means the compiler can perform layout optimizations by taking advantage of the invalid "niche value". An example application for this is the [*Discriminant elision on `Option`-like enums*](https://rust-lang.github.io/unsafe-code-guidelines/layout/enums.html#discriminant-elision-on-option-like-enums), which allows using a type's niche as the ["tag"](#tag) for an `enum` without requiring a separate field.
-<span id="nll">NLL</span>                      |  Short for [non-lexical lifetimes](../borrow_check/region_inference.md), this is an extension to Rust's borrowing system to make it be based on the control-flow graph.
-<span id="node-id">node-id or NodeId</span>    |  An index identifying a particular node in the AST or HIR; gradually being phased out and replaced with `HirId`. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir).
-<span id="obligation">obligation</span>        |  Something that must be proven by the trait system. ([see more](../traits/resolution.md))
-<span id="placeholder">placeholder</span>      |  **NOTE: skolemization is deprecated by placeholder** a way of handling subtyping around "for-all" types (e.g., `for<'a> fn(&'a u32)`) as well as solving higher-ranked trait bounds (e.g., `for<'a> T: Trait<'a>`). See [the chapter on placeholder and universes](../borrow_check/region_inference/placeholders_and_universes.md) for more details.
-<span id="point">point</span>                  |  Used in the NLL analysis to refer to some particular location in the MIR; typically used to refer to a node in the control-flow graph.
-<span id="polymorphize">polymorphize</span>    |  An optimization that avoids unnecessary monomorphisation. ([see more](../backend/monomorph.md#polymorphization))
-<span id="projection">projection</span>        |  A general term for a "relative path", e.g. `x.f` is a "field projection", and `T::Item` is an ["associated type projection"](../traits/goals-and-clauses.md#trait-ref).
-<span id="pc">promoted constants</span>        |  Constants extracted from a function and lifted to static scope; see [this section](../mir/index.md#promoted) for more details.
-<span id="provider">provider</span>            |  The function that executes a query. ([see more](../query.md))
-<span id="quantified">quantified</span>        |  In math or logic, existential and universal quantification are used to ask questions like "is there any type T for which is true?" or "is this true for all types T?"; see [the background chapter for more](./background.md#quantified).
-<span id="query">query</span>                  |  A sub-computation during compilation. Query results can be cached in the current session or to disk for incremental compilation. ([see more](../query.md))
-<span id="recovery">recovery</span>            |  Recovery refers to handling invalid syntax during parsing (e.g. a missing comma) and continuing to parse the AST. This avoid showing spurious errors to the user (e.g. showing 'missing field' errors when the struct definition contains errors).
-<span id="region">region</span>                |  Another term for "lifetime" often used in the literature and in the borrow checker.
-<span id="rib">rib</span>                      |  A data structure in the name resolver that keeps track of a single scope for names. ([see more](../name-resolution.md))
-<span id="scrutinee">scrutinee</div>           |  A scrutinee is the expression that is matched on in `match` expressions and similar pattern matching constructs. For example, in `match x { A => 1, B => 2 }`, the expression `x` is the scrutinee.
-<span id="sess">sess</span>                    |  The compiler session, which stores global data used throughout compilation
-<span id="side-tables">side tables</span>      |  Because the AST and HIR are immutable once created, we often carry extra information about them in the form of hashtables, indexed by the id of a particular node.
-<span id="sigil">sigil</span>                  |  Like a keyword but composed entirely of non-alphanumeric tokens. For example, `&` is a sigil for references.
-<span id="soundness">soundness</span>          |  A technical term in type theory. Roughly, if a type system is sound, then a program that type-checks is type-safe. That is, one can never (in safe rust) force a value into a variable of the wrong type. (see "completeness").
-<span id="span">span</span>                    |  A location in the user's source code, used for error reporting primarily. These are like a file-name/line-number/column tuple on steroids: they carry a start/end point, and also track macro expansions and compiler desugaring. All while being packed into a few bytes (really, it's an index into a table). See the Span datatype for more.
-<span id="substs">substs</span>                |  The substitutions for a given generic type or item (e.g. the `i32`, `u32` in `HashMap<i32, u32>`).
-<span id="sysroot">sysroot</span>              |  The directory for build artifacts that are loaded by the compiler at runtime. ([see more](../building/bootstrapping.html#what-is-a-sysroot))
-<span id="tag">tag</span>                      |  The "tag" of an enum/generator encodes the [discriminant](#discriminant) of the active variant/state.  Tags can either be "direct" (simply storing the discriminant in a field) or use a ["niche"](#niche).
-<span id="tcx">tcx</span>                      |  The "typing context" (`TyCtxt`), main data structure of the compiler. ([see more](../ty.md))
-<span id="lifetime-tcx">`'tcx`</span>          |  The lifetime of the allocation arenas used by `TyCtxt`. Most data interned during a compilation session will use this lifetime with the exception of HIR data which uses the `'hir` lifetime. ([see more](../ty.md))
-<span id="token">token</span>                  |  The smallest unit of parsing. Tokens are produced after lexing ([see more](../the-parser.md)).
-<span id="tls">[TLS]</span>                    |  Thread-Local Storage. Variables may be defined so that each thread has its own copy (rather than all threads sharing the variable). This has some interactions with LLVM. Not all platforms support TLS.
-<span id="trait-ref">trait reference</span>    |  The name of a trait along with a suitable set of input type/lifetimes. ([see more](../traits/goals-and-clauses.md#trait-ref))
-<span id="trans">trans</span>                  |  Short for "translation", the code to translate MIR into LLVM IR. Renamed to codegen.
-<span id="ty">`Ty`</span>                        |  The internal representation of a type. ([see more](../ty.md))
-<span id="tyctxt">TyCtxt</span>                |  The data structure often referred to as [tcx](#tcx) in code which provides access to session data and the query system.
-<span id="ufcs">UFCS</span>                    |  Short for Universal Function Call Syntax, this is an unambiguous syntax for calling a method. ([see more](../type-checking.md))
-<span id="ut">uninhabited type</span>          |  A type which has _no_ values. This is not the same as a ZST, which has exactly 1 value. An example of an uninhabited type is `enum Foo {}`, which has no variants, and so, can never be created. The compiler can treat code that deals with uninhabited types as dead code, since there is no such value to be manipulated. `!` (the never type) is an uninhabited type. Uninhabited types are also called "empty types".
-<span id="upvar">upvar</span>                  |  A variable captured by a closure from outside the closure.
-<span id="variance">variance</span>            |  Determines how changes to a generic type/lifetime parameter affect subtyping; for example, if `T` is a subtype of `U`, then `Vec<T>` is a subtype `Vec<U>` because `Vec` is *covariant* in its generic parameter. See [the background chapter](./background.md#variance) for a more general explanation. See the [variance chapter](../variance.md) for an explanation of how type checking handles variance.
-<span id="variant-idx">variant index</span>    |  In an enum, identifies a variant by assigning them indices starting at 0.  This is purely internal and not to be confused with the ["discrimiant"](#discriminant) which can be overwritten by the user (e.g. `enum Bool { True = 42, False = 0 }`).
-<span id="wide-ptr">wide pointer</span>        |  A pointer with additional metadata. See "fat pointer" for more.
-<span id="zst">ZST</span>                      |  Zero-Sized Type. A type whose values have size 0 bytes. Since `2^0 = 1`, such types can have exactly one value. For example, `()` (unit) is a ZST. `struct Foo;` is also a ZST. The compiler can do some nice optimizations around ZSTs.
+<!-- &nbsp;s are a workaround for https://github.com/badboy/mdbook-toc/issues/19 -->
+Term                                                  | Meaning
+------------------------------------------------------|--------
+<span id="arena">arena/arena allocation</span> &nbsp; |  An _arena_ is a large memory buffer from which other memory allocations are made. This style of allocation is called _arena allocation_. See [this chapter](../memory.md) for more info.
+<span id="ast">AST</span>                      &nbsp; |  The abstract syntax tree produced by the `rustc_ast` crate; reflects user syntax very closely.
+<span id="binder">binder</span>                &nbsp; |  A "binder" is a place where a variable or type is declared; for example, the `<T>` is a binder for the generic type parameter `T` in `fn foo<T>(..)`, and \|`a`\|` ...` is a binder for the parameter `a`. See [the background chapter for more](./background.md#free-vs-bound).
+<span id="body-id">BodyId</span>               &nbsp; |  An identifier that refers to a specific body (definition of a function or constant) in the crate. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir).
+<span id="bound-var">bound variable</span>     &nbsp; |  A "bound variable" is one that is declared within an expression/term. For example, the variable `a` is bound within the closure expression \|`a`\|` a * 2`. See [the background chapter for more](./background.md#free-vs-bound)
+<span id="codegen">codegen</span>              &nbsp; |  The code to translate MIR into LLVM IR.
+<span id="codegen-unit">codegen unit</span>    &nbsp; |  When we produce LLVM IR, we group the Rust code into a number of codegen units (sometimes abbreviated as CGUs). Each of these units is processed by LLVM independently from one another, enabling parallelism. They are also the unit of incremental re-use. ([see more](../backend/codegen.md))
+<span id="completeness">completeness</span>    &nbsp; |  A technical term in type theory, it means that every type-safe program also type-checks. Having both soundness and completeness is very hard, and usually soundness is more important. (see "soundness").
+<span id="cfg">control-flow graph</span>       &nbsp; |  A representation of the control-flow of a program; see [the background chapter for more](./background.md#cfg)
+<span id="ctfe">CTFE</span>                    &nbsp; |  Short for Compile-Time Function Evaluation, this is the ability of the compiler to evaluate `const fn`s at compile time. This is part of the compiler's constant evaluation system. ([see more](../const-eval.md))
+<span id="cx">cx</span>                        &nbsp; |  We tend to use "cx" as an abbreviation for context. See also `tcx`, `infcx`, etc.
+<span id="ctxt">ctxt</span>                    &nbsp; |  We also use "ctxt" as an abbreviation for context, e.g. [`TyCtxt`](#TyCtxt). See also [cx](#cx) or [tcx](#tcx).
+<span id="dag">DAG</span>                      &nbsp; |  A directed acyclic graph is used during compilation to keep track of dependencies between queries. ([see more](../queries/incremental-compilation.md))
+<span id="data-flow">data-flow analysis</span> &nbsp; |  A static analysis that figures out what properties are true at each point in the control-flow of a program; see [the background chapter for more](./background.md#dataflow).
+<span id="debruijn">DeBruijn Index</span>      &nbsp; |  A technique for describing which binder a variable is bound by using only integers. It has the benefit that it is invariant under variable renaming. ([see more](./background.md#what-is-a-debruijn-index))
+<span id="def-id">DefId</span>                 &nbsp; |  An index identifying a definition (see `rustc_middle/src/hir/def_id.rs`). Uniquely identifies a `DefPath`. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir).
+<span id="discriminant">discriminant</span>    &nbsp; |  The underlying value associated with an enum variant or generator state to indicate it as "active" (but not to be confused with its ["variant index"](#variant-idx)). At runtime, the discriminant of the active variant is encoded in the [tag](#tag).
+<span id="double-ptr">double pointer</span>    &nbsp; |  A pointer with additional metadata. See "fat pointer" for more.
+<span id="drop-glue">drop glue</span>          &nbsp; |  (internal) compiler-generated instructions that handle calling the destructors (`Drop`) for data types.
+<span id="dst">DST</span>                      &nbsp; |  Short for Dynamically-Sized Type, this is a type for which the compiler cannot statically know the size in memory (e.g. `str` or `[u8]`). Such types don't implement `Sized` and cannot be allocated on the stack. They can only occur as the last field in a struct. They can only be used behind a pointer (e.g. `&str` or `&[u8]`).
+<span id="ebl">early-bound lifetime</span>     &nbsp; |  A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted using a `Substs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html#bound-regions))
+<span id="empty-type">empty type</span>        &nbsp; |  see "uninhabited type".
+<span id="fat-ptr">fat pointer</span>          &nbsp; |  A two word value carrying the address of some value, along with some further information necessary to put the value to use. Rust includes two kinds of "fat pointers": references to slices, and trait objects. A reference to a slice carries the starting address of the slice and its length. A trait object carries a value's address and a pointer to the trait's implementation appropriate to that value. "Fat pointers" are also known as "wide pointers", and "double pointers".
+<span id="free-var">free variable</span>       &nbsp; |  A "free variable" is one that is not bound within an expression or term; see [the background chapter for more](./background.md#free-vs-bound)
+<span id="generics">generics</span>            &nbsp; |  The set of generic type parameters defined on a type or item.
+<span id="hir">HIR</span>                      &nbsp; |  The High-level IR, created by lowering and desugaring the AST. ([see more](../hir.md))
+<span id="hir-id">HirId</span>                 &nbsp; |  Identifies a particular node in the HIR by combining a def-id with an "intra-definition offset". See [the HIR chapter for more](../hir.md#identifiers-in-the-hir).
+<span id="hir-map">HIR map</span>              &nbsp; |  The HIR map, accessible via `tcx.hir()`, allows you to quickly navigate the HIR and convert between various forms of identifiers.
+<span id="ice">ICE</span>                      &nbsp; |  Short for internal compiler error, this is when the compiler crashes.
+<span id="ich">ICH</span>                      &nbsp; |  Short for incremental compilation hash, these are used as fingerprints for things such as HIR and crate metadata, to check if changes have been made. This is useful in incremental compilation to see if part of a crate has changed and should be recompiled.
+<span id="infcx">infcx</span>                  &nbsp; |  The type inference context (`InferCtxt`). (see `rustc_middle::infer`)
+<span id="inf-var">inference variable</span>   &nbsp; |  When doing type or region inference, an "inference variable" is a kind of special type/region that represents what you are trying to infer. Think of X in algebra. For example, if we are trying to infer the type of a variable in a program, we create an inference variable to represent that unknown type.
+<span id="intern">intern</span>                &nbsp; |  Interning refers to storing certain frequently-used constant data, such as strings, and then referring to the data by an identifier (e.g. a `Symbol`) rather than the data itself, to reduce memory usage and number of allocations. See [this chapter](../memory.md) for more info.
+<span id="intrinsic">intrinsic</span>          &nbsp; |  Intrinsics are special functions that are implemented in the compiler itself but exposed (often unstably) to users. They do magical and dangerous things. (See [`std::intrinsics`](https://doc.rust-lang.org/std/intrinsics/index.html))
+<span id="ir">IR</span>                        &nbsp; |  Short for Intermediate Representation, a general term in compilers. During compilation, the code is transformed from raw source (ASCII text) to various IRs. In Rust, these are primarily HIR, MIR, and LLVM IR. Each IR is well-suited for some set of computations. For example, MIR is well-suited for the borrow checker, and LLVM IR is well-suited for codegen because LLVM accepts it.
+<span id="irlo">IRLO</span>                    &nbsp; |  `IRLO` or `irlo` is sometimes used as an abbreviation for [internals.rust-lang.org](https://internals.rust-lang.org).
+<span id="item">item</span>                    &nbsp; |  A kind of "definition" in the language, such as a static, const, use statement, module, struct, etc. Concretely, this corresponds to the `Item` type.
+<span id="lang-item">lang item</span>          &nbsp; |  Items that represent concepts intrinsic to the language itself, such as special built-in traits like `Sync` and `Send`; or traits representing operations such as `Add`; or functions that are called by the compiler. ([see more](https://doc.rust-lang.org/1.9.0/book/lang-items.html))
+<span id="lbl">late-bound lifetime</span>      &nbsp; |  A lifetime region that is substituted at its call site. Bound in a HRTB and substituted by specific functions in the compiler, such as `liberate_late_bound_regions`. Contrast with **early-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html#bound-regions))
+<span id="local-crate">local crate</span>      &nbsp; |  The crate currently being compiled. This is in contrast to "upstream crates" which refer to dependencies of the local crate.
+<span id="lto">LTO</span>                      &nbsp; |  Short for Link-Time Optimizations, this is a set of optimizations offered by LLVM that occur just before the final binary is linked. These include optimizations like removing functions that are never used in the final program, for example. _ThinLTO_ is a variant of LTO that aims to be a bit more scalable and efficient, but possibly sacrifices some optimizations. You may also read issues in the Rust repo about "FatLTO", which is the loving nickname given to non-Thin LTO. LLVM documentation: [here][lto] and [here][thinlto].
+<span id="llvm">[LLVM]</span>                  &nbsp; |  (actually not an acronym :P) an open-source compiler backend. It accepts LLVM IR and outputs native binaries. Various languages (e.g. Rust) can then implement a compiler front-end that outputs LLVM IR and use LLVM to compile to all the platforms LLVM supports.
+<span id="memoization">memoization</span>      &nbsp; |  The process of storing the results of (pure) computations (such as pure function calls) to avoid having to repeat them in the future. This is typically a trade-off between execution speed and memory usage.
+<span id="mir">MIR</span>                      &nbsp; |  The Mid-level IR that is created after type-checking for use by borrowck and codegen. ([see more](../mir/index.md))
+<span id="miri">miri</span>                    &nbsp; |  An interpreter for MIR used for constant evaluation. ([see more](../miri.md))
+<span id="mono">monomorphization</span>        &nbsp; |  The process of taking generic implementations of types and functions and instantiating them with concrete types. For example, in the code we might have `Vec<T>`, but in the final executable, we will have a copy of the `Vec` code for every concrete type used in the program (e.g. a copy for `Vec<usize>`, a copy for `Vec<MyStruct>`, etc).
+<span id="normalize">normalize</span>          &nbsp; |  A general term for converting to a more canonical form, but in the case of rustc typically refers to [associated type normalization](../traits/goals-and-clauses.md#normalizeprojection---type).
+<span id="newtype">newtype</span>              &nbsp; |  A wrapper around some other type (e.g., `struct Foo(T)` is a "newtype" for `T`). This is commonly used in Rust to give a stronger type for indices.
+<span id="niche">niche</span>                  &nbsp; |  Invalid bit patterns for a type *that can be used* for layout optimizations. Some types cannot have certain bit patterns. For example, the `NonZero*` integers or the reference `&T` cannot be represented by a 0 bitstring. This means the compiler can perform layout optimizations by taking advantage of the invalid "niche value". An example application for this is the [*Discriminant elision on `Option`-like enums*](https://rust-lang.github.io/unsafe-code-guidelines/layout/enums.html#discriminant-elision-on-option-like-enums), which allows using a type's niche as the ["tag"](#tag) for an `enum` without requiring a separate field.
+<span id="nll">NLL</span>                      &nbsp; |  Short for [non-lexical lifetimes](../borrow_check/region_inference.md), this is an extension to Rust's borrowing system to make it be based on the control-flow graph.
+<span id="node-id">node-id or NodeId</span>    &nbsp; |  An index identifying a particular node in the AST or HIR; gradually being phased out and replaced with `HirId`. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir).
+<span id="obligation">obligation</span>        &nbsp; |  Something that must be proven by the trait system. ([see more](../traits/resolution.md))
+<span id="placeholder">placeholder</span>      &nbsp; |  **NOTE: skolemization is deprecated by placeholder** a way of handling subtyping around "for-all" types (e.g., `for<'a> fn(&'a u32)`) as well as solving higher-ranked trait bounds (e.g., `for<'a> T: Trait<'a>`). See [the chapter on placeholder and universes](../borrow_check/region_inference/placeholders_and_universes.md) for more details.
+<span id="point">point</span>                  &nbsp; |  Used in the NLL analysis to refer to some particular location in the MIR; typically used to refer to a node in the control-flow graph.
+<span id="polymorphize">polymorphize</span>    &nbsp; |  An optimization that avoids unnecessary monomorphisation. ([see more](../backend/monomorph.md#polymorphization))
+<span id="projection">projection</span>        &nbsp; |  A general term for a "relative path", e.g. `x.f` is a "field projection", and `T::Item` is an ["associated type projection"](../traits/goals-and-clauses.md#trait-ref).
+<span id="pc">promoted constants</span>        &nbsp; |  Constants extracted from a function and lifted to static scope; see [this section](../mir/index.md#promoted) for more details.
+<span id="provider">provider</span>            &nbsp; |  The function that executes a query. ([see more](../query.md))
+<span id="quantified">quantified</span>        &nbsp; |  In math or logic, existential and universal quantification are used to ask questions like "is there any type T for which is true?" or "is this true for all types T?"; see [the background chapter for more](./background.md#quantified).
+<span id="query">query</span>                  &nbsp; |  A sub-computation during compilation. Query results can be cached in the current session or to disk for incremental compilation. ([see more](../query.md))
+<span id="recovery">recovery</span>            &nbsp; |  Recovery refers to handling invalid syntax during parsing (e.g. a missing comma) and continuing to parse the AST. This avoid showing spurious errors to the user (e.g. showing 'missing field' errors when the struct definition contains errors).
+<span id="region">region</span>                &nbsp; |  Another term for "lifetime" often used in the literature and in the borrow checker.
+<span id="rib">rib</span>                      &nbsp; |  A data structure in the name resolver that keeps track of a single scope for names. ([see more](../name-resolution.md))
+<span id="scrutinee">scrutinee</div>           &nbsp; |  A scrutinee is the expression that is matched on in `match` expressions and similar pattern matching constructs. For example, in `match x { A => 1, B => 2 }`, the expression `x` is the scrutinee.
+<span id="sess">sess</span>                    &nbsp; |  The compiler session, which stores global data used throughout compilation
+<span id="side-tables">side tables</span>      &nbsp; |  Because the AST and HIR are immutable once created, we often carry extra information about them in the form of hashtables, indexed by the id of a particular node.
+<span id="sigil">sigil</span>                  &nbsp; |  Like a keyword but composed entirely of non-alphanumeric tokens. For example, `&` is a sigil for references.
+<span id="soundness">soundness</span>          &nbsp; |  A technical term in type theory. Roughly, if a type system is sound, then a program that type-checks is type-safe. That is, one can never (in safe rust) force a value into a variable of the wrong type. (see "completeness").
+<span id="span">span</span>                    &nbsp; |  A location in the user's source code, used for error reporting primarily. These are like a file-name/line-number/column tuple on steroids: they carry a start/end point, and also track macro expansions and compiler desugaring. All while being packed into a few bytes (really, it's an index into a table). See the Span datatype for more.
+<span id="substs">substs</span>                &nbsp; |  The substitutions for a given generic type or item (e.g. the `i32`, `u32` in `HashMap<i32, u32>`).
+<span id="sysroot">sysroot</span>              &nbsp; |  The directory for build artifacts that are loaded by the compiler at runtime. ([see more](../building/bootstrapping.html#what-is-a-sysroot))
+<span id="tag">tag</span>                      &nbsp; |  The "tag" of an enum/generator encodes the [discriminant](#discriminant) of the active variant/state.  Tags can either be "direct" (simply storing the discriminant in a field) or use a ["niche"](#niche).
+<span id="tcx">tcx</span>                      &nbsp; |  The "typing context" (`TyCtxt`), main data structure of the compiler. ([see more](../ty.md))
+<span id="lifetime-tcx">`'tcx`</span>          &nbsp; |  The lifetime of the allocation arenas used by `TyCtxt`. Most data interned during a compilation session will use this lifetime with the exception of HIR data which uses the `'hir` lifetime. ([see more](../ty.md))
+<span id="token">token</span>                  &nbsp; |  The smallest unit of parsing. Tokens are produced after lexing ([see more](../the-parser.md)).
+<span id="tls">[TLS]</span>                    &nbsp; |  Thread-Local Storage. Variables may be defined so that each thread has its own copy (rather than all threads sharing the variable). This has some interactions with LLVM. Not all platforms support TLS.
+<span id="trait-ref">trait reference</span>    &nbsp; |  The name of a trait along with a suitable set of input type/lifetimes. ([see more](../traits/goals-and-clauses.md#trait-ref))
+<span id="trans">trans</span>                  &nbsp; |  Short for "translation", the code to translate MIR into LLVM IR. Renamed to codegen.
+<span id="ty">`Ty`</span>                      &nbsp; |  The internal representation of a type. ([see more](../ty.md))
+<span id="tyctxt">TyCtxt</span>                &nbsp; |  The data structure often referred to as [tcx](#tcx) in code which provides access to session data and the query system.
+<span id="ufcs">UFCS</span>                    &nbsp; |  Short for Universal Function Call Syntax, this is an unambiguous syntax for calling a method. ([see more](../type-checking.md))
+<span id="ut">uninhabited type</span>          &nbsp; |  A type which has _no_ values. This is not the same as a ZST, which has exactly 1 value. An example of an uninhabited type is `enum Foo {}`, which has no variants, and so, can never be created. The compiler can treat code that deals with uninhabited types as dead code, since there is no such value to be manipulated. `!` (the never type) is an uninhabited type. Uninhabited types are also called "empty types".
+<span id="upvar">upvar</span>                  &nbsp; |  A variable captured by a closure from outside the closure.
+<span id="variance">variance</span>            &nbsp; |  Determines how changes to a generic type/lifetime parameter affect subtyping; for example, if `T` is a subtype of `U`, then `Vec<T>` is a subtype `Vec<U>` because `Vec` is *covariant* in its generic parameter. See [the background chapter](./background.md#variance) for a more general explanation. See the [variance chapter](../variance.md) for an explanation of how type checking handles variance.
+<span id="variant-idx">variant index</span>    &nbsp; |  In an enum, identifies a variant by assigning them indices starting at 0.  This is purely internal and not to be confused with the ["discrimiant"](#discriminant) which can be overwritten by the user (e.g. `enum Bool { True = 42, False = 0 }`).
+<span id="wide-ptr">wide pointer</span>        &nbsp; |  A pointer with additional metadata. See "fat pointer" for more.
+<span id="zst">ZST</span>                      &nbsp; |  Zero-Sized Type. A type whose values have size 0 bytes. Since `2^0 = 1`, such types can have exactly one value. For example, `()` (unit) is a ZST. `struct Foo;` is also a ZST. The compiler can do some nice optimizations around ZSTs.
 
 [LLVM]: https://llvm.org/
 [lto]: https://llvm.org/docs/LinkTimeOptimization.html
index 64e35bb93cf5aa142c57073454ccc3defff96917..ff549ca624e85991babd480ddd902cfad7864e36 100644 (file)
@@ -3,4 +3,4 @@
 AST validation is the process of checking various correctness properties about
 the AST after macro expansion.
 
-**TODO**: write this chapter.
+**TODO**: write this chapter. [#656](https://github.com/rust-lang/rustc-dev-guide/issues/656)
index 0cae01ef3957fbba3ae2fb9e6f9190612de4040b..f1a64b5ee1d61fe268e6b108de3c0ea4f6c80361 100644 (file)
@@ -1,4 +1,5 @@
 # Inline Assembly
 
-**TODO: You can find more info in
-https://github.com/rust-lang/rust/pull/69171#issue-375572066**
+**TODO**: You can find more info 
+[here](https://github.com/rust-lang/rust/pull/69171#issue-375572066)
+[#1162](https://github.com/rust-lang/rustc-dev-guide/issues/1162)
index 91d8cb3aab2a81d90c4210b7bed958d706947d7b..d2cf8b6929ca5472509666a5d38d158058072e45 100644 (file)
@@ -72,8 +72,8 @@ Here are a few highlights of things it contains:
   from any other version.
 * The [Strict Version Hash](#strict-version-hash) (SVH). This helps ensure the
   correct dependency is loaded.
-* The [Crate Disambiguator](#crate-disambiguator). This is a hash used
-  to disambiguate between different crates of the same name.
+* The [Stable Crate Id](#stable-crate-id). This is a hash used
+  to identify crates.
 * Information about all the source files in the library. This can be used for
   a variety of things, such as diagnostics pointing to sources in a
   dependency.
@@ -114,21 +114,22 @@ computed.
 [incremental compilation]: ../queries/incremental-compilation.md
 [`finalize_and_compute_crate_hash`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/collector/struct.NodeCollector.html#method.finalize_and_compute_crate_hash
 
-### Crate Disambiguator
+### Stable Crate Id
 
-The [`CrateDisambiguator`] is a 128-bit hash used to distinguish between
-different crates of the same name. It is a hash of all the [`-C metadata`] CLI
-options computed in [`compute_crate_disambiguator`]. It is used in a variety
-of places, such as symbol name mangling, crate loading, and much more.
+The [`StableCrateId`] is a 64-bit hash used to identify different crates with
+potentially the same name. It is a hash of the crate name and all the
+[`-C metadata`] CLI options computed in [`StableCrateId::new`]. It is
+used in a variety of places, such as symbol name mangling, crate loading, and
+much more.
 
-By default, all Rust symbols are mangled and incorporate the disambiguator
-hash. This allows multiple versions of the same crate to be included together.
-Cargo automatically generates `-C metadata` hashes based on a variety of
-factors, like the package version, source, and the target kind (a lib and bin
-can have the same crate name, so they need to be disambiguated).
+By default, all Rust symbols are mangled and incorporate the stable crate id.
+This allows multiple versions of the same crate to be included together. Cargo
+automatically generates `-C metadata` hashes based on a variety of factors,
+like the package version, source, and the target kind (a lib and test can have
+the same crate name, so they need to be disambiguated).
 
-[`CrateDisambiguator`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/crate_disambiguator/struct.CrateDisambiguator.html
-[`compute_crate_disambiguator`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/util/fn.compute_crate_disambiguator.html
+[`StableCrateId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/def_id/struct.StableCrateId.html
+[`StableCrateId::new`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/def_id/struct.StableCrateId.html#method.new
 [`-C metadata`]: https://doc.rust-lang.org/rustc/codegen-options/index.html#metadata
 
 ## Crate loading
index f27793140d38010a753a631cc575df2905e8d92d..bb6badcd6e20407dc46763e3da458ed6ab90fdaf 100644 (file)
@@ -43,6 +43,11 @@ you can write:
 in your `.vscode/settings.json` file. This will ask `rust-analyzer` to use
 `x.py check` to check the sources, and the stage 0 rustfmt to format them.
 
+If you're running `coc.nvim`, you can use `:CocLocalConfig` to create a
+`.vim/coc-settings.json` and enter the same settings as above, but replacing
+`editor.formatOnSave: true,` with
+`"coc.preferences.formatOnSaveFiletypes": ["rust"],`.
+
 If running `x.py check` on save is inconvenient, in VS Code you can use a [Build
 Task] instead:
 
index 61af386522ea817e86c0d7ebda4b66ec8e459b5e..b621dde7c202bfab02ef1f6d642638bc105ef54c 100644 (file)
@@ -2,15 +2,6 @@
 
 <!-- toc -->
 
-> **NOTE**: The structure of the repository is going through a lot of
-> transitions. In particular, we want to get to a point eventually where the
-> top-level directory has separate directories for the compiler, build-system,
-> std libs, etc, rather than one huge `src/` directory.
->
-> As of <!-- date: 2021-01 --> January 2021, the standard libraries have been
-> moved to `library/` and the crates that make up the `rustc` compiler itself
-> have been moved to `compiler/`.
-
 Now that we have [seen what the compiler does](./overview.md), let's take a
 look at the structure of the contents of the rust-lang/rust repo.
 
index cf049015d960e628499cd73caa92d6c354248f15..9df9b6dfc153cc8a0e1f7e903232c2b5cca795c3 100644 (file)
@@ -64,7 +64,8 @@ Pull requests (or PRs for short) are the primary mechanism we use to change Rust
 GitHub itself has some [great documentation][about-pull-requests] on using the
 Pull Request feature. We use the "fork and pull" model [described here][development-models],
 where contributors push changes to their personal fork and create pull requests to
-bring those changes into the source repository.
+bring those changes into the source repository. We have more info about how to use git
+when contributing to Rust under [the git section](./git.md).
 
 [about-pull-requests]: https://help.github.com/articles/about-pull-requests/
 [development-models]: https://help.github.com/articles/about-collaborative-development-models/
@@ -144,8 +145,7 @@ CI will also run tidy and will fail if tidy fails.
 Rust follows a _no merge-commit policy_, meaning, when you encounter merge
 conflicts you are expected to always rebase instead of merging.  E.g. always use
 rebase when bringing the latest changes from the master branch to your feature
-branch.  Also, please make sure that fixup commits are squashed into other
-related commits with meaningful commit messages.
+branch.
 
 If you encounter merge conflicts or when a reviewer asks you to perform some
 changes, your PR will get marked as `S-waiting-on-author`. When you resolve
index 6fbabdc914b04f33a9ab1143d991a1a77de015b2..bc59bfeeda02a4df301e75af8befcac32e4600bd 100644 (file)
@@ -12,7 +12,9 @@ reasons:
 - The dependency may have transitive dependencies that have one of the above
   problems.
 
-TODO: what is the vetting process?
+As of <!-- date: 2021-07 --> July 2021, there is no official policy for vetting
+new dependencies to the compiler. Generally, new dependencies are not added 
+to the compiler unless there is a good reason to do so.
 
 ## Permitted dependencies
 
index 5590311483a5d2c29dcd1393fe66d627fb4b962c..9d455084d0da03360182f28499b85662694b99a4 100644 (file)
@@ -314,8 +314,7 @@ Clang always embeds an MD5 checksum, though this does not appear in documentatio
 * New demangler in `libiberty` (gcc source tree).
 * New demangler in LLVM or LLDB.
 
-**TODO**: Check the location of the demangler source.
-[Question on Github](https://github.com/rust-lang/rustc-dev-guide/pull/316#discussion_r283062536).
+**TODO**: Check the location of the demangler source. [#1157](https://github.com/rust-lang/rustc-dev-guide/issues/1157)
 
 #### Reuse Rust compiler for expressions
 
index 38683f98db7d543d4f63ce0c74a6bbd732b098e9..385d7db60fd8c118a7348cb526a5cb5dbbcfe8ac 100644 (file)
@@ -493,10 +493,11 @@ much faster to work on.
 [`rustc_lint_defs`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/index.html
 
 Every lint is implemented via a `struct` that implements the `LintPass` `trait`
-(you also implement one of the more specific lint pass traits, either
-`EarlyLintPass` or `LateLintPass`). The trait implementation allows you to
-check certain syntactic constructs as the linter walks the source code. You can
-then choose to emit lints in a very similar way to compile errors.
+(you can also implement one of the more specific lint pass traits, either
+`EarlyLintPass` or `LateLintPass` depending on when is best for your lint to run). 
+The trait implementation allows you to check certain syntactic constructs 
+as the linter walks the AST. You can then choose to emit lints in a 
+very similar way to compile errors.
 
 You also declare the metadata of a particular lint via the `declare_lint!`
 macro. This includes the name, the default level, a short description, and some
@@ -566,7 +567,7 @@ impl EarlyLintPass for WhileTrue {
 }
 ```
 
-### Edition-gated Lints
+### Edition-gated lints
 
 Sometimes we want to change the behavior of a lint in a new edition. To do this,
 we just add the transition to our invocation of `declare_lint!`:
@@ -583,6 +584,24 @@ declare_lint! {
 This makes the `ANONYMOUS_PARAMETERS` lint allow-by-default in the 2015 edition
 but warn-by-default in the 2018 edition.
 
+### Future-incompatible lints
+
+The use of the term `future-incompatible` within the compiler has a slightly
+broader meaning than what rustc exposes to users of the compiler.
+
+Inside rustc, future-incompatible lints are for signalling to the user that code they have 
+written may not compile in the future. In general, future-incompatible code
+exists for two reasons:
+* the user has written unsound code that the compiler mistakenly accepted. While 
+it is within Rust's backwards compatibility guarantees to fix the soundness hole 
+(breaking the user's code), the lint is there to warn the user that this will happen 
+in some upcoming version of rustc *regardless of which edition the code uses*. This is the 
+meaning that rustc exclusively exposes to users as "future incompatible".
+* the user has written code that will either no longer compiler *or* will change 
+meaning in an upcoming *edition*. These are often called "edition lints" and can be
+typically seen in the various "edition compatibility" lint groups (e.g., `rust_2021_compatibility`)
+that are used to lint against code that will break if the user updates the crate's edition.
+
 A future-incompatible lint should be declared with the `@future_incompatible`
 additional "field":
 
@@ -593,31 +612,34 @@ declare_lint! {
     "detects anonymous parameters",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #41686 <https://github.com/rust-lang/rust/issues/41686>",
-        edition: Some(Edition::Edition2018),
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018),
     };
 }
 ```
 
-If you need a combination of options that's not supported by the `declare_lint!`
-macro, you can always define your own static with a type of `&Lint` but this is
-(as of <!-- date: 2021-01 --> January 2021) linted against in the compiler tree.
+Notice the `reason` field which describes why the future incompatible change is happening.
+This will change the diagnostic message the user receives as well as determine which
+lint groups the lint is added to. In the example above, the lint is an "edition lint"
+(since it's "reason" is `EditionError`) signifying to the user that the use of anonymous 
+parameters will no longer compile in Rust 2018 and beyond.
 
-<a id="future-incompatible"></a>
-####  Guidelines for creating a future incompatibility lint
+Inside [LintStore::register_lints][fi-lint-groupings], lints with `future_incompatible` 
+fields get placed into either edition-based lint groups (if their `reason` is tied to 
+an edition) or into the `future_incompatibility` lint group.
 
-- Create a lint defaulting to warn as normal, with ideally the same error
-  message you would normally give.
-- Add a suitable reference, typically an RFC or tracking issue. Go ahead
-  and include the full URL, sort items in ascending order of issue numbers.
-- Later, change lint to error.
-- Eventually, remove lint.
+[fi-lint-groupings]: https://github.com/rust-lang/rust/blob/51fd129ac12d5bfeca7d216c47b0e337bf13e0c2/compiler/rustc_lint/src/context.rs#L212-L237
+
+If you need a combination of options that's not supported by the
+`declare_lint!` macro, you can always change the `declare_lint!` macro
+to support this.
 
 ### Renaming or removing a lint
 
-A lint can be renamed or removed, which will trigger a warning if a user tries
+If it is determined that a lint is either improperly named or no longer needed, 
+the lint must be registered for renaming or removal, which will trigger a warning if a user tries
 to use the old lint name. To declare a rename/remove, add a line with
 [`store.register_renamed`] or [`store.register_removed`] to the code of the
-[`register_builtins`] function.
+[`rustc_lint::register_builtins`] function.
 
 ```rust,ignore
 store.register_renamed("single_use_lifetime", "single_use_lifetimes");
@@ -625,7 +647,7 @@ store.register_renamed("single_use_lifetime", "single_use_lifetimes");
 
 [`store.register_renamed`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_renamed
 [`store.register_removed`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_removed
-[`register_builtins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_builtins.html
+[`rustc_lint::register_builtins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_builtins.html
 
 ### Lint Groups
 
@@ -649,6 +671,14 @@ This defines the `nonstandard_style` group which turns on the listed lints. A
 user can turn on these lints with a `!#[warn(nonstandard_style)]` attribute in
 the source code, or by passing `-W nonstandard-style` on the command line.
 
+Some lint groups are created automatically in `LintStore::register_lints`. For instance, 
+any lint declared with `FutureIncompatibleInfo` where the reason is 
+`FutureIncompatibilityReason::FutureReleaseError` (the default when 
+`@future_incompatible` is used in `declare_lint!`), will be added to
+the `future_incompatible` lint group. Editions also have their own lint groups 
+(e.g., `rust_2021_compatibility`) automatically generated for any lints signaling
+future-incompatible code that will break in the specified edition.
+
 ### Linting early in the compiler
 
 On occasion, you may need to define a lint that runs before the linting system
@@ -682,7 +712,7 @@ then dumped into the `Session::buffered_lints` used by the rest of the compiler.
 
 The compiler accepts an `--error-format json` flag to output
 diagnostics as JSON objects (for the benefit of tools such as `cargo
-fix` or the RLS). It looks like this
+fix` or the RLS). It looks like this:
 
 ```console
 $ rustc json_error_demo.rs --error-format json
index 6a59cf264745ac4a431bc68ef46101dd1c6e5d16..d2796c07049d40d6eb623bf04f42a0509fed5034 100644 (file)
@@ -3,7 +3,7 @@
 This page documents some of the machinery around lint registration and how we
 run lints in the compiler.
 
-The `LintStore` is the central piece of infrastructure, around which everything
+The [`LintStore`] is the central piece of infrastructure, around which everything
 rotates. It's not available during the early parts of compilation (i.e., before
 TyCtxt) in most code, as we need to fill it in with all of the lints, which can only happen after
 plugin registration.
@@ -17,10 +17,9 @@ First, we have the lint declarations themselves: this is where the name and defa
 other metadata come from. These are normally defined by way of the [`declare_lint!`] macro, which
 boils down to a static with type `&rustc_session::lint::Lint`.
 
-As of <!-- date: 2021-01 --> January 2021, we lint against direct declarations
+As of <!-- date: 2021-07 --> July 2021, we lint against direct declarations
 without the use of the macro today (although this may change in the future, as
-the macro is somewhat unwieldy to add new fields to, like all macros by
-example).
+the macro is somewhat unwieldy to add new fields to, like all macros).
 
 Lint declarations don't carry any "state" - they are merely global identifers and descriptions of
 lints. We assert at runtime that they are not registered twice (by lint name).
@@ -34,44 +33,57 @@ lint, and frequently lints are emitted as part of other work (e.g., type checkin
 
 ### High-level overview
 
-The lint store is created and all lints are registered during plugin registration, in
-[`rustc_interface::register_plugins`]. There are three 'sources' of lint: the internal lints, plugin
-lints, and `rustc_interface::Config` [`register_lints`]. All are registered here, in
-`register_plugins`.
+In [`rustc_interface::register_plugins`] the [`LintStore`] is created and all lints are registered. 
+There are four 'sources' of lints: 
+* internal lints: lints only used by the rustc codebase
+* builtin lints: lints built into the compiler and not provided by some outside source
+* plugin lints: lints created by plugins through the plugin system.
+* `rustc_interface::Config`[`register_lints`]: lints passed into the compiler during construction
+
+Lints are registered via the [`LintStore::register_lint`] function. This should
+happen just once for any lint, or an ICE will occur.
 
 Once the registration is complete, we "freeze" the lint store by placing it in an `Lrc`. Later in
 the driver, it's passed into the `GlobalCtxt` constructor where it lives in an immutable form from
 then on.
 
-Lints are registered via the [`LintStore::register_lint`] function. This should
-happen just once for any lint, or an ICE will occur.
-
 Lint passes are registered separately into one of the categories (pre-expansion,
 early, late, late module). Passes are registered as a closure -- i.e., `impl
 Fn() -> Box<dyn X>`, where `dyn X` is either an early or late lint pass trait
 object. When we run the lint passes, we run the closure and then invoke the lint
-pass methods, which take `&mut self` -- lint passes can keep track of state
+pass methods. The lint pass methods take `&mut self` so they can keep track of state
 internally.
 
 #### Internal lints
 
-Note, these include both rustc-internal lints, and the traditional lints, like, for example the dead
-code lint.
+These are lints used just by the compiler or plugins like `clippy`. They can be found in 
+`rustc_lint::internal`.
+
+An example of such a lint is the check that lint passes are implemented using the 
+`declare_lint_pass!` macro and not by hand. This is accomplished with the 
+`LINT_PASS_IMPL_WITHOUT_MACRO` lint.
+
+Registration of these lints happens in the [`rustc_lint::register_internals`] function which is
+called when constructing a new lint store inside [`rustc_lint::new_lint_store`].
+
+### Builtin Lints
 
 These are primarily described in two places: `rustc_session::lint::builtin` and
-`rustc_lint::builtin`. The first provides the definitions for the lints themselves,
-and the latter provides the lint pass definitions (and implementations).
+`rustc_lint::builtin`. Often the first provides the definitions for the lints themselves,
+and the latter provides the lint pass definitions (and implementations), but this is not always
+true.
 
-The internal lint registration happens in the [`rustc_lint::register_builtins`] function, along with
-the [`rustc_lint::register_internals`] function. More generally, the LintStore "constructor"
-function which is *the* way to get a `LintStore` in the compiler (you should not construct it
-directly) is [`rustc_lint::new_lint_store`]; it calls the registration functions.
+The builtin lint registration happens in the [`rustc_lint::register_builtins`] function. Just like
+with internal lints, this happens inside of [`rustc_lint::new_lint_store`].
 
 #### Plugin lints
 
-This is one of the primary use cases remaining for plugins/drivers. Plugins are given access to the
-mutable `LintStore` during registration to call any functions they need on the `LintStore`, just
-like rustc code. Plugins are intended to declare lints with the `plugin` field set to true (e.g., by
+This is one of the primary use cases remaining for plugins/drivers. Plugins are given access 
+to the mutable `LintStore` during registration (which happens inside of 
+[`rustc_interface::register_plugins`]) and they can call any functions they need on 
+the `LintStore`, just like rustc code. 
+
+Plugins are intended to declare lints with the `plugin` field set to true (e.g., by
 way of the [`declare_tool_lint!`] macro), but this is purely for diagnostics and help text;
 otherwise plugin lints are mostly just as first class as rustc builtin lints.
 
@@ -86,18 +98,15 @@ within the callback they add. The best way for drivers to get access to this is
 
 Within the compiler, for performance reasons, we usually do not register dozens
 of lint passes. Instead, we have a single lint pass of each variety
-(e.g. `BuiltinCombinedModuleLateLintPass`) which will internally call all of the
+(e.g., `BuiltinCombinedModuleLateLintPass`) which will internally call all of the
 individual lint passes; this is because then we get the benefits of static over
 dynamic dispatch for each of the (often empty) trait methods.
 
-Ideally, we'd not have to do this, since it certainly adds to the complexity of
+Ideally, we'd not have to do this, since it adds to the complexity of
 understanding the code. However, with the current type-erased lint store
 approach, it is beneficial to do so for performance reasons.
 
-New lints being added likely want to join one of the existing declarations like
-`late_lint_mod_passes` in `rustc_lint/src/lib.rs`, which would then
-auto-propagate into the other.
-
+[`LintStore`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html
 [`LintStore::register_lint`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_lints
 [`rustc_interface::register_plugins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/passes/fn.register_plugins.html
 [`rustc_lint::register_builtins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_builtins.html
index 3b3a07a31a627b4a9c3af3064d1c6b3ba3f24837..c17747a11b757799fb5fe7c79bc50a33f37d1865 100644 (file)
@@ -1,3 +1,3 @@
 # Feature Gate Checking
 
-**TODO**: this chapter
+**TODO**: this chapter [#1158](https://github.com/rust-lang/rustc-dev-guide/issues/1158)
index db6c72ff8109396268a2edf4b086aceb6c8ad595..229281f2f0ba0fef9e635da8d97ee8c3acf5cd46 100644 (file)
@@ -27,6 +27,14 @@ For example:
 (active, non_ascii_idents, "1.0.0", Some(55467), None),
 ```
 
+Features can be marked as incomplete, and trigger the warn-by-default [`incomplete_features` lint]
+by setting their type to `incomplete`:
+
+```rust,ignore
+/// Allows unsized rvalues at arguments and parameters.
+(incomplete, unsized_locals, "1.30.0", Some(48055), None),
+```
+
 When added, the current version should be the one for the current nightly.
 Once the feature is moved to `accepted.rs`, the version is changed to that
 nightly version.
@@ -99,4 +107,5 @@ updating the declaration!
 
 
 ["Stability in code"]: ./implementing_new_features.md#stability-in-code
+[`incomplete_features` lint]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#incomplete-features
 ["Updating the feature-gate listing"]: ./stabilization_guide.md#updating-the-feature-gate-listing
index e10f1d7050b1c3fe2ef1340cd3394d756ca01045..1c311982cadc54923b1633291ee47aa7d8efae77 100644 (file)
@@ -46,6 +46,10 @@ git remote add upstream git@github.com:rust-lang/rust.git
 
 if you're using SSH.
 
+**NOTE:** This page is dedicated to workflows for `rust-lang/rust`, but will likely be
+useful when contributing to other repositories in the Rust project.
+
+
 ## Standard Process
 
 Below is the normal procedure that you're likely to use for most minor changes
@@ -53,7 +57,8 @@ and PRs:
 
  1. Ensure that you're making your changes on top of master:
  `git checkout master`.
- 2. Get the latest changes from the Rust repo: `git pull upstream master`.
+ 2. Get the latest changes from the Rust repo: `git pull upstream master --ff-only`.
+ (see [No-Merge Policy](#keeping-things-up-to-date) for more info about this).
  3. Make a new branch for your change: `git checkout -b issue-12345-fix`.
  4. Make some changes to the repo and test them.
  5. Stage your changes via `git add src/changed/file.rs src/another/change.rs`
@@ -62,11 +67,17 @@ and PRs:
  unintentionally commit changes that should not be committed, such as submodule
  updates. You can use `git status` to check if there are any files you forgot
  to stage.
- 6. Push your changes to your fork: `git push --set-upstream origin issue-12345-fix`.
- 7. [Open a PR][ghpullrequest] from your fork to rust-lang/rust's master branch.
+ 6. Push your changes to your fork: `git push --set-upstream origin issue-12345-fix`
+ (After adding commits, you can use `git push` and after rebasing or
+pulling-and-rebasing, you can use `git push --force-with-lease`).
+ 7. [Open a PR][ghpullrequest] from your fork to `rust-lang/rust`'s master branch.
 
 [ghpullrequest]: https://guides.github.com/activities/forking/#making-a-pull-request
 
+If you end up needing to rebase and are hitting conflicts, see [Rebasing](#rebasing).
+If you want to track upstream while working on long-running feature/issue, see
+[Keeping things up to date](#keeping-things-up-to-date).
+
 If your reviewer requests changes, the procedure for those changes looks much
 the same, with some steps skipped:
 
@@ -146,7 +157,7 @@ no changes added to commit (use "git add" and/or "git commit -a")
 These changes are not changes to files: they are changes to submodules (more on
 this [later](#git-submodules)). To get rid of those, run `git submodule update`
 (or run any `x.py` command, which will automatically update the submodules).
-Note that there is (as of <!-- date: 2021-01 --> January 2021) a bug if you use
+Note that there is (as of <!-- date: 2021-07 --> July 2021) a [bug][#77620] if you use
 worktrees, submodules, and x.py in a commit hook.  If you run into an error
 like:
 
@@ -156,11 +167,12 @@ error: failed to read `/home/joshua/rustc-worktree/src/tools/miri/cargo-miri/Car
 Caused by:
   No such file or directory (os error 2)
 ```
-it's not anything you did wrong. There is a workaround at [#77620].
+it's not anything you did wrong. There is a workaround in [the issue][#77620-workaround].
 
-[#77620]: https://github.com/rust-lang/rust/issues/77620#issuecomment-705228229
+[#77620]: https://github.com/rust-lang/rust/issues/77620
+[#77620-workaround]: https://github.com/rust-lang/rust/issues/77620#issuecomment-705228229
 
-## Conflicts
+## Rebasing and Conflicts
 
 When you edit your code locally, you are making changes to the version of
 rust-lang/rust that existed when you created your feature branch. As such, when
@@ -236,6 +248,34 @@ The advice this gives is incorrect! Because of Rust's
 will not be allowed in the final PR, in addition to defeating the point of the
 rebase! Use `git push --force-with-lease` instead.
 
+### Keeping things up to date
+
+The above section on [Rebasing](#rebasing) is a specific
+guide on rebasing work and dealing with merge conflicts.
+Here is some general advice about how to keep your local repo
+up-to-date with upstream changes:
+
+Using `git pull upstream master` while on your local master branch regularly
+will keep it up-to-date. You will also want to rebase your feature branches
+up-to-date as well. After pulling, you can checkout the feature branches
+and rebase them:
+
+```
+git checkout master
+git pull upstream master --ff-only # to make certain there are no merge commits
+git checkout feature_branch
+git rebase master
+git push --force-with-lease (set origin to be the same as local)
+```
+
+To avoid merges as per the [No-Merge Policy][#no-merge-policy], you may want to use
+`git config pull.ff only` (this will apply the config to the local repo).
+to avoid merge conflicts while pulling, without needing
+`--ff-only` or `--rebase` while `git pull`ing
+
+You can also `git push --force-with-lease` from master to keep your origin's master in sync with
+upstream.
+
 ## Advanced Rebasing
 
 If your branch contains multiple consecutive rewrites of the same code, or if
@@ -330,6 +370,7 @@ that merge commits in PRs are not accepted. As a result, if you are running
 course, this is not always true; if your merge will just be a fast-forward,
 like the merges that `git pull` usually performs, then no merge commit is
 created and you have nothing to worry about. Running `git config merge.ff only`
+(this will apply the config to the local repo).
 once will ensure that all the merges you perform are of this type, so that you
 cannot make a mistake.
 
index 519ff26677e6c38f01ad165a1fc39c5754d64c2d..8788ad4de1ac4f85bf294400a7493e27da3f6c11 100644 (file)
@@ -5,4 +5,4 @@ The `-Z unpretty=hir-tree` flag will dump out the HIR.
 If you are trying to correlate `NodeId`s or `DefId`s with source code, the
 `--pretty expanded,identified` flag may be useful.
 
-TODO: anything else?
+TODO: anything else? [#1159](https://github.com/rust-lang/rustc-dev-guide/issues/1159)
index 50d0c76e2f7bd265d8dd92a3fea45ee0000a785d..18a3efefcd8a13f1716fdb2c706fe26ffbea83f3 100644 (file)
@@ -82,7 +82,7 @@ See the [HIR chapter][hir-map] for more detailed information.
 - [`Promoted`] identifies a promoted constant within another item (related to
   const evaluation). Note: it is unique only locally within the item, so it
   should be associated with a `DefId`.
-  [`GlobalId`] will give you a more specific identifier (TODO).
+  [`GlobalId`] will give you a more specific identifier.
 
 - [`GlobalId`] identifies a global variable: a `const`, a `static`, a `const fn`
   where all arguments are [zero-sized types], or a promoted constant.
diff --git a/src/doc/rustc-dev-guide/src/lang-items.md b/src/doc/rustc-dev-guide/src/lang-items.md
new file mode 100644 (file)
index 0000000..c5774c4
--- /dev/null
@@ -0,0 +1,67 @@
+# Lang items
+
+The compiler has certain pluggable operations; that is, functionality that isn't hard-coded into
+the language, but is implemented in libraries, with a special marker to tell the compiler it
+exists. The marker is the attribute `#[lang = "..."]`, and there are various different values of
+`...`, i.e. various different 'lang items'.
+
+Many such lang items can be implemented only in one sensible way, such as `add` (`trait
+core::ops::Add`) or `future_trait` (`trait core::future::Future`). Others can be overriden to
+achieve some specific goals; for example, you can control your binary's entrypoint.
+
+Features provided by lang items include:
+
+- overloadable operators via traits: the traits corresponding to the
+  `==`, `<`, dereference (`*`), `+`, etc. operators are all
+  marked with lang items; those specific four are `eq`, `ord`,
+  `deref`, and `add` respectively.
+- panicking and stack unwinding; the `eh_personality`, `panic` and
+  `panic_bounds_checks` lang items.
+- the traits in `std::marker` used to indicate properties of types used by the compiler;
+  lang items `send`, `sync` and `copy`.
+- the special marker types used for variance indicators found in
+  `core::marker`; lang item `phantom_data`.
+
+Lang items are loaded lazily by the compiler; e.g. if one never uses `Box`
+then there is no need to define functions for `exchange_malloc` and
+`box_free`. `rustc` will emit an error when an item is needed but not found
+in the current crate or any that it depends on.
+
+Most lang items are defined by the `core` library, but if you're trying to build an
+executable with `#![no_std]`, you'll still need to define a few lang items that are
+usually provided by `std`.
+
+## Retrieving a language item
+
+You can retrieve lang items by calling [`tcx.lang_items()`].
+
+Here's a small example of retrieving the `trait Sized {}` language item:
+
+```rust
+// Note that in case of `#![no_core]`, the trait is not available.
+if let Some(sized_trait_def_id) = tcx.lang_items().sized_trait() {
+    // do something with `sized_trait_def_id`
+}
+```
+
+Note that `sized_trait()` returns an `Option`, not the `DefId` itself.
+That's because language items are defined in the standard libray, so if someone compiles with
+`#![no_core]` (or for some lang items, `#![no_std]`), the lang item may not be present.
+You can either:
+
+- Give a hard error if the lang item is necessary to continue (don't panic, since this can happen in
+  user code).
+- Proceed with limited functionality, by just omitting whatever you were going to do with the
+  `DefId`.
+
+[`tcx.lang_items()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.lang_items
+
+## List of all language items
+
+You can find language items in the following places:
+- An exhaustive reference in the compiler documentation: [`rustc_hir::LangItem`]
+- An auto-generated list with source locations by using ripgrep: `rg '#\[.*lang =' library/`
+
+Note that language items are explicitly unstable and may change in any new release.
+
+[`rustc_hir::LangItem`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/lang_items/enum.LangItem.html
index 7385cefb38449f2c897101709b044b397b7dcf3b..ce82852832058f8221f0c661bd708f857829c585 100644 (file)
@@ -608,10 +608,10 @@ Because the Rust ABI is unstable, we use the C ABI for this conversion.
 [pm]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/proc_macro/index.html
 [pms]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/proc_macro_server/index.html
 
-TODO: more here.
+TODO: more here. [#1160](https://github.com/rust-lang/rustc-dev-guide/issues/1160)
 
 ### Custom Derive
 
 Custom derives are a special type of proc macro.
 
-TODO: more?
+TODO: more? [#1160](https://github.com/rust-lang/rustc-dev-guide/issues/1160)
index 18cd6ed3923a6368396ff482319ef0ab4f39d4dd..c19ba6401249f13bc7a8f391dd73f5c1a9c83384 100644 (file)
@@ -197,10 +197,9 @@ Miri's virtual memory.  This is in contrast to `Scalar::Raw`, which is just some
 concrete integer.
 
 However, a variable of pointer or reference *type*, such as `*const T` or `&T`,
-does not have to have a pointer *value*: it could be obtaining by casting or
-transmuting an integer to a pointer (as of <!-- date: 2021-01 --> January 2021
-that is hard to do in const eval, but eventually `transmute` will be stable as a
-`const fn`).  And similarly, when casting or transmuting a reference to some
+does not have to have a pointer *value*: it could be obtained by casting or
+transmuting an integer to a pointer. 
+And similarly, when casting or transmuting a reference to some
 actual allocation to an integer, we end up with a pointer *value*
 (`Scalar::Ptr`) at integer *type* (`usize`).  This is a problem because we
 cannot meaningfully perform integer operations such as division on pointer
index 2eb76384c0f3fb36b6920a5e8211750b0ecdae0c..1cef7d08fa806ea946428a8ff3bb82079fdaf66e 100644 (file)
@@ -164,7 +164,7 @@ To tell the difference between speculative loads and loads initiated by the
 user, resolve passes around a `record_used` parameter, which is `false` when
 the load is speculative.
 
-## TODO:
+## TODO: [#16](https://github.com/rust-lang/rustc-dev-guide/issues/16)
 
 This is a result of the first pass of learning the code. It is definitely
 incomplete and not detailed enough. It also might be inaccurate in places.
index 1aa79e791466aabc84204919af7949e1c778bcb6..6c756e18ff58bd217019a552262c431b5c0a7a82 100644 (file)
@@ -68,10 +68,14 @@ we'll talk about that later.
 - We then take the AST and [convert it to High-Level Intermediate
   Representation (HIR)][hir]. This is a compiler-friendly representation of the
   AST.  This involves a lot of desugaring of things like loops and `async fn`.
-- We use the HIR to do [type inference]. This is the process of automatic
-  detection of the type of an expression.
-- **TODO: Maybe some other things are done here? I think initial type checking
-  happens here? And trait solving?**
+- We use the HIR to do [type inference] (the process of automatic
+  detection of the type of an expression), [trait solving] (the process
+  of pairing up an impl with each reference to a trait), and [type
+  checking] (the process of converting the types found in the HIR
+  (`hir::Ty`), which represent the syntactic things that the user wrote,
+  into the internal representation used by the compiler (`Ty<'tcx>`),
+  and using that information to verify the type safety, correctness and
+  coherence of the types used in the program).
 - The HIR is then [lowered to Mid-Level Intermediate Representation (MIR)][mir].
   - Along the way, we construct the THIR, which is an even more desugared HIR.
     THIR is used for pattern and exhaustiveness checking. It is also more
@@ -111,6 +115,8 @@ we'll talk about that later.
 [parser]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html
 [hir]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/index.html
 [type inference]: https://rustc-dev-guide.rust-lang.org/type-inference.html
+[trait solving]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
+[type checking]: https://rustc-dev-guide.rust-lang.org/type-checking.html
 [mir]: https://rustc-dev-guide.rust-lang.org/mir/index.html
 [borrow checking]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
 [mir-opt]: https://rustc-dev-guide.rust-lang.org/mir/optimizations.html
index 8be19e8dcfe5f730bf85008f286c837ad30af27e..eec8219a5b7fce7e8194db63cd102e38be520a00 100644 (file)
@@ -3,7 +3,7 @@
 Most of the compiler is not parallel. This represents an opportunity for
 improving compiler performance.
 
-As of <!-- date: 2021-01 --> January 2021, work on explicitly parallelizing the
+As of <!-- date: 2021-07 --> July 2021, work on explicitly parallelizing the
 compiler has stalled. There is a lot of design and correctness work that needs
 to be done.
 
index aa3a8132839d486dc04b6143cfdc921558741382..20e547b1e35db498310f6e27c754505760ba8758 100644 (file)
@@ -1,7 +1,7 @@
 # Queries: demand-driven compilation
 
 As described in [the high-level overview of the compiler][hl], the Rust compiler
-is still (as of <!-- date: 2021-01 --> January 2021) transitioning from a
+is still (as of <!-- date: 2021-07 --> July 2021) transitioning from a
 traditional "pass-based" setup to a "demand-driven" system. **The Compiler Query
 System is the key to our new demand-driven organization.** The idea is pretty
 simple. You have various queries that compute things about the input – for
index bfe7538247831d56e61c52173c8897caaf582c56..9bf93727a38346e76f28e00d6e30fea203e2fa7c 100644 (file)
@@ -9,7 +9,7 @@ want to watch [Salsa In More
 Depth](https://www.youtube.com/watch?v=i_IhACacPRY), also by Niko
 Matsakis.
 
-> As of <!-- date: 2021-01 --> January 2021, although Salsa is inspired by
+> As of <!-- date: 2021-07 --> July 2021, although Salsa is inspired by
 > (among other things) rustc's query system, it is not used directly in rustc.
 > It _is_ used in chalk and extensively in `rust-analyzer`, but there are no
 > medium or long-term concrete plans to integrate it into the compiler.
index cfb4efd891fa8a9effca9b762b052d386753756e..7eff3e88bc618104620fb04a9f9226d22f44ddb7 100644 (file)
@@ -44,7 +44,7 @@ prevents breaking dependencies by leveraging Cargo's lint capping.
 [rustc bug]: https://github.com/rust-lang/rust/issues/15702
 
 ## stable
-The `#[stable(feature = "foo", "since = "1.420.69")]` attribute explicitly
+The `#[stable(feature = "foo", since = "1.420.69")]` attribute explicitly
 marks an item as stabilized. Note that stable functions may use unstable things in their body.
 
 ## rustc_const_unstable
@@ -60,7 +60,7 @@ there's no way to add `const` to functions in `extern` blocks for now.
 
 ## rustc_const_stable
 
-The `#[rustc_const_stable(feature = "foo", "since = "1.420.69")]` attribute explicitly marks
+The `#[rustc_const_stable(feature = "foo", since = "1.420.69")]` attribute explicitly marks
 a `const fn` as having its constness be `stable`. This attribute can make sense
 even on an `unstable` function, if that function is called from another
 `rustc_const_stable` function.
@@ -85,28 +85,39 @@ To stabilize a feature, follow these steps:
    - Add the appropriate labels: `@rustbot modify labels: +T-libs`.
    - Link to the tracking issue and say "Closes #XXXXX".
 
-You can see an example of stabilizing a feature at [#75132](https://github.com/rust-lang/rust/pull/75132).
+You can see an example of stabilizing a feature with
+[tracking issue #81656 with FCP](https://github.com/rust-lang/rust/issues/81656)
+and the associated
+[implementation PR #84642](https://github.com/rust-lang/rust/pull/84642).
 
 ## allow_internal_unstable
 
-Macros, compiler desugarings and `const fn`s expose their bodies to the call
+Macros and compiler desugarings expose their bodies to the call
 site. To work around not being able to use unstable things in the standard
 library's macros, there's the `#[allow_internal_unstable(feature1, feature2)]`
-attribute that allows the given features to be used in stable macros or
-`const fn`s.
-
-Note that `const fn`s are even more special in this regard. You can't just
-allow any feature, the features need an implementation in
-`qualify_min_const_fn.rs`. For example the `const_fn_union` feature gate allows
-accessing fields of unions inside stable `const fn`s. The rules for when it's
-ok to use such a feature gate are that behavior matches the runtime behavior of
-the same code (see also [this blog post][blog]). This means that you may not
-create a `const fn` that e.g. transmutes a memory address to an integer,
+attribute that allows the given features to be used in stable macros.
+
+## rustc_allow_const_fn_unstable
+
+`const fn`, while not directly exposing their body to the world, are going to get
+evaluated at compile time in stable crates. If their body does something const-unstable,
+that could lock us into certain features indefinitely by accident. Thus no unstable const
+features are allowed inside stable `const fn`.
+
+However, sometimes we do know that a feature will get
+stabilized, just not when, or there is a stable (but e.g. runtime-slow) workaround, so we
+could always fall back to some stable version if we scrapped the unstable feature.
+In those cases, the rustc_allow_const_fn_unstable attribute can be used to allow some
+unstable features in the body of a stable `const fn`.
+
+You also need to take care to uphold the `const fn` invariant that calling it at runtime and
+compile-time needs to behave the same (see also [this blog post][blog]). This means that you
+may not create a `const fn` that e.g. transmutes a memory address to an integer,
 because the addresses of things are nondeterministic and often unknown at
 compile-time.
 
-Always ping @oli-obk, @RalfJung, and @Centril if you are adding more
-`allow_internal_unstable` attributes to any `const fn`
+Always ping @rust-lang/wg-const-eval if you are adding more
+`rustc_allow_const_fn_unstable` attributes to any `const fn`.
 
 ## staged_api
 
index 874ef82746114c5efd1f5c35ae4420469d8dacdf..34a44f9c24c133cd4f296a0042756c8dc3bc70c0 100644 (file)
@@ -92,6 +92,20 @@ tests for components you did not change at all.
 build; therefore, while the tests **usually** work fine with stage 1,
 there are some limitations.
 
+## Run unit tests on the compiler/library
+
+You may want to run unit tests on a specific file with following:
+
+```bash
+./x.py test compiler/rustc_data_structures/src/thin_vec/tests.rs
+```
+
+But unfortunately, it's impossible. You should invoke following instead:
+
+```bash
+./x.py test compiler/rustc_data_structures/ --test-args thin_vec
+```
+
 ## Running an individual test
 
 Another common thing that people want to do is to run an **individual
index 797cd9487a8873e5bd1f2765a438ac039b66a54e..cd58faf22bf6d2561569868c1ca82761f9a87fe6 100644 (file)
@@ -41,4 +41,4 @@ For more details, see the [`collect`][collect] module.
 [queries]: ./query.md
 [collect]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/collect/
 
-**TODO**: actually talk about type checking...
+**TODO**: actually talk about type checking... [#1161](https://github.com/rust-lang/rustc-dev-guide/issues/1161)
index 71c2b08b19070ae2c7ca75c5753b50c0e06b69ff..4be9211eeed4c084bbbc637a50277308418743ac 100644 (file)
@@ -71,8 +71,8 @@ inference works, or perhaps this blog post on
 
 [Unification in the Chalk project]: http://smallcultfollowing.com/babysteps/blog/2017/03/25/unification-in-chalk-part-1/
 
-All told, the inference context stores four kinds of inference variables
-(as of <!-- date: 2018-01 --> January 2018):
+All told, the inference context stores five kinds of inference variables
+(as of <!-- date: 2021-06 --> June 2021):
 
 - Type variables, which come in three varieties:
   - General type variables (the most common). These can be unified with any
@@ -82,6 +82,7 @@ All told, the inference context stores four kinds of inference variables
   - Float type variables, which can only be unified with a float type, and
     arise from a float literal expression like `22.0`.
 - Region variables, which represent lifetimes, and arise all over the place.
+- Const variables, which represent constants.
 
 All the type variables work in much the same way: you can create a new
 type variable, and what you get is `Ty<'tcx>` representing an
index b0d040942e70013ae317c0cb1f1430655507a049..5841afe4f54a8362a12e3b72f7f3aa038378890b 100644 (file)
@@ -188,7 +188,7 @@ don't request anyone; the bot will assign someone automatically.
 
 The reviewer may request changes before they approve your PR. Feel free to ask
 questions or discuss things you don't understand or disagree with. However,
-recognize that the PR won't be merged unless someone on the rust team approves
+recognize that the PR won't be merged unless someone on the Rust team approves
 it.
 
 When your reviewer approves the PR, it will go into a queue for yet another bot
index 3225e95941cf3e03591d48a9d297eaf32bbb4855..885010b039eacd7d0422f6110286c4a2b711f8eb 100644 (file)
@@ -248,6 +248,7 @@ target | std | host | notes
 `powerpc-wrs-vxworks-spe` | ? |  |
 `powerpc-wrs-vxworks` | ? |  |
 `powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2)
+`powerpc64le-unknown-freebsd` |   |   | PPC64LE FreeBSD
 `powerpc64-unknown-linux-musl` | ? |  |
 `powerpc64-wrs-vxworks` | ? |  |
 `powerpc64le-unknown-linux-musl` | ? |  |
index ae94527e2b4ca80ee5dfb25d6722ebe71235e161..3fa91bb51f02fb7d8c0ee8d2a6fac50c6aa410da 100644 (file)
@@ -10,5 +10,6 @@
 - [Lints](lints.md)
 - [Advanced features](advanced-features.md)
 - [Unstable features](unstable-features.md)
+- [Website features](website-features.md)
 - [Passes](passes.md)
 - [References](references.md)
index 2e4016e24bc3fa8d81333c5f93f2f1be94ed68b1..c8af369a9695e7f6f9f82985a7e32181f25c6f02 100644 (file)
@@ -417,3 +417,10 @@ This flag is **deprecated** and **has no effect**.
 Rustdoc only supports Rust source code and Markdown input formats. If the
 file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file.
 Otherwise, it assumes that the input file is Rust.
+
+## `--nocapture`
+
+When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be
+captured by rustdoc. Instead, the output will be directed to your terminal,
+as if you had run the test executable manually. This is especially useful
+for debugging your tests!
diff --git a/src/doc/rustdoc/src/website-features.md b/src/doc/rustdoc/src/website-features.md
new file mode 100644 (file)
index 0000000..5fade4e
--- /dev/null
@@ -0,0 +1,25 @@
+# Website features
+
+These features are about using the website generated by `rustdoc`.
+
+## Custom search engines
+
+If you find yourself often referencing online Rust docs you might enjoy using a custom search
+engine. This allows you to use the navigation bar directly to search a `rustdoc` website.
+Most browsers support this feature by letting you define a URL template containing `%s`
+which will be substituted for the search term. As an example, for the standard library you could use
+this template:
+
+```text
+https://doc.rust-lang.org/stable/std/?search=%s
+```
+
+Note that this will take you to a results page listing all matches. If you want to navigate to the first
+result right away (which is often the best match) use the following instead:
+
+```text
+https://doc.rust-lang.org/stable/std/?search=%s&go_to_first=true
+```
+
+This URL adds the `go_to_first=true` query parameter which can be appended to any `rustdoc` search URL
+to automatically go to the first result.
diff --git a/src/doc/unstable-book/src/compiler-flags/force-warn.md b/src/doc/unstable-book/src/compiler-flags/force-warn.md
new file mode 100644 (file)
index 0000000..052de0f
--- /dev/null
@@ -0,0 +1,21 @@
+# `force-warn`
+
+The tracking issue for this feature is: [#85512](https://github.com/rust-lang/rust/issues/85512).
+
+------------------------
+
+This feature allows you to cause any lint to produce a warning even if the lint has a different level by default or another level is set somewhere else. For instance, the `force-warn` option can be used to make a lint (e.g., `dead_code`) produce a warning even if that lint is allowed in code with `#![allow(dead_code)]`.
+
+## Example
+
+```rust,ignore (partial-example)
+#![allow(dead_code)]
+
+fn dead_function() {}
+// This would normally not produce a warning even though the
+// function is not used, because dead code is being allowed
+
+fn main() {}
+```
+
+We can force a warning to be produced by providing `--force-warn dead_code` to rustc.
diff --git a/src/doc/unstable-book/src/compiler-flags/force-warns.md b/src/doc/unstable-book/src/compiler-flags/force-warns.md
deleted file mode 100644 (file)
index 0a205be..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# `force-warns`
-
-The tracking issue for this feature is: [#85512](https://github.com/rust-lang/rust/issues/85512).
-
-------------------------
-
-This feature allows you to cause any lint to produce a warning even if the lint has a different level by default or another level is set somewhere else. For instance, the `force-warns` option can be used to make a lint (e.g., `dead_code`) produce a warning even if that lint is allowed in code with `#![allow(dead_code)]`.
-
-## Example
-
-```rust,ignore (partial-example)
-#![allow(dead_code)]
-
-fn dead_function() {}
-// This would normally not produce a warning even though the
-// function is not used, because dead code is being allowed
-
-fn main() {}
-```
-
-We can force a warning to be produced by providing `--force-warns dead_code` to rustc.
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.
+    }
+```
diff --git a/src/doc/unstable-book/src/language-features/impl-trait-in-bindings.md b/src/doc/unstable-book/src/language-features/impl-trait-in-bindings.md
deleted file mode 100644 (file)
index 5c6aa91..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-# `impl_trait_in_bindings`
-
-The tracking issue for this feature is: [#63065]
-
-[#63065]: https://github.com/rust-lang/rust/issues/63065
-
-------------------------
-
-The `impl_trait_in_bindings` feature gate lets you use `impl Trait` syntax in
-`let`, `static`, and `const` bindings.
-
-A simple example is:
-
-```rust
-#![feature(impl_trait_in_bindings)]
-
-use std::fmt::Debug;
-
-fn main() {
-    let a: impl Debug + Clone = 42;
-    let b = a.clone();
-    println!("{:?}", b); // prints `42`
-}
-```
-
-Note however that because the types of `a` and `b` are opaque in the above
-example, calling inherent methods or methods outside of the specified traits
-(e.g., `a.abs()` or `b.abs()`) is not allowed, and yields an error.
index 03dbf4fb617f4c2fd7f8ed637ed124bc39a788f1..e950891ef92bd504e4b7ed496d3a90a717e9e7bb 100644 (file)
@@ -456,7 +456,7 @@ reg_spec := <register class> / "<explicit register>"
 operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_"
 reg_operand := dir_spec "(" reg_spec ")" operand_expr
 operand := reg_operand / "const" const_expr / "sym" path
-option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax"
+option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw"
 options := "options(" option *["," option] [","] ")"
 asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) ["," options] [","] ")"
 ```
@@ -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` |
@@ -781,6 +791,7 @@ Currently the following options are defined:
 - `noreturn`: The `asm` block never returns, and its return type is defined as `!` (never). Behavior is undefined if execution falls through past the end of the asm code. A `noreturn` asm block behaves just like a function which doesn't return; notably, local variables in scope are not dropped before it is invoked.
 - `nostack`: The `asm` block does not push data to the stack, or write to the stack red-zone (if supported by the target). If this option is *not* used then the stack pointer is guaranteed to be suitably aligned (according to the target ABI) for a function call.
 - `att_syntax`: This option is only valid on x86, and causes the assembler to use the `.att_syntax prefix` mode of the GNU assembler. Register operands are substituted in with a leading `%`.
+- `raw`: This causes the template string to be parsed as a raw assembly string, with no special handling for `{` and `}`. This is primarily useful when including raw assembly code from an external file using `include_str!`.
 
 The compiler performs some additional checks on options:
 - The `nomem` and `readonly` options are mutually exclusive: it is a compile-time error to specify both.
diff --git a/src/doc/unstable-book/src/library-features/try-trait.md b/src/doc/unstable-book/src/library-features/try-trait.md
deleted file mode 100644 (file)
index 0226400..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-# `try_trait`
-
-The tracking issue for this feature is: [#42327]
-
-[#42327]: https://github.com/rust-lang/rust/issues/42327
-
-------------------------
-
-This introduces a new trait `Try` for extending the `?` operator to types
-other than `Result` (a part of [RFC 1859]).  The trait provides the canonical
-way to _view_ a type in terms of a success/failure dichotomy.  This will
-allow `?` to supplant the `try_opt!` macro on `Option` and the `try_ready!`
-macro on `Poll`, among other things.
-
-[RFC 1859]: https://github.com/rust-lang/rfcs/pull/1859
-
-Here's an example implementation of the trait:
-
-```rust,ignore (cannot-reimpl-Try)
-/// A distinct type to represent the `None` value of an `Option`.
-///
-/// This enables using the `?` operator on `Option`; it's rarely useful alone.
-#[derive(Debug)]
-#[unstable(feature = "try_trait", issue = "42327")]
-pub struct None { _priv: () }
-
-#[unstable(feature = "try_trait", issue = "42327")]
-impl<T> ops::Try for Option<T>  {
-    type Ok = T;
-    type Error = None;
-
-    fn into_result(self) -> Result<T, None> {
-        self.ok_or(None { _priv: () })
-    }
-
-    fn from_ok(v: T) -> Self {
-        Some(v)
-    }
-
-    fn from_error(_: None) -> Self {
-        None
-    }
-}
-```
-
-Note the `Error` associated type here is a new marker.  The `?` operator
-allows interconversion between different `Try` implementers only when
-the error type can be converted `Into` the error type of the enclosing
-function (or catch block).  Having a distinct error type (as opposed to
-just `()`, or similar) restricts this to where it's semantically meaningful.
old mode 100755 (executable)
new mode 100644 (file)
index ad2292e..aa5188d
 #!/usr/bin/env python3
 
 """
-Generate powers of ten using William Clinger's ``AlgorithmM`` for use in
+Generate powers of five using Daniel Lemire's ``Eisel-Lemire algorithm`` for use in
 decimal to floating point conversions.
 
 Specifically, computes and outputs (as Rust code) a table of 10^e for some
-range of exponents e. The output is one array of 64 bit significands and
-another array of corresponding base two exponents. The approximations are
-normalized and rounded perfectly, i.e., within 0.5 ULP of the true value.
+range of exponents e. The output is one array of 128 bit significands.
+The base two exponents can be inferred using a logarithmic slope
+of the decimal exponent. The approximations are normalized and rounded perfectly,
+i.e., within 0.5 ULP of the true value.
 
-The representation ([u64], [i16]) instead of the more natural [(u64, i16)]
-is used because (u64, i16) has a ton of padding which would make the table
-even larger, and it's already uncomfortably large (6 KiB).
+Adapted from Daniel Lemire's fast_float ``table_generation.py``,
+available here: <https://github.com/fastfloat/fast_float/blob/main/script/table_generation.py>.
 """
 from __future__ import print_function
-from math import ceil, log
+from math import ceil, floor, log, log2
 from fractions import Fraction
-from collections import namedtuple
-
-
-N = 64  # Size of the significand field in bits
-MIN_SIG = 2 ** (N - 1)
-MAX_SIG = (2 ** N) - 1
-
-# Hand-rolled fp representation without arithmetic or any other operations.
-# The significand is normalized and always N bit, but the exponent is
-# unrestricted in range.
-Fp = namedtuple('Fp', 'sig exp')
-
-
-def algorithm_m(f, e):
-    assert f > 0
-    if e < 0:
-        u = f
-        v = 10 ** abs(e)
-    else:
-        u = f * 10 ** e
-        v = 1
-    k = 0
-    x = u // v
-    while True:
-        if x < MIN_SIG:
-            u <<= 1
-            k -= 1
-        elif x >= MAX_SIG:
-            v <<= 1
-            k += 1
-        else:
-            break
-        x = u // v
-    return ratio_to_float(u, v, k)
-
-
-def ratio_to_float(u, v, k):
-    q, r = divmod(u, v)
-    v_r = v - r
-    z = Fp(q, k)
-    if r < v_r:
-        return z
-    elif r > v_r:
-        return next_float(z)
-    elif q % 2 == 0:
-        return z
-    else:
-        return next_float(z)
-
-
-def next_float(z):
-    if z.sig == MAX_SIG:
-        return Fp(MIN_SIG, z.exp + 1)
-    else:
-        return Fp(z.sig + 1, z.exp)
-
-
-def error(f, e, z):
-    decimal = f * Fraction(10) ** e
-    binary = z.sig * Fraction(2) ** z.exp
-    abs_err = abs(decimal - binary)
-    # The unit in the last place has value z.exp
-    ulp_err = abs_err / Fraction(2) ** z.exp
-    return float(ulp_err)
-
+from collections import deque
 
 HEADER = """
-//! Tables of approximations of powers of ten.
+//! Pre-computed tables powers-of-5 for extended-precision representations.
+//!
+//! These tables enable fast scaling of the significant digits
+//! of a float to the decimal exponent, with minimal rounding
+//! errors, in a 128 or 192-bit representation.
+//!
 //! DO NOT MODIFY: Generated by `src/etc/dec2flt_table.py`
 """
 
+STATIC_WARNING = """
+// Use static to avoid long compile times: Rust compiler errors
+// can have the entire table compiled multiple times, and then
+// emit code multiple times, even if it's stripped out in
+// the final binary.
+"""
 
 def main():
+    min_exp = minimum_exponent(10)
+    max_exp = maximum_exponent(10)
+    bias = -minimum_exponent(5)
+
     print(HEADER.strip())
     print()
-    print_proper_powers()
-    print()
-    print_short_powers(32, 24)
+    print('pub const SMALLEST_POWER_OF_FIVE: i32 = {};'.format(min_exp))
+    print('pub const LARGEST_POWER_OF_FIVE: i32 = {};'.format(max_exp))
+    print('pub const N_POWERS_OF_FIVE: usize = ', end='')
+    print('(LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize;')
     print()
-    print_short_powers(64, 53)
+    print_proper_powers(min_exp, max_exp, bias)
+
+
+def minimum_exponent(base):
+    return ceil(log(5e-324, base) - log(0xFFFFFFFFFFFFFFFF, base))
+
 
+def maximum_exponent(base):
+    return floor(log(1.7976931348623157e+308, base))
 
-def print_proper_powers():
-    MIN_E = -305
-    MAX_E = 305
-    e_range = range(MIN_E, MAX_E+1)
+
+def print_proper_powers(min_exp, max_exp, bias):
+    powers = deque()
+
+    # Add negative exponents.
+    # 2^(2b)/(5^−q) with b=64 + int(math.ceil(log2(5^−q)))
     powers = []
-    for e in e_range:
-        z = algorithm_m(1, e)
-        err = error(1, e, z)
-        assert err < 0.5
-        powers.append(z)
-    print("pub const MIN_E: i16 = {};".format(MIN_E))
-    print("pub const MAX_E: i16 = {};".format(MAX_E))
-    print()
-    print("#[rustfmt::skip]")
-    typ = "([u64; {0}], [i16; {0}])".format(len(powers))
-    print("pub static POWERS: ", typ, " = (", sep='')
-    print("    [")
-    for z in powers:
-        print("        0x{:x},".format(z.sig))
-    print("    ],")
-    print("    [")
-    for z in powers:
-        print("        {},".format(z.exp))
-    print("    ],")
-    print(");")
-
-
-def print_short_powers(num_bits, significand_size):
-    max_sig = 2**significand_size - 1
-    # The fast path bails out for exponents >= ceil(log5(max_sig))
-    max_e = int(ceil(log(max_sig, 5)))
-    e_range = range(max_e)
-    typ = "[f{}; {}]".format(num_bits, len(e_range))
-    print("#[rustfmt::skip]")
-    print("pub const F", num_bits, "_SHORT_POWERS: ", typ, " = [", sep='')
-    for e in e_range:
-        print("    1e{},".format(e))
-    print("];")
+    for q in range(min_exp, 0):
+        power5 = 5 ** -q
+        z = 0
+        while (1 << z) < power5:
+            z += 1
+        if q >= -27:
+            b = z + 127
+            c = 2 ** b // power5 + 1
+            powers.append((c, q))
+        else:
+            b = 2 * z + 2 * 64
+            c = 2 ** b // power5 + 1
+            # truncate
+            while c >= (1<<128):
+                c //= 2
+            powers.append((c, q))
+
+    # Add positive exponents
+    for q in range(0, max_exp + 1):
+        power5 = 5 ** q
+        # move the most significant bit in position
+        while power5 < (1<<127):
+            power5 *= 2
+        # *truncate*
+        while power5 >= (1<<128):
+            power5 //= 2
+        powers.append((power5, q))
+
+    # Print the powers.
+    print(STATIC_WARNING.strip())
+    print('#[rustfmt::skip]')
+    typ = '[(u64, u64); N_POWERS_OF_FIVE]'
+    print('pub static POWER_OF_FIVE_128: {} = ['.format(typ))
+    lo_mask = (1 << 64) - 1
+    for c, exp in powers:
+        hi = '0x{:x}'.format(c // (1 << 64))
+        lo = '0x{:x}'.format(c % (1 << 64))
+        value = '    ({}, {}), '.format(hi, lo)
+        comment = '// {}^{}'.format(5, exp)
+        print(value.ljust(46, ' ') + comment)
+    print('];')
 
 
 if __name__ == '__main__':
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 dbefe753beeb795bfa78f7c01e3b68df3fef62bb..cded3bbf7fc8298d49111487e18f9eb6fb844719 100644 (file)
@@ -18,7 +18,7 @@ prefix. You can display these options by running:
 
     $ sudo ./install.sh --help
 
-Read [The Book](http://doc.rust-lang.org/book/index.html) to learn how
+Read [The Book](https://doc.rust-lang.org/book/index.html) to learn how
 to use Rust.
 
 Rust is primarily distributed under the terms of both the MIT license
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 89280149a035140cd8943ab18a8664040d97aaeb..558536fa613a5abae81809ef20ead310cb1850e8 100644 (file)
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
   <Type Name="str">
-    <DisplayString>{data_ptr,[length]s8}</DisplayString>
-    <StringView>data_ptr,[length]s8</StringView>
+    <DisplayString>{(char*)data_ptr,[length]s8}</DisplayString>
+    <StringView>(char*)data_ptr,[length]s8</StringView>
     <Expand>
       <Item Name="[len]" ExcludeView="simple">length</Item>
       <Synthetic Name="[chars]">
@@ -15,7 +15,7 @@
       </Synthetic>
     </Expand>
   </Type>
-  <Type Name="slice&lt;*&gt;">
+  <Type Name="slice$&lt;*&gt;">
     <DisplayString>{{ len={length} }}</DisplayString>
     <Expand>
       <Item Name="[len]" ExcludeView="simple">length</Item>
       </ArrayItems>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;&gt;">
+  <Type Name="tuple$&lt;&gt;">
     <DisplayString>()</DisplayString>
   </Type>
-  <Type Name="tuple&lt;*&gt;">
+  <Type Name="tuple$&lt;*&gt;">
     <DisplayString>({__0})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*&gt;">
+  <Type Name="tuple$&lt;*,*&gt;">
     <DisplayString>({__0}, {__1})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
       <Item Name="[1]">__1</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
@@ -49,7 +49,7 @@
       <Item Name="[2]">__2</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
@@ -58,7 +58,7 @@
       <Item Name="[3]">__3</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
@@ -68,7 +68,7 @@
       <Item Name="[4]">__4</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
@@ -79,7 +79,7 @@
       <Item Name="[5]">__5</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
@@ -91,7 +91,7 @@
       <Item Name="[6]">__6</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*,*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*,*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
       <Item Name="[7]">__7</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*,*,*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*,*,*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
       <Item Name="[8]">__8</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*,*,*,*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*,*,*,*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}, {__9})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
       <Item Name="[9]">__9</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*,*,*,*,*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*,*,*,*,*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}, {__9}, ...)</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
       <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 9cc60fc7b47e557e57b0f4b4f7efa056b020a2ab..d001f40fccbc7d573c526511f5772f162bc2403e 100644 (file)
@@ -48,6 +48,7 @@
       <Item Name="[len]" ExcludeView="simple">vec.len</Item>
       <Item Name="[capacity]" ExcludeView="simple">vec.buf.cap</Item>
       <Synthetic Name="[chars]">
+        <DisplayString>{(char*)vec.buf.ptr.pointer,[vec.len]s8}</DisplayString>
         <Expand>
           <ArrayItems>
             <Size>vec.len</Size>
       </Synthetic>
     </Expand>
   </Type>
+
   <Type Name="alloc::rc::Rc&lt;*&gt;">
     <DisplayString>{ptr.pointer->value}</DisplayString>
     <Expand>
       <ExpandedItem>ptr.pointer->value</ExpandedItem>
+      <Item Name="[Reference count]">ptr.pointer->strong</Item>
+      <Item Name="[Weak reference count]">ptr.pointer->weak</Item>
     </Expand>
   </Type>
+  <Type Name="alloc::rc::Weak&lt;*&gt;">
+    <DisplayString>{ptr.pointer->value}</DisplayString>
+    <Expand>
+      <ExpandedItem>ptr.pointer->value</ExpandedItem>
+      <Item Name="[Reference count]">ptr.pointer->strong</Item>
+      <Item Name="[Weak reference count]">ptr.pointer->weak</Item>
+    </Expand>
+  </Type>
+
   <Type Name="alloc::sync::Arc&lt;*&gt;">
     <DisplayString>{ptr.pointer->data}</DisplayString>
     <Expand>
       <ExpandedItem>ptr.pointer->data</ExpandedItem>
+      <Item Name="[Reference count]">ptr.pointer->strong</Item>
+      <Item Name="[Weak reference count]">ptr.pointer->weak</Item>
     </Expand>
   </Type>
   <Type Name="alloc::sync::Weak&lt;*&gt;">
     <DisplayString>{ptr.pointer->data}</DisplayString>
     <Expand>
       <ExpandedItem>ptr.pointer->data</ExpandedItem>
+      <Item Name="[Reference count]">ptr.pointer->strong</Item>
+      <Item Name="[Weak reference count]">ptr.pointer->weak</Item>
     </Expand>
   </Type>
   <Type Name="alloc::borrow::Cow&lt;*&gt;">
index 17667770520ce0e4442fce1f661dda04a0694403..fa8ee2d70bbab4a775a38ca7e401639b4f74b564 100644 (file)
 <?xml version="1.0" encoding="utf-8"?>
 <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
-  <Type Name="core::ptr::Unique&lt;*&gt;">
-    <DisplayString>{{ Unique {pointer} }}</DisplayString>
+  <Type Name="core::cell::Cell&lt;*&gt;">
+    <DisplayString>{value.value}</DisplayString>
     <Expand>
-      <Item Name="[ptr]">pointer</Item>
+      <ExpandedItem>value.value</ExpandedItem>
+    </Expand>
+  </Type>
+  <Type Name="core::cell::Ref&lt;*&gt;">
+    <DisplayString>{value}</DisplayString>
+    <Expand>
+      <ExpandedItem>value</ExpandedItem>
+    </Expand>
+  </Type>
+  <Type Name="core::cell::RefMut&lt;*&gt;">
+    <DisplayString>{value}</DisplayString>
+    <Expand>
+      <ExpandedItem>value</ExpandedItem>
+    </Expand>
+  </Type>
+  <Type Name="core::cell::RefCell&lt;*&gt;">
+    <DisplayString>{value.value}</DisplayString>
+    <Expand>
+      <Item Name="[Borrow state]" Condition="borrow.value.value == 0">"Unborrowed",sb</Item>
+      <Item Name="[Borrow state]" Condition="borrow.value.value &gt; 0">"Immutably borrowed",sb</Item>
+      <Item Name="[Borrow state]" Condition="borrow.value.value &lt; 0">"Mutably borrowed",sb</Item>
+      <ExpandedItem>value.value</ExpandedItem>
+    </Expand>
+  </Type>
+  <Type Name="core::cell::UnsafeCell&lt;*&gt;">
+    <DisplayString>{value}</DisplayString>
+    <Expand>
+      <ExpandedItem>value</ExpandedItem>
     </Expand>
   </Type>
 
-  <Type Name="core::ptr::Shared&lt;*&gt;">
-    <DisplayString>{{ Shared {pointer} }}</DisplayString>
+  <Type Name="core::mem::manually_drop::ManuallyDrop&lt;*&gt;">
+    <DisplayString>{value}</DisplayString>
     <Expand>
-      <Item Name="[ptr]">pointer</Item>
+      <ExpandedItem>value</ExpandedItem>
     </Expand>
   </Type>
 
-  <Type Name="core::option::Option&lt;*&gt;" Priority="MediumLow">
-    <DisplayString Condition="*(void**)this == nullptr">None</DisplayString>
-    <DisplayString>Some({($T1 *)this})</DisplayString>
+  <Type Name="core::num::nonzero::NonZeroI8">
+    <DisplayString>{__0}</DisplayString>
+  </Type>
+  <Type Name="core::num::nonzero::NonZeroI16">
+    <DisplayString>{__0}</DisplayString>
+  </Type>
+  <Type Name="core::num::nonzero::NonZeroI32">
+    <DisplayString>{__0}</DisplayString>
+  </Type>
+  <Type Name="core::num::nonzero::NonZeroI64">
+    <DisplayString>{__0}</DisplayString>
+  </Type>
+  <Type Name="core::num::nonzero::NonZeroI128">
+    <DisplayString>{__0}</DisplayString>
+  </Type>
+  <Type Name="core::num::nonzero::NonZeroIsize">
+    <DisplayString>{__0}</DisplayString>
+  </Type>
+  <Type Name="core::num::nonzero::NonZeroU8">
+    <DisplayString>{__0}</DisplayString>
+  </Type>
+  <Type Name="core::num::nonzero::NonZeroU16">
+    <DisplayString>{__0}</DisplayString>
+  </Type>
+  <Type Name="core::num::nonzero::NonZeroU32">
+    <DisplayString>{__0}</DisplayString>
+  </Type>
+  <Type Name="core::num::nonzero::NonZeroU64">
+    <DisplayString>{__0}</DisplayString>
+  </Type>
+  <Type Name="core::num::nonzero::NonZeroU128">
+    <DisplayString>{__0}</DisplayString>
+  </Type>
+  <Type Name="core::num::nonzero::NonZeroUsize">
+    <DisplayString>{__0}</DisplayString>
+  </Type>
+
+  <Type Name="core::num::wrapping::Wrapping&lt;*&gt;">
+    <DisplayString>{__0}</DisplayString>
+  </Type>
+
+  <Type Name="core::ops::range::Range&lt;*&gt;">
+    <DisplayString>({start}..{end})</DisplayString>
+  </Type>
+  <Type Name="core::ops::range::RangeFrom&lt;*&gt;">
+    <DisplayString>({start}..)</DisplayString>
+  </Type>
+  <Type Name="core::ops::range::RangeInclusive&lt;*&gt;">
+    <DisplayString>({start}..={end})</DisplayString>
+  </Type>
+  <Type Name="core::ops::range::RangeTo&lt;*&gt;">
+    <DisplayString>(..{end})</DisplayString>
+  </Type>
+  <Type Name="core::ops::range::RangeToInclusive&lt;*&gt;">
+    <DisplayString>(..={end})</DisplayString>
+  </Type>
+
+  <Type Name="core::pin::Pin&lt;*&gt;">
+    <DisplayString>Pin({(void*)pointer}: {pointer})</DisplayString>
     <Expand>
-      <Item Name="Some" ExcludeView="simple" Condition="*(void**)this != nullptr">($T1 *)this</Item>
+      <ExpandedItem>pointer</ExpandedItem>
     </Expand>
   </Type>
 
   <Type Name="core::ptr::non_null::NonNull&lt;*&gt;">
-    <DisplayString>{(void*) pointer}</DisplayString>
+    <DisplayString>NonNull({(void*) pointer}: {pointer})</DisplayString>
+    <Expand>
+      <ExpandedItem>pointer</ExpandedItem>
+    </Expand>
+  </Type>
+
+  <Type Name="core::ptr::unique::Unique&lt;*&gt;">
+    <DisplayString>Unique({(void*)pointer}: {pointer})</DisplayString>
+    <Expand>
+      <ExpandedItem>pointer</ExpandedItem>
+    </Expand>
+  </Type>
+
+  <Type Name="core::sync::atomic::AtomicBool">
+    <DisplayString>{(bool)v.value}</DisplayString>
+  </Type>
+  <Type Name="core::sync::atomic::AtomicI8">
+    <DisplayString>{v.value}</DisplayString>
+  </Type>
+  <Type Name="core::sync::atomic::AtomicI16">
+    <DisplayString>{v.value}</DisplayString>
+  </Type>
+  <Type Name="core::sync::atomic::AtomicI32">
+    <DisplayString>{v.value}</DisplayString>
+  </Type>
+  <Type Name="core::sync::atomic::AtomicI64">
+    <DisplayString>{v.value}</DisplayString>
+  </Type>
+  <Type Name="core::sync::atomic::AtomicIsize">
+    <DisplayString>{v.value}</DisplayString>
+  </Type>
+    <Type Name="core::sync::atomic::AtomicU8">
+    <DisplayString>{v.value}</DisplayString>
+  </Type>
+  <Type Name="core::sync::atomic::AtomicU16">
+    <DisplayString>{v.value}</DisplayString>
+  </Type>
+  <Type Name="core::sync::atomic::AtomicU32">
+    <DisplayString>{v.value}</DisplayString>
+  </Type>
+  <Type Name="core::sync::atomic::AtomicU64">
+    <DisplayString>{v.value}</DisplayString>
+  </Type>
+  <Type Name="core::sync::atomic::AtomicUsize">
+    <DisplayString>{v.value}</DisplayString>
+  </Type>
+
+  <Type Name="core::time::Duration">
+    <DisplayString>{secs,d}s {nanos,d}ns</DisplayString>
     <Expand>
-      <Item Name="[value]">*pointer</Item>
+      <Item Name="seconds">secs,d</Item>
+      <Item Name="nanoseconds">nanos,d</Item>
     </Expand>
   </Type>
-</AutoVisualizer>
\ No newline at end of file
+</AutoVisualizer>
index 2c05f9d7c12e5c095a2dad6656f85267de9195e3..c7be0167de9fdb8233f84cb35333688c3e0e36de 100644 (file)
@@ -41,7 +41,7 @@
           <If Condition="(base.table.table.ctrl.pointer[i] &amp; 0x80) == 0">
             <!-- Bucket is populated -->
             <Exec>n--</Exec>
-            <Item Name="{((tuple&lt;$T1, $T2&gt;*)base.table.table.ctrl.pointer)[-(i + 1)].__0}">((tuple&lt;$T1, $T2&gt;*)base.table.table.ctrl.pointer)[-(i + 1)].__1</Item>
+            <Item Name="{((tuple$&lt;$T1, $T2&gt;*)base.table.table.ctrl.pointer)[-(i + 1)].__0}">((tuple$&lt;$T1, $T2&gt;*)base.table.table.ctrl.pointer)[-(i + 1)].__1</Item>
           </If>
           <Exec>i++</Exec>
         </Loop>
   </Type>
 
   <Type Name="std::ffi::c_str::CString">
-    <DisplayString>{inner.data_ptr,s}</DisplayString>
+    <DisplayString>{(char*)inner.data_ptr}</DisplayString>
     <Expand>
       <Synthetic Name="[chars]">
+        <DisplayString>{(char*)inner.data_ptr}</DisplayString>
         <Expand>
           <ArrayItems>
             <Size>inner.length</Size>
       </Synthetic>
     </Expand>
   </Type>
+
+  <Type Name="std::ffi::os_str::OsString">
+    <DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer,[inner.inner.bytes.len]}</DisplayString>
+    <Expand>
+      <Synthetic Name="[chars]">
+        <DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer,[inner.inner.bytes.len]}</DisplayString>
+        <Expand>
+          <ArrayItems>
+            <Size>inner.inner.bytes.len</Size>
+            <ValuePointer>(char*)inner.inner.bytes.buf.ptr.pointer</ValuePointer>
+          </ArrayItems>
+        </Expand>
+      </Synthetic>
+    </Expand>
+  </Type>
 </AutoVisualizer>
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<.+>$")
diff --git a/src/etc/test-float-parse/Cargo.toml b/src/etc/test-float-parse/Cargo.toml
new file mode 100644 (file)
index 0000000..8226e81
--- /dev/null
@@ -0,0 +1,13 @@
+[package]
+name = "test-float-parse"
+version = "0.1.0"
+edition = "2018"
+publish = false
+
+[workspace]
+
+[dependencies]
+rand = "0.4"
+
+[lib]
+name = "test_float_parse"
diff --git a/src/etc/test-float-parse/_common.rs b/src/etc/test-float-parse/_common.rs
deleted file mode 100644 (file)
index 9cbad54..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-use std::io;
-use std::io::prelude::*;
-use std::mem::transmute;
-
-// Nothing up my sleeve: Just (PI - 3) in base 16.
-#[allow(dead_code)]
-pub const SEED: [u32; 3] = [0x243f_6a88, 0x85a3_08d3, 0x1319_8a2e];
-
-pub fn validate(text: &str) {
-    let mut out = io::stdout();
-    let x: f64 = text.parse().unwrap();
-    let f64_bytes: u64 = unsafe { transmute(x) };
-    let x: f32 = text.parse().unwrap();
-    let f32_bytes: u32 = unsafe { transmute(x) };
-    writeln!(&mut out, "{:016x} {:08x} {}", f64_bytes, f32_bytes, text).unwrap();
-}
diff --git a/src/etc/test-float-parse/few-ones.rs b/src/etc/test-float-parse/few-ones.rs
deleted file mode 100644 (file)
index 2d82918..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-mod _common;
-
-use _common::validate;
-
-fn main() {
-    let mut pow = vec![];
-    for i in 0..63 {
-        pow.push(1u64 << i);
-    }
-    for a in &pow {
-        for b in &pow {
-            for c in &pow {
-                validate(&(a | b | c).to_string());
-            }
-        }
-    }
-}
diff --git a/src/etc/test-float-parse/huge-pow10.rs b/src/etc/test-float-parse/huge-pow10.rs
deleted file mode 100644 (file)
index 9a16d9c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-mod _common;
-
-use _common::validate;
-
-fn main() {
-    for e in 300..310 {
-        for i in 0..100000 {
-            validate(&format!("{}e{}", i, e));
-        }
-    }
-}
diff --git a/src/etc/test-float-parse/long-fractions.rs b/src/etc/test-float-parse/long-fractions.rs
deleted file mode 100644 (file)
index 60cf85c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-mod _common;
-
-use _common::validate;
-use std::char;
-
-fn main() {
-    for n in 0..10 {
-        let digit = char::from_digit(n, 10).unwrap();
-        let mut s = "0.".to_string();
-        for _ in 0..400 {
-            s.push(digit);
-            if s.parse::<f64>().is_ok() {
-                validate(&s);
-            }
-        }
-    }
-}
diff --git a/src/etc/test-float-parse/many-digits.rs b/src/etc/test-float-parse/many-digits.rs
deleted file mode 100644 (file)
index 599986e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-extern crate rand;
-
-mod _common;
-
-use _common::{validate, SEED};
-use rand::distributions::{Range, Sample};
-use rand::{IsaacRng, Rng, SeedableRng};
-use std::char;
-
-fn main() {
-    let mut rnd = IsaacRng::from_seed(&SEED);
-    let mut range = Range::new(0, 10);
-    for _ in 0..5_000_000u64 {
-        let num_digits = rnd.gen_range(100, 400);
-        let digits = gen_digits(num_digits, &mut range, &mut rnd);
-        validate(&digits);
-    }
-}
-
-fn gen_digits<R: Rng>(n: u32, range: &mut Range<u32>, rnd: &mut R) -> String {
-    let mut s = String::new();
-    for _ in 0..n {
-        let digit = char::from_digit(range.sample(rnd), 10).unwrap();
-        s.push(digit);
-    }
-    s
-}
diff --git a/src/etc/test-float-parse/rand-f64.rs b/src/etc/test-float-parse/rand-f64.rs
deleted file mode 100644 (file)
index 39ad639..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-extern crate rand;
-
-mod _common;
-
-use _common::{validate, SEED};
-use rand::{IsaacRng, Rng, SeedableRng};
-use std::mem::transmute;
-
-fn main() {
-    let mut rnd = IsaacRng::from_seed(&SEED);
-    let mut i = 0;
-    while i < 10_000_000 {
-        let bits = rnd.next_u64();
-        let x: f64 = unsafe { transmute(bits) };
-        if x.is_finite() {
-            validate(&format!("{:e}", x));
-            i += 1;
-        }
-    }
-}
index 218552a45972d860f022ce2d86b8421b40a646bc..cf7279534dc86edf3b099e187169023845f8c771 100644 (file)
@@ -131,22 +131,20 @@ def write_errors():
             exit_status = 101
 
 
-def rustc(test):
-    rs = test + '.rs'
-    exe = test + '.exe'  # hopefully this makes it work on *nix
-    print("compiling", test)
+def cargo():
+    print("compiling tests")
     sys.stdout.flush()
-    check_call(['rustc', rs, '-o', exe])
+    check_call(['cargo', 'build', '--release'])
 
 
 def run(test):
     global test_name
     test_name = test
 
-    t0 = time.clock()
+    t0 = time.perf_counter()
     msg("setting up supervisor")
-    exe = test + '.exe'
-    proc = Popen(exe, bufsize=1<<20 , stdin=PIPE, stdout=PIPE, stderr=PIPE)
+    command = ['cargo', 'run', '--bin', test, '--release']
+    proc = Popen(command, bufsize=1<<20 , stdin=PIPE, stdout=PIPE, stderr=PIPE)
     done = multiprocessing.Value(ctypes.c_bool)
     queue = multiprocessing.Queue(maxsize=5)#(maxsize=1024)
     workers = []
@@ -166,7 +164,7 @@ def run(test):
         worker.join()
     msg("python is done")
     assert queue.empty(), "did not validate everything"
-    dt = time.clock() - t0
+    dt = time.perf_counter() - t0
     msg("took", round(dt, 3), "seconds")
 
 
@@ -176,7 +174,7 @@ def interact(proc, queue):
         line = proc.stdout.readline()
         if not line:
             continue
-        assert line.endswith('\n'), "incomplete line: " + repr(line)
+        assert line.endswith(b'\n'), "incomplete line: " + repr(line)
         queue.put(line)
         n += 1
         if n % UPDATE_EVERY_N == 0:
@@ -185,7 +183,7 @@ def interact(proc, queue):
     rest, stderr = proc.communicate()
     if stderr:
         msg("rust stderr output:", stderr)
-    for line in rest.split('\n'):
+    for line in rest.split(b'\n'):
         if not line:
             continue
         queue.put(line)
@@ -193,18 +191,19 @@ def interact(proc, queue):
 
 def main():
     global MAILBOX
-    all_tests = [os.path.splitext(f)[0] for f in glob('*.rs') if not f.startswith('_')]
+    files = glob('src/bin/*.rs')
+    basenames = [os.path.basename(i) for i in files]
+    all_tests = [os.path.splitext(f)[0] for f in basenames if not f.startswith('_')]
     args = sys.argv[1:]
     if args:
         tests = [test for test in all_tests if test in args]
-    else
+    else:
         tests = all_tests
     if not tests:
         print("Error: No tests to run")
         sys.exit(1)
     # Compile first for quicker feedback
-    for test in tests:
-        rustc(test)
+    cargo()
     # Set up mailbox once for all tests
     MAILBOX = multiprocessing.Queue()
     mailman = threading.Thread(target=write_errors)
@@ -251,7 +250,7 @@ def do_work(queue):
             else:
                 continue
         bin64, bin32, text = line.rstrip().split()
-        validate(bin64, bin32, text)
+        validate(bin64, bin32, text.decode('utf-8'))
 
 
 def decode_binary64(x):
@@ -331,7 +330,11 @@ SINGLE_ZERO_CUTOFF = MIN_SUBNORMAL_SINGLE / 2
 SINGLE_INF_CUTOFF = MAX_SINGLE + 2 ** (MAX_ULP_SINGLE - 1)
 
 def validate(bin64, bin32, text):
-    double = decode_binary64(bin64)
+    try:
+        double = decode_binary64(bin64)
+    except AssertionError:
+        print(bin64, bin32, text)
+        raise
     single = decode_binary32(bin32)
     real = Fraction(text)
 
diff --git a/src/etc/test-float-parse/short-decimals.rs b/src/etc/test-float-parse/short-decimals.rs
deleted file mode 100644 (file)
index 8b9b6f7..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-mod _common;
-
-use _common::validate;
-
-fn main() {
-    // Skip e = 0 because small-u32 already does those.
-    for e in 1..301 {
-        for i in 0..10000 {
-            // If it ends in zeros, the parser will strip those (and adjust the exponent),
-            // which almost always (except for exponents near +/- 300) result in an input
-            // equivalent to something we already generate in a different way.
-            if i % 10 == 0 {
-                continue;
-            }
-            validate(&format!("{}e{}", i, e));
-            validate(&format!("{}e-{}", i, e));
-        }
-    }
-}
diff --git a/src/etc/test-float-parse/src/bin/few-ones.rs b/src/etc/test-float-parse/src/bin/few-ones.rs
new file mode 100644 (file)
index 0000000..6bb406a
--- /dev/null
@@ -0,0 +1,15 @@
+use test_float_parse::validate;
+
+fn main() {
+    let mut pow = vec![];
+    for i in 0..63 {
+        pow.push(1u64 << i);
+    }
+    for a in &pow {
+        for b in &pow {
+            for c in &pow {
+                validate(&(a | b | c).to_string());
+            }
+        }
+    }
+}
diff --git a/src/etc/test-float-parse/src/bin/huge-pow10.rs b/src/etc/test-float-parse/src/bin/huge-pow10.rs
new file mode 100644 (file)
index 0000000..722a24f
--- /dev/null
@@ -0,0 +1,9 @@
+use test_float_parse::validate;
+
+fn main() {
+    for e in 300..310 {
+        for i in 0..100000 {
+            validate(&format!("{}e{}", i, e));
+        }
+    }
+}
diff --git a/src/etc/test-float-parse/src/bin/long-fractions.rs b/src/etc/test-float-parse/src/bin/long-fractions.rs
new file mode 100644 (file)
index 0000000..c715bc1
--- /dev/null
@@ -0,0 +1,15 @@
+use std::char;
+use test_float_parse::validate;
+
+fn main() {
+    for n in 0..10 {
+        let digit = char::from_digit(n, 10).unwrap();
+        let mut s = "0.".to_string();
+        for _ in 0..400 {
+            s.push(digit);
+            if s.parse::<f64>().is_ok() {
+                validate(&s);
+            }
+        }
+    }
+}
diff --git a/src/etc/test-float-parse/src/bin/many-digits.rs b/src/etc/test-float-parse/src/bin/many-digits.rs
new file mode 100644 (file)
index 0000000..ba166fd
--- /dev/null
@@ -0,0 +1,25 @@
+extern crate rand;
+
+use rand::distributions::{Range, Sample};
+use rand::{IsaacRng, Rng, SeedableRng};
+use std::char;
+use test_float_parse::{validate, SEED};
+
+fn main() {
+    let mut rnd = IsaacRng::from_seed(&SEED);
+    let mut range = Range::new(0, 10);
+    for _ in 0..5_000_000u64 {
+        let num_digits = rnd.gen_range(100, 400);
+        let digits = gen_digits(num_digits, &mut range, &mut rnd);
+        validate(&digits);
+    }
+}
+
+fn gen_digits<R: Rng>(n: u32, range: &mut Range<u32>, rnd: &mut R) -> String {
+    let mut s = String::new();
+    for _ in 0..n {
+        let digit = char::from_digit(range.sample(rnd), 10).unwrap();
+        s.push(digit);
+    }
+    s
+}
diff --git a/src/etc/test-float-parse/src/bin/rand-f64.rs b/src/etc/test-float-parse/src/bin/rand-f64.rs
new file mode 100644 (file)
index 0000000..6991e8b
--- /dev/null
@@ -0,0 +1,18 @@
+extern crate rand;
+
+use rand::{IsaacRng, Rng, SeedableRng};
+use std::mem::transmute;
+use test_float_parse::{validate, SEED};
+
+fn main() {
+    let mut rnd = IsaacRng::from_seed(&SEED);
+    let mut i = 0;
+    while i < 10_000_000 {
+        let bits = rnd.next_u64();
+        let x: f64 = unsafe { transmute(bits) };
+        if x.is_finite() {
+            validate(&format!("{:e}", x));
+            i += 1;
+        }
+    }
+}
diff --git a/src/etc/test-float-parse/src/bin/short-decimals.rs b/src/etc/test-float-parse/src/bin/short-decimals.rs
new file mode 100644 (file)
index 0000000..49084eb
--- /dev/null
@@ -0,0 +1,17 @@
+use test_float_parse::validate;
+
+fn main() {
+    // Skip e = 0 because small-u32 already does those.
+    for e in 1..301 {
+        for i in 0..10000 {
+            // If it ends in zeros, the parser will strip those (and adjust the exponent),
+            // which almost always (except for exponents near +/- 300) result in an input
+            // equivalent to something we already generate in a different way.
+            if i % 10 == 0 {
+                continue;
+            }
+            validate(&format!("{}e{}", i, e));
+            validate(&format!("{}e-{}", i, e));
+        }
+    }
+}
diff --git a/src/etc/test-float-parse/src/bin/subnorm.rs b/src/etc/test-float-parse/src/bin/subnorm.rs
new file mode 100644 (file)
index 0000000..ac88747
--- /dev/null
@@ -0,0 +1,11 @@
+use std::mem::transmute;
+use test_float_parse::validate;
+
+fn main() {
+    for bits in 0u32..(1 << 21) {
+        let single: f32 = unsafe { transmute(bits) };
+        validate(&format!("{:e}", single));
+        let double: f64 = unsafe { transmute(bits as u64) };
+        validate(&format!("{:e}", double));
+    }
+}
diff --git a/src/etc/test-float-parse/src/bin/tiny-pow10.rs b/src/etc/test-float-parse/src/bin/tiny-pow10.rs
new file mode 100644 (file)
index 0000000..fb6ba16
--- /dev/null
@@ -0,0 +1,9 @@
+use test_float_parse::validate;
+
+fn main() {
+    for e in 301..327 {
+        for i in 0..100000 {
+            validate(&format!("{}e-{}", i, e));
+        }
+    }
+}
diff --git a/src/etc/test-float-parse/src/bin/u32-small.rs b/src/etc/test-float-parse/src/bin/u32-small.rs
new file mode 100644 (file)
index 0000000..5ec9d1e
--- /dev/null
@@ -0,0 +1,7 @@
+use test_float_parse::validate;
+
+fn main() {
+    for i in 0..(1 << 19) {
+        validate(&i.to_string());
+    }
+}
diff --git a/src/etc/test-float-parse/src/bin/u64-pow2.rs b/src/etc/test-float-parse/src/bin/u64-pow2.rs
new file mode 100644 (file)
index 0000000..984e492
--- /dev/null
@@ -0,0 +1,15 @@
+use test_float_parse::validate;
+
+fn main() {
+    for exp in 19..64 {
+        let power: u64 = 1 << exp;
+        validate(&power.to_string());
+        for offset in 1..123 {
+            validate(&(power + offset).to_string());
+            validate(&(power - offset).to_string());
+        }
+    }
+    for offset in 0..123 {
+        validate(&(u64::MAX - offset).to_string());
+    }
+}
diff --git a/src/etc/test-float-parse/src/lib.rs b/src/etc/test-float-parse/src/lib.rs
new file mode 100644 (file)
index 0000000..9cbad54
--- /dev/null
@@ -0,0 +1,16 @@
+use std::io;
+use std::io::prelude::*;
+use std::mem::transmute;
+
+// Nothing up my sleeve: Just (PI - 3) in base 16.
+#[allow(dead_code)]
+pub const SEED: [u32; 3] = [0x243f_6a88, 0x85a3_08d3, 0x1319_8a2e];
+
+pub fn validate(text: &str) {
+    let mut out = io::stdout();
+    let x: f64 = text.parse().unwrap();
+    let f64_bytes: u64 = unsafe { transmute(x) };
+    let x: f32 = text.parse().unwrap();
+    let f32_bytes: u32 = unsafe { transmute(x) };
+    writeln!(&mut out, "{:016x} {:08x} {}", f64_bytes, f32_bytes, text).unwrap();
+}
diff --git a/src/etc/test-float-parse/subnorm.rs b/src/etc/test-float-parse/subnorm.rs
deleted file mode 100644 (file)
index ba68d31..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-mod _common;
-
-use _common::validate;
-use std::mem::transmute;
-
-fn main() {
-    for bits in 0u32..(1 << 21) {
-        let single: f32 = unsafe { transmute(bits) };
-        validate(&format!("{:e}", single));
-        let double: f64 = unsafe { transmute(bits as u64) };
-        validate(&format!("{:e}", double));
-    }
-}
diff --git a/src/etc/test-float-parse/tiny-pow10.rs b/src/etc/test-float-parse/tiny-pow10.rs
deleted file mode 100644 (file)
index 43fad5b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-mod _common;
-
-use _common::validate;
-
-fn main() {
-    for e in 301..327 {
-        for i in 0..100000 {
-            validate(&format!("{}e-{}", i, e));
-        }
-    }
-}
diff --git a/src/etc/test-float-parse/u32-small.rs b/src/etc/test-float-parse/u32-small.rs
deleted file mode 100644 (file)
index 3ae6242..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-mod _common;
-
-use _common::validate;
-
-fn main() {
-    for i in 0..(1 << 19) {
-        validate(&i.to_string());
-    }
-}
diff --git a/src/etc/test-float-parse/u64-pow2.rs b/src/etc/test-float-parse/u64-pow2.rs
deleted file mode 100644 (file)
index 7e67e2b..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-mod _common;
-
-use _common::validate;
-
-fn main() {
-    for exp in 19..64 {
-        let power: u64 = 1 << exp;
-        validate(&power.to_string());
-        for offset in 1..123 {
-            validate(&(power + offset).to_string());
-            validate(&(power - offset).to_string());
-        }
-    }
-    for offset in 0..123 {
-        validate(&(u64::MAX - offset).to_string());
-    }
-}
index 5ce75949457f582bea9a74979091b40267c87d72..d5957b632dc167abad3f01877c79333cbabcc4e4 100644 (file)
@@ -21,6 +21,7 @@ regex = "1"
 rustdoc-json-types = { path = "../rustdoc-json-types" }
 tracing = "0.1"
 tracing-tree = "0.1.9"
+tera = { version = "1.10.0", default-features = false }
 
 [dependencies.tracing-subscriber]
 version = "0.2.13"
index a3f63ea1046e32c45859b3340634a2f793d591e4..e479d162b8ffb85419057c7e8a562f4a1f28ad62 100644 (file)
@@ -113,7 +113,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
             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,
@@ -353,12 +353,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                     let (poly_trait, output) =
                         (data.0.as_ref().expect("as_ref failed").clone(), data.1.as_ref().cloned());
                     let new_ty = match poly_trait.trait_ {
-                        Type::ResolvedPath {
-                            ref path,
-                            ref param_names,
-                            ref did,
-                            ref is_generic,
-                        } => {
+                        Type::ResolvedPath { ref path, ref did, ref is_generic } => {
                             let mut new_path = path.clone();
                             let last_segment =
                                 new_path.segments.pop().expect("segments were empty");
@@ -395,7 +390,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
 
                             Type::ResolvedPath {
                                 path: new_path,
-                                param_names: param_names.clone(),
                                 did: *did,
                                 is_generic: *is_generic,
                             }
@@ -414,7 +408,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                 let mut bounds_vec = bounds.into_iter().collect();
                 self.sort_where_bounds(&mut bounds_vec);
 
-                Some(WherePredicate::BoundPredicate { ty, bounds: bounds_vec })
+                Some(WherePredicate::BoundPredicate {
+                    ty,
+                    bounds: bounds_vec,
+                    bound_params: Vec::new(),
+                })
             })
             .chain(
                 lifetime_to_bounds.into_iter().filter(|&(_, ref bounds)| !bounds.is_empty()).map(
@@ -492,7 +490,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
             }
             let p = p.unwrap();
             match p {
-                WherePredicate::BoundPredicate { ty, mut bounds } => {
+                WherePredicate::BoundPredicate { ty, mut bounds, .. } => {
                     // Writing a projection trait bound of the form
                     // <T as Trait>::Name : ?Sized
                     // is illegal, because ?Sized bounds can only
@@ -566,7 +564,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                             match **trait_ {
                                 Type::ResolvedPath {
                                     path: ref trait_path,
-                                    ref param_names,
                                     ref did,
                                     ref is_generic,
                                 } => {
@@ -613,7 +610,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                                         PolyTrait {
                                             trait_: Type::ResolvedPath {
                                                 path: new_trait_path,
-                                                param_names: param_names.clone(),
                                                 did: *did,
                                                 is_generic: *is_generic,
                                             },
index 3f2fae1aca33b30eeb654d6f77a68721c27b075a..8f74a48547d8833c0f88a12e6ec8ac111cda1af4 100644 (file)
@@ -96,9 +96,9 @@ 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: self.cx.tcx.def_span(impl_def_id).clean(self.cx),
+                        span: Span::from_rustc_span(self.cx.tcx.def_span(impl_def_id)),
                         unsafety: hir::Unsafety::Normal,
                         generics: (
                             self.cx.tcx.generics_of(impl_def_id),
index 34b9cbcb6793ab608539ae722ddd8bd7de5dcbd1..275d1b3ebd938add90368a1cee9e59077a29d5cf 100644 (file)
@@ -2,8 +2,8 @@ use super::*;
 
 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 111827aacdff8b64a40d0eab96eb501d6c5691f8..b3b89e6e673a29f1a438e3ce3d6d9ebaeab5e17b 100644 (file)
@@ -13,9 +13,10 @@ use rustc_metadata::creader::LoadedMacro;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::Span;
 
-use crate::clean::{self, Attributes, AttributesExt, FakeDefId, GetDefId, ToSource};
+use crate::clean::{
+    self, utils, Attributes, AttributesExt, GetDefId, ItemId, NestedAttributesExt, Type,
+};
 use crate::core::DocContext;
 use crate::formats::item_type::ItemType;
 
@@ -40,6 +41,7 @@ type Attrs<'hir> = rustc_middle::ty::Attributes<'hir>;
 crate fn try_inline(
     cx: &mut DocContext<'_>,
     parent_module: DefId,
+    import_def_id: Option<DefId>,
     res: Res,
     name: Symbol,
     attrs: Option<Attrs<'_>>,
@@ -107,7 +109,7 @@ crate fn try_inline(
             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,
@@ -122,14 +124,13 @@ crate fn try_inline(
 
     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)
 }
 
@@ -420,6 +421,21 @@ crate fn build_impl(
     if trait_.def_id() == tcx.lang_items().deref_trait() {
         super::build_deref_target_impls(cx, &trait_items, ret);
     }
+
+    // Return if the trait itself or any types of the generic parameters are doc(hidden).
+    let mut stack: Vec<&Type> = trait_.iter().collect();
+    stack.push(&for_);
+    while let Some(ty) = stack.pop() {
+        if let Some(did) = ty.def_id() {
+            if cx.tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) {
+                return;
+            }
+        }
+        if let Some(generics) = ty.generics() {
+            stack.extend(generics);
+        }
+    }
+
     if let Some(trait_did) = trait_.def_id() {
         record_extern_trait(cx, trait_did);
     }
@@ -467,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,
@@ -479,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(),
@@ -492,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)
             }
         }
@@ -526,27 +545,29 @@ 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, _) => {
-            let matchers: Vec<Span> = if let ast::ItemKind::MacroDef(ref def) = def.kind {
-                let tts: Vec<_> = def.body.inner_tokens().into_trees().collect();
-                tts.chunks(4).map(|arm| arm[0].span()).collect()
+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!()
-            };
-
-            let source = format!(
-                "macro_rules! {} {{\n{}}}",
-                name.clean(cx),
-                matchers
-                    .iter()
-                    .map(|span| { format!("    {} => {{ ... }};\n", span.to_src(cx)) })
-                    .collect::<String>()
-            );
-
-            clean::MacroItem(clean::Macro { source, imported_from: Some(imported_from) })
+            }
         }
         LoadedMacro::ProcMacro(ext) => clean::ProcMacroItem(clean::ProcMacro {
             kind: ext.macro_kind(),
@@ -566,9 +587,11 @@ fn build_macro(cx: &mut DocContext<'_>, did: DefId, name: Symbol) -> clean::Item
 fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics {
     for pred in &mut g.where_predicates {
         match *pred {
-            clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref mut bounds }
-                if *s == kw::SelfUpper =>
-            {
+            clean::WherePredicate::BoundPredicate {
+                ty: clean::Generic(ref s),
+                ref mut bounds,
+                ..
+            } if *s == kw::SelfUpper => {
                 bounds.retain(|bound| match *bound {
                     clean::GenericBound::TraitBound(
                         clean::PolyTrait { trait_: clean::ResolvedPath { did, .. }, .. },
@@ -591,6 +614,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
                     ..
                 },
             ref bounds,
+            ..
         } => !(bounds.is_empty() || *s == kw::SelfUpper && did == trait_did),
         _ => true,
     });
@@ -605,7 +629,7 @@ fn separate_supertrait_bounds(
 ) -> (clean::Generics, Vec<clean::GenericBound>) {
     let mut ty_bounds = Vec::new();
     g.where_predicates.retain(|pred| match *pred {
-        clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref bounds }
+        clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref bounds, .. }
             if *s == kw::SelfUpper =>
         {
             ty_bounds.extend(bounds.iter().cloned());
index d1c18821ea644f9defcf73b72029c422141b0a53..1a2852dc6c724e4aa662f73eb2929793d3147e76 100644 (file)
@@ -14,18 +14,20 @@ use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_middle::middle::resolve_lifetime as rl;
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
-use rustc_middle::ty::{self, AdtKind, Lift, Ty, TyCtxt};
+use rustc_middle::ty::{self, AdtKind, DefIdTree, Lift, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_mir::const_eval::{is_const_fn, is_unstable_const_fn};
 use rustc_span::hygiene::{AstPass, MacroKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{self, ExpnKind};
+use rustc_target::spec::abi::Abi;
+use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety;
 use rustc_typeck::hir_ty_to_ty;
 
 use std::collections::hash_map::Entry;
@@ -83,12 +85,6 @@ impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
     }
 }
 
-impl Clean<ExternalCrate> for CrateNum {
-    fn clean(&self, _cx: &mut DocContext<'_>) -> ExternalCrate {
-        ExternalCrate { crate_num: *self }
-    }
-}
-
 impl Clean<Item> for doctree::Module<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
         let mut items: Vec<Item> = vec![];
@@ -178,7 +174,7 @@ impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) {
 
         debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
 
-        ResolvedPath { path, param_names: None, did: trait_ref.def_id, is_generic: false }
+        ResolvedPath { path, did: trait_ref.def_id, is_generic: false }
     }
 }
 
@@ -225,20 +221,6 @@ impl<'tcx> Clean<GenericBound> for ty::PolyTraitRef<'tcx> {
     }
 }
 
-impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Option<Vec<GenericBound>> {
-        let mut v = Vec::new();
-        v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
-        v.extend(self.types().map(|t| {
-            GenericBound::TraitBound(
-                PolyTrait { trait_: t.clean(cx), generic_params: Vec::new() },
-                hir::TraitBoundModifier::None,
-            )
-        }));
-        if !v.is_empty() { Some(v) } else { None }
-    }
-}
-
 impl Clean<Lifetime> for hir::Lifetime {
     fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime {
         let def = cx.tcx.named_region(self.hir_id);
@@ -294,12 +276,6 @@ impl Clean<Constant> for hir::ConstArg {
     }
 }
 
-impl Clean<Lifetime> for ty::GenericParamDef {
-    fn clean(&self, _cx: &mut DocContext<'_>) -> Lifetime {
-        Lifetime(self.name)
-    }
-}
-
 impl Clean<Option<Lifetime>> for ty::RegionKind {
     fn clean(&self, _cx: &mut DocContext<'_>) -> Option<Lifetime> {
         match *self {
@@ -328,6 +304,7 @@ impl Clean<WherePredicate> for hir::WherePredicate<'_> {
             hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate {
                 ty: wbp.bounded_ty.clean(cx),
                 bounds: wbp.bounds.clean(cx),
+                bound_params: wbp.bound_generic_params.into_iter().map(|x| x.clean(cx)).collect(),
             },
 
             hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
@@ -350,12 +327,12 @@ impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
             ty::PredicateKind::RegionOutlives(pred) => pred.clean(cx),
             ty::PredicateKind::TypeOutlives(pred) => pred.clean(cx),
             ty::PredicateKind::Projection(pred) => Some(pred.clean(cx)),
+            ty::PredicateKind::ConstEvaluatable(..) => None,
 
             ty::PredicateKind::Subtype(..)
             | ty::PredicateKind::WellFormed(..)
             | ty::PredicateKind::ObjectSafe(..)
             | ty::PredicateKind::ClosureKind(..)
-            | ty::PredicateKind::ConstEvaluatable(..)
             | ty::PredicateKind::ConstEquate(..)
             | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"),
         }
@@ -368,6 +345,7 @@ impl<'a> Clean<WherePredicate> for ty::PolyTraitPredicate<'a> {
         WherePredicate::BoundPredicate {
             ty: poly_trait_ref.skip_binder().self_ty().clean(cx),
             bounds: vec![poly_trait_ref.clean(cx)],
+            bound_params: Vec::new(),
         }
     }
 }
@@ -400,6 +378,7 @@ impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty:
         Some(WherePredicate::BoundPredicate {
             ty: ty.clean(cx),
             bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))],
+            bound_params: Vec::new(),
         })
     }
 }
@@ -433,8 +412,23 @@ impl Clean<GenericParamDef> for ty::GenericParamDef {
         let (name, kind) = match self.kind {
             ty::GenericParamDefKind::Lifetime => (self.name, GenericParamDefKind::Lifetime),
             ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
-                let default =
-                    if has_default { Some(cx.tcx.type_of(self.def_id).clean(cx)) } else { None };
+                let default = if has_default {
+                    let mut default = cx.tcx.type_of(self.def_id).clean(cx);
+
+                    // We need to reassign the `self_def_id`, if there's a parent (which is the
+                    // `Self` type), so we can properly render `<Self as X>` casts, because the
+                    // information about which type `Self` is, is only present here, but not in
+                    // the cleaning process of the type itself. To resolve this and have the
+                    // `self_def_id` set, we override it here.
+                    // See https://github.com/rust-lang/rust/issues/85454
+                    if let QPath { ref mut self_def_id, .. } = default {
+                        *self_def_id = cx.tcx.parent(self.def_id);
+                    }
+
+                    Some(default)
+                } else {
+                    None
+                };
                 (
                     self.name,
                     GenericParamDefKind::Type {
@@ -565,7 +559,9 @@ impl Clean<Generics> for hir::Generics<'_> {
         // to where predicates when such cases occur.
         for where_pred in &mut generics.where_predicates {
             match *where_pred {
-                WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
+                WherePredicate::BoundPredicate {
+                    ty: Generic(ref name), ref mut bounds, ..
+                } => {
                     if bounds.is_empty() {
                         for param in &mut generics.params {
                             match param.kind {
@@ -719,7 +715,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
         // handled in cleaning associated types
         let mut sized_params = FxHashSet::default();
         where_predicates.retain(|pred| match *pred {
-            WP::BoundPredicate { ty: Generic(ref g), ref bounds } => {
+            WP::BoundPredicate { ty: Generic(ref g), ref bounds, .. } => {
                 if bounds.iter().any(|b| b.is_sized_bound(cx)) {
                     sized_params.insert(*g);
                     false
@@ -739,6 +735,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
                 where_predicates.push(WP::BoundPredicate {
                     ty: Type::Generic(tp.name),
                     bounds: vec![GenericBound::maybe_sized(cx)],
+                    bound_params: Vec::new(),
                 })
             }
         }
@@ -1115,6 +1112,7 @@ impl Clean<Item> for ty::AssocItem {
                                 WherePredicate::BoundPredicate {
                                     ty: QPath { ref name, ref self_type, ref trait_, .. },
                                     ref bounds,
+                                    ..
                                 } => (name, self_type, trait_, bounds),
                                 _ => return None,
                             };
@@ -1369,24 +1367,9 @@ impl Clean<Type> for hir::Ty<'_> {
             }
             TyKind::Path(_) => clean_qpath(&self, cx),
             TyKind::TraitObject(ref bounds, ref lifetime, _) => {
-                match bounds[0].clean(cx).trait_ {
-                    ResolvedPath { path, param_names: None, did, is_generic } => {
-                        let mut bounds: Vec<self::GenericBound> = bounds[1..]
-                            .iter()
-                            .map(|bound| {
-                                self::GenericBound::TraitBound(
-                                    bound.clean(cx),
-                                    hir::TraitBoundModifier::None,
-                                )
-                            })
-                            .collect();
-                        if !lifetime.is_elided() {
-                            bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
-                        }
-                        ResolvedPath { path, param_names: Some(bounds), did, is_generic }
-                    }
-                    _ => Infer, // shouldn't happen
-                }
+                let bounds = bounds.iter().map(|bound| bound.clean(cx)).collect();
+                let lifetime = if !lifetime.is_elided() { Some(lifetime.clean(cx)) } else { None };
+                DynTrait(bounds, lifetime)
             }
             TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
             TyKind::Infer | TyKind::Err => Infer,
@@ -1469,7 +1452,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                 };
                 inline::record_extern_fqn(cx, did, kind);
                 let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs);
-                ResolvedPath { path, param_names: None, did, is_generic: false }
+                ResolvedPath { path, did, is_generic: false }
             }
             ty::Foreign(did) => {
                 inline::record_extern_fqn(cx, did, ItemType::ForeignType);
@@ -1481,7 +1464,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     vec![],
                     InternalSubsts::empty(),
                 );
-                ResolvedPath { path, param_names: None, did, is_generic: false }
+                ResolvedPath { path, did, is_generic: false }
             }
             ty::Dynamic(ref obj, ref reg) => {
                 // HACK: pick the first `did` as the `did` of the trait object. Someone
@@ -1499,28 +1482,19 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
 
                 inline::record_extern_fqn(cx, did, ItemType::Trait);
 
-                let mut param_names = vec![];
-                if let Some(b) = reg.clean(cx) {
-                    param_names.push(GenericBound::Outlives(b));
-                }
+                let lifetime = reg.clean(cx);
+                let mut bounds = vec![];
+
                 for did in dids {
                     let empty = cx.tcx.intern_substs(&[]);
                     let path =
                         external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
                     inline::record_extern_fqn(cx, did, ItemType::Trait);
-                    let bound = GenericBound::TraitBound(
-                        PolyTrait {
-                            trait_: ResolvedPath {
-                                path,
-                                param_names: None,
-                                did,
-                                is_generic: false,
-                            },
-                            generic_params: Vec::new(),
-                        },
-                        hir::TraitBoundModifier::None,
-                    );
-                    param_names.push(bound);
+                    let bound = PolyTrait {
+                        trait_: ResolvedPath { path, did, is_generic: false },
+                        generic_params: Vec::new(),
+                    };
+                    bounds.push(bound);
                 }
 
                 let mut bindings = vec![];
@@ -1533,7 +1507,15 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
 
                 let path =
                     external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs);
-                ResolvedPath { path, param_names: Some(param_names), did, is_generic: false }
+                bounds.insert(
+                    0,
+                    PolyTrait {
+                        trait_: ResolvedPath { path, did, is_generic: false },
+                        generic_params: Vec::new(),
+                    },
+                );
+
+                DynTrait(bounds, lifetime)
             }
             ty::Tuple(ref t) => {
                 Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx))
@@ -1756,12 +1738,6 @@ impl Clean<Variant> for hir::VariantData<'_> {
     }
 }
 
-impl Clean<Span> for rustc_span::Span {
-    fn clean(&self, _cx: &mut DocContext<'_>) -> Span {
-        Span::from_rustc_span(*self)
-    }
-}
-
 impl Clean<Path> for hir::Path<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Path {
         Path {
@@ -1806,20 +1782,6 @@ impl Clean<PathSegment> for hir::PathSegment<'_> {
     }
 }
 
-impl Clean<String> for Ident {
-    #[inline]
-    fn clean(&self, cx: &mut DocContext<'_>) -> String {
-        self.name.clean(cx)
-    }
-}
-
-impl Clean<String> for Symbol {
-    #[inline]
-    fn clean(&self, _: &mut DocContext<'_>) -> String {
-        self.to_string()
-    }
-}
-
 impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl {
         let (generic_params, decl) = enter_impl_trait(cx, |cx| {
@@ -2003,6 +1965,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),
@@ -2058,7 +2021,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)
@@ -2094,17 +2058,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,
@@ -2132,7 +2098,11 @@ impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Symbol>) {
                         decl,
                         generics,
                         header: hir::FnHeader {
-                            unsafety: hir::Unsafety::Unsafe,
+                            unsafety: if abi == Abi::RustIntrinsic {
+                                intrinsic_operation_unsafety(item.ident.name)
+                            } else {
+                                hir::Unsafety::Unsafe
+                            },
                             abi,
                             constness: hir::Constness::NotConst,
                             asyncness: hir::IsAsync::NotAsync,
@@ -2159,46 +2129,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 spans of all matchers. They represent the "interface" of the macro.
-        let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect::<Vec<_>>();
-        let source = if item.ast.macro_rules {
-            format!(
-                "macro_rules! {} {{\n{}}}",
-                name,
-                matchers
-                    .iter()
-                    .map(|span| { format!("    {} => {{ ... }};\n", span.to_src(cx)) })
-                    .collect::<String>(),
-            )
-        } 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.iter().map(|span| span.to_src(cx)).collect::<String>(),
-                )
-            } else {
-                format!(
-                    "{}macro {} {{\n{}}}",
-                    vis.to_src_with_space(cx.tcx, def_id),
-                    name,
-                    matchers
-                        .iter()
-                        .map(|span| { format!("    {} => {{ ... }},\n", span.to_src(cx)) })
-                        .collect::<String>(),
-                )
-            }
-        };
+        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,
         )
     }
@@ -2222,27 +2161,3 @@ impl Clean<TypeBindingKind> for hir::TypeBindingKind<'_> {
         }
     }
 }
-
-enum SimpleBound {
-    TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
-    Outlives(Lifetime),
-}
-
-impl From<GenericBound> for SimpleBound {
-    fn from(bound: GenericBound) -> Self {
-        match bound.clone() {
-            GenericBound::Outlives(l) => SimpleBound::Outlives(l),
-            GenericBound::TraitBound(t, mod_) => match t.trait_ {
-                Type::ResolvedPath { path, param_names, .. } => SimpleBound::TraitBound(
-                    path.segments,
-                    param_names.map_or_else(Vec::new, |v| {
-                        v.iter().map(|p| SimpleBound::from(p.clone())).collect()
-                    }),
-                    t.generic_params,
-                    mod_,
-                ),
-                _ => panic!("Unexpected bound {:?}", bound),
-            },
-        }
-    }
-}
index d4d0a8ce24c7b90677290f9d4143f9d0449a8b7a..3ec0a22a2c09a4a3f8b91a1f6e85c2180af7a08a 100644 (file)
@@ -24,16 +24,20 @@ use crate::core::DocContext;
 
 crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
     // First, partition the where clause into its separate components
-    let mut params: BTreeMap<_, Vec<_>> = BTreeMap::new();
+    let mut params: BTreeMap<_, (Vec<_>, Vec<_>)> = BTreeMap::new();
     let mut lifetimes = Vec::new();
     let mut equalities = Vec::new();
     let mut tybounds = Vec::new();
 
     for clause in clauses {
         match clause {
-            WP::BoundPredicate { ty, bounds } => match ty {
-                clean::Generic(s) => params.entry(s).or_default().extend(bounds),
-                t => tybounds.push((t, bounds)),
+            WP::BoundPredicate { ty, bounds, bound_params } => match ty {
+                clean::Generic(s) => {
+                    let (b, p) = params.entry(s).or_default();
+                    b.extend(bounds);
+                    p.extend(bound_params);
+                }
+                t => tybounds.push((t, (bounds, bound_params))),
             },
             WP::RegionPredicate { lifetime, bounds } => {
                 lifetimes.push((lifetime, bounds));
@@ -54,7 +58,7 @@ crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
             clean::Generic(s) => s,
             _ => return true,
         };
-        let bounds = match params.get_mut(generic) {
+        let (bounds, _) = match params.get_mut(generic) {
             Some(bound) => bound,
             None => return true,
         };
@@ -67,10 +71,16 @@ crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
     clauses.extend(
         lifetimes.into_iter().map(|(lt, bounds)| WP::RegionPredicate { lifetime: lt, bounds }),
     );
-    clauses.extend(
-        params.into_iter().map(|(k, v)| WP::BoundPredicate { ty: clean::Generic(k), bounds: v }),
-    );
-    clauses.extend(tybounds.into_iter().map(|(ty, bounds)| WP::BoundPredicate { ty, bounds }));
+    clauses.extend(params.into_iter().map(|(k, (bounds, params))| WP::BoundPredicate {
+        ty: clean::Generic(k),
+        bounds,
+        bound_params: params,
+    }));
+    clauses.extend(tybounds.into_iter().map(|(ty, (bounds, bound_params))| WP::BoundPredicate {
+        ty,
+        bounds,
+        bound_params,
+    }));
     clauses.extend(equalities.into_iter().map(|(lhs, rhs)| WP::EqPredicate { lhs, rhs }));
     clauses
 }
index 6a7c3f8caa49fdd80a8a4382eb0bdb3ed0b45330..2fd2d14bcabc3ec25a6ace935a70a58246cb57aa 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;
@@ -48,73 +48,68 @@ use self::ItemKind::*;
 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)
     }
 }
 
@@ -123,7 +118,7 @@ crate struct Crate {
     crate name: Symbol,
     crate src: FileName,
     crate module: Item,
-    crate externs: Vec<(CrateNum, ExternalCrate)>,
+    crate externs: Vec<ExternalCrate>,
     crate primitives: ThinVec<(DefId, PrimitiveType)>,
     // These are later on moved into `CACHEKEY`, leaving the map empty.
     // Only here so that they can be filtered through the rustdoc passes.
@@ -138,14 +133,14 @@ crate struct TraitWithExtraInfo {
     crate is_notable: bool,
 }
 
-#[derive(Clone, Debug)]
+#[derive(Copy, Clone, Debug)]
 crate struct ExternalCrate {
     crate crate_num: CrateNum,
 }
 
 impl ExternalCrate {
     #[inline]
-    fn def_id(&self) -> DefId {
+    crate fn def_id(&self) -> DefId {
         DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }
     }
 
@@ -338,14 +333,14 @@ crate struct Item {
     /// 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 @@ crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
 
 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())
         }
     }
 
@@ -466,7 +459,7 @@ impl Item {
             .filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
                 match did {
                     Some(did) => {
-                        if let Some((mut href, ..)) = href(did.clone(), cx) {
+                        if let Ok((mut href, ..)) = href(did.clone(), cx) {
                             if let Some(ref fragment) = *fragment {
                                 href.push('#');
                                 href.push_str(fragment);
@@ -523,8 +516,35 @@ impl Item {
             .collect()
     }
 
+    /// Find a list of all link names, without finding their href.
+    ///
+    /// This is used for generating summary text, which does not include
+    /// the link text, but does need to know which `[]`-bracketed names
+    /// are actually links.
+    crate fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
+        cache
+            .intra_doc_links
+            .get(&self.def_id)
+            .map_or(&[][..], |v| v.as_slice())
+            .iter()
+            .filter_map(|ItemLink { link: s, link_text, did, fragment }| {
+                // FIXME(83083): using fragments as a side-channel for
+                // primitive names is very unfortunate
+                if did.is_some() || fragment.is_some() {
+                    Some(RenderedLink {
+                        original_text: s.clone(),
+                        new_text: link_text.clone(),
+                        href: String::new(),
+                    })
+                } else {
+                    None
+                }
+            })
+            .collect()
+    }
+
     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
@@ -635,10 +655,6 @@ impl Item {
             _ => false,
         }
     }
-
-    crate fn is_fake(&self) -> bool {
-        matches!(self.def_id, FakeDefId::Fake(_, _))
-    }
 }
 
 #[derive(Clone, Debug)]
@@ -1141,7 +1157,7 @@ impl GenericBound {
         inline::record_extern_fqn(cx, did, ItemType::Trait);
         GenericBound::TraitBound(
             PolyTrait {
-                trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
+                trait_: ResolvedPath { path, did, is_generic: false },
                 generic_params: Vec::new(),
             },
             hir::TraitBoundModifier::Maybe,
@@ -1193,7 +1209,7 @@ impl Lifetime {
 
 #[derive(Clone, Debug)]
 crate enum WherePredicate {
-    BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
+    BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> },
     RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
     EqPredicate { lhs: Type, rhs: Type },
 }
@@ -1407,11 +1423,12 @@ crate enum Type {
     /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
     ResolvedPath {
         path: Path,
-        param_names: Option<Vec<GenericBound>>,
         did: DefId,
         /// `true` if is a `T::Name` path for associated types.
         is_generic: bool,
     },
+    /// `dyn for<'a> Trait<'a> + Send + 'static`
+    DynTrait(Vec<PolyTrait>, Option<Lifetime>),
     /// For parameterized types, so the consumer of the JSON don't go
     /// looking for types which don't exist anywhere.
     Generic(Symbol),
@@ -1598,6 +1615,7 @@ impl Type {
     fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
         let t: PrimitiveType = match *self {
             ResolvedPath { did, .. } => return Some(did.into()),
+            DynTrait(ref bounds, _) => return bounds[0].trait_.inner_def_id(cache),
             Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
             BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
             BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
index 706a56fbcbfe6c7f01961bca88ee2fdfe6126e1d..bdd5350aab2cb1571f81bf8ed1e8c8bcecf21e9a 100644 (file)
@@ -1,12 +1,15 @@
 use crate::clean::auto_trait::AutoTraitFinder;
 use crate::clean::blanket_impl::BlanketImplFinder;
 use crate::clean::{
-    inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime,
-    Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
+    inline, Clean, Crate, ExternalCrate, 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};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
@@ -14,6 +17,7 @@ use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::{self, DefIdTree, TyCtxt};
 use rustc_span::symbol::{kw, sym, Symbol};
+use std::fmt::Write as _;
 use std::mem;
 
 #[cfg(test)]
@@ -30,12 +34,12 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
     cx.cache.owned_box_did = cx.tcx.lang_items().owned_box();
 
     let mut externs = Vec::new();
-    for &cnum in cx.tcx.crates().iter() {
-        externs.push((cnum, cnum.clean(cx)));
+    for &cnum in cx.tcx.crates(()).iter() {
+        externs.push(ExternalCrate { crate_num: cnum });
         // Analyze doc-reachability for extern items
         LibEmbargoVisitor::new(cx).visit_lib(cnum);
     }
-    externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
+    externs.sort_unstable_by_key(|e| e.crate_num);
 
     // Clean the crate, translating the entire librustc_ast AST to one that is
     // understood by rustdoc.
@@ -57,7 +61,7 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
         _ => unreachable!(),
     }
 
-    let local_crate = LOCAL_CRATE.clean(cx);
+    let local_crate = ExternalCrate { crate_num: LOCAL_CRATE };
     let src = local_crate.src(cx.tcx);
     let name = local_crate.name(cx.tcx);
     let primitives = local_crate.primitives(cx.tcx);
@@ -163,8 +167,18 @@ pub(super) fn external_path(
 
 crate fn strip_type(ty: Type) -> Type {
     match ty {
-        Type::ResolvedPath { path, param_names, did, is_generic } => {
-            Type::ResolvedPath { path: strip_path(&path), param_names, did, is_generic }
+        Type::ResolvedPath { path, did, is_generic } => {
+            Type::ResolvedPath { path: strip_path(&path), did, is_generic }
+        }
+        Type::DynTrait(mut bounds, lt) => {
+            let first = bounds.remove(0);
+            let stripped_trait = strip_type(first.trait_);
+
+            bounds.insert(
+                0,
+                PolyTrait { trait_: stripped_trait, generic_params: first.generic_params },
+            );
+            Type::DynTrait(bounds, lt)
         }
         Type::Tuple(inner_tys) => {
             Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect())
@@ -238,22 +252,6 @@ crate fn build_deref_target_impls(cx: &mut DocContext<'_>, items: &[Item], ret:
     }
 }
 
-crate trait ToSource {
-    fn to_src(&self, cx: &DocContext<'_>) -> String;
-}
-
-impl ToSource for rustc_span::Span {
-    fn to_src(&self, cx: &DocContext<'_>) -> String {
-        debug!("converting span {:?} to snippet", self);
-        let sn = match cx.sess().source_map().span_to_snippet(*self) {
-            Ok(x) => x,
-            Err(_) => String::new(),
-        };
-        debug!("got snippet {}", sn);
-        sn
-    }
-}
-
 crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
     use rustc_hir::*;
     debug!("trying to get a name from pattern: {:?}", p);
@@ -262,17 +260,12 @@ crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
         PatKind::Wild | PatKind::Struct(..) => return kw::Underscore,
         PatKind::Binding(_, _, ident, _) => return ident.name,
         PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
-        PatKind::Or(ref pats) => pats
-            .iter()
-            .map(|p| name_from_pat(&**p).to_string())
-            .collect::<Vec<String>>()
-            .join(" | "),
+        PatKind::Or(ref pats) => {
+            pats.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(" | ")
+        }
         PatKind::Tuple(ref elts, _) => format!(
             "({})",
-            elts.iter()
-                .map(|p| name_from_pat(&**p).to_string())
-                .collect::<Vec<String>>()
-                .join(", ")
+            elts.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(", ")
         ),
         PatKind::Box(ref p) => return name_from_pat(&**p),
         PatKind::Ref(ref p, _) => return name_from_pat(&**p),
@@ -284,9 +277,9 @@ crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
         }
         PatKind::Range(..) => return kw::Underscore,
         PatKind::Slice(ref begin, ref mid, ref end) => {
-            let begin = begin.iter().map(|p| name_from_pat(&**p).to_string());
+            let begin = begin.iter().map(|p| name_from_pat(p).to_string());
             let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
-            let end = end.iter().map(|p| name_from_pat(&**p).to_string());
+            let end = end.iter().map(|p| name_from_pat(p).to_string());
             format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
         }
     })
@@ -431,7 +424,7 @@ crate fn resolve_type(cx: &mut DocContext<'_>, path: Path, id: hir::HirId) -> Ty
         _ => false,
     };
     let did = register_res(cx, path.res);
-    ResolvedPath { path, param_names: None, did, is_generic }
+    ResolvedPath { path, did, is_generic }
 }
 
 crate fn get_auto_trait_and_blanket_impls(
@@ -562,3 +555,56 @@ crate fn has_doc_flag(attrs: ty::Attributes<'_>, flag: Symbol) -> bool {
 ///
 /// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable.
 crate const DOC_RUST_LANG_ORG_CHANNEL: &'static str = env!("DOC_RUST_LANG_ORG_CHANNEL");
+
+/// Render a sequence of macro arms in a format suitable for displaying to the user
+/// as part of an item declaration.
+pub(super) fn render_macro_arms<'a>(
+    matchers: impl Iterator<Item = &'a TokenTree>,
+    arm_delim: &str,
+) -> String {
+    let mut out = String::new();
+    for matcher in matchers {
+        writeln!(out, "    {} => {{ ... }}{}", render_macro_matcher(matcher), arm_delim).unwrap();
+    }
+    out
+}
+
+/// Render a macro matcher in a format suitable for displaying to the user
+/// as part of an item declaration.
+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..abd1fd2bf39a29c13702beaf484680ae232f53f8 100644 (file)
@@ -156,6 +156,8 @@ crate struct Options {
     crate run_check: bool,
     /// Whether doctests should emit unused externs
     crate json_unused_externs: bool,
+    /// Whether to skip capturing stdout and stderr of tests.
+    crate nocapture: bool,
 }
 
 impl fmt::Debug for Options {
@@ -199,6 +201,7 @@ impl fmt::Debug for Options {
             .field("enable-per-target-ignores", &self.enable_per_target_ignores)
             .field("run_check", &self.run_check)
             .field("no_run", &self.no_run)
+            .field("nocapture", &self.nocapture)
             .finish()
     }
 }
@@ -456,7 +459,31 @@ impl Options {
                 })
                 .collect(),
         ];
-        let default_settings = default_settings.into_iter().flatten().collect();
+        let default_settings = default_settings
+            .into_iter()
+            .flatten()
+            .map(
+                // The keys here become part of `data-` attribute names in the generated HTML.  The
+                // browser does a strange mapping when converting them into attributes on the
+                // `dataset` property on the DOM HTML Node:
+                //   https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset
+                //
+                // The original key values we have are the same as the DOM storage API keys and the
+                // command line options, so contain `-`.  Our Javascript needs to be able to look
+                // these values up both in `dataset` and in the storage API, so it needs to be able
+                // to convert the names back and forth.  Despite doing this kebab-case to
+                // StudlyCaps transformation automatically, the JS DOM API does not provide a
+                // mechanism for doing the just transformation on a string.  So we want to avoid
+                // the StudlyCaps representation in the `dataset` property.
+                //
+                // We solve this by replacing all the `-`s with `_`s.  We do that here, when we
+                // generate the `data-` attributes, and in the JS, when we look them up.  (See
+                // `getSettingValue` in `storage.js.`) Converting `-` to `_` is simple in JS.
+                //
+                // The values will be HTML-escaped by the default Tera escaping.
+                |(k, v)| (k.replace('-', "_"), v),
+            )
+            .collect();
 
         let test_args = matches.opt_strs("test-args");
         let test_args: Vec<String> =
@@ -513,7 +540,7 @@ impl Options {
                     ))
                     .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();
@@ -627,8 +654,9 @@ impl Options {
         let run_check = matches.opt_present("check");
         let generate_redirect_map = matches.opt_present("generate-redirect-map");
         let show_type_layout = matches.opt_present("show-type-layout");
+        let nocapture = matches.opt_present("nocapture");
 
-        let (lint_opts, describe_lints, lint_cap, _) =
+        let (lint_opts, describe_lints, lint_cap) =
             get_cmd_lint_options(matches, error_format, &debugging_opts);
 
         Ok(Options {
@@ -665,6 +693,7 @@ impl Options {
             test_builder,
             run_check,
             no_run,
+            nocapture,
             render_options: RenderOptions {
                 output,
                 external_html,
index 97be79a6559bea862562b6bec96a6849596f7b0b..0689d72e4e0cf7187f19059995b839bd5071f541 100644 (file)
@@ -30,7 +30,7 @@ use std::mem;
 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 @@ crate struct DocContext<'tcx> {
     /// 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,
         }
     }
 }
@@ -312,7 +313,6 @@ crate fn create_resolver<'a>(
         .collect();
 
     let (_, resolver, _) = &*abort_on_err(queries.expansion(), sess).peek();
-    let resolver = resolver.borrow();
 
     // Before we actually clone it, let's force all the extern'd crates to
     // actually be loaded, just in case they're only referred to inside
index 88e2f6048e9c700d3d66088bd7b183540b63d98d..b45e84aff8cf5961e49ccec9faf00d5dca35d72e 100644 (file)
@@ -3,6 +3,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{ColorConfig, ErrorReported};
 use rustc_hir as hir;
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::intravisit;
 use rustc_hir::{HirId, CRATE_HIR_ID};
 use rustc_interface::interface;
@@ -13,6 +14,7 @@ use rustc_session::{lint, DiagnosticOutput, Session};
 use rustc_span::edition::Edition;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::sym;
+use rustc_span::Symbol;
 use rustc_span::{BytePos, FileName, Pos, Span, DUMMY_SP};
 use rustc_target::spec::TargetTriple;
 use tempfile::Builder as TempFileBuilder;
@@ -103,16 +105,14 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
         registry: rustc_driver::diagnostics_registry(),
     };
 
-    let mut test_args = options.test_args.clone();
+    let test_args = options.test_args.clone();
     let display_warnings = options.display_warnings;
+    let nocapture = options.nocapture;
     let externs = options.externs.clone();
     let json_unused_externs = options.json_unused_externs;
 
     let res = interface::run_compiler(config, |compiler| {
         compiler.enter(|queries| {
-            let _lower_to_hir = queries.lower_to_hir()?;
-
-            let crate_name = queries.crate_name()?.peek().to_string();
             let mut global_ctxt = queries.global_ctxt()?.take();
 
             let collector = global_ctxt.enter(|tcx| {
@@ -123,7 +123,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
                 opts.display_warnings |= options.display_warnings;
                 let enable_per_target_ignores = options.enable_per_target_ignores;
                 let mut collector = Collector::new(
-                    crate_name,
+                    tcx.crate_name(LOCAL_CRATE),
                     options,
                     false,
                     opts,
@@ -166,13 +166,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
         Err(ErrorReported) => return Err(ErrorReported),
     };
 
-    test_args.insert(0, "rustdoctest".to_string());
-
-    testing::test_main(
-        &test_args,
-        tests,
-        Some(testing::Options::new().display_output(display_warnings)),
-    );
+    run_tests(test_args, nocapture, display_warnings, tests);
 
     // Collect and warn about unused externs, but only if we've gotten
     // reports for each doctest
@@ -215,6 +209,19 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
     Ok(())
 }
 
+crate fn run_tests(
+    mut test_args: Vec<String>,
+    nocapture: bool,
+    display_warnings: bool,
+    tests: Vec<test::TestDescAndFn>,
+) {
+    test_args.insert(0, "rustdoctest".to_string());
+    if nocapture {
+        test_args.push("--nocapture".to_string());
+    }
+    test::test_main(&test_args, tests, Some(test::Options::new().display_output(display_warnings)));
+}
+
 // Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
 fn scrape_test_config(attrs: &[ast::Attribute]) -> TestOptions {
     use rustc_ast_pretty::pprust;
@@ -293,7 +300,7 @@ struct UnusedExterns {
 
 fn run_test(
     test: &str,
-    cratename: &str,
+    crate_name: &str,
     line: usize,
     options: Options,
     should_panic: bool,
@@ -312,7 +319,7 @@ fn run_test(
     report_unused_externs: impl Fn(UnusedExterns),
 ) -> Result<(), TestFailure> {
     let (test, line_offset, supports_color) =
-        make_test(test, Some(cratename), as_test_harness, opts, edition, Some(test_id));
+        make_test(test, Some(crate_name), as_test_harness, opts, edition, Some(test_id));
 
     let output_file = outdir.path().join("rust_out");
 
@@ -461,7 +468,16 @@ fn run_test(
         cmd.current_dir(run_directory);
     }
 
-    match cmd.output() {
+    let result = if options.nocapture {
+        cmd.status().map(|status| process::Output {
+            status,
+            stdout: Vec::new(),
+            stderr: Vec::new(),
+        })
+    } else {
+        cmd.output()
+    };
+    match result {
         Err(e) => return Err(TestFailure::ExecutionError(e)),
         Ok(out) => {
             if should_panic && out.status.success() {
@@ -479,7 +495,7 @@ fn run_test(
 /// lines before the test code begins as well as if the output stream supports colors or not.
 crate fn make_test(
     s: &str,
-    cratename: Option<&str>,
+    crate_name: Option<&str>,
     dont_insert_main: bool,
     opts: &TestOptions,
     edition: Edition,
@@ -514,7 +530,7 @@ crate fn make_test(
     // 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;
@@ -540,7 +556,7 @@ crate fn make_test(
             let sess = ParseSess::with_span_handler(handler, sm);
 
             let mut found_main = false;
-            let mut found_extern_crate = cratename.is_none();
+            let mut found_extern_crate = crate_name.is_none();
             let mut found_macro = false;
 
             let mut parser = match maybe_new_parser_from_source_str(&sess, filename, source) {
@@ -567,13 +583,13 @@ crate fn make_test(
 
                         if !found_extern_crate {
                             if let ast::ItemKind::ExternCrate(original) = item.kind {
-                                // This code will never be reached if `cratename` is none because
+                                // This code will never be reached if `crate_name` is none because
                                 // `found_extern_crate` is initialized to `true` if it is none.
-                                let cratename = cratename.unwrap();
+                                let crate_name = crate_name.unwrap();
 
                                 match original {
-                                    Some(name) => found_extern_crate = name.as_str() == cratename,
-                                    None => found_extern_crate = item.ident.as_str() == cratename,
+                                    Some(name) => found_extern_crate = name.as_str() == crate_name,
+                                    None => found_extern_crate = item.ident.as_str() == crate_name,
                                 }
                             }
                         }
@@ -631,14 +647,14 @@ crate fn make_test(
 
     // Don't inject `extern crate std` because it's already injected by the
     // compiler.
-    if !already_has_extern_crate && !opts.no_crate_inject && cratename != Some("std") {
-        if let Some(cratename) = cratename {
+    if !already_has_extern_crate && !opts.no_crate_inject && crate_name != Some("std") {
+        if let Some(crate_name) = crate_name {
             // Don't inject `extern crate` if the crate is never used.
             // NOTE: this is terribly inaccurate because it doesn't actually
             // parse the source, but only has false positives, not false
             // negatives.
-            if s.contains(cratename) {
-                prog.push_str(&format!("extern crate r#{};\n", cratename));
+            if s.contains(crate_name) {
+                prog.push_str(&format!("extern crate r#{};\n", crate_name));
                 line_offset += 1;
             }
         }
@@ -770,7 +786,7 @@ crate trait Tester {
 }
 
 crate struct Collector {
-    crate tests: Vec<testing::TestDescAndFn>,
+    crate tests: Vec<test::TestDescAndFn>,
 
     // The name of the test displayed to the user, separated by `::`.
     //
@@ -797,7 +813,7 @@ crate struct Collector {
     options: Options,
     use_headers: bool,
     enable_per_target_ignores: bool,
-    cratename: String,
+    crate_name: Symbol,
     opts: TestOptions,
     position: Span,
     source_map: Option<Lrc<SourceMap>>,
@@ -809,7 +825,7 @@ crate struct Collector {
 
 impl Collector {
     crate fn new(
-        cratename: String,
+        crate_name: Symbol,
         options: Options,
         use_headers: bool,
         opts: TestOptions,
@@ -823,7 +839,7 @@ impl Collector {
             options,
             use_headers,
             enable_per_target_ignores,
-            cratename,
+            crate_name,
             opts,
             position: DUMMY_SP,
             source_map,
@@ -871,7 +887,7 @@ impl Tester for Collector {
     fn add_test(&mut self, test: String, config: LangString, line: usize) {
         let filename = self.get_filename();
         let name = self.generate_name(line, &filename);
-        let cratename = self.cratename.to_string();
+        let crate_name = self.crate_name.to_string();
         let opts = self.opts.clone();
         let edition = config.edition.unwrap_or(self.options.edition);
         let options = self.options.clone();
@@ -931,30 +947,28 @@ impl Tester for Collector {
         };
 
         debug!("creating test {}: {}", name, test);
-        self.tests.push(testing::TestDescAndFn {
-            desc: testing::TestDesc {
-                name: testing::DynTestName(name),
+        self.tests.push(test::TestDescAndFn {
+            desc: test::TestDesc {
+                name: test::DynTestName(name),
                 ignore: match config.ignore {
                     Ignore::All => true,
                     Ignore::None => false,
                     Ignore::Some(ref ignores) => ignores.iter().any(|s| target_str.contains(s)),
                 },
                 // compiler failures are test failures
-                should_panic: testing::ShouldPanic::No,
+                should_panic: test::ShouldPanic::No,
                 allow_fail: config.allow_fail,
-                #[cfg(not(bootstrap))]
                 compile_fail: config.compile_fail,
-                #[cfg(not(bootstrap))]
                 no_run,
-                test_type: testing::TestType::DocTest,
+                test_type: test::TestType::DocTest,
             },
-            testfn: testing::DynTestFn(box move || {
+            testfn: test::DynTestFn(box move || {
                 let report_unused_externs = |uext| {
                     unused_externs.lock().unwrap().push(uext);
                 };
                 let res = run_test(
                     &test,
-                    &cratename,
+                    &crate_name,
                     line,
                     options,
                     config.should_panic,
index 6c86baa36ac7de8dbf9e1f10e3d1c0306756c290..56d2ca57218c55be305c1f1b64c44a9c28199882 100644 (file)
@@ -4,7 +4,9 @@ use std::fs;
 use std::path::Path;
 use std::str;
 
-#[derive(Clone, Debug)]
+use serde::Serialize;
+
+#[derive(Clone, Debug, Serialize)]
 crate struct ExternalHtml {
     /// Content that will be included inline in the <head> section of a
     /// rendered Markdown file or generated documentation
index 5734a4a98e2b5f32f870497f28c8e567410d747e..5ea2cdc2ad9093a239b8615303e409af1b828a72 100644 (file)
@@ -8,7 +8,7 @@ use rustc_middle::middle::privacy::AccessLevels;
 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;
@@ -122,13 +122,12 @@ crate struct Cache {
     /// 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`.
 struct CacheBuilder<'a, 'tcx> {
     cache: &'a mut Cache,
-    empty_cache: Cache,
     tcx: TyCtxt<'tcx>,
 }
 
@@ -152,19 +151,18 @@ impl Cache {
 
         // Cache where all our extern crates are located
         // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code
-        for &(n, ref e) in &krate.externs {
+        for &e in &krate.externs {
             let name = e.name(tcx);
             let extern_url = extern_html_root_urls.get(&*name.as_str()).map(|u| &**u);
-            let did = DefId { krate: n, index: CRATE_DEF_INDEX };
-            self.extern_locations.insert(n, e.location(extern_url, &dst, tcx));
-            self.external_paths.insert(did, (vec![name.to_string()], ItemType::Module));
+            self.extern_locations.insert(e.crate_num, e.location(extern_url, &dst, tcx));
+            self.external_paths.insert(e.def_id(), (vec![name.to_string()], ItemType::Module));
         }
 
         // Cache where all known primitives have their documentation located.
         //
         // Favor linking to as local extern as possible, so iterate all crates in
         // reverse topological order.
-        for &(_, ref e) in krate.externs.iter().rev() {
+        for &e in krate.externs.iter().rev() {
             for &(def_id, prim) in &e.primitives(tcx) {
                 self.primitive_locations.insert(prim, def_id);
             }
@@ -173,7 +171,7 @@ impl Cache {
             self.primitive_locations.insert(prim, def_id);
         }
 
-        krate = CacheBuilder { tcx, cache: self, empty_cache: Cache::default() }.fold_crate(krate);
+        krate = CacheBuilder { tcx, cache: self }.fold_crate(krate);
 
         for (trait_did, dids, impl_) in self.orphan_trait_impls.drain(..) {
             if self.traits.contains_key(&trait_did) {
@@ -216,7 +214,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
         // 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),
@@ -292,16 +290,17 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
                     // which should not be indexed. The crate-item itself is
                     // inserted later on when serializing the search-index.
                     if item.def_id.index().map_or(false, |idx| idx != CRATE_DEF_INDEX) {
+                        let desc = item.doc_value().map_or_else(String::new, |x| {
+                            short_markdown_summary(&x.as_str(), &item.link_names(&self.cache))
+                        });
                         self.cache.search_index.push(IndexItem {
                             ty: item.type_(),
                             name: s.to_string(),
                             path: path.join("::"),
-                            desc: item
-                                .doc_value()
-                                .map_or_else(String::new, |x| short_markdown_summary(&x.as_str())),
+                            desc,
                             parent,
                             parent_idx: None,
-                            search_type: get_index_search_type(&item, &self.empty_cache, self.tcx),
+                            search_type: get_index_search_type(&item, self.tcx),
                             aliases: item.attrs.get_doc_aliases(),
                         });
                     }
@@ -348,11 +347,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
                     // `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 +360,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
             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 +390,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
             | 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
             }
@@ -402,6 +401,15 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
                         self.cache.parent_stack.push(did);
                         true
                     }
+                    clean::DynTrait(ref bounds, _)
+                    | clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => {
+                        if let Some(did) = bounds[0].trait_.def_id() {
+                            self.cache.parent_stack.push(did);
+                            true
+                        } else {
+                            false
+                        }
+                    }
                     ref t => {
                         let prim_did = t
                             .primitive_type()
@@ -432,6 +440,12 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
                 | clean::BorrowedRef { type_: box clean::ResolvedPath { did, .. }, .. } => {
                     dids.insert(did);
                 }
+                clean::DynTrait(ref bounds, _)
+                | clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => {
+                    if let Some(did) = bounds[0].trait_.def_id() {
+                        dids.insert(did);
+                    }
+                }
                 ref t => {
                     let did = t
                         .primitive_type()
index 918a5cb5094305c4c9b68bb6b6425495c75c58b6..08499cef33ef19cb23564159e605f7408587341c 100644 (file)
@@ -9,6 +9,7 @@ use std::cell::Cell;
 use std::fmt;
 use std::iter;
 
+use rustc_attr::{ConstStability, StabilityLevel};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
@@ -18,7 +19,7 @@ use rustc_span::def_id::CRATE_DEF_INDEX;
 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;
@@ -249,17 +250,33 @@ crate fn print_where_clause<'a, 'tcx: 'a>(
             }
 
             match pred {
-                clean::WherePredicate::BoundPredicate { ty, bounds } => {
+                clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
                     let bounds = bounds;
+                    let for_prefix = match bound_params.len() {
+                        0 => String::new(),
+                        _ if f.alternate() => {
+                            format!(
+                                "for<{:#}> ",
+                                comma_sep(bound_params.iter().map(|lt| lt.print()))
+                            )
+                        }
+                        _ => format!(
+                            "for&lt;{}&gt; ",
+                            comma_sep(bound_params.iter().map(|lt| lt.print()))
+                        ),
+                    };
+
                     if f.alternate() {
                         clause.push_str(&format!(
-                            "{:#}: {:#}",
+                            "{}{:#}: {:#}",
+                            for_prefix,
                             ty.print(cx),
                             print_generic_bounds(bounds, cx)
                         ));
                     } else {
                         clause.push_str(&format!(
-                            "{}: {}",
+                            "{}{}: {}",
+                            for_prefix,
                             ty.print(cx),
                             print_generic_bounds(bounds, cx)
                         ));
@@ -455,7 +472,19 @@ impl clean::GenericArgs {
     }
 }
 
-crate fn href(did: DefId, cx: &Context<'_>) -> Option<(String, ItemType, Vec<String>)> {
+// Possible errors when computing href link source for a `DefId`
+crate enum HrefError {
+    /// This item is known to rustdoc, but from a crate that does not have documentation generated.
+    ///
+    /// This can only happen for non-local items.
+    DocumentationNotBuilt,
+    /// This can only happen for non-local items when `--document-private-items` is not passed.
+    Private,
+    // Not in external cache, href link should be in same page
+    NotInExternalCache,
+}
+
+crate fn href(did: DefId, cx: &Context<'_>) -> Result<(String, ItemType, Vec<String>), HrefError> {
     let cache = &cx.cache();
     let relative_to = &cx.current;
     fn to_module_fqp(shortty: ItemType, fqp: &[String]) -> &[String] {
@@ -463,7 +492,7 @@ crate fn href(did: DefId, cx: &Context<'_>) -> Option<(String, ItemType, Vec<Str
     }
 
     if !did.is_local() && !cache.access_levels.is_public(did) && !cache.document_private {
-        return None;
+        return Err(HrefError::Private);
     }
 
     let (fqp, shortty, mut url_parts) = match cache.paths.get(&did) {
@@ -472,22 +501,25 @@ crate fn href(did: DefId, cx: &Context<'_>) -> Option<(String, ItemType, Vec<Str
             href_relative_parts(module_fqp, relative_to)
         }),
         None => {
-            let &(ref fqp, shortty) = cache.external_paths.get(&did)?;
-            let module_fqp = to_module_fqp(shortty, fqp);
-            (
-                fqp,
-                shortty,
-                match cache.extern_locations[&did.krate] {
-                    ExternalLocation::Remote(ref s) => {
-                        let s = s.trim_end_matches('/');
-                        let mut s = vec![&s[..]];
-                        s.extend(module_fqp[..].iter().map(String::as_str));
-                        s
-                    }
-                    ExternalLocation::Local => href_relative_parts(module_fqp, relative_to),
-                    ExternalLocation::Unknown => return None,
-                },
-            )
+            if let Some(&(ref fqp, shortty)) = cache.external_paths.get(&did) {
+                let module_fqp = to_module_fqp(shortty, fqp);
+                (
+                    fqp,
+                    shortty,
+                    match cache.extern_locations[&did.krate] {
+                        ExternalLocation::Remote(ref s) => {
+                            let s = s.trim_end_matches('/');
+                            let mut s = vec![&s[..]];
+                            s.extend(module_fqp[..].iter().map(String::as_str));
+                            s
+                        }
+                        ExternalLocation::Local => href_relative_parts(module_fqp, relative_to),
+                        ExternalLocation::Unknown => return Err(HrefError::DocumentationNotBuilt),
+                    },
+                )
+            } else {
+                return Err(HrefError::NotInExternalCache);
+            }
         }
     };
     let last = &fqp.last().unwrap()[..];
@@ -501,7 +533,7 @@ crate fn href(did: DefId, cx: &Context<'_>) -> Option<(String, ItemType, Vec<Str
             url_parts.push(&filename);
         }
     }
-    Some((url_parts.join("/"), shortty, fqp.to_vec()))
+    Ok((url_parts.join("/"), shortty, fqp.to_vec()))
 }
 
 /// Both paths should only be modules.
@@ -550,7 +582,7 @@ fn resolved_path<'a, 'cx: 'a>(
         write!(w, "{}{:#}", &last.name, last.args.print(cx))?;
     } else {
         let path = if use_absolute {
-            if let Some((_, _, fqp)) = href(did, cx) {
+            if let Ok((_, _, fqp)) = href(did, cx) {
                 format!(
                     "{}::{}",
                     fqp[..fqp.len() - 1].join("::"),
@@ -630,18 +662,24 @@ fn primitive_link(
 
 /// Helper to render type parameters
 fn tybounds<'a, 'tcx: 'a>(
-    param_names: &'a Option<Vec<clean::GenericBound>>,
+    bounds: &'a Vec<clean::PolyTrait>,
+    lt: &'a Option<clean::Lifetime>,
     cx: &'a Context<'tcx>,
 ) -> impl fmt::Display + 'a + Captures<'tcx> {
-    display_fn(move |f| match *param_names {
-        Some(ref params) => {
-            for param in params {
+    display_fn(move |f| {
+        for (i, bound) in bounds.iter().enumerate() {
+            if i > 0 {
                 write!(f, " + ")?;
-                fmt::Display::fmt(&param.print(cx), f)?;
             }
-            Ok(())
+
+            fmt::Display::fmt(&bound.print(cx), f)?;
         }
-        None => Ok(()),
+
+        if let Some(lt) = lt {
+            write!(f, " + ")?;
+            fmt::Display::fmt(&lt.print(), f)?;
+        }
+        Ok(())
     })
 }
 
@@ -652,7 +690,7 @@ crate fn anchor<'a, 'cx: 'a>(
 ) -> impl fmt::Display + 'a {
     let parts = href(did.into(), cx);
     display_fn(move |f| {
-        if let Some((url, short_ty, fqp)) = parts {
+        if let Ok((url, short_ty, fqp)) = parts {
             write!(
                 f,
                 r#"<a class="{}" href="{}" title="{} {}">{}</a>"#,
@@ -678,13 +716,13 @@ fn fmt_type<'cx>(
 
     match *t {
         clean::Generic(name) => write!(f, "{}", name),
-        clean::ResolvedPath { did, ref param_names, ref path, is_generic } => {
-            if param_names.is_some() {
-                f.write_str("dyn ")?;
-            }
+        clean::ResolvedPath { did, ref path, is_generic } => {
             // Paths like `T::Output` and `Self::Output` should be rendered with all segments.
-            resolved_path(f, did, path, is_generic, use_absolute, cx)?;
-            fmt::Display::fmt(&tybounds(param_names, cx), f)
+            resolved_path(f, did, path, is_generic, use_absolute, cx)
+        }
+        clean::DynTrait(ref bounds, ref lt) => {
+            f.write_str("dyn ")?;
+            fmt::Display::fmt(&tybounds(bounds, lt, cx), f)
         }
         clean::Infer => write!(f, "_"),
         clean::Primitive(prim) => primitive_link(f, prim, &*prim.as_sym().as_str(), cx),
@@ -819,7 +857,9 @@ fn fmt_type<'cx>(
                         }
                     }
                 }
-                clean::ResolvedPath { param_names: Some(ref v), .. } if !v.is_empty() => {
+                clean::DynTrait(ref bounds, ref trait_lt)
+                    if bounds.len() > 1 || trait_lt.is_some() =>
+                {
                     write!(f, "{}{}{}(", amp, lt, m)?;
                     fmt_type(&ty, f, use_absolute, cx)?;
                     write!(f, ")")
@@ -880,9 +920,9 @@ fn fmt_type<'cx>(
                 //        the ugliness comes from inlining across crates where
                 //        everything comes in as a fully resolved QPath (hard to
                 //        look at).
-                box clean::ResolvedPath { did, ref param_names, .. } => {
+                box clean::ResolvedPath { did, .. } => {
                     match href(did.into(), cx) {
-                        Some((ref url, _, ref path)) if !f.alternate() => {
+                        Ok((ref url, _, ref path)) if !f.alternate() => {
                             write!(
                                 f,
                                 "<a class=\"type\" href=\"{url}#{shortty}.{name}\" \
@@ -895,9 +935,6 @@ fn fmt_type<'cx>(
                         }
                         _ => write!(f, "{}", name)?,
                     }
-
-                    // FIXME: `param_names` are not rendered, and this seems bad?
-                    drop(param_names);
                     Ok(())
                 }
                 _ => write!(f, "{}", name),
@@ -1159,7 +1196,7 @@ impl clean::FnDecl {
 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 {
@@ -1169,7 +1206,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()
@@ -1253,15 +1290,6 @@ impl PrintWithSpace for hir::Unsafety {
     }
 }
 
-impl PrintWithSpace for hir::Constness {
-    fn print_with_space(&self) -> &str {
-        match self {
-            hir::Constness::Const => "const ",
-            hir::Constness::NotConst => "",
-        }
-    }
-}
-
 impl PrintWithSpace for hir::IsAsync {
     fn print_with_space(&self) -> &str {
         match self {
@@ -1280,6 +1308,22 @@ impl PrintWithSpace for hir::Mutability {
     }
 }
 
+crate fn print_constness_with_space(
+    c: &hir::Constness,
+    s: Option<&ConstStability>,
+) -> &'static str {
+    match (c, s) {
+        // const stable or when feature(staged_api) is not set
+        (
+            hir::Constness::Const,
+            Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }),
+        )
+        | (hir::Constness::Const, None) => "const ",
+        // const unstable or not const
+        _ => "",
+    }
+}
+
 impl clean::Import {
     crate fn print<'a, 'tcx: 'a>(
         &'a self,
index 51392ca1191891a7dc3932f909bb4e5e9efa62eb..33b1d98313ce3cd3c5efb3cc3404f26f1fdeab36 100644 (file)
@@ -413,7 +413,7 @@ impl<'a> Classifier<'a> {
                 },
                 c => c,
             },
-            TokenKind::RawIdent => Class::Ident,
+            TokenKind::RawIdent | TokenKind::UnknownPrefix => Class::Ident,
             TokenKind::Lifetime { .. } => Class::Lifetime,
         };
         // Anything that didn't return above is the simple case where we the
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 @@ const STYLE: &str = r#"
 
 #[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 d2d1757b9009ada499bcbb2bf75b9ee23b9f6bbe..6ed603c96bbf2820a5bf2c43d807e0086ddb569f 100644 (file)
@@ -7,7 +7,9 @@ use crate::html::escape::Escape;
 use crate::html::format::{Buffer, Print};
 use crate::html::render::{ensure_trailing_slash, StylePath};
 
-#[derive(Clone)]
+use serde::Serialize;
+
+#[derive(Clone, Serialize)]
 crate struct Layout {
     crate logo: String,
     crate favicon: String,
@@ -22,6 +24,7 @@ crate struct Layout {
     crate generate_search_filter: bool,
 }
 
+#[derive(Serialize)]
 crate struct Page<'a> {
     crate title: &'a str,
     crate css_class: &'a str,
@@ -40,7 +43,19 @@ impl<'a> Page<'a> {
     }
 }
 
+#[derive(Serialize)]
+struct PageLayout<'a> {
+    static_root_path: &'a str,
+    page: &'a Page<'a>,
+    layout: &'a Layout,
+    style_files: String,
+    sidebar: String,
+    content: String,
+    krate_with_trailing_slash: String,
+}
+
 crate fn render<T: Print, S: Print>(
+    templates: &tera::Tera,
     layout: &Layout,
     page: &Page<'_>,
     sidebar: S,
@@ -48,184 +63,35 @@ crate fn render<T: Print, S: Print>(
     style_files: &[StylePath],
 ) -> String {
     let static_root_path = page.get_static_root_path();
-    format!(
-        "<!DOCTYPE html>\
-<html lang=\"en\">\
-<head>\
-    <meta charset=\"utf-8\">\
-    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\
-    <meta name=\"generator\" content=\"rustdoc\">\
-    <meta name=\"description\" content=\"{description}\">\
-    <meta name=\"keywords\" content=\"{keywords}\">\
-    <title>{title}</title>\
-    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
-    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
-          id=\"mainThemeStyle\">\
-    {style_files}\
-    <script id=\"default-settings\"{default_settings}></script>\
-    <script src=\"{static_root_path}storage{suffix}.js\"></script>\
-    <script src=\"{root_path}crates{suffix}.js\"></script>\
-    <noscript><link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\"></noscript>\
-    {css_extension}\
-    {favicon}\
-    {in_header}\
-    <style type=\"text/css\">\
-    #crate-search{{background-image:url(\"{static_root_path}down-arrow{suffix}.svg\");}}\
-    </style>\
-</head>\
-<body class=\"rustdoc {css_class}\">\
-    <!--[if lte IE 11]>\
-    <div class=\"warning\">\
-        This old browser is unsupported and will most likely display funky \
-        things.\
-    </div>\
-    <![endif]-->\
-    {before_content}\
-    <nav class=\"sidebar\">\
-        <div class=\"sidebar-menu\" role=\"button\">&#9776;</div>\
-        {logo}\
-        {sidebar}\
-    </nav>\
-    <div class=\"theme-picker\">\
-        <button id=\"theme-picker\" aria-label=\"Pick another theme!\" aria-haspopup=\"menu\" title=\"themes\">\
-            <img src=\"{static_root_path}brush{suffix}.svg\" \
-                 width=\"18\" height=\"18\" \
-                 alt=\"Pick another theme!\">\
-        </button>\
-        <div id=\"theme-choices\" role=\"menu\"></div>\
-    </div>\
-    <nav class=\"sub\">\
-        <form class=\"search-form\">\
-            <div class=\"search-container\">\
-                <div>{filter_crates}\
-                    <input class=\"search-input\" name=\"search\" \
-                           disabled \
-                           autocomplete=\"off\" \
-                           spellcheck=\"false\" \
-                           placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
-                           type=\"search\">\
-                </div>\
-                <button type=\"button\" id=\"help-button\" title=\"help\">?</button>\
-                <a id=\"settings-menu\" href=\"{root_path}settings.html\" title=\"settings\">\
-                    <img src=\"{static_root_path}wheel{suffix}.svg\" \
-                         width=\"18\" height=\"18\" \
-                         alt=\"Change settings\">\
-                </a>\
-            </div>\
-        </form>\
-    </nav>\
-    <section id=\"main\" class=\"content\">{content}</section>\
-    <section id=\"search\" class=\"content hidden\"></section>\
-    {after_content}\
-    <div id=\"rustdoc-vars\" data-root-path=\"{root_path}\" data-current-crate=\"{krate}\" \
-       data-search-index-js=\"{root_path}search-index{suffix}.js\" \
-       data-search-js=\"{static_root_path}search{suffix}.js\"></div>\
-    <script src=\"{static_root_path}main{suffix}.js\"></script>\
-    {extra_scripts}\
-</body>\
-</html>",
-        css_extension = if layout.css_file_extension.is_some() {
+    let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string();
+    let style_files = style_files
+        .iter()
+        .filter_map(|t| {
+            if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
+        })
+        .filter_map(|t| if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None })
+        .map(|t| {
             format!(
-                "<link rel=\"stylesheet\" \
-                       type=\"text/css\" \
-                       href=\"{static_root_path}theme{suffix}.css\">",
-                static_root_path = static_root_path,
-                suffix = page.resource_suffix
-            )
-        } else {
-            String::new()
-        },
-        content = Buffer::html().to_display(t),
-        static_root_path = static_root_path,
-        root_path = page.root_path,
-        css_class = page.css_class,
-        logo = {
-            if layout.logo.is_empty() {
-                format!(
-                    "<a href='{root}{path}index.html'>\
-                     <div class='logo-container rust-logo'>\
-                     <img src='{static_root_path}rust-logo{suffix}.png' alt='logo'></div></a>",
-                    root = page.root_path,
-                    path = ensure_trailing_slash(&layout.krate),
-                    static_root_path = static_root_path,
-                    suffix = page.resource_suffix
-                )
-            } else {
-                format!(
-                    "<a href='{root}{path}index.html'>\
-                     <div class='logo-container'><img src='{logo}' alt='logo'></div></a>",
-                    root = page.root_path,
-                    path = ensure_trailing_slash(&layout.krate),
-                    logo = layout.logo
-                )
-            }
-        },
-        title = page.title,
-        description = Escape(page.description),
-        keywords = page.keywords,
-        favicon = if layout.favicon.is_empty() {
-            format!(
-                r##"<link rel="icon" type="image/svg+xml" href="{static_root_path}favicon{suffix}.svg">
-<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-16x16{suffix}.png">
-<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-32x32{suffix}.png">"##,
-                static_root_path = static_root_path,
-                suffix = page.resource_suffix
-            )
-        } else {
-            format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
-        },
-        in_header = layout.external_html.in_header,
-        before_content = layout.external_html.before_content,
-        after_content = layout.external_html.after_content,
-        sidebar = Buffer::html().to_display(sidebar),
-        krate = layout.krate,
-        default_settings = layout
-            .default_settings
-            .iter()
-            .map(|(k, v)| format!(r#" data-{}="{}""#, k.replace('-', "_"), Escape(v)))
-            .collect::<String>(),
-        style_files = style_files
-            .iter()
-            .filter_map(|t| {
-                if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
-            })
-            .filter_map(|t| {
-                if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None }
-            })
-            .map(|t| format!(
                 r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#,
                 Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
                 if t.1 { "disabled" } else { "" },
                 if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
-            ))
-            .collect::<String>(),
-        suffix = page.resource_suffix,
-        extra_scripts = page
-            .static_extra_scripts
-            .iter()
-            .map(|e| {
-                format!(
-                    "<script src=\"{static_root_path}{extra_script}.js\"></script>",
-                    static_root_path = static_root_path,
-                    extra_script = e
-                )
-            })
-            .chain(page.extra_scripts.iter().map(|e| {
-                format!(
-                    "<script src=\"{root_path}{extra_script}.js\"></script>",
-                    root_path = page.root_path,
-                    extra_script = e
-                )
-            }))
-            .collect::<String>(),
-        filter_crates = if layout.generate_search_filter {
-            "<select id=\"crate-search\">\
-                 <option value=\"All crates\">All crates</option>\
-             </select>"
-        } else {
-            ""
-        },
-    )
+            )
+        })
+        .collect::<String>();
+    let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
+    let sidebar = Buffer::html().to_display(sidebar);
+    let teractx = tera::Context::from_serialize(PageLayout {
+        static_root_path,
+        page,
+        layout,
+        style_files,
+        sidebar,
+        content,
+        krate_with_trailing_slash,
+    })
+    .unwrap();
+    templates.render("page.html", &teractx).unwrap()
 }
 
 crate fn redirect(url: &str) -> String {
index 00a91e07d65e3ff46d5e2d65da8697616a627854..908e292d968efbb045a2bb474a540a1e1e0cc06d 100644 (file)
@@ -33,6 +33,7 @@ use std::str;
 
 use crate::clean::RenderedLink;
 use crate::doctest;
+use crate::html::escape::Escape;
 use crate::html::highlight;
 use crate::html::toc::TocBuilder;
 
@@ -56,7 +57,7 @@ pub(crate) fn opts() -> Options {
 
 /// A subset of [`opts()`] used for rendering summaries.
 pub(crate) fn summary_opts() -> Options {
-    Options::ENABLE_STRIKETHROUGH | Options::ENABLE_SMART_PUNCTUATION
+    Options::ENABLE_STRIKETHROUGH | Options::ENABLE_SMART_PUNCTUATION | Options::ENABLE_TABLES
 }
 
 /// When `to_string` is called, this struct will emit the HTML corresponding to
@@ -207,26 +208,11 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
         let should_panic;
         let ignore;
         let edition;
-        if let Some(Event::Start(Tag::CodeBlock(kind))) = event {
-            let parse_result = match kind {
-                CodeBlockKind::Fenced(ref lang) => {
-                    LangString::parse_without_check(&lang, self.check_error_codes, false)
-                }
-                CodeBlockKind::Indented => Default::default(),
-            };
-            if !parse_result.rust {
-                return Some(Event::Start(Tag::CodeBlock(kind)));
-            }
-            compile_fail = parse_result.compile_fail;
-            should_panic = parse_result.should_panic;
-            ignore = parse_result.ignore;
-            edition = parse_result.edition;
+        let kind = if let Some(Event::Start(Tag::CodeBlock(kind))) = event {
+            kind
         } else {
             return event;
-        }
-
-        let explicit_edition = edition.is_some();
-        let edition = edition.unwrap_or(self.edition);
+        };
 
         let mut origtext = String::new();
         for event in &mut self.inner {
@@ -241,6 +227,35 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
         let lines = origtext.lines().filter_map(|l| map_line(l).for_html());
         let text = lines.collect::<Vec<Cow<'_, str>>>().join("\n");
 
+        let parse_result = match kind {
+            CodeBlockKind::Fenced(ref lang) => {
+                let parse_result =
+                    LangString::parse_without_check(&lang, self.check_error_codes, false);
+                if !parse_result.rust {
+                    return Some(Event::Html(
+                        format!(
+                            "<div class=\"example-wrap\">\
+                                 <pre{}>{}</pre>\
+                             </div>",
+                            format!(" class=\"language-{}\"", lang),
+                            Escape(&text),
+                        )
+                        .into(),
+                    ));
+                }
+                parse_result
+            }
+            CodeBlockKind::Indented => Default::default(),
+        };
+
+        compile_fail = parse_result.compile_fail;
+        should_panic = parse_result.should_panic;
+        ignore = parse_result.ignore;
+        edition = parse_result.edition;
+
+        let explicit_edition = edition.is_some();
+        let edition = edition.unwrap_or(self.edition);
+
         let playground_button = self.playground.as_ref().and_then(|playground| {
             let krate = &playground.crate_name;
             let url = &playground.url;
@@ -507,6 +522,10 @@ fn check_if_allowed_tag(t: &Tag<'_>) -> bool {
     )
 }
 
+fn is_forbidden_tag(t: &Tag<'_>) -> bool {
+    matches!(t, Tag::CodeBlock(_) | Tag::Table(_) | Tag::TableHead | Tag::TableRow | Tag::TableCell)
+}
+
 impl<'a, I: Iterator<Item = Event<'a>>> Iterator for SummaryLine<'a, I> {
     type Item = Event<'a>;
 
@@ -520,14 +539,17 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for SummaryLine<'a, I> {
         if let Some(event) = self.inner.next() {
             let mut is_start = true;
             let is_allowed_tag = match event {
-                Event::Start(Tag::CodeBlock(_)) | Event::End(Tag::CodeBlock(_)) => {
-                    return None;
-                }
                 Event::Start(ref c) => {
+                    if is_forbidden_tag(c) {
+                        return None;
+                    }
                     self.depth += 1;
                     check_if_allowed_tag(c)
                 }
                 Event::End(ref c) => {
+                    if is_forbidden_tag(c) {
+                        return None;
+                    }
                     self.depth -= 1;
                     is_start = false;
                     check_if_allowed_tag(c)
@@ -606,8 +628,7 @@ impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> {
                                 is_paragraph = true;
                             }
                             html::push_html(&mut ret, content.into_iter());
-                            write!(ret, "&nbsp;<a href=\"#fnref{}\" rev=\"footnote\">↩</a>", id)
-                                .unwrap();
+                            write!(ret, "&nbsp;<a href=\"#fnref{}\">↩</a>", id).unwrap();
                             if is_paragraph {
                                 ret.push_str("</p>");
                             }
@@ -1051,7 +1072,11 @@ impl MarkdownSummaryLine<'_> {
 ///
 /// Returns a tuple of the rendered HTML string and whether the output was shortened
 /// due to the provided `length_limit`.
-fn markdown_summary_with_limit(md: &str, length_limit: usize) -> (String, bool) {
+fn markdown_summary_with_limit(
+    md: &str,
+    link_names: &[RenderedLink],
+    length_limit: usize,
+) -> (String, bool) {
     if md.is_empty() {
         return (String::new(), false);
     }
@@ -1065,7 +1090,20 @@ fn markdown_summary_with_limit(md: &str, length_limit: usize) -> (String, bool)
         *text_length += text.len();
     }
 
-    'outer: for event in Parser::new_ext(md, summary_opts()) {
+    let mut replacer = |broken_link: BrokenLink<'_>| {
+        if let Some(link) =
+            link_names.iter().find(|link| &*link.original_text == broken_link.reference)
+        {
+            Some((link.href.as_str().into(), link.new_text.as_str().into()))
+        } else {
+            None
+        }
+    };
+
+    let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer));
+    let p = LinkReplacer::new(p, link_names);
+
+    'outer: for event in p {
         match &event {
             Event::Text(text) => {
                 for word in text.split_inclusive(char::is_whitespace) {
@@ -1121,8 +1159,8 @@ fn markdown_summary_with_limit(md: &str, length_limit: usize) -> (String, bool)
 /// Will shorten to 59 or 60 characters, including an ellipsis (…) if it was shortened.
 ///
 /// See [`markdown_summary_with_limit`] for details about what is rendered and what is not.
-crate fn short_markdown_summary(markdown: &str) -> String {
-    let (mut s, was_shortened) = markdown_summary_with_limit(markdown, 59);
+crate fn short_markdown_summary(markdown: &str, link_names: &[RenderedLink]) -> String {
+    let (mut s, was_shortened) = markdown_summary_with_limit(markdown, link_names, 59);
 
     if was_shortened {
         s.push('…');
@@ -1341,7 +1379,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);
@@ -1358,14 +1399,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);
@@ -1376,6 +1417,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 ac3ea4c8c5f6fd88fd7b6b4d7ae059ba642c75d9..d10da64ccfaa5447a50e4610d046e21e6e3dd520 100644 (file)
@@ -221,7 +221,7 @@ fn test_header_ids_multiple_blocks() {
 #[test]
 fn test_short_markdown_summary() {
     fn t(input: &str, expect: &str) {
-        let output = short_markdown_summary(input);
+        let output = short_markdown_summary(input, &[][..]);
         assert_eq!(output, expect, "original: {}", input);
     }
 
@@ -232,6 +232,7 @@ fn test_short_markdown_summary() {
     t("Hard-break  \nsummary", "Hard-break summary");
     t("hello [Rust] :)\n\n[Rust]: https://www.rust-lang.org", "hello Rust :)");
     t("hello [Rust](https://www.rust-lang.org \"Rust\") :)", "hello Rust :)");
+    t("dud [link]", "dud [link]");
     t("code `let x = i32;` ...", "code <code>let x = i32;</code> …");
     t("type `Type<'static>` ...", "type <code>Type<'static></code> …");
     t("# top header", "top header");
@@ -259,6 +260,7 @@ fn test_plain_text_summary() {
     t("Hard-break  \nsummary", "Hard-break summary");
     t("hello [Rust] :)\n\n[Rust]: https://www.rust-lang.org", "hello Rust :)");
     t("hello [Rust](https://www.rust-lang.org \"Rust\") :)", "hello Rust :)");
+    t("dud [link]", "dud [link]");
     t("code `let x = i32;` ...", "code `let x = i32;` …");
     t("type `Type<'static>` ...", "type `Type<'static>` …");
     t("# top header", "top header");
index 3e056c4b67a70df1d3127b54b22d9e7b910444cf..0734d2670ccfae7b07379fc8630d3408937a67f2 100644 (file)
@@ -12,7 +12,7 @@ use crate::clean::types::{
 use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
 use crate::html::markdown::short_markdown_summary;
-use crate::html::render::{Generic, IndexItem, IndexItemFunctionType, RenderType, TypeWithKind};
+use crate::html::render::{IndexItem, IndexItemFunctionType, RenderType, TypeWithKind};
 
 /// Indicates where an external crate can be found.
 crate enum ExternalLocation {
@@ -34,19 +34,27 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
     // has since been learned.
     for &(did, ref item) in &cache.orphan_impl_items {
         if let Some(&(ref fqp, _)) = cache.paths.get(&did) {
+            let desc = item
+                .doc_value()
+                .map_or_else(String::new, |s| short_markdown_summary(&s, &item.link_names(&cache)));
             cache.search_index.push(IndexItem {
                 ty: item.type_(),
                 name: item.name.unwrap().to_string(),
                 path: fqp[..fqp.len() - 1].join("::"),
-                desc: item.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)),
+                desc,
                 parent: Some(did.into()),
                 parent_idx: None,
-                search_type: get_index_search_type(&item, cache, tcx),
+                search_type: get_index_search_type(&item, tcx),
                 aliases: item.attrs.get_doc_aliases(),
             });
         }
     }
 
+    let crate_doc = krate
+        .module
+        .doc_value()
+        .map_or_else(String::new, |s| short_markdown_summary(&s, &krate.module.link_names(&cache)));
+
     let Cache { ref mut search_index, ref paths, .. } = *cache;
 
     // Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
@@ -100,9 +108,6 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
         crate_items.push(&*item);
     }
 
-    let crate_doc =
-        krate.module.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s));
-
     struct CrateData<'a> {
         doc: String,
         items: Vec<&'a IndexItem>,
@@ -187,7 +192,6 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
 
 crate fn get_index_search_type<'tcx>(
     item: &clean::Item,
-    cache: &Cache,
     tcx: TyCtxt<'tcx>,
 ) -> Option<IndexItemFunctionType> {
     let (all_types, ret_types) = match *item.kind {
@@ -199,12 +203,12 @@ crate fn get_index_search_type<'tcx>(
 
     let inputs = all_types
         .iter()
-        .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty, &cache), *kind)))
+        .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind)))
         .filter(|a| a.ty.name.is_some())
         .collect();
     let output = ret_types
         .iter()
-        .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty, &cache), *kind)))
+        .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind)))
         .filter(|a| a.ty.name.is_some())
         .collect::<Vec<_>>();
     let output = if output.is_empty() { None } else { Some(output) };
@@ -212,12 +216,10 @@ crate fn get_index_search_type<'tcx>(
     Some(IndexItemFunctionType { inputs, output })
 }
 
-fn get_index_type(clean_type: &clean::Type, cache: &Cache) -> RenderType {
+fn get_index_type(clean_type: &clean::Type) -> RenderType {
     RenderType {
-        ty: clean_type.def_id_full(cache),
-        idx: None,
         name: get_index_type_name(clean_type, true).map(|s| s.as_str().to_ascii_lowercase()),
-        generics: get_generics(clean_type, cache),
+        generics: get_generics(clean_type),
     }
 }
 
@@ -233,6 +235,7 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
             });
             Some(path_segment.name)
         }
+        clean::DynTrait(ref bounds, _) => get_index_type_name(&bounds[0].trait_, accept_generic),
         clean::Generic(s) if accept_generic => Some(s),
         clean::Primitive(ref p) => Some(p.as_sym()),
         clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_, accept_generic),
@@ -249,16 +252,17 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
     }
 }
 
-fn get_generics(clean_type: &clean::Type, cache: &Cache) -> Option<Vec<Generic>> {
+/// Return a list of generic parameters for use in the search index.
+///
+/// This function replaces bounds with types, so that `T where T: Debug` just becomes `Debug`.
+/// It does return duplicates, and that's intentional, since search queries like `Result<usize, usize>`
+/// are supposed to match only results where both parameters are `usize`.
+fn get_generics(clean_type: &clean::Type) -> Option<Vec<String>> {
     clean_type.generics().and_then(|types| {
         let r = types
             .iter()
             .filter_map(|t| {
-                get_index_type_name(t, false).map(|name| Generic {
-                    name: name.as_str().to_ascii_lowercase(),
-                    defid: t.def_id_full(cache),
-                    idx: None,
-                })
+                get_index_type_name(t, false).map(|name| name.as_str().to_ascii_lowercase())
             })
             .collect::<Vec<_>>();
         if r.is_empty() { None } else { Some(r) }
index 84c5b5dd60466ab273aa014b70b6c0ed7d5ba183..b6c3220901f06ad4289f50311357ebbf525084dc 100644 (file)
@@ -1,5 +1,6 @@
 use std::cell::RefCell;
 use std::collections::BTreeMap;
+use std::error::Error as StdError;
 use std::io;
 use std::path::{Path, PathBuf};
 use std::rc::Rc;
@@ -29,6 +30,7 @@ use crate::formats::FormatRenderer;
 use crate::html::escape::Escape;
 use crate::html::format::Buffer;
 use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
+use crate::html::static_files::PAGE;
 use crate::html::{layout, sources};
 
 /// Major driving force in all rustdoc rendering. This contains information
@@ -121,6 +123,8 @@ crate struct SharedContext<'tcx> {
     /// to `Some(...)`, it'll store redirections and then generate a JSON file at the top level of
     /// the crate.
     redirections: Option<RefCell<FxHashMap<String, String>>>,
+
+    pub(crate) templates: tera::Tera,
 }
 
 impl SharedContext<'_> {
@@ -218,6 +222,7 @@ impl<'tcx> Context<'tcx> {
 
         if !self.render_redirect_pages {
             layout::render(
+                &self.shared.templates,
                 &self.shared.layout,
                 &page,
                 |buf: &mut _| print_sidebar(self, it, buf),
@@ -225,7 +230,7 @@ impl<'tcx> Context<'tcx> {
                 &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);
@@ -408,6 +413,12 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         let mut issue_tracker_base_url = None;
         let mut include_sources = true;
 
+        let mut templates = tera::Tera::default();
+        templates.add_raw_template("page.html", PAGE).map_err(|e| Error {
+            file: "page.html".into(),
+            error: format!("{}: {}", e, e.source().map(|e| e.to_string()).unwrap_or_default()),
+        })?;
+
         // Crawl the crate attributes looking for attributes which control how we're
         // going to emit HTML
         for attr in krate.module.attrs.lists(sym::doc) {
@@ -454,6 +465,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             errors: receiver,
             redirections: if generate_redirect_map { Some(Default::default()) } else { None },
             show_type_layout,
+            templates,
         };
 
         // Add the default themes to the `Vec` of stylepaths
@@ -540,6 +552,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         };
         let all = self.shared.all.replace(AllTypes::new());
         let v = layout::render(
+            &self.shared.templates,
             &self.shared.layout,
             &page,
             sidebar,
@@ -557,6 +570,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
         style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false });
         let v = layout::render(
+            &self.shared.templates,
             &self.shared.layout,
             &page,
             sidebar,
index 0b14c327e47236773d0c1092c1ea4c88076e6f0a..fab7440817ce5ef00619fa117c54031c56d69ce1 100644 (file)
@@ -42,7 +42,7 @@ use std::str;
 use std::string::ToString;
 
 use rustc_ast_pretty::pprust;
-use rustc_attr::{Deprecation, StabilityLevel};
+use rustc_attr::{ConstStability, Deprecation, StabilityLevel};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
@@ -53,7 +53,7 @@ use rustc_span::symbol::{kw, sym, Symbol};
 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;
@@ -61,8 +61,8 @@ use crate::formats::item_type::ItemType;
 use crate::formats::{AssocItemRender, Impl, RenderMode};
 use crate::html::escape::Escape;
 use crate::html::format::{
-    href, print_abi_with_space, print_default_space, print_generic_bounds, print_where_clause,
-    Buffer, PrintWithSpace,
+    href, print_abi_with_space, print_constness_with_space, print_default_space,
+    print_generic_bounds, print_where_clause, Buffer, HrefError, PrintWithSpace,
 };
 use crate::html::markdown::{Markdown, MarkdownHtml, MarkdownSummaryLine};
 
@@ -95,53 +95,8 @@ crate struct IndexItem {
 /// A type used for the search index.
 #[derive(Debug)]
 crate struct RenderType {
-    ty: Option<DefId>,
-    idx: Option<usize>,
     name: Option<String>,
-    generics: Option<Vec<Generic>>,
-}
-
-impl Serialize for RenderType {
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    where
-        S: Serializer,
-    {
-        if let Some(name) = &self.name {
-            let mut seq = serializer.serialize_seq(None)?;
-            if let Some(id) = self.idx {
-                seq.serialize_element(&id)?;
-            } else {
-                seq.serialize_element(&name)?;
-            }
-            if let Some(generics) = &self.generics {
-                seq.serialize_element(&generics)?;
-            }
-            seq.end()
-        } else {
-            serializer.serialize_none()
-        }
-    }
-}
-
-/// A type used for the search index.
-#[derive(Debug)]
-crate struct Generic {
-    name: String,
-    defid: Option<DefId>,
-    idx: Option<usize>,
-}
-
-impl Serialize for Generic {
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    where
-        S: Serializer,
-    {
-        if let Some(id) = self.idx {
-            serializer.serialize_some(&id)
-        } else {
-            serializer.serialize_some(&self.name)
-        }
-    }
+    generics: Option<Vec<String>>,
 }
 
 /// Full type of functions/methods in the search index.
@@ -195,7 +150,13 @@ impl Serialize for TypeWithKind {
     where
         S: Serializer,
     {
-        (&self.ty.name, self.kind).serialize(serializer)
+        let mut seq = serializer.serialize_seq(None)?;
+        seq.serialize_element(&self.ty.name)?;
+        seq.serialize_element(&self.kind)?;
+        if let Some(generics) = &self.ty.generics {
+            seq.serialize_element(generics)?;
+        }
+        seq.end()
     }
 }
 
@@ -488,9 +449,8 @@ fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result<Strin
             .into(),
         ("auto-hide-large-items", "Auto-hide item contents for large items.", true).into(),
         ("auto-hide-method-docs", "Auto-hide item methods' documentation", false).into(),
-        ("auto-hide-trait-implementations", "Auto-hide trait implementation documentation", true)
+        ("auto-hide-trait-implementations", "Auto-hide trait implementation documentation", false)
             .into(),
-        ("auto-collapse-implementors", "Auto-hide implementors of a trait", true).into(),
         ("go-to-only-result", "Directly go to item in search if there is only one result", false)
             .into(),
         ("line-numbers", "Show line numbers on code examples", false).into(),
@@ -724,6 +684,8 @@ fn short_item_info(
     extra_info
 }
 
+// Render the list of items inside one of the sections "Trait Implementations",
+// "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages).
 fn render_impls(
     cx: &Context<'_>,
     w: &mut Buffer,
@@ -746,13 +708,15 @@ fn render_impls(
                 containing_item,
                 assoc_link,
                 RenderMode::Normal,
-                containing_item.stable_since(tcx).as_deref(),
-                containing_item.const_stable_since(tcx).as_deref(),
-                true,
                 None,
-                false,
-                true,
                 &[],
+                ImplRenderingParameters {
+                    show_def_docs: true,
+                    is_on_foreign_type: false,
+                    show_default_items: true,
+                    show_non_assoc_items: true,
+                    toggle_open_by_default: true,
+                },
             );
             buffer.into_inner()
         })
@@ -775,7 +739,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)
         }
     }
 }
@@ -827,21 +791,45 @@ fn assoc_type(
 fn render_stability_since_raw(
     w: &mut Buffer,
     ver: Option<&str>,
-    const_ver: Option<&str>,
+    const_stability: Option<&ConstStability>,
     containing_ver: Option<&str>,
     containing_const_ver: Option<&str>,
 ) {
     let ver = ver.filter(|inner| !inner.is_empty());
-    let const_ver = const_ver.filter(|inner| !inner.is_empty());
 
-    match (ver, const_ver) {
-        (Some(v), Some(cv)) if const_ver != containing_const_ver => {
+    match (ver, const_stability) {
+        // stable and const stable
+        (Some(v), Some(ConstStability { level: StabilityLevel::Stable { since }, .. }))
+            if Some(since.as_str()).as_deref() != containing_const_ver =>
+        {
             write!(
                 w,
                 "<span class=\"since\" title=\"Stable since Rust version {0}, const since {1}\">{0} (const: {1})</span>",
-                v, cv
+                v, since
+            );
+        }
+        // stable and const unstable
+        (
+            Some(v),
+            Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }),
+        ) => {
+            write!(
+                w,
+                "<span class=\"since\" title=\"Stable since Rust version {0}, const unstable\">{0} (const: ",
+                v
             );
+            if let Some(n) = issue {
+                write!(
+                    w,
+                    "<a href=\"https://github.com/rust-lang/rust/issues/{}\" title=\"Tracking issue for {}\">unstable</a>",
+                    n, feature
+                );
+            } else {
+                write!(w, "unstable");
+            }
+            write!(w, ")</span>");
         }
+        // stable
         (Some(v), _) if ver != containing_ver => {
             write!(
                 w,
@@ -872,8 +860,8 @@ fn render_assoc_item(
     ) {
         let name = meth.name.as_ref().unwrap();
         let href = match link {
-            AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id),
-            AssocItemLink::Anchor(None) => format!("#{}.{}", meth.type_(), name),
+            AssocItemLink::Anchor(Some(ref id)) => Some(format!("#{}", id)),
+            AssocItemLink::Anchor(None) => Some(format!("#{}.{}", meth.type_(), name)),
             AssocItemLink::GotoSource(did, provided_methods) => {
                 // We're creating a link from an impl-item to the corresponding
                 // trait-item and need to map the anchored type accordingly.
@@ -883,17 +871,21 @@ fn render_assoc_item(
                     ItemType::TyMethod
                 };
 
-                href(did.expect_real(), cx)
-                    .map(|p| format!("{}#{}.{}", p.0, ty, name))
-                    .unwrap_or_else(|| format!("#{}.{}", ty, name))
+                match (href(did.expect_def_id(), cx), ty) {
+                    (Ok(p), ty) => Some(format!("{}#{}.{}", p.0, ty, name)),
+                    (Err(HrefError::DocumentationNotBuilt), ItemType::TyMethod) => None,
+                    (Err(_), ty) => Some(format!("#{}.{}", ty, name)),
+                }
             }
         };
         let vis = meth.visibility.print_with_space(meth.def_id, cx).to_string();
-        let constness = header.constness.print_with_space();
+        let constness =
+            print_constness_with_space(&header.constness, meth.const_stability(cx.tcx()));
         let asyncness = header.asyncness.print_with_space();
         let unsafety = header.unsafety.print_with_space();
         let defaultness = print_default_space(meth.is_default());
         let abi = print_abi_with_space(header.abi).to_string();
+
         // NOTE: `{:#}` does not print HTML formatting, `{}` does. So `g.print` can't be reused between the length calculation and `write!`.
         let generics_len = format!("{:#}", g.print(cx)).len();
         let mut header_len = "fn ".len()
@@ -918,16 +910,17 @@ fn render_assoc_item(
         w.reserve(header_len + "<a href=\"\" class=\"fnname\">{".len() + "</a>".len());
         write!(
             w,
-            "{}{}{}{}{}{}{}fn <a href=\"{href}\" class=\"fnname\">{name}</a>\
+            "{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn <a {href} class=\"fnname\">{name}</a>\
              {generics}{decl}{notable_traits}{where_clause}",
-            indent_str,
-            vis,
-            constness,
-            asyncness,
-            unsafety,
-            defaultness,
-            abi,
-            href = href,
+            indent = indent_str,
+            vis = vis,
+            constness = constness,
+            asyncness = asyncness,
+            unsafety = unsafety,
+            defaultness = defaultness,
+            abi = abi,
+            // links without a href are valid - https://www.w3schools.com/tags/att_a_href.asp
+            href = href.map(|href| format!("href=\"{}\"", href)).unwrap_or_else(|| "".to_string()),
             name = name,
             generics = g.print(cx),
             decl = d.full_print(header_len, indent, header.asyncness, cx),
@@ -965,14 +958,8 @@ fn render_assoc_item(
     }
 }
 
-const ALLOWED_ATTRIBUTES: &[Symbol] = &[
-    sym::export_name,
-    sym::link_section,
-    sym::must_use,
-    sym::no_mangle,
-    sym::repr,
-    sym::non_exhaustive,
-];
+const ALLOWED_ATTRIBUTES: &[Symbol] =
+    &[sym::export_name, sym::link_section, sym::no_mangle, sym::repr, sym::non_exhaustive];
 
 fn attributes(it: &clean::Item) -> Vec<String> {
     it.attrs
@@ -1007,7 +994,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> {
@@ -1031,7 +1018,6 @@ fn render_assoc_items(
         Some(v) => v,
         None => return,
     };
-    let tcx = cx.tcx();
     let cache = cx.cache();
     let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
     if !non_trait.is_empty() {
@@ -1048,7 +1034,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),
@@ -1065,13 +1051,15 @@ fn render_assoc_items(
                 containing_item,
                 AssocItemLink::Anchor(None),
                 render_mode,
-                containing_item.stable_since(tcx).as_deref(),
-                containing_item.const_stable_since(tcx).as_deref(),
-                true,
                 None,
-                false,
-                true,
                 &[],
+                ImplRenderingParameters {
+                    show_def_docs: true,
+                    is_on_foreign_type: false,
+                    show_default_items: true,
+                    show_non_assoc_items: true,
+                    toggle_open_by_default: true,
+                },
             );
         }
     }
@@ -1260,6 +1248,16 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
     out.into_inner()
 }
 
+#[derive(Clone, Copy, Debug)]
+struct ImplRenderingParameters {
+    show_def_docs: bool,
+    is_on_foreign_type: bool,
+    show_default_items: bool,
+    /// Whether or not to show methods.
+    show_non_assoc_items: bool,
+    toggle_open_by_default: bool,
+}
+
 fn render_impl(
     w: &mut Buffer,
     cx: &Context<'_>,
@@ -1267,15 +1265,9 @@ fn render_impl(
     parent: &clean::Item,
     link: AssocItemLink<'_>,
     render_mode: RenderMode,
-    outer_version: Option<&str>,
-    outer_const_version: Option<&str>,
-    show_def_docs: bool,
     use_absolute: Option<bool>,
-    is_on_foreign_type: bool,
-    show_default_items: bool,
-    // This argument is used to reference same type with different paths to avoid duplication
-    // in documentation pages for trait with automatic implementations like "Send" and "Sync".
     aliases: &[String],
+    rendering_params: ImplRenderingParameters,
 ) {
     let cache = cx.cache();
     let traits = &cache.traits;
@@ -1285,30 +1277,31 @@ fn render_impl(
     // For trait implementations, the `interesting` output contains all methods that have doc
     // comments, and the `boring` output contains all methods that do not. The distinction is
     // used to allow hiding the boring methods.
+    // `containing_item` is used for rendering stability info. If the parent is a trait impl,
+    // `containing_item` will the grandparent, since trait impls can't have stability attached.
     fn doc_impl_item(
         boring: &mut Buffer,
         interesting: &mut Buffer,
         cx: &Context<'_>,
         item: &clean::Item,
         parent: &clean::Item,
+        containing_item: &clean::Item,
         link: AssocItemLink<'_>,
         render_mode: RenderMode,
         is_default_item: bool,
-        outer_version: Option<&str>,
-        outer_const_version: Option<&str>,
         trait_: Option<&clean::Trait>,
-        show_def_docs: bool,
+        rendering_params: ImplRenderingParameters,
     ) {
         let item_type = item.type_();
         let name = item.name.as_ref().unwrap();
-        let tcx = cx.tcx();
 
-        let render_method_item = match render_mode {
-            RenderMode::Normal => true,
-            RenderMode::ForDeref { mut_: deref_mut_ } => {
-                should_render_item(&item, deref_mut_, &cx.cache)
-            }
-        };
+        let render_method_item = rendering_params.show_non_assoc_items
+            && match render_mode {
+                RenderMode::Normal => true,
+                RenderMode::ForDeref { mut_: deref_mut_ } => {
+                    should_render_item(&item, deref_mut_, &cx.cache)
+                }
+            };
 
         let in_trait_class = if trait_.is_some() { " trait-impl" } else { "" };
 
@@ -1331,18 +1324,32 @@ fn render_impl(
                         } else {
                             // In case the item isn't documented,
                             // provide short documentation from the trait.
-                            document_short(&mut doc_buffer, it, cx, link, parent, show_def_docs);
+                            document_short(
+                                &mut doc_buffer,
+                                it,
+                                cx,
+                                link,
+                                parent,
+                                rendering_params.show_def_docs,
+                            );
                         }
                     }
                 } else {
                     document_item_info(&mut info_buffer, cx, item, Some(parent));
-                    if show_def_docs {
+                    if rendering_params.show_def_docs {
                         document_full(&mut doc_buffer, item, cx);
                         short_documented = false;
                     }
                 }
             } else {
-                document_short(&mut doc_buffer, item, cx, link, parent, show_def_docs);
+                document_short(
+                    &mut doc_buffer,
+                    item,
+                    cx,
+                    link,
+                    parent,
+                    rendering_params.show_def_docs,
+                );
             }
         }
         let w = if short_documented && trait_.is_some() { interesting } else { boring };
@@ -1370,6 +1377,8 @@ fn render_impl(
                         "<div id=\"{}\" class=\"{}{} has-srclink\">",
                         id, item_type, in_trait_class,
                     );
+                    render_rightside(w, cx, item, containing_item);
+                    write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
                     w.write_str("<h4 class=\"code-header\">");
                     render_assoc_item(
                         w,
@@ -1379,15 +1388,6 @@ fn render_impl(
                         cx,
                     );
                     w.write_str("</h4>");
-                    render_stability_since_raw(
-                        w,
-                        item.stable_since(tcx).as_deref(),
-                        item.const_stable_since(tcx).as_deref(),
-                        outer_version,
-                        outer_const_version,
-                    );
-                    write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
-                    write_srclink(cx, item, w);
                     w.write_str("</div>");
                 }
             }
@@ -1399,6 +1399,7 @@ fn render_impl(
                     "<div id=\"{}\" class=\"{}{} has-srclink\">",
                     id, item_type, in_trait_class
                 );
+                write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
                 w.write_str("<h4 class=\"code-header\">");
                 assoc_type(
                     w,
@@ -1410,7 +1411,6 @@ fn render_impl(
                     cx,
                 );
                 w.write_str("</h4>");
-                write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
                 w.write_str("</div>");
             }
             clean::AssocConstItem(ref ty, ref default) => {
@@ -1421,6 +1421,8 @@ fn render_impl(
                     "<div id=\"{}\" class=\"{}{} has-srclink\">",
                     id, item_type, in_trait_class
                 );
+                render_rightside(w, cx, item, containing_item);
+                write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
                 w.write_str("<h4 class=\"code-header\">");
                 assoc_const(
                     w,
@@ -1432,21 +1434,13 @@ fn render_impl(
                     cx,
                 );
                 w.write_str("</h4>");
-                render_stability_since_raw(
-                    w,
-                    item.stable_since(tcx).as_deref(),
-                    item.const_stable_since(tcx).as_deref(),
-                    outer_version,
-                    outer_const_version,
-                );
-                write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
-                write_srclink(cx, item, w);
                 w.write_str("</div>");
             }
             clean::AssocTypeItem(ref bounds, ref default) => {
                 let source_id = format!("{}.{}", item_type, name);
                 let id = cx.derive_id(source_id.clone());
                 write!(w, "<div id=\"{}\" class=\"{}{}\">", id, item_type, in_trait_class,);
+                write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
                 w.write_str("<h4 class=\"code-header\">");
                 assoc_type(
                     w,
@@ -1458,7 +1452,6 @@ fn render_impl(
                     cx,
                 );
                 w.write_str("</h4>");
-                write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
                 w.write_str("</div>");
             }
             clean::StrippedItem(..) => return,
@@ -1483,13 +1476,12 @@ fn render_impl(
             cx,
             trait_item,
             if trait_.is_some() { &i.impl_item } else { parent },
+            parent,
             link,
             render_mode,
             false,
-            outer_version,
-            outer_const_version,
             trait_.map(|t| &t.trait_),
-            show_def_docs,
+            rendering_params,
         );
     }
 
@@ -1500,10 +1492,9 @@ fn render_impl(
         t: &clean::Trait,
         i: &clean::Impl,
         parent: &clean::Item,
+        containing_item: &clean::Item,
         render_mode: RenderMode,
-        outer_version: Option<&str>,
-        outer_const_version: Option<&str>,
-        show_def_docs: bool,
+        rendering_params: ImplRenderingParameters,
     ) {
         for trait_item in &t.items {
             let n = trait_item.name;
@@ -1520,13 +1511,12 @@ fn render_impl(
                 cx,
                 trait_item,
                 parent,
+                containing_item,
                 assoc_link,
                 render_mode,
                 true,
-                outer_version,
-                outer_const_version,
                 Some(t),
-                show_def_docs,
+                rendering_params,
             );
         }
     }
@@ -1535,7 +1525,7 @@ fn render_impl(
     // default items which weren't overridden in the implementation block.
     // We don't emit documentation for default items if they appear in the
     // Implementations on Foreign Types or Implementors sections.
-    if show_default_items {
+    if rendering_params.show_default_items {
         if let Some(t) = trait_ {
             render_default_items(
                 &mut default_impl_items,
@@ -1544,46 +1534,37 @@ fn render_impl(
                 &t.trait_,
                 &i.inner_impl(),
                 &i.impl_item,
+                parent,
                 render_mode,
-                outer_version,
-                outer_const_version,
-                show_def_docs,
+                rendering_params,
             );
         }
     }
     if render_mode == RenderMode::Normal {
-        let is_implementing_trait = i.inner_impl().trait_.is_some();
-        let toggled = !impl_items.is_empty() || !default_impl_items.is_empty();
+        let toggled = !(impl_items.is_empty() && default_impl_items.is_empty());
         if toggled {
             close_tags.insert_str(0, "</details>");
-            if is_implementing_trait {
-                write!(w, "<details class=\"rustdoc-toggle implementors-toggle\">");
-            } else {
-                write!(w, "<details class=\"rustdoc-toggle implementors-toggle\" open>");
-            }
-        }
-        if toggled {
+            write!(
+                w,
+                "<details class=\"rustdoc-toggle implementors-toggle\"{}>",
+                if rendering_params.toggle_open_by_default { " open" } else { "" }
+            );
             write!(w, "<summary>")
         }
         render_impl_summary(
             w,
             cx,
             i,
-            outer_version,
-            outer_const_version,
-            show_def_docs,
+            parent,
+            parent,
+            rendering_params.show_def_docs,
             use_absolute,
-            is_on_foreign_type,
+            rendering_params.is_on_foreign_type,
             aliases,
         );
         if toggled {
             write!(w, "</summary>")
         }
-        if trait_.is_some() {
-            if let Some(portability) = portability(&i.impl_item, Some(parent)) {
-                write!(w, "<div class=\"item-info\">{}</div>", portability);
-            }
-        }
 
         if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) {
             let mut ids = cx.id_map.borrow_mut();
@@ -1611,12 +1592,35 @@ fn render_impl(
     w.write_str(&close_tags);
 }
 
-fn render_impl_summary(
+// Render the items that appear on the right side of methods, impls, and
+// associated types. For example "1.0.0 (const: 1.39.0) [src]".
+fn render_rightside(
+    w: &mut Buffer,
+    cx: &Context<'_>,
+    item: &clean::Item,
+    containing_item: &clean::Item,
+) {
+    let tcx = cx.tcx();
+
+    write!(w, "<div class=\"rightside\">");
+    render_stability_since_raw(
+        w,
+        item.stable_since(tcx).as_deref(),
+        item.const_stability(tcx),
+        containing_item.stable_since(tcx).as_deref(),
+        containing_item.const_stable_since(tcx).as_deref(),
+    );
+
+    write_srclink(cx, item, w);
+    w.write_str("</div>");
+}
+
+pub(crate) fn render_impl_summary(
     w: &mut Buffer,
     cx: &Context<'_>,
     i: &Impl,
-    outer_version: Option<&str>,
-    outer_const_version: Option<&str>,
+    parent: &clean::Item,
+    containing_item: &clean::Item,
     show_def_docs: bool,
     use_absolute: Option<bool>,
     is_on_foreign_type: bool,
@@ -1624,7 +1628,6 @@ fn render_impl_summary(
     // in documentation pages for trait with automatic implementations like "Send" and "Sync".
     aliases: &[String],
 ) {
-    let tcx = cx.tcx();
     let id = cx.derive_id(match i.inner_impl().trait_ {
         Some(ref t) => {
             if is_on_foreign_type {
@@ -1640,9 +1643,12 @@ fn render_impl_summary(
     } else {
         format!(" data-aliases=\"{}\"", aliases.join(","))
     };
+    write!(w, "<div id=\"{}\" class=\"impl has-srclink\"{}>", id, aliases);
+    render_rightside(w, cx, &i.impl_item, containing_item);
+    write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
+    write!(w, "<h3 class=\"code-header in-band\">");
+
     if let Some(use_absolute) = use_absolute {
-        write!(w, "<div id=\"{}\" class=\"impl has-srclink\"{}>", id, aliases);
-        write!(w, "<h3 class=\"code-header in-band\">");
         write!(w, "{}", i.inner_impl().print(use_absolute, cx));
         if show_def_docs {
             for it in &i.inner_impl().items {
@@ -1653,26 +1659,18 @@ fn render_impl_summary(
                 }
             }
         }
-        w.write_str("</h3>");
     } else {
-        write!(
-            w,
-            "<div id=\"{}\" class=\"impl has-srclink\"{}>\
-                     <h3 class=\"code-header in-band\">{}</h3>",
-            id,
-            aliases,
-            i.inner_impl().print(false, cx)
-        );
+        write!(w, "{}", i.inner_impl().print(false, cx));
     }
-    write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
-    render_stability_since_raw(
-        w,
-        i.impl_item.stable_since(tcx).as_deref(),
-        i.impl_item.const_stable_since(tcx).as_deref(),
-        outer_version,
-        outer_const_version,
-    );
-    write_srclink(cx, &i.impl_item, w);
+    write!(w, "</h3>");
+
+    let is_trait = i.inner_impl().trait_.is_some();
+    if is_trait {
+        if let Some(portability) = portability(&i.impl_item, Some(parent)) {
+            write!(w, "<div class=\"item-info\">{}</div>", portability);
+        }
+    }
+
     w.write_str("</div>");
 }
 
@@ -1715,6 +1713,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
             write!(
                 buffer,
                 "<div class=\"block version\">\
+                     <div class=\"narrow-helper\"></div>\
                      <p>Version {}</p>\
                  </div>",
                 Escape(version),
@@ -1856,7 +1855,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();
@@ -2022,19 +2021,6 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
                 out.push_str("</div>");
             }
         }
-
-        // Recurse into any further impls that might exist for `target`
-        if let Some(target_did) = target.def_id_full(c) {
-            if let Some(target_impls) = c.impls.get(&target_did) {
-                if let Some(target_deref_impl) = target_impls
-                    .iter()
-                    .filter(|i| i.inner_impl().trait_.is_some())
-                    .find(|i| i.inner_impl().trait_.def_id_full(c) == c.deref_trait_did)
-                {
-                    sidebar_deref_methods(cx, out, target_deref_impl, target_impls);
-                }
-            }
-        }
     }
 }
 
@@ -2159,7 +2145,7 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
         "</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 aef516e33354d9b5bcf6f433d2c194b8f89d3800..b12e56bfe9b3cbfa1ea31da3a114b58830b9cc57 100644 (file)
@@ -1,6 +1,7 @@
 use clean::AttributesExt;
 
 use std::cmp::Ordering;
+use std::fmt;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
@@ -16,16 +17,22 @@ use super::{
     collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl,
     render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre,
     render_impl, render_stability_since_raw, write_srclink, AssocItemLink, Context,
+    ImplRenderingParameters,
 };
 use crate::clean::{self, GetDefId};
 use crate::formats::item_type::ItemType;
 use crate::formats::{AssocItemRender, Impl, RenderMode};
 use crate::html::escape::Escape;
-use crate::html::format::{print_abi_with_space, print_where_clause, Buffer, PrintWithSpace};
+use crate::html::format::{
+    print_abi_with_space, print_constness_with_space, print_where_clause, Buffer, PrintWithSpace,
+};
 use crate::html::highlight;
 use crate::html::layout::Page;
 use crate::html::markdown::MarkdownSummaryLine;
 
+const ITEM_TABLE_OPEN: &'static str = "<div class=\"item-table\">";
+const ITEM_TABLE_CLOSE: &'static str = "</div>";
+
 pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, page: &Page<'_>) {
     debug_assert!(!item.is_stripped());
     // Write the breadcrumb trail header for the top
@@ -93,7 +100,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer,
     render_stability_since_raw(
         buf,
         item.stable_since(cx.tcx()).as_deref(),
-        item.const_stable_since(cx.tcx()).as_deref(),
+        item.const_stability(cx.tcx()),
         None,
         None,
     );
@@ -127,7 +134,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),
@@ -149,7 +156,7 @@ fn should_hide_fields(n_fields: usize) -> bool {
     n_fields > 12
 }
 
-fn toggle_open(w: &mut Buffer, text: &str) {
+fn toggle_open(w: &mut Buffer, text: impl fmt::Display) {
     write!(
         w,
         "<details class=\"rustdoc-toggle type-contents-toggle\">\
@@ -260,14 +267,15 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
             curty = myty;
         } else if myty != curty {
             if curty.is_some() {
-                w.write_str("</table>");
+                w.write_str(ITEM_TABLE_CLOSE);
             }
             curty = myty;
             let (short, name) = item_ty_to_strs(myty.unwrap());
             write!(
                 w,
                 "<h2 id=\"{id}\" class=\"section-header\">\
-                       <a href=\"#{id}\">{name}</a></h2>\n<table>",
+                       <a href=\"#{id}\">{name}</a></h2>\n{}",
+                ITEM_TABLE_OPEN,
                 id = cx.derive_id(short.to_owned()),
                 name = name
             );
@@ -280,23 +288,23 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
                 match *src {
                     Some(ref src) => write!(
                         w,
-                        "<tr><td><code>{}extern crate {} as {};",
+                        "<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!(
                         w,
-                        "<tr><td><code>{}extern crate {};",
+                        "<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
                         ),
                     ),
                 }
-                w.write_str("</code></td></tr>");
+                w.write_str("</code></div>");
             }
 
             clean::ImportItem(ref import) => {
@@ -323,10 +331,10 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
 
                 write!(
                     w,
-                    "<tr class=\"{stab}{add}import-item\">\
-                         <td><code>{vis}{imp}</code></td>\
-                         <td class=\"docblock-short\">{stab_tags}</td>\
-                     </tr>",
+                    "<div class=\"item-left {stab}{add}import-item\">\
+                         <code>{vis}{imp}</code>\
+                     </div>\
+                     <div class=\"item-right docblock-short\">{stab_tags}</div>",
                     stab = stab.unwrap_or_default(),
                     add = add,
                     vis = myitem.visibility.print_with_space(myitem.def_id, cx),
@@ -355,11 +363,12 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
                 let doc_value = myitem.doc_value().unwrap_or_default();
                 write!(
                     w,
-                    "<tr class=\"{stab}{add}module-item\">\
-                         <td><a class=\"{class}\" href=\"{href}\" \
-                             title=\"{title}\">{name}</a>{unsafety_flag}</td>\
-                         <td class=\"docblock-short\">{stab_tags}{docs}</td>\
-                     </tr>",
+                    "<div class=\"item-left {stab}{add}module-item\">\
+                         <a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\
+                             {unsafety_flag}\
+                             {stab_tags}\
+                     </div>\
+                     <div class=\"item-right docblock-short\">{docs}</div>",
                     name = *myitem.name.as_ref().unwrap(),
                     stab_tags = extra_info_tags(myitem, item, cx.tcx()),
                     docs = MarkdownSummaryLine(&doc_value, &myitem.links(cx)).into_string(),
@@ -379,7 +388,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
     }
 
     if curty.is_some() {
-        w.write_str("</table>");
+        w.write_str(ITEM_TABLE_CLOSE);
     }
 }
 
@@ -429,29 +438,36 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) ->
 }
 
 fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) {
-    let header_len = format!(
-        "{}{}{}{}{:#}fn {}{:#}",
-        it.visibility.print_with_space(it.def_id, cx),
-        f.header.constness.print_with_space(),
-        f.header.asyncness.print_with_space(),
-        f.header.unsafety.print_with_space(),
-        print_abi_with_space(f.header.abi),
-        it.name.as_ref().unwrap(),
-        f.generics.print(cx),
-    )
-    .len();
+    let vis = it.visibility.print_with_space(it.def_id, cx).to_string();
+    let constness = print_constness_with_space(&f.header.constness, it.const_stability(cx.tcx()));
+    let asyncness = f.header.asyncness.print_with_space();
+    let unsafety = f.header.unsafety.print_with_space();
+    let abi = print_abi_with_space(f.header.abi).to_string();
+    let name = it.name.as_ref().unwrap();
+
+    let generics_len = format!("{:#}", f.generics.print(cx)).len();
+    let header_len = "fn ".len()
+        + vis.len()
+        + constness.len()
+        + asyncness.len()
+        + unsafety.len()
+        + abi.len()
+        + name.as_str().len()
+        + generics_len;
+
     w.write_str("<pre class=\"rust fn\">");
     render_attributes_in_pre(w, it, "");
+    w.reserve(header_len);
     write!(
         w,
         "{vis}{constness}{asyncness}{unsafety}{abi}fn \
          {name}{generics}{decl}{notable_traits}{where_clause}</pre>",
-        vis = it.visibility.print_with_space(it.def_id, cx),
-        constness = f.header.constness.print_with_space(),
-        asyncness = f.header.asyncness.print_with_space(),
-        unsafety = f.header.unsafety.print_with_space(),
-        abi = print_abi_with_space(f.header.abi),
-        name = it.name.as_ref().unwrap(),
+        vis = vis,
+        constness = constness,
+        asyncness = asyncness,
+        unsafety = unsafety,
+        abi = abi,
+        name = name,
         generics = f.generics.print(cx),
         where_clause = print_where_clause(&f.generics, cx, 0, true),
         decl = f.decl.full_print(header_len, 0, f.header.asyncness, cx),
@@ -466,6 +482,9 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
     let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::<Vec<_>>();
     let required = t.items.iter().filter(|m| m.is_ty_method()).collect::<Vec<_>>();
     let provided = t.items.iter().filter(|m| m.is_method()).collect::<Vec<_>>();
+    let count_types = types.len();
+    let count_consts = consts.len();
+    let count_methods = required.len() + provided.len();
 
     // Output the trait definition
     wrap_into_docblock(w, |w| {
@@ -496,9 +515,12 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
             let mut toggle = false;
 
             // If there are too many associated types, hide _everything_
-            if should_hide_fields(types.len()) {
+            if should_hide_fields(count_types) {
                 toggle = true;
-                toggle_open(w, "associated items");
+                toggle_open(
+                    w,
+                    format_args!("{} associated items", count_types + count_consts + count_methods),
+                );
             }
             for t in &types {
                 render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait, cx);
@@ -508,9 +530,18 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
             // We also do this if the types + consts is large because otherwise we could
             // render a bunch of types and _then_ a bunch of consts just because both were
             // _just_ under the limit
-            if !toggle && should_hide_fields(types.len() + consts.len()) {
+            if !toggle && should_hide_fields(count_types + count_consts) {
                 toggle = true;
-                toggle_open(w, "associated constants and methods");
+                toggle_open(
+                    w,
+                    format_args!(
+                        "{} associated constant{} and {} method{}",
+                        count_consts,
+                        pluralize(count_consts),
+                        count_methods,
+                        pluralize(count_methods),
+                    ),
+                );
             }
             if !types.is_empty() && !consts.is_empty() {
                 w.write_str("\n");
@@ -519,9 +550,9 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
                 render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait, cx);
                 w.write_str(";\n");
             }
-            if !toggle && should_hide_fields(required.len() + provided.len()) {
+            if !toggle && should_hide_fields(count_methods) {
                 toggle = true;
-                toggle_open(w, "methods");
+                toggle_open(w, format_args!("{} methods", count_methods));
             }
             if !consts.is_empty() && !required.is_empty() {
                 w.write_str("\n");
@@ -586,11 +617,13 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
             write!(w, "<details class=\"rustdoc-toggle\" open><summary>");
         }
         write!(w, "<div id=\"{}\" class=\"method has-srclink\">", id);
+        write!(w, "<div class=\"rightside\">");
+        render_stability_since(w, m, t, cx.tcx());
+        write_srclink(cx, m, w);
+        write!(w, "</div>");
         write!(w, "<h4 class=\"code-header\">");
         render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl, cx);
         w.write_str("</h4>");
-        render_stability_since(w, m, t, cx.tcx());
-        write_srclink(cx, m, w);
         w.write_str("</div>");
         if toggled {
             write!(w, "</summary>");
@@ -652,9 +685,9 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
     }
 
     // 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();
@@ -702,13 +735,15 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
                     it,
                     assoc_link,
                     RenderMode::Normal,
-                    implementor.impl_item.stable_since(cx.tcx()).as_deref(),
-                    implementor.impl_item.const_stable_since(cx.tcx()).as_deref(),
-                    false,
                     None,
-                    true,
-                    false,
                     &[],
+                    ImplRenderingParameters {
+                        show_def_docs: false,
+                        is_on_foreign_type: true,
+                        show_default_items: false,
+                        show_non_assoc_items: true,
+                        toggle_open_by_default: false,
+                    },
                 );
             }
         }
@@ -772,7 +807,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
         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_(),
@@ -798,7 +833,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) {
@@ -819,12 +854,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>",
@@ -836,7 +880,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
@@ -865,7 +909,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
     if fields.peek().is_some() {
         write!(
             w,
-            "<h2 id=\"fields\" class=\"fields small-section-header\">
+            "<h2 id=\"fields\" class=\"fields small-section-header\">\
                    Fields<a href=\"#fields\" class=\"anchor\"></a></h2>"
         );
         for (field, ty) in fields {
@@ -888,7 +932,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);
 }
@@ -909,9 +953,10 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
             w.write_str(" {}");
         } else {
             w.write_str(" {\n");
-            let toggle = should_hide_fields(e.variants.len());
+            let count_variants = e.variants.len();
+            let toggle = should_hide_fields(count_variants);
             if toggle {
-                toggle_open(w, "variants");
+                toggle_open(w, format_args!("{} variants", count_variants));
             }
             for v in &e.variants {
                 w.write_str("    ");
@@ -954,8 +999,8 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
     if !e.variants.is_empty() {
         write!(
             w,
-            "<h2 id=\"variants\" class=\"variants small-section-header\">
-                   Variants{}<a href=\"#variants\" class=\"anchor\"></a></h2>\n",
+            "<h2 id=\"variants\" class=\"variants small-section-header\">\
+                   Variants{}<a href=\"#variants\" class=\"anchor\"></a></h2>",
             document_non_exhaustive_header(it)
         );
         document_non_exhaustive(w, it);
@@ -980,19 +1025,20 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                 }
                 w.write_str(")");
             }
-            w.write_str("</code></div>");
+            w.write_str("</code>");
+            render_stability_since(w, variant, it, cx.tcx());
+            w.write_str("</div>");
             document(w, cx, variant, Some(it));
             document_non_exhaustive(w, variant);
 
             use crate::clean::Variant;
             if let clean::VariantItem(Variant::Struct(ref s)) = *variant.kind {
-                toggle_open(w, "fields");
                 let variant_id = cx.derive_id(format!(
                     "{}.{}.fields",
                     ItemType::Variant,
                     variant.name.as_ref().unwrap()
                 ));
-                write!(w, "<div class=\"autohide sub-variant\" id=\"{id}\">", id = variant_id);
+                write!(w, "<div class=\"sub-variant\" id=\"{id}\">", id = variant_id);
                 write!(
                     w,
                     "<h3>Fields of <b>{name}</b></h3><div>",
@@ -1020,12 +1066,10 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                     }
                 }
                 w.write_str("</div></div>");
-                toggle_close(w);
             }
-            render_stability_since(w, variant, it, cx.tcx());
         }
     }
-    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);
 }
@@ -1077,7 +1121,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) {
@@ -1140,7 +1184,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
         if fields.peek().is_some() {
             write!(
                 w,
-                "<h2 id=\"fields\" class=\"fields small-section-header\">
+                "<h2 id=\"fields\" class=\"fields small-section-header\">\
                        Fields{}<a href=\"#fields\" class=\"anchor\"></a></h2>",
                 document_non_exhaustive_header(it)
             );
@@ -1166,7 +1210,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);
 }
@@ -1197,7 +1241,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) {
@@ -1289,7 +1333,7 @@ fn render_stability_since(
     render_stability_since_raw(
         w,
         item.stable_since(tcx).as_deref(),
-        item.const_stable_since(tcx).as_deref(),
+        item.const_stability(tcx),
         containing_item.stable_since(tcx).as_deref(),
         containing_item.const_stable_since(tcx).as_deref(),
     )
@@ -1311,7 +1355,7 @@ fn render_implementor(
     implementor_dups: &FxHashMap<Symbol, (DefId, bool)>,
     aliases: &[String],
 ) {
-    // If there's already another implementor that has the same abbridged name, use the
+    // If there's already another implementor that has the same abridged name, use the
     // full path, for example in `std::iter::ExactSizeIterator`
     let use_absolute = match implementor.inner_impl().for_ {
         clean::ResolvedPath { ref path, is_generic: false, .. }
@@ -1328,13 +1372,15 @@ fn render_implementor(
         trait_,
         AssocItemLink::Anchor(None),
         RenderMode::Normal,
-        trait_.stable_since(cx.tcx()).as_deref(),
-        trait_.const_stable_since(cx.tcx()).as_deref(),
-        false,
         Some(use_absolute),
-        false,
-        false,
         aliases,
+        ImplRenderingParameters {
+            show_def_docs: false,
+            is_on_foreign_type: false,
+            show_default_items: false,
+            show_non_assoc_items: false,
+            toggle_open_by_default: false,
+        },
     );
 }
 
@@ -1364,7 +1410,7 @@ fn render_union(
         fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count();
     let toggle = should_hide_fields(count_fields);
     if toggle {
-        toggle_open(w, "fields");
+        toggle_open(w, format_args!("{} fields", count_fields));
     }
 
     for field in fields {
@@ -1420,7 +1466,7 @@ fn render_struct(
             let has_visible_fields = count_fields > 0;
             let toggle = should_hide_fields(count_fields);
             if toggle {
-                toggle_open(w, "fields");
+                toggle_open(w, format_args!("{} fields", count_fields));
             }
             for field in fields {
                 if let clean::StructFieldItem(ref ty) = *field.kind {
@@ -1597,3 +1643,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
 
     writeln!(w, "</div>");
 }
+
+fn pluralize(count: usize) -> &'static str {
+    if count > 1 { "s" } else { "" }
+}
index a4188e6b203bb2ff5649cc7af62141b1a9037011..94a902a2d05225cb434b56454759d8b387457d31 100644 (file)
@@ -25,10 +25,16 @@ static FILES_UNVERSIONED: Lazy<FxHashMap<&str, &[u8]>> = Lazy::new(|| {
         "FiraSans-Regular.woff" => static_files::fira_sans::REGULAR,
         "FiraSans-Medium.woff" => static_files::fira_sans::MEDIUM,
         "FiraSans-LICENSE.txt" => static_files::fira_sans::LICENSE,
+        "SourceSerif4-Regular.ttf.woff2" => static_files::source_serif_4::REGULAR2,
+        "SourceSerif4-Bold.ttf.woff2" => static_files::source_serif_4::BOLD2,
+        "SourceSerif4-It.ttf.woff2" => static_files::source_serif_4::ITALIC2,
         "SourceSerif4-Regular.ttf.woff" => static_files::source_serif_4::REGULAR,
         "SourceSerif4-Bold.ttf.woff" => static_files::source_serif_4::BOLD,
         "SourceSerif4-It.ttf.woff" => static_files::source_serif_4::ITALIC,
         "SourceSerif4-LICENSE.md" => static_files::source_serif_4::LICENSE,
+        "SourceCodePro-Regular.ttf.woff2" => static_files::source_code_pro::REGULAR2,
+        "SourceCodePro-Semibold.ttf.woff2" => static_files::source_code_pro::SEMIBOLD2,
+        "SourceCodePro-It.ttf.woff2" => static_files::source_code_pro::ITALIC2,
         "SourceCodePro-Regular.ttf.woff" => static_files::source_code_pro::REGULAR,
         "SourceCodePro-Semibold.ttf.woff" => static_files::source_code_pro::SEMIBOLD,
         "SourceCodePro-It.ttf.woff" => static_files::source_code_pro::ITALIC,
@@ -460,7 +466,14 @@ pub(super) fn write_shared(
                     })
                     .collect::<String>()
             );
-            let v = layout::render(&cx.shared.layout, &page, "", content, &cx.shared.style_files);
+            let v = layout::render(
+                &cx.shared.templates,
+                &cx.shared.layout,
+                &page,
+                "",
+                content,
+                &cx.shared.style_files,
+            );
             cx.shared.fs.write(&dst, v.as_bytes())?;
         }
     }
index 5e2a94fe6845ff3026e12f7462702398ada8b53d..80dd7a7a952f0071fd6501cb29053b6894a7b9fc 100644 (file)
@@ -136,6 +136,7 @@ impl SourceCollector<'_, 'tcx> {
             static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)],
         };
         let v = layout::render(
+            &self.scx.templates,
             &self.scx.layout,
             &page,
             "",
index 16d79032fcc63edacc6b5485564fc4e6db3e80b2..c2629a83f7092f112f3916d63a840be14d9ea759 100644 (file)
@@ -2,7 +2,8 @@ These documentation pages include resources by third parties. This copyright
 file applies only to those resources. The following third party resources are
 included, and carry their own copyright notices and license terms:
 
-* Fira Sans (FiraSans-Regular.woff, FiraSans-Medium.woff):
+* Fira Sans (FiraSans-Regular.woff2, FiraSans-Medium.woff2,
+    FiraSans-Regular.woff, FiraSans-Medium.woff):
 
     Copyright (c) 2014, Mozilla Foundation https://mozilla.org/
     with Reserved Font Name Fira Sans.
@@ -23,8 +24,10 @@ included, and carry their own copyright notices and license terms:
     Copyright (c) Nicolas Gallagher and Jonathan Neal.
     Licensed under the MIT license (see LICENSE-MIT.txt).
 
-* Source Code Pro (SourceCodePro-Regular.ttf.woff,
-    SourceCodePro-Semibold.ttf.woff, SourceCodePro-It.ttf.woff):
+* Source Code Pro (SourceCodePro-Regular.ttf.woff2,
+    SourceCodePro-Semibold.ttf.woff2, SourceCodePro-It.ttf.woff2,
+    SourceCodePro-Regular.ttf.woff, SourceCodePro-Semibold.ttf.woff,
+    SourceCodePro-It.ttf.woff):
 
     Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/),
     with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark
@@ -33,8 +36,9 @@ included, and carry their own copyright notices and license terms:
     Licensed under the SIL Open Font License, Version 1.1.
     See SourceCodePro-LICENSE.txt.
 
-* Source Serif 4 (SourceSerif4-Regular.ttf.woff, SourceSerif4-Bold.ttf.woff,
-    SourceSerif4-It.ttf.woff):
+* Source Serif 4 (SourceSerif4-Regular.ttf.woff2, SourceSerif4-Bold.ttf.woff2,
+    SourceSerif4-It.ttf.woff2, SourceSerif4-Regular.ttf.woff,
+    SourceSerif4-Bold.ttf.woff, SourceSerif4-It.ttf.woff):
 
     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
diff --git a/src/librustdoc/html/static/FiraSans-LICENSE.txt b/src/librustdoc/html/static/FiraSans-LICENSE.txt
deleted file mode 100644 (file)
index d444ea9..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-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-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/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-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-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/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..91243a4
--- /dev/null
@@ -0,0 +1,1905 @@
+/* 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;
+}
+h3.code-header, h4.code-header {
+       font-size: 1em;
+       font-weight: 600;
+       border: none;
+       padding: 0;
+       margin: 0;
+}
+.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, .code-header {
+       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;
+}
+.type-decl pre {
+       overflow-x: auto;
+}
+
+.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;
+       height: 100%;
+       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;
+       font-weight: inherit;
+       padding: 0;
+}
+
+.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;
+       font-weight: inherit;
+       padding: 0;
+}
+
+.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:not(.line-number) {
+       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-header, .trait-impl > .code-header, .invisible > .code-header {
+       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, .in-band > .code-header {
+       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);
+       overflow-x: auto;
+       display: block;
+}
+
+.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-header + .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;;
+}
+
+.item-info .stab {
+       display: table;
+}
+.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 .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, :target > .code-header {
+       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;
+       }
+
+       /* We do NOT hide this element so that alternative device readers still have this information
+          available. */
+       .sidebar-elems {
+               position: fixed;
+               z-index: 1;
+               top: 45px;
+               bottom: 0;
+               width: 246px;
+               /* We move the sidebar to the left by its own width so it doesn't appear. */
+               left: -246px;
+               overflow-y: auto;
+               border-right: 1px solid;
+       }
+
+       .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, .sidebar-elems:focus-within {
+               z-index:  2;
+               left: 0;
+       }
+
+       .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..df386fb
--- /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);
+}
+
+.docblock 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 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 div.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;
+}
+
+.result-name .primitive > i, .result-name .keyword > i {
+       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..c8a5dbd
--- /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 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;
+}
+
+.result-name .primitive > i, .result-name .keyword > i {
+       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..bc18a72
--- /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 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;
+}
+
+.result-name .primitive > i, .result-name .keyword > i {
+       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/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..869aff5
--- /dev/null
@@ -0,0 +1,1029 @@
+// 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 currentNbImpls = implementors.getElementsByClassName("impl").length;
+        var traitName = document.querySelector("h1.fqn > .in-band > .trait").textContent;
+        var baseIdName = "impl-" + traitName + "-";
+        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("h3");
+                code.innerHTML = struct.text;
+                addClass(code, "code-header");
+                addClass(code, "in-band");
+
+                onEachLazy(code.getElementsByTagName("a"), function(elem) {
+                    var href = elem.getAttribute("href");
+
+                    if (href && href.indexOf("http") !== 0) {
+                        elem.setAttribute("href", window.rootPath + href);
+                    }
+                });
+
+                var currentId = baseIdName + currentNbImpls;
+                var anchor = document.createElement("a");
+                anchor.href = "#" + currentId;
+                addClass(anchor, "anchor");
+
+                var display = document.createElement("div");
+                display.id = currentId;
+                addClass(display, "impl");
+                display.appendChild(anchor);
+                display.appendChild(code);
+                list.appendChild(display);
+                currentNbImpls += 1;
+            }
+        }
+    };
+    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..78ed17e
--- /dev/null
@@ -0,0 +1,221 @@
+// 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) {
+        // See the comment for `default_settings.into_iter()` etc. in
+        // `Options::from_matches` in `librustdoc/config.rs`.
+        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 fe1ce2e..0000000
+++ /dev/null
@@ -1,1025 +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("h3");
-                code.innerHTML = struct.text;
-                addClass(code, "code-header");
-                addClass(code, "in-band");
-
-                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 hideImplementors = getSettingValue("auto-collapse-implementors") !== "false";
-        var hideImplementations = getSettingValue("auto-hide-trait-implementations") !== "false";
-        var hideLargeItemContents = getSettingValue("auto-hide-large-items") !== "false";
-
-        function openImplementors(id) {
-            var list = document.getElementById(id);
-            if (list !== null) {
-                onEachLazy(list.getElementsByClassName("implementors-toggle"), function(e) {
-                    e.open = true;
-                });
-            }
-        }
-
-        if (!hideImplementations) {
-            openImplementors("trait-implementations-list");
-            openImplementors("blanket-implementations-list");
-        }
-
-        if (!hideImplementors) {
-            openImplementors("implementors-list");
-        }
-
-        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 0e04262..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/* ignore-tidy-linelength */
-/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}
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 f801ef0..0000000
+++ /dev/null
@@ -1,1854 +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.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.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.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.woff") format('woff');
-       font-display: swap;
-}
-@font-face {
-       font-family: 'Source Code Pro';
-       font-style: italic;
-       font-weight: 400;
-       src: 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.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;
-}
-#main > h2, #main > h3, #main > h4 {
-       border-bottom: 1px solid;
-}
-h3.code-header, h4.code-header {
-       font-size: 1em;
-       font-weight: 600;
-       border: none;
-       padding: 0;
-       margin: 0;
-}
-.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,
-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, .code-header {
-       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;
-       font-weight: inherit;
-       padding: 0;
-}
-
-.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;
-       font-weight: inherit;
-       padding: 0;
-}
-
-.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-header, .trait-impl > .code-header, .invisible > .code-header {
-       max-width: calc(100% - 41px);
-       display: block;
-       flex-grow: 1;
-}
-
-.invisible {
-       width: 100%;
-       display: inline-block;
-}
-
-.content .in-band {
-       flex-grow: 1;
-       margin: 0px;
-       padding: 0px;
-}
-
-.in-band > code, .in-band > .code-header {
-       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;
-       margin-top: -6px;
-}
-
-.sub-variant > div > .item-info {
-       margin-top: initial;
-}
-
-.content .item-info::before {
-       content: '⬑';
-       font-size: 25px;
-       position: absolute;
-       top: 0px;
-       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: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-header + .srclink {
-       position: absolute;
-       top: 0;
-       right: 0;
-       font-size: 17px;
-       font-weight: normal;
-}
-
-.block a.current.crate { font-weight: 500; }
-
-.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 {
-       display: table;
-       border-width: 1px;
-       border-style: solid;
-       padding: 3px;
-       margin-bottom: 5px;
-       font-size: 90%;
-}
-.stab p {
-       display: inline;
-}
-
-.stab summary {
-       display: list-item;
-}
-
-.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-right: .3em;
-       padding: 2px;
-       vertical-align: text-bottom;
-}
-
-.module-item.unstable,
-.import-item.unstable {
-       opacity: 0.65;
-}
-
-.since {
-       font-weight: normal;
-       font-size: initial;
-       position: absolute;
-       right: 0;
-       top: 0;
-}
-
-.impl-items .since, .impl .since, .methods .since {
-       flex-grow: 0;
-       padding-left: 12px;
-       padding-right: 6px;
-       position: initial;
-}
-
-.impl-items .srclink, .impl .srclink, .methods .srclink {
-       flex-grow: 0;
-       /* Override header settings otherwise it's too bold */
-       font-size: 17px;
-       font-weight: normal;
-}
-
-.impl-items code, .impl code, .methods code {
-       flex-grow: 1;
-}
-
-.has-srclink {
-       display: flex;
-       flex-basis: 100%;
-       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 {
-       display: table-cell;
-       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, :target > .code-header {
-       opacity: 1;
-}
-
-.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;
-       }
-
-       /* We do NOT hide this element so that alternative device readers still have this information
-          available. */
-       .sidebar-elems {
-               position: fixed;
-               z-index: 1;
-               top: 45px;
-               bottom: 0;
-               width: 246px;
-               /* We move the sidebar to the left by its own width so it doesn't appear. */
-               left: -246px;
-               overflow-y: auto;
-               border-right: 1px solid;
-       }
-
-       .sidebar > .block.version {
-               border-bottom: none;
-               margin-top: 12px;
-               margin-bottom: 0;
-       }
-
-       nav.sub {
-               width: calc(100% - 32px);
-               float: right;
-       }
-
-       .content {
-               margin-left: 0px;
-       }
-
-       #main, #search {
-               margin-top: 45px;
-               padding: 0;
-       }
-
-       #search {
-               margin-left: 0;
-       }
-
-       .content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant,
-       .impl-items > .associatedtype {
-               display: flex;
-       }
-
-       .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 {
-               left: 0;
-       }
-
-       .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;
-       }
-       .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 {
-               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 35be246..0000000
+++ /dev/null
@@ -1,1512 +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 http://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 = 1;
-    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) {
-                        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 >= val.generics.length) {
-                            var elems = Object.create(null);
-                            len = obj[GENERICS_DATA].length;
-                            for (x = 0; x < len; ++x) {
-                                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;
-                            }
-                        } else {
-                            return false;
-                        }
-                    }
-                    return true;
-                }
-                // 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 {
-                    return 0;
-                }
-            }
-            // Names didn't match so let's check if one of the generic types could.
-            if (literalSearch) {
-                 if (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 (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) {
-        var search = searchState.outputElement();
-        if (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;
-        }
-
-        var queries = query.raw.split(",");
-        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));
-    }
-
-    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);
-                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 1fc648d..0000000
+++ /dev/null
@@ -1,603 +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;
-}
-
-.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);
-       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 3105a99..0000000
+++ /dev/null
@@ -1,475 +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;
-}
-
-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 10fde92..0000000
+++ /dev/null
@@ -1,466 +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; }
-
-pre.rust .comment { color: #8E908C; }
-pre.rust .doccomment { color: #4D4D4C; }
-
-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 .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;
-}
-
-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 ca7e5ef8150809a95cf9b0d169c07b6f4f727e38..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.
@@ -58,87 +58,114 @@ crate static LICENSE_APACHE: &[u8] = include_bytes!("static/LICENSE-APACHE.txt")
 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");
 
 /// The built-in themes given to every documentation site.
 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/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/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/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/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/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/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");
 }
diff --git a/src/librustdoc/html/templates/STYLE.md b/src/librustdoc/html/templates/STYLE.md
new file mode 100644 (file)
index 0000000..fff65e3
--- /dev/null
@@ -0,0 +1,37 @@
+# Style for Templates
+
+This directory has templates in the [Tera templating language](teradoc), which is very
+similar to [Jinja2](jinjadoc) and [Django](djangodoc) templates, and also to [Askama](askamadoc).
+
+[teradoc]: https://tera.netlify.app/docs/#templates
+[jinjadoc]: https://jinja.palletsprojects.com/en/3.0.x/templates/
+[djangodoc]: https://docs.djangoproject.com/en/3.2/topics/templates/
+[askamadoc]: https://docs.rs/askama/0.10.5/askama/
+
+We want our rendered output to have as little unnecessary whitespace as
+possible, so that pages load quickly. To achieve that we use Tera's
+[whitespace control] features. At the end of most lines, we put an empty comment
+tag with the whitespace control characters: `{#- -#}`. This causes all
+whitespace between the end of the line and the beginning of the next, including
+indentation, to be omitted on render. Sometimes we want to preserve a single
+space. In those cases we put the space at the end of the line, followed by
+`{# -#}`, which is a directive to remove following whitespace but not preceding.
+We also use the whitespace control characters in most instances of tags with
+control flow, for example `{%- if foo -%}`.
+
+[whitespace control]: https://tera.netlify.app/docs/#whitespace-control
+
+We want our templates to be readable, so we use indentation and newlines
+liberally. We indent by four spaces after opening an HTML tag _or_ a Tera
+tag. In most cases an HTML tag should be followed by a newline, but if the
+tag has simple contents and fits with its close tag on a single line, the
+contents don't necessarily need a new line.
+
+Tera templates support quite sophisticated control flow. To keep our templates
+simple and understandable, we use only a subset: `if` and `for`. In particular
+we avoid [assignments in the template logic](assignments) and [Tera
+macros](macros). This also may make things easier if we switch to a different
+Jinja-style template system, like Askama, in the future.
+
+[assignments]: https://tera.netlify.app/docs/#assignments
+[macros]: https://tera.netlify.app/docs/#macros
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
new file mode 100644 (file)
index 0000000..9b1bef5
--- /dev/null
@@ -0,0 +1,119 @@
+<!DOCTYPE html> {#- -#}
+<html lang="en"> {#- -#}
+<head> {#- -#}
+    <meta charset="utf-8"> {#- -#}
+    <meta name="viewport" content="width=device-width, initial-scale=1.0"> {#- -#}
+    <meta name="generator" content="rustdoc"> {#- -#}
+    <meta name="description" content="{{page.description}}"> {#- -#}
+    <meta name="keywords" content="{{page.keywords}}"> {#- -#}
+    <title>{{page.title}}</title> {#- -#}
+    <link rel="stylesheet" type="text/css" {# -#}
+          href="{{static_root_path | safe}}normalize{{page.resource_suffix}}.css"> {#- -#}
+    <link rel="stylesheet" type="text/css" {# -#}
+          href="{{static_root_path | safe}}rustdoc{{page.resource_suffix}}.css" {# -#}
+          id="mainThemeStyle"> {#- -#}
+    {{- style_files | safe -}}
+    <script id="default-settings" {# -#}
+      {% for k, v in layout.default_settings %}
+        data-{{k}}="{{v}}"
+      {%- endfor -%}
+    ></script> {#- -#}
+    <script src="{{static_root_path | safe}}storage{{page.resource_suffix}}.js"></script> {#- -#}
+    <script src="{{page.root_path | safe}}crates{{page.resource_suffix}}.js"></script> {#- -#}
+    <noscript> {#- -#}
+        <link rel="stylesheet" {# -#}
+           href="{{static_root_path | safe}}noscript{{page.resource_suffix}}.css"> {#- -#}
+    </noscript> {#- -#}
+    {%- if layout.css_file_extension -%}
+        <link rel="stylesheet" type="text/css" {# -#}
+            href="{{static_root_path | safe}}theme{{page.resource_suffix}}.css"> {#- -#}
+    {%- endif -%}
+    {%- if layout.favicon -%}
+        <link rel="shortcut icon" href="{{layout.favicon}}"> {#- -#}
+    {%- else -%}
+        <link rel="icon" type="image/svg+xml" {# -#}
+            href="{{static_root_path | safe}}favicon{{page.resource_suffix}}.svg"> {#- -#}
+        <link rel="alternate icon" type="image/png" {# -#}
+            href="{{static_root_path | safe}}favicon-16x16{{page.resource_suffix}}.png"> {#- -#}
+        <link rel="alternate icon" type="image/png" {# -#}
+            href="{{static_root_path | safe}}favicon-32x32{{page.resource_suffix}}.png"> {#- -#}
+    {%- endif -%}
+    {{- layout.external_html.in_header | safe -}}
+    <style type="text/css"> {#- -#}
+    #crate-search{ {#- -#}
+        background-image:url("{{static_root_path | safe}}down-arrow{{page.resource_suffix}}.svg"); {#- -#}
+    } {#- -#}
+    </style> {#- -#}
+</head> {#- -#}
+<body class="rustdoc {{page.css_class}}"> {#- -#}
+    <!--[if lte IE 11]> {#- -#}
+    <div class="warning"> {#- -#}
+        This old browser is unsupported and will most likely display funky things. {#- -#}
+    </div> {#- -#}
+    <![endif]--> {#- -#}
+    {{- layout.external_html.before_content | safe -}}
+    <nav class="sidebar"> {#- -#}
+        <div class="sidebar-menu" role="button">&#9776;</div> {#- -#}
+        <a href='{{page.root_path | safe}}{{krate_with_trailing_slash | safe}}index.html'> {#- -#}
+            <div class='logo-container rust-logo'> {#- -#}
+            <img src='
+                {%- if layout.logo -%}
+                {{layout.logo}}
+                {%- else -%}
+                {{static_root_path | safe}}rust-logo{{page.resource_suffix}}.png
+                {%- endif -%}
+                ' alt='logo'> {#- -#}
+            </div> {#- -#}
+        </a> {#- -#}
+        {{- sidebar | safe -}}
+    </nav> {#- -#}
+    <div class="theme-picker"> {#- -#}
+        <button id="theme-picker" aria-label="Pick another theme!" aria-haspopup="menu" title="themes"> {#- -#}
+            <img width="18" height="18" alt="Pick another theme!" {# -#}
+             src="{{static_root_path | safe}}brush{{page.resource_suffix}}.svg"> {#- -#}
+        </button> {#- -#}
+        <div id="theme-choices" role="menu"></div> {#- -#}
+    </div> {#- -#}
+    <nav class="sub"> {#- -#}
+        <form class="search-form"> {#- -#}
+            <div class="search-container"> {#- -#}
+                <div>{%- if layout.generate_search_filter -%}
+                    <select id="crate-search"> {#- -#}
+                        <option value="All crates">All crates</option> {#- -#}
+                    </select> {#- -#}
+                    {%- endif -%}
+                    <input {# -#}
+                        class="search-input"{# -#}
+                        name="search" {# -#}
+                        disabled {# -#}
+                        autocomplete="off" {# -#}
+                        spellcheck="false" {# -#}
+                        placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {# -#}
+                        type="search"> {#- -#}
+                </div> {#- -#}
+                <button type="button" id="help-button" title="help">?</button> {#- -#}
+                <a id="settings-menu" href="{{page.root_path | safe}}settings.html" title="settings"> {#- -#}
+                    <img width="18" height="18" alt="Change settings" {# -#}
+                         src="{{static_root_path | safe}}wheel{{page.resource_suffix}}.svg"> {#- -#}
+                </a> {#- -#}
+            </div> {#- -#}
+        </form> {#- -#}
+    </nav> {#- -#}
+    <section id="main" class="content">{{- content | safe -}}</section> {#- -#}
+    <section id="search" class="content hidden"></section> {#- -#}
+    {{- layout.external_html.after_content | safe -}}
+    <div id="rustdoc-vars" {# -#}
+         data-root-path="{{page.root_path | safe}}" {# -#}
+         data-current-crate="{{layout.krate}}" {# -#}
+         data-search-index-js="{{page.root_path | safe}}search-index{{page.resource_suffix}}.js" {# -#}
+         data-search-js="{{static_root_path | safe}}search{{page.resource_suffix}}.js"> {#- -#}
+    </div>
+    <script src="{{static_root_path | safe}}main{{page.resource_suffix}}.js"></script> {#- -#}
+    {%- for script in page.static_extra_scripts -%}
+    <script src="{{static_root_path | safe}}{{script}}.js"></script> {#- -#}
+    {% endfor %}
+    {%- for script in page.extra_scripts -%}
+    <script src="{{page.root_path | safe}}{{script}}.js"></script> {#- -#}
+    {% endfor %}
+</body> {#- -#}
+</html> {#- -#}
index 7086dd8c4d25832c2ceee26ff955f727bf6c9fb9..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 rustc_span::Pos;
 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 @@ impl JsonRenderer<'_> {
             .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 @@ impl JsonRenderer<'_> {
             _ => 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 @@ impl JsonRenderer<'_> {
             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 @@ impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind {
     }
 }
 
-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())),
     }
 }
 
@@ -328,9 +341,10 @@ impl FromWithTcx<clean::WherePredicate> for WherePredicate {
     fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self {
         use clean::WherePredicate::*;
         match predicate {
-            BoundPredicate { ty, bounds } => WherePredicate::BoundPredicate {
+            BoundPredicate { ty, bounds, .. } => WherePredicate::BoundPredicate {
                 ty: ty.into_tcx(tcx),
                 bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
+                // FIXME: add `bound_params` to rustdoc-json-params?
             },
             RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate {
                 lifetime: lifetime.0.to_string(),
@@ -372,14 +386,35 @@ impl FromWithTcx<clean::Type> for Type {
     fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
         use clean::Type::*;
         match ty {
-            ResolvedPath { path, param_names, did, is_generic: _ } => Type::ResolvedPath {
+            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: param_names
-                    .map(|v| v.into_iter().map(|x| x.into_tcx(tcx)).collect())
-                    .unwrap_or_default(),
+                param_names: Vec::new(),
             },
+            DynTrait(mut bounds, lt) => {
+                let (path, id) = match bounds.remove(0).trait_ {
+                    ResolvedPath { path, did, .. } => (path, did),
+                    _ => unreachable!(),
+                };
+
+                Type::ResolvedPath {
+                    name: path.whole_name(),
+                    id: from_item_id(id.into()),
+                    args: path
+                        .segments
+                        .last()
+                        .map(|args| Box::new(args.clone().args.into_tcx(tcx))),
+                    param_names: bounds
+                        .into_iter()
+                        .map(|t| {
+                            clean::GenericBound::TraitBound(t, rustc_hir::TraitBoundModifier::None)
+                        })
+                        .chain(lt.into_iter().map(|lt| clean::GenericBound::Outlives(lt)))
+                        .map(|bound| bound.into_tcx(tcx))
+                        .collect(),
+                }
+            }
             Generic(s) => Type::Generic(s.to_string()),
             Primitive(p) => Type::Primitive(p.as_sym().to_string()),
             BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
@@ -546,13 +581,13 @@ impl FromWithTcx<clean::Import> for Import {
             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,
             },
         }
@@ -646,5 +681,5 @@ impl FromWithTcx<ItemType> for ItemKind {
 }
 
 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::error::Error;
 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 @@ impl JsonRenderer<'tcx> {
                     .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 @@ impl JsonRenderer<'tcx> {
                         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 @@ impl JsonRenderer<'tcx> {
                     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 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
         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 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
                 .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..fa755777584f3cdacb58abe4cc4aa6722ce4d7e9 100644 (file)
@@ -53,11 +53,11 @@ extern crate rustc_parse;
 extern crate rustc_passes;
 extern crate rustc_resolve;
 extern crate rustc_session;
-extern crate rustc_span as rustc_span;
+extern crate rustc_span;
 extern crate rustc_target;
 extern crate rustc_trait_selection;
 extern crate rustc_typeck;
-extern crate test as testing;
+extern crate test;
 
 #[cfg(feature = "jemalloc")]
 extern crate tikv_jemalloc_sys;
@@ -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")),
@@ -511,10 +511,10 @@ fn opts() -> Vec<RustcOptGroup> {
                 "LEVEL",
             )
         }),
-        unstable("force-warns", |o| {
+        unstable("force-warn", |o| {
             o.optopt(
                 "",
-                "force-warns",
+                "force-warn",
                 "Lints that will warn even if allowed somewhere else",
                 "LINTS",
             )
@@ -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,14 @@ 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")
+        }),
+        unstable("nocapture", |o| {
+            o.optflag("", "nocapture", "Don't capture stdout and stderr of tests")
         }),
     ]
 }
index 376c83b1a6ea8836e492b202c7bada77e79d4d46..49d8d7fb7fb8e9eb3c50a90623c399449a6b3876 100644 (file)
@@ -193,7 +193,7 @@ crate fn register_lints(_sess: &Session, lint_store: &mut LintStore) {
     );
     for lint in &*RUSTDOC_LINTS {
         let name = lint.name_lower();
-        lint_store.register_alias(&name.replace("rustdoc::", ""), &name);
+        lint_store.register_renamed(&name.replace("rustdoc::", ""), &name);
     }
     lint_store
         .register_renamed("intra_doc_link_resolution_failure", "rustdoc::broken_intra_doc_links");
index 963f2cf71f389761c9bd8f4f367c13df5a7c737f..80af2a7aaf5c8ab820ef593534f023a9dc22d073 100644 (file)
@@ -4,6 +4,7 @@ use std::path::Path;
 
 use rustc_span::edition::Edition;
 use rustc_span::source_map::DUMMY_SP;
+use rustc_span::Symbol;
 
 use crate::config::{Options, RenderOptions};
 use crate::doctest::{Collector, TestOptions};
@@ -114,14 +115,14 @@ crate fn render<P: AsRef<Path>>(
 }
 
 /// Runs any tests/code examples in the markdown file `input`.
-crate fn test(mut options: Options) -> Result<(), String> {
+crate fn test(options: Options) -> Result<(), String> {
     let input_str = read_to_string(&options.input)
         .map_err(|err| format!("{}: {}", options.input.display(), err))?;
     let mut opts = TestOptions::default();
     opts.no_crate_inject = true;
     opts.display_warnings = options.display_warnings;
     let mut collector = Collector::new(
-        options.input.display().to_string(),
+        Symbol::intern(&options.input.display().to_string()),
         options.clone(),
         true,
         opts,
@@ -134,11 +135,11 @@ crate fn test(mut options: Options) -> Result<(), String> {
 
     find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores, None);
 
-    options.test_args.insert(0, "rustdoctest".to_string());
-    testing::test_main(
-        &options.test_args,
+    crate::doctest::run_tests(
+        options.test_args,
+        options.nocapture,
+        options.display_warnings,
         collector.tests,
-        Some(testing::Options::new().display_output(options.display_warnings)),
     );
     Ok(())
 }
index 26a22f5b304945ccb2d426538c43b855821ad799..92e678e4c024ba9f3f67b8f2f3bba8aa35715570 100644 (file)
@@ -213,13 +213,13 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
 
                 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 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
             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 @@ impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> {
             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 0008155aa0411c6f4d37316de948b6791bc340e5..21bd3ebd21bc838d86cd89f2c6ef0d52fbc87a97 100644 (file)
@@ -541,6 +541,44 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             })
     }
 
+    /// Convert a DefId to a Res, where possible.
+    ///
+    /// This is used for resolving type aliases.
+    fn def_id_to_res(&self, ty_id: DefId) -> Option<Res> {
+        use PrimitiveType::*;
+        Some(match *self.cx.tcx.type_of(ty_id).kind() {
+            ty::Bool => Res::Primitive(Bool),
+            ty::Char => Res::Primitive(Char),
+            ty::Int(ity) => Res::Primitive(ity.into()),
+            ty::Uint(uty) => Res::Primitive(uty.into()),
+            ty::Float(fty) => Res::Primitive(fty.into()),
+            ty::Str => Res::Primitive(Str),
+            ty::Tuple(ref tys) if tys.is_empty() => Res::Primitive(Unit),
+            ty::Tuple(_) => Res::Primitive(Tuple),
+            ty::Array(..) => Res::Primitive(Array),
+            ty::Slice(_) => Res::Primitive(Slice),
+            ty::RawPtr(_) => Res::Primitive(RawPointer),
+            ty::Ref(..) => Res::Primitive(Reference),
+            ty::FnDef(..) => panic!("type alias to a function definition"),
+            ty::FnPtr(_) => Res::Primitive(Fn),
+            ty::Never => Res::Primitive(Never),
+            ty::Adt(&ty::AdtDef { did, .. }, _) | ty::Foreign(did) => {
+                Res::Def(self.cx.tcx.def_kind(did), did)
+            }
+            ty::Projection(_)
+            | ty::Closure(..)
+            | ty::Generator(..)
+            | ty::GeneratorWitness(_)
+            | ty::Opaque(..)
+            | ty::Dynamic(..)
+            | ty::Param(_)
+            | ty::Bound(..)
+            | ty::Placeholder(_)
+            | ty::Infer(_)
+            | ty::Error(_) => return None,
+        })
+    }
+
     /// Returns:
     /// - None if no associated item was found
     /// - Some((_, _, Some(_))) if an item was found and should go through a side channel
@@ -556,12 +594,15 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
 
         match root_res {
             Res::Primitive(prim) => self.resolve_primitive_associated_item(prim, ns, item_name),
+            Res::Def(DefKind::TyAlias, did) => {
+                // Resolve the link on the type the alias points to.
+                // FIXME: if the associated item is defined directly on the type alias,
+                // it will show up on its documentation page, we should link there instead.
+                let res = self.def_id_to_res(did)?;
+                self.resolve_associated_item(res, item_name, ns, module_id)
+            }
             Res::Def(
-                DefKind::Struct
-                | DefKind::Union
-                | DefKind::Enum
-                | DefKind::TyAlias
-                | DefKind::ForeignTy,
+                DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::ForeignTy,
                 did,
             ) => {
                 debug!("looking for associated item named {} for item {:?}", item_name, did);
@@ -789,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
@@ -856,7 +896,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
         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.
@@ -883,7 +923,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
 
         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);
@@ -948,9 +988,9 @@ fn preprocess_link<'a>(
     }
 
     // Parse and strip the disambiguator from the link, if present.
-    let (path_str, disambiguator) = match Disambiguator::from_str(&link) {
-        Ok(Some((d, path))) => (path.trim(), Some(d)),
-        Ok(None) => (link.trim(), None),
+    let (disambiguator, path_str, link_text) = match Disambiguator::from_str(&link) {
+        Ok(Some((d, path, link_text))) => (Some(d), path.trim(), link_text.trim()),
+        Ok(None) => (None, link.trim(), link.trim()),
         Err((err_msg, relative_range)) => {
             // Only report error if we would not have ignored this link. See issue #83859.
             if !should_ignore_link_with_disambiguators(link) {
@@ -968,11 +1008,6 @@ fn preprocess_link<'a>(
         return None;
     }
 
-    // We stripped `()` and `!` when parsing the disambiguator.
-    // Add them back to be displayed, but not prefix disambiguators.
-    let link_text =
-        disambiguator.map(|d| d.display_for(path_str)).unwrap_or_else(|| path_str.to_owned());
-
     // Strip generics from the path.
     let path_str = if path_str.contains(['<', '>'].as_slice()) {
         match strip_generics_from_path(&path_str) {
@@ -1002,7 +1037,7 @@ fn preprocess_link<'a>(
         path_str,
         disambiguator,
         extra_fragment: extra_fragment.map(String::from),
-        link_text,
+        link_text: link_text.to_owned(),
     }))
 }
 
@@ -1199,10 +1234,10 @@ impl LinkCollector<'_, '_> {
             // 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);
@@ -1343,7 +1378,7 @@ impl LinkCollector<'_, '_> {
                             let other_ns = if expected_ns == ValueNS { TypeNS } else { ValueNS };
                             // FIXME: really it should be `resolution_failure` that does this, not `resolve_with_disambiguator`
                             // See https://github.com/rust-lang/rust/pull/76955#discussion_r493953382 for a good approach
-                            for &new_ns in &[other_ns, MacroNS] {
+                            for new_ns in [other_ns, MacroNS] {
                                 if let Some(res) =
                                     self.check_full_res(new_ns, path_str, base_node, extra_fragment)
                                 {
@@ -1441,7 +1476,7 @@ impl LinkCollector<'_, '_> {
                     Ok(res) => Some((res, extra_fragment.clone())),
                     Err(mut kind) => {
                         // `resolve_macro` only looks in the macro namespace. Try to give a better error if possible.
-                        for &ns in &[TypeNS, ValueNS] {
+                        for ns in [TypeNS, ValueNS] {
                             if let Some(res) =
                                 self.check_full_res(ns, path_str, base_node, extra_fragment)
                             {
@@ -1510,24 +1545,12 @@ enum Disambiguator {
 }
 
 impl Disambiguator {
-    /// The text that should be displayed when the path is rendered as HTML.
-    ///
-    /// NOTE: `path` is not the original link given by the user, but a name suitable for passing to `resolve`.
-    fn display_for(&self, path: &str) -> String {
-        match self {
-            // FIXME: this will have different output if the user had `m!()` originally.
-            Self::Kind(DefKind::Macro(MacroKind::Bang)) => format!("{}!", path),
-            Self::Kind(DefKind::Fn) => format!("{}()", path),
-            _ => path.to_owned(),
-        }
-    }
-
-    /// Given a link, parse and return `(disambiguator, path_str)`.
+    /// Given a link, parse and return `(disambiguator, path_str, link_text)`.
     ///
     /// This returns `Ok(Some(...))` if a disambiguator was found,
     /// `Ok(None)` if no disambiguator was found, or `Err(...)`
     /// if there was a problem with the disambiguator.
-    fn from_str(link: &str) -> Result<Option<(Self, &str)>, (String, Range<usize>)> {
+    fn from_str(link: &str) -> Result<Option<(Self, &str, &str)>, (String, Range<usize>)> {
         use Disambiguator::{Kind, Namespace as NS, Primitive};
 
         if let Some(idx) = link.find('@') {
@@ -1548,18 +1571,20 @@ impl Disambiguator {
                 "prim" | "primitive" => Primitive,
                 _ => return Err((format!("unknown disambiguator `{}`", prefix), 0..idx)),
             };
-            Ok(Some((d, &rest[1..])))
+            Ok(Some((d, &rest[1..], &rest[1..])))
         } else {
             let suffixes = [
                 ("!()", DefKind::Macro(MacroKind::Bang)),
+                ("!{}", DefKind::Macro(MacroKind::Bang)),
+                ("![]", DefKind::Macro(MacroKind::Bang)),
                 ("()", DefKind::Fn),
                 ("!", DefKind::Macro(MacroKind::Bang)),
             ];
-            for &(suffix, kind) in &suffixes {
-                if let Some(link) = link.strip_suffix(suffix) {
+            for (suffix, kind) in suffixes {
+                if let Some(path_str) = link.strip_suffix(suffix) {
                     // Avoid turning `!` or `()` into an empty string
-                    if !link.is_empty() {
-                        return Ok(Some((Kind(kind), link)));
+                    if !path_str.is_empty() {
+                        return Ok(Some((Kind(kind), path_str, link)));
                     }
                 }
             }
@@ -1585,6 +1610,8 @@ impl Disambiguator {
             return Suggestion::Macro;
         } else if kind == DefKind::Fn || kind == DefKind::AssocFn {
             return Suggestion::Function;
+        } else if kind == DefKind::Field {
+            return Suggestion::RemoveDisambiguator;
         }
 
         let prefix = match kind {
@@ -1649,6 +1676,8 @@ enum Suggestion {
     Function,
     /// `m!`
     Macro,
+    /// `foo` without any disambiguator
+    RemoveDisambiguator,
 }
 
 impl Suggestion {
@@ -1657,6 +1686,7 @@ impl Suggestion {
             Self::Prefix(x) => format!("prefix with `{}@`", x).into(),
             Self::Function => "add parentheses".into(),
             Self::Macro => "add an exclamation mark".into(),
+            Self::RemoveDisambiguator => "remove the disambiguator".into(),
         }
     }
 
@@ -1666,6 +1696,7 @@ impl Suggestion {
             Self::Prefix(prefix) => format!("{}@{}", prefix, path_str),
             Self::Function => format!("{}()", path_str),
             Self::Macro => format!("{}!", path_str),
+            Self::RemoveDisambiguator => path_str.into(),
         }
     }
 }
@@ -1795,7 +1826,7 @@ fn resolution_failure(
                             break;
                         };
                         name = start;
-                        for &ns in &[TypeNS, ValueNS, MacroNS] {
+                        for ns in [TypeNS, ValueNS, MacroNS] {
                             if let Some(res) =
                                 collector.check_full_res(ns, &start, module_id.into(), &None)
                             {
index 6d7c45f6eeacbb0bb944bd1f9acfe0e8fd25dcec..91c495a2bbc069d95cb1c898657bcc3dcdfd7cb1 100644 (file)
@@ -29,7 +29,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
 
     let mut new_items = Vec::new();
 
-    for &cnum in cx.tcx.crates().iter() {
+    for &cnum in cx.tcx.crates(()).iter() {
         for &(did, _) in cx.tcx.all_trait_implementations(cnum).iter() {
             cx.tcx.sess.prof.generic_activity("build_extern_trait_impl").run(|| {
                 inline::build_impl(cx, None, did, None, &mut new_items);
@@ -85,7 +85,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
         }
     });
 
-    // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations`
+    // `tcx.crates(())` doesn't include the local crate, and `tcx.all_trait_implementations`
     // doesn't work with it anyway, so pull them from the HIR map instead
     let mut extra_attrs = Vec::new();
     for &trait_did in cx.tcx.all_traits(()).iter() {
@@ -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 @@ impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> {
 
 #[derive(Default)]
 struct ItemCollector {
-    items: FxHashSet<FakeDefId>,
+    items: FxHashSet<ItemId>,
 }
 
 impl ItemCollector {
@@ -168,7 +173,7 @@ impl DocFolder for ItemCollector {
 
 struct BadImplStripper {
     prims: FxHashSet<PrimitiveType>,
-    items: FxHashSet<FakeDefId>,
+    items: FxHashSet<ItemId>,
 }
 
 impl BadImplStripper {
@@ -185,7 +190,7 @@ impl BadImplStripper {
         }
     }
 
-    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 @@ impl crate::doctest::Tester for Tests {
 }
 
 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 @@ crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> boo
     {
         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 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
                 |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 rustc_span::symbol::sym;
 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 @@ crate const STRIP_HIDDEN: Pass = Pass {
 
 /// 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 @@ crate fn strip_hidden(krate: clean::Crate, _: &mut DocContext<'_>) -> clean::Cra
 }
 
 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 const STRIP_PRIVATE: Pass = Pass {
 /// 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_hir::def_id::DefId;
 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 @@ impl<'a> DocFolder for Stripper<'a> {
             | 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 @@ impl<'a> DocFolder for Stripper<'a> {
 
 /// 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());
index 2af238ff6a35814510b3713d37990d18d31ec49a..53a437569b8f1f8c6966995a854b39b63e3261bf 100644 (file)
 # stable release's version number. `date` is the date where the release we're
 # bootstrapping off was released.
 
-date: 2021-06-17
-rustc: 1.53.0
+date: 2021-07-29
+rustc: 1.54.0
 
 # We use a nightly rustfmt to format the source because it solves some
 # bootstrapping issues with use of new syntax in this repo. If you're looking at
 # the beta/stable branch, this key should be omitted, as we don't want to depend
 # on rustfmt from nightly there.
-# rustfmt: nightly-2021-03-25
+#rustfmt: nightly-2021-03-25
 
 # When making a stable release the process currently looks like:
 #
index 60cfebdd99290bb51965cfae44aa92731f41359d..9ec7ba83c4278b263b4e57add025815a0780d673 100644 (file)
@@ -2,8 +2,9 @@
 // revisions: mips32 mips64
 // assembly-output: emit-asm
 //[mips32] compile-flags: --target mips-unknown-linux-gnu
+//[mips32] needs-llvm-components: mips
 //[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64
-// needs-llvm-components: mips
+//[mips64] needs-llvm-components: mips
 
 #![feature(no_core, lang_items, rustc_attrs, repr_simd)]
 #![crate_type = "rlib"]
index 742e4ddaed6c96d2629c9dfb00e297440b48a47a..1e263649e860a335d9291e76773e5c18db81f366 100644 (file)
@@ -2,8 +2,9 @@
 // revisions: powerpc powerpc64
 // assembly-output: emit-asm
 //[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
+//[powerpc] needs-llvm-components: powerpc
 //[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
-// needs-llvm-components: powerpc
+//[powerpc64] needs-llvm-components: powerpc
 
 #![feature(no_core, lang_items, rustc_attrs, repr_simd)]
 #![crate_type = "rlib"]
index 1ba73fcac9d3c5417387906ef9f3f185b4a503cd..e62a6197b9a5e319adc698b4ea29c465afbee48c 100644 (file)
@@ -2,9 +2,10 @@
 // revisions: riscv64 riscv32
 // assembly-output: emit-asm
 //[riscv64] compile-flags: --target riscv64imac-unknown-none-elf
+//[riscv64] needs-llvm-components: riscv
 //[riscv32] compile-flags: --target riscv32imac-unknown-none-elf
+//[riscv32] needs-llvm-components: riscv
 // compile-flags: -C target-feature=+d
-// needs-llvm-components: riscv
 // min-system-llvm-version: 12.0
 
 #![feature(no_core, lang_items, rustc_attrs)]
index da2dc51d69e32275c353b60ea15cc4979da2c567..c926fd7b3f56539a81d8c905c7f946df22fa8b61 100644 (file)
@@ -3,7 +3,9 @@
 // assembly-output: emit-asm
 // compile-flags: -O
 //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[x86_64] needs-llvm-components: x86
 //[i686] compile-flags: --target i686-unknown-linux-gnu
+//[i686] needs-llvm-components: x86
 // compile-flags: -C llvm-args=--x86-asm-syntax=intel
 // compile-flags: -C target-feature=+avx512bw
 
index b65b727d2255c1fe20d68bea8a0aea324145c84a..d25f3a03777a6746beed80a72b1e525062374421 100644 (file)
@@ -2,7 +2,9 @@
 // revisions: x86_64 i686
 // assembly-output: emit-asm
 //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[x86_64] needs-llvm-components: x86
 //[i686] compile-flags: --target i686-unknown-linux-gnu
+//[i686] needs-llvm-components: x86
 // compile-flags: -C llvm-args=--x86-asm-syntax=intel
 // compile-flags: -C target-feature=+avx512bw
 
index 2cd74a01c8424d8fcbf7bacad59e3e876976d747..b331d45668ab378711f10001434f8101eba80252 100644 (file)
@@ -1,10 +1,12 @@
 // min-llvm-version: 12.0.0
-// needs-llvm-components: aarch64 x86 powerpc
 // revisions: x64 A64 ppc64le
 // assembly-output: emit-asm
 // [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=static
+// [x64] needs-llvm-components: x86
 // [A64] compile-flags: --target aarch64-unknown-linux-gnu -Crelocation-model=static
+// [A64] needs-llvm-components: aarch64
 // [ppc64le] compile-flags: --target powerpc64le-unknown-linux-gnu -Crelocation-model=static
+// [ppc64le] needs-llvm-components: powerpc
 
 #![feature(no_core, lang_items)]
 #![no_core]
index 613b0bf50e5343806089dc2485a64b5f285b9149..b4fda5f8c8428d0c879382dbf0a6e616af8315f6 100644 (file)
@@ -1,13 +1,16 @@
 // Checks if the correct annotation for the efiapi ABI is passed to llvm.
 
 // revisions:x86_64 i686 aarch64 arm riscv
-// needs-llvm-components: aarch64 arm riscv
-
 //[x86_64] compile-flags: --target x86_64-unknown-uefi
+//[x86_64] needs-llvm-components: aarch64 arm riscv
 //[i686] compile-flags: --target i686-unknown-linux-musl
+//[i686] needs-llvm-components: aarch64 arm riscv
 //[aarch64] compile-flags: --target aarch64-unknown-none
+//[aarch64] needs-llvm-components: aarch64 arm riscv
 //[arm] compile-flags: --target armv7r-none-eabi
+//[arm] needs-llvm-components: aarch64 arm riscv
 //[riscv] compile-flags: --target riscv64gc-unknown-none-elf
+//[riscv] needs-llvm-components: aarch64 arm riscv
 // compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
diff --git a/src/test/codegen/align-fn.rs b/src/test/codegen/align-fn.rs
new file mode 100644 (file)
index 0000000..c5886cf
--- /dev/null
@@ -0,0 +1,9 @@
+// compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0
+
+#![crate_type = "lib"]
+#![feature(fn_align)]
+
+// CHECK: align 16
+#[no_mangle]
+#[repr(align(16))]
+pub fn fn_align() {}
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 70391661b0cfbcb3f3593a292460159a62be26c7..28df0f9b8523e62439a208ba1166862d1c1d26d5 100644 (file)
@@ -94,3 +94,10 @@ pub unsafe fn dont_remove_nonpure() {
     asm!("", options(nomem));
     asm!("", options(readonly));
 }
+
+// CHECK-LABEL: @raw
+// CHECK: call void asm sideeffect inteldialect "{} {}", ""()
+#[no_mangle]
+pub unsafe fn raw() {
+    asm!("{} {}", options(nostack, nomem, preserves_flags, raw));
+}
index fe09caa69730936818194fc502e1616631e34965..135177016bf9a9e3fe50196920c6a082d5a0ffbd 100644 (file)
@@ -1,5 +1,6 @@
-// FIXME(nagisa): remove the flags here once all targets support `asm!`.
+// FIXME(nagisa): remove the flags below once all targets support `asm!`.
 // compile-flags: --target x86_64-unknown-linux-gnu
+// needs-llvm-components: x86
 
 // Verify we sanitize the special tokens for the LLVM inline-assembly, ensuring people won't
 // inadvertently rely on the LLVM-specific syntax and features.
index e410180bfff6fa837640c4411e42b69a5aa0b170..0c16b9ad3ab510fa70fa22c4886d28bb922debdd 100644 (file)
@@ -17,7 +17,7 @@ async fn async_fn_test() {
 // FIXME: No way to reliably check the filename.
 
 // CHECK-DAG:  [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
-// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0"
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator$0"
 // CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
 // For brevity, we only check the struct name and members of the last variant.
 // CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,
@@ -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 7de115f7e9194d7d062c3346f2d76fd64e3e579a..39319a3ea722cbfea9603e354b70ada40cd13284 100644 (file)
@@ -17,7 +17,7 @@ async fn async_fn_test() {
 // FIXME: No way to reliably check the filename.
 
 // CHECK-DAG:  [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
-// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[ASYNC_FN]]
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator#0}", scope: [[ASYNC_FN]]
 // CHECK:      [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[ASYNC_FN]],
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: discriminator: [[DISC:![0-9]*]]
index 3aab4bea3d042530b51ccca414abe8093ddb3d3e..7f945299c22a6c9bb77fb8b39f9c797071da59d4 100644 (file)
@@ -10,7 +10,7 @@
 // CHECK: @STATIC = {{.*}}, align 4
 
 // This checks the constants from inline_enum_const
-// CHECK: @alloc8 = {{.*}}, align 2
+// CHECK: @alloc9 = {{.*}}, align 2
 
 // This checks the constants from {low,high}_align_const, they share the same
 // constant, but the alignment differs, so the higher one should be used
index d4c4200c5d23002e590586ab5553e8bcc6abc1aa..5d77d3f14bb12bd9066a362ec6acdbbdfab0f062 100644 (file)
@@ -1,8 +1,9 @@
 // revisions: WINDOWS ANDROID
-// needs-llvm-components: x86 arm
 // compile-flags: -C panic=abort
 // [WINDOWS] compile-flags: --target=x86_64-pc-windows-msvc
+// [WINDOWS] needs-llvm-components: x86
 // [ANDROID] compile-flags: --target=armv7-linux-androideabi
+// [ANDROID] needs-llvm-components: arm
 
 #![feature(no_core, lang_items)]
 #![crate_type = "lib"]
index f9113d50197c19950fead49653da4d78b495b374..4bd811bed10e5d2999a7551e860e4f902548632c 100644 (file)
@@ -1,7 +1,8 @@
 // compile-flags: -g
 //
 // CHECK-LABEL: @main
-// CHECK: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> <recursive_type>",{{.*}}
+// MSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "recursive_type$ (*)()",{{.*}}
+// NONMSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> <recursive_type>",{{.*}}
 //
 // CHECK: {{.*}}DISubroutineType{{.*}}
 // CHECK: {{.*}}DIBasicType(name: "<recur_type>", encoding: DW_ATE_unsigned)
diff --git a/src/test/codegen/frame-pointer.rs b/src/test/codegen/frame-pointer.rs
new file mode 100644 (file)
index 0000000..367591d
--- /dev/null
@@ -0,0 +1,35 @@
+// compile-flags: --crate-type=rlib
+// revisions: aarch64-apple aarch64-linux force x64-apple x64-linux
+// [aarch64-apple] needs-llvm-components: aarch64
+// [aarch64-apple] compile-flags: --target=aarch64-apple-darwin
+// [aarch64-linux] needs-llvm-components: aarch64
+// [aarch64-linux] compile-flags: --target=aarch64-unknown-linux-gnu
+// [force] needs-llvm-components: x86
+// [force] compile-flags: --target=x86_64-unknown-linux-gnu -Cforce-frame-pointers=yes
+// [x64-apple] needs-llvm-components: x86
+// [x64-apple] compile-flags: --target=x86_64-apple-darwin
+// [x64-linux] needs-llvm-components: x86
+// [x64-linux] compile-flags: --target=x86_64-unknown-linux-gnu
+
+#![feature(no_core, lang_items)]
+#![no_core]
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+
+
+
+// CHECK: define i32 @peach{{.*}}[[PEACH_ATTRS:\#[0-9]+]] {
+#[no_mangle]
+pub fn peach(x: u32) -> u32 {
+    x
+}
+
+// CHECK: attributes [[PEACH_ATTRS]] = {
+// x64-linux-NOT: {{.*}}"frame-pointer"{{.*}}
+// aarch64-linux-NOT: {{.*}}"frame-pointer"{{.*}}
+// x64-apple-SAME: {{.*}}"frame-pointer"="all"
+// force-SAME: {{.*}}"frame-pointer"="all"
+// aarch64-apple-SAME: {{.*}}"frame-pointer"="non-leaf"
+// CHECK-SAME: }
index 7edb07d224c3646865aaa169f27c6b11a0a06826..68d138f8df2f062536d188b464315011299539b2 100644 (file)
@@ -21,7 +21,7 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
 // FIXME: No way to reliably check the filename.
 
 // CHECK-DAG:  [[GEN_FN:!.*]] = !DINamespace(name: "generator_test"
-// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0"
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator$0"
 // CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
 // For brevity, we only check the struct name and members of the last variant.
 // CHECK-SAME: file: [[FILE:![0-9]*]], line: 14,
@@ -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 8b87a2f0646044af947a3639e32637aaeec6e82f..ea324695c15d79d83fc65d94eb4f8f64b72f2db9 100644 (file)
@@ -21,7 +21,7 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
 // FIXME: No way to reliably check the filename.
 
 // CHECK-DAG:  [[GEN_FN:!.*]] = !DINamespace(name: "generator_test"
-// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[GEN_FN]]
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator#0}", scope: [[GEN_FN]]
 // CHECK:      [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[GEN_FN]],
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: discriminator: [[DISC:![0-9]*]]
index dad376d6677f73cf4670c4ab4beccc1f96fc15a9..17258a264a5e60c668ea3166219346e4f06f91fe 100644 (file)
@@ -3,6 +3,7 @@
 // See issue #60235.
 
 // compile-flags: -O --target=i686-apple-darwin --crate-type=rlib
+// needs-llvm-components: x86
 // rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9
 #![feature(no_core, lang_items)]
 #![no_core]
index 1cebc49236feedf66de871e825385ee66413d068..043040a95e364b89a3f9c421cd106e2120631d77 100644 (file)
@@ -3,6 +3,7 @@
 // See issue #60235.
 
 // compile-flags: -O --target=i686-apple-darwin --crate-type=rlib
+// needs-llvm-components: x86
 // unset-rustc-env:MACOSX_DEPLOYMENT_TARGET
 #![feature(no_core, lang_items)]
 #![no_core]
index c085f3c829ea440f7b7954b61587fea1a2f42916..05c2d2fc0d8c1cd354521ff7b9d2169dc7123ce9 100644 (file)
@@ -1,8 +1,7 @@
 // Test that `-Cprofile-generate` creates expected instrumentation artifacts in LLVM IR.
-// Compiling with `-Cpanic=abort` because PGO+unwinding isn't supported on all platforms.
 
 // needs-profiler-support
-// compile-flags: -Cprofile-generate -Ccodegen-units=1 -Cpanic=abort
+// compile-flags: -Cprofile-generate -Ccodegen-units=1
 
 // CHECK: @__llvm_profile_raw_version =
 // CHECK-DAG: @__profc_{{.*}}pgo_instrumentation{{.*}}some_function{{.*}} = {{.*}}global
index c2d01c7fec2311047c6c3daf43ba76e545fa969b..698dfe6b4f3419e76f7770b06136dfe13e53294d 100644 (file)
@@ -12,7 +12,7 @@ mod aux_mod;
 include!("aux_mod.rs");
 
 // Here we check that the expansion of the file!() macro is mapped.
-// CHECK: @alloc1 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1
+// CHECK: @alloc2 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1
 pub static FILE_PATH: &'static str = file!();
 
 fn main() {
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 78e5b14a212141848abeeb9410ddb972769d81de..f228d7c55008487c583114f1e59e61b490b7bd8d 100644 (file)
@@ -1,9 +1,8 @@
-//
 // Checks that we correctly codegen extern "C" functions returning structs.
 // See issue #52638.
 
-// only-sparc64
 // compile-flags: -O --target=sparc64-unknown-linux-gnu --crate-type=rlib
+// needs-llvm-components: sparc
 #![feature(no_core, lang_items)]
 #![no_core]
 
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 8e291b7b298d5a3c41cff7b1179f1edeb2b2adc5..8e673d11d98e941075e21ba79f97ce35de0cdf69 100644 (file)
@@ -3,6 +3,7 @@
 // See issue #60235.
 
 // compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib
+// needs-llvm-components: x86
 // rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9
 #![feature(no_core, lang_items)]
 #![no_core]
index c5ac73b54e186c065fc32343ccd3d41925e42875..25ae6924de03e191e8c77f9dec335cff0de95c43 100644 (file)
@@ -3,6 +3,7 @@
 // See issue #60235.
 
 // compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib
+// needs-llvm-components: x86
 // unset-rustc-env:MACOSX_DEPLOYMENT_TARGET
 #![feature(no_core, lang_items)]
 #![no_core]
index 3721b87678d55f3bdb19645f45885cac59d3aa5e..c35c32554983a6976d08789fb606d422d7713dd8 100644 (file)
@@ -6,9 +6,8 @@
 
 // min-lldb-version: 310
 
-// This fails on lldb 6.0.1 on x86-64 Fedora 28; so mark it macOS-only
-// for now.
-// only-macos
+// This fails on lldb 6.0.1 on x86-64 Fedora 28; so ignore Linux for now.
+// ignore-linux
 
 // compile-flags:-g
 
@@ -44,6 +43,9 @@
 // gdb-check:$13 = 2.5
 // gdb-command:print f64
 // gdb-check:$14 = 3.5
+// gdb-command:print s
+// gdbg-check:$15 = {data_ptr = [...] "Hello, World!", length = 13}
+// gdbr-check:$15 = "Hello, World!"
 
 
 // === LLDB TESTS ==================================================================================
 // lldbg-check:[...]$12 = 3.5
 // lldbr-check:(f64) f64 = 3.5
 
+
+// === CDB TESTS ===================================================================================
+
+// cdb-command:g
+// cdb-command:dx b
+// cdb-check:b                : false [Type: bool]
+// cdb-command:dx i
+// cdb-check:i                : -1 [Type: [...]]
+// The variable 'c' doesn't appear for some reason...
+// cdb-command:dx i8
+// cdb-check:i8               : 68 [Type: char]
+// cdb-command:dx i16
+// cdb-check:i16              : -16 [Type: short]
+// cdb-command:dx i32
+// cdb-check:i32              : -32 [Type: int]
+// cdb-command:dx i64
+// cdb-check:i64              : -64 [Type: __int64]
+// cdb-command:dx u
+// cdb-check:u                : 0x1 [Type: [...]]
+// cdb-command:dx u8
+// cdb-check:u8               : 0x64 [Type: unsigned char]
+// cdb-command:dx u16
+// cdb-check:u16              : 0x10 [Type: unsigned short]
+// cdb-command:dx u32
+// cdb-check:u32              : 0x20 [Type: unsigned int]
+// cdb-command:dx u64
+// cdb-check:u64              : 0x40 [Type: unsigned __int64]
+// cdb-command:dx f32
+// cdb-check:f32              : 2.500000 [Type: float]
+// cdb-command:dx f64
+// cdb-check:f64              : 3.500000 [Type: double]
+// cdb-command:.enable_unicode 1
+// cdb-command:dx  s
+// cdb-check:s                : "Hello, World!" [Type: str]
+
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
@@ -113,6 +150,7 @@ fn main() {
     let u64: u64 = 64;
     let f32: f32 = 2.5;
     let f64: f64 = 3.5;
+    let s: &str = "Hello, World!";
     _zzz(); // #break
 }
 
diff --git a/src/test/debuginfo/duration-type.rs b/src/test/debuginfo/duration-type.rs
new file mode 100644 (file)
index 0000000..bc0266d
--- /dev/null
@@ -0,0 +1,22 @@
+// only-cdb
+// compile-flags:-g
+
+// === CDB TESTS ==================================================================================
+
+// cdb-command: g
+
+// cdb-command: dx duration
+// cdb-check:duration         : 5s 12ns [Type: core::time::Duration]
+// cdb-check:    [<Raw View>]     [Type: core::time::Duration]
+// cdb-check:    seconds          : 5 [Type: unsigned __int64]
+// cdb-check:    nanoseconds      : 12 [Type: unsigned int]
+
+use std::time::Duration;
+
+fn main() {
+    let duration = Duration::new(5, 12);
+
+    zzz(); // #break
+}
+
+fn zzz() { }
diff --git a/src/test/debuginfo/fixed-sized-array.rs b/src/test/debuginfo/fixed-sized-array.rs
new file mode 100644 (file)
index 0000000..d889922
--- /dev/null
@@ -0,0 +1,39 @@
+// Testing the display of fixed sized arrays in cdb.
+
+// cdb-only
+// min-cdb-version: 10.0.18317.1001
+// compile-flags:-g
+
+// === CDB TESTS ==================================================================================
+
+// cdb-command: g
+
+// cdb-command: dx xs,d
+// cdb-check:xs,d             [Type: int [5]]
+// cdb-check:    [0]              : 1 [Type: int]
+// cdb-check:    [1]              : 2 [Type: int]
+// cdb-check:    [2]              : 3 [Type: int]
+// cdb-check:    [3]              : 4 [Type: int]
+// cdb-check:    [4]              : 5 [Type: int]
+
+// cdb-command: dx ys,d
+// cdb-check:ys,d             [Type: int [3]]
+// cdb-check:    [0]              : 0 [Type: int]
+// cdb-check:    [1]              : 0 [Type: int]
+// cdb-check:    [2]              : 0 [Type: int]
+
+fn main() {
+    // Fixed-size array (type signature is superfluous)
+    let xs: [i32; 5] = [1, 2, 3, 4, 5];
+
+    // All elements can be initialized to the same value
+    let ys: [i32; 3] = [0; 3];
+
+    // Indexing starts at 0
+    println!("first element of the array: {}", xs[0]);
+    println!("second element of the array: {}", xs[1]);
+
+    zzz(); // #break
+}
+
+fn zzz() { () }
diff --git a/src/test/debuginfo/function-names.rs b/src/test/debuginfo/function-names.rs
new file mode 100644 (file)
index 0000000..28ab176
--- /dev/null
@@ -0,0 +1,201 @@
+// Function names are formatted differently in old versions of GDB
+// min-gdb-version: 9.2
+
+// compile-flags:-g
+
+// === GDB TESTS ===================================================================================
+
+// Top-level function
+// gdb-command:info functions -q function_names::main
+// gdb-check:[...]static fn function_names::main();
+// gdb-command:info functions -q function_names::generic_func<*
+// gdb-check:[...]static fn function_names::generic_func(i32) -> i32;
+
+// Implementations
+// gdb-command:info functions -q function_names::.*::impl_function.*
+// gdb-check:[...]static fn function_names::GenericStruct<T1,T2>::impl_function();
+// gdb-check:[...]static fn function_names::Mod1::TestStruct2::impl_function();
+// gdb-check:[...]static fn function_names::TestStruct1::impl_function();
+
+// Trait implementations
+// gdb-command:info functions -q function_names::.*::trait_function.*
+// gdb-check:[...]static fn <function_names::GenericStruct<T,i32> as function_names::TestTrait1>::trait_function();
+// gdb-check:[...]static fn <function_names::GenericStruct<[T; N],f32> as function_names::TestTrait1>::trait_function();
+// gdb-check:[...]static fn <function_names::Mod1::TestStruct2 as function_names::Mod1::TestTrait2>::trait_function();
+// gdb-check:[...]static fn <function_names::TestStruct1 as function_names::TestTrait1>::trait_function();
+
+// Closure
+// gdb-command:info functions -q function_names::.*::{{closure.*
+// gdb-check:[...]static fn function_names::GenericStruct<T1,T2>::impl_function::{{closure}}(*mut function_names::{impl#2}::impl_function::{closure#0});
+// gdb-check:[...]static fn function_names::generic_func::{{closure}}(*mut function_names::generic_func::{closure#0});
+// gdb-check:[...]static fn function_names::main::{{closure}}(*mut function_names::main::{closure#0});
+
+// Generator
+// Generators don't seem to appear in GDB's symbol table.
+
+// Const generic parameter
+// gdb-command:info functions -q function_names::const_generic_fn.*
+// gdb-check:[...]static fn function_names::const_generic_fn_bool();
+// gdb-check:[...]static fn function_names::const_generic_fn_non_int();
+// gdb-check:[...]static fn function_names::const_generic_fn_signed_int();
+// gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int();
+
+// === CDB TESTS ===================================================================================
+
+// Top-level function
+// cdb-command:x a!function_names::main
+// cdb-check:[...] a!function_names::main (void)
+// cdb-command:x a!function_names::generic_func<*
+// cdb-check:[...] a!function_names::generic_func<i32> (int)
+
+// Implementations
+// cdb-command:x a!function_names::*::impl_function*
+// cdb-check:[...] a!function_names::Mod1::TestStruct2::impl_function (void)
+// cdb-check:[...] a!function_names::TestStruct1::impl_function (void)
+// cdb-check:[...] a!function_names::GenericStruct<i32,i32>::impl_function<i32,i32> (void)
+
+// Trait implementations
+// cdb-command:x a!function_names::*::trait_function*
+// cdb-check:[...] a!function_names::impl$3::trait_function<i32> (void)
+// cdb-check:[...] a!function_names::impl$6::trait_function<i32,1> (void)
+// cdb-check:[...] a!function_names::impl$1::trait_function (void)
+// cdb-check:[...] a!function_names::impl$5::trait_function3<function_names::TestStruct1> (void)
+// cdb-check:[...] a!function_names::Mod1::impl$1::trait_function (void)
+
+// Closure
+// cdb-command:x a!function_names::*::closure*
+// cdb-check:[...] a!function_names::impl$2::impl_function::closure$0<i32,i32> (void)
+// cdb-check:[...] a!function_names::main::closure$0 (void)
+// cdb-check:[...] a!function_names::generic_func::closure$0<i32> (void)
+
+// Generator
+// cdb-command:x a!function_names::*::generator*
+// cdb-check:[...] a!function_names::main::generator$1 (void)
+
+// Const generic parameter
+// cdb-command:x a!function_names::const_generic_fn*
+// cdb-check:[...] a!function_names::const_generic_fn_bool<false> (void)
+// cdb-check:[...] a!function_names::const_generic_fn_non_int<CONST$fe3cfa0214ac55c7> (void)
+// cdb-check:[...] a!function_names::const_generic_fn_unsigned_int<14> (void)
+// cdb-check:[...] a!function_names::const_generic_fn_signed_int<-7> (void)
+
+#![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
+#![omit_gdb_pretty_printer_section]
+#![feature(const_generics, generators, generator_trait)]
+#![allow(incomplete_features)] // for const_generics
+
+use Mod1::TestTrait2;
+use std::ops::Generator;
+use std::pin::Pin;
+
+fn main() {
+    // Implementations
+    TestStruct1::impl_function();
+    Mod1::TestStruct2::impl_function();
+    GenericStruct::<i32, i32>::impl_function();
+
+    // Trait implementations
+    TestStruct1::trait_function();
+    Mod1::TestStruct2::trait_function();
+    GenericStruct::<i32, i32>::trait_function();
+    GenericStruct::<[i32; 1], f32>::trait_function();
+    GenericStruct::<TestStruct1, usize>::trait_function3();
+
+    // Generic function
+    let _ = generic_func(42);
+
+    // Closure
+    let closure = || { TestStruct1 };
+    closure();
+
+    // Generator
+    let mut generator = || { yield; return; };
+    Pin::new(&mut generator).resume(());
+
+    // Const generic functions
+    const_generic_fn_bool::<false>();
+    const_generic_fn_non_int::<{()}>();
+    const_generic_fn_signed_int::<-7>();
+    const_generic_fn_unsigned_int::<14>();
+}
+
+struct TestStruct1;
+trait TestTrait1 {
+    fn trait_function();
+}
+
+// Implementation
+impl TestStruct1 {
+    pub fn impl_function() {}
+}
+
+// Implementation for a trait
+impl TestTrait1 for TestStruct1 {
+    fn trait_function() {}
+}
+
+// Implementation and implementation within a mod
+mod Mod1 {
+    pub struct TestStruct2;
+    pub trait TestTrait2 {
+        fn trait_function();
+    }
+
+    impl TestStruct2 {
+        pub fn impl_function() {}
+    }
+
+    impl TestTrait2 for TestStruct2 {
+        fn trait_function() {}
+    }
+}
+
+struct GenericStruct<T1, T2>(std::marker::PhantomData<(T1, T2)>);
+
+// Generic implementation
+impl<T1, T2> GenericStruct<T1, T2> {
+    pub fn impl_function() {
+        // Closure in a generic implementation
+        let closure = || { TestStruct1 };
+        closure();
+    }
+}
+
+// Generic trait implementation
+impl<T> TestTrait1 for GenericStruct<T, i32> {
+    fn trait_function() {}
+}
+
+// Implementation based on associated type
+trait TestTrait3 {
+    type AssocType;
+    fn trait_function3();
+}
+impl TestTrait3 for TestStruct1 {
+    type AssocType = usize;
+    fn trait_function3() {}
+}
+impl<T: TestTrait3> TestTrait3 for GenericStruct<T, T::AssocType> {
+    type AssocType = T::AssocType;
+    fn trait_function3() {}
+}
+
+// Generic trait implementation with const generics
+impl<T, const N: usize> TestTrait1 for GenericStruct<[T; N], f32> {
+    fn trait_function() {}
+}
+
+// Generic function
+fn generic_func<T>(value: T) -> T {
+    // Closure in a generic function
+    let closure = || { TestStruct1 };
+    closure();
+
+    value
+}
+
+fn const_generic_fn_bool<const C: bool>() {}
+fn const_generic_fn_non_int<const C: ()>() {}
+fn const_generic_fn_signed_int<const C: i64>() {}
+fn const_generic_fn_unsigned_int<const C: u32>() {}
index 1beed1c835d977d566d388f019057a1d6722eb25..7ac3304aa963491547aa53342567595888610237 100644 (file)
 
 // gdb-command:run
 // gdb-command:print b
-// gdb-check:$1 = generator_objects::main::generator-0::Unresumed(0x[...])
+// gdb-check:$1 = generator_objects::main::{generator#0}::Unresumed(0x[...])
 // gdb-command:continue
 // gdb-command:print b
-// gdb-check:$2 = generator_objects::main::generator-0::Suspend0{c: 6, d: 7, __0: 0x[...]}
+// gdb-check:$2 = generator_objects::main::{generator#0}::Suspend0{c: 6, d: 7, __0: 0x[...]}
 // gdb-command:continue
 // gdb-command:print b
-// gdb-check:$3 = generator_objects::main::generator-0::Suspend1{c: 7, d: 8, __0: 0x[...]}
+// gdb-check:$3 = generator_objects::main::{generator#0}::Suspend1{c: 7, d: 8, __0: 0x[...]}
 // gdb-command:continue
 // gdb-command:print b
-// gdb-check:$4 = generator_objects::main::generator-0::Returned(0x[...])
+// gdb-check:$4 = generator_objects::main::{generator#0}::Returned(0x[...])
 
 // === LLDB TESTS ==================================================================================
 
 // lldb-command:run
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::generator-0) $0 =
+// lldbg-check:(generator_objects::main::{generator#0}) $0 =
 // lldb-command:continue
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::generator-0) $1 =
+// lldbg-check:(generator_objects::main::{generator#0}) $1 =
 // lldb-command:continue
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::generator-0) $2 =
+// lldbg-check:(generator_objects::main::{generator#0}) $2 =
 // lldb-command:continue
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::generator-0) $3 =
+// lldbg-check:(generator_objects::main::{generator#0}) $3 =
 
 #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)]
 #![omit_gdb_pretty_printer_section]
index 170a610c621c035ddc44ce36c6fad533e2372858..5fa5ce80099358821d4f6f9b641d6524ac1da7eb 100644 (file)
 // lldbg-check:[...]$3 = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } }
 // lldbr-check:(generic_struct::AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>>) float_int_float = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } }
 
+// === CDB TESTS ===================================================================================
+
+// cdb-command:g
+
+// cdb-command:dx int_int
+// cdb-check:int_int          [Type: generic_struct::AGenericStruct<i32,i32>]
+// cdb-check:[...]key              : 0 [Type: int]
+// cdb-check:[...]value            : 1 [Type: int]
+// cdb-command:dx int_float
+// cdb-check:int_float        [Type: generic_struct::AGenericStruct<i32,f64>]
+// cdb-check:[...]key              : 2 [Type: int]
+// cdb-check:[...]value            : 3.500000 [Type: double]
+// cdb-command:dx float_int
+// cdb-check:float_int        [Type: generic_struct::AGenericStruct<f64,i32>]
+// cdb-check:[...]key              : 4.500000 [Type: double]
+// cdb-check:[...]value            : 5 [Type: int]
+// cdb-command:dx float_int_float
+// cdb-check:float_int_float  [Type: generic_struct::AGenericStruct<f64,generic_struct::AGenericStruct<i32,f64> >]
+// cdb-check:[...]key              : 6.500000 [Type: double]
+// cdb-check:[...]value            [Type: generic_struct::AGenericStruct<i32,f64>]
+
 
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
index 6b2b12edda5d7a710c48862caaed0560b263be0c..f6d2146fe11fa43654053d80df0a9ae6004a800c 100644 (file)
 // gdb-command:run
 
 // gdb-command:print g
-// gdb-check:$1 = issue_57822::main::closure-1 (issue_57822::main::closure-0 (1))
+// gdb-check:$1 = issue_57822::main::{closure#1} (issue_57822::main::{closure#0} (1))
 
 // gdb-command:print b
-// gdb-check:$2 = issue_57822::main::generator-3::Unresumed(issue_57822::main::generator-2::Unresumed(2))
+// gdb-check:$2 = issue_57822::main::{generator#3}::Unresumed(issue_57822::main::{generator#2}::Unresumed(2))
 
 // === LLDB TESTS ==================================================================================
 
 // lldb-command:run
 
 // lldb-command:print g
-// lldbg-check:(issue_57822::main::closure-1) $0 = { 0 = { 0 = 1 } }
+// lldbg-check:(issue_57822::main::{closure#1}) $0 = { 0 = { 0 = 1 } }
 
 // lldb-command:print b
-// lldbg-check:(issue_57822::main::generator-3) $1 =
+// lldbg-check:(issue_57822::main::{generator#3}) $1 =
 
 #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)]
 #![omit_gdb_pretty_printer_section]
diff --git a/src/test/debuginfo/marker-types.rs b/src/test/debuginfo/marker-types.rs
new file mode 100644 (file)
index 0000000..8373d78
--- /dev/null
@@ -0,0 +1,49 @@
+// only-cdb
+// compile-flags:-g
+
+// === CDB TESTS ==================================================================================
+
+// cdb-command: g
+
+// cdb-command: dx nonnull
+// cdb-check:nonnull          : NonNull(0x[...]: 0xc) [Type: core::ptr::non_null::NonNull<u32>]
+// cdb-check:    [<Raw View>]     [Type: core::ptr::non_null::NonNull<u32>]
+// cdb-check:    0xc [Type: unsigned int]
+
+// cdb-command: dx manuallydrop
+// cdb-check:manuallydrop     : 12345 [Type: core::mem::manually_drop::ManuallyDrop<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::mem::manually_drop::ManuallyDrop<i32>]
+
+// cdb-command: dx pin
+// cdb-check:pin              : Pin(0x[...]: "this") [Type: core::pin::Pin<ref_mut$<alloc::string::String> >]
+// cdb-check:    [<Raw View>]     [Type: core::pin::Pin<ref_mut$<alloc::string::String> >]
+// cdb-check:    [len]            : 0x4 [Type: unsigned [...]]
+// cdb-check:    [capacity]       : 0x4 [Type: unsigned [...]]
+// cdb-check:    [chars]          : "this"
+
+// cdb-command: dx unique
+// cdb-check:unique           : Unique(0x[...]: (0x2a, 4321)) [Type: core::ptr::unique::Unique<tuple$<u64,i32> >]
+// cdb-check:    [<Raw View>]     [Type: core::ptr::unique::Unique<tuple$<u64,i32> >]
+// cdb-check:    [0]              : 0x2a [Type: unsigned __int64]
+// cdb-check:    [1]              : 4321 [Type: int]
+
+#![feature(ptr_internals)]
+
+use std::mem::ManuallyDrop;
+use std::pin::Pin;
+use std::ptr::{NonNull, Unique};
+
+fn main() {
+    let nonnull: NonNull<_> = (&12u32).into();
+
+    let manuallydrop = ManuallyDrop::new(12345i32);
+
+    let mut s = "this".to_string();
+    let pin = Pin::new(&mut s);
+
+    let unique: Unique<_> = (&mut (42u64, 4321i32)).into();
+
+    zzz(); // #break
+}
+
+fn zzz() { }
index 550cc66f3899c01407419469880ccffc6c7a34ff..9463f82c797496b5a05f9fde1f3622f3dd47c1c4 100644 (file)
@@ -5,19 +5,22 @@
 // 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] dataful_variant  [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Some]
+// cdb-check:a,!              [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Some]
 // cdb-check:        [+0x000] __0              : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check:    [+0x000] discriminant     : 0x2 [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Discriminant$]
+// cdb-check:    [+0x000] discriminant     : 0x2 [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Discriminant$]
 
 // cdb-command: dx -r2 b,!
-// cdb-check:b,!              [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Some]
+// cdb-check:b,!              [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Some]
 // cdb-check:        [+0x000] __0              : 0x11 [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check:    [+0x000] discriminant     : None (0x11) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Discriminant$]
+// cdb-check:    [+0x000] discriminant     : None (0x11) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Discriminant$]
 
 // cdb-command: dx -r2 c,!
 // cdb-check:c,!              [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
 // cdb-check:    [+0x000] discriminant     : Tag2 (0x13) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
 
 // cdb-command: dx -r2 f,!
-// cdb-check:f,!              [Type: enum$<core::option::Option<u32*>, 1, [...], Some>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Some]
+// cdb-check:f,!              [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Some]
 // cdb-check:        [+0x000] __0              : 0x[...] : 0x1 [Type: unsigned int *]
-// cdb-check:    [+0x000] discriminant     : 0x[...] [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Discriminant$]
+// cdb-check:    [+0x000] discriminant     : 0x[...] [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$]
 
 // cdb-command: dx -r2 g,!
-// cdb-check:g,!              [Type: enum$<core::option::Option<u32*>, 1, [...], Some>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Some]
+// cdb-check:g,!              [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Some]
 // cdb-check:        [+0x000] __0              : 0x0 [Type: unsigned int *]
-// cdb-check:    [+0x000] discriminant     : None (0x0) [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Discriminant$]
+// 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:h                : Some [Type: enum$<core::option::Option<u32> >]
+// 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:i                : None [Type: enum$<core::option::Option<u32> >]
+// 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,
@@ -78,6 +102,8 @@ pub enum NicheLayoutEnum {
     Tag2,
 }
 
+pub enum Empty { }
+
 fn main() {
     let a = Some(CStyleEnum::Low);
     let b = Option::<CStyleEnum>::None;
@@ -90,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
 }
diff --git a/src/test/debuginfo/mutable-locs.rs b/src/test/debuginfo/mutable-locs.rs
new file mode 100644 (file)
index 0000000..688483e
--- /dev/null
@@ -0,0 +1,104 @@
+// Testing the display of Cell, RefCell, and RefMut in cdb.
+
+// cdb-only
+// min-cdb-version: 10.0.18317.1001
+// compile-flags:-g
+
+// === CDB TESTS ==================================================================================
+
+// cdb-command: g
+
+// cdb-command:dx static_c,d
+// cdb-check:static_c,d       : 10 [Type: core::cell::Cell<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::cell::Cell<i32>]
+
+// cdb-command: dx static_c.value,d
+// cdb-check:static_c.value,d : 10 [Type: core::cell::UnsafeCell<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::cell::UnsafeCell<i32>]
+
+// cdb-command:  dx dynamic_c,d
+// cdb-check:dynamic_c,d      : 15 [Type: core::cell::RefCell<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::cell::RefCell<i32>]
+// cdb-check:    [Borrow state]   : Unborrowed
+
+// cdb-command: dx dynamic_c.value,d
+// cdb-check:dynamic_c.value,d : 15 [Type: core::cell::UnsafeCell<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::cell::UnsafeCell<i32>]
+
+// cdb-command: dx b,d
+// cdb-check:b,d              : 42 [Type: core::cell::RefMut<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::cell::RefMut<i32>]
+// cdb-check:    42 [Type: int]
+
+// cdb-command: g
+
+// cdb-command: dx dynamic_c,d
+// cdb-check:dynamic_c,d      : 15 [Type: core::cell::RefCell<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::cell::RefCell<i32>]
+// cdb-check:    [Borrow state]   : Immutably borrowed
+
+// cdb-command: dx r_borrow,d
+// cdb-check:r_borrow,d       : 15 [Type: core::cell::Ref<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::cell::Ref<i32>]
+// cdb-check:    15 [Type: int]
+
+// cdb-command: g
+
+// cdb-command: dx dynamic_c,d
+// cdb-check:dynamic_c,d      : 15 [Type: core::cell::RefCell<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::cell::RefCell<i32>]
+// cdb-check:    [Borrow state]   : Unborrowed
+
+// cdb-command: g
+
+// cdb-command: dx dynamic_c,d
+// cdb-check:dynamic_c,d      : 15 [Type: core::cell::RefCell<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::cell::RefCell<i32>]
+// cdb-check:    [Borrow state]   : Mutably borrowed
+
+// cdb-command: dx r_borrow_mut,d
+// cdb-check:r_borrow_mut,d   : 15 [Type: core::cell::RefMut<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::cell::RefMut<i32>]
+// cdb-check:    15 [Type: int]
+
+// cdb-command: g
+
+// cdb-command: dx dynamic_c,d
+// cdb-check:dynamic_c,d      : 15 [Type: core::cell::RefCell<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::cell::RefCell<i32>]
+// cdb-check:    [Borrow state]   : Unborrowed
+
+#![allow(unused_variables)]
+
+use std::cell::{Cell, RefCell};
+
+fn main() {
+    let static_c = Cell::new(5);
+    static_c.set(10);
+
+    let dynamic_c = RefCell::new(5);
+    dynamic_c.replace(15);
+
+    let dynamic_c_0 = RefCell::new(15);
+    let mut b = dynamic_c_0.borrow_mut();
+    *b = 42;
+
+    zzz(); // #break
+
+    // Check that `RefCell`'s borrow state visualizes correctly
+    {
+        let r_borrow = dynamic_c.borrow();
+        zzz(); // #break
+    }
+
+    zzz(); // #break
+
+    {
+        let r_borrow_mut = dynamic_c.borrow_mut();
+        zzz(); // #break
+    }
+
+    zzz(); // #break
+}
+
+fn zzz() {()}
diff --git a/src/test/debuginfo/mutex.rs b/src/test/debuginfo/mutex.rs
new file mode 100644 (file)
index 0000000..40bea30
--- /dev/null
@@ -0,0 +1,38 @@
+// Testing the display of Mutex and MutexGuard in cdb.
+
+// cdb-only
+// min-cdb-version: 10.0.21287.1005
+// compile-flags:-g
+
+// === CDB TESTS ==================================================================================
+//
+// cdb-command:g
+//
+// cdb-command:dx m,d
+// cdb-check:m,d              [Type: std::sync::mutex::Mutex<i32>]
+// cdb-check:    [...] inner            [Type: std::sys_common::mutex::MovableMutex]
+// cdb-check:    [...] poison           [Type: std::sync::poison::Flag]
+// cdb-check:    [...] data             [Type: core::cell::UnsafeCell<i32>]
+
+//
+// cdb-command:dx m.data,d
+// cdb-check:m.data,d         [Type: core::cell::UnsafeCell<i32>]
+// cdb-check:    [...] value            : 0 [Type: int]
+
+//
+// cdb-command:dx lock,d
+// cdb-check:lock,d           : Ok [Type: enum$<core::result::Result<std::sync::mutex::MutexGuard<i32>, enum$<std::sync::poison::TryLockError<std::sync::mutex::MutexGuard<i32> >, 0, 1, Poisoned> > >]
+// cdb-check:    [...] variant$         : Ok (0) [Type: core::result::Result]
+// cdb-check:    [...] __0              [Type: std::sync::mutex::MutexGuard<i32>]
+
+use std::sync::Mutex;
+
+#[allow(unused_variables)]
+fn main()
+{
+    let m = Mutex::new(0);
+    let lock = m.try_lock();
+    zzz(); // #break
+}
+
+fn zzz() {}
diff --git a/src/test/debuginfo/numeric-types.rs b/src/test/debuginfo/numeric-types.rs
new file mode 100644 (file)
index 0000000..2eae923
--- /dev/null
@@ -0,0 +1,206 @@
+// only-cdb
+// compile-flags:-g
+
+// Tests the visualizations for `NonZero{I,U}{8,16,32,64,128,size}`, `Wrapping<T>` and
+// `Atomic{Bool,I8,I16,I32,I64,Isize,U8,U16,U32,U64,Usize}` located in `libcore.natvis`.
+
+// === CDB TESTS ==================================================================================
+// cdb-command: g
+
+// cdb-command: dx nz_i8
+// cdb-check:nz_i8            : 11 [Type: core::num::nonzero::NonZeroI8]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroI8]
+
+// cdb-command: dx nz_i16
+// cdb-check:nz_i16           : 22 [Type: core::num::nonzero::NonZeroI16]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroI16]
+
+// cdb-command: dx nz_i32
+// cdb-check:nz_i32           : 33 [Type: core::num::nonzero::NonZeroI32]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroI32]
+
+// cdb-command: dx nz_i64
+// cdb-check:nz_i64           : 44 [Type: core::num::nonzero::NonZeroI64]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroI64]
+
+// 128-bit integers don't seem to work in CDB
+// cdb-command: dx nz_i128
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroI128]
+
+// cdb-command: dx nz_isize
+// cdb-check:nz_isize         : 66 [Type: core::num::nonzero::NonZeroIsize]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroIsize]
+
+// cdb-command: dx nz_u8
+// cdb-check:nz_u8            : 0x4d [Type: core::num::nonzero::NonZeroU8]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroU8]
+
+// cdb-command: dx nz_u16
+// cdb-check:nz_u16           : 0x58 [Type: core::num::nonzero::NonZeroU16]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroU16]
+
+// cdb-command: dx nz_u32
+// cdb-check:nz_u32           : 0x63 [Type: core::num::nonzero::NonZeroU32]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroU32]
+
+// cdb-command: dx nz_u64
+// cdb-check:nz_u64           : 0x64 [Type: core::num::nonzero::NonZeroU64]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroU64]
+
+// 128-bit integers don't seem to work in CDB
+// cdb-command: dx nz_u128
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroU128]
+
+// cdb-command: dx nz_usize
+// cdb-check:nz_usize         : 0x7a [Type: core::num::nonzero::NonZeroUsize]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroUsize]
+
+// cdb-command: dx w_i8
+// cdb-check:w_i8             : 10 [Type: core::num::wrapping::Wrapping<i8>]
+// cdb-check:    [<Raw View>]     [Type: core::num::wrapping::Wrapping<i8>]
+
+// cdb-command: dx w_i16
+// cdb-check:w_i16            : 20 [Type: core::num::wrapping::Wrapping<i16>]
+// cdb-check:    [<Raw View>]     [Type: core::num::wrapping::Wrapping<i16>]
+
+// cdb-command: dx w_i32
+// cdb-check:w_i32            : 30 [Type: core::num::wrapping::Wrapping<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::num::wrapping::Wrapping<i32>]
+
+// cdb-command: dx w_i64
+// cdb-check:w_i64            : 40 [Type: core::num::wrapping::Wrapping<i64>]
+// cdb-check:    [<Raw View>]     [Type: core::num::wrapping::Wrapping<i64>]
+
+// 128-bit integers don't seem to work in CDB
+// cdb-command: dx w_i128
+// cdb-check:w_i128           [Type: core::num::wrapping::Wrapping<i128>]
+// cdb-check:    [<Raw View>]     [Type: core::num::wrapping::Wrapping<i128>]
+
+// cdb-command: dx w_isize
+// cdb-check:w_isize          : 60 [Type: core::num::wrapping::Wrapping<isize>]
+// cdb-check:    [<Raw View>]     [Type: core::num::wrapping::Wrapping<isize>]
+
+// cdb-command: dx w_u8
+// cdb-check:w_u8             : 0x46 [Type: core::num::wrapping::Wrapping<u8>]
+// cdb-check:    [<Raw View>]     [Type: core::num::wrapping::Wrapping<u8>]
+
+// cdb-command: dx w_u16
+// cdb-check:w_u16            : 0x50 [Type: core::num::wrapping::Wrapping<u16>]
+// cdb-check:    [<Raw View>]     [Type: core::num::wrapping::Wrapping<u16>]
+
+// cdb-command: dx w_u32
+// cdb-check:w_u32            : 0x5a [Type: core::num::wrapping::Wrapping<u32>]
+// cdb-check:    [<Raw View>]     [Type: core::num::wrapping::Wrapping<u32>]
+
+// cdb-command: dx w_u64
+// cdb-check:w_u64            : 0x64 [Type: core::num::wrapping::Wrapping<u64>]
+// cdb-check:    [<Raw View>]     [Type: core::num::wrapping::Wrapping<u64>]
+
+// 128-bit integers don't seem to work in CDB
+// cdb-command: dx w_u128
+// cdb-check:w_u128           [Type: core::num::wrapping::Wrapping<u128>]
+// cdb-check:    [<Raw View>]     [Type: core::num::wrapping::Wrapping<u128>]
+
+// cdb-command: dx w_usize
+// cdb-check:w_usize          : 0x78 [Type: core::num::wrapping::Wrapping<usize>]
+// cdb-check:    [<Raw View>]     [Type: core::num::wrapping::Wrapping<usize>]
+
+// cdb-command: dx a_bool_t
+// cdb-check:a_bool_t         : true [Type: core::sync::atomic::AtomicBool]
+// cdb-check:    [<Raw View>]     [Type: core::sync::atomic::AtomicBool]
+
+// cdb-command: dx a_bool_f
+// cdb-check:a_bool_f         : false [Type: core::sync::atomic::AtomicBool]
+// cdb-check:    [<Raw View>]     [Type: core::sync::atomic::AtomicBool]
+
+// cdb-command: dx a_i8
+// cdb-check:a_i8             : 2 [Type: core::sync::atomic::AtomicI8]
+// cdb-check:    [<Raw View>]     [Type: core::sync::atomic::AtomicI8]
+
+// cdb-command: dx a_i16
+// cdb-check:a_i16            : 4 [Type: core::sync::atomic::AtomicI16]
+// cdb-check:    [<Raw View>]     [Type: core::sync::atomic::AtomicI16]
+
+// cdb-command: dx a_i32
+// cdb-check:a_i32            : 8 [Type: core::sync::atomic::AtomicI32]
+// cdb-check:    [<Raw View>]     [Type: core::sync::atomic::AtomicI32]
+
+// cdb-command: dx a_i64
+// cdb-check:a_i64            : 16 [Type: core::sync::atomic::AtomicI64]
+// cdb-check:    [<Raw View>]     [Type: core::sync::atomic::AtomicI64]
+
+// cdb-command: dx a_isize
+// cdb-check:a_isize          : 32 [Type: core::sync::atomic::AtomicIsize]
+// cdb-check:    [<Raw View>]     [Type: core::sync::atomic::AtomicIsize]
+
+// cdb-command: dx a_u8
+// cdb-check:a_u8             : 0x40 [Type: core::sync::atomic::AtomicU8]
+// cdb-check:    [<Raw View>]     [Type: core::sync::atomic::AtomicU8]
+
+// cdb-command: dx a_u16
+// cdb-check:a_u16            : 0x80 [Type: core::sync::atomic::AtomicU16]
+// cdb-check:    [<Raw View>]     [Type: core::sync::atomic::AtomicU16]
+
+// cdb-command: dx a_u32
+// cdb-check:a_u32            : 0x100 [Type: core::sync::atomic::AtomicU32]
+// cdb-check:    [<Raw View>]     [Type: core::sync::atomic::AtomicU32]
+
+// cdb-command: dx a_u64
+// cdb-check:a_u64            : 0x200 [Type: core::sync::atomic::AtomicU64]
+// cdb-check:    [<Raw View>]     [Type: core::sync::atomic::AtomicU64]
+
+// cdb-command: dx a_usize
+// cdb-check:a_usize          : 0x400 [Type: core::sync::atomic::AtomicUsize]
+// cdb-check:    [<Raw View>]     [Type: core::sync::atomic::AtomicUsize]
+
+use std::num::*;
+use std::sync::atomic::*;
+
+fn main() {
+    let nz_i8 = NonZeroI8::new(11).unwrap();
+    let nz_i16 = NonZeroI16::new(22).unwrap();
+    let nz_i32 = NonZeroI32::new(33).unwrap();
+    let nz_i64 = NonZeroI64::new(44).unwrap();
+    let nz_i128 = NonZeroI128::new(55).unwrap();
+    let nz_isize = NonZeroIsize::new(66).unwrap();
+
+    let nz_u8 = NonZeroU8::new(77).unwrap();
+    let nz_u16 = NonZeroU16::new(88).unwrap();
+    let nz_u32 = NonZeroU32::new(99).unwrap();
+    let nz_u64 = NonZeroU64::new(100).unwrap();
+    let nz_u128 = NonZeroU128::new(111).unwrap();
+    let nz_usize = NonZeroUsize::new(122).unwrap();
+
+    let w_i8 = Wrapping(10i8);
+    let w_i16 = Wrapping(20i16);
+    let w_i32 = Wrapping(30i32);
+    let w_i64 = Wrapping(40i64);
+    let w_i128 = Wrapping(50i128);
+    let w_isize = Wrapping(60isize);
+
+    let w_u8 = Wrapping(70u8);
+    let w_u16 = Wrapping(80u16);
+    let w_u32 = Wrapping(90u32);
+    let w_u64 = Wrapping(100u64);
+    let w_u128 = Wrapping(110u128);
+    let w_usize = Wrapping(120usize);
+
+    let a_bool_t = AtomicBool::new(true);
+    let a_bool_f = AtomicBool::new(false);
+
+    let a_i8 = AtomicI8::new(2);
+    let a_i16 = AtomicI16::new(4);
+    let a_i32 = AtomicI32::new(8);
+    let a_i64 = AtomicI64::new(16);
+    let a_isize = AtomicIsize::new(32);
+
+    let a_u8 = AtomicU8::new(64);
+    let a_u16 = AtomicU16::new(128);
+    let a_u32 = AtomicU32::new(256);
+    let a_u64 = AtomicU64::new(512);
+    let a_usize = AtomicUsize::new(1024);
+
+    zzz(); // #break
+}
+
+fn zzz() { }
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 7115aec1041af49774955f1a9733de8572c90d92..40bde8606996aaabdae5ec3d5cbd4fcb6233814c 100644 (file)
@@ -10,7 +10,7 @@
 // cdb-command: g
 
 // cdb-command: dx hash_set,d
-// cdb-check:hash_set,d [...] : { len=15 } [Type: [...]::HashSet<u64, [...]>]
+// cdb-check:hash_set,d [...] : { len=15 } [Type: [...]::HashSet<u64,[...]>]
 // cdb-check:    [len]            : 15 [Type: [...]]
 // cdb-check:    [capacity]       : [...]
 // cdb-check:    [[...]] [...]    : 0 [Type: u64]
@@ -44,7 +44,7 @@
 // cdb-check:    [[...]] [...]    : 14 [Type: u64]
 
 // cdb-command: dx hash_map,d
-// cdb-check:hash_map,d [...] : { len=15 } [Type: [...]::HashMap<u64, u64, [...]>]
+// cdb-check:hash_map,d [...] : { len=15 } [Type: [...]::HashMap<u64,u64,[...]>]
 // cdb-check:    [len]            : 15 [Type: [...]]
 // cdb-check:    [capacity]       : [...]
 // cdb-check:    ["0x0"]          : 0 [Type: unsigned __int64]
@@ -77,6 +77,8 @@
 // cdb-command: dx hash_map,d
 // cdb-check:    ["0xe"]          : 14 [Type: unsigned __int64]
 
+// cdb-command: dx x
+
 #![allow(unused_variables)]
 use std::collections::HashSet;
 use std::collections::HashMap;
@@ -95,6 +97,9 @@ fn main() {
         hash_map.insert(i as u64, i as u64);
     }
 
+    let x = &(123u64, 456u64);
+    let string = "awefawefawe".to_string();
+
     zzz(); // #break
 }
 
index 68e73b5f38da98024d6e5ce863e5e71d56b9dde1..a190a29eec2a59491f32fa85884e1bf8082d7f56 100644 (file)
@@ -1,10 +1,10 @@
 // ignore-freebsd: gdb package too new
 // only-cdb // "Temporarily" ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155
 // ignore-android: FIXME(#10381)
-// ignore-tidy-linelength
 // compile-flags:-g
 // min-gdb-version: 7.7
 // min-lldb-version: 310
+// min-cdb-version: 10.0.18317.1001
 
 // === GDB TESTS ===================================================================================
 
 // cdb-command: g
 
 // cdb-command: dx slice,d
-// cdb-check:slice,d [...]
-// NOTE: While slices have a .natvis entry that works in VS & VS Code, it fails in CDB 10.0.18362.1
+// cdb-check:slice,d          : { len=4 } [Type: slice$<i32>]
+// cdb-check:    [len]            : 4 [Type: [...]]
+// cdb-check:    [0]              : 0 [Type: int]
+// cdb-check:    [1]              : 1 [Type: int]
+// cdb-check:    [2]              : 2 [Type: int]
+// cdb-check:    [3]              : 3 [Type: int]
 
 // cdb-command: dx vec,d
-// cdb-check:vec,d [...] : { len=4 } [Type: [...]::Vec<u64, alloc::alloc::Global>]
+// cdb-check:vec,d [...] : { len=4 } [Type: [...]::Vec<u64,alloc::alloc::Global>]
 // cdb-check:    [len]            : 4 [Type: [...]]
 // cdb-check:    [capacity]       : [...] [Type: [...]]
 // cdb-check:    [0]              : 4 [Type: unsigned __int64]
@@ -84,8 +88,7 @@
 // cdb-check:    [3]              : 7 [Type: unsigned __int64]
 
 // cdb-command: dx str_slice
-// cdb-check:str_slice [...]
-// NOTE: While string slices have a .natvis entry that works in VS & VS Code, it fails in CDB
+// cdb-check:str_slice        : "IAMA string slice!" [Type: str]
 
 // cdb-command: dx string
 // cdb-check:string           : "IAMA string!" [Type: [...]::String]
 // cdb-check:    [11]             : 33 '!' [Type: char]
 
 // cdb-command: dx os_string
-// cdb-check:os_string        [Type: [...]::OsString]
-// NOTE: OsString doesn't have a .natvis entry yet.
+// cdb-check:os_string        : "IAMA OS string 😃" [Type: std::ffi::os_str::OsString]
+// cdb-check:    [<Raw View>]     [Type: std::ffi::os_str::OsString]
+// cdb-check:    [chars]          : "IAMA OS string 😃"
 
 // cdb-command: dx some
-// cdb-check:some             : Some [Type: enum$<core::option::Option<i16>>]
+// cdb-check:some             : Some [Type: enum$<core::option::Option<i16> >]
+// 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:none             : None [Type: enum$<core::option::Option<i64> >]
+// 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.
 // cdb-check:some_string      [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
 
+// cdb-command: dx linkedlist
+// cdb-check:linkedlist       : { len=0x2 } [Type: alloc::collections::linked_list::LinkedList<i32>]
+// cdb-check:    [<Raw View>]     [Type: alloc::collections::linked_list::LinkedList<i32>]
+// cdb-check:    [0x0]            : 128 [Type: int]
+// cdb-check:    [0x1]            : 42 [Type: int]
+
+// cdb-command: dx vecdeque
+// cdb-check:vecdeque         : { len=0x2 } [Type: alloc::collections::vec_deque::VecDeque<i32>]
+// cdb-check:    [<Raw View>]     [Type: alloc::collections::vec_deque::VecDeque<i32>]
+// cdb-check:    [len]            : 0x2
+// cdb-check:    [capacity]       : 0x8 [Type: unsigned [...]]
+// cdb-check:    [0x0]            : 90 [Type: int]
+// cdb-check:    [0x1]            : 20 [Type: int]
+
 #![allow(unused_variables)]
+use std::collections::{LinkedList, VecDeque};
 use std::ffi::OsString;
 
-
 fn main() {
 
     // &[]
@@ -145,6 +171,16 @@ fn main() {
 
     let some_string = Some("IAMA optional string!".to_owned());
 
+    // LinkedList
+    let mut linkedlist = LinkedList::new();
+    linkedlist.push_back(42);
+    linkedlist.push_front(128);
+
+    // VecDeque
+    let mut vecdeque = VecDeque::new();
+    vecdeque.push_back(20);
+    vecdeque.push_front(90);
+
     zzz(); // #break
 }
 
diff --git a/src/test/debuginfo/range-types.rs b/src/test/debuginfo/range-types.rs
new file mode 100644 (file)
index 0000000..7362a50
--- /dev/null
@@ -0,0 +1,49 @@
+// Testing the display of range types in cdb.
+
+// cdb-only
+// min-cdb-version: 10.0.18317.1001
+// compile-flags:-g
+
+// === CDB TESTS ==================================================================================
+
+// cdb-command: g
+
+// cdb-command: dx r1,d
+// cdb-check:r1,d             : (3..5) [Type: core::ops::range::Range<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::ops::range::Range<i32>]
+
+// cdb-command: dx r2,d
+// cdb-check:r2,d             : (2..) [Type: core::ops::range::RangeFrom<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::ops::range::RangeFrom<i32>]
+
+// cdb-command: dx r3,d
+// cdb-check:r3,d             : (1..=4) [Type: core::ops::range::RangeInclusive<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::ops::range::RangeInclusive<i32>]
+
+// cdb-command: dx r4,d
+// cdb-check:r4,d             : (..10) [Type: core::ops::range::RangeTo<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::ops::range::RangeTo<i32>]
+
+// cdb-command: dx r5,d
+// cdb-check:r5,d             : (..=3) [Type: core::ops::range::RangeToInclusive<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::ops::range::RangeToInclusive<i32>]
+
+// cdb-command: dx r6,d
+// cdb-check:r6,d             [Type: core::ops::range::RangeFull]
+
+#[allow(unused_variables)]
+
+use std::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeToInclusive};
+
+fn main()
+{
+    let r1 = (3..5);
+    let r2 = (2..);
+    let r3 = (1..=4);
+    let r4 = (..10);
+    let r5 = (..=3);
+    let r6 = (..);
+    zzz(); // #break
+}
+
+fn zzz() { () }
index 87bc79ea794377a6f5e77768a15501e3340f8319..55cddf7c6c6b4d762231e39b34578098fcddee20 100644 (file)
@@ -1,7 +1,8 @@
-// ignore-windows pretty-printers are not loaded
+// pretty-printers are not loaded
 // compile-flags:-g
 
 // min-gdb-version: 8.1
+// min-cdb-version: 10.0.18317.1001
 
 // === GDB TESTS ==================================================================================
 
 // lldb-command:print a
 // lldb-check:[...]$1 = strong=2, weak=1 { data = 42 }
 
+// === CDB TESTS ==================================================================================
+
+// cdb-command:g
+
+// cdb-command:dx r,d
+// cdb-check:r,d              : 42 [Type: alloc::rc::Rc<i32>]
+// cdb-check:    [<Raw View>]     [Type: alloc::rc::Rc<i32>]
+// cdb-check:    [Reference count] : 2 [Type: core::cell::Cell<usize>]
+// cdb-check:    [Weak reference count] : 2 [Type: core::cell::Cell<usize>]
+
+// cdb-command:dx r1,d
+// cdb-check:r1,d             : 42 [Type: alloc::rc::Rc<i32>]
+// cdb-check:    [<Raw View>]     [Type: alloc::rc::Rc<i32>]
+// cdb-check:    [Reference count] : 2 [Type: core::cell::Cell<usize>]
+// cdb-check:    [Weak reference count] : 2 [Type: core::cell::Cell<usize>]
+
+// cdb-command:dx w1,d
+// cdb-check:w1,d             : 42 [Type: alloc::rc::Weak<i32>]
+// cdb-check:    [<Raw View>]     [Type: alloc::rc::Weak<i32>]
+// cdb-check:    [Reference count] : 2 [Type: core::cell::Cell<usize>]
+// cdb-check:    [Weak reference count] : 2 [Type: core::cell::Cell<usize>]
+
+// cdb-command:dx a,d
+// cdb-check:a,d              : 42 [Type: alloc::sync::Arc<i32>]
+// cdb-check:    [<Raw View>]     [Type: alloc::sync::Arc<i32>]
+// cdb-check:    [Reference count] : 2 [Type: core::sync::atomic::AtomicUsize]
+// cdb-check:    [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize]
+
+// cdb-command:dx a1,d
+// cdb-check:a1,d             : 42 [Type: alloc::sync::Arc<i32>]
+// cdb-check:    [<Raw View>]     [Type: alloc::sync::Arc<i32>]
+// cdb-check:    [Reference count] : 2 [Type: core::sync::atomic::AtomicUsize]
+// cdb-check:    [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize]
+
+// cdb-command:dx w2,d
+// cdb-check:w2,d             : 42 [Type: alloc::sync::Weak<i32>]
+// cdb-check:    [<Raw View>]     [Type: alloc::sync::Weak<i32>]
+// cdb-check:    [Reference count] : 2 [Type: core::sync::atomic::AtomicUsize]
+// cdb-check:    [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize]
+
 use std::rc::Rc;
 use std::sync::Arc;
 
diff --git a/src/test/debuginfo/result-types.rs b/src/test/debuginfo/result-types.rs
new file mode 100644 (file)
index 0000000..c0d905a
--- /dev/null
@@ -0,0 +1,28 @@
+// cdb-only
+// min-cdb-version: 10.0.18317.1001
+// compile-flags:-g
+
+// === CDB TESTS ==================================================================================
+
+// cdb-command: g
+
+// cdb-command: dx x,d
+// cdb-check:x,d              : Ok [Type: enum$<core::result::Result<i32,str> >]
+// cdb-check:    [...] __0              : -3 [Type: int]
+
+// cdb-command: dx y
+// cdb-check:y                : Err [Type: enum$<core::result::Result<i32,str> >]
+// cdb-check:    [...] __0              : "Some error message" [Type: str]
+
+fn main()
+{
+    let x: Result<i32, &str> = Ok(-3);
+    assert_eq!(x.is_ok(), true);
+
+    let y: Result<i32, &str> = Err("Some error message");
+    assert_eq!(y.is_ok(), false);
+
+    zzz(); // #break.
+}
+
+fn zzz() { () }
diff --git a/src/test/debuginfo/rwlock-read.rs b/src/test/debuginfo/rwlock-read.rs
new file mode 100644 (file)
index 0000000..e1c10a4
--- /dev/null
@@ -0,0 +1,35 @@
+// Testing the display of RwLock and RwLockReadGuard in cdb.
+
+// cdb-only
+// min-cdb-version: 10.0.18317.1001
+// compile-flags:-g
+
+// === CDB TESTS ==================================================================================
+//
+// cdb-command:g
+//
+// cdb-command:dx l
+// cdb-check:l                [Type: std::sync::rwlock::RwLock<i32>]
+// cdb-check:    [...] poison           [Type: std::sync::poison::Flag]
+// cdb-check:    [...] data             : 0 [Type: core::cell::UnsafeCell<i32>]
+//
+// cdb-command:dx r
+// cdb-check:r                [Type: std::sync::rwlock::RwLockReadGuard<i32>]
+// cdb-check:    [...] lock             : [...] [Type: std::sync::rwlock::RwLock<i32> *]
+//
+// cdb-command:dx r.lock->data,d
+// cdb-check:r.lock->data,d   : 0 [Type: core::cell::UnsafeCell<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::cell::UnsafeCell<i32>]
+
+#[allow(unused_variables)]
+
+use std::sync::RwLock;
+
+fn main()
+{
+    let l = RwLock::new(0);
+    let r = l.read().unwrap();
+    zzz(); // #break
+}
+
+fn zzz() {}
diff --git a/src/test/debuginfo/rwlock-write.rs b/src/test/debuginfo/rwlock-write.rs
new file mode 100644 (file)
index 0000000..8decf54
--- /dev/null
@@ -0,0 +1,27 @@
+// Testing the display of RwLockWriteGuard.
+
+// cdb-only
+// min-cdb-version: 10.0.18317.1001
+// compile-flags:-g
+
+// === CDB TESTS ==================================================================================
+//
+// cdb-command:g
+//
+// cdb-command:dx w
+// cdb-check:w                [Type: std::sync::rwlock::RwLockWriteGuard<i32>]
+// cdb-check:    [...] lock             : [...] [Type: std::sync::rwlock::RwLock<i32> *]
+// cdb-check:    [...] poison           [Type: std::sync::poison::Guard]
+
+#[allow(unused_variables)]
+
+use std::sync::RwLock;
+
+fn main()
+{
+    let l = RwLock::new(0);
+    let w = l.write().unwrap();
+    zzz(); // #break
+}
+
+fn zzz() {}
index b7fcfeef090aa590dc4e41c63a68ba840323a14c..0807cfedce01d844522bc05b2b0dcfaf4d1346c8 100644 (file)
 // cdb-command: g
 
 // cdb-command:dx noPadding8,d
-// cdb-check:noPadding8,d [...]: (-100, 100) [Type: tuple<i8, u8>]
+// cdb-check:noPadding8,d [...]: (-100, 100) [Type: tuple$<i8,u8>]
 // cdb-check:[...][0]              : -100 [Type: [...]]
 // cdb-check:[...][1]              : 100 [Type: [...]]
 // cdb-command:dx noPadding16,d
-// cdb-check:noPadding16,d [...]: (0, 1, 2) [Type: tuple<i16, i16, u16>]
+// cdb-check:noPadding16,d [...]: (0, 1, 2) [Type: tuple$<i16,i16,u16>]
 // cdb-check:[...][0]              : 0 [Type: [...]]
 // cdb-check:[...][1]              : 1 [Type: [...]]
 // cdb-check:[...][2]              : 2 [Type: [...]]
 // cdb-command:dx noPadding32,d
-// cdb-check:noPadding32,d [...]: (3, 4.5[...], 5) [Type: tuple<i32, f32, u32>]
+// cdb-check:noPadding32,d [...]: (3, 4.5[...], 5) [Type: tuple$<i32,f32,u32>]
 // cdb-check:[...][0]              : 3 [Type: [...]]
 // cdb-check:[...][1]              : 4.5[...] [Type: [...]]
 // cdb-check:[...][2]              : 5 [Type: [...]]
 // cdb-command:dx noPadding64,d
-// cdb-check:noPadding64,d [...]: (6, 7.5[...], 8) [Type: tuple<i64, f64, u64>]
+// cdb-check:noPadding64,d [...]: (6, 7.5[...], 8) [Type: tuple$<i64,f64,u64>]
 // cdb-check:[...][0]              : 6 [Type: [...]]
 // cdb-check:[...][1]              : 7.500000 [Type: [...]]
 // cdb-check:[...][2]              : 8 [Type: [...]]
 
 // cdb-command:dx internalPadding1,d
-// cdb-check:internalPadding1,d [...]: (9, 10) [Type: tuple<i16, i32>]
+// cdb-check:internalPadding1,d [...]: (9, 10) [Type: tuple$<i16,i32>]
 // cdb-check:[...][0]              : 9 [Type: short]
 // cdb-check:[...][1]              : 10 [Type: int]
 // cdb-command:dx internalPadding2,d
-// cdb-check:internalPadding2,d [...]: (11, 12, 13, 14) [Type: tuple<i16, i32, u32, u64>]
+// cdb-check:internalPadding2,d [...]: (11, 12, 13, 14) [Type: tuple$<i16,i32,u32,u64>]
 // cdb-check:[...][0]              : 11 [Type: [...]]
 // cdb-check:[...][1]              : 12 [Type: [...]]
 // cdb-check:[...][2]              : 13 [Type: [...]]
 // cdb-check:[...][3]              : 14 [Type: [...]]
 
 // cdb-command:dx paddingAtEnd,d
-// cdb-check:paddingAtEnd,d [...]: (15, 16) [Type: tuple<i32, i16>]
+// cdb-check:paddingAtEnd,d [...]: (15, 16) [Type: tuple$<i32,i16>]
 // cdb-check:[...][0]              : 15 [Type: [...]]
 // cdb-check:[...][1]              : 16 [Type: [...]]
 
diff --git a/src/test/debuginfo/thread.rs b/src/test/debuginfo/thread.rs
new file mode 100644 (file)
index 0000000..531c37a
--- /dev/null
@@ -0,0 +1,31 @@
+// Testing the the display of JoinHandle and Thread in cdb.
+
+// cdb-only
+// min-cdb-version: 10.0.18317.1001
+// compile-flags:-g
+
+// === CDB TESTS ==================================================================================
+//
+// cdb-command:g
+//
+// cdb-command:dx join_handle,d
+// cdb-check:join_handle,d    [Type: std::thread::JoinHandle<tuple$<> >]
+// cdb-check:    [...] __0              [Type: std::thread::JoinInner<tuple$<> >]
+//
+// cdb-command:dx t,d
+// cdb-check:t,d              : [...] [Type: std::thread::Thread *]
+// cdb-check:    [...] inner            : {...} [Type: alloc::sync::Arc<std::thread::Inner>]
+
+use std::thread;
+
+#[allow(unused_variables)]
+fn main()
+{
+    let join_handle = thread::spawn(|| {
+        println!("Initialize a thread");
+    });
+    let t = join_handle.thread();
+    zzz(); // #break
+}
+
+fn zzz() {}
index 0447d8e9ddeb0d8d1caf255cf497b54d5de39cea..578db74e9eeb640b783d152ec8fa1b265660706b 100644 (file)
 // cdb-command: g
 
 // cdb-command:dx no_padding1,d
-// cdb-check:no_padding1,d [...]: ((0, 1), 2, 3) [Type: tuple<tuple<u32, u32>, u32, u32>]
-// cdb-check:[...][0]              : (0, 1) [Type: tuple<u32, u32>]
+// cdb-check:no_padding1,d [...]: ((0, 1), 2, 3) [Type: tuple$<tuple$<u32,u32>,u32,u32>]
+// cdb-check:[...][0]              : (0, 1) [Type: tuple$<u32,u32>]
 // cdb-check:[...][1]              : 2 [Type: [...]]
 // cdb-check:[...][2]              : 3 [Type: [...]]
 // cdb-command:dx no_padding1.__0,d
-// cdb-check:no_padding1.__0,d [...]: (0, 1) [Type: tuple<u32, u32>]
+// cdb-check:no_padding1.__0,d [...]: (0, 1) [Type: tuple$<u32,u32>]
 // cdb-check:[...][0]              : 0 [Type: [...]]
 // cdb-check:[...][1]              : 1 [Type: [...]]
 // cdb-command:dx no_padding2,d
-// cdb-check:no_padding2,d [...]: (4, (5, 6), 7) [Type: tuple<u32, tuple<u32, u32>, u32>]
+// cdb-check:no_padding2,d [...]: (4, (5, 6), 7) [Type: tuple$<u32,tuple$<u32,u32>,u32>]
 // cdb-check:[...][0]              : 4 [Type: [...]]
-// cdb-check:[...][1]              : (5, 6) [Type: tuple<u32, u32>]
+// cdb-check:[...][1]              : (5, 6) [Type: tuple$<u32,u32>]
 // cdb-check:[...][2]              : 7 [Type: [...]]
 // cdb-command:dx no_padding2.__1,d
-// cdb-check:no_padding2.__1,d [...]: (5, 6) [Type: tuple<u32, u32>]
+// cdb-check:no_padding2.__1,d [...]: (5, 6) [Type: tuple$<u32,u32>]
 // cdb-check:[...][0]              : 5 [Type: [...]]
 // cdb-check:[...][1]              : 6 [Type: [...]]
 // cdb-command:dx no_padding3,d
-// cdb-check:no_padding3,d [...]: (8, 9, (10, 11)) [Type: tuple<u32, u32, tuple<u32, u32>>]
+// cdb-check:no_padding3,d [...]: (8, 9, (10, 11)) [Type: tuple$<u32,u32,tuple$<u32,u32> >]
 // cdb-check:[...][0]              : 8 [Type: [...]]
 // cdb-check:[...][1]              : 9 [Type: [...]]
-// cdb-check:[...][2]              : (10, 11) [Type: tuple<u32, u32>]
+// cdb-check:[...][2]              : (10, 11) [Type: tuple$<u32,u32>]
 // cdb-command:dx no_padding3.__2,d
-// cdb-check:no_padding3.__2,d [...]: (10, 11) [Type: tuple<u32, u32>]
+// cdb-check:no_padding3.__2,d [...]: (10, 11) [Type: tuple$<u32,u32>]
 // cdb-check:[...][0]              : 10 [Type: [...]]
 // cdb-check:[...][1]              : 11 [Type: [...]]
 
 // cdb-command:dx internal_padding1,d
-// cdb-check:internal_padding1,d [...]: (12, (13, 14)) [Type: tuple<i16, tuple<i32, i32>>]
+// cdb-check:internal_padding1,d [...]: (12, (13, 14)) [Type: tuple$<i16,tuple$<i32,i32> >]
 // cdb-check:[...][0]              : 12 [Type: [...]]
-// cdb-check:[...][1]              : (13, 14) [Type: tuple<i32, i32>]
+// cdb-check:[...][1]              : (13, 14) [Type: tuple$<i32,i32>]
 // cdb-command:dx internal_padding1.__1,d
-// cdb-check:internal_padding1.__1,d [...]: (13, 14) [Type: tuple<i32, i32>]
+// cdb-check:internal_padding1.__1,d [...]: (13, 14) [Type: tuple$<i32,i32>]
 // cdb-check:[...][0]              : 13 [Type: [...]]
 // cdb-check:[...][1]              : 14 [Type: [...]]
 // cdb-command:dx internal_padding2,d
-// cdb-check:internal_padding2,d [...]: (15, (16, 17)) [Type: tuple<i16, tuple<i16, i32>>]
+// cdb-check:internal_padding2,d [...]: (15, (16, 17)) [Type: tuple$<i16,tuple$<i16,i32> >]
 // cdb-check:[...][0]              : 15 [Type: [...]]
-// cdb-check:[...][1]              : (16, 17) [Type: tuple<i16, i32>]
+// cdb-check:[...][1]              : (16, 17) [Type: tuple$<i16,i32>]
 // cdb-command:dx internal_padding2.__1,d
-// cdb-check:internal_padding2.__1,d [...]: (16, 17) [Type: tuple<i16, i32>]
+// cdb-check:internal_padding2.__1,d [...]: (16, 17) [Type: tuple$<i16,i32>]
 // cdb-check:[...][0]              : 16 [Type: [...]]
 // cdb-check:[...][1]              : 17 [Type: [...]]
 
 // cdb-command:dx padding_at_end1,d
-// cdb-check:padding_at_end1,d [...]: (18, (19, 20)) [Type: tuple<i32, tuple<i32, i16>>]
+// cdb-check:padding_at_end1,d [...]: (18, (19, 20)) [Type: tuple$<i32,tuple$<i32,i16> >]
 // cdb-check:[...][0]              : 18 [Type: [...]]
-// cdb-check:[...][1]              : (19, 20) [Type: tuple<i32, i16>]
+// cdb-check:[...][1]              : (19, 20) [Type: tuple$<i32,i16>]
 // cdb-command:dx padding_at_end1.__1,d
-// cdb-check:padding_at_end1.__1,d [...][Type: tuple<i32, i16>]
+// cdb-check:padding_at_end1.__1,d [...][Type: tuple$<i32,i16>]
 // cdb-check:[...][0]              : 19 [Type: [...]]
 // cdb-check:[...][1]              : 20 [Type: [...]]
 // cdb-command:dx padding_at_end2,d
-// cdb-check:padding_at_end2,d [...]: ((21, 22), 23) [Type: tuple<tuple<i32, i16>, i32>]
-// cdb-check:[...][0]              : (21, 22) [Type: tuple<i32, i16>]
+// cdb-check:padding_at_end2,d [...]: ((21, 22), 23) [Type: tuple$<tuple$<i32,i16>,i32>]
+// cdb-check:[...][0]              : (21, 22) [Type: tuple$<i32,i16>]
 // cdb-check:[...][1]              : 23 [Type: [...]]
 // cdb-command:dx padding_at_end2.__0,d
-// cdb-check:padding_at_end2.__0,d [...]: (21, 22) [Type: tuple<i32, i16>]
+// cdb-check:padding_at_end2.__0,d [...]: (21, 22) [Type: tuple$<i32,i16>]
 // cdb-check:[...][0]              : 21 [Type: [...]]
 // cdb-check:[...][1]              : 22 [Type: [...]]
 
diff --git a/src/test/debuginfo/type-names.cdb.js b/src/test/debuginfo/type-names.cdb.js
new file mode 100644 (file)
index 0000000..8f8b20b
--- /dev/null
@@ -0,0 +1,17 @@
+// Helper functions for running the type-names.rs test under CDB
+
+// CDB exposes an "object model" via JavaScript that allows you to inspect debugging info - in this
+// case we want to ask the object model for the return and parameter types for a local variable
+// that is a function pointer to make sure that we are emitting the function pointer type in such a
+// way that CDB understands how to parse it.
+
+"use strict";
+
+function getFunctionDetails(name)
+{
+    var localVariable = host.currentThread.Stack.Frames[0].LocalVariables[name];
+    var functionPointerType = localVariable.targetType.genericArguments[0];
+    var functionType = functionPointerType.baseType;
+    host.diagnostics.debugLog("Return Type: ", functionType.functionReturnType, "\n");
+    host.diagnostics.debugLog("Parameter Types: ", functionType.functionParameterTypes, "\n");
+}
index cc4a4476d160e13d49ffb8a625ead39a35f24c9e..3497f0afb2cb0bd4447872ef8bb0ceb1f2d40111 100644 (file)
 // ignore-lldb
-// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
+
+// GDB changed the way that it formatted Foreign types
+// min-gdb-version: 9.2
 
 // compile-flags:-g
 
+// === GDB TESTS ===================================================================================
+
 // gdb-command:run
 
 // STRUCTS
 // gdb-command:whatis simple_struct
-// gdbg-check:type = struct Struct1
-// gdbr-check:type = type_names::Struct1
+// gdb-check:type = type_names::Struct1
 
 // gdb-command:whatis generic_struct1
-// gdbg-check:type = struct GenericStruct<type_names::mod1::Struct2, type_names::mod1::mod2::Struct3>
-// gdbr-check:type = type_names::GenericStruct<type_names::mod1::Struct2, type_names::mod1::mod2::Struct3>
+// gdb-check:type = type_names::GenericStruct<type_names::mod1::Struct2, type_names::mod1::mod2::Struct3>
 
 // gdb-command:whatis generic_struct2
-// gdbg-check:type = struct GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> usize>
-// gdbr-check:type = type_names::GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> usize>
+// gdb-check:type = type_names::GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> usize>
 
 // gdb-command:whatis mod_struct
-// gdbg-check:type = struct Struct2
-// gdbr-check:type = type_names::mod1::Struct2
+// gdb-check:type = type_names::mod1::Struct2
 
 // ENUMS
 // gdb-command:whatis simple_enum_1
-// gdbg-check:type = union Enum1
-// gdbr-check:type = type_names::Enum1
+// gdb-check:type = type_names::Enum1
 
 // gdb-command:whatis simple_enum_2
-// gdbg-check:type = union Enum1
-// gdbr-check:type = type_names::Enum1
+// gdb-check:type = type_names::Enum1
 
 // gdb-command:whatis simple_enum_3
-// gdbg-check:type = union Enum2
-// gdbr-check:type = type_names::mod1::Enum2
+// gdb-check:type = type_names::mod1::Enum2
 
 // gdb-command:whatis generic_enum_1
-// gdbg-check:type = union Enum3<type_names::mod1::Struct2>
-// gdbr-check:type = type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>
+// gdb-check:type = type_names::mod1::mod2::Enum3
 
 // gdb-command:whatis generic_enum_2
-// gdbg-check:type = union Enum3<type_names::Struct1>
-// gdbr-check:type = type_names::mod1::mod2::Enum3<type_names::Struct1>
+// gdb-check:type = type_names::mod1::mod2::Enum3
 
 // TUPLES
 // gdb-command:whatis tuple1
-// gdbg-check:type = struct (u32, type_names::Struct1, type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>)
-// gdbr-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>)
+// gdb-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>)
 
 // gdb-command:whatis tuple2
-// gdbg-check:type = struct ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char)
-// gdbr-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char)
+// gdb-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char)
 
 // BOX
 // gdb-command:whatis box1
-// gdbg-check:type = struct (alloc::boxed::Box<f32>, i32)
-// gdbr-check:type = (alloc::boxed::Box<f32>, i32)
+// gdb-check:type = (alloc::boxed::Box<f32, alloc::alloc::Global>, i32)
 
 // gdb-command:whatis box2
-// gdbg-check:type = struct (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>>, i32)
-// gdbr-check:type = (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>>, i32)
+// gdb-check:type = (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>, alloc::alloc::Global>, i32)
 
 // REFERENCES
 // gdb-command:whatis ref1
-// gdbg-check:type = struct (&type_names::Struct1, i32)
-// gdbr-check:type = (&type_names::Struct1, i32)
+// gdb-check:type = (&type_names::Struct1, i32)
 
 // gdb-command:whatis ref2
-// gdbg-check:type = struct (&type_names::GenericStruct<char, type_names::Struct1>, i32)
-// gdbr-check:type = (&type_names::GenericStruct<char, type_names::Struct1>, i32)
+// gdb-check:type = (&type_names::GenericStruct<char, type_names::Struct1>, i32)
 
 // gdb-command:whatis mut_ref1
-// gdbg-check:type = struct (&mut type_names::Struct1, i32)
-// gdbr-check:type = (&mut type_names::Struct1, i32)
+// gdb-check:type = (&mut type_names::Struct1, i32)
 
 // gdb-command:whatis mut_ref2
-// gdbg-check:type = struct (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32)
-// gdbr-check:type = (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32)
+// gdb-check:type = (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32)
 
 // RAW POINTERS
 // gdb-command:whatis mut_ptr1
-// gdbg-check:type = struct (*mut type_names::Struct1, isize)
-// gdbr-check:type = (*mut type_names::Struct1, isize)
+// gdb-check:type = (*mut type_names::Struct1, isize)
 
 // gdb-command:whatis mut_ptr2
-// gdbg-check:type = struct (*mut isize, isize)
-// gdbr-check:type = (*mut isize, isize)
+// gdb-check:type = (*mut isize, isize)
 
 // gdb-command:whatis mut_ptr3
-// gdbg-check:type = struct (*mut type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
-// gdbr-check:type = (*mut type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
+// gdb-check:type = (*mut type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
 
 // gdb-command:whatis const_ptr1
-// gdbg-check:type = struct (*const type_names::Struct1, isize)
-// gdbr-check:type = (*const type_names::Struct1, isize)
+// gdb-check:type = (*const type_names::Struct1, isize)
 
 // gdb-command:whatis const_ptr2
-// gdbg-check:type = struct (*const isize, isize)
-// gdbr-check:type = (*const isize, isize)
+// gdb-check:type = (*const isize, isize)
 
 // gdb-command:whatis const_ptr3
-// gdbg-check:type = struct (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
-// gdbr-check:type = (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
+// gdb-check:type = (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
 
 // VECTORS
 // gdb-command:whatis fixed_size_vec1
-// gdbg-check:type = struct ([type_names::Struct1; 3], i16)
-// gdbr-check:type = ([type_names::Struct1; 3], i16)
+// gdb-check:type = ([type_names::Struct1; 3], i16)
 
 // gdb-command:whatis fixed_size_vec2
-// gdbg-check:type = struct ([usize; 3], i16)
-// gdbr-check:type = ([usize; 3], i16)
+// gdb-check:type = ([usize; 3], i16)
 
 // gdb-command:whatis slice1
-// gdbg-check:type = struct &[usize]
-// gdbr-check:type = &[usize]
+// gdb-check:type = &[usize]
 
 // gdb-command:whatis slice2
-// gdbg-check:type = struct &[type_names::mod1::Enum2]
-// gdbr-check:type = &[type_names::mod1::Enum2]
+// gdb-check:type = &[type_names::mod1::Enum2]
 
 // TRAITS
 // gdb-command:whatis box_trait
-// gdbg-check:type = struct Box<Trait1>
-// gdbr-check:type = type_names::Box<Trait1>
+// gdb-check:type = alloc::boxed::Box<dyn type_names::Trait1, alloc::alloc::Global>
 
 // gdb-command:whatis ref_trait
-// gdbg-check:type = struct &Trait1
-// gdbr-check:type = type_names::&Trait1
+// gdb-check:type = &dyn type_names::Trait1
 
 // gdb-command:whatis mut_ref_trait
-// gdbg-check:type = struct &mut Trait1
-// gdbr-check:type = type_names::&mut Trait1
+// gdb-check:type = &mut dyn type_names::Trait1
 
 // gdb-command:whatis generic_box_trait
-// gdbg-check:type = struct Box<Trait2<i32, type_names::mod1::Struct2>>
-// gdbr-check:type = type_names::Box<Trait2<i32, type_names::mod1::Struct2>>
+// gdb-check:type = alloc::boxed::Box<dyn type_names::Trait2<i32, type_names::mod1::Struct2>, alloc::alloc::Global>
 
 // gdb-command:whatis generic_ref_trait
-// gdbg-check:type = struct &Trait2<type_names::Struct1, type_names::Struct1>
-// gdbr-check:type = type_names::&Trait2<type_names::Struct1, type_names::Struct1>
+// gdb-check:type = &dyn type_names::Trait2<type_names::Struct1, type_names::Struct1>
 
 // gdb-command:whatis generic_mut_ref_trait
-// gdbg-check:type = struct &mut Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
-// gdbr-check:type = type_names::&mut Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
+// gdb-check:type = &mut dyn type_names::Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
+
+// gdb-command:whatis no_principal_trait
+// gdb-check:type = alloc::boxed::Box<(dyn core::marker::Send + core::marker::Sync), alloc::alloc::Global>
+
+// gdb-command:whatis has_associated_type_trait
+// gdb-check:type = &(dyn type_names::Trait3<u32, AssocType=isize> + core::marker::Send)
+
 
 // BARE FUNCTIONS
 // gdb-command:whatis rust_fn
-// gdbg-check:type = struct (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize)
-// gdbr-check:type = (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize)
+// gdb-check:type = (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize)
 
 // gdb-command:whatis extern_c_fn
-// gdbg-check:type = struct (extern "C" fn(isize), usize)
-// gdbr-check:type = (extern "C" fn(isize), usize)
+// gdb-check:type = (extern "C" fn(isize), usize)
 
 // gdb-command:whatis unsafe_fn
-// gdbg-check:type = struct (unsafe fn(core::result::Result<char, f64>), usize)
-// gdbr-check:type = (unsafe fn(core::result::Result<char, f64>), usize)
-
-// gdb-command:whatis extern_stdcall_fn
-// gdbg-check:type = struct (extern "stdcall" fn(), usize)
-// gdbr-check:type = (extern "stdcall" fn(), usize)
+// gdb-check:type = (unsafe fn(core::result::Result<char, f64>), usize)
 
 // gdb-command:whatis rust_fn_with_return_value
-// gdbg-check:type = struct (fn(f64) -> usize, usize)
-// gdbr-check:type = (fn(f64) -> usize, usize)
+// gdb-check:type = (fn(f64) -> usize, usize)
 
 // gdb-command:whatis extern_c_fn_with_return_value
-// gdbg-check:type = struct (extern "C" fn() -> type_names::Struct1, usize)
-// gdbr-check:type = (extern "C" fn() -> type_names::Struct1, usize)
+// gdb-check:type = (extern "C" fn() -> type_names::Struct1, usize)
 
 // gdb-command:whatis unsafe_fn_with_return_value
-// gdbg-check:type = struct (unsafe fn(type_names::GenericStruct<u16, u8>) -> type_names::mod1::Struct2, usize)
-// gdbr-check:type = (unsafe fn(type_names::GenericStruct<u16, u8>) -> type_names::mod1::Struct2, usize)
-
-// gdb-command:whatis extern_stdcall_fn_with_return_value
-// gdbg-check:type = struct (extern "stdcall" fn(alloc::boxed::Box<isize>) -> usize, usize)
-// gdbr-check:type = (extern "stdcall" fn(alloc::boxed::Box<isize>) -> usize, usize)
+// gdb-check:type = (unsafe fn(type_names::GenericStruct<u16, u8>) -> type_names::mod1::Struct2, usize)
 
 // gdb-command:whatis generic_function_int
-// gdbg-check:type = struct (fn(isize) -> isize, usize)
-// gdbr-check:type = (fn(isize) -> isize, usize)
+// gdb-check:type = (fn(isize) -> isize, usize)
 
 // gdb-command:whatis generic_function_struct3
-// gdbg-check:type = struct (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize)
-// gdbr-check:type = (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize)
+// gdb-check:type = (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize)
 
 // gdb-command:whatis variadic_function
-// gdbg-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize)
-// gdbr-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize)
+// gdb-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize)
 
 // CLOSURES
 // gdb-command:whatis closure1
-// gdbg-check:type = struct (closure, usize)
-// gdbr-check:type = (closure, usize)
+// gdb-check:type = (type_names::main::{closure#0}, usize)
 
 // gdb-command:whatis closure2
-// gdbg-check:type = struct (closure, usize)
-// gdbr-check:type = (closure, usize)
+// gdb-check:type = (type_names::main::{closure#1}, usize)
+
+// FOREIGN TYPES
+// gdb-command:whatis foreign1
+// gdb-check:type = *mut ForeignType1
+
+// gdb-command:whatis foreign2
+// gdb-check:type = *mut ForeignType2
+
+// === CDB TESTS ==================================================================================
+
+// cdb-command: g
+
+// STRUCTS
+// 0-sized structs appear to be optimized away in some cases, so only check the structs that do
+// actually appear.
+// cdb-command:dv /t *_struct
+// cdb-check:struct type_names::GenericStruct<enum$<type_names::mod1::Enum2>,f64> mut_generic_struct = [...]
+
+// ENUMS
+// cdb-command:dv /t *_enum_*
+// cdb-check:union enum$<type_names::Enum1> simple_enum_1 = [...]
+// cdb-check:union enum$<type_names::Enum1> simple_enum_2 = [...]
+// cdb-check:type_names::mod1::Enum2 simple_enum_3 = [...]
+// cdb-check:type_names::mod1::mod2::Enum3 generic_enum_1 = [...]
+// cdb-check:type_names::mod1::mod2::Enum3 generic_enum_2 = [...]
+
+// TUPLES
+// cdb-command:dv /t tuple*
+// cdb-check:struct tuple$<u32,type_names::Struct1,enum$<type_names::mod1::mod2::Enum3<type_names::mod1::Struct2> > > tuple1 = [...]
+// cdb-check:struct tuple$<tuple$<type_names::Struct1,type_names::mod1::mod2::Struct3>,enum$<type_names::mod1::Enum2>,char> tuple2 = [...]
+
+// BOX
+// cdb-command:dv /t box*
+// cdb-check:struct tuple$<alloc::boxed::Box<f32,alloc::alloc::Global>,i32> box1 = [...]
+// cdb-check:struct tuple$<alloc::boxed::Box<enum$<type_names::mod1::mod2::Enum3<f32> >,alloc::alloc::Global>,i32> box2 = [...]
+
+// REFERENCES
+// cdb-command:dv /t *ref*
+// cdb-check:struct tuple$<ref$<type_names::Struct1>,i32> ref1 = [...]
+// cdb-check:struct tuple$<ref$<type_names::GenericStruct<char,type_names::Struct1> >,i32> ref2 = [...]
+// cdb-check:struct tuple$<ref_mut$<type_names::Struct1>,i32> mut_ref1 = [...]
+// cdb-check:struct tuple$<ref_mut$<type_names::GenericStruct<enum$<type_names::mod1::Enum2>,f64> >,i32> mut_ref2 = [...]
+
+// RAW POINTERS
+// cdb-command:dv /t *_ptr*
+// cdb-check:struct tuple$<ptr_mut$<type_names::Struct1>,isize> mut_ptr1 = [...]
+// cdb-check:struct tuple$<ptr_mut$<isize>,isize> mut_ptr2 = [...]
+// cdb-check:struct tuple$<ptr_mut$<enum$<type_names::mod1::mod2::Enum3<type_names::Struct1> > >,isize> mut_ptr3 = [...]
+// cdb-check:struct tuple$<ptr_const$<type_names::Struct1>,isize> const_ptr1 = [...]
+// cdb-check:struct tuple$<ptr_const$<isize>,isize> const_ptr2 = [...]
+// cdb-check:struct tuple$<ptr_const$<enum$<type_names::mod1::mod2::Enum3<type_names::Struct1> > >,isize> const_ptr3 = [...]
+
+// VECTORS
+// cdb-command:dv /t *vec*
+// cdb-check:struct tuple$<array$<type_names::Struct1,3>,i16> fixed_size_vec1 = [...]
+// cdb-check:struct tuple$<array$<usize,3>,i16> fixed_size_vec2 = [...]
+// cdb-check:struct alloc::vec::Vec<usize,alloc::alloc::Global> vec1 = [...]
+// cdb-check:struct alloc::vec::Vec<enum$<type_names::mod1::Enum2>,alloc::alloc::Global> vec2 = [...]
+// cdb-command:dv /t slice*
+// cdb-check:struct slice$<usize> slice1 = [...]
+// cdb-check:struct slice$<enum$<type_names::mod1::Enum2> > slice2 = [...]
+
+// TRAITS
+// cdb-command:dv /t *_trait
+// cdb-check:struct ref_mut$<dyn$<type_names::Trait2<type_names::mod1::mod2::Struct3,type_names::GenericStruct<usize,isize> > > > generic_mut_ref_trait = [...]
+// cdb-check:struct ref$<dyn$<type_names::Trait2<type_names::Struct1,type_names::Struct1> > > generic_ref_trait = [...]
+// cdb-check:struct alloc::boxed::Box<dyn$<type_names::Trait2<i32,type_names::mod1::Struct2> >,alloc::alloc::Global> generic_box_trait = [...]
+// cdb-check:struct alloc::boxed::Box<dyn$<type_names::Trait1>,alloc::alloc::Global> box_trait = [...]
+// cdb-check:struct ref$<dyn$<type_names::Trait1> > ref_trait = [...]
+// cdb-check:struct ref_mut$<dyn$<type_names::Trait1> > mut_ref_trait = [...]
+// cdb-check:struct alloc::boxed::Box<dyn$<core::marker::Send,core::marker::Sync>,alloc::alloc::Global> no_principal_trait = [...]
+// cdb-check:struct ref$<dyn$<type_names::Trait3<u32,assoc$<AssocType,isize> >,core::marker::Send> > has_associated_type_trait = struct ref$<dyn$<type_names::Trait3<u32,assoc$<AssocType,isize> >,core::marker::Send> >
+
+// BARE FUNCTIONS
+// cdb-command:dv /t *_fn*
+// cdb-check:struct tuple$<type_names::mod1::Struct2 (*)(type_names::GenericStruct<u16,u8>),usize> unsafe_fn_with_return_value = [...]
+// cdb-check:struct tuple$<type_names::Struct1 (*)(),usize> extern_c_fn_with_return_value = [...]
+// cdb-check:struct tuple$<usize (*)(f64),usize> rust_fn_with_return_value = [...]
+// cdb-check:struct tuple$<void (*)(enum$<core::result::Result<char,f64> >),usize> unsafe_fn = [...]
+// cdb-check:struct tuple$<void (*)(isize),usize> extern_c_fn = [...]
+// cdb-check:struct tuple$<void (*)(enum$<core::option::Option<isize> >,enum$<core::option::Option<ref$<type_names::mod1::Struct2> >, 1, [...], Some>),usize> rust_fn = [...]
+// cdb-command:dv /t *_function*
+// cdb-check:struct tuple$<isize (*)(ptr_const$<u8>, ...),usize> variadic_function = [...]
+// cdb-check:struct tuple$<type_names::mod1::mod2::Struct3 (*)(type_names::mod1::mod2::Struct3),usize> generic_function_struct3 = [...]
+// cdb-check:struct tuple$<isize (*)(isize),usize> generic_function_int = [...]
+// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn")
+// cdb-check:Return Type: void
+// cdb-check:Parameter Types: enum$<core::option::Option<isize> >,enum$<core::option::Option<ref$<type_names::mod1::Struct2> >, 1, [...], Some>
+// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn_with_return_value")
+// cdb-check:Return Type: usize
+// cdb-check:Parameter Types: f64
+// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("extern_c_fn_with_return_value")
+// cdb-check:Return Type: type_names::Struct1
+// cdb-check:Parameter Types:
+
+// CLOSURES
+// cdb-command:dv /t closure*
+// cdb-check:struct tuple$<type_names::main::closure$1,usize> closure2 = [...]
+// cdb-check:struct tuple$<type_names::main::closure$0,usize> closure1 = [...]
+
+// FOREIGN TYPES
+// cdb-command:dv /t foreign*
+// cdb-check:struct ForeignType2 * foreign2 = [...]
+// cdb-check:struct ForeignType1 * foreign1 = [...]
 
 #![feature(box_syntax)]
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
+#![feature(extern_types)]
 
 use self::Enum1::{Variant1, Variant2};
 use std::marker::PhantomData;
@@ -216,6 +280,8 @@ enum Enum1 {
     Variant2(isize),
 }
 
+extern { type ForeignType1; }
+
 mod mod1 {
     pub use self::Enum2::{Variant1, Variant2};
     pub struct Struct2;
@@ -234,6 +300,8 @@ mod mod1 {
             Variant2(T),
         }
     }
+
+    extern { pub type ForeignType2; }
 }
 
 trait Trait1 {
@@ -242,14 +310,20 @@ trait Trait1 {
 trait Trait2<T1, T2> {
     fn dummy(&self, _: T1, _: T2) {}
 }
+trait Trait3<T> {
+    type AssocType;
+    fn dummy(&self) -> T { panic!() }
+}
 
 impl Trait1 for isize {}
 impl<T1, T2> Trait2<T1, T2> for isize {}
+impl<T> Trait3<T> for isize {
+    type AssocType = isize;
+}
 
 fn rust_fn(_: Option<isize>, _: Option<&mod1::Struct2>) {}
 extern "C" fn extern_c_fn(_: isize) {}
 unsafe fn unsafe_fn(_: Result<char, f64>) {}
-extern "stdcall" fn extern_stdcall_fn() {}
 
 fn rust_fn_with_return_value(_: f64) -> usize {
     4
@@ -260,9 +334,6 @@ extern "C" fn extern_c_fn_with_return_value() -> Struct1 {
 unsafe fn unsafe_fn_with_return_value(_: GenericStruct<u16, u8>) -> mod1::Struct2 {
     mod1::Struct2
 }
-extern "stdcall" fn extern_stdcall_fn_with_return_value(_: Box<isize>) -> usize {
-    0
-}
 
 fn generic_function<T>(x: T) -> T {
     x
@@ -333,28 +404,28 @@ fn main() {
     let slice2 = &*vec2;
 
     // Trait Objects
-    let box_trait = (box 0_isize) as Box<Trait1>;
-    let ref_trait = &0_isize as &Trait1;
+    let box_trait = (box 0_isize) as Box<dyn Trait1>;
+    let ref_trait = &0_isize as &dyn Trait1;
     let mut mut_int1 = 0_isize;
-    let mut_ref_trait = (&mut mut_int1) as &mut Trait1;
+    let mut_ref_trait = (&mut mut_int1) as &mut dyn Trait1;
+    let no_principal_trait = (box 0_isize) as Box<(dyn Send + Sync)>;
+    let has_associated_type_trait = &0_isize as &(dyn Trait3<u32, AssocType = isize> + Send);
 
-    let generic_box_trait = (box 0_isize) as Box<Trait2<i32, mod1::Struct2>>;
-    let generic_ref_trait = (&0_isize) as &Trait2<Struct1, Struct1>;
+    let generic_box_trait = (box 0_isize) as Box<dyn Trait2<i32, mod1::Struct2>>;
+    let generic_ref_trait = (&0_isize) as &dyn Trait2<Struct1, Struct1>;
 
     let mut generic_mut_ref_trait_impl = 0_isize;
     let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl)
-        as &mut Trait2<mod1::mod2::Struct3, GenericStruct<usize, isize>>;
+        as &mut dyn Trait2<mod1::mod2::Struct3, GenericStruct<usize, isize>>;
 
     // Bare Functions
     let rust_fn = (rust_fn, 0_usize);
     let extern_c_fn = (extern_c_fn, 0_usize);
     let unsafe_fn = (unsafe_fn, 0_usize);
-    let extern_stdcall_fn = (extern_stdcall_fn, 0_usize);
 
     let rust_fn_with_return_value = (rust_fn_with_return_value, 0_usize);
     let extern_c_fn_with_return_value = (extern_c_fn_with_return_value, 0_usize);
     let unsafe_fn_with_return_value = (unsafe_fn_with_return_value, 0_usize);
-    let extern_stdcall_fn_with_return_value = (extern_stdcall_fn_with_return_value, 0_usize);
 
     let generic_function_int = (generic_function::<isize>, 0_usize);
     let generic_function_struct3 = (generic_function::<mod1::mod2::Struct3>, 0_usize);
@@ -370,6 +441,10 @@ fn main() {
     let closure1 = (|x: isize| {}, 0_usize);
     let closure2 = (|x: i8, y: f32| (x as f32) + y, 0_usize);
 
+    // Foreign Types
+    let foreign1 = unsafe{ 0 as *const ForeignType1 };
+    let foreign2 = unsafe{ 0 as *const mod1::ForeignType2 };
+
     zzz(); // #break
 }
 
index 695cdc4f41fa30f53361bebd46fc9bc46dd95a8b..a2778fc6090d2bf77716bc59817bd59ed43f2848 100644 (file)
 // cdb-command: dx closure_local
 // cdb-check:closure_local    : 8 [Type: [...]]
 // cdb-command: dx nested_closure
-// cdb-check:nested_closure   [Type: var_captured_in_nested_closure::main::{{closure}}::closure-0]
+// cdb-check:nested_closure   [Type: var_captured_in_nested_closure::main::closure$0::closure$0]
 
 // cdb-command: g
 
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 3c56fce3f0a063a788d1d18b0bb96b483a24414d..e22adae815c020816e7c9a1d740b4d45d6ae23ed 100644 (file)
@@ -16,10 +16,10 @@ fn main() -> () {
         _1 = const b"foo";               // scope 0 at $DIR/byte_slice.rs:5:13: 5:19
                                          // ty::Const
                                          // + ty: &[u8; 3]
-                                         // + val: Value(Scalar(alloc0))
+                                         // + val: Value(Scalar(alloc1))
                                          // mir::Constant
                                          // + span: $DIR/byte_slice.rs:5:13: 5:19
-                                         // + literal: Const { ty: &[u8; 3], val: Value(Scalar(alloc0)) }
+                                         // + literal: Const { ty: &[u8; 3], val: Value(Scalar(alloc1)) }
         StorageLive(_2);                 // scope 1 at $DIR/byte_slice.rs:6:9: 6:10
         _2 = [const 5_u8, const 120_u8]; // scope 1 at $DIR/byte_slice.rs:6:13: 6:24
         _0 = const ();                   // scope 0 at $DIR/byte_slice.rs:4:11: 7:2
@@ -29,6 +29,6 @@ fn main() -> () {
     }
 }
 
-alloc0 (size: 3, align: 1) {
+alloc1 (size: 3, align: 1) {
     66 6f 6f                                        │ foo
 }
index a046539665b93a970aae82dcafbbbdfe3b40680c..8e02dca4fb8b6541694c546117efd7479b41ed99 100644 (file)
@@ -8,13 +8,13 @@ fn main() -> () {
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/const_allocation.rs:8:5: 8:8
         StorageLive(_2);                 // scope 0 at $DIR/const_allocation.rs:8:5: 8:8
-        _2 = const {alloc0: &&[(Option<i32>, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:8:5: 8:8
+        _2 = const {alloc1: &&[(Option<i32>, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:8:5: 8:8
                                          // ty::Const
                                          // + ty: &&[(std::option::Option<i32>, &[&str])]
-                                         // + val: Value(Scalar(alloc0))
+                                         // + val: Value(Scalar(alloc1))
                                          // mir::Constant
                                          // + span: $DIR/const_allocation.rs:8:5: 8:8
-                                         // + literal: Const { ty: &&[(std::option::Option<i32>, &[&str])], val: Value(Scalar(alloc0)) }
+                                         // + literal: Const { ty: &&[(std::option::Option<i32>, &[&str])], val: Value(Scalar(alloc1)) }
         _1 = (*_2);                      // scope 0 at $DIR/const_allocation.rs:8:5: 8:8
         StorageDead(_2);                 // scope 0 at $DIR/const_allocation.rs:8:8: 8:9
         StorageDead(_1);                 // scope 0 at $DIR/const_allocation.rs:8:8: 8:9
@@ -23,43 +23,43 @@ fn main() -> () {
     }
 }
 
-alloc0 (static: FOO, size: 8, align: 4) {
-    ╾─alloc17─╼ 03 00 00 00                         │ ╾──╼....
+alloc1 (static: FOO, size: 8, align: 4) {
+    ╾─alloc18─╼ 03 00 00 00                         │ ╾──╼....
 }
 
-alloc17 (size: 48, align: 4) {
-    0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc4──╼ 00 00 00 00 │ ....░░░░╾──╼....
-    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 02 00 00 00 │ ....░░░░╾──╼....
-    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc13─╼ 03 00 00 00 │ ....*...╾──╼....
+alloc18 (size: 48, align: 4) {
+    0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc5──╼ 00 00 00 00 │ ....░░░░╾──╼....
+    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc9──╼ 02 00 00 00 │ ....░░░░╾──╼....
+    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ....*...╾──╼....
 }
 
-alloc4 (size: 0, align: 4) {}
+alloc5 (size: 0, align: 4) {}
 
-alloc8 (size: 16, align: 4) {
-    ╾─alloc7──╼ 03 00 00 00 ╾─alloc9──╼ 03 00 00 00 │ ╾──╼....╾──╼....
+alloc9 (size: 16, align: 4) {
+    ╾─alloc8──╼ 03 00 00 00 ╾─alloc10─╼ 03 00 00 00 │ ╾──╼....╾──╼....
 }
 
-alloc7 (size: 3, align: 1) {
+alloc8 (size: 3, align: 1) {
     66 6f 6f                                        │ foo
 }
 
-alloc9 (size: 3, align: 1) {
+alloc10 (size: 3, align: 1) {
     62 61 72                                        │ bar
 }
 
-alloc13 (size: 24, align: 4) {
-    0x00 │ ╾─alloc12─╼ 03 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ╾──╼....╾──╼....
-    0x10 │ ╾─alloc15─╼ 04 00 00 00                         │ ╾──╼....
+alloc14 (size: 24, align: 4) {
+    0x00 │ ╾─alloc13─╼ 03 00 00 00 ╾─alloc15─╼ 03 00 00 00 │ ╾──╼....╾──╼....
+    0x10 │ ╾─alloc16─╼ 04 00 00 00                         │ ╾──╼....
 }
 
-alloc12 (size: 3, align: 1) {
+alloc13 (size: 3, align: 1) {
     6d 65 68                                        │ meh
 }
 
-alloc14 (size: 3, align: 1) {
+alloc15 (size: 3, align: 1) {
     6d 6f 70                                        │ mop
 }
 
-alloc15 (size: 4, align: 1) {
+alloc16 (size: 4, align: 1) {
     6d c3 b6 70                                     │ m..p
 }
index 23859439208febc315a1647afa12fb23c5d0ecab..88cdbda2fae36cbd28ccfa25c9cb86dc2914a5c4 100644 (file)
@@ -8,13 +8,13 @@ fn main() -> () {
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/const_allocation.rs:8:5: 8:8
         StorageLive(_2);                 // scope 0 at $DIR/const_allocation.rs:8:5: 8:8
-        _2 = const {alloc0: &&[(Option<i32>, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:8:5: 8:8
+        _2 = const {alloc1: &&[(Option<i32>, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:8:5: 8:8
                                          // ty::Const
                                          // + ty: &&[(std::option::Option<i32>, &[&str])]
-                                         // + val: Value(Scalar(alloc0))
+                                         // + val: Value(Scalar(alloc1))
                                          // mir::Constant
                                          // + span: $DIR/const_allocation.rs:8:5: 8:8
-                                         // + literal: Const { ty: &&[(std::option::Option<i32>, &[&str])], val: Value(Scalar(alloc0)) }
+                                         // + literal: Const { ty: &&[(std::option::Option<i32>, &[&str])], val: Value(Scalar(alloc1)) }
         _1 = (*_2);                      // scope 0 at $DIR/const_allocation.rs:8:5: 8:8
         StorageDead(_2);                 // scope 0 at $DIR/const_allocation.rs:8:8: 8:9
         StorageDead(_1);                 // scope 0 at $DIR/const_allocation.rs:8:8: 8:9
@@ -23,47 +23,47 @@ fn main() -> () {
     }
 }
 
-alloc0 (static: FOO, size: 16, align: 8) {
-    ╾───────alloc17───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc1 (static: FOO, size: 16, align: 8) {
+    ╾───────alloc18───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc17 (size: 72, align: 8) {
-    0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc4────────╼ │ ....░░░░╾──────╼
+alloc18 (size: 72, align: 8) {
+    0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc5────────╼ │ ....░░░░╾──────╼
     0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
-    0x20 │ ╾───────alloc8────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc13───────╼ │ ....*...╾──────╼
+    0x20 │ ╾───────alloc9────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc14───────╼ │ ....*...╾──────╼
     0x40 │ 03 00 00 00 00 00 00 00                         │ ........
 }
 
-alloc4 (size: 0, align: 8) {}
+alloc5 (size: 0, align: 8) {}
 
-alloc8 (size: 32, align: 8) {
-    0x00 │ ╾───────alloc7────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x10 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc9 (size: 32, align: 8) {
+    0x00 │ ╾───────alloc8────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x10 │ ╾───────alloc10───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc7 (size: 3, align: 1) {
+alloc8 (size: 3, align: 1) {
     66 6f 6f                                        │ foo
 }
 
-alloc9 (size: 3, align: 1) {
+alloc10 (size: 3, align: 1) {
     62 61 72                                        │ bar
 }
 
-alloc13 (size: 48, align: 8) {
-    0x00 │ ╾───────alloc12───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x10 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x20 │ ╾───────alloc15───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc14 (size: 48, align: 8) {
+    0x00 │ ╾───────alloc13───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x10 │ ╾───────alloc15───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x20 │ ╾───────alloc16───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc12 (size: 3, align: 1) {
+alloc13 (size: 3, align: 1) {
     6d 65 68                                        │ meh
 }
 
-alloc14 (size: 3, align: 1) {
+alloc15 (size: 3, align: 1) {
     6d 6f 70                                        │ mop
 }
 
-alloc15 (size: 4, align: 1) {
+alloc16 (size: 4, align: 1) {
     6d c3 b6 70                                     │ m..p
 }
index 1e4bd4ba914d59615a4785aa3c01ed17b51d16ed..059b721f5bb6332d0d8ac8e70e609ae0e68e9fa5 100644 (file)
@@ -8,13 +8,13 @@ fn main() -> () {
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8
         StorageLive(_2);                 // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8
-        _2 = const {alloc0: &&[(Option<i32>, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8
+        _2 = const {alloc1: &&[(Option<i32>, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8
                                          // ty::Const
                                          // + ty: &&[(std::option::Option<i32>, &[&u8])]
-                                         // + val: Value(Scalar(alloc0))
+                                         // + val: Value(Scalar(alloc1))
                                          // mir::Constant
                                          // + span: $DIR/const_allocation2.rs:5:5: 5:8
-                                         // + literal: Const { ty: &&[(std::option::Option<i32>, &[&u8])], val: Value(Scalar(alloc0)) }
+                                         // + literal: Const { ty: &&[(std::option::Option<i32>, &[&u8])], val: Value(Scalar(alloc1)) }
         _1 = (*_2);                      // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8
         StorageDead(_2);                 // scope 0 at $DIR/const_allocation2.rs:5:8: 5:9
         StorageDead(_1);                 // scope 0 at $DIR/const_allocation2.rs:5:8: 5:9
@@ -23,42 +23,42 @@ fn main() -> () {
     }
 }
 
-alloc0 (static: FOO, size: 8, align: 4) {
-    ╾─alloc27─╼ 03 00 00 00                         │ ╾──╼....
+alloc1 (static: FOO, size: 8, align: 4) {
+    ╾─alloc28─╼ 03 00 00 00                         │ ╾──╼....
 }
 
-alloc27 (size: 48, align: 4) {
-    0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc12─╼ 00 00 00 00 │ ....░░░░╾──╼....
-    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc17─╼ 02 00 00 00 │ ....░░░░╾──╼....
-    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc25─╼ 03 00 00 00 │ ....*...╾──╼....
+alloc28 (size: 48, align: 4) {
+    0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc13─╼ 00 00 00 00 │ ....░░░░╾──╼....
+    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc18─╼ 02 00 00 00 │ ....░░░░╾──╼....
+    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc26─╼ 03 00 00 00 │ ....*...╾──╼....
 }
 
-alloc12 (size: 0, align: 4) {}
+alloc13 (size: 0, align: 4) {}
 
-alloc17 (size: 8, align: 4) {
-    ╾─alloc15─╼ ╾─alloc16─╼                         │ ╾──╼╾──╼
+alloc18 (size: 8, align: 4) {
+    ╾─alloc16─╼ ╾─alloc17─╼                         │ ╾──╼╾──╼
 }
 
-alloc15 (size: 1, align: 1) {
+alloc16 (size: 1, align: 1) {
     05                                              │ .
 }
 
-alloc16 (size: 1, align: 1) {
+alloc17 (size: 1, align: 1) {
     06                                              │ .
 }
 
-alloc25 (size: 12, align: 4) {
-    ╾─a21+0x3─╼ ╾─alloc22─╼ ╾─a24+0x2─╼             │ ╾──╼╾──╼╾──╼
+alloc26 (size: 12, align: 4) {
+    ╾─a22+0x3─╼ ╾─alloc23─╼ ╾─a25+0x2─╼             │ ╾──╼╾──╼╾──╼
 }
 
-alloc21 (size: 4, align: 1) {
+alloc22 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
 
-alloc22 (size: 1, align: 1) {
+alloc23 (size: 1, align: 1) {
     2a                                              │ *
 }
 
-alloc24 (size: 4, align: 1) {
+alloc25 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
index f943beced31090558e86e41e9435269bdd23f720..d6a97917d6226c7f5aece75f866cbe85a12ca581 100644 (file)
@@ -8,13 +8,13 @@ fn main() -> () {
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8
         StorageLive(_2);                 // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8
-        _2 = const {alloc0: &&[(Option<i32>, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8
+        _2 = const {alloc1: &&[(Option<i32>, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8
                                          // ty::Const
                                          // + ty: &&[(std::option::Option<i32>, &[&u8])]
-                                         // + val: Value(Scalar(alloc0))
+                                         // + val: Value(Scalar(alloc1))
                                          // mir::Constant
                                          // + span: $DIR/const_allocation2.rs:5:5: 5:8
-                                         // + literal: Const { ty: &&[(std::option::Option<i32>, &[&u8])], val: Value(Scalar(alloc0)) }
+                                         // + literal: Const { ty: &&[(std::option::Option<i32>, &[&u8])], val: Value(Scalar(alloc1)) }
         _1 = (*_2);                      // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8
         StorageDead(_2);                 // scope 0 at $DIR/const_allocation2.rs:5:8: 5:9
         StorageDead(_1);                 // scope 0 at $DIR/const_allocation2.rs:5:8: 5:9
@@ -23,45 +23,45 @@ fn main() -> () {
     }
 }
 
-alloc0 (static: FOO, size: 16, align: 8) {
-    ╾───────alloc27───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc1 (static: FOO, size: 16, align: 8) {
+    ╾───────alloc28───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc27 (size: 72, align: 8) {
-    0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc12───────╼ │ ....░░░░╾──────╼
+alloc28 (size: 72, align: 8) {
+    0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc13───────╼ │ ....░░░░╾──────╼
     0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
-    0x20 │ ╾───────alloc17───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc25───────╼ │ ....*...╾──────╼
+    0x20 │ ╾───────alloc18───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc26───────╼ │ ....*...╾──────╼
     0x40 │ 03 00 00 00 00 00 00 00                         │ ........
 }
 
-alloc12 (size: 0, align: 8) {}
+alloc13 (size: 0, align: 8) {}
 
-alloc17 (size: 16, align: 8) {
-    ╾───────alloc15───────╼ ╾───────alloc16───────╼ │ ╾──────╼╾──────╼
+alloc18 (size: 16, align: 8) {
+    ╾───────alloc16───────╼ ╾───────alloc17───────╼ │ ╾──────╼╾──────╼
 }
 
-alloc15 (size: 1, align: 1) {
+alloc16 (size: 1, align: 1) {
     05                                              │ .
 }
 
-alloc16 (size: 1, align: 1) {
+alloc17 (size: 1, align: 1) {
     06                                              │ .
 }
 
-alloc25 (size: 24, align: 8) {
-    0x00 │ ╾─────alloc21+0x3─────╼ ╾───────alloc22───────╼ │ ╾──────╼╾──────╼
-    0x10 │ ╾─────alloc24+0x2─────╼                         │ ╾──────╼
+alloc26 (size: 24, align: 8) {
+    0x00 │ ╾─────alloc22+0x3─────╼ ╾───────alloc23───────╼ │ ╾──────╼╾──────╼
+    0x10 │ ╾─────alloc25+0x2─────╼                         │ ╾──────╼
 }
 
-alloc21 (size: 4, align: 1) {
+alloc22 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
 
-alloc22 (size: 1, align: 1) {
+alloc23 (size: 1, align: 1) {
     2a                                              │ *
 }
 
-alloc24 (size: 4, align: 1) {
+alloc25 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
index 5c95afb586ff2a1a7170dada24fc95ecf93cf79c..32000340dcebfc35a4bd434ea0fe3a2c7cb393e6 100644 (file)
@@ -8,13 +8,13 @@ fn main() -> () {
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8
         StorageLive(_2);                 // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8
-        _2 = const {alloc0: &&Packed};   // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8
+        _2 = const {alloc1: &&Packed};   // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8
                                          // ty::Const
                                          // + ty: &&Packed
-                                         // + val: Value(Scalar(alloc0))
+                                         // + val: Value(Scalar(alloc1))
                                          // mir::Constant
                                          // + span: $DIR/const_allocation3.rs:5:5: 5:8
-                                         // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc0)) }
+                                         // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc1)) }
         _1 = (*_2);                      // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8
         StorageDead(_2);                 // scope 0 at $DIR/const_allocation3.rs:5:8: 5:9
         StorageDead(_1);                 // scope 0 at $DIR/const_allocation3.rs:5:8: 5:9
@@ -23,31 +23,31 @@ fn main() -> () {
     }
 }
 
-alloc0 (static: FOO, size: 4, align: 4) {
-    ╾─alloc10─╼                                     │ ╾──╼
+alloc1 (static: FOO, size: 4, align: 4) {
+    ╾─alloc11─╼                                     │ ╾──╼
 }
 
-alloc10 (size: 168, align: 1) {
+alloc11 (size: 168, align: 1) {
     0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................
-    0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc5──╼ │ ............╾──╼
+    0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc6──╼ │ ............╾──╼
     0x20 │ 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x50 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
-    0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc7──╼ 00 00 │ ..........╾──╼..
-    0x90 │ ╾─a8+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............
+    0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc8──╼ 00 00 │ ..........╾──╼..
+    0x90 │ ╾─a9+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............
     0xa0 │ 00 00 00 00 00 00 00 00                         │ ........
 }
 
-alloc5 (size: 4, align: 4) {
+alloc6 (size: 4, align: 4) {
     2a 00 00 00                                     │ *...
 }
 
-alloc7 (fn: main)
+alloc8 (fn: main)
 
-alloc8 (size: 100, align: 1) {
+alloc9 (size: 100, align: 1) {
     0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
index 3d1858de22e75695a7677724302f1413536147d6..cac882333aeb94debb5ea1a446f5bb613d8b7643 100644 (file)
@@ -8,13 +8,13 @@ fn main() -> () {
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8
         StorageLive(_2);                 // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8
-        _2 = const {alloc0: &&Packed};   // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8
+        _2 = const {alloc1: &&Packed};   // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8
                                          // ty::Const
                                          // + ty: &&Packed
-                                         // + val: Value(Scalar(alloc0))
+                                         // + val: Value(Scalar(alloc1))
                                          // mir::Constant
                                          // + span: $DIR/const_allocation3.rs:5:5: 5:8
-                                         // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc0)) }
+                                         // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc1)) }
         _1 = (*_2);                      // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8
         StorageDead(_2);                 // scope 0 at $DIR/const_allocation3.rs:5:8: 5:9
         StorageDead(_1);                 // scope 0 at $DIR/const_allocation3.rs:5:8: 5:9
@@ -23,13 +23,13 @@ fn main() -> () {
     }
 }
 
-alloc0 (static: FOO, size: 8, align: 8) {
-    ╾───────alloc10───────╼                         │ ╾──────╼
+alloc1 (static: FOO, size: 8, align: 8) {
+    ╾───────alloc11───────╼                         │ ╾──────╼
 }
 
-alloc10 (size: 180, align: 1) {
+alloc11 (size: 180, align: 1) {
     0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................
-    0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc5── │ ............╾───
+    0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc6── │ ............╾───
     0x20 │ ──────────╼ 01 ef cd ab 00 00 00 00 00 00 00 00 │ ───╼............
     0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
@@ -37,18 +37,18 @@ alloc10 (size: 180, align: 1) {
     0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x80 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ╾──── │ ..............╾─
-    0x90 │ ─────alloc7─────╼ 00 00 ╾─────alloc8+0x63─────╼ │ ─────╼..╾──────╼
+    0x90 │ ─────alloc8─────╼ 00 00 ╾─────alloc9+0x63─────╼ │ ─────╼..╾──────╼
     0xa0 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0xb0 │ 00 00 00 00                                     │ ....
 }
 
-alloc5 (size: 4, align: 4) {
+alloc6 (size: 4, align: 4) {
     2a 00 00 00                                     │ *...
 }
 
-alloc7 (fn: main)
+alloc8 (fn: main)
 
-alloc8 (size: 100, align: 1) {
+alloc9 (size: 100, align: 1) {
     0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
index 2497c553e69702955d98921a960a796838e8614f..a64c960b9f716bf27f739eb6b3937c82f20fe164 100644 (file)
@@ -7,13 +7,13 @@ promoted[0] in BAR: &[&i32; 1] = {
     let mut _3: &i32;                    // in scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34
 
     bb0: {
-        _3 = const {alloc0: &i32};       // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34
+        _3 = const {alloc1: &i32};       // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34
                                          // ty::Const
                                          // + ty: &i32
-                                         // + val: Value(Scalar(alloc0))
+                                         // + val: Value(Scalar(alloc1))
                                          // mir::Constant
                                          // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34
-                                         // + literal: Const { ty: &i32, val: Value(Scalar(alloc0)) }
+                                         // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) }
         _2 = &(*_3);                     // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34
         _1 = [move _2];                  // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
         _0 = &_1;                        // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
@@ -21,6 +21,6 @@ promoted[0] in BAR: &[&i32; 1] = {
     }
 }
 
-alloc0 (static: Y, size: 4, align: 4) {
+alloc1 (static: Y, size: 4, align: 4) {
     2a 00 00 00                                     │ *...
 }
index 2566d745ecd060d128de11ea32f6fa3335caf9e0..6f4bd65b85d4d784f210dd403aa89eeeb11e6ffa 100644 (file)
 -         StorageLive(_3);                 // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 -         StorageLive(_4);                 // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34
 -         StorageLive(_5);                 // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34
--         _5 = const {alloc0: &i32};       // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34
+-         _5 = const {alloc1: &i32};       // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34
 +         _6 = const BAR::promoted[0];     // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
                                            // ty::Const
 -                                          // + ty: &i32
--                                          // + val: Value(Scalar(alloc0))
+-                                          // + val: Value(Scalar(alloc1))
 +                                          // + ty: &[&i32; 1]
 +                                          // + val: Unevaluated(BAR, [], Some(promoted[0]))
                                            // mir::Constant
 -                                          // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34
--                                          // + literal: Const { ty: &i32, val: Value(Scalar(alloc0)) }
+-                                          // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) }
 -         _4 = &(*_5);                     // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34
 -         _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
@@ -53,7 +53,7 @@
       }
 - }
 - 
-- alloc0 (static: Y, size: 4, align: 4) {
+- alloc1 (static: Y, size: 4, align: 4) {
 -     2a 00 00 00                                     │ *...
   }
   
index 17107ec431effdc1dd36beb7f432bff2fde90faf..8b3c5d332f2514ebfed3247cb93f5d2a22f7fbcb 100644 (file)
@@ -7,13 +7,13 @@ promoted[0] in FOO: &[&i32; 1] = {
     let mut _3: *const i32;              // in scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43
 
     bb0: {
-        _3 = const {alloc2: *const i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43
+        _3 = const {alloc3: *const i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43
                                          // ty::Const
                                          // + ty: *const i32
-                                         // + val: Value(Scalar(alloc2))
+                                         // + val: Value(Scalar(alloc3))
                                          // mir::Constant
                                          // + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43
-                                         // + literal: Const { ty: *const i32, val: Value(Scalar(alloc2)) }
+                                         // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) }
         _2 = &(*_3);                     // scope 0 at $DIR/const-promotion-extern-static.rs:13:41: 13:43
         _1 = [move _2];                  // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
         _0 = &_1;                        // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
@@ -21,4 +21,4 @@ promoted[0] in FOO: &[&i32; 1] = {
     }
 }
 
-alloc2 (extern static: X)
+alloc3 (extern static: X)
index 093e228a0ce44a57fc8d56f5441d2e16b8533edb..8c9a37bce854ba8c2db12d7066e2c8ed4054f128 100644 (file)
 -         StorageLive(_3);                 // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 -         StorageLive(_4);                 // scope 0 at $DIR/const-promotion-extern-static.rs:13:32: 13:45
 -         StorageLive(_5);                 // scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43
--         _5 = const {alloc2: *const i32}; // scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43
+-         _5 = const {alloc3: *const i32}; // scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43
 +         _6 = const FOO::promoted[0];     // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
                                            // ty::Const
 -                                          // + ty: *const i32
--                                          // + val: Value(Scalar(alloc2))
+-                                          // + val: Value(Scalar(alloc3))
 +                                          // + ty: &[&i32; 1]
 +                                          // + val: Unevaluated(FOO, [], Some(promoted[0]))
                                            // mir::Constant
 -                                          // + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43
--                                          // + literal: Const { ty: *const i32, val: Value(Scalar(alloc2)) }
+-                                          // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) }
 -         _4 = &(*_5);                     // scope 1 at $DIR/const-promotion-extern-static.rs:13:41: 13:43
 -         _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
@@ -55,5 +55,5 @@
       }
   }
 - 
-- alloc2 (extern static: X)
+- alloc3 (extern static: X)
   
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 bccfa9da6153008a8706584a74c0b49931610c08..77ff8ef4e49528554280b86aac3334a30e090469 100644 (file)
@@ -14,9 +14,6 @@
 -         _2 = CheckedAdd(const 1_u32, const 1_u32); // scope 0 at $DIR/checked_add.rs:5:18: 5:23
 -         assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:5:18: 5:23
 +         _2 = const (2_u32, false);       // scope 0 at $DIR/checked_add.rs:5:18: 5:23
-+                                          // mir::Constant
-+                                          // + span: $DIR/checked_add.rs:5:18: 5:23
-+                                          // + literal: Const { ty: (u32, bool), val: Value(ByRef { alloc: Allocation { bytes: [2, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
 +         assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:5:18: 5:23
       }
   
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 57a00ba12b0eb35283346009294eb142499adcb1..8dd55235ef37b42c6aa258d352977f62221931cf 100644 (file)
@@ -18,9 +18,6 @@
 -         assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:5:13: 5:29
 +         _2 = const 2_u8;                 // scope 0 at $DIR/indirect.rs:5:13: 5:25
 +         _3 = const (3_u8, false);        // scope 0 at $DIR/indirect.rs:5:13: 5:29
-+                                          // mir::Constant
-+                                          // + span: $DIR/indirect.rs:5:13: 5:29
-+                                          // + literal: Const { ty: (u8, bool), val: Value(ByRef { alloc: Allocation { bytes: [3, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
 +         assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u8, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:5:13: 5:29
       }
   
index 518974e24b389f0969db4cad74d099e8b087675b..2d3289f7ce51d9d475051441bd083ac68a343ec5 100644 (file)
@@ -15,9 +15,6 @@
           (_3.1: u8) = const 2_u8;         // scope 0 at $DIR/issue-67019.rs:11:11: 11:17
 -         (_2.0: (u8, u8)) = move _3;      // scope 0 at $DIR/issue-67019.rs:11:10: 11:19
 +         (_2.0: (u8, u8)) = const (1_u8, 2_u8); // scope 0 at $DIR/issue-67019.rs:11:10: 11:19
-+                                          // mir::Constant
-+                                          // + span: $DIR/issue-67019.rs:11:10: 11:19
-+                                          // + literal: Const { ty: (u8, u8), val: Value(ByRef { alloc: Allocation { bytes: [1, 2], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
           StorageDead(_3);                 // scope 0 at $DIR/issue-67019.rs:11:18: 11:19
           _1 = test(move _2) -> bb1;       // scope 0 at $DIR/issue-67019.rs:11:5: 11:20
                                            // mir::Constant
index d94c4f6fb26b5ac58231082727f2850767f92c92..a044d1dcfe1d9403239494376f8c9d893083b420 100644 (file)
@@ -20,9 +20,6 @@
           StorageLive(_2);                 // scope 1 at $DIR/mutable_variable_aggregate.rs:7:9: 7:10
 -         _2 = _1;                         // scope 1 at $DIR/mutable_variable_aggregate.rs:7:13: 7:14
 +         _2 = const (42_i32, 99_i32);     // scope 1 at $DIR/mutable_variable_aggregate.rs:7:13: 7:14
-+                                          // mir::Constant
-+                                          // + span: $DIR/mutable_variable_aggregate.rs:7:13: 7:14
-+                                          // + literal: Const { ty: (i32, i32), val: Value(ByRef { alloc: Allocation { bytes: [42, 0, 0, 0, 99, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
           nop;                             // scope 0 at $DIR/mutable_variable_aggregate.rs:4:11: 8:2
           StorageDead(_2);                 // scope 1 at $DIR/mutable_variable_aggregate.rs:8:1: 8:2
           StorageDead(_1);                 // scope 0 at $DIR/mutable_variable_aggregate.rs:8:1: 8:2
index 5dad8e721fb13927b6c7e357c4a37696e8095405..afc621784633e5cf7f8670c59d386d30ce985a52 100644 (file)
           StorageLive(_2);                 // scope 1 at $DIR/mutable_variable_no_prop.rs:8:5: 10:6
           StorageLive(_3);                 // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19
           StorageLive(_4);                 // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19
-          _4 = const {alloc0: *mut u32};   // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19
+          _4 = const {alloc1: *mut u32};   // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19
                                            // ty::Const
                                            // + ty: *mut u32
-                                           // + val: Value(Scalar(alloc0))
+                                           // + val: Value(Scalar(alloc1))
                                            // mir::Constant
                                            // + span: $DIR/mutable_variable_no_prop.rs:9:13: 9:19
-                                           // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc0)) }
+                                           // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc1)) }
           _3 = (*_4);                      // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19
           _1 = move _3;                    // scope 2 at $DIR/mutable_variable_no_prop.rs:9:9: 9:19
           StorageDead(_3);                 // scope 2 at $DIR/mutable_variable_no_prop.rs:9:18: 9:19
@@ -45,7 +45,7 @@
       }
   }
   
-  alloc0 (static: STATIC, size: 4, align: 4) {
+  alloc1 (static: STATIC, size: 4, align: 4) {
       2a 00 00 00                                     │ *...
   }
   
index 537f1b6253ca0ed98ff8d95c3b5c27d1c85b904f..4c3f66cd0907f95a883416d53e1ef7619276c209 100644 (file)
@@ -27,9 +27,6 @@
 -         _2 = CheckedAdd(const 2_i32, const 2_i32); // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
 -         assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
 +         _2 = const (4_i32, false);       // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
-+                                          // mir::Constant
-+                                          // + span: $DIR/optimizes_into_variable.rs:12:13: 12:18
-+                                          // + literal: Const { ty: (i32, bool), val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
 +         assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
       }
   
index 537f1b6253ca0ed98ff8d95c3b5c27d1c85b904f..4c3f66cd0907f95a883416d53e1ef7619276c209 100644 (file)
@@ -27,9 +27,6 @@
 -         _2 = CheckedAdd(const 2_i32, const 2_i32); // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
 -         assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
 +         _2 = const (4_i32, false);       // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
-+                                          // mir::Constant
-+                                          // + span: $DIR/optimizes_into_variable.rs:12:13: 12:18
-+                                          // + literal: Const { ty: (i32, bool), val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
 +         assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
       }
   
index 0d141a070ff6250526e7dda2fc75997df4892ca7..13ef30d89a076e89ef73b07a0f594f6a9028285f 100644 (file)
           StorageLive(_1);                 // scope 0 at $DIR/read_immutable_static.rs:7:9: 7:10
           StorageLive(_2);                 // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16
           StorageLive(_3);                 // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16
-          _3 = const {alloc0: &u8};        // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16
+          _3 = const {alloc1: &u8};        // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16
                                            // ty::Const
                                            // + ty: &u8
-                                           // + val: Value(Scalar(alloc0))
+                                           // + val: Value(Scalar(alloc1))
                                            // mir::Constant
                                            // + span: $DIR/read_immutable_static.rs:7:13: 7:16
-                                           // + literal: Const { ty: &u8, val: Value(Scalar(alloc0)) }
+                                           // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) }
 -         _2 = (*_3);                      // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16
 +         _2 = const 2_u8;                 // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16
           StorageLive(_4);                 // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22
           StorageLive(_5);                 // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22
-          _5 = const {alloc0: &u8};        // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22
+          _5 = const {alloc1: &u8};        // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22
                                            // ty::Const
                                            // + ty: &u8
-                                           // + val: Value(Scalar(alloc0))
+                                           // + val: Value(Scalar(alloc1))
                                            // mir::Constant
                                            // + span: $DIR/read_immutable_static.rs:7:19: 7:22
-                                           // + literal: Const { ty: &u8, val: Value(Scalar(alloc0)) }
+                                           // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) }
 -         _4 = (*_5);                      // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22
 -         _1 = Add(move _2, move _4);      // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:22
 +         _4 = const 2_u8;                 // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22
@@ -48,7 +48,7 @@
       }
   }
   
-  alloc0 (static: FOO, size: 1, align: 1) {
+  alloc1 (static: FOO, size: 1, align: 1) {
       02                                              │ .
   }
   
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 97808246dd4bcaf8bfa2b6c2a2632f064b6f8a17..c6ac8d6fb139d7bf2cdd29968d088bc3a9d38acf 100644 (file)
@@ -9,9 +9,6 @@
 -         _1 = CheckedAdd(const 2_u32, const 2_u32); // scope 0 at $DIR/return_place.rs:6:5: 6:10
 -         assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:6:5: 6:10
 +         _1 = const (4_u32, false);       // scope 0 at $DIR/return_place.rs:6:5: 6:10
-+                                          // mir::Constant
-+                                          // + span: $DIR/return_place.rs:6:5: 6:10
-+                                          // + literal: Const { ty: (u32, bool), val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
 +         assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:6:5: 6:10
       }
   
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 b8f9cd34c99cbef9072e44ce5862a869bd36c7fa..15253a364e99026493c7a275c1c70605162a82aa 100644 (file)
@@ -18,9 +18,6 @@
           StorageLive(_3);                 // scope 1 at $DIR/tuple_literal_propagation.rs:5:13: 5:14
 -         _3 = _1;                         // scope 1 at $DIR/tuple_literal_propagation.rs:5:13: 5:14
 +         _3 = const (1_u32, 2_u32);       // scope 1 at $DIR/tuple_literal_propagation.rs:5:13: 5:14
-+                                          // mir::Constant
-+                                          // + span: $DIR/tuple_literal_propagation.rs:5:13: 5:14
-+                                          // + literal: Const { ty: (u32, u32), val: Value(ByRef { alloc: Allocation { bytes: [1, 0, 0, 0, 2, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
           _2 = consume(move _3) -> bb1;    // scope 1 at $DIR/tuple_literal_propagation.rs:5:5: 5:15
                                            // mir::Constant
                                            // + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12
index e60a1f3e75f9fe93d41767b3f7032b24ea3d2100..d3c7136c6478f2eb1041d942821066c147a3c57b 100644 (file)
@@ -12,9 +12,6 @@
 -         _0 = Baz { x: move _2, y: const 0f32, z: const false }; // scope 0 at $DIR/deaggregator_test.rs:9:5: 9:35
 +         (_0.0: usize) = move _2;         // scope 0 at $DIR/deaggregator_test.rs:9:5: 9:35
 +         (_0.1: f32) = const 0f32;        // scope 0 at $DIR/deaggregator_test.rs:9:5: 9:35
-                                           // mir::Constant
-                                           // + span: $DIR/deaggregator_test.rs:9:20: 9:23
-                                           // + literal: Const { ty: f32, val: Value(Scalar(0x00000000)) }
 +         (_0.2: bool) = const false;      // scope 0 at $DIR/deaggregator_test.rs:9:5: 9:35
           StorageDead(_2);                 // scope 0 at $DIR/deaggregator_test.rs:9:34: 9:35
           return;                          // scope 0 at $DIR/deaggregator_test.rs:10:2: 10:2
index 6da0460286b9af7cf5c908822dfe385f11628e9b..d19229aabada8c215e7d93c253140926c95ff1f4 100644 (file)
@@ -14,7 +14,7 @@
     },
 } */
 
-fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 13:6 {String, ()}]) -> () {
+fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 13:6]) -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6
     let mut _2: ();                      // in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6
     let _3: std::string::String;         // in scope 0 at $DIR/generator-drop-cleanup.rs:11:13: 11:15
index 296a459b99f409acafa7d5b16ff1373f540fed80..642d9b3fb35dd6b5af34dfbfbff3890b8a4e45a4 100644 (file)
@@ -1,6 +1,6 @@
 // MIR for `main::{closure#0}` before StateTransform
 
-fn main::{closure#0}(_1: [generator@$DIR/generator-storage-dead-unwind.rs:22:16: 28:6 {Foo, Bar, ()}], _2: ()) -> ()
+fn main::{closure#0}(_1: [generator@$DIR/generator-storage-dead-unwind.rs:22:16: 28:6], _2: ()) -> ()
 yields ()
  {
     let mut _0: ();                      // return place in scope 0 at $DIR/generator-storage-dead-unwind.rs:22:19: 22:19
index 990aa1ec08775ec239c3defb5452a5095f58a72b..539988cad245efc11f9049a70bd7071b22ef2571 100644 (file)
@@ -10,7 +10,7 @@
     storage_conflicts: BitMatrix(0x0) {},
 } */
 
-fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}]>, _2: u8) -> GeneratorState<(), ()> {
+fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6]>, _2: u8) -> GeneratorState<(), ()> {
     debug _x => _10;                     // in scope 0 at $DIR/generator-tiny.rs:19:17: 19:19
     let mut _0: std::ops::GeneratorState<(), ()>; // return place in scope 0 at $DIR/generator-tiny.rs:19:16: 25:6
     let _3: HasDrop;                     // in scope 0 at $DIR/generator-tiny.rs:20:13: 20:15
@@ -27,7 +27,7 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6
     }
 
     bb0: {
-        _11 = discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}]))); // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6
+        _11 = discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6]))); // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6
         switchInt(move _11) -> [0_u32: bb1, 3_u32: bb5, otherwise: bb6]; // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6
     }
 
@@ -43,7 +43,7 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6
         StorageLive(_7);                 // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
         ((_0 as Yielded).0: ()) = move _7; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
         discriminant(_0) = 0;            // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
-        discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}]))) = 3; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
+        discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6]))) = 3; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
         return;                          // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
     }
 
index 2c4952402a49d907783efd663300622e5763306a..64a3f52f3a06ac870b750c0353c90de61e916db4 100644 (file)
@@ -12,9 +12,6 @@
           StorageLive(_3);                 // scope 0 at $DIR/if-condition-int.rs:53:8: 53:9
           _3 = _1;                         // scope 0 at $DIR/if-condition-int.rs:53:8: 53:9
           _2 = Eq(move _3, const -42f32);  // scope 0 at $DIR/if-condition-int.rs:53:8: 53:18
-                                           // mir::Constant
-                                           // + span: $DIR/if-condition-int.rs:53:13: 53:18
-                                           // + literal: Const { ty: f32, val: Value(Scalar(0xc2280000)) }
           StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:53:17: 53:18
           switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:53:5: 53:35
       }
index fba88c83eb4f39bb27b9878eb8ff85116b167a1d..9035b46f4c69da407697aa3eba9822edf7525788 100644 (file)
       }
 +     scope 2 (inlined g) {                // at $DIR/inline-generator.rs:9:28: 9:31
 +     }
-+     scope 3 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]>::new) { // at $DIR/inline-generator.rs:9:14: 9:32
++     scope 3 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>::new) { // at $DIR/inline-generator.rs:9:14: 9:32
 +         debug pointer => _3;             // in scope 3 at $DIR/inline-generator.rs:9:14: 9:32
-+         let mut _5: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]; // in scope 3 at $DIR/inline-generator.rs:9:14: 9:32
++         let mut _5: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 3 at $DIR/inline-generator.rs:9:14: 9:32
 +         scope 4 {
-+             scope 5 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]>::new_unchecked) { // at $DIR/inline-generator.rs:9:14: 9:32
++             scope 5 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>::new_unchecked) { // at $DIR/inline-generator.rs:9:14: 9:32
 +                 debug pointer => _5;     // in scope 5 at $DIR/inline-generator.rs:9:14: 9:32
-+                 let mut _6: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]; // in scope 5 at $DIR/inline-generator.rs:9:14: 9:32
++                 let mut _6: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 5 at $DIR/inline-generator.rs:9:14: 9:32
 +             }
 +         }
 +     }
@@ -58,7 +58,7 @@
 +         _5 = move _3;                    // scope 4 at $DIR/inline-generator.rs:9:14: 9:32
 +         StorageLive(_6);                 // scope 5 at $DIR/inline-generator.rs:9:14: 9:32
 +         _6 = move _5;                    // scope 5 at $DIR/inline-generator.rs:9:14: 9:32
-+         (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]) = move _6; // scope 5 at $DIR/inline-generator.rs:9:14: 9:32
++         (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]) = move _6; // scope 5 at $DIR/inline-generator.rs:9:14: 9:32
 +         StorageDead(_6);                 // scope 5 at $DIR/inline-generator.rs:9:14: 9:32
 +         StorageDead(_5);                 // scope 4 at $DIR/inline-generator.rs:9:14: 9:32
           StorageDead(_3);                 // scope 0 at $DIR/inline-generator.rs:9:31: 9:32
@@ -71,7 +71,7 @@
 +         StorageLive(_10);                // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
 +         StorageLive(_11);                // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
 +         StorageLive(_12);                // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
-+         _12 = discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         _12 = discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]))); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
 +         switchInt(move _12) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
       }
   
 +         StorageDead(_9);                 // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
 +         ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
 +         discriminant(_1) = 0;            // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
-+         discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))) = 3; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]))) = 3; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
 +         goto -> bb1;                     // scope 0 at $DIR/inline-generator.rs:15:11: 15:39
 +     }
 + 
 +         StorageDead(_8);                 // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
 +         ((_1 as Complete).0: bool) = move _10; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
 +         discriminant(_1) = 1;            // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
-+         discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))) = 1; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]))) = 1; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
 +         goto -> bb1;                     // scope 0 at $DIR/inline-generator.rs:15:41: 15:41
 +     }
 + 
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
diff --git a/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff b/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
new file mode 100644 (file)
index 0000000..d2056ac
--- /dev/null
@@ -0,0 +1,63 @@
+- // MIR for `bound` before LowerSliceLenCalls
++ // MIR for `bound` after LowerSliceLenCalls
+  
+  fn bound(_1: usize, _2: &[u8]) -> u8 {
+      debug index => _1;                   // in scope 0 at $DIR/lower_slice_len.rs:4:14: 4:19
+      debug slice => _2;                   // in scope 0 at $DIR/lower_slice_len.rs:4:28: 4:33
+      let mut _0: u8;                      // return place in scope 0 at $DIR/lower_slice_len.rs:4:45: 4:47
+      let mut _3: bool;                    // in scope 0 at $DIR/lower_slice_len.rs:5:8: 5:27
+      let mut _4: usize;                   // in scope 0 at $DIR/lower_slice_len.rs:5:8: 5:13
+      let mut _5: usize;                   // in scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27
+      let mut _6: &[u8];                   // in scope 0 at $DIR/lower_slice_len.rs:5:16: 5:21
+      let _7: usize;                       // in scope 0 at $DIR/lower_slice_len.rs:6:15: 6:20
+      let mut _8: usize;                   // in scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21
+      let mut _9: bool;                    // in scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/lower_slice_len.rs:5:8: 5:27
+          StorageLive(_4);                 // scope 0 at $DIR/lower_slice_len.rs:5:8: 5:13
+          _4 = _1;                         // scope 0 at $DIR/lower_slice_len.rs:5:8: 5:13
+          StorageLive(_5);                 // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27
+          StorageLive(_6);                 // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:21
+          _6 = &(*_2);                     // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:21
+-         _5 = core::slice::<impl [u8]>::len(move _6) -> bb1; // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27
+-                                          // mir::Constant
+-                                          // + span: $DIR/lower_slice_len.rs:5:22: 5:25
+-                                          // + literal: Const { ty: for<'r> fn(&'r [u8]) -> usize {core::slice::<impl [u8]>::len}, val: Value(Scalar(<ZST>)) }
++         _5 = Len((*_6));                 // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27
++         goto -> bb1;                     // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27
+      }
+  
+      bb1: {
+          StorageDead(_6);                 // scope 0 at $DIR/lower_slice_len.rs:5:26: 5:27
+          _3 = Lt(move _4, move _5);       // scope 0 at $DIR/lower_slice_len.rs:5:8: 5:27
+          StorageDead(_5);                 // scope 0 at $DIR/lower_slice_len.rs:5:26: 5:27
+          StorageDead(_4);                 // scope 0 at $DIR/lower_slice_len.rs:5:26: 5:27
+          switchInt(move _3) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/lower_slice_len.rs:5:5: 9:6
+      }
+  
+      bb2: {
+          StorageLive(_7);                 // scope 0 at $DIR/lower_slice_len.rs:6:15: 6:20
+          _7 = _1;                         // scope 0 at $DIR/lower_slice_len.rs:6:15: 6:20
+          _8 = Len((*_2));                 // scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21
+          _9 = Lt(_7, _8);                 // scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21
+          assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> bb4; // scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21
+      }
+  
+      bb3: {
+          _0 = const 42_u8;                // scope 0 at $DIR/lower_slice_len.rs:8:9: 8:11
+          goto -> bb5;                     // scope 0 at $DIR/lower_slice_len.rs:5:5: 9:6
+      }
+  
+      bb4: {
+          _0 = (*_2)[_7];                  // scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21
+          StorageDead(_7);                 // scope 0 at $DIR/lower_slice_len.rs:7:5: 7:6
+          goto -> bb5;                     // scope 0 at $DIR/lower_slice_len.rs:5:5: 9:6
+      }
+  
+      bb5: {
+          StorageDead(_3);                 // scope 0 at $DIR/lower_slice_len.rs:9:5: 9:6
+          return;                          // scope 0 at $DIR/lower_slice_len.rs:10:2: 10:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/lower_slice_len.rs b/src/test/mir-opt/lower_slice_len.rs
new file mode 100644 (file)
index 0000000..f2438e6
--- /dev/null
@@ -0,0 +1,14 @@
+// compile-flags: -Z mir-opt-level=3
+
+// EMIT_MIR lower_slice_len.bound.LowerSliceLenCalls.diff
+pub fn bound(index: usize, slice: &[u8]) -> u8 {
+    if index < slice.len() {
+        slice[index]
+    } else {
+        42
+    }
+}
+
+fn main() {
+    let _ = bound(1, &[1, 2, 3]);
+}
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 a698d8abcdb5a8285a04955d8421b7b4f39ef24f..598e8247efc5af37f4eb93a63bedd31b034c0116 100644 (file)
@@ -38,9 +38,6 @@
                                            // mir::Constant
                                            // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:12
                                            // + literal: Const { ty: fn(((), ())) {use_zst}, val: Value(Scalar(<ZST>)) }
-                                           // mir::Constant
-                                           // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
-                                           // + literal: Const { ty: ((), ()), val: Value(Scalar(<ZST>)) }
       }
   
       bb1: {
diff --git a/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
new file mode 100644 (file)
index 0000000..373be9f
--- /dev/null
@@ -0,0 +1,106 @@
+// MIR for `main` after SimplifyCfg-after-uninhabited-enum-branching
+
+fn main() -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/uninhabited_enum_branching2.rs:18:11: 18:11
+    let _1: Plop;                        // in scope 0 at $DIR/uninhabited_enum_branching2.rs:19:9: 19:13
+    let mut _2: Test1;                   // in scope 0 at $DIR/uninhabited_enum_branching2.rs:19:38: 19:46
+    let _3: &str;                        // in scope 0 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+    let mut _4: &Test1;                  // in scope 0 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22
+    let mut _5: isize;                   // in scope 0 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20
+    let _6: &str;                        // in scope 0 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34
+    let _7: &str;                        // in scope 0 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24
+    let _8: &str;                        // in scope 0 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24
+    let _9: &str;                        // in scope 0 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+    let mut _10: isize;                  // in scope 0 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20
+    let _11: &str;                       // in scope 0 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34
+    let _12: &str;                       // in scope 0 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24
+    let _13: &str;                       // in scope 0 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24
+    scope 1 {
+        debug plop => _1;                // in scope 1 at $DIR/uninhabited_enum_branching2.rs:19:9: 19:13
+    }
+
+    bb0: {
+        StorageLive(_1);                 // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:9: 19:13
+        StorageLive(_2);                 // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:38: 19:46
+        discriminant(_2) = 2;            // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:38: 19:46
+        (_1.0: u32) = const 51_u32;      // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:16: 19:48
+        (_1.1: Test1) = move _2;         // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:16: 19:48
+        StorageDead(_2);                 // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:47: 19:48
+        StorageLive(_3);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+        StorageLive(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22
+        _4 = &(_1.1: Test1);             // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22
+        _5 = discriminant((*_4));        // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20
+        switchInt(move _5) -> [2_isize: bb2, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20
+    }
+
+    bb1: {
+        StorageLive(_8);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24
+        _8 = const "D";                  // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24
+                                         // ty::Const
+                                         // + ty: &str
+                                         // + val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 })
+                                         // mir::Constant
+                                         // + span: $DIR/uninhabited_enum_branching2.rs:25:21: 25:24
+                                         // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
+        _3 = &(*_8);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24
+        StorageDead(_8);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24
+        goto -> bb3;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+    }
+
+    bb2: {
+        StorageLive(_7);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24
+        _7 = const "C";                  // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24
+                                         // ty::Const
+                                         // + ty: &str
+                                         // + val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 })
+                                         // mir::Constant
+                                         // + span: $DIR/uninhabited_enum_branching2.rs:24:21: 24:24
+                                         // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
+        _3 = &(*_7);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24
+        StorageDead(_7);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24
+        goto -> bb3;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+    }
+
+    bb3: {
+        StorageDead(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:26:6: 26:7
+        StorageDead(_3);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:26:6: 26:7
+        StorageLive(_9);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+        _10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20
+        switchInt(move _10) -> [2_isize: bb5, otherwise: bb4]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20
+    }
+
+    bb4: {
+        StorageLive(_13);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24
+        _13 = const "D";                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24
+                                         // ty::Const
+                                         // + ty: &str
+                                         // + val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 })
+                                         // mir::Constant
+                                         // + span: $DIR/uninhabited_enum_branching2.rs:32:21: 32:24
+                                         // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
+        _9 = &(*_13);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24
+        StorageDead(_13);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24
+        goto -> bb6;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+    }
+
+    bb5: {
+        StorageLive(_12);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24
+        _12 = const "C";                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24
+                                         // ty::Const
+                                         // + ty: &str
+                                         // + val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 })
+                                         // mir::Constant
+                                         // + span: $DIR/uninhabited_enum_branching2.rs:31:21: 31:24
+                                         // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
+        _9 = &(*_12);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24
+        StorageDead(_12);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24
+        goto -> bb6;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+    }
+
+    bb6: {
+        StorageDead(_9);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:33:6: 33:7
+        _0 = const ();                   // scope 0 at $DIR/uninhabited_enum_branching2.rs:18:11: 34:2
+        StorageDead(_1);                 // scope 0 at $DIR/uninhabited_enum_branching2.rs:34:1: 34:2
+        return;                          // scope 0 at $DIR/uninhabited_enum_branching2.rs:34:2: 34:2
+    }
+}
diff --git a/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff
new file mode 100644 (file)
index 0000000..f9488ba
--- /dev/null
@@ -0,0 +1,160 @@
+- // MIR for `main` before UninhabitedEnumBranching
++ // MIR for `main` after UninhabitedEnumBranching
+  
+  fn main() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/uninhabited_enum_branching2.rs:18:11: 18:11
+      let _1: Plop;                        // in scope 0 at $DIR/uninhabited_enum_branching2.rs:19:9: 19:13
+      let mut _2: Test1;                   // in scope 0 at $DIR/uninhabited_enum_branching2.rs:19:38: 19:46
+      let _3: &str;                        // in scope 0 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+      let mut _4: &Test1;                  // in scope 0 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22
+      let mut _5: isize;                   // in scope 0 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20
+      let _6: &str;                        // in scope 0 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34
+      let _7: &str;                        // in scope 0 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24
+      let _8: &str;                        // in scope 0 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24
+      let _9: &str;                        // in scope 0 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+      let mut _10: isize;                  // in scope 0 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20
+      let _11: &str;                       // in scope 0 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34
+      let _12: &str;                       // in scope 0 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24
+      let _13: &str;                       // in scope 0 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24
+      scope 1 {
+          debug plop => _1;                // in scope 1 at $DIR/uninhabited_enum_branching2.rs:19:9: 19:13
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:9: 19:13
+          StorageLive(_2);                 // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:38: 19:46
+          discriminant(_2) = 2;            // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:38: 19:46
+          (_1.0: u32) = const 51_u32;      // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:16: 19:48
+          (_1.1: Test1) = move _2;         // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:16: 19:48
+          StorageDead(_2);                 // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:47: 19:48
+          StorageLive(_3);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+          StorageLive(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22
+          _4 = &(_1.1: Test1);             // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22
+          _5 = discriminant((*_4));        // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20
+-         switchInt(move _5) -> [0_isize: bb2, 1_isize: bb3, 2_isize: bb4, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20
++         switchInt(move _5) -> [2_isize: bb4, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20
+      }
+  
+      bb1: {
+          StorageLive(_8);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24
+          _8 = const "D";                  // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24
+                                           // ty::Const
+                                           // + ty: &str
+                                           // + val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 })
+                                           // mir::Constant
+                                           // + span: $DIR/uninhabited_enum_branching2.rs:25:21: 25:24
+                                           // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
+          _3 = &(*_8);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24
+          StorageDead(_8);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24
+          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+      }
+  
+      bb2: {
+          _3 = const "A(Empty)";           // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:24: 22:34
+                                           // ty::Const
+                                           // + ty: &str
+                                           // + val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 })
+                                           // mir::Constant
+                                           // + span: $DIR/uninhabited_enum_branching2.rs:22:24: 22:34
+                                           // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) }
+          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+      }
+  
+      bb3: {
+          StorageLive(_6);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34
+          _6 = const "B(Empty)";           // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34
+                                           // ty::Const
+                                           // + ty: &str
+                                           // + val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 })
+                                           // mir::Constant
+                                           // + span: $DIR/uninhabited_enum_branching2.rs:23:24: 23:34
+                                           // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) }
+          _3 = &(*_6);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34
+          StorageDead(_6);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:33: 23:34
+          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+      }
+  
+      bb4: {
+          StorageLive(_7);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24
+          _7 = const "C";                  // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24
+                                           // ty::Const
+                                           // + ty: &str
+                                           // + val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 })
+                                           // mir::Constant
+                                           // + span: $DIR/uninhabited_enum_branching2.rs:24:21: 24:24
+                                           // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
+          _3 = &(*_7);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24
+          StorageDead(_7);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24
+          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+      }
+  
+      bb5: {
+          StorageDead(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:26:6: 26:7
+          StorageDead(_3);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:26:6: 26:7
+          StorageLive(_9);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+          _10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20
+-         switchInt(move _10) -> [0_isize: bb7, 1_isize: bb8, 2_isize: bb9, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20
++         switchInt(move _10) -> [2_isize: bb9, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20
+      }
+  
+      bb6: {
+          StorageLive(_13);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24
+          _13 = const "D";                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24
+                                           // ty::Const
+                                           // + ty: &str
+                                           // + val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 })
+                                           // mir::Constant
+                                           // + span: $DIR/uninhabited_enum_branching2.rs:32:21: 32:24
+                                           // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
+          _9 = &(*_13);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24
+          StorageDead(_13);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24
+          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+      }
+  
+      bb7: {
+          _9 = const "A(Empty)";           // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:24: 29:34
+                                           // ty::Const
+                                           // + ty: &str
+                                           // + val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 })
+                                           // mir::Constant
+                                           // + span: $DIR/uninhabited_enum_branching2.rs:29:24: 29:34
+                                           // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) }
+          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+      }
+  
+      bb8: {
+          StorageLive(_11);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34
+          _11 = const "B(Empty)";          // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34
+                                           // ty::Const
+                                           // + ty: &str
+                                           // + val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 })
+                                           // mir::Constant
+                                           // + span: $DIR/uninhabited_enum_branching2.rs:30:24: 30:34
+                                           // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) }
+          _9 = &(*_11);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34
+          StorageDead(_11);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:33: 30:34
+          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+      }
+  
+      bb9: {
+          StorageLive(_12);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24
+          _12 = const "C";                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24
+                                           // ty::Const
+                                           // + ty: &str
+                                           // + val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 })
+                                           // mir::Constant
+                                           // + span: $DIR/uninhabited_enum_branching2.rs:31:21: 31:24
+                                           // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
+          _9 = &(*_12);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24
+          StorageDead(_12);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24
+          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+      }
+  
+      bb10: {
+          StorageDead(_9);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:33:6: 33:7
+          _0 = const ();                   // scope 0 at $DIR/uninhabited_enum_branching2.rs:18:11: 34:2
+          StorageDead(_1);                 // scope 0 at $DIR/uninhabited_enum_branching2.rs:34:1: 34:2
+          return;                          // scope 0 at $DIR/uninhabited_enum_branching2.rs:34:2: 34:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/uninhabited_enum_branching2.rs b/src/test/mir-opt/uninhabited_enum_branching2.rs
new file mode 100644 (file)
index 0000000..e22e943
--- /dev/null
@@ -0,0 +1,34 @@
+enum Empty { }
+
+// test matching an enum with uninhabited variants
+enum Test1 {
+    A(Empty),
+    B(Empty),
+    C,
+    D,
+}
+
+struct Plop {
+    xx: u32,
+    test1: Test1,
+}
+
+// EMIT_MIR uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff
+// EMIT_MIR uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
+fn main() {
+    let plop = Plop { xx: 51, test1: Test1::C };
+
+    match &plop.test1 {
+        Test1::A(_) => "A(Empty)",
+        Test1::B(_) => "B(Empty)",
+        Test1::C => "C",
+        Test1::D => "D",
+    };
+
+    match plop.test1 {
+        Test1::A(_) => "A(Empty)",
+        Test1::B(_) => "B(Empty)",
+        Test1::C => "C",
+        Test1::D => "D",
+    };
+}
index a32903a6409a413bef8802e904334a8708a6f7de..32d1da390c547728e3f0efb5f32f8db16e492af6 100644 (file)
@@ -39,7 +39,7 @@ fn syntax() {
                     #![attr]
                 };
     let _ =
-        #[attr] loop  {
+        #[attr] loop {
                     #![attr]
                 };
     let _ =
index 2bfcdd75e15cff94d54007075bcacc3d586c6238..2d0a10d4c27d231a10285a46a7d3433055f60557 100644 (file)
@@ -90,7 +90,7 @@ fn f() {
 }
 
 fn main() {
-    // Taken from http://www.unicode.org/Public/UNIDATA/PropList.txt
+    // Taken from https://www.unicode.org/Public/UNIDATA/PropList.txt
     let chars =
         ['\x0A', '\x0B', '\x0C', '\x0D', '\x20', '\u{85}', '\u{A0}',
          '\u{1680}', '\u{2000}', '\u{2001}', '\u{2002}', '\u{2003}',
index 93373c5da6558bcf66fb3cd4fdf58cd8f1076d93..075230196e3923176a2c210af4ba7d1d7da737bf 100644 (file)
@@ -86,7 +86,7 @@ fn f() {
 }
 
 fn main() {
-    // Taken from http://www.unicode.org/Public/UNIDATA/PropList.txt
+    // Taken from https://www.unicode.org/Public/UNIDATA/PropList.txt
     let chars =
         ['\x0A', '\x0B', '\x0C', '\x0D', '\x20', '\u{85}', '\u{A0}',
          '\u{1680}', '\u{2000}', '\u{2001}', '\u{2002}', '\u{2003}',
index 4f6a924909029ec7798ae331a20a061d8c04a6b0..e6c4d195691ca0d2abf06982908e9745cd2e5629 100644 (file)
@@ -8,6 +8,6 @@ extern crate std;
 // pretty-mode:expanded
 // pp-exact:cast-lt.pp
 
-macro_rules! negative { ($ e : expr) => { $ e < 0 } }
+macro_rules! negative { ($e : expr) => { $e < 0 } }
 
 fn main() { (1 as i32) < 0; }
index 125f2b0fa1687fed066ab6ab51d289c12eb6cedf..257c032b536da2356a97dba71cddea90560b49f4 100644 (file)
@@ -2,7 +2,7 @@
 
 #![feature(rustc_attrs)]
 
-macro_rules! mac { ($ ($ tt : tt) *) => () }
+macro_rules! mac { ($($tt : tt) *) => () }
 
 mac! {
     struct S { field1 : u8, field2 : u16, } impl Clone for S
diff --git a/src/test/pretty/hir-pretty-loop.pp b/src/test/pretty/hir-pretty-loop.pp
new file mode 100644 (file)
index 0000000..19b3a17
--- /dev/null
@@ -0,0 +1,9 @@
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+// pretty-compare-only
+// pretty-mode:hir
+// pp-exact:hir-pretty-loop.pp
+
+pub fn foo() { loop { break ; } }
diff --git a/src/test/pretty/hir-pretty-loop.rs b/src/test/pretty/hir-pretty-loop.rs
new file mode 100644 (file)
index 0000000..87a3ef8
--- /dev/null
@@ -0,0 +1,9 @@
+// pretty-compare-only
+// pretty-mode:hir
+// pp-exact:hir-pretty-loop.pp
+
+pub fn foo(){
+    loop{
+        break;
+    }
+}
index 1e1e1dbfb3ea58a1a94ff6077c5b5e76d12497c3..d3865d93a30d8ca0949c0808a39f0aeded46aa11 100644 (file)
@@ -2,6 +2,6 @@
 
 #![feature(decl_macro)]
 
-pub(crate) macro mac { ($ arg : expr) => { $ arg + $ arg } }
+pub(crate) macro mac { ($arg : expr) => { $arg + $arg } }
 
 fn main() { }
index da223d164f9b09adb685fc41fcda07f6eff8878d..3b13f2530dd9276f2009948de758835e9c6bd63c 100644 (file)
@@ -11,9 +11,9 @@ macro_rules! matcher_brackets {
 }
 
 macro_rules! all_fragments {
-    ($ b : block, $ e : expr, $ i : ident, $ it : item, $ l : lifetime, $ lit
-     : literal, $ m : meta, $ p : pat, $ pth : path, $ s : stmt, $ tt : tt, $
-     ty : ty, $ vis : vis) => { } ;
+    ($b : block, $e : expr, $i : ident, $it : item, $l : lifetime, $lit :
+     literal, $m : meta, $p : pat, $pth : path, $s : stmt, $tt : tt, $ty : ty,
+     $vis : vis) => { } ;
 }
 
 fn main() { }
index 231351433c8906fe47d52d9bcd6851cd4988da98..e4a3acade871be7e443fb85e71d3da1dba43233b 100644 (file)
@@ -166,9 +166,8 @@ fn _11() {
         #[rustc_dummy] for _ in 0..0 {
                            #![rustc_dummy]
                        };
-    // FIXME: pp bug, two spaces after the loop
     let _ =
-        #[rustc_dummy] loop  {
+        #[rustc_dummy] loop {
                            #![rustc_dummy]
                        };
     let _ =
diff --git a/src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile b/src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile
new file mode 100644 (file)
index 0000000..bc4562b
--- /dev/null
@@ -0,0 +1,4 @@
+-include ../tools.mk
+
+all:
+       $(RUSTC) --edition=2018 --crate-type=rlib ../../../../library/core/src/lib.rs --cfg no_fp_fmt_parse
index d3d398f1fac2972097b6a3c348b26858f4333aaf..78fbf811f12bf5b70aa2ad0842db9bbb5a5ad748 100644 (file)
@@ -87,7 +87,7 @@ endif
        # Run it in order to generate some profiling data,
        # with `LLVM_PROFILE_FILE=<profdata_file>` environment variable set to
        # output the coverage stats for this run.
-       LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p.profraw \
+       LLVM_PROFILE_FILE="$(TMPDIR)"/$@.profraw \
                        $(call RUN,$@) || \
                        ( \
                                status=$$?; \
@@ -97,8 +97,11 @@ endif
                                ) \
                        )
 
-       # Run it through rustdoc as well to cover doctests
-       LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p.profraw \
+       # Run it through rustdoc as well to cover doctests.
+       # `%p` is the pid, and `%m` the binary signature. We suspect that the pid alone
+       # might result in overwritten files and failed tests, as rustdoc spawns each
+       # doctest as its own process, so make sure the filename is as unique as possible.
+       LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p-%m.profraw \
                        $(RUSTDOC) --crate-name workaround_for_79771 --test $(SOURCEDIR)/$@.rs \
                        $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \
                        -L "$(TMPDIR)" -Zinstrument-coverage \
@@ -106,7 +109,7 @@ endif
 
        # Postprocess the profiling data so it can be used by the llvm-cov tool
        "$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \
-                       "$(TMPDIR)"/$@-*.profraw \
+                       "$(TMPDIR)"/$@*.profraw \
                        -o "$(TMPDIR)"/$@.profdata
 
        # Generate a coverage report using `llvm-cov show`.
@@ -118,8 +121,7 @@ endif
                        --instr-profile="$(TMPDIR)"/$@.profdata \
                        $(call BIN,"$(TMPDIR)"/$@) \
                        $$( \
-                               for file in $(TMPDIR)/rustdoc-$@/*/rust_out; \
-                               do \
+                               for file in $(TMPDIR)/rustdoc-$@/*/rust_out; do \
                                [ -x "$$file" ] && printf "%s %s " -object $$file; \
                                done \
                        ) \
index 52af3dceb109c83d1d176e467401058596793a89..c89f8272b1e8376a4a5b29440bf48c94dd8f3ee3 100644 (file)
@@ -1,4 +1,4 @@
-// Pragma needed cause of gcc bug on windows: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991
+// Pragma needed cause of gcc bug on windows: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991
 
 #include <assert.h>
 
index 443e2df357fb408fc30a30293718ffb2764ecff3..d3862309ce46f54c6f33aa493dc522bfd709e32c 100644 (file)
@@ -12,7 +12,6 @@ extern crate rustc_span;
 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 @@ impl CodegenBackend for TheBackend {
             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 0656346e95868487ea39788fd19ee2f5e57c7fe0..9773e3f1fdfc4b8c8949e94f2c936674171da94b 100644 (file)
@@ -1,25 +1,11 @@
 # needs-profiler-support
 # ignore-windows-gnu
-# ignore-aarch64
 
 # FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
 # properly. Since we only have GCC on the CI ignore the test for now.
 
 -include ../tools.mk
 
-# This test makes sure that instrumented binaries record the right counts for
-# functions being called and branches being taken. We run an instrumented binary
-# with an argument that causes a know path through the program and then check
-# that the expected counts get added to the use-phase LLVM IR.
-
-# LLVM doesn't support instrumenting binaries that use SEH:
-# https://github.com/rust-lang/rust/issues/61002
-#
-# Things work fine with -Cpanic=abort though.
-ifdef IS_MSVC
-COMMON_FLAGS=-Cpanic=abort
-endif
-
 # For some very small programs GNU ld seems to not properly handle
 # instrumentation sections correctly. Neither Gold nor LLD have that problem.
 ifeq ($(UNAME),Linux)
index f1ac39aa0ea8a0bf6107d857666af2110c59d167..a7d5c561632574b485db2251f2cec14c8152da85 100644 (file)
@@ -8,14 +8,6 @@
 
 COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Cprofile-generate="$(TMPDIR)"
 
-# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
-# https://github.com/rust-lang/rust/issues/61002
-#
-# Things work fine with -Cpanic=abort though.
-ifdef IS_MSVC
-COMPILE_FLAGS+= -Cpanic=abort
-endif
-
 all:
        $(RUSTC) $(COMPILE_FLAGS) test.rs
        $(call RUN,test) || exit 1
index 3fbfeb09eb373d308e67a25b53b04084e5fe6b3c..425bfc28a9766d058b44aa1b18750867e8138093 100644 (file)
@@ -4,14 +4,6 @@
 
 COMPILE_FLAGS=-O -Ccodegen-units=1 -Cprofile-generate="$(TMPDIR)"
 
-# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
-# https://github.com/rust-lang/rust/issues/61002
-#
-# Things work fine with -Cpanic=abort though.
-ifdef IS_MSVC
-COMPILE_FLAGS+= -Cpanic=abort
-endif
-
 all:
        $(RUSTC) $(COMPILE_FLAGS) --emit=llvm-ir test.rs
        # We expect symbols starting with "__llvm_profile_".
index 69b19801bf0916073335613120688faf93fcf2ca..6533355be34182e3bc1dd7033de138f7bdf27664 100644 (file)
@@ -8,14 +8,6 @@
 
 COMPILE_FLAGS=-g -Cprofile-generate="$(TMPDIR)"
 
-# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
-# https://github.com/rust-lang/rust/issues/61002
-#
-# Things work fine with -Cpanic=abort though.
-ifdef IS_MSVC
-COMPILE_FLAGS+= -Cpanic=abort
-endif
-
 all:
        $(RUSTC) $(COMPILE_FLAGS) test.rs
        $(call RUN,test) || exit 1
index 876a9b2c439918353eb6c4c1f3a4685665206481..c0195dcbb31be047bb1d16677c6c8b76c231f65e 100644 (file)
@@ -6,20 +6,6 @@
 
 -include ../tools.mk
 
-# This test makes sure that indirect call promotion is performed. The test
-# programs calls the same function a thousand times through a function pointer.
-# Only PGO data provides the information that it actually always is the same
-# function. We verify that the indirect call promotion pass inserts a check
-# whether it can make a direct call instead of the indirect call.
-
-# LLVM doesn't support instrumenting binaries that use SEH:
-# https://github.com/rust-lang/rust/issues/61002
-#
-# Things work fine with -Cpanic=abort though.
-ifdef IS_MSVC
-COMMON_FLAGS=-Cpanic=abort
-endif
-
 all:
        # We don't compile `opaque` with either optimizations or instrumentation.
        # We don't compile `opaque` with either optimizations or instrumentation.
index 01bc211df161650f8b794f5035e8a6c41e747bb5..d7863c9c587a50481b18b08b765b8fee1c00ebe0 100644 (file)
 
 COMMON_FLAGS=-Copt-level=2 -Ccodegen-units=1 -Cllvm-args=-disable-preinline
 
-# LLVM doesn't support instrumenting binaries that use SEH:
-# https://github.com/rust-lang/rust/issues/61002
-#
-# Things work fine with -Cpanic=abort though.
-ifdef IS_MSVC
-COMMON_FLAGS+= -Cpanic=abort
-endif
-
 ifeq ($(UNAME),Darwin)
 # macOS does not have the `tac` command, but `tail -r` does the same thing
 TAC := tail -r
index 08303a46d19299e590e59b1e1d38a74632d87bf2..013bf3baca45f1d18d321ba80ea4641bbc72ecbc 100644 (file)
@@ -6,6 +6,8 @@ all: default
        $(RUSTC) --target i686-pc-windows-msvc --print cfg | $(CGREP) msvc
        $(RUSTC) --target i686-apple-darwin --print cfg | $(CGREP) macos
        $(RUSTC) --target i686-unknown-linux-gnu --print cfg | $(CGREP) gnu
+       $(RUSTC) --target arm-unknown-linux-gnueabihf --print cfg | $(CGREP) target_abi=
+       $(RUSTC) --target arm-unknown-linux-gnueabihf --print cfg | $(CGREP) eabihf
 
 ifdef IS_WINDOWS
 default:
index 58e924a9895c85b7687780a562e52ffde7101414..34357182c205e39e9294ce0ec782bc1c4f9ac8d3 100644 (file)
@@ -8,7 +8,6 @@
   "executables": true,
   "has-elf-tls": true,
   "has-rpath": true,
-  "is-builtin": true,
   "linker-is-gnu": true,
   "llvm-target": "x86_64-unknown-linux-gnu",
   "max-atomic-width": 64,
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
index aff15ce38b4aef08c84c63917384ae48b3ac784f..dff7a966c9678fe5f44eb405e6c6e56e1c779646 100644 (file)
@@ -7,3 +7,5 @@ all:
        RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-awesome-platform --crate-type=lib --emit=asm
        RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-x86_64-unknown-linux-gnu-platform --crate-type=lib --emit=asm
        $(RUSTC) -Z unstable-options --target=my-awesome-platform.json --print target-spec-json > $(TMPDIR)/test-platform.json && $(RUSTC) -Z unstable-options --target=$(TMPDIR)/test-platform.json --print target-spec-json | diff -q $(TMPDIR)/test-platform.json -
+       $(RUSTC) foo.rs --target=definitely-not-builtin-target 2>&1 | $(CGREP) 'may not set is_builtin'
+       $(RUSTC) foo.rs --target=mismatching-data-layout
diff --git a/src/test/run-make-fulldeps/target-specs/definitely-not-builtin-target.json b/src/test/run-make-fulldeps/target-specs/definitely-not-builtin-target.json
new file mode 100644 (file)
index 0000000..b36fa99
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "arch": "x86_64",
+  "is-builtin": true,
+  "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
+  "llvm-target": "x86_64-unknown-unknown-gnu",
+  "target-pointer-width": "64"
+}
diff --git a/src/test/run-make-fulldeps/target-specs/mismatching-data-layout.json b/src/test/run-make-fulldeps/target-specs/mismatching-data-layout.json
new file mode 100644 (file)
index 0000000..d12caaa
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "arch": "x86_64",
+  "data-layout": "e-m:e-i64:16:32:64",
+  "llvm-target": "x86_64-unknown-unknown-gnu",
+  "target-pointer-width": "64"
+}
diff --git a/src/test/run-make/emit-path-unhashed/Makefile b/src/test/run-make/emit-path-unhashed/Makefile
new file mode 100644 (file)
index 0000000..b6b2d8a
--- /dev/null
@@ -0,0 +1,37 @@
+-include ../../run-make-fulldeps/tools.mk
+
+OUT=$(TMPDIR)/emit
+
+# --emit KIND=PATH should not affect crate hash vs --emit KIND
+all: $(OUT)/a/libfoo.rlib $(OUT)/b/libfoo.rlib $(OUT)/c/libfoo.rlib \
+               $(TMPDIR)/libfoo.rlib
+       $(RUSTC) -Zls $(TMPDIR)/libfoo.rlib > $(TMPDIR)/base.txt
+       $(RUSTC) -Zls $(OUT)/a/libfoo.rlib > $(TMPDIR)/a.txt
+       $(RUSTC) -Zls $(OUT)/b/libfoo.rlib > $(TMPDIR)/b.txt
+       $(RUSTC) -Zls $(OUT)/c/libfoo.rlib > $(TMPDIR)/c.txt
+
+       diff $(TMPDIR)/base.txt $(TMPDIR)/a.txt
+       diff $(TMPDIR)/base.txt $(TMPDIR)/b.txt
+
+       # Different KIND parameters do affect hash.
+       # diff exits 1 on difference, 2 on trouble
+       diff $(TMPDIR)/base.txt $(TMPDIR)/c.txt ; test "$$?" -eq 1
+
+# Default output name
+$(TMPDIR)/libfoo.rlib: foo.rs
+       $(RUSTC) --emit link foo.rs
+
+# Output named with -o
+$(OUT)/a/libfoo.rlib: foo.rs
+       mkdir -p $(OUT)/a
+       $(RUSTC) --emit link -o $@ foo.rs
+
+# Output named with KIND=PATH
+$(OUT)/b/libfoo.rlib: foo.rs
+       mkdir -p $(OUT)/b
+       $(RUSTC) --emit link=$@ foo.rs
+
+# Output multiple kinds
+$(OUT)/c/libfoo.rlib: foo.rs
+       mkdir -p $(OUT)/c
+       $(RUSTC) --emit link=$@,metadata foo.rs
diff --git a/src/test/run-make/emit-path-unhashed/foo.rs b/src/test/run-make/emit-path-unhashed/foo.rs
new file mode 100644 (file)
index 0000000..c1bfaa6
--- /dev/null
@@ -0,0 +1 @@
+#![crate_type = "rlib"]
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/run-make/track-path-dep-info/Makefile b/src/test/run-make/track-path-dep-info/Makefile
new file mode 100644 (file)
index 0000000..465d374
--- /dev/null
@@ -0,0 +1,13 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# FIXME(eddyb) provide `HOST_RUSTC` and `TARGET_RUSTC`
+# instead of hardcoding them everywhere they're needed.
+ifeq ($(IS_MUSL_HOST),1)
+ADDITIONAL_ARGS := $(RUSTFLAGS)
+endif
+
+all:
+       # Proc macro
+       $(BARE_RUSTC) $(ADDITIONAL_ARGS) --out-dir $(TMPDIR) macro_def.rs
+       EXISTING_PROC_MACRO_ENV=1 $(RUSTC) --emit dep-info macro_use.rs
+       $(CGREP) "emojis.txt:" < $(TMPDIR)/macro_use.d
diff --git a/src/test/run-make/track-path-dep-info/emojis.txt b/src/test/run-make/track-path-dep-info/emojis.txt
new file mode 100644 (file)
index 0000000..e1a7284
--- /dev/null
@@ -0,0 +1 @@
+👾👾👾👾👾👾
diff --git a/src/test/run-make/track-path-dep-info/macro_def.rs b/src/test/run-make/track-path-dep-info/macro_def.rs
new file mode 100644 (file)
index 0000000..8777ce2
--- /dev/null
@@ -0,0 +1,11 @@
+#![feature(track_path)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn access_tracked_paths(_: TokenStream) -> TokenStream {
+    tracked_path::path("emojis.txt");
+    TokenStream::new()
+}
diff --git a/src/test/run-make/track-path-dep-info/macro_use.rs b/src/test/run-make/track-path-dep-info/macro_use.rs
new file mode 100644 (file)
index 0000000..3c49fd0
--- /dev/null
@@ -0,0 +1,6 @@
+#[macro_use]
+extern crate macro_def;
+
+access_tracked_paths!();
+
+fn main() {}
index aa20d6aa4bf27b35accfeaed036ec6f0ebd77d1d..a9aad54162f110749cd45699c399452f27e61ed9 100644 (file)
@@ -2,4 +2,4 @@
 
 all:
        $(RUSTDOC) --output-format=json x.html 2>&1 | diff - output-format-json.stderr
-       $(RUSTC) --force-warns dead_code x.rs 2>&1 | diff - force-warns.stderr
+       $(RUSTC) --force-warn dead_code x.rs 2>&1 | diff - force-warn.stderr
diff --git a/src/test/run-make/unstable-flag-required/force-warn.stderr b/src/test/run-make/unstable-flag-required/force-warn.stderr
new file mode 100644 (file)
index 0000000..1b70dc8
--- /dev/null
@@ -0,0 +1,2 @@
+error: the `-Z unstable-options` flag must also be passed to enable the flag `--force-warn=lints`
+
diff --git a/src/test/run-make/unstable-flag-required/force-warns.stderr b/src/test/run-make/unstable-flag-required/force-warns.stderr
deleted file mode 100644 (file)
index e093619..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-error: the `-Z unstable-options` flag must also be passed to enable the flag `--force-warns=lints`
-
index 499a98a3d223793b413d0c6776758b944ed24151..8efe7a578b8f065942641a70db551e3c317a1b31 100644 (file)
@@ -8,5 +8,17 @@ test what's being currently displayed in the web page.
 
 You can find more information and its documentation in its [repository][browser-ui-test].
 
+If you need to have more information on the tests run, you can use `--test-args`:
+
+```bash
+$ ./x.py test src/test/rustdoc-gui --stage 1 --jobs 8 --test-args --debug
+```
+
+There are three options supported:
+
+ * `--debug`: allows to see puppeteer commands.
+ * `--no-headless`: disable headless mode so you can see what's going on.
+ * `--show-text`: by default, text isn't rendered because of issues with fonts, it enables it back.
+
 [browser-ui-test]: https://github.com/GuillaumeGomez/browser-UI-test/
 [puppeteer]: https://pptr.dev/
diff --git a/src/test/rustdoc-gui/auto-hide-trait-implementations.goml b/src/test/rustdoc-gui/auto-hide-trait-implementations.goml
new file mode 100644 (file)
index 0000000..7b1358f
--- /dev/null
@@ -0,0 +1,13 @@
+// Checks that the setting "auto hide trait implementations" is working as expected.
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+
+// By default, the trait implementations are not collapsed.
+assert-attribute: ("#trait-implementations-list > details", {"open": ""}, ALL)
+
+// We now set the setting to auto hide all trait implementations.
+local-storage: {"rustdoc-auto-hide-trait-implementations": "true" }
+// We reload to ensure the trait implementations are collapsed as expected.
+reload:
+
+// We now check that all matching elements don't have the open attributes.
+assert-attribute-false: ("#trait-implementations-list > details", {"open": ""}, ALL)
diff --git a/src/test/rustdoc-gui/ayu-code-tag-colors.goml b/src/test/rustdoc-gui/ayu-code-tag-colors.goml
new file mode 100644 (file)
index 0000000..50af36f
--- /dev/null
@@ -0,0 +1,13 @@
+// The ayu theme has a different color for the "<code>" tags in the doc blocks. We need to
+// check that the rule isn't applied on other "<code>" elements.
+goto: file://|DOC_PATH|/test_docs/enum.AnEnum.html
+// We need to show the text, otherwise the colors aren't "computed" by the web browser.
+show-text: true
+// We set the theme to ayu.
+local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"}
+// We reload to get the text appearing and the theme applied.
+reload:
+
+assert-css: (".docblock code", {"color": "rgb(255, 180, 84)"}, ALL)
+// It includes variants and the "titles" as well (for example: "impl RefUnwindSafe for AnEnum").
+assert-css: ("div:not(.docblock) > code", {"color": "rgb(197, 197, 197)"}, ALL)
diff --git a/src/test/rustdoc-gui/basic-code.goml b/src/test/rustdoc-gui/basic-code.goml
new file mode 100644 (file)
index 0000000..27deb2c
--- /dev/null
@@ -0,0 +1,3 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+click: ".srclink"
+assert-count: (".line-numbers", 1)
diff --git a/src/test/rustdoc-gui/basic.goml b/src/test/rustdoc-gui/basic.goml
new file mode 100644 (file)
index 0000000..44fcec3
--- /dev/null
@@ -0,0 +1,4 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+assert: ("#functions")
+goto: ./struct.Foo.html
+assert: ("div.type-decl")
diff --git a/src/test/rustdoc-gui/check_info_sign_position.goml b/src/test/rustdoc-gui/check_info_sign_position.goml
new file mode 100644 (file)
index 0000000..94e3fe7
--- /dev/null
@@ -0,0 +1,9 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+goto: ./fn.check_list_code_block.html
+// If the codeblock is the first element of the docblock, the information tooltip must have
+// have some top margin to avoid going over the toggle (the "[+]").
+assert-css: (".docblock > .information > .compile_fail", { "margin-top": "16px" })
+// Checks that the other codeblocks don't have this top margin.
+assert-css: ("ol > li > .information > .compile_fail", { "margin-top": "0px" })
+assert-css: ("ol > li > .information > .ignore", { "margin-top": "0px" })
+assert-css: (".docblock > .information > .ignore", { "margin-top": "0px" })
diff --git a/src/test/rustdoc-gui/code-blocks-overflow.goml b/src/test/rustdoc-gui/code-blocks-overflow.goml
new file mode 100644 (file)
index 0000000..ee4dad4
--- /dev/null
@@ -0,0 +1,8 @@
+// This test ensures that codeblocks content don't overflow.
+goto: file://|DOC_PATH|/lib2/sub_mod/struct.Foo.html
+size: (1080, 600)
+// There should be two codeblocks: a rust one and a non-rust one.
+assert-count: (".docblock > .example-wrap", 2)
+assert: ".docblock > .example-wrap > .language-txt"
+assert: ".docblock > .example-wrap > .rust-example-rendered"
+assert-css: (".docblock > .example-wrap > pre", {"width": "796px", "overflow-x": "auto"}, ALL)
diff --git a/src/test/rustdoc-gui/code-sidebar-toggle.goml b/src/test/rustdoc-gui/code-sidebar-toggle.goml
new file mode 100644 (file)
index 0000000..00326e9
--- /dev/null
@@ -0,0 +1,6 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+click: ".srclink"
+click: "#sidebar-toggle"
+wait-for: 500
+fail: true
+assert-css: ("#source-sidebar", { "left": "-300px" })
diff --git a/src/test/rustdoc-gui/default-settings.goml b/src/test/rustdoc-gui/default-settings.goml
new file mode 100644 (file)
index 0000000..68b674a
--- /dev/null
@@ -0,0 +1,8 @@
+// This test ensures that the default settings are correctly applied.
+//
+// The "settings" crate uses "ayu" as default setting, which is what we will
+// check.
+goto: file://|DOC_PATH|/settings/index.html
+// Wait a bit to be sure the default theme is applied.
+wait-for: 1000
+assert-css: ("body", {"background-color": "rgb(15, 20, 25)"})
diff --git a/src/test/rustdoc-gui/docblock-table-overflow.goml b/src/test/rustdoc-gui/docblock-table-overflow.goml
new file mode 100644 (file)
index 0000000..9ab7cd0
--- /dev/null
@@ -0,0 +1,9 @@
+// This test ensures that the type declaration content overflow is handled inside the <pre> directly.
+goto: file://|DOC_PATH|/lib2/long_table/struct.Foo.html
+// We set a fixed size so there is no chance of "random" resize.
+size: (1100, 800)
+// Logically, the ".docblock" and the "<p>" should have the same scroll width.
+compare-elements-property: (".top-doc .docblock", ".top-doc .docblock > p", ["scrollWidth"])
+assert-property: (".top-doc .docblock", {"scrollWidth": "816"})
+// However, since there is overflow in the <table>, its scroll width is bigger.
+assert-property: (".top-doc .docblock table", {"scrollWidth": "1573"})
diff --git a/src/test/rustdoc-gui/escape-key.goml b/src/test/rustdoc-gui/escape-key.goml
new file mode 100644 (file)
index 0000000..5cf8a5e
--- /dev/null
@@ -0,0 +1,34 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+// First, we check that the search results are hidden when the Escape key is pressed.
+write: (".search-input", "test")
+wait-for: "#search > h1" // The search element is empty before the first search 
+assert-attribute: ("#search", {"class": "content"})
+assert-attribute: ("#main", {"class": "content hidden"})
+press-key: "Escape"
+assert-attribute: ("#search", {"class": "content hidden"})
+assert-attribute: ("#main", {"class": "content"})
+
+// Check that focusing the search input brings back the search results
+focus: ".search-input"
+assert-attribute: ("#search", {"class": "content"})
+assert-attribute: ("#main", {"class": "content hidden"})
+
+// Now let's check that when the help popup is displayed and we press Escape, it doesn't
+// hide the search results too.
+click: "#help-button"
+assert-attribute: ("#help", {"class": ""})
+press-key: "Escape"
+assert-attribute: ("#help", {"class": "hidden"})
+assert-attribute: ("#search", {"class": "content"})
+assert-attribute: ("#main", {"class": "content hidden"})
+
+// Check that Escape hides the search results when a search result is focused.
+focus: ".search-input"
+assert: ".search-input:focus"
+press-key: "ArrowDown"
+assert-false: ".search-input:focus"
+assert: "#results a:focus"
+press-key: "Escape"
+assert-attribute: ("#help", {"class": "hidden"})
+assert-attribute: ("#search", {"class": "content hidden"})
+assert-attribute: ("#main", {"class": "content"})
diff --git a/src/test/rustdoc-gui/font-weight.goml b/src/test/rustdoc-gui/font-weight.goml
new file mode 100644 (file)
index 0000000..92ad92a
--- /dev/null
@@ -0,0 +1,20 @@
+goto: file://|DOC_PATH|/lib2/struct.Foo.html
+// This test checks that the font weight is correctly applied.
+assert-css: ("//*[@class='docblock type-decl']//a[text()='Alias']", {"font-weight": "400"})
+assert-css: ("//*[@class='structfield small-section-header']//a[text()='Alias']", {"font-weight": "400"})
+assert-css: ("#method\.a_method > .code-header", {"font-weight": "600"})
+assert-css: ("#associatedtype\.X > .code-header", {"font-weight": "600"})
+assert-css: ("#associatedconstant\.Y > .code-header", {"font-weight": "600"})
+
+goto: file://|DOC_PATH|/test_docs/type.SomeType.html
+assert-css: (".top-doc .docblock p", {"font-weight": "400"}, ALL)
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+assert-css: (".impl-items .method", {"font-weight": "600"}, ALL)
+
+goto: file://|DOC_PATH|/lib2/trait.Trait.html
+assert-count: (".methods .type", 1)
+assert-css: (".methods .type", {"font-weight": "600"})
+assert-count: (".methods .constant", 1)
+assert-css: (".methods .constant", {"font-weight": "600"})
+assert-css: (".methods .method", {"font-weight": "600"})
diff --git a/src/test/rustdoc-gui/hash-item-expansion.goml b/src/test/rustdoc-gui/hash-item-expansion.goml
new file mode 100644 (file)
index 0000000..42bc1c1
--- /dev/null
@@ -0,0 +1,15 @@
+// This test ensures that the element corresponding to the hash is displayed.
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.borrow
+// In the blanket implementations list, "Borrow" is the second one, hence the ":nth(2)".
+assert-attribute: ("#blanket-implementations-list > details:nth-child(2)", {"open": ""})
+// We first check that the impl block is open by default.
+assert-attribute: ("#implementations + details", {"open": ""})
+// We collapse it.
+click: "#implementations + details > summary"
+// We check that it was collapsed as expected.
+assert-attribute-false: ("#implementations + details", {"open": ""})
+// To ensure that we will click on the currently hidden method.
+assert-text: (".sidebar-links > a", "must_use")
+click: ".sidebar-links > a"
+// We check that the impl block was opened as expected so that we can see the method.
+assert-attribute: ("#implementations + details", {"open": ""})
diff --git a/src/test/rustdoc-gui/impl-default-expansion.goml b/src/test/rustdoc-gui/impl-default-expansion.goml
new file mode 100644 (file)
index 0000000..b268ec6
--- /dev/null
@@ -0,0 +1,3 @@
+// This test ensures that the impl blocks are open by default.
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+assert-attribute: ("#main > details.implementors-toggle", {"open": ""})
diff --git a/src/test/rustdoc-gui/implementors.goml b/src/test/rustdoc-gui/implementors.goml
new file mode 100644 (file)
index 0000000..c9042eb
--- /dev/null
@@ -0,0 +1,16 @@
+// The goal of this test is to check that the external trait implementors, generated with JS,
+// have the same display than the "local" ones.
+goto: file://|DOC_PATH|/implementors/trait.Whatever.html
+assert: "#implementors-list"
+// There are supposed to be two implementors listed.
+assert-count: ("#implementors-list .impl", 2)
+// Now we check that both implementors have an anchor, an ID and a similar DOM.
+assert: ("#implementors-list .impl:nth-child(1) > a.anchor")
+assert-attribute: ("#implementors-list .impl:nth-child(1)", {"id": "impl-Whatever"})
+assert-attribute: ("#implementors-list .impl:nth-child(1) > a.anchor", {"href": "#impl-Whatever"})
+assert: "#implementors-list .impl:nth-child(1) > .code-header.in-band"
+
+assert: ("#implementors-list .impl:nth-child(2) > a.anchor")
+assert-attribute: ("#implementors-list .impl:nth-child(2)", {"id": "impl-Whatever-1"})
+assert-attribute: ("#implementors-list .impl:nth-child(2) > a.anchor", {"href": "#impl-Whatever-1"})
+assert: "#implementors-list .impl:nth-child(2) > .code-header.in-band"
diff --git a/src/test/rustdoc-gui/item-info-width.goml b/src/test/rustdoc-gui/item-info-width.goml
new file mode 100644 (file)
index 0000000..44b79e6
--- /dev/null
@@ -0,0 +1,7 @@
+// This test ensures that the item information don't take 100% of the width if unnecessary.
+goto: file://|DOC_PATH|/lib2/struct.Foo.html
+// We set a fixed size so there is no chance of "random" resize.
+size: (1100, 800)
+// We check that ".item-info" is bigger than its content.
+assert-css: (".item-info", {"width": "807px"})
+assert-css: (".item-info .stab", {"width": "343px"})
diff --git a/src/test/rustdoc-gui/item-summary-table.goml b/src/test/rustdoc-gui/item-summary-table.goml
new file mode 100644 (file)
index 0000000..6bf4e28
--- /dev/null
@@ -0,0 +1,6 @@
+// This test ensures that <table> elements aren't display in items summary.
+goto: file://|DOC_PATH|/lib2/summary_table/index.html
+// We check that we picked the right item first.
+assert-text: (".item-table .item-left", "Foo")
+// Then we check that its summary is empty.
+assert-text: (".item-table .item-right", "")
diff --git a/src/test/rustdoc-gui/label-next-to-symbol.goml b/src/test/rustdoc-gui/label-next-to-symbol.goml
new file mode 100644 (file)
index 0000000..4fef4e6
--- /dev/null
@@ -0,0 +1,36 @@
+// These tests verify that labels like "UNIX" and "Deprecated" stay on the same line as their symbol.
+// It also verifies the staggered layout on mobile.
+goto: file://|DOC_PATH|/test_docs/index.html
+
+// Desktop view
+size: (1080, 600)
+assert: (".stab.deprecated")
+assert: (".stab.portability")
+
+// make sure that deprecated and portability are different colours
+assert-css: (".item-table .item-left .stab.deprecated", { "background-color": "rgb(255, 196, 196)" })
+assert-css: (".item-table .item-left .stab.portability", { "background-color": "rgb(243, 223, 255)" })
+
+// table like view
+assert-css: (".item-right.docblock-short", { "padding-left": "0px" })
+compare-elements-position-near: ("//*[@class='item-left module-item']//a[text()='replaced_function']", ".item-left .stab.deprecated", {"y": 2})
+compare-elements-position: (".item-left .stab.deprecated", ".item-left .stab.portability", ("y"))
+
+// Ensure no wrap
+compare-elements-position-near: ("//*[@class='item-left module-item']//a[text()='replaced_function']", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']", {"y": 2})
+// compare parent elements
+compare-elements-position: ("//*[@class='item-left module-item']//a[text()='replaced_function']/..", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']/..", ("y"))
+
+
+// Mobile view
+size: (600, 600)
+// staggered layout with 2em spacing
+assert-css: (".item-right.docblock-short", { "padding-left": "32px" })
+compare-elements-position-near: ("//*[@class='item-left module-item']//a[text()='replaced_function']", ".item-left .stab.deprecated", {"y": 1})
+compare-elements-position: (".item-left .stab.deprecated", ".item-left .stab.portability", ("y"))
+
+// Ensure wrap
+compare-elements-position-near-false: ("//*[@class='item-left module-item']//a[text()='replaced_function']", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']", {"y": 12})
+// compare parent elements
+compare-elements-position-false: ("//*[@class='item-left module-item']//a[text()='replaced_function']/..", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']/..", ("y"))
+compare-elements-position-false: (".item-left .stab.deprecated", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']", ("y"))
diff --git a/src/test/rustdoc-gui/list_code_block.goml b/src/test/rustdoc-gui/list_code_block.goml
new file mode 100644 (file)
index 0000000..7d3490e
--- /dev/null
@@ -0,0 +1,3 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+goto: ./fn.check_list_code_block.html
+assert: ("pre.rust.fn")
diff --git a/src/test/rustdoc-gui/module-items-font.goml b/src/test/rustdoc-gui/module-items-font.goml
new file mode 100644 (file)
index 0000000..817b148
--- /dev/null
@@ -0,0 +1,4 @@
+// This test checks that the correct font is used on module items (in index.html pages).
+goto: file://|DOC_PATH|/test_docs/index.html
+assert-css: (".item-table .module-item a", {"font-family": '"Fira Sans", Arial, sans-serif'}, ALL)
+assert-css: (".item-table .docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'}, ALL)
diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml
new file mode 100644 (file)
index 0000000..a098dbd
--- /dev/null
@@ -0,0 +1,17 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+write: (".search-input", "test")
+// Waiting for the search results to appear...
+wait-for: "#titles"
+assert-text: ("#results .externcrate", "test_docs")
+text: (".search-input", "")
+// We now want to change the crate filter.
+click: "#crate-search"
+// We select "lib2" option then press enter to change the filter.
+press-key: "ArrowDown"
+press-key: "Enter"
+// We now make the search again.
+write: (".search-input", "test")
+// Waiting for the search results to appear...
+wait-for: "#titles"
+// We check that there is no more "test_docs" appearing.
+assert-false: "#results .externcrate"
diff --git a/src/test/rustdoc-gui/search-input-mobile.goml b/src/test/rustdoc-gui/search-input-mobile.goml
new file mode 100644 (file)
index 0000000..5c95db7
--- /dev/null
@@ -0,0 +1,11 @@
+// Test to ensure that you can click on the search input, whatever the width.
+// The PR which fixed it is: https://github.com/rust-lang/rust/pull/81592
+goto: file://|DOC_PATH|/test_docs/index.html
+size: (463, 700)
+// We first check that the search input isn't already focused.
+assert-false: ("input.search-input:focus")
+click: "input.search-input"
+reload:
+size: (750, 700)
+click: "input.search-input"
+assert: ("input.search-input:focus")
diff --git a/src/test/rustdoc-gui/search-result-color.goml b/src/test/rustdoc-gui/search-result-color.goml
new file mode 100644 (file)
index 0000000..bb8ecb9
--- /dev/null
@@ -0,0 +1,41 @@
+// The goal of this test is to ensure the color of the text is the one expected.
+goto: file://|DOC_PATH|/test_docs/index.html?search=coo
+
+// This is needed so that the text color is computed.
+show-text: true
+
+// Ayu theme
+local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"}
+reload:
+
+// Waiting for the search results to appear...
+wait-for: "#titles"
+assert-css: ("//*[@class='desc']//*[text()='Just a normal struct.']", {"color": "rgb(197, 197, 197)"})
+assert-css: ("//*[@class='result-name']/*[text()='test_docs::']", {"color": "rgb(0, 150, 207)"})
+
+// Checking the color for "keyword".
+assert-css: ("//*[@class='result-name']//*[text()='(keyword)']", {"color": "rgb(120, 135, 151)"})
+
+// Dark theme
+local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"}
+reload:
+
+// Waiting for the search results to appear...
+wait-for: "#titles"
+assert-css: ("//*[@class='desc']//*[text()='Just a normal struct.']", {"color": "rgb(221, 221, 221)"})
+assert-css: ("//*[@class='result-name']/*[text()='test_docs::']", {"color": "rgb(221, 221, 221)"})
+
+// Checking the color for "keyword".
+assert-css: ("//*[@class='result-name']//*[text()='(keyword)']", {"color": "rgb(221, 221, 221)"})
+
+// Light theme
+local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
+reload:
+
+// Waiting for the search results to appear...
+wait-for: "#titles"
+assert-css: ("//*[@class='desc']//*[text()='Just a normal struct.']", {"color": "rgb(0, 0, 0)"})
+assert-css: ("//*[@class='result-name']/*[text()='test_docs::']", {"color": "rgb(0, 0, 0)"})
+
+// Checking the color for "keyword".
+assert-css: ("//*[@class='result-name']//*[text()='(keyword)']", {"color": "rgb(0, 0, 0)"})
diff --git a/src/test/rustdoc-gui/search-result-colors.goml b/src/test/rustdoc-gui/search-result-colors.goml
new file mode 100644 (file)
index 0000000..6ed6200
--- /dev/null
@@ -0,0 +1,14 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+// We set the theme so we're sure that the corect values will be used, whatever the computer
+// this test is running on.
+local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"}
+// If the text isn't displayed, the browser doesn't compute color style correctly...
+show-text: true
+// We reload the page so the local storage settings are being used.
+reload:
+write: (".search-input", "thisisanalias")
+// Waiting for the search results to appear...
+wait-for: "#titles"
+// Checking that the colors for the alias element are the ones expected.
+assert-css: (".result-name > .alias", {"color": "rgb(255, 255, 255)"})
+assert-css: (".result-name > .alias > .grey", {"color": "rgb(204, 204, 204)"})
diff --git a/src/test/rustdoc-gui/search-result-description.goml b/src/test/rustdoc-gui/search-result-description.goml
new file mode 100644 (file)
index 0000000..d8cb6ee
--- /dev/null
@@ -0,0 +1,5 @@
+// This test is to ensure that the codeblocks are correctly rendered in the search results.
+goto: file://|DOC_PATH|/test_docs/index.html?search=some_more_function
+// Waiting for the search results to appear...
+wait-for: "#titles"
+assert-text: (".search-results .desc code", "format!")
diff --git a/src/test/rustdoc-gui/search-result-display.goml b/src/test/rustdoc-gui/search-result-display.goml
new file mode 100644 (file)
index 0000000..ea94e56
--- /dev/null
@@ -0,0 +1,12 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+size: (900, 1000)
+write: (".search-input", "test")
+// Waiting for the search results to appear...
+wait-for: "#titles"
+// The width is returned by "getComputedStyle" which returns the exact number instead of the
+// CSS rule which is "50%"...
+assert-css: (".search-results div.desc", {"width": "320px"})
+size: (600, 100)
+// As counter-intuitive as it may seem, in this width, the width is "100%", which is why
+// when computed it's larger.
+assert-css: (".search-results div.desc", {"width": "570px"})
diff --git a/src/test/rustdoc-gui/search-result-go-to-first.goml b/src/test/rustdoc-gui/search-result-go-to-first.goml
new file mode 100644 (file)
index 0000000..5d709f6
--- /dev/null
@@ -0,0 +1,20 @@
+// This test ensures that the "go_to_first" feature is working as expected.
+
+// First, we check that the first page doesn't have the string we're looking for to ensure
+// that the feature is changing page as expected.
+goto: file://|DOC_PATH|/test_docs/index.html
+assert-text-false: (".fqn .in-band", "Struct test_docs::Foo")
+
+// We now check that we land on the search result page if "go_to_first" isn't set.
+goto: file://|DOC_PATH|/test_docs/index.html?search=struct%3AFoo
+// Waiting for the search results to appear...
+wait-for: "#titles"
+assert-text-false: (".fqn .in-band", "Struct test_docs::Foo")
+// Ensure that the search results are displayed, not the "normal" content.
+assert-css: ("#main", {"display": "none"})
+
+// Now we can check that the feature is working as expected!
+goto: file://|DOC_PATH|/test_docs/index.html?search=struct%3AFoo&go_to_first=true
+// Waiting for the page to load...
+wait-for: 500
+assert-text: (".fqn .in-band", "Struct test_docs::Foo")
diff --git a/src/test/rustdoc-gui/search-result-keyword.goml b/src/test/rustdoc-gui/search-result-keyword.goml
new file mode 100644 (file)
index 0000000..5342d43
--- /dev/null
@@ -0,0 +1,10 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+write: (".search-input", "CookieMonster")
+// Waiting for the search results to appear...
+wait-for: "#titles"
+// Note: The two next assert commands could be merged as one but readability would be
+// less good.
+//
+// Checking that the CSS is displaying " (keyword)" in italic.
+assert-text: (".result-name span.keyword > i", "(keyword)")
+assert-text: (".result-name span.keyword", "CookieMonster (keyword)")
diff --git a/src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml b/src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml
new file mode 100644 (file)
index 0000000..a61ec67
--- /dev/null
@@ -0,0 +1,21 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+write: (".search-input", "Foo")
+// Waiting for the search results to appear...
+wait-for: "#titles"
+assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
+
+// To go back to the original "state"
+goto: file://|DOC_PATH|/test_docs/index.html
+write: (".search-input", "-> String")
+// Waiting for the search results to appear...
+wait-for: "#titles"
+// With this search, only the last tab shouldn't be empty so it should be selected.
+assert-attribute: ("#titles > button:nth-of-type(3)", {"class": "selected"})
+
+// To go back to the original "state"
+goto: file://|DOC_PATH|/test_docs/index.html
+write: (".search-input", "-> Something")
+// Waiting for the search results to appear...
+wait-for: "#titles"
+// With this search, all the tabs are empty so the first one should remain selected.
+assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
diff --git a/src/test/rustdoc-gui/shortcuts.goml b/src/test/rustdoc-gui/shortcuts.goml
new file mode 100644 (file)
index 0000000..42d945d
--- /dev/null
@@ -0,0 +1,26 @@
+// Check that the various shortcuts are working.
+goto: file://|DOC_PATH|/test_docs/index.html
+// We first check that the search input isn't already focused.
+assert-false: "input.search-input:focus"
+press-key: "s"
+assert: "input.search-input:focus"
+press-key: "Escape"
+assert-false: "input.search-input:focus"
+// We now check for the help popup.
+press-key: "?"
+assert-css: ("#help", {"display": "flex"})
+assert-false: "#help.hidden"
+press-key: "Escape"
+assert-css: ("#help.hidden", {"display": "none"})
+// Check for the themes list.
+assert-css: ("#theme-choices", {"display": "none"})
+press-key: "t"
+assert-css: ("#theme-choices", {"display": "block"})
+press-key: "t"
+// We ensure that 't' hides back the menu.
+assert-css: ("#theme-choices", {"display": "none"})
+press-key: "t"
+assert-css: ("#theme-choices", {"display": "block"})
+press-key: "Escape"
+// We ensure that 'Escape' hides the menu too.
+assert-css: ("#theme-choices", {"display": "none"})
diff --git a/src/test/rustdoc-gui/sidebar-mobile.goml b/src/test/rustdoc-gui/sidebar-mobile.goml
new file mode 100644 (file)
index 0000000..7138f91
--- /dev/null
@@ -0,0 +1,20 @@
+// This test ensure that the sidebar isn't "hidden" on mobile but instead moved out of the viewport.
+// This is especially important for devices for "text-first" content (like for users with
+// sight issues).
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+// Switching to "mobile view" by reducing the width to 600px.
+size: (600, 600)
+assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"})
+// Opening the sidebar menu.
+click: ".sidebar-menu"
+assert-css: (".sidebar-elems", {"display": "block", "left": "0px"})
+// Closing the sidebar menu.
+click: ".sidebar-menu"
+assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"})
+// Force the sidebar open by focusing a link inside it.
+// This makes it easier for keyboard users to get to it.
+focus: ".sidebar-title a"
+assert-css: (".sidebar-elems", {"display": "block", "left": "0px"})
+// When we tab out of the sidebar, close it.
+focus: ".search-input"
+assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"})
diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml
new file mode 100644 (file)
index 0000000..c8ebb8c
--- /dev/null
@@ -0,0 +1,60 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+assert-text: (".sidebar > .location", "Crate test_docs")
+// In modules, we only have one "location" element.
+assert-count: (".sidebar .location", 1)
+assert-text: (".sidebar-elems > #all-types", "See all test_docs's items")
+// We check that we have the crates list and that the "current" on is "test_docs".
+assert-text: (".sidebar-elems > .crate > ul > li > a.current", "test_docs")
+// And we're also supposed to have the list of items in the current module.
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Enums")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Traits")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Functions")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(6)", "Type Definitions")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(7)", "Keywords")
+assert-text: ("#structs + .item-table .item-left > a", "Foo")
+click: "#structs + .item-table .item-left > a"
+
+// PAGE: struct.Foo.html
+assert-count: (".sidebar .location", 2)
+// We check that there is no crate listed outside of the top level.
+assert-false: ".sidebar-elems > .crate"
+// We now go back to the crate page to click on the "lib2" crate link.
+goto: file://|DOC_PATH|/test_docs/index.html
+click: ".sidebar-elems > .crate > ul > li:first-child > a"
+
+// PAGE: lib2/index.html
+goto: file://|DOC_PATH|/lib2/index.html
+assert-text: (".sidebar > .location", "Crate lib2")
+// We check that we have the crates list and that the "current" on is now "lib2".
+assert-text: (".sidebar-elems > .crate > ul > li > a.current", "lib2")
+// We now go to the "foobar" function page.
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Traits")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Functions")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Type Definitions")
+assert-text: ("#functions + .item-table .item-left > a", "foobar")
+click: "#functions + .item-table .item-left > a"
+
+// PAGE: fn.foobar.html
+// In items containing no items (like functions or constants) and in modules, we have one
+// "location" elements.
+assert-count: (".sidebar .location", 1)
+// There is a "<br>" tag between "in" and "lib2", but it doesn't count as a space.
+assert-text: (".sidebar .sidebar-elems .location", "Other items inlib2")
+// We check that we don't have the crate list.
+assert-false: ".sidebar-elems > .crate"
+
+goto: ./module/index.html
+assert-text: (".sidebar > .location", "Module module")
+// We check that we don't have the crate list.
+assert-false: ".sidebar-elems > .crate"
+
+goto: ./sub_module/sub_sub_module/index.html
+assert-text: (".sidebar > .location", "Module sub_sub_module")
+// We check that we don't have the crate list.
+assert-false: ".sidebar-elems > .crate"
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Functions")
+assert-text: ("#functions + .item-table .item-left > a", "foo")
diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml
new file mode 100644 (file)
index 0000000..d7bae93
--- /dev/null
@@ -0,0 +1,15 @@
+goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
+// Check that we can click on the line number.
+click: (40, 224) // This is the position of the span for line 4.
+// Unfortunately, "#4" isn't a valid query selector, so we have to go around that limitation
+// by instead getting the nth span.
+assert-attribute: (".line-numbers > span:nth-child(4)", {"class": "line-highlighted"})
+// We now check that the good spans are highlighted
+goto: file://|DOC_PATH|/src/test_docs/lib.rs.html#4-6
+assert-attribute-false: (".line-numbers > span:nth-child(3)", {"class": "line-highlighted"})
+assert-attribute: (".line-numbers > span:nth-child(4)", {"class": "line-highlighted"})
+assert-attribute: (".line-numbers > span:nth-child(5)", {"class": "line-highlighted"})
+assert-attribute: (".line-numbers > span:nth-child(6)", {"class": "line-highlighted"})
+assert-attribute-false: (".line-numbers > span:nth-child(7)", {"class": "line-highlighted"})
+// This is to ensure that the content is correctly align with the line numbers.
+compare-elements-position: ("//*[@id='1']", ".rust > span", ("y"))
diff --git a/src/test/rustdoc-gui/src/lib.rs b/src/test/rustdoc-gui/src/lib.rs
deleted file mode 100644 (file)
index 5141b6d..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-//! The point of this crate is to be able to have enough different "kinds" of
-//! documentation generated so we can test each different features.
-
-#![crate_name = "test_docs"]
-#![feature(doc_keyword)]
-
-use std::fmt;
-
-/// Basic function with some code examples:
-///
-/// ```
-/// println!("nothing fancy");
-/// ```
-///
-/// A failing to compile one:
-///
-/// ```compile_fail
-/// println!("where did my argument {} go? :'(");
-/// ```
-///
-/// An ignored one:
-///
-/// ```ignore (it's a test)
-/// Let's say I'm just some text will ya?
-/// ```
-pub fn foo() {}
-
-/// Just a normal struct.
-pub struct Foo;
-
-impl Foo {
-    #[must_use]
-    pub fn must_use(&self) -> bool {
-        true
-    }
-}
-
-/// Just a normal enum.
-#[doc(alias = "ThisIsAnAlias")]
-pub enum WhoLetTheDogOut {
-    /// Woof!
-    Woof,
-    /// Meoooooooow...
-    Meow,
-}
-
-/// Who doesn't love to wrap a `format!` call?
-pub fn some_more_function<T: fmt::Debug>(t: &T) -> String {
-    format!("{:?}", t)
-}
-
-/// Woohoo! A trait!
-pub trait AnotherOne {
-    /// Some func 3.
-    fn func3();
-
-    /// Some func 1.
-    fn func1();
-
-    fn another();
-    fn why_not();
-
-    /// Some func 2.
-    fn func2();
-
-    fn hello();
-}
-
-/// ```compile_fail
-/// whatever
-/// ```
-///
-/// Check for "i" signs in lists!
-///
-/// 1. elem 1
-/// 2. test 1
-///    ```compile_fail
-///    fn foo() {}
-///    ```
-/// 3. elem 3
-/// 4. ```ignore (it's a test)
-///    fn foo() {}
-///    ```
-/// 5. elem 5
-///
-/// Final one:
-///
-/// ```ignore (still a test)
-/// let x = 12;
-/// ```
-pub fn check_list_code_block() {}
-
-pub enum AnEnum {
-    WithVariants { and: usize, sub: usize, variants: usize },
-}
-
-#[doc(keyword = "CookieMonster")]
-pub mod keyword {}
-
-/// Just some type alias.
-pub type SomeType = u32;
diff --git a/src/test/rustdoc-gui/src/lib2.rs b/src/test/rustdoc-gui/src/lib2.rs
deleted file mode 100644 (file)
index 73384cb..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-pub mod module {
-    pub mod sub_module {
-        pub mod sub_sub_module {
-            pub fn foo() {}
-        }
-        pub fn bar() {}
-    }
-    pub fn whatever() {}
-}
-
-pub fn foobar() {}
diff --git a/src/test/rustdoc-gui/src/lib2/Cargo.lock b/src/test/rustdoc-gui/src/lib2/Cargo.lock
new file mode 100644 (file)
index 0000000..a5873ce
--- /dev/null
@@ -0,0 +1,14 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "implementors"
+version = "0.1.0"
+
+[[package]]
+name = "lib2"
+version = "0.1.0"
+dependencies = [
+ "implementors",
+]
diff --git a/src/test/rustdoc-gui/src/lib2/Cargo.toml b/src/test/rustdoc-gui/src/lib2/Cargo.toml
new file mode 100644 (file)
index 0000000..2e37f3f
--- /dev/null
@@ -0,0 +1,10 @@
+[package]
+name = "lib2"
+version = "0.1.0"
+edition = "2018"
+
+[lib]
+path = "lib.rs"
+
+[dependencies]
+implementors = { path = "./implementors" }
diff --git a/src/test/rustdoc-gui/src/lib2/implementors/Cargo.lock b/src/test/rustdoc-gui/src/lib2/implementors/Cargo.lock
new file mode 100644 (file)
index 0000000..cad99a9
--- /dev/null
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "implementors"
+version = "0.1.0"
diff --git a/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml b/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml
new file mode 100644 (file)
index 0000000..7ef1052
--- /dev/null
@@ -0,0 +1,7 @@
+[package]
+name = "implementors"
+version = "0.1.0"
+edition = "2018"
+
+[lib]
+path = "lib.rs"
diff --git a/src/test/rustdoc-gui/src/lib2/implementors/lib.rs b/src/test/rustdoc-gui/src/lib2/implementors/lib.rs
new file mode 100644 (file)
index 0000000..6417a6a
--- /dev/null
@@ -0,0 +1,11 @@
+pub trait Whatever {
+    type Foo;
+
+    fn method() {}
+}
+
+pub struct Struct;
+
+impl Whatever for Struct {
+    type Foo = u8;
+}
diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs
new file mode 100644 (file)
index 0000000..cb63a9f
--- /dev/null
@@ -0,0 +1,77 @@
+// ignore-tidy-linelength
+
+#![feature(doc_cfg)]
+
+pub mod module {
+    pub mod sub_module {
+        pub mod sub_sub_module {
+            pub fn foo() {}
+        }
+        pub fn bar() {}
+    }
+    pub fn whatever() {}
+}
+
+pub fn foobar() {}
+
+pub type Alias = u32;
+
+#[doc(cfg(feature = "foo-method"))]
+pub struct Foo {
+    pub x: Alias,
+}
+
+impl Foo {
+    pub fn a_method(&self) {}
+}
+
+pub trait Trait {
+    type X;
+    const Y: u32;
+
+    fn foo() {}
+}
+
+impl Trait for Foo {
+    type X = u32;
+    const Y: u32 = 0;
+}
+
+
+impl implementors::Whatever for Foo {
+    type Foo = u32;
+}
+
+pub mod sub_mod {
+    /// ```txt
+    /// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+    /// ```
+    ///
+    /// ```
+    /// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+    /// ```
+    pub struct Foo;
+}
+
+pub mod long_trait {
+    use std::ops::DerefMut;
+
+    pub trait ALongNameBecauseItHelpsTestingTheCurrentProblem: DerefMut<Target = u32>
+        + From<u128> + Send + Sync + AsRef<str> + 'static {}
+}
+
+pub mod long_table {
+    /// | This::is::a::kinda::very::long::header::number::one | This::is::a::kinda::very::long::header::number::two | This::is::a::kinda::very::long::header::number::one | This::is::a::kinda::very::long::header::number::two |
+    /// | ----------- | ----------- | ----------- | ----------- |
+    /// | This::is::a::kinda::long::content::number::one | This::is::a::kinda::very::long::content::number::two | This::is::a::kinda::long::content::number::one | This::is::a::kinda::very::long::content::number::two |
+    ///
+    /// I wanna sqdkfnqds f dsqf qds f dsqf dsq f dsq f qds f qds f qds f dsqq f dsf sqdf dsq fds f dsq f dq f ds fq sd fqds f dsq f sqd fsq df sd fdsqfqsd fdsq f dsq f dsqfd s dfq
+    pub struct Foo;
+}
+
+pub mod summary_table {
+    /// | header 1 | header 2 |
+    /// | -------- | -------- |
+    /// | content | content |
+    pub struct Foo;
+}
diff --git a/src/test/rustdoc-gui/src/settings/.cargo/config.toml b/src/test/rustdoc-gui/src/settings/.cargo/config.toml
new file mode 100644 (file)
index 0000000..bbb8d11
--- /dev/null
@@ -0,0 +1,2 @@
+[build]
+rustdocflags = ["--default-theme", "ayu"]
diff --git a/src/test/rustdoc-gui/src/settings/.package-cache b/src/test/rustdoc-gui/src/settings/.package-cache
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/test/rustdoc-gui/src/settings/Cargo.lock b/src/test/rustdoc-gui/src/settings/Cargo.lock
new file mode 100644 (file)
index 0000000..6f0de1a
--- /dev/null
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "settings"
+version = "0.1.0"
diff --git a/src/test/rustdoc-gui/src/settings/Cargo.toml b/src/test/rustdoc-gui/src/settings/Cargo.toml
new file mode 100644 (file)
index 0000000..c8a211a
--- /dev/null
@@ -0,0 +1,7 @@
+[package]
+name = "settings"
+version = "0.1.0"
+edition = "2018"
+
+[lib]
+path = "lib.rs"
diff --git a/src/test/rustdoc-gui/src/settings/lib.rs b/src/test/rustdoc-gui/src/settings/lib.rs
new file mode 100644 (file)
index 0000000..b76b432
--- /dev/null
@@ -0,0 +1 @@
+pub fn foo() {}
diff --git a/src/test/rustdoc-gui/src/test_docs/Cargo.lock b/src/test/rustdoc-gui/src/test_docs/Cargo.lock
new file mode 100644 (file)
index 0000000..6b80f6e
--- /dev/null
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "test_docs"
+version = "0.1.0"
diff --git a/src/test/rustdoc-gui/src/test_docs/Cargo.toml b/src/test/rustdoc-gui/src/test_docs/Cargo.toml
new file mode 100644 (file)
index 0000000..7f3c657
--- /dev/null
@@ -0,0 +1,7 @@
+[package]
+name = "test_docs"
+version = "0.1.0"
+edition = "2018"
+
+[lib]
+path = "lib.rs"
diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs
new file mode 100644 (file)
index 0000000..bed72cc
--- /dev/null
@@ -0,0 +1,116 @@
+//! The point of this crate is to be able to have enough different "kinds" of
+//! documentation generated so we can test each different features.
+
+#![crate_name = "test_docs"]
+#![feature(doc_keyword)]
+#![feature(doc_cfg)]
+
+use std::convert::AsRef;
+use std::fmt;
+
+/// Basic function with some code examples:
+///
+/// ```
+/// println!("nothing fancy");
+/// ```
+///
+/// A failing to compile one:
+///
+/// ```compile_fail
+/// println!("where did my argument {} go? :'(");
+/// ```
+///
+/// An ignored one:
+///
+/// ```ignore (it's a test)
+/// Let's say I'm just some text will ya?
+/// ```
+pub fn foo() {}
+
+/// Just a normal struct.
+pub struct Foo;
+
+impl Foo {
+    #[must_use]
+    pub fn must_use(&self) -> bool {
+        true
+    }
+}
+
+impl AsRef<str> for Foo {
+    fn as_ref(&self) -> &str {
+        "hello"
+    }
+}
+
+/// Just a normal enum.
+#[doc(alias = "ThisIsAnAlias")]
+pub enum WhoLetTheDogOut {
+    /// Woof!
+    Woof,
+    /// Meoooooooow...
+    Meow,
+}
+
+/// Who doesn't love to wrap a `format!` call?
+pub fn some_more_function<T: fmt::Debug>(t: &T) -> String {
+    format!("{:?}", t)
+}
+
+/// Woohoo! A trait!
+pub trait AnotherOne {
+    /// Some func 3.
+    fn func3();
+
+    /// Some func 1.
+    fn func1();
+
+    fn another();
+    fn why_not();
+
+    /// Some func 2.
+    fn func2();
+
+    fn hello();
+}
+
+/// ```compile_fail
+/// whatever
+/// ```
+///
+/// Check for "i" signs in lists!
+///
+/// 1. elem 1
+/// 2. test 1
+///    ```compile_fail
+///    fn foo() {}
+///    ```
+/// 3. elem 3
+/// 4. ```ignore (it's a test)
+///    fn foo() {}
+///    ```
+/// 5. elem 5
+///
+/// Final one:
+///
+/// ```ignore (still a test)
+/// let x = 12;
+/// ```
+pub fn check_list_code_block() {}
+
+/// a thing with a label
+#[deprecated(since = "1.0.0", note = "text why this deprecated")]
+#[doc(cfg(unix))]
+pub fn replaced_function() {}
+
+/// Some doc with `code`!
+pub enum AnEnum {
+    WithVariants { and: usize, sub: usize, variants: usize },
+}
+
+#[doc(keyword = "CookieMonster")]
+/// Some keyword.
+pub mod keyword {}
+
+/// Just some type alias.
+pub type SomeType = u32;
diff --git a/src/test/rustdoc-gui/theme-change.goml b/src/test/rustdoc-gui/theme-change.goml
new file mode 100644 (file)
index 0000000..5221cda
--- /dev/null
@@ -0,0 +1,10 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+click: "#theme-picker"
+click: "#theme-choices > button:first-child"
+wait-for: 500
+// should be the ayu theme so let's check the color
+assert-css: ("body", { "background-color": "rgb(15, 20, 25)" })
+click: "#theme-choices > button:last-child"
+wait-for: 500
+// should be the light theme so let's check the color
+assert-css: ("body", { "background-color": "rgb(255, 255, 255)" })
diff --git a/src/test/rustdoc-gui/toggle-docs-mobile.goml b/src/test/rustdoc-gui/toggle-docs-mobile.goml
new file mode 100644 (file)
index 0000000..471d887
--- /dev/null
@@ -0,0 +1,21 @@
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+size: (433, 600)
+assert-attribute: (".top-doc", {"open": ""})
+click: (4, 280) // This is the position of the top doc comment toggle
+assert-attribute-false: (".top-doc", {"open": ""})
+click: (4, 280)
+assert-attribute: (".top-doc", {"open": ""})
+// To ensure that the toggle isn't over the text, we check that the toggle isn't clicked.
+click: (3, 280)
+assert-attribute: (".top-doc", {"open": ""})
+
+// Now we do the same but with a little bigger width
+size: (600, 600)
+assert-attribute: (".top-doc", {"open": ""})
+click: (4, 240) // New Y position since all search elements are back on one line.
+assert-attribute-false: (".top-doc", {"open": ""})
+click: (4, 240)
+assert-attribute: (".top-doc", {"open": ""})
+// To ensure that the toggle isn't over the text, we check that the toggle isn't clicked.
+click: (3, 240)
+assert-attribute: (".top-doc", {"open": ""})
diff --git a/src/test/rustdoc-gui/toggle-docs.goml b/src/test/rustdoc-gui/toggle-docs.goml
new file mode 100644 (file)
index 0000000..136868f
--- /dev/null
@@ -0,0 +1,10 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+assert-attribute: ("#main > details.top-doc", {"open": ""})
+click: "#toggle-all-docs"
+wait-for: 1000
+// This is now collapsed so there shouldn't be the "open" attribute on details.
+assert-attribute-false: ("#main > details.top-doc", {"open": ""})
+click: "#toggle-all-docs"
+wait-for: 1000
+// Not collapsed anymore so the "open" attribute should be back.
+assert-attribute: ("#main > details.top-doc", {"open": ""})
diff --git a/src/test/rustdoc-gui/toggle-implementors.goml b/src/test/rustdoc-gui/toggle-implementors.goml
new file mode 100644 (file)
index 0000000..15521ff
--- /dev/null
@@ -0,0 +1,4 @@
+// This test ensures that the implementors toggle are not open by default.
+goto: file://|DOC_PATH|/implementors/trait.Whatever.html
+
+assert-attribute-false: ("#implementors-list > details", {"open": ""}, ALL)
diff --git a/src/test/rustdoc-gui/toggled-open-implementations.goml b/src/test/rustdoc-gui/toggled-open-implementations.goml
new file mode 100644 (file)
index 0000000..bc97b38
--- /dev/null
@@ -0,0 +1,5 @@
+// This tests that the "implementations" section on struct/enum pages
+// has all the implementations toggled open by default, so users can
+// find method names in those implementations with Ctrl-F.
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+assert-attribute: (".rustdoc-toggle.implementors-toggle", {"open": ""})
diff --git a/src/test/rustdoc-gui/trait-sidebar-item-order.goml b/src/test/rustdoc-gui/trait-sidebar-item-order.goml
new file mode 100644 (file)
index 0000000..7397457
--- /dev/null
@@ -0,0 +1,7 @@
+goto: file://|DOC_PATH|/test_docs/trait.AnotherOne.html
+assert-text: (".sidebar-links a:nth-of-type(1)", "another")
+assert-text: (".sidebar-links a:nth-of-type(2)", "func1")
+assert-text: (".sidebar-links a:nth-of-type(3)", "func2")
+assert-text: (".sidebar-links a:nth-of-type(4)", "func3")
+assert-text: (".sidebar-links a:nth-of-type(5)", "hello")
+assert-text: (".sidebar-links a:nth-of-type(6)", "why_not")
diff --git a/src/test/rustdoc-gui/type-declation-overflow.goml b/src/test/rustdoc-gui/type-declation-overflow.goml
new file mode 100644 (file)
index 0000000..0a316e2
--- /dev/null
@@ -0,0 +1,8 @@
+// This test ensures that the type declaration content overflow is handled inside the <pre> directly.
+goto: file://|DOC_PATH|/lib2/long_trait/trait.ALongNameBecauseItHelpsTestingTheCurrentProblem.html
+// We set a fixed size so there is no chance of "random" resize.
+size: (1100, 800)
+// Logically, the <body> scroll width should be the width of the window.
+assert-property: ("body", {"scrollWidth": "1100"})
+// However, since there is overflow in the type declaration, its scroll width is bigger.
+assert-property: (".type-decl pre", {"scrollWidth": "1324"})
diff --git a/src/test/rustdoc-gui/type-weight.rs b/src/test/rustdoc-gui/type-weight.rs
deleted file mode 100644 (file)
index 8b6518e..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-goto: file://|DOC_PATH|/test_docs/type.SomeType.html
-assert-all: (".top-block .docblock p", {"font-weight": "400"})
diff --git a/src/test/rustdoc-js-std/alias-4.js b/src/test/rustdoc-js-std/alias-4.js
new file mode 100644 (file)
index 0000000..bf2bb4d
--- /dev/null
@@ -0,0 +1,7 @@
+const QUERY = '<';
+
+const EXPECTED = {
+    'others': [
+        { 'name': 'Ord' },
+    ],
+};
diff --git a/src/test/rustdoc-js-std/typed-query.js b/src/test/rustdoc-js-std/typed-query.js
new file mode 100644 (file)
index 0000000..f656aa7
--- /dev/null
@@ -0,0 +1,12 @@
+// exact-check
+
+const QUERY = 'macro:print';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'print' },
+        { 'path': 'std', 'name': 'eprint' },
+        { 'path': 'std', 'name': 'println' },
+        { 'path': 'std', 'name': 'eprintln' },
+    ],
+};
diff --git a/src/test/rustdoc-js/generics-trait.js b/src/test/rustdoc-js/generics-trait.js
new file mode 100644 (file)
index 0000000..7876622
--- /dev/null
@@ -0,0 +1,23 @@
+const QUERY = [
+    'Result<SomeTrait>',
+    'OtherThingxxxxxxxx',
+];
+
+const EXPECTED = [
+    {
+        'in_args': [
+            { 'path': 'generics_trait', 'name': 'beta' },
+        ],
+        'returned': [
+            { 'path': 'generics_trait', 'name': 'bet' },
+        ],
+    },
+    {
+        'in_args': [
+            { 'path': 'generics_trait', 'name': 'alpha' },
+        ],
+        'returned': [
+            { 'path': 'generics_trait', 'name': 'alef' },
+        ],
+    },
+];
diff --git a/src/test/rustdoc-js/generics-trait.rs b/src/test/rustdoc-js/generics-trait.rs
new file mode 100644 (file)
index 0000000..20db117
--- /dev/null
@@ -0,0 +1,8 @@
+pub trait SomeTrait {}
+pub trait OtherThingxxxxxxxx {}
+
+pub fn alef<T: OtherThingxxxxxxxx>() -> Result<T, ()> { loop {} }
+pub fn bet<T: SomeTrait>() -> Result<T, ()> { loop {} }
+
+pub fn alpha<T: OtherThingxxxxxxxx>(_param: Result<T, ()>) { loop {} }
+pub fn beta<T: SomeTrait>(_param: Result<T, ()>) { loop {} }
diff --git a/src/test/rustdoc-js/generics.js b/src/test/rustdoc-js/generics.js
new file mode 100644 (file)
index 0000000..49a80ae
--- /dev/null
@@ -0,0 +1,44 @@
+// exact-check
+
+const QUERY = [
+  '"R<P>"',
+  '"P"',
+  'P',
+  '"ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>"',
+];
+
+const EXPECTED = [
+    {
+        'returned': [
+            { 'path': 'generics', 'name': 'alef' },
+        ],
+        'in_args': [
+            { 'path': 'generics', 'name': 'alpha' },
+        ],
+    },
+    {
+        'others': [
+            { 'path': 'generics', 'name': 'P' },
+        ],
+        'returned': [
+            { 'path': 'generics', 'name': 'alef' },
+        ],
+        'in_args': [
+            { 'path': 'generics', 'name': 'alpha' },
+        ],
+    },
+    {
+        'returned': [
+            { 'path': 'generics', 'name': 'alef' },
+        ],
+        'in_args': [
+            { 'path': 'generics', 'name': 'alpha' },
+        ],
+    },
+    {
+        'in_args': [
+            { 'path': 'generics', 'name': 'extracreditlabhomework' },
+        ],
+        'returned': [],
+    },
+];
diff --git a/src/test/rustdoc-js/generics.rs b/src/test/rustdoc-js/generics.rs
new file mode 100644 (file)
index 0000000..a0dc086
--- /dev/null
@@ -0,0 +1,21 @@
+pub struct P;
+pub struct Q;
+pub struct R<T>(T);
+
+// returns test
+pub fn alef() -> R<P> { loop {} }
+pub fn bet() -> R<Q> { loop {} }
+
+// in_args test
+pub fn alpha(_x: R<P>) { loop {} }
+pub fn beta(_x: R<Q>) { loop {} }
+
+// test case with multiple appearances of the same type
+pub struct ExtraCreditStructMulti<T, U> { t: T, u: U }
+pub struct ExtraCreditInnerMulti {}
+pub fn extracreditlabhomework(
+    _param: ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>
+) { loop {} }
+pub fn redherringmatchforextracredit(
+    _param: ExtraCreditStructMulti<ExtraCreditInnerMulti, ()>
+) { loop {} }
index f175e47342df64d64321297dd9d8f0c12d2349ce..dfb11e80414c1abc686766ad6575e1cc3fe20620 100644 (file)
@@ -5,7 +5,7 @@ const QUERY = ['summaries', 'summaries::Sidebar', 'summaries::Sidebar2'];
 const EXPECTED = [
     {
         'others': [
-           { 'path': '', 'name': 'summaries', 'desc': 'This <em>summary</em> has a link and <code>code</code>.' },
+           { 'path': '', 'name': 'summaries', 'desc': 'This <em>summary</em> has a link, [<code>code</code>], and <code>Sidebar2</code> intra-doc.' },
         ],
     },
     {
index beb91e286b61080b127cbcefb420fdb632e82ea7..418c9f8d0edd02dd969fb56458f1002c652aee6e 100644 (file)
@@ -1,9 +1,11 @@
 #![crate_type = "lib"]
 #![crate_name = "summaries"]
 
-//! This *summary* has a [link] and `code`.
+//! This *summary* has a [link], [`code`], and [`Sidebar2`] intra-doc.
 //!
-//! This is the second paragraph.
+//! This is the second paragraph. It should not be rendered.
+//! To test that intra-doc links are resolved properly, [`code`] should render
+//! the square brackets, and [`Sidebar2`] should not.
 //!
 //! [link]: https://example.com
 
diff --git a/src/test/rustdoc-ui/intra-doc/field-ice.rs b/src/test/rustdoc-ui/intra-doc/field-ice.rs
new file mode 100644 (file)
index 0000000..c5d501e
--- /dev/null
@@ -0,0 +1,11 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+//~^NOTE the lint level is defined here
+
+/// [`Foo::bar`]
+/// [`Foo::bar()`]
+//~^ERROR incompatible link kind for `Foo::bar`
+//~|HELP to link to the field, remove the disambiguator
+//~|NOTE this link resolved to a field, which is not a function
+pub struct Foo {
+    pub bar: u8
+}
diff --git a/src/test/rustdoc-ui/intra-doc/field-ice.stderr b/src/test/rustdoc-ui/intra-doc/field-ice.stderr
new file mode 100644 (file)
index 0000000..ccb05b8
--- /dev/null
@@ -0,0 +1,15 @@
+error: incompatible link kind for `Foo::bar`
+  --> $DIR/field-ice.rs:5:6
+   |
+LL | /// [`Foo::bar()`]
+   |      ^^^^^^^^^^^^ help: to link to the field, remove the disambiguator: ``Foo::bar``
+   |
+note: the lint level is defined here
+  --> $DIR/field-ice.rs:1:9
+   |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this link resolved to a field, which is not a function
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/nocapture-fail.rs b/src/test/rustdoc-ui/nocapture-fail.rs
new file mode 100644 (file)
index 0000000..7706bd1
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+// compile-flags:--test -Zunstable-options --nocapture
+// normalize-stderr-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```compile_fail
+/// fn foo() {
+///     Input: 123
+/// }
+/// ```
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/nocapture-fail.stderr b/src/test/rustdoc-ui/nocapture-fail.stderr
new file mode 100644 (file)
index 0000000..16a5ac4
--- /dev/null
@@ -0,0 +1,18 @@
+error: struct literal body without path
+  --> $DIR/nocapture-fail.rs:8:10
+   |
+LL |   fn foo() {
+   |  __________^
+LL | |     Input: 123
+LL | | }
+   | |_^
+   |
+help: you might have forgotten to add the struct literal inside the block
+   |
+LL | fn foo() { SomeStruct {
+LL |     Input: 123
+LL | } }
+   |
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/nocapture-fail.stdout b/src/test/rustdoc-ui/nocapture-fail.stdout
new file mode 100644 (file)
index 0000000..754f77d
--- /dev/null
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/nocapture-fail.rs - Foo (line 7) - compile fail ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/nocapture.rs b/src/test/rustdoc-ui/nocapture.rs
new file mode 100644 (file)
index 0000000..321f5ca
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+// compile-flags:--test -Zunstable-options --nocapture
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// println!("hello!");
+/// eprintln!("stderr");
+/// ```
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/nocapture.stderr b/src/test/rustdoc-ui/nocapture.stderr
new file mode 100644 (file)
index 0000000..af6415d
--- /dev/null
@@ -0,0 +1 @@
+stderr
diff --git a/src/test/rustdoc-ui/nocapture.stdout b/src/test/rustdoc-ui/nocapture.stdout
new file mode 100644 (file)
index 0000000..4880e75
--- /dev/null
@@ -0,0 +1,7 @@
+
+running 1 test
+hello!
+test $DIR/nocapture.rs - Foo (line 6) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
index 05a32d3cc310962fb075ecdae376289a53ed9ceb..a4d3a4b497117b80948337551fbfa18348c4bda8 100644 (file)
@@ -1,7 +1,6 @@
 // compile-args: --crate-type lib
 #![deny(broken_intra_doc_links)]
-// FIXME: the old names for rustdoc lints should warn by default once `rustdoc::` makes it to the
-// stable channel.
+//~^ WARNING renamed to `rustdoc::broken_intra_doc_links`
 //! [x]
 //~^ ERROR unresolved link
 
index 3040cad532c826ec4f7ce9d461f15baa9d26f06b..8e2a2cdd7592f773fdf76ace563b8e0621f3c07f 100644 (file)
@@ -1,13 +1,19 @@
+warning: lint `broken_intra_doc_links` has been renamed to `rustdoc::broken_intra_doc_links`
+  --> $DIR/renamed-lint-still-applies.rs:2:9
+   |
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::broken_intra_doc_links`
+   |
+   = note: `#[warn(renamed_and_removed_lints)]` on by default
+
 warning: lint `rustdoc::non_autolinks` has been renamed to `rustdoc::bare_urls`
-  --> $DIR/renamed-lint-still-applies.rs:8:9
+  --> $DIR/renamed-lint-still-applies.rs:7:9
    |
 LL | #![deny(rustdoc::non_autolinks)]
    |         ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::bare_urls`
-   |
-   = note: `#[warn(renamed_and_removed_lints)]` on by default
 
 error: unresolved link to `x`
-  --> $DIR/renamed-lint-still-applies.rs:5:6
+  --> $DIR/renamed-lint-still-applies.rs:4:6
    |
 LL | //! [x]
    |      ^ no item named `x` in scope
@@ -17,21 +23,20 @@ note: the lint level is defined here
    |
 LL | #![deny(broken_intra_doc_links)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
-   = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(broken_intra_doc_links)]`
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 error: this URL is not a hyperlink
-  --> $DIR/renamed-lint-still-applies.rs:10:5
+  --> $DIR/renamed-lint-still-applies.rs:9:5
    |
 LL | //! http://example.com
    |     ^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<http://example.com>`
    |
 note: the lint level is defined here
-  --> $DIR/renamed-lint-still-applies.rs:8:9
+  --> $DIR/renamed-lint-still-applies.rs:7:9
    |
 LL | #![deny(rustdoc::non_autolinks)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
    = note: bare URLs are not automatically turned into clickable links
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors; 2 warnings emitted
 
index 9096cce127658d93169762c999f749b8d5fe28e4..ddf03dd079f94257fc73f675dbccc08d1502b60c 100644 (file)
@@ -14,8 +14,7 @@
 //~^ ERROR renamed to `rustdoc::bare_urls`
 
 #![deny(private_doc_tests)]
-// FIXME: the old names for rustdoc lints should warn by default once `rustdoc::` makes it to the
-// stable channel.
+//~^ ERROR renamed to `rustdoc::private_doc_tests`
 
 #![deny(rustdoc)]
 //~^ ERROR removed: use `rustdoc::all` instead
index 51e06821cf7ab824b184b4c972e06e2f4b1d6d00..b105f47d751718980d60564cb43eab0dc4af562d 100644 (file)
@@ -14,7 +14,7 @@ error: unknown lint: `rustdoc::x`
   --> $DIR/unknown-renamed-lints.rs:7:9
    |
 LL | #![deny(rustdoc::x)]
-   |         ^^^^^^^^^^
+   |         ^^^^^^^^^^ help: did you mean: `rustdoc::all`
 
 error: lint `intra_doc_link_resolution_failure` has been renamed to `rustdoc::broken_intra_doc_links`
   --> $DIR/unknown-renamed-lints.rs:9:9
@@ -40,19 +40,25 @@ error: lint `rustdoc::non_autolinks` has been renamed to `rustdoc::bare_urls`
 LL | #![deny(rustdoc::non_autolinks)]
    |         ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::bare_urls`
 
+error: lint `private_doc_tests` has been renamed to `rustdoc::private_doc_tests`
+  --> $DIR/unknown-renamed-lints.rs:16:9
+   |
+LL | #![deny(private_doc_tests)]
+   |         ^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::private_doc_tests`
+
 error: lint `rustdoc` has been removed: use `rustdoc::all` instead
-  --> $DIR/unknown-renamed-lints.rs:20:9
+  --> $DIR/unknown-renamed-lints.rs:19:9
    |
 LL | #![deny(rustdoc)]
    |         ^^^^^^^
 
 error: unknown lint: `rustdoc::intra_doc_link_resolution_failure`
-  --> $DIR/unknown-renamed-lints.rs:24:9
+  --> $DIR/unknown-renamed-lints.rs:23:9
    |
 LL | #![deny(rustdoc::intra_doc_link_resolution_failure)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Compilation failed, aborting rustdoc
 
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
 
index 51cd4a6cbfd12d6a7f9b7c21e19e3e394ab1145e..6a588fbd56e75945b2c5ae02936d8e5a99084f7f 100644 (file)
@@ -8,14 +8,6 @@ pub extern "C" fn f() {}
 #[export_name = "bar"]
 pub extern "C" fn g() {}
 
-// @matches foo/enum.Foo.html '//*[@class="rust enum"]' \
-//      '#\[repr\(i64\)\]\n#\[must_use\]'
-#[repr(i64)]
-#[must_use]
-pub enum Foo {
-    Bar,
-}
-
 // @has foo/struct.Repr.html '//*[@class="docblock type-decl"]' '#[repr(C, align(8))]'
 #[repr(C, align(8))]
 pub struct Repr;
diff --git a/src/test/rustdoc/auxiliary/cross-crate-hidden-impl-parameter.rs b/src/test/rustdoc/auxiliary/cross-crate-hidden-impl-parameter.rs
new file mode 100644 (file)
index 0000000..1595312
--- /dev/null
@@ -0,0 +1,5 @@
+#[doc(hidden)]
+pub enum HiddenType {}
+
+#[doc(hidden)]
+pub trait HiddenTrait {}
diff --git a/src/test/rustdoc/auxiliary/issue-85454.rs b/src/test/rustdoc/auxiliary/issue-85454.rs
new file mode 100644 (file)
index 0000000..45664df
--- /dev/null
@@ -0,0 +1,17 @@
+// @has issue_85454/trait.FromResidual.html
+// @has - '//pre[@class="rust trait"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+pub trait FromResidual<R = <Self as Try>::Residual> {
+    fn from_residual(residual: R) -> Self;
+}
+
+pub trait Try: FromResidual {
+    type Output;
+    type Residual;
+    fn from_output(output: Self::Output) -> Self;
+    fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+}
+
+pub enum ControlFlow<B, C = ()> {
+    Continue(C),
+    Break(B),
+}
diff --git a/src/test/rustdoc/auxiliary/issue-86620-1.rs b/src/test/rustdoc/auxiliary/issue-86620-1.rs
new file mode 100644 (file)
index 0000000..f6debf6
--- /dev/null
@@ -0,0 +1,11 @@
+#![crate_name = "issue_86620_1"]
+
+pub trait VZip {
+    fn vzip() -> usize;
+}
+
+impl<T> VZip for T {
+    fn vzip() -> usize {
+        0
+    }
+}
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,
+}
index b66f75695f2ab5f324a4508d0f4298c724db89b0..15910e1e9006d1e8ff738a7c8814ecda10c483c1 100644 (file)
@@ -3,8 +3,7 @@
 // therefore should not concern itself with the lints.
 #[deny(warnings)]
 
-// @has cap_lints/struct.Foo.html //pre '#[must_use]'
-#[must_use]
+// @has cap_lints/struct.Foo.html //* 'Struct Foo'
 pub struct Foo {
     field: i32,
 }
index be5ae93392beb052d74d53adc8da68a5e38625ee..fb8ea7e33c28ce2f419bd60d7eee6ca6b770616d 100644 (file)
@@ -7,12 +7,20 @@
 #![feature(foo, foo2)]
 #![feature(staged_api)]
 
-// @has 'foo/fn.foo.html' '//pre' 'pub unsafe fn foo() -> u32'
+// @has 'foo/fn.foo.html' '//pre' 'pub fn foo() -> u32'
+// @has - '//span[@class="since"]' '1.0.0 (const: unstable)'
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature="foo", issue = "none")]
-pub const unsafe fn foo() -> u32 { 42 }
+pub const fn foo() -> u32 { 42 }
+
+// @has 'foo/fn.foo_unsafe.html' '//pre' 'pub unsafe fn foo_unsafe() -> u32'
+// @has - '//span[@class="since"]' '1.0.0 (const: unstable)'
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo", issue = "none")]
+pub const unsafe fn foo_unsafe() -> u32 { 42 }
 
 // @has 'foo/fn.foo2.html' '//pre' 'pub const fn foo2() -> u32'
+// @!has - '//span[@class="since"]'
 #[unstable(feature = "humans", issue = "none")]
 pub const fn foo2() -> u32 { 42 }
 
@@ -22,7 +30,9 @@ pub const fn foo2() -> u32 { 42 }
 #[rustc_const_stable(feature = "rust1", since = "1.0.0")]
 pub const fn bar2() -> u32 { 42 }
 
+
 // @has 'foo/fn.foo2_gated.html' '//pre' 'pub const unsafe fn foo2_gated() -> u32'
+// @!has - '//span[@class="since"]'
 #[unstable(feature = "foo2", issue = "none")]
 pub const unsafe fn foo2_gated() -> u32 { 42 }
 
@@ -33,19 +43,23 @@ pub const unsafe fn foo2_gated() -> u32 { 42 }
 pub const unsafe fn bar2_gated() -> u32 { 42 }
 
 // @has 'foo/fn.bar_not_gated.html' '//pre' 'pub const unsafe fn bar_not_gated() -> u32'
+// @!has - '//span[@class="since"]'
 pub const unsafe fn bar_not_gated() -> u32 { 42 }
 
 pub struct Foo;
 
 impl Foo {
     // @has 'foo/struct.Foo.html' '//div[@id="method.gated"]/h4[@class="code-header"]' 'pub fn gated() -> u32'
+    // @has - '//span[@class="since"]' '1.0.0 (const: unstable)'
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature="foo", issue = "none")]
     pub const fn gated() -> u32 { 42 }
 
+    // @has 'foo/struct.Foo.html' '//div[@id="method.gated_unsafe"]/h4[@class="code-header"]' 'pub unsafe fn gated_unsafe() -> u32'
+    // @has - '//span[@class="since"]' '1.0.0 (const: unstable)'
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature="foo", issue = "none")]
-    pub const unsafe fn gated() -> u32 { 42 }
+    pub const unsafe fn gated_unsafe() -> u32 { 42 }
 
     // @has 'foo/struct.Foo.html' '//div[@id="method.stable_impl"]/h4[@class="code-header"]' 'pub const fn stable_impl() -> u32'
     // @has - '//span[@class="since"]' '1.0.0 (const: 1.2.0)'
diff --git a/src/test/rustdoc/const-generics/const-evaluatable-checked.rs b/src/test/rustdoc/const-generics/const-evaluatable-checked.rs
new file mode 100644 (file)
index 0000000..1c074fd
--- /dev/null
@@ -0,0 +1,7 @@
+#![crate_name = "foo"]
+#![feature(const_evaluatable_checked, const_generics)]
+#![allow(incomplete_features)]
+// make sure that `ConstEvaluatable` predicates dont cause rustdoc to ICE #77647
+// @has foo/struct.Ice.html '//pre[@class="rust struct"]' \
+//      'pub struct Ice<const N: usize> where [(); N + 1]: ;'
+pub struct Ice<const N: usize> where [(); N + 1]:;
diff --git a/src/test/rustdoc/cross-crate-hidden-impl-parameter.rs b/src/test/rustdoc/cross-crate-hidden-impl-parameter.rs
new file mode 100644 (file)
index 0000000..eb2ced2
--- /dev/null
@@ -0,0 +1,35 @@
+// Issue #86448: test for cross-crate `doc(hidden)`
+#![crate_name = "foo"]
+
+// aux-build:cross-crate-hidden-impl-parameter.rs
+extern crate cross_crate_hidden_impl_parameter;
+
+pub use ::cross_crate_hidden_impl_parameter::{HiddenType, HiddenTrait}; // OK, not re-exported
+
+pub enum MyLibType {}
+
+// @!has foo/enum.MyLibType.html '//*[@id="impl-From%3CHiddenType%3E"]' 'impl From<HiddenType> for MyLibType'
+impl From<HiddenType> for MyLibType {
+    fn from(it: HiddenType) -> MyLibType {
+        match it {}
+    }
+}
+
+pub struct T<T>(T);
+
+// @!has foo/enum.MyLibType.html '//*[@id="impl-From%3CT%3CT%3CT%3CT%3CHiddenType%3E%3E%3E%3E%3E"]' 'impl From<T<T<T<T<HiddenType>>>>> for MyLibType'
+impl From<T<T<T<T<HiddenType>>>>> for MyLibType {
+    fn from(it: T<T<T<T<HiddenType>>>>) -> MyLibType {
+        todo!()
+    }
+}
+
+// @!has foo/enum.MyLibType.html '//*[@id="impl-HiddenTrait"]' 'impl HiddenTrait for MyLibType'
+impl HiddenTrait for MyLibType {}
+
+// @!has foo/struct.T.html '//*[@id="impl-From%3CMyLibType%3E"]' 'impl From<MyLibType> for T<T<T<T<HiddenType>>>>'
+impl From<MyLibType> for T<T<T<T<HiddenType>>>> {
+    fn from(it: MyLibType) -> T<T<T<T<HiddenType>>>> {
+        match it {}
+    }
+}
index ede3f455a2044c4e1d27f671f87d32497708c43c..fe19dadbe0243113ffde82585b78e34123115ef8 100644 (file)
@@ -9,7 +9,7 @@ pub macro my_macro() {
 
 }
 
-// @has decl_macro/macro.my_macro_2.html //pre 'pub macro my_macro_2($($tok:tt)*) {'
+// @has decl_macro/macro.my_macro_2.html //pre 'pub macro my_macro_2($($tok : tt) *) {'
 // @has - //pre '...'
 // @has - //pre '}'
 pub macro my_macro_2($($tok:tt)*) {
@@ -18,8 +18,8 @@ pub macro my_macro_2($($tok:tt)*) {
 
 // @has decl_macro/macro.my_macro_multi.html //pre 'pub macro my_macro_multi {'
 // @has - //pre '(_) => { ... },'
-// @has - //pre '($foo:ident . $bar:expr) => { ... },'
-// @has - //pre '($($foo:literal),+) => { ... }'
+// @has - //pre '($foo : ident.$bar : expr) => { ... },'
+// @has - //pre '($($foo : literal), +) => { ... },'
 // @has - //pre '}'
 pub macro my_macro_multi {
     (_) => {
@@ -33,7 +33,7 @@ pub macro my_macro_multi {
     }
 }
 
-// @has decl_macro/macro.by_example_single.html //pre 'pub macro by_example_single($foo:expr) {'
+// @has decl_macro/macro.by_example_single.html //pre 'pub macro by_example_single($foo : expr) {'
 // @has - //pre '...'
 // @has - //pre '}'
 pub macro by_example_single {
@@ -42,12 +42,12 @@ pub macro by_example_single {
 
 mod a {
     mod b {
-        // @has decl_macro/a/b/macro.by_example_vis.html //pre 'pub(super) macro by_example_vis($foo:expr) {'
+        // @has decl_macro/a/b/macro.by_example_vis.html //pre 'pub(super) macro by_example_vis($foo : expr) {'
         pub(in super) macro by_example_vis {
             ($foo:expr) => {}
         }
         mod c {
-            // @has decl_macro/a/b/c/macro.by_example_vis_named.html //pre 'pub(in a) macro by_example_vis_named($foo:expr) {'
+            // @has decl_macro/a/b/c/macro.by_example_vis_named.html //pre 'pub(in a) macro by_example_vis_named($foo : expr) {'
             pub(in a) macro by_example_vis_named {
                 ($foo:expr) => {}
             }
diff --git a/src/test/rustdoc/default-theme.rs b/src/test/rustdoc/default-theme.rs
new file mode 100644 (file)
index 0000000..ecb8f0b
--- /dev/null
@@ -0,0 +1,7 @@
+// compile-flags: --default-theme ayu
+
+// @has default_theme/index.html
+// @has - '//script[@id="default-settings"]/@data-theme' 'ayu'
+// @has - '//script[@id="default-settings"]/@data-use_system_theme' 'false'
+
+pub fn whatever() {}
index a286856b2c3c1db62d3633254795bb2909241d5e..b3178da98eeb282ecc836c22b5b57937b717451d 100644 (file)
@@ -1,6 +1,6 @@
-// @has deprecated/index.html '//*[@class="docblock-short"]/span[@class="stab deprecated"]' \
+// @has deprecated/index.html '//*[@class="item-left module-item"]/span[@class="stab deprecated"]' \
 //      'Deprecated'
-// @has - '//*[@class="docblock-short"]' 'Deprecated docs'
+// @has - '//*[@class="item-right docblock-short"]' 'Deprecated docs'
 
 // @has deprecated/struct.S.html '//*[@class="stab deprecated"]' \
 //      'Deprecated since 1.0.0: text'
@@ -8,7 +8,7 @@
 #[deprecated(since = "1.0.0", note = "text")]
 pub struct S;
 
-// @matches deprecated/index.html '//*[@class="docblock-short"]' '^Docs'
+// @matches deprecated/index.html '//*[@class="item-right docblock-short"]' '^Docs'
 /// Docs
 pub struct T;
 
index 1fc80b3e76c53a7d775bf2f06192a9bef0028185..416ffb60098639fb044a1a25b99c9ab1dcade03b 100644 (file)
@@ -12,7 +12,7 @@ pub struct Portable;
 // @has doc_cfg/unix_only/index.html \
 //  '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' \
 //  'This is supported on Unix only.'
-// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AARM\Z'
+// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AARM\Z'
 // @count - '//*[@class="stab portability"]' 2
 #[doc(cfg(unix))]
 pub mod unix_only {
@@ -42,7 +42,7 @@ pub mod unix_only {
 // @has doc_cfg/wasi_only/index.html \
 //  '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' \
 //  'This is supported on WASI only.'
-// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AWebAssembly\Z'
+// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AWebAssembly\Z'
 // @count - '//*[@class="stab portability"]' 2
 #[doc(cfg(target_os = "wasi"))]
 pub mod wasi_only {
@@ -74,7 +74,7 @@ pub mod wasi_only {
 
 // the portability header is different on the module view versus the full view
 // @has doc_cfg/index.html
-// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\Aavx\Z'
+// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\Aavx\Z'
 
 // @has doc_cfg/fn.uses_target_feature.html
 // @has - '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' \
index cec504ea1517a2c523e818228476ca9a5dcc125b..886ec6750304abb092266e2f6832e5aa95f7f36d 100644 (file)
@@ -2,13 +2,14 @@
 #![feature(doc_cfg)]
 
 // @has 'foo/index.html'
-// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync$'
-// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` only'
+// @matches '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]' '^sync$'
+// @has '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` only'
 
 // @has 'foo/struct.Foo.html'
 // @has '-' '//*[@class="stab portability"]' 'sync'
 #[doc(cfg(feature = "sync"))]
 #[doc(cfg(feature = "sync"))]
+/// my feature sync struct
 pub struct Foo;
 
 // @has 'foo/bar/index.html'
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;
index 4b6270b26da276fe122d7955317aa3a308323aff..6189acb72542a613612d67d183886e28441e03ff 100644 (file)
@@ -2,5 +2,5 @@
 
 // This test ensures that the [src] link is present on traits items.
 
-// @has foo/trait.Iterator.html '//div[@id="method.zip"]/a[@class="srclink"]' "[src]"
+// @has foo/trait.Iterator.html '//div[@id="method.zip"]//a[@class="srclink"]' "[src]"
 pub use std::iter::Iterator;
index 810c591c53e1e48909ff02f881ad26e10f88148a..efa2025b4b9c229d8d199426528597c34c016a88 100644 (file)
@@ -4,4 +4,6 @@
 extern crate rustdoc_extern_default_method as ext;
 
 // @count extern_default_method/struct.Struct.html '//*[@id="method.provided"]' 1
+// @has extern_default_method/struct.Struct.html '//div[@id="method.provided"]//a[@class="fnname"]/@href' #method.provided
+// @has extern_default_method/struct.Struct.html '//div[@id="method.provided"]//a[@class="anchor"]/@href' #method.provided
 pub use ext::Struct;
diff --git a/src/test/rustdoc/for-lifetime.rs b/src/test/rustdoc/for-lifetime.rs
deleted file mode 100644 (file)
index 34a7eae..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#![crate_name = "foo"]
-#![crate_type = "lib"]
-
-pub struct Foo {
-    pub some_func: for<'a> fn(val: &'a i32) -> i32,
-    pub some_trait: dyn for<'a> Trait<'a>,
-}
-
-// @has foo/struct.Foo.html '//span[@id="structfield.some_func"]' "some_func: for<'a> fn(val: &'a i32) -> i32"
-// @has foo/struct.Foo.html '//span[@id="structfield.some_trait"]' "some_trait: dyn Trait<'a>"
-
-pub trait Trait<'a> {}
diff --git a/src/test/rustdoc/higher-ranked-trait-bounds.rs b/src/test/rustdoc/higher-ranked-trait-bounds.rs
new file mode 100644 (file)
index 0000000..b75b8de
--- /dev/null
@@ -0,0 +1,61 @@
+#![crate_name = "foo"]
+
+// @has foo/trait.Trait.html
+pub trait Trait<'x> {}
+
+// @has foo/fn.test1.html
+// @has - '//pre' "pub fn test1<T>() where for<'a> &'a T: Iterator,"
+pub fn test1<T>()
+where
+    for<'a> &'a T: Iterator,
+{
+}
+
+// @has foo/fn.test2.html
+// @has - '//pre' "pub fn test2<T>() where for<'a, 'b> &'a T: Trait<'b>,"
+pub fn test2<T>()
+where
+    for<'a, 'b> &'a T: Trait<'b>,
+{
+}
+
+// @has foo/fn.test3.html
+// @has - '//pre' "pub fn test3<F>() where F: for<'a, 'b> Fn(&'a u8, &'b u8),"
+pub fn test3<F>()
+where
+    F: for<'a, 'b> Fn(&'a u8, &'b u8),
+{
+}
+
+// @has foo/struct.Foo.html
+pub struct Foo<'a> {
+    _x: &'a u8,
+    pub some_trait: &'a dyn for<'b> Trait<'b>,
+    pub some_func: for<'c> fn(val: &'c i32) -> i32,
+}
+
+// @has - '//span[@id="structfield.some_func"]' "some_func: for<'c> fn(val: &'c i32) -> i32"
+// @has - '//span[@id="structfield.some_trait"]' "some_trait: &'a dyn for<'b> Trait<'b>"
+
+impl<'a> Foo<'a> {
+    // @has - '//h4[@class="code-header"]' "pub fn bar<T>() where T: Trait<'a>,"
+    pub fn bar<T>()
+    where
+        T: Trait<'a>,
+    {
+    }
+}
+
+// @has foo/trait.B.html
+pub trait B<'x> {}
+
+// @has - '//h3[@class="code-header in-band"]' "impl<'a> B<'a> for dyn for<'b> Trait<'b>"
+impl<'a> B<'a> for dyn for<'b> Trait<'b> {}
+
+// @has foo/struct.Bar.html
+// @has - '//span[@id="structfield.bar"]' "bar: &'a (dyn for<'b> Trait<'b> + Unpin)"
+// @has - '//span[@id="structfield.baz"]' "baz: &'a (dyn Unpin + for<'b> Trait<'b>)"
+pub struct Bar<'a> {
+    pub bar: &'a (dyn for<'b> Trait<'b> + Unpin),
+    pub baz: &'a (dyn Unpin + for<'b> Trait<'b>),
+}
index f9bf982659e0210a68bed7a530d03acff0124f2f..9cb933c177bf0dd96e00cff460734d476ce3668f 100644 (file)
@@ -7,8 +7,10 @@
 
 extern crate macros;
 
-// @has foo/index.html '//*[@class="docblock-short"]/span[@class="stab deprecated"]' Deprecated
-// @has - '//*[@class="docblock-short"]/span[@class="stab unstable"]' Experimental
+// @has foo/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab deprecated"]' \
+//         Deprecated
+// @has - '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab unstable"]' \
+//         Experimental
 
 // @has foo/macro.my_macro.html
 // @has - '//*[@class="docblock"]' 'docs for my_macro'
index a1e322fb9a30704e45e120048864fd263fc8b8ae..f316eb24a48514067dd5b5ad16e7201702c432a7 100644 (file)
@@ -2,9 +2,11 @@
 
 // Check that the unstable marker is not added for "rustc_private".
 
-// @!matches internal/index.html '//*[@class="docblock-short"]/span[@class="stab unstable"]'
-// @!matches internal/index.html '//*[@class="docblock-short"]/span[@class="stab internal"]'
-// @matches - '//*[@class="docblock-short"]' 'Docs'
+// @!matches internal/index.html \
+//      '//*[@class="item-right docblock-short"]/span[@class="stab unstable"]'
+// @!matches internal/index.html \
+//      '//*[@class="item-right docblock-short"]/span[@class="stab internal"]'
+// @matches - '//*[@class="item-right docblock-short"]' 'Docs'
 
 // @!has internal/struct.S.html '//*[@class="stab unstable"]'
 // @!has internal/struct.S.html '//*[@class="stab internal"]'
diff --git a/src/test/rustdoc/intra-doc/macros-disambiguators.rs b/src/test/rustdoc/intra-doc/macros-disambiguators.rs
new file mode 100644 (file)
index 0000000..cd4caa6
--- /dev/null
@@ -0,0 +1,25 @@
+#![crate_name = "foo"]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+//! [foo!()]
+// @has foo/index.html '//a[@href="macro.foo.html"]' 'foo!()'
+
+//! [foo!{}]
+// @has - '//a[@href="macro.foo.html"]' 'foo!{}'
+
+//! [foo![]](foo![])
+// @has - '//a[@href="macro.foo.html"]' 'foo![]'
+
+//! [foo1](foo!())
+// @has - '//a[@href="macro.foo.html"]' 'foo1'
+
+//! [foo2](foo!{})
+// @has - '//a[@href="macro.foo.html"]' 'foo2'
+
+//! [foo3](foo![])
+// @has - '//a[@href="macro.foo.html"]' 'foo3'
+
+#[macro_export]
+macro_rules! foo {
+    () => {};
+}
diff --git a/src/test/rustdoc/intra-doc/type-alias.rs b/src/test/rustdoc/intra-doc/type-alias.rs
new file mode 100644 (file)
index 0000000..f3609cc
--- /dev/null
@@ -0,0 +1,19 @@
+// Regression test for issue #86120.
+
+#![deny(broken_intra_doc_links)]
+#![crate_name = "foo"]
+
+pub struct Foo;
+
+/// You should really try [`Self::bar`]!
+pub type Bar = Foo;
+
+impl Bar {
+    pub fn bar() {}
+}
+
+/// The minimum is [`Self::MIN`].
+pub type Int = i32;
+
+// @has foo/type.Bar.html '//a[@href="struct.Foo.html#method.bar"]' 'Self::bar'
+// @has foo/type.Int.html '//a[@href="{{channel}}/std/primitive.i32.html#associatedconstant.MIN"]' 'Self::MIN'
diff --git a/src/test/rustdoc/issue-19055.rs b/src/test/rustdoc/issue-19055.rs
deleted file mode 100644 (file)
index dbaf744..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// @has issue_19055/trait.Any.html
-pub trait Any {}
-
-impl<'any> Any + 'any {
-    // @has - '//*[@id="method.is"]' 'fn is'
-    pub fn is<T: 'static>(&self) -> bool { loop {} }
-
-    // @has - '//*[@id="method.downcast_ref"]' 'fn downcast_ref'
-    pub fn downcast_ref<T: 'static>(&self) -> Option<&T> { loop {} }
-
-    // @has - '//*[@id="method.downcast_mut"]' 'fn downcast_mut'
-    pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> { loop {} }
-}
-
-pub trait Foo {
-    fn foo(&self) {}
-}
-
-// @has - '//*[@id="method.foo"]' 'fn foo'
-impl Foo for Any {}
index 11caa34d4b11426db2138f1419a05181ecfa6df1..4e92ae49a20afa311d580d039cc485ee1a554f5a 100644 (file)
@@ -1,17 +1,17 @@
 #![feature(staged_api)]
-#![doc(issue_tracker_base_url = "http://issue_url/")]
+#![doc(issue_tracker_base_url = "https://issue_url/")]
 
 #![unstable(feature="test", issue = "32374")]
 
-// @matches issue_32374/index.html '//*[@class="docblock-short"]/span[@class="stab deprecated"]' \
+// @matches issue_32374/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab deprecated"]' \
 //      'Deprecated'
-// @matches issue_32374/index.html '//*[@class="docblock-short"]/span[@class="stab unstable"]' \
+// @matches issue_32374/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab unstable"]' \
 //      'Experimental'
-// @matches issue_32374/index.html '//*[@class="docblock-short"]/text()' 'Docs'
+// @matches issue_32374/index.html '//*[@class="item-right docblock-short"]/text()' 'Docs'
 
 // @has issue_32374/struct.T.html '//*[@class="stab deprecated"]' \
 //      '👎 Deprecated since 1.0.0: text'
-// @has - '<code>test</code>&nbsp;<a href="http://issue_url/32374">#32374</a>'
+// @has - '<code>test</code>&nbsp;<a href="https://issue_url/32374">#32374</a>'
 // @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' \
 //      '🔬 This is a nightly-only experimental API. \(test\s#32374\)$'
 /// Docs
index 236afb20be53e03beea938ea825d3f4a5514630e..4489f038c5934f5f45560db327292c1956fd6edf 100644 (file)
@@ -1,3 +1,3 @@
-// @has 'issue_46377/index.html' '//*[@class="docblock-short"]' 'Check out this struct!'
+// @has 'issue_46377/index.html' '//*[@class="item-right docblock-short"]' 'Check out this struct!'
 /// # Check out this struct!
 pub struct SomeStruct;
index bc0ad14be03e07e48465bd6e6f479adc305691b3..70aa10767b270ca6552678ac642d19438b5c7656 100644 (file)
@@ -29,8 +29,8 @@ pub mod subone {
 // @has - '//section[@id="main"]/details/div[@class="docblock"]//a[@href="../fn.foo.html"]' 'foo'
 // @has - '//section[@id="main"]/details/div[@class="docblock"]//a[@href="../fn.bar.html"]' 'bar'
 // Though there should be such links later
-// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td/a[@class="fn"][@href="fn.foo.html"]' 'foo'
-// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td/a[@class="fn"][@href="fn.bar.html"]' 'bar'
+// @has - '//section[@id="main"]/div[@class="item-table"]//div[@class="item-left module-item"]/a[@class="fn"][@href="fn.foo.html"]' 'foo'
+// @has - '//section[@id="main"]/div[@class="item-table"]//div[@class="item-left module-item"]/a[@class="fn"][@href="fn.bar.html"]' 'bar'
 /// See either [foo] or [bar].
 pub mod subtwo {
 
@@ -68,8 +68,8 @@ pub mod subthree {
 // Next we go *deeper* - In order to ensure it's not just "this or parent"
 // we test `crate::` and a `super::super::...` chain
 // @has issue_55364/subfour/subfive/subsix/subseven/subeight/index.html
-// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td[@class="docblock-short"]//a[@href="../../../../../subone/fn.foo.html"]' 'other foo'
-// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td[@class="docblock-short"]//a[@href="../../../../../subtwo/fn.bar.html"]' 'other bar'
+// @has - '//section[@id="main"]/div[@class="item-table"]//div[@class="item-right docblock-short"]//a[@href="../../../../../subone/fn.foo.html"]' 'other foo'
+// @has - '//section[@id="main"]/div[@class="item-table"]//div[@class="item-right docblock-short"]//a[@href="../../../../../subtwo/fn.bar.html"]' 'other bar'
 pub mod subfour {
     pub mod subfive {
         pub mod subsix {
index 45664dfc3823da490d5625df87efdb3c2594b43e..3351b5c8350fd7284ac0e7d2598e5c866ee7c9a7 100644 (file)
@@ -1,4 +1,10 @@
-// @has issue_85454/trait.FromResidual.html
+// aux-build:issue-85454.rs
+// build-aux-docs
+#![crate_name = "foo"]
+
+extern crate issue_85454;
+
+// @has foo/trait.FromResidual.html
 // @has - '//pre[@class="rust trait"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
 pub trait FromResidual<R = <Self as Try>::Residual> {
     fn from_residual(residual: R) -> Self;
@@ -15,3 +21,9 @@ pub enum ControlFlow<B, C = ()> {
     Continue(C),
     Break(B),
 }
+
+pub mod reexport {
+    // @has foo/reexport/trait.FromResidual.html
+    // @has - '//pre[@class="rust trait"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+    pub use issue_85454::*;
+}
diff --git a/src/test/rustdoc/issue-86620.rs b/src/test/rustdoc/issue-86620.rs
new file mode 100644 (file)
index 0000000..b14e266
--- /dev/null
@@ -0,0 +1,9 @@
+// aux-build:issue-86620-1.rs
+
+extern crate issue_86620_1;
+
+use issue_86620_1::*;
+
+// @!has issue_86620/struct.S.html '//div[@id="method.vzip"]//a[@class="fnname"]/@href' #tymethod.vzip
+// @has issue_86620/struct.S.html '//div[@id="method.vzip"]//a[@class="anchor"]/@href' #method.vzip
+pub struct S;
diff --git a/src/test/rustdoc/macro_rules-matchers.rs b/src/test/rustdoc/macro_rules-matchers.rs
new file mode 100644 (file)
index 0000000..5f8340e
--- /dev/null
@@ -0,0 +1,45 @@
+// This is a regression test for issue #86208.
+// It is also a general test of macro_rules! display.
+
+#![crate_name = "foo"]
+
+// @has 'foo/macro.todo.html'
+// @has - '//span[@class="macro"]' 'macro_rules!'
+// @has - '//span[@class="ident"]' 'todo'
+// Note: count = 2 * ('=' + '>') + '+' = 2 * (1 + 1) + 1 = 5
+// @count - '//pre[@class="rust macro"]//span[@class="op"]' 5
+
+// @has - '{ ()'
+// @has - '//span[@class="op"]' '='
+// @has - '//span[@class="op"]' '>'
+// @has - '{ ... };'
+
+// @has - '($('
+// @has - '//span[@class="macro-nonterminal"]' '$'
+// @has - '//span[@class="macro-nonterminal"]' 'arg'
+// @has - ':'
+// @has - '//span[@class="ident"]' 'tt'
+// @has - '),'
+// @has - '//span[@class="op"]' '+'
+// @has - ')'
+pub use std::todo;
+
+mod mod1 {
+    // @has 'foo/macro.macro1.html'
+    // @has - 'macro_rules!'
+    // @has - 'macro1'
+    // @has - '{ ()'
+    // @has - '($('
+    // @has - '//span[@class="macro-nonterminal"]' '$'
+    // @has - '//span[@class="macro-nonterminal"]' 'arg'
+    // @has - ':'
+    // @has - 'expr'
+    // @has - '),'
+    // @has - '+'
+    // @has - ')'
+    #[macro_export]
+    macro_rules! macro1 {
+        () => {};
+        ($($arg:expr),+) => { stringify!($($arg),+) };
+    }
+}
index ae0cf7a14789d78103c6cb4585ea36ab650153f7..1cd454720e7d14250bc3fc07cb0e0be25f4dbcc9 100644 (file)
@@ -1,7 +1,7 @@
 // @has macros/macro.my_macro.html //pre 'macro_rules! my_macro {'
 // @has - //pre '() => { ... };'
-// @has - //pre '($a:tt) => { ... };'
-// @has - //pre '($e:expr) => { ... };'
+// @has - //pre '($a : tt) => { ... };'
+// @has - //pre '($e : expr) => { ... };'
 #[macro_export]
 macro_rules! my_macro {
     () => [];
@@ -12,8 +12,8 @@ macro_rules! my_macro {
 // Check that exported macro defined in a module are shown at crate root.
 // @has macros/macro.my_sub_macro.html //pre 'macro_rules! my_sub_macro {'
 // @has - //pre '() => { ... };'
-// @has - //pre '($a:tt) => { ... };'
-// @has - //pre '($e:expr) => { ... };'
+// @has - //pre '($a : tt) => { ... };'
+// @has - //pre '($e : expr) => { ... };'
 mod sub {
     #[macro_export]
     macro_rules! my_sub_macro {
diff --git a/src/test/rustdoc/must-use.rs b/src/test/rustdoc/must-use.rs
deleted file mode 100644 (file)
index b52557f..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// @has must_use/struct.Struct.html //pre '#[must_use]'
-#[must_use]
-pub struct Struct {
-    field: i32,
-}
-
-// @has must_use/enum.Enum.html //pre '#[must_use = "message"]'
-#[must_use = "message"]
-pub enum Enum {
-    Variant(i32),
-}
diff --git a/src/test/rustdoc/recursive-deref-sidebar.rs b/src/test/rustdoc/recursive-deref-sidebar.rs
new file mode 100644 (file)
index 0000000..fcb636a
--- /dev/null
@@ -0,0 +1,22 @@
+use std::ops::Deref;
+
+pub struct A {}
+impl A { pub fn foo_a(&self) {} }
+
+pub struct B {}
+impl B { pub fn foo_b(&self) {} }
+
+pub struct C {}
+impl C { pub fn foo_c(&self) {} }
+
+// @has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_b'
+impl Deref for A {
+    type Target = B;
+    fn deref(&self) -> &B { todo!() }
+}
+
+// @!has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c'
+impl Deref for B {
+    type Target = C;
+    fn deref(&self) -> &C { todo!() }
+}
diff --git a/src/test/rustdoc/recursive-deref.rs b/src/test/rustdoc/recursive-deref.rs
new file mode 100644 (file)
index 0000000..3d17bce
--- /dev/null
@@ -0,0 +1,22 @@
+use std::ops::Deref;
+
+pub struct A;
+pub struct B;
+
+// @has recursive_deref/struct.A.html '//h3[@class="code-header in-band"]' 'impl Deref for A'
+impl Deref for A {
+    type Target = B;
+
+    fn deref(&self) -> &Self::Target {
+        panic!()
+    }
+}
+
+// @has recursive_deref/struct.B.html '//h3[@class="code-header in-band"]' 'impl Deref for B'
+impl Deref for B {
+    type Target = A;
+
+    fn deref(&self) -> &Self::Target {
+        panic!()
+    }
+}
index 9a22903a94cc809c94ed783b9367041be3bcc62e..db1f90c69997855b7ad6ad078104eb484f98d8d5 100644 (file)
@@ -4,15 +4,15 @@
 extern crate reexport_check;
 
 // @!has 'foo/index.html' '//code' 'pub use self::i32;'
-// @has 'foo/index.html' '//tr[@class="deprecated module-item"]' 'i32'
+// @has 'foo/index.html' '//div[@class="item-left deprecated module-item"]' 'i32'
 // @has 'foo/i32/index.html'
 #[allow(deprecated, deprecated_in_future)]
 pub use std::i32;
 // @!has 'foo/index.html' '//code' 'pub use self::string::String;'
-// @has 'foo/index.html' '//tr[@class="module-item"]' 'String'
+// @has 'foo/index.html' '//div[@class="item-left module-item"]' 'String'
 pub use std::string::String;
 
-// @has 'foo/index.html' '//td[@class="docblock-short"]' 'Docs in original'
+// @has 'foo/index.html' '//div[@class="item-right docblock-short"]' 'Docs in original'
 // this is a no-op, but shows what happens if there's an attribute that isn't a doc-comment
 #[doc(inline)]
 pub use reexport_check::S;
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;
diff --git a/src/test/rustdoc/safe-intrinsic.rs b/src/test/rustdoc/safe-intrinsic.rs
new file mode 100644 (file)
index 0000000..d3bb851
--- /dev/null
@@ -0,0 +1,20 @@
+#![feature(intrinsics)]
+#![feature(no_core)]
+
+#![no_core]
+#![crate_name = "foo"]
+
+extern "rust-intrinsic" {
+    // @has 'foo/fn.abort.html'
+    // @has - '//pre[@class="rust fn"]' 'pub extern "rust-intrinsic" fn abort() -> !'
+    pub fn abort() -> !;
+    // @has 'foo/fn.unreachable.html'
+    // @has - '//pre[@class="rust fn"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
+    pub fn unreachable() -> !;
+}
+
+extern "C" {
+    // @has 'foo/fn.needs_drop.html'
+    // @has - '//pre[@class="rust fn"]' 'pub unsafe extern "C" fn needs_drop() -> !'
+    pub fn needs_drop() -> !;
+}
diff --git a/src/test/rustdoc/same-crate-hidden-impl-parameter.rs b/src/test/rustdoc/same-crate-hidden-impl-parameter.rs
new file mode 100644 (file)
index 0000000..d55393a
--- /dev/null
@@ -0,0 +1,36 @@
+// test for `doc(hidden)` with impl parameters in the same crate.
+#![crate_name = "foo"]
+
+#[doc(hidden)]
+pub enum HiddenType {}
+
+#[doc(hidden)]
+pub trait HiddenTrait {}
+
+pub enum MyLibType {}
+
+// @!has foo/enum.MyLibType.html '//*[@id="impl-From%3CHiddenType%3E"]' 'impl From<HiddenType> for MyLibType'
+impl From<HiddenType> for MyLibType {
+    fn from(it: HiddenType) -> MyLibType {
+        match it {}
+    }
+}
+
+pub struct T<T>(T);
+
+// @!has foo/enum.MyLibType.html '//*[@id="impl-From%3CT%3CT%3CT%3CT%3CHiddenType%3E%3E%3E%3E%3E"]' 'impl From<T<T<T<T<HiddenType>>>>> for MyLibType'
+impl From<T<T<T<T<HiddenType>>>>> for MyLibType {
+    fn from(it: T<T<T<T<HiddenType>>>>) -> MyLibType {
+        todo!()
+    }
+}
+
+// @!has foo/enum.MyLibType.html '//*[@id="impl-HiddenTrait"]' 'impl HiddenTrait for MyLibType'
+impl HiddenTrait for MyLibType {}
+
+// @!has foo/struct.T.html '//*[@id="impl-From%3CMyLibType%3E"]' 'impl From<MyLibType> for T<T<T<T<HiddenType>>>>'
+impl From<MyLibType> for T<T<T<T<HiddenType>>>> {
+    fn from(it: MyLibType) -> T<T<T<T<HiddenType>>>> {
+        match it {}
+    }
+}
index fc8d53ccf35016efc4eef134f55c2dabc171def5..c6b318b0677cea5f7ebae71bdd13900a21a56787 100644 (file)
@@ -1,8 +1,8 @@
 #![crate_name = "foo"]
 
-// @has foo/index.html '//*[@class="module-item"]//td[@class="docblock-short"]' ""
-// @!has foo/index.html '//*[@id="module-item"]//td[@class="docblock-short"]' "Some text."
-// @!has foo/index.html '//*[@id="module-item"]//td[@class="docblock-short"]' "let x = 12;"
+// @has foo/index.html '//*[@class="item-right docblock-short"]' ""
+// @!has foo/index.html '//*[@class="item-right docblock-short"]' "Some text."
+// @!has foo/index.html '//*[@class="item-right docblock-short"]' "let x = 12;"
 
 /// ```
 /// let x = 12;
diff --git a/src/test/rustdoc/short-docblock.rs b/src/test/rustdoc/short-docblock.rs
new file mode 100644 (file)
index 0000000..74fa783
--- /dev/null
@@ -0,0 +1,25 @@
+#![crate_name = "foo"]
+
+// @has foo/index.html '//*[@class="item-right docblock-short"]/p' 'fooo'
+// @!has foo/index.html '//*[@class="item-right docblock-short"]/p/h1' 'fooo'
+// @has foo/fn.foo.html '//h1[@id="fooo"]/a[@href="#fooo"]' 'fooo'
+
+/// # fooo
+///
+/// foo
+pub fn foo() {}
+
+// @has foo/index.html '//*[@class="item-right docblock-short"]/p' 'mooood'
+// @!has foo/index.html '//*[@class="item-right docblock-short"]/p/h2' 'mooood'
+// @has foo/foo/index.html '//h2[@id="mooood"]/a[@href="#mooood"]' 'mooood'
+
+/// ## mooood
+///
+/// foo mod
+pub mod foo {}
+
+// @has foo/index.html '//*[@class="item-right docblock-short"]/p/a[@href=\
+//                      "https://nougat.world"]/code' 'nougat'
+
+/// [`nougat`](https://nougat.world)
+pub struct Bar;
diff --git a/src/test/rustdoc/short-dockblock.rs b/src/test/rustdoc/short-dockblock.rs
deleted file mode 100644 (file)
index 5493bca..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#![crate_name = "foo"]
-
-// @has foo/index.html '//*[@class="docblock-short"]/p' 'fooo'
-// @!has foo/index.html '//*[@class="docblock-short"]/p/h1' 'fooo'
-// @has foo/fn.foo.html '//h1[@id="fooo"]/a[@href="#fooo"]' 'fooo'
-
-/// # fooo
-///
-/// foo
-pub fn foo() {}
-
-// @has foo/index.html '//*[@class="docblock-short"]/p' 'mooood'
-// @!has foo/index.html '//*[@class="docblock-short"]/p/h2' 'mooood'
-// @has foo/foo/index.html '//h2[@id="mooood"]/a[@href="#mooood"]' 'mooood'
-
-/// ## mooood
-///
-/// foo mod
-pub mod foo {}
-
-// @has foo/index.html '//*[@class="docblock-short"]/p/a[@href=\
-//                      "https://nougat.world"]/code' 'nougat'
-
-/// [`nougat`](https://nougat.world)
-pub struct Bar;
index 6e3c0b4c681f7c6e3b8604eb4a67f1465fe3e3e4..8d2046591d08ac42244212c68e20a691d754a17c 100644 (file)
@@ -9,7 +9,7 @@ pub struct PubStruct {
 
 // @has 'toggle_item_contents/struct.BigPubStruct.html'
 // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields'
+// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 fields'
 pub struct BigPubStruct {
     pub a: usize,
     pub b: usize,
@@ -28,7 +28,7 @@ pub struct BigPubStruct {
 
 // @has 'toggle_item_contents/union.BigUnion.html'
 // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields'
+// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 fields'
 pub union BigUnion {
     pub a: usize,
     pub b: usize,
@@ -62,8 +62,7 @@ pub struct PrivStruct {
 }
 
 // @has 'toggle_item_contents/enum.Enum.html'
-// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields'
+// @!has - '//details[@class="rustdoc-toggle type-contents-toggle"]'
 pub enum Enum {
     A, B, C,
     D {
@@ -72,9 +71,18 @@ pub enum Enum {
     }
 }
 
+// @has 'toggle_item_contents/enum.EnumStructVariant.html'
+// @!has - '//details[@class="rustdoc-toggle type-contents-toggle"]'
+pub enum EnumStructVariant {
+    A, B, C,
+    D {
+        a: u8,
+    }
+}
+
 // @has 'toggle_item_contents/enum.LargeEnum.html'
 // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show variants'
+// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 variants'
 pub enum LargeEnum {
     A, B, C, D, E, F(u8), G, H, I, J, K, L, M
 }
@@ -90,7 +98,7 @@ pub trait Trait {
 
 // @has 'toggle_item_contents/trait.GinormousTrait.html'
 // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show associated items'
+// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 16 associated items'
 pub trait GinormousTrait {
     type A;
     type B;
@@ -113,7 +121,7 @@ pub trait GinormousTrait {
 
 // @has 'toggle_item_contents/trait.HugeTrait.html'
 // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show associated constants and methods'
+// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 12 associated constants and 2 methods'
 pub trait HugeTrait {
     type A;
     const M: usize = 1;
@@ -133,9 +141,30 @@ pub trait HugeTrait {
     fn bar();
 }
 
+// @has 'toggle_item_contents/trait.GiganticTrait.html'
+// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
+// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 1 associated constant and 1 method'
+pub trait GiganticTrait {
+    type A;
+    type B;
+    type C;
+    type D;
+    type E;
+    type F;
+    type G;
+    type H;
+    type I;
+    type J;
+    type K;
+    type L;
+    const M: usize = 1;
+    #[must_use]
+    fn foo();
+}
+
 // @has 'toggle_item_contents/trait.BigTrait.html'
 // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show methods'
+// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 14 methods'
 pub trait BigTrait {
     type A;
     #[must_use]
diff --git a/src/test/rustdoc/trait-attributes.rs b/src/test/rustdoc/trait-attributes.rs
deleted file mode 100644 (file)
index d0dfb87..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#![crate_name = "foo"]
-
-
-pub trait Foo {
-    // @has foo/trait.Foo.html '//div[@id="tymethod.foo"]//div[@class="code-attribute"]' '#[must_use]'
-    #[must_use]
-    fn foo();
-}
-
-#[must_use]
-pub struct Bar;
-
-impl Bar {
-    // @has foo/struct.Bar.html '//div[@id="method.bar"]//div[@class="code-attribute"]' '#[must_use]'
-    #[must_use]
-    pub fn bar() {}
-
-    // @has foo/struct.Bar.html '//div[@id="method.bar2"]//div[@class="code-attribute"]' '#[must_use]'
-    #[must_use]
-    pub fn bar2() {}
-}
index 5b7c04c0d4445a185a2df8607907b08bca42244d..4d25835bf08fd231d479e4306ac9a3ed7af15af6 100644 (file)
@@ -1,6 +1,6 @@
 pub trait MyTrait {
     type Assoc;
-    const VALUE: u32;
+    const VALUE: u32 = 12;
     fn trait_function(&self);
     fn defaulted(&self) {}
     fn defaulted_override(&self) {}
@@ -38,23 +38,17 @@ impl MyTrait for Vec<u8> {
 }
 
 impl MyTrait for MyStruct {
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-3"]//a[@class="type"]/@href' #associatedtype.Assoc
     // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-3"]//a[@class="anchor"]/@href' #associatedtype.Assoc-3
     // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedtype.Assoc"]//a[@class="type"]/@href' trait.MyTrait.html#associatedtype.Assoc
     // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedtype.Assoc"]//a[@class="anchor"]/@href' #associatedtype.Assoc
     type Assoc = bool;
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-3"]//a[@class="constant"]/@href' #associatedconstant.VALUE
     // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-3"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-3
     // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedconstant.VALUE"]//a[@class="constant"]/@href' trait.MyTrait.html#associatedconstant.VALUE
     // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedconstant.VALUE"]//a[@class="anchor"]/@href' #associatedconstant.VALUE
     const VALUE: u32 = 20;
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function-2"]//a[@class="fnname"]/@href' #tymethod.trait_function
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function-2"]//a[@class="anchor"]/@href' #method.trait_function-2
     // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.trait_function"]//a[@class="fnname"]/@href' trait.MyTrait.html#tymethod.trait_function
     // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.trait_function"]//a[@class="anchor"]/@href' #method.trait_function
     fn trait_function(&self) {}
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-3"]//a[@class="fnname"]/@href' #method.defaulted_override
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-3"]//a[@class="anchor"]/@href' #method.defaulted_override-3
     // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.defaulted_override"]//a[@class="fnname"]/@href' trait.MyTrait.html#method.defaulted_override
     // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.defaulted_override"]//a[@class="anchor"]/@href' #method.defaulted_override
     fn defaulted_override(&self) {}
@@ -63,3 +57,10 @@ impl MyTrait for MyStruct {
 }
 
 pub struct MyStruct;
+
+// We check that associated items with default values aren't generated in the implementors list.
+impl MyTrait for (u8, u8) {
+    // @!has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-4"]'
+    type Assoc = bool;
+    fn trait_function(&self) {}
+}
index 3786c6de7e78c400a827cf3f4e339e47d232e6c1..795c7d2dcb7354270bcf64004ddd9810fea6587e 100644 (file)
@@ -1,22 +1,29 @@
 // compile-flags: -Z unstable-options
 
 #![feature(rustc_private)]
+#![deny(rustc::default_hash_types)]
 
 extern crate rustc_data_structures;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use std::collections::{HashMap, HashSet};
 
-#[deny(rustc::default_hash_types)]
+mod foo {
+    pub struct HashMap;
+}
+
 fn main() {
     let _map: HashMap<String, String> = HashMap::default();
-    //~^ ERROR Prefer FxHashMap over HashMap, it has better performance
-    //~^^ ERROR Prefer FxHashMap over HashMap, it has better performance
+    //~^ ERROR prefer `FxHashMap` over `HashMap`, it has better performance
+    //~^^ ERROR prefer `FxHashMap` over `HashMap`, it has better performance
     let _set: HashSet<String> = HashSet::default();
-    //~^ ERROR Prefer FxHashSet over HashSet, it has better performance
-    //~^^ ERROR Prefer FxHashSet over HashSet, it has better performance
+    //~^ ERROR prefer `FxHashSet` over `HashSet`, it has better performance
+    //~^^ ERROR prefer `FxHashSet` over `HashSet`, it has better performance
 
     // test that the lint doesn't also match the Fx variants themselves
     let _fx_map: FxHashMap<String, String> = FxHashMap::default();
     let _fx_set: FxHashSet<String> = FxHashSet::default();
+
+    // test another struct of the same name
+    let _ = foo::HashMap;
 }
index 4f78f51b676f4110f6359467475d31104b46f925..9d13ee89bca649d66d9921e1e49e628aa727ae7b 100644 (file)
@@ -1,37 +1,37 @@
-error: Prefer FxHashMap over HashMap, it has better performance
-  --> $DIR/default_hash_types.rs:12:15
+error: prefer `FxHashMap` over `HashMap`, it has better performance
+  --> $DIR/default_hash_types.rs:16:41
    |
 LL |     let _map: HashMap<String, String> = HashMap::default();
-   |               ^^^^^^^ help: use: `FxHashMap`
+   |                                         ^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/default_hash_types.rs:10:8
+  --> $DIR/default_hash_types.rs:4:9
    |
-LL | #[deny(rustc::default_hash_types)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rustc::default_hash_types)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary
 
-error: Prefer FxHashMap over HashMap, it has better performance
-  --> $DIR/default_hash_types.rs:12:41
+error: prefer `FxHashMap` over `HashMap`, it has better performance
+  --> $DIR/default_hash_types.rs:16:15
    |
 LL |     let _map: HashMap<String, String> = HashMap::default();
-   |                                         ^^^^^^^ help: use: `FxHashMap`
+   |               ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary
 
-error: Prefer FxHashSet over HashSet, it has better performance
-  --> $DIR/default_hash_types.rs:15:15
+error: prefer `FxHashSet` over `HashSet`, it has better performance
+  --> $DIR/default_hash_types.rs:19:33
    |
 LL |     let _set: HashSet<String> = HashSet::default();
-   |               ^^^^^^^ help: use: `FxHashSet`
+   |                                 ^^^^^^^
    |
    = note: a `use rustc_data_structures::fx::FxHashSet` may be necessary
 
-error: Prefer FxHashSet over HashSet, it has better performance
-  --> $DIR/default_hash_types.rs:15:33
+error: prefer `FxHashSet` over `HashSet`, it has better performance
+  --> $DIR/default_hash_types.rs:19:15
    |
 LL |     let _set: HashSet<String> = HashSet::default();
-   |                                 ^^^^^^^ help: use: `FxHashSet`
+   |               ^^^^^^^^^^^^^^^
    |
    = note: a `use rustc_data_structures::fx::FxHashSet` may be necessary
 
index 448c57da754a0c31d374ec146834913acae39f02..bb246de0e572dd4aa65f7a92f33ec63303ce9b19 100644 (file)
@@ -19,7 +19,7 @@ use std::path::Path;
 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 @@ impl MutVisitor for AddParens {
 }
 
 fn main() {
-    rustc_span::with_default_session_globals(|| run());
+    rustc_span::create_default_session_globals_then(|| run());
 }
 
 fn run() {
index 2f1debe25b74fddb5563fe44345a4c267fbaa159..c7853f5275e01768b302490d51f6f59686c69094 100644 (file)
@@ -56,6 +56,8 @@ LL | #[message = "This error has a field, and references {name}"]
 error: invalid format string: expected `'}'` but string was terminated
   --> $DIR/session-derive-errors.rs:116:1
    |
+LL | #[derive(SessionDiagnostic)]
+   |          ----------------- in this derive macro expansion
 LL | #[error = "E0123"]
    |               - because of this opening brace
 LL | #[message = "This is missing a closing brace: {name"]
@@ -67,6 +69,9 @@ LL | #[message = "This is missing a closing brace: {name"]
 error: invalid format string: unmatched `}` found
   --> $DIR/session-derive-errors.rs:125:1
    |
+LL | #[derive(SessionDiagnostic)]
+   |          ----------------- in this derive macro expansion
+LL | #[error = "E0123"]
 LL | #[message = "This is missing an opening brace: name}"]
    | ^ unmatched `}` in format string
    |
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..fdeb79f
--- /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 #87678 <https://github.com/rust-lang/rust/issues/87678>
+
+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 #87678 <https://github.com/rust-lang/rust/issues/87678>
+
+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..60d067a
--- /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 #87678 <https://github.com/rust-lang/rust/issues/87678>
+
+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 #87678 <https://github.com/rust-lang/rust/issues/87678>
+
+error: aborting due to 6 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0570`.
index 0851e1a5e9cf7b739f59a6973cc372463b796c6d..628b48a45d76d6b19604f4a47537b4cbb7a4e2d6 100644 (file)
@@ -1,37 +1,61 @@
 error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
   --> $DIR/not-an-allocator.rs:2:1
    |
+LL | #[global_allocator]
+   | ------------------- in this procedural macro expansion
 LL | static A: usize = 0;
    | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
-   = note: required by `std::alloc::GlobalAlloc::alloc`
+note: required by `std::alloc::GlobalAlloc::alloc`
+  --> $SRC_DIR/core/src/alloc/global.rs:LL:COL
+   |
+LL |     unsafe fn alloc(&self, layout: Layout) -> *mut u8;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
   --> $DIR/not-an-allocator.rs:2:1
    |
+LL | #[global_allocator]
+   | ------------------- in this procedural macro expansion
 LL | static A: usize = 0;
    | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
-   = note: required by `std::alloc::GlobalAlloc::dealloc`
+note: required by `std::alloc::GlobalAlloc::dealloc`
+  --> $SRC_DIR/core/src/alloc/global.rs:LL:COL
+   |
+LL |     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
   --> $DIR/not-an-allocator.rs:2:1
    |
+LL | #[global_allocator]
+   | ------------------- in this procedural macro expansion
 LL | static A: usize = 0;
    | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
-   = note: required by `std::alloc::GlobalAlloc::realloc`
+note: required by `std::alloc::GlobalAlloc::realloc`
+  --> $SRC_DIR/core/src/alloc/global.rs:LL:COL
+   |
+LL |     unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
   --> $DIR/not-an-allocator.rs:2:1
    |
+LL | #[global_allocator]
+   | ------------------- in this procedural macro expansion
 LL | static A: usize = 0;
    | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
-   = note: required by `std::alloc::GlobalAlloc::alloc_zeroed`
+note: required by `std::alloc::GlobalAlloc::alloc_zeroed`
+  --> $SRC_DIR/core/src/alloc/global.rs:LL:COL
+   |
+LL |     unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 4 previous errors
index dbf1054f1068cfb394b5c27255b2a6eee88d905d..7a914c2a3907c673887f791bcc81458690230b7a 100644 (file)
@@ -4,6 +4,7 @@ error: cannot define multiple global allocators
 LL | static A: System = System;
    | -------------------------- previous global allocator defined here
 LL | #[global_allocator]
+   | ------------------- in this procedural macro expansion
 LL | static B: System = System;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot define a new global allocator
    |
index d288bba5957a282e169f541ad948623680730c33..c09e20770846e313f26fd4e87f345cf7df7728b9 100644 (file)
@@ -7,13 +7,13 @@
 
 trait T {
     fn foo(_: i32); //~ WARNING anonymous parameters are deprecated
-                 //~| WARNING hard error
+                 //~| WARNING this is accepted in the current edition
 
     fn bar_with_default_impl(_: String, _: String) {}
     //~^ WARNING anonymous parameters are deprecated
-    //~| WARNING hard error
+    //~| WARNING this is accepted in the current edition
     //~| WARNING anonymous parameters are deprecated
-    //~| WARNING hard error
+    //~| WARNING this is accepted in the current edition
 }
 
 fn main() {}
index d677e0c32b04a4ee9e1e2040fb39eeb162e009f6..6f7385da040c552282c49ed9c092a90acd941d00 100644 (file)
@@ -7,13 +7,13 @@
 
 trait T {
     fn foo(i32); //~ WARNING anonymous parameters are deprecated
-                 //~| WARNING hard error
+                 //~| WARNING this is accepted in the current edition
 
     fn bar_with_default_impl(String, String) {}
     //~^ WARNING anonymous parameters are deprecated
-    //~| WARNING hard error
+    //~| WARNING this is accepted in the current edition
     //~| WARNING anonymous parameters are deprecated
-    //~| WARNING hard error
+    //~| WARNING this is accepted in the current edition
 }
 
 fn main() {}
index c1bf5f690ecbaad55947a2ac08a85d4439f4a307..98d52d659a9d387da6ba8720af72848bcccecb36 100644 (file)
@@ -9,7 +9,7 @@ note: the lint level is defined here
    |
 LL | #![warn(anonymous_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
 
 warning: anonymous parameters are deprecated and will be removed in the next edition.
@@ -18,7 +18,7 @@ warning: anonymous parameters are deprecated and will be removed in the next edi
 LL |     fn bar_with_default_impl(String, String) {}
    |                              ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
 
 warning: anonymous parameters are deprecated and will be removed in the next edition.
@@ -27,7 +27,7 @@ warning: anonymous parameters are deprecated and will be removed in the next edi
 LL |     fn bar_with_default_impl(String, String) {}
    |                                      ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
 
 warning: 3 warnings emitted
index 8b27d055e2be317ab50152db891513450c76c569..4134c62377835003796144bce8079c00204c7a7a 100644 (file)
@@ -17,7 +17,7 @@ impl Drop for Foo {
 
 fn foo() {
     let x: &[_] = &[Foo, Foo];
-    &x[3..4];
+    let _ = &x[3..4];
 }
 
 fn main() {
index 2ee564cadb3442d1d5e2f3e1940a29002303519f..2f7178fb3e1326a74816db0af2142288a289d733 100644 (file)
@@ -21,7 +21,7 @@ fn bar() -> usize {
 
 fn foo() {
     let x: &[_] = &[Foo, Foo];
-    &x[3..bar()];
+    let _ = &x[3..bar()];
 }
 
 fn main() {
index 14e1ddf52eb7b4f28b2f8db93cb22fc0a8697c3c..a514e20277365e43e798ff7553fef84adcc1ebd1 100644 (file)
@@ -67,14 +67,14 @@ impl IndexMut<RangeFull> for Foo {
 
 fn main() {
     let mut x = Foo;
-    &x[..];
-    &x[Foo..];
-    &x[..Foo];
-    &x[Foo..Foo];
-    &mut x[..];
-    &mut x[Foo..];
-    &mut x[..Foo];
-    &mut x[Foo..Foo];
+    let _ = &x[..];
+    let _ = &x[Foo..];
+    let _ = &x[..Foo];
+    let _ = &x[Foo..Foo];
+    let _ = &mut x[..];
+    let _ = &mut x[Foo..];
+    let _ = &mut x[..Foo];
+    let _ = &mut x[Foo..Foo];
     unsafe {
         assert_eq!(COUNT, 8);
     }
index 4e27a6e2cb5958b77b5e662af07efc95a7e9cf96..9039483be4bf95b63d73908c89b3a0357cd40048 100644 (file)
@@ -28,41 +28,41 @@ error: asm outputs are not allowed with the `noreturn` option
 LL |         asm!("{}", out(reg) foo, options(noreturn));
    |                    ^^^^^^^^^^^^
 
-error: expected one of `)` or `att_syntax`, found `nomem`
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
   --> $DIR/bad-options.rs:20:25
    |
 LL | global_asm!("", options(nomem));
-   |                         ^^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: expected one of `)` or `att_syntax`, found `readonly`
+error: expected one of `)`, `att_syntax`, or `raw`, found `readonly`
   --> $DIR/bad-options.rs:22:25
    |
 LL | global_asm!("", options(readonly));
-   |                         ^^^^^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: expected one of `)` or `att_syntax`, found `noreturn`
+error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn`
   --> $DIR/bad-options.rs:24:25
    |
 LL | global_asm!("", options(noreturn));
-   |                         ^^^^^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: expected one of `)` or `att_syntax`, found `pure`
+error: expected one of `)`, `att_syntax`, or `raw`, found `pure`
   --> $DIR/bad-options.rs:26:25
    |
 LL | global_asm!("", options(pure));
-   |                         ^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: expected one of `)` or `att_syntax`, found `nostack`
+error: expected one of `)`, `att_syntax`, or `raw`, found `nostack`
   --> $DIR/bad-options.rs:28:25
    |
 LL | global_asm!("", options(nostack));
-   |                         ^^^^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: expected one of `)` or `att_syntax`, found `preserves_flags`
+error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags`
   --> $DIR/bad-options.rs:30:25
    |
 LL | global_asm!("", options(preserves_flags));
-   |                         ^^^^^^^^^^^^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: aborting due to 11 previous errors
 
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 b1685bd4e027a7600815ff3fbff8623bf6f3b05f..bf6ea6b67f9bbfbc63b898c135fa0fd94f19e057 100644 (file)
@@ -13,7 +13,7 @@ LL | .intel_syntax noprefix
    | ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:29:15
+  --> $DIR/inline-syntax.rs:31:15
    |
 LL |         asm!(".intel_syntax noprefix", "nop");
    |               ^
@@ -25,7 +25,7 @@ LL |     .intel_syntax noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:32:15
+  --> $DIR/inline-syntax.rs:34:15
    |
 LL |         asm!(".intel_syntax aaa noprefix", "nop");
    |               ^
@@ -37,7 +37,7 @@ LL |     .intel_syntax aaa noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:35:15
+  --> $DIR/inline-syntax.rs:37:15
    |
 LL |         asm!(".att_syntax noprefix", "nop");
    |               ^
@@ -49,7 +49,7 @@ LL |     .att_syntax noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:38:15
+  --> $DIR/inline-syntax.rs:40:15
    |
 LL |         asm!(".att_syntax bbb noprefix", "nop");
    |               ^
@@ -61,7 +61,7 @@ LL |     .att_syntax bbb noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:41:15
+  --> $DIR/inline-syntax.rs:43:15
    |
 LL |         asm!(".intel_syntax noprefix; nop");
    |               ^
@@ -73,7 +73,7 @@ LL |     .intel_syntax noprefix; nop
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:47:13
+  --> $DIR/inline-syntax.rs:49:13
    |
 LL |             .intel_syntax noprefix
    |             ^
index 2d54ef7bd6b401e46e4bd593d12cf5c0a97c0579..481990398f4c6ac0a1ed00aed3bdec4735b24d52 100644 (file)
@@ -1,11 +1,13 @@
-// needs-llvm-components: arm
 // revisions: x86_64 arm
 //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
 //[x86_64] check-pass
+//[x86_64] needs-llvm-components: x86
 //[x86_64_allowed] compile-flags: --target x86_64-unknown-linux-gnu
 //[x86_64_allowed] check-pass
+//[x86_64_allowed] needs-llvm-components: x86
 //[arm] compile-flags: --target armv7-unknown-linux-gnueabihf
 //[arm] build-fail
+//[arm] needs-llvm-components: arm
 
 #![feature(no_core, lang_items, rustc_attrs)]
 #![crate_type = "rlib"]
index 59c95194322aaf2a5bbb4c2aa24ff448a780155b..dcbc17bb26089380e71045b68fde32f27a55978b 100644 (file)
@@ -1,5 +1,5 @@
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:55:14
+  --> $DIR/inline-syntax.rs:57:14
    |
 LL | global_asm!(".intel_syntax noprefix", "nop");
    |              ^^^^^^^^^^^^^^^^^^^^^^
@@ -7,37 +7,37 @@ LL | global_asm!(".intel_syntax noprefix", "nop");
    = note: `#[warn(bad_asm_style)]` on by default
 
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:29:15
+  --> $DIR/inline-syntax.rs:31:15
    |
 LL |         asm!(".intel_syntax noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:32:15
+  --> $DIR/inline-syntax.rs:34:15
    |
 LL |         asm!(".intel_syntax aaa noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
-  --> $DIR/inline-syntax.rs:35:15
+  --> $DIR/inline-syntax.rs:37:15
    |
 LL |         asm!(".att_syntax noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
-  --> $DIR/inline-syntax.rs:38:15
+  --> $DIR/inline-syntax.rs:40:15
    |
 LL |         asm!(".att_syntax bbb noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:41:15
+  --> $DIR/inline-syntax.rs:43:15
    |
 LL |         asm!(".intel_syntax noprefix; nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:47:13
+  --> $DIR/inline-syntax.rs:49:13
    |
 LL |             .intel_syntax noprefix
    |             ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/asm/issue-82869.rs b/src/test/ui/asm/issue-82869.rs
new file mode 100644 (file)
index 0000000..a8e688c
--- /dev/null
@@ -0,0 +1,23 @@
+// only-x86_64
+// Make sure rustc doesn't ICE on asm! for a foreign architecture.
+
+#![feature(asm)]
+#![crate_type = "rlib"]
+
+pub unsafe fn aarch64(a: f64, b: f64) -> f64 {
+    let c;
+    asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
+        || {};
+        b
+    });
+    //~^^^^ invalid register class
+    //~^^^^^ invalid register class
+    //~^^^^^^ invalid register
+    c
+}
+
+pub unsafe fn x86(a: f64, b: f64) -> f64 {
+    let c;
+    asm!("addsd {}, {}, xmm0", out(xmm_reg) c, in(xmm_reg) a, in("xmm0") b);
+    c
+}
diff --git a/src/test/ui/asm/issue-82869.stderr b/src/test/ui/asm/issue-82869.stderr
new file mode 100644 (file)
index 0000000..d05714e
--- /dev/null
@@ -0,0 +1,24 @@
+error: invalid register class `vreg`: unknown register class
+  --> $DIR/issue-82869.rs:9:32
+   |
+LL |     asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
+   |                                ^^^^^^^^^^^
+
+error: invalid register class `vreg`: unknown register class
+  --> $DIR/issue-82869.rs:9:45
+   |
+LL |     asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
+   |                                             ^^^^^^^^^^
+
+error: invalid register `d0`: unknown register
+  --> $DIR/issue-82869.rs:9:57
+   |
+LL |       asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
+   |  _________________________________________________________^
+LL | |         || {};
+LL | |         b
+LL | |     });
+   | |_____^
+
+error: aborting due to 3 previous errors
+
index afd262b851c0993c567346c22a68fb28e2022747..33dca61dc8e347870e961f4e8c98fc26ef75acbc 100644 (file)
@@ -64,11 +64,11 @@ error: argument to `sym` must be a path expression
 LL |         asm!("{}", sym foo + bar);
    |                        ^^^^^^^^^
 
-error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, or `readonly`, found `foo`
+error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
   --> $DIR/parse-error.rs:31:26
    |
 LL |         asm!("", options(foo));
-   |                          ^^^ expected one of 8 possible tokens
+   |                          ^^^ expected one of 9 possible tokens
 
 error: expected one of `)` or `,`, found `foo`
   --> $DIR/parse-error.rs:33:32
@@ -76,11 +76,11 @@ error: expected one of `)` or `,`, found `foo`
 LL |         asm!("", options(nomem foo));
    |                                ^^^ expected one of `)` or `,`
 
-error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, or `readonly`, found `foo`
+error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
   --> $DIR/parse-error.rs:35:33
    |
 LL |         asm!("", options(nomem, foo));
-   |                                 ^^^ expected one of 8 possible tokens
+   |                                 ^^^ expected one of 9 possible tokens
 
 error: arguments are not allowed after options
   --> $DIR/parse-error.rs:37:31
@@ -200,23 +200,23 @@ error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
 LL | global_asm!("{}", const(reg) FOO);
    |                              ^^^ expected one of `,`, `.`, `?`, or an operator
 
-error: expected one of `)` or `att_syntax`, found `FOO`
+error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
   --> $DIR/parse-error.rs:81:25
    |
 LL | global_asm!("", options(FOO));
-   |                         ^^^ expected one of `)` or `att_syntax`
+   |                         ^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: expected one of `)` or `att_syntax`, found `nomem`
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
   --> $DIR/parse-error.rs:83:25
    |
 LL | global_asm!("", options(nomem FOO));
-   |                         ^^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: expected one of `)` or `att_syntax`, found `nomem`
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
   --> $DIR/parse-error.rs:85:25
    |
 LL | global_asm!("", options(nomem, FOO));
-   |                         ^^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: arguments are not allowed after options
   --> $DIR/parse-error.rs:87:30
index 2fdfa3da3086c812adf4dfa7f612c0b2b6742db8..ff56d112c8184254fd9645f52a097180504f37b9 100644 (file)
@@ -1,11 +1,14 @@
 error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/associated-const-array-len.rs:5:16
    |
-LL |     const ID: usize;
-   |     ---------------- required by `Foo::ID`
-...
 LL | const X: [i32; <i32 as Foo>::ID] = [0, 1, 2];
    |                ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+   |
+note: required by `Foo::ID`
+  --> $DIR/associated-const-array-len.rs:2:5
+   |
+LL |     const ID: usize;
+   |     ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 1b9d7ac7e6c3f2e0d6e5247ca84e8b7bf09ee7b8..aa356c596f8a05586ff3d63f9aa68418ca31b4d5 100644 (file)
@@ -1,6 +1,9 @@
 error[E0624]: associated constant `ID` is private
   --> $DIR/associated-const-private-impl.rs:13:30
    |
+LL |             const ID: i32 = 1;
+   |             ------------------ private associated constant defined here
+...
 LL |     assert_eq!(1, bar1::Foo::ID);
    |                              ^^ private associated constant
 
index 34e947030a072ff8b693e7bdc83492721c489c10..cea56cd5946c969ddbd9fb6d6d1a87c61b0f14cc 100644 (file)
@@ -1,9 +1,6 @@
 error[E0283]: type annotations needed
   --> $DIR/issue-63496.rs:4:21
    |
-LL |     const C: usize;
-   |     --------------- required by `A::C`
-LL | 
 LL |     fn f() -> ([u8; A::C], [u8; A::C]);
    |                     ^^^^
    |                     |
@@ -12,13 +9,15 @@ LL |     fn f() -> ([u8; A::C], [u8; A::C]);
    |
    = note: cannot satisfy `_: A`
    = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+note: required by `A::C`
+  --> $DIR/issue-63496.rs:2:5
+   |
+LL |     const C: usize;
+   |     ^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed
   --> $DIR/issue-63496.rs:4:33
    |
-LL |     const C: usize;
-   |     --------------- required by `A::C`
-LL | 
 LL |     fn f() -> ([u8; A::C], [u8; A::C]);
    |                                 ^^^^
    |                                 |
@@ -27,6 +26,11 @@ LL |     fn f() -> ([u8; A::C], [u8; A::C]);
    |
    = note: cannot satisfy `_: A`
    = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+note: required by `A::C`
+  --> $DIR/issue-63496.rs:2:5
+   |
+LL |     const C: usize;
+   |     ^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 92d74e38cfa8db81a4164e62c0a3374b293a02df..33ab4bb967a9704135fa83e75bb38cff50417d56 100644 (file)
@@ -16,8 +16,6 @@ LL |     const X: usize;
 error[E0283]: type annotations needed
   --> $DIR/issue-48027.rs:3:32
    |
-LL |     const X: usize;
-   |     --------------- required by `Bar::X`
 LL |     fn return_n(&self) -> [u8; Bar::X];
    |                                ^^^^^^
    |                                |
@@ -26,6 +24,11 @@ LL |     fn return_n(&self) -> [u8; Bar::X];
    |
    = note: cannot satisfy `_: Bar`
    = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+note: required by `Bar::X`
+  --> $DIR/issue-48027.rs:2:5
+   |
+LL |     const X: usize;
+   |     ^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 73b23da5bcb66528d55385ef3179ca718852de42..7950dd3e99e29b11b14606560844698b27d16aa9 100644 (file)
@@ -29,7 +29,6 @@ impl Bar for AssocNoCopy {
 impl Thing for AssocNoCopy {
     type Out = Box<dyn Bar<Assoc: Copy>>;
     //~^ ERROR the trait bound `String: Copy` is not satisfied
-    //~| ERROR the trait bound `String: Copy` is not satisfied
 
     fn func() -> Self::Out {
         Box::new(AssocNoCopy)
index 414d74d4786d97ce6d2da284b35b21a023ca975d..0f1d35be0eb7a19c970be8f52f1de83e30c6dd7c 100644 (file)
@@ -4,12 +4,6 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
 LL |     type Out = Box<dyn Bar<Assoc: Copy>>;
    |                            ^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
 
-error[E0277]: the trait bound `String: Copy` is not satisfied
-  --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28
-   |
-LL |     type Out = Box<dyn Bar<Assoc: Copy>>;
-   |                            ^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
index bd3cac1f887bf10748b0c458dda40156098e87d8..bffa5150fe1ce80bde0a549cdf3fe230c03319f4 100644 (file)
@@ -7,16 +7,8 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/duplicate.rs:6:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:11:36
+  --> $DIR/duplicate.rs:10:36
    |
 LL | struct SI1<T: Iterator<Item: Copy, Item: Send>> { f: T }
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -24,7 +16,7 @@ LL | struct SI1<T: Iterator<Item: Copy, Item: Send>> { f: T }
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:13:36
+  --> $DIR/duplicate.rs:12:36
    |
 LL | struct SI2<T: Iterator<Item: Copy, Item: Copy>> { f: T }
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -32,7 +24,7 @@ LL | struct SI2<T: Iterator<Item: Copy, Item: Copy>> { f: T }
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:15:39
+  --> $DIR/duplicate.rs:14:39
    |
 LL | struct SI3<T: Iterator<Item: 'static, Item: 'static>> { f: T }
    |                        -------------  ^^^^^^^^^^^^^ re-bound here
@@ -40,7 +32,7 @@ LL | struct SI3<T: Iterator<Item: 'static, Item: 'static>> { f: T }
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:17:45
+  --> $DIR/duplicate.rs:16:45
    |
 LL | struct SW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T }
    |                                 ----------  ^^^^^^^^^^ re-bound here
@@ -48,7 +40,7 @@ LL | struct SW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T }
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:19:45
+  --> $DIR/duplicate.rs:18:45
    |
 LL | struct SW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T }
    |                                 ----------  ^^^^^^^^^^ re-bound here
@@ -56,7 +48,7 @@ LL | struct SW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T }
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:21:48
+  --> $DIR/duplicate.rs:20:48
    |
 LL | struct SW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T }
    |                                 -------------  ^^^^^^^^^^^^^ re-bound here
@@ -64,7 +56,7 @@ LL | struct SW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T }
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:24:34
+  --> $DIR/duplicate.rs:23:34
    |
 LL | enum EI1<T: Iterator<Item: Copy, Item: Send>> { V(T) }
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -72,7 +64,7 @@ LL | enum EI1<T: Iterator<Item: Copy, Item: Send>> { V(T) }
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:26:34
+  --> $DIR/duplicate.rs:25:34
    |
 LL | enum EI2<T: Iterator<Item: Copy, Item: Copy>> { V(T) }
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -80,7 +72,7 @@ LL | enum EI2<T: Iterator<Item: Copy, Item: Copy>> { V(T) }
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:28:37
+  --> $DIR/duplicate.rs:27:37
    |
 LL | enum EI3<T: Iterator<Item: 'static, Item: 'static>> { V(T) }
    |                      -------------  ^^^^^^^^^^^^^ re-bound here
@@ -88,7 +80,7 @@ LL | enum EI3<T: Iterator<Item: 'static, Item: 'static>> { V(T) }
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:30:43
+  --> $DIR/duplicate.rs:29:43
    |
 LL | enum EW1<T> where T: Iterator<Item: Copy, Item: Send> { V(T) }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -96,7 +88,7 @@ LL | enum EW1<T> where T: Iterator<Item: Copy, Item: Send> { V(T) }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:32:43
+  --> $DIR/duplicate.rs:31:43
    |
 LL | enum EW2<T> where T: Iterator<Item: Copy, Item: Copy> { V(T) }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -104,7 +96,7 @@ LL | enum EW2<T> where T: Iterator<Item: Copy, Item: Copy> { V(T) }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:34:46
+  --> $DIR/duplicate.rs:33:46
    |
 LL | enum EW3<T> where T: Iterator<Item: 'static, Item: 'static> { V(T) }
    |                               -------------  ^^^^^^^^^^^^^ re-bound here
@@ -112,7 +104,7 @@ LL | enum EW3<T> where T: Iterator<Item: 'static, Item: 'static> { V(T) }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:37:35
+  --> $DIR/duplicate.rs:36:35
    |
 LL | union UI1<T: Iterator<Item: Copy, Item: Send>> { f: T }
    |                       ----------  ^^^^^^^^^^ re-bound here
@@ -120,7 +112,7 @@ LL | union UI1<T: Iterator<Item: Copy, Item: Send>> { f: T }
    |                       `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:39:35
+  --> $DIR/duplicate.rs:38:35
    |
 LL | union UI2<T: Iterator<Item: Copy, Item: Copy>> { f: T }
    |                       ----------  ^^^^^^^^^^ re-bound here
@@ -128,7 +120,7 @@ LL | union UI2<T: Iterator<Item: Copy, Item: Copy>> { f: T }
    |                       `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:41:38
+  --> $DIR/duplicate.rs:40:38
    |
 LL | union UI3<T: Iterator<Item: 'static, Item: 'static>> { f: T }
    |                       -------------  ^^^^^^^^^^^^^ re-bound here
@@ -136,7 +128,7 @@ LL | union UI3<T: Iterator<Item: 'static, Item: 'static>> { f: T }
    |                       `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:43:44
+  --> $DIR/duplicate.rs:42:44
    |
 LL | union UW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T }
    |                                ----------  ^^^^^^^^^^ re-bound here
@@ -144,7 +136,7 @@ LL | union UW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T }
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:45:44
+  --> $DIR/duplicate.rs:44:44
    |
 LL | union UW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T }
    |                                ----------  ^^^^^^^^^^ re-bound here
@@ -152,7 +144,7 @@ LL | union UW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T }
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:47:47
+  --> $DIR/duplicate.rs:46:47
    |
 LL | union UW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T }
    |                                -------------  ^^^^^^^^^^^^^ re-bound here
@@ -160,7 +152,7 @@ LL | union UW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T }
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:50:32
+  --> $DIR/duplicate.rs:49:32
    |
 LL | fn FI1<T: Iterator<Item: Copy, Item: Send>>() {}
    |                    ----------  ^^^^^^^^^^ re-bound here
@@ -168,7 +160,7 @@ LL | fn FI1<T: Iterator<Item: Copy, Item: Send>>() {}
    |                    `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:52:32
+  --> $DIR/duplicate.rs:51:32
    |
 LL | fn FI2<T: Iterator<Item: Copy, Item: Copy>>() {}
    |                    ----------  ^^^^^^^^^^ re-bound here
@@ -176,7 +168,7 @@ LL | fn FI2<T: Iterator<Item: Copy, Item: Copy>>() {}
    |                    `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:54:35
+  --> $DIR/duplicate.rs:53:35
    |
 LL | fn FI3<T: Iterator<Item: 'static, Item: 'static>>() {}
    |                    -------------  ^^^^^^^^^^^^^ re-bound here
@@ -184,7 +176,7 @@ LL | fn FI3<T: Iterator<Item: 'static, Item: 'static>>() {}
    |                    `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:56:43
+  --> $DIR/duplicate.rs:55:43
    |
 LL | fn FW1<T>() where T: Iterator<Item: Copy, Item: Send> {}
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -192,7 +184,7 @@ LL | fn FW1<T>() where T: Iterator<Item: Copy, Item: Send> {}
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:58:43
+  --> $DIR/duplicate.rs:57:43
    |
 LL | fn FW2<T>() where T: Iterator<Item: Copy, Item: Copy> {}
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -200,7 +192,7 @@ LL | fn FW2<T>() where T: Iterator<Item: Copy, Item: Copy> {}
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:60:46
+  --> $DIR/duplicate.rs:59:46
    |
 LL | fn FW3<T>() where T: Iterator<Item: 'static, Item: 'static> {}
    |                               -------------  ^^^^^^^^^^^^^ re-bound here
@@ -208,7 +200,7 @@ LL | fn FW3<T>() where T: Iterator<Item: 'static, Item: 'static> {}
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:66:40
+  --> $DIR/duplicate.rs:65:40
    |
 LL | fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {}
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -216,7 +208,7 @@ LL | fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {}
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:68:40
+  --> $DIR/duplicate.rs:67:40
    |
 LL | fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {}
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -224,7 +216,7 @@ LL | fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {}
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:70:43
+  --> $DIR/duplicate.rs:69:43
    |
 LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {}
    |                            -------------  ^^^^^^^^^^^^^ re-bound here
@@ -232,79 +224,7 @@ LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {}
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:73:39
-   |
-LL | const CIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty();
-   |                           ----------  ^^^^^^^^^^ re-bound here
-   |                           |
-   |                           `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:75:39
-   |
-LL | const CIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty();
-   |                           ----------  ^^^^^^^^^^ re-bound here
-   |                           |
-   |                           `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:77:42
-   |
-LL | const CIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty();
-   |                           -------------  ^^^^^^^^^^^^^ re-bound here
-   |                           |
-   |                           `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:79:40
-   |
-LL | static SIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty();
-   |                            ----------  ^^^^^^^^^^ re-bound here
-   |                            |
-   |                            `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:81:40
-   |
-LL | static SIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty();
-   |                            ----------  ^^^^^^^^^^ re-bound here
-   |                            |
-   |                            `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:83:43
-   |
-LL | static SIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty();
-   |                            -------------  ^^^^^^^^^^^^^ re-bound here
-   |                            |
-   |                            `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:86:46
-   |
-LL | fn lit1() { let _: impl Iterator<Item: Copy, Item: Send> = iter::empty(); }
-   |                                  ----------  ^^^^^^^^^^ re-bound here
-   |                                  |
-   |                                  `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:88:46
-   |
-LL | fn lit2() { let _: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); }
-   |                                  ----------  ^^^^^^^^^^ re-bound here
-   |                                  |
-   |                                  `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:90:49
-   |
-LL | fn lit3() { let _: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); }
-   |                                  -------------  ^^^^^^^^^^^^^ re-bound here
-   |                                  |
-   |                                  `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:93:35
+  --> $DIR/duplicate.rs:72:35
    |
 LL | type TAI1<T: Iterator<Item: Copy, Item: Send>> = T;
    |                       ----------  ^^^^^^^^^^ re-bound here
@@ -312,7 +232,7 @@ LL | type TAI1<T: Iterator<Item: Copy, Item: Send>> = T;
    |                       `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:95:35
+  --> $DIR/duplicate.rs:74:35
    |
 LL | type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T;
    |                       ----------  ^^^^^^^^^^ re-bound here
@@ -320,7 +240,7 @@ LL | type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T;
    |                       `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:97:38
+  --> $DIR/duplicate.rs:76:38
    |
 LL | type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T;
    |                       -------------  ^^^^^^^^^^^^^ re-bound here
@@ -328,7 +248,7 @@ LL | type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T;
    |                       `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:99:44
+  --> $DIR/duplicate.rs:78:44
    |
 LL | type TAW1<T> where T: Iterator<Item: Copy, Item: Send> = T;
    |                                ----------  ^^^^^^^^^^ re-bound here
@@ -336,7 +256,7 @@ LL | type TAW1<T> where T: Iterator<Item: Copy, Item: Send> = T;
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:101:44
+  --> $DIR/duplicate.rs:80:44
    |
 LL | type TAW2<T> where T: Iterator<Item: Copy, Item: Copy> = T;
    |                                ----------  ^^^^^^^^^^ re-bound here
@@ -344,7 +264,7 @@ LL | type TAW2<T> where T: Iterator<Item: Copy, Item: Copy> = T;
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:103:47
+  --> $DIR/duplicate.rs:82:47
    |
 LL | type TAW3<T> where T: Iterator<Item: 'static, Item: 'static> = T;
    |                                -------------  ^^^^^^^^^^^^^ re-bound here
@@ -352,7 +272,7 @@ LL | type TAW3<T> where T: Iterator<Item: 'static, Item: 'static> = T;
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:106:36
+  --> $DIR/duplicate.rs:85:36
    |
 LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -360,7 +280,7 @@ LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:108:36
+  --> $DIR/duplicate.rs:87:36
    |
 LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -368,7 +288,7 @@ LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:110:39
+  --> $DIR/duplicate.rs:89:39
    |
 LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
    |                        -------------  ^^^^^^^^^^^^^ re-bound here
@@ -376,7 +296,7 @@ LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:112:40
+  --> $DIR/duplicate.rs:91:40
    |
 LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -384,7 +304,7 @@ LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:114:40
+  --> $DIR/duplicate.rs:93:40
    |
 LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -392,7 +312,7 @@ LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:116:43
+  --> $DIR/duplicate.rs:95:43
    |
 LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                            -------------  ^^^^^^^^^^^^^ re-bound here
@@ -400,7 +320,7 @@ LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:119:36
+  --> $DIR/duplicate.rs:98:36
    |
 LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -408,7 +328,7 @@ LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:121:36
+  --> $DIR/duplicate.rs:100:36
    |
 LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -416,7 +336,7 @@ LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:123:39
+  --> $DIR/duplicate.rs:102:39
    |
 LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
    |                        -------------  ^^^^^^^^^^^^^ re-bound here
@@ -424,7 +344,7 @@ LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:125:34
+  --> $DIR/duplicate.rs:104:34
    |
 LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -432,7 +352,7 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:127:34
+  --> $DIR/duplicate.rs:106:34
    |
 LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -440,7 +360,7 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:129:37
+  --> $DIR/duplicate.rs:108:37
    |
 LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    |                      -------------  ^^^^^^^^^^^^^ re-bound here
@@ -448,7 +368,7 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:131:45
+  --> $DIR/duplicate.rs:110:45
    |
 LL | trait TRW1<T> where T: Iterator<Item: Copy, Item: Send> {}
    |                                 ----------  ^^^^^^^^^^ re-bound here
@@ -456,7 +376,7 @@ LL | trait TRW1<T> where T: Iterator<Item: Copy, Item: Send> {}
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:133:45
+  --> $DIR/duplicate.rs:112:45
    |
 LL | trait TRW2<T> where T: Iterator<Item: Copy, Item: Copy> {}
    |                                 ----------  ^^^^^^^^^^ re-bound here
@@ -464,7 +384,7 @@ LL | trait TRW2<T> where T: Iterator<Item: Copy, Item: Copy> {}
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:135:48
+  --> $DIR/duplicate.rs:114:48
    |
 LL | trait TRW3<T> where T: Iterator<Item: 'static, Item: 'static> {}
    |                                 -------------  ^^^^^^^^^^^^^ re-bound here
@@ -472,7 +392,7 @@ LL | trait TRW3<T> where T: Iterator<Item: 'static, Item: 'static> {}
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:137:46
+  --> $DIR/duplicate.rs:116:46
    |
 LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -480,7 +400,7 @@ LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:137:46
+  --> $DIR/duplicate.rs:116:46
    |
 LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -488,7 +408,7 @@ LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:140:46
+  --> $DIR/duplicate.rs:119:46
    |
 LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -496,7 +416,7 @@ LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:140:46
+  --> $DIR/duplicate.rs:119:46
    |
 LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -504,7 +424,7 @@ LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:143:49
+  --> $DIR/duplicate.rs:122:49
    |
 LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  -------------  ^^^^^^^^^^^^^ re-bound here
@@ -512,7 +432,7 @@ LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:143:49
+  --> $DIR/duplicate.rs:122:49
    |
 LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  -------------  ^^^^^^^^^^^^^ re-bound here
@@ -520,7 +440,7 @@ LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:153:40
+  --> $DIR/duplicate.rs:132:40
    |
 LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -528,7 +448,7 @@ LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:155:44
+  --> $DIR/duplicate.rs:134:44
    |
 LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                ----------  ^^^^^^^^^^ re-bound here
@@ -536,7 +456,7 @@ LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:157:43
+  --> $DIR/duplicate.rs:136:43
    |
 LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            -------------  ^^^^^^^^^^^^^ re-bound here
@@ -544,7 +464,7 @@ LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:146:43
+  --> $DIR/duplicate.rs:125:43
    |
 LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -552,7 +472,7 @@ LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:148:43
+  --> $DIR/duplicate.rs:127:43
    |
 LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -560,13 +480,13 @@ LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:150:46
+  --> $DIR/duplicate.rs:129:46
    |
 LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; }
    |                               -------------  ^^^^^^^^^^^^^ re-bound here
    |                               |
    |                               `Item` bound here first
 
-error: aborting due to 69 previous errors; 2 warnings emitted
+error: aborting due to 60 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0719`.
index 500e527a0188afcfb3911bbaa4d97f27e8ec53f9..06bfac588de0060374fc515e9a26b7860c3d0938 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/duplicate.rs:6:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:11:36
+  --> $DIR/duplicate.rs:10:36
    |
 LL | struct SI1<T: Iterator<Item: Copy, Item: Send>> { f: T }
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -16,7 +7,7 @@ LL | struct SI1<T: Iterator<Item: Copy, Item: Send>> { f: T }
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:13:36
+  --> $DIR/duplicate.rs:12:36
    |
 LL | struct SI2<T: Iterator<Item: Copy, Item: Copy>> { f: T }
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -24,7 +15,7 @@ LL | struct SI2<T: Iterator<Item: Copy, Item: Copy>> { f: T }
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:15:39
+  --> $DIR/duplicate.rs:14:39
    |
 LL | struct SI3<T: Iterator<Item: 'static, Item: 'static>> { f: T }
    |                        -------------  ^^^^^^^^^^^^^ re-bound here
@@ -32,7 +23,7 @@ LL | struct SI3<T: Iterator<Item: 'static, Item: 'static>> { f: T }
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:17:45
+  --> $DIR/duplicate.rs:16:45
    |
 LL | struct SW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T }
    |                                 ----------  ^^^^^^^^^^ re-bound here
@@ -40,7 +31,7 @@ LL | struct SW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T }
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:19:45
+  --> $DIR/duplicate.rs:18:45
    |
 LL | struct SW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T }
    |                                 ----------  ^^^^^^^^^^ re-bound here
@@ -48,7 +39,7 @@ LL | struct SW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T }
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:21:48
+  --> $DIR/duplicate.rs:20:48
    |
 LL | struct SW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T }
    |                                 -------------  ^^^^^^^^^^^^^ re-bound here
@@ -56,7 +47,7 @@ LL | struct SW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T }
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:24:34
+  --> $DIR/duplicate.rs:23:34
    |
 LL | enum EI1<T: Iterator<Item: Copy, Item: Send>> { V(T) }
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -64,7 +55,7 @@ LL | enum EI1<T: Iterator<Item: Copy, Item: Send>> { V(T) }
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:26:34
+  --> $DIR/duplicate.rs:25:34
    |
 LL | enum EI2<T: Iterator<Item: Copy, Item: Copy>> { V(T) }
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -72,7 +63,7 @@ LL | enum EI2<T: Iterator<Item: Copy, Item: Copy>> { V(T) }
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:28:37
+  --> $DIR/duplicate.rs:27:37
    |
 LL | enum EI3<T: Iterator<Item: 'static, Item: 'static>> { V(T) }
    |                      -------------  ^^^^^^^^^^^^^ re-bound here
@@ -80,7 +71,7 @@ LL | enum EI3<T: Iterator<Item: 'static, Item: 'static>> { V(T) }
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:30:43
+  --> $DIR/duplicate.rs:29:43
    |
 LL | enum EW1<T> where T: Iterator<Item: Copy, Item: Send> { V(T) }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -88,7 +79,7 @@ LL | enum EW1<T> where T: Iterator<Item: Copy, Item: Send> { V(T) }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:32:43
+  --> $DIR/duplicate.rs:31:43
    |
 LL | enum EW2<T> where T: Iterator<Item: Copy, Item: Copy> { V(T) }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -96,7 +87,7 @@ LL | enum EW2<T> where T: Iterator<Item: Copy, Item: Copy> { V(T) }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:34:46
+  --> $DIR/duplicate.rs:33:46
    |
 LL | enum EW3<T> where T: Iterator<Item: 'static, Item: 'static> { V(T) }
    |                               -------------  ^^^^^^^^^^^^^ re-bound here
@@ -104,7 +95,7 @@ LL | enum EW3<T> where T: Iterator<Item: 'static, Item: 'static> { V(T) }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:37:35
+  --> $DIR/duplicate.rs:36:35
    |
 LL | union UI1<T: Iterator<Item: Copy, Item: Send>> { f: T }
    |                       ----------  ^^^^^^^^^^ re-bound here
@@ -112,7 +103,7 @@ LL | union UI1<T: Iterator<Item: Copy, Item: Send>> { f: T }
    |                       `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:39:35
+  --> $DIR/duplicate.rs:38:35
    |
 LL | union UI2<T: Iterator<Item: Copy, Item: Copy>> { f: T }
    |                       ----------  ^^^^^^^^^^ re-bound here
@@ -120,7 +111,7 @@ LL | union UI2<T: Iterator<Item: Copy, Item: Copy>> { f: T }
    |                       `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:41:38
+  --> $DIR/duplicate.rs:40:38
    |
 LL | union UI3<T: Iterator<Item: 'static, Item: 'static>> { f: T }
    |                       -------------  ^^^^^^^^^^^^^ re-bound here
@@ -128,7 +119,7 @@ LL | union UI3<T: Iterator<Item: 'static, Item: 'static>> { f: T }
    |                       `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:43:44
+  --> $DIR/duplicate.rs:42:44
    |
 LL | union UW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T }
    |                                ----------  ^^^^^^^^^^ re-bound here
@@ -136,7 +127,7 @@ LL | union UW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T }
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:45:44
+  --> $DIR/duplicate.rs:44:44
    |
 LL | union UW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T }
    |                                ----------  ^^^^^^^^^^ re-bound here
@@ -144,7 +135,7 @@ LL | union UW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T }
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:47:47
+  --> $DIR/duplicate.rs:46:47
    |
 LL | union UW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T }
    |                                -------------  ^^^^^^^^^^^^^ re-bound here
@@ -152,7 +143,7 @@ LL | union UW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T }
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:50:32
+  --> $DIR/duplicate.rs:49:32
    |
 LL | fn FI1<T: Iterator<Item: Copy, Item: Send>>() {}
    |                    ----------  ^^^^^^^^^^ re-bound here
@@ -160,7 +151,7 @@ LL | fn FI1<T: Iterator<Item: Copy, Item: Send>>() {}
    |                    `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:52:32
+  --> $DIR/duplicate.rs:51:32
    |
 LL | fn FI2<T: Iterator<Item: Copy, Item: Copy>>() {}
    |                    ----------  ^^^^^^^^^^ re-bound here
@@ -168,7 +159,7 @@ LL | fn FI2<T: Iterator<Item: Copy, Item: Copy>>() {}
    |                    `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:54:35
+  --> $DIR/duplicate.rs:53:35
    |
 LL | fn FI3<T: Iterator<Item: 'static, Item: 'static>>() {}
    |                    -------------  ^^^^^^^^^^^^^ re-bound here
@@ -176,7 +167,7 @@ LL | fn FI3<T: Iterator<Item: 'static, Item: 'static>>() {}
    |                    `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:56:43
+  --> $DIR/duplicate.rs:55:43
    |
 LL | fn FW1<T>() where T: Iterator<Item: Copy, Item: Send> {}
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -184,7 +175,7 @@ LL | fn FW1<T>() where T: Iterator<Item: Copy, Item: Send> {}
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:58:43
+  --> $DIR/duplicate.rs:57:43
    |
 LL | fn FW2<T>() where T: Iterator<Item: Copy, Item: Copy> {}
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -192,7 +183,7 @@ LL | fn FW2<T>() where T: Iterator<Item: Copy, Item: Copy> {}
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:60:46
+  --> $DIR/duplicate.rs:59:46
    |
 LL | fn FW3<T>() where T: Iterator<Item: 'static, Item: 'static> {}
    |                               -------------  ^^^^^^^^^^^^^ re-bound here
@@ -200,7 +191,7 @@ LL | fn FW3<T>() where T: Iterator<Item: 'static, Item: 'static> {}
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:66:40
+  --> $DIR/duplicate.rs:65:40
    |
 LL | fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {}
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -208,7 +199,7 @@ LL | fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {}
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:68:40
+  --> $DIR/duplicate.rs:67:40
    |
 LL | fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {}
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -216,7 +207,7 @@ LL | fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {}
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:70:43
+  --> $DIR/duplicate.rs:69:43
    |
 LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {}
    |                            -------------  ^^^^^^^^^^^^^ re-bound here
@@ -224,79 +215,7 @@ LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {}
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:73:39
-   |
-LL | const CIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty();
-   |                           ----------  ^^^^^^^^^^ re-bound here
-   |                           |
-   |                           `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:75:39
-   |
-LL | const CIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty();
-   |                           ----------  ^^^^^^^^^^ re-bound here
-   |                           |
-   |                           `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:77:42
-   |
-LL | const CIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty();
-   |                           -------------  ^^^^^^^^^^^^^ re-bound here
-   |                           |
-   |                           `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:79:40
-   |
-LL | static SIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty();
-   |                            ----------  ^^^^^^^^^^ re-bound here
-   |                            |
-   |                            `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:81:40
-   |
-LL | static SIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty();
-   |                            ----------  ^^^^^^^^^^ re-bound here
-   |                            |
-   |                            `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:83:43
-   |
-LL | static SIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty();
-   |                            -------------  ^^^^^^^^^^^^^ re-bound here
-   |                            |
-   |                            `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:86:46
-   |
-LL | fn lit1() { let _: impl Iterator<Item: Copy, Item: Send> = iter::empty(); }
-   |                                  ----------  ^^^^^^^^^^ re-bound here
-   |                                  |
-   |                                  `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:88:46
-   |
-LL | fn lit2() { let _: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); }
-   |                                  ----------  ^^^^^^^^^^ re-bound here
-   |                                  |
-   |                                  `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:90:49
-   |
-LL | fn lit3() { let _: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); }
-   |                                  -------------  ^^^^^^^^^^^^^ re-bound here
-   |                                  |
-   |                                  `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:93:35
+  --> $DIR/duplicate.rs:72:35
    |
 LL | type TAI1<T: Iterator<Item: Copy, Item: Send>> = T;
    |                       ----------  ^^^^^^^^^^ re-bound here
@@ -304,7 +223,7 @@ LL | type TAI1<T: Iterator<Item: Copy, Item: Send>> = T;
    |                       `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:95:35
+  --> $DIR/duplicate.rs:74:35
    |
 LL | type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T;
    |                       ----------  ^^^^^^^^^^ re-bound here
@@ -312,7 +231,7 @@ LL | type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T;
    |                       `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:97:38
+  --> $DIR/duplicate.rs:76:38
    |
 LL | type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T;
    |                       -------------  ^^^^^^^^^^^^^ re-bound here
@@ -320,7 +239,7 @@ LL | type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T;
    |                       `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:99:44
+  --> $DIR/duplicate.rs:78:44
    |
 LL | type TAW1<T> where T: Iterator<Item: Copy, Item: Send> = T;
    |                                ----------  ^^^^^^^^^^ re-bound here
@@ -328,7 +247,7 @@ LL | type TAW1<T> where T: Iterator<Item: Copy, Item: Send> = T;
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:101:44
+  --> $DIR/duplicate.rs:80:44
    |
 LL | type TAW2<T> where T: Iterator<Item: Copy, Item: Copy> = T;
    |                                ----------  ^^^^^^^^^^ re-bound here
@@ -336,7 +255,7 @@ LL | type TAW2<T> where T: Iterator<Item: Copy, Item: Copy> = T;
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:103:47
+  --> $DIR/duplicate.rs:82:47
    |
 LL | type TAW3<T> where T: Iterator<Item: 'static, Item: 'static> = T;
    |                                -------------  ^^^^^^^^^^^^^ re-bound here
@@ -344,7 +263,7 @@ LL | type TAW3<T> where T: Iterator<Item: 'static, Item: 'static> = T;
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:106:36
+  --> $DIR/duplicate.rs:85:36
    |
 LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -352,7 +271,7 @@ LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:108:36
+  --> $DIR/duplicate.rs:87:36
    |
 LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -360,7 +279,7 @@ LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:110:39
+  --> $DIR/duplicate.rs:89:39
    |
 LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
    |                        -------------  ^^^^^^^^^^^^^ re-bound here
@@ -368,7 +287,7 @@ LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:112:40
+  --> $DIR/duplicate.rs:91:40
    |
 LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -376,7 +295,7 @@ LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:114:40
+  --> $DIR/duplicate.rs:93:40
    |
 LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -384,7 +303,7 @@ LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:116:43
+  --> $DIR/duplicate.rs:95:43
    |
 LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                            -------------  ^^^^^^^^^^^^^ re-bound here
@@ -392,7 +311,7 @@ LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:119:36
+  --> $DIR/duplicate.rs:98:36
    |
 LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -400,7 +319,7 @@ LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:121:36
+  --> $DIR/duplicate.rs:100:36
    |
 LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -408,7 +327,7 @@ LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:123:39
+  --> $DIR/duplicate.rs:102:39
    |
 LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
    |                        -------------  ^^^^^^^^^^^^^ re-bound here
@@ -416,7 +335,7 @@ LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:125:34
+  --> $DIR/duplicate.rs:104:34
    |
 LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -424,7 +343,7 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:127:34
+  --> $DIR/duplicate.rs:106:34
    |
 LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -432,7 +351,7 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:129:37
+  --> $DIR/duplicate.rs:108:37
    |
 LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    |                      -------------  ^^^^^^^^^^^^^ re-bound here
@@ -440,7 +359,7 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:131:45
+  --> $DIR/duplicate.rs:110:45
    |
 LL | trait TRW1<T> where T: Iterator<Item: Copy, Item: Send> {}
    |                                 ----------  ^^^^^^^^^^ re-bound here
@@ -448,7 +367,7 @@ LL | trait TRW1<T> where T: Iterator<Item: Copy, Item: Send> {}
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:133:45
+  --> $DIR/duplicate.rs:112:45
    |
 LL | trait TRW2<T> where T: Iterator<Item: Copy, Item: Copy> {}
    |                                 ----------  ^^^^^^^^^^ re-bound here
@@ -456,7 +375,7 @@ LL | trait TRW2<T> where T: Iterator<Item: Copy, Item: Copy> {}
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:135:48
+  --> $DIR/duplicate.rs:114:48
    |
 LL | trait TRW3<T> where T: Iterator<Item: 'static, Item: 'static> {}
    |                                 -------------  ^^^^^^^^^^^^^ re-bound here
@@ -464,7 +383,7 @@ LL | trait TRW3<T> where T: Iterator<Item: 'static, Item: 'static> {}
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:137:46
+  --> $DIR/duplicate.rs:116:46
    |
 LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -472,7 +391,7 @@ LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:137:46
+  --> $DIR/duplicate.rs:116:46
    |
 LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -480,7 +399,7 @@ LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:140:46
+  --> $DIR/duplicate.rs:119:46
    |
 LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -488,7 +407,7 @@ LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:140:46
+  --> $DIR/duplicate.rs:119:46
    |
 LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -496,7 +415,7 @@ LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:143:49
+  --> $DIR/duplicate.rs:122:49
    |
 LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  -------------  ^^^^^^^^^^^^^ re-bound here
@@ -504,7 +423,7 @@ LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:143:49
+  --> $DIR/duplicate.rs:122:49
    |
 LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  -------------  ^^^^^^^^^^^^^ re-bound here
@@ -512,7 +431,7 @@ LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:153:40
+  --> $DIR/duplicate.rs:132:40
    |
 LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -520,7 +439,7 @@ LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:155:44
+  --> $DIR/duplicate.rs:134:44
    |
 LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                ----------  ^^^^^^^^^^ re-bound here
@@ -528,7 +447,7 @@ LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:157:43
+  --> $DIR/duplicate.rs:136:43
    |
 LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            -------------  ^^^^^^^^^^^^^ re-bound here
@@ -536,7 +455,7 @@ LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:146:43
+  --> $DIR/duplicate.rs:125:43
    |
 LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -544,7 +463,7 @@ LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:148:43
+  --> $DIR/duplicate.rs:127:43
    |
 LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -552,13 +471,13 @@ LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:150:46
+  --> $DIR/duplicate.rs:129:46
    |
 LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; }
    |                               -------------  ^^^^^^^^^^^^^ re-bound here
    |                               |
    |                               `Item` bound here first
 
-error: aborting due to 69 previous errors; 1 warning emitted
+error: aborting due to 60 previous errors
 
 For more information about this error, try `rustc --explain E0719`.
index c3319a7050d5d0d20f3d01ae712c71315900bfd7..0d7804ef1a7d5feb499b3f52cb99a04138588ccc 100644 (file)
@@ -3,7 +3,6 @@
 #![feature(min_type_alias_impl_trait)]
 #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
 //[full_tait]~^ WARN incomplete
-#![feature(impl_trait_in_bindings)] //~ WARN the feature `impl_trait_in_bindings` is incomplete
 #![feature(untagged_unions)]
 
 use std::iter;
@@ -70,26 +69,6 @@ fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {}
 fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {}
 //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
 
-const CIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty();
-//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
-const CIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty();
-//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
-const CIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty();
-//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
-static SIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty();
-//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
-static SIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty();
-//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
-static SIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty();
-//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
-
-fn lit1() { let _: impl Iterator<Item: Copy, Item: Send> = iter::empty(); }
-//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
-fn lit2() { let _: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); }
-//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
-fn lit3() { let _: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); }
-//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
-
 type TAI1<T: Iterator<Item: Copy, Item: Send>> = T;
 //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
 type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T;
diff --git a/src/test/ui/associated-type-bounds/dyn-lcsit.rs b/src/test/ui/associated-type-bounds/dyn-lcsit.rs
deleted file mode 100644 (file)
index b7869e2..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-// run-pass
-
-#![feature(associated_type_bounds)]
-#![feature(impl_trait_in_bindings)]
-//~^ WARNING `impl_trait_in_bindings` is incomplete
-#![allow(non_upper_case_globals)]
-
-use std::ops::Add;
-
-trait Tr1 { type As1; fn mk(&self) -> Self::As1; }
-trait Tr2<'a> { fn tr2(self) -> &'a Self; }
-
-fn assert_copy<T: Copy>(x: T) { let _x = x; let _x = x; }
-fn assert_static<T: 'static>(_: T) {}
-fn assert_forall_tr2<T: for<'a> Tr2<'a>>(_: T) {}
-
-#[derive(Copy, Clone)]
-struct S1;
-#[derive(Copy, Clone)]
-struct S2;
-impl Tr1 for S1 { type As1 = S2; fn mk(&self) -> Self::As1 { S2 } }
-
-const cdef_et1: &dyn Tr1<As1: Copy> = &S1;
-const sdef_et1: &dyn Tr1<As1: Copy> = &S1;
-pub fn use_et1() { assert_copy(cdef_et1.mk()); assert_copy(sdef_et1.mk()); }
-
-const cdef_et2: &(dyn Tr1<As1: 'static> + Sync) = &S1;
-static sdef_et2: &(dyn Tr1<As1: 'static> + Sync) = &S1;
-pub fn use_et2() { assert_static(cdef_et2.mk()); assert_static(sdef_et2.mk()); }
-
-const cdef_et3: &dyn Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>> = {
-    struct A;
-    impl Tr1 for A {
-        type As1 = core::ops::Range<u8>;
-        fn mk(&self) -> Self::As1 { 0..10 }
-    }
-    &A
-};
-pub fn use_et3() {
-    let _0 = cdef_et3.mk().clone();
-    let mut s = 0u8;
-    for _1 in _0 {
-        let _2 = _1 + 1u8;
-        s += _2.into();
-    }
-    assert_eq!(s, (0..10).map(|x| x + 1).sum());
-}
-
-const cdef_et4: &(dyn Tr1<As1: for<'a> Tr2<'a>> + Sync) = {
-    #[derive(Copy, Clone)]
-    struct A;
-    impl Tr1 for A {
-        type As1 = A;
-        fn mk(&self) -> A { A }
-    }
-    impl<'a> Tr2<'a> for A {
-        fn tr2(self) -> &'a Self { &A }
-    }
-    &A
-};
-static sdef_et4: &(dyn Tr1<As1: for<'a> Tr2<'a>> + Sync) = cdef_et4;
-pub fn use_et4() { assert_forall_tr2(cdef_et4.mk()); assert_forall_tr2(sdef_et4.mk()); }
-
-fn main() {
-    let _ = use_et1();
-    let _ = use_et2();
-    let _ = use_et3();
-    let _ = use_et4();
-}
diff --git a/src/test/ui/associated-type-bounds/dyn-lcsit.stderr b/src/test/ui/associated-type-bounds/dyn-lcsit.stderr
deleted file mode 100644 (file)
index 3637f95..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/dyn-lcsit.rs:4:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/associated-type-bounds/lcsit.rs b/src/test/ui/associated-type-bounds/lcsit.rs
deleted file mode 100644 (file)
index 5364f25..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-// run-pass
-
-#![feature(associated_type_bounds)]
-#![feature(impl_trait_in_bindings)]
-//~^ WARNING `impl_trait_in_bindings` is incomplete
-#![allow(non_upper_case_globals)]
-
-use std::ops::Add;
-
-trait Tr1 { type As1; fn mk(&self) -> Self::As1; }
-trait Tr2<'a> { fn tr2(self) -> &'a Self; }
-
-fn assert_copy<T: Copy>(x: T) { let _x = x; let _x = x; }
-fn assert_static<T: 'static>(_: T) {}
-fn assert_forall_tr2<T: for<'a> Tr2<'a>>(_: T) {}
-
-#[derive(Copy, Clone)]
-struct S1;
-#[derive(Copy, Clone)]
-struct S2;
-impl Tr1 for S1 { type As1 = S2; fn mk(&self) -> Self::As1 { S2 } }
-
-const cdef_et1: impl Copy + Tr1<As1: Copy> = {
-    let x: impl Copy + Tr1<As1: Copy> = S1;
-    x
-};
-static sdef_et1: impl Copy + Tr1<As1: Copy> = cdef_et1;
-pub fn use_et1() { assert_copy(cdef_et1.mk()); assert_copy(sdef_et1.mk()); }
-
-const cdef_et2: impl Tr1<As1: 'static> = {
-    let x: impl Tr1<As1: 'static> = S1;
-    x
-};
-static sdef_et2: impl Tr1<As1: 'static> = cdef_et2;
-pub fn use_et2() { assert_static(cdef_et2.mk()); assert_static(sdef_et2.mk()); }
-
-const cdef_et3: impl Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>> = {
-    struct A;
-    impl Tr1 for A {
-        type As1 = core::ops::Range<u8>;
-        fn mk(&self) -> Self::As1 { 0..10 }
-    }
-    let x: impl Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>> = A;
-    x
-};
-pub fn use_et3() {
-    let _0 = cdef_et3.mk().clone();
-    let mut s = 0u8;
-    for _1 in _0 {
-        let _2 = _1 + 1u8;
-        s += _2.into();
-    }
-    assert_eq!(s, (0..10).map(|x| x + 1).sum());
-}
-
-const cdef_et4: impl Copy + Tr1<As1: for<'a> Tr2<'a>> = {
-    #[derive(Copy, Clone)]
-    struct A;
-    impl Tr1 for A {
-        type As1 = A;
-        fn mk(&self) -> A { A }
-    }
-    impl<'a> Tr2<'a> for A {
-        fn tr2(self) -> &'a Self { &A }
-    }
-    let x: impl Copy + Tr1<As1: for<'a> Tr2<'a>> = A;
-    x
-};
-
-static sdef_et4: impl Copy + Tr1<As1: for<'a> Tr2<'a>> = cdef_et4;
-pub fn use_et4() { assert_forall_tr2(cdef_et4.mk()); assert_forall_tr2(sdef_et4.mk()); }
-
-fn main() {
-    let _ = use_et1();
-    let _ = use_et2();
-    let _ = use_et3();
-    let _ = use_et4();
-}
diff --git a/src/test/ui/associated-type-bounds/lcsit.stderr b/src/test/ui/associated-type-bounds/lcsit.stderr
deleted file mode 100644 (file)
index 11ff03d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/lcsit.rs:4:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-warning: 1 warning emitted
-
index ab8909d1092baf3411cead06af2b90de50634cd3..41e2d8ec314b777c707f2a661d388ca66aa98383 100644 (file)
@@ -1,12 +1,14 @@
 error[E0277]: the trait bound `<G as GetToInt>::R: ToInt` is not satisfied
   --> $DIR/associated-types-bound-failure.rs:19:19
    |
-LL |     fn to_int(&self) -> isize;
-   |     -------------------------- required by `ToInt::to_int`
-...
 LL |     ToInt::to_int(&g.get())
    |                   ^^^^^^^^ the trait `ToInt` is not implemented for `<G as GetToInt>::R`
    |
+note: required by `ToInt::to_int`
+  --> $DIR/associated-types-bound-failure.rs:6:5
+   |
+LL |     fn to_int(&self) -> isize;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider further restricting the associated type
    |
 LL |     where G : GetToInt, <G as GetToInt>::R: ToInt
index 6d7289bd0712ba897074def15916d9b3a83d9b34..25e80159b0b180cf5e7080206c5a23bb56595df9 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-for-unimpl-trait.rs:10:5
+  --> $DIR/associated-types-for-unimpl-trait.rs:10:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
index 0b5dee611e489be85c879e1d2470c4373807f437..19500f58aa6883d721d6dbd02e94220635693b2f 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `T: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-bound.rs:11:5
+  --> $DIR/associated-types-no-suitable-bound.rs:11:21
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<T>(foo: <T as Get>::Value) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
+   |                     ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
index dfe62aa5d6b00b8e5d0ec23137ee721eeb62c42e..0e978f20a6634237dc8ca2a383025ba0b44d3158 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5
+  --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
index f0f2451a1eceac5216475e92a120c398991f7e20..1ec3c05983aefdc193557b482cd82ba8f4945ebc 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait.rs:17:5
+  --> $DIR/associated-types-no-suitable-supertrait.rs:17:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
@@ -10,10 +13,13 @@ LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Ge
    |                                                              ^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `(T, U): Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait.rs:22:5
+  --> $DIR/associated-types-no-suitable-supertrait.rs:22:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
 
 error: aborting due to 2 previous errors
 
index 4528f03c54a639b276004f2fc0eb1727ee0f770f..b6ee1ed733c3e99cc0f82f280bc964083bd170bc 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:5
+  --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
index 9d084203e3a8664c3962dedb90c85445bc1d1555..5f4b65bd131ee4129757a80d6a85ff776f03d80d 100644 (file)
@@ -1,13 +1,15 @@
 error[E0283]: type annotations needed
   --> $DIR/associated-types-unconstrained.rs:14:20
    |
-LL |     fn bar() -> isize;
-   |     ------------------ required by `Foo::bar`
-...
 LL |     let x: isize = Foo::bar();
    |                    ^^^^^^^^ cannot infer type
    |
    = note: cannot satisfy `_: Foo`
+note: required by `Foo::bar`
+  --> $DIR/associated-types-unconstrained.rs:5:5
+   |
+LL |     fn bar() -> isize;
+   |     ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index d4fa5be742ff3486dab53e8773b600c9fa3f410b..73ef567ffae6db158edd31d1f79f17644e2dd4c5 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/defaults-wf.rs:7:5
+  --> $DIR/defaults-wf.rs:7:15
    |
 LL |     type Ty = Vec<[u8]>;
-   |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |               ^^^^^^^^^ doesn't have a size known at compile-time
    | 
   ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
    |
index 1270cd6706aef85ffd6c3c696c76e2c58802ba01..bad736b64c038122dc7988cae58fb89600e997c7 100644 (file)
@@ -11,7 +11,7 @@ where
 }
 
 impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
-    //~^ ERROR the trait bound `<T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied
+    //~^ ERROR the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied
     type Item = T;
     //~^ ERROR the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref
 }
index cf4ec0babfc219a04b89a9b2bdc0af659c068e4b..49fad4e1b1cb80e975cd9bad2e36fd1c8d9a9eb7 100644 (file)
@@ -14,16 +14,16 @@ LL |     type Item = T;
              <&T as Deref>
              <&mut T as Deref>
 
-error[E0277]: the trait bound `<T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied
+error[E0277]: the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied
   --> $DIR/hr-associated-type-projection-1.rs:13:33
    |
 LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
-   |                                 ^^^^^^^^^^^^^^^^^ the trait `Deref` is not implemented for `<T as UnsafeCopy<'b, T>>::Item`
+   |                                 ^^^^^^^^^^^^^^^^^ the trait `for<'b> Deref` is not implemented for `<T as UnsafeCopy<'b, T>>::Item`
    |
 help: consider further restricting the associated type
    |
-LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T where <T as UnsafeCopy<'b, T>>::Item: Deref {
-   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T where for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref {
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/issue-20005.rs b/src/test/ui/associated-types/issue-20005.rs
new file mode 100644 (file)
index 0000000..36350bf
--- /dev/null
@@ -0,0 +1,15 @@
+trait From<Src> {
+    type Result;
+
+    fn from(src: Src) -> Self::Result;
+}
+
+trait To {
+    fn to<Dst>(
+        self
+    ) -> <Dst as From<Self>>::Result where Dst: From<Self> { //~ ERROR the size for values of type
+        From::from(self)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-20005.stderr b/src/test/ui/associated-types/issue-20005.stderr
new file mode 100644 (file)
index 0000000..bc41404
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+  --> $DIR/issue-20005.rs:10:49
+   |
+LL | trait From<Src> {
+   |            --- required by this bound in `From`
+...
+LL |     ) -> <Dst as From<Self>>::Result where Dst: From<Self> {
+   |                                                 ^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+help: consider further restricting `Self`
+   |
+LL |     ) -> <Dst as From<Self>>::Result where Dst: From<Self>, Self: Sized {
+   |                                                           ^^^^^^^^^^^^^
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait From<Src: ?Sized> {
+   |               ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index b7db5d385829cd2d1f7b5c334919da4f0f56128a..7bf36d5e91515dbff90e8c892258273262f9ccc7 100644 (file)
@@ -1,9 +1,6 @@
 error[E0271]: type mismatch resolving `<() as Array>::Element == &()`
   --> $DIR/issue-44153.rs:18:5
    |
-LL |     fn visit() {}
-   |     ---------- required by `Visit::visit`
-...
 LL |     <() as Visit>::visit();
    |     ^^^^^^^^^^^^^^^^^^^^ expected `&()`, found `()`
    |
@@ -12,6 +9,11 @@ note: required because of the requirements on the impl of `Visit` for `()`
    |
 LL | impl<'a> Visit for () where
    |          ^^^^^     ^^
+note: required by `Visit::visit`
+  --> $DIR/issue-44153.rs:6:5
+   |
+LL |     fn visit() {}
+   |     ^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/normalization-debruijn-1.rs b/src/test/ui/associated-types/normalization-debruijn-1.rs
new file mode 100644 (file)
index 0000000..a5abf1b
--- /dev/null
@@ -0,0 +1,36 @@
+// build-pass
+// edition:2018
+
+// Regression test to ensure we handle debruijn indices correctly in projection
+// normalization under binders. Found in crater run for #85499
+
+use std::future::Future;
+use std::pin::Pin;
+pub enum Outcome<S, E> {
+    Success((S, E)),
+}
+pub struct Request<'r> {
+    _marker: std::marker::PhantomData<&'r ()>,
+}
+pub trait FromRequest<'r>: Sized {
+    type Error;
+    fn from_request<'life0>(
+        request: &'r Request<'life0>,
+    ) -> Pin<Box<dyn Future<Output = Outcome<Self, Self::Error>>>>;
+}
+impl<'r, T: FromRequest<'r>> FromRequest<'r> for Option<T> {
+    type Error = ();
+    fn from_request<'life0>(
+        request: &'r Request<'life0>,
+    ) -> Pin<Box<dyn Future<Output = Outcome<Self, Self::Error>>>> {
+        Box::pin(async move {
+            let request = request;
+            match T::from_request(request).await {
+                _ => todo!(),
+            }
+        });
+        todo!()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/normalization-debruijn-2.rs b/src/test/ui/associated-types/normalization-debruijn-2.rs
new file mode 100644 (file)
index 0000000..abe248e
--- /dev/null
@@ -0,0 +1,31 @@
+// build-pass
+// edition:2018
+
+// Regression test to ensure we handle debruijn indices correctly in projection
+// normalization under binders. Found in crater run for #85499
+
+use std::future::Future;
+use std::pin::Pin;
+pub enum Outcome<S, E> {
+    Success(S),
+    Failure(E),
+}
+pub struct Request<'r> {
+    _marker: std::marker::PhantomData<&'r ()>,
+}
+pub trait FromRequest<'r>: Sized {
+    type Error;
+    fn from_request<'life0>(
+        request: &'r Request<'life0>,
+    ) -> Pin<Box<dyn Future<Output = Outcome<Self, Self::Error>>>>;
+}
+pub struct S<T> {
+    _marker: std::marker::PhantomData<T>,
+}
+impl<'r, T: FromRequest<'r>> S<T> {
+    pub async fn from_request(request: &'r Request<'_>) {
+        let _ = T::from_request(request).await;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/normalization-debruijn-3.rs b/src/test/ui/associated-types/normalization-debruijn-3.rs
new file mode 100644 (file)
index 0000000..2bea78c
--- /dev/null
@@ -0,0 +1,41 @@
+// build-pass
+// edition:2018
+
+// Regression test to ensure we handle debruijn indices correctly in projection
+// normalization under binders. Found in crater run for #85499
+
+use std::future::{Future, Ready};
+async fn read() {
+    let _ = connect(&()).await;
+}
+async fn connect<A: ToSocketAddr>(addr: A) {
+    let _ = addr.to_socket_addr().await;
+}
+pub trait ToSocketAddr {
+    type Future: Future<Output = ()>;
+    fn to_socket_addr(&self) -> Self::Future;
+}
+impl ToSocketAddr for &() {
+    type Future = Ready<()>;
+    fn to_socket_addr(&self) -> Self::Future {
+        unimplemented!()
+    }
+}
+struct Server;
+impl Server {
+    fn and_then<F>(self, _fun: F) -> AndThen<F> {
+        unimplemented!()
+    }
+}
+struct AndThen<F> {
+    _marker: std::marker::PhantomData<F>,
+}
+pub async fn run<F>(_: F) {
+}
+fn main() {
+    let _ = async {
+        let server = Server;
+        let verification_route = server.and_then(read);
+        run(verification_route).await;
+    };
+}
diff --git a/src/test/ui/associated-types/normalization-generality.rs b/src/test/ui/associated-types/normalization-generality.rs
new file mode 100644 (file)
index 0000000..f8e3f5b
--- /dev/null
@@ -0,0 +1,36 @@
+// build-pass
+
+// Ensures that we don't regress on "implementation is not general enough" when
+// normalizating under binders.
+
+#![feature(no_core)]
+
+pub trait Yokeable<'a> {
+    type Output: 'a;
+}
+
+pub struct Yoke<Y: for<'a> Yokeable<'a>> {
+    _yokeable: Y,
+}
+
+impl<Y: for<'a> Yokeable<'a>> Yoke<Y> {
+    pub fn project<'this, P>(
+        &'this self,
+        _f: for<'a> fn(<Y as Yokeable<'a>>::Output, &'a ()) -> <P as Yokeable<'a>>::Output,
+    ) -> Yoke<P>
+    where
+        P: for<'a> Yokeable<'a>,
+    {
+        unimplemented!()
+    }
+}
+
+pub fn slice(y: Yoke<&'static ()>) -> Yoke<&'static ()> {
+    y.project(move |yk, _| yk)
+}
+
+impl<'a, T> Yokeable<'a> for &'static T {
+    type Output = &'a T;
+}
+
+fn main() {}
index 9694742200ef07d658e0a5606156f0f04f53a4ba..36fb73a8dde247e5b8b03bc273512fab66b36605 100644 (file)
@@ -3,6 +3,8 @@ error[E0726]: implicit elided lifetime not allowed here
    |
 LL | async fn error(lt: HasLifetime) {
    |                    ^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+   |
+   = note: assuming a `'static` lifetime...
 
 error: aborting due to previous error
 
index a3a20cb97e150d45e03d094342e7a6d70cdb3888..50c1639996ee54865d794eedb933ee062436a784 100644 (file)
@@ -3,36 +3,36 @@
 
 mod outer_mod {
     pub mod await { //~ ERROR `await` is a keyword in the 2018 edition
-    //~^ WARN this was previously accepted by the compiler
+    //~^ WARN this is accepted in the current edition
         pub struct await; //~ ERROR `await` is a keyword in the 2018 edition
-        //~^ WARN this was previously accepted by the compiler
+        //~^ WARN this is accepted in the current edition
     }
 }
 use outer_mod::await::await; //~ ERROR `await` is a keyword in the 2018 edition
 //~^ ERROR `await` is a keyword in the 2018 edition
-//~^^ WARN this was previously accepted by the compiler
-//~^^^ WARN this was previously accepted by the compiler
+//~^^ WARN this is accepted in the current edition
+//~^^^ WARN this is accepted in the current edition
 
 struct Foo { await: () }
 //~^ ERROR `await` is a keyword in the 2018 edition
-//~^^ WARN this was previously accepted by the compiler
+//~^^ WARN this is accepted in the current edition
 
 impl Foo { fn await() {} }
 //~^ ERROR `await` is a keyword in the 2018 edition
-//~^^ WARN this was previously accepted by the compiler
+//~^^ WARN this is accepted in the current edition
 
 macro_rules! await {
 //~^ ERROR `await` is a keyword in the 2018 edition
-//~^^ WARN this was previously accepted by the compiler
+//~^^ WARN this is accepted in the current edition
     () => {}
 }
 
 fn main() {
     await!(); //~ ERROR `await` is a keyword in the 2018 edition
-    //~^ WARN this was previously accepted by the compiler
+    //~^ WARN this is accepted in the current edition
 
     match await { await => {} } //~ ERROR `await` is a keyword in the 2018 edition
     //~^ ERROR `await` is a keyword in the 2018 edition
-    //~^^ WARN this was previously accepted by the compiler
-    //~^^^ WARN this was previously accepted by the compiler
+    //~^^ WARN this is accepted in the current edition
+    //~^^^ WARN this is accepted in the current edition
 }
index 474c09d79dfbbe4b115c3a937acdf7892dc0382d..50a82c08c3f85372f63346942f8fd02c7dbb82d3 100644 (file)
@@ -9,7 +9,7 @@ note: the lint level is defined here
    |
 LL | #![deny(keyword_idents)]
    |         ^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
@@ -18,7 +18,7 @@ error: `await` is a keyword in the 2018 edition
 LL |         pub struct await;
    |                    ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
@@ -27,7 +27,7 @@ error: `await` is a keyword in the 2018 edition
 LL | use outer_mod::await::await;
    |                ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
@@ -36,7 +36,7 @@ error: `await` is a keyword in the 2018 edition
 LL | use outer_mod::await::await;
    |                       ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
@@ -45,7 +45,7 @@ error: `await` is a keyword in the 2018 edition
 LL | struct Foo { await: () }
    |              ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
@@ -54,7 +54,7 @@ error: `await` is a keyword in the 2018 edition
 LL | impl Foo { fn await() {} }
    |               ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
@@ -63,7 +63,7 @@ error: `await` is a keyword in the 2018 edition
 LL | macro_rules! await {
    |              ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
@@ -72,7 +72,7 @@ error: `await` is a keyword in the 2018 edition
 LL |     await!();
    |     ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
@@ -81,7 +81,7 @@ error: `await` is a keyword in the 2018 edition
 LL |     match await { await => {} }
    |           ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
@@ -90,7 +90,7 @@ error: `await` is a keyword in the 2018 edition
 LL |     match await { await => {} }
    |                   ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: aborting due to 10 previous errors
index c58496c91f513061cb388700fbe15ae64760263c..117495e130f925193d46da47e47d4107177226d2 100644 (file)
@@ -6,22 +6,22 @@
 mod outer_mod {
     pub mod r#await {
 //~^ ERROR `await` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
         pub struct r#await;
 //~^ ERROR `await` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
     }
 }
 use outer_mod::r#await::r#await;
 //~^ ERROR `await` is a keyword
 //~| ERROR `await` is a keyword
-//~| WARN was previously accepted
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
+//~| WARN this is accepted in the current edition
 
 fn main() {
     match r#await { r#await => {} }
 //~^ ERROR `await` is a keyword
 //~| ERROR `await` is a keyword
-//~| WARN was previously accepted
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
+//~| WARN this is accepted in the current edition
 }
index a7543a14325fbecfc1f9a774382d128640b65157..b3c64895c6dd68f01f2eb5e7e2ceff20200e16f4 100644 (file)
@@ -6,22 +6,22 @@
 mod outer_mod {
     pub mod await {
 //~^ ERROR `await` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
         pub struct await;
 //~^ ERROR `await` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
     }
 }
 use outer_mod::await::await;
 //~^ ERROR `await` is a keyword
 //~| ERROR `await` is a keyword
-//~| WARN was previously accepted
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
+//~| WARN this is accepted in the current edition
 
 fn main() {
     match await { await => {} }
 //~^ ERROR `await` is a keyword
 //~| ERROR `await` is a keyword
-//~| WARN was previously accepted
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
+//~| WARN this is accepted in the current edition
 }
index 0c558eb12f089e7b62c1e4d0e354dbb46c99b79c..1c4c19ea45f72b5276d78ccdfd65995d5797a071 100644 (file)
@@ -9,7 +9,7 @@ note: the lint level is defined here
    |
 LL | #![deny(keyword_idents)]
    |         ^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
@@ -18,7 +18,7 @@ error: `await` is a keyword in the 2018 edition
 LL |         pub struct await;
    |                    ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
@@ -27,7 +27,7 @@ error: `await` is a keyword in the 2018 edition
 LL | use outer_mod::await::await;
    |                ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
@@ -36,7 +36,7 @@ error: `await` is a keyword in the 2018 edition
 LL | use outer_mod::await::await;
    |                       ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
@@ -45,7 +45,7 @@ error: `await` is a keyword in the 2018 edition
 LL |     match await { await => {} }
    |           ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
@@ -54,7 +54,7 @@ error: `await` is a keyword in the 2018 edition
 LL |     match await { await => {} }
    |                   ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: aborting due to 6 previous errors
index ad661fb2833fa08e7992ea0d4de9a6eff2372da0..ba97e135790c16a0ded828d8426afe0448f178c2 100644 (file)
@@ -5,7 +5,11 @@ LL |     foo()?;
    |     ^^^^^^ the `?` operator cannot be applied to type `impl Future`
    |
    = help: the trait `Try` is not implemented for `impl Future`
-   = note: required by `branch`
+note: required by `branch`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider `await`ing on the `Future`
    |
 LL |     foo().await?;
@@ -18,7 +22,11 @@ LL |     t?;
    |     ^^ the `?` operator cannot be applied to type `T`
    |
    = help: the trait `Try` is not implemented for `T`
-   = note: required by `branch`
+note: required by `branch`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider `await`ing on the `Future`
    |
 LL |     t.await?;
index e97d088cf3ed3d5a82897f0fa3727f05d63278ad..62a1f451a1c7ed1121e100ee8fb48bbe4741c4e9 100644 (file)
@@ -41,14 +41,14 @@ LL |     require_send(send_fut);
    |
    = 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 `[static generator@$DIR/issue-68112.rs:47:31: 47:36 {}]`
-   = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36 {}]>`
+   = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36]`
+   = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>`
    = note: required because it appears within the type `impl Future`
    = note: required because it appears within the type `impl Future`
    = note: required because it appears within the type `impl Future`
    = note: required because it appears within the type `{ResumeTy, impl Future, (), i32, Ready<i32>}`
-   = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6 {ResumeTy, impl Future, (), i32, Ready<i32>}]`
-   = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6 {ResumeTy, impl Future, (), i32, Ready<i32>}]>`
+   = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6]`
+   = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>`
    = note: required because it appears within the type `impl Future`
 
 error: aborting due to 3 previous errors
index fb1f8e4ffd251fed8cae966a820a0177bba95e5a..e20e2e8f6ba3848bc327b112c2f449d88b8548c3 100644 (file)
@@ -25,7 +25,11 @@ LL |     [1; ().await];
    |         ^^^^^^^^ `()` is not a future
    |
    = help: the trait `Future` is not implemented for `()`
-   = note: required by `poll`
+note: required by `poll`
+  --> $SRC_DIR/core/src/future/future.rs:LL:COL
+   |
+LL |     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/async-await/issue-84841.rs b/src/test/ui/async-await/issue-84841.rs
new file mode 100644 (file)
index 0000000..ba3a161
--- /dev/null
@@ -0,0 +1,16 @@
+// edition:2018
+
+fn main() {
+
+}
+
+async fn foo() {
+    // Adding an .await here avoids the ICE
+    test()?;
+    //~^ ERROR the `?` operator can only be applied to values that implement `Try`
+    //~| ERROR the `?` operator can only be used in an async function that returns
+}
+
+// Removing the const generic parameter here avoids the ICE
+async fn test<const N: usize>() {
+}
diff --git a/src/test/ui/async-await/issue-84841.stderr b/src/test/ui/async-await/issue-84841.stderr
new file mode 100644 (file)
index 0000000..e28ba74
--- /dev/null
@@ -0,0 +1,36 @@
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+  --> $DIR/issue-84841.rs:9:5
+   |
+LL |     test()?;
+   |     ^^^^^^^ the `?` operator cannot be applied to type `impl Future`
+   |
+   = help: the trait `Try` is not implemented for `impl Future`
+note: required by `branch`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/issue-84841.rs:9:11
+   |
+LL |   async fn foo() {
+   |  ________________-
+LL | |     // Adding an .await here avoids the ICE
+LL | |     test()?;
+   | |           ^ cannot use the `?` operator in an async function that returns `()`
+LL | |
+LL | |
+LL | | }
+   | |_- this function should return `Result` or `Option` to accept `?`
+   |
+   = help: the trait `FromResidual<_>` is not implemented for `()`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/async-await/issue-86507.rs b/src/test/ui/async-await/issue-86507.rs
new file mode 100644 (file)
index 0000000..317f031
--- /dev/null
@@ -0,0 +1,25 @@
+// edition:2018
+
+use ::core::pin::Pin;
+use ::core::future::Future;
+use ::core::marker::Send;
+
+trait Foo {
+    fn bar<'me, 'async_trait, T: Send>(x: &'me T)
+        -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
+        where 'me: 'async_trait;
+}
+
+impl Foo for () {
+    fn bar<'me, 'async_trait, T: Send>(x: &'me T)
+        -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
+        where 'me:'async_trait {
+            Box::pin( //~ ERROR future cannot be sent between threads safely
+                async move {
+                    let x = x;
+                }
+            )
+         }
+}
+
+fn main() { }
diff --git a/src/test/ui/async-await/issue-86507.stderr b/src/test/ui/async-await/issue-86507.stderr
new file mode 100644 (file)
index 0000000..51e8f61
--- /dev/null
@@ -0,0 +1,23 @@
+error: future cannot be sent between threads safely
+  --> $DIR/issue-86507.rs:17:13
+   |
+LL | /             Box::pin(
+LL | |                 async move {
+LL | |                     let x = x;
+LL | |                 }
+LL | |             )
+   | |_____________^ future created by async block is not `Send`
+   |
+note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
+  --> $DIR/issue-86507.rs:19:29
+   |
+LL |                     let x = x;
+   |                             ^ has type `&T` which is not `Send`, because `T` is not `Sync`
+   = note: required for the cast to the object type `dyn Future<Output = ()> + Send`
+help: consider further restricting type parameter `T`
+   |
+LL |         where 'me:'async_trait, T: std::marker::Sync {
+   |                               ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index c879a65bc7f77008f553ebdfb5155454e8e9b992..946b8d19e6936a11e162723db023fbe1694f0c04 100644 (file)
@@ -34,7 +34,11 @@ LL |     (|_| 2333).await;
    |     ^^^^^^^^^^^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future
    |
    = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]`
-   = note: required by `poll`
+note: required by `poll`
+  --> $SRC_DIR/core/src/future/future.rs:LL:COL
+   |
+LL |     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
index aee2ae0e2e4a89470a735190b12eda6406418c2c..ea5c90a81d4f9ae7503958197b6e334a2ea3360a 100644 (file)
@@ -14,8 +14,8 @@ LL | pub async fn run() {
    |
    = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`
    = note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3> {ResumeTy, Arc<Mutex<()>>, &'r Mutex<()>, Result<MutexGuard<'s, ()>, PoisonError<MutexGuard<'t0, ()>>>, &'t1 MutexGuard<'t2, ()>, MutexGuard<'t3, ()>, (), impl Future}`
-   = note: required because it appears within the type `[static generator@run::{closure#0} for<'r, 's, 't0, 't1, 't2, 't3> {ResumeTy, Arc<Mutex<()>>, &'r Mutex<()>, Result<MutexGuard<'s, ()>, PoisonError<MutexGuard<'t0, ()>>>, &'t1 MutexGuard<'t2, ()>, MutexGuard<'t3, ()>, (), impl Future}]`
-   = note: required because it appears within the type `from_generator::GenFuture<[static generator@run::{closure#0} for<'r, 's, 't0, 't1, 't2, 't3> {ResumeTy, Arc<Mutex<()>>, &'r Mutex<()>, Result<MutexGuard<'s, ()>, PoisonError<MutexGuard<'t0, ()>>>, &'t1 MutexGuard<'t2, ()>, MutexGuard<'t3, ()>, (), impl Future}]>`
+   = note: required because it appears within the type `[static generator@run::{closure#0}]`
+   = note: required because it appears within the type `from_generator::GenFuture<[static generator@run::{closure#0}]>`
    = note: required because it appears within the type `impl Future`
    = note: required because it appears within the type `impl Future`
 
index eed90772d29e39e4485f362f2b39082a3c9e1d88..b6841da1f0ba9b0690a7b0c34f8a34faf66efe14 100644 (file)
@@ -1,15 +1,11 @@
 error: lifetime may not live long enough
-  --> $DIR/ret-impl-trait-one.rs:10:80
+  --> $DIR/ret-impl-trait-one.rs:10:65
    |
-LL |   async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
-   |  ________________________________--__--__________________________________________^
-   | |                                |   |
-   | |                                |   lifetime `'b` defined here
-   | |                                lifetime `'a` defined here
-LL | |
-LL | |     (a, b)
-LL | | }
-   | |_^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+   |                                --  --                           ^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a`
+   |                                |   |
+   |                                |   lifetime `'b` defined here
+   |                                lifetime `'a` defined here
    |
    = help: consider adding the following bound: `'b: 'a`
 
index c4d21de8aaf75b4bfc6f894f9d3a9133e5326e1a..8c581ff2229fc00889d0b9684cd75de5b2750938 100644 (file)
@@ -10,7 +10,11 @@ note: required because it appears within the type `Sleep`
    |
 LL | struct Sleep(std::marker::PhantomPinned);
    |        ^^^^^
-   = note: required by `Pin::<P>::new`
+note: required by `Pin::<P>::new`
+  --> $SRC_DIR/core/src/pin.rs:LL:COL
+   |
+LL |     pub const fn new(pointer: P) -> Pin<P> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index a3f122a466361fc4e3dd033c6f002a739ce0d92d..e8bb4aca9a9c9d5b92174d6cd4eb8cdb1228eb54 100644 (file)
@@ -11,7 +11,11 @@ LL | |     }
    | |_____- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-in-async.rs:17:10
@@ -26,7 +30,11 @@ LL | |     };
    | |_____- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-in-async.rs:26:6
@@ -41,7 +49,11 @@ LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
index b4f523936a0b0a9ccf4f36555a9a1a200ac57706..97bf225f0cc733b9803844bc583f8ea6134aaeb1 100644 (file)
@@ -2,8 +2,9 @@
 
 macro_rules! pass_nonterminal {
     ($n:expr) => {
-        #[repr(align($n))] //~ ERROR expected unsuffixed literal or identifier, found `n!()`
-                           //~| ERROR unrecognized representation hint
+        #[repr(align($n))]
+        //~^ ERROR expected unsuffixed literal or identifier, found `n!()`
+        //~| ERROR incorrect `repr(align)` attribute format
         struct S;
     };
 }
index e6a36b68d47c34843de0287b2ddced8673bbc86c..9bf36f3c58e8120401905cd8cbce8131aefd22a2 100644 (file)
@@ -9,7 +9,7 @@ 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[E0552]: unrecognized representation hint
+error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
   --> $DIR/nonterminal-expansion.rs:5:16
    |
 LL |         #[repr(align($n))]
@@ -22,4 +22,4 @@ LL | pass_nonterminal!(n!());
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0552`.
+For more information about this error, try `rustc --explain E0693`.
index d9ca7ddc7cab731c95b4949ad2dc8f3a4c54462f..233ddbbe11784694a672bd1c1575638e7f353141 100644 (file)
 //
 // My heart aches in sorrow, for I know I am defeated. Let this be a warning
 // to all those who come after. Here stands the bastion of the Turbofish.
+//
+// RIP Anna Harren, Guardian Angel of the Hallowed Turbofish. <3
 
 // See https://github.com/rust-lang/rust/pull/53562
 // and https://github.com/rust-lang/rfcs/pull/2527
+// and https://twitter.com/garblefart/status/1393236602856611843
 // for context.
 
 fn main() {
index fa967ccb9d096167c49afb3e6ad6cf2a27759e9f..ed71b99da0f52dcae1ba8a26e5052ead06c1c9f6 100644 (file)
@@ -14,11 +14,6 @@ error[E0277]: `for<'r> fn(&'r i32) -> &'r i32 {foo}` doesn't implement `Debug`
    |
 LL |     assert_eq!(foo, y);
    |     ^^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   | 
-  ::: $SRC_DIR/core/src/panicking.rs:LL:COL
-   |
-LL |     T: fmt::Debug + ?Sized,
-   |        ---------- required by this bound in `core::panicking::assert_failed`
    |
    = help: the trait `Debug` is not implemented for `for<'r> fn(&'r i32) -> &'r i32 {foo}`
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
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;
diff --git a/src/test/ui/borrowck/fsu-moves-and-copies.rs b/src/test/ui/borrowck/fsu-moves-and-copies.rs
new file mode 100644 (file)
index 0000000..6a0b4ed
--- /dev/null
@@ -0,0 +1,95 @@
+// run-pass
+
+#![allow(non_camel_case_types)]
+#![allow(stable_features)]
+// Issue 4691: Ensure that functional-struct-updates operates
+// correctly and moves rather than copy when appropriate.
+
+#![feature(box_syntax, core)]
+
+struct ncint { v: isize }
+fn ncint(v: isize) -> ncint { ncint { v: v } }
+
+struct NoFoo { copied: isize, nocopy: ncint, }
+impl NoFoo {
+    fn new(x:isize,y:isize) -> NoFoo { NoFoo { copied: x, nocopy: ncint(y) } }
+}
+
+struct MoveFoo { copied: isize, moved: Box<isize>, }
+impl MoveFoo {
+    fn new(x:isize,y:isize) -> MoveFoo { MoveFoo { copied: x, moved: box y } }
+}
+
+struct DropNoFoo { inner: NoFoo }
+impl DropNoFoo {
+    fn new(x:isize,y:isize) -> DropNoFoo { DropNoFoo { inner: NoFoo::new(x,y) } }
+}
+impl Drop for DropNoFoo { fn drop(&mut self) { } }
+
+struct DropMoveFoo { inner: MoveFoo }
+impl DropMoveFoo {
+    fn new(x:isize,y:isize) -> DropMoveFoo { DropMoveFoo { inner: MoveFoo::new(x,y) } }
+}
+impl Drop for DropMoveFoo { fn drop(&mut self) { } }
+
+
+fn test0() {
+    // just copy implicitly copyable fields from `f`, no moves
+    // (and thus it is okay that these are Drop; compare against
+    // test ui/borrowck/borrowck-struct-update-with-dtor.rs).
+
+    // Case 1: Nocopyable
+    let f = DropNoFoo::new(1, 2);
+    let b = DropNoFoo { inner: NoFoo { nocopy: ncint(3), ..f.inner }};
+    let c = DropNoFoo { inner: NoFoo { nocopy: ncint(4), ..f.inner }};
+    assert_eq!(f.inner.copied,    1);
+    assert_eq!(f.inner.nocopy.v, 2);
+
+    assert_eq!(b.inner.copied,    1);
+    assert_eq!(b.inner.nocopy.v, 3);
+
+    assert_eq!(c.inner.copied,    1);
+    assert_eq!(c.inner.nocopy.v, 4);
+
+    // Case 2: Owned
+    let f = DropMoveFoo::new(5, 6);
+    let b = DropMoveFoo { inner: MoveFoo { moved: box 7, ..f.inner }};
+    let c = DropMoveFoo { inner: MoveFoo { moved: box 8, ..f.inner }};
+    assert_eq!(f.inner.copied,    5);
+    assert_eq!(*f.inner.moved,    6);
+
+    assert_eq!(b.inner.copied,    5);
+    assert_eq!(*b.inner.moved,    7);
+
+    assert_eq!(c.inner.copied,    5);
+    assert_eq!(*c.inner.moved,    8);
+}
+
+fn test1() {
+    // copying move-by-default fields from `f`, so it moves:
+    let f = MoveFoo::new(11, 12);
+
+    let b = MoveFoo {moved: box 13, ..f};
+    let c = MoveFoo {copied: 14, ..f};
+    assert_eq!(b.copied,    11);
+    assert_eq!(*b.moved,    13);
+    assert_eq!(c.copied,    14);
+    assert_eq!(*c.moved,    12);
+}
+
+fn test2() {
+    // move non-copyable field
+    let f = NoFoo::new(21, 22);
+    let b = NoFoo {nocopy: ncint(23), ..f};
+    let c = NoFoo {copied: 24, ..f};
+    assert_eq!(b.copied,    21);
+    assert_eq!(b.nocopy.v, 23);
+    assert_eq!(c.copied,    24);
+    assert_eq!(c.nocopy.v, 22);
+}
+
+pub fn main() {
+    test0();
+    test1();
+    test2();
+}
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() {
diff --git a/src/test/ui/borrowck/issue-83760.rs b/src/test/ui/borrowck/issue-83760.rs
new file mode 100644 (file)
index 0000000..e25b4f7
--- /dev/null
@@ -0,0 +1,40 @@
+struct Struct;
+
+fn test1() {
+    let mut val = Some(Struct);
+    while let Some(foo) = val { //~ ERROR use of moved value
+        if true {
+            val = None;
+        } else {
+
+        }
+    }
+}
+
+fn test2() {
+    let mut foo = Some(Struct);
+    let _x = foo.unwrap();
+    if true {
+        foo = Some(Struct);
+    } else {
+    }
+    let _y = foo; //~ ERROR use of moved value: `foo`
+}
+
+fn test3() {
+    let mut foo = Some(Struct);
+    let _x = foo.unwrap();
+    if true {
+        foo = Some(Struct);
+    } else if true {
+        foo = Some(Struct);
+    } else if true {
+        foo = Some(Struct);
+    } else if true {
+        foo = Some(Struct);
+    } else {
+    }
+    let _y = foo; //~ ERROR use of moved value: `foo`
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-83760.stderr b/src/test/ui/borrowck/issue-83760.stderr
new file mode 100644 (file)
index 0000000..beeda56
--- /dev/null
@@ -0,0 +1,62 @@
+error[E0382]: use of moved value
+  --> $DIR/issue-83760.rs:5:20
+   |
+LL |     while let Some(foo) = val {
+   |                    ^^^ value moved here, in previous iteration of loop
+LL |         if true {
+LL |             val = None;
+   |             ---------- this reinitialization might get skipped
+   |
+   = note: move occurs because value has type `Struct`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `foo`
+  --> $DIR/issue-83760.rs:21:14
+   |
+LL |     let mut foo = Some(Struct);
+   |         ------- move occurs because `foo` has type `Option<Struct>`, which does not implement the `Copy` trait
+LL |     let _x = foo.unwrap();
+   |                  -------- `foo` moved due to this method call
+LL |     if true {
+LL |         foo = Some(Struct);
+   |         ------------------ this reinitialization might get skipped
+...
+LL |     let _y = foo;
+   |              ^^^ value used here after move
+   |
+note: this function takes ownership of the receiver `self`, which moves `foo`
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+   |
+LL |     pub const fn unwrap(self) -> T {
+   |                         ^^^^
+
+error[E0382]: use of moved value: `foo`
+  --> $DIR/issue-83760.rs:37:14
+   |
+LL |     let mut foo = Some(Struct);
+   |         ------- move occurs because `foo` has type `Option<Struct>`, which does not implement the `Copy` trait
+LL |     let _x = foo.unwrap();
+   |                  -------- `foo` moved due to this method call
+...
+LL |     let _y = foo;
+   |              ^^^ value used here after move
+   |
+note: these 3 reinitializations and 1 other might get skipped
+  --> $DIR/issue-83760.rs:30:9
+   |
+LL |         foo = Some(Struct);
+   |         ^^^^^^^^^^^^^^^^^^
+LL |     } else if true {
+LL |         foo = Some(Struct);
+   |         ^^^^^^^^^^^^^^^^^^
+LL |     } else if true {
+LL |         foo = Some(Struct);
+   |         ^^^^^^^^^^^^^^^^^^
+note: this function takes ownership of the receiver `self`, which moves `foo`
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+   |
+LL |     pub const fn unwrap(self) -> T {
+   |                         ^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/issue-85581.rs b/src/test/ui/borrowck/issue-85581.rs
new file mode 100644 (file)
index 0000000..ccc120c
--- /dev/null
@@ -0,0 +1,15 @@
+// Regression test of #85581.
+// Checks not to suggest to add `;` when the second mutable borrow
+// is in the first's scope.
+
+use std::collections::BinaryHeap;
+
+fn foo(heap: &mut BinaryHeap<i32>) {
+    match heap.peek_mut() {
+        Some(_) => { heap.pop(); },
+        //~^ ERROR: cannot borrow `*heap` as mutable more than once at a time
+        None => (),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-85581.stderr b/src/test/ui/borrowck/issue-85581.stderr
new file mode 100644 (file)
index 0000000..29c0429
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0499]: cannot borrow `*heap` as mutable more than once at a time
+  --> $DIR/issue-85581.rs:9:22
+   |
+LL |     match heap.peek_mut() {
+   |           ---------------
+   |           |
+   |           first mutable borrow occurs here
+   |           a temporary with access to the first borrow is created here ...
+LL |         Some(_) => { heap.pop(); },
+   |                      ^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option<PeekMut<'_, i32>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
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 f7392bfeaab36414997d0ee85ee6da47a2621d9c..50248a55838f2a5e993b121daa4702a34fc58c44 100644 (file)
@@ -1,8 +1,8 @@
 // revisions: nll_target
 
-// The following revisions are disabled due to missing support from two-phase beyond autorefs
+// The nll_beyond revision is disabled due to missing support from two-phase beyond autorefs
 //[nll_beyond]compile-flags: -Z borrowck=mir -Z two-phase-beyond-autoref
-//[nll_beyond] should-fail
+//[nll_beyond]should-fail
 
 //[nll_target]compile-flags: -Z borrowck=mir
 
index a3177903162aa70394d929157a6d8c3351ecf845..78f62592960ffe844f4c9bb6d5384e09e970bb29 100644 (file)
@@ -4,7 +4,6 @@ error[E0277]: `impl Sized` doesn't implement `Debug`
 LL |     println!("{:?}", t);
    |                      ^ `impl Sized` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required by `std::fmt::Debug::fmt`
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider further restricting this bound
    |
@@ -17,7 +16,6 @@ error[E0277]: `T` doesn't implement `Debug`
 LL |     println!("{:?}", t);
    |                      ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required by `std::fmt::Debug::fmt`
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
    |
@@ -30,7 +28,6 @@ error[E0277]: `T` doesn't implement `Debug`
 LL |     println!("{:?}", t);
    |                      ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required by `std::fmt::Debug::fmt`
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider further restricting this bound
    |
@@ -43,7 +40,6 @@ error[E0277]: `Y` doesn't implement `Debug`
 LL |     println!("{:?} {:?}", x, y);
    |                              ^ `Y` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required by `std::fmt::Debug::fmt`
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider further restricting type parameter `Y`
    |
@@ -56,7 +52,6 @@ error[E0277]: `X` doesn't implement `Debug`
 LL |     println!("{:?}", x);
    |                      ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required by `std::fmt::Debug::fmt`
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider further restricting this bound
    |
@@ -69,7 +64,6 @@ error[E0277]: `X` doesn't implement `Debug`
 LL |     println!("{:?}", x);
    |                      ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required by `std::fmt::Debug::fmt`
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider further restricting type parameter `X`
    |
index 7a5ba16461f76001b598fd91fd0a6023a388add2..5e3b43a47eeeef69952049d75d122a9489cb600c 100644 (file)
@@ -5,7 +5,11 @@ LL |     let _ = Box::into_boxed_slice(boxed_slice);
    |                                   ^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
-   = note: required by `Box::<T, A>::into_boxed_slice`
+note: required by `Box::<T, A>::into_boxed_slice`
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+   |
+LL |     pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
   --> $DIR/into-boxed-slice-fail.rs:7:13
@@ -23,7 +27,11 @@ LL |     let _ = Box::into_boxed_slice(boxed_trait);
    |                                   ^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `dyn Debug`
-   = note: required by `Box::<T, A>::into_boxed_slice`
+note: required by `Box::<T, A>::into_boxed_slice`
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+   |
+LL |     pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
   --> $DIR/into-boxed-slice-fail.rs:11:13
diff --git a/src/test/ui/c-variadic/issue-86053-1.rs b/src/test/ui/c-variadic/issue-86053-1.rs
new file mode 100644 (file)
index 0000000..b30548e
--- /dev/null
@@ -0,0 +1,12 @@
+// Regression test for the ICE described in issue #86053.
+// error-pattern:unexpected `self` parameter in function
+// error-pattern:`...` must be the last argument of a C-variadic function
+// error-pattern:cannot find type `F` in this scope
+// error-pattern:in type `&'a &'b usize`, reference has a longer lifetime than the data it references
+
+#![feature(c_variadic)]
+#![crate_type="lib"]
+
+fn ordering4 < 'a , 'b     > ( a :            ,   self , self ,   self ,
+    self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
+}
diff --git a/src/test/ui/c-variadic/issue-86053-1.stderr b/src/test/ui/c-variadic/issue-86053-1.stderr
new file mode 100644 (file)
index 0000000..ec7ee74
--- /dev/null
@@ -0,0 +1,101 @@
+error: expected type, found `,`
+  --> $DIR/issue-86053-1.rs:10:47
+   |
+LL | fn ordering4 < 'a , 'b     > ( a :            ,   self , self ,   self ,
+   |                                               ^ expected type
+
+error: unexpected `self` parameter in function
+  --> $DIR/issue-86053-1.rs:10:51
+   |
+LL | fn ordering4 < 'a , 'b     > ( a :            ,   self , self ,   self ,
+   |                                                   ^^^^ must be the first parameter of an associated function
+
+error: unexpected `self` parameter in function
+  --> $DIR/issue-86053-1.rs:10:58
+   |
+LL | fn ordering4 < 'a , 'b     > ( a :            ,   self , self ,   self ,
+   |                                                          ^^^^ must be the first parameter of an associated function
+
+error: unexpected `self` parameter in function
+  --> $DIR/issue-86053-1.rs:10:67
+   |
+LL | fn ordering4 < 'a , 'b     > ( a :            ,   self , self ,   self ,
+   |                                                                   ^^^^ must be the first parameter of an associated function
+
+error: unexpected `self` parameter in function
+  --> $DIR/issue-86053-1.rs:11:5
+   |
+LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
+   |     ^^^^ must be the first parameter of an associated function
+
+error: unexpected `self` parameter in function
+  --> $DIR/issue-86053-1.rs:11:20
+   |
+LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
+   |                    ^^^^ must be the first parameter of an associated function
+
+error: unexpected `self` parameter in function
+  --> $DIR/issue-86053-1.rs:11:29
+   |
+LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
+   |                             ^^^^ must be the first parameter of an associated function
+
+error: `...` must be the last argument of a C-variadic function
+  --> $DIR/issue-86053-1.rs:11:12
+   |
+LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
+   |            ^^^^
+
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
+  --> $DIR/issue-86053-1.rs:11:12
+   |
+LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
+   |            ^^^^
+
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
+  --> $DIR/issue-86053-1.rs:11:36
+   |
+LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
+   |                                    ^^^^
+
+error[E0412]: cannot find type `F` in this scope
+  --> $DIR/issue-86053-1.rs:11:48
+   |
+LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
+   |                                                ^
+   | 
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   | ------------------------------- similarly named trait `Fn` defined here
+   |
+help: a trait with a similar name exists
+   |
+LL |     self , ... ,   self ,   self , ... ) where Fn : FnOnce ( & 'a & 'b usize ) {
+   |                                                ^^
+help: you might be missing a type parameter
+   |
+LL | fn ordering4 < 'a , 'b, F     > ( a :            ,   self , self ,   self ,
+   |                       ^^^
+
+error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references
+  --> $DIR/issue-86053-1.rs:11:52
+   |
+LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime `'a` as defined on the function body at 10:16
+  --> $DIR/issue-86053-1.rs:10:16
+   |
+LL | fn ordering4 < 'a , 'b     > ( a :            ,   self , self ,   self ,
+   |                ^^
+note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 10:21
+  --> $DIR/issue-86053-1.rs:10:21
+   |
+LL | fn ordering4 < 'a , 'b     > ( a :            ,   self , self ,   self ,
+   |                     ^^
+
+error: aborting due to 12 previous errors
+
+Some errors have detailed explanations: E0412, E0491.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/c-variadic/issue-86053-2.rs b/src/test/ui/c-variadic/issue-86053-2.rs
new file mode 100644 (file)
index 0000000..c545831
--- /dev/null
@@ -0,0 +1,11 @@
+// Regression test for the ICE caused by the example in
+// https://github.com/rust-lang/rust/issues/86053#issuecomment-855672258
+
+#![feature(c_variadic)]
+
+trait H<T> {}
+
+unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {}
+//~^ ERROR: in type `&'static &'a ()`, reference has a longer lifetime than the data it references [E0491]
+
+fn main() {}
diff --git a/src/test/ui/c-variadic/issue-86053-2.stderr b/src/test/ui/c-variadic/issue-86053-2.stderr
new file mode 100644 (file)
index 0000000..4fc5e63
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0491]: in type `&'static &'a ()`, reference has a longer lifetime than the data it references
+  --> $DIR/issue-86053-2.rs:8:39
+   |
+LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {}
+   |                                       ^^^^^^^^^^^^^^^^^^
+   |
+   = note: the pointer is valid for the static lifetime
+note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 8:32
+  --> $DIR/issue-86053-2.rs:8:32
+   |
+LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {}
+   |                                ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
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`.
index 9fa2255e1b34824455fb24a7ecf9c75b52926c5c..f5747eb8b96669cb328b6faa1399a6954907a04f 100644 (file)
@@ -1,12 +1,6 @@
 // run-pass
 
-// Remove this file when `std::raw` is removed.
-// The replacement pointer metadata APIs are tested in library/core/tests/ptr.rs
-#![allow(deprecated)]
-#![feature(raw)]
-
-use std::mem;
-use std::raw;
+#![feature(ptr_metadata)]
 
 trait Foo {
     fn foo(&self) {}
@@ -31,13 +25,10 @@ fn main() {
 
     // And conversion to a void pointer/address for trait objects too.
     let a: *mut dyn Foo = &mut Bar;
-    let b = a as *mut ();
+    let b = a as *mut () as usize;
     let c = a as *const () as usize;
-    let d = unsafe {
-        let r: raw::TraitObject = mem::transmute(a);
-        r.data
-    };
+    let d = a.to_raw_parts().0 as usize;
 
     assert_eq!(b, d);
-    assert_eq!(c, d as usize);
+    assert_eq!(c, d);
 }
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`.
diff --git a/src/test/ui/cfg/cfg-target-abi.rs b/src/test/ui/cfg/cfg-target-abi.rs
new file mode 100644 (file)
index 0000000..acc570f
--- /dev/null
@@ -0,0 +1,10 @@
+// run-pass
+#![feature(cfg_target_abi)]
+
+#[cfg(target_abi = "eabihf")]
+pub fn main() {
+}
+
+#[cfg(not(target_abi = "eabihf"))]
+pub fn main() {
+}
index 3cd60369454930eb138acded147f096dcdd24919..ebd885a7d323f641baea3fd84a6abcd9602a1798 100644 (file)
@@ -1,15 +1,17 @@
 error[E0277]: the trait bound `{float}: Foo` is not satisfied
   --> $DIR/type_wf.rs:18:13
    |
-LL | struct S<T: Foo> {
-   | ---------------- required by `S`
-...
 LL |     let s = S {
    |             ^ the trait `Foo` is not implemented for `{float}`
    |
    = help: the following implementations were found:
              <Option<T> as Foo>
              <i32 as Foo>
+note: required by `S`
+  --> $DIR/type_wf.rs:6:1
+   |
+LL | struct S<T: Foo> {
+   | ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 131af6a10c8985632c36ca15cebb5c6da39eca10..7a4b21f02236568626f374e5d18b4f4354bfcc24 100644 (file)
@@ -1,7 +1,4 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| `#[warn(incomplete_features)]` on by default
-//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
 #![feature(rustc_attrs)]
 
 // Ensure that capture analysis results in arrays being completely captured.
index 2a350f303319277bb4620c89e5fe432161f25374..69ec53447b8a6bbf3043f4504b5e7d6b96fa1e3d 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/arrays-completely-captured.rs:11:17
+  --> $DIR/arrays-completely-captured.rs:8:17
    |
 LL |     let mut c = #[rustc_capture_analysis]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ LL |     let mut 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/arrays-completely-captured.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/arrays-completely-captured.rs:14:5
+  --> $DIR/arrays-completely-captured.rs:11:5
    |
 LL | /     || {
 LL | |
@@ -29,13 +20,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing m[] -> MutBorrow
-  --> $DIR/arrays-completely-captured.rs:17:9
+  --> $DIR/arrays-completely-captured.rs:14:9
    |
 LL |         m[0] += 10;
    |         ^
 
 error: Min Capture analysis includes:
-  --> $DIR/arrays-completely-captured.rs:14:5
+  --> $DIR/arrays-completely-captured.rs:11:5
    |
 LL | /     || {
 LL | |
@@ -47,11 +38,11 @@ LL | |     };
    | |_____^
    |
 note: Min Capture m[] -> MutBorrow
-  --> $DIR/arrays-completely-captured.rs:17:9
+  --> $DIR/arrays-completely-captured.rs:14:9
    |
 LL |         m[0] += 10;
    |         ^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 27c8fb1363f17a03144b1707cece124c012c1769..d8d3bbee200db67df8cb258fec03b2097f227601 100644 (file)
@@ -1,11 +1,7 @@
+// edition:2021
+
 // Test that we handle derferences properly when only some of the captures are being moved with
 // `capture_disjoint_fields` enabled.
-
-
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
 #![feature(rustc_attrs)]
 
 #[derive(Debug, Default)]
@@ -26,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 944e4c40a78ef6707a21e7b35bf1f11544235829..097462253aae73f0d3d37ac1f03a6b86c5cc5b2b 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/by_value.rs:22:13
+  --> $DIR/by_value.rs:18:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/by_value.rs:5:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/by_value.rs:25:5
+  --> $DIR/by_value.rs:21:5
    |
 LL | /     || {
 LL | |
@@ -28,24 +19,19 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
-  --> $DIR/by_value.rs:28:17
-   |
-LL |         let p = t.0.0;
-   |                 ^^^^^
-note: Capturing t[(0, 0)] -> ByValue
-  --> $DIR/by_value.rs:28:17
+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:32:29
+  --> $DIR/by_value.rs:27:29
    |
 LL |         println!("{} {:?}", t.1, p);
    |                             ^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/by_value.rs:25:5
+  --> $DIR/by_value.rs:21:5
    |
 LL | /     || {
 LL | |
@@ -57,16 +43,16 @@ LL | |     };
    | |_____^
    |
 note: Min Capture t[(0, 0)] -> ByValue
-  --> $DIR/by_value.rs:28:17
+  --> $DIR/by_value.rs:24:17
    |
 LL |         let p = t.0.0;
    |                 ^^^^^
 note: Min Capture t[(1, 0)] -> ImmBorrow
-  --> $DIR/by_value.rs:32:29
+  --> $DIR/by_value.rs:27:29
    |
 LL |         println!("{} {:?}", t.1, p);
    |                             ^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 4368c830e1c612b8162e5780bd544b462b1d294a..dc53b31768ec5bcb6fa01253b103c0c30db37e93 100644 (file)
@@ -1,7 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
+
 #![feature(rustc_attrs)]
 
 #[derive(Debug)]
index 09255343af0e8bc3fa95efb0a1b0f281ce76b657..fceafb9c84eeb10a841b65a8533e343392f7b5a3 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/capture-analysis-1.rs:17:13
+  --> $DIR/capture-analysis-1.rs:15:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/capture-analysis-1.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/capture-analysis-1.rs:20:5
+  --> $DIR/capture-analysis-1.rs:18:5
    |
 LL | /     || {
 LL | |
@@ -29,28 +20,28 @@ LL | |     };
    | |_____^
    |
 note: Capturing p[] -> ImmBorrow
-  --> $DIR/capture-analysis-1.rs:23:26
+  --> $DIR/capture-analysis-1.rs:21:26
    |
 LL |         println!("{:?}", p);
    |                          ^
 note: Capturing p[(0, 0)] -> ImmBorrow
-  --> $DIR/capture-analysis-1.rs:26:26
+  --> $DIR/capture-analysis-1.rs:24:26
    |
 LL |         println!("{:?}", p.x);
    |                          ^^^
 note: Capturing q[(0, 0)] -> ImmBorrow
-  --> $DIR/capture-analysis-1.rs:29:26
+  --> $DIR/capture-analysis-1.rs:27:26
    |
 LL |         println!("{:?}", q.x);
    |                          ^^^
 note: Capturing q[] -> ImmBorrow
-  --> $DIR/capture-analysis-1.rs:31:26
+  --> $DIR/capture-analysis-1.rs:29:26
    |
 LL |         println!("{:?}", q);
    |                          ^
 
 error: Min Capture analysis includes:
-  --> $DIR/capture-analysis-1.rs:20:5
+  --> $DIR/capture-analysis-1.rs:18:5
    |
 LL | /     || {
 LL | |
@@ -62,16 +53,16 @@ LL | |     };
    | |_____^
    |
 note: Min Capture p[] -> ImmBorrow
-  --> $DIR/capture-analysis-1.rs:23:26
+  --> $DIR/capture-analysis-1.rs:21:26
    |
 LL |         println!("{:?}", p);
    |                          ^
 note: Min Capture q[] -> ImmBorrow
-  --> $DIR/capture-analysis-1.rs:31:26
+  --> $DIR/capture-analysis-1.rs:29:26
    |
 LL |         println!("{:?}", q);
    |                          ^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index ab7fce6a43099eb887dc713b969e69b0c12c295c..99d12f8d8f1dbf37ee19c2c5d93f7fb0ab3173d7 100644 (file)
@@ -1,7 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
+
 #![feature(rustc_attrs)]
 
 #[derive(Debug)]
index 0e48d6b300b7252f403447681780dc26b0101842..cb44ca2665293bbaa6a16e6eb51e3a4919dff107 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/capture-analysis-2.rs:16:13
+  --> $DIR/capture-analysis-2.rs:14:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/capture-analysis-2.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/capture-analysis-2.rs:19:5
+  --> $DIR/capture-analysis-2.rs:17:5
    |
 LL | /     || {
 LL | |
@@ -29,18 +20,18 @@ LL | |     };
    | |_____^
    |
 note: Capturing p[(0, 0)] -> ByValue
-  --> $DIR/capture-analysis-2.rs:22:18
+  --> $DIR/capture-analysis-2.rs:20:18
    |
 LL |         let _x = p.x;
    |                  ^^^
 note: Capturing p[] -> ImmBorrow
-  --> $DIR/capture-analysis-2.rs:25:26
+  --> $DIR/capture-analysis-2.rs:23:26
    |
 LL |         println!("{:?}", p);
    |                          ^
 
 error: Min Capture analysis includes:
-  --> $DIR/capture-analysis-2.rs:19:5
+  --> $DIR/capture-analysis-2.rs:17:5
    |
 LL | /     || {
 LL | |
@@ -52,7 +43,7 @@ LL | |     };
    | |_____^
    |
 note: Min Capture p[] -> ByValue
-  --> $DIR/capture-analysis-2.rs:22:18
+  --> $DIR/capture-analysis-2.rs:20:18
    |
 LL |         let _x = p.x;
    |                  ^^^ p[] captured as ByValue here
@@ -60,6 +51,6 @@ LL |         let _x = p.x;
 LL |         println!("{:?}", p);
    |                          ^ p[] used here
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 817ade899e2a0bc290e2f76fa65e368a85cc3479..3f337097dbd2fb70ed33cc1091f3748ba0be81c4 100644 (file)
@@ -1,7 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
+
 #![feature(rustc_attrs)]
 
 #[derive(Debug)]
index 263e9ca56ebf6e840fe97cf4d83d29d1490c2348..71e7bdc354fb2c2de771adfbf71ecb1560bf5e63 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/capture-analysis-3.rs:21:13
+  --> $DIR/capture-analysis-3.rs:19:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/capture-analysis-3.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/capture-analysis-3.rs:24:5
+  --> $DIR/capture-analysis-3.rs:22:5
    |
 LL | /     || {
 LL | |
@@ -29,18 +20,18 @@ LL | |     };
    | |_____^
    |
 note: Capturing a[(0, 0),(0, 0)] -> ByValue
-  --> $DIR/capture-analysis-3.rs:27:18
+  --> $DIR/capture-analysis-3.rs:25:18
    |
 LL |         let _x = a.b.c;
    |                  ^^^^^
 note: Capturing a[(0, 0)] -> ImmBorrow
-  --> $DIR/capture-analysis-3.rs:30:26
+  --> $DIR/capture-analysis-3.rs:28:26
    |
 LL |         println!("{:?}", a.b);
    |                          ^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/capture-analysis-3.rs:24:5
+  --> $DIR/capture-analysis-3.rs:22:5
    |
 LL | /     || {
 LL | |
@@ -52,7 +43,7 @@ LL | |     };
    | |_____^
    |
 note: Min Capture a[(0, 0)] -> ByValue
-  --> $DIR/capture-analysis-3.rs:27:18
+  --> $DIR/capture-analysis-3.rs:25:18
    |
 LL |         let _x = a.b.c;
    |                  ^^^^^ a[(0, 0)] captured as ByValue here
@@ -60,6 +51,6 @@ LL |         let _x = a.b.c;
 LL |         println!("{:?}", a.b);
    |                          ^^^ a[(0, 0)] used here
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index e8401299b30ada6f0f4b0fbdaca5694780f5430d..bc46ec997360bba5c117742bd97b8d5de320f98c 100644 (file)
@@ -1,7 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
+
 #![feature(rustc_attrs)]
 
 #[derive(Debug)]
index f4605c1d51b760225a032691c9bdc1e0cc0a1146..7e6e625bc7d489f5ac5e0d26a1aee1c118fab8de 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/capture-analysis-4.rs:21:13
+  --> $DIR/capture-analysis-4.rs:19:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/capture-analysis-4.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/capture-analysis-4.rs:24:5
+  --> $DIR/capture-analysis-4.rs:22:5
    |
 LL | /     || {
 LL | |
@@ -29,18 +20,18 @@ LL | |     };
    | |_____^
    |
 note: Capturing a[(0, 0)] -> ByValue
-  --> $DIR/capture-analysis-4.rs:27:18
+  --> $DIR/capture-analysis-4.rs:25:18
    |
 LL |         let _x = a.b;
    |                  ^^^
 note: Capturing a[(0, 0),(0, 0)] -> ImmBorrow
-  --> $DIR/capture-analysis-4.rs:30:26
+  --> $DIR/capture-analysis-4.rs:28:26
    |
 LL |         println!("{:?}", a.b.c);
    |                          ^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/capture-analysis-4.rs:24:5
+  --> $DIR/capture-analysis-4.rs:22:5
    |
 LL | /     || {
 LL | |
@@ -52,11 +43,11 @@ LL | |     };
    | |_____^
    |
 note: Min Capture a[(0, 0)] -> ByValue
-  --> $DIR/capture-analysis-4.rs:27:18
+  --> $DIR/capture-analysis-4.rs:25:18
    |
 LL |         let _x = a.b;
    |                  ^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index ba4955085372a20551dc900aef1362cbaeca4da4..6fd15155331607e2baa9856e98251f6eb881d7e4 100644 (file)
@@ -1,9 +1,5 @@
-// FIXME(arora-aman) add run-pass once 2229 is implemented
+// edition:2021
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
 #![feature(rustc_attrs)]
 
 struct Point {
index 5fac6963afd32b49e352ec0b2809f851c0b805b0..0f64ecf3a0ccb7bc055ada5be9ab91cf05fa4cb9 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/capture-disjoint-field-struct.rs:17:13
+  --> $DIR/capture-disjoint-field-struct.rs:13:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/capture-disjoint-field-struct.rs:3:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/capture-disjoint-field-struct.rs:20:5
+  --> $DIR/capture-disjoint-field-struct.rs:16:5
    |
 LL | /     || {
 LL | |
@@ -29,13 +20,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing p[(0, 0)] -> ImmBorrow
-  --> $DIR/capture-disjoint-field-struct.rs:23:24
+  --> $DIR/capture-disjoint-field-struct.rs:19:24
    |
 LL |         println!("{}", p.x);
    |                        ^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/capture-disjoint-field-struct.rs:20:5
+  --> $DIR/capture-disjoint-field-struct.rs:16:5
    |
 LL | /     || {
 LL | |
@@ -47,11 +38,11 @@ LL | |     };
    | |_____^
    |
 note: Min Capture p[(0, 0)] -> ImmBorrow
-  --> $DIR/capture-disjoint-field-struct.rs:23:24
+  --> $DIR/capture-disjoint-field-struct.rs:19:24
    |
 LL |         println!("{}", p.x);
    |                        ^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index c1693fbad7986b342e7372aa77651f4b68c03eaa..8d3bb3262fb2b940821ae98f18d1edb07718a0cd 100644 (file)
@@ -1,9 +1,5 @@
-// FIXME(arora-aman) add run-pass once 2229 is implemented
+// edition:2021
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
 #![feature(rustc_attrs)]
 
 fn main() {
index 1bfd63f2ace8c5e8ed8b33fc260a6dc52fefad45..a8ca9622a6a68b8a7a47e7513eb9bd455d4169da 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/capture-disjoint-field-tuple.rs:12:13
+  --> $DIR/capture-disjoint-field-tuple.rs:8:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/capture-disjoint-field-tuple.rs:3:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/capture-disjoint-field-tuple.rs:15:5
+  --> $DIR/capture-disjoint-field-tuple.rs:11:5
    |
 LL | /     || {
 LL | |
@@ -29,13 +20,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing t[(0, 0)] -> ImmBorrow
-  --> $DIR/capture-disjoint-field-tuple.rs:18:24
+  --> $DIR/capture-disjoint-field-tuple.rs:14:24
    |
 LL |         println!("{}", t.0);
    |                        ^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/capture-disjoint-field-tuple.rs:15:5
+  --> $DIR/capture-disjoint-field-tuple.rs:11:5
    |
 LL | /     || {
 LL | |
@@ -47,11 +38,11 @@ LL | |     };
    | |_____^
    |
 note: Min Capture t[(0, 0)] -> ImmBorrow
-  --> $DIR/capture-disjoint-field-tuple.rs:18:24
+  --> $DIR/capture-disjoint-field-tuple.rs:14:24
    |
 LL |         println!("{}", t.0);
    |                        ^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 8fb2f7f16d69c4e44841e7ed5c6bff9941d32ad6..322ae99b861388b95a333ca796fbfccb9d2e4b14 100644 (file)
@@ -1,7 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
+
 #![feature(rustc_attrs)]
 
 enum Info {
index ebe1dcb98848b8ef44b8f6201dd15f28488e7b5e..8a6ba8444a80a4492001820daa440e265589e029 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/capture-enums.rs:18:13
+  --> $DIR/capture-enums.rs:16:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,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/capture-enums.rs:49:13
+  --> $DIR/capture-enums.rs:47:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,17 +16,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/capture-enums.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/capture-enums.rs:21:5
+  --> $DIR/capture-enums.rs:19:5
    |
 LL | /     || {
 LL | |
@@ -38,28 +29,28 @@ LL | |     };
    | |_____^
    |
 note: Capturing point[] -> ImmBorrow
-  --> $DIR/capture-enums.rs:24:41
+  --> $DIR/capture-enums.rs:22:41
    |
 LL |         if let Info::Point(_, _, str) = point {
    |                                         ^^^^^
 note: Capturing point[(2, 0)] -> ByValue
-  --> $DIR/capture-enums.rs:24:41
+  --> $DIR/capture-enums.rs:22:41
    |
 LL |         if let Info::Point(_, _, str) = point {
    |                                         ^^^^^
 note: Capturing meta[] -> ImmBorrow
-  --> $DIR/capture-enums.rs:31:35
+  --> $DIR/capture-enums.rs:29:35
    |
 LL |         if let Info::Meta(_, v) = meta {
    |                                   ^^^^
 note: Capturing meta[(1, 1)] -> ByValue
-  --> $DIR/capture-enums.rs:31:35
+  --> $DIR/capture-enums.rs:29:35
    |
 LL |         if let Info::Meta(_, v) = meta {
    |                                   ^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/capture-enums.rs:21:5
+  --> $DIR/capture-enums.rs:19:5
    |
 LL | /     || {
 LL | |
@@ -71,18 +62,18 @@ LL | |     };
    | |_____^
    |
 note: Min Capture point[] -> ByValue
-  --> $DIR/capture-enums.rs:24:41
+  --> $DIR/capture-enums.rs:22:41
    |
 LL |         if let Info::Point(_, _, str) = point {
    |                                         ^^^^^
 note: Min Capture meta[] -> ByValue
-  --> $DIR/capture-enums.rs:31:35
+  --> $DIR/capture-enums.rs:29:35
    |
 LL |         if let Info::Meta(_, v) = meta {
    |                                   ^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/capture-enums.rs:52:5
+  --> $DIR/capture-enums.rs:50:5
    |
 LL | /     || {
 LL | |
@@ -94,13 +85,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing point[(2, 0)] -> ByValue
-  --> $DIR/capture-enums.rs:55:47
+  --> $DIR/capture-enums.rs:53:47
    |
 LL |         let SingleVariant::Point(_, _, str) = point;
    |                                               ^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/capture-enums.rs:52:5
+  --> $DIR/capture-enums.rs:50:5
    |
 LL | /     || {
 LL | |
@@ -112,11 +103,11 @@ LL | |     };
    | |_____^
    |
 note: Min Capture point[(2, 0)] -> ByValue
-  --> $DIR/capture-enums.rs:55:47
+  --> $DIR/capture-enums.rs:53:47
    |
 LL |         let SingleVariant::Point(_, _, str) = point;
    |                                               ^^^^^
 
-error: aborting due to 6 previous errors; 1 warning emitted
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index f81866bb7e0967ea8e0780517af02e5a7ded4f5f..3341166e22b92bf3e38db923f33e8ca9c4313911 100644 (file)
@@ -1,7 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
+
 #![feature(rustc_attrs)]
 #![allow(unused)]
 
index 863f1009131a161d0e963469d5dab132d85a54ba..29e1af0431ec6b32f59b048bf9e127e0b0a8c75a 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/deep-multilevel-struct.rs:36:13
+  --> $DIR/deep-multilevel-struct.rs:34:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/deep-multilevel-struct.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/deep-multilevel-struct.rs:39:5
+  --> $DIR/deep-multilevel-struct.rs:37:5
    |
 LL | /     || {
 LL | |
@@ -29,23 +20,23 @@ LL | |     };
    | |_____^
    |
 note: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow
-  --> $DIR/deep-multilevel-struct.rs:42:18
+  --> $DIR/deep-multilevel-struct.rs:40:18
    |
 LL |         let x = &p.a.p.x;
    |                  ^^^^^^^
 note: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow
-  --> $DIR/deep-multilevel-struct.rs:44:9
+  --> $DIR/deep-multilevel-struct.rs:42:9
    |
 LL |         p.b.q.y = 9;
    |         ^^^^^^^
 note: Capturing p[] -> ImmBorrow
-  --> $DIR/deep-multilevel-struct.rs:47:26
+  --> $DIR/deep-multilevel-struct.rs:45:26
    |
 LL |         println!("{:?}", p);
    |                          ^
 
 error: Min Capture analysis includes:
-  --> $DIR/deep-multilevel-struct.rs:39:5
+  --> $DIR/deep-multilevel-struct.rs:37:5
    |
 LL | /     || {
 LL | |
@@ -57,7 +48,7 @@ LL | |     };
    | |_____^
    |
 note: Min Capture p[] -> MutBorrow
-  --> $DIR/deep-multilevel-struct.rs:44:9
+  --> $DIR/deep-multilevel-struct.rs:42:9
    |
 LL |         p.b.q.y = 9;
    |         ^^^^^^^ p[] captured as MutBorrow here
@@ -65,6 +56,6 @@ LL |         p.b.q.y = 9;
 LL |         println!("{:?}", p);
    |                          ^ p[] used here
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index fb03a02efa09e3e9d870a0405b99a96238ee91dd..34b0132f3cb0b9038a338f998e27b1f20cabd58c 100644 (file)
@@ -1,7 +1,4 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
 #![feature(rustc_attrs)]
 #![allow(unused)]
 
index 252db4447322288f64432a7c238b414d5dd2df36..e917516765c8fd731f7e1873947171d16a2a6d76 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/deep-multilevel-tuple.rs:11:13
+  --> $DIR/deep-multilevel-tuple.rs:8:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/deep-multilevel-tuple.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/deep-multilevel-tuple.rs:14:5
+  --> $DIR/deep-multilevel-tuple.rs:11:5
    |
 LL | /     || {
 LL | |
@@ -29,23 +20,23 @@ LL | |     };
    | |_____^
    |
 note: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow
-  --> $DIR/deep-multilevel-tuple.rs:17:18
+  --> $DIR/deep-multilevel-tuple.rs:14:18
    |
 LL |         let x = &t.0.0.0;
    |                  ^^^^^^^
 note: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow
-  --> $DIR/deep-multilevel-tuple.rs:19:9
+  --> $DIR/deep-multilevel-tuple.rs:16:9
    |
 LL |         t.1.1.1 = 9;
    |         ^^^^^^^
 note: Capturing t[] -> ImmBorrow
-  --> $DIR/deep-multilevel-tuple.rs:22:26
+  --> $DIR/deep-multilevel-tuple.rs:19:26
    |
 LL |         println!("{:?}", t);
    |                          ^
 
 error: Min Capture analysis includes:
-  --> $DIR/deep-multilevel-tuple.rs:14:5
+  --> $DIR/deep-multilevel-tuple.rs:11:5
    |
 LL | /     || {
 LL | |
@@ -57,7 +48,7 @@ LL | |     };
    | |_____^
    |
 note: Min Capture t[] -> MutBorrow
-  --> $DIR/deep-multilevel-tuple.rs:19:9
+  --> $DIR/deep-multilevel-tuple.rs:16:9
    |
 LL |         t.1.1.1 = 9;
    |         ^^^^^^^ t[] captured as MutBorrow here
@@ -65,6 +56,6 @@ LL |         t.1.1.1 = 9;
 LL |         println!("{:?}", t);
    |                          ^ t[] used here
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 080ca0405b4776c42ac0a5bc87a79d3c743ec0d3..9918802334ecc4d0bbe96faa6e19413f4d86fb70 100644 (file)
@@ -1,7 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
+
 #![feature(rustc_attrs)]
 
 // Test to ensure Index projections are handled properly during capture analysis
index 06ccc2d7a88b49e5b39d58ea1f72e652b45d8f52..b53adb5248161ef23cffb10c4cbd3101a0212d90 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/destructure_patterns.rs:12:13
+  --> $DIR/destructure_patterns.rs:10:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,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/destructure_patterns.rs:38:13
+  --> $DIR/destructure_patterns.rs:36:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,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/destructure_patterns.rs:58:13
+  --> $DIR/destructure_patterns.rs:56:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -25,17 +25,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/destructure_patterns.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/destructure_patterns.rs:15:5
+  --> $DIR/destructure_patterns.rs:13:5
    |
 LL | /     || {
 LL | |
@@ -47,13 +38,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing arr[Index] -> ByValue
-  --> $DIR/destructure_patterns.rs:18:29
+  --> $DIR/destructure_patterns.rs:16:29
    |
 LL |         let [a, b, .., e] = arr;
    |                             ^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/destructure_patterns.rs:15:5
+  --> $DIR/destructure_patterns.rs:13:5
    |
 LL | /     || {
 LL | |
@@ -65,13 +56,13 @@ LL | |     };
    | |_____^
    |
 note: Min Capture arr[] -> ByValue
-  --> $DIR/destructure_patterns.rs:18:29
+  --> $DIR/destructure_patterns.rs:16:29
    |
 LL |         let [a, b, .., e] = arr;
    |                             ^^^
 
 error: First Pass analysis includes:
-  --> $DIR/destructure_patterns.rs:41:5
+  --> $DIR/destructure_patterns.rs:39:5
    |
 LL | /     || {
 LL | |
@@ -83,18 +74,18 @@ LL | |     };
    | |_____^
    |
 note: Capturing p[(0, 0)] -> MutBorrow
-  --> $DIR/destructure_patterns.rs:44:58
+  --> $DIR/destructure_patterns.rs:42:58
    |
 LL |         let Point { x: ref mut x, y: _, id: moved_id } = p;
    |                                                          ^
 note: Capturing p[(2, 0)] -> ByValue
-  --> $DIR/destructure_patterns.rs:44:58
+  --> $DIR/destructure_patterns.rs:42:58
    |
 LL |         let Point { x: ref mut x, y: _, id: moved_id } = p;
    |                                                          ^
 
 error: Min Capture analysis includes:
-  --> $DIR/destructure_patterns.rs:41:5
+  --> $DIR/destructure_patterns.rs:39:5
    |
 LL | /     || {
 LL | |
@@ -106,18 +97,18 @@ LL | |     };
    | |_____^
    |
 note: Min Capture p[(0, 0)] -> MutBorrow
-  --> $DIR/destructure_patterns.rs:44:58
+  --> $DIR/destructure_patterns.rs:42:58
    |
 LL |         let Point { x: ref mut x, y: _, id: moved_id } = p;
    |                                                          ^
 note: Min Capture p[(2, 0)] -> ByValue
-  --> $DIR/destructure_patterns.rs:44:58
+  --> $DIR/destructure_patterns.rs:42:58
    |
 LL |         let Point { x: ref mut x, y: _, id: moved_id } = p;
    |                                                          ^
 
 error: First Pass analysis includes:
-  --> $DIR/destructure_patterns.rs:61:5
+  --> $DIR/destructure_patterns.rs:59:5
    |
 LL | /     || {
 LL | |
@@ -129,23 +120,23 @@ LL | |     };
    | |_____^
    |
 note: Capturing t[(0, 0)] -> MutBorrow
-  --> $DIR/destructure_patterns.rs:64:54
+  --> $DIR/destructure_patterns.rs:62:54
    |
 LL |         let (ref mut x, ref ref_str, (moved_s, _)) = t;
    |                                                      ^
 note: Capturing t[(1, 0)] -> ImmBorrow
-  --> $DIR/destructure_patterns.rs:64:54
+  --> $DIR/destructure_patterns.rs:62:54
    |
 LL |         let (ref mut x, ref ref_str, (moved_s, _)) = t;
    |                                                      ^
 note: Capturing t[(2, 0),(0, 0)] -> ByValue
-  --> $DIR/destructure_patterns.rs:64:54
+  --> $DIR/destructure_patterns.rs:62:54
    |
 LL |         let (ref mut x, ref ref_str, (moved_s, _)) = t;
    |                                                      ^
 
 error: Min Capture analysis includes:
-  --> $DIR/destructure_patterns.rs:61:5
+  --> $DIR/destructure_patterns.rs:59:5
    |
 LL | /     || {
 LL | |
@@ -157,21 +148,21 @@ LL | |     };
    | |_____^
    |
 note: Min Capture t[(0, 0)] -> MutBorrow
-  --> $DIR/destructure_patterns.rs:64:54
+  --> $DIR/destructure_patterns.rs:62:54
    |
 LL |         let (ref mut x, ref ref_str, (moved_s, _)) = t;
    |                                                      ^
 note: Min Capture t[(1, 0)] -> ImmBorrow
-  --> $DIR/destructure_patterns.rs:64:54
+  --> $DIR/destructure_patterns.rs:62:54
    |
 LL |         let (ref mut x, ref ref_str, (moved_s, _)) = t;
    |                                                      ^
 note: Min Capture t[(2, 0),(0, 0)] -> ByValue
-  --> $DIR/destructure_patterns.rs:64:54
+  --> $DIR/destructure_patterns.rs:62:54
    |
 LL |         let (ref mut x, ref ref_str, (moved_s, _)) = t;
    |                                                      ^
 
-error: aborting due to 9 previous errors; 1 warning emitted
+error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 0b94317fd7136e36badef7c0ef073cd78eed2143..93131b2ac4e4d47999a4f761a9953b9cfc64c9e0 100644 (file)
@@ -1,7 +1,6 @@
-// Test that arrays are completely captured by closures by relying on the borrow check diagnostics
+// edition:2021
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+// Test that arrays are completely captured by closures by relying on the borrow check diagnostics
 
 fn arrays_1() {
     let mut arr = [1, 2, 3, 4, 5];
index 77e3e71bc6120c2bc3bc0c1d2c467540d530bcd5..a3f2f25e447e1ac500cff609f5136a058678adb7 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/arrays.rs:3:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0503]: cannot use `arr` because it was mutably borrowed
-  --> $DIR/arrays.rs:15:5
+  --> $DIR/arrays.rs:14:5
    |
 LL |     let mut c = || {
    |                 -- borrow of `arr` occurs here
@@ -22,7 +13,7 @@ LL |     c();
    |     - borrow later used here
 
 error[E0503]: cannot use `arr[_]` because it was mutably borrowed
-  --> $DIR/arrays.rs:15:5
+  --> $DIR/arrays.rs:14:5
    |
 LL |     let mut c = || {
    |                 -- borrow of `arr` occurs here
@@ -36,7 +27,7 @@ LL |     c();
    |     - borrow later used here
 
 error[E0506]: cannot assign to `arr[_]` because it is borrowed
-  --> $DIR/arrays.rs:30:5
+  --> $DIR/arrays.rs:29:5
    |
 LL |     let c = || {
    |             -- borrow of `arr[_]` occurs here
@@ -50,7 +41,7 @@ LL |     c();
    |     - borrow later used here
 
 error[E0506]: cannot assign to `arr[_]` because it is borrowed
-  --> $DIR/arrays.rs:44:5
+  --> $DIR/arrays.rs:43:5
    |
 LL |     let c = || {
    |             -- borrow of `arr[_]` occurs here
@@ -64,7 +55,7 @@ LL |     c();
    |     - borrow later used here
 
 error[E0503]: cannot use `arr` because it was mutably borrowed
-  --> $DIR/arrays.rs:58:20
+  --> $DIR/arrays.rs:57:20
    |
 LL |     let mut c = || {
    |                 -- borrow of `arr` occurs here
@@ -78,7 +69,7 @@ LL |     c();
    |     - borrow later used here
 
 error[E0502]: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable
-  --> $DIR/arrays.rs:58:20
+  --> $DIR/arrays.rs:57:20
    |
 LL |     let mut c = || {
    |                 -- mutable borrow occurs here
@@ -92,7 +83,7 @@ LL |     c();
    |     - mutable borrow later used here
 
 error[E0502]: cannot borrow `arr` as immutable because it is also borrowed as mutable
-  --> $DIR/arrays.rs:74:24
+  --> $DIR/arrays.rs:73:24
    |
 LL |     let mut c = || {
    |                 -- mutable borrow occurs here
@@ -105,7 +96,7 @@ LL |     println!("{:#?}", &arr[3..2]);
 LL |     c();
    |     - mutable borrow later used here
 
-error: aborting due to 7 previous errors; 1 warning emitted
+error: aborting due to 7 previous errors
 
 Some errors have detailed explanations: E0502, E0503, E0506.
 For more information about an error, try `rustc --explain E0502`.
index 2f3358dcd8db71d3d8749dffd35348aa0ad9bdb6..3664d76c2038f2da3c93f3e9532801d94d4e6c06 100644 (file)
@@ -1,5 +1,4 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+// edition:2021
 
 #[derive(Debug)]
 struct Point {
index e15067b264d63af8e850c67b9dc122c9ddb4dfbc..341d2bc65634b505db9faa9894608c52851bc65a 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/borrowck-1.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0499]: cannot borrow `p` as mutable more than once at a time
-  --> $DIR/borrowck-1.rs:13:17
+  --> $DIR/borrowck-1.rs:12:17
    |
 LL |     let y = &mut p.y;
    |             -------- first mutable borrow occurs here
@@ -23,6 +14,6 @@ LL |        println!("{:?}", p);
 LL |     *y+=1;
    |     ----- first borrow later used here
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0499`.
index 06c6a87eb105dd0170001930a8e9b6ec688fd43b..ae416bab65ea5128728987d5e0a56ce48bb9da52 100644 (file)
@@ -1,5 +1,4 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+// edition:2021
 
 #[derive(Debug)]
 struct Point {
index a195b981eaadd416aaaa4497f3a5d45911dd1199..584bb862b2c0aa8ccd5a5d430e331c895952f385 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/borrowck-2.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-2.rs:13:17
+  --> $DIR/borrowck-2.rs:12:17
    |
 LL |     let y = &p.y;
    |             ---- immutable borrow occurs here
@@ -23,6 +14,6 @@ LL |        let x = &mut p.x;
 LL |     println!("{}", y);
    |                    - immutable borrow later used here
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0502`.
index ba998f78c87acb68f7ce3383b61879198d349454..bdd6cb79b60b09f414508c21884102b06cace66d 100644 (file)
@@ -1,5 +1,4 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+// edition:2021
 
 #[derive(Debug)]
 struct Point {
index b54c729a307c0c61b19c46a99bbe1c2d8438a3cf..dab1809a381ee28a1e5241253069faadc37d8126 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/borrowck-3.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0597]: `p` does not live long enough
-  --> $DIR/borrowck-3.rs:14:29
+  --> $DIR/borrowck-3.rs:13:29
    |
 LL |     let mut c = {
    |         ----- borrow later stored here
@@ -22,6 +13,6 @@ LL |            println!("{:?}", p);
 LL |     };
    |     - `p` dropped here while still borrowed
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0597`.
index 4fab0189c27f8df4de52b4f9866184bd9299dbe2..a2290d850207d2bcfebfec3edfa3b50072a3c541 100644 (file)
@@ -1,5 +1,4 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+// edition:2021
 
 #[derive(Debug)]
 struct Point {
index 905fa3475edd86644f148570208ad6ca2f159dee..29bd4b27d6b07f6365e79a38c2bafb42a792a505 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/borrowck-4.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0373]: closure may outlive the current function, but it borrows `p`, which is owned by the current function
-  --> $DIR/borrowck-4.rs:11:17
+  --> $DIR/borrowck-4.rs:10:17
    |
 LL |     let mut c = || {
    |                 ^^ may outlive borrowed value `p`
@@ -17,7 +8,7 @@ LL |        println!("{:?}", p);
    |                         - `p` is borrowed here
    |
 note: closure is returned here
-  --> $DIR/borrowck-4.rs:9:14
+  --> $DIR/borrowck-4.rs:8:14
    |
 LL | fn foo () -> impl FnMut()->() {
    |              ^^^^^^^^^^^^^^^^
@@ -26,6 +17,6 @@ help: to force the closure to take ownership of `p` (and any other referenced va
 LL |     let mut c = move || {
    |                 ^^^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0373`.
index b23947ad5d1bff38b74c1f3cdc473f9e39de3a83..6a8c9664051dfc0e4c9681cbe695e63738adc6c1 100644 (file)
@@ -1,8 +1,8 @@
+// edition:2021
+
 // Tests that two closures cannot simultaneously have mutable
 // and immutable access to the variable. Issue #6801.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
 #![feature(box_syntax)]
 
 #[derive(Debug)]
index 58975c6f46fe49fa8671c901312862bfd1b700ef..5f1dae2972f9e6766ffef3e107c843d507dffb78 100644 (file)
@@ -1,12 +1,3 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/borrowck-closures-mut-and-imm.rs:4:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-closures-mut-and-imm.rs:17:14
    |
@@ -25,6 +16,6 @@ LL |     };
 LL |     drop(c2);
    |          -- immutable borrow later used here
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0502`.
index 15be1d8c7220dadaded08bf126d1e014131f9526..a110fa4e2cb3e257165523f1be3e972d5734914d 100644 (file)
@@ -1,7 +1,6 @@
-// Test borrow checker when we precise capture when using boxes
+// edition:2021
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+// Test borrow checker when we precise capture when using boxes
 
 struct MetaData { x: String, name: String }
 struct Data { m: MetaData }
index 174faa33c49ab53b2cf8d3f8b16620b7548a4d20..2badf0514187eb135ec44b6d9cf4ca04bfd0c83d 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/box.rs:3:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed
-  --> $DIR/box.rs:22:5
+  --> $DIR/box.rs:21:5
    |
 LL |     let mut c = || {
    |                 -- borrow of `e.0.0.m.x` occurs here
@@ -22,7 +13,7 @@ LL |     c();
    |     - borrow later used here
 
 error[E0502]: cannot borrow `e.0.0.m.x` as immutable because it is also borrowed as mutable
-  --> $DIR/box.rs:39:20
+  --> $DIR/box.rs:38:20
    |
 LL |     let mut c = || {
    |                 -- mutable borrow occurs here
@@ -36,7 +27,7 @@ LL |     c();
    |     - mutable borrow later used here
 
 error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed
-  --> $DIR/box.rs:56:5
+  --> $DIR/box.rs:55:5
    |
 LL |     let c = || {
    |             -- borrow of `e.0.0.m.x` occurs here
@@ -49,7 +40,7 @@ LL |
 LL |     c();
    |     - borrow later used here
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0502, E0506.
 For more information about an error, try `rustc --explain E0502`.
index 1ea38e260b645d91d6ed09da639fbe57fbafa4e0..77effcb006588f263df2c996d3763c3c2bb73ab5 100644 (file)
@@ -1,18 +1,17 @@
+// edition:2021
+
 // Test that if we deref an immutable borrow to access a Place,
 // then we can't mutate the final place.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-
 fn main() {
     let mut x = (format!(""), format!("X2"));
     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 39a11fb332725881392d25e0e4a4306a72bb2d2a..38c530b809a624680626c6b52c608c2113777974 100644 (file)
@@ -1,21 +1,12 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/cant-mutate-imm-borrow.rs:4:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-error[E0596]: cannot borrow `z.0.0.0` as mutable, as it is behind a `&` reference
-  --> $DIR/cant-mutate-imm-borrow.rs:14:17
+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; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0596`.
index 928c866726f71db5085b60093332ab695ad9a2bd..25ee9a1490e0c3aa290d665b2967dd488ecc4330 100644 (file)
@@ -1,5 +1,4 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+// edition:2021
 
 // Ensure that diagnostics for mutability error (because the root variable
 // isn't mutable) work with `capture_disjoint_fields` enabled.
index 9fb8dd4a1c36e350bc414eebbf730262a51db7e2..98414fa8a3d5f1dec4b2627653228008bcc6bccb 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/cant-mutate-imm.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0594]: cannot assign to `z.0.0.0`, as it is not declared as mutable
-  --> $DIR/cant-mutate-imm.rs:13:9
+  --> $DIR/cant-mutate-imm.rs:12:9
    |
 LL |     let z = (y, 10);
    |         - help: consider changing this to be mutable: `mut z`
@@ -17,7 +8,7 @@ LL |         z.0.0.0 = 20;
    |         ^^^^^^^^^^^^ cannot assign
 
 error[E0594]: cannot assign to `*bx.0`, as it is not declared as mutable
-  --> $DIR/cant-mutate-imm.rs:25:9
+  --> $DIR/cant-mutate-imm.rs:24:9
    |
 LL |     let bx = Box::new(x);
    |         -- help: consider changing this to be mutable: `mut bx`
@@ -25,6 +16,6 @@ LL |     let bx = Box::new(x);
 LL |         bx.0 = 20;
    |         ^^^^^^^^^ cannot assign
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0594`.
index cd7c25620a7c43bccf5020fa0e36270e6d2352b6..f3be542e40d7a506ea48451e17d4e4bc56c9f46f 100644 (file)
@@ -1,7 +1,4 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| `#[warn(incomplete_features)]` on by default
-//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
 
 // Test that array access is not stored as part of closure kind origin
 
index bd9428771f4c5b5816d91791e97ced2499b8c346..bcde35983fc4c3f6484c38b8052c1cb6a9d33724 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/closure-origin-array-diagnostics.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
-  --> $DIR/closure-origin-array-diagnostics.rs:12:13
+  --> $DIR/closure-origin-array-diagnostics.rs:9:13
    |
 LL |     let c = || {
    |             ^^ this closure implements `FnOnce`, not `Fn`
@@ -18,6 +9,6 @@ LL |     };
 LL |     expect_fn(c);
    |     --------- the requirement to implement `Fn` derives from here
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0525`.
index 2916d8c794f22e22b8b7f4c455077e21e14ea086..aa85b55b15cc73344bffc25c52f43660362a7db0 100644 (file)
@@ -1,11 +1,7 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| `#[warn(incomplete_features)]` on by default
-//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
 
 // Check that precise paths are being reported back in the error message.
 
-
 enum MultiVariant {
     Point(i32, i32),
     Meta(i32)
index de0bfe3bd769fb035af319882b6fbfafa13e2fe4..066c000c832d8b61ded2f62bd1b8455ca9065603 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/closure-origin-multi-variant-diagnostics.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0382]: use of moved value: `c`
-  --> $DIR/closure-origin-multi-variant-diagnostics.rs:30:13
+  --> $DIR/closure-origin-multi-variant-diagnostics.rs:26:13
    |
 LL |     let a = c;
    |             - value moved here
@@ -16,11 +7,11 @@ LL |     let b = c;
    |             ^ value used here after move
    |
 note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment
-  --> $DIR/closure-origin-multi-variant-diagnostics.rs:20:52
+  --> $DIR/closure-origin-multi-variant-diagnostics.rs:16:52
    |
 LL |         if let MultiVariant::Point(ref mut x, _) = point {
    |                                                    ^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0382`.
index 2ed0149b9db7d47fa441b71db68dc80e885febc2..bedb103cc4c7bd5da4c06aeb8ac528ace3138010 100644 (file)
@@ -1,9 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| `#[warn(incomplete_features)]` on by default
-//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
 
-// Check that precise paths are being reported back in the error message.
 
 enum SingleVariant {
     Point(i32, i32),
index 402f5e4f33e6f30bbf29239d4fcade7aceac5d5b..2a6e00850fa8a22a31b2052013e3c2f8a418c634 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/closure-origin-single-variant-diagnostics.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0382]: use of moved value: `c`
-  --> $DIR/closure-origin-single-variant-diagnostics.rs:21:13
+  --> $DIR/closure-origin-single-variant-diagnostics.rs:17:13
    |
 LL |     let b = c;
    |             - value moved here
@@ -16,11 +7,11 @@ LL |     let a = c;
    |             ^ value used here after move
    |
 note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment
-  --> $DIR/closure-origin-single-variant-diagnostics.rs:16:50
+  --> $DIR/closure-origin-single-variant-diagnostics.rs:12:50
    |
 LL |         let SingleVariant::Point(ref mut x, _) = point;
    |                                                  ^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0382`.
index 103890f1f353754a8de003296c63d1c3a4d370e7..3277a83c4e147547a64e61353943765bdb163b84 100644 (file)
@@ -1,7 +1,4 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| `#[warn(incomplete_features)]` on by default
-//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
 
 // Check that precise paths are being reported back in the error message.
 
index 474d77b7cd2086a541c11ff28f70ae845384f1ee..d7fc51c55eae32249ac9c409ff1c37b53d22f637 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/closure-origin-struct-diagnostics.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0382]: use of moved value: `hello`
-  --> $DIR/closure-origin-struct-diagnostics.rs:24:13
+  --> $DIR/closure-origin-struct-diagnostics.rs:21:13
    |
 LL |     let b = hello;
    |             ----- value moved here
@@ -16,11 +7,11 @@ LL |     let c = hello;
    |             ^^^^^ value used here after move
    |
 note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.y.a` out of its environment
-  --> $DIR/closure-origin-struct-diagnostics.rs:20:9
+  --> $DIR/closure-origin-struct-diagnostics.rs:17:9
    |
 LL |         x.y.a += 1;
    |         ^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0382`.
index 6b078d2329c2ffbf8d3c96a8812179e85d8debd3..dc3a57ae793e7c71ed33c76db2d381fdb157f6e3 100644 (file)
@@ -1,7 +1,4 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| `#[warn(incomplete_features)]` on by default
-//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
 
 // Check that precise paths are being reported back in the error message.
 
index 716728e96ecbbb101c67e9d9089208711b6dfeb9..63e2d300eb06a82cebdf7b304f5b701a5f5b2e6a 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/closure-origin-tuple-diagnostics-1.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0382]: use of moved value: `hello`
-  --> $DIR/closure-origin-tuple-diagnostics-1.rs:15:13
+  --> $DIR/closure-origin-tuple-diagnostics-1.rs:12:13
    |
 LL |     let b = hello;
    |             ----- value moved here
@@ -16,11 +7,11 @@ LL |     let c = hello;
    |             ^^^^^ value used here after move
    |
 note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.0` out of its environment
-  --> $DIR/closure-origin-tuple-diagnostics-1.rs:11:9
+  --> $DIR/closure-origin-tuple-diagnostics-1.rs:8:9
    |
 LL |         x.0 += 1;
    |         ^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0382`.
index 0638db607690fda2987ba416a85ddffd90691fef..fa1328013db456eadc0d9837098cf915fd538e1f 100644 (file)
@@ -1,7 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| `#[warn(incomplete_features)]` on by default
-//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
+
 struct S(String, String);
 
 fn expect_fn<F: Fn()>(_f: F) {}
index 77eb2a94ffb4d7ba01bfb5aae7dfb3029043a995..df33c4f1fd6d4836c1db1ac0995aa9843601631a 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/closure-origin-tuple-diagnostics.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
-  --> $DIR/closure-origin-tuple-diagnostics.rs:11:13
+  --> $DIR/closure-origin-tuple-diagnostics.rs:9:13
    |
 LL |     let c = || {
    |             ^^ this closure implements `FnOnce`, not `Fn`
@@ -18,6 +9,6 @@ LL |     };
 LL |     expect_fn(c);
    |     --------- the requirement to implement `Fn` derives from here
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0525`.
index 09491f296f6672a346892bef646fa71deb504c70..1cc22fac35282217cf9a121bc11222a220e9fa66 100644 (file)
@@ -1,6 +1,6 @@
+// edition:2021
+
 // check-pass
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
 #![allow(unreachable_code)]
 #![warn(unused)]
 
index 81bbc4e1dc0c24166912805efd0e6a7f098448aa..4eac5a2d282b07b527e6cbe8f3fe0841e57591e2 100644 (file)
@@ -1,12 +1,3 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/liveness.rs:2:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 warning: value captured by `a` is never read
   --> $DIR/liveness.rs:23:9
    |
@@ -75,5 +66,5 @@ LL |             b = Some("e1");
    |
    = help: did you mean to capture by reference instead?
 
-warning: 8 warnings emitted
+warning: 7 warnings emitted
 
index e2035464dfa8a658cdc0f378f96a2669cfb6985c..10a7d07a1df99937e38e1a7aa4d05a62862f9e4d 100644 (file)
@@ -1,6 +1,6 @@
+// edition:2021
+
 // check-pass
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
 #![warn(unused)]
 
 #[derive(Debug)]
index 35b0c22fc4fb97dae4b1ebc9c0a2e7cd928c693a..f74303e3dd682672d8d13cdba48d6669ee40ad9f 100644 (file)
@@ -1,12 +1,3 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/liveness_unintentional_copy.rs:2:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 warning: value assigned to `a` is never read
   --> $DIR/liveness_unintentional_copy.rs:19:9
    |
@@ -43,5 +34,5 @@ LL |         a += x;
    |
    = help: did you mean to capture by reference instead?
 
-warning: 4 warnings emitted
+warning: 3 warnings emitted
 
index 39b04c833e384d3c9baf43541181f3dfd5ebe435..fa73ff23f9cd37bdaaa40f070eacf67c082f044a 100644 (file)
@@ -1,8 +1,8 @@
+// edition:2021
+
 // Test that when a borrow checker diagnostics are emitted, it's as precise
 // as the capture by the closure.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
 #![allow(unused)]
 
 struct Point {
index a3d1f550557affc7c7721d9a80f4b3d926e08097..ac4c9c93769ce93dd465bded5a50d5b44a3de6d8 100644 (file)
@@ -1,12 +1,3 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/multilevel-path.rs:4:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0499]: cannot borrow `w.p.x` as mutable more than once at a time
   --> $DIR/multilevel-path.rs:23:14
    |
@@ -21,6 +12,6 @@ LL |
 LL |     c();
    |     - first borrow later used here
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0499`.
index 676fde558dfbc684d81a732cef204de7effe072b..3d5a31e8b8e49e383cf589dec005c13644d0abb2 100644 (file)
@@ -1,9 +1,8 @@
+// edition:2021
+
 // Test that we can't mutate a place if we need to deref an imm-borrow
 // to reach it.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-
 fn imm_mut_ref() {
     let mut x = String::new();
     let y = String::new();
index 831e486db82af60e5c01d39d943641b8ee3675b2..dbf8523a3bae111512411a19667815596495fa69 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/mut_ref.rs:4:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0596]: cannot borrow `**ref_mref_x` as mutable, as it is behind a `&` reference
-  --> $DIR/mut_ref.rs:13:13
+  --> $DIR/mut_ref.rs:12:13
    |
 LL |     let ref_mref_x = &mref_x;
    |                      ------- help: consider changing this to be a mutable reference: `&mut mref_x`
@@ -20,7 +11,7 @@ LL |         **ref_mref_x = y;
    |         ------------ mutable borrow occurs due to use of `**ref_mref_x` in closure
 
 error[E0596]: cannot borrow `**mref_ref_x` as mutable, as it is behind a `&` reference
-  --> $DIR/mut_ref.rs:27:13
+  --> $DIR/mut_ref.rs:26:13
    |
 LL |     let c = || {
    |             ^^ cannot borrow as mutable
@@ -28,6 +19,6 @@ LL |
 LL |         **mref_ref_x = y;
    |         ------------ mutable borrow occurs due to use of `**mref_ref_x` in closure
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0596`.
index 82ec60a2e790af65ac7ce2103c59d50e73ab5ddd..4799f488d7d525eb0b21c12bf6f5991c3be107a6 100644 (file)
@@ -1,7 +1,6 @@
-// check-pass
+// edition:2021
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+// check-pass
 
 // Given how the closure desugaring is implemented (at least at the time of writing this test),
 // we don't need to truncate the captured path to a reference into a packed-struct if the field
index e8cc164be8754fabbbec6c7dc47e07e998426186..d2466681a0877a24836da8cd4ed7d180699ec12e 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/repr_packed.rs:3:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 warning: reference to packed field is unaligned
-  --> $DIR/repr_packed.rs:25:24
+  --> $DIR/repr_packed.rs:24:24
    |
 LL |         println!("{}", foo.x);
    |                        ^^^^^
@@ -18,5 +9,5 @@ LL |         println!("{}", foo.x);
    = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
 
-warning: 2 warnings emitted
+warning: 1 warning emitted
 
index e78d8715e4893def8d891f92fdb9de09721c5343..ed2d9a3de00f87417039e58315578d9e3d593741 100644 (file)
@@ -1,9 +1,8 @@
+// edition:2021
+
 // Test that borrow checker error is accurate and that min capture pass of the
 // closure analysis is working as expected.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-
 #[derive(Debug)]
 struct Point {
     x: i32,
index f1748fda151c51a5ed52c81e0e78e1fc4ccd3ab8..32705af3d016623eba451e00feba3c98ef12328c 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/simple-struct-min-capture.rs:4:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable
-  --> $DIR/simple-struct-min-capture.rs:23:22
+  --> $DIR/simple-struct-min-capture.rs:22:22
    |
 LL |     let mut c = || {
    |                 -- mutable borrow occurs here
@@ -23,6 +14,6 @@ LL |
 LL |     c();
    |     - mutable borrow later used here
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0502`.
index a3222635b626c4953c709c1c8099dd84211e13d5..269cf76e6735126b67e979bab9165e4babe5e961 100644 (file)
@@ -1,7 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
+
 #![feature(rustc_attrs)]
 
 fn main() {
index a031360ed34e1acd757979f5b197a76c356e6050..b936c5ee35a4dd27cfd875a8abc46cc2f1d14adc 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/feature-gate-capture_disjoint_fields.rs:10:13
+  --> $DIR/feature-gate-capture_disjoint_fields.rs:8:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/feature-gate-capture_disjoint_fields.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/feature-gate-capture_disjoint_fields.rs:13:5
+  --> $DIR/feature-gate-capture_disjoint_fields.rs:11:5
    |
 LL | /     || {
 LL | |
@@ -29,13 +20,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing s[] -> ImmBorrow
-  --> $DIR/feature-gate-capture_disjoint_fields.rs:16:69
+  --> $DIR/feature-gate-capture_disjoint_fields.rs:14:69
    |
 LL |         println!("This uses new capture analyysis to capture s={}", s);
    |                                                                     ^
 
 error: Min Capture analysis includes:
-  --> $DIR/feature-gate-capture_disjoint_fields.rs:13:5
+  --> $DIR/feature-gate-capture_disjoint_fields.rs:11:5
    |
 LL | /     || {
 LL | |
@@ -47,11 +38,11 @@ LL | |     };
    | |_____^
    |
 note: Min Capture s[] -> ImmBorrow
-  --> $DIR/feature-gate-capture_disjoint_fields.rs:16:69
+  --> $DIR/feature-gate-capture_disjoint_fields.rs:14:69
    |
 LL |         println!("This uses new capture analyysis to capture s={}", s);
    |                                                                     ^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 9466e103897fb2c972449c4c9c01a7f6fa035a37..bfa3ebcd6d2866806601ac0a3045d3850e899efb 100644 (file)
@@ -1,9 +1,5 @@
-// FIXME(arora-aman) add run-pass once 2229 is implemented
+// edition:2021
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
 #![feature(rustc_attrs)]
 
 struct Filter {
index e9420fe5a0c3a814c13b977f5a7aa3ee881e242b..10e0d076b427621dd6bfcb74cd16514e1c4e8afd 100644 (file)
@@ -1,35 +1,26 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/filter-on-struct-member.rs:3:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/filter-on-struct-member.rs:28:13
+  --> $DIR/filter-on-struct-member.rs:24:13
    |
 LL |             |v| self.filter.allowed(*v),
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: Capturing self[Deref,(0, 0)] -> ImmBorrow
-  --> $DIR/filter-on-struct-member.rs:28:17
+  --> $DIR/filter-on-struct-member.rs:24:17
    |
 LL |             |v| self.filter.allowed(*v),
    |                 ^^^^^^^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/filter-on-struct-member.rs:28:13
+  --> $DIR/filter-on-struct-member.rs:24:13
    |
 LL |             |v| self.filter.allowed(*v),
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: Min Capture self[Deref,(0, 0)] -> ImmBorrow
-  --> $DIR/filter-on-struct-member.rs:28:17
+  --> $DIR/filter-on-struct-member.rs:24:17
    |
 LL |             |v| self.filter.allowed(*v),
    |                 ^^^^^^^^^^^
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87097.rs b/src/test/ui/closures/2229_closure_analysis/issue-87097.rs
new file mode 100644 (file)
index 0000000..241ddcb
--- /dev/null
@@ -0,0 +1,35 @@
+// run-pass
+// edition:2021
+
+enum Variant {
+    A,
+    B, //~ WARNING: variant is never constructed: `B`
+}
+
+struct A {
+    field: Variant,
+}
+
+fn discriminant_is_a_ref() {
+    let here = A { field: Variant::A };
+    let out_ref = &here.field;
+
+    || match out_ref { //~ WARNING: unused closure that must be used
+        Variant::A => (),
+        Variant::B => (),
+    };
+}
+
+fn discriminant_is_a_field() {
+    let here = A { field: Variant::A };
+
+    || match here.field { //~ WARNING: unused closure that must be used
+        Variant::A => (),
+        Variant::B => (),
+    };
+}
+
+fn main() {
+    discriminant_is_a_ref();
+    discriminant_is_a_field();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87097.stderr b/src/test/ui/closures/2229_closure_analysis/issue-87097.stderr
new file mode 100644 (file)
index 0000000..38f2929
--- /dev/null
@@ -0,0 +1,33 @@
+warning: variant is never constructed: `B`
+  --> $DIR/issue-87097.rs:6:5
+   |
+LL |     B,
+   |     ^
+   |
+   = note: `#[warn(dead_code)]` on by default
+
+warning: unused closure that must be used
+  --> $DIR/issue-87097.rs:17:5
+   |
+LL | /     || match out_ref {
+LL | |         Variant::A => (),
+LL | |         Variant::B => (),
+LL | |     };
+   | |______^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: closures are lazy and do nothing unless called
+
+warning: unused closure that must be used
+  --> $DIR/issue-87097.rs:26:5
+   |
+LL | /     || match here.field {
+LL | |         Variant::A => (),
+LL | |         Variant::B => (),
+LL | |     };
+   | |______^
+   |
+   = note: closures are lazy and do nothing unless called
+
+warning: 3 warnings emitted
+
index 93e6cf034055a98aca21a0d89e62e214983e3f76..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 affected for closure because of `capture_disjoint_fields`
+        //~^ 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 affected for closure because of `capture_disjoint_fields`
+        //~^ 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 affected for closure because of `capture_disjoint_fields`
+        //~^ 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 2c0dbd017548b0749a428330a2c8437b0b70cee0..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 affected for closure because of `capture_disjoint_fields`
+        //~^ 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 affected for closure because of `capture_disjoint_fields`
+        //~^ 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 = || {
-        //~^ ERROR: `Clone` trait implementation, and drop order affected for closure because of `capture_disjoint_fields`
+        //~^ 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 6e3723b8bdb20da46fa839f90a35501b76fe54be..9c954b1465d837e5a3d8293382a76323d92eae2b 100644 (file)
@@ -1,69 +1,70 @@
-error: `Send` trait implementation affected for closure because of `capture_disjoint_fields`
-  --> $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 affected for closure because of `capture_disjoint_fields`
-  --> $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
    |
 LL |     thread::spawn(move || { let _ = &fptr; unsafe {
 LL |
 LL |
+LL |
+LL |
 LL |         *fptr.0.0 = 20;
-LL |     } });
-   |
+ ...
 
-error: `Clone` trait implementation, and drop order affected for closure because of `capture_disjoint_fields`
-  --> $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
    |
 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 3770e93239a8efde54d3a754109eee92b0667d20..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,16 +13,23 @@ fn test1_all_need_migration() {
     let t2 = (String::new(), String::new());
 
     let c = || { let _ = (&t, &t1, &t2); 
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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
@@ -32,15 +39,20 @@ fn test2_only_precise_paths_need_migration() {
     let t2 = (String::new(), String::new());
 
     let c = || { let _ = (&t, &t1); 
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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.
@@ -48,14 +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 affected for closure because of `capture_disjoint_fields`
-    //~| 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.
@@ -66,14 +81,17 @@ fn test4_only_non_copy_types_need_migration() {
     let t1 = (0i32, 0i32);
 
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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);
@@ -84,14 +102,17 @@ fn test5_only_drop_types_need_migration() {
     let s = S(0i32, 0i32);
 
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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.
@@ -99,13 +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 affected for closure because of `capture_disjoint_fields`
-    //~| 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,
@@ -114,13 +140,16 @@ fn test7_drop_non_drop_aggregate_need_migration() {
     let t = (String::new(), String::new(), 0i32);
 
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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 2015ab7e9b8cb5b5bb52a2243960b2d84034dfcc..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,16 +13,23 @@ fn test1_all_need_migration() {
     let t2 = (String::new(), String::new());
 
     let c = || {
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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
@@ -32,15 +39,20 @@ fn test2_only_precise_paths_need_migration() {
     let t2 = (String::new(), String::new());
 
     let c = || {
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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.
@@ -48,14 +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 affected for closure because of `capture_disjoint_fields`
-    //~| 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.
@@ -66,14 +81,17 @@ fn test4_only_non_copy_types_need_migration() {
     let t1 = (0i32, 0i32);
 
     let c = || {
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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);
@@ -84,14 +102,17 @@ fn test5_only_drop_types_need_migration() {
     let s = S(0i32, 0i32);
 
     let c = || {
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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.
@@ -99,13 +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 affected for closure because of `capture_disjoint_fields`
-    //~| 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,
@@ -114,13 +140,16 @@ fn test7_drop_non_drop_aggregate_need_migration() {
     let t = (String::new(), String::new(), 0i32);
 
     let c = || {
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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 69a99f7a53a53a30ff483a6b1d06a405cb1b20fd..e9e4794cff5f797c76a2af945130ebf14ebc871a 100644 (file)
-error: drop order affected for closure because of `capture_disjoint_fields`
+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
    |
 LL |     let c = || { let _ = (&t, &t1, &t2); 
 LL |
 LL |
+LL |
 LL | 
 LL |         let _t = t.0;
-LL |         let _t1 = t1.0;
  ...
 
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $DIR/insignificant_drop.rs:34:13
-   |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |         let _t = t.0;
-LL | |         let _t1 = t1.0;
-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
    |
 LL |     let c = || { let _ = (&t, &t1); 
 LL |
 LL |
+LL |
 LL |         let _t = t.0;
-LL |         let _t1 = t1.0;
-LL |         let _t2 = t2;
+LL |
  ...
 
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $DIR/insignificant_drop.rs:50:13
-   |
-LL |       let c = || {
-   |  _____________^
-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
    |
 LL |     let c = || { let _ = &t; 
 LL |
 LL |
+LL |
 LL |         let _t = t.0;
-LL |         println!("{}", t1.1);
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $DIR/insignificant_drop.rs:68:13
-   |
-LL |       let c = || {
-   |  _____________^
-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
    |
 LL |     let c = || { let _ = &t; 
 LL |
 LL |
+LL |
 LL |         let _t = t.0;
-LL |         let _t1 = t1.0;
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $DIR/insignificant_drop.rs:86:13
-   |
-LL |       let c = || {
-   |  _____________^
-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
    |
 LL |     let c = || { let _ = &t; 
 LL |
 LL |
+LL |
 LL |         let _t = t.0;
-LL |         let _s = s.0;
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $DIR/insignificant_drop.rs:101:13
-   |
-LL |       let c = move || {
-   |  _____________^
-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
    |
 LL |     let c = move || { let _ = (&t1, &t); 
 LL |
 LL |
+LL |
 LL |         println!("{} {}", t1.1, t.1);
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $DIR/insignificant_drop.rs:116: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 | |         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
    |
 LL |     let c = || { let _ = &t; 
 LL |
 LL |
+LL |
 LL |         let _t = t.0;
-LL |     };
-   |
+LL |
+ ...
 
 error: aborting due to 7 previous errors
 
index e89cc2c8fb3618bc0e5c8e29b0aabcf3beee9e06..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,13 +35,16 @@ fn significant_drop_needs_migration() {
     let t = (SigDrop {}, SigDrop {});
 
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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
@@ -53,13 +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 affected for closure because of `capture_disjoint_fields`
-    //~| 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 e16cd9d52b78c010a44544b565677893440938d1..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,13 +35,16 @@ fn significant_drop_needs_migration() {
     let t = (SigDrop {}, SigDrop {});
 
     let c = || {
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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
@@ -53,13 +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 affected for closure because of `capture_disjoint_fields`
-    //~| 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 2b141656be2a8d0002349a4afa930af8bdb9136d..1e97ca34d162e3f3c58f4ac27514a3f9701ab15c 100644 (file)
@@ -1,47 +1,53 @@
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $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 | |         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
    |
 LL |     let c = || { let _ = &t; 
 LL |
 LL |
+LL |
 LL |         let _t = t.0;
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $DIR/insignificant_drop_attr_migrations.rs:55: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 | |         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
    |
 LL |     let c = move || { let _ = &t; 
 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));
     }
 }
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/issue-86753.rs b/src/test/ui/closures/2229_closure_analysis/migrations/issue-86753.rs
new file mode 100644 (file)
index 0000000..fce9cac
--- /dev/null
@@ -0,0 +1,34 @@
+// edition:2018
+// check-pass
+
+#![warn(rust_2021_compatibility)]
+
+use std::future::Future;
+
+struct Runtime;
+
+impl Runtime {
+    pub fn block_on<F: Future>(&self, _future: F) -> F::Output {
+        unimplemented!()
+    }
+}
+
+pub fn http<F, Fut>(_func: F)
+where
+    F: Fn() -> Fut,
+    Fut: Future<Output = ()>,
+{
+    let rt = Runtime {};
+    let srv = rt.block_on(async move { serve(move || async move { unimplemented!() }) });
+    let _ = || rt.block_on(async { srv });
+}
+
+pub struct Server<S> {
+    _marker: std::marker::PhantomData<S>,
+}
+
+pub fn serve<S>(_new_service: S) -> Server<S> {
+    unimplemented!()
+}
+
+fn main() { }
index 979c023fc53ace02c460c10ed526bda026266289..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
@@ -17,22 +17,28 @@ impl Drop for Foo {
 fn closure_contains_block() {
     let t = (Foo(0), Foo(0));
     let c = || { let _ = &t; 
-        //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
+        //~^ 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
 
 fn closure_doesnt_contain_block() {
     let t = (Foo(0), Foo(0));
     let c = || { let _ = &t; t.0 };
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
+    //~^ 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 c2a700bd9caa00be1e8b379d7bd29792eec315c3..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
@@ -17,22 +17,28 @@ impl Drop for Foo {
 fn closure_contains_block() {
     let t = (Foo(0), Foo(0));
     let c = || {
-        //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
+        //~^ 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
 
 fn closure_doesnt_contain_block() {
     let t = (Foo(0), Foo(0));
     let c = || t.0;
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
+    //~^ 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 a968d3a093b154b40b219bdb15eee8a723424128..f8f72d1580ca9df798300436768020562789e41e 100644 (file)
@@ -1,34 +1,43 @@
-error: drop order affected for closure because of `capture_disjoint_fields`
+error: changes to closure capture in Rust 2021 will affect drop order
   --> $DIR/migrations_rustfix.rs:19:13
    |
-LL |       let c = || {
-   |  _____________^
-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
    |
 LL |     let c = || { let _ = &t; 
 LL |
 LL |
+LL |
 LL |         let _t = t.0;
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $DIR/migrations_rustfix.rs:30: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
    |
 LL |     let c = || { let _ = &t; t.0 };
index 95463a62185e96f9e6d5b5862a757c4abb5a5605..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 affected for closure because of `capture_disjoint_fields`
+        //~^ 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 fae7fc87c0285e91936eda44ca7cc693854b9763..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 affected for closure because of `capture_disjoint_fields`
+        //~^ 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 bbc8eb9a9cd25064c3899e61f9dee5da66d8b096..6ee0d0d252aba783b11a1747133ca92481651fbe 100644 (file)
@@ -1,27 +1,27 @@
-error: `UnwindSafe`, `RefUnwindSafe` trait implementation affected for closure because of `capture_disjoint_fields`
-  --> $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 5c93fce92507b8c07dcada0e834ef434559c38f8..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 affected for closure because of `capture_disjoint_fields`
-    //~| 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 affected for closure because of `capture_disjoint_fields`
-    //~| 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 fb4af00aa06166b2b9f9cd777ad70fbaec4493e4..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 affected for closure because of `capture_disjoint_fields`
-    //~| 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 affected for closure because of `capture_disjoint_fields`
-    //~| 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 0cd191e2c98c5a3c9c40db94615b81de1d461b9f..5bf73ccc55400edbdc5f1c2a98ab8735cd4608f5 100644 (file)
@@ -1,51 +1,62 @@
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $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 affected for closure because of `capture_disjoint_fields`
-  --> $DIR/precise.rs:42: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 | |     };
-   | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/precise.rs:45:13
    |
+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
    |
 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 1fa0fb3db2f8d9d779dcc182baf812f765d2e0a1..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,15 +23,22 @@ fn test1_all_need_migration() {
     let t2 = (Foo(0), Foo(0));
 
     let c = || { let _ = (&t, &t1, &t2); 
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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
@@ -41,15 +48,20 @@ fn test2_only_precise_paths_need_migration() {
     let t2 = (Foo(0), Foo(0));
 
     let c = || { let _ = (&t, &t1); 
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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.
@@ -57,14 +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 affected for closure because of `capture_disjoint_fields`
-    //~| 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.
@@ -74,13 +89,16 @@ fn test4_type_contains_drop_need_migration() {
     let t = ConstainsDropField(Foo(0), Foo(0));
 
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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,
@@ -89,26 +107,32 @@ fn test5_drop_non_drop_aggregate_need_migration() {
     let t = (Foo(0), Foo(0), 0i32);
 
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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 affected for closure because of `capture_disjoint_fields`
-    //~| 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.
@@ -117,13 +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 affected for closure because of `capture_disjoint_fields`
-    //~| 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();
@@ -133,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 1f0efbe1ebc43313664dcefa08c6bd755db1e3a4..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,15 +23,22 @@ fn test1_all_need_migration() {
     let t2 = (Foo(0), Foo(0));
 
     let c = || {
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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
@@ -41,15 +48,20 @@ fn test2_only_precise_paths_need_migration() {
     let t2 = (Foo(0), Foo(0));
 
     let c = || {
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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.
@@ -57,14 +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 affected for closure because of `capture_disjoint_fields`
-    //~| 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.
@@ -74,13 +89,16 @@ fn test4_type_contains_drop_need_migration() {
     let t = ConstainsDropField(Foo(0), Foo(0));
 
     let c = || {
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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,
@@ -89,26 +107,32 @@ fn test5_drop_non_drop_aggregate_need_migration() {
     let t = (Foo(0), Foo(0), 0i32);
 
     let c = || {
-    //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
-    //~| 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 affected for closure because of `capture_disjoint_fields`
-    //~| 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.
@@ -117,13 +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 affected for closure because of `capture_disjoint_fields`
-    //~| 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();
@@ -133,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 91e75ffb81a96217e392fad1e8592846962c2935..b2b9ae8fd12f51b4274ea3b549821e2443d26b36 100644 (file)
-error: drop order affected for closure because of `capture_disjoint_fields`
+error: changes to closure capture in Rust 2021 will affect drop order
   --> $DIR/significant_drop.rs:25:13
    |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |         let _t = t.0;
-LL | |         let _t1 = t1.0;
-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
    |
 LL |     let c = || { let _ = (&t, &t1, &t2); 
 LL |
 LL |
+LL |
 LL |         let _t = t.0;
-LL |         let _t1 = t1.0;
-LL |         let _t2 = t2.0;
+LL |
  ...
 
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $DIR/significant_drop.rs:43:13
-   |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |         let _t = t.0;
-LL | |         let _t1 = t1.0;
-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
    |
 LL |     let c = || { let _ = (&t, &t1); 
 LL |
 LL |
+LL |
 LL |         let _t = t.0;
-LL |         let _t1 = t1.0;
-LL |         let _t2 = t2;
+LL |
  ...
 
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $DIR/significant_drop.rs:59:13
-   |
-LL |       let c = || {
-   |  _____________^
-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
    |
 LL |     let c = || { let _ = &t; 
 LL |
 LL |
+LL |
 LL |         let _t = t.0;
-LL |         println!("{:?}", t1.1);
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $DIR/significant_drop.rs:76:13
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/significant_drop.rs:91:13
    |
-LL |       let c = || {
-   |  _____________^
-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
    |
 LL |     let c = || { let _ = &t; 
 LL |
 LL |
+LL |
 LL |         let _t = t.0;
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $DIR/significant_drop.rs:91:13
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/significant_drop.rs:109:13
    |
-LL |       let c = || {
-   |  _____________^
-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
    |
 LL |     let c = || { let _ = &t; 
 LL |
 LL |
+LL |
 LL |         let _t = t.0;
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $DIR/significant_drop.rs:104: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 | |         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
    |
 LL |     let c = || { let _ = &t; 
 LL |
 LL |
+LL |
 LL |         let _t = t.1;
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order affected for closure because of `capture_disjoint_fields`
-  --> $DIR/significant_drop.rs:119:13
-   |
-LL |       let c = move || {
-   |  _____________^
-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:143: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
    |
 LL |     let c = move || { let _ = (&t1, &t); 
 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 1c574da5f48bc24bc182d975425e72eaf1226466..0e7abf64fab068cacc48300a876c8e61d9c2c08a 100644 (file)
@@ -1,9 +1,7 @@
+// edition:2021
+
 // Test that move closures drop derefs with `capture_disjoint_fields` enabled.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
 #![feature(rustc_attrs)]
 
 fn simple_move_closure() {
@@ -18,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();
@@ -81,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();
@@ -102,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
     };
 
@@ -114,8 +111,9 @@ fn struct_contains_ref_to_another_struct_3() {
 fn truncate_box_derefs() {
     struct S(i32);
 
-    let b = Box::new(S(10));
 
+    // Content within the box is moved within the closure
+    let b = Box::new(S(10));
     let c = #[rustc_capture_analysis]
     //~^ ERROR: attributes on expressions are experimental
     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
@@ -123,12 +121,93 @@ 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
     };
 
     c();
+
+    // Content within the box is used by a shared ref and the box is the root variable
+    let b = Box::new(S(10));
+
+    let c = #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+    move || {
+    //~^ ERROR: First Pass analysis includes:
+    //~| ERROR: Min Capture analysis includes:
+        println!("{}", b.0);
+        //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
+        //~| NOTE: Min Capture b[] -> ByValue
+    };
+
+    c();
+
+    // Content within the box is used by a shared ref and the box is not the root variable
+    let b = Box::new(S(10));
+    let t = (0, b);
+
+    let c = #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+    move || {
+    //~^ ERROR: First Pass analysis includes:
+    //~| ERROR: Min Capture analysis includes:
+        println!("{}", t.1.0);
+        //~^ 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
+}
+
+// Test that move closures can take ownership of Copy type
+fn returned_closure_owns_copy_type_data() -> impl Fn() -> i32 {
+    let x = 10;
+
+    let c = #[rustc_capture_analysis] move || x;
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+    //~| First Pass analysis includes:
+    //~| NOTE: Capturing x[] -> ImmBorrow
+    //~| Min Capture analysis includes:
+    //~| NOTE: Min Capture x[] -> ByValue
+
+    c
 }
 
 fn main() {
@@ -138,4 +217,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 b91ef4dd85c487118d3ac1509fb9c2fc0c11054d..82ed99f9444d32243ab26af32c74d853ecd94084 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/move_closure.rs:14:17
+  --> $DIR/move_closure.rs:12:17
    |
 LL |     let mut c = #[rustc_capture_analysis]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,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:32:17
+  --> $DIR/move_closure.rs:30:17
    |
 LL |     let mut c = #[rustc_capture_analysis]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,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:53:17
+  --> $DIR/move_closure.rs:51:17
    |
 LL |     let mut c = #[rustc_capture_analysis]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,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:76:17
+  --> $DIR/move_closure.rs:74:17
    |
 LL |     let mut c = #[rustc_capture_analysis]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -35,7 +35,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:98:17
+  --> $DIR/move_closure.rs:96:17
    |
 LL |     let mut c = #[rustc_capture_analysis]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -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:119:13
+  --> $DIR/move_closure.rs:117:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -52,17 +52,77 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/move_closure.rs:3:12
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/move_closure.rs:133:13
+   |
+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:150:13
+   |
+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[E0658]: attributes on expressions are experimental
+  --> $DIR/move_closure.rs:202:13
    |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
+LL |     let c = #[rustc_capture_analysis] move || x;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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:202:39
+   |
+LL |     let c = #[rustc_capture_analysis] move || x;
+   |                                       ^^^^^^^^^
+   |
+note: Capturing x[] -> ImmBorrow
+  --> $DIR/move_closure.rs:202:47
    |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+LL |     let c = #[rustc_capture_analysis] move || x;
+   |                                               ^
+
+error: Min Capture analysis includes:
+  --> $DIR/move_closure.rs:202:39
+   |
+LL |     let c = #[rustc_capture_analysis] move || x;
+   |                                       ^^^^^^^^^
+   |
+note: Min Capture x[] -> ByValue
+  --> $DIR/move_closure.rs:202:47
+   |
+LL |     let c = #[rustc_capture_analysis] move || x;
+   |                                               ^
 
 error: First Pass analysis includes:
-  --> $DIR/move_closure.rs:17:5
+  --> $DIR/move_closure.rs:15:5
    |
 LL | /     move || {
 LL | |
@@ -73,14 +133,14 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(0, 0),(0, 0)] -> ByValue
-  --> $DIR/move_closure.rs:20:9
+note: Capturing t[(0, 0),(0, 0)] -> MutBorrow
+  --> $DIR/move_closure.rs:18:9
    |
 LL |         t.0.0 = "new S".into();
    |         ^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/move_closure.rs:17:5
+  --> $DIR/move_closure.rs:15:5
    |
 LL | /     move || {
 LL | |
@@ -92,13 +152,13 @@ LL | |     };
    | |_____^
    |
 note: Min Capture t[(0, 0),(0, 0)] -> ByValue
-  --> $DIR/move_closure.rs:20:9
+  --> $DIR/move_closure.rs:18:9
    |
 LL |         t.0.0 = "new S".into();
    |         ^^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/move_closure.rs:35:5
+  --> $DIR/move_closure.rs:33:5
    |
 LL | /     move || {
 LL | |
@@ -110,13 +170,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing ref_s[Deref] -> UniqueImmBorrow
-  --> $DIR/move_closure.rs:38:9
+  --> $DIR/move_closure.rs:36:9
    |
 LL |         *ref_s += 10;
    |         ^^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/move_closure.rs:35:5
+  --> $DIR/move_closure.rs:33:5
    |
 LL | /     move || {
 LL | |
@@ -128,13 +188,13 @@ LL | |     };
    | |_____^
    |
 note: Min Capture ref_s[Deref] -> UniqueImmBorrow
-  --> $DIR/move_closure.rs:38:9
+  --> $DIR/move_closure.rs:36:9
    |
 LL |         *ref_s += 10;
    |         ^^^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/move_closure.rs:56:5
+  --> $DIR/move_closure.rs:54:5
    |
 LL | /     move || {
 LL | |
@@ -146,13 +206,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing t[(0, 0),Deref,(0, 0)] -> UniqueImmBorrow
-  --> $DIR/move_closure.rs:59:9
+  --> $DIR/move_closure.rs:57:9
    |
 LL |         t.0.0 = "new s".into();
    |         ^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/move_closure.rs:56:5
+  --> $DIR/move_closure.rs:54:5
    |
 LL | /     move || {
 LL | |
@@ -164,13 +224,13 @@ LL | |     };
    | |_____^
    |
 note: Min Capture t[(0, 0),Deref,(0, 0)] -> UniqueImmBorrow
-  --> $DIR/move_closure.rs:59:9
+  --> $DIR/move_closure.rs:57:9
    |
 LL |         t.0.0 = "new s".into();
    |         ^^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/move_closure.rs:79:5
+  --> $DIR/move_closure.rs:77:5
    |
 LL | /     move || {
 LL | |
@@ -182,13 +242,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
-  --> $DIR/move_closure.rs:82:18
+  --> $DIR/move_closure.rs:80:18
    |
 LL |         let _t = t.0.0;
    |                  ^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/move_closure.rs:79:5
+  --> $DIR/move_closure.rs:77:5
    |
 LL | /     move || {
 LL | |
@@ -199,94 +259,204 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture t[(0, 0),Deref,(0, 0)] -> ImmBorrow
-  --> $DIR/move_closure.rs:82:18
+note: Min Capture t[(0, 0),Deref] -> ImmBorrow
+  --> $DIR/move_closure.rs:80:18
    |
 LL |         let _t = t.0.0;
    |                  ^^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/move_closure.rs:101:5
+  --> $DIR/move_closure.rs:99:5
    |
 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:104:18
-   |
-LL |         let _t = t.0.0;
-   |                  ^^^^^
-note: Capturing t[(0, 0)] -> ByValue
-  --> $DIR/move_closure.rs:104:18
+note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
+  --> $DIR/move_closure.rs:102:18
    |
 LL |         let _t = t.0.0;
    |                  ^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/move_closure.rs:101:5
+  --> $DIR/move_closure.rs:99:5
    |
 LL | /     move || {
 LL | |
 LL | |
 LL | |         let _t = t.0.0;
-...  |
+LL | |
 LL | |
 LL | |     };
    | |_____^
    |
 note: Min Capture t[(0, 0)] -> ByValue
-  --> $DIR/move_closure.rs:104:18
+  --> $DIR/move_closure.rs:102:18
    |
 LL |         let _t = t.0.0;
    |                  ^^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/move_closure.rs:122: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:125:18
-   |
-LL |         let _t = b.0;
-   |                  ^^^
-note: Capturing b[] -> ByValue
-  --> $DIR/move_closure.rs:125: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:122: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:125:18
+  --> $DIR/move_closure.rs:123:18
    |
 LL |         let _t = b.0;
    |                  ^^^
 
-error: aborting due to 18 previous errors; 1 warning emitted
+error: First Pass analysis includes:
+  --> $DIR/move_closure.rs:136:5
+   |
+LL | /     move || {
+LL | |
+LL | |
+LL | |         println!("{}", b.0);
+LL | |
+LL | |
+LL | |     };
+   | |_____^
+   |
+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:136:5
+   |
+LL | /     move || {
+LL | |
+LL | |
+LL | |         println!("{}", b.0);
+LL | |
+LL | |
+LL | |     };
+   | |_____^
+   |
+note: Min Capture b[] -> ByValue
+  --> $DIR/move_closure.rs:139:24
+   |
+LL |         println!("{}", b.0);
+   |                        ^^^
+
+error: First Pass analysis includes:
+  --> $DIR/move_closure.rs:153:5
+   |
+LL | /     move || {
+LL | |
+LL | |
+LL | |         println!("{}", t.1.0);
+LL | |
+LL | |
+LL | |     };
+   | |_____^
+   |
+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:153:5
+   |
+LL | /     move || {
+LL | |
+LL | |
+LL | |         println!("{}", t.1.0);
+LL | |
+LL | |
+LL | |     };
+   | |_____^
+   |
+note: Min Capture t[(1, 0)] -> ByValue
+  --> $DIR/move_closure.rs:156:24
+   |
+LL |         println!("{}", t.1.0);
+   |                        ^^^^^
+
+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 33 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 7d2d4c104d489c8e22f30eb01324b5499cbc0e09..a8a2acfa78d2c74ce95d1f98b272e4b5be5f706a 100644 (file)
@@ -1,7 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
+
 #![feature(rustc_attrs)]
 #![allow(unused)]
 
index 1c8db7952afe714f21a8e537771300171c6bc4cd..29ad1c59198cff9c4f78a96b891f04a0a7ae99b3 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/multilevel-path-1.rs:24:13
+  --> $DIR/multilevel-path-1.rs:22:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/multilevel-path-1.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/multilevel-path-1.rs:27:5
+  --> $DIR/multilevel-path-1.rs:25:5
    |
 LL | /     || {
 LL | |
@@ -29,13 +20,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing w[(0, 0)] -> ImmBorrow
-  --> $DIR/multilevel-path-1.rs:30:19
+  --> $DIR/multilevel-path-1.rs:28:19
    |
 LL |         let wp = &w.p;
    |                   ^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/multilevel-path-1.rs:27:5
+  --> $DIR/multilevel-path-1.rs:25:5
    |
 LL | /     || {
 LL | |
@@ -47,11 +38,11 @@ LL | |     };
    | |_____^
    |
 note: Min Capture w[(0, 0)] -> ImmBorrow
-  --> $DIR/multilevel-path-1.rs:30:19
+  --> $DIR/multilevel-path-1.rs:28:19
    |
 LL |         let wp = &w.p;
    |                   ^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 540e70138e50ed546f89eb4d15d4e52bf56301e6..e21fe318cd105d577c442f381f4c0e2f931c7302 100644 (file)
@@ -1,9 +1,5 @@
-// FIXME(arora-aman) add run-pass once 2229 is implemented
+// edition:2021
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
 #![feature(rustc_attrs)]
 #![allow(unused)]
 
index 37287f6b3bc745f1204effe2384037b5251b3fc1..929cba113146b5569f251643cbb72d9f66f31c79 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/multilevel-path-2.rs:21:13
+  --> $DIR/multilevel-path-2.rs:17:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/multilevel-path-2.rs:3:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/multilevel-path-2.rs:24:5
+  --> $DIR/multilevel-path-2.rs:20:5
    |
 LL | /     || {
 LL | |
@@ -29,13 +20,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing w[(0, 0),(0, 0)] -> ImmBorrow
-  --> $DIR/multilevel-path-2.rs:27:24
+  --> $DIR/multilevel-path-2.rs:23:24
    |
 LL |         println!("{}", w.p.x);
    |                        ^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/multilevel-path-2.rs:24:5
+  --> $DIR/multilevel-path-2.rs:20:5
    |
 LL | /     || {
 LL | |
@@ -47,11 +38,11 @@ LL | |     };
    | |_____^
    |
 note: Min Capture w[(0, 0),(0, 0)] -> ImmBorrow
-  --> $DIR/multilevel-path-2.rs:27:24
+  --> $DIR/multilevel-path-2.rs:23:24
    |
 LL |         println!("{}", w.p.x);
    |                        ^^^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 88620550f2e7c97577ac0037c3a3a9dfd7573450..f6775b3a3a5ac4a827db7e9f11250545df437de0 100644 (file)
@@ -1,9 +1,5 @@
-// FIXME(arora-aman) add run-pass once 2229 is implemented
+// edition:2021
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
 #![feature(rustc_attrs)]
 
 struct Point {
index 21147be3f1d0896d6527293e9f78f0b9a6bca112..013bc74e67e1ecdf2d09a4b5d7eb3486e7900521 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/nested-closure.rs:23:18
+  --> $DIR/nested-closure.rs:19:18
    |
 LL |     let mut c1 = #[rustc_capture_analysis]
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     let mut c1 = #[rustc_capture_analysis]
    = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
 
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/nested-closure.rs:33:22
+  --> $DIR/nested-closure.rs:29:22
    |
 LL |         let mut c2 = #[rustc_capture_analysis]
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,51 +16,42 @@ LL |         let mut c2 = #[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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/nested-closure.rs:3:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/nested-closure.rs:36:9
+  --> $DIR/nested-closure.rs:32:9
    |
 LL |         || p.y += incr;
    |         ^^^^^^^^^^^^^^
    |
 note: Capturing p[(1, 0)] -> MutBorrow
-  --> $DIR/nested-closure.rs:36:12
+  --> $DIR/nested-closure.rs:32:12
    |
 LL |         || p.y += incr;
    |            ^^^
 note: Capturing incr[] -> ImmBorrow
-  --> $DIR/nested-closure.rs:36:19
+  --> $DIR/nested-closure.rs:32:19
    |
 LL |         || p.y += incr;
    |                   ^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/nested-closure.rs:36:9
+  --> $DIR/nested-closure.rs:32:9
    |
 LL |         || p.y += incr;
    |         ^^^^^^^^^^^^^^
    |
 note: Min Capture p[(1, 0)] -> MutBorrow
-  --> $DIR/nested-closure.rs:36:12
+  --> $DIR/nested-closure.rs:32:12
    |
 LL |         || p.y += incr;
    |            ^^^
 note: Min Capture incr[] -> ImmBorrow
-  --> $DIR/nested-closure.rs:36:19
+  --> $DIR/nested-closure.rs:32:19
    |
 LL |         || p.y += incr;
    |                   ^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/nested-closure.rs:26:5
+  --> $DIR/nested-closure.rs:22:5
    |
 LL | /     || {
 LL | |
@@ -72,18 +63,18 @@ LL | |     };
    | |_____^
    |
 note: Capturing p[(0, 0)] -> ImmBorrow
-  --> $DIR/nested-closure.rs:29:24
+  --> $DIR/nested-closure.rs:25:24
    |
 LL |         println!("{}", p.x);
    |                        ^^^
 note: Capturing p[(1, 0)] -> MutBorrow
-  --> $DIR/nested-closure.rs:36:12
+  --> $DIR/nested-closure.rs:32:12
    |
 LL |         || p.y += incr;
    |            ^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/nested-closure.rs:26:5
+  --> $DIR/nested-closure.rs:22:5
    |
 LL | /     || {
 LL | |
@@ -95,16 +86,16 @@ LL | |     };
    | |_____^
    |
 note: Min Capture p[(0, 0)] -> ImmBorrow
-  --> $DIR/nested-closure.rs:29:24
+  --> $DIR/nested-closure.rs:25:24
    |
 LL |         println!("{}", p.x);
    |                        ^^^
 note: Min Capture p[(1, 0)] -> MutBorrow
-  --> $DIR/nested-closure.rs:36:12
+  --> $DIR/nested-closure.rs:32:12
    |
 LL |         || p.y += incr;
    |            ^^^
 
-error: aborting due to 6 previous errors; 1 warning emitted
+error: aborting due to 6 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);
+}
index 16acd2f3206c91ec7c29d7582f5b6312d4b128db..0c10319314a6f10555491cd98b2fd47545225d92 100644 (file)
@@ -1,7 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
+
 #![feature(rustc_attrs)]
 
 struct Point {
index 3c8d07ed9ba67b46bb2b667094e86fabfd3c2e5e..124b7bf6fe27052c8e77f6ecbfedf3ac7862252d 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/path-with-array-access.rs:25:13
+  --> $DIR/path-with-array-access.rs:23:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/path-with-array-access.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/path-with-array-access.rs:28:5
+  --> $DIR/path-with-array-access.rs:26:5
    |
 LL | /     || {
 LL | |
@@ -29,13 +20,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing pent[(0, 0)] -> ImmBorrow
-  --> $DIR/path-with-array-access.rs:31:24
+  --> $DIR/path-with-array-access.rs:29:24
    |
 LL |         println!("{}", pent.points[5].x);
    |                        ^^^^^^^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/path-with-array-access.rs:28:5
+  --> $DIR/path-with-array-access.rs:26:5
    |
 LL | /     || {
 LL | |
@@ -47,11 +38,11 @@ LL | |     };
    | |_____^
    |
 note: Min Capture pent[(0, 0)] -> ImmBorrow
-  --> $DIR/path-with-array-access.rs:31:24
+  --> $DIR/path-with-array-access.rs:29:24
    |
 LL |         println!("{}", pent.points[5].x);
    |                        ^^^^^^^^^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 609a11a578ae81eca6f8b79c7a18e77a5195ff0c..0f288ffa95a872a0936fca437c765bbabb5ba0ec 100644 (file)
@@ -1,7 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| `#[warn(incomplete_features)]` on by default
-//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
+
 #![feature(never_type)]
 
 // Should fake read the discriminant and throw an error
index c225abb58b7311a625fb70332510bb5f9eb57fdf..45641ea3de3e0812b30da2653a18bdf037830530 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/pattern-matching-should-fail.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/pattern-matching-should-fail.rs:72:23
+  --> $DIR/pattern-matching-should-fail.rs:70:23
    |
 LL |     let c1 = || match x { };
    |                       ^
@@ -17,13 +8,13 @@ LL |     let c1 = || match x { };
    = note: the matched value is of type `u8`
 
 error[E0381]: use of possibly-uninitialized variable: `x`
-  --> $DIR/pattern-matching-should-fail.rs:10:23
+  --> $DIR/pattern-matching-should-fail.rs:8:23
    |
 LL |     let c1 = || match x { };
    |                       ^ use of possibly-uninitialized `x`
 
 error[E0381]: borrow of possibly-uninitialized variable: `x`
-  --> $DIR/pattern-matching-should-fail.rs:17:14
+  --> $DIR/pattern-matching-should-fail.rs:15:14
    |
 LL |     let c2 = || match x { _ => () };
    |              ^^       - borrow occurs due to use in closure
@@ -31,7 +22,7 @@ LL |     let c2 = || match x { _ => () };
    |              use of possibly-uninitialized `x`
 
 error[E0381]: borrow of possibly-uninitialized variable: `variant`
-  --> $DIR/pattern-matching-should-fail.rs:29:13
+  --> $DIR/pattern-matching-should-fail.rs:27:13
    |
 LL |     let c = || {
    |             ^^ use of possibly-uninitialized `variant`
@@ -40,7 +31,7 @@ LL |         match variant {
    |               ------- borrow occurs due to use in closure
 
 error[E0381]: borrow of possibly-uninitialized variable: `variant`
-  --> $DIR/pattern-matching-should-fail.rs:41:13
+  --> $DIR/pattern-matching-should-fail.rs:39:13
    |
 LL |     let c = || {
    |             ^^ use of possibly-uninitialized `variant`
@@ -49,24 +40,24 @@ LL |         match variant {
    |               ------- borrow occurs due to use in closure
 
 error[E0381]: use of possibly-uninitialized variable: `g`
-  --> $DIR/pattern-matching-should-fail.rs:57:15
+  --> $DIR/pattern-matching-should-fail.rs:55:15
    |
 LL |         match g { };
    |               ^ use of possibly-uninitialized `g`
 
 error[E0381]: use of possibly-uninitialized variable: `t`
-  --> $DIR/pattern-matching-should-fail.rs:60:19
+  --> $DIR/pattern-matching-should-fail.rs:58:19
    |
 LL |             match t { };
    |                   ^ use of possibly-uninitialized `t`
 
 error[E0381]: use of possibly-uninitialized variable: `x`
-  --> $DIR/pattern-matching-should-fail.rs:72:23
+  --> $DIR/pattern-matching-should-fail.rs:70:23
    |
 LL |     let c1 = || match x { };
    |                       ^ use of possibly-uninitialized `x`
 
-error: aborting due to 8 previous errors; 1 warning emitted
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0004, E0381.
 For more information about an error, try `rustc --explain E0004`.
index 0a877dd366c7fc93952567df43b1f0f04b9caaa1..56f5ac44db068735218de1728f56d4608d178a50 100644 (file)
@@ -1,7 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
+
 #![feature(rustc_attrs)]
 
 // Should capture the discriminant since a variant of a multivariant enum is
index ad3e96a5753e337c58e0c6ecb66184b83f12c5ed..460813333952bd0ae18d76f84fae6c2ae99400f7 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/patterns-capture-analysis.rs:12:14
+  --> $DIR/patterns-capture-analysis.rs:10:14
    |
 LL |     let c =  #[rustc_capture_analysis]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,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/patterns-capture-analysis.rs:33:14
+  --> $DIR/patterns-capture-analysis.rs:31:14
    |
 LL |     let c =  #[rustc_capture_analysis]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,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/patterns-capture-analysis.rs:54:14
+  --> $DIR/patterns-capture-analysis.rs:52:14
    |
 LL |     let c =  #[rustc_capture_analysis]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,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/patterns-capture-analysis.rs:70:14
+  --> $DIR/patterns-capture-analysis.rs:68:14
    |
 LL |     let c =  #[rustc_capture_analysis]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -35,7 +35,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/patterns-capture-analysis.rs:92:14
+  --> $DIR/patterns-capture-analysis.rs:90:14
    |
 LL |     let c =  #[rustc_capture_analysis]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,7 +44,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/patterns-capture-analysis.rs:116:14
+  --> $DIR/patterns-capture-analysis.rs:114:14
    |
 LL |     let c =  #[rustc_capture_analysis]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -52,17 +52,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/patterns-capture-analysis.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:16:5
+  --> $DIR/patterns-capture-analysis.rs:14:5
    |
 LL | /     || {
 LL | |
@@ -74,13 +65,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:19:15
+  --> $DIR/patterns-capture-analysis.rs:17:15
    |
 LL |         match variant {
    |               ^^^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:16:5
+  --> $DIR/patterns-capture-analysis.rs:14:5
    |
 LL | /     || {
 LL | |
@@ -92,13 +83,13 @@ LL | |     };
    | |_____^
    |
 note: Min Capture variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:19:15
+  --> $DIR/patterns-capture-analysis.rs:17:15
    |
 LL |         match variant {
    |               ^^^^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:36:5
+  --> $DIR/patterns-capture-analysis.rs:34:5
    |
 LL | /     || {
 LL | |
@@ -109,7 +100,7 @@ LL | |     };
    | |_____^
 
 error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:57:5
+  --> $DIR/patterns-capture-analysis.rs:55:5
    |
 LL | /     || {
 LL | |
@@ -120,7 +111,7 @@ LL | |     };
    | |_____^
 
 error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:73:5
+  --> $DIR/patterns-capture-analysis.rs:71:5
    |
 LL | /     || {
 LL | |
@@ -132,18 +123,18 @@ LL | |     };
    | |_____^
    |
 note: Capturing variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:76:15
+  --> $DIR/patterns-capture-analysis.rs:74:15
    |
 LL |         match variant {
    |               ^^^^^^^
 note: Capturing variant[(0, 0)] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:76:15
+  --> $DIR/patterns-capture-analysis.rs:74:15
    |
 LL |         match variant {
    |               ^^^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:73:5
+  --> $DIR/patterns-capture-analysis.rs:71:5
    |
 LL | /     || {
 LL | |
@@ -155,13 +146,13 @@ LL | |     };
    | |_____^
    |
 note: Min Capture variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:76:15
+  --> $DIR/patterns-capture-analysis.rs:74:15
    |
 LL |         match variant {
    |               ^^^^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:95:5
+  --> $DIR/patterns-capture-analysis.rs:93:5
    |
 LL | /     || {
 LL | |
@@ -172,7 +163,7 @@ LL | |     };
    | |_____^
 
 error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:119:5
+  --> $DIR/patterns-capture-analysis.rs:117:5
    |
 LL | /     || {
 LL | |
@@ -184,13 +175,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:122:15
+  --> $DIR/patterns-capture-analysis.rs:120:15
    |
 LL |         match variant {
    |               ^^^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:119:5
+  --> $DIR/patterns-capture-analysis.rs:117:5
    |
 LL | /     || {
 LL | |
@@ -202,11 +193,11 @@ LL | |     };
    | |_____^
    |
 note: Min Capture variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:122:15
+  --> $DIR/patterns-capture-analysis.rs:120:15
    |
 LL |         match variant {
    |               ^^^^^^^
 
-error: aborting due to 15 previous errors; 1 warning emitted
+error: aborting due to 15 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 2b9ef2a76bba74cc739eae4c95443262d1af82b1..7d472ad020f29444667b73af854a43dce327b785 100644 (file)
@@ -1,7 +1,4 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| `#[warn(incomplete_features)]` on by default
-//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
 
 #![feature(rustc_attrs)]
 
index 0517dd04b6f44696a483ff4cd1f4f4ad7bed3a50..405f66210aa55f43abfd4b6a9b610ecc0c54ea37 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/repr_packed.rs:16:17
+  --> $DIR/repr_packed.rs:13:17
    |
 LL |     let mut c = #[rustc_capture_analysis]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,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/repr_packed.rs:47:17
+  --> $DIR/repr_packed.rs:44:17
    |
 LL |     let mut c = #[rustc_capture_analysis]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,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/repr_packed.rs:81:13
+  --> $DIR/repr_packed.rs:78:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -25,17 +25,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/repr_packed.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/repr_packed.rs:19:5
+  --> $DIR/repr_packed.rs:16:5
    |
 LL | /     || {
 LL | |
@@ -47,18 +38,18 @@ LL | |     };
    | |_____^
    |
 note: Capturing foo[(0, 0)] -> ImmBorrow
-  --> $DIR/repr_packed.rs:22:24
+  --> $DIR/repr_packed.rs:19:24
    |
 LL |         let z1: &u8 = &foo.x;
    |                        ^^^^^
 note: Capturing foo[(1, 0)] -> MutBorrow
-  --> $DIR/repr_packed.rs:25:32
+  --> $DIR/repr_packed.rs:22:32
    |
 LL |         let z2: &mut u8 = &mut foo.y;
    |                                ^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/repr_packed.rs:19:5
+  --> $DIR/repr_packed.rs:16:5
    |
 LL | /     || {
 LL | |
@@ -70,18 +61,18 @@ LL | |     };
    | |_____^
    |
 note: Min Capture foo[(0, 0)] -> ImmBorrow
-  --> $DIR/repr_packed.rs:22:24
+  --> $DIR/repr_packed.rs:19:24
    |
 LL |         let z1: &u8 = &foo.x;
    |                        ^^^^^
 note: Min Capture foo[(1, 0)] -> MutBorrow
-  --> $DIR/repr_packed.rs:25:32
+  --> $DIR/repr_packed.rs:22:32
    |
 LL |         let z2: &mut u8 = &mut foo.y;
    |                                ^^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/repr_packed.rs:50:5
+  --> $DIR/repr_packed.rs:47:5
    |
 LL | /     || {
 LL | |
@@ -93,13 +84,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing foo[] -> MutBorrow
-  --> $DIR/repr_packed.rs:54:33
+  --> $DIR/repr_packed.rs:51:33
    |
 LL |         let z2: &mut u16 = &mut foo.y;
    |                                 ^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/repr_packed.rs:50:5
+  --> $DIR/repr_packed.rs:47:5
    |
 LL | /     || {
 LL | |
@@ -111,13 +102,13 @@ LL | |     };
    | |_____^
    |
 note: Min Capture foo[] -> MutBorrow
-  --> $DIR/repr_packed.rs:54:33
+  --> $DIR/repr_packed.rs:51:33
    |
 LL |         let z2: &mut u16 = &mut foo.y;
    |                                 ^^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/repr_packed.rs:84:5
+  --> $DIR/repr_packed.rs:81:5
    |
 LL | /     || {
 LL | |
@@ -129,18 +120,18 @@ LL | |     };
    | |_____^
    |
 note: Capturing foo[] -> ImmBorrow
-  --> $DIR/repr_packed.rs:87:24
+  --> $DIR/repr_packed.rs:84:24
    |
 LL |         println!("{}", foo.x);
    |                        ^^^^^
 note: Capturing foo[(0, 0)] -> ByValue
-  --> $DIR/repr_packed.rs:91:18
+  --> $DIR/repr_packed.rs:88:18
    |
 LL |         let _z = foo.x;
    |                  ^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/repr_packed.rs:84:5
+  --> $DIR/repr_packed.rs:81:5
    |
 LL | /     || {
 LL | |
@@ -152,7 +143,7 @@ LL | |     };
    | |_____^
    |
 note: Min Capture foo[] -> ByValue
-  --> $DIR/repr_packed.rs:87:24
+  --> $DIR/repr_packed.rs:84:24
    |
 LL |         println!("{}", foo.x);
    |                        ^^^^^ foo[] used here
@@ -160,6 +151,6 @@ LL |         println!("{}", foo.x);
 LL |         let _z = foo.x;
    |                  ^^^^^ foo[] captured as ByValue here
 
-error: aborting due to 9 previous errors; 1 warning emitted
+error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 3a66399d02899bb606e2238f4bab28094ab0d41b..73aca288faa88b1267dc7b79f77ced534275ba23 100644 (file)
@@ -1,13 +1,8 @@
+// edition:2021
 // run-pass
 
 // Test precise capture when using boxes
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
-
-
 struct MetaData { x: String, name: String }
 struct Data { m: MetaData }
 struct BoxedData(Box<Data>);
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/box.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/box.stderr
deleted file mode 100644 (file)
index 9883c01..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/box.rs:5:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index 9a93e6cf1e1efd787734c446d3f9105281838ea6..2c828aed528bfcb98c09731835fb5c1dc968a091 100644 (file)
@@ -1,11 +1,9 @@
+// edition:2021
 // run-pass
 
 // Test that ByValue captures compile sucessefully especially when the captures are
 // derefenced within the closure.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-
 #[derive(Debug, Default)]
 struct SomeLargeType;
 struct MuchLargerType([SomeLargeType; 32]);
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.stderr
deleted file mode 100644 (file)
index 98715c6..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/by_value.rs:6:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index 2c359519b769b4a745dbd28fd8abbb658b8e5375..3cb1eb32952d84fe6abd5096dd79ee2059aeff49 100644 (file)
@@ -1,13 +1,9 @@
+// edition:2021
 // run-pass
 
 // Test that we can immutably borrow field of an instance of a structure from within a closure,
 // while having a mutable borrow to another field of the same instance outside the closure.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
-
 struct Point {
     x: i32,
     y: i32,
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.stderr
deleted file mode 100644 (file)
index 9b0dea7..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/capture-disjoint-field-struct.rs:6:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index 2c6679feabe46a795656921bb2ccf3fb740e8ce2..0f79b7ae7b8c623eb98849cdd0415e9f7b9e592f 100644 (file)
@@ -1,12 +1,9 @@
+// edition:2021
 // run-pass
 
 // Test that we can mutate an element of a tuple from within a closure
 // while immutably borrowing another element of the same tuple outside the closure.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
 #![feature(rustc_attrs)]
 
 fn main() {
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.stderr
deleted file mode 100644 (file)
index 28d0915..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/capture-disjoint-field-tuple-mut.rs:6:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index 52f5cef9f01c686d47ef5dfbb19947476544c465..81f0328b9ba5ff0bd2864764c92805fa9f25c442 100644 (file)
@@ -1,12 +1,9 @@
+// edition:2021
 // run-pass
 
 // Test that we can immutably borrow an element of a tuple from within a closure,
 // while having a mutable borrow to another element of the same tuple outside the closure.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
 #![feature(rustc_attrs)]
 
 fn main() {
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.stderr
deleted file mode 100644 (file)
index 4fb37f8..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/capture-disjoint-field-tuple.rs:6:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index eaea0dbfb5e8c4d4f141a386808f7f17bade1891..cea02fbe15d34978a16678420693732dceb28c4d 100644 (file)
@@ -1,6 +1,5 @@
+// edition:2021
 //check-pass
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
 
 fn test1() {
     let foo : [Vec<u8>; 3] = ["String".into(), "String".into(), "String".into()];
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.stderr
deleted file mode 100644 (file)
index 2c17a18..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/capture_with_wildcard_match.rs:2:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index 3ad083a92d569690522072d3b28c47ec83eecdaf..5c278bff90bb0acafeacd70dd3d5128b1a314111 100644 (file)
@@ -1,6 +1,5 @@
-//check-pass
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+// edition:2021
+// check-pass
 #![warn(unused)]
 
 fn main() {
index c4abf934123b376e9b9efd669c167f06afb6b43f..40274c88318c3d4ff6ddda58216f55997a2f903c 100644 (file)
@@ -1,30 +1,21 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/destructure-pattern-closure-within-closure.rs:2:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 warning: unused variable: `t2`
-  --> $DIR/destructure-pattern-closure-within-closure.rs:14:21
+  --> $DIR/destructure-pattern-closure-within-closure.rs:13:21
    |
 LL |             let (_, t2) = t;
    |                     ^^ help: if this is intentional, prefix it with an underscore: `_t2`
    |
 note: the lint level is defined here
-  --> $DIR/destructure-pattern-closure-within-closure.rs:4:9
+  --> $DIR/destructure-pattern-closure-within-closure.rs:3:9
    |
 LL | #![warn(unused)]
    |         ^^^^^^
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
 
 warning: unused variable: `g2`
-  --> $DIR/destructure-pattern-closure-within-closure.rs:11:17
+  --> $DIR/destructure-pattern-closure-within-closure.rs:10:17
    |
 LL |         let (_, g2) = g;
    |                 ^^ help: if this is intentional, prefix it with an underscore: `_g2`
 
-warning: 3 warnings emitted
+warning: 2 warnings emitted
 
index 65527648b2c991e7f185bdadd27434b25e91fb72..07adbee03f968c71009f644ee0793148e72ff743 100644 (file)
@@ -1,6 +1,5 @@
-//check-pass
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+// edition:2021
+// check-pass
 #![warn(unused)]
 
 struct Point {
index fcfe9ee95f185726d7377bd894c864dc2e5cae49..6523f2b34d537c076a53d36e20a5b633c06b6878 100644 (file)
@@ -1,66 +1,57 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/destructure_patterns.rs:2:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 warning: unused variable: `t1`
-  --> $DIR/destructure_patterns.rs:15:14
+  --> $DIR/destructure_patterns.rs:14:14
    |
 LL |         let (t1, t2) = t;
    |              ^^ help: if this is intentional, prefix it with an underscore: `_t1`
    |
 note: the lint level is defined here
-  --> $DIR/destructure_patterns.rs:4:9
+  --> $DIR/destructure_patterns.rs:3:9
    |
 LL | #![warn(unused)]
    |         ^^^^^^
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
 
 warning: unused variable: `t2`
-  --> $DIR/destructure_patterns.rs:15:18
+  --> $DIR/destructure_patterns.rs:14:18
    |
 LL |         let (t1, t2) = t;
    |                  ^^ help: if this is intentional, prefix it with an underscore: `_t2`
 
 warning: unused variable: `t1`
-  --> $DIR/destructure_patterns.rs:27:14
+  --> $DIR/destructure_patterns.rs:26:14
    |
 LL |         let (t1, _) = t;
    |              ^^ help: if this is intentional, prefix it with an underscore: `_t1`
 
 warning: unused variable: `t2`
-  --> $DIR/destructure_patterns.rs:38:17
+  --> $DIR/destructure_patterns.rs:37:17
    |
 LL |         let (_, t2) = t;
    |                 ^^ help: if this is intentional, prefix it with an underscore: `_t2`
 
 warning: unused variable: `t`
-  --> $DIR/destructure_patterns.rs:46:9
+  --> $DIR/destructure_patterns.rs:45:9
    |
 LL |     let t = (String::from("Hello"), String::from("World"));
    |         ^ help: if this is intentional, prefix it with an underscore: `_t`
 
 warning: unused variable: `x`
-  --> $DIR/destructure_patterns.rs:92:21
+  --> $DIR/destructure_patterns.rs:91:21
    |
 LL |         let Point { x, y } = p;
    |                     ^ help: try ignoring the field: `x: _`
 
 warning: unused variable: `x`
-  --> $DIR/destructure_patterns.rs:84:9
+  --> $DIR/destructure_patterns.rs:83:9
    |
 LL |     let x = 0;
    |         ^ help: if this is intentional, prefix it with an underscore: `_x`
 
 warning: unused variable: `tup`
-  --> $DIR/destructure_patterns.rs:86:9
+  --> $DIR/destructure_patterns.rs:85:9
    |
 LL |     let tup = (1, 2);
    |         ^^^ help: if this is intentional, prefix it with an underscore: `_tup`
 
-warning: 9 warnings emitted
+warning: 8 warnings emitted
 
index 3f8e197b7837d407fdb7ed4209ec4749508088f8..88a9816a05263b4024f4f18b299c2fb52da371aa 100644 (file)
@@ -1,10 +1,6 @@
+// edition:2021
 // run-pass
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
-
 // Tests that if a closure uses indivual fields of the same object
 // then that case is handled properly.
 
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.stderr
deleted file mode 100644 (file)
index bba90f8..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/disjoint-capture-in-same-closure.rs:3:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index dae50854d82fb1b8982515f0bbb3f6da7e4cca5b..477fdd613f521a1e4556baf3d2be0cbbc15c26e4 100644 (file)
@@ -1,6 +1,5 @@
-//check-pass
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+// edition:2021
+// check-pass
 #![feature(rustc_attrs)]
 
 fn main() {
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.stderr
deleted file mode 100644 (file)
index 7f81187..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/drop_then_use_fake_reads.rs:2:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/edition.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/edition.rs
new file mode 100644 (file)
index 0000000..20bbe1d
--- /dev/null
@@ -0,0 +1,23 @@
+// edition:2021
+// run-pass
+
+// Test that edition 2021 enables disjoint capture by default.
+
+struct Point {
+    x: i32,
+    y: i32,
+}
+
+fn main() {
+    let mut p = Point { x: 10, y: 10 };
+
+    let c = || {
+        println!("{}", p.x);
+    };
+
+    // `c` should only capture `p.x`, therefore mutating `p.y` is allowed.
+    let py = &mut p.y;
+
+    c();
+    *py = 20;
+}
index 8c12593430ef0c38240f5fc96afa8c01da7b0171..e19f5ff1bae4dfc1e7cd450c6fc256e40b9b48ae 100644 (file)
@@ -1,12 +1,8 @@
+// edition:2021
 // run-pass
 
 // Test disjoint capture within an impl block
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
-
 struct Filter {
     div: i32,
 }
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.stderr
deleted file mode 100644 (file)
index 6930e18..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/filter-on-struct-member.rs:5:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index e89cf4550c15475f1772b2dc8d0d20250d0552e7..1286613cb13badccde26aaae09859b46f65795fa 100644 (file)
@@ -1,13 +1,9 @@
+// edition:2021
 // run-pass
 
 // Test that functional record update/struct update syntax works inside
 // a closure when the feature `capture_disjoint_fields` is enabled.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
-
 #[derive(Clone)]
 struct S {
     a: String,
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr
deleted file mode 100644 (file)
index 7ed73ab..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/fru_syntax.rs:6:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index 9c086fe4bdfe780650ab2c6f2717a5142e4b6f03..d2375aa69ec257ad4cec1d0e068895f8d2782773 100644 (file)
@@ -1,6 +1,5 @@
+// edition:2021
 //check-pass
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
 #![warn(unused)]
 #![feature(rustc_attrs)]
 #![feature(btree_drain_filter)]
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.stderr
deleted file mode 100644 (file)
index bc046ec..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/lit-pattern-matching-with-methods.rs:2:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index afaafbda018774feb36039447a98ec1feae56170..e1b61e85ec1927d18444a778bcb188820ce67bee 100644 (file)
@@ -1,9 +1,9 @@
+// edition:2021
 // run-pass
 
 // Test that move closures compile properly with `capture_disjoint_fields` enabled.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+#![allow(unused)]
 
 fn simple_ref() {
     let mut s = 10;
@@ -94,6 +94,15 @@ fn data_moved_but_not_fn_once() {
     c();
 }
 
+// Test that move closures can take ownership of Copy type
+fn returned_closure_owns_copy_type_data() -> impl Fn() -> i32 {
+    let x = 10;
+
+    let c = move || x;
+
+    c
+}
+
 fn main() {
     simple_ref();
     struct_contains_ref_to_another_struct();
@@ -102,4 +111,6 @@ fn main() {
 
     disjoint_via_ref();
     data_moved_but_not_fn_once();
+
+    returned_closure_owns_copy_type_data();
 }
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.stderr
deleted file mode 100644 (file)
index c1d8ba5..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/move_closure.rs:5:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index 142c156bd56e723005c80a28ab76ef8e4e3936ab..b8e464031813bd42a71e8966570c7fe8e96827ab 100644 (file)
@@ -1,3 +1,4 @@
+// edition:2021
 // run-pass
 
 // Test that closures can catpure paths that are more precise than just one level
@@ -7,10 +8,6 @@
 // while being able to mutate another path outside the closure, where the two paths are disjoint
 // after applying two projections on the root variable.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
 #![allow(unused)]
 
 struct Point {
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.stderr
deleted file mode 100644 (file)
index 94b8775..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/multilevel-path-1.rs:10:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index d8f7d55d5aa7be204c82e07ae715b2c96866ab9f..11a324d8a34e361c7da8db413e55b22ba87ad153 100644 (file)
@@ -1,9 +1,6 @@
+// edition:2021
 // run-pass
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
 #![allow(unused)]
 
 // If the closures can handle such precison we should be able to read one path in the closure
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.stderr
deleted file mode 100644 (file)
index 100a0e1..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/multilevel-path-2.rs:3:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index fc3d48ec45810545141efda87cfa047764300b91..8fc0efb60b755e1d681005c86e5f86a1efc00563 100644 (file)
@@ -1,9 +1,6 @@
+// edition:2021
 // run-pass
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
 #![allow(unused)]
 
 // Test that when `capture_disjoint_fields` is enabled we can read a path
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.stderr
deleted file mode 100644 (file)
index cf5be6a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/multilevel-path-3.rs:3:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index 315622443c3cc83da55341277c9cf7a3e66ff6cc..9f0c4d96aa5d923429db5dbce51a837f33d702a3 100644 (file)
@@ -1,11 +1,9 @@
+// edition:2021
 // run-pass
 
 // Test that we can mutate a place through a mut-borrow
 // that is captured by the closure
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-
 // Check that we can mutate when one deref is required
 fn mut_ref_1() {
     let mut x = String::new();
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.stderr
deleted file mode 100644 (file)
index 4b37a0b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/mut_ref.rs:6:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index 2dba923647a2e6f4044a08ad8f467af054e77b98..bb784774b8cd439180a05d2a6e12e15db57b6982 100644 (file)
@@ -1,3 +1,4 @@
+// edition:2021
 // run-pass
 
 // Test that we can mutate a place through a mut-borrow
@@ -6,9 +7,6 @@
 // More specifically we test that the if the mutable reference isn't root variable of a capture
 // but rather accessed while acessing the precise capture.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-
 fn mut_tuple() {
     let mut t = (10, 10);
 
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.stderr
deleted file mode 100644 (file)
index 418ab29..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/mut_ref_struct_mem.rs:9:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index 238580929ef110a0705c103048ea446a4ccfd644..a80b40bb46957b8f871af21d720e43d1c326f691 100644 (file)
@@ -1,12 +1,8 @@
+// edition:2021
 // run-pass
 
 // Test whether if we can do precise capture when using nested clsoure.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
-
 struct Point {
     x: i32,
     y: i32,
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.stderr
deleted file mode 100644 (file)
index 293aa82..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/nested-closure.rs:5:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index d260a448926d63cf7b2f1be0c53254e6f76923a2..045fe78040a922e330fb926908e33ba64ec74f9a 100644 (file)
@@ -1,6 +1,5 @@
+// edition:2021
 //check-pass
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
 #![warn(unused)]
 #![feature(rustc_attrs)]
 
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.stderr
deleted file mode 100644 (file)
index 3e4303a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/struct-pattern-matching-with-methods.rs:2:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index b3bee79254ec4b2cc9ea2a2af877fb27719ba3d6..f3f44433ccf3dbc9b4934659251c3f36643ecdea 100644 (file)
@@ -1,6 +1,5 @@
+// edition:2021
 //check-pass
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
 
 #[derive(Copy, Clone)]
 enum PointType {
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.stderr
deleted file mode 100644 (file)
index ded0e37..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/tuple-struct-pattern-matching-with-methods.rs:2:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index f6e9862b26c11d7fafb2af139c1b1534e1d42444..8e4f91c27e224d5c82405b91621700c7193fd917 100644 (file)
@@ -1,10 +1,8 @@
+// edition:2021
 // run-pass
 
 // Test that we can use raw ptrs when using `capture_disjoint_fields`.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-
 #[derive(Debug)]
 struct S {
     s: String,
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.stderr
deleted file mode 100644 (file)
index c64c8b7..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unsafe_ptr.rs:5:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index 0e6da8f4f18894c2205ca7e1ff3d32b62391edfd..0206927cc59e948a9de617ce884fcc1f28534c6a 100644 (file)
@@ -1,6 +1,5 @@
+// edition:2021
 //check-pass
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
 #![feature(rustc_attrs)]
 
 fn main() {
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.stderr
deleted file mode 100644 (file)
index 7d16d77..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/use_of_mutable_borrow_and_fake_reads.rs:2:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
-warning: 1 warning emitted
-
index a6b5e12d2ed78e4d6f562d00794764af78f67f10..563095d440d24e9274602016cbce32357e66a707 100644 (file)
@@ -1,9 +1,5 @@
-// FIXME(arora-aman) add run-pass once 2229 is implemented
+// edition:2021
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
 #![feature(rustc_attrs)]
 
 // Test to ensure that min analysis meets capture kind for all paths captured.
index cbbc8792199153639bdd13bb1074e16e5b299074..05d79797ab3c0e2e632bee2cb555859f03d59a3b 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/simple-struct-min-capture.rs:27:17
+  --> $DIR/simple-struct-min-capture.rs:23:17
    |
 LL |     let mut c = #[rustc_capture_analysis]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,17 +7,8 @@ LL |     let mut 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/simple-struct-min-capture.rs:3:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/simple-struct-min-capture.rs:30:5
+  --> $DIR/simple-struct-min-capture.rs:26:5
    |
 LL | /     || {
 LL | |
@@ -29,18 +20,18 @@ LL | |     };
    | |_____^
    |
 note: Capturing p[(0, 0)] -> MutBorrow
-  --> $DIR/simple-struct-min-capture.rs:33:9
+  --> $DIR/simple-struct-min-capture.rs:29:9
    |
 LL |         p.x += 10;
    |         ^^^
 note: Capturing p[] -> ImmBorrow
-  --> $DIR/simple-struct-min-capture.rs:36:26
+  --> $DIR/simple-struct-min-capture.rs:32:26
    |
 LL |         println!("{:?}", p);
    |                          ^
 
 error: Min Capture analysis includes:
-  --> $DIR/simple-struct-min-capture.rs:30:5
+  --> $DIR/simple-struct-min-capture.rs:26:5
    |
 LL | /     || {
 LL | |
@@ -52,7 +43,7 @@ LL | |     };
    | |_____^
    |
 note: Min Capture p[] -> MutBorrow
-  --> $DIR/simple-struct-min-capture.rs:33:9
+  --> $DIR/simple-struct-min-capture.rs:29:9
    |
 LL |         p.x += 10;
    |         ^^^ p[] captured as MutBorrow here
@@ -60,6 +51,6 @@ LL |         p.x += 10;
 LL |         println!("{:?}", p);
    |                          ^ p[] used here
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 79d3ecc2d2bedfeefa1e5469a8a683f100be1167..eab9f9d08a9f634ca3f591b346846a2070835fcc 100644 (file)
@@ -1,10 +1,9 @@
+// edition:2021
+
 // Test that we restrict precision of a capture when we access a raw ptr,
 // i.e. the capture doesn't deref the raw ptr.
 
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| `#[warn(incomplete_features)]` on by default
-//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+
 #![feature(rustc_attrs)]
 
 #[derive(Debug)]
index 4508b2426e8ff8d29596dd496fa882663848f9c8..e740a4d2d6b803a10b6a5ab55de08f13e3b8e7e8 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/unsafe_ptr.rs:26:13
+  --> $DIR/unsafe_ptr.rs:25:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,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/unsafe_ptr.rs:46:13
+  --> $DIR/unsafe_ptr.rs:45:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,17 +16,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unsafe_ptr.rs:4:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/unsafe_ptr.rs:29:6
+  --> $DIR/unsafe_ptr.rs:28:6
    |
 LL | /      || unsafe {
 LL | |
@@ -38,13 +29,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
-  --> $DIR/unsafe_ptr.rs:32:26
+  --> $DIR/unsafe_ptr.rs:31:26
    |
 LL |         println!("{:?}", (*t.0).s);
    |                          ^^^^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/unsafe_ptr.rs:29:6
+  --> $DIR/unsafe_ptr.rs:28:6
    |
 LL | /      || unsafe {
 LL | |
@@ -56,13 +47,13 @@ LL | |     };
    | |_____^
    |
 note: Min Capture t[(0, 0)] -> ImmBorrow
-  --> $DIR/unsafe_ptr.rs:32:26
+  --> $DIR/unsafe_ptr.rs:31:26
    |
 LL |         println!("{:?}", (*t.0).s);
    |                          ^^^^^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/unsafe_ptr.rs:49:5
+  --> $DIR/unsafe_ptr.rs:48:5
    |
 LL | /     || {
 LL | |
@@ -74,13 +65,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing p[Deref,(0, 0)] -> ImmBorrow
-  --> $DIR/unsafe_ptr.rs:52:31
+  --> $DIR/unsafe_ptr.rs:51:31
    |
 LL |         let x = unsafe { &mut (*p).s };
    |                               ^^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/unsafe_ptr.rs:49:5
+  --> $DIR/unsafe_ptr.rs:48:5
    |
 LL | /     || {
 LL | |
@@ -92,11 +83,11 @@ LL | |     };
    | |_____^
    |
 note: Min Capture p[] -> ImmBorrow
-  --> $DIR/unsafe_ptr.rs:52:31
+  --> $DIR/unsafe_ptr.rs:51:31
    |
 LL |         let x = unsafe { &mut (*p).s };
    |                               ^^^^^^
 
-error: aborting due to 6 previous errors; 1 warning emitted
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 90b8033d074a17357c042d712d1aa50daea37955..7843c251666c5e20b692491b632826fb992e8bb7 100644 (file)
@@ -1,7 +1,5 @@
-#![feature(capture_disjoint_fields)]
-//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
-//~| NOTE: `#[warn(incomplete_features)]` on by default
-//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+// edition:2021
+
 #![feature(rustc_attrs)]
 
 // Test to ensure that we can handle cases where
index 36be8431be508f5f9c7e9de8b683b95b86db6aa7..c64378091e6e02dfb24cc5bcc25aed99175813ac 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/wild_patterns.rs:24:13
+  --> $DIR/wild_patterns.rs:22:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,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/wild_patterns.rs:42:13
+  --> $DIR/wild_patterns.rs:40:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,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/wild_patterns.rs:60:13
+  --> $DIR/wild_patterns.rs:58:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -25,17 +25,8 @@ 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
 
-warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/wild_patterns.rs:1:12
-   |
-LL | #![feature(capture_disjoint_fields)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
-
 error: First Pass analysis includes:
-  --> $DIR/wild_patterns.rs:27:5
+  --> $DIR/wild_patterns.rs:25:5
    |
 LL | /     || {
 LL | |
@@ -47,13 +38,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing p[(0, 0)] -> ImmBorrow
-  --> $DIR/wild_patterns.rs:31:37
+  --> $DIR/wild_patterns.rs:29:37
    |
 LL |         let Point { x: _x, y: _ } = p;
    |                                     ^
 
 error: Min Capture analysis includes:
-  --> $DIR/wild_patterns.rs:27:5
+  --> $DIR/wild_patterns.rs:25:5
    |
 LL | /     || {
 LL | |
@@ -65,13 +56,13 @@ LL | |     };
    | |_____^
    |
 note: Min Capture p[(0, 0)] -> ImmBorrow
-  --> $DIR/wild_patterns.rs:31:37
+  --> $DIR/wild_patterns.rs:29:37
    |
 LL |         let Point { x: _x, y: _ } = p;
    |                                     ^
 
 error: First Pass analysis includes:
-  --> $DIR/wild_patterns.rs:45:5
+  --> $DIR/wild_patterns.rs:43:5
    |
 LL | /     || {
 LL | |
@@ -83,13 +74,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing t[(0, 0)] -> ByValue
-  --> $DIR/wild_patterns.rs:49:23
+  --> $DIR/wild_patterns.rs:47:23
    |
 LL |         let (_x, _) = t;
    |                       ^
 
 error: Min Capture analysis includes:
-  --> $DIR/wild_patterns.rs:45:5
+  --> $DIR/wild_patterns.rs:43:5
    |
 LL | /     || {
 LL | |
@@ -101,13 +92,13 @@ LL | |     };
    | |_____^
    |
 note: Min Capture t[(0, 0)] -> ByValue
-  --> $DIR/wild_patterns.rs:49:23
+  --> $DIR/wild_patterns.rs:47:23
    |
 LL |         let (_x, _) = t;
    |                       ^
 
 error: First Pass analysis includes:
-  --> $DIR/wild_patterns.rs:63:5
+  --> $DIR/wild_patterns.rs:61:5
    |
 LL | /     || {
 LL | |
@@ -119,13 +110,13 @@ LL | |     };
    | |_____^
    |
 note: Capturing arr[Index] -> ByValue
-  --> $DIR/wild_patterns.rs:67:23
+  --> $DIR/wild_patterns.rs:65:23
    |
 LL |         let [_x, _] = arr;
    |                       ^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/wild_patterns.rs:63:5
+  --> $DIR/wild_patterns.rs:61:5
    |
 LL | /     || {
 LL | |
@@ -137,11 +128,11 @@ LL | |     };
    | |_____^
    |
 note: Min Capture arr[] -> ByValue
-  --> $DIR/wild_patterns.rs:67:23
+  --> $DIR/wild_patterns.rs:65:23
    |
 LL |         let [_x, _] = arr;
    |                       ^^^
 
-error: aborting due to 9 previous errors; 1 warning emitted
+error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 72ef5b3b962c734d5386c07b0796aca96c57007b..ffe0bce6f0fd8b01d0c079e221c4ba9e3092a07e 100644 (file)
@@ -5,7 +5,7 @@ LL |     (&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
    |     ^^------^
    |     | |
    |     | found signature of `fn(u16) -> _`
-   |     expected signature of `fn(<u32 as T<'x>>::V) -> _`
+   |     expected signature of `for<'x> fn(<u32 as T<'x>>::V) -> _`
    |
    = note: required for the cast to the object type `dyn for<'x> Fn(<u32 as T<'x>>::V)`
 
index b09ea06c8f3d20f01af19ac2045d57c80f401039..9e4521df8c34f4d84c065af641cf79abad1f29e8 100644 (file)
@@ -1,13 +1,21 @@
 // build-pass
 // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
-// only-thumbv8m.main-none-eabi
-#![feature(abi_c_cmse_nonsecure_call)]
-#![no_std]
+// needs-llvm-components: arm
+#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)]
+#![no_core]
+#[lang="sized"]
+pub trait Sized { }
+#[lang="copy"]
+pub trait Copy { }
+
+extern "rust-intrinsic" {
+    pub fn transmute<T, U>(e: T) -> U;
+}
 
 #[no_mangle]
 pub fn test(a: u32, b: u32, c: u32, d: u32) -> u32 {
     let non_secure_function = unsafe {
-        core::mem::transmute::<usize, extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u32>(
+        transmute::<usize, extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u32>(
             0x10000004,
         )
     };
index cfdce4f4e92fa69b2a06b09aa8046294f4cef984..9697146d5c3d83623b7d2390bf07de83f65bb447 100644 (file)
@@ -1,12 +1,22 @@
+// build-fail
 // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
-// only-thumbv8m.main-none-eabi
-#![feature(abi_c_cmse_nonsecure_call)]
-#![no_std]
+// needs-llvm-components: arm
+// min-llvm-version: 11.0
+#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)]
+#![no_core]
+#[lang="sized"]
+pub trait Sized { }
+#[lang="copy"]
+pub trait Copy { }
+
+extern "rust-intrinsic" {
+    pub fn transmute<T, U>(e: T) -> U;
+}
 
 #[no_mangle]
 pub fn test(a: u32, b: u32, c: u32, d: u32, e: u32) -> u32 {
     let non_secure_function = unsafe {
-        core::mem::transmute::<
+        transmute::<
             usize,
             extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32>
         (
index 17117301fefcb0d23be86822ff32bb28a3637807..f32b3709002e6c2db959b33f3b7b5e16381744f4 100644 (file)
@@ -1,6 +1,8 @@
 // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
-// only-thumbv8m.main-none-eabi
-#![feature(abi_c_cmse_nonsecure_call)]
-#![no_std]
+// needs-llvm-components: arm
+#![feature(abi_c_cmse_nonsecure_call, lang_items, no_core)]
+#![no_core]
+#[lang="sized"]
+trait Sized { }
 
 pub extern "C-cmse-nonsecure-call" fn test() {} //~ ERROR [E0781]
index 78490bf8f68a203af73e3fcd5f085995363d25c1..3564ab4b6cd4dd76241a6de8bac0f96d8d5516fe 100644 (file)
@@ -1,8 +1,8 @@
-error[E0781]: the `"cmse-nonsecure-call"` ABI is only allowed on function pointers.
-  --> $DIR/wrong-abi-location-1.rs:6:1
+error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers.
+  --> $DIR/wrong-abi-location-1.rs:8:1
    |
-LL | pub extern "C-cmse-nonsecure-call" fn test() {} //~ ERROR [E0781]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | pub extern "C-cmse-nonsecure-call" fn test() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 78f553d747c20923c187899cf84bd4c1a2b70661..6f8bb24aa69e84f120992167cb011b87e052fc0c 100644 (file)
@@ -1,7 +1,9 @@
 // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
-// only-thumbv8m.main-none-eabi
-#![feature(abi_c_cmse_nonsecure_call)]
-#![no_std]
+// needs-llvm-components: arm
+#![feature(abi_c_cmse_nonsecure_call, lang_items, no_core)]
+#![no_core]
+#[lang="sized"]
+trait Sized { }
 
 extern "C-cmse-nonsecure-call" { //~ ERROR [E0781]
     fn test();
index 5c148e2cd6fe0b83f071be129ef6f1eaab3cf06d..76073f548848a70bfaa1a47ab9c8ecefffbf7bff 100644 (file)
@@ -1,8 +1,8 @@
 error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers.
-  --> $DIR/wrong-abi-location-2.rs:6:1
+  --> $DIR/wrong-abi-location-2.rs:8:1
    |
 LL | / extern "C-cmse-nonsecure-call" {
-LL | |     fn test(); //~ ERROR [E0781]
+LL | |     fn test();
 LL | | }
    | |_^
 
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs
new file mode 100644 (file)
index 0000000..a839406
--- /dev/null
@@ -0,0 +1,9 @@
+// Regression test for the ICE described in #83475.
+
+#![crate_type="lib"]
+
+#![feature(cmse_nonsecure_entry)]
+#[cmse_nonsecure_entry]
+//~^ ERROR: attribute should be applied to a function definition
+struct XEmpty2;
+//~^ NOTE: not a function definition
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr
new file mode 100644 (file)
index 0000000..426d82d
--- /dev/null
@@ -0,0 +1,11 @@
+error: attribute should be applied to a function definition
+  --> $DIR/issue-83475.rs:6:1
+   |
+LL | #[cmse_nonsecure_entry]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | struct XEmpty2;
+   | --------------- not a function definition
+
+error: aborting due to previous error
+
index a723eb734731d2d53ee8e06ec6b8e51c9d53a355..8cde9ba58b93b0a3e24c228cc01186d5074bd935 100644 (file)
@@ -1,11 +1,15 @@
 // build-pass
 // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
-// only-thumbv8m.main-none-eabi
-#![feature(cmse_nonsecure_entry)]
-#![no_std]
+// needs-llvm-components: arm
+#![feature(cmse_nonsecure_entry, no_core, lang_items)]
+#![no_core]
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
 
 #[no_mangle]
 #[cmse_nonsecure_entry]
-pub extern "C" fn entry_function(a: u32, b: u32, c: u32, d: u32) -> u32 {
-    a + b + c + d
+pub extern "C" fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 {
+    d
 }
index 553d3a8cb0be7966dc2ee857a0c0b5f26e4d6631..74321fdfdde907b5694b04a5ea928f0a004dc587 100644 (file)
@@ -1,10 +1,16 @@
+// build-fail
 // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
-// only-thumbv8m.main-none-eabi
-#![feature(cmse_nonsecure_entry)]
-#![no_std]
+// needs-llvm-components: arm
+// min-llvm-version: 11.0
+#![feature(cmse_nonsecure_entry, no_core, lang_items)]
+#![no_core]
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
 
 #[no_mangle]
 #[cmse_nonsecure_entry]
-pub extern "C" fn entry_function(a: u32, b: u32, c: u32, d: u32, e: u32) -> u32 { //~ ERROR
-    a + b + c + d + e
+pub extern "C" fn entry_function(_: u32, _: u32, _: u32, _: u32, e: u32) -> u32 {
+    e
 }
index 611c8643dcb0227e7e3c5da226eec8685a588144..6320d296373c09236a8328d2069c4639fae4cf98 100644 (file)
@@ -1,10 +1,13 @@
 // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
-// only-thumbv8m.main-none-eabi
-#![feature(cmse_nonsecure_entry)]
-#![no_std]
+// needs-llvm-components: arm
+#![feature(cmse_nonsecure_entry, no_core, lang_items)]
+#![no_core]
+#[lang="sized"]
+trait Sized { }
 
 #[no_mangle]
 #[cmse_nonsecure_entry]
-pub fn entry_function(a: u32, b: u32, c: u32, d: u32) -> u32 { //~ ERROR [E0776]
-    a + b + c + d
+//~^ ERROR `#[cmse_nonsecure_entry]` requires C ABI [E0776]
+pub fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 {
+    d
 }
index d6967a11e6bf7d7ff1c8c6e0df505b113459b9e6..36d76c9674adff6754947d238740eb24fc3554bc 100644 (file)
@@ -1,5 +1,5 @@
-error[E0776]: `#[cmse_nonsecure_entry]` functions require C ABI
-  --> $DIR/wrong-abi.rs:7:1
+error[E0776]: `#[cmse_nonsecure_entry]` requires C ABI
+  --> $DIR/wrong-abi.rs:9:1
    |
 LL | #[cmse_nonsecure_entry]
    | ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/codegen/issue-88043-bb-does-not-have-terminator.rs b/src/test/ui/codegen/issue-88043-bb-does-not-have-terminator.rs
new file mode 100644 (file)
index 0000000..38dfca3
--- /dev/null
@@ -0,0 +1,35 @@
+// build-pass
+// compile-flags: -Copt-level=0
+
+// Regression test for #88043: LLVM crash when the RemoveZsts mir-opt pass is enabled.
+// We should not see the error:
+// `Basic Block in function '_ZN4main10take_until17h0067b8a660429bc9E' does not have terminator!`
+
+fn bump() -> Option<usize> {
+    unreachable!()
+}
+
+fn take_until(terminate: impl Fn() -> bool) {
+    loop {
+        if terminate() {
+            return;
+        } else {
+            bump();
+        }
+    }
+}
+
+// CHECK-LABEL: @main
+fn main() {
+    take_until(|| true);
+    f(None);
+}
+
+fn f(_a: Option<String>) -> Option<u32> {
+    loop {
+        g();
+        ()
+    }
+}
+
+fn g() -> Option<u32> { None }
diff --git a/src/test/ui/coercion/issue-37655.rs b/src/test/ui/coercion/issue-37655.rs
new file mode 100644 (file)
index 0000000..416854d
--- /dev/null
@@ -0,0 +1,37 @@
+// check-pass
+// Regression test for #37655. The problem was a false edge created by
+// coercion that wound up requiring that `'a` (in `split()`) outlive
+// `'b`, which shouldn't be necessary.
+
+#![allow(warnings)]
+
+trait SliceExt<T> {
+    type Item;
+
+    fn get_me<I>(&self, index: I) -> &I::Output
+        where I: SliceIndex<Self::Item>;
+}
+
+impl<T> SliceExt<T> for [T] {
+    type Item = T;
+
+    fn get_me<I>(&self, index: I) -> &I::Output
+        where I: SliceIndex<T>
+    {
+        panic!()
+    }
+}
+
+pub trait SliceIndex<T> {
+    type Output: ?Sized;
+}
+
+impl<T> SliceIndex<T> for usize {
+    type Output = T;
+}
+
+fn foo<'a, 'b>(split: &'b [&'a [u8]]) -> &'a [u8] {
+    split.get_me(0)
+}
+
+fn main() { }
index 7dabd97b94e823d93462b0cc5c8b61ff4789cddf..cfcef9699f3721f7c91af8e607cb7eaa414168bc 100644 (file)
@@ -1,10 +1,10 @@
-error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))`
+error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(for<'r> fn(&'r ()))`
   --> $DIR/coherence-fn-covariant-bound-vs-static.rs:17:1
    |
 LL | impl Trait for for<'r> fn(fn(&'r ())) {}
    | ------------------------------------- first implementation here
 LL | impl<'a> Trait for fn(fn(&'a ())) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(fn(&'r ()))`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(for<'r> fn(&'r ()))`
    |
    = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
 
diff --git a/src/test/ui/conditional-compilation/test-cfg.rs b/src/test/ui/conditional-compilation/test-cfg.rs
new file mode 100644 (file)
index 0000000..8750bae
--- /dev/null
@@ -0,0 +1,8 @@
+// compile-flags: --cfg foo
+
+#[cfg(all(foo, bar))] // foo AND bar
+fn foo() {}
+
+fn main() {
+    foo(); //~ ERROR cannot find function `foo` in this scope
+}
diff --git a/src/test/ui/conditional-compilation/test-cfg.stderr b/src/test/ui/conditional-compilation/test-cfg.stderr
new file mode 100644 (file)
index 0000000..c35fe2f
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `foo` in this scope
+  --> $DIR/test-cfg.rs:7:5
+   |
+LL |     foo();
+   |     ^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
index 09dade20992ba15234337205d6345200214e9b1a..ed82b6a742c8de7aebef7428e7ccb52728431e70 100644 (file)
@@ -66,4 +66,15 @@ union Z {
     i: i32,
 }
 
+#[repr(packed, align(0x100))]
+pub struct S(u16); //~ ERROR type has conflicting packed and align representation hints
+
+#[repr(packed, align(0x100))]
+pub union U { //~ ERROR type has conflicting packed and align representation hints
+    u: u16
+}
+
+static B: U = U { u: 0 };
+static A: S = S(0);
+
 fn main() {}
index 0b78532c73751fbf9298b29445e88a643ad508a3..0f32fc0481bc6e251c2a581675d76a3ffa02ce63 100644 (file)
@@ -74,7 +74,21 @@ LL | |     i: i32,
 LL | | }
    | |_^
 
-error: aborting due to 10 previous errors
+error[E0587]: type has conflicting packed and align representation hints
+  --> $DIR/conflicting-repr-hints.rs:70:1
+   |
+LL | pub struct S(u16);
+   | ^^^^^^^^^^^^^^^^^^
+
+error[E0587]: type has conflicting packed and align representation hints
+  --> $DIR/conflicting-repr-hints.rs:73:1
+   |
+LL | / pub union U {
+LL | |     u: u16
+LL | | }
+   | |_^
+
+error: aborting due to 12 previous errors
 
 Some errors have detailed explanations: E0566, E0587, E0634.
 For more information about an error, try `rustc --explain E0566`.
diff --git a/src/test/ui/const-generics/auxiliary/impl-const.rs b/src/test/ui/const-generics/auxiliary/impl-const.rs
deleted file mode 100644 (file)
index 4a6b578..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-pub struct Num<const N: usize>;
-
-// Braces around const expression causes crash
-impl Num<{5}> {
-    pub fn five(&self) {
-    }
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-1.rs b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-1.rs
new file mode 100644 (file)
index 0000000..744a1c4
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+#![feature(const_evaluatable_checked, const_generics)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: u8>([u8; N as usize])
+where
+    [(); N as usize]:;
+
+struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 2) as usize]:;
+
+// unifying with subtrees
+struct Evaluatable<const N: u16>;
+fn foo<const N: u8>() where Evaluatable<{N as usize as u16 }>: {
+    let _ = Foo::<N>([1; N as usize]);
+}
+
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.rs b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.rs
new file mode 100644 (file)
index 0000000..5437746
--- /dev/null
@@ -0,0 +1,20 @@
+#![feature(const_evaluatable_checked, const_generics)]
+#![allow(incomplete_features)]
+
+struct Evaluatable<const N: u128> {}
+
+struct Foo<const N: u8>([u8; N as usize])
+//~^ Error: unconstrained generic constant
+//~| help: try adding a `where` bound using this expression: `where [(); N as usize]:`
+where
+    Evaluatable<{N as u128}>:;
+
+struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:;
+//~^ Error: unconstrained generic constant
+//~| help: try adding a `where` bound using this expression: `where [(); {N as u128}]:`
+
+struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:;
+//~^ Error: unconstrained generic constant
+//~| help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:`
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.stderr b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.stderr
new file mode 100644 (file)
index 0000000..5ca04d2
--- /dev/null
@@ -0,0 +1,26 @@
+error: unconstrained generic constant
+  --> $DIR/abstract-const-as-cast-2.rs:6:25
+   |
+LL | struct Foo<const N: u8>([u8; N as usize])
+   |                         ^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); N as usize]:`
+
+error: unconstrained generic constant
+  --> $DIR/abstract-const-as-cast-2.rs:12:26
+   |
+LL | struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:;
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); {N as u128}]:`
+
+error: unconstrained generic constant
+  --> $DIR/abstract-const-as-cast-2.rs:16:25
+   |
+LL | struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:;
+   |                         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.rs b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.rs
new file mode 100644 (file)
index 0000000..2ca06bd
--- /dev/null
@@ -0,0 +1,47 @@
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+trait Trait {}
+pub struct EvaluatableU128<const N: u128>;
+
+struct HasCastInTraitImpl<const N: usize, const M: u128>;
+impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
+
+pub fn use_trait_impl<const N: usize>()
+where
+    [(); { N + 1}]:,
+    EvaluatableU128<{N as u128}>:, {
+    fn assert_impl<T: Trait>() {}
+
+    // errors are bad but seems to be pre-existing issue #86198
+    assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
+    //~^ Error: mismatched types
+    //~^^ Error: unconstrained generic constant
+    assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
+    //~^ Error: mismatched types
+    //~^^ Error: unconstrained generic constant
+    assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
+    //~^ Error: mismatched types
+    assert_impl::<HasCastInTraitImpl<14, 13>>();
+    //~^ Error: mismatched types
+}
+pub fn use_trait_impl_2<const N: usize>()
+where
+    [(); { N + 1}]:,
+    EvaluatableU128<{N as _}>:, {
+    fn assert_impl<T: Trait>() {}
+
+    // errors are bad but seems to be pre-existing issue #86198
+    assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
+    //~^ Error: mismatched types
+    //~^^ Error: unconstrained generic constant
+    assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
+    //~^ Error: mismatched types
+    //~^^ Error: unconstrained generic constant
+    assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
+    //~^ Error: mismatched types
+    assert_impl::<HasCastInTraitImpl<14, 13>>();
+    //~^ Error: mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.stderr b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.stderr
new file mode 100644 (file)
index 0000000..c5237fc
--- /dev/null
@@ -0,0 +1,139 @@
+error: unconstrained generic constant
+  --> $DIR/abstract-const-as-cast-3.rs:17:5
+   |
+LL |     fn assert_impl<T: Trait>() {}
+   |                       ----- required by this bound in `use_trait_impl::assert_impl`
+...
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
+note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>`
+  --> $DIR/abstract-const-as-cast-3.rs:8:22
+   |
+LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
+   |                      ^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:17:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }`
+   |
+   = note: expected type `{ N as u128 }`
+              found type `{ O as u128 }`
+
+error: unconstrained generic constant
+  --> $DIR/abstract-const-as-cast-3.rs:20:5
+   |
+LL |     fn assert_impl<T: Trait>() {}
+   |                       ----- required by this bound in `use_trait_impl::assert_impl`
+...
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
+note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>`
+  --> $DIR/abstract-const-as-cast-3.rs:8:22
+   |
+LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
+   |                      ^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:20:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }`
+   |
+   = note: expected type `{ N as _ }`
+              found type `{ O as u128 }`
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:23:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12_u128`, found `13_u128`
+   |
+   = note: expected type `12_u128`
+              found type `13_u128`
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:25:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<14, 13>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13_u128`, found `14_u128`
+   |
+   = note: expected type `13_u128`
+              found type `14_u128`
+
+error: unconstrained generic constant
+  --> $DIR/abstract-const-as-cast-3.rs:35:5
+   |
+LL |     fn assert_impl<T: Trait>() {}
+   |                       ----- required by this bound in `use_trait_impl_2::assert_impl`
+...
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
+note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>`
+  --> $DIR/abstract-const-as-cast-3.rs:8:22
+   |
+LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
+   |                      ^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:35:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }`
+   |
+   = note: expected type `{ N as u128 }`
+              found type `{ O as u128 }`
+
+error: unconstrained generic constant
+  --> $DIR/abstract-const-as-cast-3.rs:38:5
+   |
+LL |     fn assert_impl<T: Trait>() {}
+   |                       ----- required by this bound in `use_trait_impl_2::assert_impl`
+...
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
+note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>`
+  --> $DIR/abstract-const-as-cast-3.rs:8:22
+   |
+LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
+   |                      ^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:38:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }`
+   |
+   = note: expected type `{ N as _ }`
+              found type `{ O as u128 }`
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:41:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12_u128`, found `13_u128`
+   |
+   = note: expected type `12_u128`
+              found type `13_u128`
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:43:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<14, 13>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13_u128`, found `14_u128`
+   |
+   = note: expected type `13_u128`
+              found type `14_u128`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-4.rs b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-4.rs
new file mode 100644 (file)
index 0000000..0bb4fcf
--- /dev/null
@@ -0,0 +1,29 @@
+// check-pass
+#![feature(const_evaluatable_checked, const_generics)]
+#![allow(incomplete_features)]
+
+trait Trait {}
+pub struct EvaluatableU128<const N: u128>;
+
+struct HasCastInTraitImpl<const N: usize, const M: u128>;
+impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
+
+pub fn use_trait_impl<const N: usize>() where EvaluatableU128<{N as u128}>:, {
+    fn assert_impl<T: Trait>() {}
+
+    assert_impl::<HasCastInTraitImpl<N, { N as u128 }>>();
+    assert_impl::<HasCastInTraitImpl<N, { N as _ }>>();
+    assert_impl::<HasCastInTraitImpl<12, { 12 as u128 }>>();
+    assert_impl::<HasCastInTraitImpl<13, 13>>();
+}
+pub fn use_trait_impl_2<const N: usize>() where EvaluatableU128<{N as _}>:, {
+    fn assert_impl<T: Trait>() {}
+
+    assert_impl::<HasCastInTraitImpl<N, { N as u128 }>>();
+    assert_impl::<HasCastInTraitImpl<N, { N as _ }>>();
+    assert_impl::<HasCastInTraitImpl<12, { 12 as u128 }>>();
+    assert_impl::<HasCastInTraitImpl<13, 13>>();
+}
+
+
+fn main() {}
index e0e6029252c00b3471084c478d037e1e4e86f45e..319e6c2c032a0e067bf9fd2009cfe3416fbc63f9 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/object-safety-err-ret.rs:17:15
+  --> $DIR/object-safety-err-ret.rs:17:16
    |
 LL | fn use_dyn(v: &dyn Foo) {
-   |               ^^^^^^^^ `Foo` cannot be made into an object
+   |                ^^^^^^^ `Foo` cannot be made into an object
    |
    = help: consider moving `test` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
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-generics/defaults/default-const-param-cannot-reference-self.rs b/src/test/ui/const-generics/defaults/default-const-param-cannot-reference-self.rs
new file mode 100644 (file)
index 0000000..9af8443
--- /dev/null
@@ -0,0 +1,16 @@
+#![feature(const_generics_defaults)]
+
+struct Struct<const N: usize = { Self; 10 }>;
+//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735]
+
+enum Enum<const N: usize = { Self; 10 }> { }
+//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735]
+
+union Union<const N: usize = { Self; 10 }> { not_empty: () }
+//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735]
+
+fn main() {
+    let _: Struct;
+    let _: Enum;
+    let _: Union;
+}
diff --git a/src/test/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr b/src/test/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr
new file mode 100644 (file)
index 0000000..5dfec2f
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0735]: generic parameters cannot use `Self` in their defaults
+  --> $DIR/default-const-param-cannot-reference-self.rs:3:34
+   |
+LL | struct Struct<const N: usize = { Self; 10 }>;
+   |                                  ^^^^ `Self` in generic parameter default
+
+error[E0735]: generic parameters cannot use `Self` in their defaults
+  --> $DIR/default-const-param-cannot-reference-self.rs:6:30
+   |
+LL | enum Enum<const N: usize = { Self; 10 }> { }
+   |                              ^^^^ `Self` in generic parameter default
+
+error[E0735]: generic parameters cannot use `Self` in their defaults
+  --> $DIR/default-const-param-cannot-reference-self.rs:9:32
+   |
+LL | union Union<const N: usize = { Self; 10 }> { not_empty: () }
+   |                                ^^^^ `Self` in generic parameter default
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0735`.
index d894fa90ba9e1c72a67bf84ea293541be55f9895..09986f623fc4b393b742aa9d60243a50d2d1fef8 100644 (file)
@@ -3,9 +3,12 @@ error[E0277]: the trait bound `[Adt; _]: Foo` is not satisfied
    |
 LL |         <[Adt; std::mem::size_of::<Self::Assoc>()] as Foo>::bar()
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[Adt; _]`
-...
+   |
+note: required by `Foo::bar`
+  --> $DIR/dont-evaluate-array-len-on-err-1.rs:19:5
+   |
 LL |     fn bar() {}
-   |     -------- required by `Foo::bar`
+   |     ^^^^^^^^
 
 error: aborting due to previous error
 
index e0e1423ba0107083d9b9583e57cb6eef12a0810e..4e89e4a3b17e97b285dc5466b8145d2b1cc45f48 100644 (file)
@@ -1,9 +1,6 @@
 error[E0277]: the trait bound `(): Foo<N>` is not satisfied
   --> $DIR/exhaustive-value.rs:266:5
    |
-LL |     fn test() {}
-   |     --------- required by `Foo::test`
-...
 LL |     <() as Foo<N>>::test()
    |     ^^^^^^^^^^^^^^^^^^^^ the trait `Foo<N>` is not implemented for `()`
    |
@@ -13,6 +10,11 @@ LL |     <() as Foo<N>>::test()
              <() as Foo<101_u8>>
              <() as Foo<102_u8>>
            and 252 others
+note: required by `Foo::test`
+  --> $DIR/exhaustive-value.rs:6:5
+   |
+LL |     fn test() {}
+   |     ^^^^^^^^^
 
 error: aborting due to previous error
 
index e0e1423ba0107083d9b9583e57cb6eef12a0810e..4e89e4a3b17e97b285dc5466b8145d2b1cc45f48 100644 (file)
@@ -1,9 +1,6 @@
 error[E0277]: the trait bound `(): Foo<N>` is not satisfied
   --> $DIR/exhaustive-value.rs:266:5
    |
-LL |     fn test() {}
-   |     --------- required by `Foo::test`
-...
 LL |     <() as Foo<N>>::test()
    |     ^^^^^^^^^^^^^^^^^^^^ the trait `Foo<N>` is not implemented for `()`
    |
@@ -13,6 +10,11 @@ LL |     <() as Foo<N>>::test()
              <() as Foo<101_u8>>
              <() as Foo<102_u8>>
            and 252 others
+note: required by `Foo::test`
+  --> $DIR/exhaustive-value.rs:6:5
+   |
+LL |     fn test() {}
+   |     ^^^^^^^^^
 
 error: aborting due to previous error
 
index 26b965901a4c4d061f6d526f4918bbf20e480ace..ebc8f458f79c78788d7bbb346069a311123e32af 100644 (file)
@@ -6,3 +6,4 @@ LL |     assert_eq!(f::<4usize>(Usizable), 20usize);
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0632`.
index 26b965901a4c4d061f6d526f4918bbf20e480ace..ebc8f458f79c78788d7bbb346069a311123e32af 100644 (file)
@@ -6,3 +6,4 @@ LL |     assert_eq!(f::<4usize>(Usizable), 20usize);
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0632`.
diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr b/src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr
deleted file mode 100644 (file)
index 56deec1..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-61522-array-len-succ.rs:6:40
-   |
-LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
-   |                                        ^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-61522-array-len-succ.rs:11:24
-   |
-LL |     fn inner(&self) -> &[u8; COUNT + 1] {
-   |                        ^^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr b/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr
deleted file mode 100644 (file)
index 36a0a37..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-61522-array-len-succ.rs:6:45
-   |
-LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
-   |                                             ^^^^^ cannot perform const operation using `COUNT`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `COUNT`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-61522-array-len-succ.rs:11:30
-   |
-LL |     fn inner(&self) -> &[u8; COUNT + 1] {
-   |                              ^^^^^ cannot perform const operation using `COUNT`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `COUNT`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.rs b/src/test/ui/const-generics/issue-61522-array-len-succ.rs
deleted file mode 100644 (file)
index d4a948b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[min]~^^ ERROR generic parameters may not be used
-
-impl<const COUNT: usize> MyArray<COUNT> {
-    fn inner(&self) -> &[u8; COUNT + 1] {
-        //[full]~^ ERROR constant expression depends on a generic parameter
-        //[min]~^^ ERROR generic parameters may not be used
-        &self.0
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr
deleted file mode 100644 (file)
index e96b9e7..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: `&'static str` is forbidden as the type of a const generic parameter
-  --> $DIR/issue-66596-impl-trait-for-str-const-arg.rs:8:25
-   |
-LL | trait Trait<const NAME: &'static str> {
-   |                         ^^^^^^^^^^^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs
deleted file mode 100644 (file)
index 2a741ba..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-//[full] check-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-
-trait Trait<const NAME: &'static str> {
-//[min]~^ ERROR `&'static str` is forbidden
-    type Assoc;
-}
-
-impl Trait<"0"> for () {
-    type Assoc = ();
-}
-
-fn main() {
-    let _: <() as Trait<"0">>::Assoc = ();
-}
diff --git a/src/test/ui/const-generics/issue-67375.full.stderr b/src/test/ui/const-generics/issue-67375.full.stderr
deleted file mode 100644 (file)
index 0fe6527..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-warning: cannot use constants which depend on generic parameters in types
-  --> $DIR/issue-67375.rs:8:12
-   |
-LL |     inner: [(); { [|_: &T| {}; 0].len() }],
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(const_evaluatable_unchecked)]` 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 #76200 <https://github.com/rust-lang/rust/issues/76200>
-
-error[E0392]: parameter `T` is never used
-  --> $DIR/issue-67375.rs:6:12
-   |
-LL | struct Bug<T> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `T` to be a const parameter, use `const T: usize` instead
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issue-67375.min.stderr b/src/test/ui/const-generics/issue-67375.min.stderr
deleted file mode 100644 (file)
index be81fa9..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-67375.rs:8:25
-   |
-LL |     inner: [(); { [|_: &T| {}; 0].len() }],
-   |                         ^ cannot perform const operation using `T`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error[E0392]: parameter `T` is never used
-  --> $DIR/issue-67375.rs:6:12
-   |
-LL | struct Bug<T> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `T` to be a const parameter, use `const T: usize` instead
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issue-67375.rs b/src/test/ui/const-generics/issue-67375.rs
deleted file mode 100644 (file)
index a8875b8..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
-struct Bug<T> {
-    //~^ ERROR parameter `T` is never used
-    inner: [(); { [|_: &T| {}; 0].len() }],
-    //[min]~^ ERROR generic parameters may not be used in const operations
-    //[full]~^^ WARN cannot use constants which depend on generic parameters in types
-    //[full]~^^^ WARN this was previously accepted by the compiler
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-67945-1.full.stderr b/src/test/ui/const-generics/issue-67945-1.full.stderr
deleted file mode 100644 (file)
index 63c50b5..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-67945-1.rs:13:20
-   |
-LL | struct Bug<S> {
-   |            - this type parameter
-...
-LL |         let x: S = MaybeUninit::uninit();
-   |                -   ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found union `MaybeUninit`
-   |                |
-   |                expected due to this
-   |
-   = note: expected type parameter `S`
-                       found union `MaybeUninit<_>`
-
-error[E0392]: parameter `S` is never used
-  --> $DIR/issue-67945-1.rs:10:12
-   |
-LL | struct Bug<S> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0308, E0392.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issue-67945-1.min.stderr b/src/test/ui/const-generics/issue-67945-1.min.stderr
deleted file mode 100644 (file)
index 074d36c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-67945-1.rs:13:16
-   |
-LL |         let x: S = MaybeUninit::uninit();
-   |                ^ cannot perform const operation using `S`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-67945-1.rs:16:45
-   |
-LL |         let b = &*(&x as *const _ as *const S);
-   |                                             ^ cannot perform const operation using `S`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error[E0392]: parameter `S` is never used
-  --> $DIR/issue-67945-1.rs:10:12
-   |
-LL | struct Bug<S> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issue-67945-1.rs b/src/test/ui/const-generics/issue-67945-1.rs
deleted file mode 100644 (file)
index 84737e4..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
-use std::marker::PhantomData;
-
-use std::mem::{self, MaybeUninit};
-
-struct Bug<S> {
-    //~^ ERROR parameter `S` is never used
-    A: [(); {
-        let x: S = MaybeUninit::uninit();
-        //[min]~^ ERROR generic parameters may not be used in const operations
-        //[full]~^^ ERROR mismatched types
-        let b = &*(&x as *const _ as *const S);
-        //[min]~^ ERROR generic parameters may not be used in const operations
-        0
-    }],
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-67945-2.full.stderr b/src/test/ui/const-generics/issue-67945-2.full.stderr
deleted file mode 100644 (file)
index b900406..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-67945-2.rs:11:20
-   |
-LL | struct Bug<S> {
-   |            - this type parameter
-...
-LL |         let x: S = MaybeUninit::uninit();
-   |                -   ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found union `MaybeUninit`
-   |                |
-   |                expected due to this
-   |
-   = note: expected type parameter `S`
-                       found union `MaybeUninit<_>`
-
-error[E0392]: parameter `S` is never used
-  --> $DIR/issue-67945-2.rs:8:12
-   |
-LL | struct Bug<S> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0308, E0392.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issue-67945-2.min.stderr b/src/test/ui/const-generics/issue-67945-2.min.stderr
deleted file mode 100644 (file)
index c06df79..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-67945-2.rs:11:16
-   |
-LL |         let x: S = MaybeUninit::uninit();
-   |                ^ cannot perform const operation using `S`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-67945-2.rs:14:45
-   |
-LL |         let b = &*(&x as *const _ as *const S);
-   |                                             ^ cannot perform const operation using `S`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error[E0392]: parameter `S` is never used
-  --> $DIR/issue-67945-2.rs:8:12
-   |
-LL | struct Bug<S> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issue-67945-2.rs b/src/test/ui/const-generics/issue-67945-2.rs
deleted file mode 100644 (file)
index 4a46786..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
-use std::mem::MaybeUninit;
-
-struct Bug<S> {
-    //~^ ERROR parameter `S` is never used
-    A: [(); {
-        let x: S = MaybeUninit::uninit();
-        //[min]~^ ERROR generic parameters may not be used in const operations
-        //[full]~^^ ERROR mismatched types
-        let b = &*(&x as *const _ as *const S);
-        //[min]~^ ERROR generic parameters may not be used in const operations
-        0
-    }],
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-67945-3.full.stderr b/src/test/ui/const-generics/issue-67945-3.full.stderr
deleted file mode 100644 (file)
index fa66252..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-67945-3.rs:7:8
-   |
-LL |       A: [(); {
-   |  ________^
-LL | |
-LL | |         let x: Option<Box<Self>> = None;
-LL | |
-LL | |         0
-LL | |     }],
-   | |______^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issue-67945-3.min.stderr b/src/test/ui/const-generics/issue-67945-3.min.stderr
deleted file mode 100644 (file)
index 5c30429..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: generic `Self` types are currently not permitted in anonymous constants
-  --> $DIR/issue-67945-3.rs:9:27
-   |
-LL |         let x: Option<Box<Self>> = None;
-   |                           ^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issue-67945-3.rs b/src/test/ui/const-generics/issue-67945-3.rs
deleted file mode 100644 (file)
index 5bad61c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
-struct Bug<S: ?Sized> {
-    A: [(); {
-        //[full]~^ ERROR constant expression depends on a generic parameter
-        let x: Option<Box<Self>> = None;
-        //[min]~^ ERROR generic `Self` types are currently not permitted in anonymous constants
-        0
-    }],
-    B: S
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs b/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs
deleted file mode 100644 (file)
index 43c3999..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// aux-build:impl-const.rs
-// run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-extern crate impl_const;
-
-use impl_const::*;
-
-pub fn main() {
-    let n = Num::<5>;
-    n.five();
-}
diff --git a/src/test/ui/const-generics/issue-70180-1-stalled_on.rs b/src/test/ui/const-generics/issue-70180-1-stalled_on.rs
deleted file mode 100644 (file)
index f055482..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// build-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-pub fn works() {
-    let array/*: [_; _]*/ = default_array();
-    let _: [_; 4] = array;
-    Foo::foo(&array);
-}
-
-pub fn didnt_work() {
-    let array/*: [_; _]*/ = default_array();
-    Foo::foo(&array);
-    let _: [_; 4] = array;
-}
-
-trait Foo {
-    fn foo(&self) {}
-}
-
-impl Foo for [i32; 4] {}
-impl Foo for [i64; 8] {}
-
-// Only needed because `[_; _]` is not valid type syntax.
-fn default_array<T, const N: usize>() -> [T; N]
-where
-    [T; N]: Default,
-{
-    Default::default()
-}
-
-fn main() {
-    works();
-    didnt_work();
-}
diff --git a/src/test/ui/const-generics/issue-70180-2-stalled_on.rs b/src/test/ui/const-generics/issue-70180-2-stalled_on.rs
deleted file mode 100644 (file)
index 21cefc0..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// build-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-fn works() {
-    let array/*: [u8; _]*/ = default_byte_array();
-    let _: [_; 4] = array;
-    Foo::foo(&array);
-}
-
-fn didnt_work() {
-    let array/*: [u8; _]*/ = default_byte_array();
-    Foo::foo(&array);
-    let _: [_; 4] = array;
-}
-
-trait Foo<T> {
-    fn foo(&self) {}
-}
-
-impl Foo<i32> for [u8; 4] {}
-impl Foo<i64> for [u8; 8] {}
-
-// Only needed because `[u8; _]` is not valid type syntax.
-fn default_byte_array<const N: usize>() -> [u8; N]
-where
-    [u8; N]: Default,
-{
-    Default::default()
-}
-
-fn main() {
-    works();
-    didnt_work();
-}
diff --git a/src/test/ui/const-generics/issue-71202.rs b/src/test/ui/const-generics/issue-71202.rs
deleted file mode 100644 (file)
index 78dee17..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// check-pass
-
-#![feature(const_generics)]
-#![allow(incomplete_features, const_evaluatable_unchecked)]
-
-use std::marker::PhantomData;
-
-struct DataHolder<T> {
-    item: T,
-}
-
-impl<T: Copy> DataHolder<T> {
-    const ITEM_IS_COPY: [(); 1 - {
-        trait NotCopy {
-            const VALUE: bool = false;
-        }
-
-        impl<__Type: ?Sized> NotCopy for __Type {}
-
-        struct IsCopy<__Type: ?Sized>(PhantomData<__Type>);
-
-        impl<__Type> IsCopy<__Type>
-        where
-            __Type: Sized + Copy,
-        {
-            const VALUE: bool = true;
-        }
-
-        <IsCopy<T>>::VALUE
-    } as usize] = [];
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-71986.rs b/src/test/ui/const-generics/issue-71986.rs
deleted file mode 100644 (file)
index 6bfdba5..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-pub trait Foo<const B: bool> {}
-pub fn bar<T: Foo<{ true }>>() {}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-73899.rs b/src/test/ui/const-generics/issue-73899.rs
deleted file mode 100644 (file)
index 2a3a5ab..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// run-pass
-#![feature(const_evaluatable_checked)]
-#![feature(const_generics)]
-#![allow(incomplete_features)]
-
-trait Foo {}
-
-impl<const N: usize> Foo for [(); N] where Self: FooImpl<{ N == 0 }> {}
-
-trait FooImpl<const IS_ZERO: bool> {}
-
-impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {}
-
-impl<const N: usize> FooImpl<{ 0u8 != 0u8 }> for [(); N] {}
-
-fn foo<T: Foo>(_v: T) {}
-
-fn main() {
-    foo([]);
-    foo([()]);
-}
diff --git a/src/test/ui/const-generics/issue-74906.rs b/src/test/ui/const-generics/issue-74906.rs
deleted file mode 100644 (file)
index dc3c337..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// edition:2018
-// check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-const SIZE: usize = 16;
-
-struct Bar<const H: usize> {}
-
-struct Foo<const H: usize> {}
-
-impl<const H: usize> Foo<H> {
-    async fn biz(_: &[[u8; SIZE]]) -> Vec<()> {
-        vec![]
-    }
-
-    pub async fn baz(&self) -> Bar<H> {
-        Self::biz(&vec![]).await;
-        Bar {}
-    }
-}
-
-fn main() { }
diff --git a/src/test/ui/const-generics/issue-75763.rs b/src/test/ui/const-generics/issue-75763.rs
deleted file mode 100644 (file)
index c311de0..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// ignore-test
-// FIXME(const_generics): This test causes an ICE after reverting #76030.
-
-#![allow(incomplete_features)]
-#![feature(const_generics)]
-
-struct Bug<const S: &'static str>;
-
-fn main() {
-    let b: Bug::<{
-        unsafe {
-            // FIXME(const_generics): Decide on how to deal with invalid values as const params.
-            std::mem::transmute::<&[u8], &str>(&[0xC0, 0xC1, 0xF5])
-        }
-    }>;
-}
diff --git a/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.rs b/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.rs
deleted file mode 100644 (file)
index 8f02bfb..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-// This test is a minimized reproduction for #79518 where
-// during error handling for the type mismatch we would try
-// to evaluate std::mem::size_of::<Self::Assoc> causing an ICE
-
-trait Foo {
-    type Assoc: PartialEq;
-    const AssocInstance: Self::Assoc;
-
-    fn foo()
-    where
-        [(); std::mem::size_of::<Self::Assoc>()]: ,
-    {
-        Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
-        //~^ Error: mismatched types
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.stderr b/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.stderr
deleted file mode 100644 (file)
index c90774e..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-79518-default_trait_method_normalization.rs:16:32
-   |
-LL |         Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); _]`
-   |
-   = note: expected associated type `<Self as Foo>::Assoc`
-                        found array `[(); _]`
-   = help: consider constraining the associated type `<Self as Foo>::Assoc` to `[(); _]` or calling a method that returns `<Self as Foo>::Assoc`
-   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issue-80561-incorrect-param-env.rs b/src/test/ui/const-generics/issue-80561-incorrect-param-env.rs
deleted file mode 100644 (file)
index a34d74b..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// check-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-// This tests that the correct `param_env` is used so that
-// attempting to normalize `Self::N` does not cause an ICE.
-
-pub struct Foo<const N: usize>;
-
-impl<const N: usize> Foo<N> {
-    pub fn foo() {}
-}
-
-pub trait Bar {
-    const N: usize;
-    fn bar()
-    where
-        [(); Self::N]: ,
-    {
-        Foo::<{ Self::N }>::foo();
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issues/auxiliary/impl-const.rs b/src/test/ui/const-generics/issues/auxiliary/impl-const.rs
new file mode 100644 (file)
index 0000000..4a6b578
--- /dev/null
@@ -0,0 +1,10 @@
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+pub struct Num<const N: usize>;
+
+// Braces around const expression causes crash
+impl Num<{5}> {
+    pub fn five(&self) {
+    }
+}
index 0e228126d77896c9f2359c05383c2019557184a9..97ab07daccefb94843eac8d33c3ebd3dceca98ad 100644 (file)
@@ -6,9 +6,9 @@ fn promote<const N: i32>() {
     // works:
     //
     // let n = N;
-    // &n;
+    // let _ = &n;
 
-    &N;
+    let _ = &N;
 }
 
 fn main() {
diff --git a/src/test/ui/const-generics/issues/issue-61522-array-len-succ.full.stderr b/src/test/ui/const-generics/issues/issue-61522-array-len-succ.full.stderr
new file mode 100644 (file)
index 0000000..56deec1
--- /dev/null
@@ -0,0 +1,18 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-61522-array-len-succ.rs:6:40
+   |
+LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
+   |                                        ^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-61522-array-len-succ.rs:11:24
+   |
+LL |     fn inner(&self) -> &[u8; COUNT + 1] {
+   |                        ^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/issues/issue-61522-array-len-succ.min.stderr b/src/test/ui/const-generics/issues/issue-61522-array-len-succ.min.stderr
new file mode 100644 (file)
index 0000000..36a0a37
--- /dev/null
@@ -0,0 +1,20 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-61522-array-len-succ.rs:6:45
+   |
+LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
+   |                                             ^^^^^ cannot perform const operation using `COUNT`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `COUNT`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-61522-array-len-succ.rs:11:30
+   |
+LL |     fn inner(&self) -> &[u8; COUNT + 1] {
+   |                              ^^^^^ cannot perform const operation using `COUNT`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `COUNT`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/issues/issue-61522-array-len-succ.rs b/src/test/ui/const-generics/issues/issue-61522-array-len-succ.rs
new file mode 100644 (file)
index 0000000..d4a948b
--- /dev/null
@@ -0,0 +1,18 @@
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
+//[full]~^ ERROR constant expression depends on a generic parameter
+//[min]~^^ ERROR generic parameters may not be used
+
+impl<const COUNT: usize> MyArray<COUNT> {
+    fn inner(&self) -> &[u8; COUNT + 1] {
+        //[full]~^ ERROR constant expression depends on a generic parameter
+        //[min]~^^ ERROR generic parameters may not be used
+        &self.0
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.min.stderr b/src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.min.stderr
new file mode 100644 (file)
index 0000000..e96b9e7
--- /dev/null
@@ -0,0 +1,11 @@
+error: `&'static str` is forbidden as the type of a const generic parameter
+  --> $DIR/issue-66596-impl-trait-for-str-const-arg.rs:8:25
+   |
+LL | trait Trait<const NAME: &'static str> {
+   |                         ^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = help: more complex types are supported with `#![feature(const_generics)]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs b/src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs
new file mode 100644 (file)
index 0000000..2a741ba
--- /dev/null
@@ -0,0 +1,19 @@
+//[full] check-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+
+trait Trait<const NAME: &'static str> {
+//[min]~^ ERROR `&'static str` is forbidden
+    type Assoc;
+}
+
+impl Trait<"0"> for () {
+    type Assoc = ();
+}
+
+fn main() {
+    let _: <() as Trait<"0">>::Assoc = ();
+}
diff --git a/src/test/ui/const-generics/issues/issue-67375.full.stderr b/src/test/ui/const-generics/issues/issue-67375.full.stderr
new file mode 100644 (file)
index 0000000..0fe6527
--- /dev/null
@@ -0,0 +1,22 @@
+warning: cannot use constants which depend on generic parameters in types
+  --> $DIR/issue-67375.rs:8:12
+   |
+LL |     inner: [(); { [|_: &T| {}; 0].len() }],
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(const_evaluatable_unchecked)]` 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 #76200 <https://github.com/rust-lang/rust/issues/76200>
+
+error[E0392]: parameter `T` is never used
+  --> $DIR/issue-67375.rs:6:12
+   |
+LL | struct Bug<T> {
+   |            ^ unused parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: usize` instead
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issues/issue-67375.min.stderr b/src/test/ui/const-generics/issues/issue-67375.min.stderr
new file mode 100644 (file)
index 0000000..be81fa9
--- /dev/null
@@ -0,0 +1,21 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-67375.rs:8:25
+   |
+LL |     inner: [(); { [|_: &T| {}; 0].len() }],
+   |                         ^ cannot perform const operation using `T`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error[E0392]: parameter `T` is never used
+  --> $DIR/issue-67375.rs:6:12
+   |
+LL | struct Bug<T> {
+   |            ^ unused parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: usize` instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issues/issue-67375.rs b/src/test/ui/const-generics/issues/issue-67375.rs
new file mode 100644 (file)
index 0000000..a8875b8
--- /dev/null
@@ -0,0 +1,14 @@
+// revisions: full min
+
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(full, feature(const_generics))]
+
+struct Bug<T> {
+    //~^ ERROR parameter `T` is never used
+    inner: [(); { [|_: &T| {}; 0].len() }],
+    //[min]~^ ERROR generic parameters may not be used in const operations
+    //[full]~^^ WARN cannot use constants which depend on generic parameters in types
+    //[full]~^^^ WARN this was previously accepted by the compiler
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-67945-1.full.stderr b/src/test/ui/const-generics/issues/issue-67945-1.full.stderr
new file mode 100644 (file)
index 0000000..63c50b5
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-67945-1.rs:13:20
+   |
+LL | struct Bug<S> {
+   |            - this type parameter
+...
+LL |         let x: S = MaybeUninit::uninit();
+   |                -   ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found union `MaybeUninit`
+   |                |
+   |                expected due to this
+   |
+   = note: expected type parameter `S`
+                       found union `MaybeUninit<_>`
+
+error[E0392]: parameter `S` is never used
+  --> $DIR/issue-67945-1.rs:10:12
+   |
+LL | struct Bug<S> {
+   |            ^ unused parameter
+   |
+   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0392.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issues/issue-67945-1.min.stderr b/src/test/ui/const-generics/issues/issue-67945-1.min.stderr
new file mode 100644 (file)
index 0000000..074d36c
--- /dev/null
@@ -0,0 +1,30 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-67945-1.rs:13:16
+   |
+LL |         let x: S = MaybeUninit::uninit();
+   |                ^ cannot perform const operation using `S`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-67945-1.rs:16:45
+   |
+LL |         let b = &*(&x as *const _ as *const S);
+   |                                             ^ cannot perform const operation using `S`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error[E0392]: parameter `S` is never used
+  --> $DIR/issue-67945-1.rs:10:12
+   |
+LL | struct Bug<S> {
+   |            ^ unused parameter
+   |
+   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issues/issue-67945-1.rs b/src/test/ui/const-generics/issues/issue-67945-1.rs
new file mode 100644 (file)
index 0000000..84737e4
--- /dev/null
@@ -0,0 +1,22 @@
+// revisions: full min
+
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(full, feature(const_generics))]
+
+use std::marker::PhantomData;
+
+use std::mem::{self, MaybeUninit};
+
+struct Bug<S> {
+    //~^ ERROR parameter `S` is never used
+    A: [(); {
+        let x: S = MaybeUninit::uninit();
+        //[min]~^ ERROR generic parameters may not be used in const operations
+        //[full]~^^ ERROR mismatched types
+        let b = &*(&x as *const _ as *const S);
+        //[min]~^ ERROR generic parameters may not be used in const operations
+        0
+    }],
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-67945-2.full.stderr b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr
new file mode 100644 (file)
index 0000000..b900406
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-67945-2.rs:11:20
+   |
+LL | struct Bug<S> {
+   |            - this type parameter
+...
+LL |         let x: S = MaybeUninit::uninit();
+   |                -   ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found union `MaybeUninit`
+   |                |
+   |                expected due to this
+   |
+   = note: expected type parameter `S`
+                       found union `MaybeUninit<_>`
+
+error[E0392]: parameter `S` is never used
+  --> $DIR/issue-67945-2.rs:8:12
+   |
+LL | struct Bug<S> {
+   |            ^ unused parameter
+   |
+   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0392.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issues/issue-67945-2.min.stderr b/src/test/ui/const-generics/issues/issue-67945-2.min.stderr
new file mode 100644 (file)
index 0000000..c06df79
--- /dev/null
@@ -0,0 +1,30 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-67945-2.rs:11:16
+   |
+LL |         let x: S = MaybeUninit::uninit();
+   |                ^ cannot perform const operation using `S`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-67945-2.rs:14:45
+   |
+LL |         let b = &*(&x as *const _ as *const S);
+   |                                             ^ cannot perform const operation using `S`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error[E0392]: parameter `S` is never used
+  --> $DIR/issue-67945-2.rs:8:12
+   |
+LL | struct Bug<S> {
+   |            ^ unused parameter
+   |
+   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issues/issue-67945-2.rs b/src/test/ui/const-generics/issues/issue-67945-2.rs
new file mode 100644 (file)
index 0000000..4a46786
--- /dev/null
@@ -0,0 +1,20 @@
+// revisions: full min
+
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(full, feature(const_generics))]
+
+use std::mem::MaybeUninit;
+
+struct Bug<S> {
+    //~^ ERROR parameter `S` is never used
+    A: [(); {
+        let x: S = MaybeUninit::uninit();
+        //[min]~^ ERROR generic parameters may not be used in const operations
+        //[full]~^^ ERROR mismatched types
+        let b = &*(&x as *const _ as *const S);
+        //[min]~^ ERROR generic parameters may not be used in const operations
+        0
+    }],
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-67945-3.full.stderr b/src/test/ui/const-generics/issues/issue-67945-3.full.stderr
new file mode 100644 (file)
index 0000000..fa66252
--- /dev/null
@@ -0,0 +1,16 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-67945-3.rs:7:8
+   |
+LL |       A: [(); {
+   |  ________^
+LL | |
+LL | |         let x: Option<Box<Self>> = None;
+LL | |
+LL | |         0
+LL | |     }],
+   | |______^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-67945-3.min.stderr b/src/test/ui/const-generics/issues/issue-67945-3.min.stderr
new file mode 100644 (file)
index 0000000..5c30429
--- /dev/null
@@ -0,0 +1,8 @@
+error: generic `Self` types are currently not permitted in anonymous constants
+  --> $DIR/issue-67945-3.rs:9:27
+   |
+LL |         let x: Option<Box<Self>> = None;
+   |                           ^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-67945-3.rs b/src/test/ui/const-generics/issues/issue-67945-3.rs
new file mode 100644 (file)
index 0000000..5bad61c
--- /dev/null
@@ -0,0 +1,16 @@
+// revisions: full min
+
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(full, feature(const_generics))]
+
+struct Bug<S: ?Sized> {
+    A: [(); {
+        //[full]~^ ERROR constant expression depends on a generic parameter
+        let x: Option<Box<Self>> = None;
+        //[min]~^ ERROR generic `Self` types are currently not permitted in anonymous constants
+        0
+    }],
+    B: S
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-68104-print-stack-overflow.rs b/src/test/ui/const-generics/issues/issue-68104-print-stack-overflow.rs
new file mode 100644 (file)
index 0000000..43c3999
--- /dev/null
@@ -0,0 +1,15 @@
+// aux-build:impl-const.rs
+// run-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+extern crate impl_const;
+
+use impl_const::*;
+
+pub fn main() {
+    let n = Num::<5>;
+    n.five();
+}
diff --git a/src/test/ui/const-generics/issues/issue-70180-1-stalled_on.rs b/src/test/ui/const-generics/issues/issue-70180-1-stalled_on.rs
new file mode 100644 (file)
index 0000000..f055482
--- /dev/null
@@ -0,0 +1,37 @@
+// build-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+pub fn works() {
+    let array/*: [_; _]*/ = default_array();
+    let _: [_; 4] = array;
+    Foo::foo(&array);
+}
+
+pub fn didnt_work() {
+    let array/*: [_; _]*/ = default_array();
+    Foo::foo(&array);
+    let _: [_; 4] = array;
+}
+
+trait Foo {
+    fn foo(&self) {}
+}
+
+impl Foo for [i32; 4] {}
+impl Foo for [i64; 8] {}
+
+// Only needed because `[_; _]` is not valid type syntax.
+fn default_array<T, const N: usize>() -> [T; N]
+where
+    [T; N]: Default,
+{
+    Default::default()
+}
+
+fn main() {
+    works();
+    didnt_work();
+}
diff --git a/src/test/ui/const-generics/issues/issue-70180-2-stalled_on.rs b/src/test/ui/const-generics/issues/issue-70180-2-stalled_on.rs
new file mode 100644 (file)
index 0000000..21cefc0
--- /dev/null
@@ -0,0 +1,37 @@
+// build-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+fn works() {
+    let array/*: [u8; _]*/ = default_byte_array();
+    let _: [_; 4] = array;
+    Foo::foo(&array);
+}
+
+fn didnt_work() {
+    let array/*: [u8; _]*/ = default_byte_array();
+    Foo::foo(&array);
+    let _: [_; 4] = array;
+}
+
+trait Foo<T> {
+    fn foo(&self) {}
+}
+
+impl Foo<i32> for [u8; 4] {}
+impl Foo<i64> for [u8; 8] {}
+
+// Only needed because `[u8; _]` is not valid type syntax.
+fn default_byte_array<const N: usize>() -> [u8; N]
+where
+    [u8; N]: Default,
+{
+    Default::default()
+}
+
+fn main() {
+    works();
+    didnt_work();
+}
diff --git a/src/test/ui/const-generics/issues/issue-71202.rs b/src/test/ui/const-generics/issues/issue-71202.rs
new file mode 100644 (file)
index 0000000..78dee17
--- /dev/null
@@ -0,0 +1,33 @@
+// check-pass
+
+#![feature(const_generics)]
+#![allow(incomplete_features, const_evaluatable_unchecked)]
+
+use std::marker::PhantomData;
+
+struct DataHolder<T> {
+    item: T,
+}
+
+impl<T: Copy> DataHolder<T> {
+    const ITEM_IS_COPY: [(); 1 - {
+        trait NotCopy {
+            const VALUE: bool = false;
+        }
+
+        impl<__Type: ?Sized> NotCopy for __Type {}
+
+        struct IsCopy<__Type: ?Sized>(PhantomData<__Type>);
+
+        impl<__Type> IsCopy<__Type>
+        where
+            __Type: Sized + Copy,
+        {
+            const VALUE: bool = true;
+        }
+
+        <IsCopy<T>>::VALUE
+    } as usize] = [];
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-71986.rs b/src/test/ui/const-generics/issues/issue-71986.rs
new file mode 100644 (file)
index 0000000..6bfdba5
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+pub trait Foo<const B: bool> {}
+pub fn bar<T: Foo<{ true }>>() {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-73899.rs b/src/test/ui/const-generics/issues/issue-73899.rs
new file mode 100644 (file)
index 0000000..2a3a5ab
--- /dev/null
@@ -0,0 +1,21 @@
+// run-pass
+#![feature(const_evaluatable_checked)]
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+trait Foo {}
+
+impl<const N: usize> Foo for [(); N] where Self: FooImpl<{ N == 0 }> {}
+
+trait FooImpl<const IS_ZERO: bool> {}
+
+impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {}
+
+impl<const N: usize> FooImpl<{ 0u8 != 0u8 }> for [(); N] {}
+
+fn foo<T: Foo>(_v: T) {}
+
+fn main() {
+    foo([]);
+    foo([()]);
+}
diff --git a/src/test/ui/const-generics/issues/issue-74906.rs b/src/test/ui/const-generics/issues/issue-74906.rs
new file mode 100644 (file)
index 0000000..dc3c337
--- /dev/null
@@ -0,0 +1,24 @@
+// edition:2018
+// check-pass
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+const SIZE: usize = 16;
+
+struct Bar<const H: usize> {}
+
+struct Foo<const H: usize> {}
+
+impl<const H: usize> Foo<H> {
+    async fn biz(_: &[[u8; SIZE]]) -> Vec<()> {
+        vec![]
+    }
+
+    pub async fn baz(&self) -> Bar<H> {
+        Self::biz(&vec![]).await;
+        Bar {}
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/const-generics/issues/issue-75763.rs b/src/test/ui/const-generics/issues/issue-75763.rs
new file mode 100644 (file)
index 0000000..c311de0
--- /dev/null
@@ -0,0 +1,16 @@
+// ignore-test
+// FIXME(const_generics): This test causes an ICE after reverting #76030.
+
+#![allow(incomplete_features)]
+#![feature(const_generics)]
+
+struct Bug<const S: &'static str>;
+
+fn main() {
+    let b: Bug::<{
+        unsafe {
+            // FIXME(const_generics): Decide on how to deal with invalid values as const params.
+            std::mem::transmute::<&[u8], &str>(&[0xC0, 0xC1, 0xF5])
+        }
+    }>;
+}
diff --git a/src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.rs b/src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.rs
new file mode 100644 (file)
index 0000000..8f02bfb
--- /dev/null
@@ -0,0 +1,21 @@
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+// This test is a minimized reproduction for #79518 where
+// during error handling for the type mismatch we would try
+// to evaluate std::mem::size_of::<Self::Assoc> causing an ICE
+
+trait Foo {
+    type Assoc: PartialEq;
+    const AssocInstance: Self::Assoc;
+
+    fn foo()
+    where
+        [(); std::mem::size_of::<Self::Assoc>()]: ,
+    {
+        Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
+        //~^ Error: mismatched types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.stderr b/src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.stderr
new file mode 100644 (file)
index 0000000..c90774e
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-79518-default_trait_method_normalization.rs:16:32
+   |
+LL |         Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); _]`
+   |
+   = note: expected associated type `<Self as Foo>::Assoc`
+                        found array `[(); _]`
+   = help: consider constraining the associated type `<Self as Foo>::Assoc` to `[(); _]` or calling a method that returns `<Self as Foo>::Assoc`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issues/issue-80561-incorrect-param-env.rs b/src/test/ui/const-generics/issues/issue-80561-incorrect-param-env.rs
new file mode 100644 (file)
index 0000000..a34d74b
--- /dev/null
@@ -0,0 +1,24 @@
+// check-pass
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+// This tests that the correct `param_env` is used so that
+// attempting to normalize `Self::N` does not cause an ICE.
+
+pub struct Foo<const N: usize>;
+
+impl<const N: usize> Foo<N> {
+    pub fn foo() {}
+}
+
+pub trait Bar {
+    const N: usize;
+    fn bar()
+    where
+        [(); Self::N]: ,
+    {
+        Foo::<{ Self::N }>::foo();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-83765.rs b/src/test/ui/const-generics/issues/issue-83765.rs
new file mode 100644 (file)
index 0000000..f34badc
--- /dev/null
@@ -0,0 +1,38 @@
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+trait TensorDimension {
+    const DIM: usize;
+}
+
+trait TensorSize: TensorDimension {
+    fn size(&self) -> [usize; Self::DIM];
+}
+
+trait Broadcastable: TensorSize + Sized {
+    type Element;
+    fn lazy_updim<const NEWDIM: usize>(&self, size: [usize; NEWDIM]) {}
+}
+
+struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> {
+    reference: &'a T,
+    closure: F,
+}
+
+impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension
+    for BMap<'a, R, T, F, DIM>
+{
+    const DIM: usize = DIM;
+}
+impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize
+    for BMap<'a, R, T, F, DIM>
+{
+    fn size(&self) -> [usize; DIM] {
+        //~^ ERROR: method not compatible with trait [E0308]
+        self.reference.size()
+        //~^ ERROR: unconstrained generic constant
+        //~| ERROR: mismatched types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr
new file mode 100644 (file)
index 0000000..ef785bf
--- /dev/null
@@ -0,0 +1,29 @@
+error[E0308]: method not compatible with trait
+  --> $DIR/issue-83765.rs:30:5
+   |
+LL |     fn size(&self) -> [usize; DIM] {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
+   |
+   = note: expected type `Self::DIM`
+              found type `DIM`
+
+error: unconstrained generic constant
+  --> $DIR/issue-83765.rs:32:24
+   |
+LL |         self.reference.size()
+   |                        ^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); Self::DIM]:`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-83765.rs:32:9
+   |
+LL |         self.reference.size()
+   |         ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM`
+   |
+   = note: expected type `DIM`
+              found type `Self::DIM`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issues/issue-85848.rs b/src/test/ui/const-generics/issues/issue-85848.rs
new file mode 100644 (file)
index 0000000..4787198
--- /dev/null
@@ -0,0 +1,31 @@
+#![feature(const_generics, const_fn_trait_bound, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+trait _Contains<T> {
+    const does_contain: bool;
+}
+
+trait Contains<T, const Satisfied: bool> {}
+
+trait Delegates<T> {}
+
+impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
+
+const fn contains<A, B>() -> bool
+where
+    A: _Contains<B>,
+{
+    A::does_contain
+}
+
+impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
+
+fn writes_to_path<C>(cap: &C) {
+    writes_to_specific_path(&cap);
+    //~^ ERROR: the trait bound `(): _Contains<&C>` is not satisfied [E0277]
+    //~| ERROR: unconstrained generic constant
+}
+
+fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-85848.stderr b/src/test/ui/const-generics/issues/issue-85848.stderr
new file mode 100644 (file)
index 0000000..5e65136
--- /dev/null
@@ -0,0 +1,44 @@
+error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied
+  --> $DIR/issue-85848.rs:24:5
+   |
+LL |     writes_to_specific_path(&cap);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ the trait `_Contains<&C>` is not implemented for `()`
+...
+LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
+   |                               ------------- required by this bound in `writes_to_specific_path`
+   |
+note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
+  --> $DIR/issue-85848.rs:21:12
+   |
+LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^     ^
+note: required because of the requirements on the impl of `Delegates<()>` for `&C`
+  --> $DIR/issue-85848.rs:12:12
+   |
+LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
+   |            ^^^^^^^^^^^^     ^
+
+error: unconstrained generic constant
+  --> $DIR/issue-85848.rs:24:5
+   |
+LL |     writes_to_specific_path(&cap);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
+   |                               ------------- required by this bound in `writes_to_specific_path`
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { contains::<T, U>() }]:`
+note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
+  --> $DIR/issue-85848.rs:21:12
+   |
+LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^     ^
+note: required because of the requirements on the impl of `Delegates<()>` for `&C`
+  --> $DIR/issue-85848.rs:12:12
+   |
+LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
+   |            ^^^^^^^^^^^^     ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issues/issue-86820.rs b/src/test/ui/const-generics/issues/issue-86820.rs
new file mode 100644 (file)
index 0000000..0465040
--- /dev/null
@@ -0,0 +1,25 @@
+// Regression test for the ICE described in #86820.
+
+#![allow(unused,dead_code)]
+use std::ops::BitAnd;
+
+const C: fn() = || is_set();
+fn is_set() {
+    0xffu8.bit::<0>();
+}
+
+trait Bits {
+    fn bit<const I : u8>(self) -> bool;
+    //~^ NOTE: the const parameter `I` has type `usize`, but the declaration in trait `Bits::bit` has type `u8`
+}
+
+impl Bits for u8 {
+    fn bit<const I : usize>(self) -> bool {
+    //~^ ERROR: method `bit` has an incompatible const parameter type for trait [E0053]
+        let i = 1 << I;
+        let mask = u8::from(i);
+        mask & self == mask
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-86820.stderr b/src/test/ui/const-generics/issues/issue-86820.stderr
new file mode 100644 (file)
index 0000000..f4396f2
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0053]: method `bit` has an incompatible const parameter type for trait
+  --> $DIR/issue-86820.rs:17:18
+   |
+LL |     fn bit<const I : usize>(self) -> bool {
+   |                  ^
+   |
+note: the const parameter `I` has type `usize`, but the declaration in trait `Bits::bit` has type `u8`
+  --> $DIR/issue-86820.rs:12:18
+   |
+LL |     fn bit<const I : u8>(self) -> bool;
+   |                  ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/const-generics/issues/issue-87076.rs b/src/test/ui/const-generics/issues/issue-87076.rs
new file mode 100644 (file)
index 0000000..5dfda94
--- /dev/null
@@ -0,0 +1,20 @@
+// build-pass
+
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+#[derive(PartialEq, Eq)]
+pub struct UnitDims {
+    pub time: u8,
+    pub length: u8,
+}
+
+pub struct UnitValue<const DIMS: UnitDims>;
+
+impl<const DIMS: UnitDims> UnitValue<DIMS> {
+    fn crash() {}
+}
+
+fn main() {
+    UnitValue::<{ UnitDims { time: 1, length: 2 } }>::crash();
+}
index d845e00694a2dfdac606b6a0b7cec12531cb6452..ae8863c567d0fdd28a54426d3e0695dd5ac15551 100644 (file)
@@ -13,7 +13,7 @@ fn b() {
     //~| ERROR expected trait, found constant `BAR`
     //~| ERROR type provided when a constant was expected
     //~| WARN trait objects without an explicit `dyn` are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
 }
 fn c() {
     foo::<3 + 3>(); //~ ERROR expressions must be enclosed in braces
index 857498a1111f5d16b9222a3464ca6c3b8c0d8ebf..b93bd6c6fa064b26b998c9ac61e0807af11830f9 100644 (file)
@@ -138,7 +138,7 @@ LL |     foo::<BAR + BAR>();
    |           ^^^^^^^^^ help: use `dyn`: `dyn BAR + BAR`
    |
    = note: `#[warn(bare_trait_objects)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error[E0747]: type provided when a constant was expected
index 6830288acc0ad25c49e82e5b1b7fcf36c5a085b1..382dd0ee5a64eaa909cbc9b8fdb4d26a2427ed08 100644 (file)
@@ -1,16 +1,18 @@
 error[E0277]: the trait bound `A<{_: usize}>: Bar<{_: usize}>` is not satisfied
   --> $DIR/unused-substs-1.rs:12:13
    |
-LL | / struct A<const N: usize>
-LL | | where
-LL | |     A<N>: Bar<N>;
-   | |_________________- required by `A`
-...
-LL |       let _ = A;
-   |               ^ the trait `Bar<{_: usize}>` is not implemented for `A<{_: usize}>`
+LL |     let _ = A;
+   |             ^ the trait `Bar<{_: usize}>` is not implemented for `A<{_: usize}>`
    |
    = help: the following implementations were found:
              <A<7_usize> as Bar<N>>
+note: required by `A`
+  --> $DIR/unused-substs-1.rs:7:1
+   |
+LL | / struct A<const N: usize>
+LL | | where
+LL | |     A<N>: Bar<N>;
+   | |_________________^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-ptr/out_of_bounds_read.rs b/src/test/ui/const-ptr/out_of_bounds_read.rs
new file mode 100644 (file)
index 0000000..c45198c
--- /dev/null
@@ -0,0 +1,16 @@
+// error-pattern: evaluation of constant value failed
+
+#![feature(const_ptr_read)]
+#![feature(const_ptr_offset)]
+
+fn main() {
+    use std::ptr;
+
+    const DATA: [u32; 1] = [42];
+
+    const PAST_END_PTR: *const u32 = unsafe { DATA.as_ptr().add(1) };
+
+    const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) };
+    const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() };
+    const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() };
+}
diff --git a/src/test/ui/const-ptr/out_of_bounds_read.stderr b/src/test/ui/const-ptr/out_of_bounds_read.stderr
new file mode 100644 (file)
index 0000000..9254177
--- /dev/null
@@ -0,0 +1,70 @@
+error[E0080]: evaluation of constant value failed
+  --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+LL |     unsafe { copy_nonoverlapping(src, dst, count) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              |
+   |              memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   |              inside `copy_nonoverlapping::<u32>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   | 
+  ::: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
+   |         --------------------------------------------- inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   | 
+  ::: $DIR/out_of_bounds_read.rs:13:33
+   |
+LL |     const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) };
+   |                                 ----------------------- inside `_READ` at $DIR/out_of_bounds_read.rs:13:33
+
+error[E0080]: evaluation of constant value failed
+  --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+LL |     unsafe { copy_nonoverlapping(src, dst, count) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              |
+   |              memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   |              inside `copy_nonoverlapping::<u32>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   | 
+  ::: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
+   |         --------------------------------------------- inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   | 
+  ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { read(self) }
+   |                  ---------- inside `ptr::const_ptr::<impl *const u32>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   | 
+  ::: $DIR/out_of_bounds_read.rs:14:39
+   |
+LL |     const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() };
+   |                                       ------------------- inside `_CONST_READ` at $DIR/out_of_bounds_read.rs:14:39
+
+error[E0080]: evaluation of constant value failed
+  --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+LL |     unsafe { copy_nonoverlapping(src, dst, count) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              |
+   |              memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   |              inside `copy_nonoverlapping::<u32>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   | 
+  ::: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
+   |         --------------------------------------------- inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   | 
+  ::: $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+   |
+LL |         unsafe { read(self) }
+   |                  ---------- inside `ptr::mut_ptr::<impl *mut u32>::read` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+   | 
+  ::: $DIR/out_of_bounds_read.rs:15:37
+   |
+LL |     const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() };
+   |                                     --------------------------------- inside `_MUT_READ` at $DIR/out_of_bounds_read.rs:15:37
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
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 187e2760ad2ca90e6ccd748237f58893a3f3c043..5f23cc2311db0be75c7b1341c51d56134c3bef23 100644 (file)
@@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:26:5
    |
 LL |     const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc2, but expected initialized plain (non-pointer) bytes
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc3, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc2────────╼                         │ ╾──────╼
+               ╾───────alloc3────────╼                         │ ╾──────╼
            }
 
 error: any use of this value will cause an error
@@ -47,11 +47,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:41:5
    |
 LL |     const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc18, but expected initialized plain (non-pointer) bytes
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc19, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc18───────╼                         │ ╾──────╼
+               ╾───────alloc19───────╼                         │ ╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -102,11 +102,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:59:5
    |
 LL |     const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc38, but expected initialized plain (non-pointer) bytes
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc39, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc38───────╼                         │ ╾──────╼
+               ╾───────alloc39───────╼                         │ ╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -135,11 +135,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:69:5
    |
 LL |     const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc50, but expected initialized plain (non-pointer) bytes
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc51, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc50───────╼                         │ ╾──────╼
+               ╾───────alloc51───────╼                         │ ╾──────╼
            }
 
 error: any use of this value will cause an error
@@ -201,11 +201,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:92:5
    |
 LL |     const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc71, but expected initialized plain (non-pointer) bytes
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc72, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc71───────╼                         │ ╾──────╼
+               ╾───────alloc72───────╼                         │ ╾──────╼
            }
 
 error: any use of this value will cause an error
@@ -256,11 +256,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:111:5
    |
 LL |     const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc86, but expected initialized plain (non-pointer) bytes
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc87, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc86───────╼                         │ ╾──────╼
+               ╾───────alloc87───────╼                         │ ╾──────╼
            }
 
 error: any use of this value will cause an error
@@ -289,11 +289,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:122:5
    |
 LL |     const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc95, but expected initialized plain (non-pointer) bytes
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc96, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc95───────╼                         │ ╾──────╼
+               ╾───────alloc96───────╼                         │ ╾──────╼
            }
 
 error: any use of this value will cause an error
index b33b1475a2221722c814ae3d651e370e906f0728..e4455d86a1440b7f183c7d96582f5557bcd6d5f2 100644 (file)
@@ -1,35 +1,35 @@
 #![feature(const_panic)]
-#![allow(non_fmt_panic)]
+#![allow(non_fmt_panics)]
 #![crate_type = "lib"]
 
 const MSG: &str = "hello";
 
 const Z: () = std::panic!("cheese");
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
 
 const Z2: () = std::panic!();
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
 
 const Y: () = std::unreachable!();
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
 
 const X: () = std::unimplemented!();
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
 //
 const W: () = std::panic!(MSG);
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
 
 const Z_CORE: () = core::panic!("cheese");
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
 
 const Z2_CORE: () = core::panic!();
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
 
 const Y_CORE: () = core::unreachable!();
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
 
 const X_CORE: () = core::unimplemented!();
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
 
 const W_CORE: () = core::panic!(MSG);
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
index 3c890f78af741f193b1f5f5bfad7cd467daf3df2..c0c749ede56126084186ec71a2b79d34283794b8 100644 (file)
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic.rs:7:15
    |
 LL | const Z: () = std::panic!("cheese");
-   | --------------^^^^^^^^^^^^^^^^^^^^^-
-   |               |
-   |               the evaluated program panicked at 'cheese', $DIR/const_panic.rs:7:15
+   |               ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:7:15
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic.rs:10:16
    |
 LL | const Z2: () = std::panic!();
-   | ---------------^^^^^^^^^^^^^-
-   |                |
-   |                the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:10:16
+   |                ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:10:16
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic.rs:13:15
    |
 LL | const Y: () = std::unreachable!();
-   | --------------^^^^^^^^^^^^^^^^^^^-
-   |               |
-   |               the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:13:15
+   |               ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:13:15
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic.rs:16:15
    |
 LL | const X: () = std::unimplemented!();
-   | --------------^^^^^^^^^^^^^^^^^^^^^-
-   |               |
-   |               the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:16:15
+   |               ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:16:15
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic.rs:19:15
    |
 LL | const W: () = std::panic!(MSG);
-   | --------------^^^^^^^^^^^^^^^^-
-   |               |
-   |               the evaluated program panicked at 'hello', $DIR/const_panic.rs:19:15
+   |               ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:19:15
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic.rs:22:20
    |
 LL | const Z_CORE: () = core::panic!("cheese");
-   | -------------------^^^^^^^^^^^^^^^^^^^^^^-
-   |                    |
-   |                    the evaluated program panicked at 'cheese', $DIR/const_panic.rs:22:20
+   |                    ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:22:20
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic.rs:25:21
    |
 LL | const Z2_CORE: () = core::panic!();
-   | --------------------^^^^^^^^^^^^^^-
-   |                     |
-   |                     the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:25:21
+   |                     ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:25:21
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic.rs:28:20
    |
 LL | const Y_CORE: () = core::unreachable!();
-   | -------------------^^^^^^^^^^^^^^^^^^^^-
-   |                    |
-   |                    the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:28:20
+   |                    ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:28:20
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic.rs:31:20
    |
 LL | const X_CORE: () = core::unimplemented!();
-   | -------------------^^^^^^^^^^^^^^^^^^^^^^-
-   |                    |
-   |                    the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:31:20
+   |                    ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:31:20
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic.rs:34:20
    |
 LL | const W_CORE: () = core::panic!(MSG);
-   | -------------------^^^^^^^^^^^^^^^^^-
-   |                    |
-   |                    the evaluated program panicked at 'hello', $DIR/const_panic.rs:34:20
+   |                    ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:34:20
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
index 6b03e847def140dbf98864f75a05aaef99254ad9..1ea0845c968c6fcaa50a88e7341628e3667efdfa 100644 (file)
@@ -7,13 +7,13 @@
 use core::panic::PanicInfo;
 
 const Z: () = panic!("cheese");
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
 
 const Y: () = unreachable!();
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
 
 const X: () = unimplemented!();
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
 
 #[lang = "eh_personality"]
 fn eh() {}
index 2a3ad3ca18060c0768067c643d7acd2886548763..9abf8a20b8a35e769e56ae8f413cd512d7b34bb9 100644 (file)
@@ -1,30 +1,24 @@
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic_libcore_bin.rs:9:15
    |
 LL | const Z: () = panic!("cheese");
-   | --------------^^^^^^^^^^^^^^^^-
-   |               |
-   |               the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_bin.rs:9:15
+   |               ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_bin.rs:9:15
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic_libcore_bin.rs:12:15
    |
 LL | const Y: () = unreachable!();
-   | --------------^^^^^^^^^^^^^^-
-   |               |
-   |               the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_bin.rs:12:15
+   |               ^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_bin.rs:12:15
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic_libcore_bin.rs:15:15
    |
 LL | const X: () = unimplemented!();
-   | --------------^^^^^^^^^^^^^^^^-
-   |               |
-   |               the evaluated program panicked at 'not implemented', $DIR/const_panic_libcore_bin.rs:15:15
+   |               ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_libcore_bin.rs:15:15
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
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..11f6a58be360ce96550a973884a357396f2006af 100644 (file)
@@ -1,16 +1,12 @@
-#![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
-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
-//~| WARN this was previously accepted by the compiler but is being phased out
+
+// bad, will thus error in miri
+const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR evaluation of constant value failed
+//~| is not a valid pointer
+const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR evaluation of constant value failed
+//~| is not a valid pointer
index df8b33a0898f659deab953e1a3b9e7614a8a5dcd..ca3290077378a9edf8a7fb0a3135f9265f5b07a8 100644 (file)
@@ -1,36 +1,15 @@
-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
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const_raw_ptr_ops2.rs:9:26
    |
 LL | const Z2: i32 = unsafe { *(42 as *const i32) };
-   | -------------------------^^^^^^^^^^^^^^^^^^^---
-   |                          |
-   |                          unable to turn bytes into a pointer
-   |
-   = 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>
+   |                          ^^^^^^^^^^^^^^^^^^^ 0x2a is not a valid pointer
 
-error: any use of this value will cause an error
-  --> $DIR/const_raw_ptr_ops2.rs:15:26
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const_raw_ptr_ops2.rs:11:26
    |
 LL | const Z3: i32 = unsafe { *(44 as *const i32) };
-   | -------------------------^^^^^^^^^^^^^^^^^^^---
-   |                          |
-   |                          unable to turn bytes into a pointer
-   |
-   = 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>
+   |                          ^^^^^^^^^^^^^^^^^^^ 0x2c is not a valid pointer
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0080`.
index 45c429c7eb0d50831381a5e4312707e2ae2c2a9c..610531c7b4c9e8fad03dcd8703b3fbe66565b542 100644 (file)
@@ -5,9 +5,8 @@ use std::mem;
 // Make sure we error with the right kind of error on a too large slice.
 const TEST: () = { unsafe {
     let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
-    let _val = &*slice; //~ ERROR: any use of this value will cause an error
+    let _val = &*slice; //~ ERROR: evaluation of constant value failed
     //~| slice is bigger than largest supported object
-    //~| WARN this was previously accepted by the compiler but is being phased out
 } };
 
 fn main() {}
index 224fbb62a46492d89d1d376e69b4e5e450fc26b3..5665a9c3e05239c853efb8059e19c40a4d189f60 100644 (file)
@@ -1,18 +1,9 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/dangling.rs:8:16
    |
-LL | / const TEST: () = { unsafe {
-LL | |     let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
-LL | |     let _val = &*slice;
-   | |                ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object
-LL | |
-LL | |
-LL | | } };
-   | |____-
-   |
-   = 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>
+LL |     let _val = &*slice;
+   |                ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0080`.
index 43d79badd72826e8d177523e8b285af8ef7c5f45..4df541eeeb4e9ae14e6da37f044e831a73db56ee 100644 (file)
@@ -8,8 +8,7 @@ const FOO: i32 = foo();
 const fn foo() -> i32 {
     unsafe {
         let _ = intrinsics::const_allocate(4, 3) as * mut i32;
-        //~^ error: any use of this value will cause an error [const_err]
-        //~| WARN this was previously accepted by the compiler but is being phased out
+        //~^ error: evaluation of constant value failed
     }
     1
 
index 3d529ab4ca6e599aa04bcc50b884376a76a1c813..327e2911205a3f465aa5d407b612893d2a84585e 100644 (file)
@@ -1,19 +1,15 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/alloc_intrinsic_errors.rs:10:17
    |
 LL | const FOO: i32 = foo();
-   | -----------------------
+   |                  ----- inside `FOO` at $DIR/alloc_intrinsic_errors.rs:7:18
 ...
 LL |         let _ = intrinsics::const_allocate(4, 3) as * mut i32;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                 |
    |                 align has to be a power of 2, `3` is not a power of 2
    |                 inside `foo` at $DIR/alloc_intrinsic_errors.rs:10:17
-   |                 inside `FOO` at $DIR/alloc_intrinsic_errors.rs:7:18
-   |
-   = 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
 
+For more information about this error, try `rustc --explain E0080`.
index 92d990f1498e2f63ce86b46b90391fd063729a54..c11fea8533d8517eeae0d68c4de907b4e43fc35d 100644 (file)
@@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/alloc_intrinsic_uninit.rs:9:1
    |
 LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .<deref>, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc1──╼                                     │ ╾──╼
+               ╾─alloc2──╼                                     │ ╾──╼
            }
 
 error: aborting due to previous error
index 6d63233997da468ce7ee2f653f014660b841c17d..58d24dc2e8e0be709bb71448529a50439574d875 100644 (file)
@@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/alloc_intrinsic_uninit.rs:9:1
    |
 LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .<deref>, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc1────────╼                         │ ╾──────╼
+               ╾───────alloc2────────╼                         │ ╾──────╼
            }
 
 error: aborting due to previous error
index f2d9758b8dc08cee390edb4d8483e8c0824508ff..baa1848e9c31ac264ca8595c41b81b58e4a36c03 100644 (file)
@@ -17,8 +17,7 @@ const fn wat(x: u64) -> &'static u64 {
     unsafe { transmute(&x) }
 }
 const X: u64 = *wat(42);
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 fn main() {
     println!("{}", X);
index 0389471edb57ce84efaf6d9ec01d879c2a99394d..4fd8e18909655bacc5bfbfc4022dcb7619d8b266 100644 (file)
@@ -1,14 +1,9 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/issue-49296.rs:19:16
    |
 LL | const X: u64 = *wat(42);
-   | ---------------^^^^^^^^-
-   |                |
-   |                pointer to alloc1 was dereferenced after this allocation got freed
-   |
-   = 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>
+   |                ^^^^^^^^ pointer to alloc2 was dereferenced after this allocation got freed
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0080`.
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 dd18a98035bca05df11fdaa1390cd63a60451c59..78cf25308fff9e637dd3f8cd8d8470e36876a057 100644 (file)
@@ -9,7 +9,7 @@ struct PrintName;
 
 impl PrintName {
     const VOID: ! = panic!();
-    //~^ ERROR any use of this value will cause an error
+    //~^ ERROR evaluation of constant value failed
 }
 
 fn main() {
index e186240f53ad2f9e2b358bf53f79e8acd58a0050..085609483098b73e8b3182828352331b76bc43ee 100644 (file)
@@ -1,10 +1,8 @@
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/panic-assoc-never-type.rs:11:21
    |
 LL |     const VOID: ! = panic!();
-   |     ----------------^^^^^^^^-
-   |                     |
-   |                     the evaluated program panicked at 'explicit panic', $DIR/panic-assoc-never-type.rs:11:21
+   |                     ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/panic-assoc-never-type.rs:11:21
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
index 71b489d828c081fd1c3c91285aa0be381d110d26..dd875768b168faa9ec9bad7c595a250670e32a87 100644 (file)
@@ -4,7 +4,7 @@
 #![feature(never_type)]
 
 const VOID: ! = panic!();
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
 
 fn main() {
     let _ = VOID;
index 2254c3dcfdfb0c80c9f7436887047b0f6216917e..9b7f2181c166258d6b00584cf497585a96e6a047 100644 (file)
@@ -1,10 +1,8 @@
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/panic-never-type.rs:6:17
    |
 LL | const VOID: ! = panic!();
-   | ----------------^^^^^^^^-
-   |                 |
-   |                 the evaluated program panicked at 'explicit panic', $DIR/panic-never-type.rs:6:17
+   |                 ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/panic-never-type.rs:6:17
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
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 c14457490ac45f65af1e31a7f9e9200d97e11549..ff90bb5fdd2423dbf0e866abdec69236bd5b7962 100644 (file)
@@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ref_to_int_match.rs:26:1
    |
 LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc2, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc3, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc2──╼                                     │ ╾──╼
+               ╾─alloc3──╼                                     │ ╾──╼
            }
 
 error: could not evaluate constant pattern
index 6ea1cf145a26c63c4bf9a132caf6d2ac37be2398..499c4536c4b661a9be0def683d1bfb2c0ef2811f 100644 (file)
@@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ref_to_int_match.rs:26:1
    |
 LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc2, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc3, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc2────────╼                         │ ╾──────╼
+               ╾───────alloc3────────╼                         │ ╾──────╼
            }
 
 error: could not evaluate constant pattern
index 2274366fa216b6d46beea229015c37dfbc2fa802..850acb52b0c8987b9be23f7fade77904202b3c59 100644 (file)
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:24:1
    |
 LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000001 at .<enum-tag>, but expected a valid enum tag
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered 0x00000001, but expected a valid enum tag
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
@@ -13,29 +13,29 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:27:1
    |
 LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc8 at .<enum-tag>, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered pointer to alloc9, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc8──╼                                     │ ╾──╼
+               ╾─alloc9──╼                                     │ ╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:30:1
    |
 LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc12 at .0.<enum-tag>, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.<enum-tag>: encountered pointer to alloc13, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc12─╼                                     │ ╾──╼
+               ╾─alloc13─╼                                     │ ╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:42:1
    |
 LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000000 at .<enum-tag>, but expected a valid enum tag
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered 0x00000000, but expected a valid enum tag
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
@@ -46,29 +46,29 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:44:1
    |
 LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc18 at .<enum-tag>, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered pointer to alloc19, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc18─╼                                     │ ╾──╼
+               ╾─alloc19─╼                                     │ ╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:47:1
    |
 LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc22 at .0.<enum-tag>, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.<enum-tag>: encountered pointer to alloc23, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc22─╼                                     │ ╾──╼
+               ╾─alloc23─╼                                     │ ╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:56:1
    |
 LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .<enum-tag>, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
@@ -79,18 +79,18 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:60:1
    |
 LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc28 at .<enum-tag>, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered pointer to alloc29, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc28─╼                                     │ ╾──╼
+               ╾─alloc29─╼                                     │ ╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:77:1
    |
 LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<enum-variant(B)>.0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(B)>.0: encountered a value of the never type `!`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 1, align: 1) {
@@ -101,7 +101,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:79:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at .<enum-variant(D)>.0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(D)>.0: encountered a value of uninhabited type Never
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 1, align: 1) {
@@ -112,7 +112,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:87:1
    |
 LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0xffffffff at .<enum-variant(Some)>.0.1, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -123,7 +123,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:92:1
    |
 LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at .<enum-variant(Ok)>.0.1
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of uninhabited type Never
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -134,7 +134,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:94:1
    |
 LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<enum-variant(Ok)>.0.1
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of the never type `!`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
index 29d97962f32d7a6c07b909a449948e0191b0a61d..4f7dd5cdf7c733c91973e4d8a552b0620d22cd85 100644 (file)
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:24:1
    |
 LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x0000000000000001 at .<enum-tag>, but expected a valid enum tag
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered 0x0000000000000001, but expected a valid enum tag
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
@@ -13,29 +13,29 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:27:1
    |
 LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc8 at .<enum-tag>, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered pointer to alloc9, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc8────────╼                         │ ╾──────╼
+               ╾───────alloc9────────╼                         │ ╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:30:1
    |
 LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc12 at .0.<enum-tag>, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.<enum-tag>: encountered pointer to alloc13, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc12───────╼                         │ ╾──────╼
+               ╾───────alloc13───────╼                         │ ╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:42:1
    |
 LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x0000000000000000 at .<enum-tag>, but expected a valid enum tag
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered 0x0000000000000000, but expected a valid enum tag
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
@@ -46,29 +46,29 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:44:1
    |
 LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc18 at .<enum-tag>, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered pointer to alloc19, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc18───────╼                         │ ╾──────╼
+               ╾───────alloc19───────╼                         │ ╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:47:1
    |
 LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc22 at .0.<enum-tag>, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.<enum-tag>: encountered pointer to alloc23, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc22───────╼                         │ ╾──────╼
+               ╾───────alloc23───────╼                         │ ╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:56:1
    |
 LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .<enum-tag>, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
@@ -79,18 +79,18 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:60:1
    |
 LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc28 at .<enum-tag>, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered pointer to alloc29, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc28───────╼                         │ ╾──────╼
+               ╾───────alloc29───────╼                         │ ╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:77:1
    |
 LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<enum-variant(B)>.0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(B)>.0: encountered a value of the never type `!`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 1, align: 1) {
@@ -101,7 +101,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:79:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at .<enum-variant(D)>.0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(D)>.0: encountered a value of uninhabited type Never
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 1, align: 1) {
@@ -112,7 +112,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:87:1
    |
 LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0xffffffff at .<enum-variant(Some)>.0.1, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -123,7 +123,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:92:1
    |
 LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at .<enum-variant(Ok)>.0.1
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of uninhabited type Never
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -134,7 +134,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:94:1
    |
 LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<enum-variant(Ok)>.0.1
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of the never type `!`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
diff --git a/src/test/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr b/src/test/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr
new file mode 100644 (file)
index 0000000..ffde14f
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-incorrect-vtable.rs:19:14
+   |
+LL |     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: alignment `1000` is not a power of 2
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-incorrect-vtable.rs:24:14
+   |
+LL |     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: size is bigger than largest supported object
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-incorrect-vtable.rs:34:1
+   |
+LL | / const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
+LL | |     unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) };
+   | |_____________________________________________________________________________________________^ type validation failed at .0: encountered invalid vtable: alignment `1000` is not a power of 2
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾─allocN─╼ ╾─allocN─╼                         │ ╾──╼╾──╼
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-incorrect-vtable.rs:39:1
+   |
+LL | / const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
+LL | |     unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) };
+   | |______________________________________________________________________________________________^ type validation failed at .0: encountered invalid vtable: size is bigger than largest supported object
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾─allocN─╼ ╾─allocN─╼                         │ ╾──╼╾──╼
+           }
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr b/src/test/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr
new file mode 100644 (file)
index 0000000..2ad164a
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-incorrect-vtable.rs:19:14
+   |
+LL |     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: alignment `1000` is not a power of 2
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-incorrect-vtable.rs:24:14
+   |
+LL |     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: size is bigger than largest supported object
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-incorrect-vtable.rs:34:1
+   |
+LL | / const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
+LL | |     unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) };
+   | |_____________________________________________________________________________________________^ type validation failed at .0: encountered invalid vtable: alignment `1000` is not a power of 2
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-incorrect-vtable.rs:39:1
+   |
+LL | / const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
+LL | |     unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) };
+   | |______________________________________________________________________________________________^ type validation failed at .0: encountered invalid vtable: size is bigger than largest supported object
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼
+           }
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
index 0c0e3682de4d647530e991fb9a15c19e56a52f6f..4ec853576c91bd4b7a202f230c370f9db0662e9d 100644 (file)
@@ -3,19 +3,42 @@
 //   triggers an error
 // - a similar test that triggers a previously-untested const UB error: emitted close to the above
 //   error, it checks the correctness of the size
+//
+// As is, this code will only hard error when the constants are used, and the errors are emitted via
+// the `#[allow]`-able `const_err` lint. However, if the transparent wrapper technique to prevent
+// reborrows is used -- from `ub-wide-ptr.rs` -- these two errors reach validation and would trigger
+// ICEs as tracked by #86193. So we also use the transparent wrapper to verify proper validation
+// errors are emitted instead of ICEs.
+
+// stderr-per-bitwidth
+// normalize-stderr-test "alloc\d+" -> "allocN"
 
 trait Trait {}
 
 const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
-//~^ ERROR any use of this value will cause an error
-//~| WARNING this was previously accepted by the compiler
+//~^ ERROR evaluation of constant value failed
 //~| invalid vtable: alignment `1000` is not a power of 2
 
 const INVALID_VTABLE_SIZE: &dyn Trait =
     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
-//~^ ERROR any use of this value will cause an error
-//~| WARNING this was previously accepted by the compiler
+//~^ ERROR evaluation of constant value failed
+//~| invalid vtable: size is bigger than largest supported object
+
+#[repr(transparent)]
+struct W<T>(T);
+
+// The drop fn is checked before size/align are, so get ourselves a "sufficiently valid" drop fn
+fn drop_me(_: *mut usize) {}
+
+const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
+    unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) };
+//~^^ ERROR it is undefined behavior to use this value
+//~| invalid vtable: alignment `1000` is not a power of 2
+
+const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
+    unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) };
+//~^^ ERROR it is undefined behavior to use this value
 //~| invalid vtable: size is bigger than largest supported object
 
 fn main() {}
diff --git a/src/test/ui/consts/const-eval/ub-incorrect-vtable.stderr b/src/test/ui/consts/const-eval/ub-incorrect-vtable.stderr
deleted file mode 100644 (file)
index c937d03..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-error: any use of this value will cause an error
-  --> $DIR/ub-incorrect-vtable.rs:10:14
-   |
-LL | / const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
-LL | |     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
-   | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
-   |                |
-   |                invalid vtable: alignment `1000` is not a power of 2
-   |
-   = 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/ub-incorrect-vtable.rs:16:14
-   |
-LL | / const INVALID_VTABLE_SIZE: &dyn Trait =
-LL | |     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
-   | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
-   |                |
-   |                invalid vtable: size is bigger than largest supported object
-   |
-   = 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 2 previous errors
-
index c13271a1e5eca899f1923e3b66c5331d17226331..df02bdaa33cd9dcb206591c2b9774cebc1844d3b 100644 (file)
@@ -8,7 +8,7 @@ LL | |     [
 ...  |
 LL | |     ]
 LL | | };
-   | |__^ type validation failed: encountered uninitialized bytes at [0]
+   | |__^ type validation failed at [0]: encountered uninitialized bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 12, align: 4) {
@@ -25,7 +25,7 @@ LL | |     mem::transmute(
 ...  |
 LL | |     )
 LL | | };
-   | |__^ type validation failed: encountered uninitialized bytes at [1]
+   | |__^ type validation failed at [1]: encountered uninitialized bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 12, align: 4) {
@@ -42,7 +42,7 @@ LL | |     mem::transmute(
 ...  |
 LL | |     )
 LL | | };
-   | |__^ type validation failed: encountered uninitialized bytes at [2]
+   | |__^ type validation failed at [2]: encountered uninitialized bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 12, align: 4) {
index c13271a1e5eca899f1923e3b66c5331d17226331..df02bdaa33cd9dcb206591c2b9774cebc1844d3b 100644 (file)
@@ -8,7 +8,7 @@ LL | |     [
 ...  |
 LL | |     ]
 LL | | };
-   | |__^ type validation failed: encountered uninitialized bytes at [0]
+   | |__^ type validation failed at [0]: encountered uninitialized bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 12, align: 4) {
@@ -25,7 +25,7 @@ LL | |     mem::transmute(
 ...  |
 LL | |     )
 LL | | };
-   | |__^ type validation failed: encountered uninitialized bytes at [1]
+   | |__^ type validation failed at [1]: encountered uninitialized bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 12, align: 4) {
@@ -42,7 +42,7 @@ LL | |     mem::transmute(
 ...  |
 LL | |     )
 LL | | };
-   | |__^ type validation failed: encountered uninitialized bytes at [2]
+   | |__^ type validation failed at [2]: encountered uninitialized bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 12, align: 4) {
index 635cbb8cef66c61acd6470f4d9f5b962c78172a1..7e0fb33bc1187fb2f9d6d1f72f4f6bde59364bbb 100644 (file)
@@ -13,7 +13,7 @@ union MaybeUninit<T: Copy> {
 
 const UNINIT_INT_0: [u32; 3] = unsafe {
 //~^ ERROR it is undefined behavior to use this value
-//~| type validation failed: encountered uninitialized bytes at [0]
+//~| type validation failed at [0]: encountered uninitialized bytes
     [
         MaybeUninit { uninit: () }.init,
         1,
@@ -22,7 +22,7 @@ const UNINIT_INT_0: [u32; 3] = unsafe {
 };
 const UNINIT_INT_1: [u32; 3] = unsafe {
 //~^ ERROR it is undefined behavior to use this value
-//~| type validation failed: encountered uninitialized bytes at [1]
+//~| type validation failed at [1]: encountered uninitialized bytes
     mem::transmute(
         [
             0u8,
@@ -42,7 +42,7 @@ const UNINIT_INT_1: [u32; 3] = unsafe {
 };
 const UNINIT_INT_2: [u32; 3] = unsafe {
 //~^ ERROR it is undefined behavior to use this value
-//~| type validation failed: encountered uninitialized bytes at [2]
+//~| type validation failed at [2]: encountered uninitialized bytes
     mem::transmute(
         [
             0u8,
index ce8ab632fcf3e08feac3d7b292da51d3ab17dc81..e44f324945481e2f84cc695315d701aecd25078e 100644 (file)
@@ -9,29 +9,14 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
                00 00 00 00                                     │ ....
            }
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/ub-nonnull.rs:19:30
    |
-LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
-LL | |     let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
-LL | |     // Use address-of-element for pointer arithmetic. This could wrap around to null!
-LL | |     let out_of_bounds_ptr = &ptr[255];
-   | |                              ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
-LL | |
-LL | |     mem::transmute(out_of_bounds_ptr)
-LL | | } };
-   | |____-
-   |
-note: the lint level is defined here
-  --> $DIR/ub-nonnull.rs:15:8
-   |
-LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen
-   |        ^^^^^^^^^
-   = 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>
+LL |     let out_of_bounds_ptr = &ptr[255];
+   |                              ^^^^^^^^ dereferencing pointer failed: alloc11 has size 1, so pointer to 256 bytes starting at offset 0 is out-of-bounds
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:24:1
+  --> $DIR/ub-nonnull.rs:23:1
    |
 LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
@@ -42,7 +27,7 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:26:1
+  --> $DIR/ub-nonnull.rs:25:1
    |
 LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
@@ -53,10 +38,10 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:34:1
+  --> $DIR/ub-nonnull.rs:33:1
    |
 LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 1, align: 1) {
@@ -64,7 +49,7 @@ LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:42:1
+  --> $DIR/ub-nonnull.rs:41:1
    |
 LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30
@@ -75,7 +60,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:48:1
+  --> $DIR/ub-nonnull.rs:47:1
    |
 LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30
index 3f49a262ae46768041ccac414df3cd2ce0cb10a8..1ce87bc7c1ce87a4e22b3c66578373ff1b11703e 100644 (file)
@@ -9,29 +9,14 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
                00 00 00 00 00 00 00 00                         │ ........
            }
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/ub-nonnull.rs:19:30
    |
-LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
-LL | |     let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
-LL | |     // Use address-of-element for pointer arithmetic. This could wrap around to null!
-LL | |     let out_of_bounds_ptr = &ptr[255];
-   | |                              ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
-LL | |
-LL | |     mem::transmute(out_of_bounds_ptr)
-LL | | } };
-   | |____-
-   |
-note: the lint level is defined here
-  --> $DIR/ub-nonnull.rs:15:8
-   |
-LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen
-   |        ^^^^^^^^^
-   = 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>
+LL |     let out_of_bounds_ptr = &ptr[255];
+   |                              ^^^^^^^^ dereferencing pointer failed: alloc11 has size 1, so pointer to 256 bytes starting at offset 0 is out-of-bounds
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:24:1
+  --> $DIR/ub-nonnull.rs:23:1
    |
 LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
@@ -42,7 +27,7 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:26:1
+  --> $DIR/ub-nonnull.rs:25:1
    |
 LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
@@ -53,10 +38,10 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:34:1
+  --> $DIR/ub-nonnull.rs:33:1
    |
 LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 1, align: 1) {
@@ -64,7 +49,7 @@ LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:42:1
+  --> $DIR/ub-nonnull.rs:41:1
    |
 LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30
@@ -75,7 +60,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:48:1
+  --> $DIR/ub-nonnull.rs:47:1
    |
 LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30
index 75c02a8da194fdc2904dbcdca00a620a633a31a4..259707b8028da33ed0b6288655850180741b233a 100644 (file)
@@ -16,8 +16,7 @@ const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
 const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
     let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
     // Use address-of-element for pointer arithmetic. This could wrap around to null!
-    let out_of_bounds_ptr = &ptr[255]; //~ ERROR any use of this value will cause an error
-    //~| WARN this was previously accepted by the compiler but is being phased out
+    let out_of_bounds_ptr = &ptr[255]; //~ ERROR evaluation of constant value failed
     mem::transmute(out_of_bounds_ptr)
 } };
 
index d4a61a4631932d73c9eadeb200ca5dbe910c99c4..c8ec7cc4875a53ea098b3534243e48792cd72f69 100644 (file)
@@ -6,7 +6,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc2──╼                                     │ ╾──╼
+               ╾─alloc3──╼                                     │ ╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -17,7 +17,7 @@ LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc6──╼                                     │ ╾──╼
+               ╾─alloc7──╼                                     │ ╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -46,40 +46,40 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:30:1
    |
 LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc14, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc15, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc14─╼                                     │ ╾──╼
+               ╾─alloc15─╼                                     │ ╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:33:1
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc20─╼                                     │ ╾──╼
+               ╾─alloc21─╼                                     │ ╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:36:1
    |
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc25─╼                                     │ ╾──╼
+               ╾─alloc26─╼                                     │ ╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:39:1
    |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (address 0x539 is unallocated)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
@@ -90,7 +90,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:42:1
    |
 LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (created from integer)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (address 0x539 is unallocated)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
index 17da7c25bac95dfac834ea128b099af3c10b00ab..60a174ac5a7f61421a3fc583465248c96fe222d1 100644 (file)
@@ -6,7 +6,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc2────────╼                         │ ╾──────╼
+               ╾───────alloc3────────╼                         │ ╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -17,7 +17,7 @@ LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc6────────╼                         │ ╾──────╼
+               ╾───────alloc7────────╼                         │ ╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -46,40 +46,40 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:30:1
    |
 LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc14, but expected initialized plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc15, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc14───────╼                         │ ╾──────╼
+               ╾───────alloc15───────╼                         │ ╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:33:1
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc20───────╼                         │ ╾──────╼
+               ╾───────alloc21───────╼                         │ ╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:36:1
    |
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc25───────╼                         │ ╾──────╼
+               ╾───────alloc26───────╼                         │ ╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:39:1
    |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (address 0x539 is unallocated)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
@@ -90,7 +90,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:42:1
    |
 LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (created from integer)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (address 0x539 is unallocated)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
index 4155a8a2ef9f34d2a66e19db4f757220cfafff2e..350bd941939b1aa7256de4941951c56c9d86912d 100644 (file)
@@ -11,7 +11,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-uninhabit.rs:18:1
    |
 LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at .<deref>
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered a value of uninhabited type Bar
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
@@ -22,7 +22,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-uninhabit.rs:21:1
    |
 LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at [0]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Bar
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 0, align: 1) {}
index def795c7f563c7399a5ff2cfca6e45543f439196..13a4fde0830e4d2945080aa0c23dea9b5cc468dc 100644 (file)
@@ -11,7 +11,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-uninhabit.rs:18:1
    |
 LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at .<deref>
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered a value of uninhabited type Bar
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
@@ -22,7 +22,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-uninhabit.rs:21:1
    |
 LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at [0]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Bar
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 0, align: 1) {}
index 33251535be9033f07213ab760e211100acf02f12..27b98c2547ce7eab9154c69ae5ba0bd95c6b3b38 100644 (file)
@@ -6,11 +6,11 @@ LL | |     let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) };
 LL | |     let another_var = 13;
 LL | |     move || { let _ = bad_ref; let _ = another_var; }
 LL | | };
-   | |__^ type validation failed: encountered a null reference at .<deref>.<dyn-downcast>.<captured-var(bad_ref)>
+   | |__^ type validation failed at .<deref>.<dyn-downcast>.<captured-var(bad_ref)>: encountered a null reference
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─alloc2──╼ ╾─alloc3──╼                         │ ╾──╼╾──╼
+               ╾─alloc3──╼ ╾─alloc6──╼                         │ ╾──╼╾──╼
            }
 
 error: aborting due to previous error
index de6033702ae3002053be959d454d337ae575bd32..9cc9fb59bd7f076bffdb7a99cb51fdc341eaf3c0 100644 (file)
@@ -6,11 +6,11 @@ LL | |     let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) };
 LL | |     let another_var = 13;
 LL | |     move || { let _ = bad_ref; let _ = another_var; }
 LL | | };
-   | |__^ type validation failed: encountered a null reference at .<deref>.<dyn-downcast>.<captured-var(bad_ref)>
+   | |__^ type validation failed at .<deref>.<dyn-downcast>.<captured-var(bad_ref)>: encountered a null reference
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────alloc2────────╼ ╾───────alloc3────────╼ │ ╾──────╼╾──────╼
+               ╾───────alloc3────────╼ ╾───────alloc6────────╼ │ ╾──────╼╾──────╼
            }
 
 error: aborting due to previous error
index c69674a6721bc0fd61f04913849a30e1e70fc4ff..2a489e8b69c8f70a7fe2a9b8c327cd9289ae7ac4 100644 (file)
@@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:40:1
    |
 LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object at .0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -57,7 +57,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:52:1
    |
 LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in `str` at .<deref>
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered uninitialized data in `str`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -68,7 +68,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:55:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in `str` at .<deref>.0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.0: encountered uninitialized data in `str`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -138,7 +138,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:81:1
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .<deref>[0], but expected a boolean
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
@@ -149,7 +149,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:87:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .<deref>.0, but expected a boolean
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.0: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
@@ -160,7 +160,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:90:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .<deref>.1[0], but expected a boolean
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.1[0]: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
@@ -186,7 +186,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:105:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable at .0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -197,7 +197,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:108:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable at .0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -208,7 +208,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:111:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer at .0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered dangling vtable pointer in wide pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -252,7 +252,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:119:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function) at .0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid drop function pointer in vtable (not pointing to a function)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -263,7 +263,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:123:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .<deref>.<dyn-downcast>, but expected a boolean
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -302,7 +302,7 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/ub-wide-ptr.rs:139:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: allocN has size N, so pointer to 12 bytes starting at offset N is out-of-bounds
 
 error: aborting due to 28 previous errors
 
index bb95343a786a40056bcf471a8358432bd19cb2b3..ff850d2dbe9a0aa2cb072ade07eefda59c98d110 100644 (file)
@@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:40:1
    |
 LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object at .0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -57,7 +57,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:52:1
    |
 LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in `str` at .<deref>
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered uninitialized data in `str`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -68,7 +68,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:55:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in `str` at .<deref>.0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.0: encountered uninitialized data in `str`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -138,7 +138,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:81:1
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .<deref>[0], but expected a boolean
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
@@ -149,7 +149,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:87:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .<deref>.0, but expected a boolean
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.0: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
@@ -160,7 +160,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:90:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .<deref>.1[0], but expected a boolean
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.1[0]: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
@@ -186,7 +186,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:105:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable at .0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -197,7 +197,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:108:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable at .0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -208,7 +208,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:111:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer at .0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered dangling vtable pointer in wide pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -252,7 +252,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:119:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function) at .0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid drop function pointer in vtable (not pointing to a function)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -263,7 +263,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:123:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .<deref>.<dyn-downcast>, but expected a boolean
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -302,7 +302,7 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/ub-wide-ptr.rs:139:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: allocN has size N, so pointer to 24 bytes starting at offset N is out-of-bounds
 
 error: aborting due to 28 previous errors
 
index 6d44b3c8b282f53604f4c1d159047214bb19542c..b1ab03400c18f436623c4fc5382a98e0509fa9a1 100644 (file)
@@ -16,7 +16,7 @@ LL | / const FIELD_PATH: Struct = Struct {
 LL | |     a: 42,
 LL | |     b: unsafe { UNION.field3 },
 LL | | };
-   | |__^ type validation failed: encountered uninitialized bytes at .b, but expected initialized plain (non-pointer) bytes
+   | |__^ type validation failed at .b: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -33,7 +33,7 @@ LL | |         unsafe { UNION.field3 },
 ...  |
 LL | |     a: 42,
 LL | | };
-   | |__^ type validation failed: encountered uninitialized bytes at .b[1]
+   | |__^ type validation failed at .b[1]: encountered uninitialized bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 40, align: 8) {
index 9bc63d9328c69342d1f720732c2ef83f5a0bb3c8..766a0c49be68afcf9fc85d3f2481faabf17bd2ce 100644 (file)
@@ -2,7 +2,7 @@
 
 #[unwind(aborts)]
 const fn foo() {
-    panic!() //~ ERROR any use of this value will cause an error
+    panic!() //~ ERROR evaluation of constant value failed
 }
 
 const _: () = foo();
index b41d786169b9e8cd6225d78ad6f88fbe2e7209af..e3b871ee529bef3a7f3d58cf68581a464e43c6be 100644 (file)
@@ -1,4 +1,4 @@
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/unwind-abort.rs:5:5
    |
 LL |     panic!()
@@ -6,10 +6,9 @@ LL |     panic!()
    |     |
    |     the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:5:5
    |     inside `foo` at $SRC_DIR/std/src/panic.rs:LL:COL
-   |     inside `_` at $DIR/unwind-abort.rs:8:15
 ...
 LL | const _: () = foo();
-   | --------------------
+   |               ----- inside `_` at $DIR/unwind-abort.rs:8:15
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
index e25abab7e37487634ce411dd8e91e397387dd99f..0022d19e95395d734da46f03810340a10f2cfefc 100644 (file)
@@ -1,4 +1,4 @@
-warning: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/validate_uninhabited_zsts.rs:5:14
    |
 LL |     unsafe { std::mem::transmute(()) }
@@ -6,24 +6,15 @@ LL |     unsafe { std::mem::transmute(()) }
    |              |
    |              transmuting to uninhabited type
    |              inside `foo` at $DIR/validate_uninhabited_zsts.rs:5:14
-   |              inside `FOO` at $DIR/validate_uninhabited_zsts.rs:15:26
 ...
 LL | const FOO: [Empty; 3] = [foo(); 3];
-   | -----------------------------------
-   |
-note: the lint level is defined here
-  --> $DIR/validate_uninhabited_zsts.rs:14:8
-   |
-LL | #[warn(const_err)]
-   |        ^^^^^^^^^
-   = 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>
+   |                          ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:14:26
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/validate_uninhabited_zsts.rs:18:1
+  --> $DIR/validate_uninhabited_zsts.rs:17:1
    |
 LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Empty at [0]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Empty
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 0, align: 1) {}
@@ -41,7 +32,7 @@ LL |     unsafe { std::mem::transmute(()) }
    = note: the `!` type has no valid value
 
 warning: the type `Empty` does not permit zero-initialization
-  --> $DIR/validate_uninhabited_zsts.rs:18:35
+  --> $DIR/validate_uninhabited_zsts.rs:17:35
    |
 LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^
@@ -51,6 +42,6 @@ LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
    |
    = note: enums with no variants have no valid value
 
-error: aborting due to previous error; 3 warnings emitted
+error: aborting due to 2 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0080`.
index e25abab7e37487634ce411dd8e91e397387dd99f..0022d19e95395d734da46f03810340a10f2cfefc 100644 (file)
@@ -1,4 +1,4 @@
-warning: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/validate_uninhabited_zsts.rs:5:14
    |
 LL |     unsafe { std::mem::transmute(()) }
@@ -6,24 +6,15 @@ LL |     unsafe { std::mem::transmute(()) }
    |              |
    |              transmuting to uninhabited type
    |              inside `foo` at $DIR/validate_uninhabited_zsts.rs:5:14
-   |              inside `FOO` at $DIR/validate_uninhabited_zsts.rs:15:26
 ...
 LL | const FOO: [Empty; 3] = [foo(); 3];
-   | -----------------------------------
-   |
-note: the lint level is defined here
-  --> $DIR/validate_uninhabited_zsts.rs:14:8
-   |
-LL | #[warn(const_err)]
-   |        ^^^^^^^^^
-   = 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>
+   |                          ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:14:26
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/validate_uninhabited_zsts.rs:18:1
+  --> $DIR/validate_uninhabited_zsts.rs:17:1
    |
 LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Empty at [0]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Empty
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 0, align: 1) {}
@@ -41,7 +32,7 @@ LL |     unsafe { std::mem::transmute(()) }
    = note: the `!` type has no valid value
 
 warning: the type `Empty` does not permit zero-initialization
-  --> $DIR/validate_uninhabited_zsts.rs:18:35
+  --> $DIR/validate_uninhabited_zsts.rs:17:35
    |
 LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^
@@ -51,6 +42,6 @@ LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
    |
    = note: enums with no variants have no valid value
 
-error: aborting due to previous error; 3 warnings emitted
+error: aborting due to 2 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0080`.
index 112ace5e97fe691857dfe3ab12108b29593fdf47..f6b6a1f53eb9f2c54dc1f23aad21e22b0cae6cda 100644 (file)
@@ -3,9 +3,8 @@
 
 const fn foo() -> ! {
     unsafe { std::mem::transmute(()) }
-    //~^ WARN any use of this value will cause an error [const_err]
+    //~^ ERROR evaluation of constant value failed
     //~| WARN the type `!` does not permit zero-initialization [invalid_value]
-    //~| WARN this was previously accepted by the compiler but is being phased out
 }
 
 #[derive(Clone, Copy)]
index 76380ebcb6599b13a671da959749f61249a6da13..46748673067cebb02e795c78449a413186722521 100644 (file)
@@ -7,7 +7,7 @@ const unsafe extern "C" fn closure() -> fn() { || {} }
 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 36fec9976be372d9a9acd6f45b3cc63192f237a6..5d38e032ac408518ffae53627349156d7856145d 100644 (file)
@@ -5,7 +5,6 @@
 #![feature(const_float_bits_conv)]
 #![feature(const_float_classify)]
 #![feature(const_trait_impl)]
-#![allow(incomplete_features)]
 
 // Don't promote
 const fn nop<T>(x: T) -> T { x }
@@ -53,6 +52,9 @@ impl const PartialEq<NonDet> for bool {
     fn eq(&self, _: &NonDet) -> bool {
         true
     }
+    fn ne(&self, _: &NonDet) -> bool {
+        false
+    }
 }
 
 // The result of the `is_sign` methods are not checked for correctness, since LLVM does not
index 2ccc5d27bbb781f5fc5138dc79a25e76c60bcaeb..902a668488b8773d0754c1e6efdc2324f86631eb 100644 (file)
@@ -13,186 +13,137 @@ use std::intrinsics;
 // unsigned types:
 
 const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // signed types:
 
 const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // and make sure we capture y < 0:
 
 const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // and that there's no special relation to the value -1 by picking some
 // negative values at random:
 
 const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // Repeat it all over for `unchecked_shr`
 
 // unsigned types:
 
 const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // signed types:
 
 const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // and make sure we capture y < 0:
 
 const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // and that there's no special relation to the value -1 by picking some
 // negative values at random:
 
 const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // Other arithmetic functions:
 
 const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 const _: i32 = unsafe { std::intrinsics::unchecked_div(1, 0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::MIN, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 const _: i32 = unsafe { std::intrinsics::unchecked_rem(1, 0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::MIN, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // capture fault with zero value
 
 const _: u32 = unsafe { std::intrinsics::ctlz_nonzero(0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const _: u32 = unsafe { std::intrinsics::cttz_nonzero(0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 fn main() {}
index 999b26543e2d51041141ecb42ad24186ba38c703..22e8c8dabc970a139b63d58e2fa635411e03b009 100644 (file)
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:15:29
    |
 LL | const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
-   | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                             |
-   |                             overflowing shift by 8 in `unchecked_shl`
-   |
-   = 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>
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:18:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:17:31
    |
 LL | const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 16 in `unchecked_shl`
-   |
-   = 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>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:21:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:19:31
    |
 LL | const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 32 in `unchecked_shl`
-   |
-   = 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>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:24:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:21:31
    |
 LL | const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 64 in `unchecked_shl`
-   |
-   = 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>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:27:33
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:23:33
    |
 LL | const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) };
-   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                 |
-   |                                 overflowing shift by 128 in `unchecked_shl`
-   |
-   = 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>
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:33:29
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:28:29
    |
 LL | const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) };
-   | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                             |
-   |                             overflowing shift by 8 in `unchecked_shl`
-   |
-   = 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>
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:36:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:30:31
    |
 LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 16 in `unchecked_shl`
-   |
-   = 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>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:39:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:32:31
    |
 LL | const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 32 in `unchecked_shl`
-   |
-   = 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>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:42:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:34:31
    |
 LL | const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 64 in `unchecked_shl`
-   |
-   = 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>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:45:33
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:36:33
    |
 LL | const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) };
-   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                 |
-   |                                 overflowing shift by 128 in `unchecked_shl`
-   |
-   = 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>
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:51:33
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:41:33
    |
 LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
-   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                 |
-   |                                 overflowing shift by 255 in `unchecked_shl`
-   |
-   = 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>
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 255 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:54:35
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:43:35
    |
 LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) };
-   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                   |
-   |                                   overflowing shift by 65535 in `unchecked_shl`
-   |
-   = 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>
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65535 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:57:35
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:45:35
    |
 LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) };
-   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                   |
-   |                                   overflowing shift by 4294967295 in `unchecked_shl`
-   |
-   = 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>
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967295 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:60:35
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:47:35
    |
 LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) };
-   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                   |
-   |                                   overflowing shift by 18446744073709551615 in `unchecked_shl`
-   |
-   = 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>
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551615 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:63:37
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:49:37
    |
 LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) };
-   | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                     |
-   |                                     overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl`
-   |
-   = 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>
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:70:40
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:55:40
    |
 LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) };
-   | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                        |
-   |                                        overflowing shift by 250 in `unchecked_shl`
-   |
-   = 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>
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 250 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:73:42
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:57:42
    |
 LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) };
-   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                          |
-   |                                          overflowing shift by 65523 in `unchecked_shl`
-   |
-   = 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>
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65523 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:76:42
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:59:42
    |
 LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) };
-   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                          |
-   |                                          overflowing shift by 4294967271 in `unchecked_shl`
-   |
-   = 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>
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967271 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:79:42
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:61:42
    |
 LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) };
-   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                          |
-   |                                          overflowing shift by 18446744073709551586 in `unchecked_shl`
-   |
-   = 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>
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551586 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:82:44
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:63:44
    |
 LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) };
-   | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                            |
-   |                                            overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl`
-   |
-   = 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>
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:90:29
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:70:29
    |
 LL | const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
-   | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                             |
-   |                             overflowing shift by 8 in `unchecked_shr`
-   |
-   = 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>
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:93:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:72:31
    |
 LL | const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 16 in `unchecked_shr`
-   |
-   = 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>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:96:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:74:31
    |
 LL | const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 32 in `unchecked_shr`
-   |
-   = 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>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:99:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:76:31
    |
 LL | const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 64 in `unchecked_shr`
-   |
-   = 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>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:102:33
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:78:33
    |
 LL | const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) };
-   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                 |
-   |                                 overflowing shift by 128 in `unchecked_shr`
-   |
-   = 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>
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:108:29
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:83:29
    |
 LL | const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) };
-   | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                             |
-   |                             overflowing shift by 8 in `unchecked_shr`
-   |
-   = 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>
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:111:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:85:31
    |
 LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 16 in `unchecked_shr`
-   |
-   = 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>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:114:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:87:31
    |
 LL | const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 32 in `unchecked_shr`
-   |
-   = 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>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:117:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:89:31
    |
 LL | const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 64 in `unchecked_shr`
-   |
-   = 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>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:120:33
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:91:33
    |
 LL | const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) };
-   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                 |
-   |                                 overflowing shift by 128 in `unchecked_shr`
-   |
-   = 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>
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:126:33
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:96:33
    |
 LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
-   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                 |
-   |                                 overflowing shift by 255 in `unchecked_shr`
-   |
-   = 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>
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 255 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:129:35
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:98:35
    |
 LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) };
-   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                   |
-   |                                   overflowing shift by 65535 in `unchecked_shr`
-   |
-   = 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>
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65535 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:132:35
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:100:35
    |
 LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) };
-   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                   |
-   |                                   overflowing shift by 4294967295 in `unchecked_shr`
-   |
-   = 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>
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967295 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:135:35
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:102:35
    |
 LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) };
-   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                   |
-   |                                   overflowing shift by 18446744073709551615 in `unchecked_shr`
-   |
-   = 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>
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551615 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:138:37
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:104:37
    |
 LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) };
-   | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                     |
-   |                                     overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr`
-   |
-   = 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>
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:145:40
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:110:40
    |
 LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) };
-   | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                        |
-   |                                        overflowing shift by 250 in `unchecked_shr`
-   |
-   = 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>
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 250 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:148:42
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:112:42
    |
 LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) };
-   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                          |
-   |                                          overflowing shift by 65523 in `unchecked_shr`
-   |
-   = 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>
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65523 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:151:42
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:114:42
    |
 LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) };
-   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                          |
-   |                                          overflowing shift by 4294967271 in `unchecked_shr`
-   |
-   = 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>
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967271 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:154:42
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:116:42
    |
 LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) };
-   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                          |
-   |                                          overflowing shift by 18446744073709551586 in `unchecked_shr`
-   |
-   = 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>
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551586 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:157:44
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:118:44
    |
 LL | const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) };
-   | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                            |
-   |                                            overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr`
-   |
-   = 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>
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:163:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:123:25
    |
 LL | const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         overflow executing `unchecked_add`
-   |
-   = 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>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_add`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:167:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:126:25
    |
 LL | const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         overflow executing `unchecked_sub`
-   |
-   = 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>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_sub`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:171:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:129:25
    |
 LL | const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         overflow executing `unchecked_mul`
-   |
-   = 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>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_mul`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:175:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:132:25
    |
 LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(1, 0) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         dividing by zero
-   |
-   = 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>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dividing by zero
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:178:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:134:25
    |
 LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::MIN, -1) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         overflow executing `unchecked_div`
-   |
-   = 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>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_div`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:182:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:137:25
    |
 LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(1, 0) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         calculating the remainder with a divisor of zero
-   |
-   = 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>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calculating the remainder with a divisor of zero
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:185:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:139:25
    |
 LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::MIN, -1) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         overflow executing `unchecked_rem`
-   |
-   = 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>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_rem`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:191:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:144:25
    |
 LL | const _: u32 = unsafe { std::intrinsics::ctlz_nonzero(0) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         `ctlz_nonzero` called on 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 #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ctlz_nonzero` called on 0
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:194:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:146:25
    |
 LL | const _: u32 = unsafe { std::intrinsics::cttz_nonzero(0) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         `cttz_nonzero` called on 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 #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `cttz_nonzero` called on 0
 
 error: aborting due to 49 previous errors
 
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr
new file mode 100644 (file)
index 0000000..a9411fb
--- /dev/null
@@ -0,0 +1,36 @@
+error[E0764]: mutable references are not allowed in the final value of constants
+  --> $DIR/issue-76510.rs:5:29
+   |
+LL | const S: &'static mut str = &mut " hello ";
+   |                             ^^^^^^^^^^^^^^
+
+error[E0658]: mutation through a reference is not allowed in constants
+  --> $DIR/issue-76510.rs:5:29
+   |
+LL | const S: &'static mut str = &mut " hello ";
+   |                             ^^^^^^^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/issue-76510.rs:5:29
+   |
+LL | const S: &'static mut str = &mut " hello ";
+   |                             ^^^^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/issue-76510.rs:5:1
+   |
+LL | const S: &'static mut str = &mut " hello ";
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered mutable reference in a `const`
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾─alloc3──╼ 07 00 00 00                         │ ╾──╼....
+           }
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0080, E0596, E0658, E0764.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr
new file mode 100644 (file)
index 0000000..9ad5f20
--- /dev/null
@@ -0,0 +1,36 @@
+error[E0764]: mutable references are not allowed in the final value of constants
+  --> $DIR/issue-76510.rs:5:29
+   |
+LL | const S: &'static mut str = &mut " hello ";
+   |                             ^^^^^^^^^^^^^^
+
+error[E0658]: mutation through a reference is not allowed in constants
+  --> $DIR/issue-76510.rs:5:29
+   |
+LL | const S: &'static mut str = &mut " hello ";
+   |                             ^^^^^^^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/issue-76510.rs:5:29
+   |
+LL | const S: &'static mut str = &mut " hello ";
+   |                             ^^^^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/issue-76510.rs:5:1
+   |
+LL | const S: &'static mut str = &mut " hello ";
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered mutable reference in a `const`
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾───────alloc3────────╼ 07 00 00 00 00 00 00 00 │ ╾──────╼........
+           }
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0080, E0596, E0658, E0764.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.rs b/src/test/ui/consts/const-mut-refs/issue-76510.rs
new file mode 100644 (file)
index 0000000..892f6c9
--- /dev/null
@@ -0,0 +1,18 @@
+// stderr-per-bitwidth
+
+use std::mem::{transmute, ManuallyDrop};
+
+const S: &'static mut str = &mut " hello ";
+//~^ ERROR: mutable references are not allowed in the final value of constants
+//~| ERROR: mutation through a reference is not allowed in constants
+//~| ERROR: cannot borrow data in a `&` reference as mutable
+//~| ERROR: it is undefined behavior to use this value
+
+const fn trigger() -> [(); unsafe {
+        let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
+        0
+    }] {
+    [(); 0]
+}
+
+fn main() {}
index 638a98130a236f501c8777492f6b412437e246cb..24d7bc49147d89df6f825b806763cbfb5f46eb63 100644 (file)
@@ -11,8 +11,8 @@
 const fn helper() -> Option<&'static mut i32> { unsafe {
     // Undefined behaviour (integer as pointer), who doesn't love tests like this.
     // This code never gets executed, because the static checks fail before that.
-    Some(&mut *(42 as *mut i32)) //~ ERROR any use of this value will cause an error
-    //~| WARN this was previously accepted by the compiler but is being phased out
+    Some(&mut *(42 as *mut i32)) //~ ERROR evaluation of constant value failed
+    //~| 0x2a is not a valid pointer
 } }
 // The error is an evaluation error and not a validation error, so the error is reported
 // directly at the site where it occurs.
index 6d3d18f6e68985e051abf35c6ba547917b266198..b3fcd6a7fecd3d508239c744e174fa7372c5b187 100644 (file)
@@ -1,19 +1,14 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/mut_ref_in_final_dynamic_check.rs:14:10
    |
 LL |     Some(&mut *(42 as *mut i32))
    |          ^^^^^^^^^^^^^^^^^^^^^^
    |          |
-   |          unable to turn bytes into a pointer
+   |          0x2a is not a valid pointer
    |          inside `helper` at $DIR/mut_ref_in_final_dynamic_check.rs:14:10
-   |          inside `A` at $DIR/mut_ref_in_final_dynamic_check.rs:19:29
 ...
 LL | const A: Option<&mut i32> = helper();
-   | -------------------------------------
-   |
-   = 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>
+   |                             -------- inside `A` at $DIR/mut_ref_in_final_dynamic_check.rs:19:29
 
 error: encountered dangling pointer in final constant
   --> $DIR/mut_ref_in_final_dynamic_check.rs:26:1
@@ -23,3 +18,4 @@ LL | const B: Option<&mut i32> = helper2();
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0080`.
index c582678e2d65bd9c2ed4774cb42a357d26f7c739..78af2c30d0437091b1b29d12abfaa50d3d3df0e2 100644 (file)
@@ -6,7 +6,7 @@ LL | const TEST: &u8 = &MY_STATIC;
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc0──╼                                     │ ╾──╼
+               ╾─alloc1──╼                                     │ ╾──╼
            }
 
 warning: skipping const checks
index 1112499a3ee6435d879361247f2c6de49d49d7c4..f5a0a6b0addef7810f209b23111e43480aa807df 100644 (file)
@@ -6,7 +6,7 @@ LL | const TEST: &u8 = &MY_STATIC;
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc0────────╼                         │ ╾──────╼
+               ╾───────alloc1────────╼                         │ ╾──────╼
            }
 
 warning: skipping const checks
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 95f4711cb65b036770db39844eec5025e6f163e5..d2cbe4550f4bbd73d87de07cfb47297b6d80001c 100644 (file)
@@ -1,19 +1,8 @@
-error[E0080]: any use of this value will cause an error
-  --> $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
-   |                     inside `BAR` at $DIR/const-unwrap.rs:9:18
-   | 
-  ::: $DIR/const-unwrap.rs:9:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-unwrap.rs:7:18
    |
 LL | const BAR: i32 = Option::<i32>::None.unwrap();
-   | ----------------------------------------------
-   |
-   = 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 4ae3a88c45143a9ec2018a0df9e81ff37d8d564d..8cee5b506513623094dc9717d12b5beceb21bcde 100644 (file)
@@ -1,5 +1,4 @@
-// build-fail
-
+// error-pattern: evaluation of constant value failed
 #![feature(const_unreachable_unchecked)]
 
 const unsafe fn foo(x: bool) -> bool {
@@ -9,12 +8,8 @@ const unsafe fn foo(x: bool) -> bool {
     }
 }
 
-#[warn(const_err)]
 const BAR: bool = unsafe { foo(false) };
 
 fn main() {
   assert_eq!(BAR, true);
-  //~^ ERROR E0080
-  //~| ERROR erroneous constant
-  //~| WARN this was previously accepted by the compiler but is being phased out
 }
index fc7a53e2774866e9933c182254084b7783296b3a..ecdd0ca3f54c1bf995b840caf38afa1c3d50d99a 100644 (file)
@@ -1,4 +1,4 @@
-warning: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/hint.rs:LL:COL
    |
 LL |     unsafe { intrinsics::unreachable() }
@@ -6,39 +6,15 @@ LL |     unsafe { intrinsics::unreachable() }
    |              |
    |              entering unreachable code
    |              inside `unreachable_unchecked` at $SRC_DIR/core/src/hint.rs:LL:COL
-   |              inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:8:18
-   |              inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:13:28
    | 
-  ::: $DIR/const_unsafe_unreachable_ub.rs:13:1
+  ::: $DIR/const_unsafe_unreachable_ub.rs:7:18
    |
+LL |         false => std::hint::unreachable_unchecked(),
+   |                  ---------------------------------- inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:7:18
+...
 LL | const BAR: bool = unsafe { foo(false) };
-   | ----------------------------------------
-   |
-note: the lint level is defined here
-  --> $DIR/const_unsafe_unreachable_ub.rs:12:8
-   |
-LL | #[warn(const_err)]
-   |        ^^^^^^^^^
-   = 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[E0080]: evaluation of constant value failed
-  --> $DIR/const_unsafe_unreachable_ub.rs:16:14
-   |
-LL |   assert_eq!(BAR, true);
-   |              ^^^ referenced constant has errors
-
-error: erroneous constant used
-  --> $DIR/const_unsafe_unreachable_ub.rs:16:3
-   |
-LL |   assert_eq!(BAR, true);
-   |   ^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-   |
-   = 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>
-   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+   |                            ---------- inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:11:28
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0080`.
index 8e1a2b5eb461096e2db6de30112b9c61f10d6b9f..1deaa937edb37db94501895bc46db9da4c7cedbb 100644 (file)
@@ -1,10 +1,8 @@
-error[E0080]: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/assert.rs:10:15
    |
 LL | const _: () = assert!(false);
-   | --------------^^^^^^^^^^^^^^-
-   |               |
-   |               the evaluated program panicked at 'assertion failed: false', $DIR/assert.rs:10:15
+   |               ^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: false', $DIR/assert.rs:10:15
    |
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
index 90017fee1933738022a13a7cc6b0167f21af6f97..b311cb140ccf69d03b45863c0fcd651b74ed3ccd 100644 (file)
@@ -9,6 +9,6 @@ const _: () = assert!(true);
 
 const _: () = assert!(false);
 //[stock]~^ ERROR panicking in constants is unstable
-//[const_panic]~^^ ERROR any use of this value will cause an error
+//[const_panic]~^^ ERROR evaluation of constant value failed
 
 fn main() {}
diff --git a/src/test/ui/consts/copy-intrinsic.rs b/src/test/ui/consts/copy-intrinsic.rs
new file mode 100644 (file)
index 0000000..124e16e
--- /dev/null
@@ -0,0 +1,52 @@
+#![stable(feature = "dummy", since = "1.0.0")]
+
+// ignore-tidy-linelength
+#![feature(intrinsics, staged_api)]
+#![feature(const_mut_refs, const_intrinsic_copy, const_ptr_offset)]
+use std::mem;
+
+extern "rust-intrinsic" {
+    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
+    fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+
+    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
+    fn copy<T>(src: *const T, dst: *mut T, count: usize);
+}
+
+const COPY_ZERO: () = unsafe {
+    // Since we are not copying anything, this should be allowed.
+    let src = ();
+    let mut dst = ();
+    copy_nonoverlapping(&src as *const _ as *const i32, &mut dst as *mut _ as *mut i32, 0);
+};
+
+const COPY_OOB_1: () = unsafe {
+    let mut x = 0i32;
+    let dangle = (&mut x as *mut i32).wrapping_add(10);
+    // Even if the first ptr is an int ptr and this is a ZST copy, we should detect dangling 2nd ptrs.
+    copy_nonoverlapping(0x100 as *const i32, dangle, 0); //~ ERROR evaluation of constant value failed [E0080]
+    //~| pointer at offset 40 is out-of-bounds
+};
+const COPY_OOB_2: () = unsafe {
+    let x = 0i32;
+    let dangle = (&x as *const i32).wrapping_add(10);
+    // Even if the second ptr is an int ptr and this is a ZST copy, we should detect dangling 1st ptrs.
+    copy_nonoverlapping(dangle, 0x100 as *mut i32, 0); //~ ERROR evaluation of constant value failed [E0080]
+    //~| pointer at offset 40 is out-of-bounds
+};
+
+const COPY_SIZE_OVERFLOW: () = unsafe {
+    let x = 0;
+    let mut y = 0;
+    copy(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1)); //~ ERROR evaluation of constant value failed [E0080]
+    //~| overflow computing total size of `copy`
+};
+const COPY_NONOVERLAPPING_SIZE_OVERFLOW: () = unsafe {
+    let x = 0;
+    let mut y = 0;
+    copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1)); //~ evaluation of constant value failed [E0080]
+    //~| overflow computing total size of `copy_nonoverlapping`
+};
+
+fn main() {
+}
diff --git a/src/test/ui/consts/copy-intrinsic.stderr b/src/test/ui/consts/copy-intrinsic.stderr
new file mode 100644 (file)
index 0000000..be41c2d
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/copy-intrinsic.rs:27:5
+   |
+LL |     copy_nonoverlapping(0x100 as *const i32, dangle, 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc5 has size 4, so pointer at offset 40 is out-of-bounds
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/copy-intrinsic.rs:34:5
+   |
+LL |     copy_nonoverlapping(dangle, 0x100 as *mut i32, 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc7 has size 4, so pointer at offset 40 is out-of-bounds
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/copy-intrinsic.rs:41:5
+   |
+LL |     copy(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy`
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/copy-intrinsic.rs:47:5
+   |
+LL |     copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy_nonoverlapping`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
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-17756.rs b/src/test/ui/consts/issue-17756.rs
new file mode 100644 (file)
index 0000000..1835b17
--- /dev/null
@@ -0,0 +1,8 @@
+// run-pass
+#![allow(unused_variables)]
+#![allow(non_upper_case_globals)]
+
+const count : usize = 2 as usize;
+fn main() {
+    let larger : [usize; count*2];
+}
diff --git a/src/test/ui/consts/issue-39161-bogus-error.rs b/src/test/ui/consts/issue-39161-bogus-error.rs
new file mode 100644 (file)
index 0000000..a954385
--- /dev/null
@@ -0,0 +1,13 @@
+// check-pass
+
+pub struct X {
+    pub a: i32,
+    pub b: i32,
+}
+
+fn main() {
+    const DX: X = X { a: 0, b: 0 };
+    const _X1: X = X { a: 1, ..DX };
+    let _x2 = X { a: 1, b: 2, ..DX };
+    const _X3: X = X { a: 1, b: 2, ..DX };
+}
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 6d52ed065bff262e1babc39b7321a1df746f7f2b..6a6097d5ec6238cf15b568ad6ec3bae80adaed21 100644 (file)
@@ -12,7 +12,7 @@ LL | | };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─alloc3──╼ ff ff ff ff                         │ ╾──╼....
+               ╾─alloc4──╼ ff ff ff ff                         │ ╾──╼....
            }
 
 error: aborting due to previous error
index 3335c5bf72ef58669671d9c2d574f987784a2a67..6547c3384da8291ac06cca40565916e025d3fef9 100644 (file)
@@ -12,7 +12,7 @@ LL | | };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────alloc3────────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
+               ╾───────alloc4────────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
            }
 
 error: aborting due to previous error
diff --git a/src/test/ui/consts/issue-69532.rs b/src/test/ui/consts/issue-69532.rs
new file mode 100644 (file)
index 0000000..81007b1
--- /dev/null
@@ -0,0 +1,24 @@
+// run-pass
+#![feature(const_fn_transmute)]
+
+const fn make_nans() -> (f64, f64, f32, f32) {
+    let nan1: f64 = unsafe { std::mem::transmute(0x7FF0_0001_0000_0001u64) };
+    let nan2: f64 = unsafe { std::mem::transmute(0x7FF0_0000_0000_0001u64) };
+
+    let nan1_32 = nan1 as f32;
+    let nan2_32 = nan2 as f32;
+
+    (nan1, nan2, nan1_32, nan2_32)
+}
+
+static NANS: (f64, f64, f32, f32) = make_nans();
+
+fn main() {
+    let (nan1, nan2, nan1_32, nan2_32) = NANS;
+
+    assert!(nan1.is_nan());
+    assert!(nan2.is_nan());
+
+    assert!(nan1_32.is_nan());
+    assert!(nan2_32.is_nan());
+}
index 2639bc4812cbb9255cbad187f8bccabd6cf5b581..bf0ef9e6dc07e966843556b1938f5809d1787ae3 100644 (file)
@@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/issue-79690.rs:30:1
    |
 LL | const G: Fat = unsafe { Transmute { t: FOO }.u };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered (potentially part of) a pointer at .1.<deref>.size.foo, but expected plain (non-pointer) bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .1.<deref>.size.foo: encountered (potentially part of) a pointer, but expected plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────alloc2────────╼ ╾───────alloc3────────╼ │ ╾──────╼╾──────╼
+               ╾───────alloc3────────╼ ╾───────alloc6────────╼ │ ╾──────╼╾──────╼
            }
 
 error: aborting due to previous error
index 3352f0e1724bda54f20d417e4e4ef51544bb418c..a15668d4ec1b955a73b3b52424847691b9a527cf 100644 (file)
@@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/issue-83182.rs:5:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer in `str` at .<deref>.0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.0: encountered a pointer in `str`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─alloc3──╼ 01 00 00 00                         │ ╾──╼....
+               ╾─alloc4──╼ 01 00 00 00                         │ ╾──╼....
            }
 
 error: aborting due to previous error
index b75707207488d4bb24a134ecad24b7de80ce68c2..5c3ade7c1de44115861e001267349bb8a033395c 100644 (file)
@@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/issue-83182.rs:5:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer in `str` at .<deref>.0
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.0: encountered a pointer in `str`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────alloc3────────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾───────alloc4────────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error: aborting due to previous error
index 55a0722e5ddd4a23c5cf8c3b8201e0ed802a23ed..f714fd6e8f9df85503bcead3595f83dc25e1606c 100644 (file)
@@ -4,5 +4,5 @@ use std::mem;
 struct MyStr(str);
 const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
 //~^ ERROR: it is undefined behavior to use this value
-//~| type validation failed: encountered a pointer in `str`
+//~| type validation failed at .<deref>.0: encountered a pointer in `str`
 fn main() {}
diff --git a/src/test/ui/consts/issue-87046.rs b/src/test/ui/consts/issue-87046.rs
new file mode 100644 (file)
index 0000000..1f14743
--- /dev/null
@@ -0,0 +1,34 @@
+// Regression test for the ICE described in #87046.
+
+#![crate_type="lib"]
+#![allow(unreachable_patterns)]
+#![feature(const_fn_union)]
+
+#[derive(PartialEq, Eq)]
+#[repr(transparent)]
+pub struct Username(str);
+
+pub const ROOT_USER: &Username = Username::from_str("root");
+
+impl Username {
+    pub const fn from_str(raw: &str) -> &Self {
+        union Transmute<'a> {
+            raw: &'a str,
+            typed: &'a Username,
+        }
+
+        unsafe { Transmute { raw }.typed }
+    }
+
+    pub const fn as_str(&self) -> &str {
+        &self.0
+    }
+
+    pub fn is_root(&self) -> bool {
+        match self {
+            ROOT_USER => true,
+            //~^ ERROR: cannot use unsized non-slice type `Username` in constant patterns
+            _ => false,
+        }
+    }
+}
diff --git a/src/test/ui/consts/issue-87046.stderr b/src/test/ui/consts/issue-87046.stderr
new file mode 100644 (file)
index 0000000..5da7a9e
--- /dev/null
@@ -0,0 +1,8 @@
+error: cannot use unsized non-slice type `Username` in constant patterns
+  --> $DIR/issue-87046.rs:29:13
+   |
+LL |             ROOT_USER => true,
+   |             ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/large_const_alloc.rs b/src/test/ui/consts/large_const_alloc.rs
new file mode 100644 (file)
index 0000000..54abaab
--- /dev/null
@@ -0,0 +1,18 @@
+// only-64bit
+// on 32bit and 16bit platforms it is plausible that the maximum allocation size will succeed
+
+const FOO: () = {
+    // 128 TiB, unlikely anyone has that much RAM
+    let x = [0_u8; (1 << 47) - 1];
+    //~^ ERROR evaluation of constant value failed
+};
+
+static FOO2: () = {
+    let x = [0_u8; (1 << 47) - 1];
+    //~^ ERROR could not evaluate static initializer
+};
+
+fn main() {
+    let _ = FOO;
+    let _ = FOO2;
+}
diff --git a/src/test/ui/consts/large_const_alloc.stderr b/src/test/ui/consts/large_const_alloc.stderr
new file mode 100644 (file)
index 0000000..25d660f
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/large_const_alloc.rs:6:13
+   |
+LL |     let x = [0_u8; (1 << 47) - 1];
+   |             ^^^^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler
+
+error[E0080]: could not evaluate static initializer
+  --> $DIR/large_const_alloc.rs:11:13
+   |
+LL |     let x = [0_u8; (1 << 47) - 1];
+   |             ^^^^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
index b7904e6841b5d448a26b48b9916757fd99993bbd..bb525d57197789ad5b1ebfbd6a370b00e155e848 100644 (file)
@@ -90,13 +90,13 @@ static BAR: u32 = 42;
 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 64ebd0122673101521fd0ec9d09fbcd90dd6fbb0..1a6ed0f43b0f1d0581a03e8cc167a328f3b56d0c 100644 (file)
@@ -10,7 +10,7 @@ LL | | };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc0──╼                                     │ ╾──╼
+               ╾─alloc1──╼                                     │ ╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -25,7 +25,7 @@ LL | | };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc1──╼                                     │ ╾──╼
+               ╾─alloc2──╼                                     │ ╾──╼
            }
 
 warning: skipping const checks
index 4157b313f9f55f282599b335e3f1c3e0bf02864e..4f268dd905d03d9aae102ea6890d27c3effe3867 100644 (file)
@@ -10,7 +10,7 @@ LL | | };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc0────────╼                         │ ╾──────╼
+               ╾───────alloc1────────╼                         │ ╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -25,7 +25,7 @@ LL | | };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc1────────╼                         │ ╾──────╼
+               ╾───────alloc2────────╼                         │ ╾──────╼
            }
 
 warning: skipping const checks
index 583b2ef6725107f94010bce6303f3852006db67b..64a1214e8bf1b06995039b00c38f9c827c3923b9 100644 (file)
@@ -9,7 +9,7 @@ LL | | };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc0──╼                                     │ ╾──╼
+               ╾─alloc1──╼                                     │ ╾──╼
            }
 
 error: could not evaluate constant pattern
@@ -29,7 +29,7 @@ LL | | };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc0──╼                                     │ ╾──╼
+               ╾─alloc1──╼                                     │ ╾──╼
            }
 
 error: could not evaluate constant pattern
index b381a25a63df29545750a96cd463443ca107e939..66fe4ec076005eabab019bc48fba0edea4700ffc 100644 (file)
@@ -9,7 +9,7 @@ LL | | };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc0────────╼                         │ ╾──────╼
+               ╾───────alloc1────────╼                         │ ╾──────╼
            }
 
 error: could not evaluate constant pattern
@@ -29,7 +29,7 @@ LL | | };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc0────────╼                         │ ╾──────╼
+               ╾───────alloc1────────╼                         │ ╾──────╼
            }
 
 error: could not evaluate constant pattern
index 62126ef2babd39a2252f0f3d50e2ae7564b09073..9d1bb2ac91c49d48b9d953a935b1797025e3ab2b 100644 (file)
@@ -4,22 +4,22 @@ error[E0080]: it is undefined behavior to use this value
 LL | / const MUH: Meh = Meh {
 LL | |     x: &UnsafeCell::new(42),
 LL | | };
-   | |__^ type validation failed: encountered `UnsafeCell` in a `const` at .x.<deref>
+   | |__^ type validation failed at .x.<deref>: encountered `UnsafeCell` in a `const`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc2──╼                                     │ ╾──╼
+               ╾─alloc3──╼                                     │ ╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/mutable_references_err.rs:27:1
    |
 LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered `UnsafeCell` in a `const` at .<deref>.<dyn-downcast>.x
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.<dyn-downcast>.x: encountered `UnsafeCell` in a `const`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─alloc6──╼ ╾─alloc7──╼                         │ ╾──╼╾──╼
+               ╾─alloc7──╼ ╾─alloc9──╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -30,7 +30,7 @@ LL | const BLUNT: &mut i32 = &mut 42;
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc10─╼                                     │ ╾──╼
+               ╾─alloc11─╼                                     │ ╾──╼
            }
 
 warning: skipping const checks
index 606184e5732557470647360f7bcbf9778c07bb1c..fe939c039318966adc5b4a174746a12c8b1c43d9 100644 (file)
@@ -4,22 +4,22 @@ error[E0080]: it is undefined behavior to use this value
 LL | / const MUH: Meh = Meh {
 LL | |     x: &UnsafeCell::new(42),
 LL | | };
-   | |__^ type validation failed: encountered `UnsafeCell` in a `const` at .x.<deref>
+   | |__^ type validation failed at .x.<deref>: encountered `UnsafeCell` in a `const`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc2────────╼                         │ ╾──────╼
+               ╾───────alloc3────────╼                         │ ╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/mutable_references_err.rs:27:1
    |
 LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered `UnsafeCell` in a `const` at .<deref>.<dyn-downcast>.x
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.<dyn-downcast>.x: encountered `UnsafeCell` in a `const`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────alloc6────────╼ ╾───────alloc7────────╼ │ ╾──────╼╾──────╼
+               ╾───────alloc7────────╼ ╾───────alloc9────────╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -30,7 +30,7 @@ LL | const BLUNT: &mut i32 = &mut 42;
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc10───────╼                         │ ╾──────╼
+               ╾───────alloc11───────╼                         │ ╾──────╼
            }
 
 warning: skipping const checks
index aae6d837204e3a2e596bb5a2774f46944c39640e..22314160c5e89e5a839696ddb295ee2fa954246a 100644 (file)
@@ -8,14 +8,21 @@ static CMP: () = {
     let x = &0 as *const _;
     let _v = x == x;
     //~^ ERROR could not evaluate static initializer
-    //~| NOTE pointer arithmetic or comparison
+    //~| "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
 };
 
-static INT_PTR_ARITH: () = unsafe {
+static PTR_INT_CAST: () = {
+    let x = &0 as *const _ as usize;
+    //~^ ERROR could not evaluate static initializer
+    //~| unable to turn pointer into raw bytes
+    let _v = x == x;
+};
+
+static PTR_INT_TRANSMUTE: () = unsafe {
     let x: usize = std::mem::transmute(&0);
     let _v = x + 0;
     //~^ ERROR could not evaluate static initializer
-    //~| NOTE cannot cast pointer to integer
+    //~| unable to turn pointer into raw bytes
 };
 
 fn main() {}
index 8ac4aa87f642a41df642fdf73ee2538901d77380..2764d10348a761689260ea58f83f9b270ba23aef 100644 (file)
@@ -5,10 +5,16 @@ LL |     let _v = x == x;
    |              ^^^^^^ "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ptr_arith.rs:16:14
+  --> $DIR/ptr_arith.rs:15:13
+   |
+LL |     let x = &0 as *const _ as usize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+
+error[E0080]: could not evaluate static initializer
+  --> $DIR/ptr_arith.rs:23:14
    |
 LL |     let _v = x + 0;
-   |              ^^^^^ cannot cast pointer to integer because it was not created by cast from integer
+   |              ^^^^^ unable to turn pointer into raw bytes
 
 warning: skipping const checks
    |
@@ -17,7 +23,12 @@ help: skipping check that does not even have a feature gate
    |
 LL |     let _v = x == x;
    |              ^^^^^^
+help: skipping check that does not even have a feature gate
+  --> $DIR/ptr_arith.rs:15:13
+   |
+LL |     let x = &0 as *const _ as usize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0080`.
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
    |
index b73191d56a6129d840d3ede8f745f4de6ceaea05..4b55c299b5c4c93901bd44cc47acbdb8a73992bf 100644 (file)
@@ -1,5 +1,8 @@
 #![feature(const_raw_ptr_deref)]
 #![feature(const_ptr_offset_from)]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::ptr_offset_from;
 
 #[repr(C)]
 struct Struct {
@@ -8,39 +11,38 @@ struct Struct {
 }
 
 pub const DIFFERENT_ALLOC: usize = {
-    //~^ NOTE
     let uninit = std::mem::MaybeUninit::<Struct>::uninit();
     let base_ptr: *const Struct = &uninit as *const _ as *const Struct;
     let uninit2 = std::mem::MaybeUninit::<Struct>::uninit();
     let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct;
-    let offset = unsafe { field_ptr.offset_from(base_ptr) };
+    let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) }; //~ERROR evaluation of constant value failed
+    //~| cannot compute offset of pointers into different allocations.
     offset as usize
 };
 
 pub const NOT_PTR: usize = {
-    //~^ NOTE
     unsafe { (42 as *const u8).offset_from(&5u8) as usize }
 };
 
 pub const NOT_MULTIPLE_OF_SIZE: isize = {
-    //~^ NOTE
     let data = [5u8, 6, 7];
     let base_ptr = data.as_ptr();
     let field_ptr = &data[1] as *const u8 as *const u16;
-    unsafe { field_ptr.offset_from(base_ptr as *const u16) }
+    unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) } //~ERROR evaluation of constant value failed
+    //~| 1_isize cannot be divided by 2_isize without remainder
 };
 
 pub const OFFSET_FROM_NULL: isize = {
-    //~^ NOTE
     let ptr = 0 as *const u8;
-    unsafe { ptr.offset_from(ptr) }
+    unsafe { ptr_offset_from(ptr, ptr) } //~ERROR evaluation of constant value failed
+    //~| null pointer is not a valid pointer
 };
 
 pub const DIFFERENT_INT: isize = { // offset_from with two different integers: like DIFFERENT_ALLOC
-    //~^ NOTE
     let ptr1 = 8 as *const u8;
     let ptr2 = 16 as *const u8;
-    unsafe { ptr2.offset_from(ptr1) }
+    unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed
+    //~| 0x10 is not a valid pointer
 };
 
 fn main() {}
index 4254cda2a0084c4f81f8f53b943e2584e9483cfe..663bfbdade0ce932c660dadb1203daec2d16eee1 100644 (file)
-error: any use of this value will cause an error
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                    |
-   |                    ptr_offset_from cannot compute offset of pointers into different allocations.
-   |                    inside `ptr::const_ptr::<impl *const Struct>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `DIFFERENT_ALLOC` at $DIR/offset_from_ub.rs:16:27
-   | 
-  ::: $DIR/offset_from_ub.rs:10:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/offset_from_ub.rs:18:27
    |
-LL | / pub const DIFFERENT_ALLOC: usize = {
-LL | |
-LL | |     let uninit = std::mem::MaybeUninit::<Struct>::uninit();
-LL | |     let base_ptr: *const Struct = &uninit as *const _ as *const Struct;
-...  |
-LL | |     offset as usize
-LL | | };
-   | |__-
-   |
-   = note: `#[deny(const_err)]` on by default
-   = 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>
+LL |     let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) };
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from cannot compute offset of pointers into different allocations.
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                    |
-   |                    unable to turn bytes into a pointer
-   |                    inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `NOT_PTR` at $DIR/offset_from_ub.rs:22:14
+LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  0x2a is not a valid pointer
+   |                  inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    | 
-  ::: $DIR/offset_from_ub.rs:20:1
-   |
-LL | / pub const NOT_PTR: usize = {
-LL | |
-LL | |     unsafe { (42 as *const u8).offset_from(&5u8) as usize }
-LL | | };
-   | |__-
+  ::: $DIR/offset_from_ub.rs:24:14
    |
-   = 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>
+LL |     unsafe { (42 as *const u8).offset_from(&5u8) as usize }
+   |              ----------------------------------- inside `NOT_PTR` at $DIR/offset_from_ub.rs:24:14
 
-error: any use of this value will cause an error
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                    |
-   |                    exact_div: 1_isize cannot be divided by 2_isize without remainder
-   |                    inside `ptr::const_ptr::<impl *const u16>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `NOT_MULTIPLE_OF_SIZE` at $DIR/offset_from_ub.rs:30:14
-   | 
-  ::: $DIR/offset_from_ub.rs:25:1
-   |
-LL | / pub const NOT_MULTIPLE_OF_SIZE: isize = {
-LL | |
-LL | |     let data = [5u8, 6, 7];
-LL | |     let base_ptr = data.as_ptr();
-LL | |     let field_ptr = &data[1] as *const u8 as *const u16;
-LL | |     unsafe { field_ptr.offset_from(base_ptr as *const u16) }
-LL | | };
-   | |__-
+error[E0080]: evaluation of constant value failed
+  --> $DIR/offset_from_ub.rs:31:14
    |
-   = 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>
+LL |     unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exact_div: 1_isize cannot be divided by 2_isize without remainder
 
-error: any use of this value will cause an error
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                    |
-   |                    null pointer is not a valid pointer for this operation
-   |                    inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `OFFSET_FROM_NULL` at $DIR/offset_from_ub.rs:36:14
-   | 
-  ::: $DIR/offset_from_ub.rs:33:1
-   |
-LL | / pub const OFFSET_FROM_NULL: isize = {
-LL | |
-LL | |     let ptr = 0 as *const u8;
-LL | |     unsafe { ptr.offset_from(ptr) }
-LL | | };
-   | |__-
+error[E0080]: evaluation of constant value failed
+  --> $DIR/offset_from_ub.rs:37:14
    |
-   = 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>
+LL |     unsafe { ptr_offset_from(ptr, ptr) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ null pointer is not a valid pointer for this operation
 
-error: any use of this value will cause an error
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                    |
-   |                    unable to turn bytes into a pointer
-   |                    inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `DIFFERENT_INT` at $DIR/offset_from_ub.rs:43:14
-   | 
-  ::: $DIR/offset_from_ub.rs:39:1
-   |
-LL | / pub const DIFFERENT_INT: isize = { // offset_from with two different integers: like DIFFERENT_ALLOC
-LL | |
-LL | |     let ptr1 = 8 as *const u8;
-LL | |     let ptr2 = 16 as *const u8;
-LL | |     unsafe { ptr2.offset_from(ptr1) }
-LL | | };
-   | |__-
+error[E0080]: evaluation of constant value failed
+  --> $DIR/offset_from_ub.rs:44:14
    |
-   = 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>
+LL |     unsafe { ptr_offset_from(ptr2, ptr1) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0x10 is not a valid pointer
 
 error: aborting due to 5 previous errors
 
+For more information about this error, try `rustc --explain E0080`.
index 7ce45ba9c4b2b77e5ea9dd23a4e49fed5894efce..42a285a6eab4972fcfc2c9e235949f9d77a4d238 100644 (file)
@@ -2,6 +2,8 @@
 use std::ptr;
 
 // normalize-stderr-test "alloc\d+" -> "allocN"
+// normalize-stderr-test "0x7f+" -> "0x7f..f"
+
 
 pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) }; //~NOTE
 pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; //~NOTE
@@ -11,6 +13,7 @@ pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX)
 pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) }; //~NOTE
 pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) }; //~NOTE
 pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) }; //~NOTE
+pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) }; //~NOTE
 
 pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) }; //~NOTE
 pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) }; //~NOTE
index 45203d3e271199b82e42e735f8d6685b51aa901e..66a2722ed4acd1d244f4c9818fe1589ddb35875f 100644 (file)
@@ -1,4 +1,4 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -6,54 +6,41 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `BEFORE_START` at $DIR/offset_ub.rs:6:46
    | 
-  ::: $DIR/offset_ub.rs:6:1
+  ::: $DIR/offset_ub.rs:8:46
    |
 LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) };
-   | ------------------------------------------------------------------------------
-   |
-   = 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>
+   |                                              ------------------------------ inside `BEFORE_START` at $DIR/offset_ub.rs:8:46
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                  |
-   |                  pointer arithmetic failed: pointer must be in-bounds at offset 2, but is outside bounds of allocN which has size 1
+   |                  pointer arithmetic failed: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `AFTER_END` at $DIR/offset_ub.rs:7:43
    | 
-  ::: $DIR/offset_ub.rs:7:1
+  ::: $DIR/offset_ub.rs:9:43
    |
 LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) };
-   | --------------------------------------------------------------------------
-   |
-   = 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>
+   |                                           ----------------------------- inside `AFTER_END` at $DIR/offset_ub.rs:9:43
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                  |
-   |                  pointer arithmetic failed: pointer must be in-bounds at offset 101, but is outside bounds of allocN which has size 100
+   |                  pointer arithmetic failed: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `AFTER_ARRAY` at $DIR/offset_ub.rs:8:45
    | 
-  ::: $DIR/offset_ub.rs:8:1
+  ::: $DIR/offset_ub.rs:10:45
    |
 LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) };
-   | ------------------------------------------------------------------------------
-   |
-   = 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>
+   |                                             ------------------------------- inside `AFTER_ARRAY` at $DIR/offset_ub.rs:10:45
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -61,17 +48,13 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `OVERFLOW` at $DIR/offset_ub.rs:10:43
    | 
-  ::: $DIR/offset_ub.rs:10:1
+  ::: $DIR/offset_ub.rs:12:43
    |
 LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) };
-   | ----------------------------------------------------------------------------------
-   |
-   = 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>
+   |                                           ------------------------------------- inside `OVERFLOW` at $DIR/offset_ub.rs:12:43
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -79,17 +62,13 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `UNDERFLOW` at $DIR/offset_ub.rs:11:44
    | 
-  ::: $DIR/offset_ub.rs:11:1
+  ::: $DIR/offset_ub.rs:13:44
    |
 LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) };
-   | -----------------------------------------------------------------------------------
-   |
-   = 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>
+   |                                            ------------------------------------- inside `UNDERFLOW` at $DIR/offset_ub.rs:13:44
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -97,17 +76,13 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:12:56
    | 
-  ::: $DIR/offset_ub.rs:12:1
+  ::: $DIR/offset_ub.rs:14:56
    |
 LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) };
-   | ---------------------------------------------------------------------------------------------
-   |
-   = 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>
+   |                                                        ----------------------------------- inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:14:56
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -115,53 +90,55 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:57
    | 
-  ::: $DIR/offset_ub.rs:13:1
+  ::: $DIR/offset_ub.rs:15:57
    |
 LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) };
-   | --------------------------------------------------------------------------------------
+   |                                                         --------------------------- inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:15:57
+
+error[E0080]: evaluation of constant value failed
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  pointer arithmetic failed: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds
+   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   | 
+  ::: $DIR/offset_ub.rs:16:49
    |
-   = 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>
+LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) };
+   |                                                 ------------------------------------------------ inside `NEGATIVE_OFFSET` at $DIR/offset_ub.rs:16:49
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                  |
-   |                  pointer arithmetic failed: pointer must be in-bounds at offset 1, but is outside bounds of allocN which has size 0
+   |                  pointer arithmetic failed: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:15:50
    | 
-  ::: $DIR/offset_ub.rs:15:1
+  ::: $DIR/offset_ub.rs:18:50
    |
 LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(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 #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                                  --------------------------- inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:18:50
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) as *mut T }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                  |
-   |                  unable to turn bytes into a pointer
+   |                  0x1 is not a valid pointer
    |                  inside `ptr::mut_ptr::<impl *mut u8>::offset` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-   |                  inside `DANGLING` at $DIR/offset_ub.rs:16:42
    | 
-  ::: $DIR/offset_ub.rs:16:1
+  ::: $DIR/offset_ub.rs:19:42
    |
 LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) };
-   | ---------------------------------------------------------------------------------------------
-   |
-   = 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>
+   |                                          ------------------------------------------------- inside `DANGLING` at $DIR/offset_ub.rs:19:42
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -169,33 +146,26 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  pointer arithmetic failed: 0x0 is not a valid pointer
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:19:50
    | 
-  ::: $DIR/offset_ub.rs:19:1
+  ::: $DIR/offset_ub.rs:22:50
    |
 LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::<u8>().offset(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 #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                                  --------------------------- inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:22:50
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                  |
-   |                  unable to turn bytes into a pointer
+   |                  0x7f..f is not a valid pointer
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:22:47
    | 
-  ::: $DIR/offset_ub.rs:22:1
+  ::: $DIR/offset_ub.rs:25:47
    |
 LL | pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) };
-   | ---------------------------------------------------------------------------------------------
-   |
-   = 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>
+   |                                               -------------------------------------------- inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:25:47
 
-error: aborting due to 11 previous errors
+error: aborting due to 12 previous errors
 
+For more information about this error, try `rustc --explain E0080`.
index 0306a55af4e09bfa4139d67809d109e545e0229f..9b5fd18f818b0a0b071ddf98d62d6d68583b57f2 100644 (file)
@@ -1,6 +1,6 @@
 // compile-flags: --crate-type=lib
-// normalize-stderr-32bit: "offset 8" -> "offset $$TWO_WORDS"
-// normalize-stderr-64bit: "offset 16" -> "offset $$TWO_WORDS"
+// normalize-stderr-32bit: "8 bytes" -> "$$TWO_WORDS bytes"
+// normalize-stderr-64bit: "16 bytes" -> "$$TWO_WORDS bytes"
 // normalize-stderr-32bit: "size 4" -> "size $$WORD"
 // normalize-stderr-64bit: "size 8" -> "size $$WORD"
 
@@ -62,15 +62,15 @@ const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
 
 const _: *const u8 =
     unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
+//~| out-of-bounds
 
 const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
 //~^ ERROR any use of this value will cause an error
-//~| cannot cast pointer to integer
+//~| unable to turn pointer into raw bytes
 //~| WARN this was previously accepted by the compiler but is being phased out
 
 const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
 //~^ ERROR any use of this value will cause an error
-//~| cannot cast pointer to integer
+//~| unable to turn pointer into raw bytes
 //~| WARN this was previously accepted by the compiler but is being phased out
index 943de47879b5369aa4409037efefd4eaf84b4b6b..6ae24c179ff1c838dff09e859328d831bdc7b74f 100644 (file)
@@ -1,33 +1,22 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                  |
-   |                  pointer arithmetic failed: pointer must be in-bounds at offset $TWO_WORDS, but is outside bounds of alloc2 which has size $WORD
+   |                  pointer arithmetic failed: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
    |                  inside `ptr::const_ptr::<impl *const usize>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `_` at $DIR/ptr_comparisons.rs:61:34
    | 
-  ::: $DIR/ptr_comparisons.rs:61:1
+  ::: $DIR/ptr_comparisons.rs:61:34
    |
 LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
-   | -------------------------------------------------------------------
-   |
-   = 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>
+   |                                  ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:61:34
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/ptr_comparisons.rs:64:33
    |
-LL | / const _: *const u8 =
-LL | |     unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
-   | |_________________________________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^___-
-   |                                   |
-   |                                   memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD
-   |
-   = 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>
+LL |     unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc3 has size $WORD, so pointer to 1000 bytes starting at offset 0 is out-of-bounds
 
 error: any use of this value will cause an error
   --> $DIR/ptr_comparisons.rs:68:27
@@ -35,8 +24,9 @@ error: any use of this value will cause an error
 LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
    | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                           |
-   |                           cannot cast pointer to integer because it was not created by cast from integer
+   |                           unable to turn pointer into raw bytes
    |
+   = 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>
 
@@ -46,10 +36,11 @@ error: any use of this value will cause an error
 LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
    | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                           |
-   |                           cannot cast pointer to integer because it was not created by cast from integer
+   |                           unable to turn pointer into raw bytes
    |
    = 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 4 previous errors
 
+For more information about this error, try `rustc --explain E0080`.
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..e3fda57
--- /dev/null
@@ -0,0 +1,20 @@
+// build-pass
+
+#![crate_type = "lib"]
+#![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 }
+    }
+}
index bb9ccbba37692787209d323ca561705090c74899..67bc3202c105c133895da262781b485deb7ec253 100644 (file)
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/alloc.rs:8:1
    |
 LL | const LAYOUT_INVALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0 at .align_, but expected something greater or equal to 1
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .align_: encountered 0, but expected something greater or equal to 1
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
index 2c891b1d79c134678bc7a071519dfeefecf1ba32..ec89dec272dbc992adaa9ddf79ba35eef151b8f0 100644 (file)
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/alloc.rs:8:1
    |
 LL | const LAYOUT_INVALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0 at .align_, but expected something greater or equal to 1
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .align_: encountered 0, but expected something greater or equal to 1
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
index 2d1bba391e8202fb6e0fbba7ad851b3c1e6f3299..e2f5175bf0ac98186db436187812a108781aafc4 100644 (file)
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_never_arrays.rs:4:1
    |
 LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<deref>[0]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered a value of the never type `!`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
@@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_never_arrays.rs:7:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<deref>[0]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered a value of the never type `!`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -24,7 +24,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_never_arrays.rs:8:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<deref>[0]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered a value of the never type `!`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
index dd677f1b21edd55227c9292d1b67cf08c04faf97..c145eddef575b31afc4d743b0f4c18a40133617e 100644 (file)
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_never_arrays.rs:4:1
    |
 LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<deref>[0]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered a value of the never type `!`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
@@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_never_arrays.rs:7:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<deref>[0]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered a value of the never type `!`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -24,7 +24,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_never_arrays.rs:8:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<deref>[0]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered a value of the never type `!`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
diff --git a/src/test/ui/conversion-methods.rs b/src/test/ui/conversion-methods.rs
deleted file mode 100644 (file)
index 46c2e51..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-use std::path::{Path, PathBuf};
-
-
-fn main() {
-    let _tis_an_instants_play: String = "'Tis a fond Ambush—"; //~ ERROR mismatched types
-    let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise");
-    //~^ ERROR mismatched types
-
-    let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here
-    //~^ ERROR mismatched types
-
-    let _prove_piercing_earnest: Vec<usize> = &[1, 2, 3]; //~ ERROR mismatched types
-}
diff --git a/src/test/ui/conversion-methods.stderr b/src/test/ui/conversion-methods.stderr
deleted file mode 100644 (file)
index 4f47e1f..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/conversion-methods.rs:5:41
-   |
-LL |     let _tis_an_instants_play: String = "'Tis a fond Ambush—";
-   |                                ------   ^^^^^^^^^^^^^^^^^^^^^
-   |                                |        |
-   |                                |        expected struct `String`, found `&str`
-   |                                |        help: try using a conversion method: `"'Tis a fond Ambush—".to_string()`
-   |                                expected due to this
-
-error[E0308]: mismatched types
-  --> $DIR/conversion-methods.rs:6:40
-   |
-LL |     let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise");
-   |                              -------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                              |         |
-   |                              |         expected struct `PathBuf`, found `&Path`
-   |                              |         help: try using a conversion method: `Path::new("/ern/her/own/surprise").to_path_buf()`
-   |                              expected due to this
-
-error[E0308]: mismatched types
-  --> $DIR/conversion-methods.rs:9:40
-   |
-LL |     let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here
-   |                               ------   ^
-   |                               |        |
-   |                               |        expected struct `String`, found integer
-   |                               |        help: try using a conversion method: `2.to_string()`
-   |                               expected due to this
-
-error[E0308]: mismatched types
-  --> $DIR/conversion-methods.rs:12:47
-   |
-LL |     let _prove_piercing_earnest: Vec<usize> = &[1, 2, 3];
-   |                                  ----------   ^^^^^^^^^^
-   |                                  |            |
-   |                                  |            expected struct `Vec`, found `&[{integer}; 3]`
-   |                                  |            help: try using a conversion method: `(&[1, 2, 3]).to_vec()`
-   |                                  expected due to this
-   |
-   = note: expected struct `Vec<usize>`
-           found reference `&[{integer}; 3]`
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/crate-loading/auxiliary/proc-macro.rs b/src/test/ui/crate-loading/auxiliary/proc-macro.rs
new file mode 100644 (file)
index 0000000..52631de
--- /dev/null
@@ -0,0 +1,12 @@
+// force-host
+// no-prefer-dynamic
+#![crate_name = "reproduction"]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn mac(input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/ui/crate-loading/cross-compiled-proc-macro.rs b/src/test/ui/crate-loading/cross-compiled-proc-macro.rs
new file mode 100644 (file)
index 0000000..c1f4331
--- /dev/null
@@ -0,0 +1,8 @@
+// edition:2018
+// compile-flags:--extern reproduction
+// aux-build:proc-macro.rs
+// check-pass
+
+reproduction::mac!();
+
+fn main() {}
index 442a7c01e5a69421da5a91fe10f859624c202912..de4ccc185608c82ebadf5dbdd65a099ece02130a 100644 (file)
@@ -1,4 +1,5 @@
 // compile-flags: --target x86_64-unknown-uefi
+// needs-llvm-components: x86
 // rustc-env:CARGO=/usr/bin/cargo
 // rustc-env:RUSTUP_HOME=/home/bors/.rustup
 #![no_core]
index 25808efdfa6993e94c45af96bfd0878e1598f4ad..e61486fdc6ffd22069596fdb3f80b9b45293b904 100644 (file)
@@ -1,5 +1,5 @@
 error[E0463]: can't find crate for `core`
-  --> $DIR/missing-std.rs:5:1
+  --> $DIR/missing-std.rs:6:1
    |
 LL | extern crate core;
    | ^^^^^^^^^^^^^^^^^^ can't find crate
index 8967a7c6d33c7cd55cf8eb66ed34e82fa9be34b6..e848ddc55b7dff8be1152ab5cbfdef8a7dc9bebd 100644 (file)
@@ -1,6 +1,8 @@
 error[E0277]: the trait bound `TestDescAndFn: Testable` is not satisfied
   --> $DIR/mismatch.rs:9:1
    |
+LL | #[test]
+   | ------- in this procedural macro expansion
 LL | fn wrong_kind(){}
    | ^^^^^^^^^^^^^^^^^ the trait `Testable` is not implemented for `TestDescAndFn`
    |
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 @@ 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.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 b847000a81d80089c9d3bc98a1c043b4494d0962..7e579ec22dd42762b36768d7a2aa463a3d9c25e9 100644 (file)
@@ -1,6 +1,6 @@
 trait Foo {
     #[derive(Clone)]
-    //~^ ERROR `derive` may only be applied to structs, enums and unions
+    //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
     type Bar;
 }
 
@@ -8,7 +8,7 @@ struct Bar;
 
 impl Bar {
     #[derive(Clone)]
-    //~^ ERROR `derive` may only be applied to structs, enums and unions
+    //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
     fn bar(&self) {}
 }
 
index e892d3f0863036ff6c40b2da5e30d8fbd92204cd..1fd97bdd5ec62f4f24df1a1d0bec0ee4fbe75891 100644 (file)
@@ -1,14 +1,20 @@
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/derive-on-trait-item-or-impl-item.rs:2:5
    |
 LL |     #[derive(Clone)]
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^ not applicable here
+LL |
+LL |     type Bar;
+   |     --------- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/derive-on-trait-item-or-impl-item.rs:10:5
    |
 LL |     #[derive(Clone)]
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^ not applicable here
+LL |
+LL |     fn bar(&self) {}
+   |     ---------------- not a `struct`, `enum` or `union`
 
 error: aborting due to 2 previous errors
 
index 3d62bd8e8e7918d9fc52cc1a89c68fb8d410a679..c5bc50e407b25787dbd8d5ca2278e6597311a926 100644 (file)
@@ -1,10 +1,17 @@
 error[E0277]: the trait bound `Error: Clone` is not satisfied
   --> $DIR/derives-span-Clone-enum-struct-variant.rs:9:6
    |
+LL | #[derive(Clone)]
+   |          ----- in this derive macro expansion
+...
 LL |      x: Error
    |      ^^^^^^^^ the trait `Clone` is not implemented for `Error`
    |
-   = note: required by `clone`
+note: required by `clone`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL |     fn clone(&self) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index c855ec8e99327abb0d1311cb6311e5357a0924ac..a6dc818eb6fe4ea4786377c627695c123ef41ae3 100644 (file)
@@ -1,10 +1,17 @@
 error[E0277]: the trait bound `Error: Clone` is not satisfied
   --> $DIR/derives-span-Clone-enum.rs:9:6
    |
+LL | #[derive(Clone)]
+   |          ----- in this derive macro expansion
+...
 LL |      Error
    |      ^^^^^ the trait `Clone` is not implemented for `Error`
    |
-   = note: required by `clone`
+note: required by `clone`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL |     fn clone(&self) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 522ec9719ed41ca9277205fa21c34345aa5f58ce..cf7b9ec276e2542e52adadf8f645899bad42f4d5 100644 (file)
@@ -1,10 +1,17 @@
 error[E0277]: the trait bound `Error: Clone` is not satisfied
   --> $DIR/derives-span-Clone-struct.rs:8:5
    |
+LL | #[derive(Clone)]
+   |          ----- in this derive macro expansion
+LL | struct Struct {
 LL |     x: Error
    |     ^^^^^^^^ the trait `Clone` is not implemented for `Error`
    |
-   = note: required by `clone`
+note: required by `clone`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL |     fn clone(&self) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index b1f3e72f0d5634111daecb82bf8516adb1ab90c5..80733d62730d7a2fc78e3ddc5c377d34ec996cce 100644 (file)
@@ -1,10 +1,17 @@
 error[E0277]: the trait bound `Error: Clone` is not satisfied
   --> $DIR/derives-span-Clone-tuple-struct.rs:8:5
    |
+LL | #[derive(Clone)]
+   |          ----- in this derive macro expansion
+LL | struct Struct(
 LL |     Error
    |     ^^^^^ the trait `Clone` is not implemented for `Error`
    |
-   = note: required by `clone`
+note: required by `clone`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL |     fn clone(&self) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 2151335992fbcac3212f2146c0b39e9a47145e83..bdcbbf0c75787cf67e4034ba329c2e15e8ae60ca 100644 (file)
@@ -1,13 +1,14 @@
 error[E0277]: `Error` doesn't implement `Debug`
   --> $DIR/derives-span-Debug-enum-struct-variant.rs:9:6
    |
+LL | #[derive(Debug)]
+   |          ----- in this derive macro expansion
+...
 LL |      x: Error
    |      ^^^^^^^^ `Error` cannot be formatted using `{:?}`
    |
    = help: the trait `Debug` is not implemented for `Error`
-   = note: add `#[derive(Debug)]` or manually implement `Debug`
-   = note: required because of the requirements on the impl of `Debug` for `&Error`
-   = note: required for the cast to the object type `dyn Debug`
+   = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 99e618b40ece2c636ad18969859d665eee388de2..4ffb75935af9b996146a5a3e92a6719a31818a3e 100644 (file)
@@ -1,13 +1,14 @@
 error[E0277]: `Error` doesn't implement `Debug`
   --> $DIR/derives-span-Debug-enum.rs:9:6
    |
+LL | #[derive(Debug)]
+   |          ----- in this derive macro expansion
+...
 LL |      Error
    |      ^^^^^ `Error` cannot be formatted using `{:?}`
    |
    = help: the trait `Debug` is not implemented for `Error`
-   = note: add `#[derive(Debug)]` or manually implement `Debug`
-   = note: required because of the requirements on the impl of `Debug` for `&Error`
-   = note: required for the cast to the object type `dyn Debug`
+   = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 0086642c557cc9a38c97aaad27f26865f8078237..74d2460bb6906ba38e69f66b3f0c2e120d7d0a28 100644 (file)
@@ -1,13 +1,14 @@
 error[E0277]: `Error` doesn't implement `Debug`
   --> $DIR/derives-span-Debug-struct.rs:8:5
    |
+LL | #[derive(Debug)]
+   |          ----- in this derive macro expansion
+LL | struct Struct {
 LL |     x: Error
    |     ^^^^^^^^ `Error` cannot be formatted using `{:?}`
    |
    = help: the trait `Debug` is not implemented for `Error`
-   = note: add `#[derive(Debug)]` or manually implement `Debug`
-   = note: required because of the requirements on the impl of `Debug` for `&Error`
-   = note: required for the cast to the object type `dyn Debug`
+   = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 0b74908d1ee446b0b1aaab665e6267a12d362ebe..34ddb4e594377927288768dc0946b4f08ff8aa0f 100644 (file)
@@ -1,13 +1,14 @@
 error[E0277]: `Error` doesn't implement `Debug`
   --> $DIR/derives-span-Debug-tuple-struct.rs:8:5
    |
+LL | #[derive(Debug)]
+   |          ----- in this derive macro expansion
+LL | struct Struct(
 LL |     Error
    |     ^^^^^ `Error` cannot be formatted using `{:?}`
    |
    = help: the trait `Debug` is not implemented for `Error`
-   = note: add `#[derive(Debug)]` or manually implement `Debug`
-   = note: required because of the requirements on the impl of `Debug` for `&Error`
-   = note: required for the cast to the object type `dyn Debug`
+   = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index b4cf1119eeb8ab752801cce4e2309e0c927bf1b8..c60b6ac456ebf962e42821018a919f461e06bbc5 100644 (file)
@@ -1,10 +1,17 @@
 error[E0277]: the trait bound `Error: Default` is not satisfied
   --> $DIR/derives-span-Default-struct.rs:8:5
    |
+LL | #[derive(Default)]
+   |          ------- in this derive macro expansion
+LL | struct Struct {
 LL |     x: Error
    |     ^^^^^^^^ the trait `Default` is not implemented for `Error`
    |
-   = note: required by `std::default::Default::default`
+note: required by `std::default::Default::default`
+  --> $SRC_DIR/core/src/default.rs:LL:COL
+   |
+LL |     fn default() -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 62661a659be58c1fbdcf4654bb33870e710f3635..ed342f539da03e3f80e567b0bd8e90ed3cde3a39 100644 (file)
@@ -1,10 +1,17 @@
 error[E0277]: the trait bound `Error: Default` is not satisfied
   --> $DIR/derives-span-Default-tuple-struct.rs:8:5
    |
+LL | #[derive(Default)]
+   |          ------- in this derive macro expansion
+LL | struct Struct(
 LL |     Error
    |     ^^^^^ the trait `Default` is not implemented for `Error`
    |
-   = note: required by `std::default::Default::default`
+note: required by `std::default::Default::default`
+  --> $SRC_DIR/core/src/default.rs:LL:COL
+   |
+LL |     fn default() -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index b14f2f8f0735c713338bb3e74a270e89c53f472d..0a764053824562e9e265d3172dfb7bb7a0531b72 100644 (file)
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `Error: Eq` is not satisfied
   --> $DIR/derives-span-Eq-enum-struct-variant.rs:9:6
    |
+LL | #[derive(Eq,PartialEq)]
+   |          -- in this derive macro expansion
+...
 LL |      x: Error
    |      ^^^^^^^^ the trait `Eq` is not implemented for `Error`
    | 
index ed7e6936f56c51ddd5ff5777f784c2e52ee7ff77..c17e2c518aa76246498c77ecafed04f9a6140bc8 100644 (file)
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `Error: Eq` is not satisfied
   --> $DIR/derives-span-Eq-enum.rs:9:6
    |
+LL | #[derive(Eq,PartialEq)]
+   |          -- in this derive macro expansion
+...
 LL |      Error
    |      ^^^^^ the trait `Eq` is not implemented for `Error`
    | 
index ec26c5617210781834e76e3bfd35340f0757cf10..7a7640b40f627980bcaedd7aa7b3b0dca9fa4b15 100644 (file)
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `Error: Eq` is not satisfied
   --> $DIR/derives-span-Eq-struct.rs:8:5
    |
+LL | #[derive(Eq,PartialEq)]
+   |          -- in this derive macro expansion
+LL | struct Struct {
 LL |     x: Error
    |     ^^^^^^^^ the trait `Eq` is not implemented for `Error`
    | 
index a41acfbf5b515cda3349f66bc7afb894a084c2f1..35932986b0499660fd2f6b6e1b8621a7e3b76be4 100644 (file)
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `Error: Eq` is not satisfied
   --> $DIR/derives-span-Eq-tuple-struct.rs:8:5
    |
+LL | #[derive(Eq,PartialEq)]
+   |          -- in this derive macro expansion
+LL | struct Struct(
 LL |     Error
    |     ^^^^^ the trait `Eq` is not implemented for `Error`
    | 
index fef7b8f75ac6f0bb69a6c2e595e4ffa455c238ed..4616dadbe6bf7e7998c272f08901bcaf1aaa284b 100644 (file)
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `Error: Hash` is not satisfied
   --> $DIR/derives-span-Hash-enum-struct-variant.rs:9:6
    |
+LL | #[derive(Hash)]
+   |          ---- in this derive macro expansion
+...
 LL |      x: Error
    |      ^^^^^^^^ the trait `Hash` is not implemented for `Error`
    | 
index 90c5f91af919df7134f22947b08f8f9554974d86..ffc7f7bb7daafd2640ad7b97f02c3e09057efafe 100644 (file)
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `Error: Hash` is not satisfied
   --> $DIR/derives-span-Hash-enum.rs:8:6
    |
+LL | #[derive(Hash)]
+   |          ---- in this derive macro expansion
+...
 LL |      Error
    |      ^^^^^ the trait `Hash` is not implemented for `Error`
    | 
index b48828f439e1fcd306276021213a2e233ae9b6c1..14aebb4faace9b898f8c929941712391f45e6452 100644 (file)
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `Error: Hash` is not satisfied
   --> $DIR/derives-span-Hash-struct.rs:8:5
    |
+LL | #[derive(Hash)]
+   |          ---- in this derive macro expansion
+LL | struct Struct {
 LL |     x: Error
    |     ^^^^^^^^ the trait `Hash` is not implemented for `Error`
    | 
index 3db0299192f05a5a988b706fd70ee8d8a92f120f..50139dc3f0a7950824461cdbeb5d6d6d4724b1fd 100644 (file)
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `Error: Hash` is not satisfied
   --> $DIR/derives-span-Hash-tuple-struct.rs:8:5
    |
+LL | #[derive(Hash)]
+   |          ---- in this derive macro expansion
+LL | struct Struct(
 LL |     Error
    |     ^^^^^ the trait `Hash` is not implemented for `Error`
    | 
index 9f77122286ab66fce00fdb08409330d4dfb1dfe7..1e1cd715e6479343fc3ba6b9828a0a8d9cb8c6bd 100644 (file)
@@ -1,10 +1,17 @@
 error[E0277]: the trait bound `Error: Ord` is not satisfied
   --> $DIR/derives-span-Ord-enum-struct-variant.rs:9:6
    |
+LL | #[derive(Ord,Eq,PartialOrd,PartialEq)]
+   |          --- in this derive macro expansion
+...
 LL |      x: Error
    |      ^^^^^^^^ the trait `Ord` is not implemented for `Error`
    |
-   = note: required by `std::cmp::Ord::cmp`
+note: required by `std::cmp::Ord::cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn cmp(&self, other: &Self) -> Ordering;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index f5d2dd3daefb2e6b4f1dda5666cef0d9c468bef6..43abe9a954738ca3cbe4f86009de01b75162107d 100644 (file)
@@ -1,10 +1,17 @@
 error[E0277]: the trait bound `Error: Ord` is not satisfied
   --> $DIR/derives-span-Ord-enum.rs:9:6
    |
+LL | #[derive(Ord,Eq,PartialOrd,PartialEq)]
+   |          --- in this derive macro expansion
+...
 LL |      Error
    |      ^^^^^ the trait `Ord` is not implemented for `Error`
    |
-   = note: required by `std::cmp::Ord::cmp`
+note: required by `std::cmp::Ord::cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn cmp(&self, other: &Self) -> Ordering;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 7a61ca483127910ee5f1748ce2143d65fd76bdcd..44f6bab08c127854a2dd332374e30d3f6eb7e329 100644 (file)
@@ -1,10 +1,17 @@
 error[E0277]: the trait bound `Error: Ord` is not satisfied
   --> $DIR/derives-span-Ord-struct.rs:8:5
    |
+LL | #[derive(Ord,Eq,PartialOrd,PartialEq)]
+   |          --- in this derive macro expansion
+LL | struct Struct {
 LL |     x: Error
    |     ^^^^^^^^ the trait `Ord` is not implemented for `Error`
    |
-   = note: required by `std::cmp::Ord::cmp`
+note: required by `std::cmp::Ord::cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn cmp(&self, other: &Self) -> Ordering;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index cd67d9ce98e09fa4b759f52085228a9a7021eee0..e604018245ae3a6aeb0e7882a4f36337ee85245a 100644 (file)
@@ -1,10 +1,17 @@
 error[E0277]: the trait bound `Error: Ord` is not satisfied
   --> $DIR/derives-span-Ord-tuple-struct.rs:8:5
    |
+LL | #[derive(Ord,Eq,PartialOrd,PartialEq)]
+   |          --- in this derive macro expansion
+LL | struct Struct(
 LL |     Error
    |     ^^^^^ the trait `Ord` is not implemented for `Error`
    |
-   = note: required by `std::cmp::Ord::cmp`
+note: required by `std::cmp::Ord::cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn cmp(&self, other: &Self) -> Ordering;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index a579d695700d4286924395298c91582dbc313e24..abcba6da8aaee74c3e06b4cf401456a211fa9b37 100644 (file)
@@ -1,6 +1,9 @@
 error[E0369]: binary operation `==` cannot be applied to type `Error`
   --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:9:6
    |
+LL | #[derive(PartialEq)]
+   |          --------- in this derive macro expansion
+...
 LL |      x: Error
    |      ^^^^^^^^
    |
@@ -10,6 +13,9 @@ LL |      x: Error
 error[E0369]: binary operation `!=` cannot be applied to type `Error`
   --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:9:6
    |
+LL | #[derive(PartialEq)]
+   |          --------- in this derive macro expansion
+...
 LL |      x: Error
    |      ^^^^^^^^
    |
index 532430729c7cf3463ed05caa63d0a725778e0c90..cdb40c39f169ce7657f767654dad57b169820ac1 100644 (file)
@@ -1,6 +1,9 @@
 error[E0369]: binary operation `==` cannot be applied to type `Error`
   --> $DIR/derives-span-PartialEq-enum.rs:9:6
    |
+LL | #[derive(PartialEq)]
+   |          --------- in this derive macro expansion
+...
 LL |      Error
    |      ^^^^^
    |
@@ -10,6 +13,9 @@ LL |      Error
 error[E0369]: binary operation `!=` cannot be applied to type `Error`
   --> $DIR/derives-span-PartialEq-enum.rs:9:6
    |
+LL | #[derive(PartialEq)]
+   |          --------- in this derive macro expansion
+...
 LL |      Error
    |      ^^^^^
    |
index 5fec402dcd8565dde5625a2df0955fa8dc16f20d..4cf8851a098bcdb10289e9638e8953b78128ccea 100644 (file)
@@ -1,6 +1,9 @@
 error[E0369]: binary operation `==` cannot be applied to type `Error`
   --> $DIR/derives-span-PartialEq-struct.rs:8:5
    |
+LL | #[derive(PartialEq)]
+   |          --------- in this derive macro expansion
+LL | struct Struct {
 LL |     x: Error
    |     ^^^^^^^^
    |
@@ -10,6 +13,9 @@ LL |     x: Error
 error[E0369]: binary operation `!=` cannot be applied to type `Error`
   --> $DIR/derives-span-PartialEq-struct.rs:8:5
    |
+LL | #[derive(PartialEq)]
+   |          --------- in this derive macro expansion
+LL | struct Struct {
 LL |     x: Error
    |     ^^^^^^^^
    |
index 0a7f9e14859ae94e91c5e9f8ebc615ac4837ed2a..66bc16873538984644b7ec65f93128f87b8c3e8f 100644 (file)
@@ -1,6 +1,9 @@
 error[E0369]: binary operation `==` cannot be applied to type `Error`
   --> $DIR/derives-span-PartialEq-tuple-struct.rs:8:5
    |
+LL | #[derive(PartialEq)]
+   |          --------- in this derive macro expansion
+LL | struct Struct(
 LL |     Error
    |     ^^^^^
    |
@@ -10,6 +13,9 @@ LL |     Error
 error[E0369]: binary operation `!=` cannot be applied to type `Error`
   --> $DIR/derives-span-PartialEq-tuple-struct.rs:8:5
    |
+LL | #[derive(PartialEq)]
+   |          --------- in this derive macro expansion
+LL | struct Struct(
 LL |     Error
    |     ^^^^^
    |
index 8d84b1217b7a371ae3bbc8140d06e177be433baa..9a716048e26aa0a0694bc974b9ef636cb6b33b20 100644 (file)
@@ -1,11 +1,18 @@
 error[E0277]: can't compare `Error` with `Error`
   --> $DIR/derives-span-PartialOrd-enum-struct-variant.rs:9:6
    |
+LL | #[derive(PartialOrd,PartialEq)]
+   |          ---------- in this derive macro expansion
+...
 LL |      x: Error
    |      ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
    |
    = help: the trait `PartialOrd` is not implemented for `Error`
-   = note: required by `std::cmp::PartialOrd::partial_cmp`
+note: required by `std::cmp::PartialOrd::partial_cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index ce12727989df8ad60007a7171a52663f9e868c08..c726d33eab0135ef850f8c547e5b98fbcf0294ce 100644 (file)
@@ -1,11 +1,18 @@
 error[E0277]: can't compare `Error` with `Error`
   --> $DIR/derives-span-PartialOrd-enum.rs:9:6
    |
+LL | #[derive(PartialOrd,PartialEq)]
+   |          ---------- in this derive macro expansion
+...
 LL |      Error
    |      ^^^^^ no implementation for `Error < Error` and `Error > Error`
    |
    = help: the trait `PartialOrd` is not implemented for `Error`
-   = note: required by `std::cmp::PartialOrd::partial_cmp`
+note: required by `std::cmp::PartialOrd::partial_cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index fc488e734f752821819bb09830b44725a3b6406c..a56c163ca788ae061cbeff8d8afb601f9559e4d7 100644 (file)
@@ -1,11 +1,18 @@
 error[E0277]: can't compare `Error` with `Error`
   --> $DIR/derives-span-PartialOrd-struct.rs:8:5
    |
+LL | #[derive(PartialOrd,PartialEq)]
+   |          ---------- in this derive macro expansion
+LL | struct Struct {
 LL |     x: Error
    |     ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
    |
    = help: the trait `PartialOrd` is not implemented for `Error`
-   = note: required by `std::cmp::PartialOrd::partial_cmp`
+note: required by `std::cmp::PartialOrd::partial_cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index e18b039f21f26f7ef5c39fed4f627888b6c11cee..7a0a52e582444861a996ec12cc1aba12099cde47 100644 (file)
@@ -1,11 +1,18 @@
 error[E0277]: can't compare `Error` with `Error`
   --> $DIR/derives-span-PartialOrd-tuple-struct.rs:8:5
    |
+LL | #[derive(PartialOrd,PartialEq)]
+   |          ---------- in this derive macro expansion
+LL | struct Struct(
 LL |     Error
    |     ^^^^^ no implementation for `Error < Error` and `Error > Error`
    |
    = help: the trait `PartialOrd` is not implemented for `Error`
-   = note: required by `std::cmp::PartialOrd::partial_cmp`
+note: required by `std::cmp::PartialOrd::partial_cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 4919bac526360df08a5e6711009f95fa558b7d11..09611555fb9a57d0972ca500327170efd6eb1631 100644 (file)
@@ -10,7 +10,12 @@ LL |     is_copy(B { a: 1, b: C });
    |             expected an implementor of trait `Copy`
    |             help: consider borrowing here: `&B { a: 1, b: C }`
    |
-   = note: required because of the requirements on the impl of `Copy` for `B<C>`
+note: required because of the requirements on the impl of `Copy` for `B<C>`
+  --> $DIR/deriving-copyclone.rs:9:10
+   |
+LL | #[derive(Copy, Clone)]
+   |          ^^^^
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `C: Clone` is not satisfied
   --> $DIR/deriving-copyclone.rs:32:14
@@ -24,7 +29,12 @@ LL |     is_clone(B { a: 1, b: C });
    |              expected an implementor of trait `Clone`
    |              help: consider borrowing here: `&B { a: 1, b: C }`
    |
-   = note: required because of the requirements on the impl of `Clone` for `B<C>`
+note: required because of the requirements on the impl of `Clone` for `B<C>`
+  --> $DIR/deriving-copyclone.rs:9:16
+   |
+LL | #[derive(Copy, Clone)]
+   |                ^^^^^
+   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `D: Copy` is not satisfied
   --> $DIR/deriving-copyclone.rs:35:13
@@ -38,7 +48,12 @@ LL |     is_copy(B { a: 1, b: D });
    |             expected an implementor of trait `Copy`
    |             help: consider borrowing here: `&B { a: 1, b: D }`
    |
-   = note: required because of the requirements on the impl of `Copy` for `B<D>`
+note: required because of the requirements on the impl of `Copy` for `B<D>`
+  --> $DIR/deriving-copyclone.rs:9:10
+   |
+LL | #[derive(Copy, Clone)]
+   |          ^^^^
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 3 previous errors
 
index 0f69f94bf3a2a0d8402451b190a0cc76917ebdab..b97f87da4bfce22f357120e0fd88a310c207d411 100644 (file)
@@ -1,6 +1,9 @@
 error[E0369]: binary operation `==` cannot be applied to type `NoCloneOrEq`
   --> $DIR/deriving-no-inner-impl-error-message.rs:5:5
    |
+LL | #[derive(PartialEq)]
+   |          --------- in this derive macro expansion
+LL | struct E {
 LL |     x: NoCloneOrEq
    |     ^^^^^^^^^^^^^^
    |
@@ -10,6 +13,9 @@ LL |     x: NoCloneOrEq
 error[E0369]: binary operation `!=` cannot be applied to type `NoCloneOrEq`
   --> $DIR/deriving-no-inner-impl-error-message.rs:5:5
    |
+LL | #[derive(PartialEq)]
+   |          --------- in this derive macro expansion
+LL | struct E {
 LL |     x: NoCloneOrEq
    |     ^^^^^^^^^^^^^^
    |
@@ -19,10 +25,17 @@ LL |     x: NoCloneOrEq
 error[E0277]: the trait bound `NoCloneOrEq: Clone` is not satisfied
   --> $DIR/deriving-no-inner-impl-error-message.rs:10:5
    |
+LL | #[derive(Clone)]
+   |          ----- in this derive macro expansion
+LL | struct C {
 LL |     x: NoCloneOrEq
    |     ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoCloneOrEq`
    |
-   = note: required by `clone`
+note: required by `clone`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL |     fn clone(&self) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 3 previous errors
index 7e14c12c0a9920afb94c4322541724228062f6db..9afffa90085908d0d6857bb44efbb4bb20a0f754 100644 (file)
@@ -2,29 +2,29 @@
 
 struct S;
 
-#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s
 trait T { }
 
-#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s
 impl S { }
 
-#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s
 impl T for S { }
 
-#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s
 static s: usize = 0;
 
-#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s
 const c: usize = 0;
 
-#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s
 mod m { }
 
-#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s
 extern "C" { }
 
-#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s
 type A = usize;
 
-#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s
 fn main() { }
index 8c9daf4d4b30bfaed66c5a019a28d7d77810abd1..ef7ef54d1ae6b494d48f0baae983cc38fdfe40a6 100644 (file)
@@ -1,56 +1,74 @@
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/deriving-non-type.rs:5:1
    |
 LL | #[derive(PartialEq)]
-   | ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^ not applicable here
+LL | trait T { }
+   | ----------- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/deriving-non-type.rs:8:1
    |
 LL | #[derive(PartialEq)]
-   | ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^ not applicable here
+LL | impl S { }
+   | ---------- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/deriving-non-type.rs:11:1
    |
 LL | #[derive(PartialEq)]
-   | ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^ not applicable here
+LL | impl T for S { }
+   | ---------------- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/deriving-non-type.rs:14:1
    |
 LL | #[derive(PartialEq)]
-   | ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^ not applicable here
+LL | static s: usize = 0;
+   | -------------------- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/deriving-non-type.rs:17:1
    |
 LL | #[derive(PartialEq)]
-   | ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^ not applicable here
+LL | const c: usize = 0;
+   | ------------------- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/deriving-non-type.rs:20:1
    |
 LL | #[derive(PartialEq)]
-   | ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^ not applicable here
+LL | mod m { }
+   | --------- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/deriving-non-type.rs:23:1
    |
 LL | #[derive(PartialEq)]
-   | ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^ not applicable here
+LL | extern "C" { }
+   | -------------- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/deriving-non-type.rs:26:1
    |
 LL | #[derive(PartialEq)]
-   | ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^ not applicable here
+LL | type A = usize;
+   | --------------- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/deriving-non-type.rs:29:1
    |
 LL | #[derive(PartialEq)]
-   | ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^ not applicable here
+LL | fn main() { }
+   | ------------- not a `struct`, `enum` or `union`
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/deriving/deriving-with-helper.rs b/src/test/ui/deriving/deriving-with-helper.rs
new file mode 100644 (file)
index 0000000..ea74a15
--- /dev/null
@@ -0,0 +1,36 @@
+// check-pass
+// compile-flags: --crate-type=lib
+
+#![feature(decl_macro)]
+#![feature(lang_items)]
+#![feature(no_core)]
+#![feature(rustc_attrs)]
+
+#![no_core]
+
+#[rustc_builtin_macro]
+macro derive() {}
+
+#[rustc_builtin_macro(Default, attributes(default))]
+macro Default() {}
+
+mod default {
+    pub trait Default {
+        fn default() -> Self;
+    }
+
+    impl Default for u8 {
+        fn default() -> u8 {
+            0
+        }
+    }
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+#[derive(Default)]
+struct S {
+    #[default] // OK
+    field: u8,
+}
index 99ebe84cd9d83772506f5b2d7537f53c59985abd..1b6bcfbb9fcdedf5ad0a39935a092193cffcd9cc 100644 (file)
@@ -16,7 +16,7 @@ type D = (u8, u8)::AssocTy;
 
 type E = _::AssocTy;
 //~^ ERROR missing angle brackets in associated item path
-//~| ERROR the type placeholder `_` is not allowed within types on item signatures
+//~| ERROR the type placeholder `_` is not allowed within types on item signatures for type aliases
 
 type F = &'static (u8)::AssocTy;
 //~^ ERROR missing angle brackets in associated item path
@@ -47,37 +47,37 @@ type I = ty!()::AssocTy;
 
 trait K<A, B> {}
 fn foo<X: K<_, _>>(x: X) {}
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 
 fn bar<F>(_: F) where F: Fn() -> _ {}
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 
 fn baz<F: Fn() -> _>(_: F) {}
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 
 struct L<F>(F) where F: Fn() -> _;
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs
 struct M<F> where F: Fn() -> _ {
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs
     a: F,
 }
 enum N<F> where F: Fn() -> _ {
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for enums
     Foo(F),
 }
 
 union O<F> where F: Fn() -> _ {
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for unions
     foo: F,
 }
 
 trait P<F> where F: Fn() -> _ {
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for traits
 }
 
 trait Q {
     fn foo<F>(_: F) where F: Fn() -> _ {}
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 }
 
 fn main() {}
index fc5f218c04f1380e0a9101f67fea0df01360c301..8db9652b1eadeb6a686c956e64c95006b5908289 100644 (file)
@@ -81,7 +81,7 @@ error[E0223]: ambiguous associated type
 LL | type D = (u8, u8)::AssocTy;
    |          ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(u8, u8) as Trait>::AssocTy`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for type aliases
   --> $DIR/bad-assoc-ty.rs:17:10
    |
 LL | type E = _::AssocTy;
@@ -122,7 +122,7 @@ error[E0223]: ambiguous associated type
 LL | type I = ty!()::AssocTy;
    |          ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/bad-assoc-ty.rs:49:13
    |
 LL | fn foo<X: K<_, _>>(x: X) {}
@@ -135,7 +135,7 @@ help: use type parameters instead
 LL | fn foo<X: K<T, T>, T>(x: X) {}
    |             ^  ^ ^^^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/bad-assoc-ty.rs:52:34
    |
 LL | fn bar<F>(_: F) where F: Fn() -> _ {}
@@ -146,7 +146,7 @@ help: use type parameters instead
 LL | fn bar<F, T>(_: F) where F: Fn() -> T {}
    |         ^^^                         ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/bad-assoc-ty.rs:55:19
    |
 LL | fn baz<F: Fn() -> _>(_: F) {}
@@ -157,7 +157,7 @@ help: use type parameters instead
 LL | fn baz<F: Fn() -> T, T>(_: F) {}
    |                   ^^^^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
   --> $DIR/bad-assoc-ty.rs:58:33
    |
 LL | struct L<F>(F) where F: Fn() -> _;
@@ -168,7 +168,7 @@ help: use type parameters instead
 LL | struct L<F, T>(F) where F: Fn() -> T;
    |           ^^^                      ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
   --> $DIR/bad-assoc-ty.rs:60:30
    |
 LL | struct M<F> where F: Fn() -> _ {
@@ -179,7 +179,7 @@ help: use type parameters instead
 LL | struct M<F, T> where F: Fn() -> T {
    |           ^^^                   ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for enums
   --> $DIR/bad-assoc-ty.rs:64:28
    |
 LL | enum N<F> where F: Fn() -> _ {
@@ -190,7 +190,7 @@ help: use type parameters instead
 LL | enum N<F, T> where F: Fn() -> T {
    |         ^^^                   ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for unions
   --> $DIR/bad-assoc-ty.rs:69:29
    |
 LL | union O<F> where F: Fn() -> _ {
@@ -201,7 +201,7 @@ help: use type parameters instead
 LL | union O<F, T> where F: Fn() -> T {
    |          ^^^                   ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for traits
   --> $DIR/bad-assoc-ty.rs:74:29
    |
 LL | trait P<F> where F: Fn() -> _ {
@@ -212,7 +212,7 @@ help: use type parameters instead
 LL | trait P<F, T> where F: Fn() -> T {
    |          ^^^                   ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/bad-assoc-ty.rs:79:38
    |
 LL |     fn foo<F>(_: F) where F: Fn() -> _ {}
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 1bd4543f2316c5bfab5d4a9ff7d4847931dc7d40..fcb4ea1d592b589d81bbeb0a174890e993335348 100644 (file)
@@ -1,9 +1,6 @@
 error[E0277]: the trait bound `i8: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:24:21
    |
-LL |     fn bar(&self){}
-   |     ------------- required by `Foo::bar`
-...
 LL |     Foo::<i32>::bar(&1i8);
    |                     ^^^^ the trait `Foo<i32>` is not implemented for `i8`
    |
@@ -13,13 +10,15 @@ LL |     Foo::<i32>::bar(&1i8);
              <i8 as Foo<u32>>
              <i8 as Foo<u64>>
              <i8 as Foo<u8>>
+note: required by `Foo::bar`
+  --> $DIR/issue-39802-show-5-trait-impls.rs:2:5
+   |
+LL |     fn bar(&self){}
+   |     ^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:25:21
    |
-LL |     fn bar(&self){}
-   |     ------------- required by `Foo::bar`
-...
 LL |     Foo::<i32>::bar(&1u8);
    |                     ^^^^ the trait `Foo<i32>` is not implemented for `u8`
    |
@@ -28,13 +27,15 @@ LL |     Foo::<i32>::bar(&1u8);
              <u8 as Foo<u16>>
              <u8 as Foo<u32>>
              <u8 as Foo<u64>>
+note: required by `Foo::bar`
+  --> $DIR/issue-39802-show-5-trait-impls.rs:2:5
+   |
+LL |     fn bar(&self){}
+   |     ^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `bool: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:26:21
    |
-LL |     fn bar(&self){}
-   |     ------------- required by `Foo::bar`
-...
 LL |     Foo::<i32>::bar(&true);
    |                     ^^^^^ the trait `Foo<i32>` is not implemented for `bool`
    |
@@ -44,6 +45,11 @@ LL |     Foo::<i32>::bar(&true);
              <bool as Foo<u16>>
              <bool as Foo<u32>>
            and 2 others
+note: required by `Foo::bar`
+  --> $DIR/issue-39802-show-5-trait-impls.rs:2:5
+   |
+LL |     fn bar(&self){}
+   |     ^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/dyn-drop/dyn-drop.rs b/src/test/ui/dyn-drop/dyn-drop.rs
new file mode 100644 (file)
index 0000000..e1668a3
--- /dev/null
@@ -0,0 +1,16 @@
+#![deny(dyn_drop)]
+#![allow(bare_trait_objects)]
+fn foo(_: Box<dyn Drop>) {} //~ ERROR
+fn bar(_: &dyn Drop) {} //~ERROR
+fn baz(_: *mut Drop) {} //~ ERROR
+struct Foo {
+  _x: Box<dyn Drop> //~ ERROR
+}
+trait Bar {
+  type T: ?Sized;
+}
+struct Baz {}
+impl Bar for Baz {
+  type T = dyn Drop; //~ ERROR
+}
+fn main() {}
diff --git a/src/test/ui/dyn-drop/dyn-drop.stderr b/src/test/ui/dyn-drop/dyn-drop.stderr
new file mode 100644 (file)
index 0000000..1b1dbc4
--- /dev/null
@@ -0,0 +1,38 @@
+error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped
+  --> $DIR/dyn-drop.rs:3:19
+   |
+LL | fn foo(_: Box<dyn Drop>) {}
+   |                   ^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/dyn-drop.rs:1:9
+   |
+LL | #![deny(dyn_drop)]
+   |         ^^^^^^^^
+
+error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped
+  --> $DIR/dyn-drop.rs:4:16
+   |
+LL | fn bar(_: &dyn Drop) {}
+   |                ^^^^
+
+error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped
+  --> $DIR/dyn-drop.rs:5:16
+   |
+LL | fn baz(_: *mut Drop) {}
+   |                ^^^^
+
+error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped
+  --> $DIR/dyn-drop.rs:7:15
+   |
+LL |   _x: Box<dyn Drop>
+   |               ^^^^
+
+error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped
+  --> $DIR/dyn-drop.rs:14:16
+   |
+LL |   type T = dyn Drop;
+   |                ^^^^
+
+error: aborting due to 5 previous errors
+
index 003736208ed38e818974558a932cd1732e19d4df..c815080fc4ab6f563bbdc63ec43578e91d69c568 100644 (file)
@@ -3,7 +3,8 @@
 // to detect or fix uses of `dyn` under a macro. Since we are testing
 // this file via `rustfix`, we want the rustfix output to be
 // compilable; so the macros here carefully use `dyn` "correctly."
-
+//
+// edition:2015
 // run-rustfix
 
 #![allow(non_camel_case_types)]
 mod outer_mod {
     pub mod r#dyn {
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
         pub struct r#dyn;
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
     }
 }
 use outer_mod::r#dyn::r#dyn;
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 //~| ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 
 fn main() {
     match r#dyn { r#dyn => {} }
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 //~| ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
     macro_defn::r#dyn();
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 
     macro_defn::boxed();
 }
@@ -42,7 +43,7 @@ mod macro_defn {
 
     macro_rules! r#dyn {
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 
         // Note that we do not lint nor fix occurrences under macros
         ($dyn:tt) => { (Box<dyn Trait>, Box<$dyn Trait>) }
@@ -50,23 +51,23 @@ mod macro_defn {
 
     pub fn r#dyn() -> ::outer_mod::r#dyn::r#dyn {
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 //~| ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 //~| ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
         ::outer_mod::r#dyn::r#dyn
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 //~| ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
     }
 
 
 
     pub fn boxed() -> r#dyn!(
         //~^ ERROR `dyn` is a keyword
-        //~| WARN was previously accepted
+        //~| WARN this is accepted in the current edition
 
             // Note that we do not lint nor fix occurrences under macros
             dyn
index 0e5c39fc501beecc166f4d5b9c1dfcad6f147919..6cdc70714942527174f726caa582b3912de618ac 100644 (file)
@@ -3,7 +3,8 @@
 // to detect or fix uses of `dyn` under a macro. Since we are testing
 // this file via `rustfix`, we want the rustfix output to be
 // compilable; so the macros here carefully use `dyn` "correctly."
-
+//
+// edition:2015
 // run-rustfix
 
 #![allow(non_camel_case_types)]
 mod outer_mod {
     pub mod dyn {
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
         pub struct dyn;
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
     }
 }
 use outer_mod::dyn::dyn;
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 //~| ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 
 fn main() {
     match dyn { dyn => {} }
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 //~| ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
     macro_defn::dyn();
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 
     macro_defn::boxed();
 }
@@ -42,7 +43,7 @@ mod macro_defn {
 
     macro_rules! dyn {
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 
         // Note that we do not lint nor fix occurrences under macros
         ($dyn:tt) => { (Box<dyn Trait>, Box<$dyn Trait>) }
@@ -50,23 +51,23 @@ mod macro_defn {
 
     pub fn dyn() -> ::outer_mod::dyn::dyn {
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 //~| ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 //~| ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
         ::outer_mod::dyn::dyn
 //~^ ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
 //~| ERROR `dyn` is a keyword
-//~| WARN was previously accepted
+//~| WARN this is accepted in the current edition
     }
 
 
 
     pub fn boxed() -> dyn!(
         //~^ ERROR `dyn` is a keyword
-        //~| WARN was previously accepted
+        //~| WARN this is accepted in the current edition
 
             // Note that we do not lint nor fix occurrences under macros
             dyn
index 32f06b62bb41acacc04eda5b89f6e19096d6be74..3eb5bb7b26d426b821baf6dc7dfffaa928ec6445 100644 (file)
 error: `dyn` is a keyword in the 2018 edition
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:13:13
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:14:13
    |
 LL |     pub mod dyn {
    |             ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
    |
 note: the lint level is defined here
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:10:9
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:11:9
    |
 LL | #![deny(keyword_idents)]
    |         ^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `dyn` is a keyword in the 2018 edition
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:16:20
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:17:20
    |
 LL |         pub struct dyn;
    |                    ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `dyn` is a keyword in the 2018 edition
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:21:16
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:22:16
    |
 LL | use outer_mod::dyn::dyn;
    |                ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `dyn` is a keyword in the 2018 edition
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:21:21
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:22:21
    |
 LL | use outer_mod::dyn::dyn;
    |                     ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `dyn` is a keyword in the 2018 edition
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:28:11
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:29:11
    |
 LL |     match dyn { dyn => {} }
    |           ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `dyn` is a keyword in the 2018 edition
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:28:17
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:29:17
    |
 LL |     match dyn { dyn => {} }
    |                 ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `dyn` is a keyword in the 2018 edition
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:33:17
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:34:17
    |
 LL |     macro_defn::dyn();
    |                 ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `dyn` is a keyword in the 2018 edition
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:43:18
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:44:18
    |
 LL |     macro_rules! dyn {
    |                  ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `dyn` is a keyword in the 2018 edition
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:12
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:52:12
    |
 LL |     pub fn dyn() -> ::outer_mod::dyn::dyn {
    |            ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `dyn` is a keyword in the 2018 edition
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:34
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:52:34
    |
 LL |     pub fn dyn() -> ::outer_mod::dyn::dyn {
    |                                  ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `dyn` is a keyword in the 2018 edition
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:39
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:52:39
    |
 LL |     pub fn dyn() -> ::outer_mod::dyn::dyn {
    |                                       ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `dyn` is a keyword in the 2018 edition
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:58:22
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:59:22
    |
 LL |         ::outer_mod::dyn::dyn
    |                      ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `dyn` is a keyword in the 2018 edition
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:58:27
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:59:27
    |
 LL |         ::outer_mod::dyn::dyn
    |                           ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `dyn` is a keyword in the 2018 edition
-  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:67:23
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:68:23
    |
 LL |     pub fn boxed() -> dyn!(
    |                       ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: aborting due to 14 previous errors
index cf14aef7900a73bda28932fc0772110b5f5e95d3..bda2ed17ecfab458018ea611c51ec8626a80ce7a 100644 (file)
@@ -1,11 +1,12 @@
-// build-pass (FIXME(62277): could be check-pass?)
-
 // Under the 2015 edition with the keyword_idents lint, `dyn` is
 // not entirely acceptable as an identifier.
 //
 // We currently do not attempt to detect or fix uses of `dyn` as an
 // identifier under a macro, including under the declarative `macro`
 // forms from macros 1.2 and macros 2.0.
+//
+// check-pass
+// edition:2015
 
 #![feature(decl_macro)]
 #![allow(non_camel_case_types)]
index 0d85b87dee5a163a5faefc6a34b0ee4c6cbd171e..472f6b5c8e5141fc59716eef3203b9d511c50720 100644 (file)
@@ -1,10 +1,11 @@
-// build-pass (FIXME(62277): could be check-pass?)
-
 // Under the 2015 edition with the keyword_idents lint, `dyn` is
 // not entirely acceptable as an identifier.
 //
 // We currently do not attempt to detect or fix uses of `dyn` as an
 // identifier under a macro.
+//
+// check-pass
+// edition:2015
 
 #![allow(non_camel_case_types)]
 #![deny(keyword_idents)]
index 2a8b6b24831c0376b793bf3eab3686cb18ed68e7..d6a33c08d199faa6302cf98ce9798c379094f5f8 100644 (file)
@@ -1,7 +1,8 @@
 // Under the 2015 edition without the keyword_idents lint, `dyn` is
 // entirely acceptable as an identifier.
-
-// build-pass (FIXME(62277): could be check-pass?)
+//
+// check-pass
+// edition:2015
 
 #![allow(non_camel_case_types)]
 
index 7c2babaf7abaa2fa6b42c56822b6654dbe7ade9b..23ca36b71e00f7ac22904f6d19420862bea29cdc 100644 (file)
@@ -3,12 +3,12 @@
 
 fn function(x: &SomeTrait, y: Box<SomeTrait>) {
     //~^ ERROR trait objects without an explicit `dyn` are deprecated
-    //~| WARN this was previously accepted
+    //~| WARN this is accepted in the current edition
     //~| ERROR trait objects without an explicit `dyn` are deprecated
-    //~| WARN this was previously accepted
+    //~| WARN this is accepted in the current edition
     let _x: &SomeTrait = todo!();
     //~^ ERROR trait objects without an explicit `dyn` are deprecated
-    //~| WARN this was previously accepted
+    //~| WARN this is accepted in the current edition
 }
 
 trait SomeTrait {}
index ea73e56d8433da6a100118a527c1aba0befcf035..30f09e22792167ea0a9151c9a4430713810fb8c0 100644 (file)
@@ -9,7 +9,7 @@ note: the lint level is defined here
    |
 LL | #[deny(bare_trait_objects)]
    |        ^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
    = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
 
 error: trait objects without an explicit `dyn` are deprecated
@@ -18,7 +18,7 @@ error: trait objects without an explicit `dyn` are deprecated
 LL | fn function(x: &SomeTrait, y: Box<SomeTrait>) {
    |                                   ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
    = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
 
 error: trait objects without an explicit `dyn` are deprecated
@@ -27,7 +27,7 @@ error: trait objects without an explicit `dyn` are deprecated
 LL |     let _x: &SomeTrait = todo!();
    |              ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
    = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
 
 error: aborting due to 3 previous errors
index 4cb9bd1975a7f5a5e6741e29960158843987cf90..59e7f9a6083ced1b4d395b247939aa63960fb0c9 100644 (file)
@@ -1,5 +1,6 @@
 // check-pass
-
+// edition:2015
+//
 // rust-lang/rust#56327: Some occurrences of `dyn` within a macro are
 // not instances of identifiers, and thus should *not* be caught by the
 // keyword_ident lint.
@@ -9,6 +10,7 @@
 // anything.
 
 #![deny(rust_2018_compatibility)]
+#![allow(dyn_drop)]
 
 macro_rules! foo {
     () => {
index 980d99a6d6c11170b52e96ebe93845fc6a7bb17c..8aa65bbfdc9e7bd233ef93860622538b063b83b8 100644 (file)
@@ -29,6 +29,6 @@ impl Index<usize> for T {
 
 fn main() {
     assert_eq!(&S[0], "hello");
-    &T[0];
+    let _ = &T[0];
     // let x = &x as &Debug;
 }
index 126421326949b41bc4c16ab9a9bf0692c50119e3..69242fd715cef30b81a032342f3137ca227e9ea4 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![feature(rust_2018_preview)]
 
index 310bff21d1851636299fee16c2f6700e33014d96..3fffb30c612d02d8e2caf0f7d416ce5d435c3466 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 // edition:2018
 // compile-flags:--extern edition_imports_2015
 // aux-build:edition-imports-2015.rs
index 9c3beb1ce58c19b5a231a347c8799c4f6eb1f85f..b2695bea5c39dc0d408d2f0bf2eaf8ce4837625b 100644 (file)
@@ -1,6 +1,6 @@
 // edition:2015
 // aux-build:edition-kw-macro-2015.rs
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![allow(keyword_idents)]
 
index 619e6424db441f645e1108571014bcb7d15ee40c..707d8e95c14140a37e7dfa78f504b733ded708bd 100644 (file)
@@ -1,6 +1,6 @@
 // edition:2018
 // aux-build:edition-kw-macro-2015.rs
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![allow(keyword_idents)]
 
index 3631415fc5f987f9f9f981a8628667aa48e995fe..fcfe493c1a228b7bf877414dd97a5c4eefba8545 100644 (file)
@@ -8,5 +8,5 @@ fn main() {
     let y = &x as *const _;
     let _ = y.is_null();
     //~^ error: type annotations needed [tyvar_behind_raw_pointer]
-    //~^^ warning: this was previously accepted
+    //~^^ warning: this is accepted in the current edition
 }
index 1df582ee06c42f97a43f6c021931b1872f8954cd..417daf36fca7dd3ad678c2d73d635782f342d847 100644 (file)
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #[deny(warnings)]
    |        ^^^^^^^^
    = note: `#[deny(tyvar_behind_raw_pointer)]` implied by `#[deny(warnings)]`
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
 
 error: aborting due to previous error
index 559f10de109815b0492d7548d75b95dfb3fac98d..d8553815b75de11cbd209aa915e947983cfd9426 100644 (file)
@@ -1,12 +1,14 @@
 #![feature(imported_main)]
-#![feature(min_type_alias_impl_trait, impl_trait_in_bindings)]
+#![feature(min_type_alias_impl_trait)]
 #![allow(incomplete_features)]
 //~^^^ ERROR `main` function not found in crate
 pub mod foo {
     type MainFn = impl Fn();
+    //~^ ERROR could not find defining uses
 
     fn bar() {}
     pub const BAR: MainFn = bar;
+    //~^ ERROR mismatched types [E0308]
 }
 
 use foo::BAR as main;
index 9b879fc09f7290c3e06d97f0bb32dc3587c19ead..c4c0afc5687c1aa99bf4e6ee112a91836846401d 100644 (file)
@@ -2,7 +2,7 @@ error[E0601]: `main` function not found in crate `imported_main_const_fn_item_ty
   --> $DIR/imported_main_const_fn_item_type_forbidden.rs:1:1
    |
 LL | / #![feature(imported_main)]
-LL | | #![feature(min_type_alias_impl_trait, impl_trait_in_bindings)]
+LL | | #![feature(min_type_alias_impl_trait)]
 LL | | #![allow(incomplete_features)]
 LL | |
 ...  |
@@ -12,6 +12,25 @@ LL | | use foo::BAR as main;
    |       |
    |       non-function item at `crate::main` is found
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:10:29
+   |
+LL |     type MainFn = impl Fn();
+   |                   --------- the expected opaque type
+...
+LL |     pub const BAR: MainFn = bar;
+   |                             ^^^ expected opaque type, found fn item
+   |
+   = note: expected opaque type `impl Fn<()>`
+                  found fn item `fn() {bar}`
+
+error: could not find defining uses
+  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:6:19
+   |
+LL |     type MainFn = impl Fn();
+   |                   ^^^^^^^^^
+
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0601`.
+Some errors have detailed explanations: E0308, E0601.
+For more information about an error, try `rustc --explain E0308`.
index eb68a6298d1ac1217a3deca57ec8d270478359df..cead9776e4abb3a4a4d96319cbc747a6d84df428 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Trait` cannot be made into an object
-  --> $DIR/E0038.rs:5:16
+  --> $DIR/E0038.rs:5:20
    |
 LL | fn call_foo(x: Box<dyn Trait>) {
-   |                ^^^^^^^^^^^^^^ `Trait` cannot be made into an object
+   |                    ^^^^^^^^^ `Trait` cannot be made into an object
    |
    = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
index f8b4d61b3230102eda9efc78d08ec554706bdb43..98cd6d54c1fd4e00732c196172da08157c1caf01 100644 (file)
@@ -2,5 +2,4 @@ fn foo() -> _ { 5 } //~ ERROR E0121
 
 static BAR: _ = "test"; //~ ERROR E0121
 
-fn main() {
-}
+fn main() {}
index 246f69558ff0d46224d4061c3ba903d496545ad9..cc0c2df72ea7ccbf3c90fb041c9c033950861951 100644 (file)
@@ -1,4 +1,4 @@
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/E0121.rs:1:13
    |
 LL | fn foo() -> _ { 5 }
@@ -7,7 +7,7 @@ LL | fn foo() -> _ { 5 }
    |             not allowed in type signatures
    |             help: replace with the correct return type: `i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
   --> $DIR/E0121.rs:3:13
    |
 LL | static BAR: _ = "test";
index 2f0dfb6dd8248e8093fb75036b175f9b4fdb4863..b6078e302360612b8f7c218c8942345c99b57957 100644 (file)
@@ -1,13 +1,15 @@
 error[E0283]: type annotations needed
   --> $DIR/E0283.rs:30:21
    |
-LL |     fn create() -> u32;
-   |     ------------------- required by `Generator::create`
-...
 LL |     let cont: u32 = Generator::create();
    |                     ^^^^^^^^^^^^^^^^^ cannot infer type
    |
    = note: cannot satisfy `_: Generator`
+note: required by `Generator::create`
+  --> $DIR/E0283.rs:2:5
+   |
+LL |     fn create() -> u32;
+   |     ^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed
   --> $DIR/E0283.rs:35:24
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 76dd857ea56163620b81bb0d77dad7f88dff0ab6..654b21f05b6fe58e315fa586b73f59969c9e8b20 100644 (file)
@@ -3,8 +3,7 @@
 const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
 
 const VALUE: u8 = unsafe { *REG_ADDR };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 fn main() {
 }
index 521394bdc8e015c9b7b88c50ef46bbe5704e591e..91997fcf0f901c66fe733d8a7246832cf3182b65 100644 (file)
@@ -1,14 +1,9 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/E0396-fixed.rs:5:28
    |
 LL | const VALUE: u8 = unsafe { *REG_ADDR };
-   | ---------------------------^^^^^^^^^---
-   |                            |
-   |                            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>
+   |                            ^^^^^^^^^ 0x5f3759df is not a valid pointer
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0080`.
index 3bf428676105d383d48a1798cf33bbb0df604760..df76f6b13af9b4f8a147ee7f2e927cb9cd371afe 100644 (file)
@@ -1,6 +1,5 @@
 // repr currently doesn't support literals
 #[repr("C")] //~ ERROR E0565
-             //~| ERROR E0565
-struct A {  }
+struct A {}
 
-fn main() {  }
+fn main() {}
index aa0951528e1ed5764e246a0c49d48d8029fc1bb7..6ed90c0ae4ffe10e97ed190a0cea077e17ed65e3 100644 (file)
@@ -4,12 +4,6 @@ error[E0565]: meta item in `repr` must be an identifier
 LL | #[repr("C")]
    |        ^^^
 
-error[E0565]: meta item in `repr` must be an identifier
-  --> $DIR/E0565.rs:2:8
-   |
-LL | #[repr("C")]
-   |        ^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0565`.
index 1d3336fb181a06778af862ecf457850ae2f1c893..e59b8a8ae35ac1bf3b854b4ac1286eadf274c2fc 100644 (file)
@@ -1,6 +1,9 @@
 error[E0624]: associated function `method` is private
   --> $DIR/E0624.rs:11:9
    |
+LL |         fn method(&self) {}
+   |         ---------------- private associated function defined here
+...
 LL |     foo.method();
    |         ^^^^^^ private associated function
 
index ea73c58993e2b70fee65eaa5967186d38ff2d48a..14697d89e822bb6d1eeb6cbabf51aaa4f5a67fdc 100644 (file)
@@ -2,7 +2,7 @@ error[E0777]: expected path to a trait, found literal
   --> $DIR/E0777.rs:1:10
    |
 LL | #[derive("Clone")]
-   |          ^^^^^^^
+   |          ^^^^^^^ not a trait
    |
    = help: try using `#[derive(Clone)]`
 
@@ -12,7 +12,7 @@ error[E0777]: expected path to a trait, found literal
 LL |   #[derive("Clone
    |  __________^
 LL | | ")]
-   | |_^
+   | |_^ not a trait
    |
    = help: for example, write `#[derive(Debug)]` for `Debug`
 
index 55f43840b9a3ad6a87a94e10292e5da941b2745f..f4a2330da177381d8e4dd887d5dbe68f629d3170 100644 (file)
@@ -84,18 +84,33 @@ error[E0624]: associated function `pub_crate` is private
    |
 LL |     r.pub_crate();
    |       ^^^^^^^^^ private associated function
+   | 
+  ::: $DIR/auxiliary/pub-and-stability.rs:114:9
+   |
+LL |         pub(crate) fn pub_crate(&self) -> i32 { self.d_priv }
+   |         ------------------------------------- private associated function defined here
 
 error[E0624]: associated function `pub_mod` is private
   --> $DIR/explore-issue-38412.rs:51:7
    |
 LL |     r.pub_mod();
    |       ^^^^^^^ private associated function
+   | 
+  ::: $DIR/auxiliary/pub-and-stability.rs:116:9
+   |
+LL |         pub(in m) fn pub_mod(&self) -> i32 { self.d_priv }
+   |         ---------------------------------- private associated function defined here
 
 error[E0624]: associated function `private` is private
   --> $DIR/explore-issue-38412.rs:52:7
    |
 LL |     r.private();
    |       ^^^^^^^ private associated function
+   | 
+  ::: $DIR/auxiliary/pub-and-stability.rs:118:9
+   |
+LL |         fn private(&self) -> i32 { self.d_priv }
+   |         ------------------------ private associated function defined here
 
 error[E0658]: use of unstable library feature 'unstable_undeclared'
   --> $DIR/explore-issue-38412.rs:57:7
@@ -120,18 +135,33 @@ error[E0624]: associated function `pub_crate` is private
    |
 LL |     t.pub_crate();
    |       ^^^^^^^^^ private associated function
+   | 
+  ::: $DIR/auxiliary/pub-and-stability.rs:129:9
+   |
+LL |         pub(crate) fn pub_crate(&self) -> i32 { self.0 }
+   |         ------------------------------------- private associated function defined here
 
 error[E0624]: associated function `pub_mod` is private
   --> $DIR/explore-issue-38412.rs:64:7
    |
 LL |     t.pub_mod();
    |       ^^^^^^^ private associated function
+   | 
+  ::: $DIR/auxiliary/pub-and-stability.rs:130:9
+   |
+LL |         pub(in m) fn pub_mod(&self) -> i32 { self.0 }
+   |         ---------------------------------- private associated function defined here
 
 error[E0624]: associated function `private` is private
   --> $DIR/explore-issue-38412.rs:65:7
    |
 LL |     t.private();
    |       ^^^^^^^ private associated function
+   | 
+  ::: $DIR/auxiliary/pub-and-stability.rs:131:9
+   |
+LL |         fn private(&self) -> i32 { self.0 }
+   |         ------------------------ private associated function defined here
 
 error: aborting due to 19 previous errors
 
diff --git a/src/test/ui/extern/extern-main-issue-86110.rs b/src/test/ui/extern/extern-main-issue-86110.rs
new file mode 100644 (file)
index 0000000..83af7a1
--- /dev/null
@@ -0,0 +1,7 @@
+// missing and missing2 exist to make sure that the error only happens on a `main` declaration
+extern "C" {
+    fn missing();
+    fn main();
+    //~^ the `main` function cannot be declared in an `extern` block
+    fn missing2();
+}
diff --git a/src/test/ui/extern/extern-main-issue-86110.stderr b/src/test/ui/extern/extern-main-issue-86110.stderr
new file mode 100644 (file)
index 0000000..cd3de22
--- /dev/null
@@ -0,0 +1,8 @@
+error: the `main` function cannot be declared in an `extern` block
+  --> $DIR/extern-main-issue-86110.rs:4:5
+   |
+LL |     fn main();
+   |     ^^^^^^^^^^
+
+error: aborting due to previous error
+
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 32b45ee10ad6f1c823a13d272419a20dcde6f077..f69629232aed1123ac691d08159fea475431edd0 100644 (file)
@@ -6,6 +6,8 @@ LL |     type A;
 LL |     type B;
    |     ------- the expected foreign type
 ...
+LL | fn foo(r: &A) -> &B {
+   |                  -- expected `&B` because of return type
 LL |     r
    |     ^ expected extern type `B`, found extern type `A`
    |
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 @@ impl Tr for S {
                                        //~^ 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 @@ impl S {
                                         //~^ 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 38be85ff8201ed77a5840269e0acacd6ef558284..1e48996acb83346f9cd4390423146d6b2601a428 100644 (file)
@@ -57,20 +57,20 @@ fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) }
 
 const _cdef: impl Tr1<As1: Copy> = S1;
 //~^ ERROR associated type bounds are unstable
-//~| ERROR `impl Trait` not allowed outside of function and inherent method return types [E0562]
+//~| ERROR `impl Trait` not allowed outside of function and method return types [E0562]
 // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed.
 // const _cdef_dyn: &dyn Tr1<As1: Copy> = &S1;
 
 static _sdef: impl Tr1<As1: Copy> = S1;
 //~^ ERROR associated type bounds are unstable
-//~| ERROR `impl Trait` not allowed outside of function and inherent method return types [E0562]
+//~| ERROR `impl Trait` not allowed outside of function and method return types [E0562]
 // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed.
 // static _sdef_dyn: &dyn Tr1<As1: Copy> = &S1;
 
 fn main() {
     let _: impl Tr1<As1: Copy> = S1;
     //~^ ERROR associated type bounds are unstable
-    //~| ERROR `impl Trait` not allowed outside of function and inherent method return types [E0562]
+    //~| ERROR `impl Trait` not allowed outside of function and method return types [E0562]
     // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed.
     // let _: &dyn Tr1<As1: Copy> = &S1;
 }
index be5d35139b65c7db978aa46e1301d24f32071d65..2dacb94bcc07a7dad743f01c0b6674f888abec0a 100644 (file)
@@ -115,29 +115,23 @@ LL |     let _: impl Tr1<As1: Copy> = S1;
    = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/feature-gate-associated_type_bounds.rs:58:14
    |
 LL | const _cdef: impl Tr1<As1: Copy> = S1;
    |              ^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/feature-gate-associated_type_bounds.rs:64:15
    |
 LL | static _sdef: impl Tr1<As1: Copy> = S1;
    |               ^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/feature-gate-associated_type_bounds.rs:71:12
    |
 LL |     let _: impl Tr1<As1: Copy> = S1;
    |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
 
 error[E0277]: the trait bound `<<Self as _Tr3>::A as Iterator>::Item: Copy` is not satisfied
   --> $DIR/feature-gate-associated_type_bounds.rs:15:28
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-abi.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-abi.rs
new file mode 100644 (file)
index 0000000..f265149
--- /dev/null
@@ -0,0 +1,11 @@
+#[cfg(target_abi = "x")] //~ ERROR `cfg(target_abi)` is experimental
+#[cfg_attr(target_abi = "x", x)] //~ ERROR `cfg(target_abi)` is experimental
+struct Foo(u64, u64);
+
+#[cfg(not(any(all(target_abi = "x"))))] //~ ERROR `cfg(target_abi)` is experimental
+fn foo() {}
+
+fn main() {
+    cfg!(target_abi = "x");
+    //~^ ERROR `cfg(target_abi)` is experimental and subject to change
+}
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-abi.stderr b/src/test/ui/feature-gates/feature-gate-cfg-target-abi.stderr
new file mode 100644 (file)
index 0000000..ed8cbcb
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0658]: `cfg(target_abi)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-abi.rs:2:12
+   |
+LL | #[cfg_attr(target_abi = "x", x)]
+   |            ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #80970 <https://github.com/rust-lang/rust/issues/80970> for more information
+   = help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable
+
+error[E0658]: `cfg(target_abi)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-abi.rs:1:7
+   |
+LL | #[cfg(target_abi = "x")]
+   |       ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #80970 <https://github.com/rust-lang/rust/issues/80970> for more information
+   = help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable
+
+error[E0658]: `cfg(target_abi)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-abi.rs:5:19
+   |
+LL | #[cfg(not(any(all(target_abi = "x"))))]
+   |                   ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #80970 <https://github.com/rust-lang/rust/issues/80970> for more information
+   = help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable
+
+error[E0658]: `cfg(target_abi)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-abi.rs:9:10
+   |
+LL |     cfg!(target_abi = "x");
+   |          ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #80970 <https://github.com/rust-lang/rust/issues/80970> for more information
+   = help: add `#![feature(cfg_target_abi)]` 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/feature-gates/feature-gate-fn_align.rs b/src/test/ui/feature-gates/feature-gate-fn_align.rs
new file mode 100644 (file)
index 0000000..ea873db
--- /dev/null
@@ -0,0 +1,4 @@
+#![crate_type = "lib"]
+
+#[repr(align(16))] //~ ERROR `repr(align)` attributes on functions are unstable
+fn requires_alignment() {}
diff --git a/src/test/ui/feature-gates/feature-gate-fn_align.stderr b/src/test/ui/feature-gates/feature-gate-fn_align.stderr
new file mode 100644 (file)
index 0000000..5ff124e
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: `repr(align)` attributes on functions are unstable
+  --> $DIR/feature-gate-fn_align.rs:3:8
+   |
+LL | #[repr(align(16))]
+   |        ^^^^^^^^^
+   |
+   = note: see issue #82232 <https://github.com/rust-lang/rust/issues/82232> for more information
+   = help: add `#![feature(fn_align)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.rs b/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.rs
deleted file mode 100644 (file)
index 39cc64f..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-const FOO: impl Copy = 42;
-//~^ ERROR `impl Trait` not allowed
-
-static BAR: impl Copy = 42;
-//~^ ERROR `impl Trait` not allowed
-
-fn main() {
-    let foo = impl Copy = 42;
-//~^ ERROR expected expression, found keyword `impl`
-    let foo: impl Copy = 42;
-}
diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.stderr b/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.stderr
deleted file mode 100644 (file)
index bd648b4..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-error: expected expression, found keyword `impl`
-  --> $DIR/feature-gate-impl_trait_in_bindings.rs:8:15
-   |
-LL |     let foo = impl Copy = 42;
-   |               ^^^^ expected expression
-
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-impl_trait_in_bindings.rs:1:12
-   |
-LL | const FOO: impl Copy = 42;
-   |            ^^^^^^^^^
-   |
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
-
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-impl_trait_in_bindings.rs:4:13
-   |
-LL | static BAR: impl Copy = 42;
-   |             ^^^^^^^^^
-   |
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0562`.
index b82867c67025a398e283e9776b4d5499642bf542..07857289aaeb55a34488bdbd049e110f80153a62 100644 (file)
@@ -106,7 +106,7 @@ LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debu
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
    = help: add `#![feature(min_type_alias_impl_trait)]` to the crate attributes to enable
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/feature-gate-min_type_alias_impl_trait.rs:23:18
    |
 LL |     type Assoc = impl Debug;
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
index 12195bc1071a08144f9eb6851e0eb96a63a8e2d4..c13c05f146a7e676f94dadf53f7ca31eb8b773a9 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `NonObjectSafe1` cannot be made into an object
-  --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:38
+  --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:39
    |
 LL | fn takes_non_object_safe_ref<T>(obj: &dyn NonObjectSafe1) {
-   |                                      ^^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object
+   |                                       ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23
@@ -35,10 +35,10 @@ LL |     fn static_fn() where Self: Sized {}
    |                    ^^^^^^^^^^^^^^^^^
 
 error[E0038]: the trait `NonObjectSafe3` cannot be made into an object
-  --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:35
+  --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:39
    |
 LL | fn takes_non_object_safe_box(obj: Box<dyn NonObjectSafe3>) {
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object
+   |                                       ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object
    |
    = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
index 50ce6427e8b584cd497a51e58f7c5768d1514310..a3ced35155f370a465449d788fe91e75202c83aa 100644 (file)
@@ -51,4 +51,5 @@ LL | #[optimize(banana)]
 
 error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
+Some errors have detailed explanations: E0658, E0722.
+For more information about an error, try `rustc --explain E0658`.
index dfd82a25f4c8757750cca9c99d0214a9669d0b60..4fb1cd2aae1d311c7bd1b9b7d846a0ca153f1db2 100644 (file)
@@ -31,7 +31,7 @@ type Foo4 = impl Debug;
 
 fn define4() {
     let y: Foo4 = 42;
-    //~^ ERROR not permitted here
+    //~^ ERROR mismatched types [E0308]
 }
 
 fn main() {}
index 43fd76ef0ed9fe2e0d6546750d0ab1ffb35ecad1..10409d5fc4badabbe492f53fbf79ef4454fc730a 100644 (file)
@@ -45,14 +45,19 @@ LL |     define3(42)
    = note: expected opaque type `impl Debug`
                      found type `{integer}`
 
-error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:33:12
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:33:19
    |
+LL | type Foo4 = impl Debug;
+   |             ---------- the expected opaque type
+...
 LL |     let y: Foo4 = 42;
-   |            ^^^^
+   |            ----   ^^ expected opaque type, found integer
+   |            |
+   |            expected due to this
    |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+   = note: expected opaque type `impl Debug`
+                     found type `{integer}`
 
 error: could not find defining uses
   --> $DIR/feature-gate-type_alias_impl_trait.rs:5:12
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 5404b8c04bb76e0b40677fe84b1a426919be8cd6..86a352251b2020599743f0cd4fec020c20f4c9e7 100644 (file)
@@ -2,14 +2,14 @@
 // definitions.
 
 #[derive(Debug)]
-//~^ ERROR `derive` may only be applied to structs, enums and unions
+//~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
 mod derive {
     mod inner { #![derive(Debug)] }
-    //~^ ERROR `derive` may only be applied to structs, enums and unions
+    //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
     //~| ERROR inner macro attributes are unstable
 
     #[derive(Debug)]
-    //~^ ERROR `derive` may only be applied to structs, enums and unions
+    //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
     fn derive() { }
 
     #[derive(Copy, Clone)] // (can't derive Debug for unions)
@@ -22,11 +22,11 @@ mod derive {
     enum E { }
 
     #[derive(Debug)]
-    //~^ ERROR `derive` may only be applied to structs, enums and unions
+    //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
     type T = S;
 
     #[derive(Debug)]
-    //~^ ERROR `derive` may only be applied to structs, enums and unions
+    //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
     impl S { }
 }
 
index 9b1f4f46219d2e85f964709d16a1b7685b689b9e..bb8651ffb0955778c0d78a5689ca2e025da17e57 100644 (file)
@@ -1,8 +1,17 @@
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/issue-43106-gating-of-derive.rs:4:1
    |
-LL | #[derive(Debug)]
-   | ^^^^^^^^^^^^^^^^
+LL |   #[derive(Debug)]
+   |   ^^^^^^^^^^^^^^^^ not applicable here
+LL |
+LL | / mod derive {
+LL | |     mod inner { #![derive(Debug)] }
+LL | |
+LL | |
+...  |
+LL | |     impl S { }
+LL | | }
+   | |_- not a `struct`, `enum` or `union`
 
 error[E0658]: inner macro attributes are unstable
   --> $DIR/issue-43106-gating-of-derive.rs:7:20
@@ -13,29 +22,41 @@ LL |     mod inner { #![derive(Debug)] }
    = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information
    = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/issue-43106-gating-of-derive.rs:7:17
    |
 LL |     mod inner { #![derive(Debug)] }
-   |                 ^^^^^^^^^^^^^^^^^
+   |     ------------^^^^^^^^^^^^^^^^^--
+   |     |           |
+   |     |           not applicable here
+   |     not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/issue-43106-gating-of-derive.rs:11:5
    |
 LL |     #[derive(Debug)]
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^ not applicable here
+LL |
+LL |     fn derive() { }
+   |     --------------- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/issue-43106-gating-of-derive.rs:24:5
    |
 LL |     #[derive(Debug)]
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^ not applicable here
+LL |
+LL |     type T = S;
+   |     ----------- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/issue-43106-gating-of-derive.rs:28:5
    |
 LL |     #[derive(Debug)]
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^ not applicable here
+LL |
+LL |     impl S { }
+   |     ---------- not a `struct`, `enum` or `union`
 
 error: aborting due to 6 previous errors
 
index 0b401942c4792661797020c75891bf05be36a239..0c30c9dc50c0d8ecd206482d9ed766bc57108629 100644 (file)
@@ -6,3 +6,4 @@ LL |     #[ffi_pure]
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0757`.
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()))
 }
diff --git a/src/test/ui/fmt/format-concat-span.rs b/src/test/ui/fmt/format-concat-span.rs
new file mode 100644 (file)
index 0000000..ce92df0
--- /dev/null
@@ -0,0 +1,15 @@
+// If the format string is another macro invocation, rustc would previously
+// compute nonsensical spans, such as:
+//
+//   error: invalid format string: unmatched `}` found
+//    --> test.rs:2:17
+//     |
+//   2 |     format!(concat!("abc}"));
+//     |                 ^ unmatched `}` in format string
+//
+// This test checks that this behavior has been fixed.
+
+fn main() {
+    format!(concat!("abc}"));
+    //~^ ERROR: invalid format string: unmatched `}` found
+}
diff --git a/src/test/ui/fmt/format-concat-span.stderr b/src/test/ui/fmt/format-concat-span.stderr
new file mode 100644 (file)
index 0000000..da46f40
--- /dev/null
@@ -0,0 +1,11 @@
+error: invalid format string: unmatched `}` found
+  --> $DIR/format-concat-span.rs:13:13
+   |
+LL |     format!(concat!("abc}"));
+   |             ^^^^^^^^^^^^^^^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+   = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
index 05305e12c04027c1cf240ed5d7edffc8de27c5a1..0a68c24b6067cdfa2b41f6be87f541d2a1657aab 100644 (file)
@@ -5,7 +5,11 @@ LL |     format!("{:X}", "3");
    |                     ^^^ the trait `UpperHex` is not implemented for `str`
    |
    = note: required because of the requirements on the impl of `UpperHex` for `&str`
-   = note: required by `std::fmt::UpperHex::fmt`
+note: required by `std::fmt::UpperHex::fmt`
+  --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+   |
+LL |     fn fmt(&self, f: &mut Formatter<'_>) -> Result;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `$crate::__export::format_args` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/fmt/issue-86085.rs b/src/test/ui/fmt/issue-86085.rs
new file mode 100644 (file)
index 0000000..63d42b7
--- /dev/null
@@ -0,0 +1,6 @@
+// Tests for an ICE with the fuzzed input below.
+
+fn main ( ) {
+format ! ( concat ! ( r#"lJ𐏿Æ�.𐏿�"# , "r} {}" )     ) ;
+//~^ ERROR: invalid format string: unmatched `}` found
+}
diff --git a/src/test/ui/fmt/issue-86085.stderr b/src/test/ui/fmt/issue-86085.stderr
new file mode 100644 (file)
index 0000000..ee7d8a5
--- /dev/null
@@ -0,0 +1,11 @@
+error: invalid format string: unmatched `}` found
+  --> $DIR/issue-86085.rs:4:12
+   |
+LL | format ! ( concat ! ( r#"lJ𐏿Æ�.𐏿�"# , "r} {}" )     ) ;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+   = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
index 7609b1525cc90a286922949b75278d6d75e2aee8..550974bf7788157aa72a0a3d3197e43c4ef100bd 100644 (file)
@@ -8,7 +8,7 @@ fn returns_i32() -> i32 {
 }
 
 fn returns_fn_ptr() -> _ {
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures [E0121]
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types [E0121]
 //~| NOTE not allowed in type signatures
 //~| HELP replace with the correct return type
 //~| SUGGESTION fn() -> i32
@@ -16,7 +16,7 @@ fn returns_fn_ptr() -> _ {
 }
 
 fn returns_closure() -> _ {
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures [E0121]
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types [E0121]
 //~| NOTE not allowed in type signatures
 //~| HELP consider using an `Fn`, `FnMut`, or `FnOnce` trait bound
 //~| NOTE for more information on `Fn` traits and closure types, see
index 63571e71b34f49415cbbe450c1123f219ef51658..96d0f02b01af4478c4c88ac656f0b7aefb2cee65 100644 (file)
@@ -1,4 +1,4 @@
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/issue-80179.rs:10:24
    |
 LL | fn returns_fn_ptr() -> _ {
@@ -7,7 +7,7 @@ LL | fn returns_fn_ptr() -> _ {
    |                        not allowed in type signatures
    |                        help: replace with the correct return type: `fn() -> i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/issue-80179.rs:18:25
    |
 LL | fn returns_closure() -> _ {
index 18e46e1d7ded73b0320982a3b6ef3e36def7e344..7eac8c9c5a8df12fabbb531da3fe5942dfc9494e 100644 (file)
@@ -6,7 +6,11 @@ LL |     for c in "asdf" {
    |
    = help: the trait `Iterator` is not implemented for `&str`
    = note: required because of the requirements on the impl of `IntoIterator` for `&str`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 0d9409626897fb35ba12899221f743195f9e6529..288243325c48c412064798a85a89becb012a869c 100644 (file)
@@ -6,7 +6,11 @@ LL |     for x in bogus {
    |
    = help: the trait `Iterator` is not implemented for `MyStruct`
    = note: required because of the requirements on the impl of `IntoIterator` for `MyStruct`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/fsu-moves-and-copies.rs b/src/test/ui/fsu-moves-and-copies.rs
deleted file mode 100644 (file)
index 6a0b4ed..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-// run-pass
-
-#![allow(non_camel_case_types)]
-#![allow(stable_features)]
-// Issue 4691: Ensure that functional-struct-updates operates
-// correctly and moves rather than copy when appropriate.
-
-#![feature(box_syntax, core)]
-
-struct ncint { v: isize }
-fn ncint(v: isize) -> ncint { ncint { v: v } }
-
-struct NoFoo { copied: isize, nocopy: ncint, }
-impl NoFoo {
-    fn new(x:isize,y:isize) -> NoFoo { NoFoo { copied: x, nocopy: ncint(y) } }
-}
-
-struct MoveFoo { copied: isize, moved: Box<isize>, }
-impl MoveFoo {
-    fn new(x:isize,y:isize) -> MoveFoo { MoveFoo { copied: x, moved: box y } }
-}
-
-struct DropNoFoo { inner: NoFoo }
-impl DropNoFoo {
-    fn new(x:isize,y:isize) -> DropNoFoo { DropNoFoo { inner: NoFoo::new(x,y) } }
-}
-impl Drop for DropNoFoo { fn drop(&mut self) { } }
-
-struct DropMoveFoo { inner: MoveFoo }
-impl DropMoveFoo {
-    fn new(x:isize,y:isize) -> DropMoveFoo { DropMoveFoo { inner: MoveFoo::new(x,y) } }
-}
-impl Drop for DropMoveFoo { fn drop(&mut self) { } }
-
-
-fn test0() {
-    // just copy implicitly copyable fields from `f`, no moves
-    // (and thus it is okay that these are Drop; compare against
-    // test ui/borrowck/borrowck-struct-update-with-dtor.rs).
-
-    // Case 1: Nocopyable
-    let f = DropNoFoo::new(1, 2);
-    let b = DropNoFoo { inner: NoFoo { nocopy: ncint(3), ..f.inner }};
-    let c = DropNoFoo { inner: NoFoo { nocopy: ncint(4), ..f.inner }};
-    assert_eq!(f.inner.copied,    1);
-    assert_eq!(f.inner.nocopy.v, 2);
-
-    assert_eq!(b.inner.copied,    1);
-    assert_eq!(b.inner.nocopy.v, 3);
-
-    assert_eq!(c.inner.copied,    1);
-    assert_eq!(c.inner.nocopy.v, 4);
-
-    // Case 2: Owned
-    let f = DropMoveFoo::new(5, 6);
-    let b = DropMoveFoo { inner: MoveFoo { moved: box 7, ..f.inner }};
-    let c = DropMoveFoo { inner: MoveFoo { moved: box 8, ..f.inner }};
-    assert_eq!(f.inner.copied,    5);
-    assert_eq!(*f.inner.moved,    6);
-
-    assert_eq!(b.inner.copied,    5);
-    assert_eq!(*b.inner.moved,    7);
-
-    assert_eq!(c.inner.copied,    5);
-    assert_eq!(*c.inner.moved,    8);
-}
-
-fn test1() {
-    // copying move-by-default fields from `f`, so it moves:
-    let f = MoveFoo::new(11, 12);
-
-    let b = MoveFoo {moved: box 13, ..f};
-    let c = MoveFoo {copied: 14, ..f};
-    assert_eq!(b.copied,    11);
-    assert_eq!(*b.moved,    13);
-    assert_eq!(c.copied,    14);
-    assert_eq!(*c.moved,    12);
-}
-
-fn test2() {
-    // move non-copyable field
-    let f = NoFoo::new(21, 22);
-    let b = NoFoo {nocopy: ncint(23), ..f};
-    let c = NoFoo {copied: 24, ..f};
-    assert_eq!(b.copied,    21);
-    assert_eq!(b.nocopy.v, 23);
-    assert_eq!(c.copied,    24);
-    assert_eq!(c.nocopy.v, 22);
-}
-
-pub fn main() {
-    test0();
-    test1();
-    test2();
-}
diff --git a/src/test/ui/function-pointer/function-pointer-comparison-issue-54685.rs b/src/test/ui/function-pointer/function-pointer-comparison-issue-54685.rs
new file mode 100644 (file)
index 0000000..a036d10
--- /dev/null
@@ -0,0 +1,31 @@
+// min-llvm-version: 12.0
+// compile-flags: -C opt-level=3
+// run-pass
+
+fn foo(_i: i32) -> i32 {
+    1
+}
+fn bar(_i: i32) -> i32 {
+    1
+}
+
+fn main() {
+    let x: fn(i32) -> i32 = foo;
+    let y: fn(i32) -> i32 = bar;
+
+    let s1;
+    if x == y {
+        s1 = "same".to_string();
+    } else {
+        s1 = format!("{:?}, {:?}", x, y);
+    }
+
+    let s2;
+    if x == y {
+        s2 = "same".to_string();
+    } else {
+        s2 = format!("{:?}, {:?}", x, y);
+    }
+
+    assert_eq!(s1, s2);
+}
index 3630f08c937781feeb368012d2c43facb8ede170..bbd0e33d7193e9081fd0df6b99515a86f47b6e22 100644 (file)
@@ -1,8 +1,18 @@
+// Ensure that the future_incompatible lint group only includes
+// lints for changes that are not tied to an edition
 #![deny(future_incompatible)]
 
 trait Tr {
-    fn f(u8) {} //~ ERROR anonymous parameters are deprecated
-                //~^ WARN this was previously accepted
+    // Warn only since this is not a `future_incompatible` lint
+    fn f(u8) {} //~ WARN anonymous parameters are deprecated
+                //~| WARN this is accepted in the current edition
+}
+
+pub mod submodule {
+    // Error since this is a `future_incompatible` lint
+    #![doc(test(some_test))]
+        //~^ ERROR this attribute can only be applied at the crate level
+        //~| WARN this was previously accepted by the compiler
 }
 
 fn main() {}
index a19051e8bc0b281a6306e85aca2d345e94312399..cb9be88c9ee44f43a14e63f267f545fbf9588f95 100644 (file)
@@ -1,17 +1,28 @@
-error: anonymous parameters are deprecated and will be removed in the next edition.
-  --> $DIR/future-incompatible-lint-group.rs:4:10
+warning: anonymous parameters are deprecated and will be removed in the next edition.
+  --> $DIR/future-incompatible-lint-group.rs:7:10
    |
 LL |     fn f(u8) {}
    |          ^^ help: try naming the parameter or explicitly ignoring it: `_: u8`
    |
+   = note: `#[warn(anonymous_parameters)]` on by default
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+
+error: this attribute can only be applied at the crate level
+  --> $DIR/future-incompatible-lint-group.rs:13:12
+   |
+LL |     #![doc(test(some_test))]
+   |            ^^^^^^^^^^^^^^^
+   |
 note: the lint level is defined here
-  --> $DIR/future-incompatible-lint-group.rs:1:9
+  --> $DIR/future-incompatible-lint-group.rs:3:9
    |
 LL | #![deny(future_incompatible)]
    |         ^^^^^^^^^^^^^^^^^^^
-   = note: `#[deny(anonymous_parameters)]` implied by `#[deny(future_incompatible)]`
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
-   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+   = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(future_incompatible)]`
+   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level for more information
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
index 96a8d6d70e016affe934bbb195154e68a53d77ef..46d27baa5453b3ebc4fdc4c2066976c2552a3153 100644 (file)
@@ -29,11 +29,11 @@ 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 `[generator@$DIR/issue-68112.rs:38:5: 41:6 {()}]`
+   = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:38:5: 41:6]`
    = note: required because it appears within the type `impl Generator`
    = note: required because it appears within the type `impl Generator`
    = note: required because it appears within the type `{impl Generator, ()}`
-   = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:48:20: 51:6 {impl Generator, ()}]`
+   = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:48:20: 51:6]`
 
 error: aborting due to 2 previous errors
 
index 805a4d1d000cd86f22ff693518825d10de7924ca..bf647d089833a69dd7da2e15ca3beda47261afc3 100644 (file)
@@ -1,26 +1,18 @@
 error[E0425]: cannot find value `Foo` in this scope
-  --> $DIR/layout-error.rs:25:17
+  --> $DIR/layout-error.rs:24:17
    |
 LL |         let a = Foo;
    |                 ^^^ not found in this scope
 
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
+warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/layout-error.rs:8:32
    |
-LL | #![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))]
-   |                                ^^^^^^^^^^^^^^^^^^^^^^
+LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
+   |                                ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/layout-error.rs:8:56
-   |
-LL | #![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))]
-   |                                                        ^^^^^^^^^^^^^^^^^^^^^
-   |
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0425`.
index be469d781b5c62f388fdd3730fa353aede322919..ed31c260cbc0f95a04698f6eff880c3935206994 100644 (file)
@@ -1,11 +1,11 @@
 error[E0425]: cannot find value `Foo` in this scope
-  --> $DIR/layout-error.rs:25:17
+  --> $DIR/layout-error.rs:24:17
    |
 LL |         let a = Foo;
    |                 ^^^ not found in this scope
 
 error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/layout-error.rs:31:27
+  --> $DIR/layout-error.rs:30:27
    |
 LL |     Task::spawn(&POOL, || cb());
    |                           ^
@@ -13,28 +13,7 @@ LL |     Task::spawn(&POOL, || cb());
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
-error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/layout-error.rs:30:28
-   |
-LL |     static POOL: Task<F> = Task::new();
-   |                            ^^^^^^^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
-
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/layout-error.rs:31:24
-   |
-LL |     Task::spawn(&POOL, || cb());
-   |                        ^^^^^^^ expected `[type error]`, got `impl Future`
-   |
-note: previous use here
-  --> $DIR/layout-error.rs:30:5
-   |
-LL |     static POOL: Task<F> = Task::new();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0425, E0658.
 For more information about an error, try `rustc --explain E0425`.
index 9f15a6b2eca0011c50aeddc850abef9c090271e8..a5efc3899dd4d8538ab889764e1890ef1a1241c3 100644 (file)
@@ -5,9 +5,8 @@
 
 // revisions: min_tait full_tait
 #![feature(min_type_alias_impl_trait)]
-#![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))]
+#![cfg_attr(full_tait, feature(type_alias_impl_trait))]
 //[full_tait]~^ WARN incomplete
-//[full_tait]~| WARN incomplete
 use std::future::Future;
 
 pub struct Task<F: Future>(F);
@@ -27,7 +26,6 @@ fn main() {
 
     type F = impl Future;
     // Check that statics are inhabited computes they layout.
-    static POOL: Task<F> = Task::new(); //[min_tait]~ ERROR not permitted here
+    static POOL: Task<F> = Task::new();
     Task::spawn(&POOL, || cb()); //[min_tait]~ ERROR type alias impl trait is not permitted here
-    //[min_tait]~^ ERROR concrete type differs from previous
 }
index ce874c1518c0e15e42f7e7d91b1edfced3099212..1e609e8388277042708681aac897eecfa3fd5cd1 100644 (file)
@@ -1,25 +1,17 @@
 warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/metadata-sufficient-for-layout.rs:10:32
    |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
+LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    |                                ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/metadata-sufficient-for-layout.rs:10:55
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
-   |                                                       ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/metadata-sufficient-for-layout.rs:29:1
+  --> $DIR/metadata-sufficient-for-layout.rs:28:1
    |
 LL | fn main() {}
    | ^^^^^^^^^
 
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to previous error; 1 warning emitted
 
index e2b0d3622a6000231df82f07412ff28de922ea60..52d42fd59a003a1fa8c807241cdc131ce705a043 100644 (file)
@@ -1,24 +1,8 @@
-error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/metadata-sufficient-for-layout.rs:22:23
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/metadata-sufficient-for-layout.rs:28:1
    |
-LL | static A: Option<F> = None;
-   |                       ^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
-
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/metadata-sufficient-for-layout.rs:25:1
-   |
-LL | fn f() -> F { metadata_sufficient_for_layout::g() }
-   | ^^^^^^^^^^^ expected `[type error]`, got `impl Generator`
-   |
-note: previous use here
-  --> $DIR/metadata-sufficient-for-layout.rs:22:1
-   |
-LL | static A: Option<F> = None;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn main() {}
+   | ^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
index f206093d9710c23e5ea984ff938b8dfb50690358..c01354569f07d408a6aca5cb0fd9024b2df33475 100644 (file)
@@ -7,9 +7,8 @@
 
 // revisions: min_tait full_tait
 #![feature(min_type_alias_impl_trait, rustc_attrs)]
-#![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
+#![cfg_attr(full_tait, feature(type_alias_impl_trait))]
 //[full_tait]~^ WARN incomplete
-//[full_tait]~| WARN incomplete
 #![feature(generator_trait)]
 
 extern crate metadata_sufficient_for_layout;
@@ -20,10 +19,10 @@ type F = impl Generator<(), Yield = (), Return = ()>;
 
 // Static queries the layout of the generator.
 static A: Option<F> = None;
-//[min_tait]~^ ERROR not permitted here
 
-fn f() -> F { metadata_sufficient_for_layout::g() }
-//[min_tait]~^ ERROR concrete type differs
+fn f() -> F {
+    metadata_sufficient_for_layout::g()
+}
 
 #[rustc_error]
-fn main() {} //[full_tait]~ ERROR
+fn main() {} //~ ERROR
index 2384ed3d24972ad458192c03f22e80552aab79d6..448cb2a043a059092d899805b03b5f5ccdf6ebe0 100644 (file)
@@ -9,7 +9,7 @@ LL |     assert_send(|| {
    |
    = help: the trait `Sync` is not implemented for `Cell<i32>`
    = note: required because of the requirements on the impl of `Send` for `&Cell<i32>`
-   = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 _]`
+   = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6]`
 
 error: generator cannot be shared between threads safely
   --> $DIR/not-send-sync.rs:9:5
@@ -20,7 +20,7 @@ LL |     fn assert_sync<T: Sync>(_: T) {}
 LL |     assert_sync(|| {
    |     ^^^^^^^^^^^ generator is not `Sync`
    |
-   = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {Cell<i32>, ()}]`, the trait `Sync` is not implemented for `Cell<i32>`
+   = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6]`, the trait `Sync` is not implemented for `Cell<i32>`
 note: generator is not `Sync` as this value is used across a yield
   --> $DIR/not-send-sync.rs:12:9
    |
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 7f118c88e5e6e5a8197c0e118734a837b51b2f0f..e0b856db7a55d9f9d8334642aa437f14335fdb65 100644 (file)
@@ -15,7 +15,7 @@ fn main() {
                 yield ();
                 4i32
             };
-            &a;
+            let _ = &a;
         };
     }
 }
index 88dacff7b559be1706de68efb5933b48b2b02c35..72a2bd4ebc55c3a7501ebd345688e6dc303a7e39 100644 (file)
@@ -6,7 +6,7 @@ LL | |             // Tests that the generator transformation finds out that `a`
 LL | |             // during the yield expression. Type checking will also compute liveness
 LL | |             // and it should also find out that `a` is not live.
 ...  |
-LL | |             &a;
+LL | |             let _ = &a;
 LL | |         };
    | |__________^
    |
index 2f8754c95715f15ab6d04b835d14e7acfdd4ff4c..0cab36e5f2880017d77000ff050150b078165961 100644 (file)
@@ -11,7 +11,7 @@ fn main() {
                 yield;
                 true
             };
-            &opt;
+            let _ = &opt;
         }
     };
 }
index f0c7cb0e5d50c305fdad3f45b1620368f2f1a082..dff743bc35b2dafd67d0decd1966f9ec7d8d84b1 100644 (file)
@@ -13,7 +13,11 @@ LL |     yield || for i in 0 { }
    = help: the trait `Iterator` is not implemented for `{integer}`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `{integer}`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 5fbae02573c62a31a95e8e9c16cfd633bf6e74e7..0944bf110c1b5211a74d70797d57535e1be0a576 100644 (file)
@@ -1,9 +1,8 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 #![feature(associated_type_defaults)]
 
 // A Collection trait and collection families. Based on
-// http://smallcultfollowing.com/babysteps/blog/2016/11/03/
+// https://smallcultfollowing.com/babysteps/blog/2016/11/03/
 // associated-type-constructors-part-2-family-traits/
 
 // check that we don't normalize with trait defaults.
index ca02b2603ba64703160e84ad0e93e0fcf13d2308..22fbc0271b481af2fc85d8c7a03a77c6dccdd1b9 100644 (file)
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/collections-project-default.rs:60:5
+  --> $DIR/collections-project-default.rs:59:5
    |
 LL | fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
    |                                     ------------------------------------ expected `<C as Collection<i32>>::Sibling<f32>` because of return type
index 1b5b9c181fb612ea83926eee74f460b1d9f4a7ea..f14c6dac1b1ed9d28436adfc09c4dd511baf5f68 100644 (file)
@@ -1,9 +1,8 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 #![feature(associated_type_defaults)]
 
 // A Collection trait and collection families. Based on
-// http://smallcultfollowing.com/babysteps/blog/2016/11/03/
+// https://smallcultfollowing.com/babysteps/blog/2016/11/03/
 // associated-type-constructors-part-2-family-traits/
 
 // run-pass
index ab33ef6f2442c4c0a9777c7967054e8677ef7e35..afde5f37634b1d1722c34b7db6ad4d64a8c3ba0a 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 #![feature(generic_associated_types)]
-#![allow(incomplete_features)]
 
 // This test unsures that with_opt_const_param returns the
 // def_id of the N param in the Foo::Assoc GAT.
index ba9a82ae721092a9a9c94ed6a3bfc8af3e534bd1..51046be79b7e5af1719378354c95656e105df107 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 #![feature(generic_associated_types)]
-#![allow(incomplete_features)]
 
 // This test unsures that with_opt_const_param returns the
 // def_id of the N param in the Foo::Assoc GAT.
index 9da5334056a37e9844abbde110073fc47a82874e..457fe27b3ff3aacbbc1009409cee4e8bc9dfd1d1 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 #![feature(generic_associated_types)]
-#![allow(incomplete_features)]
 
 // This test unsures that with_opt_const_param returns the
 // def_id of the N param in the Bar::Assoc GAT.
index 36db3d1bb9e4793da39e538383a55ea570befdc4..e315ee842180ed30c03acdd34e728d1c26fefeb0 100644 (file)
@@ -1,7 +1,6 @@
 // Test that correct syntax is used in suggestion to constrain associated type
 
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete
 
 trait X {
     type Y<T>;
index ecf559d9e94a1867d2b6a993e049deb76a24c860..ad02202dfc90c0e22a153f20ac703000a0e9bc3c 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/constraint-assoc-type-suggestion.rs:3:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0308]: mismatched types
-  --> $DIR/constraint-assoc-type-suggestion.rs:13:23
+  --> $DIR/constraint-assoc-type-suggestion.rs:12:23
    |
 LL |     let b: Vec<i32> = a;
    |            --------   ^ expected struct `Vec`, found associated type
@@ -22,6 +13,6 @@ help: consider constraining the associated type `<T as X>::Y<i32>` to `Vec<i32>`
 LL | fn f<T: X<Y<i32> = Vec<i32>>>(a: T::Y<i32>) {
    |          ^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0308`.
index ff9d61658f4eb2a1da4aad9ebad725cb0ce66881..9ae328cc48b1d988d8a9fecd3632987ab2d8a219 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 // check-pass
index 6eb25a92f34133587558e8196be83835d03d9a88..772b7f2b4e3012e8cbc100161abd5fd563ab6045 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 trait Foo {
index 1599d683ad6dd7dc078b9e9b01d0c80a446cd9c8..ac22bfc0835b946e769f5ef7ab86e4719440373f 100644 (file)
@@ -1,5 +1,5 @@
 error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
-  --> $DIR/empty_generics.rs:5:14
+  --> $DIR/empty_generics.rs:4:14
    |
 LL | trait Foo {
    |           - while parsing this item list starting here
index 2c543455b6ebdf437e1ee99545308a71a5ecf339..f542a7f545e0be907c10bfdc678eaa89d5a0cc52 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-  //~^ WARNING: the feature `generic_associated_types` is incomplete
 
 trait X {
   type Y<'x>;
index 1c7c107d78354d60c1f22872d04eed0830c8509e..ce9df46483d136079ec4b81383b739f89b979297 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0261]: use of undeclared lifetime name `'x`
-  --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:9:35
+  --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:8:35
    |
 LL |   fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
    |        -                          ^^ undeclared lifetime
@@ -18,12 +9,12 @@ LL |   fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
    = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
 
 error[E0582]: binding for associated type `Y` references lifetime `'a`, which does not appear in the trait input types
-  --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:9:33
+  --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:8:33
    |
 LL |   fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
    |                                 ^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0261, E0582.
 For more information about an error, try `rustc --explain E0261`.
index 6527eb4750455f79dcf08c30b6fa378e78a632fa..fb03a86e169715df91c5d4bcaae07a096c4f359b 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-  //~^ WARNING: the feature `generic_associated_types` is incomplete
 #![feature(associated_type_defaults)]
 
 trait Foo {
index 49dfce8b4bd380199930e3caf9bf6ad1b8e7bf65..8651789688eaa75d4f850b00e1a19382a6f23eb3 100644 (file)
@@ -1,27 +1,18 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/gat-in-trait-path.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/gat-in-trait-path.rs:22:13
+  --> $DIR/gat-in-trait-path.rs:21:17
    |
 LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
    |
    = help: consider moving `A` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/gat-in-trait-path.rs:6:10
+  --> $DIR/gat-in-trait-path.rs:5:10
    |
 LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     type A<'a> where Self: 'a;
    |          ^ ...because it contains the generic associated type `A`
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0038`.
index 33593884de31f724e72884fc3bd99498c5f58ab1..607ea1759888c6e857e4c3aa0dc69ef0bb95ac63 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete
 
 fn main() {}
diff --git a/src/test/ui/generic-associated-types/gat-incomplete-warning.stderr b/src/test/ui/generic-associated-types/gat-incomplete-warning.stderr
deleted file mode 100644 (file)
index 0215ff3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/gat-incomplete-warning.rs:3:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
-warning: 1 warning emitted
-
index cff5a21052f9bc98eeca3f4551e83d5da10f88de..246659a268ac933d07359093c05b0acfdbdb4a4a 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-  //~^ WARNING: the feature `generic_associated_types` is incomplete
 
 trait Foo {
     type F<'a>;
index e83af1d0c739d1535dc930f44523fc60ebd11e15..310f722e120fdf8ef49045ffbaa82f3f64fff6f9 100644 (file)
@@ -1,22 +1,13 @@
 error[E0403]: the name `T1` is already used for a generic parameter in this item's generic parameters
-  --> $DIR/gat-trait-path-generic-type-arg.rs:11:12
+  --> $DIR/gat-trait-path-generic-type-arg.rs:10:12
    |
 LL | impl <T, T1> Foo for T {
    |          -- first use of `T1`
 LL |     type F<T1> = &[u8];
    |            ^^ already used
 
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/gat-trait-path-generic-type-arg.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0106]: missing lifetime specifier
-  --> $DIR/gat-trait-path-generic-type-arg.rs:11:18
+  --> $DIR/gat-trait-path-generic-type-arg.rs:10:18
    |
 LL |     type F<T1> = &[u8];
    |                  ^ expected named lifetime parameter
@@ -26,7 +17,7 @@ help: consider introducing a named lifetime parameter
 LL |     type F<'a, T1> = &'a [u8];
    |            ^^^       ^^^
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0106, E0403.
 For more information about an error, try `rustc --explain E0106`.
index 484790501b98e54ede42afa1975ef6dbff5beadc..9864787f0aa2f40287dffab453bd22045546dd94 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-  //~^ WARNING: the feature `generic_associated_types` is incomplete
 
 trait X {
   type Y<'a>;
index 56b5551cd3fde9d93a403103a4ececb4a57373c2..9b63e8f30726b0381b16ffe44881321587ae9255 100644 (file)
@@ -1,20 +1,11 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/gat-trait-path-missing-lifetime.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0107]: missing generics for associated type `X::Y`
-  --> $DIR/gat-trait-path-missing-lifetime.rs:11:20
+  --> $DIR/gat-trait-path-missing-lifetime.rs:10:20
    |
 LL |   fn foo<'a, T1: X<Y = T1>>(t : T1) -> T1::Y<'a> {
    |                    ^ expected 1 lifetime argument
    |
 note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/gat-trait-path-missing-lifetime.rs:5:8
+  --> $DIR/gat-trait-path-missing-lifetime.rs:4:8
    |
 LL |   type Y<'a>;
    |        ^ --
@@ -24,13 +15,13 @@ LL |   fn foo<'a, T1: X<Y<'a> = T1>>(t : T1) -> T1::Y<'a> {
    |                    ^^^^^
 
 error[E0107]: missing generics for associated type `X::Y`
-  --> $DIR/gat-trait-path-missing-lifetime.rs:11:20
+  --> $DIR/gat-trait-path-missing-lifetime.rs:10:20
    |
 LL |   fn foo<'a, T1: X<Y = T1>>(t : T1) -> T1::Y<'a> {
    |                    ^ expected 1 lifetime argument
    |
 note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/gat-trait-path-missing-lifetime.rs:5:8
+  --> $DIR/gat-trait-path-missing-lifetime.rs:4:8
    |
 LL |   type Y<'a>;
    |        ^ --
@@ -39,6 +30,6 @@ help: add missing lifetime argument
 LL |   fn foo<'a, T1: X<Y<'a> = T1>>(t : T1) -> T1::Y<'a> {
    |                    ^^^^^
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0107`.
index f1af6860284cb5a0ad8988fdcf1898f06e5b00a8..48b4a4fc393777ecb289ecfc5e8468dec949af9f 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-  //~^ WARNING: the feature `generic_associated_types` is incomplete
 
 trait X {
   type Y<'a>;
@@ -11,6 +10,6 @@ fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
   //~| ERROR this associated type takes 0 generic arguments but 1 generic argument
   //~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments
   //~| WARNING: trait objects without an explicit `dyn` are deprecated
-  //~| WARNING: this was previously accepted by the compiler
+  //~| WARNING: this is accepted in the current edition
 
 fn main() {}
index 400600a086c0c0031f9a81ff6454b5dbb1da31ff..d6fba8b8e4c8ac4ec4038b0ad94c942a5197e8f9 100644 (file)
@@ -1,42 +1,33 @@
 error: lifetime in trait object type must be followed by `+`
-  --> $DIR/gat-trait-path-parenthesised-args.rs:8:29
+  --> $DIR/gat-trait-path-parenthesised-args.rs:7:29
    |
 LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
    |                             ^^
 
 error: parenthesized generic arguments cannot be used in associated type constraints
-  --> $DIR/gat-trait-path-parenthesised-args.rs:8:27
+  --> $DIR/gat-trait-path-parenthesised-args.rs:7:27
    |
 LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
    |                           ^^^^^
 
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/gat-trait-path-parenthesised-args.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/gat-trait-path-parenthesised-args.rs:8:29
+  --> $DIR/gat-trait-path-parenthesised-args.rs:7:29
    |
 LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
    |                             ^^ help: use `dyn`: `dyn 'a`
    |
    = note: `#[warn(bare_trait_objects)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
-  --> $DIR/gat-trait-path-parenthesised-args.rs:8:27
+  --> $DIR/gat-trait-path-parenthesised-args.rs:7:27
    |
 LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
    |                           ^ expected 1 lifetime argument
    |
 note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/gat-trait-path-parenthesised-args.rs:5:8
+  --> $DIR/gat-trait-path-parenthesised-args.rs:4:8
    |
 LL |   type Y<'a>;
    |        ^ --
@@ -46,7 +37,7 @@ LL | fn foo<'a>(arg: Box<dyn X<Y('a, 'a) = &'a ()>>) {}
    |                             ^^^
 
 error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied
-  --> $DIR/gat-trait-path-parenthesised-args.rs:8:27
+  --> $DIR/gat-trait-path-parenthesised-args.rs:7:27
    |
 LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
    |                           ^---- help: remove these generics
@@ -54,11 +45,11 @@ LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
    |                           expected 0 generic arguments
    |
 note: associated type defined here, with 0 generic parameters
-  --> $DIR/gat-trait-path-parenthesised-args.rs:5:8
+  --> $DIR/gat-trait-path-parenthesised-args.rs:4:8
    |
 LL |   type Y<'a>;
    |        ^
 
-error: aborting due to 4 previous errors; 2 warnings emitted
+error: aborting due to 4 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0107`.
index 8094450e5e137dfb9c93bd1b9df2f449d95cfe54..5d3a3a893527eec22a81d8e34129fc277116698e 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 pub trait X {
index 27970b15a411d6d94df825d1547de7b7691f6a46..592ff9399232371489bbb3bb3aede873efcd2d4c 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 // Checking the interaction with this other feature
index da8b625ea7f751ea01ed1ac1f474a1f353256673..d65265438220999d516e0ac415053af58757e93e 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: `T` doesn't implement `std::fmt::Display`
-  --> $DIR/generic-associated-types-where.rs:21:5
+  --> $DIR/generic-associated-types-where.rs:20:5
    |
 LL |     type Assoc2<T> = Vec<T>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
@@ -11,7 +11,7 @@ LL |     type Assoc2<T: std::fmt::Display> = Vec<T>;
    |                  ^^^^^^^^^^^^^^^^^^^
 
 error[E0276]: impl has stricter requirements than trait
-  --> $DIR/generic-associated-types-where.rs:23:5
+  --> $DIR/generic-associated-types-where.rs:22:5
    |
 LL |     type Assoc3<T>;
    |     --------------- definition of `Assoc3` from trait
index 4b4e59a512462791c0e639b7c87794e16c6bb5c9..43058f7eb41bfb7930edf1549227083722fb78d7 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 use std::ops::Deref;
index f164c0d07a3c45c4f624d84dec5a21c817d94747..e87176e0fb27ba5c31b51506f8c70c0b20d5f2eb 100644 (file)
@@ -1,5 +1,5 @@
 error[E0261]: use of undeclared lifetime name `'b`
-  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:9:37
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:8:37
    |
 LL |         + Deref<Target = Self::Item<'b>>;
    |                                     ^^ undeclared lifetime
@@ -15,7 +15,7 @@ LL |     type Iter<'b, 'a>: Iterator<Item = Self::Item<'a>>
    |               ^^^
 
 error[E0261]: use of undeclared lifetime name `'undeclared`
-  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:12:41
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:11:41
    |
 LL |     fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
    |                                         ^^^^^^^^^^^ undeclared lifetime
index 50e1c50644e356cb3ee3ce33c2cf04fd13123310..01edad00a89f15408d93c5ae018360b569fb16b8 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 #![feature(associated_type_defaults)]
 
index 58bcb13e68ebdfb1eb0394c45714a4a57ba43f42..585ba16a491b7b5b6e38413293c224e70f627fb3 100644 (file)
@@ -1,5 +1,5 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/impl_bounds.rs:16:5
+  --> $DIR/impl_bounds.rs:15:5
    |
 LL |     type A<'a> where Self: 'static = (&'a ());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,74 +8,84 @@ LL |     type A<'a> where Self: 'static = (&'a ());
    = note: ...so that the type `Fooy<T>` will meet its required lifetime bounds
 
 error[E0478]: lifetime bound not satisfied
-  --> $DIR/impl_bounds.rs:18:5
+  --> $DIR/impl_bounds.rs:17:5
    |
 LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 18:16
-  --> $DIR/impl_bounds.rs:18:16
+note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 17:16
+  --> $DIR/impl_bounds.rs:17:16
    |
 LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
    |                ^^
-note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 18:12
-  --> $DIR/impl_bounds.rs:18:12
+note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 17:12
+  --> $DIR/impl_bounds.rs:17:12
    |
 LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
    |            ^^
 
 error[E0478]: lifetime bound not satisfied
-  --> $DIR/impl_bounds.rs:18:5
+  --> $DIR/impl_bounds.rs:17:5
    |
 LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 18:12
-  --> $DIR/impl_bounds.rs:18:12
+note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 17:12
+  --> $DIR/impl_bounds.rs:17:12
    |
 LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
    |            ^^
-note: but lifetime parameter must outlive the lifetime `'b` as defined on the associated item at 18:16
-  --> $DIR/impl_bounds.rs:18:16
+note: but lifetime parameter must outlive the lifetime `'b` as defined on the associated item at 17:16
+  --> $DIR/impl_bounds.rs:17:16
    |
 LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
    |                ^^
 
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/impl_bounds.rs:21:5
+  --> $DIR/impl_bounds.rs:20:5
    |
 LL |     type C where Self: Copy = String;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
-   = note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
+note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
+  --> $DIR/impl_bounds.rs:11:10
+   |
+LL | #[derive(Copy, Clone)]
+   |          ^^^^
 note: the requirement `Fooy<T>: Copy` appears on the associated impl type `C` but not on the corresponding associated trait type
-  --> $DIR/impl_bounds.rs:8:5
+  --> $DIR/impl_bounds.rs:7:5
    |
 LL | trait Foo {
    |       --- in this trait
 ...
 LL |     type C where Self: Clone;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ this trait associated type doesn't have the requirement `Fooy<T>: Copy`
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
    |
 LL | impl<T: std::marker::Copy> Foo for Fooy<T> {
    |       ^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/impl_bounds.rs:23:5
+  --> $DIR/impl_bounds.rs:22:5
    |
 LL |     fn d() where Self: Copy {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
-   = note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
+note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
+  --> $DIR/impl_bounds.rs:11:10
+   |
+LL | #[derive(Copy, Clone)]
+   |          ^^^^
 note: the requirement `Fooy<T>: Copy` appears on the impl method `d` but not on the corresponding trait method
-  --> $DIR/impl_bounds.rs:9:8
+  --> $DIR/impl_bounds.rs:8:8
    |
 LL | trait Foo {
    |       --- in this trait
 ...
 LL |     fn d() where Self: Clone;
    |        ^ this trait method doesn't have the requirement `Fooy<T>: Copy`
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
    |
 LL | impl<T: std::marker::Copy> Foo for Fooy<T> {
index 98aa82aba83055a33a1f244a9365b454fe69c3ce..08120b9670f67da1a295391463d3aae2ce27d0c0 100644 (file)
@@ -1,6 +1,5 @@
 // check-pass
 
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 #![feature(associated_type_defaults)]
 
index de2b978460f7f19020cc78d6e99384733d0dd405..da5fca2a6569f942a833beb392ba72176dd54d53 100644 (file)
@@ -1,6 +1,5 @@
 // Check that this program doesn't cause the compiler to error without output.
 
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 trait Foo {
index 439b8ab90c9d8b8894d6d05caf6ca09ca7d7478a..56677457726f7868229e2cf090a1c9ef4db3f690 100644 (file)
@@ -1,5 +1,5 @@
 error[E0276]: impl has stricter requirements than trait
-  --> $DIR/issue-47206-where-clause.rs:13:5
+  --> $DIR/issue-47206-where-clause.rs:12:5
    |
 LL |     type Assoc3<T>;
    |     --------------- definition of `Assoc3` from trait
index 2298aa5b0b751d3c9ae1732044fba53c141e23ef..e87a76825c37de3793da7474208ae74abb2028d3 100644 (file)
@@ -1,6 +1,5 @@
 // check-pass
 
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 trait Cert {
index 404be59a36d9258b2da2fb91976e7ba41a0c8c64..d74d6d056d665e37b8d0c8b7e19d734fc37a83c0 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 // check-pass
index 6ee865072aebf8886b851674ef46720438919fc1..99f0e84fa6df4c25b7d224bc8e6f0f79c56c5f45 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-  //~^ WARNING: the feature `generic_associated_types` is incomplete
 
 trait X {
     type Y<'a>;
index 65998afa7f914428f7cb8bdfd06d340ef95cc98f..b4b89ab047363ce28c2cf43558a2c455b4484b8a 100644 (file)
@@ -1,27 +1,18 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-67510-pass.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0038]: the trait `X` cannot be made into an object
-  --> $DIR/issue-67510-pass.rs:8:19
+  --> $DIR/issue-67510-pass.rs:7:23
    |
 LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
+   |                       ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
    |
    = help: consider moving `Y` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-67510-pass.rs:5:10
+  --> $DIR/issue-67510-pass.rs:4:10
    |
 LL | trait X {
    |       - this trait cannot be made into an object...
 LL |     type Y<'a>;
    |          ^ ...because it contains the generic associated type `Y`
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0038`.
index 62b22089f917c73ac927105432d37654d1a16e95..e81a5b231a0015f34f267b32f8324f04718bf61e 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-  //~^ WARNING: the feature `generic_associated_types` is incomplete
 
 trait X {
     type Y<'a>;
index 12755c56974f2a82e08d711ef268865d6370e3e6..8ed2854ed3057108bac806b838da23fc56e2bb98 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-67510.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/issue-67510.rs:8:21
+  --> $DIR/issue-67510.rs:7:21
    |
 LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
    |     -               ^^ undeclared lifetime
@@ -18,7 +9,7 @@ LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
    = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
 
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/issue-67510.rs:8:26
+  --> $DIR/issue-67510.rs:7:26
    |
 LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
    |     -                    ^^ undeclared lifetime
@@ -27,6 +18,6 @@ LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
    |
    = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0261`.
index 0020887eaea90165e0c9b0cae30674b5c4272fc9..617d985dce9fed60dfc433e8ea96f17136c7a5a3 100644 (file)
@@ -1,7 +1,6 @@
 // Regression test for #68641
 
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete and may not
 
 trait UnsafeCopy {
     type Item<'a>: Copy;
index c92800c3746ade2fc44977c3c8133bd124e281b1..7ac1ccf0f37f3e60d29ad486032538ebb717354e 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-68641-check-gat-bounds.rs:3:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/issue-68641-check-gat-bounds.rs:15:5
+  --> $DIR/issue-68641-check-gat-bounds.rs:14:5
    |
 LL |     type Item<'a>: Copy;
    |                    ---- required by this bound in `UnsafeCopy::Item`
@@ -21,6 +12,6 @@ help: consider restricting type parameter `T`
 LL | impl<T: std::marker::Copy> UnsafeCopy for T {
    |       ^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
index ff8d2ca05b2f4e369a6057e45ddadf79cfd3f811..def0ad18f2328e2b29ac0aa97650ca6303047700 100644 (file)
@@ -1,7 +1,6 @@
 // Regression test for #68642
 
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete and may not
 
 trait Fun {
     type F<'a>: Fn() -> u32;
index e44547b10c17bd36a51d38ffdd4c3f32b348c918..4e609ca5484df50906fbf92f96f958113ff5cd86 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-68642-broken-llvm-ir.rs:3:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0277]: expected a `Fn<()>` closure, found `T`
-  --> $DIR/issue-68642-broken-llvm-ir.rs:15:5
+  --> $DIR/issue-68642-broken-llvm-ir.rs:14:5
    |
 LL |     type F<'a>: Fn() -> u32;
    |                 ----------- required by this bound in `Fun::F`
@@ -22,6 +13,6 @@ help: consider restricting type parameter `T`
 LL | impl<T: std::ops::Fn<()>> Fun for T {
    |       ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
index 2107804a8ba1efac86866fbeb400ca5614267ff2..9af065b5d26d1003ea3244b8f3aeabd1c9062f41 100644 (file)
@@ -1,7 +1,6 @@
 // Regression test for #68643
 
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete and may not
 
 trait Fun {
     type F<'a>: Fn() -> u32;
index fd0b4733d935904bfaf9f2f57a6cdeccbdfdc40b..44600bfcf96f7f6e7e0f4dfc059d68796f8621a9 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-68643-broken-mir.rs:3:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0277]: expected a `Fn<()>` closure, found `T`
-  --> $DIR/issue-68643-broken-mir.rs:15:5
+  --> $DIR/issue-68643-broken-mir.rs:14:5
    |
 LL |     type F<'a>: Fn() -> u32;
    |                 ----------- required by this bound in `Fun::F`
@@ -22,6 +13,6 @@ help: consider restricting type parameter `T`
 LL | impl<T: std::ops::Fn<()>> Fun for T {
    |       ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
index bfe63b1be71a88cff75394ba8db20bb686c1b7ac..1d2636c260d8d3f5221f5c6029f351573882387b 100644 (file)
@@ -1,7 +1,6 @@
 // Regression test for #68644
 
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete and may not
 
 trait Fun {
     type F<'a>: Fn() -> u32;
index 0c23c870f0106059397d9a7b5c67d68f978278d7..2c21795e161993d3cb88cc095f6f86de2cad6684 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-68644-codegen-selection.rs:3:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0277]: expected a `Fn<()>` closure, found `T`
-  --> $DIR/issue-68644-codegen-selection.rs:15:5
+  --> $DIR/issue-68644-codegen-selection.rs:14:5
    |
 LL |     type F<'a>: Fn() -> u32;
    |                 ----------- required by this bound in `Fun::F`
@@ -22,6 +13,6 @@ help: consider restricting type parameter `T`
 LL | impl<T: std::ops::Fn<()>> Fun for T {
    |       ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
index 676dcf90238dd944e4c4a321e42c56eac8003a4d..aa505064f8c513bf9726ea0693561304b3e70c6f 100644 (file)
@@ -1,7 +1,6 @@
 // Regression test for #68645
 
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete and may not
 
 trait Fun {
     type F<'a>: Fn() -> u32;
index 85d8d3f8e936e7358575106c198bc0ae9ba259c7..b2a2636d3eb9b4e5a64aac311951abeadd892264 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-68645-codegen-fulfillment.rs:3:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0277]: expected a `Fn<()>` closure, found `T`
-  --> $DIR/issue-68645-codegen-fulfillment.rs:15:5
+  --> $DIR/issue-68645-codegen-fulfillment.rs:14:5
    |
 LL |     type F<'a>: Fn() -> u32;
    |                 ----------- required by this bound in `Fun::F`
@@ -22,6 +13,6 @@ help: consider restricting type parameter `T`
 LL | impl<T: std::ops::Fn<()>> Fun for T {
    |       ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
index f294b22f73c6715efad3de35dfddf4ebf4dc074a..17bc034b39584219ca78e42346e459b8781434c5 100644 (file)
@@ -1,7 +1,6 @@
 // check-pass
 
 #![feature(generic_associated_types)]
-  //~^ WARNING: the feature `generic_associated_types` is incomplete
 
 
 trait Fun {
diff --git a/src/test/ui/generic-associated-types/issue-68648-1.stderr b/src/test/ui/generic-associated-types/issue-68648-1.stderr
deleted file mode 100644 (file)
index 322a8f9..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-68648-1.rs:3:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
-warning: 1 warning emitted
-
index e55bfcd4ba295f7bf77f0dceaea1c6cd6796b3c9..6c9a0d126a78232f8cacdced7e59a2562fc5ebc7 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-  //~^ WARNING: the feature `generic_associated_types` is incomplete
 
 trait Fun {
     type F<'a>;
index b51e0bca9f7a96eb58779fa5d03d4679c2010b98..7a7d5a6c2313fbed08e806c66180b3ae643514e8 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-68648-2.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0308]: mismatched types
-  --> $DIR/issue-68648-2.rs:15:17
+  --> $DIR/issue-68648-2.rs:14:17
    |
 LL | fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> {
    |            - this type parameter
@@ -18,6 +9,6 @@ LL |     T::identity(())
    = note: expected type parameter `T`
                    found unit type `()`
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0308`.
index 396315302f74c6b0a4b337bb7f94015bdd57c6d3..33f08faff56bd3ce23520eccad26ab27963d7244 100644 (file)
@@ -1,7 +1,6 @@
 // check-pass
 
 #![feature(generic_associated_types)]
-  //~^ WARNING: the feature `generic_associated_types` is incomplete
 
 trait Fun {
     type F<'a>;
diff --git a/src/test/ui/generic-associated-types/issue-68649-pass.stderr b/src/test/ui/generic-associated-types/issue-68649-pass.stderr
deleted file mode 100644 (file)
index e4a2f8d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-68649-pass.rs:3:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
-warning: 1 warning emitted
-
index 01f4c95639d195ced536abd5fe25f74af186397b..1e84717e9259f9fe5c2e4c0ab5704be3abca19aa 100644 (file)
@@ -2,7 +2,6 @@
 
 // check-pass
 
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 trait Fun {
index f682bdd8ac75a52d323bed2e09a199f9d856e7dd..c0d933362567e71182c2d6efabd7f08f6f5d7b00 100644 (file)
@@ -1,7 +1,6 @@
 // Regression test for #68656
 
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete and may not
 
 trait UnsafeCopy<T: Copy> {
     type Item<'a>: std::ops::Deref<Target = T>;
index c4ee2c4e61872c4114d36e3e3069f703a58b87b4..9d90d6f608f7af58bbdfe705b9cdcdb2e3a7bdfd 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-68656-unsized-values.rs:3:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0271]: type mismatch resolving `<T as Deref>::Target == T`
-  --> $DIR/issue-68656-unsized-values.rs:16:5
+  --> $DIR/issue-68656-unsized-values.rs:15:5
    |
 LL |     type Item<'a>: std::ops::Deref<Target = T>;
    |                                    ---------- required by this bound in `UnsafeCopy::Item`
@@ -25,6 +16,6 @@ help: consider further restricting this bound
 LL | impl<T: Copy + std::ops::Deref + Deref<Target = T>> UnsafeCopy<T> for T {
    |                                ^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0271`.
index a1cb2295b639ee348311773026f425bda5c2da18..d238f53bde7bee4df9e2d9d28628c710c3478e31 100644 (file)
@@ -1,6 +1,5 @@
 // check-pass
 
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 trait Document {
index 225f61d132ee61b11db5b8489c3705bcd220430a..ae64f9310d112912fb24bf32deaba3943153d377 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 trait Document {
index dfa86018976dc62ca1b6812fb6353c2057ab66c5..fd9e1acc557fa7a4ecb57746bdefd00348fc1a85 100644 (file)
@@ -1,5 +1,5 @@
 error[E0106]: missing lifetime specifier
-  --> $DIR/issue-70304.rs:55:41
+  --> $DIR/issue-70304.rs:54:41
    |
 LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
    |                                         ^^ expected named lifetime parameter
index c767bef1552ed642e05cb88a1e6b58947571455b..c2f0d59f4435fc41b6d6bb05e188d532e5b5788e 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 trait Provider {
index 2df800d065f4034f73ce644e67619bb4239a5232..f0babdaa60bea5337b0ae1f68f840261fac1a157 100644 (file)
@@ -1,11 +1,11 @@
 error[E0107]: missing generics for associated type `Provider::A`
-  --> $DIR/issue-71176.rs:13:27
+  --> $DIR/issue-71176.rs:12:27
    |
 LL |   inner: Box<dyn Provider<A = B>>,
    |                           ^ expected 1 lifetime argument
    |
 note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-71176.rs:5:10
+  --> $DIR/issue-71176.rs:4:10
    |
 LL |     type A<'a>;
    |          ^ --
index a483da863ff00200d457eda40af404232223b8a3..0e3899a88cc965ad02ca3a7e33e2a90c23867441 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-  //~^ WARNING: the feature `generic_associated_types` is incomplete
 
 trait Fun {
     type F<'a>: ?Sized;
index 651da696827c3c3ccd51c81c98b69e55bb9633f4..2cd050ed8be6c3e9e7ec9e3d40c9e8351961fa7c 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-74684-1.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0597]: `a` does not live long enough
-  --> $DIR/issue-74684-1.rs:16:26
+  --> $DIR/issue-74684-1.rs:15:26
    |
 LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(_ : Box<T>) -> &'static T::F<'a> {
    |        -- lifetime `'a` defined here
@@ -22,6 +13,6 @@ LL |     let _x = T::identity(&a);
 LL | }
    | - `a` dropped here while still borrowed
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0597`.
index 0caf19cb030389096432280999d475d3c1910479..fca55070b5ba3cf596292f607d44951ad7869146 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-  //~^ WARNING: the feature `generic_associated_types` is incomplete
 
 trait Fun {
     type F<'a>: ?Sized;
index 8c3484f9a7300251493aa6b42b31f3d7c52f6e20..23fb4285fc9d3a52d2b83939c0a824e881ea16af 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-74684-2.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0271]: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]`
-  --> $DIR/issue-74684-2.rs:24:5
+  --> $DIR/issue-74684-2.rs:23:5
    |
 LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> {
    |                            ------------ required by this bound in `bug`
@@ -16,6 +7,6 @@ LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> {
 LL |     bug(Box::new(x));
    |     ^^^ expected slice `[u8]`, found `i32`
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0271`.
index 754397229a6883f1946cca481a45933bffe7f3b7..c932025d1178c79787208e1bb34e87270ff9cb60 100644 (file)
@@ -1,6 +1,5 @@
 #![feature(associated_type_defaults)]
 #![feature(generic_associated_types)]
-#![allow(incomplete_features)]
 
 trait Trait1 {
     fn foo();
index 64bc94d601b7838d3848231e5ceba327903804b1..431182e79c4f07070989ebb38c8e2cdde1f40e6d 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `Self: Trait1` is not satisfied
-  --> $DIR/issue-74816.rs:10:5
+  --> $DIR/issue-74816.rs:9:5
    |
 LL |     type Associated: Trait1 = Self;
    |     ^^^^^^^^^^^^^^^^^------^^^^^^^^
@@ -13,7 +13,7 @@ LL | trait Trait2: Trait1 {
    |             ^^^^^^^^
 
 error[E0277]: the size for values of type `Self` cannot be known at compilation time
-  --> $DIR/issue-74816.rs:10:5
+  --> $DIR/issue-74816.rs:9:5
    |
 LL |     type Associated: Trait1 = Self;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 00761a97d00c729eac537bd4872f8aa70ba139fd..1bbf7aac5cdabc6ff70bb90f645e3f85ccda02f8 100644 (file)
@@ -1,6 +1,5 @@
 #![feature(generic_associated_types)]
 #![feature(associated_type_defaults)]
-#![allow(incomplete_features)]
 
 use std::ops::Deref;
 
index 7a7b5fd4f1c557ac7f7f7626d42282b4057f9801..54cb3fba2b5872113765ea0808d534ed9125c64b 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `Box<T>: Copy` is not satisfied
-  --> $DIR/issue-74824.rs:8:5
+  --> $DIR/issue-74824.rs:7:5
    |
 LL |     type Copy<T>: Copy = Box<T>;
    |     ^^^^^^^^^^^^^^----^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     type Copy<T>: Copy = Box<T>;
    |     the trait `Copy` is not implemented for `Box<T>`
 
 error[E0277]: the trait bound `T: Clone` is not satisfied
-  --> $DIR/issue-74824.rs:8:5
+  --> $DIR/issue-74824.rs:7:5
    |
 LL |     type Copy<T>: Copy = Box<T>;
    |     ^^^^^^^^^^^^^^----^^^^^^^^^^
diff --git a/src/test/ui/generic-associated-types/issue-76407.rs b/src/test/ui/generic-associated-types/issue-76407.rs
new file mode 100644 (file)
index 0000000..a814182
--- /dev/null
@@ -0,0 +1,27 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+
+trait Marker {}
+
+impl Marker for u32 {}
+
+trait MyTrait {
+    type Item<'a>;
+}
+
+struct MyStruct;
+
+impl MyTrait for MyStruct {
+    type Item<'a> = u32;
+}
+
+fn ty_check<T>()
+where
+    T: MyTrait,
+    for<'a> T::Item<'a>: Marker
+{}
+
+fn main() {
+    ty_check::<MyStruct>();
+}
index 3db3c38216aaab56049e4d01c49c29631e1b1d6c..1dad856d5a370fd888f13e7b3e83cce8d46706ba 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-//~^ WARNING the feature
 
 pub trait SubTrait {}
 
index d9829e59605588648fc506ac57307decc4c2ef68..45af30e39651eef333b61492a2590638373d9389 100644 (file)
@@ -1,20 +1,11 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-76535.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0107]: missing generics for associated type `SuperTrait::SubType`
-  --> $DIR/issue-76535.rs:37:33
+  --> $DIR/issue-76535.rs:36:33
    |
 LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
    |                                 ^^^^^^^ expected 1 lifetime argument
    |
 note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-76535.rs:7:10
+  --> $DIR/issue-76535.rs:6:10
    |
 LL |     type SubType<'a>: SubTrait;
    |          ^^^^^^^ --
@@ -24,14 +15,14 @@ LL |     let sub: Box<dyn SuperTrait<SubType<'a> = SubStruct>> = Box::new(SuperS
    |                                 ^^^^^^^^^^^
 
 error[E0038]: the trait `SuperTrait` cannot be made into an object
-  --> $DIR/issue-76535.rs:37:14
+  --> $DIR/issue-76535.rs:36:14
    |
 LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
    |
    = help: consider moving `SubType` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-76535.rs:7:10
+  --> $DIR/issue-76535.rs:6:10
    |
 LL | pub trait SuperTrait {
    |           ---------- this trait cannot be made into an object...
@@ -39,14 +30,14 @@ LL |     type SubType<'a>: SubTrait;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
 
 error[E0038]: the trait `SuperTrait` cannot be made into an object
-  --> $DIR/issue-76535.rs:37:57
+  --> $DIR/issue-76535.rs:36:57
    |
 LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
    |
    = help: consider moving `SubType` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-76535.rs:7:10
+  --> $DIR/issue-76535.rs:6:10
    |
 LL | pub trait SuperTrait {
    |           ---------- this trait cannot be made into an object...
@@ -55,7 +46,7 @@ LL |     type SubType<'a>: SubTrait;
    = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>`
    = note: required by cast to type `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0038, E0107.
 For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/generic-associated-types/issue-76826.rs b/src/test/ui/generic-associated-types/issue-76826.rs
new file mode 100644 (file)
index 0000000..d3201a1
--- /dev/null
@@ -0,0 +1,44 @@
+// run-pass
+
+#![feature(generic_associated_types)]
+
+pub trait Iter {
+    type Item<'a> where Self: 'a;
+
+    fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
+
+    fn for_each<F>(mut self, mut f: F)
+        where Self: Sized, F: for<'a> FnMut(Self::Item<'a>)
+    {
+        while let Some(item) = self.next() {
+            f(item);
+        }
+    }
+}
+
+pub struct Windows<T> {
+    items: Vec<T>,
+    start: usize,
+    len: usize,
+}
+
+impl<T> Windows<T> {
+    pub fn new(items: Vec<T>, len: usize) -> Self {
+        Self { items, start: 0, len }
+    }
+}
+
+impl<T> Iter for Windows<T> {
+    type Item<'a> where T: 'a = &'a mut [T];
+
+    fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> {
+        let slice = self.items.get_mut(self.start..self.start + self.len)?;
+        self.start += 1;
+        Some(slice)
+    }
+}
+
+fn main() {
+    Windows::new(vec![1, 2, 3, 4, 5], 3)
+        .for_each(|slice| println!("{:?}", slice));
+}
diff --git a/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs b/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs
new file mode 100644 (file)
index 0000000..850d83b
--- /dev/null
@@ -0,0 +1,40 @@
+// Test for diagnostics when we have mismatched lifetime due to implict 'static lifetime in GATs
+
+// check-fail
+
+#![feature(generic_associated_types)]
+
+pub trait A {}
+impl A for &dyn A {}
+impl A for Box<dyn A> {}
+
+pub trait B {
+    type T<'a>: A;
+}
+
+impl B for () {
+    // `'a` doesn't match implicit `'static`: suggest `'_`
+    type T<'a> = Box<dyn A + 'a>; //~ incompatible lifetime on type
+}
+
+trait C {}
+impl C for Box<dyn A + 'static> {}
+pub trait D {
+    type T<'a>: C;
+}
+impl D for () {
+    // `'a` doesn't match explicit `'static`: we *should* suggest removing `'static`
+    type T<'a> = Box<dyn A + 'a>; //~ incompatible lifetime on type
+}
+
+trait E {}
+impl E for (Box<dyn A>, Box<dyn A>) {}
+pub trait F {
+    type T<'a>: E;
+}
+impl F for () {
+    // `'a` doesn't match explicit `'static`: suggest `'_`
+    type T<'a> = (Box<dyn A + 'a>, Box<dyn A + 'a>); //~ incompatible lifetime on type
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr b/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr
new file mode 100644 (file)
index 0000000..fedc6a3
--- /dev/null
@@ -0,0 +1,87 @@
+error: incompatible lifetime on type
+  --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:17:5
+   |
+LL |     type T<'a> = Box<dyn A + 'a>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: because this has an unmet lifetime requirement
+  --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:12:17
+   |
+LL |     type T<'a>: A;
+   |                 ^ introduces a `'static` lifetime requirement
+note: the lifetime `'a` as defined on the associated item at 17:12...
+  --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:17:12
+   |
+LL |     type T<'a> = Box<dyn A + 'a>;
+   |            ^^
+   = note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
+note: this has an implicit `'static` lifetime requirement
+  --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:9:20
+   |
+LL | impl A for Box<dyn A> {}
+   |                    ^
+help: consider relaxing the implicit `'static` requirement
+   |
+LL | impl A for Box<dyn A + '_> {}
+   |                      ^^^^
+
+error: incompatible lifetime on type
+  --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:27:5
+   |
+LL |     type T<'a> = Box<dyn A + 'a>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: because this has an unmet lifetime requirement
+  --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:23:17
+   |
+LL |     type T<'a>: C;
+   |                 ^ introduces a `'static` lifetime requirement
+note: the lifetime `'a` as defined on the associated item at 27:12...
+  --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:27:12
+   |
+LL |     type T<'a> = Box<dyn A + 'a>;
+   |            ^^
+note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
+  --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:21:1
+   |
+LL | impl C for Box<dyn A + 'static> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: incompatible lifetime on type
+  --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:37:5
+   |
+LL |     type T<'a> = (Box<dyn A + 'a>, Box<dyn A + 'a>);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: because this has an unmet lifetime requirement
+  --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:33:17
+   |
+LL |     type T<'a>: E;
+   |                 ^ introduces a `'static` lifetime requirement
+note: the lifetime `'a` as defined on the associated item at 37:12...
+  --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:37:12
+   |
+LL |     type T<'a> = (Box<dyn A + 'a>, Box<dyn A + 'a>);
+   |            ^^
+   = note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
+note: this has an implicit `'static` lifetime requirement
+  --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:31:21
+   |
+LL | impl E for (Box<dyn A>, Box<dyn A>) {}
+   |                     ^
+note: this has an implicit `'static` lifetime requirement
+  --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:31:33
+   |
+LL | impl E for (Box<dyn A>, Box<dyn A>) {}
+   |                                 ^
+help: consider relaxing the implicit `'static` requirement
+   |
+LL | impl E for (Box<dyn A + '_>, Box<dyn A>) {}
+   |                       ^^^^
+help: consider relaxing the implicit `'static` requirement
+   |
+LL | impl E for (Box<dyn A>, Box<dyn A + '_>) {}
+   |                                   ^^^^
+
+error: aborting due to 3 previous errors
+
index 310dd51ea0c827d667eb49e6119176ba86587735..7ccf376e5cb633a98a50edba0824b4a16aee0585 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 trait CollectionFamily {
index 0a231d22b62681407ffb3ece1f1e98da43257ee7..802621bd18c0b707b843f377fd20b43dcd0b989d 100644 (file)
@@ -1,11 +1,11 @@
 error[E0107]: missing generics for associated type `CollectionFamily::Member`
-  --> $DIR/issue-78671.rs:8:47
+  --> $DIR/issue-78671.rs:7:47
    |
 LL |     Box::new(Family) as &dyn CollectionFamily<Member=usize>
    |                                               ^^^^^^ expected 1 generic argument
    |
 note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-78671.rs:5:10
+  --> $DIR/issue-78671.rs:4:10
    |
 LL |     type Member<T>;
    |          ^^^^^^ -
@@ -15,14 +15,14 @@ LL |     Box::new(Family) as &dyn CollectionFamily<Member<T>=usize>
    |                                               ^^^^^^^^^
 
 error[E0038]: the trait `CollectionFamily` cannot be made into an object
-  --> $DIR/issue-78671.rs:8:25
+  --> $DIR/issue-78671.rs:7:25
    |
 LL |     Box::new(Family) as &dyn CollectionFamily<Member=usize>
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object
    |
    = help: consider moving `Member` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-78671.rs:5:10
+  --> $DIR/issue-78671.rs:4:10
    |
 LL | trait CollectionFamily {
    |       ---------------- this trait cannot be made into an object...
index 216e426ada265da691b21e5bd957feb802fcb9e2..7f0ac348358840c6bc0975e954cc1238345933e1 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 trait RefCont<'a, T> {
index 11b4a519d51883764b2d79ea30cdc9ee480a5bc5..cf0a80bb2c58d4fbd8631b021cc08dd820739f63 100644 (file)
@@ -1,11 +1,11 @@
 error[E0107]: missing generics for associated type `MapLike::VRefCont`
-  --> $DIR/issue-79422.rs:43:36
+  --> $DIR/issue-79422.rs:42:36
    |
 LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
    |                                    ^^^^^^^^ expected 1 lifetime argument
    |
 note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-79422.rs:21:10
+  --> $DIR/issue-79422.rs:20:10
    |
 LL |     type VRefCont<'a>: RefCont<'a, V>;
    |          ^^^^^^^^ --
@@ -15,14 +15,14 @@ LL |         as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>;
    |                                    ^^^^^^^^^^^^
 
 error[E0038]: the trait `MapLike` cannot be made into an object
-  --> $DIR/issue-79422.rs:43:12
+  --> $DIR/issue-79422.rs:42:12
    |
 LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
    |
    = help: consider moving `VRefCont` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-79422.rs:21:10
+  --> $DIR/issue-79422.rs:20:10
    |
 LL | trait MapLike<K, V> {
    |       ------- this trait cannot be made into an object...
@@ -30,14 +30,14 @@ LL |     type VRefCont<'a>: RefCont<'a, V>;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
 
 error[E0038]: the trait `MapLike` cannot be made into an object
-  --> $DIR/issue-79422.rs:42:13
+  --> $DIR/issue-79422.rs:41:13
    |
 LL |     let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
    |
    = help: consider moving `VRefCont` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-79422.rs:21:10
+  --> $DIR/issue-79422.rs:20:10
    |
 LL | trait MapLike<K, V> {
    |       ------- this trait cannot be made into an object...
index 412a9f8257c8ae284ccc62792151ac8b70a77812..6d73fd68dbed17b4247a0371bc6560b17c2ec008 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 trait Monad {
index b7a0ef0a6d674a68b952d868130de5b9f5d819bd..e6f9a0c754681a08b29de9e518efd5a447e3972f 100644 (file)
@@ -1,11 +1,11 @@
 error[E0107]: missing generics for associated type `Monad::Wrapped`
-  --> $DIR/issue-79636-1.rs:16:34
+  --> $DIR/issue-79636-1.rs:15:34
    |
 LL |     MInner: Monad<Unwrapped = A, Wrapped = MOuter::Wrapped<A>>,
    |                                  ^^^^^^^ expected 1 generic argument
    |
 note: associated type defined here, with 1 generic parameter: `B`
-  --> $DIR/issue-79636-1.rs:6:10
+  --> $DIR/issue-79636-1.rs:5:10
    |
 LL |     type Wrapped<B>;
    |          ^^^^^^^ -
index ef39378e78d68a3f37b4277903bca9402b1044a0..cdaf2e483411eb93791e7e681427311449f5a782 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 trait SomeTrait {
index d5ba1aaeed5e3863a2a8037052432c624b694afd..9a240c6545824aeea3ec3cf80df94310abc3f3c0 100644 (file)
@@ -1,11 +1,11 @@
 error[E0107]: missing generics for associated type `SomeTrait::Wrapped`
-  --> $DIR/issue-79636-2.rs:12:18
+  --> $DIR/issue-79636-2.rs:11:18
    |
 LL |     W: SomeTrait<Wrapped = W>,
    |                  ^^^^^^^ expected 1 generic argument
    |
 note: associated type defined here, with 1 generic parameter: `A`
-  --> $DIR/issue-79636-2.rs:5:10
+  --> $DIR/issue-79636-2.rs:4:10
    |
 LL |     type Wrapped<A>: SomeTrait;
    |          ^^^^^^^ -
index 7c1673edc51a4bf522a08ef66c1c288e6f861066..f15d4d8b1385a7ec47faac3921a8fc17e4e8d16b 100644 (file)
@@ -1,6 +1,5 @@
 // check-pass
 
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 struct E {}
index fd81804f234e51797bfa2ccb5e4cca26eeaedd75..6a1fe7519a840ee20b92669a15ebb8169f360eb1 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-#![allow(incomplete_features)]
 
 #[derive(Default)]
 struct E<T> {
index 31483ff0cd63d58b9996c852dffa05c6853b0bf1..26c879193b66b9a838f5576f2b9adbf0e4a939d3 100644 (file)
@@ -1,11 +1,11 @@
 error[E0107]: missing generics for associated type `TestMut::Output`
-  --> $DIR/issue-80433.rs:24:47
+  --> $DIR/issue-80433.rs:23:47
    |
 LL | fn test_simpler<'a>(dst: &'a mut impl TestMut<Output = &'a mut f32>)
    |                                               ^^^^^^ expected 1 lifetime argument
    |
 note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-80433.rs:10:10
+  --> $DIR/issue-80433.rs:9:10
    |
 LL |     type Output<'a>;
    |          ^^^^^^ --
diff --git a/src/test/ui/generic-associated-types/issue-81487.rs b/src/test/ui/generic-associated-types/issue-81487.rs
new file mode 100644 (file)
index 0000000..7f399c4
--- /dev/null
@@ -0,0 +1,19 @@
+// build-pass
+
+#![feature(generic_associated_types)]
+
+trait Trait {
+    type Ref<'a>;
+}
+
+impl Trait for () {
+    type Ref<'a> = &'a i8;
+}
+
+struct RefRef<'a, T: Trait>(&'a <T as Trait>::Ref<'a>);
+
+fn wrap<'a, T: Trait>(reff: &'a <T as Trait>::Ref<'a>) -> RefRef<'a, T> {
+    RefRef(reff)
+}
+
+fn main() {}
index b5512ee6d6290bc2e3eaecf8837074ac138a6854..fa2f86242257f95141a74ff9840b4d1823fc462a 100644 (file)
@@ -1,7 +1,6 @@
 // Regression test for #81712.
 
 #![feature(generic_associated_types)]
-#![allow(incomplete_features)]
 
 trait A {
     type BType: B<AType = Self>;
index 4a7b96db30a9b9a705b4a8848d7348853c9ecf78..850b434e9bfdc8e77e66b1274d4fba6a614e6eb7 100644 (file)
@@ -1,11 +1,11 @@
 error[E0107]: missing generics for associated type `C::DType`
-  --> $DIR/issue-81712-cyclic-traits.rs:17:19
+  --> $DIR/issue-81712-cyclic-traits.rs:16:19
    |
 LL |     type CType: C<DType = Self>;
    |                   ^^^^^ expected 1 generic argument
    |
 note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-81712-cyclic-traits.rs:14:10
+  --> $DIR/issue-81712-cyclic-traits.rs:13:10
    |
 LL |     type DType<T>: D<T, CType = Self>;
    |          ^^^^^ -
index 02f843b07e23d07b43089d379dc858fe4d9488fc..e457bca0c09636edf557ba337220deb564bddbf2 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 trait StreamingIterator {
index d7b904165c0ec39b73ccfd4069d98b576465f642..1ba21ccd796792c1614058a1d282462b4d0d5edf 100644 (file)
@@ -1,11 +1,11 @@
 error[E0107]: missing generics for associated type `StreamingIterator::Item`
-  --> $DIR/issue-81862.rs:6:40
+  --> $DIR/issue-81862.rs:5:40
    |
 LL |     fn next(&mut self) -> Option<Self::Item>;
    |                                        ^^^^ expected 1 lifetime argument
    |
 note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-81862.rs:5:10
+  --> $DIR/issue-81862.rs:4:10
    |
 LL |     type Item<'a>;
    |          ^^^^ --
diff --git a/src/test/ui/generic-associated-types/issue-86483.rs b/src/test/ui/generic-associated-types/issue-86483.rs
new file mode 100644 (file)
index 0000000..a8b54c3
--- /dev/null
@@ -0,0 +1,14 @@
+// Regression test of #86483.
+
+#![feature(generic_associated_types)]
+
+pub trait IceIce<T> //~ ERROR: the parameter type `T` may not live long enough
+where
+    for<'a> T: 'a,
+{
+    type Ice<'v>: IntoIterator<Item = &'v T>;
+    //~^ ERROR: the parameter type `T` may not live long enough
+    //~| ERROR: the parameter type `T` may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-86483.stderr b/src/test/ui/generic-associated-types/issue-86483.stderr
new file mode 100644 (file)
index 0000000..2106b21
--- /dev/null
@@ -0,0 +1,36 @@
+error[E0311]: the parameter type `T` may not live long enough
+  --> $DIR/issue-86483.rs:5:1
+   |
+LL |   pub trait IceIce<T>
+   |   ^                - help: consider adding an explicit lifetime bound...: `T: 'a`
+   |  _|
+   | |
+LL | | where
+LL | |     for<'a> T: 'a,
+LL | | {
+...  |
+LL | |
+LL | | }
+   | |_^ ...so that the type `T` will meet its required lifetime bounds
+
+error[E0311]: the parameter type `T` may not live long enough
+  --> $DIR/issue-86483.rs:9:5
+   |
+LL | pub trait IceIce<T>
+   |                  - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
+LL |     type Ice<'v>: IntoIterator<Item = &'v T>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/issue-86483.rs:9:32
+   |
+LL | pub trait IceIce<T>
+   |                  - help: consider adding an explicit lifetime bound...: `T: 'v`
+...
+LL |     type Ice<'v>: IntoIterator<Item = &'v T>;
+   |                                ^^^^^^^^^^^^ ...so that the reference type `&'v T` does not outlive the data it points at
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
index 600a69006c1ea6184a008166e2796f4777a7993f..952fca8ab8a65fff5314647d3de9d60cf94ee965 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 // run-pass
index 2de4c7b8492a34244977ccc8ec7618220b47ca92..6db249221b849821494b7dad00ee512693baa4bb 100644 (file)
@@ -2,9 +2,6 @@
 // generics for a generic associated type.
 
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete
-//~| NOTE `#[warn(incomplete_features)]` on by default
-//~| NOTE see issue #44265
 
 trait X {
     type Y<T>;
index c94155d13c344a78f3889f4a2d5cf3a645883a4e..8af9fbed872e15e72da14bb01cd84696eaed08ed 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/method-unsatified-assoc-type-predicate.rs:4:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied
-  --> $DIR/method-unsatified-assoc-type-predicate.rs:29:7
+  --> $DIR/method-unsatified-assoc-type-predicate.rs:26:7
    |
 LL | struct S;
    | ---------
@@ -24,6 +15,6 @@ LL |     a.f();
            `<S as X>::Y<i32> = i32`
            which is required by `S: M`
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0599`.
index de24361dfde32876fec2816dfc6f1be14473c252..cd918157f7c8d123c3223943698b071ab51af574 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types`
 
 trait X {
     type Y<'a, 'b>;
index 73829594c826a09a929217ba8e65c5e0445ef002..95b048d36c2dec25e2a60f44851de4d6d941e4ef 100644 (file)
@@ -1,20 +1,11 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/missing_lifetime_args.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0107]: missing generics for associated type `X::Y`
-  --> $DIR/missing_lifetime_args.rs:14:32
+  --> $DIR/missing_lifetime_args.rs:13:32
    |
 LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y = (&'c u32, &'d u32)>>) {}
    |                                ^ expected 2 lifetime arguments
    |
 note: associated type defined here, with 2 lifetime parameters: `'a`, `'b`
-  --> $DIR/missing_lifetime_args.rs:5:10
+  --> $DIR/missing_lifetime_args.rs:4:10
    |
 LL |     type Y<'a, 'b>;
    |          ^ --  --
@@ -24,7 +15,7 @@ LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'c, 'd> = (&'c u32, &'d u32)>>) {}
    |                                ^^^^^^^^^
 
 error[E0107]: this struct takes 3 lifetime arguments but 2 lifetime arguments were supplied
-  --> $DIR/missing_lifetime_args.rs:17:26
+  --> $DIR/missing_lifetime_args.rs:16:26
    |
 LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {}
    |                          ^^^ --  -- supplied 2 lifetime arguments
@@ -32,7 +23,7 @@ LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {}
    |                          expected 3 lifetime arguments
    |
 note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c`
-  --> $DIR/missing_lifetime_args.rs:8:8
+  --> $DIR/missing_lifetime_args.rs:7:8
    |
 LL | struct Foo<'a, 'b, 'c> {
    |        ^^^ --  --  --
@@ -42,7 +33,7 @@ LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b, 'a>) {}
    |                                    ^^^^
 
 error[E0107]: this struct takes 3 lifetime arguments but 1 lifetime argument was supplied
-  --> $DIR/missing_lifetime_args.rs:20:16
+  --> $DIR/missing_lifetime_args.rs:19:16
    |
 LL | fn f<'a>(_arg: Foo<'a>) {}
    |                ^^^ -- supplied 1 lifetime argument
@@ -50,7 +41,7 @@ LL | fn f<'a>(_arg: Foo<'a>) {}
    |                expected 3 lifetime arguments
    |
 note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c`
-  --> $DIR/missing_lifetime_args.rs:8:8
+  --> $DIR/missing_lifetime_args.rs:7:8
    |
 LL | struct Foo<'a, 'b, 'c> {
    |        ^^^ --  --  --
@@ -59,6 +50,6 @@ help: add missing lifetime arguments
 LL | fn f<'a>(_arg: Foo<'a, 'b, 'c>) {}
    |                      ^^^^^^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0107`.
index 37cb7cab121ba196f63343d43a48a19cf1369128..e3e78dd96f62bce481282300183829ba92fd664e 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-//~^ WARNING the feature
 
 trait Foo {
     type Assoc<'a, const N: usize>;
index 6c66312e7b160099cf7e25c1179ed2b2f75cadba..02d3cd2e8d5f9e7f7b1603e78a1e483af9f8ccf2 100644 (file)
@@ -1,20 +1,11 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/missing_lifetime_const.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
-  --> $DIR/missing_lifetime_const.rs:9:24
+  --> $DIR/missing_lifetime_const.rs:8:24
    |
 LL |     let _: <T as Foo>::Assoc<3>;
    |                        ^^^^^ expected 1 lifetime argument
    |
 note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/missing_lifetime_const.rs:5:10
+  --> $DIR/missing_lifetime_const.rs:4:10
    |
 LL |     type Assoc<'a, const N: usize>;
    |          ^^^^^ --
@@ -23,6 +14,6 @@ help: add missing lifetime argument
 LL |     let _: <T as Foo>::Assoc<'a, 3>;
    |                              ^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0107`.
index 3f92c031e18d003ad4fc65587889411bd71fdeec..0508cc2daeae0fb3328d42c5052f5ad027cf8bb8 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 #![feature(associated_type_defaults)]
 
index b6f600964c9a398eba8a200b392662ba8801a092..db469597f9a637654d2d4b6c226d3049592a55bd 100644 (file)
@@ -1,5 +1,5 @@
 error[E0107]: this associated type takes 1 lifetime argument but 2 lifetime arguments were supplied
-  --> $DIR/parameter_number_and_kind.rs:13:24
+  --> $DIR/parameter_number_and_kind.rs:12:24
    |
 LL |     type FErr1 = Self::E<'static, 'static>;
    |                        ^          ------- help: remove this lifetime argument
@@ -7,19 +7,19 @@ LL |     type FErr1 = Self::E<'static, 'static>;
    |                        expected 1 lifetime argument
    |
 note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/parameter_number_and_kind.rs:10:10
+  --> $DIR/parameter_number_and_kind.rs:9:10
    |
 LL |     type E<'a, T>;
    |          ^ --
 
 error[E0107]: this associated type takes 1 generic argument but 0 generic arguments were supplied
-  --> $DIR/parameter_number_and_kind.rs:13:24
+  --> $DIR/parameter_number_and_kind.rs:12:24
    |
 LL |     type FErr1 = Self::E<'static, 'static>;
    |                        ^ expected 1 generic argument
    |
 note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/parameter_number_and_kind.rs:10:10
+  --> $DIR/parameter_number_and_kind.rs:9:10
    |
 LL |     type E<'a, T>;
    |          ^     -
@@ -29,7 +29,7 @@ LL |     type FErr1 = Self::E<'static, 'static, T>;
    |                                          ^^^
 
 error[E0107]: this associated type takes 1 generic argument but 2 generic arguments were supplied
-  --> $DIR/parameter_number_and_kind.rs:16:27
+  --> $DIR/parameter_number_and_kind.rs:15:27
    |
 LL |     type FErr2<T> = Self::E<'static, T, u32>;
    |                           ^             --- help: remove this generic argument
@@ -37,7 +37,7 @@ LL |     type FErr2<T> = Self::E<'static, T, u32>;
    |                           expected 1 generic argument
    |
 note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/parameter_number_and_kind.rs:10:10
+  --> $DIR/parameter_number_and_kind.rs:9:10
    |
 LL |     type E<'a, T>;
    |          ^     -
index 74b9cec1da3fa2cfb3af9321057c0ae5358e4e94..6ca0bc6ddbc9f150d4d7859a43cf89de89277b67 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 #![feature(associated_type_defaults)]
 
index bdd1c895fd911cdb982c2545b31b185f4cb5cc4b..1458bf0c4a49341147eb47f4bf57c7601c8e5199 100644 (file)
@@ -1,5 +1,5 @@
 error[E0195]: lifetime parameters or bounds on type `A` do not match the trait declaration
-  --> $DIR/parameter_number_and_kind_impl.rs:16:11
+  --> $DIR/parameter_number_and_kind_impl.rs:15:11
    |
 LL |     type A<'a>;
    |           ---- lifetimes in impl do not match this type in trait
@@ -8,7 +8,7 @@ LL |     type A = u32;
    |           ^ lifetimes do not match type in trait
 
 error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/parameter_number_and_kind_impl.rs:18:12
+  --> $DIR/parameter_number_and_kind_impl.rs:17:12
    |
 LL |     type B<'a, 'b>;
    |            --  --
@@ -21,7 +21,7 @@ LL |     type B<'a, T> = Vec<T>;
    |            found 1 type parameter
 
 error[E0195]: lifetime parameters or bounds on type `C` do not match the trait declaration
-  --> $DIR/parameter_number_and_kind_impl.rs:20:11
+  --> $DIR/parameter_number_and_kind_impl.rs:19:11
    |
 LL |     type C;
    |           - lifetimes in impl do not match this type in trait
@@ -30,7 +30,7 @@ LL |     type C<'a> = u32;
    |           ^^^^ lifetimes do not match type in trait
 
 error[E0049]: type `A` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/parameter_number_and_kind_impl.rs:27:12
+  --> $DIR/parameter_number_and_kind_impl.rs:26:12
    |
 LL |     type A<'a>;
    |            -- expected 0 type parameters
@@ -39,7 +39,7 @@ LL |     type A<T> = u32;
    |            ^ found 1 type parameter
 
 error[E0195]: lifetime parameters or bounds on type `B` do not match the trait declaration
-  --> $DIR/parameter_number_and_kind_impl.rs:29:11
+  --> $DIR/parameter_number_and_kind_impl.rs:28:11
    |
 LL |     type B<'a, 'b>;
    |           -------- lifetimes in impl do not match this type in trait
@@ -48,7 +48,7 @@ LL |     type B<'a> = u32;
    |           ^^^^ lifetimes do not match type in trait
 
 error[E0049]: type `C` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/parameter_number_and_kind_impl.rs:31:12
+  --> $DIR/parameter_number_and_kind_impl.rs:30:12
    |
 LL |     type C;
    |           - expected 0 type parameters
index b10bfea9febe50efb34384d8ec3287301d10cf3b..be85598b7bfaf758cf59be07028c2774425c4136 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-//~^ WARNING: the feature `generic_associated_types` is incomplete
 
 trait X {
     type Y<'a>;
index 8abc4ccc9a5fa590e7fa88bff8e21c49608afbcc..2b265e921616db1fb1d1dc47b66f3b1fa635477d 100644 (file)
@@ -1,19 +1,10 @@
 error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=`
-  --> $DIR/trait-path-expected-token.rs:8:33
+  --> $DIR/trait-path-expected-token.rs:7:33
    |
 LL | fn f1<'a>(arg : Box<dyn X<Y = B = &'a ()>>) {}
    |                               - ^ expected one of 7 possible tokens
    |                               |
    |                               maybe try to close unmatched angle bracket
 
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/trait-path-expected-token.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
index 5e50c6b35c9602ab2abae3b2aa76269527ff7f53..d57c2813b38a972f0dc25343208f0560ee246373 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-//~^ WARNING: the feature `generic_associated_types` is incomplete
 
 mod error1 {
   trait X {
index 27e1a750b213197f865e0a16ea5b9b4b336b6488..b1fea6d33a7f0e5c6ec522b352fa9a5629b43143 100644 (file)
@@ -1,5 +1,5 @@
 error: expected expression, found `)`
-  --> $DIR/trait-path-expressions.rs:9:39
+  --> $DIR/trait-path-expressions.rs:8:39
    |
 LL |   fn f1<'a>(arg : Box<dyn X< 1 = 32 >>) {}
    |                              -        ^ expected expression
@@ -7,21 +7,12 @@ LL |   fn f1<'a>(arg : Box<dyn X< 1 = 32 >>) {}
    |                              while parsing a const generic argument starting here
 
 error: expected one of `,`, `:`, or `>`, found `=`
-  --> $DIR/trait-path-expressions.rs:19:36
+  --> $DIR/trait-path-expressions.rs:18:36
    |
 LL |   fn f2<'a>(arg : Box<dyn X< { 1 } = 32 >>) {}
    |                                  - ^ expected one of `,`, `:`, or `>`
    |                                  |
    |                                  maybe try to close unmatched angle bracket
 
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/trait-path-expressions.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
index 94dda17aad710f9d9792c8c707ff449a0a8d8743..7914864807ce3ab61e56f458c5da0e39dd8f042d 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-//~^ WARNING: the feature `generic_associated_types` is incomplete
 
 trait X {
     type Y<'a>;
index f6038566e5b5e83479c6907c2fb334de15be19ae..c2908150429e342951e1ce2d2135bfe20c130c4b 100644 (file)
@@ -1,5 +1,5 @@
 error: expected one of `>`, a const expression, lifetime, or type, found `:`
-  --> $DIR/trait-path-missing-gen_arg.rs:9:30
+  --> $DIR/trait-path-missing-gen_arg.rs:8:30
    |
 LL |   fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
    |                              ^ expected one of `>`, a const expression, lifetime, or type
@@ -10,13 +10,13 @@ LL |   fn f1<'a>(arg : Box<{ dyn X< : 32 } >>) {}
    |                       ^             ^
 
 error: expected parameter name, found `>`
-  --> $DIR/trait-path-missing-gen_arg.rs:9:36
+  --> $DIR/trait-path-missing-gen_arg.rs:8:36
    |
 LL |   fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
    |                                    ^ expected parameter name
 
 error: expected one of `!`, `)`, `+`, `,`, or `::`, found `>`
-  --> $DIR/trait-path-missing-gen_arg.rs:9:36
+  --> $DIR/trait-path-missing-gen_arg.rs:8:36
    |
 LL |   fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
    |                                    ^
@@ -25,28 +25,19 @@ LL |   fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
    |                                    help: missing `,`
 
 error: expected one of `>`, a const expression, lifetime, or type, found `=`
-  --> $DIR/trait-path-missing-gen_arg.rs:17:30
+  --> $DIR/trait-path-missing-gen_arg.rs:16:30
    |
 LL |   fn f1<'a>(arg : Box<dyn X< = 32 >>) {}
    |                            - ^ expected one of `>`, a const expression, lifetime, or type
    |                            |
    |                            maybe try to close unmatched angle bracket
 
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/trait-path-missing-gen_arg.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0747]: constant provided when a type was expected
-  --> $DIR/trait-path-missing-gen_arg.rs:9:23
+  --> $DIR/trait-path-missing-gen_arg.rs:8:23
    |
 LL |   fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
    |                       ^^^^^^^^^^^
 
-error: aborting due to 5 previous errors; 1 warning emitted
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0747`.
index eba30e1438f04c75d4c1d54207018bddb5546be8..e943f075f53427bcee1961a7a719ddd9db341e15 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-//~^ WARNING: the feature `generic_associated_types` is incomplete
 
 const _: () = {
     trait X {
index c82953aaed7dd5022d18506fa0b5a9db722150f6..bfb109fbfa40d3b97c060d7d8c8b949185057e44 100644 (file)
@@ -1,5 +1,5 @@
 error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, or `>`, found `=`
-  --> $DIR/trait-path-segments.rs:9:36
+  --> $DIR/trait-path-segments.rs:8:36
    |
 LL |     fn f1<'a>(arg : Box<dyn X<X::Y = u32>>) {}
    |                                  - ^ expected one of 8 possible tokens
@@ -7,7 +7,7 @@ LL |     fn f1<'a>(arg : Box<dyn X<X::Y = u32>>) {}
    |                                  maybe try to close unmatched angle bracket
 
 error: expected one of `,`, `::`, `:`, or `>`, found `=`
-  --> $DIR/trait-path-segments.rs:20:35
+  --> $DIR/trait-path-segments.rs:19:35
    |
 LL |     impl<T : X<<Self as X>::Y<'a> = &'a u32>> Z for T {}
    |                                 - ^ expected one of `,`, `::`, `:`, or `>`
@@ -15,21 +15,12 @@ LL |     impl<T : X<<Self as X>::Y<'a> = &'a u32>> Z for T {}
    |                                 maybe try to close unmatched angle bracket
 
 error: expected one of `!`, `+`, `,`, `::`, `:`, or `>`, found `=`
-  --> $DIR/trait-path-segments.rs:31:25
+  --> $DIR/trait-path-segments.rs:30:25
    |
 LL |     impl<T : X<X::Y<'a> = &'a u32>> Z for T {}
    |                       - ^ expected one of `!`, `+`, `,`, `::`, `:`, or `>`
    |                       |
    |                       maybe try to close unmatched angle bracket
 
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/trait-path-segments.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
index d7a0ef4916a1820563d2ad14c3e1661eca5afa31..4846af96d32ac6d91958f8be05cd7e0107845232 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-  //~^ the feature `generic_associated_types` is incomplete
 
 trait X {
     type Y<'a>;
index 5685e5208c6d8e00afffa54ab4478b26c78c7b8e..59b53c70388acdb094f3ee1de11250af7683cb55 100644 (file)
@@ -1,20 +1,11 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/trait-path-type-error-once-implemented.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
-  --> $DIR/trait-path-type-error-once-implemented.rs:9:29
+  --> $DIR/trait-path-type-error-once-implemented.rs:8:29
    |
 LL |   fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
    |                             ^ expected 1 lifetime argument
    |
 note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/trait-path-type-error-once-implemented.rs:5:10
+  --> $DIR/trait-path-type-error-once-implemented.rs:4:10
    |
 LL |     type Y<'a>;
    |          ^ --
@@ -24,7 +15,7 @@ LL |   fn f2<'a>(arg : Box<dyn X<Y<'a, 1> = &'a ()>>) {}
    |                               ^^^
 
 error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied
-  --> $DIR/trait-path-type-error-once-implemented.rs:9:29
+  --> $DIR/trait-path-type-error-once-implemented.rs:8:29
    |
 LL |   fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
    |                             ^--- help: remove these generics
@@ -32,11 +23,11 @@ LL |   fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
    |                             expected 0 generic arguments
    |
 note: associated type defined here, with 0 generic parameters
-  --> $DIR/trait-path-type-error-once-implemented.rs:5:10
+  --> $DIR/trait-path-type-error-once-implemented.rs:4:10
    |
 LL |     type Y<'a>;
    |          ^
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0107`.
index 522b3edc638ea73b988d2c6123d89ad2650d9d7c..856253cc7fab6d18b7b5750f88566803dce49827 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-//~^ WARNING: the feature `generic_associated_types` is incomplete
 
 trait X {
     type Y<'a>;
index ac791c224810e8c15ccffec76ae16f30ee3a8fbf..c0fa41b9e0e0c48d499325447f2c4834e2196db3 100644 (file)
@@ -1,5 +1,5 @@
 error: expected one of `,`, `:`, or `>`, found `=`
-  --> $DIR/trait-path-types.rs:9:37
+  --> $DIR/trait-path-types.rs:8:37
    |
 LL |   fn f<'a>(arg : Box<dyn X< [u8; 1] = u32>>) {}
    |                                   - ^ expected one of `,`, `:`, or `>`
@@ -7,7 +7,7 @@ LL |   fn f<'a>(arg : Box<dyn X< [u8; 1] = u32>>) {}
    |                                   maybe try to close unmatched angle bracket
 
 error: expected one of `,`, `:`, or `>`, found `=`
-  --> $DIR/trait-path-types.rs:14:37
+  --> $DIR/trait-path-types.rs:13:37
    |
 LL |   fn f1<'a>(arg : Box<dyn X<(Y<'a>) = &'a ()>>) {}
    |                                   - ^ expected one of `,`, `:`, or `>`
@@ -15,21 +15,12 @@ LL |   fn f1<'a>(arg : Box<dyn X<(Y<'a>) = &'a ()>>) {}
    |                                   maybe try to close unmatched angle bracket
 
 error: expected one of `,`, `:`, or `>`, found `=`
-  --> $DIR/trait-path-types.rs:19:33
+  --> $DIR/trait-path-types.rs:18:33
    |
 LL |   fn f1<'a>(arg : Box<dyn X< 'a = u32 >>) {}
    |                              -- ^ expected one of `,`, `:`, or `>`
    |                              |
    |                              maybe try to close unmatched angle bracket
 
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/trait-path-types.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
index b322b752a156738a349bb866f9ef1a837fdb678c..da86e7f274820e24f16603ad6010d5f6865a90e8 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 // check-pass
index 0cd676a9b37f3f9e3c69747846c047538929abd6..7517e1fa9d061fc3777ba41f8e21fb2b6a9466c7 100644 (file)
@@ -2,7 +2,6 @@
 // `feature(trivial_bounds)`.
 
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete
 
 trait Print {
     fn print();
index d27e46f6836df9cf5483e53a07d5599732770704..d5e9caf9ecd4e3f0bc2a15cd7300791bf2fcf013 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/projection-bound-cycle-generic.rs:4:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
-  --> $DIR/projection-bound-cycle-generic.rs:45:5
+  --> $DIR/projection-bound-cycle-generic.rs:44:5
    |
 LL | struct OnlySized<T> where T: Sized { f: T }
    |                  - required by this bound in `OnlySized`
@@ -16,6 +7,6 @@ LL | struct OnlySized<T> where T: Sized { f: T }
 LL |     type Assoc = OnlySized<<T as Foo>::Item>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0275`.
index 5043fe5c08f515d238611c6e838d7a85fbde6162..8f8cb679e9c0e8c7815fa0a85a1d5f6c2293c771 100644 (file)
@@ -3,7 +3,6 @@
 // proven when a bound and a where clause of an associated type are the same.
 
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete
 #![feature(trivial_bounds)]
 
 trait Print {
index 400b664f97ca9401b097ec69830108a8590a8db2..fac62fef1ecff0094f9a50ad0259babd5dde441d 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/projection-bound-cycle.rs:5:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
-  --> $DIR/projection-bound-cycle.rs:47:5
+  --> $DIR/projection-bound-cycle.rs:46:5
    |
 LL | struct OnlySized<T> where T: Sized { f: T }
    |                  - required by this bound in `OnlySized`
@@ -16,6 +7,6 @@ LL | struct OnlySized<T> where T: Sized { f: T }
 LL |     type Assoc = OnlySized<<T as Foo>::Item>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0275`.
index 0024e127a982c94f65899d927be8c4b733b6d735..b976ee3261fcc7f9569d9fc2758dd50da656a0aa 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 pub trait X {
index aec878625661bef9bb668b8d7f0300515432dc84..315bef16c5f1377ac550d54b7186f5d553f5823e 100644 (file)
@@ -1,17 +1,17 @@
 error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/projection-type-lifetime-mismatch.rs:18:5
+  --> $DIR/projection-type-lifetime-mismatch.rs:17:5
    |
 LL |     x.m()
    |     ^^^^^ lifetime `'static` required
 
 error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/projection-type-lifetime-mismatch.rs:23:5
+  --> $DIR/projection-type-lifetime-mismatch.rs:22:5
    |
 LL |     x.m()
    |     ^^^^^ lifetime `'static` required
 
 error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/projection-type-lifetime-mismatch.rs:28:5
+  --> $DIR/projection-type-lifetime-mismatch.rs:27:5
    |
 LL |     x.m()
    |     ^^^^^ lifetime `'static` required
index 44528ca1da36e40f37c198167f0b2d087b3c24d2..2a9763457df753cd10955cbd59302d64dcc3915c 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 trait Shadow<'a> {
index d45ef83873af725b811cd28b1561c5a5f4f8c5aa..857757f8940dc41668d6f0de58e4376e7217dc46 100644 (file)
@@ -1,5 +1,5 @@
 error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
-  --> $DIR/shadowing.rs:19:14
+  --> $DIR/shadowing.rs:18:14
    |
 LL | trait ShadowT<T> {
    |               - first use of `T`
@@ -7,7 +7,7 @@ LL |     type Bar<T>;
    |              ^ already used
 
 error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
-  --> $DIR/shadowing.rs:28:14
+  --> $DIR/shadowing.rs:27:14
    |
 LL | impl<T> NoShadowT<T> for Option<T> {
    |      - first use of `T`
@@ -15,7 +15,7 @@ LL |     type Bar<T> = i32;
    |              ^ already used
 
 error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
-  --> $DIR/shadowing.rs:14:14
+  --> $DIR/shadowing.rs:13:14
    |
 LL | impl<'a> NoShadow<'a> for &'a u32 {
    |      -- first declared here
@@ -23,7 +23,7 @@ LL |     type Bar<'a> = i32;
    |              ^^ lifetime `'a` already in scope
 
 error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
-  --> $DIR/shadowing.rs:5:14
+  --> $DIR/shadowing.rs:4:14
    |
 LL | trait Shadow<'a> {
    |              -- first declared here
index d814f7140d9299797405e6271a0544cd506eb242..2feff9f4c6f2ff3f64e191e5ac148064fd68018a 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 use std::fmt::Display;
index 997a550b0effb714a3cf023c7829ddc12b6ffbc4..559e6758a32af62d91893377f6be44c6843c3417 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-#![allow(incomplete_features)]
 
 trait StreamingIterator {
     type Item<'a> where Self: 'a;
index a8f1768ba261798e10392bae55865f0830c6fcc4..6429bb8159e1f9899debc6bce4e7d442e6148a3e 100644 (file)
@@ -1,12 +1,12 @@
 error[E0038]: the trait `StreamingIterator` cannot be made into an object
-  --> $DIR/trait-objects.rs:11:16
+  --> $DIR/trait-objects.rs:10:21
    |
 LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
    |
    = help: consider moving `Item` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/trait-objects.rs:5:10
+  --> $DIR/trait-objects.rs:4:10
    |
 LL | trait StreamingIterator {
    |       ----------------- this trait cannot be made into an object...
index 7bcc7ba752ad04b8c263c5ebf43ee93cea172f6d..8b40dac574a43c33fc1c6469fb416dbc44a63c26 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 pub trait X {
index 1c81d33ccfe7280f423c70a63d716a7d2cbb3dfd..772d027685d0831d2a8f78009d6495229fa94eb8 100644 (file)
@@ -1,5 +1,5 @@
 warning: unnecessary lifetime parameter `'a`
-  --> $DIR/unsatified-item-lifetime-bound.rs:5:12
+  --> $DIR/unsatified-item-lifetime-bound.rs:4:12
    |
 LL |     type Y<'a: 'static>;
    |            ^^^^^^^^^^^
@@ -7,39 +7,39 @@ LL |     type Y<'a: 'static>;
    = help: you can use the `'static` lifetime directly, in place of `'a`
 
 error[E0478]: lifetime bound not satisfied
-  --> $DIR/unsatified-item-lifetime-bound.rs:14:8
+  --> $DIR/unsatified-item-lifetime-bound.rs:13:8
    |
 LL |     f: <T as X>::Y<'a>,
    |        ^^^^^^^^^^^^^^^
    |
-note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 13:10
-  --> $DIR/unsatified-item-lifetime-bound.rs:13:10
+note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 12:10
+  --> $DIR/unsatified-item-lifetime-bound.rs:12:10
    |
 LL | struct B<'a, T: for<'r> X<Y<'r> = &'r ()>> {
    |          ^^
    = note: but lifetime parameter must outlive the static lifetime
 
 error[E0478]: lifetime bound not satisfied
-  --> $DIR/unsatified-item-lifetime-bound.rs:19:8
+  --> $DIR/unsatified-item-lifetime-bound.rs:18:8
    |
 LL |     f: <T as X>::Y<'a>,
    |        ^^^^^^^^^^^^^^^
    |
-note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 18:10
-  --> $DIR/unsatified-item-lifetime-bound.rs:18:10
+note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 17:10
+  --> $DIR/unsatified-item-lifetime-bound.rs:17:10
    |
 LL | struct C<'a, T: X> {
    |          ^^
    = note: but lifetime parameter must outlive the static lifetime
 
 error[E0478]: lifetime bound not satisfied
-  --> $DIR/unsatified-item-lifetime-bound.rs:24:8
+  --> $DIR/unsatified-item-lifetime-bound.rs:23:8
    |
 LL |     f: <() as X>::Y<'a>,
    |        ^^^^^^^^^^^^^^^^
    |
-note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 23:10
-  --> $DIR/unsatified-item-lifetime-bound.rs:23:10
+note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 22:10
+  --> $DIR/unsatified-item-lifetime-bound.rs:22:10
    |
 LL | struct D<'a> {
    |          ^^
index 99d5bcf2bace9a3cb6abb00bf404c0f157fbcaad..6466bf98dfc8fc0f83e05fc6b1a615fa3d390da8 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
 trait ATy {
index 5d612284a21873ebef696a19e25ac31a8ab9c65f..d2482b2998b9ba8ca812434839c2b263678f33dd 100644 (file)
@@ -1,17 +1,17 @@
 error[E0477]: the type `&'b ()` does not fulfill the required lifetime
-  --> $DIR/unsatisfied-outlives-bound.rs:9:5
+  --> $DIR/unsatisfied-outlives-bound.rs:8:5
    |
 LL |     type Item<'a> = &'b ();
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: type must outlive the lifetime `'a` as defined on the associated item at 9:15
-  --> $DIR/unsatisfied-outlives-bound.rs:9:15
+note: type must outlive the lifetime `'a` as defined on the associated item at 8:15
+  --> $DIR/unsatisfied-outlives-bound.rs:8:15
    |
 LL |     type Item<'a> = &'b ();
    |               ^^
 
 error[E0477]: the type `&'a ()` does not fulfill the required lifetime
-  --> $DIR/unsatisfied-outlives-bound.rs:18:5
+  --> $DIR/unsatisfied-outlives-bound.rs:17:5
    |
 LL |     type Item<'a> = &'a ();
    |     ^^^^^^^^^^^^^^^^^^^^^^^
index 36db80706b4999cd0b3470def52b629d7f3833c1..7bc250ee87b944dc50cf4f0714923f5ce893bb4f 100644 (file)
@@ -1,7 +1,6 @@
 // check-pass
 // issue #69184
 #![feature(generic_associated_types)]
-#![allow(incomplete_features)]
 
 trait A {
     type B<'a>;
index b560cc2ce7060d33f03ca8c61584136de9a5e8c7..12db143e474492a8e79a72869082feadbc303502 100644 (file)
 // compatibility concern.
 
 struct Snobound<'a, P = Self> { x: Option<&'a P> }
-//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
+//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735]
 
 enum Enobound<'a, P = Self> { A, B(Option<&'a P>) }
-//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
+//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735]
 
 union Unobound<'a, P = Self> { x: i32, y: Option<&'a P> }
-//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
+//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735]
 
 // Disallowing `Self` in defaults sidesteps need to check the bounds
 // on the defaults in cases like these.
 
 struct Ssized<'a, P: Sized = [Self]> { x: Option<&'a P> }
-//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
+//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735]
 
 enum Esized<'a, P: Sized = [Self]> { A, B(Option<&'a P>) }
-//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
+//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735]
 
 union Usized<'a, P: Sized = [Self]> { x: i32, y: Option<&'a P> }
-//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
+//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735]
 
 fn demo_usages() {
     // An ICE means you only get the error from the first line of the
index 689ffbd0febc2e7bf1ea8a7c076b0bf98f3c7158..f3a550801b9bd57084de7633e165b38eb6f0d223 100644 (file)
@@ -1,38 +1,38 @@
-error[E0735]: type parameters cannot use `Self` in their defaults
+error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:13:25
    |
 LL | struct Snobound<'a, P = Self> { x: Option<&'a P> }
-   |                         ^^^^ `Self` in type parameter default
+   |                         ^^^^ `Self` in generic parameter default
 
-error[E0735]: type parameters cannot use `Self` in their defaults
+error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:16:23
    |
 LL | enum Enobound<'a, P = Self> { A, B(Option<&'a P>) }
-   |                       ^^^^ `Self` in type parameter default
+   |                       ^^^^ `Self` in generic parameter default
 
-error[E0735]: type parameters cannot use `Self` in their defaults
+error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:19:24
    |
 LL | union Unobound<'a, P = Self> { x: i32, y: Option<&'a P> }
-   |                        ^^^^ `Self` in type parameter default
+   |                        ^^^^ `Self` in generic parameter default
 
-error[E0735]: type parameters cannot use `Self` in their defaults
+error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:25:31
    |
 LL | struct Ssized<'a, P: Sized = [Self]> { x: Option<&'a P> }
-   |                               ^^^^ `Self` in type parameter default
+   |                               ^^^^ `Self` in generic parameter default
 
-error[E0735]: type parameters cannot use `Self` in their defaults
+error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:28:29
    |
 LL | enum Esized<'a, P: Sized = [Self]> { A, B(Option<&'a P>) }
-   |                             ^^^^ `Self` in type parameter default
+   |                             ^^^^ `Self` in generic parameter default
 
-error[E0735]: type parameters cannot use `Self` in their defaults
+error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:31:30
    |
 LL | union Usized<'a, P: Sized = [Self]> { x: i32, y: Option<&'a P> }
-   |                              ^^^^ `Self` in type parameter default
+   |                              ^^^^ `Self` in generic parameter default
 
 error: aborting due to 6 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 e3445a4b80f7b00564a98746ccd9330a0e839ff9..ffb9f9eed41fb92a1f20c322c893dff491fbf900 100644 (file)
@@ -8,7 +8,7 @@
 #![feature /* 0#0 */(no_core)]
 #![no_core /* 0#0 */]
 
-macro_rules! foo /* 0#0 */ { ($ x : ident) => { y + $ x } }
+macro_rules! foo /* 0#0 */ { ($x : ident) => { y + $x } }
 
 fn bar /* 0#0 */() {
     let x /* 0#0 */ = 1;
@@ -19,10 +19,10 @@ 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 }
+crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
+crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "foo")
 
 SyntaxContexts:
-#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
-#1: parent: #0, outer_mark: (ExpnId(1), SemiTransparent)
+#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque)
+#1: parent: #0, outer_mark: (crate0::{{expn1}}, SemiTransparent)
 */
index 6500a2a55f6677d807922ec67f2cff89d53f6fe3..1c81c69620165df971959f6fc3ecb7d024f75f99 100644 (file)
@@ -3,6 +3,8 @@ error[E0726]: implicit elided lifetime not allowed here
    |
 LL | impl MyTrait for Foo {
    |                  ^^^- help: indicate the anonymous lifetime: `<'_>`
+   |
+   = note: assuming a `'static` lifetime...
 
 error: aborting due to previous error
 
index ad97cb0abd6239bc34ba3c0f04e0034a0ad0e8e8..735f01379f09fc4f50ceb45157e0543f25d9a483 100644 (file)
@@ -3,6 +3,8 @@ error[E0726]: implicit elided lifetime not allowed here
    |
 LL | impl MyTrait for u32 {
    |      ^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+   |
+   = note: assuming a `'static` lifetime...
 
 error: aborting due to previous error
 
index 087f4582b21c3b3db46753486e2e479980b3444e..c2fbbf94fd66623678df17d392e4507993b2330e 100644 (file)
@@ -12,7 +12,6 @@ fn main() {
 fn cycle1() -> impl Clone {
     //~^ ERROR cycle detected
     send(cycle2().clone());
-    //~^ ERROR cannot be sent between threads safely
 
     Rc::new(Cell::new(5))
 }
index e578c4b4f819ee79581cbb3c1d2ec06c078b836e..3eb141cc2bb55276341e1b22549c3aa553c0fb74 100644 (file)
@@ -36,37 +36,37 @@ LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires computing type of `cycle2::{opaque#0}`...
-  --> $DIR/auto-trait-leak.rs:20:16
+  --> $DIR/auto-trait-leak.rs:19:16
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
 note: ...which requires borrow-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires unsafety-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires building MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -84,22 +84,6 @@ LL | |     Rc::new(String::from("foo"))
 LL | | }
    | |_^
 
-error[E0277]: `Rc<String>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak.rs:14:5
-   |
-LL | fn send<T: Send>(_: T) {}
-   |            ---- required by this bound in `send`
-...
-LL |     send(cycle2().clone());
-   |     ^^^^ `Rc<String>` cannot be sent between threads safely
-...
-LL | fn cycle2() -> impl Clone {
-   |                ---------- within this `impl Clone`
-   |
-   = help: within `impl Clone`, the trait `Send` is not implemented for `Rc<String>`
-   = note: required because it appears within the type `impl Clone`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0277, E0391.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/impl-trait/binding-without-value.rs b/src/test/ui/impl-trait/binding-without-value.rs
deleted file mode 100644 (file)
index 6a97f28..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#![allow(incomplete_features)]
-#![feature(impl_trait_in_bindings)]
-
-fn foo() {
-    let _ : impl Copy;
-    //~^ ERROR cannot resolve opaque type
-}
-
-fn main() {}
diff --git a/src/test/ui/impl-trait/binding-without-value.stderr b/src/test/ui/impl-trait/binding-without-value.stderr
deleted file mode 100644 (file)
index 0d2faea..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0720]: cannot resolve opaque type
-  --> $DIR/binding-without-value.rs:5:13
-   |
-LL |     let _ : impl Copy;
-   |         -   ^^^^^^^^^ cannot resolve opaque type
-   |         |
-   |         this binding might not have a concrete type
-   |
-help: set the binding to a value for a concrete type to be resolved
-   |
-LL |     let _ : impl Copy = /* value */;
-   |                       ^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/bindings-opaque.rs b/src/test/ui/impl-trait/bindings-opaque.rs
deleted file mode 100644 (file)
index d1f42be..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#![feature(impl_trait_in_bindings)]
-//~^ WARN the feature `impl_trait_in_bindings` is incomplete
-
-const FOO: impl Copy = 42;
-
-static BAR: impl Copy = 42;
-
-fn main() {
-    let foo: impl Copy = 42;
-
-    let _ = FOO.count_ones();
-//~^ ERROR no method
-    let _ = BAR.count_ones();
-//~^ ERROR no method
-    let _ = foo.count_ones();
-//~^ ERROR no method
-}
diff --git a/src/test/ui/impl-trait/bindings-opaque.stderr b/src/test/ui/impl-trait/bindings-opaque.stderr
deleted file mode 100644 (file)
index 170bd46..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/bindings-opaque.rs:1:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-error[E0599]: no method named `count_ones` found for opaque type `impl Copy` in the current scope
-  --> $DIR/bindings-opaque.rs:11:17
-   |
-LL |     let _ = FOO.count_ones();
-   |                 ^^^^^^^^^^ method not found in `impl Copy`
-
-error[E0599]: no method named `count_ones` found for opaque type `impl Copy` in the current scope
-  --> $DIR/bindings-opaque.rs:13:17
-   |
-LL |     let _ = BAR.count_ones();
-   |                 ^^^^^^^^^^ method not found in `impl Copy`
-
-error[E0599]: no method named `count_ones` found for opaque type `impl Copy` in the current scope
-  --> $DIR/bindings-opaque.rs:15:17
-   |
-LL |     let _ = foo.count_ones();
-   |                 ^^^^^^^^^^ method not found in `impl Copy`
-
-error: aborting due to 3 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/impl-trait/bindings.rs b/src/test/ui/impl-trait/bindings.rs
deleted file mode 100644 (file)
index fd79ba6..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#![feature(impl_trait_in_bindings)]
-//~^ WARN the feature `impl_trait_in_bindings` is incomplete
-
-fn a<T: Clone>(x: T) {
-    const foo: impl Clone = x;
-    //~^ ERROR attempt to use a non-constant value in a constant
-}
-
-fn b<T: Clone>(x: T) {
-    let _ = move || {
-        const foo: impl Clone = x;
-        //~^ ERROR attempt to use a non-constant value in a constant
-    };
-}
-
-trait Foo<T: Clone> {
-    fn a(x: T) {
-        const foo: impl Clone = x;
-        //~^ ERROR attempt to use a non-constant value in a constant
-    }
-}
-
-impl<T: Clone> Foo<T> for i32 {
-    fn a(x: T) {
-        const foo: impl Clone = x;
-        //~^ ERROR attempt to use a non-constant value in a constant
-    }
-}
-
-fn main() { }
diff --git a/src/test/ui/impl-trait/bindings.stderr b/src/test/ui/impl-trait/bindings.stderr
deleted file mode 100644 (file)
index 4da49f4..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/bindings.rs:5:29
-   |
-LL |     const foo: impl Clone = x;
-   |     ---------               ^ non-constant value
-   |     |
-   |     help: consider using `let` instead of `const`: `let foo`
-
-error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/bindings.rs:11:33
-   |
-LL |         const foo: impl Clone = x;
-   |         ---------               ^ non-constant value
-   |         |
-   |         help: consider using `let` instead of `const`: `let foo`
-
-error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/bindings.rs:18:33
-   |
-LL |         const foo: impl Clone = x;
-   |         ---------               ^ non-constant value
-   |         |
-   |         help: consider using `let` instead of `const`: `let foo`
-
-error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/bindings.rs:25:33
-   |
-LL |         const foo: impl Clone = x;
-   |         ---------               ^ non-constant value
-   |         |
-   |         help: consider using `let` instead of `const`: `let foo`
-
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/bindings.rs:1:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-error: aborting due to 4 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0435`.
index d3056fb8851257aced8142dcb3224fc6be1ab0d9..8ec06e534d14336bd569ab85a615539a542475b3 100644 (file)
@@ -1,15 +1,14 @@
 // edition:2018
 
-#![feature(impl_trait_in_bindings)]
-//~^ WARNING the feature `impl_trait_in_bindings` is incomplete
-
 // See issue 60414
 
 // Reduction to `impl Trait`
 
 struct Foo<T>(T);
 
-trait FooLike { type Output; }
+trait FooLike {
+    type Output;
+}
 
 impl<T> FooLike for Foo<T> {
     type Output = T;
@@ -23,7 +22,7 @@ mod impl_trait {
     }
 
     /// `T::Assoc` can't be normalized any further here.
-    fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> {
+    fn foo_fail<T: Trait>() -> impl FooLike<Output = T::Assoc> {
         //~^ ERROR: type mismatch
         Foo(())
     }
@@ -39,9 +38,9 @@ mod lifetimes {
     }
 
     /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further.
-    fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
-    //~^ ERROR: type mismatch
-    //~^^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
+    fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
+        //~^ ERROR: type mismatch
+        //~^^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
         Foo(())
     }
 }
index ba3a2e7f8d4c9445aff1b79fa3e2423dd1a3fad7..611543a19260b05863eb6a5fb51a12422a45d3a4 100644 (file)
@@ -1,45 +1,36 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/bound-normalization-fail.rs:3:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
 error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
-  --> $DIR/bound-normalization-fail.rs:26:32
+  --> $DIR/bound-normalization-fail.rs:25:32
    |
-LL |     fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> {
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()`
+LL |     fn foo_fail<T: Trait>() -> impl FooLike<Output = T::Assoc> {
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()`
    |
    = note: expected associated type `<T as impl_trait::Trait>::Assoc`
                          found type `()`
 help: consider constraining the associated type `<T as impl_trait::Trait>::Assoc` to `()`
    |
-LL |     fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output=T::Assoc> {
+LL |     fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
    |                         ^^^^^^^^^^^^
 
 error[E0760]: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
-  --> $DIR/bound-normalization-fail.rs:42:41
+  --> $DIR/bound-normalization-fail.rs:41:41
    |
-LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
-   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc`
-  --> $DIR/bound-normalization-fail.rs:42:41
+  --> $DIR/bound-normalization-fail.rs:41:41
    |
-LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
-   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()`
+LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()`
    |
    = note: expected associated type `<T as lifetimes::Trait<'static>>::Assoc`
                          found type `()`
 help: consider constraining the associated type `<T as lifetimes::Trait<'static>>::Assoc` to `()`
    |
-LL |     fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output=T::Assoc> {
+LL |     fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
    |                                 ^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0271, E0760.
 For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/impl-trait/bound-normalization-pass.default.stderr b/src/test/ui/impl-trait/bound-normalization-pass.default.stderr
deleted file mode 100644 (file)
index ef3cb74..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/bound-normalization-pass.rs:8:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-warning: 1 warning emitted
-
index 6a01753b4c29caafad20bfc95700a511a56e4359..4218bc5206596b84d0e9b4f5c988fe5e8079dab0 100644 (file)
@@ -5,8 +5,6 @@
 //-^ To make this the regression test for #75962.
 
 #![feature(min_type_alias_impl_trait)]
-#![feature(impl_trait_in_bindings)]
-//~^ WARNING the feature `impl_trait_in_bindings` is incomplete
 
 // See issue 60414
 
@@ -14,7 +12,9 @@
 
 struct Foo<T>(T);
 
-trait FooLike { type Output; }
+trait FooLike {
+    type Output;
+}
 
 impl<T> FooLike for Foo<T> {
     type Output = T;
@@ -28,7 +28,7 @@ mod impl_trait {
     }
 
     /// `T::Assoc` should be normalized to `()` here.
-    fn foo_pass<T: Trait<Assoc=()>>() -> impl FooLike<Output=T::Assoc> {
+    fn foo_pass<T: Trait<Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
         Foo(())
     }
 }
@@ -45,40 +45,20 @@ mod lifetimes {
     /// Like above.
     ///
     /// FIXME(#51525) -- the shorter notation `T::Assoc` winds up referencing `'static` here
-    fn foo2_pass<'a, T: Trait<'a, Assoc=()> + 'a>(
-    ) -> impl FooLike<Output=<T as Trait<'a>>::Assoc> + 'a {
+    fn foo2_pass<'a, T: Trait<'a, Assoc = ()> + 'a>()
+    -> impl FooLike<Output = <T as Trait<'a>>::Assoc> + 'a {
         Foo(())
     }
 
     /// Normalization to type containing bound region.
     ///
     /// FIXME(#51525) -- the shorter notation `T::Assoc` winds up referencing `'static` here
-    fn foo2_pass2<'a, T: Trait<'a, Assoc=&'a ()> + 'a>(
-    ) -> impl FooLike<Output=<T as Trait<'a>>::Assoc> + 'a {
+    fn foo2_pass2<'a, T: Trait<'a, Assoc = &'a ()> + 'a>()
+    -> impl FooLike<Output = <T as Trait<'a>>::Assoc> + 'a {
         Foo(&())
     }
 }
 
-// Reduction using `impl Trait` in bindings
-
-mod impl_trait_in_bindings {
-    struct Foo;
-
-    trait FooLike { type Output; }
-
-    impl FooLike for Foo {
-        type Output = u32;
-    }
-
-    trait Trait {
-        type Assoc;
-    }
-
-    fn foo<T: Trait<Assoc=u32>>() {
-        let _: impl FooLike<Output=T::Assoc> = Foo;
-    }
-}
-
 // The same applied to `type Foo = impl Bar`s
 
 mod opaque_types {
diff --git a/src/test/ui/impl-trait/bound-normalization-pass.sa.stderr b/src/test/ui/impl-trait/bound-normalization-pass.sa.stderr
deleted file mode 100644 (file)
index ef3cb74..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/bound-normalization-pass.rs:8:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.rs b/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.rs
deleted file mode 100644 (file)
index fd8fe5f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// check-pass
-
-#![feature(impl_trait_in_bindings)]
-//~^ WARN the feature `impl_trait_in_bindings` is incomplete
-
-const _: impl Fn() = ||();
-
-fn main() {}
diff --git a/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.stderr b/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.stderr
deleted file mode 100644 (file)
index 715671c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/impl-trait-in-bindings-issue-73003.rs:3:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/impl-trait/impl-trait-in-bindings.rs b/src/test/ui/impl-trait/impl-trait-in-bindings.rs
deleted file mode 100644 (file)
index c7fae45..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// run-pass
-
-#![feature(impl_trait_in_bindings)]
-//~^ WARN the feature `impl_trait_in_bindings` is incomplete
-
-use std::fmt::Debug;
-
-const FOO: impl Debug + Clone + PartialEq<i32> = 42;
-
-static BAR: impl Debug + Clone + PartialEq<i32> = 42;
-
-fn a<T: Clone>(x: T) {
-    let y: impl Clone = x;
-    let _ = y.clone();
-}
-
-fn b<T: Clone>(x: T) {
-    let f = move || {
-        let y: impl Clone = x;
-        let _ = y.clone();
-    };
-    f();
-}
-
-trait Foo<T: Clone> {
-    fn a(x: T) {
-        let y: impl Clone = x;
-        let _ = y.clone();
-    }
-}
-
-impl<T: Clone> Foo<T> for i32 {
-    fn a(x: T) {
-        let y: impl Clone = x;
-        let _ = y.clone();
-    }
-}
-
-fn main() {
-    let foo: impl Debug + Clone + PartialEq<i32> = 42;
-
-    assert_eq!(FOO.clone(), 42);
-    assert_eq!(BAR.clone(), 42);
-    assert_eq!(foo.clone(), 42);
-
-    a(42);
-    b(42);
-    i32::a(42);
-}
diff --git a/src/test/ui/impl-trait/impl-trait-in-bindings.stderr b/src/test/ui/impl-trait/impl-trait-in-bindings.stderr
deleted file mode 100644 (file)
index bf739d4..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/impl-trait-in-bindings.rs:3:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/impl-trait/issue-57200.rs b/src/test/ui/impl-trait/issue-57200.rs
deleted file mode 100644 (file)
index e0c71d1..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Regression test for #57200
-// FIXME: The error is temporary hack, we'll revisit here at some point.
-
-#![feature(impl_trait_in_bindings)]
-#![allow(incomplete_features)]
-
-fn bug<'a, 'b, T>()
-where
-    'a: 'b,
-{
-    let f: impl Fn(&'a T) -> &'b T = |x| x;
-    //~^ ERROR: lifetimes in impl Trait types in bindings are not currently supported
-}
-
-fn main() {}
diff --git a/src/test/ui/impl-trait/issue-57200.stderr b/src/test/ui/impl-trait/issue-57200.stderr
deleted file mode 100644 (file)
index b44f332..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: lifetimes in impl Trait types in bindings are not currently supported
-  --> $DIR/issue-57200.rs:11:12
-   |
-LL |     let f: impl Fn(&'a T) -> &'b T = |x| x;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/impl-trait/issue-57201.rs b/src/test/ui/impl-trait/issue-57201.rs
deleted file mode 100644 (file)
index c1a98d8..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Regression test for #57201
-// FIXME: The error is temporary hack, we'll revisit here at some point.
-
-#![feature(impl_trait_in_bindings)]
-#![allow(incomplete_features)]
-
-fn bug<'a, 'b, T>()
-where
-    'a: 'b,
-{
-    let f: &impl Fn(&'a T) -> &'b T = &|x| x;
-    //~^ ERROR: lifetimes in impl Trait types in bindings are not currently supported
-}
-
-fn main() {}
diff --git a/src/test/ui/impl-trait/issue-57201.stderr b/src/test/ui/impl-trait/issue-57201.stderr
deleted file mode 100644 (file)
index 462b17b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: lifetimes in impl Trait types in bindings are not currently supported
-  --> $DIR/issue-57201.rs:11:13
-   |
-LL |     let f: &impl Fn(&'a T) -> &'b T = &|x| x;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/impl-trait/issue-60473.rs b/src/test/ui/impl-trait/issue-60473.rs
deleted file mode 100644 (file)
index 2ef86f0..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Regression test for #60473
-
-#![feature(impl_trait_in_bindings)]
-#![allow(incomplete_features)]
-
-struct A<'a>(&'a ());
-
-trait Trait<T> {}
-
-impl<T> Trait<T> for () {}
-
-fn main() {
-    let x: impl Trait<A> = ();
-    //~^ ERROR: missing lifetime specifier
-}
diff --git a/src/test/ui/impl-trait/issue-60473.stderr b/src/test/ui/impl-trait/issue-60473.stderr
deleted file mode 100644 (file)
index 367b5db..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0106]: missing lifetime specifier
-  --> $DIR/issue-60473.rs:13:23
-   |
-LL |     let x: impl Trait<A> = ();
-   |                       ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL | fn main<'a>() {
-LL |     let x: impl Trait<A<'a>> = ();
-   |
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/impl-trait/issue-67166.rs b/src/test/ui/impl-trait/issue-67166.rs
deleted file mode 100644 (file)
index efa6755..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// Regression test for #67166
-
-#![feature(impl_trait_in_bindings)]
-#![allow(incomplete_features)]
-
-pub fn run() {
-    let _foo: Box<impl Copy + '_> = Box::new(());
-    //~^ ERROR: missing lifetime specifier
-}
-
-fn main() {}
diff --git a/src/test/ui/impl-trait/issue-67166.stderr b/src/test/ui/impl-trait/issue-67166.stderr
deleted file mode 100644 (file)
index 14c7868..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0106]: missing lifetime specifier
-  --> $DIR/issue-67166.rs:7:31
-   |
-LL |     let _foo: Box<impl Copy + '_> = Box::new(());
-   |                               ^^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL | pub fn run<'a>() {
-LL |     let _foo: Box<impl Copy + 'a> = Box::new(());
-   |
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/impl-trait/issue-69840.rs b/src/test/ui/impl-trait/issue-69840.rs
deleted file mode 100644 (file)
index b270f88..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// check-pass
-
-#![feature(impl_trait_in_bindings)]
-#![allow(incomplete_features)]
-
-struct A<'a>(&'a ());
-
-trait Trait<T> {}
-
-impl<T> Trait<T> for () {}
-
-pub fn foo<'a>() {
-    let _x: impl Trait<A<'a>> = ();
-}
-
-fn main() {}
diff --git a/src/test/ui/impl-trait/issue-86465.rs b/src/test/ui/impl-trait/issue-86465.rs
new file mode 100644 (file)
index 0000000..23a3748
--- /dev/null
@@ -0,0 +1,10 @@
+#![feature(min_type_alias_impl_trait)]
+
+type X<'a, 'b> = impl std::fmt::Debug;
+
+fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
+    //~^ ERROR concrete type differs from previous defining opaque type use
+    (a, a)
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-86465.stderr b/src/test/ui/impl-trait/issue-86465.stderr
new file mode 100644 (file)
index 0000000..595b16a
--- /dev/null
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/issue-86465.rs:5:1
+   |
+LL | fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&'a u32`, got `&'b u32`
+   |
+note: previous use here
+  --> $DIR/issue-86465.rs:5:1
+   |
+LL | fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/issues/issue-54600.rs b/src/test/ui/impl-trait/issues/issue-54600.rs
new file mode 100644 (file)
index 0000000..7a64799
--- /dev/null
@@ -0,0 +1,7 @@
+use std::fmt::Debug;
+
+fn main() {
+    let x: Option<impl Debug> = Some(44_u32);
+    //~^ `impl Trait` not allowed outside of function and method return types
+    println!("{:?}", x);
+}
diff --git a/src/test/ui/impl-trait/issues/issue-54600.stderr b/src/test/ui/impl-trait/issues/issue-54600.stderr
new file mode 100644 (file)
index 0000000..4d0c32c
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-54600.rs:4:19
+   |
+LL |     let x: Option<impl Debug> = Some(44_u32);
+   |                   ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-54840.rs b/src/test/ui/impl-trait/issues/issue-54840.rs
new file mode 100644 (file)
index 0000000..030d571
--- /dev/null
@@ -0,0 +1,7 @@
+use std::ops::Add;
+
+fn main() {
+    let i: i32 = 0;
+    let j: &impl Add = &i;
+    //~^ `impl Trait` not allowed outside of function and method return types
+}
diff --git a/src/test/ui/impl-trait/issues/issue-54840.stderr b/src/test/ui/impl-trait/issues/issue-54840.stderr
new file mode 100644 (file)
index 0000000..b8046b7
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-54840.rs:5:13
+   |
+LL |     let j: &impl Add = &i;
+   |             ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-58504.rs b/src/test/ui/impl-trait/issues/issue-58504.rs
new file mode 100644 (file)
index 0000000..aac33b3
--- /dev/null
@@ -0,0 +1,12 @@
+#![feature(generators, generator_trait, never_type)]
+
+use std::ops::Generator;
+
+fn mk_gen() -> impl Generator<Return=!, Yield=()> {
+    || { loop { yield; } }
+}
+
+fn main() {
+    let gens: [impl Generator<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ];
+    //~^ `impl Trait` not allowed outside of function and method return types
+}
diff --git a/src/test/ui/impl-trait/issues/issue-58504.stderr b/src/test/ui/impl-trait/issues/issue-58504.stderr
new file mode 100644 (file)
index 0000000..ff1010f
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-58504.rs:10:16
+   |
+LL |     let gens: [impl Generator<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ];
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-58956.rs b/src/test/ui/impl-trait/issues/issue-58956.rs
new file mode 100644 (file)
index 0000000..5fe18b6
--- /dev/null
@@ -0,0 +1,14 @@
+trait Lam {}
+
+pub struct B;
+impl Lam for B {}
+pub struct Wrap<T>(T);
+
+const _A: impl Lam = {
+    //~^ `impl Trait` not allowed outside of function and method return types
+    let x: Wrap<impl Lam> = Wrap(B);
+    //~^ `impl Trait` not allowed outside of function and method return types
+    x.0
+};
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-58956.stderr b/src/test/ui/impl-trait/issues/issue-58956.stderr
new file mode 100644 (file)
index 0000000..00ebf17
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-58956.rs:7:11
+   |
+LL | const _A: impl Lam = {
+   |           ^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-58956.rs:9:17
+   |
+LL |     let x: Wrap<impl Lam> = Wrap(B);
+   |                 ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0562`.
index 8e42b9d46db390b9d61f6e6ee7e6e764f7f33adb..1f4e3f78afa45e23d368ccd218d967cb9aa86b71 100644 (file)
@@ -1,5 +1,5 @@
 error[E0271]: type mismatch resolving `<Bar as Iterator>::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
-  --> $DIR/issue-70877.rs:11:12
+  --> $DIR/issue-70877.rs:10:12
    |
 LL | type FooRet = impl std::fmt::Debug;
    |               -------------------- the found opaque type
index 8e42b9d46db390b9d61f6e6ee7e6e764f7f33adb..1f4e3f78afa45e23d368ccd218d967cb9aa86b71 100644 (file)
@@ -1,5 +1,5 @@
 error[E0271]: type mismatch resolving `<Bar as Iterator>::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
-  --> $DIR/issue-70877.rs:11:12
+  --> $DIR/issue-70877.rs:10:12
    |
 LL | type FooRet = impl std::fmt::Debug;
    |               -------------------- the found opaque type
index 7ca0f90e2dced687a3fbda9124f686e0e365059d..29aa705ef9d4df21dba80e04e00137f90d19f638 100644 (file)
@@ -1,7 +1,6 @@
 // revisions: min_tait full_tait
 #![feature(min_type_alias_impl_trait)]
 #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
-#![feature(impl_trait_in_bindings)]
 #![allow(incomplete_features)]
 
 type FooArg<'a> = &'a dyn ToString;
diff --git a/src/test/ui/impl-trait/issues/issue-70971.rs b/src/test/ui/impl-trait/issues/issue-70971.rs
new file mode 100644 (file)
index 0000000..d4dc2fd
--- /dev/null
@@ -0,0 +1,4 @@
+fn main() {
+    let x : (impl Copy,) = (true,);
+    //~^ `impl Trait` not allowed outside of function and method return types
+}
diff --git a/src/test/ui/impl-trait/issues/issue-70971.stderr b/src/test/ui/impl-trait/issues/issue-70971.stderr
new file mode 100644 (file)
index 0000000..31993da
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-70971.rs:2:14
+   |
+LL |     let x : (impl Copy,) = (true,);
+   |              ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-78721.rs b/src/test/ui/impl-trait/issues/issue-78721.rs
deleted file mode 100644 (file)
index f7dbef9..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// edition:2018
-
-#![feature(impl_trait_in_bindings)]
-//~^ WARN the feature `impl_trait_in_bindings` is incomplete
-
-struct Bug {
-    V1: [(); {
-        let f: impl core::future::Future<Output = u8> = async { 1 };
-        //~^ ERROR `async` blocks are not allowed in constants
-        //~| ERROR destructors cannot be evaluated at compile-time
-        1
-    }],
-}
-
-fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-78721.stderr b/src/test/ui/impl-trait/issues/issue-78721.stderr
deleted file mode 100644 (file)
index d5712dd..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-78721.rs:3:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-error[E0658]: `async` blocks are not allowed in constants
-  --> $DIR/issue-78721.rs:8:57
-   |
-LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
-   |                                                         ^^^^^^^^^^^
-   |
-   = note: see issue #85368 <https://github.com/rust-lang/rust/issues/85368> for more information
-   = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
-
-error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/issue-78721.rs:8:13
-   |
-LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
-   |             ^ constants cannot evaluate destructors
-...
-LL |     }],
-   |     - value is dropped here
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-Some errors have detailed explanations: E0493, E0658.
-For more information about an error, try `rustc --explain E0493`.
index 7a4be1d5f6df271a84a543817b333b8a03d13713..728644f7579917960b8b85791bd759baafcb9730 100644 (file)
@@ -7,33 +7,26 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-78722.rs:7:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-error[E0658]: `async` blocks are not allowed in constants
-  --> $DIR/issue-78722.rs:17:20
+error[E0308]: mismatched types
+  --> $DIR/issue-78722.rs:15:20
    |
+LL | type F = impl core::future::Future<Output = u8>;
+   |          -------------------------------------- the expected opaque type
+...
 LL |         let f: F = async { 1 };
-   |                    ^^^^^^^^^^^
+   |                -   ^^^^^^^^^^^ expected opaque type, found a different opaque type
+   |                |
+   |                expected due to this
+   | 
+  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
-   = note: see issue #85368 <https://github.com/rust-lang/rust/issues/85368> for more information
-   = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
-
-error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/issue-78722.rs:17:13
+LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
+   |                                           ------------------------------- the found opaque type
    |
-LL |         let f: F = async { 1 };
-   |             ^ constants cannot evaluate destructors
-...
-LL |     }],
-   |     - value is dropped here
+   = note: expected opaque type `impl Future` (opaque type at <$DIR/issue-78722.rs:8:10>)
+              found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
+   = note: distinct uses of `impl Trait` result in different opaque types
 
-error: aborting due to 2 previous errors; 2 warnings emitted
+error: aborting due to previous error; 1 warning emitted
 
-Some errors have detailed explanations: E0493, E0658.
-For more information about an error, try `rustc --explain E0493`.
+For more information about this error, try `rustc --explain E0308`.
index 131033063d209579973c5a80f0a3d3c607de69bb..221b23ae3d2adf08de38f81dad208f370fc77277 100644 (file)
@@ -1,31 +1,23 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-78722.rs:7:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-error[E0658]: `async` blocks are not allowed in constants
-  --> $DIR/issue-78722.rs:17:20
+error[E0308]: mismatched types
+  --> $DIR/issue-78722.rs:15:20
    |
+LL | type F = impl core::future::Future<Output = u8>;
+   |          -------------------------------------- the expected opaque type
+...
 LL |         let f: F = async { 1 };
-   |                    ^^^^^^^^^^^
+   |                -   ^^^^^^^^^^^ expected opaque type, found a different opaque type
+   |                |
+   |                expected due to this
+   | 
+  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
-   = note: see issue #85368 <https://github.com/rust-lang/rust/issues/85368> for more information
-   = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
-
-error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/issue-78722.rs:17:13
+LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
+   |                                           ------------------------------- the found opaque type
    |
-LL |         let f: F = async { 1 };
-   |             ^ constants cannot evaluate destructors
-...
-LL |     }],
-   |     - value is dropped here
+   = note: expected opaque type `impl Future` (opaque type at <$DIR/issue-78722.rs:8:10>)
+              found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
+   = note: distinct uses of `impl Trait` result in different opaque types
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0493, E0658.
-For more information about an error, try `rustc --explain E0493`.
+For more information about this error, try `rustc --explain E0308`.
index 0999ec63e032c5cd4dec5a5d08033e579152b6fd..480b55eed21e2046c1c9e0b14b4f43cac489b38c 100644 (file)
@@ -4,8 +4,6 @@
 #![feature(min_type_alias_impl_trait)]
 #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
 //[full_tait]~^ WARN incomplete
-#![feature(impl_trait_in_bindings)]
-//~^ WARN the feature `impl_trait_in_bindings` is incomplete
 
 type F = impl core::future::Future<Output = u8>;
 
@@ -15,8 +13,7 @@ struct Bug {
             async {}
         }
         let f: F = async { 1 };
-        //~^ ERROR `async` blocks are not allowed in constants
-        //~| ERROR destructors cannot be evaluated at compile-time
+        //~^ ERROR mismatched types [E0308]
         1
     }],
 }
diff --git a/src/test/ui/impl-trait/issues/issue-79099.rs b/src/test/ui/impl-trait/issues/issue-79099.rs
new file mode 100644 (file)
index 0000000..f72533d
--- /dev/null
@@ -0,0 +1,10 @@
+struct Bug {
+    V1: [(); {
+        let f: impl core::future::Future<Output = u8> = async { 1 };
+        //~^ `impl Trait` not allowed outside of function and method return types
+        //~| expected identifier
+        1
+    }],
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-79099.stderr b/src/test/ui/impl-trait/issues/issue-79099.stderr
new file mode 100644 (file)
index 0000000..121536d
--- /dev/null
@@ -0,0 +1,20 @@
+error: expected identifier, found `1`
+  --> $DIR/issue-79099.rs:3:65
+   |
+LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
+   |                                                         -----   ^ expected identifier
+   |                                                         |
+   |                                                         `async` blocks are only allowed in Rust 2018 or later
+   |
+   = help: set `edition = "2018"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-79099.rs:3:16
+   |
+LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0562`.
index d9d2e3929b10c2cd3778b12f1527a6dbe814e09e..773cd0b81cc53ff6a2960ebee538d402a094ce3b 100644 (file)
@@ -1,8 +1,8 @@
 struct Foo<T = impl Copy>(T);
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 type Result<T, E = impl std::error::Error> = std::result::Result<T, E>;
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // should not cause ICE
 fn x() -> Foo {
index eef6844adfccba365e4fb96ac8444d4819174068..d44dcf1f7fa2377c70220369bcab8dc95cb071de 100644 (file)
@@ -1,10 +1,10 @@
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/issue-83929-impl-trait-in-generic-default.rs:1:16
    |
 LL | struct Foo<T = impl Copy>(T);
    |                ^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/issue-83929-impl-trait-in-generic-default.rs:4:20
    |
 LL | type Result<T, E = impl std::error::Error> = std::result::Result<T, E>;
diff --git a/src/test/ui/impl-trait/issues/issue-84919.rs b/src/test/ui/impl-trait/issues/issue-84919.rs
new file mode 100644 (file)
index 0000000..479bad9
--- /dev/null
@@ -0,0 +1,9 @@
+trait Trait {}
+impl Trait for () {}
+
+fn foo<'a: 'a>() {
+    let _x: impl Trait = ();
+    //~^ `impl Trait` not allowed outside of function and method return types
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-84919.stderr b/src/test/ui/impl-trait/issues/issue-84919.stderr
new file mode 100644 (file)
index 0000000..bb1bcfe
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-84919.rs:5:13
+   |
+LL |     let _x: impl Trait = ();
+   |             ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-86201.rs b/src/test/ui/impl-trait/issues/issue-86201.rs
new file mode 100644 (file)
index 0000000..8dc76f4
--- /dev/null
@@ -0,0 +1,13 @@
+#![feature(unboxed_closures)]
+#![feature(min_type_alias_impl_trait)]
+
+type FunType = impl Fn<()>;
+//~^ could not find defining uses
+static STATIC_FN: FunType = some_fn;
+//~^ mismatched types
+
+fn some_fn() {}
+
+fn main() {
+    let _: <FunType as FnOnce<()>>::Output = STATIC_FN();
+}
diff --git a/src/test/ui/impl-trait/issues/issue-86201.stderr b/src/test/ui/impl-trait/issues/issue-86201.stderr
new file mode 100644 (file)
index 0000000..b146009
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-86201.rs:6:29
+   |
+LL | type FunType = impl Fn<()>;
+   |                ----------- the expected opaque type
+LL |
+LL | static STATIC_FN: FunType = some_fn;
+   |                             ^^^^^^^ expected opaque type, found fn item
+   |
+   = note: expected opaque type `impl Fn<()>`
+                  found fn item `fn() {some_fn}`
+
+error: could not find defining uses
+  --> $DIR/issue-86201.rs:4:16
+   |
+LL | type FunType = impl Fn<()>;
+   |                ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/issues/issue-86642.rs b/src/test/ui/impl-trait/issues/issue-86642.rs
new file mode 100644 (file)
index 0000000..8953ff8
--- /dev/null
@@ -0,0 +1,8 @@
+static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
+    //~^ `impl Trait` not allowed outside of function and method return types
+    let res = (move |source| Ok(source))(source);
+    let res = res.or((move |source| Ok(source))(source));
+    res
+};
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-86642.stderr b/src/test/ui/impl-trait/issues/issue-86642.stderr
new file mode 100644 (file)
index 0000000..2fc0a6f
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-86642.rs:1:11
+   |
+LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-87295.rs b/src/test/ui/impl-trait/issues/issue-87295.rs
new file mode 100644 (file)
index 0000000..2f2bfe1
--- /dev/null
@@ -0,0 +1,18 @@
+trait Trait {
+    type Output;
+}
+impl Trait for () {
+    type Output = i32;
+}
+
+struct Struct<F>(F);
+impl<F> Struct<F> {
+    pub fn new(_: F) -> Self {
+        todo!()
+    }
+}
+
+fn main() {
+    let _do_not_waste: Struct<impl Trait<Output = i32>> = Struct::new(());
+    //~^ `impl Trait` not allowed outside of function and method return types
+}
diff --git a/src/test/ui/impl-trait/issues/issue-87295.stderr b/src/test/ui/impl-trait/issues/issue-87295.stderr
new file mode 100644 (file)
index 0000000..f5c7603
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-87295.rs:16:31
+   |
+LL |     let _do_not_waste: Struct<impl Trait<Output = i32>> = Struct::new(());
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
index 8f05ab3c4940c30e22f0f170108907dbeb31e65e..6800b37b5b175aaaee409116c67c9acefa9a4848 100644 (file)
@@ -6,3 +6,4 @@ LL |     foo::<String>('a');
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0632`.
index c980e9463e48ae383b377412b67cfaac37976414..db66d461095993f8fb9f5b3ad9a5c711dcadb30f 100644 (file)
@@ -8,3 +8,4 @@ LL |     evt.handle_event::<TestEvent, fn(TestEvent)>(|_evt| {
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0632`.
index 4372de245078fc930be3cb4a27dd1f30e337be7d..e9d620877345423f65e0683bad69c34df47ab0ce 100644 (file)
@@ -9,7 +9,7 @@ LL | fn elided(x: &i32) -> impl Copy { x }
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
    |
 LL | fn elided(x: &i32) -> impl Copy + '_ { x }
-   |                       ^^^^^^^^^^^^^^
+   |                                 ^^^^
 
 error: lifetime may not live long enough
   --> $DIR/must_outlive_least_region_or_bound.rs:5:32
@@ -23,7 +23,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
-   |                                ^^^^^^^^^^^^^^
+   |                                          ^^^^
 
 error: lifetime may not live long enough
   --> $DIR/must_outlive_least_region_or_bound.rs:7:46
index 3749c268a68b345e935cd57fd2d551d9a693d0a8..59c7e4d5f4e92b8aa0a8867f5e04120567f9a026 100644 (file)
@@ -34,13 +34,13 @@ LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                  |         nested `impl Trait` here
    |                                  outer `impl Trait`
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/nested_impl_trait.rs:8:32
    |
 LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
    |                                ^^^^^^^^^^^^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/nested_impl_trait.rs:25:42
    |
 LL | fn allowed_in_ret_type() -> impl Fn() -> impl Into<u32> {
index 0f89ec2475ccb59b5aa94d2cb89a942a9b3217b1..b9b2ce249f7bf5be81746a7399986fb943e98ab3 100644 (file)
@@ -95,7 +95,7 @@ LL | /     move || {
 LL | |         yield;
 LL | |         x;
 LL | |     }
-   | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 64:6 {()}]`
+   | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 64:6]`
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:67:35
@@ -117,7 +117,7 @@ LL | |         let x = generator_hold();
 LL | |         yield;
 LL | |         x;
 LL | |     }
-   | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 78:6 {impl Sized, ()}]`
+   | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 78:6]`
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:86:26
index 65178cc9d24c262f3b186f99310df4a36a8c5330..6c5264671a9120c3f397bc612d465736f98a4d24 100644 (file)
@@ -9,7 +9,7 @@ LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                           ^^^^
 
 error: lifetime may not live long enough
   --> $DIR/static-return-lifetime-infered.rs:9:37
@@ -23,7 +23,7 @@ LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
-   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                             ^^^^
 
 error: aborting due to 2 previous errors
 
index c3e21c81f03bea8a33e7253a6ac8252a42b156d7..4605e76ac96d28a44cb50f3563daee0b2be0d873 100644 (file)
@@ -13,61 +13,61 @@ fn in_adt_in_parameters(_: Vec<impl Debug>) { panic!() }
 
 // Disallowed
 fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 //~^^ ERROR nested `impl Trait` is not allowed
 
 // Disallowed
 fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 //~| ERROR nested `impl Trait` is not allowed
 
 // Disallowed
 fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 
 // Allowed
@@ -80,22 +80,22 @@ fn in_impl_Trait_in_return() -> impl IntoIterator<Item = impl IntoIterator> {
 
 // Disallowed
 struct InBraceStructField { x: impl Debug }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 struct InAdtInBraceStructField { x: Vec<impl Debug> }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 struct InTupleStructField(impl Debug);
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 enum InEnum {
     InBraceVariant { x: impl Debug },
-    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    //~^ ERROR `impl Trait` not allowed outside of function and method return types
     InTupleVariant(impl Debug),
-    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    //~^ ERROR `impl Trait` not allowed outside of function and method return types
 }
 
 // Allowed
@@ -106,7 +106,7 @@ trait InTraitDefnParameters {
 // Disallowed
 trait InTraitDefnReturn {
     fn in_return() -> impl Debug;
-    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    //~^ ERROR `impl Trait` not allowed outside of function and method return types
 }
 
 // Allowed and disallowed in trait impls
@@ -123,7 +123,7 @@ impl DummyTrait for () {
     // Allowed
 
     fn in_trait_impl_return() -> impl Debug { () }
-    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    //~^ ERROR `impl Trait` not allowed outside of function and method return types
 }
 
 // Allowed
@@ -136,10 +136,10 @@ impl DummyType {
 // Disallowed
 extern "C" {
     fn in_foreign_parameters(_: impl Debug);
-    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    //~^ ERROR `impl Trait` not allowed outside of function and method return types
 
     fn in_foreign_return() -> impl Debug;
-    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    //~^ ERROR `impl Trait` not allowed outside of function and method return types
 }
 
 // Allowed
@@ -155,96 +155,96 @@ type InTypeAlias<R> = impl Debug;
 //~^ ERROR `impl Trait` in type aliases is unstable
 
 type InReturnInTypeAlias<R> = fn() -> impl Debug;
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 //~| ERROR `impl Trait` in type aliases is unstable
 
 // Disallowed in impl headers
 impl PartialEq<impl Debug> for () {
-    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    //~^ ERROR `impl Trait` not allowed outside of function and method return types
 }
 
 // Disallowed in impl headers
 impl PartialEq<()> for impl Debug {
-    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    //~^ ERROR `impl Trait` not allowed outside of function and method return types
 }
 
 // Disallowed in inherent impls
 impl impl Debug {
-    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    //~^ ERROR `impl Trait` not allowed outside of function and method return types
 }
 
 // Disallowed in inherent impls
 struct InInherentImplAdt<T> { t: T }
 impl InInherentImplAdt<impl Debug> {
-    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    //~^ ERROR `impl Trait` not allowed outside of function and method return types
 }
 
 // Disallowed in where clauses
 fn in_fn_where_clause()
     where impl Debug: Debug
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 {
 }
 
 // Disallowed in where clauses
 fn in_adt_in_fn_where_clause()
     where Vec<impl Debug>: Debug
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 {
 }
 
 // Disallowed
 fn in_trait_parameter_in_fn_where_clause<T>()
     where T: PartialEq<impl Debug>
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 {
 }
 
 // Disallowed
 fn in_Fn_parameter_in_fn_where_clause<T>()
     where T: Fn(impl Debug)
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 {
 }
 
 // Disallowed
 fn in_Fn_return_in_fn_where_clause<T>()
     where T: Fn() -> impl Debug
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 {
 }
 
 // Disallowed
 struct InStructGenericParamDefault<T = impl Debug>(T);
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 enum InEnumGenericParamDefault<T = impl Debug> { Variant(T) }
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 trait InTraitGenericParamDefault<T = impl Debug> {}
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 type InTypeAliasGenericParamDefault<T = impl Debug> = T;
-//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^ ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 impl <T = impl Debug> T {}
 //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
 //~| WARNING this was previously accepted by the compiler but is being phased out
-//~| ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~| ERROR `impl Trait` not allowed outside of function and method return types
 
 // Disallowed
 fn in_method_generic_param_default<T = impl Debug>(_: T) {}
 //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
 //~| WARNING this was previously accepted by the compiler but is being phased out
-//~| ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~| ERROR `impl Trait` not allowed outside of function and method return types
 
 fn main() {
     let _in_local_variable: impl Fn() = || {};
-    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    //~^ ERROR `impl Trait` not allowed outside of function and method return types
     let _in_return_in_local_variable = || -> impl Fn() { || {} };
-    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    //~^ ERROR `impl Trait` not allowed outside of function and method return types
 }
index 09ec4d5b202c36a498414a771deb3cbc15455e54..93a3de61ccf8aeb2f79a8ccfb5aeb9a164cc9a11 100644 (file)
@@ -43,249 +43,247 @@ LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
    = help: add `#![feature(min_type_alias_impl_trait)]` to the crate attributes to enable
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:15:40
    |
 LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
    |                                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:19:42
    |
 LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
    |                                          ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:23:38
    |
 LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
    |                                      ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:27:40
    |
 LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
    |                                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:31:49
    |
 LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
    |                                                 ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:35:51
    |
 LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
    |                                                   ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:39:55
    |
 LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
    |                                                       ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:43:57
    |
 LL | fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
    |                                                         ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:47:51
    |
 LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
    |                                                   ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:52:53
    |
 LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
    |                                                     ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:56:57
    |
 LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
    |                                                         ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:61:59
    |
 LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
    |                                                           ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:65:38
    |
 LL | fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
    |                                      ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:69:40
    |
 LL | fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
    |                                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:82:32
    |
 LL | struct InBraceStructField { x: impl Debug }
    |                                ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:86:41
    |
 LL | struct InAdtInBraceStructField { x: Vec<impl Debug> }
    |                                         ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:90:27
    |
 LL | struct InTupleStructField(impl Debug);
    |                           ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:95:25
    |
 LL |     InBraceVariant { x: impl Debug },
    |                         ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:97:20
    |
 LL |     InTupleVariant(impl Debug),
    |                    ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:108:23
    |
 LL |     fn in_return() -> impl Debug;
    |                       ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:125:34
    |
 LL |     fn in_trait_impl_return() -> impl Debug { () }
    |                                  ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:138:33
    |
 LL |     fn in_foreign_parameters(_: impl Debug);
    |                                 ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:141:31
    |
 LL |     fn in_foreign_return() -> impl Debug;
    |                               ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:157:39
    |
 LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
    |                                       ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:162:16
    |
 LL | impl PartialEq<impl Debug> for () {
    |                ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:167:24
    |
 LL | impl PartialEq<()> for impl Debug {
    |                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:172:6
    |
 LL | impl impl Debug {
    |      ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:178:24
    |
 LL | impl InInherentImplAdt<impl Debug> {
    |                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:184:11
    |
 LL |     where impl Debug: Debug
    |           ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:191:15
    |
 LL |     where Vec<impl Debug>: Debug
    |               ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:198:24
    |
 LL |     where T: PartialEq<impl Debug>
    |                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:205:17
    |
 LL |     where T: Fn(impl Debug)
    |                 ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:212:22
    |
 LL |     where T: Fn() -> impl Debug
    |                      ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:218:40
    |
 LL | struct InStructGenericParamDefault<T = impl Debug>(T);
    |                                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:222:36
    |
 LL | enum InEnumGenericParamDefault<T = impl Debug> { Variant(T) }
    |                                    ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:226:38
    |
 LL | trait InTraitGenericParamDefault<T = impl Debug> {}
    |                                      ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:230:41
    |
 LL | type InTypeAliasGenericParamDefault<T = impl Debug> = T;
    |                                         ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:234:11
    |
 LL | impl <T = impl Debug> T {}
    |           ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:240:40
    |
 LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    |                                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:246:29
    |
 LL |     let _in_local_variable: impl Fn() = || {};
    |                             ^^^^^^^^^
-   |
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/where-allowed.rs:248:46
    |
 LL |     let _in_return_in_local_variable = || -> impl Fn() { || {} };
diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs
deleted file mode 100644 (file)
index 7beb2db..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// edition:2018
-#![feature(impl_trait_in_bindings)]
-//~^ WARN the feature `impl_trait_in_bindings` is incomplete
-
-use std::io::Error;
-
-fn make_unit() -> Result<(), Error> {
-    Ok(())
-}
-
-fn main() {
-    let fut = async {
-        make_unit()?;
-
-        Ok(()) //~ ERROR type annotations needed
-    };
-}
diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr
deleted file mode 100644 (file)
index 8e632fb..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:2:12
-   |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-error[E0282]: type annotations needed for `impl Future`
-  --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:15:9
-   |
-LL |     let fut = async {
-   |         --- consider giving `fut` the explicit type `impl Future`, where the type parameter `E` is specified
-...
-LL |         Ok(())
-   |         ^^ cannot infer type for type parameter `E` declared on the enum `Result`
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0282`.
index 1d508e8e820ce4c375f472ba4962cda3a472bb93..6662e46b1c7e26a3d2f153969448b6bc1a188f63 100644 (file)
@@ -7,5 +7,5 @@ fn main() {
     let _ = &data as *const *const ();
     if data.is_null() {}
     //~^ WARNING type annotations needed
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~| WARNING this is accepted in the current edition
 }
index 12848982b8d28750791de19ac4aadaac64064ef4..c38f57912adff57827fef07ddfd7d5b5b809d753 100644 (file)
@@ -5,7 +5,7 @@ LL |     if data.is_null() {}
    |             ^^^^^^^
    |
    = note: `#[warn(tyvar_behind_raw_pointer)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
 
 warning: 1 warning emitted
diff --git a/src/test/ui/inference/issue-70703.rs b/src/test/ui/inference/issue-70703.rs
new file mode 100644 (file)
index 0000000..d90498e
--- /dev/null
@@ -0,0 +1,26 @@
+// check-pass
+
+trait Factory {
+    type Product;
+}
+
+impl Factory for () {
+    type Product = ();
+}
+
+trait ProductConsumer<P> {
+    fn consume(self, product: P);
+}
+
+impl<P> ProductConsumer<P> for () {
+    fn consume(self, _: P) {}
+}
+
+fn make_product_consumer<F: Factory>(_: F) -> impl ProductConsumer<F::Product> {
+    ()
+}
+
+fn main() {
+    let consumer = make_product_consumer(());
+    consumer.consume(());
+}
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..ff78c25
--- /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 alloc3, but 1 byte is uninitialized starting at alloc3+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);
+}
diff --git a/src/test/ui/intrinsics/non-integer-atomic.rs b/src/test/ui/intrinsics/non-integer-atomic.rs
new file mode 100644 (file)
index 0000000..00a7f36
--- /dev/null
@@ -0,0 +1,92 @@
+// build-fail
+
+#![feature(core_intrinsics)]
+#![allow(warnings)]
+#![crate_type = "rlib"]
+
+use std::intrinsics;
+
+#[derive(Copy, Clone)]
+pub struct Foo(i64);
+pub type Bar = &'static Fn();
+pub type Quux = [u8; 100];
+
+pub unsafe fn test_bool_load(p: &mut bool, v: bool) {
+    intrinsics::atomic_load(p);
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool`
+}
+
+pub unsafe fn test_bool_store(p: &mut bool, v: bool) {
+    intrinsics::atomic_store(p, v);
+    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `bool`
+}
+
+pub unsafe fn test_bool_xchg(p: &mut bool, v: bool) {
+    intrinsics::atomic_xchg(p, v);
+    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `bool`
+}
+
+pub unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
+    intrinsics::atomic_cxchg(p, v, v);
+    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
+}
+
+pub unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
+    intrinsics::atomic_load(p);
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo`
+}
+
+pub unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
+    intrinsics::atomic_store(p, v);
+    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `Foo`
+}
+
+pub unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) {
+    intrinsics::atomic_xchg(p, v);
+    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
+}
+
+pub unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
+    intrinsics::atomic_cxchg(p, v, v);
+    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
+}
+
+pub unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
+    intrinsics::atomic_load(p);
+    //~^ ERROR expected basic integer type, found `&dyn Fn()`
+}
+
+pub unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
+    intrinsics::atomic_store(p, v);
+    //~^ ERROR expected basic integer type, found `&dyn Fn()`
+}
+
+pub unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
+    intrinsics::atomic_xchg(p, v);
+    //~^ ERROR expected basic integer type, found `&dyn Fn()`
+}
+
+pub unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
+    intrinsics::atomic_cxchg(p, v, v);
+    //~^ ERROR expected basic integer type, found `&dyn Fn()`
+}
+
+pub unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
+    intrinsics::atomic_load(p);
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
+}
+
+pub unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
+    intrinsics::atomic_store(p, v);
+    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
+}
+
+pub unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) {
+    intrinsics::atomic_xchg(p, v);
+    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
+}
+
+pub unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) {
+    intrinsics::atomic_cxchg(p, v, v);
+    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
+}
diff --git a/src/test/ui/intrinsics/non-integer-atomic.stderr b/src/test/ui/intrinsics/non-integer-atomic.stderr
new file mode 100644 (file)
index 0000000..ee485c2
--- /dev/null
@@ -0,0 +1,99 @@
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `bool`
+  --> $DIR/non-integer-atomic.rs:15:5
+   |
+LL |     intrinsics::atomic_load(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `bool`
+  --> $DIR/non-integer-atomic.rs:20:5
+   |
+LL |     intrinsics::atomic_store(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `bool`
+  --> $DIR/non-integer-atomic.rs:25:5
+   |
+LL |     intrinsics::atomic_xchg(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
+  --> $DIR/non-integer-atomic.rs:30:5
+   |
+LL |     intrinsics::atomic_cxchg(p, v, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `Foo`
+  --> $DIR/non-integer-atomic.rs:35:5
+   |
+LL |     intrinsics::atomic_load(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `Foo`
+  --> $DIR/non-integer-atomic.rs:40:5
+   |
+LL |     intrinsics::atomic_store(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
+  --> $DIR/non-integer-atomic.rs:45:5
+   |
+LL |     intrinsics::atomic_xchg(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
+  --> $DIR/non-integer-atomic.rs:50:5
+   |
+LL |     intrinsics::atomic_cxchg(p, v, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `&dyn Fn()`
+  --> $DIR/non-integer-atomic.rs:55:5
+   |
+LL |     intrinsics::atomic_load(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `&dyn Fn()`
+  --> $DIR/non-integer-atomic.rs:60:5
+   |
+LL |     intrinsics::atomic_store(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `&dyn Fn()`
+  --> $DIR/non-integer-atomic.rs:65:5
+   |
+LL |     intrinsics::atomic_xchg(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `&dyn Fn()`
+  --> $DIR/non-integer-atomic.rs:70:5
+   |
+LL |     intrinsics::atomic_cxchg(p, v, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
+  --> $DIR/non-integer-atomic.rs:75:5
+   |
+LL |     intrinsics::atomic_load(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
+  --> $DIR/non-integer-atomic.rs:80:5
+   |
+LL |     intrinsics::atomic_store(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
+  --> $DIR/non-integer-atomic.rs:85:5
+   |
+LL |     intrinsics::atomic_xchg(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
+  --> $DIR/non-integer-atomic.rs:90:5
+   |
+LL |     intrinsics::atomic_cxchg(p, v, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 16 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/invalid-compile-flags/codegen-option-without-group.rs b/src/test/ui/invalid-compile-flags/codegen-option-without-group.rs
new file mode 100644 (file)
index 0000000..7bbf47a
--- /dev/null
@@ -0,0 +1 @@
+// compile-flags: --llvm-args
diff --git a/src/test/ui/invalid-compile-flags/codegen-option-without-group.stderr b/src/test/ui/invalid-compile-flags/codegen-option-without-group.stderr
new file mode 100644 (file)
index 0000000..c5a0c29
--- /dev/null
@@ -0,0 +1,2 @@
+error: Unrecognized option: 'llvm-args'. Did you mean `-C llvm-args`?
+
diff --git a/src/test/ui/invalid-compile-flags/debug-option-without-group.rs b/src/test/ui/invalid-compile-flags/debug-option-without-group.rs
new file mode 100644 (file)
index 0000000..86e40c1
--- /dev/null
@@ -0,0 +1 @@
+// compile-flags: --unpretty=hir
diff --git a/src/test/ui/invalid-compile-flags/debug-option-without-group.stderr b/src/test/ui/invalid-compile-flags/debug-option-without-group.stderr
new file mode 100644 (file)
index 0000000..0e57e31
--- /dev/null
@@ -0,0 +1,2 @@
+error: Unrecognized option: 'unpretty'. Did you mean `-Z unpretty`?
+
index 2a6e2414593aa4145e89f77dcf1bcd2ec92c7f19..9d181eab7fbcdf1cd51989d3143f792224b6b557 100644 (file)
@@ -45,6 +45,8 @@ error[E0726]: implicit elided lifetime not allowed here
    |
 LL | impl<'self> Serializable<str> for &'self str {
    |             ^^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Serializable<'_, str>`
+   |
+   = note: assuming a `'static` lifetime...
 
 error[E0277]: the size for values of type `str` cannot be known at compilation time
   --> $DIR/issue-10412.rs:6:13
index 695d657cb529ca65e272d02b9a84d7d8a3939089..3b89e8bc451518b1714dfd14df5a1c5603977b25 100644 (file)
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/issue-12997-2.rs:8:1
    |
+LL | #[bench]
+   | -------- in this procedural macro expansion
 LL | fn bar(x: isize) { }
    | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `&mut Bencher`
    |
index 69817f10c9f32c9c45663cc3581faec77601073b..ee1464fd8481105f4f87e2969c2dc80aaccaf7b2 100644 (file)
@@ -5,7 +5,11 @@ LL |     (|| Box::new(*(&[0][..])))();
    |                  ^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[{integer}]`
-   = note: required by `Box::<T>::new`
+note: required by `Box::<T>::new`
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+   |
+LL |     pub fn new(x: T) -> Self {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
   --> $DIR/issue-17651.rs:5:9
diff --git a/src/test/ui/issues/issue-17756.rs b/src/test/ui/issues/issue-17756.rs
deleted file mode 100644 (file)
index 1835b17..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-#![allow(unused_variables)]
-#![allow(non_upper_case_globals)]
-
-const count : usize = 2 as usize;
-fn main() {
-    let larger : [usize; count*2];
-}
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 22c3470b61edeb955e8cb92b46c1d837c4c241aa..0e942e80e254436dca5792928e63162bcb2811ef 100644 (file)
@@ -1,10 +1,11 @@
 error[E0277]: the trait bound `isize: HasState` is not satisfied
-  --> $DIR/issue-18611.rs:1:1
+  --> $DIR/issue-18611.rs:1:18
    |
-LL | / fn add_state(op: <isize as HasState>::State) {
-LL | |
-LL | | }
-   | |_^ the trait `HasState` is not implemented for `isize`
+LL | fn add_state(op: <isize as HasState>::State) {
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize`
+...
+LL | trait HasState {
+   | -------------- required by this bound in `HasState`
 
 error: aborting due to previous error
 
index 86b530e85a80ac8091e6d411ab9d1bf7fb9d5e34..2a5416ce85ba65e78140c4a40aaa85dce68c7338 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Bar` cannot be made into an object
-  --> $DIR/issue-18959.rs:11:11
+  --> $DIR/issue-18959.rs:11:12
    |
 LL | fn foo(b: &dyn Bar) {
-   |           ^^^^^^^^ `Bar` cannot be made into an object
+   |            ^^^^^^^ `Bar` cannot be made into an object
    |
    = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
index c3a5d3dfeee7ddcfd68ce29bafba5aeef6acf117..4400b6179c6f8ad782b870d846de1618226cc6e1 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Qiz` cannot be made into an object
-  --> $DIR/issue-19380.rs:11:9
+  --> $DIR/issue-19380.rs:11:29
    |
 LL |   foos: &'static [&'static (dyn Qiz + 'static)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Qiz` cannot be made into an object
+   |                             ^^^^^^^^^^^^^^^^^ `Qiz` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-19380.rs:2:6
diff --git a/src/test/ui/issues/issue-20005.rs b/src/test/ui/issues/issue-20005.rs
deleted file mode 100644 (file)
index 36350bf..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-trait From<Src> {
-    type Result;
-
-    fn from(src: Src) -> Self::Result;
-}
-
-trait To {
-    fn to<Dst>(
-        self
-    ) -> <Dst as From<Self>>::Result where Dst: From<Self> { //~ ERROR the size for values of type
-        From::from(self)
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-20005.stderr b/src/test/ui/issues/issue-20005.stderr
deleted file mode 100644 (file)
index bc41404..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0277]: the size for values of type `Self` cannot be known at compilation time
-  --> $DIR/issue-20005.rs:10:49
-   |
-LL | trait From<Src> {
-   |            --- required by this bound in `From`
-...
-LL |     ) -> <Dst as From<Self>>::Result where Dst: From<Self> {
-   |                                                 ^^^^^^^^^^ doesn't have a size known at compile-time
-   |
-help: consider further restricting `Self`
-   |
-LL |     ) -> <Dst as From<Self>>::Result where Dst: From<Self>, Self: Sized {
-   |                                                           ^^^^^^^^^^^^^
-help: consider relaxing the implicit `Sized` restriction
-   |
-LL | trait From<Src: ?Sized> {
-   |               ^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
index 41922c6229351446d772870c9fad3d381feeef20..cfd8b2191ac38ed8d66aeacb4e7f4b0f0a3496a1 100644 (file)
@@ -7,7 +7,6 @@
 #![allow(deprecated, deprecated_in_future)]
 
 // aux-build:i8.rs
-// ignore-pretty issue #37201
 
 extern crate i8;
 use std::string as i16;
index 9940f43cc44404ce631f3d092015f4038da9edb5..25a90df45613b9b8e2777a9965c2b1b90c46f045 100644 (file)
@@ -6,7 +6,11 @@ LL |     for item in *things { *item = 0 }
    |
    = help: the trait `Sized` is not implemented for `dyn Iterator<Item = &'a mut u8>`
    = note: required because of the requirements on the impl of `IntoIterator` for `dyn Iterator<Item = &'a mut u8>`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 71c6746e0e04059f761981cad47234156eae2988..1b90727fbc0a66f1a706130a91a43476a9773c8d 100644 (file)
@@ -19,9 +19,7 @@ use std::path::Path;
 
 pub fn parse_summary<R: Read>(_: R, _: &Path) {
      let path_from_root = Path::new("");
-     Path::new(&iter::repeat("../")
-               .take(path_from_root.components().count() - 1)
-               .collect::<String>());
+     Path::new(&"../".repeat(path_from_root.components().count() - 1));
  }
 
 fn foo() {
index e68482d1caf696db159003465d951dac2fddcc84..03e3311e0f39bac7d151723e1276e51e79bcba52 100644 (file)
@@ -1,8 +1,8 @@
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/issue-20831-debruijn.rs:28:33
+  --> $DIR/issue-20831-debruijn.rs:28:8
    |
 LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |        ^^^^^^^^^
    |
 note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 28:58...
   --> $DIR/issue-20831-debruijn.rs:28:58
@@ -15,10 +15,10 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined on
 LL | impl<'a> Publisher<'a> for MyStruct<'a> {
    |      ^^
 note: ...so that the types are compatible
-  --> $DIR/issue-20831-debruijn.rs:28:33
+  --> $DIR/issue-20831-debruijn.rs:28:8
    |
 LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |        ^^^^^^^^^
    = note: expected `Publisher<'_>`
               found `Publisher<'_>`
 
index 4cef23ac42cb394c031dfedea09340b746ed30f7..c864381e6b0a629d9779de007a76361cefe74fec 100644 (file)
@@ -1,6 +1,8 @@
 error[E0277]: the trait bound `Bar: Hash` is not satisfied
   --> $DIR/issue-21160.rs:8:12
    |
+LL | #[derive(Hash)]
+   |          ---- in this derive macro expansion
 LL | struct Foo(Bar);
    |            ^^^ the trait `Hash` is not implemented for `Bar`
    | 
index 9b3b7a72e049eb617948574afc1b56569c564a70..47f28d7c443fcce61b15e9860a0f4659223d2eca 100644 (file)
@@ -3,6 +3,11 @@ error[E0624]: associated function `foo` is private
    |
 LL |         Foo::foo(&f);
    |              ^^^ private associated function
+   | 
+  ::: $DIR/auxiliary/issue-21202.rs:4:9
+   |
+LL |         fn foo(&self) { }
+   |         ------------- private associated function defined here
 
 error: aborting due to previous error
 
index e2ae1f96ee53379c8dd2982c04c5b8997a500532..292a0ae298dcf17c4bca6c69a20107ada2a78cf3 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-pretty issue #37201
 
 struct X { val: i32 }
 impl std::ops::Deref for X {
index 823be8c832d09a54bb256484c7deaed6c6867cb6..a99f260dde3b260f871dcc2a1ee92c4ee5ce315d 100644 (file)
@@ -1,8 +1,6 @@
 // run-pass
 #![allow(non_upper_case_globals)]
 
-// ignore-pretty issue #37201
-
 // This test is ensuring that parameters are indeed dropped after
 // temporaries in a fn body.
 
diff --git a/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs b/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs
deleted file mode 100644 (file)
index 7253d35..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// run-pass
-// This test illustrates that under NLL, we can remove our overly
-// conservative approach for disallowing mutations of match inputs.
-
-// See further discussion on rust-lang/rust#24535,
-// rust-lang/rfcs#1006, and rust-lang/rfcs#107
-
-fn main() {
-    rust_issue_24535();
-    rfcs_issue_1006_1();
-    rfcs_issue_1006_2();
-}
-
-fn rust_issue_24535() {
-    fn compare(a: &u8, b: &mut u8) -> bool {
-        a == b
-    }
-
-    let a = 3u8;
-
-    match a {
-        0 => panic!("nope"),
-        3 if compare(&a, &mut 3) => (),
-        _ => panic!("nope"),
-    }
-}
-
-fn rfcs_issue_1006_1() {
-    let v = vec!["1".to_string(), "2".to_string(), "3".to_string()];
-    match Some(&v) {
-        Some(iv) if iv.iter().any(|x| &x[..]=="2") => true,
-        _ => panic!("nope"),
-    };
-}
-
-fn rfcs_issue_1006_2() {
-    #[inline(always)]
-    fn check<'a, I: Iterator<Item=&'a i32>>(mut i: I) -> bool {
-        i.any(|&x| x == 2)
-    }
-
-    let slice = [1, 2, 3];
-
-    match 42 {
-        _ if slice.iter().any(|&x| x == 2) => { true },
-        _ => { panic!("nope"); }
-    };
-
-    // (This match is just illustrating how easy it was to circumvent
-    // the checking performed for the previous `match`.)
-    match 42 {
-        _ if check(slice.iter()) => { true },
-        _ => { panic!("nope"); }
-    };
-}
diff --git a/src/test/ui/issues/issue-27060-2.rs b/src/test/ui/issues/issue-27060-2.rs
deleted file mode 100644 (file)
index a001ce1..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#[repr(packed)]
-pub struct Bad<T: ?Sized> {
-    data: T, //~ ERROR the size for values of type
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-27060-2.stderr b/src/test/ui/issues/issue-27060-2.stderr
deleted file mode 100644 (file)
index 5dbcc96..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-error[E0277]: the size for values of type `T` cannot be known at compilation time
-  --> $DIR/issue-27060-2.rs:3:11
-   |
-LL | pub struct Bad<T: ?Sized> {
-   |                - this type parameter needs to be `std::marker::Sized`
-LL |     data: T,
-   |           ^ doesn't have a size known at compile-time
-   |
-   = note: the last field of a packed struct may only have a dynamically sized type if it does not need drop to be run
-   = help: change the field's type to have a statically known size
-help: borrowed types always have a statically known size
-   |
-LL |     data: &T,
-   |           ^
-help: the `Box` type always has a statically known size and allocates its contents in the heap
-   |
-LL |     data: Box<T>,
-   |           ^^^^ ^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-27060-rpass.rs b/src/test/ui/issues/issue-27060-rpass.rs
deleted file mode 100644 (file)
index d9159f6..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-#[repr(packed)]
-pub struct Good {
-    data: &'static u32,
-    data2: [&'static u32; 2],
-    aligned: [u8; 32],
-}
-
-// kill this test when that turns to a hard error
-#[allow(unaligned_references)]
-fn main() {
-    let good = Good { data: &0, data2: [&0, &0], aligned: [0; 32] };
-
-    let _ = &good.data; // ok
-    let _ = &good.data2[0]; // ok
-
-    let _ = &good.data;
-    let _ = &good.data2[0];
-    let _ = &*good.data; // ok, behind a pointer
-    let _ = &good.aligned; // ok, has align 1
-    let _ = &good.aligned[2]; // ok, has align 1
-}
diff --git a/src/test/ui/issues/issue-27060.rs b/src/test/ui/issues/issue-27060.rs
deleted file mode 100644 (file)
index 5317a61..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#[repr(packed)]
-pub struct Good {
-    data: &'static u32,
-    data2: [&'static u32; 2],
-    aligned: [u8; 32],
-}
-
-#[deny(unaligned_references)]
-fn main() {
-    let good = Good {
-        data: &0,
-        data2: [&0, &0],
-        aligned: [0; 32]
-    };
-
-    let _ = &good.data; //~ ERROR reference to packed field
-    //~| hard error
-    let _ = &good.data2[0]; //~ ERROR reference to packed field
-    //~| hard error
-
-    let _ = &good.data; //~ ERROR reference to packed field
-                        //~| hard error
-    let _ = &good.data2[0]; //~ ERROR reference to packed field
-                            //~| hard error
-    let _ = &*good.data; // ok, behind a pointer
-    let _ = &good.aligned; // ok, has align 1
-    let _ = &good.aligned[2]; // ok, has align 1
-}
diff --git a/src/test/ui/issues/issue-27060.stderr b/src/test/ui/issues/issue-27060.stderr
deleted file mode 100644 (file)
index 0929788..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-error: reference to packed field is unaligned
-  --> $DIR/issue-27060.rs:16:13
-   |
-LL |     let _ = &good.data;
-   |             ^^^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-27060.rs:8:8
-   |
-LL | #[deny(unaligned_references)]
-   |        ^^^^^^^^^^^^^^^^^^^^
-   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
-   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
-
-error: reference to packed field is unaligned
-  --> $DIR/issue-27060.rs:18:13
-   |
-LL |     let _ = &good.data2[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 #82523 <https://github.com/rust-lang/rust/issues/82523>
-   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
-
-error: reference to packed field is unaligned
-  --> $DIR/issue-27060.rs:21:13
-   |
-LL |     let _ = &good.data;
-   |             ^^^^^^^^^^
-   |
-   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
-   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
-
-error: reference to packed field is unaligned
-  --> $DIR/issue-27060.rs:23:13
-   |
-LL |     let _ = &good.data2[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 #82523 <https://github.com/rust-lang/rust/issues/82523>
-   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
-
-error: aborting due to 4 previous errors
-
index e137575c2f825becd1bfcbb42969e79344862239..ab54af29bd6b9bd23427342b1029e3f5db4576ae 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-pretty issue #37201
 
 // Check that when a `let`-binding occurs in a loop, its associated
 // drop-flag is reinitialized (to indicate "needs-drop" at the end of
diff --git a/src/test/ui/issues/issue-27895.rs b/src/test/ui/issues/issue-27895.rs
deleted file mode 100644 (file)
index 0018ac1..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-fn main() {
-    let i = 5;
-    let index = 6;
-
-    match i {
-        0..=index => println!("winner"),
-        //~^ ERROR runtime values cannot be referenced in patterns
-        _ => println!("hello"),
-    }
-}
diff --git a/src/test/ui/issues/issue-27895.stderr b/src/test/ui/issues/issue-27895.stderr
deleted file mode 100644 (file)
index 55bd938..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0080]: runtime values cannot be referenced in patterns
-  --> $DIR/issue-27895.rs:6:13
-   |
-LL |         0..=index => println!("winner"),
-   |             ^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
index 4c927a0cb458f8c471b52398a0a024de39b5350c..70caeb0ea39092578f8c7d32a234dfd8504f645f 100644 (file)
@@ -5,7 +5,11 @@ LL |     let _ = Iterator::next(&mut ());
    |                            ^^^^^^^ `()` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `()`
-   = note: required by `std::iter::Iterator::next`
+note: required by `std::iter::Iterator::next`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn next(&mut self) -> Option<Self::Item>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `bool` is not an iterator
   --> $DIR/issue-28098.rs:6:14
@@ -15,7 +19,11 @@ LL |     for _ in false {}
    |
    = help: the trait `Iterator` is not implemented for `bool`
    = note: required because of the requirements on the impl of `IntoIterator` for `bool`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `()` is not an iterator
   --> $DIR/issue-28098.rs:9:28
@@ -24,7 +32,11 @@ LL |     let _ = Iterator::next(&mut ());
    |                            ^^^^^^^ `()` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `()`
-   = note: required by `std::iter::Iterator::next`
+note: required by `std::iter::Iterator::next`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn next(&mut self) -> Option<Self::Item>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `()` is not an iterator
   --> $DIR/issue-28098.rs:2:13
@@ -41,7 +53,11 @@ LL |     let _ = Iterator::next(&mut ());
    |                            ^^^^^^^ `()` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `()`
-   = note: required by `std::iter::Iterator::next`
+note: required by `std::iter::Iterator::next`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn next(&mut self) -> Option<Self::Item>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `()` is not an iterator
   --> $DIR/issue-28098.rs:22:28
@@ -50,7 +66,11 @@ LL |     let _ = Iterator::next(&mut ());
    |                            ^^^^^^^ `()` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `()`
-   = note: required by `std::iter::Iterator::next`
+note: required by `std::iter::Iterator::next`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn next(&mut self) -> Option<Self::Item>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `bool` is not an iterator
   --> $DIR/issue-28098.rs:25:14
@@ -60,7 +80,11 @@ LL |     for _ in false {}
    |
    = help: the trait `Iterator` is not implemented for `bool`
    = note: required because of the requirements on the impl of `IntoIterator` for `bool`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `()` is not an iterator
   --> $DIR/issue-28098.rs:18:13
index 94aff5963544c59dd8d1cf566976ba31cebe8866..f00d5d32bbf28d6bc40fcfdb732e3cdebd512587 100644 (file)
@@ -1,13 +1,15 @@
 error[E0283]: type annotations needed
   --> $DIR/issue-29147.rs:21:13
    |
-LL | trait Foo { fn xxx(&self); }
-   |             -------------- required by `Foo::xxx`
-...
 LL |     let _ = <S5<_>>::xxx;
    |             ^^^^^^^^^^^^ cannot infer type for struct `S5<_>`
    |
    = note: cannot satisfy `S5<_>: Foo`
+note: required by `Foo::xxx`
+  --> $DIR/issue-29147.rs:10:13
+   |
+LL | trait Foo { fn xxx(&self); }
+   |             ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-31109.rs b/src/test/ui/issues/issue-31109.rs
deleted file mode 100644 (file)
index 37c2390..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
-    // FIXME(#31407) this error should go away, but in the meantime we test that it
-    // is accompanied by a somewhat useful error message.
-    let _: f64 = 1234567890123456789012345678901234567890e-340;
-    //~^ ERROR could not evaluate float literal (see issue #31407)
-}
diff --git a/src/test/ui/issues/issue-31109.stderr b/src/test/ui/issues/issue-31109.stderr
deleted file mode 100644 (file)
index d354f61..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: could not evaluate float literal (see issue #31407)
-  --> $DIR/issue-31109.rs:4:18
-   |
-LL |     let _: f64 = 1234567890123456789012345678901234567890e-340;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
index 2d020188198af843ff55c811fd2f122c211fd24a..bc7eb0688ee84bb68bafa8803967f1f8b974b909 100644 (file)
@@ -8,7 +8,11 @@ LL |     Err(5)?;
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, {integer}>>` for `Result<i32, ()>`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 63e1b28a60a1e405913d8ebf8f46674f8b37b0cd..840c7ff8355d0f20c8a8f736833a455f5a7a7f2a 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 #![feature(box_syntax)]
+#![allow(dead_code)]
 
 pub fn main() {
    let mut x: Box<_> = box 3;
index 043658c9508f3721a52cfa2746099d246eceedc9..d588214f5077c9f3d459e943bfd09d6e9e099c27 100644 (file)
@@ -17,7 +17,11 @@ LL |     for _ in HashMap::new().iter().cloned() {}
                   found tuple `(&_, &_)`
    = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
    = note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_`
   --> $DIR/issue-33941.rs:4:14
@@ -28,7 +32,11 @@ LL |     for _ in HashMap::new().iter().cloned() {}
    = note: expected reference `&_`
                   found tuple `(&_, &_)`
    = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
-   = note: required by `std::iter::Iterator::next`
+note: required by `std::iter::Iterator::next`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn next(&mut self) -> Option<Self::Item>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
index c32fe7e0ec6238c910ac515007427f61ccccbf08..fba75de8cc0523f8c746178f738a838df4ee0b11 100644 (file)
@@ -2,10 +2,16 @@ error[E0277]: can't compare `Comparable` with `Comparable`
   --> $DIR/issue-34229.rs:2:46
    |
 LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable);
-   |                                              ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable`
+   |                     ----------               ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable`
+   |                     |
+   |                     in this derive macro expansion
    |
    = help: the trait `PartialOrd` is not implemented for `Comparable`
-   = note: required by `std::cmp::PartialOrd::partial_cmp`
+note: required by `std::cmp::PartialOrd::partial_cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-36638.rs b/src/test/ui/issues/issue-36638.rs
deleted file mode 100644 (file)
index 2e64853..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-struct Foo<Self>(Self);
-//~^ ERROR expected identifier, found keyword `Self`
-//~^^ ERROR E0392
-
-trait Bar<Self> {}
-//~^ ERROR expected identifier, found keyword `Self`
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-36638.stderr b/src/test/ui/issues/issue-36638.stderr
deleted file mode 100644 (file)
index 733fc4a..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-error: expected identifier, found keyword `Self`
-  --> $DIR/issue-36638.rs:1:12
-   |
-LL | struct Foo<Self>(Self);
-   |            ^^^^ expected identifier, found keyword
-
-error: expected identifier, found keyword `Self`
-  --> $DIR/issue-36638.rs:5:11
-   |
-LL | trait Bar<Self> {}
-   |           ^^^^ expected identifier, found keyword
-
-error[E0392]: parameter `Self` is never used
-  --> $DIR/issue-36638.rs:1:12
-   |
-LL | struct Foo<Self>(Self);
-   |            ^^^^ unused parameter
-   |
-   = help: consider removing `Self`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `Self` to be a const parameter, use `const Self: usize` instead
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0392`.
index 7f54c9f8a6b9ff9077bf8d7810f08a54f932985d..6f4567546d00b6a206282ac762f14af0b3080a6c 100644 (file)
@@ -13,12 +13,18 @@ LL |     let _woohoo = (Box::new(my_struct)).priv_field;
 error[E0624]: associated function `happyfun` is private
   --> $DIR/issue-3763.rs:24:18
    |
+LL |         fn happyfun(&self) {}
+   |         ------------------ private associated function defined here
+...
 LL |     (&my_struct).happyfun();
    |                  ^^^^^^^^ private associated function
 
 error[E0624]: associated function `happyfun` is private
   --> $DIR/issue-3763.rs:26:27
    |
+LL |         fn happyfun(&self) {}
+   |         ------------------ private associated function defined here
+...
 LL |     (Box::new(my_struct)).happyfun();
    |                           ^^^^^^^^ private associated function
 
diff --git a/src/test/ui/issues/issue-37655.rs b/src/test/ui/issues/issue-37655.rs
deleted file mode 100644 (file)
index 416854d..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// check-pass
-// Regression test for #37655. The problem was a false edge created by
-// coercion that wound up requiring that `'a` (in `split()`) outlive
-// `'b`, which shouldn't be necessary.
-
-#![allow(warnings)]
-
-trait SliceExt<T> {
-    type Item;
-
-    fn get_me<I>(&self, index: I) -> &I::Output
-        where I: SliceIndex<Self::Item>;
-}
-
-impl<T> SliceExt<T> for [T] {
-    type Item = T;
-
-    fn get_me<I>(&self, index: I) -> &I::Output
-        where I: SliceIndex<T>
-    {
-        panic!()
-    }
-}
-
-pub trait SliceIndex<T> {
-    type Output: ?Sized;
-}
-
-impl<T> SliceIndex<T> for usize {
-    type Output = T;
-}
-
-fn foo<'a, 'b>(split: &'b [&'a [u8]]) -> &'a [u8] {
-    split.get_me(0)
-}
-
-fn main() { }
index 2a0693a581c319e9f85706e8387e66a075367c7f..f609e47e818d493bfb9447be009384952c30f312 100644 (file)
@@ -1,9 +1,6 @@
 error[E0271]: type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()`
   --> $DIR/issue-39970.rs:19:5
    |
-LL |     fn visit() {}
-   |     ---------- required by `Visit::visit`
-...
 LL |     <() as Visit>::visit();
    |     ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&()`
    |
@@ -12,6 +9,11 @@ note: required because of the requirements on the impl of `Visit` for `()`
    |
 LL | impl Visit for () where
    |      ^^^^^     ^^
+note: required by `Visit::visit`
+  --> $DIR/issue-39970.rs:6:5
+   |
+LL |     fn visit() {}
+   |     ^^^^^^^^^^
 
 error: aborting due to previous error
 
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 072243d881ca68f1507b631ef6f47cfb532f035f..c0208e680841eec256346603280c756516055d05 100644 (file)
@@ -1,19 +1,19 @@
 struct S;
 
 impl S {
-    #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions
+    #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
     fn f() {
         file!();
     }
 }
 
 trait Tr1 {
-    #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions
+    #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
     fn f();
 }
 
 trait Tr2 {
-    #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions
+    #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
     type F;
 }
 
index f5f51cdcd4885a0bd8d7afdea6812f45f13b77c4..007eb259594704110e040ce39dd10a78f3505b9c 100644 (file)
@@ -1,20 +1,28 @@
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/issue-43023.rs:4:5
    |
-LL |     #[derive(Debug)]
-   |     ^^^^^^^^^^^^^^^^
+LL |       #[derive(Debug)]
+   |       ^^^^^^^^^^^^^^^^ not applicable here
+LL | /     fn f() {
+LL | |         file!();
+LL | |     }
+   | |_____- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/issue-43023.rs:11:5
    |
 LL |     #[derive(Debug)]
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^ not applicable here
+LL |     fn f();
+   |     ------- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/issue-43023.rs:16:5
    |
 LL |     #[derive(Debug)]
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^ not applicable here
+LL |     type F;
+   |     ------- not a `struct`, `enum` or `union`
 
 error: aborting due to 3 previous errors
 
index 894a61f3eff0ee10939a6cde8ec49095256a46c9..f47d5a347bb11823fdca66d33cab33e60c793d16 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
 fn main() {
-   &&[()][0];
+   let _ = &&[()][0];
    println!("{:?}", &[(),()][1]);
 }
index 80aca482b3d29b8c8e614353bd7e9f4360d02178..4bc5eb03e922cb26ffcf205feef26df4ed3467e4 100644 (file)
@@ -10,7 +10,7 @@ LL | {
 LL |     break_me::<Type, fn(_)>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |     |
-   |     expected signature of `fn(<Type as Trait<'b>>::Assoc) -> _`
+   |     expected signature of `for<'b> fn(<Type as Trait<'b>>::Assoc) -> _`
    |     found signature of `fn(()) -> _`
 
 error: aborting due to previous error
index 4b3a0269baea266b934fc3e02073825b1cc501df..b114e8e03333d99ca90680b50633d0439c792e50 100644 (file)
@@ -13,13 +13,13 @@ fn main() {
 
     #[repr(nothing)]
     let _x = 0;
-    //~^^ ERROR attribute should be applied to a struct, enum, or union
+    //~^^ ERROR E0552
 
     #[repr(something_not_real)]
     loop {
         ()
     };
-    //~^^^^ ERROR attribute should be applied to a struct, enum, or union
+    //~^^^^ ERROR E0552
 
     #[repr]
     let _y = "123";
index f1205d447e4ba97936baf6279b6f72c86be7492f..03aa37f52075f73b9a70fb8401136f06273e4363 100644 (file)
@@ -26,23 +26,17 @@ LL |     #[inline(XYZ)]
 LL |     let _b = 4;
    |     ----------- not a function or closure
 
-error[E0517]: attribute should be applied to a struct, enum, or union
+error[E0552]: unrecognized representation hint
   --> $DIR/issue-43988.rs:14:12
    |
 LL |     #[repr(nothing)]
    |            ^^^^^^^
-LL |     let _x = 0;
-   |     ----------- not a struct, enum, or union
 
-error[E0517]: attribute should be applied to a struct, enum, or union
+error[E0552]: unrecognized representation hint
   --> $DIR/issue-43988.rs:18:12
    |
-LL |       #[repr(something_not_real)]
-   |              ^^^^^^^^^^^^^^^^^^
-LL | /     loop {
-LL | |         ()
-LL | |     };
-   | |_____- not a struct, enum, or union
+LL |     #[repr(something_not_real)]
+   |            ^^^^^^^^^^^^^^^^^^
 
 error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43988.rs:30:5
@@ -54,5 +48,5 @@ LL |     foo();
 
 error: aborting due to 7 previous errors
 
-Some errors have detailed explanations: E0517, E0518.
-For more information about an error, try `rustc --explain E0517`.
+Some errors have detailed explanations: E0518, E0552.
+For more information about an error, try `rustc --explain E0518`.
diff --git a/src/test/ui/issues/issue-45157.rs b/src/test/ui/issues/issue-45157.rs
deleted file mode 100644 (file)
index 8d2bf22..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#![allow(unused)]
-
-
-#[derive(Clone, Copy, Default)]
-struct S {
-    a: u8,
-    b: u8,
-}
-#[derive(Clone, Copy, Default)]
-struct Z {
-    c: u8,
-    d: u8,
-}
-
-union U {
-    s: S,
-    z: Z,
-}
-
-fn main() {
-    unsafe {
-        let mut u = U { s: Default::default() };
-
-        let mref = &mut u.s.a;
-        *mref = 22;
-
-        let nref = &u.z.c;
-        //~^ ERROR cannot borrow `u` (via `u.z.c`) as immutable because it is also borrowed as mutable (via `u.s.a`) [E0502]
-        println!("{} {}", mref, nref)
-    }
-}
diff --git a/src/test/ui/issues/issue-45157.stderr b/src/test/ui/issues/issue-45157.stderr
deleted file mode 100644 (file)
index 57fd8d4..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0502]: cannot borrow `u` (via `u.z.c`) as immutable because it is also borrowed as mutable (via `u.s.a`)
-  --> $DIR/issue-45157.rs:27:20
-   |
-LL |         let mref = &mut u.s.a;
-   |                    ---------- mutable borrow occurs here (via `u.s.a`)
-...
-LL |         let nref = &u.z.c;
-   |                    ^^^^^^ immutable borrow of `u.z.c` -- which overlaps with `u.s.a` -- occurs here
-LL |
-LL |         println!("{} {}", mref, nref)
-   |                           ---- mutable borrow later used here
-   |
-   = note: `u.z.c` is a field of the union `U`, so it overlaps the field `u.s.a`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0502`.
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 296de362db1b1a94154649a758713654b92db1de..63a28d997e11a04be36bc02d32df4544a2fc00f8 100644 (file)
@@ -1,22 +1,22 @@
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/issue-47715.rs:9:37
    |
 LL | struct Container<T: Iterable<Item = impl Foo>> {
    |                                     ^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/issue-47715.rs:14:30
    |
 LL | enum Enum<T: Iterable<Item = impl Foo>> {
    |                              ^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/issue-47715.rs:19:32
    |
 LL | union Union<T: Iterable<Item = impl Foo> + Copy> {
    |                                ^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+error[E0562]: `impl Trait` not allowed outside of function and method return types
   --> $DIR/issue-47715.rs:24:30
    |
 LL | type Type<T: Iterable<Item = impl Foo>> = T;
diff --git a/src/test/ui/issues/issue-48636.fixed b/src/test/ui/issues/issue-48636.fixed
deleted file mode 100644 (file)
index 87c19a3..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// run-rustfix
-
-#![allow(dead_code)]
-
-struct S {
-    x: u8,
-    /// The ID of the parent core
-    y: u8,
-}
-//~^^^ ERROR found a documentation comment that doesn't document anything
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-48636.rs b/src/test/ui/issues/issue-48636.rs
deleted file mode 100644 (file)
index 8610dc2..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// run-rustfix
-
-#![allow(dead_code)]
-
-struct S {
-    x: u8
-    /// The ID of the parent core
-    y: u8,
-}
-//~^^^ ERROR found a documentation comment that doesn't document anything
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-48636.stderr b/src/test/ui/issues/issue-48636.stderr
deleted file mode 100644 (file)
index 462723d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0585]: found a documentation comment that doesn't document anything
-  --> $DIR/issue-48636.rs:7:5
-   |
-LL |     x: u8
-   |          - help: missing comma here: `,`
-LL |     /// The ID of the parent core
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0585`.
index ec73e670634df943a1ccb10684d0d493d120d022..119d84a068859f1ad043cd85533063160af0d9ec 100644 (file)
@@ -7,24 +7,24 @@ fn main() {
     struct Foo;
 
     // fold_stmt (Mac)
-    #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions
+    #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
     println!("Hello, world!");
 
     // fold_stmt (Semi)
-    #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions
+    #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
     "Hello, world!";
 
     // fold_stmt (Local)
-    #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions
+    #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
     let _ = "Hello, world!";
 
     // visit_expr
     let _ = #[derive(Debug)] "Hello, world!";
-    //~^ ERROR `derive` may only be applied to structs, enums and unions
+    //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
 
     let _ = [
         // filter_map_expr
-        #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions
+        #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
         "Hello, world!",
     ];
 }
index 7746ad287ab796f945677e5e92d13c1b7a0da827..f2ff541bb9925026215b068ea5c113467cee182d 100644 (file)
@@ -1,32 +1,42 @@
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/issue-49934.rs:10:5
    |
 LL |     #[derive(Debug)]
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^ not applicable here
+LL |     println!("Hello, world!");
+   |     -------------------------- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/issue-49934.rs:14:5
    |
 LL |     #[derive(Debug)]
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^ not applicable here
+LL |     "Hello, world!";
+   |     ---------------- not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/issue-49934.rs:18:5
    |
 LL |     #[derive(Debug)]
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^ not applicable here
+LL |     let _ = "Hello, world!";
+   |     ------------------------ not a `struct`, `enum` or `union`
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/issue-49934.rs:22:13
    |
 LL |     let _ = #[derive(Debug)] "Hello, world!";
-   |             ^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^ --------------- not a `struct`, `enum` or `union`
+   |             |
+   |             not applicable here
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/issue-49934.rs:27:9
    |
 LL |         #[derive(Debug)]
-   |         ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^ not applicable here
+LL |         "Hello, world!",
+   |         --------------- not a `struct`, `enum` or `union`
 
 error: aborting due to 5 previous errors
 
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 0dc588d75c654dfc7338d77ef605ea2140514935..8716524d6f4b527957281101625b8ce3ea9b1261 100644 (file)
@@ -1,13 +1,21 @@
 fn main() {
+//~^ NOTE: not the enclosing function body
+//~| NOTE: not the enclosing function body
+//~| NOTE: not the enclosing function body
+//~| NOTE: not the enclosing function body
     |_:  [_; return || {}] | {};
-    //~^ ERROR return statement outside of function body
+    //~^ ERROR: return statement outside of function body [E0572]
+    //~| NOTE: the return is part of this body...
 
     [(); return || {}];
-    //~^ ERROR return statement outside of function body
+    //~^ ERROR: return statement outside of function body [E0572]
+    //~| NOTE: the return is part of this body...
 
     [(); return |ice| {}];
-    //~^ ERROR return statement outside of function body
+    //~^ ERROR: return statement outside of function body [E0572]
+    //~| NOTE: the return is part of this body...
 
     [(); return while let Some(n) = Some(0) {}];
-    //~^ ERROR return statement outside of function body
+    //~^ ERROR: return statement outside of function body [E0572]
+    //~| NOTE: the return is part of this body...
 }
index 023d9013ab4ed48061d41dc68685977a9888d462..514d69c1c7d3985f6254d32fca7afaed5274189f 100644 (file)
@@ -1,26 +1,62 @@
 error[E0572]: return statement outside of function body
-  --> $DIR/issue-51714.rs:2:14
+  --> $DIR/issue-51714.rs:6:14
    |
-LL |     |_:  [_; return || {}] | {};
-   |              ^^^^^^^^^^^^
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |     |_:  [_; return || {}] | {};
+   | |              ^^^^^^^^^^^^ the return is part of this body...
+...  |
+LL | |
+LL | | }
+   | |_- ...not the enclosing function body
 
 error[E0572]: return statement outside of function body
-  --> $DIR/issue-51714.rs:5:10
+  --> $DIR/issue-51714.rs:10:10
    |
-LL |     [(); return || {}];
-   |          ^^^^^^^^^^^^
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     [(); return || {}];
+   | |          ^^^^^^^^^^^^ the return is part of this body...
+...  |
+LL | |
+LL | | }
+   | |_- ...not the enclosing function body
 
 error[E0572]: return statement outside of function body
-  --> $DIR/issue-51714.rs:8:10
+  --> $DIR/issue-51714.rs:14:10
    |
-LL |     [(); return |ice| {}];
-   |          ^^^^^^^^^^^^^^^
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     [(); return |ice| {}];
+   | |          ^^^^^^^^^^^^^^^ the return is part of this body...
+...  |
+LL | |
+LL | | }
+   | |_- ...not the enclosing function body
 
 error[E0572]: return statement outside of function body
-  --> $DIR/issue-51714.rs:11:10
+  --> $DIR/issue-51714.rs:18:10
    |
-LL |     [(); return while let Some(n) = Some(0) {}];
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     [(); return while let Some(n) = Some(0) {}];
+   | |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body...
+LL | |
+LL | |
+LL | | }
+   | |_- ...not the enclosing function body
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-52169.rs b/src/test/ui/issues/issue-52169.rs
deleted file mode 100644 (file)
index 60be97f..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-pass
-
-macro_rules! a {
-    ($i:literal) => { "right" };
-    ($i:tt) => { "wrong" };
-}
-
-macro_rules! b {
-    ($i:literal) => { a!($i) };
-}
-
-fn main() {
-    assert_eq!(b!(0), "right");
-}
index 3c97dad6b148bb5c4f3dea66fed5e9ea9a47aaef..5c5ce6c987ad124a2bc7662418e98fbf88a1428a 100644 (file)
@@ -9,7 +9,7 @@ trait FontTableTagConversions {
 
 impl FontTableTagConversions for FontTableTag {
   fn tag_to_string(self) {
-    &self;
+      let _ = &self;
   }
 }
 
index 3c0f7f2b55026e6eda83f5b5be03b040d8e69884..b28fbff62b907f6569c61b5ac100e76a0e7125f6 100644 (file)
@@ -1,6 +1,9 @@
 error[E0624]: associated function `foo` is private
   --> $DIR/issue-53498.rs:16:27
    |
+LL |         fn foo() {}
+   |         -------- private associated function defined here
+...
 LL |     test::Foo::<test::B>::foo();
    |                           ^^^ private associated function
 
diff --git a/src/test/ui/issues/issue-54521-1.rs b/src/test/ui/issues/issue-54521-1.rs
deleted file mode 100644 (file)
index 8a682ef..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// check-pass
-
-// This test checks that the `remove extra angle brackets` error doesn't happen for some
-// potential edge-cases..
-
-struct X {
-    len: u32,
-}
-
-fn main() {
-    let x = X { len: 3 };
-
-    let _ = x.len > (3);
-
-    let _ = x.len >> (3);
-}
diff --git a/src/test/ui/issues/issue-54521-2.fixed b/src/test/ui/issues/issue-54521-2.fixed
deleted file mode 100644 (file)
index a91c4fe..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// run-rustfix
-
-// This test checks that the following error is emitted and the suggestion works:
-//
-// ```
-// let _ = Vec::<usize>>>::new();
-//                     ^^ help: remove extra angle brackets
-// ```
-
-fn main() {
-    let _ = Vec::<usize>::new();
-    //~^ ERROR unmatched angle bracket
-
-    let _ = Vec::<usize>::new();
-    //~^ ERROR unmatched angle bracket
-
-    let _ = Vec::<usize>::new();
-    //~^ ERROR unmatched angle bracket
-
-    let _ = Vec::<usize>::new();
-    //~^ ERROR unmatched angle bracket
-}
diff --git a/src/test/ui/issues/issue-54521-2.rs b/src/test/ui/issues/issue-54521-2.rs
deleted file mode 100644 (file)
index 3639aac..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// run-rustfix
-
-// This test checks that the following error is emitted and the suggestion works:
-//
-// ```
-// let _ = Vec::<usize>>>::new();
-//                     ^^ help: remove extra angle brackets
-// ```
-
-fn main() {
-    let _ = Vec::<usize>>>>>::new();
-    //~^ ERROR unmatched angle bracket
-
-    let _ = Vec::<usize>>>>::new();
-    //~^ ERROR unmatched angle bracket
-
-    let _ = Vec::<usize>>>::new();
-    //~^ ERROR unmatched angle bracket
-
-    let _ = Vec::<usize>>::new();
-    //~^ ERROR unmatched angle bracket
-}
diff --git a/src/test/ui/issues/issue-54521-2.stderr b/src/test/ui/issues/issue-54521-2.stderr
deleted file mode 100644 (file)
index 9556b83..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-error: unmatched angle brackets
-  --> $DIR/issue-54521-2.rs:11:25
-   |
-LL |     let _ = Vec::<usize>>>>>::new();
-   |                         ^^^^ help: remove extra angle brackets
-
-error: unmatched angle brackets
-  --> $DIR/issue-54521-2.rs:14:25
-   |
-LL |     let _ = Vec::<usize>>>>::new();
-   |                         ^^^ help: remove extra angle brackets
-
-error: unmatched angle brackets
-  --> $DIR/issue-54521-2.rs:17:25
-   |
-LL |     let _ = Vec::<usize>>>::new();
-   |                         ^^ help: remove extra angle brackets
-
-error: unmatched angle bracket
-  --> $DIR/issue-54521-2.rs:20:25
-   |
-LL |     let _ = Vec::<usize>>::new();
-   |                         ^ help: remove extra angle bracket
-
-error: aborting due to 4 previous errors
-
diff --git a/src/test/ui/issues/issue-54521.fixed b/src/test/ui/issues/issue-54521.fixed
deleted file mode 100644 (file)
index 84ab686..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// run-rustfix
-
-// This test checks that the following error is emitted and the suggestion works:
-//
-// ```
-// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
-//                                                        ^^ help: remove extra angle brackets
-// ```
-
-fn main() {
-    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
-    //~^ ERROR unmatched angle bracket
-
-    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
-    //~^ ERROR unmatched angle bracket
-
-    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
-    //~^ ERROR unmatched angle bracket
-
-    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
-    //~^ ERROR unmatched angle bracket
-}
diff --git a/src/test/ui/issues/issue-54521.rs b/src/test/ui/issues/issue-54521.rs
deleted file mode 100644 (file)
index f1d6850..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// run-rustfix
-
-// This test checks that the following error is emitted and the suggestion works:
-//
-// ```
-// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
-//                                                        ^^ help: remove extra angle brackets
-// ```
-
-fn main() {
-    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>>();
-    //~^ ERROR unmatched angle bracket
-
-    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>();
-    //~^ ERROR unmatched angle bracket
-
-    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
-    //~^ ERROR unmatched angle bracket
-
-    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>();
-    //~^ ERROR unmatched angle bracket
-}
diff --git a/src/test/ui/issues/issue-54521.stderr b/src/test/ui/issues/issue-54521.stderr
deleted file mode 100644 (file)
index ffefbfd..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-error: unmatched angle brackets
-  --> $DIR/issue-54521.rs:11:60
-   |
-LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>>();
-   |                                                            ^^^^ help: remove extra angle brackets
-
-error: unmatched angle brackets
-  --> $DIR/issue-54521.rs:14:60
-   |
-LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>();
-   |                                                            ^^^ help: remove extra angle brackets
-
-error: unmatched angle brackets
-  --> $DIR/issue-54521.rs:17:60
-   |
-LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
-   |                                                            ^^ help: remove extra angle brackets
-
-error: unmatched angle bracket
-  --> $DIR/issue-54521.rs:20:60
-   |
-LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>();
-   |                                                            ^ help: remove extra angle bracket
-
-error: aborting due to 4 previous errors
-
index d8408ed85491f38d83a4e0b3a31b24d6f1bd5796..15355d30db6a561bc5d0512a3609c3bcc2acb203 100644 (file)
@@ -2,7 +2,7 @@
 
 fn main() {
     // We shouldn't promote this
-    &(main as fn() == main as fn());
+    let _ = &(main as fn() == main as fn());
     // Also check nested case
-    &(&(main as fn()) == &(main as fn()));
+    let _ = &(&(main as fn()) == &(main as fn()));
 }
index fb31467ec47fa356adc951b8c6ece17c7d8bc380..a1715bd99e094c8bdd9373465c0dcc157a8bd0e7 100644 (file)
@@ -7,9 +7,6 @@ LL |         Foo(Box::new(*slice))
 error[E0283]: type annotations needed
   --> $DIR/issue-58022.rs:4:25
    |
-LL |     const SIZE: usize;
-   |     ------------------ required by `Foo::SIZE`
-LL | 
 LL |     fn new(slice: &[u8; Foo::SIZE]) -> Self;
    |                         ^^^^^^^^^
    |                         |
@@ -18,6 +15,11 @@ LL |     fn new(slice: &[u8; Foo::SIZE]) -> Self;
    |
    = note: cannot satisfy `_: Foo`
    = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+note: required by `Foo::SIZE`
+  --> $DIR/issue-58022.rs:2:5
+   |
+LL |     const SIZE: usize;
+   |     ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 93d2f3001f8991ecc38cbd1bef301c91f9b88224..46d1f9924118729cec7c2d3dce8171161d4a50c9 100644 (file)
@@ -84,11 +84,6 @@ error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug`
    |
 LL |     assert_eq!(Foo::Bar, i);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   | 
-  ::: $SRC_DIR/core/src/panicking.rs:LL:COL
-   |
-LL |     T: fmt::Debug + ?Sized,
-   |        ---------- required by this bound in `core::panicking::assert_failed`
    |
    = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
index 650570b6471eb13266ce99e8273e68350eaaf272..149562f8fb31c7e61d832fc8e1e9fcf1c2350628 100644 (file)
@@ -10,7 +10,7 @@ LL |     F: for<'a> FnMut(<T as Trait<'a>>::Item),
 LL |     foo((), drop)
    |             ^^^^
    |             |
-   |             expected signature of `fn(<() as Trait<'a>>::Item) -> _`
+   |             expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
    |             found signature of `fn(()) -> _`
 
 error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
index 8fd50300ca63e7d1c7967fad26f02916c857eeec..59a521c7360faaefb8e8ab376e301e9b12c69756 100644 (file)
@@ -7,11 +7,14 @@ LL |     _Func::< <() as _A>::AssocT >::func(());
 error[E0277]: the trait bound `(): _Func<_>` is not satisfied
   --> $DIR/issue-66353.rs:12:41
    |
-LL |     fn func(_: Self);
-   |     ----------------- required by `_Func::func`
-...
 LL |     _Func::< <() as _A>::AssocT >::func(());
    |                                         ^^ the trait `_Func<_>` is not implemented for `()`
+   |
+note: required by `_Func::func`
+  --> $DIR/issue-66353.rs:4:5
+   |
+LL |     fn func(_: Self);
+   |     ^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
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 69fc0c1cbb96b71b0a8fc3ed3aa0acbd42032aaa..6880e1a46293f99a204fcccada17fa1ff91ffd10 100644 (file)
@@ -4,7 +4,7 @@ macro_rules! suite {
             const A = "A".$fn();
             //~^ ERROR the name `A` is defined multiple times
             //~| ERROR missing type for `const` item
-            //~| ERROR the type placeholder `_` is not allowed within types
+            //~| ERROR the type placeholder `_` is not allowed within types on item signatures for constants
         )*
     }
 }
index a84c048fab967dd72ce6fcaa40523a652c123dae..34c2073db0485f05a44b956f35609ad5c345816f 100644 (file)
@@ -20,7 +20,7 @@ error: missing type for `const` item
   --> $DIR/issue-69396-const-no-type-in-macro.rs:4:19
    |
 LL |               const A = "A".$fn();
-   |                     ^ help: provide a type for the item: `A: usize`
+   |                     ^ help: provide a type for the constant: `A: usize`
 ...
 LL | / suite! {
 LL | |     len;
@@ -30,7 +30,7 @@ LL | | }
    |
    = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
   --> $DIR/issue-69396-const-no-type-in-macro.rs:4:19
    |
 LL |               const A = "A".$fn();
diff --git a/src/test/ui/issues/issue-69532.rs b/src/test/ui/issues/issue-69532.rs
deleted file mode 100644 (file)
index 81007b1..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-#![feature(const_fn_transmute)]
-
-const fn make_nans() -> (f64, f64, f32, f32) {
-    let nan1: f64 = unsafe { std::mem::transmute(0x7FF0_0001_0000_0001u64) };
-    let nan2: f64 = unsafe { std::mem::transmute(0x7FF0_0000_0000_0001u64) };
-
-    let nan1_32 = nan1 as f32;
-    let nan2_32 = nan2 as f32;
-
-    (nan1, nan2, nan1_32, nan2_32)
-}
-
-static NANS: (f64, f64, f32, f32) = make_nans();
-
-fn main() {
-    let (nan1, nan2, nan1_32, nan2_32) = NANS;
-
-    assert!(nan1.is_nan());
-    assert!(nan2.is_nan());
-
-    assert!(nan1_32.is_nan());
-    assert!(nan2_32.is_nan());
-}
index 0f095f5a77b231b7e69ad797986dbad7269862d8..f074a99e5ecfb1dfe45058ff2d22d4f7c77976dc 100644 (file)
@@ -28,11 +28,6 @@ LL | fn a() -> i32 {
 ...
 LL |     assert_eq!(a, 0);
    |     ^^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   | 
-  ::: $SRC_DIR/core/src/panicking.rs:LL:COL
-   |
-LL |     T: fmt::Debug + ?Sized,
-   |        ---------- required by this bound in `core::panicking::assert_failed`
    |
    = help: the trait `Debug` is not implemented for `fn() -> i32 {a}`
    = help: use parentheses to call the function: `a()`
index 3443cca5f327058695df5f7bde8e9d57eb726164..af3459a7d2d6fec7194d42c57f85009d3acfc8d3 100644 (file)
@@ -5,7 +5,11 @@ LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
    |
    = note: cannot satisfy `String: From<&_>`
-   = note: required by `from`
+note: required by `from`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn from(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0282]: type annotations needed
   --> $DIR/issue-72690.rs:11:6
@@ -30,7 +34,11 @@ LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
    |
    = note: cannot satisfy `String: From<&_>`
-   = note: required by `from`
+note: required by `from`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn from(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed
   --> $DIR/issue-72690.rs:25:5
@@ -39,7 +47,11 @@ LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
    |
    = note: cannot satisfy `String: From<&_>`
-   = note: required by `from`
+note: required by `from`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn from(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed
   --> $DIR/issue-72690.rs:33:5
@@ -48,7 +60,11 @@ LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
    |
    = note: cannot satisfy `String: From<&_>`
-   = note: required by `from`
+note: required by `from`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn from(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed
   --> $DIR/issue-72690.rs:41:5
@@ -57,7 +73,11 @@ LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
    |
    = note: cannot satisfy `String: From<&_>`
-   = note: required by `from`
+note: required by `from`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn from(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed
   --> $DIR/issue-72690.rs:47:5
@@ -66,7 +86,11 @@ LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
    |
    = note: cannot satisfy `String: From<&_>`
-   = note: required by `from`
+note: required by `from`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn from(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed
   --> $DIR/issue-72690.rs:55:5
@@ -75,7 +99,11 @@ LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
    |
    = note: cannot satisfy `String: From<&_>`
-   = note: required by `from`
+note: required by `from`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn from(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 9 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/issues/issue-74086.rs b/src/test/ui/issues/issue-74086.rs
deleted file mode 100644 (file)
index f68a665..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    static BUG: fn(_) -> u8 = |_| 8;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures [E0121]
-}
diff --git a/src/test/ui/issues/issue-74086.stderr b/src/test/ui/issues/issue-74086.stderr
deleted file mode 100644 (file)
index e602425..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/issue-74086.rs:2:20
-   |
-LL |     static BUG: fn(_) -> u8 = |_| 8;
-   |                    ^ not allowed in type signatures
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/issues/issue-81885.rs b/src/test/ui/issues/issue-81885.rs
deleted file mode 100644 (file)
index 86c39d4..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-const TEST4: fn() -> _ = 42;
-                  //~^ ERROR the type placeholder `_` is not allowed within types on item
-                  //signatures
-
-fn main() {
-    const TEST5: fn() -> _ = 42;
-                      //~^ ERROR the type placeholder `_` is not allowed within types on item
-                      //signatures
-
-}
diff --git a/src/test/ui/issues/issue-81885.stderr b/src/test/ui/issues/issue-81885.stderr
deleted file mode 100644 (file)
index 955b428..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/issue-81885.rs:1:22
-   |
-LL | const TEST4: fn() -> _ = 42;
-   |                      ^ not allowed in type signatures
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/issue-81885.rs:6:26
-   |
-LL |     const TEST5: fn() -> _ = 42;
-   |                          ^ not allowed in type signatures
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/issues/issue-82869.rs b/src/test/ui/issues/issue-82869.rs
deleted file mode 100644 (file)
index a8e688c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// only-x86_64
-// Make sure rustc doesn't ICE on asm! for a foreign architecture.
-
-#![feature(asm)]
-#![crate_type = "rlib"]
-
-pub unsafe fn aarch64(a: f64, b: f64) -> f64 {
-    let c;
-    asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
-        || {};
-        b
-    });
-    //~^^^^ invalid register class
-    //~^^^^^ invalid register class
-    //~^^^^^^ invalid register
-    c
-}
-
-pub unsafe fn x86(a: f64, b: f64) -> f64 {
-    let c;
-    asm!("addsd {}, {}, xmm0", out(xmm_reg) c, in(xmm_reg) a, in("xmm0") b);
-    c
-}
diff --git a/src/test/ui/issues/issue-82869.stderr b/src/test/ui/issues/issue-82869.stderr
deleted file mode 100644 (file)
index d05714e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-error: invalid register class `vreg`: unknown register class
-  --> $DIR/issue-82869.rs:9:32
-   |
-LL |     asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
-   |                                ^^^^^^^^^^^
-
-error: invalid register class `vreg`: unknown register class
-  --> $DIR/issue-82869.rs:9:45
-   |
-LL |     asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
-   |                                             ^^^^^^^^^^
-
-error: invalid register `d0`: unknown register
-  --> $DIR/issue-82869.rs:9:57
-   |
-LL |       asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
-   |  _________________________________________________________^
-LL | |         || {};
-LL | |         b
-LL | |     });
-   | |_____^
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/issues/issue-87199.rs b/src/test/ui/issues/issue-87199.rs
new file mode 100644 (file)
index 0000000..a80a64a
--- /dev/null
@@ -0,0 +1,20 @@
+// Regression test for issue #87199, where attempting to relax a bound
+// other than the only supported `?Sized` would still cause the compiler
+// to assume that the `Sized` bound was relaxed.
+
+// check-fail
+
+// Check that these function definitions only emit warnings, not errors
+fn arg<T: ?Send>(_: T) {}
+//~^ warning: default bound relaxed for a type parameter, but this does nothing
+fn ref_arg<T: ?Send>(_: &T) {}
+//~^ warning: default bound relaxed for a type parameter, but this does nothing
+fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }
+//~^ warning: default bound relaxed for a type parameter, but this does nothing
+
+// Check that there's no `?Sized` relaxation!
+fn main() {
+    ref_arg::<i32>(&5);
+    ref_arg::<[i32]>(&[5]);
+    //~^ the size for values of type `[i32]` cannot be known
+}
diff --git a/src/test/ui/issues/issue-87199.stderr b/src/test/ui/issues/issue-87199.stderr
new file mode 100644 (file)
index 0000000..e3a8e82
--- /dev/null
@@ -0,0 +1,36 @@
+warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
+  --> $DIR/issue-87199.rs:8:8
+   |
+LL | fn arg<T: ?Send>(_: T) {}
+   |        ^
+
+warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
+  --> $DIR/issue-87199.rs:10:12
+   |
+LL | fn ref_arg<T: ?Send>(_: &T) {}
+   |            ^
+
+warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
+  --> $DIR/issue-87199.rs:12:13
+   |
+LL | fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+  --> $DIR/issue-87199.rs:18:22
+   |
+LL | fn ref_arg<T: ?Send>(_: &T) {}
+   |            - required by this bound in `ref_arg`
+...
+LL |     ref_arg::<[i32]>(&[5]);
+   |                      ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[i32]`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | fn ref_arg<T: ?Send + ?Sized>(_: &T) {}
+   |                     ^^^^^^^^
+
+error: aborting due to previous error; 3 warnings emitted
+
+For more information about this error, try `rustc --explain E0277`.
index e31ee59785c8b7ff48691be11a61a3fe184b661a..60b2cbfdf4592f2ddcf24fef389c88d49ad2530a 100644 (file)
@@ -7,7 +7,11 @@ LL |     for _ in 42 {}
    = help: the trait `Iterator` is not implemented for `{integer}`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `{integer}`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `u8` is not an iterator
   --> $DIR/integral.rs:4:14
@@ -18,7 +22,11 @@ LL |     for _ in 42 as u8 {}
    = help: the trait `Iterator` is not implemented for `u8`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `u8`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `i8` is not an iterator
   --> $DIR/integral.rs:6:14
@@ -29,7 +37,11 @@ LL |     for _ in 42 as i8 {}
    = help: the trait `Iterator` is not implemented for `i8`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `i8`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `u16` is not an iterator
   --> $DIR/integral.rs:8:14
@@ -40,7 +52,11 @@ LL |     for _ in 42 as u16 {}
    = help: the trait `Iterator` is not implemented for `u16`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `u16`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `i16` is not an iterator
   --> $DIR/integral.rs:10:14
@@ -51,7 +67,11 @@ LL |     for _ in 42 as i16 {}
    = help: the trait `Iterator` is not implemented for `i16`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `i16`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `u32` is not an iterator
   --> $DIR/integral.rs:12:14
@@ -62,7 +82,11 @@ LL |     for _ in 42 as u32 {}
    = help: the trait `Iterator` is not implemented for `u32`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `u32`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `i32` is not an iterator
   --> $DIR/integral.rs:14:14
@@ -73,7 +97,11 @@ LL |     for _ in 42 as i32 {}
    = help: the trait `Iterator` is not implemented for `i32`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `i32`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `u64` is not an iterator
   --> $DIR/integral.rs:16:14
@@ -84,7 +112,11 @@ LL |     for _ in 42 as u64 {}
    = help: the trait `Iterator` is not implemented for `u64`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `u64`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `i64` is not an iterator
   --> $DIR/integral.rs:18:14
@@ -95,7 +127,11 @@ LL |     for _ in 42 as i64 {}
    = help: the trait `Iterator` is not implemented for `i64`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `i64`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `usize` is not an iterator
   --> $DIR/integral.rs:20:14
@@ -106,7 +142,11 @@ LL |     for _ in 42 as usize {}
    = help: the trait `Iterator` is not implemented for `usize`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `usize`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `isize` is not an iterator
   --> $DIR/integral.rs:22:14
@@ -117,7 +157,11 @@ LL |     for _ in 42 as isize {}
    = help: the trait `Iterator` is not implemented for `isize`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `isize`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `{float}` is not an iterator
   --> $DIR/integral.rs:24:14
@@ -127,7 +171,11 @@ LL |     for _ in 42.0 {}
    |
    = help: the trait `Iterator` is not implemented for `{float}`
    = note: required because of the requirements on the impl of `IntoIterator` for `{float}`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 12 previous errors
 
index 5661397b3c17b2e151b71340de63bfca23bfdef0..e56c2956a697e8fa21cbe738168eb2c8ea188a16 100644 (file)
@@ -12,12 +12,12 @@ fn main() {
     // Before 2021, the method dispatched to `IntoIterator for &[T; N]`,
     // which we continue to support for compatibility.
     let _: Iter<'_, i32> = array.into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
 
     let _: Iter<'_, i32> = Box::new(array).into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
 
     // The `array_into_iter` lint doesn't cover other wrappers that deref to an array.
     let _: Iter<'_, i32> = Rc::new(array).into_iter();
@@ -25,6 +25,10 @@ fn main() {
 
     // But you can always use the trait method explicitly as an array.
     let _: IntoIter<i32, 10> = IntoIterator::into_iter(array);
+
+    for _ in [1, 2, 3].into_iter() {}
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
 }
 
 /// User type that dereferences to an array.
index b43338382f20c25c547c8c62f863d71ca4f68990..3bd3ca6e875a13ddfcab03361aad1dcb41d26a5e 100644 (file)
@@ -1,42 +1,54 @@
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
   --> $DIR/into-iter-on-arrays-2018.rs:14:34
    |
 LL |     let _: Iter<'_, i32> = array.into_iter();
-   |                                  ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+   |                                  ^^^^^^^^^
    |
    = note: `#[warn(array_into_iter)]` 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!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
+   |
+LL |     let _: Iter<'_, i32> = array.iter();
+   |                                  ^^^^
+help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
+   |
+LL |     let _: Iter<'_, i32> = IntoIterator::into_iter(array);
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^     ^
 
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
   --> $DIR/into-iter-on-arrays-2018.rs:18:44
    |
 LL |     let _: Iter<'_, i32> = Box::new(array).into_iter();
-   |                                            ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+   |                                            ^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
-
-warning: 2 warnings emitted
-
-Future incompatibility report: Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-2018.rs:14:34
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
-LL |     let _: Iter<'_, i32> = array.into_iter();
-   |                                  ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     let _: Iter<'_, i32> = Box::new(array).iter();
+   |                                            ^^^^
+help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
    |
-   = note: `#[warn(array_into_iter)]` 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
+LL |     let _: Iter<'_, i32> = IntoIterator::into_iter(Box::new(array));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^               ^
 
-Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-2018.rs:18:44
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-2018.rs:29:24
    |
-LL |     let _: Iter<'_, i32> = Box::new(array).into_iter();
-   |                                            ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     for _ in [1, 2, 3].into_iter() {}
+   |                        ^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
+   |
+LL |     for _ in [1, 2, 3].iter() {}
+   |                        ^^^^
+help: or remove `.into_iter()` to iterate by value
+   |
+LL |     for _ in [1, 2, 3] {}
+   |                      --
+
+warning: 3 warnings emitted
 
index 7f511bde3cbfcd97a9d019b5caf58583da74d6d9..0055758a6a442ab1f8e2a119d7e9a2b2a00b384d 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 // run-rustfix
+// rustfix-only-machine-applicable
 
 fn main() {
     let small = [1, 2];
@@ -7,43 +8,43 @@ fn main() {
 
     // Expressions that should trigger the lint
     small.iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     [1, 2].iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     big.iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     [0u8; 33].iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
 
     Box::new(small).iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     Box::new([1, 2]).iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     Box::new(big).iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     Box::new([0u8; 33]).iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
 
     Box::new(Box::new(small)).iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     Box::new(Box::new([1, 2])).iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     Box::new(Box::new(big)).iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     Box::new(Box::new([0u8; 33])).iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
 
     // Expressions that should not
     (&[1, 2]).into_iter();
index d5fe83a7834b6422d81c466b65793be8374c46a7..01857c78a730c58122c5e62a57c476995353bf1d 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 // run-rustfix
+// rustfix-only-machine-applicable
 
 fn main() {
     let small = [1, 2];
@@ -7,43 +8,43 @@ fn main() {
 
     // Expressions that should trigger the lint
     small.into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     [1, 2].into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     big.into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     [0u8; 33].into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
 
     Box::new(small).into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     Box::new([1, 2]).into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     Box::new(big).into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     Box::new([0u8; 33]).into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
 
     Box::new(Box::new(small)).into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     Box::new(Box::new([1, 2])).into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     Box::new(Box::new(big)).into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     Box::new(Box::new([0u8; 33])).into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
-    //~| WARNING this was previously accepted by the compiler but is being phased out
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
 
     // Expressions that should not
     (&[1, 2]).into_iter();
index 211315c3fcf05d48281d70e90f48bf21c44e96a8..01789e0e257485847031f1b40df54bd885a9ecfb 100644 (file)
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:9:11
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-lint.rs:10:11
    |
 LL |     small.into_iter();
-   |           ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+   |           ^^^^^^^^^
    |
    = note: `#[warn(array_into_iter)]` 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!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
-
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:12:12
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
-LL |     [1, 2].into_iter();
-   |            ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     small.iter();
+   |           ^^^^
+help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
    |
-   = 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
+LL |     IntoIterator::into_iter(small);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^     ^
 
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:15:9
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-lint.rs:13:12
    |
-LL |     big.into_iter();
-   |         ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     [1, 2].into_iter();
+   |            ^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
-
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:18:15
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
-LL |     [0u8; 33].into_iter();
-   |               ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     [1, 2].iter();
+   |            ^^^^
+help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
    |
-   = 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
+LL |     IntoIterator::into_iter([1, 2]);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^      ^
 
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:22:21
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-lint.rs:16:9
    |
-LL |     Box::new(small).into_iter();
-   |                     ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     big.into_iter();
+   |         ^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
-
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:25:22
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
-LL |     Box::new([1, 2]).into_iter();
-   |                      ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     big.iter();
+   |         ^^^^
+help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
    |
-   = 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
+LL |     IntoIterator::into_iter(big);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^   ^
 
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:28:19
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-lint.rs:19:15
    |
-LL |     Box::new(big).into_iter();
-   |                   ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
-   |
-   = 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
-
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:31:25
-   |
-LL |     Box::new([0u8; 33]).into_iter();
-   |                         ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     [0u8; 33].into_iter();
+   |               ^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
-
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:35:31
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
-LL |     Box::new(Box::new(small)).into_iter();
-   |                               ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     [0u8; 33].iter();
+   |               ^^^^
+help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
    |
-   = 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
+LL |     IntoIterator::into_iter([0u8; 33]);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^         ^
 
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:38:32
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-lint.rs:23:21
    |
-LL |     Box::new(Box::new([1, 2])).into_iter();
-   |                                ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new(small).into_iter();
+   |                     ^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
-
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:41:29
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
-LL |     Box::new(Box::new(big)).into_iter();
-   |                             ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new(small).iter();
+   |                     ^^^^
+help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
    |
-   = 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
+LL |     IntoIterator::into_iter(Box::new(small));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^               ^
 
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:44:35
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-lint.rs:26:22
    |
-LL |     Box::new(Box::new([0u8; 33])).into_iter();
-   |                                   ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new([1, 2]).into_iter();
+   |                      ^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
-
-warning: 12 warnings emitted
-
-Future incompatibility report: Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:9:11
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
-LL |     small.into_iter();
-   |           ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new([1, 2]).iter();
+   |                      ^^^^
+help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
    |
-   = note: `#[warn(array_into_iter)]` 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
+LL |     IntoIterator::into_iter(Box::new([1, 2]));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^                ^
 
-Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:12:12
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-lint.rs:29:19
    |
-LL |     [1, 2].into_iter();
-   |            ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new(big).into_iter();
+   |                   ^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
-
-Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:15:9
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
-LL |     big.into_iter();
-   |         ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new(big).iter();
+   |                   ^^^^
+help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
    |
-   = 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
+LL |     IntoIterator::into_iter(Box::new(big));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^             ^
 
-Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:18:15
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-lint.rs:32:25
    |
-LL |     [0u8; 33].into_iter();
-   |               ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new([0u8; 33]).into_iter();
+   |                         ^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
-
-Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:22:21
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
-LL |     Box::new(small).into_iter();
-   |                     ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new([0u8; 33]).iter();
+   |                         ^^^^
+help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
    |
-   = 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
+LL |     IntoIterator::into_iter(Box::new([0u8; 33]));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^                   ^
 
-Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:25:22
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-lint.rs:36:31
    |
-LL |     Box::new([1, 2]).into_iter();
-   |                      ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new(Box::new(small)).into_iter();
+   |                               ^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
-
-Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:28:19
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
-LL |     Box::new(big).into_iter();
-   |                   ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new(Box::new(small)).iter();
+   |                               ^^^^
+help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
    |
-   = 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
+LL |     IntoIterator::into_iter(Box::new(Box::new(small)));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^                         ^
 
-Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:31:25
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-lint.rs:39:32
    |
-LL |     Box::new([0u8; 33]).into_iter();
-   |                         ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new(Box::new([1, 2])).into_iter();
+   |                                ^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
-
-Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:35:31
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
-LL |     Box::new(Box::new(small)).into_iter();
-   |                               ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new(Box::new([1, 2])).iter();
+   |                                ^^^^
+help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
    |
-   = 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
+LL |     IntoIterator::into_iter(Box::new(Box::new([1, 2])));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^                          ^
 
-Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:38:32
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-lint.rs:42:29
    |
-LL |     Box::new(Box::new([1, 2])).into_iter();
-   |                                ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new(Box::new(big)).into_iter();
+   |                             ^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
-
-Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:41:29
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
-LL |     Box::new(Box::new(big)).into_iter();
-   |                             ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new(Box::new(big)).iter();
+   |                             ^^^^
+help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
    |
-   = 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
+LL |     IntoIterator::into_iter(Box::new(Box::new(big)));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^                       ^
 
-Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:44:35
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-lint.rs:45:35
    |
 LL |     Box::new(Box::new([0u8; 33])).into_iter();
-   |                                   ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+   |                                   ^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this changes meaning in Rust 2021
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
-
-Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/into-iter-on-arrays-lint.rs:60:12
+help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
-LL |     [0, 1].into_iter();
-   |            ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+LL |     Box::new(Box::new([0u8; 33])).iter();
+   |                                   ^^^^
+help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
    |
-note: the lint level is defined here
-  --> $DIR/into-iter-on-arrays-lint.rs:59:13
-   |
-LL |     #[allow(array_into_iter)]
-   |             ^^^^^^^^^^^^^^^
-   = 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
+LL |     IntoIterator::into_iter(Box::new(Box::new([0u8; 33])));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^                             ^
+
+warning: 12 warnings emitted
 
index 73844329e361d5d69c8773d8bae997318df9aa3e..fdc33862c0aba1392f72c2c9d5e0fdcc6a7ea261 100644 (file)
@@ -7,7 +7,11 @@ LL |     for _ in ..10 {}
    = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>`
    = note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end`
    = note: required because of the requirements on the impl of `IntoIterator` for `RangeTo<{integer}>`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `RangeToInclusive<{integer}>` is not an iterator
   --> $DIR/ranges.rs:4:14
@@ -18,7 +22,11 @@ LL |     for _ in ..=10 {}
    = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>`
    = note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `RangeToInclusive<{integer}>`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 1d77bcb753630f860ce28fd2999e59ce91a3751e..f7089be2772968ce60112912f3ead2fcd4f14375 100644 (file)
@@ -6,7 +6,11 @@ LL |     for _ in "".to_owned() {}
    |
    = help: the trait `Iterator` is not implemented for `String`
    = note: required because of the requirements on the impl of `IntoIterator` for `String`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `&str` is not an iterator
   --> $DIR/string.rs:4:14
@@ -16,7 +20,11 @@ LL |     for _ in "" {}
    |
    = help: the trait `Iterator` is not implemented for `&str`
    = note: required because of the requirements on the impl of `IntoIterator` for `&str`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/keyword/keyword-self-as-type-param.rs b/src/test/ui/keyword/keyword-self-as-type-param.rs
new file mode 100644 (file)
index 0000000..785d64e
--- /dev/null
@@ -0,0 +1,10 @@
+// Regression test of #36638.
+
+struct Foo<Self>(Self);
+//~^ ERROR expected identifier, found keyword `Self`
+//~^^ ERROR E0392
+
+trait Bar<Self> {}
+//~^ ERROR expected identifier, found keyword `Self`
+
+fn main() {}
diff --git a/src/test/ui/keyword/keyword-self-as-type-param.stderr b/src/test/ui/keyword/keyword-self-as-type-param.stderr
new file mode 100644 (file)
index 0000000..cc3df2e
--- /dev/null
@@ -0,0 +1,24 @@
+error: expected identifier, found keyword `Self`
+  --> $DIR/keyword-self-as-type-param.rs:3:12
+   |
+LL | struct Foo<Self>(Self);
+   |            ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `Self`
+  --> $DIR/keyword-self-as-type-param.rs:7:11
+   |
+LL | trait Bar<Self> {}
+   |           ^^^^ expected identifier, found keyword
+
+error[E0392]: parameter `Self` is never used
+  --> $DIR/keyword-self-as-type-param.rs:3:12
+   |
+LL | struct Foo<Self>(Self);
+   |            ^^^^ unused parameter
+   |
+   = help: consider removing `Self`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `Self` to be a const parameter, use `const Self: usize` instead
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
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
+
index c229458da47daabe37c9dd49650c3faa4d62404a..f7923bd47439f114235b3f16846ae7a56c24e56b 100644 (file)
@@ -1,8 +1,8 @@
 error: values of the type `[u8; 18446744073709551615]` are too big for the current architecture
-  --> $DIR/issue-69485-var-size-diffs-too-large.rs:6:12
+  --> $DIR/issue-69485-var-size-diffs-too-large.rs:6:5
    |
 LL |     Bug::V([0; !0]);
-   |            ^^^^^^^
+   |     ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 74f838e9ed18dd4e4cedfff46f67464dc85facb9..0a7c5a8dbd10b44b374fd8d1b67eddd049389c63 100644 (file)
@@ -13,12 +13,12 @@ impl Assoc for dyn Dyn {}
 fn main() {
     Dyn::func();
     //~^ WARN trait objects without an explicit `dyn` are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
     ::Dyn::func();
     //~^ WARN trait objects without an explicit `dyn` are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
     Dyn::CONST;
     //~^ WARN trait objects without an explicit `dyn` are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
     let _: Dyn::Ty; //~ ERROR ambiguous associated type
 }
index 55c9ea234de29661081f11889c80c6d04fba0128..40fafc4b3b59b7085334612994de57150f5c2b5f 100644 (file)
@@ -11,7 +11,7 @@ LL |     Dyn::func();
    |     ^^^ help: use `dyn`: `<dyn Dyn>`
    |
    = note: `#[warn(bare_trait_objects)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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: trait objects without an explicit `dyn` are deprecated
@@ -20,7 +20,7 @@ warning: trait objects without an explicit `dyn` are deprecated
 LL |     ::Dyn::func();
    |     ^^^^^ help: use `dyn`: `<dyn (::Dyn)>`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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: trait objects without an explicit `dyn` are deprecated
@@ -29,7 +29,7 @@ warning: trait objects without an explicit `dyn` are deprecated
 LL |     Dyn::CONST;
    |     ^^^ help: use `dyn`: `<dyn Dyn>`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: aborting due to previous error; 3 warnings emitted
diff --git a/src/test/ui/lint/cli-lint-override.forbid_warn.stderr b/src/test/ui/lint/cli-lint-override.forbid_warn.stderr
new file mode 100644 (file)
index 0000000..ff4dc4a
--- /dev/null
@@ -0,0 +1,11 @@
+error: extern declarations without an explicit ABI are deprecated
+  --> $DIR/cli-lint-override.rs:12:1
+   |
+LL | extern fn foo() {}
+   | ^^^^^^^^^^^^^^^ ABI should be specified here
+   |
+   = note: requested on the command line with `-F missing-abi`
+   = help: the default ABI is C
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/cli-lint-override.force_warn_deny.stderr b/src/test/ui/lint/cli-lint-override.force_warn_deny.stderr
new file mode 100644 (file)
index 0000000..74e7823
--- /dev/null
@@ -0,0 +1,11 @@
+warning: extern declarations without an explicit ABI are deprecated
+  --> $DIR/cli-lint-override.rs:12:1
+   |
+LL | extern fn foo() {}
+   | ^^^^^^^^^^^^^^^ ABI should be specified here
+   |
+   = note: requested on the command line with `--force-warn missing-abi`
+   = help: the default ABI is C
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/cli-lint-override.rs b/src/test/ui/lint/cli-lint-override.rs
new file mode 100644 (file)
index 0000000..a0a96d0
--- /dev/null
@@ -0,0 +1,17 @@
+// Tests that subsequent lints specified via the command line override
+// each other, except for ForceWarn and Forbid, which cannot be overriden.
+//
+// revisions: warn_deny forbid_warn force_warn_deny
+//
+//[warn_deny] compile-flags: --warn missing_abi --deny missing_abi
+//[forbid_warn] compile-flags: --warn missing_abi --forbid missing_abi
+//[force_warn_deny] compile-flags: -Z unstable-options --force-warn missing_abi --allow missing_abi
+//[force_warn_deny] check-pass
+
+
+extern fn foo() {}
+//[warn_deny]~^ ERROR extern declarations without an explicit ABI are deprecated
+//[forbid_warn]~^^ ERROR extern declarations without an explicit ABI are deprecated
+//[force_warn_deny]~^^^ WARN extern declarations without an explicit ABI are deprecated
+
+fn main() {}
diff --git a/src/test/ui/lint/cli-lint-override.warn_deny.stderr b/src/test/ui/lint/cli-lint-override.warn_deny.stderr
new file mode 100644 (file)
index 0000000..2d869ad
--- /dev/null
@@ -0,0 +1,11 @@
+error: extern declarations without an explicit ABI are deprecated
+  --> $DIR/cli-lint-override.rs:12:1
+   |
+LL | extern fn foo() {}
+   | ^^^^^^^^^^^^^^^ ABI should be specified here
+   |
+   = note: requested on the command line with `-D missing-abi`
+   = help: the default ABI is C
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/cli-unknown-force-warn.rs b/src/test/ui/lint/cli-unknown-force-warn.rs
new file mode 100644 (file)
index 0000000..55544cc
--- /dev/null
@@ -0,0 +1,7 @@
+// Checks that rustc correctly errors when passed an invalid lint with
+// `--force-warn`. This is a regression test for issue #86958.
+//
+// compile-flags: -Z unstable-options --force-warn foo-qux
+// error-pattern: unknown lint: `foo_qux`
+
+fn main() {}
diff --git a/src/test/ui/lint/cli-unknown-force-warn.stderr b/src/test/ui/lint/cli-unknown-force-warn.stderr
new file mode 100644 (file)
index 0000000..4367c3b
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0602]: unknown lint: `foo_qux`
+   |
+   = note: requested on the command line with `--force-warn foo_qux`
+
+error[E0602]: unknown lint: `foo_qux`
+   |
+   = note: requested on the command line with `--force-warn foo_qux`
+
+error[E0602]: unknown lint: `foo_qux`
+   |
+   = note: requested on the command line with `--force-warn foo_qux`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0602`.
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/dead-code/self-assign.rs b/src/test/ui/lint/dead-code/self-assign.rs
new file mode 100644 (file)
index 0000000..ea7ce98
--- /dev/null
@@ -0,0 +1,52 @@
+// Test that dead code warnings are issued for superfluous assignments of
+// fields or variables to themselves (issue #75356).
+
+// ignore-test FIXME(81658, 83171)
+
+// check-pass
+#![allow(unused_assignments)]
+#![warn(dead_code)]
+
+fn main() {
+    let mut x = 0;
+    x = x;
+    //~^ WARNING: useless assignment of variable of type `i32` to itself
+
+    x = (x);
+    //~^ WARNING: useless assignment of variable of type `i32` to itself
+
+    x = {x};
+    // block expressions don't count as self-assignments
+
+
+    struct S<'a> { f: &'a str }
+    let mut s = S { f: "abc" };
+    s = s;
+    //~^ WARNING: useless assignment of variable of type `S` to itself
+
+    s.f = s.f;
+    //~^ WARNING: useless assignment of field of type `&str` to itself
+
+
+    struct N0 { x: Box<i32> }
+    struct N1 { n: N0 }
+    struct N2(N1);
+    struct N3 { n: N2 };
+    let mut n3 = N3 { n: N2(N1 { n: N0 { x: Box::new(42) } }) };
+    n3.n.0.n.x = n3.n.0.n.x;
+    //~^ WARNING: useless assignment of field of type `Box<i32>` to itself
+
+    let mut t = (1, ((2, 3, (4, 5)),));
+    t.1.0.2.1 = t.1.0.2.1;
+    //~^ WARNING: useless assignment of field of type `i32` to itself
+
+
+    let mut y = 0;
+    macro_rules! assign_to_y {
+        ($cur:expr) => {{
+            y = $cur;
+        }};
+    }
+    assign_to_y!(y);
+    // self-assignments in macro expansions are not reported either
+}
diff --git a/src/test/ui/lint/dead-code/self-assign.stderr b/src/test/ui/lint/dead-code/self-assign.stderr
new file mode 100644 (file)
index 0000000..bb79c0e
--- /dev/null
@@ -0,0 +1,44 @@
+warning: useless assignment of variable of type `i32` to itself
+  --> $DIR/self-assign.rs:10:5
+   |
+LL |     x = x;
+   |     ^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/self-assign.rs:6:9
+   |
+LL | #![warn(dead_code)]
+   |         ^^^^^^^^^
+
+warning: useless assignment of variable of type `i32` to itself
+  --> $DIR/self-assign.rs:13:5
+   |
+LL |     x = (x);
+   |     ^^^^^^^
+
+warning: useless assignment of variable of type `S` to itself
+  --> $DIR/self-assign.rs:22:5
+   |
+LL |     s = s;
+   |     ^^^^^
+
+warning: useless assignment of field of type `&str` to itself
+  --> $DIR/self-assign.rs:25:5
+   |
+LL |     s.f = s.f;
+   |     ^^^^^^^^^
+
+warning: useless assignment of field of type `Box<i32>` to itself
+  --> $DIR/self-assign.rs:34:5
+   |
+LL |     n3.n.0.n.x = n3.n.0.n.x;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: useless assignment of field of type `i32` to itself
+  --> $DIR/self-assign.rs:38:5
+   |
+LL |     t.1.0.2.1 = t.1.0.2.1;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+warning: 6 warnings emitted
+
index 0a3e20b4f7d66dbff56971c0fd45df3f1dec2659..4799429ea2c69317f6e084e84fd4ccea37578160 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns elided_lifetimes_in_paths -Zunstable-options
+// compile-flags: --force-warn elided_lifetimes_in_paths -Zunstable-options
 // check-pass
 
 struct Foo<'a> {
index 0e0e934c7655f5796d4b2ace32b2a18a62913552..05513de81d1c85c521b2c14027bd6ac37c150c6e 100644 (file)
@@ -4,7 +4,7 @@ warning: hidden lifetime parameters in types are deprecated
 LL | fn foo(x: &Foo) {}
    |            ^^^- help: indicate the anonymous lifetime: `<'_>`
    |
-   = note: warning forced by `force-warns` commandline option
+   = note: requested on the command line with `--force-warn elided-lifetimes-in-paths`
 
 warning: 1 warning emitted
 
index 0abc49137269d93e6a7f5d0d9a8e472e3b0e6e1b..d066feba86984c99395a78b7460a7cf032d77637 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns const_err -Zunstable-options
+// compile-flags: --force-warn const_err -Zunstable-options
 // check-pass
 
 #![allow(const_err)]
index bad12f94b18053cec336742f321f7ce3b1e37b2c..dd4f88a3b533ee90579ab13a6527e9e7e291bf1b 100644 (file)
@@ -6,7 +6,7 @@ LL | const C: i32 = 1 / 0;
    |                |
    |                attempt to divide `1_i32` by zero
    |
-   = note: warning forced by `force-warns` commandline option
+   = note: requested on the command line with `--force-warn const-err`
    = 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>
 
index bac0e4f8f8e866559d19e08e9c1d033b9ecb6c9f..280de5064720ae7deb70d6aa5fbbcb0ada2121e7 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns dead_code -Zunstable-options
+// compile-flags: --force-warn dead_code -Zunstable-options
 // check-pass
 
 #![allow(dead_code)]
index 145798a32a9eff5c8aa051de6e9d8f30087c6c71..fced147254e82483f9b8bd4e45986a6299eebb3b 100644 (file)
@@ -4,7 +4,7 @@ warning: function is never used: `dead_function`
 LL | fn dead_function() {}
    |    ^^^^^^^^^^^^^
    |
-   = note: warning forced by `force-warns` commandline option
+   = note: requested on the command line with `--force-warn dead-code`
 
 warning: 1 warning emitted
 
index e721760ab2da0a4785e80012eba114842b88b063..8331df02da7637de159e97e103736641747aa0c5 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns const_err -Zunstable-options
+// compile-flags: --force-warn const_err -Zunstable-options
 // check-pass
 
 const C: i32 = 1 / 0;
index 4b004cf367d94cb4b525ac4c866762bfeb779835..68cd3a392f5830c6db2bdf4426ff38811c62d9dd 100644 (file)
@@ -6,7 +6,7 @@ LL | const C: i32 = 1 / 0;
    |                |
    |                attempt to divide `1_i32` by zero
    |
-   = note: warning forced by `force-warns` commandline option
+   = note: requested on the command line with `--force-warn const-err`
    = 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>
 
index 0dc1ce28ac4f5f2e8f42fb00d3d81aa276160d4d..0e8a65a41173d050e599a47acbd8dfbc69aa5597 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns dead_code -Zunstable-options
+// compile-flags: --force-warn dead_code -Zunstable-options
 // check-pass
 
 #![allow(warnings)]
index 577dbe1fea8df452eddc5de2cef378ee62c8ea0e..3305f2c02834d7571ef7024e20d65a47b2dada84 100644 (file)
@@ -4,7 +4,7 @@ warning: function is never used: `dead_function`
 LL | fn dead_function() {}
    |    ^^^^^^^^^^^^^
    |
-   = note: warning forced by `force-warns` commandline option
+   = note: requested on the command line with `--force-warn dead-code`
 
 warning: 1 warning emitted
 
index 4f637c7fefa2b873670b3e7d5f5dc81cf0b5f643..aaca59a2a2aabba9700515c49dad81d9d10dc33d 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns nonstandard_style -Zunstable-options
+// compile-flags: --force-warn nonstandard_style -Zunstable-options
 // check-pass
 
 #![allow(warnings)]
index 8665fa2610a3a08f392f08dad25ee59ca240a08d..065a8f6a556a0d9613c857af8b9abb897a2fa2d4 100644 (file)
@@ -4,7 +4,7 @@ warning: function `FUNCTION` should have a snake case name
 LL | pub fn FUNCTION() {}
    |        ^^^^^^^^ help: convert the identifier to snake case: `function`
    |
-   = note: warning forced by `force-warns` commandline option
+   = note: `--force-warn non-snake-case` implied by `--force-warn nonstandard-style`
 
 warning: 1 warning emitted
 
index bb2f394aef3e69e00d62c70569fde3cd395ae0ad..d8447bd23824440ca3140732cf9f0b9f338af1f3 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns bare_trait_objects -Zunstable-options
+// compile-flags: --force-warn bare_trait_objects -Zunstable-options
 // check-pass
 
 #![allow(rust_2018_idioms)]
@@ -7,6 +7,6 @@ pub trait SomeTrait {}
 
 pub fn function(_x: Box<SomeTrait>) {}
 //~^ WARN trait objects without an explicit `dyn` are deprecated
-//~| WARN this was previously accepted by the compiler
+//~| WARN this is accepted in the current edition
 
 fn main() {}
index 40750ffea8c87f2b717c4d92e39f29f28a8e9947..185c0e8e3d0eba88105739eb1e0821a59ba31dd5 100644 (file)
@@ -4,8 +4,8 @@ warning: trait objects without an explicit `dyn` are deprecated
 LL | pub fn function(_x: Box<SomeTrait>) {}
    |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
    |
-   = note: warning forced by `force-warns` commandline option
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = note: requested on the command line with `--force-warn 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/force-warn/force-warn-cap-lints-allow.rs b/src/test/ui/lint/force-warn/force-warn-cap-lints-allow.rs
new file mode 100644 (file)
index 0000000..e10d161
--- /dev/null
@@ -0,0 +1,10 @@
+// compile-flags: --cap-lints allow  --force-warn 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-warn-cap-lints-allow.stderr b/src/test/ui/lint/force-warn/force-warn-cap-lints-allow.stderr
new file mode 100644 (file)
index 0000000..a899705
--- /dev/null
@@ -0,0 +1,12 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/force-warn-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-warn 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/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..4afc086
--- /dev/null
@@ -0,0 +1,15 @@
+// compile-flags: --cap-lints warn  --force-warn 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..1d5f880
--- /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-warn ellipsis-inclusive-range-patterns` implied by `--force-warn 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
+
index fd029a3d55cb9e0f75bfffe129249f45b1735676..193ba2b6f0da52bbeb597cb0d4443a5c383b0dd6 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns rust_2018_idioms -Zunstable-options
+// compile-flags: --force-warn rust-2018-idioms -Zunstable-options
 // check-pass
 
 #![allow(bare_trait_objects)]
@@ -7,6 +7,6 @@ pub trait SomeTrait {}
 
 pub fn function(_x: Box<SomeTrait>) {}
 //~^ WARN trait objects without an explicit `dyn` are deprecated
-//~| WARN this was previously accepted by the compiler
+//~| WARN this is accepted in the current edition
 
 fn main() {}
index 88ae846caa0a940e5507ca889975b61f50feeae2..d242ef266b8d1a2e2f36ceeef1dd0225927086fe 100644 (file)
@@ -4,8 +4,8 @@ warning: trait objects without an explicit `dyn` are deprecated
 LL | pub fn function(_x: Box<SomeTrait>) {}
    |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
    |
-   = note: warning forced by `force-warns` commandline option
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
+   = 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
index c97eeabbd4e04013e62773c40dbf9f9661a11791..0198610b78e10c8e8fecb7a94588a324c6cf2804 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns rust_2018_idioms -Zunstable-options
+// compile-flags: --force-warn rust_2018_idioms -Zunstable-options
 // check-pass
 
 #![allow(rust_2018_idioms)]
@@ -7,6 +7,6 @@ pub trait SomeTrait {}
 
 pub fn function(_x: Box<SomeTrait>) {}
 //~^ WARN trait objects without an explicit `dyn` are deprecated
-//~| WARN this was previously accepted by the compiler
+//~| WARN this is accepted in the current edition
 
 fn main() {}
index f808727991ed45da83e17d5f4a8262b09316346e..180dff880a65828356280598b923880db57b1045 100644 (file)
@@ -4,8 +4,8 @@ warning: trait objects without an explicit `dyn` are deprecated
 LL | pub fn function(_x: Box<SomeTrait>) {}
    |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
    |
-   = note: warning forced by `force-warns` commandline option
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
+   = 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/future-incompat-test.rs b/src/test/ui/lint/future-incompat-test.rs
new file mode 100644 (file)
index 0000000..ce8c118
--- /dev/null
@@ -0,0 +1,10 @@
+// compile-flags: -Zfuture-incompat-test -Zemit-future-incompat-report
+// check-pass
+
+// The `-Zfuture-incompat-test flag causes any normal warning to be included
+// in the future-incompatible report. The stderr output here should mention
+// the future incompatible report (as extracted by compiletest).
+
+fn main() {
+    let x = 1;
+}
diff --git a/src/test/ui/lint/future-incompat-test.stderr b/src/test/ui/lint/future-incompat-test.stderr
new file mode 100644 (file)
index 0000000..52674a8
--- /dev/null
@@ -0,0 +1,9 @@
+Future incompatibility report: Future breakage diagnostic:
+warning: unused variable: `x`
+  --> $DIR/future-incompat-test.rs:9:9
+   |
+LL |     let x = 1;
+   |         ^ help: if this is intentional, prefix it with an underscore: `_x`
+   |
+   = note: `-A unused-variables` implied by `-A unused`
+
index a1b738e33fa9bdfd50bae3ae63d46fb97b5dba9c..bee5d4ae4b1b330553f1857d936b8e14ea112639 100644 (file)
@@ -8,14 +8,14 @@ fn main() {
     match despondency {
         1..=2 => {}
         //~^ WARN `...` range patterns are deprecated
-        //~| WARN this was previously accepted by the compiler
+        //~| WARN this is accepted in the current edition
         _ => {}
     }
 
     match &despondency {
         &(1..=2) => {}
         //~^ WARN `...` range patterns are deprecated
-        //~| WARN this was previously accepted by the compiler
+        //~| WARN this is accepted in the current edition
         _ => {}
     }
 }
index d3ebbf38e1cba047dbe89b0c5ff3d5b38d01cb2c..d98c10c26c7cfd96e22e7850bf439bbed5d011b5 100644 (file)
@@ -8,14 +8,14 @@ fn main() {
     match despondency {
         1...2 => {}
         //~^ WARN `...` range patterns are deprecated
-        //~| WARN this was previously accepted by the compiler
+        //~| WARN this is accepted in the current edition
         _ => {}
     }
 
     match &despondency {
         &1...2 => {}
         //~^ WARN `...` range patterns are deprecated
-        //~| WARN this was previously accepted by the compiler
+        //~| WARN this is accepted in the current edition
         _ => {}
     }
 }
index ba4ae208e39cb2e01ed5b697c84a91fd04e9e7fd..efa684a24e3d393c5fcba1e45cdc0d03ec21521d 100644 (file)
@@ -9,7 +9,7 @@ note: the lint level is defined here
    |
 LL | #![warn(ellipsis_inclusive_range_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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: `...` range patterns are deprecated
@@ -18,7 +18,7 @@ warning: `...` range patterns are deprecated
 LL |         &1...2 => {}
    |         ^^^^^^ help: use `..=` for an inclusive range: `&(1..=2)`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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: 2 warnings emitted
diff --git a/src/test/ui/lint/issue-78660-cap-lints-future-compat.rs b/src/test/ui/lint/issue-78660-cap-lints-future-compat.rs
deleted file mode 100644 (file)
index 4d98f0a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// compile-flags: -D warnings --cap-lints allow
-// check-pass
-
-// Regression test for issue #78660
-// Tests that we don't ICE when a future-incompat-report lint has
-// has a command-line source, but is capped to allow
-
-fn main() {
-    ["hi"].into_iter();
-}
diff --git a/src/test/ui/lint/issue-78660-cap-lints-future-compat.stderr b/src/test/ui/lint/issue-78660-cap-lints-future-compat.stderr
deleted file mode 100644 (file)
index 79958ba..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-Future incompatibility report: Future breakage date: None, diagnostic:
-warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
-  --> $DIR/issue-78660-cap-lints-future-compat.rs:9:12
-   |
-LL |     ["hi"].into_iter();
-   |            ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
-   |
-   = note: `-D array-into-iter` implied by `-D warnings`
-   = 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 #66145 <https://github.com/rust-lang/rust/issues/66145>
-
index ab62f0c8b8c897bcc37e586d4df23f4533c24a1c..4262a28799db26ac412e30a243e34c9a7824d82e 100644 (file)
@@ -12,6 +12,5 @@
 //~| SUGGESTION rustc::default_hash_types
 fn main() {
     let _ = std::collections::HashMap::<String, String>::new();
-    //~^ WARN Prefer FxHashMap over HashMap, it has better performance
-    //~| HELP use
+    //~^ WARN prefer `FxHashMap` over `HashMap`, it has better performance
 }
index 028890f3623df8a477493ef022784aed4b48d079..e619bcfe23f6408740678c9a0eb916cd6743e9f0 100644 (file)
@@ -12,11 +12,11 @@ warning: unknown lint: `rustc::foo::default_hash_types`
 LL | #[allow(rustc::foo::default_hash_types)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `rustc::default_hash_types`
 
-warning: Prefer FxHashMap over HashMap, it has better performance
-  --> $DIR/issue-83477.rs:14:31
+warning: prefer `FxHashMap` over `HashMap`, it has better performance
+  --> $DIR/issue-83477.rs:14:13
    |
 LL |     let _ = std::collections::HashMap::<String, String>::new();
-   |                               ^^^^^^^ help: use: `FxHashMap`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/issue-83477.rs:3:9
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
+
diff --git a/src/test/ui/lint/issue-87274-paren-parent.rs b/src/test/ui/lint/issue-87274-paren-parent.rs
new file mode 100644 (file)
index 0000000..0141c5a
--- /dev/null
@@ -0,0 +1,9 @@
+// check-pass
+// Tests that we properly lint at 'paren' expressions
+
+fn foo() -> Result<(), String>  {
+    (try!(Ok::<u8, String>(1))); //~ WARN use of deprecated macro `try`
+    Ok(())
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/issue-87274-paren-parent.stderr b/src/test/ui/lint/issue-87274-paren-parent.stderr
new file mode 100644 (file)
index 0000000..f060242
--- /dev/null
@@ -0,0 +1,10 @@
+warning: use of deprecated macro `try`: use the `?` operator instead
+  --> $DIR/issue-87274-paren-parent.rs:5:6
+   |
+LL |     (try!(Ok::<u8, String>(1)));
+   |      ^^^
+   |
+   = note: `#[warn(deprecated)]` on by default
+
+warning: 1 warning emitted
+
index 6efd03f14a1dcb14e6e9945f0c6646b855925588..3355bb4e4ff402042bdf9a708d7d4de0db5d6161 100644 (file)
@@ -5,7 +5,7 @@ LL | pub fn try() {}
    |        ^^^ help: you can use a raw identifier to stay compatible: `r#try`
    |
    = note: `-W keyword-idents` implied by `-W rust-2018-compatibility`
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 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
 
index c36a8b2a4bf8c39babdc14570940cc9e8b4cd9d8..2d842d5142097e0eb37596f0e86744e582c8ecc6 100644 (file)
@@ -6,4 +6,8 @@
                    //~| HELP did you mean
                    //~| SUGGESTION dead_code
 
+#![deny(rust_2018_idiots)] //~ ERROR unknown lint
+                           //~| HELP did you mean
+                           //~| SUGGESTION rust_2018_idioms
+
 fn main() {}
index 3a102769e855b4696df7e0567cf184ad42f71fa7..0cb6b49578cf30490bbe0426d6c4ed0554dde053 100644 (file)
@@ -16,5 +16,11 @@ error: unknown lint: `dead_cod`
 LL | #![deny(dead_cod)]
    |         ^^^^^^^^ help: did you mean: `dead_code`
 
-error: aborting due to 2 previous errors
+error: unknown lint: `rust_2018_idiots`
+  --> $DIR/lint-unknown-lint.rs:9:9
+   |
+LL | #![deny(rust_2018_idiots)]
+   |         ^^^^^^^^^^^^^^^^ help: did you mean: `rust_2018_idioms`
+
+error: aborting due to 3 previous errors
 
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 0bbd7dc6c8a7aff906f98990f7c63997aa00d879..fff380934e8e9be3f682b211f087d1576ae8f79b 100644 (file)
@@ -1,14 +1,17 @@
 // check-pass
 // edition:2018
+#![feature(stmt_expr_attributes)]
 #![warn(semicolon_in_expressions_from_macros)]
 
 #[allow(dead_code)]
 macro_rules! foo {
     ($val:ident) => {
-        true; //~ WARN trailing
-              //~| WARN this was previously
-              //~| WARN trailing
-              //~| WARN this was previously
+        true; //~  WARN trailing semicolon in macro
+              //~| WARN this was previously accepted
+              //~| WARN trailing semicolon in macro
+              //~| WARN this was previously accepted
+              //~| WARN trailing semicolon in macro
+              //~| WARN this was previously accepted
     }
 }
 
@@ -18,17 +21,14 @@ async fn bar() {
 }
 
 fn main() {
-    // This `allow` doesn't work
     #[allow(semicolon_in_expressions_from_macros)]
     let _ = {
         foo!(first)
     };
 
-    // This 'allow' doesn't work either
     #[allow(semicolon_in_expressions_from_macros)]
     let _ = foo!(second);
 
-    // But this 'allow' does
     #[allow(semicolon_in_expressions_from_macros)]
     fn inner() {
         let _ = foo!(third);
@@ -38,4 +38,14 @@ fn main() {
     async {
         let _ = foo!(fourth);
     };
+
+    let _ = {
+        foo!(warn_in_block)
+    };
+
+    let _ = foo!(warn_in_expr);
+
+    // This `#[allow]` does not work, since the attribute gets dropped
+    // when we expand the macro
+    let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work);
 }
index 111ebea61dd12c94499ab583a31d7165214cc9a3..c00c3d77dcedc8bd961f165d6a7551b2b001374b 100644 (file)
@@ -1,14 +1,14 @@
 warning: trailing semicolon in macro used in expression position
-  --> $DIR/semicolon-in-expressions-from-macros.rs:8:13
+  --> $DIR/semicolon-in-expressions-from-macros.rs:9:13
    |
 LL |         true;
    |             ^
 ...
-LL |         foo!(first)
-   |         ----------- in this macro invocation
+LL |         foo!(warn_in_block)
+   |         ------------------- in this macro invocation
    |
 note: the lint level is defined here
-  --> $DIR/semicolon-in-expressions-from-macros.rs:3:9
+  --> $DIR/semicolon-in-expressions-from-macros.rs:4:9
    |
 LL | #![warn(semicolon_in_expressions_from_macros)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,17 +17,30 @@ LL | #![warn(semicolon_in_expressions_from_macros)]
    = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: trailing semicolon in macro used in expression position
-  --> $DIR/semicolon-in-expressions-from-macros.rs:8:13
+  --> $DIR/semicolon-in-expressions-from-macros.rs:9:13
    |
 LL |         true;
    |             ^
 ...
-LL |     let _ = foo!(second);
-   |             ------------ in this macro invocation
+LL |     let _ = foo!(warn_in_expr);
+   |             ------------------ in this macro invocation
    |
    = 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 #79813 <https://github.com/rust-lang/rust/issues/79813>
    = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-warning: 2 warnings emitted
+warning: trailing semicolon in macro used in expression position
+  --> $DIR/semicolon-in-expressions-from-macros.rs:9:13
+   |
+LL |         true;
+   |             ^
+...
+LL |     let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work);
+   |                                                            ------------------------- in this macro invocation
+   |
+   = 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 #79813 <https://github.com/rust-lang/rust/issues/79813>
+   = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 3 warnings emitted
 
diff --git a/src/test/ui/lint/unused-borrows.rs b/src/test/ui/lint/unused-borrows.rs
new file mode 100644 (file)
index 0000000..4518522
--- /dev/null
@@ -0,0 +1,33 @@
+#![deny(unused_must_use)]
+
+fn foo(_: i32) -> bool { todo!() }
+
+fn bar() -> &'static i32 {
+    &42;
+    //~^ unused
+
+    &mut foo(42);
+    //~^ unused
+
+    &&42;
+    //~^ unused
+
+    &&mut 42;
+    //~^ unused
+
+    &mut &42;
+    //~^ unused
+
+    let _result = foo(4)
+        && foo(2); // Misplaced semi-colon (perhaps due to reordering of lines)
+    && foo(42);
+    //~^ unused
+
+    let _ = &42; // ok
+
+    &42 // ok
+}
+
+fn main() {
+    let _ = bar();
+}
diff --git a/src/test/ui/lint/unused-borrows.stderr b/src/test/ui/lint/unused-borrows.stderr
new file mode 100644 (file)
index 0000000..24899fe
--- /dev/null
@@ -0,0 +1,44 @@
+error: unused borrow that must be used
+  --> $DIR/unused-borrows.rs:6:5
+   |
+LL |     &42;
+   |     ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-borrows.rs:1:9
+   |
+LL | #![deny(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+
+error: unused borrow that must be used
+  --> $DIR/unused-borrows.rs:9:5
+   |
+LL |     &mut foo(42);
+   |     ^^^^^^^^^^^^
+
+error: unused borrow that must be used
+  --> $DIR/unused-borrows.rs:12:5
+   |
+LL |     &&42;
+   |     ^^^^
+
+error: unused borrow that must be used
+  --> $DIR/unused-borrows.rs:15:5
+   |
+LL |     &&mut 42;
+   |     ^^^^^^^^
+
+error: unused borrow that must be used
+  --> $DIR/unused-borrows.rs:18:5
+   |
+LL |     &mut &42;
+   |     ^^^^^^^^
+
+error: unused borrow that must be used
+  --> $DIR/unused-borrows.rs:23:5
+   |
+LL |     && foo(42);
+   |     ^^^^^^^^^^
+
+error: aborting due to 6 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());
diff --git a/src/test/ui/macros/auxiliary/or-pattern.rs b/src/test/ui/macros/auxiliary/or-pattern.rs
new file mode 100644 (file)
index 0000000..a319c40
--- /dev/null
@@ -0,0 +1,6 @@
+#![crate_type = "lib"]
+
+#[macro_export]
+macro_rules! a {
+    ($x:pat|) => ();
+}
diff --git a/src/test/ui/macros/issue-52169.rs b/src/test/ui/macros/issue-52169.rs
new file mode 100644 (file)
index 0000000..60be97f
--- /dev/null
@@ -0,0 +1,14 @@
+// run-pass
+
+macro_rules! a {
+    ($i:literal) => { "right" };
+    ($i:tt) => { "wrong" };
+}
+
+macro_rules! b {
+    ($i:literal) => { a!($i) };
+}
+
+fn main() {
+    assert_eq!(b!(0), "right");
+}
diff --git a/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.rs b/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.rs
new file mode 100644 (file)
index 0000000..9139775
--- /dev/null
@@ -0,0 +1,16 @@
+// Regression test for #84632: Recursion limit is ignored
+// for builtin macros that eagerly expands.
+
+#![recursion_limit = "15"]
+macro_rules! a {
+    () => ("");
+    (A) => (concat!("", a!()));
+    (A, $($A:ident),*) => (concat!("", a!($($A),*)))
+    //~^ ERROR recursion limit reached
+    //~| HELP consider adding
+}
+
+fn main() {
+    a!(A, A, A, A, A);
+    a!(A, A, A, A, A, A, A, A, A, A, A);
+}
diff --git a/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr b/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr
new file mode 100644 (file)
index 0000000..e6067e3
--- /dev/null
@@ -0,0 +1,14 @@
+error: recursion limit reached while expanding `concat!`
+  --> $DIR/issue-84632-eager-expansion-recursion-limit.rs:8:28
+   |
+LL |     (A, $($A:ident),*) => (concat!("", a!($($A),*)))
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     a!(A, A, A, A, A, A, A, A, A, A, A);
+   |     ------------------------------------ in this macro invocation
+   |
+   = help: consider adding a `#![recursion_limit="30"]` attribute to your crate (`issue_84632_eager_expansion_recursion_limit`)
+   = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
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 f829129d516b2247ff39aa5b9533bc6f91e5ea5a..b0d56e9bb1ef0a5bd97923bf1b572401c1df7e38 100644 (file)
@@ -1,14 +1,28 @@
 // run-rustfix
+// aux-build:or-pattern.rs
 
-#![deny(or_patterns_back_compat)]
+#![deny(rust_2021_incompatible_or_patterns)]
 #![allow(unused_macros)]
-macro_rules! foo { ($x:pat_param | $y:pat) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-macro_rules! bar { ($($x:pat_param)+ | $($y:pat)+) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+
+#[macro_use]
+extern crate or_pattern;
+
+macro_rules! foo { ($x:pat_param | $y:pat) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this is accepted in the current edition
+macro_rules! bar { ($($x:pat_param)+ | $($y:pat)+) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this is accepted in the current edition
+
 macro_rules! baz { ($x:pat_param | $y:pat_param) => {} } // should be ok
 macro_rules! qux { ($x:pat_param | $y:pat) => {} } // should be ok
-macro_rules! ogg { ($x:pat_param | $y:pat_param) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+macro_rules! ogg { ($x:pat_param | $y:pat_param) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this is accepted in the current edition
 macro_rules! match_any {
-    ( $expr:expr , $( $( $pat:pat_param )|+ => $expr_arm:expr ),+ ) => { //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+    ( $expr:expr , $( $( $pat:pat_param )|+ => $expr_arm:expr ),+ ) => {
+        //~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+        //~| WARN this is accepted in the current edition
         match $expr {
             $(
                 $( $pat => $expr_arm, )+
@@ -21,4 +35,5 @@ fn main() {
     let result: Result<i64, i32> = Err(42);
     let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into());
     assert_eq!(int, 42);
+    a!(1|);
 }
index 1cdaa1cd6317bc8d809a7f445c1e51d554df53bb..9e24b5106b8bf528fbf3b5fdfdc71745a19ac4d5 100644 (file)
@@ -1,14 +1,28 @@
 // run-rustfix
+// aux-build:or-pattern.rs
 
-#![deny(or_patterns_back_compat)]
+#![deny(rust_2021_incompatible_or_patterns)]
 #![allow(unused_macros)]
-macro_rules! foo { ($x:pat | $y:pat) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+
+#[macro_use]
+extern crate or_pattern;
+
+macro_rules! foo { ($x:pat | $y:pat) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this is accepted in the current edition
+macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this is accepted in the current edition
+
 macro_rules! baz { ($x:pat_param | $y:pat_param) => {} } // should be ok
 macro_rules! qux { ($x:pat_param | $y:pat) => {} } // should be ok
-macro_rules! ogg { ($x:pat | $y:pat_param) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+macro_rules! ogg { ($x:pat | $y:pat_param) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this is accepted in the current edition
 macro_rules! match_any {
-    ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+    ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
+        //~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+        //~| WARN this is accepted in the current edition
         match $expr {
             $(
                 $( $pat => $expr_arm, )+
@@ -21,4 +35,5 @@ fn main() {
     let result: Result<i64, i32> = Err(42);
     let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into());
     assert_eq!(int, 42);
+    a!(1|);
 }
index 01d220dd0b11473450c13bb4ba80902339dc83be..eb6204fa02e69221dc89aee8af589b70bbbc1d97 100644 (file)
@@ -1,32 +1,43 @@
 error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-  --> $DIR/macro-or-patterns-back-compat.rs:5:21
+  --> $DIR/macro-or-patterns-back-compat.rs:10:21
    |
 LL | macro_rules! foo { ($x:pat | $y:pat) => {} }
    |                     ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param`
    |
 note: the lint level is defined here
-  --> $DIR/macro-or-patterns-back-compat.rs:3:9
+  --> $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>
 
 error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-  --> $DIR/macro-or-patterns-back-compat.rs:6:23
+  --> $DIR/macro-or-patterns-back-compat.rs:13:23
    |
 LL | macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} }
    |                       ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param`
+   |
+   = 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>
 
 error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-  --> $DIR/macro-or-patterns-back-compat.rs:9:21
+  --> $DIR/macro-or-patterns-back-compat.rs:19:21
    |
 LL | macro_rules! ogg { ($x:pat | $y:pat_param) => {} }
    |                     ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param`
+   |
+   = 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>
 
 error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-  --> $DIR/macro-or-patterns-back-compat.rs:11:26
+  --> $DIR/macro-or-patterns-back-compat.rs:23:26
    |
 LL |     ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
    |                          ^^^^^^^^ help: use pat_param to preserve semantics: `$pat:pat_param`
+   |
+   = 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>
 
 error: aborting due to 4 previous errors
 
index 5a8e2f50ce33d2fbca03f7f73da240fbe2c3e520..b2fdd2e1965818fbb2543551d1e88f21dc10e6a7 100644 (file)
@@ -39,5 +39,5 @@ fn main() {
 #[my_macro]
 fn use_bang_macro_as_attr() {}
 
-#[derive(Debug)] //~ ERROR `derive` may only be applied to structs
+#[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s
 fn use_derive_macro_as_attr() {}
index 96e7d61398b7e052230f3fe2ecbc2ee3c1d00164..38affde5f6c3301ac07522fe34fea420cb56c99b 100644 (file)
@@ -60,11 +60,13 @@ LL |     let a = pat_macro!();
    |
    = note: this error originates in the macro `pat_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/trace_faulty_macros.rs:42:1
    |
 LL | #[derive(Debug)]
-   | ^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^ not applicable here
+LL | fn use_derive_macro_as_attr() {}
+   | -------------------------------- not a `struct`, `enum` or `union`
 
 note: trace_macro
   --> $DIR/trace_faulty_macros.rs:36:13
index aff19094b7af8c2ed24eaddf7cce01eed9fc0d0d..543d15fadc6be78762074d7186b385c7aee5db45 100644 (file)
@@ -7,15 +7,11 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
-error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/issue-75053.rs:52:15
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/issue-75053.rs:49:1
    |
-LL |     let _pos: Phantom1<DummyT<()>> = Scope::new().my_index();
-   |               ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+LL | fn main() {
+   | ^^^^^^^^^
 
 error: aborting due to previous error; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0658`.
index a43fabc8f5d91a55fcd31109a15117f9f607c446..d75996bf0b3ae3615b4c9bdab12390bdcd4ba889 100644 (file)
@@ -1,24 +1,11 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
+error[E0557]: feature has been removed
   --> $DIR/issue-75053.rs:7:34
    |
 LL | #![cfg_attr(in_bindings, feature(impl_trait_in_bindings))]
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^ feature has been removed
    |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = note: removed due to being incomplete and unstable
 
-error[E0282]: type annotations needed
-  --> $DIR/issue-75053.rs:52:38
-   |
-LL |     type O;
-   |     ------- `<Self as MyIndex<T>>::O` defined here
-...
-LL |     let _pos: Phantom1<DummyT<()>> = Scope::new().my_index();
-   |                                      ^^^^^^^^^^-------------
-   |                                      |
-   |                                      this method call resolves to `<Self as MyIndex<T>>::O`
-   |                                      cannot infer type for type parameter `T`
-
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0557`.
index 7ce91e851a755399783e5fee7a53ce54ea051681..c533275c99a79554657bdf219d9e567b90c8fc79 100644 (file)
@@ -1,12 +1,8 @@
-error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/issue-75053.rs:52:15
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/issue-75053.rs:49:1
    |
-LL |     let _pos: Phantom1<DummyT<()>> = Scope::new().my_index();
-   |               ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+LL | fn main() {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
index 89ae3ca3006b951ff22de0c6d506ff64903a623f..b71f84dd9c24ef730bd79afb21a5324ab194e4e7 100644 (file)
@@ -1,11 +1,9 @@
 // compile-flags: -Z mir-opt-level=3
 
-// revisions: min_tait full_tait in_bindings
+// revisions: min_tait full_tait
 #![feature(min_type_alias_impl_trait, rustc_attrs)]
 #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
 //[full_tait]~^ WARN incomplete
-#![cfg_attr(in_bindings, feature(impl_trait_in_bindings))]
-//[in_bindings]~^ WARN incomplete
 
 use std::marker::PhantomData;
 
@@ -49,7 +47,6 @@ impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<Phantom1<T>> for Scope<U> {
 
 #[rustc_error]
 fn main() {
+    //~^ ERROR
     let _pos: Phantom1<DummyT<()>> = Scope::new().my_index();
-    //[min_tait,full_tait]~^ ERROR not permitted here
-    //[in_bindings]~^^ ERROR type annotations needed
 }
index 4d404d015ec0b017e96f4827f1740bc02c9428a8..0086d2ec18cfad98d05f8a9f1603749d00c8ea28 100644 (file)
@@ -5,6 +5,6 @@
 fn main() {}
 
 fn foo(_: Bar, ...) -> impl {}
-//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
 //~| ERROR cannot find type `Bar` in this scope
 //~| ERROR at least one trait must be specified
index eb172684899cfbdd92f8de352591358fb514a241..4eb3adc8b4f1c88e9212869c1bf7e537f7349fa3 100644 (file)
@@ -1,4 +1,4 @@
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/issue-83499-input-output-iteration-ice.rs:7:16
    |
 LL | fn foo(_: Bar, ...) -> impl {}
index 0385a120ce21314996a1859ee31aea166360d965..86fd37e78142c651a6071fd72110daf02b88f1f1 100644 (file)
@@ -1,6 +1,6 @@
 // Tests correct kind-checking of the reason stack closures without the :Copy
 // bound must be noncopyable. For details see
-// http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/
+// https://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/
 
 struct R<'a> {
     // This struct is needed to create the
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) {
diff --git a/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs b/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs
new file mode 100644 (file)
index 0000000..7253d35
--- /dev/null
@@ -0,0 +1,55 @@
+// run-pass
+// This test illustrates that under NLL, we can remove our overly
+// conservative approach for disallowing mutations of match inputs.
+
+// See further discussion on rust-lang/rust#24535,
+// rust-lang/rfcs#1006, and rust-lang/rfcs#107
+
+fn main() {
+    rust_issue_24535();
+    rfcs_issue_1006_1();
+    rfcs_issue_1006_2();
+}
+
+fn rust_issue_24535() {
+    fn compare(a: &u8, b: &mut u8) -> bool {
+        a == b
+    }
+
+    let a = 3u8;
+
+    match a {
+        0 => panic!("nope"),
+        3 if compare(&a, &mut 3) => (),
+        _ => panic!("nope"),
+    }
+}
+
+fn rfcs_issue_1006_1() {
+    let v = vec!["1".to_string(), "2".to_string(), "3".to_string()];
+    match Some(&v) {
+        Some(iv) if iv.iter().any(|x| &x[..]=="2") => true,
+        _ => panic!("nope"),
+    };
+}
+
+fn rfcs_issue_1006_2() {
+    #[inline(always)]
+    fn check<'a, I: Iterator<Item=&'a i32>>(mut i: I) -> bool {
+        i.any(|&x| x == 2)
+    }
+
+    let slice = [1, 2, 3];
+
+    match 42 {
+        _ if slice.iter().any(|&x| x == 2) => { true },
+        _ => { panic!("nope"); }
+    };
+
+    // (This match is just illustrating how easy it was to circumvent
+    // the checking performed for the previous `match`.)
+    match 42 {
+        _ if check(slice.iter()) => { true },
+        _ => { panic!("nope"); }
+    };
+}
diff --git a/src/test/ui/nll/issue-45157.rs b/src/test/ui/nll/issue-45157.rs
new file mode 100644 (file)
index 0000000..8d2bf22
--- /dev/null
@@ -0,0 +1,31 @@
+#![allow(unused)]
+
+
+#[derive(Clone, Copy, Default)]
+struct S {
+    a: u8,
+    b: u8,
+}
+#[derive(Clone, Copy, Default)]
+struct Z {
+    c: u8,
+    d: u8,
+}
+
+union U {
+    s: S,
+    z: Z,
+}
+
+fn main() {
+    unsafe {
+        let mut u = U { s: Default::default() };
+
+        let mref = &mut u.s.a;
+        *mref = 22;
+
+        let nref = &u.z.c;
+        //~^ ERROR cannot borrow `u` (via `u.z.c`) as immutable because it is also borrowed as mutable (via `u.s.a`) [E0502]
+        println!("{} {}", mref, nref)
+    }
+}
diff --git a/src/test/ui/nll/issue-45157.stderr b/src/test/ui/nll/issue-45157.stderr
new file mode 100644 (file)
index 0000000..57fd8d4
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0502]: cannot borrow `u` (via `u.z.c`) as immutable because it is also borrowed as mutable (via `u.s.a`)
+  --> $DIR/issue-45157.rs:27:20
+   |
+LL |         let mref = &mut u.s.a;
+   |                    ---------- mutable borrow occurs here (via `u.s.a`)
+...
+LL |         let nref = &u.z.c;
+   |                    ^^^^^^ immutable borrow of `u.z.c` -- which overlaps with `u.s.a` -- occurs here
+LL |
+LL |         println!("{} {}", mref, nref)
+   |                           ---- mutable borrow later used here
+   |
+   = note: `u.z.c` is a field of the union `U`, so it overlaps the field `u.s.a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
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 69d7cdd83a6a1023964889e9c20077daa2ac9e87..2458b171e645851b864c976842950fce9a4f9b35 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 
 #![deny(unused_mut)]
+#![allow(dead_code)]
 
 struct Foo {
     pub value: i32
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 d003acd879a77407d9d161ee6345381fe0944893..8c7c8918f3fc60d5d63127de280eb492ea3cb8dc 100644 (file)
@@ -1,8 +1,8 @@
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` due to conflicting requirements
-  --> $DIR/normalization-bounds-error.rs:12:1
+  --> $DIR/normalization-bounds-error.rs:12:4
    |
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |    ^^^^^^^^^
    |
 note: first, the lifetime cannot outlive the lifetime `'d` as defined on the function body at 12:14...
   --> $DIR/normalization-bounds-error.rs:12:14
@@ -15,10 +15,10 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined on
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
    |                  ^^
 note: ...so that the types are compatible
-  --> $DIR/normalization-bounds-error.rs:12:1
+  --> $DIR/normalization-bounds-error.rs:12:4
    |
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |    ^^^^^^^^^
    = note: expected `Visitor<'d>`
               found `Visitor<'_>`
 
diff --git a/src/test/ui/non-constant-in-const-path.rs b/src/test/ui/non-constant-in-const-path.rs
deleted file mode 100644 (file)
index 343bb98..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
-    let x = 0;
-    match 1 {
-        0 ..= x => {}
-        //~^ ERROR runtime values cannot be referenced in patterns
-    };
-}
diff --git a/src/test/ui/non-constant-in-const-path.stderr b/src/test/ui/non-constant-in-const-path.stderr
deleted file mode 100644 (file)
index 5936f76..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0080]: runtime values cannot be referenced in patterns
-  --> $DIR/non-constant-in-const-path.rs:4:15
-   |
-LL |         0 ..= x => {}
-   |               ^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
index 3278eb5f0238e41db4b3b71a8731755c9b7dddaf..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
    |
@@ -61,7 +61,8 @@ warning: panic message is not a string literal
 LL |     assert!(false, S);
    |                    ^
    |
-   = note: this is no longer accepted in Rust 2021
+   = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
 help: add a "{}" format string to Display the message
    |
 LL |     assert!(false, "{}", S);
@@ -85,7 +86,8 @@ warning: panic message is not a string literal
 LL |     panic!(C);
    |            ^
    |
-   = note: this is no longer accepted in Rust 2021
+   = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
 help: add a "{}" format string to Display the message
    |
 LL |     panic!("{}", C);
@@ -101,7 +103,8 @@ warning: panic message is not a string literal
 LL |     panic!(S);
    |            ^
    |
-   = note: this is no longer accepted in Rust 2021
+   = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
 help: add a "{}" format string to Display the message
    |
 LL |     panic!("{}", S);
@@ -117,7 +120,8 @@ warning: panic message is not a string literal
 LL |     std::panic!(123);
    |                 ^^^
    |
-   = note: this is no longer accepted in Rust 2021
+   = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
 help: add a "{}" format string to Display the message
    |
 LL |     std::panic!("{}", 123);
@@ -133,7 +137,8 @@ warning: panic message is not a string literal
 LL |     core::panic!(&*"abc");
    |                  ^^^^^^^
    |
-   = note: this is no longer accepted in Rust 2021
+   = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
 help: add a "{}" format string to Display the message
    |
 LL |     core::panic!("{}", &*"abc");
@@ -181,7 +186,8 @@ warning: panic message is not a string literal
 LL |     fancy_panic::fancy_panic!(S);
    |                               ^
    |
-   = note: this is no longer accepted in Rust 2021
+   = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
 
 warning: panic message is not a string literal
   --> $DIR/non-fmt-panic.rs:36:12
@@ -189,7 +195,8 @@ warning: panic message is not a string literal
 LL |     panic!(a!());
    |            ^^^^
    |
-   = note: this is no longer accepted in Rust 2021
+   = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
 help: add a "{}" format string to Display the message
    |
 LL |     panic!("{}", a!());
@@ -205,7 +212,8 @@ warning: panic message is not a string literal
 LL |     panic!(format!("{}", 1));
    |            ^^^^^^^^^^^^^^^^
    |
-   = note: this is no longer accepted in Rust 2021
+   = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
    = note: the panic!() macro supports formatting, so there's no need for the format!() macro here
 help: remove the `format!(..)` macro call
    |
@@ -218,7 +226,8 @@ warning: panic message is not a string literal
 LL |     assert!(false, format!("{}", 1));
    |                    ^^^^^^^^^^^^^^^^
    |
-   = note: this is no longer accepted in Rust 2021
+   = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
    = note: the assert!() macro supports formatting, so there's no need for the format!() macro here
 help: remove the `format!(..)` macro call
    |
@@ -231,7 +240,8 @@ warning: panic message is not a string literal
 LL |     debug_assert!(false, format!("{}", 1));
    |                          ^^^^^^^^^^^^^^^^
    |
-   = note: this is no longer accepted in Rust 2021
+   = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
    = note: the debug_assert!() macro supports formatting, so there's no need for the format!() macro here
 help: remove the `format!(..)` macro call
    |
@@ -244,7 +254,8 @@ warning: panic message is not a string literal
 LL |     panic![123];
    |            ^^^
    |
-   = note: this is no longer accepted in Rust 2021
+   = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
 help: add a "{}" format string to Display the message
    |
 LL |     panic!["{}", 123];
@@ -260,7 +271,8 @@ warning: panic message is not a string literal
 LL |     panic!{123};
    |            ^^^
    |
-   = note: this is no longer accepted in Rust 2021
+   = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
 help: add a "{}" format string to Display the message
    |
 LL |     panic!{"{}", 123};
diff --git a/src/test/ui/non-integer-atomic.rs b/src/test/ui/non-integer-atomic.rs
deleted file mode 100644 (file)
index 00a7f36..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-// build-fail
-
-#![feature(core_intrinsics)]
-#![allow(warnings)]
-#![crate_type = "rlib"]
-
-use std::intrinsics;
-
-#[derive(Copy, Clone)]
-pub struct Foo(i64);
-pub type Bar = &'static Fn();
-pub type Quux = [u8; 100];
-
-pub unsafe fn test_bool_load(p: &mut bool, v: bool) {
-    intrinsics::atomic_load(p);
-    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool`
-}
-
-pub unsafe fn test_bool_store(p: &mut bool, v: bool) {
-    intrinsics::atomic_store(p, v);
-    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `bool`
-}
-
-pub unsafe fn test_bool_xchg(p: &mut bool, v: bool) {
-    intrinsics::atomic_xchg(p, v);
-    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `bool`
-}
-
-pub unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
-    intrinsics::atomic_cxchg(p, v, v);
-    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
-}
-
-pub unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
-    intrinsics::atomic_load(p);
-    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo`
-}
-
-pub unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
-    intrinsics::atomic_store(p, v);
-    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `Foo`
-}
-
-pub unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) {
-    intrinsics::atomic_xchg(p, v);
-    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
-}
-
-pub unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
-    intrinsics::atomic_cxchg(p, v, v);
-    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
-}
-
-pub unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
-    intrinsics::atomic_load(p);
-    //~^ ERROR expected basic integer type, found `&dyn Fn()`
-}
-
-pub unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
-    intrinsics::atomic_store(p, v);
-    //~^ ERROR expected basic integer type, found `&dyn Fn()`
-}
-
-pub unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
-    intrinsics::atomic_xchg(p, v);
-    //~^ ERROR expected basic integer type, found `&dyn Fn()`
-}
-
-pub unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
-    intrinsics::atomic_cxchg(p, v, v);
-    //~^ ERROR expected basic integer type, found `&dyn Fn()`
-}
-
-pub unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
-    intrinsics::atomic_load(p);
-    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
-}
-
-pub unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
-    intrinsics::atomic_store(p, v);
-    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
-}
-
-pub unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) {
-    intrinsics::atomic_xchg(p, v);
-    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
-}
-
-pub unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) {
-    intrinsics::atomic_cxchg(p, v, v);
-    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
-}
diff --git a/src/test/ui/non-integer-atomic.stderr b/src/test/ui/non-integer-atomic.stderr
deleted file mode 100644 (file)
index ee485c2..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `bool`
-  --> $DIR/non-integer-atomic.rs:15:5
-   |
-LL |     intrinsics::atomic_load(p);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `bool`
-  --> $DIR/non-integer-atomic.rs:20:5
-   |
-LL |     intrinsics::atomic_store(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `bool`
-  --> $DIR/non-integer-atomic.rs:25:5
-   |
-LL |     intrinsics::atomic_xchg(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
-  --> $DIR/non-integer-atomic.rs:30:5
-   |
-LL |     intrinsics::atomic_cxchg(p, v, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `Foo`
-  --> $DIR/non-integer-atomic.rs:35:5
-   |
-LL |     intrinsics::atomic_load(p);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `Foo`
-  --> $DIR/non-integer-atomic.rs:40:5
-   |
-LL |     intrinsics::atomic_store(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
-  --> $DIR/non-integer-atomic.rs:45:5
-   |
-LL |     intrinsics::atomic_xchg(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
-  --> $DIR/non-integer-atomic.rs:50:5
-   |
-LL |     intrinsics::atomic_cxchg(p, v, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `&dyn Fn()`
-  --> $DIR/non-integer-atomic.rs:55:5
-   |
-LL |     intrinsics::atomic_load(p);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `&dyn Fn()`
-  --> $DIR/non-integer-atomic.rs:60:5
-   |
-LL |     intrinsics::atomic_store(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `&dyn Fn()`
-  --> $DIR/non-integer-atomic.rs:65:5
-   |
-LL |     intrinsics::atomic_xchg(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `&dyn Fn()`
-  --> $DIR/non-integer-atomic.rs:70:5
-   |
-LL |     intrinsics::atomic_cxchg(p, v, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
-  --> $DIR/non-integer-atomic.rs:75:5
-   |
-LL |     intrinsics::atomic_load(p);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
-  --> $DIR/non-integer-atomic.rs:80:5
-   |
-LL |     intrinsics::atomic_store(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
-  --> $DIR/non-integer-atomic.rs:85:5
-   |
-LL |     intrinsics::atomic_xchg(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
-  --> $DIR/non-integer-atomic.rs:90:5
-   |
-LL |     intrinsics::atomic_cxchg(p, v, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 16 previous errors
-
-For more information about this error, try `rustc --explain E0511`.
index 4c6964f294b5e18cb5525078d1406e2a4b17207c..568c3e144be2c302cabef8446cd0f166954bad0a 100644 (file)
@@ -4,7 +4,7 @@
 
 // Iota-reduction is a rule in the Calculus of (Co-)Inductive Constructions,
 // which "says that a destructor applied to an object built from a constructor
-// behaves as expected".  -- http://coq.inria.fr/doc/Reference-Manual006.html
+// behaves as expected".  -- https://coq.inria.fr/doc/language/core/conversion.html#iota-reduction
 //
 // It's a little more complicated here, because of pointers and regions and
 // trying to get assert failure messages that at least identify which case
index f0651c4cdef0e33d10d316d2372c9b4d6ea30627..804b6282202be85cd9082d4bab3c18233cbcca47 100644 (file)
@@ -1,35 +1,41 @@
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/multiple-impls.rs:33:18
    |
-LL |     fn index(&self, index: Idx) -> &Self::Output;
-   |     --------------------------------------------- required by `Index::index`
-...
 LL |     Index::index(&[] as &[i32], 2u32);
    |                  ^^^^^^^^^^^^^ trait message
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
+note: required by `Index::index`
+  --> $DIR/multiple-impls.rs:12:5
+   |
+LL |     fn index(&self, index: Idx) -> &Self::Output;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:36:18
    |
-LL |     fn index(&self, index: Idx) -> &Self::Output;
-   |     --------------------------------------------- required by `Index::index`
-...
 LL |     Index::index(&[] as &[i32], Foo(2u32));
    |                  ^^^^^^^^^^^^^ on impl for Foo
    |
    = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
+note: required by `Index::index`
+  --> $DIR/multiple-impls.rs:12:5
+   |
+LL |     fn index(&self, index: Idx) -> &Self::Output;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:39:18
    |
-LL |     fn index(&self, index: Idx) -> &Self::Output;
-   |     --------------------------------------------- required by `Index::index`
-...
 LL |     Index::index(&[] as &[i32], Bar(2u32));
    |                  ^^^^^^^^^^^^^ on impl for Bar
    |
    = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
+note: required by `Index::index`
+  --> $DIR/multiple-impls.rs:12:5
+   |
+LL |     fn index(&self, index: Idx) -> &Self::Output;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/multiple-impls.rs:33:5
index fe4114aeddc009f002a70eb9229680a2b4c4e3a7..b17c1d4c252085bf0f1eea4267d190020ddd7219 100644 (file)
@@ -5,8 +5,7 @@ LL |     println!("{:?} {:?}", Foo, Bar);
    |                           ^^^ `Foo` cannot be formatted using `{:?}`
    |
    = help: the trait `Debug` is not implemented for `Foo`
-   = note: add `#[derive(Debug)]` or manually implement `Debug`
-   = note: required by `std::fmt::Debug::fmt`
+   = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo`
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: `Bar` doesn't implement `Debug`
@@ -16,7 +15,6 @@ LL |     println!("{:?} {:?}", Foo, Bar);
    |                                ^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = help: the trait `Debug` is not implemented for `Bar`
-   = note: required by `std::fmt::Debug::fmt`
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: `Foo` doesn't implement `std::fmt::Display`
@@ -27,7 +25,6 @@ LL |     println!("{} {}", Foo, Bar);
    |
    = help: the trait `std::fmt::Display` is not implemented for `Foo`
    = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
-   = note: required by `std::fmt::Display::fmt`
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: `Bar` doesn't implement `std::fmt::Display`
@@ -38,7 +35,6 @@ LL |     println!("{} {}", Foo, Bar);
    |
    = help: the trait `std::fmt::Display` is not implemented for `Bar`
    = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
-   = note: required by `std::fmt::Display::fmt`
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 4 previous errors
index f19fa8a07fe64822caf26969934b8da5f303caaf..bfd438e5cc215212efa3983cd252901ce12a56fc 100644 (file)
@@ -1,13 +1,15 @@
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/on-impl.rs:22:25
    |
-LL |     fn index(&self, index: Idx) -> &Self::Output;
-   |     --------------------------------------------- required by `Index::index`
-...
 LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
    |                         ^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
+note: required by `Index::index`
+  --> $DIR/on-impl.rs:9:5
+   |
+LL |     fn index(&self, index: Idx) -> &Self::Output;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/on-impl.rs:22:5
diff --git a/src/test/ui/packed/issue-27060-2.rs b/src/test/ui/packed/issue-27060-2.rs
new file mode 100644 (file)
index 0000000..a001ce1
--- /dev/null
@@ -0,0 +1,6 @@
+#[repr(packed)]
+pub struct Bad<T: ?Sized> {
+    data: T, //~ ERROR the size for values of type
+}
+
+fn main() {}
diff --git a/src/test/ui/packed/issue-27060-2.stderr b/src/test/ui/packed/issue-27060-2.stderr
new file mode 100644 (file)
index 0000000..5dbcc96
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/issue-27060-2.rs:3:11
+   |
+LL | pub struct Bad<T: ?Sized> {
+   |                - this type parameter needs to be `std::marker::Sized`
+LL |     data: T,
+   |           ^ doesn't have a size known at compile-time
+   |
+   = note: the last field of a packed struct may only have a dynamically sized type if it does not need drop to be run
+   = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+   |
+LL |     data: &T,
+   |           ^
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+   |
+LL |     data: Box<T>,
+   |           ^^^^ ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/packed/issue-27060-rpass.rs b/src/test/ui/packed/issue-27060-rpass.rs
new file mode 100644 (file)
index 0000000..d9159f6
--- /dev/null
@@ -0,0 +1,23 @@
+// run-pass
+#![allow(dead_code)]
+#[repr(packed)]
+pub struct Good {
+    data: &'static u32,
+    data2: [&'static u32; 2],
+    aligned: [u8; 32],
+}
+
+// kill this test when that turns to a hard error
+#[allow(unaligned_references)]
+fn main() {
+    let good = Good { data: &0, data2: [&0, &0], aligned: [0; 32] };
+
+    let _ = &good.data; // ok
+    let _ = &good.data2[0]; // ok
+
+    let _ = &good.data;
+    let _ = &good.data2[0];
+    let _ = &*good.data; // ok, behind a pointer
+    let _ = &good.aligned; // ok, has align 1
+    let _ = &good.aligned[2]; // ok, has align 1
+}
diff --git a/src/test/ui/packed/issue-27060.rs b/src/test/ui/packed/issue-27060.rs
new file mode 100644 (file)
index 0000000..5317a61
--- /dev/null
@@ -0,0 +1,28 @@
+#[repr(packed)]
+pub struct Good {
+    data: &'static u32,
+    data2: [&'static u32; 2],
+    aligned: [u8; 32],
+}
+
+#[deny(unaligned_references)]
+fn main() {
+    let good = Good {
+        data: &0,
+        data2: [&0, &0],
+        aligned: [0; 32]
+    };
+
+    let _ = &good.data; //~ ERROR reference to packed field
+    //~| hard error
+    let _ = &good.data2[0]; //~ ERROR reference to packed field
+    //~| hard error
+
+    let _ = &good.data; //~ ERROR reference to packed field
+                        //~| hard error
+    let _ = &good.data2[0]; //~ ERROR reference to packed field
+                            //~| hard error
+    let _ = &*good.data; // ok, behind a pointer
+    let _ = &good.aligned; // ok, has align 1
+    let _ = &good.aligned[2]; // ok, has align 1
+}
diff --git a/src/test/ui/packed/issue-27060.stderr b/src/test/ui/packed/issue-27060.stderr
new file mode 100644 (file)
index 0000000..0929788
--- /dev/null
@@ -0,0 +1,47 @@
+error: reference to packed field is unaligned
+  --> $DIR/issue-27060.rs:16:13
+   |
+LL |     let _ = &good.data;
+   |             ^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-27060.rs:8:8
+   |
+LL | #[deny(unaligned_references)]
+   |        ^^^^^^^^^^^^^^^^^^^^
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+
+error: reference to packed field is unaligned
+  --> $DIR/issue-27060.rs:18:13
+   |
+LL |     let _ = &good.data2[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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+
+error: reference to packed field is unaligned
+  --> $DIR/issue-27060.rs:21:13
+   |
+LL |     let _ = &good.data;
+   |             ^^^^^^^^^^
+   |
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+
+error: reference to packed field is unaligned
+  --> $DIR/issue-27060.rs:23:13
+   |
+LL |     let _ = &good.data2[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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/panic-runtime/incompatible-type.rs b/src/test/ui/panic-runtime/incompatible-type.rs
new file mode 100644 (file)
index 0000000..026364a
--- /dev/null
@@ -0,0 +1,24 @@
+// Check that rust_eh_personality can have a different type signature than the
+// one hardcoded in the compiler.  Regression test for #70117. Used to fail with:
+//
+// Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
+//
+// build-pass
+// compile-flags: --crate-type=lib -Ccodegen-units=1
+#![no_std]
+#![panic_runtime]
+#![feature(panic_runtime)]
+#![feature(rustc_attrs)]
+
+pub struct DropMe;
+
+impl Drop for DropMe {
+    fn drop(&mut self) {}
+}
+
+pub fn test(_: DropMe) {
+    unreachable!();
+}
+
+#[rustc_std_internal_symbol]
+pub unsafe extern "C" fn rust_eh_personality() {}
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>);
index 02816ef2791b0dcaa5b83ec0a694795e5083e730..c217ab9774fd23c63c2f2096c61326a46fb8c8c7 100644 (file)
@@ -1,4 +1,5 @@
 // run-rustfix
+// rustfix-only-machine-applicable
 #![allow(unused_variables)]
 #![allow(dead_code)]
 #![allow(unused_must_use)]
index 93baa8278f890b7bd431c0d86bf63c1d001d5721..b04025faaec63caabf71a1c9d8fdf47a38860f28 100644 (file)
@@ -1,4 +1,5 @@
 // run-rustfix
+// rustfix-only-machine-applicable
 #![allow(unused_variables)]
 #![allow(dead_code)]
 #![allow(unused_must_use)]
index 09a6d7cbeb17673514c4f02a500806d3cb107849..067b7edc7709447e6e2e78b1a8e80a1ea040d7bd 100644 (file)
@@ -1,5 +1,5 @@
 error: expected expression, found `+`
-  --> $DIR/expr-as-stmt.rs:7:9
+  --> $DIR/expr-as-stmt.rs:8:9
    |
 LL |     {2} + {2}
    |     --- ^ expected expression
@@ -7,7 +7,7 @@ LL |     {2} + {2}
    |     help: parentheses are required to parse this as an expression: `({2})`
 
 error: expected expression, found `+`
-  --> $DIR/expr-as-stmt.rs:12:9
+  --> $DIR/expr-as-stmt.rs:13:9
    |
 LL |     {2} + 2
    |     --- ^ expected expression
@@ -15,7 +15,7 @@ LL |     {2} + 2
    |     help: parentheses are required to parse this as an expression: `({2})`
 
 error: expected expression, found `+`
-  --> $DIR/expr-as-stmt.rs:18:12
+  --> $DIR/expr-as-stmt.rs:19:12
    |
 LL |     { 42 } + foo;
    |     ------ ^ expected expression
@@ -23,7 +23,7 @@ LL |     { 42 } + foo;
    |     help: parentheses are required to parse this as an expression: `({ 42 })`
 
 error: expected expression, found `>`
-  --> $DIR/expr-as-stmt.rs:31:7
+  --> $DIR/expr-as-stmt.rs:32:7
    |
 LL |     } > 0
    |       ^ expected expression
@@ -36,7 +36,7 @@ LL |     }) > 0
    |
 
 error[E0308]: mismatched types
-  --> $DIR/expr-as-stmt.rs:7:6
+  --> $DIR/expr-as-stmt.rs:8:6
    |
 LL |     {2} + {2}
    |      ^ expected `()`, found integer
@@ -47,7 +47,7 @@ LL |     {return 2;} + {2}
    |      ^^^^^^  ^
 
 error[E0308]: mismatched types
-  --> $DIR/expr-as-stmt.rs:12:6
+  --> $DIR/expr-as-stmt.rs:13:6
    |
 LL |     {2} + 2
    |      ^ expected `()`, found integer
@@ -58,7 +58,7 @@ LL |     {return 2;} + 2
    |      ^^^^^^  ^
 
 error[E0308]: mismatched types
-  --> $DIR/expr-as-stmt.rs:18:7
+  --> $DIR/expr-as-stmt.rs:19:7
    |
 LL |     { 42 } + foo;
    |       ^^ expected `()`, found integer
@@ -69,7 +69,7 @@ LL |     { return 42; } + foo;
    |       ^^^^^^   ^
 
 error[E0308]: mismatched types
-  --> $DIR/expr-as-stmt.rs:24:7
+  --> $DIR/expr-as-stmt.rs:25:7
    |
 LL |     { 3 } * 3
    |       ^ expected `()`, found integer
@@ -80,7 +80,7 @@ LL |     { return 3; } * 3
    |       ^^^^^^  ^
 
 error[E0614]: type `{integer}` cannot be dereferenced
-  --> $DIR/expr-as-stmt.rs:24:11
+  --> $DIR/expr-as-stmt.rs:25:11
    |
 LL |     { 3 } * 3
    |     ----- ^^^
diff --git a/src/test/ui/parser/float-literals.rs b/src/test/ui/parser/float-literals.rs
new file mode 100644 (file)
index 0000000..1e9319f
--- /dev/null
@@ -0,0 +1,9 @@
+// build-pass
+// ignore-tidy-linelength
+// Regression test for #31109 and #31407.
+
+pub fn main() {
+    let _: f64 = 0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333;
+
+    let _: f64 = 1234567890123456789012345678901234567890e-340;
+}
index 1ccc9497d9d81b82d31715637a5f150230f71204..9871cb8fe3ee84955ce5f58e503e0300d138b3e0 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(generic_associated_types)]
-//~^ WARN the feature `generic_associated_types` is incomplete
 
 fn main() {}
 
index 818d73c898dcaf6ef4a19222d28584851f5b67bc..4b398d791c4d1907057e5c7101b8cf0b48485fa4 100644 (file)
@@ -1,5 +1,5 @@
 error: associated type in `impl` without body
-  --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:8:5
    |
 LL |     type Y;
    |     ^^^^^^-
@@ -7,7 +7,7 @@ LL |     type Y;
    |           help: provide a definition for the type: `= <type>;`
 
 error: associated type in `impl` without body
-  --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:11:5
    |
 LL |     type Z: Ord;
    |     ^^^^^^^^^^^-
@@ -15,13 +15,13 @@ LL |     type Z: Ord;
    |                help: provide a definition for the type: `= <type>;`
 
 error: bounds on `type`s in `impl`s have no effect
-  --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:13
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:11:13
    |
 LL |     type Z: Ord;
    |             ^^^
 
 error: associated type in `impl` without body
-  --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:15:5
    |
 LL |     type W: Ord where Self: Eq;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -29,30 +29,21 @@ LL |     type W: Ord where Self: Eq;
    |                               help: provide a definition for the type: `= <type>;`
 
 error: bounds on `type`s in `impl`s have no effect
-  --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:13
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:15:13
    |
 LL |     type W: Ord where Self: Eq;
    |             ^^^
 
 error: associated type in `impl` without body
-  --> $DIR/impl-item-type-no-body-semantic-fail.rs:20:5
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:19:5
    |
 LL |     type W where Self: Eq;
    |     ^^^^^^^^^^^^^^^^^^^^^-
    |                          |
    |                          help: provide a definition for the type: `= <type>;`
 
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/impl-item-type-no-body-semantic-fail.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0658]: inherent associated types are unstable
-  --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:8:5
    |
 LL |     type Y;
    |     ^^^^^^^
@@ -61,7 +52,7 @@ LL |     type Y;
    = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
 
 error[E0658]: inherent associated types are unstable
-  --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:11:5
    |
 LL |     type Z: Ord;
    |     ^^^^^^^^^^^^
@@ -70,7 +61,7 @@ LL |     type Z: Ord;
    = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
 
 error[E0658]: inherent associated types are unstable
-  --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:15:5
    |
 LL |     type W: Ord where Self: Eq;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -79,7 +70,7 @@ LL |     type W: Ord where Self: Eq;
    = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
 
 error[E0658]: inherent associated types are unstable
-  --> $DIR/impl-item-type-no-body-semantic-fail.rs:20:5
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:19:5
    |
 LL |     type W where Self: Eq;
    |     ^^^^^^^^^^^^^^^^^^^^^^
@@ -87,6 +78,6 @@ LL |     type W where Self: Eq;
    = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
    = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
 
-error: aborting due to 10 previous errors; 1 warning emitted
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/parser/issue-48636.fixed b/src/test/ui/parser/issue-48636.fixed
new file mode 100644 (file)
index 0000000..87c19a3
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+struct S {
+    x: u8,
+    /// The ID of the parent core
+    y: u8,
+}
+//~^^^ ERROR found a documentation comment that doesn't document anything
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-48636.rs b/src/test/ui/parser/issue-48636.rs
new file mode 100644 (file)
index 0000000..8610dc2
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+struct S {
+    x: u8
+    /// The ID of the parent core
+    y: u8,
+}
+//~^^^ ERROR found a documentation comment that doesn't document anything
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-48636.stderr b/src/test/ui/parser/issue-48636.stderr
new file mode 100644 (file)
index 0000000..462723d
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0585]: found a documentation comment that doesn't document anything
+  --> $DIR/issue-48636.rs:7:5
+   |
+LL |     x: u8
+   |          - help: missing comma here: `,`
+LL |     /// The ID of the parent core
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0585`.
diff --git a/src/test/ui/parser/issue-54521-1.rs b/src/test/ui/parser/issue-54521-1.rs
new file mode 100644 (file)
index 0000000..8a682ef
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+
+// This test checks that the `remove extra angle brackets` error doesn't happen for some
+// potential edge-cases..
+
+struct X {
+    len: u32,
+}
+
+fn main() {
+    let x = X { len: 3 };
+
+    let _ = x.len > (3);
+
+    let _ = x.len >> (3);
+}
diff --git a/src/test/ui/parser/issue-54521-2.fixed b/src/test/ui/parser/issue-54521-2.fixed
new file mode 100644 (file)
index 0000000..a91c4fe
--- /dev/null
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = Vec::<usize>>>::new();
+//                     ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/parser/issue-54521-2.rs b/src/test/ui/parser/issue-54521-2.rs
new file mode 100644 (file)
index 0000000..3639aac
--- /dev/null
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = Vec::<usize>>>::new();
+//                     ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = Vec::<usize>>>>>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>>>>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>>>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>>::new();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/parser/issue-54521-2.stderr b/src/test/ui/parser/issue-54521-2.stderr
new file mode 100644 (file)
index 0000000..9556b83
--- /dev/null
@@ -0,0 +1,26 @@
+error: unmatched angle brackets
+  --> $DIR/issue-54521-2.rs:11:25
+   |
+LL |     let _ = Vec::<usize>>>>>::new();
+   |                         ^^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521-2.rs:14:25
+   |
+LL |     let _ = Vec::<usize>>>>::new();
+   |                         ^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521-2.rs:17:25
+   |
+LL |     let _ = Vec::<usize>>>::new();
+   |                         ^^ help: remove extra angle brackets
+
+error: unmatched angle bracket
+  --> $DIR/issue-54521-2.rs:20:25
+   |
+LL |     let _ = Vec::<usize>>::new();
+   |                         ^ help: remove extra angle bracket
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/parser/issue-54521-3.fixed b/src/test/ui/parser/issue-54521-3.fixed
new file mode 100644 (file)
index 0000000..84ab686
--- /dev/null
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+//                                                        ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/parser/issue-54521-3.rs b/src/test/ui/parser/issue-54521-3.rs
new file mode 100644 (file)
index 0000000..f1d6850
--- /dev/null
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+//                                                        ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/parser/issue-54521-3.stderr b/src/test/ui/parser/issue-54521-3.stderr
new file mode 100644 (file)
index 0000000..0f23dd6
--- /dev/null
@@ -0,0 +1,26 @@
+error: unmatched angle brackets
+  --> $DIR/issue-54521-3.rs:11:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>>();
+   |                                                            ^^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521-3.rs:14:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>();
+   |                                                            ^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521-3.rs:17:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+   |                                                            ^^ help: remove extra angle brackets
+
+error: unmatched angle bracket
+  --> $DIR/issue-54521-3.rs:20:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>();
+   |                                                            ^ help: remove extra angle bracket
+
+error: aborting due to 4 previous errors
+
index 88527cc8783c83a6b455dace86b10911cbb231b4..0a6e26acfc77f2d21c6740f68ae8d1af0be5f83d 100644 (file)
@@ -4,4 +4,4 @@ type X<'a> = (?'a) +;
 //~^ ERROR `?` may only modify trait bounds, not lifetime bounds
 //~| ERROR at least one trait is required for an object type
 //~| WARN trait objects without an explicit `dyn` are deprecated
-//~| WARN this was previously accepted by the compiler
+//~| WARN this is accepted in the current edition
index 37f38365b016f16fd53edce39cba98666a96ab94..dce03e1a9635cf5e66b0f937fafdbda442503de8 100644 (file)
@@ -11,7 +11,7 @@ LL | type X<'a> = (?'a) +;
    |              ^^^^^^^ help: use `dyn`: `dyn (?'a) +`
    |
    = note: `#[warn(bare_trait_objects)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error[E0224]: at least one trait is required for an object type
index 0733b2d2df781453a82bf598e6dc2ef9cf0014b0..e68ee747cfdb5bbbbe3585f6973c3c033fa40b48 100644 (file)
@@ -14,10 +14,10 @@ mac!('a);
 fn y<'a>(y: &mut 'a + Send) {
     //~^ ERROR expected a path on the left-hand side of `+`, not `&mut 'a`
     //~| WARNING trait objects without an explicit `dyn` are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
     //~| ERROR at least one trait is required for an object type
     let z = y as &mut 'a + Send;
     //~^ ERROR expected value, found trait `Send`
     //~| WARNING trait objects without an explicit `dyn` are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
 }
index f83b7944b1ba181adbac974dd823a4765e4d1e26..c10037d44e30d9f92b30431fb0dbb6b7e182efdd 100644 (file)
@@ -34,7 +34,7 @@ LL | fn y<'a>(y: &mut 'a + Send) {
    |                  ^^ help: use `dyn`: `dyn 'a`
    |
    = note: `#[warn(bare_trait_objects)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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: trait objects without an explicit `dyn` are deprecated
@@ -43,7 +43,7 @@ warning: trait objects without an explicit `dyn` are deprecated
 LL |     let z = y as &mut 'a + Send;
    |                       ^^ help: use `dyn`: `dyn 'a`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error[E0224]: at least one trait is required for an object type
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/issue-87086-colon-path-sep.rs b/src/test/ui/parser/issue-87086-colon-path-sep.rs
new file mode 100644 (file)
index 0000000..4ee0b20
--- /dev/null
@@ -0,0 +1,66 @@
+// Tests that a suggestion is issued if the user wrote a colon instead of
+// a path separator in a match arm.
+
+enum Foo {
+    Bar,
+    Baz,
+}
+
+fn f() -> Foo { Foo::Bar }
+
+fn g1() {
+    match f() {
+        Foo:Bar => {}
+        //~^ ERROR: expected one of
+        //~| HELP: maybe write a path separator here
+        _ => {}
+    }
+    match f() {
+        Foo::Bar:Baz => {}
+        //~^ ERROR: expected one of
+        //~| HELP: maybe write a path separator here
+        _ => {}
+    }
+    match f() {
+        Foo:Bar::Baz => {}
+        //~^ ERROR: expected one of
+        //~| HELP: maybe write a path separator here
+        _ => {}
+    }
+    match f() {
+        Foo: Bar::Baz if true => {}
+        //~^ ERROR: expected one of
+        //~| HELP: maybe write a path separator here
+        _ => {}
+    }
+    if let Bar:Baz = f() {
+    //~^ ERROR: expected one of
+    //~| HELP: maybe write a path separator here
+    }
+}
+
+fn g1_neg() {
+    match f() {
+        ref Foo: Bar::Baz => {}
+        //~^ ERROR: expected one of
+        _ => {}
+    }
+}
+
+fn g2_neg() {
+    match f() {
+        mut Foo: Bar::Baz => {}
+        //~^ ERROR: expected one of
+        _ => {}
+    }
+}
+
+fn main() {
+    let myfoo = Foo::Bar;
+    match myfoo {
+        Foo::Bar => {}
+        Foo:Bar::Baz => {}
+        //~^ ERROR: expected one of
+        //~| HELP: maybe write a path separator here
+    }
+}
diff --git a/src/test/ui/parser/issue-87086-colon-path-sep.stderr b/src/test/ui/parser/issue-87086-colon-path-sep.stderr
new file mode 100644 (file)
index 0000000..8f93661
--- /dev/null
@@ -0,0 +1,68 @@
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/issue-87086-colon-path-sep.rs:13:12
+   |
+LL |         Foo:Bar => {}
+   |            ^
+   |            |
+   |            expected one of `@` or `|`
+   |            help: maybe write a path separator here: `::`
+
+error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `{`, or `|`, found `:`
+  --> $DIR/issue-87086-colon-path-sep.rs:19:17
+   |
+LL |         Foo::Bar:Baz => {}
+   |                 ^
+   |                 |
+   |                 expected one of 8 possible tokens
+   |                 help: maybe write a path separator here: `::`
+
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/issue-87086-colon-path-sep.rs:25:12
+   |
+LL |         Foo:Bar::Baz => {}
+   |            ^
+   |            |
+   |            expected one of `@` or `|`
+   |            help: maybe write a path separator here: `::`
+
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/issue-87086-colon-path-sep.rs:31:12
+   |
+LL |         Foo: Bar::Baz if true => {}
+   |            ^
+   |            |
+   |            expected one of `@` or `|`
+   |            help: maybe write a path separator here: `::`
+
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/issue-87086-colon-path-sep.rs:36:15
+   |
+LL |     if let Bar:Baz = f() {
+   |               ^
+   |               |
+   |               expected one of `@` or `|`
+   |               help: maybe write a path separator here: `::`
+
+error: expected one of `=>`, `@`, `if`, or `|`, found `:`
+  --> $DIR/issue-87086-colon-path-sep.rs:44:16
+   |
+LL |         ref Foo: Bar::Baz => {}
+   |                ^ expected one of `=>`, `@`, `if`, or `|`
+
+error: expected one of `=>`, `@`, `if`, or `|`, found `:`
+  --> $DIR/issue-87086-colon-path-sep.rs:52:16
+   |
+LL |         mut Foo: Bar::Baz => {}
+   |                ^ expected one of `=>`, `@`, `if`, or `|`
+
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/issue-87086-colon-path-sep.rs:62:12
+   |
+LL |         Foo:Bar::Baz => {}
+   |            ^
+   |            |
+   |            expected one of `@` or `|`
+   |            help: maybe write a path separator here: `::`
+
+error: aborting due to 8 previous errors
+
index 0428ea0e2c1b1e74ce09efeeba5297d4d2f01410..663739f235a438340521d585fb98219411ec008a 100644 (file)
@@ -12,5 +12,5 @@ fn main() {
     //~^ ERROR lifetime in trait object type must be followed by `+`
     //~| ERROR at least one trait is required for an object type
     //~| WARN trait objects without an explicit `dyn` are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
 }
index 8ae5611d89d196aa6d9ac0d8ba6f9b0ef77962fc..caca84f695d76d67a52890939974fb867e0bad78 100644 (file)
@@ -11,7 +11,7 @@ LL |     m!('static);
    |        ^^^^^^^ help: use `dyn`: `dyn 'static`
    |
    = note: `#[warn(bare_trait_objects)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error[E0224]: at least one trait is required for an object type
index 2d1fa7dc42e0cb3c06cb0bec89a2a2766fd45314..555cd68c3a76f07d1f35d5b0fc559a6354ce07c0 100644 (file)
@@ -1,7 +1,7 @@
 // run-pass
 // Beware editing: it has numerous whitespace characters which are important.
 // It contains one ranges from the 'PATTERN_WHITE_SPACE' property outlined in
-// http://unicode.org/Public/UNIDATA/PropList.txt
+// https://unicode.org/Public/UNIDATA/PropList.txt
 //
 // The characters in the first expression of the assertion can be generated
 // from: "4\u{0C}+\n\t\r7\t*\u{20}2\u{85}/\u{200E}3\u{200F}*\u{2028}2\u{2029}"
diff --git a/src/test/ui/parser/range-inclusive-extra-equals.rs b/src/test/ui/parser/range-inclusive-extra-equals.rs
new file mode 100644 (file)
index 0000000..d41c069
--- /dev/null
@@ -0,0 +1,10 @@
+// Makes sure that a helpful message is shown when someone mistypes
+// an inclusive range as `..==` rather than `..=`. This is an
+// easy mistake, because of the resemblance to`==`.
+// See #86395 for a bit of background.
+
+pub fn main() {
+    if let 1..==3 = 1 {} //~ERROR unexpected `=` after inclusive range
+                      //~|HELP use `..=` instead
+                      //~|NOTE inclusive ranges end with a single equals sign
+}
diff --git a/src/test/ui/parser/range-inclusive-extra-equals.stderr b/src/test/ui/parser/range-inclusive-extra-equals.stderr
new file mode 100644 (file)
index 0000000..d37b6be
--- /dev/null
@@ -0,0 +1,10 @@
+error: unexpected `=` after inclusive range
+  --> $DIR/range-inclusive-extra-equals.rs:7:13
+   |
+LL |     if let 1..==3 = 1 {}
+   |             ^^^^ help: use `..=` instead
+   |
+   = note: inclusive ranges end with a single equals sign (`..=`)
+
+error: aborting due to previous error
+
index a10add6d9e523c073c21b099161405d2605be2eb..2e5a991543ff93341909f2b9306e81498af88d37 100644 (file)
@@ -41,30 +41,30 @@ fn inclusive_from_to() {
 fn inclusive2_from_to() {
     if let 0...3 = 0 {}
     //~^ ERROR `...` range patterns are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
     if let 0...Y = 0 {}
     //~^ ERROR `...` range patterns are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
     if let X...3 = 0 {}
     //~^ ERROR `...` range patterns are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
     if let X...Y = 0 {}
     //~^ ERROR `...` range patterns are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
     if let true...Y = 0 {} //~ ERROR only `char` and numeric types
     //~^ ERROR `...` range patterns are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
     if let X...true = 0 {} //~ ERROR only `char` and numeric types
     //~^ ERROR `...` range patterns are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
     if let .0...Y = 0 {} //~ ERROR mismatched types
     //~^ ERROR float literals must have an integer part
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
     //~| ERROR `...` range patterns are deprecated
     if let X... .0 = 0 {} //~ ERROR mismatched types
     //~^ ERROR float literals must have an integer part
     //~| ERROR `...` range patterns are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
 }
 
 fn exclusive_from() {
@@ -137,7 +137,7 @@ fn with_macro_expr_var() {
             let $e1..$e2;
             let $e1...$e2;
             //~^ ERROR `...` range patterns are deprecated
-            //~| WARN this was previously accepted by the compiler
+            //~| WARN this is accepted in the current edition
             let $e1..=$e2;
         }
     }
index 3236ef0db2837d11494abf7943f5e52ec4e877d8..2d8088432a257a1890965432224e7851eb9fe537 100644 (file)
@@ -204,7 +204,7 @@ note: the lint level is defined here
    |
 LL | #![deny(ellipsis_inclusive_range_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: `...` range patterns are deprecated
@@ -213,7 +213,7 @@ error: `...` range patterns are deprecated
 LL |     if let 0...Y = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: `...` range patterns are deprecated
@@ -222,7 +222,7 @@ error: `...` range patterns are deprecated
 LL |     if let X...3 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: `...` range patterns are deprecated
@@ -231,7 +231,7 @@ error: `...` range patterns are deprecated
 LL |     if let X...Y = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: `...` range patterns are deprecated
@@ -240,7 +240,7 @@ error: `...` range patterns are deprecated
 LL |     if let true...Y = 0 {}
    |                ^^^ help: use `..=` for an inclusive range
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: `...` range patterns are deprecated
@@ -249,7 +249,7 @@ error: `...` range patterns are deprecated
 LL |     if let X...true = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: `...` range patterns are deprecated
@@ -258,7 +258,7 @@ error: `...` range patterns are deprecated
 LL |     if let .0...Y = 0 {}
    |              ^^^ help: use `..=` for an inclusive range
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: `...` range patterns are deprecated
@@ -267,7 +267,7 @@ error: `...` range patterns are deprecated
 LL |     if let X... .0 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: `...` range patterns are deprecated
@@ -279,7 +279,7 @@ LL |             let $e1...$e2;
 LL |     mac2!(0, 1);
    |     ------------ in this macro invocation
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
    = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
 
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 fe9c113710c3c09f71508f7d0a14ff50977dbcdf..5c229431ad34cc2c0edb378e30498ba04142a37d 100644 (file)
@@ -25,7 +25,11 @@ LL | |     }.hi() {
    |
    = help: the trait `Iterator` is not implemented for `bool`
    = note: required because of the requirements on the impl of `IntoIterator` for `bool`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 7d55da7d09721a75758813eed37ac39820feeb68..438034bc38aa45d38e1d85468df92f61b62d57e1 100644 (file)
@@ -9,15 +9,15 @@ fn main() {
     //~^ ERROR `?Trait` is not permitted in trait object types
     //~| ERROR only auto traits can be used as additional traits
     //~| WARN trait objects without an explicit `dyn` are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
     let _: Box<?Sized + (for<'a> Trait<'a>) + (Obj)>;
     //~^ ERROR `?Trait` is not permitted in trait object types
     //~| ERROR only auto traits can be used as additional traits
     //~| WARN trait objects without an explicit `dyn` are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
     let _: Box<for<'a> Trait<'a> + (Obj) + (?Sized)>;
     //~^ ERROR `?Trait` is not permitted in trait object types
     //~| ERROR only auto traits can be used as additional traits
     //~| WARN trait objects without an explicit `dyn` are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
 }
index 79b6892dc079a182e6dfc9a884ec5e09a70e467f..9bfc4943fe9414c3338a82c66e522f357d885456 100644 (file)
@@ -23,7 +23,7 @@ LL |     let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (Obj) + (?Sized) + (for<'a> Trait<'a>)`
    |
    = note: `#[warn(bare_trait_objects)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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: trait objects without an explicit `dyn` are deprecated
@@ -32,7 +32,7 @@ warning: trait objects without an explicit `dyn` are deprecated
 LL |     let _: Box<?Sized + (for<'a> Trait<'a>) + (Obj)>;
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn ?Sized + (for<'a> Trait<'a>) + (Obj)`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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: trait objects without an explicit `dyn` are deprecated
@@ -41,7 +41,7 @@ warning: trait objects without an explicit `dyn` are deprecated
 LL |     let _: Box<for<'a> Trait<'a> + (Obj) + (?Sized)>;
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn for<'a> Trait<'a> + (Obj) + (?Sized)`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
index fe993a6ee13022167ee79b5ea32bb4329145423a..0b61e267da80b6529fbcedfc014a51b8135f727f 100644 (file)
@@ -4,32 +4,32 @@
 fn main() {}
 
 fn f1_1(x: isize, ...) {}
-//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
 
 fn f1_2(...) {}
-//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
 //~| ERROR C-variadic function must be declared with at least one named argument
 
 extern "C" fn f2_1(x: isize, ...) {}
-//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
 
 extern "C" fn f2_2(...) {}
-//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
 //~| ERROR C-variadic function must be declared with at least one named argument
 
 extern "C" fn f2_3(..., x: isize) {}
-//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
 //~| ERROR `...` must be the last argument of a C-variadic function
 
 extern "C" fn f3_1(x: isize, ...) {}
-//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
 
 extern "C" fn f3_2(...) {}
-//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
 //~| ERROR C-variadic function must be declared with at least one named argument
 
 extern "C" fn f3_3(..., x: isize) {}
-//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
 //~| ERROR `...` must be the last argument of a C-variadic function
 
 extern "C" {
@@ -43,35 +43,35 @@ struct X;
 
 impl X {
     fn i_f1(x: isize, ...) {}
-    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
     fn i_f2(...) {}
-    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
     //~| ERROR C-variadic function must be declared with at least one named argument
     fn i_f3(..., x: isize, ...) {}
-    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
-    //~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
+    //~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
     //~| ERROR `...` must be the last argument of a C-variadic function
     fn i_f4(..., x: isize, ...) {}
-    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
-    //~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
+    //~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
     //~| ERROR `...` must be the last argument of a C-variadic function
 }
 
 trait T {
     fn t_f1(x: isize, ...) {}
-    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
     fn t_f2(x: isize, ...);
-    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
     fn t_f3(...) {}
-    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
     //~| ERROR C-variadic function must be declared with at least one named argument
     fn t_f4(...);
-    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
     //~| ERROR C-variadic function must be declared with at least one named argument
     fn t_f5(..., x: isize) {}
-    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
     //~| ERROR `...` must be the last argument of a C-variadic function
     fn t_f6(..., x: isize);
-    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
     //~| ERROR `...` must be the last argument of a C-variadic function
 }
index 10fd05c0bef3feaef4e8b811a5deb790f1ca91f9..f1cbbb279c8492f19725ce44690aeeb88e386d8d 100644 (file)
@@ -1,4 +1,4 @@
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:6:19
    |
 LL | fn f1_1(x: isize, ...) {}
@@ -10,13 +10,13 @@ error: C-variadic function must be declared with at least one named argument
 LL | fn f1_2(...) {}
    |         ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:9:9
    |
 LL | fn f1_2(...) {}
    |         ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:13:30
    |
 LL | extern "C" fn f2_1(x: isize, ...) {}
@@ -28,7 +28,7 @@ error: C-variadic function must be declared with at least one named argument
 LL | extern "C" fn f2_2(...) {}
    |                    ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:16:20
    |
 LL | extern "C" fn f2_2(...) {}
@@ -40,13 +40,13 @@ error: `...` must be the last argument of a C-variadic function
 LL | extern "C" fn f2_3(..., x: isize) {}
    |                    ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:20:20
    |
 LL | extern "C" fn f2_3(..., x: isize) {}
    |                    ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:24:30
    |
 LL | extern "C" fn f3_1(x: isize, ...) {}
@@ -58,7 +58,7 @@ error: C-variadic function must be declared with at least one named argument
 LL | extern "C" fn f3_2(...) {}
    |                    ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:27:20
    |
 LL | extern "C" fn f3_2(...) {}
@@ -70,7 +70,7 @@ error: `...` must be the last argument of a C-variadic function
 LL | extern "C" fn f3_3(..., x: isize) {}
    |                    ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:31:20
    |
 LL | extern "C" fn f3_3(..., x: isize) {}
@@ -88,7 +88,7 @@ error: `...` must be the last argument of a C-variadic function
 LL |     fn e_f2(..., x: isize);
    |             ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:45:23
    |
 LL |     fn i_f1(x: isize, ...) {}
@@ -100,7 +100,7 @@ error: C-variadic function must be declared with at least one named argument
 LL |     fn i_f2(...) {}
    |             ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:47:13
    |
 LL |     fn i_f2(...) {}
@@ -112,13 +112,13 @@ error: `...` must be the last argument of a C-variadic function
 LL |     fn i_f3(..., x: isize, ...) {}
    |             ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
    |
 LL |     fn i_f3(..., x: isize, ...) {}
    |             ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:50:28
    |
 LL |     fn i_f3(..., x: isize, ...) {}
@@ -130,25 +130,25 @@ error: `...` must be the last argument of a C-variadic function
 LL |     fn i_f4(..., x: isize, ...) {}
    |             ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:54:13
    |
 LL |     fn i_f4(..., x: isize, ...) {}
    |             ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:54:28
    |
 LL |     fn i_f4(..., x: isize, ...) {}
    |                            ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:61:23
    |
 LL |     fn t_f1(x: isize, ...) {}
    |                       ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:63:23
    |
 LL |     fn t_f2(x: isize, ...);
@@ -160,7 +160,7 @@ error: C-variadic function must be declared with at least one named argument
 LL |     fn t_f3(...) {}
    |             ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
    |
 LL |     fn t_f3(...) {}
@@ -172,7 +172,7 @@ error: C-variadic function must be declared with at least one named argument
 LL |     fn t_f4(...);
    |             ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:68:13
    |
 LL |     fn t_f4(...);
@@ -184,7 +184,7 @@ error: `...` must be the last argument of a C-variadic function
 LL |     fn t_f5(..., x: isize) {}
    |             ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:71:13
    |
 LL |     fn t_f5(..., x: isize) {}
@@ -196,7 +196,7 @@ error: `...` must be the last argument of a C-variadic function
 LL |     fn t_f6(..., x: isize);
    |             ^^^
 
-error: only foreign or `unsafe extern "C" functions may be C-variadic
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:74:13
    |
 LL |     fn t_f6(..., x: isize);
diff --git a/src/test/ui/pattern/issue-68394-let-pat-runtime-value.rs b/src/test/ui/pattern/issue-68394-let-pat-runtime-value.rs
deleted file mode 100644 (file)
index f10a7f2..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
-    let x = 255u8;
-    let 0u8..=x = 0;
-    //~^ ERROR runtime values cannot be referenced in patterns
-}
diff --git a/src/test/ui/pattern/issue-68394-let-pat-runtime-value.stderr b/src/test/ui/pattern/issue-68394-let-pat-runtime-value.stderr
deleted file mode 100644 (file)
index c1508bd..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0080]: runtime values cannot be referenced in patterns
-  --> $DIR/issue-68394-let-pat-runtime-value.rs:3:15
-   |
-LL |     let 0u8..=x = 0;
-   |               ^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/pattern/issue-68396-let-float-bug.rs b/src/test/ui/pattern/issue-68396-let-float-bug.rs
deleted file mode 100644 (file)
index afc599a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
-    let 1234567890123456789012345678901234567890e-340: f64 = 0.0;
-    //~^ ERROR could not evaluate float literal (see issue #31407)
-
-    fn param(1234567890123456789012345678901234567890e-340: f64) {}
-    //~^ ERROR could not evaluate float literal (see issue #31407)
-}
diff --git a/src/test/ui/pattern/issue-68396-let-float-bug.stderr b/src/test/ui/pattern/issue-68396-let-float-bug.stderr
deleted file mode 100644 (file)
index 618aa4b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0080]: could not evaluate float literal (see issue #31407)
-  --> $DIR/issue-68396-let-float-bug.rs:2:9
-   |
-LL |     let 1234567890123456789012345678901234567890e-340: f64 = 0.0;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0080]: could not evaluate float literal (see issue #31407)
-  --> $DIR/issue-68396-let-float-bug.rs:5:14
-   |
-LL |     fn param(1234567890123456789012345678901234567890e-340: f64) {}
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.rs b/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.rs
deleted file mode 100644 (file)
index 65f27cf..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#![feature(impl_trait_in_bindings)]
-#![allow(incomplete_features)]
-
-fn main() {
-    const C: impl Copy = 0;
-    match C {
-        C | //~ ERROR: `impl Copy` cannot be used in patterns
-        _ => {}
-    }
-}
diff --git a/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.stderr b/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.stderr
deleted file mode 100644 (file)
index 62dc856..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: `impl Copy` cannot be used in patterns
-  --> $DIR/issue-71042-opaquely-typed-constant-used-in-pattern.rs:7:9
-   |
-LL |         C |
-   |         ^
-
-error: aborting due to previous error
-
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;
diff --git a/src/test/ui/pattern/non-constant-in-const-path.rs b/src/test/ui/pattern/non-constant-in-const-path.rs
new file mode 100644 (file)
index 0000000..3918485
--- /dev/null
@@ -0,0 +1,18 @@
+// Checks if we emit `PatternError`s correctly.
+// This is also a regression test for #27895 and #68394.
+
+static FOO: u8 = 10;
+
+fn main() {
+    let x = 0;
+    let 0u8..=x = 0;
+    //~^ ERROR: runtime values cannot be referenced in patterns
+    let 0u8..=FOO = 0;
+    //~^ ERROR: statics cannot be referenced in patterns
+    match 1 {
+        0 ..= x => {}
+        //~^ ERROR: runtime values cannot be referenced in patterns
+        0 ..= FOO => {}
+        //~^ ERROR: statics cannot be referenced in patterns
+    };
+}
diff --git a/src/test/ui/pattern/non-constant-in-const-path.stderr b/src/test/ui/pattern/non-constant-in-const-path.stderr
new file mode 100644 (file)
index 0000000..53c3974
--- /dev/null
@@ -0,0 +1,28 @@
+error[E0080]: runtime values cannot be referenced in patterns
+  --> $DIR/non-constant-in-const-path.rs:8:15
+   |
+LL |     let 0u8..=x = 0;
+   |               ^
+
+error[E0158]: statics cannot be referenced in patterns
+  --> $DIR/non-constant-in-const-path.rs:10:15
+   |
+LL |     let 0u8..=FOO = 0;
+   |               ^^^
+
+error[E0080]: runtime values cannot be referenced in patterns
+  --> $DIR/non-constant-in-const-path.rs:13:15
+   |
+LL |         0 ..= x => {}
+   |               ^
+
+error[E0158]: statics cannot be referenced in patterns
+  --> $DIR/non-constant-in-const-path.rs:15:15
+   |
+LL |         0 ..= FOO => {}
+   |               ^^^
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0080, E0158.
+For more information about an error, try `rustc --explain E0080`.
index 65c10a7bca75deba5dc98673354130e2d2d1f361..70e6fcb7a07ed2409e7ad8b6f0cae030a0acc69f 100644 (file)
@@ -157,30 +157,45 @@ LL |     trait B {
 error[E0624]: associated function `bar` is private
   --> $DIR/privacy1.rs:77:23
    |
+LL |             fn bar() {}
+   |             -------- private associated function defined here
+...
 LL |         self::baz::A::bar();
    |                       ^^^ private associated function
 
 error[E0624]: associated function `bar` is private
   --> $DIR/privacy1.rs:95:13
    |
+LL |         fn bar() {}
+   |         -------- private associated function defined here
+...
 LL |     bar::A::bar();
    |             ^^^ private associated function
 
 error[E0624]: associated function `bar` is private
   --> $DIR/privacy1.rs:102:19
    |
+LL |         fn bar() {}
+   |         -------- private associated function defined here
+...
 LL |         ::bar::A::bar();
    |                   ^^^ private associated function
 
 error[E0624]: associated function `bar` is private
   --> $DIR/privacy1.rs:105:24
    |
+LL |             fn bar() {}
+   |             -------- private associated function defined here
+...
 LL |         ::bar::baz::A::bar();
    |                        ^^^ private associated function
 
 error[E0624]: associated function `bar2` is private
   --> $DIR/privacy1.rs:108:23
    |
+LL |             fn bar2(&self) {}
+   |             -------------- private associated function defined here
+...
 LL |         ::bar::baz::A.bar2();
    |                       ^^^^ private associated function
 
index 444b9180b3f5977334777f201560760d100b870b..bb54dce7e7e05d4d08e827dfbbfabe08f2c22dd4 100644 (file)
@@ -1,6 +1,9 @@
 error[E0624]: associated function `foo` is private
   --> $DIR/private-impl-method.rs:20:7
    |
+LL |         fn foo(&self) {}
+   |         ------------- private associated function defined here
+...
 LL |     s.foo();
    |       ^^^ private associated function
 
index 8a47846d667e34c8a687e190979e33c3b9f644b4..65329329933635e1e52aea8b8e627fcb230d12f2 100644 (file)
@@ -3,6 +3,11 @@ error[E0624]: associated function `nap` is private
    |
 LL |   nyan.nap();
    |        ^^^ private associated function
+   | 
+  ::: $DIR/auxiliary/cci_class_5.rs:8:9
+   |
+LL |         fn nap(&self) {}
+   |         ------------- private associated function defined here
 
 error: aborting due to previous error
 
index 8083b197a5d78e0facf8b1a24de0f87a0e80adb1..011a7fee478a65b35e1f6fc0e42f5671d9f00fdd 100644 (file)
@@ -1,6 +1,9 @@
 error[E0624]: associated function `f` is private
   --> $DIR/private-method-inherited.rs:13:7
    |
+LL |         fn f(self) {}
+   |         ---------- private associated function defined here
+...
 LL |     x.f();
    |       ^ private associated function
 
index a15fce46877ceb8c3e35cefc43f96a16a97dabdb..17c7179dc3684ed53186edb50a13f6f020c1281d 100644 (file)
@@ -1,6 +1,9 @@
 error[E0624]: associated function `nap` is private
   --> $DIR/private-method.rs:22:8
    |
+LL |         fn nap(&self) {}
+   |         ------------- private associated function defined here
+...
 LL |   nyan.nap();
    |        ^^^ private associated function
 
index 61b9a43f899f9c5fc87cbeeb7969883083ffe67d..6950667f1ea0ba6810c373afdef82cac1f9c1a6b 100644 (file)
@@ -55,12 +55,18 @@ LL |     S::default().x;
 error[E0624]: associated function `f` is private
   --> $DIR/test.rs:32:18
    |
+LL |             pub(super) fn f(&self) {}
+   |             ---------------------- private associated function defined here
+...
 LL |     S::default().f();
    |                  ^ private associated function
 
 error[E0624]: associated function `g` is private
   --> $DIR/test.rs:33:8
    |
+LL |             pub(super) fn g() {}
+   |             ----------------- private associated function defined here
+...
 LL |     S::g();
    |        ^ private associated function
 
@@ -81,12 +87,22 @@ error[E0624]: associated function `g` is private
    |
 LL |     u.g();
    |       ^ private associated function
+   | 
+  ::: $DIR/auxiliary/pub_restricted.rs:14:5
+   |
+LL |     pub(crate) fn g(&self) {}
+   |     ---------------------- private associated function defined here
 
 error[E0624]: associated function `h` is private
   --> $DIR/test.rs:46:7
    |
 LL |     u.h();
    |       ^ private associated function
+   | 
+  ::: $DIR/auxiliary/pub_restricted.rs:15:5
+   |
+LL |     crate fn h(&self) {}
+   |     ----------------- private associated function defined here
 
 error: aborting due to 12 previous errors
 
index c506e903e7f897b7f2ebac04210e0c15615b0a59..6c30e8f4f9558da2a9a3265d1d77c45bea2e0ed6 100644 (file)
@@ -13,7 +13,7 @@ mod m {
 struct Y;
 type A = X; //~ ERROR cannot find type `X` in this scope
 
-#[derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
+#[derive(Copy)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
 mod n {}
 
 #[empty_attr]
index 7141a1b50b570538c371d5d8387089e1792bb7fd..bb6cbb6984d7c1dd30072f73fda3db31a1fd31ea 100644 (file)
@@ -1,8 +1,10 @@
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/attributes-on-modules-fail.rs:16:1
    |
 LL | #[derive(Copy)]
-   | ^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^ not applicable here
+LL | mod n {}
+   | -------- not a `struct`, `enum` or `union`
 
 error[E0658]: non-inline modules in proc macro input are unstable
   --> $DIR/attributes-on-modules-fail.rs:20:1
diff --git a/src/test/ui/proc-macro/auxiliary/call-deprecated.rs b/src/test/ui/proc-macro/auxiliary/call-deprecated.rs
new file mode 100644 (file)
index 0000000..2f48480
--- /dev/null
@@ -0,0 +1,19 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_attribute]
+#[deprecated(since = "1.0.0", note = "test")]
+pub fn attr(_: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_attribute]
+#[deprecated(since = "1.0.0", note = "test")]
+pub fn attr_remove(_: TokenStream, _: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
diff --git a/src/test/ui/proc-macro/call-deprecated.rs b/src/test/ui/proc-macro/call-deprecated.rs
new file mode 100644 (file)
index 0000000..b92cc23
--- /dev/null
@@ -0,0 +1,34 @@
+// check-pass
+// aux-build:call-deprecated.rs
+
+extern crate call_deprecated;
+
+// These first two `#[allow(deprecated)]` attributes
+// do nothing, since the AST nodes for `First` and `Second`
+// haven't been been assigned a `NodeId`.
+// See #63221 for a discussion about how we should
+// handle the interaction of 'inert' attributes and
+// proc-macro attributes.
+
+#[allow(deprecated)]
+#[call_deprecated::attr] //~ WARN use of deprecated macro
+struct First;
+
+#[allow(deprecated)]
+#[call_deprecated::attr_remove] //~ WARN use of deprecated macro
+struct Second;
+
+#[allow(deprecated)]
+mod bar {
+    #[allow(deprecated)]
+    #[call_deprecated::attr]
+    struct Third;
+
+    #[allow(deprecated)]
+    #[call_deprecated::attr_remove]
+    struct Fourth;
+}
+
+
+fn main() {
+}
diff --git a/src/test/ui/proc-macro/call-deprecated.stderr b/src/test/ui/proc-macro/call-deprecated.stderr
new file mode 100644 (file)
index 0000000..3506f9a
--- /dev/null
@@ -0,0 +1,16 @@
+warning: use of deprecated macro `call_deprecated::attr`: test
+  --> $DIR/call-deprecated.rs:14:3
+   |
+LL | #[call_deprecated::attr]
+   |   ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(deprecated)]` on by default
+
+warning: use of deprecated macro `call_deprecated::attr_remove`: test
+  --> $DIR/call-deprecated.rs:18:3
+   |
+LL | #[call_deprecated::attr_remove]
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 2 warnings emitted
+
index e764480e8e548b881f8fa0ba37aee390933d65be..070b066721350956fb1c3fa83d6c3add1b43988f 100644 (file)
@@ -81,7 +81,7 @@ LL |     tuple_from_req!(Foo);
 
 warning: 5 warnings emitted
 
-Future incompatibility report: Future breakage date: None, diagnostic:
+Future incompatibility report: Future breakage diagnostic:
 warning: using an old version of `time-macros-impl`
   --> $DIR/time-macros-impl/src/lib.rs:5:32
    |
@@ -99,7 +99,7 @@ LL |     impl_macros!(Foo);
    = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
    = note: this warning originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-Future breakage date: None, diagnostic:
+Future breakage diagnostic:
 warning: using an old version of `time-macros-impl`
   --> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32
    |
@@ -116,7 +116,7 @@ LL |     impl_macros!(Foo);
    = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
    = note: this warning originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-Future breakage date: None, diagnostic:
+Future breakage diagnostic:
 warning: using an old version of `js-sys`
   --> $DIR/js-sys-0.3.17/src/lib.rs:5:32
    |
@@ -133,7 +133,7 @@ LL |     arrays!(Foo);
    = note: older versions of the `js-sys` crate will stop compiling in future versions of Rust; please update to `js-sys` v0.3.40 or above
    = note: this warning originates in the macro `arrays` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-Future breakage date: None, diagnostic:
+Future breakage diagnostic:
 warning: using an old version of `actix-web`
   --> $DIR/actix-web/src/extract.rs:5:34
    |
@@ -150,7 +150,7 @@ LL |     tuple_from_req!(Foo);
    = note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage
    = note: this warning originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-Future breakage date: None, diagnostic:
+Future breakage diagnostic:
 warning: using an old version of `actix-web`
   --> $DIR/actix-web-2.0.0/src/extract.rs:5:34
    |
index 0b930705e35105dd1df67abc970ef59fe1c755b3..4d6edab08e2cf28b85f668ad55a2549780241bff 100644 (file)
@@ -11,7 +11,7 @@ LL | enum ProceduralMasqueradeDummyType {
 
 warning: 1 warning emitted
 
-Future incompatibility report: Future breakage date: None, diagnostic:
+Future incompatibility report: Future breakage diagnostic:
 warning: using `procedural-masquerade` crate
   --> $DIR/issue-73933-procedural-masquerade.rs:8:6
    |
diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs
new file mode 100644 (file)
index 0000000..8be1ae7
--- /dev/null
@@ -0,0 +1,11 @@
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+//! Inner doc comment
+//~^ ERROR expected outer doc comment
+#[derive(Empty)]
+pub struct Foo;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr
new file mode 100644 (file)
index 0000000..0b2e612
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0753]: expected outer doc comment
+  --> $DIR/issue-86781-bad-inner-doc.rs:6:1
+   |
+LL | //! Inner doc comment
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0753`.
index e52bf435a1244f2dc20f5881d7714e63f4c79c50..c8b26b00597dee378dfe5fa38e8bf793307a3031 100644 (file)
@@ -1,5 +1,5 @@
 extern "C" {
-    #[derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
+    #[derive(Copy)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
     fn f();
 }
 
index 6b73744920931e2406fd6da35287c2a48974f7d2..efd9ff22506ce1b82e7af512486380fdf26d834b 100644 (file)
@@ -1,8 +1,10 @@
-error[E0774]: `derive` may only be applied to structs, enums and unions
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
   --> $DIR/macros-in-extern-derive.rs:2:5
    |
 LL |     #[derive(Copy)]
-   |     ^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^ not applicable here
+LL |     fn f();
+   |     ------- not a `struct`, `enum` or `union`
 
 error: aborting due to previous error
 
index 95ef260537a8a729c5fe2586d15d41a66588e331..2524d8273b705163512b431191dbee7ac7d4654e 100644 (file)
@@ -30,7 +30,7 @@ macro_rules! produce_it
     */ {
     () =>
     {
-        meta_macro :: print_def_site! ($ crate :: dummy! ()) ;
+        meta_macro :: print_def_site! ($crate :: dummy! ()) ;
         // `print_def_site!` will respan the `$crate` identifier
         // with `Span::def_site()`. This should cause it to resolve
         // relative to `meta_macro`, *not* `make_macro` (despite
@@ -43,23 +43,23 @@ 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 }
-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 }
+crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
+crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
+crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it")
+crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site")
+crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy")
+crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
 
 SyntaxContexts:
-#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
-#1: parent: #0, outer_mark: (ExpnId(1), Opaque)
-#2: parent: #0, outer_mark: (ExpnId(1), Transparent)
-#3: parent: #0, outer_mark: (ExpnId(3), Opaque)
-#4: parent: #0, outer_mark: (ExpnId(2), SemiTransparent)
-#5: parent: #0, outer_mark: (ExpnId(4), Opaque)
-#6: parent: #4, outer_mark: (ExpnId(4), Transparent)
-#7: parent: #0, outer_mark: (ExpnId(4), SemiTransparent)
-#8: parent: #0, outer_mark: (ExpnId(5), Opaque)
-#9: parent: #5, outer_mark: (ExpnId(5), Transparent)
-#10: parent: #5, outer_mark: (ExpnId(5), SemiTransparent)
+#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque)
+#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
+#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
+#3: parent: #0, outer_mark: (crate2::{{expn1}}, Opaque)
+#4: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
+#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
+#6: parent: #4, outer_mark: (crate0::{{expn3}}, Transparent)
+#7: parent: #0, outer_mark: (crate0::{{expn3}}, SemiTransparent)
+#8: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque)
+#9: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent)
+#10: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent)
 */
index ac020cddf087438e01fa02bd810eea1f4b8499e0..b5ab82737e9b615acf22b524892f1bd223eeb0bd 100644 (file)
@@ -50,9 +50,9 @@ macro_rules! outer
     /*
     0#0
     */ {
-    ($ item : item) =>
+    ($item : item) =>
     {
-        macro inner() { print_bang! { $ item } } inner! () ;
+        macro inner() { print_bang! { $item } } inner! () ;
 
     } ;
 }
@@ -67,22 +67,22 @@ 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 }
-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 }
+crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
+crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
+crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer")
+crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro(Bang, "inner")
+crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
+crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
 
 SyntaxContexts:
-#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
-#1: parent: #0, outer_mark: (ExpnId(1), Opaque)
-#2: parent: #0, outer_mark: (ExpnId(1), Transparent)
-#3: parent: #0, outer_mark: (ExpnId(3), Opaque)
-#4: parent: #0, outer_mark: (ExpnId(2), SemiTransparent)
-#5: parent: #0, outer_mark: (ExpnId(4), Opaque)
-#6: parent: #4, outer_mark: (ExpnId(4), Opaque)
-#7: parent: #0, outer_mark: (ExpnId(5), Opaque)
-#8: parent: #6, outer_mark: (ExpnId(5), Transparent)
-#9: parent: #5, outer_mark: (ExpnId(5), SemiTransparent)
+#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque)
+#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
+#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
+#3: parent: #0, outer_mark: (crate2::{{expn1}}, Opaque)
+#4: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
+#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
+#6: parent: #4, outer_mark: (crate0::{{expn3}}, Opaque)
+#7: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque)
+#8: parent: #6, outer_mark: (crate0::{{expn4}}, Transparent)
+#9: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent)
 */
index 2cbe91afacdd18557031dd1873ac779e28816059..c3904d62c8df38c0ce536e8594f0bca9bc54ffa0 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
@@ -10,13 +10,13 @@ LL |             field: MissingType
   ::: $DIR/span-from-proc-macro.rs:8:1
    |
 LL | #[error_from_attribute]
-   | ----------------------- in this macro invocation
+   | ----------------------- in this procedural macro expansion
 
 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
@@ -24,13 +24,13 @@ LL |             Variant(OtherMissingType)
   ::: $DIR/span-from-proc-macro.rs:11:10
    |
 LL | #[derive(ErrorFromDerive)]
-   |          --------------- in this macro invocation
+   |          --------------- in this derive macro expansion
 
 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 f306a61a53876fb8572e7493cffdc349b3c27845..b2dab5c93814bce935e3c104d741f5ee06bb52e7 100644 (file)
@@ -9,7 +9,7 @@ use std::{net::TcpListener, sync::mpsc, thread};
 fn main() {
     let (tx, rx) = mpsc::channel();
     thread::spawn(move || {
-        let listen = TcpListener::bind("0.0.0.0:0").unwrap();
+        let listen = TcpListener::bind("127.0.0.1:0").unwrap();
         tx.send(()).unwrap();
         while let Ok(_) = listen.accept() {}
     });
index 2cebffec990f69177bf04e22d444b57824682c25..b282fa7803f03a119cc1b5eb0b3c88975f1a3da2 100644 (file)
@@ -12,7 +12,11 @@ LL |     for i in false..true {}
    |
    = note: required because of the requirements on the impl of `Iterator` for `std::ops::Range<bool>`
    = note: required because of the requirements on the impl of `IntoIterator` for `std::ops::Range<bool>`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
   --> $DIR/range-1.rs:14:17
index 6c01209967605fbc1117a545047c60919c5832fd..8a4b8fc38e37a5c6df74149648a03d4f54ec4edb 100644 (file)
@@ -10,7 +10,7 @@ pub fn main() {
     match &12 {
         &(0..=9) => {}
         //~^ WARN `...` range patterns are deprecated
-        //~| WARN this was previously accepted by the compiler
+        //~| WARN this is accepted in the current edition
         //~| HELP use `..=` for an inclusive range
         &(10 ..=15) => {}
         //~^ ERROR the range pattern here has ambiguous interpretation
index ce763ba267798fc4c43c8f26dd443d493b11ed1f..b294e436fa65457fa5364c405188a212976921cf 100644 (file)
@@ -10,7 +10,7 @@ pub fn main() {
     match &12 {
         &0...9 => {}
         //~^ WARN `...` range patterns are deprecated
-        //~| WARN this was previously accepted by the compiler
+        //~| WARN this is accepted in the current edition
         //~| HELP use `..=` for an inclusive range
         &10..=15 => {}
         //~^ ERROR the range pattern here has ambiguous interpretation
index ffb833535c2f0cf37a06859b89b5c54fe96fe843..3330ced1ebf341aeebb65ee6b145b741de95542a 100644 (file)
@@ -15,7 +15,7 @@ note: the lint level is defined here
    |
 LL | #![warn(ellipsis_inclusive_range_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: aborting due to previous error; 1 warning emitted
index 7fa2698a49603286d3c1c6277c69d9a7c4df55f5..bede9c579766fea4541fc490d00a612b8c9c6e9e 100644 (file)
@@ -9,7 +9,7 @@ fn main() {
         // FIXME: can we add suggestions like `&(0..=9)`?
         box 0...9 => {}
         //~^ WARN `...` range patterns are deprecated
-        //~| WARN this was previously accepted by the compiler
+        //~| WARN this is accepted in the current edition
         //~| HELP use `..=` for an inclusive range
         box 10..=15 => {}
         //~^ ERROR the range pattern here has ambiguous interpretation
index e8e62b485cc1d9615c614fbe99d960956090155c..90a4aa68222f64f16a58bd56e3f3d335d2eae893 100644 (file)
@@ -15,7 +15,7 @@ note: the lint level is defined here
    |
 LL | #![warn(ellipsis_inclusive_range_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: aborting due to previous error; 1 warning emitted
index bc4c9a04b5e4b3aff82dc4c45dbe8362763a5f8a..34c59fcb318a99df40f6829fc7d5d2fdea7ea3b2 100644 (file)
 error[E0277]: can't compare `std::ops::Range<usize>` with `std::ops::Range<usize>`
   --> $DIR/range_traits-1.rs:5:5
    |
+LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+   |                                ---------- in this derive macro expansion
+LL | struct AllTheRanges {
 LL |     a: Range<usize>,
    |     ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range<usize> < std::ops::Range<usize>` and `std::ops::Range<usize> > std::ops::Range<usize>`
    |
    = help: the trait `PartialOrd` is not implemented for `std::ops::Range<usize>`
-   = note: required by `std::cmp::PartialOrd::partial_cmp`
+note: required by `std::cmp::PartialOrd::partial_cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: can't compare `std::ops::RangeTo<usize>` with `std::ops::RangeTo<usize>`
   --> $DIR/range_traits-1.rs:8:5
    |
+LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+   |                                ---------- in this derive macro expansion
+...
 LL |     b: RangeTo<usize>,
    |     ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo<usize> < std::ops::RangeTo<usize>` and `std::ops::RangeTo<usize> > std::ops::RangeTo<usize>`
    |
    = help: the trait `PartialOrd` is not implemented for `std::ops::RangeTo<usize>`
-   = note: required by `std::cmp::PartialOrd::partial_cmp`
+note: required by `std::cmp::PartialOrd::partial_cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: can't compare `std::ops::RangeFrom<usize>` with `std::ops::RangeFrom<usize>`
   --> $DIR/range_traits-1.rs:11:5
    |
+LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+   |                                ---------- in this derive macro expansion
+...
 LL |     c: RangeFrom<usize>,
    |     ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom<usize> < std::ops::RangeFrom<usize>` and `std::ops::RangeFrom<usize> > std::ops::RangeFrom<usize>`
    |
    = help: the trait `PartialOrd` is not implemented for `std::ops::RangeFrom<usize>`
-   = note: required by `std::cmp::PartialOrd::partial_cmp`
+note: required by `std::cmp::PartialOrd::partial_cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull`
   --> $DIR/range_traits-1.rs:14:5
    |
+LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+   |                                ---------- in this derive macro expansion
+...
 LL |     d: RangeFull,
    |     ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull`
    |
    = help: the trait `PartialOrd` is not implemented for `std::ops::RangeFull`
-   = note: required by `std::cmp::PartialOrd::partial_cmp`
+note: required by `std::cmp::PartialOrd::partial_cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: can't compare `std::ops::RangeInclusive<usize>` with `std::ops::RangeInclusive<usize>`
   --> $DIR/range_traits-1.rs:17:5
    |
+LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+   |                                ---------- in this derive macro expansion
+...
 LL |     e: RangeInclusive<usize>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive<usize> < std::ops::RangeInclusive<usize>` and `std::ops::RangeInclusive<usize> > std::ops::RangeInclusive<usize>`
    |
    = help: the trait `PartialOrd` is not implemented for `std::ops::RangeInclusive<usize>`
-   = note: required by `std::cmp::PartialOrd::partial_cmp`
+note: required by `std::cmp::PartialOrd::partial_cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: can't compare `std::ops::RangeToInclusive<usize>` with `std::ops::RangeToInclusive<usize>`
   --> $DIR/range_traits-1.rs:20:5
    |
+LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+   |                                ---------- in this derive macro expansion
+...
 LL |     f: RangeToInclusive<usize>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive<usize> < std::ops::RangeToInclusive<usize>` and `std::ops::RangeToInclusive<usize> > std::ops::RangeToInclusive<usize>`
    |
    = help: the trait `PartialOrd` is not implemented for `std::ops::RangeToInclusive<usize>`
-   = note: required by `std::cmp::PartialOrd::partial_cmp`
+note: required by `std::cmp::PartialOrd::partial_cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `std::ops::Range<usize>: Ord` is not satisfied
   --> $DIR/range_traits-1.rs:5:5
    |
+LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+   |                                            --- in this derive macro expansion
+LL | struct AllTheRanges {
 LL |     a: Range<usize>,
    |     ^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::Range<usize>`
    |
-   = note: required by `std::cmp::Ord::cmp`
+note: required by `std::cmp::Ord::cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn cmp(&self, other: &Self) -> Ordering;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `std::ops::RangeTo<usize>: Ord` is not satisfied
   --> $DIR/range_traits-1.rs:8:5
    |
+LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+   |                                            --- in this derive macro expansion
+...
 LL |     b: RangeTo<usize>,
    |     ^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeTo<usize>`
    |
-   = note: required by `std::cmp::Ord::cmp`
+note: required by `std::cmp::Ord::cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn cmp(&self, other: &Self) -> Ordering;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `std::ops::RangeFrom<usize>: Ord` is not satisfied
   --> $DIR/range_traits-1.rs:11:5
    |
+LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+   |                                            --- in this derive macro expansion
+...
 LL |     c: RangeFrom<usize>,
    |     ^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeFrom<usize>`
    |
-   = note: required by `std::cmp::Ord::cmp`
+note: required by `std::cmp::Ord::cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn cmp(&self, other: &Self) -> Ordering;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `std::ops::RangeFull: Ord` is not satisfied
   --> $DIR/range_traits-1.rs:14:5
    |
+LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+   |                                            --- in this derive macro expansion
+...
 LL |     d: RangeFull,
    |     ^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeFull`
    |
-   = note: required by `std::cmp::Ord::cmp`
+note: required by `std::cmp::Ord::cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn cmp(&self, other: &Self) -> Ordering;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `std::ops::RangeInclusive<usize>: Ord` is not satisfied
   --> $DIR/range_traits-1.rs:17:5
    |
+LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+   |                                            --- in this derive macro expansion
+...
 LL |     e: RangeInclusive<usize>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeInclusive<usize>`
    |
-   = note: required by `std::cmp::Ord::cmp`
+note: required by `std::cmp::Ord::cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn cmp(&self, other: &Self) -> Ordering;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `std::ops::RangeToInclusive<usize>: Ord` is not satisfied
   --> $DIR/range_traits-1.rs:20:5
    |
+LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+   |                                            --- in this derive macro expansion
+...
 LL |     f: RangeToInclusive<usize>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeToInclusive<usize>`
    |
-   = note: required by `std::cmp::Ord::cmp`
+note: required by `std::cmp::Ord::cmp`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL |     fn cmp(&self, other: &Self) -> Ordering;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 12 previous errors
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-83505-repr-simd.rs b/src/test/ui/repr/issue-83505-repr-simd.rs
new file mode 100644 (file)
index 0000000..280b771
--- /dev/null
@@ -0,0 +1,10 @@
+// Regression test for the ICE described in #83505.
+
+#![crate_type="lib"]
+
+#[repr(simd)]
+//~^ ERROR: attribute should be applied to a struct [E0517]
+//~| ERROR: unsupported representation for zero-variant enum [E0084]
+enum Es {}
+static CLs: Es;
+//~^ ERROR: free static item without body
diff --git a/src/test/ui/repr/issue-83505-repr-simd.stderr b/src/test/ui/repr/issue-83505-repr-simd.stderr
new file mode 100644 (file)
index 0000000..f1390a6
--- /dev/null
@@ -0,0 +1,30 @@
+error: free static item without body
+  --> $DIR/issue-83505-repr-simd.rs:9:1
+   |
+LL | static CLs: Es;
+   | ^^^^^^^^^^^^^^-
+   |               |
+   |               help: provide a definition for the static: `= <expr>;`
+
+error[E0517]: attribute should be applied to a struct
+  --> $DIR/issue-83505-repr-simd.rs:5:8
+   |
+LL | #[repr(simd)]
+   |        ^^^^
+...
+LL | enum Es {}
+   | ---------- not a struct
+
+error[E0084]: unsupported representation for zero-variant enum
+  --> $DIR/issue-83505-repr-simd.rs:5:1
+   |
+LL | #[repr(simd)]
+   | ^^^^^^^^^^^^^
+...
+LL | enum Es {}
+   | ---------- zero-variant enum
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0084, E0517.
+For more information about an error, try `rustc --explain E0084`.
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 90cad7e647b057d54b75626a30847a66b5e37075..d9bd0b0e38a692bbe527612187c8a53c8cf7b311 100644 (file)
@@ -2,7 +2,7 @@ struct Test;
 
 enum Foo {
     #[repr(u8)]
-    //~^ ERROR attribute should be applied to a struct, enum, or union
+    //~^ ERROR attribute should be applied to an enum
     Variant,
 }
 
index 70b45e393fcf1a7182d4525b9151862eee4751dc..f7e4dcc9d81be39db1bb52a2ffc97809ac67267a 100644 (file)
@@ -1,11 +1,11 @@
-error[E0517]: attribute should be applied to a struct, enum, or union
+error[E0517]: attribute should be applied to an enum
   --> $DIR/repr-disallow-on-variant.rs:4:12
    |
 LL |     #[repr(u8)]
    |            ^^
 LL |
 LL |     Variant,
-   |     ------- not a struct, enum, or union
+   |     ------- not an enum
 
 error: aborting due to previous error
 
index 8fbdb4cc80b5e14bebc5fb9ac61b1841ddb11689..8c9d1639c0a51ffc965388a2204fdf14dc4fd1f6 100644 (file)
@@ -8,27 +8,29 @@
 use std::marker::PhantomData;
 
 #[repr(transparent)]
-struct NoFields; //~ ERROR needs exactly one non-zero-sized field
+struct NoFields;
 
 #[repr(transparent)]
-struct ContainsOnlyZst(()); //~ ERROR needs exactly one non-zero-sized field
+struct ContainsOnlyZst(());
 
 #[repr(transparent)]
-struct ContainsOnlyZstArray([bool; 0]); //~ ERROR needs exactly one non-zero-sized field
+struct ContainsOnlyZstArray([bool; 0]);
 
 #[repr(transparent)]
 struct ContainsMultipleZst(PhantomData<*const i32>, NoFields);
-//~^ ERROR needs exactly one non-zero-sized field
 
 #[repr(transparent)]
-struct MultipleNonZst(u8, u8); //~ ERROR needs exactly one non-zero-sized field
+struct ContainsZstAndNonZst((), [i32; 2]);
+
+#[repr(transparent)]
+struct MultipleNonZst(u8, u8); //~ ERROR needs at most one non-zero-sized field
 
 trait Mirror { type It: ?Sized; }
 impl<T: ?Sized> Mirror for T { type It = Self; }
 
 #[repr(transparent)]
 pub struct StructWithProjection(f32, <f32 as Mirror>::It);
-//~^ ERROR needs exactly one non-zero-sized field
+//~^ ERROR needs at most one non-zero-sized field
 
 #[repr(transparent)]
 struct NontrivialAlignZst(u32, [u16; 0]); //~ ERROR alignment larger than 1
@@ -40,22 +42,26 @@ struct ZstAlign32<T>(PhantomData<T>);
 struct GenericAlign<T>(ZstAlign32<T>, u32); //~ ERROR alignment larger than 1
 
 #[repr(transparent)] //~ ERROR unsupported representation for zero-variant enum
-enum Void {}
-//~^ ERROR transparent enum needs exactly one variant, but has 0
+enum Void {} //~ ERROR transparent enum needs exactly one variant, but has 0
 
 #[repr(transparent)]
-enum FieldlessEnum { //~ ERROR transparent enum needs exactly one non-zero-sized field, but has 0
+enum FieldlessEnum {
     Foo,
 }
 
+#[repr(transparent)]
+enum UnitFieldEnum {
+    Foo(()),
+}
+
 #[repr(transparent)]
 enum TooManyFieldsEnum {
     Foo(u32, String),
 }
-//~^^^ ERROR transparent enum needs exactly one non-zero-sized field, but has 2
+//~^^^ ERROR transparent enum needs at most one non-zero-sized field, but has 2
 
 #[repr(transparent)]
-enum TooManyVariants { //~ ERROR transparent enum needs exactly one variant, but has 2
+enum MultipleVariants { //~ ERROR transparent enum needs exactly one variant, but has 2
     Foo(String),
     Bar,
 }
@@ -71,12 +77,12 @@ enum GenericAlignEnum<T> {
 }
 
 #[repr(transparent)]
-union UnitUnion { //~ ERROR transparent union needs exactly one non-zero-sized field, but has 0
+union UnitUnion {
     u: (),
 }
 
 #[repr(transparent)]
-union TooManyFields { //~ ERROR transparent union needs exactly one non-zero-sized field, but has 2
+union TooManyFields { //~ ERROR transparent union needs at most one non-zero-sized field, but has 2
     u: u32,
     s: i32
 }
index cbc74fbb6a2cf48b638f60fe14afbcdd8ddfceeb..001a181881f14cf5775fc3b9e0b73c89e0b86e8b 100644 (file)
@@ -1,61 +1,37 @@
-error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
-  --> $DIR/repr-transparent.rs:11:1
-   |
-LL | struct NoFields;
-   | ^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
-
-error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
-  --> $DIR/repr-transparent.rs:14:1
-   |
-LL | struct ContainsOnlyZst(());
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
-
-error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
-  --> $DIR/repr-transparent.rs:17:1
-   |
-LL | struct ContainsOnlyZstArray([bool; 0]);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
-
-error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
-  --> $DIR/repr-transparent.rs:20:1
-   |
-LL | struct ContainsMultipleZst(PhantomData<*const i32>, NoFields);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
-
-error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2
-  --> $DIR/repr-transparent.rs:24:1
+error[E0690]: transparent struct needs at most one non-zero-sized field, but has 2
+  --> $DIR/repr-transparent.rs:26:1
    |
 LL | struct MultipleNonZst(u8, u8);
    | ^^^^^^^^^^^^^^^^^^^^^^--^^--^^
    | |                     |   |
    | |                     |   this field is non-zero-sized
    | |                     this field is non-zero-sized
-   | needs exactly one non-zero-sized field, but has 2
+   | needs at most one non-zero-sized field, but has 2
 
-error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2
-  --> $DIR/repr-transparent.rs:30:1
+error[E0690]: transparent struct needs at most one non-zero-sized field, but has 2
+  --> $DIR/repr-transparent.rs:32:1
    |
 LL | pub struct StructWithProjection(f32, <f32 as Mirror>::It);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^-------------------^^
    | |                               |    |
    | |                               |    this field is non-zero-sized
    | |                               this field is non-zero-sized
-   | needs exactly one non-zero-sized field, but has 2
+   | needs at most one non-zero-sized field, but has 2
 
 error[E0691]: zero-sized field in transparent struct has alignment larger than 1
-  --> $DIR/repr-transparent.rs:34:32
+  --> $DIR/repr-transparent.rs:36:32
    |
 LL | struct NontrivialAlignZst(u32, [u16; 0]);
    |                                ^^^^^^^^ has alignment larger than 1
 
 error[E0691]: zero-sized field in transparent struct has alignment larger than 1
-  --> $DIR/repr-transparent.rs:40:24
+  --> $DIR/repr-transparent.rs:42:24
    |
 LL | struct GenericAlign<T>(ZstAlign32<T>, u32);
    |                        ^^^^^^^^^^^^^ has alignment larger than 1
 
 error[E0084]: unsupported representation for zero-variant enum
-  --> $DIR/repr-transparent.rs:42:1
+  --> $DIR/repr-transparent.rs:44:1
    |
 LL | #[repr(transparent)]
    | ^^^^^^^^^^^^^^^^^^^^
@@ -63,66 +39,54 @@ LL | enum Void {}
    | ------------ zero-variant enum
 
 error[E0731]: transparent enum needs exactly one variant, but has 0
-  --> $DIR/repr-transparent.rs:43:1
+  --> $DIR/repr-transparent.rs:45:1
    |
 LL | enum Void {}
    | ^^^^^^^^^ needs exactly one variant, but has 0
 
-error[E0690]: the variant of a transparent enum needs exactly one non-zero-sized field, but has 0
-  --> $DIR/repr-transparent.rs:47:1
-   |
-LL | enum FieldlessEnum {
-   | ^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
-
-error[E0690]: the variant of a transparent enum needs exactly one non-zero-sized field, but has 2
-  --> $DIR/repr-transparent.rs:52:1
+error[E0690]: the variant of a transparent enum needs at most one non-zero-sized field, but has 2
+  --> $DIR/repr-transparent.rs:58:1
    |
 LL | enum TooManyFieldsEnum {
-   | ^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 2
+   | ^^^^^^^^^^^^^^^^^^^^^^ needs at most one non-zero-sized field, but has 2
 LL |     Foo(u32, String),
    |         ---  ------ this field is non-zero-sized
    |         |
    |         this field is non-zero-sized
 
 error[E0731]: transparent enum needs exactly one variant, but has 2
-  --> $DIR/repr-transparent.rs:58:1
+  --> $DIR/repr-transparent.rs:64:1
    |
-LL | enum TooManyVariants {
-   | ^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2
+LL | enum MultipleVariants {
+   | ^^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2
 LL |     Foo(String),
    |     -----------
 LL |     Bar,
-   |     --- too many variants in `TooManyVariants`
+   |     --- too many variants in `MultipleVariants`
 
 error[E0691]: zero-sized field in transparent enum has alignment larger than 1
-  --> $DIR/repr-transparent.rs:65:14
+  --> $DIR/repr-transparent.rs:71:14
    |
 LL |     Foo(u32, [u16; 0]),
    |              ^^^^^^^^ has alignment larger than 1
 
 error[E0691]: zero-sized field in transparent enum has alignment larger than 1
-  --> $DIR/repr-transparent.rs:70:11
+  --> $DIR/repr-transparent.rs:76:11
    |
 LL |     Foo { bar: ZstAlign32<T>, baz: u32 }
    |           ^^^^^^^^^^^^^^^^^^ has alignment larger than 1
 
-error[E0690]: transparent union needs exactly one non-zero-sized field, but has 0
-  --> $DIR/repr-transparent.rs:74:1
-   |
-LL | union UnitUnion {
-   | ^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
-
-error[E0690]: transparent union needs exactly one non-zero-sized field, but has 2
-  --> $DIR/repr-transparent.rs:79:1
+error[E0690]: transparent union needs at most one non-zero-sized field, but has 2
+  --> $DIR/repr-transparent.rs:85:1
    |
 LL | union TooManyFields {
-   | ^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 2
+   | ^^^^^^^^^^^^^^^^^^^ needs at most one non-zero-sized field, but has 2
 LL |     u: u32,
    |     ------ this field is non-zero-sized
 LL |     s: i32
    |     ------ this field is non-zero-sized
 
-error: aborting due to 17 previous errors
+error: aborting due to 11 previous errors
 
 Some errors have detailed explanations: E0084, E0690, E0691, E0731.
 For more information about an error, try `rustc --explain E0084`.
diff --git a/src/test/ui/resolve/use_suggestion_placement.fixed b/src/test/ui/resolve/use_suggestion_placement.fixed
new file mode 100644 (file)
index 0000000..6367632
--- /dev/null
@@ -0,0 +1,39 @@
+// run-rustfix
+#![allow(dead_code)]
+
+use m::A;
+
+use std::collections::HashMap;
+
+macro_rules! y {
+    () => {}
+}
+
+mod m {
+    pub const A: i32 = 0;
+}
+
+mod foo {
+    // FIXME: UsePlacementFinder is broken because active attributes are
+    // removed, and thus the `derive` attribute here is not in the AST.
+    // An inert attribute should work, though.
+    // #[derive(Debug)]
+    use std::path::Path;
+
+#[allow(warnings)]
+    pub struct Foo;
+
+    // test whether the use suggestion isn't
+    // placed into the expansion of `#[derive(Debug)]
+    type Bar = Path; //~ ERROR cannot find
+}
+
+fn main() {
+    y!();
+    let _ = A; //~ ERROR cannot find
+    foo();
+}
+
+fn foo() {
+    type Dict<K, V> = HashMap<K, V>; //~ ERROR cannot find
+}
index 56d4b8d6d11cfcd978986db7c2bcb94839f10d29..ecc74d781679d5702ae193fb39b96d3bf274f678 100644 (file)
@@ -1,3 +1,6 @@
+// run-rustfix
+#![allow(dead_code)]
+
 macro_rules! y {
     () => {}
 }
@@ -7,7 +10,11 @@ mod m {
 }
 
 mod foo {
-    #[derive(Debug)]
+    // FIXME: UsePlacementFinder is broken because active attributes are
+    // removed, and thus the `derive` attribute here is not in the AST.
+    // An inert attribute should work, though.
+    // #[derive(Debug)]
+    #[allow(warnings)]
     pub struct Foo;
 
     // test whether the use suggestion isn't
index af0495a57a1e078e68f6612af18b7d9de6dcbdb5..217c08a560b77f7b1f754bef703097233e96beba 100644 (file)
@@ -1,5 +1,5 @@
 error[E0412]: cannot find type `Path` in this scope
-  --> $DIR/use_suggestion_placement.rs:15:16
+  --> $DIR/use_suggestion_placement.rs:22:16
    |
 LL |     type Bar = Path;
    |                ^^^^ not found in this scope
@@ -10,7 +10,7 @@ LL |     use std::path::Path;
    |
 
 error[E0425]: cannot find value `A` in this scope
-  --> $DIR/use_suggestion_placement.rs:20:13
+  --> $DIR/use_suggestion_placement.rs:27:13
    |
 LL |     let _ = A;
    |             ^ not found in this scope
@@ -21,7 +21,7 @@ LL | use m::A;
    |
 
 error[E0412]: cannot find type `HashMap` in this scope
-  --> $DIR/use_suggestion_placement.rs:25:23
+  --> $DIR/use_suggestion_placement.rs:32:23
    |
 LL |     type Dict<K, V> = HashMap<K, V>;
    |                       ^^^^^^^ not found in this scope
index 9b5f11ce667653d0df23ec2733183e73d536bfca..798ce1199a9dc24ac41b70f26fc13f00c5f85b43 100644 (file)
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/retslot-cast.rs:13:5
    |
+LL |             -> Option<&Iterator<Item=()>> {
+   |                -------------------------- expected `Option<&dyn Iterator<Item = ()>>` because of return type
+...
 LL |     inner(x)
    |     ^^^^^^^^ expected trait `Iterator<Item = ()>`, found trait `Iterator<Item = ()> + Send`
    |
diff --git a/src/test/ui/return/issue-86188-return-not-in-fn-body.rs b/src/test/ui/return/issue-86188-return-not-in-fn-body.rs
new file mode 100644 (file)
index 0000000..4f076fa
--- /dev/null
@@ -0,0 +1,41 @@
+// Due to a compiler bug, if a return occurs outside of a function body
+// (e.g. in an AnonConst body), the return value expression would not be
+// type-checked, leading to an ICE. This test checks that the ICE no
+// longer happens, and that an appropriate error message is issued that
+// also explains why the return is considered "outside of a function body"
+// if it seems to be inside one, as in the main function below.
+
+const C: [(); 42] = {
+    [(); return || {
+    //~^ ERROR: return statement outside of function body [E0572]
+        let tx;
+    }]
+};
+
+struct S {}
+trait Tr {
+    fn foo();
+    fn bar() {
+    //~^ NOTE: ...not the enclosing function body
+        [(); return];
+        //~^ ERROR: return statement outside of function body [E0572]
+        //~| NOTE: the return is part of this body...
+    }
+}
+impl Tr for S {
+    fn foo() {
+    //~^ NOTE: ...not the enclosing function body
+        [(); return];
+        //~^ ERROR: return statement outside of function body [E0572]
+        //~| NOTE: the return is part of this body...
+    }
+}
+
+fn main() {
+//~^ NOTE: ...not the enclosing function body
+    [(); return || {
+    //~^ ERROR: return statement outside of function body [E0572]
+    //~| NOTE: the return is part of this body...
+        let tx;
+    }];
+}
diff --git a/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr b/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr
new file mode 100644 (file)
index 0000000..d7eeb3a
--- /dev/null
@@ -0,0 +1,52 @@
+error[E0572]: return statement outside of function body
+  --> $DIR/issue-86188-return-not-in-fn-body.rs:9:10
+   |
+LL |       [(); return || {
+   |  __________^
+LL | |
+LL | |         let tx;
+LL | |     }]
+   | |_____^
+
+error[E0572]: return statement outside of function body
+  --> $DIR/issue-86188-return-not-in-fn-body.rs:20:14
+   |
+LL | /     fn bar() {
+LL | |
+LL | |         [(); return];
+   | |              ^^^^^^ the return is part of this body...
+LL | |
+LL | |
+LL | |     }
+   | |_____- ...not the enclosing function body
+
+error[E0572]: return statement outside of function body
+  --> $DIR/issue-86188-return-not-in-fn-body.rs:28:14
+   |
+LL | /     fn foo() {
+LL | |
+LL | |         [(); return];
+   | |              ^^^^^^ the return is part of this body...
+LL | |
+LL | |
+LL | |     }
+   | |_____- ...not the enclosing function body
+
+error[E0572]: return statement outside of function body
+  --> $DIR/issue-86188-return-not-in-fn-body.rs:36:10
+   |
+LL |  / fn main() {
+LL |  |
+LL |  |     [(); return || {
+   |  |__________^
+LL | ||
+LL | ||
+LL | ||         let tx;
+LL | ||     }];
+   | ||_____^ the return is part of this body...
+LL |  | }
+   |  |_- ...not the enclosing function body
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0572`.
index f21eac37c17b5325405b37638ee5fba497d0d15c..b619a4d57f9553ef4812cfa3a4b1fa5ecd8640c1 100644 (file)
@@ -1,10 +1,19 @@
 fn main() {
+//~^ NOTE: not the enclosing function body
+//~| NOTE: not the enclosing function body
+//~| NOTE: not the enclosing function body
     [(); return match 0 { n => n }];
-    //~^ ERROR: return statement outside of function body
+    //~^ ERROR: return statement outside of function body [E0572]
+    //~| NOTE: the return is part of this body...
 
     [(); return match 0 { 0 => 0 }];
-    //~^ ERROR: return statement outside of function body
+    //~^ ERROR: return statement outside of function body [E0572]
+    //~| NOTE: the return is part of this body...
 
     [(); return match () { 'a' => 0, _ => 0 }];
-    //~^ ERROR: return statement outside of function body
+    //~^ ERROR: return statement outside of function body [E0572]
+    //~| NOTE: the return is part of this body...
+    //~| ERROR: mismatched types [E0308]
+    //~| NOTE: expected `()`, found `char`
+    //~| NOTE: this expression has type `()`
 }
index 8e801e3fbb7abd9f030b1b2ad719008205f5f860..85a733adfee69448cd7ff6d804502e971c64b309 100644 (file)
@@ -1,21 +1,56 @@
 error[E0572]: return statement outside of function body
-  --> $DIR/return-match-array-const.rs:2:10
+  --> $DIR/return-match-array-const.rs:5:10
    |
-LL |     [(); return match 0 { n => n }];
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+LL | |     [(); return match 0 { n => n }];
+   | |          ^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body...
+...  |
+LL | |
+LL | | }
+   | |_- ...not the enclosing function body
 
 error[E0572]: return statement outside of function body
-  --> $DIR/return-match-array-const.rs:5:10
+  --> $DIR/return-match-array-const.rs:9:10
    |
-LL |     [(); return match 0 { 0 => 0 }];
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     [(); return match 0 { 0 => 0 }];
+   | |          ^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body...
+...  |
+LL | |
+LL | | }
+   | |_- ...not the enclosing function body
 
 error[E0572]: return statement outside of function body
-  --> $DIR/return-match-array-const.rs:8:10
+  --> $DIR/return-match-array-const.rs:13:10
+   |
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     [(); return match () { 'a' => 0, _ => 0 }];
+   | |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body...
+...  |
+LL | |
+LL | | }
+   | |_- ...not the enclosing function body
+
+error[E0308]: mismatched types
+  --> $DIR/return-match-array-const.rs:13:28
    |
 LL |     [(); return match () { 'a' => 0, _ => 0 }];
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       --   ^^^ expected `()`, found `char`
+   |                       |
+   |                       this expression has type `()`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0572`.
+Some errors have detailed explanations: E0308, E0572.
+For more information about an error, try `rustc --explain E0308`.
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 1949e762873761067502b20afd4462e50270cf29..e33253b19c4bdba4d396239783a1d85cf8be7a49 100644 (file)
@@ -1,6 +1,8 @@
 error[E0277]: `main` has invalid return type `Result<f32, ParseFloatError>`
   --> $DIR/termination-trait-test-wrong-type.rs:6:1
    |
+LL |   #[test]
+   |   ------- in this procedural macro expansion
 LL | / fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
 LL | |     "0".parse()
 LL | | }
index af82d36f87eb080e7046c2ee29663726fb744408..4e57769d6e24c877885437173092118d558a9e52 100644 (file)
@@ -6,17 +6,17 @@ use Wrapper::Wrap;
 
 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);
 }
index 850ca30405ff1025a6358802c7d2236b9e04d1f3..3cdab6541e7d10e62f980323407866a90dffc203 100644 (file)
@@ -5,9 +5,7 @@ LL |     let _: NotDebug = dbg!(NotDebug);
    |                       ^^^^^^^^^^^^^^ `NotDebug` cannot be formatted using `{:?}`
    |
    = help: the trait `Debug` is not implemented for `NotDebug`
-   = note: add `#[derive(Debug)]` or manually implement `Debug`
-   = note: required because of the requirements on the impl of `Debug` for `&NotDebug`
-   = note: required by `std::fmt::Debug::fmt`
+   = note: add `#[derive(Debug)]` to `NotDebug` or manually `impl Debug for NotDebug`
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 6985f1b71a8db806b8aa7871e424a82029fd6634..4950b65414161afc230c7b6882523b6eb37b62d3 100644 (file)
@@ -502,7 +502,11 @@ LL |     if (let 0 = 0)? {}
    |        ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
    |
    = help: the trait `Try` is not implemented for `bool`
-   = note: required by `branch`
+note: required by `branch`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/disallowed-positions.rs:46:19
@@ -520,7 +524,11 @@ LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<_>` is not implemented for `()`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:56:8
@@ -660,7 +668,11 @@ LL |         if let 0 = 0? {}
    |                    ^^ the `?` operator cannot be applied to type `{integer}`
    |
    = help: the trait `Try` is not implemented for `{integer}`
-   = note: required by `branch`
+note: required by `branch`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:96:11
@@ -690,7 +702,11 @@ LL |     while (let 0 = 0)? {}
    |           ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
    |
    = help: the trait `Try` is not implemented for `bool`
-   = note: required by `branch`
+note: required by `branch`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/disallowed-positions.rs:110:22
@@ -708,7 +724,11 @@ LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<_>` is not implemented for `()`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:120:11
@@ -848,7 +868,11 @@ LL |         while let 0 = 0? {}
    |                       ^^ the `?` operator cannot be applied to type `{integer}`
    |
    = help: the trait `Try` is not implemented for `{integer}`
-   = note: required by `branch`
+note: required by `branch`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0614]: type `bool` cannot be dereferenced
   --> $DIR/disallowed-positions.rs:173:5
@@ -869,7 +893,11 @@ LL |     (let 0 = 0)?;
    |     ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
    |
    = help: the trait `Try` is not implemented for `bool`
-   = note: required by `branch`
+note: required by `branch`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/disallowed-positions.rs:183:16
@@ -887,7 +915,11 @@ LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<_>` is not implemented for `()`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:198:10
@@ -916,7 +948,11 @@ LL |         let 0 = 0?;
    |                 ^^ the `?` operator cannot be applied to type `{integer}`
    |
    = help: the trait `Try` is not implemented for `{integer}`
-   = note: required by `branch`
+note: required by `branch`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 104 previous errors; 2 warnings emitted
 
diff --git a/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs
new file mode 100644 (file)
index 0000000..d02bebc
--- /dev/null
@@ -0,0 +1,19 @@
+// only-i686-pc-windows-msvc
+// compile-flags: --crate-type lib --emit link
+#![allow(clashing_extern_declarations)]
+#![feature(raw_dylib)]
+//~^ WARN the feature `raw_dylib` is incomplete
+#[link(name = "foo", kind = "raw-dylib")]
+extern "C" {
+    fn f(x: i32);
+}
+
+pub fn lib_main() {
+    #[link(name = "foo", kind = "raw-dylib")]
+    extern "stdcall" {
+        fn f(x: i32);
+        //~^ ERROR multiple declarations of external function `f` from library `foo.dll` have different calling conventions
+    }
+
+    unsafe { f(42); }
+}
diff --git a/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr
new file mode 100644 (file)
index 0000000..a9cfd6b
--- /dev/null
@@ -0,0 +1,17 @@
+warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/multiple-declarations.rs:4:12
+   |
+LL | #![feature(raw_dylib)]
+   |            ^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
+
+error: multiple declarations of external function `f` from library `foo.dll` have different calling conventions
+  --> $DIR/multiple-declarations.rs:14:9
+   |
+LL |         fn f(x: i32);
+   |         ^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
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 5a66af1d29e9483039a6e61457fa68dffc8ba752..4a1bd5da98b8a403876e778d041c7589f7f05a8d 100644 (file)
@@ -3,7 +3,6 @@
 // FIXME: This test should fail since, within a const impl of `Foo`, the bound on `Foo::Bar` should
 // require a const impl of `Add` for the associated type.
 
-#![allow(incomplete_features)]
 #![feature(const_trait_impl)]
 
 struct NonConstAdd(i32);
diff --git a/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs b/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs
new file mode 100644 (file)
index 0000000..be73ec0
--- /dev/null
@@ -0,0 +1,13 @@
+#![feature(const_trait_impl)]
+
+#[default_method_body_is_const] //~ ERROR attribute should be applied
+trait A {
+    #[default_method_body_is_const] //~ ERROR attribute should be applied
+    fn no_body(self);
+
+    #[default_method_body_is_const]
+    fn correct_use(&self) {}
+}
+
+#[default_method_body_is_const] //~ ERROR attribute should be applied
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.stderr b/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.stderr
new file mode 100644 (file)
index 0000000..fcb7e15
--- /dev/null
@@ -0,0 +1,32 @@
+error: attribute should be applied to a trait method with body
+  --> $DIR/attr-misuse.rs:3:1
+   |
+LL |   #[default_method_body_is_const]
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait A {
+LL | |     #[default_method_body_is_const]
+LL | |     fn no_body(self);
+LL | |
+LL | |     #[default_method_body_is_const]
+LL | |     fn correct_use(&self) {}
+LL | | }
+   | |_- not a trait method or missing a body
+
+error: attribute should be applied to a trait method with body
+  --> $DIR/attr-misuse.rs:12:1
+   |
+LL | #[default_method_body_is_const]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn main() {}
+   | ------------ not a trait method or missing a body
+
+error: attribute should be applied to a trait method with body
+  --> $DIR/attr-misuse.rs:5:5
+   |
+LL |     #[default_method_body_is_const]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     fn no_body(self);
+   |     ----------------- not a trait method or missing a body
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs
new file mode 100644 (file)
index 0000000..d8fd7ef
--- /dev/null
@@ -0,0 +1,21 @@
+#![feature(const_trait_impl)]
+
+pub trait MyTrait {
+    fn func(self);
+}
+
+pub struct NonConst;
+
+impl MyTrait for NonConst {
+    fn func(self) {
+
+    }
+}
+
+pub struct Const;
+
+impl const MyTrait for Const {
+    fn func(self) {
+
+    }
+}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs
new file mode 100644 (file)
index 0000000..80e61ab
--- /dev/null
@@ -0,0 +1,21 @@
+#![feature(const_trait_impl)]
+
+#![feature(staged_api)]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait MyTrait {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn func();
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Unstable;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature = "staged", issue = "none")]
+impl const MyTrait for Unstable {
+    fn func() {
+
+    }
+}
index fa5570d5454a05c2c0659eff12ad5772c4cb501e..33e839fd1203d51b5e70e6d9aa0e24e79df29a91 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(const_trait_impl)]
 
 pub trait Plus {
index d3f350e1b61db98a8c6085b3ec034c51e2076faa..5a73c4debb481d0bfe1c47bb657c2490c9ed5692 100644 (file)
@@ -1,5 +1,5 @@
 error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/call-const-trait-method-fail.rs:25:5
+  --> $DIR/call-const-trait-method-fail.rs:24:5
    |
 LL |     a.plus(b)
    |     ^^^^^^^^^
index ec6f45f956d75d8c77d21aacb749b3535baa965d..cf38bc3c9645321cafbcf9f9e3e279e07e01a3a7 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 
-#![allow(incomplete_features)]
 #![feature(const_trait_impl)]
 
 struct Int(i32);
@@ -17,6 +16,9 @@ impl const PartialEq for Int {
     fn eq(&self, rhs: &Self) -> bool {
         self.0 == rhs.0
     }
+    fn ne(&self, other: &Self) -> bool {
+        !self.eq(other)
+    }
 }
 
 pub trait Plus {
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs
new file mode 100644 (file)
index 0000000..536c1d7
--- /dev/null
@@ -0,0 +1,15 @@
+// check-pass
+#![feature(const_fn_trait_bound)]
+#![feature(const_trait_impl)]
+
+trait MyPartialEq {
+    fn eq(&self, other: &Self) -> bool;
+}
+
+impl<T: PartialEq> const MyPartialEq for T {
+    fn eq(&self, other: &Self) -> bool {
+        PartialEq::eq(self, other)
+    }
+}
+
+fn main() {}
index c37990b1af3ddf4ab086779d294038264bb047de..f3391aa63468cf91580aec8019bdd5bcb5e7a73e 100644 (file)
@@ -4,7 +4,6 @@
 
 #![feature(const_trait_impl)]
 #![feature(const_fn_trait_bound)]
-#![allow(incomplete_features)]
 
 struct S;
 
@@ -12,6 +11,9 @@ impl const PartialEq for S {
     fn eq(&self, _: &S) -> bool {
         true
     }
+    fn ne(&self, other: &S) -> bool {
+        !self.eq(other)
+    }
 }
 
 const fn equals_self<T: PartialEq>(t: &T) -> bool {
index d553b2ab8ec47b75e31dabed861570048e68238c..00a3c7f51fe90df88eeedf1b1aa9cbc2654d83db 100644 (file)
@@ -11,6 +11,9 @@ impl const PartialEq for S {
     fn eq(&self, _: &S) -> bool {
         true
     }
+    fn ne(&self, other: &S) -> bool {
+        !self.eq(other)
+    }
 }
 
 // This duplicate bound should not result in ambiguities. It should be equivalent to a single const
index 9aefe6380cb18133109a0f588a00f070e57cf06f..087f8fbdcd1ea85eaca4ce49b197b9d250159742 100644 (file)
@@ -2,7 +2,6 @@
 // ignore-test
 
 #![feature(const_trait_impl)]
-#![allow(incomplete_features)]
 
 struct S;
 
index 74b0d5fbe474ba767110754fbf0ddf0cfb5ab22a..aee88d6053eee2cee24404f497867fe66abe009e 100644 (file)
@@ -4,7 +4,6 @@
 
 #![feature(const_trait_impl)]
 #![feature(const_fn_trait_bound)]
-#![allow(incomplete_features)]
 
 struct S;
 
@@ -12,6 +11,9 @@ impl const PartialEq for S {
     fn eq(&self, _: &S) -> bool {
         true
     }
+    fn ne(&self, other: &S) -> bool {
+        !self.eq(other)
+    }
 }
 
 const fn equals_self<T: PartialEq>(t: &T) -> bool {
index e148ad9a0ee14d217381b80a355a2bbec35615a6..4b2f049b99d9e05063772574e45b0b1f2e34a63c 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(const_trait_impl)]
 
 pub struct Int(i32);
index 99560ed06888aeab78a1e16d1f2c0a2b3e950597..a0960a21d46f87e1c45420e6911e85ba61bce4df 100644 (file)
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `std::ops::Add` for type `i32`
-  --> $DIR/const-and-non-const-impl.rs:6:1
+  --> $DIR/const-and-non-const-impl.rs:5:1
    |
 LL | impl const std::ops::Add for i32 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | impl const std::ops::Add for i32 {
            - impl Add for i32;
 
 error[E0119]: conflicting implementations of trait `std::ops::Add` for type `Int`
-  --> $DIR/const-and-non-const-impl.rs:24:1
+  --> $DIR/const-and-non-const-impl.rs:23:1
    |
 LL | impl std::ops::Add for Int {
    | -------------------------- first implementation here
@@ -17,7 +17,7 @@ LL | impl const std::ops::Add for Int {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int`
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/const-and-non-const-impl.rs:6:1
+  --> $DIR/const-and-non-const-impl.rs:5:1
    |
 LL | impl const std::ops::Add for i32 {
    | ^^^^^^^^^^^-------------^^^^^---
index fc85e98ef532689d924d1ec0741c7458935cde7e..3a7074163523b0dab00be8a7c79ec3ebf47031d3 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(const_trait_impl)]
 
 struct S;
index c6c78c7d1e89564873908c5bb6cff24f0334bd01..aaec67161a6afe241b7eaee1a55cc7ec3b7f6f7e 100644 (file)
@@ -1,5 +1,5 @@
 error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/const-check-fns-in-const-impl.rs:12:16
+  --> $DIR/const-check-fns-in-const-impl.rs:11:16
    |
 LL |     fn foo() { non_const() }
    |                ^^^^^^^^^^^
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs
new file mode 100644 (file)
index 0000000..7a0db9c
--- /dev/null
@@ -0,0 +1,30 @@
+#![feature(const_trait_impl)]
+#![feature(const_fn_trait_bound)] // FIXME is this needed?
+
+trait ConstDefaultFn: Sized {
+    fn b(self);
+
+    #[default_method_body_is_const]
+    fn a(self) {
+        self.b();
+    }
+}
+
+struct NonConstImpl;
+struct ConstImpl;
+
+impl ConstDefaultFn for NonConstImpl {
+    fn b(self) {}
+}
+
+impl const ConstDefaultFn for ConstImpl {
+    fn b(self) {}
+}
+
+const fn test() {
+    NonConstImpl.a();
+    //~^ ERROR calls in constant functions are limited to constant functions, tuple structs and tuple variants
+    ConstImpl.a();
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
new file mode 100644 (file)
index 0000000..63e4095
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/const-default-method-bodies.rs:25:5
+   |
+LL |     NonConstImpl.a();
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
index 936c90e88aaeecdd4d75270ee0865e98c0cce5b7..bed4e9fd1e610acf74fe18e2b6aefe0626104ecb 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(const_trait_impl)]
-#![allow(incomplete_features)]
 
 struct Foo;
 
index 612511a479956d388544f40d7ba023fb7c77d1c4..603f6b7d2835e88b373b31d2a6b2d8b4710d6bed 100644 (file)
@@ -1,5 +1,5 @@
 error: expected identifier, found keyword `impl`
-  --> $DIR/const-impl-norecover.rs:6:7
+  --> $DIR/const-impl-norecover.rs:5:7
    |
 LL | const impl Foo {
    |       ^^^^ expected identifier, found keyword
index fd3dd2cef9d1c9c8ba95d8d6e51ec9fceff8f1e1..470c653dd47019b5b1a978c766e37c5303d8f540 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(const_trait_impl)]
-#![allow(incomplete_features)]
 
 trait Foo {}
 
index 84fb619dc9648815d6c83b6c3bb4054c3838e787..f815389ff01c3cacfbd480fab870243544426b9a 100644 (file)
@@ -1,5 +1,5 @@
 error: expected identifier, found keyword `impl`
-  --> $DIR/const-impl-recovery.rs:6:7
+  --> $DIR/const-impl-recovery.rs:5:7
    |
 LL | const impl Foo for i32 {}
    |       ^^^^ expected identifier, found keyword
@@ -10,7 +10,7 @@ LL | impl const Foo for i32 {}
    |--    ^^^^^
 
 error: expected identifier, found keyword `impl`
-  --> $DIR/const-impl-recovery.rs:10:7
+  --> $DIR/const-impl-recovery.rs:9:7
    |
 LL | const impl<T: Foo> Bar for T {}
    |       ^^^^ expected identifier, found keyword
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr
new file mode 100644 (file)
index 0000000..3f553a8
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/cross-crate.rs:15:5
+   |
+LL |     NonConst.func();
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs
new file mode 100644 (file)
index 0000000..4bd3359
--- /dev/null
@@ -0,0 +1,21 @@
+// revisions: stock gated
+#![cfg_attr(gated, feature(const_trait_impl))]
+
+// aux-build: cross-crate.rs
+extern crate cross_crate;
+
+use cross_crate::*;
+
+fn non_const_context() {
+    NonConst.func();
+    Const.func();
+}
+
+const fn const_context() {
+    NonConst.func();
+    //~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+    Const.func();
+    //[stock]~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr
new file mode 100644 (file)
index 0000000..9908f47
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/cross-crate.rs:15:5
+   |
+LL |     NonConst.func();
+   |     ^^^^^^^^^^^^^^^
+
+error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/cross-crate.rs:17:5
+   |
+LL |     Const.func();
+   |     ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0015`.
index 4c630d33c55163b7eca430c391c21e601613f246..af4d3909e40515d083c322f20741e7b8f3256aff 100644 (file)
@@ -1,5 +1,5 @@
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/feature-gate.rs:14:1
+  --> $DIR/feature-gate.rs:13:1
    |
 LL | fn main() {}
    | ^^^^^^^^^
index d9772431941d373ab5bab07cad3741c6203971e4..7bac72e1bb6fb608c2854ac5a3f89f7d391efed4 100644 (file)
@@ -2,7 +2,6 @@
 // gate-test-const_trait_impl
 
 #![cfg_attr(gated, feature(const_trait_impl))]
-#![allow(incomplete_features)]
 #![feature(rustc_attrs)]
 
 struct S;
index 724090e49cd415ed8e3d2e0ea502eb159a7e67e1..91a8bb578a829ecdd7f0ec9f8312a745fc5b9acf 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: const trait impls are experimental
-  --> $DIR/feature-gate.rs:10:6
+  --> $DIR/feature-gate.rs:9:6
    |
 LL | impl const T for S {}
    |      ^^^^^
index d3680820312605d8a57a14353e830254cfa405b4..91c3d2d5920bc6675b625f86ace4209f335d169a 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 
-#![allow(incomplete_features)]
 #![feature(const_trait_impl)]
 #![feature(const_fn_trait_bound)]
 
index ad14dd62bc7b5b7c021522214501e23283bd6e11..80a4442de2cba7332df2d0d4ce4787f02d9db52f 100644 (file)
@@ -1,7 +1,6 @@
 // Regression test for #69615.
 
 #![feature(const_trait_impl)]
-#![allow(incomplete_features)]
 
 pub trait MyTrait {
     fn method(&self) -> Option<()>;
index 8c76d7eb597b6a29c08e42820c934acc1a739bc1..3ec329cba1eb2a027bbd07794078ae136b6e5079 100644 (file)
@@ -1,5 +1,5 @@
 error[E0744]: `?` is not allowed in a `const fn`
-  --> $DIR/hir-const-check.rs:12:9
+  --> $DIR/hir-const-check.rs:11:9
    |
 LL |         Some(())?;
    |         ^^^^^^^^^
diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs
new file mode 100644 (file)
index 0000000..59de9e9
--- /dev/null
@@ -0,0 +1,37 @@
+#![feature(const_trait_impl)]
+
+trait Tr {
+    fn req(&self);
+
+    fn prov(&self) {
+        println!("lul");
+        self.req();
+    }
+
+    #[default_method_body_is_const]
+    fn default() {}
+}
+
+struct S;
+
+impl const Tr for S {
+    fn req(&self) {}
+} //~^^ ERROR const trait implementations may not use non-const default functions
+
+impl const Tr for u8 {
+    fn req(&self) {}
+    fn prov(&self) {}
+}
+
+impl const Tr for u16 {
+    fn prov(&self) {}
+    fn default() {}
+} //~^^^ ERROR not all trait items implemented
+
+
+impl const Tr for u32 {
+    fn req(&self) {}
+    fn default() {}
+} //~^^^ ERROR const trait implementations may not use non-const default functions
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr
new file mode 100644 (file)
index 0000000..5301e0a
--- /dev/null
@@ -0,0 +1,33 @@
+error: const trait implementations may not use non-const default functions
+  --> $DIR/impl-with-default-fn.rs:17:1
+   |
+LL | / impl const Tr for S {
+LL | |     fn req(&self) {}
+LL | | }
+   | |_^
+   |
+   = note: `prov` not implemented
+
+error: const trait implementations may not use non-const default functions
+  --> $DIR/impl-with-default-fn.rs:32:1
+   |
+LL | / impl const Tr for u32 {
+LL | |     fn req(&self) {}
+LL | |     fn default() {}
+LL | | }
+   | |_^
+   |
+   = note: `prov` not implemented
+
+error[E0046]: not all trait items implemented, missing: `req`
+  --> $DIR/impl-with-default-fn.rs:26:1
+   |
+LL |     fn req(&self);
+   |     -------------- `req` from trait
+...
+LL | impl const Tr for u16 {
+   | ^^^^^^^^^^^^^^^^^^^^^ missing `req` in implementation
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0046`.
index 454fde34a2cdca25aee5f58945b45ba4c88d204a..6b54a9eab5205bb904bfb9474b30d7f44f773962 100644 (file)
@@ -1,4 +1,3 @@
-#![allow(incomplete_features)]
 #![feature(allow_internal_unstable)]
 #![feature(const_add)]
 #![feature(const_trait_impl)]
index 5b2ebccef1c6dd42c5654bafd35d0e1653d5eb31..86b685959a6cbcc77f0239a165cbed1349f82ee8 100644 (file)
@@ -1,5 +1,5 @@
 error: trait methods cannot be stable const fn
-  --> $DIR/stability.rs:14:5
+  --> $DIR/stability.rs:13:5
    |
 LL | /     fn sub(self, rhs: Self) -> Self {
 LL | |
@@ -8,7 +8,7 @@ LL | |     }
    | |_____^
 
 error: `<Int as Add>::add` is not yet stable as a const fn
-  --> $DIR/stability.rs:32:5
+  --> $DIR/stability.rs:31:5
    |
 LL |     Int(1i32) + Int(2i32)
    |     ^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs
new file mode 100644 (file)
index 0000000..39a1b60
--- /dev/null
@@ -0,0 +1,39 @@
+// revisions: stock staged
+#![cfg_attr(staged, feature(staged))]
+
+#![feature(const_trait_impl)]
+#![allow(incomplete_features)]
+
+#![feature(staged_api)]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+// aux-build: staged-api.rs
+extern crate staged_api;
+
+use staged_api::*;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Stable;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(staged, rustc_const_stable(feature = "rust1", since = "1.0.0"))]
+// ^ should trigger error with or without the attribute
+impl const MyTrait for Stable {
+    fn func() { //~ ERROR trait methods cannot be stable const fn
+
+    }
+}
+
+fn non_const_context() {
+    Unstable::func();
+    Stable::func();
+}
+
+#[unstable(feature = "none", issue = "none")]
+const fn const_context() {
+    Unstable::func();
+    //[stock]~^ ERROR `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn
+    Stable::func();
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr
new file mode 100644 (file)
index 0000000..d2ff4ce
--- /dev/null
@@ -0,0 +1,10 @@
+error: trait methods cannot be stable const fn
+  --> $DIR/staged-api.rs:22:5
+   |
+LL | /     fn func() {
+LL | |
+LL | |     }
+   | |_____^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr
new file mode 100644 (file)
index 0000000..91c5469
--- /dev/null
@@ -0,0 +1,18 @@
+error: trait methods cannot be stable const fn
+  --> $DIR/staged-api.rs:22:5
+   |
+LL | /     fn func() {
+LL | |
+LL | |     }
+   | |_____^
+
+error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn
+  --> $DIR/staged-api.rs:34:5
+   |
+LL |     Unstable::func();
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(staged)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
index 354d48d630f7b6c14a6d0b6e2a78005c8af5b91d..82a1275bffaedf89ee825a02233a49d1985306f9 100644 (file)
@@ -3,7 +3,6 @@
 
 #![feature(const_trait_bound_opt_out)]
 #![feature(const_trait_impl)]
-#![allow(incomplete_features)]
 
 // For now, this parses since an error does not occur until AST lowering.
 impl ?const T {}
diff --git a/src/test/ui/rt-explody-panic-payloads.rs b/src/test/ui/rt-explody-panic-payloads.rs
new file mode 100644 (file)
index 0000000..1d3a2ff
--- /dev/null
@@ -0,0 +1,30 @@
+// run-pass
+// ignore-emscripten no processes
+// ignore-sgx no processes
+// ignore-wasm32-bare no unwinding panic
+// ignore-avr no unwinding panic
+// ignore-nvptx64 no unwinding panic
+
+use std::env;
+use std::process::Command;
+
+struct Bomb;
+
+impl Drop for Bomb {
+    fn drop(&mut self) {
+        std::panic::panic_any(Bomb);
+    }
+}
+
+fn main() {
+    let args = env::args().collect::<Vec<_>>();
+    let output = match &args[..] {
+        [me] => Command::new(&me).arg("plant the").output(),
+        [..] => std::panic::panic_any(Bomb),
+    }.expect("running the command should have succeeded");
+    println!("{:#?}", output);
+    let stderr = std::str::from_utf8(&output.stderr);
+    assert!(stderr.map(|v| {
+        v.ends_with("drop of the panic payload panicked")
+    }).unwrap_or(false));
+}
index 9d961214afc07da41d23e81578c1036bb7bc1ffb..8efcfbb7074240c12a247b7bd77811c9d2ea5cc0 100644 (file)
@@ -7,5 +7,5 @@
 
 fn main() {
     let async = 3; //~ ERROR: is a keyword
-    //~^ WARN previously accepted
+    //~^ WARN this is accepted in the current edition
 }
index 43fc3f5e334ecec1164f8daa519a2a93bd62827c..5b63eab8e466dcff64911874b21627728506680d 100644 (file)
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![deny(rust_2018_compatibility)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^
    = note: `#[deny(keyword_idents)]` implied by `#[deny(rust_2018_compatibility)]`
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: aborting due to previous error
index 3d6f6ff8c492249954b99a68fcb7711582ad1ca8..f4ae518c71d2727fdd2a5003c84c02b483868cc5 100644 (file)
@@ -5,20 +5,20 @@
 // run-rustfix
 
 fn r#async() {} //~ ERROR async
-//~^ WARN hard error in the 2018 edition
+//~^ WARN this is accepted in the current edition
 
 macro_rules! foo {
     ($foo:ident) => {};
     ($r#async:expr, r#async) => {};
     //~^ ERROR async
     //~| ERROR async
-    //~| WARN hard error in the 2018 edition
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
+    //~| WARN this is accepted in the current edition
 }
 
 foo!(r#async);
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 
 mod dont_lint_raw {
     fn r#async() {}
@@ -27,53 +27,53 @@ mod dont_lint_raw {
 mod async_trait {
     trait r#async {}
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
     struct MyStruct;
     impl r#async for MyStruct {}
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 }
 
 mod async_static {
     static r#async: u32 = 0;
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 }
 
 mod async_const {
     const r#async: u32 = 0;
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 }
 
 struct Foo;
 impl Foo { fn r#async() {} }
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 
 fn main() {
     struct r#async {}
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
     let r#async: r#async = r#async {};
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
     //~| ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
     //~| ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 }
 
 #[macro_export]
 macro_rules! produces_async {
     () => (pub fn r#async() {})
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 }
 
 #[macro_export]
 macro_rules! consumes_async {
     (r#async) => (1)
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 }
index 6e8d33d237d526bf6ba3b27c41391efc11554eb9..79c73dafac7a3391f33f9a0261385fafef38eee0 100644 (file)
@@ -5,20 +5,20 @@
 // run-rustfix
 
 fn async() {} //~ ERROR async
-//~^ WARN hard error in the 2018 edition
+//~^ WARN this is accepted in the current edition
 
 macro_rules! foo {
     ($foo:ident) => {};
     ($async:expr, async) => {};
     //~^ ERROR async
     //~| ERROR async
-    //~| WARN hard error in the 2018 edition
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
+    //~| WARN this is accepted in the current edition
 }
 
 foo!(async);
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 
 mod dont_lint_raw {
     fn r#async() {}
@@ -27,53 +27,53 @@ mod dont_lint_raw {
 mod async_trait {
     trait async {}
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
     struct MyStruct;
     impl async for MyStruct {}
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 }
 
 mod async_static {
     static async: u32 = 0;
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 }
 
 mod async_const {
     const async: u32 = 0;
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 }
 
 struct Foo;
 impl Foo { fn async() {} }
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 
 fn main() {
     struct async {}
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
     let async: async = async {};
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
     //~| ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
     //~| ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 }
 
 #[macro_export]
 macro_rules! produces_async {
     () => (pub fn async() {})
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 }
 
 #[macro_export]
 macro_rules! consumes_async {
     (async) => (1)
     //~^ ERROR async
-    //~| WARN hard error in the 2018 edition
+    //~| WARN this is accepted in the current edition
 }
index 6051c81f77c9070ca8ec61df6c68e53d77a20401..6396e9deee228e945e6bd3723a8eeeea45a693e8 100644 (file)
@@ -9,7 +9,7 @@ note: the lint level is defined here
    |
 LL | #![deny(keyword_idents)]
    |         ^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
@@ -18,7 +18,7 @@ error: `async` is a keyword in the 2018 edition
 LL |     ($async:expr, async) => {};
    |       ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
@@ -27,7 +27,7 @@ error: `async` is a keyword in the 2018 edition
 LL |     ($async:expr, async) => {};
    |                   ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
@@ -36,7 +36,7 @@ error: `async` is a keyword in the 2018 edition
 LL | foo!(async);
    |      ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
@@ -45,7 +45,7 @@ error: `async` is a keyword in the 2018 edition
 LL |     trait async {}
    |           ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
@@ -54,7 +54,7 @@ error: `async` is a keyword in the 2018 edition
 LL |     impl async for MyStruct {}
    |          ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
@@ -63,7 +63,7 @@ error: `async` is a keyword in the 2018 edition
 LL |     static async: u32 = 0;
    |            ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
@@ -72,7 +72,7 @@ error: `async` is a keyword in the 2018 edition
 LL |     const async: u32 = 0;
    |           ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
@@ -81,7 +81,7 @@ error: `async` is a keyword in the 2018 edition
 LL | impl Foo { fn async() {} }
    |               ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
@@ -90,7 +90,7 @@ error: `async` is a keyword in the 2018 edition
 LL |     struct async {}
    |            ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
@@ -99,7 +99,7 @@ error: `async` is a keyword in the 2018 edition
 LL |     let async: async = async {};
    |         ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
@@ -108,7 +108,7 @@ error: `async` is a keyword in the 2018 edition
 LL |     let async: async = async {};
    |                ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
@@ -117,7 +117,7 @@ error: `async` is a keyword in the 2018 edition
 LL |     let async: async = async {};
    |                        ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
@@ -126,7 +126,7 @@ error: `async` is a keyword in the 2018 edition
 LL |     () => (pub fn async() {})
    |                   ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
@@ -135,7 +135,7 @@ error: `async` is a keyword in the 2018 edition
 LL |     (async) => (1)
    |      ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: aborting due to 15 previous errors
index e9cda1af939321d435923db4d948ca52fe6fb0af..044824cbbd3677fd89f0c93bda3faac47b888785 100644 (file)
@@ -6,5 +6,5 @@
 
 fn main() {
     let r#dyn = (); //~ ERROR dyn
-    //~^ WARN hard error in the 2018 edition
+    //~^ WARN this is accepted in the current edition
 }
index bdd3a90cab9ec40ad43b93c367f876556d76c9d0..5989cfa1c799a7a192431656cc971c0633bd583d 100644 (file)
@@ -6,5 +6,5 @@
 
 fn main() {
     let dyn = (); //~ ERROR dyn
-    //~^ WARN hard error in the 2018 edition
+    //~^ WARN this is accepted in the current edition
 }
index 0fe11168c440fd40e3e40ab1f728e244597f697e..699242f2dcb01a0da333399ba6ee63a7e32459a0 100644 (file)
@@ -9,7 +9,7 @@ note: the lint level is defined here
    |
 LL | #![deny(keyword_idents)]
    |         ^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: aborting due to previous error
index 76fbfa660311aeb0438a089f35be7efe0052f6eb..37847a98ac7826cb000583abd06614dafd0ae42d 100644 (file)
@@ -8,20 +8,19 @@ mod foo {
         type Bar;
     }
 
-    crate struct Baz { }
+    crate struct Baz {}
 
     impl Foo for Baz {
         type Bar = ();
     }
 }
 
-
 fn main() {
     let _: <foo::Baz as crate::foo::Foo>::Bar = ();
     //~^ ERROR absolute paths must start with
-    //~| this was previously accepted
+    //~| this is accepted in the current edition
 
     let _: <crate::foo::Baz as foo::Foo>::Bar = ();
     //~^ ERROR absolute paths must start with
-    //~| this was previously accepted
+    //~| this is accepted in the current edition
 }
index ace90a180d65fba3b7d4124582e2f818c27ce7b2..36efa14601d184532556cc821a5501a1a7d11ae0 100644 (file)
@@ -8,20 +8,19 @@ mod foo {
         type Bar;
     }
 
-    crate struct Baz { }
+    crate struct Baz {}
 
     impl Foo for Baz {
         type Bar = ();
     }
 }
 
-
 fn main() {
     let _: <foo::Baz as ::foo::Foo>::Bar = ();
     //~^ ERROR absolute paths must start with
-    //~| this was previously accepted
+    //~| this is accepted in the current edition
 
     let _: <::foo::Baz as foo::Foo>::Bar = ();
     //~^ ERROR absolute paths must start with
-    //~| this was previously accepted
+    //~| this is accepted in the current edition
 }
index 0b400786d3507fb232befbe7435d7f99d723fd98..6f529fa9114bc76b4521bde195b6084a77d7117d 100644 (file)
@@ -1,5 +1,5 @@
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-fully-qualified-paths.rs:20:25
+  --> $DIR/edition-lint-fully-qualified-paths.rs:19:25
    |
 LL |     let _: <foo::Baz as ::foo::Foo>::Bar = ();
    |                         ^^^^^^^^^^ help: use `crate`: `crate::foo::Foo`
@@ -9,16 +9,16 @@ note: the lint level is defined here
    |
 LL | #![deny(absolute_paths_not_starting_with_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-fully-qualified-paths.rs:24:13
+  --> $DIR/edition-lint-fully-qualified-paths.rs:23:13
    |
 LL |     let _: <::foo::Baz as foo::Foo>::Bar = ();
    |             ^^^^^^^^^^ help: use `crate`: `crate::foo::Baz`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: aborting due to 2 previous errors
index 77478e8c608ff3e653461c00e4e03fda4d2e8843..03d15cea280f6bf84c342526754730bf69e08231 100644 (file)
@@ -16,15 +16,15 @@ crate mod foo {
 
 use crate::foo::{bar::{baz::{}}};
 //~^ ERROR absolute paths must start with
-//~| WARN this was previously accepted
+//~| WARN this is accepted in the current edition
 
 use crate::foo::{bar::{XX, baz::{}}};
 //~^ ERROR absolute paths must start with
-//~| WARN this was previously accepted
+//~| WARN this is accepted in the current edition
 
 use crate::foo::{bar::{baz::{}, baz1::{}}};
 //~^ ERROR absolute paths must start with
-//~| WARN this was previously accepted
+//~| WARN this is accepted in the current edition
 
 fn main() {
 }
index 69bd4e3a187e69f37b74cc6af77ffa226278c058..d898daaba59cafad7a23fd810284b4ada2e56358 100644 (file)
@@ -16,15 +16,15 @@ crate mod foo {
 
 use foo::{bar::{baz::{}}};
 //~^ ERROR absolute paths must start with
-//~| WARN this was previously accepted
+//~| WARN this is accepted in the current edition
 
 use foo::{bar::{XX, baz::{}}};
 //~^ ERROR absolute paths must start with
-//~| WARN this was previously accepted
+//~| WARN this is accepted in the current edition
 
 use foo::{bar::{baz::{}, baz1::{}}};
 //~^ ERROR absolute paths must start with
-//~| WARN this was previously accepted
+//~| WARN this is accepted in the current edition
 
 fn main() {
 }
index d554cc28621c27ad6e88b655b61ed8973bd1c513..54a4fed5cf9b8293d14f17a8aec5e52785899bbf 100644 (file)
@@ -9,7 +9,7 @@ note: the lint level is defined here
    |
 LL | #![deny(absolute_paths_not_starting_with_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
@@ -18,7 +18,7 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external c
 LL | use foo::{bar::{XX, baz::{}}};
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{XX, baz::{}}}`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
@@ -27,7 +27,7 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external c
 LL | use foo::{bar::{baz::{}, baz1::{}}};
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{baz::{}, baz1::{}}}`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: aborting due to 3 previous errors
index da7524a63e2405d53957d5551d56b340610f9734..7c6e4a71a37e356fd4aaf69d00097a6ee2964fb0 100644 (file)
@@ -5,7 +5,7 @@
 
 use crate::foo::{a, b};
 //~^ ERROR absolute paths must start with
-//~| this was previously accepted
+//~| this is accepted in the current edition
 
 mod foo {
     crate fn a() {}
@@ -20,7 +20,7 @@ fn main() {
     {
         use crate::foo::{self as x, c};
         //~^ ERROR absolute paths must start with
-        //~| this was previously accepted
+        //~| this is accepted in the current edition
         x::a();
         c();
     }
index e13b7d0086406354d5947418f4c4f6d0f04c7e92..3925f76391ab81895802c22a72fecbdde7fe659d 100644 (file)
@@ -5,7 +5,7 @@
 
 use foo::{a, b};
 //~^ ERROR absolute paths must start with
-//~| this was previously accepted
+//~| this is accepted in the current edition
 
 mod foo {
     crate fn a() {}
@@ -20,7 +20,7 @@ fn main() {
     {
         use foo::{self as x, c};
         //~^ ERROR absolute paths must start with
-        //~| this was previously accepted
+        //~| this is accepted in the current edition
         x::a();
         c();
     }
index 040aa4a54806ab0d65a8925f7bda3df14dc6aba0..c2f91e342f56a7f5417333add6cff71920026bed 100644 (file)
@@ -9,7 +9,7 @@ note: the lint level is defined here
    |
 LL | #![deny(absolute_paths_not_starting_with_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
@@ -18,7 +18,7 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external c
 LL |         use foo::{self as x, c};
    |             ^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{self as x, c}`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: aborting due to 2 previous errors
index de16291fea6bd322a212abf9885ed20dc5e1f405..f91405929ee115e4cc7852f5d33501179c9f92c8 100644 (file)
@@ -11,30 +11,29 @@ pub mod foo {
     use edition_lint_paths;
     use crate::bar::Bar;
     //~^ ERROR absolute
-    //~| WARN this was previously accepted
+    //~| WARN this is accepted in the current edition
     use super::bar::Bar2;
     use crate::bar::Bar3;
 
     use crate::bar;
     //~^ ERROR absolute
-    //~| WARN this was previously accepted
-    use crate::{bar as something_else};
+    //~| WARN this is accepted in the current edition
+    use crate::bar as something_else;
 
-    use crate::{Bar as SomethingElse, main};
+    use crate::{main, Bar as SomethingElse};
     //~^ ERROR absolute
-    //~| WARN this was previously accepted
+    //~| WARN this is accepted in the current edition
 
-    use crate::{Bar as SomethingElse2, main as another_main};
+    use crate::{main as another_main, Bar as SomethingElse2};
 
-    pub fn test() {
-    }
+    pub fn test() {}
 
-    pub trait SomeTrait { }
+    pub trait SomeTrait {}
 }
 
 use crate::bar::Bar;
 //~^ ERROR absolute
-//~| WARN this was previously accepted
+//~| WARN this is accepted in the current edition
 
 pub mod bar {
     use edition_lint_paths as foo;
@@ -46,17 +45,17 @@ pub mod bar {
 mod baz {
     use crate::*;
     //~^ ERROR absolute
-    //~| WARN this was previously accepted
+    //~| WARN this is accepted in the current edition
 }
 
-impl crate::foo::SomeTrait for u32 { }
+impl crate::foo::SomeTrait for u32 {}
 //~^ ERROR absolute
-//~| WARN this was previously accepted
+//~| WARN this is accepted in the current edition
 
 fn main() {
     let x = crate::bar::Bar;
     //~^ ERROR absolute
-    //~| WARN this was previously accepted
+    //~| WARN this is accepted in the current edition
     let x = bar::Bar;
     let x = crate::bar::Bar;
     let x = self::bar::Bar;
index c5b4be5a3acf9f41a01e71714ebe20f3abf8289c..52c97c7a25393e7b3061b7a056930c495af367c7 100644 (file)
@@ -9,32 +9,31 @@ extern crate edition_lint_paths;
 
 pub mod foo {
     use edition_lint_paths;
-    use ::bar::Bar;
+    use bar::Bar;
     //~^ ERROR absolute
-    //~| WARN this was previously accepted
+    //~| WARN this is accepted in the current edition
     use super::bar::Bar2;
     use crate::bar::Bar3;
 
     use bar;
     //~^ ERROR absolute
-    //~| WARN this was previously accepted
-    use crate::{bar as something_else};
+    //~| WARN this is accepted in the current edition
+    use crate::bar as something_else;
 
-    use {Bar as SomethingElse, main};
+    use {main, Bar as SomethingElse};
     //~^ ERROR absolute
-    //~| WARN this was previously accepted
+    //~| WARN this is accepted in the current edition
 
-    use crate::{Bar as SomethingElse2, main as another_main};
+    use crate::{main as another_main, Bar as SomethingElse2};
 
-    pub fn test() {
-    }
+    pub fn test() {}
 
-    pub trait SomeTrait { }
+    pub trait SomeTrait {}
 }
 
 use bar::Bar;
 //~^ ERROR absolute
-//~| WARN this was previously accepted
+//~| WARN this is accepted in the current edition
 
 pub mod bar {
     use edition_lint_paths as foo;
@@ -46,17 +45,17 @@ pub mod bar {
 mod baz {
     use *;
     //~^ ERROR absolute
-    //~| WARN this was previously accepted
+    //~| WARN this is accepted in the current edition
 }
 
-impl ::foo::SomeTrait for u32 { }
+impl ::foo::SomeTrait for u32 {}
 //~^ ERROR absolute
-//~| WARN this was previously accepted
+//~| WARN this is accepted in the current edition
 
 fn main() {
     let x = ::bar::Bar;
     //~^ ERROR absolute
-    //~| WARN this was previously accepted
+    //~| WARN this is accepted in the current edition
     let x = bar::Bar;
     let x = crate::bar::Bar;
     let x = self::bar::Bar;
index dd36d07da56edb5c21c3fc433763568358d8bd35..23deeda14a4d0d7a266e66e19ea28225e129a622 100644 (file)
@@ -1,15 +1,15 @@
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
   --> $DIR/edition-lint-paths.rs:12:9
    |
-LL |     use ::bar::Bar;
-   |         ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar`
+LL |     use bar::Bar;
+   |         ^^^^^^^^ help: use `crate`: `crate::bar::Bar`
    |
 note: the lint level is defined here
   --> $DIR/edition-lint-paths.rs:5:9
    |
 LL | #![deny(absolute_paths_not_starting_with_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
@@ -18,52 +18,52 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external c
 LL |     use bar;
    |         ^^^ help: use `crate`: `crate::bar`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
   --> $DIR/edition-lint-paths.rs:23:9
    |
-LL |     use {Bar as SomethingElse, main};
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::{Bar as SomethingElse, main}`
+LL |     use {main, Bar as SomethingElse};
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::{main, Bar as SomethingElse}`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-paths.rs:35:5
+  --> $DIR/edition-lint-paths.rs:34:5
    |
 LL | use bar::Bar;
    |     ^^^^^^^^ help: use `crate`: `crate::bar::Bar`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-paths.rs:47:9
+  --> $DIR/edition-lint-paths.rs:46:9
    |
 LL |     use *;
    |         ^ help: use `crate`: `crate::*`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-paths.rs:52:6
+  --> $DIR/edition-lint-paths.rs:51:6
    |
-LL | impl ::foo::SomeTrait for u32 { }
+LL | impl ::foo::SomeTrait for u32 {}
    |      ^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::SomeTrait`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-paths.rs:57:13
+  --> $DIR/edition-lint-paths.rs:56:13
    |
 LL |     let x = ::bar::Bar;
    |             ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: aborting due to 7 previous errors
index c4c9bdf58c3d81374a06b0611ae4421b2df6d6ee..ea832ef3e7d70b52387367238f5eef453ef73303 100644 (file)
@@ -11,7 +11,7 @@ extern crate edition_lint_paths as my_crate;
 
 use crate::my_crate::foo;
 //~^ ERROR absolute paths must start
-//~| WARNING this was previously accepted
+//~| WARNING this is accepted in the current edition
 
 fn main() {
     foo();
index 8f14f2f1fec87dd2b1076f61b9a9553616e91dba..b1f617dd8847844b6f74eb4509ab1b5d2b0efb20 100644 (file)
@@ -11,7 +11,7 @@ extern crate edition_lint_paths as my_crate;
 
 use my_crate::foo;
 //~^ ERROR absolute paths must start
-//~| WARNING this was previously accepted
+//~| WARNING this is accepted in the current edition
 
 fn main() {
     foo();
index 6ea762ed999a07f6ebf8c3fe5a87f28127e3acb3..4bccbc51223f3b5c9ca2fb809d433ff8e920a162 100644 (file)
@@ -9,7 +9,7 @@ note: the lint level is defined here
    |
 LL | #![deny(absolute_paths_not_starting_with_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: aborting due to previous error
index 2a8e24db0bdc559dd1f982cd7e3b59a7b2ac2dcc..9b0b0dd8ee1d43f810691719bb340c9b3da11f37 100644 (file)
@@ -18,7 +18,7 @@ mod m {
 // *could* rewrite it to `use edition_lint_paths::foo`
 use crate::m::edition_lint_paths::foo;
 //~^ ERROR absolute paths must start
-//~| WARNING this was previously accepted
+//~| WARNING this is accepted in the current edition
 
 fn main() {
     foo();
index f3a357917cc7f23c7d1874867bd97a70d3d48e7e..dfce9128c51148494f86cd73af5fc9506ee0f42b 100644 (file)
@@ -18,7 +18,7 @@ mod m {
 // *could* rewrite it to `use edition_lint_paths::foo`
 use m::edition_lint_paths::foo;
 //~^ ERROR absolute paths must start
-//~| WARNING this was previously accepted
+//~| WARNING this is accepted in the current edition
 
 fn main() {
     foo();
index 87a0d492675c7d504437f25ac495711299ddcb06..3c75319aedaedfc320dc904d13bab8f1528ec851 100644 (file)
@@ -9,7 +9,7 @@ note: the lint level is defined here
    |
 LL | #![deny(absolute_paths_not_starting_with_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: aborting due to previous error
index 13f6f8e28291df6f1b006fece83f0373e6f142a0..985348665c9081c7fc6390d3d3d66148d32701b1 100644 (file)
@@ -6,10 +6,10 @@
 fn main() {
     r#try();
     //~^ WARNING `try` is a keyword in the 2018 edition
-    //~| WARNING it will become a hard error in the 2018 edition!
+    //~| WARNING this is accepted in the current edition
 }
 
 fn r#try() {
     //~^ WARNING `try` is a keyword in the 2018 edition
-    //~| WARNING it will become a hard error in the 2018 edition!
+    //~| WARNING this is accepted in the current edition
 }
index bed7118011e9a882bce0f87087356156de8f842f..2c02b75960ec7ec9d8a40f9e5338f2dac3de1aae 100644 (file)
@@ -6,10 +6,10 @@
 fn main() {
     try();
     //~^ WARNING `try` is a keyword in the 2018 edition
-    //~| WARNING it will become a hard error in the 2018 edition!
+    //~| WARNING this is accepted in the current edition
 }
 
 fn try() {
     //~^ WARNING `try` is a keyword in the 2018 edition
-    //~| WARNING it will become a hard error in the 2018 edition!
+    //~| WARNING this is accepted in the current edition
 }
index 2939dc1df705ab97bb83fb3de6ba678776063f1e..3d93b433cf28047340224f3367b0d923272a0100 100644 (file)
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![warn(rust_2018_compatibility)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^
    = note: `#[warn(keyword_idents)]` implied by `#[warn(rust_2018_compatibility)]`
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 warning: `try` is a keyword in the 2018 edition
@@ -19,7 +19,7 @@ warning: `try` is a keyword in the 2018 edition
 LL | fn try() {
    |    ^^^ help: you can use a raw identifier to stay compatible: `r#try`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 warning: 2 warnings emitted
index 5c899378b943fe7690d6181187c57a9353481512..3308870f654c97d1192f9090d3a54e55767120dd 100644 (file)
@@ -11,8 +11,8 @@ fn foo() -> Result<usize, ()> {
     let x: Result<usize, ()> = Ok(22);
     r#try!(x);
     //~^ WARNING `try` is a keyword in the 2018 edition
-    //~| WARNING this was previously accepted
+    //~| WARNING this is accepted in the current edition
     Ok(44)
 }
 
-fn main() { }
+fn main() {}
index db8a198d282cc4ec313944ba3c4586ed4aa15999..69e87a1ff621cc3414f06587e215285b3504224e 100644 (file)
@@ -11,8 +11,8 @@ fn foo() -> Result<usize, ()> {
     let x: Result<usize, ()> = Ok(22);
     try!(x);
     //~^ WARNING `try` is a keyword in the 2018 edition
-    //~| WARNING this was previously accepted
+    //~| WARNING this is accepted in the current edition
     Ok(44)
 }
 
-fn main() { }
+fn main() {}
index cdbb215605e717e461a039d81406fc32ce423932..f315b4d4a9eb9eb274f05926342f6a213c4cb4c9 100644 (file)
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![warn(rust_2018_compatibility)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^
    = note: `#[warn(keyword_idents)]` implied by `#[warn(rust_2018_compatibility)]`
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 warning: 1 warning emitted
diff --git a/src/test/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs b/src/test/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs
new file mode 100644 (file)
index 0000000..eb301e5
--- /dev/null
@@ -0,0 +1,25 @@
+// force-host
+// edition:2018
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+use std::str::FromStr;
+
+#[proc_macro]
+pub fn number_of_tokens_in_a_prefixed_integer_literal(_: TokenStream) -> TokenStream {
+    TokenStream::from_str("hey#123").unwrap().into_iter().count().to_string().parse().unwrap()
+}
+
+#[proc_macro]
+pub fn number_of_tokens_in_a_prefixed_char_literal(_: TokenStream) -> TokenStream {
+    TokenStream::from_str("hey#'a'").unwrap().into_iter().count().to_string().parse().unwrap()
+}
+
+#[proc_macro]
+pub fn number_of_tokens_in_a_prefixed_string_literal(_: TokenStream) -> TokenStream {
+    TokenStream::from_str("hey#\"abc\"").unwrap().into_iter().count().to_string().parse().unwrap()
+}
diff --git a/src/test/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs b/src/test/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs
new file mode 100644 (file)
index 0000000..691bfdc
--- /dev/null
@@ -0,0 +1,25 @@
+// force-host
+// edition:2021
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+use std::str::FromStr;
+
+#[proc_macro]
+pub fn number_of_tokens_in_a_prefixed_integer_literal(_: TokenStream) -> TokenStream {
+    TokenStream::from_str("hey#123").unwrap().into_iter().count().to_string().parse().unwrap()
+}
+
+#[proc_macro]
+pub fn number_of_tokens_in_a_prefixed_char_literal(_: TokenStream) -> TokenStream {
+    TokenStream::from_str("hey#'a'").unwrap().into_iter().count().to_string().parse().unwrap()
+}
+
+#[proc_macro]
+pub fn number_of_tokens_in_a_prefixed_string_literal(_: TokenStream) -> TokenStream {
+    TokenStream::from_str("hey#\"abc\"").unwrap().into_iter().count().to_string().parse().unwrap()
+}
diff --git a/src/test/ui/rust-2021/future-prelude-collision-imported.fixed b/src/test/ui/rust-2021/future-prelude-collision-imported.fixed
new file mode 100644 (file)
index 0000000..c5ff0b4
--- /dev/null
@@ -0,0 +1,59 @@
+// run-rustfix
+// edition:2018
+// check-pass
+#![warn(rust_2021_prelude_collisions)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+mod m {
+    pub trait TryIntoU32 {
+        fn try_into(self) -> Result<u32, ()>;
+    }
+
+    impl TryIntoU32 for u8 {
+        fn try_into(self) -> Result<u32, ()> {
+            Ok(self as u32)
+        }
+    }
+
+    pub trait AnotherTrick {}
+}
+
+mod a {
+    use crate::m::TryIntoU32;
+
+    fn main() {
+        // In this case, we can just use `TryIntoU32`
+        let _: u32 = TryIntoU32::try_into(3u8).unwrap();
+        //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+        //~^^ WARNING this is accepted in the current edition
+    }
+}
+
+mod b {
+    use crate::m::AnotherTrick as TryIntoU32;
+    use crate::m::TryIntoU32 as _;
+
+    fn main() {
+        // In this case, a `TryIntoU32::try_into` rewrite will not work, and we need to use
+        // the path `crate::m::TryIntoU32` (with which it was imported).
+        let _: u32 = crate::m::TryIntoU32::try_into(3u8).unwrap();
+        //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+        //~^^ WARNING this is accepted in the current edition
+    }
+}
+
+mod c {
+    use super::m::TryIntoU32 as _;
+    use crate::m::AnotherTrick as TryIntoU32;
+
+    fn main() {
+        // In this case, a `TryIntoU32::try_into` rewrite will not work, and we need to use
+        // the path `super::m::TryIntoU32` (with which it was imported).
+        let _: u32 = super::m::TryIntoU32::try_into(3u8).unwrap();
+        //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+        //~^^ WARNING this is accepted in the current edition
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2021/future-prelude-collision-imported.rs b/src/test/ui/rust-2021/future-prelude-collision-imported.rs
new file mode 100644 (file)
index 0000000..cd39eec
--- /dev/null
@@ -0,0 +1,59 @@
+// run-rustfix
+// edition:2018
+// check-pass
+#![warn(rust_2021_prelude_collisions)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+mod m {
+    pub trait TryIntoU32 {
+        fn try_into(self) -> Result<u32, ()>;
+    }
+
+    impl TryIntoU32 for u8 {
+        fn try_into(self) -> Result<u32, ()> {
+            Ok(self as u32)
+        }
+    }
+
+    pub trait AnotherTrick {}
+}
+
+mod a {
+    use crate::m::TryIntoU32;
+
+    fn main() {
+        // In this case, we can just use `TryIntoU32`
+        let _: u32 = 3u8.try_into().unwrap();
+        //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+        //~^^ WARNING this is accepted in the current edition
+    }
+}
+
+mod b {
+    use crate::m::AnotherTrick as TryIntoU32;
+    use crate::m::TryIntoU32 as _;
+
+    fn main() {
+        // In this case, a `TryIntoU32::try_into` rewrite will not work, and we need to use
+        // the path `crate::m::TryIntoU32` (with which it was imported).
+        let _: u32 = 3u8.try_into().unwrap();
+        //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+        //~^^ WARNING this is accepted in the current edition
+    }
+}
+
+mod c {
+    use super::m::TryIntoU32 as _;
+    use crate::m::AnotherTrick as TryIntoU32;
+
+    fn main() {
+        // In this case, a `TryIntoU32::try_into` rewrite will not work, and we need to use
+        // the path `super::m::TryIntoU32` (with which it was imported).
+        let _: u32 = 3u8.try_into().unwrap();
+        //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+        //~^^ WARNING this is accepted in the current edition
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2021/future-prelude-collision-imported.stderr b/src/test/ui/rust-2021/future-prelude-collision-imported.stderr
new file mode 100644 (file)
index 0000000..6197587
--- /dev/null
@@ -0,0 +1,34 @@
+warning: trait method `try_into` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision-imported.rs:27:22
+   |
+LL |         let _: u32 = 3u8.try_into().unwrap();
+   |                      ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(3u8)`
+   |
+note: the lint level is defined here
+  --> $DIR/future-prelude-collision-imported.rs:4:9
+   |
+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>
+
+warning: trait method `try_into` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision-imported.rs:40:22
+   |
+LL |         let _: u32 = 3u8.try_into().unwrap();
+   |                      ^^^^^^^^^^^^^^ help: disambiguate the associated function: `crate::m::TryIntoU32::try_into(3u8)`
+   |
+   = 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>
+
+warning: trait method `try_into` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision-imported.rs:53:22
+   |
+LL |         let _: u32 = 3u8.try_into().unwrap();
+   |                      ^^^^^^^^^^^^^^ help: disambiguate the associated function: `super::m::TryIntoU32::try_into(3u8)`
+   |
+   = 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>
+
+warning: 3 warnings emitted
+
diff --git a/src/test/ui/rust-2021/future-prelude-collision-shadow.rs b/src/test/ui/rust-2021/future-prelude-collision-shadow.rs
new file mode 100644 (file)
index 0000000..27891a8
--- /dev/null
@@ -0,0 +1,32 @@
+// edition:2018
+#![warn(rust_2021_prelude_collisions)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+mod m {
+    pub trait TryIntoU32 {
+        fn try_into(self) -> Result<u32, ()>;
+    }
+
+    impl TryIntoU32 for u8 {
+        fn try_into(self) -> Result<u32, ()> {
+            Ok(self as u32)
+        }
+    }
+
+    pub trait AnotherTrick {}
+}
+
+mod d {
+    use crate::m::AnotherTrick as TryIntoU32;
+    use crate::m::*;
+
+    fn main() {
+        // Here, `TryIntoU32` is imported but shadowed, but in that case we don't permit its methods
+        // to be available.
+        let _: u32 = 3u8.try_into().unwrap();
+        //~^ ERROR no method named `try_into` found for type `u8` in the current scope
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr b/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr
new file mode 100644 (file)
index 0000000..ad9b8af
--- /dev/null
@@ -0,0 +1,40 @@
+error[E0599]: no method named `try_into` found for type `u8` in the current scope
+  --> $DIR/future-prelude-collision-shadow.rs:27:26
+   |
+LL |         let _: u32 = 3u8.try_into().unwrap();
+   |                          ^^^^^^^^ method not found in `u8`
+   | 
+  ::: $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn try_into(self) -> Result<T, Self::Error>;
+   |        --------
+   |        |
+   |        the method is available for `Box<u8>` here
+   |        the method is available for `Pin<u8>` here
+   |        the method is available for `Arc<u8>` here
+   |        the method is available for `Rc<u8>` here
+   |
+   = help: items from traits can only be used if the trait is in scope
+   = note: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
+           candidate #1: `use crate::m::TryIntoU32;`
+           candidate #2: `use std::convert::TryInto;`
+help: consider wrapping the receiver expression with the appropriate type
+   |
+LL |         let _: u32 = Box::new(3u8).try_into().unwrap();
+   |                      ^^^^^^^^^   ^
+help: consider wrapping the receiver expression with the appropriate type
+   |
+LL |         let _: u32 = Pin::new(3u8).try_into().unwrap();
+   |                      ^^^^^^^^^   ^
+help: consider wrapping the receiver expression with the appropriate type
+   |
+LL |         let _: u32 = Arc::new(3u8).try_into().unwrap();
+   |                      ^^^^^^^^^   ^
+help: consider wrapping the receiver expression with the appropriate type
+   |
+LL |         let _: u32 = Rc::new(3u8).try_into().unwrap();
+   |                      ^^^^^^^^   ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/rust-2021/future-prelude-collision-unneeded.rs b/src/test/ui/rust-2021/future-prelude-collision-unneeded.rs
new file mode 100644 (file)
index 0000000..247d588
--- /dev/null
@@ -0,0 +1,60 @@
+// edition:2018
+// check-pass
+#![allow(unused)]
+#![deny(rust_2021_prelude_collisions)]
+
+struct S;
+
+impl 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!()
+    }
+}
+
+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);
+}
diff --git a/src/test/ui/rust-2021/future-prelude-collision.fixed b/src/test/ui/rust-2021/future-prelude-collision.fixed
new file mode 100644 (file)
index 0000000..43b0ec1
--- /dev/null
@@ -0,0 +1,98 @@
+// run-rustfix
+// edition:2018
+// check-pass
+#![warn(rust_2021_prelude_collisions)]
+
+trait TryIntoU32 {
+    fn try_into(self) -> Result<u32, ()>;
+}
+
+impl TryIntoU32 for u8 {
+    fn try_into(self) -> Result<u32, ()> {
+        Ok(self as u32)
+    }
+}
+
+// needed for autoref test
+impl TryIntoU32 for &f32 {
+    fn try_into(self) -> Result<u32, ()> {
+        Ok(*self as u32)
+    }
+}
+
+trait TryFromU8: Sized {
+    fn try_from(x: u8) -> Result<Self, ()>;
+}
+
+impl TryFromU8 for u32 {
+    fn try_from(x: u8) -> Result<Self, ()> {
+        Ok(x as u32)
+    }
+}
+
+impl TryIntoU32 for *const u16 {
+    fn try_into(self) -> Result<u32, ()> {
+        Ok(unsafe { *self } as u32)
+    }
+}
+
+trait FromByteIterator {
+    fn from_iter<T>(iter: T) -> Self
+    where
+        T: Iterator<Item = u8>;
+}
+
+impl FromByteIterator for Vec<u8> {
+    fn from_iter<T>(iter: T) -> Self
+    where
+        T: Iterator<Item = u8>,
+    {
+        iter.collect()
+    }
+}
+
+fn main() {
+    // test dot-call that will break in 2021 edition
+    let _: u32 = TryIntoU32::try_into(3u8).unwrap();
+    //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+
+    // test associated function call that will break in 2021 edition
+    let _ = <u32 as TryFromU8>::try_from(3u8).unwrap();
+    //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+
+    // test reverse turbofish too
+    let _ = <Vec<u8> as FromByteIterator>::from_iter(vec![1u8, 2, 3, 4, 5, 6].into_iter());
+    //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+
+    // negative testing lint (this line should *not* emit a warning)
+    let _: u32 = TryFromU8::try_from(3u8).unwrap();
+
+    // test type omission
+    let _: u32 = <_ as TryFromU8>::try_from(3u8).unwrap();
+    //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+
+    // test autoderef
+    let _: u32 = TryIntoU32::try_into(*(&3u8)).unwrap();
+    //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+
+    // test autoref
+    let _: u32 = TryIntoU32::try_into(&3.0).unwrap();
+    //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+
+    let mut data = 3u16;
+    let mut_ptr = std::ptr::addr_of_mut!(data);
+    let _: u32 = TryIntoU32::try_into(mut_ptr as *const _).unwrap();
+    //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+
+    type U32Alias = u32;
+    let _ = <U32Alias as TryFromU8>::try_from(3u8).unwrap();
+    //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+}
diff --git a/src/test/ui/rust-2021/future-prelude-collision.rs b/src/test/ui/rust-2021/future-prelude-collision.rs
new file mode 100644 (file)
index 0000000..4c7a47f
--- /dev/null
@@ -0,0 +1,98 @@
+// run-rustfix
+// edition:2018
+// check-pass
+#![warn(rust_2021_prelude_collisions)]
+
+trait TryIntoU32 {
+    fn try_into(self) -> Result<u32, ()>;
+}
+
+impl TryIntoU32 for u8 {
+    fn try_into(self) -> Result<u32, ()> {
+        Ok(self as u32)
+    }
+}
+
+// needed for autoref test
+impl TryIntoU32 for &f32 {
+    fn try_into(self) -> Result<u32, ()> {
+        Ok(*self as u32)
+    }
+}
+
+trait TryFromU8: Sized {
+    fn try_from(x: u8) -> Result<Self, ()>;
+}
+
+impl TryFromU8 for u32 {
+    fn try_from(x: u8) -> Result<Self, ()> {
+        Ok(x as u32)
+    }
+}
+
+impl TryIntoU32 for *const u16 {
+    fn try_into(self) -> Result<u32, ()> {
+        Ok(unsafe { *self } as u32)
+    }
+}
+
+trait FromByteIterator {
+    fn from_iter<T>(iter: T) -> Self
+    where
+        T: Iterator<Item = u8>;
+}
+
+impl FromByteIterator for Vec<u8> {
+    fn from_iter<T>(iter: T) -> Self
+    where
+        T: Iterator<Item = u8>,
+    {
+        iter.collect()
+    }
+}
+
+fn main() {
+    // test dot-call that will break in 2021 edition
+    let _: u32 = 3u8.try_into().unwrap();
+    //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+
+    // test associated function call that will break in 2021 edition
+    let _ = u32::try_from(3u8).unwrap();
+    //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+
+    // test reverse turbofish too
+    let _ = <Vec<u8>>::from_iter(vec![1u8, 2, 3, 4, 5, 6].into_iter());
+    //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+
+    // negative testing lint (this line should *not* emit a warning)
+    let _: u32 = TryFromU8::try_from(3u8).unwrap();
+
+    // test type omission
+    let _: u32 = <_>::try_from(3u8).unwrap();
+    //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+
+    // test autoderef
+    let _: u32 = (&3u8).try_into().unwrap();
+    //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+
+    // test autoref
+    let _: u32 = 3.0.try_into().unwrap();
+    //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+
+    let mut data = 3u16;
+    let mut_ptr = std::ptr::addr_of_mut!(data);
+    let _: u32 = mut_ptr.try_into().unwrap();
+    //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+
+    type U32Alias = u32;
+    let _ = U32Alias::try_from(3u8).unwrap();
+    //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+}
diff --git a/src/test/ui/rust-2021/future-prelude-collision.stderr b/src/test/ui/rust-2021/future-prelude-collision.stderr
new file mode 100644 (file)
index 0000000..03b89da
--- /dev/null
@@ -0,0 +1,79 @@
+warning: trait method `try_into` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision.rs:56:18
+   |
+LL |     let _: u32 = 3u8.try_into().unwrap();
+   |                  ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(3u8)`
+   |
+note: the lint level is defined here
+  --> $DIR/future-prelude-collision.rs:4:9
+   |
+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>
+
+warning: trait-associated function `try_from` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision.rs:61:13
+   |
+LL |     let _ = u32::try_from(3u8).unwrap();
+   |             ^^^^^^^^^^^^^ help: disambiguate the associated function: `<u32 as TryFromU8>::try_from`
+   |
+   = 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>
+
+warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision.rs:66:13
+   |
+LL |     let _ = <Vec<u8>>::from_iter(vec![1u8, 2, 3, 4, 5, 6].into_iter());
+   |             ^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Vec<u8> as FromByteIterator>::from_iter`
+   |
+   = 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>
+
+warning: trait-associated function `try_from` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision.rs:74:18
+   |
+LL |     let _: u32 = <_>::try_from(3u8).unwrap();
+   |                  ^^^^^^^^^^^^^ help: disambiguate the associated function: `<_ as TryFromU8>::try_from`
+   |
+   = 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>
+
+warning: trait method `try_into` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision.rs:79:18
+   |
+LL |     let _: u32 = (&3u8).try_into().unwrap();
+   |                  ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(*(&3u8))`
+   |
+   = 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>
+
+warning: trait method `try_into` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision.rs:84:18
+   |
+LL |     let _: u32 = 3.0.try_into().unwrap();
+   |                  ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(&3.0)`
+   |
+   = 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>
+
+warning: trait method `try_into` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision.rs:90:18
+   |
+LL |     let _: u32 = mut_ptr.try_into().unwrap();
+   |                  ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(mut_ptr as *const _)`
+   |
+   = 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>
+
+warning: trait-associated function `try_from` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision.rs:95:13
+   |
+LL |     let _ = U32Alias::try_from(3u8).unwrap();
+   |             ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<U32Alias as TryFromU8>::try_from`
+   |
+   = 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>
+
+warning: 8 warnings emitted
+
diff --git a/src/test/ui/rust-2021/generic-type-collision.fixed b/src/test/ui/rust-2021/generic-type-collision.fixed
new file mode 100644 (file)
index 0000000..feba7d1
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+// run-rustfix
+// edition 2018
+#![warn(rust_2021_prelude_collisions)]
+
+trait MyTrait<A> {
+    fn from_iter(x: Option<A>);
+}
+
+impl<T> MyTrait<()> for Vec<T> {
+    fn from_iter(_: Option<()>) {}
+}
+
+fn main() {
+    <Vec<i32> as MyTrait<_>>::from_iter(None);
+    //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+}
diff --git a/src/test/ui/rust-2021/generic-type-collision.rs b/src/test/ui/rust-2021/generic-type-collision.rs
new file mode 100644 (file)
index 0000000..335e7e5
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+// run-rustfix
+// edition 2018
+#![warn(rust_2021_prelude_collisions)]
+
+trait MyTrait<A> {
+    fn from_iter(x: Option<A>);
+}
+
+impl<T> MyTrait<()> for Vec<T> {
+    fn from_iter(_: Option<()>) {}
+}
+
+fn main() {
+    <Vec<i32>>::from_iter(None);
+    //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
+    //~^^ WARNING this is accepted in the current edition
+}
diff --git a/src/test/ui/rust-2021/generic-type-collision.stderr b/src/test/ui/rust-2021/generic-type-collision.stderr
new file mode 100644 (file)
index 0000000..d499920
--- /dev/null
@@ -0,0 +1,16 @@
+warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
+  --> $DIR/generic-type-collision.rs:15:5
+   |
+LL |     <Vec<i32>>::from_iter(None);
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Vec<i32> as MyTrait<_>>::from_iter`
+   |
+note: the lint level is defined here
+  --> $DIR/generic-type-collision.rs:4:9
+   |
+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>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/rust-2021/inherent-dyn-collision.fixed b/src/test/ui/rust-2021/inherent-dyn-collision.fixed
new file mode 100644 (file)
index 0000000..5789a90
--- /dev/null
@@ -0,0 +1,53 @@
+// Test case where the method we want is an inherent method on a
+// dyn Trait. In that case, the fix is to insert `*` on the receiver.
+//
+// check-pass
+// run-rustfix
+// edition:2018
+
+#![warn(rust_2021_prelude_collisions)]
+
+trait TryIntoU32 {
+    fn try_into(&self) -> Result<u32, ()>;
+}
+
+impl TryIntoU32 for u8 {
+    // note: &self
+    fn try_into(&self) -> Result<u32, ()> {
+        Ok(22)
+    }
+}
+
+mod inner {
+    use super::get_dyn_trait;
+
+    // note: this does nothing, but is copying from ffishim's problem of
+    // having a struct of the same name as the trait in-scope, while *also*
+    // implementing the trait for that struct but **without** importing the
+    // trait itself into scope
+    struct TryIntoU32;
+
+    impl super::TryIntoU32 for TryIntoU32 {
+        fn try_into(&self) -> Result<u32, ()> {
+            Ok(0)
+        }
+    }
+
+    // this is where the gross part happens. since `get_dyn_trait` returns
+    // a Box<dyn Trait>, it can still call the method for `dyn Trait` without
+    // `Trait` being in-scope. it might even be possible to make the trait itself
+    // entirely unreference-able from the callsite?
+    pub fn test() -> u32 {
+        (&*get_dyn_trait()).try_into().unwrap()
+        //~^ WARNING trait method `try_into` will become ambiguous
+        //~| WARNING this is accepted in the current edition
+    }
+}
+
+fn get_dyn_trait() -> Box<dyn TryIntoU32> {
+    Box::new(3u8) as Box<dyn TryIntoU32>
+}
+
+fn main() {
+    dbg!(inner::test());
+}
diff --git a/src/test/ui/rust-2021/inherent-dyn-collision.rs b/src/test/ui/rust-2021/inherent-dyn-collision.rs
new file mode 100644 (file)
index 0000000..a3893c0
--- /dev/null
@@ -0,0 +1,53 @@
+// Test case where the method we want is an inherent method on a
+// dyn Trait. In that case, the fix is to insert `*` on the receiver.
+//
+// check-pass
+// run-rustfix
+// edition:2018
+
+#![warn(rust_2021_prelude_collisions)]
+
+trait TryIntoU32 {
+    fn try_into(&self) -> Result<u32, ()>;
+}
+
+impl TryIntoU32 for u8 {
+    // note: &self
+    fn try_into(&self) -> Result<u32, ()> {
+        Ok(22)
+    }
+}
+
+mod inner {
+    use super::get_dyn_trait;
+
+    // note: this does nothing, but is copying from ffishim's problem of
+    // having a struct of the same name as the trait in-scope, while *also*
+    // implementing the trait for that struct but **without** importing the
+    // trait itself into scope
+    struct TryIntoU32;
+
+    impl super::TryIntoU32 for TryIntoU32 {
+        fn try_into(&self) -> Result<u32, ()> {
+            Ok(0)
+        }
+    }
+
+    // this is where the gross part happens. since `get_dyn_trait` returns
+    // a Box<dyn Trait>, it can still call the method for `dyn Trait` without
+    // `Trait` being in-scope. it might even be possible to make the trait itself
+    // entirely unreference-able from the callsite?
+    pub fn test() -> u32 {
+        get_dyn_trait().try_into().unwrap()
+        //~^ WARNING trait method `try_into` will become ambiguous
+        //~| WARNING this is accepted in the current edition
+    }
+}
+
+fn get_dyn_trait() -> Box<dyn TryIntoU32> {
+    Box::new(3u8) as Box<dyn TryIntoU32>
+}
+
+fn main() {
+    dbg!(inner::test());
+}
diff --git a/src/test/ui/rust-2021/inherent-dyn-collision.stderr b/src/test/ui/rust-2021/inherent-dyn-collision.stderr
new file mode 100644 (file)
index 0000000..605f9ce
--- /dev/null
@@ -0,0 +1,16 @@
+warning: trait method `try_into` will become ambiguous in Rust 2021
+  --> $DIR/inherent-dyn-collision.rs:41:9
+   |
+LL |         get_dyn_trait().try_into().unwrap()
+   |         ^^^^^^^^^^^^^^^ help: disambiguate the method call: `(&*get_dyn_trait())`
+   |
+note: the lint level is defined here
+  --> $DIR/inherent-dyn-collision.rs:8:9
+   |
+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>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/rust-2021/inherent-method-collision.rs b/src/test/ui/rust-2021/inherent-method-collision.rs
new file mode 100644 (file)
index 0000000..5071052
--- /dev/null
@@ -0,0 +1,15 @@
+// Test that we do NOT warn for inherent methods invoked via `T::` form.
+//
+// check-pass
+
+#![deny(rust_2021_prelude_collisions)]
+
+pub struct MySeq {}
+
+impl MySeq {
+    pub fn from_iter(_: impl IntoIterator<Item = u32>) {}
+}
+
+fn main() {
+    MySeq::from_iter(Some(22));
+}
diff --git a/src/test/ui/rust-2021/reserved-prefixes-migration.fixed b/src/test/ui/rust-2021/reserved-prefixes-migration.fixed
new file mode 100644 (file)
index 0000000..e026f01
--- /dev/null
@@ -0,0 +1,38 @@
+// check-pass
+// run-rustfix
+// compile-flags: -Z unstable-options --edition 2018
+
+#![warn(rust_2021_prefixes_incompatible_syntax)]
+
+macro_rules! m2 {
+    ($a:tt $b:tt) => {};
+}
+
+macro_rules! m3 {
+    ($a:tt $b:tt $c:tt) => {};
+}
+
+fn main() {
+    m2!(z "hey");
+    //~^ WARNING prefix `z` is unknown [rust_2021_prefixes_incompatible_syntax]
+    //~| WARNING hard error in Rust 2021
+    m2!(prefix "hey");
+    //~^ WARNING prefix `prefix` is unknown [rust_2021_prefixes_incompatible_syntax]
+    //~| WARNING hard error in Rust 2021
+    m3!(hey #123);
+    //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax]
+    //~| WARNING hard error in Rust 2021
+    m3!(hey #hey);
+    //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax]
+    //~| WARNING hard error in Rust 2021
+}
+
+macro_rules! quote {
+    (# name = # kind # value) => {};
+}
+
+quote! {
+    #name = #kind #value
+    //~^ WARNING prefix `kind` is unknown [rust_2021_prefixes_incompatible_syntax]
+    //~| WARNING hard error in Rust 2021
+}
diff --git a/src/test/ui/rust-2021/reserved-prefixes-migration.rs b/src/test/ui/rust-2021/reserved-prefixes-migration.rs
new file mode 100644 (file)
index 0000000..d24f296
--- /dev/null
@@ -0,0 +1,38 @@
+// check-pass
+// run-rustfix
+// compile-flags: -Z unstable-options --edition 2018
+
+#![warn(rust_2021_prefixes_incompatible_syntax)]
+
+macro_rules! m2 {
+    ($a:tt $b:tt) => {};
+}
+
+macro_rules! m3 {
+    ($a:tt $b:tt $c:tt) => {};
+}
+
+fn main() {
+    m2!(z"hey");
+    //~^ WARNING prefix `z` is unknown [rust_2021_prefixes_incompatible_syntax]
+    //~| WARNING hard error in Rust 2021
+    m2!(prefix"hey");
+    //~^ WARNING prefix `prefix` is unknown [rust_2021_prefixes_incompatible_syntax]
+    //~| WARNING hard error in Rust 2021
+    m3!(hey#123);
+    //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax]
+    //~| WARNING hard error in Rust 2021
+    m3!(hey#hey);
+    //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax]
+    //~| WARNING hard error in Rust 2021
+}
+
+macro_rules! quote {
+    (# name = # kind # value) => {};
+}
+
+quote! {
+    #name = #kind#value
+    //~^ WARNING prefix `kind` is unknown [rust_2021_prefixes_incompatible_syntax]
+    //~| WARNING hard error in Rust 2021
+}
diff --git a/src/test/ui/rust-2021/reserved-prefixes-migration.stderr b/src/test/ui/rust-2021/reserved-prefixes-migration.stderr
new file mode 100644 (file)
index 0000000..95105f9
--- /dev/null
@@ -0,0 +1,72 @@
+warning: prefix `z` is unknown
+  --> $DIR/reserved-prefixes-migration.rs:16:9
+   |
+LL |     m2!(z"hey");
+   |         ^ unknown prefix
+   |
+note: the lint level is defined here
+  --> $DIR/reserved-prefixes-migration.rs:5:9
+   |
+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
+   |
+LL |     m2!(z "hey");
+   |          --
+
+warning: prefix `prefix` is unknown
+  --> $DIR/reserved-prefixes-migration.rs:19:9
+   |
+LL |     m2!(prefix"hey");
+   |         ^^^^^^ unknown prefix
+   |
+   = 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
+   |
+LL |     m2!(prefix "hey");
+   |               --
+
+warning: prefix `hey` is unknown
+  --> $DIR/reserved-prefixes-migration.rs:22:9
+   |
+LL |     m3!(hey#123);
+   |         ^^^ unknown prefix
+   |
+   = 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
+   |
+LL |     m3!(hey #123);
+   |            --
+
+warning: prefix `hey` is unknown
+  --> $DIR/reserved-prefixes-migration.rs:25:9
+   |
+LL |     m3!(hey#hey);
+   |         ^^^ unknown prefix
+   |
+   = 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
+   |
+LL |     m3!(hey #hey);
+   |            --
+
+warning: prefix `kind` is unknown
+  --> $DIR/reserved-prefixes-migration.rs:35:14
+   |
+LL |     #name = #kind#value
+   |              ^^^^ unknown prefix
+   |
+   = 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
+   |
+LL |     #name = #kind #value
+   |                  --
+
+warning: 5 warnings emitted
+
diff --git a/src/test/ui/rust-2021/reserved-prefixes-via-macro-2.rs b/src/test/ui/rust-2021/reserved-prefixes-via-macro-2.rs
new file mode 100644 (file)
index 0000000..74f2066
--- /dev/null
@@ -0,0 +1,21 @@
+// edition:2018
+// aux-build:reserved-prefixes-macro-2018.rs
+// aux-build:reserved-prefixes-macro-2021.rs
+
+extern crate reserved_prefixes_macro_2018 as m2018;
+extern crate reserved_prefixes_macro_2021 as m2021;
+
+fn main() {
+    // Ok:
+    m2018::number_of_tokens_in_a_prefixed_integer_literal!();
+    m2018::number_of_tokens_in_a_prefixed_char_literal!();
+    m2018::number_of_tokens_in_a_prefixed_string_literal!();
+
+    // Error, even though *this* crate is 2018:
+    m2021::number_of_tokens_in_a_prefixed_integer_literal!();
+    //~^ ERROR prefix `hey` is unknown
+    m2021::number_of_tokens_in_a_prefixed_char_literal!();
+    //~^ ERROR prefix `hey` is unknown
+    m2021::number_of_tokens_in_a_prefixed_string_literal!();
+    //~^ ERROR prefix `hey` is unknown
+}
diff --git a/src/test/ui/rust-2021/reserved-prefixes-via-macro-2.stderr b/src/test/ui/rust-2021/reserved-prefixes-via-macro-2.stderr
new file mode 100644 (file)
index 0000000..9d7ca57
--- /dev/null
@@ -0,0 +1,29 @@
+error: prefix `hey` is unknown
+  --> $DIR/reserved-prefixes-via-macro-2.rs:15:5
+   |
+LL |     m2021::number_of_tokens_in_a_prefixed_integer_literal!();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix
+   |
+   = note: prefixed identifiers and literals are reserved since Rust 2021
+   = note: this error originates in the macro `m2021::number_of_tokens_in_a_prefixed_integer_literal` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: prefix `hey` is unknown
+  --> $DIR/reserved-prefixes-via-macro-2.rs:17:5
+   |
+LL |     m2021::number_of_tokens_in_a_prefixed_char_literal!();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix
+   |
+   = note: prefixed identifiers and literals are reserved since Rust 2021
+   = note: this error originates in the macro `m2021::number_of_tokens_in_a_prefixed_char_literal` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: prefix `hey` is unknown
+  --> $DIR/reserved-prefixes-via-macro-2.rs:19:5
+   |
+LL |     m2021::number_of_tokens_in_a_prefixed_string_literal!();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix
+   |
+   = note: prefixed identifiers and literals are reserved since Rust 2021
+   = note: this error originates in the macro `m2021::number_of_tokens_in_a_prefixed_string_literal` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/rust-2021/reserved-prefixes-via-macro.rs b/src/test/ui/rust-2021/reserved-prefixes-via-macro.rs
new file mode 100644 (file)
index 0000000..110b6d6
--- /dev/null
@@ -0,0 +1,12 @@
+// run-pass
+// edition:2021
+// aux-build:reserved-prefixes-macro-2018.rs
+
+extern crate reserved_prefixes_macro_2018 as m2018;
+
+fn main() {
+    // Ok, even though *this* crate is 2021:
+    assert_eq!(m2018::number_of_tokens_in_a_prefixed_integer_literal!(), 3);
+    assert_eq!(m2018::number_of_tokens_in_a_prefixed_char_literal!(), 3);
+    assert_eq!(m2018::number_of_tokens_in_a_prefixed_string_literal!(), 3);
+}
diff --git a/src/test/ui/rust-2021/reserved-prefixes.rs b/src/test/ui/rust-2021/reserved-prefixes.rs
new file mode 100644 (file)
index 0000000..5882c7d
--- /dev/null
@@ -0,0 +1,36 @@
+// compile-flags: -Z unstable-options --edition 2021
+
+macro_rules! demo2 {
+    ( $a:tt $b:tt ) => { println!("two tokens") };
+}
+
+macro_rules! demo3 {
+    ( $a:tt $b:tt $c:tt ) => { println!("three tokens") };
+}
+
+macro_rules! demo4 {
+    ( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") };
+}
+
+fn main() {
+    demo3!(foo#bar);   //~ ERROR prefix `foo` is unknown
+    demo2!(foo"bar");  //~ ERROR prefix `foo` is unknown
+    demo2!(foo'b');    //~ ERROR prefix `foo` is unknown
+
+    demo2!(foo'b);     //~ ERROR prefix `foo` is unknown
+    demo3!(foo# bar);  //~ ERROR prefix `foo` is unknown
+    demo4!(foo#! bar); //~ ERROR prefix `foo` is unknown
+    demo4!(foo## bar); //~ ERROR prefix `foo` is unknown
+
+    demo4!(foo#bar#);
+    //~^ ERROR prefix `foo` is unknown
+    //~| ERROR prefix `bar` is unknown
+
+    demo3!(foo # bar);
+    demo3!(foo #bar);
+    demo4!(foo!#bar);
+    demo4!(foo ##bar);
+
+    demo3!(r"foo"#bar);
+    demo3!(r#foo#bar);
+}
diff --git a/src/test/ui/rust-2021/reserved-prefixes.stderr b/src/test/ui/rust-2021/reserved-prefixes.stderr
new file mode 100644 (file)
index 0000000..32e1856
--- /dev/null
@@ -0,0 +1,110 @@
+error: prefix `foo` is unknown
+  --> $DIR/reserved-prefixes.rs:16:12
+   |
+LL |     demo3!(foo#bar);
+   |            ^^^ unknown prefix
+   |
+   = note: prefixed identifiers and literals are reserved since Rust 2021
+help: consider inserting whitespace here
+   |
+LL |     demo3!(foo #bar);
+   |               --
+
+error: prefix `foo` is unknown
+  --> $DIR/reserved-prefixes.rs:17:12
+   |
+LL |     demo2!(foo"bar");
+   |            ^^^ unknown prefix
+   |
+   = note: prefixed identifiers and literals are reserved since Rust 2021
+help: consider inserting whitespace here
+   |
+LL |     demo2!(foo "bar");
+   |               --
+
+error: prefix `foo` is unknown
+  --> $DIR/reserved-prefixes.rs:18:12
+   |
+LL |     demo2!(foo'b');
+   |            ^^^ unknown prefix
+   |
+   = note: prefixed identifiers and literals are reserved since Rust 2021
+help: consider inserting whitespace here
+   |
+LL |     demo2!(foo 'b');
+   |               --
+
+error: prefix `foo` is unknown
+  --> $DIR/reserved-prefixes.rs:20:12
+   |
+LL |     demo2!(foo'b);
+   |            ^^^ unknown prefix
+   |
+   = note: prefixed identifiers and literals are reserved since Rust 2021
+help: consider inserting whitespace here
+   |
+LL |     demo2!(foo 'b);
+   |               --
+
+error: prefix `foo` is unknown
+  --> $DIR/reserved-prefixes.rs:21:12
+   |
+LL |     demo3!(foo# bar);
+   |            ^^^ unknown prefix
+   |
+   = note: prefixed identifiers and literals are reserved since Rust 2021
+help: consider inserting whitespace here
+   |
+LL |     demo3!(foo # bar);
+   |               --
+
+error: prefix `foo` is unknown
+  --> $DIR/reserved-prefixes.rs:22:12
+   |
+LL |     demo4!(foo#! bar);
+   |            ^^^ unknown prefix
+   |
+   = note: prefixed identifiers and literals are reserved since Rust 2021
+help: consider inserting whitespace here
+   |
+LL |     demo4!(foo #! bar);
+   |               --
+
+error: prefix `foo` is unknown
+  --> $DIR/reserved-prefixes.rs:23:12
+   |
+LL |     demo4!(foo## bar);
+   |            ^^^ unknown prefix
+   |
+   = note: prefixed identifiers and literals are reserved since Rust 2021
+help: consider inserting whitespace here
+   |
+LL |     demo4!(foo ## bar);
+   |               --
+
+error: prefix `foo` is unknown
+  --> $DIR/reserved-prefixes.rs:25:12
+   |
+LL |     demo4!(foo#bar#);
+   |            ^^^ unknown prefix
+   |
+   = note: prefixed identifiers and literals are reserved since Rust 2021
+help: consider inserting whitespace here
+   |
+LL |     demo4!(foo #bar#);
+   |               --
+
+error: prefix `bar` is unknown
+  --> $DIR/reserved-prefixes.rs:25:16
+   |
+LL |     demo4!(foo#bar#);
+   |                ^^^ unknown prefix
+   |
+   = note: prefixed identifiers and literals are reserved since Rust 2021
+help: consider inserting whitespace here
+   |
+LL |     demo4!(foo#bar #);
+   |                   --
+
+error: aborting due to 9 previous errors
+
index 007d2ae6506d7864a5b276224753059c73d43b32..4738e5116b4274c982fcc92b296670670e692a24 100644 (file)
@@ -1,9 +1,9 @@
-#![crate_type="lib"]
+#![crate_type = "lib"]
 
 pub struct Bar;
 pub trait Foo {
     type X;
-    fn foo() -> Self::X;
+    fn foo(x: u32) -> Self::X;
 }
 
 #[doc(alias = "foo")] //~ ERROR
@@ -19,7 +19,8 @@ impl Bar {
 impl Foo for Bar {
     #[doc(alias = "assoc")] //~ ERROR
     type X = i32;
-    fn foo() -> Self::X {
+    fn foo(#[doc(alias = "qux")] _x: u32) -> Self::X {
+        //~^ ERROR
         0
     }
 }
index a66e9939eaf18060a370627c079d7869d46fce35..2b25882be21f15689cb75975a3e4e777c5a6ff40 100644 (file)
@@ -1,3 +1,9 @@
+error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
+  --> $DIR/check-doc-alias-attr-location.rs:22:12
+   |
+LL |     fn foo(#[doc(alias = "qux")] _x: u32) -> Self::X {
+   |            ^^^^^^^^^^^^^^^^^^^^^
+
 error: `#[doc(alias = "...")]` isn't allowed on extern block
   --> $DIR/check-doc-alias-attr-location.rs:9:7
    |
@@ -22,5 +28,5 @@ error: `#[doc(alias = "...")]` isn't allowed on type alias in implementation blo
 LL |     #[doc(alias = "assoc")]
    |           ^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
index 4c72e7e96842cb8ad6bfae46999eba8eb1cfce68..4518f77ef933dec06e287d9104895f23b62549d2 100644 (file)
@@ -10,3 +10,11 @@ mod foo {
 
 #[doc(keyword = "hall")] //~ ERROR
 fn foo() {}
+
+
+// Regression test for the ICE described in #83512.
+trait Foo {
+    #[doc(keyword = "match")]
+    //~^ ERROR: `#[doc(keyword = "...")]` can only be used on modules
+    fn quux() {}
+}
index 0679bb8c5a7a6f832bf70c587da1d289c67f7102..6ba7034d5412212acfa48d3873a7026d84573b06 100644 (file)
@@ -10,11 +10,17 @@ error: `#[doc(keyword = "...")]` can only be used on modules
 LL | #[doc(keyword = "hall")]
    |       ^^^^^^^^^^^^^^^^
 
+error: `#[doc(keyword = "...")]` can only be used on modules
+  --> $DIR/doc_keyword.rs:17:11
+   |
+LL |     #[doc(keyword = "match")]
+   |           ^^^^^^^^^^^^^^^^^
+
 error: `#![doc(keyword = "...")]` isn't allowed as a crate-level attribute
   --> $DIR/doc_keyword.rs:4:8
    |
 LL | #![doc(keyword = "hello")]
    |        ^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
index f5dd2a40cc4cb8e15d1c152dcf307326344680c0..7a6b9eda3fa123a40675c5a620231ac6eca89abb 100644 (file)
@@ -1,4 +1,5 @@
 // compile-flags: -Z sanitizer=address -C target-feature=+crt-static --target x86_64-unknown-linux-gnu
+// needs-llvm-components: x86
 
 #![feature(no_core)]
 #![no_core]
index 4947f3b3d8b13b883ebab44eb5248518518960ca..bcafc2891fda82893e86abbde549049db8e5c75d 100644 (file)
@@ -1,4 +1,5 @@
 // compile-flags: -Z sanitizer=address -Z sanitizer=memory --target x86_64-unknown-linux-gnu
+// needs-llvm-components: x86
 // error-pattern: error: `-Zsanitizer=address` is incompatible with `-Zsanitizer=memory`
 
 #![feature(no_core)]
index 3fb749815f7c3ba4af3348cd8480887cefb47c14..9f29c76353bac9da0537ae523a9f837443d4853b 100644 (file)
@@ -1,4 +1,5 @@
 // compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu
+// needs-llvm-components: x86
 // error-pattern: error: leak sanitizer is not supported for this target
 #![feature(no_core)]
 #![no_core]
index f2e556c63cbf3774bcfed5881f6b4114a0e844dd..e25c6363515be7d0ff556f1ad0e9af6ad6d96345 100644 (file)
@@ -1,15 +1,15 @@
 error: lifetime may not live long enough
-  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                          -                     ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+   |                          -          ^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
    |                          |
    |                          let's call the lifetime of this reference `'1`
    |
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
-   |                                     ^^^^^^^^^^^^^^^
+   |                                                ^^^^
 
 error: aborting due to previous error
 
index 73766c31b93b60779f52797906257f384c9cd78c..962593e411e92a16aac8f7d1a3f35edaf77268ae 100644 (file)
@@ -9,7 +9,7 @@ LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
-   |                               ^^^^^^^^^^^^^^^
+   |                                          ^^^^
 
 error: aborting due to previous error
 
index 0956f2a56918cdffc065749cfce011d302244220..cc17d8f8e3962e59f2d3782367c7eb6f63603132 100644 (file)
@@ -1,8 +1,8 @@
 struct S;
 
 impl S {
-    fn f(self: _) {} //~ERROR the type placeholder `_` is not allowed within types on item sig
-    fn g(self: &_) {} //~ERROR the type placeholder `_` is not allowed within types on item sig
+    fn f(self: _) {} //~ERROR the type placeholder `_` is not allowed within types on item signatures for functions
+    fn g(self: &_) {} //~ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 }
 
 fn main() {}
index 1475b212b56a6a3b89d20c3e13f28e7f3294bb90..8d70c6287e55ac65cac1d3a2454ee913020d640c 100644 (file)
@@ -1,4 +1,4 @@
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/self-infer.rs:4:16
    |
 LL |     fn f(self: _) {}
@@ -9,7 +9,7 @@ help: use type parameters instead
 LL |     fn f<T>(self: T) {}
    |         ^^^       ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/self-infer.rs:5:17
    |
 LL |     fn g(self: &_) {}
index a7b089ebff4c37c63a9a0bd32aadb019f57f3f2f..88e8614683227117abbb41dac3d7d69e87dc998b 100644 (file)
@@ -3,6 +3,7 @@
 // that we do not glue_drop before we glue_take (#3290).
 
 #![feature(box_syntax)]
+#![allow(dead_code)]
 
 use std::rc::Rc;
 
diff --git a/src/test/ui/simd-intrinsic/issue-85855.rs b/src/test/ui/simd-intrinsic/issue-85855.rs
new file mode 100644 (file)
index 0000000..f276fbd
--- /dev/null
@@ -0,0 +1,19 @@
+// Check that appropriate errors are reported if an intrinsic is defined
+// with the wrong number of generic lifetime/type/const parameters, and
+// that no ICE occurs in these cases.
+
+#![feature(platform_intrinsics)]
+#![crate_type="lib"]
+
+extern "platform-intrinsic" {
+    fn simd_saturating_add<'a, T: 'a>(x: T, y: T);
+    //~^ ERROR: intrinsic has wrong number of lifetime parameters
+
+    fn simd_add<'a, T>(x: T, y: T) -> T;
+
+    fn simd_sub<T, U>(x: T, y: U);
+    //~^ ERROR: intrinsic has wrong number of type parameters
+
+    fn simd_mul<T, const N: usize>(x: T, y: T);
+    //~^ ERROR: intrinsic has wrong number of const parameters
+}
diff --git a/src/test/ui/simd-intrinsic/issue-85855.stderr b/src/test/ui/simd-intrinsic/issue-85855.stderr
new file mode 100644 (file)
index 0000000..fb2f1fb
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expected 0
+  --> $DIR/issue-85855.rs:9:27
+   |
+LL |     fn simd_saturating_add<'a, T: 'a>(x: T, y: T);
+   |                           ^^^^^^^^^^^ expected 0 lifetime parameters
+
+error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1
+  --> $DIR/issue-85855.rs:14:16
+   |
+LL |     fn simd_sub<T, U>(x: T, y: U);
+   |                ^^^^^^ expected 1 type parameter
+
+error[E0094]: intrinsic has wrong number of const parameters: found 1, expected 0
+  --> $DIR/issue-85855.rs:17:16
+   |
+LL |     fn simd_mul<T, const N: usize>(x: T, y: T);
+   |                ^^^^^^^^^^^^^^^^^^^ expected 0 const parameters
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0094`.
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 1d3e33e4b05030c1d45698d4b76938fc8a1b972a..24dfdf8ebc2990b54b7c5f8ca861093b81cf0c4a 100644 (file)
@@ -1,11 +1,14 @@
 error[E0277]: the trait bound `u8: Tr` is not satisfied
   --> $DIR/issue-29595.rs:6:17
    |
-LL |     const C: Self;
-   |     -------------- required by `Tr::C`
-...
 LL |     let a: u8 = Tr::C;
    |                 ^^^^^ the trait `Tr` is not implemented for `u8`
+   |
+note: required by `Tr::C`
+  --> $DIR/issue-29595.rs:2:5
+   |
+LL |     const C: Self;
+   |     ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index b8fb332120a4e4d56a51ba0e6fda2650b8b94034..5b9861da6e8544079bcb506ddc7e683f4d76788e 100644 (file)
@@ -8,7 +8,7 @@ impl S {
 }
 
 fn main() {
-    let _: Result<(), String> = Ok(); //~ ERROR this function takes
+    let _: Result<(), String> = Ok(); //~ ERROR this enum variant takes
     foo(); //~ ERROR this function takes
     foo(()); //~ ERROR this function takes
     bar(); //~ ERROR this function takes
index b15da2cb47955c27462ad3945abc8c4126a1beb9..7a24ffbd81c88d2e6edbd271dcf3e32eafa3b4a8 100644 (file)
@@ -1,4 +1,4 @@
-error[E0061]: this function takes 1 argument but 0 arguments were supplied
+error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:11:33
    |
 LL |     let _: Result<(), String> = Ok();
index f14588e6e023c9aba6bad6125b87f4a1a7e6985a..0f5714e996a17cef78e0dd3c6112882e72c57db3 100644 (file)
@@ -3,7 +3,6 @@
 #![feature(specialization)]
 #![feature(generic_associated_types)]
 //~^^ WARNING `specialization` is incomplete
-//~^^ WARNING the feature `generic_associated_types` is incomplete
 
 trait X {
     type U<'a>: PartialEq<&'a Self> where Self: 'a;
index eb5d80bc4dda68ddb78c32da9453ce55eeb41bad..e646c1640b1c6f28a52bc4bc80aad18442d94b5b 100644 (file)
@@ -8,16 +8,8 @@ LL | #![feature(specialization)]
    = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
    = help: consider using `min_specialization` instead, which is more stable and complete
 
-warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/deafult-generic-associated-type-bound.rs:4:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
-
 error[E0277]: can't compare `T` with `T`
-  --> $DIR/deafult-generic-associated-type-bound.rs:19:5
+  --> $DIR/deafult-generic-associated-type-bound.rs:18:5
    |
 LL |     type U<'a>: PartialEq<&'a Self> where Self: 'a;
    |                 ------------------- required by this bound in `X::U`
@@ -31,6 +23,6 @@ help: consider further restricting this bound
 LL | impl<T: 'static + std::cmp::PartialEq> X for T {
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0277`.
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 569608780def99ee4f066f3a31c38009dc97fa1d..4be1b22fc6b4f4d3b926a4a217f49e198f55a603 100644 (file)
@@ -1,6 +1,9 @@
 error[E0624]: associated function `new` is private
   --> $DIR/static-method-privacy.rs:9:19
    |
+LL |         fn new() -> S { S }
+   |         ------------- private associated function defined here
+...
 LL |     let _ = a::S::new();
    |                   ^^^ private associated function
 
index cea3d5d4df35d0a1a0d15c9fbcdc8e025dcda56b..e0a22c2df1aca529b65b67bcf33bf55ddf09b838 100644 (file)
@@ -1,11 +1,14 @@
 error[E0277]: the trait bound `NoClone: Clone` is not satisfied
   --> $DIR/struct-path-alias-bounds.rs:9:13
    |
-LL | struct S<T: Clone> { a: T }
-   | ------------------ required by `S`
-...
 LL |     let s = A { a: NoClone };
    |             ^ the trait `Clone` is not implemented for `NoClone`
+   |
+note: required by `S`
+  --> $DIR/struct-path-alias-bounds.rs:3:1
+   |
+LL | struct S<T: Clone> { a: T }
+   | ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 2ffb24c6e6c66ad87a1ac38af81a4cf31f45dc80..6f46cfdf02467ffa934dc6d46aaedea1f2534ed2 100644 (file)
@@ -32,20 +32,20 @@ static mut SM2 = "abc";
 
 const C = 42;
 //~^ ERROR missing type for `const` item
-//~| HELP provide a type for the item
+//~| HELP provide a type for the constant
 //~| SUGGESTION C: i32
 
 const D = &&42;
 //~^ ERROR missing type for `const` item
-//~| HELP provide a type for the item
+//~| HELP provide a type for the constant
 //~| SUGGESTION D: &&i32
 
 static S = Vec::<String>::new();
 //~^ ERROR missing type for `static` item
-//~| HELP provide a type for the item
+//~| HELP provide a type for the static variable
 //~| SUGGESTION S: Vec<String>
 
 static mut SM = "abc";
 //~^ ERROR missing type for `static mut` item
-//~| HELP provide a type for the item
+//~| HELP provide a type for the static variable
 //~| SUGGESTION &str
index b180a6a9a9b4e7100313fefb691243876f5faba6..3b0fd6337f1f15df902909f9493cc36f5b4306f9 100644 (file)
@@ -2,25 +2,25 @@ error: missing type for `const` item
   --> $DIR/const-no-type.rs:33:7
    |
 LL | const C = 42;
-   |       ^ help: provide a type for the item: `C: i32`
+   |       ^ help: provide a type for the constant: `C: i32`
 
 error: missing type for `const` item
   --> $DIR/const-no-type.rs:38:7
    |
 LL | const D = &&42;
-   |       ^ help: provide a type for the item: `D: &&i32`
+   |       ^ help: provide a type for the constant: `D: &&i32`
 
 error: missing type for `static` item
   --> $DIR/const-no-type.rs:43:8
    |
 LL | static S = Vec::<String>::new();
-   |        ^ help: provide a type for the item: `S: Vec<String>`
+   |        ^ help: provide a type for the static variable: `S: Vec<String>`
 
 error: missing type for `static mut` item
   --> $DIR/const-no-type.rs:48:12
    |
 LL | static mut SM = "abc";
-   |            ^^ help: provide a type for the item: `SM: &str`
+   |            ^^ help: provide a type for the static variable: `SM: &str`
 
 error: missing type for `const` item
   --> $DIR/const-no-type.rs:14:7
index 3786457fb1ae3ac5fc54a2d2f83cd59ec9e5944f..d5d51324e63c5969594c0e9f163a565461dc1edb 100644 (file)
@@ -47,7 +47,11 @@ LL |     Pin::new(x)
    |     ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send`
    |
    = note: consider using `Box::pin`
-   = note: required by `Pin::<P>::new`
+note: required by `Pin::<P>::new`
+  --> $SRC_DIR/core/src/pin.rs:LL:COL
+   |
+LL |     pub const fn new(pointer: P) -> Pin<P> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
   --> $DIR/expected-boxed-future-isnt-pinned.rs:27:5
@@ -56,7 +60,11 @@ LL |     Pin::new(Box::new(x))
    |     ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send`
    |
    = note: consider using `Box::pin`
-   = note: required by `Pin::<P>::new`
+note: required by `Pin::<P>::new`
+  --> $SRC_DIR/core/src/pin.rs:LL:COL
+   |
+LL |     pub const fn new(pointer: P) -> Pin<P> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/expected-boxed-future-isnt-pinned.rs:31:5
index b5c379ebc6eb94da5e5a716044ca41a269795cf3..d31ed01b1916be31cb3d3fbaedd596581472277e 100644 (file)
@@ -17,11 +17,11 @@ pub struct Qux<T>(T);
 #[dom_struct]
 pub struct Foo {
     //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
     qux: Qux<Qux<Baz>>,
     bar: Box<Bar>,
     //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
 }
 
 fn main() {}
index f8c58b6173477dc7711cfc5489ce7fdc24566862..6282a693855af778e1f86fb0ef67f14a37eb034f 100644 (file)
@@ -9,7 +9,7 @@ note: the lint level is defined here
    |
 LL | #![deny(bare_trait_objects)]
    |         ^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: trait objects without an explicit `dyn` are deprecated
@@ -18,7 +18,7 @@ error: trait objects without an explicit `dyn` are deprecated
 LL | pub struct Foo {
    | ^^^ help: use `dyn`: `dyn pub`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: aborting due to 2 previous errors
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 eb67170d47cdf10c51e145be9582de38803b46d0..fcc49ef59d1294711d6e781e537976d074f83b66 100644 (file)
@@ -5,7 +5,11 @@ LL |     SadGirl {}.call()?;
    |     ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future`
    |
    = help: the trait `Try` is not implemented for `impl Future`
-   = note: required by `branch`
+note: required by `branch`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider `await`ing on the `Future`
    |
 LL |     SadGirl {}.call().await?;
index 49fa94da8592304a44ae8fbc25a62c1220b94067..649517b7d99da6c8cffb3d78e81e8ee8c836df19 100644 (file)
@@ -6,9 +6,12 @@ LL |     let o = Other::new(f);
    |                        |
    |                        expected an implementor of trait `SomeTrait`
    |                        help: consider borrowing here: `&f`
-...
+   |
+note: required by `Other::<'a, G>::new`
+  --> $DIR/issue-84973.rs:27:5
+   |
 LL |     pub fn new(g: G) -> Self {
-   |     ------------------------ required by `Other::<'a, G>::new`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/issue-86667.rs b/src/test/ui/suggestions/issue-86667.rs
new file mode 100644 (file)
index 0000000..6aceb13
--- /dev/null
@@ -0,0 +1,16 @@
+// Regression test for #86667, where a garbled suggestion was issued for
+// a missing named lifetime parameter.
+
+// compile-flags: --edition 2018
+
+async fn a(s1: &str, s2: &str) -> &str {
+//~^ ERROR: missing lifetime specifier [E0106]
+    s1
+}
+
+fn b(s1: &str, s2: &str) -> &str {
+//~^ ERROR: missing lifetime specifier [E0106]
+    s1
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-86667.stderr b/src/test/ui/suggestions/issue-86667.stderr
new file mode 100644 (file)
index 0000000..77f7f87
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-86667.rs:6:35
+   |
+LL | async fn a(s1: &str, s2: &str) -> &str {
+   |                ----      ----     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `s1` or `s2`
+help: consider introducing a named lifetime parameter
+   |
+LL | async fn a<'a>(s1: &'a str, s2: &'a str) -> &'a str {
+   |           ^^^^     ^^^^^^^      ^^^^^^^     ^^^
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-86667.rs:11:29
+   |
+LL | fn b(s1: &str, s2: &str) -> &str {
+   |          ----      ----     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `s1` or `s2`
+help: consider introducing a named lifetime parameter
+   |
+LL | fn b<'a>(s1: &'a str, s2: &'a str) -> &'a str {
+   |     ^^^^     ^^^^^^^      ^^^^^^^     ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
index 2407d13714a2ad555938006713e07684149f71c7..05ba7808600b01131933898a9206009e9f8c3542 100644 (file)
@@ -9,7 +9,7 @@ LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
    |
 LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                          ^^^^
 
 error: lifetime may not live long enough
   --> $DIR/trait-object-nested-in-impl-trait.rs:39:9
@@ -47,7 +47,7 @@ LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound
    |
 LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
-   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                                 ^^^^
 
 error: aborting due to 4 previous errors
 
index 71b09d43612ea5915574615732dd6bc339c4b2b2..4d1b5306bb130120b748809e34ebdd1726fe326a 100644 (file)
@@ -5,7 +5,11 @@ LL |     let fp = BufWriter::new(fp);
    |                             ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
    |
    = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
-   = note: required by `BufWriter::<W>::new`
+note: required by `BufWriter::<W>::new`
+  --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
+   |
+LL |     pub fn new(inner: W) -> BufWriter<W> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
   --> $DIR/mut-borrow-needed-by-trait.rs:17:14
index 797406f869fe6b6b149b6e228a5352638ec64499..f332b7213d8bcc6e5b13b6721308bca4383af306 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Trait` cannot be made into an object
-  --> $DIR/object-unsafe-trait-references-self.rs:6:11
+  --> $DIR/object-unsafe-trait-references-self.rs:6:12
    |
 LL | fn bar(x: &dyn Trait) {}
-   |           ^^^^^^^^^^ `Trait` cannot be made into an object
+   |            ^^^^^^^^^ `Trait` cannot be made into an object
    |
    = help: consider moving `baz` to another trait
    = help: consider moving `bat` to another trait
@@ -17,10 +17,10 @@ LL |     fn bat(&self) -> Self {}
    |                      ^^^^ ...because method `bat` references the `Self` type in its return type
 
 error[E0038]: the trait `Other` cannot be made into an object
-  --> $DIR/object-unsafe-trait-references-self.rs:10:11
+  --> $DIR/object-unsafe-trait-references-self.rs:10:12
    |
 LL | fn foo(x: &dyn Other) {}
-   |           ^^^^^^^^^^ `Other` cannot be made into an object
+   |            ^^^^^^^^^ `Other` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-unsafe-trait-references-self.rs:8:14
index a2caf846cc5febe6a3a4e7ea5650b39a9a54ae1d..4c18f6d79d077d679f92d2b1911c2a84555a0c38 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Trait` cannot be made into an object
-  --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:11
+  --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:12
    |
 LL | fn bar(x: &dyn Trait) {}
-   |           ^^^^^^^^^^ `Trait` cannot be made into an object
+   |            ^^^^^^^^^ `Trait` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-unsafe-trait-should-use-where-sized.rs:5:8
index 80ed1cdedf1e7972b8e58cee1e4626096478572a..25c73c4c8741af5b8ddf32949e18601f80e50bc0 100644 (file)
@@ -6,8 +6,6 @@ LL |     println!("{}", path);
    |
    = help: the trait `std::fmt::Display` is not implemented for `Path`
    = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data
-   = note: required because of the requirements on the impl of `std::fmt::Display` for `&Path`
-   = note: required by `std::fmt::Display::fmt`
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 9b8181647a0c15790715e665241946d0e47f7b5a..e68152d5fc3aa7006495013fd672e89567bf8ea9 100644 (file)
@@ -4,7 +4,11 @@ error[E0277]: the trait bound `&T: std::io::Read` is not satisfied
 LL |         let mut stream_reader = BufReader::new(&stream);
    |                                                ^^^^^^^ the trait `std::io::Read` is not implemented for `&T`
    |
-   = note: required by `BufReader::<R>::new`
+note: required by `BufReader::<R>::new`
+  --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
+   |
+LL |     pub fn new(inner: R) -> BufReader<R> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider removing the leading `&`-reference
    |
 LL |         let mut stream_reader = BufReader::new(stream);
diff --git a/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.rs b/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.rs
new file mode 100644 (file)
index 0000000..1dfc078
--- /dev/null
@@ -0,0 +1,10 @@
+mod option {
+    pub enum O<T> {
+        Some(T),
+        None,
+    }
+}
+
+fn main() {
+    let _: option::O<()> = (); //~ ERROR 9:28: 9:30: mismatched types [E0308]
+}
diff --git a/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr b/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr
new file mode 100644 (file)
index 0000000..22a0ce1
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/suggest-full-enum-variant-for-local-module.rs:9:28
+   |
+LL |     let _: option::O<()> = ();
+   |            -------------   ^^
+   |            |               |
+   |            |               expected enum `O`, found `()`
+   |            |               help: try using a variant of the expected enum: `option::O::Some(())`
+   |            expected due to this
+   |
+   = note:   expected enum `O<()>`
+           found unit type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
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; },
index 4aa0ad219cf25fc1c26e03255af628b6f9fdb4c3..a5c01484d424c5e2829a6c3ceeeb543e66dfd895 100644 (file)
@@ -9,7 +9,11 @@ LL |     for (i, _) in &v.iter().enumerate() {
    |
    = help: the trait `Iterator` is not implemented for `&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required because of the requirements on the impl of `IntoIterator` for `&Enumerate<std::slice::Iter<'_, {integer}>>`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 15c4b7fcb8b3b089ba3950c18a06c84aec08b08d..b128590f9d0e75de0daaf3a1e082b814ae8bd85a 100644 (file)
@@ -9,7 +9,11 @@ LL |     for (i, _) in & & & & &v.iter().enumerate() {
    |
    = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 0bd6d956aff97196e00bb9d17151f98feeba0814..1c32a33e3712fb3a61e488ba175cfc8be7ae369d 100644 (file)
@@ -13,7 +13,11 @@ LL | |          .enumerate() {
    |
    = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
-   = note: required by `into_iter`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
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`.
diff --git a/src/test/ui/suggestions/unnamable-types.rs b/src/test/ui/suggestions/unnamable-types.rs
new file mode 100644 (file)
index 0000000..483f9bb
--- /dev/null
@@ -0,0 +1,39 @@
+// Test that we do not suggest to add type annotations for unnamable types.
+
+#![crate_type="lib"]
+#![feature(generators)]
+
+const A = 5;
+//~^ ERROR: missing type for `const` item
+//~| HELP: provide a type for the constant
+
+static B: _ = "abc";
+//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for static variables
+//~| NOTE: not allowed in type signatures
+//~| HELP: replace with the correct type
+
+
+// FIXME: this should also suggest a function pointer, as the closure is non-capturing
+const C: _ = || 42;
+//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for constants
+//~| NOTE: not allowed in type signatures
+//~| NOTE: however, the inferred type
+
+struct S<T> { t: T }
+const D = S { t: { let i = 0; move || -> i32 { i } } };
+//~^ ERROR: missing type for `const` item
+//~| NOTE: however, the inferred type
+
+
+fn foo() -> i32 { 42 }
+const E = foo;
+//~^ ERROR: missing type for `const` item
+//~| HELP: provide a type for the constant
+const F = S { t: foo };
+//~^ ERROR: missing type for `const` item
+//~| HELP: provide a type for the constant
+
+
+const G = || -> i32 { yield 0; return 1; };
+//~^ ERROR: missing type for `const` item
+//~| NOTE: however, the inferred type
diff --git a/src/test/ui/suggestions/unnamable-types.stderr b/src/test/ui/suggestions/unnamable-types.stderr
new file mode 100644 (file)
index 0000000..3a489a6
--- /dev/null
@@ -0,0 +1,66 @@
+error: missing type for `const` item
+  --> $DIR/unnamable-types.rs:6:7
+   |
+LL | const A = 5;
+   |       ^ help: provide a type for the constant: `A: i32`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
+  --> $DIR/unnamable-types.rs:10:11
+   |
+LL | static B: _ = "abc";
+   |           ^
+   |           |
+   |           not allowed in type signatures
+   |           help: replace with the correct type: `&str`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/unnamable-types.rs:17:10
+   |
+LL | const C: _ = || 42;
+   |          ^ not allowed in type signatures
+   |
+note: however, the inferred type `[closure@$DIR/unnamable-types.rs:17:14: 17:19]` cannot be named
+  --> $DIR/unnamable-types.rs:17:14
+   |
+LL | const C: _ = || 42;
+   |              ^^^^^
+
+error: missing type for `const` item
+  --> $DIR/unnamable-types.rs:23:7
+   |
+LL | const D = S { t: { let i = 0; move || -> i32 { i } } };
+   |       ^
+   |
+note: however, the inferred type `S<[closure@$DIR/unnamable-types.rs:23:31: 23:51]>` cannot be named
+  --> $DIR/unnamable-types.rs:23:11
+   |
+LL | const D = S { t: { let i = 0; move || -> i32 { i } } };
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing type for `const` item
+  --> $DIR/unnamable-types.rs:29:7
+   |
+LL | const E = foo;
+   |       ^ help: provide a type for the constant: `E: fn() -> i32`
+
+error: missing type for `const` item
+  --> $DIR/unnamable-types.rs:32:7
+   |
+LL | const F = S { t: foo };
+   |       ^ help: provide a type for the constant: `F: S<fn() -> i32>`
+
+error: missing type for `const` item
+  --> $DIR/unnamable-types.rs:37:7
+   |
+LL | const G = || -> i32 { yield 0; return 1; };
+   |       ^
+   |
+note: however, the inferred type `[generator@$DIR/unnamable-types.rs:37:11: 37:43]` cannot be named
+  --> $DIR/unnamable-types.rs:37:11
+   |
+LL | const G = || -> i32 { yield 0; return 1; };
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/suggestions/use-placement-resolve.fixed b/src/test/ui/suggestions/use-placement-resolve.fixed
new file mode 100644 (file)
index 0000000..afe74cf
--- /dev/null
@@ -0,0 +1,13 @@
+// compile-flags: --test
+// run-rustfix
+// Checks that the `use` suggestion appears *below* this inner attribute.
+// There was an issue where the test synthetic #[allow(dead)] attribute on
+// main which has a dummy span caused the suggestion to be placed at the top
+// of the file.
+#![allow(unused)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+fn foobar<T: Debug>(x: T) {} //~ ERROR expected trait, found derive macro
diff --git a/src/test/ui/suggestions/use-placement-resolve.rs b/src/test/ui/suggestions/use-placement-resolve.rs
new file mode 100644 (file)
index 0000000..b30ddb3
--- /dev/null
@@ -0,0 +1,11 @@
+// compile-flags: --test
+// run-rustfix
+// Checks that the `use` suggestion appears *below* this inner attribute.
+// There was an issue where the test synthetic #[allow(dead)] attribute on
+// main which has a dummy span caused the suggestion to be placed at the top
+// of the file.
+#![allow(unused)]
+
+fn main() {}
+
+fn foobar<T: Debug>(x: T) {} //~ ERROR expected trait, found derive macro
diff --git a/src/test/ui/suggestions/use-placement-resolve.stderr b/src/test/ui/suggestions/use-placement-resolve.stderr
new file mode 100644 (file)
index 0000000..9da9e8e
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0404]: expected trait, found derive macro `Debug`
+  --> $DIR/use-placement-resolve.rs:11:14
+   |
+LL | fn foobar<T: Debug>(x: T) {}
+   |              ^^^^^ not a trait
+   |
+help: consider importing this trait instead
+   |
+LL | use std::fmt::Debug;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/suggestions/use-placement-typeck.fixed b/src/test/ui/suggestions/use-placement-typeck.fixed
new file mode 100644 (file)
index 0000000..40c55d1
--- /dev/null
@@ -0,0 +1,22 @@
+// compile-flags: --test
+// run-rustfix
+// Checks that the `use` suggestion appears *below* this inner attribute.
+// There was an issue where the test synthetic #[allow(dead)] attribute on
+// main which has a dummy span caused the suggestion to be placed at the top
+// of the file.
+#![allow(unused)]
+
+use m::Foo;
+
+fn main() {
+    let s = m::S;
+    s.abc(); //~ ERROR no method named `abc`
+}
+
+mod m {
+    pub trait Foo {
+        fn abc(&self) {}
+    }
+    pub struct S;
+    impl Foo for S{}
+}
diff --git a/src/test/ui/suggestions/use-placement-typeck.rs b/src/test/ui/suggestions/use-placement-typeck.rs
new file mode 100644 (file)
index 0000000..aab20d2
--- /dev/null
@@ -0,0 +1,20 @@
+// compile-flags: --test
+// run-rustfix
+// Checks that the `use` suggestion appears *below* this inner attribute.
+// There was an issue where the test synthetic #[allow(dead)] attribute on
+// main which has a dummy span caused the suggestion to be placed at the top
+// of the file.
+#![allow(unused)]
+
+fn main() {
+    let s = m::S;
+    s.abc(); //~ ERROR no method named `abc`
+}
+
+mod m {
+    pub trait Foo {
+        fn abc(&self) {}
+    }
+    pub struct S;
+    impl Foo for S{}
+}
diff --git a/src/test/ui/suggestions/use-placement-typeck.stderr b/src/test/ui/suggestions/use-placement-typeck.stderr
new file mode 100644 (file)
index 0000000..21f22da
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0599]: no method named `abc` found for struct `S` in the current scope
+  --> $DIR/use-placement-typeck.rs:11:7
+   |
+LL |     s.abc();
+   |       ^^^ method not found in `S`
+...
+LL |         fn abc(&self) {}
+   |            --- the method is available for `S` here
+LL |     }
+LL |     pub struct S;
+   |     ------------- method `abc` not found for this
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL | use m::Foo;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
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 @@ mod 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 @@ mod bar {
         //[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 main() {
             //[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 @@ mod 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 @@ where
     //[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 951d7edb7f523ec14cbd3ad24f921b9d963fe8a5..101132d05fa0eb98f6a5d0f05e45d20800f5a2b4 100644 (file)
@@ -18,3 +18,4 @@ LL |     Bar::<i8>::func::<u8>(42);
 
 error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0632`.
diff --git a/src/test/ui/test-attrs/test-panic-abort-disabled.rs b/src/test/ui/test-attrs/test-panic-abort-disabled.rs
new file mode 100644 (file)
index 0000000..874dbdb
--- /dev/null
@@ -0,0 +1,20 @@
+// error-pattern:building tests with panic=abort is not supported
+// no-prefer-dynamic
+// compile-flags: --test -Cpanic=abort -Zpanic-abort-tests=no
+// run-flags: --test-threads=1
+
+// ignore-wasm no panic or subprocess support
+// ignore-emscripten no panic or subprocess support
+
+#![cfg(test)]
+
+#[test]
+fn it_works() {
+    assert_eq!(1 + 1, 2);
+}
+
+#[test]
+#[should_panic]
+fn it_panics() {
+    assert_eq!(1 + 1, 4);
+}
diff --git a/src/test/ui/test-attrs/test-panic-abort-disabled.stderr b/src/test/ui/test-attrs/test-panic-abort-disabled.stderr
new file mode 100644 (file)
index 0000000..9c65c73
--- /dev/null
@@ -0,0 +1,4 @@
+error: building tests with panic=abort is not supported without `-Zpanic_abort_tests`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/test-attrs/test-panic-abort-nocapture.rs b/src/test/ui/test-attrs/test-panic-abort-nocapture.rs
new file mode 100644 (file)
index 0000000..af530cc
--- /dev/null
@@ -0,0 +1,41 @@
+// no-prefer-dynamic
+// compile-flags: --test -Cpanic=abort -Zpanic_abort_tests
+// run-flags: --test-threads=1 --nocapture
+// run-fail
+// check-run-results
+// exec-env:RUST_BACKTRACE=0
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+// ignore-wasm no panic or subprocess support
+// ignore-emscripten no panic or subprocess support
+// ignore-sgx no subprocess support
+
+#![cfg(test)]
+
+use std::io::Write;
+
+#[test]
+fn it_works() {
+    println!("about to succeed");
+    assert_eq!(1 + 1, 2);
+}
+
+#[test]
+#[should_panic]
+fn it_panics() {
+    println!("about to panic");
+    assert_eq!(1 + 1, 4);
+}
+
+#[test]
+fn it_fails() {
+    println!("about to fail");
+    assert_eq!(1 + 1, 4);
+}
+
+#[test]
+fn it_writes_to_stdio() {
+    println!("hello, world");
+    writeln!(std::io::stdout(), "testing123").unwrap();
+    writeln!(std::io::stderr(), "testing321").unwrap();
+}
diff --git a/src/test/ui/test-attrs/test-panic-abort-nocapture.run.stderr b/src/test/ui/test-attrs/test-panic-abort-nocapture.run.stderr
new file mode 100644 (file)
index 0000000..727e969
--- /dev/null
@@ -0,0 +1,9 @@
+thread 'main' panicked at 'assertion failed: `(left == right)`
+  left: `2`,
+ right: `4`', $DIR/test-panic-abort-nocapture.rs:33:5
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+thread 'main' panicked at 'assertion failed: `(left == right)`
+  left: `2`,
+ right: `4`', $DIR/test-panic-abort-nocapture.rs:27:5
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+testing321
diff --git a/src/test/ui/test-attrs/test-panic-abort-nocapture.run.stdout b/src/test/ui/test-attrs/test-panic-abort-nocapture.run.stdout
new file mode 100644 (file)
index 0000000..8a91732
--- /dev/null
@@ -0,0 +1,23 @@
+
+running 4 tests
+test it_fails ... about to fail
+FAILED
+test it_panics - should panic ... about to panic
+ok
+test it_works ... about to succeed
+ok
+test it_writes_to_stdio ... hello, world
+testing123
+ok
+
+failures:
+
+---- it_fails stdout ----
+---- it_fails stderr ----
+
+
+failures:
+    it_fails
+
+test result: FAILED. 3 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/ui/test-attrs/test-panic-abort.rs b/src/test/ui/test-attrs/test-panic-abort.rs
new file mode 100644 (file)
index 0000000..931b799
--- /dev/null
@@ -0,0 +1,50 @@
+// no-prefer-dynamic
+// compile-flags: --test -Cpanic=abort -Zpanic_abort_tests
+// run-flags: --test-threads=1
+// run-fail
+// check-run-results
+// exec-env:RUST_BACKTRACE=0
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+// ignore-wasm no panic or subprocess support
+// ignore-emscripten no panic or subprocess support
+// ignore-sgx no subprocess support
+
+#![cfg(test)]
+
+use std::io::Write;
+use std::env;
+
+#[test]
+fn it_works() {
+    assert_eq!(1 + 1, 2);
+}
+
+#[test]
+#[should_panic]
+fn it_panics() {
+    assert_eq!(1 + 1, 4);
+}
+
+#[test]
+fn it_fails() {
+    println!("hello, world");
+    writeln!(std::io::stdout(), "testing123").unwrap();
+    writeln!(std::io::stderr(), "testing321").unwrap();
+    assert_eq!(1 + 1, 5);
+}
+
+#[test]
+fn it_exits() {
+    std::process::exit(123);
+}
+
+#[test]
+fn no_residual_environment() {
+    for (key, _) in env::vars() {
+        // Look for keys like __RUST_TEST_INVOKE.
+        if key.contains("TEST_INVOKE") {
+            panic!("shouldn't have '{}' in environment", key);
+        }
+    }
+}
diff --git a/src/test/ui/test-attrs/test-panic-abort.run.stdout b/src/test/ui/test-attrs/test-panic-abort.run.stdout
new file mode 100644 (file)
index 0000000..f608a8c
--- /dev/null
@@ -0,0 +1,30 @@
+
+running 5 tests
+test it_exits ... FAILED
+test it_fails ... FAILED
+test it_panics - should panic ... ok
+test it_works ... ok
+test no_residual_environment ... ok
+
+failures:
+
+---- it_exits stdout ----
+---- it_exits stderr ----
+note: got unexpected return code 123
+---- it_fails stdout ----
+hello, world
+testing123
+---- it_fails stderr ----
+testing321
+thread 'main' panicked at 'assertion failed: `(left == right)`
+  left: `2`,
+ right: `5`', $DIR/test-panic-abort.rs:34:5
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+
+
+failures:
+    it_exits
+    it_fails
+
+test result: FAILED. 3 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/ui/test-attrs/test-panic-while-printing.rs b/src/test/ui/test-attrs/test-panic-while-printing.rs
new file mode 100644 (file)
index 0000000..23f4540
--- /dev/null
@@ -0,0 +1,24 @@
+// compile-flags:--test
+// run-pass
+// ignore-emscripten no subprocess support
+
+use std::fmt;
+use std::fmt::{Display, Formatter};
+
+pub struct A(Vec<u32>);
+
+impl Display for A {
+    fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
+        self.0[0];
+        Ok(())
+    }
+}
+
+#[test]
+fn main() {
+    let result = std::panic::catch_unwind(|| {
+        let a = A(vec![]);
+        eprintln!("{}", a);
+    });
+    assert!(result.is_err());
+}
diff --git a/src/test/ui/test-attrs/test-passed-wasm.rs b/src/test/ui/test-attrs/test-passed-wasm.rs
new file mode 100644 (file)
index 0000000..578aa4b
--- /dev/null
@@ -0,0 +1,20 @@
+// no-prefer-dynamic
+// compile-flags: --test
+// run-flags: --test-threads=1
+// run-pass
+// check-run-results
+// only-wasm32
+
+// Tests the output of the test harness with only passed tests.
+
+#![cfg(test)]
+
+#[test]
+fn it_works() {
+    assert_eq!(1 + 1, 2);
+}
+
+#[test]
+fn it_works_too() {
+    assert_eq!(1 * 0, 0);
+}
diff --git a/src/test/ui/test-attrs/test-passed-wasm.run.stdout b/src/test/ui/test-attrs/test-passed-wasm.run.stdout
new file mode 100644 (file)
index 0000000..c3005a7
--- /dev/null
@@ -0,0 +1,7 @@
+
+running 2 tests
+test it_works ... ok
+test it_works_too ... ok
+
+test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+
diff --git a/src/test/ui/test-attrs/test-passed.rs b/src/test/ui/test-attrs/test-passed.rs
new file mode 100644 (file)
index 0000000..f65f000
--- /dev/null
@@ -0,0 +1,21 @@
+// no-prefer-dynamic
+// compile-flags: --test
+// run-flags: --test-threads=1
+// run-pass
+// check-run-results
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// ignore-wasm32 no support for `Instant`
+
+// Tests the output of the test harness with only passed tests.
+
+#![cfg(test)]
+
+#[test]
+fn it_works() {
+    assert_eq!(1 + 1, 2);
+}
+
+#[test]
+fn it_works_too() {
+    assert_eq!(1 * 0, 0);
+}
diff --git a/src/test/ui/test-attrs/test-passed.run.stdout b/src/test/ui/test-attrs/test-passed.run.stdout
new file mode 100644 (file)
index 0000000..17f70d6
--- /dev/null
@@ -0,0 +1,7 @@
+
+running 2 tests
+test it_works ... ok
+test it_works_too ... ok
+
+test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/ui/test-attrs/test-thread-capture.rs b/src/test/ui/test-attrs/test-thread-capture.rs
new file mode 100644 (file)
index 0000000..edc9728
--- /dev/null
@@ -0,0 +1,32 @@
+// compile-flags: --test
+// run-fail
+// run-flags: --test-threads=1
+// check-run-results
+// exec-env:RUST_BACKTRACE=0
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// ignore-emscripten no threads support
+
+#[test]
+fn thready_pass() {
+    println!("fee");
+    std::thread::spawn(|| {
+        println!("fie");
+        println!("foe");
+    })
+    .join()
+    .unwrap();
+    println!("fum");
+}
+
+#[test]
+fn thready_fail() {
+    println!("fee");
+    std::thread::spawn(|| {
+        println!("fie");
+        println!("foe");
+    })
+    .join()
+    .unwrap();
+    println!("fum");
+    panic!();
+}
diff --git a/src/test/ui/test-attrs/test-thread-capture.run.stdout b/src/test/ui/test-attrs/test-thread-capture.run.stdout
new file mode 100644 (file)
index 0000000..487cfb5
--- /dev/null
@@ -0,0 +1,21 @@
+
+running 2 tests
+test thready_fail ... FAILED
+test thready_pass ... ok
+
+failures:
+
+---- thready_fail stdout ----
+fee
+fie
+foe
+fum
+thread 'main' panicked at 'explicit panic', $DIR/test-thread-capture.rs:31:5
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+
+
+failures:
+    thready_fail
+
+test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/ui/test-attrs/test-thread-nocapture.rs b/src/test/ui/test-attrs/test-thread-nocapture.rs
new file mode 100644 (file)
index 0000000..8e8e9bb
--- /dev/null
@@ -0,0 +1,32 @@
+// compile-flags: --test
+// run-fail
+// run-flags: --test-threads=1 --nocapture
+// check-run-results
+// exec-env:RUST_BACKTRACE=0
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// ignore-emscripten no threads support
+
+#[test]
+fn thready_pass() {
+    println!("fee");
+    std::thread::spawn(|| {
+        println!("fie");
+        println!("foe");
+    })
+    .join()
+    .unwrap();
+    println!("fum");
+}
+
+#[test]
+fn thready_fail() {
+    println!("fee");
+    std::thread::spawn(|| {
+        println!("fie");
+        println!("foe");
+    })
+    .join()
+    .unwrap();
+    println!("fum");
+    panic!();
+}
diff --git a/src/test/ui/test-attrs/test-thread-nocapture.run.stderr b/src/test/ui/test-attrs/test-thread-nocapture.run.stderr
new file mode 100644 (file)
index 0000000..0649568
--- /dev/null
@@ -0,0 +1,2 @@
+thread 'main' panicked at 'explicit panic', $DIR/test-thread-nocapture.rs:31:5
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/test/ui/test-attrs/test-thread-nocapture.run.stdout b/src/test/ui/test-attrs/test-thread-nocapture.run.stdout
new file mode 100644 (file)
index 0000000..9d2da50
--- /dev/null
@@ -0,0 +1,20 @@
+
+running 2 tests
+test thready_fail ... fee
+fie
+foe
+fum
+FAILED
+test thready_pass ... fee
+fie
+foe
+fum
+ok
+
+failures:
+
+failures:
+    thready_fail
+
+test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/ui/test-cfg.rs b/src/test/ui/test-cfg.rs
deleted file mode 100644 (file)
index 8750bae..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// compile-flags: --cfg foo
-
-#[cfg(all(foo, bar))] // foo AND bar
-fn foo() {}
-
-fn main() {
-    foo(); //~ ERROR cannot find function `foo` in this scope
-}
diff --git a/src/test/ui/test-cfg.stderr b/src/test/ui/test-cfg.stderr
deleted file mode 100644 (file)
index c35fe2f..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0425]: cannot find function `foo` in this scope
-  --> $DIR/test-cfg.rs:7:5
-   |
-LL |     foo();
-   |     ^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/test-panic-abort-disabled.rs b/src/test/ui/test-panic-abort-disabled.rs
deleted file mode 100644 (file)
index 874dbdb..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// error-pattern:building tests with panic=abort is not supported
-// no-prefer-dynamic
-// compile-flags: --test -Cpanic=abort -Zpanic-abort-tests=no
-// run-flags: --test-threads=1
-
-// ignore-wasm no panic or subprocess support
-// ignore-emscripten no panic or subprocess support
-
-#![cfg(test)]
-
-#[test]
-fn it_works() {
-    assert_eq!(1 + 1, 2);
-}
-
-#[test]
-#[should_panic]
-fn it_panics() {
-    assert_eq!(1 + 1, 4);
-}
diff --git a/src/test/ui/test-panic-abort-disabled.stderr b/src/test/ui/test-panic-abort-disabled.stderr
deleted file mode 100644 (file)
index 9c65c73..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-error: building tests with panic=abort is not supported without `-Zpanic_abort_tests`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/test-panic-abort-nocapture.rs b/src/test/ui/test-panic-abort-nocapture.rs
deleted file mode 100644 (file)
index af530cc..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-// no-prefer-dynamic
-// compile-flags: --test -Cpanic=abort -Zpanic_abort_tests
-// run-flags: --test-threads=1 --nocapture
-// run-fail
-// check-run-results
-// exec-env:RUST_BACKTRACE=0
-// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
-
-// ignore-wasm no panic or subprocess support
-// ignore-emscripten no panic or subprocess support
-// ignore-sgx no subprocess support
-
-#![cfg(test)]
-
-use std::io::Write;
-
-#[test]
-fn it_works() {
-    println!("about to succeed");
-    assert_eq!(1 + 1, 2);
-}
-
-#[test]
-#[should_panic]
-fn it_panics() {
-    println!("about to panic");
-    assert_eq!(1 + 1, 4);
-}
-
-#[test]
-fn it_fails() {
-    println!("about to fail");
-    assert_eq!(1 + 1, 4);
-}
-
-#[test]
-fn it_writes_to_stdio() {
-    println!("hello, world");
-    writeln!(std::io::stdout(), "testing123").unwrap();
-    writeln!(std::io::stderr(), "testing321").unwrap();
-}
diff --git a/src/test/ui/test-panic-abort-nocapture.run.stderr b/src/test/ui/test-panic-abort-nocapture.run.stderr
deleted file mode 100644 (file)
index 727e969..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-thread 'main' panicked at 'assertion failed: `(left == right)`
-  left: `2`,
- right: `4`', $DIR/test-panic-abort-nocapture.rs:33:5
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-thread 'main' panicked at 'assertion failed: `(left == right)`
-  left: `2`,
- right: `4`', $DIR/test-panic-abort-nocapture.rs:27:5
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-testing321
diff --git a/src/test/ui/test-panic-abort-nocapture.run.stdout b/src/test/ui/test-panic-abort-nocapture.run.stdout
deleted file mode 100644 (file)
index 8a91732..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-
-running 4 tests
-test it_fails ... about to fail
-FAILED
-test it_panics - should panic ... about to panic
-ok
-test it_works ... about to succeed
-ok
-test it_writes_to_stdio ... hello, world
-testing123
-ok
-
-failures:
-
----- it_fails stdout ----
----- it_fails stderr ----
-
-
-failures:
-    it_fails
-
-test result: FAILED. 3 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
-
diff --git a/src/test/ui/test-panic-abort.rs b/src/test/ui/test-panic-abort.rs
deleted file mode 100644 (file)
index 931b799..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-// no-prefer-dynamic
-// compile-flags: --test -Cpanic=abort -Zpanic_abort_tests
-// run-flags: --test-threads=1
-// run-fail
-// check-run-results
-// exec-env:RUST_BACKTRACE=0
-// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
-
-// ignore-wasm no panic or subprocess support
-// ignore-emscripten no panic or subprocess support
-// ignore-sgx no subprocess support
-
-#![cfg(test)]
-
-use std::io::Write;
-use std::env;
-
-#[test]
-fn it_works() {
-    assert_eq!(1 + 1, 2);
-}
-
-#[test]
-#[should_panic]
-fn it_panics() {
-    assert_eq!(1 + 1, 4);
-}
-
-#[test]
-fn it_fails() {
-    println!("hello, world");
-    writeln!(std::io::stdout(), "testing123").unwrap();
-    writeln!(std::io::stderr(), "testing321").unwrap();
-    assert_eq!(1 + 1, 5);
-}
-
-#[test]
-fn it_exits() {
-    std::process::exit(123);
-}
-
-#[test]
-fn no_residual_environment() {
-    for (key, _) in env::vars() {
-        // Look for keys like __RUST_TEST_INVOKE.
-        if key.contains("TEST_INVOKE") {
-            panic!("shouldn't have '{}' in environment", key);
-        }
-    }
-}
diff --git a/src/test/ui/test-panic-abort.run.stdout b/src/test/ui/test-panic-abort.run.stdout
deleted file mode 100644 (file)
index f608a8c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-
-running 5 tests
-test it_exits ... FAILED
-test it_fails ... FAILED
-test it_panics - should panic ... ok
-test it_works ... ok
-test no_residual_environment ... ok
-
-failures:
-
----- it_exits stdout ----
----- it_exits stderr ----
-note: got unexpected return code 123
----- it_fails stdout ----
-hello, world
-testing123
----- it_fails stderr ----
-testing321
-thread 'main' panicked at 'assertion failed: `(left == right)`
-  left: `2`,
- right: `5`', $DIR/test-panic-abort.rs:34:5
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-
-
-failures:
-    it_exits
-    it_fails
-
-test result: FAILED. 3 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
-
diff --git a/src/test/ui/test-panic-while-printing.rs b/src/test/ui/test-panic-while-printing.rs
deleted file mode 100644 (file)
index 23f4540..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// compile-flags:--test
-// run-pass
-// ignore-emscripten no subprocess support
-
-use std::fmt;
-use std::fmt::{Display, Formatter};
-
-pub struct A(Vec<u32>);
-
-impl Display for A {
-    fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
-        self.0[0];
-        Ok(())
-    }
-}
-
-#[test]
-fn main() {
-    let result = std::panic::catch_unwind(|| {
-        let a = A(vec![]);
-        eprintln!("{}", a);
-    });
-    assert!(result.is_err());
-}
diff --git a/src/test/ui/test-passed-wasm.rs b/src/test/ui/test-passed-wasm.rs
deleted file mode 100644 (file)
index 578aa4b..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// no-prefer-dynamic
-// compile-flags: --test
-// run-flags: --test-threads=1
-// run-pass
-// check-run-results
-// only-wasm32
-
-// Tests the output of the test harness with only passed tests.
-
-#![cfg(test)]
-
-#[test]
-fn it_works() {
-    assert_eq!(1 + 1, 2);
-}
-
-#[test]
-fn it_works_too() {
-    assert_eq!(1 * 0, 0);
-}
diff --git a/src/test/ui/test-passed-wasm.run.stdout b/src/test/ui/test-passed-wasm.run.stdout
deleted file mode 100644 (file)
index c3005a7..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-
-running 2 tests
-test it_works ... ok
-test it_works_too ... ok
-
-test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
-
diff --git a/src/test/ui/test-passed.rs b/src/test/ui/test-passed.rs
deleted file mode 100644 (file)
index f65f000..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// no-prefer-dynamic
-// compile-flags: --test
-// run-flags: --test-threads=1
-// run-pass
-// check-run-results
-// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
-// ignore-wasm32 no support for `Instant`
-
-// Tests the output of the test harness with only passed tests.
-
-#![cfg(test)]
-
-#[test]
-fn it_works() {
-    assert_eq!(1 + 1, 2);
-}
-
-#[test]
-fn it_works_too() {
-    assert_eq!(1 * 0, 0);
-}
diff --git a/src/test/ui/test-passed.run.stdout b/src/test/ui/test-passed.run.stdout
deleted file mode 100644 (file)
index 17f70d6..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-
-running 2 tests
-test it_works ... ok
-test it_works_too ... ok
-
-test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
-
diff --git a/src/test/ui/test-thread-capture.rs b/src/test/ui/test-thread-capture.rs
deleted file mode 100644 (file)
index edc9728..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// compile-flags: --test
-// run-fail
-// run-flags: --test-threads=1
-// check-run-results
-// exec-env:RUST_BACKTRACE=0
-// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
-// ignore-emscripten no threads support
-
-#[test]
-fn thready_pass() {
-    println!("fee");
-    std::thread::spawn(|| {
-        println!("fie");
-        println!("foe");
-    })
-    .join()
-    .unwrap();
-    println!("fum");
-}
-
-#[test]
-fn thready_fail() {
-    println!("fee");
-    std::thread::spawn(|| {
-        println!("fie");
-        println!("foe");
-    })
-    .join()
-    .unwrap();
-    println!("fum");
-    panic!();
-}
diff --git a/src/test/ui/test-thread-capture.run.stdout b/src/test/ui/test-thread-capture.run.stdout
deleted file mode 100644 (file)
index 487cfb5..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-
-running 2 tests
-test thready_fail ... FAILED
-test thready_pass ... ok
-
-failures:
-
----- thready_fail stdout ----
-fee
-fie
-foe
-fum
-thread 'main' panicked at 'explicit panic', $DIR/test-thread-capture.rs:31:5
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-
-
-failures:
-    thready_fail
-
-test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
-
diff --git a/src/test/ui/test-thread-nocapture.rs b/src/test/ui/test-thread-nocapture.rs
deleted file mode 100644 (file)
index 8e8e9bb..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// compile-flags: --test
-// run-fail
-// run-flags: --test-threads=1 --nocapture
-// check-run-results
-// exec-env:RUST_BACKTRACE=0
-// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
-// ignore-emscripten no threads support
-
-#[test]
-fn thready_pass() {
-    println!("fee");
-    std::thread::spawn(|| {
-        println!("fie");
-        println!("foe");
-    })
-    .join()
-    .unwrap();
-    println!("fum");
-}
-
-#[test]
-fn thready_fail() {
-    println!("fee");
-    std::thread::spawn(|| {
-        println!("fie");
-        println!("foe");
-    })
-    .join()
-    .unwrap();
-    println!("fum");
-    panic!();
-}
diff --git a/src/test/ui/test-thread-nocapture.run.stderr b/src/test/ui/test-thread-nocapture.run.stderr
deleted file mode 100644 (file)
index 0649568..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-thread 'main' panicked at 'explicit panic', $DIR/test-thread-nocapture.rs:31:5
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/test/ui/test-thread-nocapture.run.stdout b/src/test/ui/test-thread-nocapture.run.stdout
deleted file mode 100644 (file)
index 9d2da50..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-
-running 2 tests
-test thready_fail ... fee
-fie
-foe
-fum
-FAILED
-test thready_pass ... fee
-fie
-foe
-fum
-ok
-
-failures:
-
-failures:
-    thready_fail
-
-test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
-
diff --git a/src/test/ui/thir-unsafeck-issue-85871.rs b/src/test/ui/thir-unsafeck-issue-85871.rs
new file mode 100644 (file)
index 0000000..aea539b
--- /dev/null
@@ -0,0 +1,20 @@
+// Tests that no ICE occurs when a closure appears inside a node
+// that does not have a body when compiling with
+// compile-flags: -Zthir-unsafeck=yes
+// check-pass
+
+#![allow(dead_code)]
+
+struct Bug {
+    inner: [(); match || 1 {
+        _n => 42, // we may not call the closure here (E0015)
+    }],
+}
+
+enum E {
+    V([(); { let _ = || 1; 42 }]),
+}
+
+type Ty = [(); { let _ = || 1; 42 }];
+
+fn main() {}
index dc542fe2db961747857f5c519a307be920efa872..c7fee9e6b4c5a2f8edcef7ef624ffcaa60721d55 100644 (file)
@@ -11,7 +11,6 @@ const fn g(x: &mut [u32; 8]) {
     //~| ERROR mutable references are not allowed
     //~| ERROR use of mutable static is unsafe
     //~| constant functions cannot refer to statics
-    //~| ERROR calls in constant functions are limited to constant functions
 }
 
 fn main() {}
index a213282eb85cd5b3273bf5a9116121520a180430..08bf593a5a748d92c1058a33d55036d04c3ad879 100644 (file)
@@ -30,12 +30,6 @@ LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/thread-local-static.rs:9:5
-   |
-LL |     std::mem::swap(x, &mut STATIC_VAR_2)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0133]: use of mutable static is unsafe and requires unsafe function or block
   --> $DIR/thread-local-static.rs:9:23
    |
@@ -44,7 +38,7 @@ LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    |
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0013, E0015, E0133, E0658.
+Some errors have detailed explanations: E0013, E0133, E0658.
 For more information about an error, try `rustc --explain E0013`.
diff --git a/src/test/ui/thread-local/thread-local-issue-37508.rs b/src/test/ui/thread-local/thread-local-issue-37508.rs
new file mode 100644 (file)
index 0000000..219108c
--- /dev/null
@@ -0,0 +1,36 @@
+// only-x86_64
+// compile-flags: -Ccode-model=large --crate-type lib
+// build-pass
+//
+// Regression test for issue #37508
+
+#![no_main]
+#![no_std]
+#![feature(thread_local, lang_items)]
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(_panic: &PanicInfo<'_>) -> ! {
+    loop {}
+}
+
+pub struct BB;
+
+#[thread_local]
+static mut KEY: Key = Key { inner: BB, dtor_running: false };
+
+pub unsafe fn set() -> Option<&'static BB> {
+    if KEY.dtor_running {
+        return None;
+    }
+    Some(&KEY.inner)
+}
+
+pub struct Key {
+    inner: BB,
+    dtor_running: bool,
+}
index 768893d6e25d475dc932f4a163f4abaff477230a..5a9d4286ce6d10fe715c6fed1ec337d139b48bf0 100644 (file)
@@ -29,7 +29,11 @@ LL |     let x: Vec<dyn Trait + Sized> = Vec::new();
    |                                     ^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `dyn Trait`
-   = note: required by `Vec::<T>::new`
+note: required by `Vec::<T>::new`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+   |
+LL |     pub const fn new() -> Self {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
   --> $DIR/bad-sized.rs:4:37
index 08355a55630f643bcc89f65965e66812bca0903c..daf18c6702e4695066197af2257326425389af72 100644 (file)
@@ -7,7 +7,7 @@ trait Foo {
 fn foo(_x: Foo + Send) {
     //~^ ERROR the size for values of type
     //~| WARN trait objects without an explicit `dyn` are deprecated
-    //~| WARN this was previously accepted by the compiler
+    //~| WARN this is accepted in the current edition
 }
 
 fn main() {}
index 418e67d56ea1d0fd4667cc665dc858f28024a9e5..e65b8989e0b1ec47f1c5e9517db88551e8af54e5 100644 (file)
@@ -5,7 +5,7 @@ LL | fn foo(_x: Foo + Send) {
    |            ^^^^^^^^^^ help: use `dyn`: `dyn Foo + Send`
    |
    = note: `#[warn(bare_trait_objects)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time
index 967b7320ab6cd9d4cc64009f465615d2a05efc38..7480d243f4e62fc3000c38c6c1694089583db0f2 100644 (file)
@@ -10,11 +10,14 @@ LL |     let baz: Foo<usize> = loop { };
 error[E0277]: the trait bound `{integer}: Trait` is not satisfied
   --> $DIR/on-structs-and-enums-locals.rs:10:15
    |
-LL | struct Foo<T:Trait> {
-   | ------------------- required by `Foo`
-...
 LL |     let foo = Foo {
    |               ^^^ the trait `Trait` is not implemented for `{integer}`
+   |
+note: required by `Foo`
+  --> $DIR/on-structs-and-enums-locals.rs:5:1
+   |
+LL | struct Foo<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 08f0f20e7480a688acf89032a9125723a976416b..ada2445c1c96259871914cd9f06756dbb9468f3a 100644 (file)
@@ -15,7 +15,11 @@ error[E0277]: the trait bound `{integer}: Trait` is not satisfied
 LL |     let foo = Foo {
    |               ^^^ the trait `Trait` is not implemented for `{integer}`
    |
-   = note: required by `Foo`
+note: required by `Foo`
+  --> $DIR/auxiliary/on_structs_and_enums_xc.rs:5:1
+   |
+LL | pub struct Foo<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 40386f706132bb6d38c8c01f6db040df4fd3c514..565899677bf1a74d55e7d39acf7d304edfcf2150 100644 (file)
@@ -1,9 +1,6 @@
 error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe`
   --> $DIR/cycle-cache-err-60010.rs:69:5
    |
-LL |     fn parse(&self) {
-   |     --------------- required by `SourceDatabase::parse`
-...
 LL |     SourceDatabase::parse(db);
    |     ^^^^^^^^^^^^^^^^^^^^^
    |
@@ -25,6 +22,11 @@ note: required because of the requirements on the impl of `SourceDatabase` for `
    |
 LL | impl<T> SourceDatabase for T
    |         ^^^^^^^^^^^^^^     ^
+note: required by `SourceDatabase::parse`
+  --> $DIR/cycle-cache-err-60010.rs:14:5
+   |
+LL |     fn parse(&self) {
+   |     ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index bb11f18e54505bd8f953ae9599edbb2a8f405847..bc7b863ca4f5175392ef1a0451c994a5575e7e0e 100644 (file)
@@ -18,21 +18,26 @@ LL | fn with_trait<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool {
 error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied
   --> $DIR/repeated-supertrait-ambig.rs:34:5
    |
-LL |     fn same_as(&self, t: T) -> bool;
-   |     -------------------------------- required by `CompareTo::same_as`
-...
 LL |     <dyn CompareToInts>::same_as(c, 22)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
+   |
+note: required by `CompareTo::same_as`
+  --> $DIR/repeated-supertrait-ambig.rs:9:5
+   |
+LL |     fn same_as(&self, t: T) -> bool;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
   --> $DIR/repeated-supertrait-ambig.rs:38:5
    |
-LL |     fn same_as(&self, t: T) -> bool;
-   |     -------------------------------- required by `CompareTo::same_as`
-...
 LL |     CompareTo::same_as(c, 22)
    |     ^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `C`
    |
+note: required by `CompareTo::same_as`
+  --> $DIR/repeated-supertrait-ambig.rs:9:5
+   |
+LL |     fn same_as(&self, t: T) -> bool;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider further restricting this bound
    |
 LL | fn with_ufcs2<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool {
index d1be955b41ed64fa2e50692adcb0ac09c7c1b713..23b78d023b600dc8f3665e3a5b6a6ea97eca3599 100644 (file)
@@ -1,11 +1,18 @@
 error[E0277]: the trait bound `Foo: Clone` is not satisfied
   --> $DIR/issue-71136.rs:5:5
    |
+LL | #[derive(Clone)]
+   |          ----- in this derive macro expansion
+LL | struct FooHolster {
 LL |     the_foos: Vec<Foo>,
    |     ^^^^^^^^^^^^^^^^^^ expected an implementor of trait `Clone`
    |
    = note: required because of the requirements on the impl of `Clone` for `Vec<Foo>`
-   = note: required by `clone`
+note: required by `clone`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL |     fn clone(&self) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index d788f1871ffac83233b8cd186a5706baeb621bac..68347207bda45d10b0a6e046e513b6848c5fa979 100644 (file)
@@ -17,7 +17,11 @@ LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(
    |                                            cannot infer type for type parameter `T` declared on the trait `From`
    |
    = note: cannot satisfy `u32: From<_>`
-   = note: required by `from`
+note: required by `from`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn from(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed for `Box<T>`
   --> $DIR/issue-77982.rs:35:16
diff --git a/src/test/ui/traits/issue-78632.rs b/src/test/ui/traits/issue-78632.rs
new file mode 100644 (file)
index 0000000..c72a2ae
--- /dev/null
@@ -0,0 +1,59 @@
+// check-pass
+//
+// Regression test for issue #78632
+
+#![crate_type = "lib"]
+
+pub trait Corge<T> {
+    type Fred;
+}
+
+impl Corge<u8> for () {
+    type Fred = u32;
+}
+
+pub trait Waldo {
+    type Quax;
+}
+
+impl Waldo for u32 {
+    type Quax = u8;
+}
+
+pub trait Grault
+where
+    (): Corge<Self::Thud>,
+{
+    type Thud;
+    fn bar(_: <() as Corge<Self::Thud>>::Fred) {}
+}
+
+impl<T> Grault for T
+where
+    T: Waldo,
+    (): Corge<T::Quax>,
+    <() as Corge<T::Quax>>::Fred: Waldo,
+{
+    type Thud = u8;
+}
+
+pub trait Plugh<I> {
+    fn baz();
+}
+
+#[derive(Copy, Clone, Debug)]
+pub struct Qiz<T> {
+    foo: T,
+}
+
+impl<T> Plugh<<() as Corge<T::Thud>>::Fred> for Qiz<T>
+where
+    T: Grault,
+    (): Corge<T::Thud>,
+{
+    fn baz() {}
+}
+
+pub fn test() {
+    <Qiz<u32> as Plugh<u32>>::baz();
+}
index 7e990cdc34e25fbda74db60ceb4aa8ffe21bd22e..2f5b4ad0e62c88069a285bf3bbade8d8e36fc3f4 100644 (file)
@@ -1,13 +1,20 @@
 error[E0277]: the trait bound `&mut T: Clone` is not satisfied
   --> $DIR/issue-79458.rs:6:5
    |
+LL | #[derive(Clone)]
+   |          ----- in this derive macro expansion
+LL | struct Foo<'a, T> {
 LL |     bar: &'a mut T
    |     ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&mut T`
    |
    = help: the following implementations were found:
              <&T as Clone>
    = note: `Clone` is implemented for `&T`, but not for `&mut T`
-   = note: required by `clone`
+note: required by `clone`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL |     fn clone(&self) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index e186570167d76e8b32efee96b4c747cca17923a1..1be0b05fa2b8c25a753cff2b82e3abe610bcf7a7 100644 (file)
@@ -17,8 +17,8 @@ pub struct Second {
     d: Vec<First>,
 }
 
-struct Third<f> {
-    g: Vec<f>,
+struct Third<'a, f> {
+    g: Vec<(f, &'a f)>,
 }
 
 enum Ty {
@@ -38,29 +38,29 @@ struct Sixth {
 }
 
 #[rustc_evaluate_where_clauses]
-fn forward()
+fn forward<'a>()
 where
     Vec<First>: Unpin,
-    Third<Ty>: Unpin,
+    Third<'a, Ty>: Unpin,
 {
 }
 
 #[rustc_evaluate_where_clauses]
-fn reverse()
+fn reverse<'a>()
 where
-    Third<Ty>: Unpin,
+    Third<'a, Ty>: Unpin,
     Vec<First>: Unpin,
 {
 }
 
 fn main() {
-    // Key is that Vec<First> is "ok" and Third<Ty> is "ok modulo regions":
+    // Key is that Vec<First> is "ok" and Third<'_, Ty> is "ok modulo regions":
 
     forward();
     //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk)
-    //~| ERROR evaluate(Binder(TraitPredicate(<Third<Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
+    //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
 
     reverse();
     //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk)
-    //~| ERROR evaluate(Binder(TraitPredicate(<Third<Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
+    //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
 }
index bfe3e76b214b0c3ba930880cdbae41b7bf021cc5..43acc66fd73cbb00a589f918c15cd1357b61eee0 100644 (file)
@@ -7,20 +7,20 @@ LL |     Vec<First>: Unpin,
 LL |     forward();
    |     ^^^^^^^
 
-error: evaluate(Binder(TraitPredicate(<Third<Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
+error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
   --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5
    |
-LL |     Third<Ty>: Unpin,
-   |                ----- predicate
+LL |     Third<'a, Ty>: Unpin,
+   |                    ----- predicate
 ...
 LL |     forward();
    |     ^^^^^^^
 
-error: evaluate(Binder(TraitPredicate(<Third<Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
+error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
   --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5
    |
-LL |     Third<Ty>: Unpin,
-   |                ----- predicate
+LL |     Third<'a, Ty>: Unpin,
+   |                    ----- predicate
 ...
 LL |     reverse();
    |     ^^^^^^^
index 30daf8e27702441b0504987446bc7d6c30d70a38..2260dcfc70ea38f4d4eff58a6ca91234fba9d67a 100644 (file)
@@ -35,6 +35,9 @@ LL | use method::B;
 error[E0624]: associated function `a` is private
   --> $DIR/item-privacy.rs:72:7
    |
+LL |         fn a(&self) { }
+   |         ----------- private associated function defined here
+...
 LL |     c.a();
    |       ^ private associated function
 
@@ -72,6 +75,9 @@ LL | use method::B;
 error[E0624]: associated function `a` is private
   --> $DIR/item-privacy.rs:84:14
    |
+LL |         fn a(&self) { }
+   |         ----------- private associated function defined here
+...
 LL |     <dyn C>::a(&S);
    |              ^ private associated function
 
@@ -109,6 +115,9 @@ LL | use assoc_const::B;
 error[E0624]: associated constant `A` is private
   --> $DIR/item-privacy.rs:101:14
    |
+LL |         const A: u8 = 0;
+   |         ---------------- private associated constant defined here
+...
 LL |     <dyn C>::A;
    |              ^ private associated constant
 
index 99f330b38ae3de6e37660b84bd525e0fcc731973..8e991ec018c3e0c105bb4ff32074f132747b3d9d 100644 (file)
@@ -1,6 +1,9 @@
 error[E0624]: associated function `method` is private
   --> $DIR/method-private.rs:19:9
    |
+LL |         fn method(&self) {}
+   |         ---------------- private associated function defined here
+...
 LL |     foo.method();
    |         ^^^^^^ private associated function
    |
index 4f7d1be793891c4526b2c292f34b0c7266c6de09..cad298cf247330c7b075701557f1b254010f6698 100644 (file)
@@ -1,13 +1,15 @@
 error[E0277]: `dummy::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:23:11
    |
-LL | struct Outer<T: Send>(T);
-   | ------------------------- required by `Outer`
-...
 LL |     Outer(TestType);
    |           ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `dummy::TestType`
+note: required by `Outer`
+  --> $DIR/negated-auto-traits-error.rs:10:1
+   |
+LL | struct Outer<T: Send>(T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `dummy::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:23:5
index 46b68f1c9fe07821b32f4b195d4e19216a1db1b4..8abd92da362d36c0c68351a58f97503af5812ef0 100644 (file)
@@ -1,6 +1,7 @@
 // check-pass
 
 #![warn(order_dependent_trait_objects)]
+#![allow(dyn_drop)]
 
 // Check that traitobject 0.1.0 compiles
 
index 781decb5ae2813cc6b2dd1eef21853537bf4b834..77d71360b806b1249c0bde060add8df6a183e927 100644 (file)
@@ -1,5 +1,5 @@
 warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
-  --> $DIR/issue-33140-traitobject-crate.rs:85:1
+  --> $DIR/issue-33140-traitobject-crate.rs:86:1
    |
 LL | unsafe impl Trait for dyn (::std::marker::Send) + Sync { }
    | ------------------------------------------------------ first implementation here
@@ -15,7 +15,7 @@ LL | #![warn(order_dependent_trait_objects)]
    = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
 
 warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
-  --> $DIR/issue-33140-traitobject-crate.rs:88:1
+  --> $DIR/issue-33140-traitobject-crate.rs:89:1
    |
 LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { }
    | ------------------------------------------------------------- first implementation here
@@ -27,7 +27,7 @@ LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { }
    = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
 
 warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
-  --> $DIR/issue-33140-traitobject-crate.rs:92:1
+  --> $DIR/issue-33140-traitobject-crate.rs:93:1
    |
 LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { }
    | ------------------------------------------------------ first implementation here
diff --git a/src/test/ui/traits/operator-overloading-issue-52025.rs b/src/test/ui/traits/operator-overloading-issue-52025.rs
new file mode 100644 (file)
index 0000000..7ce6388
--- /dev/null
@@ -0,0 +1,57 @@
+// only-x86_64
+// build-pass
+
+use std::arch::x86_64::*;
+use std::fmt::Debug;
+use std::ops::*;
+
+pub trait Simd {
+    type Vf32: Copy + Debug + Add<Self::Vf32, Output = Self::Vf32> + Add<f32, Output = Self::Vf32>;
+
+    unsafe fn set1_ps(a: f32) -> Self::Vf32;
+    unsafe fn add_ps(a: Self::Vf32, b: Self::Vf32) -> Self::Vf32;
+}
+
+#[derive(Copy, Debug, Clone)]
+pub struct F32x4(pub __m128);
+
+impl Add<F32x4> for F32x4 {
+    type Output = F32x4;
+
+    fn add(self, rhs: F32x4) -> F32x4 {
+        F32x4(unsafe { _mm_add_ps(self.0, rhs.0) })
+    }
+}
+
+impl Add<f32> for F32x4 {
+    type Output = F32x4;
+    fn add(self, rhs: f32) -> F32x4 {
+        F32x4(unsafe { _mm_add_ps(self.0, _mm_set1_ps(rhs)) })
+    }
+}
+
+pub struct Sse2;
+impl Simd for Sse2 {
+    type Vf32 = F32x4;
+
+    #[inline(always)]
+    unsafe fn set1_ps(a: f32) -> Self::Vf32 {
+        F32x4(_mm_set1_ps(a))
+    }
+
+    #[inline(always)]
+    unsafe fn add_ps(a: Self::Vf32, b: Self::Vf32) -> Self::Vf32 {
+        F32x4(_mm_add_ps(a.0, b.0))
+    }
+}
+
+unsafe fn test<S: Simd>() -> S::Vf32 {
+    let a = S::set1_ps(3.0);
+    let b = S::set1_ps(2.0);
+    let result = a + b;
+    result
+}
+
+fn main() {
+    println!("{:?}", unsafe { test::<Sse2>() });
+}
index fb4a443435fa5d5aca98fbac1d4cfd32e5dc4cb8..526c0e9ed540fa3485fbe1d8726246bdc19f87d8 100644 (file)
@@ -1,14 +1,16 @@
 error[E0277]: the trait bound `(): MyTrait` is not satisfied
   --> $DIR/no-use.rs:10:26
    |
-LL | trait MyTrait { fn foo(&self); }
-   |                 -------------- required by `MyTrait::foo`
-...
 LL |     <() as MyTrait>::foo(&());
    |                          ^^^ the trait `MyTrait` is not implemented for `()`
    |
    = help: the following implementations were found:
              <() as MyTrait>
+note: required by `MyTrait::foo`
+  --> $DIR/no-use.rs:5:17
+   |
+LL | trait MyTrait { fn foo(&self); }
+   |                 ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index f14589ccf846d07e06fb6f6f2262c36602bc1e5e..b894577c1f7da5c58853456aa1962f257d1183d6 100644 (file)
@@ -28,7 +28,7 @@
 // go with a known approach, we should go with a "marker trait overlap"-style
 // approach.
 //
-// [ii]: http://smallcultfollowing.com/babysteps/blog/2016/09/24/intersection-impls/
+// [ii]: https://smallcultfollowing.com/babysteps/blog/2016/09/24/intersection-impls/
 
 #![feature(rustc_attrs, never_type)]
 
index 2b9ce7321eeae19100bb97b253f379d98fd97c5c..c8c804a9013bfd80f3f4008156e4af9b95252c2b 100644 (file)
@@ -1,13 +1,15 @@
 error[E0283]: type annotations needed
   --> $DIR/static-method-generic-inference.rs:24:25
    |
-LL |         fn new() -> T;
-   |         -------------- required by `HasNew::new`
-...
 LL |     let _f: base::Foo = base::HasNew::new();
    |                         ^^^^^^^^^^^^^^^^^ cannot infer type
    |
    = note: cannot satisfy `_: HasNew<Foo>`
+note: required by `HasNew::new`
+  --> $DIR/static-method-generic-inference.rs:8:9
+   |
+LL |         fn new() -> T;
+   |         ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 025706480821d29d2d23ebec267dae624bfd4941..f15e7e35839d584f8f37804ba6c7dd744a4217a4 100644 (file)
@@ -38,7 +38,11 @@ error[E0277]: the trait bound `u64: From<T>` is not satisfied
 LL |     <u64 as From<T>>::from;
    |     ^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `u64`
    |
-   = note: required by `from`
+note: required by `from`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn from(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
    |
 LL | fn check<T: Iterator, U: ?Sized>() where u64: From<T> {
@@ -50,7 +54,11 @@ error[E0277]: the trait bound `u64: From<<T as Iterator>::Item>` is not satisfie
 LL |     <u64 as From<<T as Iterator>::Item>>::from;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<<T as Iterator>::Item>` is not implemented for `u64`
    |
-   = note: required by `from`
+note: required by `from`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn from(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
    |
 LL | fn check<T: Iterator, U: ?Sized>() where u64: From<<T as Iterator>::Item> {
@@ -62,7 +70,11 @@ error[E0277]: the trait bound `Misc<_>: From<T>` is not satisfied
 LL |     <Misc<_> as From<T>>::from;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `Misc<_>`
    |
-   = note: required by `from`
+note: required by `from`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn from(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `[T]` cannot be known at compilation time
   --> $DIR/suggest-where-clause.rs:28:20
index de7a431d6ff541db718d3805433f37e5dff112a3..41a19bff8703b21571f1294198490fb422582903 100644 (file)
@@ -23,11 +23,14 @@ LL | pub trait Foo {
 error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/trivial-bounds-leak.rs:25:15
    |
-LL |     fn test(&self);
-   |     --------------- required by `Foo::test`
-...
 LL |     Foo::test(&4i32);
    |               ^^^^^ the trait `Foo` is not implemented for `i32`
+   |
+note: required by `Foo::test`
+  --> $DIR/trivial-bounds-leak.rs:5:5
+   |
+LL |     fn test(&self);
+   |     ^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/trivial-bounds-leak.rs:26:22
index ec5e91f10c28614bb3cef54ee7064d200d1ec4e2..fce8dbab4856ca7daf4e4de7278e22f62cb8b29c 100644 (file)
@@ -8,7 +8,11 @@ LL |         Err("")?;
    = help: the following implementations were found:
              <TryFromSliceError as From<Infallible>>
    = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, &str>>` for `Result<u32, TryFromSliceError>`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str`
   --> $DIR/try-block-bad-type.rs:12:9
@@ -29,7 +33,11 @@ LL |     let res: () = try { };
    |                         ^ could not wrap the final value of the block as `()` doesn't implement `Try`
    |
    = help: the trait `Try` is not implemented for `()`
-   = note: required by `from_output`
+note: required by `from_output`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_output(output: Self::Output) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
   --> $DIR/try-block-bad-type.rs:20:26
@@ -38,7 +46,11 @@ LL |     let res: i32 = try { 5 };
    |                          ^ could not wrap the final value of the block as `i32` doesn't implement `Try`
    |
    = help: the trait `Try` is not implemented for `i32`
-   = note: required by `from_output`
+note: required by `from_output`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_output(output: Self::Output) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
index c83351d5c434634766476d45340a5b533cb38494..4270df5b4063cc05439155017a371c7974f9e532 100644 (file)
@@ -5,7 +5,11 @@ LL |     while try { false } {}
    |                 ^^^^^ could not wrap the final value of the block as `bool` doesn't implement `Try`
    |
    = help: the trait `Try` is not implemented for `bool`
-   = note: required by `from_output`
+note: required by `from_output`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_output(output: Self::Output) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index f5b315c25193377cf0987c90ff30a65e92e41be1..5cecf9128bb2ca4118878aa27914d6116f7b8fc0 100644 (file)
@@ -11,7 +11,11 @@ LL |     Ok(Err(123_i32)?)
              <u8 as From<NonZeroU8>>
              <u8 as From<bool>>
    = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, i32>>` for `Result<u64, u8>`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
   --> $DIR/bad-interconversion.rs:11:12
@@ -25,7 +29,11 @@ LL | | }
    | |_- this function returns a `Result`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u64, String>`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result`
   --> $DIR/bad-interconversion.rs:17:31
@@ -38,7 +46,11 @@ LL | | }
    | |_- this function returns a `Result`
    |
    = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Result<u64, String>`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
   --> $DIR/bad-interconversion.rs:22:22
@@ -51,7 +63,11 @@ LL | | }
    | |_- this function returns an `Option`
    |
    = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `Option<u16>`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
   --> $DIR/bad-interconversion.rs:27:33
@@ -64,7 +80,11 @@ LL | | }
    | |_- this function returns an `Option`
    |
    = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Option<u64>`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
   --> $DIR/bad-interconversion.rs:32:39
@@ -77,7 +97,11 @@ LL | | }
    | |_- this function returns a `ControlFlow`
    |
    = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `ControlFlow<String>`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
   --> $DIR/bad-interconversion.rs:37:12
@@ -91,7 +115,11 @@ LL | | }
    | |_- this function returns a `ControlFlow`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `ControlFlow<u64>`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator in a function that returns `ControlFlow<B, _>` can only be used on other `ControlFlow<B, _>`s (with the same Break type)
   --> $DIR/bad-interconversion.rs:43:29
@@ -106,7 +134,11 @@ LL | | }
    |
    = help: the trait `FromResidual<ControlFlow<u8, Infallible>>` is not implemented for `ControlFlow<i64>`
    = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 8 previous errors
 
index 9f7d80d4f23cdc1bdb834e1b023d98f591bc9d2b..f89813e729fad60c22e2f8da16b3aec924137136 100644 (file)
@@ -10,7 +10,11 @@ LL | | }
    | |_- this function returns a `Result`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<(), ()>`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
   --> $DIR/option-to-result.rs:11:6
@@ -24,7 +28,11 @@ LL | | }
    | |_- this function returns an `Option`
    |
    = help: the trait `FromResidual<Result<Infallible, i32>>` is not implemented for `Option<i32>`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index e7c67c21bb3e3f1e9155733303f7fd28ec51b687..bb65aae561f97949a5277c0435073d3e340ce7fc 100644 (file)
@@ -10,7 +10,11 @@ LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-diagnostics.rs:14:10
@@ -25,7 +29,11 @@ LL | |     };
    | |_____- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-diagnostics.rs:26:14
@@ -38,7 +46,11 @@ LL | |         }
    | |_________- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-diagnostics.rs:39:14
@@ -51,7 +63,11 @@ LL | |         }
    | |_________- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
index 604baa8550b45837b07679775fd87f4b24040ea5..b522dd5709b2946601927dc00480e362887fd5c2 100644 (file)
@@ -10,7 +10,11 @@ LL | | }
    | |_- this function returns a `Result`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u32, ()>`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option.rs:13:6
@@ -24,7 +28,11 @@ LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 7d42c2e4d10d367cdb4938a7493740ff74f039df..dd893cadff77a2e85d9ab0628af77982c7c4c538 100644 (file)
@@ -12,7 +12,11 @@ LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
   --> $DIR/try-operator-on-main.rs:10:5
@@ -21,7 +25,11 @@ LL |     ()?;
    |     ^^^ the `?` operator cannot be applied to type `()`
    |
    = help: the trait `Try` is not implemented for `()`
-   = note: required by `branch`
+note: required by `branch`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-operator-on-main.rs:10:7
@@ -39,7 +47,11 @@ LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<_>` is not implemented for `()`
-   = note: required by `from_residual`
+note: required by `from_residual`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn from_residual(residual: R) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `(): Try` is not satisfied
   --> $DIR/try-operator-on-main.rs:14:25
@@ -57,7 +69,11 @@ LL |     ()?;
    |     ^^^ the `?` operator cannot be applied to type `()`
    |
    = help: the trait `Try` is not implemented for `()`
-   = note: required by `branch`
+note: required by `branch`
+  --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL
+   |
+LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/associated-type-lifetime-ice.rs b/src/test/ui/type-alias-impl-trait/associated-type-lifetime-ice.rs
deleted file mode 100644 (file)
index 967d4c3..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// failure-status: 101
-// rustc-env:RUST_BACKTRACE=0
-// normalize-stderr-test "note: .*\n\n" -> ""
-// normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
-
-// compile-flags: --crate-type=rlib
-
-// Regression test for https://github.com/rust-lang/rust/issues/78450
-
-#![feature(min_type_alias_impl_trait)]
-#![no_std]
-
-pub trait AssociatedImpl {
-    type ImplTrait;
-
-    fn f() -> Self::ImplTrait;
-}
-
-struct S<T>(T);
-
-trait Associated {
-    type A;
-}
-
-// ICE
-impl<'a, T: Associated<A = &'a ()>> AssociatedImpl for S<T> {
-    type ImplTrait = impl core::fmt::Debug;
-
-    fn f() -> Self::ImplTrait {
-    //~^ ERROR unexpected concrete region in borrowck: ReEarlyBound(0, 'a)
-        ()
-    }
-}
diff --git a/src/test/ui/type-alias-impl-trait/associated-type-lifetime-ice.stderr b/src/test/ui/type-alias-impl-trait/associated-type-lifetime-ice.stderr
deleted file mode 100644 (file)
index 64ab7b7..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error: internal compiler error: unexpected concrete region in borrowck: ReEarlyBound(0, 'a)
-  --> $DIR/associated-type-lifetime-ice.rs:29:5
-   |
-LL | /     fn f() -> Self::ImplTrait {
-LL | |
-LL | |         ()
-LL | |     }
-   | |_____^
-   |
-   = error: internal compiler error: unexpected panic
-
-query stack during panic:
-end of query stack
index d0f3be336dccb2b36419e9b5a89dbd879676373e..28ac61a6b984a6165c820bedb20085eeacd6c7a1 100644 (file)
@@ -28,7 +28,7 @@ LL | type WrongGeneric<T> = impl 'static;
            found opaque type `impl Sized`
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:17:30
+  --> $DIR/generic_type_does_not_live_long_enough.rs:16:30
    |
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                              ^^^^^^^^^^^^^^^
index 6394a1f8e8509f1f6b4780f217e46ae2dacab15b..90a753b5a6de16d58995cd5f7433fff64ab5d17a 100644 (file)
@@ -36,16 +36,7 @@ LL | type WrongGeneric<T> = impl 'static;
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                  - help: consider adding an explicit lifetime bound...: `T: 'static`
 
-error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:12:24
-   |
-LL | type WrongGeneric<T> = impl 'static;
-   |                        ^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the type `T` will meet its required lifetime bounds
-
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0308, E0310.
 For more information about an error, try `rustc --explain E0308`.
index 7496d96fa2136aff302dae359aa353e11b8aa9fd..b8ca8e46079aad4c5db20b159b4fcd62da6f5be7 100644 (file)
@@ -19,7 +19,7 @@ LL | type WrongGeneric<T> = impl 'static;
            found opaque type `impl Sized`
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:17:30
+  --> $DIR/generic_type_does_not_live_long_enough.rs:16:30
    |
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                              ^^^^^^^^^^^^^^^
index 49ead8b094c1977f95bcef33e12889ee18c5b28d..e50282201074ecb98c291816f2adac9d038e3d40 100644 (file)
@@ -27,16 +27,7 @@ LL | type WrongGeneric<T> = impl 'static;
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                  - help: consider adding an explicit lifetime bound...: `T: 'static`
 
-error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:12:24
-   |
-LL | type WrongGeneric<T> = impl 'static;
-   |                        ^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the type `T` will meet its required lifetime bounds
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0308, E0310.
 For more information about an error, try `rustc --explain E0308`.
index 3dda34ff668ced241736e9bc2d45f0f54781a0ba..9f647d9e737fecbdb14fcf2a99fcaec1761e0e2a 100644 (file)
@@ -11,7 +11,6 @@ fn main() {
 
 type WrongGeneric<T> = impl 'static;
 //~^ ERROR the parameter type `T` may not live long enough
-//~| ERROR the parameter type `T` may not live long enough
 //~| ERROR: at least one trait must be specified
 
 fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
index 1a03ce79661115b2e44b91f0587e816b4171cb90..a8dd6a93d3dbfd5a34887e76d4bf96c1c0fd8715 100644 (file)
@@ -1,18 +1,10 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
+warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/issue-53096.rs:4:32
    |
-LL | #![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))]
-   |                                ^^^^^^^^^^^^^^^^^^^^^^
+LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
+   |                                ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-53096.rs:4:56
-   |
-LL | #![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))]
-   |                                                        ^^^^^^^^^^^^^^^^^^^^^
-   |
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
 error: fatal error triggered by #[rustc_error]
@@ -21,5 +13,5 @@ error: fatal error triggered by #[rustc_error]
 LL | fn main() {}
    | ^^^^^^^^^
 
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to previous error; 1 warning emitted
 
index c6c7a51618dd3ad405220bb58783f384f514f9d8..4210d0c1cb17a460b703bea2e368bb75849e999b 100644 (file)
@@ -1,12 +1,8 @@
-error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/issue-53096.rs:10:19
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/issue-53096.rs:14:1
    |
-LL | const BAZR: Foo = bar();
-   |                   ^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+LL | fn main() {}
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
index fb621dc0bce9fecfdcba88c9e0edef58f89cad0b..7bb0066b7ef4209ad9202b29490d8c0e66c63391 100644 (file)
@@ -1,14 +1,14 @@
 #![feature(const_impl_trait, const_fn_fn_ptr_basics, rustc_attrs)]
 // revisions: min_tait full_tait
 #![feature(min_type_alias_impl_trait)]
-#![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))]
+#![cfg_attr(full_tait, feature(type_alias_impl_trait))]
 //[full_tait]~^ WARN incomplete
-//[full_tait]~| WARN incomplete
 
 type Foo = impl Fn() -> usize;
-const fn bar() -> Foo { || 0usize }
+const fn bar() -> Foo {
+    || 0usize
+}
 const BAZR: Foo = bar();
-//[min_tait]~^ ERROR not permitted here
 
 #[rustc_error]
-fn main() {} //[full_tait]~ ERROR
+fn main() {} //~ ERROR
index 70d049ffa76bdb367fb8272f8f2dffcf71c67621..b23fed5dadfe77e1eabe97dcdd05deed81d22ba6 100644 (file)
@@ -1,25 +1,17 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
+warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/issue-53678-generator-and-const-fn.rs:4:32
    |
-LL | #![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))]
-   |                                ^^^^^^^^^^^^^^^^^^^^^^
+LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
+   |                                ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
-warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-53678-generator-and-const-fn.rs:4:56
-   |
-LL | #![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))]
-   |                                                        ^^^^^^^^^^^^^^^^^^^^^
-   |
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/issue-53678-generator-and-const-fn.rs:23:1
+  --> $DIR/issue-53678-generator-and-const-fn.rs:22:1
    |
 LL | fn main() {}
    | ^^^^^^^^^
 
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to previous error; 1 warning emitted
 
index a3dea45a6a5ad6901fe72c20428147190e5c3c0b..fabba2183531f9c81d5fd1ecfd3d04782b886e98 100644 (file)
@@ -1,12 +1,8 @@
-error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/issue-53678-generator-and-const-fn.rs:20:36
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/issue-53678-generator-and-const-fn.rs:22:1
    |
-LL | const FOO: GenOnce<usize, usize> = const_generator(10, 100);
-   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+LL | fn main() {}
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
index bf607d29ce46241ea6b833dfb317d5cce2b9b39a..a8215c41826f8f0d4c89a35c503e1b3b0b7ef1b5 100644 (file)
@@ -1,9 +1,8 @@
 #![feature(const_impl_trait, generators, generator_trait, rustc_attrs)]
 // revisions: min_tait full_tait
 #![feature(min_type_alias_impl_trait)]
-#![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))]
+#![cfg_attr(full_tait, feature(type_alias_impl_trait))]
 //[full_tait]~^ WARN incomplete
-//[full_tait]~| WARN incomplete
 
 use std::ops::Generator;
 
@@ -17,7 +16,7 @@ const fn const_generator<Y, R>(yielding: Y, returning: R) -> GenOnce<Y, R> {
     }
 }
 
-const FOO: GenOnce<usize, usize> = const_generator(10, 100); //[min_tait]~ ERROR not permitted here
+const FOO: GenOnce<usize, usize> = const_generator(10, 100);
 
 #[rustc_error]
-fn main() {} //[full_tait]~ ERROR
+fn main() {} //~ ERROR
index 481d66dd8110f5400f6b65738d3fe26ffeebd63a..e2b8b19aeba1bb815d00c8be2e48a06d53cf09c6 100644 (file)
@@ -8,13 +8,13 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
@@ -28,7 +28,7 @@ LL |     type Bar = impl Baz<Self, Self>;
    = note: expected type `for<'r> Fn<(&'r X,)>`
               found type `Fn<(&'static X,)>`
 note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
index d90f328708a7bdeb9a482a1a903952248437ad2f..61e8da91bbaa98d26c237bfd75488ec993c5297a 100644 (file)
@@ -16,52 +16,5 @@ LL |     type Bar = impl Baz<Self, Self>;
    = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected type `for<'r> Fn<(&'r X,)>`
-              found type `Fn<(&'<empty> X,)>`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
-
-error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected type `for<'r> Fn<(&'r X,)>`
-              found type `Fn<(&'<empty> X,)>`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
-
-error: aborting due to 5 previous errors; 1 warning emitted
+error: aborting due to previous error; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0308`.
index 0343a769564af807e62b9dffdd9ce948138abca3..3a4d1d90c039731d4a1396e44dd4402a7922400b 100644 (file)
@@ -1,11 +1,11 @@
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
@@ -19,7 +19,7 @@ LL |     type Bar = impl Baz<Self, Self>;
    = note: expected type `for<'r> Fn<(&'r X,)>`
               found type `Fn<(&'static X,)>`
 note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
index d019f40757eedf9cc8af457cb509f25af57ba602..f65e91e52c7132b90589e3c7e19b9cbefc222f4c 100644 (file)
@@ -7,52 +7,5 @@ LL |     type Bar = impl Baz<Self, Self>;
    = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected type `for<'r> Fn<(&'r X,)>`
-              found type `Fn<(&'<empty> X,)>`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
-
-error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected type `for<'r> Fn<(&'r X,)>`
-              found type `Fn<(&'<empty> X,)>`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
-
-error: aborting due to 5 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
index ccc727e0bf01b10349e95ac0a7378fdbeb2518ba..508ecdd88a482b4c2a7cb569228199459368ce6c 100644 (file)
@@ -19,10 +19,6 @@ struct X;
 impl Foo for X {
     type Bar = impl Baz<Self, Self>;
     //~^ ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR mismatched types
-    //~| ERROR mismatched types
 
     fn bar(&self) -> Self::Bar {
         |x| x
index 4ac7f9423ff419f95f21f8075df2974ff5e5438c..cee5e5a01cc2a5aefc6fb6df8065ac87865bc863 100644 (file)
@@ -9,7 +9,6 @@ trait Bug {
 impl Bug for &() {
     type Item = impl Bug; //~ ERROR `impl Trait` in type aliases is unstable
     //~^ ERROR the trait bound `(): Bug` is not satisfied
-    //~^^ ERROR could not find defining uses
 
     const FUN: fn() -> Self::Item = || ();
     //~^ ERROR type alias impl trait is not permitted here
index 255d381bf06837b9588828780c6fe1ae71132262..a9df74689df295b76bb0c60c79771bf18817c75f 100644 (file)
@@ -8,13 +8,13 @@ LL |     type Item = impl Bug;
    = help: add `#![feature(min_type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/issue-60371.rs:14:37
+  --> $DIR/issue-60371.rs:13:40
    |
 LL |     const FUN: fn() -> Self::Item = || ();
-   |                                     ^^^^^
+   |                                        ^
    |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0277]: the trait bound `(): Bug` is not satisfied
   --> $DIR/issue-60371.rs:10:17
@@ -25,13 +25,7 @@ LL |     type Item = impl Bug;
    = help: the following implementations were found:
              <&() as Bug>
 
-error: could not find defining uses
-  --> $DIR/issue-60371.rs:10:17
-   |
-LL |     type Item = impl Bug;
-   |                 ^^^^^^^^
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0277, E0658.
 For more information about an error, try `rustc --explain E0277`.
index 5edf73c8cedc645a069f7d1522a6809e8133882b..9d3f366ad810a34b431a2c0d56c22e64ed461d1f 100644 (file)
@@ -1,25 +1,17 @@
 warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/issue-60407.rs:3:32
    |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
+LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    |                                ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-60407.rs:3:55
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
-   |                                                       ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/issue-60407.rs:12:1
+  --> $DIR/issue-60407.rs:11:1
    |
 LL | fn main() {
    | ^^^^^^^^^
 
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to previous error; 1 warning emitted
 
index edb8141c1b1042de460106431d0a82dccb6bb04a..1a3ceafa3e29405bf287ff3c19184db6ad45e115 100644 (file)
@@ -1,24 +1,8 @@
-error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/issue-60407.rs:9:39
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/issue-60407.rs:11:1
    |
-LL | static mut TEST: Option<Debuggable> = None;
-   |                                       ^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
-
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/issue-60407.rs:16:1
-   |
-LL | fn foo() -> Debuggable {
-   | ^^^^^^^^^^^^^^^^^^^^^^ expected `[type error]`, got `u32`
-   |
-note: previous use here
-  --> $DIR/issue-60407.rs:9:1
-   |
-LL | static mut TEST: Option<Debuggable> = None;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn main() {
+   | ^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
index afcbf313cc855497827b7f58771429416d32848e..3c6b873b4ca5a23d255f67f2c0124023678b3ae0 100644 (file)
@@ -1,18 +1,18 @@
 // revisions: min_tait full_tait
 #![feature(min_type_alias_impl_trait, rustc_attrs)]
-#![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
+#![cfg_attr(full_tait, feature(type_alias_impl_trait))]
 //[full_tait]~^ WARN incomplete
-//[full_tait]~| WARN incomplete
 
 type Debuggable = impl core::fmt::Debug;
 
-static mut TEST: Option<Debuggable> = None; //[min_tait]~ ERROR not permitted here
+static mut TEST: Option<Debuggable> = None;
 
 #[rustc_error]
-fn main() { //[full_tait]~ ERROR
+fn main() {
+    //~^ ERROR
     unsafe { TEST = Some(foo()) }
 }
 
-fn foo() -> Debuggable { //[min_tait]~ ERROR concrete type differs
+fn foo() -> Debuggable {
     0u32
 }
diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.rs b/src/test/ui/type-alias-impl-trait/issue-63355.rs
new file mode 100644 (file)
index 0000000..8762d18
--- /dev/null
@@ -0,0 +1,50 @@
+#![feature(min_type_alias_impl_trait)]
+#![feature(type_alias_impl_trait)]
+#![allow(incomplete_features)]
+
+pub trait Foo {}
+
+pub trait Bar {
+    type Foo: Foo;
+
+    fn foo() -> Self::Foo;
+}
+
+pub trait Baz {
+    type Foo: Foo;
+    type Bar: Bar<Foo = Self::Foo>;
+
+    fn foo() -> Self::Foo;
+    fn bar() -> Self::Bar;
+}
+
+impl Foo for () {}
+
+impl Bar for () {
+    type Foo = FooImpl;
+
+    fn foo() -> Self::Foo {
+        ()
+    }
+}
+
+// FIXME(#86731): The below is illegal use of `min_type_alias_impl_trait`
+// but the compiler doesn't report it, we should fix it.
+pub type FooImpl = impl Foo;
+pub type BarImpl = impl Bar<Foo = FooImpl>;
+//~^ ERROR: type mismatch resolving `<() as Bar>::Foo == ()`
+
+impl Baz for () {
+    type Foo = FooImpl;
+    type Bar = BarImpl;
+
+    fn foo() -> Self::Foo {
+        ()
+    }
+
+    fn bar() -> Self::Bar {
+        ()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.stderr b/src/test/ui/type-alias-impl-trait/issue-63355.stderr
new file mode 100644 (file)
index 0000000..dc5370a
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0271]: type mismatch resolving `<() as Bar>::Foo == ()`
+  --> $DIR/issue-63355.rs:34:20
+   |
+LL | pub type FooImpl = impl Foo;
+   |                    -------- the found opaque type
+LL | pub type BarImpl = impl Bar<Foo = FooImpl>;
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found opaque type
+   |
+   = note: expected unit type `()`
+            found opaque type `impl Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-65384.rs b/src/test/ui/type-alias-impl-trait/issue-65384.rs
new file mode 100644 (file)
index 0000000..63666c4
--- /dev/null
@@ -0,0 +1,16 @@
+#![feature(min_type_alias_impl_trait)]
+#![feature(type_alias_impl_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait {}
+
+impl MyTrait for () {}
+
+type Bar = impl MyTrait;
+
+impl MyTrait for Bar {}
+//~^ ERROR: cannot implement trait on type alias impl trait
+
+fn bazr() -> Bar { }
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-65384.stderr b/src/test/ui/type-alias-impl-trait/issue-65384.stderr
new file mode 100644 (file)
index 0000000..01d0372
--- /dev/null
@@ -0,0 +1,14 @@
+error: cannot implement trait on type alias impl trait
+  --> $DIR/issue-65384.rs:11:1
+   |
+LL | impl MyTrait for Bar {}
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+note: type alias impl trait defined here
+  --> $DIR/issue-65384.rs:9:12
+   |
+LL | type Bar = impl MyTrait;
+   |            ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index cf668fc6e06665b87399a9724397be46d752c49c..ee26789d204f1309e6417d43167eddd432b66d98 100644 (file)
@@ -1,25 +1,17 @@
 warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/issue-65679-inst-opaque-ty-from-val-twice.rs:5:32
    |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
+LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    |                                ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-65679-inst-opaque-ty-from-val-twice.rs:5:55
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
-   |                                                       ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/issue-65679-inst-opaque-ty-from-val-twice.rs:19:1
+  --> $DIR/issue-65679-inst-opaque-ty-from-val-twice.rs:18:1
    |
 LL | fn main() {
    | ^^^^^^^^^
 
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to previous error; 1 warning emitted
 
index b7f05bd83ed6e31f702afc8b0562dde717083385..d37be640e0b04a6844a3ed1a824f7689e518a3d3 100644 (file)
@@ -2,9 +2,8 @@
 
 // revisions: min_tait full_tait
 #![feature(min_type_alias_impl_trait, rustc_attrs)]
-#![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
+#![cfg_attr(full_tait, feature(type_alias_impl_trait))]
 //[full_tait]~^ WARN incomplete
-//[full_tait]~| WARN incomplete
 
 type T = impl Sized;
 // The concrete type referred by impl-trait-type-alias(`T`) is guaranteed
@@ -16,7 +15,8 @@ type T = impl Sized;
 fn take(_: fn() -> T) {}
 
 #[rustc_error]
-fn main() { //[full_tait]~ ERROR fatal error triggered by #[rustc_error]
+fn main() {
+    //[full_tait]~^ ERROR fatal error triggered by #[rustc_error]
     take(|| {});
     //[min_tait]~^ ERROR not permitted here
     take(|| {});
diff --git a/src/test/ui/type-alias-impl-trait/issue-69323.full.stderr b/src/test/ui/type-alias-impl-trait/issue-69323.full.stderr
new file mode 100644 (file)
index 0000000..71cc6f6
--- /dev/null
@@ -0,0 +1,11 @@
+warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-69323.rs:5:27
+   |
+LL | #![cfg_attr(full, feature(type_alias_impl_trait))]
+   |                           ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/type-alias-impl-trait/issue-69323.rs b/src/test/ui/type-alias-impl-trait/issue-69323.rs
new file mode 100644 (file)
index 0000000..824558c
--- /dev/null
@@ -0,0 +1,19 @@
+// check-pass
+
+// revisions: min full
+#![feature(min_type_alias_impl_trait)]
+#![cfg_attr(full, feature(type_alias_impl_trait))]
+//[full]~^ WARN incomplete
+
+use std::iter::{once, Chain};
+
+fn test1<A: Iterator<Item = &'static str>>(x: A) -> Chain<A, impl Iterator<Item = &'static str>> {
+    x.chain(once(","))
+}
+
+type I<A> = Chain<A, impl Iterator<Item = &'static str>>;
+fn test2<A: Iterator<Item = &'static str>>(x: A) -> I<A> {
+    x.chain(once(","))
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-74761-2.rs b/src/test/ui/type-alias-impl-trait/issue-74761-2.rs
new file mode 100644 (file)
index 0000000..4b0f2af
--- /dev/null
@@ -0,0 +1,19 @@
+#![feature(member_constraints)]
+#![feature(type_alias_impl_trait)]
+//~^ WARN incomplete
+
+pub trait A {
+    type B;
+    fn f(&self) -> Self::B;
+}
+impl<'a, 'b> A for () {
+    //~^ ERROR the lifetime parameter `'a` is not constrained
+    //~| ERROR the lifetime parameter `'b` is not constrained
+    type B = impl core::fmt::Debug;
+    //~^ ERROR is unstable
+
+
+    fn f(&self) -> Self::B {}
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr b/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr
new file mode 100644 (file)
index 0000000..4506a6e
--- /dev/null
@@ -0,0 +1,34 @@
+error[E0658]: `impl Trait` in type aliases is unstable
+  --> $DIR/issue-74761-2.rs:12:14
+   |
+LL |     type B = impl core::fmt::Debug;
+   |              ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(min_type_alias_impl_trait)]` to the crate attributes to enable
+
+warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-74761-2.rs:2:12
+   |
+LL | #![feature(type_alias_impl_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+
+error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-74761-2.rs:9:6
+   |
+LL | impl<'a, 'b> A for () {
+   |      ^^ unconstrained lifetime parameter
+
+error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-74761-2.rs:9:10
+   |
+LL | impl<'a, 'b> A for () {
+   |          ^^ unconstrained lifetime parameter
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0207, E0658.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-78450.rs b/src/test/ui/type-alias-impl-trait/issue-78450.rs
new file mode 100644 (file)
index 0000000..640f929
--- /dev/null
@@ -0,0 +1,27 @@
+// check-pass
+
+#![feature(min_type_alias_impl_trait)]
+#![feature(type_alias_impl_trait)]
+//~^ WARNING: the feature `type_alias_impl_trait` is incomplete
+
+pub trait AssociatedImpl {
+    type ImplTrait;
+
+    fn f() -> Self::ImplTrait;
+}
+
+struct S<T>(T);
+
+trait Associated {
+    type A;
+}
+
+impl<'a, T: Associated<A = &'a ()>> AssociatedImpl for S<T> {
+    type ImplTrait = impl core::fmt::Debug;
+
+    fn f() -> Self::ImplTrait {
+        ()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-78450.stderr b/src/test/ui/type-alias-impl-trait/issue-78450.stderr
new file mode 100644 (file)
index 0000000..efccf62
--- /dev/null
@@ -0,0 +1,11 @@
+warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-78450.rs:4:12
+   |
+LL | #![feature(type_alias_impl_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs b/src/test/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs
new file mode 100644 (file)
index 0000000..80a74eb
--- /dev/null
@@ -0,0 +1,73 @@
+// check-pass
+
+use std::error::Error as StdError;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+pub trait Stream {
+    type Item;
+    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>;
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (0, None)
+    }
+}
+
+pub trait TryStream: Stream {
+    type Ok;
+    type Error;
+
+    fn try_poll_next(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+    ) -> Poll<Option<Result<Self::Ok, Self::Error>>>;
+}
+
+impl<S, T, E> TryStream for S
+where
+    S: ?Sized + Stream<Item = Result<T, E>>,
+{
+    type Ok = T;
+    type Error = E;
+
+    fn try_poll_next(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+    ) -> Poll<Option<Result<Self::Ok, Self::Error>>> {
+        self.poll_next(cx)
+    }
+}
+
+pub trait ServerSentEvent: Sized + Send + Sync + 'static {}
+
+impl<T: Send + Sync + 'static> ServerSentEvent for T {}
+
+struct SseKeepAlive<S> {
+    event_stream: S,
+}
+
+struct SseComment<T>(T);
+
+impl<S> Stream for SseKeepAlive<S>
+where
+    S: TryStream + Send + 'static,
+    S::Ok: ServerSentEvent,
+    S::Error: StdError + Send + Sync + 'static,
+{
+    type Item = Result<SseComment<&'static str>, ()>;
+    fn poll_next(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Option<Self::Item>> {
+        unimplemented!()
+    }
+}
+
+pub fn keep<S>(
+    event_stream: S,
+) -> impl TryStream<Ok = impl ServerSentEvent + Send + 'static, Error = ()> + Send + 'static
+where
+    S: TryStream + Send + 'static,
+    S::Ok: ServerSentEvent + Send,
+    S::Error: StdError + Send + Sync + 'static,
+{
+    SseKeepAlive { event_stream }
+}
+
+fn main() {}
index 38aa18fe40ee71ab57da0c7d82945a0b14904b34..11756017ad846538f7dbdc74ec5760573655d71d 100644 (file)
@@ -5,9 +5,9 @@
 #![feature(min_type_alias_impl_trait)]
 
 type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
-//~^ ERROR could not find defining uses
 
 fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+    //~^ ERROR concrete type differs from previous defining opaque type
     (a.clone(), a)
 }
 
index c00973c0761b058c4410913294223756e8ec9e7f..52b0462de988c28d21c987efc822a0adbae587eb 100644 (file)
@@ -1,8 +1,14 @@
-error: could not find defining uses
-  --> $DIR/multiple-def-uses-in-one-fn2.rs:7:52
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/multiple-def-uses-in-one-fn2.rs:9:1
    |
-LL | type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
-   |                                                    ^^^^^^^^^^^^^
+LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A`, got `B`
+   |
+note: previous use here
+  --> $DIR/multiple-def-uses-in-one-fn2.rs:9:1
+   |
+LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 17e900058113dd8283be89c3672611d5beb32af9..5f25365666c7f9d5b78a1d6899f3840dc5beafb6 100644 (file)
@@ -11,6 +11,7 @@ fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>)
 }
 
 fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
+    //~^ ERROR concrete type differs from previous defining opaque type
     (a, b)
     //~^ ERROR mismatched types
 }
index bbe709dccab4eb6e9404d4b5cba860ad4a7a2592..3d943b77af57da8a7586a1d5a5ba97514ae8886c 100644 (file)
@@ -1,10 +1,11 @@
 error[E0308]: mismatched types
-  --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9
+  --> $DIR/multiple-def-uses-in-one-fn3.rs:15:9
    |
 LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
    |      -                    - found type parameter
    |      |
    |      expected type parameter
+LL |
 LL |     (a, b)
    |         ^ expected type parameter `A`, found type parameter `B`
    |
@@ -13,6 +14,18 @@ LL |     (a, b)
    = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
 
-error: aborting due to previous error
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/multiple-def-uses-in-one-fn3.rs:13:1
+   |
+LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A`, got `[type error]`
+   |
+note: previous use here
+  --> $DIR/multiple-def-uses-in-one-fn3.rs:9:1
+   |
+LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
index 40949c84d2395dec914174b9942124a340a2be78..faddecb21766446bb7bd398efc2aec7a9ae8a4e7 100644 (file)
@@ -1,25 +1,17 @@
 warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/no_inferrable_concrete_type.rs:6:32
    |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
+LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    |                                ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/no_inferrable_concrete_type.rs:6:55
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
-   |                                                       ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
 error: could not find defining uses
-  --> $DIR/no_inferrable_concrete_type.rs:10:12
+  --> $DIR/no_inferrable_concrete_type.rs:9:12
    |
 LL | type Foo = impl Copy;
    |            ^^^^^^^^^
 
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to previous error; 1 warning emitted
 
index d69e4cccdf0af6f3ff4bda9b741947fe106b6f42..3194bd7610712d77379be1be3f246e591f743677 100644 (file)
@@ -1,18 +1,8 @@
-error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/no_inferrable_concrete_type.rs:16:12
-   |
-LL |     let _: Foo = std::mem::transmute(0u8);
-   |            ^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
-
 error: could not find defining uses
-  --> $DIR/no_inferrable_concrete_type.rs:10:12
+  --> $DIR/no_inferrable_concrete_type.rs:9:12
    |
 LL | type Foo = impl Copy;
    |            ^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
index 8ff588ef278ca194dd4e8e894394cc045ca8f095..409eec7250fd0464bf0475966bb41db7718cff76 100644 (file)
@@ -3,15 +3,16 @@
 
 // revisions: min_tait full_tait
 #![feature(min_type_alias_impl_trait)]
-#![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
+#![cfg_attr(full_tait, feature(type_alias_impl_trait))]
 //[full_tait]~^ WARN incomplete
-//[full_tait]~| WARN incomplete
 
 type Foo = impl Copy; //~ could not find defining uses
 
 // make compiler happy about using 'Foo'
-fn bar(x: Foo) -> Foo { x }
+fn bar(x: Foo) -> Foo {
+    x
+}
 
 fn main() {
-    let _: Foo = std::mem::transmute(0u8); //[min_tait]~ ERROR not permitted here
+    let _: Foo = std::mem::transmute(0u8);
 }
index b560c0c918a86df37acd223d89a2b04776fe7152..d5a4fa52dfb7b81fd6ab5498ab20201c884e64bd 100644 (file)
@@ -1,25 +1,17 @@
 warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/structural-match-no-leak.rs:4:32
    |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
+LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    |                                ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/structural-match-no-leak.rs:4:55
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
-   |                                                       ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
 error: `impl Send` cannot be used in patterns
-  --> $DIR/structural-match-no-leak.rs:19:9
+  --> $DIR/structural-match-no-leak.rs:18:9
    |
 LL |         LEAK_FREE => (),
    |         ^^^^^^^^^
 
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to previous error; 1 warning emitted
 
index e962b23a587de1dc7d8725ba9919d5c5b785d482..b7caf8ed2986896cab867d5b85b1332a90dc2317 100644 (file)
@@ -1,12 +1,8 @@
-error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/structural-match-no-leak.rs:15:24
+error: `impl Send` cannot be used in patterns
+  --> $DIR/structural-match-no-leak.rs:18:9
    |
-LL | const LEAK_FREE: Bar = leak_free();
-   |                        ^^^^^^^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+LL |         LEAK_FREE => (),
+   |         ^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
index d0bae30f9963f5231086df4278a4b1f3c543b5da..e2b10e7355fbb820a339b0805ff9c88d87e929e3 100644 (file)
@@ -1,9 +1,8 @@
 #![feature(const_impl_trait)]
 // revisions: min_tait full_tait
 #![feature(min_type_alias_impl_trait)]
-#![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
+#![cfg_attr(full_tait, feature(type_alias_impl_trait))]
 //[full_tait]~^ WARN incomplete
-//[full_tait]~| WARN incomplete
 
 type Bar = impl Send;
 
@@ -12,12 +11,12 @@ type Bar = impl Send;
 const fn leak_free() -> Bar {
     7i32
 }
-const LEAK_FREE: Bar = leak_free(); //[min_tait]~ ERROR not permitted here
+const LEAK_FREE: Bar = leak_free();
 
 fn leak_free_test() {
     match todo!() {
         LEAK_FREE => (),
-        //[full_tait]~^ `impl Send` cannot be used in patterns
+        //~^ `impl Send` cannot be used in patterns
         _ => (),
     }
 }
index b94e06e6d0ef40222aaa33da3c71016ebe34ab7f..d394c99df80293c1f9df69d145479ddb0445892d 100644 (file)
@@ -1,25 +1,17 @@
 warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/structural-match.rs:4:32
    |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
+LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    |                                ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/structural-match.rs:4:55
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
-   |                                                       ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-
 error: `impl Send` cannot be used in patterns
-  --> $DIR/structural-match.rs:20:9
+  --> $DIR/structural-match.rs:19:9
    |
 LL |         VALUE => (),
    |         ^^^^^
 
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to previous error; 1 warning emitted
 
index 36c49a954bda8a0fc449071cec8c8f45659f3e8d..f63b1fb23df7e67003203de2aa1a56ff22d5f8c0 100644 (file)
@@ -1,12 +1,8 @@
-error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/structural-match.rs:16:20
+error: `impl Send` cannot be used in patterns
+  --> $DIR/structural-match.rs:19:9
    |
-LL | const VALUE: Foo = value();
-   |                    ^^^^^^^
-   |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
-   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+LL |         VALUE => (),
+   |         ^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
index daf914cc494aca84e3d7b972f27d73960978d9f5..aed9334b3cc86825b00004ca5d1bf0fcaa1ed8ae 100644 (file)
@@ -1,9 +1,8 @@
 #![feature(const_impl_trait)]
 // revisions: min_tait full_tait
 #![feature(min_type_alias_impl_trait)]
-#![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))]
+#![cfg_attr(full_tait, feature(type_alias_impl_trait))]
 //[full_tait]~^ WARN incomplete
-//[full_tait]~| WARN incomplete
 
 type Foo = impl Send;
 
@@ -13,12 +12,12 @@ struct A;
 const fn value() -> Foo {
     A
 }
-const VALUE: Foo = value(); //[min_tait]~ ERROR not permitted here
+const VALUE: Foo = value();
 
 fn test() {
     match todo!() {
         VALUE => (),
-        //[full_tait]~^ `impl Send` cannot be used in patterns
+        //~^ `impl Send` cannot be used in patterns
         _ => (),
     }
 }
index 894d61502a7210be8d97bf91d135eae9eb0df55c..6f817757cc4b3c3d798167cc2d4b5bb6d7de647a 100644 (file)
@@ -1,5 +1,5 @@
 warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/type-alias-impl-trait-const.rs:5:32
+  --> $DIR/type-alias-impl-trait-const.rs:3:32
    |
 LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    |                                ^^^^^^^^^^^^^^^^^^^^^
@@ -7,13 +7,24 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/type-alias-impl-trait-const.rs:11:12
+error[E0308]: mismatched types
+  --> $DIR/type-alias-impl-trait-const.rs:13:19
    |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
+LL | pub type Foo = impl Debug;
+   |                ---------- the expected opaque type
+...
+LL | const _FOO: Foo = 5;
+   |                   ^ expected opaque type, found integer
    |
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = note: expected opaque type `impl Debug`
+                     found type `{integer}`
 
-warning: 2 warnings emitted
+error: could not find defining uses
+  --> $DIR/type-alias-impl-trait-const.rs:10:16
+   |
+LL | pub type Foo = impl Debug;
+   |                ^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0308`.
index 66e4c242168d151e67314eb6915048c511f75c49..ce98318333b01687b81b9a35ec187501aa95d572 100644 (file)
@@ -1,11 +1,21 @@
-warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/type-alias-impl-trait-const.rs:11:12
+error[E0308]: mismatched types
+  --> $DIR/type-alias-impl-trait-const.rs:13:19
    |
-LL | #![feature(impl_trait_in_bindings)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
+LL | pub type Foo = impl Debug;
+   |                ---------- the expected opaque type
+...
+LL | const _FOO: Foo = 5;
+   |                   ^ expected opaque type, found integer
    |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = note: expected opaque type `impl Debug`
+                     found type `{integer}`
 
-warning: 1 warning emitted
+error: could not find defining uses
+  --> $DIR/type-alias-impl-trait-const.rs:10:16
+   |
+LL | pub type Foo = impl Debug;
+   |                ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
index 0b0551cd96d3b9cd445e4330c5d786dd092d80c2..751512c5dfc03b58561a6b33b3c9ffee5b7e827e 100644 (file)
@@ -1,23 +1,16 @@
-// check-pass
-
 // revisions: min_tait full_tait
 #![feature(min_type_alias_impl_trait)]
 #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
 //[full_tait]~^ WARN incomplete
-// Currently, the `type_alias_impl_trait` feature implicitly
-// depends on `impl_trait_in_bindings` in order to work properly.
-// Specifically, this line requires `impl_trait_in_bindings` to be enabled:
-// https://github.com/rust-lang/rust/blob/481068a707679257e2a738b40987246e0420e787/compiler/rustc_typeck/check/mod.rs#L856
-#![feature(impl_trait_in_bindings)]
-//~^ WARN the feature `impl_trait_in_bindings` is incomplete
 
 // Ensures that `const` items can constrain an opaque `impl Trait`.
 
 use std::fmt::Debug;
 
 pub type Foo = impl Debug;
+//~^ ERROR could not find defining uses
 
 const _FOO: Foo = 5;
+//~^ ERROR mismatched types [E0308]
 
-fn main() {
-}
+fn main() {}
index ddfa31cf6244807f76f90594794b2ce33e7910e6..adf3fa2c8074820084d87d85c672aaa2953271de 100644 (file)
@@ -23,28 +23,37 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
   --> $DIR/type-check-defaults.rs:11:17
    |
 LL | struct Bounds<T:Copy=String>(T);
-   | ----------------^^^^------------
-   | |               |
-   | |               the trait `Copy` is not implemented for `String`
-   | required by `Bounds`
+   |                 ^^^^ the trait `Copy` is not implemented for `String`
+   |
+note: required by `Bounds`
+  --> $DIR/type-check-defaults.rs:11:1
+   |
+LL | struct Bounds<T:Copy=String>(T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `String: Copy` is not satisfied
   --> $DIR/type-check-defaults.rs:14:42
    |
 LL | struct WhereClause<T=String>(T) where T: Copy;
-   | -----------------------------------------^^^^-
-   | |                                        |
-   | |                                        the trait `Copy` is not implemented for `String`
-   | required by `WhereClause`
+   |                                          ^^^^ the trait `Copy` is not implemented for `String`
+   |
+note: required by `WhereClause`
+  --> $DIR/type-check-defaults.rs:14:1
+   |
+LL | struct WhereClause<T=String>(T) where T: Copy;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `String: Copy` is not satisfied
   --> $DIR/type-check-defaults.rs:17:20
    |
 LL | trait TraitBound<T:Copy=String> {}
-   | -------------------^^^^--------
-   | |                  |
-   | |                  the trait `Copy` is not implemented for `String`
-   | required by `TraitBound`
+   |                    ^^^^ the trait `Copy` is not implemented for `String`
+   |
+note: required by `TraitBound`
+  --> $DIR/type-check-defaults.rs:17:1
+   |
+LL | trait TraitBound<T:Copy=String> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/type-check-defaults.rs:21:25
@@ -63,12 +72,14 @@ error[E0277]: cannot add `u8` to `i32`
   --> $DIR/type-check-defaults.rs:24:66
    |
 LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
-   | -----------------------------------------------------------------^^^^^^^
-   | |                                                                |
-   | |                                                                no implementation for `i32 + u8`
-   | required by `ProjectionPred`
+   |                                                                  ^^^^^^^ no implementation for `i32 + u8`
    |
    = help: the trait `Add<u8>` is not implemented for `i32`
+note: required by `ProjectionPred`
+  --> $DIR/type-check-defaults.rs:24:1
+   |
+LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 7 previous errors
 
index e0039f2a316026c57f3a6a298d06cb98cc60a8d7..a6b41520d67b1841786a40990f0c81e66287189b 100644 (file)
@@ -1,12 +1,14 @@
 error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
   --> $DIR/type-params-in-different-spaces-2.rs:10:9
    |
-LL |     fn op(_: T) -> Self;
-   |     -------------------- required by `Tr::op`
-...
 LL |         Tr::op(u)
    |         ^^^^^^ the trait `Tr<U>` is not implemented for `Self`
    |
+note: required by `Tr::op`
+  --> $DIR/type-params-in-different-spaces-2.rs:5:5
+   |
+LL |     fn op(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^
 help: consider further restricting `Self`
    |
 LL |     fn test<U>(u: U) -> Self where Self: Tr<U> {
@@ -15,12 +17,14 @@ LL |     fn test<U>(u: U) -> Self where Self: Tr<U> {
 error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
   --> $DIR/type-params-in-different-spaces-2.rs:16:9
    |
-LL |     fn op(_: T) -> Self;
-   |     -------------------- required by `Tr::op`
-...
 LL |         Tr::op(u)
    |         ^^^^^^ the trait `Tr<U>` is not implemented for `Self`
    |
+note: required by `Tr::op`
+  --> $DIR/type-params-in-different-spaces-2.rs:5:5
+   |
+LL |     fn op(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^
 help: consider further restricting `Self`
    |
 LL |     fn test<U>(u: U) -> Self where Self: Tr<U> {
diff --git a/src/test/ui/typeck-closure-to-unsafe-fn-ptr.rs b/src/test/ui/typeck-closure-to-unsafe-fn-ptr.rs
deleted file mode 100644 (file)
index 2530a1e..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// run-pass
-
-unsafe fn call_unsafe(func: unsafe fn() -> ()) -> () {
-    func()
-}
-
-pub fn main() {
-    unsafe { call_unsafe(|| {}); }
-}
diff --git a/src/test/ui/typeck-fn-to-unsafe-fn-ptr.rs b/src/test/ui/typeck-fn-to-unsafe-fn-ptr.rs
deleted file mode 100644 (file)
index 1e954f5..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// run-pass
-// This tests reification from safe function to `unsafe fn` pointer
-
-fn do_nothing() -> () {}
-
-unsafe fn call_unsafe(func: unsafe fn() -> ()) -> () {
-    func()
-}
-
-pub fn main() {
-    unsafe { call_unsafe(do_nothing); }
-}
diff --git a/src/test/ui/typeck/conversion-methods.rs b/src/test/ui/typeck/conversion-methods.rs
new file mode 100644 (file)
index 0000000..46c2e51
--- /dev/null
@@ -0,0 +1,13 @@
+use std::path::{Path, PathBuf};
+
+
+fn main() {
+    let _tis_an_instants_play: String = "'Tis a fond Ambush—"; //~ ERROR mismatched types
+    let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise");
+    //~^ ERROR mismatched types
+
+    let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here
+    //~^ ERROR mismatched types
+
+    let _prove_piercing_earnest: Vec<usize> = &[1, 2, 3]; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/typeck/conversion-methods.stderr b/src/test/ui/typeck/conversion-methods.stderr
new file mode 100644 (file)
index 0000000..4f47e1f
--- /dev/null
@@ -0,0 +1,46 @@
+error[E0308]: mismatched types
+  --> $DIR/conversion-methods.rs:5:41
+   |
+LL |     let _tis_an_instants_play: String = "'Tis a fond Ambush—";
+   |                                ------   ^^^^^^^^^^^^^^^^^^^^^
+   |                                |        |
+   |                                |        expected struct `String`, found `&str`
+   |                                |        help: try using a conversion method: `"'Tis a fond Ambush—".to_string()`
+   |                                expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/conversion-methods.rs:6:40
+   |
+LL |     let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise");
+   |                              -------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                              |         |
+   |                              |         expected struct `PathBuf`, found `&Path`
+   |                              |         help: try using a conversion method: `Path::new("/ern/her/own/surprise").to_path_buf()`
+   |                              expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/conversion-methods.rs:9:40
+   |
+LL |     let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here
+   |                               ------   ^
+   |                               |        |
+   |                               |        expected struct `String`, found integer
+   |                               |        help: try using a conversion method: `2.to_string()`
+   |                               expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/conversion-methods.rs:12:47
+   |
+LL |     let _prove_piercing_earnest: Vec<usize> = &[1, 2, 3];
+   |                                  ----------   ^^^^^^^^^^
+   |                                  |            |
+   |                                  |            expected struct `Vec`, found `&[{integer}; 3]`
+   |                                  |            help: try using a conversion method: `(&[1, 2, 3]).to_vec()`
+   |                                  expected due to this
+   |
+   = note: expected struct `Vec<usize>`
+           found reference `&[{integer}; 3]`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/issue-74086.rs b/src/test/ui/typeck/issue-74086.rs
new file mode 100644 (file)
index 0000000..1de9cd8
--- /dev/null
@@ -0,0 +1,4 @@
+fn main() {
+    static BUG: fn(_) -> u8 = |_| 8;
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions [E0121]
+}
diff --git a/src/test/ui/typeck/issue-74086.stderr b/src/test/ui/typeck/issue-74086.stderr
new file mode 100644 (file)
index 0000000..ac1752e
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/issue-74086.rs:2:20
+   |
+LL |     static BUG: fn(_) -> u8 = |_| 8;
+   |                    ^ not allowed in type signatures
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
index 8cd34f48835edf27e4903cd4ea1777d794b446ec..0d1534df091fa42ce494c035a02877e7bae7618e 100644 (file)
@@ -5,7 +5,7 @@ pub struct UI {}
 impl UI {
     pub fn run() -> Result<_> {
         //~^ ERROR: this enum takes 2 generic arguments but 1 generic argument was supplied
-        //~| ERROR: the type placeholder `_` is not allowed within types on item signatures
+        //~| ERROR: the type placeholder `_` is not allowed within types on item signatures for return types
         let mut ui = UI {};
         ui.interact();
 
@@ -14,7 +14,7 @@ impl UI {
 
     pub fn interact(&mut self) -> Result<_> {
         //~^ ERROR: this enum takes 2 generic arguments but 1 generic argument was supplied
-        //~| ERROR: the type placeholder `_` is not allowed within types on item signatures
+        //~| ERROR: the type placeholder `_` is not allowed within types on item signatures for return types
         unimplemented!();
     }
 }
index 71f4138c81d56c08f7a8a282b7e24855340435d6..a722c4b5e3ea6b79dfa9df772558898fb68c8581 100644 (file)
@@ -34,13 +34,13 @@ help: add missing generic argument
 LL |     pub fn interact(&mut self) -> Result<_, E> {
    |                                           ^^^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/issue-75883.rs:15:42
    |
 LL |     pub fn interact(&mut self) -> Result<_> {
    |                                          ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/issue-75883.rs:6:28
    |
 LL |     pub fn run() -> Result<_> {
diff --git a/src/test/ui/typeck/issue-75889.rs b/src/test/ui/typeck/issue-75889.rs
new file mode 100644 (file)
index 0000000..84c067e
--- /dev/null
@@ -0,0 +1,6 @@
+// Regression test for #75889.
+
+const FOO: dyn Fn() -> _ = ""; //~ ERROR E0121
+static BOO: dyn Fn() -> _ = ""; //~ ERROR E0121
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-75889.stderr b/src/test/ui/typeck/issue-75889.stderr
new file mode 100644 (file)
index 0000000..de4bdf4
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constant items
+  --> $DIR/issue-75889.rs:3:24
+   |
+LL | const FOO: dyn Fn() -> _ = "";
+   |                        ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static items
+  --> $DIR/issue-75889.rs:4:25
+   |
+LL | static BOO: dyn Fn() -> _ = "";
+   |                         ^ not allowed in type signatures
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
index 6791976196f36a1e72087e2f47dfec5c3360ef3c..99a93b1863d6ed804d2194f26b56f8560b66abe4 100644 (file)
@@ -3,11 +3,11 @@
 pub struct T<'a>(&'a str);
 
 pub fn f<'a>(val: T<'a>) -> _ {
-    //~^ ERROR: the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for return types
     g(val)
 }
 
 pub fn g(_: T<'static>) -> _ {}
-//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for return types
 
 fn main() {}
index aca494520f8b2a1b6bb95a602d6927d13d32739a..5a695fecc29dc7f4e4fbcb136988070be8c69b67 100644 (file)
@@ -1,4 +1,4 @@
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/issue-80779.rs:10:28
    |
 LL | pub fn g(_: T<'static>) -> _ {}
@@ -7,7 +7,7 @@ LL | pub fn g(_: T<'static>) -> _ {}
    |                            not allowed in type signatures
    |                            help: replace with the correct return type: `()`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/issue-80779.rs:5:29
    |
 LL | pub fn f<'a>(val: T<'a>) -> _ {
diff --git a/src/test/ui/typeck/issue-81885.rs b/src/test/ui/typeck/issue-81885.rs
new file mode 100644 (file)
index 0000000..5117f25
--- /dev/null
@@ -0,0 +1,8 @@
+const TEST4: fn() -> _ = 42;
+                  //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
+
+fn main() {
+    const TEST5: fn() -> _ = 42;
+                      //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
+
+}
diff --git a/src/test/ui/typeck/issue-81885.stderr b/src/test/ui/typeck/issue-81885.stderr
new file mode 100644 (file)
index 0000000..8206156
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/issue-81885.rs:1:22
+   |
+LL | const TEST4: fn() -> _ = 42;
+   |                      ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/issue-81885.rs:5:26
+   |
+LL |     const TEST5: fn() -> _ = 42;
+   |                          ^ not allowed in type signatures
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
index b1bec4c0827f9255077a5e8112a504c7847782d9..7c5cf1082be0925cadb8517a02825d3a4e0801dd 100644 (file)
@@ -1,4 +1,4 @@
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
   --> $DIR/issue-83621-placeholder-static-in-extern.rs:4:15
    |
 LL |     static x: _;
diff --git a/src/test/ui/typeck/issue-84160.rs b/src/test/ui/typeck/issue-84160.rs
new file mode 100644 (file)
index 0000000..7b444df
--- /dev/null
@@ -0,0 +1,9 @@
+fn mismatched_types_with_reference(x: &u32) -> &u32 {
+    if false {
+        return x;
+    }
+    return "test";
+    //~^ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-84160.stderr b/src/test/ui/typeck/issue-84160.stderr
new file mode 100644 (file)
index 0000000..24c188b
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-84160.rs:5:12
+   |
+LL | fn mismatched_types_with_reference(x: &u32) -> &u32 {
+   |                                                ---- expected `&u32` because of return type
+...
+LL |     return "test";
+   |            ^^^^^^ expected `u32`, found `str`
+   |
+   = note: expected reference `&u32`
+              found reference `&'static str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/issue-86721-return-expr-ice.rev1.stderr b/src/test/ui/typeck/issue-86721-return-expr-ice.rev1.stderr
new file mode 100644 (file)
index 0000000..b1111fc
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0572]: return statement outside of function body
+  --> $DIR/issue-86721-return-expr-ice.rs:9:22
+   |
+LL |     const U: usize = return;
+   |                      ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0572`.
diff --git a/src/test/ui/typeck/issue-86721-return-expr-ice.rev2.stderr b/src/test/ui/typeck/issue-86721-return-expr-ice.rev2.stderr
new file mode 100644 (file)
index 0000000..f489ae2
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0572]: return statement outside of function body
+  --> $DIR/issue-86721-return-expr-ice.rs:15:20
+   |
+LL |     fn foo(a: [(); return]);
+   |                    ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0572`.
diff --git a/src/test/ui/typeck/issue-86721-return-expr-ice.rs b/src/test/ui/typeck/issue-86721-return-expr-ice.rs
new file mode 100644 (file)
index 0000000..cd7135f
--- /dev/null
@@ -0,0 +1,17 @@
+// Regression test for the ICE described in #86721.
+
+// revisions: rev1 rev2
+#![cfg_attr(any(), rev1, rev2)]
+#![crate_type="lib"]
+
+#[cfg(any(rev1))]
+trait T {
+    const U: usize = return;
+    //[rev1]~^ ERROR: return statement outside of function body [E0572]
+}
+
+#[cfg(any(rev2))]
+trait T2 {
+    fn foo(a: [(); return]);
+    //[rev2]~^ ERROR: return statement outside of function body [E0572]
+}
diff --git a/src/test/ui/typeck/struct-enum-wrong-args.rs b/src/test/ui/typeck/struct-enum-wrong-args.rs
new file mode 100644 (file)
index 0000000..19de4d6
--- /dev/null
@@ -0,0 +1,14 @@
+// Regression test of #86481.
+struct Wrapper(i32);
+struct DoubleWrapper(i32, i32);
+
+fn main() {
+    let _ = Some(3, 2); //~ ERROR this enum variant takes
+    let _ = Ok(3, 6, 2); //~ ERROR this enum variant takes
+    let _ = Ok(); //~ ERROR this enum variant takes
+    let _ = Wrapper(); //~ ERROR this struct takes
+    let _ = Wrapper(5, 2); //~ ERROR this struct takes
+    let _ = DoubleWrapper(); //~ ERROR this struct takes
+    let _ = DoubleWrapper(5); //~ ERROR this struct takes
+    let _ = DoubleWrapper(5, 2, 7); //~ ERROR this struct takes
+}
diff --git a/src/test/ui/typeck/struct-enum-wrong-args.stderr b/src/test/ui/typeck/struct-enum-wrong-args.stderr
new file mode 100644 (file)
index 0000000..d77ef73
--- /dev/null
@@ -0,0 +1,67 @@
+error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
+  --> $DIR/struct-enum-wrong-args.rs:6:13
+   |
+LL |     let _ = Some(3, 2);
+   |             ^^^^ -  - supplied 2 arguments
+   |             |
+   |             expected 1 argument
+
+error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied
+  --> $DIR/struct-enum-wrong-args.rs:7:13
+   |
+LL |     let _ = Ok(3, 6, 2);
+   |             ^^ -  -  - supplied 3 arguments
+   |             |
+   |             expected 1 argument
+
+error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
+  --> $DIR/struct-enum-wrong-args.rs:8:13
+   |
+LL |     let _ = Ok();
+   |             ^^-- supplied 0 arguments
+   |             |
+   |             expected 1 argument
+
+error[E0061]: this struct takes 1 argument but 0 arguments were supplied
+  --> $DIR/struct-enum-wrong-args.rs:9:13
+   |
+LL |     let _ = Wrapper();
+   |             ^^^^^^^-- supplied 0 arguments
+   |             |
+   |             expected 1 argument
+
+error[E0061]: this struct takes 1 argument but 2 arguments were supplied
+  --> $DIR/struct-enum-wrong-args.rs:10:13
+   |
+LL |     let _ = Wrapper(5, 2);
+   |             ^^^^^^^ -  - supplied 2 arguments
+   |             |
+   |             expected 1 argument
+
+error[E0061]: this struct takes 2 arguments but 0 arguments were supplied
+  --> $DIR/struct-enum-wrong-args.rs:11:13
+   |
+LL |     let _ = DoubleWrapper();
+   |             ^^^^^^^^^^^^^-- supplied 0 arguments
+   |             |
+   |             expected 2 arguments
+
+error[E0061]: this struct takes 2 arguments but 1 argument was supplied
+  --> $DIR/struct-enum-wrong-args.rs:12:13
+   |
+LL |     let _ = DoubleWrapper(5);
+   |             ^^^^^^^^^^^^^ - supplied 1 argument
+   |             |
+   |             expected 2 arguments
+
+error[E0061]: this struct takes 2 arguments but 3 arguments were supplied
+  --> $DIR/struct-enum-wrong-args.rs:13:13
+   |
+LL |     let _ = DoubleWrapper(5, 2, 7);
+   |             ^^^^^^^^^^^^^ -  -  - supplied 3 arguments
+   |             |
+   |             expected 2 arguments
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/typeck/type-placeholder-fn-in-const.rs b/src/test/ui/typeck/type-placeholder-fn-in-const.rs
new file mode 100644 (file)
index 0000000..f657bea
--- /dev/null
@@ -0,0 +1,14 @@
+struct MyStruct;
+
+trait Test {
+    const TEST: fn() -> _;
+    //~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for functions [E0121]
+    //~| ERROR: the type placeholder `_` is not allowed within types on item signatures for constants [E0121]
+}
+
+impl Test for MyStruct {
+    const TEST: fn() -> _ = 42;
+    //~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for functions [E0121]
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/type-placeholder-fn-in-const.stderr b/src/test/ui/typeck/type-placeholder-fn-in-const.stderr
new file mode 100644 (file)
index 0000000..62f4db8
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/type-placeholder-fn-in-const.rs:4:25
+   |
+LL |     const TEST: fn() -> _;
+   |                         ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/type-placeholder-fn-in-const.rs:4:25
+   |
+LL |     const TEST: fn() -> _;
+   |                         ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/type-placeholder-fn-in-const.rs:10:25
+   |
+LL |     const TEST: fn() -> _ = 42;
+   |                         ^ not allowed in type signatures
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/typeck/typeck-closure-to-unsafe-fn-ptr.rs b/src/test/ui/typeck/typeck-closure-to-unsafe-fn-ptr.rs
new file mode 100644 (file)
index 0000000..2530a1e
--- /dev/null
@@ -0,0 +1,9 @@
+// run-pass
+
+unsafe fn call_unsafe(func: unsafe fn() -> ()) -> () {
+    func()
+}
+
+pub fn main() {
+    unsafe { call_unsafe(|| {}); }
+}
diff --git a/src/test/ui/typeck/typeck-fn-to-unsafe-fn-ptr.rs b/src/test/ui/typeck/typeck-fn-to-unsafe-fn-ptr.rs
new file mode 100644 (file)
index 0000000..1e954f5
--- /dev/null
@@ -0,0 +1,12 @@
+// run-pass
+// This tests reification from safe function to `unsafe fn` pointer
+
+fn do_nothing() -> () {}
+
+unsafe fn call_unsafe(func: unsafe fn() -> ()) -> () {
+    func()
+}
+
+pub fn main() {
+    unsafe { call_unsafe(do_nothing); }
+}
diff --git a/src/test/ui/typeck/typeck_type_placeholder_1.rs b/src/test/ui/typeck/typeck_type_placeholder_1.rs
new file mode 100644 (file)
index 0000000..ea7aa52
--- /dev/null
@@ -0,0 +1,32 @@
+// run-pass
+
+#![allow(dead_code)]
+// This test checks that the `_` type placeholder works
+// correctly for enabling type inference.
+
+
+struct TestStruct {
+    x: *const isize
+}
+
+unsafe impl Sync for TestStruct {}
+
+static CONSTEXPR: TestStruct = TestStruct{ x: &413 };
+
+
+pub fn main() {
+    let x: Vec<_> = (0..5).collect();
+    let expected: &[usize] = &[0,1,2,3,4];
+    assert_eq!(x, expected);
+
+    let x = (0..5).collect::<Vec<_>>();
+    assert_eq!(x, expected);
+
+    let y: _ = "hello";
+    assert_eq!(y.len(), 5);
+
+    let ptr: &usize = &5;
+    let ptr2 = ptr as *const _;
+
+    assert_eq!(ptr as *const usize as usize, ptr2 as usize);
+}
index bd7cbd444d70409e6f75db1332a4452fd206de87..b6aea9586b8794027fc1e2ada3fa8a149b0724df 100644 (file)
@@ -1,35 +1,35 @@
 error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:158:18
+  --> $DIR/typeck_type_placeholder_item.rs:157:18
    |
 LL | struct BadStruct<_>(_);
    |                  ^ expected identifier, found reserved identifier
 
 error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:161:16
+  --> $DIR/typeck_type_placeholder_item.rs:160:16
    |
 LL | trait BadTrait<_> {}
    |                ^ expected identifier, found reserved identifier
 
 error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:171:19
+  --> $DIR/typeck_type_placeholder_item.rs:170:19
    |
 LL | struct BadStruct1<_, _>(_);
    |                   ^ expected identifier, found reserved identifier
 
 error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:171:22
+  --> $DIR/typeck_type_placeholder_item.rs:170:22
    |
 LL | struct BadStruct1<_, _>(_);
    |                      ^ expected identifier, found reserved identifier
 
 error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:176:19
+  --> $DIR/typeck_type_placeholder_item.rs:175:19
    |
 LL | struct BadStruct2<_, T>(_, T);
    |                   ^ expected identifier, found reserved identifier
 
 error: associated constant in `impl` without body
-  --> $DIR/typeck_type_placeholder_item.rs:209:5
+  --> $DIR/typeck_type_placeholder_item.rs:208:5
    |
 LL |     const C: _;
    |     ^^^^^^^^^^-
@@ -37,7 +37,7 @@ LL |     const C: _;
    |               help: provide a definition for the constant: `= <expr>;`
 
 error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters
-  --> $DIR/typeck_type_placeholder_item.rs:171:22
+  --> $DIR/typeck_type_placeholder_item.rs:170:22
    |
 LL | struct BadStruct1<_, _>(_);
    |                   -  ^ already used
@@ -53,7 +53,7 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:10:14
    |
 LL | fn test() -> _ { 5 }
@@ -62,7 +62,7 @@ LL | fn test() -> _ { 5 }
    |              not allowed in type signatures
    |              help: replace with the correct return type: `i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:13:16
    |
 LL | fn test2() -> (_, _) { (5, 5) }
@@ -72,7 +72,7 @@ LL | fn test2() -> (_, _) { (5, 5) }
    |               |not allowed in type signatures
    |               help: replace with the correct return type: `(i32, i32)`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
   --> $DIR/typeck_type_placeholder_item.rs:16:15
    |
 LL | static TEST3: _ = "test";
@@ -81,7 +81,7 @@ LL | static TEST3: _ = "test";
    |               not allowed in type signatures
    |               help: replace with the correct type: `&str`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
   --> $DIR/typeck_type_placeholder_item.rs:19:15
    |
 LL | static TEST4: _ = 145;
@@ -90,13 +90,13 @@ LL | static TEST4: _ = 145;
    |               not allowed in type signatures
    |               help: replace with the correct type: `i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
   --> $DIR/typeck_type_placeholder_item.rs:22:15
    |
 LL | static TEST5: (_, _) = (1, 2);
    |               ^^^^^^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:25:13
    |
 LL | fn test6(_: _) { }
@@ -107,7 +107,7 @@ help: use type parameters instead
 LL | fn test6<T>(_: T) { }
    |         ^^^    ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:28:18
    |
 LL | fn test6_b<T>(_: _, _: T) { }
@@ -118,7 +118,7 @@ help: use type parameters instead
 LL | fn test6_b<T, U>(_: U, _: T) { }
    |             ^^^     ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:31:30
    |
 LL | fn test6_c<T, K, L, A, B>(_: _, _: (T, K, L, A, B)) { }
@@ -129,7 +129,7 @@ help: use type parameters instead
 LL | fn test6_c<T, K, L, A, B, U>(_: U, _: (T, K, L, A, B)) { }
    |                         ^^^     ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:34:13
    |
 LL | fn test7(x: _) { let _x: usize = x; }
@@ -140,7 +140,7 @@ help: use type parameters instead
 LL | fn test7<T>(x: T) { let _x: usize = x; }
    |         ^^^    ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:37:22
    |
 LL | fn test8(_f: fn() -> _) { }
@@ -149,7 +149,7 @@ LL | fn test8(_f: fn() -> _) { }
    |                      not allowed in type signatures
    |                      help: use type parameters instead: `T`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:37:22
    |
 LL | fn test8(_f: fn() -> _) { }
@@ -160,7 +160,7 @@ help: use type parameters instead
 LL | fn test8<T>(_f: fn() -> T) { }
    |         ^^^             ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:51:26
    |
 LL | fn test11(x: &usize) -> &_ {
@@ -169,7 +169,7 @@ LL | fn test11(x: &usize) -> &_ {
    |                         |not allowed in type signatures
    |                         help: replace with the correct return type: `&'static &'static usize`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:56:52
    |
 LL | unsafe fn test12(x: *const usize) -> *const *const _ {
@@ -178,7 +178,7 @@ LL | unsafe fn test12(x: *const usize) -> *const *const _ {
    |                                      |             not allowed in type signatures
    |                                      help: replace with the correct return type: `*const *const usize`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
   --> $DIR/typeck_type_placeholder_item.rs:70:8
    |
 LL |     a: _,
@@ -201,9 +201,9 @@ error: missing type for `static` item
   --> $DIR/typeck_type_placeholder_item.rs:76:12
    |
 LL |     static A = 42;
-   |            ^ help: provide a type for the item: `A: i32`
+   |            ^ help: provide a type for the static variable: `A: i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
   --> $DIR/typeck_type_placeholder_item.rs:78:15
    |
 LL |     static B: _ = 42;
@@ -212,14 +212,14 @@ LL |     static B: _ = 42;
    |               not allowed in type signatures
    |               help: replace with the correct type: `i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
   --> $DIR/typeck_type_placeholder_item.rs:80:15
    |
 LL |     static C: Option<_> = Some(42);
    |               ^^^^^^^^^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:83:21
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:82:21
    |
 LL |     fn fn_test() -> _ { 5 }
    |                     ^
@@ -227,8 +227,8 @@ LL |     fn fn_test() -> _ { 5 }
    |                     not allowed in type signatures
    |                     help: replace with the correct return type: `i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:86:23
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:85:23
    |
 LL |     fn fn_test2() -> (_, _) { (5, 5) }
    |                      -^--^-
@@ -237,8 +237,8 @@ LL |     fn fn_test2() -> (_, _) { (5, 5) }
    |                      |not allowed in type signatures
    |                      help: replace with the correct return type: `(i32, i32)`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:89:22
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
+  --> $DIR/typeck_type_placeholder_item.rs:88:22
    |
 LL |     static FN_TEST3: _ = "test";
    |                      ^
@@ -246,8 +246,8 @@ LL |     static FN_TEST3: _ = "test";
    |                      not allowed in type signatures
    |                      help: replace with the correct type: `&str`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:92:22
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
+  --> $DIR/typeck_type_placeholder_item.rs:91:22
    |
 LL |     static FN_TEST4: _ = 145;
    |                      ^
@@ -255,14 +255,14 @@ LL |     static FN_TEST4: _ = 145;
    |                      not allowed in type signatures
    |                      help: replace with the correct type: `i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:95:22
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
+  --> $DIR/typeck_type_placeholder_item.rs:94:22
    |
 LL |     static FN_TEST5: (_, _) = (1, 2);
    |                      ^^^^^^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:98:20
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:97:20
    |
 LL |     fn fn_test6(_: _) { }
    |                    ^ not allowed in type signatures
@@ -272,8 +272,8 @@ help: use type parameters instead
 LL |     fn fn_test6<T>(_: T) { }
    |                ^^^    ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:101:20
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:100:20
    |
 LL |     fn fn_test7(x: _) { let _x: usize = x; }
    |                    ^ not allowed in type signatures
@@ -283,8 +283,8 @@ help: use type parameters instead
 LL |     fn fn_test7<T>(x: T) { let _x: usize = x; }
    |                ^^^    ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:104:29
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:103:29
    |
 LL |     fn fn_test8(_f: fn() -> _) { }
    |                             ^
@@ -292,8 +292,8 @@ LL |     fn fn_test8(_f: fn() -> _) { }
    |                             not allowed in type signatures
    |                             help: use type parameters instead: `T`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:104:29
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:103:29
    |
 LL |     fn fn_test8(_f: fn() -> _) { }
    |                             ^ not allowed in type signatures
@@ -303,8 +303,8 @@ help: use type parameters instead
 LL |     fn fn_test8<T>(_f: fn() -> T) { }
    |                ^^^             ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:127:12
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
+  --> $DIR/typeck_type_placeholder_item.rs:126:12
    |
 LL |         a: _,
    |            ^ not allowed in type signatures
@@ -323,21 +323,21 @@ LL |         b: (T, T),
    |
 
 error[E0282]: type annotations needed
-  --> $DIR/typeck_type_placeholder_item.rs:132:18
+  --> $DIR/typeck_type_placeholder_item.rs:131:18
    |
 LL |     fn fn_test11(_: _) -> (_, _) { panic!() }
    |                  ^ cannot infer type
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:132:28
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:131:28
    |
 LL |     fn fn_test11(_: _) -> (_, _) { panic!() }
    |                            ^  ^ not allowed in type signatures
    |                            |
    |                            not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:136:30
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:135:30
    |
 LL |     fn fn_test12(x: i32) -> (_, _) { (x, x) }
    |                             -^--^-
@@ -346,8 +346,8 @@ LL |     fn fn_test12(x: i32) -> (_, _) { (x, x) }
    |                             |not allowed in type signatures
    |                             help: replace with the correct return type: `(i32, i32)`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:139:33
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:138:33
    |
 LL |     fn fn_test13(x: _) -> (i32, _) { (x, x) }
    |                           ------^-
@@ -355,8 +355,8 @@ LL |     fn fn_test13(x: _) -> (i32, _) { (x, x) }
    |                           |     not allowed in type signatures
    |                           help: replace with the correct return type: `(i32, i32)`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:158:21
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
+  --> $DIR/typeck_type_placeholder_item.rs:157:21
    |
 LL | struct BadStruct<_>(_);
    |                     ^ not allowed in type signatures
@@ -366,8 +366,8 @@ help: use type parameters instead
 LL | struct BadStruct<T>(T);
    |                  ^  ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:163:15
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for implementations
+  --> $DIR/typeck_type_placeholder_item.rs:162:15
    |
 LL | impl BadTrait<_> for BadStruct<_> {}
    |               ^                ^ not allowed in type signatures
@@ -379,14 +379,14 @@ help: use type parameters instead
 LL | impl<T> BadTrait<T> for BadStruct<T> {}
    |     ^^^          ^                ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:166:34
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for opaque types
+  --> $DIR/typeck_type_placeholder_item.rs:165:34
    |
 LL | fn impl_trait() -> impl BadTrait<_> {
    |                                  ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:171:25
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
+  --> $DIR/typeck_type_placeholder_item.rs:170:25
    |
 LL | struct BadStruct1<_, _>(_);
    |                         ^ not allowed in type signatures
@@ -396,8 +396,8 @@ help: use type parameters instead
 LL | struct BadStruct1<T, _>(T);
    |                   ^     ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:176:25
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
+  --> $DIR/typeck_type_placeholder_item.rs:175:25
    |
 LL | struct BadStruct2<_, T>(_, T);
    |                         ^ not allowed in type signatures
@@ -407,20 +407,20 @@ help: use type parameters instead
 LL | struct BadStruct2<U, T>(U, T);
    |                   ^     ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:180:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for type aliases
+  --> $DIR/typeck_type_placeholder_item.rs:179:14
    |
 LL | type X = Box<_>;
    |              ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:186:21
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for opaque types
+  --> $DIR/typeck_type_placeholder_item.rs:185:21
    |
 LL | type Y = impl Trait<_>;
    |                     ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:220:31
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:219:31
    |
 LL | fn value() -> Option<&'static _> {
    |               ----------------^-
@@ -428,8 +428,8 @@ LL | fn value() -> Option<&'static _> {
    |               |               not allowed in type signatures
    |               help: replace with the correct return type: `Option<&'static u8>`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:225:10
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/typeck_type_placeholder_item.rs:224:10
    |
 LL | const _: Option<_> = map(value);
    |          ^^^^^^^^^
@@ -437,8 +437,8 @@ LL | const _: Option<_> = map(value);
    |          not allowed in type signatures
    |          help: replace with the correct type: `Option<u8>`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:144:31
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:143:31
    |
 LL |     fn method_test1(&self, x: _);
    |                               ^ not allowed in type signatures
@@ -448,8 +448,8 @@ help: use type parameters instead
 LL |     fn method_test1<T>(&self, x: T);
    |                    ^^^           ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:146:31
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:145:31
    |
 LL |     fn method_test2(&self, x: _) -> _;
    |                               ^     ^ not allowed in type signatures
@@ -461,8 +461,8 @@ help: use type parameters instead
 LL |     fn method_test2<T>(&self, x: T) -> T;
    |                    ^^^           ^     ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:148:31
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:147:31
    |
 LL |     fn method_test3(&self) -> _;
    |                               ^ not allowed in type signatures
@@ -472,8 +472,8 @@ help: use type parameters instead
 LL |     fn method_test3<T>(&self) -> T;
    |                    ^^^           ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:150:26
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:149:26
    |
 LL |     fn assoc_fn_test1(x: _);
    |                          ^ not allowed in type signatures
@@ -483,8 +483,8 @@ help: use type parameters instead
 LL |     fn assoc_fn_test1<T>(x: T);
    |                      ^^^    ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:152:26
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:151:26
    |
 LL |     fn assoc_fn_test2(x: _) -> _;
    |                          ^     ^ not allowed in type signatures
@@ -496,8 +496,8 @@ help: use type parameters instead
 LL |     fn assoc_fn_test2<T>(x: T) -> T;
    |                      ^^^    ^     ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:154:28
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:153:28
    |
 LL |     fn assoc_fn_test3() -> _;
    |                            ^ not allowed in type signatures
@@ -507,20 +507,20 @@ help: use type parameters instead
 LL |     fn assoc_fn_test3<T>() -> T;
    |                      ^^^      ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:194:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
+  --> $DIR/typeck_type_placeholder_item.rs:193:14
    |
 LL |     type B = _;
    |              ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:196:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/typeck_type_placeholder_item.rs:195:14
    |
 LL |     const C: _;
    |              ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:198:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/typeck_type_placeholder_item.rs:197:14
    |
 LL |     const D: _ = 42;
    |              ^
@@ -528,13 +528,13 @@ LL |     const D: _ = 42;
    |              not allowed in type signatures
    |              help: replace with the correct type: `i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:201:26
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
+  --> $DIR/typeck_type_placeholder_item.rs:200:26
    |
 LL |     type F: std::ops::Fn(_);
    |                          ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:44:24
    |
 LL |     fn test9(&self) -> _ { () }
@@ -543,7 +543,7 @@ LL |     fn test9(&self) -> _ { () }
    |                        not allowed in type signatures
    |                        help: replace with the correct return type: `()`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:47:27
    |
 LL |     fn test10(&self, _x : _) { }
@@ -554,7 +554,7 @@ help: use type parameters instead
 LL |     fn test10<T>(&self, _x : T) { }
    |              ^^^             ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:62:24
    |
 LL |     fn clone(&self) -> _ { Test9 }
@@ -563,7 +563,7 @@ LL |     fn clone(&self) -> _ { Test9 }
    |                        not allowed in type signatures
    |                        help: replace with the correct return type: `Test9`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:65:37
    |
 LL |     fn clone_from(&mut self, other: _) { *self = Test9; }
@@ -574,8 +574,8 @@ help: use type parameters instead
 LL |     fn clone_from<T>(&mut self, other: T) { *self = Test9; }
    |                  ^^^                   ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:111:31
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:110:31
    |
 LL |         fn fn_test9(&self) -> _ { () }
    |                               ^
@@ -583,8 +583,8 @@ LL |         fn fn_test9(&self) -> _ { () }
    |                               not allowed in type signatures
    |                               help: replace with the correct return type: `()`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:114:34
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:113:34
    |
 LL |         fn fn_test10(&self, _x : _) { }
    |                                  ^ not allowed in type signatures
@@ -594,8 +594,8 @@ help: use type parameters instead
 LL |         fn fn_test10<T>(&self, _x : T) { }
    |                     ^^^             ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:119:28
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:118:28
    |
 LL |         fn clone(&self) -> _ { FnTest9 }
    |                            ^
@@ -603,8 +603,8 @@ LL |         fn clone(&self) -> _ { FnTest9 }
    |                            not allowed in type signatures
    |                            help: replace with the correct return type: `FnTest9`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:122:41
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:121:41
    |
 LL |         fn clone_from(&mut self, other: _) { *self = FnTest9; }
    |                                         ^ not allowed in type signatures
@@ -614,26 +614,26 @@ help: use type parameters instead
 LL |         fn clone_from<T>(&mut self, other: T) { *self = FnTest9; }
    |                      ^^^                   ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:205:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
+  --> $DIR/typeck_type_placeholder_item.rs:204:14
    |
 LL |     type A = _;
    |              ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:207:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
+  --> $DIR/typeck_type_placeholder_item.rs:206:14
    |
 LL |     type B = _;
    |              ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:209:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/typeck_type_placeholder_item.rs:208:14
    |
 LL |     const C: _;
    |              ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:212:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/typeck_type_placeholder_item.rs:211:14
    |
 LL |     const D: _ = 42;
    |              ^
index afd6aaf4e55ab6b81a3036fe4093a931e065f931..88cc3bfc7f8c3a29d016fdd4c8f4eb07f63de4e1 100644 (file)
@@ -1,35 +1,35 @@
 error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:158:18
+  --> $DIR/typeck_type_placeholder_item.rs:157:18
    |
 LL | struct BadStruct<_>(_);
    |                  ^ expected identifier, found reserved identifier
 
 error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:161:16
+  --> $DIR/typeck_type_placeholder_item.rs:160:16
    |
 LL | trait BadTrait<_> {}
    |                ^ expected identifier, found reserved identifier
 
 error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:171:19
+  --> $DIR/typeck_type_placeholder_item.rs:170:19
    |
 LL | struct BadStruct1<_, _>(_);
    |                   ^ expected identifier, found reserved identifier
 
 error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:171:22
+  --> $DIR/typeck_type_placeholder_item.rs:170:22
    |
 LL | struct BadStruct1<_, _>(_);
    |                      ^ expected identifier, found reserved identifier
 
 error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:176:19
+  --> $DIR/typeck_type_placeholder_item.rs:175:19
    |
 LL | struct BadStruct2<_, T>(_, T);
    |                   ^ expected identifier, found reserved identifier
 
 error: associated constant in `impl` without body
-  --> $DIR/typeck_type_placeholder_item.rs:209:5
+  --> $DIR/typeck_type_placeholder_item.rs:208:5
    |
 LL |     const C: _;
    |     ^^^^^^^^^^-
@@ -37,14 +37,14 @@ LL |     const C: _;
    |               help: provide a definition for the constant: `= <expr>;`
 
 error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters
-  --> $DIR/typeck_type_placeholder_item.rs:171:22
+  --> $DIR/typeck_type_placeholder_item.rs:170:22
    |
 LL | struct BadStruct1<_, _>(_);
    |                   -  ^ already used
    |                   |
    |                   first use of `_`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:10:14
    |
 LL | fn test() -> _ { 5 }
@@ -53,7 +53,7 @@ LL | fn test() -> _ { 5 }
    |              not allowed in type signatures
    |              help: replace with the correct return type: `i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:13:16
    |
 LL | fn test2() -> (_, _) { (5, 5) }
@@ -63,7 +63,7 @@ LL | fn test2() -> (_, _) { (5, 5) }
    |               |not allowed in type signatures
    |               help: replace with the correct return type: `(i32, i32)`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
   --> $DIR/typeck_type_placeholder_item.rs:16:15
    |
 LL | static TEST3: _ = "test";
@@ -72,7 +72,7 @@ LL | static TEST3: _ = "test";
    |               not allowed in type signatures
    |               help: replace with the correct type: `&str`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
   --> $DIR/typeck_type_placeholder_item.rs:19:15
    |
 LL | static TEST4: _ = 145;
@@ -81,13 +81,13 @@ LL | static TEST4: _ = 145;
    |               not allowed in type signatures
    |               help: replace with the correct type: `i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
   --> $DIR/typeck_type_placeholder_item.rs:22:15
    |
 LL | static TEST5: (_, _) = (1, 2);
    |               ^^^^^^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:25:13
    |
 LL | fn test6(_: _) { }
@@ -98,7 +98,7 @@ help: use type parameters instead
 LL | fn test6<T>(_: T) { }
    |         ^^^    ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:28:18
    |
 LL | fn test6_b<T>(_: _, _: T) { }
@@ -109,7 +109,7 @@ help: use type parameters instead
 LL | fn test6_b<T, U>(_: U, _: T) { }
    |             ^^^     ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:31:30
    |
 LL | fn test6_c<T, K, L, A, B>(_: _, _: (T, K, L, A, B)) { }
@@ -120,7 +120,7 @@ help: use type parameters instead
 LL | fn test6_c<T, K, L, A, B, U>(_: U, _: (T, K, L, A, B)) { }
    |                         ^^^     ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:34:13
    |
 LL | fn test7(x: _) { let _x: usize = x; }
@@ -131,7 +131,7 @@ help: use type parameters instead
 LL | fn test7<T>(x: T) { let _x: usize = x; }
    |         ^^^    ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:37:22
    |
 LL | fn test8(_f: fn() -> _) { }
@@ -140,7 +140,7 @@ LL | fn test8(_f: fn() -> _) { }
    |                      not allowed in type signatures
    |                      help: use type parameters instead: `T`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:37:22
    |
 LL | fn test8(_f: fn() -> _) { }
@@ -151,7 +151,7 @@ help: use type parameters instead
 LL | fn test8<T>(_f: fn() -> T) { }
    |         ^^^             ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:51:26
    |
 LL | fn test11(x: &usize) -> &_ {
@@ -160,7 +160,7 @@ LL | fn test11(x: &usize) -> &_ {
    |                         |not allowed in type signatures
    |                         help: replace with the correct return type: `&'static &'static usize`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:56:52
    |
 LL | unsafe fn test12(x: *const usize) -> *const *const _ {
@@ -169,7 +169,7 @@ LL | unsafe fn test12(x: *const usize) -> *const *const _ {
    |                                      |             not allowed in type signatures
    |                                      help: replace with the correct return type: `*const *const usize`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
   --> $DIR/typeck_type_placeholder_item.rs:70:8
    |
 LL |     a: _,
@@ -192,9 +192,9 @@ error: missing type for `static` item
   --> $DIR/typeck_type_placeholder_item.rs:76:12
    |
 LL |     static A = 42;
-   |            ^ help: provide a type for the item: `A: i32`
+   |            ^ help: provide a type for the static variable: `A: i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
   --> $DIR/typeck_type_placeholder_item.rs:78:15
    |
 LL |     static B: _ = 42;
@@ -203,14 +203,14 @@ LL |     static B: _ = 42;
    |               not allowed in type signatures
    |               help: replace with the correct type: `i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
   --> $DIR/typeck_type_placeholder_item.rs:80:15
    |
 LL |     static C: Option<_> = Some(42);
    |               ^^^^^^^^^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:83:21
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:82:21
    |
 LL |     fn fn_test() -> _ { 5 }
    |                     ^
@@ -218,8 +218,8 @@ LL |     fn fn_test() -> _ { 5 }
    |                     not allowed in type signatures
    |                     help: replace with the correct return type: `i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:86:23
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:85:23
    |
 LL |     fn fn_test2() -> (_, _) { (5, 5) }
    |                      -^--^-
@@ -228,8 +228,8 @@ LL |     fn fn_test2() -> (_, _) { (5, 5) }
    |                      |not allowed in type signatures
    |                      help: replace with the correct return type: `(i32, i32)`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:89:22
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
+  --> $DIR/typeck_type_placeholder_item.rs:88:22
    |
 LL |     static FN_TEST3: _ = "test";
    |                      ^
@@ -237,8 +237,8 @@ LL |     static FN_TEST3: _ = "test";
    |                      not allowed in type signatures
    |                      help: replace with the correct type: `&str`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:92:22
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
+  --> $DIR/typeck_type_placeholder_item.rs:91:22
    |
 LL |     static FN_TEST4: _ = 145;
    |                      ^
@@ -246,14 +246,14 @@ LL |     static FN_TEST4: _ = 145;
    |                      not allowed in type signatures
    |                      help: replace with the correct type: `i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:95:22
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
+  --> $DIR/typeck_type_placeholder_item.rs:94:22
    |
 LL |     static FN_TEST5: (_, _) = (1, 2);
    |                      ^^^^^^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:98:20
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:97:20
    |
 LL |     fn fn_test6(_: _) { }
    |                    ^ not allowed in type signatures
@@ -263,8 +263,8 @@ help: use type parameters instead
 LL |     fn fn_test6<T>(_: T) { }
    |                ^^^    ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:101:20
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:100:20
    |
 LL |     fn fn_test7(x: _) { let _x: usize = x; }
    |                    ^ not allowed in type signatures
@@ -274,8 +274,8 @@ help: use type parameters instead
 LL |     fn fn_test7<T>(x: T) { let _x: usize = x; }
    |                ^^^    ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:104:29
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:103:29
    |
 LL |     fn fn_test8(_f: fn() -> _) { }
    |                             ^
@@ -283,8 +283,8 @@ LL |     fn fn_test8(_f: fn() -> _) { }
    |                             not allowed in type signatures
    |                             help: use type parameters instead: `T`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:104:29
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:103:29
    |
 LL |     fn fn_test8(_f: fn() -> _) { }
    |                             ^ not allowed in type signatures
@@ -294,8 +294,8 @@ help: use type parameters instead
 LL |     fn fn_test8<T>(_f: fn() -> T) { }
    |                ^^^             ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:127:12
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
+  --> $DIR/typeck_type_placeholder_item.rs:126:12
    |
 LL |         a: _,
    |            ^ not allowed in type signatures
@@ -314,21 +314,21 @@ LL |         b: (T, T),
    |
 
 error[E0282]: type annotations needed
-  --> $DIR/typeck_type_placeholder_item.rs:132:18
+  --> $DIR/typeck_type_placeholder_item.rs:131:18
    |
 LL |     fn fn_test11(_: _) -> (_, _) { panic!() }
    |                  ^ cannot infer type
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:132:28
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:131:28
    |
 LL |     fn fn_test11(_: _) -> (_, _) { panic!() }
    |                            ^  ^ not allowed in type signatures
    |                            |
    |                            not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:136:30
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:135:30
    |
 LL |     fn fn_test12(x: i32) -> (_, _) { (x, x) }
    |                             -^--^-
@@ -337,8 +337,8 @@ LL |     fn fn_test12(x: i32) -> (_, _) { (x, x) }
    |                             |not allowed in type signatures
    |                             help: replace with the correct return type: `(i32, i32)`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:139:33
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:138:33
    |
 LL |     fn fn_test13(x: _) -> (i32, _) { (x, x) }
    |                           ------^-
@@ -346,8 +346,8 @@ LL |     fn fn_test13(x: _) -> (i32, _) { (x, x) }
    |                           |     not allowed in type signatures
    |                           help: replace with the correct return type: `(i32, i32)`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:158:21
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
+  --> $DIR/typeck_type_placeholder_item.rs:157:21
    |
 LL | struct BadStruct<_>(_);
    |                     ^ not allowed in type signatures
@@ -357,8 +357,8 @@ help: use type parameters instead
 LL | struct BadStruct<T>(T);
    |                  ^  ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:163:15
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for implementations
+  --> $DIR/typeck_type_placeholder_item.rs:162:15
    |
 LL | impl BadTrait<_> for BadStruct<_> {}
    |               ^                ^ not allowed in type signatures
@@ -370,14 +370,14 @@ help: use type parameters instead
 LL | impl<T> BadTrait<T> for BadStruct<T> {}
    |     ^^^          ^                ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:166:34
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for opaque types
+  --> $DIR/typeck_type_placeholder_item.rs:165:34
    |
 LL | fn impl_trait() -> impl BadTrait<_> {
    |                                  ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:171:25
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
+  --> $DIR/typeck_type_placeholder_item.rs:170:25
    |
 LL | struct BadStruct1<_, _>(_);
    |                         ^ not allowed in type signatures
@@ -387,8 +387,8 @@ help: use type parameters instead
 LL | struct BadStruct1<T, _>(T);
    |                   ^     ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:176:25
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
+  --> $DIR/typeck_type_placeholder_item.rs:175:25
    |
 LL | struct BadStruct2<_, T>(_, T);
    |                         ^ not allowed in type signatures
@@ -398,20 +398,20 @@ help: use type parameters instead
 LL | struct BadStruct2<U, T>(U, T);
    |                   ^     ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:180:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for type aliases
+  --> $DIR/typeck_type_placeholder_item.rs:179:14
    |
 LL | type X = Box<_>;
    |              ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:186:21
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for opaque types
+  --> $DIR/typeck_type_placeholder_item.rs:185:21
    |
 LL | type Y = impl Trait<_>;
    |                     ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:220:31
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:219:31
    |
 LL | fn value() -> Option<&'static _> {
    |               ----------------^-
@@ -419,8 +419,8 @@ LL | fn value() -> Option<&'static _> {
    |               |               not allowed in type signatures
    |               help: replace with the correct return type: `Option<&'static u8>`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:225:10
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/typeck_type_placeholder_item.rs:224:10
    |
 LL | const _: Option<_> = map(value);
    |          ^^^^^^^^^
@@ -428,8 +428,8 @@ LL | const _: Option<_> = map(value);
    |          not allowed in type signatures
    |          help: replace with the correct type: `Option<u8>`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:144:31
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:143:31
    |
 LL |     fn method_test1(&self, x: _);
    |                               ^ not allowed in type signatures
@@ -439,8 +439,8 @@ help: use type parameters instead
 LL |     fn method_test1<T>(&self, x: T);
    |                    ^^^           ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:146:31
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:145:31
    |
 LL |     fn method_test2(&self, x: _) -> _;
    |                               ^     ^ not allowed in type signatures
@@ -452,8 +452,8 @@ help: use type parameters instead
 LL |     fn method_test2<T>(&self, x: T) -> T;
    |                    ^^^           ^     ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:148:31
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:147:31
    |
 LL |     fn method_test3(&self) -> _;
    |                               ^ not allowed in type signatures
@@ -463,8 +463,8 @@ help: use type parameters instead
 LL |     fn method_test3<T>(&self) -> T;
    |                    ^^^           ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:150:26
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:149:26
    |
 LL |     fn assoc_fn_test1(x: _);
    |                          ^ not allowed in type signatures
@@ -474,8 +474,8 @@ help: use type parameters instead
 LL |     fn assoc_fn_test1<T>(x: T);
    |                      ^^^    ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:152:26
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:151:26
    |
 LL |     fn assoc_fn_test2(x: _) -> _;
    |                          ^     ^ not allowed in type signatures
@@ -487,8 +487,8 @@ help: use type parameters instead
 LL |     fn assoc_fn_test2<T>(x: T) -> T;
    |                      ^^^    ^     ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:154:28
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:153:28
    |
 LL |     fn assoc_fn_test3() -> _;
    |                            ^ not allowed in type signatures
@@ -498,20 +498,20 @@ help: use type parameters instead
 LL |     fn assoc_fn_test3<T>() -> T;
    |                      ^^^      ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:194:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
+  --> $DIR/typeck_type_placeholder_item.rs:193:14
    |
 LL |     type B = _;
    |              ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:196:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/typeck_type_placeholder_item.rs:195:14
    |
 LL |     const C: _;
    |              ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:198:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/typeck_type_placeholder_item.rs:197:14
    |
 LL |     const D: _ = 42;
    |              ^
@@ -519,13 +519,13 @@ LL |     const D: _ = 42;
    |              not allowed in type signatures
    |              help: replace with the correct type: `i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:201:26
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
+  --> $DIR/typeck_type_placeholder_item.rs:200:26
    |
 LL |     type F: std::ops::Fn(_);
    |                          ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:44:24
    |
 LL |     fn test9(&self) -> _ { () }
@@ -534,7 +534,7 @@ LL |     fn test9(&self) -> _ { () }
    |                        not allowed in type signatures
    |                        help: replace with the correct return type: `()`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:47:27
    |
 LL |     fn test10(&self, _x : _) { }
@@ -545,7 +545,7 @@ help: use type parameters instead
 LL |     fn test10<T>(&self, _x : T) { }
    |              ^^^             ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:62:24
    |
 LL |     fn clone(&self) -> _ { Test9 }
@@ -554,7 +554,7 @@ LL |     fn clone(&self) -> _ { Test9 }
    |                        not allowed in type signatures
    |                        help: replace with the correct return type: `Test9`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:65:37
    |
 LL |     fn clone_from(&mut self, other: _) { *self = Test9; }
@@ -565,8 +565,8 @@ help: use type parameters instead
 LL |     fn clone_from<T>(&mut self, other: T) { *self = Test9; }
    |                  ^^^                   ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:111:31
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:110:31
    |
 LL |         fn fn_test9(&self) -> _ { () }
    |                               ^
@@ -574,8 +574,8 @@ LL |         fn fn_test9(&self) -> _ { () }
    |                               not allowed in type signatures
    |                               help: replace with the correct return type: `()`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:114:34
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:113:34
    |
 LL |         fn fn_test10(&self, _x : _) { }
    |                                  ^ not allowed in type signatures
@@ -585,8 +585,8 @@ help: use type parameters instead
 LL |         fn fn_test10<T>(&self, _x : T) { }
    |                     ^^^             ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:119:28
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:118:28
    |
 LL |         fn clone(&self) -> _ { FnTest9 }
    |                            ^
@@ -594,8 +594,8 @@ LL |         fn clone(&self) -> _ { FnTest9 }
    |                            not allowed in type signatures
    |                            help: replace with the correct return type: `FnTest9`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:122:41
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:121:41
    |
 LL |         fn clone_from(&mut self, other: _) { *self = FnTest9; }
    |                                         ^ not allowed in type signatures
@@ -605,26 +605,26 @@ help: use type parameters instead
 LL |         fn clone_from<T>(&mut self, other: T) { *self = FnTest9; }
    |                      ^^^                   ^
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:205:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
+  --> $DIR/typeck_type_placeholder_item.rs:204:14
    |
 LL |     type A = _;
    |              ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:207:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
+  --> $DIR/typeck_type_placeholder_item.rs:206:14
    |
 LL |     type B = _;
    |              ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:209:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/typeck_type_placeholder_item.rs:208:14
    |
 LL |     const C: _;
    |              ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:212:14
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/typeck_type_placeholder_item.rs:211:14
    |
 LL |     const D: _ = 42;
    |              ^
index 8a52556ed346e1564b37f57e64ad47577aadf6ee..55f5d44d46b37c27dadfc6ef0014c352087d5e0f 100644 (file)
@@ -8,67 +8,67 @@
 // inference by using the `_` type placeholder.
 
 fn test() -> _ { 5 }
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
 
 fn test2() -> (_, _) { (5, 5) }
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
 
 static TEST3: _ = "test";
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
 
 static TEST4: _ = 145;
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
 
 static TEST5: (_, _) = (1, 2);
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
 
 fn test6(_: _) { }
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 
 fn test6_b<T>(_: _, _: T) { }
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 
 fn test6_c<T, K, L, A, B>(_: _, _: (T, K, L, A, B)) { }
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 
 fn test7(x: _) { let _x: usize = x; }
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 
 fn test8(_f: fn() -> _) { }
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
-//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
+//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 
 struct Test9;
 
 impl Test9 {
     fn test9(&self) -> _ { () }
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
 
     fn test10(&self, _x : _) { }
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 }
 
 fn test11(x: &usize) -> &_ {
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
     &x
 }
 
 unsafe fn test12(x: *const usize) -> *const *const _ {
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
     &x
 }
 
 impl Clone for Test9 {
     fn clone(&self) -> _ { Test9 }
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
 
     fn clone_from(&mut self, other: _) { *self = Test9; }
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 }
 
 struct Test10 {
     a: _,
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs
     b: (_, _),
 }
 
@@ -76,95 +76,94 @@ pub fn main() {
     static A = 42;
     //~^ ERROR missing type for `static` item
     static B: _ = 42;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
     static C: Option<_> = Some(42);
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
-
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
     fn fn_test() -> _ { 5 }
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
 
     fn fn_test2() -> (_, _) { (5, 5) }
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
 
     static FN_TEST3: _ = "test";
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
 
     static FN_TEST4: _ = 145;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
 
     static FN_TEST5: (_, _) = (1, 2);
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
 
     fn fn_test6(_: _) { }
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 
     fn fn_test7(x: _) { let _x: usize = x; }
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 
     fn fn_test8(_f: fn() -> _) { }
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
-    //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
+    //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 
     struct FnTest9;
 
     impl FnTest9 {
         fn fn_test9(&self) -> _ { () }
-        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
 
         fn fn_test10(&self, _x : _) { }
-        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
     }
 
     impl Clone for FnTest9 {
         fn clone(&self) -> _ { FnTest9 }
-        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
 
         fn clone_from(&mut self, other: _) { *self = FnTest9; }
-        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
     }
 
     struct FnTest10 {
         a: _,
-        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs
         b: (_, _),
     }
 
     fn fn_test11(_: _) -> (_, _) { panic!() }
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
     //~| ERROR type annotations needed
 
     fn fn_test12(x: i32) -> (_, _) { (x, x) }
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
 
     fn fn_test13(x: _) -> (i32, _) { (x, x) }
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
 }
 
 trait T {
     fn method_test1(&self, x: _);
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
     fn method_test2(&self, x: _) -> _;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
     fn method_test3(&self) -> _;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
     fn assoc_fn_test1(x: _);
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
     fn assoc_fn_test2(x: _) -> _;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
     fn assoc_fn_test3() -> _;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 }
 
 struct BadStruct<_>(_);
 //~^ ERROR expected identifier, found reserved identifier `_`
-//~| ERROR the type placeholder `_` is not allowed within types on item signatures
+//~| ERROR the type placeholder `_` is not allowed within types on item signatures for structs
 trait BadTrait<_> {}
 //~^ ERROR expected identifier, found reserved identifier `_`
 impl BadTrait<_> for BadStruct<_> {}
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for implementations
 
 fn impl_trait() -> impl BadTrait<_> {
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for opaque types
     unimplemented!()
 }
 
@@ -172,19 +171,19 @@ struct BadStruct1<_, _>(_);
 //~^ ERROR expected identifier, found reserved identifier `_`
 //~| ERROR expected identifier, found reserved identifier `_`
 //~| ERROR the name `_` is already used
-//~| ERROR the type placeholder `_` is not allowed within types on item signatures
+//~| ERROR the type placeholder `_` is not allowed within types on item signatures for structs
 struct BadStruct2<_, T>(_, T);
 //~^ ERROR expected identifier, found reserved identifier `_`
-//~| ERROR the type placeholder `_` is not allowed within types on item signatures
+//~| ERROR the type placeholder `_` is not allowed within types on item signatures for structs
 
 type X = Box<_>;
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for type aliases
 
 struct Struct;
 trait Trait<T> {}
 impl Trait<usize> for Struct {}
 type Y = impl Trait<_>;
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for opaque types
 fn foo() -> Y {
     Struct
 }
@@ -192,25 +191,25 @@ fn foo() -> Y {
 trait Qux {
     type A;
     type B = _;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types
     const C: _;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
     const D: _ = 42;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
     // type E: _; // FIXME: make the parser propagate the existence of `B`
     type F: std::ops::Fn(_);
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types
 }
 impl Qux for Struct {
     type A = _;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types
     type B = _;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types
     const C: _;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
     //~| ERROR associated constant in `impl` without body
     const D: _ = 42;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
 }
 
 fn map<T>(_: fn() -> Option<&'static T>) -> Option<T> {
@@ -218,9 +217,9 @@ fn map<T>(_: fn() -> Option<&'static T>) -> Option<T> {
 }
 
 fn value() -> Option<&'static _> {
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
     Option::<&'static u8>::None
 }
 
 const _: Option<_> = map(value);
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
index 0c890f88c60dca2530554a8030b06935d8bb0b41..3af5cf926abf0a4eb2c076d56eb7c854b0fd6f83 100644 (file)
@@ -2,27 +2,27 @@
 // using the `_` type placeholder.
 
 fn test1() -> _ { Some(42) }
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
 
 const TEST2: _ = 42u32;
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
 
 const TEST3: _ = Some(42);
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
 
 const TEST4: fn() -> _ = 42;
-//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
 
 trait Test5 {
     const TEST5: _ = 42;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
 }
 
 struct Test6;
 
 impl Test6 {
     const TEST6: _ = 13;
-    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
 }
 
 pub fn main() {
index 2b64df774b08f2f6b23b6060240ab994ffee1cc4..1b56b1033a8c1f23d5a81460848452d290f83b5a 100644 (file)
@@ -1,4 +1,4 @@
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item_help.rs:4:15
    |
 LL | fn test1() -> _ { Some(42) }
@@ -7,7 +7,7 @@ LL | fn test1() -> _ { Some(42) }
    |               not allowed in type signatures
    |               help: replace with the correct return type: `Option<i32>`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
   --> $DIR/typeck_type_placeholder_item_help.rs:7:14
    |
 LL | const TEST2: _ = 42u32;
@@ -16,7 +16,7 @@ LL | const TEST2: _ = 42u32;
    |              not allowed in type signatures
    |              help: replace with the correct type: `u32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
   --> $DIR/typeck_type_placeholder_item_help.rs:10:14
    |
 LL | const TEST3: _ = Some(42);
@@ -25,13 +25,13 @@ LL | const TEST3: _ = Some(42);
    |              not allowed in type signatures
    |              help: replace with the correct type: `Option<i32>`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item_help.rs:13:22
    |
 LL | const TEST4: fn() -> _ = 42;
    |                      ^ not allowed in type signatures
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
   --> $DIR/typeck_type_placeholder_item_help.rs:17:18
    |
 LL |     const TEST5: _ = 42;
@@ -40,7 +40,7 @@ LL |     const TEST5: _ = 42;
    |                  not allowed in type signatures
    |                  help: replace with the correct type: `i32`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
   --> $DIR/typeck_type_placeholder_item_help.rs:24:18
    |
 LL |     const TEST6: _ = 13;
diff --git a/src/test/ui/typeck_type_placeholder_1.rs b/src/test/ui/typeck_type_placeholder_1.rs
deleted file mode 100644 (file)
index ea7aa52..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// run-pass
-
-#![allow(dead_code)]
-// This test checks that the `_` type placeholder works
-// correctly for enabling type inference.
-
-
-struct TestStruct {
-    x: *const isize
-}
-
-unsafe impl Sync for TestStruct {}
-
-static CONSTEXPR: TestStruct = TestStruct{ x: &413 };
-
-
-pub fn main() {
-    let x: Vec<_> = (0..5).collect();
-    let expected: &[usize] = &[0,1,2,3,4];
-    assert_eq!(x, expected);
-
-    let x = (0..5).collect::<Vec<_>>();
-    assert_eq!(x, expected);
-
-    let y: _ = "hello";
-    assert_eq!(y.len(), 5);
-
-    let ptr: &usize = &5;
-    let ptr2 = ptr as *const _;
-
-    assert_eq!(ptr as *const usize as usize, ptr2 as usize);
-}
index a2bf963044582278e921e1872847b920b8de665f..e30e4f5e7d3fd9caea78d069b224b8c6a521d9f8 100644 (file)
@@ -5,7 +5,11 @@ LL |     <i32 as Add<u32>>::add(1, 2);
    |     ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32`
    |
    = help: the trait `Add<u32>` is not implemented for `i32`
-   = note: required by `add`
+note: required by `add`
+  --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
+   |
+LL |     fn add(self, rhs: Rhs) -> Self::Output;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/ufcs-qpath-self-mismatch.rs:6:28
index 2079f6fd53173d7ddd713634e7f11b79e3c8d0ad..be6ed8d56232e6b454300e0f38d73698926b3d6e 100644 (file)
@@ -1,14 +1,16 @@
 error[E0277]: the trait bound `[(); 0]: Foo` is not satisfied
   --> $DIR/unevaluated_fixed_size_array_len.rs:12:5
    |
-LL |     fn foo();
-   |     --------- required by `Foo::foo`
-...
 LL |     <[(); 0] as Foo>::foo()
    |     ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[(); 0]`
    |
    = help: the following implementations were found:
              <[(); 1] as Foo>
+note: required by `Foo::foo`
+  --> $DIR/unevaluated_fixed_size_array_len.rs:4:5
+   |
+LL |     fn foo();
+   |     ^^^^^^^^^
 
 error: aborting due to previous error
 
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..c2fd854
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied
+  --> $DIR/union-derive-eq.rs:16:5
+   |
+LL | #[derive(Eq)]
+   |          -- in this derive macro expansion
+LL | union U2 {
+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..c2fd854
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied
+  --> $DIR/union-derive-eq.rs:16:5
+   |
+LL | #[derive(Eq)]
+   |          -- in this derive macro expansion
+LL | union U2 {
+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..cd85778
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+  --> $DIR/union-generic.rs:11:13
+   |
+LL |     let u = U { a: Rc::new(0u32) };
+   |             ^ the trait `Copy` is not implemented for `Rc<u32>`
+   |
+note: required by `U`
+  --> $DIR/union-generic.rs:6:1
+   |
+LL | union U<T: Copy> {
+   | ^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+  --> $DIR/union-generic.rs:13:13
+   |
+LL |     let u = U::<Rc<u32>> { a: Default::default() };
+   |             ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
+   |
+note: required by `U`
+  --> $DIR/union-generic.rs:6:1
+   |
+LL | union U<T: Copy> {
+   | ^^^^^^^^^^^^^^^^
+
+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..cd85778
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+  --> $DIR/union-generic.rs:11:13
+   |
+LL |     let u = U { a: Rc::new(0u32) };
+   |             ^ the trait `Copy` is not implemented for `Rc<u32>`
+   |
+note: required by `U`
+  --> $DIR/union-generic.rs:6:1
+   |
+LL | union U<T: Copy> {
+   | ^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+  --> $DIR/union-generic.rs:13:13
+   |
+LL |     let u = U::<Rc<u32>> { a: Default::default() };
+   |             ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
+   |
+note: required by `U`
+  --> $DIR/union-generic.rs:6:1
+   |
+LL | union U<T: Copy> {
+   | ^^^^^^^^^^^^^^^^
+
+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/unpretty-expr-fn-arg.rs b/src/test/ui/unpretty-expr-fn-arg.rs
new file mode 100644 (file)
index 0000000..6e1132a
--- /dev/null
@@ -0,0 +1,13 @@
+// Regression test for the ICE described in #82328. The pretty-printer for
+// `-Zunpretty=hir,typed` would previously retrieve type-checking results
+// when entering a body, which means that type information was not available
+// for expressions occurring in function signatures, as in the `foo` example
+// below, leading to an ICE.
+
+// check-pass
+// compile-flags: -Zunpretty=hir,typed
+#![allow(dead_code)]
+
+fn main() {}
+
+fn foo(-128..=127: i8) {}
diff --git a/src/test/ui/unpretty-expr-fn-arg.stdout b/src/test/ui/unpretty-expr-fn-arg.stdout
new file mode 100644 (file)
index 0000000..cb04dfe
--- /dev/null
@@ -0,0 +1,17 @@
+// Regression test for the ICE described in #82328. The pretty-printer for
+// `-Zunpretty=hir,typed` would previously retrieve type-checking results
+// when entering a body, which means that type information was not available
+// for expressions occurring in function signatures, as in the `foo` example
+// below, leading to an ICE.
+
+// check-pass
+// compile-flags: -Zunpretty=hir,typed
+#![allow(dead_code)]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+
+fn main() ({ } as ())
+
+fn foo((-(128 as i8) as i8) ...(127 as i8): i8) ({ } as ())
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/ranged_ints2.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints2.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..427843f
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints2.rs:11:13
+   |
+LL |     let y = &mut x.0;
+   |             ^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
index 68ba120b279c02a80bdde064cea4bd3fe7f581ba..9a6bb18f9266494cd926f8f4d05b84d5cfeac803 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![feature(rustc_attrs)]
 
 #[rustc_layout_scalar_valid_range_start(1)]
diff --git a/src/test/ui/unsafe/ranged_ints2.stderr b/src/test/ui/unsafe/ranged_ints2.stderr
deleted file mode 100644 (file)
index ee1d1f1..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
-  --> $DIR/ranged_ints2.rs:8:13
-   |
-LL |     let y = &mut x.0;
-   |             ^^^^^^^^ mutation of layout constrained field
-   |
-   = note: mutating layout constrained fields cannot statically be checked for valid values
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..427843f
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints2.rs:11:13
+   |
+LL |     let y = &mut x.0;
+   |             ^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..c16550a
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/ranged_ints2_const.rs:14:13
+   |
+LL |     let y = &mut x.0;
+   |             ^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/ranged_ints2_const.rs:21:22
+   |
+LL |     let y = unsafe { &mut x.0 };
+   |                      ^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/ranged_ints2_const.rs:27:22
+   |
+LL |     unsafe { let y = &mut x.0; }
+   |                      ^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints2_const.rs:14:13
+   |
+LL |     let y = &mut x.0;
+   |             ^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0133, E0658.
+For more information about an error, try `rustc --explain E0133`.
index b7178c2b52bfbff8424977ee5d71a5c90ac0cbf7..56f5407bb6ebe6dc1e54238f1a2f293d7f9027c1 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![feature(rustc_attrs)]
 
 #[rustc_layout_scalar_valid_range_start(1)]
diff --git a/src/test/ui/unsafe/ranged_ints2_const.stderr b/src/test/ui/unsafe/ranged_ints2_const.stderr
deleted file mode 100644 (file)
index a0dc950..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-error[E0658]: mutable references are not allowed in constant functions
-  --> $DIR/ranged_ints2_const.rs:11:13
-   |
-LL |     let y = &mut x.0;
-   |             ^^^^^^^^
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-
-error[E0658]: mutable references are not allowed in constant functions
-  --> $DIR/ranged_ints2_const.rs:18:22
-   |
-LL |     let y = unsafe { &mut x.0 };
-   |                      ^^^^^^^^
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-
-error[E0658]: mutable references are not allowed in constant functions
-  --> $DIR/ranged_ints2_const.rs:24:22
-   |
-LL |     unsafe { let y = &mut x.0; }
-   |                      ^^^^^^^^
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-
-error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
-  --> $DIR/ranged_ints2_const.rs:11:13
-   |
-LL |     let y = &mut x.0;
-   |             ^^^^^^^^ mutation of layout constrained field
-   |
-   = note: mutating layout constrained fields cannot statically be checked for valid values
-
-error: aborting due to 4 previous errors
-
-Some errors have detailed explanations: E0133, E0658.
-For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..b3f139f
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints2_const.rs:14:13
+   |
+LL |     let y = &mut x.0;
+   |             ^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/ranged_ints2_const.rs:14:13
+   |
+LL |     let y = &mut x.0;
+   |             ^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/ranged_ints2_const.rs:21:22
+   |
+LL |     let y = unsafe { &mut x.0 };
+   |                      ^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/ranged_ints2_const.rs:27:22
+   |
+LL |     unsafe { let y = &mut x.0; }
+   |                      ^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0133, E0658.
+For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints3.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..9eec0b0
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints3.rs:13:13
+   |
+LL |     let y = &x.0;
+   |             ^^^^ borrow of layout constrained field with interior mutability
+   |
+   = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
index 47d67fac6785c651f030b15970cc7d16caea7dd4..76d4bfe95307d763e9b52742b3c2a919fc822a05 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![feature(rustc_attrs)]
 
 use std::cell::Cell;
diff --git a/src/test/ui/unsafe/ranged_ints3.stderr b/src/test/ui/unsafe/ranged_ints3.stderr
deleted file mode 100644 (file)
index 4d4c916..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
-  --> $DIR/ranged_ints3.rs:10:13
-   |
-LL |     let y = &x.0;
-   |             ^^^^ borrow of layout constrained field with interior mutability
-   |
-   = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..9eec0b0
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints3.rs:13:13
+   |
+LL |     let y = &x.0;
+   |             ^^^^ borrow of layout constrained field with interior mutability
+   |
+   = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..62df933
--- /dev/null
@@ -0,0 +1,30 @@
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
+  --> $DIR/ranged_ints3_const.rs:15:13
+   |
+LL |     let y = &x.0;
+   |             ^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
+
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
+  --> $DIR/ranged_ints3_const.rs:22:22
+   |
+LL |     let y = unsafe { &x.0 };
+   |                      ^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
+
+error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints3_const.rs:15:13
+   |
+LL |     let y = &x.0;
+   |             ^^^^ borrow of layout constrained field with interior mutability
+   |
+   = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0133, E0658.
+For more information about an error, try `rustc --explain E0133`.
index c069ae7da021232d8ab79ec6e543440857152d89..637198d36042239e8edb0f5aba0c9eb62540ecb1 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![feature(rustc_attrs)]
 
 use std::cell::Cell;
diff --git a/src/test/ui/unsafe/ranged_ints3_const.stderr b/src/test/ui/unsafe/ranged_ints3_const.stderr
deleted file mode 100644 (file)
index 2150055..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
-  --> $DIR/ranged_ints3_const.rs:12:13
-   |
-LL |     let y = &x.0;
-   |             ^^^^
-   |
-   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
-   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
-
-error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
-  --> $DIR/ranged_ints3_const.rs:19:22
-   |
-LL |     let y = unsafe { &x.0 };
-   |                      ^^^^
-   |
-   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
-   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
-
-error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
-  --> $DIR/ranged_ints3_const.rs:12:13
-   |
-LL |     let y = &x.0;
-   |             ^^^^ borrow of layout constrained field with interior mutability
-   |
-   = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0133, E0658.
-For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..5dbc563
--- /dev/null
@@ -0,0 +1,30 @@
+error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints3_const.rs:15:13
+   |
+LL |     let y = &x.0;
+   |             ^^^^ borrow of layout constrained field with interior mutability
+   |
+   = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
+  --> $DIR/ranged_ints3_const.rs:15:13
+   |
+LL |     let y = &x.0;
+   |             ^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
+
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
+  --> $DIR/ranged_ints3_const.rs:22:22
+   |
+LL |     let y = unsafe { &x.0 };
+   |                      ^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0133, E0658.
+For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..27c0664
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints3_match.rs:14:17
+   |
+LL |         NonZero(ref x) => { x }
+   |                 ^^^^^ borrow of layout constrained field with interior mutability
+   |
+   = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints3_match.rs:20:23
+   |
+LL |     match y { NonZero(ref mut y) => { y } };
+   |                       ^^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints3_match.rs b/src/test/ui/unsafe/ranged_ints3_match.rs
new file mode 100644 (file)
index 0000000..d9fcf0b
--- /dev/null
@@ -0,0 +1,22 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+    let mut x = unsafe { NonZero(Cell::new(1)) };
+    match x {
+        NonZero(ref x) => { x }
+        //~^ ERROR borrow of layout constrained field with interior mutability
+    };
+
+    let mut y = unsafe { NonZero(42) };
+    match y { NonZero(ref y) => { y } }; // OK, type of `y` is freeze
+    match y { NonZero(ref mut y) => { y } };
+    //~^ ERROR mutation of layout constrained field
+}
diff --git a/src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..27c0664
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints3_match.rs:14:17
+   |
+LL |         NonZero(ref x) => { x }
+   |                 ^^^^^ borrow of layout constrained field with interior mutability
+   |
+   = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints3_match.rs:20:23
+   |
+LL |     match y { NonZero(ref mut y) => { y } };
+   |                       ^^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints4.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints4.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..493483d
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints4.rs:11:5
+   |
+LL |     x.0 = 0;
+   |     ^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
index d8632c48434f25f1653ea41aeec4c889b2739e65..fe80af454cb8d1396a097fcbc441d5e401ddf7b3 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![feature(rustc_attrs)]
 
 #[rustc_layout_scalar_valid_range_start(1)]
diff --git a/src/test/ui/unsafe/ranged_ints4.stderr b/src/test/ui/unsafe/ranged_ints4.stderr
deleted file mode 100644 (file)
index 68c2258..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
-  --> $DIR/ranged_ints4.rs:8:5
-   |
-LL |     x.0 = 0;
-   |     ^^^^^^^ mutation of layout constrained field
-   |
-   = note: mutating layout constrained fields cannot statically be checked for valid values
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints4.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints4.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..493483d
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints4.rs:11:5
+   |
+LL |     x.0 = 0;
+   |     ^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..a06c6f4
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints4_const.rs:13:5
+   |
+LL |     x.0 = 0;
+   |     ^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
index f09168c3d3f9ca48a8225cc0b165cb0d62d6fb1a..a43c8be71c4fd2e2338a4b35cb8ea12e7288cb2e 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![feature(rustc_attrs)]
 
 #[rustc_layout_scalar_valid_range_start(1)]
diff --git a/src/test/ui/unsafe/ranged_ints4_const.stderr b/src/test/ui/unsafe/ranged_ints4_const.stderr
deleted file mode 100644 (file)
index fe83b15..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
-  --> $DIR/ranged_ints4_const.rs:10:5
-   |
-LL |     x.0 = 0;
-   |     ^^^^^^^ mutation of layout constrained field
-   |
-   = note: mutating layout constrained fields cannot statically be checked for valid values
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..a06c6f4
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints4_const.rs:13:5
+   |
+LL |     x.0 = 0;
+   |     ^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+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 6810132686124c125938caebcb191bac75d0a923..29bd84cd0db53834fde1c6364b4eff790e89d4d5 100644 (file)
@@ -1,11 +1,11 @@
 error: unnecessary `unsafe` block
-  --> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:5
+  --> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:9
    |
-LL |     unsafe { println!("foo"); }
-   |     ^^^^^^ unnecessary `unsafe` block
+LL |         unsafe { async {}.await; }
+   |         ^^^^^^ unnecessary `unsafe` block
    |
 note: the lint level is defined here
-  --> $DIR/unsafe-around-compiler-generated-unsafe.rs:6:9
+  --> $DIR/unsafe-around-compiler-generated-unsafe.rs:5:9
    |
 LL | #![deny(unused_unsafe)]
    |         ^^^^^^^^^^^^^
index 08801f9ef59ffb14f410db4cb3da59f8b927a62a..e9c7efb9e8b80e17bf07fa1d5ac633f417ef4904 100644 (file)
@@ -1,10 +1,11 @@
-// issue #12418
-
+// edition:2018
 // revisions: mir thir
 // [thir]compile-flags: -Z thir-unsafeck
 
 #![deny(unused_unsafe)]
 
 fn main() {
-    unsafe { println!("foo"); } //~ ERROR unnecessary `unsafe`
+    let _ = async {
+        unsafe { async {}.await; } //~ ERROR unnecessary `unsafe`
+    };
 }
index 6810132686124c125938caebcb191bac75d0a923..29bd84cd0db53834fde1c6364b4eff790e89d4d5 100644 (file)
@@ -1,11 +1,11 @@
 error: unnecessary `unsafe` block
-  --> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:5
+  --> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:9
    |
-LL |     unsafe { println!("foo"); }
-   |     ^^^^^^ unnecessary `unsafe` block
+LL |         unsafe { async {}.await; }
+   |         ^^^^^^ unnecessary `unsafe` block
    |
 note: the lint level is defined here
-  --> $DIR/unsafe-around-compiler-generated-unsafe.rs:6:9
+  --> $DIR/unsafe-around-compiler-generated-unsafe.rs:5:9
    |
 LL | #![deny(unused_unsafe)]
    |         ^^^^^^^^^^^^^
diff --git a/src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr b/src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..9abc514
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-assign.rs:12:5
+   |
+LL |     foo.0.0 = 0;
+   |     ^^^^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-assign.rs b/src/test/ui/unsafe/unsafe-assign.rs
new file mode 100644 (file)
index 0000000..1527316
--- /dev/null
@@ -0,0 +1,25 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+#![allow(unused,dead_code)]
+
+fn nested_field() {
+    #[rustc_layout_scalar_valid_range_start(1)]
+    struct NonZero<T>(T);
+
+    let mut foo = unsafe { NonZero((1,)) };
+    foo.0.0 = 0;
+    //~^ ERROR: mutation of layout constrained field is unsafe
+}
+
+fn block() {
+    #[rustc_layout_scalar_valid_range_start(1)]
+    struct NonZero<T>(T);
+
+    let mut foo = unsafe { NonZero((1,)) };
+    { foo.0 }.0 = 0;
+    // ^ not unsafe because the result of the block expression is a new place
+}
+
+fn main() {}
diff --git a/src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr b/src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..9abc514
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-assign.rs:12:5
+   |
+LL |     foo.0.0 = 0;
+   |     ^^^^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr b/src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..a206722
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-borrow.rs:12:13
+   |
+LL |     let a = &mut foo.0.0;
+   |             ^^^^^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-borrow.rs:32:13
+   |
+LL |     let a = &mut foo.0[2];
+   |             ^^^^^^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-borrow.rs:51:18
+   |
+LL |         NonZero((a,)) => *a = 0,
+   |                  ^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-borrow.rs b/src/test/ui/unsafe/unsafe-borrow.rs
new file mode 100644 (file)
index 0000000..8dddc70
--- /dev/null
@@ -0,0 +1,56 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+#![allow(unused,dead_code)]
+
+fn tuple_struct() {
+    #[rustc_layout_scalar_valid_range_start(1)]
+    struct NonZero<T>(T);
+
+    let mut foo = unsafe { NonZero((1,)) };
+    let a = &mut foo.0.0;
+    //~^ ERROR: mutation of layout constrained field is unsafe
+}
+
+fn slice() {
+    #[rustc_layout_scalar_valid_range_start(1)]
+    struct NonZero<'a, T>(&'a mut [T]);
+
+    let mut nums = [1, 2, 3, 4];
+    let mut foo = unsafe { NonZero(&mut nums[..]) };
+    let a = &mut foo.0[2];
+    // ^ not unsafe because there is an implicit dereference here
+}
+
+fn array() {
+    #[rustc_layout_scalar_valid_range_start(1)]
+    struct NonZero<T>([T; 4]);
+
+    let nums = [1, 2, 3, 4];
+    let mut foo = unsafe { NonZero(nums) };
+    let a = &mut foo.0[2];
+    //~^ ERROR: mutation of layout constrained field is unsafe
+}
+
+fn block() {
+    #[rustc_layout_scalar_valid_range_start(1)]
+    struct NonZero<T>(T);
+
+    let foo = unsafe { NonZero((1,)) };
+    &mut { foo.0 }.0;
+    // ^ not unsafe because the result of the block expression is a new place
+}
+
+fn mtch() {
+    #[rustc_layout_scalar_valid_range_start(1)]
+    struct NonZero<T>(T);
+
+    let mut foo = unsafe { NonZero((1,)) };
+    match &mut foo {
+        NonZero((a,)) => *a = 0,
+        //~^ ERROR: mutation of layout constrained field is unsafe
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr b/src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..a206722
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-borrow.rs:12:13
+   |
+LL |     let a = &mut foo.0.0;
+   |             ^^^^^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-borrow.rs:32:13
+   |
+LL |     let a = &mut foo.0[2];
+   |             ^^^^^^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-borrow.rs:51:18
+   |
+LL |         NonZero((a,)) => *a = 0,
+   |                  ^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
index 65efbd6b52070c5ff628aab36b9c41919129cc7f..c5c5ed26c7384b263dcf857a844f6c118194b9d9 100644 (file)
@@ -1,12 +1,11 @@
 // run-pass
 // Test structs with always-unsized fields.
 
-
 #![allow(warnings)]
-#![feature(box_syntax, unsize, raw)]
+#![feature(box_syntax, unsize, ptr_metadata)]
 
 use std::mem;
-use std::raw;
+use std::ptr;
 use std::slice;
 
 struct Foo<T> {
@@ -28,7 +27,7 @@ trait Tr {
 }
 
 struct St {
-    f: usize
+    f: usize,
 }
 
 impl Tr for St {
@@ -38,7 +37,7 @@ impl Tr for St {
 }
 
 struct Qux<'a> {
-    f: Tr+'a
+    f: Tr + 'a,
 }
 
 pub fn main() {
@@ -56,10 +55,10 @@ pub fn main() {
 
     unsafe {
         struct Foo_<T> {
-            f: [T; 3]
+            f: [T; 3],
         }
 
-        let data: Box<Foo_<i32>> = box Foo_{f: [1, 2, 3] };
+        let data: Box<Foo_<i32>> = box Foo_ { f: [1, 2, 3] };
         let x: &Foo<i32> = mem::transmute(slice::from_raw_parts(&*data, 3));
         assert_eq!(x.f.len(), 3);
         assert_eq!(x.f[0], 1);
@@ -69,8 +68,8 @@ pub fn main() {
             f2: [u8; 5],
         }
 
-        let data: Box<_> = box Baz_ {
-            f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] };
+        let data: Box<_> =
+            box Baz_ { f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] };
         let x: &Baz = mem::transmute(slice::from_raw_parts(&*data, 5));
         assert_eq!(x.f1, 42);
         let chs: Vec<char> = x.f2.chars().collect();
@@ -82,15 +81,13 @@ pub fn main() {
         assert_eq!(chs[4], 'e');
 
         struct Qux_ {
-            f: St
+            f: St,
         }
 
         let obj: Box<St> = box St { f: 42 };
         let obj: &Tr = &*obj;
-        let obj: raw::TraitObject = mem::transmute(&*obj);
-        let data: Box<_> = box Qux_{ f: St { f: 234 } };
-        let x: &Qux = mem::transmute(raw::TraitObject { vtable: obj.vtable,
-                                                        data: mem::transmute(&*data) });
+        let data: Box<_> = box Qux_ { f: St { f: 234 } };
+        let x: &Qux = &*ptr::from_raw_parts::<Qux>((&*data as *const _).cast(), ptr::metadata(obj));
         assert_eq!(x.f.foo(), 234);
     }
 }
diff --git a/src/test/ui/unused/unused-doc-comments-edge-cases.rs b/src/test/ui/unused/unused-doc-comments-edge-cases.rs
new file mode 100644 (file)
index 0000000..fd9baf8
--- /dev/null
@@ -0,0 +1,29 @@
+#![deny(unused_doc_comments)]
+
+fn doc_comment_on_match_arms(num: u8) -> bool {
+    match num {
+        3 => true,
+        /// useless doc comment
+        //~^ ERROR: unused doc comment
+        _ => false,
+    }
+}
+
+fn doc_comment_between_if_else(num: u8) -> bool {
+    if num == 3 {
+        true //~ ERROR: mismatched types
+    }
+    /// useless doc comment
+    else { //~ ERROR: expected expression, found keyword `else`
+        false
+    }
+}
+
+fn doc_comment_on_expr(num: u8) -> bool {
+    /// useless doc comment
+    //~^ ERROR: attributes on expressions are experimental
+    //~| ERROR: unused doc comment
+    num == 3
+}
+
+fn main() {}
diff --git a/src/test/ui/unused/unused-doc-comments-edge-cases.stderr b/src/test/ui/unused/unused-doc-comments-edge-cases.stderr
new file mode 100644 (file)
index 0000000..14db5f6
--- /dev/null
@@ -0,0 +1,61 @@
+error: expected expression, found keyword `else`
+  --> $DIR/unused-doc-comments-edge-cases.rs:17:5
+   |
+LL |     else {
+   |     ^^^^ expected expression
+
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/unused-doc-comments-edge-cases.rs:23:5
+   |
+LL |     /// useless doc comment
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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
+   = help: `///` is for documentation comments. For a plain comment, use `//`.
+
+error: unused doc comment
+  --> $DIR/unused-doc-comments-edge-cases.rs:6:9
+   |
+LL |         /// useless doc comment
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL |         _ => false,
+   |         ---------- rustdoc does not generate documentation for match arms
+   |
+note: the lint level is defined here
+  --> $DIR/unused-doc-comments-edge-cases.rs:1:9
+   |
+LL | #![deny(unused_doc_comments)]
+   |         ^^^^^^^^^^^^^^^^^^^
+   = help: use `//` for a plain comment
+
+error: unused doc comment
+  --> $DIR/unused-doc-comments-edge-cases.rs:23:5
+   |
+LL |     /// useless doc comment
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     num == 3
+   |     --- rustdoc does not generate documentation for expressions
+   |
+   = help: use `//` for a plain comment
+
+error[E0308]: mismatched types
+  --> $DIR/unused-doc-comments-edge-cases.rs:14:9
+   |
+LL | /     if num == 3 {
+LL | |         true
+   | |         ^^^^ expected `()`, found `bool`
+LL | |     }
+   | |_____- expected this to be `()`
+   |
+help: you might have meant to return this value
+   |
+LL |         return true;
+   |         ^^^^^^     ^
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
index 5a0af8db7c504dfa78b3342375dbf1fb9a9a26e2..0054426fb1ec0cccf257bf1436f41f1040c8ac38 100644 (file)
@@ -26,6 +26,8 @@ LL |     /// a
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |     let x = 12;
    |     ----------- rustdoc does not generate documentation for statements
+   |
+   = help: use `//` for a plain comment
 
 error: unused doc comment
   --> $DIR/useless-comment.rs:16:5
@@ -40,6 +42,8 @@ LL | |         1 => {},
 LL | |         _ => {}
 LL | |     }
    | |_____- rustdoc does not generate documentation for expressions
+   |
+   = help: use `//` for a plain comment
 
 error: unused doc comment
   --> $DIR/useless-comment.rs:20:9
@@ -48,6 +52,8 @@ LL |         /// c
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |         1 => {},
    |         ------- rustdoc does not generate documentation for match arms
+   |
+   = help: use `//` for a plain comment
 
 error: unused doc comment
   --> $DIR/useless-comment.rs:25:5
@@ -56,6 +62,8 @@ LL |     /// foo
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |     unsafe {}
    |     --------- rustdoc does not generate documentation for expressions
+   |
+   = help: use `//` for a plain comment
 
 error: unused doc comment
   --> $DIR/useless-comment.rs:28:5
@@ -65,6 +73,8 @@ LL |     #[doc = "foo"]
 LL |     #[doc = "bar"]
 LL |     3;
    |     - rustdoc does not generate documentation for expressions
+   |
+   = help: use `//` for a plain comment
 
 error: unused doc comment
   --> $DIR/useless-comment.rs:29:5
@@ -73,12 +83,16 @@ LL |     #[doc = "bar"]
    |     ^^^^^^^^^^^^^^
 LL |     3;
    |     - rustdoc does not generate documentation for expressions
+   |
+   = help: use `//` for a plain comment
 
 error: unused doc comment
   --> $DIR/useless-comment.rs:35:13
    |
 LL |     let x = /** comment */ 47;
    |             ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions
+   |
+   = help: use `/* */` for a plain comment
 
 error: unused doc comment
   --> $DIR/useless-comment.rs:37:5
@@ -89,6 +103,8 @@ LL | /     {
 LL | |
 LL | |     }
    | |_____- rustdoc does not generate documentation for expressions
+   |
+   = help: use `//` for a plain comment
 
 error: aborting due to 10 previous errors
 
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 be18737b5f13105b8d5b7b89d01a727c679a5fa2..4b653238aa75032cd6e9aeeb9c332bd5308fd1ff 100644 (file)
@@ -39,7 +39,47 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:18:5
+  --> $DIR/variance-btree-invariant-types.rs:17:5
+   |
+LL | fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> {
+   |                      ---- lifetime `'new` defined here
+LL |     v
+   |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/variance-btree-invariant-types.rs:20:5
+   |
+LL | fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> {
+   |                      ---- lifetime `'new` defined here
+LL |     v
+   |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/variance-btree-invariant-types.rs:23:5
+   |
+LL | fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> {
+   |                         ---- lifetime `'new` defined here
+LL |     v
+   |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/variance-btree-invariant-types.rs:26:5
+   |
+LL | fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> {
+   |                         ---- lifetime `'new` defined here
+LL |     v
+   |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/variance-btree-invariant-types.rs:31:5
    |
 LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>)
    |                    ---- lifetime `'new` defined here
@@ -50,7 +90,7 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:22:5
+  --> $DIR/variance-btree-invariant-types.rs:35:5
    |
 LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>)
    |                    ---- lifetime `'new` defined here
@@ -61,7 +101,7 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:26:5
+  --> $DIR/variance-btree-invariant-types.rs:39:5
    |
 LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>)
    |                       ---- lifetime `'new` defined here
@@ -72,7 +112,7 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:30:5
+  --> $DIR/variance-btree-invariant-types.rs:43:5
    |
 LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>)
    |                       ---- lifetime `'new` defined here
@@ -83,7 +123,7 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:35:5
+  --> $DIR/variance-btree-invariant-types.rs:48:5
    |
 LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>)
    |                    ---- lifetime `'new` defined here
@@ -94,7 +134,7 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:39:5
+  --> $DIR/variance-btree-invariant-types.rs:52:5
    |
 LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>)
    |                    ---- lifetime `'new` defined here
@@ -105,7 +145,7 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:43:5
+  --> $DIR/variance-btree-invariant-types.rs:56:5
    |
 LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>)
    |                       ---- lifetime `'new` defined here
@@ -116,7 +156,7 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:47:5
+  --> $DIR/variance-btree-invariant-types.rs:60:5
    |
 LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>)
    |                       ---- lifetime `'new` defined here
@@ -126,5 +166,5 @@ LL |     v
    |
    = help: consider replacing `'new` with `'static`
 
-error: aborting due to 12 previous errors
+error: aborting due to 16 previous errors
 
index 2e5dc671db8811684bb1abfa44734e032f0a02d8..4549622f24ac3276710b150c2e0c4cda970bc6b2 100644 (file)
@@ -1,4 +1,4 @@
-use std::collections::btree_map::{IterMut, OccupiedEntry, VacantEntry};
+use std::collections::btree_map::{IterMut, OccupiedEntry, RangeMut, VacantEntry};
 
 fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> {
     v //~ ERROR mismatched types
@@ -13,6 +13,19 @@ fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &'
     v //~ ERROR mismatched types
 }
 
+fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> {
+    v //~ ERROR mismatched types
+}
+fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> {
+    v //~ ERROR mismatched types
+}
+fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> {
+    v //~ ERROR mismatched types
+}
+fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> {
+    v //~ ERROR mismatched types
+}
+
 fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>)
                          -> OccupiedEntry<'a, &'new (), ()> {
     v //~ ERROR mismatched types
index 8172a019b65edcabcbd93ef39ef5f5cb483c962c..ba47bdff281a2afe6422db485e2761d09bca29e2 100644 (file)
@@ -59,125 +59,185 @@ LL | fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:18:5
+  --> $DIR/variance-btree-invariant-types.rs:17:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected struct `RangeMut<'_, &'new (), _>`
+              found struct `RangeMut<'_, &'static (), _>`
+note: the lifetime `'new` as defined on the function body at 16:22...
+  --> $DIR/variance-btree-invariant-types.rs:16:22
+   |
+LL | fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> {
+   |                      ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:20:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected struct `RangeMut<'_, _, &'new ()>`
+              found struct `RangeMut<'_, _, &'static ()>`
+note: the lifetime `'new` as defined on the function body at 19:22...
+  --> $DIR/variance-btree-invariant-types.rs:19:22
+   |
+LL | fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> {
+   |                      ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:23:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected struct `RangeMut<'_, &'static (), _>`
+              found struct `RangeMut<'_, &'new (), _>`
+note: the lifetime `'new` as defined on the function body at 22:25...
+  --> $DIR/variance-btree-invariant-types.rs:22:25
+   |
+LL | fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> {
+   |                         ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:26:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected struct `RangeMut<'_, _, &'static ()>`
+              found struct `RangeMut<'_, _, &'new ()>`
+note: the lifetime `'new` as defined on the function body at 25:25...
+  --> $DIR/variance-btree-invariant-types.rs:25:25
+   |
+LL | fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> {
+   |                         ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:31:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>`
               found struct `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>`
-note: the lifetime `'new` as defined on the function body at 16:20...
-  --> $DIR/variance-btree-invariant-types.rs:16:20
+note: the lifetime `'new` as defined on the function body at 29:20...
+  --> $DIR/variance-btree-invariant-types.rs:29:20
    |
 LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>)
    |                    ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:22:5
+  --> $DIR/variance-btree-invariant-types.rs:35:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>`
               found struct `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>`
-note: the lifetime `'new` as defined on the function body at 20:20...
-  --> $DIR/variance-btree-invariant-types.rs:20:20
+note: the lifetime `'new` as defined on the function body at 33:20...
+  --> $DIR/variance-btree-invariant-types.rs:33:20
    |
 LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>)
    |                    ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:26:5
+  --> $DIR/variance-btree-invariant-types.rs:39:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>`
               found struct `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>`
-note: the lifetime `'new` as defined on the function body at 24:23...
-  --> $DIR/variance-btree-invariant-types.rs:24:23
+note: the lifetime `'new` as defined on the function body at 37:23...
+  --> $DIR/variance-btree-invariant-types.rs:37:23
    |
 LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>)
    |                       ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:30:5
+  --> $DIR/variance-btree-invariant-types.rs:43:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>`
               found struct `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>`
-note: the lifetime `'new` as defined on the function body at 28:23...
-  --> $DIR/variance-btree-invariant-types.rs:28:23
+note: the lifetime `'new` as defined on the function body at 41:23...
+  --> $DIR/variance-btree-invariant-types.rs:41:23
    |
 LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>)
    |                       ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:35:5
+  --> $DIR/variance-btree-invariant-types.rs:48:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::VacantEntry<'_, &'new (), _>`
               found struct `std::collections::btree_map::VacantEntry<'_, &'static (), _>`
-note: the lifetime `'new` as defined on the function body at 33:20...
-  --> $DIR/variance-btree-invariant-types.rs:33:20
+note: the lifetime `'new` as defined on the function body at 46:20...
+  --> $DIR/variance-btree-invariant-types.rs:46:20
    |
 LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>)
    |                    ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:39:5
+  --> $DIR/variance-btree-invariant-types.rs:52:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::VacantEntry<'_, _, &'new ()>`
               found struct `std::collections::btree_map::VacantEntry<'_, _, &'static ()>`
-note: the lifetime `'new` as defined on the function body at 37:20...
-  --> $DIR/variance-btree-invariant-types.rs:37:20
+note: the lifetime `'new` as defined on the function body at 50:20...
+  --> $DIR/variance-btree-invariant-types.rs:50:20
    |
 LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>)
    |                    ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:43:5
+  --> $DIR/variance-btree-invariant-types.rs:56:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::VacantEntry<'_, &'static (), _>`
               found struct `std::collections::btree_map::VacantEntry<'_, &'new (), _>`
-note: the lifetime `'new` as defined on the function body at 41:23...
-  --> $DIR/variance-btree-invariant-types.rs:41:23
+note: the lifetime `'new` as defined on the function body at 54:23...
+  --> $DIR/variance-btree-invariant-types.rs:54:23
    |
 LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>)
    |                       ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:47:5
+  --> $DIR/variance-btree-invariant-types.rs:60:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::VacantEntry<'_, _, &'static ()>`
               found struct `std::collections::btree_map::VacantEntry<'_, _, &'new ()>`
-note: the lifetime `'new` as defined on the function body at 45:23...
-  --> $DIR/variance-btree-invariant-types.rs:45:23
+note: the lifetime `'new` as defined on the function body at 58:23...
+  --> $DIR/variance-btree-invariant-types.rs:58:23
    |
 LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>)
    |                       ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
-error: aborting due to 12 previous errors
+error: aborting due to 16 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
index 2683590775904c433bbf061d11df9c6eb5f78ad7..0eb0fe071f50d41cb80782614dd216eaeceda8d9 100644 (file)
@@ -28,7 +28,7 @@ use std::process::Command;
 fn find_zombies() {
     let my_pid = unsafe { libc::getpid() };
 
-    // http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html
+    // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html
     let ps_cmd_output = Command::new("ps").args(&["-A", "-o", "pid,ppid,args"]).output().unwrap();
     let ps_output = String::from_utf8_lossy(&ps_cmd_output.stdout);
 
diff --git a/src/test/ui/wf/hir-wf-check-erase-regions.rs b/src/test/ui/wf/hir-wf-check-erase-regions.rs
new file mode 100644 (file)
index 0000000..bb398e5
--- /dev/null
@@ -0,0 +1,14 @@
+// Regression test for #87549.
+// compile-flags: -C incremental=tmp/wf/hir-wf-check-erase-regions
+
+pub struct Table<T, const N: usize>([Option<T>; N]);
+
+impl<'a, T, const N: usize> IntoIterator for &'a Table<T, N> {
+    type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>; //~ ERROR `&T` is not an iterator
+    type Item = &'a T;
+
+    fn into_iter(self) -> Self::IntoIter { //~ ERROR `&T` is not an iterator
+        unimplemented!()
+    }
+}
+fn main() {}
diff --git a/src/test/ui/wf/hir-wf-check-erase-regions.stderr b/src/test/ui/wf/hir-wf-check-erase-regions.stderr
new file mode 100644 (file)
index 0000000..203f099
--- /dev/null
@@ -0,0 +1,31 @@
+error[E0277]: `&T` is not an iterator
+  --> $DIR/hir-wf-check-erase-regions.rs:7:5
+   |
+LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator
+   | 
+  ::: $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
+   |
+LL | pub struct Flatten<I: Iterator<Item: IntoIterator>> {
+   |                                      ------------ required by this bound in `Flatten`
+   |
+   = help: the trait `Iterator` is not implemented for `&T`
+   = note: required because of the requirements on the impl of `IntoIterator` for `&T`
+
+error[E0277]: `&T` is not an iterator
+  --> $DIR/hir-wf-check-erase-regions.rs:10:27
+   |
+LL |     fn into_iter(self) -> Self::IntoIter {
+   |                           ^^^^^^^^^^^^^^ `&T` is not an iterator
+   | 
+  ::: $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
+   |
+LL | pub struct Flatten<I: Iterator<Item: IntoIterator>> {
+   |                                      ------------ required by this bound in `Flatten`
+   |
+   = help: the trait `Iterator` is not implemented for `&T`
+   = note: required because of the requirements on the impl of `IntoIterator` for `&T`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-complex-assoc-type.rs b/src/test/ui/wf/wf-complex-assoc-type.rs
new file mode 100644 (file)
index 0000000..c3811e8
--- /dev/null
@@ -0,0 +1,12 @@
+trait MyTrait {}
+struct AssertMyTrait<T: MyTrait>(T);
+
+trait HelperTrait {
+    type MyItem;
+}
+
+impl HelperTrait for () {
+    type MyItem = Option<((AssertMyTrait<bool>, u8))>; //~ ERROR the trait bound
+}
+
+fn main() {}
diff --git a/src/test/ui/wf/wf-complex-assoc-type.stderr b/src/test/ui/wf/wf-complex-assoc-type.stderr
new file mode 100644 (file)
index 0000000..c366519
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `bool: MyTrait` is not satisfied
+  --> $DIR/wf-complex-assoc-type.rs:9:28
+   |
+LL | struct AssertMyTrait<T: MyTrait>(T);
+   |                         ------- required by this bound in `AssertMyTrait`
+...
+LL |     type MyItem = Option<((AssertMyTrait<bool>, u8))>;
+   |                            ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `bool`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 9081b7929d935676221fddc052407f4c487a4592..f6b48938f9b04437bf699c469ca51c284f135498 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/wf-foreign-fn-decl-ret.rs:11:5
+  --> $DIR/wf-foreign-fn-decl-ret.rs:11:25
    |
+LL | pub trait Foo {
+   | ------------- required by this bound in `Foo`
+...
 LL |     pub fn lint_me() -> <() as Foo>::Assoc;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
+   |                         ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
 
 error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied
   --> $DIR/wf-foreign-fn-decl-ret.rs:14:32
index 89399e30cad4504b034ca56523a3243f86d0a727..0d4480fbf26e012956677e35924f018ba3231ea1 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: MyHash` is not satisfied
-  --> $DIR/wf-impl-associated-type-trait.rs:17:5
+  --> $DIR/wf-impl-associated-type-trait.rs:17:16
    |
 LL | pub struct MySet<T:MyHash> {
    |                    ------ required by this bound in `MySet`
 ...
 LL |     type Bar = MySet<T>;
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `MyHash` is not implemented for `T`
+   |                ^^^^^^^^ the trait `MyHash` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
index 9687658feba43b50936900e63c938265b4957242..ca90e9222dea9c9f29773f7a5153a9cd4ddbc47b 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/wf-in-fn-arg.rs:10:14
+  --> $DIR/wf-in-fn-arg.rs:10:15
    |
 LL | struct MustBeCopy<T:Copy> {
    |                     ---- required by this bound in `MustBeCopy`
 ...
 LL | fn bar<T>(_: &MustBeCopy<T>)
-   |              ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |               ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
index 33300b3964258e0b21571481625e282d13f942d4..20aa97707105e2156079225216800fd2bb60229f 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/wf-in-fn-type-arg.rs:9:8
+  --> $DIR/wf-in-fn-type-arg.rs:9:11
    |
 LL | struct MustBeCopy<T:Copy> {
    |                     ---- required by this bound in `MustBeCopy`
 ...
 LL |     x: fn(MustBeCopy<T>)
-   |        ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |           ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
index 1ffc47e6d826c842603291ac253aa276562d6612..48af696c3a7527aac89b520c901bd24bc0c5ff98 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/wf-in-fn-type-ret.rs:9:8
+  --> $DIR/wf-in-fn-type-ret.rs:9:16
    |
 LL | struct MustBeCopy<T:Copy> {
    |                     ---- required by this bound in `MustBeCopy`
 ...
 LL |     x: fn() -> MustBeCopy<T>
-   |        ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |                ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
index 8386959cfb3a83327850c86e6386ffb8ed97c185..4fcf8f403bbb6e38ac9da13de6627395f38a7c15 100644 (file)
@@ -13,5 +13,5 @@ pub struct Ref<'a>(&'a u8);
 impl Trait for Ref {} //~ ERROR:  implicit elided lifetime not allowed here
 
 extern "C" {
-    pub fn repro(_: Wrapper<Ref>); //~ ERROR: mismatched types
+    pub fn repro(_: Wrapper<Ref>); //~ ERROR: incompatible lifetime on type
 }
index bb839d0a5eca685438a24a35def594c617ddc182..4e927cd983d0d4d906defe475a6d98e19fe3c4cc 100644 (file)
@@ -3,22 +3,30 @@ error[E0726]: implicit elided lifetime not allowed here
    |
 LL | impl Trait for Ref {}
    |                ^^^- help: indicate the anonymous lifetime: `<'_>`
+   |
+   = note: assuming a `'static` lifetime...
 
-error[E0308]: mismatched types
+error: incompatible lifetime on type
   --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:21
    |
 LL |     pub fn repro(_: Wrapper<Ref>);
-   |                     ^^^^^^^^^^^^ lifetime mismatch
+   |                     ^^^^^^^^^^^^
+   |
+note: because this has an unmet lifetime requirement
+  --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:8:23
    |
-   = note: expected trait `Trait`
-              found trait `Trait`
+LL | pub struct Wrapper<T: Trait>(T);
+   |                       ^^^^^ introduces a `'static` lifetime requirement
 note: the anonymous lifetime #1 defined on the method body at 16:5...
   --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:5
    |
 LL |     pub fn repro(_: Wrapper<Ref>);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...does not necessarily outlive the static lifetime
+note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
+  --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:1
+   |
+LL | impl Trait for Ref {}
+   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
index 8606eabf59c146f0680c8112cae0db333d55102a..b3b919a569ed41fa0b08a79355bab4088a6dbb55 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/wf-in-obj-type-trait.rs:11:8
+  --> $DIR/wf-in-obj-type-trait.rs:11:19
    |
 LL | struct MustBeCopy<T:Copy> {
    |                     ---- required by this bound in `MustBeCopy`
 ...
 LL |     x: dyn Object<MustBeCopy<T>>
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |                   ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
index ddc0b323a11a1f6977911fd82fc49aa489947cf0..d67e110edeeee0aabb7406503e707c9615e21df0 100644 (file)
@@ -8,7 +8,7 @@ struct IsCopy<T:Copy> { x: T }
 
 trait SomeTrait {
     type Type1;
-    type Type2 = IsCopy<Self::Type1>;
+    type Type2 = (IsCopy<Self::Type1>, bool);
     //~^ ERROR E0277
 }
 
index a139186ebb67349c02b71235b73f2f55cd6bdf57..d1c2c65043d21b8ee8fe2ec862cc504bd8d4743a 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `<Self as SomeTrait>::Type1: Copy` is not satisfied
-  --> $DIR/wf-trait-associated-type-trait.rs:11:5
+  --> $DIR/wf-trait-associated-type-trait.rs:11:19
    |
 LL | struct IsCopy<T:Copy> { x: T }
    |                 ---- required by this bound in `IsCopy`
 ...
-LL |     type Type2 = IsCopy<Self::Type1>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `<Self as SomeTrait>::Type1`
+LL |     type Type2 = (IsCopy<Self::Type1>, bool);
+   |                   ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `<Self as SomeTrait>::Type1`
    |
 help: consider further restricting the associated type
    |
index c3d5d2b9669b80edd54c11e24b8ca3519e6d816a..2a129538f76333bbfb69cf8b829a255f8947227a 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `Self: Eq` is not satisfied
-  --> $DIR/wf-trait-default-fn-arg.rs:11:22
+  --> $DIR/wf-trait-default-fn-arg.rs:11:23
    |
 LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
    |              -- required by this bound in `Bar`
 ...
 LL |     fn bar(&self, x: &Bar<Self>) {
-   |                      ^^^^^^^^^^ the trait `Eq` is not implemented for `Self`
+   |                       ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
index 4510f50feea58871f3e8bd03638732e613d85f36..7693aa6d2d583ed64a597ddc705a1488cea19216 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `Self: Eq` is not satisfied
-  --> $DIR/wf-trait-fn-arg.rs:10:22
+  --> $DIR/wf-trait-fn-arg.rs:10:23
    |
 LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
    |              -- required by this bound in `Bar`
 ...
 LL |     fn bar(&self, x: &Bar<Self>);
-   |                      ^^^^^^^^^^ the trait `Eq` is not implemented for `Self`
+   |                       ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
index 7dd98564425f879076d8ea614955cbcab83f5105..3fcaefaa63ef1517c4ef0323805205a4a565dcdc 100644 (file)
@@ -1,5 +1,7 @@
 // run-pass
 
+#![feature(io_error_uncategorized)]
+
 use std::fmt;
 use std::io::{self, Error, Write, sink};
 
@@ -13,7 +15,7 @@ impl fmt::Display for ErrorDisplay {
 
 struct ErrorWriter;
 
-const FORMAT_ERROR: io::ErrorKind = io::ErrorKind::Other;
+const FORMAT_ERROR: io::ErrorKind = io::ErrorKind::Uncategorized;
 const WRITER_ERROR: io::ErrorKind = io::ErrorKind::NotConnected;
 
 impl Write for ErrorWriter {
index 8b7e43ccc04e90e4f566ede7d44dbebd68e9da48..69b414cc8f92363ff1bcac98f75dee6f7507f796 100644 (file)
@@ -3,12 +3,22 @@ error[E0624]: associated function `static_meth_struct` is private
    |
 LL |     let _ = xc_private_method_lib::Struct::static_meth_struct();
    |                                            ^^^^^^^^^^^^^^^^^^ private associated function
+   | 
+  ::: $DIR/auxiliary/xc-private-method-lib.rs:8:5
+   |
+LL |     fn static_meth_struct() -> Struct {
+   |     --------------------------------- private associated function defined here
 
 error[E0624]: associated function `static_meth_enum` is private
   --> $DIR/xc-private-method.rs:9:42
    |
 LL |     let _ = xc_private_method_lib::Enum::static_meth_enum();
    |                                          ^^^^^^^^^^^^^^^^ private associated function
+   | 
+  ::: $DIR/auxiliary/xc-private-method-lib.rs:23:5
+   |
+LL |     fn static_meth_enum() -> Enum {
+   |     ----------------------------- private associated function defined here
 
 error: aborting due to 2 previous errors
 
index 0ebdb0a06d82b45340ec2ecf3c4c1d9a2f55f37a..685ce0e0a186fc668d92225936fadd30e22ec8ed 100644 (file)
@@ -3,12 +3,22 @@ error[E0624]: associated function `meth_struct` is private
    |
 LL |     let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct();
    |                                                    ^^^^^^^^^^^ private associated function
+   | 
+  ::: $DIR/auxiliary/xc-private-method-lib.rs:12:5
+   |
+LL |     fn meth_struct(&self) -> isize {
+   |     ------------------------------ private associated function defined here
 
 error[E0624]: associated function `meth_enum` is private
   --> $DIR/xc-private-method2.rs:9:55
    |
 LL |     let _ = xc_private_method_lib::Enum::Variant1(20).meth_enum();
    |                                                       ^^^^^^^^^ private associated function
+   | 
+  ::: $DIR/auxiliary/xc-private-method-lib.rs:27:5
+   |
+LL |     fn meth_enum(&self) -> isize {
+   |     ---------------------------- private associated function defined here
 
 error: aborting due to 2 previous errors
 
index 32103f59d8b0e14d389e4b714c8fc419e9999ba9..d856c55a41a4b8768b246009e43785a0b21ef6ca 100644 (file)
@@ -71,7 +71,7 @@ jobs:
       working-directory: clippy_workspace_tests
 
     - name: Test cargo-clippy --fix
-      run: ../target/debug/cargo-clippy clippy --fix -Zunstable-options
+      run: ../target/debug/cargo-clippy clippy --fix
       working-directory: clippy_workspace_tests
 
     - name: Test clippy-driver
index f27fee87dc1653f508555f90661143aa338a5e2c..146b6fccd0c76e94962ca9260732ce849a535ee0 100644 (file)
@@ -90,11 +90,6 @@ jobs:
     - name: Checkout
       uses: actions/checkout@v2.3.3
 
-    # FIXME: should not be necessary once 1.24.2 is the default version on the windows runner
-    - name: Update rustup
-      run: rustup self update
-      if: runner.os == 'Windows'
-
     - name: Install toolchain
       run: rustup show active-toolchain
 
@@ -139,7 +134,7 @@ jobs:
       working-directory: clippy_workspace_tests
 
     - name: Test cargo-clippy --fix
-      run: ../target/debug/cargo-clippy clippy --fix -Zunstable-options
+      run: ../target/debug/cargo-clippy clippy --fix
       working-directory: clippy_workspace_tests
 
     - name: Test clippy-driver
index 4f25a86b2e4df3cac0a28a61639b0d6df04d36cd..77efdec1e50db71b34a533df1d0deb068e3827e7 100644 (file)
@@ -22,7 +22,7 @@ jobs:
       uses: actions/setup-node@v1.4.4
 
     - name: Install remark
-      run: npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended
+      run: npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended remark-gfm
 
     # Run
     - name: Check *.md files
index 0ede7ac75cb6f98d73d8a4efa0cc2cad09b55fa3..04b82b8cc581ff573d7bc7cd14856d38c2d127ed 100644 (file)
@@ -1,6 +1,7 @@
 {
   "plugins": [
     "remark-preset-lint-recommended",
+    "remark-gfm",
     ["remark-lint-list-item-indent", false],
     ["remark-lint-no-literal-urls", false],
     ["remark-lint-no-shortcut-reference-link", false],
index 41af8e190ddf3581503dc5cd0b902f68cb1e0f20..acbefc8064ddaece56e268883775df69ea0b341d 100644 (file)
@@ -6,11 +6,139 @@ document.
 
 ## Unreleased / In Rust Nightly
 
-[7c7683c...master](https://github.com/rust-lang/rust-clippy/compare/7c7683c...master)
+[3ae8faf...master](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...master)
+
+## Rust 1.54
+
+Current beta, release 2021-07-29
+
+[7c7683c...3ae8faf](https://github.com/rust-lang/rust-clippy/compare/7c7683c...3ae8faf)
+
+### New Lints
+
+- [`ref_binding_to_reference`]
+  [#7105](https://github.com/rust-lang/rust-clippy/pull/7105)
+- [`needless_bitwise_bool`]
+  [#7133](https://github.com/rust-lang/rust-clippy/pull/7133)
+- [`unused_async`] [#7225](https://github.com/rust-lang/rust-clippy/pull/7225)
+- [`manual_str_repeat`]
+  [#7265](https://github.com/rust-lang/rust-clippy/pull/7265)
+- [`suspicious_splitn`]
+  [#7292](https://github.com/rust-lang/rust-clippy/pull/7292)
+
+### Moves and Deprecations
+
+- Deprecate `pub_enum_variant_names` and `wrong_pub_self_convention` in favor of
+  the new `avoid_breaking_exported_api` config option (see
+  [Enhancements](#1-54-enhancements))
+  [#7187](https://github.com/rust-lang/rust-clippy/pull/7187)
+- Move [`inconsistent_struct_constructor`] to `pedantic`
+  [#7193](https://github.com/rust-lang/rust-clippy/pull/7193)
+- Move [`needless_borrow`] to `style` (now warn-by-default)
+  [#7254](https://github.com/rust-lang/rust-clippy/pull/7254)
+- Move [`suspicious_operation_groupings`] to `nursery`
+  [#7266](https://github.com/rust-lang/rust-clippy/pull/7266)
+- Move [`semicolon_if_nothing_returned`] to `pedantic`
+  [#7268](https://github.com/rust-lang/rust-clippy/pull/7268)
+
+### Enhancements <a name="1-54-enhancements"></a>
+
+- [`while_let_on_iterator`]: Now also lints in nested loops
+  [#6966](https://github.com/rust-lang/rust-clippy/pull/6966)
+- [`single_char_pattern`]: Now also lints on `strip_prefix` and `strip_suffix`
+  [#7156](https://github.com/rust-lang/rust-clippy/pull/7156)
+- [`needless_collect`]: Now also lints on assignments with type annotations
+  [#7163](https://github.com/rust-lang/rust-clippy/pull/7163)
+- [`if_then_some_else_none`]: Now works with the MSRV config
+  [#7177](https://github.com/rust-lang/rust-clippy/pull/7177)
+- Add `avoid_breaking_exported_api` config option for the lints
+  [`enum_variant_names`], [`large_types_passed_by_value`],
+  [`trivially_copy_pass_by_ref`], [`unnecessary_wraps`],
+  [`upper_case_acronyms`], and [`wrong_self_convention`]. We recommend to set
+  this configuration option to `false` before a major release (1.0/2.0/...) to
+  clean up the API [#7187](https://github.com/rust-lang/rust-clippy/pull/7187)
+- [`needless_collect`]: Now lints on even more data structures
+  [#7188](https://github.com/rust-lang/rust-clippy/pull/7188)
+- [`missing_docs_in_private_items`]: No longer sees `#[<name> = "<value>"]` like
+  attributes as sufficient documentation
+  [#7281](https://github.com/rust-lang/rust-clippy/pull/7281)
+- [`needless_collect`], [`short_circuit_statement`], [`unnecessary_operation`]:
+  Now work as expected when used with `allow`
+  [#7282](https://github.com/rust-lang/rust-clippy/pull/7282)
+
+### False Positive Fixes
+
+- [`implicit_return`]: Now takes all diverging functions in account to avoid
+  false positives [#6951](https://github.com/rust-lang/rust-clippy/pull/6951)
+- [`while_let_on_iterator`]: No longer lints when the iterator is a struct field
+  and the struct is used in the loop
+  [#6966](https://github.com/rust-lang/rust-clippy/pull/6966)
+- [`multiple_inherent_impl`]: No longer lints with generic arguments
+  [#7089](https://github.com/rust-lang/rust-clippy/pull/7089)
+- [`comparison_chain`]: No longer lints in a `const` context
+  [#7118](https://github.com/rust-lang/rust-clippy/pull/7118)
+- [`while_immutable_condition`]: Fix false positive where mutation in the loop
+  variable wasn't picked up
+  [#7144](https://github.com/rust-lang/rust-clippy/pull/7144)
+- [`default_trait_access`]: No longer lints in macros
+  [#7150](https://github.com/rust-lang/rust-clippy/pull/7150)
+- [`needless_question_mark`]: No longer lints when the inner value is implicitly
+  dereferenced [#7165](https://github.com/rust-lang/rust-clippy/pull/7165)
+- [`unused_unit`]: No longer lints when multiple macro contexts are involved
+  [#7167](https://github.com/rust-lang/rust-clippy/pull/7167)
+- [`eval_order_dependence`]: Fix false positive in async context
+  [#7174](https://github.com/rust-lang/rust-clippy/pull/7174)
+- [`unnecessary_filter_map`]: No longer lints if the `filter_map` changes the
+  type [#7175](https://github.com/rust-lang/rust-clippy/pull/7175)
+- [`wrong_self_convention`]: No longer lints in trait implementations of
+  non-`Copy` types [#7182](https://github.com/rust-lang/rust-clippy/pull/7182)
+- [`suboptimal_flops`]: No longer lints on `powi(2)`
+  [#7201](https://github.com/rust-lang/rust-clippy/pull/7201)
+- [`wrong_self_convention`]: No longer lints if there is no implicit `self`
+  [#7215](https://github.com/rust-lang/rust-clippy/pull/7215)
+- [`option_if_let_else`]: No longer lints on `else if let` pattern
+  [#7216](https://github.com/rust-lang/rust-clippy/pull/7216)
+- [`use_self`], [`useless_conversion`]: Fix false positives when generic
+  arguments are involved
+  [#7223](https://github.com/rust-lang/rust-clippy/pull/7223)
+- [`manual_unwrap_or`]: Fix false positive with deref coercion
+  [#7233](https://github.com/rust-lang/rust-clippy/pull/7233)
+- [`similar_names`]: No longer lints on `wparam`/`lparam`
+  [#7255](https://github.com/rust-lang/rust-clippy/pull/7255)
+- [`redundant_closure`]: No longer lints on using the `vec![]` macro in a
+  closure [#7263](https://github.com/rust-lang/rust-clippy/pull/7263)
+
+### Suggestion Fixes/Improvements
+
+- [`implicit_return`]
+  [#6951](https://github.com/rust-lang/rust-clippy/pull/6951)
+    - Fix suggestion for async functions
+    - Improve suggestion with macros
+    - Suggest to change `break` to `return` when appropriate
+- [`while_let_on_iterator`]: Now suggests `&mut iter` when necessary
+  [#6966](https://github.com/rust-lang/rust-clippy/pull/6966)
+- [`match_single_binding`]: Improve suggestion when match scrutinee has side
+  effects [#7095](https://github.com/rust-lang/rust-clippy/pull/7095)
+- [`needless_borrow`]: Now suggests to also change usage sites as needed
+  [#7105](https://github.com/rust-lang/rust-clippy/pull/7105)
+- [`write_with_newline`]: Improve suggestion when only `\n` is written to the
+  buffer [#7183](https://github.com/rust-lang/rust-clippy/pull/7183)
+- [`from_iter_instead_of_collect`]: The suggestion is now auto applicable also
+  when a `<_ as Trait>::_` is involved
+  [#7264](https://github.com/rust-lang/rust-clippy/pull/7264)
+- [`not_unsafe_ptr_arg_deref`]: Improved error message
+  [#7294](https://github.com/rust-lang/rust-clippy/pull/7294)
+
+### ICE Fixes
+
+- Fix ICE when running Clippy on `libstd`
+  [#7140](https://github.com/rust-lang/rust-clippy/pull/7140)
+- [`implicit_return`]
+  [#7242](https://github.com/rust-lang/rust-clippy/pull/7242)
 
 ## Rust 1.53
 
-Current beta, release 2021-06-17
+Current stable, released 2021-06-17
 
 [6ed6f1e...7c7683c](https://github.com/rust-lang/rust-clippy/compare/6ed6f1e...7c7683c)
 
@@ -194,7 +322,7 @@ Current beta, release 2021-06-17
 
 ## Rust 1.52
 
-Current stable, released 2021-05-06
+Released 2021-05-06
 
 [3e41797...6ed6f1e](https://github.com/rust-lang/rust-clippy/compare/3e41797...6ed6f1e)
 
@@ -464,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)
@@ -2358,6 +2486,8 @@ Released 2018-09-13
 [`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq
 [`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord
 [`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method
+[`disallowed_script_idents`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents
+[`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type
 [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression
 [`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
 [`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons
@@ -2391,6 +2521,7 @@ Released 2018-09-13
 [`explicit_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop
 [`explicit_write`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_write
 [`extend_from_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_from_slice
+[`extend_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_with_drain
 [`extra_unused_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes
 [`fallible_impl_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#fallible_impl_from
 [`field_reassign_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default
@@ -2527,6 +2658,7 @@ Released 2018-09-13
 [`misrefactored_assign_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#misrefactored_assign_op
 [`missing_const_for_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn
 [`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items
+[`missing_enforced_import_renames`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames
 [`missing_errors_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc
 [`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items
 [`missing_panics_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc
@@ -2574,6 +2706,7 @@ Released 2018-09-13
 [`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
 [`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
 [`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options
+[`nonstandard_macro_braces`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces
 [`not_unsafe_ptr_arg_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref
 [`ok_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#ok_expect
 [`op_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#op_ref
@@ -2611,6 +2744,7 @@ Released 2018-09-13
 [`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero
 [`range_zip_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_zip_with_len
 [`rc_buffer`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer
+[`rc_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex
 [`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation
 [`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone
 [`redundant_closure`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
@@ -2638,6 +2772,7 @@ Released 2018-09-13
 [`same_item_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push
 [`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some
 [`self_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_assignment
+[`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors
 [`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
 [`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse
 [`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse
@@ -2664,6 +2799,7 @@ Released 2018-09-13
 [`string_from_utf8_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_from_utf8_as_bytes
 [`string_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_as_bytes
 [`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string
+[`strlen_on_c_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#strlen_on_c_strings
 [`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools
 [`suboptimal_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#suboptimal_flops
 [`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl
index 7265d1b832376401f9a8997a9b5c4b8e2a2a8209..4273fda4e640d5d9356a5d63f166db26224fc603 100644 (file)
@@ -115,7 +115,7 @@ To work around this, you need to have a copy of the [rustc-repo][rustc_repo] ava
 `git clone https://github.com/rust-lang/rust/`.
 Then you can run a `cargo dev` command to automatically make Clippy use the rustc-repo via path-dependencies
 which `IntelliJ Rust` will be able to understand.
-Run `cargo dev ide_setup --repo-path <repo-path>` where `<repo-path>` is a path to the rustc repo
+Run `cargo dev setup intellij --repo-path <repo-path>` where `<repo-path>` is a path to the rustc repo
 you just cloned.
 The command will add path-dependencies pointing towards rustc-crates inside the rustc repo to
 Clippys `Cargo.toml`s and should allow `IntelliJ Rust` to understand most of the types that Clippy uses.
@@ -342,7 +342,7 @@ We have prioritization labels and a sync-blocker label, which are described belo
 - [P-low][p-low]: Requires attention (fix/response/evaluation) by a team member but isn't urgent.
 - [P-medium][p-medium]: Should be addressed by a team member until the next sync.
 - [P-high][p-high]: Should be immediately addressed and will require an out-of-cycle sync or a backport.
-- [L-sync-blocker][l-sync-blocker]: An issue that "blocks" a sync. 
+- [L-sync-blocker][l-sync-blocker]: An issue that "blocks" a sync.
 Or rather: before the sync this should be addressed,
 e.g. by removing a lint again, so it doesn't hit beta/stable.
 
index b003b15a11d750553db593179b658ae375bf6464..9b5d9b2adf3b2413c85027477d1a2e36043b9801 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.1.54"
+version = "0.1.55"
 authors = ["The Rust Clippy Developers"]
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
index 6c556f579ca4f96cdc9e984663d2a3af00e8c364..e1c968273cdf63ef95eae0633929566df1304e7e 100644 (file)
@@ -10,16 +10,17 @@ A collection of lints to catch common mistakes and improve your [Rust](https://g
 Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html).
 You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category.
 
-| Category              | Description                                                             | Default level |
-| --------------------- | ----------------------------------------------------------------------- | ------------- |
-| `clippy::all`         | all lints that are on by default (correctness, style, complexity, perf) | **warn/deny** |
-| `clippy::correctness` | code that is outright wrong or very useless                             | **deny**      |
-| `clippy::style`       | code that should be written in a more idiomatic way                     | **warn**      |
-| `clippy::complexity`  | code that does something simple but in a complex way                    | **warn**      |
-| `clippy::perf`        | code that can be written to run faster                                  | **warn**      |
-| `clippy::pedantic`    | lints which are rather strict or might have false positives             | allow         |
-| `clippy::nursery`     | new lints that are still under development                              | allow         |
-| `clippy::cargo`       | lints for the cargo manifest                                            | allow         |
+| Category              | Description                                                                         | Default level |
+| --------------------- | ----------------------------------------------------------------------------------- | ------------- |
+| `clippy::all`         | all lints that are on by default (correctness, suspicious, style, complexity, perf) | **warn/deny** |
+| `clippy::correctness` | code that is outright wrong or useless                                              | **deny**      |
+| `clippy::suspicious`  | code that is most likely wrong or useless                                           | **warn**      |
+| `clippy::style`       | code that should be written in a more idiomatic way                                 | **warn**      |
+| `clippy::complexity`  | code that does something simple but in a complex way                                | **warn**      |
+| `clippy::perf`        | code that can be written to run faster                                              | **warn**      |
+| `clippy::pedantic`    | lints which are rather strict or might have false positives                         | allow         |
+| `clippy::nursery`     | new lints that are still under development                                          | allow         |
+| `clippy::cargo`       | lints for the cargo manifest                                                        | allow         |
 
 More to come, please [file an issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas!
 
@@ -75,11 +76,10 @@ cargo clippy
 
 #### Automatically applying Clippy suggestions
 
-Clippy can automatically apply some lint suggestions.
-Note that this is still experimental and only supported on the nightly channel:
+Clippy can automatically apply some lint suggestions, just like the compiler.
 
 ```terminal
-cargo clippy --fix -Z unstable-options
+cargo clippy --fix
 ```
 
 #### Workspaces
@@ -95,7 +95,7 @@ As with `cargo check`, this includes dependencies that are members of the worksp
 If you want to run Clippy **only** on the given crate, use the `--no-deps` option like this:
 
 ```terminal
-cargo clippy -p example -- --no-deps 
+cargo clippy -p example -- --no-deps
 ```
 
 ### As a rustc replacement (`clippy-driver`)
index b1844e29b3273fa3e41a1a65fe070f4db1ffe73f..5c6c106e0e638429705e62ebba344f6e4ca6bf78 100644 (file)
@@ -8,7 +8,7 @@ edition = "2018"
 bytecount = "0.6"
 clap = "2.33"
 itertools = "0.9"
-opener = "0.4"
+opener = "0.5"
 regex = "1"
 shell-escape = "0.1"
 walkdir = "2"
index 1517cdc9419626600ad03b60cbc28e1ef1cc7d42..c81eb40d52f3551ffc698db36acf7767b5c3874e 100644 (file)
@@ -60,11 +60,7 @@ pub fn run(check: bool, verbose: bool) {
             let entry = entry?;
             let path = entry.path();
 
-            if path.extension() != Some("rs".as_ref())
-                || entry.file_name() == "ice-3891.rs"
-                // Avoid rustfmt bug rust-lang/rustfmt#1873
-                || cfg!(windows) && entry.file_name() == "implicit_hasher.rs"
-            {
+            if path.extension() != Some("rs".as_ref()) || entry.file_name() == "ice-3891.rs" {
                 continue;
             }
 
@@ -90,7 +86,7 @@ pub fn run(check: bool, verbose: bool) {
             },
             CliError::RaSetupActive => {
                 eprintln!(
-                    "error: a local rustc repo is enabled as path dependency via `cargo dev ide_setup`.
+                    "error: a local rustc repo is enabled as path dependency via `cargo dev setup intellij`.
 Not formatting because that would format the local repo as well!
 Please revert the changes to Cargo.tomls first."
                 );
diff --git a/src/tools/clippy/clippy_dev/src/ide_setup.rs b/src/tools/clippy/clippy_dev/src/ide_setup.rs
deleted file mode 100644 (file)
index defb113..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-use std::fs;
-use std::fs::File;
-use std::io::prelude::*;
-use std::path::{Path, PathBuf};
-
-// This module takes an absolute path to a rustc repo and alters the dependencies to point towards
-// the respective rustc subcrates instead of using extern crate xyz.
-// This allows rust analyzer to analyze rustc internals and show proper information inside clippy
-// code. See https://github.com/rust-analyzer/rust-analyzer/issues/3517 and https://github.com/rust-lang/rust-clippy/issues/5514 for details
-
-/// # Panics
-///
-/// Panics if `rustc_path` does not lead to a rustc repo or the files could not be read
-pub fn run(rustc_path: Option<&str>) {
-    // we can unwrap here because the arg is required by clap
-    let rustc_path = PathBuf::from(rustc_path.unwrap())
-        .canonicalize()
-        .expect("failed to get the absolute repo path");
-    assert!(rustc_path.is_dir(), "path is not a directory");
-    let rustc_source_basedir = rustc_path.join("compiler");
-    assert!(
-        rustc_source_basedir.is_dir(),
-        "are you sure the path leads to a rustc repo?"
-    );
-
-    let clippy_root_manifest = fs::read_to_string("Cargo.toml").expect("failed to read ./Cargo.toml");
-    let clippy_root_lib_rs = fs::read_to_string("src/driver.rs").expect("failed to read ./src/driver.rs");
-    inject_deps_into_manifest(
-        &rustc_source_basedir,
-        "Cargo.toml",
-        &clippy_root_manifest,
-        &clippy_root_lib_rs,
-    )
-    .expect("Failed to inject deps into ./Cargo.toml");
-
-    let clippy_lints_manifest =
-        fs::read_to_string("clippy_lints/Cargo.toml").expect("failed to read ./clippy_lints/Cargo.toml");
-    let clippy_lints_lib_rs =
-        fs::read_to_string("clippy_lints/src/lib.rs").expect("failed to read ./clippy_lints/src/lib.rs");
-    inject_deps_into_manifest(
-        &rustc_source_basedir,
-        "clippy_lints/Cargo.toml",
-        &clippy_lints_manifest,
-        &clippy_lints_lib_rs,
-    )
-    .expect("Failed to inject deps into ./clippy_lints/Cargo.toml");
-}
-
-fn inject_deps_into_manifest(
-    rustc_source_dir: &Path,
-    manifest_path: &str,
-    cargo_toml: &str,
-    lib_rs: &str,
-) -> std::io::Result<()> {
-    // do not inject deps if we have aleady done so
-    if cargo_toml.contains("[target.'cfg(NOT_A_PLATFORM)'.dependencies]") {
-        eprintln!(
-            "cargo dev ide_setup: warning: deps already found inside {}, doing nothing.",
-            manifest_path
-        );
-        return Ok(());
-    }
-
-    let extern_crates = lib_rs
-        .lines()
-        // get the deps
-        .filter(|line| line.starts_with("extern crate"))
-        // we have something like "extern crate foo;", we only care about the "foo"
-        //              ↓          ↓
-        // extern crate rustc_middle;
-        .map(|s| &s[13..(s.len() - 1)]);
-
-    let new_deps = extern_crates.map(|dep| {
-        // format the dependencies that are going to be put inside the Cargo.toml
-        format!(
-            "{dep} = {{ path = \"{source_path}/{dep}\" }}\n",
-            dep = dep,
-            source_path = rustc_source_dir.display()
-        )
-    });
-
-    // format a new [dependencies]-block with the new deps we need to inject
-    let mut all_deps = String::from("[target.'cfg(NOT_A_PLATFORM)'.dependencies]\n");
-    new_deps.for_each(|dep_line| {
-        all_deps.push_str(&dep_line);
-    });
-    all_deps.push_str("\n[dependencies]\n");
-
-    // replace "[dependencies]" with
-    // [dependencies]
-    // dep1 = { path = ... }
-    // dep2 = { path = ... }
-    // etc
-    let new_manifest = cargo_toml.replacen("[dependencies]\n", &all_deps, 1);
-
-    // println!("{}", new_manifest);
-    let mut file = File::create(manifest_path)?;
-    file.write_all(new_manifest.as_bytes())?;
-
-    println!("Dependency paths injected: {}", manifest_path);
-
-    Ok(())
-}
index 69f42aca8b6900a092fc09e73aff9b23eea1e817..72bdaf8d59282f89f39f63142a9191325f4c224f 100644 (file)
@@ -14,9 +14,9 @@ use walkdir::WalkDir;
 
 pub mod bless;
 pub mod fmt;
-pub mod ide_setup;
 pub mod new_lint;
 pub mod serve;
+pub mod setup;
 pub mod stderr_length_check;
 pub mod update_lints;
 
index 7040c257c831b0e49ec02e340ecdb4878876d8a1..ff324ff6ee6fff5b6a38edc9aaefc6ee09df0f34 100644 (file)
@@ -2,8 +2,8 @@
 // warn on lints, that are included in `rust-lang/rust`s bootstrap
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
-use clap::{App, Arg, ArgMatches, SubCommand};
-use clippy_dev::{bless, fmt, ide_setup, new_lint, serve, stderr_length_check, update_lints};
+use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
+use clippy_dev::{bless, fmt, new_lint, serve, setup, stderr_length_check, update_lints};
 fn main() {
     let matches = get_clap_config();
 
@@ -36,7 +36,22 @@ fn main() {
         ("limit_stderr_length", _) => {
             stderr_length_check::check();
         },
-        ("ide_setup", Some(matches)) => ide_setup::run(matches.value_of("rustc-repo-path")),
+        ("setup", Some(sub_command)) => match sub_command.subcommand() {
+            ("intellij", Some(matches)) => setup::intellij::setup_rustc_src(
+                matches
+                    .value_of("rustc-repo-path")
+                    .expect("this field is mandatory and therefore always valid"),
+            ),
+            ("git-hook", Some(matches)) => setup::git_hook::install_hook(matches.is_present("force-override")),
+            ("vscode-tasks", Some(matches)) => setup::vscode::install_tasks(matches.is_present("force-override")),
+            _ => {},
+        },
+        ("remove", Some(sub_command)) => match sub_command.subcommand() {
+            ("git-hook", Some(_)) => setup::git_hook::remove_hook(),
+            ("intellij", Some(_)) => setup::intellij::remove_rustc_src(),
+            ("vscode-tasks", Some(_)) => setup::vscode::remove_tasks(),
+            _ => {},
+        },
         ("serve", Some(matches)) => {
             let port = matches.value_of("port").unwrap().parse().unwrap();
             let lint = matches.value_of("lint");
@@ -48,6 +63,7 @@ fn main() {
 
 fn get_clap_config<'a>() -> ArgMatches<'a> {
     App::new("Clippy developer tooling")
+        .setting(AppSettings::ArgRequiredElseHelp)
         .subcommand(
             SubCommand::with_name("bless")
                 .about("bless the test output changes")
@@ -123,6 +139,7 @@ fn get_clap_config<'a>() -> ArgMatches<'a> {
                         .possible_values(&[
                             "style",
                             "correctness",
+                            "suspicious",
                             "complexity",
                             "perf",
                             "pedantic",
@@ -140,16 +157,54 @@ fn get_clap_config<'a>() -> ArgMatches<'a> {
                 .about("Ensures that stderr files do not grow longer than a certain amount of lines."),
         )
         .subcommand(
-            SubCommand::with_name("ide_setup")
-                .about("Alter dependencies so Intellij Rust can find rustc internals")
-                .arg(
-                    Arg::with_name("rustc-repo-path")
-                        .long("repo-path")
-                        .short("r")
-                        .help("The path to a rustc repo that will be used for setting the dependencies")
-                        .takes_value(true)
-                        .value_name("path")
-                        .required(true),
+            SubCommand::with_name("setup")
+                .about("Support for setting up your personal development environment")
+                .setting(AppSettings::ArgRequiredElseHelp)
+                .subcommand(
+                    SubCommand::with_name("intellij")
+                        .about("Alter dependencies so Intellij Rust can find rustc internals")
+                        .arg(
+                            Arg::with_name("rustc-repo-path")
+                                .long("repo-path")
+                                .short("r")
+                                .help("The path to a rustc repo that will be used for setting the dependencies")
+                                .takes_value(true)
+                                .value_name("path")
+                                .required(true),
+                        ),
+                )
+                .subcommand(
+                    SubCommand::with_name("git-hook")
+                        .about("Add a pre-commit git hook that formats your code to make it look pretty")
+                        .arg(
+                            Arg::with_name("force-override")
+                                .long("force-override")
+                                .short("f")
+                                .help("Forces the override of an existing git pre-commit hook")
+                                .required(false),
+                        ),
+                )
+                .subcommand(
+                    SubCommand::with_name("vscode-tasks")
+                        .about("Add several tasks to vscode for formatting, validation and testing")
+                        .arg(
+                            Arg::with_name("force-override")
+                                .long("force-override")
+                                .short("f")
+                                .help("Forces the override of existing vscode tasks")
+                                .required(false),
+                        ),
+                ),
+        )
+        .subcommand(
+            SubCommand::with_name("remove")
+                .about("Support for undoing changes done by the setup command")
+                .setting(AppSettings::ArgRequiredElseHelp)
+                .subcommand(SubCommand::with_name("git-hook").about("Remove any existing pre-commit git hook"))
+                .subcommand(SubCommand::with_name("vscode-tasks").about("Remove any existing vscode tasks"))
+                .subcommand(
+                    SubCommand::with_name("intellij")
+                        .about("Removes rustc source paths added via `cargo dev setup intellij`"),
                 ),
         )
         .subcommand(
diff --git a/src/tools/clippy/clippy_dev/src/setup/git_hook.rs b/src/tools/clippy/clippy_dev/src/setup/git_hook.rs
new file mode 100644 (file)
index 0000000..3fbb77d
--- /dev/null
@@ -0,0 +1,85 @@
+use std::fs;
+use std::path::Path;
+
+use super::verify_inside_clippy_dir;
+
+/// Rusts setup uses `git rev-parse --git-common-dir` to get the root directory of the repo.
+/// I've decided against this for the sake of simplicity and to make sure that it doesn't install
+/// the hook if `clippy_dev` would be used in the rust tree. The hook also references this tool
+/// for formatting and should therefor only be used in a normal clone of clippy
+const REPO_GIT_DIR: &str = ".git";
+const HOOK_SOURCE_FILE: &str = "util/etc/pre-commit.sh";
+const HOOK_TARGET_FILE: &str = ".git/hooks/pre-commit";
+
+pub fn install_hook(force_override: bool) {
+    if !check_precondition(force_override) {
+        return;
+    }
+
+    // So a little bit of a funny story. Git on unix requires the pre-commit file
+    // to have the `execute` permission to be set. The Rust functions for modifying
+    // these flags doesn't seem to work when executed with normal user permissions.
+    //
+    // However, there is a little hack that is also being used by Rust itself in their
+    // setup script. Git saves the `execute` flag when syncing files. This means
+    // that we can check in a file with execution permissions and the sync it to create
+    // a file with the flag set. We then copy this file here. The copy function will also
+    // include the `execute` permission.
+    match fs::copy(HOOK_SOURCE_FILE, HOOK_TARGET_FILE) {
+        Ok(_) => {
+            println!("info: the hook can be removed with `cargo dev remove git-hook`");
+            println!("git hook successfully installed");
+        },
+        Err(err) => eprintln!(
+            "error: unable to copy `{}` to `{}` ({})",
+            HOOK_SOURCE_FILE, HOOK_TARGET_FILE, err
+        ),
+    }
+}
+
+fn check_precondition(force_override: bool) -> bool {
+    if !verify_inside_clippy_dir() {
+        return false;
+    }
+
+    // Make sure that we can find the git repository
+    let git_path = Path::new(REPO_GIT_DIR);
+    if !git_path.exists() || !git_path.is_dir() {
+        eprintln!("error: clippy_dev was unable to find the `.git` directory");
+        return false;
+    }
+
+    // Make sure that we don't override an existing hook by accident
+    let path = Path::new(HOOK_TARGET_FILE);
+    if path.exists() {
+        if force_override {
+            return delete_git_hook_file(path);
+        }
+
+        eprintln!("error: there is already a pre-commit hook installed");
+        println!("info: use the `--force-override` flag to override the existing hook");
+        return false;
+    }
+
+    true
+}
+
+pub fn remove_hook() {
+    let path = Path::new(HOOK_TARGET_FILE);
+    if path.exists() {
+        if delete_git_hook_file(path) {
+            println!("git hook successfully removed");
+        }
+    } else {
+        println!("no pre-commit hook was found");
+    }
+}
+
+fn delete_git_hook_file(path: &Path) -> bool {
+    if let Err(err) = fs::remove_file(path) {
+        eprintln!("error: unable to delete existing pre-commit git hook ({})", err);
+        false
+    } else {
+        true
+    }
+}
diff --git a/src/tools/clippy/clippy_dev/src/setup/intellij.rs b/src/tools/clippy/clippy_dev/src/setup/intellij.rs
new file mode 100644 (file)
index 0000000..bf741e6
--- /dev/null
@@ -0,0 +1,223 @@
+use std::fs;
+use std::fs::File;
+use std::io::prelude::*;
+use std::path::{Path, PathBuf};
+
+// This module takes an absolute path to a rustc repo and alters the dependencies to point towards
+// the respective rustc subcrates instead of using extern crate xyz.
+// This allows IntelliJ to analyze rustc internals and show proper information inside Clippy
+// code. See https://github.com/rust-lang/rust-clippy/issues/5514 for details
+
+const RUSTC_PATH_SECTION: &str = "[target.'cfg(NOT_A_PLATFORM)'.dependencies]";
+const DEPENDENCIES_SECTION: &str = "[dependencies]";
+
+const CLIPPY_PROJECTS: &[ClippyProjectInfo] = &[
+    ClippyProjectInfo::new("root", "Cargo.toml", "src/driver.rs"),
+    ClippyProjectInfo::new("clippy_lints", "clippy_lints/Cargo.toml", "clippy_lints/src/lib.rs"),
+    ClippyProjectInfo::new("clippy_utils", "clippy_utils/Cargo.toml", "clippy_utils/src/lib.rs"),
+];
+
+/// Used to store clippy project information to later inject the dependency into.
+struct ClippyProjectInfo {
+    /// Only used to display information to the user
+    name: &'static str,
+    cargo_file: &'static str,
+    lib_rs_file: &'static str,
+}
+
+impl ClippyProjectInfo {
+    const fn new(name: &'static str, cargo_file: &'static str, lib_rs_file: &'static str) -> Self {
+        Self {
+            name,
+            cargo_file,
+            lib_rs_file,
+        }
+    }
+}
+
+pub fn setup_rustc_src(rustc_path: &str) {
+    let rustc_source_dir = match check_and_get_rustc_dir(rustc_path) {
+        Ok(path) => path,
+        Err(_) => return,
+    };
+
+    for project in CLIPPY_PROJECTS {
+        if inject_deps_into_project(&rustc_source_dir, project).is_err() {
+            return;
+        }
+    }
+
+    println!("info: the source paths can be removed again with `cargo dev remove intellij`");
+}
+
+fn check_and_get_rustc_dir(rustc_path: &str) -> Result<PathBuf, ()> {
+    let mut path = PathBuf::from(rustc_path);
+
+    if path.is_relative() {
+        match path.canonicalize() {
+            Ok(absolute_path) => {
+                println!("info: the rustc path was resolved to: `{}`", absolute_path.display());
+                path = absolute_path;
+            },
+            Err(err) => {
+                eprintln!("error: unable to get the absolute path of rustc ({})", err);
+                return Err(());
+            },
+        };
+    }
+
+    let path = path.join("compiler");
+    println!("info: looking for compiler sources at: {}", path.display());
+
+    if !path.exists() {
+        eprintln!("error: the given path does not exist");
+        return Err(());
+    }
+
+    if !path.is_dir() {
+        eprintln!("error: the given path is not a directory");
+        return Err(());
+    }
+
+    Ok(path)
+}
+
+fn inject_deps_into_project(rustc_source_dir: &Path, project: &ClippyProjectInfo) -> Result<(), ()> {
+    let cargo_content = read_project_file(project.cargo_file)?;
+    let lib_content = read_project_file(project.lib_rs_file)?;
+
+    if inject_deps_into_manifest(rustc_source_dir, project.cargo_file, &cargo_content, &lib_content).is_err() {
+        eprintln!(
+            "error: unable to inject dependencies into {} with the Cargo file {}",
+            project.name, project.cargo_file
+        );
+        Err(())
+    } else {
+        Ok(())
+    }
+}
+
+/// `clippy_dev` expects to be executed in the root directory of Clippy. This function
+/// loads the given file or returns an error. Having it in this extra function ensures
+/// that the error message looks nice.
+fn read_project_file(file_path: &str) -> Result<String, ()> {
+    let path = Path::new(file_path);
+    if !path.exists() {
+        eprintln!("error: unable to find the file `{}`", file_path);
+        return Err(());
+    }
+
+    match fs::read_to_string(path) {
+        Ok(content) => Ok(content),
+        Err(err) => {
+            eprintln!("error: the file `{}` could not be read ({})", file_path, err);
+            Err(())
+        },
+    }
+}
+
+fn inject_deps_into_manifest(
+    rustc_source_dir: &Path,
+    manifest_path: &str,
+    cargo_toml: &str,
+    lib_rs: &str,
+) -> std::io::Result<()> {
+    // do not inject deps if we have already done so
+    if cargo_toml.contains(RUSTC_PATH_SECTION) {
+        eprintln!(
+            "warn: dependencies are already setup inside {}, skipping file",
+            manifest_path
+        );
+        return Ok(());
+    }
+
+    let extern_crates = lib_rs
+        .lines()
+        // only take dependencies starting with `rustc_`
+        .filter(|line| line.starts_with("extern crate rustc_"))
+        // we have something like "extern crate foo;", we only care about the "foo"
+        // extern crate rustc_middle;
+        //              ^^^^^^^^^^^^
+        .map(|s| &s[13..(s.len() - 1)]);
+
+    let new_deps = extern_crates.map(|dep| {
+        // format the dependencies that are going to be put inside the Cargo.toml
+        format!(
+            "{dep} = {{ path = \"{source_path}/{dep}\" }}\n",
+            dep = dep,
+            source_path = rustc_source_dir.display()
+        )
+    });
+
+    // format a new [dependencies]-block with the new deps we need to inject
+    let mut all_deps = String::from("[target.'cfg(NOT_A_PLATFORM)'.dependencies]\n");
+    new_deps.for_each(|dep_line| {
+        all_deps.push_str(&dep_line);
+    });
+    all_deps.push_str("\n[dependencies]\n");
+
+    // replace "[dependencies]" with
+    // [dependencies]
+    // dep1 = { path = ... }
+    // dep2 = { path = ... }
+    // etc
+    let new_manifest = cargo_toml.replacen("[dependencies]\n", &all_deps, 1);
+
+    // println!("{}", new_manifest);
+    let mut file = File::create(manifest_path)?;
+    file.write_all(new_manifest.as_bytes())?;
+
+    println!("info: successfully setup dependencies inside {}", manifest_path);
+
+    Ok(())
+}
+
+pub fn remove_rustc_src() {
+    for project in CLIPPY_PROJECTS {
+        remove_rustc_src_from_project(project);
+    }
+}
+
+fn remove_rustc_src_from_project(project: &ClippyProjectInfo) -> bool {
+    let mut cargo_content = if let Ok(content) = read_project_file(project.cargo_file) {
+        content
+    } else {
+        return false;
+    };
+    let section_start = if let Some(section_start) = cargo_content.find(RUSTC_PATH_SECTION) {
+        section_start
+    } else {
+        println!(
+            "info: dependencies could not be found in `{}` for {}, skipping file",
+            project.cargo_file, project.name
+        );
+        return true;
+    };
+
+    let end_point = if let Some(end_point) = cargo_content.find(DEPENDENCIES_SECTION) {
+        end_point
+    } else {
+        eprintln!(
+            "error: the end of the rustc dependencies section could not be found in `{}`",
+            project.cargo_file
+        );
+        return false;
+    };
+
+    cargo_content.replace_range(section_start..end_point, "");
+
+    match File::create(project.cargo_file) {
+        Ok(mut file) => {
+            file.write_all(cargo_content.as_bytes()).unwrap();
+            println!("info: successfully removed dependencies inside {}", project.cargo_file);
+            true
+        },
+        Err(err) => {
+            eprintln!(
+                "error: unable to open file `{}` to remove rustc dependencies for {} ({})",
+                project.cargo_file, project.name, err
+            );
+            false
+        },
+    }
+}
diff --git a/src/tools/clippy/clippy_dev/src/setup/mod.rs b/src/tools/clippy/clippy_dev/src/setup/mod.rs
new file mode 100644 (file)
index 0000000..a1e4dd1
--- /dev/null
@@ -0,0 +1,23 @@
+pub mod git_hook;
+pub mod intellij;
+pub mod vscode;
+
+use std::path::Path;
+
+const CLIPPY_DEV_DIR: &str = "clippy_dev";
+
+/// This function verifies that the tool is being executed in the clippy directory.
+/// This is useful to ensure that setups only modify Clippys resources. The verification
+/// is done by checking that `clippy_dev` is a sub directory of the current directory.
+///
+/// It will print an error message and return `false` if the directory could not be
+/// verified.
+fn verify_inside_clippy_dir() -> bool {
+    let path = Path::new(CLIPPY_DEV_DIR);
+    if path.exists() && path.is_dir() {
+        true
+    } else {
+        eprintln!("error: unable to verify that the working directory is clippys directory");
+        false
+    }
+}
diff --git a/src/tools/clippy/clippy_dev/src/setup/vscode.rs b/src/tools/clippy/clippy_dev/src/setup/vscode.rs
new file mode 100644 (file)
index 0000000..d59001b
--- /dev/null
@@ -0,0 +1,104 @@
+use std::fs;
+use std::path::Path;
+
+use super::verify_inside_clippy_dir;
+
+const VSCODE_DIR: &str = ".vscode";
+const TASK_SOURCE_FILE: &str = "util/etc/vscode-tasks.json";
+const TASK_TARGET_FILE: &str = ".vscode/tasks.json";
+
+pub fn install_tasks(force_override: bool) {
+    if !check_install_precondition(force_override) {
+        return;
+    }
+
+    match fs::copy(TASK_SOURCE_FILE, TASK_TARGET_FILE) {
+        Ok(_) => {
+            println!("info: the task file can be removed with `cargo dev remove vscode-tasks`");
+            println!("vscode tasks successfully installed");
+        },
+        Err(err) => eprintln!(
+            "error: unable to copy `{}` to `{}` ({})",
+            TASK_SOURCE_FILE, TASK_TARGET_FILE, err
+        ),
+    }
+}
+
+fn check_install_precondition(force_override: bool) -> bool {
+    if !verify_inside_clippy_dir() {
+        return false;
+    }
+
+    let vs_dir_path = Path::new(VSCODE_DIR);
+    if vs_dir_path.exists() {
+        // verify the target will be valid
+        if !vs_dir_path.is_dir() {
+            eprintln!("error: the `.vscode` path exists but seems to be a file");
+            return false;
+        }
+
+        // make sure that we don't override any existing tasks by accident
+        let path = Path::new(TASK_TARGET_FILE);
+        if path.exists() {
+            if force_override {
+                return delete_vs_task_file(path);
+            }
+
+            eprintln!(
+                "error: there is already a `task.json` file inside the `{}` directory",
+                VSCODE_DIR
+            );
+            println!("info: use the `--force-override` flag to override the existing `task.json` file");
+            return false;
+        }
+    } else {
+        match fs::create_dir(vs_dir_path) {
+            Ok(_) => {
+                println!("info: created `{}` directory for clippy", VSCODE_DIR);
+            },
+            Err(err) => {
+                eprintln!(
+                    "error: the task target directory `{}` could not be created ({})",
+                    VSCODE_DIR, err
+                );
+            },
+        }
+    }
+
+    true
+}
+
+pub fn remove_tasks() {
+    let path = Path::new(TASK_TARGET_FILE);
+    if path.exists() {
+        if delete_vs_task_file(path) {
+            try_delete_vs_directory_if_empty();
+            println!("vscode tasks successfully removed");
+        }
+    } else {
+        println!("no vscode tasks were found");
+    }
+}
+
+fn delete_vs_task_file(path: &Path) -> bool {
+    if let Err(err) = fs::remove_file(path) {
+        eprintln!("error: unable to delete the existing `tasks.json` file ({})", err);
+        return false;
+    }
+
+    true
+}
+
+/// This function will try to delete the `.vscode` directory if it's empty.
+/// It may fail silently.
+fn try_delete_vs_directory_if_empty() {
+    let path = Path::new(VSCODE_DIR);
+    if path.read_dir().map_or(false, |mut iter| iter.next().is_none()) {
+        // The directory is empty. We just try to delete it but allow a silence
+        // fail as an empty `.vscode` directory is still valid
+        let _silence_result = fs::remove_dir(path);
+    } else {
+        // The directory is not empty or could not be read. Either way don't take
+        // any further actions
+    }
+}
index edf6c5f57a49766d44f8a353c55937ac0b015354..db467c26f15466de263ddd1c5a00bac7b1f995e5 100644 (file)
@@ -92,7 +92,10 @@ pub fn run(update_mode: UpdateMode) {
         || {
             // clippy::all should only include the following lint groups:
             let all_group_lints = usable_lints.iter().filter(|l| {
-                l.group == "correctness" || l.group == "style" || l.group == "complexity" || l.group == "perf"
+                matches!(
+                    &*l.group,
+                    "correctness" | "suspicious" | "style" | "complexity" | "perf"
+                )
             });
 
             gen_lint_group_list(all_group_lints)
index 48f2972ec58d1887c166ebdd6f1e6d043c3adb74..42cf7547f519459a6cb470ed8a963a181490d7fd 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "clippy_lints"
 # begin automatic update
-version = "0.1.54"
+version = "0.1.55"
 # end automatic update
 authors = ["The Rust Clippy Developers"]
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
@@ -23,6 +23,7 @@ serde = { version = "1.0", features = ["derive"] }
 serde_json = { version = "1.0", optional = true }
 toml = "0.5.3"
 unicode-normalization = "0.1"
+unicode-script = { version = "0.5.3", default-features = false }
 semver = "0.11"
 rustc-semver = "1.1.0"
 # NOTE: cargo requires serde feat in its url dep
index bc6eec0051a41d872c466b2a0a4f5becee8b5585..17ce3cd809f6fcb9e88618b955750b5fd9372516 100644 (file)
@@ -1,8 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{eq_expr_value, get_trait_def_id, trait_ref_of_method};
-use clippy_utils::{higher, paths, sugg};
+use clippy_utils::{binop_traits, sugg};
+use clippy_utils::{eq_expr_value, trait_ref_of_method};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -55,7 +55,7 @@ declare_clippy_lint! {
     /// a += a + b;
     /// ```
     pub MISREFACTORED_ASSIGN_OP,
-    complexity,
+    suspicious,
     "having a variable on both sides of an assign op"
 }
 
@@ -85,71 +85,34 @@ impl<'tcx> LateLintPass<'tcx> for AssignOps {
                     let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| {
                         let ty = cx.typeck_results().expr_ty(assignee);
                         let rty = cx.typeck_results().expr_ty(rhs);
-                        macro_rules! ops {
-                            ($op:expr,
-                             $cx:expr,
-                             $ty:expr,
-                             $rty:expr,
-                             $($trait_name:ident),+) => {
-                                match $op {
-                                    $(hir::BinOpKind::$trait_name => {
-                                        let [krate, module] = paths::OPS_MODULE;
-                                        let path: [&str; 3] = [krate, module, concat!(stringify!($trait_name), "Assign")];
-                                        let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
-                                            trait_id
-                                        } else {
-                                            return; // useless if the trait doesn't exist
-                                        };
-                                        // check that we are not inside an `impl AssignOp` of this exact operation
-                                        let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id);
-                                        if_chain! {
-                                            if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
-                                            if trait_ref.path.res.def_id() == trait_id;
-                                            then { return; }
+                        if_chain! {
+                            if let Some((_, lang_item)) = binop_traits(op.node);
+                            if let Ok(trait_id) = cx.tcx.lang_items().require(lang_item);
+                            let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id);
+                            if trait_ref_of_method(cx, parent_fn)
+                                .map_or(true, |t| t.path.res.def_id() != trait_id);
+                            if implements_trait(cx, ty, trait_id, &[rty.into()]);
+                            then {
+                                span_lint_and_then(
+                                    cx,
+                                    ASSIGN_OP_PATTERN,
+                                    expr.span,
+                                    "manual implementation of an assign operation",
+                                    |diag| {
+                                        if let (Some(snip_a), Some(snip_r)) =
+                                            (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span))
+                                        {
+                                            diag.span_suggestion(
+                                                expr.span,
+                                                "replace it with",
+                                                format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
+                                                Applicability::MachineApplicable,
+                                            );
                                         }
-                                        implements_trait($cx, $ty, trait_id, &[$rty])
-                                    },)*
-                                    _ => false,
-                                }
+                                    },
+                                );
                             }
                         }
-                        if ops!(
-                            op.node,
-                            cx,
-                            ty,
-                            rty.into(),
-                            Add,
-                            Sub,
-                            Mul,
-                            Div,
-                            Rem,
-                            And,
-                            Or,
-                            BitAnd,
-                            BitOr,
-                            BitXor,
-                            Shr,
-                            Shl
-                        ) {
-                            span_lint_and_then(
-                                cx,
-                                ASSIGN_OP_PATTERN,
-                                expr.span,
-                                "manual implementation of an assign operation",
-                                |diag| {
-                                    if let (Some(snip_a), Some(snip_r)) =
-                                        (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span))
-                                    {
-                                        diag.span_suggestion(
-                                            expr.span,
-                                            "replace it with",
-                                            format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
-                                            Applicability::MachineApplicable,
-                                        );
-                                    }
-                                },
-                            );
-                        }
                     };
 
                     let mut visitor = ExprVisitor {
@@ -206,7 +169,7 @@ fn lint_misrefactored_assign_op(
             if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) {
                 let a = &sugg::Sugg::hir(cx, assignee, "..");
                 let r = &sugg::Sugg::hir(cx, rhs, "..");
-                let long = format!("{} = {}", snip_a, sugg::make_binop(higher::binop(op.node), a, r));
+                let long = format!("{} = {}", snip_a, sugg::make_binop(op.node.into(), a, r));
                 diag.span_suggestion(
                     expr.span,
                     &format!(
index 932cd58bf6259c5783ac210af6814232a746913b..f272ed010a1b03df405044a4750f5b0afe4f64b5 100644 (file)
@@ -173,7 +173,7 @@ declare_clippy_lint! {
     /// #![deny(clippy::as_conversions)]
     /// ```
     pub BLANKET_CLIPPY_RESTRICTION_LINTS,
-    style,
+    suspicious,
     "enabling the complete restriction group"
 }
 
index b26ef33e056981ccd084623f97c13356dadec84b..8eb94f3c28e447943dcbc5702085a4c1bba9614e 100644 (file)
@@ -1,6 +1,6 @@
-use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{diagnostics::span_lint, is_test_module_or_function};
 use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::{Pat, PatKind};
+use rustc_hir::{Item, Pat, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 
@@ -25,18 +25,37 @@ declare_clippy_lint! {
 #[derive(Clone, Debug)]
 pub struct BlacklistedName {
     blacklist: FxHashSet<String>,
+    test_modules_deep: u32,
 }
 
 impl BlacklistedName {
     pub fn new(blacklist: FxHashSet<String>) -> Self {
-        Self { blacklist }
+        Self {
+            blacklist,
+            test_modules_deep: 0,
+        }
+    }
+
+    fn in_test_module(&self) -> bool {
+        self.test_modules_deep != 0
     }
 }
 
 impl_lint_pass!(BlacklistedName => [BLACKLISTED_NAME]);
 
 impl<'tcx> LateLintPass<'tcx> for BlacklistedName {
+    fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+        if is_test_module_or_function(cx.tcx, item) {
+            self.test_modules_deep = self.test_modules_deep.saturating_add(1);
+        }
+    }
+
     fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
+        // Check whether we are under the `test` attribute.
+        if self.in_test_module() {
+            return;
+        }
+
         if let PatKind::Binding(.., ident, _) = pat.kind {
             if self.blacklist.contains(&ident.name.to_string()) {
                 span_lint(
@@ -48,4 +67,10 @@ impl<'tcx> LateLintPass<'tcx> for BlacklistedName {
             }
         }
     }
+
+    fn check_item_post(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+        if is_test_module_or_function(cx.tcx, item) {
+            self.test_modules_deep = self.test_modules_deep.saturating_sub(1);
+        }
+    }
 }
index 877ae002d36e9de67bb360716112cf266929ae4d..4f7ffdcdfb499ac972c9dbd9eeced0153b492ddc 100644 (file)
@@ -1,15 +1,15 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::match_type;
-use clippy_utils::{contains_name, get_pat_name, paths, single_segment_path};
+use clippy_utils::visitors::LocalUsedVisitor;
+use clippy_utils::{path_to_local_id, paths, peel_ref_operators, remove_blocks, strip_pat_refs};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, UnOp};
+use rustc_hir::{BinOpKind, Expr, ExprKind, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, UintTy};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
-use rustc_span::Symbol;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for naive byte counts
@@ -38,42 +38,43 @@ declare_lint_pass!(ByteCount => [NAIVE_BYTECOUNT]);
 impl<'tcx> LateLintPass<'tcx> for ByteCount {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(count, _, count_args, _) = expr.kind;
+            if let ExprKind::MethodCall(count, _, [count_recv], _) = expr.kind;
             if count.ident.name == sym!(count);
-            if count_args.len() == 1;
-            if let ExprKind::MethodCall(filter, _, filter_args, _) = count_args[0].kind;
+            if let ExprKind::MethodCall(filter, _, [filter_recv, filter_arg], _) = count_recv.kind;
             if filter.ident.name == sym!(filter);
-            if filter_args.len() == 2;
-            if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].kind;
+            if let ExprKind::Closure(_, _, body_id, _, _) = filter_arg.kind;
             let body = cx.tcx.hir().body(body_id);
-            if body.params.len() == 1;
-            if let Some(argname) = get_pat_name(body.params[0].pat);
+            if let [param] = body.params;
+            if let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind;
             if let ExprKind::Binary(ref op, l, r) = body.value.kind;
             if op.node == BinOpKind::Eq;
             if match_type(cx,
-                       cx.typeck_results().expr_ty(&filter_args[0]).peel_refs(),
+                       cx.typeck_results().expr_ty(filter_recv).peel_refs(),
                        &paths::SLICE_ITER);
+            let operand_is_arg = |expr| {
+                let expr = peel_ref_operators(cx, remove_blocks(expr));
+                path_to_local_id(expr, arg_id)
+            };
+            let needle = if operand_is_arg(l) {
+                r
+            } else if operand_is_arg(r) {
+                l
+            } else {
+                return;
+            };
+            if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind();
+            if !LocalUsedVisitor::new(cx, arg_id).check_expr(needle);
             then {
-                let needle = match get_path_name(l) {
-                    Some(name) if check_arg(name, argname, r) => r,
-                    _ => match get_path_name(r) {
-                        Some(name) if check_arg(name, argname, l) => l,
-                        _ => { return; }
-                    }
-                };
-                if ty::Uint(UintTy::U8) != *cx.typeck_results().expr_ty(needle).peel_refs().kind() {
-                    return;
-                }
                 let haystack = if let ExprKind::MethodCall(path, _, args, _) =
-                        filter_args[0].kind {
+                        filter_recv.kind {
                     let p = path.ident.name;
                     if (p == sym::iter || p == sym!(iter_mut)) && args.len() == 1 {
                         &args[0]
                     } else {
-                        &filter_args[0]
+                        &filter_recv
                     }
                 } else {
-                    &filter_args[0]
+                    &filter_recv
                 };
                 let mut applicability = Applicability::MaybeIncorrect;
                 span_lint_and_sugg(
@@ -91,24 +92,3 @@ impl<'tcx> LateLintPass<'tcx> for ByteCount {
         };
     }
 }
-
-fn check_arg(name: Symbol, arg: Symbol, needle: &Expr<'_>) -> bool {
-    name == arg && !contains_name(name, needle)
-}
-
-fn get_path_name(expr: &Expr<'_>) -> Option<Symbol> {
-    match expr.kind {
-        ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) | ExprKind::Unary(UnOp::Deref, e) => {
-            get_path_name(e)
-        },
-        ExprKind::Block(b, _) => {
-            if b.stmts.is_empty() {
-                b.expr.as_ref().and_then(|p| get_path_name(p))
-            } else {
-                None
-            }
-        },
-        ExprKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name),
-        _ => None,
-    }
-}
index 8097a1c832613b7c4a1a5b23a953bf8c55315318..21c7b2448cec8dffdc714d22e628b1e1d801e6df 100644 (file)
@@ -2,8 +2,7 @@
 
 use std::path::PathBuf;
 
-use clippy_utils::diagnostics::span_lint;
-use clippy_utils::run_lints;
+use clippy_utils::{diagnostics::span_lint, is_lint_allowed};
 use rustc_hir::{hir_id::CRATE_HIR_ID, Crate};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -85,7 +84,7 @@ fn is_empty_vec(value: &[String]) -> bool {
 
 impl LateLintPass<'_> for CargoCommonMetadata {
     fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
-        if !run_lints(cx, &[CARGO_COMMON_METADATA], CRATE_HIR_ID) {
+        if is_lint_allowed(cx, CARGO_COMMON_METADATA, CRATE_HIR_ID) {
             return;
         }
 
index ab22578abd674efec12970050170789ec492d5d9..a6c3a5b0e83c466bc8b98f14e55ca7070a876da1 100644 (file)
@@ -1,11 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::visitors::LocalUsedVisitor;
-use clippy_utils::{is_lang_ctor, path_to_local, SpanlessEq};
+use clippy_utils::{is_lang_ctor, path_to_local, peel_ref_operators, SpanlessEq};
 use if_chain::if_chain;
 use rustc_hir::LangItem::OptionNone;
-use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, StmtKind, UnOp};
+use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::TypeckResults;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{MultiSpan, Span};
 
@@ -73,7 +72,7 @@ fn check_arm<'tcx>(arm: &Arm<'tcx>, wild_outer_arm: &Arm<'tcx>, cx: &LateContext
         if arms_inner.iter().all(|arm| arm.guard.is_none());
         // match expression must be a local binding
         // match <local> { .. }
-        if let Some(binding_id) = path_to_local(strip_ref_operators(expr_in, cx.typeck_results()));
+        if let Some(binding_id) = path_to_local(peel_ref_operators(cx, expr_in));
         // one of the branches must be "wild-like"
         if let Some(wild_inner_arm_idx) = arms_inner.iter().rposition(|arm_inner| arm_is_wild_like(cx, arm_inner));
         let (wild_inner_arm, non_wild_inner_arm) =
@@ -163,16 +162,3 @@ fn pat_contains_or(pat: &Pat<'_>) -> bool {
     });
     result
 }
-
-/// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is
-/// dereferenced. An overloaded deref such as `Vec` to slice would not be removed.
-fn strip_ref_operators<'hir>(mut expr: &'hir Expr<'hir>, typeck_results: &TypeckResults<'_>) -> &'hir Expr<'hir> {
-    loop {
-        match expr.kind {
-            ExprKind::AddrOf(_, _, e) => expr = e,
-            ExprKind::Unary(UnOp::Deref, e) if typeck_results.expr_ty(e).is_ref() => expr = e,
-            _ => break,
-        }
-    }
-    expr
-}
index 376a14b8181ff6eb739fbb6f9040f377949246c1..9cbcde597686e8c212c45ce95d4e28ad954624cf 100644 (file)
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then};
 use clippy_utils::source::{first_line_of_span, indent_of, reindent_multiline, snippet, snippet_opt};
 use clippy_utils::{
     both, count_eq, eq_expr_value, get_enclosing_block, get_parent_expr, if_sequence, in_macro, is_else_clause,
-    run_lints, search_same, ContainsName, SpanlessEq, SpanlessHash,
+    is_lint_allowed, search_same, ContainsName, SpanlessEq, SpanlessHash,
 };
 use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashSet;
@@ -120,7 +120,10 @@ declare_clippy_lint! {
     ///
     /// **Why is this bad?** Duplicate code is less maintainable.
     ///
-    /// **Known problems:** Hopefully none.
+    /// **Known problems:**
+    /// * The lint doesn't check if the moved expressions modify values that are beeing used in
+    ///   the if condition. The suggestion can in that case modify the behavior of the program.
+    ///   See [rust-clippy#7452](https://github.com/rust-lang/rust-clippy/issues/7452)
     ///
     /// **Example:**
     /// ```ignore
@@ -337,8 +340,8 @@ fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> Option<
             if block_expr_eq;
             if l_stmts.len() == r_stmts.len();
             if l_stmts.len() == current_start_eq;
-            if run_lints(cx, &[IF_SAME_THEN_ELSE], win[0].hir_id);
-            if run_lints(cx, &[IF_SAME_THEN_ELSE], win[1].hir_id);
+            if !is_lint_allowed(cx, IF_SAME_THEN_ELSE, win[0].hir_id);
+            if !is_lint_allowed(cx, IF_SAME_THEN_ELSE, win[1].hir_id);
             then {
                 span_lint_and_note(
                     cx,
@@ -358,8 +361,7 @@ fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> Option<
         expr_eq &= block_expr_eq;
     }
 
-    let has_expr = blocks[0].expr.is_some();
-    if has_expr && !expr_eq {
+    if !expr_eq {
         end_eq = 0;
     }
 
index 7a53d390bb45f00159ce682c485377c7f80b6504..947479db8f5d78e77fdc1b6fa60a08357fb609fa 100644 (file)
@@ -7,7 +7,6 @@ use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::{Ident, Symbol};
@@ -122,7 +121,7 @@ impl LateLintPass<'_> for Default {
                 if let StmtKind::Local(local) = stmt.kind;
                 if let Some(expr) = local.init;
                 if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
-                if !in_external_macro(cx.tcx.sess, expr.span);
+                if !in_macro(expr.span);
                 // only take bindings to identifiers
                 if let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind;
                 // only when assigning `... = Default::default()`
index 759f7d4062d448ba64e3218b6435c65841fb864a..e719a1b0abf8744dd2f483d542c9c017e96e6b67 100644 (file)
@@ -1,5 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet;
+use clippy_utils::numeric_literal;
+use clippy_utils::source::snippet_opt;
 use if_chain::if_chain;
 use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
@@ -7,9 +8,10 @@ use rustc_hir::{
     intravisit::{walk_expr, walk_stmt, NestedVisitorMap, Visitor},
     Body, Expr, ExprKind, HirId, Lit, Stmt, StmtKind,
 };
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::{
     hir::map::Map,
+    lint::in_external_macro,
     ty::{self, FloatTy, IntTy, PolyFnSig, Ty},
 };
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -73,19 +75,29 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
     /// Check whether a passed literal has potential to cause fallback or not.
     fn check_lit(&self, lit: &Lit, lit_ty: Ty<'tcx>) {
         if_chain! {
+                if !in_external_macro(self.cx.sess(), lit.span);
                 if let Some(ty_bound) = self.ty_bounds.last();
                 if matches!(lit.node,
                             LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed));
-                if !ty_bound.is_integral();
+                if !ty_bound.is_numeric();
                 then {
-                    let suffix = match lit_ty.kind() {
-                        ty::Int(IntTy::I32) => "i32",
-                        ty::Float(FloatTy::F64) => "f64",
+                    let (suffix, is_float) = match lit_ty.kind() {
+                        ty::Int(IntTy::I32) => ("i32", false),
+                        ty::Float(FloatTy::F64) => ("f64", true),
                         // Default numeric fallback never results in other types.
                         _ => return,
                     };
 
-                    let sugg = format!("{}_{}", snippet(self.cx, lit.span, ""), suffix);
+                    let src = if let Some(src) = snippet_opt(self.cx, lit.span) {
+                        src
+                    } else {
+                        match lit.node {
+                            LitKind::Int(src, _) => format!("{}", src),
+                            LitKind::Float(src, _) => format!("{}", src),
+                            _ => return,
+                        }
+                    };
+                    let sugg = numeric_literal::format(&src, Some(suffix), is_float);
                     span_lint_and_sugg(
                         self.cx,
                         DEFAULT_NUMERIC_FALLBACK,
@@ -217,10 +229,10 @@ enum TyBound<'tcx> {
 }
 
 impl<'tcx> TyBound<'tcx> {
-    fn is_integral(self) -> bool {
+    fn is_numeric(self) -> bool {
         match self {
             TyBound::Any => true,
-            TyBound::Ty(t) => t.is_integral(),
+            TyBound::Ty(t) => t.is_numeric(),
             TyBound::Nothing => false,
         }
     }
index 04f3d77464f98aa764a9549279bbb9d0e63c741c..2933fbc93418add393c3e579405cf233845b6d1b 100644 (file)
@@ -149,7 +149,7 @@ declare_deprecated_lint! {
     /// enables the `enum_variant_names` lint for public items.
     /// ```
     pub PUB_ENUM_VARIANT_NAMES,
-    "set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items"
+    "set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items"
 }
 
 declare_deprecated_lint! {
@@ -158,5 +158,5 @@ declare_deprecated_lint! {
     /// **Deprecation reason:** The `avoid_breaking_exported_api` config option was added, which
     /// enables the `wrong_self_conversion` lint for public items.
     pub WRONG_PUB_SELF_CONVENTION,
-    "set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items"
+    "set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items"
 }
index 1415f8e235a7e8936ef370fc3613d67a4c05e2a1..682003f9c2c4c99d71d8bccb329b9409ed48d0bf 100644 (file)
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::peel_mid_ty_refs;
-use clippy_utils::{get_parent_node, in_macro, is_allowed};
+use clippy_utils::{get_parent_node, in_macro, is_lint_allowed};
 use rustc_ast::util::parser::PREC_PREFIX;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, UnOp};
@@ -107,7 +107,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
 
                 match kind {
                     RefOp::Method(target_mut)
-                        if !is_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id)
+                        if !is_lint_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id)
                             && is_linted_explicit_deref_position(parent, expr.hir_id, expr.span) =>
                     {
                         self.state = Some((
index 840c1eba79d115ad120dffc8c8a9edaaebbfc792..7aafaf71383011a93c298bf5d7b5931616264344 100644 (file)
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_then};
 use clippy_utils::paths;
 use clippy_utils::ty::{implements_trait, is_copy};
-use clippy_utils::{get_trait_def_id, is_allowed, is_automatically_derived, match_def_path};
+use clippy_utils::{get_trait_def_id, is_automatically_derived, is_lint_allowed, match_def_path};
 use if_chain::if_chain;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor};
@@ -362,7 +362,7 @@ fn check_unsafe_derive_deserialize<'tcx>(
         if let ty::Adt(def, _) = ty.kind();
         if let Some(local_def_id) = def.did.as_local();
         let adt_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
-        if !is_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id);
+        if !is_lint_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id);
         if cx.tcx.inherent_impls(def.did)
             .iter()
             .map(|imp_did| item_from_def_id(cx, *imp_did))
@@ -410,13 +410,8 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
         }
 
         if let ExprKind::Block(block, _) = expr.kind {
-            match block.rules {
-                BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
-                | BlockCheckMode::PushUnsafeBlock(UnsafeSource::UserProvided)
-                | BlockCheckMode::PopUnsafeBlock(UnsafeSource::UserProvided) => {
-                    self.has_unsafe = true;
-                },
-                _ => {},
+            if let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules {
+                self.has_unsafe = true;
             }
         }
 
index ded0a0fff54b24573df89db5978904dbb71d2d1b..aa1a609afedc0b91edfac0fbd4e3720d327f423b 100644 (file)
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint;
 use clippy_utils::fn_def_id;
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::Expr;
+use rustc_hir::{def::Res, def_id::DefId, Crate, Expr};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::Symbol;
@@ -13,21 +13,14 @@ declare_clippy_lint! {
     /// **Why is this bad?** Some methods are undesirable in certain contexts,
     /// and it's beneficial to lint for them as needed.
     ///
-    /// **Known problems:** Currently, you must write each function as a
-    /// fully-qualified path. This lint doesn't support aliases or reexported
-    /// names; be aware that many types in `std` are actually reexports.
-    ///
-    /// For example, if you want to disallow `Duration::as_secs`, your clippy.toml
-    /// configuration would look like
-    /// `disallowed-methods = ["core::time::Duration::as_secs"]` and not
-    /// `disallowed-methods = ["std::time::Duration::as_secs"]` as you might expect.
+    /// **Known problems:** None.
     ///
     /// **Example:**
     ///
     /// An example clippy.toml configuration:
     /// ```toml
     /// # clippy.toml
-    /// disallowed-methods = ["alloc::vec::Vec::leak", "std::time::Instant::now"]
+    /// disallowed-methods = ["std::vec::Vec::leak", "std::time::Instant::now"]
     /// ```
     ///
     /// ```rust,ignore
@@ -52,6 +45,7 @@ declare_clippy_lint! {
 #[derive(Clone, Debug)]
 pub struct DisallowedMethod {
     disallowed: FxHashSet<Vec<Symbol>>,
+    def_ids: FxHashSet<(DefId, Vec<Symbol>)>,
 }
 
 impl DisallowedMethod {
@@ -61,6 +55,7 @@ impl DisallowedMethod {
                 .iter()
                 .map(|s| s.split("::").map(|seg| Symbol::intern(seg)).collect::<Vec<_>>())
                 .collect(),
+            def_ids: FxHashSet::default(),
         }
     }
 }
@@ -68,10 +63,20 @@ impl DisallowedMethod {
 impl_lint_pass!(DisallowedMethod => [DISALLOWED_METHOD]);
 
 impl<'tcx> LateLintPass<'tcx> for DisallowedMethod {
+    fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
+        for path in &self.disallowed {
+            let segs = path.iter().map(ToString::to_string).collect::<Vec<_>>();
+            if let Res::Def(_, id) = clippy_utils::path_to_res(cx, &segs.iter().map(String::as_str).collect::<Vec<_>>())
+            {
+                self.def_ids.insert((id, path.clone()));
+            }
+        }
+    }
+
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if let Some(def_id) = fn_def_id(cx, expr) {
-            let func_path = cx.get_def_path(def_id);
-            if self.disallowed.contains(&func_path) {
+            if self.def_ids.iter().any(|(id, _)| def_id == *id) {
+                let func_path = cx.get_def_path(def_id);
                 let func_path_string = func_path
                     .into_iter()
                     .map(Symbol::to_ident_string)
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
new file mode 100644 (file)
index 0000000..12c5256
--- /dev/null
@@ -0,0 +1,112 @@
+use clippy_utils::diagnostics::span_lint;
+use rustc_ast::ast;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_lint::{EarlyContext, EarlyLintPass, Level};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use unicode_script::{Script, UnicodeScript};
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for usage of unicode scripts other than those explicitly allowed
+    /// by the lint config.
+    ///
+    /// This lint doesn't take into account non-text scripts such as `Unknown` and `Linear_A`.
+    /// It also ignores the `Common` script type.
+    /// While configuring, be sure to use official script name [aliases] from
+    /// [the list of supported scripts][supported_scripts].
+    ///
+    /// See also: [`non_ascii_idents`].
+    ///
+    /// [aliases]: http://www.unicode.org/reports/tr24/tr24-31.html#Script_Value_Aliases
+    /// [supported_scripts]: https://www.unicode.org/iso15924/iso15924-codes.html
+    ///
+    /// **Why is this bad?** It may be not desired to have many different scripts for
+    /// identifiers in the codebase.
+    ///
+    /// Note that if you only want to allow plain English, you might want to use
+    /// built-in [`non_ascii_idents`] lint instead.
+    ///
+    /// [`non_ascii_idents`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#non-ascii-idents
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust
+    /// // Assuming that `clippy.toml` contains the following line:
+    /// // allowed-locales = ["Latin", "Cyrillic"]
+    /// let counter = 10; // OK, latin is allowed.
+    /// let счётчик = 10; // OK, cyrillic is allowed.
+    /// let zähler = 10; // OK, it's still latin.
+    /// let カウンタ = 10; // Will spawn the lint.
+    /// ```
+    pub DISALLOWED_SCRIPT_IDENTS,
+    restriction,
+    "usage of non-allowed Unicode scripts"
+}
+
+#[derive(Clone, Debug)]
+pub struct DisallowedScriptIdents {
+    whitelist: FxHashSet<Script>,
+}
+
+impl DisallowedScriptIdents {
+    pub fn new(whitelist: &[String]) -> Self {
+        let whitelist = whitelist
+            .iter()
+            .map(String::as_str)
+            .filter_map(Script::from_full_name)
+            .collect();
+        Self { whitelist }
+    }
+}
+
+impl_lint_pass!(DisallowedScriptIdents => [DISALLOWED_SCRIPT_IDENTS]);
+
+impl EarlyLintPass for DisallowedScriptIdents {
+    fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
+        // Implementation is heavily inspired by the implementation of [`non_ascii_idents`] lint:
+        // https://github.com/rust-lang/rust/blob/master/compiler/rustc_lint/src/non_ascii_idents.rs
+
+        let check_disallowed_script_idents = cx.builder.lint_level(DISALLOWED_SCRIPT_IDENTS).0 != Level::Allow;
+        if !check_disallowed_script_idents {
+            return;
+        }
+
+        let symbols = cx.sess.parse_sess.symbol_gallery.symbols.lock();
+        // Sort by `Span` so that error messages make sense with respect to the
+        // order of identifier locations in the code.
+        let mut symbols: Vec<_> = symbols.iter().collect();
+        symbols.sort_unstable_by_key(|k| k.1);
+
+        for (symbol, &span) in &symbols {
+            // Note: `symbol.as_str()` is an expensive operation, thus should not be called
+            // more than once for a single symbol.
+            let symbol_str = symbol.as_str();
+            if symbol_str.is_ascii() {
+                continue;
+            }
+
+            for c in symbol_str.chars() {
+                // We want to iterate through all the scripts associated with this character
+                // and check whether at least of one scripts is in the whitelist.
+                let forbidden_script = c
+                    .script_extension()
+                    .iter()
+                    .find(|script| !self.whitelist.contains(script));
+                if let Some(script) = forbidden_script {
+                    span_lint(
+                        cx,
+                        DISALLOWED_SCRIPT_IDENTS,
+                        span,
+                        &format!(
+                            "identifier `{}` has a Unicode script that is not allowed by configuration: {}",
+                            symbol_str,
+                            script.full_name()
+                        ),
+                    );
+                    // We don't want to spawn warning multiple times over a single identifier.
+                    break;
+                }
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_type.rs b/src/tools/clippy/clippy_lints/src/disallowed_type.rs
new file mode 100644 (file)
index 0000000..e4a88c6
--- /dev/null
@@ -0,0 +1,126 @@
+use clippy_utils::diagnostics::span_lint;
+
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::{
+    def::Res, def_id::DefId, Crate, Item, ItemKind, PolyTraitRef, TraitBoundModifier, Ty, TyKind, UseKind,
+};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{Span, Symbol};
+
+declare_clippy_lint! {
+    /// **What it does:** Denies the configured types in clippy.toml.
+    ///
+    /// **Why is this bad?** Some types are undesirable in certain contexts.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// N.B. There is no way to ban primitive types.
+    ///
+    /// **Example:**
+    ///
+    /// An example clippy.toml configuration:
+    /// ```toml
+    /// # clippy.toml
+    /// disallowed-methods = ["std::collections::BTreeMap"]
+    /// ```
+    ///
+    /// ```rust,ignore
+    /// use std::collections::BTreeMap;
+    /// // or its use
+    /// let x = std::collections::BTreeMap::new();
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// // A similar type that is allowed by the config
+    /// use std::collections::HashMap;
+    /// ```
+    pub DISALLOWED_TYPE,
+    nursery,
+    "use of a disallowed type"
+}
+#[derive(Clone, Debug)]
+pub struct DisallowedType {
+    disallowed: FxHashSet<Vec<Symbol>>,
+    def_ids: FxHashSet<(DefId, Vec<Symbol>)>,
+}
+
+impl DisallowedType {
+    pub fn new(disallowed: &FxHashSet<String>) -> Self {
+        Self {
+            disallowed: disallowed
+                .iter()
+                .map(|s| s.split("::").map(|seg| Symbol::intern(seg)).collect::<Vec<_>>())
+                .collect(),
+            def_ids: FxHashSet::default(),
+        }
+    }
+}
+
+impl_lint_pass!(DisallowedType => [DISALLOWED_TYPE]);
+
+impl<'tcx> LateLintPass<'tcx> for DisallowedType {
+    fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
+        for path in &self.disallowed {
+            let segs = path.iter().map(ToString::to_string).collect::<Vec<_>>();
+            if let Res::Def(_, id) = clippy_utils::path_to_res(cx, &segs.iter().map(String::as_str).collect::<Vec<_>>())
+            {
+                self.def_ids.insert((id, path.clone()));
+            }
+        }
+    }
+
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+        if_chain! {
+            if let ItemKind::Use(path, UseKind::Single) = &item.kind;
+            if let Res::Def(_, did) = path.res;
+            if let Some((_, name)) = self.def_ids.iter().find(|(id, _)| *id == did);
+            then {
+                emit(cx, name, item.span,);
+            }
+        }
+    }
+
+    fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
+        if_chain! {
+            if let TyKind::Path(path) = &ty.kind;
+            if let Some(did) = cx.qpath_res(path, ty.hir_id).opt_def_id();
+            if let Some((_, name)) = self.def_ids.iter().find(|(id, _)| *id == did);
+            then {
+                emit(cx, name, path.span());
+            }
+        }
+    }
+
+    fn check_poly_trait_ref(&mut self, cx: &LateContext<'tcx>, poly: &'tcx PolyTraitRef<'tcx>, _: TraitBoundModifier) {
+        if_chain! {
+            if let Res::Def(_, did) = poly.trait_ref.path.res;
+            if let Some((_, name)) = self.def_ids.iter().find(|(id, _)| *id == did);
+            then {
+                emit(cx, name, poly.trait_ref.path.span);
+            }
+        }
+    }
+
+    // TODO: if non primitive const generics are a thing
+    // fn check_generic_arg(&mut self, cx: &LateContext<'tcx>, arg: &'tcx GenericArg<'tcx>) {
+    //     match arg {
+    //         GenericArg::Const(c) => {},
+    //     }
+    // }
+    // fn check_generic_param(&mut self, cx: &LateContext<'tcx>, param: &'tcx GenericParam<'tcx>) {
+    //     match param.kind {
+    //         GenericParamKind::Const { .. } => {},
+    //     }
+    // }
+}
+
+fn emit(cx: &LateContext<'_>, name: &[Symbol], span: Span) {
+    let name = name.iter().map(|s| s.to_ident_string()).collect::<Vec<_>>().join("::");
+    span_lint(
+        cx,
+        DISALLOWED_TYPE,
+        span,
+        &format!("`{}` is not allowed according to config", name),
+    );
+}
index e67ec4e06c547d3455f6cd83507ddd227d503a3e..0c19988a975a85b156031f4616084317be3c6059 100644 (file)
@@ -1,4 +1,5 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_note};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_note};
+use clippy_utils::source::first_line_of_span;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use clippy_utils::{is_entrypoint_fn, is_expn_of, match_panic_def_id, method_chain_args, return_ty};
 use if_chain::if_chain;
@@ -25,6 +26,7 @@ use rustc_span::source_map::{BytePos, FilePathMapping, MultiSpan, SourceMap, Spa
 use rustc_span::{sym, FileName, Pos};
 use std::io;
 use std::ops::Range;
+use std::thread;
 use url::Url;
 
 declare_clippy_lint! {
@@ -37,7 +39,8 @@ declare_clippy_lint! {
     /// consider that.
     ///
     /// **Known problems:** Lots of bad docs won’t be fixed, what the lint checks
-    /// for is limited, and there are still false positives.
+    /// for is limited, and there are still false positives. HTML elements and their
+    /// content are not linted.
     ///
     /// In addition, when writing documentation comments, including `[]` brackets
     /// inside a link text would trip the parser. Therfore, documenting link with
@@ -469,11 +472,11 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     spans: &[(usize, Span)],
 ) -> DocHeaders {
     // true if a safety header was found
-    use pulldown_cmark::CodeBlockKind;
     use pulldown_cmark::Event::{
         Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text,
     };
-    use pulldown_cmark::Tag::{CodeBlock, Heading, Link};
+    use pulldown_cmark::Tag::{CodeBlock, Heading, Item, Link, Paragraph};
+    use pulldown_cmark::{CodeBlockKind, CowStr};
 
     let mut headers = DocHeaders {
         safety: false,
@@ -485,6 +488,9 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     let mut in_heading = false;
     let mut is_rust = false;
     let mut edition = None;
+    let mut ticks_unbalanced = false;
+    let mut text_to_check: Vec<(CowStr<'_>, Span)> = Vec::new();
+    let mut paragraph_span = spans.get(0).expect("function isn't called if doc comment is empty").1;
     for (event, range) in events {
         match event {
             Start(CodeBlock(ref kind)) => {
@@ -510,13 +516,42 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
             },
             Start(Link(_, url, _)) => in_link = Some(url),
             End(Link(..)) => in_link = None,
-            Start(Heading(_)) => in_heading = true,
-            End(Heading(_)) => in_heading = false,
+            Start(Heading(_) | Paragraph | Item) => {
+                if let Start(Heading(_)) = event {
+                    in_heading = true;
+                }
+                ticks_unbalanced = false;
+                let (_, span) = get_current_span(spans, range.start);
+                paragraph_span = first_line_of_span(cx, span);
+            },
+            End(Heading(_) | Paragraph | Item) => {
+                if let End(Heading(_)) = event {
+                    in_heading = false;
+                }
+                if ticks_unbalanced {
+                    span_lint_and_help(
+                        cx,
+                        DOC_MARKDOWN,
+                        paragraph_span,
+                        "backticks are unbalanced",
+                        None,
+                        "a backtick may be missing a pair",
+                    );
+                } else {
+                    for (text, span) in text_to_check {
+                        check_text(cx, valid_idents, &text, span);
+                    }
+                }
+                text_to_check = Vec::new();
+            },
             Start(_tag) | End(_tag) => (), // We don't care about other tags
             Html(_html) => (),             // HTML is weird, just ignore it
             SoftBreak | HardBreak | TaskListMarker(_) | Code(_) | Rule => (),
             FootnoteReference(text) | Text(text) => {
-                if Some(&text) == in_link.as_ref() {
+                let (begin, span) = get_current_span(spans, range.start);
+                paragraph_span = paragraph_span.with_hi(span.hi());
+                ticks_unbalanced |= text.contains('`') && !in_code;
+                if Some(&text) == in_link.as_ref() || ticks_unbalanced {
                     // Probably a link of the form `<http://example.com>`
                     // Which are represented as a link to "http://example.com" with
                     // text "http://example.com" by pulldown-cmark
@@ -525,11 +560,6 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                 headers.safety |= in_heading && text.trim() == "Safety";
                 headers.errors |= in_heading && text.trim() == "Errors";
                 headers.panics |= in_heading && text.trim() == "Panics";
-                let index = match spans.binary_search_by(|c| c.0.cmp(&range.start)) {
-                    Ok(o) => o,
-                    Err(e) => e - 1,
-                };
-                let (begin, span) = spans[index];
                 if in_code {
                     if is_rust {
                         let edition = edition.unwrap_or_else(|| cx.tcx.sess.edition());
@@ -538,8 +568,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                 } else {
                     // Adjust for the beginning of the current `Event`
                     let span = span.with_lo(span.lo() + BytePos::from_usize(range.start - begin));
-
-                    check_text(cx, valid_idents, &text, span);
+                    text_to_check.push((text, span));
                 }
             },
         }
@@ -547,18 +576,26 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     headers
 }
 
+fn get_current_span(spans: &[(usize, Span)], idx: usize) -> (usize, Span) {
+    let index = match spans.binary_search_by(|c| c.0.cmp(&idx)) {
+        Ok(o) => o,
+        Err(e) => e - 1,
+    };
+    spans[index]
+}
+
 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);
                 let handler = Handler::with_emitter(false, None, box emitter);
                 let sess = ParseSess::with_span_handler(handler, sm);
 
-                let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code.into()) {
+                let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code) {
                     Ok(p) => p,
                     Err(errs) => {
                         for mut err in errs {
@@ -613,7 +650,13 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
         .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 a3a8e748d99a0f5a261f3bf8806c3063607cd50b..d39cabfb2825beb141d1afacd5cecde3b087866d 100644 (file)
@@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
             if macro_with_not_op(&left.kind) || macro_with_not_op(&right.kind) {
                 return;
             }
-            if is_useless_with_eq_exprs(higher::binop(op.node)) && eq_expr_value(cx, left, right) {
+            if is_useless_with_eq_exprs(op.node.into()) && eq_expr_value(cx, left, right) {
                 span_lint(
                     cx,
                     EQ_OP,
index 3581ab41906f414f26e97311c5d8360c2c855f21..5f400d079da2f1d7b5277e8450703003a6d2a0cc 100644 (file)
@@ -11,7 +11,7 @@ use rustc_span::source_map::Span;
 use rustc_span::symbol::kw;
 use rustc_target::abi::LayoutOf;
 use rustc_target::spec::abi::Abi;
-use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
+use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
 #[derive(Copy, Clone)]
 pub struct BoxedLocal {
@@ -133,13 +133,10 @@ fn is_argument(map: rustc_middle::hir::map::Map<'_>, id: HirId) -> bool {
 }
 
 impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
-    fn consume(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, mode: ConsumeMode) {
+    fn consume(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) {
         if cmt.place.projections.is_empty() {
             if let PlaceBase::Local(lid) = cmt.place.base {
-                if let ConsumeMode::Move = mode {
-                    // moved out or in. clearly can't be localized
-                    self.set.remove(&lid);
-                }
+                self.set.remove(&lid);
                 let map = &self.cx.tcx.hir();
                 if let Some(Node::Binding(_)) = map.find(cmt.hir_id) {
                     if self.set.contains(&lid) {
index 8d066f305ee85e44b8dab91d14b04516fe195f87..667eb8eb283bbb09997d47f8589bd86118e53e52 100644 (file)
@@ -1,15 +1,16 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::higher;
 use clippy_utils::higher::VecArgs;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::{implements_trait, type_is_unsafe_function};
+use clippy_utils::usage::UsedAfterExprVisitor;
+use clippy_utils::{get_enclosing_loop_or_closure, higher};
 use clippy_utils::{is_adjusted, iter_input_pats};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{def_id, Expr, ExprKind, Param, PatKind, QPath};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, ClosureKind, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
@@ -86,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
     }
 }
 
-fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) {
+fn check_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
     if let ExprKind::Closure(_, decl, eid, _, _) = expr.kind {
         let body = cx.tcx.hir().body(eid);
         let ex = &body.value;
@@ -131,7 +132,18 @@ fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) {
 
             then {
                 span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
-                    if let Some(snippet) = snippet_opt(cx, caller.span) {
+                    if let Some(mut snippet) = snippet_opt(cx, caller.span) {
+                        if_chain! {
+                            if let ty::Closure(_, substs) = fn_ty.kind();
+                            if let ClosureKind::FnMut = substs.as_closure().kind();
+                            if UsedAfterExprVisitor::is_found(cx, caller)
+                                || get_enclosing_loop_or_closure(cx.tcx, expr).is_some();
+
+                            then {
+                                // Mutable closure is used after current expr; we cannot consume it.
+                                snippet = format!("&mut {}", snippet);
+                            }
+                        }
                         diag.span_suggestion(
                             expr.span,
                             "replace the closure with the function itself",
index 5fdf5bc9e9d118d366f2a2ebaeafb8767a1fb40b..03a8b40df555fde5f0f4c1c1480571d000d9dc91 100644 (file)
@@ -38,7 +38,7 @@ declare_clippy_lint! {
     /// let a = tmp + x;
     /// ```
     pub EVAL_ORDER_DEPENDENCE,
-    complexity,
+    suspicious,
     "whether a variable read occurs before a write depends on sub-expression evaluation order"
 }
 
index da4936ff25b6d22d19e38f502e8d32c106cce991..66724294804a8414d1dfbbda3ac5050051fc4349 100644 (file)
@@ -1,9 +1,9 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::higher::FormatArgsExpn;
 use clippy_utils::{is_expn_of, match_function_call, paths};
 use if_chain::if_chain;
-use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_hir::{BorrowKind, Expr, ExprKind};
+use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
@@ -34,29 +34,26 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
             // match call to unwrap
-            if let ExprKind::MethodCall(unwrap_fun, _, unwrap_args, _) = expr.kind;
+            if let ExprKind::MethodCall(unwrap_fun, _, [write_call], _) = expr.kind;
             if unwrap_fun.ident.name == sym::unwrap;
             // match call to write_fmt
-            if !unwrap_args.is_empty();
-            if let ExprKind::MethodCall(write_fun, _, write_args, _) =
-                unwrap_args[0].kind;
+            if let ExprKind::MethodCall(write_fun, _, [write_recv, write_arg], _) = write_call.kind;
             if write_fun.ident.name == sym!(write_fmt);
             // match calls to std::io::stdout() / std::io::stderr ()
-            if !write_args.is_empty();
-            if let Some(dest_name) = if match_function_call(cx, &write_args[0], &paths::STDOUT).is_some() {
+            if let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() {
                 Some("stdout")
-            } else if match_function_call(cx, &write_args[0], &paths::STDERR).is_some() {
+            } else if match_function_call(cx, write_recv, &paths::STDERR).is_some() {
                 Some("stderr")
             } else {
                 None
             };
+            if let Some(format_args) = FormatArgsExpn::parse(write_arg);
             then {
-                let write_span = unwrap_args[0].span;
                 let calling_macro =
                     // ordering is important here, since `writeln!` uses `write!` internally
-                    if is_expn_of(write_span, "writeln").is_some() {
+                    if is_expn_of(write_call.span, "writeln").is_some() {
                         Some("writeln")
-                    } else if is_expn_of(write_span, "write").is_some() {
+                    } else if is_expn_of(write_call.span, "write").is_some() {
                         Some("write")
                     } else {
                         None
@@ -70,82 +67,40 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
                 // We need to remove the last trailing newline from the string because the
                 // underlying `fmt::write` function doesn't know whether `println!` or `print!` was
                 // used.
-                if let Some(mut write_output) = write_output_string(write_args) {
+                let (used, sugg_mac) = if let Some(macro_name) = calling_macro {
+                    (
+                        format!("{}!({}(), ...)", macro_name, dest_name),
+                        macro_name.replace("write", "print"),
+                    )
+                } else {
+                    (
+                        format!("{}().write_fmt(...)", dest_name),
+                        "print".into(),
+                    )
+                };
+                let msg = format!("use of `{}.unwrap()`", used);
+                if let [write_output] = *format_args.format_string_symbols {
+                    let mut write_output = write_output.to_string();
                     if write_output.ends_with('\n') {
                         write_output.pop();
                     }
 
-                    if let Some(macro_name) = calling_macro {
-                        span_lint_and_sugg(
-                            cx,
-                            EXPLICIT_WRITE,
-                            expr.span,
-                            &format!(
-                                "use of `{}!({}(), ...).unwrap()`",
-                                macro_name,
-                                dest_name
-                            ),
-                            "try this",
-                            format!("{}{}!(\"{}\")", prefix, macro_name.replace("write", "print"), write_output.escape_default()),
-                            Applicability::MachineApplicable
-                        );
-                    } else {
-                        span_lint_and_sugg(
-                            cx,
-                            EXPLICIT_WRITE,
-                            expr.span,
-                            &format!("use of `{}().write_fmt(...).unwrap()`", dest_name),
-                            "try this",
-                            format!("{}print!(\"{}\")", prefix, write_output.escape_default()),
-                            Applicability::MachineApplicable
-                        );
-                    }
+                    let sugg = format!("{}{}!(\"{}\")", prefix, sugg_mac, write_output.escape_default());
+                    span_lint_and_sugg(
+                        cx,
+                        EXPLICIT_WRITE,
+                        expr.span,
+                        &msg,
+                        "try this",
+                        sugg,
+                        Applicability::MachineApplicable
+                    );
                 } else {
                     // We don't have a proper suggestion
-                    if let Some(macro_name) = calling_macro {
-                        span_lint(
-                            cx,
-                            EXPLICIT_WRITE,
-                            expr.span,
-                            &format!(
-                                "use of `{}!({}(), ...).unwrap()`. Consider using `{}{}!` instead",
-                                macro_name,
-                                dest_name,
-                                prefix,
-                                macro_name.replace("write", "print")
-                            )
-                        );
-                    } else {
-                        span_lint(
-                            cx,
-                            EXPLICIT_WRITE,
-                            expr.span,
-                            &format!("use of `{}().write_fmt(...).unwrap()`. Consider using `{}print!` instead", dest_name, prefix),
-                        );
-                    }
+                    let help = format!("consider using `{}{}!` instead", prefix, sugg_mac);
+                    span_lint_and_help(cx, EXPLICIT_WRITE, expr.span, &msg, None, &help);
                 }
-
             }
         }
     }
 }
-
-// Extract the output string from the given `write_args`.
-fn write_output_string(write_args: &[Expr<'_>]) -> Option<String> {
-    if_chain! {
-        // Obtain the string that should be printed
-        if write_args.len() > 1;
-        if let ExprKind::Call(_, output_args) = write_args[1].kind;
-        if !output_args.is_empty();
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, output_string_expr) = output_args[0].kind;
-        if let ExprKind::Array(string_exprs) = output_string_expr.kind;
-        // we only want to provide an automatic suggestion for simple (non-format) strings
-        if string_exprs.len() == 1;
-        if let ExprKind::Lit(ref lit) = string_exprs[0].kind;
-        if let LitKind::Str(ref write_output, _) = lit.node;
-        then {
-            return Some(write_output.to_string())
-        }
-    }
-    None
-}
index b5ebe5f90ba25c6733ccafe8f054db109f08ed1f..1e503cc795ccbb70d9ec7c2fb002b703d5ef5c24 100644 (file)
@@ -36,7 +36,7 @@ declare_clippy_lint! {
      /// }
      /// ```
     pub FLOAT_EQUALITY_WITHOUT_ABS,
-    correctness,
+    suspicious,
     "float equality check without `.abs()`"
 }
 
index c2b055ed6488e4e9bdeb0d34e1980a16c8e09fdc..ca3490d8edad98c95df69f46abab20acf2335791 100644 (file)
@@ -1,17 +1,16 @@
-use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::paths;
-use clippy_utils::source::{snippet, snippet_opt};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::higher::FormatExpn;
+use clippy_utils::last_path_segment;
+use clippy_utils::source::{snippet_opt, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
-use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_expn_of, last_path_segment, match_def_path, match_function_call};
 use if_chain::if_chain;
-use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, MatchSource, PatKind};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_hir::{BorrowKind, Expr, ExprKind, QPath};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::source_map::Span;
-use rustc_span::sym;
+use rustc_span::symbol::kw;
+use rustc_span::{sym, Span};
 
 declare_clippy_lint! {
     /// **What it does:** Checks for the use of `format!("string literal with no
@@ -44,130 +43,78 @@ declare_lint_pass!(UselessFormat => [USELESS_FORMAT]);
 
 impl<'tcx> LateLintPass<'tcx> for UselessFormat {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        let span = match is_expn_of(expr.span, "format") {
-            Some(s) if !s.from_expansion() => s,
+        let FormatExpn { call_site, format_args } = match FormatExpn::parse(expr) {
+            Some(e) if !e.call_site.from_expansion() => e,
             _ => return,
         };
 
-        // Operate on the only argument of `alloc::fmt::format`.
-        if let Some(sugg) = on_new_v1(cx, expr) {
-            span_useless_format(cx, span, "consider using `.to_string()`", sugg);
-        } else if let Some(sugg) = on_new_v1_fmt(cx, expr) {
-            span_useless_format(cx, span, "consider using `.to_string()`", sugg);
-        }
-    }
-}
-
-fn span_useless_format<T: LintContext>(cx: &T, span: Span, help: &str, mut sugg: String) {
-    let to_replace = span.source_callsite();
-
-    // The callsite span contains the statement semicolon for some reason.
-    let snippet = snippet(cx, to_replace, "..");
-    if snippet.ends_with(';') {
-        sugg.push(';');
-    }
-
-    span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |diag| {
-        diag.span_suggestion(
-            to_replace,
-            help,
-            sugg,
-            Applicability::MachineApplicable, // snippet
-        );
-    });
-}
-
-fn on_argumentv1_new<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) -> Option<String> {
-    if_chain! {
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, format_args) = expr.kind;
-        if let ExprKind::Array(elems) = arms[0].body.kind;
-        if elems.len() == 1;
-        if let Some(args) = match_function_call(cx, &elems[0], &paths::FMT_ARGUMENTV1_NEW);
-        // matches `core::fmt::Display::fmt`
-        if args.len() == 2;
-        if let ExprKind::Path(ref qpath) = args[1].kind;
-        if let Some(did) = cx.qpath_res(qpath, args[1].hir_id).opt_def_id();
-        if match_def_path(cx, did, &paths::DISPLAY_FMT_METHOD);
-        // check `(arg0,)` in match block
-        if let PatKind::Tuple(pats, None) = arms[0].pat.kind;
-        if pats.len() == 1;
-        then {
-            let ty = cx.typeck_results().pat_ty(pats[0]).peel_refs();
-            if *ty.kind() != rustc_middle::ty::Str && !is_type_diagnostic_item(cx, ty, sym::string_type) {
-                return None;
-            }
-            if let ExprKind::Lit(ref lit) = format_args.kind {
-                if let LitKind::Str(ref s, _) = lit.node {
-                    return Some(format!("{:?}.to_string()", s.as_str()));
+        let mut applicability = Applicability::MachineApplicable;
+        if format_args.value_args.is_empty() {
+            if_chain! {
+                if let [e] = &*format_args.format_string_parts;
+                if let ExprKind::Lit(lit) = &e.kind;
+                if let Some(s_src) = snippet_opt(cx, lit.span);
+                then {
+                    // Simulate macro expansion, converting {{ and }} to { and }.
+                    let s_expand = s_src.replace("{{", "{").replace("}}", "}");
+                    let sugg = format!("{}.to_string()", s_expand);
+                    span_useless_format(cx, call_site, sugg, applicability);
                 }
-            } else {
-                let sugg = Sugg::hir(cx, format_args, "<arg>");
-                if let ExprKind::MethodCall(path, _, _, _) = format_args.kind {
-                    if path.ident.name == sym!(to_string) {
-                        return Some(format!("{}", sugg));
-                    }
-                } else if let ExprKind::Binary(..) = format_args.kind {
-                    return Some(format!("{}", sugg));
+            }
+        } else if let [value] = *format_args.value_args {
+            if_chain! {
+                if format_args.format_string_symbols == [kw::Empty];
+                if match cx.typeck_results().expr_ty(value).peel_refs().kind() {
+                    ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(sym::string_type, adt.did),
+                    ty::Str => true,
+                    _ => false,
+                };
+                if format_args.args.iter().all(|e| is_display_arg(e));
+                if format_args.fmt_expr.map_or(true, |e| check_unformatted(e));
+                then {
+                    let is_new_string = match value.kind {
+                        ExprKind::Binary(..) => true,
+                        ExprKind::MethodCall(path, ..) => path.ident.name.as_str() == "to_string",
+                        _ => false,
+                    };
+                    let sugg = if is_new_string {
+                        snippet_with_applicability(cx, value.span, "..", &mut applicability).into_owned()
+                    } else {
+                        let sugg = Sugg::hir_with_applicability(cx, value, "<arg>", &mut applicability);
+                        format!("{}.to_string()", sugg.maybe_par())
+                    };
+                    span_useless_format(cx, call_site, sugg, applicability);
                 }
-                return Some(format!("{}.to_string()", sugg.maybe_par()));
             }
-        }
+        };
     }
-    None
 }
 
-fn on_new_v1<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<String> {
-    if_chain! {
-        if let Some(args) = match_function_call(cx, expr, &paths::FMT_ARGUMENTS_NEW_V1);
-        if args.len() == 2;
-        // Argument 1 in `new_v1()`
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, arr) = args[0].kind;
-        if let ExprKind::Array(pieces) = arr.kind;
-        if pieces.len() == 1;
-        if let ExprKind::Lit(ref lit) = pieces[0].kind;
-        if let LitKind::Str(ref s, _) = lit.node;
-        // Argument 2 in `new_v1()`
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, arg1) = args[1].kind;
-        if let ExprKind::Match(matchee, arms, MatchSource::Normal) = arg1.kind;
-        if arms.len() == 1;
-        if let ExprKind::Tup(tup) = matchee.kind;
-        then {
-            // `format!("foo")` expansion contains `match () { () => [], }`
-            if tup.is_empty() {
-                if let Some(s_src) = snippet_opt(cx, lit.span) {
-                    // Simulate macro expansion, converting {{ and }} to { and }.
-                    let s_expand = s_src.replace("{{", "{").replace("}}", "}");
-                    return Some(format!("{}.to_string()", s_expand));
-                }
-            } else if s.as_str().is_empty() {
-                return on_argumentv1_new(cx, &tup[0], arms);
-            }
-        }
+fn span_useless_format(cx: &LateContext<'_>, span: Span, mut sugg: String, mut applicability: Applicability) {
+    // The callsite span contains the statement semicolon for some reason.
+    if snippet_with_applicability(cx, span, "..", &mut applicability).ends_with(';') {
+        sugg.push(';');
     }
-    None
+
+    span_lint_and_sugg(
+        cx,
+        USELESS_FORMAT,
+        span,
+        "useless use of `format!`",
+        "consider using `.to_string()`",
+        sugg,
+        applicability,
+    );
 }
 
-fn on_new_v1_fmt<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<String> {
+fn is_display_arg(expr: &Expr<'_>) -> bool {
     if_chain! {
-        if let Some(args) = match_function_call(cx, expr, &paths::FMT_ARGUMENTS_NEW_V1_FORMATTED);
-        if args.len() == 3;
-        if check_unformatted(&args[2]);
-        // Argument 1 in `new_v1_formatted()`
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, arr) = args[0].kind;
-        if let ExprKind::Array(pieces) = arr.kind;
-        if pieces.len() == 1;
-        if let ExprKind::Lit(ref lit) = pieces[0].kind;
-        if let LitKind::Str(..) = lit.node;
-        // Argument 2 in `new_v1_formatted()`
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, arg1) = args[1].kind;
-        if let ExprKind::Match(matchee, arms, MatchSource::Normal) = arg1.kind;
-        if arms.len() == 1;
-        if let ExprKind::Tup(tup) = matchee.kind;
-        then {
-            return on_argumentv1_new(cx, &tup[0], arms);
-        }
+        if let ExprKind::Call(_, [_, fmt]) = expr.kind;
+        if let ExprKind::Path(QPath::Resolved(_, path)) = fmt.kind;
+        if let [.., t, _] = path.segments;
+        if t.ident.name.as_str() == "Display";
+        then { true } else { false }
     }
-    None
 }
 
 /// Checks if the expression matches
@@ -184,10 +131,9 @@ fn on_new_v1_fmt<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<S
 fn check_unformatted(expr: &Expr<'_>) -> bool {
     if_chain! {
         if let ExprKind::AddrOf(BorrowKind::Ref, _, expr) = expr.kind;
-        if let ExprKind::Array(exprs) = expr.kind;
-        if exprs.len() == 1;
+        if let ExprKind::Array([expr]) = expr.kind;
         // struct `core::fmt::rt::v1::Argument`
-        if let ExprKind::Struct(_, fields, _) = exprs[0].kind;
+        if let ExprKind::Struct(_, fields, _) = expr.kind;
         if let Some(format_field) = fields.iter().find(|f| f.ident.name == sym::format);
         // struct `core::fmt::rt::v1::FormatSpec`
         if let ExprKind::Struct(_, fields, _) = format_field.expr.kind;
index 3bd6a09d3653aeb0a60887d8df220196f910d16b..8aefb8d46f6e843115d9d90d3658d1ae4f280dd0 100644 (file)
@@ -22,7 +22,7 @@ declare_clippy_lint! {
     /// a =- 42; // confusing, should it be `a -= 42` or `a = -42`?
     /// ```
     pub SUSPICIOUS_ASSIGNMENT_FORMATTING,
-    style,
+    suspicious,
     "suspicious formatting of `*=`, `-=` or `!=`"
 }
 
@@ -44,7 +44,7 @@ declare_clippy_lint! {
     /// }
     /// ```
     pub SUSPICIOUS_UNARY_OP_FORMATTING,
-    style,
+    suspicious,
     "suspicious formatting of unary `-` or `!` on the RHS of a BinOp"
 }
 
@@ -80,7 +80,7 @@ declare_clippy_lint! {
     /// }
     /// ```
     pub SUSPICIOUS_ELSE_FORMATTING,
-    style,
+    suspicious,
     "suspicious formatting of `else`"
 }
 
index 3707e792177d3317408cb59dcf6c9c51022011d5..8e45fdfecc447a641ec2882c80f41a2fe779f88b 100644 (file)
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for GetLastWithLen {
 
             // LHS of subtraction is "x.len()"
             if let ExprKind::MethodCall(arg_lhs_path, _, lhs_args, _) = &lhs.kind;
-            if arg_lhs_path.ident.name == sym!(len);
+            if arg_lhs_path.ident.name == sym::len;
             if let Some(arg_lhs_struct) = lhs_args.get(0);
 
             // The two vectors referenced (x in x.get(...) and in x.len())
index f661f7ede821a6d486a33448eab7c56fd8e106da..5403d76ea30c8774c4f5c64e2b26a73a8821c3ab 100644 (file)
@@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for IfLetMutex {
     }
 }
 
-/// Checks if `Mutex::lock` is called in the `if let _ = expr.
+/// Checks if `Mutex::lock` is called in the `if let` expr.
 pub struct OppVisitor<'a, 'tcx> {
     mutex_lock_called: bool,
     found_mutex: Option<&'tcx Expr<'tcx>>,
index 03fe0d16d480f792f8138a3480812604ab183cb4..9a040ca572af51613733a328828800d25ec6693b 100644 (file)
@@ -1,4 +1,4 @@
-#![allow(rustc::default_hash_types)]
+#![cfg_attr(bootstrap, allow(rustc::default_hash_types))]
 
 use std::borrow::Cow;
 use std::collections::BTreeMap;
index ee41c4aea2f7ec12366e016fc574f228c9f12b71..9641784eb9a27cbec1dd95e5886e417d0fb3b7a4 100644 (file)
@@ -1,7 +1,7 @@
 //! lint on inherent implementations
 
 use clippy_utils::diagnostics::span_lint_and_note;
-use clippy_utils::{in_macro, is_allowed};
+use clippy_utils::{in_macro, is_lint_allowed};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{def_id::LocalDefId, Crate, Item, ItemKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
@@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
             .filter(|(&id, impls)| {
                 impls.len() > 1
                     // Check for `#[allow]` on the type definition
-                    && !is_allowed(
+                    && !is_lint_allowed(
                         cx,
                         MULTIPLE_INHERENT_IMPL,
                         cx.tcx.hir().local_def_id_to_hir_id(id),
@@ -123,7 +123,7 @@ fn get_impl_span(cx: &LateContext<'_>, id: LocalDefId) -> Option<Span> {
         ..
     }) = cx.tcx.hir().get(id)
     {
-        (!in_macro(span) && impl_item.generics.params.is_empty() && !is_allowed(cx, MULTIPLE_INHERENT_IMPL, id))
+        (!in_macro(span) && impl_item.generics.params.is_empty() && !is_lint_allowed(cx, MULTIPLE_INHERENT_IMPL, id))
             .then(|| span)
     } else {
         None
index 583514b22f9bf65a01897fa38618d25d910913be..892b3af0b32036b3d711d80c85b5d37d35c54c1b 100644 (file)
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{get_item_name, get_parent_as_impl, is_allowed};
+use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
@@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
         if_chain! {
-            if item.ident.as_str() == "len";
+            if item.ident.name == sym::len;
             if let ImplItemKind::Fn(sig, _) = &item.kind;
             if sig.decl.implicit_self.has_implicit_self();
             if cx.access_levels.is_exported(item.hir_id());
@@ -139,7 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
             if let Some(ty_id) = cx.qpath_res(ty_path, imp.self_ty.hir_id).opt_def_id();
             if let Some(local_id) = ty_id.as_local();
             let ty_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_id);
-            if !is_allowed(cx, LEN_WITHOUT_IS_EMPTY, ty_hir_id);
+            if !is_lint_allowed(cx, LEN_WITHOUT_IS_EMPTY, ty_hir_id);
             if let Some(output) = parse_len_output(cx, cx.tcx.fn_sig(item.def_id).skip_binder());
             then {
                 let (name, kind) = match cx.tcx.hir().find(ty_hir_id) {
@@ -189,8 +189,8 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
 }
 
 fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items: &[TraitItemRef]) {
-    fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: &str) -> bool {
-        item.ident.name.as_str() == name
+    fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: Symbol) -> bool {
+        item.ident.name == name
             && if let AssocItemKind::Fn { has_self } = item.kind {
                 has_self && { cx.tcx.fn_sig(item.id.def_id).inputs().skip_binder().len() == 1 }
             } else {
@@ -207,7 +207,9 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
         }
     }
 
-    if cx.access_levels.is_exported(visited_trait.hir_id()) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) {
+    if cx.access_levels.is_exported(visited_trait.hir_id())
+        && trait_items.iter().any(|i| is_named_self(cx, i, sym::len))
+    {
         let mut current_and_super_traits = DefIdSet::default();
         fill_trait_set(visited_trait.def_id.to_def_id(), &mut current_and_super_traits, cx);
 
@@ -401,7 +403,7 @@ fn check_len(
             return;
         }
 
-        if method_name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) {
+        if method_name == sym::len && args.len() == 1 && has_is_empty(cx, &args[0]) {
             let mut applicability = Applicability::MachineApplicable;
             span_lint_and_sugg(
                 cx,
index e7dd3952b3ac96b19bf7aae3ad288730663deb2f..2a1b6d0280b9bbb45f07c77f8af73b0b88f4260c 100644 (file)
@@ -60,9 +60,9 @@ use rustc_session::Session;
 /// 4. The `description` that contains a short explanation on what's wrong with code where the
 ///    lint is triggered.
 ///
-/// Currently the categories `style`, `correctness`, `complexity` and `perf` are enabled by default.
-/// As said in the README.md of this repository, if the lint level mapping changes, please update
-/// README.md.
+/// Currently the categories `style`, `correctness`, `suspicious`, `complexity` and `perf` are
+/// enabled by default. As said in the README.md of this repository, if the lint level mapping
+/// changes, please update README.md.
 ///
 /// # Example
 ///
@@ -106,6 +106,11 @@ macro_rules! declare_clippy_lint {
             $(#[$attr])* pub clippy::$name, Deny, $description, report_in_external_macro: true
         }
     };
+    { $(#[$attr:meta])* pub $name:tt, suspicious, $description:tt } => {
+        declare_tool_lint! {
+            $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
+        }
+    };
     { $(#[$attr:meta])* pub $name:tt, complexity, $description:tt } => {
         declare_tool_lint! {
             $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
@@ -187,6 +192,8 @@ mod default_numeric_fallback;
 mod dereference;
 mod derive;
 mod disallowed_method;
+mod disallowed_script_idents;
+mod disallowed_type;
 mod doc;
 mod double_comparison;
 mod double_parens;
@@ -254,7 +261,6 @@ mod manual_strip;
 mod manual_unwrap_or;
 mod map_clone;
 mod map_err_ignore;
-mod map_identity;
 mod map_unit_fn;
 mod match_on_vec_items;
 mod matches;
@@ -267,6 +273,7 @@ mod misc;
 mod misc_early;
 mod missing_const_for_fn;
 mod missing_doc;
+mod missing_enforced_import_rename;
 mod missing_inline;
 mod modulo_arithmetic;
 mod multiple_crate_versions;
@@ -293,6 +300,7 @@ mod no_effect;
 mod non_copy_const;
 mod non_expressive_names;
 mod non_octal_unix_permissions;
+mod nonstandard_macro_braces;
 mod open_options;
 mod option_env_unwrap;
 mod option_if_let_else;
@@ -322,6 +330,7 @@ mod regex;
 mod repeat_once;
 mod returns;
 mod self_assignment;
+mod self_named_constructors;
 mod semicolon_if_nothing_returned;
 mod serde_api;
 mod shadow;
@@ -330,6 +339,7 @@ mod size_of_in_element_count;
 mod slow_vector_initialization;
 mod stable_sort_primitive;
 mod strings;
+mod strlen_on_c_strings;
 mod suspicious_operation_groupings;
 mod suspicious_trait_impl;
 mod swap;
@@ -483,11 +493,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     );
     store.register_removed(
         "clippy::pub_enum_variant_names",
-        "set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items",
+        "set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items",
     );
     store.register_removed(
         "clippy::wrong_pub_self_convention",
-        "set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items",
+        "set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items",
     );
     // end deprecated lints, do not remove this comment, it’s used in `update_lints`
 
@@ -583,6 +593,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         derive::EXPL_IMPL_CLONE_ON_COPY,
         derive::UNSAFE_DERIVE_DESERIALIZE,
         disallowed_method::DISALLOWED_METHOD,
+        disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS,
+        disallowed_type::DISALLOWED_TYPE,
         doc::DOC_MARKDOWN,
         doc::MISSING_ERRORS_DOC,
         doc::MISSING_PANICS_DOC,
@@ -705,7 +717,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         manual_unwrap_or::MANUAL_UNWRAP_OR,
         map_clone::MAP_CLONE,
         map_err_ignore::MAP_ERR_IGNORE,
-        map_identity::MAP_IDENTITY,
         map_unit_fn::OPTION_MAP_UNIT_FN,
         map_unit_fn::RESULT_MAP_UNIT_FN,
         match_on_vec_items::MATCH_ON_VEC_ITEMS,
@@ -740,6 +751,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         methods::CLONE_ON_REF_PTR,
         methods::EXPECT_FUN_CALL,
         methods::EXPECT_USED,
+        methods::EXTEND_WITH_DRAIN,
         methods::FILETYPE_IS_FILE,
         methods::FILTER_MAP_IDENTITY,
         methods::FILTER_MAP_NEXT,
@@ -765,6 +777,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         methods::MANUAL_STR_REPEAT,
         methods::MAP_COLLECT_RESULT_UNIT,
         methods::MAP_FLATTEN,
+        methods::MAP_IDENTITY,
         methods::MAP_UNWRAP_OR,
         methods::NEW_RET_NO_SELF,
         methods::OK_EXPECT,
@@ -810,6 +823,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         misc_early::ZERO_PREFIXED_LITERAL,
         missing_const_for_fn::MISSING_CONST_FOR_FN,
         missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS,
+        missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES,
         missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS,
         modulo_arithmetic::MODULO_ARITHMETIC,
         multiple_crate_versions::MULTIPLE_CRATE_VERSIONS,
@@ -843,6 +857,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         non_expressive_names::MANY_SINGLE_CHAR_NAMES,
         non_expressive_names::SIMILAR_NAMES,
         non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS,
+        nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES,
         open_options::NONSENSICAL_OPEN_OPTIONS,
         option_env_unwrap::OPTION_ENV_UNWRAP,
         option_if_let_else::OPTION_IF_LET_ELSE,
@@ -886,6 +901,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         returns::LET_AND_RETURN,
         returns::NEEDLESS_RETURN,
         self_assignment::SELF_ASSIGNMENT,
+        self_named_constructors::SELF_NAMED_CONSTRUCTORS,
         semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED,
         serde_api::SERDE_API_MISUSE,
         shadow::SHADOW_REUSE,
@@ -901,6 +917,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         strings::STRING_LIT_AS_BYTES,
         strings::STRING_TO_STRING,
         strings::STR_TO_STRING,
+        strlen_on_c_strings::STRLEN_ON_C_STRINGS,
         suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS,
         suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL,
         suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL,
@@ -931,6 +948,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         types::LINKEDLIST,
         types::OPTION_OPTION,
         types::RC_BUFFER,
+        types::RC_MUTEX,
         types::REDUNDANT_ALLOCATION,
         types::TYPE_COMPLEXITY,
         types::VEC_BOX,
@@ -989,6 +1007,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(create_dir::CREATE_DIR),
         LintId::of(dbg_macro::DBG_MACRO),
         LintId::of(default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK),
+        LintId::of(disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS),
         LintId::of(else_if_without_else::ELSE_IF_WITHOUT_ELSE),
         LintId::of(exhaustive_items::EXHAUSTIVE_ENUMS),
         LintId::of(exhaustive_items::EXHAUSTIVE_STRUCTS),
@@ -1013,6 +1032,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(misc::FLOAT_CMP_CONST),
         LintId::of(misc_early::UNNEEDED_FIELD_PATTERN),
         LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),
+        LintId::of(missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES),
         LintId::of(missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS),
         LintId::of(modulo_arithmetic::MODULO_ARITHMETIC),
         LintId::of(panic_in_result_fn::PANIC_IN_RESULT_FN),
@@ -1027,6 +1047,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(strings::STRING_TO_STRING),
         LintId::of(strings::STR_TO_STRING),
         LintId::of(types::RC_BUFFER),
+        LintId::of(types::RC_MUTEX),
         LintId::of(unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS),
         LintId::of(unwrap_in_result::UNWRAP_IN_RESULT),
         LintId::of(verbose_file_reads::VERBOSE_FILE_READS),
@@ -1090,6 +1111,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(methods::CLONED_INSTEAD_OF_COPIED),
         LintId::of(methods::FILTER_MAP_NEXT),
         LintId::of(methods::FLAT_MAP_OPTION),
+        LintId::of(methods::FROM_ITER_INSTEAD_OF_COLLECT),
         LintId::of(methods::IMPLICIT_CLONE),
         LintId::of(methods::INEFFICIENT_TO_STRING),
         LintId::of(methods::MAP_FLATTEN),
@@ -1260,7 +1282,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(manual_strip::MANUAL_STRIP),
         LintId::of(manual_unwrap_or::MANUAL_UNWRAP_OR),
         LintId::of(map_clone::MAP_CLONE),
-        LintId::of(map_identity::MAP_IDENTITY),
         LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN),
         LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN),
         LintId::of(matches::INFALLIBLE_DESTRUCTURING_MATCH),
@@ -1283,10 +1304,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(methods::CLONE_DOUBLE_REF),
         LintId::of(methods::CLONE_ON_COPY),
         LintId::of(methods::EXPECT_FUN_CALL),
+        LintId::of(methods::EXTEND_WITH_DRAIN),
         LintId::of(methods::FILTER_MAP_IDENTITY),
         LintId::of(methods::FILTER_NEXT),
         LintId::of(methods::FLAT_MAP_IDENTITY),
-        LintId::of(methods::FROM_ITER_INSTEAD_OF_COLLECT),
         LintId::of(methods::INSPECT_FOR_EACH),
         LintId::of(methods::INTO_ITER_ON_REF),
         LintId::of(methods::ITERATOR_STEP_BY_ZERO),
@@ -1301,6 +1322,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(methods::MANUAL_SATURATING_ARITHMETIC),
         LintId::of(methods::MANUAL_STR_REPEAT),
         LintId::of(methods::MAP_COLLECT_RESULT_UNIT),
+        LintId::of(methods::MAP_IDENTITY),
         LintId::of(methods::NEW_RET_NO_SELF),
         LintId::of(methods::OK_EXPECT),
         LintId::of(methods::OPTION_AS_REF_DEREF),
@@ -1386,12 +1408,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(returns::LET_AND_RETURN),
         LintId::of(returns::NEEDLESS_RETURN),
         LintId::of(self_assignment::SELF_ASSIGNMENT),
+        LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS),
         LintId::of(serde_api::SERDE_API_MISUSE),
         LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
         LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
         LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
         LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE),
         LintId::of(strings::STRING_FROM_UTF8_AS_BYTES),
+        LintId::of(strlen_on_c_strings::STRLEN_ON_C_STRINGS),
         LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
         LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
         LintId::of(swap::ALMOST_SWAPPED),
@@ -1447,7 +1471,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_group(true, "clippy::style", Some("clippy_style"), vec![
         LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
         LintId::of(assign_ops::ASSIGN_OP_PATTERN),
-        LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
         LintId::of(blacklisted_name::BLACKLISTED_NAME),
         LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS),
         LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON),
@@ -1465,9 +1488,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(eq_op::OP_REF),
         LintId::of(eta_reduction::REDUNDANT_CLOSURE),
         LintId::of(float_literal::EXCESSIVE_PRECISION),
-        LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
-        LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING),
-        LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
         LintId::of(from_over_into::FROM_OVER_INTO),
         LintId::of(from_str_radix_10::FROM_STR_RADIX_10),
         LintId::of(functions::DOUBLE_MUST_USE),
@@ -1480,7 +1500,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(len_zero::LEN_ZERO),
         LintId::of(literal_representation::INCONSISTENT_DIGIT_GROUPING),
         LintId::of(literal_representation::UNUSUAL_BYTE_GROUPINGS),
-        LintId::of(loops::EMPTY_LOOP),
         LintId::of(loops::FOR_KV_MAP),
         LintId::of(loops::NEEDLESS_RANGE_LOOP),
         LintId::of(loops::SAME_ITEM_PUSH),
@@ -1501,7 +1520,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(methods::BYTES_NTH),
         LintId::of(methods::CHARS_LAST_CMP),
         LintId::of(methods::CHARS_NEXT_CMP),
-        LintId::of(methods::FROM_ITER_INSTEAD_OF_COLLECT),
         LintId::of(methods::INTO_ITER_ON_REF),
         LintId::of(methods::ITER_CLONED_COLLECT),
         LintId::of(methods::ITER_NEXT_SLICE),
@@ -1544,6 +1562,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
         LintId::of(returns::LET_AND_RETURN),
         LintId::of(returns::NEEDLESS_RETURN),
+        LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS),
         LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
         LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
         LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME),
@@ -1560,7 +1579,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     ]);
 
     store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec![
-        LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP),
         LintId::of(attrs::DEPRECATED_CFG_ATTR),
         LintId::of(booleans::NONMINIMAL_BOOL),
         LintId::of(casts::CHAR_LIT_AS_U8),
@@ -1570,7 +1588,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(double_parens::DOUBLE_PARENS),
         LintId::of(duration_subsec::DURATION_SUBSEC),
         LintId::of(eval_order_dependence::DIVERGING_SUB_EXPRESSION),
-        LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE),
         LintId::of(explicit_write::EXPLICIT_WRITE),
         LintId::of(format::USELESS_FORMAT),
         LintId::of(functions::TOO_MANY_ARGUMENTS),
@@ -1581,12 +1598,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(lifetimes::NEEDLESS_LIFETIMES),
         LintId::of(loops::EXPLICIT_COUNTER_LOOP),
         LintId::of(loops::MANUAL_FLATTEN),
-        LintId::of(loops::MUT_RANGE_BOUND),
         LintId::of(loops::SINGLE_ELEMENT_LOOP),
         LintId::of(loops::WHILE_LET_LOOP),
         LintId::of(manual_strip::MANUAL_STRIP),
         LintId::of(manual_unwrap_or::MANUAL_UNWRAP_OR),
-        LintId::of(map_identity::MAP_IDENTITY),
         LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN),
         LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN),
         LintId::of(matches::MATCH_AS_REF),
@@ -1601,11 +1616,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(methods::ITER_COUNT),
         LintId::of(methods::MANUAL_FILTER_MAP),
         LintId::of(methods::MANUAL_FIND_MAP),
+        LintId::of(methods::MAP_IDENTITY),
         LintId::of(methods::OPTION_AS_REF_DEREF),
         LintId::of(methods::OPTION_FILTER_MAP),
         LintId::of(methods::SEARCH_IS_SOME),
         LintId::of(methods::SKIP_WHILE_NEXT),
-        LintId::of(methods::SUSPICIOUS_MAP),
         LintId::of(methods::UNNECESSARY_FILTER_MAP),
         LintId::of(methods::USELESS_ASREF),
         LintId::of(misc::SHORT_CIRCUIT_STATEMENT),
@@ -1631,6 +1646,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(reference::REF_IN_DEREF),
         LintId::of(repeat_once::REPEAT_ONCE),
         LintId::of(strings::STRING_FROM_UTF8_AS_BYTES),
+        LintId::of(strlen_on_c_strings::STRLEN_ON_C_STRINGS),
         LintId::of(swap::MANUAL_SWAP),
         LintId::of(temporary_assignment::TEMPORARY_ASSIGNMENT),
         LintId::of(transmute::CROSSPOINTER_TRANSMUTE),
@@ -1674,7 +1690,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT),
         LintId::of(eq_op::EQ_OP),
         LintId::of(erasing_op::ERASING_OP),
-        LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS),
         LintId::of(formatting::POSSIBLE_MISSING_COMMA),
         LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF),
         LintId::of(if_let_mutex::IF_LET_MUTEX),
@@ -1684,7 +1699,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
         LintId::of(let_underscore::LET_UNDERSCORE_LOCK),
         LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES),
-        LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES),
         LintId::of(loops::ITER_NEXT_LOOP),
         LintId::of(loops::NEVER_LOOP),
         LintId::of(loops::WHILE_IMMUTABLE_CONDITION),
@@ -1699,7 +1713,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(misc::CMP_NAN),
         LintId::of(misc::FLOAT_CMP),
         LintId::of(misc::MODULO_ONE),
-        LintId::of(mut_key::MUTABLE_KEY_TYPE),
         LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS),
         LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS),
         LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
@@ -1710,8 +1723,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(self_assignment::SELF_ASSIGNMENT),
         LintId::of(serde_api::SERDE_API_MISUSE),
         LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
-        LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
-        LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
         LintId::of(swap::ALMOST_SWAPPED),
         LintId::of(to_string_in_display::TO_STRING_IN_DISPLAY),
         LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE),
@@ -1728,6 +1739,23 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO),
     ]);
 
+    store.register_group(true, "clippy::suspicious", None, vec![
+        LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP),
+        LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
+        LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE),
+        LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS),
+        LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
+        LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING),
+        LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
+        LintId::of(loops::EMPTY_LOOP),
+        LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES),
+        LintId::of(loops::MUT_RANGE_BOUND),
+        LintId::of(methods::SUSPICIOUS_MAP),
+        LintId::of(mut_key::MUTABLE_KEY_TYPE),
+        LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
+        LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
+    ]);
+
     store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![
         LintId::of(entry::MAP_ENTRY),
         LintId::of(escape::BOXED_LOCAL),
@@ -1736,6 +1764,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(loops::MANUAL_MEMCPY),
         LintId::of(loops::NEEDLESS_COLLECT),
         LintId::of(methods::EXPECT_FUN_CALL),
+        LintId::of(methods::EXTEND_WITH_DRAIN),
         LintId::of(methods::ITER_NTH),
         LintId::of(methods::MANUAL_STR_REPEAT),
         LintId::of(methods::OR_FUN_CALL),
@@ -1761,6 +1790,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
         LintId::of(cognitive_complexity::COGNITIVE_COMPLEXITY),
         LintId::of(disallowed_method::DISALLOWED_METHOD),
+        LintId::of(disallowed_type::DISALLOWED_TYPE),
         LintId::of(fallible_impl_from::FALLIBLE_IMPL_FROM),
         LintId::of(floating_point_arithmetic::IMPRECISE_FLOPS),
         LintId::of(floating_point_arithmetic::SUBOPTIMAL_FLOPS),
@@ -1769,6 +1799,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(missing_const_for_fn::MISSING_CONST_FOR_FN),
         LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
         LintId::of(mutex_atomic::MUTEX_INTEGER),
+        LintId::of(nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES),
         LintId::of(path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE),
         LintId::of(redundant_pub_crate::REDUNDANT_PUB_CRATE),
         LintId::of(regex::TRIVIAL_REGEX),
@@ -2038,8 +2069,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(move || box non_expressive_names::NonExpressiveNames {
         single_char_binding_names_threshold,
     });
+    let macro_matcher = conf.standard_macro_braces.iter().cloned().collect::<FxHashSet<_>>();
+    store.register_early_pass(move || box nonstandard_macro_braces::MacroBraces::new(&macro_matcher));
     store.register_late_pass(|| box macro_use::MacroUseImports::default());
-    store.register_late_pass(|| box map_identity::MapIdentity);
     store.register_late_pass(|| box pattern_type_mismatch::PatternTypeMismatch);
     store.register_late_pass(|| box stable_sort_primitive::StableSortPrimitive);
     store.register_late_pass(|| box repeat_once::RepeatOnce);
@@ -2066,7 +2098,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(move || box if_then_some_else_none::IfThenSomeElseNone::new(msrv));
     store.register_early_pass(|| box bool_assert_comparison::BoolAssertComparison);
     store.register_late_pass(|| box unused_async::UnusedAsync);
-
+    let disallowed_types = conf.disallowed_types.iter().cloned().collect::<FxHashSet<_>>();
+    store.register_late_pass(move || box disallowed_type::DisallowedType::new(&disallowed_types));
+    let import_renames = conf.enforced_import_renames.clone();
+    store.register_late_pass(move || box missing_enforced_import_rename::ImportRename::new(import_renames.clone()));
+    let scripts = conf.allowed_scripts.clone();
+    store.register_early_pass(move || box disallowed_script_idents::DisallowedScriptIdents::new(&scripts));
+    store.register_late_pass(|| box strlen_on_c_strings::StrlenOnCStrings);
+    store.register_late_pass(move || box self_named_constructors::SelfNamedConstructors);
 }
 
 #[rustfmt::skip]
@@ -2143,7 +2182,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 c91fe88757ec719d1b59d3162c14e06a7818f511..a98e2dc1372db0d3782898625e3db5267cd8b8f2 100644 (file)
@@ -118,7 +118,7 @@ fn build_manual_memcpy_suggestion<'tcx>(
     let print_limit = |end: &Expr<'_>, end_str: &str, base: &Expr<'_>, sugg: MinifyingSugg<'static>| {
         if_chain! {
             if let ExprKind::MethodCall(method, _, len_args, _) = end.kind;
-            if method.ident.name == sym!(len);
+            if method.ident.name == sym::len;
             if len_args.len() == 1;
             if let Some(arg) = len_args.get(0);
             if path_to_local(arg) == path_to_local(base);
index a4bc3e6bd100cd4c47c9b31febd8144209b183a2..56a123b69c6aec1de3d3bf1ea6140a13c29da0eb 100644 (file)
@@ -199,7 +199,7 @@ declare_clippy_lint! {
     /// }
     /// ```
     pub FOR_LOOPS_OVER_FALLIBLES,
-    correctness,
+    suspicious,
     "for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let`"
 }
 
@@ -313,7 +313,7 @@ declare_clippy_lint! {
     /// loop {}
     /// ```
     pub EMPTY_LOOP,
-    style,
+    suspicious,
     "empty `loop {}`, which should block or sleep"
 }
 
@@ -401,7 +401,7 @@ declare_clippy_lint! {
     /// }
     /// ```
     pub MUT_RANGE_BOUND,
-    complexity,
+    suspicious,
     "for loop over a range where one of the bounds is a mutable variable"
 }
 
index d07b5a93b67c0505a6bda0238e287cda8a7ee4ca..1e54a1e2de165e8781a4c581606d5da9cbf72efe 100644 (file)
@@ -7,7 +7,7 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::{mir::FakeReadCause, ty};
 use rustc_span::source_map::Span;
-use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
+use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
 pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) {
     if let Some(higher::Range {
@@ -82,7 +82,7 @@ struct MutatePairDelegate<'a, 'tcx> {
 }
 
 impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
-    fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId, _: ConsumeMode) {}
+    fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
 
     fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) {
         if let ty::BorrowKind::MutBorrow = bk {
index eb82c9c27c3e192306bb34e502f9b41556ba2468..51d7def137e409eea10816378e774726fb29e026 100644 (file)
@@ -7,10 +7,10 @@ use clippy_utils::{is_trait_method, path_to_local_id};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_block, walk_expr, NestedVisitorMap, Visitor};
-use rustc_hir::{Block, Expr, ExprKind, GenericArg, GenericArgs, HirId, Local, Pat, PatKind, QPath, StmtKind, Ty};
+use rustc_hir::{Block, Expr, ExprKind, HirId, PatKind, StmtKind};
 use rustc_lint::LateContext;
 use rustc_middle::hir::map::Map;
-use rustc_span::symbol::{sym, Ident};
+use rustc_span::sym;
 use rustc_span::{MultiSpan, Span};
 
 const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed";
@@ -24,10 +24,8 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont
         if let ExprKind::MethodCall(method, _, args, _) = expr.kind;
         if let ExprKind::MethodCall(chain_method, method0_span, _, _) = args[0].kind;
         if chain_method.ident.name == sym!(collect) && is_trait_method(cx, &args[0], sym::Iterator);
-        if let Some(generic_args) = chain_method.args;
-        if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0);
-        if let Some(ty) = cx.typeck_results().node_type_opt(ty.hir_id);
         then {
+            let ty = cx.typeck_results().expr_ty(&args[0]);
             let mut applicability = Applicability::MachineApplicable;
             let is_empty_sugg = "next().is_none()".to_string();
             let method_name = &*method.ident.name.as_str();
@@ -72,40 +70,25 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont
 }
 
 fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) {
-    fn get_hir_id<'tcx>(ty: Option<&Ty<'tcx>>, method_args: Option<&GenericArgs<'tcx>>) -> Option<HirId> {
-        if let Some(ty) = ty {
-            return Some(ty.hir_id);
-        }
-
-        if let Some(generic_args) = method_args {
-            if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0) {
-                return Some(ty.hir_id);
-            }
-        }
-
-        None
-    }
     if let ExprKind::Block(block, _) = expr.kind {
         for stmt in block.stmts {
             if_chain! {
-                if let StmtKind::Local(
-                    Local { pat: Pat { hir_id: pat_id, kind: PatKind::Binding(_, _, ident, .. ), .. },
-                    init: Some(init_expr), ty, .. }
-                ) = stmt.kind;
+                if let StmtKind::Local(local) = stmt.kind;
+                if let PatKind::Binding(_, id, ..) = local.pat.kind;
+                if let Some(init_expr) = local.init;
                 if let ExprKind::MethodCall(method_name, collect_span, &[ref iter_source], ..) = init_expr.kind;
                 if method_name.ident.name == sym!(collect) && is_trait_method(cx, init_expr, sym::Iterator);
-                if let Some(hir_id) = get_hir_id(*ty, method_name.args);
-                if let Some(ty) = cx.typeck_results().node_type_opt(hir_id);
+                let ty = cx.typeck_results().expr_ty(init_expr);
                 if is_type_diagnostic_item(cx, ty, sym::vec_type) ||
                     is_type_diagnostic_item(cx, ty, sym::vecdeque_type) ||
                     is_type_diagnostic_item(cx, ty, sym::BinaryHeap) ||
                     is_type_diagnostic_item(cx, ty, sym::LinkedList);
-                if let Some(iter_calls) = detect_iter_and_into_iters(block, *ident);
+                if let Some(iter_calls) = detect_iter_and_into_iters(block, id);
                 if let [iter_call] = &*iter_calls;
                 then {
                     let mut used_count_visitor = UsedCountVisitor {
                         cx,
-                        id: *pat_id,
+                        id,
                         count: 0,
                     };
                     walk_block(&mut used_count_visitor, block);
@@ -187,48 +170,40 @@ enum IterFunctionKind {
 struct IterFunctionVisitor {
     uses: Vec<IterFunction>,
     seen_other: bool,
-    target: Ident,
+    target: HirId,
 }
 impl<'tcx> Visitor<'tcx> for IterFunctionVisitor {
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
         // Check function calls on our collection
-        if_chain! {
-            if let ExprKind::MethodCall(method_name, _, args, _) = &expr.kind;
-            if let Some(Expr { kind: ExprKind::Path(QPath::Resolved(_, path)), .. }) = args.get(0);
-            if let &[name] = &path.segments;
-            if name.ident == self.target;
-            then {
-                let len = sym!(len);
-                let is_empty = sym!(is_empty);
-                let contains = sym!(contains);
-                match method_name.ident.name {
-                    sym::into_iter => self.uses.push(
-                        IterFunction { func: IterFunctionKind::IntoIter, span: expr.span }
-                    ),
-                    name if name == len => self.uses.push(
-                        IterFunction { func: IterFunctionKind::Len, span: expr.span }
-                    ),
-                    name if name == is_empty => self.uses.push(
-                        IterFunction { func: IterFunctionKind::IsEmpty, span: expr.span }
-                    ),
-                    name if name == contains => self.uses.push(
-                        IterFunction { func: IterFunctionKind::Contains(args[1].span), span: expr.span }
-                    ),
+        if let ExprKind::MethodCall(method_name, _, [recv, args @ ..], _) = &expr.kind {
+            if path_to_local_id(recv, self.target) {
+                match &*method_name.ident.name.as_str() {
+                    "into_iter" => self.uses.push(IterFunction {
+                        func: IterFunctionKind::IntoIter,
+                        span: expr.span,
+                    }),
+                    "len" => self.uses.push(IterFunction {
+                        func: IterFunctionKind::Len,
+                        span: expr.span,
+                    }),
+                    "is_empty" => self.uses.push(IterFunction {
+                        func: IterFunctionKind::IsEmpty,
+                        span: expr.span,
+                    }),
+                    "contains" => self.uses.push(IterFunction {
+                        func: IterFunctionKind::Contains(args[0].span),
+                        span: expr.span,
+                    }),
                     _ => self.seen_other = true,
                 }
-                return
+                return;
             }
         }
         // Check if the collection is used for anything else
-        if_chain! {
-            if let Expr { kind: ExprKind::Path(QPath::Resolved(_, path)), .. } = expr;
-            if let &[name] = &path.segments;
-            if name.ident == self.target;
-            then {
-                self.seen_other = true;
-            } else {
-                walk_expr(self, expr);
-            }
+        if path_to_local_id(expr, self.target) {
+            self.seen_other = true;
+        } else {
+            walk_expr(self, expr);
         }
     }
 
@@ -262,10 +237,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UsedCountVisitor<'a, 'tcx> {
 
 /// Detect the occurrences of calls to `iter` or `into_iter` for the
 /// given identifier
-fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) -> Option<Vec<IterFunction>> {
+fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, id: HirId) -> Option<Vec<IterFunction>> {
     let mut visitor = IterFunctionVisitor {
         uses: Vec::new(),
-        target: identifier,
+        target: id,
         seen_other: false,
     };
     visitor.visit_block(block);
index 3065bcc3e6c81e2b70baa3d3f69a92fa9c85524d..3810d0dcc051a7da141bcb8cb775df071184d1fe 100644 (file)
@@ -192,7 +192,7 @@ fn is_len_call(expr: &Expr<'_>, var: Symbol) -> bool {
     if_chain! {
         if let ExprKind::MethodCall(method, _, len_args, _) = expr.kind;
         if len_args.len() == 1;
-        if method.ident.name == sym!(len);
+        if method.ident.name == sym::len;
         if let ExprKind::Path(QPath::Resolved(_, path)) = len_args[0].kind;
         if path.segments.len() == 1;
         if path.segments[0].ident.name == var;
index 63560047578a16aa0c39f8996745dbd02ab6c246..d57588716a5bf16c8f4b28d0b75ceb251718837e 100644 (file)
@@ -1,7 +1,9 @@
 use super::WHILE_LET_ON_ITERATOR;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{get_enclosing_loop, is_refutable, is_trait_method, match_def_path, paths, visitors::is_res_used};
+use clippy_utils::{
+    get_enclosing_loop_or_closure, is_refutable, is_trait_method, match_def_path, paths, visitors::is_res_used,
+};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor};
@@ -315,9 +317,10 @@ fn needs_mutable_borrow(cx: &LateContext<'tcx>, iter_expr: &IterExpr, loop_expr:
         }
     }
 
-    if let Some(e) = get_enclosing_loop(cx.tcx, loop_expr) {
-        // The iterator expression will be used on the next iteration unless it is declared within the outer
-        // loop.
+    if let Some(e) = get_enclosing_loop_or_closure(cx.tcx, loop_expr) {
+        // The iterator expression will be used on the next iteration (for loops), or on the next call (for
+        // closures) unless it is declared within the enclosing expression. TODO: Check for closures
+        // used where an `FnOnce` type is expected.
         let local_id = match iter_expr.path {
             Res::Local(id) => id,
             _ => return true,
index 0b873534f2c8d4be30d6fc29ed6191edebd49f69..563d5cdb5fb568046dfb447e2c5db8ee6626fe4a 100644 (file)
@@ -3,19 +3,17 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable};
 use clippy_utils::{
-    can_move_expr_to_closure, in_constant, is_allowed, is_else_clause, is_lang_ctor, match_var, peel_hir_expr_refs,
+    can_move_expr_to_closure, in_constant, is_else_clause, is_lang_ctor, is_lint_allowed, path_to_local_id,
+    peel_hir_expr_refs,
 };
 use rustc_ast::util::parser::PREC_POSTFIX;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
-use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, MatchSource, Mutability, Pat, PatKind};
+use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, HirId, MatchSource, Mutability, Pat, PatKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::{
-    symbol::{sym, Ident},
-    SyntaxContext,
-};
+use rustc_span::{sym, SyntaxContext};
 
 declare_clippy_lint! {
     /// **What it does:** Checks for usages of `match` which could be implemented using `map`
@@ -104,7 +102,7 @@ impl LateLintPass<'_> for ManualMap {
 
             // These two lints will go back and forth with each other.
             if cx.typeck_results().expr_ty(some_expr) == cx.tcx.types.unit
-                && !is_allowed(cx, OPTION_MAP_UNIT_FN, expr.hir_id)
+                && !is_lint_allowed(cx, OPTION_MAP_UNIT_FN, expr.hir_id)
             {
                 return;
             }
@@ -141,14 +139,14 @@ impl LateLintPass<'_> for ManualMap {
                     scrutinee_str.into()
                 };
 
-            let body_str = if let PatKind::Binding(annotation, _, some_binding, None) = some_pat.kind {
-                match can_pass_as_func(cx, some_binding, some_expr) {
+            let body_str = if let PatKind::Binding(annotation, id, some_binding, None) = some_pat.kind {
+                match can_pass_as_func(cx, id, some_expr) {
                     Some(func) if func.span.ctxt() == some_expr.span.ctxt() => {
                         snippet_with_applicability(cx, func.span, "..", &mut app).into_owned()
                     },
                     _ => {
-                        if match_var(some_expr, some_binding.name)
-                            && !is_allowed(cx, MATCH_AS_REF, expr.hir_id)
+                        if path_to_local_id(some_expr, id)
+                            && !is_lint_allowed(cx, MATCH_AS_REF, expr.hir_id)
                             && binding_ref.is_some()
                         {
                             return;
@@ -199,10 +197,10 @@ impl LateLintPass<'_> for ManualMap {
 
 // Checks whether the expression could be passed as a function, or whether a closure is needed.
 // Returns the function to be passed to `map` if it exists.
-fn can_pass_as_func(cx: &LateContext<'tcx>, binding: Ident, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
+fn can_pass_as_func(cx: &LateContext<'tcx>, binding: HirId, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     match expr.kind {
         ExprKind::Call(func, [arg])
-            if match_var(arg, binding.name) && cx.typeck_results().expr_adjustments(arg).is_empty() =>
+            if path_to_local_id(arg, binding) && cx.typeck_results().expr_adjustments(arg).is_empty() =>
         {
             Some(func)
         },
index 18038dd7819430e004b547a5670b6b8a1a4b0af8..9d8d77cf8f089aba80c1edd48bfd95d0dbda990f 100644 (file)
@@ -61,13 +61,13 @@ fn lint_manual_unwrap_or<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
             if let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| {
                 match arm.pat.kind {
                     PatKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
-                    PatKind::TupleStruct(ref qpath, &[pat], _) =>
+                    PatKind::TupleStruct(ref qpath, [pat], _) =>
                         matches!(pat.kind, PatKind::Wild) && is_lang_ctor(cx, qpath, ResultErr),
                     _ => false,
                 }
             });
             let unwrap_arm = &arms[1 - idx];
-            if let PatKind::TupleStruct(ref qpath, &[unwrap_pat], _) = unwrap_arm.pat.kind;
+            if let PatKind::TupleStruct(ref qpath, [unwrap_pat], _) = unwrap_arm.pat.kind;
             if is_lang_ctor(cx, qpath, OptionSome) || is_lang_ctor(cx, qpath, ResultOk);
             if let PatKind::Binding(_, binding_hir_id, ..) = unwrap_pat.kind;
             if path_to_local_id(unwrap_arm.body, binding_hir_id);
diff --git a/src/tools/clippy/clippy_lints/src/map_identity.rs b/src/tools/clippy/clippy_lints/src/map_identity.rs
deleted file mode 100644 (file)
index 41cda23..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_adjusted, is_qpath_def_path, is_trait_method, match_var, paths, remove_blocks};
-use if_chain::if_chain;
-use rustc_errors::Applicability;
-use rustc_hir::{Body, Expr, ExprKind, Pat, PatKind, QPath, StmtKind};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::sym;
-
-declare_clippy_lint! {
-    /// **What it does:** Checks for instances of `map(f)` where `f` is the identity function.
-    ///
-    /// **Why is this bad?** It can be written more concisely without the call to `map`.
-    ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
-    ///
-    /// ```rust
-    /// let x = [1, 2, 3];
-    /// let y: Vec<_> = x.iter().map(|x| x).map(|x| 2*x).collect();
-    /// ```
-    /// Use instead:
-    /// ```rust
-    /// let x = [1, 2, 3];
-    /// let y: Vec<_> = x.iter().map(|x| 2*x).collect();
-    /// ```
-    pub MAP_IDENTITY,
-    complexity,
-    "using iterator.map(|x| x)"
-}
-
-declare_lint_pass!(MapIdentity => [MAP_IDENTITY]);
-
-impl<'tcx> LateLintPass<'tcx> for MapIdentity {
-    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        if expr.span.from_expansion() {
-            return;
-        }
-
-        if_chain! {
-            if let Some([caller, func]) = get_map_argument(cx, expr);
-            if is_expr_identity_function(cx, func);
-            then {
-                span_lint_and_sugg(
-                    cx,
-                    MAP_IDENTITY,
-                    expr.span.trim_start(caller.span).unwrap(),
-                    "unnecessary map of the identity function",
-                    "remove the call to `map`",
-                    String::new(),
-                    Applicability::MachineApplicable
-                )
-            }
-        }
-    }
-}
-
-/// Returns the arguments passed into map() if the expression is a method call to
-/// map(). Otherwise, returns None.
-fn get_map_argument<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a [Expr<'a>]> {
-    if_chain! {
-        if let ExprKind::MethodCall(method, _, args, _) = expr.kind;
-        if args.len() == 2 && method.ident.name == sym::map;
-        let caller_ty = cx.typeck_results().expr_ty(&args[0]);
-        if is_trait_method(cx, expr, sym::Iterator)
-            || is_type_diagnostic_item(cx, caller_ty, sym::result_type)
-            || is_type_diagnostic_item(cx, caller_ty, sym::option_type);
-        then {
-            Some(args)
-        } else {
-            None
-        }
-    }
-}
-
-/// Checks if an expression represents the identity function
-/// Only examines closures and `std::convert::identity`
-fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    match expr.kind {
-        ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)),
-        ExprKind::Path(ref path) => is_qpath_def_path(cx, path, expr.hir_id, &paths::CONVERT_IDENTITY),
-        _ => false,
-    }
-}
-
-/// Checks if a function's body represents the identity function
-/// Looks for bodies of the form `|x| x`, `|x| return x`, `|x| { return x }` or `|x| {
-/// return x; }`
-fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
-    let params = func.params;
-    let body = remove_blocks(&func.value);
-
-    // if there's less/more than one parameter, then it is not the identity function
-    if params.len() != 1 {
-        return false;
-    }
-
-    match body.kind {
-        ExprKind::Path(QPath::Resolved(None, _)) => match_expr_param(cx, body, params[0].pat),
-        ExprKind::Ret(Some(ret_val)) => match_expr_param(cx, ret_val, params[0].pat),
-        ExprKind::Block(block, _) => {
-            if_chain! {
-                if block.stmts.len() == 1;
-                if let StmtKind::Semi(expr) | StmtKind::Expr(expr) = block.stmts[0].kind;
-                if let ExprKind::Ret(Some(ret_val)) = expr.kind;
-                then {
-                    match_expr_param(cx, ret_val, params[0].pat)
-                } else {
-                    false
-                }
-            }
-        },
-        _ => false,
-    }
-}
-
-/// Returns true iff an expression returns the same thing as a parameter's pattern
-fn match_expr_param(cx: &LateContext<'_>, expr: &Expr<'_>, pat: &Pat<'_>) -> bool {
-    if let PatKind::Binding(_, _, ident, _) = pat.kind {
-        match_var(expr, ident.name) && !(cx.typeck_results().hir_owner == expr.hir_id.owner && is_adjusted(cx, expr))
-    } else {
-        false
-    }
-}
index cd3e3b97928af8cffc423b9961c21e1ade38d351..66e3d957894173317445026cbc24a76f9d50b095 100644 (file)
@@ -7,7 +7,7 @@ use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, match_type, peel_mid_ty_refs};
 use clippy_utils::visitors::LocalUsedVisitor;
 use clippy_utils::{
-    get_parent_expr, in_macro, is_allowed, is_expn_of, is_lang_ctor, is_refutable, is_wild, meets_msrv, msrvs,
+    get_parent_expr, in_macro, is_expn_of, is_lang_ctor, is_lint_allowed, is_refutable, is_wild, meets_msrv, msrvs,
     path_to_local, path_to_local_id, peel_hir_pat_refs, peel_n_hir_expr_refs, recurse_or_patterns, remove_blocks,
     strip_pat_refs,
 };
@@ -625,7 +625,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
             if let PatKind::TupleStruct(
                 QPath::Resolved(None, variant_name), args, _) = arms[0].pat.kind;
             if args.len() == 1;
-            if let PatKind::Binding(_, arg, ..) = strip_pat_refs(args[0]).kind;
+            if let PatKind::Binding(_, arg, ..) = strip_pat_refs(&args[0]).kind;
             let body = remove_blocks(arms[0].body);
             if path_to_local_id(body, arg);
 
@@ -707,7 +707,7 @@ fn check_single_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], exp
         };
 
         let ty = cx.typeck_results().expr_ty(ex);
-        if *ty.kind() != ty::Bool || is_allowed(cx, MATCH_BOOL, ex.hir_id) {
+        if *ty.kind() != ty::Bool || is_lint_allowed(cx, MATCH_BOOL, ex.hir_id) {
             check_single_match_single_pattern(cx, ex, arms, expr, els);
             check_single_match_opt_like(cx, ex, arms, expr, ty, els);
         }
@@ -721,7 +721,7 @@ fn check_single_match_single_pattern(
     expr: &Expr<'_>,
     els: Option<&Expr<'_>>,
 ) {
-    if is_wild(&arms[1].pat) {
+    if is_wild(arms[1].pat) {
         report_single_match_single_pattern(cx, ex, arms, expr, els);
     }
 }
@@ -992,9 +992,9 @@ impl CommonPrefixSearcher<'a> {
     }
 }
 
-fn is_doc_hidden(cx: &LateContext<'_>, variant_def: &VariantDef) -> bool {
+fn is_hidden(cx: &LateContext<'_>, variant_def: &VariantDef) -> bool {
     let attrs = cx.tcx.get_attrs(variant_def.def_id);
-    clippy_utils::attrs::is_doc_hidden(attrs)
+    clippy_utils::attrs::is_doc_hidden(attrs) || clippy_utils::attrs::is_unstable(attrs)
 }
 
 #[allow(clippy::too_many_lines)]
@@ -1033,7 +1033,8 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
 
     // Accumulate the variants which should be put in place of the wildcard because they're not
     // already covered.
-    let mut missing_variants: Vec<_> = adt_def.variants.iter().collect();
+    let has_hidden = adt_def.variants.iter().any(|x| is_hidden(cx, x));
+    let mut missing_variants: Vec<_> = adt_def.variants.iter().filter(|x| !is_hidden(cx, x)).collect();
 
     let mut path_prefix = CommonPrefixSearcher::None;
     for arm in arms {
@@ -1118,7 +1119,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
 
     match missing_variants.as_slice() {
         [] => (),
-        [x] if !adt_def.is_variant_list_non_exhaustive() && !is_doc_hidden(cx, x) => span_lint_and_sugg(
+        [x] if !adt_def.is_variant_list_non_exhaustive() && !has_hidden => span_lint_and_sugg(
             cx,
             MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
             wildcard_span,
@@ -1129,7 +1130,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
         ),
         variants => {
             let mut suggestions: Vec<_> = variants.iter().copied().map(format_suggestion).collect();
-            let message = if adt_def.is_variant_list_non_exhaustive() {
+            let message = if adt_def.is_variant_list_non_exhaustive() || has_hidden {
                 suggestions.push("_".into());
                 "wildcard matches known variants and will also match future added variants"
             } else {
@@ -1286,7 +1287,7 @@ fn find_matches_sugg(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr
         if let Some((b1_arm, b0_arms)) = arms.split_last();
         if let Some(b0) = find_bool_lit(&b0_arms[0].body.kind, desugared);
         if let Some(b1) = find_bool_lit(&b1_arm.body.kind, desugared);
-        if is_wild(&b1_arm.pat);
+        if is_wild(b1_arm.pat);
         if b0 != b1;
         let if_guard = &b0_arms[0].guard;
         if if_guard.is_none() || b0_arms.len() == 1;
@@ -2266,7 +2267,8 @@ fn lint_match_arms<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) {
                             ),
                         );
                     } else {
-                        diag.span_help(i.pat.span, &format!("consider refactoring into `{} | {}`", lhs, rhs));
+                        diag.span_help(i.pat.span, &format!("consider refactoring into `{} | {}`", lhs, rhs,))
+                            .help("...or consider changing the match arm bodies");
                     }
                 },
             );
index 03cb41697d509dd46717ed6d1a1c43094749f605..f8ee31a00df821ebc0e6f7834d666b3adb3a40d5 100644 (file)
@@ -1,8 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_expn_of;
-use clippy_utils::source::{snippet, snippet_with_applicability};
+use clippy_utils::higher::FormatExpn;
+use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -94,27 +93,6 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_span: Spa
         }
     }
 
-    fn generate_format_arg_snippet(
-        cx: &LateContext<'_>,
-        a: &hir::Expr<'_>,
-        applicability: &mut Applicability,
-    ) -> Vec<String> {
-        if_chain! {
-            if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, format_arg) = a.kind;
-            if let hir::ExprKind::Match(format_arg_expr, _, _) = format_arg.kind;
-            if let hir::ExprKind::Tup(format_arg_expr_tup) = format_arg_expr.kind;
-
-            then {
-                format_arg_expr_tup
-                    .iter()
-                    .map(|a| snippet_with_applicability(cx, a.span, "..", applicability).into_owned())
-                    .collect()
-            } else {
-                unreachable!()
-            }
-        }
-    }
-
     fn is_call(node: &hir::ExprKind<'_>) -> bool {
         match node {
             hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, expr) => {
@@ -150,36 +128,22 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_span: Spa
     let mut applicability = Applicability::MachineApplicable;
 
     //Special handling for `format!` as arg_root
-    if_chain! {
-        if let hir::ExprKind::Block(block, None) = &arg_root.kind;
-        if block.stmts.len() == 1;
-        if let hir::StmtKind::Local(local) = &block.stmts[0].kind;
-        if let Some(arg_root) = &local.init;
-        if let hir::ExprKind::Call(inner_fun, inner_args) = arg_root.kind;
-        if is_expn_of(inner_fun.span, "format").is_some() && inner_args.len() == 1;
-        if let hir::ExprKind::Call(_, format_args) = &inner_args[0].kind;
-        then {
-            let fmt_spec = &format_args[0];
-            let fmt_args = &format_args[1];
-
-            let mut args = vec![snippet(cx, fmt_spec.span, "..").into_owned()];
-
-            args.extend(generate_format_arg_snippet(cx, fmt_args, &mut applicability));
-
-            let sugg = args.join(", ");
-
-            span_lint_and_sugg(
-                cx,
-                EXPECT_FUN_CALL,
-                span_replace_word,
-                &format!("use of `{}` followed by a function call", name),
-                "try this",
-                format!("unwrap_or_else({} panic!({}))", closure_args, sugg),
-                applicability,
-            );
-
-            return;
-        }
+    if let Some(format_expn) = FormatExpn::parse(arg_root) {
+        let span = match *format_expn.format_args.value_args {
+            [] => format_expn.format_args.format_string_span,
+            [.., last] => format_expn.format_args.format_string_span.to(last.span),
+        };
+        let sugg = snippet_with_applicability(cx, span, "..", &mut applicability);
+        span_lint_and_sugg(
+            cx,
+            EXPECT_FUN_CALL,
+            span_replace_word,
+            &format!("use of `{}` followed by a function call", name),
+            "try this",
+            format!("unwrap_or_else({} panic!({}))", closure_args, sugg),
+            applicability,
+        );
+        return;
     }
 
     let mut arg_root_snippet: Cow<'_, _> = snippet_with_applicability(cx, arg_root.span, "..", &mut applicability);
diff --git a/src/tools/clippy/clippy_lints/src/methods/extend_with_drain.rs b/src/tools/clippy/clippy_lints/src/methods/extend_with_drain.rs
new file mode 100644 (file)
index 0000000..57e10ce
--- /dev/null
@@ -0,0 +1,41 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
+use if_chain::if_chain;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, LangItem};
+use rustc_lint::LateContext;
+use rustc_span::symbol::sym;
+
+use super::EXTEND_WITH_DRAIN;
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) {
+    let ty = cx.typeck_results().expr_ty(recv).peel_refs();
+    if_chain! {
+        if is_type_diagnostic_item(cx, ty, sym::vec_type);
+        //check source object
+        if let ExprKind::MethodCall(src_method, _, [drain_vec, drain_arg], _) = &arg.kind;
+        if src_method.ident.as_str() == "drain";
+        if let src_ty = cx.typeck_results().expr_ty(drain_vec).peel_refs();
+        if is_type_diagnostic_item(cx, src_ty, sym::vec_type);
+        //check drain range
+        if let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs();
+        if is_type_lang_item(cx, src_ty_range, LangItem::RangeFull);
+        then {
+            let mut applicability = Applicability::MachineApplicable;
+            span_lint_and_sugg(
+                cx,
+                EXTEND_WITH_DRAIN,
+                expr.span,
+                "use of `extend` instead of `append` for adding the full range of a second vector",
+                "try this",
+                format!(
+                    "{}.append(&mut {})",
+                    snippet_with_applicability(cx, recv.span, "..", &mut applicability),
+                    snippet_with_applicability(cx, drain_vec.span, "..", &mut applicability)
+                ),
+                applicability,
+            );
+        }
+    }
+}
index 403fe8d35468468db91a9c46a13dd2755b5c9fd7..d1b5e945dfdaa83a85b5ce13d776b0d438b88579 100644 (file)
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::{is_expr_path_def_path, is_trait_method, path_to_local_id, paths};
-use if_chain::if_chain;
+use clippy_utils::{is_expr_identity_function, is_trait_method};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -9,32 +8,15 @@ use rustc_span::{source_map::Span, sym};
 use super::FILTER_MAP_IDENTITY;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, filter_map_arg: &hir::Expr<'_>, filter_map_span: Span) {
-    if is_trait_method(cx, expr, sym::Iterator) {
-        let apply_lint = |message: &str| {
-            span_lint_and_sugg(
-                cx,
-                FILTER_MAP_IDENTITY,
-                filter_map_span.with_hi(expr.span.hi()),
-                message,
-                "try",
-                "flatten()".to_string(),
-                Applicability::MachineApplicable,
-            );
-        };
-
-        if_chain! {
-            if let hir::ExprKind::Closure(_, _, body_id, _, _) = filter_map_arg.kind;
-            let body = cx.tcx.hir().body(body_id);
-
-            if let hir::PatKind::Binding(_, binding_id, ..) = body.params[0].pat.kind;
-            if path_to_local_id(&body.value, binding_id);
-            then {
-                apply_lint("called `filter_map(|x| x)` on an `Iterator`");
-            }
-        }
-
-        if is_expr_path_def_path(cx, filter_map_arg, &paths::CONVERT_IDENTITY) {
-            apply_lint("called `filter_map(std::convert::identity)` on an `Iterator`");
-        }
+    if is_trait_method(cx, expr, sym::Iterator) && is_expr_identity_function(cx, filter_map_arg) {
+        span_lint_and_sugg(
+            cx,
+            FILTER_MAP_IDENTITY,
+            filter_map_span.with_hi(expr.span.hi()),
+            "use of `filter_map` with an identity function",
+            "try",
+            "flatten()".to_string(),
+            Applicability::MachineApplicable,
+        );
     }
 }
index 25f8434cb94428f458f36fd442fcf8260e542828..6f911d79d0bc50880628e5de6f2711802601d58d 100644 (file)
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::{is_expr_path_def_path, is_trait_method, paths};
-use if_chain::if_chain;
+use clippy_utils::{is_expr_identity_function, is_trait_method};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -15,36 +14,15 @@ pub(super) fn check<'tcx>(
     flat_map_arg: &'tcx hir::Expr<'_>,
     flat_map_span: Span,
 ) {
-    if is_trait_method(cx, expr, sym::Iterator) {
-        let apply_lint = |message: &str| {
-            span_lint_and_sugg(
-                cx,
-                FLAT_MAP_IDENTITY,
-                flat_map_span.with_hi(expr.span.hi()),
-                message,
-                "try",
-                "flatten()".to_string(),
-                Applicability::MachineApplicable,
-            );
-        };
-
-        if_chain! {
-            if let hir::ExprKind::Closure(_, _, body_id, _, _) = flat_map_arg.kind;
-            let body = cx.tcx.hir().body(body_id);
-
-            if let hir::PatKind::Binding(_, _, binding_ident, _) = body.params[0].pat.kind;
-            if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = body.value.kind;
-
-            if path.segments.len() == 1;
-            if path.segments[0].ident.name == binding_ident.name;
-
-            then {
-                apply_lint("called `flat_map(|x| x)` on an `Iterator`");
-            }
-        }
-
-        if is_expr_path_def_path(cx, flat_map_arg, &paths::CONVERT_IDENTITY) {
-            apply_lint("called `flat_map(std::convert::identity)` on an `Iterator`");
-        }
+    if is_trait_method(cx, expr, sym::Iterator) && is_expr_identity_function(cx, flat_map_arg) {
+        span_lint_and_sugg(
+            cx,
+            FLAT_MAP_IDENTITY,
+            flat_map_span.with_hi(expr.span.hi()),
+            "use of `flat_map` with an identity function",
+            "try",
+            "flatten()".to_string(),
+            Applicability::MachineApplicable,
+        );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs
new file mode 100644 (file)
index 0000000..538a125
--- /dev/null
@@ -0,0 +1,38 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{is_expr_identity_function, is_trait_method};
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_lint::LateContext;
+use rustc_span::{source_map::Span, sym};
+
+use super::MAP_IDENTITY;
+
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    caller: &hir::Expr<'_>,
+    map_arg: &hir::Expr<'_>,
+    _map_span: Span,
+) {
+    let caller_ty = cx.typeck_results().expr_ty(caller);
+
+    if_chain! {
+        if is_trait_method(cx, expr, sym::Iterator)
+            || is_type_diagnostic_item(cx, caller_ty, sym::result_type)
+            || is_type_diagnostic_item(cx, caller_ty, sym::option_type);
+        if is_expr_identity_function(cx, map_arg);
+        if let Some(sugg_span) = expr.span.trim_start(caller.span);
+        then {
+            span_lint_and_sugg(
+                cx,
+                MAP_IDENTITY,
+                sugg_span,
+                "unnecessary map of the identity function",
+                "remove the call to `map`",
+                String::new(),
+                Applicability::MachineApplicable,
+            )
+        }
+    }
+}
index c8ae972f18ca62a5d4ba0f3e19ca803fa4169f7a..50e558b718ab3d7847460686381fae9207d01d6f 100644 (file)
@@ -11,6 +11,7 @@ mod clone_on_ref_ptr;
 mod cloned_instead_of_copied;
 mod expect_fun_call;
 mod expect_used;
+mod extend_with_drain;
 mod filetype_is_file;
 mod filter_map;
 mod filter_map_identity;
@@ -35,6 +36,7 @@ mod manual_saturating_arithmetic;
 mod manual_str_repeat;
 mod map_collect_result_unit;
 mod map_flatten;
+mod map_identity;
 mod map_unwrap_or;
 mod ok_expect;
 mod option_as_ref_deref;
@@ -1031,6 +1033,30 @@ declare_clippy_lint! {
     "using `.get().unwrap()` or `.get_mut().unwrap()` when using `[]` would work instead"
 }
 
+declare_clippy_lint! {
+    /// **What it does:** Checks for occurrences where one vector gets extended instead of append
+    ///
+    /// **Why is this bad?** Using `append` instead of `extend` is more concise and faster
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// let mut a = vec![1, 2, 3];
+    /// let mut b = vec![4, 5, 6];
+    ///
+    /// // Bad
+    /// a.extend(b.drain(..));
+    ///
+    /// // Good
+    /// a.append(&mut b);
+    /// ```
+    pub EXTEND_WITH_DRAIN,
+    perf,
+    "using vec.append(&mut vec) to move the full range of a vecor to another"
+}
+
 declare_clippy_lint! {
     /// **What it does:** Checks for the use of `.extend(s.chars())` where s is a
     /// `&str` or `String`.
@@ -1222,7 +1248,7 @@ declare_clippy_lint! {
     /// let _ = (0..3).map(|x| x + 2).count();
     /// ```
     pub SUSPICIOUS_MAP,
-    complexity,
+    suspicious,
     "suspicious usage of map"
 }
 
@@ -1504,7 +1530,7 @@ declare_clippy_lint! {
     /// assert_eq!(v, vec![5, 5, 5, 5, 5]);
     /// ```
     pub FROM_ITER_INSTEAD_OF_COLLECT,
-    style,
+    pedantic,
     "use `.collect()` instead of `::from_iter()`"
 }
 
@@ -1561,6 +1587,29 @@ declare_clippy_lint! {
     "call to `filter_map` where `flatten` is sufficient"
 }
 
+declare_clippy_lint! {
+    /// **What it does:** Checks for instances of `map(f)` where `f` is the identity function.
+    ///
+    /// **Why is this bad?** It can be written more concisely without the call to `map`.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// let x = [1, 2, 3];
+    /// let y: Vec<_> = x.iter().map(|x| x).map(|x| 2*x).collect();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let x = [1, 2, 3];
+    /// let y: Vec<_> = x.iter().map(|x| 2*x).collect();
+    /// ```
+    pub MAP_IDENTITY,
+    complexity,
+    "using iterator.map(|x| x)"
+}
+
 declare_clippy_lint! {
     /// **What it does:** Checks for the use of `.bytes().nth()`.
     ///
@@ -1728,6 +1777,7 @@ impl_lint_pass!(Methods => [
     FILTER_NEXT,
     SKIP_WHILE_NEXT,
     FILTER_MAP_IDENTITY,
+    MAP_IDENTITY,
     MANUAL_FILTER_MAP,
     MANUAL_FIND_MAP,
     OPTION_FILTER_MAP,
@@ -1760,7 +1810,8 @@ impl_lint_pass!(Methods => [
     INSPECT_FOR_EACH,
     IMPLICIT_CLONE,
     SUSPICIOUS_SPLITN,
-    MANUAL_STR_REPEAT
+    MANUAL_STR_REPEAT,
+    EXTEND_WITH_DRAIN
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -1985,7 +2036,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
 fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Option<&RustcVersion>) {
     if let Some((name, [recv, args @ ..], span)) = method_call!(expr) {
         match (name, args) {
-            ("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [recv, _]) => {
+            ("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [_arg]) => {
                 zst_offset::check(cx, expr, recv);
             },
             ("and_then", [arg]) => {
@@ -2022,7 +2073,10 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
                 Some(("ok", [recv], _)) => ok_expect::check(cx, expr, recv),
                 _ => expect_used::check(cx, expr, recv),
             },
-            ("extend", [arg]) => string_extend_chars::check(cx, expr, recv, arg),
+            ("extend", [arg]) => {
+                string_extend_chars::check(cx, expr, recv, arg);
+                extend_with_drain::check(cx, expr, recv, arg);
+            },
             ("filter_map", [arg]) => {
                 unnecessary_filter_map::check(cx, expr, arg);
                 filter_map_identity::check(cx, expr, arg, span);
@@ -2058,6 +2112,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
                         _ => {},
                     }
                 }
+                map_identity::check(cx, expr, recv, m_arg, span);
             },
             ("map_or", [def, map]) => option_map_or_none::check(cx, expr, recv, def, map),
             ("next", []) => {
index 800172f4cf3dcdd3ee8a51363444b396c60b4040..073c5570a88776e8c396bcc69284a3f5735cd2e6 100644 (file)
@@ -87,7 +87,7 @@ pub(super) fn check<'tcx>(
         ];
 
         if let hir::ExprKind::MethodCall(path, _, args, _) = &arg.kind {
-            if path.ident.as_str() == "len" {
+            if path.ident.name == sym::len {
                 let ty = cx.typeck_results().expr_ty(&args[0]).peel_refs();
 
                 match ty.kind() {
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
     }
diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
new file mode 100644 (file)
index 0000000..5956535
--- /dev/null
@@ -0,0 +1,102 @@
+use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet_opt};
+
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::Applicability;
+use rustc_hir::{def::Res, def_id::DefId, Crate, Item, ItemKind, UseKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::Symbol;
+
+use crate::utils::conf::Rename;
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for imports that do not rename the item as specified
+    /// in the `enforce-import-renames` config option.
+    ///
+    /// **Why is this bad?** Consistency is important, if a project has defined import
+    /// renames they should be followed. More practically, some item names are too
+    /// vague outside of their defining scope this can enforce a more meaningful naming.
+    ///
+    /// **Known problems:** None
+    ///
+    /// **Example:**
+    ///
+    /// An example clippy.toml configuration:
+    /// ```toml
+    /// # clippy.toml
+    /// enforced-import-renames = [ { path = "serde_json::Value", rename = "JsonValue" }]
+    /// ```
+    ///
+    /// ```rust,ignore
+    /// use serde_json::Value;
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// use serde_json::Value as JsonValue;
+    /// ```
+    pub MISSING_ENFORCED_IMPORT_RENAMES,
+    restriction,
+    "enforce import renames"
+}
+
+pub struct ImportRename {
+    conf_renames: Vec<Rename>,
+    renames: FxHashMap<DefId, Symbol>,
+}
+
+impl ImportRename {
+    pub fn new(conf_renames: Vec<Rename>) -> Self {
+        Self {
+            conf_renames,
+            renames: FxHashMap::default(),
+        }
+    }
+}
+
+impl_lint_pass!(ImportRename => [MISSING_ENFORCED_IMPORT_RENAMES]);
+
+impl LateLintPass<'_> for ImportRename {
+    fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
+        for Rename { path, rename } in &self.conf_renames {
+            if let Res::Def(_, id) = clippy_utils::path_to_res(cx, &path.split("::").collect::<Vec<_>>()) {
+                self.renames.insert(id, Symbol::intern(rename));
+            }
+        }
+    }
+
+    fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+        if_chain! {
+            if let ItemKind::Use(path, UseKind::Single) = &item.kind;
+            if let Res::Def(_, id) = path.res;
+            if let Some(name) = self.renames.get(&id);
+            // Remove semicolon since it is not present for nested imports
+            let span_without_semi = cx.sess().source_map().span_until_char(item.span, ';');
+            if let Some(snip) = snippet_opt(cx, span_without_semi);
+            if let Some(import) = match snip.split_once(" as ") {
+                None => Some(snip.as_str()),
+                Some((import, rename)) => {
+                    if rename.trim() == &*name.as_str() {
+                        None
+                    } else {
+                        Some(import.trim())
+                    }
+                },
+            };
+            then {
+                span_lint_and_sugg(
+                    cx,
+                    MISSING_ENFORCED_IMPORT_RENAMES,
+                    span_without_semi,
+                    "this import should be renamed",
+                    "try",
+                    format!(
+                        "{} as {}",
+                        import,
+                        name,
+                    ),
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+    }
+}
index 584daa5e11992a17921f4252592051ff8e598524..f5ce3e325512d5b838a9447c8b3517ca44315bbe 100644 (file)
@@ -1,7 +1,7 @@
 //! lint on multiple versions of a crate being used
 
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::run_lints;
+use clippy_utils::is_lint_allowed;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::{Crate, CRATE_HIR_ID};
 use rustc_lint::{LateContext, LateLintPass};
@@ -39,7 +39,7 @@ declare_lint_pass!(MultipleCrateVersions => [MULTIPLE_CRATE_VERSIONS]);
 
 impl LateLintPass<'_> for MultipleCrateVersions {
     fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
-        if !run_lints(cx, &[MULTIPLE_CRATE_VERSIONS], CRATE_HIR_ID) {
+        if is_lint_allowed(cx, MULTIPLE_CRATE_VERSIONS, CRATE_HIR_ID) {
             return;
         }
 
index 1786d5805d78b342dfa1b5c693d76b8db1aeae62..4dbbb14c504fa445f334b4b008ac248ed911a17b 100644 (file)
@@ -50,7 +50,7 @@ declare_clippy_lint! {
     /// }
     /// ```
     pub MUTABLE_KEY_TYPE,
-    correctness,
+    suspicious,
     "Check for mutable `Map`/`Set` key type"
 }
 
@@ -120,8 +120,8 @@ fn is_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) -> bo
         },
         Tuple(..) => ty.tuple_fields().any(|ty| is_mutable_type(cx, ty, span)),
         Adt(..) => {
-            cx.tcx.layout_of(cx.param_env.and(ty)).is_ok()
-                && !ty.has_escaping_bound_vars()
+            !ty.has_escaping_bound_vars()
+                && cx.tcx.layout_of(cx.param_env.and(ty)).is_ok()
                 && !ty.is_freeze(cx.tcx.at(span), cx.param_env)
         },
         _ => false,
index 3b3736fd3a19114601421a34cd60e8cd0993f5b9..780690548e52b7008d3ccd590a4592050e054161 100644 (file)
@@ -71,6 +71,9 @@ declare_lint_pass!(NeedlessBool => [NEEDLESS_BOOL]);
 impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         use self::Expression::{Bool, RetBool};
+        if e.span.from_expansion() {
+            return;
+        }
         if let ExprKind::If(pred, then_block, Some(else_expr)) = e.kind {
             let reduce = |ret, not| {
                 let mut applicability = Applicability::MachineApplicable;
index e33a33e238633aeaf5b68930e536070d80b73cb5..57fd03f4e12a68afd6fc8b322cd0b69cf7d599db 100644 (file)
@@ -326,10 +326,8 @@ impl MovedVariablesCtxt {
 }
 
 impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt {
-    fn consume(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, _: HirId, mode: euv::ConsumeMode) {
-        if let euv::ConsumeMode::Move = mode {
-            self.move_common(cmt);
-        }
+    fn consume(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, _: HirId) {
+        self.move_common(cmt);
     }
 
     fn borrow(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {}
index b2206a822088e01e9d6798a451585e533a0b1b6f..910b05360925d53dd6a6fd39aa14dbc8066d5cd0 100644 (file)
@@ -167,7 +167,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
                         BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => None,
                         BlockCheckMode::DefaultBlock => Some(vec![&**e]),
                         // in case of compiler-inserted signaling blocks
-                        _ => reduce_expression(cx, e),
+                        BlockCheckMode::UnsafeBlock(_) => reduce_expression(cx, e),
                     }
                 })
             } else {
diff --git a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
new file mode 100644 (file)
index 0000000..043e7fa
--- /dev/null
@@ -0,0 +1,280 @@
+use std::{
+    fmt,
+    hash::{Hash, Hasher},
+};
+
+use clippy_utils::{diagnostics::span_lint_and_help, in_macro, is_direct_expn_of, source::snippet_opt};
+use if_chain::if_chain;
+use rustc_ast::ast;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::Span;
+use serde::{de, Deserialize};
+
+declare_clippy_lint! {
+    /// **What it does:** Checks that common macros are used with consistent bracing.
+    ///
+    /// **Why is this bad?** This is mostly a consistency lint although using () or []
+    /// doesn't give you a semicolon in item position, which can be unexpected.
+    ///
+    /// **Known problems:**
+    /// None
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// vec!{1, 2, 3};
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// vec![1, 2, 3];
+    /// ```
+    pub NONSTANDARD_MACRO_BRACES,
+    nursery,
+    "check consistent use of braces in macro"
+}
+
+const BRACES: &[(&str, &str)] = &[("(", ")"), ("{", "}"), ("[", "]")];
+
+/// The (name, (open brace, close brace), source snippet)
+type MacroInfo<'a> = (&'a str, &'a (String, String), String);
+
+#[derive(Clone, Debug, Default)]
+pub struct MacroBraces {
+    macro_braces: FxHashMap<String, (String, String)>,
+    done: FxHashSet<Span>,
+}
+
+impl MacroBraces {
+    pub fn new(conf: &FxHashSet<MacroMatcher>) -> Self {
+        let macro_braces = macro_braces(conf.clone());
+        Self {
+            macro_braces,
+            done: FxHashSet::default(),
+        }
+    }
+}
+
+impl_lint_pass!(MacroBraces => [NONSTANDARD_MACRO_BRACES]);
+
+impl EarlyLintPass for MacroBraces {
+    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
+        if let Some((name, braces, snip)) = is_offending_macro(cx, item.span, self) {
+            let span = item.span.ctxt().outer_expn_data().call_site;
+            emit_help(cx, snip, braces, name, span);
+            self.done.insert(span);
+        }
+    }
+
+    fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) {
+        if let Some((name, braces, snip)) = is_offending_macro(cx, stmt.span, self) {
+            let span = stmt.span.ctxt().outer_expn_data().call_site;
+            emit_help(cx, snip, braces, name, span);
+            self.done.insert(span);
+        }
+    }
+
+    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
+        if let Some((name, braces, snip)) = is_offending_macro(cx, expr.span, self) {
+            let span = expr.span.ctxt().outer_expn_data().call_site;
+            emit_help(cx, snip, braces, name, span);
+            self.done.insert(span);
+        }
+    }
+
+    fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
+        if let Some((name, braces, snip)) = is_offending_macro(cx, ty.span, self) {
+            let span = ty.span.ctxt().outer_expn_data().call_site;
+            emit_help(cx, snip, braces, name, span);
+            self.done.insert(span);
+        }
+    }
+}
+
+fn is_offending_macro<'a>(cx: &EarlyContext<'_>, span: Span, mac_braces: &'a MacroBraces) -> Option<MacroInfo<'a>> {
+    if_chain! {
+        if in_macro(span);
+        if let Some((name, braces)) = find_matching_macro(span, &mac_braces.macro_braces);
+        if let Some(snip) = snippet_opt(cx, span.ctxt().outer_expn_data().call_site);
+        // we must check only invocation sites
+        // https://github.com/rust-lang/rust-clippy/issues/7422
+        if snip.starts_with(name);
+        // make formatting consistent
+        let c = snip.replace(" ", "");
+        if !c.starts_with(&format!("{}!{}", name, braces.0));
+        if !mac_braces.done.contains(&span.ctxt().outer_expn_data().call_site);
+        then {
+            Some((name, braces, snip))
+        } else {
+            None
+        }
+    }
+}
+
+fn emit_help(cx: &EarlyContext<'_>, snip: String, braces: &(String, String), name: &str, span: Span) {
+    let with_space = &format!("! {}", braces.0);
+    let without_space = &format!("!{}", braces.0);
+    let mut help = snip;
+    for b in BRACES.iter().filter(|b| b.0 != braces.0) {
+        help = help.replace(b.0, &braces.0).replace(b.1, &braces.1);
+        // Only `{` traditionally has space before the brace
+        if braces.0 != "{" && help.contains(with_space) {
+            help = help.replace(with_space, without_space);
+        } else if braces.0 == "{" && help.contains(without_space) {
+            help = help.replace(without_space, with_space);
+        }
+    }
+    span_lint_and_help(
+        cx,
+        NONSTANDARD_MACRO_BRACES,
+        span,
+        &format!("use of irregular braces for `{}!` macro", name),
+        Some(span),
+        &format!("consider writing `{}`", help),
+    );
+}
+
+fn find_matching_macro(
+    span: Span,
+    braces: &FxHashMap<String, (String, String)>,
+) -> Option<(&String, &(String, String))> {
+    braces
+        .iter()
+        .find(|(macro_name, _)| is_direct_expn_of(span, macro_name).is_some())
+}
+
+fn macro_braces(conf: FxHashSet<MacroMatcher>) -> FxHashMap<String, (String, String)> {
+    let mut braces = vec![
+        macro_matcher!(
+            name: "print",
+            braces: ("(", ")"),
+        ),
+        macro_matcher!(
+            name: "println",
+            braces: ("(", ")"),
+        ),
+        macro_matcher!(
+            name: "eprint",
+            braces: ("(", ")"),
+        ),
+        macro_matcher!(
+            name: "eprintln",
+            braces: ("(", ")"),
+        ),
+        macro_matcher!(
+            name: "write",
+            braces: ("(", ")"),
+        ),
+        macro_matcher!(
+            name: "writeln",
+            braces: ("(", ")"),
+        ),
+        macro_matcher!(
+            name: "format",
+            braces: ("(", ")"),
+        ),
+        macro_matcher!(
+            name: "format_args",
+            braces: ("(", ")"),
+        ),
+        macro_matcher!(
+            name: "vec",
+            braces: ("[", "]"),
+        ),
+    ]
+    .into_iter()
+    .collect::<FxHashMap<_, _>>();
+    // We want users items to override any existing items
+    for it in conf {
+        braces.insert(it.name, it.braces);
+    }
+    braces
+}
+
+macro_rules! macro_matcher {
+    (name: $name:expr, braces: ($open:expr, $close:expr) $(,)?) => {
+        ($name.to_owned(), ($open.to_owned(), $close.to_owned()))
+    };
+}
+pub(crate) use macro_matcher;
+
+#[derive(Clone, Debug)]
+pub struct MacroMatcher {
+    name: String,
+    braces: (String, String),
+}
+
+impl Hash for MacroMatcher {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.name.hash(state);
+    }
+}
+
+impl PartialEq for MacroMatcher {
+    fn eq(&self, other: &Self) -> bool {
+        self.name == other.name
+    }
+}
+impl Eq for MacroMatcher {}
+
+impl<'de> Deserialize<'de> for MacroMatcher {
+    fn deserialize<D>(deser: D) -> Result<Self, D::Error>
+    where
+        D: de::Deserializer<'de>,
+    {
+        #[derive(Deserialize)]
+        #[serde(field_identifier, rename_all = "lowercase")]
+        enum Field {
+            Name,
+            Brace,
+        }
+        struct MacVisitor;
+        impl<'de> de::Visitor<'de> for MacVisitor {
+            type Value = MacroMatcher;
+
+            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+                formatter.write_str("struct MacroMatcher")
+            }
+
+            fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
+            where
+                V: de::MapAccess<'de>,
+            {
+                let mut name = None;
+                let mut brace: Option<&str> = None;
+                while let Some(key) = map.next_key()? {
+                    match key {
+                        Field::Name => {
+                            if name.is_some() {
+                                return Err(de::Error::duplicate_field("name"));
+                            }
+                            name = Some(map.next_value()?);
+                        },
+                        Field::Brace => {
+                            if brace.is_some() {
+                                return Err(de::Error::duplicate_field("brace"));
+                            }
+                            brace = Some(map.next_value()?);
+                        },
+                    }
+                }
+                let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
+                let brace = brace.ok_or_else(|| de::Error::missing_field("brace"))?;
+                Ok(MacroMatcher {
+                    name,
+                    braces: BRACES
+                        .iter()
+                        .find(|b| b.0 == brace)
+                        .map(|(o, c)| ((*o).to_owned(), (*c).to_owned()))
+                        .ok_or_else(|| {
+                            de::Error::custom(&format!("expected one of `(`, `{{`, `[` found `{}`", brace))
+                        })?,
+                })
+            }
+        }
+
+        const FIELDS: &[&str] = &["name", "brace"];
+        deser.deserialize_struct("MacroMatcher", FIELDS, MacVisitor)
+    }
+}
index b6af4175edfdabce7903ba40233b106a11d8daa7..b2be35bdddb38fbb18625b0c305c092ca9ace406 100644 (file)
@@ -132,7 +132,7 @@ fn detect_option_if_let_else<'tcx>(
         if !is_else_clause(cx.tcx, expr);
         if arms.len() == 2;
         if !is_result_ok(cx, cond_expr); // Don't lint on Result::ok because a different lint does it already
-        if let PatKind::TupleStruct(struct_qpath, &[inner_pat], _) = &arms[0].pat.kind;
+        if let PatKind::TupleStruct(struct_qpath, [inner_pat], _) = &arms[0].pat.kind;
         if is_lang_ctor(cx, struct_qpath, OptionSome);
         if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind;
         if !contains_return_break_continue_macro(arms[0].body);
index 1a680e7607e0b21e0116df6e0fa4363af52081b9..dc28874c16e67febf474f13cda31f1dcb38e5711 100644 (file)
@@ -74,7 +74,9 @@ declare_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANI
 
 impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if match_panic_call(cx, expr).is_some() && is_expn_of(expr.span, "debug_assert").is_none() {
+        if match_panic_call(cx, expr).is_some()
+            && (is_expn_of(expr.span, "debug_assert").is_none() && is_expn_of(expr.span, "assert").is_none())
+        {
             let span = get_outer_span(expr);
             if is_expn_of(expr.span, "unimplemented").is_some() {
                 span_lint(
index 9bab783998aa5693088f8352a3319e55f23086a1..ea4065d371b81a1bb11b243fbd66179ff7265f5b 100644 (file)
@@ -258,7 +258,7 @@ fn get_variant<'a>(adt_def: &'a AdtDef, qpath: &QPath<'_>) -> Option<&'a Variant
 
 fn find_first_mismatch_in_tuple<'tcx, I>(
     cx: &LateContext<'tcx>,
-    pats: &[&Pat<'_>],
+    pats: &[Pat<'_>],
     ty_iter_src: I,
 ) -> Option<(Span, Mutability, Level)>
 where
index 12c44436874e1dbdff49142e105f4ef49275f82a..dba3b1805cd595df2029aa7c67ce823e8b8423c8 100644 (file)
@@ -4,7 +4,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the
 use clippy_utils::ptr::get_spans;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::{is_type_diagnostic_item, match_type, walk_ptrs_hir_ty};
-use clippy_utils::{expr_path_res, is_allowed, match_any_def_paths, paths};
+use clippy_utils::{expr_path_res, is_lint_allowed, match_any_def_paths, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{
@@ -246,7 +246,7 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
     for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() {
         // Honor the allow attribute on parameters. See issue 5644.
         if let Some(body) = &body {
-            if is_allowed(cx, PTR_ARG, body.params[idx].hir_id) {
+            if is_lint_allowed(cx, PTR_ARG, body.params[idx].hir_id) {
                 continue;
             }
         }
index ae5f0627fd65a41d5d271f895d5bd1622b48a5be..b41c478c266157d5295155ffdc4103aed7847452 100644 (file)
@@ -329,7 +329,7 @@ fn check_range_zip_with_len(cx: &LateContext<'_>, path: &PathSegment<'_>, args:
         if is_integer_const(cx, start, 0);
         // `.len()` call
         if let ExprKind::MethodCall(len_path, _, len_args, _) = end.kind;
-        if len_path.ident.name == sym!(len) && len_args.len() == 1;
+        if len_path.ident.name == sym::len && len_args.len() == 1;
         // `.iter()` and `.len()` called on same `Path`
         if let ExprKind::Path(QPath::Resolved(_, iter_path)) = iter_args[0].kind;
         if let ExprKind::Path(QPath::Resolved(_, len_path)) = len_args[0].kind;
index 7dafce60d5eda1cc2c09bbf31913a4dc277772d7..7ba7ff3a353f976d8ba7bf52f5a191b4d7bff5f2 100644 (file)
@@ -12,6 +12,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::{
     self, traversal,
     visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor as _},
+    Mutability,
 };
 use rustc_middle::ty::{self, fold::TypeVisitor, Ty};
 use rustc_mir::dataflow::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor};
@@ -87,13 +88,18 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
 
         let mir = cx.tcx.optimized_mir(def_id.to_def_id());
 
+        let possible_origin = {
+            let mut vis = PossibleOriginVisitor::new(mir);
+            vis.visit_body(mir);
+            vis.into_map(cx)
+        };
         let maybe_storage_live_result = MaybeStorageLive
             .into_engine(cx.tcx, mir)
             .pass_name("redundant_clone")
             .iterate_to_fixpoint()
             .into_results_cursor(mir);
         let mut possible_borrower = {
-            let mut vis = PossibleBorrowerVisitor::new(cx, mir);
+            let mut vis = PossibleBorrowerVisitor::new(cx, mir, possible_origin);
             vis.visit_body(mir);
             vis.into_map(cx, maybe_storage_live_result)
         };
@@ -132,7 +138,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
                 }
             }
 
-            // `{ cloned = &arg; clone(move cloned); }` or `{ cloned = &arg; to_path_buf(cloned); }`
+            // `{ arg = &cloned; clone(move arg); }` or `{ arg = &cloned; to_path_buf(arg); }`
             let (cloned, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to(cx, mir, arg, from_borrow, bb));
 
             let loc = mir::Location {
@@ -509,14 +515,20 @@ struct PossibleBorrowerVisitor<'a, 'tcx> {
     possible_borrower: TransitiveRelation<mir::Local>,
     body: &'a mir::Body<'tcx>,
     cx: &'a LateContext<'tcx>,
+    possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
 }
 
 impl<'a, 'tcx> PossibleBorrowerVisitor<'a, 'tcx> {
-    fn new(cx: &'a LateContext<'tcx>, body: &'a mir::Body<'tcx>) -> Self {
+    fn new(
+        cx: &'a LateContext<'tcx>,
+        body: &'a mir::Body<'tcx>,
+        possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
+    ) -> Self {
         Self {
             possible_borrower: TransitiveRelation::default(),
             cx,
             body,
+            possible_origin,
         }
     }
 
@@ -585,21 +597,105 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> {
             ..
         } = &terminator.kind
         {
+            // TODO add doc
             // If the call returns something with lifetimes,
             // let's conservatively assume the returned value contains lifetime of all the arguments.
             // For example, given `let y: Foo<'a> = foo(x)`, `y` is considered to be a possible borrower of `x`.
-            if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_continue() {
-                return;
-            }
+
+            let mut immutable_borrowers = vec![];
+            let mut mutable_borrowers = vec![];
 
             for op in args {
                 match op {
                     mir::Operand::Copy(p) | mir::Operand::Move(p) => {
-                        self.possible_borrower.add(p.local, *dest);
+                        if let ty::Ref(_, _, Mutability::Mut) = self.body.local_decls[p.local].ty.kind() {
+                            mutable_borrowers.push(p.local);
+                        } else {
+                            immutable_borrowers.push(p.local);
+                        }
                     },
                     mir::Operand::Constant(..) => (),
                 }
             }
+
+            let mut mutable_variables: Vec<mir::Local> = mutable_borrowers
+                .iter()
+                .filter_map(|r| self.possible_origin.get(r))
+                .flat_map(HybridBitSet::iter)
+                .collect();
+
+            if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_break() {
+                mutable_variables.push(*dest);
+            }
+
+            for y in mutable_variables {
+                for x in &immutable_borrowers {
+                    self.possible_borrower.add(*x, y);
+                }
+                for x in &mutable_borrowers {
+                    self.possible_borrower.add(*x, y);
+                }
+            }
+        }
+    }
+}
+
+/// Collect possible borrowed for every `&mut` local.
+/// For exampel, `_1 = &mut _2` generate _1: {_2,...}
+/// Known Problems: not sure all borrowed are tracked
+struct PossibleOriginVisitor<'a, 'tcx> {
+    possible_origin: TransitiveRelation<mir::Local>,
+    body: &'a mir::Body<'tcx>,
+}
+
+impl<'a, 'tcx> PossibleOriginVisitor<'a, 'tcx> {
+    fn new(body: &'a mir::Body<'tcx>) -> Self {
+        Self {
+            possible_origin: TransitiveRelation::default(),
+            body,
+        }
+    }
+
+    fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap<mir::Local, HybridBitSet<mir::Local>> {
+        let mut map = FxHashMap::default();
+        for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) {
+            if is_copy(cx, self.body.local_decls[row].ty) {
+                continue;
+            }
+
+            let borrowers = self.possible_origin.reachable_from(&row);
+            if !borrowers.is_empty() {
+                let mut bs = HybridBitSet::new_empty(self.body.local_decls.len());
+                for &c in borrowers {
+                    if c != mir::Local::from_usize(0) {
+                        bs.insert(c);
+                    }
+                }
+
+                if !bs.is_empty() {
+                    map.insert(row, bs);
+                }
+            }
+        }
+        map
+    }
+}
+
+impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleOriginVisitor<'a, 'tcx> {
+    fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _location: mir::Location) {
+        let lhs = place.local;
+        match rvalue {
+            // Only consider `&mut`, which can modify origin place
+            mir::Rvalue::Ref(_, rustc_middle::mir::BorrowKind::Mut { .. }, borrowed) |
+            // _2: &mut _;
+            // _3 = move _2
+            mir::Rvalue::Use(mir::Operand::Move(borrowed))  |
+            // _3 = move _2 as &mut _;
+            mir::Rvalue::Cast(_, mir::Operand::Move(borrowed), _)
+                => {
+                self.possible_origin.add(lhs, borrowed.local);
+            },
+            _ => {},
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
new file mode 100644 (file)
index 0000000..d9df396
--- /dev/null
@@ -0,0 +1,91 @@
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::return_ty;
+use clippy_utils::ty::{contains_adt_constructor, contains_ty};
+use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind, Node};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// **What it does:** Warns when constructors have the same name as their types.
+    ///
+    /// **Why is this bad?** Repeating the name of the type is redundant.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust,ignore
+    /// struct Foo {}
+    ///
+    /// impl Foo {
+    ///     pub fn foo() -> Foo {
+    ///         Foo {}
+    ///     }
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// struct Foo {}
+    ///
+    /// impl Foo {
+    ///     pub fn new() -> Foo {
+    ///         Foo {}
+    ///     }
+    /// }
+    /// ```
+    pub SELF_NAMED_CONSTRUCTORS,
+    style,
+    "method should not have the same name as the type it is implemented for"
+}
+
+declare_lint_pass!(SelfNamedConstructors => [SELF_NAMED_CONSTRUCTORS]);
+
+impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
+    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
+        match impl_item.kind {
+            ImplItemKind::Fn(ref sig, _) => {
+                if sig.decl.implicit_self.has_implicit_self() {
+                    return;
+                }
+            },
+            _ => return,
+        }
+
+        let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+        let item = cx.tcx.hir().expect_item(parent);
+        let self_ty = cx.tcx.type_of(item.def_id);
+        let ret_ty = return_ty(cx, impl_item.hir_id());
+
+        // Do not check trait impls
+        if matches!(item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. })) {
+            return;
+        }
+
+        // Ensure method is constructor-like
+        if let Some(self_adt) = self_ty.ty_adt_def() {
+            if !contains_adt_constructor(ret_ty, self_adt) {
+                return;
+            }
+        } else if !contains_ty(ret_ty, self_ty) {
+            return;
+        }
+
+        if_chain! {
+            if let Some(self_def) = self_ty.ty_adt_def();
+            if let Some(self_local_did) = self_def.did.as_local();
+            let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did);
+            if let Some(Node::Item(x)) = cx.tcx.hir().find(self_id);
+            let type_name = x.ident.name.as_str().to_lowercase();
+            if impl_item.ident.name.as_str() == type_name || impl_item.ident.name.as_str().replace("_", "") == type_name;
+
+            then {
+                span_lint(
+                    cx,
+                    SELF_NAMED_CONSTRUCTORS,
+                    impl_item.span,
+                    &format!("constructor `{}` has the same name as the type", impl_item.ident.name),
+                );
+            }
+        }
+    }
+}
index 16e4d73851fb4e89b67cb68ff184880254d4cee1..da3e30af35ca4ffd7e2a8de07ef16ce6e028e04c 100644 (file)
@@ -1,3 +1,4 @@
+use crate::rustc_lint::LintContext;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_macro_callsite;
 use clippy_utils::{in_macro, sugg};
@@ -45,6 +46,7 @@ impl LateLintPass<'_> for SemicolonIfNothingReturned {
             if t_expr.is_unit();
             if let snippet = snippet_with_macro_callsite(cx, expr.span, "}");
             if !snippet.ends_with('}');
+            if cx.sess().source_map().is_multiline(block.span);
             then {
                 // filter out the desugared `for` loop
                 if let ExprKind::DropTemps(..) = &expr.kind {
index 9d91b53e1bbc1ad4b4827198f2380379e596707a..958e462125ef1cafc3d823bdc1d984de575db6f6 100644 (file)
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sug
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::SpanlessEq;
-use clippy_utils::{get_parent_expr, is_allowed, match_function_call, method_calls, paths};
+use clippy_utils::{get_parent_expr, is_lint_allowed, match_function_call, method_calls, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, QPath};
@@ -124,7 +124,7 @@ impl<'tcx> LateLintPass<'tcx> for StringAdd {
         ) = e.kind
         {
             if is_string(cx, left) {
-                if !is_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) {
+                if !is_lint_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) {
                     let parent = get_parent_expr(cx, e);
                     if let Some(p) = parent {
                         if let ExprKind::Assign(target, _, _) = p.kind {
diff --git a/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs b/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs
new file mode 100644 (file)
index 0000000..2ccf3a3
--- /dev/null
@@ -0,0 +1,82 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::in_macro;
+use clippy_utils::paths;
+use clippy_utils::source::snippet_with_macro_callsite;
+use clippy_utils::ty::{is_type_diagnostic_item, is_type_ref_to_diagnostic_item};
+use if_chain::if_chain;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::symbol::{sym, Symbol};
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for usage of `libc::strlen` on a `CString` or `CStr` value,
+    /// and suggest calling `as_bytes().len()` or `to_bytes().len()` respectively instead.
+    ///
+    /// **Why is this bad?** This avoids calling an unsafe `libc` function.
+    /// Currently, it also avoids calculating the length.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust, ignore
+    /// use std::ffi::CString;
+    /// let cstring = CString::new("foo").expect("CString::new failed");
+    /// let len = unsafe { libc::strlen(cstring.as_ptr()) };
+    /// ```
+    /// Use instead:
+    /// ```rust, no_run
+    /// use std::ffi::CString;
+    /// let cstring = CString::new("foo").expect("CString::new failed");
+    /// let len = cstring.as_bytes().len();
+    /// ```
+    pub STRLEN_ON_C_STRINGS,
+    complexity,
+    "using `libc::strlen` on a `CString` or `CStr` value, while `as_bytes().len()` or `to_bytes().len()` respectively can be used instead"
+}
+
+declare_lint_pass!(StrlenOnCStrings => [STRLEN_ON_C_STRINGS]);
+
+impl LateLintPass<'tcx> for StrlenOnCStrings {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+        if in_macro(expr.span) {
+            return;
+        }
+
+        if_chain! {
+            if let hir::ExprKind::Call(func, [recv]) = expr.kind;
+            if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = func.kind;
+
+            if (&paths::LIBC_STRLEN).iter().map(|x| Symbol::intern(x)).eq(
+                path.segments.iter().map(|seg| seg.ident.name));
+            if let hir::ExprKind::MethodCall(path, _, args, _) = recv.kind;
+            if args.len() == 1;
+            if !args.iter().any(|e| e.span.from_expansion());
+            if path.ident.name == sym::as_ptr;
+            then {
+                let cstring = &args[0];
+                let ty = cx.typeck_results().expr_ty(cstring);
+                let val_name = snippet_with_macro_callsite(cx, cstring.span, "..");
+                let sugg = if is_type_diagnostic_item(cx, ty, sym::cstring_type){
+                    format!("{}.as_bytes().len()", val_name)
+                } else if is_type_ref_to_diagnostic_item(cx, ty, sym::CStr){
+                    format!("{}.to_bytes().len()", val_name)
+                } else {
+                    return;
+                };
+
+                span_lint_and_sugg(
+                    cx,
+                    STRLEN_ON_C_STRINGS,
+                    expr.span,
+                    "using `libc::strlen` on a `CString` or `CStr` value",
+                    "try this (you might also need to get rid of `unsafe` block in some cases):",
+                    sugg,
+                    Applicability::Unspecified // Sometimes unnecessary `unsafe` block
+                );
+            }
+        }
+    }
+}
index 512abde11a63433a827f797f95002b6489ac6a20..f2bffd553210b1d5d0c531543a60a7b02b286bd9 100644 (file)
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::{get_trait_def_id, paths, trait_ref_of_method};
+use clippy_utils::{binop_traits, trait_ref_of_method, BINOP_TRAITS, OP_ASSIGN_TRAITS};
 use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
@@ -26,7 +26,7 @@ declare_clippy_lint! {
     /// }
     /// ```
     pub SUSPICIOUS_ARITHMETIC_IMPL,
-    correctness,
+    suspicious,
     "suspicious use of operators in impl of arithmetic trait"
 }
 
@@ -47,7 +47,7 @@ declare_clippy_lint! {
     /// }
     /// ```
     pub SUSPICIOUS_OP_ASSIGN_IMPL,
-    correctness,
+    suspicious,
     "suspicious use of operators in impl of OpAssign trait"
 }
 
@@ -55,135 +55,48 @@ declare_lint_pass!(SuspiciousImpl => [SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_
 
 impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind {
-            match binop.node {
-                hir::BinOpKind::Eq
-                | hir::BinOpKind::Lt
-                | hir::BinOpKind::Le
-                | hir::BinOpKind::Ne
-                | hir::BinOpKind::Ge
-                | hir::BinOpKind::Gt => return,
-                _ => {},
-            }
+        if_chain! {
+            if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind;
+            if let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop.node);
+            if let Ok(binop_trait_id) = cx.tcx.lang_items().require(binop_trait_lang);
+            if let Ok(op_assign_trait_id) = cx.tcx.lang_items().require(op_assign_trait_lang);
 
             // Check for more than one binary operation in the implemented function
             // Linting when multiple operations are involved can result in false positives
             let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);
-            if_chain! {
-                if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get(parent_fn);
-                if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind;
-                then {
-                    let body = cx.tcx.hir().body(body_id);
-                    let mut visitor = BinaryExprVisitor { nb_binops: 0 };
-                    walk_expr(&mut visitor, &body.value);
-                    if visitor.nb_binops > 1 {
-                        return;
-                    }
-                }
-            }
-
-            if let Some(impl_trait) = check_binop(
-                cx,
-                expr,
-                binop.node,
-                &[
-                    "Add", "Sub", "Mul", "Div", "Rem", "BitAnd", "BitOr", "BitXor", "Shl", "Shr",
-                ],
-                &[
-                    hir::BinOpKind::Add,
-                    hir::BinOpKind::Sub,
-                    hir::BinOpKind::Mul,
-                    hir::BinOpKind::Div,
-                    hir::BinOpKind::Rem,
-                    hir::BinOpKind::BitAnd,
-                    hir::BinOpKind::BitOr,
-                    hir::BinOpKind::BitXor,
-                    hir::BinOpKind::Shl,
-                    hir::BinOpKind::Shr,
-                ],
-            ) {
-                span_lint(
-                    cx,
-                    SUSPICIOUS_ARITHMETIC_IMPL,
-                    binop.span,
-                    &format!("suspicious use of binary operator in `{}` impl", impl_trait),
-                );
-            }
-
-            if let Some(impl_trait) = check_binop(
-                cx,
-                expr,
-                binop.node,
-                &[
-                    "AddAssign",
-                    "SubAssign",
-                    "MulAssign",
-                    "DivAssign",
-                    "BitAndAssign",
-                    "BitOrAssign",
-                    "BitXorAssign",
-                    "RemAssign",
-                    "ShlAssign",
-                    "ShrAssign",
-                ],
-                &[
-                    hir::BinOpKind::Add,
-                    hir::BinOpKind::Sub,
-                    hir::BinOpKind::Mul,
-                    hir::BinOpKind::Div,
-                    hir::BinOpKind::BitAnd,
-                    hir::BinOpKind::BitOr,
-                    hir::BinOpKind::BitXor,
-                    hir::BinOpKind::Rem,
-                    hir::BinOpKind::Shl,
-                    hir::BinOpKind::Shr,
-                ],
-            ) {
+            if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get(parent_fn);
+            if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind;
+            let body = cx.tcx.hir().body(body_id);
+            let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);
+            if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
+            let trait_id = trait_ref.path.res.def_id();
+            if ![binop_trait_id, op_assign_trait_id].contains(&trait_id);
+            if let Some(&(_, lint)) = [
+                (&BINOP_TRAITS, SUSPICIOUS_ARITHMETIC_IMPL),
+                (&OP_ASSIGN_TRAITS, SUSPICIOUS_OP_ASSIGN_IMPL),
+            ]
+                .iter()
+                .find(|&(ts, _)| ts.iter().any(|&t| Ok(trait_id) == cx.tcx.lang_items().require(t)));
+            if count_binops(&body.value) == 1;
+            then {
                 span_lint(
                     cx,
-                    SUSPICIOUS_OP_ASSIGN_IMPL,
+                    lint,
                     binop.span,
-                    &format!("suspicious use of binary operator in `{}` impl", impl_trait),
+                    &format!("suspicious use of `{}` in `{}` impl", binop.node.as_str(), cx.tcx.item_name(trait_id)),
                 );
             }
         }
     }
 }
 
-fn check_binop(
-    cx: &LateContext<'_>,
-    expr: &hir::Expr<'_>,
-    binop: hir::BinOpKind,
-    traits: &[&'static str],
-    expected_ops: &[hir::BinOpKind],
-) -> Option<&'static str> {
-    let mut trait_ids = vec![];
-    let [krate, module] = paths::OPS_MODULE;
-
-    for &t in traits {
-        let path = [krate, module, t];
-        if let Some(trait_id) = get_trait_def_id(cx, &path) {
-            trait_ids.push(trait_id);
-        } else {
-            return None;
-        }
-    }
-
-    // Get the actually implemented trait
-    let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);
-
-    if_chain! {
-        if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
-        if let Some(idx) = trait_ids.iter().position(|&tid| tid == trait_ref.path.res.def_id());
-        if binop != expected_ops[idx];
-        then{
-            return Some(traits[idx])
-        }
-    }
-
-    None
+fn count_binops(expr: &hir::Expr<'_>) -> u32 {
+    let mut visitor = BinaryExprVisitor::default();
+    visitor.visit_expr(expr);
+    visitor.nb_binops
 }
 
+#[derive(Default)]
 struct BinaryExprVisitor {
     nb_binops: u32,
 }
index 70b9e8adef884e56cf34f215cd9d7e442c21455b..7d629b5455b62913f4b480ce67fed09e65c1c4f1 100644 (file)
@@ -3,6 +3,7 @@ mod box_vec;
 mod linked_list;
 mod option_option;
 mod rc_buffer;
+mod rc_mutex;
 mod redundant_allocation;
 mod type_complexity;
 mod utils;
@@ -177,8 +178,8 @@ declare_clippy_lint! {
 declare_clippy_lint! {
     /// **What it does:** Checks for use of redundant allocations anywhere in the code.
     ///
-    /// **Why is this bad?** Expressions such as `Rc<&T>`, `Rc<Rc<T>>`, `Rc<Box<T>>`, `Box<&T>`
-    /// add an unnecessary level of indirection.
+    /// **Why is this bad?** Expressions such as `Rc<&T>`, `Rc<Rc<T>>`, `Rc<Arc<T>>`, `Rc<Box<T>>`, Arc<&T>`, `Arc<Rc<T>>`,
+    /// `Arc<Arc<T>>`, `Arc<Box<T>>`, `Box<&T>`, `Box<Rc<T>>`, `Box<Arc<T>>`, `Box<Box<T>>`, add an unnecessary level of indirection.
     ///
     /// **Known problems:** None.
     ///
@@ -250,12 +251,41 @@ declare_clippy_lint! {
     "usage of very complex types that might be better factored into `type` definitions"
 }
 
+declare_clippy_lint! {
+    /// **What it does:** Checks for `Rc<Mutex<T>>`.
+    ///
+    /// **Why is this bad?** `Rc` is used in single thread and `Mutex` is used in multi thread.
+    /// Consider using `Rc<RefCell<T>>` in single thread or `Arc<Mutex<T>>` in multi thread.
+    ///
+    /// **Known problems:** Sometimes combining generic types can lead to the requirement that a
+    /// type use Rc in conjunction with Mutex. We must consider those cases false positives, but
+    /// alas they are quite hard to rule out. Luckily they are also rare.
+    ///
+    /// **Example:**
+    /// ```rust,ignore
+    /// use std::rc::Rc;
+    /// use std::sync::Mutex;
+    /// fn foo(interned: Rc<Mutex<i32>>) { ... }
+    /// ```
+    ///
+    /// Better:
+    ///
+    /// ```rust,ignore
+    /// use std::rc::Rc;
+    /// use std::cell::RefCell
+    /// fn foo(interned: Rc<RefCell<i32>>) { ... }
+    /// ```
+    pub RC_MUTEX,
+    restriction,
+    "usage of `Rc<Mutex<T>>`"
+}
+
 pub struct Types {
     vec_box_size_threshold: u64,
     type_complexity_threshold: u64,
 }
 
-impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, TYPE_COMPLEXITY]);
+impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, RC_MUTEX, TYPE_COMPLEXITY]);
 
 impl<'tcx> LateLintPass<'tcx> for Types {
     fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) {
@@ -375,6 +405,7 @@ impl Types {
                     triggered |= vec_box::check(cx, hir_ty, qpath, def_id, self.vec_box_size_threshold);
                     triggered |= option_option::check(cx, hir_ty, qpath, def_id);
                     triggered |= linked_list::check(cx, hir_ty, def_id);
+                    triggered |= rc_mutex::check(cx, hir_ty, qpath, def_id);
 
                     if triggered {
                         return;
diff --git a/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs b/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs
new file mode 100644 (file)
index 0000000..bd7a0ee
--- /dev/null
@@ -0,0 +1,27 @@
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::is_ty_param_diagnostic_item;
+use if_chain::if_chain;
+use rustc_hir::{self as hir, def_id::DefId, QPath};
+use rustc_lint::LateContext;
+use rustc_span::symbol::sym;
+
+use super::RC_MUTEX;
+
+pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
+    if_chain! {
+        if cx.tcx.is_diagnostic_item(sym::Rc, def_id) ;
+        if let Some(_) = is_ty_param_diagnostic_item(cx, qpath, sym!(mutex_type)) ;
+
+        then{
+            span_lint(
+                cx,
+                RC_MUTEX,
+                hir_ty.span,
+                "found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead",
+            );
+            return true;
+        }
+    }
+
+    false
+}
index c0c1f340583c1b53cb126407fe8ccb96c53aa9da..8e83dcbf704e0930fecd8384910e51acbc10fa9e 100644 (file)
@@ -1,5 +1,5 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::{get_qpath_generic_tys, is_ty_param_diagnostic_item, is_ty_param_lang_item};
 use rustc_errors::Applicability;
 use rustc_hir::{self as hir, def_id::DefId, LangItem, QPath, TyKind};
@@ -9,74 +9,99 @@ use rustc_span::symbol::sym;
 use super::{utils, REDUNDANT_ALLOCATION};
 
 pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
-    if Some(def_id) == cx.tcx.lang_items().owned_box() {
-        if let Some(span) = utils::match_borrows_parameter(cx, qpath) {
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_and_sugg(
-                cx,
-                REDUNDANT_ALLOCATION,
-                hir_ty.span,
-                "usage of `Box<&T>`",
-                "try",
-                snippet_with_applicability(cx, span, "..", &mut applicability).to_string(),
-                applicability,
-            );
-            return true;
-        }
+    let outer_sym = if Some(def_id) == cx.tcx.lang_items().owned_box() {
+        "Box"
+    } else if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
+        "Rc"
+    } else if cx.tcx.is_diagnostic_item(sym::Arc, def_id) {
+        "Arc"
+    } else {
+        return false;
+    };
+
+    if let Some(span) = utils::match_borrows_parameter(cx, qpath) {
+        let mut applicability = Applicability::MaybeIncorrect;
+        let generic_snippet = snippet_with_applicability(cx, span, "..", &mut applicability);
+        span_lint_and_then(
+            cx,
+            REDUNDANT_ALLOCATION,
+            hir_ty.span,
+            &format!("usage of `{}<{}>`", outer_sym, generic_snippet),
+            |diag| {
+                diag.span_suggestion(hir_ty.span, "try", format!("{}", generic_snippet), applicability);
+                diag.note(&format!(
+                    "`{generic}` is already a pointer, `{outer}<{generic}>` allocates a pointer on the heap",
+                    outer = outer_sym,
+                    generic = generic_snippet
+                ));
+            },
+        );
+        return true;
     }
 
-    if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
-        if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::Rc) {
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_and_sugg(
-                cx,
-                REDUNDANT_ALLOCATION,
-                hir_ty.span,
-                "usage of `Rc<Rc<T>>`",
-                "try",
-                snippet_with_applicability(cx, ty.span, "..", &mut applicability).to_string(),
-                applicability,
-            );
-            true
-        } else if let Some(ty) = is_ty_param_lang_item(cx, qpath, LangItem::OwnedBox) {
-            let qpath = match &ty.kind {
-                TyKind::Path(qpath) => qpath,
-                _ => return false,
-            };
-            let inner_span = match get_qpath_generic_tys(qpath).next() {
-                Some(ty) => ty.span,
-                None => return false,
-            };
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_and_sugg(
-                cx,
-                REDUNDANT_ALLOCATION,
-                hir_ty.span,
-                "usage of `Rc<Box<T>>`",
-                "try",
-                format!(
-                    "Rc<{}>",
-                    snippet_with_applicability(cx, inner_span, "..", &mut applicability)
-                ),
-                applicability,
-            );
-            true
-        } else {
-            utils::match_borrows_parameter(cx, qpath).map_or(false, |span| {
-                let mut applicability = Applicability::MachineApplicable;
-                span_lint_and_sugg(
-                    cx,
-                    REDUNDANT_ALLOCATION,
+    let (inner_sym, ty) = if let Some(ty) = is_ty_param_lang_item(cx, qpath, LangItem::OwnedBox) {
+        ("Box", ty)
+    } else if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::Rc) {
+        ("Rc", ty)
+    } else if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::Arc) {
+        ("Arc", ty)
+    } else {
+        return false;
+    };
+
+    let inner_qpath = match &ty.kind {
+        TyKind::Path(inner_qpath) => inner_qpath,
+        _ => return false,
+    };
+    let inner_span = match get_qpath_generic_tys(inner_qpath).next() {
+        Some(ty) => ty.span,
+        None => return false,
+    };
+    if inner_sym == outer_sym {
+        let mut applicability = Applicability::MaybeIncorrect;
+        let generic_snippet = snippet_with_applicability(cx, inner_span, "..", &mut applicability);
+        span_lint_and_then(
+            cx,
+            REDUNDANT_ALLOCATION,
+            hir_ty.span,
+            &format!("usage of `{}<{}<{}>>`", outer_sym, inner_sym, generic_snippet),
+            |diag| {
+                diag.span_suggestion(
                     hir_ty.span,
-                    "usage of `Rc<&T>`",
                     "try",
-                    snippet_with_applicability(cx, span, "..", &mut applicability).to_string(),
+                    format!("{}<{}>", outer_sym, generic_snippet),
                     applicability,
                 );
-                true
-            })
-        }
+                diag.note(&format!(
+                    "`{inner}<{generic}>` is already on the heap, `{outer}<{inner}<{generic}>>` makes an extra allocation",
+                    outer = outer_sym,
+                    inner = inner_sym,
+                    generic = generic_snippet
+                ));
+            },
+        );
     } else {
-        false
+        let generic_snippet = snippet(cx, inner_span, "..");
+        span_lint_and_then(
+            cx,
+            REDUNDANT_ALLOCATION,
+            hir_ty.span,
+            &format!("usage of `{}<{}<{}>>`", outer_sym, inner_sym, generic_snippet),
+            |diag| {
+                diag.note(&format!(
+                    "`{inner}<{generic}>` is already on the heap, `{outer}<{inner}<{generic}>>` makes an extra allocation",
+                    outer = outer_sym,
+                    inner = inner_sym,
+                    generic = generic_snippet
+                ));
+                diag.help(&format!(
+                    "consider using just `{outer}<{generic}>` or `{inner}<{generic}>`",
+                    outer = outer_sym,
+                    inner = inner_sym,
+                    generic = generic_snippet
+                ));
+            },
+        );
     }
+    true
 }
index 45291a120ed59b51df71bb3f28fc57ab0438d8b7..2f0a61898ba75347c7a702004c54826e6ca9e045 100644 (file)
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_allowed;
+use clippy_utils::is_lint_allowed;
 use clippy_utils::source::snippet;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
@@ -114,7 +114,7 @@ fn check_str(cx: &LateContext<'_>, span: Span, id: HirId) {
             span,
             "literal non-ASCII character detected",
             "consider replacing the string with",
-            if is_allowed(cx, UNICODE_NOT_NFC, id) {
+            if is_lint_allowed(cx, UNICODE_NOT_NFC, id) {
                 escape(string.chars())
             } else {
                 escape(string.nfc())
@@ -122,7 +122,7 @@ fn check_str(cx: &LateContext<'_>, span: Span, id: HirId) {
             Applicability::MachineApplicable,
         );
     }
-    if is_allowed(cx, NON_ASCII_LITERAL, id) && string.chars().zip(string.nfc()).any(|(a, b)| a != b) {
+    if is_lint_allowed(cx, NON_ASCII_LITERAL, id) && string.chars().zip(string.nfc()).any(|(a, b)| a != b) {
         span_lint_and_sugg(
             cx,
             UNICODE_NOT_NFC,
index 0454214651683afbfae4ede5b4afdcbeedf0f0aa..85257f3113cb774adc43f326707c0182b1eac616 100644 (file)
@@ -8,12 +8,7 @@ use super::UNIT_CMP;
 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 1b3c457b01adb64650f9965d352eabedee6d54d9..07a4e294049791f7256e41810c31ed22088a3426 100644 (file)
@@ -1,6 +1,6 @@
 #![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
 
-use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_pat, eq_path, eq_maybe_qself};
+use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_maybe_qself, eq_pat, eq_path};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::{meets_msrv, msrvs, over};
 use rustc_ast::mut_visit::*;
@@ -277,7 +277,8 @@ fn transform_with_focus_on_idx(alternatives: &mut Vec<P<Pat>>, focus_idx: usize)
             ps1, start, alternatives,
             |k, ps1, idx| matches!(
                 k,
-                TupleStruct(qself2, path2, ps2) if eq_maybe_qself(qself1, qself2) && eq_path(path1, path2) && eq_pre_post(ps1, ps2, idx)
+                TupleStruct(qself2, path2, ps2)
+                    if eq_maybe_qself(qself1, qself2) && eq_path(path1, path2) && eq_pre_post(ps1, ps2, idx)
             ),
             |k| always_pat!(k, TupleStruct(_, _, ps) => ps),
         ),
index e14945651f5010551820308a272693951cc992ab..ab0cdf75ffe0a02feceb516f65091d1f0e0e93ef 100644 (file)
@@ -24,6 +24,10 @@ declare_clippy_lint! {
     ///     ()
     /// }
     /// ```
+    /// is equivalent to
+    /// ```rust
+    /// fn return_unit() {}
+    /// ```
     pub UNUSED_UNIT,
     style,
     "needless unit expression"
index 254b104bdefb10ef088732d2fbf20c3f4ecefeb8..71117e967e31941af9da90b9239e05edf794c4bf 100644 (file)
@@ -1,23 +1,22 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::same_type_and_consts;
 use clippy_utils::{in_macro, meets_msrv, msrvs};
 use if_chain::if_chain;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir::{
     self as hir,
-    def::{self, DefKind},
+    def::{CtorOf, DefKind, Res},
     def_id::LocalDefId,
     intravisit::{walk_ty, NestedVisitorMap, Visitor},
-    Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Node, Path, PathSegment,
-    QPath, TyKind,
+    Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Path, QPath, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::map::Map;
-use rustc_middle::ty::{AssocKind, Ty};
+use rustc_middle::ty::AssocKind;
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::{BytePos, Span};
+use rustc_span::Span;
 use rustc_typeck::hir_ty_to_ty;
 
 declare_clippy_lint! {
@@ -75,10 +74,9 @@ impl UseSelf {
 #[derive(Debug)]
 enum StackItem {
     Check {
-        hir_id: HirId,
-        impl_trait_ref_def_id: Option<LocalDefId>,
-        types_to_skip: Vec<HirId>,
-        types_to_lint: Vec<HirId>,
+        impl_id: LocalDefId,
+        in_body: u32,
+        types_to_skip: FxHashSet<HirId>,
     },
     NoCheck,
 }
@@ -88,60 +86,38 @@ impl_lint_pass!(UseSelf => [USE_SELF]);
 const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element";
 
 impl<'tcx> LateLintPass<'tcx> for UseSelf {
-    fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+    fn check_item(&mut self, _cx: &LateContext<'_>, item: &Item<'_>) {
+        if matches!(item.kind, ItemKind::OpaqueTy(_)) {
+            // skip over `ItemKind::OpaqueTy` in order to lint `foo() -> impl <..>`
+            return;
+        }
         // We push the self types of `impl`s on a stack here. Only the top type on the stack is
         // relevant for linting, since this is the self type of the `impl` we're currently in. To
         // avoid linting on nested items, we push `StackItem::NoCheck` on the stack to signal, that
         // we're in an `impl` or nested item, that we don't want to lint
-        //
-        // NB: If you push something on the stack in this method, remember to also pop it in the
-        // `check_item_post` method.
-        match &item.kind {
-            ItemKind::Impl(Impl {
-                self_ty: hir_self_ty,
-                of_trait,
-                ..
-            }) => {
-                let should_check = if let TyKind::Path(QPath::Resolved(_, item_path)) = hir_self_ty.kind {
-                    let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args;
-                    parameters.as_ref().map_or(true, |params| {
-                        !params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
-                    })
-                } else {
-                    false
-                };
-                let impl_trait_ref_def_id = of_trait.as_ref().map(|_| cx.tcx.hir().local_def_id(item.hir_id()));
-                if should_check {
-                    self.stack.push(StackItem::Check {
-                        hir_id: hir_self_ty.hir_id,
-                        impl_trait_ref_def_id,
-                        types_to_lint: Vec::new(),
-                        types_to_skip: Vec::new(),
-                    });
-                } else {
-                    self.stack.push(StackItem::NoCheck);
+        let stack_item = if_chain! {
+            if let ItemKind::Impl(Impl { self_ty, .. }) = item.kind;
+            if let TyKind::Path(QPath::Resolved(_, item_path)) = self_ty.kind;
+            let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args;
+            if parameters.as_ref().map_or(true, |params| {
+                !params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
+            });
+            then {
+                StackItem::Check {
+                    impl_id: item.def_id,
+                    in_body: 0,
+                    types_to_skip: std::iter::once(self_ty.hir_id).collect(),
                 }
-            },
-            ItemKind::Static(..)
-            | ItemKind::Const(..)
-            | ItemKind::Fn(..)
-            | ItemKind::Enum(..)
-            | ItemKind::Struct(..)
-            | ItemKind::Union(..)
-            | ItemKind::Trait(..) => {
-                self.stack.push(StackItem::NoCheck);
-            },
-            _ => (),
-        }
+            } else {
+                StackItem::NoCheck
+            }
+        };
+        self.stack.push(stack_item);
     }
 
     fn check_item_post(&mut self, _: &LateContext<'_>, item: &Item<'_>) {
-        use ItemKind::{Const, Enum, Fn, Impl, Static, Struct, Trait, Union};
-        match item.kind {
-            Impl { .. } | Static(..) | Const(..) | Fn(..) | Enum(..) | Struct(..) | Union(..) | Trait(..) => {
-                self.stack.pop();
-            },
-            _ => (),
+        if !matches!(item.kind, ItemKind::OpaqueTy(_)) {
+            self.stack.pop();
         }
     }
 
@@ -151,11 +127,11 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
         if_chain! {
             if let ImplItemKind::Fn(FnSig { decl, .. }, ..) = impl_item.kind;
             if let Some(&mut StackItem::Check {
-                impl_trait_ref_def_id: Some(def_id),
+                impl_id,
                 ref mut types_to_skip,
                 ..
             }) = self.stack.last_mut();
-            if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(def_id);
+            if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_id);
             then {
                 // `self_ty` is the semantic self type of `impl <trait> for <type>`. This cannot be
                 // `Self`.
@@ -203,142 +179,76 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
         }
     }
 
-    fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) {
+    fn check_body(&mut self, _: &LateContext<'_>, _: &hir::Body<'_>) {
         // `hir_ty_to_ty` cannot be called in `Body`s or it will panic (sometimes). But in bodies
         // we can use `cx.typeck_results.node_type(..)` to get the `ty::Ty` from a `hir::Ty`.
         // However the `node_type()` method can *only* be called in bodies.
-        //
-        // This method implementation determines which types should get linted in a `Body` and
-        // which shouldn't, with a visitor. We could directly lint in the visitor, but then we
-        // could only allow this lint on item scope. And we would have to check if those types are
-        // already dealt with in `check_ty` anyway.
-        if let Some(StackItem::Check {
-            hir_id,
-            types_to_lint,
-            types_to_skip,
-            ..
-        }) = self.stack.last_mut()
-        {
-            let self_ty = ty_from_hir_id(cx, *hir_id);
-
-            let mut visitor = LintTyCollector {
-                cx,
-                self_ty,
-                types_to_lint: vec![],
-                types_to_skip: vec![],
-            };
-            visitor.visit_expr(&body.value);
-            types_to_lint.extend(visitor.types_to_lint);
-            types_to_skip.extend(visitor.types_to_skip);
+        if let Some(&mut StackItem::Check { ref mut in_body, .. }) = self.stack.last_mut() {
+            *in_body = in_body.saturating_add(1);
         }
     }
 
-    fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
-        if in_macro(hir_ty.span)
-            || in_impl(cx, hir_ty)
-            || !meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS)
-        {
-            return;
+    fn check_body_post(&mut self, _: &LateContext<'_>, _: &hir::Body<'_>) {
+        if let Some(&mut StackItem::Check { ref mut in_body, .. }) = self.stack.last_mut() {
+            *in_body = in_body.saturating_sub(1);
         }
+    }
 
-        let lint_dependend_on_expr_kind = if let Some(StackItem::Check {
-            hir_id,
-            types_to_lint,
-            types_to_skip,
-            ..
-        }) = self.stack.last()
-        {
-            if types_to_skip.contains(&hir_ty.hir_id) {
-                false
-            } else if types_to_lint.contains(&hir_ty.hir_id) {
-                true
+    fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
+        if_chain! {
+            if !in_macro(hir_ty.span);
+            if meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS);
+            if let Some(&StackItem::Check {
+                impl_id,
+                in_body,
+                ref types_to_skip,
+            }) = self.stack.last();
+            if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind;
+            if !matches!(path.res, Res::SelfTy(..) | Res::Def(DefKind::TyParam, _));
+            if !types_to_skip.contains(&hir_ty.hir_id);
+            let ty = if in_body > 0 {
+                cx.typeck_results().node_type(hir_ty.hir_id)
             } else {
-                let self_ty = ty_from_hir_id(cx, *hir_id);
-                should_lint_ty(hir_ty, hir_ty_to_ty(cx.tcx, hir_ty), self_ty)
-            }
-        } else {
-            false
-        };
-
-        if lint_dependend_on_expr_kind {
-            // FIXME: this span manipulation should not be necessary
-            // @flip1995 found an ast lowering issue in
-            // https://github.com/rust-lang/rust/blob/master/src/librustc_ast_lowering/path.rs#l142-l162
+                hir_ty_to_ty(cx.tcx, hir_ty)
+            };
+            if same_type_and_consts(ty, cx.tcx.type_of(impl_id));
             let hir = cx.tcx.hir();
             let id = hir.get_parent_node(hir_ty.hir_id);
-
-            if !hir.opt_span(id).map_or(false, in_macro) {
-                match hir.find(id) {
-                    Some(Node::Expr(Expr {
-                        kind: ExprKind::Path(QPath::TypeRelative(_, segment)),
-                        ..
-                    })) => span_lint_until_last_segment(cx, hir_ty.span, segment),
-                    _ => span_lint(cx, hir_ty.span),
-                }
+            if !hir.opt_span(id).map_or(false, in_macro);
+            then {
+                span_lint(cx, hir_ty.span);
             }
         }
     }
 
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        fn expr_ty_matches(cx: &LateContext<'_>, expr: &Expr<'_>, self_ty: Ty<'_>) -> bool {
-            let def_id = expr.hir_id.owner;
-            if cx.tcx.has_typeck_results(def_id) {
-                cx.tcx.typeck(def_id).expr_ty_opt(expr) == Some(self_ty)
-            } else {
-                false
-            }
-        }
-
-        if in_macro(expr.span) || !meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS) {
-            return;
+        if_chain! {
+            if !in_macro(expr.span);
+            if meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS);
+            if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last();
+            if cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id);
+            then {} else { return; }
         }
-
-        if let Some(StackItem::Check { hir_id, .. }) = self.stack.last() {
-            let self_ty = ty_from_hir_id(cx, *hir_id);
-
-            match &expr.kind {
-                ExprKind::Struct(QPath::Resolved(_, path), ..) => {
-                    if expr_ty_matches(cx, expr, self_ty) {
-                        match path.res {
-                            def::Res::SelfTy(..) => (),
-                            def::Res::Def(DefKind::Variant, _) => span_lint_on_path_until_last_segment(cx, path),
-                            _ => {
-                                span_lint(cx, path.span);
-                            },
-                        }
-                    }
-                },
-                // tuple struct instantiation (`Foo(arg)` or `Enum::Foo(arg)`)
-                ExprKind::Call(fun, _) => {
-                    if let Expr {
-                        kind: ExprKind::Path(ref qpath),
-                        ..
-                    } = fun
-                    {
-                        if expr_ty_matches(cx, expr, self_ty) {
-                            let res = cx.qpath_res(qpath, fun.hir_id);
-
-                            if let def::Res::Def(DefKind::Ctor(ctor_of, _), ..) = res {
-                                match ctor_of {
-                                    def::CtorOf::Variant => {
-                                        span_lint_on_qpath_resolved(cx, qpath, true);
-                                    },
-                                    def::CtorOf::Struct => {
-                                        span_lint_on_qpath_resolved(cx, qpath, false);
-                                    },
-                                }
-                            }
+        match expr.kind {
+            ExprKind::Struct(QPath::Resolved(_, path), ..) => match path.res {
+                Res::SelfTy(..) => (),
+                Res::Def(DefKind::Variant, _) => lint_path_to_variant(cx, path),
+                _ => span_lint(cx, path.span),
+            },
+            // tuple struct instantiation (`Foo(arg)` or `Enum::Foo(arg)`)
+            ExprKind::Call(fun, _) => {
+                if let ExprKind::Path(QPath::Resolved(_, path)) = fun.kind {
+                    if let Res::Def(DefKind::Ctor(ctor_of, _), ..) = path.res {
+                        match ctor_of {
+                            CtorOf::Variant => lint_path_to_variant(cx, path),
+                            CtorOf::Struct => span_lint(cx, path.span),
                         }
                     }
-                },
-                // unit enum variants (`Enum::A`)
-                ExprKind::Path(qpath) => {
-                    if expr_ty_matches(cx, expr, self_ty) {
-                        span_lint_on_qpath_resolved(cx, qpath, true);
-                    }
-                },
-                _ => (),
-            }
+                }
+            },
+            // unit enum variants (`Enum::A`)
+            ExprKind::Path(QPath::Resolved(_, path)) => lint_path_to_variant(cx, path),
+            _ => (),
         }
     }
 
@@ -364,35 +274,6 @@ impl<'tcx> Visitor<'tcx> for SkipTyCollector {
     }
 }
 
-struct LintTyCollector<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-    self_ty: Ty<'tcx>,
-    types_to_lint: Vec<HirId>,
-    types_to_skip: Vec<HirId>,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for LintTyCollector<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
-    fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'_>) {
-        if_chain! {
-            if let Some(ty) = self.cx.typeck_results().node_type_opt(hir_ty.hir_id);
-            if should_lint_ty(hir_ty, ty, self.self_ty);
-            then {
-                self.types_to_lint.push(hir_ty.hir_id);
-            } else {
-                self.types_to_skip.push(hir_ty.hir_id);
-            }
-        }
-
-        walk_ty(self, hir_ty);
-    }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
-}
-
 fn span_lint(cx: &LateContext<'_>, span: Span) {
     span_lint_and_sugg(
         cx,
@@ -405,66 +286,11 @@ fn span_lint(cx: &LateContext<'_>, span: Span) {
     );
 }
 
-#[allow(clippy::cast_possible_truncation)]
-fn span_lint_until_last_segment(cx: &LateContext<'_>, span: Span, segment: &PathSegment<'_>) {
-    let sp = span.with_hi(segment.ident.span.lo());
-    // remove the trailing ::
-    let span_without_last_segment = match snippet_opt(cx, sp) {
-        Some(snippet) => match snippet.rfind("::") {
-            Some(bidx) => sp.with_hi(sp.lo() + BytePos(bidx as u32)),
-            None => sp,
-        },
-        None => sp,
-    };
-    span_lint(cx, span_without_last_segment);
-}
-
-fn span_lint_on_path_until_last_segment(cx: &LateContext<'_>, path: &Path<'_>) {
-    if path.segments.len() > 1 {
-        span_lint_until_last_segment(cx, path.span, path.segments.last().unwrap());
-    }
-}
-
-fn span_lint_on_qpath_resolved(cx: &LateContext<'_>, qpath: &QPath<'_>, until_last_segment: bool) {
-    if let QPath::Resolved(_, path) = qpath {
-        if until_last_segment {
-            span_lint_on_path_until_last_segment(cx, path);
-        } else {
-            span_lint(cx, path.span);
-        }
-    }
-}
-
-fn ty_from_hir_id<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Ty<'tcx> {
-    if let Some(Node::Ty(hir_ty)) = cx.tcx.hir().find(hir_id) {
-        hir_ty_to_ty(cx.tcx, hir_ty)
-    } else {
-        unreachable!("This function should only be called with `HirId`s that are for sure `Node::Ty`")
-    }
-}
-
-fn in_impl(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> bool {
-    let map = cx.tcx.hir();
-    let parent = map.get_parent_node(hir_ty.hir_id);
-    if_chain! {
-        if let Some(Node::Item(item)) = map.find(parent);
-        if let ItemKind::Impl { .. } = item.kind;
-        then {
-            true
-        } else {
-            false
-        }
-    }
-}
-
-fn should_lint_ty(hir_ty: &hir::Ty<'_>, ty: Ty<'_>, self_ty: Ty<'_>) -> bool {
-    if_chain! {
-        if same_type_and_consts(ty, self_ty);
-        if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind;
-        then {
-            !matches!(path.res, def::Res::SelfTy(..))
-        } else {
-            false
-        }
+fn lint_path_to_variant(cx: &LateContext<'_>, path: &Path<'_>) {
+    if let [.., self_seg, _variant] = path.segments {
+        let span = path
+            .span
+            .with_hi(self_seg.args().span_ext().unwrap_or(self_seg.ident.span).hi());
+        span_lint(cx, span);
     }
 }
index 2be99fb761b18be18a119e8cfc48a8e1a4ca2831..c97f7e1626e76291df3ecea23dfd579116950dc0 100644 (file)
@@ -104,7 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                     }
                 }
                 if_chain! {
-                    if match_trait_method(cx, e, &paths::TRY_INTO_TRAIT) && &*name.ident.as_str() == "try_into";
+                    if match_trait_method(cx, e, &paths::TRY_INTO_TRAIT) && name.ident.name == sym::try_into;
                     let a = cx.typeck_results().expr_ty(e);
                     let b = cx.typeck_results().expr_ty(&args[0]);
                     if is_type_diagnostic_item(cx, a, sym::result_type);
index 0e33ae740d946cd00e6c2903d56094a53e9bb441..44d3d4563428d4f4de8a937a1e85263d70a4b558 100644 (file)
@@ -8,6 +8,13 @@ use std::error::Error;
 use std::path::{Path, PathBuf};
 use std::{env, fmt, fs, io};
 
+/// Holds information used by `MISSING_ENFORCED_IMPORT_RENAMES` lint.
+#[derive(Clone, Debug, Deserialize)]
+pub struct Rename {
+    pub path: String,
+    pub rename: String,
+}
+
 /// Conf with parse errors
 #[derive(Default)]
 pub struct TryConf {
@@ -24,6 +31,9 @@ impl TryConf {
     }
 }
 
+/// Note that the configuration parsing currently doesn't support documentation that will
+/// that spans over several lines. This will be possible with the new implementation
+/// See (rust-clippy#7172)
 macro_rules! define_Conf {
     ($(
         #[doc = $doc:literal]
@@ -149,7 +159,7 @@ define_Conf! {
         "WebGL",
         "TensorFlow",
         "TrueType",
-        "iOS", "macOS",
+        "iOS", "macOS", "FreeBSD",
         "TeX", "LaTeX", "BibTeX", "BibLaTeX",
         "MinGW",
         "CamelCase",
@@ -182,20 +192,28 @@ define_Conf! {
     (vec_box_size_threshold: u64 = 4096),
     /// Lint: TYPE_REPETITION_IN_BOUNDS. The maximum number of bounds a trait can have to be linted
     (max_trait_bounds: u64 = 3),
-    /// Lint: STRUCT_EXCESSIVE_BOOLS. The maximum number of bools a struct can have
+    /// Lint: STRUCT_EXCESSIVE_BOOLS. The maximum number of bool fields a struct can have
     (max_struct_bools: u64 = 3),
-    /// Lint: FN_PARAMS_EXCESSIVE_BOOLS. The maximum number of bools function parameters can have
+    /// Lint: FN_PARAMS_EXCESSIVE_BOOLS. The maximum number of bool parameters a function can have
     (max_fn_params_bools: u64 = 3),
     /// Lint: WILDCARD_IMPORTS. Whether to allow certain wildcard imports (prelude, super in tests).
     (warn_on_all_wildcard_imports: bool = false),
     /// Lint: DISALLOWED_METHOD. The list of disallowed methods, written as fully qualified paths.
     (disallowed_methods: Vec<String> = Vec::new()),
+    /// Lint: DISALLOWED_TYPE. The list of disallowed types, written as fully qualified paths.
+    (disallowed_types: Vec<String> = Vec::new()),
     /// Lint: UNREADABLE_LITERAL. Should the fraction of a decimal be linted to include separators.
     (unreadable_literal_lint_fractions: bool = true),
     /// Lint: UPPER_CASE_ACRONYMS. Enables verbose mode. Triggers if there is more than one uppercase char next to each other
     (upper_case_acronyms_aggressive: bool = false),
     /// Lint: _CARGO_COMMON_METADATA. For internal testing only, ignores the current `publish` settings in the Cargo manifest.
     (cargo_ignore_publish: bool = false),
+    /// Lint: NONSTANDARD_MACRO_BRACES. Enforce the named macros always use the braces specified. <br> A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro is could be used with a full path two `MacroMatcher`s have to be added one with the full path `crate_name::macro_name` and one with just the macro name.
+    (standard_macro_braces: Vec<crate::nonstandard_macro_braces::MacroMatcher> = Vec::new()),
+    /// Lint: MISSING_ENFORCED_IMPORT_RENAMES. The list of imports to always rename, a fully qualified path followed by the rename.
+    (enforced_import_renames: Vec<crate::utils::conf::Rename> = Vec::new()),
+    /// Lint: RESTRICTED_SCRIPTS. The list of unicode scripts allowed to be used in the scope.
+    (allowed_scripts: Vec<String> = vec!["Latin".to_string()]),
 }
 
 /// Search for the configuration file.
index b1523e032af29a05906a64548e3c42491961a3a4..668807f499f3ffde3a121cc87b1a92dc8f0a6a49 100644 (file)
@@ -3,8 +3,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sug
 use clippy_utils::source::snippet;
 use clippy_utils::ty::match_type;
 use clippy_utils::{
-    is_else_clause, is_expn_of, is_expr_path_def_path, match_def_path, method_calls, path_to_res, paths, run_lints,
-    SpanlessEq,
+    is_else_clause, is_expn_of, is_expr_path_def_path, is_lint_allowed, match_def_path, method_calls, path_to_res,
+    paths, SpanlessEq,
 };
 use if_chain::if_chain;
 use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, ModKind, NodeId};
@@ -353,7 +353,7 @@ impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS]);
 
 impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if !run_lints(cx, &[DEFAULT_LINT], item.hir_id()) {
+        if is_lint_allowed(cx, DEFAULT_LINT, item.hir_id()) {
             return;
         }
 
@@ -411,7 +411,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
     }
 
     fn check_crate_post(&mut self, cx: &LateContext<'tcx>, _: &'tcx Crate<'_>) {
-        if !run_lints(cx, &[LINT_WITHOUT_LINT_PASS], CRATE_HIR_ID) {
+        if is_lint_allowed(cx, LINT_WITHOUT_LINT_PASS, CRATE_HIR_ID) {
             return;
         }
 
@@ -497,7 +497,7 @@ impl_lint_pass!(CompilerLintFunctions => [COMPILER_LINT_FUNCTIONS]);
 
 impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if !run_lints(cx, &[COMPILER_LINT_FUNCTIONS], expr.hir_id) {
+        if is_lint_allowed(cx, COMPILER_LINT_FUNCTIONS, expr.hir_id) {
             return;
         }
 
@@ -526,7 +526,7 @@ declare_lint_pass!(OuterExpnDataPass => [OUTER_EXPN_EXPN_DATA]);
 
 impl<'tcx> LateLintPass<'tcx> for OuterExpnDataPass {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        if !run_lints(cx, &[OUTER_EXPN_EXPN_DATA], expr.hir_id) {
+        if is_lint_allowed(cx, OUTER_EXPN_EXPN_DATA, expr.hir_id) {
             return;
         }
 
@@ -576,7 +576,7 @@ declare_lint_pass!(CollapsibleCalls => [COLLAPSIBLE_SPAN_LINT_CALLS]);
 
 impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        if !run_lints(cx, &[COLLAPSIBLE_SPAN_LINT_CALLS], expr.hir_id) {
+        if is_lint_allowed(cx, COLLAPSIBLE_SPAN_LINT_CALLS, expr.hir_id) {
             return;
         }
 
@@ -757,7 +757,7 @@ declare_lint_pass!(MatchTypeOnDiagItem => [MATCH_TYPE_ON_DIAGNOSTIC_ITEM]);
 
 impl<'tcx> LateLintPass<'tcx> for MatchTypeOnDiagItem {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        if !run_lints(cx, &[MATCH_TYPE_ON_DIAGNOSTIC_ITEM], expr.hir_id) {
+        if is_lint_allowed(cx, MATCH_TYPE_ON_DIAGNOSTIC_ITEM, expr.hir_id) {
             return;
         }
 
index 46af03663b86be540a341d0a00c3111a3b6d2efc..3eccc89cdeb808f813a32177d5af76f6819c0fed 100644 (file)
@@ -9,6 +9,7 @@
 //! a simple mistake)
 
 use if_chain::if_chain;
+use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{
     self as hir, def::DefKind, intravisit, intravisit::Visitor, ExprKind, Item, ItemKind, Mutability, QPath,
@@ -46,8 +47,9 @@ const DEPRECATED_LINT_GROUP_STR: &str = "deprecated";
 const DEPRECATED_LINT_LEVEL: &str = "none";
 /// This array holds Clippy's lint groups with their corresponding default lint level. The
 /// lint level for deprecated lints is set in `DEPRECATED_LINT_LEVEL`.
-const DEFAULT_LINT_LEVELS: [(&str, &str); 8] = [
+const DEFAULT_LINT_LEVELS: &[(&str, &str)] = &[
     ("correctness", "deny"),
+    ("suspicious", "warn"),
     ("restriction", "allow"),
     ("style", "warn"),
     ("pedantic", "allow"),
@@ -485,16 +487,32 @@ fn extract_attr_docs_or_lint(cx: &LateContext<'_>, item: &Item<'_>) -> Option<St
 ///
 /// Would result in `Hello world!\n=^.^=\n`
 fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
-    cx.tcx
-        .hir()
-        .attrs(item.hir_id())
-        .iter()
-        .filter_map(|x| x.doc_str().map(|sym| sym.as_str().to_string()))
-        .reduce(|mut acc, sym| {
-            acc.push_str(&sym);
-            acc.push('\n');
-            acc
-        })
+    let attrs = cx.tcx.hir().attrs(item.hir_id());
+    let mut lines = attrs.iter().filter_map(ast::Attribute::doc_str);
+    let mut docs = String::from(&*lines.next()?.as_str());
+    let mut in_code_block = false;
+    for line in lines {
+        docs.push('\n');
+        let line = line.as_str();
+        let line = &*line;
+        if let Some(info) = line.trim_start().strip_prefix("```") {
+            in_code_block = !in_code_block;
+            if in_code_block {
+                let lang = info
+                    .trim()
+                    .split(',')
+                    // remove rustdoc directives
+                    .find(|&s| !matches!(s, "" | "ignore" | "no_run" | "should_panic"))
+                    // if no language is present, fill in "rust"
+                    .unwrap_or("rust");
+                docs.push_str("```");
+                docs.push_str(lang);
+                continue;
+            }
+        }
+        docs.push_str(line);
+    }
+    Some(docs)
 }
 
 fn get_lint_group_and_level_or_lint(
@@ -502,7 +520,9 @@ fn get_lint_group_and_level_or_lint(
     lint_name: &str,
     item: &'hir Item<'_>,
 ) -> Option<(String, &'static str)> {
-    let result = cx.lint_store.check_lint_name(lint_name, Some(sym::clippy));
+    let result = cx
+        .lint_store
+        .check_lint_name(cx.sess(), lint_name, Some(sym::clippy), &[]);
     if let CheckLintNameResult::Tool(Ok(lint_lst)) = result {
         if let Some(group) = get_lint_group(cx, lint_lst[0]) {
             if EXCLUDED_LINT_GROUPS.contains(&group.as_str()) {
index 60c3489a449b6796714a416120985ec2e8a7f33d..1ca1117a41ea5fccef9b7eb067b6a46f3856e81e 100644 (file)
@@ -1,5 +1,4 @@
-use clippy_utils::diagnostics::span_lint;
-use clippy_utils::run_lints;
+use clippy_utils::{diagnostics::span_lint, is_lint_allowed};
 use rustc_hir::{hir_id::CRATE_HIR_ID, Crate};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -31,7 +30,7 @@ declare_lint_pass!(WildcardDependencies => [WILDCARD_DEPENDENCIES]);
 
 impl LateLintPass<'_> for WildcardDependencies {
     fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
-        if !run_lints(cx, &[WILDCARD_DEPENDENCIES], CRATE_HIR_ID) {
+        if is_lint_allowed(cx, WILDCARD_DEPENDENCIES, CRATE_HIR_ID) {
             return;
         }
 
index 51c1117d20641f92c2161cc1f87b7b7a6a8934fb..520586b3a1f426e093a18dc1a4dafd10739c7e3f 100644 (file)
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::in_macro;
 use clippy_utils::source::{snippet, snippet_with_applicability};
+use clippy_utils::{in_macro, is_test_module_or_function};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{
@@ -106,7 +106,7 @@ impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]);
 
 impl LateLintPass<'_> for WildcardImports {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
-        if is_test_module_or_function(item) {
+        if is_test_module_or_function(cx.tcx, item) {
             self.test_modules_deep = self.test_modules_deep.saturating_add(1);
         }
         if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() {
@@ -183,8 +183,8 @@ impl LateLintPass<'_> for WildcardImports {
         }
     }
 
-    fn check_item_post(&mut self, _: &LateContext<'_>, item: &Item<'_>) {
-        if is_test_module_or_function(item) {
+    fn check_item_post(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+        if is_test_module_or_function(cx.tcx, item) {
             self.test_modules_deep = self.test_modules_deep.saturating_sub(1);
         }
     }
@@ -208,7 +208,3 @@ fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool {
 fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool {
     segments.len() == 1 && segments[0].ident.name == kw::Super
 }
-
-fn is_test_module_or_function(item: &Item<'_>) -> bool {
-    matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test")
-}
index f93f0047f514f5100536a77500a8a1082c48356b..053bbc9aea67433ddf6c83d1cecf141a319b946c 100644 (file)
@@ -4,7 +4,7 @@ use clippy_utils::ty::{is_normalizable, is_type_diagnostic_item, match_type};
 use if_chain::if_chain;
 use rustc_hir::{self as hir, HirId, ItemKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Adt, Ty};
+use rustc_middle::ty::{Adt, Ty, TypeFoldable};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
 use rustc_target::abi::LayoutOf as _;
@@ -52,6 +52,9 @@ impl LateLintPass<'_> for ZeroSizedMapValues {
             if is_type_diagnostic_item(cx, ty, sym::hashmap_type) || match_type(cx, ty, &paths::BTREEMAP);
             if let Adt(_, substs) = ty.kind();
             let ty = substs.type_at(1);
+            // Fixes https://github.com/rust-lang/rust-clippy/issues/7447 because of
+            // https://github.com/rust-lang/rust/blob/master/compiler/rustc_middle/src/ty/sty.rs#L968
+            if !ty.has_escaping_bound_vars();
             // Do this to prevent `layout_of` crashing, being unable to fully normalize `ty`.
             if is_normalizable(cx, cx.param_env, ty);
             if let Ok(layout) = cx.layout_of(ty);
index 93ed3b1840068416459a731f682cde21b01472a0..6ede9011208305f5905f25435744c1bf8e735ce2 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_utils"
-version = "0.1.54"
+version = "0.1.55"
 authors = ["The Rust Clippy Developers"]
 edition = "2018"
 publish = false
index e6d84bc7560ba9cc9ae8d2d76c633d938d896a77..30c2260d15cacdeb05d30416ff5d0c6276c2ecb2 100644 (file)
@@ -47,9 +47,14 @@ pub fn eq_pat(l: &Pat, r: &Pat) -> bool {
         | (Ref(l, Mutability::Mut), Ref(r, Mutability::Mut)) => eq_pat(l, r),
         (Tuple(l), Tuple(r)) | (Slice(l), Slice(r)) => over(l, r, |l, r| eq_pat(l, r)),
         (Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp),
-        (TupleStruct(lqself, lp, lfs), TupleStruct(rqself, rp, rfs)) => eq_maybe_qself(lqself, rqself) && eq_path(lp, rp) && over(lfs, rfs, |l, r| eq_pat(l, r)),
+        (TupleStruct(lqself, lp, lfs), TupleStruct(rqself, rp, rfs)) => {
+            eq_maybe_qself(lqself, rqself) && eq_path(lp, rp) && over(lfs, rfs, |l, r| eq_pat(l, r))
+        },
         (Struct(lqself, lp, lfs, lr), Struct(rqself, rp, rfs, rr)) => {
-            lr == rr && eq_maybe_qself(lqself, rqself) &&eq_path(lp, rp) && unordered_over(lfs, rfs, |lf, rf| eq_field_pat(lf, rf))
+            lr == rr
+                && eq_maybe_qself(lqself, rqself)
+                && eq_path(lp, rp)
+                && unordered_over(lfs, rfs, |lf, rf| eq_field_pat(lf, rf))
         },
         (Or(ls), Or(rs)) => unordered_over(ls, rs, |l, r| eq_pat(l, r)),
         (MacCall(l), MacCall(r)) => eq_mac_call(l, r),
@@ -82,7 +87,7 @@ pub fn eq_maybe_qself(l: &Option<QSelf>, r: &Option<QSelf>) -> bool {
     match (l, r) {
         (Some(l), Some(r)) => eq_qself(l, r),
         (None, None) => true,
-        _ => false
+        _ => false,
     }
 }
 
@@ -178,7 +183,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
         (Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp),
         (MacCall(l), MacCall(r)) => eq_mac_call(l, r),
         (Struct(lse), Struct(rse)) => {
-            eq_maybe_qself(&lse.qself, &rse.qself) 
+            eq_maybe_qself(&lse.qself, &rse.qself)
                 && eq_path(&lse.path, &rse.path)
                 && eq_struct_rest(&lse.rest, &rse.rest)
                 && unordered_over(&lse.fields, &rse.fields, |l, r| eq_field(l, r))
index 0318c483959f2182a47f996dba7f88f6d584fc04..c19b558cd8c6e044902c2713e8f169fd2113920d 100644 (file)
@@ -157,3 +157,8 @@ pub fn is_doc_hidden(attrs: &[ast::Attribute]) -> bool {
         .filter_map(ast::Attribute::meta_item_list)
         .any(|l| attr::list_contains_name(&l, sym::hidden))
 }
+
+/// Return true if the attributes contain `#[unstable]`
+pub fn is_unstable(attrs: &[ast::Attribute]) -> bool {
+    attrs.iter().any(|attr| attr.has_name(sym::unstable))
+}
index 0d7fdeeb920f2c6897f172cf0f239fbf7d6c207b..15c27d1a996d74e97abfc58d4f9752405b8f727a 100644 (file)
@@ -1,6 +1,6 @@
 #![allow(clippy::float_cmp)]
 
-use crate::{clip, sext, unsext};
+use crate::{clip, is_direct_expn_of, sext, unsext};
 use if_chain::if_chain;
 use rustc_ast::ast::{self, LitFloatType, LitKind};
 use rustc_data_structures::sync::Lrc;
@@ -230,7 +230,13 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
         match e.kind {
             ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.typeck_results.expr_ty(e)),
             ExprKind::Block(block, _) => self.block(block),
-            ExprKind::Lit(ref lit) => Some(lit_to_constant(&lit.node, self.typeck_results.expr_ty_opt(e))),
+            ExprKind::Lit(ref lit) => {
+                if is_direct_expn_of(e.span, "cfg").is_some() {
+                    None
+                } else {
+                    Some(lit_to_constant(&lit.node, self.typeck_results.expr_ty_opt(e)))
+                }
+            },
             ExprKind::Array(vec) => self.multi(vec).map(Constant::Vec),
             ExprKind::Tup(tup) => self.multi(tup).map(Constant::Tuple),
             ExprKind::Repeat(value, _) => {
index 8be36756b3332a295963c89aa3dace545fd5570d..f32f1109b08e64ec963dea3b653f120e816d0f0d 100644 (file)
@@ -5,36 +5,11 @@
 
 use crate::{is_expn_of, match_def_path, paths};
 use if_chain::if_chain;
-use rustc_ast::ast;
+use rustc_ast::ast::{self, LitKind};
 use rustc_hir as hir;
 use rustc_hir::{BorrowKind, Expr, ExprKind, StmtKind, UnOp};
 use rustc_lint::LateContext;
-use rustc_span::source_map::Span;
-
-/// Converts a hir binary operator to the corresponding `ast` type.
-#[must_use]
-pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind {
-    match op {
-        hir::BinOpKind::Eq => ast::BinOpKind::Eq,
-        hir::BinOpKind::Ge => ast::BinOpKind::Ge,
-        hir::BinOpKind::Gt => ast::BinOpKind::Gt,
-        hir::BinOpKind::Le => ast::BinOpKind::Le,
-        hir::BinOpKind::Lt => ast::BinOpKind::Lt,
-        hir::BinOpKind::Ne => ast::BinOpKind::Ne,
-        hir::BinOpKind::Or => ast::BinOpKind::Or,
-        hir::BinOpKind::Add => ast::BinOpKind::Add,
-        hir::BinOpKind::And => ast::BinOpKind::And,
-        hir::BinOpKind::BitAnd => ast::BinOpKind::BitAnd,
-        hir::BinOpKind::BitOr => ast::BinOpKind::BitOr,
-        hir::BinOpKind::BitXor => ast::BinOpKind::BitXor,
-        hir::BinOpKind::Div => ast::BinOpKind::Div,
-        hir::BinOpKind::Mul => ast::BinOpKind::Mul,
-        hir::BinOpKind::Rem => ast::BinOpKind::Rem,
-        hir::BinOpKind::Shl => ast::BinOpKind::Shl,
-        hir::BinOpKind::Shr => ast::BinOpKind::Shr,
-        hir::BinOpKind::Sub => ast::BinOpKind::Sub,
-    }
-}
+use rustc_span::{sym, ExpnKind, Span, Symbol};
 
 /// Represent a range akin to `ast::ExprKind::Range`.
 #[derive(Debug, Copy, Clone)]
@@ -266,3 +241,107 @@ pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx
     }
     None
 }
+
+/// A parsed `format!` expansion
+pub struct FormatExpn<'tcx> {
+    /// Span of `format!(..)`
+    pub call_site: Span,
+    /// Inner `format_args!` expansion
+    pub format_args: FormatArgsExpn<'tcx>,
+}
+
+impl FormatExpn<'tcx> {
+    /// Parses an expanded `format!` invocation
+    pub fn parse(expr: &'tcx Expr<'tcx>) -> Option<Self> {
+        if_chain! {
+            if let ExprKind::Block(block, _) = expr.kind;
+            if let [stmt] = block.stmts;
+            if let StmtKind::Local(local) = stmt.kind;
+            if let Some(init) = local.init;
+            if let ExprKind::Call(_, [format_args]) = init.kind;
+            let expn_data = expr.span.ctxt().outer_expn_data();
+            if let ExpnKind::Macro(_, sym::format) = expn_data.kind;
+            if let Some(format_args) = FormatArgsExpn::parse(format_args);
+            then {
+                Some(FormatExpn {
+                    call_site: expn_data.call_site,
+                    format_args,
+                })
+            } else {
+                None
+            }
+        }
+    }
+}
+
+/// A parsed `format_args!` expansion
+pub struct FormatArgsExpn<'tcx> {
+    /// Span of the first argument, the format string
+    pub format_string_span: Span,
+    /// Values passed after the format string
+    pub value_args: Vec<&'tcx Expr<'tcx>>,
+
+    /// String literal expressions which represent the format string split by "{}"
+    pub format_string_parts: &'tcx [Expr<'tcx>],
+    /// Symbols corresponding to [`format_string_parts`]
+    pub format_string_symbols: Vec<Symbol>,
+    /// Expressions like `ArgumentV1::new(arg0, Debug::fmt)`
+    pub args: &'tcx [Expr<'tcx>],
+    /// The final argument passed to `Arguments::new_v1_formatted`, if applicable
+    pub fmt_expr: Option<&'tcx Expr<'tcx>>,
+}
+
+impl FormatArgsExpn<'tcx> {
+    /// Parses an expanded `format_args!` or `format_args_nl!` invocation
+    pub fn parse(expr: &'tcx Expr<'tcx>) -> Option<Self> {
+        if_chain! {
+            if let ExpnKind::Macro(_, name) = expr.span.ctxt().outer_expn_data().kind;
+            let name = name.as_str();
+            if name.ends_with("format_args") || name.ends_with("format_args_nl");
+            if let ExprKind::Call(_, args) = expr.kind;
+            if let Some((strs_ref, args, fmt_expr)) = match args {
+                // Arguments::new_v1
+                [strs_ref, args] => Some((strs_ref, args, None)),
+                // Arguments::new_v1_formatted
+                [strs_ref, args, fmt_expr] => Some((strs_ref, args, Some(fmt_expr))),
+                _ => None,
+            };
+            if let ExprKind::AddrOf(BorrowKind::Ref, _, strs_arr) = strs_ref.kind;
+            if let ExprKind::Array(format_string_parts) = strs_arr.kind;
+            if let Some(format_string_symbols) = format_string_parts
+                .iter()
+                .map(|e| {
+                    if let ExprKind::Lit(lit) = &e.kind {
+                        if let LitKind::Str(symbol, _style) = lit.node {
+                            return Some(symbol);
+                        }
+                    }
+                    None
+                })
+                .collect();
+            if let ExprKind::AddrOf(BorrowKind::Ref, _, args) = args.kind;
+            if let ExprKind::Match(args, [arm], _) = args.kind;
+            if let ExprKind::Tup(value_args) = args.kind;
+            if let Some(value_args) = value_args
+                .iter()
+                .map(|e| match e.kind {
+                    ExprKind::AddrOf(_, _, e) => Some(e),
+                    _ => None,
+                })
+                .collect();
+            if let ExprKind::Array(args) = arm.body.kind;
+            then {
+                Some(FormatArgsExpn {
+                    format_string_span: strs_ref.span,
+                    value_args,
+                    format_string_parts,
+                    format_string_symbols,
+                    args,
+                    fmt_expr,
+                })
+            } else {
+                None
+            }
+        }
+    }
+}
index 769836aaf18ed6c54c3773c5c4e052e8528f96c5..00db52a9457d85d50b30fb15da254764a55aa835 100644 (file)
@@ -72,7 +72,7 @@ use rustc_hir::LangItem::{ResultErr, ResultOk};
 use rustc_hir::{
     def, Arm, BindingAnnotation, Block, Body, Constness, Destination, Expr, ExprKind, FnDecl, GenericArgs, HirId, Impl,
     ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, Node, Param, Pat, PatKind, Path,
-    PathSegment, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind,
+    PathSegment, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp,
 };
 use rustc_lint::{LateContext, Level, Lint, LintContext};
 use rustc_middle::hir::exports::Export;
@@ -255,7 +255,7 @@ pub fn in_macro(span: Span) -> bool {
 }
 
 /// Checks if given pattern is a wildcard (`_`)
-pub fn is_wild<'tcx>(pat: &impl std::ops::Deref<Target = Pat<'tcx>>) -> bool {
+pub fn is_wild(pat: &Pat<'_>) -> bool {
     matches!(pat.kind, PatKind::Wild)
 }
 
@@ -326,16 +326,6 @@ pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol)
         .map_or(false, |did| is_diag_trait_item(cx, did, diag_item))
 }
 
-/// Checks if an expression references a variable of the given name.
-pub fn match_var(expr: &Expr<'_>, var: Symbol) -> bool {
-    if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind {
-        if let [p] = path.segments {
-            return p.ident.name == var;
-        }
-    }
-    false
-}
-
 pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
     match *path {
         QPath::Resolved(_, path) => path.segments.last().expect("A path must have at least one segment"),
@@ -493,7 +483,7 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
         _ => return Res::Err,
     };
     let tcx = cx.tcx;
-    let crates = tcx.crates();
+    let crates = tcx.crates(());
     let krate = try_res!(crates.iter().find(|&&num| tcx.crate_name(num).as_str() == krate));
     let first = try_res!(item_child_by_name(tcx, krate.as_def_id(), first));
     let last = path
@@ -707,16 +697,6 @@ pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
     }
 }
 
-/// Gets the name of a `Pat`, if any.
-pub fn get_pat_name(pat: &Pat<'_>) -> Option<Symbol> {
-    match pat.kind {
-        PatKind::Binding(.., ref spname, _) => Some(spname.name),
-        PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name),
-        PatKind::Box(p) | PatKind::Ref(p, _) => get_pat_name(&*p),
-        _ => None,
-    }
-}
-
 pub struct ContainsName {
     pub name: Symbol,
     pub result: bool,
@@ -861,14 +841,16 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio
     })
 }
 
-/// Gets the loop enclosing the given expression, if any.
-pub fn get_enclosing_loop(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
+/// Gets the loop or closure enclosing the given expression, if any.
+pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     let map = tcx.hir();
     for (_, node) in map.parent_iter(expr.hir_id) {
         match node {
             Node::Expr(
-                e @ Expr {
-                    kind: ExprKind::Loop(..),
+                e
+                @
+                Expr {
+                    kind: ExprKind::Loop(..) | ExprKind::Closure(..),
                     ..
                 },
             ) => return Some(e),
@@ -927,12 +909,8 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool
     if is_integer_literal(e, value) {
         return true;
     }
-    let map = cx.tcx.hir();
-    let parent_item = map.get_parent_item(e.hir_id);
-    if let Some((Constant::Int(v), _)) = map
-        .maybe_body_owned_by(parent_item)
-        .and_then(|body_id| constant(cx, cx.tcx.typeck_body(body_id), e))
-    {
+    let enclosing_body = cx.tcx.hir().local_def_id(cx.tcx.hir().enclosing_body_owner(e.hir_id));
+    if let Some((Constant::Int(v), _)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
         value == v
     } else {
         false
@@ -971,12 +949,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);
                 }
@@ -1004,12 +977,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);
             }
@@ -1051,8 +1019,8 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
         )
     }
 
-    fn are_refutable<'a, I: Iterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_>, mut i: I) -> bool {
-        i.any(|pat| is_refutable(cx, pat))
+    fn are_refutable<'a, I: IntoIterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_>, i: I) -> bool {
+        i.into_iter().any(|pat| is_refutable(cx, pat))
     }
 
     match pat.kind {
@@ -1063,24 +1031,20 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
         PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
         PatKind::Or(pats) => {
             // TODO: should be the honest check, that pats is exhaustive set
-            are_refutable(cx, pats.iter().map(|pat| &**pat))
+            are_refutable(cx, pats)
         },
-        PatKind::Tuple(pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)),
+        PatKind::Tuple(pats, _) => are_refutable(cx, pats),
         PatKind::Struct(ref qpath, fields, _) => {
             is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat))
         },
-        PatKind::TupleStruct(ref qpath, pats, _) => {
-            is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats.iter().map(|pat| &**pat))
-        },
-        PatKind::Slice(head, ref middle, tail) => {
+        PatKind::TupleStruct(ref qpath, pats, _) => is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats),
+        PatKind::Slice(head, middle, tail) => {
             match &cx.typeck_results().node_type(pat.hir_id).kind() {
                 rustc_ty::Slice(..) => {
                     // [..] is the only irrefutable slice pattern.
                     !head.is_empty() || middle.is_none() || !tail.is_empty()
                 },
-                rustc_ty::Array(..) => {
-                    are_refutable(cx, head.iter().chain(middle).chain(tail.iter()).map(|pat| &**pat))
-                },
+                rustc_ty::Array(..) => are_refutable(cx, head.iter().chain(middle).chain(tail.iter())),
                 _ => {
                     // unreachable!()
                     true
@@ -1094,7 +1058,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
 /// the function once on the given pattern.
 pub fn recurse_or_patterns<'tcx, F: FnMut(&'tcx Pat<'tcx>)>(pat: &'tcx Pat<'tcx>, mut f: F) {
     if let PatKind::Or(pats) = pat.kind {
-        pats.iter().copied().for_each(f);
+        pats.iter().for_each(f);
     } else {
         f(pat);
     }
@@ -1191,7 +1155,7 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc
 /// Returns `true` if the lint is allowed in the current context
 ///
 /// Useful for skipping long running code when it's unnecessary
-pub fn is_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool {
+pub fn is_lint_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool {
     cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow
 }
 
@@ -1399,6 +1363,55 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     did.map_or(false, |did| must_use_attr(cx.tcx.get_attrs(did)).is_some())
 }
 
+/// Checks if an expression represents the identity function
+/// Only examines closures and `std::convert::identity`
+pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    /// Checks if a function's body represents the identity function. Looks for bodies of the form:
+    /// * `|x| x`
+    /// * `|x| return x`
+    /// * `|x| { return x }`
+    /// * `|x| { return x; }`
+    fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
+        let id = if_chain! {
+            if let [param] = func.params;
+            if let PatKind::Binding(_, id, _, _) = param.pat.kind;
+            then {
+                id
+            } else {
+                return false;
+            }
+        };
+
+        let mut expr = &func.value;
+        loop {
+            match expr.kind {
+                #[rustfmt::skip]
+                ExprKind::Block(&Block { stmts: [], expr: Some(e), .. }, _, )
+                | ExprKind::Ret(Some(e)) => expr = e,
+                #[rustfmt::skip]
+                ExprKind::Block(&Block { stmts: [stmt], expr: None, .. }, _) => {
+                    if_chain! {
+                        if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind;
+                        if let ExprKind::Ret(Some(ret_val)) = e.kind;
+                        then {
+                            expr = ret_val;
+                        } else {
+                            return false;
+                        }
+                    }
+                },
+                _ => return path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty(),
+            }
+        }
+    }
+
+    match expr.kind {
+        ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)),
+        ExprKind::Path(ref path) => is_qpath_def_path(cx, path, expr.hir_id, &paths::CONVERT_IDENTITY),
+        _ => false,
+    }
+}
+
 /// Gets the node where an expression is either used, or it's type is unified with another branch.
 pub fn get_expr_use_or_unification_node(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<Node<'tcx>> {
     let map = tcx.hir();
@@ -1510,25 +1523,6 @@ pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
     }
 }
 
-/// This function checks if any of the lints in the slice is enabled for the provided `HirId`.
-/// A lint counts as enabled with any of the levels: `Level::Forbid` | `Level::Deny` | `Level::Warn`
-///
-/// ```ignore
-/// #[deny(clippy::YOUR_AWESOME_LINT)]
-/// println!("Hello, World!"); // <- Clippy code: run_lints(cx, &[YOUR_AWESOME_LINT], id) == true
-///
-/// #[allow(clippy::YOUR_AWESOME_LINT)]
-/// println!("See you soon!"); // <- Clippy code: run_lints(cx, &[YOUR_AWESOME_LINT], id) == false
-/// ```
-pub fn run_lints(cx: &LateContext<'_>, lints: &[&'static Lint], id: HirId) -> bool {
-    lints.iter().any(|lint| {
-        matches!(
-            cx.tcx.lint_level_at_node(lint, id),
-            (Level::Forbid | Level::Deny | Level::Warn, _)
-        )
-    })
-}
-
 /// Returns Option<String> where String is a textual representation of the type encapsulated in the
 /// slice iff the given expression is a slice of primitives (as defined in the
 /// `is_recursively_primitive_type` function) and None otherwise.
@@ -1654,6 +1648,19 @@ pub fn peel_hir_expr_refs(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
     (e, count)
 }
 
+/// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is
+/// dereferenced. An overloaded deref such as `Vec` to slice would not be removed.
+pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {
+    loop {
+        match expr.kind {
+            ExprKind::AddrOf(_, _, e) => expr = e,
+            ExprKind::Unary(UnOp::Deref, e) if cx.typeck_results().expr_ty(e).is_ref() => expr = e,
+            _ => break,
+        }
+    }
+    expr
+}
+
 #[macro_export]
 macro_rules! unwrap_cargo_metadata {
     ($cx: ident, $lint: ident, $deps: expr) => {{
@@ -1683,3 +1690,46 @@ pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
         }
     }
 }
+
+/// Checks whether item either has `test` attribute applied, or
+/// is a module with `test` in its name.
+pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool {
+    if let Some(def_id) = tcx.hir().opt_local_def_id(item.hir_id()) {
+        if tcx.has_attr(def_id.to_def_id(), sym::test) {
+            return true;
+        }
+    }
+
+    matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test")
+}
+
+macro_rules! op_utils {
+    ($($name:ident $assign:ident)*) => {
+        /// Binary operation traits like `LangItem::Add`
+        pub static BINOP_TRAITS: &[LangItem] = &[$(LangItem::$name,)*];
+
+        /// Operator-Assign traits like `LangItem::AddAssign`
+        pub static OP_ASSIGN_TRAITS: &[LangItem] = &[$(LangItem::$assign,)*];
+
+        /// Converts `BinOpKind::Add` to `(LangItem::Add, LangItem::AddAssign)`, for example
+        pub fn binop_traits(kind: hir::BinOpKind) -> Option<(LangItem, LangItem)> {
+            match kind {
+                $(hir::BinOpKind::$name => Some((LangItem::$name, LangItem::$assign)),)*
+                _ => None,
+            }
+        }
+    };
+}
+
+op_utils! {
+    Add    AddAssign
+    Sub    SubAssign
+    Mul    MulAssign
+    Div    DivAssign
+    Rem    RemAssign
+    BitXor BitXorAssign
+    BitAnd BitAndAssign
+    BitOr  BitOrAssign
+    Shl    ShlAssign
+    Shr    ShrAssign
+}
index 546706d51d7b597c3f6d03b90a1448152533d37b..4a28c7dd9a04a3885251ef7ab44e7d5ea65aa7fe 100644 (file)
@@ -162,6 +162,9 @@ impl<'a> NumericLiteral<'a> {
         }
 
         if let Some(suffix) = self.suffix {
+            if output.ends_with('.') {
+                output.push('0');
+            }
             output.push('_');
             output.push_str(suffix);
         }
index b913d1ce8b1f769cc2b1884feb5fae2d19722eb6..c960eec306414620449cd6d05e189080b8752867 100644 (file)
@@ -38,7 +38,6 @@ pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "defa
 pub const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"];
 pub const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
 pub const DIR_BUILDER: [&str; 3] = ["std", "fs", "DirBuilder"];
-pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"];
 pub const DISPLAY_TRAIT: [&str; 3] = ["core", "fmt", "Display"];
 pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"];
 pub const DROP: [&str; 3] = ["core", "mem", "drop"];
@@ -50,9 +49,6 @@ pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
 pub const F64_EPSILON: [&str; 4] = ["core", "f64", "<impl f64>", "EPSILON"];
 pub const FILE: [&str; 3] = ["std", "fs", "File"];
 pub const FILE_TYPE: [&str; 3] = ["std", "fs", "FileType"];
-pub const FMT_ARGUMENTS_NEW_V1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"];
-pub const FMT_ARGUMENTS_NEW_V1_FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"];
-pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"];
 pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"];
 pub const FROM_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "FromIterator"];
 pub const FROM_ITERATOR_METHOD: [&str; 6] = ["core", "iter", "traits", "collect", "FromIterator", "from_iter"];
@@ -82,6 +78,7 @@ pub const ITER_REPEAT: [&str; 5] = ["core", "iter", "sources", "repeat", "repeat
 pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"];
 #[cfg(feature = "internal-lints")]
 pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"];
+pub const LIBC_STRLEN: [&str; 2] = ["libc", "strlen"];
 pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"];
 #[cfg(any(feature = "internal-lints", feature = "metadata-collector-lint"))]
 pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
index 791688cd194a997a75461edc103998525e434df4..8adb691595213fd80cd036f1aa50fa20cadd97a1 100644 (file)
@@ -1,10 +1,10 @@
 use crate::source::snippet;
-use crate::{get_pat_name, match_var};
+use crate::{path_to_local_id, strip_pat_refs};
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
-use rustc_hir::{Body, BodyId, Expr, ExprKind, Param};
+use rustc_hir::{Body, BodyId, Expr, ExprKind, HirId, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::hir::map::Map;
-use rustc_span::{Span, Symbol};
+use rustc_span::Span;
 use std::borrow::Cow;
 
 pub fn get_spans(
@@ -14,10 +14,11 @@ pub fn get_spans(
     replacements: &[(&'static str, &'static str)],
 ) -> Option<Vec<(Span, Cow<'static, str>)>> {
     if let Some(body) = opt_body_id.map(|id| cx.tcx.hir().body(id)) {
-        get_binding_name(&body.params[idx]).map_or_else(
-            || Some(vec![]),
-            |name| extract_clone_suggestions(cx, name, replacements, body),
-        )
+        if let PatKind::Binding(_, binding_id, _, _) = strip_pat_refs(body.params[idx].pat).kind {
+            extract_clone_suggestions(cx, binding_id, replacements, body)
+        } else {
+            Some(vec![])
+        }
     } else {
         Some(vec![])
     }
@@ -25,13 +26,13 @@ pub fn get_spans(
 
 fn extract_clone_suggestions<'tcx>(
     cx: &LateContext<'tcx>,
-    name: Symbol,
+    id: HirId,
     replace: &[(&'static str, &'static str)],
     body: &'tcx Body<'_>,
 ) -> Option<Vec<(Span, Cow<'static, str>)>> {
     let mut visitor = PtrCloneVisitor {
         cx,
-        name,
+        id,
         replace,
         spans: vec![],
         abort: false,
@@ -42,7 +43,7 @@ fn extract_clone_suggestions<'tcx>(
 
 struct PtrCloneVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
-    name: Symbol,
+    id: HirId,
     replace: &'a [(&'static str, &'static str)],
     spans: Vec<(Span, Cow<'static, str>)>,
     abort: bool,
@@ -55,16 +56,15 @@ impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> {
         if self.abort {
             return;
         }
-        if let ExprKind::MethodCall(seg, _, args, _) = expr.kind {
-            if args.len() == 1 && match_var(&args[0], self.name) {
+        if let ExprKind::MethodCall(seg, _, [recv], _) = expr.kind {
+            if path_to_local_id(recv, self.id) {
                 if seg.ident.name.as_str() == "capacity" {
                     self.abort = true;
                     return;
                 }
                 for &(fn_name, suffix) in self.replace {
                     if seg.ident.name.as_str() == fn_name {
-                        self.spans
-                            .push((expr.span, snippet(self.cx, args[0].span, "_") + suffix));
+                        self.spans.push((expr.span, snippet(self.cx, recv.span, "_") + suffix));
                         return;
                     }
                 }
@@ -77,7 +77,3 @@ impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> {
         NestedVisitorMap::None
     }
 }
-
-fn get_binding_name(arg: &Param<'_>) -> Option<Symbol> {
-    get_pat_name(arg.pat)
-}
index efc0ec50fdc947f9d209be2256d8c41ecf1f906b..3bd75b10e90588d45f47832a08e0ea6851737398 100644 (file)
@@ -154,7 +154,7 @@ impl<'a> Sugg<'a> {
             | hir::ExprKind::Err => Sugg::NonParen(snippet),
             hir::ExprKind::Assign(..) => Sugg::BinOp(AssocOp::Assign, snippet),
             hir::ExprKind::AssignOp(op, ..) => Sugg::BinOp(hirbinop2assignop(op), snippet),
-            hir::ExprKind::Binary(op, ..) => Sugg::BinOp(AssocOp::from_ast_binop(higher::binop(op.node)), snippet),
+            hir::ExprKind::Binary(op, ..) => Sugg::BinOp(AssocOp::from_ast_binop(op.node.into()), snippet),
             hir::ExprKind::Cast(..) => Sugg::BinOp(AssocOp::As, snippet),
             hir::ExprKind::Type(..) => Sugg::BinOp(AssocOp::Colon, snippet),
         }
index a92d3be5d3cf2b595d831769b6efbe142ccc15b6..523d55219ab6919fac1f8208c7fc739f8f98fc58 100644 (file)
@@ -14,6 +14,7 @@ use rustc_middle::ty::{self, AdtDef, IntTy, Ty, TypeFoldable, UintTy};
 use rustc_span::sym;
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::DUMMY_SP;
+use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::query::normalize::AtExt;
 
 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,16 +121,19 @@ 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`.
@@ -231,6 +236,17 @@ pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool {
     }
 }
 
+/// Checks if the type is a reference equals to a diagnostic item
+pub fn is_type_ref_to_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symbol) -> bool {
+    match ty.kind() {
+        ty::Ref(_, ref_ty, _) => match ref_ty.kind() {
+            ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(diag_item, adt.did),
+            _ => false,
+        },
+        _ => false,
+    }
+}
+
 /// Checks if the type is equal to a diagnostic item
 ///
 /// If you change the signature, remember to update the internal lint `MatchTypeOnDiagItem`
@@ -241,10 +257,12 @@ pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symb
     }
 }
 
-/// Checks if the type is equal to a lang item
+/// Checks if the type is equal to a lang item.
+///
+/// Returns `false` if the `LangItem` is not defined.
 pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool {
     match ty.kind() {
-        ty::Adt(adt, _) => cx.tcx.lang_items().require(lang_item).unwrap() == adt.did,
+        ty::Adt(adt, _) => cx.tcx.lang_items().require(lang_item).map_or(false, |li| li == adt.did),
         _ => false,
     }
 }
index 2c55021ac88374f0c8fe450e8d8d3bbd75127b6d..ac885e9994404b605dd5b0d1c91df3cc45c6b970 100644 (file)
@@ -10,7 +10,7 @@ use rustc_lint::LateContext;
 use rustc_middle::hir::map::Map;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty;
-use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
+use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
 /// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined.
 pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> Option<HirIdSet> {
@@ -67,7 +67,7 @@ impl<'tcx> MutVarsDelegate {
 }
 
 impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
-    fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId, _: ConsumeMode) {}
+    fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
 
     fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, bk: ty::BorrowKind) {
         if let ty::BorrowKind::MutBorrow = bk {
@@ -199,3 +199,50 @@ pub fn contains_return_break_continue_macro(expression: &Expr<'_>) -> bool {
     recursive_visitor.visit_expr(expression);
     recursive_visitor.seen_return_break_continue
 }
+
+pub struct UsedAfterExprVisitor<'a, 'tcx> {
+    cx: &'a LateContext<'tcx>,
+    expr: &'tcx Expr<'tcx>,
+    definition: HirId,
+    past_expr: bool,
+    used_after_expr: bool,
+}
+impl<'a, 'tcx> UsedAfterExprVisitor<'a, 'tcx> {
+    pub fn is_found(cx: &'a LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
+        utils::path_to_local(expr).map_or(false, |definition| {
+            let mut visitor = UsedAfterExprVisitor {
+                cx,
+                expr,
+                definition,
+                past_expr: false,
+                used_after_expr: false,
+            };
+            utils::get_enclosing_block(cx, definition).map_or(false, |block| {
+                visitor.visit_block(block);
+                visitor.used_after_expr
+            })
+        })
+    }
+}
+
+impl<'a, 'tcx> intravisit::Visitor<'tcx> for UsedAfterExprVisitor<'a, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+    }
+
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
+        if self.used_after_expr {
+            return;
+        }
+
+        if expr.hir_id == self.expr.hir_id {
+            self.past_expr = true;
+        } else if self.past_expr && utils::path_to_local_id(expr, self.definition) {
+            self.used_after_expr = true;
+        } else {
+            intravisit::walk_expr(self, expr);
+        }
+    }
+}
index e2e307ce4f6cf93df422f3c10afa1328191da276..43d3792f5952125a80cb1eccb4b9d35213301a60 100644 (file)
@@ -14,6 +14,7 @@ the codebase take a look at [Adding Lints] or [Common Tools].
   - [lintcheck](#lintcheck)
   - [PR](#pr)
   - [Common Abbreviations](#common-abbreviations)
+  - [Install from source](#install-from-source)
 
 ## Get the Code
 
@@ -90,15 +91,17 @@ cargo dev fmt
 cargo dev update_lints
 # create a new lint and register it
 cargo dev new_lint
+# automatically formatting all code before each commit
+cargo dev setup git-hook
 # (experimental) Setup Clippy to work with IntelliJ-Rust
-cargo dev ide_setup
+cargo dev setup intellij
 ```
 
 ## lintcheck
 `cargo lintcheck` will build and run clippy on a fixed set of crates and generate a log of the results.  
-You can `git diff` the updated log against its previous version and 
+You can `git diff` the updated log against its previous version and
 see what impact your lint made on a small set of crates.  
-If you add a new lint, please audit the resulting warnings and make sure 
+If you add a new lint, please audit the resulting warnings and make sure
 there are no false positives and that the suggestions are valid.
 
 Refer to the tools [README] for more details.
@@ -126,4 +129,45 @@ This is a concise list of abbreviations that can come up during Clippy developme
 general list can be found in the [rustc-dev-guide glossary][glossary]. Always feel free to ask if
 an abbreviation or meaning is unclear to you.
 
+## Install from source
+
+If you are hacking on Clippy and want to install it from source, do the following:
+
+First, take note of the toolchain [override](https://rust-lang.github.io/rustup/overrides.html) in `/rust-toolchain`.
+We will use this override to install Clippy into the right toolchain.
+
+> Tip: You can view the active toolchain for the current directory with `rustup show active-toolchain`.
+
+From the Clippy project root, run the following command to build the Clippy binaries and copy them into the
+toolchain directory. This will override the currently installed Clippy component.
+
+```terminal
+cargo build --release --bin cargo-clippy --bin clippy-driver -Zunstable-options --out-dir "$(rustc --print=sysroot)/bin"
+```
+
+Now you may run `cargo clippy` in any project, using the toolchain where you just installed Clippy.
+
+```terminal
+cd my-project
+cargo +nightly-2021-07-01 clippy
+```
+
+...or `clippy-driver`
+
+```terminal
+clippy-driver +nightly-2021-07-01 <filename>
+```
+
+If you need to restore the default Clippy installation, run the following (from the Clippy project root).
+
+```terminal
+rustup component remove clippy
+rustup component add clippy
+```
+
+> **DO NOT** install using `cargo install --path . --force` since this will overwrite rustup
+[proxies](https://rust-lang.github.io/rustup/concepts/proxies.html). That is, `~/.cargo/bin/cargo-clippy` and
+`~/.cargo/bin/clippy-driver` should be hard or soft links to `~/.cargo/bin/rustup`. You can repair these by running
+`rustup update`.
+
 [glossary]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html
index abac1227b4ff389cee02b348ddf01ad9a5346b78..0a85f65001101c4fa5a172ac462b73d781e5e125 100644 (file)
@@ -6,7 +6,7 @@ You may need following tooltips to catch up with common operations.
   - [Retrieving the type of an expression](#retrieving-the-type-of-an-expression)
   - [Checking if an expression is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method)
   - [Checking if a type implements a specific trait](#checking-if-a-type-implements-a-specific-trait)
-  - [Checking if a type defines a method](#checking-if-a-type-defines-a-method)
+  - [Checking if a type defines a specific method](#checking-if-a-type-defines-a-specific-method)
   - [Dealing with macros](#dealing-with-macros)
 
 Useful Rustc dev guide links:
index e0af9bf0625721a82c59fc63bb000bcd34a253f5..afe3033c288cffd8d95b06ea2e833989455cb81a 100644 (file)
@@ -101,6 +101,21 @@ After this, the release should be available on the Clippy [release page].
 
 [release page]: https://github.com/rust-lang/rust-clippy/releases
 
+## Update the `stable` branch
+
+At this step you should have already checked out the commit of the `rust-1.XX.0`
+tag. Updating the stable branch from here is as easy as:
+
+```bash
+# Assuming the current directory corresponds to the Clippy repository and the
+# commit of the just created rust-1.XX.0 tag is checked out.
+$ git push upstream rust-1.XX.0:stable  # `upstream` is the `rust-lang/rust-clippy` remote
+```
+
+_NOTE: Usually there are no stable backports for Clippy, so this update should
+be possible without force pushing or anything like this. If there should have
+happened a stable backport, make sure to re-merge those changes just as with the
+`beta` branch._
 
 ## Update `CHANGELOG.md`
 
index 52bbcc0a8317dd47e2afbe4ccd2e854deaac7d10..8c169506e533d7b7892ff558924ca46c784529ca 100644 (file)
@@ -69,9 +69,9 @@ is checked.
 is explicitly specified in the options.
 
 ### Fix mode
-You can run `./lintcheck/target/debug/lintcheck --fix` which will run Clippy with `-Zunstable-options --fix` and
+You can run `./lintcheck/target/debug/lintcheck --fix` which will run Clippy with `--fix` and
 print a warning if Clippys suggestions fail to apply (if the resulting code does not build).  
 This lets us spot bad suggestions or false positives automatically in some cases.  
 
-Please note that the target dir should be cleaned afterwards since clippy will modify 
+Please note that the target dir should be cleaned afterwards since clippy will modify
 the downloaded sources which can lead to unexpected results when running lintcheck again afterwards.
index f6a75595c986b1294e21bf8236eafd90cd97237e..7d2f3173fb0e7cd4d5d475decac18787b14f60b0 100644 (file)
@@ -260,14 +260,7 @@ impl Crate {
         let shared_target_dir = clippy_project_root().join("target/lintcheck/shared_target_dir");
 
         let mut args = if fix {
-            vec![
-                "-Zunstable-options",
-                "--fix",
-                "-Zunstable-options",
-                "--allow-no-vcs",
-                "--",
-                "--cap-lints=warn",
-            ]
+            vec!["--fix", "--allow-no-vcs", "--", "--cap-lints=warn"]
         } else {
             vec!["--", "--message-format=json", "--", "--cap-lints=warn"]
         };
index e3863c46288c2e3587445dc494a4c14d6ffa023d..3a2005e787228e2b6ab961b7a4d977c3106b09bf 100644 (file)
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-06-03"
+channel = "nightly-2021-07-19"
 components = ["llvm-tools-preview", "rustc-dev", "rust-src"]
index 7bb80b1196e5900dd2169a91e6d7ab5977c918d6..6bd4123ddeb45d92917f1dd043fa9d09ecf208de 100644 (file)
@@ -70,7 +70,6 @@ impl ClippyCmd {
         I: Iterator<Item = String>,
     {
         let mut cargo_subcommand = "check";
-        let mut unstable_options = false;
         let mut args = vec![];
 
         for arg in old_args.by_ref() {
@@ -80,18 +79,12 @@ impl ClippyCmd {
                     continue;
                 },
                 "--" => break,
-                // Cover -Zunstable-options and -Z unstable-options
-                s if s.ends_with("unstable-options") => unstable_options = true,
                 _ => {},
             }
 
             args.push(arg);
         }
 
-        if cargo_subcommand == "fix" && !unstable_options {
-            panic!("Usage of `--fix` requires `-Z unstable-options`");
-        }
-
         let mut clippy_args: Vec<String> = old_args.collect();
         if cargo_subcommand == "fix" && !clippy_args.iter().any(|arg| arg == "--no-deps") {
             clippy_args.push("--no-deps".into());
@@ -176,34 +169,23 @@ mod tests {
     use super::ClippyCmd;
 
     #[test]
-    #[should_panic]
-    fn fix_without_unstable() {
+    fn fix() {
         let args = "cargo clippy --fix".split_whitespace().map(ToString::to_string);
-        ClippyCmd::new(args);
-    }
-
-    #[test]
-    fn fix_unstable() {
-        let args = "cargo clippy --fix -Zunstable-options"
-            .split_whitespace()
-            .map(ToString::to_string);
         let cmd = ClippyCmd::new(args);
         assert_eq!("fix", cmd.cargo_subcommand);
-        assert!(cmd.args.iter().any(|arg| arg.ends_with("unstable-options")));
+        assert!(!cmd.args.iter().any(|arg| arg.ends_with("unstable-options")));
     }
 
     #[test]
     fn fix_implies_no_deps() {
-        let args = "cargo clippy --fix -Zunstable-options"
-            .split_whitespace()
-            .map(ToString::to_string);
+        let args = "cargo clippy --fix".split_whitespace().map(ToString::to_string);
         let cmd = ClippyCmd::new(args);
         assert!(cmd.clippy_args.iter().any(|arg| arg == "--no-deps"));
     }
 
     #[test]
     fn no_deps_not_duplicated_with_fix() {
-        let args = "cargo clippy --fix -Zunstable-options -- --no-deps"
+        let args = "cargo clippy --fix -- --no-deps"
             .split_whitespace()
             .map(ToString::to_string);
         let cmd = ClippyCmd::new(args);
index 7d266a36bb666387803a921db506712d073720b4..caa19e39ccd3af1baad8a61ad79688cabee02c8d 100644 (file)
@@ -48,7 +48,24 @@ fn third_party_crates() -> String {
                     && name.rsplit('.').next().map(|ext| ext.eq_ignore_ascii_case("rlib")) == Some(true)
                 {
                     if let Some(old) = crates.insert(dep, path.clone()) {
-                        panic!("Found multiple rlibs for crate `{}`: `{:?}` and `{:?}", dep, old, path);
+                        // Check which action should be done in order to remove compiled deps.
+                        // If pre-installed version of compiler is used, `cargo clean` will do.
+                        // Otherwise (for bootstrapped compiler), the dependencies directory
+                        // must be removed manually.
+                        let suggested_action = if std::env::var_os("RUSTC_BOOTSTRAP").is_some() {
+                            "remove the stageN-tools directory"
+                        } else {
+                            "run `cargo clean`"
+                        };
+
+                        panic!(
+                            "\n---------------------------------------------------\n\n \
+                            Found multiple rlibs for crate `{}`: `{:?}` and `{:?}`.\n \
+                            Probably, you need to {} before running tests again.\n \
+                            \nFor details on that error see https://github.com/rust-lang/rust-clippy/issues/7343 \
+                            \n---------------------------------------------------\n",
+                            dep, old, path, suggested_action
+                        );
                     }
                     break;
                 }
diff --git a/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/clippy.toml b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/clippy.toml
new file mode 100644 (file)
index 0000000..05ba822
--- /dev/null
@@ -0,0 +1,10 @@
+enforced-import-renames = [
+    { path = "std::option::Option", rename = "Maybe" },
+    { path = "std::process::Child", rename = "Kid" },
+    { path = "std::process::exit", rename = "goodbye" },
+    { path = "std::collections::BTreeMap", rename = "Map" },
+    { path = "std::clone", rename = "foo" },
+    { path = "std::thread::sleep", rename = "thread_sleep" },
+    { path = "std::any::type_name", rename = "ident" },
+    { path = "std::sync::Mutex", rename = "StdMutie" }
+]
diff --git a/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs
new file mode 100644 (file)
index 0000000..f60058c
--- /dev/null
@@ -0,0 +1,16 @@
+#![warn(clippy::missing_enforced_import_renames)]
+
+use std::alloc as colla;
+use std::option::Option as Maybe;
+use std::process::{exit as wrong_exit, Child as Kid};
+use std::thread::sleep;
+#[rustfmt::skip]
+use std::{
+    any::{type_name, Any},
+    clone,
+    sync :: Mutex,
+};
+
+fn main() {
+    use std::collections::BTreeMap as OopsWrongRename;
+}
diff --git a/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr
new file mode 100644 (file)
index 0000000..45de8fd
--- /dev/null
@@ -0,0 +1,40 @@
+error: this import should be renamed
+  --> $DIR/conf_missing_enforced_import_rename.rs:5:20
+   |
+LL | use std::process::{exit as wrong_exit, Child as Kid};
+   |                    ^^^^^^^^^^^^^^^^^^ help: try: `exit as goodbye`
+   |
+   = note: `-D clippy::missing-enforced-import-renames` implied by `-D warnings`
+
+error: this import should be renamed
+  --> $DIR/conf_missing_enforced_import_rename.rs:6:1
+   |
+LL | use std::thread::sleep;
+   | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `use std::thread::sleep as thread_sleep`
+
+error: this import should be renamed
+  --> $DIR/conf_missing_enforced_import_rename.rs:9:11
+   |
+LL |     any::{type_name, Any},
+   |           ^^^^^^^^^ help: try: `type_name as ident`
+
+error: this import should be renamed
+  --> $DIR/conf_missing_enforced_import_rename.rs:10:5
+   |
+LL |     clone,
+   |     ^^^^^ help: try: `clone as foo`
+
+error: this import should be renamed
+  --> $DIR/conf_missing_enforced_import_rename.rs:11:5
+   |
+LL |     sync :: Mutex,
+   |     ^^^^^^^^^^^^^ help: try: `sync :: Mutex as StdMutie`
+
+error: this import should be renamed
+  --> $DIR/conf_missing_enforced_import_rename.rs:15:5
+   |
+LL |     use std::collections::BTreeMap as OopsWrongRename;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `use std::collections::BTreeMap as Map`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs
new file mode 100644 (file)
index 0000000..6452189
--- /dev/null
@@ -0,0 +1,18 @@
+// compile-flags: --emit=link
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(DeriveSomething)]
+pub fn derive(_: TokenStream) -> TokenStream {
+    "fn _f() -> Vec<u8> { vec![] }".parse().unwrap()
+}
+
+#[proc_macro]
+pub fn foo_bar(_: TokenStream) -> TokenStream {
+    "fn issue_7422() { eprintln!(); }".parse().unwrap()
+}
diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/clippy.toml b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/clippy.toml
new file mode 100644 (file)
index 0000000..bced894
--- /dev/null
@@ -0,0 +1,6 @@
+standard-macro-braces = [
+    { name = "quote", brace = "{" },
+    { name = "quote::quote", brace = "{" },
+    { name = "eprint", brace = "[" },
+    { name = "type_pos", brace = "[" },
+]
diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs
new file mode 100644 (file)
index 0000000..e9f042d
--- /dev/null
@@ -0,0 +1,52 @@
+// aux-build:proc_macro_derive.rs
+
+#![warn(clippy::nonstandard_macro_braces)]
+
+extern crate proc_macro_derive;
+extern crate quote;
+
+use quote::quote;
+
+#[derive(proc_macro_derive::DeriveSomething)]
+pub struct S;
+
+proc_macro_derive::foo_bar!();
+
+#[rustfmt::skip]
+macro_rules! test {
+    () => {
+        vec!{0, 0, 0}
+    };
+}
+
+#[rustfmt::skip]
+macro_rules! test2 {
+    ($($arg:tt)*) => {
+        format_args!($($arg)*)
+    };
+}
+
+macro_rules! type_pos {
+    ($what:ty) => {
+        Vec<$what>
+    };
+}
+
+#[rustfmt::skip]
+fn main() {
+    let _ = vec! {1, 2, 3};
+    let _ = format!["ugh {} stop being such a good compiler", "hello"];
+    let _ = quote!(let x = 1;);
+    let _ = quote::quote!(match match match);
+    let _ = test!();
+    let _ = vec![1,2,3];
+
+    let _ = quote::quote! {true || false};
+    let _ = vec! [0 ,0 ,0];
+    let _ = format!("fds{}fds", 10);
+    let _ = test2!["{}{}{}", 1, 2, 3];
+
+    let _: type_pos!(usize) = vec![];
+
+    eprint!("test if user config overrides defaults");
+}
diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr
new file mode 100644 (file)
index 0000000..86063a0
--- /dev/null
@@ -0,0 +1,94 @@
+error: use of irregular braces for `vec!` macro
+  --> $DIR/conf_nonstandard_macro_braces.rs:37:13
+   |
+LL |     let _ = vec! {1, 2, 3};
+   |             ^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::nonstandard-macro-braces` implied by `-D warnings`
+help: consider writing `vec![1, 2, 3]`
+  --> $DIR/conf_nonstandard_macro_braces.rs:37:13
+   |
+LL |     let _ = vec! {1, 2, 3};
+   |             ^^^^^^^^^^^^^^
+
+error: use of irregular braces for `format!` macro
+  --> $DIR/conf_nonstandard_macro_braces.rs:38:13
+   |
+LL |     let _ = format!["ugh {} stop being such a good compiler", "hello"];
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider writing `format!("ugh () stop being such a good compiler", "hello")`
+  --> $DIR/conf_nonstandard_macro_braces.rs:38:13
+   |
+LL |     let _ = format!["ugh {} stop being such a good compiler", "hello"];
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of irregular braces for `quote!` macro
+  --> $DIR/conf_nonstandard_macro_braces.rs:39:13
+   |
+LL |     let _ = quote!(let x = 1;);
+   |             ^^^^^^^^^^^^^^^^^^
+   |
+help: consider writing `quote! {let x = 1;}`
+  --> $DIR/conf_nonstandard_macro_braces.rs:39:13
+   |
+LL |     let _ = quote!(let x = 1;);
+   |             ^^^^^^^^^^^^^^^^^^
+
+error: use of irregular braces for `quote::quote!` macro
+  --> $DIR/conf_nonstandard_macro_braces.rs:40:13
+   |
+LL |     let _ = quote::quote!(match match match);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider writing `quote::quote! {match match match}`
+  --> $DIR/conf_nonstandard_macro_braces.rs:40:13
+   |
+LL |     let _ = quote::quote!(match match match);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of irregular braces for `vec!` macro
+  --> $DIR/conf_nonstandard_macro_braces.rs:18:9
+   |
+LL |         vec!{0, 0, 0}
+   |         ^^^^^^^^^^^^^
+...
+LL |     let _ = test!();
+   |             ------- in this macro invocation
+   |
+help: consider writing `vec![0, 0, 0]`
+  --> $DIR/conf_nonstandard_macro_braces.rs:18:9
+   |
+LL |         vec!{0, 0, 0}
+   |         ^^^^^^^^^^^^^
+...
+LL |     let _ = test!();
+   |             ------- in this macro invocation
+   = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: use of irregular braces for `type_pos!` macro
+  --> $DIR/conf_nonstandard_macro_braces.rs:49:12
+   |
+LL |     let _: type_pos!(usize) = vec![];
+   |            ^^^^^^^^^^^^^^^^
+   |
+help: consider writing `type_pos![usize]`
+  --> $DIR/conf_nonstandard_macro_braces.rs:49:12
+   |
+LL |     let _: type_pos!(usize) = vec![];
+   |            ^^^^^^^^^^^^^^^^
+
+error: use of irregular braces for `eprint!` macro
+  --> $DIR/conf_nonstandard_macro_braces.rs:51:5
+   |
+LL |     eprint!("test if user config overrides defaults");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider writing `eprint!["test if user config overrides defaults"];`
+  --> $DIR/conf_nonstandard_macro_braces.rs:51:5
+   |
+LL |     eprint!("test if user config overrides defaults");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
index c0df3b6e8af5dd12d5ac7d618e6d9084525a3776..a3245da68250c3d28939ddb5da02dc08fbb938ce 100644 (file)
@@ -1 +1,5 @@
-disallowed-methods = ["core::iter::traits::iterator::Iterator::sum", "regex::re_unicode::Regex::is_match", "regex::re_unicode::Regex::new"]
+disallowed-methods = [
+    "std::iter::Iterator::sum",
+    "regex::Regex::is_match",
+    "regex::Regex::new"
+]
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_type/clippy.toml b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/clippy.toml
new file mode 100644 (file)
index 0000000..2eff854
--- /dev/null
@@ -0,0 +1,9 @@
+disallowed-types = [
+    "std::collections::HashMap",
+    "std::sync::atomic::AtomicU32",
+    "syn::TypePath",
+    "proc_macro2::Ident",
+    "std::thread::Thread",
+    "std::time::Instant",
+    "std::io::Read",
+]
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.rs b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.rs
new file mode 100644 (file)
index 0000000..567afb5
--- /dev/null
@@ -0,0 +1,35 @@
+#![warn(clippy::disallowed_type)]
+
+extern crate quote;
+extern crate syn;
+
+use std::sync as foo;
+use std::sync::atomic::AtomicU32;
+use std::time::Instant as Sneaky;
+
+struct HashMap;
+
+fn bad_return_type() -> fn() -> Sneaky {
+    todo!()
+}
+
+fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) {
+    todo!()
+}
+
+fn trait_obj(_: &dyn std::io::Read) {
+    todo!()
+}
+
+static BAD: foo::atomic::AtomicPtr<()> = foo::atomic::AtomicPtr::new(std::ptr::null_mut());
+
+#[allow(clippy::diverging_sub_expression)]
+fn main() {
+    let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new();
+    let _ = Sneaky::now();
+    let _ = foo::atomic::AtomicU32::new(0);
+    static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1);
+    let _: std::collections::BTreeMap<(), syn::TypePath> = Default::default();
+    let _ = syn::Ident::new("", todo!());
+    let _ = HashMap;
+}
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.stderr b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.stderr
new file mode 100644 (file)
index 0000000..4e6fd91
--- /dev/null
@@ -0,0 +1,88 @@
+error: `std::sync::atomic::AtomicU32` is not allowed according to config
+  --> $DIR/conf_disallowed_type.rs:7:1
+   |
+LL | use std::sync::atomic::AtomicU32;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::disallowed-type` implied by `-D warnings`
+
+error: `std::time::Instant` is not allowed according to config
+  --> $DIR/conf_disallowed_type.rs:8:1
+   |
+LL | use std::time::Instant as Sneaky;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `std::time::Instant` is not allowed according to config
+  --> $DIR/conf_disallowed_type.rs:12:33
+   |
+LL | fn bad_return_type() -> fn() -> Sneaky {
+   |                                 ^^^^^^
+
+error: `std::time::Instant` is not allowed according to config
+  --> $DIR/conf_disallowed_type.rs:16:28
+   |
+LL | fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) {
+   |                            ^^^^^^
+
+error: `std::sync::atomic::AtomicU32` is not allowed according to config
+  --> $DIR/conf_disallowed_type.rs:16:39
+   |
+LL | fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) {
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^
+
+error: `std::io::Read` is not allowed according to config
+  --> $DIR/conf_disallowed_type.rs:20:22
+   |
+LL | fn trait_obj(_: &dyn std::io::Read) {
+   |                      ^^^^^^^^^^^^^
+
+error: `std::collections::HashMap` is not allowed according to config
+  --> $DIR/conf_disallowed_type.rs:28:48
+   |
+LL |     let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new();
+   |                                                ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `std::collections::HashMap` is not allowed according to config
+  --> $DIR/conf_disallowed_type.rs:28:12
+   |
+LL |     let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new();
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `std::time::Instant` is not allowed according to config
+  --> $DIR/conf_disallowed_type.rs:29:13
+   |
+LL |     let _ = Sneaky::now();
+   |             ^^^^^^
+
+error: `std::sync::atomic::AtomicU32` is not allowed according to config
+  --> $DIR/conf_disallowed_type.rs:30:13
+   |
+LL |     let _ = foo::atomic::AtomicU32::new(0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+error: `std::sync::atomic::AtomicU32` is not allowed according to config
+  --> $DIR/conf_disallowed_type.rs:31:17
+   |
+LL |     static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `std::sync::atomic::AtomicU32` is not allowed according to config
+  --> $DIR/conf_disallowed_type.rs:31:48
+   |
+LL |     static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1);
+   |                                                ^^^^^^^^^^^^^^^^^^^^^^
+
+error: `syn::TypePath` is not allowed according to config
+  --> $DIR/conf_disallowed_type.rs:32:43
+   |
+LL |     let _: std::collections::BTreeMap<(), syn::TypePath> = Default::default();
+   |                                           ^^^^^^^^^^^^^
+
+error: `proc_macro2::Ident` is not allowed according to config
+  --> $DIR/conf_disallowed_type.rs:33:13
+   |
+LL |     let _ = syn::Ident::new("", todo!());
+   |             ^^^^^^^^^^
+
+error: aborting due to 14 previous errors
+
index a7be00426c41c4896cea47a60f534b172db1e648..e0029ebeb27ac4ad94966097b9c02f5914e9a4b5 100644 (file)
@@ -1,4 +1,4 @@
-error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `avoid-breaking-exported-api`, `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `third-party` at line 5 column 1
+error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `avoid-breaking-exported-api`, `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `disallowed-types`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `standard-macro-braces`, `enforced-import-renames`, `allowed-scripts`, `third-party` at line 5 column 1
 
 error: aborting due to previous error
 
index e989de654045632a1a496859c9cff7640742492a..2180f848d62cd256f7538d100d6cf5c634398ec2 100644 (file)
@@ -1,4 +1,4 @@
-#![allow(non_fmt_panic)]
+#![allow(non_fmt_panics)]
 
 macro_rules! assert_const {
     ($len:expr) => {
@@ -28,4 +28,7 @@ fn main() {
     debug_assert!(false); // #3948
     assert_const!(3);
     assert_const!(-1);
+
+    // Don't lint on this:
+    assert!(cfg!(feature = "hey") || cfg!(not(feature = "asdf")));
 }
index d4470d3f40708517027b62f158c11c692b70ecaf..170955e726cc573853764fbaaf16b187450bada7 100644 (file)
@@ -106,3 +106,10 @@ macro_rules! field_reassign_with_default {
         }
     };
 }
+
+#[macro_export]
+macro_rules! default_numeric_fallback {
+    () => {
+        let x = 22;
+    };
+}
diff --git a/src/tools/clippy/tests/ui/auxiliary/non-exhaustive-enum.rs b/src/tools/clippy/tests/ui/auxiliary/non-exhaustive-enum.rs
new file mode 100644 (file)
index 0000000..420232f
--- /dev/null
@@ -0,0 +1,8 @@
+// Stripped down version of the ErrorKind enum of std
+#[non_exhaustive]
+pub enum ErrorKind {
+    NotFound,
+    PermissionDenied,
+    #[doc(hidden)]
+    Uncategorized,
+}
index cb15bdd2f1b2d4cca8383b2967a535ee3d3ae20f..57d7139fef5683d7652d5a7c968b25326564fd6a 100644 (file)
@@ -43,3 +43,15 @@ fn issue_1647_ref_mut() {
     let ref mut baz = 0;
     if let Some(ref mut quux) = Some(42) {}
 }
+
+mod tests {
+    fn issue_7305() {
+        // `blackisted_name` lint should not be triggered inside of the test code.
+        let foo = 0;
+
+        // Check that even in nested functions warning is still not triggere.
+        fn nested() {
+            let foo = 0;
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/false_positives.rs b/src/tools/clippy/tests/ui/branches_sharing_code/false_positives.rs
new file mode 100644 (file)
index 0000000..7f42df4
--- /dev/null
@@ -0,0 +1,28 @@
+#![allow(dead_code)]
+#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+
+// ##################################
+// # Issue clippy#7369
+// ##################################
+#[derive(Debug)]
+pub struct FooBar {
+    foo: Vec<u32>,
+}
+
+impl FooBar {
+    pub fn bar(&mut self) {
+        if true {
+            self.foo.pop();
+        } else {
+            self.baz();
+
+            self.foo.pop();
+
+            self.baz()
+        }
+    }
+
+    fn baz(&mut self) {}
+}
+
+fn main() {}
index bf68a7bbbf1d4e1b398b25216a0ee8009cb7dde0..46b7833f42804c2b55787d49b947e9fca45fcc38 100644 (file)
@@ -6,6 +6,6 @@
 fn main() {
     let s = String::from("String");
     s.as_bytes().get(3);
-    &s.as_bytes().get(3);
+    let _ = &s.as_bytes().get(3);
     s[..].as_bytes().get(3);
 }
index 629812cc02cb899961fb384c7d51cb698713a698..c5e983d4d4e00d1c0c9dd803f70cd95b45b7cf95 100644 (file)
@@ -6,6 +6,6 @@
 fn main() {
     let s = String::from("String");
     s.bytes().nth(3);
-    &s.bytes().nth(3);
+    let _ = &s.bytes().nth(3);
     s[..].bytes().nth(3);
 }
index 9a5742928cd617da55eadb98ded6f012b9553f3e..536decf5e7fc49bf8ce585585ef35d02c8c49abc 100644 (file)
@@ -7,10 +7,10 @@ LL |     s.bytes().nth(3);
    = note: `-D clippy::bytes-nth` implied by `-D warnings`
 
 error: called `.byte().nth()` on a `String`
-  --> $DIR/bytes_nth.rs:9:6
+  --> $DIR/bytes_nth.rs:9:14
    |
-LL |     &s.bytes().nth(3);
-   |      ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
+LL |     let _ = &s.bytes().nth(3);
+   |              ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
 
 error: called `.byte().nth()` on a `str`
   --> $DIR/bytes_nth.rs:10:5
index fb4589a48ec428b9be229534f7cbeda3ccf5e822..8b2c318acf84e108982231e08c281889057757ba 100644 (file)
@@ -5,7 +5,7 @@ LL |     for<'a> Dst<A + 'a>: Sized,
    |                 ^^^^^^ help: use `dyn`: `dyn A + 'a`
    |
    = note: `-D bare-trait-objects` implied by `-D warnings`
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: trait objects without an explicit `dyn` are deprecated
@@ -14,7 +14,7 @@ error: trait objects without an explicit `dyn` are deprecated
 LL |     let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
    |                ^ help: use `dyn`: `dyn A`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: trait objects without an explicit `dyn` are deprecated
@@ -23,7 +23,7 @@ error: trait objects without an explicit `dyn` are deprecated
 LL |     let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
    |                                                         ^ help: use `dyn`: `dyn A`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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>
 
 error: aborting due to 3 previous errors
index f8c866a49aa20015be08faee7ade41ec0e49af06..8d9a1af8ff1180b50e824588b55bbcddc0cb93ea 100644 (file)
@@ -7,7 +7,7 @@
 struct Foo {}
 
 impl Foo {
-    fn foo() -> Self {
+    fn new() -> Self {
         impl Foo {
             fn bar() {}
         }
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7340.rs b/src/tools/clippy/tests/ui/crashes/ice-7340.rs
new file mode 100644 (file)
index 0000000..7d2351d
--- /dev/null
@@ -0,0 +1,6 @@
+#![allow(clippy::no_effect)]
+
+fn main() {
+    const CONSTANT: usize = 8;
+    [1; 1 % CONSTANT];
+}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7410.rs b/src/tools/clippy/tests/ui/crashes/ice-7410.rs
new file mode 100644 (file)
index 0000000..aaa422d
--- /dev/null
@@ -0,0 +1,31 @@
+// compile-flags: -Clink-arg=-nostartfiles
+// ignore-macos
+// ignore-windows
+
+#![feature(lang_items, start, libc)]
+#![no_std]
+#![allow(clippy::redundant_pattern_matching)]
+
+use core::panic::PanicInfo;
+
+struct S;
+
+impl Drop for S {
+    fn drop(&mut self) {}
+}
+
+#[start]
+fn main(argc: isize, argv: *const *const u8) -> isize {
+    if let Some(_) = Some(S) {
+    } else {
+    }
+    0
+}
+
+#[panic_handler]
+fn panic(_info: &PanicInfo) -> ! {
+    loop {}
+}
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7423.rs b/src/tools/clippy/tests/ui/crashes/ice-7423.rs
new file mode 100644 (file)
index 0000000..31340b0
--- /dev/null
@@ -0,0 +1,13 @@
+pub trait Trait {
+    fn f();
+}
+
+impl Trait for usize {
+    fn f() {
+        extern "C" {
+            fn g() -> usize;
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback.rs b/src/tools/clippy/tests/ui/default_numeric_fallback.rs
deleted file mode 100644 (file)
index 4346887..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-#![warn(clippy::default_numeric_fallback)]
-#![allow(unused)]
-#![allow(clippy::never_loop)]
-#![allow(clippy::no_effect)]
-#![allow(clippy::unnecessary_operation)]
-#![allow(clippy::branches_sharing_code)]
-
-mod basic_expr {
-    fn test() {
-        // Should lint unsuffixed literals typed `i32`.
-        let x = 22;
-        let x = [1, 2, 3];
-        let x = if true { (1, 2) } else { (3, 4) };
-        let x = match 1 {
-            1 => 1,
-            _ => 2,
-        };
-
-        // Should lint unsuffixed literals typed `f64`.
-        let x = 0.12;
-
-        // Should NOT lint suffixed literals.
-        let x = 22_i32;
-        let x = 0.12_f64;
-
-        // Should NOT lint literals in init expr if `Local` has a type annotation.
-        let x: f64 = 0.1;
-        let x: [i32; 3] = [1, 2, 3];
-        let x: (i32, i32) = if true { (1, 2) } else { (3, 4) };
-        let x: _ = 1;
-    }
-}
-
-mod nested_local {
-    fn test() {
-        let x: _ = {
-            // Should lint this because this literal is not bound to any types.
-            let y = 1;
-
-            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
-            1
-        };
-
-        let x: _ = if true {
-            // Should lint this because this literal is not bound to any types.
-            let y = 1;
-
-            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
-            1
-        } else {
-            // Should lint this because this literal is not bound to any types.
-            let y = 1;
-
-            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
-            2
-        };
-    }
-}
-
-mod function_def {
-    fn ret_i32() -> i32 {
-        // Even though the output type is specified,
-        // this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
-        1
-    }
-
-    fn test() {
-        // Should lint this because return type is inferred to `i32` and NOT bound to a concrete
-        // type.
-        let f = || -> _ { 1 };
-
-        // Even though the output type is specified,
-        // this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
-        let f = || -> i32 { 1 };
-    }
-}
-
-mod function_calls {
-    fn concrete_arg(x: i32) {}
-
-    fn generic_arg<T>(t: T) {}
-
-    fn test() {
-        // Should NOT lint this because the argument type is bound to a concrete type.
-        concrete_arg(1);
-
-        // Should lint this because the argument type is inferred to `i32` and NOT bound to a concrete type.
-        generic_arg(1);
-
-        // Should lint this because the argument type is inferred to `i32` and NOT bound to a concrete type.
-        let x: _ = generic_arg(1);
-    }
-}
-
-mod struct_ctor {
-    struct ConcreteStruct {
-        x: i32,
-    }
-
-    struct GenericStruct<T> {
-        x: T,
-    }
-
-    fn test() {
-        // Should NOT lint this because the field type is bound to a concrete type.
-        ConcreteStruct { x: 1 };
-
-        // Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type.
-        GenericStruct { x: 1 };
-
-        // Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type.
-        let _ = GenericStruct { x: 1 };
-    }
-}
-
-mod method_calls {
-    struct StructForMethodCallTest {}
-
-    impl StructForMethodCallTest {
-        fn concrete_arg(&self, x: i32) {}
-
-        fn generic_arg<T>(&self, t: T) {}
-    }
-
-    fn test() {
-        let s = StructForMethodCallTest {};
-
-        // Should NOT lint this because the argument type is bound to a concrete type.
-        s.concrete_arg(1);
-
-        // Should lint this because the argument type is bound to a concrete type.
-        s.generic_arg(1);
-    }
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback.stderr b/src/tools/clippy/tests/ui/default_numeric_fallback.stderr
deleted file mode 100644 (file)
index d1c4c82..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:11:17
-   |
-LL |         let x = 22;
-   |                 ^^ help: consider adding suffix: `22_i32`
-   |
-   = note: `-D clippy::default-numeric-fallback` implied by `-D warnings`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:12:18
-   |
-LL |         let x = [1, 2, 3];
-   |                  ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:12:21
-   |
-LL |         let x = [1, 2, 3];
-   |                     ^ help: consider adding suffix: `2_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:12:24
-   |
-LL |         let x = [1, 2, 3];
-   |                        ^ help: consider adding suffix: `3_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:13:28
-   |
-LL |         let x = if true { (1, 2) } else { (3, 4) };
-   |                            ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:13:31
-   |
-LL |         let x = if true { (1, 2) } else { (3, 4) };
-   |                               ^ help: consider adding suffix: `2_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:13:44
-   |
-LL |         let x = if true { (1, 2) } else { (3, 4) };
-   |                                            ^ help: consider adding suffix: `3_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:13:47
-   |
-LL |         let x = if true { (1, 2) } else { (3, 4) };
-   |                                               ^ help: consider adding suffix: `4_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:14:23
-   |
-LL |         let x = match 1 {
-   |                       ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:15:13
-   |
-LL |             1 => 1,
-   |             ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:15:18
-   |
-LL |             1 => 1,
-   |                  ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:16:18
-   |
-LL |             _ => 2,
-   |                  ^ help: consider adding suffix: `2_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:20:17
-   |
-LL |         let x = 0.12;
-   |                 ^^^^ help: consider adding suffix: `0.12_f64`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:38:21
-   |
-LL |             let y = 1;
-   |                     ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:46:21
-   |
-LL |             let y = 1;
-   |                     ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:52:21
-   |
-LL |             let y = 1;
-   |                     ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:64:9
-   |
-LL |         1
-   |         ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:70:27
-   |
-LL |         let f = || -> _ { 1 };
-   |                           ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:74:29
-   |
-LL |         let f = || -> i32 { 1 };
-   |                             ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:88:21
-   |
-LL |         generic_arg(1);
-   |                     ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:91:32
-   |
-LL |         let x: _ = generic_arg(1);
-   |                                ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:109:28
-   |
-LL |         GenericStruct { x: 1 };
-   |                            ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:112:36
-   |
-LL |         let _ = GenericStruct { x: 1 };
-   |                                    ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:132:23
-   |
-LL |         s.generic_arg(1);
-   |                       ^ help: consider adding suffix: `1_i32`
-
-error: aborting due to 24 previous errors
-
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed
new file mode 100644 (file)
index 0000000..1b0e754
--- /dev/null
@@ -0,0 +1,174 @@
+// run-rustfix
+// aux-build:macro_rules.rs
+
+#![warn(clippy::default_numeric_fallback)]
+#![allow(unused)]
+#![allow(clippy::never_loop)]
+#![allow(clippy::no_effect)]
+#![allow(clippy::unnecessary_operation)]
+#![allow(clippy::branches_sharing_code)]
+#![allow(clippy::match_single_binding)]
+
+#[macro_use]
+extern crate macro_rules;
+
+mod basic_expr {
+    fn test() {
+        // Should lint unsuffixed literals typed `f64`.
+        let x = 0.12_f64;
+        let x = [1.0_f64, 2.0_f64, 3.0_f64];
+        let x = if true { (1.0_f64, 2.0_f64) } else { (3.0_f64, 4.0_f64) };
+        let x = match 1.0_f64 {
+            _ => 1.0_f64,
+        };
+
+        // Should NOT lint suffixed literals.
+        let x = 0.12_f64;
+
+        // Should NOT lint literals in init expr if `Local` has a type annotation.
+        let x: f64 = 0.1;
+        let x: [f64; 3] = [1., 2., 3.];
+        let x: (f64, f64) = if true { (1., 2.) } else { (3., 4.) };
+        let x: _ = 1.;
+    }
+}
+
+mod nested_local {
+    fn test() {
+        let x: _ = {
+            // Should lint this because this literal is not bound to any types.
+            let y = 1.0_f64;
+
+            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+            1.
+        };
+
+        let x: _ = if true {
+            // Should lint this because this literal is not bound to any types.
+            let y = 1.0_f64;
+
+            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+            1.
+        } else {
+            // Should lint this because this literal is not bound to any types.
+            let y = 1.0_f64;
+
+            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+            2.
+        };
+    }
+}
+
+mod function_def {
+    fn ret_f64() -> f64 {
+        // Even though the output type is specified,
+        // this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
+        1.0_f64
+    }
+
+    fn test() {
+        // Should lint this because return type is inferred to `f64` and NOT bound to a concrete
+        // type.
+        let f = || -> _ { 1.0_f64 };
+
+        // Even though the output type is specified,
+        // this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
+        let f = || -> f64 { 1.0_f64 };
+    }
+}
+
+mod function_calls {
+    fn concrete_arg(f: f64) {}
+
+    fn generic_arg<T>(t: T) {}
+
+    fn test() {
+        // Should NOT lint this because the argument type is bound to a concrete type.
+        concrete_arg(1.);
+
+        // Should lint this because the argument type is inferred to `f64` and NOT bound to a concrete type.
+        generic_arg(1.0_f64);
+
+        // Should lint this because the argument type is inferred to `f64` and NOT bound to a concrete type.
+        let x: _ = generic_arg(1.0_f64);
+    }
+}
+
+mod struct_ctor {
+    struct ConcreteStruct {
+        x: f64,
+    }
+
+    struct GenericStruct<T> {
+        x: T,
+    }
+
+    fn test() {
+        // Should NOT lint this because the field type is bound to a concrete type.
+        ConcreteStruct { x: 1. };
+
+        // Should lint this because the field type is inferred to `f64` and NOT bound to a concrete type.
+        GenericStruct { x: 1.0_f64 };
+
+        // Should lint this because the field type is inferred to `f64` and NOT bound to a concrete type.
+        let _ = GenericStruct { x: 1.0_f64 };
+    }
+}
+
+mod enum_ctor {
+    enum ConcreteEnum {
+        X(f64),
+    }
+
+    enum GenericEnum<T> {
+        X(T),
+    }
+
+    fn test() {
+        // Should NOT lint this because the field type is bound to a concrete type.
+        ConcreteEnum::X(1.);
+
+        // Should lint this because the field type is inferred to `f64` and NOT bound to a concrete type.
+        GenericEnum::X(1.0_f64);
+    }
+}
+
+mod method_calls {
+    struct StructForMethodCallTest {}
+
+    impl StructForMethodCallTest {
+        fn concrete_arg(&self, f: f64) {}
+
+        fn generic_arg<T>(&self, t: T) {}
+    }
+
+    fn test() {
+        let s = StructForMethodCallTest {};
+
+        // Should NOT lint this because the argument type is bound to a concrete type.
+        s.concrete_arg(1.);
+
+        // Should lint this because the argument type is bound to a concrete type.
+        s.generic_arg(1.0_f64);
+    }
+}
+
+mod in_macro {
+    macro_rules! internal_macro {
+        () => {
+            let x = 22.0_f64;
+        };
+    }
+
+    // Should lint in internal macro.
+    fn internal() {
+        internal_macro!();
+    }
+
+    // Should NOT lint in external macro.
+    fn external() {
+        default_numeric_fallback!();
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs
new file mode 100644 (file)
index 0000000..e968777
--- /dev/null
@@ -0,0 +1,174 @@
+// run-rustfix
+// aux-build:macro_rules.rs
+
+#![warn(clippy::default_numeric_fallback)]
+#![allow(unused)]
+#![allow(clippy::never_loop)]
+#![allow(clippy::no_effect)]
+#![allow(clippy::unnecessary_operation)]
+#![allow(clippy::branches_sharing_code)]
+#![allow(clippy::match_single_binding)]
+
+#[macro_use]
+extern crate macro_rules;
+
+mod basic_expr {
+    fn test() {
+        // Should lint unsuffixed literals typed `f64`.
+        let x = 0.12;
+        let x = [1., 2., 3.];
+        let x = if true { (1., 2.) } else { (3., 4.) };
+        let x = match 1. {
+            _ => 1.,
+        };
+
+        // Should NOT lint suffixed literals.
+        let x = 0.12_f64;
+
+        // Should NOT lint literals in init expr if `Local` has a type annotation.
+        let x: f64 = 0.1;
+        let x: [f64; 3] = [1., 2., 3.];
+        let x: (f64, f64) = if true { (1., 2.) } else { (3., 4.) };
+        let x: _ = 1.;
+    }
+}
+
+mod nested_local {
+    fn test() {
+        let x: _ = {
+            // Should lint this because this literal is not bound to any types.
+            let y = 1.;
+
+            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+            1.
+        };
+
+        let x: _ = if true {
+            // Should lint this because this literal is not bound to any types.
+            let y = 1.;
+
+            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+            1.
+        } else {
+            // Should lint this because this literal is not bound to any types.
+            let y = 1.;
+
+            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+            2.
+        };
+    }
+}
+
+mod function_def {
+    fn ret_f64() -> f64 {
+        // Even though the output type is specified,
+        // this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
+        1.
+    }
+
+    fn test() {
+        // Should lint this because return type is inferred to `f64` and NOT bound to a concrete
+        // type.
+        let f = || -> _ { 1. };
+
+        // Even though the output type is specified,
+        // this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
+        let f = || -> f64 { 1. };
+    }
+}
+
+mod function_calls {
+    fn concrete_arg(f: f64) {}
+
+    fn generic_arg<T>(t: T) {}
+
+    fn test() {
+        // Should NOT lint this because the argument type is bound to a concrete type.
+        concrete_arg(1.);
+
+        // Should lint this because the argument type is inferred to `f64` and NOT bound to a concrete type.
+        generic_arg(1.);
+
+        // Should lint this because the argument type is inferred to `f64` and NOT bound to a concrete type.
+        let x: _ = generic_arg(1.);
+    }
+}
+
+mod struct_ctor {
+    struct ConcreteStruct {
+        x: f64,
+    }
+
+    struct GenericStruct<T> {
+        x: T,
+    }
+
+    fn test() {
+        // Should NOT lint this because the field type is bound to a concrete type.
+        ConcreteStruct { x: 1. };
+
+        // Should lint this because the field type is inferred to `f64` and NOT bound to a concrete type.
+        GenericStruct { x: 1. };
+
+        // Should lint this because the field type is inferred to `f64` and NOT bound to a concrete type.
+        let _ = GenericStruct { x: 1. };
+    }
+}
+
+mod enum_ctor {
+    enum ConcreteEnum {
+        X(f64),
+    }
+
+    enum GenericEnum<T> {
+        X(T),
+    }
+
+    fn test() {
+        // Should NOT lint this because the field type is bound to a concrete type.
+        ConcreteEnum::X(1.);
+
+        // Should lint this because the field type is inferred to `f64` and NOT bound to a concrete type.
+        GenericEnum::X(1.);
+    }
+}
+
+mod method_calls {
+    struct StructForMethodCallTest {}
+
+    impl StructForMethodCallTest {
+        fn concrete_arg(&self, f: f64) {}
+
+        fn generic_arg<T>(&self, t: T) {}
+    }
+
+    fn test() {
+        let s = StructForMethodCallTest {};
+
+        // Should NOT lint this because the argument type is bound to a concrete type.
+        s.concrete_arg(1.);
+
+        // Should lint this because the argument type is bound to a concrete type.
+        s.generic_arg(1.);
+    }
+}
+
+mod in_macro {
+    macro_rules! internal_macro {
+        () => {
+            let x = 22.;
+        };
+    }
+
+    // Should lint in internal macro.
+    fn internal() {
+        internal_macro!();
+    }
+
+    // Should NOT lint in external macro.
+    fn external() {
+        default_numeric_fallback!();
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.stderr b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.stderr
new file mode 100644 (file)
index 0000000..961c7cb
--- /dev/null
@@ -0,0 +1,147 @@
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:18:17
+   |
+LL |         let x = 0.12;
+   |                 ^^^^ help: consider adding suffix: `0.12_f64`
+   |
+   = note: `-D clippy::default-numeric-fallback` implied by `-D warnings`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:19:18
+   |
+LL |         let x = [1., 2., 3.];
+   |                  ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:19:22
+   |
+LL |         let x = [1., 2., 3.];
+   |                      ^^ help: consider adding suffix: `2.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:19:26
+   |
+LL |         let x = [1., 2., 3.];
+   |                          ^^ help: consider adding suffix: `3.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:20:28
+   |
+LL |         let x = if true { (1., 2.) } else { (3., 4.) };
+   |                            ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:20:32
+   |
+LL |         let x = if true { (1., 2.) } else { (3., 4.) };
+   |                                ^^ help: consider adding suffix: `2.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:20:46
+   |
+LL |         let x = if true { (1., 2.) } else { (3., 4.) };
+   |                                              ^^ help: consider adding suffix: `3.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:20:50
+   |
+LL |         let x = if true { (1., 2.) } else { (3., 4.) };
+   |                                                  ^^ help: consider adding suffix: `4.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:21:23
+   |
+LL |         let x = match 1. {
+   |                       ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:22:18
+   |
+LL |             _ => 1.,
+   |                  ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:40:21
+   |
+LL |             let y = 1.;
+   |                     ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:48:21
+   |
+LL |             let y = 1.;
+   |                     ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:54:21
+   |
+LL |             let y = 1.;
+   |                     ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:66:9
+   |
+LL |         1.
+   |         ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:72:27
+   |
+LL |         let f = || -> _ { 1. };
+   |                           ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:76:29
+   |
+LL |         let f = || -> f64 { 1. };
+   |                             ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:90:21
+   |
+LL |         generic_arg(1.);
+   |                     ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:93:32
+   |
+LL |         let x: _ = generic_arg(1.);
+   |                                ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:111:28
+   |
+LL |         GenericStruct { x: 1. };
+   |                            ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:114:36
+   |
+LL |         let _ = GenericStruct { x: 1. };
+   |                                    ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:132:24
+   |
+LL |         GenericEnum::X(1.);
+   |                        ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:152:23
+   |
+LL |         s.generic_arg(1.);
+   |                       ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_f64.rs:159:21
+   |
+LL |             let x = 22.;
+   |                     ^^^ help: consider adding suffix: `22.0_f64`
+...
+LL |         internal_macro!();
+   |         ------------------ in this macro invocation
+   |
+   = note: this error originates in the macro `internal_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 23 previous errors
+
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
new file mode 100644 (file)
index 0000000..55c082f
--- /dev/null
@@ -0,0 +1,173 @@
+// run-rustfix
+// aux-build:macro_rules.rs
+
+#![warn(clippy::default_numeric_fallback)]
+#![allow(unused)]
+#![allow(clippy::never_loop)]
+#![allow(clippy::no_effect)]
+#![allow(clippy::unnecessary_operation)]
+#![allow(clippy::branches_sharing_code)]
+
+#[macro_use]
+extern crate macro_rules;
+
+mod basic_expr {
+    fn test() {
+        // Should lint unsuffixed literals typed `i32`.
+        let x = 22_i32;
+        let x = [1_i32, 2_i32, 3_i32];
+        let x = if true { (1_i32, 2_i32) } else { (3_i32, 4_i32) };
+        let x = match 1_i32 {
+            1_i32 => 1_i32,
+            _ => 2_i32,
+        };
+
+        // Should NOT lint suffixed literals.
+        let x = 22_i32;
+
+        // Should NOT lint literals in init expr if `Local` has a type annotation.
+        let x: [i32; 3] = [1, 2, 3];
+        let x: (i32, i32) = if true { (1, 2) } else { (3, 4) };
+        let x: _ = 1;
+    }
+}
+
+mod nested_local {
+    fn test() {
+        let x: _ = {
+            // Should lint this because this literal is not bound to any types.
+            let y = 1_i32;
+
+            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+            1
+        };
+
+        let x: _ = if true {
+            // Should lint this because this literal is not bound to any types.
+            let y = 1_i32;
+
+            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+            1
+        } else {
+            // Should lint this because this literal is not bound to any types.
+            let y = 1_i32;
+
+            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+            2
+        };
+    }
+}
+
+mod function_def {
+    fn ret_i32() -> i32 {
+        // Even though the output type is specified,
+        // this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
+        1_i32
+    }
+
+    fn test() {
+        // Should lint this because return type is inferred to `i32` and NOT bound to a concrete
+        // type.
+        let f = || -> _ { 1_i32 };
+
+        // Even though the output type is specified,
+        // this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
+        let f = || -> i32 { 1_i32 };
+    }
+}
+
+mod function_calls {
+    fn concrete_arg(x: i32) {}
+
+    fn generic_arg<T>(t: T) {}
+
+    fn test() {
+        // Should NOT lint this because the argument type is bound to a concrete type.
+        concrete_arg(1);
+
+        // Should lint this because the argument type is inferred to `i32` and NOT bound to a concrete type.
+        generic_arg(1_i32);
+
+        // Should lint this because the argument type is inferred to `i32` and NOT bound to a concrete type.
+        let x: _ = generic_arg(1_i32);
+    }
+}
+
+mod struct_ctor {
+    struct ConcreteStruct {
+        x: i32,
+    }
+
+    struct GenericStruct<T> {
+        x: T,
+    }
+
+    fn test() {
+        // Should NOT lint this because the field type is bound to a concrete type.
+        ConcreteStruct { x: 1 };
+
+        // Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type.
+        GenericStruct { x: 1_i32 };
+
+        // Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type.
+        let _ = GenericStruct { x: 1_i32 };
+    }
+}
+
+mod enum_ctor {
+    enum ConcreteEnum {
+        X(i32),
+    }
+
+    enum GenericEnum<T> {
+        X(T),
+    }
+
+    fn test() {
+        // Should NOT lint this because the field type is bound to a concrete type.
+        ConcreteEnum::X(1);
+
+        // Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type.
+        GenericEnum::X(1_i32);
+    }
+}
+
+mod method_calls {
+    struct StructForMethodCallTest {}
+
+    impl StructForMethodCallTest {
+        fn concrete_arg(&self, x: i32) {}
+
+        fn generic_arg<T>(&self, t: T) {}
+    }
+
+    fn test() {
+        let s = StructForMethodCallTest {};
+
+        // Should NOT lint this because the argument type is bound to a concrete type.
+        s.concrete_arg(1);
+
+        // Should lint this because the argument type is bound to a concrete type.
+        s.generic_arg(1_i32);
+    }
+}
+
+mod in_macro {
+    macro_rules! internal_macro {
+        () => {
+            let x = 22_i32;
+        };
+    }
+
+    // Should lint in internal macro.
+    fn internal() {
+        internal_macro!();
+    }
+
+    // Should NOT lint in external macro.
+    fn external() {
+        default_numeric_fallback!();
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
new file mode 100644 (file)
index 0000000..e0a4828
--- /dev/null
@@ -0,0 +1,173 @@
+// run-rustfix
+// aux-build:macro_rules.rs
+
+#![warn(clippy::default_numeric_fallback)]
+#![allow(unused)]
+#![allow(clippy::never_loop)]
+#![allow(clippy::no_effect)]
+#![allow(clippy::unnecessary_operation)]
+#![allow(clippy::branches_sharing_code)]
+
+#[macro_use]
+extern crate macro_rules;
+
+mod basic_expr {
+    fn test() {
+        // Should lint unsuffixed literals typed `i32`.
+        let x = 22;
+        let x = [1, 2, 3];
+        let x = if true { (1, 2) } else { (3, 4) };
+        let x = match 1 {
+            1 => 1,
+            _ => 2,
+        };
+
+        // Should NOT lint suffixed literals.
+        let x = 22_i32;
+
+        // Should NOT lint literals in init expr if `Local` has a type annotation.
+        let x: [i32; 3] = [1, 2, 3];
+        let x: (i32, i32) = if true { (1, 2) } else { (3, 4) };
+        let x: _ = 1;
+    }
+}
+
+mod nested_local {
+    fn test() {
+        let x: _ = {
+            // Should lint this because this literal is not bound to any types.
+            let y = 1;
+
+            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+            1
+        };
+
+        let x: _ = if true {
+            // Should lint this because this literal is not bound to any types.
+            let y = 1;
+
+            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+            1
+        } else {
+            // Should lint this because this literal is not bound to any types.
+            let y = 1;
+
+            // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+            2
+        };
+    }
+}
+
+mod function_def {
+    fn ret_i32() -> i32 {
+        // Even though the output type is specified,
+        // this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
+        1
+    }
+
+    fn test() {
+        // Should lint this because return type is inferred to `i32` and NOT bound to a concrete
+        // type.
+        let f = || -> _ { 1 };
+
+        // Even though the output type is specified,
+        // this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
+        let f = || -> i32 { 1 };
+    }
+}
+
+mod function_calls {
+    fn concrete_arg(x: i32) {}
+
+    fn generic_arg<T>(t: T) {}
+
+    fn test() {
+        // Should NOT lint this because the argument type is bound to a concrete type.
+        concrete_arg(1);
+
+        // Should lint this because the argument type is inferred to `i32` and NOT bound to a concrete type.
+        generic_arg(1);
+
+        // Should lint this because the argument type is inferred to `i32` and NOT bound to a concrete type.
+        let x: _ = generic_arg(1);
+    }
+}
+
+mod struct_ctor {
+    struct ConcreteStruct {
+        x: i32,
+    }
+
+    struct GenericStruct<T> {
+        x: T,
+    }
+
+    fn test() {
+        // Should NOT lint this because the field type is bound to a concrete type.
+        ConcreteStruct { x: 1 };
+
+        // Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type.
+        GenericStruct { x: 1 };
+
+        // Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type.
+        let _ = GenericStruct { x: 1 };
+    }
+}
+
+mod enum_ctor {
+    enum ConcreteEnum {
+        X(i32),
+    }
+
+    enum GenericEnum<T> {
+        X(T),
+    }
+
+    fn test() {
+        // Should NOT lint this because the field type is bound to a concrete type.
+        ConcreteEnum::X(1);
+
+        // Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type.
+        GenericEnum::X(1);
+    }
+}
+
+mod method_calls {
+    struct StructForMethodCallTest {}
+
+    impl StructForMethodCallTest {
+        fn concrete_arg(&self, x: i32) {}
+
+        fn generic_arg<T>(&self, t: T) {}
+    }
+
+    fn test() {
+        let s = StructForMethodCallTest {};
+
+        // Should NOT lint this because the argument type is bound to a concrete type.
+        s.concrete_arg(1);
+
+        // Should lint this because the argument type is bound to a concrete type.
+        s.generic_arg(1);
+    }
+}
+
+mod in_macro {
+    macro_rules! internal_macro {
+        () => {
+            let x = 22;
+        };
+    }
+
+    // Should lint in internal macro.
+    fn internal() {
+        internal_macro!();
+    }
+
+    // Should NOT lint in external macro.
+    fn external() {
+        default_numeric_fallback!();
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr
new file mode 100644 (file)
index 0000000..5edf48b
--- /dev/null
@@ -0,0 +1,159 @@
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:17:17
+   |
+LL |         let x = 22;
+   |                 ^^ help: consider adding suffix: `22_i32`
+   |
+   = note: `-D clippy::default-numeric-fallback` implied by `-D warnings`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:18:18
+   |
+LL |         let x = [1, 2, 3];
+   |                  ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:18:21
+   |
+LL |         let x = [1, 2, 3];
+   |                     ^ help: consider adding suffix: `2_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:18:24
+   |
+LL |         let x = [1, 2, 3];
+   |                        ^ help: consider adding suffix: `3_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:19:28
+   |
+LL |         let x = if true { (1, 2) } else { (3, 4) };
+   |                            ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:19:31
+   |
+LL |         let x = if true { (1, 2) } else { (3, 4) };
+   |                               ^ help: consider adding suffix: `2_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:19:44
+   |
+LL |         let x = if true { (1, 2) } else { (3, 4) };
+   |                                            ^ help: consider adding suffix: `3_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:19:47
+   |
+LL |         let x = if true { (1, 2) } else { (3, 4) };
+   |                                               ^ help: consider adding suffix: `4_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:20:23
+   |
+LL |         let x = match 1 {
+   |                       ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:21:13
+   |
+LL |             1 => 1,
+   |             ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:21:18
+   |
+LL |             1 => 1,
+   |                  ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:22:18
+   |
+LL |             _ => 2,
+   |                  ^ help: consider adding suffix: `2_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:39:21
+   |
+LL |             let y = 1;
+   |                     ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:47:21
+   |
+LL |             let y = 1;
+   |                     ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:53:21
+   |
+LL |             let y = 1;
+   |                     ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:65:9
+   |
+LL |         1
+   |         ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:71:27
+   |
+LL |         let f = || -> _ { 1 };
+   |                           ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:75:29
+   |
+LL |         let f = || -> i32 { 1 };
+   |                             ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:89:21
+   |
+LL |         generic_arg(1);
+   |                     ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:92:32
+   |
+LL |         let x: _ = generic_arg(1);
+   |                                ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:110:28
+   |
+LL |         GenericStruct { x: 1 };
+   |                            ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:113:36
+   |
+LL |         let _ = GenericStruct { x: 1 };
+   |                                    ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:131:24
+   |
+LL |         GenericEnum::X(1);
+   |                        ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:151:23
+   |
+LL |         s.generic_arg(1);
+   |                       ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:158:21
+   |
+LL |             let x = 22;
+   |                     ^^ help: consider adding suffix: `22_i32`
+...
+LL |         internal_macro!();
+   |         ------------------ in this macro invocation
+   |
+   = note: this error originates in the macro `internal_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 25 previous errors
+
index 03c9f438891363fe3250e951db20ad94299e0365..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
@@ -84,13 +84,13 @@ error: lint `clippy::filter_map` has been removed: this lint has been replaced b
 LL | #[warn(clippy::filter_map)]
    |        ^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::pub_enum_variant_names` has been removed: set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items
+error: lint `clippy::pub_enum_variant_names` has been removed: set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items
   --> $DIR/deprecated.rs:15:8
    |
 LL | #[warn(clippy::pub_enum_variant_names)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::wrong_pub_self_convention` has been removed: set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items
+error: lint `clippy::wrong_pub_self_convention` has been removed: set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items
   --> $DIR/deprecated.rs:16:8
    |
 LL | #[warn(clippy::wrong_pub_self_convention)]
diff --git a/src/tools/clippy/tests/ui/disallowed_script_idents.rs b/src/tools/clippy/tests/ui/disallowed_script_idents.rs
new file mode 100644 (file)
index 0000000..cfdda35
--- /dev/null
@@ -0,0 +1,10 @@
+#![deny(clippy::disallowed_script_idents)]
+#![allow(dead_code)]
+
+fn main() {
+    let counter = 10; // OK, latin is allowed.
+    let zähler = 10; // OK, it's still latin.
+
+    let счётчик = 10; // Cyrillic is not allowed by default.
+    let カウンタ = 10; // Same for japanese.
+}
diff --git a/src/tools/clippy/tests/ui/disallowed_script_idents.stderr b/src/tools/clippy/tests/ui/disallowed_script_idents.stderr
new file mode 100644 (file)
index 0000000..cc84dc1
--- /dev/null
@@ -0,0 +1,20 @@
+error: identifier `счётчик` has a Unicode script that is not allowed by configuration: Cyrillic
+  --> $DIR/disallowed_script_idents.rs:8:9
+   |
+LL |     let счётчик = 10; // Cyrillic is not allowed by default.
+   |         ^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/disallowed_script_idents.rs:1:9
+   |
+LL | #![deny(clippy::disallowed_script_idents)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: identifier `カウンタ` has a Unicode script that is not allowed by configuration: Katakana
+  --> $DIR/disallowed_script_idents.rs:9:9
+   |
+LL |     let カウンタ = 10; // Same for japanese.
+   |         ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/doc.rs b/src/tools/clippy/tests/ui/doc.rs
deleted file mode 100644 (file)
index c946a04..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-//! This file tests for the `DOC_MARKDOWN` lint.
-
-#![allow(dead_code, incomplete_features)]
-#![warn(clippy::doc_markdown)]
-#![feature(custom_inner_attributes, const_generics, const_evaluatable_checked, const_option)]
-#![rustfmt::skip]
-
-/// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
-/// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun
-/// which should be reported only once despite being __doubly bad__.
-/// Here be ::a::global:path.
-/// That's not code ~NotInCodeBlock~.
-/// be_sure_we_got_to_the_end_of_it
-fn foo_bar() {
-}
-
-/// That one tests multiline ticks.
-/// ```rust
-/// foo_bar FOO_BAR
-/// _foo bar_
-/// ```
-///
-/// ~~~rust
-/// foo_bar FOO_BAR
-/// _foo bar_
-/// ~~~
-/// be_sure_we_got_to_the_end_of_it
-fn multiline_codeblock() {
-}
-
-/// This _is a test for
-/// multiline
-/// emphasis_.
-/// be_sure_we_got_to_the_end_of_it
-fn test_emphasis() {
-}
-
-/// This tests units. See also #835.
-/// kiB MiB GiB TiB PiB EiB
-/// kib Mib Gib Tib Pib Eib
-/// kB MB GB TB PB EB
-/// kb Mb Gb Tb Pb Eb
-/// 32kiB 32MiB 32GiB 32TiB 32PiB 32EiB
-/// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib
-/// 32kB 32MB 32GB 32TB 32PB 32EB
-/// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb
-/// NaN
-/// be_sure_we_got_to_the_end_of_it
-fn test_units() {
-}
-
-/// This tests allowed identifiers.
-/// KiB MiB GiB TiB PiB EiB
-/// DirectX
-/// ECMAScript
-/// GPLv2 GPLv3
-/// GitHub GitLab
-/// IPv4 IPv6
-/// ClojureScript CoffeeScript JavaScript PureScript TypeScript
-/// NaN NaNs
-/// OAuth GraphQL
-/// OCaml
-/// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS
-/// WebGL
-/// TensorFlow
-/// TrueType
-/// iOS macOS
-/// TeX LaTeX BibTeX BibLaTeX
-/// MinGW
-/// CamelCase (see also #2395)
-/// be_sure_we_got_to_the_end_of_it
-fn test_allowed() {
-}
-
-/// This test has [a link_with_underscores][chunked-example] inside it. See #823.
-/// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues)
-/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
-/// It can also be [inline_link2].
-///
-/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
-/// [inline_link]: https://foobar
-/// [inline_link2]: https://foobar
-/// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and
-/// `multiline_ticks` functions.
-///
-/// expression of the type  `_ <bit_op> m <cmp_op> c` (where `<bit_op>`
-/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` ,
-/// be_sure_we_got_to_the_end_of_it
-fn main() {
-    foo_bar();
-    multiline_codeblock();
-    test_emphasis();
-    test_units();
-}
-
-/// ## CamelCaseThing
-/// Talks about `CamelCaseThing`. Titles should be ignored; see issue #897.
-///
-/// # CamelCaseThing
-///
-/// Not a title #897 CamelCaseThing
-/// be_sure_we_got_to_the_end_of_it
-fn issue897() {
-}
-
-/// I am confused by brackets? (`x_y`)
-/// I am confused by brackets? (foo `x_y`)
-/// I am confused by brackets? (`x_y` foo)
-/// be_sure_we_got_to_the_end_of_it
-fn issue900() {
-}
-
-/// Diesel queries also have a similar problem to [Iterator][iterator], where
-/// /// More talking
-/// returning them from a function requires exposing the implementation of that
-/// function. The [`helper_types`][helper_types] module exists to help with this,
-/// but you might want to hide the return type or have it conditionally change.
-/// Boxing can achieve both.
-///
-/// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html
-/// [helper_types]: ../helper_types/index.html
-/// be_sure_we_got_to_the_end_of_it
-fn issue883() {
-}
-
-/// `foo_bar
-/// baz_quz`
-/// [foo
-/// bar](https://doc.rust-lang.org/stable/std/iter/trait.IteratorFooBar.html)
-fn multiline() {
-}
-
-/** E.g., serialization of an empty list: FooBar
-```
-That's in a code block: `PackedNode`
-```
-
-And BarQuz too.
-be_sure_we_got_to_the_end_of_it
-*/
-fn issue1073() {
-}
-
-/** E.g., serialization of an empty list: FooBar
-```
-That's in a code block: PackedNode
-```
-
-And BarQuz too.
-be_sure_we_got_to_the_end_of_it
-*/
-fn issue1073_alt() {
-}
-
-/// Tests more than three quotes:
-/// ````
-/// DoNotWarn
-/// ```
-/// StillDont
-/// ````
-/// be_sure_we_got_to_the_end_of_it
-fn four_quotes() {
-}
-
-/// See [NIST SP 800-56A, revision 2].
-///
-/// [NIST SP 800-56A, revision 2]:
-///     https://github.com/rust-lang/rust-clippy/issues/902#issuecomment-261919419
-fn issue_902_comment() {}
-
-#[cfg_attr(feature = "a", doc = " ```")]
-#[cfg_attr(not(feature = "a"), doc = " ```ignore")]
-/// fn main() {
-///     let s = "localhost:10000".to_string();
-///     println!("{}", s);
-/// }
-/// ```
-fn issue_1469() {}
-
-/**
- * This is a doc comment that should not be a list
- *This would also be an error under a strict common mark interpretation
- */
-fn issue_1920() {}
-
-/// Ok: <http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels>
-///
-/// Not ok: http://www.unicode.org
-/// Not ok: https://www.unicode.org
-/// Not ok: http://www.unicode.org/
-/// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
-fn issue_1832() {}
-
-/// An iterator over mycrate::Collection's values.
-/// It should not lint a `'static` lifetime in ticks.
-fn issue_2210() {}
-
-/// This should not cause the lint to trigger:
-/// #REQ-data-family.lint_partof_exists
-fn issue_2343() {}
-
-/// This should not cause an ICE:
-/// __|_ _|__||_|
-fn pulldown_cmark_crash() {}
-
-// issue #7033 - const_evaluatable_checked ICE
-struct S<T, const N: usize>
-where [(); N.checked_next_power_of_two().unwrap()]: {
-    arr: [T; N.checked_next_power_of_two().unwrap()],
-    n: usize,
-}
-
-impl<T: Copy + Default, const N: usize> S<T, N>
-where [(); N.checked_next_power_of_two().unwrap()]: {
-    fn new() -> Self {
-        Self {
-            arr: [T::default(); N.checked_next_power_of_two().unwrap()],
-            n: 0,
-        }
-    }
-}
diff --git a/src/tools/clippy/tests/ui/doc.stderr b/src/tools/clippy/tests/ui/doc.stderr
deleted file mode 100644 (file)
index 7eab8a8..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-error: you should put `foo_bar` between ticks in the documentation
-  --> $DIR/doc.rs:8:9
-   |
-LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
-   |         ^^^^^^^
-   |
-   = note: `-D clippy::doc-markdown` implied by `-D warnings`
-
-error: you should put `foo::bar` between ticks in the documentation
-  --> $DIR/doc.rs:8:51
-   |
-LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
-   |                                                   ^^^^^^^^
-
-error: you should put `Foo::some_fun` between ticks in the documentation
-  --> $DIR/doc.rs:9:83
-   |
-LL | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun
-   |                                                                                   ^^^^^^^^^^^^^
-
-error: you should put `a::global:path` between ticks in the documentation
-  --> $DIR/doc.rs:11:15
-   |
-LL | /// Here be ::a::global:path.
-   |               ^^^^^^^^^^^^^^
-
-error: you should put `NotInCodeBlock` between ticks in the documentation
-  --> $DIR/doc.rs:12:22
-   |
-LL | /// That's not code ~NotInCodeBlock~.
-   |                      ^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:13:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:27:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:34:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:48:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:71:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `link_with_underscores` between ticks in the documentation
-  --> $DIR/doc.rs:75:22
-   |
-LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823.
-   |                      ^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `inline_link2` between ticks in the documentation
-  --> $DIR/doc.rs:78:21
-   |
-LL | /// It can also be [inline_link2].
-   |                     ^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:88:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `CamelCaseThing` between ticks in the documentation
-  --> $DIR/doc.rs:96:8
-   |
-LL | /// ## CamelCaseThing
-   |        ^^^^^^^^^^^^^^
-
-error: you should put `CamelCaseThing` between ticks in the documentation
-  --> $DIR/doc.rs:99:7
-   |
-LL | /// # CamelCaseThing
-   |       ^^^^^^^^^^^^^^
-
-error: you should put `CamelCaseThing` between ticks in the documentation
-  --> $DIR/doc.rs:101:22
-   |
-LL | /// Not a title #897 CamelCaseThing
-   |                      ^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:102:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:109:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:122:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `FooBar` between ticks in the documentation
-  --> $DIR/doc.rs:133:43
-   |
-LL | /** E.g., serialization of an empty list: FooBar
-   |                                           ^^^^^^
-
-error: you should put `BarQuz` between ticks in the documentation
-  --> $DIR/doc.rs:138:5
-   |
-LL | And BarQuz too.
-   |     ^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:139:1
-   |
-LL | be_sure_we_got_to_the_end_of_it
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `FooBar` between ticks in the documentation
-  --> $DIR/doc.rs:144:43
-   |
-LL | /** E.g., serialization of an empty list: FooBar
-   |                                           ^^^^^^
-
-error: you should put `BarQuz` between ticks in the documentation
-  --> $DIR/doc.rs:149:5
-   |
-LL | And BarQuz too.
-   |     ^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:150:1
-   |
-LL | be_sure_we_got_to_the_end_of_it
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:161:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
-  --> $DIR/doc.rs:188:13
-   |
-LL | /// Not ok: http://www.unicode.org
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
-  --> $DIR/doc.rs:189:13
-   |
-LL | /// Not ok: https://www.unicode.org
-   |             ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
-  --> $DIR/doc.rs:190:13
-   |
-LL | /// Not ok: http://www.unicode.org/
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
-  --> $DIR/doc.rs:191:13
-   |
-LL | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `mycrate::Collection` between ticks in the documentation
-  --> $DIR/doc.rs:194:22
-   |
-LL | /// An iterator over mycrate::Collection's values.
-   |                      ^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 31 previous errors
-
diff --git a/src/tools/clippy/tests/ui/doc/doc.rs b/src/tools/clippy/tests/ui/doc/doc.rs
new file mode 100644 (file)
index 0000000..8afef6b
--- /dev/null
@@ -0,0 +1,221 @@
+//! This file tests for the `DOC_MARKDOWN` lint.
+
+#![allow(dead_code, incomplete_features)]
+#![warn(clippy::doc_markdown)]
+#![feature(custom_inner_attributes, const_generics, const_evaluatable_checked, const_option)]
+#![rustfmt::skip]
+
+/// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
+/// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun
+/// which should be reported only once despite being __doubly bad__.
+/// Here be ::a::global:path.
+/// That's not code ~NotInCodeBlock~.
+/// be_sure_we_got_to_the_end_of_it
+fn foo_bar() {
+}
+
+/// That one tests multiline ticks.
+/// ```rust
+/// foo_bar FOO_BAR
+/// _foo bar_
+/// ```
+///
+/// ~~~rust
+/// foo_bar FOO_BAR
+/// _foo bar_
+/// ~~~
+/// be_sure_we_got_to_the_end_of_it
+fn multiline_codeblock() {
+}
+
+/// This _is a test for
+/// multiline
+/// emphasis_.
+/// be_sure_we_got_to_the_end_of_it
+fn test_emphasis() {
+}
+
+/// This tests units. See also #835.
+/// kiB MiB GiB TiB PiB EiB
+/// kib Mib Gib Tib Pib Eib
+/// kB MB GB TB PB EB
+/// kb Mb Gb Tb Pb Eb
+/// 32kiB 32MiB 32GiB 32TiB 32PiB 32EiB
+/// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib
+/// 32kB 32MB 32GB 32TB 32PB 32EB
+/// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb
+/// NaN
+/// be_sure_we_got_to_the_end_of_it
+fn test_units() {
+}
+
+/// This tests allowed identifiers.
+/// KiB MiB GiB TiB PiB EiB
+/// DirectX
+/// ECMAScript
+/// GPLv2 GPLv3
+/// GitHub GitLab
+/// IPv4 IPv6
+/// ClojureScript CoffeeScript JavaScript PureScript TypeScript
+/// NaN NaNs
+/// OAuth GraphQL
+/// OCaml
+/// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS
+/// WebGL
+/// TensorFlow
+/// TrueType
+/// iOS macOS FreeBSD
+/// TeX LaTeX BibTeX BibLaTeX
+/// MinGW
+/// CamelCase (see also #2395)
+/// be_sure_we_got_to_the_end_of_it
+fn test_allowed() {
+}
+
+/// This test has [a link_with_underscores][chunked-example] inside it. See #823.
+/// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues)
+/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
+/// It can also be [inline_link2].
+///
+/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
+/// [inline_link]: https://foobar
+/// [inline_link2]: https://foobar
+/// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and
+/// `multiline_ticks` functions.
+///
+/// expression of the type  `_ <bit_op> m <cmp_op> c` (where `<bit_op>`
+/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` ,
+/// be_sure_we_got_to_the_end_of_it
+fn main() {
+    foo_bar();
+    multiline_codeblock();
+    test_emphasis();
+    test_units();
+}
+
+/// ## CamelCaseThing
+/// Talks about `CamelCaseThing`. Titles should be ignored; see issue #897.
+///
+/// # CamelCaseThing
+///
+/// Not a title #897 CamelCaseThing
+/// be_sure_we_got_to_the_end_of_it
+fn issue897() {
+}
+
+/// I am confused by brackets? (`x_y`)
+/// I am confused by brackets? (foo `x_y`)
+/// I am confused by brackets? (`x_y` foo)
+/// be_sure_we_got_to_the_end_of_it
+fn issue900() {
+}
+
+/// Diesel queries also have a similar problem to [Iterator][iterator], where
+/// /// More talking
+/// returning them from a function requires exposing the implementation of that
+/// function. The [`helper_types`][helper_types] module exists to help with this,
+/// but you might want to hide the return type or have it conditionally change.
+/// Boxing can achieve both.
+///
+/// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html
+/// [helper_types]: ../helper_types/index.html
+/// be_sure_we_got_to_the_end_of_it
+fn issue883() {
+}
+
+/// `foo_bar
+/// baz_quz`
+/// [foo
+/// bar](https://doc.rust-lang.org/stable/std/iter/trait.IteratorFooBar.html)
+fn multiline() {
+}
+
+/** E.g., serialization of an empty list: FooBar
+```
+That's in a code block: `PackedNode`
+```
+
+And BarQuz too.
+be_sure_we_got_to_the_end_of_it
+*/
+fn issue1073() {
+}
+
+/** E.g., serialization of an empty list: FooBar
+```
+That's in a code block: PackedNode
+```
+
+And BarQuz too.
+be_sure_we_got_to_the_end_of_it
+*/
+fn issue1073_alt() {
+}
+
+/// Tests more than three quotes:
+/// ````
+/// DoNotWarn
+/// ```
+/// StillDont
+/// ````
+/// be_sure_we_got_to_the_end_of_it
+fn four_quotes() {
+}
+
+/// See [NIST SP 800-56A, revision 2].
+///
+/// [NIST SP 800-56A, revision 2]:
+///     https://github.com/rust-lang/rust-clippy/issues/902#issuecomment-261919419
+fn issue_902_comment() {}
+
+#[cfg_attr(feature = "a", doc = " ```")]
+#[cfg_attr(not(feature = "a"), doc = " ```ignore")]
+/// fn main() {
+///     let s = "localhost:10000".to_string();
+///     println!("{}", s);
+/// }
+/// ```
+fn issue_1469() {}
+
+/**
+ * This is a doc comment that should not be a list
+ *This would also be an error under a strict common mark interpretation
+ */
+fn issue_1920() {}
+
+/// Ok: <http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels>
+///
+/// Not ok: http://www.unicode.org
+/// Not ok: https://www.unicode.org
+/// Not ok: http://www.unicode.org/
+/// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
+fn issue_1832() {}
+
+/// An iterator over mycrate::Collection's values.
+/// It should not lint a `'static` lifetime in ticks.
+fn issue_2210() {}
+
+/// This should not cause the lint to trigger:
+/// #REQ-data-family.lint_partof_exists
+fn issue_2343() {}
+
+/// This should not cause an ICE:
+/// __|_ _|__||_|
+fn pulldown_cmark_crash() {}
+
+// issue #7033 - const_evaluatable_checked ICE
+struct S<T, const N: usize>
+where [(); N.checked_next_power_of_two().unwrap()]: {
+    arr: [T; N.checked_next_power_of_two().unwrap()],
+    n: usize,
+}
+
+impl<T: Copy + Default, const N: usize> S<T, N>
+where [(); N.checked_next_power_of_two().unwrap()]: {
+    fn new() -> Self {
+        Self {
+            arr: [T::default(); N.checked_next_power_of_two().unwrap()],
+            n: 0,
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/doc/doc.stderr b/src/tools/clippy/tests/ui/doc/doc.stderr
new file mode 100644 (file)
index 0000000..7eab8a8
--- /dev/null
@@ -0,0 +1,190 @@
+error: you should put `foo_bar` between ticks in the documentation
+  --> $DIR/doc.rs:8:9
+   |
+LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
+   |         ^^^^^^^
+   |
+   = note: `-D clippy::doc-markdown` implied by `-D warnings`
+
+error: you should put `foo::bar` between ticks in the documentation
+  --> $DIR/doc.rs:8:51
+   |
+LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
+   |                                                   ^^^^^^^^
+
+error: you should put `Foo::some_fun` between ticks in the documentation
+  --> $DIR/doc.rs:9:83
+   |
+LL | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun
+   |                                                                                   ^^^^^^^^^^^^^
+
+error: you should put `a::global:path` between ticks in the documentation
+  --> $DIR/doc.rs:11:15
+   |
+LL | /// Here be ::a::global:path.
+   |               ^^^^^^^^^^^^^^
+
+error: you should put `NotInCodeBlock` between ticks in the documentation
+  --> $DIR/doc.rs:12:22
+   |
+LL | /// That's not code ~NotInCodeBlock~.
+   |                      ^^^^^^^^^^^^^^
+
+error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
+  --> $DIR/doc.rs:13:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
+  --> $DIR/doc.rs:27:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
+  --> $DIR/doc.rs:34:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
+  --> $DIR/doc.rs:48:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
+  --> $DIR/doc.rs:71:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put `link_with_underscores` between ticks in the documentation
+  --> $DIR/doc.rs:75:22
+   |
+LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823.
+   |                      ^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put `inline_link2` between ticks in the documentation
+  --> $DIR/doc.rs:78:21
+   |
+LL | /// It can also be [inline_link2].
+   |                     ^^^^^^^^^^^^
+
+error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
+  --> $DIR/doc.rs:88:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put `CamelCaseThing` between ticks in the documentation
+  --> $DIR/doc.rs:96:8
+   |
+LL | /// ## CamelCaseThing
+   |        ^^^^^^^^^^^^^^
+
+error: you should put `CamelCaseThing` between ticks in the documentation
+  --> $DIR/doc.rs:99:7
+   |
+LL | /// # CamelCaseThing
+   |       ^^^^^^^^^^^^^^
+
+error: you should put `CamelCaseThing` between ticks in the documentation
+  --> $DIR/doc.rs:101:22
+   |
+LL | /// Not a title #897 CamelCaseThing
+   |                      ^^^^^^^^^^^^^^
+
+error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
+  --> $DIR/doc.rs:102:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
+  --> $DIR/doc.rs:109:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
+  --> $DIR/doc.rs:122:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put `FooBar` between ticks in the documentation
+  --> $DIR/doc.rs:133:43
+   |
+LL | /** E.g., serialization of an empty list: FooBar
+   |                                           ^^^^^^
+
+error: you should put `BarQuz` between ticks in the documentation
+  --> $DIR/doc.rs:138:5
+   |
+LL | And BarQuz too.
+   |     ^^^^^^
+
+error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
+  --> $DIR/doc.rs:139:1
+   |
+LL | be_sure_we_got_to_the_end_of_it
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put `FooBar` between ticks in the documentation
+  --> $DIR/doc.rs:144:43
+   |
+LL | /** E.g., serialization of an empty list: FooBar
+   |                                           ^^^^^^
+
+error: you should put `BarQuz` between ticks in the documentation
+  --> $DIR/doc.rs:149:5
+   |
+LL | And BarQuz too.
+   |     ^^^^^^
+
+error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
+  --> $DIR/doc.rs:150:1
+   |
+LL | be_sure_we_got_to_the_end_of_it
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
+  --> $DIR/doc.rs:161:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put bare URLs between `<`/`>` or make a proper Markdown link
+  --> $DIR/doc.rs:188:13
+   |
+LL | /// Not ok: http://www.unicode.org
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put bare URLs between `<`/`>` or make a proper Markdown link
+  --> $DIR/doc.rs:189:13
+   |
+LL | /// Not ok: https://www.unicode.org
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put bare URLs between `<`/`>` or make a proper Markdown link
+  --> $DIR/doc.rs:190:13
+   |
+LL | /// Not ok: http://www.unicode.org/
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put bare URLs between `<`/`>` or make a proper Markdown link
+  --> $DIR/doc.rs:191:13
+   |
+LL | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: you should put `mycrate::Collection` between ticks in the documentation
+  --> $DIR/doc.rs:194:22
+   |
+LL | /// An iterator over mycrate::Collection's values.
+   |                      ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 31 previous errors
+
diff --git a/src/tools/clippy/tests/ui/doc/unbalanced_ticks.rs b/src/tools/clippy/tests/ui/doc/unbalanced_ticks.rs
new file mode 100644 (file)
index 0000000..8e8324b
--- /dev/null
@@ -0,0 +1,43 @@
+//! This file tests for the `DOC_MARKDOWN` lint, specifically cases
+//! where ticks are unbalanced (see issue #6753).
+
+#![allow(dead_code)]
+#![warn(clippy::doc_markdown)]
+
+/// This is a doc comment with `unbalanced_tick marks and several words that
+/// should be `encompassed_by` tick marks because they `contain_underscores`.
+/// Because of the initial `unbalanced_tick` pair, the error message is
+/// very `confusing_and_misleading`.
+fn main() {}
+
+/// This paragraph has `unbalanced_tick marks and should stop_linting.
+///
+/// This paragraph is fine and should_be linted normally.
+///
+/// Double unbalanced backtick from ``here to here` should lint.
+///
+/// Double balanced back ticks ``start end`` is fine.
+fn multiple_paragraphs() {}
+
+/// ```
+/// // Unbalanced tick mark in code block shouldn't warn:
+/// `
+/// ```
+fn in_code_block() {}
+
+/// # `Fine`
+///
+/// ## not_fine
+///
+/// ### `unbalanced
+///
+/// - This `item has unbalanced tick marks
+/// - This item needs backticks_here
+fn other_markdown() {}
+
+#[rustfmt::skip]
+/// - ```rust
+///   /// `lol`
+///   pub struct Struct;
+///   ```
+fn iss_7421() {}
diff --git a/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr b/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr
new file mode 100644 (file)
index 0000000..45ca34e
--- /dev/null
@@ -0,0 +1,64 @@
+error: backticks are unbalanced
+  --> $DIR/unbalanced_ticks.rs:7:1
+   |
+LL | / /// This is a doc comment with `unbalanced_tick marks and several words that
+LL | | /// should be `encompassed_by` tick marks because they `contain_underscores`.
+LL | | /// Because of the initial `unbalanced_tick` pair, the error message is
+LL | | /// very `confusing_and_misleading`.
+   | |____________________________________^
+   |
+   = note: `-D clippy::doc-markdown` implied by `-D warnings`
+   = help: a backtick may be missing a pair
+
+error: backticks are unbalanced
+  --> $DIR/unbalanced_ticks.rs:13:1
+   |
+LL | /// This paragraph has `unbalanced_tick marks and should stop_linting.
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: a backtick may be missing a pair
+
+error: you should put `should_be` between ticks in the documentation
+  --> $DIR/unbalanced_ticks.rs:15:32
+   |
+LL | /// This paragraph is fine and should_be linted normally.
+   |                                ^^^^^^^^^
+
+error: backticks are unbalanced
+  --> $DIR/unbalanced_ticks.rs:17:1
+   |
+LL | /// Double unbalanced backtick from ``here to here` should lint.
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: a backtick may be missing a pair
+
+error: you should put `not_fine` between ticks in the documentation
+  --> $DIR/unbalanced_ticks.rs:30:8
+   |
+LL | /// ## not_fine
+   |        ^^^^^^^^
+
+error: backticks are unbalanced
+  --> $DIR/unbalanced_ticks.rs:32:1
+   |
+LL | /// ### `unbalanced
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: a backtick may be missing a pair
+
+error: backticks are unbalanced
+  --> $DIR/unbalanced_ticks.rs:34:1
+   |
+LL | /// - This `item has unbalanced tick marks
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: a backtick may be missing a pair
+
+error: you should put `backticks_here` between ticks in the documentation
+  --> $DIR/unbalanced_ticks.rs:35:23
+   |
+LL | /// - This item needs backticks_here
+   |                       ^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
+
index 9e752311c67785c55478511712db79a6a003109d..91b837f9a85884d19cc74471d262c1016987cf79 100644 (file)
@@ -220,3 +220,19 @@ impl std::ops::Deref for Bar {
 fn test_deref_with_trait_method() {
     let _ = [Bar].iter().map(|s| s.to_string()).collect::<Vec<_>>();
 }
+
+fn mutable_closure_used_again(x: Vec<i32>, y: Vec<i32>, z: Vec<i32>) {
+    let mut res = Vec::new();
+    let mut add_to_res = |n| res.push(n);
+    x.into_iter().for_each(&mut add_to_res);
+    y.into_iter().for_each(&mut add_to_res);
+    z.into_iter().for_each(add_to_res);
+}
+
+fn mutable_closure_in_loop() {
+    let mut value = 0;
+    let mut closure = |n| value += n;
+    for _ in 0..5 {
+        Some(1).map(&mut closure);
+    }
+}
index 44be4628cbd34227eb51118c6698aa38f9d67efd..1b53700289db303678d57850d0b59eb7a17b998d 100644 (file)
@@ -220,3 +220,19 @@ impl std::ops::Deref for Bar {
 fn test_deref_with_trait_method() {
     let _ = [Bar].iter().map(|s| s.to_string()).collect::<Vec<_>>();
 }
+
+fn mutable_closure_used_again(x: Vec<i32>, y: Vec<i32>, z: Vec<i32>) {
+    let mut res = Vec::new();
+    let mut add_to_res = |n| res.push(n);
+    x.into_iter().for_each(|x| add_to_res(x));
+    y.into_iter().for_each(|x| add_to_res(x));
+    z.into_iter().for_each(|x| add_to_res(x));
+}
+
+fn mutable_closure_in_loop() {
+    let mut value = 0;
+    let mut closure = |n| value += n;
+    for _ in 0..5 {
+        Some(1).map(|n| closure(n));
+    }
+}
index 8795d3b42c65af72146bf63c1d110246d81347f0..28da8941346192d0a6e6c61c478a1cc57bb5415d 100644 (file)
@@ -82,5 +82,29 @@ error: redundant closure
 LL |     let a = Some(1u8).map(|a| closure(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure`
 
-error: aborting due to 13 previous errors
+error: redundant closure
+  --> $DIR/eta.rs:227:28
+   |
+LL |     x.into_iter().for_each(|x| add_to_res(x));
+   |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res`
+
+error: redundant closure
+  --> $DIR/eta.rs:228:28
+   |
+LL |     y.into_iter().for_each(|x| add_to_res(x));
+   |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res`
+
+error: redundant closure
+  --> $DIR/eta.rs:229:28
+   |
+LL |     z.into_iter().for_each(|x| add_to_res(x));
+   |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res`
+
+error: redundant closure
+  --> $DIR/eta.rs:236:21
+   |
+LL |         Some(1).map(|n| closure(n));
+   |                     ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure`
+
+error: aborting due to 17 previous errors
 
index 77cadb99bb5510601922ea7034a003a2826669a2..b94ec6403ddcea3c63bfd188bbd6914679581c70 100644 (file)
@@ -1,10 +1,11 @@
-error: use of `writeln!(stderr(), ...).unwrap()`. Consider using `eprintln!` instead
+error: use of `writeln!(stderr(), ...).unwrap()`
   --> $DIR/explicit_write_non_rustfix.rs:7:5
    |
 LL |     writeln!(std::io::stderr(), "foo {}", bar).unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::explicit-write` implied by `-D warnings`
+   = help: consider using `eprintln!` instead
 
 error: aborting due to previous error
 
diff --git a/src/tools/clippy/tests/ui/extend_with_drain.fixed b/src/tools/clippy/tests/ui/extend_with_drain.fixed
new file mode 100644 (file)
index 0000000..00170e6
--- /dev/null
@@ -0,0 +1,55 @@
+// run-rustfix
+#![warn(clippy::extend_with_drain)]
+use std::collections::BinaryHeap;
+fn main() {
+    //gets linted
+    let mut vec1 = vec![0u8; 1024];
+    let mut vec2: std::vec::Vec<u8> = Vec::new();
+
+    vec2.append(&mut vec1);
+
+    let mut vec3 = vec![0u8; 1024];
+    let mut vec4: std::vec::Vec<u8> = Vec::new();
+
+    vec4.append(&mut vec3);
+
+    let mut vec11: std::vec::Vec<u8> = Vec::new();
+
+    vec11.append(&mut return_vector());
+
+    //won't get linted it dosen't move the entire content of a vec into another
+    let mut test1 = vec![0u8, 10];
+    let mut test2: std::vec::Vec<u8> = Vec::new();
+
+    test2.extend(test1.drain(4..10));
+
+    let mut vec3 = vec![0u8; 104];
+    let mut vec7: std::vec::Vec<u8> = Vec::new();
+
+    vec3.append(&mut vec7);
+
+    let mut vec5 = vec![0u8; 1024];
+    let mut vec6: std::vec::Vec<u8> = Vec::new();
+
+    vec5.extend(vec6.drain(..4));
+
+    let mut vec9: std::vec::Vec<u8> = Vec::new();
+
+    return_vector().append(&mut vec9);
+
+    //won't get linted because it is not a vec
+
+    let mut heap = BinaryHeap::from(vec![1, 3]);
+    let mut heap2 = BinaryHeap::from(vec![]);
+    heap2.extend(heap.drain())
+}
+
+fn return_vector() -> Vec<u8> {
+    let mut new_vector = vec![];
+
+    for i in 1..10 {
+        new_vector.push(i)
+    }
+
+    new_vector
+}
diff --git a/src/tools/clippy/tests/ui/extend_with_drain.rs b/src/tools/clippy/tests/ui/extend_with_drain.rs
new file mode 100644 (file)
index 0000000..d76458c
--- /dev/null
@@ -0,0 +1,55 @@
+// run-rustfix
+#![warn(clippy::extend_with_drain)]
+use std::collections::BinaryHeap;
+fn main() {
+    //gets linted
+    let mut vec1 = vec![0u8; 1024];
+    let mut vec2: std::vec::Vec<u8> = Vec::new();
+
+    vec2.extend(vec1.drain(..));
+
+    let mut vec3 = vec![0u8; 1024];
+    let mut vec4: std::vec::Vec<u8> = Vec::new();
+
+    vec4.extend(vec3.drain(..));
+
+    let mut vec11: std::vec::Vec<u8> = Vec::new();
+
+    vec11.extend(return_vector().drain(..));
+
+    //won't get linted it dosen't move the entire content of a vec into another
+    let mut test1 = vec![0u8, 10];
+    let mut test2: std::vec::Vec<u8> = Vec::new();
+
+    test2.extend(test1.drain(4..10));
+
+    let mut vec3 = vec![0u8; 104];
+    let mut vec7: std::vec::Vec<u8> = Vec::new();
+
+    vec3.append(&mut vec7);
+
+    let mut vec5 = vec![0u8; 1024];
+    let mut vec6: std::vec::Vec<u8> = Vec::new();
+
+    vec5.extend(vec6.drain(..4));
+
+    let mut vec9: std::vec::Vec<u8> = Vec::new();
+
+    return_vector().append(&mut vec9);
+
+    //won't get linted because it is not a vec
+
+    let mut heap = BinaryHeap::from(vec![1, 3]);
+    let mut heap2 = BinaryHeap::from(vec![]);
+    heap2.extend(heap.drain())
+}
+
+fn return_vector() -> Vec<u8> {
+    let mut new_vector = vec![];
+
+    for i in 1..10 {
+        new_vector.push(i)
+    }
+
+    new_vector
+}
diff --git a/src/tools/clippy/tests/ui/extend_with_drain.stderr b/src/tools/clippy/tests/ui/extend_with_drain.stderr
new file mode 100644 (file)
index 0000000..57f3447
--- /dev/null
@@ -0,0 +1,22 @@
+error: use of `extend` instead of `append` for adding the full range of a second vector
+  --> $DIR/extend_with_drain.rs:9:5
+   |
+LL |     vec2.extend(vec1.drain(..));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec2.append(&mut vec1)`
+   |
+   = note: `-D clippy::extend-with-drain` implied by `-D warnings`
+
+error: use of `extend` instead of `append` for adding the full range of a second vector
+  --> $DIR/extend_with_drain.rs:14:5
+   |
+LL |     vec4.extend(vec3.drain(..));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec4.append(&mut vec3)`
+
+error: use of `extend` instead of `append` for adding the full range of a second vector
+  --> $DIR/extend_with_drain.rs:18:5
+   |
+LL |     vec11.extend(return_vector().drain(..));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec11.append(&mut return_vector())`
+
+error: aborting due to 3 previous errors
+
index 1368c5d79848032b423bb3f6520655a8e6567bf5..787053fb00064c861a75c37410ae26767ab2322e 100644 (file)
@@ -29,6 +29,21 @@ struct C {
     i: Vec<i32>,
     j: i64,
 }
+
+#[derive(Default)]
+struct D {
+    a: Option<i32>,
+    b: Option<i32>,
+}
+
+macro_rules! m {
+    ($key:ident: $value:tt) => {{
+        let mut data = $crate::D::default();
+        data.$key = Some($value);
+        data
+    }};
+}
+
 /// Implements .next() that returns a different number each time.
 struct SideEffect(i32);
 
@@ -143,6 +158,11 @@ fn main() {
 
     let mut a: WrapperMulti<i32, i64> = Default::default();
     a.i = 42;
+
+    // Don't lint in macros
+    m! {
+        a: 42
+    };
 }
 
 mod m {
index dd7c0360bb1e2bc40355e216bec4fad739615f43..b56db08ec8a787f63c3edc31fde93178a0237982 100644 (file)
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:48:5
+  --> $DIR/field_reassign_with_default.rs:63:5
    |
 LL |     a.i = 42;
    |     ^^^^^^^^^
    |
    = note: `-D clippy::field-reassign-with-default` implied by `-D warnings`
 note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:47:5
+  --> $DIR/field_reassign_with_default.rs:62:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:88:5
+  --> $DIR/field_reassign_with_default.rs:103:5
    |
 LL |     a.j = 43;
    |     ^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { j: 43, i: 42 }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:87:5
+  --> $DIR/field_reassign_with_default.rs:102:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:93:5
+  --> $DIR/field_reassign_with_default.rs:108:5
    |
 LL |     a.i = 42;
    |     ^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { i: 42, j: 44 }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:92:5
+  --> $DIR/field_reassign_with_default.rs:107:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:99:5
+  --> $DIR/field_reassign_with_default.rs:114:5
    |
 LL |     a.i = 42;
    |     ^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:98:5
+  --> $DIR/field_reassign_with_default.rs:113:5
    |
 LL |     let mut a = A::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:109:5
+  --> $DIR/field_reassign_with_default.rs:124:5
    |
 LL |     a.i = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { i: Default::default(), ..Default::default() }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:108:5
+  --> $DIR/field_reassign_with_default.rs:123:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:113:5
+  --> $DIR/field_reassign_with_default.rs:128:5
    |
 LL |     a.i = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { i: Default::default(), j: 45 }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:112:5
+  --> $DIR/field_reassign_with_default.rs:127:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:135:5
+  --> $DIR/field_reassign_with_default.rs:150:5
    |
 LL |     a.i = vec![1];
    |     ^^^^^^^^^^^^^^
    |
 note: consider initializing the variable with `C { i: vec![1], ..Default::default() }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:134:5
+  --> $DIR/field_reassign_with_default.rs:149:5
    |
 LL |     let mut a: C = C::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:142:5
+  --> $DIR/field_reassign_with_default.rs:157:5
    |
 LL |     a.i = true;
    |     ^^^^^^^^^^^
    |
 note: consider initializing the variable with `Wrapper::<bool> { i: true }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:141:5
+  --> $DIR/field_reassign_with_default.rs:156:5
    |
 LL |     let mut a: Wrapper<bool> = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:145:5
+  --> $DIR/field_reassign_with_default.rs:160:5
    |
 LL |     a.i = 42;
    |     ^^^^^^^^^
    |
 note: consider initializing the variable with `WrapperMulti::<i32, i64> { i: 42, ..Default::default() }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:144:5
+  --> $DIR/field_reassign_with_default.rs:159:5
    |
 LL |     let mut a: WrapperMulti<i32, i64> = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 23ce28d8e9be4c2238afe40f3a664419763305d0..a5860aa49b3bb7f909aeee04e130285188fd0ae8 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(unused_imports)]
+#![allow(unused_imports, clippy::needless_return)]
 #![warn(clippy::filter_map_identity)]
 
 fn main() {
@@ -13,4 +13,7 @@ fn main() {
     use std::convert::identity;
     let iterator = vec![Some(1), None, Some(2)].into_iter();
     let _ = iterator.flatten();
+
+    let iterator = vec![Some(1), None, Some(2)].into_iter();
+    let _ = iterator.flatten();
 }
index e698df13eea47ef4ff3eaca9319a0a0b82b14ad5..7e998b9cdf7010f4cd6e1fa84af582a3450dd6eb 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(unused_imports)]
+#![allow(unused_imports, clippy::needless_return)]
 #![warn(clippy::filter_map_identity)]
 
 fn main() {
@@ -13,4 +13,7 @@ fn main() {
     use std::convert::identity;
     let iterator = vec![Some(1), None, Some(2)].into_iter();
     let _ = iterator.filter_map(identity);
+
+    let iterator = vec![Some(1), None, Some(2)].into_iter();
+    let _ = iterator.filter_map(|x| return x);
 }
index 596a6320608c7c0acf8725c40c88c82461b20309..43c9fdca4fbe0251b54e6e6c70f4ab2fe3873eb8 100644 (file)
@@ -1,4 +1,4 @@
-error: called `filter_map(|x| x)` on an `Iterator`
+error: use of `filter_map` with an identity function
   --> $DIR/filter_map_identity.rs:8:22
    |
 LL |     let _ = iterator.filter_map(|x| x);
@@ -6,17 +6,23 @@ LL |     let _ = iterator.filter_map(|x| x);
    |
    = note: `-D clippy::filter-map-identity` implied by `-D warnings`
 
-error: called `filter_map(std::convert::identity)` on an `Iterator`
+error: use of `filter_map` with an identity function
   --> $DIR/filter_map_identity.rs:11:22
    |
 LL |     let _ = iterator.filter_map(std::convert::identity);
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
 
-error: called `filter_map(std::convert::identity)` on an `Iterator`
+error: use of `filter_map` with an identity function
   --> $DIR/filter_map_identity.rs:15:22
    |
 LL |     let _ = iterator.filter_map(identity);
    |                      ^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
 
-error: aborting due to 3 previous errors
+error: use of `filter_map` with an identity function
+  --> $DIR/filter_map_identity.rs:18:22
+   |
+LL |     let _ = iterator.filter_map(|x| return x);
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: aborting due to 4 previous errors
 
index dfe3bd47e1394b4517cdbc88ee1b288a86a0c036..1f4b880ef5bcd8fa1cea502a8b9bd5efae1d7ba9 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(unused_imports)]
+#![allow(unused_imports, clippy::needless_return)]
 #![warn(clippy::flat_map_identity)]
 
 use std::convert;
@@ -11,4 +11,7 @@ fn main() {
 
     let iterator = [[0, 1], [2, 3], [4, 5]].iter();
     let _ = iterator.flatten();
+
+    let iterator = [[0, 1], [2, 3], [4, 5]].iter();
+    let _ = iterator.flatten();
 }
index 393b95692554ca200ab9e5ac37f998e350f37d99..de14a06d4e6b3377a40d277105d073005e68229a 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(unused_imports)]
+#![allow(unused_imports, clippy::needless_return)]
 #![warn(clippy::flat_map_identity)]
 
 use std::convert;
@@ -11,4 +11,7 @@ fn main() {
 
     let iterator = [[0, 1], [2, 3], [4, 5]].iter();
     let _ = iterator.flat_map(convert::identity);
+
+    let iterator = [[0, 1], [2, 3], [4, 5]].iter();
+    let _ = iterator.flat_map(|x| return x);
 }
index e4686ae5a5493ca2d409d56eebb347d84e0530d8..e776c9fdf512e2bda03316138086e2eabd4e2dcf 100644 (file)
@@ -1,4 +1,4 @@
-error: called `flat_map(|x| x)` on an `Iterator`
+error: use of `flat_map` with an identity function
   --> $DIR/flat_map_identity.rs:10:22
    |
 LL |     let _ = iterator.flat_map(|x| x);
@@ -6,11 +6,17 @@ LL |     let _ = iterator.flat_map(|x| x);
    |
    = note: `-D clippy::flat-map-identity` implied by `-D warnings`
 
-error: called `flat_map(std::convert::identity)` on an `Iterator`
+error: use of `flat_map` with an identity function
   --> $DIR/flat_map_identity.rs:13:22
    |
 LL |     let _ = iterator.flat_map(convert::identity);
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
 
-error: aborting due to 2 previous errors
+error: use of `flat_map` with an identity function
+  --> $DIR/flat_map_identity.rs:16:22
+   |
+LL |     let _ = iterator.flat_map(|x| return x);
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: aborting due to 3 previous errors
 
index e4cfb005fd1d0d8e8a0ac4bd42392dddb56df35c..5dd64140e81165880f3d6285c60825838d96a0e2 100644 (file)
@@ -69,4 +69,6 @@ fn main() {
     // Wrap it with braces
     let v: Vec<String> = vec!["foo".to_string(), "bar".to_string()];
     let _s: String = (&*v.join("\n")).to_string();
+
+    format!("prepend {:+}", "s");
 }
index 683957f0ff0f79cb452811b66b0db83d90f55c8b..4599fb5207ea85c280f07b863d39f798f6262eaa 100644 (file)
@@ -71,4 +71,6 @@ fn main() {
     // Wrap it with braces
     let v: Vec<String> = vec!["foo".to_string(), "bar".to_string()];
     let _s: String = format!("{}", &*v.join("\n"));
+
+    format!("prepend {:+}", "s");
 }
index b59dbb3e76c6455ac99d678f4bba6cca14bd7fd6..c734051ccf320b086567185414793a707c50a379 100644 (file)
@@ -55,11 +55,11 @@ note: captured value is not `Send`
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                          ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
-note: captured value is not `Send`
+note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
   --> $DIR/future_not_send.rs:20:40
    |
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
-   |                                        ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`
+   |                                        ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync`
    = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
diff --git a/src/tools/clippy/tests/ui/issue-7447.rs b/src/tools/clippy/tests/ui/issue-7447.rs
new file mode 100644 (file)
index 0000000..fdb77f3
--- /dev/null
@@ -0,0 +1,25 @@
+use std::{borrow::Cow, collections::BTreeMap, marker::PhantomData, sync::Arc};
+
+fn byte_view<'a>(s: &'a ByteView<'_>) -> BTreeMap<&'a str, ByteView<'a>> {
+    panic!()
+}
+
+fn group_entries(s: &()) -> BTreeMap<Cow<'_, str>, Vec<Cow<'_, str>>> {
+    todo!()
+}
+
+struct Mmap;
+
+enum ByteViewBacking<'a> {
+    Buf(Cow<'a, [u8]>),
+    Mmap(Mmap),
+}
+
+pub struct ByteView<'a> {
+    backing: Arc<ByteViewBacking<'a>>,
+}
+
+fn main() {
+    byte_view(panic!());
+    group_entries(panic!());
+}
index 8a9d5a3d1d5696afe426d685f3314916e020c067..cc699b79e433ca39756717f16714487a05421da7 100644 (file)
@@ -25,7 +25,9 @@ async fn all_to_one<'a>(a: &'a str, _b: &'a str) -> &'a str {
 struct Foo;
 impl Foo {
     // ok
-    pub async fn foo(&mut self) {}
+    pub async fn new(&mut self) -> Self {
+        Foo {}
+    }
 }
 
 // rust-lang/rust#61115
index b11dadda6c24ed753f23663492f5a675a6f82702..97c5929783d882c51dd754244c8bec46ff292f5d 100644 (file)
@@ -50,7 +50,7 @@ fn main() {
     linked_list.push_back(1);
     binary_heap.push(1);
 
-    &vec[..].len();
+    let _ = &vec[..].len();
     vec.len();
     boxed_slice.len();
     vec_deque.len();
@@ -62,13 +62,13 @@ fn main() {
     binary_heap.len();
 
     vec.len();
-    &vec[..].len();
+    let _ = &vec[..].len();
     vec_deque.len();
     hash_map.len();
     b_tree_map.len();
     linked_list.len();
 
-    &vec[..].len();
+    let _ = &vec[..].len();
     vec.len();
     vec_deque.len();
     hash_set.len();
index 7d49c6a3dbbb939d90144b60e51123e85293d620..70bb734763f09bef26eb35bc4b45f9c196dce29b 100644 (file)
@@ -50,7 +50,7 @@ fn main() {
     linked_list.push_back(1);
     binary_heap.push(1);
 
-    &vec[..].iter().count();
+    let _ = &vec[..].iter().count();
     vec.iter().count();
     boxed_slice.iter().count();
     vec_deque.iter().count();
@@ -62,13 +62,13 @@ fn main() {
     binary_heap.iter().count();
 
     vec.iter_mut().count();
-    &vec[..].iter_mut().count();
+    let _ = &vec[..].iter_mut().count();
     vec_deque.iter_mut().count();
     hash_map.iter_mut().count();
     b_tree_map.iter_mut().count();
     linked_list.iter_mut().count();
 
-    &vec[..].into_iter().count();
+    let _ = &vec[..].into_iter().count();
     vec.into_iter().count();
     vec_deque.into_iter().count();
     hash_set.into_iter().count();
index f3fb98e65b9906aa35381897f64948aa21635d42..1d2c22f9dfad5470e0b1d478b439a26587bc7a1b 100644 (file)
@@ -1,8 +1,8 @@
 error: called `.iter().count()` on a `slice`
-  --> $DIR/iter_count.rs:53:6
+  --> $DIR/iter_count.rs:53:14
    |
-LL |     &vec[..].iter().count();
-   |      ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
+LL |     let _ = &vec[..].iter().count();
+   |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
    |
    = note: `-D clippy::iter-count` implied by `-D warnings`
 
@@ -67,10 +67,10 @@ LL |     vec.iter_mut().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()`
 
 error: called `.iter_mut().count()` on a `slice`
-  --> $DIR/iter_count.rs:65:6
+  --> $DIR/iter_count.rs:65:14
    |
-LL |     &vec[..].iter_mut().count();
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
+LL |     let _ = &vec[..].iter_mut().count();
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
 
 error: called `.iter_mut().count()` on a `VecDeque`
   --> $DIR/iter_count.rs:66:5
@@ -97,10 +97,10 @@ LL |     linked_list.iter_mut().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()`
 
 error: called `.into_iter().count()` on a `slice`
-  --> $DIR/iter_count.rs:71:6
+  --> $DIR/iter_count.rs:71:14
    |
-LL |     &vec[..].into_iter().count();
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
+LL |     let _ = &vec[..].into_iter().count();
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
 
 error: called `.into_iter().count()` on a `Vec`
   --> $DIR/iter_count.rs:72:5
index 0549886a1e8ec7ad8a52f497c1ff647033e63528..e48451acfe8f5f4c67f76c65298e40b9a463e9f5 100644 (file)
@@ -32,6 +32,7 @@ help: consider refactoring into `(1, .., 3) | (.., 3)`
    |
 LL |         (1, .., 3) => 42,
    |         ^^^^^^^^^^
+   = help: ...or consider changing the match arm bodies
 
 error: this `match` has identical arm bodies
   --> $DIR/match_same_arms.rs:24:15
@@ -49,6 +50,7 @@ help: consider refactoring into `42 | 51`
    |
 LL |         42 => 1,
    |         ^^
+   = help: ...or consider changing the match arm bodies
 
 error: this `match` has identical arm bodies
   --> $DIR/match_same_arms.rs:26:15
@@ -66,6 +68,7 @@ help: consider refactoring into `41 | 52`
    |
 LL |         41 => 2,
    |         ^^
+   = help: ...or consider changing the match arm bodies
 
 error: this `match` has identical arm bodies
   --> $DIR/match_same_arms.rs:32:14
@@ -83,6 +86,7 @@ help: consider refactoring into `1 | 2`
    |
 LL |         1 => 2,
    |         ^
+   = help: ...or consider changing the match arm bodies
 
 error: this `match` has identical arm bodies
   --> $DIR/match_same_arms.rs:33:14
@@ -100,6 +104,7 @@ help: consider refactoring into `1 | 3`
    |
 LL |         1 => 2,
    |         ^
+   = help: ...or consider changing the match arm bodies
 
 error: this `match` has identical arm bodies
   --> $DIR/match_same_arms.rs:33:14
@@ -117,6 +122,7 @@ help: consider refactoring into `2 | 3`
    |
 LL |         2 => 2, //~ ERROR 2nd matched arms have same body
    |         ^
+   = help: ...or consider changing the match arm bodies
 
 error: this `match` has identical arm bodies
   --> $DIR/match_same_arms.rs:50:55
@@ -134,6 +140,7 @@ help: consider refactoring into `CommandInfo::BuiltIn { name, .. } | CommandInfo
    |
 LL |                 CommandInfo::BuiltIn { name, .. } => name.to_string(),
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ...or consider changing the match arm bodies
 
 error: aborting due to 8 previous errors
 
index 430021a0f7f5acddf88545d543bef5f20d90b077..e1ed12f9370877b8b0d59411ce345529cf64b84e 100644 (file)
@@ -53,6 +53,7 @@ help: consider refactoring into `42 | 51`
    |
 LL |         42 => foo(),
    |         ^^
+   = help: ...or consider changing the match arm bodies
 
 error: this `match` has identical arm bodies
   --> $DIR/match_same_arms2.rs:40:17
@@ -70,6 +71,7 @@ help: consider refactoring into `Some(_) | None`
    |
 LL |         Some(_) => 24,
    |         ^^^^^^^
+   = help: ...or consider changing the match arm bodies
 
 error: this `match` has identical arm bodies
   --> $DIR/match_same_arms2.rs:62:28
@@ -87,6 +89,7 @@ help: consider refactoring into `(Some(a), None) | (None, Some(a))`
    |
 LL |         (Some(a), None) => bar(a),
    |         ^^^^^^^^^^^^^^^
+   = help: ...or consider changing the match arm bodies
 
 error: this `match` has identical arm bodies
   --> $DIR/match_same_arms2.rs:68:26
@@ -104,6 +107,7 @@ help: consider refactoring into `(Some(a), ..) | (.., Some(a))`
    |
 LL |         (Some(a), ..) => bar(a),
    |         ^^^^^^^^^^^^^
+   = help: ...or consider changing the match arm bodies
 
 error: this `match` has identical arm bodies
   --> $DIR/match_same_arms2.rs:102:29
@@ -121,6 +125,7 @@ help: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))`
    |
 LL |         (Ok(x), Some(_)) => println!("ok {}", x),
    |         ^^^^^^^^^^^^^^^^
+   = help: ...or consider changing the match arm bodies
    = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this `match` has identical arm bodies
@@ -139,6 +144,7 @@ help: consider refactoring into `Ok(3) | Ok(_)`
    |
 LL |         Ok(3) => println!("ok"),
    |         ^^^^^
+   = help: ...or consider changing the match arm bodies
    = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this `match` has identical arm bodies
@@ -163,6 +169,7 @@ help: consider refactoring into `0 | 1`
    |
 LL |         0 => {
    |         ^
+   = help: ...or consider changing the match arm bodies
 
 error: match expression looks like `matches!` macro
   --> $DIR/match_same_arms2.rs:162:16
index 31b743f7a18d73f53457e986d5572269a2746385..e675c183ea7117c646b99e04438c524f07fec3dc 100644 (file)
@@ -115,9 +115,16 @@ fn main() {
         pub enum Enum {
             A,
             B,
+            C,
             #[doc(hidden)]
             __Private,
         }
+        match Enum::A {
+            Enum::A => (),
+            Enum::B => (),
+            Enum::C => (),
+            _ => (),
+        }
         match Enum::A {
             Enum::A => (),
             Enum::B => (),
index d19e6ab7eb2e1ee8aa588f075550da007be81a22..38c3ffc00c71b4bc8cad9251ad1aa4b674899203 100644 (file)
@@ -115,9 +115,16 @@ fn main() {
         pub enum Enum {
             A,
             B,
+            C,
             #[doc(hidden)]
             __Private,
         }
+        match Enum::A {
+            Enum::A => (),
+            Enum::B => (),
+            Enum::C => (),
+            _ => (),
+        }
         match Enum::A {
             Enum::A => (),
             Enum::B => (),
index bfa9ef01b0e9535e4f19fabe9ed0e8113b513695..d5724bf661c634ec89f3d83ac580a5c75facd6c6 100644 (file)
@@ -59,7 +59,9 @@ pub trait E: Sized {
 }
 
 impl Foo {
-    pub fn foo() {}
+    pub fn new() -> Self {
+        Foo { a: 0, b: 0 }
+    }
     fn bar() {}
 }
 
index d33d512475b2389ec8bbd926ba28c132deb6a268..bda63d66a174af725e68b1f3b833cdb240e066e4 100644 (file)
@@ -78,23 +78,25 @@ LL |     type AssociatedTypeDef = Self;
 error: missing documentation for an associated function
   --> $DIR/missing-doc-impl.rs:62:5
    |
-LL |     pub fn foo() {}
-   |     ^^^^^^^^^^^^^^^
+LL | /     pub fn new() -> Self {
+LL | |         Foo { a: 0, b: 0 }
+LL | |     }
+   | |_____^
 
 error: missing documentation for an associated function
-  --> $DIR/missing-doc-impl.rs:63:5
+  --> $DIR/missing-doc-impl.rs:65:5
    |
 LL |     fn bar() {}
    |     ^^^^^^^^^^^
 
 error: missing documentation for an associated function
-  --> $DIR/missing-doc-impl.rs:67:5
+  --> $DIR/missing-doc-impl.rs:69:5
    |
 LL |     pub fn foo() {}
    |     ^^^^^^^^^^^^^^^
 
 error: missing documentation for an associated function
-  --> $DIR/missing-doc-impl.rs:71:5
+  --> $DIR/missing-doc-impl.rs:73:5
    |
 LL | /     fn foo2() -> u32 {
 LL | |         1
index 7cda1aaa3c22894def353f9e6223546a930ab2f5..6d2cbb6ad96fa865870159854b8e1d053d6f0b75 100644 (file)
@@ -84,7 +84,7 @@ mod with_drop {
 
     impl A {
         // This can not be const because the type implements `Drop`.
-        pub fn a(self) -> B {
+        pub fn b(self) -> B {
             B
         }
     }
index 8d6a259c7e385f307ada794ea2e9ca0f06f01853..a8460b06ca6038ef3b976e9b6867ca33049cfcc1 100644 (file)
@@ -4,7 +4,7 @@ error: mutable key type
 LL | fn should_not_take_this_arg(m: &mut HashMap<Key, usize>, _n: usize) -> HashSet<Key> {
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `#[deny(clippy::mutable_key_type)]` on by default
+   = note: `-D clippy::mutable-key-type` implied by `-D warnings`
 
 error: mutable key type
   --> $DIR/mut_key.rs:27:72
index 567dbc54100a64943337b9c02c390dd7801f7804..639eac8b8b315a0f3ec2e71f09f03ac185553b04 100644 (file)
@@ -6,7 +6,8 @@
     dead_code,
     clippy::no_effect,
     clippy::if_same_then_else,
-    clippy::needless_return
+    clippy::needless_return,
+    clippy::self_named_constructors
 )]
 
 use std::cell::Cell;
index 10126ad4dbb15aacd70053938e9e267dd42510ba..a3ce086a1c90aa3a26f2af6f59a3a1e8cda24c77 100644 (file)
@@ -6,7 +6,8 @@
     dead_code,
     clippy::no_effect,
     clippy::if_same_then_else,
-    clippy::needless_return
+    clippy::needless_return,
+    clippy::self_named_constructors
 )]
 
 use std::cell::Cell;
index 25abfb2a472b621130483c7eb5629ef7f946fab1..8026d643c44882c476a9d8a9cfd059aa4ab389e9 100644 (file)
@@ -1,5 +1,5 @@
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:39:5
+  --> $DIR/fixable.rs:40:5
    |
 LL | /     if x {
 LL | |         true
@@ -11,7 +11,7 @@ LL | |     };
    = note: `-D clippy::needless-bool` implied by `-D warnings`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:44:5
+  --> $DIR/fixable.rs:45:5
    |
 LL | /     if x {
 LL | |         false
@@ -21,7 +21,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `!x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:49:5
+  --> $DIR/fixable.rs:50:5
    |
 LL | /     if x && y {
 LL | |         false
@@ -31,7 +31,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `!(x && y)`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:69:5
+  --> $DIR/fixable.rs:70:5
    |
 LL | /     if x {
 LL | |         return true;
@@ -41,7 +41,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:77:5
+  --> $DIR/fixable.rs:78:5
    |
 LL | /     if x {
 LL | |         return false;
@@ -51,7 +51,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return !x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:85:5
+  --> $DIR/fixable.rs:86:5
    |
 LL | /     if x && y {
 LL | |         return true;
@@ -61,7 +61,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return x && y`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:93:5
+  --> $DIR/fixable.rs:94:5
    |
 LL | /     if x && y {
 LL | |         return false;
@@ -71,7 +71,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return !(x && y)`
 
 error: equality checks against true are unnecessary
-  --> $DIR/fixable.rs:101:8
+  --> $DIR/fixable.rs:102:8
    |
 LL |     if x == true {};
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
@@ -79,25 +79,25 @@ LL |     if x == true {};
    = note: `-D clippy::bool-comparison` implied by `-D warnings`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/fixable.rs:105:8
+  --> $DIR/fixable.rs:106:8
    |
 LL |     if x == false {};
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: equality checks against true are unnecessary
-  --> $DIR/fixable.rs:115:8
+  --> $DIR/fixable.rs:116:8
    |
 LL |     if x == true {};
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/fixable.rs:116:8
+  --> $DIR/fixable.rs:117:8
    |
 LL |     if x == false {};
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:125:12
+  --> $DIR/fixable.rs:126:12
    |
 LL |       } else if returns_bool() {
    |  ____________^
index bda0801e51c7f8663f648edd0eac8bae30898863..1d77382bf2cd1132549232dd03fe41af93de9389 100644 (file)
@@ -1,5 +1,5 @@
 #![warn(clippy::needless_lifetimes)]
-#![allow(dead_code, clippy::needless_pass_by_value, clippy::unnecessary_wraps)]
+#![allow(dead_code, clippy::needless_pass_by_value, clippy::unnecessary_wraps, dyn_drop)]
 
 fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
 
index 93b236f7473d5f2d3d823ae63ce8edcd37d00515..7338064646244ca7611a01d73c61203a15a0631f 100644 (file)
@@ -43,6 +43,18 @@ fn core_versions() {
     unreachable!();
 }
 
+fn assert() {
+    assert!(true);
+    assert_eq!(true, true);
+    assert_ne!(true, false);
+}
+
+fn assert_msg() {
+    assert!(true, "this should not panic");
+    assert_eq!(true, true, "this should not panic");
+    assert_ne!(true, false, "this should not panic");
+}
+
 fn debug_assert() {
     debug_assert!(true);
     debug_assert_eq!(true, true);
@@ -61,4 +73,8 @@ fn main() {
     unimplemented();
     unreachable();
     core_versions();
+    assert();
+    assert_msg();
+    debug_assert();
+    debug_assert_msg();
 }
diff --git a/src/tools/clippy/tests/ui/rc_mutex.rs b/src/tools/clippy/tests/ui/rc_mutex.rs
new file mode 100644 (file)
index 0000000..657a3ec
--- /dev/null
@@ -0,0 +1,34 @@
+#![warn(clippy::rc_mutex)]
+#![allow(clippy::blacklisted_name)]
+
+use std::rc::Rc;
+use std::sync::Mutex;
+
+pub struct MyStruct {
+    foo: Rc<Mutex<i32>>,
+}
+
+pub struct SubT<T> {
+    foo: T,
+}
+
+pub enum MyEnum {
+    One,
+    Two,
+}
+
+pub fn test1<T>(foo: Rc<Mutex<T>>) {}
+
+pub fn test2(foo: Rc<Mutex<MyEnum>>) {}
+
+pub fn test3(foo: Rc<Mutex<SubT<usize>>>) {}
+
+fn main() {
+    test1(Rc::new(Mutex::new(1)));
+    test2(Rc::new(Mutex::new(MyEnum::One)));
+    test3(Rc::new(Mutex::new(SubT { foo: 1 })));
+
+    let _my_struct = MyStruct {
+        foo: Rc::new(Mutex::new(1)),
+    };
+}
diff --git a/src/tools/clippy/tests/ui/rc_mutex.stderr b/src/tools/clippy/tests/ui/rc_mutex.stderr
new file mode 100644 (file)
index 0000000..8e58e2b
--- /dev/null
@@ -0,0 +1,28 @@
+error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
+  --> $DIR/rc_mutex.rs:8:10
+   |
+LL |     foo: Rc<Mutex<i32>>,
+   |          ^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::rc-mutex` implied by `-D warnings`
+
+error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
+  --> $DIR/rc_mutex.rs:20:22
+   |
+LL | pub fn test1<T>(foo: Rc<Mutex<T>>) {}
+   |                      ^^^^^^^^^^^^
+
+error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
+  --> $DIR/rc_mutex.rs:22:19
+   |
+LL | pub fn test2(foo: Rc<Mutex<MyEnum>>) {}
+   |                   ^^^^^^^^^^^^^^^^^
+
+error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
+  --> $DIR/rc_mutex.rs:24:19
+   |
+LL | pub fn test3(foo: Rc<Mutex<SubT<usize>>>) {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/redundant_allocation.fixed b/src/tools/clippy/tests/ui/redundant_allocation.fixed
deleted file mode 100644 (file)
index 6514fd6..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-// run-rustfix
-#![warn(clippy::all)]
-#![allow(clippy::boxed_local, clippy::needless_pass_by_value)]
-#![allow(clippy::blacklisted_name, unused_variables, dead_code)]
-
-use std::boxed::Box;
-use std::rc::Rc;
-
-pub struct MyStruct {}
-
-pub struct SubT<T> {
-    foo: T,
-}
-
-pub enum MyEnum {
-    One,
-    Two,
-}
-
-// Rc<&T>
-
-pub fn test1<T>(foo: &T) {}
-
-pub fn test2(foo: &MyStruct) {}
-
-pub fn test3(foo: &MyEnum) {}
-
-pub fn test4_neg(foo: Rc<SubT<&usize>>) {}
-
-// Rc<Rc<T>>
-
-pub fn test5(a: Rc<bool>) {}
-
-// Rc<Box<T>>
-
-pub fn test6(a: Rc<bool>) {}
-
-// Box<&T>
-
-pub fn test7<T>(foo: &T) {}
-
-pub fn test8(foo: &MyStruct) {}
-
-pub fn test9(foo: &MyEnum) {}
-
-pub fn test10_neg(foo: Box<SubT<&usize>>) {}
-
-fn main() {}
index 677b3e56d4dcebe5ea58a9996b5cac7c5332cddc..1b4f2a66c705ec088d5396bc3dbed187e12579df 100644 (file)
@@ -1,10 +1,7 @@
-// run-rustfix
 #![warn(clippy::all)]
 #![allow(clippy::boxed_local, clippy::needless_pass_by_value)]
 #![allow(clippy::blacklisted_name, unused_variables, dead_code)]
-
-use std::boxed::Box;
-use std::rc::Rc;
+#![allow(unused_imports)]
 
 pub struct MyStruct {}
 
@@ -17,32 +14,67 @@ pub enum MyEnum {
     Two,
 }
 
-// Rc<&T>
+mod outer_box {
+    use crate::MyEnum;
+    use crate::MyStruct;
+    use crate::SubT;
+    use std::boxed::Box;
+    use std::rc::Rc;
+    use std::sync::Arc;
 
-pub fn test1<T>(foo: Rc<&T>) {}
+    pub fn box_test6<T>(foo: Box<Rc<T>>) {}
 
-pub fn test2(foo: Rc<&MyStruct>) {}
+    pub fn box_test7<T>(foo: Box<Arc<T>>) {}
 
-pub fn test3(foo: Rc<&MyEnum>) {}
+    pub fn box_test8() -> Box<Rc<SubT<usize>>> {
+        unimplemented!();
+    }
 
-pub fn test4_neg(foo: Rc<SubT<&usize>>) {}
+    pub fn box_test9<T>(foo: Box<Arc<T>>) -> Box<Arc<SubT<T>>> {
+        unimplemented!();
+    }
+}
 
-// Rc<Rc<T>>
+mod outer_rc {
+    use crate::MyEnum;
+    use crate::MyStruct;
+    use crate::SubT;
+    use std::boxed::Box;
+    use std::rc::Rc;
+    use std::sync::Arc;
 
-pub fn test5(a: Rc<Rc<bool>>) {}
+    pub fn rc_test5(a: Rc<Box<bool>>) {}
 
-// Rc<Box<T>>
+    pub fn rc_test7(a: Rc<Arc<bool>>) {}
 
-pub fn test6(a: Rc<Box<bool>>) {}
+    pub fn rc_test8() -> Rc<Box<SubT<usize>>> {
+        unimplemented!();
+    }
 
-// Box<&T>
+    pub fn rc_test9<T>(foo: Rc<Arc<T>>) -> Rc<Arc<SubT<T>>> {
+        unimplemented!();
+    }
+}
 
-pub fn test7<T>(foo: Box<&T>) {}
+mod outer_arc {
+    use crate::MyEnum;
+    use crate::MyStruct;
+    use crate::SubT;
+    use std::boxed::Box;
+    use std::rc::Rc;
+    use std::sync::Arc;
 
-pub fn test8(foo: Box<&MyStruct>) {}
+    pub fn arc_test5(a: Arc<Box<bool>>) {}
 
-pub fn test9(foo: Box<&MyEnum>) {}
+    pub fn arc_test6(a: Arc<Rc<bool>>) {}
 
-pub fn test10_neg(foo: Box<SubT<&usize>>) {}
+    pub fn arc_test8() -> Arc<Box<SubT<usize>>> {
+        unimplemented!();
+    }
+
+    pub fn arc_test9<T>(foo: Arc<Rc<T>>) -> Arc<Rc<SubT<T>>> {
+        unimplemented!();
+    }
+}
 
 fn main() {}
index 92e4f67f5db6e40e6f2f0f9bd8ed422b3ec32c0c..fdab74eb538e3e7c88cc341707db01439c91395b 100644 (file)
-error: usage of `Rc<&T>`
-  --> $DIR/redundant_allocation.rs:22:22
+error: usage of `Box<Rc<T>>`
+  --> $DIR/redundant_allocation.rs:25:30
    |
-LL | pub fn test1<T>(foo: Rc<&T>) {}
-   |                      ^^^^^^ help: try: `&T`
+LL |     pub fn box_test6<T>(foo: Box<Rc<T>>) {}
+   |                              ^^^^^^^^^^
    |
    = note: `-D clippy::redundant-allocation` implied by `-D warnings`
+   = note: `Rc<T>` is already on the heap, `Box<Rc<T>>` makes an extra allocation
+   = help: consider using just `Box<T>` or `Rc<T>`
 
-error: usage of `Rc<&T>`
-  --> $DIR/redundant_allocation.rs:24:19
+error: usage of `Box<Arc<T>>`
+  --> $DIR/redundant_allocation.rs:27:30
    |
-LL | pub fn test2(foo: Rc<&MyStruct>) {}
-   |                   ^^^^^^^^^^^^^ help: try: `&MyStruct`
+LL |     pub fn box_test7<T>(foo: Box<Arc<T>>) {}
+   |                              ^^^^^^^^^^^
+   |
+   = note: `Arc<T>` is already on the heap, `Box<Arc<T>>` makes an extra allocation
+   = help: consider using just `Box<T>` or `Arc<T>`
+
+error: usage of `Box<Rc<SubT<usize>>>`
+  --> $DIR/redundant_allocation.rs:29:27
+   |
+LL |     pub fn box_test8() -> Box<Rc<SubT<usize>>> {
+   |                           ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Rc<SubT<usize>>` is already on the heap, `Box<Rc<SubT<usize>>>` makes an extra allocation
+   = help: consider using just `Box<SubT<usize>>` or `Rc<SubT<usize>>`
+
+error: usage of `Box<Arc<T>>`
+  --> $DIR/redundant_allocation.rs:33:30
+   |
+LL |     pub fn box_test9<T>(foo: Box<Arc<T>>) -> Box<Arc<SubT<T>>> {
+   |                              ^^^^^^^^^^^
+   |
+   = note: `Arc<T>` is already on the heap, `Box<Arc<T>>` makes an extra allocation
+   = help: consider using just `Box<T>` or `Arc<T>`
+
+error: usage of `Box<Arc<SubT<T>>>`
+  --> $DIR/redundant_allocation.rs:33:46
+   |
+LL |     pub fn box_test9<T>(foo: Box<Arc<T>>) -> Box<Arc<SubT<T>>> {
+   |                                              ^^^^^^^^^^^^^^^^^
+   |
+   = note: `Arc<SubT<T>>` is already on the heap, `Box<Arc<SubT<T>>>` makes an extra allocation
+   = help: consider using just `Box<SubT<T>>` or `Arc<SubT<T>>`
+
+error: usage of `Rc<Box<bool>>`
+  --> $DIR/redundant_allocation.rs:46:24
+   |
+LL |     pub fn rc_test5(a: Rc<Box<bool>>) {}
+   |                        ^^^^^^^^^^^^^
+   |
+   = note: `Box<bool>` is already on the heap, `Rc<Box<bool>>` makes an extra allocation
+   = help: consider using just `Rc<bool>` or `Box<bool>`
+
+error: usage of `Rc<Arc<bool>>`
+  --> $DIR/redundant_allocation.rs:48:24
+   |
+LL |     pub fn rc_test7(a: Rc<Arc<bool>>) {}
+   |                        ^^^^^^^^^^^^^
+   |
+   = note: `Arc<bool>` is already on the heap, `Rc<Arc<bool>>` makes an extra allocation
+   = help: consider using just `Rc<bool>` or `Arc<bool>`
+
+error: usage of `Rc<Box<SubT<usize>>>`
+  --> $DIR/redundant_allocation.rs:50:26
+   |
+LL |     pub fn rc_test8() -> Rc<Box<SubT<usize>>> {
+   |                          ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Box<SubT<usize>>` is already on the heap, `Rc<Box<SubT<usize>>>` makes an extra allocation
+   = help: consider using just `Rc<SubT<usize>>` or `Box<SubT<usize>>`
+
+error: usage of `Rc<Arc<T>>`
+  --> $DIR/redundant_allocation.rs:54:29
+   |
+LL |     pub fn rc_test9<T>(foo: Rc<Arc<T>>) -> Rc<Arc<SubT<T>>> {
+   |                             ^^^^^^^^^^
+   |
+   = note: `Arc<T>` is already on the heap, `Rc<Arc<T>>` makes an extra allocation
+   = help: consider using just `Rc<T>` or `Arc<T>`
 
-error: usage of `Rc<&T>`
-  --> $DIR/redundant_allocation.rs:26:19
+error: usage of `Rc<Arc<SubT<T>>>`
+  --> $DIR/redundant_allocation.rs:54:44
+   |
+LL |     pub fn rc_test9<T>(foo: Rc<Arc<T>>) -> Rc<Arc<SubT<T>>> {
+   |                                            ^^^^^^^^^^^^^^^^
    |
-LL | pub fn test3(foo: Rc<&MyEnum>) {}
-   |                   ^^^^^^^^^^^ help: try: `&MyEnum`
+   = note: `Arc<SubT<T>>` is already on the heap, `Rc<Arc<SubT<T>>>` makes an extra allocation
+   = help: consider using just `Rc<SubT<T>>` or `Arc<SubT<T>>`
 
-error: usage of `Rc<Rc<T>>`
-  --> $DIR/redundant_allocation.rs:32:17
+error: usage of `Arc<Box<bool>>`
+  --> $DIR/redundant_allocation.rs:67:25
    |
-LL | pub fn test5(a: Rc<Rc<bool>>) {}
-   |                 ^^^^^^^^^^^^ help: try: `Rc<bool>`
+LL |     pub fn arc_test5(a: Arc<Box<bool>>) {}
+   |                         ^^^^^^^^^^^^^^
+   |
+   = note: `Box<bool>` is already on the heap, `Arc<Box<bool>>` makes an extra allocation
+   = help: consider using just `Arc<bool>` or `Box<bool>`
 
-error: usage of `Rc<Box<T>>`
-  --> $DIR/redundant_allocation.rs:36:17
+error: usage of `Arc<Rc<bool>>`
+  --> $DIR/redundant_allocation.rs:69:25
+   |
+LL |     pub fn arc_test6(a: Arc<Rc<bool>>) {}
+   |                         ^^^^^^^^^^^^^
    |
-LL | pub fn test6(a: Rc<Box<bool>>) {}
-   |                 ^^^^^^^^^^^^^ help: try: `Rc<bool>`
+   = note: `Rc<bool>` is already on the heap, `Arc<Rc<bool>>` makes an extra allocation
+   = help: consider using just `Arc<bool>` or `Rc<bool>`
 
-error: usage of `Box<&T>`
-  --> $DIR/redundant_allocation.rs:40:22
+error: usage of `Arc<Box<SubT<usize>>>`
+  --> $DIR/redundant_allocation.rs:71:27
    |
-LL | pub fn test7<T>(foo: Box<&T>) {}
-   |                      ^^^^^^^ help: try: `&T`
+LL |     pub fn arc_test8() -> Arc<Box<SubT<usize>>> {
+   |                           ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Box<SubT<usize>>` is already on the heap, `Arc<Box<SubT<usize>>>` makes an extra allocation
+   = help: consider using just `Arc<SubT<usize>>` or `Box<SubT<usize>>`
 
-error: usage of `Box<&T>`
-  --> $DIR/redundant_allocation.rs:42:19
+error: usage of `Arc<Rc<T>>`
+  --> $DIR/redundant_allocation.rs:75:30
+   |
+LL |     pub fn arc_test9<T>(foo: Arc<Rc<T>>) -> Arc<Rc<SubT<T>>> {
+   |                              ^^^^^^^^^^
    |
-LL | pub fn test8(foo: Box<&MyStruct>) {}
-   |                   ^^^^^^^^^^^^^^ help: try: `&MyStruct`
+   = note: `Rc<T>` is already on the heap, `Arc<Rc<T>>` makes an extra allocation
+   = help: consider using just `Arc<T>` or `Rc<T>`
 
-error: usage of `Box<&T>`
-  --> $DIR/redundant_allocation.rs:44:19
+error: usage of `Arc<Rc<SubT<T>>>`
+  --> $DIR/redundant_allocation.rs:75:45
+   |
+LL |     pub fn arc_test9<T>(foo: Arc<Rc<T>>) -> Arc<Rc<SubT<T>>> {
+   |                                             ^^^^^^^^^^^^^^^^
    |
-LL | pub fn test9(foo: Box<&MyEnum>) {}
-   |                   ^^^^^^^^^^^^ help: try: `&MyEnum`
+   = note: `Rc<SubT<T>>` is already on the heap, `Arc<Rc<SubT<T>>>` makes an extra allocation
+   = help: consider using just `Arc<SubT<T>>` or `Rc<SubT<T>>`
 
-error: aborting due to 8 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed b/src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed
new file mode 100644 (file)
index 0000000..ef089b2
--- /dev/null
@@ -0,0 +1,75 @@
+// run-rustfix
+#![warn(clippy::all)]
+#![allow(clippy::boxed_local, clippy::needless_pass_by_value)]
+#![allow(clippy::blacklisted_name, unused_variables, dead_code)]
+#![allow(unused_imports)]
+
+pub struct MyStruct {}
+
+pub struct SubT<T> {
+    foo: T,
+}
+
+pub enum MyEnum {
+    One,
+    Two,
+}
+
+mod outer_box {
+    use crate::MyEnum;
+    use crate::MyStruct;
+    use crate::SubT;
+    use std::boxed::Box;
+    use std::rc::Rc;
+    use std::sync::Arc;
+
+    pub fn box_test1<T>(foo: &T) {}
+
+    pub fn box_test2(foo: &MyStruct) {}
+
+    pub fn box_test3(foo: &MyEnum) {}
+
+    pub fn box_test4_neg(foo: Box<SubT<&usize>>) {}
+
+    pub fn box_test5<T>(foo: Box<T>) {}
+}
+
+mod outer_rc {
+    use crate::MyEnum;
+    use crate::MyStruct;
+    use crate::SubT;
+    use std::boxed::Box;
+    use std::rc::Rc;
+    use std::sync::Arc;
+
+    pub fn rc_test1<T>(foo: &T) {}
+
+    pub fn rc_test2(foo: &MyStruct) {}
+
+    pub fn rc_test3(foo: &MyEnum) {}
+
+    pub fn rc_test4_neg(foo: Rc<SubT<&usize>>) {}
+
+    pub fn rc_test6(a: Rc<bool>) {}
+}
+
+mod outer_arc {
+    use crate::MyEnum;
+    use crate::MyStruct;
+    use crate::SubT;
+    use std::boxed::Box;
+    use std::rc::Rc;
+    use std::sync::Arc;
+
+    pub fn arc_test1<T>(foo: &T) {}
+
+    pub fn arc_test2(foo: &MyStruct) {}
+
+    pub fn arc_test3(foo: &MyEnum) {}
+
+    pub fn arc_test4_neg(foo: Arc<SubT<&usize>>) {}
+
+    pub fn arc_test7(a: Arc<bool>) {}
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/redundant_allocation_fixable.rs b/src/tools/clippy/tests/ui/redundant_allocation_fixable.rs
new file mode 100644 (file)
index 0000000..fefa877
--- /dev/null
@@ -0,0 +1,75 @@
+// run-rustfix
+#![warn(clippy::all)]
+#![allow(clippy::boxed_local, clippy::needless_pass_by_value)]
+#![allow(clippy::blacklisted_name, unused_variables, dead_code)]
+#![allow(unused_imports)]
+
+pub struct MyStruct {}
+
+pub struct SubT<T> {
+    foo: T,
+}
+
+pub enum MyEnum {
+    One,
+    Two,
+}
+
+mod outer_box {
+    use crate::MyEnum;
+    use crate::MyStruct;
+    use crate::SubT;
+    use std::boxed::Box;
+    use std::rc::Rc;
+    use std::sync::Arc;
+
+    pub fn box_test1<T>(foo: Box<&T>) {}
+
+    pub fn box_test2(foo: Box<&MyStruct>) {}
+
+    pub fn box_test3(foo: Box<&MyEnum>) {}
+
+    pub fn box_test4_neg(foo: Box<SubT<&usize>>) {}
+
+    pub fn box_test5<T>(foo: Box<Box<T>>) {}
+}
+
+mod outer_rc {
+    use crate::MyEnum;
+    use crate::MyStruct;
+    use crate::SubT;
+    use std::boxed::Box;
+    use std::rc::Rc;
+    use std::sync::Arc;
+
+    pub fn rc_test1<T>(foo: Rc<&T>) {}
+
+    pub fn rc_test2(foo: Rc<&MyStruct>) {}
+
+    pub fn rc_test3(foo: Rc<&MyEnum>) {}
+
+    pub fn rc_test4_neg(foo: Rc<SubT<&usize>>) {}
+
+    pub fn rc_test6(a: Rc<Rc<bool>>) {}
+}
+
+mod outer_arc {
+    use crate::MyEnum;
+    use crate::MyStruct;
+    use crate::SubT;
+    use std::boxed::Box;
+    use std::rc::Rc;
+    use std::sync::Arc;
+
+    pub fn arc_test1<T>(foo: Arc<&T>) {}
+
+    pub fn arc_test2(foo: Arc<&MyStruct>) {}
+
+    pub fn arc_test3(foo: Arc<&MyEnum>) {}
+
+    pub fn arc_test4_neg(foo: Arc<SubT<&usize>>) {}
+
+    pub fn arc_test7(a: Arc<Arc<bool>>) {}
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/redundant_allocation_fixable.stderr b/src/tools/clippy/tests/ui/redundant_allocation_fixable.stderr
new file mode 100644 (file)
index 0000000..fdd76ef
--- /dev/null
@@ -0,0 +1,99 @@
+error: usage of `Box<&T>`
+  --> $DIR/redundant_allocation_fixable.rs:26:30
+   |
+LL |     pub fn box_test1<T>(foo: Box<&T>) {}
+   |                              ^^^^^^^ help: try: `&T`
+   |
+   = note: `-D clippy::redundant-allocation` implied by `-D warnings`
+   = note: `&T` is already a pointer, `Box<&T>` allocates a pointer on the heap
+
+error: usage of `Box<&MyStruct>`
+  --> $DIR/redundant_allocation_fixable.rs:28:27
+   |
+LL |     pub fn box_test2(foo: Box<&MyStruct>) {}
+   |                           ^^^^^^^^^^^^^^ help: try: `&MyStruct`
+   |
+   = note: `&MyStruct` is already a pointer, `Box<&MyStruct>` allocates a pointer on the heap
+
+error: usage of `Box<&MyEnum>`
+  --> $DIR/redundant_allocation_fixable.rs:30:27
+   |
+LL |     pub fn box_test3(foo: Box<&MyEnum>) {}
+   |                           ^^^^^^^^^^^^ help: try: `&MyEnum`
+   |
+   = note: `&MyEnum` is already a pointer, `Box<&MyEnum>` allocates a pointer on the heap
+
+error: usage of `Box<Box<T>>`
+  --> $DIR/redundant_allocation_fixable.rs:34:30
+   |
+LL |     pub fn box_test5<T>(foo: Box<Box<T>>) {}
+   |                              ^^^^^^^^^^^ help: try: `Box<T>`
+   |
+   = note: `Box<T>` is already on the heap, `Box<Box<T>>` makes an extra allocation
+
+error: usage of `Rc<&T>`
+  --> $DIR/redundant_allocation_fixable.rs:45:29
+   |
+LL |     pub fn rc_test1<T>(foo: Rc<&T>) {}
+   |                             ^^^^^^ help: try: `&T`
+   |
+   = note: `&T` is already a pointer, `Rc<&T>` allocates a pointer on the heap
+
+error: usage of `Rc<&MyStruct>`
+  --> $DIR/redundant_allocation_fixable.rs:47:26
+   |
+LL |     pub fn rc_test2(foo: Rc<&MyStruct>) {}
+   |                          ^^^^^^^^^^^^^ help: try: `&MyStruct`
+   |
+   = note: `&MyStruct` is already a pointer, `Rc<&MyStruct>` allocates a pointer on the heap
+
+error: usage of `Rc<&MyEnum>`
+  --> $DIR/redundant_allocation_fixable.rs:49:26
+   |
+LL |     pub fn rc_test3(foo: Rc<&MyEnum>) {}
+   |                          ^^^^^^^^^^^ help: try: `&MyEnum`
+   |
+   = note: `&MyEnum` is already a pointer, `Rc<&MyEnum>` allocates a pointer on the heap
+
+error: usage of `Rc<Rc<bool>>`
+  --> $DIR/redundant_allocation_fixable.rs:53:24
+   |
+LL |     pub fn rc_test6(a: Rc<Rc<bool>>) {}
+   |                        ^^^^^^^^^^^^ help: try: `Rc<bool>`
+   |
+   = note: `Rc<bool>` is already on the heap, `Rc<Rc<bool>>` makes an extra allocation
+
+error: usage of `Arc<&T>`
+  --> $DIR/redundant_allocation_fixable.rs:64:30
+   |
+LL |     pub fn arc_test1<T>(foo: Arc<&T>) {}
+   |                              ^^^^^^^ help: try: `&T`
+   |
+   = note: `&T` is already a pointer, `Arc<&T>` allocates a pointer on the heap
+
+error: usage of `Arc<&MyStruct>`
+  --> $DIR/redundant_allocation_fixable.rs:66:27
+   |
+LL |     pub fn arc_test2(foo: Arc<&MyStruct>) {}
+   |                           ^^^^^^^^^^^^^^ help: try: `&MyStruct`
+   |
+   = note: `&MyStruct` is already a pointer, `Arc<&MyStruct>` allocates a pointer on the heap
+
+error: usage of `Arc<&MyEnum>`
+  --> $DIR/redundant_allocation_fixable.rs:68:27
+   |
+LL |     pub fn arc_test3(foo: Arc<&MyEnum>) {}
+   |                           ^^^^^^^^^^^^ help: try: `&MyEnum`
+   |
+   = note: `&MyEnum` is already a pointer, `Arc<&MyEnum>` allocates a pointer on the heap
+
+error: usage of `Arc<Arc<bool>>`
+  --> $DIR/redundant_allocation_fixable.rs:72:25
+   |
+LL |     pub fn arc_test7(a: Arc<Arc<bool>>) {}
+   |                         ^^^^^^^^^^^^^^ help: try: `Arc<bool>`
+   |
+   = note: `Arc<bool>` is already on the heap, `Arc<Arc<bool>>` makes an extra allocation
+
+error: aborting due to 12 previous errors
+
index f5da703cd1dea5e9d524f8c2950ec629525faec2..2d711082746e73aab40867f0bcc2285137e5aca2 100644 (file)
@@ -55,6 +55,8 @@ fn main() {
     issue_5405();
     manually_drop();
     clone_then_move_cloned();
+    hashmap_neg();
+    false_negative_5707();
 }
 
 #[derive(Clone)]
@@ -206,3 +208,29 @@ fn clone_then_move_cloned() {
     let mut x = S(String::new());
     x.0.clone().chars().for_each(|_| x.m());
 }
+
+fn hashmap_neg() {
+    // issue 5707
+    use std::collections::HashMap;
+    use std::path::PathBuf;
+
+    let p = PathBuf::from("/");
+
+    let mut h: HashMap<&str, &str> = HashMap::new();
+    h.insert("orig-p", p.to_str().unwrap());
+
+    let mut q = p.clone();
+    q.push("foo");
+
+    println!("{:?} {}", h, q.display());
+}
+
+fn false_negative_5707() {
+    fn foo(_x: &Alpha, _y: &mut Alpha) {}
+
+    let x = Alpha;
+    let mut y = Alpha;
+    foo(&x, &mut y);
+    let _z = x.clone(); // pr 7346 can't lint on `x`
+    drop(y);
+}
index fd7f31a1cc5b6b944a635ff0282477600f7268b7..bd3d7365229fb83ccd13ca555e53d9941f867c43 100644 (file)
@@ -55,6 +55,8 @@ fn main() {
     issue_5405();
     manually_drop();
     clone_then_move_cloned();
+    hashmap_neg();
+    false_negative_5707();
 }
 
 #[derive(Clone)]
@@ -206,3 +208,29 @@ fn clone_then_move_cloned() {
     let mut x = S(String::new());
     x.0.clone().chars().for_each(|_| x.m());
 }
+
+fn hashmap_neg() {
+    // issue 5707
+    use std::collections::HashMap;
+    use std::path::PathBuf;
+
+    let p = PathBuf::from("/");
+
+    let mut h: HashMap<&str, &str> = HashMap::new();
+    h.insert("orig-p", p.to_str().unwrap());
+
+    let mut q = p.clone();
+    q.push("foo");
+
+    println!("{:?} {}", h, q.display());
+}
+
+fn false_negative_5707() {
+    fn foo(_x: &Alpha, _y: &mut Alpha) {}
+
+    let x = Alpha;
+    let mut y = Alpha;
+    foo(&x, &mut y);
+    let _z = x.clone(); // pr 7346 can't lint on `x`
+    drop(y);
+}
index 529a6de91e266baa93294822e2337b1401e035b2..fbc90493ae94b85986e8381ef82e395fbc202e9e 100644 (file)
@@ -108,61 +108,61 @@ LL |     let _t = tup.0.clone();
    |              ^^^^^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:63:25
+  --> $DIR/redundant_clone.rs:65:25
    |
 LL |     if b { (a.clone(), a.clone()) } else { (Alpha, a) }
    |                         ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:63:24
+  --> $DIR/redundant_clone.rs:65:24
    |
 LL |     if b { (a.clone(), a.clone()) } else { (Alpha, a) }
    |                        ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:120:15
+  --> $DIR/redundant_clone.rs:122:15
    |
 LL |     let _s = s.clone();
    |               ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:120:14
+  --> $DIR/redundant_clone.rs:122:14
    |
 LL |     let _s = s.clone();
    |              ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:121:15
+  --> $DIR/redundant_clone.rs:123:15
    |
 LL |     let _t = t.clone();
    |               ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:121:14
+  --> $DIR/redundant_clone.rs:123:14
    |
 LL |     let _t = t.clone();
    |              ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:131:19
+  --> $DIR/redundant_clone.rs:133:19
    |
 LL |         let _f = f.clone();
    |                   ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:131:18
+  --> $DIR/redundant_clone.rs:133:18
    |
 LL |         let _f = f.clone();
    |                  ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:143:14
+  --> $DIR/redundant_clone.rs:145:14
    |
 LL |     let y = x.clone().join("matthias");
    |              ^^^^^^^^ help: remove this
    |
 note: cloned value is neither consumed nor mutated
-  --> $DIR/redundant_clone.rs:143:13
+  --> $DIR/redundant_clone.rs:145:13
    |
 LL |     let y = x.clone().join("matthias");
    |             ^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/self_named_constructors.rs b/src/tools/clippy/tests/ui/self_named_constructors.rs
new file mode 100644 (file)
index 0000000..356f701
--- /dev/null
@@ -0,0 +1,59 @@
+#![warn(clippy::self_named_constructors)]
+
+struct ShouldSpawn;
+struct ShouldNotSpawn;
+
+impl ShouldSpawn {
+    pub fn should_spawn() -> ShouldSpawn {
+        ShouldSpawn
+    }
+
+    fn should_not_spawn() -> ShouldNotSpawn {
+        ShouldNotSpawn
+    }
+}
+
+impl ShouldNotSpawn {
+    pub fn new() -> ShouldNotSpawn {
+        ShouldNotSpawn
+    }
+}
+
+struct ShouldNotSpawnWithTrait;
+
+trait ShouldNotSpawnTrait {
+    type Item;
+}
+
+impl ShouldNotSpawnTrait for ShouldNotSpawnWithTrait {
+    type Item = Self;
+}
+
+impl ShouldNotSpawnWithTrait {
+    pub fn should_not_spawn_with_trait() -> impl ShouldNotSpawnTrait<Item = Self> {
+        ShouldNotSpawnWithTrait
+    }
+}
+
+// Same trait name and same type name should not spawn the lint
+#[derive(Default)]
+pub struct Default;
+
+trait TraitSameTypeName {
+    fn should_not_spawn() -> Self;
+}
+impl TraitSameTypeName for ShouldNotSpawn {
+    fn should_not_spawn() -> Self {
+        ShouldNotSpawn
+    }
+}
+
+struct SelfMethodShouldNotSpawn;
+
+impl SelfMethodShouldNotSpawn {
+    fn self_method_should_not_spawn(self) -> Self {
+        SelfMethodShouldNotSpawn
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/self_named_constructors.stderr b/src/tools/clippy/tests/ui/self_named_constructors.stderr
new file mode 100644 (file)
index 0000000..ba989f0
--- /dev/null
@@ -0,0 +1,12 @@
+error: constructor `should_spawn` has the same name as the type
+  --> $DIR/self_named_constructors.rs:7:5
+   |
+LL | /     pub fn should_spawn() -> ShouldSpawn {
+LL | |         ShouldSpawn
+LL | |     }
+   | |_____^
+   |
+   = note: `-D clippy::self-named-constructors` implied by `-D warnings`
+
+error: aborting due to previous error
+
index 0abe2cca26757325fc4f7d16c45d9d07ea5912f2..79ba7402f1f49285a79b0de83952e5f46c272333 100644 (file)
@@ -17,6 +17,24 @@ fn basic101(x: i32) {
     y = x + 1
 }
 
+#[rustfmt::skip]
+fn closure_error() {
+    let _d = || {
+        hello()
+    };
+}
+
+#[rustfmt::skip]
+fn unsafe_checks_error() {
+    use std::mem::MaybeUninit;
+    use std::ptr;
+
+    let mut s = MaybeUninit::<String>::uninit();
+    let _d = || unsafe { 
+        ptr::drop_in_place(s.as_mut_ptr()) 
+    };
+}
+
 // this is fine
 fn print_sum(a: i32, b: i32) {
     println!("{}", a + b);
@@ -53,3 +71,29 @@ fn loop_test(x: i32) {
         println!("{}", ext);
     }
 }
+
+fn closure() {
+    let _d = || hello();
+}
+
+#[rustfmt::skip]
+fn closure_block() {
+    let _d = || { hello() };
+}
+
+unsafe fn some_unsafe_op() {}
+unsafe fn some_other_unsafe_fn() {}
+
+fn do_something() {
+    unsafe { some_unsafe_op() };
+
+    unsafe { some_other_unsafe_fn() };
+}
+
+fn unsafe_checks() {
+    use std::mem::MaybeUninit;
+    use std::ptr;
+
+    let mut s = MaybeUninit::<String>::uninit();
+    let _d = || unsafe { ptr::drop_in_place(s.as_mut_ptr()) };
+}
index b73f89675383f12d53aeb4298898502c443af5b0..e88ebe2ad35f0bcacf64ed5f8ee3bc57e1227ae7 100644 (file)
@@ -18,5 +18,17 @@ error: consider adding a `;` to the last statement for consistent formatting
 LL |     y = x + 1
    |     ^^^^^^^^^ help: add a `;` here: `y = x + 1;`
 
-error: aborting due to 3 previous errors
+error: consider adding a `;` to the last statement for consistent formatting
+  --> $DIR/semicolon_if_nothing_returned.rs:23:9
+   |
+LL |         hello()
+   |         ^^^^^^^ help: add a `;` here: `hello();`
+
+error: consider adding a `;` to the last statement for consistent formatting
+  --> $DIR/semicolon_if_nothing_returned.rs:34:9
+   |
+LL |         ptr::drop_in_place(s.as_mut_ptr()) 
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `ptr::drop_in_place(s.as_mut_ptr());`
+
+error: aborting due to 5 previous errors
 
diff --git a/src/tools/clippy/tests/ui/strlen_on_c_strings.rs b/src/tools/clippy/tests/ui/strlen_on_c_strings.rs
new file mode 100644 (file)
index 0000000..21902fa
--- /dev/null
@@ -0,0 +1,16 @@
+#![warn(clippy::strlen_on_c_strings)]
+#![allow(dead_code)]
+#![feature(rustc_private)]
+extern crate libc;
+
+use std::ffi::{CStr, CString};
+
+fn main() {
+    // CString
+    let cstring = CString::new("foo").expect("CString::new failed");
+    let len = unsafe { libc::strlen(cstring.as_ptr()) };
+
+    // CStr
+    let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
+    let len = unsafe { libc::strlen(cstr.as_ptr()) };
+}
diff --git a/src/tools/clippy/tests/ui/strlen_on_c_strings.stderr b/src/tools/clippy/tests/ui/strlen_on_c_strings.stderr
new file mode 100644 (file)
index 0000000..a212bd3
--- /dev/null
@@ -0,0 +1,25 @@
+error: using `libc::strlen` on a `CString` or `CStr` value
+  --> $DIR/strlen_on_c_strings.rs:11:24
+   |
+LL |     let len = unsafe { libc::strlen(cstring.as_ptr()) };
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::strlen-on-c-strings` implied by `-D warnings`
+help: try this (you might also need to get rid of `unsafe` block in some cases):
+   |
+LL |     let len = unsafe { cstring.as_bytes().len() };
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: using `libc::strlen` on a `CString` or `CStr` value
+  --> $DIR/strlen_on_c_strings.rs:15:24
+   |
+LL |     let len = unsafe { libc::strlen(cstr.as_ptr()) };
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try this (you might also need to get rid of `unsafe` block in some cases):
+   |
+LL |     let len = unsafe { cstr.to_bytes().len() };
+   |                        ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
index 388fc7400820947ab912c088099d94e20391995d..ced1305874e58611862db7bdccddc65428b911fa 100644 (file)
@@ -1,4 +1,4 @@
-error: suspicious use of binary operator in `Add` impl
+error: suspicious use of `-` in `Add` impl
   --> $DIR/suspicious_arithmetic_impl.rs:13:20
    |
 LL |         Foo(self.0 - other.0)
@@ -6,51 +6,51 @@ LL |         Foo(self.0 - other.0)
    |
    = note: `-D clippy::suspicious-arithmetic-impl` implied by `-D warnings`
 
-error: suspicious use of binary operator in `AddAssign` impl
+error: suspicious use of `-` in `AddAssign` impl
   --> $DIR/suspicious_arithmetic_impl.rs:19:23
    |
 LL |         *self = *self - other;
    |                       ^
    |
-   = note: `#[deny(clippy::suspicious_op_assign_impl)]` on by default
+   = note: `-D clippy::suspicious-op-assign-impl` implied by `-D warnings`
 
-error: suspicious use of binary operator in `MulAssign` impl
+error: suspicious use of `/` in `MulAssign` impl
   --> $DIR/suspicious_arithmetic_impl.rs:32:16
    |
 LL |         self.0 /= other.0;
    |                ^^
 
-error: suspicious use of binary operator in `Rem` impl
+error: suspicious use of `/` in `Rem` impl
   --> $DIR/suspicious_arithmetic_impl.rs:70:20
    |
 LL |         Foo(self.0 / other.0)
    |                    ^
 
-error: suspicious use of binary operator in `BitAnd` impl
+error: suspicious use of `|` in `BitAnd` impl
   --> $DIR/suspicious_arithmetic_impl.rs:78:20
    |
 LL |         Foo(self.0 | other.0)
    |                    ^
 
-error: suspicious use of binary operator in `BitOr` impl
+error: suspicious use of `^` in `BitOr` impl
   --> $DIR/suspicious_arithmetic_impl.rs:86:20
    |
 LL |         Foo(self.0 ^ other.0)
    |                    ^
 
-error: suspicious use of binary operator in `BitXor` impl
+error: suspicious use of `&` in `BitXor` impl
   --> $DIR/suspicious_arithmetic_impl.rs:94:20
    |
 LL |         Foo(self.0 & other.0)
    |                    ^
 
-error: suspicious use of binary operator in `Shl` impl
+error: suspicious use of `>>` in `Shl` impl
   --> $DIR/suspicious_arithmetic_impl.rs:102:20
    |
 LL |         Foo(self.0 >> other.0)
    |                    ^^
 
-error: suspicious use of binary operator in `Shr` impl
+error: suspicious use of `<<` in `Shr` impl
   --> $DIR/suspicious_arithmetic_impl.rs:110:20
    |
 LL |         Foo(self.0 << other.0)
index 938cc3c785978f6b929bc6bd1d1d3eac799c32e6..535683729f686a965f7aab4618adae726a9c6aee 100644 (file)
@@ -6,7 +6,8 @@
     clippy::unused_unit,
     clippy::unnecessary_wraps,
     clippy::or_fun_call,
-    clippy::needless_question_mark
+    clippy::needless_question_mark,
+    clippy::self_named_constructors
 )]
 
 use std::fmt::Debug;
index 354fd51cd6b608954dd7e84888206744824cd4de..8155c4ae1107b23f57ac42a0439381850f975fdb 100644 (file)
@@ -1,5 +1,5 @@
 error: passing a unit value to a function
-  --> $DIR/unit_arg.rs:55:5
+  --> $DIR/unit_arg.rs:56:5
    |
 LL | /     foo({
 LL | |         1;
@@ -20,7 +20,7 @@ LL |     foo(());
    |
 
 error: passing a unit value to a function
-  --> $DIR/unit_arg.rs:58:5
+  --> $DIR/unit_arg.rs:59:5
    |
 LL |     foo(foo(1));
    |     ^^^^^^^^^^^
@@ -32,7 +32,7 @@ LL |     foo(());
    |
 
 error: passing a unit value to a function
-  --> $DIR/unit_arg.rs:59:5
+  --> $DIR/unit_arg.rs:60:5
    |
 LL | /     foo({
 LL | |         foo(1);
@@ -54,7 +54,7 @@ LL |     foo(());
    |
 
 error: passing a unit value to a function
-  --> $DIR/unit_arg.rs:64:5
+  --> $DIR/unit_arg.rs:65:5
    |
 LL | /     b.bar({
 LL | |         1;
@@ -74,7 +74,7 @@ LL |     b.bar(());
    |
 
 error: passing unit values to a function
-  --> $DIR/unit_arg.rs:67:5
+  --> $DIR/unit_arg.rs:68:5
    |
 LL |     taking_multiple_units(foo(0), foo(1));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -87,7 +87,7 @@ LL |     taking_multiple_units((), ());
    |
 
 error: passing unit values to a function
-  --> $DIR/unit_arg.rs:68:5
+  --> $DIR/unit_arg.rs:69:5
    |
 LL | /     taking_multiple_units(foo(0), {
 LL | |         foo(1);
@@ -110,7 +110,7 @@ LL |     taking_multiple_units((), ());
    |
 
 error: passing unit values to a function
-  --> $DIR/unit_arg.rs:72:5
+  --> $DIR/unit_arg.rs:73:5
    |
 LL | /     taking_multiple_units(
 LL | |         {
@@ -140,7 +140,7 @@ LL |         foo(2);
  ...
 
 error: passing a unit value to a function
-  --> $DIR/unit_arg.rs:83:13
+  --> $DIR/unit_arg.rs:84:13
    |
 LL |     None.or(Some(foo(2)));
    |             ^^^^^^^^^^^^
@@ -154,7 +154,7 @@ LL |     });
    |
 
 error: passing a unit value to a function
-  --> $DIR/unit_arg.rs:86:5
+  --> $DIR/unit_arg.rs:87:5
    |
 LL |     foo(foo(()));
    |     ^^^^^^^^^^^^
@@ -166,7 +166,7 @@ LL |     foo(());
    |
 
 error: passing a unit value to a function
-  --> $DIR/unit_arg.rs:123:5
+  --> $DIR/unit_arg.rs:124:5
    |
 LL |     Some(foo(1))
    |     ^^^^^^^^^^^^
index 7fbce58a82f8e340e7d1ddc76eeb65732de23e7d..bda0f2c47cdd525a97a62f5e080334dc20e627c8 100644 (file)
@@ -1,7 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::unnecessary_cast)]
-#![allow(clippy::no_effect, clippy::unnecessary_operation)]
+#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::nonstandard_macro_braces)]
 
 fn main() {
     // casting integer literal to float is unnecessary
index a71363ea4d265ac86a4aaf3081fdc5aabdd62536..f7a4f2a5988fd42c38fc5dca1c255a7a556e07ba 100644 (file)
@@ -1,7 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::unnecessary_cast)]
-#![allow(clippy::no_effect, clippy::unnecessary_operation)]
+#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::nonstandard_macro_braces)]
 
 fn main() {
     // casting integer literal to float is unnecessary
index 631da6fe066dde1703ee467b7d7e56a837e44d54..dcf818f80763052c6d4fae4d6e282b0b67c438c2 100644 (file)
@@ -4,7 +4,12 @@
 
 #![warn(clippy::use_self)]
 #![allow(dead_code)]
-#![allow(clippy::should_implement_trait, clippy::upper_case_acronyms, clippy::from_over_into)]
+#![allow(
+    clippy::should_implement_trait,
+    clippy::upper_case_acronyms,
+    clippy::from_over_into,
+    clippy::self_named_constructors
+)]
 
 #[macro_use]
 extern crate proc_macro_derive;
@@ -492,3 +497,26 @@ mod issue7206 {
         }
     }
 }
+
+mod self_is_ty_param {
+    trait Trait {
+        type Type;
+        type Hi;
+
+        fn test();
+    }
+
+    impl<I> Trait for I
+    where
+        I: Iterator,
+        I::Item: Trait, // changing this to Self would require <Self as Iterator>
+    {
+        type Type = I;
+        type Hi = I::Item;
+
+        fn test() {
+            let _: I::Item;
+            let _: I; // this could lint, but is questionable
+        }
+    }
+}
index 7a10d755faa18e0ad96c21939b2694bc6c3ae27d..9da6fef7a380c792781aceadb6ffbb2258395995 100644 (file)
@@ -4,7 +4,12 @@
 
 #![warn(clippy::use_self)]
 #![allow(dead_code)]
-#![allow(clippy::should_implement_trait, clippy::upper_case_acronyms, clippy::from_over_into)]
+#![allow(
+    clippy::should_implement_trait,
+    clippy::upper_case_acronyms,
+    clippy::from_over_into,
+    clippy::self_named_constructors
+)]
 
 #[macro_use]
 extern crate proc_macro_derive;
@@ -279,7 +284,7 @@ mod generics {
     impl<T> Foo<T> {
         // `Self` is applicable here
         fn foo(value: T) -> Foo<T> {
-            Foo { value }
+            Foo::<T> { value }
         }
 
         // `Cannot` use `Self` as a return type as the generic types are different
@@ -492,3 +497,26 @@ mod issue7206 {
         }
     }
 }
+
+mod self_is_ty_param {
+    trait Trait {
+        type Type;
+        type Hi;
+
+        fn test();
+    }
+
+    impl<I> Trait for I
+    where
+        I: Iterator,
+        I::Item: Trait, // changing this to Self would require <Self as Iterator>
+    {
+        type Type = I;
+        type Hi = I::Item;
+
+        fn test() {
+            let _: I::Item;
+            let _: I; // this could lint, but is questionable
+        }
+    }
+}
index cf6222c9b453235e2eb8d068495e7d6843da097a..e14368a11aa746eddd1fffeeb88c3bc36c35982d 100644 (file)
@@ -1,5 +1,5 @@
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:18:21
+  --> $DIR/use_self.rs:23:21
    |
 LL |         fn new() -> Foo {
    |                     ^^^ help: use the applicable keyword: `Self`
@@ -7,163 +7,163 @@ LL |         fn new() -> Foo {
    = note: `-D clippy::use-self` implied by `-D warnings`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:19:13
+  --> $DIR/use_self.rs:24:13
    |
 LL |             Foo {}
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:21:22
+  --> $DIR/use_self.rs:26:22
    |
 LL |         fn test() -> Foo {
    |                      ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:22:13
+  --> $DIR/use_self.rs:27:13
    |
 LL |             Foo::new()
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:27:25
+  --> $DIR/use_self.rs:32:25
    |
 LL |         fn default() -> Foo {
    |                         ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:28:13
+  --> $DIR/use_self.rs:33:13
    |
 LL |             Foo::new()
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:93:24
+  --> $DIR/use_self.rs:98:24
    |
 LL |         fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
    |                        ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:93:55
+  --> $DIR/use_self.rs:98:55
    |
 LL |         fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
    |                                                       ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:108:13
+  --> $DIR/use_self.rs:113:13
    |
 LL |             TS(0)
    |             ^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:143:29
+  --> $DIR/use_self.rs:148:29
    |
 LL |                 fn bar() -> Bar {
    |                             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:144:21
+  --> $DIR/use_self.rs:149:21
    |
 LL |                     Bar { foo: Foo {} }
    |                     ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:155:21
+  --> $DIR/use_self.rs:160:21
    |
 LL |         fn baz() -> Foo {
    |                     ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:156:13
+  --> $DIR/use_self.rs:161:13
    |
 LL |             Foo {}
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:173:21
+  --> $DIR/use_self.rs:178:21
    |
 LL |             let _ = Enum::B(42);
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:174:21
+  --> $DIR/use_self.rs:179:21
    |
 LL |             let _ = Enum::C { field: true };
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:175:21
+  --> $DIR/use_self.rs:180:21
    |
 LL |             let _ = Enum::A;
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:217:13
+  --> $DIR/use_self.rs:222:13
    |
 LL |             nested::A::fun_1();
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:218:13
+  --> $DIR/use_self.rs:223:13
    |
 LL |             nested::A::A;
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:220:13
+  --> $DIR/use_self.rs:225:13
    |
 LL |             nested::A {};
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:239:13
+  --> $DIR/use_self.rs:244:13
    |
 LL |             TestStruct::from_something()
    |             ^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:253:25
+  --> $DIR/use_self.rs:258:25
    |
 LL |         async fn g() -> S {
    |                         ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:254:13
+  --> $DIR/use_self.rs:259:13
    |
 LL |             S {}
    |             ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:258:16
+  --> $DIR/use_self.rs:263:16
    |
 LL |             &p[S::A..S::B]
    |                ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:258:22
+  --> $DIR/use_self.rs:263:22
    |
 LL |             &p[S::A..S::B]
    |                      ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:281:29
+  --> $DIR/use_self.rs:286:29
    |
 LL |         fn foo(value: T) -> Foo<T> {
    |                             ^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:282:13
+  --> $DIR/use_self.rs:287:13
    |
-LL |             Foo { value }
-   |             ^^^ help: use the applicable keyword: `Self`
+LL |             Foo::<T> { value }
+   |             ^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:454:13
+  --> $DIR/use_self.rs:459:13
    |
 LL |             A::new::<submod::B>(submod::B {})
    |             ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:491:13
+  --> $DIR/use_self.rs:496:13
    |
 LL |             S2::new()
    |             ^^ help: use the applicable keyword: `Self`
index da35f2e5c1bbe34dff67105e692626a722c99368..318f9c2dceb641a206a821a81e96473648e9551d 100644 (file)
@@ -1,5 +1,5 @@
 // run-rustfix
-
+#![allow(clippy::nonstandard_macro_braces)]
 #![warn(clippy::useless_vec)]
 
 #[derive(Debug)]
index e9ed83e5c5aef2e3a4613bbbb1d9337a81852b04..d7673ce3e6437dbf7422cc218c5e17084afb857d 100644 (file)
@@ -1,5 +1,5 @@
 // run-rustfix
-
+#![allow(clippy::nonstandard_macro_braces)]
 #![warn(clippy::useless_vec)]
 
 #[derive(Debug)]
index c3e2cf0c4a4bd485e8a869e3a1b7f140eacdc9e3..52e80ceee83cf31439c07cfff967fc46a03e09fd 100644 (file)
@@ -320,6 +320,20 @@ fn issue1924() {
     println!("iterator field {}", it.1);
 }
 
+fn issue7249() {
+    let mut it = 0..10;
+    let mut x = || {
+        // Needs &mut, the closure can be called multiple times
+        for x in &mut it {
+            if x % 2 == 0 {
+                break;
+            }
+        }
+    };
+    x();
+    x();
+}
+
 fn main() {
     let mut it = 0..20;
     for _ in it {
index 1717006a4490e59884b5e6db16858021ada5e383..5078a3c9028c4762f9d7ea09e3b1baf5c837c7c5 100644 (file)
@@ -320,6 +320,20 @@ fn issue1924() {
     println!("iterator field {}", it.1);
 }
 
+fn issue7249() {
+    let mut it = 0..10;
+    let mut x = || {
+        // Needs &mut, the closure can be called multiple times
+        while let Some(x) = it.next() {
+            if x % 2 == 0 {
+                break;
+            }
+        }
+    };
+    x();
+    x();
+}
+
 fn main() {
     let mut it = 0..20;
     while let Some(..) = it.next() {
index eff559bef7e3b87a3ab9491876558389070393a9..cb0afeae15ee0ead89f0bbe769e7af04660ccd72 100644 (file)
@@ -105,10 +105,16 @@ LL |     while let Some(n) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in &mut it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:325:5
+  --> $DIR/while_let_on_iterator.rs:327:9
+   |
+LL |         while let Some(x) = it.next() {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in &mut it`
+
+error: this loop could be written as a `for` loop
+  --> $DIR/while_let_on_iterator.rs:339:5
    |
 LL |     while let Some(..) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it`
 
-error: aborting due to 18 previous errors
+error: aborting due to 19 previous errors
 
index 5ad27bb14501feb8988331dfaefd1dee909e6431..3ee4ab48ac84b215c6a21d34e4be0e85f74fa414 100644 (file)
@@ -1,4 +1,5 @@
 // run-rustfix
+// aux-build:non-exhaustive-enum.rs
 
 #![deny(clippy::wildcard_enum_match_arm)]
 #![allow(
@@ -11,7 +12,9 @@
     clippy::diverging_sub_expression
 )]
 
-use std::io::ErrorKind;
+extern crate non_exhaustive_enum;
+
+use non_exhaustive_enum::ErrorKind;
 
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 enum Color {
@@ -77,29 +80,25 @@ fn main() {
     let error_kind = ErrorKind::NotFound;
     match error_kind {
         ErrorKind::NotFound => {},
-        ErrorKind::PermissionDenied | ErrorKind::ConnectionRefused | ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::NotConnected | ErrorKind::AddrInUse | ErrorKind::AddrNotAvailable | ErrorKind::BrokenPipe | ErrorKind::AlreadyExists | ErrorKind::WouldBlock | ErrorKind::InvalidInput | ErrorKind::InvalidData | ErrorKind::TimedOut | ErrorKind::WriteZero | ErrorKind::Interrupted | ErrorKind::Other | ErrorKind::UnexpectedEof | ErrorKind::Unsupported | ErrorKind::OutOfMemory | _ => {},
+        ErrorKind::PermissionDenied | _ => {},
     }
     match error_kind {
         ErrorKind::NotFound => {},
         ErrorKind::PermissionDenied => {},
-        ErrorKind::ConnectionRefused => {},
-        ErrorKind::ConnectionReset => {},
-        ErrorKind::ConnectionAborted => {},
-        ErrorKind::NotConnected => {},
-        ErrorKind::AddrInUse => {},
-        ErrorKind::AddrNotAvailable => {},
-        ErrorKind::BrokenPipe => {},
-        ErrorKind::AlreadyExists => {},
-        ErrorKind::WouldBlock => {},
-        ErrorKind::InvalidInput => {},
-        ErrorKind::InvalidData => {},
-        ErrorKind::TimedOut => {},
-        ErrorKind::WriteZero => {},
-        ErrorKind::Interrupted => {},
-        ErrorKind::Other => {},
-        ErrorKind::UnexpectedEof => {},
-        ErrorKind::Unsupported => {},
-        ErrorKind::OutOfMemory => {},
         _ => {},
     }
+
+    {
+        #![allow(clippy::manual_non_exhaustive)]
+        pub enum Enum {
+            A,
+            B,
+            #[doc(hidden)]
+            __Private,
+        }
+        match Enum::A {
+            Enum::A => (),
+            Enum::B | _ => (),
+        }
+    }
 }
index adca0738bba5b3cdee4e8255d79916ed98a3912c..46886550453308a340353c5a8c9c8b143a0877a9 100644 (file)
@@ -1,4 +1,5 @@
 // run-rustfix
+// aux-build:non-exhaustive-enum.rs
 
 #![deny(clippy::wildcard_enum_match_arm)]
 #![allow(
@@ -11,7 +12,9 @@
     clippy::diverging_sub_expression
 )]
 
-use std::io::ErrorKind;
+extern crate non_exhaustive_enum;
+
+use non_exhaustive_enum::ErrorKind;
 
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 enum Color {
@@ -82,24 +85,20 @@ fn main() {
     match error_kind {
         ErrorKind::NotFound => {},
         ErrorKind::PermissionDenied => {},
-        ErrorKind::ConnectionRefused => {},
-        ErrorKind::ConnectionReset => {},
-        ErrorKind::ConnectionAborted => {},
-        ErrorKind::NotConnected => {},
-        ErrorKind::AddrInUse => {},
-        ErrorKind::AddrNotAvailable => {},
-        ErrorKind::BrokenPipe => {},
-        ErrorKind::AlreadyExists => {},
-        ErrorKind::WouldBlock => {},
-        ErrorKind::InvalidInput => {},
-        ErrorKind::InvalidData => {},
-        ErrorKind::TimedOut => {},
-        ErrorKind::WriteZero => {},
-        ErrorKind::Interrupted => {},
-        ErrorKind::Other => {},
-        ErrorKind::UnexpectedEof => {},
-        ErrorKind::Unsupported => {},
-        ErrorKind::OutOfMemory => {},
         _ => {},
     }
+
+    {
+        #![allow(clippy::manual_non_exhaustive)]
+        pub enum Enum {
+            A,
+            B,
+            #[doc(hidden)]
+            __Private,
+        }
+        match Enum::A {
+            Enum::A => (),
+            _ => (),
+        }
+    }
 }
index 73f6a4a80c960d36c8611b63fca88f59d1103c5d..d63f2090353151a55ec431d50b814d8e2c6c7bc2 100644 (file)
@@ -1,38 +1,44 @@
 error: wildcard match will also match any future added variants
-  --> $DIR/wildcard_enum_match_arm.rs:39:9
+  --> $DIR/wildcard_enum_match_arm.rs:42:9
    |
 LL |         _ => eprintln!("Not red"),
    |         ^ help: try this: `Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan`
    |
 note: the lint level is defined here
-  --> $DIR/wildcard_enum_match_arm.rs:3:9
+  --> $DIR/wildcard_enum_match_arm.rs:4:9
    |
 LL | #![deny(clippy::wildcard_enum_match_arm)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: wildcard match will also match any future added variants
-  --> $DIR/wildcard_enum_match_arm.rs:43:9
+  --> $DIR/wildcard_enum_match_arm.rs:46:9
    |
 LL |         _not_red => eprintln!("Not red"),
    |         ^^^^^^^^ help: try this: `_not_red @ Color::Green | _not_red @ Color::Blue | _not_red @ Color::Rgb(..) | _not_red @ Color::Cyan`
 
 error: wildcard match will also match any future added variants
-  --> $DIR/wildcard_enum_match_arm.rs:47:9
+  --> $DIR/wildcard_enum_match_arm.rs:50:9
    |
 LL |         not_red => format!("{:?}", not_red),
    |         ^^^^^^^ help: try this: `not_red @ Color::Green | not_red @ Color::Blue | not_red @ Color::Rgb(..) | not_red @ Color::Cyan`
 
 error: wildcard match will also match any future added variants
-  --> $DIR/wildcard_enum_match_arm.rs:63:9
+  --> $DIR/wildcard_enum_match_arm.rs:66:9
    |
 LL |         _ => "No red",
    |         ^ help: try this: `Color::Red | Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan`
 
 error: wildcard matches known variants and will also match future added variants
-  --> $DIR/wildcard_enum_match_arm.rs:80:9
+  --> $DIR/wildcard_enum_match_arm.rs:83:9
    |
 LL |         _ => {},
-   |         ^ help: try this: `ErrorKind::PermissionDenied | ErrorKind::ConnectionRefused | ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::NotConnected | ErrorKind::AddrInUse | ErrorKind::AddrNotAvailable | ErrorKind::BrokenPipe | ErrorKind::AlreadyExists | ErrorKind::WouldBlock | ErrorKind::InvalidInput | ErrorKind::InvalidData | ErrorKind::TimedOut | ErrorKind::WriteZero | ErrorKind::Interrupted | ErrorKind::Other | ErrorKind::UnexpectedEof | ErrorKind::Unsupported | ErrorKind::OutOfMemory | _`
+   |         ^ help: try this: `ErrorKind::PermissionDenied | _`
 
-error: aborting due to 5 previous errors
+error: wildcard matches known variants and will also match future added variants
+  --> $DIR/wildcard_enum_match_arm.rs:101:13
+   |
+LL |             _ => (),
+   |             ^ help: try this: `Enum::B | _`
+
+error: aborting due to 6 previous errors
 
index 2de904376ad45b438ef580b99f2791fe7d5ea9bd..6c190a4c86c48a3175f5b94a0c22312757de088d 100644 (file)
@@ -1,12 +1,18 @@
 fn main() {
     unsafe {
-        let x = &() as *const ();
-        x.offset(0);
-        x.wrapping_add(0);
-        x.sub(0);
-        x.wrapping_sub(0);
+        let m = &mut () as *mut ();
+        m.offset(0);
+        m.wrapping_add(0);
+        m.sub(0);
+        m.wrapping_sub(0);
 
-        let y = &1 as *const u8;
-        y.offset(0);
+        let c = &() as *const ();
+        c.offset(0);
+        c.wrapping_add(0);
+        c.sub(0);
+        c.wrapping_sub(0);
+
+        let sized = &1 as *const i32;
+        sized.offset(0);
     }
 }
index cfcd7de2b3d2c6b4503cbb125ff03be2ee0896b8..b12c8e9a73c6dab3692dc2bc97cbce8ea81b3bc2 100644 (file)
@@ -1,9 +1,52 @@
-error[E0606]: casting `&i32` as `*const u8` is invalid
-  --> $DIR/zero_offset.rs:9:17
+error: offset calculation on zero-sized value
+  --> $DIR/zero_offset.rs:4:9
    |
-LL |         let y = &1 as *const u8;
-   |                 ^^^^^^^^^^^^^^^
+LL |         m.offset(0);
+   |         ^^^^^^^^^^^
+   |
+   = note: `#[deny(clippy::zst_offset)]` on by default
+
+error: offset calculation on zero-sized value
+  --> $DIR/zero_offset.rs:5:9
+   |
+LL |         m.wrapping_add(0);
+   |         ^^^^^^^^^^^^^^^^^
+
+error: offset calculation on zero-sized value
+  --> $DIR/zero_offset.rs:6:9
+   |
+LL |         m.sub(0);
+   |         ^^^^^^^^
+
+error: offset calculation on zero-sized value
+  --> $DIR/zero_offset.rs:7:9
+   |
+LL |         m.wrapping_sub(0);
+   |         ^^^^^^^^^^^^^^^^^
+
+error: offset calculation on zero-sized value
+  --> $DIR/zero_offset.rs:10:9
+   |
+LL |         c.offset(0);
+   |         ^^^^^^^^^^^
+
+error: offset calculation on zero-sized value
+  --> $DIR/zero_offset.rs:11:9
+   |
+LL |         c.wrapping_add(0);
+   |         ^^^^^^^^^^^^^^^^^
+
+error: offset calculation on zero-sized value
+  --> $DIR/zero_offset.rs:12:9
+   |
+LL |         c.sub(0);
+   |         ^^^^^^^^
+
+error: offset calculation on zero-sized value
+  --> $DIR/zero_offset.rs:13:9
+   |
+LL |         c.wrapping_sub(0);
+   |         ^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 8 previous errors
 
-For more information about this error, try `rustc --explain E0606`.
diff --git a/src/tools/clippy/util/etc/pre-commit.sh b/src/tools/clippy/util/etc/pre-commit.sh
new file mode 100755 (executable)
index 0000000..528f895
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# hide output
+set -e
+
+# Update lints
+cargo dev update_lints
+git add clippy_lints/src/lib.rs
+
+# Formatting:
+#     Git will not automatically add the formatted code to the staged changes once
+#     fmt was executed. This collects all staged files rs files that are currently staged.
+#     They will later be added back.
+#
+#     This was proudly stolen and adjusted from here:
+#     https://medium.com/@harshitbangar/automatic-code-formatting-with-git-66c3c5c26798
+files=$( (git diff --cached --name-only --diff-filter=ACMR | grep -Ei "\.rs$") || true)
+if [ ! -z "${files}" ]; then
+    cargo dev fmt
+    git add $(echo "$files" | paste -s -d " " -)
+fi
diff --git a/src/tools/clippy/util/etc/vscode-tasks.json b/src/tools/clippy/util/etc/vscode-tasks.json
new file mode 100644 (file)
index 0000000..a4bb26b
--- /dev/null
@@ -0,0 +1,57 @@
+{
+    "version": "2.0.0",
+    "tasks": [
+        {
+            "label": "cargo check",
+            "type": "shell",
+            "command": "cargo check",
+            "problemMatcher": [],
+            "group": {
+                "kind": "build",
+                "isDefault": true,
+            },
+        },
+        {
+            "label": "cargo dev fmt",
+            "type": "shell",
+            "command": "cargo dev fmt",
+            "problemMatcher": [],
+            "group": "none",
+        },
+        {
+            "label": "cargo uitest",
+            "type": "shell",
+            "command": "cargo uitest",
+            "options": {
+                "env": {
+                    "RUST_BACKTRACE": "1",
+                    // This task will usually execute all UI tests inside `tests/ui` you can
+                    // optionally uncomment the line below and only run a specific test.
+                    //
+                    // See: https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md#testing
+                    //
+                    // "TESTNAME": "<TODO>",
+                },
+            },
+            "problemMatcher": [],
+            "group": {
+                "kind": "test",
+                "isDefault": true,
+            }
+        },
+        {
+            "label": "cargo test",
+            "type": "shell",
+            "command": "cargo test",
+            "problemMatcher": [],
+            "group": "test",
+        },
+        {
+            "label": "cargo dev bless",
+            "type": "shell",
+            "command": "cargo dev bless",
+            "problemMatcher": [],
+            "group": "none",
+        },
+    ],
+}
index 5707cf0ce0f8c08177f68866b7065c6c9feb2182..9cefb2dbb197caffafcc0ae1cd7c6f40f1fa450c 100644 (file)
@@ -12,13 +12,14 @@ Config = collections.namedtuple('Config', 'name ty doc default')
 
 lintname_re = re.compile(r'''pub\s+([A-Z_][A-Z_0-9]*)''')
 group_re = re.compile(r'''\s*([a-z_][a-z_0-9]+)''')
-conf_re = re.compile(r'''define_Conf! {\n([^}]*)\n}''', re.MULTILINE)
+conf_re = re.compile(r'''define_Conf! {\n((?!\n})[\s\S])*\n}''', re.MULTILINE)
 confvar_re = re.compile(
     r'''/// Lint: ([\w,\s]+)\. (.*)\n\s*\(([^:]+):\s*([^\s=]+)\s*=\s*([^\.\)]+).*\),''', re.MULTILINE)
 comment_re = re.compile(r'''\s*/// ?(.*)''')
 
 lint_levels = {
     "correctness": 'Deny',
+    "suspicious": 'Warn',
     "style": 'Warn',
     "complexity": 'Warn',
     "perf": 'Warn',
@@ -91,7 +92,7 @@ def parse_configs(path):
         contents = fp.read()
 
     match = re.search(conf_re, contents)
-    confvars = re.findall(confvar_re, match.group(1))
+    confvars = re.findall(confvar_re, match.group(0))
 
     for (lints, doc, name, ty, default) in confvars:
         for lint in lints.split(','):
index f61d61e8f9de20f609a130d2b835ed25166cfcb0..771e36e4d2c49fb1af716587ac0d5b9960b559b4 100644 (file)
@@ -14,7 +14,7 @@ tracing-subscriber = { version = "0.2", default-features = false, features = ["f
 regex = "1.0"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
-rustfix = "0.5.0"
+rustfix = "0.6.0"
 lazy_static = "1.0"
 walkdir = "2"
 glob = "0.3.0"
index 26c1710be742ea9596614af6e513431f3f98ac3f..68e28795347e91f8515dbd1fd7871678b2a389dd 100644 (file)
@@ -27,8 +27,6 @@ enum ParsedNameDirective {
 /// the test.
 #[derive(Default)]
 pub struct EarlyProps {
-    pub ignore: bool,
-    pub should_fail: bool,
     pub aux: Vec<String>,
     pub aux_crate: Vec<(String, String)>,
     pub revisions: Vec<String>,
@@ -36,251 +34,22 @@ pub struct EarlyProps {
 
 impl EarlyProps {
     pub fn from_file(config: &Config, testfile: &Path) -> Self {
-        let file = File::open(testfile).unwrap();
+        let file = File::open(testfile).expect("open test file to parse earlyprops");
         Self::from_reader(config, testfile, file)
     }
 
     pub fn from_reader<R: Read>(config: &Config, testfile: &Path, rdr: R) -> Self {
         let mut props = EarlyProps::default();
-        let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some();
-        let rustc_has_sanitizer_support = env::var_os("RUSTC_SANITIZER_SUPPORT").is_some();
-        let has_asm_support = util::has_asm_support(&config.target);
-        let has_asan = util::ASAN_SUPPORTED_TARGETS.contains(&&*config.target);
-        let has_lsan = util::LSAN_SUPPORTED_TARGETS.contains(&&*config.target);
-        let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target);
-        let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
-        let has_hwasan = util::HWASAN_SUPPORTED_TARGETS.contains(&&*config.target);
-        // for `-Z gcc-ld=lld`
-        let has_rust_lld = config
-            .compile_lib_path
-            .join("rustlib")
-            .join(&config.target)
-            .join("bin")
-            .join("gcc-ld")
-            .join(if config.host.contains("windows") { "ld.exe" } else { "ld" })
-            .exists();
-
-        iter_header(testfile, None, rdr, &mut |ln| {
-            // we should check if any only-<platform> exists and if it exists
-            // and does not matches the current platform, skip the test
-            if !props.ignore {
-                props.ignore = match config.parse_cfg_name_directive(ln, "ignore") {
-                    ParsedNameDirective::Match => true,
-                    ParsedNameDirective::NoMatch => props.ignore,
-                };
-
-                if config.has_cfg_prefix(ln, "only") {
-                    props.ignore = match config.parse_cfg_name_directive(ln, "only") {
-                        ParsedNameDirective::Match => props.ignore,
-                        ParsedNameDirective::NoMatch => true,
-                    };
-                }
-
-                if ignore_llvm(config, ln) {
-                    props.ignore = true;
-                }
-
-                if config.run_clang_based_tests_with.is_none()
-                    && config.parse_needs_matching_clang(ln)
-                {
-                    props.ignore = true;
-                }
-
-                if !has_asm_support && config.parse_name_directive(ln, "needs-asm-support") {
-                    props.ignore = true;
-                }
-
-                if !rustc_has_profiler_support && config.parse_needs_profiler_support(ln) {
-                    props.ignore = true;
-                }
-
-                if !config.run_enabled() && config.parse_name_directive(ln, "needs-run-enabled") {
-                    props.ignore = true;
-                }
-
-                if !rustc_has_sanitizer_support
-                    && config.parse_name_directive(ln, "needs-sanitizer-support")
-                {
-                    props.ignore = true;
-                }
-
-                if !has_asan && config.parse_name_directive(ln, "needs-sanitizer-address") {
-                    props.ignore = true;
-                }
-
-                if !has_lsan && config.parse_name_directive(ln, "needs-sanitizer-leak") {
-                    props.ignore = true;
-                }
-
-                if !has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory") {
-                    props.ignore = true;
-                }
-
-                if !has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread") {
-                    props.ignore = true;
-                }
-
-                if !has_hwasan && config.parse_name_directive(ln, "needs-sanitizer-hwaddress") {
-                    props.ignore = true;
-                }
-
-                if config.target_panic == PanicStrategy::Abort
-                    && config.parse_name_directive(ln, "needs-unwind")
-                {
-                    props.ignore = true;
-                }
-
-                if config.target == "wasm32-unknown-unknown" && config.parse_check_run_results(ln) {
-                    props.ignore = true;
-                }
-
-                if config.debugger == Some(Debugger::Cdb) && ignore_cdb(config, ln) {
-                    props.ignore = true;
-                }
-
-                if config.debugger == Some(Debugger::Gdb) && ignore_gdb(config, ln) {
-                    props.ignore = true;
-                }
-
-                if config.debugger == Some(Debugger::Lldb) && ignore_lldb(config, ln) {
-                    props.ignore = true;
-                }
-
-                if !has_rust_lld && config.parse_name_directive(ln, "needs-rust-lld") {
-                    props.ignore = true;
-                }
-            }
-
+        iter_header(testfile, rdr, &mut |_, ln| {
             if let Some(s) = config.parse_aux_build(ln) {
                 props.aux.push(s);
             }
-
             if let Some(ac) = config.parse_aux_crate(ln) {
                 props.aux_crate.push(ac);
             }
-
             config.parse_and_update_revisions(ln, &mut props.revisions);
-
-            props.should_fail = props.should_fail || config.parse_name_directive(ln, "should-fail");
         });
-
         return props;
-
-        fn ignore_cdb(config: &Config, line: &str) -> bool {
-            if let Some(actual_version) = config.cdb_version {
-                if let Some(min_version) = line.strip_prefix("min-cdb-version:").map(str::trim) {
-                    let min_version = extract_cdb_version(min_version).unwrap_or_else(|| {
-                        panic!("couldn't parse version range: {:?}", min_version);
-                    });
-
-                    // Ignore if actual version is smaller than the minimum
-                    // required version
-                    return actual_version < min_version;
-                }
-            }
-            false
-        }
-
-        fn ignore_gdb(config: &Config, line: &str) -> bool {
-            if let Some(actual_version) = config.gdb_version {
-                if let Some(rest) = line.strip_prefix("min-gdb-version:").map(str::trim) {
-                    let (start_ver, end_ver) = extract_version_range(rest, extract_gdb_version)
-                        .unwrap_or_else(|| {
-                            panic!("couldn't parse version range: {:?}", rest);
-                        });
-
-                    if start_ver != end_ver {
-                        panic!("Expected single GDB version")
-                    }
-                    // Ignore if actual version is smaller than the minimum
-                    // required version
-                    return actual_version < start_ver;
-                } else if let Some(rest) = line.strip_prefix("ignore-gdb-version:").map(str::trim) {
-                    let (min_version, max_version) =
-                        extract_version_range(rest, extract_gdb_version).unwrap_or_else(|| {
-                            panic!("couldn't parse version range: {:?}", rest);
-                        });
-
-                    if max_version < min_version {
-                        panic!("Malformed GDB version range: max < min")
-                    }
-
-                    return actual_version >= min_version && actual_version <= max_version;
-                }
-            }
-            false
-        }
-
-        fn ignore_lldb(config: &Config, line: &str) -> bool {
-            if let Some(actual_version) = config.lldb_version {
-                if let Some(min_version) = line.strip_prefix("min-lldb-version:").map(str::trim) {
-                    let min_version = min_version.parse().unwrap_or_else(|e| {
-                        panic!(
-                            "Unexpected format of LLDB version string: {}\n{:?}",
-                            min_version, e
-                        );
-                    });
-                    // Ignore if actual version is smaller the minimum required
-                    // version
-                    actual_version < min_version
-                } else {
-                    line.starts_with("rust-lldb") && !config.lldb_native_rust
-                }
-            } else {
-                false
-            }
-        }
-
-        fn ignore_llvm(config: &Config, line: &str) -> bool {
-            if config.system_llvm && line.starts_with("no-system-llvm") {
-                return true;
-            }
-            if let Some(needed_components) =
-                config.parse_name_value_directive(line, "needs-llvm-components")
-            {
-                let components: HashSet<_> = config.llvm_components.split_whitespace().collect();
-                if let Some(missing_component) = needed_components
-                    .split_whitespace()
-                    .find(|needed_component| !components.contains(needed_component))
-                {
-                    if env::var_os("COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS").is_some() {
-                        panic!("missing LLVM component: {}", missing_component);
-                    }
-                    return true;
-                }
-            }
-            if let Some(actual_version) = config.llvm_version {
-                if let Some(rest) = line.strip_prefix("min-llvm-version:").map(str::trim) {
-                    let min_version = extract_llvm_version(rest).unwrap();
-                    // Ignore if actual version is smaller the minimum required
-                    // version
-                    actual_version < min_version
-                } else if let Some(rest) =
-                    line.strip_prefix("min-system-llvm-version:").map(str::trim)
-                {
-                    let min_version = extract_llvm_version(rest).unwrap();
-                    // Ignore if using system LLVM and actual version
-                    // is smaller the minimum required version
-                    config.system_llvm && actual_version < min_version
-                } else if let Some(rest) = line.strip_prefix("ignore-llvm-version:").map(str::trim)
-                {
-                    // Syntax is: "ignore-llvm-version: <version1> [- <version2>]"
-                    let (v_min, v_max) = extract_version_range(rest, extract_llvm_version)
-                        .unwrap_or_else(|| {
-                            panic!("couldn't parse version range: {:?}", rest);
-                        });
-                    if v_max < v_min {
-                        panic!("Malformed LLVM version range: max < min")
-                    }
-                    // Ignore if version lies inside of range.
-                    actual_version >= v_min && actual_version <= v_max
-                } else {
-                    false
-                }
-            } else {
-                false
-            }
-        }
     }
 }
 
@@ -440,7 +209,11 @@ impl TestProps {
         if !testfile.is_dir() {
             let file = File::open(testfile).unwrap();
 
-            iter_header(testfile, cfg, file, &mut |ln| {
+            iter_header(testfile, file, &mut |revision, ln| {
+                if revision.is_some() && revision != cfg {
+                    return;
+                }
+
                 if let Some(ep) = config.parse_error_pattern(ln) {
                     self.error_patterns.push(ep);
                 }
@@ -672,12 +445,12 @@ impl TestProps {
     }
 }
 
-fn iter_header<R: Read>(testfile: &Path, cfg: Option<&str>, rdr: R, it: &mut dyn FnMut(&str)) {
+fn iter_header<R: Read>(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str>, &str)) {
     if testfile.is_dir() {
         return;
     }
 
-    let comment = if testfile.to_string_lossy().ends_with(".rs") { "//" } else { "#" };
+    let comment = if testfile.extension().map(|e| e == "rs") == Some(true) { "//" } else { "#" };
 
     let mut rdr = BufReader::new(rdr);
     let mut ln = String::new();
@@ -699,18 +472,12 @@ fn iter_header<R: Read>(testfile: &Path, cfg: Option<&str>, rdr: R, it: &mut dyn
             if let Some(close_brace) = ln.find(']') {
                 let open_brace = ln.find('[').unwrap();
                 let lncfg = &ln[open_brace + 1..close_brace];
-                let matches = match cfg {
-                    Some(s) => s == &lncfg[..],
-                    None => false,
-                };
-                if matches {
-                    it(ln[(close_brace + 1)..].trim_start());
-                }
+                it(Some(lncfg), ln[(close_brace + 1)..].trim_start());
             } else {
                 panic!("malformed condition directive: expected `{}[foo]`, found `{}`", comment, ln)
             }
         } else if ln.starts_with(comment) {
-            it(ln[comment.len()..].trim_start());
+            it(None, ln[comment.len()..].trim_start());
         }
     }
 }
@@ -1026,11 +793,12 @@ pub fn extract_llvm_version(version: &str) -> Option<u32> {
     Some(version)
 }
 
-// Takes a directive of the form "<version1> [- <version2>]",
-// returns the numeric representation of <version1> and <version2> as
-// tuple: (<version1> as u32, <version2> as u32)
-// If the <version2> part is omitted, the second component of the tuple
-// is the same as <version1>.
+/// Takes a directive of the form "<version1> [- <version2>]",
+/// returns the numeric representation of <version1> and <version2> as
+/// tuple: (<version1> as u32, <version2> as u32)
+///
+/// If the <version2> part is omitted, the second component of the tuple
+/// is the same as <version1>.
 fn extract_version_range<F>(line: &str, parse: F) -> Option<(u32, u32)>
 where
     F: Fn(&str) -> Option<u32>,
@@ -1056,3 +824,197 @@ where
 
     Some((min, max))
 }
+
+pub fn make_test_description<R: Read>(
+    config: &Config,
+    name: test::TestName,
+    path: &Path,
+    src: R,
+    cfg: Option<&str>,
+) -> test::TestDesc {
+    let mut ignore = false;
+    let mut should_fail = false;
+
+    let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some();
+    let rustc_has_sanitizer_support = env::var_os("RUSTC_SANITIZER_SUPPORT").is_some();
+    let has_asm_support = util::has_asm_support(&config.target);
+    let has_asan = util::ASAN_SUPPORTED_TARGETS.contains(&&*config.target);
+    let has_lsan = util::LSAN_SUPPORTED_TARGETS.contains(&&*config.target);
+    let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target);
+    let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
+    let has_hwasan = util::HWASAN_SUPPORTED_TARGETS.contains(&&*config.target);
+    // for `-Z gcc-ld=lld`
+    let has_rust_lld = config
+        .compile_lib_path
+        .join("rustlib")
+        .join(&config.target)
+        .join("bin")
+        .join("gcc-ld")
+        .join(if config.host.contains("windows") { "ld.exe" } else { "ld" })
+        .exists();
+    iter_header(path, src, &mut |revision, ln| {
+        if revision.is_some() && revision != cfg {
+            return;
+        }
+        ignore = match config.parse_cfg_name_directive(ln, "ignore") {
+            ParsedNameDirective::Match => true,
+            ParsedNameDirective::NoMatch => ignore,
+        };
+        if config.has_cfg_prefix(ln, "only") {
+            ignore = match config.parse_cfg_name_directive(ln, "only") {
+                ParsedNameDirective::Match => ignore,
+                ParsedNameDirective::NoMatch => true,
+            };
+        }
+        ignore |= ignore_llvm(config, ln);
+        ignore |=
+            config.run_clang_based_tests_with.is_none() && config.parse_needs_matching_clang(ln);
+        ignore |= !has_asm_support && config.parse_name_directive(ln, "needs-asm-support");
+        ignore |= !rustc_has_profiler_support && config.parse_needs_profiler_support(ln);
+        ignore |= !config.run_enabled() && config.parse_name_directive(ln, "needs-run-enabled");
+        ignore |= !rustc_has_sanitizer_support
+            && config.parse_name_directive(ln, "needs-sanitizer-support");
+        ignore |= !has_asan && config.parse_name_directive(ln, "needs-sanitizer-address");
+        ignore |= !has_lsan && config.parse_name_directive(ln, "needs-sanitizer-leak");
+        ignore |= !has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory");
+        ignore |= !has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread");
+        ignore |= !has_hwasan && config.parse_name_directive(ln, "needs-sanitizer-hwaddress");
+        ignore |= config.target_panic == PanicStrategy::Abort
+            && config.parse_name_directive(ln, "needs-unwind");
+        ignore |= config.target == "wasm32-unknown-unknown" && config.parse_check_run_results(ln);
+        ignore |= config.debugger == Some(Debugger::Cdb) && ignore_cdb(config, ln);
+        ignore |= config.debugger == Some(Debugger::Gdb) && ignore_gdb(config, ln);
+        ignore |= config.debugger == Some(Debugger::Lldb) && ignore_lldb(config, ln);
+        ignore |= !has_rust_lld && config.parse_name_directive(ln, "needs-rust-lld");
+        should_fail |= config.parse_name_directive(ln, "should-fail");
+    });
+
+    // The `should-fail` annotation doesn't apply to pretty tests,
+    // since we run the pretty printer across all tests by default.
+    // If desired, we could add a `should-fail-pretty` annotation.
+    let should_panic = match config.mode {
+        crate::common::Pretty => test::ShouldPanic::No,
+        _ if should_fail => test::ShouldPanic::Yes,
+        _ => test::ShouldPanic::No,
+    };
+
+    test::TestDesc {
+        name,
+        ignore,
+        should_panic,
+        allow_fail: false,
+        compile_fail: false,
+        no_run: false,
+        test_type: test::TestType::Unknown,
+    }
+}
+
+fn ignore_cdb(config: &Config, line: &str) -> bool {
+    if let Some(actual_version) = config.cdb_version {
+        if let Some(min_version) = line.strip_prefix("min-cdb-version:").map(str::trim) {
+            let min_version = extract_cdb_version(min_version).unwrap_or_else(|| {
+                panic!("couldn't parse version range: {:?}", min_version);
+            });
+
+            // Ignore if actual version is smaller than the minimum
+            // required version
+            return actual_version < min_version;
+        }
+    }
+    false
+}
+
+fn ignore_gdb(config: &Config, line: &str) -> bool {
+    if let Some(actual_version) = config.gdb_version {
+        if let Some(rest) = line.strip_prefix("min-gdb-version:").map(str::trim) {
+            let (start_ver, end_ver) = extract_version_range(rest, extract_gdb_version)
+                .unwrap_or_else(|| {
+                    panic!("couldn't parse version range: {:?}", rest);
+                });
+
+            if start_ver != end_ver {
+                panic!("Expected single GDB version")
+            }
+            // Ignore if actual version is smaller than the minimum
+            // required version
+            return actual_version < start_ver;
+        } else if let Some(rest) = line.strip_prefix("ignore-gdb-version:").map(str::trim) {
+            let (min_version, max_version) = extract_version_range(rest, extract_gdb_version)
+                .unwrap_or_else(|| {
+                    panic!("couldn't parse version range: {:?}", rest);
+                });
+
+            if max_version < min_version {
+                panic!("Malformed GDB version range: max < min")
+            }
+
+            return actual_version >= min_version && actual_version <= max_version;
+        }
+    }
+    false
+}
+
+fn ignore_lldb(config: &Config, line: &str) -> bool {
+    if let Some(actual_version) = config.lldb_version {
+        if let Some(min_version) = line.strip_prefix("min-lldb-version:").map(str::trim) {
+            let min_version = min_version.parse().unwrap_or_else(|e| {
+                panic!("Unexpected format of LLDB version string: {}\n{:?}", min_version, e);
+            });
+            // Ignore if actual version is smaller the minimum required
+            // version
+            actual_version < min_version
+        } else {
+            line.starts_with("rust-lldb") && !config.lldb_native_rust
+        }
+    } else {
+        false
+    }
+}
+
+fn ignore_llvm(config: &Config, line: &str) -> bool {
+    if config.system_llvm && line.starts_with("no-system-llvm") {
+        return true;
+    }
+    if let Some(needed_components) =
+        config.parse_name_value_directive(line, "needs-llvm-components")
+    {
+        let components: HashSet<_> = config.llvm_components.split_whitespace().collect();
+        if let Some(missing_component) = needed_components
+            .split_whitespace()
+            .find(|needed_component| !components.contains(needed_component))
+        {
+            if env::var_os("COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS").is_some() {
+                panic!("missing LLVM component: {}", missing_component);
+            }
+            return true;
+        }
+    }
+    if let Some(actual_version) = config.llvm_version {
+        if let Some(rest) = line.strip_prefix("min-llvm-version:").map(str::trim) {
+            let min_version = extract_llvm_version(rest).unwrap();
+            // Ignore if actual version is smaller the minimum required
+            // version
+            actual_version < min_version
+        } else if let Some(rest) = line.strip_prefix("min-system-llvm-version:").map(str::trim) {
+            let min_version = extract_llvm_version(rest).unwrap();
+            // Ignore if using system LLVM and actual version
+            // is smaller the minimum required version
+            config.system_llvm && actual_version < min_version
+        } else if let Some(rest) = line.strip_prefix("ignore-llvm-version:").map(str::trim) {
+            // Syntax is: "ignore-llvm-version: <version1> [- <version2>]"
+            let (v_min, v_max) =
+                extract_version_range(rest, extract_llvm_version).unwrap_or_else(|| {
+                    panic!("couldn't parse version range: {:?}", rest);
+                });
+            if v_max < v_min {
+                panic!("Malformed LLVM version range: max < min")
+            }
+            // Ignore if version lies inside of range.
+            actual_version >= v_min && actual_version <= v_max
+        } else {
+            false
+        }
+    } else {
+        false
+    }
+}
index 2c607b6a50ef7d6aa7992936b3a631c41542f24d..2485dbadab5bfdbb5bb6cb55f4ec336a90f98778 100644 (file)
@@ -1,7 +1,7 @@
 use std::path::Path;
 
 use crate::common::{Config, Debugger};
-use crate::header::{parse_normalization_string, EarlyProps};
+use crate::header::{make_test_description, parse_normalization_string, EarlyProps};
 
 #[test]
 fn test_parse_normalization_string() {
@@ -66,6 +66,13 @@ fn parse_rs(config: &Config, contents: &str) -> EarlyProps {
     EarlyProps::from_reader(config, Path::new("a.rs"), bytes)
 }
 
+fn check_ignore(config: &Config, contents: &str) -> bool {
+    let tn = test::DynTestName(String::new());
+    let p = Path::new("a.rs");
+    let d = make_test_description(&config, tn, p, std::io::Cursor::new(contents), None);
+    d.ignore
+}
+
 fn parse_makefile(config: &Config, contents: &str) -> EarlyProps {
     let bytes = contents.as_bytes();
     EarlyProps::from_reader(config, Path::new("Makefile"), bytes)
@@ -74,9 +81,13 @@ fn parse_makefile(config: &Config, contents: &str) -> EarlyProps {
 #[test]
 fn should_fail() {
     let config = config();
+    let tn = test::DynTestName(String::new());
+    let p = Path::new("a.rs");
 
-    assert!(!parse_rs(&config, "").should_fail);
-    assert!(parse_rs(&config, "// should-fail").should_fail);
+    let d = make_test_description(&config, tn.clone(), p, std::io::Cursor::new(""), None);
+    assert_eq!(d.should_panic, test::ShouldPanic::No);
+    let d = make_test_description(&config, tn, p, std::io::Cursor::new("// should-fail"), None);
+    assert_eq!(d.should_panic, test::ShouldPanic::Yes);
 }
 
 #[test]
@@ -112,10 +123,10 @@ fn no_system_llvm() {
     let mut config = config();
 
     config.system_llvm = false;
-    assert!(!parse_rs(&config, "// no-system-llvm").ignore);
+    assert!(!check_ignore(&config, "// no-system-llvm"));
 
     config.system_llvm = true;
-    assert!(parse_rs(&config, "// no-system-llvm").ignore);
+    assert!(check_ignore(&config, "// no-system-llvm"));
 }
 
 #[test]
@@ -123,16 +134,16 @@ fn llvm_version() {
     let mut config = config();
 
     config.llvm_version = Some(80102);
-    assert!(parse_rs(&config, "// min-llvm-version: 9.0").ignore);
+    assert!(check_ignore(&config, "// min-llvm-version: 9.0"));
 
     config.llvm_version = Some(90001);
-    assert!(parse_rs(&config, "// min-llvm-version: 9.2").ignore);
+    assert!(check_ignore(&config, "// min-llvm-version: 9.2"));
 
     config.llvm_version = Some(90301);
-    assert!(!parse_rs(&config, "// min-llvm-version: 9.2").ignore);
+    assert!(!check_ignore(&config, "// min-llvm-version: 9.2"));
 
     config.llvm_version = Some(100000);
-    assert!(!parse_rs(&config, "// min-llvm-version: 9.0").ignore);
+    assert!(!check_ignore(&config, "// min-llvm-version: 9.0"));
 }
 
 #[test]
@@ -140,16 +151,16 @@ fn ignore_target() {
     let mut config = config();
     config.target = "x86_64-unknown-linux-gnu".to_owned();
 
-    assert!(parse_rs(&config, "// ignore-x86_64-unknown-linux-gnu").ignore);
-    assert!(parse_rs(&config, "// ignore-x86_64").ignore);
-    assert!(parse_rs(&config, "// ignore-linux").ignore);
-    assert!(parse_rs(&config, "// ignore-gnu").ignore);
-    assert!(parse_rs(&config, "// ignore-64bit").ignore);
+    assert!(check_ignore(&config, "// ignore-x86_64-unknown-linux-gnu"));
+    assert!(check_ignore(&config, "// ignore-x86_64"));
+    assert!(check_ignore(&config, "// ignore-linux"));
+    assert!(check_ignore(&config, "// ignore-gnu"));
+    assert!(check_ignore(&config, "// ignore-64bit"));
 
-    assert!(!parse_rs(&config, "// ignore-i686").ignore);
-    assert!(!parse_rs(&config, "// ignore-windows").ignore);
-    assert!(!parse_rs(&config, "// ignore-msvc").ignore);
-    assert!(!parse_rs(&config, "// ignore-32bit").ignore);
+    assert!(!check_ignore(&config, "// ignore-i686"));
+    assert!(!check_ignore(&config, "// ignore-windows"));
+    assert!(!check_ignore(&config, "// ignore-msvc"));
+    assert!(!check_ignore(&config, "// ignore-32bit"));
 }
 
 #[test]
@@ -157,16 +168,16 @@ fn only_target() {
     let mut config = config();
     config.target = "x86_64-pc-windows-gnu".to_owned();
 
-    assert!(parse_rs(&config, "// only-i686").ignore);
-    assert!(parse_rs(&config, "// only-linux").ignore);
-    assert!(parse_rs(&config, "// only-msvc").ignore);
-    assert!(parse_rs(&config, "// only-32bit").ignore);
+    assert!(check_ignore(&config, "// only-i686"));
+    assert!(check_ignore(&config, "// only-linux"));
+    assert!(check_ignore(&config, "// only-msvc"));
+    assert!(check_ignore(&config, "// only-32bit"));
 
-    assert!(!parse_rs(&config, "// only-x86_64-pc-windows-gnu").ignore);
-    assert!(!parse_rs(&config, "// only-x86_64").ignore);
-    assert!(!parse_rs(&config, "// only-windows").ignore);
-    assert!(!parse_rs(&config, "// only-gnu").ignore);
-    assert!(!parse_rs(&config, "// only-64bit").ignore);
+    assert!(!check_ignore(&config, "// only-x86_64-pc-windows-gnu"));
+    assert!(!check_ignore(&config, "// only-x86_64"));
+    assert!(!check_ignore(&config, "// only-windows"));
+    assert!(!check_ignore(&config, "// only-gnu"));
+    assert!(!check_ignore(&config, "// only-64bit"));
 }
 
 #[test]
@@ -174,8 +185,8 @@ fn stage() {
     let mut config = config();
     config.stage_id = "stage1".to_owned();
 
-    assert!(parse_rs(&config, "// ignore-stage1").ignore);
-    assert!(!parse_rs(&config, "// ignore-stage2").ignore);
+    assert!(check_ignore(&config, "// ignore-stage1"));
+    assert!(!check_ignore(&config, "// ignore-stage2"));
 }
 
 #[test]
@@ -183,26 +194,26 @@ fn cross_compile() {
     let mut config = config();
     config.host = "x86_64-apple-darwin".to_owned();
     config.target = "wasm32-unknown-unknown".to_owned();
-    assert!(parse_rs(&config, "// ignore-cross-compile").ignore);
+    assert!(check_ignore(&config, "// ignore-cross-compile"));
 
     config.target = config.host.clone();
-    assert!(!parse_rs(&config, "// ignore-cross-compile").ignore);
+    assert!(!check_ignore(&config, "// ignore-cross-compile"));
 }
 
 #[test]
 fn debugger() {
     let mut config = config();
     config.debugger = None;
-    assert!(!parse_rs(&config, "// ignore-cdb").ignore);
+    assert!(!check_ignore(&config, "// ignore-cdb"));
 
     config.debugger = Some(Debugger::Cdb);
-    assert!(parse_rs(&config, "// ignore-cdb").ignore);
+    assert!(check_ignore(&config, "// ignore-cdb"));
 
     config.debugger = Some(Debugger::Gdb);
-    assert!(parse_rs(&config, "// ignore-gdb").ignore);
+    assert!(check_ignore(&config, "// ignore-gdb"));
 
     config.debugger = Some(Debugger::Lldb);
-    assert!(parse_rs(&config, "// ignore-lldb").ignore);
+    assert!(check_ignore(&config, "// ignore-lldb"));
 }
 
 #[test]
@@ -211,17 +222,17 @@ fn sanitizers() {
 
     // Target that supports all sanitizers:
     config.target = "x86_64-unknown-linux-gnu".to_owned();
-    assert!(!parse_rs(&config, "// needs-sanitizer-address").ignore);
-    assert!(!parse_rs(&config, "// needs-sanitizer-leak").ignore);
-    assert!(!parse_rs(&config, "// needs-sanitizer-memory").ignore);
-    assert!(!parse_rs(&config, "// needs-sanitizer-thread").ignore);
+    assert!(!check_ignore(&config, "// needs-sanitizer-address"));
+    assert!(!check_ignore(&config, "// needs-sanitizer-leak"));
+    assert!(!check_ignore(&config, "// needs-sanitizer-memory"));
+    assert!(!check_ignore(&config, "// needs-sanitizer-thread"));
 
     // Target that doesn't support sanitizers:
     config.target = "wasm32-unknown-emscripten".to_owned();
-    assert!(parse_rs(&config, "// needs-sanitizer-address").ignore);
-    assert!(parse_rs(&config, "// needs-sanitizer-leak").ignore);
-    assert!(parse_rs(&config, "// needs-sanitizer-memory").ignore);
-    assert!(parse_rs(&config, "// needs-sanitizer-thread").ignore);
+    assert!(check_ignore(&config, "// needs-sanitizer-address"));
+    assert!(check_ignore(&config, "// needs-sanitizer-leak"));
+    assert!(check_ignore(&config, "// needs-sanitizer-memory"));
+    assert!(check_ignore(&config, "// needs-sanitizer-thread"));
 }
 
 #[test]
@@ -229,10 +240,10 @@ fn asm_support() {
     let mut config = config();
 
     config.target = "avr-unknown-gnu-atmega328".to_owned();
-    assert!(parse_rs(&config, "// needs-asm-support").ignore);
+    assert!(check_ignore(&config, "// needs-asm-support"));
 
     config.target = "i686-unknown-netbsd".to_owned();
-    assert!(!parse_rs(&config, "// needs-asm-support").ignore);
+    assert!(!check_ignore(&config, "// needs-asm-support"));
 }
 
 #[test]
@@ -240,13 +251,13 @@ fn channel() {
     let mut config = config();
     config.channel = "beta".into();
 
-    assert!(parse_rs(&config, "// ignore-beta").ignore);
-    assert!(parse_rs(&config, "// only-nightly").ignore);
-    assert!(parse_rs(&config, "// only-stable").ignore);
+    assert!(check_ignore(&config, "// ignore-beta"));
+    assert!(check_ignore(&config, "// only-nightly"));
+    assert!(check_ignore(&config, "// only-stable"));
 
-    assert!(!parse_rs(&config, "// only-beta").ignore);
-    assert!(!parse_rs(&config, "// ignore-nightly").ignore);
-    assert!(!parse_rs(&config, "// ignore-stable").ignore);
+    assert!(!check_ignore(&config, "// only-beta"));
+    assert!(!check_ignore(&config, "// ignore-nightly"));
+    assert!(!check_ignore(&config, "// ignore-stable"));
 }
 
 #[test]
index 8d23227fdb8b78dab6a6ac3556ac581e81f127de..dc6d67983c5d22da7932f17b07ea77f1e386ba0e 100644 (file)
@@ -43,7 +43,6 @@ struct FutureIncompatReport {
 
 #[derive(Deserialize)]
 struct FutureBreakageItem {
-    future_breakage_date: Option<String>,
     diagnostic: Diagnostic,
 }
 
@@ -104,9 +103,7 @@ pub fn extract_rendered(output: &str) -> String {
                                 .into_iter()
                                 .map(|item| {
                                     format!(
-                                        "Future breakage date: {}, diagnostic:\n{}",
-                                        item.future_breakage_date
-                                            .unwrap_or_else(|| "None".to_string()),
+                                        "Future breakage diagnostic:\n{}",
                                         item.diagnostic
                                             .rendered
                                             .unwrap_or_else(|| "Not rendered".to_string())
index c854663706a503efb898ca8c590b5a96c0c638c7..46432d5e4f5bcd9c1a73376e3d9a3b4bdf9e4115 100644 (file)
@@ -8,7 +8,7 @@ extern crate test;
 use crate::common::{
     expected_output_path, output_base_dir, output_relative_path, PanicStrategy, UI_EXTENSIONS,
 };
-use crate::common::{CompareMode, Config, Debugger, Mode, PassMode, Pretty, TestPaths};
+use crate::common::{CompareMode, Config, Debugger, Mode, PassMode, TestPaths};
 use crate::util::logv;
 use getopts::Options;
 use std::env;
@@ -22,7 +22,7 @@ use test::ColorConfig;
 use tracing::*;
 use walkdir::WalkDir;
 
-use self::header::EarlyProps;
+use self::header::{make_test_description, EarlyProps};
 
 #[cfg(test)]
 mod tests;
@@ -620,26 +620,13 @@ pub fn is_test(file_name: &OsString) -> bool {
 }
 
 fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec<test::TestDescAndFn> {
-    let early_props = if config.mode == Mode::RunMake {
-        // Allow `ignore` directives to be in the Makefile.
-        EarlyProps::from_file(config, &testpaths.file.join("Makefile"))
+    let test_path = if config.mode == Mode::RunMake {
+        // Parse directives in the Makefile
+        testpaths.file.join("Makefile")
     } else {
-        EarlyProps::from_file(config, &testpaths.file)
-    };
-
-    // The `should-fail` annotation doesn't apply to pretty tests,
-    // since we run the pretty printer across all tests by default.
-    // If desired, we could add a `should-fail-pretty` annotation.
-    let should_panic = match config.mode {
-        Pretty => test::ShouldPanic::No,
-        _ => {
-            if early_props.should_fail {
-                test::ShouldPanic::Yes
-            } else {
-                test::ShouldPanic::No
-            }
-        }
+        PathBuf::from(&testpaths.file)
     };
+    let early_props = EarlyProps::from_file(config, &test_path);
 
     // Incremental tests are special, they inherently cannot be run in parallel.
     // `runtest::run` will be responsible for iterating over revisions.
@@ -651,29 +638,20 @@ fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec<test
     revisions
         .into_iter()
         .map(|revision| {
-            let ignore = early_props.ignore
-                // Ignore tests that already run and are up to date with respect to inputs.
-                || is_up_to_date(
-                    config,
-                    testpaths,
-                    &early_props,
-                    revision.map(|s| s.as_str()),
-                    inputs,
-                );
-            test::TestDescAndFn {
-                desc: test::TestDesc {
-                    name: make_test_name(config, testpaths, revision),
-                    ignore,
-                    should_panic,
-                    allow_fail: false,
-                    #[cfg(not(bootstrap))]
-                    compile_fail: false,
-                    #[cfg(not(bootstrap))]
-                    no_run: false,
-                    test_type: test::TestType::Unknown,
-                },
-                testfn: make_test_closure(config, testpaths, revision),
-            }
+            let src_file =
+                std::fs::File::open(&test_path).expect("open test file to parse ignores");
+            let cfg = revision.map(|v| &**v);
+            let test_name = crate::make_test_name(config, testpaths, revision);
+            let mut desc = make_test_description(config, test_name, &test_path, src_file, cfg);
+            // Ignore tests that already run and are up to date with respect to inputs.
+            desc.ignore |= is_up_to_date(
+                config,
+                testpaths,
+                &early_props,
+                revision.map(|s| s.as_str()),
+                inputs,
+            );
+            test::TestDescAndFn { desc, testfn: make_test_closure(config, testpaths, revision) }
         })
         .collect()
 }
index 02dffaab7b620c826621d84ac1d51bd141d90d07..181ce0f2c3de5808f483e95249f9bd70c29ab577 100644 (file)
@@ -778,6 +778,14 @@ impl<'test> TestCx<'test> {
         script_str.push_str("version\n"); // List CDB (and more) version info in test output
         script_str.push_str(".nvlist\n"); // List loaded `*.natvis` files, bulk of custom MSVC debug
 
+        // If a .js file exists next to the source file being tested, then this is a JavaScript
+        // debugging extension that needs to be loaded.
+        let mut js_extension = self.testpaths.file.clone();
+        js_extension.set_extension("cdb.js");
+        if js_extension.exists() {
+            script_str.push_str(&format!(".scriptload \"{}\"\n", js_extension.to_string_lossy()));
+        }
+
         // Set breakpoints on every line that contains the string "#break"
         let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy();
         for line in &breakpoint_lines {
@@ -1125,8 +1133,8 @@ impl<'test> TestCx<'test> {
 
         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<.+>$",
@@ -2329,13 +2337,17 @@ impl<'test> TestCx<'test> {
         // useful flag.
         //
         // For now, though…
-        if let Some(rev) = self.revision {
-            let prefixes = format!("CHECK,{}", rev);
-            if self.config.llvm_version.unwrap_or(0) >= 130000 {
-                filecheck.args(&["--allow-unused-prefixes", "--check-prefixes", &prefixes]);
-            } else {
-                filecheck.args(&["--check-prefixes", &prefixes]);
-            }
+        let prefix_for_target =
+            if self.config.target.contains("msvc") { "MSVC" } else { "NONMSVC" };
+        let prefixes = if let Some(rev) = self.revision {
+            format!("CHECK,{},{}", prefix_for_target, rev)
+        } else {
+            format!("CHECK,{}", prefix_for_target)
+        };
+        if self.config.llvm_version.unwrap_or(0) >= 130000 {
+            filecheck.args(&["--allow-unused-prefixes", "--check-prefixes", &prefixes]);
+        } else {
+            filecheck.args(&["--check-prefixes", &prefixes]);
         }
         self.compose_and_run(filecheck, "", None, None)
     }
@@ -3328,8 +3340,11 @@ impl<'test> TestCx<'test> {
                 },
             )
             .unwrap();
-            let fixed_code = apply_suggestions(&unfixed_code, &suggestions).unwrap_or_else(|_| {
-                panic!("failed to apply suggestions for {:?} with rustfix", self.testpaths.file)
+            let fixed_code = apply_suggestions(&unfixed_code, &suggestions).unwrap_or_else(|e| {
+                panic!(
+                    "failed to apply suggestions for {:?} with rustfix: {}",
+                    self.testpaths.file, e
+                )
             });
 
             errors += self.compare_output("fixed", &fixed_code, &expected_fixed);
index ff6923b3797ebf052ad5d3614441504fcd3dcdf3..01a3fc812b2087cbad4ef95e08524e1d0cf38060 100644 (file)
@@ -67,6 +67,7 @@ impl Formatter for HTMLFormatter {
 <title>Rust Compiler Error Index</title>
 <meta charset="utf-8">
 <!-- Include rust.css after light.css so its rules take priority. -->
+<link rel="stylesheet" type="text/css" href="rustdoc{suffix}.css"/>
 <link rel="stylesheet" type="text/css" href="light{suffix}.css"/>
 <link rel="stylesheet" type="text/css" href="rust.css"/>
 <style>
@@ -283,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());
     }
diff --git a/src/tools/html-checker/Cargo.toml b/src/tools/html-checker/Cargo.toml
new file mode 100644 (file)
index 0000000..fe35df8
--- /dev/null
@@ -0,0 +1,12 @@
+[package]
+name = "html-checker"
+version = "0.1.0"
+authors = ["Guillaume Gomez <guillaume1.gomez@gmail.com>"]
+edition = "2018"
+
+[[bin]]
+name = "html-checker"
+path = "main.rs"
+
+[dependencies]
+walkdir = "2"
diff --git a/src/tools/html-checker/main.rs b/src/tools/html-checker/main.rs
new file mode 100644 (file)
index 0000000..7bdf527
--- /dev/null
@@ -0,0 +1,98 @@
+use std::env;
+use std::path::Path;
+use std::process::{Command, Output};
+
+fn check_html_file(file: &Path) -> usize {
+    let to_mute = &[
+        // "disabled" on <link> or "autocomplete" on <select> emit this warning
+        "PROPRIETARY_ATTRIBUTE",
+        // It complains when multiple in the same page link to the same anchor for some reason...
+        "ANCHOR_NOT_UNIQUE",
+        // If a <span> contains only HTML elements and no text, it complains about it.
+        "TRIM_EMPTY_ELEMENT",
+        // FIXME: the three next warnings are about <pre> elements which are not supposed to
+        //        contain HTML. The solution here would be to replace them with a <div>
+        "MISSING_ENDTAG_BEFORE",
+        "INSERTING_TAG",
+        "DISCARDING_UNEXPECTED",
+        // This error is caused by nesting the Notable Traits tooltip within an <h4> tag.
+        // The solution is to avoid doing that, but we need to have the <h4> tags for accessibility
+        // reasons, and we need the Notable Traits tooltip to help everyone understand the Iterator
+        // combinators
+        "TAG_NOT_ALLOWED_IN",
+    ];
+    let to_mute_s = to_mute.join(",");
+    let mut command = Command::new("tidy");
+    command
+        .arg("-errors")
+        .arg("-quiet")
+        .arg("--mute-id") // this option is useful in case we want to mute more warnings
+        .arg("yes")
+        .arg("--mute")
+        .arg(&to_mute_s)
+        .arg(file);
+
+    let Output { status, stderr, .. } = command.output().expect("failed to run tidy command");
+    if status.success() {
+        0
+    } else {
+        let stderr = String::from_utf8(stderr).expect("String::from_utf8 failed...");
+        if stderr.is_empty() && status.code() != Some(2) {
+            0
+        } else {
+            eprintln!(
+                "=> Errors for `{}` (error code: {}) <=",
+                file.display(),
+                status.code().unwrap_or(-1)
+            );
+            eprintln!("{}", stderr);
+            stderr.lines().count()
+        }
+    }
+}
+
+const DOCS_TO_CHECK: &[&str] =
+    &["alloc", "core", "proc_macro", "implementors", "src", "std", "test"];
+
+// Returns the number of files read and the number of errors.
+fn find_all_html_files(dir: &Path) -> (usize, usize) {
+    let mut files_read = 0;
+    let mut errors = 0;
+
+    for entry in walkdir::WalkDir::new(dir).into_iter().filter_entry(|e| {
+        e.depth() != 1
+            || e.file_name()
+                .to_str()
+                .map(|s| DOCS_TO_CHECK.into_iter().any(|d| *d == s))
+                .unwrap_or(false)
+    }) {
+        let entry = entry.expect("failed to read file");
+        if !entry.file_type().is_file() {
+            continue;
+        }
+        let entry = entry.path();
+        if entry.extension().and_then(|s| s.to_str()) == Some("html") {
+            errors += check_html_file(&entry);
+            files_read += 1;
+        }
+    }
+    (files_read, errors)
+}
+
+fn main() -> Result<(), String> {
+    let args = env::args().collect::<Vec<_>>();
+    if args.len() != 2 {
+        return Err(format!("Usage: {} <doc folder>", args[0]));
+    }
+
+    println!("Running HTML checker...");
+
+    let (files_read, errors) = find_all_html_files(&Path::new(&args[1]));
+    println!("Done! Read {} files...", files_read);
+    if errors > 0 {
+        Err(format!("HTML check failed: {} errors", errors))
+    } else {
+        println!("No error found!");
+        Ok(())
+    }
+}
index 47960c3f6cc2b596d9977cae1c7116ff173381ca..15edd628cdffcfa4532f48f6b30175143ceeba0f 100644 (file)
@@ -347,7 +347,7 @@ impl Checker {
                 } else {
                     report.errors += 1;
                     print!("{}:{}: broken link fragment ", pretty_path, i + 1);
-                    println!("`#{}` pointing to `{}`", fragment, pretty_path);
+                    println!("`#{}` pointing to `{}`", fragment, target_pretty_path);
                 };
             }
         });
index 3e376629f74fe6f6cd7657302074bc53ad2ae04f..9c580d8e07ee8c6ce7f3eef11cd76d8c31873448 100644 (file)
@@ -2,6 +2,7 @@
 <html lang="en">
 <head>
     <meta http-equiv="refresh" content="0;URL=sometarget">
+    <title>Redirection</title>
 </head>
 <body>
     <p>Redirecting to <a href="sometarget">sometarget</a>...</p>
index c6ec999e5cfe229422420eb7b1fb5aa09ae8cbf2..1a0b1b00e0de095dde50d75f8a2cbe7f8a2a9bf8 100644 (file)
@@ -15,7 +15,7 @@ fn run(dirname: &str) -> (ExitStatus, String, String) {
 fn broken_test(dirname: &str, expected: &str) {
     let (status, stdout, stderr) = run(dirname);
     assert!(!status.success());
-    if !stdout.contains(expected) {
+    if !contains(expected, &stdout) {
         panic!(
             "stdout did not contain expected text: {}\n\
             --- stdout:\n\
@@ -27,6 +27,25 @@ fn broken_test(dirname: &str, expected: &str) {
     }
 }
 
+fn contains(expected: &str, actual: &str) -> bool {
+    // Normalize for Windows paths.
+    let actual = actual.replace('\\', "/");
+    actual.lines().any(|mut line| {
+        for (i, part) in expected.split("[..]").enumerate() {
+            match line.find(part) {
+                Some(j) => {
+                    if i == 0 && j != 0 {
+                        return false;
+                    }
+                    line = &line[j + part.len()..];
+                }
+                None => return false,
+            }
+        }
+        line.is_empty() || expected.ends_with("[..]")
+    })
+}
+
 fn valid_test(dirname: &str) {
     let (status, stdout, stderr) = run(dirname);
     if !status.success() {
@@ -48,30 +67,47 @@ fn valid() {
 
 #[test]
 fn basic_broken() {
-    broken_test("basic_broken", "bar.html");
+    broken_test("basic_broken", "foo.html:3: broken link - `bar.html`");
 }
 
 #[test]
 fn broken_fragment_local() {
-    broken_test("broken_fragment_local", "#somefrag");
+    broken_test(
+        "broken_fragment_local",
+        "foo.html:3: broken link fragment `#somefrag` pointing to `foo.html`",
+    );
 }
 
 #[test]
 fn broken_fragment_remote() {
-    broken_test("broken_fragment_remote/inner", "#somefrag");
+    broken_test(
+        "broken_fragment_remote/inner",
+        "foo.html:3: broken link fragment `#somefrag` pointing to \
+         `[..]/broken_fragment_remote/bar.html`",
+    );
 }
 
 #[test]
 fn broken_redir() {
-    broken_test("broken_redir", "sometarget");
+    broken_test(
+        "broken_redir",
+        "foo.html:3: broken redirect from `redir-bad.html` to `sometarget`",
+    );
 }
 
 #[test]
 fn directory_link() {
-    broken_test("directory_link", "somedir");
+    broken_test(
+        "directory_link",
+        "foo.html:3: directory link to `somedir` (directory links should use index.html instead)",
+    );
 }
 
 #[test]
 fn redirect_loop() {
-    broken_test("redirect_loop", "redir-bad.html");
+    broken_test(
+        "redirect_loop",
+        "foo.html:3: redirect from `redir-bad.html` to `[..]redirect_loop/redir-bad.html` \
+         which is also a redirect (not supported)",
+    );
 }
index fe7780e6739bfe3106e66f7982833ccc6ebea34d..bc567caa78b7e500efaba0d7c2290fc73931a39d 100644 (file)
@@ -2,6 +2,7 @@
 <html lang="en">
 <head>
     <meta http-equiv="refresh" content="0;URL=redir-bad.html">
+    <title>Redirection</title>
 </head>
 <body>
     <p>Redirecting to <a href="redir-bad.html">redir-bad.html</a>...</p>
index d21336e7e738bb08d3497a27aa49ecd0fda99abe..f32683efe67ec8bf382534aa88f201d38b19d61f 100644 (file)
@@ -2,6 +2,7 @@
 <html lang="en">
 <head>
     <meta http-equiv="refresh" content="0;URL=xxx">
+    <title>Redirection</title>
 </head>
 <body>
     <p>Redirecting to <a href="xxx">xxx</a>...</p>
index 1808b23aed8564f539a3e902dee107bd4773727b..3a52a8973853738b9b882e5aaeba45c341f58572 100644 (file)
@@ -2,6 +2,7 @@
 <html lang="en">
 <head>
     <meta http-equiv="refresh" content="0;URL=redir-target.html">
+    <title>Redirection</title>
 </head>
 <body>
     <p>Redirecting to <a href="redir-target.html">redir-target.html</a>...</p>
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 d39cb597b21c8af1b404599a88c3e9710bb3eaec..869245d5b9554935736d494abb9fea3409abf915 100644 (file)
@@ -17,12 +17,16 @@ path = "lib.rs"
 [target.'cfg(windows)'.dependencies.winapi]
 version = "0.3"
 features = [
-  "aclapi",
   "accctrl",
+  "aclapi",
   "basetsd",
+  "cfg",
   "consoleapi",
   "errhandlingapi",
+  "evntrace",
   "fibersapi",
+  "in6addr",
+  "inaddr",
   "ioapiset",
   "jobapi",
   "jobapi2",
@@ -32,6 +36,8 @@ features = [
   "memoryapi",
   "minschannel",
   "minwinbase",
+  "mstcpip",
+  "mswsock",
   "namedpipeapi",
   "ntdef",
   "ntsecapi",
@@ -54,6 +60,8 @@ features = [
   "winbase",
   "wincon",
   "wincrypt",
+  "windef",
+  "winioctl",
   "winsock2",
   "ws2def",
   "ws2ipdef",
@@ -61,6 +69,7 @@ features = [
 ]
 
 [dependencies]
+bstr = { version = "0.2.13", features = ["default"] }
 byteorder = { version = "1", features = ['default', 'std'] }
 curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true }
 crossbeam-utils = { version = "0.8.0", features = ["nightly"] }
@@ -77,7 +86,7 @@ syn = { version = "1", features = ['fold', 'full', 'extra-traits', 'visit', 'vis
 url = { version = "2.0", features = ['serde'] }
 
 [target.'cfg(not(windows))'.dependencies]
-openssl = { version = "0.10.12", optional = true }
+openssl = { version = "0.10.35", optional = true }
 
 [features]
 all-static = ['openssl/vendored', 'curl-sys/static-curl', 'curl-sys/force-system-lib-on-osx']
index c55e014e834d479bd6518f4cfbd6d44c8a1f691f..416d824c5645ef997fe9b579a4fd8c4452ba488d 100644 (file)
@@ -10,6 +10,10 @@ const {Options, runTest} = require('browser-ui-test');
 function showHelp() {
     console.log("rustdoc-js options:");
     console.log("  --doc-folder [PATH]        : location of the generated doc folder");
+    console.log("  --file [PATH]              : file to run (can be repeated)");
+    console.log("  --debug                    : show extra information about script run");
+    console.log("  --show-text                : render font in pages");
+    console.log("  --no-headless              : disable headless mode");
     console.log("  --help                     : show this message then quit");
     console.log("  --tests-folder [PATH]      : location of the .GOML tests folder");
 }
@@ -18,24 +22,38 @@ function parseOptions(args) {
     var opts = {
         "doc_folder": "",
         "tests_folder": "",
+        "files": [],
+        "debug": false,
+        "show_text": false,
+        "no_headless": false,
     };
     var correspondances = {
         "--doc-folder": "doc_folder",
         "--tests-folder": "tests_folder",
+        "--debug": "debug",
+        "--show-text": "show_text",
+        "--no-headless": "no_headless",
     };
 
     for (var i = 0; i < args.length; ++i) {
         if (args[i] === "--doc-folder"
-            || args[i] === "--tests-folder") {
+            || args[i] === "--tests-folder"
+            || args[i] === "--file") {
             i += 1;
             if (i >= args.length) {
                 console.log("Missing argument after `" + args[i - 1] + "` option.");
                 return null;
             }
-            opts[correspondances[args[i - 1]]] = args[i];
+            if (args[i - 1] !== "--file") {
+                opts[correspondances[args[i - 1]]] = args[i];
+            } else {
+                opts["files"].push(args[i]);
+            }
         } else if (args[i] === "--help") {
             showHelp();
             process.exit(0);
+        } else if (correspondances[args[i]]) {
+            opts[correspondances[args[i]]] = true;
         } else {
             console.log("Unknown option `" + args[i] + "`.");
             console.log("Use `--help` to see the list of options");
@@ -61,24 +79,32 @@ async function main(argv) {
     const options = new Options();
     try {
         // This is more convenient that setting fields one by one.
-        options.parseArguments([
+        let args = [
             "--no-screenshot",
-            // This option shows what puppeteer "code" is run
-            // "--debug",
-            // This option disable the headless mode, allowing you to see what's going on.
-            // "--no-headless",
-            // The text isn't rendered by default because of a lot of small differences
-            // between hosts.
-            // "--show-text",
             "--variable", "DOC_PATH", opts["doc_folder"],
-        ]);
+        ];
+        if (opts["debug"]) {
+            args.push("--debug");
+        }
+        if (opts["show_text"]) {
+            args.push("--show-text");
+        }
+        if (opts["no_headless"]) {
+            args.push("--no-headless");
+        }
+        options.parseArguments(args);
     } catch (error) {
         console.error(`invalid argument: ${error}`);
         process.exit(1);
     }
 
     let failed = false;
-    let files = fs.readdirSync(opts["tests_folder"]).filter(file => path.extname(file) == ".goml");
+    let files;
+    if (opts["files"].length === 0) {
+        files = fs.readdirSync(opts["tests_folder"]).filter(file => path.extname(file) == ".goml");
+    } else {
+        files = opts["files"].filter(file => path.extname(file) == ".goml");
+    }
 
     files.sort();
     for (var i = 0; i < files.length; ++i) {
index 0f23663d6c2f9d057b35b8479bb3a1037fdea46b..68354b6ceaf25aa1a973050c358bac6baaf823fe 100644 (file)
@@ -176,7 +176,7 @@ https://rust-lang.github.io/rustfmt/?version=v1.4.33&search=#imports_granularity
 
 ### Changed
 
-- Original comment indentation for trailing comments within an `if` is now taken into account when determining the indentation level to use for the trailing comment in formatted code. This does not modify any existing code formatted with rustfmt; it simply gives the programmer discretion to specify whether the comment is associated to the `else` block, or if the trailing comment is just a member of the `if` block. ([#1575](https://github.com/rust-lang/rustfmt/issues/1575), [#4120](https://github.com/rust-lang/rustfmt/issues/4120), [#4506](https://github.com/rust-lang/rustfmt/issues/4506)) 
+- Original comment indentation for trailing comments within an `if` is now taken into account when determining the indentation level to use for the trailing comment in formatted code. This does not modify any existing code formatted with rustfmt; it simply gives the programmer discretion to specify whether the comment is associated to the `else` block, or if the trailing comment is just a member of the `if` block. ([#1575](https://github.com/rust-lang/rustfmt/issues/1575), [#4120](https://github.com/rust-lang/rustfmt/issues/4120), [#4506](https://github.com/rust-lang/rustfmt/issues/4506))
 
 In this example the `// else comment` refers to the `else`:
 ```rust
@@ -213,7 +213,7 @@ if toks.eat_token(Token::Word("modify"))? && toks.eat_token(Token::Word("labels"
 
 ### Fixed
 - Formatting of empty blocks with attributes which only contained comments is no longer butchered.([#4475](https://github.com/rust-lang/rustfmt/issues/4475), [#4467](https://github.com/rust-lang/rustfmt/issues/4467), [#4452](https://github.com/rust-lang/rustfmt/issues/4452#issuecomment-705886282), [#4522](https://github.com/rust-lang/rustfmt/issues/4522))
-- Indentation of trailing comments in non-empty extern blocks is now correct. ([#4120](https://github.com/rust-lang/rustfmt/issues/4120#issuecomment-696491872)) 
+- Indentation of trailing comments in non-empty extern blocks is now correct. ([#4120](https://github.com/rust-lang/rustfmt/issues/4120#issuecomment-696491872))
 
 ### Install/Download Options
 - **crates.io package** - *pending*
@@ -297,7 +297,7 @@ if toks.eat_token(Token::Word("modify"))? && toks.eat_token(Token::Word("labels"
 - Fix aligning comments of different group
 - Fix flattening imports with a single `self`.
 - Fix removing attributes on function parameters.
-- Fix removing `impl` keyword from opaque type. 
+- Fix removing `impl` keyword from opaque type.
 
 ## [1.4.8] 2019-09-08
 
@@ -329,7 +329,7 @@ if toks.eat_token(Token::Word("modify"))? && toks.eat_token(Token::Word("labels"
 
 - Add `--message-format` command line option to `cargo-fmt`.
 - Add `-l,--files-with-diff` command line option to `rustfmt`.
-- Add `json` emit mode. 
+- Add `json` emit mode.
 
 ### Fixed
 
@@ -380,7 +380,7 @@ if toks.eat_token(Token::Word("modify"))? && toks.eat_token(Token::Word("labels"
 
 ### Added
 
-- Add new attribute `rustfmt::skip::attributes` to prevent rustfmt 
+- Add new attribute `rustfmt::skip::attributes` to prevent rustfmt
 from formatting an attribute #3665
 
 ### Changed
index 37cb7474130c8086300ec3d2a95d6e0c3d9e3f52..9daa70653797657d6488a952e1f56f3c7f4d3411 100644 (file)
@@ -17,7 +17,7 @@ To enable unstable options, set `unstable_features = true` in `rustfmt.toml` or
 
 Below you find a detailed visual guide on all the supported configuration options of rustfmt:
 
-## `array_width` 
+## `array_width`
 
 Maximum width of an array literal before falling back to vertical formatting.
 
@@ -25,11 +25,11 @@ Maximum width of an array literal before falling back to vertical formatting.
 - **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
 - **Stable**: Yes
 
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `array_width` will take precedence. 
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `array_width` will take precedence.
 
 See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
 
-## `attr_fn_like_width` 
+## `attr_fn_like_width`
 
 Maximum width of the args of a function-like attributes before falling back to vertical formatting.
 
@@ -37,7 +37,7 @@ Maximum width of the args of a function-like attributes before falling back to v
 - **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
 - **Stable**: Yes
 
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `attr_fn_like_width` will take precedence. 
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `attr_fn_like_width` will take precedence.
 
 See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
 
@@ -295,7 +295,7 @@ where
 }
 ```
 
-## `chain_width` 
+## `chain_width`
 
 Maximum width of a chain to fit on one line.
 
@@ -303,7 +303,7 @@ Maximum width of a chain to fit on one line.
 - **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
 - **Stable**: Yes
 
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `chain_width` will take precedence. 
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `chain_width` will take precedence.
 
 See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
 
@@ -751,7 +751,7 @@ trait Lorem {
 }
 ```
 
-## `fn_call_width` 
+## `fn_call_width`
 
 Maximum width of the args of a function call before falling back to vertical formatting.
 
@@ -759,7 +759,7 @@ Maximum width of the args of a function call before falling back to vertical for
 - **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
 - **Stable**: Yes
 
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `fn_call_width` will take precedence. 
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `fn_call_width` will take precedence.
 
 See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
 
@@ -2124,7 +2124,7 @@ Don't reformat out of line modules
 - **Possible values**: `true`, `false`
 - **Stable**: No (tracking issue: #3389)
 
-## `single_line_if_else_max_width` 
+## `single_line_if_else_max_width`
 
 Maximum line length for single line if-else expressions. A value of `0` (zero) results in if-else expressions always being broken into multiple lines. Note this occurs when `use_small_heuristics` is set to `Off`.
 
@@ -2132,7 +2132,7 @@ Maximum line length for single line if-else expressions. A value of `0` (zero) r
 - **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
 - **Stable**: Yes
 
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `single_line_if_else_max_width` will take precedence. 
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `single_line_if_else_max_width` will take precedence.
 
 See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
 
@@ -2313,7 +2313,7 @@ fn main() {
 
 See also: [`indent_style`](#indent_style).
 
-## `struct_lit_width` 
+## `struct_lit_width`
 
 Maximum width in the body of a struct literal before falling back to vertical formatting. A value of `0` (zero) results in struct literals always being broken into multiple lines. Note this occurs when `use_small_heuristics` is set to `Off`.
 
@@ -2321,11 +2321,11 @@ Maximum width in the body of a struct literal before falling back to vertical fo
 - **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
 - **Stable**: Yes
 
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `struct_lit_width` will take precedence. 
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `struct_lit_width` will take precedence.
 
 See also [`max_width`](#max_width), [`use_small_heuristics`](#use_small_heuristics), and [`struct_lit_single_line`](#struct_lit_single_line)
 
-## `struct_variant_width` 
+## `struct_variant_width`
 
 Maximum width in the body of a struct variant before falling back to vertical formatting. A value of `0` (zero) results in struct literals always being broken into multiple lines. Note this occurs when `use_small_heuristics` is set to `Off`.
 
@@ -2333,7 +2333,7 @@ Maximum width in the body of a struct variant before falling back to vertical fo
 - **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
 - **Stable**: Yes
 
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `struct_variant_width` will take precedence. 
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `struct_variant_width` will take precedence.
 
 See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
 
@@ -2530,7 +2530,7 @@ fn main() {
 
 This option can be used to simplify the management and bulk updates of the granular width configuration settings ([`fn_call_width`](#fn_call_width), [`attr_fn_like_width`](#attr_fn_like_width), [`struct_lit_width`](#struct_lit_width), [`struct_variant_width`](#struct_variant_width), [`array_width`](#array_width), [`chain_width`](#chain_width), [`single_line_if_else_max_width`](#single_line_if_else_max_width)), that respectively control when formatted constructs are multi-lined/vertical based on width.
 
-Note that explicitly provided values for the width configuration settings take precedence and override the calculated values determined by `use_small_heuristics`. 
+Note that explicitly provided values for the width configuration settings take precedence and override the calculated values determined by `use_small_heuristics`.
 
 - **Default value**: `"Default"`
 - **Possible values**: `"Default"`, `"Off"`, `"Max"`
@@ -2595,7 +2595,7 @@ fn main() {
 ```
 
 #### `Off`:
-When `use_small_heuristics` is set to `Off`, the granular width settings are functionally disabled and ignored. See the documentation for the respective width config options for specifics. 
+When `use_small_heuristics` is set to `Off`, the granular width settings are functionally disabled and ignored. See the documentation for the respective width config options for specifics.
 
 ```rust
 enum Lorem {
index 131f38dd06a2b74031117e4f692cf5edd3d86050..1b77dad11f0fe9b397de1f4ddc28f1452d4dd7a2 100644 (file)
@@ -38,7 +38,7 @@ colourised diff will be printed so that the offending line(s) can quickly be
 identified.
 
 Without explicit settings, the tests will be run using rustfmt's default
-configuration. It is possible to run a test using non-default settings in several 
+configuration. It is possible to run a test using non-default settings in several
 ways. Firstly, you can include configuration parameters in comments at the top
 of the file. For example: to use 3 spaces per tab, start your test with
 `// rustfmt-tab_spaces: 3`. Just remember that the comment is part of the input,
index 00a7652aee0dcb10286f7ea9de0cfedfc6335e6c..7a4dcf8773b61a85b7fc6fcc6dd08c9a91b55a00 100644 (file)
@@ -150,8 +150,8 @@ for its configuration.
 
 Our visitor keeps track of the desired current indent due to blocks (
 `block_indent`). Each `visit_*` method reformats code according to this indent,
-`config.comment_width()` and `config.max_width()`. Most reformatting that is done 
-in the `visit_*` methods is a bit hacky and is meant to be temporary until it can 
+`config.comment_width()` and `config.max_width()`. Most reformatting that is done
+in the `visit_*` methods is a bit hacky and is meant to be temporary until it can
 be done properly.
 
 There are a bunch of methods called `rewrite_*`. They do the bulk of the
index 7a97d31bab9c7ac70162cd1c066fa09ff14d2614..500a9f9a37c8cb58f4f718ae1a829a3a6a1b0f3e 100644 (file)
@@ -180,13 +180,13 @@ needs to be specified in `rustfmt.toml`, e.g., with `edition = "2018"`.
 
 * For things you do not want rustfmt to mangle, use `#[rustfmt::skip]`
 * To prevent rustfmt from formatting a macro or an attribute,
-  use `#[rustfmt::skip::macros(target_macro_name)]` or 
+  use `#[rustfmt::skip::macros(target_macro_name)]` or
   `#[rustfmt::skip::attributes(target_attribute_name)]`
 
   Example:
 
     ```rust
-    #![rustfmt::skip::attributes(custom_attribute)]   
+    #![rustfmt::skip::attributes(custom_attribute)]
 
     #[custom_attribute(formatting , here , should , be , Skipped)]
     #[rustfmt::skip::macros(html)]
index 13a3ecaa1961cd99188bd49f0a7e650fce36f752..0269e3ee4af931437a9e6c5d9c81bd172c1fb193 100755 (executable)
@@ -15,7 +15,7 @@ set -ex
 # it again.
 #
 #which cargo-fmt || cargo install --force
-CFG_RELEASE=nightly CFG_RELEASE_CHANNEL=nightly cargo install --path . --force 
+CFG_RELEASE=nightly CFG_RELEASE_CHANNEL=nightly cargo install --path . --force
 
 echo "Integration tests for: ${INTEGRATION}"
 cargo fmt -- --version
index b69ecdc5cb8ae2985065bf54c5872d0528f1ac69..e0403574eebc1d73a361c70e144fe67920c4a40a 100644 (file)
@@ -34,7 +34,7 @@ impl<'b, T: Write + 'b> Session<'b, T> {
             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 cde5d390cf259ed5e2947a85f2ec83c19898a763..ce8a45eea65312dd5fee34d9918b852e9ce10114 100644 (file)
@@ -1,6 +1,7 @@
 #![feature(rustc_private)]
 #![deny(rust_2018_idioms)]
 #![warn(unreachable_pub)]
+#![recursion_limit = "256"]
 
 #[macro_use]
 extern crate derive_new;
index 5597af9ee320cbe67ec82f37d6bb9a01ce073b3c..974c0c5990c7ddb38f015d1aae4ccccd35645a69 100644 (file)
@@ -1,7 +1,7 @@
 use std::iter::ExactSizeIterator;
 use std::ops::Deref;
 
-use rustc_ast::ast::{self, FnRetTy, Mutability};
+use rustc_ast::ast::{self, AttrVec, FnRetTy, Mutability};
 use rustc_span::{symbol::kw, symbol::Ident, BytePos, Pos, Span};
 
 use crate::config::lists::*;
@@ -776,7 +776,7 @@ impl Rewrite for ast::Ty {
                 );
                 let data = ast::VariantData::Struct(fields.clone(), recovered);
                 let variant = ast::Variant {
-                    attrs: vec![],
+                    attrs: AttrVec::new(),
                     id: self.id,
                     span: self.span,
                     vis: DEFAULT_VISIBILITY,
@@ -800,7 +800,7 @@ impl Rewrite for ast::Ty {
                 );
                 let data = ast::VariantData::Struct(fields.clone(), recovered);
                 let variant = ast::Variant {
-                    attrs: vec![],
+                    attrs: AttrVec::new(),
                     id: self.id,
                     span: self.span,
                     vis: DEFAULT_VISIBILITY,
index d3c349fb701e18050e574a9d35e69debf5845799..614cda5f911c2354bcb5e9ebac60d78e44941d2d 100644 (file)
@@ -6,7 +6,7 @@ use rustc_ast::ast::{
 };
 use rustc_ast::ptr;
 use rustc_ast_pretty::pprust;
-use rustc_span::{sym, symbol, BytePos, ExpnId, Span, Symbol, SyntaxContext};
+use rustc_span::{sym, symbol, BytePos, LocalExpnId, Span, Symbol, SyntaxContext};
 use unicode_width::UnicodeWidthStr;
 
 use crate::comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses};
@@ -675,7 +675,7 @@ pub(crate) trait NodeIdExt {
 
 impl NodeIdExt for NodeId {
     fn root() -> NodeId {
-        NodeId::placeholder_from_expn_id(ExpnId::root())
+        NodeId::placeholder_from_expn_id(LocalExpnId::ROOT)
     }
 }
 
index 58c32993cb6ef24b1a08ac25c9a28acb32d925ba..e44d2bb725698d343ca141cb8c3a7efe59399610 100644 (file)
@@ -6,7 +6,7 @@ edition = "2018"
 autobins = false
 
 [dependencies]
-cargo_metadata = "0.11"
+cargo_metadata = "0.12"
 regex = "1"
 lazy_static = "1"
 walkdir = "2"
index 06cec1964a080d9ab1e84dbbd849603b84f12cf7..32660ae2aeeefd5b72a1865a4a6aed4d8bd2f585 100644 (file)
@@ -28,18 +28,16 @@ const LICENSES: &[&str] = &[
 const EXCEPTIONS: &[(&str, &str)] = &[
     ("mdbook", "MPL-2.0"),                                  // mdbook
     ("openssl", "Apache-2.0"),                              // cargo, mdbook
-    ("fuchsia-zircon-sys", "BSD-3-Clause"),                 // rustdoc, rustc, cargo
-    ("fuchsia-zircon", "BSD-3-Clause"), // rustdoc, rustc, cargo (jobserver & tempdir)
-    ("colored", "MPL-2.0"),             // rustfmt
-    ("ordslice", "Apache-2.0"),         // rls
-    ("ryu", "Apache-2.0 OR BSL-1.0"),   // rls/cargo/... (because of serde)
-    ("bytesize", "Apache-2.0"),         // cargo
-    ("im-rc", "MPL-2.0+"),              // cargo
-    ("sized-chunks", "MPL-2.0+"),       // cargo via im-rc
-    ("bitmaps", "MPL-2.0+"),            // cargo via im-rc
+    ("colored", "MPL-2.0"),                                 // rustfmt
+    ("ordslice", "Apache-2.0"),                             // rls
+    ("ryu", "Apache-2.0 OR BSL-1.0"),                       // rls/cargo/... (because of serde)
+    ("bytesize", "Apache-2.0"),                             // cargo
+    ("im-rc", "MPL-2.0+"),                                  // cargo
+    ("sized-chunks", "MPL-2.0+"),                           // cargo via im-rc
+    ("bitmaps", "MPL-2.0+"),                                // cargo via im-rc
     ("crossbeam-queue", "MIT/Apache-2.0 AND BSD-2-Clause"), // rls via rayon
-    ("instant", "BSD-3-Clause"),        // rustc_driver/tracing-subscriber/parking_lot
-    ("snap", "BSD-3-Clause"),           // rustc
+    ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot
+    ("snap", "BSD-3-Clause"),    // rustc
     // FIXME: this dependency violates the documentation comment above:
     ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target
 ];
@@ -115,8 +113,6 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
     "fixedbitset",
     "flate2",
     "fortanix-sgx-abi",
-    "fuchsia-zircon",
-    "fuchsia-zircon-sys",
     "generic-array",
     "getopts",
     "getrandom",
@@ -130,7 +126,6 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
     "itertools",
     "itoa",
     "jobserver",
-    "kernel32-sys",
     "lazy_static",
     "libc",
     "libz-sys",
@@ -222,7 +217,6 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
     "version_check",
     "wasi",
     "winapi",
-    "winapi-build",
     "winapi-i686-pc-windows-gnu",
     "winapi-util",
     "winapi-x86_64-pc-windows-gnu",
@@ -254,6 +248,7 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
     "libloading",
     "log",
     "mach",
+    "memchr",
     "object",
     "regalloc",
     "region",
@@ -287,6 +282,7 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
     check_exceptions(&metadata, EXCEPTIONS, runtime_ids, bad);
     check_dependencies(&metadata, PERMITTED_DEPENDENCIES, RESTRICTED_DEPENDENCY_CRATES, bad);
     check_crate_duplicate(&metadata, FORBIDDEN_TO_HAVE_DUPLICATES, bad);
+    check_rustfix(&metadata, bad);
 
     // Check rustc_codegen_cranelift independently as it has it's own workspace.
     let mut cmd = cargo_metadata::MetadataCommand::new();
@@ -547,3 +543,22 @@ fn normal_deps_of_r<'a>(
         normal_deps_of_r(resolve, &dep.pkg, result);
     }
 }
+
+fn check_rustfix(metadata: &Metadata, bad: &mut bool) {
+    let cargo = pkg_from_name(metadata, "cargo");
+    let compiletest = pkg_from_name(metadata, "compiletest");
+    let cargo_deps = deps_of(metadata, &cargo.id);
+    let compiletest_deps = deps_of(metadata, &compiletest.id);
+    let cargo_rustfix = cargo_deps.iter().find(|p| p.name == "rustfix").unwrap();
+    let compiletest_rustfix = compiletest_deps.iter().find(|p| p.name == "rustfix").unwrap();
+    if cargo_rustfix.version != compiletest_rustfix.version {
+        tidy_error!(
+            bad,
+            "cargo's rustfix version {} does not match compiletest's rustfix version {}\n\
+             rustfix should be kept in sync, update the cargo side first, and then update \
+             compiletest along with cargo.",
+            cargo_rustfix.version,
+            compiletest_rustfix.version
+        );
+    }
+}
index d6e0ebaa5410cf0d1317b55062b060adae5104c6..53c75a463390d75b8be1e66b9a9dd2f9b31e91df 100644 (file)
@@ -6,20 +6,33 @@ use std::ffi::OsStr;
 use std::fs::read_to_string;
 use std::path::Path;
 
+use regex::Regex;
+
 // 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", "E0314", "E0315", "E0377", "E0461", "E0462", "E0464",
-    "E0465", "E0473", "E0474", "E0475", "E0476", "E0479", "E0480", "E0481", "E0482", "E0483",
-    "E0484", "E0485", "E0486", "E0487", "E0488", "E0489", "E0514", "E0519", "E0523", "E0553",
-    "E0554", "E0570", "E0629", "E0630", "E0640", "E0717", "E0729",
+    "E0227", "E0279", "E0280", "E0313", "E0377", "E0461", "E0462", "E0464", "E0465", "E0476",
+    "E0482", "E0514", "E0519", "E0523", "E0554", "E0640", "E0717", "E0729",
 ];
 
 // Some error codes don't have any tests apparently...
 const IGNORE_EXPLANATION_CHECK: &[&str] = &["E0570", "E0601", "E0602", "E0729"];
 
+// If the file path contains any of these, we don't want to try to extract error codes from it.
+//
+// We need to declare each path in the windows version (with backslash).
+const PATHS_TO_IGNORE_FOR_EXTRACTION: &[&str] =
+    &["src/test/", "src\\test\\", "src/doc/", "src\\doc\\", "src/tools/", "src\\tools\\"];
+
+#[derive(Default, Debug)]
+struct ErrorCodeStatus {
+    has_test: bool,
+    has_explanation: bool,
+    is_used: bool,
+}
+
 fn check_error_code_explanation(
     f: &str,
-    error_codes: &mut HashMap<String, bool>,
+    error_codes: &mut HashMap<String, ErrorCodeStatus>,
     err_code: String,
 ) -> bool {
     let mut invalid_compile_fail_format = false;
@@ -30,7 +43,7 @@ fn check_error_code_explanation(
         if s.starts_with("```") {
             if s.contains("compile_fail") && s.contains('E') {
                 if !found_error_code {
-                    error_codes.insert(err_code.clone(), true);
+                    error_codes.get_mut(&err_code).map(|x| x.has_test = true);
                     found_error_code = true;
                 }
             } else if s.contains("compile-fail") {
@@ -38,7 +51,7 @@ fn check_error_code_explanation(
             }
         } else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") {
             if !found_error_code {
-                error_codes.get_mut(&err_code).map(|x| *x = true);
+                error_codes.get_mut(&err_code).map(|x| x.has_test = true);
                 found_error_code = true;
             }
         }
@@ -77,7 +90,7 @@ macro_rules! some_or_continue {
 
 fn extract_error_codes(
     f: &str,
-    error_codes: &mut HashMap<String, bool>,
+    error_codes: &mut HashMap<String, ErrorCodeStatus>,
     path: &Path,
     errors: &mut Vec<String>,
 ) {
@@ -90,15 +103,16 @@ fn extract_error_codes(
                 .split_once(':')
                 .expect(
                     format!(
-                        "Expected a line with the format `E0xxx: include_str!(\"..\")`, but got {} without a `:` delimiter",
+                        "Expected a line with the format `E0xxx: include_str!(\"..\")`, but got {} \
+                         without a `:` delimiter",
                         s,
-                    ).as_str()
+                    )
+                    .as_str(),
                 )
                 .0
                 .to_owned();
-            if !error_codes.contains_key(&err_code) {
-                error_codes.insert(err_code.clone(), false);
-            }
+            error_codes.entry(err_code.clone()).or_default().has_explanation = true;
+
             // Now we extract the tests from the markdown file!
             let md_file_name = match s.split_once("include_str!(\"") {
                 None => continue,
@@ -145,7 +159,7 @@ fn extract_error_codes(
             .to_string();
             if !error_codes.contains_key(&err_code) {
                 // this check should *never* fail!
-                error_codes.insert(err_code, false);
+                error_codes.insert(err_code, ErrorCodeStatus::default());
             }
         } else if s == ";" {
             reached_no_explanation = true;
@@ -153,7 +167,7 @@ fn extract_error_codes(
     }
 }
 
-fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap<String, bool>) {
+fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap<String, ErrorCodeStatus>) {
     for line in f.lines() {
         let s = line.trim();
         if s.starts_with("error[E") || s.starts_with("warning[E") {
@@ -164,8 +178,24 @@ fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap<String, boo
                     Some((_, err_code)) => err_code,
                 },
             };
-            let nb = error_codes.entry(err_code.to_owned()).or_insert(false);
-            *nb = true;
+            error_codes.entry(err_code.to_owned()).or_default().has_test = true;
+        }
+    }
+}
+
+fn extract_error_codes_from_source(
+    f: &str,
+    error_codes: &mut HashMap<String, ErrorCodeStatus>,
+    regex: &Regex,
+) {
+    for line in f.lines() {
+        if line.trim_start().starts_with("//") {
+            continue;
+        }
+        for cap in regex.captures_iter(line) {
+            if let Some(error_code) = cap.get(1) {
+                error_codes.entry(error_code.as_str().to_owned()).or_default().is_used = true;
+            }
         }
     }
 }
@@ -174,8 +204,17 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
     let mut errors = Vec::new();
     let mut found_explanations = 0;
     let mut found_tests = 0;
+    let mut error_codes: HashMap<String, ErrorCodeStatus> = HashMap::new();
+    // We want error codes which match the following cases:
+    //
+    // * foo(a, E0111, a)
+    // * foo(a, E0111)
+    // * foo(E0111, a)
+    // * #[error = "E0111"]
+    let regex = Regex::new(r#"[(,"\s](E\d{4})[,)"]"#).unwrap();
+
     println!("Checking which error codes lack tests...");
-    let mut error_codes: HashMap<String, bool> = HashMap::new();
+
     for path in paths {
         super::walk(path, &mut |path| super::filter_dirs(path), &mut |entry, contents| {
             let file_name = entry.file_name();
@@ -185,6 +224,11 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
             } else if entry.path().extension() == Some(OsStr::new("stderr")) {
                 extract_error_codes_from_tests(contents, &mut error_codes);
                 found_tests += 1;
+            } else if entry.path().extension() == Some(OsStr::new("rs")) {
+                let path = entry.path().to_string_lossy();
+                if PATHS_TO_IGNORE_FOR_EXTRACTION.iter().all(|c| !path.contains(c)) {
+                    extract_error_codes_from_source(contents, &mut error_codes, &regex);
+                }
             }
         });
     }
@@ -199,15 +243,43 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
     if errors.is_empty() {
         println!("Found {} error codes", error_codes.len());
 
-        for (err_code, nb) in &error_codes {
-            if !*nb && !EXEMPTED_FROM_TEST.contains(&err_code.as_str()) {
+        for (err_code, error_status) in &error_codes {
+            if !error_status.has_test && !EXEMPTED_FROM_TEST.contains(&err_code.as_str()) {
                 errors.push(format!("Error code {} needs to have at least one UI test!", err_code));
-            } else if *nb && EXEMPTED_FROM_TEST.contains(&err_code.as_str()) {
+            } else if error_status.has_test && EXEMPTED_FROM_TEST.contains(&err_code.as_str()) {
                 errors.push(format!(
                     "Error code {} has a UI test, it shouldn't be listed into EXEMPTED_FROM_TEST!",
                     err_code
                 ));
             }
+            if !error_status.is_used && !error_status.has_explanation {
+                errors.push(format!(
+                    "Error code {} isn't used and doesn't have an error explanation, it should be \
+                     commented in error_codes.rs file",
+                    err_code
+                ));
+            }
+        }
+    }
+    if errors.is_empty() {
+        // Checking if local constants need to be cleaned.
+        for err_code in EXEMPTED_FROM_TEST {
+            match error_codes.get(err_code.to_owned()) {
+                Some(status) => {
+                    if status.has_test {
+                        errors.push(format!(
+                            "{} error code has a test and therefore should be \
+                            removed from the `EXEMPTED_FROM_TEST` constant",
+                            err_code
+                        ));
+                    }
+                }
+                None => errors.push(format!(
+                    "{} error code isn't used anymore and therefore should be removed \
+                        from `EXEMPTED_FROM_TEST` constant",
+                    err_code
+                )),
+            }
         }
     }
     errors.sort();
index a7e700b935e04b2a9df6fdca3b94642a9b18f54e..338dfd11310aaa0e17d14ac63ef5b115dc00ceff 100644 (file)
@@ -301,6 +301,7 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features
             let mut parts = line.split(',');
             let level = match parts.next().map(|l| l.trim().trim_start_matches('(')) {
                 Some("active") => Status::Unstable,
+                Some("incomplete") => Status::Unstable,
                 Some("removed") => Status::Removed,
                 Some("accepted") => Status::Stable,
                 _ => return None,
index fcb27dae9ea90f4f53ace9c698cc60aa9133855f..a1c41eb99810e8c51b247b6b6dcb47f9604fb981 100644 (file)
@@ -47,6 +47,7 @@ pub mod extdeps;
 pub mod features;
 pub mod pal;
 pub mod style;
+pub mod target_specific_tests;
 pub mod ui_tests;
 pub mod unit_tests;
 pub mod unstable_book;
index 10356a2fdc5fc3d59fe62087380c97058728bf9f..440c352ea5320de9319e91c01525929028e3b96f 100644 (file)
@@ -55,6 +55,8 @@ fn main() {
             }
         }
 
+        check!(target_specific_tests, &src_path);
+
         // Checks that are done on the cargo workspace.
         check!(deps, &root_path, &cargo);
         check!(extdeps, &root_path);
index db177f75ceae9e906899bbe6a4b03da899cb3cba..24a100187797256866b86df0d2f5cb8d2e7fb427 100644 (file)
@@ -56,7 +56,6 @@ const EXCEPTION_PATHS: &[&str] = &[
     "library/std/src/f32.rs",
     "library/std/src/f64.rs",
     "library/std/src/path.rs",
-    "library/std/src/thread/available_concurrency.rs",
     "library/std/src/sys_common", // Should only contain abstractions over platforms
     "library/std/src/net/test.rs", // Utility helpers for tests
 ];
@@ -123,6 +122,7 @@ fn check_cfgs(
 
         let contains_platform_specific_cfg = cfg.contains("target_os")
             || cfg.contains("target_env")
+            || cfg.contains("target_abi")
             || cfg.contains("target_vendor")
             || cfg.contains("unix")
             || cfg.contains("windows");
index 3d5f39e8c90493eca270481998ddd6b2e051e1fe..15ed2f7a0a9756f8816578fb1363e3290f1a861c 100644 (file)
@@ -52,6 +52,7 @@ const ANNOTATIONS_TO_IGNORE: &[&str] = &[
     "// error-pattern",
     "// gdb",
     "// lldb",
+    "// cdb",
     "// normalize-stderr-test",
 ];
 
diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs
new file mode 100644 (file)
index 0000000..8e17491
--- /dev/null
@@ -0,0 +1,96 @@
+//! Tidy check to ensure that all target specific tests (those that require a `--target` flag)
+//! also require the pre-requisite LLVM components to run.
+
+use std::collections::BTreeMap;
+use std::path::Path;
+
+const COMMENT: &str = "//";
+const LLVM_COMPONENTS_HEADER: &str = "needs-llvm-components:";
+const COMPILE_FLAGS_HEADER: &str = "compile-flags:";
+
+/// Iterate through compiletest headers in a test contents.
+///
+/// Adjusted from compiletest/src/header.rs.
+fn iter_header<'a>(contents: &'a str, it: &mut dyn FnMut(Option<&'a str>, &'a str)) {
+    for ln in contents.lines() {
+        let ln = ln.trim();
+        if ln.starts_with(COMMENT) && ln[COMMENT.len()..].trim_start().starts_with('[') {
+            if let Some(close_brace) = ln.find(']') {
+                let open_brace = ln.find('[').unwrap();
+                let lncfg = &ln[open_brace + 1..close_brace];
+                it(Some(lncfg), ln[(close_brace + 1)..].trim_start());
+            } else {
+                panic!("malformed condition directive: expected `//[foo]`, found `{}`", ln)
+            }
+        } else if ln.starts_with(COMMENT) {
+            it(None, ln[COMMENT.len()..].trim_start());
+        }
+    }
+}
+
+#[derive(Default, Debug)]
+struct RevisionInfo<'a> {
+    target_arch: Option<&'a str>,
+    llvm_components: Option<Vec<&'a str>>,
+}
+
+pub fn check(path: &Path, bad: &mut bool) {
+    let tests = path.join("test");
+    super::walk(
+        &tests,
+        &mut |path| path.extension().map(|p| p == "rs") == Some(false),
+        &mut |entry, content| {
+            let file = entry.path().display();
+            let mut header_map = BTreeMap::new();
+            iter_header(content, &mut |cfg, directive| {
+                if let Some(value) = directive.strip_prefix(LLVM_COMPONENTS_HEADER) {
+                    let info = header_map.entry(cfg).or_insert(RevisionInfo::default());
+                    let comp_vec = info.llvm_components.get_or_insert(Vec::new());
+                    for component in value.split(' ') {
+                        let component = component.trim();
+                        if !component.is_empty() {
+                            comp_vec.push(component);
+                        }
+                    }
+                } else if directive.starts_with(COMPILE_FLAGS_HEADER) {
+                    let compile_flags = &directive[COMPILE_FLAGS_HEADER.len()..];
+                    if let Some((_, v)) = compile_flags.split_once("--target") {
+                        if let Some((arch, _)) =
+                            v.trim_start_matches(|c| c == ' ' || c == '=').split_once("-")
+                        {
+                            let info = header_map.entry(cfg).or_insert(RevisionInfo::default());
+                            info.target_arch.replace(arch);
+                        } else {
+                            eprintln!("{}: seems to have a malformed --target value", file);
+                            *bad = true;
+                        }
+                    }
+                }
+            });
+            for (rev, RevisionInfo { target_arch, llvm_components }) in &header_map {
+                let rev = rev.unwrap_or("[unspecified]");
+                match (target_arch, llvm_components) {
+                    (None, None) => {}
+                    (Some(_), None) => {
+                        eprintln!(
+                            "{}: revision {} should specify `{}` as it has `--target` set",
+                            file, rev, LLVM_COMPONENTS_HEADER
+                        );
+                        *bad = true;
+                    }
+                    (None, Some(_)) => {
+                        eprintln!(
+                            "{}: revision {} should not specify `{}` as it doesn't need `--target`",
+                            file, rev, LLVM_COMPONENTS_HEADER
+                        );
+                        *bad = true;
+                    }
+                    (Some(_), Some(_)) => {
+                        // FIXME: check specified components against the target architectures we
+                        // gathered.
+                    }
+                }
+            }
+        },
+    );
+}
index f61295c88308c1660f002527c601fb1630c5906a..66d05d9f00ee98c082916bb346005278f6d7c8e1 100644 (file)
@@ -7,8 +7,8 @@ use std::path::Path;
 
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
-const ROOT_ENTRY_LIMIT: usize = 1371;
-const ISSUES_ENTRY_LIMIT: usize = 2559;
+const ROOT_ENTRY_LIMIT: usize = 1345;
+const ISSUES_ENTRY_LIMIT: usize = 2530;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
index b7921ae87bcbc84829848daf1f08a8d86565e7b8..094d6ad00ce785097b2113c238df3156bd57e871 100644 (file)
@@ -1 +1 @@
-1.54.0
+1.55.0
index a3a7c153e3d3833975986ab6c72ca548a56992ab..99d09e9c6d93d393af178307341aca160b9ce330 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.toml":"a38eddf30ff67599455522658d7d6bd16ece9cf9fd54a567dbe5fc1463f02200","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"4a58a26808c92aae6265a60e21745bb2891a60cf1d69985fc05d26b77c2b9a79","build.rs":"afa03584629443ec723ca4e99bd087d5f07602d8640772f6f57c8e3847f75ae6","src/backtrace.rs":"a1a52f9874f0aa1382fb404f029c6fa88e53afe38fb2417877d5711f1f2b90c9","src/chain.rs":"1627608ce95c3484d26e1742a1b8b533b74c6159916b717bacffae3ae53731f9","src/context.rs":"559478ae785ce913523aa21358cc1561ef4b0b95c5c87675a77890364c0162fe","src/error.rs":"17ff455b47fef40ad3b2ed9cdfe87f151a7c535c3a1b719836815578f176c971","src/fmt.rs":"c2d4aad6ce20625a70a7c091e3087b6a2c19a4a87c7a12edb4c98978307245ea","src/kind.rs":"ccf5d8075d44b03cc69c0478ee5e5b3a02d4f2e7cecb37588b30043d3fcdf65f","src/lib.rs":"6845e3193380766e846665aa74ea34ac2f34b04da872e31b6ee06d194e06ba3b","src/macros.rs":"88daf58370b2fcc93c43ebd5b9c1659bf5460c972681b63d89d51132126e5560","src/ptr.rs":"f1ece995b5be064773ee3d516710b4948b0bee3c237786d9988c7d2acc52c95c","src/wrapper.rs":"1229beca67dbd95ca77c9ecce282272acc55276c267c58cb73a75388b4693dda","tests/common/mod.rs":"f9088c2d7afafa64ff730b629272045b776bfafc2f5957508242da630635f2e1","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/drop/mod.rs":"382956f4bd3dcd1f6036efb8f11193595a7c60e0a5dbf5f2da149f1f25183abf","tests/test_autotrait.rs":"981e792db353be2f14c7a1cabe43b5f1329c168cb7679077cc2be786a0920d48","tests/test_backtrace.rs":"0e50edbb33b6bd07ba89ff3db72fb7c688ba2a4371fccdbbb20309ab02948b6a","tests/test_boxed.rs":"98a45325b1e86d4c5d3094ab99cd1ada1f771c505d2d7322f0afcbe7bdb71cfa","tests/test_chain.rs":"f28efeae7395d1c395e6f1a647b4199c25a00410ade45248c145c6fcf2fb448a","tests/test_context.rs":"f82c915b182df1a604a4cd558a03b1a821414983d6f6af6822398104cea70676","tests/test_convert.rs":"cae1c941727f2371b2439ff95b2628f810cfb2f77431a0807de32db84c5844e1","tests/test_downcast.rs":"e9dc236dad1cbb8b7ad74a0d87d328f23a585fbb55670b8fe55a9a2644041c5c","tests/test_ffi.rs":"d0cb4c1d6d9154090982dee72ae3ebe05a5981f976058c3250f1c9da5a45edef","tests/test_fmt.rs":"17572596f257aac9aa2ec4620e292ca6a954128b94772bb948399fab53832e70","tests/test_macros.rs":"0288c879c4735a8d317560baa3d4a6efbf1435d8ec350c5cb12cc1ba7c484080","tests/test_repr.rs":"dbb9b04ddbe1ab31eb5331ea69f05bb3a147299da2275a3d4dcc92947b5591b9","tests/test_source.rs":"b80723cf635a4f8c4df21891b34bfab9ed2b2aa407e7a2f826d24e334cd5f88e","tests/ui/no-impl.rs":"fab6cbf2f6ea510b86f567dfb3b7c31250a9fd71ae5d110dbb9188be569ec593","tests/ui/no-impl.stderr":"3fc787fb9fcaf18f6d60a5e3cf13566f90194ec8ce7dd0b3ae63ec1fc40a1b6f","tests/ui/temporary-value.rs":"4dcc96271b2403e6372cf4cfc813445e5ce4365fc6e156b6bc38274098499a70","tests/ui/temporary-value.stderr":"4b0cceae9e9b27fe2594e6c02bb3e3fd9965ed04498738e5877934dab807b50f"},"package":"28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"}
\ No newline at end of file
+{"files":{"Cargo.toml":"b63402ace56df0d5f9cbc6e4ce27c8da96922025140a473c756befbe4faa04b2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"4a58a26808c92aae6265a60e21745bb2891a60cf1d69985fc05d26b77c2b9a79","build.rs":"afa03584629443ec723ca4e99bd087d5f07602d8640772f6f57c8e3847f75ae6","src/backtrace.rs":"a1a52f9874f0aa1382fb404f029c6fa88e53afe38fb2417877d5711f1f2b90c9","src/chain.rs":"1627608ce95c3484d26e1742a1b8b533b74c6159916b717bacffae3ae53731f9","src/context.rs":"559478ae785ce913523aa21358cc1561ef4b0b95c5c87675a77890364c0162fe","src/error.rs":"2aa93ec95f16980037c244e94fa8ac75f8b20ac22530fe45a24550d1878eb0b5","src/fmt.rs":"c2d4aad6ce20625a70a7c091e3087b6a2c19a4a87c7a12edb4c98978307245ea","src/kind.rs":"ccf5d8075d44b03cc69c0478ee5e5b3a02d4f2e7cecb37588b30043d3fcdf65f","src/lib.rs":"416d465af7511afbd8d58dc8a6ea432bfd8647f577e875d3772df1328510f625","src/macros.rs":"88daf58370b2fcc93c43ebd5b9c1659bf5460c972681b63d89d51132126e5560","src/ptr.rs":"f1ece995b5be064773ee3d516710b4948b0bee3c237786d9988c7d2acc52c95c","src/wrapper.rs":"1229beca67dbd95ca77c9ecce282272acc55276c267c58cb73a75388b4693dda","tests/common/mod.rs":"f9088c2d7afafa64ff730b629272045b776bfafc2f5957508242da630635f2e1","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/drop/mod.rs":"382956f4bd3dcd1f6036efb8f11193595a7c60e0a5dbf5f2da149f1f25183abf","tests/test_autotrait.rs":"981e792db353be2f14c7a1cabe43b5f1329c168cb7679077cc2be786a0920d48","tests/test_backtrace.rs":"0e50edbb33b6bd07ba89ff3db72fb7c688ba2a4371fccdbbb20309ab02948b6a","tests/test_boxed.rs":"6b26db0e2eb72afe9af7352ea820837aab90f8d486294616dd5dc34c1b94038c","tests/test_chain.rs":"0e81cf36c45ef1e77f0765f93ea56d07146be090ab35efec573a9fce34e36a23","tests/test_context.rs":"5399c609760b71f16bb63ed593f1adaf9f265bcfbc9aa5ab3361de35ddad48fe","tests/test_convert.rs":"7e7a8b4772a427a911014ac4d1083f9519000e786177f898808980dd9bdfde61","tests/test_downcast.rs":"ce8438cb58a1b7f3599740c261f6ef05855127ccde20c83c82db15eaf51c57ad","tests/test_ffi.rs":"d0cb4c1d6d9154090982dee72ae3ebe05a5981f976058c3250f1c9da5a45edef","tests/test_fmt.rs":"17572596f257aac9aa2ec4620e292ca6a954128b94772bb948399fab53832e70","tests/test_macros.rs":"0288c879c4735a8d317560baa3d4a6efbf1435d8ec350c5cb12cc1ba7c484080","tests/test_repr.rs":"dbb9b04ddbe1ab31eb5331ea69f05bb3a147299da2275a3d4dcc92947b5591b9","tests/test_source.rs":"b80723cf635a4f8c4df21891b34bfab9ed2b2aa407e7a2f826d24e334cd5f88e","tests/ui/no-impl.rs":"fab6cbf2f6ea510b86f567dfb3b7c31250a9fd71ae5d110dbb9188be569ec593","tests/ui/no-impl.stderr":"7dd1b84a267c83121d9f85a9c1aadc072a863ec324e170af4d7d19516f0f526c","tests/ui/temporary-value.rs":"4dcc96271b2403e6372cf4cfc813445e5ce4365fc6e156b6bc38274098499a70","tests/ui/temporary-value.stderr":"4b0cceae9e9b27fe2594e6c02bb3e3fd9965ed04498738e5877934dab807b50f"},"package":"595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486"}
\ No newline at end of file
index 09c3dbf1e7ff845289124b21735c89b951fbfae1..6886ed3b207d46d4d08d9ef71dabf003f14cb13e 100644 (file)
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "anyhow"
-version = "1.0.40"
+version = "1.0.42"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 description = "Flexible concrete Error type built on std::error::Error"
 documentation = "https://docs.rs/anyhow"
@@ -25,7 +25,7 @@ repository = "https://github.com/dtolnay/anyhow"
 rustdoc-args = ["--cfg", "doc_cfg"]
 targets = ["x86_64-unknown-linux-gnu"]
 [dependencies.backtrace]
-version = "0.3"
+version = "0.3.51"
 optional = true
 [dev-dependencies.futures]
 version = "0.3"
index f4f5bc28ced1fc4885f6c7133be08460512d69d9..92bb63de0ae51c60a3886d88f54126fca551f9f3 100644 (file)
@@ -741,12 +741,11 @@ unsafe fn context_chain_downcast<C>(e: Ref<ErrorImpl>, target: TypeId) -> Option
 where
     C: 'static,
 {
+    let unerased = e.cast::<ErrorImpl<ContextError<C, Error>>>().deref();
     if TypeId::of::<C>() == target {
-        let unerased = e.cast::<ErrorImpl<ContextError<C, Error>>>().deref();
         Some(Ref::new(&unerased._object.context).cast::<()>())
     } else {
         // Recurse down the context chain per the inner error's vtable.
-        let unerased = e.cast::<ErrorImpl<ContextError<C, Error>>>().deref();
         let source = &unerased._object.error;
         (vtable(source.inner.ptr).object_downcast)(source.inner.by_ref(), target)
     }
@@ -758,12 +757,11 @@ unsafe fn context_chain_downcast_mut<C>(e: Mut<ErrorImpl>, target: TypeId) -> Op
 where
     C: 'static,
 {
+    let unerased = e.cast::<ErrorImpl<ContextError<C, Error>>>().deref_mut();
     if TypeId::of::<C>() == target {
-        let unerased = e.cast::<ErrorImpl<ContextError<C, Error>>>().deref_mut();
         Some(Mut::new(&mut unerased._object.context).cast::<()>())
     } else {
         // Recurse down the context chain per the inner error's vtable.
-        let unerased = e.cast::<ErrorImpl<ContextError<C, Error>>>().deref_mut();
         let source = &mut unerased._object.error;
         (vtable(source.inner.ptr).object_downcast_mut)(source.inner.by_mut(), target)
     }
index d6d70cf8742681ded3bd1ba8149d259980716115..b5564fd8c4fda7d806467441c38d9c2a86d9a9f7 100644 (file)
 //! will require an explicit `.map_err(Error::msg)` when working with a
 //! non-Anyhow error type inside a function that returns Anyhow's error type.
 
-#![doc(html_root_url = "https://docs.rs/anyhow/1.0.40")]
+#![doc(html_root_url = "https://docs.rs/anyhow/1.0.42")]
 #![cfg_attr(backtrace, feature(backtrace))]
 #![cfg_attr(doc_cfg, feature(doc_cfg))]
 #![cfg_attr(not(feature = "std"), no_std)]
index 38a568fb73a5dd9c75eafa26479acad80004e811..fb1fb132d50c8eacdf9aaf61250c0ce6aa91a413 100644 (file)
@@ -1,3 +1,8 @@
+#![allow(
+    // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
+    clippy::nonstandard_macro_braces,
+)]
+
 use anyhow::anyhow;
 use std::error::Error as StdError;
 use std::io;
index b1c5a3daaa8f4ba80abf17e9be4825f4e76feea2..12fd472de65d7bce850cc64d1d91dcbe8c2daeb8 100644 (file)
@@ -1,4 +1,4 @@
-use anyhow::{anyhow, Error};
+use anyhow::{anyhow, Chain, Error};
 
 fn error() -> Error {
     anyhow!(0).context(1).context(2).context(3)
@@ -33,13 +33,36 @@ fn test_len() {
     let e = error();
     let mut chain = e.chain();
     assert_eq!(4, chain.len());
+    assert_eq!((4, Some(4)), chain.size_hint());
     assert_eq!("3", chain.next().unwrap().to_string());
     assert_eq!(3, chain.len());
+    assert_eq!((3, Some(3)), chain.size_hint());
     assert_eq!("0", chain.next_back().unwrap().to_string());
     assert_eq!(2, chain.len());
+    assert_eq!((2, Some(2)), chain.size_hint());
     assert_eq!("2", chain.next().unwrap().to_string());
     assert_eq!(1, chain.len());
+    assert_eq!((1, Some(1)), chain.size_hint());
     assert_eq!("1", chain.next_back().unwrap().to_string());
     assert_eq!(0, chain.len());
+    assert_eq!((0, Some(0)), chain.size_hint());
     assert!(chain.next().is_none());
 }
+
+#[test]
+fn test_default() {
+    let mut c = Chain::default();
+    assert!(c.next().is_none());
+}
+
+#[test]
+fn test_clone() {
+    let e = error();
+    let mut chain = e.chain().clone();
+    assert_eq!("3", chain.next().unwrap().to_string());
+    assert_eq!("2", chain.next().unwrap().to_string());
+    assert_eq!("1", chain.next().unwrap().to_string());
+    assert_eq!("0", chain.next().unwrap().to_string());
+    assert!(chain.next().is_none());
+    assert!(chain.next_back().is_none());
+}
index 44c1c7036e261cc210109fadad6d64cb1bd43eaf..e2d4a29be8c7254c1db0a9ce6ff328f90d3fb514 100644 (file)
@@ -1,3 +1,8 @@
+#![allow(
+    // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
+    clippy::nonstandard_macro_braces,
+)]
+
 mod drop;
 
 use crate::drop::{DetectDrop, Flag};
@@ -157,3 +162,10 @@ fn test_unsuccessful_downcast() {
     drop(err);
     assert!(dropped.all());
 }
+
+#[test]
+fn test_root_cause() {
+    let (err, _) = make_chain();
+
+    assert_eq!(err.root_cause().to_string(), "no such file or directory");
+}
index aff64e2fc7f27baafe519749dc5b62926de42a74..6da171d1b8906687e3cbb3fbaae8faf864b66d3d 100644 (file)
@@ -8,6 +8,26 @@ use std::error::Error as StdError;
 
 #[test]
 fn test_convert() {
+    let has_dropped = Flag::new();
+    let error = Error::new(DetectDrop::new(&has_dropped));
+    let box_dyn = Box::<dyn StdError>::from(error);
+    assert_eq!("oh no!", box_dyn.to_string());
+    drop(box_dyn);
+    assert!(has_dropped.get());
+}
+
+#[test]
+fn test_convert_send() {
+    let has_dropped = Flag::new();
+    let error = Error::new(DetectDrop::new(&has_dropped));
+    let box_dyn = Box::<dyn StdError + Send>::from(error);
+    assert_eq!("oh no!", box_dyn.to_string());
+    drop(box_dyn);
+    assert!(has_dropped.get());
+}
+
+#[test]
+fn test_convert_send_sync() {
     let has_dropped = Flag::new();
     let error = Error::new(DetectDrop::new(&has_dropped));
     let box_dyn = Box::<dyn StdError + Send + Sync>::from(error);
index 6b937107cb20a5e09942d1e8e4b71cd93971baf6..7fb063f289cf5d0ef2adb0b66d252e2f3d69707c 100644 (file)
@@ -84,6 +84,15 @@ fn test_drop() {
     assert!(has_dropped.get());
 }
 
+#[test]
+fn test_as_ref() {
+    let error = bail_error().unwrap_err();
+    let ref_dyn: &dyn StdError = error.as_ref();
+    assert_eq!("oh no!", ref_dyn.to_string());
+    let ref_dyn_send_sync: &(dyn StdError + Send + Sync) = error.as_ref();
+    assert_eq!("oh no!", ref_dyn_send_sync.to_string());
+}
+
 #[test]
 fn test_large_alignment() {
     #[repr(align(64))]
index a4a829b6600e6d0216bf6f0de80ed64c5d7cda6b..976b62c7bcce26b7462dac624b85103a320b1a03 100644 (file)
@@ -18,4 +18,4 @@ error[E0599]: the method `anyhow_kind` exists for reference `&Error`, but its tr
           which is required by `&Error: anyhow::private::kind::AdhocKind`
           `&Error: Into<anyhow::Error>`
           which is required by `&Error: anyhow::private::kind::TraitKind`
-  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  = note: this error originates in the macro `anyhow` (in Nightly builds, run with -Z macro-backtrace for more info)
index 893d948ba4bb6ce312503c7323b0e7f24a33fb87..6e5ca468a6a500d3ae4571f6af9f0df2a13991af 100644 (file)
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"4b393a4e04a5c46534641dda836c23c2bbcb6b69bda26911157e4f8b56ce9c68","Cargo.toml":"3c9c6a7f8ea422179938ba688bf21f64e1312571b41279fa31e252906b7e917c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0245ee104228a100ce5fceecf43e25faae450494d9173f43fd94c27d69fdac13","README.md":"2264c34c62ea4c617d72047b00749b4786dfb9dff2fac24e0320170ee0cd19c8","benches/arraystring.rs":"fad1cecef71c290375befc77c75a868988b8d74135e8f8732bc5b58c85a8ab46","benches/extend.rs":"c38ecedbc88217a7e9fe1a73f916b168a96e48010a7ccd3dba5c3f8dea030d5d","ci/miri.sh":"6bad1d135e1bdd67a6b91c870a7cf5ee09a85f9515633592a6abfbba95fdaf52","src/array_string.rs":"cefc432a025d780e01113144cbd5c0856d4424ec7fba4e626ddea523fbc8bbaf","src/arrayvec.rs":"0ef14cd1ac4b827ae7ba3afd4c9f7b161cad8c329a6c160ffa311bbe9505b479","src/arrayvec_impl.rs":"a5e3391dc350041651f0ba3816c863ff7f552ff553e4a88f801481dfad7e7613","src/char.rs":"1de50e1d6045af2b3496426492315ba774986f9bc8301ffa391de861a08cc9cb","src/errors.rs":"ca44c0987f59ae57623088d80013e75129101caea93c278c8ebb0df898bc6b1b","src/lib.rs":"6260569570f43fd52ef1fdbd2620a03a1a8088a3ce96e21956bb45217bda7f70","src/utils.rs":"d1cdc508dfca385e63f1f57bc8b53ed4a7f515e4ac1ebaa97b1d543fc8369432","tests/serde.rs":"117eb2961b5954d13c577edf60bbb07cb7481685cc9d6c49760a981d71465849","tests/tests.rs":"70d6fdcfa4b347f6fa720d0f9ba37a99d706a02bcdb4dbbe2913c9e5b489a990"},"package":"5a2f58b0bb10c380af2b26e57212856b8c9a59e0925b4c20f4a174a49734eaf7"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"9608f4cde67279f69e80b85373f19c1dde90a075b51d930e25e26d7ddabbfa03","Cargo.toml":"f4001657c27de1386a449fc5035abc0016f4f70ad99161b16e263d1eb2892dd8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0245ee104228a100ce5fceecf43e25faae450494d9173f43fd94c27d69fdac13","README.md":"2264c34c62ea4c617d72047b00749b4786dfb9dff2fac24e0320170ee0cd19c8","benches/arraystring.rs":"fad1cecef71c290375befc77c75a868988b8d74135e8f8732bc5b58c85a8ab46","benches/extend.rs":"c38ecedbc88217a7e9fe1a73f916b168a96e48010a7ccd3dba5c3f8dea030d5d","ci/miri.sh":"6bad1d135e1bdd67a6b91c870a7cf5ee09a85f9515633592a6abfbba95fdaf52","src/array_string.rs":"cefc432a025d780e01113144cbd5c0856d4424ec7fba4e626ddea523fbc8bbaf","src/arrayvec.rs":"32da1d3202f621852a3b884491f7a1086b7d813fe64b5cd7cab858ad3e967560","src/arrayvec_impl.rs":"a5e3391dc350041651f0ba3816c863ff7f552ff553e4a88f801481dfad7e7613","src/char.rs":"1de50e1d6045af2b3496426492315ba774986f9bc8301ffa391de861a08cc9cb","src/errors.rs":"ca44c0987f59ae57623088d80013e75129101caea93c278c8ebb0df898bc6b1b","src/lib.rs":"29a4123616c0912ccae5d931d45f0ccc3746647da1ba077c34538824910dd0ca","src/utils.rs":"d1cdc508dfca385e63f1f57bc8b53ed4a7f515e4ac1ebaa97b1d543fc8369432","tests/serde.rs":"117eb2961b5954d13c577edf60bbb07cb7481685cc9d6c49760a981d71465849","tests/tests.rs":"c1cd94337f4dc9aa31a6c16e334319389c605a98ccc5792e5489167cb614b7cb"},"package":"be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd"}
\ No newline at end of file
index fba82ab32d7daafba467133c0f9674931ee4a8c6..8abfc0f2fb17be05c6545e5801854073a63d0c3f 100644 (file)
@@ -1,6 +1,11 @@
 Recent Changes (arrayvec)
 =========================
 
+## 0.7.1
+
+- Add new ArrayVec methods `.take()` and `.into_inner_unchecked()` by @conradludgate
+- `clone_from` now uses `truncate` when needed by @a1phyr
+
 ## 0.7.0
 
 - `fn new_const` is now the way to const-construct arrayvec and arraystring,
@@ -8,8 +13,12 @@ Recent Changes (arrayvec)
   This works around performance issue #182, where the const fn version did not
   optimize well. Change by @bluss with thanks to @rodrimati1992 and @niklasf
   for analyzing the problem.
+
 - The deprecated feature flag `unstable-const-fn` was removed, since it's not needed
 
+- Optimize `.retain()` by using the same algorithm as in std, change by @niklasf,
+  issue #174. Original optimization in Rust std by @oxalica in rust-lang/rust/pull/81126
+
 ## 0.6.1
 
 - The ``ArrayVec::new`` and ``ArrayString::new`` constructors are properly
index 859ff3838bbea6f122f799ca4e93aec8dddbec58..a71ed05d49900bea6bbbcf7783366d4fea3f42f1 100644 (file)
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "arrayvec"
-version = "0.7.0"
+version = "0.7.1"
 authors = ["bluss"]
 description = "A vector with fixed capacity, backed by an array (it can be stored on the stack too). Implements fixed capacity ArrayVec and ArrayString."
 documentation = "https://docs.rs/arrayvec/"
index 57002372fe4ae7162bc06e320e45ef2a34cd89a6..6b4faf8a830e987b946a7ff9f9648d92227c670d 100644 (file)
@@ -636,14 +636,34 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
         if self.len() < self.capacity() {
             Err(self)
         } else {
-            unsafe {
-                let self_ = ManuallyDrop::new(self);
-                let array = ptr::read(self_.as_ptr() as *const [T; CAP]);
-                Ok(array)
-            }
+            unsafe { Ok(self.into_inner_unchecked()) }
         }
     }
 
+    /// Return the inner fixed size array.
+    ///
+    /// Safety:
+    /// This operation is safe if and only if length equals capacity.
+    pub unsafe fn into_inner_unchecked(self) -> [T; CAP] {
+        debug_assert_eq!(self.len(), self.capacity());
+        let self_ = ManuallyDrop::new(self);
+        let array = ptr::read(self_.as_ptr() as *const [T; CAP]);
+        array
+    }
+
+    /// Returns the ArrayVec, replacing the original with a new empty ArrayVec.
+    ///
+    /// ```
+    /// use arrayvec::ArrayVec;
+    ///
+    /// let mut v = ArrayVec::from([0, 1, 2, 3]);
+    /// assert_eq!([0, 1, 2, 3], v.take().into_inner().unwrap());
+    /// assert!(v.is_empty());
+    /// ```
+    pub fn take(&mut self) -> Self  {
+        mem::replace(self, Self::new())
+    }
+
     /// Return a slice containing all elements of the vector.
     pub fn as_slice(&self) -> &[T] {
         ArrayVecImpl::as_slice(self)
@@ -1079,9 +1099,7 @@ impl<T, const CAP: usize> Clone for ArrayVec<T, CAP>
 
         if prefix < self.len() {
             // rhs was shorter
-            for _ in 0..self.len() - prefix {
-                self.pop();
-            }
+            self.truncate(prefix);
         } else {
             let rhs_elems = &rhs[self.len()..];
             self.extend_from_slice(rhs_elems);
index d5a032014ee7e5579371a26a21896525ecbefc7e..5dc0273a70b4f1378c9f4ca99e1a8ae81dbf2c10 100644 (file)
@@ -15,7 +15,7 @@
 //!
 //! This version of arrayvec requires Rust 1.51 or later.
 //!
-#![doc(html_root_url="https://docs.rs/arrayvec/0.6/")]
+#![doc(html_root_url="https://docs.rs/arrayvec/0.7/")]
 #![cfg_attr(not(feature="std"), no_std)]
 
 #[cfg(feature="serde")]
index ca42c74500ca0b6589e97af0c4daeb7a57f0327f..26d09ae6bbb9658a2a788352dbf76124dfc34d73 100644 (file)
@@ -153,6 +153,21 @@ fn test_drop() {
         assert_eq!(flag.get(), 3);
     }
 
+    // test take
+    flag.set(0);
+    {
+        let mut array1 = ArrayVec::<_,  3>::new();
+        array1.push(Bump(flag));
+        array1.push(Bump(flag));
+        array1.push(Bump(flag));
+        let array2 = array1.take();
+        assert_eq!(flag.get(), 0);
+        drop(array1);
+        assert_eq!(flag.get(), 0);
+        drop(array2);
+        assert_eq!(flag.get(), 3);
+    }
+
     // test cloning into_iter
     flag.set(0);
     {
@@ -461,6 +476,15 @@ fn test_into_inner_3() {
     assert_eq!(v.into_inner().unwrap(), [1, 2, 3, 4]);
 }
 
+#[test]
+fn test_take() {
+    let mut v1 = ArrayVec::<i32,  4>::new();
+    v1.extend(1..=4);
+    let v2 = v1.take();
+    assert!(v1.into_inner().is_err());
+    assert_eq!(v2.into_inner().unwrap(), [1, 2, 3, 4]);
+}
+
 #[cfg(feature="std")]
 #[test]
 fn test_write() {
index 434cc1a16fad758da85ab4a32186048105e062c7..80ba51cc7cc052c033071d83620dfd510d5e14be 100644 (file)
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"3a745d94ee9dce0d9dc638c02078cd5001d3d9d12d58b4f220c0101e32cfc16a","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"8585455e5a0e638cf5d489a21e286e93680f835cb8a13595918b5eb7c8c7f212","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"9d57556868344534de2489317e3c6bb611348ecd44438dcb982bd8d2a55a5a1b","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"a80bf3cd446c9b6c0cca3865c4de047bdf4644b74cdf696822f8ff87adfa1fca","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/io.rs":"9612530634d0e7ce9887a23836b58c0d972c1f45b05d9ada8355961567075627","src/lib.rs":"813ce6a8beafee3fd4e63325d783108aa02e8c57e412bc97580191d84082fbc9"},"package":"14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"51f0eb3b6139fc1a908d41a7b3cba7d58d684700986b3518f82e5af254c39e8e","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"fb8b84be3b93b1aa065558cf9f8a867e1fc0f9bda8323d686ece79bbcfe50868","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"b2dd89866b56f619661b90e8b3b7d3f741b0a8d5710e229df86843ae0881284f","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"80e43e07f34bc6d3ebe4f37cea79ba02cafce6cf30b737a1db65de55f2c38ca5","build.rs":"9671089eb30f52975911effd1fa0b30a0ab14473f44a315af0bafd6701dda6da","src/io.rs":"8f22d1b0e01fa4ce9c7c5cd727dbc40ca35c22d9c82fe8d324d9d83d37cdcc4a","src/lib.rs":"c43331d25d0d12e150b64137d6f180ae46a8c41124a374e4f62d2867482bd3d8"},"package":"08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"}
\ No newline at end of file
index 6b51eb07607371dd8736a7fcdaee9b2f16691a0f..020beb46496c511e75098a85188b0c2d314d0e41 100644 (file)
@@ -1,28 +1,3 @@
-1.3.4
-=====
-This patch release squashes deprecation warnings for the `try!` macro, in
-accordance with byteorder's minimum supported Rust version (currently at Rust
-1.12.0).
-
-
-1.3.3
-=====
-This patch release adds `ByteOrder::write_i8_into()` as a simple, safe interface
-for ordinarily unsafe or tedious code.
-
-
-1.3.2
-=====
-This patch release adds `ReadBytesExt::read_i8_into()` as a simple, safe interface
-for ordinarily unsafe or tedious code.
-
-
-1.3.1
-=====
-This minor release performs mostly small internal changes. Going forward, these
-are not going to be incorporated into the changelog.
-
-
 1.3.0
 =====
 This new minor release now enables `i128` support automatically on Rust
index c71f90ba9c89314e4895b94dd33a6bfe0d704c4d..9d6d32418c83c719f2d398f2424a1cbdf850b111 100644 (file)
 # will likely look very different (and much more reasonable)
 
 [package]
-edition = "2018"
 name = "byteorder"
-version = "1.4.3"
+version = "1.3.4"
 authors = ["Andrew Gallant <jamslam@gmail.com>"]
+build = "build.rs"
 exclude = ["/ci/*"]
 description = "Library for reading/writing numbers in big-endian and little-endian."
 homepage = "https://github.com/BurntSushi/byteorder"
 documentation = "https://docs.rs/byteorder"
 readme = "README.md"
 keywords = ["byte", "endian", "big-endian", "little-endian", "binary"]
-categories = ["encoding", "parsing", "no-std"]
+categories = ["encoding", "parsing"]
 license = "Unlicense OR MIT"
 repository = "https://github.com/BurntSushi/byteorder"
 [profile.bench]
@@ -30,14 +30,19 @@ opt-level = 3
 [lib]
 name = "byteorder"
 bench = false
+[dev-dependencies.doc-comment]
+version = "0.3"
+
 [dev-dependencies.quickcheck]
-version = "0.9.2"
+version = "0.8"
 default-features = false
 
 [dev-dependencies.rand]
-version = "0.7"
+version = "0.6"
 
 [features]
 default = ["std"]
 i128 = []
 std = []
+[badges.travis-ci]
+repository = "BurntSushi/byteorder"
index d8461c58f7060ea5511e21da072e9465acd7c6f6..8940b295199257e3ccafaf4b0432f2460e83c5f7 100644 (file)
@@ -1,12 +1,10 @@
-byteorder
-=========
 This crate provides convenience methods for encoding and decoding
 numbers in either big-endian or little-endian order.
 
-[![Build status](https://github.com/BurntSushi/byteorder/workflows/ci/badge.svg)](https://github.com/BurntSushi/byteorder/actions)
-[![](https://meritbadge.herokuapp.com/byteorder)](https://crates.io/crates/byteorder)
+[![Build status](https://api.travis-ci.org/BurntSushi/byteorder.svg)](https://travis-ci.org/BurntSushi/byteorder)
+[![](http://meritbadge.herokuapp.com/byteorder)](https://crates.io/crates/byteorder)
 
-Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
+Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
 
 
 ### Documentation
@@ -29,6 +27,8 @@ If you want to augment existing `Read` and `Write` traits, then import the
 extension methods like so:
 
 ```rust
+extern crate byteorder;
+
 use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian, LittleEndian};
 ```
 
index bb00422f7952a12049cd00c43f4f746e76d11578..d53d25e4b5df224191131b59adfda24ba6d33651 100644 (file)
@@ -1,15 +1,15 @@
 #![feature(test)]
 
+extern crate byteorder;
+extern crate rand;
 extern crate test;
 
 macro_rules! bench_num {
-    ($name:ident, $read:ident, $bytes:expr, $data:expr) => {
+    ($name:ident, $read:ident, $bytes:expr, $data:expr) => (
         mod $name {
-            use byteorder::{
-                BigEndian, ByteOrder, LittleEndian, NativeEndian,
-            };
-            use test::black_box as bb;
-            use test::Bencher;
+            use byteorder::{ByteOrder, BigEndian, NativeEndian, LittleEndian};
+            use super::test::Bencher;
+            use super::test::black_box as bb;
 
             const NITER: usize = 100_000;
 
@@ -43,16 +43,14 @@ macro_rules! bench_num {
                 });
             }
         }
-    };
+    );
     ($ty:ident, $max:ident,
-     $read:ident, $write:ident, $size:expr, $data:expr) => {
+     $read:ident, $write:ident, $size:expr, $data:expr) => (
         mod $ty {
-            use byteorder::{
-                BigEndian, ByteOrder, LittleEndian, NativeEndian,
-            };
             use std::$ty;
-            use test::black_box as bb;
-            use test::Bencher;
+            use byteorder::{ByteOrder, BigEndian, NativeEndian, LittleEndian};
+            use super::test::Bencher;
+            use super::test::black_box as bb;
 
             const NITER: usize = 100_000;
 
@@ -119,7 +117,7 @@ macro_rules! bench_num {
                 });
             }
         }
-    };
+    );
 }
 
 bench_num!(u16, MAX, read_u16, write_u16, 2, [1, 2]);
@@ -129,7 +127,8 @@ bench_num!(i32, MAX, read_i32, write_i32, 4, [1, 2, 3, 4]);
 bench_num!(u64, MAX, read_u64, write_u64, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
 bench_num!(i64, MAX, read_i64, write_i64, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
 bench_num!(f32, MAX, read_f32, write_f32, 4, [1, 2, 3, 4]);
-bench_num!(f64, MAX, read_f64, write_f64, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
+bench_num!(f64, MAX, read_f64, write_f64, 8,
+           [1, 2, 3, 4, 5, 6, 7, 8]);
 
 bench_num!(uint_1, read_uint, 1, [1]);
 bench_num!(uint_2, read_uint, 2, [1, 2]);
@@ -149,115 +148,120 @@ bench_num!(int_6, read_int, 6, [1, 2, 3, 4, 5, 6]);
 bench_num!(int_7, read_int, 7, [1, 2, 3, 4, 5, 6, 7]);
 bench_num!(int_8, read_int, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
 
-bench_num!(
-    u128,
-    MAX,
-    read_u128,
-    write_u128,
-    16,
-    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
-);
-bench_num!(
-    i128,
-    MAX,
-    read_i128,
-    write_i128,
-    16,
-    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
-);
+#[cfg(byteorder_i128)]
+bench_num!(u128, MAX, read_u128, write_u128,
+    16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
+#[cfg(byteorder_i128)]
+bench_num!(i128, MAX, read_i128, write_i128,
+    16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
+
+#[cfg(byteorder_i128)]
+bench_num!(uint128_1, read_uint128,
+    1, [1]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_2, read_uint128,
+    2, [1, 2]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_3, read_uint128,
+    3, [1, 2, 3]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_4, read_uint128,
+    4, [1, 2, 3, 4]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_5, read_uint128,
+    5, [1, 2, 3, 4, 5]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_6, read_uint128,
+    6, [1, 2, 3, 4, 5, 6]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_7, read_uint128,
+    7, [1, 2, 3, 4, 5, 6, 7]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_8, read_uint128,
+    8, [1, 2, 3, 4, 5, 6, 7, 8]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_9, read_uint128,
+    9, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_10, read_uint128,
+    10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_11, read_uint128,
+    11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_12, read_uint128,
+    12, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_13, read_uint128,
+    13, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_14, read_uint128,
+    14, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_15, read_uint128,
+    15, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
+#[cfg(byteorder_i128)]
+bench_num!(uint128_16, read_uint128,
+    16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
 
-bench_num!(uint128_1, read_uint128, 1, [1]);
-bench_num!(uint128_2, read_uint128, 2, [1, 2]);
-bench_num!(uint128_3, read_uint128, 3, [1, 2, 3]);
-bench_num!(uint128_4, read_uint128, 4, [1, 2, 3, 4]);
-bench_num!(uint128_5, read_uint128, 5, [1, 2, 3, 4, 5]);
-bench_num!(uint128_6, read_uint128, 6, [1, 2, 3, 4, 5, 6]);
-bench_num!(uint128_7, read_uint128, 7, [1, 2, 3, 4, 5, 6, 7]);
-bench_num!(uint128_8, read_uint128, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
-bench_num!(uint128_9, read_uint128, 9, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
-bench_num!(uint128_10, read_uint128, 10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
-bench_num!(uint128_11, read_uint128, 11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
-bench_num!(
-    uint128_12,
-    read_uint128,
-    12,
-    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
-);
-bench_num!(
-    uint128_13,
-    read_uint128,
-    13,
-    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
-);
-bench_num!(
-    uint128_14,
-    read_uint128,
-    14,
-    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
-);
-bench_num!(
-    uint128_15,
-    read_uint128,
-    15,
-    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
-);
-bench_num!(
-    uint128_16,
-    read_uint128,
-    16,
-    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
-);
+#[cfg(byteorder_i128)]
+bench_num!(int128_1, read_int128,
+    1, [1]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_2, read_int128,
+    2, [1, 2]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_3, read_int128,
+    3, [1, 2, 3]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_4, read_int128,
+    4, [1, 2, 3, 4]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_5, read_int128,
+    5, [1, 2, 3, 4, 5]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_6, read_int128,
+    6, [1, 2, 3, 4, 5, 6]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_7, read_int128,
+    7, [1, 2, 3, 4, 5, 6, 7]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_8, read_int128,
+    8, [1, 2, 3, 4, 5, 6, 7, 8]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_9, read_int128,
+    9, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_10, read_int128,
+    10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_11, read_int128,
+    11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_12, read_int128,
+    12, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_13, read_int128,
+    13, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_14, read_int128,
+    14, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_15, read_int128,
+    15, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
+#[cfg(byteorder_i128)]
+bench_num!(int128_16, read_int128,
+    16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
 
-bench_num!(int128_1, read_int128, 1, [1]);
-bench_num!(int128_2, read_int128, 2, [1, 2]);
-bench_num!(int128_3, read_int128, 3, [1, 2, 3]);
-bench_num!(int128_4, read_int128, 4, [1, 2, 3, 4]);
-bench_num!(int128_5, read_int128, 5, [1, 2, 3, 4, 5]);
-bench_num!(int128_6, read_int128, 6, [1, 2, 3, 4, 5, 6]);
-bench_num!(int128_7, read_int128, 7, [1, 2, 3, 4, 5, 6, 7]);
-bench_num!(int128_8, read_int128, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
-bench_num!(int128_9, read_int128, 9, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
-bench_num!(int128_10, read_int128, 10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
-bench_num!(int128_11, read_int128, 11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
-bench_num!(
-    int128_12,
-    read_int128,
-    12,
-    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
-);
-bench_num!(
-    int128_13,
-    read_int128,
-    13,
-    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
-);
-bench_num!(
-    int128_14,
-    read_int128,
-    14,
-    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
-);
-bench_num!(
-    int128_15,
-    read_int128,
-    15,
-    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
-);
-bench_num!(
-    int128_16,
-    read_int128,
-    16,
-    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
-);
 
 macro_rules! bench_slice {
     ($name:ident, $numty:ty, $read:ident, $write:ident) => {
         mod $name {
             use std::mem::size_of;
 
-            use byteorder::{BigEndian, ByteOrder, LittleEndian};
-            use rand::distributions;
+            use byteorder::{ByteOrder, BigEndian, LittleEndian};
             use rand::{self, Rng};
+            use rand::distributions;
             use test::Bencher;
 
             #[bench]
@@ -318,7 +322,7 @@ macro_rules! bench_slice {
                 });
             }
         }
-    };
+    }
 }
 
 bench_slice!(slice_u64, u64, read_u64_into, write_u64_into);
diff --git a/vendor/byteorder/build.rs b/vendor/byteorder/build.rs
new file mode 100644 (file)
index 0000000..320e894
--- /dev/null
@@ -0,0 +1,90 @@
+// For the 'try!' macro, until we bump MSRV past 1.12.
+#![allow(deprecated)]
+
+use std::env;
+use std::ffi::OsString;
+use std::io::{self, Write};
+use std::process::Command;
+
+fn main() {
+    let version = match Version::read() {
+        Ok(version) => version,
+        Err(err) => {
+            writeln!(
+                &mut io::stderr(),
+                "failed to parse `rustc --version`: {}",
+                err
+            ).unwrap();
+            return;
+        }
+    };
+    enable_i128(version);
+}
+
+fn enable_i128(version: Version) {
+    if version < (Version { major: 1, minor: 26, patch: 0 }) {
+        return;
+    }
+
+    println!("cargo:rustc-cfg=byteorder_i128");
+}
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
+struct Version {
+    major: u32,
+    minor: u32,
+    patch: u32,
+}
+
+impl Version {
+    fn read() -> Result<Version, String> {
+        let rustc = env::var_os("RUSTC").unwrap_or(OsString::from("rustc"));
+        let output = Command::new(&rustc)
+            .arg("--version")
+            .output()
+            .unwrap()
+            .stdout;
+        Version::parse(&String::from_utf8(output).unwrap())
+    }
+
+    fn parse(mut s: &str) -> Result<Version, String> {
+        if !s.starts_with("rustc ") {
+            return Err(format!("unrecognized version string: {}", s));
+        }
+        s = &s["rustc ".len()..];
+
+        let parts: Vec<&str> = s.split(".").collect();
+        if parts.len() < 3 {
+            return Err(format!("not enough version parts: {:?}", parts));
+        }
+
+        let mut num = String::new();
+        for c in parts[0].chars() {
+            if !c.is_digit(10) {
+                break;
+            }
+            num.push(c);
+        }
+        let major = try!(num.parse::<u32>().map_err(|e| e.to_string()));
+
+        num.clear();
+        for c in parts[1].chars() {
+            if !c.is_digit(10) {
+                break;
+            }
+            num.push(c);
+        }
+        let minor = try!(num.parse::<u32>().map_err(|e| e.to_string()));
+
+        num.clear();
+        for c in parts[2].chars() {
+            if !c.is_digit(10) {
+                break;
+            }
+            num.push(c);
+        }
+        let patch = try!(num.parse::<u32>().map_err(|e| e.to_string()));
+
+        Ok(Version { major: major, minor: minor, patch: patch })
+    }
+}
diff --git a/vendor/byteorder/rustfmt.toml b/vendor/byteorder/rustfmt.toml
deleted file mode 100644 (file)
index aa37a21..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-max_width = 79
-use_small_heuristics = "max"
index dfad2ca39e9f619021c316bd885e788fa98a4e41..ed6a848451dec5731d54674b0c2117ed530a342b 100644 (file)
@@ -1,9 +1,7 @@
-use std::{
-    io::{self, Result},
-    slice,
-};
+use std::io::{self, Result};
+use std::slice;
 
-use crate::ByteOrder;
+use ByteOrder;
 
 /// Extends [`Read`] with methods for reading numbers. (For `std::io`.)
 ///
@@ -54,7 +52,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_u8(&mut self) -> Result<u8> {
         let mut buf = [0; 1];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(buf[0])
     }
 
@@ -84,7 +82,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_i8(&mut self) -> Result<i8> {
         let mut buf = [0; 1];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(buf[0] as i8)
     }
 
@@ -111,7 +109,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_u16<T: ByteOrder>(&mut self) -> Result<u16> {
         let mut buf = [0; 2];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(T::read_u16(&buf))
     }
 
@@ -138,7 +136,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_i16<T: ByteOrder>(&mut self) -> Result<i16> {
         let mut buf = [0; 2];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(T::read_i16(&buf))
     }
 
@@ -164,7 +162,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_u24<T: ByteOrder>(&mut self) -> Result<u32> {
         let mut buf = [0; 3];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(T::read_u24(&buf))
     }
 
@@ -190,7 +188,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_i24<T: ByteOrder>(&mut self) -> Result<i32> {
         let mut buf = [0; 3];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(T::read_i24(&buf))
     }
 
@@ -216,7 +214,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_u32<T: ByteOrder>(&mut self) -> Result<u32> {
         let mut buf = [0; 4];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(T::read_u32(&buf))
     }
 
@@ -242,7 +240,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_i32<T: ByteOrder>(&mut self) -> Result<i32> {
         let mut buf = [0; 4];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(T::read_i32(&buf))
     }
 
@@ -268,7 +266,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_u48<T: ByteOrder>(&mut self) -> Result<u64> {
         let mut buf = [0; 6];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(T::read_u48(&buf))
     }
 
@@ -294,7 +292,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_i48<T: ByteOrder>(&mut self) -> Result<i64> {
         let mut buf = [0; 6];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(T::read_i48(&buf))
     }
 
@@ -320,7 +318,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_u64<T: ByteOrder>(&mut self) -> Result<u64> {
         let mut buf = [0; 8];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(T::read_u64(&buf))
     }
 
@@ -346,7 +344,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_i64<T: ByteOrder>(&mut self) -> Result<i64> {
         let mut buf = [0; 8];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(T::read_i64(&buf))
     }
 
@@ -372,10 +370,11 @@ pub trait ReadBytesExt: io::Read {
     /// ]);
     /// assert_eq!(16947640962301618749969007319746179, rdr.read_u128::<BigEndian>().unwrap());
     /// ```
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_u128<T: ByteOrder>(&mut self) -> Result<u128> {
         let mut buf = [0; 16];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(T::read_u128(&buf))
     }
 
@@ -398,10 +397,11 @@ pub trait ReadBytesExt: io::Read {
     /// let mut rdr = Cursor::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
     /// assert_eq!(i128::min_value(), rdr.read_i128::<BigEndian>().unwrap());
     /// ```
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_i128<T: ByteOrder>(&mut self) -> Result<i128> {
         let mut buf = [0; 16];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(T::read_i128(&buf))
     }
 
@@ -426,7 +426,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_uint<T: ByteOrder>(&mut self, nbytes: usize) -> Result<u64> {
         let mut buf = [0; 8];
-        self.read_exact(&mut buf[..nbytes])?;
+        try!(self.read_exact(&mut buf[..nbytes]));
         Ok(T::read_uint(&buf[..nbytes], nbytes))
     }
 
@@ -451,23 +451,25 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_int<T: ByteOrder>(&mut self, nbytes: usize) -> Result<i64> {
         let mut buf = [0; 8];
-        self.read_exact(&mut buf[..nbytes])?;
+        try!(self.read_exact(&mut buf[..nbytes]));
         Ok(T::read_int(&buf[..nbytes], nbytes))
     }
 
     /// Reads an unsigned n-bytes integer from the underlying reader.
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_uint128<T: ByteOrder>(&mut self, nbytes: usize) -> Result<u128> {
         let mut buf = [0; 16];
-        self.read_exact(&mut buf[..nbytes])?;
+        try!(self.read_exact(&mut buf[..nbytes]));
         Ok(T::read_uint128(&buf[..nbytes], nbytes))
     }
 
     /// Reads a signed n-bytes integer from the underlying reader.
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_int128<T: ByteOrder>(&mut self, nbytes: usize) -> Result<i128> {
         let mut buf = [0; 16];
-        self.read_exact(&mut buf[..nbytes])?;
+        try!(self.read_exact(&mut buf[..nbytes]));
         Ok(T::read_int128(&buf[..nbytes], nbytes))
     }
 
@@ -498,7 +500,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_f32<T: ByteOrder>(&mut self) -> Result<f32> {
         let mut buf = [0; 4];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(T::read_f32(&buf))
     }
 
@@ -529,7 +531,7 @@ pub trait ReadBytesExt: io::Read {
     #[inline]
     fn read_f64<T: ByteOrder>(&mut self) -> Result<f64> {
         let mut buf = [0; 8];
-        self.read_exact(&mut buf)?;
+        try!(self.read_exact(&mut buf));
         Ok(T::read_f64(&buf))
     }
 
@@ -562,7 +564,7 @@ pub trait ReadBytesExt: io::Read {
     fn read_u16_into<T: ByteOrder>(&mut self, dst: &mut [u16]) -> Result<()> {
         {
             let buf = unsafe { slice_to_u8_mut(dst) };
-            self.read_exact(buf)?;
+            try!(self.read_exact(buf));
         }
         T::from_slice_u16(dst);
         Ok(())
@@ -597,7 +599,7 @@ pub trait ReadBytesExt: io::Read {
     fn read_u32_into<T: ByteOrder>(&mut self, dst: &mut [u32]) -> Result<()> {
         {
             let buf = unsafe { slice_to_u8_mut(dst) };
-            self.read_exact(buf)?;
+            try!(self.read_exact(buf));
         }
         T::from_slice_u32(dst);
         Ok(())
@@ -635,7 +637,7 @@ pub trait ReadBytesExt: io::Read {
     fn read_u64_into<T: ByteOrder>(&mut self, dst: &mut [u64]) -> Result<()> {
         {
             let buf = unsafe { slice_to_u8_mut(dst) };
-            self.read_exact(buf)?;
+            try!(self.read_exact(buf));
         }
         T::from_slice_u64(dst);
         Ok(())
@@ -669,6 +671,7 @@ pub trait ReadBytesExt: io::Read {
     /// rdr.read_u128_into::<BigEndian>(&mut dst).unwrap();
     /// assert_eq!([517, 768], dst);
     /// ```
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_u128_into<T: ByteOrder>(
         &mut self,
@@ -676,7 +679,7 @@ pub trait ReadBytesExt: io::Read {
     ) -> Result<()> {
         {
             let buf = unsafe { slice_to_u8_mut(dst) };
-            self.read_exact(buf)?;
+            try!(self.read_exact(buf));
         }
         T::from_slice_u128(dst);
         Ok(())
@@ -747,7 +750,7 @@ pub trait ReadBytesExt: io::Read {
     fn read_i16_into<T: ByteOrder>(&mut self, dst: &mut [i16]) -> Result<()> {
         {
             let buf = unsafe { slice_to_u8_mut(dst) };
-            self.read_exact(buf)?;
+            try!(self.read_exact(buf));
         }
         T::from_slice_i16(dst);
         Ok(())
@@ -782,7 +785,7 @@ pub trait ReadBytesExt: io::Read {
     fn read_i32_into<T: ByteOrder>(&mut self, dst: &mut [i32]) -> Result<()> {
         {
             let buf = unsafe { slice_to_u8_mut(dst) };
-            self.read_exact(buf)?;
+            try!(self.read_exact(buf));
         }
         T::from_slice_i32(dst);
         Ok(())
@@ -820,7 +823,7 @@ pub trait ReadBytesExt: io::Read {
     fn read_i64_into<T: ByteOrder>(&mut self, dst: &mut [i64]) -> Result<()> {
         {
             let buf = unsafe { slice_to_u8_mut(dst) };
-            self.read_exact(buf)?;
+            try!(self.read_exact(buf));
         }
         T::from_slice_i64(dst);
         Ok(())
@@ -854,6 +857,7 @@ pub trait ReadBytesExt: io::Read {
     /// rdr.read_i128_into::<BigEndian>(&mut dst).unwrap();
     /// assert_eq!([517, 768], dst);
     /// ```
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_i128_into<T: ByteOrder>(
         &mut self,
@@ -861,7 +865,7 @@ pub trait ReadBytesExt: io::Read {
     ) -> Result<()> {
         {
             let buf = unsafe { slice_to_u8_mut(dst) };
-            self.read_exact(buf)?;
+            try!(self.read_exact(buf));
         }
         T::from_slice_i128(dst);
         Ok(())
@@ -899,10 +903,13 @@ pub trait ReadBytesExt: io::Read {
     /// assert_eq!([f32::consts::PI, 1.0], dst);
     /// ```
     #[inline]
-    fn read_f32_into<T: ByteOrder>(&mut self, dst: &mut [f32]) -> Result<()> {
+    fn read_f32_into<T: ByteOrder>(
+        &mut self,
+        dst: &mut [f32],
+    ) -> Result<()> {
         {
             let buf = unsafe { slice_to_u8_mut(dst) };
-            self.read_exact(buf)?;
+            try!(self.read_exact(buf));
         }
         T::from_slice_f32(dst);
         Ok(())
@@ -944,7 +951,7 @@ pub trait ReadBytesExt: io::Read {
     /// assert_eq!([f32::consts::PI, 1.0], dst);
     /// ```
     #[inline]
-    #[deprecated(since = "1.2.0", note = "please use `read_f32_into` instead")]
+    #[deprecated(since="1.2.0", note="please use `read_f32_into` instead")]
     fn read_f32_into_unchecked<T: ByteOrder>(
         &mut self,
         dst: &mut [f32],
@@ -984,10 +991,13 @@ pub trait ReadBytesExt: io::Read {
     /// assert_eq!([f64::consts::PI, 1.0], dst);
     /// ```
     #[inline]
-    fn read_f64_into<T: ByteOrder>(&mut self, dst: &mut [f64]) -> Result<()> {
+    fn read_f64_into<T: ByteOrder>(
+        &mut self,
+        dst: &mut [f64],
+    ) -> Result<()> {
         {
             let buf = unsafe { slice_to_u8_mut(dst) };
-            self.read_exact(buf)?;
+            try!(self.read_exact(buf));
         }
         T::from_slice_f64(dst);
         Ok(())
@@ -1035,7 +1045,7 @@ pub trait ReadBytesExt: io::Read {
     /// assert_eq!([f64::consts::PI, 1.0], dst);
     /// ```
     #[inline]
-    #[deprecated(since = "1.2.0", note = "please use `read_f64_into` instead")]
+    #[deprecated(since="1.2.0", note="please use `read_f64_into` instead")]
     fn read_f64_into_unchecked<T: ByteOrder>(
         &mut self,
         dst: &mut [f64],
@@ -1398,6 +1408,7 @@ pub trait WriteBytesExt: io::Write {
     }
 
     /// Writes an unsigned 128 bit integer to the underlying writer.
+    #[cfg(byteorder_i128)]
     #[inline]
     fn write_u128<T: ByteOrder>(&mut self, n: u128) -> Result<()> {
         let mut buf = [0; 16];
@@ -1406,6 +1417,7 @@ pub trait WriteBytesExt: io::Write {
     }
 
     /// Writes a signed 128 bit integer to the underlying writer.
+    #[cfg(byteorder_i128)]
     #[inline]
     fn write_i128<T: ByteOrder>(&mut self, n: i128) -> Result<()> {
         let mut buf = [0; 16];
@@ -1489,6 +1501,7 @@ pub trait WriteBytesExt: io::Write {
     ///
     /// If the given integer is not representable in the given number of bytes,
     /// this method panics. If `nbytes > 16`, this method panics.
+    #[cfg(byteorder_i128)]
     #[inline]
     fn write_uint128<T: ByteOrder>(
         &mut self,
@@ -1504,6 +1517,7 @@ pub trait WriteBytesExt: io::Write {
     ///
     /// If the given integer is not representable in the given number of bytes,
     /// this method panics. If `nbytes > 16`, this method panics.
+    #[cfg(byteorder_i128)]
     #[inline]
     fn write_int128<T: ByteOrder>(
         &mut self,
@@ -1582,8 +1596,7 @@ impl<W: io::Write + ?Sized> WriteBytesExt for W {}
 /// representation.
 ///
 /// This function is wildly unsafe because it permits arbitrary modification of
-/// the binary representation of any `Copy` type. Use with care. It's intended
-/// to be called only where `T` is a numeric type.
+/// the binary representation of any `Copy` type. Use with care.
 unsafe fn slice_to_u8_mut<T: Copy>(slice: &mut [T]) -> &mut [u8] {
     use std::mem::size_of;
 
index cc37cca6aeeaac300d19d81c474ea4cc045f9502..5423ed1cff8187764386c4db106b46a9d19e33aa 100644 (file)
@@ -67,15 +67,29 @@ cases.
 [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
 */
 
+// For the 'try!' macro, until we bump MSRV past 1.12.
+#![allow(deprecated)]
+
 #![deny(missing_docs)]
 #![cfg_attr(not(feature = "std"), no_std)]
 
-use core::{
-    convert::TryInto, fmt::Debug, hash::Hash, ptr::copy_nonoverlapping, slice,
-};
+#[cfg(feature = "std")]
+extern crate core;
+
+#[cfg(test)]
+#[macro_use]
+extern crate doc_comment;
+
+#[cfg(test)]
+doctest!("../README.md");
+
+use core::fmt::Debug;
+use core::hash::Hash;
+use core::ptr::copy_nonoverlapping;
+use core::slice;
 
 #[cfg(feature = "std")]
-pub use crate::io::{ReadBytesExt, WriteBytesExt};
+pub use io::{ReadBytesExt, WriteBytesExt};
 
 #[cfg(feature = "std")]
 mod io;
@@ -86,6 +100,7 @@ fn extend_sign(val: u64, nbytes: usize) -> i64 {
     (val << shift) as i64 >> shift
 }
 
+#[cfg(byteorder_i128)]
 #[inline]
 fn extend_sign128(val: u128, nbytes: usize) -> i128 {
     let shift = (16 - nbytes) * 8;
@@ -98,6 +113,7 @@ fn unextend_sign(val: i64, nbytes: usize) -> u64 {
     (val << shift) as u64 >> shift
 }
 
+#[cfg(byteorder_i128)]
 #[inline]
 fn unextend_sign128(val: i128, nbytes: usize) -> u128 {
     let shift = (16 - nbytes) * 8;
@@ -125,6 +141,7 @@ fn pack_size(n: u64) -> usize {
     }
 }
 
+#[cfg(byteorder_i128)]
 #[inline]
 fn pack_size128(n: u128) -> usize {
     if n < 1 << 8 {
@@ -165,7 +182,7 @@ fn pack_size128(n: u128) -> usize {
 mod private {
     /// Sealed stops crates other than byteorder from implementing any traits
     /// that use it.
-    pub trait Sealed {}
+    pub trait Sealed{}
     impl Sealed for super::LittleEndian {}
     impl Sealed for super::BigEndian {}
 }
@@ -205,16 +222,8 @@ mod private {
 ///
 /// [`BigEndian`]: enum.BigEndian.html
 /// [`LittleEndian`]: enum.LittleEndian.html
-pub trait ByteOrder:
-    Clone
-    + Copy
-    + Debug
-    + Default
-    + Eq
-    + Hash
-    + Ord
-    + PartialEq
-    + PartialOrd
+pub trait ByteOrder
+    : Clone + Copy + Debug + Default + Eq + Hash + Ord + PartialEq + PartialOrd
     + private::Sealed
 {
     /// Reads an unsigned 16 bit integer from `buf`.
@@ -321,6 +330,7 @@ pub trait ByteOrder:
     /// LittleEndian::write_u128(&mut buf, 1_000_000);
     /// assert_eq!(1_000_000, LittleEndian::read_u128(&buf));
     /// ```
+    #[cfg(byteorder_i128)]
     fn read_u128(buf: &[u8]) -> u128;
 
     /// Reads an unsigned n-bytes integer from `buf`.
@@ -361,6 +371,7 @@ pub trait ByteOrder:
     /// LittleEndian::write_uint128(&mut buf, 1_000_000, 3);
     /// assert_eq!(1_000_000, LittleEndian::read_uint128(&buf, 3));
     /// ```
+    #[cfg(byteorder_i128)]
     fn read_uint128(buf: &[u8], nbytes: usize) -> u128;
 
     /// Writes an unsigned 16 bit integer `n` to `buf`.
@@ -479,6 +490,7 @@ pub trait ByteOrder:
     /// LittleEndian::write_u128(&mut buf, 1_000_000);
     /// assert_eq!(1_000_000, LittleEndian::read_u128(&buf));
     /// ```
+    #[cfg(byteorder_i128)]
     fn write_u128(buf: &mut [u8], n: u128);
 
     /// Writes an unsigned integer `n` to `buf` using only `nbytes`.
@@ -519,6 +531,7 @@ pub trait ByteOrder:
     /// LittleEndian::write_uint128(&mut buf, 1_000_000, 3);
     /// assert_eq!(1_000_000, LittleEndian::read_uint128(&buf, 3));
     /// ```
+    #[cfg(byteorder_i128)]
     fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize);
 
     /// Reads a signed 16 bit integer from `buf`.
@@ -648,6 +661,7 @@ pub trait ByteOrder:
     /// LittleEndian::write_i128(&mut buf, -1_000_000_000);
     /// assert_eq!(-1_000_000_000, LittleEndian::read_i128(&buf));
     /// ```
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_i128(buf: &[u8]) -> i128 {
         Self::read_u128(buf) as i128
@@ -694,6 +708,7 @@ pub trait ByteOrder:
     /// LittleEndian::write_int128(&mut buf, -1_000, 3);
     /// assert_eq!(-1_000, LittleEndian::read_int128(&buf, 3));
     /// ```
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_int128(buf: &[u8], nbytes: usize) -> i128 {
         extend_sign128(Self::read_uint128(buf, nbytes), nbytes)
@@ -719,7 +734,7 @@ pub trait ByteOrder:
     /// ```
     #[inline]
     fn read_f32(buf: &[u8]) -> f32 {
-        f32::from_bits(Self::read_u32(buf))
+        unsafe { *(&Self::read_u32(buf) as *const u32 as *const f32) }
     }
 
     /// Reads a IEEE754 double-precision (8 bytes) floating point number.
@@ -742,7 +757,7 @@ pub trait ByteOrder:
     /// ```
     #[inline]
     fn read_f64(buf: &[u8]) -> f64 {
-        f64::from_bits(Self::read_u64(buf))
+        unsafe { *(&Self::read_u64(buf) as *const u64 as *const f64) }
     }
 
     /// Writes a signed 16 bit integer `n` to `buf`.
@@ -872,6 +887,7 @@ pub trait ByteOrder:
     /// LittleEndian::write_i128(&mut buf, -1_000_000_000);
     /// assert_eq!(-1_000_000_000, LittleEndian::read_i128(&buf));
     /// ```
+    #[cfg(byteorder_i128)]
     #[inline]
     fn write_i128(buf: &mut [u8], n: i128) {
         Self::write_u128(buf, n as u128)
@@ -918,6 +934,7 @@ pub trait ByteOrder:
     /// LittleEndian::write_int128(&mut buf, -1_000, 3);
     /// assert_eq!(-1_000, LittleEndian::read_int128(&buf, 3));
     /// ```
+    #[cfg(byteorder_i128)]
     #[inline]
     fn write_int128(buf: &mut [u8], n: i128, nbytes: usize) {
         Self::write_uint128(buf, unextend_sign128(n, nbytes), nbytes)
@@ -943,7 +960,8 @@ pub trait ByteOrder:
     /// ```
     #[inline]
     fn write_f32(buf: &mut [u8], n: f32) {
-        Self::write_u32(buf, n.to_bits())
+        let n = unsafe { *(&n as *const f32 as *const u32) };
+        Self::write_u32(buf, n)
     }
 
     /// Writes a IEEE754 double-precision (8 bytes) floating point number.
@@ -966,7 +984,8 @@ pub trait ByteOrder:
     /// ```
     #[inline]
     fn write_f64(buf: &mut [u8], n: f64) {
-        Self::write_u64(buf, n.to_bits())
+        let n = unsafe { *(&n as *const f64 as *const u64) };
+        Self::write_u64(buf, n)
     }
 
     /// Reads unsigned 16 bit integers from `src` into `dst`.
@@ -1059,6 +1078,7 @@ pub trait ByteOrder:
     /// LittleEndian::read_u128_into(&bytes, &mut numbers_got);
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
+    #[cfg(byteorder_i128)]
     fn read_u128_into(src: &[u8], dst: &mut [u128]);
 
     /// Reads signed 16 bit integers from `src` to `dst`.
@@ -1169,6 +1189,7 @@ pub trait ByteOrder:
     /// LittleEndian::read_i128_into(&bytes, &mut numbers_got);
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_i128_into(src: &[u8], dst: &mut [i128]) {
         let dst = unsafe {
@@ -1233,7 +1254,7 @@ pub trait ByteOrder:
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     #[inline]
-    #[deprecated(since = "1.3.0", note = "please use `read_f32_into` instead")]
+    #[deprecated(since="1.3.0", note="please use `read_f32_into` instead")]
     fn read_f32_into_unchecked(src: &[u8], dst: &mut [f32]) {
         Self::read_f32_into(src, dst);
     }
@@ -1295,7 +1316,7 @@ pub trait ByteOrder:
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     #[inline]
-    #[deprecated(since = "1.3.0", note = "please use `read_f64_into` instead")]
+    #[deprecated(since="1.3.0", note="please use `read_f64_into` instead")]
     fn read_f64_into_unchecked(src: &[u8], dst: &mut [f64]) {
         Self::read_f64_into(src, dst);
     }
@@ -1390,6 +1411,7 @@ pub trait ByteOrder:
     /// LittleEndian::read_u128_into(&bytes, &mut numbers_got);
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
+    #[cfg(byteorder_i128)]
     fn write_u128_into(src: &[u128], dst: &mut [u8]);
 
     /// Writes signed 8 bit integers from `src` into `dst`.
@@ -1531,6 +1553,7 @@ pub trait ByteOrder:
     /// LittleEndian::read_i128_into(&bytes, &mut numbers_got);
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
+    #[cfg(byteorder_i128)]
     fn write_i128_into(src: &[i128], dst: &mut [u8]) {
         let src = unsafe {
             slice::from_raw_parts(src.as_ptr() as *const u128, src.len())
@@ -1557,7 +1580,9 @@ pub trait ByteOrder:
     /// LittleEndian::write_f32_into(&numbers_given, &mut bytes);
     ///
     /// let mut numbers_got = [0.0; 4];
-    /// LittleEndian::read_f32_into(&bytes, &mut numbers_got);
+    /// unsafe {
+    ///     LittleEndian::read_f32_into(&bytes, &mut numbers_got);
+    /// }
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     fn write_f32_into(src: &[f32], dst: &mut [u8]) {
@@ -1586,7 +1611,9 @@ pub trait ByteOrder:
     /// LittleEndian::write_f64_into(&numbers_given, &mut bytes);
     ///
     /// let mut numbers_got = [0.0; 4];
-    /// LittleEndian::read_f64_into(&bytes, &mut numbers_got);
+    /// unsafe {
+    ///     LittleEndian::read_f64_into(&bytes, &mut numbers_got);
+    /// }
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     fn write_f64_into(src: &[f64], dst: &mut [u8]) {
@@ -1670,6 +1697,7 @@ pub trait ByteOrder:
     /// BigEndian::from_slice_u128(&mut numbers);
     /// assert_eq!(numbers, [5u128.to_be(), 65000u128.to_be()]);
     /// ```
+    #[cfg(byteorder_i128)]
     fn from_slice_u128(numbers: &mut [u128]);
 
     /// Converts the given slice of signed 16 bit integers to a particular
@@ -1692,7 +1720,7 @@ pub trait ByteOrder:
     #[inline]
     fn from_slice_i16(src: &mut [i16]) {
         let src = unsafe {
-            slice::from_raw_parts_mut(src.as_mut_ptr() as *mut u16, src.len())
+            slice::from_raw_parts_mut(src.as_ptr() as *mut u16, src.len())
         };
         Self::from_slice_u16(src);
     }
@@ -1717,7 +1745,7 @@ pub trait ByteOrder:
     #[inline]
     fn from_slice_i32(src: &mut [i32]) {
         let src = unsafe {
-            slice::from_raw_parts_mut(src.as_mut_ptr() as *mut u32, src.len())
+            slice::from_raw_parts_mut(src.as_ptr() as *mut u32, src.len())
         };
         Self::from_slice_u32(src);
     }
@@ -1742,7 +1770,7 @@ pub trait ByteOrder:
     #[inline]
     fn from_slice_i64(src: &mut [i64]) {
         let src = unsafe {
-            slice::from_raw_parts_mut(src.as_mut_ptr() as *mut u64, src.len())
+            slice::from_raw_parts_mut(src.as_ptr() as *mut u64, src.len())
         };
         Self::from_slice_u64(src);
     }
@@ -1764,10 +1792,11 @@ pub trait ByteOrder:
     /// BigEndian::from_slice_i128(&mut numbers);
     /// assert_eq!(numbers, [5i128.to_be(), 65000i128.to_be()]);
     /// ```
+    #[cfg(byteorder_i128)]
     #[inline]
     fn from_slice_i128(src: &mut [i128]) {
         let src = unsafe {
-            slice::from_raw_parts_mut(src.as_mut_ptr() as *mut u128, src.len())
+            slice::from_raw_parts_mut(src.as_ptr() as *mut u128, src.len())
         };
         Self::from_slice_u128(src);
     }
@@ -1895,30 +1924,33 @@ pub type NativeEndian = LittleEndian;
 #[cfg(target_endian = "big")]
 pub type NativeEndian = BigEndian;
 
-/// Copies $size bytes from a number $n to a &mut [u8] $dst. $ty represents the
-/// numeric type of $n and $which must be either to_be or to_le, depending on
-/// which endianness one wants to use when writing to $dst.
-///
-/// This macro is only safe to call when $ty is a numeric type and $size ==
-/// size_of::<$ty>() and where $dst is a &mut [u8].
-macro_rules! unsafe_write_num_bytes {
-    ($ty:ty, $size:expr, $n:expr, $dst:expr, $which:ident) => {{
+macro_rules! read_num_bytes {
+    ($ty:ty, $size:expr, $src:expr, $which:ident) => ({
+        assert!($size == ::core::mem::size_of::<$ty>());
+        assert!($size <= $src.len());
+        let mut data: $ty = 0;
+        unsafe {
+            copy_nonoverlapping(
+                $src.as_ptr(),
+                &mut data as *mut $ty as *mut u8,
+                $size);
+        }
+        data.$which()
+    });
+}
+
+macro_rules! write_num_bytes {
+    ($ty:ty, $size:expr, $n:expr, $dst:expr, $which:ident) => ({
         assert!($size <= $dst.len());
         unsafe {
             // N.B. https://github.com/rust-lang/rust/issues/22776
             let bytes = *(&$n.$which() as *const _ as *const [u8; $size]);
             copy_nonoverlapping((&bytes).as_ptr(), $dst.as_mut_ptr(), $size);
         }
-    }};
+    });
 }
 
-/// Copies a &[u8] $src into a &mut [<numeric>] $dst for the endianness given
-/// by $which (must be either to_be or to_le).
-///
-/// This macro is only safe to call when $src and $dst are &[u8] and &mut [u8],
-/// respectively. The macro will panic if $src.len() != $size * $dst.len(),
-/// where $size represents the size of the integers encoded in $src.
-macro_rules! unsafe_read_slice {
+macro_rules! read_slice {
     ($src:expr, $dst:expr, $size:expr, $which:ident) => {{
         assert_eq!($src.len(), $size * $dst.len());
 
@@ -1926,8 +1958,7 @@ macro_rules! unsafe_read_slice {
             copy_nonoverlapping(
                 $src.as_ptr(),
                 $dst.as_mut_ptr() as *mut u8,
-                $src.len(),
-            );
+                $src.len());
         }
         for v in $dst.iter_mut() {
             *v = v.$which();
@@ -1935,57 +1966,51 @@ macro_rules! unsafe_read_slice {
     }};
 }
 
-/// Copies a &[$ty] $src into a &mut [u8] $dst, where $ty must be a numeric
-/// type. This panics if size_of::<$ty>() * $src.len() != $dst.len().
-///
-/// This macro is only safe to call when $src is a slice of numeric types and
-/// $dst is a &mut [u8] and where $ty represents the type of the integers in
-/// $src.
-macro_rules! unsafe_write_slice_native {
-    ($src:expr, $dst:expr, $ty:ty) => {{
-        let size = core::mem::size_of::<$ty>();
-        assert_eq!(size * $src.len(), $dst.len());
+macro_rules! write_slice_native {
+    ($src:expr, $dst:expr, $ty:ty, $size:expr) => {{
+        assert!($size == ::core::mem::size_of::<$ty>());
+        assert_eq!($size * $src.len(), $dst.len());
 
         unsafe {
             copy_nonoverlapping(
                 $src.as_ptr() as *const u8,
                 $dst.as_mut_ptr(),
-                $dst.len(),
-            );
+                $dst.len());
         }
     }};
 }
 
 macro_rules! write_slice {
-    ($src:expr, $dst:expr, $ty:ty, $size:expr, $write:expr) => {{
+    ($src:expr, $dst:expr, $ty:ty, $size:expr, $write:expr) => ({
         assert!($size == ::core::mem::size_of::<$ty>());
         assert_eq!($size * $src.len(), $dst.len());
 
         for (&n, chunk) in $src.iter().zip($dst.chunks_mut($size)) {
             $write(chunk, n);
         }
-    }};
+    });
 }
 
 impl ByteOrder for BigEndian {
     #[inline]
     fn read_u16(buf: &[u8]) -> u16 {
-        u16::from_be_bytes(buf[..2].try_into().unwrap())
+        read_num_bytes!(u16, 2, buf, to_be)
     }
 
     #[inline]
     fn read_u32(buf: &[u8]) -> u32 {
-        u32::from_be_bytes(buf[..4].try_into().unwrap())
+        read_num_bytes!(u32, 4, buf, to_be)
     }
 
     #[inline]
     fn read_u64(buf: &[u8]) -> u64 {
-        u64::from_be_bytes(buf[..8].try_into().unwrap())
+        read_num_bytes!(u64, 8, buf, to_be)
     }
 
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_u128(buf: &[u8]) -> u128 {
-        u128::from_be_bytes(buf[..16].try_into().unwrap())
+        read_num_bytes!(u128, 16, buf, to_be)
     }
 
     #[inline]
@@ -1995,14 +2020,12 @@ impl ByteOrder for BigEndian {
         let ptr_out = &mut out as *mut u64 as *mut u8;
         unsafe {
             copy_nonoverlapping(
-                buf.as_ptr(),
-                ptr_out.offset((8 - nbytes) as isize),
-                nbytes,
-            );
+                buf.as_ptr(), ptr_out.offset((8 - nbytes) as isize), nbytes);
         }
         out.to_be()
     }
 
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_uint128(buf: &[u8], nbytes: usize) -> u128 {
         assert!(1 <= nbytes && nbytes <= 16 && nbytes <= buf.len());
@@ -2010,32 +2033,30 @@ impl ByteOrder for BigEndian {
         let ptr_out = &mut out as *mut u128 as *mut u8;
         unsafe {
             copy_nonoverlapping(
-                buf.as_ptr(),
-                ptr_out.offset((16 - nbytes) as isize),
-                nbytes,
-            );
+                buf.as_ptr(), ptr_out.offset((16 - nbytes) as isize), nbytes);
         }
         out.to_be()
     }
 
     #[inline]
     fn write_u16(buf: &mut [u8], n: u16) {
-        unsafe_write_num_bytes!(u16, 2, n, buf, to_be);
+        write_num_bytes!(u16, 2, n, buf, to_be);
     }
 
     #[inline]
     fn write_u32(buf: &mut [u8], n: u32) {
-        unsafe_write_num_bytes!(u32, 4, n, buf, to_be);
+        write_num_bytes!(u32, 4, n, buf, to_be);
     }
 
     #[inline]
     fn write_u64(buf: &mut [u8], n: u64) {
-        unsafe_write_num_bytes!(u64, 8, n, buf, to_be);
+        write_num_bytes!(u64, 8, n, buf, to_be);
     }
 
+    #[cfg(byteorder_i128)]
     #[inline]
     fn write_u128(buf: &mut [u8], n: u128) {
-        unsafe_write_num_bytes!(u128, 16, n, buf, to_be);
+        write_num_bytes!(u128, 16, n, buf, to_be);
     }
 
     #[inline]
@@ -2047,11 +2068,11 @@ impl ByteOrder for BigEndian {
             copy_nonoverlapping(
                 bytes.as_ptr().offset((8 - nbytes) as isize),
                 buf.as_mut_ptr(),
-                nbytes,
-            );
+                nbytes);
         }
     }
 
+    #[cfg(byteorder_i128)]
     #[inline]
     fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize) {
         assert!(pack_size128(n) <= nbytes && nbytes <= 16);
@@ -2061,35 +2082,35 @@ impl ByteOrder for BigEndian {
             copy_nonoverlapping(
                 bytes.as_ptr().offset((16 - nbytes) as isize),
                 buf.as_mut_ptr(),
-                nbytes,
-            );
+                nbytes);
         }
     }
 
     #[inline]
     fn read_u16_into(src: &[u8], dst: &mut [u16]) {
-        unsafe_read_slice!(src, dst, 2, to_be);
+        read_slice!(src, dst, 2, to_be);
     }
 
     #[inline]
     fn read_u32_into(src: &[u8], dst: &mut [u32]) {
-        unsafe_read_slice!(src, dst, 4, to_be);
+        read_slice!(src, dst, 4, to_be);
     }
 
     #[inline]
     fn read_u64_into(src: &[u8], dst: &mut [u64]) {
-        unsafe_read_slice!(src, dst, 8, to_be);
+        read_slice!(src, dst, 8, to_be);
     }
 
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_u128_into(src: &[u8], dst: &mut [u128]) {
-        unsafe_read_slice!(src, dst, 16, to_be);
+        read_slice!(src, dst, 16, to_be);
     }
 
     #[inline]
     fn write_u16_into(src: &[u16], dst: &mut [u8]) {
         if cfg!(target_endian = "big") {
-            unsafe_write_slice_native!(src, dst, u16);
+            write_slice_native!(src, dst, u16, 2);
         } else {
             write_slice!(src, dst, u16, 2, Self::write_u16);
         }
@@ -2098,7 +2119,7 @@ impl ByteOrder for BigEndian {
     #[inline]
     fn write_u32_into(src: &[u32], dst: &mut [u8]) {
         if cfg!(target_endian = "big") {
-            unsafe_write_slice_native!(src, dst, u32);
+            write_slice_native!(src, dst, u32, 4);
         } else {
             write_slice!(src, dst, u32, 4, Self::write_u32);
         }
@@ -2107,16 +2128,17 @@ impl ByteOrder for BigEndian {
     #[inline]
     fn write_u64_into(src: &[u64], dst: &mut [u8]) {
         if cfg!(target_endian = "big") {
-            unsafe_write_slice_native!(src, dst, u64);
+            write_slice_native!(src, dst, u64, 8);
         } else {
             write_slice!(src, dst, u64, 8, Self::write_u64);
         }
     }
 
+    #[cfg(byteorder_i128)]
     #[inline]
     fn write_u128_into(src: &[u128], dst: &mut [u8]) {
         if cfg!(target_endian = "big") {
-            unsafe_write_slice_native!(src, dst, u128);
+            write_slice_native!(src, dst, u128, 16);
         } else {
             write_slice!(src, dst, u128, 16, Self::write_u128);
         }
@@ -2149,6 +2171,7 @@ impl ByteOrder for BigEndian {
         }
     }
 
+    #[cfg(byteorder_i128)]
     #[inline]
     fn from_slice_u128(numbers: &mut [u128]) {
         if cfg!(target_endian = "little") {
@@ -2186,22 +2209,23 @@ impl ByteOrder for BigEndian {
 impl ByteOrder for LittleEndian {
     #[inline]
     fn read_u16(buf: &[u8]) -> u16 {
-        u16::from_le_bytes(buf[..2].try_into().unwrap())
+        read_num_bytes!(u16, 2, buf, to_le)
     }
 
     #[inline]
     fn read_u32(buf: &[u8]) -> u32 {
-        u32::from_le_bytes(buf[..4].try_into().unwrap())
+        read_num_bytes!(u32, 4, buf, to_le)
     }
 
     #[inline]
     fn read_u64(buf: &[u8]) -> u64 {
-        u64::from_le_bytes(buf[..8].try_into().unwrap())
+        read_num_bytes!(u64, 8, buf, to_le)
     }
 
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_u128(buf: &[u8]) -> u128 {
-        u128::from_le_bytes(buf[..16].try_into().unwrap())
+        read_num_bytes!(u128, 16, buf, to_le)
     }
 
     #[inline]
@@ -2215,6 +2239,7 @@ impl ByteOrder for LittleEndian {
         out.to_le()
     }
 
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_uint128(buf: &[u8], nbytes: usize) -> u128 {
         assert!(1 <= nbytes && nbytes <= 16 && nbytes <= buf.len());
@@ -2228,22 +2253,23 @@ impl ByteOrder for LittleEndian {
 
     #[inline]
     fn write_u16(buf: &mut [u8], n: u16) {
-        unsafe_write_num_bytes!(u16, 2, n, buf, to_le);
+        write_num_bytes!(u16, 2, n, buf, to_le);
     }
 
     #[inline]
     fn write_u32(buf: &mut [u8], n: u32) {
-        unsafe_write_num_bytes!(u32, 4, n, buf, to_le);
+        write_num_bytes!(u32, 4, n, buf, to_le);
     }
 
     #[inline]
     fn write_u64(buf: &mut [u8], n: u64) {
-        unsafe_write_num_bytes!(u64, 8, n, buf, to_le);
+        write_num_bytes!(u64, 8, n, buf, to_le);
     }
 
+    #[cfg(byteorder_i128)]
     #[inline]
     fn write_u128(buf: &mut [u8], n: u128) {
-        unsafe_write_num_bytes!(u128, 16, n, buf, to_le);
+        write_num_bytes!(u128, 16, n, buf, to_le);
     }
 
     #[inline]
@@ -2256,6 +2282,7 @@ impl ByteOrder for LittleEndian {
         }
     }
 
+    #[cfg(byteorder_i128)]
     #[inline]
     fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize) {
         assert!(pack_size128(n as u128) <= nbytes && nbytes <= 16);
@@ -2268,28 +2295,29 @@ impl ByteOrder for LittleEndian {
 
     #[inline]
     fn read_u16_into(src: &[u8], dst: &mut [u16]) {
-        unsafe_read_slice!(src, dst, 2, to_le);
+        read_slice!(src, dst, 2, to_le);
     }
 
     #[inline]
     fn read_u32_into(src: &[u8], dst: &mut [u32]) {
-        unsafe_read_slice!(src, dst, 4, to_le);
+        read_slice!(src, dst, 4, to_le);
     }
 
     #[inline]
     fn read_u64_into(src: &[u8], dst: &mut [u64]) {
-        unsafe_read_slice!(src, dst, 8, to_le);
+        read_slice!(src, dst, 8, to_le);
     }
 
+    #[cfg(byteorder_i128)]
     #[inline]
     fn read_u128_into(src: &[u8], dst: &mut [u128]) {
-        unsafe_read_slice!(src, dst, 16, to_le);
+        read_slice!(src, dst, 16, to_le);
     }
 
     #[inline]
     fn write_u16_into(src: &[u16], dst: &mut [u8]) {
         if cfg!(target_endian = "little") {
-            unsafe_write_slice_native!(src, dst, u16);
+            write_slice_native!(src, dst, u16, 2);
         } else {
             write_slice!(src, dst, u16, 2, Self::write_u16);
         }
@@ -2298,7 +2326,7 @@ impl ByteOrder for LittleEndian {
     #[inline]
     fn write_u32_into(src: &[u32], dst: &mut [u8]) {
         if cfg!(target_endian = "little") {
-            unsafe_write_slice_native!(src, dst, u32);
+            write_slice_native!(src, dst, u32, 4);
         } else {
             write_slice!(src, dst, u32, 4, Self::write_u32);
         }
@@ -2307,16 +2335,17 @@ impl ByteOrder for LittleEndian {
     #[inline]
     fn write_u64_into(src: &[u64], dst: &mut [u8]) {
         if cfg!(target_endian = "little") {
-            unsafe_write_slice_native!(src, dst, u64);
+            write_slice_native!(src, dst, u64, 8);
         } else {
             write_slice!(src, dst, u64, 8, Self::write_u64);
         }
     }
 
+    #[cfg(byteorder_i128)]
     #[inline]
     fn write_u128_into(src: &[u128], dst: &mut [u8]) {
         if cfg!(target_endian = "little") {
-            unsafe_write_slice_native!(src, dst, u128);
+            write_slice_native!(src, dst, u128, 16);
         } else {
             write_slice!(src, dst, u128, 16, Self::write_u128);
         }
@@ -2349,6 +2378,7 @@ impl ByteOrder for LittleEndian {
         }
     }
 
+    #[cfg(byteorder_i128)]
     #[inline]
     fn from_slice_u128(numbers: &mut [u128]) {
         if cfg!(target_endian = "big") {
@@ -2385,8 +2415,15 @@ impl ByteOrder for LittleEndian {
 
 #[cfg(test)]
 mod test {
-    use quickcheck::{Arbitrary, Gen, QuickCheck, StdGen, Testable};
-    use rand::{thread_rng, Rng};
+    extern crate quickcheck;
+    extern crate rand;
+
+    use self::quickcheck::{QuickCheck, StdGen, Testable};
+    use self::rand::thread_rng;
+    #[cfg(byteorder_i128)]
+    use self::rand::Rng;
+    #[cfg(byteorder_i128)]
+    use self::quickcheck::{Arbitrary, Gen};
 
     pub const U24_MAX: u32 = 16_777_215;
     pub const I24_MAX: i32 = 8_388_607;
@@ -2397,9 +2434,7 @@ mod test {
     pub const I64_MAX: u64 = ::core::i64::MAX as u64;
 
     macro_rules! calc_max {
-        ($max:expr, $bytes:expr) => {
-            calc_max!($max, $bytes, 8)
-        };
+        ($max:expr, $bytes:expr) => { calc_max!($max, $bytes, 8) };
         ($max:expr, $bytes:expr, $maxbytes:expr) => {
             ($max - 1) >> (8 * ($maxbytes - $bytes))
         };
@@ -2408,6 +2443,7 @@ mod test {
     #[derive(Clone, Debug)]
     pub struct Wi128<T>(pub T);
 
+    #[cfg(byteorder_i128)]
     impl<T: Clone> Wi128<T> {
         pub fn clone(&self) -> T {
             self.0.clone()
@@ -2420,20 +2456,24 @@ mod test {
         }
     }
 
+    #[cfg(byteorder_i128)]
     impl Arbitrary for Wi128<u128> {
         fn arbitrary<G: Gen>(gen: &mut G) -> Wi128<u128> {
             let max = calc_max!(::core::u128::MAX, gen.size(), 16);
-            let output = (gen.gen::<u64>() as u128)
-                | ((gen.gen::<u64>() as u128) << 64);
+            let output =
+                (gen.gen::<u64>() as u128) |
+                ((gen.gen::<u64>() as u128) << 64);
             Wi128(output & (max - 1))
         }
     }
 
+    #[cfg(byteorder_i128)]
     impl Arbitrary for Wi128<i128> {
         fn arbitrary<G: Gen>(gen: &mut G) -> Wi128<i128> {
             let max = calc_max!(::core::i128::MAX, gen.size(), 16);
-            let output = (gen.gen::<i64>() as i128)
-                | ((gen.gen::<i64>() as i128) << 64);
+            let output =
+                (gen.gen::<i64>() as i128) |
+                ((gen.gen::<i64>() as i128) << 64);
             Wi128(output & (max - 1))
         }
     }
@@ -2448,13 +2488,10 @@ mod test {
 
     macro_rules! qc_byte_order {
         ($name:ident, $ty_int:ty, $max:expr,
-         $bytes:expr, $read:ident, $write:ident) => {
+         $bytes:expr, $read:ident, $write:ident) => (
             mod $name {
-                #[allow(unused_imports)]
-                use super::{qc_sized, Wi128};
-                use crate::{
-                    BigEndian, ByteOrder, LittleEndian, NativeEndian,
-                };
+                use {BigEndian, ByteOrder, NativeEndian, LittleEndian};
+                #[allow(unused_imports)] use super::{ qc_sized, Wi128 };
 
                 #[test]
                 fn big_endian() {
@@ -2486,16 +2523,13 @@ mod test {
                     qc_sized(prop as fn($ty_int) -> bool, $max);
                 }
             }
-        };
+        );
         ($name:ident, $ty_int:ty, $max:expr,
-         $read:ident, $write:ident) => {
+         $read:ident, $write:ident) => (
             mod $name {
-                #[allow(unused_imports)]
-                use super::{qc_sized, Wi128};
-                use crate::{
-                    BigEndian, ByteOrder, LittleEndian, NativeEndian,
-                };
                 use core::mem::size_of;
+                use {BigEndian, ByteOrder, NativeEndian, LittleEndian};
+                #[allow(unused_imports)] use super::{ qc_sized, Wi128 };
 
                 #[test]
                 fn big_endian() {
@@ -2530,484 +2564,159 @@ mod test {
                     qc_sized(prop as fn($ty_int) -> bool, $max - 1);
                 }
             }
-        };
-    }
-
-    qc_byte_order!(
-        prop_u16,
-        u16,
-        ::core::u16::MAX as u64,
-        read_u16,
-        write_u16
-    );
-    qc_byte_order!(
-        prop_i16,
-        i16,
-        ::core::i16::MAX as u64,
-        read_i16,
-        write_i16
-    );
-    qc_byte_order!(
-        prop_u24,
-        u32,
-        crate::test::U24_MAX as u64,
-        read_u24,
-        write_u24
-    );
-    qc_byte_order!(
-        prop_i24,
-        i32,
-        crate::test::I24_MAX as u64,
-        read_i24,
-        write_i24
-    );
-    qc_byte_order!(
-        prop_u32,
-        u32,
-        ::core::u32::MAX as u64,
-        read_u32,
-        write_u32
-    );
-    qc_byte_order!(
-        prop_i32,
-        i32,
-        ::core::i32::MAX as u64,
-        read_i32,
-        write_i32
-    );
-    qc_byte_order!(
-        prop_u48,
-        u64,
-        crate::test::U48_MAX as u64,
-        read_u48,
-        write_u48
-    );
-    qc_byte_order!(
-        prop_i48,
-        i64,
-        crate::test::I48_MAX as u64,
-        read_i48,
-        write_i48
-    );
-    qc_byte_order!(
-        prop_u64,
-        u64,
-        ::core::u64::MAX as u64,
-        read_u64,
-        write_u64
-    );
-    qc_byte_order!(
-        prop_i64,
-        i64,
-        ::core::i64::MAX as u64,
-        read_i64,
-        write_i64
-    );
-    qc_byte_order!(
-        prop_f32,
-        f32,
-        ::core::u64::MAX as u64,
-        read_f32,
-        write_f32
-    );
-    qc_byte_order!(
-        prop_f64,
-        f64,
-        ::core::i64::MAX as u64,
-        read_f64,
-        write_f64
-    );
-
+        );
+    }
+
+    qc_byte_order!(prop_u16, u16, ::core::u16::MAX as u64, read_u16, write_u16);
+    qc_byte_order!(prop_i16, i16, ::core::i16::MAX as u64, read_i16, write_i16);
+    qc_byte_order!(prop_u24, u32, ::test::U24_MAX as u64, read_u24, write_u24);
+    qc_byte_order!(prop_i24, i32, ::test::I24_MAX as u64, read_i24, write_i24);
+    qc_byte_order!(prop_u32, u32, ::core::u32::MAX as u64, read_u32, write_u32);
+    qc_byte_order!(prop_i32, i32, ::core::i32::MAX as u64, read_i32, write_i32);
+    qc_byte_order!(prop_u48, u64, ::test::U48_MAX as u64, read_u48, write_u48);
+    qc_byte_order!(prop_i48, i64, ::test::I48_MAX as u64, read_i48, write_i48);
+    qc_byte_order!(prop_u64, u64, ::core::u64::MAX as u64, read_u64, write_u64);
+    qc_byte_order!(prop_i64, i64, ::core::i64::MAX as u64, read_i64, write_i64);
+    qc_byte_order!(prop_f32, f32, ::core::u64::MAX as u64, read_f32, write_f32);
+    qc_byte_order!(prop_f64, f64, ::core::i64::MAX as u64, read_f64, write_f64);
+
+    #[cfg(byteorder_i128)]
     qc_byte_order!(prop_u128, Wi128<u128>, 16 + 1, read_u128, write_u128);
+    #[cfg(byteorder_i128)]
     qc_byte_order!(prop_i128, Wi128<i128>, 16 + 1, read_i128, write_i128);
 
-    qc_byte_order!(
-        prop_uint_1,
-        u64,
-        calc_max!(super::U64_MAX, 1),
-        1,
-        read_uint,
-        write_uint
-    );
-    qc_byte_order!(
-        prop_uint_2,
-        u64,
-        calc_max!(super::U64_MAX, 2),
-        2,
-        read_uint,
-        write_uint
-    );
-    qc_byte_order!(
-        prop_uint_3,
-        u64,
-        calc_max!(super::U64_MAX, 3),
-        3,
-        read_uint,
-        write_uint
-    );
-    qc_byte_order!(
-        prop_uint_4,
-        u64,
-        calc_max!(super::U64_MAX, 4),
-        4,
-        read_uint,
-        write_uint
-    );
-    qc_byte_order!(
-        prop_uint_5,
-        u64,
-        calc_max!(super::U64_MAX, 5),
-        5,
-        read_uint,
-        write_uint
-    );
-    qc_byte_order!(
-        prop_uint_6,
-        u64,
-        calc_max!(super::U64_MAX, 6),
-        6,
-        read_uint,
-        write_uint
-    );
-    qc_byte_order!(
-        prop_uint_7,
-        u64,
-        calc_max!(super::U64_MAX, 7),
-        7,
-        read_uint,
-        write_uint
-    );
-    qc_byte_order!(
-        prop_uint_8,
-        u64,
-        calc_max!(super::U64_MAX, 8),
-        8,
-        read_uint,
-        write_uint
-    );
-
-    qc_byte_order!(
-        prop_uint128_1,
-        Wi128<u128>,
-        1,
-        1,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_2,
-        Wi128<u128>,
-        2,
-        2,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_3,
-        Wi128<u128>,
-        3,
-        3,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_4,
-        Wi128<u128>,
-        4,
-        4,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_5,
-        Wi128<u128>,
-        5,
-        5,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_6,
-        Wi128<u128>,
-        6,
-        6,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_7,
-        Wi128<u128>,
-        7,
-        7,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_8,
-        Wi128<u128>,
-        8,
-        8,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_9,
-        Wi128<u128>,
-        9,
-        9,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_10,
-        Wi128<u128>,
-        10,
-        10,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_11,
-        Wi128<u128>,
-        11,
-        11,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_12,
-        Wi128<u128>,
-        12,
-        12,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_13,
-        Wi128<u128>,
-        13,
-        13,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_14,
-        Wi128<u128>,
-        14,
-        14,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_15,
-        Wi128<u128>,
-        15,
-        15,
-        read_uint128,
-        write_uint128
-    );
-    qc_byte_order!(
-        prop_uint128_16,
-        Wi128<u128>,
-        16,
-        16,
-        read_uint128,
-        write_uint128
-    );
-
-    qc_byte_order!(
-        prop_int_1,
-        i64,
-        calc_max!(super::I64_MAX, 1),
-        1,
-        read_int,
-        write_int
-    );
-    qc_byte_order!(
-        prop_int_2,
-        i64,
-        calc_max!(super::I64_MAX, 2),
-        2,
-        read_int,
-        write_int
-    );
-    qc_byte_order!(
-        prop_int_3,
-        i64,
-        calc_max!(super::I64_MAX, 3),
-        3,
-        read_int,
-        write_int
-    );
-    qc_byte_order!(
-        prop_int_4,
-        i64,
-        calc_max!(super::I64_MAX, 4),
-        4,
-        read_int,
-        write_int
-    );
-    qc_byte_order!(
-        prop_int_5,
-        i64,
-        calc_max!(super::I64_MAX, 5),
-        5,
-        read_int,
-        write_int
-    );
-    qc_byte_order!(
-        prop_int_6,
-        i64,
-        calc_max!(super::I64_MAX, 6),
-        6,
-        read_int,
-        write_int
-    );
-    qc_byte_order!(
-        prop_int_7,
-        i64,
-        calc_max!(super::I64_MAX, 7),
-        7,
-        read_int,
-        write_int
-    );
-    qc_byte_order!(
-        prop_int_8,
-        i64,
-        calc_max!(super::I64_MAX, 8),
-        8,
-        read_int,
-        write_int
-    );
-
-    qc_byte_order!(
-        prop_int128_1,
-        Wi128<i128>,
-        1,
-        1,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_2,
-        Wi128<i128>,
-        2,
-        2,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_3,
-        Wi128<i128>,
-        3,
-        3,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_4,
-        Wi128<i128>,
-        4,
-        4,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_5,
-        Wi128<i128>,
-        5,
-        5,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_6,
-        Wi128<i128>,
-        6,
-        6,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_7,
-        Wi128<i128>,
-        7,
-        7,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_8,
-        Wi128<i128>,
-        8,
-        8,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_9,
-        Wi128<i128>,
-        9,
-        9,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_10,
-        Wi128<i128>,
-        10,
-        10,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_11,
-        Wi128<i128>,
-        11,
-        11,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_12,
-        Wi128<i128>,
-        12,
-        12,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_13,
-        Wi128<i128>,
-        13,
-        13,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_14,
-        Wi128<i128>,
-        14,
-        14,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_15,
-        Wi128<i128>,
-        15,
-        15,
-        read_int128,
-        write_int128
-    );
-    qc_byte_order!(
-        prop_int128_16,
-        Wi128<i128>,
-        16,
-        16,
-        read_int128,
-        write_int128
-    );
+    qc_byte_order!(prop_uint_1,
+        u64, calc_max!(super::U64_MAX, 1), 1, read_uint, write_uint);
+    qc_byte_order!(prop_uint_2,
+        u64, calc_max!(super::U64_MAX, 2), 2, read_uint, write_uint);
+    qc_byte_order!(prop_uint_3,
+        u64, calc_max!(super::U64_MAX, 3), 3, read_uint, write_uint);
+    qc_byte_order!(prop_uint_4,
+        u64, calc_max!(super::U64_MAX, 4), 4, read_uint, write_uint);
+    qc_byte_order!(prop_uint_5,
+        u64, calc_max!(super::U64_MAX, 5), 5, read_uint, write_uint);
+    qc_byte_order!(prop_uint_6,
+        u64, calc_max!(super::U64_MAX, 6), 6, read_uint, write_uint);
+    qc_byte_order!(prop_uint_7,
+        u64, calc_max!(super::U64_MAX, 7), 7, read_uint, write_uint);
+    qc_byte_order!(prop_uint_8,
+        u64, calc_max!(super::U64_MAX, 8), 8, read_uint, write_uint);
+
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_1,
+        Wi128<u128>, 1, 1, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_2,
+        Wi128<u128>, 2, 2, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_3,
+        Wi128<u128>, 3, 3, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_4,
+        Wi128<u128>, 4, 4, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_5,
+        Wi128<u128>, 5, 5, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_6,
+        Wi128<u128>, 6, 6, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_7,
+        Wi128<u128>, 7, 7, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_8,
+        Wi128<u128>, 8, 8, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_9,
+        Wi128<u128>, 9, 9, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_10,
+        Wi128<u128>, 10, 10, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_11,
+        Wi128<u128>, 11, 11, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_12,
+        Wi128<u128>, 12, 12, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_13,
+        Wi128<u128>, 13, 13, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_14,
+        Wi128<u128>, 14, 14, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_15,
+        Wi128<u128>, 15, 15, read_uint128, write_uint128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_uint128_16,
+        Wi128<u128>, 16, 16, read_uint128, write_uint128);
+
+    qc_byte_order!(prop_int_1,
+        i64, calc_max!(super::I64_MAX, 1), 1, read_int, write_int);
+    qc_byte_order!(prop_int_2,
+        i64, calc_max!(super::I64_MAX, 2), 2, read_int, write_int);
+    qc_byte_order!(prop_int_3,
+        i64, calc_max!(super::I64_MAX, 3), 3, read_int, write_int);
+    qc_byte_order!(prop_int_4,
+        i64, calc_max!(super::I64_MAX, 4), 4, read_int, write_int);
+    qc_byte_order!(prop_int_5,
+        i64, calc_max!(super::I64_MAX, 5), 5, read_int, write_int);
+    qc_byte_order!(prop_int_6,
+        i64, calc_max!(super::I64_MAX, 6), 6, read_int, write_int);
+    qc_byte_order!(prop_int_7,
+        i64, calc_max!(super::I64_MAX, 7), 7, read_int, write_int);
+    qc_byte_order!(prop_int_8,
+        i64, calc_max!(super::I64_MAX, 8), 8, read_int, write_int);
+
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_1,
+        Wi128<i128>, 1, 1, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_2,
+        Wi128<i128>, 2, 2, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_3,
+        Wi128<i128>, 3, 3, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_4,
+        Wi128<i128>, 4, 4, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_5,
+        Wi128<i128>, 5, 5, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_6,
+        Wi128<i128>, 6, 6, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_7,
+        Wi128<i128>, 7, 7, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_8,
+        Wi128<i128>, 8, 8, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_9,
+        Wi128<i128>, 9, 9, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_10,
+        Wi128<i128>, 10, 10, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_11,
+        Wi128<i128>, 11, 11, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_12,
+        Wi128<i128>, 12, 12, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_13,
+        Wi128<i128>, 13, 13, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_14,
+        Wi128<i128>, 14, 14, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_15,
+        Wi128<i128>, 15, 15, read_int128, write_int128);
+    #[cfg(byteorder_i128)]
+    qc_byte_order!(prop_int128_16,
+        Wi128<i128>, 16, 16, read_int128, write_int128);
+
 
     // Test that all of the byte conversion functions panic when given a
     // buffer that is too small.
@@ -3016,11 +2725,9 @@ mod test {
     // with a buffer overflow.
     macro_rules! too_small {
         ($name:ident, $maximally_small:expr, $zero:expr,
-         $read:ident, $write:ident) => {
+         $read:ident, $write:ident) => (
             mod $name {
-                use crate::{
-                    BigEndian, ByteOrder, LittleEndian, NativeEndian,
-                };
+                use {BigEndian, ByteOrder, NativeEndian, LittleEndian};
 
                 #[test]
                 #[should_panic]
@@ -3064,12 +2771,10 @@ mod test {
                     NativeEndian::$write(&mut buf, $zero);
                 }
             }
-        };
-        ($name:ident, $maximally_small:expr, $read:ident) => {
+        );
+        ($name:ident, $maximally_small:expr, $read:ident) => (
             mod $name {
-                use crate::{
-                    BigEndian, ByteOrder, LittleEndian, NativeEndian,
-                };
+                use {BigEndian, ByteOrder, NativeEndian, LittleEndian};
 
                 #[test]
                 #[should_panic]
@@ -3092,7 +2797,7 @@ mod test {
                     NativeEndian::$read(&buf, $maximally_small + 1);
                 }
             }
-        };
+        );
     }
 
     too_small!(small_u16, 1, 0, read_u16, write_u16);
@@ -3103,7 +2808,9 @@ mod test {
     too_small!(small_i64, 7, 0, read_i64, write_i64);
     too_small!(small_f32, 3, 0.0, read_f32, write_f32);
     too_small!(small_f64, 7, 0.0, read_f64, write_f64);
+    #[cfg(byteorder_i128)]
     too_small!(small_u128, 15, 0, read_u128, write_u128);
+    #[cfg(byteorder_i128)]
     too_small!(small_i128, 15, 0, read_i128, write_i128);
 
     too_small!(small_uint_1, 1, read_uint);
@@ -3114,20 +2821,35 @@ mod test {
     too_small!(small_uint_6, 6, read_uint);
     too_small!(small_uint_7, 7, read_uint);
 
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_1, 1, read_uint128);
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_2, 2, read_uint128);
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_3, 3, read_uint128);
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_4, 4, read_uint128);
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_5, 5, read_uint128);
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_6, 6, read_uint128);
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_7, 7, read_uint128);
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_8, 8, read_uint128);
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_9, 9, read_uint128);
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_10, 10, read_uint128);
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_11, 11, read_uint128);
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_12, 12, read_uint128);
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_13, 13, read_uint128);
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_14, 14, read_uint128);
+    #[cfg(byteorder_i128)]
     too_small!(small_uint128_15, 15, read_uint128);
 
     too_small!(small_int_1, 1, read_int);
@@ -3138,20 +2860,35 @@ mod test {
     too_small!(small_int_6, 6, read_int);
     too_small!(small_int_7, 7, read_int);
 
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_1, 1, read_int128);
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_2, 2, read_int128);
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_3, 3, read_int128);
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_4, 4, read_int128);
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_5, 5, read_int128);
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_6, 6, read_int128);
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_7, 7, read_int128);
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_8, 8, read_int128);
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_9, 9, read_int128);
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_10, 10, read_int128);
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_11, 11, read_int128);
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_12, 12, read_int128);
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_13, 13, read_int128);
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_14, 14, read_int128);
+    #[cfg(byteorder_i128)]
     too_small!(small_int128_15, 15, read_int128);
 
     // Test that reading/writing slices enforces the correct lengths.
@@ -3159,9 +2896,7 @@ mod test {
         ($name:ident, $read:ident, $write:ident,
          $num_bytes:expr, $numbers:expr) => {
             mod $name {
-                use crate::{
-                    BigEndian, ByteOrder, LittleEndian, NativeEndian,
-                };
+                use {ByteOrder, BigEndian, NativeEndian, LittleEndian};
 
                 #[test]
                 #[should_panic]
@@ -3211,172 +2946,55 @@ mod test {
                     NativeEndian::$write(&numbers, &mut bytes);
                 }
             }
-        };
+        }
     }
 
     slice_lengths!(
-        slice_len_too_small_u16,
-        read_u16_into,
-        write_u16_into,
-        3,
-        [0, 0]
-    );
+        slice_len_too_small_u16, read_u16_into, write_u16_into, 3, [0, 0]);
     slice_lengths!(
-        slice_len_too_big_u16,
-        read_u16_into,
-        write_u16_into,
-        5,
-        [0, 0]
-    );
+        slice_len_too_big_u16, read_u16_into, write_u16_into, 5, [0, 0]);
     slice_lengths!(
-        slice_len_too_small_i16,
-        read_i16_into,
-        write_i16_into,
-        3,
-        [0, 0]
-    );
+        slice_len_too_small_i16, read_i16_into, write_i16_into, 3, [0, 0]);
     slice_lengths!(
-        slice_len_too_big_i16,
-        read_i16_into,
-        write_i16_into,
-        5,
-        [0, 0]
-    );
+        slice_len_too_big_i16, read_i16_into, write_i16_into, 5, [0, 0]);
 
     slice_lengths!(
-        slice_len_too_small_u32,
-        read_u32_into,
-        write_u32_into,
-        7,
-        [0, 0]
-    );
+        slice_len_too_small_u32, read_u32_into, write_u32_into, 7, [0, 0]);
     slice_lengths!(
-        slice_len_too_big_u32,
-        read_u32_into,
-        write_u32_into,
-        9,
-        [0, 0]
-    );
+        slice_len_too_big_u32, read_u32_into, write_u32_into, 9, [0, 0]);
     slice_lengths!(
-        slice_len_too_small_i32,
-        read_i32_into,
-        write_i32_into,
-        7,
-        [0, 0]
-    );
+        slice_len_too_small_i32, read_i32_into, write_i32_into, 7, [0, 0]);
     slice_lengths!(
-        slice_len_too_big_i32,
-        read_i32_into,
-        write_i32_into,
-        9,
-        [0, 0]
-    );
+        slice_len_too_big_i32, read_i32_into, write_i32_into, 9, [0, 0]);
 
     slice_lengths!(
-        slice_len_too_small_u64,
-        read_u64_into,
-        write_u64_into,
-        15,
-        [0, 0]
-    );
+        slice_len_too_small_u64, read_u64_into, write_u64_into, 15, [0, 0]);
     slice_lengths!(
-        slice_len_too_big_u64,
-        read_u64_into,
-        write_u64_into,
-        17,
-        [0, 0]
-    );
+        slice_len_too_big_u64, read_u64_into, write_u64_into, 17, [0, 0]);
     slice_lengths!(
-        slice_len_too_small_i64,
-        read_i64_into,
-        write_i64_into,
-        15,
-        [0, 0]
-    );
+        slice_len_too_small_i64, read_i64_into, write_i64_into, 15, [0, 0]);
     slice_lengths!(
-        slice_len_too_big_i64,
-        read_i64_into,
-        write_i64_into,
-        17,
-        [0, 0]
-    );
+        slice_len_too_big_i64, read_i64_into, write_i64_into, 17, [0, 0]);
 
+    #[cfg(byteorder_i128)]
     slice_lengths!(
-        slice_len_too_small_u128,
-        read_u128_into,
-        write_u128_into,
-        31,
-        [0, 0]
-    );
+        slice_len_too_small_u128, read_u128_into, write_u128_into, 31, [0, 0]);
+    #[cfg(byteorder_i128)]
     slice_lengths!(
-        slice_len_too_big_u128,
-        read_u128_into,
-        write_u128_into,
-        33,
-        [0, 0]
-    );
+        slice_len_too_big_u128, read_u128_into, write_u128_into, 33, [0, 0]);
+    #[cfg(byteorder_i128)]
     slice_lengths!(
-        slice_len_too_small_i128,
-        read_i128_into,
-        write_i128_into,
-        31,
-        [0, 0]
-    );
+        slice_len_too_small_i128, read_i128_into, write_i128_into, 31, [0, 0]);
+    #[cfg(byteorder_i128)]
     slice_lengths!(
-        slice_len_too_big_i128,
-        read_i128_into,
-        write_i128_into,
-        33,
-        [0, 0]
-    );
+        slice_len_too_big_i128, read_i128_into, write_i128_into, 33, [0, 0]);
 
     #[test]
     fn uint_bigger_buffer() {
-        use crate::{ByteOrder, LittleEndian};
+        use {ByteOrder, LittleEndian};
         let n = LittleEndian::read_uint(&[1, 2, 3, 4, 5, 6, 7, 8], 5);
         assert_eq!(n, 0x05_0403_0201);
     }
-
-    #[test]
-    fn regression173_array_impl() {
-        use crate::{BigEndian, ByteOrder, LittleEndian};
-
-        let xs = [0; 100];
-
-        let x = BigEndian::read_u16(&xs);
-        assert_eq!(x, 0);
-        let x = BigEndian::read_u32(&xs);
-        assert_eq!(x, 0);
-        let x = BigEndian::read_u64(&xs);
-        assert_eq!(x, 0);
-        let x = BigEndian::read_u128(&xs);
-        assert_eq!(x, 0);
-        let x = BigEndian::read_i16(&xs);
-        assert_eq!(x, 0);
-        let x = BigEndian::read_i32(&xs);
-        assert_eq!(x, 0);
-        let x = BigEndian::read_i64(&xs);
-        assert_eq!(x, 0);
-        let x = BigEndian::read_i128(&xs);
-        assert_eq!(x, 0);
-
-        let x = LittleEndian::read_u16(&xs);
-        assert_eq!(x, 0);
-        let x = LittleEndian::read_u32(&xs);
-        assert_eq!(x, 0);
-        let x = LittleEndian::read_u64(&xs);
-        assert_eq!(x, 0);
-        let x = LittleEndian::read_u128(&xs);
-        assert_eq!(x, 0);
-        let x = LittleEndian::read_i16(&xs);
-        assert_eq!(x, 0);
-        let x = LittleEndian::read_i32(&xs);
-        assert_eq!(x, 0);
-        let x = LittleEndian::read_i64(&xs);
-        assert_eq!(x, 0);
-        let x = LittleEndian::read_i128(&xs);
-        assert_eq!(x, 0);
-    }
 }
 
 #[cfg(test)]
@@ -3389,6 +3007,7 @@ mod stdtests {
     use self::rand::thread_rng;
 
     fn qc_unsized<A: Testable>(f: A) {
+
         QuickCheck::new()
             .gen(StdGen::new(thread_rng(), 16))
             .tests(1_00)
@@ -3397,22 +3016,19 @@ mod stdtests {
     }
 
     macro_rules! calc_max {
-        ($max:expr, $bytes:expr) => {
-            ($max - 1) >> (8 * (8 - $bytes))
-        };
+        ($max:expr, $bytes:expr) => { ($max - 1) >> (8 * (8 - $bytes)) };
     }
 
     macro_rules! qc_bytes_ext {
         ($name:ident, $ty_int:ty, $max:expr,
-         $bytes:expr, $read:ident, $write:ident) => {
+         $bytes:expr, $read:ident, $write:ident) => (
             mod $name {
-                #[allow(unused_imports)]
-                use crate::test::{qc_sized, Wi128};
-                use crate::{
-                    BigEndian, LittleEndian, NativeEndian, ReadBytesExt,
-                    WriteBytesExt,
-                };
                 use std::io::Cursor;
+                use {
+                    ReadBytesExt, WriteBytesExt,
+                    BigEndian, NativeEndian, LittleEndian,
+                };
+                #[allow(unused_imports)] use test::{qc_sized, Wi128};
 
                 #[test]
                 fn big_endian() {
@@ -3453,16 +3069,15 @@ mod stdtests {
                     qc_sized(prop as fn($ty_int) -> bool, $max);
                 }
             }
-        };
-        ($name:ident, $ty_int:ty, $max:expr, $read:ident, $write:ident) => {
+        );
+        ($name:ident, $ty_int:ty, $max:expr, $read:ident, $write:ident) => (
             mod $name {
-                #[allow(unused_imports)]
-                use crate::test::{qc_sized, Wi128};
-                use crate::{
-                    BigEndian, LittleEndian, NativeEndian, ReadBytesExt,
-                    WriteBytesExt,
-                };
                 use std::io::Cursor;
+                use {
+                    ReadBytesExt, WriteBytesExt,
+                    BigEndian, NativeEndian, LittleEndian,
+                };
+                #[allow(unused_imports)] use test::{qc_sized, Wi128};
 
                 #[test]
                 fn big_endian() {
@@ -3497,484 +3112,188 @@ mod stdtests {
                     qc_sized(prop as fn($ty_int) -> bool, $max - 1);
                 }
             }
-        };
-    }
-
-    qc_bytes_ext!(
-        prop_ext_u16,
-        u16,
-        ::std::u16::MAX as u64,
-        read_u16,
-        write_u16
-    );
-    qc_bytes_ext!(
-        prop_ext_i16,
-        i16,
-        ::std::i16::MAX as u64,
-        read_i16,
-        write_i16
-    );
-    qc_bytes_ext!(
-        prop_ext_u32,
-        u32,
-        ::std::u32::MAX as u64,
-        read_u32,
-        write_u32
-    );
-    qc_bytes_ext!(
-        prop_ext_i32,
-        i32,
-        ::std::i32::MAX as u64,
-        read_i32,
-        write_i32
-    );
-    qc_bytes_ext!(
-        prop_ext_u64,
-        u64,
-        ::std::u64::MAX as u64,
-        read_u64,
-        write_u64
-    );
-    qc_bytes_ext!(
-        prop_ext_i64,
-        i64,
-        ::std::i64::MAX as u64,
-        read_i64,
-        write_i64
-    );
-    qc_bytes_ext!(
-        prop_ext_f32,
-        f32,
-        ::std::u64::MAX as u64,
-        read_f32,
-        write_f32
-    );
-    qc_bytes_ext!(
-        prop_ext_f64,
-        f64,
-        ::std::i64::MAX as u64,
-        read_f64,
-        write_f64
-    );
-
+        );
+    }
+
+    qc_bytes_ext!(prop_ext_u16,
+        u16, ::std::u16::MAX as u64, read_u16, write_u16);
+    qc_bytes_ext!(prop_ext_i16,
+        i16, ::std::i16::MAX as u64, read_i16, write_i16);
+    qc_bytes_ext!(prop_ext_u32,
+        u32, ::std::u32::MAX as u64, read_u32, write_u32);
+    qc_bytes_ext!(prop_ext_i32,
+        i32, ::std::i32::MAX as u64, read_i32, write_i32);
+    qc_bytes_ext!(prop_ext_u64,
+        u64, ::std::u64::MAX as u64, read_u64, write_u64);
+    qc_bytes_ext!(prop_ext_i64,
+        i64, ::std::i64::MAX as u64, read_i64, write_i64);
+    qc_bytes_ext!(prop_ext_f32,
+        f32, ::std::u64::MAX as u64, read_f32, write_f32);
+    qc_bytes_ext!(prop_ext_f64,
+        f64, ::std::i64::MAX as u64, read_f64, write_f64);
+
+    #[cfg(byteorder_i128)]
     qc_bytes_ext!(prop_ext_u128, Wi128<u128>, 16 + 1, read_u128, write_u128);
+    #[cfg(byteorder_i128)]
     qc_bytes_ext!(prop_ext_i128, Wi128<i128>, 16 + 1, read_i128, write_i128);
 
-    qc_bytes_ext!(
-        prop_ext_uint_1,
-        u64,
-        calc_max!(crate::test::U64_MAX, 1),
-        1,
-        read_uint,
-        write_u64
-    );
-    qc_bytes_ext!(
-        prop_ext_uint_2,
-        u64,
-        calc_max!(crate::test::U64_MAX, 2),
-        2,
-        read_uint,
-        write_u64
-    );
-    qc_bytes_ext!(
-        prop_ext_uint_3,
-        u64,
-        calc_max!(crate::test::U64_MAX, 3),
-        3,
-        read_uint,
-        write_u64
-    );
-    qc_bytes_ext!(
-        prop_ext_uint_4,
-        u64,
-        calc_max!(crate::test::U64_MAX, 4),
-        4,
-        read_uint,
-        write_u64
-    );
-    qc_bytes_ext!(
-        prop_ext_uint_5,
-        u64,
-        calc_max!(crate::test::U64_MAX, 5),
-        5,
-        read_uint,
-        write_u64
-    );
-    qc_bytes_ext!(
-        prop_ext_uint_6,
-        u64,
-        calc_max!(crate::test::U64_MAX, 6),
-        6,
-        read_uint,
-        write_u64
-    );
-    qc_bytes_ext!(
-        prop_ext_uint_7,
-        u64,
-        calc_max!(crate::test::U64_MAX, 7),
-        7,
-        read_uint,
-        write_u64
-    );
-    qc_bytes_ext!(
-        prop_ext_uint_8,
-        u64,
-        calc_max!(crate::test::U64_MAX, 8),
-        8,
-        read_uint,
-        write_u64
-    );
-
-    qc_bytes_ext!(
-        prop_ext_uint128_1,
-        Wi128<u128>,
-        1,
-        1,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_2,
-        Wi128<u128>,
-        2,
-        2,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_3,
-        Wi128<u128>,
-        3,
-        3,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_4,
-        Wi128<u128>,
-        4,
-        4,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_5,
-        Wi128<u128>,
-        5,
-        5,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_6,
-        Wi128<u128>,
-        6,
-        6,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_7,
-        Wi128<u128>,
-        7,
-        7,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_8,
-        Wi128<u128>,
-        8,
-        8,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_9,
-        Wi128<u128>,
-        9,
-        9,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_10,
-        Wi128<u128>,
-        10,
-        10,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_11,
-        Wi128<u128>,
-        11,
-        11,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_12,
-        Wi128<u128>,
-        12,
-        12,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_13,
-        Wi128<u128>,
-        13,
-        13,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_14,
-        Wi128<u128>,
-        14,
-        14,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_15,
-        Wi128<u128>,
-        15,
-        15,
-        read_uint128,
-        write_u128
-    );
-    qc_bytes_ext!(
-        prop_ext_uint128_16,
-        Wi128<u128>,
-        16,
-        16,
-        read_uint128,
-        write_u128
-    );
-
-    qc_bytes_ext!(
-        prop_ext_int_1,
-        i64,
-        calc_max!(crate::test::I64_MAX, 1),
-        1,
-        read_int,
-        write_i64
-    );
-    qc_bytes_ext!(
-        prop_ext_int_2,
-        i64,
-        calc_max!(crate::test::I64_MAX, 2),
-        2,
-        read_int,
-        write_i64
-    );
-    qc_bytes_ext!(
-        prop_ext_int_3,
-        i64,
-        calc_max!(crate::test::I64_MAX, 3),
-        3,
-        read_int,
-        write_i64
-    );
-    qc_bytes_ext!(
-        prop_ext_int_4,
-        i64,
-        calc_max!(crate::test::I64_MAX, 4),
-        4,
-        read_int,
-        write_i64
-    );
-    qc_bytes_ext!(
-        prop_ext_int_5,
-        i64,
-        calc_max!(crate::test::I64_MAX, 5),
-        5,
-        read_int,
-        write_i64
-    );
-    qc_bytes_ext!(
-        prop_ext_int_6,
-        i64,
-        calc_max!(crate::test::I64_MAX, 6),
-        6,
-        read_int,
-        write_i64
-    );
-    qc_bytes_ext!(
-        prop_ext_int_7,
-        i64,
-        calc_max!(crate::test::I64_MAX, 1),
-        7,
-        read_int,
-        write_i64
-    );
-    qc_bytes_ext!(
-        prop_ext_int_8,
-        i64,
-        calc_max!(crate::test::I64_MAX, 8),
-        8,
-        read_int,
-        write_i64
-    );
-
-    qc_bytes_ext!(
-        prop_ext_int128_1,
-        Wi128<i128>,
-        1,
-        1,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_2,
-        Wi128<i128>,
-        2,
-        2,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_3,
-        Wi128<i128>,
-        3,
-        3,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_4,
-        Wi128<i128>,
-        4,
-        4,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_5,
-        Wi128<i128>,
-        5,
-        5,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_6,
-        Wi128<i128>,
-        6,
-        6,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_7,
-        Wi128<i128>,
-        7,
-        7,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_8,
-        Wi128<i128>,
-        8,
-        8,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_9,
-        Wi128<i128>,
-        9,
-        9,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_10,
-        Wi128<i128>,
-        10,
-        10,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_11,
-        Wi128<i128>,
-        11,
-        11,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_12,
-        Wi128<i128>,
-        12,
-        12,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_13,
-        Wi128<i128>,
-        13,
-        13,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_14,
-        Wi128<i128>,
-        14,
-        14,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_15,
-        Wi128<i128>,
-        15,
-        15,
-        read_int128,
-        write_i128
-    );
-    qc_bytes_ext!(
-        prop_ext_int128_16,
-        Wi128<i128>,
-        16,
-        16,
-        read_int128,
-        write_i128
-    );
+    qc_bytes_ext!(prop_ext_uint_1,
+        u64, calc_max!(::test::U64_MAX, 1), 1, read_uint, write_u64);
+    qc_bytes_ext!(prop_ext_uint_2,
+        u64, calc_max!(::test::U64_MAX, 2), 2, read_uint, write_u64);
+    qc_bytes_ext!(prop_ext_uint_3,
+        u64, calc_max!(::test::U64_MAX, 3), 3, read_uint, write_u64);
+    qc_bytes_ext!(prop_ext_uint_4,
+        u64, calc_max!(::test::U64_MAX, 4), 4, read_uint, write_u64);
+    qc_bytes_ext!(prop_ext_uint_5,
+        u64, calc_max!(::test::U64_MAX, 5), 5, read_uint, write_u64);
+    qc_bytes_ext!(prop_ext_uint_6,
+        u64, calc_max!(::test::U64_MAX, 6), 6, read_uint, write_u64);
+    qc_bytes_ext!(prop_ext_uint_7,
+        u64, calc_max!(::test::U64_MAX, 7), 7, read_uint, write_u64);
+    qc_bytes_ext!(prop_ext_uint_8,
+        u64, calc_max!(::test::U64_MAX, 8), 8, read_uint, write_u64);
+
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_1,
+        Wi128<u128>, 1, 1, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_2,
+        Wi128<u128>, 2, 2, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_3,
+        Wi128<u128>, 3, 3, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_4,
+        Wi128<u128>, 4, 4, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_5,
+        Wi128<u128>, 5, 5, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_6,
+        Wi128<u128>, 6, 6, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_7,
+        Wi128<u128>, 7, 7, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_8,
+        Wi128<u128>, 8, 8, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_9,
+        Wi128<u128>, 9, 9, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_10,
+        Wi128<u128>, 10, 10, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_11,
+        Wi128<u128>, 11, 11, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_12,
+        Wi128<u128>, 12, 12, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_13,
+        Wi128<u128>, 13, 13, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_14,
+        Wi128<u128>, 14, 14, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_15,
+        Wi128<u128>, 15, 15, read_uint128, write_u128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_uint128_16,
+        Wi128<u128>, 16, 16, read_uint128, write_u128);
+
+    qc_bytes_ext!(prop_ext_int_1,
+        i64, calc_max!(::test::I64_MAX, 1), 1, read_int, write_i64);
+    qc_bytes_ext!(prop_ext_int_2,
+        i64, calc_max!(::test::I64_MAX, 2), 2, read_int, write_i64);
+    qc_bytes_ext!(prop_ext_int_3,
+        i64, calc_max!(::test::I64_MAX, 3), 3, read_int, write_i64);
+    qc_bytes_ext!(prop_ext_int_4,
+        i64, calc_max!(::test::I64_MAX, 4), 4, read_int, write_i64);
+    qc_bytes_ext!(prop_ext_int_5,
+        i64, calc_max!(::test::I64_MAX, 5), 5, read_int, write_i64);
+    qc_bytes_ext!(prop_ext_int_6,
+        i64, calc_max!(::test::I64_MAX, 6), 6, read_int, write_i64);
+    qc_bytes_ext!(prop_ext_int_7,
+        i64, calc_max!(::test::I64_MAX, 1), 7, read_int, write_i64);
+    qc_bytes_ext!(prop_ext_int_8,
+        i64, calc_max!(::test::I64_MAX, 8), 8, read_int, write_i64);
+
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_1,
+        Wi128<i128>, 1, 1, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_2,
+        Wi128<i128>, 2, 2, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_3,
+        Wi128<i128>, 3, 3, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_4,
+        Wi128<i128>, 4, 4, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_5,
+        Wi128<i128>, 5, 5, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_6,
+        Wi128<i128>, 6, 6, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_7,
+        Wi128<i128>, 7, 7, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_8,
+        Wi128<i128>, 8, 8, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_9,
+        Wi128<i128>, 9, 9, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_10,
+        Wi128<i128>, 10, 10, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_11,
+        Wi128<i128>, 11, 11, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_12,
+        Wi128<i128>, 12, 12, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_13,
+        Wi128<i128>, 13, 13, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_14,
+        Wi128<i128>, 14, 14, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_15,
+        Wi128<i128>, 15, 15, read_int128, write_i128);
+    #[cfg(byteorder_i128)]
+    qc_bytes_ext!(prop_ext_int128_16,
+        Wi128<i128>, 16, 16, read_int128, write_i128);
 
     // Test slice serialization/deserialization.
     macro_rules! qc_slice {
         ($name:ident, $ty_int:ty, $read:ident, $write:ident, $zero:expr) => {
             mod $name {
+                use core::mem::size_of;
+                use {ByteOrder, BigEndian, NativeEndian, LittleEndian};
                 use super::qc_unsized;
                 #[allow(unused_imports)]
-                use crate::test::Wi128;
-                use crate::{
-                    BigEndian, ByteOrder, LittleEndian, NativeEndian,
-                };
-                use core::mem::size_of;
+                use test::Wi128;
 
                 #[test]
                 fn big_endian() {
                     #[allow(unused_unsafe)]
                     fn prop(numbers: Vec<$ty_int>) -> bool {
-                        let numbers: Vec<_> =
-                            numbers.into_iter().map(|x| x.clone()).collect();
+                        let numbers: Vec<_> = numbers
+                            .into_iter()
+                            .map(|x| x.clone())
+                            .collect();
                         let num_bytes = size_of::<$ty_int>() * numbers.len();
                         let mut bytes = vec![0; num_bytes];
 
                         BigEndian::$write(&numbers, &mut bytes);
 
                         let mut got = vec![$zero; numbers.len()];
-                        unsafe {
-                            BigEndian::$read(&bytes, &mut got);
-                        }
+                        unsafe { BigEndian::$read(&bytes, &mut got); }
 
                         numbers == got
                     }
@@ -3985,17 +3304,17 @@ mod stdtests {
                 fn little_endian() {
                     #[allow(unused_unsafe)]
                     fn prop(numbers: Vec<$ty_int>) -> bool {
-                        let numbers: Vec<_> =
-                            numbers.into_iter().map(|x| x.clone()).collect();
+                        let numbers: Vec<_> = numbers
+                            .into_iter()
+                            .map(|x| x.clone())
+                            .collect();
                         let num_bytes = size_of::<$ty_int>() * numbers.len();
                         let mut bytes = vec![0; num_bytes];
 
                         LittleEndian::$write(&numbers, &mut bytes);
 
                         let mut got = vec![$zero; numbers.len()];
-                        unsafe {
-                            LittleEndian::$read(&bytes, &mut got);
-                        }
+                        unsafe { LittleEndian::$read(&bytes, &mut got); }
 
                         numbers == got
                     }
@@ -4006,24 +3325,24 @@ mod stdtests {
                 fn native_endian() {
                     #[allow(unused_unsafe)]
                     fn prop(numbers: Vec<$ty_int>) -> bool {
-                        let numbers: Vec<_> =
-                            numbers.into_iter().map(|x| x.clone()).collect();
+                        let numbers: Vec<_> = numbers
+                            .into_iter()
+                            .map(|x| x.clone())
+                            .collect();
                         let num_bytes = size_of::<$ty_int>() * numbers.len();
                         let mut bytes = vec![0; num_bytes];
 
                         NativeEndian::$write(&numbers, &mut bytes);
 
                         let mut got = vec![$zero; numbers.len()];
-                        unsafe {
-                            NativeEndian::$read(&bytes, &mut got);
-                        }
+                        unsafe { NativeEndian::$read(&bytes, &mut got); }
 
                         numbers == got
                     }
                     qc_unsized(prop as fn(_) -> bool);
                 }
             }
-        };
+        }
     }
 
     qc_slice!(prop_slice_u16, u16, read_u16_into, write_u16_into, 0);
@@ -4032,21 +3351,15 @@ mod stdtests {
     qc_slice!(prop_slice_i32, i32, read_i32_into, write_i32_into, 0);
     qc_slice!(prop_slice_u64, u64, read_u64_into, write_u64_into, 0);
     qc_slice!(prop_slice_i64, i64, read_i64_into, write_i64_into, 0);
+    #[cfg(byteorder_i128)]
+    qc_slice!(
+        prop_slice_u128, Wi128<u128>, read_u128_into, write_u128_into, 0);
+    #[cfg(byteorder_i128)]
+    qc_slice!(
+        prop_slice_i128, Wi128<i128>, read_i128_into, write_i128_into, 0);
+
     qc_slice!(
-        prop_slice_u128,
-        Wi128<u128>,
-        read_u128_into,
-        write_u128_into,
-        0
-    );
+        prop_slice_f32, f32, read_f32_into, write_f32_into, 0.0);
     qc_slice!(
-        prop_slice_i128,
-        Wi128<i128>,
-        read_i128_into,
-        write_i128_into,
-        0
-    );
-
-    qc_slice!(prop_slice_f32, f32, read_f32_into, write_f32_into, 0.0);
-    qc_slice!(prop_slice_f64, f64, read_f64_into, write_f64_into, 0.0);
+        prop_slice_f64, f64, read_f64_into, write_f64_into, 0.0);
 }
diff --git a/vendor/cargo_metadata-0.11.1/.cargo-checksum.json b/vendor/cargo_metadata-0.11.1/.cargo-checksum.json
deleted file mode 100644 (file)
index 3de50a8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"be8b1e989478350479ab1d521682ddf562f767023121a6d0ae603af545a23462","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"b1816348f92faff49f0b8caacb9b31f38333381ff7bb4abbd11ac5bcd92e45a1","src/dependency.rs":"c85c395f4cbd4fee0a7268c614dd69437b916339bca0f94b7a14917cd8b33aff","src/diagnostic.rs":"3d497083d3704289fa003a8ba06df41db929e067e36a90ebfcd51b411721debc","src/errors.rs":"b7d396821f3c031510e18b434011a351166448889bcbdffa3c4e96e593fff474","src/lib.rs":"8823b593ced1d95d10e83ac0341c34ad4336eddbb4d618e5baae317a4ecbdcae","src/messages.rs":"6183e5ca4e49d42118f43a7cb0293c6f6281ae6d8d7135dbaa94e5869f868c2d","tests/selftest.rs":"257436f1e219aadf9343d1cd2db7cc0748c7b89340ff43ae8b5c83fceb0a8b7f","tests/test_samples.rs":"7c4ad89485e470b0271c81763bddc4f533c821b2ab600b162433a7b95a22366c"},"package":"89fec17b16f1ac67908af82e47d0a90a7afd0e1827b181cd77504323d3263d35"}
\ No newline at end of file
diff --git a/vendor/cargo_metadata-0.11.1/Cargo.toml b/vendor/cargo_metadata-0.11.1/Cargo.toml
deleted file mode 100644 (file)
index df37960..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-edition = "2018"
-name = "cargo_metadata"
-version = "0.11.1"
-authors = ["Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>"]
-description = "structured access to the output of `cargo metadata`"
-readme = "README.md"
-license = "MIT"
-repository = "https://github.com/oli-obk/cargo_metadata"
-[package.metadata.cargo_metadata_test]
-other_field = "foo"
-some_field = true
-[dependencies.semver]
-version = "0.10"
-features = ["serde"]
-
-[dependencies.serde]
-version = "1.0.79"
-features = ["derive"]
-
-[dependencies.serde_json]
-version = "1.0.1"
-
-[features]
-default = []
diff --git a/vendor/cargo_metadata-0.11.1/LICENSE-MIT b/vendor/cargo_metadata-0.11.1/LICENSE-MIT
deleted file mode 100644 (file)
index 31aa793..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/vendor/cargo_metadata-0.11.1/README.md b/vendor/cargo_metadata-0.11.1/README.md
deleted file mode 100644 (file)
index 7d9c7a0..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# cargo_metadata
-
-Structured access to the output of `cargo metadata`. Usually used from within a `cargo-*` executable.
-
-Also supports serialization to aid in implementing `--message-format=json`-like
-output generation in `cargo-*` subcommands, since some of the types in what
-`cargo --message-format=json` emits are exactly the same as the ones from `cargo metadata`.
-
-[![Build Status](https://api.travis-ci.org/oli-obk/cargo_metadata.svg?branch=master)](https://travis-ci.org/oli-obk/cargo_metadata)
-[![crates.io](https://img.shields.io/crates/v/cargo_metadata.svg)](https://crates.io/crates/cargo_metadata)
-
-[Documentation](https://docs.rs/cargo_metadata/) - contains examples of use with `std::env::args`, `docopt`, `clap`, and `structopt`.
diff --git a/vendor/cargo_metadata-0.11.1/src/dependency.rs b/vendor/cargo_metadata-0.11.1/src/dependency.rs
deleted file mode 100644 (file)
index 28b72f5..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-//! This module contains `Dependency` and the types/functions it uses for deserialization.
-
-use semver::VersionReq;
-use serde::{Deserialize, Deserializer, Serialize};
-use std::fmt;
-
-#[derive(PartialEq, Clone, Debug, Copy, Serialize, Deserialize)]
-/// Dependencies can come in three kinds
-pub enum DependencyKind {
-    #[serde(rename = "normal")]
-    /// The 'normal' kind
-    Normal,
-    #[serde(rename = "dev")]
-    /// Those used in tests only
-    Development,
-    #[serde(rename = "build")]
-    /// Those used in build scripts only
-    Build,
-    #[doc(hidden)]
-    #[serde(other)]
-    Unknown,
-}
-
-impl Default for DependencyKind {
-    fn default() -> DependencyKind {
-        DependencyKind::Normal
-    }
-}
-
-/// The `kind` can be `null`, which is interpreted as the default - `Normal`.
-pub(super) fn parse_dependency_kind<'de, D>(d: D) -> Result<DependencyKind, D::Error>
-where
-    D: Deserializer<'de>,
-{
-    Deserialize::deserialize(d).map(|x: Option<_>| x.unwrap_or_default())
-}
-
-#[derive(Clone, Serialize, Deserialize, Debug)]
-/// A dependency of the main crate
-pub struct Dependency {
-    /// Name as given in the `Cargo.toml`
-    pub name: String,
-    /// The source of dependency
-    pub source: Option<String>,
-    /// The required version
-    pub req: VersionReq,
-    /// The kind of dependency this is
-    #[serde(deserialize_with = "parse_dependency_kind")]
-    pub kind: DependencyKind,
-    /// Whether this dependency is required or optional
-    pub optional: bool,
-    /// Whether the default features in this dependency are used.
-    pub uses_default_features: bool,
-    /// The list of features enabled for this dependency.
-    pub features: Vec<String>,
-    /// The target this dependency is specific to.
-    ///
-    /// Use the [`Display`] trait to access the contents.
-    ///
-    /// [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
-    pub target: Option<Platform>,
-    /// If the dependency is renamed, this is the new name for the dependency
-    /// as a string.  None if it is not renamed.
-    pub rename: Option<String>,
-    /// The URL of the index of the registry where this dependency is from.
-    ///
-    /// If None, the dependency is from crates.io.
-    pub registry: Option<String>,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-/// A target platform.
-#[derive(Clone, Serialize, Deserialize, Debug)]
-#[serde(transparent)]
-pub struct Platform {
-    /// The underlying string representation of a platform.
-    pub repr: String,
-}
-
-impl fmt::Display for Platform {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&self.repr, f)
-    }
-}
diff --git a/vendor/cargo_metadata-0.11.1/src/diagnostic.rs b/vendor/cargo_metadata-0.11.1/src/diagnostic.rs
deleted file mode 100644 (file)
index 68f8fab..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-//! This module contains `Diagnostic` and the types/functions it uses for deserialization.
-
-use serde::{Deserialize, Serialize};
-use std::fmt;
-
-/// The error code associated to this diagnostic.
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct DiagnosticCode {
-    /// The code itself.
-    pub code: String,
-    /// An explanation for the code
-    pub explanation: Option<String>,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-/// A line of code associated with the Diagnostic
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct DiagnosticSpanLine {
-    /// The line of code associated with the error
-    pub text: String,
-    /// Start of the section of the line to highlight. 1-based, character offset in self.text
-    pub highlight_start: usize,
-    /// End of the section of the line to highlight. 1-based, character offset in self.text
-    pub highlight_end: usize,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-/// Macro expansion information associated with a diagnostic.
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct DiagnosticSpanMacroExpansion {
-    /// span where macro was applied to generate this code; note that
-    /// this may itself derive from a macro (if
-    /// `span.expansion.is_some()`)
-    pub span: DiagnosticSpan,
-
-    /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]")
-    pub macro_decl_name: String,
-
-    /// span where macro was defined (if known)
-    pub def_site_span: Option<DiagnosticSpan>,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-/// A section of the source code associated with a Diagnostic
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct DiagnosticSpan {
-    /// The file name or the macro name this diagnostic comes from.
-    pub file_name: String,
-    /// The byte offset in the file where this diagnostic starts from.
-    pub byte_start: u32,
-    /// The byte offset in the file where this diagnostic ends.
-    pub byte_end: u32,
-    /// 1-based. The line in the file.
-    pub line_start: usize,
-    /// 1-based. The line in the file.
-    pub line_end: usize,
-    /// 1-based, character offset.
-    pub column_start: usize,
-    /// 1-based, character offset.
-    pub column_end: usize,
-    /// Is this a "primary" span -- meaning the point, or one of the points,
-    /// where the error occurred?
-    ///
-    /// There are rare cases where multiple spans are marked as primary,
-    /// e.g. "immutable borrow occurs here" and "mutable borrow ends here" can
-    /// be two separate spans both "primary". Top (parent) messages should
-    /// always have at least one primary span, unless it has 0 spans. Child
-    /// messages may have 0 or more primary spans.
-    pub is_primary: bool,
-    /// Source text from the start of line_start to the end of line_end.
-    pub text: Vec<DiagnosticSpanLine>,
-    /// Label that should be placed at this location (if any)
-    pub label: Option<String>,
-    /// If we are suggesting a replacement, this will contain text
-    /// that should be sliced in atop this span.
-    pub suggested_replacement: Option<String>,
-    /// If the suggestion is approximate
-    pub suggestion_applicability: Option<Applicability>,
-    /// Macro invocations that created the code at this span, if any.
-    pub expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-/// Whether a suggestion can be safely applied.
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub enum Applicability {
-    /// The suggested replacement can be applied automatically safely
-    MachineApplicable,
-    /// The suggested replacement has placeholders that will need to be manually
-    /// replaced.
-    HasPlaceholders,
-    /// The suggested replacement may be incorrect in some circumstances. Needs
-    /// human review.
-    MaybeIncorrect,
-    /// The suggested replacement will probably not work.
-    Unspecified,
-    #[doc(hidden)]
-    #[serde(other)]
-    Unknown,
-}
-
-/// The diagnostic level
-#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
-#[serde(rename_all = "lowercase")]
-pub enum DiagnosticLevel {
-    /// Internal compiler error
-    #[serde(rename = "error: internal compiler error")]
-    Ice,
-    /// Error
-    Error,
-    /// Warning
-    Warning,
-    /// Note
-    Note,
-    /// Help
-    Help,
-    #[doc(hidden)]
-    #[serde(other)]
-    Unknown,
-}
-
-/// A diagnostic message generated by rustc
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct Diagnostic {
-    /// The error message of this diagnostic.
-    pub message: String,
-    /// The associated error code for this diagnostic
-    pub code: Option<DiagnosticCode>,
-    /// "error: internal compiler error", "error", "warning", "note", "help"
-    pub level: DiagnosticLevel,
-    /// A list of source code spans this diagnostic is associated with.
-    pub spans: Vec<DiagnosticSpan>,
-    /// Associated diagnostic messages.
-    pub children: Vec<Diagnostic>,
-    /// The message as rustc would render it
-    pub rendered: Option<String>,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-impl fmt::Display for Diagnostic {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if let Some(ref rendered) = self.rendered {
-            f.write_str(rendered)?;
-        } else {
-            f.write_str("cargo didn't render this message")?;
-        }
-        Ok(())
-    }
-}
diff --git a/vendor/cargo_metadata-0.11.1/src/errors.rs b/vendor/cargo_metadata-0.11.1/src/errors.rs
deleted file mode 100644 (file)
index 4c6668f..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-use std::fmt;
-use std::io;
-use std::str::Utf8Error;
-use std::string::FromUtf8Error;
-
-/// Custom result type for `cargo_metadata::Error`
-pub type Result<T> = ::std::result::Result<T, Error>;
-
-/// Error returned when executing/parsing `cargo metadata` fails.
-///
-/// # Note about Backtraces
-///
-/// This error type does not contain backtraces, but each error variant
-/// comes from _one_ specific place, so it's not really needed for the
-/// inside of this crate. If you need a backtrace down to, but not inside
-/// of, a failed call of `cargo_metadata` you can do one of multiple thinks:
-///
-/// 1. Convert it to a `failure::Error` (possible using the `?` operator),
-///    which is similar to a `Box<::std::error::Error + 'static + Send  + Sync>`.
-/// 2. Have appropriate variants in your own error type. E.g. you could wrap
-///    a `failure::Context<Error>` or add a `failure::Backtrace` field (which
-///    is empty if `RUST_BACKTRACE` is not set, so it's simple to use).
-/// 3. You still can place a failure based error into a `error_chain` if you
-///    really want to. (Either through foreign_links or by making it a field
-///    value of a `ErrorKind` variant).
-///
-#[derive(Debug)]
-pub enum Error {
-    /// Error during execution of `cargo metadata`
-    CargoMetadata {
-        /// stderr returned by the `cargo metadata` command
-        stderr: String,
-    },
-
-    /// IO Error during execution of `cargo metadata`
-    Io(io::Error),
-
-    /// Output of `cargo metadata` was not valid utf8
-    Utf8(Utf8Error),
-
-    /// Error output of `cargo metadata` was not valid utf8
-    ErrUtf8(FromUtf8Error),
-
-    /// Deserialization error (structure of json did not match expected structure)
-    Json(::serde_json::Error),
-
-    /// The output did not contain any json
-    NoJson,
-}
-
-impl From<io::Error> for Error {
-    fn from(v: io::Error) -> Self {
-        Error::Io(v)
-    }
-}
-
-impl From<Utf8Error> for Error {
-    fn from(v: Utf8Error) -> Self {
-        Error::Utf8(v)
-    }
-}
-
-impl From<FromUtf8Error> for Error {
-    fn from(v: FromUtf8Error) -> Self {
-        Error::ErrUtf8(v)
-    }
-}
-
-impl From<::serde_json::Error> for Error {
-    fn from(v: ::serde_json::Error) -> Self {
-        Error::Json(v)
-    }
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Error::CargoMetadata { stderr } => {
-                write!(f, "Error during execution of `cargo metadata`: {}", stderr)
-            }
-            Error::Io(err) => write!(f, "{}", err),
-            Error::Utf8(err) => write!(f, "Cannot convert the stdout of `cargo metadata`: {}", err),
-            Error::ErrUtf8(err) => {
-                write!(f, "Cannot convert the stderr of `cargo metadata`: {}", err)
-            }
-            Error::Json(err) => write!(f, "Failed to interpret `cargo metadata`'s json: {}", err),
-            Error::NoJson => write!(
-                f,
-                "Could not find any json in the output of `cargo metadata`"
-            ),
-        }
-    }
-}
-
-impl ::std::error::Error for Error {
-    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
-        match self {
-            Error::CargoMetadata { .. } => None,
-            Error::Io(err) => Some(err),
-            Error::Utf8(err) => Some(err),
-            Error::ErrUtf8(err) => Some(err),
-            Error::Json(err) => Some(err),
-            Error::NoJson => None,
-        }
-    }
-}
diff --git a/vendor/cargo_metadata-0.11.1/src/lib.rs b/vendor/cargo_metadata-0.11.1/src/lib.rs
deleted file mode 100644 (file)
index a06479d..0000000
+++ /dev/null
@@ -1,575 +0,0 @@
-#![deny(missing_docs)]
-//! Structured access to the output of `cargo metadata` and `cargo --message-format=json`.
-//! Usually used from within a `cargo-*` executable
-//!
-//! See the [cargo book](https://doc.rust-lang.org/cargo/index.html) for
-//! details on cargo itself.
-//!
-//! ## Examples
-//!
-//! ```rust
-//! # extern crate cargo_metadata;
-//! # use std::path::Path;
-//! let mut args = std::env::args().skip_while(|val| !val.starts_with("--manifest-path"));
-//!
-//! let mut cmd = cargo_metadata::MetadataCommand::new();
-//! let manifest_path = match args.next() {
-//!     Some(ref p) if p == "--manifest-path" => {
-//!         cmd.manifest_path(args.next().unwrap());
-//!     }
-//!     Some(p) => {
-//!         cmd.manifest_path(p.trim_start_matches("--manifest-path="));
-//!     }
-//!     None => {}
-//! };
-//!
-//! let _metadata = cmd.exec().unwrap();
-//! ```
-//!
-//! Pass features flags
-//!
-//! ```rust
-//! # // This should be kept in sync with the equivalent example in the readme.
-//! # extern crate cargo_metadata;
-//! # use std::path::Path;
-//! # fn main() {
-//! use cargo_metadata::{MetadataCommand, CargoOpt};
-//!
-//! let _metadata = MetadataCommand::new()
-//!     .manifest_path("./Cargo.toml")
-//!     .features(CargoOpt::AllFeatures)
-//!     .exec()
-//!     .unwrap();
-//! # }
-//! ```
-//!
-//! Parse message-format output:
-//!
-//! ```
-//! # extern crate cargo_metadata;
-//! use std::process::{Stdio, Command};
-//! use cargo_metadata::Message;
-//!
-//! let mut command = Command::new("cargo")
-//!     .args(&["build", "--message-format=json"])
-//!     .stdout(Stdio::piped())
-//!     .spawn()
-//!     .unwrap();
-//!
-//! let reader = std::io::BufReader::new(command.stdout.take().unwrap());
-//! for message in cargo_metadata::Message::parse_stream(reader) {
-//!     match message.unwrap() {
-//!         Message::CompilerMessage(msg) => {
-//!             println!("{:?}", msg);
-//!         },
-//!         Message::CompilerArtifact(artifact) => {
-//!             println!("{:?}", artifact);
-//!         },
-//!         Message::BuildScriptExecuted(script) => {
-//!             println!("{:?}", script);
-//!         },
-//!         Message::BuildFinished(finished) => {
-//!             println!("{:?}", finished);
-//!         },
-//!         _ => () // Unknown message
-//!     }
-//! }
-//!
-//! let output = command.wait().expect("Couldn't get cargo's exit status");
-//! ```
-
-use std::collections::HashMap;
-use std::env;
-use std::fmt;
-use std::path::PathBuf;
-use std::process::Command;
-use std::str::from_utf8;
-
-pub use semver::Version;
-
-pub use dependency::{Dependency, DependencyKind};
-use diagnostic::Diagnostic;
-pub use errors::{Error, Result};
-#[allow(deprecated)]
-pub use messages::parse_messages;
-pub use messages::{
-    Artifact, ArtifactProfile, BuildFinished, BuildScript, CompilerMessage, Message, MessageIter,
-};
-use serde::{Deserialize, Serialize};
-
-mod dependency;
-pub mod diagnostic;
-mod errors;
-mod messages;
-
-/// An "opaque" identifier for a package.
-/// It is possible to inspect the `repr` field, if the need arises, but its
-/// precise format is an implementation detail and is subject to change.
-///
-/// `Metadata` can be indexed by `PackageId`.
-#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[serde(transparent)]
-pub struct PackageId {
-    /// The underlying string representation of id.
-    pub repr: String,
-}
-
-impl std::fmt::Display for PackageId {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&self.repr, f)
-    }
-}
-
-#[derive(Clone, Serialize, Deserialize, Debug)]
-/// Starting point for metadata returned by `cargo metadata`
-pub struct Metadata {
-    /// A list of all crates referenced by this crate (and the crate itself)
-    pub packages: Vec<Package>,
-    /// A list of all workspace members
-    pub workspace_members: Vec<PackageId>,
-    /// Dependencies graph
-    pub resolve: Option<Resolve>,
-    /// Workspace root
-    pub workspace_root: PathBuf,
-    /// Build directory
-    pub target_directory: PathBuf,
-    version: usize,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-impl<'a> std::ops::Index<&'a PackageId> for Metadata {
-    type Output = Package;
-
-    fn index(&self, idx: &'a PackageId) -> &Package {
-        self.packages
-            .iter()
-            .find(|p| p.id == *idx)
-            .unwrap_or_else(|| panic!("no package with this id: {:?}", idx))
-    }
-}
-
-#[derive(Clone, Serialize, Deserialize, Debug)]
-/// A dependency graph
-pub struct Resolve {
-    /// Nodes in a dependencies graph
-    pub nodes: Vec<Node>,
-
-    /// The crate for which the metadata was read.
-    pub root: Option<PackageId>,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-#[derive(Clone, Serialize, Deserialize, Debug)]
-/// A node in a dependencies graph
-pub struct Node {
-    /// An opaque identifier for a package
-    pub id: PackageId,
-    /// Dependencies in a structured format.
-    ///
-    /// `deps` handles renamed dependencies whereas `dependencies` does not.
-    #[serde(default)]
-    pub deps: Vec<NodeDep>,
-
-    /// List of opaque identifiers for this node's dependencies.
-    /// It doesn't support renamed dependencies. See `deps`.
-    pub dependencies: Vec<PackageId>,
-
-    /// Features enabled on the crate
-    #[serde(default)]
-    pub features: Vec<String>,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-#[derive(Clone, Serialize, Deserialize, Debug)]
-/// A dependency in a node
-pub struct NodeDep {
-    /// The name of the dependency's library target.
-    /// If the crate was renamed, it is the new name.
-    pub name: String,
-    /// Package ID (opaque unique identifier)
-    pub pkg: PackageId,
-    /// The kinds of dependencies.
-    ///
-    /// This field was added in Rust 1.41.
-    #[serde(default)]
-    pub dep_kinds: Vec<DepKindInfo>,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-#[derive(Clone, Serialize, Deserialize, Debug)]
-/// Information about a dependency kind.
-pub struct DepKindInfo {
-    /// The kind of dependency.
-    #[serde(deserialize_with = "dependency::parse_dependency_kind")]
-    pub kind: DependencyKind,
-    /// The target platform for the dependency.
-    ///
-    /// This is `None` if it is not a target dependency.
-    ///
-    /// Use the [`Display`] trait to access the contents.
-    ///
-    /// By default all platform dependencies are included in the resolve
-    /// graph. Use Cargo's `--filter-platform` flag if you only want to
-    /// include dependencies for a specific platform.
-    ///
-    /// [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
-    pub target: Option<dependency::Platform>,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-#[derive(Clone, Serialize, Deserialize, Debug)]
-/// A crate
-pub struct Package {
-    /// Name as given in the `Cargo.toml`
-    pub name: String,
-    /// Version given in the `Cargo.toml`
-    pub version: Version,
-    /// Authors given in the `Cargo.toml`
-    #[serde(default)]
-    pub authors: Vec<String>,
-    /// An opaque identifier for a package
-    pub id: PackageId,
-    /// The source of the package, e.g.
-    /// crates.io or `None` for local projects.
-    pub source: Option<Source>,
-    /// Description as given in the `Cargo.toml`
-    pub description: Option<String>,
-    /// List of dependencies of this particular package
-    pub dependencies: Vec<Dependency>,
-    /// License as given in the `Cargo.toml`
-    pub license: Option<String>,
-    /// If the package is using a nonstandard license, this key may be specified instead of
-    /// `license`, and must point to a file relative to the manifest.
-    pub license_file: Option<PathBuf>,
-    /// Targets provided by the crate (lib, bin, example, test, ...)
-    pub targets: Vec<Target>,
-    /// Features provided by the crate, mapped to the features required by that feature.
-    pub features: HashMap<String, Vec<String>>,
-    /// Path containing the `Cargo.toml`
-    pub manifest_path: PathBuf,
-    /// Categories as given in the `Cargo.toml`
-    #[serde(default)]
-    pub categories: Vec<String>,
-    /// Keywords as given in the `Cargo.toml`
-    #[serde(default)]
-    pub keywords: Vec<String>,
-    /// Readme as given in the `Cargo.toml`
-    pub readme: Option<PathBuf>,
-    /// Repository as given in the `Cargo.toml`
-    // can't use `url::Url` because that requires a more recent stable compiler
-    pub repository: Option<String>,
-    /// Default Rust edition for the package
-    ///
-    /// Beware that individual targets may specify their own edition in
-    /// [`Target::edition`](struct.Target.html#structfield.edition).
-    #[serde(default = "edition_default")]
-    pub edition: String,
-    /// Contents of the free form package.metadata section
-    ///
-    /// This contents can be serialized to a struct using serde:
-    ///
-    /// ```rust
-    /// use serde::Deserialize;
-    /// use serde_json::json;
-    ///
-    /// #[derive(Debug, Deserialize)]
-    /// struct SomePackageMetadata {
-    ///     some_value: i32,
-    /// }
-    ///
-    /// fn main() {
-    ///     let value = json!({
-    ///         "some_value": 42,
-    ///     });
-    ///
-    ///     let package_metadata: SomePackageMetadata = serde_json::from_value(value).unwrap();
-    ///     assert_eq!(package_metadata.some_value, 42);
-    /// }
-    ///
-    /// ```
-    #[serde(default)]
-    pub metadata: serde_json::Value,
-    /// The name of a native library the package is linking to.
-    pub links: Option<String>,
-    /// List of registries to which this package may be published.
-    ///
-    /// Publishing is unrestricted if `None`, and forbidden if the `Vec` is empty.
-    ///
-    /// This is always `None` if running with a version of Cargo older than 1.39.
-    pub publish: Option<Vec<String>>,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-impl Package {
-    /// Full path to the license file if one is present in the manifest
-    pub fn license_file(&self) -> Option<PathBuf> {
-        self.license_file.as_ref().map(|file| {
-            self.manifest_path
-                .parent()
-                .unwrap_or(&self.manifest_path)
-                .join(file)
-        })
-    }
-
-    /// Full path to the readme file if one is present in the manifest
-    pub fn readme(&self) -> Option<PathBuf> {
-        self.readme
-            .as_ref()
-            .map(|file| self.manifest_path.join(file))
-    }
-}
-
-/// The source of a package such as crates.io.
-#[derive(Clone, Serialize, Deserialize, Debug)]
-#[serde(transparent)]
-pub struct Source {
-    /// The underlying string representation of a source.
-    pub repr: String,
-}
-
-impl Source {
-    /// Returns true if the source is crates.io.
-    pub fn is_crates_io(&self) -> bool {
-        self.repr == "registry+https://github.com/rust-lang/crates.io-index"
-    }
-}
-
-impl std::fmt::Display for Source {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&self.repr, f)
-    }
-}
-
-#[derive(Clone, Serialize, Deserialize, Debug)]
-/// A single target (lib, bin, example, ...) provided by a crate
-pub struct Target {
-    /// Name as given in the `Cargo.toml` or generated from the file name
-    pub name: String,
-    /// Kind of target ("bin", "example", "test", "bench", "lib")
-    pub kind: Vec<String>,
-    /// Almost the same as `kind`, except when an example is a library instead of an executable.
-    /// In that case `crate_types` contains things like `rlib` and `dylib` while `kind` is `example`
-    #[serde(default)]
-    pub crate_types: Vec<String>,
-
-    #[serde(default)]
-    #[serde(rename = "required-features")]
-    /// This target is built only if these features are enabled.
-    /// It doesn't apply to `lib` targets.
-    pub required_features: Vec<String>,
-    /// Path to the main source file of the target
-    pub src_path: PathBuf,
-    /// Rust edition for this target
-    #[serde(default = "edition_default")]
-    pub edition: String,
-    /// Whether or not this target has doc tests enabled, and the target is
-    /// compatible with doc testing.
-    ///
-    /// This is always `true` if running with a version of Cargo older than 1.37.
-    #[serde(default = "default_true")]
-    pub doctest: bool,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-fn default_true() -> bool {
-    true
-}
-
-fn edition_default() -> String {
-    "2015".to_string()
-}
-
-/// Cargo features flags
-#[derive(Debug, Clone)]
-pub enum CargoOpt {
-    /// Run cargo with `--features-all`
-    AllFeatures,
-    /// Run cargo with `--no-default-features`
-    NoDefaultFeatures,
-    /// Run cargo with `--features <FEATURES>`
-    SomeFeatures(Vec<String>),
-}
-
-/// A builder for configurating `cargo metadata` invocation.
-#[derive(Debug, Clone, Default)]
-pub struct MetadataCommand {
-    cargo_path: Option<PathBuf>,
-    manifest_path: Option<PathBuf>,
-    current_dir: Option<PathBuf>,
-    no_deps: bool,
-    /// Collections of `CargoOpt::SomeFeatures(..)`
-    features: Vec<String>,
-    /// Latched `CargoOpt::AllFeatures`
-    all_features: bool,
-    /// Latched `CargoOpt::NoDefaultFeatures`
-    no_default_features: bool,
-    other_options: Vec<String>,
-}
-
-impl MetadataCommand {
-    /// Creates a default `cargo metadata` command, which will look for
-    /// `Cargo.toml` in the ancestors of the current directory.
-    pub fn new() -> MetadataCommand {
-        MetadataCommand::default()
-    }
-    /// Path to `cargo` executable.  If not set, this will use the
-    /// the `$CARGO` environment variable, and if that is not set, will
-    /// simply be `cargo`.
-    pub fn cargo_path(&mut self, path: impl Into<PathBuf>) -> &mut MetadataCommand {
-        self.cargo_path = Some(path.into());
-        self
-    }
-    /// Path to `Cargo.toml`
-    pub fn manifest_path(&mut self, path: impl Into<PathBuf>) -> &mut MetadataCommand {
-        self.manifest_path = Some(path.into());
-        self
-    }
-    /// Current directory of the `cargo metadata` process.
-    pub fn current_dir(&mut self, path: impl Into<PathBuf>) -> &mut MetadataCommand {
-        self.current_dir = Some(path.into());
-        self
-    }
-    /// Output information only about the root package and don't fetch dependencies.
-    pub fn no_deps(&mut self) -> &mut MetadataCommand {
-        self.no_deps = true;
-        self
-    }
-    /// Which features to include.
-    ///
-    /// Call this multiple times to specify advanced feature configurations:
-    ///
-    /// ```no_run
-    /// # use cargo_metadata::{CargoOpt, MetadataCommand};
-    /// MetadataCommand::new()
-    ///     .features(CargoOpt::NoDefaultFeatures)
-    ///     .features(CargoOpt::SomeFeatures(vec!["feat1".into(), "feat2".into()]))
-    ///     .features(CargoOpt::SomeFeatures(vec!["feat3".into()]))
-    ///     // ...
-    ///     # ;
-    /// ```
-    ///
-    /// # Panics
-    ///
-    /// `cargo metadata` rejects multiple `--no-default-features` flags. Similarly, the `features()`
-    /// method panics when specifiying multiple `CargoOpt::NoDefaultFeatures`:
-    ///
-    /// ```should_panic
-    /// # use cargo_metadata::{CargoOpt, MetadataCommand};
-    /// MetadataCommand::new()
-    ///     .features(CargoOpt::NoDefaultFeatures)
-    ///     .features(CargoOpt::NoDefaultFeatures) // <-- panic!
-    ///     // ...
-    ///     # ;
-    /// ```
-    ///
-    /// The method also panics for multiple `CargoOpt::AllFeatures` arguments:
-    ///
-    /// ```should_panic
-    /// # use cargo_metadata::{CargoOpt, MetadataCommand};
-    /// MetadataCommand::new()
-    ///     .features(CargoOpt::AllFeatures)
-    ///     .features(CargoOpt::AllFeatures) // <-- panic!
-    ///     // ...
-    ///     # ;
-    /// ```
-    pub fn features(&mut self, features: CargoOpt) -> &mut MetadataCommand {
-        match features {
-            CargoOpt::SomeFeatures(features) => self.features.extend(features),
-            CargoOpt::NoDefaultFeatures => {
-                assert!(
-                    !self.no_default_features,
-                    "Do not supply CargoOpt::NoDefaultFeatures more than once!"
-                );
-                self.no_default_features = true;
-            }
-            CargoOpt::AllFeatures => {
-                assert!(
-                    !self.all_features,
-                    "Do not supply CargoOpt::AllFeatures more than once!"
-                );
-                self.all_features = true;
-            }
-        }
-        self
-    }
-    /// Arbitrary command line flags to pass to `cargo`.  These will be added
-    /// to the end of the command line invocation.
-    pub fn other_options(&mut self, options: impl Into<Vec<String>>) -> &mut MetadataCommand {
-        self.other_options = options.into();
-        self
-    }
-
-    /// Builds a command for `cargo metadata`.  This is the first
-    /// part of the work of `exec`.
-    pub fn cargo_command(&self) -> Result<Command> {
-        let cargo = self
-            .cargo_path
-            .clone()
-            .or_else(|| env::var("CARGO").map(PathBuf::from).ok())
-            .unwrap_or_else(|| PathBuf::from("cargo"));
-        let mut cmd = Command::new(cargo);
-        cmd.args(&["metadata", "--format-version", "1"]);
-
-        if self.no_deps {
-            cmd.arg("--no-deps");
-        }
-
-        if let Some(path) = self.current_dir.as_ref() {
-            cmd.current_dir(path);
-        }
-
-        if !self.features.is_empty() {
-            cmd.arg("--features").arg(self.features.join(","));
-        }
-        if self.all_features {
-            cmd.arg("--all-features");
-        }
-        if self.no_default_features {
-            cmd.arg("--no-default-features");
-        }
-
-        if let Some(manifest_path) = &self.manifest_path {
-            cmd.arg("--manifest-path").arg(manifest_path.as_os_str());
-        }
-        cmd.args(&self.other_options);
-
-        Ok(cmd)
-    }
-
-    /// Parses `cargo metadata` output.  `data` must have been
-    /// produced by a command built with `cargo_command`.
-    pub fn parse<T: AsRef<str>>(data: T) -> Result<Metadata> {
-        let meta = serde_json::from_str(data.as_ref())?;
-        Ok(meta)
-    }
-
-    /// Runs configured `cargo metadata` and returns parsed `Metadata`.
-    pub fn exec(&self) -> Result<Metadata> {
-        let mut cmd = self.cargo_command()?;
-        let output = cmd.output()?;
-        if !output.status.success() {
-            return Err(Error::CargoMetadata {
-                stderr: String::from_utf8(output.stderr)?,
-            });
-        }
-        let stdout = from_utf8(&output.stdout)?
-            .lines()
-            .find(|line| line.starts_with('{'))
-            .ok_or_else(|| Error::NoJson)?;
-        Self::parse(stdout)
-    }
-}
diff --git a/vendor/cargo_metadata-0.11.1/src/messages.rs b/vendor/cargo_metadata-0.11.1/src/messages.rs
deleted file mode 100644 (file)
index 0ac2edb..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-use super::{Diagnostic, PackageId, Target};
-use serde::{Deserialize, Serialize};
-use std::fmt;
-use std::io::{self, BufRead, Lines, Read};
-use std::path::PathBuf;
-
-/// Profile settings used to determine which compiler flags to use for a
-/// target.
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct ArtifactProfile {
-    /// Optimization level. Possible values are 0-3, s or z.
-    pub opt_level: String,
-    /// The amount of debug info. 0 for none, 1 for limited, 2 for full
-    pub debuginfo: Option<u32>,
-    /// State of the `cfg(debug_assertions)` directive, enabling macros like
-    /// `debug_assert!`
-    pub debug_assertions: bool,
-    /// State of the overflow checks.
-    pub overflow_checks: bool,
-    /// Whether this profile is a test
-    pub test: bool,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-/// A compiler-generated file.
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct Artifact {
-    /// The package this artifact belongs to
-    pub package_id: PackageId,
-    /// The target this artifact was compiled for
-    pub target: Target,
-    /// The profile this artifact was compiled with
-    pub profile: ArtifactProfile,
-    /// The enabled features for this artifact
-    pub features: Vec<String>,
-    /// The full paths to the generated artifacts
-    /// (e.g. binary file and separate debug info)
-    pub filenames: Vec<PathBuf>,
-    /// Path to the executable file
-    pub executable: Option<PathBuf>,
-    /// If true, then the files were already generated
-    pub fresh: bool,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-/// Message left by the compiler
-// TODO: Better name. This one comes from machine_message.rs
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct CompilerMessage {
-    /// The package this message belongs to
-    pub package_id: PackageId,
-    /// The target this message is aimed at
-    pub target: Target,
-    /// The message the compiler sent.
-    pub message: Diagnostic,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-/// Output of a build script execution.
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct BuildScript {
-    /// The package this build script execution belongs to
-    pub package_id: PackageId,
-    /// The libs to link
-    pub linked_libs: Vec<PathBuf>,
-    /// The paths to search when resolving libs
-    pub linked_paths: Vec<PathBuf>,
-    /// Various `--cfg` flags to pass to the compiler
-    pub cfgs: Vec<String>,
-    /// The environment variables to add to the compilation
-    pub env: Vec<(String, String)>,
-    /// The `OUT_DIR` environment variable where this script places its output
-    ///
-    /// Added in Rust 1.41.
-    #[serde(default)]
-    pub out_dir: PathBuf,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-/// Final result of a build.
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct BuildFinished {
-    /// Whether or not the build finished successfully.
-    pub success: bool,
-    #[doc(hidden)]
-    #[serde(skip)]
-    __do_not_match_exhaustively: (),
-}
-
-/// A cargo message
-#[derive(Debug, Clone, Serialize, Deserialize)]
-#[serde(tag = "reason", rename_all = "kebab-case")]
-pub enum Message {
-    /// The compiler generated an artifact
-    CompilerArtifact(Artifact),
-    /// The compiler wants to display a message
-    CompilerMessage(CompilerMessage),
-    /// A build script successfully executed.
-    BuildScriptExecuted(BuildScript),
-    /// The build has finished.
-    ///
-    /// This is emitted at the end of the build as the last message.
-    /// Added in Rust 1.44.
-    BuildFinished(BuildFinished),
-    /// A line of text which isn't a cargo or compiler message.
-    /// Line separator is not included
-    #[serde(skip)]
-    TextLine(String),
-    #[doc(hidden)]
-    #[serde(other)]
-    Unknown,
-}
-
-impl Message {
-    /// Creates an iterator of Message from a Read outputting a stream of JSON
-    /// messages. For usage information, look at the top-level documentation.
-    pub fn parse_stream<R: BufRead>(input: R) -> MessageIter<R> {
-        MessageIter {
-            lines: input.lines(),
-        }
-    }
-}
-
-impl fmt::Display for CompilerMessage {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.message)
-    }
-}
-
-/// An iterator of Messages.
-pub struct MessageIter<R> {
-    lines: Lines<R>,
-}
-
-impl<R: BufRead> Iterator for MessageIter<R> {
-    type Item = io::Result<Message>;
-    fn next(&mut self) -> Option<Self::Item> {
-        let line = self.lines.next()?;
-        let message = line.map(|it| serde_json::from_str(&it).unwrap_or(Message::TextLine(it)));
-        Some(message)
-    }
-}
-
-/// An iterator of Message.
-type MessageIterator<R> =
-    serde_json::StreamDeserializer<'static, serde_json::de::IoRead<R>, Message>;
-
-/// Creates an iterator of Message from a Read outputting a stream of JSON
-/// messages. For usage information, look at the top-level documentation.
-#[deprecated(note = "Use Message::parse_stream instead")]
-pub fn parse_messages<R: Read>(input: R) -> MessageIterator<R> {
-    serde_json::Deserializer::from_reader(input).into_iter::<Message>()
-}
diff --git a/vendor/cargo_metadata-0.11.1/tests/selftest.rs b/vendor/cargo_metadata-0.11.1/tests/selftest.rs
deleted file mode 100644 (file)
index 406d144..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-use std::env::current_dir;
-use std::path::PathBuf;
-
-use semver::Version;
-
-use cargo_metadata::{CargoOpt, Error, MetadataCommand};
-use serde::{Deserialize};
-
-#[derive(Debug, PartialEq, Eq, Deserialize)]
-struct TestPackageMetadata {
-    some_field: bool,
-    other_field: String,
-}
-
-#[test]
-fn metadata() {
-    let metadata = MetadataCommand::new().no_deps().exec().unwrap();
-
-    let this = &metadata.packages[0];
-    assert_eq!(this.name, "cargo_metadata");
-    assert_eq!(this.targets.len(), 3);
-
-    let lib = this
-        .targets
-        .iter()
-        .find(|t| t.name == "cargo_metadata")
-        .unwrap();
-    assert_eq!(lib.kind[0], "lib");
-    assert_eq!(lib.crate_types[0], "lib");
-
-    let selftest = this.targets.iter().find(|t| t.name == "selftest").unwrap();
-    assert_eq!(selftest.name, "selftest");
-    assert_eq!(selftest.kind[0], "test");
-    assert_eq!(selftest.crate_types[0], "bin");
-
-    let package_metadata = &metadata.packages[0]
-        .metadata
-        .as_object()
-        .expect("package.metadata must be a table.");
-    assert_eq!(package_metadata.len(), 1);
-
-    let value = package_metadata.get("cargo_metadata_test").unwrap();
-    let test_package_metadata: TestPackageMetadata = serde_json::from_value(value.clone()).unwrap();
-    assert_eq!(
-        test_package_metadata,
-        TestPackageMetadata {
-            some_field: true,
-            other_field: "foo".into(),
-        }
-    );
-}
-
-#[test]
-fn builder_interface() {
-    let _ = MetadataCommand::new()
-        .manifest_path("Cargo.toml")
-        .exec()
-        .unwrap();
-    let _ = MetadataCommand::new()
-        .manifest_path(String::from("Cargo.toml"))
-        .exec()
-        .unwrap();
-    let _ = MetadataCommand::new()
-        .manifest_path(PathBuf::from("Cargo.toml"))
-        .exec()
-        .unwrap();
-    let _ = MetadataCommand::new()
-        .manifest_path("Cargo.toml")
-        .no_deps()
-        .exec()
-        .unwrap();
-    let _ = MetadataCommand::new()
-        .manifest_path("Cargo.toml")
-        .features(CargoOpt::AllFeatures)
-        .exec()
-        .unwrap();
-    let _ = MetadataCommand::new()
-        .manifest_path("Cargo.toml")
-        .current_dir(current_dir().unwrap())
-        .exec()
-        .unwrap();
-}
-
-#[test]
-fn error1() {
-    match MetadataCommand::new().manifest_path("foo").exec() {
-        Err(Error::CargoMetadata { stderr }) => assert_eq!(
-            stderr.trim(),
-            "error: the manifest-path must be a path to a Cargo.toml file"
-        ),
-        _ => unreachable!(),
-    }
-}
-
-#[test]
-fn error2() {
-    match MetadataCommand::new()
-        .manifest_path("foo/Cargo.toml")
-        .exec()
-    {
-        Err(Error::CargoMetadata { stderr }) => assert_eq!(
-            stderr.trim(),
-            "error: manifest path `foo/Cargo.toml` does not exist"
-        ),
-        _ => unreachable!(),
-    }
-}
-
-#[test]
-fn cargo_path() {
-    match MetadataCommand::new()
-        .cargo_path("this does not exist")
-        .exec()
-    {
-        Err(Error::Io(e)) => assert_eq!(e.kind(), std::io::ErrorKind::NotFound),
-        _ => unreachable!(),
-    }
-}
-
-#[test]
-fn metadata_deps() {
-    std::env::set_var("CARGO_PROFILE", "3");
-    let metadata = MetadataCommand::new()
-        .manifest_path("Cargo.toml")
-        .exec()
-        .unwrap();
-    let this_id = metadata
-        .workspace_members
-        .first()
-        .expect("Did not find ourselves");
-    let this = &metadata[this_id];
-
-    assert_eq!(this.name, "cargo_metadata");
-
-    let lib = this
-        .targets
-        .iter()
-        .find(|t| t.name == "cargo_metadata")
-        .unwrap();
-    assert_eq!(lib.kind[0], "lib");
-    assert_eq!(lib.crate_types[0], "lib");
-
-    let selftest = this.targets.iter().find(|t| t.name == "selftest").unwrap();
-    assert_eq!(selftest.name, "selftest");
-    assert_eq!(selftest.kind[0], "test");
-    assert_eq!(selftest.crate_types[0], "bin");
-
-    let dependencies = &this.dependencies;
-
-    let serde = dependencies
-        .iter()
-        .find(|dep| dep.name == "serde")
-        .expect("Did not find serde dependency");
-
-    assert_eq!(serde.kind, cargo_metadata::DependencyKind::Normal);
-    assert!(!serde.req.matches(&Version::parse("1.0.0").unwrap()));
-    assert!(serde.req.matches(&Version::parse("1.99.99").unwrap()));
-    assert!(!serde.req.matches(&Version::parse("2.0.0").unwrap()));
-}
diff --git a/vendor/cargo_metadata-0.11.1/tests/test_samples.rs b/vendor/cargo_metadata-0.11.1/tests/test_samples.rs
deleted file mode 100644 (file)
index 58f30f5..0000000
+++ /dev/null
@@ -1,559 +0,0 @@
-extern crate cargo_metadata;
-extern crate semver;
-#[macro_use]
-extern crate serde_json;
-
-use cargo_metadata::{CargoOpt, DependencyKind, Metadata, MetadataCommand};
-use std::path::PathBuf;
-
-#[test]
-fn old_minimal() {
-    // Output from oldest supported version (1.24).
-    // This intentionally has as many null fields as possible.
-    // 1.8 is when metadata was introduced.
-    // Older versions not supported because the following are required:
-    // - `workspace_members` added in 1.13
-    // - `target_directory` added in 1.19
-    // - `workspace_root` added in 1.24
-    let json = r#"
-{
-  "packages": [
-    {
-      "name": "foo",
-      "version": "0.1.0",
-      "id": "foo 0.1.0 (path+file:///foo)",
-      "license": null,
-      "license_file": null,
-      "description": null,
-      "source": null,
-      "dependencies": [
-        {
-          "name": "somedep",
-          "source": null,
-          "req": "^1.0",
-          "kind": null,
-          "optional": false,
-          "uses_default_features": true,
-          "features": [],
-          "target": null
-        }
-      ],
-      "targets": [
-        {
-          "kind": [
-            "bin"
-          ],
-          "crate_types": [
-            "bin"
-          ],
-          "name": "foo",
-          "src_path": "/foo/src/main.rs"
-        }
-      ],
-      "features": {},
-      "manifest_path": "/foo/Cargo.toml"
-    }
-  ],
-  "workspace_members": [
-    "foo 0.1.0 (path+file:///foo)"
-  ],
-  "resolve": null,
-  "target_directory": "/foo/target",
-  "version": 1,
-  "workspace_root": "/foo"
-}
-"#;
-    let meta: Metadata = serde_json::from_str(json).unwrap();
-    assert_eq!(meta.packages.len(), 1);
-    let pkg = &meta.packages[0];
-    assert_eq!(pkg.name, "foo");
-    assert_eq!(pkg.version, semver::Version::parse("0.1.0").unwrap());
-    assert_eq!(pkg.authors.len(), 0);
-    assert_eq!(pkg.id.to_string(), "foo 0.1.0 (path+file:///foo)");
-    assert_eq!(pkg.description, None);
-    assert_eq!(pkg.license, None);
-    assert_eq!(pkg.license_file, None);
-    assert_eq!(pkg.dependencies.len(), 1);
-    let dep = &pkg.dependencies[0];
-    assert_eq!(dep.name, "somedep");
-    assert_eq!(dep.source, None);
-    assert_eq!(dep.req, semver::VersionReq::parse("^1.0").unwrap());
-    assert_eq!(dep.kind, DependencyKind::Normal);
-    assert_eq!(dep.optional, false);
-    assert_eq!(dep.uses_default_features, true);
-    assert_eq!(dep.features.len(), 0);
-    assert!(dep.target.is_none());
-    assert_eq!(dep.rename, None);
-    assert_eq!(dep.registry, None);
-    assert_eq!(pkg.targets.len(), 1);
-    let target = &pkg.targets[0];
-    assert_eq!(target.name, "foo");
-    assert_eq!(target.kind, vec!["bin"]);
-    assert_eq!(target.crate_types, vec!["bin"]);
-    assert_eq!(target.required_features.len(), 0);
-    assert_eq!(target.src_path, PathBuf::from("/foo/src/main.rs"));
-    assert_eq!(target.edition, "2015");
-    assert_eq!(target.doctest, true);
-    assert_eq!(pkg.features.len(), 0);
-    assert_eq!(pkg.manifest_path, PathBuf::from("/foo/Cargo.toml"));
-    assert_eq!(pkg.categories.len(), 0);
-    assert_eq!(pkg.keywords.len(), 0);
-    assert_eq!(pkg.readme, None);
-    assert_eq!(pkg.repository, None);
-    assert_eq!(pkg.edition, "2015");
-    assert_eq!(pkg.metadata, serde_json::Value::Null);
-    assert_eq!(pkg.links, None);
-    assert_eq!(pkg.publish, None);
-    assert_eq!(meta.workspace_members.len(), 1);
-    assert_eq!(
-        meta.workspace_members[0].to_string(),
-        "foo 0.1.0 (path+file:///foo)"
-    );
-    assert!(meta.resolve.is_none());
-    assert_eq!(meta.workspace_root, PathBuf::from("/foo"));
-    assert_eq!(meta.target_directory, PathBuf::from("/foo/target"));
-}
-
-macro_rules! sorted {
-    ($e:expr) => {{
-        let mut v = $e.clone();
-        v.sort();
-        v
-    }};
-}
-
-fn cargo_version() -> semver::Version {
-    let output = std::process::Command::new("cargo")
-        .arg("-V")
-        .output()
-        .expect("Failed to exec cargo.");
-    let out = std::str::from_utf8(&output.stdout)
-        .expect("invalid utf8")
-        .trim();
-    let split: Vec<&str> = out.split_whitespace().collect();
-    assert!(split.len() >= 2, "cargo -V output is unexpected: {}", out);
-    let mut ver = semver::Version::parse(split[1]).expect("cargo -V semver could not be parsed");
-    // Don't care about metadata, it is awkward to compare.
-    ver.pre = Vec::new();
-    ver.build = Vec::new();
-    ver
-}
-
-#[test]
-fn all_the_fields() {
-    // All the fields currently generated as of 1.41. This tries to exercise as
-    // much as possible.
-    let ver = cargo_version();
-    let minimum = semver::Version::parse("1.41.0").unwrap();
-    if ver < minimum {
-        // edition added in 1.30
-        // rename added in 1.31
-        // links added in 1.33
-        // doctest added in 1.37
-        // publish added in 1.39
-        // dep_kinds added in 1.41
-        eprintln!("Skipping all_the_fields test, cargo {} is too old.", ver);
-        return;
-    }
-    let meta = MetadataCommand::new()
-        .manifest_path("tests/all/Cargo.toml")
-        .exec()
-        .unwrap();
-    assert_eq!(
-        meta.workspace_root.file_name().unwrap(),
-        PathBuf::from("all")
-    );
-    assert_eq!(meta.workspace_members.len(), 1);
-    assert!(meta.workspace_members[0].to_string().starts_with("all"));
-
-    assert_eq!(meta.packages.len(), 9);
-    let all = meta.packages.iter().find(|p| p.name == "all").unwrap();
-    assert_eq!(all.version, semver::Version::parse("0.1.0").unwrap());
-    assert_eq!(all.authors, vec!["Jane Doe <user@example.com>"]);
-    assert!(all.id.to_string().starts_with("all"));
-    assert_eq!(all.description, Some("Package description.".to_string()));
-    assert_eq!(all.license, Some("MIT/Apache-2.0".to_string()));
-    assert_eq!(all.license_file, Some(PathBuf::from("LICENSE")));
-    assert!(all.license_file().unwrap().ends_with("tests/all/LICENSE"));
-    assert_eq!(all.publish, Some(vec![]));
-    assert_eq!(all.links, Some("foo".to_string()));
-
-    assert_eq!(all.dependencies.len(), 8);
-    let bitflags = all
-        .dependencies
-        .iter()
-        .find(|d| d.name == "bitflags")
-        .unwrap();
-    assert_eq!(
-        bitflags.source,
-        Some("registry+https://github.com/rust-lang/crates.io-index".to_string())
-    );
-    assert_eq!(bitflags.optional, true);
-    assert_eq!(bitflags.req, semver::VersionReq::parse("^1.0").unwrap());
-
-    let path_dep = all
-        .dependencies
-        .iter()
-        .find(|d| d.name == "path-dep")
-        .unwrap();
-    assert_eq!(path_dep.source, None);
-    assert_eq!(path_dep.kind, DependencyKind::Normal);
-    assert_eq!(path_dep.req, semver::VersionReq::parse("*").unwrap());
-
-    all.dependencies
-        .iter()
-        .find(|d| d.name == "namedep")
-        .unwrap();
-
-    let featdep = all
-        .dependencies
-        .iter()
-        .find(|d| d.name == "featdep")
-        .unwrap();
-    assert_eq!(featdep.features, vec!["i128"]);
-    assert_eq!(featdep.uses_default_features, false);
-
-    let renamed = all
-        .dependencies
-        .iter()
-        .find(|d| d.name == "oldname")
-        .unwrap();
-    assert_eq!(renamed.rename, Some("newname".to_string()));
-
-    let devdep = all
-        .dependencies
-        .iter()
-        .find(|d| d.name == "devdep")
-        .unwrap();
-    assert_eq!(devdep.kind, DependencyKind::Development);
-
-    let bdep = all.dependencies.iter().find(|d| d.name == "bdep").unwrap();
-    assert_eq!(bdep.kind, DependencyKind::Build);
-
-    let windep = all
-        .dependencies
-        .iter()
-        .find(|d| d.name == "windep")
-        .unwrap();
-    assert_eq!(
-        windep.target.as_ref().map(|x| x.to_string()),
-        Some("cfg(windows)".to_string())
-    );
-
-    macro_rules! get_file_name {
-        ($v:expr) => {
-            all.targets
-                .iter()
-                .find(|t| t.src_path.file_name().unwrap() == $v)
-                .unwrap()
-        };
-    }
-    assert_eq!(all.targets.len(), 8);
-    let lib = get_file_name!("lib.rs");
-    assert_eq!(lib.name, "all");
-    assert_eq!(
-        sorted!(lib.kind),
-        vec!["cdylib", "dylib", "rlib", "staticlib"]
-    );
-    assert_eq!(
-        sorted!(lib.crate_types),
-        vec!["cdylib", "dylib", "rlib", "staticlib"]
-    );
-    assert_eq!(lib.required_features.len(), 0);
-    assert_eq!(lib.edition, "2018");
-    assert_eq!(lib.doctest, true);
-
-    let main = get_file_name!("main.rs");
-    assert_eq!(main.crate_types, vec!["bin"]);
-    assert_eq!(main.kind, vec!["bin"]);
-    assert_eq!(main.doctest, false);
-
-    let otherbin = get_file_name!("otherbin.rs");
-    assert_eq!(otherbin.edition, "2015");
-
-    let reqfeat = get_file_name!("reqfeat.rs");
-    assert_eq!(reqfeat.required_features, vec!["feat2"]);
-
-    let ex1 = get_file_name!("ex1.rs");
-    assert_eq!(ex1.kind, vec!["example"]);
-
-    let t1 = get_file_name!("t1.rs");
-    assert_eq!(t1.kind, vec!["test"]);
-
-    let b1 = get_file_name!("b1.rs");
-    assert_eq!(b1.kind, vec!["bench"]);
-
-    let build = get_file_name!("build.rs");
-    assert_eq!(build.kind, vec!["custom-build"]);
-
-    assert_eq!(all.features.len(), 3);
-    assert_eq!(all.features["feat1"].len(), 0);
-    assert_eq!(all.features["feat2"].len(), 0);
-    assert_eq!(sorted!(all.features["default"]), vec!["bitflags", "feat1"]);
-
-    assert!(all.manifest_path.ends_with("all/Cargo.toml"));
-    assert_eq!(all.categories, vec!["command-line-utilities"]);
-    assert_eq!(all.keywords, vec!["cli"]);
-    assert_eq!(all.readme, Some(PathBuf::from("README.md")));
-    assert_eq!(
-        all.repository,
-        Some("https://github.com/oli-obk/cargo_metadata/".to_string())
-    );
-    assert_eq!(all.edition, "2018");
-    assert_eq!(
-        all.metadata,
-        json!({
-            "docs": {
-                "rs": {
-                    "all-features": true,
-                    "default-target": "x86_64-unknown-linux-gnu",
-                    "rustc-args": ["--example-rustc-arg"]
-                }
-            }
-        })
-    );
-
-    let resolve = meta.resolve.as_ref().unwrap();
-    assert!(resolve
-        .root
-        .as_ref()
-        .unwrap()
-        .to_string()
-        .starts_with("all"));
-
-    assert_eq!(resolve.nodes.len(), 9);
-    let path_dep = resolve
-        .nodes
-        .iter()
-        .find(|n| n.id.to_string().starts_with("path-dep"))
-        .unwrap();
-    assert_eq!(path_dep.deps.len(), 0);
-    assert_eq!(path_dep.dependencies.len(), 0);
-    assert_eq!(path_dep.features.len(), 0);
-
-    let bitflags = resolve
-        .nodes
-        .iter()
-        .find(|n| n.id.to_string().starts_with("bitflags"))
-        .unwrap();
-    assert_eq!(bitflags.features, vec!["default"]);
-
-    let featdep = resolve
-        .nodes
-        .iter()
-        .find(|n| n.id.to_string().starts_with("featdep"))
-        .unwrap();
-    assert_eq!(featdep.features, vec!["i128"]);
-
-    let all = resolve
-        .nodes
-        .iter()
-        .find(|n| n.id.to_string().starts_with("all"))
-        .unwrap();
-    assert_eq!(all.dependencies.len(), 8);
-    assert_eq!(all.deps.len(), 8);
-    let newname = all.deps.iter().find(|d| d.name == "newname").unwrap();
-    assert!(newname.pkg.to_string().starts_with("oldname"));
-    // Note the underscore here.
-    let path_dep = all.deps.iter().find(|d| d.name == "path_dep").unwrap();
-    assert!(path_dep.pkg.to_string().starts_with("path-dep"));
-    assert_eq!(path_dep.dep_kinds.len(), 1);
-    let kind = &path_dep.dep_kinds[0];
-    assert_eq!(kind.kind, DependencyKind::Normal);
-    assert!(kind.target.is_none());
-
-    let namedep = all
-        .deps
-        .iter()
-        .find(|d| d.name == "different_name")
-        .unwrap();
-    assert!(namedep.pkg.to_string().starts_with("namedep"));
-    assert_eq!(sorted!(all.features), vec!["bitflags", "default", "feat1"]);
-
-    let bdep = all.deps.iter().find(|d| d.name == "bdep").unwrap();
-    assert_eq!(bdep.dep_kinds.len(), 1);
-    let kind = &bdep.dep_kinds[0];
-    assert_eq!(kind.kind, DependencyKind::Build);
-    assert!(kind.target.is_none());
-
-    let devdep = all.deps.iter().find(|d| d.name == "devdep").unwrap();
-    assert_eq!(devdep.dep_kinds.len(), 1);
-    let kind = &devdep.dep_kinds[0];
-    assert_eq!(kind.kind, DependencyKind::Development);
-    assert!(kind.target.is_none());
-
-    let windep = all.deps.iter().find(|d| d.name == "windep").unwrap();
-    assert_eq!(windep.dep_kinds.len(), 1);
-    let kind = &windep.dep_kinds[0];
-    assert_eq!(kind.kind, DependencyKind::Normal);
-    assert_eq!(
-        kind.target.as_ref().map(|x| x.to_string()),
-        Some("cfg(windows)".to_string())
-    );
-}
-
-#[test]
-fn alt_registry() {
-    // This is difficult to test (would need to set up a custom index).
-    // Just manually check the JSON is handled.
-    let json = r#"
-{
-  "packages": [
-    {
-      "name": "alt",
-      "version": "0.1.0",
-      "id": "alt 0.1.0 (path+file:///alt)",
-      "source": null,
-      "dependencies": [
-        {
-          "name": "alt2",
-          "source": "registry+https://example.com",
-          "req": "^0.1",
-          "kind": null,
-          "rename": null,
-          "optional": false,
-          "uses_default_features": true,
-          "features": [],
-          "target": null,
-          "registry": "https://example.com"
-        }
-      ],
-      "targets": [
-        {
-          "kind": [
-            "lib"
-          ],
-          "crate_types": [
-            "lib"
-          ],
-          "name": "alt",
-          "src_path": "/alt/src/lib.rs",
-          "edition": "2018"
-        }
-      ],
-      "features": {},
-      "manifest_path": "/alt/Cargo.toml",
-      "metadata": null,
-      "authors": [],
-      "categories": [],
-      "keywords": [],
-      "readme": null,
-      "repository": null,
-      "edition": "2018",
-      "links": null
-    }
-  ],
-  "workspace_members": [
-    "alt 0.1.0 (path+file:///alt)"
-  ],
-  "resolve": null,
-  "target_directory": "/alt/target",
-  "version": 1,
-  "workspace_root": "/alt"
-}
-"#;
-    let meta: Metadata = serde_json::from_str(json).unwrap();
-    assert_eq!(meta.packages.len(), 1);
-    let alt = &meta.packages[0];
-    let deps = &alt.dependencies;
-    assert_eq!(deps.len(), 1);
-    let dep = &deps[0];
-    assert_eq!(dep.registry, Some("https://example.com".to_string()));
-}
-
-#[test]
-fn current_dir() {
-    let meta = MetadataCommand::new()
-        .current_dir("tests/all/namedep")
-        .exec()
-        .unwrap();
-    let namedep = meta.packages.iter().find(|p| p.name == "namedep").unwrap();
-    assert!(namedep.name.starts_with("namedep"));
-}
-
-#[test]
-fn parse_stream_is_robust() {
-    // Proc macros can print stuff to stdout, which naturally breaks JSON messages.
-    // Let's check that we don't die horribly in this case, and report an error.
-    let json_output = r##"{"reason":"compiler-artifact","package_id":"chatty 0.1.0 (path+file:///chatty-macro/chatty)","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"chatty","src_path":"/chatty-macro/chatty/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/deps/libchatty-f2adcff24cdf3bb2.so"],"executable":null,"fresh":false}
-Evil proc macro was here!
-{"reason":"compiler-artifact","package_id":"chatty-macro 0.1.0 (path+file:///chatty-macro)","target":{"kind":["lib"],"crate_types":["lib"],"name":"chatty-macro","src_path":"/chatty-macro/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/libchatty_macro.rlib","/chatty-macro/target/debug/deps/libchatty_macro-cb5956ed52a11fb6.rmeta"],"executable":null,"fresh":false}
-"##;
-    let mut n_messages = 0;
-    let mut text = String::new();
-    for message in cargo_metadata::Message::parse_stream(json_output.as_bytes()) {
-        let message = message.unwrap();
-        match message {
-            cargo_metadata::Message::TextLine(line) => text = line,
-            _ => n_messages += 1,
-        }
-    }
-    assert_eq!(n_messages, 2);
-    assert_eq!(text, "Evil proc macro was here!");
-}
-
-#[test]
-fn advanced_feature_configuration() {
-    fn build_features<F: FnOnce(&mut MetadataCommand) -> &mut MetadataCommand>(
-        func: F,
-    ) -> Vec<String> {
-        let mut meta = MetadataCommand::new();
-        let meta = meta.manifest_path("tests/all/Cargo.toml");
-
-        let meta = func(meta);
-        let meta = meta.exec().unwrap();
-
-        let resolve = meta.resolve.as_ref().unwrap();
-
-        let all = resolve
-            .nodes
-            .iter()
-            .find(|n| n.id.to_string().starts_with("all"))
-            .unwrap();
-
-        all.features.clone()
-    }
-
-    // Default behavior; tested above
-    let default_features = build_features(|meta| meta);
-    assert_eq!(
-        sorted!(default_features),
-        vec!["bitflags", "default", "feat1"]
-    );
-
-    // Manually specify the same default features
-    let manual_features = build_features(|meta| {
-        meta.features(CargoOpt::NoDefaultFeatures)
-            .features(CargoOpt::SomeFeatures(vec![
-                "feat1".into(),
-                "bitflags".into(),
-            ]))
-    });
-    assert_eq!(sorted!(manual_features), vec!["bitflags", "feat1"]);
-
-    // Multiple SomeFeatures is same as one longer SomeFeatures
-    let manual_features = build_features(|meta| {
-        meta.features(CargoOpt::NoDefaultFeatures)
-            .features(CargoOpt::SomeFeatures(vec!["feat1".into()]))
-            .features(CargoOpt::SomeFeatures(vec!["feat2".into()]))
-    });
-    assert_eq!(sorted!(manual_features), vec!["feat1", "feat2"]);
-
-    // No features + All features == All features
-    let all_features = build_features(|meta| {
-        meta.features(CargoOpt::AllFeatures)
-            .features(CargoOpt::NoDefaultFeatures)
-    });
-    assert_eq!(
-        sorted!(all_features),
-        vec!["bitflags", "default", "feat1", "feat2"]
-    );
-
-    // The '--all-features' flag supersedes other feature flags
-    let all_flag_variants = build_features(|meta| {
-        meta.features(CargoOpt::SomeFeatures(vec!["feat2".into()]))
-            .features(CargoOpt::NoDefaultFeatures)
-            .features(CargoOpt::AllFeatures)
-    });
-    assert_eq!(sorted!(all_flag_variants), sorted!(all_features));
-}
index c502b416a56e00539056175369cf98067249f2a2..a68b5560106d03e5b4bf9a3975939fd5254f2950 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.lock":"24720bf62cfad67ca24dfc9192a8f1c11a0f262655c087795605f188cee5c5f0","Cargo.toml":"84ef3b052c7b9ba469573df3ee45d89d426f2cd30d350f43198f115b9c5691fc","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"9916275542d23bfa0815b1f48d4546e514739fadc79775500de6a81cf17aac09","src/bin/gcc-shim.rs":"b77907875029494b6288841c3aed2e4939ed40708c7f597fca5c9e2570490ca6","src/com.rs":"bcdaf1c28b71e6ef889c6b08d1ce9d7c0761344a677f523bc4c3cd297957f804","src/lib.rs":"20d349f8528f191a4cf04a5a42daaaa8085c4e00885c78456ebada92dc39b7fb","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"7014103587d3382eac599cb76f016e2609b8140970861b2237982d1db24af265","src/vs_instances.rs":"2d3f8278a803b0e7052f4eeb1979b29f963dd0143f4458e2cb5f33c4e5f0963b","src/winapi.rs":"ea8b7edbb9ff87957254f465c2334e714c5d6b3b19a8d757c48ea7ca0881c50c","src/windows_registry.rs":"090b5de68e19dab9e1884175dc2a6866f697bd043d6b3a0d4b3836c9d6812569","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"16274867f23871e9b07614eda4c7344da13d1751fed63d4f633857e40be86394","tests/test.rs":"65c073e0e2cf4aa0433066102788e9f57442719e6f32f5ad5248aa7132bb4597"},"package":"4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"}
\ No newline at end of file
+{"files":{"Cargo.lock":"5c2221d3b4ee85a8b63b3022d72aeda3c20874356d6709e7af7fe8f045e7245c","Cargo.toml":"ebad046bf7fb7185e9328693ba79bd4b1f784e6569eab5640eb828cd148bb7b8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"9916275542d23bfa0815b1f48d4546e514739fadc79775500de6a81cf17aac09","src/bin/gcc-shim.rs":"b77907875029494b6288841c3aed2e4939ed40708c7f597fca5c9e2570490ca6","src/com.rs":"bcdaf1c28b71e6ef889c6b08d1ce9d7c0761344a677f523bc4c3cd297957f804","src/lib.rs":"6dde684bdcc1bb03a808784ce8ccc0721f53bfdf87b84c607045aada916730ba","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"7014103587d3382eac599cb76f016e2609b8140970861b2237982d1db24af265","src/vs_instances.rs":"2d3f8278a803b0e7052f4eeb1979b29f963dd0143f4458e2cb5f33c4e5f0963b","src/winapi.rs":"ea8b7edbb9ff87957254f465c2334e714c5d6b3b19a8d757c48ea7ca0881c50c","src/windows_registry.rs":"d8f3014140d637b50a1fa4a9739b3617299ab43f829e65b2728f515a969a5376","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"16274867f23871e9b07614eda4c7344da13d1751fed63d4f633857e40be86394","tests/test.rs":"65c073e0e2cf4aa0433066102788e9f57442719e6f32f5ad5248aa7132bb4597"},"package":"e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"}
\ No newline at end of file
index 9f1103f02cabac12d7face5f15448f03a950045b..82218644f6af0a1031634906513346d731bedee9 100644 (file)
@@ -1,8 +1,10 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
+version = 3
+
 [[package]]
 name = "cc"
-version = "1.0.68"
+version = "1.0.69"
 dependencies = [
  "jobserver",
  "tempfile",
index f2467799bbbcc6199192b1ab678defef93092433..7ff23b200eee81f53daba26b3c6a4e67930ee617 100644 (file)
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "cc"
-version = "1.0.68"
+version = "1.0.69"
 authors = ["Alex Crichton <alex@alexcrichton.com>"]
 exclude = ["/.github", "/.travis.yml", "/appveyor.yml"]
 description = "A build-time dependency for Cargo build scripts to assist in invoking the native\nC compiler to compile native C code into a static archive to be linked into Rust\ncode.\n"
index 9d133a0d1a2b405452f9442f7a55f5d34e1c1ae9..b62a1da0407dbd6b8b42af6f1f8ca64a28a9c146 100644 (file)
@@ -732,7 +732,7 @@ impl Build {
     /// This option sets the `-stdlib` flag, which is only supported by some
     /// compilers (clang, icc) but not by others (gcc). The library will not
     /// detect which compiler is used, as such it is the responsibility of the
-    /// caller to ensure that this option is only used in conjuction with a
+    /// caller to ensure that this option is only used in conjunction with a
     /// compiler which supports the `-stdlib` flag.
     ///
     /// A value of `None` indicates that no specific C++ standard library should
@@ -1484,6 +1484,10 @@ impl Build {
                                 .into(),
                             );
                         }
+                    } else if target.starts_with("riscv64gc-") {
+                        cmd.args.push(
+                            format!("--target={}", target.replace("riscv64gc", "riscv64")).into(),
+                        );
                     } else {
                         cmd.args.push(format!("--target={}", target).into());
                     }
@@ -1849,7 +1853,7 @@ impl Build {
             for flag in self.ar_flags.iter() {
                 cmd.arg(flag);
             }
-            // If the library file already exists, add the libary name
+            // If the library file already exists, add the library name
             // as an argument to let lib.exe know we are appending the objs.
             if dst.exists() {
                 cmd.arg(dst);
@@ -2124,7 +2128,7 @@ impl Build {
         //
         // As the shell script calls the main clang binary, the command line limit length
         // on Windows is restricted to around 8k characters instead of around 32k characters.
-        // To remove this limit, we call the main clang binary directly and contruct the
+        // To remove this limit, we call the main clang binary directly and construct the
         // `--target=` ourselves.
         if host.contains("windows") && android_clang_compiler_uses_target_arg_internally(&tool.path)
         {
@@ -2652,7 +2656,7 @@ impl Tool {
     }
 
     #[cfg(windows)]
-    /// Explictly set the `ToolFamily`, skipping name-based detection.
+    /// Explicitly set the `ToolFamily`, skipping name-based detection.
     fn with_family(path: PathBuf, family: ToolFamily) -> Self {
         Self {
             path: path,
@@ -3086,6 +3090,12 @@ fn map_darwin_target_from_rust_to_compiler_architecture(target: &str) -> Option<
         Some("arm64e")
     } else if target.contains("aarch64") {
         Some("arm64")
+    } else if target.contains("i686") {
+        Some("i386")
+    } else if target.contains("powerpc") {
+        Some("ppc")
+    } else if target.contains("powerpc64") {
+        Some("ppc64")
     } else {
         None
     }
index 40101a69b04aada6141dceb8b9207afbb537d3d3..d2d212c798741abd07de2ec52c712c4ef49b4e9d 100644 (file)
@@ -129,7 +129,7 @@ pub fn find_vs_version() -> Result<VsVers, String> {
             )),
         },
         _ => {
-            // Check for the presense of a specific registry key
+            // Check for the presence of a specific registry key
             // that indicates visual studio is installed.
             if impl_::has_msbuild_version("16.0") {
                 Ok(VsVers::Vs16)
@@ -277,6 +277,9 @@ mod impl_ {
                 if target.contains("x86_64") {
                     tool.env.push(("Platform".into(), "X64".into()));
                 }
+                if target.contains("aarch64") {
+                    tool.env.push(("Platform".into(), "ARM64".into()));
+                }
                 Some(tool)
             })
             .next()
@@ -407,6 +410,9 @@ mod impl_ {
             if target.contains("x86_64") {
                 tool.env.push(("Platform".into(), "X64".into()));
             }
+            if target.contains("aarch64") {
+                tool.env.push(("Platform".into(), "ARM64".into()));
+            }
             tool
         })
     }
@@ -676,7 +682,7 @@ mod impl_ {
 
     // Interestingly there are several subdirectories, `win7` `win8` and
     // `winv6.3`. Vcvars seems to only care about `winv6.3` though, so the same
-    // applies to us. Note that if we were targetting kernel mode drivers
+    // applies to us. Note that if we were targeting kernel mode drivers
     // instead of user mode applications, we would care.
     fn get_sdk81_dir() -> Option<PathBuf> {
         let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.1";
@@ -810,10 +816,12 @@ mod impl_ {
             "16.0" => {
                 find_msbuild_vs16("x86_64-pc-windows-msvc").is_some()
                     || find_msbuild_vs16("i686-pc-windows-msvc").is_some()
+                    || find_msbuild_vs16("aarch64-pc-windows-msvc").is_some()
             }
             "15.0" => {
                 find_msbuild_vs15("x86_64-pc-windows-msvc").is_some()
                     || find_msbuild_vs15("i686-pc-windows-msvc").is_some()
+                    || find_msbuild_vs15("aarch64-pc-windows-msvc").is_some()
             }
             "12.0" | "14.0" => LOCAL_MACHINE
                 .open(&OsString::from(format!(
index 10e56146d2a286f93f8785b1536a1b72698bc09a..e034df1fea7ff5075b65b4cea66cb5ae0a87d424 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.lock":"1e8987e85314772030365448b9f45d80e779b757da4d862fc00a4359fac8521a","Cargo.toml":"e943fd04b356c20f30ebd7db38b1635c3e1d0dd3bb1bbbd5b9b736d59a1e20b5","README.md":"2dd28b207028773ffee09ed0db563ac71b255b6b67256289d67a13cb19d15f94","build.rs":"171c7c0f63a78478b5410851d929f05dad575cd6cf19aaf23e28460153bf7129","examples/intrinsics.rs":"c4cdcc9f777e528fa54cb3bc3d6da4239373b8f9a5cdfe7bdf1df4598eaab64f","libm/src/math/acos.rs":"fb066ba84aba1372d706425ec14f35ff8d971756d15eeebd22ecf42a716493bb","libm/src/math/acosf.rs":"a112b82309bba1d35c4e3d6ad4d6c21ef305343d9ab601ddf4bc61d43bc9f1af","libm/src/math/acosh.rs":"56dac8538e4350cd7cf001327c89f087b68abb2e6aaad58edba8a094b09f6b0f","libm/src/math/acoshf.rs":"df5b0c4d8e37e64cf5ff2d8328b28bc35c78e84060ff769e64523ea9ff9065c1","libm/src/math/asin.rs":"095a1e98996daff45df0b154ca0ec35bbf31db964ee9fdda0207308cb20df441","libm/src/math/asinf.rs":"49cccb4db2881982643a4a7d5453f4f8daf527711bbb67313607a3c178856d61","libm/src/math/asinh.rs":"e8fc94031015fddf35e9c26b94da9f6431ee17c81cd7bd37da8ffc98f7e0b32c","libm/src/math/asinhf.rs":"8a0b8933a98a17617a66fef4c7b89eba645fdf05302000babf4a5a5f45328430","libm/src/math/atan.rs":"d4fe46e1c5739dd09997869dcfbc3c85f03c534af52e700d6c6bcf9c3fedda07","libm/src/math/atan2.rs":"2623bc8ca707d13a7092ce49adf68e9cbf4452ad1bf4a861dc40ca858606a747","libm/src/math/atan2f.rs":"dd01943e0e1f1955912e5c3ffc9467529cf64bd02ac0a6ad5ab31dbe6657f05d","libm/src/math/atanf.rs":"e41b41569474a59c970ede3538e00bda4072cf4d90040017101cc79d7dc28caa","libm/src/math/atanh.rs":"5934dbd6b7395ca4f103ace7598da723a9270e1cf6b47e7f786debe4bb3651ff","libm/src/math/atanhf.rs":"8ba4711dda19ef2dc33622be65c1483902868083543198c6bbd040d4026293de","libm/src/math/cbrt.rs":"f2c45612d2eecd93cfcdd9ebf824c754fc8f8dfd6d16862c0b9c4ccea78c2a0f","libm/src/math/cbrtf.rs":"ad0b483854aa9f17a44d36c049bf0e8ebab34c27e90b787c05f45cc230ec7d19","libm/src/math/ceil.rs":"0e6caff1597818471c28b7c3226dbfe9976fdb38ace5246172ac030754be6b79","libm/src/math/ceilf.rs":"f942bcea617de7da880b68bdfe676837a7984e2a887eaafe181be24c6bc13cc2","libm/src/math/copysign.rs":"d80c880efaf0cdf2ce0a4d4f5a68dd6c36c88d46fa997ec8ac8604bfdb26fa33","libm/src/math/copysignf.rs":"1547116071e68a42b1605eb2fc722db6466a34517dc96b92de1f29a274c3d8e3","libm/src/math/cos.rs":"74babdc13ede78e400c5ca1854c3e22d2e08cbdc5618aefa5bba6f9303ef65b6","libm/src/math/cosf.rs":"09c40f93c445b741e22477ceedf163ca33b6a47f973f7c9876cfba2692edb29c","libm/src/math/cosh.rs":"0d0a7cef18577f321996b8b87561963139f754ad7f2ea0a3b3883811f3f0693a","libm/src/math/coshf.rs":"be8ca8739e4cf1978425b349f941cb4838bba8c10cb559c7940b9fd4fdde21ad","libm/src/math/erf.rs":"9c55fc6756ba816996f0b585e07ccfa4cd87575ad525cd30c4a968b30acffda3","libm/src/math/erff.rs":"cb020e8bada9a54573a11fe3271750d73f14fed3092a881a9ceaf98fe32fd5a6","libm/src/math/exp.rs":"ca7405ad0d1993fffcf9aae96f9256307bed3c4916545aaebd1cf1d2df1807fa","libm/src/math/exp10.rs":"2deb037f88feac87a0e924b69dd496f0dd3b5d35f2a58e09d4c5166b207e517b","libm/src/math/exp10f.rs":"6979464dfe3f4f2da1f9afc909646499c4bfaef15e10a039384750e2f1586fea","libm/src/math/exp2.rs":"94a9304a2ce3bc81f6d2aefd3cde6faa30f13260d46cb13692863cdea1c9a3a1","libm/src/math/exp2f.rs":"785f2630accd35118ec07bf60273e219ed91a215b956b1552eeea5bc2a708cc8","libm/src/math/expf.rs":"ec14c18f891a9e37735ec39e6fc2e9bf674a2c2e083f22e2533b481177359c98","libm/src/math/expm1.rs":"124069f456c8ad331f265c7509d9e223b2a300e461bbfd3d6adfdcdd2ee5b8ac","libm/src/math/expm1f.rs":"18e2116d31ea8410051cc709b9d04b754b0e3ba6758ee1bf0b48749f4999b840","libm/src/math/expo2.rs":"4f4f9fecfccb43f30c2784aa7c0bb656754a52b8ab431f7d1b551c673ab133f1","libm/src/math/fabs.rs":"e6c7db39f98508098cdf64ac0c2f53866c466149a7490afb9fe22b44c4dd81b3","libm/src/math/fabsf.rs":"dc85b66e4ef662721276ae3a301af22795524e4367ee8dd40f0c24c439773c6d","libm/src/math/fdim.rs":"8ec091996005207297c2389ae563e1b18dbc6a9eac951de29a976c5cd7bc32a7","libm/src/math/fdimf.rs":"c7f3f2269834d55be26b6580ddc07c42531577955fa4de35bad1e2a361085614","libm/src/math/fenv.rs":"8730d45aa4c591f91dccdcc1ce533fa23e9c6df0c38defb9c57f749cb25e1cd0","libm/src/math/floor.rs":"be15e687a6798defc6f2c6b43028481f8104fb93d2b3f359d3d5d16b78e79d4f","libm/src/math/floorf.rs":"4ec41aa64cfafd23b8cfc043eacea5e9125cca5dcb3f5e655cc3d3458c6ba2c5","libm/src/math/fma.rs":"6872e79787e9270520189b53608f602b8ad5a099f3cef10ad5b9e0c06ef01fe0","libm/src/math/fmaf.rs":"3e0f5727e56f31218f674b9b8975d7e67b3a24a097f06a2a3eca9723cd786213","libm/src/math/fmax.rs":"f6c8e96a8b1a170648d2fa3513e7b6b459085d708c839869f82e305fe58fac37","libm/src/math/fmaxf.rs":"dff0025433232e8a5ec7bd54d847ccf596d762ea4e35f5c54fbaac9404d732fd","libm/src/math/fmin.rs":"95b6cb66ca0e0e22276f0bf88dbe8fb69796a69a196a7491bd4802efbcf2e298","libm/src/math/fminf.rs":"304bc839b15ea3d84e68d2af9f40524ec120d30a36a667b22fcb98a6c258f4c7","libm/src/math/fmod.rs":"a1c0550fc7df8164733d914e222ff0966a2ab886d6e75a1098f24fe0283ae227","libm/src/math/fmodf.rs":"ee51ed092c0eeb8195f35735ff725cfd46612e0d689a7c483538bd92fbe61828","libm/src/math/frexp.rs":"28af70026922a8ab979744c7ad4d8faba6079c4743b7eeb6d14c983a982fbbcc","libm/src/math/frexpf.rs":"2e2593ae8002ba420809ebfaf737ef001cdc912354be3d978a8c0cb930350d4d","libm/src/math/hypot.rs":"841131c4a0cea75bc8a86e29f3f6d0815a61fc99731c9984651ce83d3050d218","libm/src/math/hypotf.rs":"5f317323edc2eb699580fe54b074b7e570a7734d51a0a149c0b49b54470a836c","libm/src/math/ilogb.rs":"813413bf6266d4fc40db9c5921af3cef4f892ba93e8f6d9efe62a449d1234532","libm/src/math/ilogbf.rs":"dec462780f46682e16cfaa733238bed3b692729e951f53a44726100b6c73a716","libm/src/math/j0.rs":"9572b6396c489927d332d0e717920e61ec0618e5e9c31f7eeeec70f5e4abab06","libm/src/math/j0f.rs":"802c8254bded9b3afb6eea8b9af240038a5a4a5d811396729f69ca509e3e7d87","libm/src/math/j1.rs":"97b1af1611fa3d110c2b349ee8e4176100132ea1391b619086b47ac063b81803","libm/src/math/j1f.rs":"1d504d7750c0481273baad88196d3644f258af9ad10f8b5b16341c0aab8b9125","libm/src/math/jn.rs":"847d122334e5707ad9627146cddccc082a1f2f5bcd3e5ef54399013a7007ce88","libm/src/math/jnf.rs":"4045076f7d1a1b89882ed60d4dd60a4cbbc66b85cfb90491378c8015effcc476","libm/src/math/k_cos.rs":"f34a69e44d6b8901b03b578a75972f438ab20a7b98a0903fc1903d6fde3899be","libm/src/math/k_cosf.rs":"8f7117ff21cebf8e890a5bcfd7ea858a94172f4172b79a66d53824c2cb0888b1","libm/src/math/k_expo2.rs":"eb4ca9e6a525b7ea6da868c3cb136896682cc46f8396ba2a2ebc3ae9e9ba54b0","libm/src/math/k_expo2f.rs":"d51ad5df61cb5d1258bdb90c52bfed4572bb446a9337de9c04411ed9454ae0cb","libm/src/math/k_sin.rs":"14b2aba6ca07150c92768b5a72acaf5cde6a11d6619e14896512a7ba242e289a","libm/src/math/k_sinf.rs":"2775fcc710807164e6f37a4f8da3c8143cd5f16e19ce7c31c5591522151d7a96","libm/src/math/k_tan.rs":"a72beae4ccd9631eeeb61d6365bbeecae81c8411f3120a999c515cca0d5ea5c5","libm/src/math/k_tanf.rs":"6a794be56fa4b2f60452b9bab19af01c388f174560acbf829a351378ea39495d","libm/src/math/ldexp.rs":"b647f0096e80e4d926d8dd18d294c892ee2cb1778effe2c5e1b2664ae5cb1a4e","libm/src/math/ldexpf.rs":"98743fad2cd97a7be496f40ba3157ac1438fce0d0c25d5ab90c3b8c71c3fd0ed","libm/src/math/lgamma.rs":"498552658cc8106d7754f85ae8dbc3306ac2f0a9f7eb5a796be70c5beac92c41","libm/src/math/lgamma_r.rs":"77fb6442aeb5343926d8965e1549dde3e2cc4fd09555de6b56506001d956c344","libm/src/math/lgammaf.rs":"457105f53a4c8717e8f5a117d261dcf94e222e83981337fe23602abe883fe3f7","libm/src/math/lgammaf_r.rs":"44de75babbdd53c4a5879cd6f426e7311db82669def39df5f63914d67d6cc1b1","libm/src/math/log.rs":"b5e0c5f30d9e94351488732801be3107c12b854c3f95ad37e256dd88eeca408f","libm/src/math/log10.rs":"3425ff8be001fd1646ba15e254eb6ef4bdc6ccaf0cbee27ddf1fa84e04178b90","libm/src/math/log10f.rs":"fee4f71879bc4c99259e68c0c641364901629fb29a8ebddfcc0d090102cceddd","libm/src/math/log1p.rs":"9cf400852f165e6be19b97036ae9521fb9ca857d0a9a91c117d9123221622185","libm/src/math/log1pf.rs":"2716e6d2afa271996b7c8f47fd9e4952c88f4c1fd8c07c3e8ce8c62794bf71d8","libm/src/math/log2.rs":"dbbbfbaaa8aa6a4dbefea554ea3983090a9691228b011910c751f6adca912c40","libm/src/math/log2f.rs":"92a90350d8edce21c31c285c3e620fca7c62a2366008921715945c2c73b5b79f","libm/src/math/logf.rs":"845342cffc34d3db1f5ec12d8e5b773cd5a79056e28662fcb9bcd80207596f50","libm/src/math/mod.rs":"ffa73c08f4c0a4dc6c9d1cb9d62fe97f3a5046edede128c9441cc3adc9170dd3","libm/src/math/modf.rs":"d012ed5a708ef52b6d1313c22a46cadaf5764dde1220816e3df2f03a0fcc60ae","libm/src/math/modff.rs":"f8f1e4c27a85d2cdb3c8e74439d59ef64aa543b948f22c23227d02d8388d61c2","libm/src/math/nextafter.rs":"3282e7eef214a32736fb6928d490198ad394b26b402b45495115b104839eebfe","libm/src/math/nextafterf.rs":"0937dc8a8155c19842c12181e741cec1f7df1f7a00cee81fcb2475e2842761b7","libm/src/math/pow.rs":"64fba587143fa88cdfa5c9d30b658ab03e3a19e3ea3759394836add4068983c6","libm/src/math/powf.rs":"2c423a0ea57fdc4e20f3533f744c6e6288c998b4de8f2914fafaa0e78be81b04","libm/src/math/rem_pio2.rs":"9be99c44493b2b7088578c0fa2872630725b2da544c751516df0c6c686112a43","libm/src/math/rem_pio2_large.rs":"21762d08d72dc6f2e313123a7311683000974a09b8fcae50994d9c39239721b1","libm/src/math/rem_pio2f.rs":"377349d1308bda8cd2f776e4856fe090baa78fa3db816b680780ddf31b80d446","libm/src/math/remainder.rs":"63865f4370853c476b45bb27a5c54a4072146aa4a626835ae5263871a4e7e5dc","libm/src/math/remainderf.rs":"dd3fa432dbda8f2135428198be7bd69c57f8d13df3f365b12f52bf6a82352ac4","libm/src/math/remquo.rs":"3cc0bf55069f165c4843f2c358b3a27279c01e8cdd99f9057a3f7f31f45408f2","libm/src/math/remquof.rs":"cc749e18ecb7e766b8b8eeabdbf89ac99087d3d587e71e30f690676a3d2c1f9b","libm/src/math/round.rs":"955649c893fa3151b4a81c8e550fbc03f01bb99b40d60986e5f153ee71043f69","libm/src/math/roundf.rs":"8ae8f1f71eedd158566771cfe80b352d2f13c170a0ce8dc2691a14e8a791cfbb","libm/src/math/scalbn.rs":"b5c9d6d4177fe393cbfe1c634d75ce14b754f6cbce87c5bf979a9661491748a2","libm/src/math/scalbnf.rs":"4f198d06db1896386256fb9a5ac5b805b16b836226c18780a475cf18d7c1449c","libm/src/math/sin.rs":"0e014e6377c9673a73395ab2ffcf5962e512392afddf8a4e731fb694098faf34","libm/src/math/sincos.rs":"59e9f196140681fa817652134b8d1bdd2d6dd47bb8557b0346c77b176389f883","libm/src/math/sincosf.rs":"d37d71c7204c7892fe24c956df0fb95e7a014a808f5cbd5e125aee48c3c449b5","libm/src/math/sinf.rs":"dcddac1d56b084cbb8d0e019433c9c5fe2201d9b257a7dcf2f85c9a8f14b79cf","libm/src/math/sinh.rs":"d8ee4c7af883a526f36c1a6da13bb81fba9181b477e2f2538161a2bee97edc35","libm/src/math/sinhf.rs":"d06eb030ba9dbf7094df127262bfe99f149b4db49fa8ab8c15499660f1e46b26","libm/src/math/sqrt.rs":"824570a631c2542ccee68b65e3eb08fe79c037a29bbaaf54da5367e7b236124a","libm/src/math/sqrtf.rs":"d9e12ac55c5471c18175efdfb15c092ba71a2eb914d2e1ee3b3310a22202042e","libm/src/math/tan.rs":"930ecedaadc60f704c2dfa4e15186f59713c1ba7d948529d215223b424827db5","libm/src/math/tanf.rs":"894156a3b107aee08461eb4e7e412fc049aa237d176ae705c6e3e2d7060d94e3","libm/src/math/tanh.rs":"f1f08eb98ed959a17370a7aaf0177be36e3764543424e78feb033ed3f5e8ec98","libm/src/math/tanhf.rs":"74027b0c672a4e64bdef6d7a3069b90caec50e1e7dbb2c12d2828f310502f41e","libm/src/math/tgamma.rs":"a6aabb8365410af6611f19f58694ccb74e82bb9ba9e1cdec7e1af787cfa44815","libm/src/math/tgammaf.rs":"c95bd69957387533853532164f7e2251d2b04f5e775406b9e647226ae2bdd5ad","libm/src/math/trunc.rs":"642264897cc1505e720c8cf313be81aa9fd53aae866644a2e988d01dbc77fd8a","libm/src/math/truncf.rs":"619b675b6a9bb81eccddb1fa8214cff63e1f62136629b645c87f036672311732","src/arm.rs":"34aeb8a51784d23d32c8bda677569c8661a96f920d5343c533e204d61ca43519","src/arm_linux.rs":"80d18ce84bdfa841fa133f5ee9e9fd50167344436d2d398f74347a90f27606c6","src/float/add.rs":"3ec32ceaf470a89777b54f9cde61832fdadeade0f4894f268a949e968520bc57","src/float/cmp.rs":"79b1fdc8d5f943c4ad5ea4ad32623b18f63e17ac3852fbc64a4942228007e1fc","src/float/conv.rs":"462102f7160e30c5ca7b332a1140c8d1229d1821fdce59fbf93f2c530364b197","src/float/div.rs":"1bd41ba756dc4b2d488ed4d4b59e5029a7774900fca5d542839e3b98b3805249","src/float/extend.rs":"180b2e791c58e0526de0a798845c580ce3222c8a15c8665e6e6a4bf5cf1a34aa","src/float/mod.rs":"9b83d3f058351bee41bbae9cb72ecc5e131d257f18cf9723af17d3538ed3e58c","src/float/mul.rs":"0d0c1f0c28c149ecadeafd459d3c4c9327e4cfcae2cba479957bb8010ef51a01","src/float/pow.rs":"6231c53cad103809d84f9ab6487d31eefc516eff8cfc0fda9ef6700f1d075d38","src/float/sub.rs":"c2a87f4628f51d5d908d0f25b5d51ce0599dc559d5a72b20e131261f484d5848","src/int/addsub.rs":"7ec45ce1ba15b56a5b7129d3e5722c4db764c6545306d3fa9090983bcabd6f17","src/int/leading_zeros.rs":"9f7b10c723baae8dcbd649e44a00eb40f7e082ba7c535c8d7701c1757f2ba76d","src/int/mod.rs":"bab1b77535ceebdebb89fd4e59e7105f8c45347bb638351a626615b24544a0b1","src/int/mul.rs":"40c5a84c0bff28797eccc9cf8884b5880261818dee21c961f17f727b74d02261","src/int/sdiv.rs":"ec870b6a4b92e6f6c2ce5189bb98ce04f54272d32f8796d9d543b576ba32b76d","src/int/shift.rs":"dab226fd4ccb9ce176584c86bdb70ba31a18bd00c4fdde7f2d0b69e2118253ca","src/int/specialized_div_rem/asymmetric.rs":"27f5bf70a35109f9d4e4e1ad1e8003aa17da5a1e436bf3e63a493d7528a3a566","src/int/specialized_div_rem/binary_long.rs":"9f1ced81a394f000a21a329683144d68ee431a954136a3634eb55b1ee2cf6d51","src/int/specialized_div_rem/delegate.rs":"9df141af98e391361e25d71ae38d5e845a91d896edd2c041132fd46af8268e85","src/int/specialized_div_rem/mod.rs":"cb5776ac628d6ac56a99d8bef8c2b5fac65fa39cc5f9fb9d20fe83b7d9493c01","src/int/specialized_div_rem/norm_shift.rs":"3be7ee0dea545c1f702d9daf67dad2b624bf7b17b075c8b90d3d3f7b53df4c21","src/int/specialized_div_rem/trifecta.rs":"87eef69da255b809fd710b14f2eb3f9f59e3dac625f8564ebc8ba78f9763523b","src/int/udiv.rs":"2173ec21ced1ecf660dd6f001690b4275b0bdc36a97b3e4b31bce89e33cb1d71","src/lib.rs":"d423f142ea038aea1ba251aa49c44ecbc0c567d078d3cae0667f7eec12a3ce3d","src/macros.rs":"016100d5043d3af66584d67b38c39b9fc6934a44dd762f99bf0b4653fad79223","src/math.rs":"c97e2ad283089362721ea48e9355f8a3119559c14e1c249c67044e865827a164","src/mem/impls.rs":"8148e22bb2ac018141ec1062703a49ad154e4bee2f29211a56a4afd3d42247ea","src/mem/mod.rs":"c2918bdf0250a4b085a66e9009513e9a0fe45a553f3c7f66047a485fe66ec767","src/mem/x86_64.rs":"ee2b6bb0449de5e4b20854bd9d3403f5e4808f8356eadf0dda26866847f6b929","src/probestack.rs":"23f5de88b87a853c6e89c38563c11ecdadab34d325a58128c9e5f927b8afb671","src/riscv32.rs":"b9b433d248fce35e43a7df430697545f39898fad46be7d0197284764e44993b2","src/x86.rs":"5d5f9972cfd733fc8a5e50674db2cc2ad697b4469a254181f624dd0e0c9a8047","src/x86_64.rs":"db90462211c1dc85b784e9d229cac761dbd3de5c5fef3a18784bb5650208ef6e"},"package":"787187ae221adfcda34b03006f1617099e4ae26b50e5a4db282496014ab75837"}
\ No newline at end of file
+{"files":{"Cargo.lock":"0a0375936cc507935d8610a792439b6a2510ac25c67c23fa79d6d14a2cfb441a","Cargo.toml":"39c8c0de50ff2e359a55057445d85dc5d10b3bd4add2b56bc06e8d012b46c1a1","README.md":"2dd28b207028773ffee09ed0db563ac71b255b6b67256289d67a13cb19d15f94","build.rs":"28277271ffc69b0b549310656411eb8f6ef23c1679be0d82d22d243c92421a32","examples/intrinsics.rs":"c4cdcc9f777e528fa54cb3bc3d6da4239373b8f9a5cdfe7bdf1df4598eaab64f","libm/src/math/acos.rs":"fb066ba84aba1372d706425ec14f35ff8d971756d15eeebd22ecf42a716493bb","libm/src/math/acosf.rs":"a112b82309bba1d35c4e3d6ad4d6c21ef305343d9ab601ddf4bc61d43bc9f1af","libm/src/math/acosh.rs":"56dac8538e4350cd7cf001327c89f087b68abb2e6aaad58edba8a094b09f6b0f","libm/src/math/acoshf.rs":"df5b0c4d8e37e64cf5ff2d8328b28bc35c78e84060ff769e64523ea9ff9065c1","libm/src/math/asin.rs":"095a1e98996daff45df0b154ca0ec35bbf31db964ee9fdda0207308cb20df441","libm/src/math/asinf.rs":"49cccb4db2881982643a4a7d5453f4f8daf527711bbb67313607a3c178856d61","libm/src/math/asinh.rs":"e8fc94031015fddf35e9c26b94da9f6431ee17c81cd7bd37da8ffc98f7e0b32c","libm/src/math/asinhf.rs":"8a0b8933a98a17617a66fef4c7b89eba645fdf05302000babf4a5a5f45328430","libm/src/math/atan.rs":"d4fe46e1c5739dd09997869dcfbc3c85f03c534af52e700d6c6bcf9c3fedda07","libm/src/math/atan2.rs":"2623bc8ca707d13a7092ce49adf68e9cbf4452ad1bf4a861dc40ca858606a747","libm/src/math/atan2f.rs":"dd01943e0e1f1955912e5c3ffc9467529cf64bd02ac0a6ad5ab31dbe6657f05d","libm/src/math/atanf.rs":"e41b41569474a59c970ede3538e00bda4072cf4d90040017101cc79d7dc28caa","libm/src/math/atanh.rs":"5934dbd6b7395ca4f103ace7598da723a9270e1cf6b47e7f786debe4bb3651ff","libm/src/math/atanhf.rs":"8ba4711dda19ef2dc33622be65c1483902868083543198c6bbd040d4026293de","libm/src/math/cbrt.rs":"f2c45612d2eecd93cfcdd9ebf824c754fc8f8dfd6d16862c0b9c4ccea78c2a0f","libm/src/math/cbrtf.rs":"ad0b483854aa9f17a44d36c049bf0e8ebab34c27e90b787c05f45cc230ec7d19","libm/src/math/ceil.rs":"0e6caff1597818471c28b7c3226dbfe9976fdb38ace5246172ac030754be6b79","libm/src/math/ceilf.rs":"f942bcea617de7da880b68bdfe676837a7984e2a887eaafe181be24c6bc13cc2","libm/src/math/copysign.rs":"d80c880efaf0cdf2ce0a4d4f5a68dd6c36c88d46fa997ec8ac8604bfdb26fa33","libm/src/math/copysignf.rs":"1547116071e68a42b1605eb2fc722db6466a34517dc96b92de1f29a274c3d8e3","libm/src/math/cos.rs":"74babdc13ede78e400c5ca1854c3e22d2e08cbdc5618aefa5bba6f9303ef65b6","libm/src/math/cosf.rs":"09c40f93c445b741e22477ceedf163ca33b6a47f973f7c9876cfba2692edb29c","libm/src/math/cosh.rs":"0d0a7cef18577f321996b8b87561963139f754ad7f2ea0a3b3883811f3f0693a","libm/src/math/coshf.rs":"be8ca8739e4cf1978425b349f941cb4838bba8c10cb559c7940b9fd4fdde21ad","libm/src/math/erf.rs":"9c55fc6756ba816996f0b585e07ccfa4cd87575ad525cd30c4a968b30acffda3","libm/src/math/erff.rs":"cb020e8bada9a54573a11fe3271750d73f14fed3092a881a9ceaf98fe32fd5a6","libm/src/math/exp.rs":"ca7405ad0d1993fffcf9aae96f9256307bed3c4916545aaebd1cf1d2df1807fa","libm/src/math/exp10.rs":"2deb037f88feac87a0e924b69dd496f0dd3b5d35f2a58e09d4c5166b207e517b","libm/src/math/exp10f.rs":"6979464dfe3f4f2da1f9afc909646499c4bfaef15e10a039384750e2f1586fea","libm/src/math/exp2.rs":"94a9304a2ce3bc81f6d2aefd3cde6faa30f13260d46cb13692863cdea1c9a3a1","libm/src/math/exp2f.rs":"785f2630accd35118ec07bf60273e219ed91a215b956b1552eeea5bc2a708cc8","libm/src/math/expf.rs":"ec14c18f891a9e37735ec39e6fc2e9bf674a2c2e083f22e2533b481177359c98","libm/src/math/expm1.rs":"124069f456c8ad331f265c7509d9e223b2a300e461bbfd3d6adfdcdd2ee5b8ac","libm/src/math/expm1f.rs":"18e2116d31ea8410051cc709b9d04b754b0e3ba6758ee1bf0b48749f4999b840","libm/src/math/expo2.rs":"4f4f9fecfccb43f30c2784aa7c0bb656754a52b8ab431f7d1b551c673ab133f1","libm/src/math/fabs.rs":"e6c7db39f98508098cdf64ac0c2f53866c466149a7490afb9fe22b44c4dd81b3","libm/src/math/fabsf.rs":"dc85b66e4ef662721276ae3a301af22795524e4367ee8dd40f0c24c439773c6d","libm/src/math/fdim.rs":"8ec091996005207297c2389ae563e1b18dbc6a9eac951de29a976c5cd7bc32a7","libm/src/math/fdimf.rs":"c7f3f2269834d55be26b6580ddc07c42531577955fa4de35bad1e2a361085614","libm/src/math/fenv.rs":"8730d45aa4c591f91dccdcc1ce533fa23e9c6df0c38defb9c57f749cb25e1cd0","libm/src/math/floor.rs":"be15e687a6798defc6f2c6b43028481f8104fb93d2b3f359d3d5d16b78e79d4f","libm/src/math/floorf.rs":"4ec41aa64cfafd23b8cfc043eacea5e9125cca5dcb3f5e655cc3d3458c6ba2c5","libm/src/math/fma.rs":"7163e384eb3b75738952cb1976d387a3f2d81890fbddcc370c44132433128688","libm/src/math/fmaf.rs":"3e0f5727e56f31218f674b9b8975d7e67b3a24a097f06a2a3eca9723cd786213","libm/src/math/fmax.rs":"f6c8e96a8b1a170648d2fa3513e7b6b459085d708c839869f82e305fe58fac37","libm/src/math/fmaxf.rs":"dff0025433232e8a5ec7bd54d847ccf596d762ea4e35f5c54fbaac9404d732fd","libm/src/math/fmin.rs":"95b6cb66ca0e0e22276f0bf88dbe8fb69796a69a196a7491bd4802efbcf2e298","libm/src/math/fminf.rs":"304bc839b15ea3d84e68d2af9f40524ec120d30a36a667b22fcb98a6c258f4c7","libm/src/math/fmod.rs":"a1c0550fc7df8164733d914e222ff0966a2ab886d6e75a1098f24fe0283ae227","libm/src/math/fmodf.rs":"ee51ed092c0eeb8195f35735ff725cfd46612e0d689a7c483538bd92fbe61828","libm/src/math/frexp.rs":"28af70026922a8ab979744c7ad4d8faba6079c4743b7eeb6d14c983a982fbbcc","libm/src/math/frexpf.rs":"2e2593ae8002ba420809ebfaf737ef001cdc912354be3d978a8c0cb930350d4d","libm/src/math/hypot.rs":"841131c4a0cea75bc8a86e29f3f6d0815a61fc99731c9984651ce83d3050d218","libm/src/math/hypotf.rs":"5f317323edc2eb699580fe54b074b7e570a7734d51a0a149c0b49b54470a836c","libm/src/math/ilogb.rs":"813413bf6266d4fc40db9c5921af3cef4f892ba93e8f6d9efe62a449d1234532","libm/src/math/ilogbf.rs":"dec462780f46682e16cfaa733238bed3b692729e951f53a44726100b6c73a716","libm/src/math/j0.rs":"9572b6396c489927d332d0e717920e61ec0618e5e9c31f7eeeec70f5e4abab06","libm/src/math/j0f.rs":"802c8254bded9b3afb6eea8b9af240038a5a4a5d811396729f69ca509e3e7d87","libm/src/math/j1.rs":"97b1af1611fa3d110c2b349ee8e4176100132ea1391b619086b47ac063b81803","libm/src/math/j1f.rs":"1d504d7750c0481273baad88196d3644f258af9ad10f8b5b16341c0aab8b9125","libm/src/math/jn.rs":"847d122334e5707ad9627146cddccc082a1f2f5bcd3e5ef54399013a7007ce88","libm/src/math/jnf.rs":"4045076f7d1a1b89882ed60d4dd60a4cbbc66b85cfb90491378c8015effcc476","libm/src/math/k_cos.rs":"f34a69e44d6b8901b03b578a75972f438ab20a7b98a0903fc1903d6fde3899be","libm/src/math/k_cosf.rs":"8f7117ff21cebf8e890a5bcfd7ea858a94172f4172b79a66d53824c2cb0888b1","libm/src/math/k_expo2.rs":"eb4ca9e6a525b7ea6da868c3cb136896682cc46f8396ba2a2ebc3ae9e9ba54b0","libm/src/math/k_expo2f.rs":"d51ad5df61cb5d1258bdb90c52bfed4572bb446a9337de9c04411ed9454ae0cb","libm/src/math/k_sin.rs":"14b2aba6ca07150c92768b5a72acaf5cde6a11d6619e14896512a7ba242e289a","libm/src/math/k_sinf.rs":"2775fcc710807164e6f37a4f8da3c8143cd5f16e19ce7c31c5591522151d7a96","libm/src/math/k_tan.rs":"a72beae4ccd9631eeeb61d6365bbeecae81c8411f3120a999c515cca0d5ea5c5","libm/src/math/k_tanf.rs":"6a794be56fa4b2f60452b9bab19af01c388f174560acbf829a351378ea39495d","libm/src/math/ldexp.rs":"b647f0096e80e4d926d8dd18d294c892ee2cb1778effe2c5e1b2664ae5cb1a4e","libm/src/math/ldexpf.rs":"98743fad2cd97a7be496f40ba3157ac1438fce0d0c25d5ab90c3b8c71c3fd0ed","libm/src/math/lgamma.rs":"498552658cc8106d7754f85ae8dbc3306ac2f0a9f7eb5a796be70c5beac92c41","libm/src/math/lgamma_r.rs":"77fb6442aeb5343926d8965e1549dde3e2cc4fd09555de6b56506001d956c344","libm/src/math/lgammaf.rs":"457105f53a4c8717e8f5a117d261dcf94e222e83981337fe23602abe883fe3f7","libm/src/math/lgammaf_r.rs":"44de75babbdd53c4a5879cd6f426e7311db82669def39df5f63914d67d6cc1b1","libm/src/math/log.rs":"b5e0c5f30d9e94351488732801be3107c12b854c3f95ad37e256dd88eeca408f","libm/src/math/log10.rs":"3425ff8be001fd1646ba15e254eb6ef4bdc6ccaf0cbee27ddf1fa84e04178b90","libm/src/math/log10f.rs":"fee4f71879bc4c99259e68c0c641364901629fb29a8ebddfcc0d090102cceddd","libm/src/math/log1p.rs":"9cf400852f165e6be19b97036ae9521fb9ca857d0a9a91c117d9123221622185","libm/src/math/log1pf.rs":"2716e6d2afa271996b7c8f47fd9e4952c88f4c1fd8c07c3e8ce8c62794bf71d8","libm/src/math/log2.rs":"dbbbfbaaa8aa6a4dbefea554ea3983090a9691228b011910c751f6adca912c40","libm/src/math/log2f.rs":"92a90350d8edce21c31c285c3e620fca7c62a2366008921715945c2c73b5b79f","libm/src/math/logf.rs":"845342cffc34d3db1f5ec12d8e5b773cd5a79056e28662fcb9bcd80207596f50","libm/src/math/mod.rs":"ffa73c08f4c0a4dc6c9d1cb9d62fe97f3a5046edede128c9441cc3adc9170dd3","libm/src/math/modf.rs":"d012ed5a708ef52b6d1313c22a46cadaf5764dde1220816e3df2f03a0fcc60ae","libm/src/math/modff.rs":"f8f1e4c27a85d2cdb3c8e74439d59ef64aa543b948f22c23227d02d8388d61c2","libm/src/math/nextafter.rs":"3282e7eef214a32736fb6928d490198ad394b26b402b45495115b104839eebfe","libm/src/math/nextafterf.rs":"0937dc8a8155c19842c12181e741cec1f7df1f7a00cee81fcb2475e2842761b7","libm/src/math/pow.rs":"bc67d59403b0b35cbdbd28968bb60898254cb3700cdf491b299f81fda51037ed","libm/src/math/powf.rs":"2c423a0ea57fdc4e20f3533f744c6e6288c998b4de8f2914fafaa0e78be81b04","libm/src/math/rem_pio2.rs":"9be99c44493b2b7088578c0fa2872630725b2da544c751516df0c6c686112a43","libm/src/math/rem_pio2_large.rs":"21762d08d72dc6f2e313123a7311683000974a09b8fcae50994d9c39239721b1","libm/src/math/rem_pio2f.rs":"377349d1308bda8cd2f776e4856fe090baa78fa3db816b680780ddf31b80d446","libm/src/math/remainder.rs":"63865f4370853c476b45bb27a5c54a4072146aa4a626835ae5263871a4e7e5dc","libm/src/math/remainderf.rs":"dd3fa432dbda8f2135428198be7bd69c57f8d13df3f365b12f52bf6a82352ac4","libm/src/math/remquo.rs":"3cc0bf55069f165c4843f2c358b3a27279c01e8cdd99f9057a3f7f31f45408f2","libm/src/math/remquof.rs":"cc749e18ecb7e766b8b8eeabdbf89ac99087d3d587e71e30f690676a3d2c1f9b","libm/src/math/round.rs":"955649c893fa3151b4a81c8e550fbc03f01bb99b40d60986e5f153ee71043f69","libm/src/math/roundf.rs":"8ae8f1f71eedd158566771cfe80b352d2f13c170a0ce8dc2691a14e8a791cfbb","libm/src/math/scalbn.rs":"b5c9d6d4177fe393cbfe1c634d75ce14b754f6cbce87c5bf979a9661491748a2","libm/src/math/scalbnf.rs":"4f198d06db1896386256fb9a5ac5b805b16b836226c18780a475cf18d7c1449c","libm/src/math/sin.rs":"0e014e6377c9673a73395ab2ffcf5962e512392afddf8a4e731fb694098faf34","libm/src/math/sincos.rs":"59e9f196140681fa817652134b8d1bdd2d6dd47bb8557b0346c77b176389f883","libm/src/math/sincosf.rs":"d37d71c7204c7892fe24c956df0fb95e7a014a808f5cbd5e125aee48c3c449b5","libm/src/math/sinf.rs":"dcddac1d56b084cbb8d0e019433c9c5fe2201d9b257a7dcf2f85c9a8f14b79cf","libm/src/math/sinh.rs":"d8ee4c7af883a526f36c1a6da13bb81fba9181b477e2f2538161a2bee97edc35","libm/src/math/sinhf.rs":"d06eb030ba9dbf7094df127262bfe99f149b4db49fa8ab8c15499660f1e46b26","libm/src/math/sqrt.rs":"824570a631c2542ccee68b65e3eb08fe79c037a29bbaaf54da5367e7b236124a","libm/src/math/sqrtf.rs":"d9e12ac55c5471c18175efdfb15c092ba71a2eb914d2e1ee3b3310a22202042e","libm/src/math/tan.rs":"930ecedaadc60f704c2dfa4e15186f59713c1ba7d948529d215223b424827db5","libm/src/math/tanf.rs":"894156a3b107aee08461eb4e7e412fc049aa237d176ae705c6e3e2d7060d94e3","libm/src/math/tanh.rs":"f1f08eb98ed959a17370a7aaf0177be36e3764543424e78feb033ed3f5e8ec98","libm/src/math/tanhf.rs":"74027b0c672a4e64bdef6d7a3069b90caec50e1e7dbb2c12d2828f310502f41e","libm/src/math/tgamma.rs":"a6aabb8365410af6611f19f58694ccb74e82bb9ba9e1cdec7e1af787cfa44815","libm/src/math/tgammaf.rs":"c95bd69957387533853532164f7e2251d2b04f5e775406b9e647226ae2bdd5ad","libm/src/math/trunc.rs":"642264897cc1505e720c8cf313be81aa9fd53aae866644a2e988d01dbc77fd8a","libm/src/math/truncf.rs":"619b675b6a9bb81eccddb1fa8214cff63e1f62136629b645c87f036672311732","src/arm.rs":"34aeb8a51784d23d32c8bda677569c8661a96f920d5343c533e204d61ca43519","src/arm_linux.rs":"80d18ce84bdfa841fa133f5ee9e9fd50167344436d2d398f74347a90f27606c6","src/float/add.rs":"3ec32ceaf470a89777b54f9cde61832fdadeade0f4894f268a949e968520bc57","src/float/cmp.rs":"79b1fdc8d5f943c4ad5ea4ad32623b18f63e17ac3852fbc64a4942228007e1fc","src/float/conv.rs":"462102f7160e30c5ca7b332a1140c8d1229d1821fdce59fbf93f2c530364b197","src/float/div.rs":"1bd41ba756dc4b2d488ed4d4b59e5029a7774900fca5d542839e3b98b3805249","src/float/extend.rs":"180b2e791c58e0526de0a798845c580ce3222c8a15c8665e6e6a4bf5cf1a34aa","src/float/mod.rs":"9b83d3f058351bee41bbae9cb72ecc5e131d257f18cf9723af17d3538ed3e58c","src/float/mul.rs":"0d0c1f0c28c149ecadeafd459d3c4c9327e4cfcae2cba479957bb8010ef51a01","src/float/pow.rs":"6231c53cad103809d84f9ab6487d31eefc516eff8cfc0fda9ef6700f1d075d38","src/float/sub.rs":"c2a87f4628f51d5d908d0f25b5d51ce0599dc559d5a72b20e131261f484d5848","src/int/addsub.rs":"7ec45ce1ba15b56a5b7129d3e5722c4db764c6545306d3fa9090983bcabd6f17","src/int/leading_zeros.rs":"9f7b10c723baae8dcbd649e44a00eb40f7e082ba7c535c8d7701c1757f2ba76d","src/int/mod.rs":"bab1b77535ceebdebb89fd4e59e7105f8c45347bb638351a626615b24544a0b1","src/int/mul.rs":"40c5a84c0bff28797eccc9cf8884b5880261818dee21c961f17f727b74d02261","src/int/sdiv.rs":"ec870b6a4b92e6f6c2ce5189bb98ce04f54272d32f8796d9d543b576ba32b76d","src/int/shift.rs":"3967c28a8d61279546e91958d64745fec63f15aee9175eb0602cc6353830da6c","src/int/specialized_div_rem/asymmetric.rs":"27f5bf70a35109f9d4e4e1ad1e8003aa17da5a1e436bf3e63a493d7528a3a566","src/int/specialized_div_rem/binary_long.rs":"9f1ced81a394f000a21a329683144d68ee431a954136a3634eb55b1ee2cf6d51","src/int/specialized_div_rem/delegate.rs":"9df141af98e391361e25d71ae38d5e845a91d896edd2c041132fd46af8268e85","src/int/specialized_div_rem/mod.rs":"cb5776ac628d6ac56a99d8bef8c2b5fac65fa39cc5f9fb9d20fe83b7d9493c01","src/int/specialized_div_rem/norm_shift.rs":"3be7ee0dea545c1f702d9daf67dad2b624bf7b17b075c8b90d3d3f7b53df4c21","src/int/specialized_div_rem/trifecta.rs":"87eef69da255b809fd710b14f2eb3f9f59e3dac625f8564ebc8ba78f9763523b","src/int/udiv.rs":"2173ec21ced1ecf660dd6f001690b4275b0bdc36a97b3e4b31bce89e33cb1d71","src/lib.rs":"d423f142ea038aea1ba251aa49c44ecbc0c567d078d3cae0667f7eec12a3ce3d","src/macros.rs":"016100d5043d3af66584d67b38c39b9fc6934a44dd762f99bf0b4653fad79223","src/math.rs":"c97e2ad283089362721ea48e9355f8a3119559c14e1c249c67044e865827a164","src/mem/impls.rs":"8148e22bb2ac018141ec1062703a49ad154e4bee2f29211a56a4afd3d42247ea","src/mem/mod.rs":"c2918bdf0250a4b085a66e9009513e9a0fe45a553f3c7f66047a485fe66ec767","src/mem/x86_64.rs":"ee2b6bb0449de5e4b20854bd9d3403f5e4808f8356eadf0dda26866847f6b929","src/probestack.rs":"23f5de88b87a853c6e89c38563c11ecdadab34d325a58128c9e5f927b8afb671","src/riscv32.rs":"b9b433d248fce35e43a7df430697545f39898fad46be7d0197284764e44993b2","src/x86.rs":"5d5f9972cfd733fc8a5e50674db2cc2ad697b4469a254181f624dd0e0c9a8047","src/x86_64.rs":"db90462211c1dc85b784e9d229cac761dbd3de5c5fef3a18784bb5650208ef6e"},"package":"20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2"}
\ No newline at end of file
index d8b1285d9d3c7847a459b67b825b9844ffb46cbe..58451163b2e3e259b0c7c68addbd436ebe933d8d 100644 (file)
@@ -10,7 +10,7 @@ checksum = "7db2f146208d7e0fbee761b09cd65a7f51ccc38705d4e7262dad4d73b12a76b1"
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.45"
+version = "0.1.49"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
index 35768d0d34fe655c55976b220bbae3f5f6fceab1..9c4f37006b6252ab3b4facc18361f42cf9a70914 100644 (file)
@@ -3,16 +3,15 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
 name = "compiler_builtins"
-version = "0.1.45"
+version = "0.1.49"
 authors = ["Jorge Aparicio <japaricious@gmail.com>"]
 links = "compiler-rt"
 include = ["/Cargo.toml", "/build.rs", "/src/*", "/examples/*", "/LICENSE.txt", "/README.md", "/compiler-rt/*", "/libm/src/math/*"]
index f0617b6e92a10e77ccb1d7711487be0d8a889603..d4cfe0e1c2b3ab526a44aeb096e0816a12e4daef 100644 (file)
@@ -84,7 +84,7 @@ fn main() {
 mod c {
     extern crate cc;
 
-    use std::collections::BTreeMap;
+    use std::collections::{BTreeMap, HashSet};
     use std::env;
     use std::path::{Path, PathBuf};
 
@@ -419,23 +419,18 @@ mod c {
                 ("__floatunsitf", "floatunsitf.c"),
                 ("__trunctfdf2", "trunctfdf2.c"),
                 ("__trunctfsf2", "trunctfsf2.c"),
+                ("__addtf3", "addtf3.c"),
+                ("__multf3", "multf3.c"),
+                ("__subtf3", "subtf3.c"),
+                ("__divtf3", "divtf3.c"),
+                ("__powitf2", "powitf2.c"),
+                ("__fe_getround", "fp_mode.c"),
+                ("__fe_raise_inexact", "fp_mode.c"),
             ]);
 
             if target_os != "windows" {
                 sources.extend(&[("__multc3", "multc3.c")]);
             }
-
-            if target_env == "musl" {
-                sources.extend(&[
-                    ("__addtf3", "addtf3.c"),
-                    ("__multf3", "multf3.c"),
-                    ("__subtf3", "subtf3.c"),
-                    ("__divtf3", "divtf3.c"),
-                    ("__powitf2", "powitf2.c"),
-                    ("__fe_getround", "fp_mode.c"),
-                    ("__fe_raise_inexact", "fp_mode.c"),
-                ]);
-            }
         }
 
         if target_arch == "mips" {
@@ -496,8 +491,9 @@ mod c {
 
         // Include out-of-line atomics for aarch64, which are all generated by supplying different
         // sets of flags to the same source file.
+        // Note: Out-of-line aarch64 atomics are not supported by the msvc toolchain (#430).
         let src_dir = root.join("lib/builtins");
-        if target_arch == "aarch64" {
+        if target_arch == "aarch64" && target_env != "msvc" {
             // See below for why we're building these as separate libraries.
             build_aarch64_out_of_line_atomics_libraries(&src_dir, cfg);
 
@@ -505,10 +501,13 @@ mod c {
             sources.extend(&[("__aarch64_have_lse_atomics", "cpu_model.c")]);
         }
 
+        let mut added_sources = HashSet::new();
         for (sym, src) in sources.map.iter() {
             let src = src_dir.join(src);
-            cfg.file(&src);
-            println!("cargo:rerun-if-changed={}", src.display());
+            if added_sources.insert(src.clone()) {
+                cfg.file(&src);
+                println!("cargo:rerun-if-changed={}", src.display());
+            }
             println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
         }
 
index 3219dbcce1fbe547a3e8b130d0c4195a619900a7..85d842119cb3be1922d2aa6129d4657e39cd6c06 100644 (file)
@@ -122,9 +122,9 @@ pub fn fma(x: f64, y: f64, z: f64) -> f64 {
         rhi += zhi + (rlo < zlo) as u64;
     } else {
         /* r -= z */
-        let t = rlo;
-        rlo = rlo.wrapping_sub(zlo);
-        rhi = rhi.wrapping_sub(zhi.wrapping_sub((t < rlo) as u64));
+        let (res, borrow) = rlo.overflowing_sub(zlo);
+        rlo = res;
+        rhi = rhi.wrapping_sub(zhi.wrapping_add(borrow as u64));
         if (rhi >> 63) != 0 {
             rlo = (-(rlo as i64)) as u64;
             rhi = (-(rhi as i64)) as u64 - (rlo != 0) as u64;
@@ -218,6 +218,14 @@ mod tests {
             -0.00000000000000022204460492503126,
         );
 
-        assert_eq!(fma(-0.992, -0.992, -0.992), -0.00793599999988632,);
+        assert_eq!(fma(-0.992, -0.992, -0.992), -0.007936000000000007,);
+    }
+
+    #[test]
+    fn fma_sbb() {
+        assert_eq!(
+            fma(-(1.0 - f64::EPSILON), f64::MIN, f64::MIN),
+            -3991680619069439e277
+        );
     }
 }
index c7fd0dfa117608859f6b0fbeb79a6a02fd1f5943..f79680a05d015baafecfc1cb3add29ed4e24a771 100644 (file)
@@ -604,7 +604,7 @@ mod tests {
 
         // Factoring -1 out:
         // (negative anything ^ integer should be (-1 ^ integer) * (positive anything ^ integer))
-        &[POS_ZERO, NEG_ZERO, POS_ONE, NEG_ONE, POS_EVENS, NEG_EVENS]
+        (&[POS_ZERO, NEG_ZERO, POS_ONE, NEG_ONE, POS_EVENS, NEG_EVENS])
             .iter()
             .for_each(|int_set| {
                 int_set.iter().for_each(|int| {
@@ -616,7 +616,7 @@ mod tests {
 
         // Negative base (imaginary results):
         // (-anything except 0 and Infinity ^ non-integer should be NAN)
-        &NEG[1..(NEG.len() - 1)].iter().for_each(|set| {
+        (&NEG[1..(NEG.len() - 1)]).iter().for_each(|set| {
             set.iter().for_each(|val| {
                 test_sets(&ALL[3..7], &|v: f64| pow(*val, v), &|_| NAN);
             })
index 59909929e58c28d7e7e1ff3d9bac05a9e2db2ab0..908e619e1dd81ca6b8a5f5e1a1cf63ca757f82cf 100644 (file)
@@ -6,13 +6,13 @@ trait Ashl: DInt {
         let n_h = Self::H::BITS;
         if shl & n_h != 0 {
             // we only need `self.lo()` because `self.hi()` will be shifted out entirely
-            (self.lo() << (shl - n_h)).widen_hi()
+            self.lo().wrapping_shl(shl - n_h).widen_hi()
         } else if shl == 0 {
             self
         } else {
             Self::from_lo_hi(
-                self.lo() << shl,
-                self.lo().logical_shr(n_h - shl) | (self.hi() << shl),
+                self.lo().wrapping_shl(shl),
+                self.lo().logical_shr(n_h - shl) | self.hi().wrapping_shl(shl),
             )
         }
     }
@@ -28,16 +28,16 @@ trait Ashr: DInt {
         let n_h = Self::H::BITS;
         if shr & n_h != 0 {
             Self::from_lo_hi(
-                self.hi() >> (shr - n_h),
+                self.hi().wrapping_shr(shr - n_h),
                 // smear the sign bit
-                self.hi() >> (n_h - 1),
+                self.hi().wrapping_shr(n_h - 1),
             )
         } else if shr == 0 {
             self
         } else {
             Self::from_lo_hi(
-                self.lo().logical_shr(shr) | (self.hi() << (n_h - shr)),
-                self.hi() >> shr,
+                self.lo().logical_shr(shr) | self.hi().wrapping_shl(n_h - shr),
+                self.hi().wrapping_shr(shr),
             )
         }
     }
@@ -57,7 +57,7 @@ trait Lshr: DInt {
             self
         } else {
             Self::from_lo_hi(
-                self.lo().logical_shr(shr) | (self.hi() << (n_h - shr)),
+                self.lo().logical_shr(shr) | self.hi().wrapping_shl(n_h - shr),
                 self.hi().logical_shr(shr),
             )
         }
diff --git a/vendor/globwalk/.cargo-checksum.json b/vendor/globwalk/.cargo-checksum.json
new file mode 100644 (file)
index 0000000..1f269d7
--- /dev/null
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"7284c15572c1078c3e2294008ed3b85ba9b1d3021cb621897c2067654c4ec9ea","Cargo.toml":"32115f0a2276dc41e0be442d4e93d94c29d5b6a5763d3fb260c40d3f0e545175","LICENSE":"3234ac55816264ee7b6c7ee27efd61cf0a1fe775806870e3d9b4c41ea73c5cb1","README.md":"471f8d8fb2a0c0789201b9ffd9ad1cb41bd2e624654b0a011832007d1971b81e","appveyor.yml":"cd39c9865ae4ccd930371a9d93542f33ab6e6c6add2db34df12cd9868831fa88","examples/list.rs":"9d8fde1e89e4e19430a11e877ec413bd4d9f6b50bf438e4900d8200de015453b","src/doctests.rs":"d9fd71aea77920f5fd17ac77d24b5e8a1df53dea5e52e9fc61df4250de98bb2e","src/lib.rs":"18c92c1f988cd6ceebdda69986d2d96b9db14e404ea756b776d3b714d1e71abb","tests/docs.rs":"c6efa1a842ee941b3aa6758b1edbbe4a665fcb0d096d5f782cdb12266d1e8c5f"},"package":"93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"}
\ No newline at end of file
diff --git a/vendor/globwalk/Cargo.lock b/vendor/globwalk/Cargo.lock
new file mode 100644 (file)
index 0000000..7e3e961
--- /dev/null
@@ -0,0 +1,334 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "aho-corasick"
+version = "0.7.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "backtrace"
+version = "0.3.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace-sys 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "backtrace-sys"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "bstr"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cc"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "docmatic"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "failure"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "fuchsia-cprng"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "globset"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aho-corasick 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bstr 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "globwalk"
+version = "0.8.1"
+dependencies = [
+ "backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "docmatic 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ignore 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "ignore"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-utils 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "globset 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.81"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "log"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "memchr"
+version = "2.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rand"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rdrand"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aho-corasick 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tempdir"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "walkdir"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "which"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum aho-corasick 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
+"checksum autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+"checksum backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "1371048253fa3bac6704bfd6bbfc922ee9bdcee8881330d40f308b81cc5adc55"
+"checksum backtrace-sys 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "18fbebbe1c9d1f383a9cc7e8ccdb471b91c8d024ee9c2ca5b5346121fe8b4399"
+"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+"checksum bstr 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf"
+"checksum cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
+"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+"checksum cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+"checksum crossbeam-utils 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
+"checksum docmatic 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d58ebceaf539cb79420fb3046da9396e11021c536ae953be6ba5363842da8c3"
+"checksum failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
+"checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
+"checksum globset 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a"
+"checksum ignore 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b287fb45c60bb826a0dc68ff08742b9d88a2fea13d6e0c286b3172065aaf878c"
+"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+"checksum libc 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)" = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
+"checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
+"checksum memchr 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
+"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
+"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
+"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
+"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
+"checksum regex 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
+"checksum regex-syntax 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
+"checksum remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+"checksum rustc-demangle 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
+"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
+"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
+"checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
+"checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164"
+"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+"checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/vendor/globwalk/Cargo.toml b/vendor/globwalk/Cargo.toml
new file mode 100644 (file)
index 0000000..7076f8c
--- /dev/null
@@ -0,0 +1,43 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "globwalk"
+version = "0.8.1"
+authors = ["Gilad Naaman <gilad@naaman.io>"]
+description = "Glob-matched recursive file system walking."
+readme = "README.md"
+keywords = ["regex", "glob", "pattern", "walk", "iterator"]
+categories = ["filesystem"]
+license = "MIT"
+repository = "https://github.com/gilnaa/globwalk"
+[dependencies.bitflags]
+version = "1.2"
+
+[dependencies.ignore]
+version = "0.4.11"
+
+[dependencies.walkdir]
+version = "2"
+[dev-dependencies.backtrace]
+version = "=0.3.35"
+
+[dev-dependencies.docmatic]
+version = "0.1.2"
+
+[dev-dependencies.tempdir]
+version = "0.3.6"
+[badges.appveyor]
+repository = "Gilnaa/globwalk"
+
+[badges.travis-ci]
+repository = "Gilnaa/globwalk"
diff --git a/vendor/globwalk/LICENSE b/vendor/globwalk/LICENSE
new file mode 100644 (file)
index 0000000..61f6081
--- /dev/null
@@ -0,0 +1,19 @@
+Copyright (c) 2017 Gilad Naaman
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/vendor/globwalk/README.md b/vendor/globwalk/README.md
new file mode 100644 (file)
index 0000000..74be098
--- /dev/null
@@ -0,0 +1,46 @@
+# GlobWalk #
+
+[![Build Status](https://travis-ci.org/Gilnaa/globwalk.svg?branch=master)](https://travis-ci.org/Gilnaa/globwalk)
+[![Build status](https://ci.appveyor.com/api/projects/status/81rkf5lcyt1ouh9n/branch/master?svg=true)](https://ci.appveyor.com/project/Gilnaa/globwalk)
+[![](https://docs.rs/globwalk/badge.svg)](https://docs.rs/globwalk/)
+![License](https://img.shields.io/crates/l/globwalk.svg)
+[![crates.io](https://img.shields.io/crates/v/globwalk.svg)](https://crates.io/crates/globwalk)
+
+Recursively find files in a directory using globs.
+
+Based on both `walkdir` & `ignore` (❤), this crate inherits many goodies from
+both, such as limiting search depth and amount of open file descriptors.
+
+Licensed under MIT.
+
+### Why not `glob` ###
+
+ - The `glob` crate does not support having `{a,b}` in patterns.
+ - `globwalk` can match several glob-patterns at the same time.
+ - `globwalk` supports excluding results with `!`.
+ - `glob` searches for files in the current working directory, whereas `globwalk` starts at a specified base-dir.
+
+### Usage ###
+
+To use this crate, add `globwalk` as a dependency to your project's `Cargo.toml`:
+
+```toml
+[dependencies]
+globwalk = "0.8.1"
+```
+
+The following piece of code recursively find all `png`, `jpg`, or `gif` files:
+
+```rust
+extern crate globwalk;
+
+use std::fs;
+
+for img in globwalk::glob("*.{png,jpg,gif}").unwrap() {
+    if let Ok(img) = img {
+        println!("{:?}", img.path());
+    }
+}
+```
+
+See the [documentation](https://docs.rs/globwalk/) for more details.
diff --git a/vendor/globwalk/appveyor.yml b/vendor/globwalk/appveyor.yml
new file mode 100644 (file)
index 0000000..9354d77
--- /dev/null
@@ -0,0 +1,125 @@
+# Appveyor configuration template for Rust using rustup for Rust installation
+# https://github.com/starkat99/appveyor-rust
+
+## Operating System (VM environment) ##
+
+# Rust needs at least Visual Studio 2013 Appveyor OS for MSVC targets.
+os: Visual Studio 2015
+
+## Build Matrix ##
+
+# This configuration will setup a build for each channel & target combination (12 windows
+# combinations in all).
+#
+# There are 3 channels: stable, beta, and nightly.
+#
+# Alternatively, the full version may be specified for the channel to build using that specific
+# version (e.g. channel: 1.5.0)
+#
+# The values for target are the set of windows Rust build targets. Each value is of the form
+#
+# ARCH-pc-windows-TOOLCHAIN
+#
+# Where ARCH is the target architecture, either x86_64 or i686, and TOOLCHAIN is the linker
+# toolchain to use, either msvc or gnu. See https://www.rust-lang.org/downloads.html#win-foot for
+# a description of the toolchain differences.
+# See https://github.com/rust-lang-nursery/rustup.rs/#toolchain-specification for description of
+# toolchains and host triples.
+#
+# Comment out channel/target combos you do not wish to build in CI.
+#
+# You may use the `cargoflags` and `RUSTFLAGS` variables to set additional flags for cargo commands
+# and rustc, respectively. For instance, you can uncomment the cargoflags lines in the nightly
+# channels to enable unstable features when building for nightly. Or you could add additional
+# matrix entries to test different combinations of features.
+environment:
+  matrix:
+
+### MSVC Toolchains ###
+
+  # Stable 64-bit MSVC
+    - channel: stable
+      target: x86_64-pc-windows-msvc
+  # Stable 32-bit MSVC
+    - channel: stable
+      target: i686-pc-windows-msvc
+  # Beta 64-bit MSVC
+    - channel: beta
+      target: x86_64-pc-windows-msvc
+  # Beta 32-bit MSVC
+    - channel: beta
+      target: i686-pc-windows-msvc
+  # Nightly 64-bit MSVC
+    - channel: nightly
+      target: x86_64-pc-windows-msvc
+      #cargoflags: --features "unstable"
+  # Nightly 32-bit MSVC
+    - channel: nightly
+      target: i686-pc-windows-msvc
+      #cargoflags: --features "unstable"
+
+# Note: Disabled these targets due to linking errors I have no time to fix.
+#### GNU Toolchains ###
+#
+#  # Stable 64-bit GNU
+#    - channel: stable
+#      target: x86_64-pc-windows-gnu
+#  # Stable 32-bit GNU
+#    - channel: stable
+#      target: i686-pc-windows-gnu
+#  # Beta 64-bit GNU
+#    - channel: beta
+#      target: x86_64-pc-windows-gnu
+#  # Beta 32-bit GNU
+#    - channel: beta
+#      target: i686-pc-windows-gnu
+#  # Nightly 64-bit GNU
+#    - channel: nightly
+#      target: x86_64-pc-windows-gnu
+#      #cargoflags: --features "unstable"
+#  # Nightly 32-bit GNU
+#    - channel: nightly
+#      target: i686-pc-windows-gnu
+#      #cargoflags: --features "unstable"
+
+### Allowed failures ###
+
+# See Appveyor documentation for specific details. In short, place any channel or targets you wish
+# to allow build failures on (usually nightly at least is a wise choice). This will prevent a build
+# or test failure in the matching channels/targets from failing the entire build.
+matrix:
+  allow_failures:
+    - channel: nightly
+
+# If you only care about stable channel build failures, uncomment the following line:
+    #- channel: beta
+
+## Install Script ##
+
+# This is the most important part of the Appveyor configuration. This installs the version of Rust
+# specified by the 'channel' and 'target' environment variables from the build matrix. This uses
+# rustup to install Rust.
+#
+# For simple configurations, instead of using the build matrix, you can simply set the
+# default-toolchain and default-host manually here.
+install:
+  - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
+  - rustup-init -yv --default-toolchain %channel% --default-host %target%
+  - set PATH=%PATH%;%USERPROFILE%\.cargo\bin
+  - if "%TARGET%" == "i686-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw32\bin
+  - if "%TARGET%" == "x86_64-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw64\bin
+  - rustc -vV
+  - cargo -vV
+
+## Build Script ##
+
+# 'cargo test' takes care of building for us, so disable Appveyor's build stage. This prevents
+# the "directory does not contain a project or solution file" error.
+build: false
+
+# Uses 'cargo test' to run tests and build. Alternatively, the project may call compiled programs
+#directly or perform other testing commands. Rust will automatically be placed in the PATH
+# environment variable.
+test_script:
+  - cargo test --verbose %cargoflags%
+
diff --git a/vendor/globwalk/examples/list.rs b/vendor/globwalk/examples/list.rs
new file mode 100644 (file)
index 0000000..3674490
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright (c) 2018 Gilad Naaman
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+extern crate globwalk;
+
+use globwalk::GlobWalkerBuilder;
+use std::env::args;
+
+fn main() {
+    let patterns = args().skip(1).collect::<Vec<_>>();
+
+    for f in GlobWalkerBuilder::from_patterns(".", &patterns[..])
+        .build()
+        .unwrap()
+    {
+        println!("{:?}", f.unwrap().path());
+    }
+}
diff --git a/vendor/globwalk/src/doctests.rs b/vendor/globwalk/src/doctests.rs
new file mode 100644 (file)
index 0000000..a66a422
--- /dev/null
@@ -0,0 +1,20 @@
+extern crate tempdir;
+
+use std::error::Error;
+use std::fs::{File, create_dir_all};
+use std::path::PathBuf;
+use tempdir::TempDir;
+
+fn create_files(files: &[&str]) -> Result<TempDir, Box<Error>> {
+    let tmp_dir = TempDir::new("globwalk")?;
+
+    for f in files {
+        let file_path = PathBuf::from(f);
+        if let Some(dir) = file_path.parent() {
+            create_dir_all(tmp_dir.path().join(dir))?;
+        }
+        File::create(tmp_dir.path().join(file_path))?;
+    }
+
+    Ok(tmp_dir)
+}
diff --git a/vendor/globwalk/src/lib.rs b/vendor/globwalk/src/lib.rs
new file mode 100644 (file)
index 0000000..2c2871a
--- /dev/null
@@ -0,0 +1,839 @@
+// Copyright (c) 2017 Gilad Naaman
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//! Recursively find files in a directory using globs.
+//!
+//! Features include
+//! - [`gitignore`'s extended glob syntax][gitignore]
+//! - Control over symlink behavior
+//! - Control depth walked
+//! - Control order results are returned
+//!
+//! [gitignore]: https://git-scm.com/docs/gitignore#_pattern_format
+//!
+//! # Examples
+//!
+//! ## Finding image files in the current directory.
+//!
+//! ```rust
+//! extern crate globwalk;
+//! # include!("doctests.rs");
+//!
+//! use std::fs;
+//! # fn run() -> Result<(), Box<::std::error::Error>> {
+//! # let temp_dir = create_files(&["cow.jog", "cat.gif"])?;
+//! # ::std::env::set_current_dir(&temp_dir)?;
+//!
+//! for img in globwalk::glob("*.{png,jpg,gif}")? {
+//!     if let Ok(img) = img {
+//!         fs::remove_file(img.path())?;
+//!     }
+//! }
+//! # Ok(()) }
+//! # fn main() { run().unwrap() }
+//! ```
+//!
+//! ## Advanced Globbing ###
+//!
+//! By using one of the constructors of `globwalk::GlobWalker`, it is possible to alter the
+//! base-directory or add multiple patterns.
+//!
+//! ```rust
+//! extern crate globwalk;
+//! # include!("doctests.rs");
+//!
+//! use std::fs;
+//!
+//! # fn run() -> Result<(), Box<::std::error::Error>> {
+//! # let temp_dir = create_files(&["cow.jog", "cat.gif"])?;
+//! # let BASE_DIR = &temp_dir;
+//! let walker = globwalk::GlobWalkerBuilder::from_patterns(
+//!         BASE_DIR,
+//!         &["*.{png,jpg,gif}", "!Pictures/*"],
+//!     )
+//!     .max_depth(4)
+//!     .follow_links(true)
+//!     .build()?
+//!     .into_iter()
+//!     .filter_map(Result::ok);
+//!
+//! for img in walker {
+//!     fs::remove_file(img.path())?;
+//! }
+//! # Ok(()) }
+//! # fn main() { run().unwrap() }
+//! ```
+
+// Our doctests need main to compile; AFAICT this is a false positive generated by clippy
+#![allow(clippy::needless_doctest_main)]
+#![warn(missing_docs)]
+
+extern crate ignore;
+extern crate walkdir;
+
+extern crate bitflags;
+#[cfg(test)]
+extern crate tempdir;
+
+use ignore::overrides::{Override, OverrideBuilder};
+use ignore::Match;
+use std::cmp::Ordering;
+use std::path::Path;
+use std::path::PathBuf;
+use walkdir::WalkDir;
+
+/// Error from parsing globs.
+#[derive(Debug)]
+pub struct GlobError(ignore::Error);
+
+/// Error from iterating on files.
+pub type WalkError = walkdir::Error;
+/// A directory entry.
+///
+/// This is the type of value that is yielded from the iterators defined in this crate.
+pub type DirEntry = walkdir::DirEntry;
+
+impl From<std::io::Error> for GlobError {
+    fn from(e: std::io::Error) -> Self {
+        GlobError(e.into())
+    }
+}
+
+impl From<GlobError> for std::io::Error {
+    fn from(e: GlobError) -> Self {
+        if let ignore::Error::Io(e) = e.0 {
+            e
+        } else {
+            std::io::ErrorKind::Other.into()
+        }
+    }
+}
+
+impl std::fmt::Display for GlobError {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+        self.0.fmt(f)
+    }
+}
+
+impl std::error::Error for GlobError {
+    fn description(&self) -> &str {
+        self.0.description()
+    }
+}
+
+bitflags::bitflags! {
+    /// Possible file type filters.
+    /// Constants can be OR'd to filter for several types at a time.
+    ///
+    /// Note that not all files are represented in this enum.
+    /// For example, a char-device is neither a file, a directory, nor a symlink.
+    pub struct FileType: u32 {
+        #[allow(missing_docs)] const FILE =    0b001;
+        #[allow(missing_docs)] const DIR =     0b010;
+        #[allow(missing_docs)] const SYMLINK = 0b100;
+    }
+}
+
+/// An iterator for recursively yielding glob matches.
+///
+/// The order of elements yielded by this iterator is unspecified.
+pub struct GlobWalkerBuilder {
+    root: PathBuf,
+    patterns: Vec<String>,
+    walker: WalkDir,
+    case_insensitive: bool,
+    file_type: Option<FileType>,
+}
+
+impl GlobWalkerBuilder {
+    /// Construct a new `GlobWalker` with a glob pattern.
+    ///
+    /// When iterated, the `base` directory will be recursively searched for paths
+    /// matching `pattern`.
+    pub fn new<P, S>(base: P, pattern: S) -> Self
+    where
+        P: AsRef<Path>,
+        S: AsRef<str>,
+    {
+        GlobWalkerBuilder::from_patterns(base, &[pattern])
+    }
+
+    /// Construct a new `GlobWalker` from a list of patterns.
+    ///
+    /// When iterated, the `base` directory will be recursively searched for paths
+    /// matching `patterns`.
+    pub fn from_patterns<P, S>(base: P, patterns: &[S]) -> Self
+    where
+        P: AsRef<Path>,
+        S: AsRef<str>,
+    {
+        fn normalize_pattern<S: AsRef<str>>(pattern: S) -> String {
+            // Either `ignore` or our iteration code treat a single asterisk pretty strangely, matching everything, even
+            // paths that are inside a sub-direcrtory.
+            if pattern.as_ref() == "*" {
+                String::from("/*")
+            } else {
+                pattern.as_ref().to_owned()
+            }
+        }
+        GlobWalkerBuilder {
+            root: base.as_ref().into(),
+            patterns: patterns.iter().map(normalize_pattern).collect::<_>(),
+            walker: WalkDir::new(base),
+            case_insensitive: false,
+            file_type: None,
+        }
+    }
+
+    /// Set the minimum depth of entries yielded by the iterator.
+    ///
+    /// The smallest depth is `0` and always corresponds to the path given
+    /// to the `new` function on this type. Its direct descendents have depth
+    /// `1`, and their descendents have depth `2`, and so on.
+    pub fn min_depth(mut self, depth: usize) -> Self {
+        self.walker = self.walker.min_depth(depth);
+        self
+    }
+
+    /// Set the maximum depth of entries yield by the iterator.
+    ///
+    /// The smallest depth is `0` and always corresponds to the path given
+    /// to the `new` function on this type. Its direct descendents have depth
+    /// `1`, and their descendents have depth `2`, and so on.
+    ///
+    /// Note that this will not simply filter the entries of the iterator, but
+    /// it will actually avoid descending into directories when the depth is
+    /// exceeded.
+    pub fn max_depth(mut self, depth: usize) -> Self {
+        self.walker = self.walker.max_depth(depth);
+        self
+    }
+
+    /// Follow symbolic links. By default, this is disabled.
+    ///
+    /// When `yes` is `true`, symbolic links are followed as if they were
+    /// normal directories and files. If a symbolic link is broken or is
+    /// involved in a loop, an error is yielded.
+    ///
+    /// When enabled, the yielded [`DirEntry`] values represent the target of
+    /// the link while the path corresponds to the link. See the [`DirEntry`]
+    /// type for more details.
+    ///
+    /// [`DirEntry`]: struct.DirEntry.html
+    pub fn follow_links(mut self, yes: bool) -> Self {
+        self.walker = self.walker.follow_links(yes);
+        self
+    }
+
+    /// Set the maximum number of simultaneously open file descriptors used
+    /// by the iterator.
+    ///
+    /// `n` must be greater than or equal to `1`. If `n` is `0`, then it is set
+    /// to `1` automatically. If this is not set, then it defaults to some
+    /// reasonably low number.
+    ///
+    /// This setting has no impact on the results yielded by the iterator
+    /// (even when `n` is `1`). Instead, this setting represents a trade off
+    /// between scarce resources (file descriptors) and memory. Namely, when
+    /// the maximum number of file descriptors is reached and a new directory
+    /// needs to be opened to continue iteration, then a previous directory
+    /// handle is closed and has its unyielded entries stored in memory. In
+    /// practice, this is a satisfying trade off because it scales with respect
+    /// to the *depth* of your file tree. Therefore, low values (even `1`) are
+    /// acceptable.
+    ///
+    /// Note that this value does not impact the number of system calls made by
+    /// an exhausted iterator.
+    ///
+    /// # Platform behavior
+    ///
+    /// On Windows, if `follow_links` is enabled, then this limit is not
+    /// respected. In particular, the maximum number of file descriptors opened
+    /// is proportional to the depth of the directory tree traversed.
+    pub fn max_open(mut self, n: usize) -> Self {
+        self.walker = self.walker.max_open(n);
+        self
+    }
+
+    /// Set a function for sorting directory entries.
+    ///
+    /// If a compare function is set, the resulting iterator will return all
+    /// paths in sorted order. The compare function will be called to compare
+    /// entries from the same directory.
+    pub fn sort_by<F>(mut self, cmp: F) -> Self
+    where
+        F: FnMut(&DirEntry, &DirEntry) -> Ordering + Send + Sync + 'static,
+    {
+        self.walker = self.walker.sort_by(cmp);
+        self
+    }
+
+    /// Yield a directory's contents before the directory itself. By default,
+    /// this is disabled.
+    ///
+    /// When `yes` is `false` (as is the default), the directory is yielded
+    /// before its contents are read. This is useful when, e.g. you want to
+    /// skip processing of some directories.
+    ///
+    /// When `yes` is `true`, the iterator yields the contents of a directory
+    /// before yielding the directory itself. This is useful when, e.g. you
+    /// want to recursively delete a directory.
+    pub fn contents_first(mut self, yes: bool) -> Self {
+        self.walker = self.walker.contents_first(yes);
+        self
+    }
+
+    /// Toggle whether the globs should be matched case insensitively or not.
+    ///
+    /// This is disabled by default.
+    pub fn case_insensitive(mut self, yes: bool) -> Self {
+        self.case_insensitive = yes;
+        self
+    }
+
+    /// Toggle filtering by file type.
+    /// `FileType` can be an OR of several types.
+    ///
+    /// Note that not all file-types can be whitelisted by this filter (e.g. char-devices, fifos, etc.)
+    pub fn file_type(mut self, file_type: FileType) -> Self {
+        self.file_type = Some(file_type);
+        self
+    }
+
+    /// Finalize and build a `GlobWalker` instance.
+    pub fn build(self) -> Result<GlobWalker, GlobError> {
+        let mut builder = OverrideBuilder::new(self.root);
+
+        builder
+            .case_insensitive(self.case_insensitive)
+            .map_err(GlobError)?;
+
+        for pattern in self.patterns {
+            builder.add(pattern.as_ref()).map_err(GlobError)?;
+        }
+
+        Ok(GlobWalker {
+            ignore: builder.build().map_err(GlobError)?,
+            walker: self.walker.into_iter(),
+            file_type_filter: self.file_type,
+        })
+    }
+}
+
+/// An iterator which emits glob-matched patterns.
+///
+/// An instance of this type must be constructed through `GlobWalker`,
+/// which uses a builder-style pattern.
+///
+/// The order of the yielded paths is undefined, unless specified by the user
+/// using `GlobWalker::sort_by`.
+pub struct GlobWalker {
+    ignore: Override,
+    walker: walkdir::IntoIter,
+    file_type_filter: Option<FileType>,
+}
+
+impl Iterator for GlobWalker {
+    type Item = Result<DirEntry, WalkError>;
+
+    // Possible optimization - Do not descend into directory that will never be a match
+    fn next(&mut self) -> Option<Self::Item> {
+        let mut skip_dir = false;
+
+        // The outer loop allows us to avoid multiple mutable borrows on `self.walker` when
+        // we want to skip.
+        'skipper: loop {
+            if skip_dir {
+                self.walker.skip_current_dir();
+            }
+
+            // The inner loop just advances the iterator until a match is found.
+            for entry in &mut self.walker {
+                match entry {
+                    Ok(e) => {
+                        let is_dir = e.file_type().is_dir();
+
+                        let file_type = if e.file_type().is_dir() {
+                            Some(FileType::DIR)
+                        } else if e.file_type().is_file() {
+                            Some(FileType::FILE)
+                        } else if e.file_type().is_symlink() {
+                            Some(FileType::SYMLINK)
+                        } else {
+                            None
+                        };
+
+                        let file_type_matches = match (self.file_type_filter, file_type) {
+                            (None, _) => true,
+                            (Some(_), None) => false,
+                            (Some(filter), Some(actual)) => filter.contains(actual),
+                        };
+
+                        // Strip the common base directory so that the matcher will be
+                        // able to recognize the file name.
+                        // `unwrap` here is safe, since walkdir returns the files with relation
+                        // to the given base-dir.
+                        let path = e
+                            .path()
+                            .strip_prefix(self.ignore.path())
+                            .unwrap()
+                            .to_owned();
+
+                        // The path might be empty after stripping if the current base-directory is matched.
+                        if let Some("") = path.to_str() {
+                            continue 'skipper;
+                        }
+
+                        match self.ignore.matched(path, is_dir) {
+                            Match::Whitelist(_) if file_type_matches => return Some(Ok(e)),
+                            // If the directory is ignored, quit the iterator loop and
+                            // skip-out of this directory.
+                            Match::Ignore(_) if is_dir => {
+                                skip_dir = true;
+                                continue 'skipper;
+                            }
+                            _ => {}
+                        }
+                    }
+                    Err(e) => {
+                        return Some(Err(e));
+                    }
+                }
+            }
+            break;
+        }
+
+        None
+    }
+}
+
+/// Construct a new `GlobWalkerBuilder` with a glob pattern.
+///
+/// When iterated, the current directory will be recursively searched for paths
+/// matching `pattern`, unless the pattern specifies an absolute path.
+pub fn glob_builder<S: AsRef<str>>(pattern: S) -> GlobWalkerBuilder {
+    // Check to see if the pattern starts with an absolute path
+    let path_pattern: PathBuf = pattern.as_ref().into();
+    if path_pattern.is_absolute() {
+        // If the pattern is an absolute path, split it into the longest base and a pattern.
+        let mut base = PathBuf::new();
+        let mut pattern = PathBuf::new();
+        let mut globbing = false;
+
+        // All `to_str().unwrap()` calls should be valid since the input is a string.
+        for c in path_pattern.components() {
+            let os = c.as_os_str().to_str().unwrap();
+            for c in &["*", "{", "}"][..] {
+                if os.contains(c) {
+                    globbing = true;
+                    break;
+                }
+            }
+
+            if globbing {
+                pattern.push(c);
+            } else {
+                base.push(c);
+            }
+        }
+
+        let pat = pattern.to_str().unwrap();
+        if cfg!(windows) {
+            GlobWalkerBuilder::new(base.to_str().unwrap(), pat.replace("\\", "/"))
+        } else {
+            GlobWalkerBuilder::new(base.to_str().unwrap(), pat)
+        }
+    } else {
+        // If the pattern is relative, start searching from the current directory.
+        GlobWalkerBuilder::new(".", pattern)
+    }
+}
+
+/// Construct a new `GlobWalker` with a glob pattern.
+///
+/// When iterated, the current directory will be recursively searched for paths
+/// matching `pattern`, unless the pattern specifies an absolute path.
+pub fn glob<S: AsRef<str>>(pattern: S) -> Result<GlobWalker, GlobError> {
+    glob_builder(pattern).build()
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use std::fs::{create_dir_all, File};
+    use tempdir::TempDir;
+
+    fn touch(dir: &TempDir, names: &[&str]) {
+        for name in names {
+            let name = normalize_path_sep(name);
+            File::create(dir.path().join(name)).expect("Failed to create a test file");
+        }
+    }
+
+    fn normalize_path_sep<S: AsRef<str>>(s: S) -> String {
+        s.as_ref()
+            .replace("[/]", if cfg!(windows) { "\\" } else { "/" })
+    }
+
+    fn equate_to_expected(g: GlobWalker, mut expected: Vec<String>, dir_path: &Path) {
+        for matched_file in g.into_iter().filter_map(Result::ok) {
+            let path = matched_file
+                .path()
+                .strip_prefix(dir_path)
+                .unwrap()
+                .to_str()
+                .unwrap();
+            let path = normalize_path_sep(path);
+
+            let del_idx = if let Some(idx) = expected.iter().position(|n| &path == n) {
+                idx
+            } else {
+                panic!("Iterated file is unexpected: {}", path);
+            };
+
+            expected.remove(del_idx);
+        }
+
+        // Not equating `.len() == 0` so that the assertion output
+        // will contain the extra files
+        let empty: &[&str] = &[][..];
+        assert_eq!(expected, empty);
+    }
+
+    #[test]
+    fn test_absolute_path() {
+        let dir = TempDir::new("globset_walkdir").expect("Failed to create temporary folder");
+        let dir_path = dir.path().canonicalize().unwrap();
+
+        touch(&dir, &["a.rs", "a.jpg", "a.png", "b.docx"][..]);
+
+        let expected = ["a.jpg", "a.png"].iter().map(ToString::to_string).collect();
+        let mut cwd = dir_path.clone();
+        cwd.push("*.{png,jpg,gif}");
+
+        let glob = glob(cwd.to_str().unwrap().to_owned()).unwrap();
+        equate_to_expected(glob, expected, &dir_path);
+    }
+
+    #[test]
+    fn test_new() {
+        let dir = TempDir::new("globset_walkdir").expect("Failed to create temporary folder");
+        let dir_path = dir.path();
+
+        touch(&dir, &["a.rs", "a.jpg", "a.png", "b.docx"][..]);
+
+        let expected = ["a.jpg", "a.png"].iter().map(ToString::to_string).collect();
+
+        let g = GlobWalkerBuilder::new(dir_path, "*.{png,jpg,gif}")
+            .build()
+            .unwrap();
+
+        equate_to_expected(g, expected, dir_path);
+    }
+
+    #[test]
+    fn test_from_patterns() {
+        let dir = TempDir::new("globset_walkdir").expect("Failed to create temporary folder");
+        let dir_path = dir.path();
+        create_dir_all(dir_path.join("src/some_mod")).expect("");
+        create_dir_all(dir_path.join("tests")).expect("");
+        create_dir_all(dir_path.join("contrib")).expect("");
+
+        touch(
+            &dir,
+            &[
+                "a.rs",
+                "b.rs",
+                "avocado.rs",
+                "lib.c",
+                "src[/]hello.rs",
+                "src[/]world.rs",
+                "src[/]some_mod[/]unexpected.rs",
+                "src[/]cruel.txt",
+                "contrib[/]README.md",
+                "contrib[/]README.rst",
+                "contrib[/]lib.rs",
+            ][..],
+        );
+
+        let expected: Vec<_> = [
+            "src[/]some_mod[/]unexpected.rs",
+            "src[/]world.rs",
+            "src[/]hello.rs",
+            "lib.c",
+            "contrib[/]lib.rs",
+            "contrib[/]README.md",
+            "contrib[/]README.rst",
+        ]
+        .iter()
+        .map(normalize_path_sep)
+        .collect();
+
+        let patterns = ["src/**/*.rs", "*.c", "**/lib.rs", "**/*.{md,rst}"];
+        let glob = GlobWalkerBuilder::from_patterns(dir_path, &patterns)
+            .build()
+            .unwrap();
+
+        equate_to_expected(glob, expected, dir_path);
+    }
+
+    #[test]
+    fn test_case_insensitive_matching() {
+        let dir = TempDir::new("globset_walkdir").expect("Failed to create temporary folder");
+        let dir_path = dir.path();
+        create_dir_all(dir_path.join("src/some_mod")).expect("");
+        create_dir_all(dir_path.join("tests")).expect("");
+        create_dir_all(dir_path.join("contrib")).expect("");
+
+        touch(
+            &dir,
+            &[
+                "a.rs",
+                "b.rs",
+                "avocado.RS",
+                "lib.c",
+                "src[/]hello.RS",
+                "src[/]world.RS",
+                "src[/]some_mod[/]unexpected.rs",
+                "src[/]cruel.txt",
+                "contrib[/]README.md",
+                "contrib[/]README.rst",
+                "contrib[/]lib.rs",
+            ][..],
+        );
+
+        let expected: Vec<_> = [
+            "src[/]some_mod[/]unexpected.rs",
+            "src[/]hello.RS",
+            "src[/]world.RS",
+            "lib.c",
+            "contrib[/]lib.rs",
+            "contrib[/]README.md",
+            "contrib[/]README.rst",
+        ]
+        .iter()
+        .map(normalize_path_sep)
+        .collect();
+
+        let patterns = ["src/**/*.rs", "*.c", "**/lib.rs", "**/*.{md,rst}"];
+        let glob = GlobWalkerBuilder::from_patterns(dir_path, &patterns)
+            .case_insensitive(true)
+            .build()
+            .unwrap();
+
+        equate_to_expected(glob, expected, dir_path);
+    }
+
+    #[test]
+    fn test_match_dir() {
+        let dir = TempDir::new("globset_walkdir").expect("Failed to create temporary folder");
+        let dir_path = dir.path();
+        create_dir_all(dir_path.join("mod")).expect("");
+
+        touch(
+            &dir,
+            &[
+                "a.png",
+                "b.png",
+                "c.png",
+                "mod[/]a.png",
+                "mod[/]b.png",
+                "mod[/]c.png",
+            ][..],
+        );
+
+        let expected: Vec<_> = ["mod"].iter().map(normalize_path_sep).collect();
+        let glob = GlobWalkerBuilder::new(dir_path, "mod").build().unwrap();
+
+        equate_to_expected(glob, expected, dir_path);
+    }
+
+    #[test]
+    fn test_blacklist() {
+        let dir = TempDir::new("globset_walkdir").expect("Failed to create temporary folder");
+        let dir_path = dir.path();
+        create_dir_all(dir_path.join("src/some_mod")).expect("");
+        create_dir_all(dir_path.join("tests")).expect("");
+        create_dir_all(dir_path.join("contrib")).expect("");
+
+        touch(
+            &dir,
+            &[
+                "a.rs",
+                "b.rs",
+                "avocado.rs",
+                "lib.c",
+                "src[/]hello.rs",
+                "src[/]world.rs",
+                "src[/]some_mod[/]unexpected.rs",
+                "src[/]cruel.txt",
+                "contrib[/]README.md",
+                "contrib[/]README.rst",
+                "contrib[/]lib.rs",
+            ][..],
+        );
+
+        let expected: Vec<_> = [
+            "src[/]some_mod[/]unexpected.rs",
+            "src[/]hello.rs",
+            "lib.c",
+            "contrib[/]lib.rs",
+            "contrib[/]README.md",
+            "contrib[/]README.rst",
+        ]
+        .iter()
+        .map(normalize_path_sep)
+        .collect();
+
+        let patterns = [
+            "src/**/*.rs",
+            "*.c",
+            "**/lib.rs",
+            "**/*.{md,rst}",
+            "!world.rs",
+        ];
+
+        let glob = GlobWalkerBuilder::from_patterns(dir_path, &patterns)
+            .build()
+            .unwrap();
+
+        equate_to_expected(glob, expected, dir_path);
+    }
+
+    #[test]
+    fn test_blacklist_dir() {
+        let dir = TempDir::new("globset_walkdir").expect("Failed to create temporary folder");
+        let dir_path = dir.path();
+        create_dir_all(dir_path.join("Pictures")).expect("");
+
+        touch(
+            &dir,
+            &[
+                "a.png",
+                "b.png",
+                "c.png",
+                "Pictures[/]a.png",
+                "Pictures[/]b.png",
+                "Pictures[/]c.png",
+            ][..],
+        );
+
+        let expected: Vec<_> = ["a.png", "b.png", "c.png"]
+            .iter()
+            .map(normalize_path_sep)
+            .collect();
+
+        let patterns = ["*.{png,jpg,gif}", "!Pictures"];
+        let glob = GlobWalkerBuilder::from_patterns(dir_path, &patterns)
+            .build()
+            .unwrap();
+
+        equate_to_expected(glob, expected, dir_path);
+    }
+
+    #[test]
+    fn test_glob_with_double_star_pattern() {
+        let dir = TempDir::new("globset_walkdir").expect("Failed to create temporary folder");
+        let dir_path = dir.path().canonicalize().unwrap();
+
+        touch(&dir, &["a.rs", "a.jpg", "a.png", "b.docx"][..]);
+
+        let expected = ["a.jpg", "a.png"].iter().map(ToString::to_string).collect();
+        let mut cwd = dir_path.clone();
+        cwd.push("**");
+        cwd.push("*.{png,jpg,gif}");
+        let glob = glob(cwd.to_str().unwrap().to_owned()).unwrap();
+        equate_to_expected(glob, expected, &dir_path);
+    }
+
+    #[test]
+    fn test_glob_single_star() {
+        let dir = TempDir::new("globset_walkdir").expect("Failed to create temporary folder");
+        let dir_path = dir.path();
+        create_dir_all(dir_path.join("Pictures")).expect("");
+        create_dir_all(dir_path.join("Pictures").join("b")).expect("");
+
+        touch(
+            &dir,
+            &[
+                "a.png",
+                "b.png",
+                "c.png",
+                "Pictures[/]a.png",
+                "Pictures[/]b.png",
+                "Pictures[/]c.png",
+                "Pictures[/]b[/]c.png",
+                "Pictures[/]b[/]c.png",
+                "Pictures[/]b[/]c.png",
+            ][..],
+        );
+
+        let glob = GlobWalkerBuilder::new(dir_path, "*")
+            .sort_by(|a, b| a.path().cmp(b.path()))
+            .build()
+            .unwrap();
+        let expected = ["Pictures", "a.png", "b.png", "c.png"]
+            .iter()
+            .map(ToString::to_string)
+            .collect();
+        equate_to_expected(glob, expected, dir_path);
+    }
+
+    #[test]
+    fn test_file_type() {
+        let dir = TempDir::new("globset_walkdir").expect("Failed to create temporary folder");
+        let dir_path = dir.path();
+        create_dir_all(dir_path.join("Pictures")).expect("");
+        create_dir_all(dir_path.join("Pictures").join("b")).expect("");
+
+        touch(
+            &dir,
+            &[
+                "a.png",
+                "b.png",
+                "c.png",
+                "Pictures[/]a.png",
+                "Pictures[/]b.png",
+                "Pictures[/]c.png",
+                "Pictures[/]b[/]c.png",
+                "Pictures[/]b[/]c.png",
+                "Pictures[/]b[/]c.png",
+            ][..],
+        );
+
+        let glob = GlobWalkerBuilder::new(dir_path, "*")
+            .sort_by(|a, b| a.path().cmp(b.path()))
+            .file_type(FileType::DIR)
+            .build()
+            .unwrap();
+        let expected = ["Pictures"].iter().map(ToString::to_string).collect();
+        equate_to_expected(glob, expected, dir_path);
+
+        let glob = GlobWalkerBuilder::new(dir_path, "*")
+            .sort_by(|a, b| a.path().cmp(b.path()))
+            .file_type(FileType::FILE)
+            .build()
+            .unwrap();
+        let expected = ["a.png", "b.png", "c.png"]
+            .iter()
+            .map(ToString::to_string)
+            .collect();
+        equate_to_expected(glob, expected, dir_path);
+    }
+}
diff --git a/vendor/globwalk/tests/docs.rs b/vendor/globwalk/tests/docs.rs
new file mode 100644 (file)
index 0000000..1d51e99
--- /dev/null
@@ -0,0 +1,10 @@
+extern crate docmatic;
+
+#[test]
+fn readme_test() {
+    let readme = std::path::Path::new(file!()).canonicalize().unwrap();
+    let readme = readme.parent().unwrap().parent().unwrap().join("README.md");
+    let readme = readme.to_str().unwrap();
+
+    docmatic::assert_file(readme);
+}
diff --git a/vendor/hashbrown-0.9.1/.cargo-checksum.json b/vendor/hashbrown-0.9.1/.cargo-checksum.json
deleted file mode 100644 (file)
index 53328fd..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"CHANGELOG.md":"5a7c89b011b8a47ae3c3097d0badc86dadeac1084ce459cc9888f3f6519d7e47","Cargo.toml":"ba475021bd4563dde7d812713dbb79fc9fc7f522ad58bd0deaeed9ebadff69ef","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ff8f68cb076caf8cefe7a6430d4ac086ce6af2ca8ce2c4e5a2004d4552ef52a2","README.md":"29d265575e99c6e4b8960fa0a17571580c8973b91b1b2ce63b9b83f8e1bdc58a","benches/bench.rs":"a3f8426559ebf68d93e37edee0bf83c28f18572b394b22e47dbff33e25cac403","clippy.toml":"7535949f908c6d9aea4f9a9f3a7625552c93fc29e963d059d40f4def9d77ea7b","src/external_trait_impls/mod.rs":"d69528827794524cfd9acbeacc1ac4f6131e3c7574311e6d919f818f65fbff07","src/external_trait_impls/rayon/helpers.rs":"d4fbca4db924925548f8dab8eb94cf4a3955a53c5e1ff15f59c460546c394034","src/external_trait_impls/rayon/map.rs":"eee0d42bd8cd347d49cfb1332f15297ca63b864c3690299a3ccd6d52c22c67de","src/external_trait_impls/rayon/mod.rs":"156de9c1ad0123334ea3b7e5a17444faf1b8bf971aa88a1f23e2f2d1c3021141","src/external_trait_impls/rayon/raw.rs":"d1b2415a4c3c42279f99a23bcf45c80ddb9a641c7f7974d42ed4d55f57bf6854","src/external_trait_impls/rayon/set.rs":"59afc7b1cdc985a85952d456e34eada4ca2fedf90d2a14dccf98a69f8f496137","src/external_trait_impls/serde.rs":"9306fb6e0e339398dc23ba9e7400a9a28d713df248e8b260e3d4dc44f799e101","src/lib.rs":"a455a0387b0133114247380659c2825713a4b91ef38a45f737007b47a2c30ee4","src/macros.rs":"0b1e9a55e8f5232b82f7e56f352a98904b35ddfca015377cf71daa31939baabf","src/map.rs":"56dc55edfd3c818d8c69464ec9edce9e3fe40e5975c02a2965e0a15878a08295","src/raw/bitmask.rs":"05e72c64957af7383001ca43a827cc5b3a8a39d00fac332ecea2fd7d2704099c","src/raw/generic.rs":"28da6bb3a722dcaa26cb5aba9e028111f32212dc9ce0c323e8f39ff5f367385e","src/raw/mod.rs":"ad887f865799502e852a3c100a49cc785ee97cb755b8394b31f87ed24fffa836","src/raw/sse2.rs":"ff332a9104558fe6a86b85ab975b6f43d4a042c634d5dc6cf70cf1d71d97ad7d","src/rustc_entry.rs":"64e47870015a9f152340017b79e2262e5c70d0f42b4fc2dfa48dd25ca70465f7","src/scopeguard.rs":"337cde60c9e1109cd19d4fa53529014cef1e3d5900dffde82f647881df1505f7","src/set.rs":"4ec68cf40a41bbc50da754047893640c62c55f612e03c43e3e3e837a23defc6d","tests/hasher.rs":"9a8fdf67e4415618e16729969c386eefe71408cded5d46cf7b67d969276a3452","tests/rayon.rs":"2286707a87b139f41902c82488c355b9fb402a3e734f392f3a73e87b9b932795","tests/serde.rs":"eed27382c0e43f67e402cd9eed20dea23ef5582e1a26a183e708ca9217a559e0","tests/set.rs":"374bd312c01a01cf8953bbbc9494f431b260c2657d7c79cc250e977b869a76ad"},"package":"d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"}
\ No newline at end of file
diff --git a/vendor/hashbrown-0.9.1/CHANGELOG.md b/vendor/hashbrown-0.9.1/CHANGELOG.md
deleted file mode 100644 (file)
index b6eb671..0000000
+++ /dev/null
@@ -1,294 +0,0 @@
-# Change Log
-
-All notable changes to this project will be documented in this file.
-
-The format is based on [Keep a Changelog](http://keepachangelog.com/)
-and this project adheres to [Semantic Versioning](http://semver.org/).
-
-## [Unreleased]
-
-## [v0.9.1] - 2020-09-28
-
-## Added
-- Added safe methods to `RawTable` (#202):
-  - `get`: `find` and `as_ref`
-  - `get_mut`: `find` and `as_mut`
-  - `insert_entry`: `insert` and `as_mut`
-  - `remove_entry`: `find` and `remove`
-  - `erase_entry`: `find` and `erase`
-
-## Changed
-- Removed `from_key_hashed_nocheck`'s `Q: Hash`. (#200)
-- Made `RawTable::drain` safe. (#201)
-
-## [v0.9.0] - 2020-09-03
-
-### Fixed
-- `drain_filter` now removes and yields items that do match the predicate,
-  rather than items that don't.  This is a **breaking change** to match the
-  behavior of the `drain_filter` methods in `std`. (#187)
-
-### Added
-- Added `replace_entry_with` to `OccupiedEntry`, and `and_replace_entry_with` to `Entry`. (#190)
-- Implemented `FusedIterator` and `size_hint` for `DrainFilter`. (#188)
-
-### Changed
-- The minimum Rust version has been bumped to 1.36 (due to `crossbeam` dependency). (#193)
-- Updated `ahash` dependency to 0.4. (#198)
-- `HashMap::with_hasher` and `HashSet::with_hasher` are now `const fn`. (#195)
-- Removed `T: Hash + Eq` and `S: BuildHasher` bounds on `HashSet::new`,
-  `with_capacity`, `with_hasher`, and `with_capacity_and_hasher`.  (#185)
-
-## [v0.8.2] - 2020-08-08
-
-### Changed
-- Avoid closures to improve compile times. (#183)
-- Do not iterate to drop if empty. (#182)
-
-## [v0.8.1] - 2020-07-16
-
-### Added
-- Added `erase` and `remove` to `RawTable`. (#171)
-- Added `try_with_capacity` to `RawTable`. (#174)
-- Added methods that allow re-using a `RawIter` for `RawDrain`,
-  `RawIntoIter`, and `RawParIter`. (#175)
-- Added `reflect_remove` and `reflect_insert` to `RawIter`. (#175)
-- Added a `drain_filter` function to `HashSet`. (#179)
-
-### Changed
-- Deprecated `RawTable::erase_no_drop` in favor of `erase` and `remove`. (#176)
-- `insert_no_grow` is now exposed under the `"raw"` feature. (#180)
-
-## [v0.8.0] - 2020-06-18
-
-### Fixed
-- Marked `RawTable::par_iter` as `unsafe`. (#157)
-
-### Changed
-- Reduced the size of `HashMap`. (#159)
-- No longer create tables with a capacity of 1 element. (#162)
-- Removed `K: Eq + Hash` bounds on `retain`. (#163)
-- Pulled in `HashMap` changes from rust-lang/rust (#164):
-  - `extend_one` support on nightly.
-  - `CollectionAllocErr` renamed to `TryReserveError`.
-  - Added `HashSet::get_or_insert_owned`.
-  - `Default` for `HashSet` no longer requires `T: Eq + Hash` and `S: BuildHasher`.
-
-## [v0.7.2] - 2020-04-27
-
-### Added
-- Added `or_insert_with_key` to `Entry`. (#152)
-
-### Fixed
-- Partially reverted `Clone` optimization which was unsound. (#154)
-
-### Changed
-- Disabled use of `const-random` by default, which prevented reproducible builds. (#155)
-- Optimized `repeat` function. (#150)
-- Use `NonNull` for buckets, which improves codegen for iterators. (#148)
-
-## [v0.7.1] - 2020-03-16
-
-### Added
-- Added `HashMap::get_key_value_mut`. (#145)
-
-### Changed
-- Optimized `Clone` implementation. (#146)
-
-## [v0.7.0] - 2020-01-31
-
-### Added
-- Added a `drain_filter` function to `HashMap`. (#135)
-
-### Changed
-- Updated `ahash` dependency to 0.3. (#141)
-- Optimized set union and intersection. (#130)
-- `raw_entry` can now be used without requiring `S: BuildHasher`. (#123)
-- `RawTable::bucket_index` can now be used under the `raw` feature. (#128)
-
-## [v0.6.3] - 2019-10-31
-
-### Added
-- Added an `ahash-compile-time-rng` feature (enabled by default) which allows disabling the
-  `compile-time-rng` feature in `ahash` to work around a Cargo bug. (#125)
-
-## [v0.6.2] - 2019-10-23
-
-### Added
-- Added an `inline-more` feature (enabled by default) which allows choosing a tradeoff between 
-  runtime performance and compilation time. (#119)
-
-## [v0.6.1] - 2019-10-04
-
-### Added
-- Added `Entry::insert` and `RawEntryMut::insert`. (#118)
-
-### Changed
-- `Group::static_empty` was changed from a `const` to a `static` (#116).
-
-## [v0.6.0] - 2019-08-13
-
-### Fixed
-- Fixed AHash accidentally depending on `std`. (#110)
-
-### Changed
-- The minimum Rust version has been bumped to 1.32 (due to `rand` dependency).
-
-## ~~[v0.5.1] - 2019-08-04~~
-
-This release was _yanked_ due to a breaking change for users of `no-default-features`.
-
-### Added
-- The experimental and unsafe `RawTable` API is available under the "raw" feature. (#108)
-- Added entry-like methods for `HashSet`. (#98)
-
-### Changed
-- Changed the default hasher from FxHash to AHash. (#97)
-- `hashbrown` is now fully `no_std` on recent Rust versions (1.36+). (#96)
-
-### Fixed
-- We now avoid growing the table during insertions when it wasn't necessary. (#106)
-- `RawOccupiedEntryMut` now properly implements `Send` and `Sync`. (#100)
-- Relaxed `lazy_static` version. (#92)
-
-## [v0.5.0] - 2019-06-12
-
-### Fixed
-- Resize with a more conservative amount of space after deletions. (#86)
-
-### Changed
-- Exposed the Layout of the failed allocation in CollectionAllocErr::AllocErr. (#89)
-
-## [v0.4.0] - 2019-05-30
-
-### Fixed
-- Fixed `Send` trait bounds on `IterMut` not matching the libstd one. (#82)
-
-## [v0.3.1] - 2019-05-30
-
-### Fixed
-- Fixed incorrect use of slice in unsafe code. (#80)
-
-## [v0.3.0] - 2019-04-23
-
-### Changed
-- Changed shrink_to to not panic if min_capacity < capacity. (#67)
-
-### Fixed
-- Worked around emscripten bug emscripten-core/emscripten-fastcomp#258. (#66)
-
-## [v0.2.2] - 2019-04-16
-
-### Fixed
-- Inlined non-nightly lowest_set_bit_nonzero. (#64)
-- Fixed build on latest nightly. (#65)
-
-## [v0.2.1] - 2019-04-14
-
-### Changed
-- Use for_each in map Extend and FromIterator. (#58)
-- Improved worst-case performance of HashSet.is_subset. (#61)
-
-### Fixed
-- Removed incorrect debug_assert. (#60)
-
-## [v0.2.0] - 2019-03-31
-
-### Changed
-- The code has been updated to Rust 2018 edition. This means that the minimum
-  Rust version has been bumped to 1.31 (2018 edition).
-
-### Added
-- Added `insert_with_hasher` to the raw_entry API to allow `K: !(Hash + Eq)`. (#54)
-- Added support for using hashbrown as the hash table implementation in libstd. (#46)
-
-### Fixed
-- Fixed cargo build with minimal-versions. (#45)
-- Fixed `#[may_dangle]` attributes to match the libstd `HashMap`. (#46)
-- ZST keys and values are now handled properly. (#46)
-
-## [v0.1.8] - 2019-01-14
-
-### Added
-- Rayon parallel iterator support (#37)
-- `raw_entry` support (#31)
-- `#[may_dangle]` on nightly (#31)
-- `try_reserve` support (#31)
-
-### Fixed
-- Fixed variance on `IterMut`. (#31)
-
-## [v0.1.7] - 2018-12-05
-
-### Fixed
-- Fixed non-SSE version of convert_special_to_empty_and_full_to_deleted. (#32)
-- Fixed overflow in rehash_in_place. (#33)
-
-## [v0.1.6] - 2018-11-17
-
-### Fixed
-- Fixed compile error on nightly. (#29)
-
-## [v0.1.5] - 2018-11-08
-
-### Fixed
-- Fixed subtraction overflow in generic::Group::match_byte. (#28)
-
-## [v0.1.4] - 2018-11-04
-
-### Fixed
-- Fixed a bug in the `erase_no_drop` implementation. (#26)
-
-## [v0.1.3] - 2018-11-01
-
-### Added
-- Serde support. (#14)
-
-### Fixed
-- Make the compiler inline functions more aggressively. (#20)
-
-## [v0.1.2] - 2018-10-31
-
-### Fixed
-- `clear` segfaults when called on an empty table. (#13)
-
-## [v0.1.1] - 2018-10-30
-
-### Fixed
-- `erase_no_drop` optimization not triggering in the SSE2 implementation. (#3)
-- Missing `Send` and `Sync` for hash map and iterator types. (#7)
-- Bug when inserting into a table smaller than the group width. (#5)
-
-## v0.1.0 - 2018-10-29
-
-- Initial release
-
-[Unreleased]: https://github.com/rust-lang/hashbrown/compare/v0.9.1...HEAD
-[v0.9.1]: https://github.com/rust-lang/hashbrown/compare/v0.9.0...v0.9.1
-[v0.9.0]: https://github.com/rust-lang/hashbrown/compare/v0.8.2...v0.9.0
-[v0.8.2]: https://github.com/rust-lang/hashbrown/compare/v0.8.1...v0.8.2
-[v0.8.1]: https://github.com/rust-lang/hashbrown/compare/v0.8.0...v0.8.1
-[v0.8.0]: https://github.com/rust-lang/hashbrown/compare/v0.7.2...v0.8.0
-[v0.7.2]: https://github.com/rust-lang/hashbrown/compare/v0.7.1...v0.7.2
-[v0.7.1]: https://github.com/rust-lang/hashbrown/compare/v0.7.0...v0.7.1
-[v0.7.0]: https://github.com/rust-lang/hashbrown/compare/v0.6.3...v0.7.0
-[v0.6.3]: https://github.com/rust-lang/hashbrown/compare/v0.6.2...v0.6.3
-[v0.6.2]: https://github.com/rust-lang/hashbrown/compare/v0.6.1...v0.6.2
-[v0.6.1]: https://github.com/rust-lang/hashbrown/compare/v0.6.0...v0.6.1
-[v0.6.0]: https://github.com/rust-lang/hashbrown/compare/v0.5.1...v0.6.0
-[v0.5.1]: https://github.com/rust-lang/hashbrown/compare/v0.5.0...v0.5.1
-[v0.5.0]: https://github.com/rust-lang/hashbrown/compare/v0.4.0...v0.5.0
-[v0.4.0]: https://github.com/rust-lang/hashbrown/compare/v0.3.1...v0.4.0
-[v0.3.1]: https://github.com/rust-lang/hashbrown/compare/v0.3.0...v0.3.1
-[v0.3.0]: https://github.com/rust-lang/hashbrown/compare/v0.2.2...v0.3.0
-[v0.2.2]: https://github.com/rust-lang/hashbrown/compare/v0.2.1...v0.2.2
-[v0.2.1]: https://github.com/rust-lang/hashbrown/compare/v0.2.0...v0.2.1
-[v0.2.0]: https://github.com/rust-lang/hashbrown/compare/v0.1.8...v0.2.0
-[v0.1.8]: https://github.com/rust-lang/hashbrown/compare/v0.1.7...v0.1.8
-[v0.1.7]: https://github.com/rust-lang/hashbrown/compare/v0.1.6...v0.1.7
-[v0.1.6]: https://github.com/rust-lang/hashbrown/compare/v0.1.5...v0.1.6
-[v0.1.5]: https://github.com/rust-lang/hashbrown/compare/v0.1.4...v0.1.5
-[v0.1.4]: https://github.com/rust-lang/hashbrown/compare/v0.1.3...v0.1.4
-[v0.1.3]: https://github.com/rust-lang/hashbrown/compare/v0.1.2...v0.1.3
-[v0.1.2]: https://github.com/rust-lang/hashbrown/compare/v0.1.1...v0.1.2
-[v0.1.1]: https://github.com/rust-lang/hashbrown/compare/v0.1.0...v0.1.1
diff --git a/vendor/hashbrown-0.9.1/Cargo.toml b/vendor/hashbrown-0.9.1/Cargo.toml
deleted file mode 100644 (file)
index 7be0341..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-edition = "2018"
-name = "hashbrown"
-version = "0.9.1"
-authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
-exclude = [".travis.yml", "bors.toml", "/ci/*"]
-description = "A Rust port of Google's SwissTable hash map"
-readme = "README.md"
-keywords = ["hash", "no_std", "hashmap", "swisstable"]
-categories = ["data-structures", "no-std"]
-license = "Apache-2.0/MIT"
-repository = "https://github.com/rust-lang/hashbrown"
-[package.metadata.docs.rs]
-features = ["nightly", "rayon", "serde", "raw"]
-[dependencies.ahash]
-version = "0.4.4"
-optional = true
-default-features = false
-
-[dependencies.alloc]
-version = "1.0.0"
-optional = true
-package = "rustc-std-workspace-alloc"
-
-[dependencies.compiler_builtins]
-version = "0.1.2"
-optional = true
-
-[dependencies.core]
-version = "1.0.0"
-optional = true
-package = "rustc-std-workspace-core"
-
-[dependencies.rayon]
-version = "1.0"
-optional = true
-
-[dependencies.serde]
-version = "1.0.25"
-optional = true
-default-features = false
-[dev-dependencies.doc-comment]
-version = "0.3.1"
-
-[dev-dependencies.lazy_static]
-version = "1.2"
-
-[dev-dependencies.rand]
-version = "0.7.3"
-features = ["small_rng"]
-
-[dev-dependencies.rayon]
-version = "1.0"
-
-[dev-dependencies.rustc-hash]
-version = "=1.0"
-
-[dev-dependencies.serde_test]
-version = "1.0"
-
-[features]
-ahash-compile-time-rng = ["ahash/compile-time-rng"]
-default = ["ahash", "inline-more"]
-inline-more = []
-nightly = []
-raw = []
-rustc-dep-of-std = ["nightly", "core", "compiler_builtins", "alloc", "rustc-internal-api"]
-rustc-internal-api = []
diff --git a/vendor/hashbrown-0.9.1/LICENSE-APACHE b/vendor/hashbrown-0.9.1/LICENSE-APACHE
deleted file mode 100644 (file)
index 16fe87b..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-                              Apache License
-                        Version 2.0, January 2004
-                     http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-   "License" shall mean the terms and conditions for use, reproduction,
-   and distribution as defined by Sections 1 through 9 of this document.
-
-   "Licensor" shall mean the copyright owner or entity authorized by
-   the copyright owner that is granting the License.
-
-   "Legal Entity" shall mean the union of the acting entity and all
-   other entities that control, are controlled by, or are under common
-   control with that entity. For the purposes of this definition,
-   "control" means (i) the power, direct or indirect, to cause the
-   direction or management of such entity, whether by contract or
-   otherwise, or (ii) ownership of fifty percent (50%) or more of the
-   outstanding shares, or (iii) beneficial ownership of such entity.
-
-   "You" (or "Your") shall mean an individual or Legal Entity
-   exercising permissions granted by this License.
-
-   "Source" form shall mean the preferred form for making modifications,
-   including but not limited to software source code, documentation
-   source, and configuration files.
-
-   "Object" form shall mean any form resulting from mechanical
-   transformation or translation of a Source form, including but
-   not limited to compiled object code, generated documentation,
-   and conversions to other media types.
-
-   "Work" shall mean the work of authorship, whether in Source or
-   Object form, made available under the License, as indicated by a
-   copyright notice that is included in or attached to the work
-   (an example is provided in the Appendix below).
-
-   "Derivative Works" shall mean any work, whether in Source or Object
-   form, that is based on (or derived from) the Work and for which the
-   editorial revisions, annotations, elaborations, or other modifications
-   represent, as a whole, an original work of authorship. For the purposes
-   of this License, Derivative Works shall not include works that remain
-   separable from, or merely link (or bind by name) to the interfaces of,
-   the Work and Derivative Works thereof.
-
-   "Contribution" shall mean any work of authorship, including
-   the original version of the Work and any modifications or additions
-   to that Work or Derivative Works thereof, that is intentionally
-   submitted to Licensor for inclusion in the Work by the copyright owner
-   or by an individual or Legal Entity authorized to submit on behalf of
-   the copyright owner. For the purposes of this definition, "submitted"
-   means any form of electronic, verbal, or written communication sent
-   to the Licensor or its representatives, including but not limited to
-   communication on electronic mailing lists, source code control systems,
-   and issue tracking systems that are managed by, or on behalf of, the
-   Licensor for the purpose of discussing and improving the Work, but
-   excluding communication that is conspicuously marked or otherwise
-   designated in writing by the copyright owner as "Not a Contribution."
-
-   "Contributor" shall mean Licensor and any individual or Legal Entity
-   on behalf of whom a Contribution has been received by Licensor and
-   subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   copyright license to reproduce, prepare Derivative Works of,
-   publicly display, publicly perform, sublicense, and distribute the
-   Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   (except as stated in this section) patent license to make, have made,
-   use, offer to sell, sell, import, and otherwise transfer the Work,
-   where such license applies only to those patent claims licensable
-   by such Contributor that are necessarily infringed by their
-   Contribution(s) alone or by combination of their Contribution(s)
-   with the Work to which such Contribution(s) was submitted. If You
-   institute patent litigation against any entity (including a
-   cross-claim or counterclaim in a lawsuit) alleging that the Work
-   or a Contribution incorporated within the Work constitutes direct
-   or contributory patent infringement, then any patent licenses
-   granted to You under this License for that Work shall terminate
-   as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
-   Work or Derivative Works thereof in any medium, with or without
-   modifications, and in Source or Object form, provided that You
-   meet the following conditions:
-
-   (a) You must give any other recipients of the Work or
-       Derivative Works a copy of this License; and
-
-   (b) You must cause any modified files to carry prominent notices
-       stating that You changed the files; and
-
-   (c) You must retain, in the Source form of any Derivative Works
-       that You distribute, all copyright, patent, trademark, and
-       attribution notices from the Source form of the Work,
-       excluding those notices that do not pertain to any part of
-       the Derivative Works; and
-
-   (d) If the Work includes a "NOTICE" text file as part of its
-       distribution, then any Derivative Works that You distribute must
-       include a readable copy of the attribution notices contained
-       within such NOTICE file, excluding those notices that do not
-       pertain to any part of the Derivative Works, in at least one
-       of the following places: within a NOTICE text file distributed
-       as part of the Derivative Works; within the Source form or
-       documentation, if provided along with the Derivative Works; or,
-       within a display generated by the Derivative Works, if and
-       wherever such third-party notices normally appear. The contents
-       of the NOTICE file are for informational purposes only and
-       do not modify the License. You may add Your own attribution
-       notices within Derivative Works that You distribute, alongside
-       or as an addendum to the NOTICE text from the Work, provided
-       that such additional attribution notices cannot be construed
-       as modifying the License.
-
-   You may add Your own copyright statement to Your modifications and
-   may provide additional or different license terms and conditions
-   for use, reproduction, or distribution of Your modifications, or
-   for any such Derivative Works as a whole, provided Your use,
-   reproduction, and distribution of the Work otherwise complies with
-   the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-   any Contribution intentionally submitted for inclusion in the Work
-   by You to the Licensor shall be under the terms and conditions of
-   this License, without any additional terms or conditions.
-   Notwithstanding the above, nothing herein shall supersede or modify
-   the terms of any separate license agreement you may have executed
-   with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-   names, trademarks, service marks, or product names of the Licensor,
-   except as required for reasonable and customary use in describing the
-   origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-   agreed to in writing, Licensor provides the Work (and each
-   Contributor provides its Contributions) on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-   implied, including, without limitation, any warranties or conditions
-   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-   PARTICULAR PURPOSE. You are solely responsible for determining the
-   appropriateness of using or redistributing the Work and assume any
-   risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-   whether in tort (including negligence), contract, or otherwise,
-   unless required by applicable law (such as deliberate and grossly
-   negligent acts) or agreed to in writing, shall any Contributor be
-   liable to You for damages, including any direct, indirect, special,
-   incidental, or consequential damages of any character arising as a
-   result of this License or out of the use or inability to use the
-   Work (including but not limited to damages for loss of goodwill,
-   work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses), even if such Contributor
-   has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-   the Work or Derivative Works thereof, You may choose to offer,
-   and charge a fee for, acceptance of support, warranty, indemnity,
-   or other liability obligations and/or rights consistent with this
-   License. However, in accepting such obligations, You may act only
-   on Your own behalf and on Your sole responsibility, not on behalf
-   of any other Contributor, and only if You agree to indemnify,
-   defend, and hold each Contributor harmless for any liability
-   incurred by, or claims asserted against, such Contributor by reason
-   of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-   To apply the Apache License to your work, attach the following
-   boilerplate notice, with the fields enclosed by brackets "[]"
-   replaced with your own identifying information. (Don't include
-   the brackets!)  The text should be enclosed in the appropriate
-   comment syntax for the file format. We also recommend that a
-   file or class name and description of purpose be included on the
-   same "printed page" as the copyright notice for easier
-   identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/vendor/hashbrown-0.9.1/LICENSE-MIT b/vendor/hashbrown-0.9.1/LICENSE-MIT
deleted file mode 100644 (file)
index 5afc2a7..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2016 Amanieu d'Antras
-
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/vendor/hashbrown-0.9.1/README.md b/vendor/hashbrown-0.9.1/README.md
deleted file mode 100644 (file)
index 2e43171..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-hashbrown
-=========
-
-[![Build Status](https://travis-ci.com/rust-lang/hashbrown.svg?branch=master)](https://travis-ci.com/rust-lang/hashbrown)
-[![Crates.io](https://img.shields.io/crates/v/hashbrown.svg)](https://crates.io/crates/hashbrown)
-[![Documentation](https://docs.rs/hashbrown/badge.svg)](https://docs.rs/hashbrown)
-[![Rust](https://img.shields.io/badge/rust-1.36.0%2B-blue.svg?maxAge=3600)](https://github.com/rust-lang/hashbrown)
-
-This crate is a Rust port of Google's high-performance [SwissTable] hash
-map, adapted to make it a drop-in replacement for Rust's standard `HashMap`
-and `HashSet` types.
-
-The original C++ version of SwissTable can be found [here], and this
-[CppCon talk] gives an overview of how the algorithm works.
-
-Since Rust 1.36, this is now the `HashMap` implementation for the Rust standard
-library. However you may still want to use this crate instead since it works
-in environments without `std`, such as embedded systems and kernels.
-
-[SwissTable]: https://abseil.io/blog/20180927-swisstables
-[here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h
-[CppCon talk]: https://www.youtube.com/watch?v=ncHmEUmJZf4
-
-## [Change log](CHANGELOG.md)
-
-## Features
-
-- Drop-in replacement for the standard library `HashMap` and `HashSet` types.
-- Uses `AHash` as the default hasher, which is much faster than SipHash.
-- Around 2x faster than the previous standard library `HashMap`.
-- Lower memory usage: only 1 byte of overhead per entry instead of 8.
-- Compatible with `#[no_std]` (but requires a global allocator with the `alloc` crate).
-- Empty hash maps do not allocate any memory.
-- SIMD lookups to scan multiple hash entries in parallel.
-
-## Performance
-
-Compared to the previous implementation of `std::collections::HashMap` (Rust 1.35).
-
-With the hashbrown default AHash hasher (not HashDoS-resistant):
-
-```text
- name                       oldstdhash ns/iter  hashbrown ns/iter  diff ns/iter   diff %  speedup 
- insert_ahash_highbits        20,846              7,397                   -13,449  -64.52%   x 2.82 
- insert_ahash_random          20,515              7,796                   -12,719  -62.00%   x 2.63 
- insert_ahash_serial          21,668              7,264                   -14,404  -66.48%   x 2.98 
- insert_erase_ahash_highbits  29,570              17,498                  -12,072  -40.83%   x 1.69 
- insert_erase_ahash_random    39,569              17,474                  -22,095  -55.84%   x 2.26 
- insert_erase_ahash_serial    32,073              17,332                  -14,741  -45.96%   x 1.85 
- iter_ahash_highbits          1,572               2,087                       515   32.76%   x 0.75 
- iter_ahash_random            1,609               2,074                       465   28.90%   x 0.78 
- iter_ahash_serial            2,293               2,120                      -173   -7.54%   x 1.08 
- lookup_ahash_highbits        3,460               4,403                       943   27.25%   x 0.79 
- lookup_ahash_random          6,377               3,911                    -2,466  -38.67%   x 1.63 
- lookup_ahash_serial          3,629               3,586                       -43   -1.18%   x 1.01 
- lookup_fail_ahash_highbits   5,286               3,411                    -1,875  -35.47%   x 1.55 
- lookup_fail_ahash_random     12,365              4,171                    -8,194  -66.27%   x 2.96 
- lookup_fail_ahash_serial     4,902               3,240                    -1,662  -33.90%   x 1.51 
-```
-
-With the libstd default SipHash hasher (HashDoS-resistant):
-
-```text
- name                       oldstdhash ns/iter  hashbrown ns/iter  diff ns/iter   diff %  speedup 
- insert_std_highbits        32,598              20,199                  -12,399  -38.04%   x 1.61 
- insert_std_random          29,824              20,760                   -9,064  -30.39%   x 1.44 
- insert_std_serial          33,151              17,256                  -15,895  -47.95%   x 1.92 
- insert_erase_std_highbits  74,731              48,735                  -25,996  -34.79%   x 1.53 
- insert_erase_std_random    73,828              47,649                  -26,179  -35.46%   x 1.55 
- insert_erase_std_serial    73,864              40,147                  -33,717  -45.65%   x 1.84 
- iter_std_highbits          1,518               2,264                       746   49.14%   x 0.67 
- iter_std_random            1,502               2,414                       912   60.72%   x 0.62 
- iter_std_serial            6,361               2,118                    -4,243  -66.70%   x 3.00 
- lookup_std_highbits        21,705              16,962                   -4,743  -21.85%   x 1.28 
- lookup_std_random          21,654              17,158                   -4,496  -20.76%   x 1.26 
- lookup_std_serial          18,726              14,509                   -4,217  -22.52%   x 1.29 
- lookup_fail_std_highbits   25,852              17,323                   -8,529  -32.99%   x 1.49 
- lookup_fail_std_random     25,913              17,760                   -8,153  -31.46%   x 1.46 
- lookup_fail_std_serial     22,648              14,839                   -7,809  -34.48%   x 1.53 
-```
-
-## Usage
-
-Add this to your `Cargo.toml`:
-
-```toml
-[dependencies]
-hashbrown = "0.9"
-```
-
-Then:
-
-```rust
-use hashbrown::HashMap;
-
-let mut map = HashMap::new();
-map.insert(1, "one");
-```
-
-This crate has the following Cargo features:
-
-- `nightly`: Enables nightly-only features: `#[may_dangle]`.
-- `serde`: Enables serde serialization support.
-- `rayon`: Enables rayon parallel iterator support.
-- `raw`: Enables access to the experimental and unsafe `RawTable` API.
-- `inline-more`: Adds inline hints to most functions, improving run-time performance at the cost
-  of compilation time. (enabled by default)
-- `ahash`: Compiles with ahash as default hasher. (enabled by default)
-- `ahash-compile-time-rng`: Activates the `compile-time-rng` feature of ahash, to increase the
-   DOS-resistance, but can result in issues for `no_std` builds. More details in
-   [issue#124](https://github.com/rust-lang/hashbrown/issues/124). (enabled by default)
-
-## License
-
-Licensed under either of:
-
- * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
-
-at your option.
-
-### Contribution
-
-Unless you explicitly state otherwise, any contribution intentionally submitted
-for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
-additional terms or conditions.
diff --git a/vendor/hashbrown-0.9.1/benches/bench.rs b/vendor/hashbrown-0.9.1/benches/bench.rs
deleted file mode 100644 (file)
index 771e716..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-// This benchmark suite contains some benchmarks along a set of dimensions:
-//   Hasher: std default (SipHash) and crate default (AHash).
-//   Int key distribution: low bit heavy, top bit heavy, and random.
-//   Task: basic functionality: insert, insert_erase, lookup, lookup_fail, iter
-#![feature(test)]
-
-extern crate test;
-
-use test::{black_box, Bencher};
-
-use hashbrown::hash_map::DefaultHashBuilder;
-use hashbrown::HashMap;
-use std::collections::hash_map::RandomState;
-
-const SIZE: usize = 1000;
-
-// The default hashmap when using this crate directly.
-type AHashMap<K, V> = HashMap<K, V, DefaultHashBuilder>;
-// This uses the hashmap from this crate with the default hasher of the stdlib.
-type StdHashMap<K, V> = HashMap<K, V, RandomState>;
-
-// A random key iterator.
-#[derive(Clone, Copy)]
-struct RandomKeys {
-    state: usize,
-}
-
-impl RandomKeys {
-    fn new() -> Self {
-        RandomKeys { state: 0 }
-    }
-}
-
-impl Iterator for RandomKeys {
-    type Item = usize;
-    fn next(&mut self) -> Option<usize> {
-        // Add 1 then multiply by some 32 bit prime.
-        self.state = self.state.wrapping_add(1).wrapping_mul(3787392781);
-        Some(self.state)
-    }
-}
-
-macro_rules! bench_suite {
-    ($bench_macro:ident, $bench_ahash_serial:ident, $bench_std_serial:ident,
-     $bench_ahash_highbits:ident, $bench_std_highbits:ident,
-     $bench_ahash_random:ident, $bench_std_random:ident) => {
-        $bench_macro!($bench_ahash_serial, AHashMap, 0..);
-        $bench_macro!($bench_std_serial, StdHashMap, 0..);
-        $bench_macro!(
-            $bench_ahash_highbits,
-            AHashMap,
-            (0..).map(usize::swap_bytes)
-        );
-        $bench_macro!(
-            $bench_std_highbits,
-            StdHashMap,
-            (0..).map(usize::swap_bytes)
-        );
-        $bench_macro!($bench_ahash_random, AHashMap, RandomKeys::new());
-        $bench_macro!($bench_std_random, StdHashMap, RandomKeys::new());
-    };
-}
-
-macro_rules! bench_insert {
-    ($name:ident, $maptype:ident, $keydist:expr) => {
-        #[bench]
-        fn $name(b: &mut Bencher) {
-            let mut m = $maptype::with_capacity_and_hasher(SIZE, Default::default());
-            b.iter(|| {
-                m.clear();
-                for i in ($keydist).take(SIZE) {
-                    m.insert(i, i);
-                }
-                black_box(&mut m);
-            })
-        }
-    };
-}
-
-bench_suite!(
-    bench_insert,
-    insert_ahash_serial,
-    insert_std_serial,
-    insert_ahash_highbits,
-    insert_std_highbits,
-    insert_ahash_random,
-    insert_std_random
-);
-
-macro_rules! bench_insert_erase {
-    ($name:ident, $maptype:ident, $keydist:expr) => {
-        #[bench]
-        fn $name(b: &mut Bencher) {
-            let mut base = $maptype::default();
-            for i in ($keydist).take(SIZE) {
-                base.insert(i, i);
-            }
-            let skip = $keydist.skip(SIZE);
-            b.iter(|| {
-                let mut m = base.clone();
-                let mut add_iter = skip.clone();
-                let mut remove_iter = $keydist;
-                // While keeping the size constant,
-                // replace the first keydist with the second.
-                for (add, remove) in (&mut add_iter).zip(&mut remove_iter).take(SIZE) {
-                    m.insert(add, add);
-                    black_box(m.remove(&remove));
-                }
-                black_box(m);
-            })
-        }
-    };
-}
-
-bench_suite!(
-    bench_insert_erase,
-    insert_erase_ahash_serial,
-    insert_erase_std_serial,
-    insert_erase_ahash_highbits,
-    insert_erase_std_highbits,
-    insert_erase_ahash_random,
-    insert_erase_std_random
-);
-
-macro_rules! bench_lookup {
-    ($name:ident, $maptype:ident, $keydist:expr) => {
-        #[bench]
-        fn $name(b: &mut Bencher) {
-            let mut m = $maptype::default();
-            for i in $keydist.take(SIZE) {
-                m.insert(i, i);
-            }
-
-            b.iter(|| {
-                for i in $keydist.take(SIZE) {
-                    black_box(m.get(&i));
-                }
-            })
-        }
-    };
-}
-
-bench_suite!(
-    bench_lookup,
-    lookup_ahash_serial,
-    lookup_std_serial,
-    lookup_ahash_highbits,
-    lookup_std_highbits,
-    lookup_ahash_random,
-    lookup_std_random
-);
-
-macro_rules! bench_lookup_fail {
-    ($name:ident, $maptype:ident, $keydist:expr) => {
-        #[bench]
-        fn $name(b: &mut Bencher) {
-            let mut m = $maptype::default();
-            let mut iter = $keydist;
-            for i in (&mut iter).take(SIZE) {
-                m.insert(i, i);
-            }
-
-            b.iter(|| {
-                for i in (&mut iter).take(SIZE) {
-                    black_box(m.get(&i));
-                }
-            })
-        }
-    };
-}
-
-bench_suite!(
-    bench_lookup_fail,
-    lookup_fail_ahash_serial,
-    lookup_fail_std_serial,
-    lookup_fail_ahash_highbits,
-    lookup_fail_std_highbits,
-    lookup_fail_ahash_random,
-    lookup_fail_std_random
-);
-
-macro_rules! bench_iter {
-    ($name:ident, $maptype:ident, $keydist:expr) => {
-        #[bench]
-        fn $name(b: &mut Bencher) {
-            let mut m = $maptype::default();
-            for i in ($keydist).take(SIZE) {
-                m.insert(i, i);
-            }
-
-            b.iter(|| {
-                for i in &m {
-                    black_box(i);
-                }
-            })
-        }
-    };
-}
-
-bench_suite!(
-    bench_iter,
-    iter_ahash_serial,
-    iter_std_serial,
-    iter_ahash_highbits,
-    iter_std_highbits,
-    iter_ahash_random,
-    iter_std_random
-);
-
-#[bench]
-fn clone_small(b: &mut Bencher) {
-    let mut m = HashMap::new();
-    for i in 0..10 {
-        m.insert(i, i);
-    }
-
-    b.iter(|| {
-        black_box(m.clone());
-    })
-}
-
-#[bench]
-fn clone_from_small(b: &mut Bencher) {
-    let mut m = HashMap::new();
-    let mut m2 = HashMap::new();
-    for i in 0..10 {
-        m.insert(i, i);
-    }
-
-    b.iter(|| {
-        m2.clone_from(&m);
-        black_box(&mut m2);
-    })
-}
-
-#[bench]
-fn clone_large(b: &mut Bencher) {
-    let mut m = HashMap::new();
-    for i in 0..1000 {
-        m.insert(i, i);
-    }
-
-    b.iter(|| {
-        black_box(m.clone());
-    })
-}
-
-#[bench]
-fn clone_from_large(b: &mut Bencher) {
-    let mut m = HashMap::new();
-    let mut m2 = HashMap::new();
-    for i in 0..1000 {
-        m.insert(i, i);
-    }
-
-    b.iter(|| {
-        m2.clone_from(&m);
-        black_box(&mut m2);
-    })
-}
diff --git a/vendor/hashbrown-0.9.1/clippy.toml b/vendor/hashbrown-0.9.1/clippy.toml
deleted file mode 100644 (file)
index d98bf2c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-doc-valid-idents = [ "CppCon", "SwissTable", "SipHash", "HashDoS" ]
diff --git a/vendor/hashbrown-0.9.1/src/external_trait_impls/mod.rs b/vendor/hashbrown-0.9.1/src/external_trait_impls/mod.rs
deleted file mode 100644 (file)
index ef49783..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#[cfg(feature = "rayon")]
-pub(crate) mod rayon;
-#[cfg(feature = "serde")]
-mod serde;
diff --git a/vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/helpers.rs b/vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/helpers.rs
deleted file mode 100644 (file)
index 9382007..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-use alloc::collections::LinkedList;
-use alloc::vec::Vec;
-
-use rayon::iter::{IntoParallelIterator, ParallelIterator};
-
-/// Helper for collecting parallel iterators to an intermediary
-pub(super) fn collect<I: IntoParallelIterator>(iter: I) -> (LinkedList<Vec<I::Item>>, usize) {
-    let list = iter
-        .into_par_iter()
-        .fold(Vec::new, |mut vec, elem| {
-            vec.push(elem);
-            vec
-        })
-        .map(|vec| {
-            let mut list = LinkedList::new();
-            list.push_back(vec);
-            list
-        })
-        .reduce(LinkedList::new, |mut list1, mut list2| {
-            list1.append(&mut list2);
-            list1
-        });
-
-    let len = list.iter().map(Vec::len).sum();
-    (list, len)
-}
diff --git a/vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/map.rs b/vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/map.rs
deleted file mode 100644 (file)
index 334f8bb..0000000
+++ /dev/null
@@ -1,666 +0,0 @@
-//! Rayon extensions for `HashMap`.
-
-use crate::hash_map::HashMap;
-use core::fmt;
-use core::hash::{BuildHasher, Hash};
-use rayon::iter::plumbing::UnindexedConsumer;
-use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator};
-
-/// Parallel iterator over shared references to entries in a map.
-///
-/// This iterator is created by the [`par_iter`] method on [`HashMap`]
-/// (provided by the [`IntoParallelRefIterator`] trait).
-/// See its documentation for more.
-///
-/// [`par_iter`]: /hashbrown/struct.HashMap.html#method.par_iter
-/// [`HashMap`]: /hashbrown/struct.HashMap.html
-/// [`IntoParallelRefIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefIterator.html
-pub struct ParIter<'a, K, V, S> {
-    map: &'a HashMap<K, V, S>,
-}
-
-impl<'a, K: Sync, V: Sync, S: Sync> ParallelIterator for ParIter<'a, K, V, S> {
-    type Item = (&'a K, &'a V);
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        unsafe { self.map.table.par_iter() }
-            .map(|x| unsafe {
-                let r = x.as_ref();
-                (&r.0, &r.1)
-            })
-            .drive_unindexed(consumer)
-    }
-}
-
-impl<K, V, S> Clone for ParIter<'_, K, V, S> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn clone(&self) -> Self {
-        ParIter { map: self.map }
-    }
-}
-
-impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug for ParIter<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.map.iter().fmt(f)
-    }
-}
-
-/// Parallel iterator over shared references to keys in a map.
-///
-/// This iterator is created by the [`par_keys`] method on [`HashMap`].
-/// See its documentation for more.
-///
-/// [`par_keys`]: /hashbrown/struct.HashMap.html#method.par_keys
-/// [`HashMap`]: /hashbrown/struct.HashMap.html
-pub struct ParKeys<'a, K, V, S> {
-    map: &'a HashMap<K, V, S>,
-}
-
-impl<'a, K: Sync, V: Sync, S: Sync> ParallelIterator for ParKeys<'a, K, V, S> {
-    type Item = &'a K;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        unsafe { self.map.table.par_iter() }
-            .map(|x| unsafe { &x.as_ref().0 })
-            .drive_unindexed(consumer)
-    }
-}
-
-impl<K, V, S> Clone for ParKeys<'_, K, V, S> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn clone(&self) -> Self {
-        ParKeys { map: self.map }
-    }
-}
-
-impl<K: fmt::Debug + Eq + Hash, V, S: BuildHasher> fmt::Debug for ParKeys<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.map.keys().fmt(f)
-    }
-}
-
-/// Parallel iterator over shared references to values in a map.
-///
-/// This iterator is created by the [`par_values`] method on [`HashMap`].
-/// See its documentation for more.
-///
-/// [`par_values`]: /hashbrown/struct.HashMap.html#method.par_values
-/// [`HashMap`]: /hashbrown/struct.HashMap.html
-pub struct ParValues<'a, K, V, S> {
-    map: &'a HashMap<K, V, S>,
-}
-
-impl<'a, K: Sync, V: Sync, S: Sync> ParallelIterator for ParValues<'a, K, V, S> {
-    type Item = &'a V;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        unsafe { self.map.table.par_iter() }
-            .map(|x| unsafe { &x.as_ref().1 })
-            .drive_unindexed(consumer)
-    }
-}
-
-impl<K, V, S> Clone for ParValues<'_, K, V, S> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn clone(&self) -> Self {
-        ParValues { map: self.map }
-    }
-}
-
-impl<K: Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug for ParValues<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.map.values().fmt(f)
-    }
-}
-
-/// Parallel iterator over mutable references to entries in a map.
-///
-/// This iterator is created by the [`par_iter_mut`] method on [`HashMap`]
-/// (provided by the [`IntoParallelRefMutIterator`] trait).
-/// See its documentation for more.
-///
-/// [`par_iter_mut`]: /hashbrown/struct.HashMap.html#method.par_iter_mut
-/// [`HashMap`]: /hashbrown/struct.HashMap.html
-/// [`IntoParallelRefMutIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefMutIterator.html
-pub struct ParIterMut<'a, K, V, S> {
-    map: &'a mut HashMap<K, V, S>,
-}
-
-impl<'a, K: Send + Sync, V: Send, S: Send> ParallelIterator for ParIterMut<'a, K, V, S> {
-    type Item = (&'a K, &'a mut V);
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        unsafe { self.map.table.par_iter() }
-            .map(|x| unsafe {
-                let r = x.as_mut();
-                (&r.0, &mut r.1)
-            })
-            .drive_unindexed(consumer)
-    }
-}
-
-impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug
-    for ParIterMut<'_, K, V, S>
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.map.iter().fmt(f)
-    }
-}
-
-/// Parallel iterator over mutable references to values in a map.
-///
-/// This iterator is created by the [`par_values_mut`] method on [`HashMap`].
-/// See its documentation for more.
-///
-/// [`par_values_mut`]: /hashbrown/struct.HashMap.html#method.par_values_mut
-/// [`HashMap`]: /hashbrown/struct.HashMap.html
-pub struct ParValuesMut<'a, K, V, S> {
-    map: &'a mut HashMap<K, V, S>,
-}
-
-impl<'a, K: Send, V: Send, S: Send> ParallelIterator for ParValuesMut<'a, K, V, S> {
-    type Item = &'a mut V;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        unsafe { self.map.table.par_iter() }
-            .map(|x| unsafe { &mut x.as_mut().1 })
-            .drive_unindexed(consumer)
-    }
-}
-
-impl<K: Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug for ParValuesMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.map.values().fmt(f)
-    }
-}
-
-/// Parallel iterator over entries of a consumed map.
-///
-/// This iterator is created by the [`into_par_iter`] method on [`HashMap`]
-/// (provided by the [`IntoParallelIterator`] trait).
-/// See its documentation for more.
-///
-/// [`into_par_iter`]: /hashbrown/struct.HashMap.html#method.into_par_iter
-/// [`HashMap`]: /hashbrown/struct.HashMap.html
-/// [`IntoParallelIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelIterator.html
-pub struct IntoParIter<K, V, S> {
-    map: HashMap<K, V, S>,
-}
-
-impl<K: Send, V: Send, S: Send> ParallelIterator for IntoParIter<K, V, S> {
-    type Item = (K, V);
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.map.table.into_par_iter().drive_unindexed(consumer)
-    }
-}
-
-impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug for IntoParIter<K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.map.iter().fmt(f)
-    }
-}
-
-/// Parallel draining iterator over entries of a map.
-///
-/// This iterator is created by the [`par_drain`] method on [`HashMap`].
-/// See its documentation for more.
-///
-/// [`par_drain`]: /hashbrown/struct.HashMap.html#method.par_drain
-/// [`HashMap`]: /hashbrown/struct.HashMap.html
-pub struct ParDrain<'a, K, V, S> {
-    map: &'a mut HashMap<K, V, S>,
-}
-
-impl<K: Send, V: Send, S: Send> ParallelIterator for ParDrain<'_, K, V, S> {
-    type Item = (K, V);
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.map.table.par_drain().drive_unindexed(consumer)
-    }
-}
-
-impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug
-    for ParDrain<'_, K, V, S>
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.map.iter().fmt(f)
-    }
-}
-
-impl<K: Sync, V: Sync, S: Sync> HashMap<K, V, S> {
-    /// Visits (potentially in parallel) immutably borrowed keys in an arbitrary order.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn par_keys(&self) -> ParKeys<'_, K, V, S> {
-        ParKeys { map: self }
-    }
-
-    /// Visits (potentially in parallel) immutably borrowed values in an arbitrary order.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn par_values(&self) -> ParValues<'_, K, V, S> {
-        ParValues { map: self }
-    }
-}
-
-impl<K: Send, V: Send, S: Send> HashMap<K, V, S> {
-    /// Visits (potentially in parallel) mutably borrowed values in an arbitrary order.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn par_values_mut(&mut self) -> ParValuesMut<'_, K, V, S> {
-        ParValuesMut { map: self }
-    }
-
-    /// Consumes (potentially in parallel) all values in an arbitrary order,
-    /// while preserving the map's allocated memory for reuse.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn par_drain(&mut self) -> ParDrain<'_, K, V, S> {
-        ParDrain { map: self }
-    }
-}
-
-impl<K, V, S> HashMap<K, V, S>
-where
-    K: Eq + Hash + Sync,
-    V: PartialEq + Sync,
-    S: BuildHasher + Sync,
-{
-    /// Returns `true` if the map is equal to another,
-    /// i.e. both maps contain the same keys mapped to the same values.
-    ///
-    /// This method runs in a potentially parallel fashion.
-    pub fn par_eq(&self, other: &Self) -> bool {
-        self.len() == other.len()
-            && self
-                .into_par_iter()
-                .all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
-    }
-}
-
-impl<K: Send, V: Send, S: Send> IntoParallelIterator for HashMap<K, V, S> {
-    type Item = (K, V);
-    type Iter = IntoParIter<K, V, S>;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn into_par_iter(self) -> Self::Iter {
-        IntoParIter { map: self }
-    }
-}
-
-impl<'a, K: Sync, V: Sync, S: Sync> IntoParallelIterator for &'a HashMap<K, V, S> {
-    type Item = (&'a K, &'a V);
-    type Iter = ParIter<'a, K, V, S>;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn into_par_iter(self) -> Self::Iter {
-        ParIter { map: self }
-    }
-}
-
-impl<'a, K: Send + Sync, V: Send, S: Send> IntoParallelIterator for &'a mut HashMap<K, V, S> {
-    type Item = (&'a K, &'a mut V);
-    type Iter = ParIterMut<'a, K, V, S>;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn into_par_iter(self) -> Self::Iter {
-        ParIterMut { map: self }
-    }
-}
-
-/// Collect (key, value) pairs from a parallel iterator into a
-/// hashmap. If multiple pairs correspond to the same key, then the
-/// ones produced earlier in the parallel iterator will be
-/// overwritten, just as with a sequential iterator.
-impl<K, V, S> FromParallelIterator<(K, V)> for HashMap<K, V, S>
-where
-    K: Eq + Hash + Send,
-    V: Send,
-    S: BuildHasher + Default,
-{
-    fn from_par_iter<P>(par_iter: P) -> Self
-    where
-        P: IntoParallelIterator<Item = (K, V)>,
-    {
-        let mut map = HashMap::default();
-        map.par_extend(par_iter);
-        map
-    }
-}
-
-/// Extend a hash map with items from a parallel iterator.
-impl<K, V, S> ParallelExtend<(K, V)> for HashMap<K, V, S>
-where
-    K: Eq + Hash + Send,
-    V: Send,
-    S: BuildHasher,
-{
-    fn par_extend<I>(&mut self, par_iter: I)
-    where
-        I: IntoParallelIterator<Item = (K, V)>,
-    {
-        extend(self, par_iter);
-    }
-}
-
-/// Extend a hash map with copied items from a parallel iterator.
-impl<'a, K, V, S> ParallelExtend<(&'a K, &'a V)> for HashMap<K, V, S>
-where
-    K: Copy + Eq + Hash + Sync,
-    V: Copy + Sync,
-    S: BuildHasher,
-{
-    fn par_extend<I>(&mut self, par_iter: I)
-    where
-        I: IntoParallelIterator<Item = (&'a K, &'a V)>,
-    {
-        extend(self, par_iter);
-    }
-}
-
-// This is equal to the normal `HashMap` -- no custom advantage.
-fn extend<K, V, S, I>(map: &mut HashMap<K, V, S>, par_iter: I)
-where
-    K: Eq + Hash,
-    S: BuildHasher,
-    I: IntoParallelIterator,
-    HashMap<K, V, S>: Extend<I::Item>,
-{
-    let (list, len) = super::helpers::collect(par_iter);
-
-    // Keys may be already present or show multiple times in the iterator.
-    // Reserve the entire length if the map is empty.
-    // Otherwise reserve half the length (rounded up), so the map
-    // will only resize twice in the worst case.
-    let reserve = if map.is_empty() { len } else { (len + 1) / 2 };
-    map.reserve(reserve);
-    for vec in list {
-        map.extend(vec);
-    }
-}
-
-#[cfg(test)]
-mod test_par_map {
-    use alloc::vec::Vec;
-    use core::hash::{Hash, Hasher};
-    use core::sync::atomic::{AtomicUsize, Ordering};
-
-    use rayon::prelude::*;
-
-    use crate::hash_map::HashMap;
-
-    struct Dropable<'a> {
-        k: usize,
-        counter: &'a AtomicUsize,
-    }
-
-    impl Dropable<'_> {
-        fn new(k: usize, counter: &AtomicUsize) -> Dropable<'_> {
-            counter.fetch_add(1, Ordering::Relaxed);
-
-            Dropable { k, counter }
-        }
-    }
-
-    impl Drop for Dropable<'_> {
-        fn drop(&mut self) {
-            self.counter.fetch_sub(1, Ordering::Relaxed);
-        }
-    }
-
-    impl Clone for Dropable<'_> {
-        fn clone(&self) -> Self {
-            Dropable::new(self.k, self.counter)
-        }
-    }
-
-    impl Hash for Dropable<'_> {
-        fn hash<H>(&self, state: &mut H)
-        where
-            H: Hasher,
-        {
-            self.k.hash(state)
-        }
-    }
-
-    impl PartialEq for Dropable<'_> {
-        fn eq(&self, other: &Self) -> bool {
-            self.k == other.k
-        }
-    }
-
-    impl Eq for Dropable<'_> {}
-
-    #[test]
-    fn test_into_iter_drops() {
-        let key = AtomicUsize::new(0);
-        let value = AtomicUsize::new(0);
-
-        let hm = {
-            let mut hm = HashMap::new();
-
-            assert_eq!(key.load(Ordering::Relaxed), 0);
-            assert_eq!(value.load(Ordering::Relaxed), 0);
-
-            for i in 0..100 {
-                let d1 = Dropable::new(i, &key);
-                let d2 = Dropable::new(i + 100, &value);
-                hm.insert(d1, d2);
-            }
-
-            assert_eq!(key.load(Ordering::Relaxed), 100);
-            assert_eq!(value.load(Ordering::Relaxed), 100);
-
-            hm
-        };
-
-        // By the way, ensure that cloning doesn't screw up the dropping.
-        drop(hm.clone());
-
-        assert_eq!(key.load(Ordering::Relaxed), 100);
-        assert_eq!(value.load(Ordering::Relaxed), 100);
-
-        // Ensure that dropping the iterator does not leak anything.
-        drop(hm.clone().into_par_iter());
-
-        {
-            assert_eq!(key.load(Ordering::Relaxed), 100);
-            assert_eq!(value.load(Ordering::Relaxed), 100);
-
-            // retain only half
-            let _v: Vec<_> = hm
-                .into_par_iter()
-                .filter(|&(ref key, _)| key.k < 50)
-                .collect();
-
-            assert_eq!(key.load(Ordering::Relaxed), 50);
-            assert_eq!(value.load(Ordering::Relaxed), 50);
-        };
-
-        assert_eq!(key.load(Ordering::Relaxed), 0);
-        assert_eq!(value.load(Ordering::Relaxed), 0);
-    }
-
-    #[test]
-    fn test_drain_drops() {
-        let key = AtomicUsize::new(0);
-        let value = AtomicUsize::new(0);
-
-        let mut hm = {
-            let mut hm = HashMap::new();
-
-            assert_eq!(key.load(Ordering::Relaxed), 0);
-            assert_eq!(value.load(Ordering::Relaxed), 0);
-
-            for i in 0..100 {
-                let d1 = Dropable::new(i, &key);
-                let d2 = Dropable::new(i + 100, &value);
-                hm.insert(d1, d2);
-            }
-
-            assert_eq!(key.load(Ordering::Relaxed), 100);
-            assert_eq!(value.load(Ordering::Relaxed), 100);
-
-            hm
-        };
-
-        // By the way, ensure that cloning doesn't screw up the dropping.
-        drop(hm.clone());
-
-        assert_eq!(key.load(Ordering::Relaxed), 100);
-        assert_eq!(value.load(Ordering::Relaxed), 100);
-
-        // Ensure that dropping the drain iterator does not leak anything.
-        drop(hm.clone().par_drain());
-
-        {
-            assert_eq!(key.load(Ordering::Relaxed), 100);
-            assert_eq!(value.load(Ordering::Relaxed), 100);
-
-            // retain only half
-            let _v: Vec<_> = hm.drain().filter(|&(ref key, _)| key.k < 50).collect();
-            assert!(hm.is_empty());
-
-            assert_eq!(key.load(Ordering::Relaxed), 50);
-            assert_eq!(value.load(Ordering::Relaxed), 50);
-        };
-
-        assert_eq!(key.load(Ordering::Relaxed), 0);
-        assert_eq!(value.load(Ordering::Relaxed), 0);
-    }
-
-    #[test]
-    fn test_empty_iter() {
-        let mut m: HashMap<isize, bool> = HashMap::new();
-        assert_eq!(m.par_drain().count(), 0);
-        assert_eq!(m.par_keys().count(), 0);
-        assert_eq!(m.par_values().count(), 0);
-        assert_eq!(m.par_values_mut().count(), 0);
-        assert_eq!(m.par_iter().count(), 0);
-        assert_eq!(m.par_iter_mut().count(), 0);
-        assert_eq!(m.len(), 0);
-        assert!(m.is_empty());
-        assert_eq!(m.into_par_iter().count(), 0);
-    }
-
-    #[test]
-    fn test_iterate() {
-        let mut m = HashMap::with_capacity(4);
-        for i in 0..32 {
-            assert!(m.insert(i, i * 2).is_none());
-        }
-        assert_eq!(m.len(), 32);
-
-        let observed = AtomicUsize::new(0);
-
-        m.par_iter().for_each(|(k, v)| {
-            assert_eq!(*v, *k * 2);
-            observed.fetch_or(1 << *k, Ordering::Relaxed);
-        });
-        assert_eq!(observed.into_inner(), 0xFFFF_FFFF);
-    }
-
-    #[test]
-    fn test_keys() {
-        let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
-        let map: HashMap<_, _> = vec.into_par_iter().collect();
-        let keys: Vec<_> = map.par_keys().cloned().collect();
-        assert_eq!(keys.len(), 3);
-        assert!(keys.contains(&1));
-        assert!(keys.contains(&2));
-        assert!(keys.contains(&3));
-    }
-
-    #[test]
-    fn test_values() {
-        let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
-        let map: HashMap<_, _> = vec.into_par_iter().collect();
-        let values: Vec<_> = map.par_values().cloned().collect();
-        assert_eq!(values.len(), 3);
-        assert!(values.contains(&'a'));
-        assert!(values.contains(&'b'));
-        assert!(values.contains(&'c'));
-    }
-
-    #[test]
-    fn test_values_mut() {
-        let vec = vec![(1, 1), (2, 2), (3, 3)];
-        let mut map: HashMap<_, _> = vec.into_par_iter().collect();
-        map.par_values_mut().for_each(|value| *value = (*value) * 2);
-        let values: Vec<_> = map.par_values().cloned().collect();
-        assert_eq!(values.len(), 3);
-        assert!(values.contains(&2));
-        assert!(values.contains(&4));
-        assert!(values.contains(&6));
-    }
-
-    #[test]
-    fn test_eq() {
-        let mut m1 = HashMap::new();
-        m1.insert(1, 2);
-        m1.insert(2, 3);
-        m1.insert(3, 4);
-
-        let mut m2 = HashMap::new();
-        m2.insert(1, 2);
-        m2.insert(2, 3);
-
-        assert!(!m1.par_eq(&m2));
-
-        m2.insert(3, 4);
-
-        assert!(m1.par_eq(&m2));
-    }
-
-    #[test]
-    fn test_from_iter() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let map: HashMap<_, _> = xs.par_iter().cloned().collect();
-
-        for &(k, v) in &xs {
-            assert_eq!(map.get(&k), Some(&v));
-        }
-    }
-
-    #[test]
-    fn test_extend_ref() {
-        let mut a = HashMap::new();
-        a.insert(1, "one");
-        let mut b = HashMap::new();
-        b.insert(2, "two");
-        b.insert(3, "three");
-
-        a.par_extend(&b);
-
-        assert_eq!(a.len(), 3);
-        assert_eq!(a[&1], "one");
-        assert_eq!(a[&2], "two");
-        assert_eq!(a[&3], "three");
-    }
-}
diff --git a/vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/mod.rs b/vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/mod.rs
deleted file mode 100644 (file)
index 99337a1..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-mod helpers;
-pub(crate) mod map;
-pub(crate) mod raw;
-pub(crate) mod set;
diff --git a/vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/raw.rs b/vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/raw.rs
deleted file mode 100644 (file)
index 1bd2c17..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-use crate::raw::Bucket;
-use crate::raw::{RawIter, RawIterRange, RawTable};
-use crate::scopeguard::guard;
-use alloc::alloc::dealloc;
-use core::marker::PhantomData;
-use core::mem;
-use core::ptr::NonNull;
-use rayon::iter::{
-    plumbing::{self, Folder, UnindexedConsumer, UnindexedProducer},
-    ParallelIterator,
-};
-
-/// Parallel iterator which returns a raw pointer to every full bucket in the table.
-pub struct RawParIter<T> {
-    iter: RawIterRange<T>,
-}
-
-impl<T> From<RawIter<T>> for RawParIter<T> {
-    fn from(it: RawIter<T>) -> Self {
-        RawParIter { iter: it.iter }
-    }
-}
-
-impl<T> ParallelIterator for RawParIter<T> {
-    type Item = Bucket<T>;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        let producer = ParIterProducer { iter: self.iter };
-        plumbing::bridge_unindexed(producer, consumer)
-    }
-}
-
-/// Producer which returns a `Bucket<T>` for every element.
-struct ParIterProducer<T> {
-    iter: RawIterRange<T>,
-}
-
-impl<T> UnindexedProducer for ParIterProducer<T> {
-    type Item = Bucket<T>;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn split(self) -> (Self, Option<Self>) {
-        let (left, right) = self.iter.split();
-        let left = ParIterProducer { iter: left };
-        let right = right.map(|right| ParIterProducer { iter: right });
-        (left, right)
-    }
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn fold_with<F>(self, folder: F) -> F
-    where
-        F: Folder<Self::Item>,
-    {
-        folder.consume_iter(self.iter)
-    }
-}
-
-/// Parallel iterator which consumes a table and returns elements.
-pub struct RawIntoParIter<T> {
-    table: RawTable<T>,
-}
-
-impl<T: Send> ParallelIterator for RawIntoParIter<T> {
-    type Item = T;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        let iter = unsafe { self.table.iter().iter };
-        let _guard = guard(self.table.into_alloc(), |alloc| {
-            if let Some((ptr, layout)) = *alloc {
-                unsafe {
-                    dealloc(ptr.as_ptr(), layout);
-                }
-            }
-        });
-        let producer = ParDrainProducer { iter };
-        plumbing::bridge_unindexed(producer, consumer)
-    }
-}
-
-/// Parallel iterator which consumes elements without freeing the table storage.
-pub struct RawParDrain<'a, T> {
-    // We don't use a &'a mut RawTable<T> because we want RawParDrain to be
-    // covariant over T.
-    table: NonNull<RawTable<T>>,
-    marker: PhantomData<&'a RawTable<T>>,
-}
-
-unsafe impl<T> Send for RawParDrain<'_, T> {}
-
-impl<T: Send> ParallelIterator for RawParDrain<'_, T> {
-    type Item = T;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        let _guard = guard(self.table, |table| unsafe {
-            table.as_mut().clear_no_drop()
-        });
-        let iter = unsafe { self.table.as_ref().iter().iter };
-        mem::forget(self);
-        let producer = ParDrainProducer { iter };
-        plumbing::bridge_unindexed(producer, consumer)
-    }
-}
-
-impl<T> Drop for RawParDrain<'_, T> {
-    fn drop(&mut self) {
-        // If drive_unindexed is not called then simply clear the table.
-        unsafe { self.table.as_mut().clear() }
-    }
-}
-
-/// Producer which will consume all elements in the range, even if it is dropped
-/// halfway through.
-struct ParDrainProducer<T> {
-    iter: RawIterRange<T>,
-}
-
-impl<T: Send> UnindexedProducer for ParDrainProducer<T> {
-    type Item = T;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn split(self) -> (Self, Option<Self>) {
-        let (left, right) = self.iter.clone().split();
-        mem::forget(self);
-        let left = ParDrainProducer { iter: left };
-        let right = right.map(|right| ParDrainProducer { iter: right });
-        (left, right)
-    }
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn fold_with<F>(mut self, mut folder: F) -> F
-    where
-        F: Folder<Self::Item>,
-    {
-        // Make sure to modify the iterator in-place so that any remaining
-        // elements are processed in our Drop impl.
-        while let Some(item) = self.iter.next() {
-            folder = folder.consume(unsafe { item.read() });
-            if folder.full() {
-                return folder;
-            }
-        }
-
-        // If we processed all elements then we don't need to run the drop.
-        mem::forget(self);
-        folder
-    }
-}
-
-impl<T> Drop for ParDrainProducer<T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drop(&mut self) {
-        // Drop all remaining elements
-        if mem::needs_drop::<T>() {
-            while let Some(item) = self.iter.next() {
-                unsafe {
-                    item.drop();
-                }
-            }
-        }
-    }
-}
-
-impl<T> RawTable<T> {
-    /// Returns a parallel iterator over the elements in a `RawTable`.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn par_iter(&self) -> RawParIter<T> {
-        RawParIter {
-            iter: self.iter().iter,
-        }
-    }
-
-    /// Returns a parallel iterator over the elements in a `RawTable`.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn into_par_iter(self) -> RawIntoParIter<T> {
-        RawIntoParIter { table: self }
-    }
-
-    /// Returns a parallel iterator which consumes all elements of a `RawTable`
-    /// without freeing its memory allocation.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn par_drain(&mut self) -> RawParDrain<'_, T> {
-        RawParDrain {
-            table: NonNull::from(self),
-            marker: PhantomData,
-        }
-    }
-}
diff --git a/vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/set.rs b/vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/set.rs
deleted file mode 100644 (file)
index 53d2660..0000000
+++ /dev/null
@@ -1,646 +0,0 @@
-//! Rayon extensions for `HashSet`.
-
-use crate::hash_set::HashSet;
-use core::hash::{BuildHasher, Hash};
-use rayon::iter::plumbing::UnindexedConsumer;
-use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator};
-
-/// Parallel iterator over elements of a consumed set.
-///
-/// This iterator is created by the [`into_par_iter`] method on [`HashSet`]
-/// (provided by the [`IntoParallelIterator`] trait).
-/// See its documentation for more.
-///
-/// [`into_par_iter`]: /hashbrown/struct.HashSet.html#method.into_par_iter
-/// [`HashSet`]: /hashbrown/struct.HashSet.html
-/// [`IntoParallelIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelIterator.html
-pub struct IntoParIter<T, S> {
-    set: HashSet<T, S>,
-}
-
-impl<T: Send, S: Send> ParallelIterator for IntoParIter<T, S> {
-    type Item = T;
-
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.set
-            .map
-            .into_par_iter()
-            .map(|(k, _)| k)
-            .drive_unindexed(consumer)
-    }
-}
-
-/// Parallel draining iterator over entries of a set.
-///
-/// This iterator is created by the [`par_drain`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`par_drain`]: /hashbrown/struct.HashSet.html#method.par_drain
-/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParDrain<'a, T, S> {
-    set: &'a mut HashSet<T, S>,
-}
-
-impl<T: Send, S: Send> ParallelIterator for ParDrain<'_, T, S> {
-    type Item = T;
-
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.set
-            .map
-            .par_drain()
-            .map(|(k, _)| k)
-            .drive_unindexed(consumer)
-    }
-}
-
-/// Parallel iterator over shared references to elements in a set.
-///
-/// This iterator is created by the [`par_iter`] method on [`HashSet`]
-/// (provided by the [`IntoParallelRefIterator`] trait).
-/// See its documentation for more.
-///
-/// [`par_iter`]: /hashbrown/struct.HashSet.html#method.par_iter
-/// [`HashSet`]: /hashbrown/struct.HashSet.html
-/// [`IntoParallelRefIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefIterator.html
-pub struct ParIter<'a, T, S> {
-    set: &'a HashSet<T, S>,
-}
-
-impl<'a, T: Sync, S: Sync> ParallelIterator for ParIter<'a, T, S> {
-    type Item = &'a T;
-
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.set.map.par_keys().drive_unindexed(consumer)
-    }
-}
-
-/// Parallel iterator over shared references to elements in the difference of
-/// sets.
-///
-/// This iterator is created by the [`par_difference`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`par_difference`]: /hashbrown/struct.HashSet.html#method.par_difference
-/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParDifference<'a, T, S> {
-    a: &'a HashSet<T, S>,
-    b: &'a HashSet<T, S>,
-}
-
-impl<'a, T, S> ParallelIterator for ParDifference<'a, T, S>
-where
-    T: Eq + Hash + Sync,
-    S: BuildHasher + Sync,
-{
-    type Item = &'a T;
-
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.a
-            .into_par_iter()
-            .filter(|&x| !self.b.contains(x))
-            .drive_unindexed(consumer)
-    }
-}
-
-/// Parallel iterator over shared references to elements in the symmetric
-/// difference of sets.
-///
-/// This iterator is created by the [`par_symmetric_difference`] method on
-/// [`HashSet`].
-/// See its documentation for more.
-///
-/// [`par_symmetric_difference`]: /hashbrown/struct.HashSet.html#method.par_symmetric_difference
-/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParSymmetricDifference<'a, T, S> {
-    a: &'a HashSet<T, S>,
-    b: &'a HashSet<T, S>,
-}
-
-impl<'a, T, S> ParallelIterator for ParSymmetricDifference<'a, T, S>
-where
-    T: Eq + Hash + Sync,
-    S: BuildHasher + Sync,
-{
-    type Item = &'a T;
-
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.a
-            .par_difference(self.b)
-            .chain(self.b.par_difference(self.a))
-            .drive_unindexed(consumer)
-    }
-}
-
-/// Parallel iterator over shared references to elements in the intersection of
-/// sets.
-///
-/// This iterator is created by the [`par_intersection`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`par_intersection`]: /hashbrown/struct.HashSet.html#method.par_intersection
-/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParIntersection<'a, T, S> {
-    a: &'a HashSet<T, S>,
-    b: &'a HashSet<T, S>,
-}
-
-impl<'a, T, S> ParallelIterator for ParIntersection<'a, T, S>
-where
-    T: Eq + Hash + Sync,
-    S: BuildHasher + Sync,
-{
-    type Item = &'a T;
-
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.a
-            .into_par_iter()
-            .filter(|&x| self.b.contains(x))
-            .drive_unindexed(consumer)
-    }
-}
-
-/// Parallel iterator over shared references to elements in the union of sets.
-///
-/// This iterator is created by the [`par_union`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`par_union`]: /hashbrown/struct.HashSet.html#method.par_union
-/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParUnion<'a, T, S> {
-    a: &'a HashSet<T, S>,
-    b: &'a HashSet<T, S>,
-}
-
-impl<'a, T, S> ParallelIterator for ParUnion<'a, T, S>
-where
-    T: Eq + Hash + Sync,
-    S: BuildHasher + Sync,
-{
-    type Item = &'a T;
-
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.a
-            .into_par_iter()
-            .chain(self.b.par_difference(self.a))
-            .drive_unindexed(consumer)
-    }
-}
-
-impl<T, S> HashSet<T, S>
-where
-    T: Eq + Hash + Sync,
-    S: BuildHasher + Sync,
-{
-    /// Visits (potentially in parallel) the values representing the difference,
-    /// i.e. the values that are in `self` but not in `other`.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn par_difference<'a>(&'a self, other: &'a Self) -> ParDifference<'a, T, S> {
-        ParDifference { a: self, b: other }
-    }
-
-    /// Visits (potentially in parallel) the values representing the symmetric
-    /// difference, i.e. the values that are in `self` or in `other` but not in both.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn par_symmetric_difference<'a>(
-        &'a self,
-        other: &'a Self,
-    ) -> ParSymmetricDifference<'a, T, S> {
-        ParSymmetricDifference { a: self, b: other }
-    }
-
-    /// Visits (potentially in parallel) the values representing the
-    /// intersection, i.e. the values that are both in `self` and `other`.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn par_intersection<'a>(&'a self, other: &'a Self) -> ParIntersection<'a, T, S> {
-        ParIntersection { a: self, b: other }
-    }
-
-    /// Visits (potentially in parallel) the values representing the union,
-    /// i.e. all the values in `self` or `other`, without duplicates.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn par_union<'a>(&'a self, other: &'a Self) -> ParUnion<'a, T, S> {
-        ParUnion { a: self, b: other }
-    }
-
-    /// Returns `true` if `self` has no elements in common with `other`.
-    /// This is equivalent to checking for an empty intersection.
-    ///
-    /// This method runs in a potentially parallel fashion.
-    pub fn par_is_disjoint(&self, other: &Self) -> bool {
-        self.into_par_iter().all(|x| !other.contains(x))
-    }
-
-    /// Returns `true` if the set is a subset of another,
-    /// i.e. `other` contains at least all the values in `self`.
-    ///
-    /// This method runs in a potentially parallel fashion.
-    pub fn par_is_subset(&self, other: &Self) -> bool {
-        if self.len() <= other.len() {
-            self.into_par_iter().all(|x| other.contains(x))
-        } else {
-            false
-        }
-    }
-
-    /// Returns `true` if the set is a superset of another,
-    /// i.e. `self` contains at least all the values in `other`.
-    ///
-    /// This method runs in a potentially parallel fashion.
-    pub fn par_is_superset(&self, other: &Self) -> bool {
-        other.par_is_subset(self)
-    }
-
-    /// Returns `true` if the set is equal to another,
-    /// i.e. both sets contain the same values.
-    ///
-    /// This method runs in a potentially parallel fashion.
-    pub fn par_eq(&self, other: &Self) -> bool {
-        self.len() == other.len() && self.par_is_subset(other)
-    }
-}
-
-impl<T, S> HashSet<T, S>
-where
-    T: Eq + Hash + Send,
-    S: BuildHasher + Send,
-{
-    /// Consumes (potentially in parallel) all values in an arbitrary order,
-    /// while preserving the set's allocated memory for reuse.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn par_drain(&mut self) -> ParDrain<'_, T, S> {
-        ParDrain { set: self }
-    }
-}
-
-impl<T: Send, S: Send> IntoParallelIterator for HashSet<T, S> {
-    type Item = T;
-    type Iter = IntoParIter<T, S>;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn into_par_iter(self) -> Self::Iter {
-        IntoParIter { set: self }
-    }
-}
-
-impl<'a, T: Sync, S: Sync> IntoParallelIterator for &'a HashSet<T, S> {
-    type Item = &'a T;
-    type Iter = ParIter<'a, T, S>;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn into_par_iter(self) -> Self::Iter {
-        ParIter { set: self }
-    }
-}
-
-/// Collect values from a parallel iterator into a hashset.
-impl<T, S> FromParallelIterator<T> for HashSet<T, S>
-where
-    T: Eq + Hash + Send,
-    S: BuildHasher + Default,
-{
-    fn from_par_iter<P>(par_iter: P) -> Self
-    where
-        P: IntoParallelIterator<Item = T>,
-    {
-        let mut set = HashSet::default();
-        set.par_extend(par_iter);
-        set
-    }
-}
-
-/// Extend a hash set with items from a parallel iterator.
-impl<T, S> ParallelExtend<T> for HashSet<T, S>
-where
-    T: Eq + Hash + Send,
-    S: BuildHasher,
-{
-    fn par_extend<I>(&mut self, par_iter: I)
-    where
-        I: IntoParallelIterator<Item = T>,
-    {
-        extend(self, par_iter);
-    }
-}
-
-/// Extend a hash set with copied items from a parallel iterator.
-impl<'a, T, S> ParallelExtend<&'a T> for HashSet<T, S>
-where
-    T: 'a + Copy + Eq + Hash + Sync,
-    S: BuildHasher,
-{
-    fn par_extend<I>(&mut self, par_iter: I)
-    where
-        I: IntoParallelIterator<Item = &'a T>,
-    {
-        extend(self, par_iter);
-    }
-}
-
-// This is equal to the normal `HashSet` -- no custom advantage.
-fn extend<T, S, I>(set: &mut HashSet<T, S>, par_iter: I)
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-    I: IntoParallelIterator,
-    HashSet<T, S>: Extend<I::Item>,
-{
-    let (list, len) = super::helpers::collect(par_iter);
-
-    // Values may be already present or show multiple times in the iterator.
-    // Reserve the entire length if the set is empty.
-    // Otherwise reserve half the length (rounded up), so the set
-    // will only resize twice in the worst case.
-    let reserve = if set.is_empty() { len } else { (len + 1) / 2 };
-    set.reserve(reserve);
-    for vec in list {
-        set.extend(vec);
-    }
-}
-
-#[cfg(test)]
-mod test_par_set {
-    use alloc::vec::Vec;
-    use core::sync::atomic::{AtomicUsize, Ordering};
-
-    use rayon::prelude::*;
-
-    use crate::hash_set::HashSet;
-
-    #[test]
-    fn test_disjoint() {
-        let mut xs = HashSet::new();
-        let mut ys = HashSet::new();
-        assert!(xs.par_is_disjoint(&ys));
-        assert!(ys.par_is_disjoint(&xs));
-        assert!(xs.insert(5));
-        assert!(ys.insert(11));
-        assert!(xs.par_is_disjoint(&ys));
-        assert!(ys.par_is_disjoint(&xs));
-        assert!(xs.insert(7));
-        assert!(xs.insert(19));
-        assert!(xs.insert(4));
-        assert!(ys.insert(2));
-        assert!(ys.insert(-11));
-        assert!(xs.par_is_disjoint(&ys));
-        assert!(ys.par_is_disjoint(&xs));
-        assert!(ys.insert(7));
-        assert!(!xs.par_is_disjoint(&ys));
-        assert!(!ys.par_is_disjoint(&xs));
-    }
-
-    #[test]
-    fn test_subset_and_superset() {
-        let mut a = HashSet::new();
-        assert!(a.insert(0));
-        assert!(a.insert(5));
-        assert!(a.insert(11));
-        assert!(a.insert(7));
-
-        let mut b = HashSet::new();
-        assert!(b.insert(0));
-        assert!(b.insert(7));
-        assert!(b.insert(19));
-        assert!(b.insert(250));
-        assert!(b.insert(11));
-        assert!(b.insert(200));
-
-        assert!(!a.par_is_subset(&b));
-        assert!(!a.par_is_superset(&b));
-        assert!(!b.par_is_subset(&a));
-        assert!(!b.par_is_superset(&a));
-
-        assert!(b.insert(5));
-
-        assert!(a.par_is_subset(&b));
-        assert!(!a.par_is_superset(&b));
-        assert!(!b.par_is_subset(&a));
-        assert!(b.par_is_superset(&a));
-    }
-
-    #[test]
-    fn test_iterate() {
-        let mut a = HashSet::new();
-        for i in 0..32 {
-            assert!(a.insert(i));
-        }
-        let observed = AtomicUsize::new(0);
-        a.par_iter().for_each(|k| {
-            observed.fetch_or(1 << *k, Ordering::Relaxed);
-        });
-        assert_eq!(observed.into_inner(), 0xFFFF_FFFF);
-    }
-
-    #[test]
-    fn test_intersection() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(11));
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(77));
-        assert!(a.insert(103));
-        assert!(a.insert(5));
-        assert!(a.insert(-5));
-
-        assert!(b.insert(2));
-        assert!(b.insert(11));
-        assert!(b.insert(77));
-        assert!(b.insert(-9));
-        assert!(b.insert(-42));
-        assert!(b.insert(5));
-        assert!(b.insert(3));
-
-        let expected = [3, 5, 11, 77];
-        let i = a
-            .par_intersection(&b)
-            .map(|x| {
-                assert!(expected.contains(x));
-                1
-            })
-            .sum::<usize>();
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_difference() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-
-        assert!(b.insert(3));
-        assert!(b.insert(9));
-
-        let expected = [1, 5, 11];
-        let i = a
-            .par_difference(&b)
-            .map(|x| {
-                assert!(expected.contains(x));
-                1
-            })
-            .sum::<usize>();
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_symmetric_difference() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-
-        assert!(b.insert(-2));
-        assert!(b.insert(3));
-        assert!(b.insert(9));
-        assert!(b.insert(14));
-        assert!(b.insert(22));
-
-        let expected = [-2, 1, 5, 11, 14, 22];
-        let i = a
-            .par_symmetric_difference(&b)
-            .map(|x| {
-                assert!(expected.contains(x));
-                1
-            })
-            .sum::<usize>();
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_union() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-        assert!(a.insert(16));
-        assert!(a.insert(19));
-        assert!(a.insert(24));
-
-        assert!(b.insert(-2));
-        assert!(b.insert(1));
-        assert!(b.insert(5));
-        assert!(b.insert(9));
-        assert!(b.insert(13));
-        assert!(b.insert(19));
-
-        let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
-        let i = a
-            .par_union(&b)
-            .map(|x| {
-                assert!(expected.contains(x));
-                1
-            })
-            .sum::<usize>();
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_from_iter() {
-        let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
-
-        let set: HashSet<_> = xs.par_iter().cloned().collect();
-
-        for x in &xs {
-            assert!(set.contains(x));
-        }
-    }
-
-    #[test]
-    fn test_move_iter() {
-        let hs = {
-            let mut hs = HashSet::new();
-
-            hs.insert('a');
-            hs.insert('b');
-
-            hs
-        };
-
-        let v = hs.into_par_iter().collect::<Vec<char>>();
-        assert!(v == ['a', 'b'] || v == ['b', 'a']);
-    }
-
-    #[test]
-    fn test_eq() {
-        // These constants once happened to expose a bug in insert().
-        // I'm keeping them around to prevent a regression.
-        let mut s1 = HashSet::new();
-
-        s1.insert(1);
-        s1.insert(2);
-        s1.insert(3);
-
-        let mut s2 = HashSet::new();
-
-        s2.insert(1);
-        s2.insert(2);
-
-        assert!(!s1.par_eq(&s2));
-
-        s2.insert(3);
-
-        assert!(s1.par_eq(&s2));
-    }
-
-    #[test]
-    fn test_extend_ref() {
-        let mut a = HashSet::new();
-        a.insert(1);
-
-        a.par_extend(&[2, 3, 4][..]);
-
-        assert_eq!(a.len(), 4);
-        assert!(a.contains(&1));
-        assert!(a.contains(&2));
-        assert!(a.contains(&3));
-        assert!(a.contains(&4));
-
-        let mut b = HashSet::new();
-        b.insert(5);
-        b.insert(6);
-
-        a.par_extend(&b);
-
-        assert_eq!(a.len(), 6);
-        assert!(a.contains(&1));
-        assert!(a.contains(&2));
-        assert!(a.contains(&3));
-        assert!(a.contains(&4));
-        assert!(a.contains(&5));
-        assert!(a.contains(&6));
-    }
-}
diff --git a/vendor/hashbrown-0.9.1/src/external_trait_impls/serde.rs b/vendor/hashbrown-0.9.1/src/external_trait_impls/serde.rs
deleted file mode 100644 (file)
index 7816e78..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-mod size_hint {
-    use core::cmp;
-
-    /// This presumably exists to prevent denial of service attacks.
-    ///
-    /// Original discussion: https://github.com/serde-rs/serde/issues/1114.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub(super) fn cautious(hint: Option<usize>) -> usize {
-        cmp::min(hint.unwrap_or(0), 4096)
-    }
-}
-
-mod map {
-    use core::fmt;
-    use core::hash::{BuildHasher, Hash};
-    use core::marker::PhantomData;
-    use serde::de::{Deserialize, Deserializer, MapAccess, Visitor};
-    use serde::ser::{Serialize, Serializer};
-
-    use crate::hash_map::HashMap;
-
-    use super::size_hint;
-
-    impl<K, V, H> Serialize for HashMap<K, V, H>
-    where
-        K: Serialize + Eq + Hash,
-        V: Serialize,
-        H: BuildHasher,
-    {
-        #[cfg_attr(feature = "inline-more", inline)]
-        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-        where
-            S: Serializer,
-        {
-            serializer.collect_map(self)
-        }
-    }
-
-    impl<'de, K, V, S> Deserialize<'de> for HashMap<K, V, S>
-    where
-        K: Deserialize<'de> + Eq + Hash,
-        V: Deserialize<'de>,
-        S: BuildHasher + Default,
-    {
-        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
-        where
-            D: Deserializer<'de>,
-        {
-            struct MapVisitor<K, V, S> {
-                marker: PhantomData<HashMap<K, V, S>>,
-            }
-
-            impl<'de, K, V, S> Visitor<'de> for MapVisitor<K, V, S>
-            where
-                K: Deserialize<'de> + Eq + Hash,
-                V: Deserialize<'de>,
-                S: BuildHasher + Default,
-            {
-                type Value = HashMap<K, V, S>;
-
-                fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    formatter.write_str("a map")
-                }
-
-                #[cfg_attr(feature = "inline-more", inline)]
-                fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
-                where
-                    A: MapAccess<'de>,
-                {
-                    let mut values = HashMap::with_capacity_and_hasher(
-                        size_hint::cautious(map.size_hint()),
-                        S::default(),
-                    );
-
-                    while let Some((key, value)) = map.next_entry()? {
-                        values.insert(key, value);
-                    }
-
-                    Ok(values)
-                }
-            }
-
-            let visitor = MapVisitor {
-                marker: PhantomData,
-            };
-            deserializer.deserialize_map(visitor)
-        }
-    }
-}
-
-mod set {
-    use core::fmt;
-    use core::hash::{BuildHasher, Hash};
-    use core::marker::PhantomData;
-    use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
-    use serde::ser::{Serialize, Serializer};
-
-    use crate::hash_set::HashSet;
-
-    use super::size_hint;
-
-    impl<T, H> Serialize for HashSet<T, H>
-    where
-        T: Serialize + Eq + Hash,
-        H: BuildHasher,
-    {
-        #[cfg_attr(feature = "inline-more", inline)]
-        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-        where
-            S: Serializer,
-        {
-            serializer.collect_seq(self)
-        }
-    }
-
-    impl<'de, T, S> Deserialize<'de> for HashSet<T, S>
-    where
-        T: Deserialize<'de> + Eq + Hash,
-        S: BuildHasher + Default,
-    {
-        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
-        where
-            D: Deserializer<'de>,
-        {
-            struct SeqVisitor<T, S> {
-                marker: PhantomData<HashSet<T, S>>,
-            }
-
-            impl<'de, T, S> Visitor<'de> for SeqVisitor<T, S>
-            where
-                T: Deserialize<'de> + Eq + Hash,
-                S: BuildHasher + Default,
-            {
-                type Value = HashSet<T, S>;
-
-                fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    formatter.write_str("a sequence")
-                }
-
-                #[cfg_attr(feature = "inline-more", inline)]
-                fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
-                where
-                    A: SeqAccess<'de>,
-                {
-                    let mut values = HashSet::with_capacity_and_hasher(
-                        size_hint::cautious(seq.size_hint()),
-                        S::default(),
-                    );
-
-                    while let Some(value) = seq.next_element()? {
-                        values.insert(value);
-                    }
-
-                    Ok(values)
-                }
-            }
-
-            let visitor = SeqVisitor {
-                marker: PhantomData,
-            };
-            deserializer.deserialize_seq(visitor)
-        }
-
-        fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
-        where
-            D: Deserializer<'de>,
-        {
-            struct SeqInPlaceVisitor<'a, T, S>(&'a mut HashSet<T, S>);
-
-            impl<'a, 'de, T, S> Visitor<'de> for SeqInPlaceVisitor<'a, T, S>
-            where
-                T: Deserialize<'de> + Eq + Hash,
-                S: BuildHasher + Default,
-            {
-                type Value = ();
-
-                fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    formatter.write_str("a sequence")
-                }
-
-                #[cfg_attr(feature = "inline-more", inline)]
-                fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
-                where
-                    A: SeqAccess<'de>,
-                {
-                    self.0.clear();
-                    self.0.reserve(size_hint::cautious(seq.size_hint()));
-
-                    while let Some(value) = seq.next_element()? {
-                        self.0.insert(value);
-                    }
-
-                    Ok(())
-                }
-            }
-
-            deserializer.deserialize_seq(SeqInPlaceVisitor(place))
-        }
-    }
-}
diff --git a/vendor/hashbrown-0.9.1/src/lib.rs b/vendor/hashbrown-0.9.1/src/lib.rs
deleted file mode 100644 (file)
index 3aff40a..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-//! This crate is a Rust port of Google's high-performance [SwissTable] hash
-//! map, adapted to make it a drop-in replacement for Rust's standard `HashMap`
-//! and `HashSet` types.
-//!
-//! The original C++ version of [SwissTable] can be found [here], and this
-//! [CppCon talk] gives an overview of how the algorithm works.
-//!
-//! [SwissTable]: https://abseil.io/blog/20180927-swisstables
-//! [here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h
-//! [CppCon talk]: https://www.youtube.com/watch?v=ncHmEUmJZf4
-
-#![no_std]
-#![cfg_attr(
-    feature = "nightly",
-    feature(test, core_intrinsics, dropck_eyepatch, min_specialization, extend_one)
-)]
-#![allow(
-    clippy::doc_markdown,
-    clippy::module_name_repetitions,
-    clippy::must_use_candidate,
-    clippy::option_if_let_else
-)]
-#![warn(missing_docs)]
-#![warn(rust_2018_idioms)]
-
-#[cfg(test)]
-#[macro_use]
-extern crate std;
-
-#[cfg_attr(test, macro_use)]
-extern crate alloc;
-
-#[cfg(feature = "nightly")]
-#[cfg(doctest)]
-doc_comment::doctest!("../README.md");
-
-#[macro_use]
-mod macros;
-
-#[cfg(feature = "raw")]
-/// Experimental and unsafe `RawTable` API. This module is only available if the
-/// `raw` feature is enabled.
-pub mod raw {
-    // The RawTable API is still experimental and is not properly documented yet.
-    #[allow(missing_docs)]
-    #[path = "mod.rs"]
-    mod inner;
-    pub use inner::*;
-
-    #[cfg(feature = "rayon")]
-    pub mod rayon {
-        pub use crate::external_trait_impls::rayon::raw::*;
-    }
-}
-#[cfg(not(feature = "raw"))]
-mod raw;
-
-mod external_trait_impls;
-mod map;
-#[cfg(feature = "rustc-internal-api")]
-mod rustc_entry;
-mod scopeguard;
-mod set;
-
-pub mod hash_map {
-    //! A hash map implemented with quadratic probing and SIMD lookup.
-    pub use crate::map::*;
-
-    #[cfg(feature = "rustc-internal-api")]
-    pub use crate::rustc_entry::*;
-
-    #[cfg(feature = "rayon")]
-    /// [rayon]-based parallel iterator types for hash maps.
-    /// You will rarely need to interact with it directly unless you have need
-    /// to name one of the iterator types.
-    ///
-    /// [rayon]: https://docs.rs/rayon/1.0/rayon
-    pub mod rayon {
-        pub use crate::external_trait_impls::rayon::map::*;
-    }
-}
-pub mod hash_set {
-    //! A hash set implemented as a `HashMap` where the value is `()`.
-    pub use crate::set::*;
-
-    #[cfg(feature = "rayon")]
-    /// [rayon]-based parallel iterator types for hash sets.
-    /// You will rarely need to interact with it directly unless you have need
-    /// to name one of the iterator types.
-    ///
-    /// [rayon]: https://docs.rs/rayon/1.0/rayon
-    pub mod rayon {
-        pub use crate::external_trait_impls::rayon::set::*;
-    }
-}
-
-pub use crate::map::HashMap;
-pub use crate::set::HashSet;
-
-/// The error type for `try_reserve` methods.
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub enum TryReserveError {
-    /// Error due to the computed capacity exceeding the collection's maximum
-    /// (usually `isize::MAX` bytes).
-    CapacityOverflow,
-
-    /// The memory allocator returned an error
-    AllocError {
-        /// The layout of the allocation request that failed.
-        layout: alloc::alloc::Layout,
-    },
-}
diff --git a/vendor/hashbrown-0.9.1/src/macros.rs b/vendor/hashbrown-0.9.1/src/macros.rs
deleted file mode 100644 (file)
index 0279597..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-// See the cfg-if crate.
-macro_rules! cfg_if {
-    // match if/else chains with a final `else`
-    ($(
-        if #[cfg($($meta:meta),*)] { $($it:item)* }
-    ) else * else {
-        $($it2:item)*
-    }) => {
-        cfg_if! {
-            @__items
-            () ;
-            $( ( ($($meta),*) ($($it)*) ), )*
-            ( () ($($it2)*) ),
-        }
-    };
-
-    // match if/else chains lacking a final `else`
-    (
-        if #[cfg($($i_met:meta),*)] { $($i_it:item)* }
-        $(
-            else if #[cfg($($e_met:meta),*)] { $($e_it:item)* }
-        )*
-    ) => {
-        cfg_if! {
-            @__items
-            () ;
-            ( ($($i_met),*) ($($i_it)*) ),
-            $( ( ($($e_met),*) ($($e_it)*) ), )*
-            ( () () ),
-        }
-    };
-
-    // Internal and recursive macro to emit all the items
-    //
-    // Collects all the negated cfgs in a list at the beginning and after the
-    // semicolon is all the remaining items
-    (@__items ($($not:meta,)*) ; ) => {};
-    (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
-        // Emit all items within one block, applying an approprate #[cfg]. The
-        // #[cfg] will require all `$m` matchers specified and must also negate
-        // all previous matchers.
-        cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* }
-
-        // Recurse to emit all other items in `$rest`, and when we do so add all
-        // our `$m` matchers to the list of `$not` matchers as future emissions
-        // will have to negate everything we just matched as well.
-        cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* }
-    };
-
-    // Internal macro to Apply a cfg attribute to a list of items
-    (@__apply $m:meta, $($it:item)*) => {
-        $(#[$m] $it)*
-    };
-}
-
-// Helper macro for specialization. This also helps avoid parse errors if the
-// default fn syntax for specialization changes in the future.
-#[cfg(feature = "nightly")]
-macro_rules! default_fn {
-       ($($tt:tt)*) => {
-        default $($tt)*
-    }
-}
-#[cfg(not(feature = "nightly"))]
-macro_rules! default_fn {
-       ($($tt:tt)*) => {
-        $($tt)*
-    }
-}
diff --git a/vendor/hashbrown-0.9.1/src/map.rs b/vendor/hashbrown-0.9.1/src/map.rs
deleted file mode 100644 (file)
index 1ccba31..0000000
+++ /dev/null
@@ -1,4524 +0,0 @@
-use crate::raw::{Bucket, RawDrain, RawIntoIter, RawIter, RawTable};
-use crate::TryReserveError;
-use core::borrow::Borrow;
-use core::fmt::{self, Debug};
-use core::hash::{BuildHasher, Hash, Hasher};
-use core::iter::{FromIterator, FusedIterator};
-use core::marker::PhantomData;
-use core::mem;
-use core::ops::Index;
-
-/// Default hasher for `HashMap`.
-#[cfg(feature = "ahash")]
-pub type DefaultHashBuilder = ahash::RandomState;
-
-/// Dummy default hasher for `HashMap`.
-#[cfg(not(feature = "ahash"))]
-pub enum DefaultHashBuilder {}
-
-/// A hash map implemented with quadratic probing and SIMD lookup.
-///
-/// The default hashing algorithm is currently [`AHash`], though this is
-/// subject to change at any point in the future. This hash function is very
-/// fast for all types of keys, but this algorithm will typically *not* protect
-/// against attacks such as HashDoS.
-///
-/// The hashing algorithm can be replaced on a per-`HashMap` basis using the
-/// [`default`], [`with_hasher`], and [`with_capacity_and_hasher`] methods. Many
-/// alternative algorithms are available on crates.io, such as the [`fnv`] crate.
-///
-/// It is required that the keys implement the [`Eq`] and [`Hash`] traits, although
-/// this can frequently be achieved by using `#[derive(PartialEq, Eq, Hash)]`.
-/// If you implement these yourself, it is important that the following
-/// property holds:
-///
-/// ```text
-/// k1 == k2 -> hash(k1) == hash(k2)
-/// ```
-///
-/// In other words, if two keys are equal, their hashes must be equal.
-///
-/// It is a logic error for a key to be modified in such a way that the key's
-/// hash, as determined by the [`Hash`] trait, or its equality, as determined by
-/// the [`Eq`] trait, changes while it is in the map. This is normally only
-/// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
-///
-/// It is also a logic error for the [`Hash`] implementation of a key to panic.
-/// This is generally only possible if the trait is implemented manually. If a
-/// panic does occur then the contents of the `HashMap` may become corrupted and
-/// some items may be dropped from the table.
-///
-/// # Examples
-///
-/// ```
-/// use hashbrown::HashMap;
-///
-/// // Type inference lets us omit an explicit type signature (which
-/// // would be `HashMap<String, String>` in this example).
-/// let mut book_reviews = HashMap::new();
-///
-/// // Review some books.
-/// book_reviews.insert(
-///     "Adventures of Huckleberry Finn".to_string(),
-///     "My favorite book.".to_string(),
-/// );
-/// book_reviews.insert(
-///     "Grimms' Fairy Tales".to_string(),
-///     "Masterpiece.".to_string(),
-/// );
-/// book_reviews.insert(
-///     "Pride and Prejudice".to_string(),
-///     "Very enjoyable.".to_string(),
-/// );
-/// book_reviews.insert(
-///     "The Adventures of Sherlock Holmes".to_string(),
-///     "Eye lyked it alot.".to_string(),
-/// );
-///
-/// // Check for a specific one.
-/// // When collections store owned values (String), they can still be
-/// // queried using references (&str).
-/// if !book_reviews.contains_key("Les Misérables") {
-///     println!("We've got {} reviews, but Les Misérables ain't one.",
-///              book_reviews.len());
-/// }
-///
-/// // oops, this review has a lot of spelling mistakes, let's delete it.
-/// book_reviews.remove("The Adventures of Sherlock Holmes");
-///
-/// // Look up the values associated with some keys.
-/// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
-/// for &book in &to_find {
-///     match book_reviews.get(book) {
-///         Some(review) => println!("{}: {}", book, review),
-///         None => println!("{} is unreviewed.", book)
-///     }
-/// }
-///
-/// // Look up the value for a key (will panic if the key is not found).
-/// println!("Review for Jane: {}", book_reviews["Pride and Prejudice"]);
-///
-/// // Iterate over everything.
-/// for (book, review) in &book_reviews {
-///     println!("{}: \"{}\"", book, review);
-/// }
-/// ```
-///
-/// `HashMap` also implements an [`Entry API`](#method.entry), which allows
-/// for more complex methods of getting, setting, updating and removing keys and
-/// their values:
-///
-/// ```
-/// use hashbrown::HashMap;
-///
-/// // type inference lets us omit an explicit type signature (which
-/// // would be `HashMap<&str, u8>` in this example).
-/// let mut player_stats = HashMap::new();
-///
-/// fn random_stat_buff() -> u8 {
-///     // could actually return some random value here - let's just return
-///     // some fixed value for now
-///     42
-/// }
-///
-/// // insert a key only if it doesn't already exist
-/// player_stats.entry("health").or_insert(100);
-///
-/// // insert a key using a function that provides a new value only if it
-/// // doesn't already exist
-/// player_stats.entry("defence").or_insert_with(random_stat_buff);
-///
-/// // update a key, guarding against the key possibly not being set
-/// let stat = player_stats.entry("attack").or_insert(100);
-/// *stat += random_stat_buff();
-/// ```
-///
-/// The easiest way to use `HashMap` with a custom key type is to derive [`Eq`] and [`Hash`].
-/// We must also derive [`PartialEq`].
-///
-/// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-/// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-/// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html
-/// [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html
-/// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html
-/// [`default`]: #method.default
-/// [`with_hasher`]: #method.with_hasher
-/// [`with_capacity_and_hasher`]: #method.with_capacity_and_hasher
-/// [`fnv`]: https://crates.io/crates/fnv
-/// [`AHash`]: https://crates.io/crates/ahash
-///
-/// ```
-/// use hashbrown::HashMap;
-///
-/// #[derive(Hash, Eq, PartialEq, Debug)]
-/// struct Viking {
-///     name: String,
-///     country: String,
-/// }
-///
-/// impl Viking {
-///     /// Creates a new Viking.
-///     fn new(name: &str, country: &str) -> Viking {
-///         Viking { name: name.to_string(), country: country.to_string() }
-///     }
-/// }
-///
-/// // Use a HashMap to store the vikings' health points.
-/// let mut vikings = HashMap::new();
-///
-/// vikings.insert(Viking::new("Einar", "Norway"), 25);
-/// vikings.insert(Viking::new("Olaf", "Denmark"), 24);
-/// vikings.insert(Viking::new("Harald", "Iceland"), 12);
-///
-/// // Use derived implementation to print the status of the vikings.
-/// for (viking, health) in &vikings {
-///     println!("{:?} has {} hp", viking, health);
-/// }
-/// ```
-///
-/// A `HashMap` with fixed list of elements can be initialized from an array:
-///
-/// ```
-/// use hashbrown::HashMap;
-///
-/// let timber_resources: HashMap<&str, i32> = [("Norway", 100), ("Denmark", 50), ("Iceland", 10)]
-///     .iter().cloned().collect();
-/// // use the values stored in map
-/// ```
-pub struct HashMap<K, V, S = DefaultHashBuilder> {
-    pub(crate) hash_builder: S,
-    pub(crate) table: RawTable<(K, V)>,
-}
-
-impl<K: Clone, V: Clone, S: Clone> Clone for HashMap<K, V, S> {
-    fn clone(&self) -> Self {
-        HashMap {
-            hash_builder: self.hash_builder.clone(),
-            table: self.table.clone(),
-        }
-    }
-
-    fn clone_from(&mut self, source: &Self) {
-        self.table.clone_from(&source.table);
-
-        // Update hash_builder only if we successfully cloned all elements.
-        self.hash_builder.clone_from(&source.hash_builder);
-    }
-}
-
-#[cfg_attr(feature = "inline-more", inline)]
-pub(crate) fn make_hash<K: Hash + ?Sized>(hash_builder: &impl BuildHasher, val: &K) -> u64 {
-    let mut state = hash_builder.build_hasher();
-    val.hash(&mut state);
-    state.finish()
-}
-
-#[cfg(feature = "ahash")]
-impl<K, V> HashMap<K, V, DefaultHashBuilder> {
-    /// Creates an empty `HashMap`.
-    ///
-    /// The hash map is initially created with a capacity of 0, so it will not allocate until it
-    /// is first inserted into.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// let mut map: HashMap<&str, i32> = HashMap::new();
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn new() -> Self {
-        Self::default()
-    }
-
-    /// Creates an empty `HashMap` with the specified capacity.
-    ///
-    /// The hash map will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash map will not allocate.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// let mut map: HashMap<&str, i32> = HashMap::with_capacity(10);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn with_capacity(capacity: usize) -> Self {
-        Self::with_capacity_and_hasher(capacity, DefaultHashBuilder::default())
-    }
-}
-
-impl<K, V, S> HashMap<K, V, S> {
-    /// Creates an empty `HashMap` which will use the given hash builder to hash
-    /// keys.
-    ///
-    /// The created map has the default initial capacity.
-    ///
-    /// Warning: `hash_builder` is normally randomly generated, and
-    /// is designed to allow HashMaps to be resistant to attacks that
-    /// cause many collisions and very poor performance. Setting it
-    /// manually using this function can expose a DoS attack vector.
-    ///
-    /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
-    /// the HashMap to be useful, see its documentation for details.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::DefaultHashBuilder;
-    ///
-    /// let s = DefaultHashBuilder::default();
-    /// let mut map = HashMap::with_hasher(s);
-    /// map.insert(1, 2);
-    /// ```
-    ///
-    /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub const fn with_hasher(hash_builder: S) -> Self {
-        Self {
-            hash_builder,
-            table: RawTable::new(),
-        }
-    }
-
-    /// Creates an empty `HashMap` with the specified capacity, using `hash_builder`
-    /// to hash the keys.
-    ///
-    /// The hash map will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash map will not allocate.
-    ///
-    /// Warning: `hash_builder` is normally randomly generated, and
-    /// is designed to allow HashMaps to be resistant to attacks that
-    /// cause many collisions and very poor performance. Setting it
-    /// manually using this function can expose a DoS attack vector.
-    ///
-    /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
-    /// the HashMap to be useful, see its documentation for details.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::DefaultHashBuilder;
-    ///
-    /// let s = DefaultHashBuilder::default();
-    /// let mut map = HashMap::with_capacity_and_hasher(10, s);
-    /// map.insert(1, 2);
-    /// ```
-    ///
-    /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self {
-        Self {
-            hash_builder,
-            table: RawTable::with_capacity(capacity),
-        }
-    }
-
-    /// Returns a reference to the map's [`BuildHasher`].
-    ///
-    /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::DefaultHashBuilder;
-    ///
-    /// let hasher = DefaultHashBuilder::default();
-    /// let map: HashMap<i32, i32> = HashMap::with_hasher(hasher);
-    /// let hasher: &DefaultHashBuilder = map.hasher();
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn hasher(&self) -> &S {
-        &self.hash_builder
-    }
-
-    /// Returns the number of elements the map can hold without reallocating.
-    ///
-    /// This number is a lower bound; the `HashMap<K, V>` might be able to hold
-    /// more, but is guaranteed to be able to hold at least this many.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// let map: HashMap<i32, i32> = HashMap::with_capacity(100);
-    /// assert!(map.capacity() >= 100);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn capacity(&self) -> usize {
-        self.table.capacity()
-    }
-
-    /// An iterator visiting all keys in arbitrary order.
-    /// The iterator element type is `&'a K`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// for key in map.keys() {
-    ///     println!("{}", key);
-    /// }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn keys(&self) -> Keys<'_, K, V> {
-        Keys { inner: self.iter() }
-    }
-
-    /// An iterator visiting all values in arbitrary order.
-    /// The iterator element type is `&'a V`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// for val in map.values() {
-    ///     println!("{}", val);
-    /// }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn values(&self) -> Values<'_, K, V> {
-        Values { inner: self.iter() }
-    }
-
-    /// An iterator visiting all values mutably in arbitrary order.
-    /// The iterator element type is `&'a mut V`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    ///
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// for val in map.values_mut() {
-    ///     *val = *val + 10;
-    /// }
-    ///
-    /// for val in map.values() {
-    ///     println!("{}", val);
-    /// }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
-        ValuesMut {
-            inner: self.iter_mut(),
-        }
-    }
-
-    /// An iterator visiting all key-value pairs in arbitrary order.
-    /// The iterator element type is `(&'a K, &'a V)`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// for (key, val) in map.iter() {
-    ///     println!("key: {} val: {}", key, val);
-    /// }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn iter(&self) -> Iter<'_, K, V> {
-        // Here we tie the lifetime of self to the iter.
-        unsafe {
-            Iter {
-                inner: self.table.iter(),
-                marker: PhantomData,
-            }
-        }
-    }
-
-    /// An iterator visiting all key-value pairs in arbitrary order,
-    /// with mutable references to the values.
-    /// The iterator element type is `(&'a K, &'a mut V)`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// // Update all values
-    /// for (_, val) in map.iter_mut() {
-    ///     *val *= 2;
-    /// }
-    ///
-    /// for (key, val) in &map {
-    ///     println!("key: {} val: {}", key, val);
-    /// }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
-        // Here we tie the lifetime of self to the iter.
-        unsafe {
-            IterMut {
-                inner: self.table.iter(),
-                marker: PhantomData,
-            }
-        }
-    }
-
-    #[cfg(test)]
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn raw_capacity(&self) -> usize {
-        self.table.buckets()
-    }
-
-    /// Returns the number of elements in the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut a = HashMap::new();
-    /// assert_eq!(a.len(), 0);
-    /// a.insert(1, "a");
-    /// assert_eq!(a.len(), 1);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn len(&self) -> usize {
-        self.table.len()
-    }
-
-    /// Returns `true` if the map contains no elements.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut a = HashMap::new();
-    /// assert!(a.is_empty());
-    /// a.insert(1, "a");
-    /// assert!(!a.is_empty());
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn is_empty(&self) -> bool {
-        self.len() == 0
-    }
-
-    /// Clears the map, returning all key-value pairs as an iterator. Keeps the
-    /// allocated memory for reuse.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut a = HashMap::new();
-    /// a.insert(1, "a");
-    /// a.insert(2, "b");
-    ///
-    /// for (k, v) in a.drain().take(1) {
-    ///     assert!(k == 1 || k == 2);
-    ///     assert!(v == "a" || v == "b");
-    /// }
-    ///
-    /// assert!(a.is_empty());
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn drain(&mut self) -> Drain<'_, K, V> {
-        Drain {
-            inner: self.table.drain(),
-        }
-    }
-
-    /// Retains only the elements specified by the predicate.
-    ///
-    /// In other words, remove all pairs `(k, v)` such that `f(&k,&mut v)` returns `false`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<i32, i32> = (0..8).map(|x|(x, x*10)).collect();
-    /// map.retain(|&k, _| k % 2 == 0);
-    /// assert_eq!(map.len(), 4);
-    /// ```
-    pub fn retain<F>(&mut self, mut f: F)
-    where
-        F: FnMut(&K, &mut V) -> bool,
-    {
-        // Here we only use `iter` as a temporary, preventing use-after-free
-        unsafe {
-            for item in self.table.iter() {
-                let &mut (ref key, ref mut value) = item.as_mut();
-                if !f(key, value) {
-                    self.table.erase(item);
-                }
-            }
-        }
-    }
-
-    /// Drains elements which are true under the given predicate,
-    /// and returns an iterator over the removed items.
-    ///
-    /// In other words, move all pairs `(k, v)` such that `f(&k,&mut v)` returns `true` out
-    /// into another iterator.
-    ///
-    /// When the returned DrainedFilter is dropped, any remaining elements that satisfy
-    /// the predicate are dropped from the table.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
-    /// let drained: HashMap<i32, i32> = map.drain_filter(|k, _v| k % 2 == 0).collect();
-    ///
-    /// let mut evens = drained.keys().cloned().collect::<Vec<_>>();
-    /// let mut odds = map.keys().cloned().collect::<Vec<_>>();
-    /// evens.sort();
-    /// odds.sort();
-    ///
-    /// assert_eq!(evens, vec![0, 2, 4, 6]);
-    /// assert_eq!(odds, vec![1, 3, 5, 7]);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn drain_filter<F>(&mut self, f: F) -> DrainFilter<'_, K, V, F>
-    where
-        F: FnMut(&K, &mut V) -> bool,
-    {
-        DrainFilter {
-            f,
-            inner: DrainFilterInner {
-                iter: unsafe { self.table.iter() },
-                table: &mut self.table,
-            },
-        }
-    }
-
-    /// Clears the map, removing all key-value pairs. Keeps the allocated memory
-    /// for reuse.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut a = HashMap::new();
-    /// a.insert(1, "a");
-    /// a.clear();
-    /// assert!(a.is_empty());
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn clear(&mut self) {
-        self.table.clear();
-    }
-}
-
-impl<K, V, S> HashMap<K, V, S>
-where
-    K: Eq + Hash,
-    S: BuildHasher,
-{
-    /// Reserves capacity for at least `additional` more elements to be inserted
-    /// in the `HashMap`. The collection may reserve more space to avoid
-    /// frequent reallocations.
-    ///
-    /// # Panics
-    ///
-    /// Panics if the new allocation size overflows [`usize`].
-    ///
-    /// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// let mut map: HashMap<&str, i32> = HashMap::new();
-    /// map.reserve(10);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn reserve(&mut self, additional: usize) {
-        let hash_builder = &self.hash_builder;
-        self.table
-            .reserve(additional, |x| make_hash(hash_builder, &x.0));
-    }
-
-    /// Tries to reserve capacity for at least `additional` more elements to be inserted
-    /// in the given `HashMap<K,V>`. The collection may reserve more space to avoid
-    /// frequent reallocations.
-    ///
-    /// # Errors
-    ///
-    /// If the capacity overflows, or the allocator reports a failure, then an error
-    /// is returned.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// let mut map: HashMap<&str, isize> = HashMap::new();
-    /// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
-        let hash_builder = &self.hash_builder;
-        self.table
-            .try_reserve(additional, |x| make_hash(hash_builder, &x.0))
-    }
-
-    /// Shrinks the capacity of the map as much as possible. It will drop
-    /// down as much as possible while maintaining the internal rules
-    /// and possibly leaving some space in accordance with the resize policy.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<i32, i32> = HashMap::with_capacity(100);
-    /// map.insert(1, 2);
-    /// map.insert(3, 4);
-    /// assert!(map.capacity() >= 100);
-    /// map.shrink_to_fit();
-    /// assert!(map.capacity() >= 2);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn shrink_to_fit(&mut self) {
-        let hash_builder = &self.hash_builder;
-        self.table.shrink_to(0, |x| make_hash(hash_builder, &x.0));
-    }
-
-    /// Shrinks the capacity of the map with a lower limit. It will drop
-    /// down no lower than the supplied limit while maintaining the internal rules
-    /// and possibly leaving some space in accordance with the resize policy.
-    ///
-    /// This function does nothing if the current capacity is smaller than the
-    /// supplied minimum capacity.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<i32, i32> = HashMap::with_capacity(100);
-    /// map.insert(1, 2);
-    /// map.insert(3, 4);
-    /// assert!(map.capacity() >= 100);
-    /// map.shrink_to(10);
-    /// assert!(map.capacity() >= 10);
-    /// map.shrink_to(0);
-    /// assert!(map.capacity() >= 2);
-    /// map.shrink_to(10);
-    /// assert!(map.capacity() >= 2);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn shrink_to(&mut self, min_capacity: usize) {
-        let hash_builder = &self.hash_builder;
-        self.table
-            .shrink_to(min_capacity, |x| make_hash(hash_builder, &x.0));
-    }
-
-    /// Gets the given key's corresponding entry in the map for in-place manipulation.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut letters = HashMap::new();
-    ///
-    /// for ch in "a short treatise on fungi".chars() {
-    ///     let counter = letters.entry(ch).or_insert(0);
-    ///     *counter += 1;
-    /// }
-    ///
-    /// assert_eq!(letters[&'s'], 2);
-    /// assert_eq!(letters[&'t'], 3);
-    /// assert_eq!(letters[&'u'], 1);
-    /// assert_eq!(letters.get(&'y'), None);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S> {
-        let hash = make_hash(&self.hash_builder, &key);
-        if let Some(elem) = self.table.find(hash, |q| q.0.eq(&key)) {
-            Entry::Occupied(OccupiedEntry {
-                hash,
-                key: Some(key),
-                elem,
-                table: self,
-            })
-        } else {
-            Entry::Vacant(VacantEntry {
-                hash,
-                key,
-                table: self,
-            })
-        }
-    }
-
-    /// Returns a reference to the value corresponding to the key.
-    ///
-    /// The key may be any borrowed form of the map's key type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.get(&1), Some(&"a"));
-    /// assert_eq!(map.get(&2), None);
-    /// ```
-    #[inline]
-    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.get_inner(k) {
-            Some(&(_, ref v)) => Some(v),
-            None => None,
-        }
-    }
-
-    /// Returns the key-value pair corresponding to the supplied key.
-    ///
-    /// The supplied key may be any borrowed form of the map's key type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.get_key_value(&1), Some((&1, &"a")));
-    /// assert_eq!(map.get_key_value(&2), None);
-    /// ```
-    #[inline]
-    pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.get_inner(k) {
-            Some(&(ref key, ref value)) => Some((key, value)),
-            None => None,
-        }
-    }
-
-    #[inline]
-    fn get_inner<Q: ?Sized>(&self, k: &Q) -> Option<&(K, V)>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        let hash = make_hash(&self.hash_builder, k);
-        self.table.get(hash, |x| k.eq(x.0.borrow()))
-    }
-
-    /// Returns the key-value pair corresponding to the supplied key, with a mutable reference to value.
-    ///
-    /// The supplied key may be any borrowed form of the map's key type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// let (k, v) = map.get_key_value_mut(&1).unwrap();
-    /// assert_eq!(k, &1);
-    /// assert_eq!(v, &mut "a");
-    /// *v = "b";
-    /// assert_eq!(map.get_key_value_mut(&1), Some((&1, &mut "b")));
-    /// assert_eq!(map.get_key_value_mut(&2), None);
-    /// ```
-    #[inline]
-    pub fn get_key_value_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<(&K, &mut V)>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.get_inner_mut(k) {
-            Some(&mut (ref key, ref mut value)) => Some((key, value)),
-            None => None,
-        }
-    }
-
-    /// Returns `true` if the map contains a value for the specified key.
-    ///
-    /// The key may be any borrowed form of the map's key type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.contains_key(&1), true);
-    /// assert_eq!(map.contains_key(&2), false);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        self.get_inner(k).is_some()
-    }
-
-    /// Returns a mutable reference to the value corresponding to the key.
-    ///
-    /// The key may be any borrowed form of the map's key type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// if let Some(x) = map.get_mut(&1) {
-    ///     *x = "b";
-    /// }
-    /// assert_eq!(map[&1], "b");
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.get_inner_mut(k) {
-            Some(&mut (_, ref mut v)) => Some(v),
-            None => None,
-        }
-    }
-
-    #[inline]
-    fn get_inner_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut (K, V)>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        let hash = make_hash(&self.hash_builder, k);
-        self.table.get_mut(hash, |x| k.eq(x.0.borrow()))
-    }
-
-    /// Inserts a key-value pair into the map.
-    ///
-    /// If the map did not have this key present, [`None`] is returned.
-    ///
-    /// If the map did have this key present, the value is updated, and the old
-    /// value is returned. The key is not updated, though; this matters for
-    /// types that can be `==` without being identical. See the [module-level
-    /// documentation] for more.
-    ///
-    /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
-    /// [module-level documentation]: index.html#insert-and-complex-keys
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// assert_eq!(map.insert(37, "a"), None);
-    /// assert_eq!(map.is_empty(), false);
-    ///
-    /// map.insert(37, "b");
-    /// assert_eq!(map.insert(37, "c"), Some("b"));
-    /// assert_eq!(map[&37], "c");
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
-        let hash = make_hash(&self.hash_builder, &k);
-        if let Some((_, item)) = self.table.get_mut(hash, |x| k.eq(&x.0)) {
-            Some(mem::replace(item, v))
-        } else {
-            let hash_builder = &self.hash_builder;
-            self.table
-                .insert(hash, (k, v), |x| make_hash(hash_builder, &x.0));
-            None
-        }
-    }
-
-    /// Removes a key from the map, returning the value at the key if the key
-    /// was previously in the map.
-    ///
-    /// The key may be any borrowed form of the map's key type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.remove(&1), Some("a"));
-    /// assert_eq!(map.remove(&1), None);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.remove_entry(k) {
-            Some((_, v)) => Some(v),
-            None => None,
-        }
-    }
-
-    /// Removes a key from the map, returning the stored key and value if the
-    /// key was previously in the map.
-    ///
-    /// The key may be any borrowed form of the map's key type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.remove_entry(&1), Some((1, "a")));
-    /// assert_eq!(map.remove(&1), None);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        let hash = make_hash(&self.hash_builder, &k);
-        self.table.remove_entry(hash, |x| k.eq(x.0.borrow()))
-    }
-}
-
-impl<K, V, S> HashMap<K, V, S> {
-    /// Creates a raw entry builder for the HashMap.
-    ///
-    /// Raw entries provide the lowest level of control for searching and
-    /// manipulating a map. They must be manually initialized with a hash and
-    /// then manually searched. After this, insertions into a vacant entry
-    /// still require an owned key to be provided.
-    ///
-    /// Raw entries are useful for such exotic situations as:
-    ///
-    /// * Hash memoization
-    /// * Deferring the creation of an owned key until it is known to be required
-    /// * Using a search key that doesn't work with the Borrow trait
-    /// * Using custom comparison logic without newtype wrappers
-    ///
-    /// Because raw entries provide much more low-level control, it's much easier
-    /// to put the HashMap into an inconsistent state which, while memory-safe,
-    /// will cause the map to produce seemingly random results. Higher-level and
-    /// more foolproof APIs like `entry` should be preferred when possible.
-    ///
-    /// In particular, the hash used to initialized the raw entry must still be
-    /// consistent with the hash of the key that is ultimately stored in the entry.
-    /// This is because implementations of HashMap may need to recompute hashes
-    /// when resizing, at which point only the keys are available.
-    ///
-    /// Raw entries give mutable access to the keys. This must not be used
-    /// to modify how the key would compare or hash, as the map will not re-evaluate
-    /// where the key should go, meaning the keys may become "lost" if their
-    /// location does not reflect their state. For instance, if you change a key
-    /// so that the map now contains keys which compare equal, search may start
-    /// acting erratically, with two keys randomly masking each other. Implementations
-    /// are free to assume this doesn't happen (within the limits of memory-safety).
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S> {
-        RawEntryBuilderMut { map: self }
-    }
-
-    /// Creates a raw immutable entry builder for the HashMap.
-    ///
-    /// Raw entries provide the lowest level of control for searching and
-    /// manipulating a map. They must be manually initialized with a hash and
-    /// then manually searched.
-    ///
-    /// This is useful for
-    /// * Hash memoization
-    /// * Using a search key that doesn't work with the Borrow trait
-    /// * Using custom comparison logic without newtype wrappers
-    ///
-    /// Unless you are in such a situation, higher-level and more foolproof APIs like
-    /// `get` should be preferred.
-    ///
-    /// Immutable raw entries have very limited use; you might instead want `raw_entry_mut`.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S> {
-        RawEntryBuilder { map: self }
-    }
-}
-
-impl<K, V, S> PartialEq for HashMap<K, V, S>
-where
-    K: Eq + Hash,
-    V: PartialEq,
-    S: BuildHasher,
-{
-    fn eq(&self, other: &Self) -> bool {
-        if self.len() != other.len() {
-            return false;
-        }
-
-        self.iter()
-            .all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
-    }
-}
-
-impl<K, V, S> Eq for HashMap<K, V, S>
-where
-    K: Eq + Hash,
-    V: Eq,
-    S: BuildHasher,
-{
-}
-
-impl<K, V, S> Debug for HashMap<K, V, S>
-where
-    K: Debug,
-    V: Debug,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_map().entries(self.iter()).finish()
-    }
-}
-
-impl<K, V, S> Default for HashMap<K, V, S>
-where
-    S: Default,
-{
-    /// Creates an empty `HashMap<K, V, S>`, with the `Default` value for the hasher.
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn default() -> Self {
-        Self::with_hasher(Default::default())
-    }
-}
-
-impl<K, Q: ?Sized, V, S> Index<&Q> for HashMap<K, V, S>
-where
-    K: Eq + Hash + Borrow<Q>,
-    Q: Eq + Hash,
-    S: BuildHasher,
-{
-    type Output = V;
-
-    /// Returns a reference to the value corresponding to the supplied key.
-    ///
-    /// # Panics
-    ///
-    /// Panics if the key is not present in the `HashMap`.
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn index(&self, key: &Q) -> &V {
-        self.get(key).expect("no entry found for key")
-    }
-}
-
-/// An iterator over the entries of a `HashMap`.
-///
-/// This `struct` is created by the [`iter`] method on [`HashMap`]. See its
-/// documentation for more.
-///
-/// [`iter`]: struct.HashMap.html#method.iter
-/// [`HashMap`]: struct.HashMap.html
-pub struct Iter<'a, K, V> {
-    inner: RawIter<(K, V)>,
-    marker: PhantomData<(&'a K, &'a V)>,
-}
-
-// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-impl<K, V> Clone for Iter<'_, K, V> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn clone(&self) -> Self {
-        Iter {
-            inner: self.inner.clone(),
-            marker: PhantomData,
-        }
-    }
-}
-
-impl<K: Debug, V: Debug> fmt::Debug for Iter<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-/// A mutable iterator over the entries of a `HashMap`.
-///
-/// This `struct` is created by the [`iter_mut`] method on [`HashMap`]. See its
-/// documentation for more.
-///
-/// [`iter_mut`]: struct.HashMap.html#method.iter_mut
-/// [`HashMap`]: struct.HashMap.html
-pub struct IterMut<'a, K, V> {
-    inner: RawIter<(K, V)>,
-    // To ensure invariance with respect to V
-    marker: PhantomData<(&'a K, &'a mut V)>,
-}
-
-// We override the default Send impl which has K: Sync instead of K: Send. Both
-// are correct, but this one is more general since it allows keys which
-// implement Send but not Sync.
-unsafe impl<K: Send, V: Send> Send for IterMut<'_, K, V> {}
-
-impl<K, V> IterMut<'_, K, V> {
-    /// Returns a iterator of references over the remaining items.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub(super) fn iter(&self) -> Iter<'_, K, V> {
-        Iter {
-            inner: self.inner.clone(),
-            marker: PhantomData,
-        }
-    }
-}
-
-/// An owning iterator over the entries of a `HashMap`.
-///
-/// This `struct` is created by the [`into_iter`] method on [`HashMap`]
-/// (provided by the `IntoIterator` trait). See its documentation for more.
-///
-/// [`into_iter`]: struct.HashMap.html#method.into_iter
-/// [`HashMap`]: struct.HashMap.html
-pub struct IntoIter<K, V> {
-    inner: RawIntoIter<(K, V)>,
-}
-
-impl<K, V> IntoIter<K, V> {
-    /// Returns a iterator of references over the remaining items.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub(super) fn iter(&self) -> Iter<'_, K, V> {
-        Iter {
-            inner: self.inner.iter(),
-            marker: PhantomData,
-        }
-    }
-}
-
-/// An iterator over the keys of a `HashMap`.
-///
-/// This `struct` is created by the [`keys`] method on [`HashMap`]. See its
-/// documentation for more.
-///
-/// [`keys`]: struct.HashMap.html#method.keys
-/// [`HashMap`]: struct.HashMap.html
-pub struct Keys<'a, K, V> {
-    inner: Iter<'a, K, V>,
-}
-
-// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-impl<K, V> Clone for Keys<'_, K, V> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn clone(&self) -> Self {
-        Keys {
-            inner: self.inner.clone(),
-        }
-    }
-}
-
-impl<K: Debug, V> fmt::Debug for Keys<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-/// An iterator over the values of a `HashMap`.
-///
-/// This `struct` is created by the [`values`] method on [`HashMap`]. See its
-/// documentation for more.
-///
-/// [`values`]: struct.HashMap.html#method.values
-/// [`HashMap`]: struct.HashMap.html
-pub struct Values<'a, K, V> {
-    inner: Iter<'a, K, V>,
-}
-
-// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-impl<K, V> Clone for Values<'_, K, V> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn clone(&self) -> Self {
-        Values {
-            inner: self.inner.clone(),
-        }
-    }
-}
-
-impl<K, V: Debug> fmt::Debug for Values<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-/// A draining iterator over the entries of a `HashMap`.
-///
-/// This `struct` is created by the [`drain`] method on [`HashMap`]. See its
-/// documentation for more.
-///
-/// [`drain`]: struct.HashMap.html#method.drain
-/// [`HashMap`]: struct.HashMap.html
-pub struct Drain<'a, K, V> {
-    inner: RawDrain<'a, (K, V)>,
-}
-
-impl<K, V> Drain<'_, K, V> {
-    /// Returns a iterator of references over the remaining items.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub(super) fn iter(&self) -> Iter<'_, K, V> {
-        Iter {
-            inner: self.inner.iter(),
-            marker: PhantomData,
-        }
-    }
-}
-
-/// A draining iterator over entries of a `HashMap` which don't satisfy the predicate `f`.
-///
-/// This `struct` is created by the [`drain_filter`] method on [`HashMap`]. See its
-/// documentation for more.
-///
-/// [`drain_filter`]: struct.HashMap.html#method.drain_filter
-/// [`HashMap`]: struct.HashMap.html
-pub struct DrainFilter<'a, K, V, F>
-where
-    F: FnMut(&K, &mut V) -> bool,
-{
-    f: F,
-    inner: DrainFilterInner<'a, K, V>,
-}
-
-impl<'a, K, V, F> Drop for DrainFilter<'a, K, V, F>
-where
-    F: FnMut(&K, &mut V) -> bool,
-{
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drop(&mut self) {
-        while let Some(item) = self.next() {
-            let guard = ConsumeAllOnDrop(self);
-            drop(item);
-            mem::forget(guard);
-        }
-    }
-}
-
-pub(super) struct ConsumeAllOnDrop<'a, T: Iterator>(pub &'a mut T);
-
-impl<T: Iterator> Drop for ConsumeAllOnDrop<'_, T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drop(&mut self) {
-        self.0.for_each(drop)
-    }
-}
-
-impl<K, V, F> Iterator for DrainFilter<'_, K, V, F>
-where
-    F: FnMut(&K, &mut V) -> bool,
-{
-    type Item = (K, V);
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<Self::Item> {
-        self.inner.next(&mut self.f)
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (0, self.inner.iter.size_hint().1)
-    }
-}
-
-impl<K, V, F> FusedIterator for DrainFilter<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {}
-
-/// Portions of `DrainFilter` shared with `set::DrainFilter`
-pub(super) struct DrainFilterInner<'a, K, V> {
-    pub iter: RawIter<(K, V)>,
-    pub table: &'a mut RawTable<(K, V)>,
-}
-
-impl<K, V> DrainFilterInner<'_, K, V> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub(super) fn next<F>(&mut self, f: &mut F) -> Option<(K, V)>
-    where
-        F: FnMut(&K, &mut V) -> bool,
-    {
-        unsafe {
-            while let Some(item) = self.iter.next() {
-                let &mut (ref key, ref mut value) = item.as_mut();
-                if f(key, value) {
-                    return Some(self.table.remove(item));
-                }
-            }
-        }
-        None
-    }
-}
-
-/// A mutable iterator over the values of a `HashMap`.
-///
-/// This `struct` is created by the [`values_mut`] method on [`HashMap`]. See its
-/// documentation for more.
-///
-/// [`values_mut`]: struct.HashMap.html#method.values_mut
-/// [`HashMap`]: struct.HashMap.html
-pub struct ValuesMut<'a, K, V> {
-    inner: IterMut<'a, K, V>,
-}
-
-/// A builder for computing where in a [`HashMap`] a key-value pair would be stored.
-///
-/// See the [`HashMap::raw_entry_mut`] docs for usage examples.
-///
-/// [`HashMap::raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut
-pub struct RawEntryBuilderMut<'a, K, V, S> {
-    map: &'a mut HashMap<K, V, S>,
-}
-
-/// A view into a single entry in a map, which may either be vacant or occupied.
-///
-/// This is a lower-level version of [`Entry`].
-///
-/// This `enum` is constructed through the [`raw_entry_mut`] method on [`HashMap`],
-/// then calling one of the methods of that [`RawEntryBuilderMut`].
-///
-/// [`HashMap`]: struct.HashMap.html
-/// [`Entry`]: enum.Entry.html
-/// [`raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut
-/// [`RawEntryBuilderMut`]: struct.RawEntryBuilderMut.html
-pub enum RawEntryMut<'a, K, V, S> {
-    /// An occupied entry.
-    Occupied(RawOccupiedEntryMut<'a, K, V, S>),
-    /// A vacant entry.
-    Vacant(RawVacantEntryMut<'a, K, V, S>),
-}
-
-/// A view into an occupied entry in a `HashMap`.
-/// It is part of the [`RawEntryMut`] enum.
-///
-/// [`RawEntryMut`]: enum.RawEntryMut.html
-pub struct RawOccupiedEntryMut<'a, K, V, S> {
-    elem: Bucket<(K, V)>,
-    table: &'a mut RawTable<(K, V)>,
-    hash_builder: &'a S,
-}
-
-unsafe impl<K, V, S> Send for RawOccupiedEntryMut<'_, K, V, S>
-where
-    K: Send,
-    V: Send,
-    S: Sync,
-{
-}
-unsafe impl<K, V, S> Sync for RawOccupiedEntryMut<'_, K, V, S>
-where
-    K: Sync,
-    V: Sync,
-    S: Sync,
-{
-}
-
-/// A view into a vacant entry in a `HashMap`.
-/// It is part of the [`RawEntryMut`] enum.
-///
-/// [`RawEntryMut`]: enum.RawEntryMut.html
-pub struct RawVacantEntryMut<'a, K, V, S> {
-    table: &'a mut RawTable<(K, V)>,
-    hash_builder: &'a S,
-}
-
-/// A builder for computing where in a [`HashMap`] a key-value pair would be stored.
-///
-/// See the [`HashMap::raw_entry`] docs for usage examples.
-///
-/// [`HashMap::raw_entry`]: struct.HashMap.html#method.raw_entry
-pub struct RawEntryBuilder<'a, K, V, S> {
-    map: &'a HashMap<K, V, S>,
-}
-
-impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> {
-    /// Creates a `RawEntryMut` from the given key.
-    #[cfg_attr(feature = "inline-more", inline)]
-    #[allow(clippy::wrong_self_convention)]
-    pub fn from_key<Q: ?Sized>(self, k: &Q) -> RawEntryMut<'a, K, V, S>
-    where
-        S: BuildHasher,
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        let mut hasher = self.map.hash_builder.build_hasher();
-        k.hash(&mut hasher);
-        self.from_key_hashed_nocheck(hasher.finish(), k)
-    }
-
-    /// Creates a `RawEntryMut` from the given key and its hash.
-    #[inline]
-    #[allow(clippy::wrong_self_convention)]
-    pub fn from_key_hashed_nocheck<Q: ?Sized>(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S>
-    where
-        K: Borrow<Q>,
-        Q: Eq,
-    {
-        self.from_hash(hash, |q| q.borrow().eq(k))
-    }
-}
-
-impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> {
-    /// Creates a `RawEntryMut` from the given hash.
-    #[cfg_attr(feature = "inline-more", inline)]
-    #[allow(clippy::wrong_self_convention)]
-    pub fn from_hash<F>(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S>
-    where
-        for<'b> F: FnMut(&'b K) -> bool,
-    {
-        self.search(hash, is_match)
-    }
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn search<F>(self, hash: u64, mut is_match: F) -> RawEntryMut<'a, K, V, S>
-    where
-        for<'b> F: FnMut(&'b K) -> bool,
-    {
-        match self.map.table.find(hash, |(k, _)| is_match(k)) {
-            Some(elem) => RawEntryMut::Occupied(RawOccupiedEntryMut {
-                elem,
-                table: &mut self.map.table,
-                hash_builder: &self.map.hash_builder,
-            }),
-            None => RawEntryMut::Vacant(RawVacantEntryMut {
-                table: &mut self.map.table,
-                hash_builder: &self.map.hash_builder,
-            }),
-        }
-    }
-}
-
-impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> {
-    /// Access an entry by key.
-    #[cfg_attr(feature = "inline-more", inline)]
-    #[allow(clippy::wrong_self_convention)]
-    pub fn from_key<Q: ?Sized>(self, k: &Q) -> Option<(&'a K, &'a V)>
-    where
-        S: BuildHasher,
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        let mut hasher = self.map.hash_builder.build_hasher();
-        k.hash(&mut hasher);
-        self.from_key_hashed_nocheck(hasher.finish(), k)
-    }
-
-    /// Access an entry by a key and its hash.
-    #[cfg_attr(feature = "inline-more", inline)]
-    #[allow(clippy::wrong_self_convention)]
-    pub fn from_key_hashed_nocheck<Q: ?Sized>(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)>
-    where
-        K: Borrow<Q>,
-        Q: Eq,
-    {
-        self.from_hash(hash, |q| q.borrow().eq(k))
-    }
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn search<F>(self, hash: u64, mut is_match: F) -> Option<(&'a K, &'a V)>
-    where
-        F: FnMut(&K) -> bool,
-    {
-        match self.map.table.get(hash, |(k, _)| is_match(k)) {
-            Some(&(ref key, ref value)) => Some((key, value)),
-            None => None,
-        }
-    }
-
-    /// Access an entry by hash.
-    #[cfg_attr(feature = "inline-more", inline)]
-    #[allow(clippy::wrong_self_convention)]
-    pub fn from_hash<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)>
-    where
-        F: FnMut(&K) -> bool,
-    {
-        self.search(hash, is_match)
-    }
-}
-
-impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
-    /// Sets the value of the entry, and returns a RawOccupiedEntryMut.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// let entry = map.raw_entry_mut().from_key("horseyland").insert("horseyland", 37);
-    ///
-    /// assert_eq!(entry.remove_entry(), ("horseyland", 37));
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert(self, key: K, value: V) -> RawOccupiedEntryMut<'a, K, V, S>
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            RawEntryMut::Occupied(mut entry) => {
-                entry.insert(value);
-                entry
-            }
-            RawEntryMut::Vacant(entry) => entry.insert_entry(key, value),
-        }
-    }
-
-    /// Ensures a value is in the entry by inserting the default if empty, and returns
-    /// mutable references to the key and value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 3);
-    /// assert_eq!(map["poneyland"], 3);
-    ///
-    /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 *= 2;
-    /// assert_eq!(map["poneyland"], 6);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V)
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            RawEntryMut::Occupied(entry) => entry.into_key_value(),
-            RawEntryMut::Vacant(entry) => entry.insert(default_key, default_val),
-        }
-    }
-
-    /// Ensures a value is in the entry by inserting the result of the default function if empty,
-    /// and returns mutable references to the key and value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, String> = HashMap::new();
-    ///
-    /// map.raw_entry_mut().from_key("poneyland").or_insert_with(|| {
-    ///     ("poneyland", "hoho".to_string())
-    /// });
-    ///
-    /// assert_eq!(map["poneyland"], "hoho".to_string());
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn or_insert_with<F>(self, default: F) -> (&'a mut K, &'a mut V)
-    where
-        F: FnOnce() -> (K, V),
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            RawEntryMut::Occupied(entry) => entry.into_key_value(),
-            RawEntryMut::Vacant(entry) => {
-                let (k, v) = default();
-                entry.insert(k, v)
-            }
-        }
-    }
-
-    /// Provides in-place mutable access to an occupied entry before any
-    /// potential inserts into the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// map.raw_entry_mut()
-    ///    .from_key("poneyland")
-    ///    .and_modify(|_k, v| { *v += 1 })
-    ///    .or_insert("poneyland", 42);
-    /// assert_eq!(map["poneyland"], 42);
-    ///
-    /// map.raw_entry_mut()
-    ///    .from_key("poneyland")
-    ///    .and_modify(|_k, v| { *v += 1 })
-    ///    .or_insert("poneyland", 0);
-    /// assert_eq!(map["poneyland"], 43);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn and_modify<F>(self, f: F) -> Self
-    where
-        F: FnOnce(&mut K, &mut V),
-    {
-        match self {
-            RawEntryMut::Occupied(mut entry) => {
-                {
-                    let (k, v) = entry.get_key_value_mut();
-                    f(k, v);
-                }
-                RawEntryMut::Occupied(entry)
-            }
-            RawEntryMut::Vacant(entry) => RawEntryMut::Vacant(entry),
-        }
-    }
-
-    /// Provides shared access to the key and owned access to the value of
-    /// an occupied entry and allows to replace or remove it based on the
-    /// value of the returned option.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RawEntryMut;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// let entry = map
-    ///     .raw_entry_mut()
-    ///     .from_key("poneyland")
-    ///     .and_replace_entry_with(|_k, _v| panic!());
-    ///
-    /// match entry {
-    ///     RawEntryMut::Vacant(_) => {},
-    ///     RawEntryMut::Occupied(_) => panic!(),
-    /// }
-    ///
-    /// map.insert("poneyland", 42);
-    ///
-    /// let entry = map
-    ///     .raw_entry_mut()
-    ///     .from_key("poneyland")
-    ///     .and_replace_entry_with(|k, v| {
-    ///         assert_eq!(k, &"poneyland");
-    ///         assert_eq!(v, 42);
-    ///         Some(v + 1)
-    ///     });
-    ///
-    /// match entry {
-    ///     RawEntryMut::Occupied(e) => {
-    ///         assert_eq!(e.key(), &"poneyland");
-    ///         assert_eq!(e.get(), &43);
-    ///     },
-    ///     RawEntryMut::Vacant(_) => panic!(),
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 43);
-    ///
-    /// let entry = map
-    ///     .raw_entry_mut()
-    ///     .from_key("poneyland")
-    ///     .and_replace_entry_with(|_k, _v| None);
-    ///
-    /// match entry {
-    ///     RawEntryMut::Vacant(_) => {},
-    ///     RawEntryMut::Occupied(_) => panic!(),
-    /// }
-    ///
-    /// assert!(!map.contains_key("poneyland"));
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn and_replace_entry_with<F>(self, f: F) -> Self
-    where
-        F: FnOnce(&K, V) -> Option<V>,
-    {
-        match self {
-            RawEntryMut::Occupied(entry) => entry.replace_entry_with(f),
-            RawEntryMut::Vacant(_) => self,
-        }
-    }
-}
-
-impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> {
-    /// Gets a reference to the key in the entry.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn key(&self) -> &K {
-        unsafe { &self.elem.as_ref().0 }
-    }
-
-    /// Gets a mutable reference to the key in the entry.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn key_mut(&mut self) -> &mut K {
-        unsafe { &mut self.elem.as_mut().0 }
-    }
-
-    /// Converts the entry into a mutable reference to the key in the entry
-    /// with a lifetime bound to the map itself.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn into_key(self) -> &'a mut K {
-        unsafe { &mut self.elem.as_mut().0 }
-    }
-
-    /// Gets a reference to the value in the entry.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn get(&self) -> &V {
-        unsafe { &self.elem.as_ref().1 }
-    }
-
-    /// Converts the OccupiedEntry into a mutable reference to the value in the entry
-    /// with a lifetime bound to the map itself.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn into_mut(self) -> &'a mut V {
-        unsafe { &mut self.elem.as_mut().1 }
-    }
-
-    /// Gets a mutable reference to the value in the entry.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn get_mut(&mut self) -> &mut V {
-        unsafe { &mut self.elem.as_mut().1 }
-    }
-
-    /// Gets a reference to the key and value in the entry.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn get_key_value(&mut self) -> (&K, &V) {
-        unsafe {
-            let &(ref key, ref value) = self.elem.as_ref();
-            (key, value)
-        }
-    }
-
-    /// Gets a mutable reference to the key and value in the entry.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) {
-        unsafe {
-            let &mut (ref mut key, ref mut value) = self.elem.as_mut();
-            (key, value)
-        }
-    }
-
-    /// Converts the OccupiedEntry into a mutable reference to the key and value in the entry
-    /// with a lifetime bound to the map itself.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn into_key_value(self) -> (&'a mut K, &'a mut V) {
-        unsafe {
-            let &mut (ref mut key, ref mut value) = self.elem.as_mut();
-            (key, value)
-        }
-    }
-
-    /// Sets the value of the entry, and returns the entry's old value.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert(&mut self, value: V) -> V {
-        mem::replace(self.get_mut(), value)
-    }
-
-    /// Sets the value of the entry, and returns the entry's old value.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert_key(&mut self, key: K) -> K {
-        mem::replace(self.key_mut(), key)
-    }
-
-    /// Takes the value out of the entry, and returns it.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn remove(self) -> V {
-        self.remove_entry().1
-    }
-
-    /// Take the ownership of the key and value from the map.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn remove_entry(self) -> (K, V) {
-        unsafe { self.table.remove(self.elem) }
-    }
-
-    /// Provides shared access to the key and owned access to the value of
-    /// the entry and allows to replace or remove it based on the
-    /// value of the returned option.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn replace_entry_with<F>(self, f: F) -> RawEntryMut<'a, K, V, S>
-    where
-        F: FnOnce(&K, V) -> Option<V>,
-    {
-        unsafe {
-            let still_occupied = self
-                .table
-                .replace_bucket_with(self.elem.clone(), |(key, value)| {
-                    f(&key, value).map(|new_value| (key, new_value))
-                });
-
-            if still_occupied {
-                RawEntryMut::Occupied(self)
-            } else {
-                RawEntryMut::Vacant(RawVacantEntryMut {
-                    table: self.table,
-                    hash_builder: self.hash_builder,
-                })
-            }
-        }
-    }
-}
-
-impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> {
-    /// Sets the value of the entry with the VacantEntry's key,
-    /// and returns a mutable reference to it.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V)
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        let mut hasher = self.hash_builder.build_hasher();
-        key.hash(&mut hasher);
-        self.insert_hashed_nocheck(hasher.finish(), key, value)
-    }
-
-    /// Sets the value of the entry with the VacantEntry's key,
-    /// and returns a mutable reference to it.
-    #[cfg_attr(feature = "inline-more", inline)]
-    #[allow(clippy::shadow_unrelated)]
-    pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V)
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        let hash_builder = self.hash_builder;
-        self.insert_with_hasher(hash, key, value, |k| make_hash(hash_builder, k))
-    }
-
-    /// Set the value of an entry with a custom hasher function.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert_with_hasher<H>(
-        self,
-        hash: u64,
-        key: K,
-        value: V,
-        hasher: H,
-    ) -> (&'a mut K, &'a mut V)
-    where
-        H: Fn(&K) -> u64,
-    {
-        let &mut (ref mut k, ref mut v) = self
-            .table
-            .insert_entry(hash, (key, value), |x| hasher(&x.0));
-        (k, v)
-    }
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn insert_entry(self, key: K, value: V) -> RawOccupiedEntryMut<'a, K, V, S>
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        let hash_builder = self.hash_builder;
-        let mut hasher = self.hash_builder.build_hasher();
-        key.hash(&mut hasher);
-
-        let elem = self.table.insert(hasher.finish(), (key, value), |k| {
-            make_hash(hash_builder, &k.0)
-        });
-        RawOccupiedEntryMut {
-            elem,
-            table: self.table,
-            hash_builder: self.hash_builder,
-        }
-    }
-}
-
-impl<K, V, S> Debug for RawEntryBuilderMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("RawEntryBuilder").finish()
-    }
-}
-
-impl<K: Debug, V: Debug, S> Debug for RawEntryMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            RawEntryMut::Vacant(ref v) => f.debug_tuple("RawEntry").field(v).finish(),
-            RawEntryMut::Occupied(ref o) => f.debug_tuple("RawEntry").field(o).finish(),
-        }
-    }
-}
-
-impl<K: Debug, V: Debug, S> Debug for RawOccupiedEntryMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("RawOccupiedEntryMut")
-            .field("key", self.key())
-            .field("value", self.get())
-            .finish()
-    }
-}
-
-impl<K, V, S> Debug for RawVacantEntryMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("RawVacantEntryMut").finish()
-    }
-}
-
-impl<K, V, S> Debug for RawEntryBuilder<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("RawEntryBuilder").finish()
-    }
-}
-
-/// A view into a single entry in a map, which may either be vacant or occupied.
-///
-/// This `enum` is constructed from the [`entry`] method on [`HashMap`].
-///
-/// [`HashMap`]: struct.HashMap.html
-/// [`entry`]: struct.HashMap.html#method.entry
-pub enum Entry<'a, K, V, S> {
-    /// An occupied entry.
-    Occupied(OccupiedEntry<'a, K, V, S>),
-
-    /// A vacant entry.
-    Vacant(VacantEntry<'a, K, V, S>),
-}
-
-impl<K: Debug, V: Debug, S> Debug for Entry<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
-            Entry::Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(),
-        }
-    }
-}
-
-/// A view into an occupied entry in a `HashMap`.
-/// It is part of the [`Entry`] enum.
-///
-/// [`Entry`]: enum.Entry.html
-pub struct OccupiedEntry<'a, K, V, S> {
-    hash: u64,
-    key: Option<K>,
-    elem: Bucket<(K, V)>,
-    table: &'a mut HashMap<K, V, S>,
-}
-
-unsafe impl<K, V, S> Send for OccupiedEntry<'_, K, V, S>
-where
-    K: Send,
-    V: Send,
-    S: Send,
-{
-}
-unsafe impl<K, V, S> Sync for OccupiedEntry<'_, K, V, S>
-where
-    K: Sync,
-    V: Sync,
-    S: Sync,
-{
-}
-
-impl<K: Debug, V: Debug, S> Debug for OccupiedEntry<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("OccupiedEntry")
-            .field("key", self.key())
-            .field("value", self.get())
-            .finish()
-    }
-}
-
-/// A view into a vacant entry in a `HashMap`.
-/// It is part of the [`Entry`] enum.
-///
-/// [`Entry`]: enum.Entry.html
-pub struct VacantEntry<'a, K, V, S> {
-    hash: u64,
-    key: K,
-    table: &'a mut HashMap<K, V, S>,
-}
-
-impl<K: Debug, V, S> Debug for VacantEntry<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple("VacantEntry").field(self.key()).finish()
-    }
-}
-
-impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S> {
-    type Item = (&'a K, &'a V);
-    type IntoIter = Iter<'a, K, V>;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn into_iter(self) -> Iter<'a, K, V> {
-        self.iter()
-    }
-}
-
-impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S> {
-    type Item = (&'a K, &'a mut V);
-    type IntoIter = IterMut<'a, K, V>;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn into_iter(self) -> IterMut<'a, K, V> {
-        self.iter_mut()
-    }
-}
-
-impl<K, V, S> IntoIterator for HashMap<K, V, S> {
-    type Item = (K, V);
-    type IntoIter = IntoIter<K, V>;
-
-    /// Creates a consuming iterator, that is, one that moves each key-value
-    /// pair out of the map in arbitrary order. The map cannot be used after
-    /// calling this.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// // Not possible with .iter()
-    /// let vec: Vec<(&str, i32)> = map.into_iter().collect();
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn into_iter(self) -> IntoIter<K, V> {
-        IntoIter {
-            inner: self.table.into_iter(),
-        }
-    }
-}
-
-impl<'a, K, V> Iterator for Iter<'a, K, V> {
-    type Item = (&'a K, &'a V);
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<(&'a K, &'a V)> {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.inner.next() {
-            Some(x) => unsafe {
-                let r = x.as_ref();
-                Some((&r.0, &r.1))
-            },
-            None => None,
-        }
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-impl<K, V> ExactSizeIterator for Iter<'_, K, V> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-
-impl<K, V> FusedIterator for Iter<'_, K, V> {}
-
-impl<'a, K, V> Iterator for IterMut<'a, K, V> {
-    type Item = (&'a K, &'a mut V);
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.inner.next() {
-            Some(x) => unsafe {
-                let r = x.as_mut();
-                Some((&r.0, &mut r.1))
-            },
-            None => None,
-        }
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-impl<K, V> ExactSizeIterator for IterMut<'_, K, V> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-impl<K, V> FusedIterator for IterMut<'_, K, V> {}
-
-impl<K, V> fmt::Debug for IterMut<'_, K, V>
-where
-    K: fmt::Debug,
-    V: fmt::Debug,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.iter()).finish()
-    }
-}
-
-impl<K, V> Iterator for IntoIter<K, V> {
-    type Item = (K, V);
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<(K, V)> {
-        self.inner.next()
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-impl<K, V> ExactSizeIterator for IntoIter<K, V> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-impl<K, V> FusedIterator for IntoIter<K, V> {}
-
-impl<K: Debug, V: Debug> fmt::Debug for IntoIter<K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.iter()).finish()
-    }
-}
-
-impl<'a, K, V> Iterator for Keys<'a, K, V> {
-    type Item = &'a K;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<&'a K> {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.inner.next() {
-            Some((k, _)) => Some(k),
-            None => None,
-        }
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-impl<K, V> ExactSizeIterator for Keys<'_, K, V> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-impl<K, V> FusedIterator for Keys<'_, K, V> {}
-
-impl<'a, K, V> Iterator for Values<'a, K, V> {
-    type Item = &'a V;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<&'a V> {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.inner.next() {
-            Some((_, v)) => Some(v),
-            None => None,
-        }
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-impl<K, V> ExactSizeIterator for Values<'_, K, V> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-impl<K, V> FusedIterator for Values<'_, K, V> {}
-
-impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
-    type Item = &'a mut V;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<&'a mut V> {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.inner.next() {
-            Some((_, v)) => Some(v),
-            None => None,
-        }
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-impl<K, V> ExactSizeIterator for ValuesMut<'_, K, V> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-impl<K, V> FusedIterator for ValuesMut<'_, K, V> {}
-
-impl<K, V> fmt::Debug for ValuesMut<'_, K, V>
-where
-    K: fmt::Debug,
-    V: fmt::Debug,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.inner.iter()).finish()
-    }
-}
-
-impl<'a, K, V> Iterator for Drain<'a, K, V> {
-    type Item = (K, V);
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<(K, V)> {
-        self.inner.next()
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-impl<K, V> ExactSizeIterator for Drain<'_, K, V> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-impl<K, V> FusedIterator for Drain<'_, K, V> {}
-
-impl<K, V> fmt::Debug for Drain<'_, K, V>
-where
-    K: fmt::Debug,
-    V: fmt::Debug,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.iter()).finish()
-    }
-}
-
-impl<'a, K, V, S> Entry<'a, K, V, S> {
-    /// Sets the value of the entry, and returns an OccupiedEntry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// let entry = map.entry("horseyland").insert(37);
-    ///
-    /// assert_eq!(entry.key(), &"horseyland");
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert(self, value: V) -> OccupiedEntry<'a, K, V, S>
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            Entry::Occupied(mut entry) => {
-                entry.insert(value);
-                entry
-            }
-            Entry::Vacant(entry) => entry.insert_entry(value),
-        }
-    }
-
-    /// Ensures a value is in the entry by inserting the default if empty, and returns
-    /// a mutable reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// map.entry("poneyland").or_insert(3);
-    /// assert_eq!(map["poneyland"], 3);
-    ///
-    /// *map.entry("poneyland").or_insert(10) *= 2;
-    /// assert_eq!(map["poneyland"], 6);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn or_insert(self, default: V) -> &'a mut V
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            Entry::Occupied(entry) => entry.into_mut(),
-            Entry::Vacant(entry) => entry.insert(default),
-        }
-    }
-
-    /// Ensures a value is in the entry by inserting the result of the default function if empty,
-    /// and returns a mutable reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, String> = HashMap::new();
-    /// let s = "hoho".to_string();
-    ///
-    /// map.entry("poneyland").or_insert_with(|| s);
-    ///
-    /// assert_eq!(map["poneyland"], "hoho".to_string());
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            Entry::Occupied(entry) => entry.into_mut(),
-            Entry::Vacant(entry) => entry.insert(default()),
-        }
-    }
-
-    /// Ensures a value is in the entry by inserting, if empty, the result of the default function,
-    /// which takes the key as its argument, and returns a mutable reference to the value in the
-    /// entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, usize> = HashMap::new();
-    ///
-    /// map.entry("poneyland").or_insert_with_key(|key| key.chars().count());
-    ///
-    /// assert_eq!(map["poneyland"], 9);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> &'a mut V
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            Entry::Occupied(entry) => entry.into_mut(),
-            Entry::Vacant(entry) => {
-                let value = default(entry.key());
-                entry.insert(value)
-            }
-        }
-    }
-
-    /// Returns a reference to this entry's key.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn key(&self) -> &K {
-        match *self {
-            Entry::Occupied(ref entry) => entry.key(),
-            Entry::Vacant(ref entry) => entry.key(),
-        }
-    }
-
-    /// Provides in-place mutable access to an occupied entry before any
-    /// potential inserts into the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// map.entry("poneyland")
-    ///    .and_modify(|e| { *e += 1 })
-    ///    .or_insert(42);
-    /// assert_eq!(map["poneyland"], 42);
-    ///
-    /// map.entry("poneyland")
-    ///    .and_modify(|e| { *e += 1 })
-    ///    .or_insert(42);
-    /// assert_eq!(map["poneyland"], 43);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn and_modify<F>(self, f: F) -> Self
-    where
-        F: FnOnce(&mut V),
-    {
-        match self {
-            Entry::Occupied(mut entry) => {
-                f(entry.get_mut());
-                Entry::Occupied(entry)
-            }
-            Entry::Vacant(entry) => Entry::Vacant(entry),
-        }
-    }
-
-    /// Provides shared access to the key and owned access to the value of
-    /// an occupied entry and allows to replace or remove it based on the
-    /// value of the returned option.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// let entry = map
-    ///     .entry("poneyland")
-    ///     .and_replace_entry_with(|_k, _v| panic!());
-    ///
-    /// match entry {
-    ///     Entry::Vacant(e) => {
-    ///         assert_eq!(e.key(), &"poneyland");
-    ///     }
-    ///     Entry::Occupied(_) => panic!(),
-    /// }
-    ///
-    /// map.insert("poneyland", 42);
-    ///
-    /// let entry = map
-    ///     .entry("poneyland")
-    ///     .and_replace_entry_with(|k, v| {
-    ///         assert_eq!(k, &"poneyland");
-    ///         assert_eq!(v, 42);
-    ///         Some(v + 1)
-    ///     });
-    ///
-    /// match entry {
-    ///     Entry::Occupied(e) => {
-    ///         assert_eq!(e.key(), &"poneyland");
-    ///         assert_eq!(e.get(), &43);
-    ///     }
-    ///     Entry::Vacant(_) => panic!(),
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 43);
-    ///
-    /// let entry = map
-    ///     .entry("poneyland")
-    ///     .and_replace_entry_with(|_k, _v| None);
-    ///
-    /// match entry {
-    ///     Entry::Vacant(e) => assert_eq!(e.key(), &"poneyland"),
-    ///     Entry::Occupied(_) => panic!(),
-    /// }
-    ///
-    /// assert!(!map.contains_key("poneyland"));
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn and_replace_entry_with<F>(self, f: F) -> Self
-    where
-        F: FnOnce(&K, V) -> Option<V>,
-    {
-        match self {
-            Entry::Occupied(entry) => entry.replace_entry_with(f),
-            Entry::Vacant(_) => self,
-        }
-    }
-}
-
-impl<'a, K, V: Default, S> Entry<'a, K, V, S> {
-    /// Ensures a value is in the entry by inserting the default value if empty,
-    /// and returns a mutable reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, Option<u32>> = HashMap::new();
-    /// map.entry("poneyland").or_default();
-    ///
-    /// assert_eq!(map["poneyland"], None);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn or_default(self) -> &'a mut V
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            Entry::Occupied(entry) => entry.into_mut(),
-            Entry::Vacant(entry) => entry.insert(Default::default()),
-        }
-    }
-}
-
-impl<'a, K, V, S> OccupiedEntry<'a, K, V, S> {
-    /// Gets a reference to the key in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.entry("poneyland").or_insert(12);
-    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn key(&self) -> &K {
-        unsafe { &self.elem.as_ref().0 }
-    }
-
-    /// Take the ownership of the key and value from the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.entry("poneyland").or_insert(12);
-    ///
-    /// if let Entry::Occupied(o) = map.entry("poneyland") {
-    ///     // We delete the entry from the map.
-    ///     o.remove_entry();
-    /// }
-    ///
-    /// assert_eq!(map.contains_key("poneyland"), false);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn remove_entry(self) -> (K, V) {
-        unsafe { self.table.table.remove(self.elem) }
-    }
-
-    /// Gets a reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.entry("poneyland").or_insert(12);
-    ///
-    /// if let Entry::Occupied(o) = map.entry("poneyland") {
-    ///     assert_eq!(o.get(), &12);
-    /// }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn get(&self) -> &V {
-        unsafe { &self.elem.as_ref().1 }
-    }
-
-    /// Gets a mutable reference to the value in the entry.
-    ///
-    /// If you need a reference to the `OccupiedEntry` which may outlive the
-    /// destruction of the `Entry` value, see [`into_mut`].
-    ///
-    /// [`into_mut`]: #method.into_mut
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.entry("poneyland").or_insert(12);
-    ///
-    /// assert_eq!(map["poneyland"], 12);
-    /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
-    ///     *o.get_mut() += 10;
-    ///     assert_eq!(*o.get(), 22);
-    ///
-    ///     // We can use the same Entry multiple times.
-    ///     *o.get_mut() += 2;
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 24);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn get_mut(&mut self) -> &mut V {
-        unsafe { &mut self.elem.as_mut().1 }
-    }
-
-    /// Converts the OccupiedEntry into a mutable reference to the value in the entry
-    /// with a lifetime bound to the map itself.
-    ///
-    /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
-    ///
-    /// [`get_mut`]: #method.get_mut
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.entry("poneyland").or_insert(12);
-    ///
-    /// assert_eq!(map["poneyland"], 12);
-    /// if let Entry::Occupied(o) = map.entry("poneyland") {
-    ///     *o.into_mut() += 10;
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 22);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn into_mut(self) -> &'a mut V {
-        unsafe { &mut self.elem.as_mut().1 }
-    }
-
-    /// Sets the value of the entry, and returns the entry's old value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.entry("poneyland").or_insert(12);
-    ///
-    /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
-    ///     assert_eq!(o.insert(15), 12);
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 15);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert(&mut self, mut value: V) -> V {
-        let old_value = self.get_mut();
-        mem::swap(&mut value, old_value);
-        value
-    }
-
-    /// Takes the value out of the entry, and returns it.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.entry("poneyland").or_insert(12);
-    ///
-    /// if let Entry::Occupied(o) = map.entry("poneyland") {
-    ///     assert_eq!(o.remove(), 12);
-    /// }
-    ///
-    /// assert_eq!(map.contains_key("poneyland"), false);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn remove(self) -> V {
-        self.remove_entry().1
-    }
-
-    /// Replaces the entry, returning the old key and value. The new key in the hash map will be
-    /// the key used to create this entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::hash_map::{Entry, HashMap};
-    /// use std::rc::Rc;
-    ///
-    /// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
-    /// map.insert(Rc::new("Stringthing".to_string()), 15);
-    ///
-    /// let my_key = Rc::new("Stringthing".to_string());
-    ///
-    /// if let Entry::Occupied(entry) = map.entry(my_key) {
-    ///     // Also replace the key with a handle to our other key.
-    ///     let (old_key, old_value): (Rc<String>, u32) = entry.replace_entry(16);
-    /// }
-    ///
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn replace_entry(self, value: V) -> (K, V) {
-        let entry = unsafe { self.elem.as_mut() };
-
-        let old_key = mem::replace(&mut entry.0, self.key.unwrap());
-        let old_value = mem::replace(&mut entry.1, value);
-
-        (old_key, old_value)
-    }
-
-    /// Replaces the key in the hash map with the key used to create this entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::hash_map::{Entry, HashMap};
-    /// use std::rc::Rc;
-    ///
-    /// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
-    /// let mut known_strings: Vec<Rc<String>> = Vec::new();
-    ///
-    /// // Initialise known strings, run program, etc.
-    ///
-    /// reclaim_memory(&mut map, &known_strings);
-    ///
-    /// fn reclaim_memory(map: &mut HashMap<Rc<String>, u32>, known_strings: &[Rc<String>] ) {
-    ///     for s in known_strings {
-    ///         if let Entry::Occupied(entry) = map.entry(s.clone()) {
-    ///             // Replaces the entry's key with our version of it in `known_strings`.
-    ///             entry.replace_key();
-    ///         }
-    ///     }
-    /// }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn replace_key(self) -> K {
-        let entry = unsafe { self.elem.as_mut() };
-        mem::replace(&mut entry.0, self.key.unwrap())
-    }
-
-    /// Provides shared access to the key and owned access to the value of
-    /// the entry and allows to replace or remove it based on the
-    /// value of the returned option.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.insert("poneyland", 42);
-    ///
-    /// let entry = match map.entry("poneyland") {
-    ///     Entry::Occupied(e) => {
-    ///         e.replace_entry_with(|k, v| {
-    ///             assert_eq!(k, &"poneyland");
-    ///             assert_eq!(v, 42);
-    ///             Some(v + 1)
-    ///         })
-    ///     }
-    ///     Entry::Vacant(_) => panic!(),
-    /// };
-    ///
-    /// match entry {
-    ///     Entry::Occupied(e) => {
-    ///         assert_eq!(e.key(), &"poneyland");
-    ///         assert_eq!(e.get(), &43);
-    ///     }
-    ///     Entry::Vacant(_) => panic!(),
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 43);
-    ///
-    /// let entry = match map.entry("poneyland") {
-    ///     Entry::Occupied(e) => e.replace_entry_with(|_k, _v| None),
-    ///     Entry::Vacant(_) => panic!(),
-    /// };
-    ///
-    /// match entry {
-    ///     Entry::Vacant(e) => {
-    ///         assert_eq!(e.key(), &"poneyland");
-    ///     }
-    ///     Entry::Occupied(_) => panic!(),
-    /// }
-    ///
-    /// assert!(!map.contains_key("poneyland"));
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn replace_entry_with<F>(self, f: F) -> Entry<'a, K, V, S>
-    where
-        F: FnOnce(&K, V) -> Option<V>,
-    {
-        unsafe {
-            let mut spare_key = None;
-
-            self.table
-                .table
-                .replace_bucket_with(self.elem.clone(), |(key, value)| {
-                    if let Some(new_value) = f(&key, value) {
-                        Some((key, new_value))
-                    } else {
-                        spare_key = Some(key);
-                        None
-                    }
-                });
-
-            if let Some(key) = spare_key {
-                Entry::Vacant(VacantEntry {
-                    hash: self.hash,
-                    key,
-                    table: self.table,
-                })
-            } else {
-                Entry::Occupied(self)
-            }
-        }
-    }
-}
-
-impl<'a, K, V, S> VacantEntry<'a, K, V, S> {
-    /// Gets a reference to the key that would be used when inserting a value
-    /// through the `VacantEntry`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn key(&self) -> &K {
-        &self.key
-    }
-
-    /// Take ownership of the key.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// if let Entry::Vacant(v) = map.entry("poneyland") {
-    ///     v.into_key();
-    /// }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn into_key(self) -> K {
-        self.key
-    }
-
-    /// Sets the value of the entry with the VacantEntry's key,
-    /// and returns a mutable reference to it.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// if let Entry::Vacant(o) = map.entry("poneyland") {
-    ///     o.insert(37);
-    /// }
-    /// assert_eq!(map["poneyland"], 37);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert(self, value: V) -> &'a mut V
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        let hash_builder = &self.table.hash_builder;
-        let table = &mut self.table.table;
-        let entry = table.insert_entry(self.hash, (self.key, value), |x| {
-            make_hash(hash_builder, &x.0)
-        });
-        &mut entry.1
-    }
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, S>
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        let hash_builder = &self.table.hash_builder;
-        let elem = self.table.table.insert(self.hash, (self.key, value), |x| {
-            make_hash(hash_builder, &x.0)
-        });
-        OccupiedEntry {
-            hash: self.hash,
-            key: None,
-            elem,
-            table: self.table,
-        }
-    }
-}
-
-impl<K, V, S> FromIterator<(K, V)> for HashMap<K, V, S>
-where
-    K: Eq + Hash,
-    S: BuildHasher + Default,
-{
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
-        let iter = iter.into_iter();
-        let mut map = Self::with_capacity_and_hasher(iter.size_hint().0, S::default());
-        iter.for_each(|(k, v)| {
-            map.insert(k, v);
-        });
-        map
-    }
-}
-
-/// Inserts all new key-values from the iterator and replaces values with existing
-/// keys with new values returned from the iterator.
-impl<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
-where
-    K: Eq + Hash,
-    S: BuildHasher,
-{
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
-        // Keys may be already present or show multiple times in the iterator.
-        // Reserve the entire hint lower bound if the map is empty.
-        // Otherwise reserve half the hint (rounded up), so the map
-        // will only resize twice in the worst case.
-        let iter = iter.into_iter();
-        let reserve = if self.is_empty() {
-            iter.size_hint().0
-        } else {
-            (iter.size_hint().0 + 1) / 2
-        };
-        self.reserve(reserve);
-        iter.for_each(move |(k, v)| {
-            self.insert(k, v);
-        });
-    }
-
-    #[inline]
-    #[cfg(feature = "nightly")]
-    fn extend_one(&mut self, (k, v): (K, V)) {
-        self.insert(k, v);
-    }
-
-    #[inline]
-    #[cfg(feature = "nightly")]
-    fn extend_reserve(&mut self, additional: usize) {
-        // Keys may be already present or show multiple times in the iterator.
-        // Reserve the entire hint lower bound if the map is empty.
-        // Otherwise reserve half the hint (rounded up), so the map
-        // will only resize twice in the worst case.
-        let reserve = if self.is_empty() {
-            additional
-        } else {
-            (additional + 1) / 2
-        };
-        self.reserve(reserve);
-    }
-}
-
-impl<'a, K, V, S> Extend<(&'a K, &'a V)> for HashMap<K, V, S>
-where
-    K: Eq + Hash + Copy,
-    V: Copy,
-    S: BuildHasher,
-{
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn extend<T: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: T) {
-        self.extend(iter.into_iter().map(|(&key, &value)| (key, value)));
-    }
-
-    #[inline]
-    #[cfg(feature = "nightly")]
-    fn extend_one(&mut self, (k, v): (&'a K, &'a V)) {
-        self.insert(*k, *v);
-    }
-
-    #[inline]
-    #[cfg(feature = "nightly")]
-    fn extend_reserve(&mut self, additional: usize) {
-        Extend::<(K, V)>::extend_reserve(self, additional);
-    }
-}
-
-#[allow(dead_code)]
-fn assert_covariance() {
-    fn map_key<'new>(v: HashMap<&'static str, u8>) -> HashMap<&'new str, u8> {
-        v
-    }
-    fn map_val<'new>(v: HashMap<u8, &'static str>) -> HashMap<u8, &'new str> {
-        v
-    }
-    fn iter_key<'a, 'new>(v: Iter<'a, &'static str, u8>) -> Iter<'a, &'new str, u8> {
-        v
-    }
-    fn iter_val<'a, 'new>(v: Iter<'a, u8, &'static str>) -> Iter<'a, u8, &'new str> {
-        v
-    }
-    fn into_iter_key<'new>(v: IntoIter<&'static str, u8>) -> IntoIter<&'new str, u8> {
-        v
-    }
-    fn into_iter_val<'new>(v: IntoIter<u8, &'static str>) -> IntoIter<u8, &'new str> {
-        v
-    }
-    fn keys_key<'a, 'new>(v: Keys<'a, &'static str, u8>) -> Keys<'a, &'new str, u8> {
-        v
-    }
-    fn keys_val<'a, 'new>(v: Keys<'a, u8, &'static str>) -> Keys<'a, u8, &'new str> {
-        v
-    }
-    fn values_key<'a, 'new>(v: Values<'a, &'static str, u8>) -> Values<'a, &'new str, u8> {
-        v
-    }
-    fn values_val<'a, 'new>(v: Values<'a, u8, &'static str>) -> Values<'a, u8, &'new str> {
-        v
-    }
-    fn drain<'new>(
-        d: Drain<'static, &'static str, &'static str>,
-    ) -> Drain<'new, &'new str, &'new str> {
-        d
-    }
-}
-
-#[cfg(test)]
-mod test_map {
-    use super::DefaultHashBuilder;
-    use super::Entry::{Occupied, Vacant};
-    use super::{HashMap, RawEntryMut};
-    use crate::TryReserveError::*;
-    use rand::{rngs::SmallRng, Rng, SeedableRng};
-    use std::cell::RefCell;
-    use std::usize;
-    use std::vec::Vec;
-
-    #[test]
-    fn test_zero_capacities() {
-        type HM = HashMap<i32, i32>;
-
-        let m = HM::new();
-        assert_eq!(m.capacity(), 0);
-
-        let m = HM::default();
-        assert_eq!(m.capacity(), 0);
-
-        let m = HM::with_hasher(DefaultHashBuilder::default());
-        assert_eq!(m.capacity(), 0);
-
-        let m = HM::with_capacity(0);
-        assert_eq!(m.capacity(), 0);
-
-        let m = HM::with_capacity_and_hasher(0, DefaultHashBuilder::default());
-        assert_eq!(m.capacity(), 0);
-
-        let mut m = HM::new();
-        m.insert(1, 1);
-        m.insert(2, 2);
-        m.remove(&1);
-        m.remove(&2);
-        m.shrink_to_fit();
-        assert_eq!(m.capacity(), 0);
-
-        let mut m = HM::new();
-        m.reserve(0);
-        assert_eq!(m.capacity(), 0);
-    }
-
-    #[test]
-    fn test_create_capacity_zero() {
-        let mut m = HashMap::with_capacity(0);
-
-        assert!(m.insert(1, 1).is_none());
-
-        assert!(m.contains_key(&1));
-        assert!(!m.contains_key(&0));
-    }
-
-    #[test]
-    fn test_insert() {
-        let mut m = HashMap::new();
-        assert_eq!(m.len(), 0);
-        assert!(m.insert(1, 2).is_none());
-        assert_eq!(m.len(), 1);
-        assert!(m.insert(2, 4).is_none());
-        assert_eq!(m.len(), 2);
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert_eq!(*m.get(&2).unwrap(), 4);
-    }
-
-    #[test]
-    fn test_clone() {
-        let mut m = HashMap::new();
-        assert_eq!(m.len(), 0);
-        assert!(m.insert(1, 2).is_none());
-        assert_eq!(m.len(), 1);
-        assert!(m.insert(2, 4).is_none());
-        assert_eq!(m.len(), 2);
-        let m2 = m.clone();
-        assert_eq!(*m2.get(&1).unwrap(), 2);
-        assert_eq!(*m2.get(&2).unwrap(), 4);
-        assert_eq!(m2.len(), 2);
-    }
-
-    #[test]
-    fn test_clone_from() {
-        let mut m = HashMap::new();
-        let mut m2 = HashMap::new();
-        assert_eq!(m.len(), 0);
-        assert!(m.insert(1, 2).is_none());
-        assert_eq!(m.len(), 1);
-        assert!(m.insert(2, 4).is_none());
-        assert_eq!(m.len(), 2);
-        m2.clone_from(&m);
-        assert_eq!(*m2.get(&1).unwrap(), 2);
-        assert_eq!(*m2.get(&2).unwrap(), 4);
-        assert_eq!(m2.len(), 2);
-    }
-
-    thread_local! { static DROP_VECTOR: RefCell<Vec<i32>> = RefCell::new(Vec::new()) }
-
-    #[derive(Hash, PartialEq, Eq)]
-    struct Droppable {
-        k: usize,
-    }
-
-    impl Droppable {
-        fn new(k: usize) -> Droppable {
-            DROP_VECTOR.with(|slot| {
-                slot.borrow_mut()[k] += 1;
-            });
-
-            Droppable { k }
-        }
-    }
-
-    impl Drop for Droppable {
-        fn drop(&mut self) {
-            DROP_VECTOR.with(|slot| {
-                slot.borrow_mut()[self.k] -= 1;
-            });
-        }
-    }
-
-    impl Clone for Droppable {
-        fn clone(&self) -> Self {
-            Droppable::new(self.k)
-        }
-    }
-
-    #[test]
-    fn test_drops() {
-        DROP_VECTOR.with(|slot| {
-            *slot.borrow_mut() = vec![0; 200];
-        });
-
-        {
-            let mut m = HashMap::new();
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 0);
-                }
-            });
-
-            for i in 0..100 {
-                let d1 = Droppable::new(i);
-                let d2 = Droppable::new(i + 100);
-                m.insert(d1, d2);
-            }
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 1);
-                }
-            });
-
-            for i in 0..50 {
-                let k = Droppable::new(i);
-                let v = m.remove(&k);
-
-                assert!(v.is_some());
-
-                DROP_VECTOR.with(|v| {
-                    assert_eq!(v.borrow()[i], 1);
-                    assert_eq!(v.borrow()[i + 100], 1);
-                });
-            }
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..50 {
-                    assert_eq!(v.borrow()[i], 0);
-                    assert_eq!(v.borrow()[i + 100], 0);
-                }
-
-                for i in 50..100 {
-                    assert_eq!(v.borrow()[i], 1);
-                    assert_eq!(v.borrow()[i + 100], 1);
-                }
-            });
-        }
-
-        DROP_VECTOR.with(|v| {
-            for i in 0..200 {
-                assert_eq!(v.borrow()[i], 0);
-            }
-        });
-    }
-
-    #[test]
-    fn test_into_iter_drops() {
-        DROP_VECTOR.with(|v| {
-            *v.borrow_mut() = vec![0; 200];
-        });
-
-        let hm = {
-            let mut hm = HashMap::new();
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 0);
-                }
-            });
-
-            for i in 0..100 {
-                let d1 = Droppable::new(i);
-                let d2 = Droppable::new(i + 100);
-                hm.insert(d1, d2);
-            }
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 1);
-                }
-            });
-
-            hm
-        };
-
-        // By the way, ensure that cloning doesn't screw up the dropping.
-        drop(hm.clone());
-
-        {
-            let mut half = hm.into_iter().take(50);
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 1);
-                }
-            });
-
-            for _ in half.by_ref() {}
-
-            DROP_VECTOR.with(|v| {
-                let nk = (0..100).filter(|&i| v.borrow()[i] == 1).count();
-
-                let nv = (0..100).filter(|&i| v.borrow()[i + 100] == 1).count();
-
-                assert_eq!(nk, 50);
-                assert_eq!(nv, 50);
-            });
-        };
-
-        DROP_VECTOR.with(|v| {
-            for i in 0..200 {
-                assert_eq!(v.borrow()[i], 0);
-            }
-        });
-    }
-
-    #[test]
-    fn test_empty_remove() {
-        let mut m: HashMap<i32, bool> = HashMap::new();
-        assert_eq!(m.remove(&0), None);
-    }
-
-    #[test]
-    fn test_empty_entry() {
-        let mut m: HashMap<i32, bool> = HashMap::new();
-        match m.entry(0) {
-            Occupied(_) => panic!(),
-            Vacant(_) => {}
-        }
-        assert!(*m.entry(0).or_insert(true));
-        assert_eq!(m.len(), 1);
-    }
-
-    #[test]
-    fn test_empty_iter() {
-        let mut m: HashMap<i32, bool> = HashMap::new();
-        assert_eq!(m.drain().next(), None);
-        assert_eq!(m.keys().next(), None);
-        assert_eq!(m.values().next(), None);
-        assert_eq!(m.values_mut().next(), None);
-        assert_eq!(m.iter().next(), None);
-        assert_eq!(m.iter_mut().next(), None);
-        assert_eq!(m.len(), 0);
-        assert!(m.is_empty());
-        assert_eq!(m.into_iter().next(), None);
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // FIXME: takes too long
-    fn test_lots_of_insertions() {
-        let mut m = HashMap::new();
-
-        // Try this a few times to make sure we never screw up the hashmap's
-        // internal state.
-        for _ in 0..10 {
-            assert!(m.is_empty());
-
-            for i in 1..1001 {
-                assert!(m.insert(i, i).is_none());
-
-                for j in 1..=i {
-                    let r = m.get(&j);
-                    assert_eq!(r, Some(&j));
-                }
-
-                for j in i + 1..1001 {
-                    let r = m.get(&j);
-                    assert_eq!(r, None);
-                }
-            }
-
-            for i in 1001..2001 {
-                assert!(!m.contains_key(&i));
-            }
-
-            // remove forwards
-            for i in 1..1001 {
-                assert!(m.remove(&i).is_some());
-
-                for j in 1..=i {
-                    assert!(!m.contains_key(&j));
-                }
-
-                for j in i + 1..1001 {
-                    assert!(m.contains_key(&j));
-                }
-            }
-
-            for i in 1..1001 {
-                assert!(!m.contains_key(&i));
-            }
-
-            for i in 1..1001 {
-                assert!(m.insert(i, i).is_none());
-            }
-
-            // remove backwards
-            for i in (1..1001).rev() {
-                assert!(m.remove(&i).is_some());
-
-                for j in i..1001 {
-                    assert!(!m.contains_key(&j));
-                }
-
-                for j in 1..i {
-                    assert!(m.contains_key(&j));
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn test_find_mut() {
-        let mut m = HashMap::new();
-        assert!(m.insert(1, 12).is_none());
-        assert!(m.insert(2, 8).is_none());
-        assert!(m.insert(5, 14).is_none());
-        let new = 100;
-        match m.get_mut(&5) {
-            None => panic!(),
-            Some(x) => *x = new,
-        }
-        assert_eq!(m.get(&5), Some(&new));
-    }
-
-    #[test]
-    fn test_insert_overwrite() {
-        let mut m = HashMap::new();
-        assert!(m.insert(1, 2).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert!(!m.insert(1, 3).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 3);
-    }
-
-    #[test]
-    fn test_insert_conflicts() {
-        let mut m = HashMap::with_capacity(4);
-        assert!(m.insert(1, 2).is_none());
-        assert!(m.insert(5, 3).is_none());
-        assert!(m.insert(9, 4).is_none());
-        assert_eq!(*m.get(&9).unwrap(), 4);
-        assert_eq!(*m.get(&5).unwrap(), 3);
-        assert_eq!(*m.get(&1).unwrap(), 2);
-    }
-
-    #[test]
-    fn test_conflict_remove() {
-        let mut m = HashMap::with_capacity(4);
-        assert!(m.insert(1, 2).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert!(m.insert(5, 3).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert_eq!(*m.get(&5).unwrap(), 3);
-        assert!(m.insert(9, 4).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert_eq!(*m.get(&5).unwrap(), 3);
-        assert_eq!(*m.get(&9).unwrap(), 4);
-        assert!(m.remove(&1).is_some());
-        assert_eq!(*m.get(&9).unwrap(), 4);
-        assert_eq!(*m.get(&5).unwrap(), 3);
-    }
-
-    #[test]
-    fn test_is_empty() {
-        let mut m = HashMap::with_capacity(4);
-        assert!(m.insert(1, 2).is_none());
-        assert!(!m.is_empty());
-        assert!(m.remove(&1).is_some());
-        assert!(m.is_empty());
-    }
-
-    #[test]
-    fn test_remove() {
-        let mut m = HashMap::new();
-        m.insert(1, 2);
-        assert_eq!(m.remove(&1), Some(2));
-        assert_eq!(m.remove(&1), None);
-    }
-
-    #[test]
-    fn test_remove_entry() {
-        let mut m = HashMap::new();
-        m.insert(1, 2);
-        assert_eq!(m.remove_entry(&1), Some((1, 2)));
-        assert_eq!(m.remove(&1), None);
-    }
-
-    #[test]
-    fn test_iterate() {
-        let mut m = HashMap::with_capacity(4);
-        for i in 0..32 {
-            assert!(m.insert(i, i * 2).is_none());
-        }
-        assert_eq!(m.len(), 32);
-
-        let mut observed: u32 = 0;
-
-        for (k, v) in &m {
-            assert_eq!(*v, *k * 2);
-            observed |= 1 << *k;
-        }
-        assert_eq!(observed, 0xFFFF_FFFF);
-    }
-
-    #[test]
-    fn test_keys() {
-        let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
-        let map: HashMap<_, _> = vec.into_iter().collect();
-        let keys: Vec<_> = map.keys().cloned().collect();
-        assert_eq!(keys.len(), 3);
-        assert!(keys.contains(&1));
-        assert!(keys.contains(&2));
-        assert!(keys.contains(&3));
-    }
-
-    #[test]
-    fn test_values() {
-        let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
-        let map: HashMap<_, _> = vec.into_iter().collect();
-        let values: Vec<_> = map.values().cloned().collect();
-        assert_eq!(values.len(), 3);
-        assert!(values.contains(&'a'));
-        assert!(values.contains(&'b'));
-        assert!(values.contains(&'c'));
-    }
-
-    #[test]
-    fn test_values_mut() {
-        let vec = vec![(1, 1), (2, 2), (3, 3)];
-        let mut map: HashMap<_, _> = vec.into_iter().collect();
-        for value in map.values_mut() {
-            *value = (*value) * 2
-        }
-        let values: Vec<_> = map.values().cloned().collect();
-        assert_eq!(values.len(), 3);
-        assert!(values.contains(&2));
-        assert!(values.contains(&4));
-        assert!(values.contains(&6));
-    }
-
-    #[test]
-    fn test_find() {
-        let mut m = HashMap::new();
-        assert!(m.get(&1).is_none());
-        m.insert(1, 2);
-        match m.get(&1) {
-            None => panic!(),
-            Some(v) => assert_eq!(*v, 2),
-        }
-    }
-
-    #[test]
-    fn test_eq() {
-        let mut m1 = HashMap::new();
-        m1.insert(1, 2);
-        m1.insert(2, 3);
-        m1.insert(3, 4);
-
-        let mut m2 = HashMap::new();
-        m2.insert(1, 2);
-        m2.insert(2, 3);
-
-        assert!(m1 != m2);
-
-        m2.insert(3, 4);
-
-        assert_eq!(m1, m2);
-    }
-
-    #[test]
-    fn test_show() {
-        let mut map = HashMap::new();
-        let empty: HashMap<i32, i32> = HashMap::new();
-
-        map.insert(1, 2);
-        map.insert(3, 4);
-
-        let map_str = format!("{:?}", map);
-
-        assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}");
-        assert_eq!(format!("{:?}", empty), "{}");
-    }
-
-    #[test]
-    fn test_expand() {
-        let mut m = HashMap::new();
-
-        assert_eq!(m.len(), 0);
-        assert!(m.is_empty());
-
-        let mut i = 0;
-        let old_raw_cap = m.raw_capacity();
-        while old_raw_cap == m.raw_capacity() {
-            m.insert(i, i);
-            i += 1;
-        }
-
-        assert_eq!(m.len(), i);
-        assert!(!m.is_empty());
-    }
-
-    #[test]
-    fn test_behavior_resize_policy() {
-        let mut m = HashMap::new();
-
-        assert_eq!(m.len(), 0);
-        assert_eq!(m.raw_capacity(), 1);
-        assert!(m.is_empty());
-
-        m.insert(0, 0);
-        m.remove(&0);
-        assert!(m.is_empty());
-        let initial_raw_cap = m.raw_capacity();
-        m.reserve(initial_raw_cap);
-        let raw_cap = m.raw_capacity();
-
-        assert_eq!(raw_cap, initial_raw_cap * 2);
-
-        let mut i = 0;
-        for _ in 0..raw_cap * 3 / 4 {
-            m.insert(i, i);
-            i += 1;
-        }
-        // three quarters full
-
-        assert_eq!(m.len(), i);
-        assert_eq!(m.raw_capacity(), raw_cap);
-
-        for _ in 0..raw_cap / 4 {
-            m.insert(i, i);
-            i += 1;
-        }
-        // half full
-
-        let new_raw_cap = m.raw_capacity();
-        assert_eq!(new_raw_cap, raw_cap * 2);
-
-        for _ in 0..raw_cap / 2 - 1 {
-            i -= 1;
-            m.remove(&i);
-            assert_eq!(m.raw_capacity(), new_raw_cap);
-        }
-        // A little more than one quarter full.
-        m.shrink_to_fit();
-        assert_eq!(m.raw_capacity(), raw_cap);
-        // again, a little more than half full
-        for _ in 0..raw_cap / 2 {
-            i -= 1;
-            m.remove(&i);
-        }
-        m.shrink_to_fit();
-
-        assert_eq!(m.len(), i);
-        assert!(!m.is_empty());
-        assert_eq!(m.raw_capacity(), initial_raw_cap);
-    }
-
-    #[test]
-    fn test_reserve_shrink_to_fit() {
-        let mut m = HashMap::new();
-        m.insert(0, 0);
-        m.remove(&0);
-        assert!(m.capacity() >= m.len());
-        for i in 0..128 {
-            m.insert(i, i);
-        }
-        m.reserve(256);
-
-        let usable_cap = m.capacity();
-        for i in 128..(128 + 256) {
-            m.insert(i, i);
-            assert_eq!(m.capacity(), usable_cap);
-        }
-
-        for i in 100..(128 + 256) {
-            assert_eq!(m.remove(&i), Some(i));
-        }
-        m.shrink_to_fit();
-
-        assert_eq!(m.len(), 100);
-        assert!(!m.is_empty());
-        assert!(m.capacity() >= m.len());
-
-        for i in 0..100 {
-            assert_eq!(m.remove(&i), Some(i));
-        }
-        m.shrink_to_fit();
-        m.insert(0, 0);
-
-        assert_eq!(m.len(), 1);
-        assert!(m.capacity() >= m.len());
-        assert_eq!(m.remove(&0), Some(0));
-    }
-
-    #[test]
-    fn test_from_iter() {
-        let xs = [(1, 1), (2, 2), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        for &(k, v) in &xs {
-            assert_eq!(map.get(&k), Some(&v));
-        }
-
-        assert_eq!(map.iter().len(), xs.len() - 1);
-    }
-
-    #[test]
-    fn test_size_hint() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        let mut iter = map.iter();
-
-        for _ in iter.by_ref().take(3) {}
-
-        assert_eq!(iter.size_hint(), (3, Some(3)));
-    }
-
-    #[test]
-    fn test_iter_len() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        let mut iter = map.iter();
-
-        for _ in iter.by_ref().take(3) {}
-
-        assert_eq!(iter.len(), 3);
-    }
-
-    #[test]
-    fn test_mut_size_hint() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let mut map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        let mut iter = map.iter_mut();
-
-        for _ in iter.by_ref().take(3) {}
-
-        assert_eq!(iter.size_hint(), (3, Some(3)));
-    }
-
-    #[test]
-    fn test_iter_mut_len() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let mut map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        let mut iter = map.iter_mut();
-
-        for _ in iter.by_ref().take(3) {}
-
-        assert_eq!(iter.len(), 3);
-    }
-
-    #[test]
-    fn test_index() {
-        let mut map = HashMap::new();
-
-        map.insert(1, 2);
-        map.insert(2, 1);
-        map.insert(3, 4);
-
-        assert_eq!(map[&2], 1);
-    }
-
-    #[test]
-    #[should_panic]
-    fn test_index_nonexistent() {
-        let mut map = HashMap::new();
-
-        map.insert(1, 2);
-        map.insert(2, 1);
-        map.insert(3, 4);
-
-        map[&4];
-    }
-
-    #[test]
-    fn test_entry() {
-        let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
-
-        let mut map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        // Existing key (insert)
-        match map.entry(1) {
-            Vacant(_) => unreachable!(),
-            Occupied(mut view) => {
-                assert_eq!(view.get(), &10);
-                assert_eq!(view.insert(100), 10);
-            }
-        }
-        assert_eq!(map.get(&1).unwrap(), &100);
-        assert_eq!(map.len(), 6);
-
-        // Existing key (update)
-        match map.entry(2) {
-            Vacant(_) => unreachable!(),
-            Occupied(mut view) => {
-                let v = view.get_mut();
-                let new_v = (*v) * 10;
-                *v = new_v;
-            }
-        }
-        assert_eq!(map.get(&2).unwrap(), &200);
-        assert_eq!(map.len(), 6);
-
-        // Existing key (take)
-        match map.entry(3) {
-            Vacant(_) => unreachable!(),
-            Occupied(view) => {
-                assert_eq!(view.remove(), 30);
-            }
-        }
-        assert_eq!(map.get(&3), None);
-        assert_eq!(map.len(), 5);
-
-        // Inexistent key (insert)
-        match map.entry(10) {
-            Occupied(_) => unreachable!(),
-            Vacant(view) => {
-                assert_eq!(*view.insert(1000), 1000);
-            }
-        }
-        assert_eq!(map.get(&10).unwrap(), &1000);
-        assert_eq!(map.len(), 6);
-    }
-
-    #[test]
-    fn test_entry_take_doesnt_corrupt() {
-        #![allow(deprecated)] //rand
-                              // Test for #19292
-        fn check(m: &HashMap<i32, ()>) {
-            for k in m.keys() {
-                assert!(m.contains_key(k), "{} is in keys() but not in the map?", k);
-            }
-        }
-
-        let mut m = HashMap::new();
-
-        let mut rng = {
-            let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
-            SmallRng::from_seed(seed)
-        };
-
-        // Populate the map with some items.
-        for _ in 0..50 {
-            let x = rng.gen_range(-10, 10);
-            m.insert(x, ());
-        }
-
-        for _ in 0..1000 {
-            let x = rng.gen_range(-10, 10);
-            match m.entry(x) {
-                Vacant(_) => {}
-                Occupied(e) => {
-                    e.remove();
-                }
-            }
-
-            check(&m);
-        }
-    }
-
-    #[test]
-    fn test_extend_ref() {
-        let mut a = HashMap::new();
-        a.insert(1, "one");
-        let mut b = HashMap::new();
-        b.insert(2, "two");
-        b.insert(3, "three");
-
-        a.extend(&b);
-
-        assert_eq!(a.len(), 3);
-        assert_eq!(a[&1], "one");
-        assert_eq!(a[&2], "two");
-        assert_eq!(a[&3], "three");
-    }
-
-    #[test]
-    fn test_capacity_not_less_than_len() {
-        let mut a = HashMap::new();
-        let mut item = 0;
-
-        for _ in 0..116 {
-            a.insert(item, 0);
-            item += 1;
-        }
-
-        assert!(a.capacity() > a.len());
-
-        let free = a.capacity() - a.len();
-        for _ in 0..free {
-            a.insert(item, 0);
-            item += 1;
-        }
-
-        assert_eq!(a.len(), a.capacity());
-
-        // Insert at capacity should cause allocation.
-        a.insert(item, 0);
-        assert!(a.capacity() > a.len());
-    }
-
-    #[test]
-    fn test_occupied_entry_key() {
-        let mut a = HashMap::new();
-        let key = "hello there";
-        let value = "value goes here";
-        assert!(a.is_empty());
-        a.insert(key.clone(), value.clone());
-        assert_eq!(a.len(), 1);
-        assert_eq!(a[key], value);
-
-        match a.entry(key.clone()) {
-            Vacant(_) => panic!(),
-            Occupied(e) => assert_eq!(key, *e.key()),
-        }
-        assert_eq!(a.len(), 1);
-        assert_eq!(a[key], value);
-    }
-
-    #[test]
-    fn test_vacant_entry_key() {
-        let mut a = HashMap::new();
-        let key = "hello there";
-        let value = "value goes here";
-
-        assert!(a.is_empty());
-        match a.entry(key.clone()) {
-            Occupied(_) => panic!(),
-            Vacant(e) => {
-                assert_eq!(key, *e.key());
-                e.insert(value.clone());
-            }
-        }
-        assert_eq!(a.len(), 1);
-        assert_eq!(a[key], value);
-    }
-
-    #[test]
-    fn test_occupied_entry_replace_entry_with() {
-        let mut a = HashMap::new();
-
-        let key = "a key";
-        let value = "an initial value";
-        let new_value = "a new value";
-
-        let entry = a.entry(key).insert(value).replace_entry_with(|k, v| {
-            assert_eq!(k, &key);
-            assert_eq!(v, value);
-            Some(new_value)
-        });
-
-        match entry {
-            Occupied(e) => {
-                assert_eq!(e.key(), &key);
-                assert_eq!(e.get(), &new_value);
-            }
-            Vacant(_) => panic!(),
-        }
-
-        assert_eq!(a[key], new_value);
-        assert_eq!(a.len(), 1);
-
-        let entry = match a.entry(key) {
-            Occupied(e) => e.replace_entry_with(|k, v| {
-                assert_eq!(k, &key);
-                assert_eq!(v, new_value);
-                None
-            }),
-            Vacant(_) => panic!(),
-        };
-
-        match entry {
-            Vacant(e) => assert_eq!(e.key(), &key),
-            Occupied(_) => panic!(),
-        }
-
-        assert!(!a.contains_key(key));
-        assert_eq!(a.len(), 0);
-    }
-
-    #[test]
-    fn test_entry_and_replace_entry_with() {
-        let mut a = HashMap::new();
-
-        let key = "a key";
-        let value = "an initial value";
-        let new_value = "a new value";
-
-        let entry = a.entry(key).and_replace_entry_with(|_, _| panic!());
-
-        match entry {
-            Vacant(e) => assert_eq!(e.key(), &key),
-            Occupied(_) => panic!(),
-        }
-
-        a.insert(key, value);
-
-        let entry = a.entry(key).and_replace_entry_with(|k, v| {
-            assert_eq!(k, &key);
-            assert_eq!(v, value);
-            Some(new_value)
-        });
-
-        match entry {
-            Occupied(e) => {
-                assert_eq!(e.key(), &key);
-                assert_eq!(e.get(), &new_value);
-            }
-            Vacant(_) => panic!(),
-        }
-
-        assert_eq!(a[key], new_value);
-        assert_eq!(a.len(), 1);
-
-        let entry = a.entry(key).and_replace_entry_with(|k, v| {
-            assert_eq!(k, &key);
-            assert_eq!(v, new_value);
-            None
-        });
-
-        match entry {
-            Vacant(e) => assert_eq!(e.key(), &key),
-            Occupied(_) => panic!(),
-        }
-
-        assert!(!a.contains_key(key));
-        assert_eq!(a.len(), 0);
-    }
-
-    #[test]
-    fn test_raw_occupied_entry_replace_entry_with() {
-        let mut a = HashMap::new();
-
-        let key = "a key";
-        let value = "an initial value";
-        let new_value = "a new value";
-
-        let entry = a
-            .raw_entry_mut()
-            .from_key(&key)
-            .insert(key, value)
-            .replace_entry_with(|k, v| {
-                assert_eq!(k, &key);
-                assert_eq!(v, value);
-                Some(new_value)
-            });
-
-        match entry {
-            RawEntryMut::Occupied(e) => {
-                assert_eq!(e.key(), &key);
-                assert_eq!(e.get(), &new_value);
-            }
-            RawEntryMut::Vacant(_) => panic!(),
-        }
-
-        assert_eq!(a[key], new_value);
-        assert_eq!(a.len(), 1);
-
-        let entry = match a.raw_entry_mut().from_key(&key) {
-            RawEntryMut::Occupied(e) => e.replace_entry_with(|k, v| {
-                assert_eq!(k, &key);
-                assert_eq!(v, new_value);
-                None
-            }),
-            RawEntryMut::Vacant(_) => panic!(),
-        };
-
-        match entry {
-            RawEntryMut::Vacant(_) => {}
-            RawEntryMut::Occupied(_) => panic!(),
-        }
-
-        assert!(!a.contains_key(key));
-        assert_eq!(a.len(), 0);
-    }
-
-    #[test]
-    fn test_raw_entry_and_replace_entry_with() {
-        let mut a = HashMap::new();
-
-        let key = "a key";
-        let value = "an initial value";
-        let new_value = "a new value";
-
-        let entry = a
-            .raw_entry_mut()
-            .from_key(&key)
-            .and_replace_entry_with(|_, _| panic!());
-
-        match entry {
-            RawEntryMut::Vacant(_) => {}
-            RawEntryMut::Occupied(_) => panic!(),
-        }
-
-        a.insert(key, value);
-
-        let entry = a
-            .raw_entry_mut()
-            .from_key(&key)
-            .and_replace_entry_with(|k, v| {
-                assert_eq!(k, &key);
-                assert_eq!(v, value);
-                Some(new_value)
-            });
-
-        match entry {
-            RawEntryMut::Occupied(e) => {
-                assert_eq!(e.key(), &key);
-                assert_eq!(e.get(), &new_value);
-            }
-            RawEntryMut::Vacant(_) => panic!(),
-        }
-
-        assert_eq!(a[key], new_value);
-        assert_eq!(a.len(), 1);
-
-        let entry = a
-            .raw_entry_mut()
-            .from_key(&key)
-            .and_replace_entry_with(|k, v| {
-                assert_eq!(k, &key);
-                assert_eq!(v, new_value);
-                None
-            });
-
-        match entry {
-            RawEntryMut::Vacant(_) => {}
-            RawEntryMut::Occupied(_) => panic!(),
-        }
-
-        assert!(!a.contains_key(key));
-        assert_eq!(a.len(), 0);
-    }
-
-    #[test]
-    fn test_replace_entry_with_doesnt_corrupt() {
-        #![allow(deprecated)] //rand
-                              // Test for #19292
-        fn check(m: &HashMap<i32, ()>) {
-            for k in m.keys() {
-                assert!(m.contains_key(k), "{} is in keys() but not in the map?", k);
-            }
-        }
-
-        let mut m = HashMap::new();
-
-        let mut rng = {
-            let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
-            SmallRng::from_seed(seed)
-        };
-
-        // Populate the map with some items.
-        for _ in 0..50 {
-            let x = rng.gen_range(-10, 10);
-            m.insert(x, ());
-        }
-
-        for _ in 0..1000 {
-            let x = rng.gen_range(-10, 10);
-            m.entry(x).and_replace_entry_with(|_, _| None);
-            check(&m);
-        }
-    }
-
-    #[test]
-    fn test_retain() {
-        let mut map: HashMap<i32, i32> = (0..100).map(|x| (x, x * 10)).collect();
-
-        map.retain(|&k, _| k % 2 == 0);
-        assert_eq!(map.len(), 50);
-        assert_eq!(map[&2], 20);
-        assert_eq!(map[&4], 40);
-        assert_eq!(map[&6], 60);
-    }
-
-    #[test]
-    fn test_drain_filter() {
-        {
-            let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x * 10)).collect();
-            let drained = map.drain_filter(|&k, _| k % 2 == 0);
-            let mut out = drained.collect::<Vec<_>>();
-            out.sort_unstable();
-            assert_eq!(vec![(0, 0), (2, 20), (4, 40), (6, 60)], out);
-            assert_eq!(map.len(), 4);
-        }
-        {
-            let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x * 10)).collect();
-            drop(map.drain_filter(|&k, _| k % 2 == 0));
-            assert_eq!(map.len(), 4);
-        }
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // FIXME: no OOM signalling (https://github.com/rust-lang/miri/issues/613)
-    fn test_try_reserve() {
-        let mut empty_bytes: HashMap<u8, u8> = HashMap::new();
-
-        const MAX_USIZE: usize = usize::MAX;
-
-        if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) {
-        } else {
-            panic!("usize::MAX should trigger an overflow!");
-        }
-
-        if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE / 8) {
-        } else {
-            // This may succeed if there is enough free memory. Attempt to
-            // allocate a second hashmap to ensure the allocation will fail.
-            let mut empty_bytes2: HashMap<u8, u8> = HashMap::new();
-            if let Err(AllocError { .. }) = empty_bytes2.try_reserve(MAX_USIZE / 8) {
-            } else {
-                panic!("usize::MAX / 8 should trigger an OOM!");
-            }
-        }
-    }
-
-    #[test]
-    fn test_raw_entry() {
-        use super::RawEntryMut::{Occupied, Vacant};
-
-        let xs = [(1i32, 10i32), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
-
-        let mut map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        let compute_hash = |map: &HashMap<i32, i32>, k: i32| -> u64 {
-            use core::hash::{BuildHasher, Hash, Hasher};
-
-            let mut hasher = map.hasher().build_hasher();
-            k.hash(&mut hasher);
-            hasher.finish()
-        };
-
-        // Existing key (insert)
-        match map.raw_entry_mut().from_key(&1) {
-            Vacant(_) => unreachable!(),
-            Occupied(mut view) => {
-                assert_eq!(view.get(), &10);
-                assert_eq!(view.insert(100), 10);
-            }
-        }
-        let hash1 = compute_hash(&map, 1);
-        assert_eq!(map.raw_entry().from_key(&1).unwrap(), (&1, &100));
-        assert_eq!(
-            map.raw_entry().from_hash(hash1, |k| *k == 1).unwrap(),
-            (&1, &100)
-        );
-        assert_eq!(
-            map.raw_entry().from_key_hashed_nocheck(hash1, &1).unwrap(),
-            (&1, &100)
-        );
-        assert_eq!(map.len(), 6);
-
-        // Existing key (update)
-        match map.raw_entry_mut().from_key(&2) {
-            Vacant(_) => unreachable!(),
-            Occupied(mut view) => {
-                let v = view.get_mut();
-                let new_v = (*v) * 10;
-                *v = new_v;
-            }
-        }
-        let hash2 = compute_hash(&map, 2);
-        assert_eq!(map.raw_entry().from_key(&2).unwrap(), (&2, &200));
-        assert_eq!(
-            map.raw_entry().from_hash(hash2, |k| *k == 2).unwrap(),
-            (&2, &200)
-        );
-        assert_eq!(
-            map.raw_entry().from_key_hashed_nocheck(hash2, &2).unwrap(),
-            (&2, &200)
-        );
-        assert_eq!(map.len(), 6);
-
-        // Existing key (take)
-        let hash3 = compute_hash(&map, 3);
-        match map.raw_entry_mut().from_key_hashed_nocheck(hash3, &3) {
-            Vacant(_) => unreachable!(),
-            Occupied(view) => {
-                assert_eq!(view.remove_entry(), (3, 30));
-            }
-        }
-        assert_eq!(map.raw_entry().from_key(&3), None);
-        assert_eq!(map.raw_entry().from_hash(hash3, |k| *k == 3), None);
-        assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash3, &3), None);
-        assert_eq!(map.len(), 5);
-
-        // Nonexistent key (insert)
-        match map.raw_entry_mut().from_key(&10) {
-            Occupied(_) => unreachable!(),
-            Vacant(view) => {
-                assert_eq!(view.insert(10, 1000), (&mut 10, &mut 1000));
-            }
-        }
-        assert_eq!(map.raw_entry().from_key(&10).unwrap(), (&10, &1000));
-        assert_eq!(map.len(), 6);
-
-        // Ensure all lookup methods produce equivalent results.
-        for k in 0..12 {
-            let hash = compute_hash(&map, k);
-            let v = map.get(&k).cloned();
-            let kv = v.as_ref().map(|v| (&k, v));
-
-            assert_eq!(map.raw_entry().from_key(&k), kv);
-            assert_eq!(map.raw_entry().from_hash(hash, |q| *q == k), kv);
-            assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash, &k), kv);
-
-            match map.raw_entry_mut().from_key(&k) {
-                Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv),
-                Vacant(_) => assert_eq!(v, None),
-            }
-            match map.raw_entry_mut().from_key_hashed_nocheck(hash, &k) {
-                Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv),
-                Vacant(_) => assert_eq!(v, None),
-            }
-            match map.raw_entry_mut().from_hash(hash, |q| *q == k) {
-                Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv),
-                Vacant(_) => assert_eq!(v, None),
-            }
-        }
-    }
-
-    #[test]
-    fn test_key_without_hash_impl() {
-        #[derive(Debug)]
-        struct IntWrapper(u64);
-
-        let mut m: HashMap<IntWrapper, (), ()> = HashMap::default();
-        {
-            assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_none());
-        }
-        {
-            let vacant_entry = match m.raw_entry_mut().from_hash(0, |k| k.0 == 0) {
-                RawEntryMut::Occupied(..) => panic!("Found entry for key 0"),
-                RawEntryMut::Vacant(e) => e,
-            };
-            vacant_entry.insert_with_hasher(0, IntWrapper(0), (), |k| k.0);
-        }
-        {
-            assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_some());
-            assert!(m.raw_entry().from_hash(1, |k| k.0 == 1).is_none());
-            assert!(m.raw_entry().from_hash(2, |k| k.0 == 2).is_none());
-        }
-        {
-            let vacant_entry = match m.raw_entry_mut().from_hash(1, |k| k.0 == 1) {
-                RawEntryMut::Occupied(..) => panic!("Found entry for key 1"),
-                RawEntryMut::Vacant(e) => e,
-            };
-            vacant_entry.insert_with_hasher(1, IntWrapper(1), (), |k| k.0);
-        }
-        {
-            assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_some());
-            assert!(m.raw_entry().from_hash(1, |k| k.0 == 1).is_some());
-            assert!(m.raw_entry().from_hash(2, |k| k.0 == 2).is_none());
-        }
-        {
-            let occupied_entry = match m.raw_entry_mut().from_hash(0, |k| k.0 == 0) {
-                RawEntryMut::Occupied(e) => e,
-                RawEntryMut::Vacant(..) => panic!("Couldn't find entry for key 0"),
-            };
-            occupied_entry.remove();
-        }
-        assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_none());
-        assert!(m.raw_entry().from_hash(1, |k| k.0 == 1).is_some());
-        assert!(m.raw_entry().from_hash(2, |k| k.0 == 2).is_none());
-    }
-
-    #[test]
-    #[cfg(feature = "raw")]
-    fn test_into_iter_refresh() {
-        use core::hash::{BuildHasher, Hash, Hasher};
-
-        #[cfg(miri)]
-        const N: usize = 32;
-        #[cfg(not(miri))]
-        const N: usize = 128;
-
-        let mut rng = rand::thread_rng();
-        for n in 0..N {
-            let mut m = HashMap::new();
-            for i in 0..n {
-                assert!(m.insert(i, 2 * i).is_none());
-            }
-            let hasher = m.hasher().clone();
-
-            let mut it = unsafe { m.table.iter() };
-            assert_eq!(it.len(), n);
-
-            let mut i = 0;
-            let mut left = n;
-            let mut removed = Vec::new();
-            loop {
-                // occasionally remove some elements
-                if i < n && rng.gen_bool(0.1) {
-                    let mut hsh = hasher.build_hasher();
-                    i.hash(&mut hsh);
-                    let hash = hsh.finish();
-
-                    unsafe {
-                        let e = m.table.find(hash, |q| q.0.eq(&i));
-                        if let Some(e) = e {
-                            it.reflect_remove(&e);
-                            let t = m.table.remove(e);
-                            removed.push(t);
-                            left -= 1;
-                        } else {
-                            assert!(removed.contains(&(i, 2 * i)), "{} not in {:?}", i, removed);
-                            let e = m
-                                .table
-                                .insert(hash, (i, 2 * i), |x| super::make_hash(&hasher, &x.0));
-                            it.reflect_insert(&e);
-                            if let Some(p) = removed.iter().position(|e| e == &(i, 2 * i)) {
-                                removed.swap_remove(p);
-                            }
-                            left += 1;
-                        }
-                    }
-                }
-
-                let e = it.next();
-                if e.is_none() {
-                    break;
-                }
-                assert!(i < n);
-                let t = unsafe { e.unwrap().as_ref() };
-                assert!(!removed.contains(t));
-                let (k, v) = t;
-                assert_eq!(*v, 2 * k);
-                i += 1;
-            }
-            assert!(i <= n);
-
-            // just for safety:
-            assert_eq!(m.table.len(), left);
-        }
-    }
-
-    #[test]
-    fn test_const_with_hasher() {
-        use core::hash::BuildHasher;
-        use std::borrow::ToOwned;
-        use std::collections::hash_map::DefaultHasher;
-
-        #[derive(Clone)]
-        struct MyHasher;
-        impl BuildHasher for MyHasher {
-            type Hasher = DefaultHasher;
-
-            fn build_hasher(&self) -> DefaultHasher {
-                DefaultHasher::new()
-            }
-        }
-
-        const EMPTY_MAP: HashMap<u32, std::string::String, MyHasher> =
-            HashMap::with_hasher(MyHasher);
-
-        let mut map = EMPTY_MAP.clone();
-        map.insert(17, "seventeen".to_owned());
-        assert_eq!("seventeen", map[&17]);
-    }
-}
diff --git a/vendor/hashbrown-0.9.1/src/raw/bitmask.rs b/vendor/hashbrown-0.9.1/src/raw/bitmask.rs
deleted file mode 100644 (file)
index 99b2d53..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-use super::imp::{BitMaskWord, BITMASK_MASK, BITMASK_STRIDE};
-#[cfg(feature = "nightly")]
-use core::intrinsics;
-
-/// A bit mask which contains the result of a `Match` operation on a `Group` and
-/// allows iterating through them.
-///
-/// The bit mask is arranged so that low-order bits represent lower memory
-/// addresses for group match results.
-///
-/// For implementation reasons, the bits in the set may be sparsely packed, so
-/// that there is only one bit-per-byte used (the high bit, 7). If this is the
-/// case, `BITMASK_STRIDE` will be 8 to indicate a divide-by-8 should be
-/// performed on counts/indices to normalize this difference. `BITMASK_MASK` is
-/// similarly a mask of all the actually-used bits.
-#[derive(Copy, Clone)]
-pub struct BitMask(pub BitMaskWord);
-
-#[allow(clippy::use_self)]
-impl BitMask {
-    /// Returns a new `BitMask` with all bits inverted.
-    #[inline]
-    #[must_use]
-    pub fn invert(self) -> Self {
-        BitMask(self.0 ^ BITMASK_MASK)
-    }
-
-    /// Flip the bit in the mask for the entry at the given index.
-    ///
-    /// Returns the bit's previous state.
-    #[inline]
-    #[allow(clippy::cast_ptr_alignment)]
-    #[cfg(feature = "raw")]
-    pub unsafe fn flip(&mut self, index: usize) -> bool {
-        // NOTE: The + BITMASK_STRIDE - 1 is to set the high bit.
-        let mask = 1 << (index * BITMASK_STRIDE + BITMASK_STRIDE - 1);
-        self.0 ^= mask;
-        // The bit was set if the bit is now 0.
-        self.0 & mask == 0
-    }
-
-    /// Returns a new `BitMask` with the lowest bit removed.
-    #[inline]
-    #[must_use]
-    pub fn remove_lowest_bit(self) -> Self {
-        BitMask(self.0 & (self.0 - 1))
-    }
-    /// Returns whether the `BitMask` has at least one set bit.
-    #[inline]
-    pub fn any_bit_set(self) -> bool {
-        self.0 != 0
-    }
-
-    /// Returns the first set bit in the `BitMask`, if there is one.
-    #[inline]
-    pub fn lowest_set_bit(self) -> Option<usize> {
-        if self.0 == 0 {
-            None
-        } else {
-            Some(unsafe { self.lowest_set_bit_nonzero() })
-        }
-    }
-
-    /// Returns the first set bit in the `BitMask`, if there is one. The
-    /// bitmask must not be empty.
-    #[inline]
-    #[cfg(feature = "nightly")]
-    pub unsafe fn lowest_set_bit_nonzero(self) -> usize {
-        intrinsics::cttz_nonzero(self.0) as usize / BITMASK_STRIDE
-    }
-    #[inline]
-    #[cfg(not(feature = "nightly"))]
-    pub unsafe fn lowest_set_bit_nonzero(self) -> usize {
-        self.trailing_zeros()
-    }
-
-    /// Returns the number of trailing zeroes in the `BitMask`.
-    #[inline]
-    pub fn trailing_zeros(self) -> usize {
-        // ARM doesn't have a trailing_zeroes instruction, and instead uses
-        // reverse_bits (RBIT) + leading_zeroes (CLZ). However older ARM
-        // versions (pre-ARMv7) don't have RBIT and need to emulate it
-        // instead. Since we only have 1 bit set in each byte on ARM, we can
-        // use swap_bytes (REV) + leading_zeroes instead.
-        if cfg!(target_arch = "arm") && BITMASK_STRIDE % 8 == 0 {
-            self.0.swap_bytes().leading_zeros() as usize / BITMASK_STRIDE
-        } else {
-            self.0.trailing_zeros() as usize / BITMASK_STRIDE
-        }
-    }
-
-    /// Returns the number of leading zeroes in the `BitMask`.
-    #[inline]
-    pub fn leading_zeros(self) -> usize {
-        self.0.leading_zeros() as usize / BITMASK_STRIDE
-    }
-}
-
-impl IntoIterator for BitMask {
-    type Item = usize;
-    type IntoIter = BitMaskIter;
-
-    #[inline]
-    fn into_iter(self) -> BitMaskIter {
-        BitMaskIter(self)
-    }
-}
-
-/// Iterator over the contents of a `BitMask`, returning the indicies of set
-/// bits.
-pub struct BitMaskIter(BitMask);
-
-impl Iterator for BitMaskIter {
-    type Item = usize;
-
-    #[inline]
-    fn next(&mut self) -> Option<usize> {
-        let bit = self.0.lowest_set_bit()?;
-        self.0 = self.0.remove_lowest_bit();
-        Some(bit)
-    }
-}
diff --git a/vendor/hashbrown-0.9.1/src/raw/generic.rs b/vendor/hashbrown-0.9.1/src/raw/generic.rs
deleted file mode 100644 (file)
index 26f8c58..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-use super::bitmask::BitMask;
-use super::EMPTY;
-use core::{mem, ptr};
-
-// Use the native word size as the group size. Using a 64-bit group size on
-// a 32-bit architecture will just end up being more expensive because
-// shifts and multiplies will need to be emulated.
-#[cfg(any(
-    target_pointer_width = "64",
-    target_arch = "aarch64",
-    target_arch = "x86_64",
-))]
-type GroupWord = u64;
-#[cfg(all(
-    target_pointer_width = "32",
-    not(target_arch = "aarch64"),
-    not(target_arch = "x86_64"),
-))]
-type GroupWord = u32;
-
-pub type BitMaskWord = GroupWord;
-pub const BITMASK_STRIDE: usize = 8;
-// We only care about the highest bit of each byte for the mask.
-#[allow(clippy::cast_possible_truncation, clippy::unnecessary_cast)]
-pub const BITMASK_MASK: BitMaskWord = 0x8080_8080_8080_8080_u64 as GroupWord;
-
-/// Helper function to replicate a byte across a `GroupWord`.
-#[inline]
-fn repeat(byte: u8) -> GroupWord {
-    GroupWord::from_ne_bytes([byte; Group::WIDTH])
-}
-
-/// Abstraction over a group of control bytes which can be scanned in
-/// parallel.
-///
-/// This implementation uses a word-sized integer.
-#[derive(Copy, Clone)]
-pub struct Group(GroupWord);
-
-// We perform all operations in the native endianess, and convert to
-// little-endian just before creating a BitMask. The can potentially
-// enable the compiler to eliminate unnecessary byte swaps if we are
-// only checking whether a BitMask is empty.
-#[allow(clippy::use_self)]
-impl Group {
-    /// Number of bytes in the group.
-    pub const WIDTH: usize = mem::size_of::<Self>();
-
-    /// Returns a full group of empty bytes, suitable for use as the initial
-    /// value for an empty hash table.
-    ///
-    /// This is guaranteed to be aligned to the group size.
-    pub const fn static_empty() -> &'static [u8; Group::WIDTH] {
-        #[repr(C)]
-        struct AlignedBytes {
-            _align: [Group; 0],
-            bytes: [u8; Group::WIDTH],
-        };
-        const ALIGNED_BYTES: AlignedBytes = AlignedBytes {
-            _align: [],
-            bytes: [EMPTY; Group::WIDTH],
-        };
-        &ALIGNED_BYTES.bytes
-    }
-
-    /// Loads a group of bytes starting at the given address.
-    #[inline]
-    #[allow(clippy::cast_ptr_alignment)] // unaligned load
-    pub unsafe fn load(ptr: *const u8) -> Self {
-        Group(ptr::read_unaligned(ptr as *const _))
-    }
-
-    /// Loads a group of bytes starting at the given address, which must be
-    /// aligned to `mem::align_of::<Group>()`.
-    #[inline]
-    #[allow(clippy::cast_ptr_alignment)]
-    pub unsafe fn load_aligned(ptr: *const u8) -> Self {
-        // FIXME: use align_offset once it stabilizes
-        debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
-        Group(ptr::read(ptr as *const _))
-    }
-
-    /// Stores the group of bytes to the given address, which must be
-    /// aligned to `mem::align_of::<Group>()`.
-    #[inline]
-    #[allow(clippy::cast_ptr_alignment)]
-    pub unsafe fn store_aligned(self, ptr: *mut u8) {
-        // FIXME: use align_offset once it stabilizes
-        debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
-        ptr::write(ptr as *mut _, self.0);
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which *may*
-    /// have the given value.
-    ///
-    /// This function may return a false positive in certain cases where
-    /// the byte in the group differs from the searched value only in its
-    /// lowest bit. This is fine because:
-    /// - This never happens for `EMPTY` and `DELETED`, only full entries.
-    /// - The check for key equality will catch these.
-    /// - This only happens if there is at least 1 true match.
-    /// - The chance of this happening is very low (< 1% chance per byte).
-    #[inline]
-    pub fn match_byte(self, byte: u8) -> BitMask {
-        // This algorithm is derived from
-        // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord
-        let cmp = self.0 ^ repeat(byte);
-        BitMask((cmp.wrapping_sub(repeat(0x01)) & !cmp & repeat(0x80)).to_le())
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which are
-    /// `EMPTY`.
-    #[inline]
-    pub fn match_empty(self) -> BitMask {
-        // If the high bit is set, then the byte must be either:
-        // 1111_1111 (EMPTY) or 1000_0000 (DELETED).
-        // So we can just check if the top two bits are 1 by ANDing them.
-        BitMask((self.0 & (self.0 << 1) & repeat(0x80)).to_le())
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which are
-    /// `EMPTY` or `DELETED`.
-    #[inline]
-    pub fn match_empty_or_deleted(self) -> BitMask {
-        // A byte is EMPTY or DELETED iff the high bit is set
-        BitMask((self.0 & repeat(0x80)).to_le())
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which are full.
-    #[inline]
-    pub fn match_full(self) -> BitMask {
-        self.match_empty_or_deleted().invert()
-    }
-
-    /// Performs the following transformation on all bytes in the group:
-    /// - `EMPTY => EMPTY`
-    /// - `DELETED => EMPTY`
-    /// - `FULL => DELETED`
-    #[inline]
-    pub fn convert_special_to_empty_and_full_to_deleted(self) -> Self {
-        // Map high_bit = 1 (EMPTY or DELETED) to 1111_1111
-        // and high_bit = 0 (FULL) to 1000_0000
-        //
-        // Here's this logic expanded to concrete values:
-        //   let full = 1000_0000 (true) or 0000_0000 (false)
-        //   !1000_0000 + 1 = 0111_1111 + 1 = 1000_0000 (no carry)
-        //   !0000_0000 + 0 = 1111_1111 + 0 = 1111_1111 (no carry)
-        let full = !self.0 & repeat(0x80);
-        Group(!full + (full >> 7))
-    }
-}
diff --git a/vendor/hashbrown-0.9.1/src/raw/mod.rs b/vendor/hashbrown-0.9.1/src/raw/mod.rs
deleted file mode 100644 (file)
index 32fec98..0000000
+++ /dev/null
@@ -1,1924 +0,0 @@
-use crate::alloc::alloc::{alloc, dealloc, handle_alloc_error};
-use crate::scopeguard::guard;
-use crate::TryReserveError;
-use core::alloc::Layout;
-use core::hint;
-use core::iter::FusedIterator;
-use core::marker::PhantomData;
-use core::mem;
-use core::mem::ManuallyDrop;
-use core::ptr::NonNull;
-
-cfg_if! {
-    // Use the SSE2 implementation if possible: it allows us to scan 16 buckets
-    // at once instead of 8. We don't bother with AVX since it would require
-    // runtime dispatch and wouldn't gain us much anyways: the probability of
-    // finding a match drops off drastically after the first few buckets.
-    //
-    // I attempted an implementation on ARM using NEON instructions, but it
-    // turns out that most NEON instructions have multi-cycle latency, which in
-    // the end outweighs any gains over the generic implementation.
-    if #[cfg(all(
-        target_feature = "sse2",
-        any(target_arch = "x86", target_arch = "x86_64"),
-        not(miri)
-    ))] {
-        mod sse2;
-        use sse2 as imp;
-    } else {
-        #[path = "generic.rs"]
-        mod generic;
-        use generic as imp;
-    }
-}
-
-mod bitmask;
-
-use self::bitmask::{BitMask, BitMaskIter};
-use self::imp::Group;
-
-// Branch prediction hint. This is currently only available on nightly but it
-// consistently improves performance by 10-15%.
-#[cfg(feature = "nightly")]
-use core::intrinsics::{likely, unlikely};
-#[cfg(not(feature = "nightly"))]
-#[inline]
-fn likely(b: bool) -> bool {
-    b
-}
-#[cfg(not(feature = "nightly"))]
-#[inline]
-fn unlikely(b: bool) -> bool {
-    b
-}
-
-#[cfg(feature = "nightly")]
-#[cfg_attr(feature = "inline-more", inline)]
-unsafe fn offset_from<T>(to: *const T, from: *const T) -> usize {
-    to.offset_from(from) as usize
-}
-#[cfg(not(feature = "nightly"))]
-#[cfg_attr(feature = "inline-more", inline)]
-unsafe fn offset_from<T>(to: *const T, from: *const T) -> usize {
-    (to as usize - from as usize) / mem::size_of::<T>()
-}
-
-/// Whether memory allocation errors should return an error or abort.
-#[derive(Copy, Clone)]
-enum Fallibility {
-    Fallible,
-    Infallible,
-}
-
-impl Fallibility {
-    /// Error to return on capacity overflow.
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn capacity_overflow(self) -> TryReserveError {
-        match self {
-            Fallibility::Fallible => TryReserveError::CapacityOverflow,
-            Fallibility::Infallible => panic!("Hash table capacity overflow"),
-        }
-    }
-
-    /// Error to return on allocation error.
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn alloc_err(self, layout: Layout) -> TryReserveError {
-        match self {
-            Fallibility::Fallible => TryReserveError::AllocError { layout },
-            Fallibility::Infallible => handle_alloc_error(layout),
-        }
-    }
-}
-
-/// Control byte value for an empty bucket.
-const EMPTY: u8 = 0b1111_1111;
-
-/// Control byte value for a deleted bucket.
-const DELETED: u8 = 0b1000_0000;
-
-/// Checks whether a control byte represents a full bucket (top bit is clear).
-#[inline]
-fn is_full(ctrl: u8) -> bool {
-    ctrl & 0x80 == 0
-}
-
-/// Checks whether a control byte represents a special value (top bit is set).
-#[inline]
-fn is_special(ctrl: u8) -> bool {
-    ctrl & 0x80 != 0
-}
-
-/// Checks whether a special control value is EMPTY (just check 1 bit).
-#[inline]
-fn special_is_empty(ctrl: u8) -> bool {
-    debug_assert!(is_special(ctrl));
-    ctrl & 0x01 != 0
-}
-
-/// Primary hash function, used to select the initial bucket to probe from.
-#[inline]
-#[allow(clippy::cast_possible_truncation)]
-fn h1(hash: u64) -> usize {
-    // On 32-bit platforms we simply ignore the higher hash bits.
-    hash as usize
-}
-
-/// Secondary hash function, saved in the low 7 bits of the control byte.
-#[inline]
-#[allow(clippy::cast_possible_truncation)]
-fn h2(hash: u64) -> u8 {
-    // Grab the top 7 bits of the hash. While the hash is normally a full 64-bit
-    // value, some hash functions (such as FxHash) produce a usize result
-    // instead, which means that the top 32 bits are 0 on 32-bit platforms.
-    let hash_len = usize::min(mem::size_of::<usize>(), mem::size_of::<u64>());
-    let top7 = hash >> (hash_len * 8 - 7);
-    (top7 & 0x7f) as u8 // truncation
-}
-
-/// Probe sequence based on triangular numbers, which is guaranteed (since our
-/// table size is a power of two) to visit every group of elements exactly once.
-///
-/// A triangular probe has us jump by 1 more group every time. So first we
-/// jump by 1 group (meaning we just continue our linear scan), then 2 groups
-/// (skipping over 1 group), then 3 groups (skipping over 2 groups), and so on.
-///
-/// Proof that the probe will visit every group in the table:
-/// <https://fgiesen.wordpress.com/2015/02/22/triangular-numbers-mod-2n/>
-struct ProbeSeq {
-    bucket_mask: usize,
-    pos: usize,
-    stride: usize,
-}
-
-impl Iterator for ProbeSeq {
-    type Item = usize;
-
-    #[inline]
-    fn next(&mut self) -> Option<usize> {
-        // We should have found an empty bucket by now and ended the probe.
-        debug_assert!(
-            self.stride <= self.bucket_mask,
-            "Went past end of probe sequence"
-        );
-
-        let result = self.pos;
-        self.stride += Group::WIDTH;
-        self.pos += self.stride;
-        self.pos &= self.bucket_mask;
-        Some(result)
-    }
-}
-
-/// Returns the number of buckets needed to hold the given number of items,
-/// taking the maximum load factor into account.
-///
-/// Returns `None` if an overflow occurs.
-// Workaround for emscripten bug emscripten-core/emscripten-fastcomp#258
-#[cfg_attr(target_os = "emscripten", inline(never))]
-#[cfg_attr(not(target_os = "emscripten"), inline)]
-fn capacity_to_buckets(cap: usize) -> Option<usize> {
-    debug_assert_ne!(cap, 0);
-
-    // For small tables we require at least 1 empty bucket so that lookups are
-    // guaranteed to terminate if an element doesn't exist in the table.
-    if cap < 8 {
-        // We don't bother with a table size of 2 buckets since that can only
-        // hold a single element. Instead we skip directly to a 4 bucket table
-        // which can hold 3 elements.
-        return Some(if cap < 4 { 4 } else { 8 });
-    }
-
-    // Otherwise require 1/8 buckets to be empty (87.5% load)
-    //
-    // Be careful when modifying this, calculate_layout relies on the
-    // overflow check here.
-    let adjusted_cap = cap.checked_mul(8)? / 7;
-
-    // Any overflows will have been caught by the checked_mul. Also, any
-    // rounding errors from the division above will be cleaned up by
-    // next_power_of_two (which can't overflow because of the previous divison).
-    Some(adjusted_cap.next_power_of_two())
-}
-
-/// Returns the maximum effective capacity for the given bucket mask, taking
-/// the maximum load factor into account.
-#[inline]
-fn bucket_mask_to_capacity(bucket_mask: usize) -> usize {
-    if bucket_mask < 8 {
-        // For tables with 1/2/4/8 buckets, we always reserve one empty slot.
-        // Keep in mind that the bucket mask is one less than the bucket count.
-        bucket_mask
-    } else {
-        // For larger tables we reserve 12.5% of the slots as empty.
-        ((bucket_mask + 1) / 8) * 7
-    }
-}
-
-/// Returns a Layout which describes the allocation required for a hash table,
-/// and the offset of the control bytes in the allocation.
-/// (the offset is also one past last element of buckets)
-///
-/// Returns `None` if an overflow occurs.
-#[cfg_attr(feature = "inline-more", inline)]
-#[cfg(feature = "nightly")]
-fn calculate_layout<T>(buckets: usize) -> Option<(Layout, usize)> {
-    debug_assert!(buckets.is_power_of_two());
-
-    // Array of buckets
-    let data = Layout::array::<T>(buckets).ok()?;
-
-    // Array of control bytes. This must be aligned to the group size.
-    //
-    // We add `Group::WIDTH` control bytes at the end of the array which
-    // replicate the bytes at the start of the array and thus avoids the need to
-    // perform bounds-checking while probing.
-    //
-    // There is no possible overflow here since buckets is a power of two and
-    // Group::WIDTH is a small number.
-    let ctrl = unsafe { Layout::from_size_align_unchecked(buckets + Group::WIDTH, Group::WIDTH) };
-
-    data.extend(ctrl).ok()
-}
-
-/// Returns a Layout which describes the allocation required for a hash table,
-/// and the offset of the control bytes in the allocation.
-/// (the offset is also one past last element of buckets)
-///
-/// Returns `None` if an overflow occurs.
-#[cfg_attr(feature = "inline-more", inline)]
-#[cfg(not(feature = "nightly"))]
-fn calculate_layout<T>(buckets: usize) -> Option<(Layout, usize)> {
-    debug_assert!(buckets.is_power_of_two());
-
-    // Manual layout calculation since Layout methods are not yet stable.
-    let ctrl_align = usize::max(mem::align_of::<T>(), Group::WIDTH);
-    let ctrl_offset = mem::size_of::<T>()
-        .checked_mul(buckets)?
-        .checked_add(ctrl_align - 1)?
-        & !(ctrl_align - 1);
-    let len = ctrl_offset.checked_add(buckets + Group::WIDTH)?;
-
-    Some((
-        unsafe { Layout::from_size_align_unchecked(len, ctrl_align) },
-        ctrl_offset,
-    ))
-}
-
-/// A reference to a hash table bucket containing a `T`.
-///
-/// This is usually just a pointer to the element itself. However if the element
-/// is a ZST, then we instead track the index of the element in the table so
-/// that `erase` works properly.
-pub struct Bucket<T> {
-    // Actually it is pointer to next element than element itself
-    // this is needed to maintain pointer arithmetic invariants
-    // keeping direct pointer to element introduces difficulty.
-    // Using `NonNull` for variance and niche layout
-    ptr: NonNull<T>,
-}
-
-// This Send impl is needed for rayon support. This is safe since Bucket is
-// never exposed in a public API.
-unsafe impl<T> Send for Bucket<T> {}
-
-impl<T> Clone for Bucket<T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn clone(&self) -> Self {
-        Self { ptr: self.ptr }
-    }
-}
-
-impl<T> Bucket<T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    unsafe fn from_base_index(base: NonNull<T>, index: usize) -> Self {
-        let ptr = if mem::size_of::<T>() == 0 {
-            // won't overflow because index must be less than length
-            (index + 1) as *mut T
-        } else {
-            base.as_ptr().sub(index)
-        };
-        Self {
-            ptr: NonNull::new_unchecked(ptr),
-        }
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    unsafe fn to_base_index(&self, base: NonNull<T>) -> usize {
-        if mem::size_of::<T>() == 0 {
-            self.ptr.as_ptr() as usize - 1
-        } else {
-            offset_from(base.as_ptr(), self.ptr.as_ptr())
-        }
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn as_ptr(&self) -> *mut T {
-        if mem::size_of::<T>() == 0 {
-            // Just return an arbitrary ZST pointer which is properly aligned
-            mem::align_of::<T>() as *mut T
-        } else {
-            self.ptr.as_ptr().sub(1)
-        }
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    unsafe fn next_n(&self, offset: usize) -> Self {
-        let ptr = if mem::size_of::<T>() == 0 {
-            (self.ptr.as_ptr() as usize + offset) as *mut T
-        } else {
-            self.ptr.as_ptr().sub(offset)
-        };
-        Self {
-            ptr: NonNull::new_unchecked(ptr),
-        }
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn drop(&self) {
-        self.as_ptr().drop_in_place();
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn read(&self) -> T {
-        self.as_ptr().read()
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn write(&self, val: T) {
-        self.as_ptr().write(val);
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn as_ref<'a>(&self) -> &'a T {
-        &*self.as_ptr()
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn as_mut<'a>(&self) -> &'a mut T {
-        &mut *self.as_ptr()
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn copy_from_nonoverlapping(&self, other: &Self) {
-        self.as_ptr().copy_from_nonoverlapping(other.as_ptr(), 1);
-    }
-}
-
-/// A raw hash table with an unsafe API.
-pub struct RawTable<T> {
-    // Mask to get an index from a hash value. The value is one less than the
-    // number of buckets in the table.
-    bucket_mask: usize,
-
-    // [Padding], T1, T2, ..., Tlast, C1, C2, ...
-    //                                ^ points here
-    ctrl: NonNull<u8>,
-
-    // Number of elements that can be inserted before we need to grow the table
-    growth_left: usize,
-
-    // Number of elements in the table, only really used by len()
-    items: usize,
-
-    // Tell dropck that we own instances of T.
-    marker: PhantomData<T>,
-}
-
-impl<T> RawTable<T> {
-    /// Creates a new empty hash table without allocating any memory.
-    ///
-    /// In effect this returns a table with exactly 1 bucket. However we can
-    /// leave the data pointer dangling since that bucket is never written to
-    /// due to our load factor forcing us to always have at least 1 free bucket.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub const fn new() -> Self {
-        Self {
-            // Be careful to cast the entire slice to a raw pointer.
-            ctrl: unsafe { NonNull::new_unchecked(Group::static_empty() as *const _ as *mut u8) },
-            bucket_mask: 0,
-            items: 0,
-            growth_left: 0,
-            marker: PhantomData,
-        }
-    }
-
-    /// Allocates a new hash table with the given number of buckets.
-    ///
-    /// The control bytes are left uninitialized.
-    #[cfg_attr(feature = "inline-more", inline)]
-    unsafe fn new_uninitialized(
-        buckets: usize,
-        fallability: Fallibility,
-    ) -> Result<Self, TryReserveError> {
-        debug_assert!(buckets.is_power_of_two());
-
-        // Avoid `Option::ok_or_else` because it bloats LLVM IR.
-        let (layout, ctrl_offset) = match calculate_layout::<T>(buckets) {
-            Some(lco) => lco,
-            None => return Err(fallability.capacity_overflow()),
-        };
-        let ptr = match NonNull::new(alloc(layout)) {
-            Some(ptr) => ptr,
-            None => return Err(fallability.alloc_err(layout)),
-        };
-        let ctrl = NonNull::new_unchecked(ptr.as_ptr().add(ctrl_offset));
-        Ok(Self {
-            ctrl,
-            bucket_mask: buckets - 1,
-            items: 0,
-            growth_left: bucket_mask_to_capacity(buckets - 1),
-            marker: PhantomData,
-        })
-    }
-
-    /// Attempts to allocate a new hash table with at least enough capacity
-    /// for inserting the given number of elements without reallocating.
-    fn fallible_with_capacity(
-        capacity: usize,
-        fallability: Fallibility,
-    ) -> Result<Self, TryReserveError> {
-        if capacity == 0 {
-            Ok(Self::new())
-        } else {
-            unsafe {
-                // Avoid `Option::ok_or_else` because it bloats LLVM IR.
-                let buckets = match capacity_to_buckets(capacity) {
-                    Some(buckets) => buckets,
-                    None => return Err(fallability.capacity_overflow()),
-                };
-                let result = Self::new_uninitialized(buckets, fallability)?;
-                result.ctrl(0).write_bytes(EMPTY, result.num_ctrl_bytes());
-
-                Ok(result)
-            }
-        }
-    }
-
-    /// Attempts to allocate a new hash table with at least enough capacity
-    /// for inserting the given number of elements without reallocating.
-    #[cfg(feature = "raw")]
-    pub fn try_with_capacity(capacity: usize) -> Result<Self, TryReserveError> {
-        Self::fallible_with_capacity(capacity, Fallibility::Fallible)
-    }
-
-    /// Allocates a new hash table with at least enough capacity for inserting
-    /// the given number of elements without reallocating.
-    pub fn with_capacity(capacity: usize) -> Self {
-        // Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
-        match Self::fallible_with_capacity(capacity, Fallibility::Infallible) {
-            Ok(capacity) => capacity,
-            Err(_) => unsafe { hint::unreachable_unchecked() },
-        }
-    }
-
-    /// Deallocates the table without dropping any entries.
-    #[cfg_attr(feature = "inline-more", inline)]
-    unsafe fn free_buckets(&mut self) {
-        // Avoid `Option::unwrap_or_else` because it bloats LLVM IR.
-        let (layout, ctrl_offset) = match calculate_layout::<T>(self.buckets()) {
-            Some(lco) => lco,
-            None => hint::unreachable_unchecked(),
-        };
-        dealloc(self.ctrl.as_ptr().sub(ctrl_offset), layout);
-    }
-
-    /// Returns pointer to one past last element of data table.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn data_end(&self) -> NonNull<T> {
-        NonNull::new_unchecked(self.ctrl.as_ptr() as *mut T)
-    }
-
-    /// Returns pointer to start of data table.
-    #[cfg_attr(feature = "inline-more", inline)]
-    #[cfg(feature = "nightly")]
-    pub unsafe fn data_start(&self) -> *mut T {
-        self.data_end().as_ptr().wrapping_sub(self.buckets())
-    }
-
-    /// Returns the index of a bucket from a `Bucket`.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn bucket_index(&self, bucket: &Bucket<T>) -> usize {
-        bucket.to_base_index(self.data_end())
-    }
-
-    /// Returns a pointer to a control byte.
-    #[cfg_attr(feature = "inline-more", inline)]
-    unsafe fn ctrl(&self, index: usize) -> *mut u8 {
-        debug_assert!(index < self.num_ctrl_bytes());
-        self.ctrl.as_ptr().add(index)
-    }
-
-    /// Returns a pointer to an element in the table.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn bucket(&self, index: usize) -> Bucket<T> {
-        debug_assert_ne!(self.bucket_mask, 0);
-        debug_assert!(index < self.buckets());
-        Bucket::from_base_index(self.data_end(), index)
-    }
-
-    /// Erases an element from the table without dropping it.
-    #[cfg_attr(feature = "inline-more", inline)]
-    #[deprecated(since = "0.8.1", note = "use erase or remove instead")]
-    pub unsafe fn erase_no_drop(&mut self, item: &Bucket<T>) {
-        let index = self.bucket_index(item);
-        debug_assert!(is_full(*self.ctrl(index)));
-        let index_before = index.wrapping_sub(Group::WIDTH) & self.bucket_mask;
-        let empty_before = Group::load(self.ctrl(index_before)).match_empty();
-        let empty_after = Group::load(self.ctrl(index)).match_empty();
-
-        // If we are inside a continuous block of Group::WIDTH full or deleted
-        // cells then a probe window may have seen a full block when trying to
-        // insert. We therefore need to keep that block non-empty so that
-        // lookups will continue searching to the next probe window.
-        //
-        // Note that in this context `leading_zeros` refers to the bytes at the
-        // end of a group, while `trailing_zeros` refers to the bytes at the
-        // begining of a group.
-        let ctrl = if empty_before.leading_zeros() + empty_after.trailing_zeros() >= Group::WIDTH {
-            DELETED
-        } else {
-            self.growth_left += 1;
-            EMPTY
-        };
-        self.set_ctrl(index, ctrl);
-        self.items -= 1;
-    }
-
-    /// Erases an element from the table, dropping it in place.
-    #[cfg_attr(feature = "inline-more", inline)]
-    #[allow(clippy::needless_pass_by_value)]
-    #[allow(deprecated)]
-    pub unsafe fn erase(&mut self, item: Bucket<T>) {
-        // Erase the element from the table first since drop might panic.
-        self.erase_no_drop(&item);
-        item.drop();
-    }
-
-    /// Finds and erases an element from the table, dropping it in place.
-    /// Returns true if an element was found.
-    #[cfg(feature = "raw")]
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn erase_entry(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> bool {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        if let Some(bucket) = self.find(hash, eq) {
-            unsafe { self.erase(bucket) };
-            true
-        } else {
-            false
-        }
-    }
-
-    /// Removes an element from the table, returning it.
-    #[cfg_attr(feature = "inline-more", inline)]
-    #[allow(clippy::needless_pass_by_value)]
-    #[allow(deprecated)]
-    pub unsafe fn remove(&mut self, item: Bucket<T>) -> T {
-        self.erase_no_drop(&item);
-        item.read()
-    }
-
-    /// Finds and removes an element from the table, returning it.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn remove_entry(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<T> {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.find(hash, eq) {
-            Some(bucket) => Some(unsafe { self.remove(bucket) }),
-            None => None,
-        }
-    }
-
-    /// Returns an iterator for a probe sequence on the table.
-    ///
-    /// This iterator never terminates, but is guaranteed to visit each bucket
-    /// group exactly once. The loop using `probe_seq` must terminate upon
-    /// reaching a group containing an empty bucket.
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn probe_seq(&self, hash: u64) -> ProbeSeq {
-        ProbeSeq {
-            bucket_mask: self.bucket_mask,
-            pos: h1(hash) & self.bucket_mask,
-            stride: 0,
-        }
-    }
-
-    /// Sets a control byte, and possibly also the replicated control byte at
-    /// the end of the array.
-    #[cfg_attr(feature = "inline-more", inline)]
-    unsafe fn set_ctrl(&self, index: usize, ctrl: u8) {
-        // Replicate the first Group::WIDTH control bytes at the end of
-        // the array without using a branch:
-        // - If index >= Group::WIDTH then index == index2.
-        // - Otherwise index2 == self.bucket_mask + 1 + index.
-        //
-        // The very last replicated control byte is never actually read because
-        // we mask the initial index for unaligned loads, but we write it
-        // anyways because it makes the set_ctrl implementation simpler.
-        //
-        // If there are fewer buckets than Group::WIDTH then this code will
-        // replicate the buckets at the end of the trailing group. For example
-        // with 2 buckets and a group size of 4, the control bytes will look
-        // like this:
-        //
-        //     Real    |             Replicated
-        // ---------------------------------------------
-        // | [A] | [B] | [EMPTY] | [EMPTY] | [A] | [B] |
-        // ---------------------------------------------
-        let index2 = ((index.wrapping_sub(Group::WIDTH)) & self.bucket_mask) + Group::WIDTH;
-
-        *self.ctrl(index) = ctrl;
-        *self.ctrl(index2) = ctrl;
-    }
-
-    /// Searches for an empty or deleted bucket which is suitable for inserting
-    /// a new element.
-    ///
-    /// There must be at least 1 empty bucket in the table.
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn find_insert_slot(&self, hash: u64) -> usize {
-        for pos in self.probe_seq(hash) {
-            unsafe {
-                let group = Group::load(self.ctrl(pos));
-                if let Some(bit) = group.match_empty_or_deleted().lowest_set_bit() {
-                    let result = (pos + bit) & self.bucket_mask;
-
-                    // In tables smaller than the group width, trailing control
-                    // bytes outside the range of the table are filled with
-                    // EMPTY entries. These will unfortunately trigger a
-                    // match, but once masked may point to a full bucket that
-                    // is already occupied. We detect this situation here and
-                    // perform a second scan starting at the begining of the
-                    // table. This second scan is guaranteed to find an empty
-                    // slot (due to the load factor) before hitting the trailing
-                    // control bytes (containing EMPTY).
-                    if unlikely(is_full(*self.ctrl(result))) {
-                        debug_assert!(self.bucket_mask < Group::WIDTH);
-                        debug_assert_ne!(pos, 0);
-                        return Group::load_aligned(self.ctrl(0))
-                            .match_empty_or_deleted()
-                            .lowest_set_bit_nonzero();
-                    } else {
-                        return result;
-                    }
-                }
-            }
-        }
-
-        // probe_seq never returns.
-        unreachable!();
-    }
-
-    /// Marks all table buckets as empty without dropping their contents.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn clear_no_drop(&mut self) {
-        if !self.is_empty_singleton() {
-            unsafe {
-                self.ctrl(0).write_bytes(EMPTY, self.num_ctrl_bytes());
-            }
-        }
-        self.items = 0;
-        self.growth_left = bucket_mask_to_capacity(self.bucket_mask);
-    }
-
-    /// Removes all elements from the table without freeing the backing memory.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn clear(&mut self) {
-        // Ensure that the table is reset even if one of the drops panic
-        let self_ = guard(self, |self_| self_.clear_no_drop());
-
-        if mem::needs_drop::<T>() && self_.len() != 0 {
-            unsafe {
-                for item in self_.iter() {
-                    item.drop();
-                }
-            }
-        }
-    }
-
-    /// Shrinks the table to fit `max(self.len(), min_size)` elements.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn shrink_to(&mut self, min_size: usize, hasher: impl Fn(&T) -> u64) {
-        // Calculate the minimal number of elements that we need to reserve
-        // space for.
-        let min_size = usize::max(self.items, min_size);
-        if min_size == 0 {
-            *self = Self::new();
-            return;
-        }
-
-        // Calculate the number of buckets that we need for this number of
-        // elements. If the calculation overflows then the requested bucket
-        // count must be larger than what we have right and nothing needs to be
-        // done.
-        let min_buckets = match capacity_to_buckets(min_size) {
-            Some(buckets) => buckets,
-            None => return,
-        };
-
-        // If we have more buckets than we need, shrink the table.
-        if min_buckets < self.buckets() {
-            // Fast path if the table is empty
-            if self.items == 0 {
-                *self = Self::with_capacity(min_size)
-            } else {
-                // Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
-                if self
-                    .resize(min_size, hasher, Fallibility::Infallible)
-                    .is_err()
-                {
-                    unsafe { hint::unreachable_unchecked() }
-                }
-            }
-        }
-    }
-
-    /// Ensures that at least `additional` items can be inserted into the table
-    /// without reallocation.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn reserve(&mut self, additional: usize, hasher: impl Fn(&T) -> u64) {
-        if additional > self.growth_left {
-            // Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
-            if self
-                .reserve_rehash(additional, hasher, Fallibility::Infallible)
-                .is_err()
-            {
-                unsafe { hint::unreachable_unchecked() }
-            }
-        }
-    }
-
-    /// Tries to ensure that at least `additional` items can be inserted into
-    /// the table without reallocation.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn try_reserve(
-        &mut self,
-        additional: usize,
-        hasher: impl Fn(&T) -> u64,
-    ) -> Result<(), TryReserveError> {
-        if additional > self.growth_left {
-            self.reserve_rehash(additional, hasher, Fallibility::Fallible)
-        } else {
-            Ok(())
-        }
-    }
-
-    /// Out-of-line slow path for `reserve` and `try_reserve`.
-    #[cold]
-    #[inline(never)]
-    fn reserve_rehash(
-        &mut self,
-        additional: usize,
-        hasher: impl Fn(&T) -> u64,
-        fallability: Fallibility,
-    ) -> Result<(), TryReserveError> {
-        // Avoid `Option::ok_or_else` because it bloats LLVM IR.
-        let new_items = match self.items.checked_add(additional) {
-            Some(new_items) => new_items,
-            None => return Err(fallability.capacity_overflow()),
-        };
-        let full_capacity = bucket_mask_to_capacity(self.bucket_mask);
-        if new_items <= full_capacity / 2 {
-            // Rehash in-place without re-allocating if we have plenty of spare
-            // capacity that is locked up due to DELETED entries.
-            self.rehash_in_place(hasher);
-            Ok(())
-        } else {
-            // Otherwise, conservatively resize to at least the next size up
-            // to avoid churning deletes into frequent rehashes.
-            self.resize(
-                usize::max(new_items, full_capacity + 1),
-                hasher,
-                fallability,
-            )
-        }
-    }
-
-    /// Rehashes the contents of the table in place (i.e. without changing the
-    /// allocation).
-    ///
-    /// If `hasher` panics then some the table's contents may be lost.
-    fn rehash_in_place(&mut self, hasher: impl Fn(&T) -> u64) {
-        unsafe {
-            // Bulk convert all full control bytes to DELETED, and all DELETED
-            // control bytes to EMPTY. This effectively frees up all buckets
-            // containing a DELETED entry.
-            for i in (0..self.buckets()).step_by(Group::WIDTH) {
-                let group = Group::load_aligned(self.ctrl(i));
-                let group = group.convert_special_to_empty_and_full_to_deleted();
-                group.store_aligned(self.ctrl(i));
-            }
-
-            // Fix up the trailing control bytes. See the comments in set_ctrl
-            // for the handling of tables smaller than the group width.
-            if self.buckets() < Group::WIDTH {
-                self.ctrl(0)
-                    .copy_to(self.ctrl(Group::WIDTH), self.buckets());
-            } else {
-                self.ctrl(0)
-                    .copy_to(self.ctrl(self.buckets()), Group::WIDTH);
-            }
-
-            // If the hash function panics then properly clean up any elements
-            // that we haven't rehashed yet. We unfortunately can't preserve the
-            // element since we lost their hash and have no way of recovering it
-            // without risking another panic.
-            let mut guard = guard(self, |self_| {
-                if mem::needs_drop::<T>() {
-                    for i in 0..self_.buckets() {
-                        if *self_.ctrl(i) == DELETED {
-                            self_.set_ctrl(i, EMPTY);
-                            self_.bucket(i).drop();
-                            self_.items -= 1;
-                        }
-                    }
-                }
-                self_.growth_left = bucket_mask_to_capacity(self_.bucket_mask) - self_.items;
-            });
-
-            // At this point, DELETED elements are elements that we haven't
-            // rehashed yet. Find them and re-insert them at their ideal
-            // position.
-            'outer: for i in 0..guard.buckets() {
-                if *guard.ctrl(i) != DELETED {
-                    continue;
-                }
-                'inner: loop {
-                    // Hash the current item
-                    let item = guard.bucket(i);
-                    let hash = hasher(item.as_ref());
-
-                    // Search for a suitable place to put it
-                    let new_i = guard.find_insert_slot(hash);
-
-                    // Probing works by scanning through all of the control
-                    // bytes in groups, which may not be aligned to the group
-                    // size. If both the new and old position fall within the
-                    // same unaligned group, then there is no benefit in moving
-                    // it and we can just continue to the next item.
-                    let probe_index = |pos: usize| {
-                        (pos.wrapping_sub(guard.probe_seq(hash).pos) & guard.bucket_mask)
-                            / Group::WIDTH
-                    };
-                    if likely(probe_index(i) == probe_index(new_i)) {
-                        guard.set_ctrl(i, h2(hash));
-                        continue 'outer;
-                    }
-
-                    // We are moving the current item to a new position. Write
-                    // our H2 to the control byte of the new position.
-                    let prev_ctrl = *guard.ctrl(new_i);
-                    guard.set_ctrl(new_i, h2(hash));
-
-                    if prev_ctrl == EMPTY {
-                        // If the target slot is empty, simply move the current
-                        // element into the new slot and clear the old control
-                        // byte.
-                        guard.set_ctrl(i, EMPTY);
-                        guard.bucket(new_i).copy_from_nonoverlapping(&item);
-                        continue 'outer;
-                    } else {
-                        // If the target slot is occupied, swap the two elements
-                        // and then continue processing the element that we just
-                        // swapped into the old slot.
-                        debug_assert_eq!(prev_ctrl, DELETED);
-                        mem::swap(guard.bucket(new_i).as_mut(), item.as_mut());
-                        continue 'inner;
-                    }
-                }
-            }
-
-            guard.growth_left = bucket_mask_to_capacity(guard.bucket_mask) - guard.items;
-            mem::forget(guard);
-        }
-    }
-
-    /// Allocates a new table of a different size and moves the contents of the
-    /// current table into it.
-    fn resize(
-        &mut self,
-        capacity: usize,
-        hasher: impl Fn(&T) -> u64,
-        fallability: Fallibility,
-    ) -> Result<(), TryReserveError> {
-        unsafe {
-            debug_assert!(self.items <= capacity);
-
-            // Allocate and initialize the new table.
-            let mut new_table = Self::fallible_with_capacity(capacity, fallability)?;
-            new_table.growth_left -= self.items;
-            new_table.items = self.items;
-
-            // The hash function may panic, in which case we simply free the new
-            // table without dropping any elements that may have been copied into
-            // it.
-            //
-            // This guard is also used to free the old table on success, see
-            // the comment at the bottom of this function.
-            let mut new_table = guard(ManuallyDrop::new(new_table), |new_table| {
-                if !new_table.is_empty_singleton() {
-                    new_table.free_buckets();
-                }
-            });
-
-            // Copy all elements to the new table.
-            for item in self.iter() {
-                // This may panic.
-                let hash = hasher(item.as_ref());
-
-                // We can use a simpler version of insert() here since:
-                // - there are no DELETED entries.
-                // - we know there is enough space in the table.
-                // - all elements are unique.
-                let index = new_table.find_insert_slot(hash);
-                new_table.set_ctrl(index, h2(hash));
-                new_table.bucket(index).copy_from_nonoverlapping(&item);
-            }
-
-            // We successfully copied all elements without panicking. Now replace
-            // self with the new table. The old table will have its memory freed but
-            // the items will not be dropped (since they have been moved into the
-            // new table).
-            mem::swap(self, &mut new_table);
-
-            Ok(())
-        }
-    }
-
-    /// Inserts a new element into the table, and returns its raw bucket.
-    ///
-    /// This does not check if the given element already exists in the table.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> Bucket<T> {
-        unsafe {
-            let mut index = self.find_insert_slot(hash);
-
-            // We can avoid growing the table once we have reached our load
-            // factor if we are replacing a tombstone. This works since the
-            // number of EMPTY slots does not change in this case.
-            let old_ctrl = *self.ctrl(index);
-            if unlikely(self.growth_left == 0 && special_is_empty(old_ctrl)) {
-                self.reserve(1, hasher);
-                index = self.find_insert_slot(hash);
-            }
-
-            let bucket = self.bucket(index);
-            self.growth_left -= special_is_empty(old_ctrl) as usize;
-            self.set_ctrl(index, h2(hash));
-            bucket.write(value);
-            self.items += 1;
-            bucket
-        }
-    }
-
-    /// Inserts a new element into the table, and returns a mutable reference to it.
-    ///
-    /// This does not check if the given element already exists in the table.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert_entry(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> &mut T {
-        unsafe { self.insert(hash, value, hasher).as_mut() }
-    }
-
-    /// Inserts a new element into the table, without growing the table.
-    ///
-    /// There must be enough space in the table to insert the new element.
-    ///
-    /// This does not check if the given element already exists in the table.
-    #[cfg_attr(feature = "inline-more", inline)]
-    #[cfg(any(feature = "raw", feature = "rustc-internal-api"))]
-    pub fn insert_no_grow(&mut self, hash: u64, value: T) -> Bucket<T> {
-        unsafe {
-            let index = self.find_insert_slot(hash);
-            let bucket = self.bucket(index);
-
-            // If we are replacing a DELETED entry then we don't need to update
-            // the load counter.
-            let old_ctrl = *self.ctrl(index);
-            self.growth_left -= special_is_empty(old_ctrl) as usize;
-
-            self.set_ctrl(index, h2(hash));
-            bucket.write(value);
-            self.items += 1;
-            bucket
-        }
-    }
-
-    /// Temporary removes a bucket, applying the given function to the removed
-    /// element and optionally put back the returned value in the same bucket.
-    ///
-    /// Returns `true` if the bucket still contains an element
-    ///
-    /// This does not check if the given bucket is actually occupied.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn replace_bucket_with<F>(&mut self, bucket: Bucket<T>, f: F) -> bool
-    where
-        F: FnOnce(T) -> Option<T>,
-    {
-        let index = self.bucket_index(&bucket);
-        let old_ctrl = *self.ctrl(index);
-        debug_assert!(is_full(old_ctrl));
-        let old_growth_left = self.growth_left;
-        let item = self.remove(bucket);
-        if let Some(new_item) = f(item) {
-            self.growth_left = old_growth_left;
-            self.set_ctrl(index, old_ctrl);
-            self.items += 1;
-            self.bucket(index).write(new_item);
-            true
-        } else {
-            false
-        }
-    }
-
-    /// Searches for an element in the table.
-    #[inline]
-    pub fn find(&self, hash: u64, mut eq: impl FnMut(&T) -> bool) -> Option<Bucket<T>> {
-        unsafe {
-            for bucket in self.iter_hash(hash) {
-                let elm = bucket.as_ref();
-                if likely(eq(elm)) {
-                    return Some(bucket);
-                }
-            }
-            None
-        }
-    }
-
-    /// Gets a reference to an element in the table.
-    #[inline]
-    pub fn get(&self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<&T> {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.find(hash, eq) {
-            Some(bucket) => Some(unsafe { bucket.as_ref() }),
-            None => None,
-        }
-    }
-
-    /// Gets a mutable reference to an element in the table.
-    #[inline]
-    pub fn get_mut(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<&mut T> {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.find(hash, eq) {
-            Some(bucket) => Some(unsafe { bucket.as_mut() }),
-            None => None,
-        }
-    }
-
-    /// Returns the number of elements the map can hold without reallocating.
-    ///
-    /// This number is a lower bound; the table might be able to hold
-    /// more, but is guaranteed to be able to hold at least this many.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn capacity(&self) -> usize {
-        self.items + self.growth_left
-    }
-
-    /// Returns the number of elements in the table.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn len(&self) -> usize {
-        self.items
-    }
-
-    /// Returns the number of buckets in the table.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn buckets(&self) -> usize {
-        self.bucket_mask + 1
-    }
-
-    /// Returns the number of control bytes in the table.
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn num_ctrl_bytes(&self) -> usize {
-        self.bucket_mask + 1 + Group::WIDTH
-    }
-
-    /// Returns whether this table points to the empty singleton with a capacity
-    /// of 0.
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn is_empty_singleton(&self) -> bool {
-        self.bucket_mask == 0
-    }
-
-    /// Returns an iterator over every element in the table. It is up to
-    /// the caller to ensure that the `RawTable` outlives the `RawIter`.
-    /// Because we cannot make the `next` method unsafe on the `RawIter`
-    /// struct, we have to make the `iter` method unsafe.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn iter(&self) -> RawIter<T> {
-        let data = Bucket::from_base_index(self.data_end(), 0);
-        RawIter {
-            iter: RawIterRange::new(self.ctrl.as_ptr(), data, self.buckets()),
-            items: self.items,
-        }
-    }
-
-    /// Returns an iterator over occupied buckets that could match a given hash.
-    ///
-    /// In rare cases, the iterator may return a bucket with a different hash.
-    ///
-    /// It is up to the caller to ensure that the `RawTable` outlives the
-    /// `RawIterHash`. Because we cannot make the `next` method unsafe on the
-    /// `RawIterHash` struct, we have to make the `iter_hash` method unsafe.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn iter_hash(&self, hash: u64) -> RawIterHash<'_, T> {
-        RawIterHash::new(self, hash)
-    }
-
-    /// Returns an iterator which removes all elements from the table without
-    /// freeing the memory.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn drain(&mut self) -> RawDrain<'_, T> {
-        unsafe {
-            let iter = self.iter();
-            self.drain_iter_from(iter)
-        }
-    }
-
-    /// Returns an iterator which removes all elements from the table without
-    /// freeing the memory.
-    ///
-    /// Iteration starts at the provided iterator's current location.
-    ///
-    /// It is up to the caller to ensure that the iterator is valid for this
-    /// `RawTable` and covers all items that remain in the table.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub unsafe fn drain_iter_from(&mut self, iter: RawIter<T>) -> RawDrain<'_, T> {
-        debug_assert_eq!(iter.len(), self.len());
-        RawDrain {
-            iter,
-            table: ManuallyDrop::new(mem::replace(self, Self::new())),
-            orig_table: NonNull::from(self),
-            marker: PhantomData,
-        }
-    }
-
-    /// Returns an iterator which consumes all elements from the table.
-    ///
-    /// Iteration starts at the provided iterator's current location.
-    ///
-    /// It is up to the caller to ensure that the iterator is valid for this
-    /// `RawTable` and covers all items that remain in the table.
-    pub unsafe fn into_iter_from(self, iter: RawIter<T>) -> RawIntoIter<T> {
-        debug_assert_eq!(iter.len(), self.len());
-
-        let alloc = self.into_alloc();
-        RawIntoIter {
-            iter,
-            alloc,
-            marker: PhantomData,
-        }
-    }
-
-    /// Converts the table into a raw allocation. The contents of the table
-    /// should be dropped using a `RawIter` before freeing the allocation.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub(crate) fn into_alloc(self) -> Option<(NonNull<u8>, Layout)> {
-        let alloc = if self.is_empty_singleton() {
-            None
-        } else {
-            // Avoid `Option::unwrap_or_else` because it bloats LLVM IR.
-            let (layout, ctrl_offset) = match calculate_layout::<T>(self.buckets()) {
-                Some(lco) => lco,
-                None => unsafe { hint::unreachable_unchecked() },
-            };
-            Some((
-                unsafe { NonNull::new_unchecked(self.ctrl.as_ptr().sub(ctrl_offset)) },
-                layout,
-            ))
-        };
-        mem::forget(self);
-        alloc
-    }
-}
-
-unsafe impl<T> Send for RawTable<T> where T: Send {}
-unsafe impl<T> Sync for RawTable<T> where T: Sync {}
-
-impl<T: Clone> Clone for RawTable<T> {
-    fn clone(&self) -> Self {
-        if self.is_empty_singleton() {
-            Self::new()
-        } else {
-            unsafe {
-                let mut new_table = ManuallyDrop::new(
-                    // Avoid `Result::ok_or_else` because it bloats LLVM IR.
-                    match Self::new_uninitialized(self.buckets(), Fallibility::Infallible) {
-                        Ok(table) => table,
-                        Err(_) => hint::unreachable_unchecked(),
-                    },
-                );
-
-                new_table.clone_from_spec(self, |new_table| {
-                    // We need to free the memory allocated for the new table.
-                    new_table.free_buckets();
-                });
-
-                // Return the newly created table.
-                ManuallyDrop::into_inner(new_table)
-            }
-        }
-    }
-
-    fn clone_from(&mut self, source: &Self) {
-        if source.is_empty_singleton() {
-            *self = Self::new();
-        } else {
-            unsafe {
-                // First, drop all our elements without clearing the control bytes.
-                if mem::needs_drop::<T>() && self.len() != 0 {
-                    for item in self.iter() {
-                        item.drop();
-                    }
-                }
-
-                // If necessary, resize our table to match the source.
-                if self.buckets() != source.buckets() {
-                    // Skip our drop by using ptr::write.
-                    if !self.is_empty_singleton() {
-                        self.free_buckets();
-                    }
-                    (self as *mut Self).write(
-                        // Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
-                        match Self::new_uninitialized(source.buckets(), Fallibility::Infallible) {
-                            Ok(table) => table,
-                            Err(_) => hint::unreachable_unchecked(),
-                        },
-                    );
-                }
-
-                self.clone_from_spec(source, |self_| {
-                    // We need to leave the table in an empty state.
-                    self_.clear_no_drop()
-                });
-            }
-        }
-    }
-}
-
-/// Specialization of `clone_from` for `Copy` types
-trait RawTableClone {
-    unsafe fn clone_from_spec(&mut self, source: &Self, on_panic: impl FnMut(&mut Self));
-}
-impl<T: Clone> RawTableClone for RawTable<T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    default_fn! {
-        unsafe fn clone_from_spec(&mut self, source: &Self, on_panic: impl FnMut(&mut Self)) {
-            self.clone_from_impl(source, on_panic);
-        }
-    }
-}
-#[cfg(feature = "nightly")]
-impl<T: Copy> RawTableClone for RawTable<T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    unsafe fn clone_from_spec(&mut self, source: &Self, _on_panic: impl FnMut(&mut Self)) {
-        source
-            .ctrl(0)
-            .copy_to_nonoverlapping(self.ctrl(0), self.num_ctrl_bytes());
-        source
-            .data_start()
-            .copy_to_nonoverlapping(self.data_start(), self.buckets());
-
-        self.items = source.items;
-        self.growth_left = source.growth_left;
-    }
-}
-
-impl<T: Clone> RawTable<T> {
-    /// Common code for clone and clone_from. Assumes `self.buckets() == source.buckets()`.
-    #[cfg_attr(feature = "inline-more", inline)]
-    unsafe fn clone_from_impl(&mut self, source: &Self, mut on_panic: impl FnMut(&mut Self)) {
-        // Copy the control bytes unchanged. We do this in a single pass
-        source
-            .ctrl(0)
-            .copy_to_nonoverlapping(self.ctrl(0), self.num_ctrl_bytes());
-
-        // The cloning of elements may panic, in which case we need
-        // to make sure we drop only the elements that have been
-        // cloned so far.
-        let mut guard = guard((0, &mut *self), |(index, self_)| {
-            if mem::needs_drop::<T>() && self_.len() != 0 {
-                for i in 0..=*index {
-                    if is_full(*self_.ctrl(i)) {
-                        self_.bucket(i).drop();
-                    }
-                }
-            }
-
-            // Depending on whether we were called from clone or clone_from, we
-            // either need to free the memory for the destination table or just
-            // clear the control bytes.
-            on_panic(self_);
-        });
-
-        for from in source.iter() {
-            let index = source.bucket_index(&from);
-            let to = guard.1.bucket(index);
-            to.write(from.as_ref().clone());
-
-            // Update the index in case we need to unwind.
-            guard.0 = index;
-        }
-
-        // Successfully cloned all items, no need to clean up.
-        mem::forget(guard);
-
-        self.items = source.items;
-        self.growth_left = source.growth_left;
-    }
-
-    /// Variant of `clone_from` to use when a hasher is available.
-    #[cfg(feature = "raw")]
-    pub fn clone_from_with_hasher(&mut self, source: &Self, hasher: impl Fn(&T) -> u64) {
-        // If we have enough capacity in the table, just clear it and insert
-        // elements one by one. We don't do this if we have the same number of
-        // buckets as the source since we can just copy the contents directly
-        // in that case.
-        if self.buckets() != source.buckets()
-            && bucket_mask_to_capacity(self.bucket_mask) >= source.len()
-        {
-            self.clear();
-
-            let guard_self = guard(&mut *self, |self_| {
-                // Clear the partially copied table if a panic occurs, otherwise
-                // items and growth_left will be out of sync with the contents
-                // of the table.
-                self_.clear();
-            });
-
-            unsafe {
-                for item in source.iter() {
-                    // This may panic.
-                    let item = item.as_ref().clone();
-                    let hash = hasher(&item);
-
-                    // We can use a simpler version of insert() here since:
-                    // - there are no DELETED entries.
-                    // - we know there is enough space in the table.
-                    // - all elements are unique.
-                    let index = guard_self.find_insert_slot(hash);
-                    guard_self.set_ctrl(index, h2(hash));
-                    guard_self.bucket(index).write(item);
-                }
-            }
-
-            // Successfully cloned all items, no need to clean up.
-            mem::forget(guard_self);
-
-            self.items = source.items;
-            self.growth_left -= source.items;
-        } else {
-            self.clone_from(source);
-        }
-    }
-}
-
-#[cfg(feature = "nightly")]
-unsafe impl<#[may_dangle] T> Drop for RawTable<T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drop(&mut self) {
-        if !self.is_empty_singleton() {
-            unsafe {
-                if mem::needs_drop::<T>() && self.len() != 0 {
-                    for item in self.iter() {
-                        item.drop();
-                    }
-                }
-                self.free_buckets();
-            }
-        }
-    }
-}
-#[cfg(not(feature = "nightly"))]
-impl<T> Drop for RawTable<T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drop(&mut self) {
-        if !self.is_empty_singleton() {
-            unsafe {
-                if mem::needs_drop::<T>() && self.len() != 0 {
-                    for item in self.iter() {
-                        item.drop();
-                    }
-                }
-                self.free_buckets();
-            }
-        }
-    }
-}
-
-impl<T> IntoIterator for RawTable<T> {
-    type Item = T;
-    type IntoIter = RawIntoIter<T>;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn into_iter(self) -> RawIntoIter<T> {
-        unsafe {
-            let iter = self.iter();
-            self.into_iter_from(iter)
-        }
-    }
-}
-
-/// Iterator over a sub-range of a table. Unlike `RawIter` this iterator does
-/// not track an item count.
-pub(crate) struct RawIterRange<T> {
-    // Mask of full buckets in the current group. Bits are cleared from this
-    // mask as each element is processed.
-    current_group: BitMask,
-
-    // Pointer to the buckets for the current group.
-    data: Bucket<T>,
-
-    // Pointer to the next group of control bytes,
-    // Must be aligned to the group size.
-    next_ctrl: *const u8,
-
-    // Pointer one past the last control byte of this range.
-    end: *const u8,
-}
-
-impl<T> RawIterRange<T> {
-    /// Returns a `RawIterRange` covering a subset of a table.
-    ///
-    /// The control byte address must be aligned to the group size.
-    #[cfg_attr(feature = "inline-more", inline)]
-    unsafe fn new(ctrl: *const u8, data: Bucket<T>, len: usize) -> Self {
-        debug_assert_ne!(len, 0);
-        debug_assert_eq!(ctrl as usize % Group::WIDTH, 0);
-        let end = ctrl.add(len);
-
-        // Load the first group and advance ctrl to point to the next group
-        let current_group = Group::load_aligned(ctrl).match_full();
-        let next_ctrl = ctrl.add(Group::WIDTH);
-
-        Self {
-            current_group,
-            data,
-            next_ctrl,
-            end,
-        }
-    }
-
-    /// Splits a `RawIterRange` into two halves.
-    ///
-    /// Returns `None` if the remaining range is smaller than or equal to the
-    /// group width.
-    #[cfg_attr(feature = "inline-more", inline)]
-    #[cfg(feature = "rayon")]
-    pub(crate) fn split(mut self) -> (Self, Option<RawIterRange<T>>) {
-        unsafe {
-            if self.end <= self.next_ctrl {
-                // Nothing to split if the group that we are current processing
-                // is the last one.
-                (self, None)
-            } else {
-                // len is the remaining number of elements after the group that
-                // we are currently processing. It must be a multiple of the
-                // group size (small tables are caught by the check above).
-                let len = offset_from(self.end, self.next_ctrl);
-                debug_assert_eq!(len % Group::WIDTH, 0);
-
-                // Split the remaining elements into two halves, but round the
-                // midpoint down in case there is an odd number of groups
-                // remaining. This ensures that:
-                // - The tail is at least 1 group long.
-                // - The split is roughly even considering we still have the
-                //   current group to process.
-                let mid = (len / 2) & !(Group::WIDTH - 1);
-
-                let tail = Self::new(
-                    self.next_ctrl.add(mid),
-                    self.data.next_n(Group::WIDTH).next_n(mid),
-                    len - mid,
-                );
-                debug_assert_eq!(
-                    self.data.next_n(Group::WIDTH).next_n(mid).ptr,
-                    tail.data.ptr
-                );
-                debug_assert_eq!(self.end, tail.end);
-                self.end = self.next_ctrl.add(mid);
-                debug_assert_eq!(self.end.add(Group::WIDTH), tail.next_ctrl);
-                (self, Some(tail))
-            }
-        }
-    }
-}
-
-// We make raw iterators unconditionally Send and Sync, and let the PhantomData
-// in the actual iterator implementations determine the real Send/Sync bounds.
-unsafe impl<T> Send for RawIterRange<T> {}
-unsafe impl<T> Sync for RawIterRange<T> {}
-
-impl<T> Clone for RawIterRange<T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn clone(&self) -> Self {
-        Self {
-            data: self.data.clone(),
-            next_ctrl: self.next_ctrl,
-            current_group: self.current_group,
-            end: self.end,
-        }
-    }
-}
-
-impl<T> Iterator for RawIterRange<T> {
-    type Item = Bucket<T>;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<Bucket<T>> {
-        unsafe {
-            loop {
-                if let Some(index) = self.current_group.lowest_set_bit() {
-                    self.current_group = self.current_group.remove_lowest_bit();
-                    return Some(self.data.next_n(index));
-                }
-
-                if self.next_ctrl >= self.end {
-                    return None;
-                }
-
-                // We might read past self.end up to the next group boundary,
-                // but this is fine because it only occurs on tables smaller
-                // than the group size where the trailing control bytes are all
-                // EMPTY. On larger tables self.end is guaranteed to be aligned
-                // to the group size (since tables are power-of-two sized).
-                self.current_group = Group::load_aligned(self.next_ctrl).match_full();
-                self.data = self.data.next_n(Group::WIDTH);
-                self.next_ctrl = self.next_ctrl.add(Group::WIDTH);
-            }
-        }
-    }
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        // We don't have an item count, so just guess based on the range size.
-        (
-            0,
-            Some(unsafe { offset_from(self.end, self.next_ctrl) + Group::WIDTH }),
-        )
-    }
-}
-
-impl<T> FusedIterator for RawIterRange<T> {}
-
-/// Iterator which returns a raw pointer to every full bucket in the table.
-///
-/// For maximum flexibility this iterator is not bound by a lifetime, but you
-/// must observe several rules when using it:
-/// - You must not free the hash table while iterating (including via growing/shrinking).
-/// - It is fine to erase a bucket that has been yielded by the iterator.
-/// - Erasing a bucket that has not yet been yielded by the iterator may still
-///   result in the iterator yielding that bucket (unless `reflect_remove` is called).
-/// - It is unspecified whether an element inserted after the iterator was
-///   created will be yielded by that iterator (unless `reflect_insert` is called).
-/// - The order in which the iterator yields bucket is unspecified and may
-///   change in the future.
-pub struct RawIter<T> {
-    pub(crate) iter: RawIterRange<T>,
-    items: usize,
-}
-
-impl<T> RawIter<T> {
-    /// Refresh the iterator so that it reflects a removal from the given bucket.
-    ///
-    /// For the iterator to remain valid, this method must be called once
-    /// for each removed bucket before `next` is called again.
-    ///
-    /// This method should be called _before_ the removal is made. It is not necessary to call this
-    /// method if you are removing an item that this iterator yielded in the past.
-    #[cfg(feature = "raw")]
-    pub fn reflect_remove(&mut self, b: &Bucket<T>) {
-        self.reflect_toggle_full(b, false);
-    }
-
-    /// Refresh the iterator so that it reflects an insertion into the given bucket.
-    ///
-    /// For the iterator to remain valid, this method must be called once
-    /// for each insert before `next` is called again.
-    ///
-    /// This method does not guarantee that an insertion of a bucket witha greater
-    /// index than the last one yielded will be reflected in the iterator.
-    ///
-    /// This method should be called _after_ the given insert is made.
-    #[cfg(feature = "raw")]
-    pub fn reflect_insert(&mut self, b: &Bucket<T>) {
-        self.reflect_toggle_full(b, true);
-    }
-
-    /// Refresh the iterator so that it reflects a change to the state of the given bucket.
-    #[cfg(feature = "raw")]
-    fn reflect_toggle_full(&mut self, b: &Bucket<T>, is_insert: bool) {
-        unsafe {
-            if b.as_ptr() > self.iter.data.as_ptr() {
-                // The iterator has already passed the bucket's group.
-                // So the toggle isn't relevant to this iterator.
-                return;
-            }
-
-            if self.iter.next_ctrl < self.iter.end
-                && b.as_ptr() <= self.iter.data.next_n(Group::WIDTH).as_ptr()
-            {
-                // The iterator has not yet reached the bucket's group.
-                // We don't need to reload anything, but we do need to adjust the item count.
-
-                if cfg!(debug_assertions) {
-                    // Double-check that the user isn't lying to us by checking the bucket state.
-                    // To do that, we need to find its control byte. We know that self.iter.data is
-                    // at self.iter.next_ctrl - Group::WIDTH, so we work from there:
-                    let offset = offset_from(self.iter.data.as_ptr(), b.as_ptr());
-                    let ctrl = self.iter.next_ctrl.sub(Group::WIDTH).add(offset);
-                    // This method should be called _before_ a removal, or _after_ an insert,
-                    // so in both cases the ctrl byte should indicate that the bucket is full.
-                    assert!(is_full(*ctrl));
-                }
-
-                if is_insert {
-                    self.items += 1;
-                } else {
-                    self.items -= 1;
-                }
-
-                return;
-            }
-
-            // The iterator is at the bucket group that the toggled bucket is in.
-            // We need to do two things:
-            //
-            //  - Determine if the iterator already yielded the toggled bucket.
-            //    If it did, we're done.
-            //  - Otherwise, update the iterator cached group so that it won't
-            //    yield a to-be-removed bucket, or _will_ yield a to-be-added bucket.
-            //    We'll also need ot update the item count accordingly.
-            if let Some(index) = self.iter.current_group.lowest_set_bit() {
-                let next_bucket = self.iter.data.next_n(index);
-                if b.as_ptr() > next_bucket.as_ptr() {
-                    // The toggled bucket is "before" the bucket the iterator would yield next. We
-                    // therefore don't need to do anything --- the iterator has already passed the
-                    // bucket in question.
-                    //
-                    // The item count must already be correct, since a removal or insert "prior" to
-                    // the iterator's position wouldn't affect the item count.
-                } else {
-                    // The removed bucket is an upcoming bucket. We need to make sure it does _not_
-                    // get yielded, and also that it's no longer included in the item count.
-                    //
-                    // NOTE: We can't just reload the group here, both since that might reflect
-                    // inserts we've already passed, and because that might inadvertently unset the
-                    // bits for _other_ removals. If we do that, we'd have to also decrement the
-                    // item count for those other bits that we unset. But the presumably subsequent
-                    // call to reflect for those buckets might _also_ decrement the item count.
-                    // Instead, we _just_ flip the bit for the particular bucket the caller asked
-                    // us to reflect.
-                    let our_bit = offset_from(self.iter.data.as_ptr(), b.as_ptr());
-                    let was_full = self.iter.current_group.flip(our_bit);
-                    debug_assert_ne!(was_full, is_insert);
-
-                    if is_insert {
-                        self.items += 1;
-                    } else {
-                        self.items -= 1;
-                    }
-
-                    if cfg!(debug_assertions) {
-                        if b.as_ptr() == next_bucket.as_ptr() {
-                            // The removed bucket should no longer be next
-                            debug_assert_ne!(self.iter.current_group.lowest_set_bit(), Some(index));
-                        } else {
-                            // We should not have changed what bucket comes next.
-                            debug_assert_eq!(self.iter.current_group.lowest_set_bit(), Some(index));
-                        }
-                    }
-                }
-            } else {
-                // We must have already iterated past the removed item.
-            }
-        }
-    }
-}
-
-impl<T> Clone for RawIter<T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn clone(&self) -> Self {
-        Self {
-            iter: self.iter.clone(),
-            items: self.items,
-        }
-    }
-}
-
-impl<T> Iterator for RawIter<T> {
-    type Item = Bucket<T>;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<Bucket<T>> {
-        if let Some(b) = self.iter.next() {
-            self.items -= 1;
-            Some(b)
-        } else {
-            // We don't check against items == 0 here to allow the
-            // compiler to optimize away the item count entirely if the
-            // iterator length is never queried.
-            debug_assert_eq!(self.items, 0);
-            None
-        }
-    }
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (self.items, Some(self.items))
-    }
-}
-
-impl<T> ExactSizeIterator for RawIter<T> {}
-impl<T> FusedIterator for RawIter<T> {}
-
-/// Iterator which consumes a table and returns elements.
-pub struct RawIntoIter<T> {
-    iter: RawIter<T>,
-    alloc: Option<(NonNull<u8>, Layout)>,
-    marker: PhantomData<T>,
-}
-
-impl<T> RawIntoIter<T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn iter(&self) -> RawIter<T> {
-        self.iter.clone()
-    }
-}
-
-unsafe impl<T> Send for RawIntoIter<T> where T: Send {}
-unsafe impl<T> Sync for RawIntoIter<T> where T: Sync {}
-
-#[cfg(feature = "nightly")]
-unsafe impl<#[may_dangle] T> Drop for RawIntoIter<T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drop(&mut self) {
-        unsafe {
-            // Drop all remaining elements
-            if mem::needs_drop::<T>() && self.iter.len() != 0 {
-                while let Some(item) = self.iter.next() {
-                    item.drop();
-                }
-            }
-
-            // Free the table
-            if let Some((ptr, layout)) = self.alloc {
-                dealloc(ptr.as_ptr(), layout);
-            }
-        }
-    }
-}
-#[cfg(not(feature = "nightly"))]
-impl<T> Drop for RawIntoIter<T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drop(&mut self) {
-        unsafe {
-            // Drop all remaining elements
-            if mem::needs_drop::<T>() && self.iter.len() != 0 {
-                while let Some(item) = self.iter.next() {
-                    item.drop();
-                }
-            }
-
-            // Free the table
-            if let Some((ptr, layout)) = self.alloc {
-                dealloc(ptr.as_ptr(), layout);
-            }
-        }
-    }
-}
-
-impl<T> Iterator for RawIntoIter<T> {
-    type Item = T;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<T> {
-        unsafe { Some(self.iter.next()?.read()) }
-    }
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-impl<T> ExactSizeIterator for RawIntoIter<T> {}
-impl<T> FusedIterator for RawIntoIter<T> {}
-
-/// Iterator which consumes elements without freeing the table storage.
-pub struct RawDrain<'a, T> {
-    iter: RawIter<T>,
-
-    // The table is moved into the iterator for the duration of the drain. This
-    // ensures that an empty table is left if the drain iterator is leaked
-    // without dropping.
-    table: ManuallyDrop<RawTable<T>>,
-    orig_table: NonNull<RawTable<T>>,
-
-    // We don't use a &'a mut RawTable<T> because we want RawDrain to be
-    // covariant over T.
-    marker: PhantomData<&'a RawTable<T>>,
-}
-
-impl<T> RawDrain<'_, T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn iter(&self) -> RawIter<T> {
-        self.iter.clone()
-    }
-}
-
-unsafe impl<T> Send for RawDrain<'_, T> where T: Send {}
-unsafe impl<T> Sync for RawDrain<'_, T> where T: Sync {}
-
-impl<T> Drop for RawDrain<'_, T> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drop(&mut self) {
-        unsafe {
-            // Drop all remaining elements. Note that this may panic.
-            if mem::needs_drop::<T>() && self.iter.len() != 0 {
-                while let Some(item) = self.iter.next() {
-                    item.drop();
-                }
-            }
-
-            // Reset the contents of the table now that all elements have been
-            // dropped.
-            self.table.clear_no_drop();
-
-            // Move the now empty table back to its original location.
-            self.orig_table
-                .as_ptr()
-                .copy_from_nonoverlapping(&*self.table, 1);
-        }
-    }
-}
-
-impl<T> Iterator for RawDrain<'_, T> {
-    type Item = T;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<T> {
-        unsafe {
-            let item = self.iter.next()?;
-            Some(item.read())
-        }
-    }
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-impl<T> ExactSizeIterator for RawDrain<'_, T> {}
-impl<T> FusedIterator for RawDrain<'_, T> {}
-
-/// Iterator over occupied buckets that could match a given hash.
-///
-/// In rare cases, the iterator may return a bucket with a different hash.
-pub struct RawIterHash<'a, T> {
-    table: &'a RawTable<T>,
-
-    // The top 7 bits of the hash.
-    h2_hash: u8,
-
-    // The sequence of groups to probe in the search.
-    probe_seq: ProbeSeq,
-
-    // The current group and its position.
-    pos: usize,
-    group: Group,
-
-    // The elements within the group with a matching h2-hash.
-    bitmask: BitMaskIter,
-}
-
-impl<'a, T> RawIterHash<'a, T> {
-    fn new(table: &'a RawTable<T>, hash: u64) -> Self {
-        unsafe {
-            let h2_hash = h2(hash);
-            let mut probe_seq = table.probe_seq(hash);
-            let pos = probe_seq.next().unwrap();
-            let group = Group::load(table.ctrl(pos));
-            let bitmask = group.match_byte(h2_hash).into_iter();
-
-            RawIterHash {
-                table,
-                h2_hash,
-                probe_seq,
-                pos,
-                group,
-                bitmask,
-            }
-        }
-    }
-}
-
-impl<'a, T> Iterator for RawIterHash<'a, T> {
-    type Item = Bucket<T>;
-
-    fn next(&mut self) -> Option<Bucket<T>> {
-        unsafe {
-            loop {
-                if let Some(bit) = self.bitmask.next() {
-                    let index = (self.pos + bit) & self.table.bucket_mask;
-                    let bucket = self.table.bucket(index);
-                    return Some(bucket);
-                }
-                if likely(self.group.match_empty().any_bit_set()) {
-                    return None;
-                }
-                self.pos = self.probe_seq.next().unwrap();
-                self.group = Group::load(self.table.ctrl(self.pos));
-                self.bitmask = self.group.match_byte(self.h2_hash).into_iter();
-            }
-        }
-    }
-}
diff --git a/vendor/hashbrown-0.9.1/src/raw/sse2.rs b/vendor/hashbrown-0.9.1/src/raw/sse2.rs
deleted file mode 100644 (file)
index a27bc09..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-use super::bitmask::BitMask;
-use super::EMPTY;
-use core::mem;
-
-#[cfg(target_arch = "x86")]
-use core::arch::x86;
-#[cfg(target_arch = "x86_64")]
-use core::arch::x86_64 as x86;
-
-pub type BitMaskWord = u16;
-pub const BITMASK_STRIDE: usize = 1;
-pub const BITMASK_MASK: BitMaskWord = 0xffff;
-
-/// Abstraction over a group of control bytes which can be scanned in
-/// parallel.
-///
-/// This implementation uses a 128-bit SSE value.
-#[derive(Copy, Clone)]
-pub struct Group(x86::__m128i);
-
-// FIXME: https://github.com/rust-lang/rust-clippy/issues/3859
-#[allow(clippy::use_self)]
-impl Group {
-    /// Number of bytes in the group.
-    pub const WIDTH: usize = mem::size_of::<Self>();
-
-    /// Returns a full group of empty bytes, suitable for use as the initial
-    /// value for an empty hash table.
-    ///
-    /// This is guaranteed to be aligned to the group size.
-    pub const fn static_empty() -> &'static [u8; Group::WIDTH] {
-        #[repr(C)]
-        struct AlignedBytes {
-            _align: [Group; 0],
-            bytes: [u8; Group::WIDTH],
-        };
-        const ALIGNED_BYTES: AlignedBytes = AlignedBytes {
-            _align: [],
-            bytes: [EMPTY; Group::WIDTH],
-        };
-        &ALIGNED_BYTES.bytes
-    }
-
-    /// Loads a group of bytes starting at the given address.
-    #[inline]
-    #[allow(clippy::cast_ptr_alignment)] // unaligned load
-    pub unsafe fn load(ptr: *const u8) -> Self {
-        Group(x86::_mm_loadu_si128(ptr as *const _))
-    }
-
-    /// Loads a group of bytes starting at the given address, which must be
-    /// aligned to `mem::align_of::<Group>()`.
-    #[inline]
-    #[allow(clippy::cast_ptr_alignment)]
-    pub unsafe fn load_aligned(ptr: *const u8) -> Self {
-        // FIXME: use align_offset once it stabilizes
-        debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
-        Group(x86::_mm_load_si128(ptr as *const _))
-    }
-
-    /// Stores the group of bytes to the given address, which must be
-    /// aligned to `mem::align_of::<Group>()`.
-    #[inline]
-    #[allow(clippy::cast_ptr_alignment)]
-    pub unsafe fn store_aligned(self, ptr: *mut u8) {
-        // FIXME: use align_offset once it stabilizes
-        debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
-        x86::_mm_store_si128(ptr as *mut _, self.0);
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which have
-    /// the given value.
-    #[inline]
-    pub fn match_byte(self, byte: u8) -> BitMask {
-        #[allow(
-            clippy::cast_possible_wrap, // byte: u8 as i8
-            // byte: i32 as u16
-            //   note: _mm_movemask_epi8 returns a 16-bit mask in a i32, the
-            //   upper 16-bits of the i32 are zeroed:
-            clippy::cast_sign_loss,
-            clippy::cast_possible_truncation
-        )]
-        unsafe {
-            let cmp = x86::_mm_cmpeq_epi8(self.0, x86::_mm_set1_epi8(byte as i8));
-            BitMask(x86::_mm_movemask_epi8(cmp) as u16)
-        }
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which are
-    /// `EMPTY`.
-    #[inline]
-    pub fn match_empty(self) -> BitMask {
-        self.match_byte(EMPTY)
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which are
-    /// `EMPTY` or `DELETED`.
-    #[inline]
-    pub fn match_empty_or_deleted(self) -> BitMask {
-        #[allow(
-            // byte: i32 as u16
-            //   note: _mm_movemask_epi8 returns a 16-bit mask in a i32, the
-            //   upper 16-bits of the i32 are zeroed:
-            clippy::cast_sign_loss,
-            clippy::cast_possible_truncation
-        )]
-        unsafe {
-            // A byte is EMPTY or DELETED iff the high bit is set
-            BitMask(x86::_mm_movemask_epi8(self.0) as u16)
-        }
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which are full.
-    #[inline]
-    pub fn match_full(&self) -> BitMask {
-        self.match_empty_or_deleted().invert()
-    }
-
-    /// Performs the following transformation on all bytes in the group:
-    /// - `EMPTY => EMPTY`
-    /// - `DELETED => EMPTY`
-    /// - `FULL => DELETED`
-    #[inline]
-    pub fn convert_special_to_empty_and_full_to_deleted(self) -> Self {
-        // Map high_bit = 1 (EMPTY or DELETED) to 1111_1111
-        // and high_bit = 0 (FULL) to 1000_0000
-        //
-        // Here's this logic expanded to concrete values:
-        //   let special = 0 > byte = 1111_1111 (true) or 0000_0000 (false)
-        //   1111_1111 | 1000_0000 = 1111_1111
-        //   0000_0000 | 1000_0000 = 1000_0000
-        #[allow(
-            clippy::cast_possible_wrap, // byte: 0x80_u8 as i8
-        )]
-        unsafe {
-            let zero = x86::_mm_setzero_si128();
-            let special = x86::_mm_cmpgt_epi8(zero, self.0);
-            Group(x86::_mm_or_si128(
-                special,
-                x86::_mm_set1_epi8(0x80_u8 as i8),
-            ))
-        }
-    }
-}
diff --git a/vendor/hashbrown-0.9.1/src/rustc_entry.rs b/vendor/hashbrown-0.9.1/src/rustc_entry.rs
deleted file mode 100644 (file)
index b6ea7bc..0000000
+++ /dev/null
@@ -1,618 +0,0 @@
-use self::RustcEntry::*;
-use crate::map::{make_hash, Drain, HashMap, IntoIter, Iter, IterMut};
-use crate::raw::{Bucket, RawTable};
-use core::fmt::{self, Debug};
-use core::hash::{BuildHasher, Hash};
-use core::mem;
-
-impl<K, V, S> HashMap<K, V, S>
-where
-    K: Eq + Hash,
-    S: BuildHasher,
-{
-    /// Gets the given key's corresponding entry in the map for in-place manipulation.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut letters = HashMap::new();
-    ///
-    /// for ch in "a short treatise on fungi".chars() {
-    ///     let counter = letters.rustc_entry(ch).or_insert(0);
-    ///     *counter += 1;
-    /// }
-    ///
-    /// assert_eq!(letters[&'s'], 2);
-    /// assert_eq!(letters[&'t'], 3);
-    /// assert_eq!(letters[&'u'], 1);
-    /// assert_eq!(letters.get(&'y'), None);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn rustc_entry(&mut self, key: K) -> RustcEntry<'_, K, V> {
-        let hash = make_hash(&self.hash_builder, &key);
-        if let Some(elem) = self.table.find(hash, |q| q.0.eq(&key)) {
-            RustcEntry::Occupied(RustcOccupiedEntry {
-                key: Some(key),
-                elem,
-                table: &mut self.table,
-            })
-        } else {
-            // Ideally we would put this in VacantEntry::insert, but Entry is not
-            // generic over the BuildHasher and adding a generic parameter would be
-            // a breaking change.
-            self.reserve(1);
-
-            RustcEntry::Vacant(RustcVacantEntry {
-                hash,
-                key,
-                table: &mut self.table,
-            })
-        }
-    }
-}
-
-/// A view into a single entry in a map, which may either be vacant or occupied.
-///
-/// This `enum` is constructed from the [`entry`] method on [`HashMap`].
-///
-/// [`HashMap`]: struct.HashMap.html
-/// [`entry`]: struct.HashMap.html#method.rustc_entry
-pub enum RustcEntry<'a, K, V> {
-    /// An occupied entry.
-    Occupied(RustcOccupiedEntry<'a, K, V>),
-
-    /// A vacant entry.
-    Vacant(RustcVacantEntry<'a, K, V>),
-}
-
-impl<K: Debug, V: Debug> Debug for RustcEntry<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
-            Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(),
-        }
-    }
-}
-
-/// A view into an occupied entry in a `HashMap`.
-/// It is part of the [`RustcEntry`] enum.
-///
-/// [`RustcEntry`]: enum.RustcEntry.html
-pub struct RustcOccupiedEntry<'a, K, V> {
-    key: Option<K>,
-    elem: Bucket<(K, V)>,
-    table: &'a mut RawTable<(K, V)>,
-}
-
-unsafe impl<K, V> Send for RustcOccupiedEntry<'_, K, V>
-where
-    K: Send,
-    V: Send,
-{
-}
-unsafe impl<K, V> Sync for RustcOccupiedEntry<'_, K, V>
-where
-    K: Sync,
-    V: Sync,
-{
-}
-
-impl<K: Debug, V: Debug> Debug for RustcOccupiedEntry<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("OccupiedEntry")
-            .field("key", self.key())
-            .field("value", self.get())
-            .finish()
-    }
-}
-
-/// A view into a vacant entry in a `HashMap`.
-/// It is part of the [`RustcEntry`] enum.
-///
-/// [`RustcEntry`]: enum.RustcEntry.html
-pub struct RustcVacantEntry<'a, K, V> {
-    hash: u64,
-    key: K,
-    table: &'a mut RawTable<(K, V)>,
-}
-
-impl<K: Debug, V> Debug for RustcVacantEntry<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple("VacantEntry").field(self.key()).finish()
-    }
-}
-
-impl<'a, K, V> RustcEntry<'a, K, V> {
-    /// Sets the value of the entry, and returns a RustcOccupiedEntry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// let entry = map.entry("horseyland").insert(37);
-    ///
-    /// assert_eq!(entry.key(), &"horseyland");
-    /// ```
-    pub fn insert(self, value: V) -> RustcOccupiedEntry<'a, K, V> {
-        match self {
-            Vacant(entry) => entry.insert_entry(value),
-            Occupied(mut entry) => {
-                entry.insert(value);
-                entry
-            }
-        }
-    }
-
-    /// Ensures a value is in the entry by inserting the default if empty, and returns
-    /// a mutable reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// map.rustc_entry("poneyland").or_insert(3);
-    /// assert_eq!(map["poneyland"], 3);
-    ///
-    /// *map.rustc_entry("poneyland").or_insert(10) *= 2;
-    /// assert_eq!(map["poneyland"], 6);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn or_insert(self, default: V) -> &'a mut V
-    where
-        K: Hash,
-    {
-        match self {
-            Occupied(entry) => entry.into_mut(),
-            Vacant(entry) => entry.insert(default),
-        }
-    }
-
-    /// Ensures a value is in the entry by inserting the result of the default function if empty,
-    /// and returns a mutable reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, String> = HashMap::new();
-    /// let s = "hoho".to_string();
-    ///
-    /// map.rustc_entry("poneyland").or_insert_with(|| s);
-    ///
-    /// assert_eq!(map["poneyland"], "hoho".to_string());
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V
-    where
-        K: Hash,
-    {
-        match self {
-            Occupied(entry) => entry.into_mut(),
-            Vacant(entry) => entry.insert(default()),
-        }
-    }
-
-    /// Returns a reference to this entry's key.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// assert_eq!(map.rustc_entry("poneyland").key(), &"poneyland");
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn key(&self) -> &K {
-        match *self {
-            Occupied(ref entry) => entry.key(),
-            Vacant(ref entry) => entry.key(),
-        }
-    }
-
-    /// Provides in-place mutable access to an occupied entry before any
-    /// potential inserts into the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// map.rustc_entry("poneyland")
-    ///    .and_modify(|e| { *e += 1 })
-    ///    .or_insert(42);
-    /// assert_eq!(map["poneyland"], 42);
-    ///
-    /// map.rustc_entry("poneyland")
-    ///    .and_modify(|e| { *e += 1 })
-    ///    .or_insert(42);
-    /// assert_eq!(map["poneyland"], 43);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn and_modify<F>(self, f: F) -> Self
-    where
-        F: FnOnce(&mut V),
-    {
-        match self {
-            Occupied(mut entry) => {
-                f(entry.get_mut());
-                Occupied(entry)
-            }
-            Vacant(entry) => Vacant(entry),
-        }
-    }
-}
-
-impl<'a, K, V: Default> RustcEntry<'a, K, V> {
-    /// Ensures a value is in the entry by inserting the default value if empty,
-    /// and returns a mutable reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # fn main() {
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, Option<u32>> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_default();
-    ///
-    /// assert_eq!(map["poneyland"], None);
-    /// # }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn or_default(self) -> &'a mut V
-    where
-        K: Hash,
-    {
-        match self {
-            Occupied(entry) => entry.into_mut(),
-            Vacant(entry) => entry.insert(Default::default()),
-        }
-    }
-}
-
-impl<'a, K, V> RustcOccupiedEntry<'a, K, V> {
-    /// Gets a reference to the key in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_insert(12);
-    /// assert_eq!(map.rustc_entry("poneyland").key(), &"poneyland");
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn key(&self) -> &K {
-        unsafe { &self.elem.as_ref().0 }
-    }
-
-    /// Take the ownership of the key and value from the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_insert(12);
-    ///
-    /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") {
-    ///     // We delete the entry from the map.
-    ///     o.remove_entry();
-    /// }
-    ///
-    /// assert_eq!(map.contains_key("poneyland"), false);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn remove_entry(self) -> (K, V) {
-        unsafe { self.table.remove(self.elem) }
-    }
-
-    /// Gets a reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_insert(12);
-    ///
-    /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") {
-    ///     assert_eq!(o.get(), &12);
-    /// }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn get(&self) -> &V {
-        unsafe { &self.elem.as_ref().1 }
-    }
-
-    /// Gets a mutable reference to the value in the entry.
-    ///
-    /// If you need a reference to the `RustcOccupiedEntry` which may outlive the
-    /// destruction of the `RustcEntry` value, see [`into_mut`].
-    ///
-    /// [`into_mut`]: #method.into_mut
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_insert(12);
-    ///
-    /// assert_eq!(map["poneyland"], 12);
-    /// if let RustcEntry::Occupied(mut o) = map.rustc_entry("poneyland") {
-    ///     *o.get_mut() += 10;
-    ///     assert_eq!(*o.get(), 22);
-    ///
-    ///     // We can use the same RustcEntry multiple times.
-    ///     *o.get_mut() += 2;
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 24);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn get_mut(&mut self) -> &mut V {
-        unsafe { &mut self.elem.as_mut().1 }
-    }
-
-    /// Converts the RustcOccupiedEntry into a mutable reference to the value in the entry
-    /// with a lifetime bound to the map itself.
-    ///
-    /// If you need multiple references to the `RustcOccupiedEntry`, see [`get_mut`].
-    ///
-    /// [`get_mut`]: #method.get_mut
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_insert(12);
-    ///
-    /// assert_eq!(map["poneyland"], 12);
-    /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") {
-    ///     *o.into_mut() += 10;
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 22);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn into_mut(self) -> &'a mut V {
-        unsafe { &mut self.elem.as_mut().1 }
-    }
-
-    /// Sets the value of the entry, and returns the entry's old value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_insert(12);
-    ///
-    /// if let RustcEntry::Occupied(mut o) = map.rustc_entry("poneyland") {
-    ///     assert_eq!(o.insert(15), 12);
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 15);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert(&mut self, mut value: V) -> V {
-        let old_value = self.get_mut();
-        mem::swap(&mut value, old_value);
-        value
-    }
-
-    /// Takes the value out of the entry, and returns it.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_insert(12);
-    ///
-    /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") {
-    ///     assert_eq!(o.remove(), 12);
-    /// }
-    ///
-    /// assert_eq!(map.contains_key("poneyland"), false);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn remove(self) -> V {
-        self.remove_entry().1
-    }
-
-    /// Replaces the entry, returning the old key and value. The new key in the hash map will be
-    /// the key used to create this entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::hash_map::{RustcEntry, HashMap};
-    /// use std::rc::Rc;
-    ///
-    /// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
-    /// map.insert(Rc::new("Stringthing".to_string()), 15);
-    ///
-    /// let my_key = Rc::new("Stringthing".to_string());
-    ///
-    /// if let RustcEntry::Occupied(entry) = map.rustc_entry(my_key) {
-    ///     // Also replace the key with a handle to our other key.
-    ///     let (old_key, old_value): (Rc<String>, u32) = entry.replace_entry(16);
-    /// }
-    ///
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn replace_entry(self, value: V) -> (K, V) {
-        let entry = unsafe { self.elem.as_mut() };
-
-        let old_key = mem::replace(&mut entry.0, self.key.unwrap());
-        let old_value = mem::replace(&mut entry.1, value);
-
-        (old_key, old_value)
-    }
-
-    /// Replaces the key in the hash map with the key used to create this entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::hash_map::{RustcEntry, HashMap};
-    /// use std::rc::Rc;
-    ///
-    /// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
-    /// let mut known_strings: Vec<Rc<String>> = Vec::new();
-    ///
-    /// // Initialise known strings, run program, etc.
-    ///
-    /// reclaim_memory(&mut map, &known_strings);
-    ///
-    /// fn reclaim_memory(map: &mut HashMap<Rc<String>, u32>, known_strings: &[Rc<String>] ) {
-    ///     for s in known_strings {
-    ///         if let RustcEntry::Occupied(entry) = map.rustc_entry(s.clone()) {
-    ///             // Replaces the entry's key with our version of it in `known_strings`.
-    ///             entry.replace_key();
-    ///         }
-    ///     }
-    /// }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn replace_key(self) -> K {
-        let entry = unsafe { self.elem.as_mut() };
-        mem::replace(&mut entry.0, self.key.unwrap())
-    }
-}
-
-impl<'a, K, V> RustcVacantEntry<'a, K, V> {
-    /// Gets a reference to the key that would be used when inserting a value
-    /// through the `RustcVacantEntry`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// assert_eq!(map.rustc_entry("poneyland").key(), &"poneyland");
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn key(&self) -> &K {
-        &self.key
-    }
-
-    /// Take ownership of the key.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// if let RustcEntry::Vacant(v) = map.rustc_entry("poneyland") {
-    ///     v.into_key();
-    /// }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn into_key(self) -> K {
-        self.key
-    }
-
-    /// Sets the value of the entry with the RustcVacantEntry's key,
-    /// and returns a mutable reference to it.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// if let RustcEntry::Vacant(o) = map.rustc_entry("poneyland") {
-    ///     o.insert(37);
-    /// }
-    /// assert_eq!(map["poneyland"], 37);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert(self, value: V) -> &'a mut V {
-        let bucket = self.table.insert_no_grow(self.hash, (self.key, value));
-        unsafe { &mut bucket.as_mut().1 }
-    }
-
-    /// Sets the value of the entry with the RustcVacantEntry's key,
-    /// and returns a RustcOccupiedEntry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// if let RustcEntry::Vacant(v) = map.rustc_entry("poneyland") {
-    ///     let o = v.insert_entry(37);
-    ///     assert_eq!(o.get(), &37);
-    /// }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert_entry(self, value: V) -> RustcOccupiedEntry<'a, K, V> {
-        let bucket = self.table.insert_no_grow(self.hash, (self.key, value));
-        RustcOccupiedEntry {
-            key: None,
-            elem: bucket,
-            table: self.table,
-        }
-    }
-}
-
-impl<K, V> IterMut<'_, K, V> {
-    /// Returns a iterator of references over the remaining items.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn rustc_iter(&self) -> Iter<'_, K, V> {
-        self.iter()
-    }
-}
-
-impl<K, V> IntoIter<K, V> {
-    /// Returns a iterator of references over the remaining items.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn rustc_iter(&self) -> Iter<'_, K, V> {
-        self.iter()
-    }
-}
-
-impl<K, V> Drain<'_, K, V> {
-    /// Returns a iterator of references over the remaining items.
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn rustc_iter(&self) -> Iter<'_, K, V> {
-        self.iter()
-    }
-}
diff --git a/vendor/hashbrown-0.9.1/src/scopeguard.rs b/vendor/hashbrown-0.9.1/src/scopeguard.rs
deleted file mode 100644 (file)
index 32c9694..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// Extracted from the scopeguard crate
-use core::ops::{Deref, DerefMut};
-
-pub struct ScopeGuard<T, F>
-where
-    F: FnMut(&mut T),
-{
-    dropfn: F,
-    value: T,
-}
-
-#[cfg_attr(feature = "inline-more", inline)]
-pub fn guard<T, F>(value: T, dropfn: F) -> ScopeGuard<T, F>
-where
-    F: FnMut(&mut T),
-{
-    ScopeGuard { dropfn, value }
-}
-
-impl<T, F> Deref for ScopeGuard<T, F>
-where
-    F: FnMut(&mut T),
-{
-    type Target = T;
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn deref(&self) -> &T {
-        &self.value
-    }
-}
-
-impl<T, F> DerefMut for ScopeGuard<T, F>
-where
-    F: FnMut(&mut T),
-{
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn deref_mut(&mut self) -> &mut T {
-        &mut self.value
-    }
-}
-
-impl<T, F> Drop for ScopeGuard<T, F>
-where
-    F: FnMut(&mut T),
-{
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drop(&mut self) {
-        (self.dropfn)(&mut self.value)
-    }
-}
diff --git a/vendor/hashbrown-0.9.1/src/set.rs b/vendor/hashbrown-0.9.1/src/set.rs
deleted file mode 100644 (file)
index b8460fd..0000000
+++ /dev/null
@@ -1,2119 +0,0 @@
-use crate::TryReserveError;
-use alloc::borrow::ToOwned;
-use core::borrow::Borrow;
-use core::fmt;
-use core::hash::{BuildHasher, Hash};
-use core::iter::{Chain, FromIterator, FusedIterator};
-use core::mem;
-use core::ops::{BitAnd, BitOr, BitXor, Sub};
-
-use super::map::{self, ConsumeAllOnDrop, DefaultHashBuilder, DrainFilterInner, HashMap, Keys};
-
-// Future Optimization (FIXME!)
-// =============================
-//
-// Iteration over zero sized values is a noop. There is no need
-// for `bucket.val` in the case of HashSet. I suppose we would need HKT
-// to get rid of it properly.
-
-/// A hash set implemented as a `HashMap` where the value is `()`.
-///
-/// As with the [`HashMap`] type, a `HashSet` requires that the elements
-/// implement the [`Eq`] and [`Hash`] traits. This can frequently be achieved by
-/// using `#[derive(PartialEq, Eq, Hash)]`. If you implement these yourself,
-/// it is important that the following property holds:
-///
-/// ```text
-/// k1 == k2 -> hash(k1) == hash(k2)
-/// ```
-///
-/// In other words, if two keys are equal, their hashes must be equal.
-///
-///
-/// It is a logic error for an item to be modified in such a way that the
-/// item's hash, as determined by the [`Hash`] trait, or its equality, as
-/// determined by the [`Eq`] trait, changes while it is in the set. This is
-/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or
-/// unsafe code.
-///
-/// It is also a logic error for the [`Hash`] implementation of a key to panic.
-/// This is generally only possible if the trait is implemented manually. If a
-/// panic does occur then the contents of the `HashSet` may become corrupted and
-/// some items may be dropped from the table.
-///
-/// # Examples
-///
-/// ```
-/// use hashbrown::HashSet;
-/// // Type inference lets us omit an explicit type signature (which
-/// // would be `HashSet<String>` in this example).
-/// let mut books = HashSet::new();
-///
-/// // Add some books.
-/// books.insert("A Dance With Dragons".to_string());
-/// books.insert("To Kill a Mockingbird".to_string());
-/// books.insert("The Odyssey".to_string());
-/// books.insert("The Great Gatsby".to_string());
-///
-/// // Check for a specific one.
-/// if !books.contains("The Winds of Winter") {
-///     println!("We have {} books, but The Winds of Winter ain't one.",
-///              books.len());
-/// }
-///
-/// // Remove a book.
-/// books.remove("The Odyssey");
-///
-/// // Iterate over everything.
-/// for book in &books {
-///     println!("{}", book);
-/// }
-/// ```
-///
-/// The easiest way to use `HashSet` with a custom type is to derive
-/// [`Eq`] and [`Hash`]. We must also derive [`PartialEq`], this will in the
-/// future be implied by [`Eq`].
-///
-/// ```
-/// use hashbrown::HashSet;
-/// #[derive(Hash, Eq, PartialEq, Debug)]
-/// struct Viking {
-///     name: String,
-///     power: usize,
-/// }
-///
-/// let mut vikings = HashSet::new();
-///
-/// vikings.insert(Viking { name: "Einar".to_string(), power: 9 });
-/// vikings.insert(Viking { name: "Einar".to_string(), power: 9 });
-/// vikings.insert(Viking { name: "Olaf".to_string(), power: 4 });
-/// vikings.insert(Viking { name: "Harald".to_string(), power: 8 });
-///
-/// // Use derived implementation to print the vikings.
-/// for x in &vikings {
-///     println!("{:?}", x);
-/// }
-/// ```
-///
-/// A `HashSet` with fixed list of elements can be initialized from an array:
-///
-/// ```
-/// use hashbrown::HashSet;
-///
-/// let viking_names: HashSet<&'static str> =
-///     [ "Einar", "Olaf", "Harald" ].iter().cloned().collect();
-/// // use the values stored in the set
-/// ```
-///
-/// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html
-/// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-/// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-/// [`HashMap`]: struct.HashMap.html
-/// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html
-/// [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html
-pub struct HashSet<T, S = DefaultHashBuilder> {
-    pub(crate) map: HashMap<T, (), S>,
-}
-
-impl<T: Clone, S: Clone> Clone for HashSet<T, S> {
-    fn clone(&self) -> Self {
-        HashSet {
-            map: self.map.clone(),
-        }
-    }
-
-    fn clone_from(&mut self, source: &Self) {
-        self.map.clone_from(&source.map);
-    }
-}
-
-#[cfg(feature = "ahash")]
-impl<T> HashSet<T, DefaultHashBuilder> {
-    /// Creates an empty `HashSet`.
-    ///
-    /// The hash set is initially created with a capacity of 0, so it will not allocate until it
-    /// is first inserted into.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let set: HashSet<i32> = HashSet::new();
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn new() -> Self {
-        Self {
-            map: HashMap::new(),
-        }
-    }
-
-    /// Creates an empty `HashSet` with the specified capacity.
-    ///
-    /// The hash set will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash set will not allocate.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let set: HashSet<i32> = HashSet::with_capacity(10);
-    /// assert!(set.capacity() >= 10);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn with_capacity(capacity: usize) -> Self {
-        Self {
-            map: HashMap::with_capacity(capacity),
-        }
-    }
-}
-
-impl<T, S> HashSet<T, S> {
-    /// Creates a new empty hash set which will use the given hasher to hash
-    /// keys.
-    ///
-    /// The hash set is also created with the default initial capacity.
-    ///
-    /// Warning: `hasher` is normally randomly generated, and
-    /// is designed to allow `HashSet`s to be resistant to attacks that
-    /// cause many collisions and very poor performance. Setting it
-    /// manually using this function can expose a DoS attack vector.
-    ///
-    /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
-    /// the HashMap to be useful, see its documentation for details.
-    ///
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// use hashbrown::hash_map::DefaultHashBuilder;
-    ///
-    /// let s = DefaultHashBuilder::default();
-    /// let mut set = HashSet::with_hasher(s);
-    /// set.insert(2);
-    /// ```
-    ///
-    /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub const fn with_hasher(hasher: S) -> Self {
-        Self {
-            map: HashMap::with_hasher(hasher),
-        }
-    }
-
-    /// Creates an empty `HashSet` with the specified capacity, using
-    /// `hasher` to hash the keys.
-    ///
-    /// The hash set will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash set will not allocate.
-    ///
-    /// Warning: `hasher` is normally randomly generated, and
-    /// is designed to allow `HashSet`s to be resistant to attacks that
-    /// cause many collisions and very poor performance. Setting it
-    /// manually using this function can expose a DoS attack vector.
-    ///
-    /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
-    /// the HashMap to be useful, see its documentation for details.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// use hashbrown::hash_map::DefaultHashBuilder;
-    ///
-    /// let s = DefaultHashBuilder::default();
-    /// let mut set = HashSet::with_capacity_and_hasher(10, s);
-    /// set.insert(1);
-    /// ```
-    ///
-    /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
-        Self {
-            map: HashMap::with_capacity_and_hasher(capacity, hasher),
-        }
-    }
-
-    /// Returns the number of elements the set can hold without reallocating.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let set: HashSet<i32> = HashSet::with_capacity(100);
-    /// assert!(set.capacity() >= 100);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn capacity(&self) -> usize {
-        self.map.capacity()
-    }
-
-    /// An iterator visiting all elements in arbitrary order.
-    /// The iterator element type is `&'a T`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let mut set = HashSet::new();
-    /// set.insert("a");
-    /// set.insert("b");
-    ///
-    /// // Will print in an arbitrary order.
-    /// for x in set.iter() {
-    ///     println!("{}", x);
-    /// }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn iter(&self) -> Iter<'_, T> {
-        Iter {
-            iter: self.map.keys(),
-        }
-    }
-
-    /// Returns the number of elements in the set.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut v = HashSet::new();
-    /// assert_eq!(v.len(), 0);
-    /// v.insert(1);
-    /// assert_eq!(v.len(), 1);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn len(&self) -> usize {
-        self.map.len()
-    }
-
-    /// Returns `true` if the set contains no elements.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut v = HashSet::new();
-    /// assert!(v.is_empty());
-    /// v.insert(1);
-    /// assert!(!v.is_empty());
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn is_empty(&self) -> bool {
-        self.map.is_empty()
-    }
-
-    /// Clears the set, returning all elements in an iterator.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// assert!(!set.is_empty());
-    ///
-    /// // print 1, 2, 3 in an arbitrary order
-    /// for i in set.drain() {
-    ///     println!("{}", i);
-    /// }
-    ///
-    /// assert!(set.is_empty());
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn drain(&mut self) -> Drain<'_, T> {
-        Drain {
-            iter: self.map.drain(),
-        }
-    }
-
-    /// Retains only the elements specified by the predicate.
-    ///
-    /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let xs = [1,2,3,4,5,6];
-    /// let mut set: HashSet<i32> = xs.iter().cloned().collect();
-    /// set.retain(|&k| k % 2 == 0);
-    /// assert_eq!(set.len(), 3);
-    /// ```
-    pub fn retain<F>(&mut self, mut f: F)
-    where
-        F: FnMut(&T) -> bool,
-    {
-        self.map.retain(|k, _| f(k));
-    }
-
-    /// Drains elements which are true under the given predicate,
-    /// and returns an iterator over the removed items.
-    ///
-    /// In other words, move all elements `e` such that `f(&e)` returns `true` out
-    /// into another iterator.
-    ///
-    /// When the returned DrainedFilter is dropped, any remaining elements that satisfy
-    /// the predicate are dropped from the set.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set: HashSet<i32> = (0..8).collect();
-    /// let drained: HashSet<i32> = set.drain_filter(|v| v % 2 == 0).collect();
-    ///
-    /// let mut evens = drained.into_iter().collect::<Vec<_>>();
-    /// let mut odds = set.into_iter().collect::<Vec<_>>();
-    /// evens.sort();
-    /// odds.sort();
-    ///
-    /// assert_eq!(evens, vec![0, 2, 4, 6]);
-    /// assert_eq!(odds, vec![1, 3, 5, 7]);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn drain_filter<F>(&mut self, f: F) -> DrainFilter<'_, T, F>
-    where
-        F: FnMut(&T) -> bool,
-    {
-        DrainFilter {
-            f,
-            inner: DrainFilterInner {
-                iter: unsafe { self.map.table.iter() },
-                table: &mut self.map.table,
-            },
-        }
-    }
-
-    /// Clears the set, removing all values.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut v = HashSet::new();
-    /// v.insert(1);
-    /// v.clear();
-    /// assert!(v.is_empty());
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn clear(&mut self) {
-        self.map.clear()
-    }
-
-    /// Returns a reference to the set's [`BuildHasher`].
-    ///
-    /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// use hashbrown::hash_map::DefaultHashBuilder;
-    ///
-    /// let hasher = DefaultHashBuilder::default();
-    /// let set: HashSet<i32> = HashSet::with_hasher(hasher);
-    /// let hasher: &DefaultHashBuilder = set.hasher();
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn hasher(&self) -> &S {
-        self.map.hasher()
-    }
-}
-
-impl<T, S> HashSet<T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-    /// Reserves capacity for at least `additional` more elements to be inserted
-    /// in the `HashSet`. The collection may reserve more space to avoid
-    /// frequent reallocations.
-    ///
-    /// # Panics
-    ///
-    /// Panics if the new allocation size overflows `usize`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let mut set: HashSet<i32> = HashSet::new();
-    /// set.reserve(10);
-    /// assert!(set.capacity() >= 10);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn reserve(&mut self, additional: usize) {
-        self.map.reserve(additional)
-    }
-
-    /// Tries to reserve capacity for at least `additional` more elements to be inserted
-    /// in the given `HashSet<K,V>`. The collection may reserve more space to avoid
-    /// frequent reallocations.
-    ///
-    /// # Errors
-    ///
-    /// If the capacity overflows, or the allocator reports a failure, then an error
-    /// is returned.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let mut set: HashSet<i32> = HashSet::new();
-    /// set.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
-        self.map.try_reserve(additional)
-    }
-
-    /// Shrinks the capacity of the set as much as possible. It will drop
-    /// down as much as possible while maintaining the internal rules
-    /// and possibly leaving some space in accordance with the resize policy.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set = HashSet::with_capacity(100);
-    /// set.insert(1);
-    /// set.insert(2);
-    /// assert!(set.capacity() >= 100);
-    /// set.shrink_to_fit();
-    /// assert!(set.capacity() >= 2);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn shrink_to_fit(&mut self) {
-        self.map.shrink_to_fit()
-    }
-
-    /// Shrinks the capacity of the set with a lower limit. It will drop
-    /// down no lower than the supplied limit while maintaining the internal rules
-    /// and possibly leaving some space in accordance with the resize policy.
-    ///
-    /// Panics if the current capacity is smaller than the supplied
-    /// minimum capacity.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set = HashSet::with_capacity(100);
-    /// set.insert(1);
-    /// set.insert(2);
-    /// assert!(set.capacity() >= 100);
-    /// set.shrink_to(10);
-    /// assert!(set.capacity() >= 10);
-    /// set.shrink_to(0);
-    /// assert!(set.capacity() >= 2);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn shrink_to(&mut self, min_capacity: usize) {
-        self.map.shrink_to(min_capacity)
-    }
-
-    /// Visits the values representing the difference,
-    /// i.e., the values that are in `self` but not in `other`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
-    ///
-    /// // Can be seen as `a - b`.
-    /// for x in a.difference(&b) {
-    ///     println!("{}", x); // Print 1
-    /// }
-    ///
-    /// let diff: HashSet<_> = a.difference(&b).collect();
-    /// assert_eq!(diff, [1].iter().collect());
-    ///
-    /// // Note that difference is not symmetric,
-    /// // and `b - a` means something else:
-    /// let diff: HashSet<_> = b.difference(&a).collect();
-    /// assert_eq!(diff, [4].iter().collect());
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn difference<'a>(&'a self, other: &'a Self) -> Difference<'a, T, S> {
-        Difference {
-            iter: self.iter(),
-            other,
-        }
-    }
-
-    /// Visits the values representing the symmetric difference,
-    /// i.e., the values that are in `self` or in `other` but not in both.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
-    ///
-    /// // Print 1, 4 in arbitrary order.
-    /// for x in a.symmetric_difference(&b) {
-    ///     println!("{}", x);
-    /// }
-    ///
-    /// let diff1: HashSet<_> = a.symmetric_difference(&b).collect();
-    /// let diff2: HashSet<_> = b.symmetric_difference(&a).collect();
-    ///
-    /// assert_eq!(diff1, diff2);
-    /// assert_eq!(diff1, [1, 4].iter().collect());
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn symmetric_difference<'a>(&'a self, other: &'a Self) -> SymmetricDifference<'a, T, S> {
-        SymmetricDifference {
-            iter: self.difference(other).chain(other.difference(self)),
-        }
-    }
-
-    /// Visits the values representing the intersection,
-    /// i.e., the values that are both in `self` and `other`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
-    ///
-    /// // Print 2, 3 in arbitrary order.
-    /// for x in a.intersection(&b) {
-    ///     println!("{}", x);
-    /// }
-    ///
-    /// let intersection: HashSet<_> = a.intersection(&b).collect();
-    /// assert_eq!(intersection, [2, 3].iter().collect());
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, T, S> {
-        let (smaller, larger) = if self.len() <= other.len() {
-            (self, other)
-        } else {
-            (other, self)
-        };
-        Intersection {
-            iter: smaller.iter(),
-            other: larger,
-        }
-    }
-
-    /// Visits the values representing the union,
-    /// i.e., all the values in `self` or `other`, without duplicates.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
-    ///
-    /// // Print 1, 2, 3, 4 in arbitrary order.
-    /// for x in a.union(&b) {
-    ///     println!("{}", x);
-    /// }
-    ///
-    /// let union: HashSet<_> = a.union(&b).collect();
-    /// assert_eq!(union, [1, 2, 3, 4].iter().collect());
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, T, S> {
-        let (smaller, larger) = if self.len() >= other.len() {
-            (self, other)
-        } else {
-            (other, self)
-        };
-        Union {
-            iter: larger.iter().chain(smaller.difference(larger)),
-        }
-    }
-
-    /// Returns `true` if the set contains a value.
-    ///
-    /// The value may be any borrowed form of the set's value type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the value type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// assert_eq!(set.contains(&1), true);
-    /// assert_eq!(set.contains(&4), false);
-    /// ```
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
-    where
-        T: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        self.map.contains_key(value)
-    }
-
-    /// Returns a reference to the value in the set, if any, that is equal to the given value.
-    ///
-    /// The value may be any borrowed form of the set's value type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the value type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// assert_eq!(set.get(&2), Some(&2));
-    /// assert_eq!(set.get(&4), None);
-    /// ```
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
-    where
-        T: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.map.get_key_value(value) {
-            Some((k, _)) => Some(k),
-            None => None,
-        }
-    }
-
-    /// Inserts the given `value` into the set if it is not present, then
-    /// returns a reference to the value in the set.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// assert_eq!(set.len(), 3);
-    /// assert_eq!(set.get_or_insert(2), &2);
-    /// assert_eq!(set.get_or_insert(100), &100);
-    /// assert_eq!(set.len(), 4); // 100 was inserted
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn get_or_insert(&mut self, value: T) -> &T {
-        // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
-        // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
-        self.map
-            .raw_entry_mut()
-            .from_key(&value)
-            .or_insert(value, ())
-            .0
-    }
-
-    /// Inserts an owned copy of the given `value` into the set if it is not
-    /// present, then returns a reference to the value in the set.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set: HashSet<String> = ["cat", "dog", "horse"]
-    ///     .iter().map(|&pet| pet.to_owned()).collect();
-    ///
-    /// assert_eq!(set.len(), 3);
-    /// for &pet in &["cat", "dog", "fish"] {
-    ///     let value = set.get_or_insert_owned(pet);
-    ///     assert_eq!(value, pet);
-    /// }
-    /// assert_eq!(set.len(), 4); // a new "fish" was inserted
-    /// ```
-    #[inline]
-    pub fn get_or_insert_owned<Q: ?Sized>(&mut self, value: &Q) -> &T
-    where
-        T: Borrow<Q>,
-        Q: Hash + Eq + ToOwned<Owned = T>,
-    {
-        // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
-        // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
-        self.map
-            .raw_entry_mut()
-            .from_key(value)
-            .or_insert_with(|| (value.to_owned(), ()))
-            .0
-    }
-
-    /// Inserts a value computed from `f` into the set if the given `value` is
-    /// not present, then returns a reference to the value in the set.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set: HashSet<String> = ["cat", "dog", "horse"]
-    ///     .iter().map(|&pet| pet.to_owned()).collect();
-    ///
-    /// assert_eq!(set.len(), 3);
-    /// for &pet in &["cat", "dog", "fish"] {
-    ///     let value = set.get_or_insert_with(pet, str::to_owned);
-    ///     assert_eq!(value, pet);
-    /// }
-    /// assert_eq!(set.len(), 4); // a new "fish" was inserted
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn get_or_insert_with<Q: ?Sized, F>(&mut self, value: &Q, f: F) -> &T
-    where
-        T: Borrow<Q>,
-        Q: Hash + Eq,
-        F: FnOnce(&Q) -> T,
-    {
-        // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
-        // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
-        self.map
-            .raw_entry_mut()
-            .from_key(value)
-            .or_insert_with(|| (f(value), ()))
-            .0
-    }
-
-    /// Returns `true` if `self` has no elements in common with `other`.
-    /// This is equivalent to checking for an empty intersection.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// let mut b = HashSet::new();
-    ///
-    /// assert_eq!(a.is_disjoint(&b), true);
-    /// b.insert(4);
-    /// assert_eq!(a.is_disjoint(&b), true);
-    /// b.insert(1);
-    /// assert_eq!(a.is_disjoint(&b), false);
-    /// ```
-    pub fn is_disjoint(&self, other: &Self) -> bool {
-        self.iter().all(|v| !other.contains(v))
-    }
-
-    /// Returns `true` if the set is a subset of another,
-    /// i.e., `other` contains at least all the values in `self`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let sup: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// let mut set = HashSet::new();
-    ///
-    /// assert_eq!(set.is_subset(&sup), true);
-    /// set.insert(2);
-    /// assert_eq!(set.is_subset(&sup), true);
-    /// set.insert(4);
-    /// assert_eq!(set.is_subset(&sup), false);
-    /// ```
-    pub fn is_subset(&self, other: &Self) -> bool {
-        self.len() <= other.len() && self.iter().all(|v| other.contains(v))
-    }
-
-    /// Returns `true` if the set is a superset of another,
-    /// i.e., `self` contains at least all the values in `other`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let sub: HashSet<_> = [1, 2].iter().cloned().collect();
-    /// let mut set = HashSet::new();
-    ///
-    /// assert_eq!(set.is_superset(&sub), false);
-    ///
-    /// set.insert(0);
-    /// set.insert(1);
-    /// assert_eq!(set.is_superset(&sub), false);
-    ///
-    /// set.insert(2);
-    /// assert_eq!(set.is_superset(&sub), true);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn is_superset(&self, other: &Self) -> bool {
-        other.is_subset(self)
-    }
-
-    /// Adds a value to the set.
-    ///
-    /// If the set did not have this value present, `true` is returned.
-    ///
-    /// If the set did have this value present, `false` is returned.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set = HashSet::new();
-    ///
-    /// assert_eq!(set.insert(2), true);
-    /// assert_eq!(set.insert(2), false);
-    /// assert_eq!(set.len(), 1);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn insert(&mut self, value: T) -> bool {
-        self.map.insert(value, ()).is_none()
-    }
-
-    /// Adds a value to the set, replacing the existing value, if any, that is equal to the given
-    /// one. Returns the replaced value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set = HashSet::new();
-    /// set.insert(Vec::<i32>::new());
-    ///
-    /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 0);
-    /// set.replace(Vec::with_capacity(10));
-    /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10);
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn replace(&mut self, value: T) -> Option<T> {
-        match self.map.entry(value) {
-            map::Entry::Occupied(occupied) => Some(occupied.replace_key()),
-            map::Entry::Vacant(vacant) => {
-                vacant.insert(());
-                None
-            }
-        }
-    }
-
-    /// Removes a value from the set. Returns whether the value was
-    /// present in the set.
-    ///
-    /// The value may be any borrowed form of the set's value type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the value type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set = HashSet::new();
-    ///
-    /// set.insert(2);
-    /// assert_eq!(set.remove(&2), true);
-    /// assert_eq!(set.remove(&2), false);
-    /// ```
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
-    where
-        T: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        self.map.remove(value).is_some()
-    }
-
-    /// Removes and returns the value in the set, if any, that is equal to the given one.
-    ///
-    /// The value may be any borrowed form of the set's value type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the value type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// assert_eq!(set.take(&2), Some(2));
-    /// assert_eq!(set.take(&2), None);
-    /// ```
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    #[cfg_attr(feature = "inline-more", inline)]
-    pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
-    where
-        T: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.map.remove_entry(value) {
-            Some((k, _)) => Some(k),
-            None => None,
-        }
-    }
-}
-
-impl<T, S> PartialEq for HashSet<T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-    fn eq(&self, other: &Self) -> bool {
-        if self.len() != other.len() {
-            return false;
-        }
-
-        self.iter().all(|key| other.contains(key))
-    }
-}
-
-impl<T, S> Eq for HashSet<T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-}
-
-impl<T, S> fmt::Debug for HashSet<T, S>
-where
-    T: Eq + Hash + fmt::Debug,
-    S: BuildHasher,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_set().entries(self.iter()).finish()
-    }
-}
-
-impl<T, S> FromIterator<T> for HashSet<T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher + Default,
-{
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
-        let mut set = Self::with_hasher(Default::default());
-        set.extend(iter);
-        set
-    }
-}
-
-impl<T, S> Extend<T> for HashSet<T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
-        self.map.extend(iter.into_iter().map(|k| (k, ())));
-    }
-
-    #[inline]
-    #[cfg(feature = "nightly")]
-    fn extend_one(&mut self, k: T) {
-        self.map.insert(k, ());
-    }
-
-    #[inline]
-    #[cfg(feature = "nightly")]
-    fn extend_reserve(&mut self, additional: usize) {
-        Extend::<(T, ())>::extend_reserve(&mut self.map, additional);
-    }
-}
-
-impl<'a, T, S> Extend<&'a T> for HashSet<T, S>
-where
-    T: 'a + Eq + Hash + Copy,
-    S: BuildHasher,
-{
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
-        self.extend(iter.into_iter().cloned());
-    }
-
-    #[inline]
-    #[cfg(feature = "nightly")]
-    fn extend_one(&mut self, k: &'a T) {
-        self.map.insert(*k, ());
-    }
-
-    #[inline]
-    #[cfg(feature = "nightly")]
-    fn extend_reserve(&mut self, additional: usize) {
-        Extend::<(T, ())>::extend_reserve(&mut self.map, additional);
-    }
-}
-
-impl<T, S> Default for HashSet<T, S>
-where
-    S: Default,
-{
-    /// Creates an empty `HashSet<T, S>` with the `Default` value for the hasher.
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn default() -> Self {
-        Self {
-            map: HashMap::default(),
-        }
-    }
-}
-
-impl<T, S> BitOr<&HashSet<T, S>> for &HashSet<T, S>
-where
-    T: Eq + Hash + Clone,
-    S: BuildHasher + Default,
-{
-    type Output = HashSet<T, S>;
-
-    /// Returns the union of `self` and `rhs` as a new `HashSet<T, S>`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
-    /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
-    ///
-    /// let set = &a | &b;
-    ///
-    /// let mut i = 0;
-    /// let expected = [1, 2, 3, 4, 5];
-    /// for x in &set {
-    ///     assert!(expected.contains(x));
-    ///     i += 1;
-    /// }
-    /// assert_eq!(i, expected.len());
-    /// ```
-    fn bitor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
-        self.union(rhs).cloned().collect()
-    }
-}
-
-impl<T, S> BitAnd<&HashSet<T, S>> for &HashSet<T, S>
-where
-    T: Eq + Hash + Clone,
-    S: BuildHasher + Default,
-{
-    type Output = HashSet<T, S>;
-
-    /// Returns the intersection of `self` and `rhs` as a new `HashSet<T, S>`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
-    /// let b: HashSet<_> = vec![2, 3, 4].into_iter().collect();
-    ///
-    /// let set = &a & &b;
-    ///
-    /// let mut i = 0;
-    /// let expected = [2, 3];
-    /// for x in &set {
-    ///     assert!(expected.contains(x));
-    ///     i += 1;
-    /// }
-    /// assert_eq!(i, expected.len());
-    /// ```
-    fn bitand(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
-        self.intersection(rhs).cloned().collect()
-    }
-}
-
-impl<T, S> BitXor<&HashSet<T, S>> for &HashSet<T, S>
-where
-    T: Eq + Hash + Clone,
-    S: BuildHasher + Default,
-{
-    type Output = HashSet<T, S>;
-
-    /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet<T, S>`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
-    /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
-    ///
-    /// let set = &a ^ &b;
-    ///
-    /// let mut i = 0;
-    /// let expected = [1, 2, 4, 5];
-    /// for x in &set {
-    ///     assert!(expected.contains(x));
-    ///     i += 1;
-    /// }
-    /// assert_eq!(i, expected.len());
-    /// ```
-    fn bitxor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
-        self.symmetric_difference(rhs).cloned().collect()
-    }
-}
-
-impl<T, S> Sub<&HashSet<T, S>> for &HashSet<T, S>
-where
-    T: Eq + Hash + Clone,
-    S: BuildHasher + Default,
-{
-    type Output = HashSet<T, S>;
-
-    /// Returns the difference of `self` and `rhs` as a new `HashSet<T, S>`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
-    /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
-    ///
-    /// let set = &a - &b;
-    ///
-    /// let mut i = 0;
-    /// let expected = [1, 2];
-    /// for x in &set {
-    ///     assert!(expected.contains(x));
-    ///     i += 1;
-    /// }
-    /// assert_eq!(i, expected.len());
-    /// ```
-    fn sub(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
-        self.difference(rhs).cloned().collect()
-    }
-}
-
-/// An iterator over the items of a `HashSet`.
-///
-/// This `struct` is created by the [`iter`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`HashSet`]: struct.HashSet.html
-/// [`iter`]: struct.HashSet.html#method.iter
-pub struct Iter<'a, K> {
-    iter: Keys<'a, K, ()>,
-}
-
-/// An owning iterator over the items of a `HashSet`.
-///
-/// This `struct` is created by the [`into_iter`] method on [`HashSet`]
-/// (provided by the `IntoIterator` trait). See its documentation for more.
-///
-/// [`HashSet`]: struct.HashSet.html
-/// [`into_iter`]: struct.HashSet.html#method.into_iter
-pub struct IntoIter<K> {
-    iter: map::IntoIter<K, ()>,
-}
-
-/// A draining iterator over the items of a `HashSet`.
-///
-/// This `struct` is created by the [`drain`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`HashSet`]: struct.HashSet.html
-/// [`drain`]: struct.HashSet.html#method.drain
-pub struct Drain<'a, K> {
-    iter: map::Drain<'a, K, ()>,
-}
-
-/// A draining iterator over entries of a `HashSet` which don't satisfy the predicate `f`.
-///
-/// This `struct` is created by the [`drain_filter`] method on [`HashSet`]. See its
-/// documentation for more.
-///
-/// [`drain_filter`]: struct.HashSet.html#method.drain_filter
-/// [`HashSet`]: struct.HashSet.html
-pub struct DrainFilter<'a, K, F>
-where
-    F: FnMut(&K) -> bool,
-{
-    f: F,
-    inner: DrainFilterInner<'a, K, ()>,
-}
-
-/// A lazy iterator producing elements in the intersection of `HashSet`s.
-///
-/// This `struct` is created by the [`intersection`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`HashSet`]: struct.HashSet.html
-/// [`intersection`]: struct.HashSet.html#method.intersection
-pub struct Intersection<'a, T, S> {
-    // iterator of the first set
-    iter: Iter<'a, T>,
-    // the second set
-    other: &'a HashSet<T, S>,
-}
-
-/// A lazy iterator producing elements in the difference of `HashSet`s.
-///
-/// This `struct` is created by the [`difference`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`HashSet`]: struct.HashSet.html
-/// [`difference`]: struct.HashSet.html#method.difference
-pub struct Difference<'a, T, S> {
-    // iterator of the first set
-    iter: Iter<'a, T>,
-    // the second set
-    other: &'a HashSet<T, S>,
-}
-
-/// A lazy iterator producing elements in the symmetric difference of `HashSet`s.
-///
-/// This `struct` is created by the [`symmetric_difference`] method on
-/// [`HashSet`]. See its documentation for more.
-///
-/// [`HashSet`]: struct.HashSet.html
-/// [`symmetric_difference`]: struct.HashSet.html#method.symmetric_difference
-pub struct SymmetricDifference<'a, T, S> {
-    iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>,
-}
-
-/// A lazy iterator producing elements in the union of `HashSet`s.
-///
-/// This `struct` is created by the [`union`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`HashSet`]: struct.HashSet.html
-/// [`union`]: struct.HashSet.html#method.union
-pub struct Union<'a, T, S> {
-    iter: Chain<Iter<'a, T>, Difference<'a, T, S>>,
-}
-
-impl<'a, T, S> IntoIterator for &'a HashSet<T, S> {
-    type Item = &'a T;
-    type IntoIter = Iter<'a, T>;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn into_iter(self) -> Iter<'a, T> {
-        self.iter()
-    }
-}
-
-impl<T, S> IntoIterator for HashSet<T, S> {
-    type Item = T;
-    type IntoIter = IntoIter<T>;
-
-    /// Creates a consuming iterator, that is, one that moves each value out
-    /// of the set in arbitrary order. The set cannot be used after calling
-    /// this.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let mut set = HashSet::new();
-    /// set.insert("a".to_string());
-    /// set.insert("b".to_string());
-    ///
-    /// // Not possible to collect to a Vec<String> with a regular `.iter()`.
-    /// let v: Vec<String> = set.into_iter().collect();
-    ///
-    /// // Will print in an arbitrary order.
-    /// for x in &v {
-    ///     println!("{}", x);
-    /// }
-    /// ```
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn into_iter(self) -> IntoIter<T> {
-        IntoIter {
-            iter: self.map.into_iter(),
-        }
-    }
-}
-
-impl<K> Clone for Iter<'_, K> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn clone(&self) -> Self {
-        Iter {
-            iter: self.iter.clone(),
-        }
-    }
-}
-impl<'a, K> Iterator for Iter<'a, K> {
-    type Item = &'a K;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<&'a K> {
-        self.iter.next()
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-impl<'a, K> ExactSizeIterator for Iter<'a, K> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn len(&self) -> usize {
-        self.iter.len()
-    }
-}
-impl<K> FusedIterator for Iter<'_, K> {}
-
-impl<K: fmt::Debug> fmt::Debug for Iter<'_, K> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-impl<K> Iterator for IntoIter<K> {
-    type Item = K;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<K> {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.iter.next() {
-            Some((k, _)) => Some(k),
-            None => None,
-        }
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-impl<K> ExactSizeIterator for IntoIter<K> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn len(&self) -> usize {
-        self.iter.len()
-    }
-}
-impl<K> FusedIterator for IntoIter<K> {}
-
-impl<K: fmt::Debug> fmt::Debug for IntoIter<K> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let entries_iter = self.iter.iter().map(|(k, _)| k);
-        f.debug_list().entries(entries_iter).finish()
-    }
-}
-
-impl<K> Iterator for Drain<'_, K> {
-    type Item = K;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<K> {
-        // Avoid `Option::map` because it bloats LLVM IR.
-        match self.iter.next() {
-            Some((k, _)) => Some(k),
-            None => None,
-        }
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-impl<K> ExactSizeIterator for Drain<'_, K> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn len(&self) -> usize {
-        self.iter.len()
-    }
-}
-impl<K> FusedIterator for Drain<'_, K> {}
-
-impl<K: fmt::Debug> fmt::Debug for Drain<'_, K> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let entries_iter = self.iter.iter().map(|(k, _)| k);
-        f.debug_list().entries(entries_iter).finish()
-    }
-}
-
-impl<'a, K, F> Drop for DrainFilter<'a, K, F>
-where
-    F: FnMut(&K) -> bool,
-{
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn drop(&mut self) {
-        while let Some(item) = self.next() {
-            let guard = ConsumeAllOnDrop(self);
-            drop(item);
-            mem::forget(guard);
-        }
-    }
-}
-
-impl<K, F> Iterator for DrainFilter<'_, K, F>
-where
-    F: FnMut(&K) -> bool,
-{
-    type Item = K;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<Self::Item> {
-        let f = &mut self.f;
-        let (k, _) = self.inner.next(&mut |k, _| f(k))?;
-        Some(k)
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (0, self.inner.iter.size_hint().1)
-    }
-}
-
-impl<K, F> FusedIterator for DrainFilter<'_, K, F> where F: FnMut(&K) -> bool {}
-
-impl<T, S> Clone for Intersection<'_, T, S> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn clone(&self) -> Self {
-        Intersection {
-            iter: self.iter.clone(),
-            ..*self
-        }
-    }
-}
-
-impl<'a, T, S> Iterator for Intersection<'a, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-    type Item = &'a T;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<&'a T> {
-        loop {
-            let elt = self.iter.next()?;
-            if self.other.contains(elt) {
-                return Some(elt);
-            }
-        }
-    }
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (_, upper) = self.iter.size_hint();
-        (0, upper)
-    }
-}
-
-impl<T, S> fmt::Debug for Intersection<'_, T, S>
-where
-    T: fmt::Debug + Eq + Hash,
-    S: BuildHasher,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-impl<T, S> FusedIterator for Intersection<'_, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-}
-
-impl<T, S> Clone for Difference<'_, T, S> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn clone(&self) -> Self {
-        Difference {
-            iter: self.iter.clone(),
-            ..*self
-        }
-    }
-}
-
-impl<'a, T, S> Iterator for Difference<'a, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-    type Item = &'a T;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<&'a T> {
-        loop {
-            let elt = self.iter.next()?;
-            if !self.other.contains(elt) {
-                return Some(elt);
-            }
-        }
-    }
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (_, upper) = self.iter.size_hint();
-        (0, upper)
-    }
-}
-
-impl<T, S> FusedIterator for Difference<'_, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-}
-
-impl<T, S> fmt::Debug for Difference<'_, T, S>
-where
-    T: fmt::Debug + Eq + Hash,
-    S: BuildHasher,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-impl<T, S> Clone for SymmetricDifference<'_, T, S> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn clone(&self) -> Self {
-        SymmetricDifference {
-            iter: self.iter.clone(),
-        }
-    }
-}
-
-impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-    type Item = &'a T;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<&'a T> {
-        self.iter.next()
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-impl<T, S> FusedIterator for SymmetricDifference<'_, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-}
-
-impl<T, S> fmt::Debug for SymmetricDifference<'_, T, S>
-where
-    T: fmt::Debug + Eq + Hash,
-    S: BuildHasher,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-impl<T, S> Clone for Union<'_, T, S> {
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn clone(&self) -> Self {
-        Union {
-            iter: self.iter.clone(),
-        }
-    }
-}
-
-impl<T, S> FusedIterator for Union<'_, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-}
-
-impl<T, S> fmt::Debug for Union<'_, T, S>
-where
-    T: fmt::Debug + Eq + Hash,
-    S: BuildHasher,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-impl<'a, T, S> Iterator for Union<'a, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-    type Item = &'a T;
-
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn next(&mut self) -> Option<&'a T> {
-        self.iter.next()
-    }
-    #[cfg_attr(feature = "inline-more", inline)]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-#[allow(dead_code)]
-fn assert_covariance() {
-    fn set<'new>(v: HashSet<&'static str>) -> HashSet<&'new str> {
-        v
-    }
-    fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> {
-        v
-    }
-    fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> {
-        v
-    }
-    fn difference<'a, 'new>(
-        v: Difference<'a, &'static str, DefaultHashBuilder>,
-    ) -> Difference<'a, &'new str, DefaultHashBuilder> {
-        v
-    }
-    fn symmetric_difference<'a, 'new>(
-        v: SymmetricDifference<'a, &'static str, DefaultHashBuilder>,
-    ) -> SymmetricDifference<'a, &'new str, DefaultHashBuilder> {
-        v
-    }
-    fn intersection<'a, 'new>(
-        v: Intersection<'a, &'static str, DefaultHashBuilder>,
-    ) -> Intersection<'a, &'new str, DefaultHashBuilder> {
-        v
-    }
-    fn union<'a, 'new>(
-        v: Union<'a, &'static str, DefaultHashBuilder>,
-    ) -> Union<'a, &'new str, DefaultHashBuilder> {
-        v
-    }
-    fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
-        d
-    }
-}
-
-#[cfg(test)]
-mod test_set {
-    use super::super::map::DefaultHashBuilder;
-    use super::HashSet;
-    use std::vec::Vec;
-
-    #[test]
-    fn test_zero_capacities() {
-        type HS = HashSet<i32>;
-
-        let s = HS::new();
-        assert_eq!(s.capacity(), 0);
-
-        let s = HS::default();
-        assert_eq!(s.capacity(), 0);
-
-        let s = HS::with_hasher(DefaultHashBuilder::default());
-        assert_eq!(s.capacity(), 0);
-
-        let s = HS::with_capacity(0);
-        assert_eq!(s.capacity(), 0);
-
-        let s = HS::with_capacity_and_hasher(0, DefaultHashBuilder::default());
-        assert_eq!(s.capacity(), 0);
-
-        let mut s = HS::new();
-        s.insert(1);
-        s.insert(2);
-        s.remove(&1);
-        s.remove(&2);
-        s.shrink_to_fit();
-        assert_eq!(s.capacity(), 0);
-
-        let mut s = HS::new();
-        s.reserve(0);
-        assert_eq!(s.capacity(), 0);
-    }
-
-    #[test]
-    fn test_disjoint() {
-        let mut xs = HashSet::new();
-        let mut ys = HashSet::new();
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(xs.insert(5));
-        assert!(ys.insert(11));
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(xs.insert(7));
-        assert!(xs.insert(19));
-        assert!(xs.insert(4));
-        assert!(ys.insert(2));
-        assert!(ys.insert(-11));
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(ys.insert(7));
-        assert!(!xs.is_disjoint(&ys));
-        assert!(!ys.is_disjoint(&xs));
-    }
-
-    #[test]
-    fn test_subset_and_superset() {
-        let mut a = HashSet::new();
-        assert!(a.insert(0));
-        assert!(a.insert(5));
-        assert!(a.insert(11));
-        assert!(a.insert(7));
-
-        let mut b = HashSet::new();
-        assert!(b.insert(0));
-        assert!(b.insert(7));
-        assert!(b.insert(19));
-        assert!(b.insert(250));
-        assert!(b.insert(11));
-        assert!(b.insert(200));
-
-        assert!(!a.is_subset(&b));
-        assert!(!a.is_superset(&b));
-        assert!(!b.is_subset(&a));
-        assert!(!b.is_superset(&a));
-
-        assert!(b.insert(5));
-
-        assert!(a.is_subset(&b));
-        assert!(!a.is_superset(&b));
-        assert!(!b.is_subset(&a));
-        assert!(b.is_superset(&a));
-    }
-
-    #[test]
-    fn test_iterate() {
-        let mut a = HashSet::new();
-        for i in 0..32 {
-            assert!(a.insert(i));
-        }
-        let mut observed: u32 = 0;
-        for k in &a {
-            observed |= 1 << *k;
-        }
-        assert_eq!(observed, 0xFFFF_FFFF);
-    }
-
-    #[test]
-    fn test_intersection() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(11));
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(77));
-        assert!(a.insert(103));
-        assert!(a.insert(5));
-        assert!(a.insert(-5));
-
-        assert!(b.insert(2));
-        assert!(b.insert(11));
-        assert!(b.insert(77));
-        assert!(b.insert(-9));
-        assert!(b.insert(-42));
-        assert!(b.insert(5));
-        assert!(b.insert(3));
-
-        let mut i = 0;
-        let expected = [3, 5, 11, 77];
-        for x in a.intersection(&b) {
-            assert!(expected.contains(x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_difference() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-
-        assert!(b.insert(3));
-        assert!(b.insert(9));
-
-        let mut i = 0;
-        let expected = [1, 5, 11];
-        for x in a.difference(&b) {
-            assert!(expected.contains(x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_symmetric_difference() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-
-        assert!(b.insert(-2));
-        assert!(b.insert(3));
-        assert!(b.insert(9));
-        assert!(b.insert(14));
-        assert!(b.insert(22));
-
-        let mut i = 0;
-        let expected = [-2, 1, 5, 11, 14, 22];
-        for x in a.symmetric_difference(&b) {
-            assert!(expected.contains(x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_union() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-        assert!(a.insert(16));
-        assert!(a.insert(19));
-        assert!(a.insert(24));
-
-        assert!(b.insert(-2));
-        assert!(b.insert(1));
-        assert!(b.insert(5));
-        assert!(b.insert(9));
-        assert!(b.insert(13));
-        assert!(b.insert(19));
-
-        let mut i = 0;
-        let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
-        for x in a.union(&b) {
-            assert!(expected.contains(x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_from_iter() {
-        let xs = [1, 2, 2, 3, 4, 5, 6, 7, 8, 9];
-
-        let set: HashSet<_> = xs.iter().cloned().collect();
-
-        for x in &xs {
-            assert!(set.contains(x));
-        }
-
-        assert_eq!(set.iter().len(), xs.len() - 1);
-    }
-
-    #[test]
-    fn test_move_iter() {
-        let hs = {
-            let mut hs = HashSet::new();
-
-            hs.insert('a');
-            hs.insert('b');
-
-            hs
-        };
-
-        let v = hs.into_iter().collect::<Vec<char>>();
-        assert!(v == ['a', 'b'] || v == ['b', 'a']);
-    }
-
-    #[test]
-    fn test_eq() {
-        // These constants once happened to expose a bug in insert().
-        // I'm keeping them around to prevent a regression.
-        let mut s1 = HashSet::new();
-
-        s1.insert(1);
-        s1.insert(2);
-        s1.insert(3);
-
-        let mut s2 = HashSet::new();
-
-        s2.insert(1);
-        s2.insert(2);
-
-        assert!(s1 != s2);
-
-        s2.insert(3);
-
-        assert_eq!(s1, s2);
-    }
-
-    #[test]
-    fn test_show() {
-        let mut set = HashSet::new();
-        let empty = HashSet::<i32>::new();
-
-        set.insert(1);
-        set.insert(2);
-
-        let set_str = format!("{:?}", set);
-
-        assert!(set_str == "{1, 2}" || set_str == "{2, 1}");
-        assert_eq!(format!("{:?}", empty), "{}");
-    }
-
-    #[test]
-    fn test_trivial_drain() {
-        let mut s = HashSet::<i32>::new();
-        for _ in s.drain() {}
-        assert!(s.is_empty());
-        drop(s);
-
-        let mut s = HashSet::<i32>::new();
-        drop(s.drain());
-        assert!(s.is_empty());
-    }
-
-    #[test]
-    fn test_drain() {
-        let mut s: HashSet<_> = (1..100).collect();
-
-        // try this a bunch of times to make sure we don't screw up internal state.
-        for _ in 0..20 {
-            assert_eq!(s.len(), 99);
-
-            {
-                let mut last_i = 0;
-                let mut d = s.drain();
-                for (i, x) in d.by_ref().take(50).enumerate() {
-                    last_i = i;
-                    assert!(x != 0);
-                }
-                assert_eq!(last_i, 49);
-            }
-
-            for _ in &s {
-                panic!("s should be empty!");
-            }
-
-            // reset to try again.
-            s.extend(1..100);
-        }
-    }
-
-    #[test]
-    fn test_replace() {
-        use core::hash;
-
-        #[derive(Debug)]
-        struct Foo(&'static str, i32);
-
-        impl PartialEq for Foo {
-            fn eq(&self, other: &Self) -> bool {
-                self.0 == other.0
-            }
-        }
-
-        impl Eq for Foo {}
-
-        impl hash::Hash for Foo {
-            fn hash<H: hash::Hasher>(&self, h: &mut H) {
-                self.0.hash(h);
-            }
-        }
-
-        let mut s = HashSet::new();
-        assert_eq!(s.replace(Foo("a", 1)), None);
-        assert_eq!(s.len(), 1);
-        assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1)));
-        assert_eq!(s.len(), 1);
-
-        let mut it = s.iter();
-        assert_eq!(it.next(), Some(&Foo("a", 2)));
-        assert_eq!(it.next(), None);
-    }
-
-    #[test]
-    fn test_extend_ref() {
-        let mut a = HashSet::new();
-        a.insert(1);
-
-        a.extend(&[2, 3, 4]);
-
-        assert_eq!(a.len(), 4);
-        assert!(a.contains(&1));
-        assert!(a.contains(&2));
-        assert!(a.contains(&3));
-        assert!(a.contains(&4));
-
-        let mut b = HashSet::new();
-        b.insert(5);
-        b.insert(6);
-
-        a.extend(&b);
-
-        assert_eq!(a.len(), 6);
-        assert!(a.contains(&1));
-        assert!(a.contains(&2));
-        assert!(a.contains(&3));
-        assert!(a.contains(&4));
-        assert!(a.contains(&5));
-        assert!(a.contains(&6));
-    }
-
-    #[test]
-    fn test_retain() {
-        let xs = [1, 2, 3, 4, 5, 6];
-        let mut set: HashSet<i32> = xs.iter().cloned().collect();
-        set.retain(|&k| k % 2 == 0);
-        assert_eq!(set.len(), 3);
-        assert!(set.contains(&2));
-        assert!(set.contains(&4));
-        assert!(set.contains(&6));
-    }
-
-    #[test]
-    fn test_drain_filter() {
-        {
-            let mut set: HashSet<i32> = (0..8).collect();
-            let drained = set.drain_filter(|&k| k % 2 == 0);
-            let mut out = drained.collect::<Vec<_>>();
-            out.sort_unstable();
-            assert_eq!(vec![0, 2, 4, 6], out);
-            assert_eq!(set.len(), 4);
-        }
-        {
-            let mut set: HashSet<i32> = (0..8).collect();
-            drop(set.drain_filter(|&k| k % 2 == 0));
-            assert_eq!(set.len(), 4, "Removes non-matching items on drop");
-        }
-    }
-
-    #[test]
-    fn test_const_with_hasher() {
-        use core::hash::BuildHasher;
-        use std::collections::hash_map::DefaultHasher;
-
-        #[derive(Clone)]
-        struct MyHasher;
-        impl BuildHasher for MyHasher {
-            type Hasher = DefaultHasher;
-
-            fn build_hasher(&self) -> DefaultHasher {
-                DefaultHasher::new()
-            }
-        }
-
-        const EMPTY_SET: HashSet<u32, MyHasher> = HashSet::with_hasher(MyHasher);
-
-        let mut set = EMPTY_SET.clone();
-        set.insert(19);
-        assert!(set.contains(&19));
-    }
-}
diff --git a/vendor/hashbrown-0.9.1/tests/hasher.rs b/vendor/hashbrown-0.9.1/tests/hasher.rs
deleted file mode 100644 (file)
index e455e3d..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-//! Sanity check that alternate hashers work correctly.
-
-#![cfg(not(miri))] // FIXME: takes too long
-
-use hashbrown::HashSet;
-use std::hash::{BuildHasher, BuildHasherDefault, Hasher};
-
-fn check<S: BuildHasher + Default>() {
-    let range = 0..1_000;
-
-    let mut set = HashSet::<i32, S>::default();
-    set.extend(range.clone());
-
-    assert!(!set.contains(&i32::min_value()));
-    assert!(!set.contains(&(range.start - 1)));
-    for i in range.clone() {
-        assert!(set.contains(&i));
-    }
-    assert!(!set.contains(&range.end));
-    assert!(!set.contains(&i32::max_value()));
-}
-
-/// Use hashbrown's default hasher.
-#[test]
-fn default() {
-    check::<hashbrown::hash_map::DefaultHashBuilder>();
-}
-
-/// Use std's default hasher.
-#[test]
-fn random_state() {
-    check::<std::collections::hash_map::RandomState>();
-}
-
-/// Use a constant 0 hash.
-#[test]
-fn zero() {
-    #[derive(Default)]
-    struct ZeroHasher;
-
-    impl Hasher for ZeroHasher {
-        fn finish(&self) -> u64 {
-            0
-        }
-        fn write(&mut self, _: &[u8]) {}
-    }
-
-    check::<BuildHasherDefault<ZeroHasher>>();
-}
-
-/// Use a constant maximum hash.
-#[test]
-fn max() {
-    #[derive(Default)]
-    struct MaxHasher;
-
-    impl Hasher for MaxHasher {
-        fn finish(&self) -> u64 {
-            u64::max_value()
-        }
-        fn write(&mut self, _: &[u8]) {}
-    }
-
-    check::<BuildHasherDefault<MaxHasher>>();
-}
diff --git a/vendor/hashbrown-0.9.1/tests/rayon.rs b/vendor/hashbrown-0.9.1/tests/rayon.rs
deleted file mode 100644 (file)
index 39b4770..0000000
+++ /dev/null
@@ -1,533 +0,0 @@
-#![cfg(feature = "rayon")]
-
-#[macro_use]
-extern crate lazy_static;
-
-use hashbrown::{HashMap, HashSet};
-use rayon::iter::{
-    IntoParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelExtend,
-    ParallelIterator,
-};
-
-macro_rules! assert_eq3 {
-    ($e1:expr, $e2:expr, $e3:expr) => {{
-        assert_eq!($e1, $e2);
-        assert_eq!($e1, $e3);
-        assert_eq!($e2, $e3);
-    }};
-}
-
-lazy_static! {
-    static ref MAP_EMPTY: HashMap<char, u32> = HashMap::new();
-    static ref MAP: HashMap<char, u32> = {
-        let mut m = HashMap::new();
-        m.insert('b', 20);
-        m.insert('a', 10);
-        m.insert('c', 30);
-        m.insert('e', 50);
-        m.insert('f', 60);
-        m.insert('d', 40);
-        m
-    };
-}
-
-#[test]
-fn map_seq_par_equivalence_iter_empty() {
-    let vec_seq = MAP_EMPTY.iter().collect::<Vec<_>>();
-    let vec_par = MAP_EMPTY.par_iter().collect::<Vec<_>>();
-
-    assert_eq3!(vec_seq, vec_par, []);
-}
-
-#[test]
-fn map_seq_par_equivalence_iter() {
-    let mut vec_seq = MAP.iter().collect::<Vec<_>>();
-    let mut vec_par = MAP.par_iter().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = [
-        (&'a', &10),
-        (&'b', &20),
-        (&'c', &30),
-        (&'d', &40),
-        (&'e', &50),
-        (&'f', &60),
-    ];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-#[test]
-fn map_seq_par_equivalence_keys_empty() {
-    let vec_seq = MAP_EMPTY.keys().collect::<Vec<&char>>();
-    let vec_par = MAP_EMPTY.par_keys().collect::<Vec<&char>>();
-
-    let expected: [&char; 0] = [];
-
-    assert_eq3!(vec_seq, vec_par, expected);
-}
-
-#[test]
-fn map_seq_par_equivalence_keys() {
-    let mut vec_seq = MAP.keys().collect::<Vec<_>>();
-    let mut vec_par = MAP.par_keys().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = [&'a', &'b', &'c', &'d', &'e', &'f'];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-#[test]
-fn map_seq_par_equivalence_values_empty() {
-    let vec_seq = MAP_EMPTY.values().collect::<Vec<_>>();
-    let vec_par = MAP_EMPTY.par_values().collect::<Vec<_>>();
-
-    let expected: [&u32; 0] = [];
-
-    assert_eq3!(vec_seq, vec_par, expected);
-}
-
-#[test]
-fn map_seq_par_equivalence_values() {
-    let mut vec_seq = MAP.values().collect::<Vec<_>>();
-    let mut vec_par = MAP.par_values().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = [&10, &20, &30, &40, &50, &60];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-#[test]
-fn map_seq_par_equivalence_iter_mut_empty() {
-    let mut map1 = MAP_EMPTY.clone();
-    let mut map2 = MAP_EMPTY.clone();
-
-    let vec_seq = map1.iter_mut().collect::<Vec<_>>();
-    let vec_par = map2.par_iter_mut().collect::<Vec<_>>();
-
-    assert_eq3!(vec_seq, vec_par, []);
-}
-
-#[test]
-fn map_seq_par_equivalence_iter_mut() {
-    let mut map1 = MAP.clone();
-    let mut map2 = MAP.clone();
-
-    let mut vec_seq = map1.iter_mut().collect::<Vec<_>>();
-    let mut vec_par = map2.par_iter_mut().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = [
-        (&'a', &mut 10),
-        (&'b', &mut 20),
-        (&'c', &mut 30),
-        (&'d', &mut 40),
-        (&'e', &mut 50),
-        (&'f', &mut 60),
-    ];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-#[test]
-fn map_seq_par_equivalence_values_mut_empty() {
-    let mut map1 = MAP_EMPTY.clone();
-    let mut map2 = MAP_EMPTY.clone();
-
-    let vec_seq = map1.values_mut().collect::<Vec<_>>();
-    let vec_par = map2.par_values_mut().collect::<Vec<_>>();
-
-    let expected: [&u32; 0] = [];
-
-    assert_eq3!(vec_seq, vec_par, expected);
-}
-
-#[test]
-fn map_seq_par_equivalence_values_mut() {
-    let mut map1 = MAP.clone();
-    let mut map2 = MAP.clone();
-
-    let mut vec_seq = map1.values_mut().collect::<Vec<_>>();
-    let mut vec_par = map2.par_values_mut().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = [&mut 10, &mut 20, &mut 30, &mut 40, &mut 50, &mut 60];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-#[test]
-fn map_seq_par_equivalence_into_iter_empty() {
-    let vec_seq = MAP_EMPTY.clone().into_iter().collect::<Vec<_>>();
-    let vec_par = MAP_EMPTY.clone().into_par_iter().collect::<Vec<_>>();
-
-    assert_eq3!(vec_seq, vec_par, []);
-}
-
-#[test]
-fn map_seq_par_equivalence_into_iter() {
-    let mut vec_seq = MAP.clone().into_iter().collect::<Vec<_>>();
-    let mut vec_par = MAP.clone().into_par_iter().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = [
-        ('a', 10),
-        ('b', 20),
-        ('c', 30),
-        ('d', 40),
-        ('e', 50),
-        ('f', 60),
-    ];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-lazy_static! {
-    static ref MAP_VEC_EMPTY: Vec<(char, u32)> = vec![];
-    static ref MAP_VEC: Vec<(char, u32)> = vec![
-        ('b', 20),
-        ('a', 10),
-        ('c', 30),
-        ('e', 50),
-        ('f', 60),
-        ('d', 40),
-    ];
-}
-
-#[test]
-fn map_seq_par_equivalence_collect_empty() {
-    let map_expected = MAP_EMPTY.clone();
-    let map_seq = MAP_VEC_EMPTY.clone().into_iter().collect::<HashMap<_, _>>();
-    let map_par = MAP_VEC_EMPTY
-        .clone()
-        .into_par_iter()
-        .collect::<HashMap<_, _>>();
-
-    assert_eq!(map_seq, map_par);
-    assert_eq!(map_seq, map_expected);
-    assert_eq!(map_par, map_expected);
-}
-
-#[test]
-fn map_seq_par_equivalence_collect() {
-    let map_expected = MAP.clone();
-    let map_seq = MAP_VEC.clone().into_iter().collect::<HashMap<_, _>>();
-    let map_par = MAP_VEC.clone().into_par_iter().collect::<HashMap<_, _>>();
-
-    assert_eq!(map_seq, map_par);
-    assert_eq!(map_seq, map_expected);
-    assert_eq!(map_par, map_expected);
-}
-
-lazy_static! {
-    static ref MAP_EXISTING_EMPTY: HashMap<char, u32> = HashMap::new();
-    static ref MAP_EXISTING: HashMap<char, u32> = {
-        let mut m = HashMap::new();
-        m.insert('b', 20);
-        m.insert('a', 10);
-        m
-    };
-    static ref MAP_EXTENSION_EMPTY: Vec<(char, u32)> = vec![];
-    static ref MAP_EXTENSION: Vec<(char, u32)> = vec![('c', 30), ('e', 50), ('f', 60), ('d', 40),];
-}
-
-#[test]
-fn map_seq_par_equivalence_existing_empty_extend_empty() {
-    let expected = HashMap::new();
-    let mut map_seq = MAP_EXISTING_EMPTY.clone();
-    let mut map_par = MAP_EXISTING_EMPTY.clone();
-
-    map_seq.extend(MAP_EXTENSION_EMPTY.iter().cloned());
-    map_par.par_extend(MAP_EXTENSION_EMPTY.par_iter().cloned());
-
-    assert_eq3!(map_seq, map_par, expected);
-}
-
-#[test]
-fn map_seq_par_equivalence_existing_empty_extend() {
-    let expected = MAP_EXTENSION.iter().cloned().collect::<HashMap<_, _>>();
-    let mut map_seq = MAP_EXISTING_EMPTY.clone();
-    let mut map_par = MAP_EXISTING_EMPTY.clone();
-
-    map_seq.extend(MAP_EXTENSION.iter().cloned());
-    map_par.par_extend(MAP_EXTENSION.par_iter().cloned());
-
-    assert_eq3!(map_seq, map_par, expected);
-}
-
-#[test]
-fn map_seq_par_equivalence_existing_extend_empty() {
-    let expected = MAP_EXISTING.clone();
-    let mut map_seq = MAP_EXISTING.clone();
-    let mut map_par = MAP_EXISTING.clone();
-
-    map_seq.extend(MAP_EXTENSION_EMPTY.iter().cloned());
-    map_par.par_extend(MAP_EXTENSION_EMPTY.par_iter().cloned());
-
-    assert_eq3!(map_seq, map_par, expected);
-}
-
-#[test]
-fn map_seq_par_equivalence_existing_extend() {
-    let expected = MAP.clone();
-    let mut map_seq = MAP_EXISTING.clone();
-    let mut map_par = MAP_EXISTING.clone();
-
-    map_seq.extend(MAP_EXTENSION.iter().cloned());
-    map_par.par_extend(MAP_EXTENSION.par_iter().cloned());
-
-    assert_eq3!(map_seq, map_par, expected);
-}
-
-lazy_static! {
-    static ref SET_EMPTY: HashSet<char> = HashSet::new();
-    static ref SET: HashSet<char> = {
-        let mut s = HashSet::new();
-        s.insert('b');
-        s.insert('a');
-        s.insert('c');
-        s.insert('e');
-        s.insert('f');
-        s.insert('d');
-        s
-    };
-}
-
-#[test]
-fn set_seq_par_equivalence_iter_empty() {
-    let vec_seq = SET_EMPTY.iter().collect::<Vec<_>>();
-    let vec_par = SET_EMPTY.par_iter().collect::<Vec<_>>();
-
-    let expected: [&char; 0] = [];
-
-    assert_eq3!(vec_seq, vec_par, expected);
-}
-
-#[test]
-fn set_seq_par_equivalence_iter() {
-    let mut vec_seq = SET.iter().collect::<Vec<_>>();
-    let mut vec_par = SET.par_iter().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = [&'a', &'b', &'c', &'d', &'e', &'f'];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-#[test]
-fn set_seq_par_equivalence_into_iter_empty() {
-    let vec_seq = SET_EMPTY.clone().into_iter().collect::<Vec<_>>();
-    let vec_par = SET_EMPTY.clone().into_par_iter().collect::<Vec<_>>();
-
-    assert_eq3!(vec_seq, vec_par, []);
-}
-
-#[test]
-fn set_seq_par_equivalence_into_iter() {
-    let mut vec_seq = SET.clone().into_iter().collect::<Vec<_>>();
-    let mut vec_par = SET.clone().into_par_iter().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = ['a', 'b', 'c', 'd', 'e', 'f'];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-lazy_static! {
-    static ref SET_VEC_EMPTY: Vec<char> = vec![];
-    static ref SET_VEC: Vec<char> = vec!['b', 'a', 'c', 'e', 'f', 'd',];
-}
-
-#[test]
-fn set_seq_par_equivalence_collect_empty() {
-    let set_expected = SET_EMPTY.clone();
-    let set_seq = SET_VEC_EMPTY.clone().into_iter().collect::<HashSet<_>>();
-    let set_par = SET_VEC_EMPTY
-        .clone()
-        .into_par_iter()
-        .collect::<HashSet<_>>();
-
-    assert_eq!(set_seq, set_par);
-    assert_eq!(set_seq, set_expected);
-    assert_eq!(set_par, set_expected);
-}
-
-#[test]
-fn set_seq_par_equivalence_collect() {
-    let set_expected = SET.clone();
-    let set_seq = SET_VEC.clone().into_iter().collect::<HashSet<_>>();
-    let set_par = SET_VEC.clone().into_par_iter().collect::<HashSet<_>>();
-
-    assert_eq!(set_seq, set_par);
-    assert_eq!(set_seq, set_expected);
-    assert_eq!(set_par, set_expected);
-}
-
-lazy_static! {
-    static ref SET_EXISTING_EMPTY: HashSet<char> = HashSet::new();
-    static ref SET_EXISTING: HashSet<char> = {
-        let mut s = HashSet::new();
-        s.insert('b');
-        s.insert('a');
-        s
-    };
-    static ref SET_EXTENSION_EMPTY: Vec<char> = vec![];
-    static ref SET_EXTENSION: Vec<char> = vec!['c', 'e', 'f', 'd',];
-}
-
-#[test]
-fn set_seq_par_equivalence_existing_empty_extend_empty() {
-    let expected = HashSet::new();
-    let mut set_seq = SET_EXISTING_EMPTY.clone();
-    let mut set_par = SET_EXISTING_EMPTY.clone();
-
-    set_seq.extend(SET_EXTENSION_EMPTY.iter().cloned());
-    set_par.par_extend(SET_EXTENSION_EMPTY.par_iter().cloned());
-
-    assert_eq3!(set_seq, set_par, expected);
-}
-
-#[test]
-fn set_seq_par_equivalence_existing_empty_extend() {
-    let expected = SET_EXTENSION.iter().cloned().collect::<HashSet<_>>();
-    let mut set_seq = SET_EXISTING_EMPTY.clone();
-    let mut set_par = SET_EXISTING_EMPTY.clone();
-
-    set_seq.extend(SET_EXTENSION.iter().cloned());
-    set_par.par_extend(SET_EXTENSION.par_iter().cloned());
-
-    assert_eq3!(set_seq, set_par, expected);
-}
-
-#[test]
-fn set_seq_par_equivalence_existing_extend_empty() {
-    let expected = SET_EXISTING.clone();
-    let mut set_seq = SET_EXISTING.clone();
-    let mut set_par = SET_EXISTING.clone();
-
-    set_seq.extend(SET_EXTENSION_EMPTY.iter().cloned());
-    set_par.par_extend(SET_EXTENSION_EMPTY.par_iter().cloned());
-
-    assert_eq3!(set_seq, set_par, expected);
-}
-
-#[test]
-fn set_seq_par_equivalence_existing_extend() {
-    let expected = SET.clone();
-    let mut set_seq = SET_EXISTING.clone();
-    let mut set_par = SET_EXISTING.clone();
-
-    set_seq.extend(SET_EXTENSION.iter().cloned());
-    set_par.par_extend(SET_EXTENSION.par_iter().cloned());
-
-    assert_eq3!(set_seq, set_par, expected);
-}
-
-lazy_static! {
-    static ref SET_A: HashSet<char> = ['a', 'b', 'c', 'd'].iter().cloned().collect();
-    static ref SET_B: HashSet<char> = ['a', 'b', 'e', 'f'].iter().cloned().collect();
-    static ref SET_DIFF_AB: HashSet<char> = ['c', 'd'].iter().cloned().collect();
-    static ref SET_DIFF_BA: HashSet<char> = ['e', 'f'].iter().cloned().collect();
-    static ref SET_SYMM_DIFF_AB: HashSet<char> = ['c', 'd', 'e', 'f'].iter().cloned().collect();
-    static ref SET_INTERSECTION_AB: HashSet<char> = ['a', 'b'].iter().cloned().collect();
-    static ref SET_UNION_AB: HashSet<char> =
-        ['a', 'b', 'c', 'd', 'e', 'f'].iter().cloned().collect();
-}
-
-#[test]
-fn set_seq_par_equivalence_difference() {
-    let diff_ab_seq = SET_A.difference(&*SET_B).cloned().collect::<HashSet<_>>();
-    let diff_ab_par = SET_A
-        .par_difference(&*SET_B)
-        .cloned()
-        .collect::<HashSet<_>>();
-
-    assert_eq3!(diff_ab_seq, diff_ab_par, *SET_DIFF_AB);
-
-    let diff_ba_seq = SET_B.difference(&*SET_A).cloned().collect::<HashSet<_>>();
-    let diff_ba_par = SET_B
-        .par_difference(&*SET_A)
-        .cloned()
-        .collect::<HashSet<_>>();
-
-    assert_eq3!(diff_ba_seq, diff_ba_par, *SET_DIFF_BA);
-}
-
-#[test]
-fn set_seq_par_equivalence_symmetric_difference() {
-    let symm_diff_ab_seq = SET_A
-        .symmetric_difference(&*SET_B)
-        .cloned()
-        .collect::<HashSet<_>>();
-    let symm_diff_ab_par = SET_A
-        .par_symmetric_difference(&*SET_B)
-        .cloned()
-        .collect::<HashSet<_>>();
-
-    assert_eq3!(symm_diff_ab_seq, symm_diff_ab_par, *SET_SYMM_DIFF_AB);
-}
-
-#[test]
-fn set_seq_par_equivalence_intersection() {
-    let intersection_ab_seq = SET_A.intersection(&*SET_B).cloned().collect::<HashSet<_>>();
-    let intersection_ab_par = SET_A
-        .par_intersection(&*SET_B)
-        .cloned()
-        .collect::<HashSet<_>>();
-
-    assert_eq3!(
-        intersection_ab_seq,
-        intersection_ab_par,
-        *SET_INTERSECTION_AB
-    );
-}
-
-#[test]
-fn set_seq_par_equivalence_union() {
-    let union_ab_seq = SET_A.union(&*SET_B).cloned().collect::<HashSet<_>>();
-    let union_ab_par = SET_A.par_union(&*SET_B).cloned().collect::<HashSet<_>>();
-
-    assert_eq3!(union_ab_seq, union_ab_par, *SET_UNION_AB);
-}
diff --git a/vendor/hashbrown-0.9.1/tests/serde.rs b/vendor/hashbrown-0.9.1/tests/serde.rs
deleted file mode 100644 (file)
index 570bf70..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#![cfg(feature = "serde")]
-
-use core::hash::BuildHasherDefault;
-use hashbrown::{HashMap, HashSet};
-use rustc_hash::FxHasher;
-use serde_test::{assert_tokens, Token};
-
-// We use FxHash for this test because we rely on the ordering
-type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
-type FxHashSet<T> = HashSet<T, BuildHasherDefault<FxHasher>>;
-
-#[test]
-fn map_serde_tokens_empty() {
-    let map = FxHashMap::<char, u32>::default();
-
-    assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]);
-}
-
-#[test]
-fn map_serde_tokens() {
-    let mut map = FxHashMap::default();
-    map.insert('b', 20);
-    map.insert('a', 10);
-    map.insert('c', 30);
-
-    assert_tokens(
-        &map,
-        &[
-            Token::Map { len: Some(3) },
-            Token::Char('a'),
-            Token::I32(10),
-            Token::Char('b'),
-            Token::I32(20),
-            Token::Char('c'),
-            Token::I32(30),
-            Token::MapEnd,
-        ],
-    );
-}
-
-#[test]
-fn set_serde_tokens_empty() {
-    let set = FxHashSet::<u32>::default();
-
-    assert_tokens(&set, &[Token::Seq { len: Some(0) }, Token::SeqEnd]);
-}
-
-#[test]
-fn set_serde_tokens() {
-    let mut set = FxHashSet::default();
-    set.insert(20);
-    set.insert(10);
-    set.insert(30);
-
-    assert_tokens(
-        &set,
-        &[
-            Token::Seq { len: Some(3) },
-            Token::I32(20),
-            Token::I32(10),
-            Token::I32(30),
-            Token::SeqEnd,
-        ],
-    );
-}
diff --git a/vendor/hashbrown-0.9.1/tests/set.rs b/vendor/hashbrown-0.9.1/tests/set.rs
deleted file mode 100644 (file)
index 3fc0717..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#![cfg(not(miri))] // FIXME: takes too long
-
-use hashbrown::HashSet;
-use rand::{distributions::Alphanumeric, rngs::SmallRng, Rng, SeedableRng};
-
-#[test]
-fn test_hashset_insert_remove() {
-    let mut m: HashSet<Vec<char>> = HashSet::new();
-    //let num: u32 = 4096;
-    //let tx: Vec<Vec<u8>> = (0..num).map(|i| (i..(16 + i)).collect()).collect();
-    let seed: [u8; 16] = [
-        130, 220, 246, 217, 111, 124, 221, 189, 190, 234, 121, 93, 67, 95, 100, 43,
-    ];
-
-    let rng = &mut SmallRng::from_seed(seed);
-    let tx: Vec<Vec<char>> = (0..4096)
-        .map(|_| (rng.sample_iter(&Alphanumeric).take(32).collect()))
-        .collect();
-
-    for _ in 0..32 {
-        for i in 0..4096 {
-            assert_eq!(m.contains(&tx[i].clone()), false);
-            assert_eq!(m.insert(tx[i].clone()), true);
-        }
-        for i in 0..4096 {
-            println!("removing {} {:?}", i, tx[i]);
-            assert_eq!(m.remove(&tx[i]), true);
-        }
-    }
-}
index 76b64167dfa7d395bd2919233535e24bbd71caee..7fae6aa075f777085ab2018e95023bcb25f99409 100644 (file)
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"1a8531a56ec5114e4946dadad379f880881fad2db75e6affdeafc72415bc56d2","Cargo.toml":"b3bb242d7e332f49f444f49f4e11d3ecac44f21aeaa6bb8b69b39e8000e38fa7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ff8f68cb076caf8cefe7a6430d4ac086ce6af2ca8ce2c4e5a2004d4552ef52a2","README.md":"742ce1a4c92dada5f73ce594b224b646ff4aefe702768ec2eb39bd937a5a8fd3","benches/bench.rs":"43546a3d5aed2dd8f71f5d236f4df63d82a3767aec90d86f4ab1d1496619b45d","clippy.toml":"7535949f908c6d9aea4f9a9f3a7625552c93fc29e963d059d40f4def9d77ea7b","src/external_trait_impls/mod.rs":"d69528827794524cfd9acbeacc1ac4f6131e3c7574311e6d919f818f65fbff07","src/external_trait_impls/rayon/helpers.rs":"d4fbca4db924925548f8dab8eb94cf4a3955a53c5e1ff15f59c460546c394034","src/external_trait_impls/rayon/map.rs":"eee6371f2875085b286e950a32d13c3eff3c7280e7ea6ad346d322e7a00e7b7b","src/external_trait_impls/rayon/mod.rs":"156de9c1ad0123334ea3b7e5a17444faf1b8bf971aa88a1f23e2f2d1c3021141","src/external_trait_impls/rayon/raw.rs":"ddf349051bada9a9ebd027686e03ac2f12d74dd1b3f98a36aac257e13bac57fa","src/external_trait_impls/rayon/set.rs":"c4c44d44e56c2f59e9e1355662e29d8744ac96645ca4414127a359fb46cb0fbf","src/external_trait_impls/serde.rs":"9306fb6e0e339398dc23ba9e7400a9a28d713df248e8b260e3d4dc44f799e101","src/lib.rs":"dd3c2b1f41eb63f727e99791a9e33dcd8ed98f3348deafe4c8db112af3f62d24","src/macros.rs":"0b1e9a55e8f5232b82f7e56f352a98904b35ddfca015377cf71daa31939baabf","src/map.rs":"13be541072e0aaa15e0632eb253d2ffb29e8e4e9a0efc22baa15172ddca23c85","src/raw/alloc.rs":"893da7047ff4eb3291a3dee62c954f489c8b7666aa01ef6aeda8adf2549869c0","src/raw/bitmask.rs":"05e72c64957af7383001ca43a827cc5b3a8a39d00fac332ecea2fd7d2704099c","src/raw/generic.rs":"b31590616e76dfcca635e3aa9a8a0059b3af9a5afe6b0c5ebc98a7d96d63e8ed","src/raw/mod.rs":"a0d0b0508d41e08bfc16e5db1dd4f80cd29ca26e656a803821d1eb56a1f249b3","src/raw/sse2.rs":"a775ddd8830593bb10e2a4a11b2ce16d900a68e0b3763f24715f8f7fa9c2f69d","src/rustc_entry.rs":"148fae9e8bf4893820648c3c80b24c7161c828d103f3b2a2d7bbc32fe6605eb1","src/scopeguard.rs":"808655b3e98512fdcee5a4597e7763a6be99582ba8d77e5ba5ca130d85a97211","src/set.rs":"2bc180fd8502a62d1d478441d40395591374eb5ca1b16a3e6c8bec1266095576","tests/hasher.rs":"9a8fdf67e4415618e16729969c386eefe71408cded5d46cf7b67d969276a3452","tests/rayon.rs":"2286707a87b139f41902c82488c355b9fb402a3e734f392f3a73e87b9b932795","tests/serde.rs":"6bac8054db722dd049901b37a6e006535bac30f425eb5cd91af19b5bc1dfe78e","tests/set.rs":"374bd312c01a01cf8953bbbc9494f431b260c2657d7c79cc250e977b869a76ad"},"package":"362385356d610bd1e5a408ddf8d022041774b683f345a1d2cfcb4f60f8ae2db5"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"24ff18c978b40b166f5b3fd1090c3526d1958e79137dd9d765b571fed1c59fc2","Cargo.toml":"98ca6560469b01c01771f3c22c6182497d2239463cb4f63395d8207002d9a9ad","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ff8f68cb076caf8cefe7a6430d4ac086ce6af2ca8ce2c4e5a2004d4552ef52a2","README.md":"742ce1a4c92dada5f73ce594b224b646ff4aefe702768ec2eb39bd937a5a8fd3","benches/bench.rs":"43546a3d5aed2dd8f71f5d236f4df63d82a3767aec90d86f4ab1d1496619b45d","clippy.toml":"7535949f908c6d9aea4f9a9f3a7625552c93fc29e963d059d40f4def9d77ea7b","src/external_trait_impls/mod.rs":"d69528827794524cfd9acbeacc1ac4f6131e3c7574311e6d919f818f65fbff07","src/external_trait_impls/rayon/helpers.rs":"d4fbca4db924925548f8dab8eb94cf4a3955a53c5e1ff15f59c460546c394034","src/external_trait_impls/rayon/map.rs":"eee6371f2875085b286e950a32d13c3eff3c7280e7ea6ad346d322e7a00e7b7b","src/external_trait_impls/rayon/mod.rs":"156de9c1ad0123334ea3b7e5a17444faf1b8bf971aa88a1f23e2f2d1c3021141","src/external_trait_impls/rayon/raw.rs":"ddf349051bada9a9ebd027686e03ac2f12d74dd1b3f98a36aac257e13bac57fa","src/external_trait_impls/rayon/set.rs":"c4c44d44e56c2f59e9e1355662e29d8744ac96645ca4414127a359fb46cb0fbf","src/external_trait_impls/serde.rs":"9306fb6e0e339398dc23ba9e7400a9a28d713df248e8b260e3d4dc44f799e101","src/lib.rs":"45cd368e35bdb00232bcf2f5430ee516bb448a88724ab738424ae2e1d3c1f22e","src/macros.rs":"0b1e9a55e8f5232b82f7e56f352a98904b35ddfca015377cf71daa31939baabf","src/map.rs":"f3d43769100c59b04a978c9756e1b32f88cf7a84b9bda0e050a4adf5afb95572","src/raw/alloc.rs":"893da7047ff4eb3291a3dee62c954f489c8b7666aa01ef6aeda8adf2549869c0","src/raw/bitmask.rs":"05e72c64957af7383001ca43a827cc5b3a8a39d00fac332ecea2fd7d2704099c","src/raw/generic.rs":"b31590616e76dfcca635e3aa9a8a0059b3af9a5afe6b0c5ebc98a7d96d63e8ed","src/raw/mod.rs":"a0d0b0508d41e08bfc16e5db1dd4f80cd29ca26e656a803821d1eb56a1f249b3","src/raw/sse2.rs":"a775ddd8830593bb10e2a4a11b2ce16d900a68e0b3763f24715f8f7fa9c2f69d","src/rustc_entry.rs":"148fae9e8bf4893820648c3c80b24c7161c828d103f3b2a2d7bbc32fe6605eb1","src/scopeguard.rs":"808655b3e98512fdcee5a4597e7763a6be99582ba8d77e5ba5ca130d85a97211","src/set.rs":"d64fbadd0e6a5749cb5838f869004ea8cd46cec4b948615f810abb9e0a892d72","tests/hasher.rs":"9a8fdf67e4415618e16729969c386eefe71408cded5d46cf7b67d969276a3452","tests/rayon.rs":"2286707a87b139f41902c82488c355b9fb402a3e734f392f3a73e87b9b932795","tests/serde.rs":"6bac8054db722dd049901b37a6e006535bac30f425eb5cd91af19b5bc1dfe78e","tests/set.rs":"374bd312c01a01cf8953bbbc9494f431b260c2657d7c79cc250e977b869a76ad"},"package":"ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"}
\ No newline at end of file
index 132ab7505573a35e30fb1371e6d4c94a752ba81f..c88d3e0fea66f20564191a5762fd92405f43834f 100644 (file)
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 
 ## [Unreleased]
 
+## [v0.11.2] - 2021-03-25
+
+## Fixed
+
+- Added missing allocator type parameter to `HashMap`'s and `HashSet`'s `Clone` impls. (#252)
+
+## [v0.11.1] - 2021-03-20
+
+## Fixed
+
+- Added missing `pub` modifier to `BumpWrapper`. (#251)
+
 ## [v0.11.0] - 2021-03-14
 
 ## Added
@@ -295,7 +307,9 @@ This release was _yanked_ due to a breaking change for users of `no-default-feat
 
 - Initial release
 
-[Unreleased]: https://github.com/rust-lang/hashbrown/compare/v0.11.0...HEAD
+[Unreleased]: https://github.com/rust-lang/hashbrown/compare/v0.11.2...HEAD
+[v0.11.2]: https://github.com/rust-lang/hashbrown/compare/v0.11.1...v0.11.2
+[v0.11.1]: https://github.com/rust-lang/hashbrown/compare/v0.11.0...v0.11.1
 [v0.11.0]: https://github.com/rust-lang/hashbrown/compare/v0.10.0...v0.11.0
 [v0.10.0]: https://github.com/rust-lang/hashbrown/compare/v0.9.1...v0.10.0
 [v0.9.1]: https://github.com/rust-lang/hashbrown/compare/v0.9.0...v0.9.1
index 2a01cb346ed2afd58c131079ff734d78ec04c27a..02bd480e08fe6f60d8084e4cd06aa4929d6876b4 100644 (file)
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "hashbrown"
-version = "0.11.0"
+version = "0.11.2"
 authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
 exclude = [".travis.yml", "bors.toml", "/ci/*"]
 description = "A Rust port of Google's SwissTable hash map"
index af3c3a44e0ae49d8eb66242a47a3fd682eaf88dc..b2d6584ff3197ff3bcdd0344cfe618f656cc9fc9 100644 (file)
@@ -149,7 +149,7 @@ pub enum UnavailableMutError {
 /// the `allocator-api` feature of the `bumpalo` crate.
 #[cfg(feature = "bumpalo")]
 #[derive(Clone, Copy, Debug)]
-pub struct BumpWrapper<'a>(&'a bumpalo::Bump);
+pub struct BumpWrapper<'a>(pub &'a bumpalo::Bump);
 
 #[cfg(feature = "bumpalo")]
 #[test]
index 717eac6062c20dbb0af2df045940ea71e17f7019..ab1128879f1b1f33945f8437101c6500324de300 100644 (file)
@@ -194,7 +194,7 @@ pub struct HashMap<K, V, S = DefaultHashBuilder, A: Allocator + Clone = Global>
     pub(crate) table: RawTable<(K, V), A>,
 }
 
-impl<K: Clone, V: Clone, S: Clone> Clone for HashMap<K, V, S> {
+impl<K: Clone, V: Clone, S: Clone, A: Allocator + Clone> Clone for HashMap<K, V, S, A> {
     fn clone(&self) -> Self {
         HashMap {
             hash_builder: self.hash_builder.clone(),
index 8ceaf1200b7588dac2c88d96399d474327523fec..d59183b5cadc8a80c1b30a0967e80c35c6b4f4b1 100644 (file)
@@ -116,7 +116,7 @@ pub struct HashSet<T, S = DefaultHashBuilder, A: Allocator + Clone = Global> {
     pub(crate) map: HashMap<T, (), S, A>,
 }
 
-impl<T: Clone, S: Clone> Clone for HashSet<T, S> {
+impl<T: Clone, S: Clone, A: Allocator + Clone> Clone for HashSet<T, S, A> {
     fn clone(&self) -> Self {
         HashSet {
             map: self.map.clone(),
index 85ac9c28ab7af022261d603d5730f60362b4ba05..2241cc63c2624f359b75dc2bdc5fb548f0f7722f 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.toml":"3c88a36055be39c38da32957888c3117c6f9f6f146d0cdbfa9dd7c8e3f22f89e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"49707c0d6a7106b876e8012610e972bd8ce56427626577b7ab9d1b32e9021826","no_step_on_snek.png":"186b86731f5f07178c96da78debaeb1dcb9b5e2876a68b05e3f0f14370af4cf2","src/camel.rs":"4e0b944d83263a1ab7aec2cf0631e5c2635f2f49858c970d83019c2ca8b13d2a","src/kebab.rs":"66cba497fd1c01fec7ee265de774459779c0c459175ac72dcc754306716c513b","src/lib.rs":"93274cc28d0e24e4804de04ca7cb1e4ed1ec5deb33fb4a28b2d4e16220092873","src/mixed.rs":"4e79c4d51cfd938a6f4d5e86172d28f3429ea921a201adce68c3b263212296da","src/shouty_kebab.rs":"e40c60b641b7e04e066fa88524e1fd9f6f24f846ee6d2938b8c40da689fff27b","src/shouty_snake.rs":"5a46ec977f4490d42baf9851e5e0cf0096d9136eecc056191abf2258c3a269d7","src/snake.rs":"d70362386966c06e8208da64f90465cf94d59ba1b814fd1313e5bc8663cd9b6e","src/title.rs":"873666d445604aea6df8295ab8937ca6480e22c645d16799280101e57962fb6a"},"package":"87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"}
\ No newline at end of file
+{"files":{"Cargo.toml":"3e248a2487c80993370f242f8fbb5668f8b36a1ac9bdda89ca546d100d72b822","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"c82d9896b3309c1c590d50abe1c7fa704fd6df07f1d804915aa8646c608605ac","src/camel.rs":"1a061461a18e6dc148fb7c0d053382cacb656b937dc4ee086d74c7260b385a7e","src/kebab.rs":"a372d2aecffbf9cd860965ad703b1aa894b1cbc9f4d9d0fa9aee5372844eb24d","src/lib.rs":"a3709f595e5fcacdadb1a7074ff29a8e11fd5d75327dfafc1edac26fa5925d09","src/mixed.rs":"47ce940d45495ef3c5f9566988e2123703c2d857a3e88ec90d8d59df8d7b68e5","src/shouty_kebab.rs":"ca8dd79a2ed5c20911c970e2cd92cbf1402530d48ffe68b75960e7374bb7ffa8","src/shouty_snake.rs":"d27cea681a8c0cd31f31112b803b9bb6a0cccdc20fbebe5d524c684972899cd5","src/snake.rs":"dade07b8cd12bf4c098be7d4ad963957662d4a7105cbe7052262dcadad2daae2","src/title.rs":"5c6f0fdb66fa6421a65a036a9b111598684078716a60ce10f81f8e44bb06cceb"},"package":"6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"}
\ No newline at end of file
index aadaa089fa670ee93ceee1bdd5d1e950da30dab9..fc9c28dcdf71bb9f027a6c50bfc09cb26832799e 100644 (file)
@@ -13,8 +13,9 @@
 [package]
 edition = "2018"
 name = "heck"
-version = "0.3.2"
+version = "0.3.3"
 authors = ["Without Boats <woboats@gmail.com>"]
+include = ["src/**/*", "LICENSE-*", "README.md", "CHANGELOG.md"]
 description = "heck is a case conversion library."
 homepage = "https://github.com/withoutboats/heck"
 documentation = "https://docs.rs/heck"
index 55638752acb2fc796d31de09ad3a3f74251397da..33f2a5d3d64c9f8fdb7b73da05b48c83a8f2257f 100644 (file)
@@ -1,6 +1,6 @@
 # **heck** is a case conversion library
 
-!["I specifically requested the opposite of this."](https://github.com/withoutboats/heck/blob/master/no_step_on_snek.png)
+!["I specifically requested the opposite of this."](./no_step_on_snek.png)
 
 This library exists to provide case conversion between common cases like
 CamelCase and snake_case. It is intended to be unicode aware, internally
@@ -28,7 +28,7 @@ underscores) are folded into one. ("hello__world" in snake case is therefore
 "hello_world", not the exact same string). Leading or trailing word boundary
 indicators are dropped, except insofar as CamelCase capitalizes the first word.
 
-### Cases contained in this library:
+## Cases contained in this library:
 
 1. CamelCase
 2. snake_case
@@ -38,7 +38,7 @@ indicators are dropped, except insofar as CamelCase capitalizes the first word.
 6. Title Case
 7. SHOUTY-KEBAB-CASE
 
-### Contributing
+## Contributing
 
 PRs of additional well-established cases welcome.
 
@@ -48,7 +48,14 @@ would prefer **not** to receive PRs to make this behavior more configurable.
 
 Bug reports & fixes always welcome. :-)
 
-### License
+## MSRV
+
+The minimum supported Rust version for this crate is 1.32.0. This may change in
+minor or patch releases, but we probably won't ever require a very recent
+version. If you would like to have a stronger guarantee than that, please open
+an issue.
+
+## License
 
 heck is distributed under the terms of both the MIT license and the
 Apache License (Version 2.0).
diff --git a/vendor/heck/no_step_on_snek.png b/vendor/heck/no_step_on_snek.png
deleted file mode 100644 (file)
index 8aff445..0000000
Binary files a/vendor/heck/no_step_on_snek.png and /dev/null differ
index fa31f0cfc18b64fa7fb9bef5ffb9a2afa90de1de..6949435fc030360321fd75079c667aad70a7e990 100644 (file)
@@ -34,7 +34,7 @@ mod tests {
             fn $t() {
                 assert_eq!($s1.to_camel_case(), $s2)
             }
-        }
+        };
     }
 
     t!(test1: "CamelCase" => "CamelCase");
index 94ac322946d788c831da356c3cca786943e84900..75e597851c4339e7071fde7fcd9b3b5cfe9b4154 100644 (file)
@@ -33,7 +33,7 @@ mod tests {
             fn $t() {
                 assert_eq!($s1.to_kebab_case(), $s2)
             }
-        }
+        };
     }
 
     t!(test1: "CamelCase" => "camel-case");
index 95405878ba1ec5f5b4a558cfe5b0c8cfb01fe792..00a9fbea49a5d3c8881b19bcfd9feae4734ed222 100644 (file)
@@ -7,14 +7,15 @@
 //! ## Definition of a word boundary
 //!
 //! Word boundaries are defined as the "unicode words" defined in the
-//! `unicode_segmentation` library, as well as within those words in this manner:
+//! `unicode_segmentation` library, as well as within those words in this
+//! manner:
 //!
 //! 1. All underscore characters are considered word boundaries.
-//! 2. If an uppercase character is followed by lowercase letters, a word boundary
-//! is considered to be just prior to that uppercase character.
-//! 3. If multiple uppercase characters are consecutive, they are considered to be
-//! within a single word, except that the last will be part of the next word if it
-//! is followed by lowercase characters (see rule 2).
+//! 2. If an uppercase character is followed by lowercase letters, a word
+//! boundary is considered to be just prior to that uppercase character.
+//! 3. If multiple uppercase characters are consecutive, they are considered to
+//! be within a single word, except that the last will be part of the next word
+//! if it is followed by lowercase characters (see rule 2).
 //!
 //! That is, "HelloWorld" is segmented `Hello|World` whereas "XMLHttpRequest" is
 //! segmented `XML|Http|Request`.
@@ -24,7 +25,8 @@
 //! being converted to. Multiple adjacent word boundaries (such as a series of
 //! underscores) are folded into one. ("hello__world" in snake case is therefore
 //! "hello_world", not the exact same string). Leading or trailing word boundary
-//! indicators are dropped, except insofar as CamelCase capitalizes the first word.
+//! indicators are dropped, except insofar as CamelCase capitalizes the first
+//! word.
 //!
 //! ### Cases contained in this library:
 //!
@@ -58,18 +60,21 @@ use unicode_segmentation::UnicodeSegmentation;
 fn transform<F, G>(s: &str, with_word: F, boundary: G) -> String
 where
     F: Fn(&str, &mut String),
-    G: Fn(&mut String)
+    G: Fn(&mut String),
 {
-
-    /// Tracks the current 'mode' of the transformation algorithm as it scans the input string.
+    /// Tracks the current 'mode' of the transformation algorithm as it scans
+    /// the input string.
     ///
-    /// The mode is a tri-state which tracks the case of the last cased character of the current
-    /// word. If there is no cased character (either lowercase or uppercase) since the previous
-    /// word boundary, than the mode is `Boundary`. If the last cased character is lowercase, then
-    /// the mode is `Lowercase`. Othertherwise, the mode is `Uppercase`.
+    /// The mode is a tri-state which tracks the case of the last cased
+    /// character of the current word. If there is no cased character
+    /// (either lowercase or uppercase) since the previous word boundary,
+    /// than the mode is `Boundary`. If the last cased character is lowercase,
+    /// then the mode is `Lowercase`. Othertherwise, the mode is
+    /// `Uppercase`.
     #[derive(Clone, Copy, PartialEq)]
     enum WordMode {
-        /// There have been no lowercase or uppercase characters in the current word.
+        /// There have been no lowercase or uppercase characters in the current
+        /// word.
         Boundary,
         /// The previous cased character in the current word is lowercase.
         Lowercase,
@@ -88,14 +93,15 @@ where
         while let Some((i, c)) = char_indices.next() {
             // Skip underscore characters
             if c == '_' {
-                if init == i { init += 1; }
-                continue
+                if init == i {
+                    init += 1;
+                }
+                continue;
             }
 
             if let Some(&(next_i, next)) = char_indices.peek() {
-
-                // The mode including the current character, assuming the current character does
-                // not result in a word boundary.
+                // The mode including the current character, assuming the
+                // current character does not result in a word boundary.
                 let next_mode = if c.is_lowercase() {
                     WordMode::Lowercase
                 } else if c.is_uppercase() {
@@ -107,7 +113,9 @@ where
                 // Word boundary after if next is underscore or current is
                 // not uppercase and next is uppercase
                 if next == '_' || (next_mode == WordMode::Lowercase && next.is_uppercase()) {
-                    if !first_word { boundary(&mut out); }
+                    if !first_word {
+                        boundary(&mut out);
+                    }
                     with_word(&word[init..next_i], &mut out);
                     first_word = false;
                     init = next_i;
@@ -116,8 +124,11 @@ where
                 // Otherwise if current and previous are uppercase and next
                 // is lowercase, word boundary before
                 } else if mode == WordMode::Uppercase && c.is_uppercase() && next.is_lowercase() {
-                    if !first_word { boundary(&mut out); }
-                    else { first_word = false; }
+                    if !first_word {
+                        boundary(&mut out);
+                    } else {
+                        first_word = false;
+                    }
                     with_word(&word[init..i], &mut out);
                     init = i;
                     mode = WordMode::Boundary;
@@ -128,8 +139,11 @@ where
                 }
             } else {
                 // Collect trailing characters as a word
-                if !first_word { boundary(&mut out); }
-                else { first_word = false; }
+                if !first_word {
+                    boundary(&mut out);
+                } else {
+                    first_word = false;
+                }
                 with_word(&word[init..], &mut out);
                 break;
             }
@@ -150,7 +164,7 @@ fn lowercase(s: &str, out: &mut String) {
     }
 }
 
-fn uppercase(s: &str, out: &mut String ) {
+fn uppercase(s: &str, out: &mut String) {
     for c in s.chars() {
         out.extend(c.to_uppercase())
     }
index cca3262ab635d09fe47f107b9b12ef488206dd18..71089f2808e5037ae059bf59dd4a583bb1d8d6ed 100644 (file)
@@ -20,10 +20,17 @@ pub trait MixedCase: ToOwned {
 
 impl MixedCase for str {
     fn to_mixed_case(&self) -> String {
-        transform(self, |s, out| {
-            if out.is_empty() { lowercase(s, out); }
-            else { capitalize(s, out) }
-        }, |_| {})
+        transform(
+            self,
+            |s, out| {
+                if out.is_empty() {
+                    lowercase(s, out);
+                } else {
+                    capitalize(s, out)
+                }
+            },
+            |_| {},
+        )
     }
 }
 
@@ -37,7 +44,7 @@ mod tests {
             fn $t() {
                 assert_eq!($s1.to_mixed_case(), $s2)
             }
-        }
+        };
     }
 
     t!(test1: "CamelCase" => "camelCase");
index 0e0c7e753df7199bab6ebdeeed3d3be27041d626..0225471d9ef453324178c74dfff7b28e7c44c883 100644 (file)
@@ -34,7 +34,7 @@ mod tests {
             fn $t() {
                 assert_eq!($s1.to_shouty_kebab_case(), $s2)
             }
-        }
+        };
     }
 
     t!(test1: "CamelCase" => "CAMEL-CASE");
index 43be539283ffb48584e96abc0034eb57ac22aa4c..8f4289a0078b348157ba03af03a297ead7fc11c9 100644 (file)
@@ -18,8 +18,8 @@ pub trait ShoutySnakeCase: ToOwned {
     fn to_shouty_snake_case(&self) -> Self::Owned;
 }
 
-/// Oh heck, ShoutySnekCase is an alias for ShoutySnakeCase. See ShoutySnakeCase for
-/// more documentation.
+/// Oh heck, ShoutySnekCase is an alias for ShoutySnakeCase. See ShoutySnakeCase
+/// for more documentation.
 pub trait ShoutySnekCase: ToOwned {
     /// CONVERT THIS TYPE TO SNEK CASE.
     #[allow(non_snake_case)]
@@ -32,7 +32,6 @@ impl<T: ?Sized + ShoutySnakeCase> ShoutySnekCase for T {
     }
 }
 
-
 impl ShoutySnakeCase for str {
     fn to_shouty_snake_case(&self) -> Self::Owned {
         transform(self, uppercase, |s| s.push('_'))
@@ -49,7 +48,7 @@ mod tests {
             fn $t() {
                 assert_eq!($s1.to_shouty_snake_case(), $s2)
             }
-        }
+        };
     }
 
     t!(test1: "CamelCase" => "CAMEL_CASE");
index 13329fe8df62015c05b2248772a91071c92d9c01..c1ad37614d6468411e82761ac0046387a20443f4 100644 (file)
@@ -46,7 +46,7 @@ mod tests {
             fn $t() {
                 assert_eq!($s1.to_snake_case(), $s2)
             }
-        }
+        };
     }
 
     t!(test1: "CamelCase" => "camel_case");
index 3723f1fdc9ee7667e3422f9d9ac5581b5c3b6536..015a9fa3183718372926af80bbb4daa7e56db1a5 100644 (file)
@@ -34,7 +34,7 @@ mod tests {
             fn $t() {
                 assert_eq!($s1.to_title_case(), $s2)
             }
-        }
+        };
     }
 
     t!(test1: "CamelCase" => "Camel Case");
index 2e5929fc288acb761f99cc39d5744a7a13dfd7d8..ea9987909e488fc24d727084380fe3c23206992b 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.toml":"6cd0350a8b7cf5f825b88b1cafc7a5e71781d91dc1c2e57646d909c689e9afed","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"322fadd63e558e5a10caf980cbedf83ac1546ba40fd992f54492e21ce54205af","rust-toolchain":"58bea07cb6d97f9cfcd5c8f98b1feca0fb81cce5b0bf29a8e70ed2641956e9a6","src/lib.rs":"1fe7da738cb27c5c0941f6d4079bac8eb3e81da2aeb71fcfb81e37584fddaad7","src/tcplistener.rs":"c6e2db06d4265fa0956851e1c965336d60c53ab21573729aae76ecfe0ccc84c3","src/tcpstream.rs":"38a17de54213faf9de217f6146ff86ee75b67d4404a532b1419903269200936b"},"package":"322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"}
\ No newline at end of file
+{"files":{"Cargo.toml":"023c46a92caf2fc7a31fba3e7d4428a287e1fbdef822ed7e9a8f91284a30b387","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"322fadd63e558e5a10caf980cbedf83ac1546ba40fd992f54492e21ce54205af","rust-toolchain":"58bea07cb6d97f9cfcd5c8f98b1feca0fb81cce5b0bf29a8e70ed2641956e9a6","src/lib.rs":"c7dca30b651c91590ff46370bdaa10214062b9456395fb4bd549dedbf457c695","src/tcplistener.rs":"c6e2db06d4265fa0956851e1c965336d60c53ab21573729aae76ecfe0ccc84c3","src/tcpstream.rs":"38a17de54213faf9de217f6146ff86ee75b67d4404a532b1419903269200936b"},"package":"62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"}
\ No newline at end of file
index 4ddc9bdde6a3e0918d86d18bceb421e4c870f936..1f24268ddb8ae65b419f9ff4e330e23e365721e7 100644 (file)
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "hermit-abi"
-version = "0.1.18"
+version = "0.1.19"
 authors = ["Stefan Lankes"]
 description = "hermit-abi is small interface to call functions from the unikernel RustyHermit.\nIt is used to build the target `x86_64-unknown-hermit`.\n"
 documentation = "https://hermitcore.github.io/rusty-hermit/hermit_abi"
@@ -26,7 +26,7 @@ repository = "https://github.com/hermitcore/libhermit-rs"
 default-target = "x86_64-unknown-hermit"
 features = ["docs"]
 [dependencies.compiler_builtins]
-version = "0.1.0"
+version = "0.1"
 optional = true
 
 [dependencies.core]
index 0b8c5b44b2f66c0134d73d3888a80a8e7d707320..9151faf56117d176cc99119682021636e38f934d 100644 (file)
@@ -2,6 +2,9 @@
 //! [RustyHermit](https://github.com/hermitcore/libhermit-rs).
 
 #![no_std]
+#![allow(clippy::missing_safety_doc)]
+#![allow(clippy::result_unit_err)]
+
 extern crate libc;
 
 pub mod tcplistener;
index 752043eec82482d6d8063816ac220cefb70b0187..7551d2787c445276710ad120bdfa1c27dc6846a5 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.toml":"f74227e7c2cc4c8a1b407328d3dc5224b0633b6d81bd8bca7c4902f496e05f70","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ecc269ef87fd38a1d98e30bfac9ba964a9dbd9315c3770fed98d4d7cb5882055","README.rst":"8784bb0b101d06198fe989bbe85e5d597c6843de096faeed25a0beb2b9952722","benches/bench.rs":"dda3c7e3cd68b8f5c74dbd60189e89f0e43339cdc25dae7b1e5a9d25b1fb80a9","benches/faststring.rs":"2472b9d0d52031988cd31401357908fd850d15f1efa9f9761aa6b6779aad1889","build.rs":"558b4d0b9e9b3a44f7e1a2b69f7a7567ea721cd45cb54f4e458e850bf702f35c","src/equivalent.rs":"2e6ae24ef09a09b917f4e2b0f6288f901878e42f5080f61b1bd1afdcc90aba87","src/lib.rs":"a5f52cf1441511f3e71f1cbe8137410ecdbba96f95a61d039858c8f63768c36d","src/macros.rs":"cb2e9742b7e2bcadc4eb356a4ca4eb3317d1a80e293f37a3cd5a0155c5347c50","src/map.rs":"05b7eba2f7e2f11881e36f96abcf0038d6543ee6f1bb14b844b1a79cfc073065","src/map/core.rs":"7126a8ebc18b18e0349db01e0fbe24c3f6f40acd2346189306789dbeaaced3e0","src/map/core/raw.rs":"ef1337b6ba2820d96e34c696eeaf84c3b83cd064c2cca8f60fe9866b5caa45e6","src/mutable_keys.rs":"99fdec7c0182902ba19524f342c220b51475bcd41c44c2cb2c3f62eacb029335","src/rayon/map.rs":"cdbe6cad8e5753aca3f07b621d2bb3b480f1ae3e10697568b8c16aeb865de65b","src/rayon/mod.rs":"bf2b0fc074f20135a6734db600b04828e88dd263b3e361606be4efe8e916eafc","src/rayon/set.rs":"789efd10d41f03fa73268bae8afdc3b6582767420218a4b28f3c83c528ef726c","src/serde.rs":"d45ec8fb9c02594ca6f2e9b20764778b2b4193a24a52f1e233160a33efc6e683","src/serde_seq.rs":"c54a52fa607b6ccddda1e76e829778ca304c49b5f434edc5e582a5386c35d662","src/set.rs":"88b46246d5b39a91bf9318446bf6d8b0d7ff723ef6dd4ba4a965d67f7511f642","src/util.rs":"c415261cff9f610d7331192feba0839cb05e04d3d375a5fa2f8190a29661994e","tests/equivalent_trait.rs":"efe9393069e3cfc893d2c9c0343679979578e437fdb98a10baefeced027ba310","tests/macros_full_path.rs":"c33c86d7341581fdd08e2e6375a4afca507fa603540c54a3b9e51c4cd011cd71","tests/quick.rs":"6efe8c6dfa5bdd466b3f5c491d9dfbf57fd730301849a710abff9358968218c5","tests/tests.rs":"f6dbeeb0e2950402b0e66ac52bf74c9e4197d3c5d9c0dde64a7998a2ef74d327"},"package":"824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"}
\ No newline at end of file
+{"files":{"Cargo.toml":"ccac3c521edb40305973b59bd641a812846c844afa2ba67b7055541c1760e0bf","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ecc269ef87fd38a1d98e30bfac9ba964a9dbd9315c3770fed98d4d7cb5882055","README.rst":"1c48fc54d2ff77dcbecf26a8458b9abe6fe293a37f678521fb741d52af47df98","benches/bench.rs":"7fb78f4a64dda6b49d68d54f502260dfb9b3834c83c497eae674dd05c604a4cb","benches/faststring.rs":"2472b9d0d52031988cd31401357908fd850d15f1efa9f9761aa6b6779aad1889","build.rs":"558b4d0b9e9b3a44f7e1a2b69f7a7567ea721cd45cb54f4e458e850bf702f35c","src/equivalent.rs":"2e6ae24ef09a09b917f4e2b0f6288f901878e42f5080f61b1bd1afdcc90aba87","src/lib.rs":"7156153ea0c775e3126ad22e682804847fdfb02ddf581f4c8c993e73d3a2a1cf","src/macros.rs":"cb2e9742b7e2bcadc4eb356a4ca4eb3317d1a80e293f37a3cd5a0155c5347c50","src/map.rs":"a8b5d0e7152ebb125a8224ad62a5d391d135597efba76d1df43f462544d441f4","src/map/core.rs":"7126a8ebc18b18e0349db01e0fbe24c3f6f40acd2346189306789dbeaaced3e0","src/map/core/raw.rs":"ef1337b6ba2820d96e34c696eeaf84c3b83cd064c2cca8f60fe9866b5caa45e6","src/mutable_keys.rs":"99fdec7c0182902ba19524f342c220b51475bcd41c44c2cb2c3f62eacb029335","src/rayon/map.rs":"841e8f99388860596187329ccbf9563978dd50124bda817e6727263ede31d904","src/rayon/mod.rs":"d2764c1e854eaf40b562e0e2090ef7d5d979f4407b0c0e76c54091dcf72f3e28","src/rayon/set.rs":"a6aea27ec78be8cf2ec1f339c4226bc9d54762bce90ee6ff4fd0f7a98196d4a9","src/serde.rs":"d45ec8fb9c02594ca6f2e9b20764778b2b4193a24a52f1e233160a33efc6e683","src/serde_seq.rs":"c54a52fa607b6ccddda1e76e829778ca304c49b5f434edc5e582a5386c35d662","src/set.rs":"c626c64c354ac8209157b387a217888895b7da62a7da2c7a9c731e8d7e3fbf95","src/util.rs":"c415261cff9f610d7331192feba0839cb05e04d3d375a5fa2f8190a29661994e","tests/equivalent_trait.rs":"efe9393069e3cfc893d2c9c0343679979578e437fdb98a10baefeced027ba310","tests/macros_full_path.rs":"c33c86d7341581fdd08e2e6375a4afca507fa603540c54a3b9e51c4cd011cd71","tests/quick.rs":"60525d0b4eb9ac3054a52158f3c75695772d93e22b5f38a8e761c08f8d82d3db","tests/tests.rs":"f6dbeeb0e2950402b0e66ac52bf74c9e4197d3c5d9c0dde64a7998a2ef74d327"},"package":"bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"}
\ No newline at end of file
index 54e07a98c90123c67dbf918de1feb7ca9c3b07bf..ed0bdc0aa44693e6e3a0ede214f018948a0d4b06 100644 (file)
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "indexmap"
-version = "1.6.2"
+version = "1.7.0"
 authors = ["bluss", "Josh Stone <cuviper@gmail.com>"]
 build = "build.rs"
 description = "A hash table with consistent order and fast iteration.\n\nThe indexmap is a hash table where the iteration order of the key-value\npairs is independent of the hash values of the keys. It has the usual\nhash table functionality, it preserves insertion order except after\nremovals, and it allows lookup of its elements by either hash table key\nor numerical index. A corresponding hash set type is also provided.\n\nThis crate was initially published under the name ordermap, but it was renamed to\nindexmap.\n"
@@ -34,12 +34,12 @@ debug = true
 [lib]
 bench = false
 [dependencies.hashbrown]
-version = "0.9.1"
+version = "0.11"
 features = ["raw"]
 default-features = false
 
 [dependencies.rayon]
-version = "1.0"
+version = "1.2"
 optional = true
 
 [dependencies.serde]
index 1cf5368bf0dde0820223975a8ce654da0d577be5..e4617f8efc42059fb2f3b5f0789efebf698a6f44 100644 (file)
@@ -12,8 +12,8 @@ indexmap
 .. |docs| image:: https://docs.rs/indexmap/badge.svg
 .. _docs: https://docs.rs/indexmap
 
-.. |rustc| image:: https://img.shields.io/badge/rust-1.36%2B-orange.svg
-.. _rustc: https://img.shields.io/badge/rust-1.36%2B-orange.svg
+.. |rustc| image:: https://img.shields.io/badge/rust-1.49%2B-orange.svg
+.. _rustc: https://img.shields.io/badge/rust-1.49%2B-orange.svg
 
 A pure-Rust hash table which preserves (in a limited sense) insertion order.
 
@@ -66,6 +66,12 @@ which is roughly:
 Recent Changes
 ==============
 
+- 1.7.0
+
+  - **MSRV**: Rust 1.49 or later is now required.
+
+  - The ``hashbrown`` dependency has been updated to version 0.11.
+
 - 1.6.2
 
   - Fixed to match ``std`` behavior, ``OccupiedEntry::key`` now references the
index 102cd49c8c72327edffe7ceb11fb40d783c38145..d6de602dd88cbd24508cdeaac4f13c60abfbab7a 100644 (file)
@@ -561,7 +561,7 @@ fn indexmap_merge_shuffle(b: &mut Bencher) {
 #[bench]
 fn swap_remove_indexmap_100_000(b: &mut Bencher) {
     let map = IMAP_100K.clone();
-    let mut keys = Vec::from_iter(map.keys().cloned());
+    let mut keys = Vec::from_iter(map.keys().copied());
     let mut rng = small_rng();
     keys.shuffle(&mut rng);
 
@@ -578,7 +578,7 @@ fn swap_remove_indexmap_100_000(b: &mut Bencher) {
 #[bench]
 fn shift_remove_indexmap_100_000_few(b: &mut Bencher) {
     let map = IMAP_100K.clone();
-    let mut keys = Vec::from_iter(map.keys().cloned());
+    let mut keys = Vec::from_iter(map.keys().copied());
     let mut rng = small_rng();
     keys.shuffle(&mut rng);
     keys.truncate(50);
index 1a58a8302461d4d9c1138f9c19f39567cc449b3d..aa419da3179bb8702f709fe04ea450dd1da249fc 100644 (file)
@@ -53,7 +53,7 @@
 //!
 //! ### Rust Version
 //!
-//! This version of indexmap requires Rust 1.36 or later.
+//! This version of indexmap requires Rust 1.49 or later.
 //!
 //! The indexmap 1.x release series will use a carefully considered version
 //! upgrade policy, where in a later 1.x version, we will raise the minimum
 //!
 //! [def]: map/struct.IndexMap.html#impl-Default
 
-#[cfg(not(has_std))]
 extern crate alloc;
 
 #[cfg(has_std)]
 #[macro_use]
 extern crate std;
 
-#[cfg(not(has_std))]
 use alloc::vec::{self, Vec};
 
-#[cfg(has_std)]
-use std::vec::{self, Vec};
-
 #[macro_use]
 mod macros;
 mod equivalent;
index 3bfaa1501c1dd316097754c1338fb462b8abcca1..a482a399e07ced6f15b3037d70264aa1d67cb9ee 100644 (file)
@@ -237,7 +237,7 @@ impl<K, V, S> IndexMap<K, V, S> {
         }
     }
 
-    /// Return an iterator over mutable references to the the values of the map,
+    /// Return an iterator over mutable references to the values of the map,
     /// in their order
     pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
         ValuesMut {
@@ -424,6 +424,8 @@ where
     }
 
     /// Return item index, if it exists in the map
+    ///
+    /// Computes in **O(1)** time (average).
     pub fn get_index_of<Q: ?Sized>(&self, key: &Q) -> Option<usize>
     where
         Q: Hash + Equivalent<K>,
@@ -1674,7 +1676,7 @@ mod tests {
     fn keys() {
         let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
         let map: IndexMap<_, _> = vec.into_iter().collect();
-        let keys: Vec<_> = map.keys().cloned().collect();
+        let keys: Vec<_> = map.keys().copied().collect();
         assert_eq!(keys.len(), 3);
         assert!(keys.contains(&1));
         assert!(keys.contains(&2));
@@ -1685,7 +1687,7 @@ mod tests {
     fn values() {
         let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
         let map: IndexMap<_, _> = vec.into_iter().collect();
-        let values: Vec<_> = map.values().cloned().collect();
+        let values: Vec<_> = map.values().copied().collect();
         assert_eq!(values.len(), 3);
         assert!(values.contains(&'a'));
         assert!(values.contains(&'b'));
@@ -1699,7 +1701,7 @@ mod tests {
         for value in map.values_mut() {
             *value *= 2
         }
-        let values: Vec<_> = map.values().cloned().collect();
+        let values: Vec<_> = map.values().copied().collect();
         assert_eq!(values.len(), 3);
         assert!(values.contains(&2));
         assert!(values.contains(&4));
index ed4c74e4387692d5eefb4179a00856952523f795..ed2da3ef56f78eb2e06eccd604a444615ceeb84a 100644 (file)
@@ -275,7 +275,7 @@ where
     K: Send,
     V: Send,
 {
-    /// Return a parallel iterator over mutable references to the the values of the map
+    /// Return a parallel iterator over mutable references to the values of the map
     ///
     /// While parallel iterators can process items in any order, their relative order
     /// in the map is still preserved for operations like `reduce` and `collect`.
@@ -464,7 +464,7 @@ mod tests {
     fn keys() {
         let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
         let map: IndexMap<_, _> = vec.into_par_iter().collect();
-        let keys: Vec<_> = map.par_keys().cloned().collect();
+        let keys: Vec<_> = map.par_keys().copied().collect();
         assert_eq!(keys.len(), 3);
         assert!(keys.contains(&1));
         assert!(keys.contains(&2));
@@ -475,7 +475,7 @@ mod tests {
     fn values() {
         let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
         let map: IndexMap<_, _> = vec.into_par_iter().collect();
-        let values: Vec<_> = map.par_values().cloned().collect();
+        let values: Vec<_> = map.par_values().copied().collect();
         assert_eq!(values.len(), 3);
         assert!(values.contains(&'a'));
         assert!(values.contains(&'b'));
@@ -487,7 +487,7 @@ mod tests {
         let vec = vec![(1, 1), (2, 2), (3, 3)];
         let mut map: IndexMap<_, _> = vec.into_par_iter().collect();
         map.par_values_mut().for_each(|value| *value *= 2);
-        let values: Vec<_> = map.par_values().cloned().collect();
+        let values: Vec<_> = map.par_values().copied().collect();
         assert_eq!(values.len(), 3);
         assert!(values.contains(&2));
         assert!(values.contains(&4));
index 57c810beeae103e24e1c133e6b501a5430cfbb80..757a54dd954030f77e71d312a787a001b6cd3c53 100644 (file)
@@ -1,11 +1,7 @@
 use rayon::prelude::*;
 
-#[cfg(not(has_std))]
 use alloc::collections::LinkedList;
 
-#[cfg(has_std)]
-use std::collections::LinkedList;
-
 use crate::vec::Vec;
 
 // generate `ParallelIterator` methods by just forwarding to the underlying
index f6e08d48373d273ad713116dee947170f060bc2e..f3e0da911769bd59a56512e58b8f60754ff5a676 100644 (file)
@@ -622,7 +622,7 @@ mod tests {
             I1: ParallelIterator<Item = &'a i32>,
             I2: Iterator<Item = i32>,
         {
-            let v1: Vec<_> = iter1.cloned().collect();
+            let v1: Vec<_> = iter1.copied().collect();
             let v2: Vec<_> = iter2.collect();
             assert_eq!(v1, v2);
         }
index aa4e7749532db1c529a7495e65bd7c09c8a62700..66c3da4d3e7edcb7e17826a7b66a67c4e4046de1 100644 (file)
@@ -840,7 +840,7 @@ where
     S: BuildHasher,
 {
     fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iterable: I) {
-        let iter = iterable.into_iter().cloned(); // FIXME: use `copied` in Rust 1.36
+        let iter = iterable.into_iter().copied();
         self.extend(iter);
     }
 }
@@ -1560,7 +1560,7 @@ mod tests {
             I1: Iterator<Item = &'a i32>,
             I2: Iterator<Item = i32>,
         {
-            assert!(iter1.cloned().eq(iter2));
+            assert!(iter1.copied().eq(iter2));
         }
 
         let set_a: IndexSet<_> = (0..3).collect();
@@ -1612,8 +1612,7 @@ mod tests {
         let set_c: IndexSet<_> = (0..6).collect();
         let set_d: IndexSet<_> = (3..9).rev().collect();
 
-        // FIXME: #[allow(clippy::eq_op)] in Rust 1.31
-        #[cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints, eq_op))]
+        #[allow(clippy::eq_op)]
         {
             assert_eq!(&set_a & &set_a, set_a);
             assert_eq!(&set_a | &set_a, set_a);
index 10e11b5285df873fb189435bcb4f61defbe59d7f..848e14fca0b4f1382f0cac5241a976d8313f3812 100644 (file)
@@ -30,7 +30,7 @@ where
     I: IntoIterator<Item = &'a T>,
     T: Copy + Hash + Eq,
 {
-    iter.into_iter().cloned().collect()
+    iter.into_iter().copied().collect()
 }
 
 fn indexmap<'a, T: 'a, I>(iter: I) -> IndexMap<T, ()>
@@ -38,7 +38,7 @@ where
     I: IntoIterator<Item = &'a T>,
     T: Copy + Hash + Eq,
 {
-    IndexMap::from_iter(iter.into_iter().cloned().map(|k| (k, ())))
+    IndexMap::from_iter(iter.into_iter().copied().map(|k| (k, ())))
 }
 
 quickcheck! {
@@ -123,7 +123,7 @@ quickcheck! {
 
         // First see if `Vec::drain` is happy with this range.
         let result = std::panic::catch_unwind(|| {
-            let mut keys: Vec<u8> = map.keys().cloned().collect();
+            let mut keys: Vec<u8> = map.keys().copied().collect();
             keys.drain(range);
             keys
         });
@@ -155,7 +155,7 @@ quickcheck! {
         let mut iter = map.keys();
         for &key in insert.iter().unique() {
             if elements.contains(&key) {
-                assert_eq!(Some(key), iter.next().cloned());
+                assert_eq!(Some(&key), iter.next());
             }
         }
 
@@ -165,7 +165,7 @@ quickcheck! {
 
     fn indexing(insert: Vec<u8>) -> bool {
         let mut map: IndexMap<_, _> = insert.into_iter().map(|x| (x, x)).collect();
-        let set: IndexSet<_> = map.keys().cloned().collect();
+        let set: IndexSet<_> = map.keys().copied().collect();
         assert_eq!(map.len(), set.len());
 
         for (i, &key) in set.iter().enumerate() {
@@ -295,7 +295,7 @@ quickcheck! {
         let mut reference = HashMap::new();
         do_ops(&ops, &mut map, &mut reference);
         let mut visit = IndexMap::new();
-        let keys = Vec::from_iter(map.keys().cloned());
+        let keys = Vec::from_iter(map.keys().copied());
         for (k, v) in keys.iter().zip(map.values_mut()) {
             assert_eq!(&reference[k], v);
             assert!(!visit.contains_key(k));
index e8601b7f75e1abb8b9fc29fce3d23c5b3782e291..a535f61bb93f2e31c9bef59391f7d2823dd8d131 100644 (file)
@@ -1 +1 @@
-{"files":{"CONTRIBUTING.md":"752eea5a703d11b485c6b5f195f51bd2c79aa5159b619ce09555c779e1fb586b","Cargo.toml":"36ad390cca1931035e6087b77fa72b05b2c2239b7d83468147b948dc8344ba95","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"8228847944f1332882fbb00275b6f30e4a8aad08a13569c25d52cac012cc2a47","build.rs":"8e0e8d33cc9e7c25cde75c2b502420f943266a681024169f94084774b422681d","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"34c60f12ec5eeb90f13ec3b954427532111c2446e69617616a97aefc1086a9f1","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"f74664d478624a642ffa42067bdaf683a295861f38f41f5ff93601165d6dca2a","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"d4f7452c0fe720f3a961b918b74ec86d19cef33e6b4aac08efbbad6f6d818e09","src/macros.rs":"7844312c233a6889fa15395fe3106f6a8f6229211104a92f33ea3c9536eef763","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"6a4ce300da0d2b0db04b18548286603ffe4b47d679a41cf60f1902895894aa1f","src/unix/bsd/apple/b64/aarch64/align.rs":"f0c321265dd7671f16106b84951ac7dd77ed2e65c6623cbf2d29e76531984770","src/unix/bsd/apple/b64/aarch64/mod.rs":"46d5d061c7a74cbc09cbdfb3bee9a600867bf4e04c0e4d0ca6c817e6033b32e1","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"cc6878dd130c3f255418e4da74992ae9ba6a3cdb0530772de76c518077d3b12a","src/unix/bsd/apple/mod.rs":"f27e520f171b4c1c9e87177c30983b6314c0686a96bdca4573306e6c9196dc06","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"80d6daaeeb5ae579892eba6182d7c3f0f4d69e43256b7638355f2910af54d891","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"14f0bd6693967d4fedec904f7042bd51f2138cb843ec4df18c911b357417cdd2","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"6523af60c0e4937ad374003c1653e9e721f5b6f11572c747732f76522d07d034","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"e5d790897347b6e8b560f041d500bf97b88982ec6120b38c65f710a97d14e90d","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"52d9b72be2ed9901b3b7a88a15808afb72a05b5ec1382657e4f139a456d881ab","src/unix/bsd/freebsdlike/freebsd/mod.rs":"5f8d84965b456e2e017a398bdbaba580d79975caac3608e71650389a5c15940d","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"6132aa0973454379674ea6cbc77e6eace1e1032dd9f38182071388a036f1bc08","src/unix/bsd/freebsdlike/mod.rs":"dcc6bffbc77e84ff405ae4ea1b123984e51a46e65ed643008771b1db3f62960b","src/unix/bsd/mod.rs":"33df9bc4e6f92f78842defe59d9ac2c2afa0942ba990134ec0bf57aa76faa798","src/unix/bsd/netbsdlike/mod.rs":"e627dea0f663deb311f7428b5ca54c0363789c154e3648835699a00b25d32489","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"b38fc046f9a40fea28bd26328b96629f4d5d63d7524936bd6af1865d401a8716","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"8cf43c67e99bd89196fccb74cf5df862eef46a699c68174c77fb80962e04783c","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/mod.rs":"a231c24be76fac97e54d44927bdf4f839d93d88e195e8adf227289b26e90d714","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"e59b7fd65f68f8e857eec39e0c03bac1d3af6ddc26c9ba58494336b83659bb9b","src/unix/haiku/b32.rs":"69ae47fc52c6880e85416b4744500d5655c9ec6131cb737f3b649fceaadce15a","src/unix/haiku/b64.rs":"73e64db09275a8da8d50a13cce2cfa2b136036ddf3a930d2939f337fc995900b","src/unix/haiku/mod.rs":"34d74b3f86953c4bdba363b7b629fd3fc72d3842260ba208f91b9dc6024634ff","src/unix/haiku/native.rs":"7d21ea1c9bb2d9fd17ef30eab1cd61bacd111f2cdbafee1f44f7b9fc5fbd919d","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"d611801c875a1066ff596ba813a80c1689aa54489bbd5bd8af4610c786d97a36","src/unix/linux_like/android/b32/mod.rs":"47aab6a6babd5382db49d48aa82729931c429344984e47d7467334fb9fb31c79","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/mod.rs":"424c548e1d328475136cddbfeb4bb452880cc8e6ec878758ccc0667f0ea588b9","src/unix/linux_like/android/b64/mod.rs":"e3078e856e43fde9b57d8a5aa840a590f2e18517a3e8de23e9c2a3d798596f43","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"e84176d838e663d351450bad218715db1fafbb531e47ea0e262cbb45829dae89","src/unix/linux_like/android/mod.rs":"ee2c9b90b8d898b1ca1dd24d0f1340fa697ecce205720cd613c0efd68318904b","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"369b8e0feeed6d99a93a6b7783cad6cd9a3b2fc45de77f6b48fedc3de321f49d","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"213e70ebed2703e14a9cf17666b21ecbf180b7bff7fa22fdbb36dbbd52df326d","src/unix/linux_like/linux/arch/generic/mod.rs":"ff1fe8fad4ea15d9bec3db25efcfcb4939190c5189f86cfa4d05825aa8c10956","src/unix/linux_like/linux/arch/mips/mod.rs":"e4a980b002105aaa057eb6568e1e2c6168ade5c00e13a31ef67e316ddffdb900","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"1789eb5b41f75c29239795124a4a7cdcf7c8d213b88cf581b2f5bda08d7cf15b","src/unix/linux_like/linux/arch/sparc/mod.rs":"ded708124ee610267d011dee31fb02d1ec697c334aa822776ec95a7ddf6fc541","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"3fed009dc9af3cc81be7087da9d2d7d1f39845e4497e290259c5cdbae25f039d","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"07adf9f4b96854062db518aaf08521fde0ad4a21a5c049efccba437bd97b2b5a","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"1cb5c0c9df3af2bbe131a91593583259fac9118931744c8435e197a394eb0462","src/unix/linux_like/linux/gnu/b32/mod.rs":"1e05278ab6295e95165d0fab1698bdc82a511bcbda3250093af4e5edf08991f8","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"0cd7348badb9c4f8a0db31a2503b30c456a2bfcc7a0e5919762b1e12f912c5ad","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"9c628cd97806181dc4d34b072f63fe1eb42f08108712002e0628ffe27f2fa93f","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"1bcec269a8416ccc48a384ca5765eaaa23f30f39f32311f50008ef4eeadafb2f","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"5317dbf2323577b89370bbee3894882b89d8333176db4f7b271ddc2f036ef43c","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c3730792dabcc166d8fd22929ef2633d49bc626875382dfcd401e8e125fb7a84","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"68bcb71bbfccb4e8648948e494366d94767ce96f36daab9c1329375cdd32a459","src/unix/linux_like/linux/gnu/b64/mod.rs":"7bf5c9813032db77b964ccb90bdce15236ae9ea06ea185595278ea4565c21b7b","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"dbb8905e363ed4a2dfb984554ad9b6389d27f6a2d599ec2d80e38a6c7551a019","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"18edaa89c9746125863ff53182e0ef32cb1e1612e1ed9a2672558a9de85440e9","src/unix/linux_like/linux/gnu/b64/s390x.rs":"d9bb4e524e70d6fef49e0f77d89a92f478fd95d9a1aea32f4dc845275a7465d4","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"26fda11bdce99372c2c246e60866b56d98beb9fb49a2f6b69347ecfd03d18255","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"5a5ce7c5c92f60d8900dce63d363a38f3126aaf5be981710e172bec96ef95ac6","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"f775ac2b754f90b63053fe22afe1d19d306b5404995568d6805baa9249fb617f","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"4ba1b58468f55254717366f50fdfd3e4114fde6dc442a56681926c4d7e5b6b0d","src/unix/linux_like/linux/gnu/mod.rs":"d8e0e0db2158cdd81c5f8f436387ce12df9ebbe786a1041e9073c12eb5cd9108","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"ca303182e9ee89ea189d731023fac3734dce48637bd86835eb2abc6c11c17973","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"6255abe2ee04986832d12b7b2190589580f2a43e9bfb285b32b5747227f62727","src/unix/linux_like/linux/musl/b32/hexagon.rs":"a8811791809672be8338e6e27d1c4fcf383c2f26585be8bf9ab2923b219de032","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"b9e9ff42363ebbb884ddf6445129ec4164471df45846874fc08f5f458e659254","src/unix/linux_like/linux/musl/b32/mod.rs":"8ede3985e6243882814ce91e8ce543e7edbafc0cee5932816072b6f14207a671","src/unix/linux_like/linux/musl/b32/powerpc.rs":"4592dc5f1f2fe888dfef85fa862d42d168e73a2c6f4fc052b58287d0f4d4ffcd","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"a19a8decfab185af3cebd34aae4b15082e7552be573904b8c1a3f0c0e493ef34","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"798a9229d70ce235394f2dd625f6c4c1e10519a94382dc5b091952b638ae2928","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"a73035c6d9b776f13b839008e15c04c2c53455571efd06664affcb047e457112","src/unix/linux_like/linux/musl/b64/mips64.rs":"2744895451f3a777fbe54f7f2695be53310b965fd62084c9b7e9121c7fe28346","src/unix/linux_like/linux/musl/b64/mod.rs":"d18abc0aeba2e26342bf3416a4dba0836db2bb0ee013b0a39629475cf8640289","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"e5a55525b42493923956d668f978fb45e22d51deea00ce5edbfddf76ff19c741","src/unix/linux_like/linux/musl/b64/s390x.rs":"03dfec6794d93cb31a7c52b2d53a0973755168f91f8fa437cc5dbd54882c8ee7","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"0dd168f5a6881f32e5239fb312b23cf137b800d0ff323286a92c8a2c382b5456","src/unix/linux_like/linux/musl/mod.rs":"f0e202a92ea839c42c1176f416ece21e69ba809795b8035768b10d3813c95892","src/unix/linux_like/linux/no_align.rs":"5ed04c53bf9d27da9b4d65ba7625c6ac53330162683d1b3df98950caafa3507b","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"9b691eeec0a9bf7b2abb87e09062d2c148d18e11c96ecad0edd0b74d1d0509fd","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"18753a99b820d69e062e3ba22a63fa86577b6dcc42f740479c7be1a4c658e1be","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"e3085ba56cfbc528d7c3c55065880603238c333b6047ef51c58177508a487fcd","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"656fbf5157ab6d06fc365a8353b138818ad5b8429ea5628ff35a3972c63a1a7c","src/unix/linux_like/linux/uclibc/mod.rs":"0438ffcfa951516cbfdbd7bdc31ccee06614d5150fd271ca6ba9ba06890041ad","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"bb31053d6403091e11f95ac2203982f279f8b984a19adf30796878c45fdd8c25","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"02e21c0550a423a3f6db0a0af6a0f37cf5937feb2562a490e0ad0e09a8d9fc77","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"665aab490cd65ea811ea3e9adc8074bc30cd70986df52c7d4165d23bcd2cf29a","src/unix/mod.rs":"a5fbb90b99244f04bb37dc7d79d56261f5c5a41e9a09b7958aed9a2b4882eae8","src/unix/newlib/aarch64/mod.rs":"bb269c1468a9676442554600e87417079a787fe6220dfc23b3109639259e8710","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"c71be856bfd7f576b2db28af9f680211cbe6c1cac7d537bbc8020b39591af07c","src/unix/newlib/mod.rs":"407fe7e3c77f4c4c129788b3888a7da5d4b7b818ed3e96abb8de8cd780f83fb6","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"2d0f7af28b47f7a2a6c210ebd1c1f33ed8eac62e56b5af2b856de2ad3fdc5187","src/unix/newlib/xtensa/mod.rs":"08b314a27797ee27989f48f5a0e66e0d73670071ceabd341076cdce7ea67201c","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"6dcfe2212ea37e8e293c8fe7acc1319035594e9b951bd64c071f1a2a8be9b91e","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"e01acc1b176e15268ac0ca4d1de50bf372ba80a465af35cd612c8f7e702baf92","src/unix/solarish/mod.rs":"be9f7a37d17a7616f6dbebd871fe4ae83612af6b582ebf153284cff1e7162334","src/unix/solarish/solaris.rs":"65b005453aefa9b9d4fc860fe77cfec80d8c97a51342b15daf55fc3e808bb384","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"9caf6ff3faad5b39c9deb8eae497a61ef15aa5e03aa409a16299e700240c3b63","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"69460feb515652ec62ff258ccba4ed46738ee472938e78a3c34cbbf7a0e865c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"5349a7c76b7fa7f022627827cde65ae109949a23fe70cac5bf5967661ed18012","src/windows/msvc.rs":"ea6d87a6a9cd668261b1c043e7c36cf599e80b5d09f6e4502e85daa4797c7927","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"}
\ No newline at end of file
+{"files":{"CONTRIBUTING.md":"752eea5a703d11b485c6b5f195f51bd2c79aa5159b619ce09555c779e1fb586b","Cargo.toml":"b35f4f017f266f8cbba03d30912fb3b7792a577a0ec852b78cd5bc1460aa89ca","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"8228847944f1332882fbb00275b6f30e4a8aad08a13569c25d52cac012cc2a47","build.rs":"8e0e8d33cc9e7c25cde75c2b502420f943266a681024169f94084774b422681d","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"34c60f12ec5eeb90f13ec3b954427532111c2446e69617616a97aefc1086a9f1","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"dd7a673e4da1e476551af578be02d0409b65db43132a7fd4b5ffd222b171db56","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"d4f7452c0fe720f3a961b918b74ec86d19cef33e6b4aac08efbbad6f6d818e09","src/macros.rs":"7844312c233a6889fa15395fe3106f6a8f6229211104a92f33ea3c9536eef763","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"6a4ce300da0d2b0db04b18548286603ffe4b47d679a41cf60f1902895894aa1f","src/unix/bsd/apple/b64/aarch64/align.rs":"f0c321265dd7671f16106b84951ac7dd77ed2e65c6623cbf2d29e76531984770","src/unix/bsd/apple/b64/aarch64/mod.rs":"46d5d061c7a74cbc09cbdfb3bee9a600867bf4e04c0e4d0ca6c817e6033b32e1","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"cc6878dd130c3f255418e4da74992ae9ba6a3cdb0530772de76c518077d3b12a","src/unix/bsd/apple/mod.rs":"450b073d7c81165a720a817a00745b82259550fcbd488d66dd857eadf5fc41c9","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"867301c7095faf0c1ec195c1b032c564f0eae3a19398cd3c28e63acaf79cc0d6","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"14f0bd6693967d4fedec904f7042bd51f2138cb843ec4df18c911b357417cdd2","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"6523af60c0e4937ad374003c1653e9e721f5b6f11572c747732f76522d07d034","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"c0e8a99f61efed0578f92918d60d445d25463e9aed782675025d191cc0fae9bf","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"40e43d320fc2466e34db474290da24bd66d5d80c41245db73caa1325a1900f83","src/unix/bsd/freebsdlike/freebsd/mod.rs":"bc8b8f3e27f7122857282b6ecb1d4971915ed06c7b52c51905a8216af93685b5","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"6132aa0973454379674ea6cbc77e6eace1e1032dd9f38182071388a036f1bc08","src/unix/bsd/freebsdlike/mod.rs":"728c8a3852d04b0f7b0bf635cb330cb162a062e1b06f8d7b0078227df89dc412","src/unix/bsd/mod.rs":"b9975c103fad8f79f295bd60b65f7313206236a6b3cbbc51f8636822f49c803b","src/unix/bsd/netbsdlike/mod.rs":"4d236620acff436309f47323e457c16c793b44ccd38b3c404feda154ca1f3f72","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"b38fc046f9a40fea28bd26328b96629f4d5d63d7524936bd6af1865d401a8716","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"6cec8833e7f3fc25e1e6cdd3d2c7d705aed9def01c3de99dd097d5009e5a5535","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/mod.rs":"4d28dc8440487c05032e863488570a1e157cb92d0facb39de98e64916f1e6343","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"e59b7fd65f68f8e857eec39e0c03bac1d3af6ddc26c9ba58494336b83659bb9b","src/unix/haiku/b32.rs":"69ae47fc52c6880e85416b4744500d5655c9ec6131cb737f3b649fceaadce15a","src/unix/haiku/b64.rs":"73e64db09275a8da8d50a13cce2cfa2b136036ddf3a930d2939f337fc995900b","src/unix/haiku/mod.rs":"34d74b3f86953c4bdba363b7b629fd3fc72d3842260ba208f91b9dc6024634ff","src/unix/haiku/native.rs":"7d21ea1c9bb2d9fd17ef30eab1cd61bacd111f2cdbafee1f44f7b9fc5fbd919d","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"d971b98530a96f5892f98e1edc3133cf278d1b3939d77ab0a27a6323e0961715","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/mod.rs":"b58280177c280cecc8f5649bc18d445bacdeada3a873bf58bdf8146a56e29d69","src/unix/linux_like/android/b64/mod.rs":"5d94d05d8c10a748f0b1f67a4abaf4dd8415351e14e3bc6c84f6a46c8e18874c","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"06b22dc184e85a988ab969c75cadc52b9878faeab0eb9d21215878c95fe07c19","src/unix/linux_like/android/mod.rs":"f59260119a91675777d0f956e62cae0ca719dc2399978e23ebd754b146eb93ef","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"6ef97140ca6fb24125fdd0aacb986ef785aa21993229660d7f703f8875ebfe49","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"213e70ebed2703e14a9cf17666b21ecbf180b7bff7fa22fdbb36dbbd52df326d","src/unix/linux_like/linux/arch/generic/mod.rs":"ff1fe8fad4ea15d9bec3db25efcfcb4939190c5189f86cfa4d05825aa8c10956","src/unix/linux_like/linux/arch/mips/mod.rs":"e4a980b002105aaa057eb6568e1e2c6168ade5c00e13a31ef67e316ddffdb900","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"1789eb5b41f75c29239795124a4a7cdcf7c8d213b88cf581b2f5bda08d7cf15b","src/unix/linux_like/linux/arch/sparc/mod.rs":"ded708124ee610267d011dee31fb02d1ec697c334aa822776ec95a7ddf6fc541","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"3fed009dc9af3cc81be7087da9d2d7d1f39845e4497e290259c5cdbae25f039d","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"07adf9f4b96854062db518aaf08521fde0ad4a21a5c049efccba437bd97b2b5a","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"1cb5c0c9df3af2bbe131a91593583259fac9118931744c8435e197a394eb0462","src/unix/linux_like/linux/gnu/b32/mod.rs":"794dbcbae7dae8fd6b0b814573243197ceb532b56ef0772ad86b4b401478fcd9","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"0cd7348badb9c4f8a0db31a2503b30c456a2bfcc7a0e5919762b1e12f912c5ad","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"9c628cd97806181dc4d34b072f63fe1eb42f08108712002e0628ffe27f2fa93f","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"1bcec269a8416ccc48a384ca5765eaaa23f30f39f32311f50008ef4eeadafb2f","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"5317dbf2323577b89370bbee3894882b89d8333176db4f7b271ddc2f036ef43c","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c3730792dabcc166d8fd22929ef2633d49bc626875382dfcd401e8e125fb7a84","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"68bcb71bbfccb4e8648948e494366d94767ce96f36daab9c1329375cdd32a459","src/unix/linux_like/linux/gnu/b64/mod.rs":"6336065423c26b59681fd2ce77f1117ea36af13e163fdadaefd108bd8191e8c8","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"dbb8905e363ed4a2dfb984554ad9b6389d27f6a2d599ec2d80e38a6c7551a019","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"18edaa89c9746125863ff53182e0ef32cb1e1612e1ed9a2672558a9de85440e9","src/unix/linux_like/linux/gnu/b64/s390x.rs":"d9bb4e524e70d6fef49e0f77d89a92f478fd95d9a1aea32f4dc845275a7465d4","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"26fda11bdce99372c2c246e60866b56d98beb9fb49a2f6b69347ecfd03d18255","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"5a5ce7c5c92f60d8900dce63d363a38f3126aaf5be981710e172bec96ef95ac6","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"f775ac2b754f90b63053fe22afe1d19d306b5404995568d6805baa9249fb617f","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"4ba1b58468f55254717366f50fdfd3e4114fde6dc442a56681926c4d7e5b6b0d","src/unix/linux_like/linux/gnu/mod.rs":"cc296f6b1f0a97edfc0f025d9196c3e451752982d94f126f61eca0eb2367a779","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"d6f8e72a6d67e0af6d1f7a09420f92906a52ae226a66f43268064249ce7019df","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"6255abe2ee04986832d12b7b2190589580f2a43e9bfb285b32b5747227f62727","src/unix/linux_like/linux/musl/b32/hexagon.rs":"a8811791809672be8338e6e27d1c4fcf383c2f26585be8bf9ab2923b219de032","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"b9e9ff42363ebbb884ddf6445129ec4164471df45846874fc08f5f458e659254","src/unix/linux_like/linux/musl/b32/mod.rs":"8ede3985e6243882814ce91e8ce543e7edbafc0cee5932816072b6f14207a671","src/unix/linux_like/linux/musl/b32/powerpc.rs":"4592dc5f1f2fe888dfef85fa862d42d168e73a2c6f4fc052b58287d0f4d4ffcd","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"a19a8decfab185af3cebd34aae4b15082e7552be573904b8c1a3f0c0e493ef34","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"798a9229d70ce235394f2dd625f6c4c1e10519a94382dc5b091952b638ae2928","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"a73035c6d9b776f13b839008e15c04c2c53455571efd06664affcb047e457112","src/unix/linux_like/linux/musl/b64/mips64.rs":"2744895451f3a777fbe54f7f2695be53310b965fd62084c9b7e9121c7fe28346","src/unix/linux_like/linux/musl/b64/mod.rs":"d18abc0aeba2e26342bf3416a4dba0836db2bb0ee013b0a39629475cf8640289","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"e5a55525b42493923956d668f978fb45e22d51deea00ce5edbfddf76ff19c741","src/unix/linux_like/linux/musl/b64/s390x.rs":"03dfec6794d93cb31a7c52b2d53a0973755168f91f8fa437cc5dbd54882c8ee7","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"0dd168f5a6881f32e5239fb312b23cf137b800d0ff323286a92c8a2c382b5456","src/unix/linux_like/linux/musl/mod.rs":"f0e202a92ea839c42c1176f416ece21e69ba809795b8035768b10d3813c95892","src/unix/linux_like/linux/no_align.rs":"5ed04c53bf9d27da9b4d65ba7625c6ac53330162683d1b3df98950caafa3507b","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"9b691eeec0a9bf7b2abb87e09062d2c148d18e11c96ecad0edd0b74d1d0509fd","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"18753a99b820d69e062e3ba22a63fa86577b6dcc42f740479c7be1a4c658e1be","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"e3085ba56cfbc528d7c3c55065880603238c333b6047ef51c58177508a487fcd","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"656fbf5157ab6d06fc365a8353b138818ad5b8429ea5628ff35a3972c63a1a7c","src/unix/linux_like/linux/uclibc/mod.rs":"22f712c3e08fd8cb37e274718de1bac09966a4cd4b0f018f28737bc30940b8af","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"bb31053d6403091e11f95ac2203982f279f8b984a19adf30796878c45fdd8c25","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"02e21c0550a423a3f6db0a0af6a0f37cf5937feb2562a490e0ad0e09a8d9fc77","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"92de4f454e1e520a804613f020b35e7c8aa533f2a7375a769738b69a9ccdb53d","src/unix/mod.rs":"a5fbb90b99244f04bb37dc7d79d56261f5c5a41e9a09b7958aed9a2b4882eae8","src/unix/newlib/aarch64/mod.rs":"bb269c1468a9676442554600e87417079a787fe6220dfc23b3109639259e8710","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"c71be856bfd7f576b2db28af9f680211cbe6c1cac7d537bbc8020b39591af07c","src/unix/newlib/mod.rs":"407fe7e3c77f4c4c129788b3888a7da5d4b7b818ed3e96abb8de8cd780f83fb6","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"2d0f7af28b47f7a2a6c210ebd1c1f33ed8eac62e56b5af2b856de2ad3fdc5187","src/unix/newlib/xtensa/mod.rs":"08b314a27797ee27989f48f5a0e66e0d73670071ceabd341076cdce7ea67201c","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"6dcfe2212ea37e8e293c8fe7acc1319035594e9b951bd64c071f1a2a8be9b91e","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"be7cf5334fc8f2c6bc1b856288e53af7f90a92bd64793eb19b60b660383e508c","src/unix/solarish/mod.rs":"0cd1b335854994eca1928155234cf779bb5bc04afc2d6c60d930b480652dd24f","src/unix/solarish/solaris.rs":"65b005453aefa9b9d4fc860fe77cfec80d8c97a51342b15daf55fc3e808bb384","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"9caf6ff3faad5b39c9deb8eae497a61ef15aa5e03aa409a16299e700240c3b63","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"3800e710a40322fe0229f7665b18542dc066680c4d151e3c4f29f82202a1c294","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"2b960d585c2fc0c82659cc4caeaa3268e67a8de0a0390d084629eefd39a14c8d","src/windows/msvc.rs":"ea6d87a6a9cd668261b1c043e7c36cf599e80b5d09f6e4502e85daa4797c7927","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"}
\ No newline at end of file
index 65701bfc7de704bc70839b36faf8432c872caee9..4c7ac6c783fa80c2a6246191fa9447de08c471b4 100644 (file)
@@ -12,7 +12,7 @@
 
 [package]
 name = "libc"
-version = "0.2.95"
+version = "0.2.98"
 authors = ["The Rust Project Developers"]
 build = "build.rs"
 exclude = ["/ci/*", "/.github/*", "/.cirrus.yml", "/triagebot.toml"]
index cdd25ce3eccba5ca4f8044353df17e54fb342b28..4300338ba0b03b5bcac88e415fce86dc075a5730 100644 (file)
@@ -1768,8 +1768,10 @@ pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP;
 pub const SOCK_RAW: ::c_int = 3;
 pub const SOCK_RDM: ::c_int = 4;
 
+pub const IP_TOS: ::c_int = 1;
 pub const IP_TTL: ::c_int = 2;
 pub const IP_HDRINCL: ::c_int = 3;
+pub const IP_RECVTOS: ::c_int = 13;
 pub const IP_FREEBIND: ::c_int = 15;
 pub const IP_TRANSPARENT: ::c_int = 19;
 pub const IP_MULTICAST_IF: ::c_int = 32;
index 7a2f0ed7bb8701ff6c5b7dc5340d51a87ed848b2..a489050e4d96649058bafcdb6b1f253a004fa063 100644 (file)
@@ -29,6 +29,7 @@ pub type cpu_subtype_t = integer_t;
 pub type natural_t = u32;
 pub type mach_msg_type_number_t = natural_t;
 pub type kern_return_t = ::c_int;
+pub type uuid_t = [u8; 16];
 
 pub type posix_spawnattr_t = *mut ::c_void;
 pub type posix_spawn_file_actions_t = *mut ::c_void;
@@ -76,6 +77,10 @@ pub type thread_latency_qos_policy_t = *mut thread_latency_qos_policy;
 pub type thread_throughput_qos_policy_data_t = thread_throughput_qos_policy;
 pub type thread_throughput_qos_policy_t = *mut thread_throughput_qos_policy;
 
+pub type CCStatus = i32;
+pub type CCCryptorStatus = i32;
+pub type CCRNGStatus = ::CCCryptorStatus;
+
 deprecated_mach! {
     pub type vm_prot_t = ::c_int;
     pub type vm_size_t = ::uintptr_t;
@@ -628,6 +633,32 @@ s! {
     pub struct thread_throughput_qos_policy {
         pub thread_throughput_qos_tier: thread_throughput_qos_t,
     }
+
+    // malloc/malloc.h
+    pub struct malloc_statistics_t {
+        pub blocks_in_use: ::c_uint,
+        pub size_in_use: ::size_t,
+        pub max_size_in_use: ::size_t,
+        pub size_allocated: ::size_t,
+    }
+
+    pub struct mstats {
+        pub bytes_total: ::size_t,
+        pub chunks_used: ::size_t,
+        pub bytes_used: ::size_t,
+        pub chunks_free: ::size_t,
+        pub bytes_free: ::size_t,
+    }
+
+    pub struct malloc_zone_t {
+        __private: [::uintptr_t; 18], // FIXME: keeping private for now
+    }
+
+    // sched.h
+    pub struct sched_param {
+        pub sched_priority: ::c_int,
+        __opaque: [::c_char; 4],
+    }
 }
 
 s_no_extra_traits! {
@@ -3341,18 +3372,10 @@ pub const DLT_LOOP: ::c_uint = 108;
 pub const BPF_ALIGNMENT: ::c_int = 4;
 
 // sys/mount.h
-pub const MNT_RDONLY: ::c_int = 0x00000001;
-pub const MNT_SYNCHRONOUS: ::c_int = 0x00000002;
-pub const MNT_NOEXEC: ::c_int = 0x00000004;
-pub const MNT_NOSUID: ::c_int = 0x00000008;
 pub const MNT_NODEV: ::c_int = 0x00000010;
 pub const MNT_UNION: ::c_int = 0x00000020;
-pub const MNT_ASYNC: ::c_int = 0x00000040;
 pub const MNT_CPROTECT: ::c_int = 0x00000080;
 
-// NFS export related mount flags.
-pub const MNT_EXPORTED: ::c_int = 0x00000100;
-
 // MAC labeled / "quarantined" flag
 pub const MNT_QUARANTINE: ::c_int = 0x00000400;
 
@@ -3373,9 +3396,7 @@ pub const MNT_NOATIME: ::c_int = 0x10000000;
 pub const MNT_SNAPSHOT: ::c_int = 0x40000000;
 
 // External filesystem command modifier flags.
-pub const MNT_UPDATE: ::c_int = 0x00010000;
 pub const MNT_NOBLOCK: ::c_int = 0x00020000;
-pub const MNT_RELOAD: ::c_int = 0x00040000;
 
 // sys/spawn.h:
 pub const POSIX_SPAWN_RESETIDS: ::c_int = 0x01;
@@ -3504,6 +3525,21 @@ pub const THREAD_BACKGROUND_POLICY_DARWIN_BG: ::c_int = 0x1000;
 pub const THREAD_LATENCY_QOS_POLICY: ::c_int = 7;
 pub const THREAD_THROUGHPUT_QOS_POLICY: ::c_int = 8;
 
+// CommonCrypto/CommonCryptoError.h
+pub const kCCSuccess: i32 = 0;
+pub const kCCParamError: i32 = -4300;
+pub const kCCBufferTooSmall: i32 = -4301;
+pub const kCCMemoryFailure: i32 = -4302;
+pub const kCCAlignmentError: i32 = -4303;
+pub const kCCDecodeError: i32 = -4304;
+pub const kCCUnimplemented: i32 = -4305;
+pub const kCCOverflow: i32 = -4306;
+pub const kCCRNGFailure: i32 = -4307;
+pub const kCCUnspecifiedError: i32 = -4308;
+pub const kCCCallSequenceError: i32 = -4309;
+pub const kCCKeySizeError: i32 = -4310;
+pub const kCCInvalidKey: i32 = -4311;
+
 cfg_if! {
     if #[cfg(libc_const_extern_fn)] {
         const fn __DARWIN_ALIGN32(p: usize) -> usize {
@@ -3583,6 +3619,10 @@ f! {
         (__DARWIN_ALIGN32(::mem::size_of::<::cmsghdr>()) + length as usize)
             as ::c_uint
     }
+
+    pub {const} fn VM_MAKE_TAG(id: u8) -> u32 {
+        (id as u32) << 24u32
+    }
 }
 
 safe_f! {
@@ -3757,6 +3797,26 @@ extern "C" {
         class: *mut qos_class_t,
         priority: *mut ::c_int,
     ) -> ::c_int;
+    pub fn pthread_attr_getschedparam(
+        attr: *const ::pthread_attr_t,
+        param: *mut sched_param,
+    ) -> ::c_int;
+    pub fn pthread_attr_setschedparam(
+        attr: *mut ::pthread_attr_t,
+        param: *const sched_param,
+    ) -> ::c_int;
+    pub fn pthread_getschedparam(
+        thread: ::pthread_t,
+        policy: *mut ::c_int,
+        param: *mut sched_param,
+    ) -> ::c_int;
+    pub fn pthread_setschedparam(
+        thread: ::pthread_t,
+        policy: ::c_int,
+        param: *const sched_param,
+    ) -> ::c_int;
+    pub fn sched_get_priority_min(policy: ::c_int) -> ::c_int;
+    pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int;
     pub fn thread_policy_set(
         thread: thread_t,
         flavor: thread_policy_flavor_t,
@@ -4049,6 +4109,48 @@ extern "C" {
     // Added in macOS 10.13
     // ISO/IEC 9899:2011 ("ISO C11") K.3.7.4.1
     pub fn memset_s(s: *mut ::c_void, smax: ::size_t, c: ::c_int, n: ::size_t) -> ::c_int;
+    // Added in macOS 10.5
+    pub fn memset_pattern4(b: *mut ::c_void, pattern4: *const ::c_void, len: ::size_t);
+    pub fn memset_pattern8(b: *mut ::c_void, pattern8: *const ::c_void, len: ::size_t);
+    pub fn memset_pattern16(b: *mut ::c_void, pattern16: *const ::c_void, len: ::size_t);
+
+    pub fn mstats() -> mstats;
+    pub fn malloc_printf(format: *const ::c_char, ...);
+    pub fn malloc_zone_check(zone: *mut ::malloc_zone_t) -> ::boolean_t;
+    pub fn malloc_zone_print(zone: *mut ::malloc_zone_t, verbose: ::boolean_t);
+    pub fn malloc_zone_statistics(zone: *mut ::malloc_zone_t, stats: *mut malloc_statistics_t);
+    pub fn malloc_zone_log(zone: *mut ::malloc_zone_t, address: *mut ::c_void);
+    pub fn malloc_zone_print_ptr_info(ptr: *mut ::c_void);
+    pub fn malloc_default_zone() -> *mut ::malloc_zone_t;
+    pub fn malloc_zone_from_ptr(ptr: *const ::c_void) -> *mut ::malloc_zone_t;
+    pub fn malloc_zone_malloc(zone: *mut ::malloc_zone_t, size: ::size_t) -> *mut ::c_void;
+    pub fn malloc_zone_valloc(zone: *mut ::malloc_zone_t, size: ::size_t) -> *mut ::c_void;
+    pub fn malloc_zone_calloc(
+        zone: *mut ::malloc_zone_t,
+        num_items: ::size_t,
+        size: ::size_t,
+    ) -> *mut ::c_void;
+    pub fn malloc_zone_realloc(
+        zone: *mut ::malloc_zone_t,
+        ptr: *mut ::c_void,
+        size: ::size_t,
+    ) -> *mut ::c_void;
+    pub fn malloc_zone_free(zone: *mut ::malloc_zone_t, ptr: *mut ::c_void);
+
+    pub fn proc_listpids(
+        t: u32,
+        typeinfo: u32,
+        buffer: *mut ::c_void,
+        buffersize: ::c_int,
+    ) -> ::c_int;
+    pub fn proc_listallpids(buffer: *mut ::c_void, buffersize: ::c_int) -> ::c_int;
+    pub fn proc_listpgrppids(
+        pgrpid: ::pid_t,
+        buffer: *mut ::c_void,
+        buffersize: ::c_int,
+    ) -> ::c_int;
+    pub fn proc_listchildpids(ppid: ::pid_t, buffer: *mut ::c_void, buffersize: ::c_int)
+        -> ::c_int;
     pub fn proc_pidinfo(
         pid: ::c_int,
         flavor: ::c_int,
@@ -4063,8 +4165,43 @@ extern "C" {
         buffer: *mut ::c_void,
         buffersize: ::c_int,
     ) -> ::c_int;
+    pub fn proc_pidfileportinfo(
+        pid: ::c_int,
+        fileport: u32,
+        flavor: ::c_int,
+        buffer: *mut ::c_void,
+        buffersize: ::c_int,
+    ) -> ::c_int;
     pub fn proc_pidpath(pid: ::c_int, buffer: *mut ::c_void, buffersize: u32) -> ::c_int;
     pub fn proc_name(pid: ::c_int, buffer: *mut ::c_void, buffersize: u32) -> ::c_int;
+    pub fn proc_regionfilename(
+        pid: ::c_int,
+        address: u64,
+        buffer: *mut ::c_void,
+        buffersize: u32,
+    ) -> ::c_int;
+    pub fn proc_libversion(major: *mut ::c_int, mintor: *mut ::c_int) -> ::c_int;
+    /// # Notes
+    ///
+    /// `id` is of type [`uuid_t`].
+    pub fn gethostuuid(id: *mut u8, timeout: *const ::timespec) -> ::c_int;
+
+    pub fn CCRandomGenerateBytes(bytes: *mut ::c_void, size: ::size_t) -> ::CCRNGStatus;
+
+    pub fn _NSGetExecutablePath(buf: *mut ::c_char, bufsize: *mut u32) -> ::c_int;
+}
+
+cfg_if! {
+    if #[cfg(target_os = "macos")] {
+        extern "C" {
+            pub fn memmem(
+                haystack: *const ::c_void,
+                haystacklen: ::size_t,
+                needle: *const ::c_void,
+                needlelen: ::size_t,
+            ) -> *mut ::c_void;
+        }
+    }
 }
 
 #[link(name = "iconv")]
index 71529421ea7cb77e60f00fbfc6bcd523c063d481..02e7a8af06e2dc876aed31168fe1b72f11efde0c 100644 (file)
@@ -25,6 +25,12 @@ pub type sem_t = *mut sem;
 pub type cpuset_t = cpumask_t;
 pub type cpu_set_t = cpumask_t;
 
+pub type register_t = ::c_long;
+pub type umtx_t = ::c_int;
+pub type pthread_barrierattr_t = ::c_int;
+pub type pthread_barrier_t = ::uintptr_t;
+pub type pthread_spinlock_t = ::uintptr_t;
+
 #[cfg_attr(feature = "extra_traits", derive(Debug))]
 pub enum sem {}
 impl ::Copy for sem {}
@@ -253,6 +259,51 @@ s_no_extra_traits! {
         pub sigev_value: ::sigval,
         __unused3: *mut ::c_void        //actually a function pointer
     }
+
+    pub struct mcontext_t {
+        pub mc_onstack: register_t,
+        pub mc_rdi: register_t,
+        pub mc_rsi: register_t,
+        pub mc_rdx: register_t,
+        pub mc_rcx: register_t,
+        pub mc_r8: register_t,
+        pub mc_r9: register_t,
+        pub mc_rax: register_t,
+        pub mc_rbx: register_t,
+        pub mc_rbp: register_t,
+        pub mc_r10: register_t,
+        pub mc_r11: register_t,
+        pub mc_r12: register_t,
+        pub mc_r13: register_t,
+        pub mc_r14: register_t,
+        pub mc_r15: register_t,
+        pub mc_xflags: register_t,
+        pub mc_trapno: register_t,
+        pub mc_addr: register_t,
+        pub mc_flags: register_t,
+        pub mc_err: register_t,
+        pub mc_rip: register_t,
+        pub mc_cs: register_t,
+        pub mc_rflags: register_t,
+        pub mc_rsp: register_t,
+        pub mc_ss: register_t,
+        pub mc_len: ::c_uint,
+        pub mc_fpformat: ::c_uint,
+        pub mc_ownedfp: ::c_uint,
+        __reserved: ::c_uint,
+        __unused: [::c_uint; 8],
+        pub mc_fpregs: [[::c_uint; 8]; 32],
+    }
+
+    pub struct ucontext_t {
+        pub uc_sigmask: ::sigset_t,
+        pub uc_mcontext: mcontext_t,
+        pub uc_link: *mut ucontext_t,
+        pub uc_stack: stack_t,
+        pub uc_cofunc: ::Option<unsafe extern "C" fn(uc: *mut ucontext_t, arg: *mut ::c_void)>,
+        pub uc_arg: *mut ::c_void,
+        __pad: [::c_int; 4],
+    }
 }
 
 cfg_if! {
@@ -452,6 +503,100 @@ cfg_if! {
                 self.sigev_value.hash(state);
             }
         }
+        impl PartialEq for mcontext_t {
+            fn eq(&self, other: &mcontext_t) -> bool {
+                self.mc_onstack == other.mc_onstack &&
+                self.mc_rdi == other.mc_rdi &&
+                self.mc_rsi == other.mc_rsi &&
+                self.mc_rdx == other.mc_rdx &&
+                self.mc_rcx == other.mc_rcx &&
+                self.mc_r8 == other.mc_r8 &&
+                self.mc_r9 == other.mc_r9 &&
+                self.mc_rax == other.mc_rax &&
+                self.mc_rbx == other.mc_rbx &&
+                self.mc_rbp == other.mc_rbp &&
+                self.mc_r10 == other.mc_r10 &&
+                self.mc_r11 == other.mc_r11 &&
+                self.mc_r12 == other.mc_r12 &&
+                self.mc_r13 == other.mc_r13 &&
+                self.mc_r14 == other.mc_r14 &&
+                self.mc_r15 == other.mc_r15 &&
+                self.mc_xflags == other.mc_xflags &&
+                self.mc_trapno == other.mc_trapno &&
+                self.mc_addr == other.mc_addr &&
+                self.mc_flags == other.mc_flags &&
+                self.mc_err == other.mc_err &&
+                self.mc_rip == other.mc_rip &&
+                self.mc_cs == other.mc_cs &&
+                self.mc_rflags == other.mc_rflags &&
+                self.mc_rsp == other.mc_rsp &&
+                self.mc_ss == other.mc_ss &&
+                self.mc_len == other.mc_len &&
+                self.mc_fpformat == other.mc_fpformat &&
+                self.mc_ownedfp == other.mc_ownedfp
+                // FIXME: self.mc_fpregs == other.mc_fpregs
+            }
+        }
+        impl Eq for mcontext_t {}
+        impl ::fmt::Debug for mcontext_t {
+            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                f.debug_struct("mcontext_t")
+                    .field("mc_onstack", &self.mc_onstack)
+                    .field("mc_rdi", &self.mc_rdi)
+                    .field("mc_rsi", &self.mc_rsi)
+                    .field("mc_rdx", &self.mc_rdx)
+                    .field("mc_rcx", &self.mc_rcx)
+                    .field("mc_r8", &self.mc_r8)
+                    .field("mc_r9", &self.mc_r9)
+                    .field("mc_rax", &self.mc_rax)
+                    .field("mc_rbx", &self.mc_rbx)
+                    .field("mc_rbp", &self.mc_rbp)
+                    .field("mc_r10", &self.mc_r10)
+                    .field("mc_r11", &self.mc_r11)
+                    .field("mc_r12", &self.mc_r12)
+                    .field("mc_r13", &self.mc_r13)
+                    .field("mc_r14", &self.mc_r14)
+                    .field("mc_r15", &self.mc_r15)
+                    .field("mc_xflags", &self.mc_xflags)
+                    .field("mc_trapno", &self.mc_trapno)
+                    .field("mc_addr", &self.mc_addr)
+                    .field("mc_flags", &self.mc_flags)
+                    .field("mc_err", &self.mc_err)
+                    .field("mc_rip", &self.mc_rip)
+                    .field("mc_cs", &self.mc_cs)
+                    .field("mc_rflags", &self.mc_rflags)
+                    .field("mc_rsp", &self.mc_rsp)
+                    .field("mc_ss", &self.mc_ss)
+                    .field("mc_len", &self.mc_len)
+                    .field("mc_fpformat", &self.mc_fpformat)
+                    .field("mc_ownedfp", &self.mc_ownedfp)
+                    // FIXME: .field("mc_fpregs", &self.mc_fpregs)
+                    .finish()
+            }
+        }
+        impl PartialEq for ucontext_t {
+            fn eq(&self, other: &ucontext_t) -> bool {
+                self.uc_sigmask == other.uc_sigmask
+                    && self.uc_mcontext == other.uc_mcontext
+                    && self.uc_link == other.uc_link
+                    && self.uc_stack == other.uc_stack
+                    && self.uc_cofunc == other.uc_cofunc
+                    && self.uc_arg == other.uc_arg
+            }
+        }
+        impl Eq for ucontext_t {}
+        impl ::fmt::Debug for ucontext_t {
+            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                f.debug_struct("ucontext_t")
+                    .field("uc_sigmask", &self.uc_sigmask)
+                    .field("uc_mcontext", &self.uc_mcontext)
+                    .field("uc_link", &self.uc_link)
+                    .field("uc_stack", &self.uc_stack)
+                    .field("uc_cofunc", &self.uc_cofunc)
+                    .field("uc_arg", &self.uc_arg)
+                    .finish()
+            }
+        }
     }
 }
 
@@ -1128,9 +1273,16 @@ extern "C" {
         needle: *const ::c_void,
         needlelen: ::size_t,
     ) -> *mut ::c_void;
+    pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: ::c_int) -> ::c_int;
+    pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> ::c_int;
+
     pub fn sched_getaffinity(pid: ::pid_t, cpusetsize: ::size_t, mask: *mut cpu_set_t) -> ::c_int;
     pub fn sched_setaffinity(pid: ::pid_t, cpusetsize: ::size_t, mask: *const cpu_set_t)
         -> ::c_int;
+    pub fn setproctitle(fmt: *const ::c_char, ...);
 }
 
 #[link(name = "rt")]
index 36e0d5144107de35dc7332bc63cf065930884ceb..2def90089f240832a04aa00b105daf9df019c82f 100644 (file)
@@ -228,6 +228,9 @@ extern "C" {
 
     pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t;
     pub fn elf_aux_info(aux: ::c_int, buf: *mut ::c_void, buflen: ::c_int) -> ::c_int;
+    pub fn setproctitle_fast(fmt: *const ::c_char, ...);
+    pub fn timingsafe_bcmp(a: *const ::c_void, b: *const ::c_void, len: ::size_t) -> ::c_int;
+    pub fn timingsafe_memcmp(a: *const ::c_void, b: *const ::c_void, len: ::size_t) -> ::c_int;
 }
 
 cfg_if! {
index 8cb475d9b1abbdd937bead0eafd05539e4981132..b150e04d54d424928012714780dee095758226ae 100644 (file)
@@ -233,6 +233,9 @@ extern "C" {
     pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t;
     pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int;
     pub fn elf_aux_info(aux: ::c_int, buf: *mut ::c_void, buflen: ::c_int) -> ::c_int;
+    pub fn setproctitle_fast(fmt: *const ::c_char, ...);
+    pub fn timingsafe_bcmp(a: *const ::c_void, b: *const ::c_void, len: ::size_t) -> ::c_int;
+    pub fn timingsafe_memcmp(a: *const ::c_void, b: *const ::c_void, len: ::size_t) -> ::c_int;
 }
 
 cfg_if! {
index 9a64dc39fdd5885fea719a397501c66d6beefeef..1d24a8f5cd037e042bec9730793de3f4a62d0bfe 100644 (file)
@@ -21,6 +21,10 @@ pub type mqd_t = *mut ::c_void;
 pub type posix_spawnattr_t = *mut ::c_void;
 pub type posix_spawn_file_actions_t = *mut ::c_void;
 
+pub type pthread_spinlock_t = *mut __c_anonymous_pthread_spinlock;
+pub type pthread_barrierattr_t = *mut __c_anonymous_pthread_barrierattr;
+pub type pthread_barrier_t = *mut __c_anonymous_pthread_barrier;
+
 s! {
     pub struct aiocb {
         pub aio_fildes: ::c_int,
@@ -112,6 +116,11 @@ s! {
         pub sc_groups: [::gid_t; 1],
     }
 
+    pub struct accept_filter_arg {
+        pub af_name: [::c_char; 16],
+        af_arg: [[::c_char; 10]; 24],
+    }
+
     pub struct ptrace_vm_entry {
         pub pve_entry: ::c_int,
         pub pve_timestamp: ::c_int,
@@ -135,6 +144,42 @@ s! {
     pub struct cap_rights_t {
         cr_rights: [u64; 2],
     }
+
+    pub struct umutex {
+        m_owner: ::lwpid_t,
+        m_flags: u32,
+        m_ceilings: [u32; 2],
+        m_rb_link: ::uintptr_t,
+        #[cfg(target_pointer_width = "32")]
+        m_pad: u32,
+        m_spare: [u32; 2],
+
+    }
+
+    pub struct ucond {
+        c_has_waiters: u32,
+        c_flags: u32,
+        c_clockid: u32,
+        c_spare: [u32; 1],
+    }
+
+    pub struct __c_anonymous_pthread_spinlock {
+        s_clock: umutex,
+    }
+
+    pub struct __c_anonymous_pthread_barrierattr {
+        pshared: ::c_int,
+    }
+
+    pub struct __c_anonymous_pthread_barrier {
+        b_lock: umutex,
+        b_cv: ucond,
+        b_cycle: i64,
+        b_count: ::c_int,
+        b_waiters: ::c_int,
+        b_refcount: ::c_int,
+        b_destroying: ::c_int,
+    }
 }
 
 s_no_extra_traits! {
@@ -707,6 +752,16 @@ pub const JAIL_SYS_DISABLE: ::c_int = 0;
 pub const JAIL_SYS_NEW: ::c_int = 1;
 pub const JAIL_SYS_INHERIT: ::c_int = 2;
 
+pub const MNT_ACLS: ::c_int = 0x08000000;
+pub const MNT_BYFSID: ::c_int = 0x08000000;
+pub const MNT_GJOURNAL: ::c_int = 0x02000000;
+pub const MNT_MULTILABEL: ::c_int = 0x04000000;
+pub const MNT_NFS4ACLS: ::c_int = 0x00000010;
+pub const MNT_SNAPSHOT: ::c_int = 0x01000000;
+pub const MNT_UNION: ::c_int = 0x00000020;
+pub const MNT_EXPUBLIC: ::c_int = 0x20000000;
+pub const MNT_NONBUSY: ::c_int = 0x04000000;
+
 pub const SO_BINTIME: ::c_int = 0x2000;
 pub const SO_NO_OFFLOAD: ::c_int = 0x4000;
 pub const SO_NO_DDP: ::c_int = 0x8000;
@@ -1234,6 +1289,17 @@ pub const HOSTNAME_INCORRECTNAME: ::c_int = 1;
 pub const HOSTNAME_INVALIDADDR: ::c_int = 2;
 pub const HOSTNAME_INVALIDNAME: ::c_int = 3;
 
+// For rfork
+pub const RFFDG: ::c_int = 4;
+pub const RFPROC: ::c_int = 16;
+pub const RFMEM: ::c_int = 32;
+pub const RFNOWAIT: ::c_int = 64;
+pub const RFCFDG: ::c_int = 4096;
+pub const RFTHREAD: ::c_int = 8192;
+pub const RFLINUXTHPN: ::c_int = 65536;
+pub const RFTSIGZMB: ::c_int = 524288;
+pub const RFSPAWN: ::c_int = 2147483648;
+
 const_fn! {
     {const} fn _ALIGN(p: usize) -> usize {
         (p + _ALIGNBYTES) & !_ALIGNBYTES
@@ -1550,6 +1616,24 @@ extern "C" {
         newfd: ::c_int,
     ) -> ::c_int;
 
+    pub fn pthread_getthreadid_np() -> ::c_int;
+    pub fn pthread_getaffinity_np(
+        td: ::pthread_t,
+        cpusetsize: ::size_t,
+        cpusetp: *mut cpuset_t,
+    ) -> ::c_int;
+    pub fn pthread_setaffinity_np(
+        td: ::pthread_t,
+        cpusetsize: ::size_t,
+        cpusetp: *const cpuset_t,
+    ) -> ::c_int;
+
+    pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: ::c_int) -> ::c_int;
+    pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> ::c_int;
+
     #[cfg_attr(all(target_os = "freebsd", freebsd11), link_name = "statfs@FBSD_1.0")]
     pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int;
     #[cfg_attr(all(target_os = "freebsd", freebsd11), link_name = "fstatfs@FBSD_1.0")]
@@ -1579,6 +1663,8 @@ extern "C" {
     ) -> *mut ::c_void;
 
     pub fn nmount(iov: *mut ::iovec, niov: ::c_uint, flags: ::c_int) -> ::c_int;
+    pub fn setproctitle(fmt: *const ::c_char, ...);
+    pub fn rfork(flags: ::c_int) -> ::c_int;
     pub fn cpuset_getaffinity(
         level: cpulevel_t,
         which: cpuwhich_t,
@@ -1606,6 +1692,8 @@ extern "C" {
     pub fn cap_rights_remove(dst: *mut cap_rights_t, src: *const cap_rights_t)
         -> *mut cap_rights_t;
     pub fn cap_rights_contains(big: *const cap_rights_t, little: *const cap_rights_t) -> bool;
+
+    pub fn reallocarray(ptr: *mut ::c_void, nmemb: ::size_t, size: ::size_t) -> *mut ::c_void;
 }
 
 #[link(name = "util")]
@@ -1658,6 +1746,9 @@ cfg_if! {
     } else if #[cfg(target_arch = "powerpc64")] {
         mod powerpc64;
         pub use self::powerpc64::*;
+    } else if #[cfg(target_arch = "powerpc")] {
+        mod powerpc;
+        pub use self::powerpc::*;
     } else {
         // Unknown target_arch
     }
diff --git a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/powerpc.rs b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/powerpc.rs
new file mode 100644 (file)
index 0000000..a0120c3
--- /dev/null
@@ -0,0 +1,47 @@
+pub type c_char = u8;
+pub type c_long = i32;
+pub type c_ulong = u32;
+pub type wchar_t = i32;
+pub type time_t = i64;
+pub type suseconds_t = i32;
+pub type register_t = i32;
+
+s! {
+    pub struct stat {
+        pub st_dev: ::dev_t,
+        pub st_ino: ::ino_t,
+        pub st_mode: ::mode_t,
+        pub st_nlink: ::nlink_t,
+        pub st_uid: ::uid_t,
+        pub st_gid: ::gid_t,
+        pub st_rdev: ::dev_t,
+        pub st_atime: ::time_t,
+        pub st_atime_nsec: ::c_long,
+        pub st_mtime: ::time_t,
+        pub st_mtime_nsec: ::c_long,
+        pub st_ctime: ::time_t,
+        pub st_ctime_nsec: ::c_long,
+        pub st_size: ::off_t,
+        pub st_blocks: ::blkcnt_t,
+        pub st_blksize: ::blksize_t,
+        pub st_flags: ::fflags_t,
+        pub st_gen: u32,
+        pub st_lspare: i32,
+        pub st_birthtime: ::time_t,
+        pub st_birthtime_nsec: ::c_long,
+    }
+}
+
+// should be pub(crate), but that requires Rust 1.18.0
+cfg_if! {
+    if #[cfg(libc_const_size_of)] {
+        #[doc(hidden)]
+        pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_int>() - 1;
+    } else {
+        #[doc(hidden)]
+        pub const _ALIGNBYTES: usize = 4 - 1;
+    }
+}
+
+pub const MAP_32BIT: ::c_int = 0x00080000;
+pub const MINSIGSTKSZ: ::size_t = 2048; // 512 * 4
index b0400c34ae62954c589dbd81038a07dbd56c4d54..4ca6c2a397e6c1714a815e27b295b45e885fe850 100644 (file)
@@ -592,6 +592,18 @@ pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void;
 pub const MCL_CURRENT: ::c_int = 0x0001;
 pub const MCL_FUTURE: ::c_int = 0x0002;
 
+pub const MNT_NOATIME: ::c_int = 0x10000000;
+pub const MNT_NOCLUSTERR: ::c_int = 0x40000000;
+pub const MNT_NOCLUSTERW: ::c_int = 0x80000000;
+pub const MNT_NOSYMFOLLOW: ::c_int = 0x00400000;
+pub const MNT_SOFTDEP: ::c_int = 0x00200000;
+pub const MNT_SUIDDIR: ::c_int = 0x00100000;
+pub const MNT_EXRDONLY: ::c_int = 0x00000080;
+pub const MNT_DEFEXPORTED: ::c_int = 0x00000200;
+pub const MNT_EXPORTANON: ::c_int = 0x00000400;
+pub const MNT_EXKERB: ::c_int = 0x00000800;
+pub const MNT_DELEXPORT: ::c_int = 0x00020000;
+
 pub const MS_SYNC: ::c_int = 0x0000;
 pub const MS_ASYNC: ::c_int = 0x0001;
 pub const MS_INVALIDATE: ::c_int = 0x0002;
@@ -1501,6 +1513,23 @@ extern "C" {
         val: *mut ::c_int,
     ) -> ::c_int;
     pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: ::c_int) -> ::c_int;
+    pub fn pthread_barrierattr_init(attr: *mut ::pthread_barrierattr_t) -> ::c_int;
+    pub fn pthread_barrierattr_destroy(attr: *mut ::pthread_barrierattr_t) -> ::c_int;
+    pub fn pthread_barrierattr_getpshared(
+        attr: *const ::pthread_barrierattr_t,
+        shared: *mut ::c_int,
+    ) -> ::c_int;
+    pub fn pthread_barrierattr_setpshared(
+        attr: *mut ::pthread_barrierattr_t,
+        shared: ::c_int,
+    ) -> ::c_int;
+    pub fn pthread_barrier_init(
+        barrier: *mut pthread_barrier_t,
+        attr: *const ::pthread_barrierattr_t,
+        count: ::c_uint,
+    ) -> ::c_int;
+    pub fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> ::c_int;
+    pub fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> ::c_int;
     pub fn pthread_set_name_np(tid: ::pthread_t, name: *const ::c_char);
     pub fn ptrace(request: ::c_int, pid: ::pid_t, addr: *mut ::c_char, data: ::c_int) -> ::c_int;
     pub fn pututxline(ut: *const utmpx) -> *mut utmpx;
index f86a0080e66213205d21c4154ce32b2d104da389..156d3d60760ff336e33a1ce4073d69a87876ab13 100644 (file)
@@ -337,7 +337,15 @@ pub const F_RDLCK: ::c_short = 1;
 pub const F_UNLCK: ::c_short = 2;
 pub const F_WRLCK: ::c_short = 3;
 
-pub const MNT_FORCE: ::c_int = 0x80000;
+pub const MNT_RDONLY: ::c_int = 0x00000001;
+pub const MNT_SYNCHRONOUS: ::c_int = 0x00000002;
+pub const MNT_NOEXEC: ::c_int = 0x00000004;
+pub const MNT_NOSUID: ::c_int = 0x00000008;
+pub const MNT_ASYNC: ::c_int = 0x00000040;
+pub const MNT_EXPORTED: ::c_int = 0x00000100;
+pub const MNT_UPDATE: ::c_int = 0x00010000;
+pub const MNT_RELOAD: ::c_int = 0x00040000;
+pub const MNT_FORCE: ::c_int = 0x00080000;
 
 pub const Q_SYNC: ::c_int = 0x600;
 pub const Q_QUOTAON: ::c_int = 0x100;
@@ -852,6 +860,10 @@ extern "C" {
     ) -> ::size_t;
 
     pub fn regfree(preg: *mut regex_t);
+
+    pub fn arc4random() -> u32;
+    pub fn arc4random_buf(buf: *mut ::c_void, size: ::size_t);
+    pub fn arc4random_uniform(l: u32) -> u32;
 }
 
 cfg_if! {
index 7e7269fcff5918fffbec73c4fb86c29ad368bda2..e7e376309bca291f4ff328ea59adaf9fd7ac9978 100644 (file)
@@ -712,6 +712,11 @@ extern "C" {
         lock: *mut pthread_mutex_t,
         abstime: *const ::timespec,
     ) -> ::c_int;
+    pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: ::c_int) -> ::c_int;
+    pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> ::c_int;
     pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int;
 
     pub fn getgrouplist(
@@ -731,6 +736,10 @@ extern "C" {
     pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int;
 }
 
+extern "C" {
+    pub fn reallocarray(ptr: *mut ::c_void, nmemb: ::size_t, size: ::size_t) -> *mut ::c_void;
+}
+
 cfg_if! {
     if #[cfg(target_os = "netbsd")] {
         mod netbsd;
index f2fc288be3e9a1c6d2712c95b19eeca7546d703d..d998f57ec924c386f857bd2c7a51cd440421a8e4 100644 (file)
@@ -10,6 +10,9 @@ type __pthread_spin_t = __cpu_simple_lock_nv_t;
 pub type vm_size_t = ::uintptr_t; // FIXME: deprecated since long time
 pub type lwpid_t = ::c_uint;
 pub type shmatt_t = ::c_uint;
+pub type cpuid_t = u64;
+pub type cpuset_t = _cpuset;
+pub type pthread_spin_t = ::c_uchar;
 
 // elf.h
 
@@ -44,6 +47,10 @@ cfg_if! {
 }
 
 impl siginfo_t {
+    pub unsafe fn si_addr(&self) -> *mut ::c_void {
+        self.si_addr
+    }
+
     pub unsafe fn si_value(&self) -> ::sigval {
         #[repr(C)]
         struct siginfo_timer {
@@ -57,6 +64,23 @@ impl siginfo_t {
         }
         (*(self as *const siginfo_t as *const siginfo_timer)).value
     }
+
+    pub unsafe fn si_status(&self) -> ::c_int {
+        #[repr(C)]
+        struct siginfo_timer {
+            _si_signo: ::c_int,
+            _si_errno: ::c_int,
+            _si_code: ::c_int,
+            __pad1: ::c_int,
+            _pid: ::pid_t,
+            _uid: ::uid_t,
+            _value: ::sigval,
+            _cpid: ::pid_t,
+            _cuid: ::uid_t,
+            status: ::c_int,
+        }
+        (*(self as *const siginfo_t as *const siginfo_timer)).status
+    }
 }
 
 s! {
@@ -203,13 +227,19 @@ s! {
         ptr_private: *mut ::c_void,
     }
 
+    pub struct pthread_spinlock_t {
+        pts_magic: ::c_uint,
+        pts_spin: ::pthread_spin_t,
+        pts_flags: ::c_int,
+    }
+
     pub struct kevent {
         pub ident: ::uintptr_t,
         pub filter: u32,
         pub flags: u32,
         pub fflags: u32,
         pub data: i64,
-        pub udata: ::intptr_t,
+        pub udata: ::intptr_t, /* FIXME: NetBSD 10.0 will finally have same layout as other BSD */
     }
 
     pub struct dqblk {
@@ -425,6 +455,19 @@ s! {
         pub dlpi_tls_modid: usize,
         pub dlpi_tls_data: *mut ::c_void,
     }
+
+    pub struct _cpuset {
+        bits: [u32; 0]
+    }
+
+    pub struct accept_filter_arg {
+        pub af_name: [::c_char; 16],
+        af_arg: [[::c_char; 10]; 24],
+    }
+
+    pub struct sched_param {
+        pub sched_priority: ::c_int,
+    }
 }
 
 s_no_extra_traits! {
@@ -1200,6 +1243,8 @@ pub const MAP_RENAME: ::c_int = 0x20;
 pub const MAP_NORESERVE: ::c_int = 0x40;
 pub const MAP_HASSEMAPHORE: ::c_int = 0x200;
 pub const MAP_WIRED: ::c_int = 0x800;
+// mremap flag
+pub const MAP_REMAPDUP: ::c_int = 0x004;
 
 pub const DCCP_TYPE_REQUEST: ::c_int = 0;
 pub const DCCP_TYPE_RESPONSE: ::c_int = 1;
@@ -1502,6 +1547,15 @@ pub const NOTE_CHILD: u32 = 0x00000004;
 pub const TMP_MAX: ::c_uint = 308915776;
 
 pub const NI_MAXHOST: ::socklen_t = 1025;
+pub const NI_MAXSERV: ::socklen_t = 32;
+
+pub const NI_NOFQDN: ::c_int = 0x00000001;
+pub const NI_NUMERICHOST: ::c_int = 0x000000002;
+pub const NI_NAMEREQD: ::c_int = 0x000000004;
+pub const NI_NUMERICSERV: ::c_int = 0x000000008;
+pub const NI_DGRAM: ::c_int = 0x00000010;
+pub const NI_WITHSCOPEID: ::c_int = 0x00000020;
+pub const NI_NUMERICSCOPE: ::c_int = 0x00000040;
 
 pub const RTLD_NOLOAD: ::c_int = 0x2000;
 pub const RTLD_LOCAL: ::c_int = 0x200;
@@ -1839,6 +1893,8 @@ extern "C" {
         rqtp: *const ::timespec,
         rmtp: *mut ::timespec,
     ) -> ::c_int;
+
+    pub fn reallocarr(ptr: *mut ::c_void, number: ::size_t, size: ::size_t) -> ::c_int;
 }
 
 #[link(name = "rt")]
@@ -2031,6 +2087,24 @@ extern "C" {
         stackaddr: *mut *mut ::c_void,
         stacksize: *mut ::size_t,
     ) -> ::c_int;
+    pub fn pthread_getaffinity_np(
+        thread: ::pthread_t,
+        size: ::size_t,
+        set: *mut cpuset_t,
+    ) -> ::c_int;
+    pub fn pthread_setaffinity_np(
+        thread: ::pthread_t,
+        size: ::size_t,
+        set: *mut cpuset_t,
+    ) -> ::c_int;
+
+    pub fn _cpuset_create() -> *mut cpuset_t;
+    pub fn _cpuset_destroy(set: *mut cpuset_t);
+    pub fn _cpuset_clr(cpu: cpuid_t, set: *mut cpuset_t) -> ::c_int;
+    pub fn _cpuset_set(cpu: cpuid_t, set: *mut cpuset_t) -> ::c_int;
+    pub fn _cpuset_isset(cpu: cpuid_t, set: *const cpuset_t) -> ::c_int;
+    pub fn _cpuset_size(set: *const cpuset_t) -> ::size_t;
+    pub fn _cpuset_zero(set: *mut cpuset_t);
     #[link_name = "__sigtimedwait50"]
     pub fn sigtimedwait(
         set: *const sigset_t,
@@ -2038,6 +2112,13 @@ extern "C" {
         timeout: *const ::timespec,
     ) -> ::c_int;
     pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> ::c_int;
+    pub fn waitid(
+        idtype: idtype_t,
+        id: ::id_t,
+        infop: *mut ::siginfo_t,
+        options: ::c_int,
+    ) -> ::c_int;
+
     pub fn duplocale(base: ::locale_t) -> ::locale_t;
     pub fn freelocale(loc: ::locale_t);
     pub fn localeconv_l(loc: ::locale_t) -> *mut lconv;
@@ -2100,6 +2181,19 @@ extern "C" {
 
     // Added in `NetBSD` 7.0
     pub fn explicit_memset(b: *mut ::c_void, c: ::c_int, len: ::size_t);
+    pub fn consttime_memequal(a: *const ::c_void, b: *const ::c_void, len: ::size_t) -> ::c_int;
+
+    pub fn setproctitle(fmt: *const ::c_char, ...);
+    pub fn mremap(
+        oldp: *mut ::c_void,
+        oldsize: ::size_t,
+        newp: *mut ::c_void,
+        newsize: ::size_t,
+        flags: ::c_int,
+    ) -> *mut ::c_void;
+
+    pub fn sched_setparam(pid: ::pid_t, param: *const sched_param) -> ::c_int;
+    pub fn sched_getparam(pid: ::pid_t, param: *mut sched_param) -> ::c_int;
 }
 
 #[link(name = "util")]
@@ -2136,6 +2230,34 @@ extern "C" {
     pub fn setutent();
     pub fn endutent();
     pub fn getutent() -> *mut utmp;
+
+    pub fn efopen(p: *const ::c_char, m: *const ::c_char) -> ::FILE;
+    pub fn emalloc(n: ::size_t) -> *mut ::c_void;
+    pub fn ecalloc(n: ::size_t, c: ::size_t) -> *mut ::c_void;
+    pub fn erealloc(p: *mut ::c_void, n: ::size_t) -> *mut ::c_void;
+    pub fn estrdup(s: *const ::c_char) -> *mut ::c_char;
+    pub fn estrndup(s: *const ::c_char, len: ::size_t) -> *mut ::c_char;
+    pub fn estrlcpy(dst: *mut ::c_char, src: *const ::c_char, len: ::size_t) -> ::size_t;
+    pub fn estrlcat(dst: *mut ::c_char, src: *const ::c_char, len: ::size_t) -> ::size_t;
+    pub fn easprintf(string: *mut *mut ::c_char, fmt: *const ::c_char, ...) -> ::c_int;
+    pub fn evasprintf(string: *mut *mut ::c_char, fmt: *const ::c_char, ...) -> ::c_int;
+    pub fn esetfunc(
+        cb: ::Option<unsafe extern "C" fn(::c_int, *const ::c_char, ...)>,
+    ) -> ::Option<unsafe extern "C" fn(::c_int, *const ::c_char, ...)>;
+    pub fn secure_path(path: *const ::c_char) -> ::c_int;
+    pub fn snprintb(
+        buf: *mut ::c_char,
+        buflen: ::size_t,
+        fmt: *const ::c_char,
+        val: u64,
+    ) -> ::c_int;
+    pub fn snprintb_m(
+        buf: *mut ::c_char,
+        buflen: ::size_t,
+        fmt: *const ::c_char,
+        val: u64,
+        max: ::size_t,
+    ) -> ::c_int;
 }
 
 cfg_if! {
index 803ceac5b82397443c26a129100efa008b60e67c..038048ef17f4a39ea79337524d5cb7fc1f3af00a 100644 (file)
@@ -14,6 +14,7 @@ pub type pthread_cond_t = *mut ::c_void;
 pub type pthread_condattr_t = *mut ::c_void;
 pub type pthread_rwlock_t = *mut ::c_void;
 pub type pthread_rwlockattr_t = *mut ::c_void;
+pub type pthread_spinlock_t = ::uintptr_t;
 pub type caddr_t = *mut ::c_char;
 
 // elf.h
@@ -386,6 +387,10 @@ s! {
 }
 
 impl siginfo_t {
+    pub unsafe fn si_addr(&self) -> *mut ::c_char {
+        self.si_addr
+    }
+
     pub unsafe fn si_value(&self) -> ::sigval {
         #[repr(C)]
         struct siginfo_timer {
@@ -1526,6 +1531,7 @@ extern "C" {
     pub fn pthread_main_np() -> ::c_int;
     pub fn pthread_set_name_np(tid: ::pthread_t, name: *const ::c_char);
     pub fn pthread_stackseg_np(thread: ::pthread_t, sinfo: *mut ::stack_t) -> ::c_int;
+
     pub fn sysctl(
         name: *const ::c_int,
         namelen: ::c_uint,
@@ -1562,6 +1568,8 @@ extern "C" {
 
     // Added in `OpenBSD` 5.5
     pub fn explicit_bzero(s: *mut ::c_void, len: ::size_t);
+
+    pub fn setproctitle(fmt: *const ::c_char, ...);
 }
 
 cfg_if! {
index 8a53e5399413478272076211d824a7b320e57185..33d2fa07078d3f38bb7e6778097a57b63e767719 100644 (file)
@@ -138,7 +138,7 @@ cfg_if! {
                         self.uc_stack.hash(state);
                         self.uc_mcontext.hash(state);
                         self.uc_sigmask__c_anonymous_union.hash(state);
-                        &self.uc_regspace[..].hash(state);
+                        self.uc_regspace[..].hash(state);
                         // Ignore padding field
                     }
                 }
index fc4b3f150f361019392a4797f90233830beddbb7..fabf3838f083ffa7bd88b4f28511f4105f7362df 100644 (file)
@@ -8,6 +8,7 @@ pub type off64_t = ::c_longlong;
 pub type sigset_t = ::c_ulong;
 pub type socklen_t = i32;
 pub type time64_t = i64;
+pub type __u64 = ::c_ulonglong;
 
 s! {
     pub struct sigaction {
@@ -119,6 +120,14 @@ s! {
         __reserved: [::c_char; 12],
     }
 
+    pub struct pthread_barrier_t {
+        __private: [i32; 8],
+    }
+
+    pub struct pthread_spinlock_t {
+        __private: [i32; 2],
+    }
+
     pub struct passwd {
         pub pw_name: *mut ::c_char,
         pub pw_passwd: *mut ::c_char,
index 4912ff5d8ee8a1594bfdc22cc469b5073dd1afa7..a63f670d016ab427f9e1dbb9dca44cdaff8aae2b 100644 (file)
@@ -1,5 +1,6 @@
 pub type c_char = u8;
 pub type wchar_t = u32;
+pub type __u64 = ::c_ulonglong;
 
 s! {
     pub struct stat {
index c23e2dbf2df1dcf06047d080e108dd63d673dc52..0278c35782d9f0914300951e2a7f6b10aa368a1d 100644 (file)
@@ -105,6 +105,14 @@ s! {
         pub f_namemax: ::c_ulong,
         __f_spare: [::c_int; 6],
     }
+
+    pub struct pthread_barrier_t {
+        __private: [i64; 4],
+    }
+
+    pub struct pthread_spinlock_t {
+        __private: i64,
+    }
 }
 
 s_no_extra_traits! {
index 27fd17b3ffb34e4b8f08304c29c9be3baa4faaa5..7542cc6c6f49ad01a5edbd4864c543573d189a19 100644 (file)
@@ -1,6 +1,7 @@
 pub type c_char = i8;
 pub type wchar_t = i32;
 pub type greg_t = i64;
+pub type __u64 = ::c_ulonglong;
 
 s! {
     pub struct stat {
index d2b04dc3f26b0a4479b5cd475f413681da1bcaa3..f48cd49fd11ead4435bbae597869d69918d4f57f 100644 (file)
@@ -11,6 +11,7 @@ pub type useconds_t = u32;
 pub type pthread_t = ::c_long;
 pub type pthread_mutexattr_t = ::c_long;
 pub type pthread_rwlockattr_t = ::c_long;
+pub type pthread_barrierattr_t = ::c_int;
 pub type pthread_condattr_t = ::c_long;
 pub type pthread_key_t = ::c_int;
 pub type fsfilcnt_t = ::c_ulong;
@@ -26,6 +27,12 @@ pub type loff_t = ::c_longlong;
 pub type __kernel_loff_t = ::c_longlong;
 pub type __kernel_pid_t = ::c_int;
 
+pub type __u8 = ::c_uchar;
+pub type __u16 = ::c_ushort;
+pub type __s16 = ::c_short;
+pub type __u32 = ::c_uint;
+pub type __s32 = ::c_int;
+
 // linux/elf.h
 
 pub type Elf32_Addr = u32;
@@ -86,6 +93,19 @@ s! {
         pub c_ospeed: ::speed_t,
     }
 
+    pub struct mallinfo {
+        pub arena: ::size_t,
+        pub ordblks: ::size_t,
+        pub smblks: ::size_t,
+        pub hblks: ::size_t,
+        pub hblkhd: ::size_t,
+        pub usmblks: ::size_t,
+        pub fsmblks: ::size_t,
+        pub uordblks: ::size_t,
+        pub fordblks: ::size_t,
+        pub keepcost: ::size_t,
+    }
+
     pub struct flock {
         pub l_type: ::c_short,
         pub l_whence: ::c_short,
@@ -308,6 +328,27 @@ s! {
         pub dlpi_tls_modid: ::size_t,
         pub dlpi_tls_data: *mut ::c_void,
     }
+
+    // linux/filter.h
+    pub struct sock_filter {
+        pub code: ::__u16,
+        pub jt: ::__u8,
+        pub jf: ::__u8,
+        pub k: ::__u32,
+    }
+
+    pub struct sock_fprog {
+        pub len: ::c_ushort,
+        pub filter: *mut sock_filter,
+    }
+
+    // linux/seccomp.h
+    pub struct seccomp_data {
+        pub nr: ::c_int,
+        pub arch: ::__u32,
+        pub instruction_pointer: ::__u64,
+        pub args: [::__u64; 6],
+    }
 }
 
 s_no_extra_traits! {
@@ -1728,6 +1769,25 @@ pub const SECCOMP_MODE_DISABLED: ::c_uint = 0;
 pub const SECCOMP_MODE_STRICT: ::c_uint = 1;
 pub const SECCOMP_MODE_FILTER: ::c_uint = 2;
 
+pub const SECCOMP_FILTER_FLAG_TSYNC: ::c_ulong = 1;
+pub const SECCOMP_FILTER_FLAG_LOG: ::c_ulong = 2;
+pub const SECCOMP_FILTER_FLAG_SPEC_ALLOW: ::c_ulong = 4;
+pub const SECCOMP_FILTER_FLAG_NEW_LISTENER: ::c_ulong = 8;
+
+pub const SECCOMP_RET_ACTION_FULL: ::c_uint = 0xffff0000;
+pub const SECCOMP_RET_ACTION: ::c_uint = 0x7fff0000;
+pub const SECCOMP_RET_DATA: ::c_uint = 0x0000ffff;
+
+pub const SECCOMP_RET_KILL_PROCESS: ::c_uint = 0x80000000;
+pub const SECCOMP_RET_KILL_THREAD: ::c_uint = 0x00000000;
+pub const SECCOMP_RET_KILL: ::c_uint = SECCOMP_RET_KILL_THREAD;
+pub const SECCOMP_RET_TRAP: ::c_uint = 0x00030000;
+pub const SECCOMP_RET_ERRNO: ::c_uint = 0x00050000;
+pub const SECCOMP_RET_USER_NOTIF: ::c_uint = 0x7fc00000;
+pub const SECCOMP_RET_TRACE: ::c_uint = 0x7ff00000;
+pub const SECCOMP_RET_LOG: ::c_uint = 0x7ffc0000;
+pub const SECCOMP_RET_ALLOW: ::c_uint = 0x7fff0000;
+
 pub const NLA_F_NESTED: ::c_int = 1 << 15;
 pub const NLA_F_NET_BYTEORDER: ::c_int = 1 << 14;
 pub const NLA_TYPE_MASK: ::c_int = !(NLA_F_NESTED | NLA_F_NET_BYTEORDER);
@@ -2482,6 +2542,8 @@ extern "C" {
     pub fn __sched_cpufree(set: *mut ::cpu_set_t);
     pub fn __sched_cpucount(setsize: ::size_t, set: *const cpu_set_t) -> ::c_int;
     pub fn sched_getcpu() -> ::c_int;
+    pub fn mallinfo() -> ::mallinfo;
+    pub fn malloc_usable_size(ptr: *const ::c_void) -> ::size_t;
 
     pub fn utmpname(name: *const ::c_char) -> ::c_int;
     pub fn setutent();
@@ -2616,6 +2678,28 @@ extern "C" {
         lock: *mut pthread_mutex_t,
         abstime: *const ::timespec,
     ) -> ::c_int;
+    pub fn pthread_barrierattr_init(attr: *mut ::pthread_barrierattr_t) -> ::c_int;
+    pub fn pthread_barrierattr_destroy(attr: *mut ::pthread_barrierattr_t) -> ::c_int;
+    pub fn pthread_barrierattr_getpshared(
+        attr: *const ::pthread_barrierattr_t,
+        shared: *mut ::c_int,
+    ) -> ::c_int;
+    pub fn pthread_barrierattr_setpshared(
+        attr: *mut ::pthread_barrierattr_t,
+        shared: ::c_int,
+    ) -> ::c_int;
+    pub fn pthread_barrier_init(
+        barrier: *mut pthread_barrier_t,
+        attr: *const ::pthread_barrierattr_t,
+        count: ::c_uint,
+    ) -> ::c_int;
+    pub fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> ::c_int;
+    pub fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> ::c_int;
+    pub fn pthread_spin_init(lock: *mut ::pthread_spinlock_t, pshared: ::c_int) -> ::c_int;
+    pub fn pthread_spin_destroy(lock: *mut ::pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_lock(lock: *mut ::pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_trylock(lock: *mut ::pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_unlock(lock: *mut ::pthread_spinlock_t) -> ::c_int;
     pub fn clone(
         cb: extern "C" fn(*mut ::c_void) -> ::c_int,
         child_stack: *mut ::c_void,
@@ -2791,6 +2875,10 @@ extern "C" {
         >,
         data: *mut ::c_void,
     ) -> ::c_int;
+
+    pub fn arc4random() -> u32;
+    pub fn arc4random_uniform(__upper_bound: u32) -> u32;
+    pub fn arc4random_buf(__buf: *mut ::c_void, __n: ::size_t);
 }
 
 cfg_if! {
index f2ddeb2926f1d0f275f101ae3781e46526cd01d7..b83415a393a078096c950be6acc322041ac2d461 100644 (file)
@@ -1153,9 +1153,6 @@ pub const ITIMER_REAL: ::c_int = 0;
 pub const ITIMER_VIRTUAL: ::c_int = 1;
 pub const ITIMER_PROF: ::c_int = 2;
 
-pub const XATTR_CREATE: ::c_int = 0x1;
-pub const XATTR_REPLACE: ::c_int = 0x2;
-
 pub const _POSIX_VDISABLE: ::cc_t = 0;
 
 pub const FALLOC_FL_KEEP_SIZE: ::c_int = 0x01;
index 239492b1c94db00f417cb8feb5de804ea7f3832f..418c638063466852754559817e5521ec698a1cc0 100644 (file)
@@ -14,6 +14,7 @@ pub type __u64 = ::c_ulonglong;
 pub type __fsword_t = i32;
 pub type fsblkcnt64_t = u64;
 pub type fsfilcnt64_t = u64;
+pub type __syscall_ulong_t = ::c_ulong;
 
 cfg_if! {
     if #[cfg(target_arch = "riscv32")] {
@@ -138,6 +139,23 @@ s! {
         pub imr_address: ::in_addr,
         pub imr_ifindex: ::c_int,
     }
+
+    pub struct semid_ds {
+        pub sem_perm: ipc_perm,
+        #[cfg(target_arch = "powerpc")]
+        __reserved: ::__syscall_ulong_t,
+        pub sem_otime: ::time_t,
+        #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))]
+        __reserved: ::__syscall_ulong_t,
+        #[cfg(target_arch = "powerpc")]
+        __reserved2: ::__syscall_ulong_t,
+        pub sem_ctime: ::time_t,
+        #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))]
+        __reserved2: ::__syscall_ulong_t,
+        pub sem_nsems: ::__syscall_ulong_t,
+        __glibc_reserved3: ::__syscall_ulong_t,
+        __glibc_reserved4: ::__syscall_ulong_t,
+    }
 }
 
 pub const POSIX_FADV_DONTNEED: ::c_int = 4;
index 138adc910c801180c297a5f4b0f90507602fdf90..db82f26dc996e5eff88991169f1bd1e9ee932afe 100644 (file)
@@ -9,6 +9,11 @@ pub type msglen_t = u64;
 pub type fsblkcnt_t = u64;
 pub type fsfilcnt_t = u64;
 pub type rlim_t = u64;
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+pub type __syscall_ulong_t = ::c_ulonglong;
+#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
+pub type __syscall_ulong_t = ::c_ulong;
+
 cfg_if! {
     if #[cfg(all(target_arch = "aarch64", target_pointer_width = "32"))] {
         pub type clock_t = i32;
@@ -60,6 +65,28 @@ s! {
         __glibc_reserved5: u64,
     }
 
+    pub struct semid_ds {
+        pub sem_perm: ipc_perm,
+        pub sem_otime: ::time_t,
+        #[cfg(not(any(
+            target_arch = "aarch64",
+            target_arch = "mips64",
+            target_arch = "powerpc64",
+            target_arch = "riscv64",
+            target_arch = "sparc64")))]
+        __reserved: ::__syscall_ulong_t,
+        pub sem_ctime: ::time_t,
+        #[cfg(not(any(
+            target_arch = "aarch64",
+            target_arch = "mips64",
+            target_arch = "powerpc64",
+            target_arch = "riscv64",
+            target_arch = "sparc64")))]
+        __reserved2: ::__syscall_ulong_t,
+        pub sem_nsems: ::__syscall_ulong_t,
+        __glibc_reserved3: ::__syscall_ulong_t,
+        __glibc_reserved4: ::__syscall_ulong_t,
+    }
 }
 
 pub const RLIM_INFINITY: ::rlim_t = !0;
index cc7e414f69c29e3ed0326dad52a495a2b1fc6090..44d43904ec364814adf03f95db54da0da8b31fd0 100644 (file)
@@ -128,6 +128,19 @@ s! {
         pub keepcost: ::c_int,
     }
 
+    pub struct mallinfo2 {
+        pub arena: ::size_t,
+        pub ordblks: ::size_t,
+        pub smblks: ::size_t,
+        pub hblks: ::size_t,
+        pub hblkhd: ::size_t,
+        pub usmblks: ::size_t,
+        pub fsmblks: ::size_t,
+        pub uordblks: ::size_t,
+        pub fordblks: ::size_t,
+        pub keepcost: ::size_t,
+    }
+
     pub struct nlmsghdr {
         pub nlmsg_len: u32,
         pub nlmsg_type: u16,
@@ -300,6 +313,19 @@ s! {
         pub ch_size: ::Elf32_Word,
         pub ch_addralign: ::Elf32_Word,
     }
+
+    pub struct seminfo {
+        pub semmap: ::c_int,
+        pub semmni: ::c_int,
+        pub semmns: ::c_int,
+        pub semmnu: ::c_int,
+        pub semmsl: ::c_int,
+        pub semopm: ::c_int,
+        pub semume: ::c_int,
+        pub semusz: ::c_int,
+        pub semvmx: ::c_int,
+        pub semaem: ::c_int,
+    }
 }
 
 impl siginfo_t {
@@ -1226,6 +1252,20 @@ extern "C" {
         offset: ::off_t,
         flags: ::c_int,
     ) -> ::ssize_t;
+    pub fn preadv64v2(
+        fd: ::c_int,
+        iov: *const ::iovec,
+        iovcnt: ::c_int,
+        offset: ::off64_t,
+        flags: ::c_int,
+    ) -> ::ssize_t;
+    pub fn pwritev64v2(
+        fd: ::c_int,
+        iov: *const ::iovec,
+        iovcnt: ::c_int,
+        offset: ::off64_t,
+        flags: ::c_int,
+    ) -> ::ssize_t;
     pub fn renameat2(
         olddirfd: ::c_int,
         oldpath: *const ::c_char,
@@ -1281,6 +1321,7 @@ extern "C" {
     ) -> ::c_int;
     pub fn sched_getcpu() -> ::c_int;
     pub fn mallinfo() -> ::mallinfo;
+    pub fn mallinfo2() -> ::mallinfo2;
     pub fn malloc_usable_size(ptr: *mut ::c_void) -> ::size_t;
     pub fn getpwent_r(
         pwd: *mut ::passwd,
@@ -1301,6 +1342,12 @@ extern "C" {
 extern "C" {
     pub fn dlmopen(lmid: Lmid_t, filename: *const ::c_char, flag: ::c_int) -> *mut ::c_void;
     pub fn dlinfo(handle: *mut ::c_void, request: ::c_int, info: *mut ::c_void) -> ::c_int;
+    pub fn dladdr1(
+        addr: *const ::c_void,
+        info: *mut ::Dl_info,
+        extra_info: *mut *mut ::c_void,
+        flags: ::c_int,
+    ) -> ::c_int;
 }
 
 cfg_if! {
index 74e34edd55cd90034ea3f8e346375fd111bace93..e2d492fc4162627afa0956cbf7406bb41ffb8d8e 100644 (file)
@@ -14,6 +14,7 @@ pub type nl_item = ::c_int;
 pub type idtype_t = ::c_uint;
 pub type loff_t = ::c_longlong;
 pub type pthread_key_t = ::c_uint;
+pub type pthread_spinlock_t = ::c_int;
 
 pub type __u8 = ::c_uchar;
 pub type __u16 = ::c_ushort;
@@ -541,6 +542,27 @@ s! {
         pub can_id: canid_t,
         pub can_mask: canid_t,
     }
+
+    // linux/filter.h
+    pub struct sock_filter {
+        pub code: ::__u16,
+        pub jt: ::__u8,
+        pub jf: ::__u8,
+        pub k: ::__u32,
+    }
+
+    pub struct sock_fprog {
+        pub len: ::c_ushort,
+        pub filter: *mut sock_filter,
+    }
+
+    // linux/seccomp.h
+    pub struct seccomp_data {
+        pub nr: ::c_int,
+        pub arch: ::__u32,
+        pub instruction_pointer: ::__u64,
+        pub args: [::__u64; 6],
+    }
 }
 
 s_no_extra_traits! {
@@ -1704,6 +1726,23 @@ pub const SECCOMP_MODE_DISABLED: ::c_uint = 0;
 pub const SECCOMP_MODE_STRICT: ::c_uint = 1;
 pub const SECCOMP_MODE_FILTER: ::c_uint = 2;
 
+pub const SECCOMP_FILTER_FLAG_TSYNC: ::c_ulong = 1;
+pub const SECCOMP_FILTER_FLAG_LOG: ::c_ulong = 2;
+pub const SECCOMP_FILTER_FLAG_SPEC_ALLOW: ::c_ulong = 4;
+
+pub const SECCOMP_RET_KILL_PROCESS: ::c_uint = 0x80000000;
+pub const SECCOMP_RET_KILL_THREAD: ::c_uint = 0x00000000;
+pub const SECCOMP_RET_KILL: ::c_uint = SECCOMP_RET_KILL_THREAD;
+pub const SECCOMP_RET_TRAP: ::c_uint = 0x00030000;
+pub const SECCOMP_RET_ERRNO: ::c_uint = 0x00050000;
+pub const SECCOMP_RET_TRACE: ::c_uint = 0x7ff00000;
+pub const SECCOMP_RET_LOG: ::c_uint = 0x7ffc0000;
+pub const SECCOMP_RET_ALLOW: ::c_uint = 0x7fff0000;
+
+pub const SECCOMP_RET_ACTION_FULL: ::c_uint = 0xffff0000;
+pub const SECCOMP_RET_ACTION: ::c_uint = 0x7fff0000;
+pub const SECCOMP_RET_DATA: ::c_uint = 0x0000ffff;
+
 pub const ITIMER_REAL: ::c_int = 0;
 pub const ITIMER_VIRTUAL: ::c_int = 1;
 pub const ITIMER_PROF: ::c_int = 2;
@@ -1712,9 +1751,6 @@ pub const TFD_CLOEXEC: ::c_int = O_CLOEXEC;
 pub const TFD_NONBLOCK: ::c_int = O_NONBLOCK;
 pub const TFD_TIMER_ABSTIME: ::c_int = 1;
 
-pub const XATTR_CREATE: ::c_int = 0x1;
-pub const XATTR_REPLACE: ::c_int = 0x2;
-
 pub const _POSIX_VDISABLE: ::cc_t = 0;
 
 pub const FALLOC_FL_KEEP_SIZE: ::c_int = 0x01;
@@ -1769,6 +1805,9 @@ pub const PT_LOOS: u32 = 0x60000000;
 pub const PT_GNU_EH_FRAME: u32 = 0x6474e550;
 pub const PT_GNU_STACK: u32 = 0x6474e551;
 pub const PT_GNU_RELRO: u32 = 0x6474e552;
+pub const PT_HIOS: u32 = 0x6fffffff;
+pub const PT_LOPROC: u32 = 0x70000000;
+pub const PT_HIPROC: u32 = 0x7fffffff;
 
 // linux/if_ether.h
 pub const ETH_ALEN: ::c_int = 6;
@@ -2997,6 +3036,11 @@ pub const SOL_CAN_BASE: ::c_int = 100;
 pub const CAN_INV_FILTER: canid_t = 0x20000000;
 pub const CAN_RAW_FILTER_MAX: ::c_int = 512;
 
+#[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))]
+pub const POLLRDHUP: ::c_int = 0x2000;
+#[cfg(any(target_arch = "sparc", target_arch = "sparc64"))]
+pub const POLLRDHUP: ::c_int = 0x800;
+
 f! {
     pub fn NLA_ALIGN(len: ::c_int) -> ::c_int {
         return ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1)
@@ -3317,7 +3361,7 @@ extern "C" {
     pub fn lremovexattr(path: *const c_char, name: *const c_char) -> ::c_int;
     pub fn fremovexattr(filedes: ::c_int, name: *const c_char) -> ::c_int;
     pub fn signalfd(fd: ::c_int, mask: *const ::sigset_t, flags: ::c_int) -> ::c_int;
-    pub fn timerfd_create(clockid: ::c_int, flags: ::c_int) -> ::c_int;
+    pub fn timerfd_create(clockid: ::clockid_t, flags: ::c_int) -> ::c_int;
     pub fn timerfd_gettime(fd: ::c_int, curr_value: *mut itimerspec) -> ::c_int;
     pub fn timerfd_settime(
         fd: ::c_int,
@@ -3519,6 +3563,11 @@ extern "C" {
         lock: *mut pthread_mutex_t,
         abstime: *const ::timespec,
     ) -> ::c_int;
+    pub fn pthread_spin_init(lock: *mut ::pthread_spinlock_t, pshared: ::c_int) -> ::c_int;
+    pub fn pthread_spin_destroy(lock: *mut ::pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_lock(lock: *mut ::pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_trylock(lock: *mut ::pthread_spinlock_t) -> ::c_int;
+    pub fn pthread_spin_unlock(lock: *mut ::pthread_spinlock_t) -> ::c_int;
     pub fn clone(
         cb: extern "C" fn(*mut ::c_void) -> ::c_int,
         child_stack: *mut ::c_void,
@@ -3773,6 +3822,21 @@ extern "C" {
     pub fn iconv_close(cd: iconv_t) -> ::c_int;
 
     pub fn gettid() -> ::pid_t;
+
+    pub fn timer_create(
+        clockid: ::clockid_t,
+        sevp: *mut ::sigevent,
+        timerid: *mut ::timer_t,
+    ) -> ::c_int;
+    pub fn timer_delete(timerid: ::timer_t) -> ::c_int;
+    pub fn timer_getoverrun(timerid: ::timer_t) -> ::c_int;
+    pub fn timer_gettime(timerid: ::timer_t, curr_value: *mut ::itimerspec) -> ::c_int;
+    pub fn timer_settime(
+        timerid: ::timer_t,
+        flags: ::c_int,
+        new_value: *const ::itimerspec,
+        old_value: *mut ::itimerspec,
+    ) -> ::c_int;
 }
 
 cfg_if! {
index 9c79f99980cfc5b3af32a052687bc34c7bada987..60a40e7ab0fd40dd4fd04618a2f86f3177cb4dce 100644 (file)
@@ -41,6 +41,8 @@ pub const MCL_FUTURE: ::c_int = 0x0002;
 
 pub const SIGEV_THREAD_ID: ::c_int = 4;
 
+pub const AF_VSOCK: ::c_int = 40;
+
 pub const ADFS_SUPER_MAGIC: ::c_long = 0x0000adf5;
 pub const AFFS_SUPER_MAGIC: ::c_long = 0x0000adff;
 pub const AFS_SUPER_MAGIC: ::c_long = 0x5346414f;
index 4a6d377a3a50961ba1f337b3672fea063acf52e8..48798849d04f4d7f065b9489593f6c6cdaf4741f 100644 (file)
@@ -2,6 +2,7 @@ pub type sa_family_t = u16;
 pub type speed_t = ::c_uint;
 pub type tcflag_t = ::c_uint;
 pub type clockid_t = ::c_int;
+pub type timer_t = *mut ::c_void;
 pub type key_t = ::c_int;
 pub type id_t = ::c_uint;
 
@@ -546,6 +547,9 @@ pub const PROT_READ: ::c_int = 1;
 pub const PROT_WRITE: ::c_int = 2;
 pub const PROT_EXEC: ::c_int = 4;
 
+pub const XATTR_CREATE: ::c_int = 0x1;
+pub const XATTR_REPLACE: ::c_int = 0x2;
+
 cfg_if! {
     if #[cfg(not(target_env = "uclibc"))] {
         pub const LC_CTYPE: ::c_int = 0;
@@ -1303,6 +1307,7 @@ pub const ARPHRD_ADAPT: u16 = 264;
 pub const ARPHRD_ROSE: u16 = 270;
 pub const ARPHRD_X25: u16 = 271;
 pub const ARPHRD_HWX25: u16 = 272;
+pub const ARPHRD_CAN: u16 = 280;
 pub const ARPHRD_PPP: u16 = 512;
 pub const ARPHRD_CISCO: u16 = 513;
 pub const ARPHRD_HDLC: u16 = ARPHRD_CISCO;
index 730bb690c4ae6b0eb9aae6201e1d89ce43565eb1..c4950193497b670b5ca69870e56012371b9fa46d 100644 (file)
@@ -37,4 +37,12 @@ extern "C" {
     pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int;
 
     pub fn mincore(addr: ::caddr_t, len: ::size_t, vec: *mut ::c_char) -> ::c_int;
+
+    pub fn pset_bind_lwp(
+        pset: ::psetid_t,
+        id: ::id_t,
+        pid: ::pid_t,
+        opset: *mut ::psetid_t,
+    ) -> ::c_int;
+    pub fn pset_getloadavg(pset: ::psetid_t, load: *mut ::c_double, num: ::c_int) -> ::c_int;
 }
index 6166da5d9ecebcf717cee92484eaa6d5f7aa404c..03879bf1069ffa69781c8b617a512b6cc164b211 100644 (file)
@@ -25,6 +25,8 @@ pub type wchar_t = ::c_int;
 pub type nfds_t = ::c_ulong;
 pub type projid_t = ::c_int;
 pub type zoneid_t = ::c_int;
+pub type psetid_t = ::c_int;
+pub type processorid_t = ::c_int;
 
 pub type suseconds_t = ::c_long;
 pub type off_t = ::c_long;
@@ -988,6 +990,9 @@ pub const FILENAME_MAX: ::c_uint = 1024;
 pub const L_tmpnam: ::c_uint = 25;
 pub const TMP_MAX: ::c_uint = 17576;
 
+pub const GRND_NONBLOCK: ::c_int = 0x0001;
+pub const GRND_RANDOM: ::c_int = 0x0002;
+
 pub const O_RDONLY: ::c_int = 0;
 pub const O_WRONLY: ::c_int = 1;
 pub const O_RDWR: ::c_int = 2;
@@ -1112,6 +1117,15 @@ pub const P_CTID: idtype_t = 13;
 pub const P_CPUID: idtype_t = 14;
 pub const P_PSETID: idtype_t = 15;
 
+pub const PS_NONE: ::c_int = -1;
+pub const PS_QUERY: ::c_int = -2;
+pub const PS_MYID: ::c_int = -3;
+pub const PS_SOFT: ::c_int = -4;
+pub const PS_HARD: ::c_int = -5;
+pub const PS_QUERY_TIME: ::c_int = -6;
+pub const PS_SYSTEM: ::c_int = 1;
+pub const PS_PRIVATE: ::c_int = 2;
+
 pub const UTIME_OMIT: c_long = -2;
 pub const UTIME_NOW: c_long = -1;
 
@@ -2227,6 +2241,8 @@ extern "C" {
     pub fn labs(i: ::c_long) -> ::c_long;
     pub fn rand() -> ::c_int;
     pub fn srand(seed: ::c_uint);
+    pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int;
+    pub fn getrandom(bbuf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t;
 
     pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int;
     pub fn settimeofday(tp: *const ::timeval, tz: *const ::c_void) -> ::c_int;
@@ -2607,6 +2623,32 @@ extern "C" {
     pub fn ucred_getpflags(ucred: *const ucred_t, flags: ::c_uint) -> ::c_uint;
 
     pub fn ucred_size() -> ::size_t;
+
+    pub fn pset_create(newpset: *mut ::psetid_t) -> ::c_int;
+    pub fn pset_destroy(pset: ::psetid_t) -> ::c_int;
+    pub fn pset_assign(pset: ::psetid_t, cpu: ::processorid_t, opset: *mut psetid_t) -> ::c_int;
+    pub fn pset_info(
+        pset: ::psetid_t,
+        tpe: *mut ::c_int,
+        numcpus: *mut ::c_uint,
+        cpulist: *mut processorid_t,
+    ) -> ::c_int;
+    pub fn pset_bind(
+        pset: ::psetid_t,
+        idtype: ::idtype_t,
+        id: ::id_t,
+        opset: *mut psetid_t,
+    ) -> ::c_int;
+    pub fn pset_list(pset: *mut psetid_t, numpsets: *mut ::c_uint) -> ::c_int;
+    pub fn pset_setattr(pset: psetid_t, attr: ::c_uint) -> ::c_int;
+    pub fn pset_getattr(pset: psetid_t, attr: *mut ::c_uint) -> ::c_int;
+    pub fn processor_bind(
+        idtype: ::idtype_t,
+        id: ::id_t,
+        new_binding: ::processorid_t,
+        old_binding: *mut processorid_t,
+    ) -> ::c_int;
+    pub fn p_online(processorid: ::processorid_t, flag: ::c_int) -> ::c_int;
 }
 
 mod compat;
index 6aefff8a2faae7cec94da70da30670f174c23b6f..0fc62802586359b6cb2f3b3a679f1db6947b1293 100644 (file)
@@ -201,6 +201,7 @@ pub const O_EXEC: c_int = 0x02000000;
 pub const O_RDONLY: c_int = 0x04000000;
 pub const O_SEARCH: c_int = 0x08000000;
 pub const O_WRONLY: c_int = 0x10000000;
+pub const O_CLOEXEC: c_int = 0x0;
 pub const O_RDWR: c_int = O_WRONLY | O_RDONLY;
 pub const O_ACCMODE: c_int = O_EXEC | O_RDWR | O_SEARCH;
 pub const O_NOCTTY: c_int = 0x0;
@@ -225,6 +226,18 @@ pub const S_IFREG: mode_t = 32768;
 pub const S_IFLNK: mode_t = 40960;
 pub const S_IFSOCK: mode_t = 49152;
 pub const S_IFMT: mode_t = 57344;
+pub const S_IXOTH: mode_t = 0x1;
+pub const S_IWOTH: mode_t = 0x2;
+pub const S_IROTH: mode_t = 0x4;
+pub const S_IXGRP: mode_t = 0x8;
+pub const S_IWGRP: mode_t = 0x10;
+pub const S_IRGRP: mode_t = 0x20;
+pub const S_IXUSR: mode_t = 0x40;
+pub const S_IWUSR: mode_t = 0x80;
+pub const S_IRUSR: mode_t = 0x100;
+pub const S_ISVTX: mode_t = 0x200;
+pub const S_ISGID: mode_t = 0x400;
+pub const S_ISUID: mode_t = 0x800;
 pub const DT_UNKNOWN: u8 = 0;
 pub const DT_BLK: u8 = 1;
 pub const DT_CHR: u8 = 2;
index 377a6c75f961e41bd9a158aebe7ac90cb6df22bf..ad0dc77d2319301f947f46b79acbd66bd295cd6b 100644 (file)
@@ -244,7 +244,13 @@ pub const SIGSEGV: ::c_int = 11;
 pub const SIGTERM: ::c_int = 15;
 pub const SIGABRT: ::c_int = 22;
 pub const NSIG: ::c_int = 23;
+
 pub const SIG_ERR: ::c_int = -1;
+pub const SIG_DFL: ::sighandler_t = 0;
+pub const SIG_IGN: ::sighandler_t = 1;
+pub const SIG_GET: ::sighandler_t = 2;
+pub const SIG_SGE: ::sighandler_t = 3;
+pub const SIG_ACK: ::sighandler_t = 4;
 
 // inline comment below appeases style checker
 #[cfg(all(target_env = "msvc", feature = "rustc-dep-of-std"))] // " if "
index a07e4189f191df2c2fd8ae96cbf8f1c9c573b092..53bacfda78878b5b35855e2d070f0166d011e019 100644 (file)
@@ -1 +1 @@
-{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"7badd40099fd459f028cb7bd6ade03a4cbdcc4cdb1b1ea865e897a3a51cf8d43","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"f77810103b6c10bd2234828f0d4de14b7b6e0000dcdaa5dec907a1b7a1b1dcb9","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","build.rs":"740225b5280e53e8d73971c6ccc55152d6af32e94132bc6980fdc0eb1fb3ab48","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/cow.rs":"873d2349577b333e8ae0a925855285f2db32b652455983b4511b67d928af7485","src/lib.rs":"bd81de1030e6553d1b711e0482f00864e78ca8888147b26cc2d08384ffd4fb89","src/memchr/c.rs":"34f7caf79316f4b03908832fdbd4aff367f2bc30eae291478cc5a0a108ce6e76","src/memchr/fallback.rs":"48764f18b7ff1f00a9ac1c4ed8ec96ad11f7b09b2d062a8ed3fe81160add627d","src/memchr/iter.rs":"61463e7fa22ca8f212c2cbfb882af0c87b0fb1bc6b4676678a4822a581ec1037","src/memchr/mod.rs":"d5bfc881c7c089e1a0825209a4d21c3f792f38c6f16f3bc715d0d539477376b6","src/memchr/naive.rs":"c7453bc99cc4e58eb37cf5a50c88688833e50a270ee1849baefddb8acc0ccd94","src/memchr/x86/avx.rs":"3c2750174ce7ff033daa4096e7961bbee9a2da898068266b27dee22ef8cfddad","src/memchr/x86/mod.rs":"a642d5aefdb7452ead4ab7946b5c6cfb6cc6df636dcd0ebbd6f5e6e1ac8305c0","src/memchr/x86/sse2.rs":"79ede1aba71a655e86eb5873d682c5da26933bffa4fffd7042a2313f18cf4675","src/memchr/x86/sse42.rs":"de4c6f354dbfec170876cddb8d9157b35928f96ed2339a0c5d094cc953a2f52d","src/memmem/byte_frequencies.rs":"2fb85b381c038c1e44ce94294531cdcd339dca48b1e61f41455666e802cbbc9e","src/memmem/genericsimd.rs":"7d42f15f03cfec0bc387895b3a7b4ffd6a9c7517fdcd2d5bcd2018eb6b1a6aea","src/memmem/mod.rs":"c265518c0d9e6afca1536306de707e5817f81bc1528ca6956d92c8f5a1ed9248","src/memmem/prefilter/fallback.rs":"aa44ece210fbed15d2f61dd384f17b01cee9fcc1d20dfbf3472c57dc8f176f37","src/memmem/prefilter/genericsimd.rs":"57d5523cf0299b37ef1dd1b351e3d387d5070f2f7ecffc9a9ca66528101ebd3f","src/memmem/prefilter/mod.rs":"0e0c7d656497dc8a7d20cd446db1ebc05341fe2612d3864795704beae07df89f","src/memmem/prefilter/x86/avx.rs":"e344cae36a88b59c07a1c1d395edeb9c636a399e1528ce69b2bc7c94d8d8bb0b","src/memmem/prefilter/x86/mod.rs":"df2d84b23b22574383c281d33671a121b5faf7b1a48dd6f67c3085cd02cd4498","src/memmem/prefilter/x86/sse.rs":"d39af926e3d0f19dbf447f28d8b9833c470224fb3109f5500ef8de6f4bb1568b","src/memmem/rabinkarp.rs":"9b44eb092524a51792eba4deaca6c6d3cbc51db98cb548ea4fa7e5d8988cc71a","src/memmem/rarebytes.rs":"571082c71fc3dca5e4304171d41fb3c44e241df6dcd88bac4d7a15b52f9521e0","src/memmem/twoway.rs":"102f8bbb29696d5656cd2f5a1769a3af96d044fb09972881455cfb6424d6b50a","src/memmem/util.rs":"0194d40b912137e2352863af9cc1c0273baf97fdf6b27799628680846c06febd","src/memmem/vector.rs":"7925496f273e8d8837e7850d7d0592f5a3f0472a0e0f5d8852b6d6f8e2c45ecd","src/memmem/x86/avx.rs":"de85dbc415603c844baf94fbc92d676a738dd4b99246be468bd5f7be5921b25f","src/memmem/x86/mod.rs":"5012fca41b91caf229278aa221e8dd514ede497fe4938d64562d03fef2fc46e6","src/memmem/x86/sse.rs":"148a40c0952aca8b16d9eb3e724a5b9b60693bc7b2bcc5209bcc43c94faf560a","src/tests/memchr/iter.rs":"b68c7ecdb6222c5dbf61212e6863f78f98ad343868a74cb8612692fc790240b2","src/tests/memchr/memchr.rs":"09589c5899324c9b26ea4513c80389a2ffdf6ddc460031e2ca8da43bd493ae3f","src/tests/memchr/mod.rs":"29e0855f946c7babf603b3d610a29235a56a26a4c867fef0768542388eac4c95","src/tests/memchr/simple.rs":"b9997903ede972272c01c1750522a20692a28488cc7c5cf745ea83ff96d65fe3","src/tests/memchr/testdata.rs":"b74e613b1c7e89f2d78a13641607aafef5472b798162a55b15a736d6f961ef0a","src/tests/mod.rs":"9054a2a2f9af140f305ca29155d942fafbac9fb0874067611adc8a5990546be4","src/tests/x86_64-soft_float.json":"c0e416487fe9b4809534edb7db2a9eff3453dc40d9f1e23362c37f45a77ec717"},"package":"b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"}
\ No newline at end of file
+{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"79d36439427134dd97c1a648579acb179dc594f960ab31abd0f447fdea4e7886","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"8e0a803533f359a91e0cedb0e664b4d880d5e571543eed2b58888dd84555cf0f","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","build.rs":"740225b5280e53e8d73971c6ccc55152d6af32e94132bc6980fdc0eb1fb3ab48","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","scripts/make-byte-frequency-table":"21d1ded41fe5a780507bb88e1910d471b4081cc626a48891a408712e45b7b2bf","src/cow.rs":"a23c3b009e5215b5c3ac46627a5dd844235bef0136d76b3fc1eeeb744565c125","src/lib.rs":"9430cd37b13399df8f8c27a752ccdf6422a563e24171d1b4802424f9193a8f37","src/memchr/c.rs":"34f7caf79316f4b03908832fdbd4aff367f2bc30eae291478cc5a0a108ce6e76","src/memchr/fallback.rs":"48764f18b7ff1f00a9ac1c4ed8ec96ad11f7b09b2d062a8ed3fe81160add627d","src/memchr/iter.rs":"61463e7fa22ca8f212c2cbfb882af0c87b0fb1bc6b4676678a4822a581ec1037","src/memchr/mod.rs":"d5bfc881c7c089e1a0825209a4d21c3f792f38c6f16f3bc715d0d539477376b6","src/memchr/naive.rs":"c7453bc99cc4e58eb37cf5a50c88688833e50a270ee1849baefddb8acc0ccd94","src/memchr/x86/avx.rs":"3c2750174ce7ff033daa4096e7961bbee9a2da898068266b27dee22ef8cfddad","src/memchr/x86/mod.rs":"a642d5aefdb7452ead4ab7946b5c6cfb6cc6df636dcd0ebbd6f5e6e1ac8305c0","src/memchr/x86/sse2.rs":"79ede1aba71a655e86eb5873d682c5da26933bffa4fffd7042a2313f18cf4675","src/memchr/x86/sse42.rs":"de4c6f354dbfec170876cddb8d9157b35928f96ed2339a0c5d094cc953a2f52d","src/memmem/byte_frequencies.rs":"2fb85b381c038c1e44ce94294531cdcd339dca48b1e61f41455666e802cbbc9e","src/memmem/genericsimd.rs":"9ce7283db0994438eb6df2bea6ad984e80512b6f643ebae7ae7d82eb5d39fa11","src/memmem/mod.rs":"c265518c0d9e6afca1536306de707e5817f81bc1528ca6956d92c8f5a1ed9248","src/memmem/prefilter/fallback.rs":"d32248c41aa09701c2410c52f948bbe009dd1b13a01b444ce0fb8c4b4e404ede","src/memmem/prefilter/genericsimd.rs":"57d5523cf0299b37ef1dd1b351e3d387d5070f2f7ecffc9a9ca66528101ebd3f","src/memmem/prefilter/mod.rs":"108bbab9ccca2843996c4e5def7db9210841c610d28493a18163ea1b63e6a785","src/memmem/prefilter/x86/avx.rs":"e344cae36a88b59c07a1c1d395edeb9c636a399e1528ce69b2bc7c94d8d8bb0b","src/memmem/prefilter/x86/mod.rs":"df2d84b23b22574383c281d33671a121b5faf7b1a48dd6f67c3085cd02cd4498","src/memmem/prefilter/x86/sse.rs":"d39af926e3d0f19dbf447f28d8b9833c470224fb3109f5500ef8de6f4bb1568b","src/memmem/rabinkarp.rs":"9b44eb092524a51792eba4deaca6c6d3cbc51db98cb548ea4fa7e5d8988cc71a","src/memmem/rarebytes.rs":"571082c71fc3dca5e4304171d41fb3c44e241df6dcd88bac4d7a15b52f9521e0","src/memmem/twoway.rs":"102f8bbb29696d5656cd2f5a1769a3af96d044fb09972881455cfb6424d6b50a","src/memmem/util.rs":"0194d40b912137e2352863af9cc1c0273baf97fdf6b27799628680846c06febd","src/memmem/vector.rs":"7925496f273e8d8837e7850d7d0592f5a3f0472a0e0f5d8852b6d6f8e2c45ecd","src/memmem/x86/avx.rs":"de85dbc415603c844baf94fbc92d676a738dd4b99246be468bd5f7be5921b25f","src/memmem/x86/mod.rs":"5012fca41b91caf229278aa221e8dd514ede497fe4938d64562d03fef2fc46e6","src/memmem/x86/sse.rs":"148a40c0952aca8b16d9eb3e724a5b9b60693bc7b2bcc5209bcc43c94faf560a","src/tests/memchr/iter.rs":"b68c7ecdb6222c5dbf61212e6863f78f98ad343868a74cb8612692fc790240b2","src/tests/memchr/memchr.rs":"09589c5899324c9b26ea4513c80389a2ffdf6ddc460031e2ca8da43bd493ae3f","src/tests/memchr/mod.rs":"29e0855f946c7babf603b3d610a29235a56a26a4c867fef0768542388eac4c95","src/tests/memchr/simple.rs":"b9997903ede972272c01c1750522a20692a28488cc7c5cf745ea83ff96d65fe3","src/tests/memchr/testdata.rs":"3e34377fe60eca3687d1ebc66127bd631af27ceaccc8f08806a293199b69a83f","src/tests/mod.rs":"9054a2a2f9af140f305ca29155d942fafbac9fb0874067611adc8a5990546be4","src/tests/x86_64-soft_float.json":"c0e416487fe9b4809534edb7db2a9eff3453dc40d9f1e23362c37f45a77ec717"},"package":"308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"}
\ No newline at end of file
index ed97e9fee9266f1f83f4f1c5dd4a779739452778..e739019be8f3974cdad399708237e267972a6c3e 100644 (file)
@@ -3,26 +3,25 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
 edition = "2018"
 name = "memchr"
-version = "2.4.0"
+version = "2.4.1"
 authors = ["Andrew Gallant <jamslam@gmail.com>", "bluss"]
 exclude = ["/bench", "/.github", "/fuzz"]
 description = "Safe interface to memchr."
-homepage = "https://github.com/BurntSushi/rust-memchr"
+homepage = "https://github.com/BurntSushi/memchr"
 documentation = "https://docs.rs/memchr/"
 readme = "README.md"
 keywords = ["memchr", "char", "scan", "strchr", "string"]
 license = "Unlicense/MIT"
-repository = "https://github.com/BurntSushi/rust-memchr"
+repository = "https://github.com/BurntSushi/memchr"
 [profile.bench]
 debug = true
 
@@ -36,6 +35,15 @@ debug = true
 [lib]
 name = "memchr"
 bench = false
+[dependencies.compiler_builtins]
+version = "0.1.2"
+optional = true
+
+[dependencies.core]
+version = "1.0.0"
+optional = true
+package = "rustc-std-workspace-core"
+
 [dependencies.libc]
 version = "0.2.18"
 optional = true
@@ -46,5 +54,6 @@ default-features = false
 
 [features]
 default = ["std"]
+rustc-dep-of-std = ["core", "compiler_builtins"]
 std = []
 use_std = ["std"]
index 3b92e188a1833635729bce0c74440c3012811600..df758160365ca0dfecc0ddc85d2a99f3dc1f8e05 100644 (file)
@@ -2,7 +2,7 @@ memchr
 ======
 This library provides heavily optimized routines for string search primitives.
 
-[![Build status](https://github.com/BurntSushi/rust-memchr/workflows/ci/badge.svg)](https://github.com/BurntSushi/rust-memchr/actions)
+[![Build status](https://github.com/BurntSushi/memchr/workflows/ci/badge.svg)](https://github.com/BurntSushi/memchr/actions)
 [![](https://meritbadge.herokuapp.com/memchr)](https://crates.io/crates/memchr)
 
 Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
@@ -84,4 +84,24 @@ approaches:
 * A huge suite of benchmarks that are also run as tests. Benchmarks always
   confirm that the expected result occurs.
 
-Improvements to the testing infrastructue are very welcome.
+Improvements to the testing infrastructure are very welcome.
+
+
+### Algorithms used
+
+At time of writing, this crate's implementation of substring search actually
+has a few different algorithms to choose from depending on the situation.
+
+* For very small haystacks,
+  [Rabin-Karp](https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm)
+  is used to reduce latency. Rabin-Karp has very small overhead and can often
+  complete before other searchers have even been constructed.
+* For small needles, a variant of the
+  ["Generic SIMD"](http://0x80.pl/articles/simd-strfind.html#algorithm-1-generic-simd)
+  algorithm is used. Instead of using the first and last bytes, a heuristic is
+  used to select bytes based on a background distribution of byte frequencies.
+* In all other cases,
+  [Two-Way](https://en.wikipedia.org/wiki/Two-way_string-matching_algorithm)
+  is used. If possible, a prefilter based on the "Generic SIMD" algorithm
+  linked above is used to find candidates quickly. A dynamic heuristic is used
+  to detect if the prefilter is ineffective, and if so, disables it.
diff --git a/vendor/memchr/scripts/make-byte-frequency-table b/vendor/memchr/scripts/make-byte-frequency-table
new file mode 100755 (executable)
index 0000000..37eeca7
--- /dev/null
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+
+# This does simple normalized frequency analysis on UTF-8 encoded text. The
+# result of the analysis is translated to a ranked list, where every byte is
+# assigned a rank. This list is written to src/freqs.rs.
+#
+# Currently, the frequencies are generated from the following corpuses:
+#
+#   * The CIA world fact book
+#   * The source code of rustc
+#   * Septuaginta
+
+from __future__ import absolute_import, division, print_function
+
+import argparse
+from collections import Counter
+import sys
+
+preamble = '''
+// NOTE: The following code was generated by "scripts/frequencies.py", do not
+// edit directly
+'''.lstrip()
+
+
+def eprint(*args, **kwargs):
+    kwargs['file'] = sys.stderr
+    print(*args, **kwargs)
+
+
+def main():
+    p = argparse.ArgumentParser()
+    p.add_argument('corpus', metavar='FILE', nargs='+')
+    args = p.parse_args()
+
+    # Get frequency counts of each byte.
+    freqs = Counter()
+    for i in range(0, 256):
+        freqs[i] = 0
+
+    eprint('reading entire corpus into memory')
+    corpus = []
+    for fpath in args.corpus:
+        corpus.append(open(fpath, 'rb').read())
+
+    eprint('computing byte frequencies')
+    for c in corpus:
+        for byte in c:
+            freqs[byte] += 1.0 / float(len(c))
+
+    eprint('writing Rust code')
+    # Get the rank of each byte. A lower rank => lower relative frequency.
+    rank = [0] * 256
+    for i, (byte, _) in enumerate(freqs.most_common()):
+        # print(byte)
+        rank[byte] = 255 - i
+
+    # Forcefully set the highest rank possible for bytes that start multi-byte
+    # UTF-8 sequences. The idea here is that a continuation byte will be more
+    # discerning in a homogenous haystack.
+    for byte in range(0xC0, 0xFF + 1):
+        rank[byte] = 255
+
+    # Now write Rust.
+    olines = ['pub const BYTE_FREQUENCIES: [u8; 256] = [']
+    for byte in range(256):
+        olines.append('    %3d, // %r' % (rank[byte], chr(byte)))
+    olines.append('];')
+
+    print(preamble)
+    print('\n'.join(olines))
+
+
+if __name__ == '__main__':
+    main()
index 95a08241aca758e6b9c0c04bb88338c58b9c5452..0b7d0dad091ccaa2212c828339568c4acb2933ec 100644 (file)
@@ -5,7 +5,7 @@ use core::ops;
 /// The purpose of this type is to permit usage of a "borrowed or owned
 /// byte string" in a way that keeps std/no-std compatibility. That is, in
 /// no-std mode, this type devolves into a simple &[u8] with no owned variant
-/// availble. We can't just use a plain Cow because Cow is not in core.
+/// available. We can't just use a plain Cow because Cow is not in core.
 #[derive(Clone, Debug)]
 pub struct CowBytes<'a>(Imp<'a>);
 
index c3154b60ddcd935d599cf9bd50f145fae86972e1..e0b4ce3fda4e70a26026c528fa476449b5dd05ff 100644 (file)
@@ -160,7 +160,7 @@ standard library exposes a platform independent SIMD API.
 #![cfg_attr(miri, allow(dead_code, unused_macros))]
 
 // Supporting 8-bit (or others) would be fine. If you need it, please submit a
-// bug report at https://github.com/BurntSushi/rust-memchr
+// bug report at https://github.com/BurntSushi/memchr
 #[cfg(not(any(
     target_pointer_width = "16",
     target_pointer_width = "32",
index 2417f917b6d42ee64501605dd77d058072782d6c..28bfdab880c370c3e24c9c0049132ef8ce2ec7ae 100644 (file)
@@ -195,7 +195,9 @@ pub(crate) unsafe fn fwd_find<V: Vector>(
 }
 
 /// Search for an occurrence of two rare bytes from the needle in the chunk
-/// pointed to by ptr, with the end of the haystack pointed to by end_ptr.
+/// pointed to by ptr, with the end of the haystack pointed to by end_ptr. When
+/// an occurrence is found, memcmp is run to check if a match occurs at the
+/// corresponding position.
 ///
 /// rare1chunk and rare2chunk correspond to vectors with the rare1 and rare2
 /// bytes repeated in each 8-bit lane, respectively.
@@ -210,7 +212,7 @@ pub(crate) unsafe fn fwd_find<V: Vector>(
 ///
 /// It must be safe to do an unaligned read of size(V) bytes starting at both
 /// (ptr + rare1i) and (ptr + rare2i). It must also be safe to do unaligned
-/// loads on ptr up to end_ptr.
+/// loads on ptr up to (end_ptr - needle.len()).
 #[inline(always)]
 unsafe fn fwd_find_in_chunk<V: Vector>(
     fwd: &Forward,
index 8ae1f4e98b8910be9b18b91226db181c89107dff..ae1bbccb32b4c04346fe3d3f6373a38ce5a7ac80 100644 (file)
@@ -20,7 +20,7 @@ make use of the background frequency distribution of bytes though.)
 
 This fallback implementation was originally formulated in regex many moons ago:
 https://github.com/rust-lang/regex/blob/3db8722d0b204a85380fe2a65e13d7065d7dd968/src/literal/imp.rs#L370-L501
-Prior to that, I'm not aware of anyone using this technique in any prominant
+Prior to that, I'm not aware of anyone using this technique in any prominent
 substring search implementation. Although, I'm sure folks have had this same
 insight long before me.
 
index 2481cfecc3ae253cf872c84f5bc6f9b78ba56d84..6461f338c0407e6476117a8d132ab68e4da22552 100644 (file)
@@ -18,7 +18,7 @@ const MAX_FALLBACK_RANK: usize = 250;
 /// instead of needing to pass around all three as distinct function
 /// parameters.
 pub(crate) struct Pre<'a> {
-    /// State that tracks the effectivess of a prefilter.
+    /// State that tracks the effectiveness of a prefilter.
     pub(crate) state: &'a mut PrefilterState,
     /// The actual prefilter function.
     pub(crate) prefn: PrefilterFn,
@@ -146,7 +146,7 @@ impl core::fmt::Debug for PrefilterFn {
 /// The use of prefilters in this implementation does use a heuristic to detect
 /// when a prefilter might not be carrying its weight, and will dynamically
 /// disable its use. Nevertheless, this configuration option gives callers
-/// the ability to disable pefilters if you have knowledge that they won't be
+/// the ability to disable prefilters if you have knowledge that they won't be
 /// useful.
 #[derive(Clone, Copy, Debug)]
 #[non_exhaustive]
index acb1fd8d6d36bc297e185ecbd72f54e201a6ec38..6dda5246fd8d0f57cd43680171e43e59b5a9b90f 100644 (file)
@@ -160,7 +160,7 @@ impl MemchrTest {
         //
         // You might think this would cause most needles to not be found, but
         // we actually expand our tests to include corpus sizes all the way up
-        // to >500 bytes, so we should exericse most branches.
+        // to >500 bytes, so we should exercise most branches.
         for align in 0..130 {
             let corpus = self.corpus(align);
             assert_eq!(
diff --git a/vendor/memmap2-0.2.1/.cargo-checksum.json b/vendor/memmap2-0.2.1/.cargo-checksum.json
new file mode 100644 (file)
index 0000000..19a48c7
--- /dev/null
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"a89928f51b2c7899a897b0f0864b8071c4a35efa353a5d8dd54b1c19621b9aa1","Cargo.lock":"9d2daf6059412a3ff3d7e0aadb74c92d6be8d400d9b38d671246378675d48c38","Cargo.toml":"864c720597df45669fbc7a5bf1150212a813ba5a0b92a87bc52c442bb4e33102","LICENSE-APACHE":"04ea4849dba9dcae07113850c6f1b1a69052c625210639914eee352023f750ad","LICENSE-MIT":"e9116f7228fce981d81aa680ae1add0cfb8122c35d801c4664d3d674ad0beda8","README.md":"4e70c39451ff48d9b60e2a0db4754fefc2fe349149b4baf4747ca3556ac7ae15","examples/cat.rs":"ab0b575d19662e2d5b6c7cea2756b57530e495d56acdb4fd2b56c0ba4d768dfd","src/lib.rs":"bc2563ca78e820217366df7c0065938f65c318e8a09e6202652c78efb6b8539e","src/unix.rs":"7fe62be97f49a9225e52d59cdb1a576be868996ab26c4ab445e4b12dc15d6b09","src/windows.rs":"73e7ef54c44a2af917d2f733f4ba3abc7c293653c40f06a10a61bcf3f2757ef5"},"package":"04e3e85b970d650e2ae6d70592474087051c11c54da7f7b4949725c5735fbcc6"}
\ No newline at end of file
diff --git a/vendor/memmap2-0.2.1/CHANGELOG.md b/vendor/memmap2-0.2.1/CHANGELOG.md
new file mode 100644 (file)
index 0000000..258be14
--- /dev/null
@@ -0,0 +1,31 @@
+# Change Log
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/)
+and this project adheres to [Semantic Versioning](http://semver.org/).
+
+## [Unreleased]
+
+## 0.2.1 - 2021-02-08
+### Added
+- `MmapOptions::map_raw` and `MmapRaw`. [@diwic](https://github.com/diwic).
+
+## 0.2.0 - 2020-12-19
+### Changed
+- MSRV is 1.31 now (edition 2018).
+- Make anonymous memory maps private by default on unix. Thanks to [@CensoredUsername](https://github.com/CensoredUsername).
+- Add `map_copy_read_only`. [@zserik](https://github.com/zserik).
+
+## 0.1.0 - 2020-01-18
+### Added
+- Fork [memmap-rs](https://github.com/danburkert/memmap-rs).
+
+### Changed
+- Use `LICENSE-APACHE` instead of `README.md` for some tests since it's immutable.
+
+### Removed
+- `winapi` dependency. [memmap-rs/pull/89](https://github.com/danburkert/memmap-rs/pull/89)
+
+[Unreleased]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.2.1...HEAD
+[0.2.1]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.2.0...v0.2.1
+[0.2.0]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.1.0...v0.2.0
diff --git a/vendor/memmap2-0.2.1/Cargo.lock b/vendor/memmap2-0.2.1/Cargo.lock
new file mode 100644 (file)
index 0000000..76c7131
--- /dev/null
@@ -0,0 +1,99 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "fuchsia-cprng"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
+
+[[package]]
+name = "libc"
+version = "0.2.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
+
+[[package]]
+name = "memmap2"
+version = "0.2.1"
+dependencies = [
+ "libc",
+ "tempdir",
+]
+
+[[package]]
+name = "rand"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
+dependencies = [
+ "fuchsia-cprng",
+ "libc",
+ "rand_core 0.3.1",
+ "rdrand",
+ "winapi",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
+dependencies = [
+ "rand_core 0.4.2",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
+
+[[package]]
+name = "rdrand"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
+dependencies = [
+ "rand_core 0.3.1",
+]
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "tempdir"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
+dependencies = [
+ "rand",
+ "remove_dir_all",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/vendor/memmap2-0.2.1/Cargo.toml b/vendor/memmap2-0.2.1/Cargo.toml
new file mode 100644 (file)
index 0000000..1765b84
--- /dev/null
@@ -0,0 +1,26 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "memmap2"
+version = "0.2.1"
+authors = ["Dan Burkert <dan@danburkert.com>", "Evgeniy Reizner <razrfalcon@gmail.com>"]
+description = "Cross-platform Rust API for memory-mapped file IO"
+documentation = "https://docs.rs/memmap2"
+keywords = ["mmap", "memory-map", "io", "file"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/RazrFalcon/memmap2-rs"
+[dev-dependencies.tempdir]
+version = "0.3"
+[target."cfg(unix)".dependencies.libc]
+version = "0.2"
diff --git a/vendor/memmap2-0.2.1/LICENSE-APACHE b/vendor/memmap2-0.2.1/LICENSE-APACHE
new file mode 100644 (file)
index 0000000..7be3d81
--- /dev/null
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [2015] [Dan Burkert]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/vendor/memmap2-0.2.1/LICENSE-MIT b/vendor/memmap2-0.2.1/LICENSE-MIT
new file mode 100644 (file)
index 0000000..5cc9371
--- /dev/null
@@ -0,0 +1,26 @@
+Copyright (c) 2020 Evgeniy Reizner
+Copyright (c) 2015 Dan Burkert
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/vendor/memmap2-0.2.1/README.md b/vendor/memmap2-0.2.1/README.md
new file mode 100644 (file)
index 0000000..6749093
--- /dev/null
@@ -0,0 +1,33 @@
+# memmap2
+![Build Status](https://github.com/RazrFalcon/memmap2-rs/workflows/Rust/badge.svg)
+[![Crates.io](https://img.shields.io/crates/v/memmap2.svg)](https://crates.io/crates/memmap2)
+[![Documentation](https://docs.rs/memmap2/badge.svg)](https://docs.rs/memmap2)
+[![Rust 1.31+](https://img.shields.io/badge/rust-1.31+-orange.svg)](https://www.rust-lang.org)
+
+A Rust library for cross-platform memory mapped IO.
+
+This is a **fork** of the [memmap-rs](https://github.com/danburkert/memmap-rs) crate.
+
+## Features
+
+- [x] file-backed memory maps
+- [x] anonymous memory maps
+- [x] synchronous and asynchronous flushing
+- [x] copy-on-write memory maps
+- [x] read-only memory maps
+- [x] stack support (`MAP_STACK` on unix)
+- [x] executable memory maps
+- [ ] huge page support
+
+A list of supported/tested targets can be found in [Actions](https://github.com/RazrFalcon/memmap2-rs/actions).
+
+## License
+
+`memmap2` is primarily distributed under the terms of both the MIT license and the
+Apache License (Version 2.0).
+
+See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT) for details.
+
+Copyright (c) 2020 Evgeniy Reizner
+
+Copyright (c) 2015 Dan Burkert
diff --git a/vendor/memmap2-0.2.1/examples/cat.rs b/vendor/memmap2-0.2.1/examples/cat.rs
new file mode 100644 (file)
index 0000000..34599af
--- /dev/null
@@ -0,0 +1,23 @@
+extern crate memmap2;
+
+use std::env;
+use std::fs::File;
+use std::io::{self, Write};
+
+use memmap2::Mmap;
+
+/// Output a file's contents to stdout. The file path must be provided as the first process
+/// argument.
+fn main() {
+    let path = env::args()
+        .nth(1)
+        .expect("supply a single path as the program argument");
+
+    let file = File::open(path).expect("failed to open the file");
+
+    let mmap = unsafe { Mmap::map(&file).expect("failed to map the file") };
+
+    io::stdout()
+        .write_all(&mmap[..])
+        .expect("failed to output the file contents");
+}
diff --git a/vendor/memmap2-0.2.1/src/lib.rs b/vendor/memmap2-0.2.1/src/lib.rs
new file mode 100644 (file)
index 0000000..b408ba8
--- /dev/null
@@ -0,0 +1,1199 @@
+//! A cross-platform Rust API for memory mapped buffers.
+
+#![doc(html_root_url = "https://docs.rs/memmap2/0.2.1")]
+
+#[cfg(windows)]
+mod windows;
+#[cfg(windows)]
+use windows::MmapInner;
+
+#[cfg(unix)]
+mod unix;
+#[cfg(unix)]
+use crate::unix::MmapInner;
+
+use std::fmt;
+use std::fs::File;
+use std::io::{Error, ErrorKind, Result};
+use std::ops::{Deref, DerefMut};
+use std::slice;
+use std::usize;
+
+/// A memory map builder, providing advanced options and flags for specifying memory map behavior.
+///
+/// `MmapOptions` can be used to create an anonymous memory map using [`map_anon()`], or a
+/// file-backed memory map using one of [`map()`], [`map_mut()`], [`map_exec()`],
+/// [`map_copy()`], or [`map_copy_read_only()`].
+///
+/// ## Safety
+///
+/// All file-backed memory map constructors are marked `unsafe` because of the potential for
+/// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
+/// out of process. Applications must consider the risk and take appropriate precautions when
+/// using file-backed maps. Solutions such as file permissions, locks or process-private (e.g.
+/// unlinked) files exist but are platform specific and limited.
+///
+/// [`map_anon()`]: MmapOptions::map_anon()
+/// [`map()`]: MmapOptions::map()
+/// [`map_mut()`]: MmapOptions::map_mut()
+/// [`map_exec()`]: MmapOptions::map_exec()
+/// [`map_copy()`]: MmapOptions::map_copy()
+/// [`map_copy_read_only()`]: MmapOptions::map_copy_read_only()
+#[derive(Clone, Debug, Default)]
+pub struct MmapOptions {
+    offset: u64,
+    len: Option<usize>,
+    stack: bool,
+}
+
+impl MmapOptions {
+    /// Creates a new set of options for configuring and creating a memory map.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use memmap2::{MmapMut, MmapOptions};
+    /// # use std::io::Result;
+    ///
+    /// # fn main() -> Result<()> {
+    /// // Create a new memory map builder.
+    /// let mut mmap_options = MmapOptions::new();
+    ///
+    /// // Configure the memory map builder using option setters, then create
+    /// // a memory map using one of `mmap_options.map_anon`, `mmap_options.map`,
+    /// // `mmap_options.map_mut`, `mmap_options.map_exec`, or `mmap_options.map_copy`:
+    /// let mut mmap: MmapMut = mmap_options.len(36).map_anon()?;
+    ///
+    /// // Use the memory map:
+    /// mmap.copy_from_slice(b"...data to copy to the memory map...");
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub fn new() -> MmapOptions {
+        MmapOptions::default()
+    }
+
+    /// Configures the memory map to start at byte `offset` from the beginning of the file.
+    ///
+    /// This option has no effect on anonymous memory maps.
+    ///
+    /// By default, the offset is 0.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use memmap2::MmapOptions;
+    /// use std::fs::File;
+    ///
+    /// # fn main() -> std::io::Result<()> {
+    /// let mmap = unsafe {
+    ///     MmapOptions::new()
+    ///                 .offset(30)
+    ///                 .map(&File::open("LICENSE-APACHE")?)?
+    /// };
+    /// assert_eq!(&b"Apache License"[..],
+    ///            &mmap[..14]);
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub fn offset(&mut self, offset: u64) -> &mut Self {
+        self.offset = offset;
+        self
+    }
+
+    /// Configures the created memory mapped buffer to be `len` bytes long.
+    ///
+    /// This option is mandatory for anonymous memory maps.
+    ///
+    /// For file-backed memory maps, the length will default to the file length.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use memmap2::MmapOptions;
+    /// use std::fs::File;
+    ///
+    /// # fn main() -> std::io::Result<()> {
+    /// let mmap = unsafe {
+    ///     MmapOptions::new()
+    ///                 .len(9)
+    ///                 .map(&File::open("README.md")?)?
+    /// };
+    /// assert_eq!(&b"# memmap2"[..], &mmap[..]);
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub fn len(&mut self, len: usize) -> &mut Self {
+        self.len = Some(len);
+        self
+    }
+
+    /// Returns the configured length, or the length of the provided file.
+    fn get_len(&self, file: &File) -> Result<usize> {
+        self.len.map(Ok).unwrap_or_else(|| {
+            let len = file.metadata()?.len() - self.offset;
+            if len > (usize::MAX as u64) {
+                return Err(Error::new(
+                    ErrorKind::InvalidData,
+                    "memory map length overflows usize",
+                ));
+            }
+            Ok(len as usize)
+        })
+    }
+
+    /// Configures the anonymous memory map to be suitable for a process or thread stack.
+    ///
+    /// This option corresponds to the `MAP_STACK` flag on Linux.
+    ///
+    /// This option has no effect on file-backed memory maps.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use memmap2::MmapOptions;
+    ///
+    /// # fn main() -> std::io::Result<()> {
+    /// let stack = MmapOptions::new().stack().len(4096).map_anon();
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub fn stack(&mut self) -> &mut Self {
+        self.stack = true;
+        self
+    }
+
+    /// Creates a read-only memory map backed by a file.
+    ///
+    /// # Errors
+    ///
+    /// This method returns an error when the underlying system call fails, which can happen for a
+    /// variety of reasons, such as when the file is not open with read permissions.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use memmap2::MmapOptions;
+    /// use std::fs::File;
+    /// use std::io::Read;
+    ///
+    /// # fn main() -> std::io::Result<()> {
+    /// let mut file = File::open("LICENSE-APACHE")?;
+    ///
+    /// let mut contents = Vec::new();
+    /// file.read_to_end(&mut contents)?;
+    ///
+    /// let mmap = unsafe {
+    ///     MmapOptions::new().map(&file)?
+    /// };
+    ///
+    /// assert_eq!(&contents[..], &mmap[..]);
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub unsafe fn map(&self, file: &File) -> Result<Mmap> {
+        MmapInner::map(self.get_len(file)?, file, self.offset).map(|inner| Mmap { inner: inner })
+    }
+
+    /// Creates a readable and executable memory map backed by a file.
+    ///
+    /// # Errors
+    ///
+    /// This method returns an error when the underlying system call fails, which can happen for a
+    /// variety of reasons, such as when the file is not open with read permissions.
+    pub unsafe fn map_exec(&self, file: &File) -> Result<Mmap> {
+        MmapInner::map_exec(self.get_len(file)?, file, self.offset)
+            .map(|inner| Mmap { inner: inner })
+    }
+
+    /// Creates a writeable memory map backed by a file.
+    ///
+    /// # Errors
+    ///
+    /// This method returns an error when the underlying system call fails, which can happen for a
+    /// variety of reasons, such as when the file is not open with read and write permissions.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # extern crate memmap2;
+    /// # extern crate tempdir;
+    /// #
+    /// use std::fs::OpenOptions;
+    /// use std::path::PathBuf;
+    ///
+    /// use memmap2::MmapOptions;
+    /// #
+    /// # fn main() -> std::io::Result<()> {
+    /// # let tempdir = tempdir::TempDir::new("mmap")?;
+    /// let path: PathBuf = /* path to file */
+    /// #   tempdir.path().join("map_mut");
+    /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?;
+    /// file.set_len(13)?;
+    ///
+    /// let mut mmap = unsafe {
+    ///     MmapOptions::new().map_mut(&file)?
+    /// };
+    ///
+    /// mmap.copy_from_slice(b"Hello, world!");
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub unsafe fn map_mut(&self, file: &File) -> Result<MmapMut> {
+        MmapInner::map_mut(self.get_len(file)?, file, self.offset)
+            .map(|inner| MmapMut { inner: inner })
+    }
+
+    /// Creates a copy-on-write memory map backed by a file.
+    ///
+    /// Data written to the memory map will not be visible by other processes,
+    /// and will not be carried through to the underlying file.
+    ///
+    /// # Errors
+    ///
+    /// This method returns an error when the underlying system call fails, which can happen for a
+    /// variety of reasons, such as when the file is not open with writable permissions.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use memmap2::MmapOptions;
+    /// use std::fs::File;
+    /// use std::io::Write;
+    ///
+    /// # fn main() -> std::io::Result<()> {
+    /// let file = File::open("LICENSE-APACHE")?;
+    /// let mut mmap = unsafe { MmapOptions::new().map_copy(&file)? };
+    /// (&mut mmap[..]).write_all(b"Hello, world!")?;
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub unsafe fn map_copy(&self, file: &File) -> Result<MmapMut> {
+        MmapInner::map_copy(self.get_len(file)?, file, self.offset)
+            .map(|inner| MmapMut { inner: inner })
+    }
+
+    /// Creates a copy-on-write read-only memory map backed by a file.
+    ///
+    /// # Errors
+    ///
+    /// This method returns an error when the underlying system call fails, which can happen for a
+    /// variety of reasons, such as when the file is not open with read permissions.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use memmap2::MmapOptions;
+    /// use std::fs::File;
+    /// use std::io::Read;
+    ///
+    /// # fn main() -> std::io::Result<()> {
+    /// let mut file = File::open("README.md")?;
+    ///
+    /// let mut contents = Vec::new();
+    /// file.read_to_end(&mut contents)?;
+    ///
+    /// let mmap = unsafe {
+    ///     MmapOptions::new().map_copy_read_only(&file)?
+    /// };
+    ///
+    /// assert_eq!(&contents[..], &mmap[..]);
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub unsafe fn map_copy_read_only(&self, file: &File) -> Result<Mmap> {
+        MmapInner::map_copy_read_only(self.get_len(file)?, file, self.offset)
+            .map(|inner| Mmap { inner: inner })
+    }
+
+    /// Creates an anonymous memory map.
+    ///
+    /// Note: the memory map length must be configured to be greater than 0 before creating an
+    /// anonymous memory map using `MmapOptions::len()`.
+    ///
+    /// # Errors
+    ///
+    /// This method returns an error when the underlying system call fails.
+    pub fn map_anon(&self) -> Result<MmapMut> {
+        MmapInner::map_anon(self.len.unwrap_or(0), self.stack).map(|inner| MmapMut { inner: inner })
+    }
+
+    /// Creates a raw memory map.
+    ///
+    /// # Errors
+    ///
+    /// This method returns an error when the underlying system call fails, which can happen for a
+    /// variety of reasons, such as when the file is not open with read and write permissions.
+    pub fn map_raw(&self, file: &File) -> Result<MmapRaw> {
+        MmapInner::map_mut(self.get_len(file)?, file, self.offset)
+            .map(|inner| MmapRaw { inner: inner })
+    }
+}
+
+/// A handle to an immutable memory mapped buffer.
+///
+/// A `Mmap` may be backed by a file, or it can be anonymous map, backed by volatile memory. Use
+/// [`MmapOptions`] or [`map()`] to create a file-backed memory map. To create an immutable
+/// anonymous memory map, first create a mutable anonymous memory map, and then make it immutable
+/// with [`MmapMut::make_read_only()`].
+///
+/// A file backed `Mmap` is created by `&File` reference, and will remain valid even after the
+/// `File` is dropped. In other words, the `Mmap` handle is completely independent of the `File`
+/// used to create it. For consistency, on some platforms this is achieved by duplicating the
+/// underlying file handle. The memory will be unmapped when the `Mmap` handle is dropped.
+///
+/// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping
+/// the mapped pages into physical memory) though the details of this are platform specific.
+///
+/// `Mmap` is [`Sync`](std::marker::Sync) and [`Send`](std::marker::Send).
+///
+/// ## Safety
+///
+/// All file-backed memory map constructors are marked `unsafe` because of the potential for
+/// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
+/// out of process. Applications must consider the risk and take appropriate precautions when using
+/// file-backed maps. Solutions such as file permissions, locks or process-private (e.g. unlinked)
+/// files exist but are platform specific and limited.
+///
+/// ## Example
+///
+/// ```
+/// use memmap2::MmapOptions;
+/// use std::io::Write;
+/// use std::fs::File;
+///
+/// # fn main() -> std::io::Result<()> {
+/// let file = File::open("README.md")?;
+/// let mmap = unsafe { MmapOptions::new().map(&file)? };
+/// assert_eq!(b"# memmap2", &mmap[0..9]);
+/// # Ok(())
+/// # }
+/// ```
+///
+/// See [`MmapMut`] for the mutable version.
+///
+/// [`map()`]: Mmap::map()
+pub struct Mmap {
+    inner: MmapInner,
+}
+
+impl Mmap {
+    /// Creates a read-only memory map backed by a file.
+    ///
+    /// This is equivalent to calling `MmapOptions::new().map(file)`.
+    ///
+    /// # Errors
+    ///
+    /// This method returns an error when the underlying system call fails, which can happen for a
+    /// variety of reasons, such as when the file is not open with read permissions.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use std::fs::File;
+    /// use std::io::Read;
+    ///
+    /// use memmap2::Mmap;
+    ///
+    /// # fn main() -> std::io::Result<()> {
+    /// let mut file = File::open("LICENSE-APACHE")?;
+    ///
+    /// let mut contents = Vec::new();
+    /// file.read_to_end(&mut contents)?;
+    ///
+    /// let mmap = unsafe { Mmap::map(&file)?  };
+    ///
+    /// assert_eq!(&contents[..], &mmap[..]);
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub unsafe fn map(file: &File) -> Result<Mmap> {
+        MmapOptions::new().map(file)
+    }
+
+    /// Transition the memory map to be writable.
+    ///
+    /// If the memory map is file-backed, the file must have been opened with write permissions.
+    ///
+    /// # Errors
+    ///
+    /// This method returns an error when the underlying system call fails, which can happen for a
+    /// variety of reasons, such as when the file is not open with writable permissions.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # extern crate memmap2;
+    /// # extern crate tempdir;
+    /// #
+    /// use memmap2::Mmap;
+    /// use std::ops::DerefMut;
+    /// use std::io::Write;
+    /// # use std::fs::OpenOptions;
+    ///
+    /// # fn main() -> std::io::Result<()> {
+    /// # let tempdir = tempdir::TempDir::new("mmap")?;
+    /// let file = /* file opened with write permissions */
+    /// #          OpenOptions::new()
+    /// #                      .read(true)
+    /// #                      .write(true)
+    /// #                      .create(true)
+    /// #                      .open(tempdir.path()
+    /// #                      .join("make_mut"))?;
+    /// # file.set_len(128)?;
+    /// let mmap = unsafe { Mmap::map(&file)? };
+    /// // ... use the read-only memory map ...
+    /// let mut mut_mmap = mmap.make_mut()?;
+    /// mut_mmap.deref_mut().write_all(b"hello, world!")?;
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub fn make_mut(mut self) -> Result<MmapMut> {
+        self.inner.make_mut()?;
+        Ok(MmapMut { inner: self.inner })
+    }
+}
+
+impl Deref for Mmap {
+    type Target = [u8];
+
+    #[inline]
+    fn deref(&self) -> &[u8] {
+        unsafe { slice::from_raw_parts(self.inner.ptr(), self.inner.len()) }
+    }
+}
+
+impl AsRef<[u8]> for Mmap {
+    #[inline]
+    fn as_ref(&self) -> &[u8] {
+        self.deref()
+    }
+}
+
+impl fmt::Debug for Mmap {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        fmt.debug_struct("Mmap")
+            .field("ptr", &self.as_ptr())
+            .field("len", &self.len())
+            .finish()
+    }
+}
+
+/// A handle to a raw memory mapped buffer.
+///
+/// This struct never hands out references to its interior, only raw pointers.
+/// This can be helpful when creating shared memory maps between untrusted processes.
+pub struct MmapRaw {
+    inner: MmapInner,
+}
+
+impl MmapRaw {
+    /// Creates a writeable memory map backed by a file.
+    ///
+    /// This is equivalent to calling `MmapOptions::new().map_raw(file)`.
+    ///
+    /// # Errors
+    ///
+    /// This method returns an error when the underlying system call fails, which can happen for a
+    /// variety of reasons, such as when the file is not open with read and write permissions.
+    pub fn map_raw(file: &File) -> Result<MmapRaw> {
+        MmapOptions::new().map_raw(file)
+    }
+
+    /// Returns a raw pointer to the memory mapped file.
+    ///
+    /// # Safety
+    ///
+    /// To safely dereference this pointer, you need to make sure that the file has not been
+    /// truncated since the memory map was created.
+    #[inline]
+    pub fn as_ptr(&self) -> *const u8 { self.inner.ptr() }
+
+    /// Returns an unsafe mutable pointer to the memory mapped file.
+    ///
+    /// # Safety
+    ///
+    /// To safely dereference this pointer, you need to make sure that the file has not been
+    /// truncated since the memory map was created.
+    #[inline]
+    pub fn as_mut_ptr(&self) -> *mut u8 { self.inner.ptr() as _ }
+
+    /// Returns the length in bytes of the memory map.
+    ///
+    /// Note that truncating the file can cause the length to change (and render this value unusable).
+    #[inline]
+    pub fn len(&self) -> usize { self.inner.len() }
+}
+
+impl fmt::Debug for MmapRaw {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        fmt.debug_struct("MmapRaw")
+            .field("ptr", &self.as_ptr())
+            .field("len", &self.len())
+            .finish()
+    }
+}
+
+/// A handle to a mutable memory mapped buffer.
+///
+/// A file-backed `MmapMut` buffer may be used to read from or write to a file. An anonymous
+/// `MmapMut` buffer may be used any place that an in-memory byte buffer is needed. Use
+/// [`MmapMut::map_mut()`] and [`MmapMut::map_anon()`] to create a mutable memory map of the
+/// respective types, or [`MmapOptions::map_mut()`] and [`MmapOptions::map_anon()`] if non-default
+/// options are required.
+///
+/// A file backed `MmapMut` is created by `&File` reference, and will remain valid even after the
+/// `File` is dropped. In other words, the `MmapMut` handle is completely independent of the `File`
+/// used to create it. For consistency, on some platforms this is achieved by duplicating the
+/// underlying file handle. The memory will be unmapped when the `MmapMut` handle is dropped.
+///
+/// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping
+/// the mapped pages into physical memory) though the details of this are platform specific.
+///
+/// `Mmap` is [`Sync`](std::marker::Sync) and [`Send`](std::marker::Send).
+///
+/// See [`Mmap`] for the immutable version.
+///
+/// ## Safety
+///
+/// All file-backed memory map constructors are marked `unsafe` because of the potential for
+/// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
+/// out of process. Applications must consider the risk and take appropriate precautions when using
+/// file-backed maps. Solutions such as file permissions, locks or process-private (e.g. unlinked)
+/// files exist but are platform specific and limited.
+pub struct MmapMut {
+    inner: MmapInner,
+}
+
+impl MmapMut {
+    /// Creates a writeable memory map backed by a file.
+    ///
+    /// This is equivalent to calling `MmapOptions::new().map_mut(file)`.
+    ///
+    /// # Errors
+    ///
+    /// This method returns an error when the underlying system call fails, which can happen for a
+    /// variety of reasons, such as when the file is not open with read and write permissions.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # extern crate memmap2;
+    /// # extern crate tempdir;
+    /// #
+    /// use std::fs::OpenOptions;
+    /// use std::path::PathBuf;
+    ///
+    /// use memmap2::MmapMut;
+    /// #
+    /// # fn main() -> std::io::Result<()> {
+    /// # let tempdir = tempdir::TempDir::new("mmap")?;
+    /// let path: PathBuf = /* path to file */
+    /// #   tempdir.path().join("map_mut");
+    /// let file = OpenOptions::new()
+    ///                        .read(true)
+    ///                        .write(true)
+    ///                        .create(true)
+    ///                        .open(&path)?;
+    /// file.set_len(13)?;
+    ///
+    /// let mut mmap = unsafe { MmapMut::map_mut(&file)? };
+    ///
+    /// mmap.copy_from_slice(b"Hello, world!");
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub unsafe fn map_mut(file: &File) -> Result<MmapMut> {
+        MmapOptions::new().map_mut(file)
+    }
+
+    /// Creates an anonymous memory map.
+    ///
+    /// This is equivalent to calling `MmapOptions::new().len(length).map_anon()`.
+    ///
+    /// # Errors
+    ///
+    /// This method returns an error when the underlying system call fails.
+    pub fn map_anon(length: usize) -> Result<MmapMut> {
+        MmapOptions::new().len(length).map_anon()
+    }
+
+    /// Flushes outstanding memory map modifications to disk.
+    ///
+    /// When this method returns with a non-error result, all outstanding changes to a file-backed
+    /// memory map are guaranteed to be durably stored. The file's metadata (including last
+    /// modification timestamp) may not be updated.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # extern crate memmap2;
+    /// # extern crate tempdir;
+    /// #
+    /// use std::fs::OpenOptions;
+    /// use std::io::Write;
+    /// use std::path::PathBuf;
+    ///
+    /// use memmap2::MmapMut;
+    ///
+    /// # fn main() -> std::io::Result<()> {
+    /// # let tempdir = tempdir::TempDir::new("mmap")?;
+    /// let path: PathBuf = /* path to file */
+    /// #   tempdir.path().join("flush");
+    /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?;
+    /// file.set_len(128)?;
+    ///
+    /// let mut mmap = unsafe { MmapMut::map_mut(&file)? };
+    ///
+    /// (&mut mmap[..]).write_all(b"Hello, world!")?;
+    /// mmap.flush()?;
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub fn flush(&self) -> Result<()> {
+        let len = self.len();
+        self.inner.flush(0, len)
+    }
+
+    /// Asynchronously flushes outstanding memory map modifications to disk.
+    ///
+    /// This method initiates flushing modified pages to durable storage, but it will not wait for
+    /// the operation to complete before returning. The file's metadata (including last
+    /// modification timestamp) may not be updated.
+    pub fn flush_async(&self) -> Result<()> {
+        let len = self.len();
+        self.inner.flush_async(0, len)
+    }
+
+    /// Flushes outstanding memory map modifications in the range to disk.
+    ///
+    /// The offset and length must be in the bounds of the memory map.
+    ///
+    /// When this method returns with a non-error result, all outstanding changes to a file-backed
+    /// memory in the range are guaranteed to be durable stored. The file's metadata (including
+    /// last modification timestamp) may not be updated. It is not guaranteed the only the changes
+    /// in the specified range are flushed; other outstanding changes to the memory map may be
+    /// flushed as well.
+    pub fn flush_range(&self, offset: usize, len: usize) -> Result<()> {
+        self.inner.flush(offset, len)
+    }
+
+    /// Asynchronously flushes outstanding memory map modifications in the range to disk.
+    ///
+    /// The offset and length must be in the bounds of the memory map.
+    ///
+    /// This method initiates flushing modified pages to durable storage, but it will not wait for
+    /// the operation to complete before returning. The file's metadata (including last
+    /// modification timestamp) may not be updated. It is not guaranteed that the only changes
+    /// flushed are those in the specified range; other outstanding changes to the memory map may
+    /// be flushed as well.
+    pub fn flush_async_range(&self, offset: usize, len: usize) -> Result<()> {
+        self.inner.flush_async(offset, len)
+    }
+
+    /// Returns an immutable version of this memory mapped buffer.
+    ///
+    /// If the memory map is file-backed, the file must have been opened with read permissions.
+    ///
+    /// # Errors
+    ///
+    /// This method returns an error when the underlying system call fails, which can happen for a
+    /// variety of reasons, such as when the file has not been opened with read permissions.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # extern crate memmap2;
+    /// #
+    /// use std::io::Write;
+    /// use std::path::PathBuf;
+    ///
+    /// use memmap2::{Mmap, MmapMut};
+    ///
+    /// # fn main() -> std::io::Result<()> {
+    /// let mut mmap = MmapMut::map_anon(128)?;
+    ///
+    /// (&mut mmap[..]).write(b"Hello, world!")?;
+    ///
+    /// let mmap: Mmap = mmap.make_read_only()?;
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub fn make_read_only(mut self) -> Result<Mmap> {
+        self.inner.make_read_only()?;
+        Ok(Mmap { inner: self.inner })
+    }
+
+    /// Transition the memory map to be readable and executable.
+    ///
+    /// If the memory map is file-backed, the file must have been opened with execute permissions.
+    ///
+    /// # Errors
+    ///
+    /// This method returns an error when the underlying system call fails, which can happen for a
+    /// variety of reasons, such as when the file has not been opened with execute permissions.
+    pub fn make_exec(mut self) -> Result<Mmap> {
+        self.inner.make_exec()?;
+        Ok(Mmap { inner: self.inner })
+    }
+}
+
+impl Deref for MmapMut {
+    type Target = [u8];
+
+    #[inline]
+    fn deref(&self) -> &[u8] {
+        unsafe { slice::from_raw_parts(self.inner.ptr(), self.inner.len()) }
+    }
+}
+
+impl DerefMut for MmapMut {
+    #[inline]
+    fn deref_mut(&mut self) -> &mut [u8] {
+        unsafe { slice::from_raw_parts_mut(self.inner.mut_ptr(), self.inner.len()) }
+    }
+}
+
+impl AsRef<[u8]> for MmapMut {
+    #[inline]
+    fn as_ref(&self) -> &[u8] {
+        self.deref()
+    }
+}
+
+impl AsMut<[u8]> for MmapMut {
+    #[inline]
+    fn as_mut(&mut self) -> &mut [u8] {
+        self.deref_mut()
+    }
+}
+
+impl fmt::Debug for MmapMut {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        fmt.debug_struct("MmapMut")
+            .field("ptr", &self.as_ptr())
+            .field("len", &self.len())
+            .finish()
+    }
+}
+
+#[cfg(test)]
+mod test {
+    extern crate tempdir;
+
+    use std::fs::OpenOptions;
+    use std::io::{Read, Write};
+    #[cfg(windows)]
+    use std::os::windows::fs::OpenOptionsExt;
+    use std::sync::Arc;
+    use std::thread;
+
+    #[cfg(windows)]
+    const GENERIC_ALL: u32 = 0x10000000;
+
+    use super::{Mmap, MmapMut, MmapOptions};
+
+    #[test]
+    fn map_file() {
+        let expected_len = 128;
+        let tempdir = tempdir::TempDir::new("mmap").unwrap();
+        let path = tempdir.path().join("mmap");
+
+        let file = OpenOptions::new()
+            .read(true)
+            .write(true)
+            .create(true)
+            .open(&path)
+            .unwrap();
+
+        file.set_len(expected_len as u64).unwrap();
+
+        let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
+        let len = mmap.len();
+        assert_eq!(expected_len, len);
+
+        let zeros = vec![0; len];
+        let incr: Vec<u8> = (0..len as u8).collect();
+
+        // check that the mmap is empty
+        assert_eq!(&zeros[..], &mmap[..]);
+
+        // write values into the mmap
+        (&mut mmap[..]).write_all(&incr[..]).unwrap();
+
+        // read values back
+        assert_eq!(&incr[..], &mmap[..]);
+    }
+
+    /// Checks that a 0-length file will not be mapped.
+    #[test]
+    fn map_empty_file() {
+        let tempdir = tempdir::TempDir::new("mmap").unwrap();
+        let path = tempdir.path().join("mmap");
+
+        let file = OpenOptions::new()
+            .read(true)
+            .write(true)
+            .create(true)
+            .open(&path)
+            .unwrap();
+        let mmap = unsafe { Mmap::map(&file) };
+        assert!(mmap.is_err());
+    }
+
+    #[test]
+    fn map_anon() {
+        let expected_len = 128;
+        let mut mmap = MmapMut::map_anon(expected_len).unwrap();
+        let len = mmap.len();
+        assert_eq!(expected_len, len);
+
+        let zeros = vec![0; len];
+        let incr: Vec<u8> = (0..len as u8).collect();
+
+        // check that the mmap is empty
+        assert_eq!(&zeros[..], &mmap[..]);
+
+        // write values into the mmap
+        (&mut mmap[..]).write_all(&incr[..]).unwrap();
+
+        // read values back
+        assert_eq!(&incr[..], &mmap[..]);
+    }
+
+    #[test]
+    fn map_anon_zero_len() {
+        assert!(MmapOptions::new().map_anon().is_err())
+    }
+
+    #[test]
+    fn file_write() {
+        let tempdir = tempdir::TempDir::new("mmap").unwrap();
+        let path = tempdir.path().join("mmap");
+
+        let mut file = OpenOptions::new()
+            .read(true)
+            .write(true)
+            .create(true)
+            .open(&path)
+            .unwrap();
+        file.set_len(128).unwrap();
+
+        let write = b"abc123";
+        let mut read = [0u8; 6];
+
+        let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
+        (&mut mmap[..]).write_all(write).unwrap();
+        mmap.flush().unwrap();
+
+        file.read(&mut read).unwrap();
+        assert_eq!(write, &read);
+    }
+
+    #[test]
+    fn flush_range() {
+        let tempdir = tempdir::TempDir::new("mmap").unwrap();
+        let path = tempdir.path().join("mmap");
+
+        let file = OpenOptions::new()
+            .read(true)
+            .write(true)
+            .create(true)
+            .open(&path)
+            .unwrap();
+        file.set_len(128).unwrap();
+        let write = b"abc123";
+
+        let mut mmap = unsafe {
+            MmapOptions::new()
+                .offset(2)
+                .len(write.len())
+                .map_mut(&file)
+                .unwrap()
+        };
+        (&mut mmap[..]).write_all(write).unwrap();
+        mmap.flush_range(0, write.len()).unwrap();
+    }
+
+    #[test]
+    fn map_copy() {
+        let tempdir = tempdir::TempDir::new("mmap").unwrap();
+        let path = tempdir.path().join("mmap");
+
+        let mut file = OpenOptions::new()
+            .read(true)
+            .write(true)
+            .create(true)
+            .open(&path)
+            .unwrap();
+        file.set_len(128).unwrap();
+
+        let nulls = b"\0\0\0\0\0\0";
+        let write = b"abc123";
+        let mut read = [0u8; 6];
+
+        let mut mmap = unsafe { MmapOptions::new().map_copy(&file).unwrap() };
+
+        (&mut mmap[..]).write(write).unwrap();
+        mmap.flush().unwrap();
+
+        // The mmap contains the write
+        (&mmap[..]).read(&mut read).unwrap();
+        assert_eq!(write, &read);
+
+        // The file does not contain the write
+        file.read(&mut read).unwrap();
+        assert_eq!(nulls, &read);
+
+        // another mmap does not contain the write
+        let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
+        (&mmap2[..]).read(&mut read).unwrap();
+        assert_eq!(nulls, &read);
+    }
+
+    #[test]
+    fn map_copy_read_only() {
+        let tempdir = tempdir::TempDir::new("mmap").unwrap();
+        let path = tempdir.path().join("mmap");
+
+        let file = OpenOptions::new()
+            .read(true)
+            .write(true)
+            .create(true)
+            .open(&path)
+            .unwrap();
+        file.set_len(128).unwrap();
+
+        let nulls = b"\0\0\0\0\0\0";
+        let mut read = [0u8; 6];
+
+        let mmap = unsafe { MmapOptions::new().map_copy_read_only(&file).unwrap() };
+        (&mmap[..]).read(&mut read).unwrap();
+        assert_eq!(nulls, &read);
+
+        let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
+        (&mmap2[..]).read(&mut read).unwrap();
+        assert_eq!(nulls, &read);
+    }
+
+    #[test]
+    fn map_offset() {
+        let tempdir = tempdir::TempDir::new("mmap").unwrap();
+        let path = tempdir.path().join("mmap");
+
+        let file = OpenOptions::new()
+            .read(true)
+            .write(true)
+            .create(true)
+            .open(&path)
+            .unwrap();
+
+        let offset = u32::max_value() as u64 + 2;
+        let len = 5432;
+        file.set_len(offset + len as u64).unwrap();
+
+        // Check inferred length mmap.
+        let mmap = unsafe { MmapOptions::new().offset(offset).map_mut(&file).unwrap() };
+        assert_eq!(len, mmap.len());
+
+        // Check explicit length mmap.
+        let mut mmap = unsafe {
+            MmapOptions::new()
+                .offset(offset)
+                .len(len)
+                .map_mut(&file)
+                .unwrap()
+        };
+        assert_eq!(len, mmap.len());
+
+        let zeros = vec![0; len];
+        let incr: Vec<_> = (0..len).map(|i| i as u8).collect();
+
+        // check that the mmap is empty
+        assert_eq!(&zeros[..], &mmap[..]);
+
+        // write values into the mmap
+        (&mut mmap[..]).write_all(&incr[..]).unwrap();
+
+        // read values back
+        assert_eq!(&incr[..], &mmap[..]);
+    }
+
+    #[test]
+    fn index() {
+        let mut mmap = MmapMut::map_anon(128).unwrap();
+        mmap[0] = 42;
+        assert_eq!(42, mmap[0]);
+    }
+
+    #[test]
+    fn sync_send() {
+        let mmap = Arc::new(MmapMut::map_anon(129).unwrap());
+        thread::spawn(move || {
+            &mmap[..];
+        });
+    }
+
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+    fn jit_x86(mut mmap: MmapMut) {
+        use std::mem;
+        mmap[0] = 0xB8; // mov eax, 0xAB
+        mmap[1] = 0xAB;
+        mmap[2] = 0x00;
+        mmap[3] = 0x00;
+        mmap[4] = 0x00;
+        mmap[5] = 0xC3; // ret
+
+        let mmap = mmap.make_exec().expect("make_exec");
+
+        let jitfn: extern "C" fn() -> u8 = unsafe { mem::transmute(mmap.as_ptr()) };
+        assert_eq!(jitfn(), 0xab);
+    }
+
+    #[test]
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+    fn jit_x86_anon() {
+        jit_x86(MmapMut::map_anon(4096).unwrap());
+    }
+
+    #[test]
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+    fn jit_x86_file() {
+        let tempdir = tempdir::TempDir::new("mmap").unwrap();
+        let mut options = OpenOptions::new();
+        #[cfg(windows)]
+        options.access_mode(GENERIC_ALL);
+
+        let file = options
+            .read(true)
+            .write(true)
+            .create(true)
+            .open(&tempdir.path().join("jit_x86"))
+            .expect("open");
+
+        file.set_len(4096).expect("set_len");
+        jit_x86(unsafe { MmapMut::map_mut(&file).expect("map_mut") });
+    }
+
+    #[test]
+    fn mprotect_file() {
+        let tempdir = tempdir::TempDir::new("mmap").unwrap();
+        let path = tempdir.path().join("mmap");
+
+        let mut options = OpenOptions::new();
+        #[cfg(windows)]
+        options.access_mode(GENERIC_ALL);
+
+        let mut file = options
+            .read(true)
+            .write(true)
+            .create(true)
+            .open(&path)
+            .expect("open");
+        file.set_len(256 as u64).expect("set_len");
+
+        let mmap = unsafe { MmapMut::map_mut(&file).expect("map_mut") };
+
+        let mmap = mmap.make_read_only().expect("make_read_only");
+        let mut mmap = mmap.make_mut().expect("make_mut");
+
+        let write = b"abc123";
+        let mut read = [0u8; 6];
+
+        (&mut mmap[..]).write(write).unwrap();
+        mmap.flush().unwrap();
+
+        // The mmap contains the write
+        (&mmap[..]).read(&mut read).unwrap();
+        assert_eq!(write, &read);
+
+        // The file should contain the write
+        file.read(&mut read).unwrap();
+        assert_eq!(write, &read);
+
+        // another mmap should contain the write
+        let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
+        (&mmap2[..]).read(&mut read).unwrap();
+        assert_eq!(write, &read);
+
+        let mmap = mmap.make_exec().expect("make_exec");
+
+        drop(mmap);
+    }
+
+    #[test]
+    fn mprotect_copy() {
+        let tempdir = tempdir::TempDir::new("mmap").unwrap();
+        let path = tempdir.path().join("mmap");
+
+        let mut options = OpenOptions::new();
+        #[cfg(windows)]
+        options.access_mode(GENERIC_ALL);
+
+        let mut file = options
+            .read(true)
+            .write(true)
+            .create(true)
+            .open(&path)
+            .expect("open");
+        file.set_len(256 as u64).expect("set_len");
+
+        let mmap = unsafe { MmapOptions::new().map_copy(&file).expect("map_mut") };
+
+        let mmap = mmap.make_read_only().expect("make_read_only");
+        let mut mmap = mmap.make_mut().expect("make_mut");
+
+        let nulls = b"\0\0\0\0\0\0";
+        let write = b"abc123";
+        let mut read = [0u8; 6];
+
+        (&mut mmap[..]).write(write).unwrap();
+        mmap.flush().unwrap();
+
+        // The mmap contains the write
+        (&mmap[..]).read(&mut read).unwrap();
+        assert_eq!(write, &read);
+
+        // The file does not contain the write
+        file.read(&mut read).unwrap();
+        assert_eq!(nulls, &read);
+
+        // another mmap does not contain the write
+        let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
+        (&mmap2[..]).read(&mut read).unwrap();
+        assert_eq!(nulls, &read);
+
+        let mmap = mmap.make_exec().expect("make_exec");
+
+        drop(mmap);
+    }
+
+    #[test]
+    fn mprotect_anon() {
+        let mmap = MmapMut::map_anon(256).expect("map_mut");
+
+        let mmap = mmap.make_read_only().expect("make_read_only");
+        let mmap = mmap.make_mut().expect("make_mut");
+        let mmap = mmap.make_exec().expect("make_exec");
+        drop(mmap);
+    }
+
+    #[test]
+    fn raw() {
+        let tempdir = tempdir::TempDir::new("mmap").unwrap();
+        let path = tempdir.path().join("mmapraw");
+
+        let mut options = OpenOptions::new();
+        let mut file = options
+            .read(true)
+            .write(true)
+            .create(true)
+            .open(&path)
+            .expect("open");
+        file.write(b"abc123").unwrap();
+        let mmap = MmapOptions::new().map_raw(&file).unwrap();
+        assert_eq!(mmap.len(), 6);
+        assert!(!mmap.as_ptr().is_null());
+        assert_eq!(unsafe { std::ptr::read(mmap.as_ptr()) }, b'a');
+    }
+}
diff --git a/vendor/memmap2-0.2.1/src/unix.rs b/vendor/memmap2-0.2.1/src/unix.rs
new file mode 100644 (file)
index 0000000..d8437a9
--- /dev/null
@@ -0,0 +1,224 @@
+extern crate libc;
+
+use std::fs::File;
+use std::os::unix::io::{AsRawFd, RawFd};
+use std::{io, ptr};
+
+#[cfg(any(
+    all(target_os = "linux", not(target_arch = "mips")),
+    target_os = "freebsd",
+    target_os = "android"
+))]
+const MAP_STACK: libc::c_int = libc::MAP_STACK;
+
+#[cfg(not(any(
+    all(target_os = "linux", not(target_arch = "mips")),
+    target_os = "freebsd",
+    target_os = "android"
+)))]
+const MAP_STACK: libc::c_int = 0;
+
+pub struct MmapInner {
+    ptr: *mut libc::c_void,
+    len: usize,
+}
+
+impl MmapInner {
+    /// Creates a new `MmapInner`.
+    ///
+    /// This is a thin wrapper around the `mmap` sytem call.
+    fn new(
+        len: usize,
+        prot: libc::c_int,
+        flags: libc::c_int,
+        file: RawFd,
+        offset: u64,
+    ) -> io::Result<MmapInner> {
+        let alignment = offset % page_size() as u64;
+        let aligned_offset = offset - alignment;
+        let aligned_len = len + alignment as usize;
+        if aligned_len == 0 {
+            // Normally the OS would catch this, but it segfaults under QEMU.
+            return Err(io::Error::new(
+                io::ErrorKind::InvalidInput,
+                "memory map must have a non-zero length",
+            ));
+        }
+
+        unsafe {
+            let ptr = libc::mmap(
+                ptr::null_mut(),
+                aligned_len as libc::size_t,
+                prot,
+                flags,
+                file,
+                aligned_offset as libc::off_t,
+            );
+
+            if ptr == libc::MAP_FAILED {
+                Err(io::Error::last_os_error())
+            } else {
+                Ok(MmapInner {
+                    ptr: ptr.offset(alignment as isize),
+                    len: len,
+                })
+            }
+        }
+    }
+
+    pub fn map(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> {
+        MmapInner::new(
+            len,
+            libc::PROT_READ,
+            libc::MAP_SHARED,
+            file.as_raw_fd(),
+            offset,
+        )
+    }
+
+    pub fn map_exec(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> {
+        MmapInner::new(
+            len,
+            libc::PROT_READ | libc::PROT_EXEC,
+            libc::MAP_SHARED,
+            file.as_raw_fd(),
+            offset,
+        )
+    }
+
+    pub fn map_mut(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> {
+        MmapInner::new(
+            len,
+            libc::PROT_READ | libc::PROT_WRITE,
+            libc::MAP_SHARED,
+            file.as_raw_fd(),
+            offset,
+        )
+    }
+
+    pub fn map_copy(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> {
+        MmapInner::new(
+            len,
+            libc::PROT_READ | libc::PROT_WRITE,
+            libc::MAP_PRIVATE,
+            file.as_raw_fd(),
+            offset,
+        )
+    }
+
+    pub fn map_copy_read_only(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> {
+        MmapInner::new(
+            len,
+            libc::PROT_READ,
+            libc::MAP_PRIVATE,
+            file.as_raw_fd(),
+            offset,
+        )
+    }
+
+    /// Open an anonymous memory map.
+    pub fn map_anon(len: usize, stack: bool) -> io::Result<MmapInner> {
+        let stack = if stack { MAP_STACK } else { 0 };
+        MmapInner::new(
+            len,
+            libc::PROT_READ | libc::PROT_WRITE,
+            libc::MAP_PRIVATE | libc::MAP_ANON | stack,
+            -1,
+            0,
+        )
+    }
+
+    pub fn flush(&self, offset: usize, len: usize) -> io::Result<()> {
+        let alignment = (self.ptr as usize + offset) % page_size();
+        let offset = offset as isize - alignment as isize;
+        let len = len + alignment;
+        let result =
+            unsafe { libc::msync(self.ptr.offset(offset), len as libc::size_t, libc::MS_SYNC) };
+        if result == 0 {
+            Ok(())
+        } else {
+            Err(io::Error::last_os_error())
+        }
+    }
+
+    pub fn flush_async(&self, offset: usize, len: usize) -> io::Result<()> {
+        let alignment = offset % page_size();
+        let aligned_offset = offset - alignment;
+        let aligned_len = len + alignment;
+        let result = unsafe {
+            libc::msync(
+                self.ptr.offset(aligned_offset as isize),
+                aligned_len as libc::size_t,
+                libc::MS_ASYNC,
+            )
+        };
+        if result == 0 {
+            Ok(())
+        } else {
+            Err(io::Error::last_os_error())
+        }
+    }
+
+    fn mprotect(&mut self, prot: libc::c_int) -> io::Result<()> {
+        unsafe {
+            let alignment = self.ptr as usize % page_size();
+            let ptr = self.ptr.offset(-(alignment as isize));
+            let len = self.len + alignment;
+            if libc::mprotect(ptr, len, prot) == 0 {
+                Ok(())
+            } else {
+                Err(io::Error::last_os_error())
+            }
+        }
+    }
+
+    pub fn make_read_only(&mut self) -> io::Result<()> {
+        self.mprotect(libc::PROT_READ)
+    }
+
+    pub fn make_exec(&mut self) -> io::Result<()> {
+        self.mprotect(libc::PROT_READ | libc::PROT_EXEC)
+    }
+
+    pub fn make_mut(&mut self) -> io::Result<()> {
+        self.mprotect(libc::PROT_READ | libc::PROT_WRITE)
+    }
+
+    #[inline]
+    pub fn ptr(&self) -> *const u8 {
+        self.ptr as *const u8
+    }
+
+    #[inline]
+    pub fn mut_ptr(&mut self) -> *mut u8 {
+        self.ptr as *mut u8
+    }
+
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.len
+    }
+}
+
+impl Drop for MmapInner {
+    fn drop(&mut self) {
+        let alignment = self.ptr as usize % page_size();
+        unsafe {
+            assert!(
+                libc::munmap(
+                    self.ptr.offset(-(alignment as isize)),
+                    (self.len + alignment) as libc::size_t
+                ) == 0,
+                "unable to unmap mmap: {}",
+                io::Error::last_os_error()
+            );
+        }
+    }
+}
+
+unsafe impl Sync for MmapInner {}
+unsafe impl Send for MmapInner {}
+
+fn page_size() -> usize {
+    unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
+}
diff --git a/vendor/memmap2-0.2.1/src/windows.rs b/vendor/memmap2-0.2.1/src/windows.rs
new file mode 100644 (file)
index 0000000..a0f3d55
--- /dev/null
@@ -0,0 +1,426 @@
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+
+use std::fs::File;
+use std::os::raw::c_void;
+use std::os::windows::io::{AsRawHandle, RawHandle};
+use std::{io, mem, ptr};
+
+type BOOL = i32;
+type WORD = u16;
+type DWORD = u32;
+type WCHAR = u16;
+type HANDLE = *mut c_void;
+type LPVOID = *mut c_void;
+type LPCVOID = *const c_void;
+type ULONG_PTR = usize;
+type SIZE_T = ULONG_PTR;
+type LPCWSTR = *const WCHAR;
+type PDWORD = *mut DWORD;
+type DWORD_PTR = ULONG_PTR;
+type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES;
+type LPSYSTEM_INFO = *mut SYSTEM_INFO;
+
+const INVALID_HANDLE_VALUE: HANDLE = -1isize as HANDLE;
+
+const STANDARD_RIGHTS_REQUIRED: DWORD = 0x000F0000;
+
+const SECTION_QUERY: DWORD = 0x0001;
+const SECTION_MAP_WRITE: DWORD = 0x0002;
+const SECTION_MAP_READ: DWORD = 0x0004;
+const SECTION_MAP_EXECUTE: DWORD = 0x0008;
+const SECTION_EXTEND_SIZE: DWORD = 0x0010;
+const SECTION_MAP_EXECUTE_EXPLICIT: DWORD = 0x0020;
+const SECTION_ALL_ACCESS: DWORD = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY
+    | SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_EXTEND_SIZE;
+
+const PAGE_READONLY: DWORD = 0x02;
+const PAGE_READWRITE: DWORD = 0x04;
+const PAGE_WRITECOPY: DWORD = 0x08;
+const PAGE_EXECUTE_READ: DWORD = 0x20;
+const PAGE_EXECUTE_READWRITE: DWORD = 0x40;
+const PAGE_EXECUTE_WRITECOPY: DWORD = 0x80;
+
+const FILE_MAP_WRITE: DWORD = SECTION_MAP_WRITE;
+const FILE_MAP_READ: DWORD = SECTION_MAP_READ;
+const FILE_MAP_ALL_ACCESS: DWORD = SECTION_ALL_ACCESS;
+const FILE_MAP_EXECUTE: DWORD = SECTION_MAP_EXECUTE_EXPLICIT;
+const FILE_MAP_COPY: DWORD = 0x00000001;
+
+#[repr(C)]
+#[derive(Clone, Copy)]
+struct SECURITY_ATTRIBUTES {
+    nLength: DWORD,
+    lpSecurityDescriptor: LPVOID,
+    bInheritHandle: BOOL,
+}
+
+#[repr(C)]
+#[derive(Clone, Copy)]
+struct SYSTEM_INFO_u_s {
+    wProcessorArchitecture: WORD,
+    wReserved: WORD,
+}
+
+#[repr(C)]
+#[derive(Clone, Copy)]
+struct SYSTEM_INFO_u([u32; 1]);
+
+#[repr(C)]
+#[derive(Clone, Copy)]
+struct SYSTEM_INFO {
+    u: SYSTEM_INFO_u,
+    dwPageSize: DWORD,
+    lpMinimumApplicationAddress: LPVOID,
+    lpMaximumApplicationAddress: LPVOID,
+    dwActiveProcessorMask: DWORD_PTR,
+    dwNumberOfProcessors: DWORD,
+    dwProcessorType: DWORD,
+    dwAllocationGranularity: DWORD,
+    wProcessorLevel: WORD,
+    wProcessorRevision: WORD,
+}
+
+extern "system" {
+    fn CloseHandle(
+        hObject: HANDLE,
+    ) -> BOOL;
+
+    fn CreateFileMappingW(
+        hFile: HANDLE,
+        lpFileMappingAttributes: LPSECURITY_ATTRIBUTES,
+        flProtect: DWORD,
+        dwMaximumSizeHigh: DWORD,
+        dwMaximumSizeLow: DWORD,
+        lpName: LPCWSTR,
+    ) -> HANDLE;
+
+    fn FlushViewOfFile(
+        lpBaseAddress: LPCVOID,
+        dwNumberOfBytesToFlush: SIZE_T,
+    ) -> BOOL;
+
+    fn UnmapViewOfFile(
+        lpBaseAddress: LPCVOID,
+    ) -> BOOL;
+
+    fn MapViewOfFile(
+        hFileMappingObject: HANDLE,
+        dwDesiredAccess: DWORD,
+        dwFileOffsetHigh: DWORD,
+        dwFileOffsetLow: DWORD,
+        dwNumberOfBytesToMap: SIZE_T,
+    ) -> LPVOID;
+
+    fn VirtualProtect(
+        lpAddress: LPVOID,
+        dwSize: SIZE_T,
+        flNewProtect: DWORD,
+        lpflOldProtect: PDWORD,
+    ) -> BOOL;
+
+    fn GetSystemInfo(
+        lpSystemInfo: LPSYSTEM_INFO,
+    );
+}
+
+pub struct MmapInner {
+    file: Option<File>,
+    ptr: *mut c_void,
+    len: usize,
+    copy: bool,
+}
+
+impl MmapInner {
+    /// Creates a new `MmapInner`.
+    ///
+    /// This is a thin wrapper around the `CreateFileMappingW` and `MapViewOfFile` system calls.
+    pub fn new(
+        file: &File,
+        protect: DWORD,
+        access: DWORD,
+        offset: u64,
+        len: usize,
+        copy: bool,
+    ) -> io::Result<MmapInner> {
+        let alignment = offset % allocation_granularity() as u64;
+        let aligned_offset = offset - alignment as u64;
+        let aligned_len = len + alignment as usize;
+
+        unsafe {
+            let handle = CreateFileMappingW(
+                file.as_raw_handle(),
+                ptr::null_mut(),
+                protect,
+                0,
+                0,
+                ptr::null(),
+            );
+            if handle == ptr::null_mut() {
+                return Err(io::Error::last_os_error());
+            }
+
+            let ptr = MapViewOfFile(
+                handle,
+                access,
+                (aligned_offset >> 16 >> 16) as DWORD,
+                (aligned_offset & 0xffffffff) as DWORD,
+                aligned_len as SIZE_T,
+            );
+            CloseHandle(handle);
+
+            if ptr == ptr::null_mut() {
+                Err(io::Error::last_os_error())
+            } else {
+                Ok(MmapInner {
+                    file: Some(file.try_clone()?),
+                    ptr: ptr.offset(alignment as isize),
+                    len: len as usize,
+                    copy: copy,
+                })
+            }
+        }
+    }
+
+    pub fn map(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> {
+        let write = protection_supported(file.as_raw_handle(), PAGE_READWRITE);
+        let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READ);
+        let mut access = FILE_MAP_READ;
+        let protection = match (write, exec) {
+            (true, true) => {
+                access |= FILE_MAP_WRITE | FILE_MAP_EXECUTE;
+                PAGE_EXECUTE_READWRITE
+            }
+            (true, false) => {
+                access |= FILE_MAP_WRITE;
+                PAGE_READWRITE
+            }
+            (false, true) => {
+                access |= FILE_MAP_EXECUTE;
+                PAGE_EXECUTE_READ
+            }
+            (false, false) => PAGE_READONLY,
+        };
+
+        let mut inner = MmapInner::new(file, protection, access, offset, len, false)?;
+        if write || exec {
+            inner.make_read_only()?;
+        }
+        Ok(inner)
+    }
+
+    pub fn map_exec(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> {
+        let write = protection_supported(file.as_raw_handle(), PAGE_READWRITE);
+        let mut access = FILE_MAP_READ | FILE_MAP_EXECUTE;
+        let protection = if write {
+            access |= FILE_MAP_WRITE;
+            PAGE_EXECUTE_READWRITE
+        } else {
+            PAGE_EXECUTE_READ
+        };
+
+        let mut inner = MmapInner::new(file, protection, access, offset, len, false)?;
+        if write {
+            inner.make_exec()?;
+        }
+        Ok(inner)
+    }
+
+    pub fn map_mut(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> {
+        let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READ);
+        let mut access = FILE_MAP_READ | FILE_MAP_WRITE;
+        let protection = if exec {
+            access |= FILE_MAP_EXECUTE;
+            PAGE_EXECUTE_READWRITE
+        } else {
+            PAGE_READWRITE
+        };
+
+        let mut inner = MmapInner::new(file, protection, access, offset, len, false)?;
+        if exec {
+            inner.make_mut()?;
+        }
+        Ok(inner)
+    }
+
+    pub fn map_copy(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> {
+        let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READWRITE);
+        let mut access = FILE_MAP_COPY;
+        let protection = if exec {
+            access |= FILE_MAP_EXECUTE;
+            PAGE_EXECUTE_WRITECOPY
+        } else {
+            PAGE_WRITECOPY
+        };
+
+        let mut inner = MmapInner::new(file, protection, access, offset, len, true)?;
+        if exec {
+            inner.make_mut()?;
+        }
+        Ok(inner)
+    }
+
+    pub fn map_copy_read_only(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> {
+        let write = protection_supported(file.as_raw_handle(), PAGE_READWRITE);
+        let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READ);
+        let mut access = FILE_MAP_COPY;
+        let protection = if exec {
+            access |= FILE_MAP_EXECUTE;
+            PAGE_EXECUTE_WRITECOPY
+        } else {
+            PAGE_WRITECOPY
+        };
+
+        let mut inner = MmapInner::new(file, protection, access, offset, len, true)?;
+        if write || exec {
+            inner.make_read_only()?;
+        }
+        Ok(inner)
+    }
+
+    pub fn map_anon(len: usize, _stack: bool) -> io::Result<MmapInner> {
+        unsafe {
+            // Create a mapping and view with maximum access permissions, then use `VirtualProtect`
+            // to set the actual `Protection`. This way, we can set more permissive protection later
+            // on.
+            // Also see https://msdn.microsoft.com/en-us/library/windows/desktop/aa366537.aspx
+
+            let handle = CreateFileMappingW(
+                INVALID_HANDLE_VALUE,
+                ptr::null_mut(),
+                PAGE_EXECUTE_READWRITE,
+                (len >> 16 >> 16) as DWORD,
+                (len & 0xffffffff) as DWORD,
+                ptr::null(),
+            );
+            if handle == ptr::null_mut() {
+                return Err(io::Error::last_os_error());
+            }
+            let access = FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE;
+            let ptr = MapViewOfFile(handle, access, 0, 0, len as SIZE_T);
+            CloseHandle(handle);
+
+            if ptr == ptr::null_mut() {
+                return Err(io::Error::last_os_error());
+            }
+
+            let mut old = 0;
+            let result = VirtualProtect(ptr, len as SIZE_T, PAGE_READWRITE, &mut old);
+            if result != 0 {
+                Ok(MmapInner {
+                    file: None,
+                    ptr: ptr,
+                    len: len as usize,
+                    copy: false,
+                })
+            } else {
+                Err(io::Error::last_os_error())
+            }
+        }
+    }
+
+    pub fn flush(&self, offset: usize, len: usize) -> io::Result<()> {
+        self.flush_async(offset, len)?;
+        if let Some(ref file) = self.file {
+            file.sync_data()?;
+        }
+        Ok(())
+    }
+
+    pub fn flush_async(&self, offset: usize, len: usize) -> io::Result<()> {
+        let result = unsafe { FlushViewOfFile(self.ptr.offset(offset as isize), len as SIZE_T) };
+        if result != 0 {
+            Ok(())
+        } else {
+            Err(io::Error::last_os_error())
+        }
+    }
+
+    fn virtual_protect(&mut self, protect: DWORD) -> io::Result<()> {
+        unsafe {
+            let alignment = self.ptr as usize % allocation_granularity();
+            let ptr = self.ptr.offset(-(alignment as isize));
+            let aligned_len = self.len as SIZE_T + alignment as SIZE_T;
+
+            let mut old = 0;
+            let result = VirtualProtect(ptr, aligned_len, protect, &mut old);
+
+            if result != 0 {
+                Ok(())
+            } else {
+                Err(io::Error::last_os_error())
+            }
+        }
+    }
+
+    pub fn make_read_only(&mut self) -> io::Result<()> {
+        self.virtual_protect(PAGE_READONLY)
+    }
+
+    pub fn make_exec(&mut self) -> io::Result<()> {
+        if self.copy {
+            self.virtual_protect(PAGE_EXECUTE_WRITECOPY)
+        } else {
+            self.virtual_protect(PAGE_EXECUTE_READ)
+        }
+    }
+
+    pub fn make_mut(&mut self) -> io::Result<()> {
+        if self.copy {
+            self.virtual_protect(PAGE_WRITECOPY)
+        } else {
+            self.virtual_protect(PAGE_READWRITE)
+        }
+    }
+
+    #[inline]
+    pub fn ptr(&self) -> *const u8 {
+        self.ptr as *const u8
+    }
+
+    #[inline]
+    pub fn mut_ptr(&mut self) -> *mut u8 {
+        self.ptr as *mut u8
+    }
+
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.len
+    }
+}
+
+impl Drop for MmapInner {
+    fn drop(&mut self) {
+        let alignment = self.ptr as usize % allocation_granularity();
+        unsafe {
+            let ptr = self.ptr.offset(-(alignment as isize));
+            assert!(
+                UnmapViewOfFile(ptr) != 0,
+                "unable to unmap mmap: {}",
+                io::Error::last_os_error()
+            );
+        }
+    }
+}
+
+unsafe impl Sync for MmapInner {}
+unsafe impl Send for MmapInner {}
+
+fn protection_supported(handle: RawHandle, protection: DWORD) -> bool {
+    unsafe {
+        let handle = CreateFileMappingW(handle, ptr::null_mut(), protection, 0, 0, ptr::null());
+        if handle == ptr::null_mut() {
+            return false;
+        }
+        CloseHandle(handle);
+        true
+    }
+}
+
+fn allocation_granularity() -> usize {
+    unsafe {
+        let mut info = mem::zeroed();
+        GetSystemInfo(&mut info);
+        return info.dwAllocationGranularity as usize;
+    }
+}
diff --git a/vendor/memmap2/.cargo-checksum.json b/vendor/memmap2/.cargo-checksum.json
deleted file mode 100644 (file)
index 58b1c4a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"CHANGELOG.md":"e365ce6fa5522d987eba49f65cb456b0459157fd57cdb255543cbc7534a73976","Cargo.lock":"2845110e68e42db3500fb871e6869890c74eeb5d9896407597e2002e9df771c1","Cargo.toml":"47e1e62ecbc842ab36a59d6c693ce4fadf5d676a6cada6fd313ee48c865771c2","LICENSE-APACHE":"04ea4849dba9dcae07113850c6f1b1a69052c625210639914eee352023f750ad","LICENSE-MIT":"e9116f7228fce981d81aa680ae1add0cfb8122c35d801c4664d3d674ad0beda8","README.md":"4e70c39451ff48d9b60e2a0db4754fefc2fe349149b4baf4747ca3556ac7ae15","examples/cat.rs":"ab0b575d19662e2d5b6c7cea2756b57530e495d56acdb4fd2b56c0ba4d768dfd","src/lib.rs":"72336fe793cd220b48b6e064ba258767d9521ed7ec47f0692b2cbbc3181c0e79","src/stub.rs":"f64675e86e590aa5aea779a60c22153fe4ab47a3d021b74f6dd697227e9971b1","src/unix.rs":"11f1f7c628827ad4d84564586b2718b046b5aae8d6b70bed3a2b715f1bb39ef4","src/windows.rs":"bca08b6db9a81ebb22517f92b9c38660d5ec3f8681cd9322f723ce2d715c1886"},"package":"723e3ebdcdc5c023db1df315364573789f8857c11b631a2fdfad7c00f5c046b4"}
\ No newline at end of file
diff --git a/vendor/memmap2/CHANGELOG.md b/vendor/memmap2/CHANGELOG.md
deleted file mode 100644 (file)
index 7e0ceaa..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-# Change Log
-All notable changes to this project will be documented in this file.
-
-The format is based on [Keep a Changelog](http://keepachangelog.com/)
-and this project adheres to [Semantic Versioning](http://semver.org/).
-
-## [Unreleased]
-
-## [0.2.3] - 2021-05-24
-### Added
-- Allow compilation on unsupported platform.
-  The code will panic on access just like in `std`.
-  [@jcaesar](https://github.com/jcaesar)
-
-## [0.2.2] - 2021-04-03
-### Added
-- `MmapOptions::populate`. [@adamreichold](https://github.com/adamreichold)
-
-### Fixed
-- Fix alignment computation for `flush_async` to match `flush`.
-  [@adamreichold](https://github.com/adamreichold)
-
-## [0.2.1] - 2021-02-08
-### Added
-- `MmapOptions::map_raw` and `MmapRaw`. [@diwic](https://github.com/diwic)
-
-## [0.2.0] - 2020-12-19
-### Changed
-- MSRV is 1.31 now (edition 2018).
-- Make anonymous memory maps private by default on unix. [@CensoredUsername](https://github.com/CensoredUsername)
-- Add `map_copy_read_only`. [@zserik](https://github.com/zserik)
-
-## 0.1.0 - 2020-01-18
-### Added
-- Fork [memmap-rs](https://github.com/danburkert/memmap-rs).
-
-### Changed
-- Use `LICENSE-APACHE` instead of `README.md` for some tests since it's immutable.
-
-### Removed
-- `winapi` dependency. [memmap-rs/pull/89](https://github.com/danburkert/memmap-rs/pull/89)
-
-[Unreleased]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.2.3...HEAD
-[0.2.3]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.2.2...v0.2.3
-[0.2.2]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.2.1...v0.2.2
-[0.2.1]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.2.0...v0.2.1
-[0.2.0]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.1.0...v0.2.0
diff --git a/vendor/memmap2/Cargo.lock b/vendor/memmap2/Cargo.lock
deleted file mode 100644 (file)
index d4b7653..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-[[package]]
-name = "fuchsia-cprng"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
-
-[[package]]
-name = "libc"
-version = "0.2.94"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
-
-[[package]]
-name = "memmap2"
-version = "0.2.3"
-dependencies = [
- "libc",
- "tempdir",
-]
-
-[[package]]
-name = "rand"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
-dependencies = [
- "fuchsia-cprng",
- "libc",
- "rand_core 0.3.1",
- "rdrand",
- "winapi",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
-dependencies = [
- "rand_core 0.4.2",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
-
-[[package]]
-name = "rdrand"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
-dependencies = [
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "remove_dir_all"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "tempdir"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
-dependencies = [
- "rand",
- "remove_dir_all",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/vendor/memmap2/Cargo.toml b/vendor/memmap2/Cargo.toml
deleted file mode 100644 (file)
index 840701f..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-edition = "2018"
-name = "memmap2"
-version = "0.2.3"
-authors = ["Dan Burkert <dan@danburkert.com>", "Evgeniy Reizner <razrfalcon@gmail.com>"]
-description = "Cross-platform Rust API for memory-mapped file IO"
-documentation = "https://docs.rs/memmap2"
-keywords = ["mmap", "memory-map", "io", "file"]
-license = "MIT/Apache-2.0"
-repository = "https://github.com/RazrFalcon/memmap2-rs"
-[dev-dependencies.tempdir]
-version = "0.3"
-[target."cfg(unix)".dependencies.libc]
-version = "0.2"
diff --git a/vendor/memmap2/LICENSE-APACHE b/vendor/memmap2/LICENSE-APACHE
deleted file mode 100644 (file)
index 7be3d81..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-                              Apache License
-                        Version 2.0, January 2004
-                     http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-   "License" shall mean the terms and conditions for use, reproduction,
-   and distribution as defined by Sections 1 through 9 of this document.
-
-   "Licensor" shall mean the copyright owner or entity authorized by
-   the copyright owner that is granting the License.
-
-   "Legal Entity" shall mean the union of the acting entity and all
-   other entities that control, are controlled by, or are under common
-   control with that entity. For the purposes of this definition,
-   "control" means (i) the power, direct or indirect, to cause the
-   direction or management of such entity, whether by contract or
-   otherwise, or (ii) ownership of fifty percent (50%) or more of the
-   outstanding shares, or (iii) beneficial ownership of such entity.
-
-   "You" (or "Your") shall mean an individual or Legal Entity
-   exercising permissions granted by this License.
-
-   "Source" form shall mean the preferred form for making modifications,
-   including but not limited to software source code, documentation
-   source, and configuration files.
-
-   "Object" form shall mean any form resulting from mechanical
-   transformation or translation of a Source form, including but
-   not limited to compiled object code, generated documentation,
-   and conversions to other media types.
-
-   "Work" shall mean the work of authorship, whether in Source or
-   Object form, made available under the License, as indicated by a
-   copyright notice that is included in or attached to the work
-   (an example is provided in the Appendix below).
-
-   "Derivative Works" shall mean any work, whether in Source or Object
-   form, that is based on (or derived from) the Work and for which the
-   editorial revisions, annotations, elaborations, or other modifications
-   represent, as a whole, an original work of authorship. For the purposes
-   of this License, Derivative Works shall not include works that remain
-   separable from, or merely link (or bind by name) to the interfaces of,
-   the Work and Derivative Works thereof.
-
-   "Contribution" shall mean any work of authorship, including
-   the original version of the Work and any modifications or additions
-   to that Work or Derivative Works thereof, that is intentionally
-   submitted to Licensor for inclusion in the Work by the copyright owner
-   or by an individual or Legal Entity authorized to submit on behalf of
-   the copyright owner. For the purposes of this definition, "submitted"
-   means any form of electronic, verbal, or written communication sent
-   to the Licensor or its representatives, including but not limited to
-   communication on electronic mailing lists, source code control systems,
-   and issue tracking systems that are managed by, or on behalf of, the
-   Licensor for the purpose of discussing and improving the Work, but
-   excluding communication that is conspicuously marked or otherwise
-   designated in writing by the copyright owner as "Not a Contribution."
-
-   "Contributor" shall mean Licensor and any individual or Legal Entity
-   on behalf of whom a Contribution has been received by Licensor and
-   subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   copyright license to reproduce, prepare Derivative Works of,
-   publicly display, publicly perform, sublicense, and distribute the
-   Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   (except as stated in this section) patent license to make, have made,
-   use, offer to sell, sell, import, and otherwise transfer the Work,
-   where such license applies only to those patent claims licensable
-   by such Contributor that are necessarily infringed by their
-   Contribution(s) alone or by combination of their Contribution(s)
-   with the Work to which such Contribution(s) was submitted. If You
-   institute patent litigation against any entity (including a
-   cross-claim or counterclaim in a lawsuit) alleging that the Work
-   or a Contribution incorporated within the Work constitutes direct
-   or contributory patent infringement, then any patent licenses
-   granted to You under this License for that Work shall terminate
-   as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
-   Work or Derivative Works thereof in any medium, with or without
-   modifications, and in Source or Object form, provided that You
-   meet the following conditions:
-
-   (a) You must give any other recipients of the Work or
-       Derivative Works a copy of this License; and
-
-   (b) You must cause any modified files to carry prominent notices
-       stating that You changed the files; and
-
-   (c) You must retain, in the Source form of any Derivative Works
-       that You distribute, all copyright, patent, trademark, and
-       attribution notices from the Source form of the Work,
-       excluding those notices that do not pertain to any part of
-       the Derivative Works; and
-
-   (d) If the Work includes a "NOTICE" text file as part of its
-       distribution, then any Derivative Works that You distribute must
-       include a readable copy of the attribution notices contained
-       within such NOTICE file, excluding those notices that do not
-       pertain to any part of the Derivative Works, in at least one
-       of the following places: within a NOTICE text file distributed
-       as part of the Derivative Works; within the Source form or
-       documentation, if provided along with the Derivative Works; or,
-       within a display generated by the Derivative Works, if and
-       wherever such third-party notices normally appear. The contents
-       of the NOTICE file are for informational purposes only and
-       do not modify the License. You may add Your own attribution
-       notices within Derivative Works that You distribute, alongside
-       or as an addendum to the NOTICE text from the Work, provided
-       that such additional attribution notices cannot be construed
-       as modifying the License.
-
-   You may add Your own copyright statement to Your modifications and
-   may provide additional or different license terms and conditions
-   for use, reproduction, or distribution of Your modifications, or
-   for any such Derivative Works as a whole, provided Your use,
-   reproduction, and distribution of the Work otherwise complies with
-   the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-   any Contribution intentionally submitted for inclusion in the Work
-   by You to the Licensor shall be under the terms and conditions of
-   this License, without any additional terms or conditions.
-   Notwithstanding the above, nothing herein shall supersede or modify
-   the terms of any separate license agreement you may have executed
-   with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-   names, trademarks, service marks, or product names of the Licensor,
-   except as required for reasonable and customary use in describing the
-   origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-   agreed to in writing, Licensor provides the Work (and each
-   Contributor provides its Contributions) on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-   implied, including, without limitation, any warranties or conditions
-   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-   PARTICULAR PURPOSE. You are solely responsible for determining the
-   appropriateness of using or redistributing the Work and assume any
-   risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-   whether in tort (including negligence), contract, or otherwise,
-   unless required by applicable law (such as deliberate and grossly
-   negligent acts) or agreed to in writing, shall any Contributor be
-   liable to You for damages, including any direct, indirect, special,
-   incidental, or consequential damages of any character arising as a
-   result of this License or out of the use or inability to use the
-   Work (including but not limited to damages for loss of goodwill,
-   work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses), even if such Contributor
-   has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-   the Work or Derivative Works thereof, You may choose to offer,
-   and charge a fee for, acceptance of support, warranty, indemnity,
-   or other liability obligations and/or rights consistent with this
-   License. However, in accepting such obligations, You may act only
-   on Your own behalf and on Your sole responsibility, not on behalf
-   of any other Contributor, and only if You agree to indemnify,
-   defend, and hold each Contributor harmless for any liability
-   incurred by, or claims asserted against, such Contributor by reason
-   of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-   To apply the Apache License to your work, attach the following
-   boilerplate notice, with the fields enclosed by brackets "[]"
-   replaced with your own identifying information. (Don't include
-   the brackets!)  The text should be enclosed in the appropriate
-   comment syntax for the file format. We also recommend that a
-   file or class name and description of purpose be included on the
-   same "printed page" as the copyright notice for easier
-   identification within third-party archives.
-
-Copyright [2015] [Dan Burkert]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/vendor/memmap2/LICENSE-MIT b/vendor/memmap2/LICENSE-MIT
deleted file mode 100644 (file)
index 5cc9371..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright (c) 2020 Evgeniy Reizner
-Copyright (c) 2015 Dan Burkert
-
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/vendor/memmap2/README.md b/vendor/memmap2/README.md
deleted file mode 100644 (file)
index 6749093..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-# memmap2
-![Build Status](https://github.com/RazrFalcon/memmap2-rs/workflows/Rust/badge.svg)
-[![Crates.io](https://img.shields.io/crates/v/memmap2.svg)](https://crates.io/crates/memmap2)
-[![Documentation](https://docs.rs/memmap2/badge.svg)](https://docs.rs/memmap2)
-[![Rust 1.31+](https://img.shields.io/badge/rust-1.31+-orange.svg)](https://www.rust-lang.org)
-
-A Rust library for cross-platform memory mapped IO.
-
-This is a **fork** of the [memmap-rs](https://github.com/danburkert/memmap-rs) crate.
-
-## Features
-
-- [x] file-backed memory maps
-- [x] anonymous memory maps
-- [x] synchronous and asynchronous flushing
-- [x] copy-on-write memory maps
-- [x] read-only memory maps
-- [x] stack support (`MAP_STACK` on unix)
-- [x] executable memory maps
-- [ ] huge page support
-
-A list of supported/tested targets can be found in [Actions](https://github.com/RazrFalcon/memmap2-rs/actions).
-
-## License
-
-`memmap2` is primarily distributed under the terms of both the MIT license and the
-Apache License (Version 2.0).
-
-See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT) for details.
-
-Copyright (c) 2020 Evgeniy Reizner
-
-Copyright (c) 2015 Dan Burkert
diff --git a/vendor/memmap2/examples/cat.rs b/vendor/memmap2/examples/cat.rs
deleted file mode 100644 (file)
index 34599af..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-extern crate memmap2;
-
-use std::env;
-use std::fs::File;
-use std::io::{self, Write};
-
-use memmap2::Mmap;
-
-/// Output a file's contents to stdout. The file path must be provided as the first process
-/// argument.
-fn main() {
-    let path = env::args()
-        .nth(1)
-        .expect("supply a single path as the program argument");
-
-    let file = File::open(path).expect("failed to open the file");
-
-    let mmap = unsafe { Mmap::map(&file).expect("failed to map the file") };
-
-    io::stdout()
-        .write_all(&mmap[..])
-        .expect("failed to output the file contents");
-}
diff --git a/vendor/memmap2/src/lib.rs b/vendor/memmap2/src/lib.rs
deleted file mode 100644 (file)
index 532ad7e..0000000
+++ /dev/null
@@ -1,1244 +0,0 @@
-//! A cross-platform Rust API for memory mapped buffers.
-
-#![doc(html_root_url = "https://docs.rs/memmap2/0.2.3")]
-
-#[cfg(windows)]
-mod windows;
-#[cfg(windows)]
-use windows::MmapInner;
-
-#[cfg(unix)]
-mod unix;
-#[cfg(unix)]
-use unix::MmapInner;
-
-#[cfg(not(any(unix, windows)))]
-mod stub;
-#[cfg(not(any(unix, windows)))]
-use crate::stub::MmapInner;
-
-use std::fmt;
-use std::fs::File;
-use std::io::{Error, ErrorKind, Result};
-use std::ops::{Deref, DerefMut};
-use std::slice;
-use std::usize;
-
-/// A memory map builder, providing advanced options and flags for specifying memory map behavior.
-///
-/// `MmapOptions` can be used to create an anonymous memory map using [`map_anon()`], or a
-/// file-backed memory map using one of [`map()`], [`map_mut()`], [`map_exec()`],
-/// [`map_copy()`], or [`map_copy_read_only()`].
-///
-/// ## Safety
-///
-/// All file-backed memory map constructors are marked `unsafe` because of the potential for
-/// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
-/// out of process. Applications must consider the risk and take appropriate precautions when
-/// using file-backed maps. Solutions such as file permissions, locks or process-private (e.g.
-/// unlinked) files exist but are platform specific and limited.
-///
-/// [`map_anon()`]: MmapOptions::map_anon()
-/// [`map()`]: MmapOptions::map()
-/// [`map_mut()`]: MmapOptions::map_mut()
-/// [`map_exec()`]: MmapOptions::map_exec()
-/// [`map_copy()`]: MmapOptions::map_copy()
-/// [`map_copy_read_only()`]: MmapOptions::map_copy_read_only()
-#[derive(Clone, Debug, Default)]
-pub struct MmapOptions {
-    offset: u64,
-    len: Option<usize>,
-    stack: bool,
-    populate: bool,
-}
-
-impl MmapOptions {
-    /// Creates a new set of options for configuring and creating a memory map.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use memmap2::{MmapMut, MmapOptions};
-    /// # use std::io::Result;
-    ///
-    /// # fn main() -> Result<()> {
-    /// // Create a new memory map builder.
-    /// let mut mmap_options = MmapOptions::new();
-    ///
-    /// // Configure the memory map builder using option setters, then create
-    /// // a memory map using one of `mmap_options.map_anon`, `mmap_options.map`,
-    /// // `mmap_options.map_mut`, `mmap_options.map_exec`, or `mmap_options.map_copy`:
-    /// let mut mmap: MmapMut = mmap_options.len(36).map_anon()?;
-    ///
-    /// // Use the memory map:
-    /// mmap.copy_from_slice(b"...data to copy to the memory map...");
-    /// # Ok(())
-    /// # }
-    /// ```
-    pub fn new() -> MmapOptions {
-        MmapOptions::default()
-    }
-
-    /// Configures the memory map to start at byte `offset` from the beginning of the file.
-    ///
-    /// This option has no effect on anonymous memory maps.
-    ///
-    /// By default, the offset is 0.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use memmap2::MmapOptions;
-    /// use std::fs::File;
-    ///
-    /// # fn main() -> std::io::Result<()> {
-    /// let mmap = unsafe {
-    ///     MmapOptions::new()
-    ///                 .offset(30)
-    ///                 .map(&File::open("LICENSE-APACHE")?)?
-    /// };
-    /// assert_eq!(&b"Apache License"[..],
-    ///            &mmap[..14]);
-    /// # Ok(())
-    /// # }
-    /// ```
-    pub fn offset(&mut self, offset: u64) -> &mut Self {
-        self.offset = offset;
-        self
-    }
-
-    /// Configures the created memory mapped buffer to be `len` bytes long.
-    ///
-    /// This option is mandatory for anonymous memory maps.
-    ///
-    /// For file-backed memory maps, the length will default to the file length.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use memmap2::MmapOptions;
-    /// use std::fs::File;
-    ///
-    /// # fn main() -> std::io::Result<()> {
-    /// let mmap = unsafe {
-    ///     MmapOptions::new()
-    ///                 .len(9)
-    ///                 .map(&File::open("README.md")?)?
-    /// };
-    /// assert_eq!(&b"# memmap2"[..], &mmap[..]);
-    /// # Ok(())
-    /// # }
-    /// ```
-    pub fn len(&mut self, len: usize) -> &mut Self {
-        self.len = Some(len);
-        self
-    }
-
-    /// Returns the configured length, or the length of the provided file.
-    fn get_len(&self, file: &File) -> Result<usize> {
-        self.len.map(Ok).unwrap_or_else(|| {
-            let len = file.metadata()?.len() - self.offset;
-            if len > (usize::MAX as u64) {
-                return Err(Error::new(
-                    ErrorKind::InvalidData,
-                    "memory map length overflows usize",
-                ));
-            }
-            Ok(len as usize)
-        })
-    }
-
-    /// Configures the anonymous memory map to be suitable for a process or thread stack.
-    ///
-    /// This option corresponds to the `MAP_STACK` flag on Linux. It has no effect on Windows.
-    ///
-    /// This option has no effect on file-backed memory maps.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use memmap2::MmapOptions;
-    ///
-    /// # fn main() -> std::io::Result<()> {
-    /// let stack = MmapOptions::new().stack().len(4096).map_anon();
-    /// # Ok(())
-    /// # }
-    /// ```
-    pub fn stack(&mut self) -> &mut Self {
-        self.stack = true;
-        self
-    }
-
-    /// Populate (prefault) page tables for a mapping.
-    ///
-    /// For a file mapping, this causes read-ahead on the file. This will help to reduce blocking on page faults later.
-    ///
-    /// This option corresponds to the `MAP_POPULATE` flag on Linux. It has no effect on Windows.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use memmap2::MmapOptions;
-    /// use std::fs::File;
-    ///
-    /// # fn main() -> std::io::Result<()> {
-    /// let file = File::open("LICENSE-MIT")?;
-    ///
-    /// let mmap = unsafe {
-    ///     MmapOptions::new().populate().map(&file)?
-    /// };
-    ///
-    /// assert_eq!(&b"Copyright"[..], &mmap[..9]);
-    /// # Ok(())
-    /// # }
-    /// ```
-    pub fn populate(&mut self) -> &mut Self {
-        self.populate = true;
-        self
-    }
-
-    /// Creates a read-only memory map backed by a file.
-    ///
-    /// # Errors
-    ///
-    /// This method returns an error when the underlying system call fails, which can happen for a
-    /// variety of reasons, such as when the file is not open with read permissions.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use memmap2::MmapOptions;
-    /// use std::fs::File;
-    /// use std::io::Read;
-    ///
-    /// # fn main() -> std::io::Result<()> {
-    /// let mut file = File::open("LICENSE-APACHE")?;
-    ///
-    /// let mut contents = Vec::new();
-    /// file.read_to_end(&mut contents)?;
-    ///
-    /// let mmap = unsafe {
-    ///     MmapOptions::new().map(&file)?
-    /// };
-    ///
-    /// assert_eq!(&contents[..], &mmap[..]);
-    /// # Ok(())
-    /// # }
-    /// ```
-    pub unsafe fn map(&self, file: &File) -> Result<Mmap> {
-        MmapInner::map(self.get_len(file)?, file, self.offset, self.populate)
-            .map(|inner| Mmap { inner })
-    }
-
-    /// Creates a readable and executable memory map backed by a file.
-    ///
-    /// # Errors
-    ///
-    /// This method returns an error when the underlying system call fails, which can happen for a
-    /// variety of reasons, such as when the file is not open with read permissions.
-    pub unsafe fn map_exec(&self, file: &File) -> Result<Mmap> {
-        MmapInner::map_exec(self.get_len(file)?, file, self.offset, self.populate)
-            .map(|inner| Mmap { inner })
-    }
-
-    /// Creates a writeable memory map backed by a file.
-    ///
-    /// # Errors
-    ///
-    /// This method returns an error when the underlying system call fails, which can happen for a
-    /// variety of reasons, such as when the file is not open with read and write permissions.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # extern crate memmap2;
-    /// # extern crate tempdir;
-    /// #
-    /// use std::fs::OpenOptions;
-    /// use std::path::PathBuf;
-    ///
-    /// use memmap2::MmapOptions;
-    /// #
-    /// # fn main() -> std::io::Result<()> {
-    /// # let tempdir = tempdir::TempDir::new("mmap")?;
-    /// let path: PathBuf = /* path to file */
-    /// #   tempdir.path().join("map_mut");
-    /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?;
-    /// file.set_len(13)?;
-    ///
-    /// let mut mmap = unsafe {
-    ///     MmapOptions::new().map_mut(&file)?
-    /// };
-    ///
-    /// mmap.copy_from_slice(b"Hello, world!");
-    /// # Ok(())
-    /// # }
-    /// ```
-    pub unsafe fn map_mut(&self, file: &File) -> Result<MmapMut> {
-        MmapInner::map_mut(self.get_len(file)?, file, self.offset, self.populate)
-            .map(|inner| MmapMut { inner })
-    }
-
-    /// Creates a copy-on-write memory map backed by a file.
-    ///
-    /// Data written to the memory map will not be visible by other processes,
-    /// and will not be carried through to the underlying file.
-    ///
-    /// # Errors
-    ///
-    /// This method returns an error when the underlying system call fails, which can happen for a
-    /// variety of reasons, such as when the file is not open with writable permissions.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use memmap2::MmapOptions;
-    /// use std::fs::File;
-    /// use std::io::Write;
-    ///
-    /// # fn main() -> std::io::Result<()> {
-    /// let file = File::open("LICENSE-APACHE")?;
-    /// let mut mmap = unsafe { MmapOptions::new().map_copy(&file)? };
-    /// (&mut mmap[..]).write_all(b"Hello, world!")?;
-    /// # Ok(())
-    /// # }
-    /// ```
-    pub unsafe fn map_copy(&self, file: &File) -> Result<MmapMut> {
-        MmapInner::map_copy(self.get_len(file)?, file, self.offset, self.populate)
-            .map(|inner| MmapMut { inner })
-    }
-
-    /// Creates a copy-on-write read-only memory map backed by a file.
-    ///
-    /// # Errors
-    ///
-    /// This method returns an error when the underlying system call fails, which can happen for a
-    /// variety of reasons, such as when the file is not open with read permissions.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use memmap2::MmapOptions;
-    /// use std::fs::File;
-    /// use std::io::Read;
-    ///
-    /// # fn main() -> std::io::Result<()> {
-    /// let mut file = File::open("README.md")?;
-    ///
-    /// let mut contents = Vec::new();
-    /// file.read_to_end(&mut contents)?;
-    ///
-    /// let mmap = unsafe {
-    ///     MmapOptions::new().map_copy_read_only(&file)?
-    /// };
-    ///
-    /// assert_eq!(&contents[..], &mmap[..]);
-    /// # Ok(())
-    /// # }
-    /// ```
-    pub unsafe fn map_copy_read_only(&self, file: &File) -> Result<Mmap> {
-        MmapInner::map_copy_read_only(self.get_len(file)?, file, self.offset, self.populate)
-            .map(|inner| Mmap { inner })
-    }
-
-    /// Creates an anonymous memory map.
-    ///
-    /// Note: the memory map length must be configured to be greater than 0 before creating an
-    /// anonymous memory map using `MmapOptions::len()`.
-    ///
-    /// # Errors
-    ///
-    /// This method returns an error when the underlying system call fails.
-    pub fn map_anon(&self) -> Result<MmapMut> {
-        MmapInner::map_anon(self.len.unwrap_or(0), self.stack).map(|inner| MmapMut { inner })
-    }
-
-    /// Creates a raw memory map.
-    ///
-    /// # Errors
-    ///
-    /// This method returns an error when the underlying system call fails, which can happen for a
-    /// variety of reasons, such as when the file is not open with read and write permissions.
-    pub fn map_raw(&self, file: &File) -> Result<MmapRaw> {
-        MmapInner::map_mut(self.get_len(file)?, file, self.offset, self.populate)
-            .map(|inner| MmapRaw { inner })
-    }
-}
-
-/// A handle to an immutable memory mapped buffer.
-///
-/// A `Mmap` may be backed by a file, or it can be anonymous map, backed by volatile memory. Use
-/// [`MmapOptions`] or [`map()`] to create a file-backed memory map. To create an immutable
-/// anonymous memory map, first create a mutable anonymous memory map, and then make it immutable
-/// with [`MmapMut::make_read_only()`].
-///
-/// A file backed `Mmap` is created by `&File` reference, and will remain valid even after the
-/// `File` is dropped. In other words, the `Mmap` handle is completely independent of the `File`
-/// used to create it. For consistency, on some platforms this is achieved by duplicating the
-/// underlying file handle. The memory will be unmapped when the `Mmap` handle is dropped.
-///
-/// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping
-/// the mapped pages into physical memory) though the details of this are platform specific.
-///
-/// `Mmap` is [`Sync`](std::marker::Sync) and [`Send`](std::marker::Send).
-///
-/// ## Safety
-///
-/// All file-backed memory map constructors are marked `unsafe` because of the potential for
-/// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
-/// out of process. Applications must consider the risk and take appropriate precautions when using
-/// file-backed maps. Solutions such as file permissions, locks or process-private (e.g. unlinked)
-/// files exist but are platform specific and limited.
-///
-/// ## Example
-///
-/// ```
-/// use memmap2::MmapOptions;
-/// use std::io::Write;
-/// use std::fs::File;
-///
-/// # fn main() -> std::io::Result<()> {
-/// let file = File::open("README.md")?;
-/// let mmap = unsafe { MmapOptions::new().map(&file)? };
-/// assert_eq!(b"# memmap2", &mmap[0..9]);
-/// # Ok(())
-/// # }
-/// ```
-///
-/// See [`MmapMut`] for the mutable version.
-///
-/// [`map()`]: Mmap::map()
-pub struct Mmap {
-    inner: MmapInner,
-}
-
-impl Mmap {
-    /// Creates a read-only memory map backed by a file.
-    ///
-    /// This is equivalent to calling `MmapOptions::new().map(file)`.
-    ///
-    /// # Errors
-    ///
-    /// This method returns an error when the underlying system call fails, which can happen for a
-    /// variety of reasons, such as when the file is not open with read permissions.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::fs::File;
-    /// use std::io::Read;
-    ///
-    /// use memmap2::Mmap;
-    ///
-    /// # fn main() -> std::io::Result<()> {
-    /// let mut file = File::open("LICENSE-APACHE")?;
-    ///
-    /// let mut contents = Vec::new();
-    /// file.read_to_end(&mut contents)?;
-    ///
-    /// let mmap = unsafe { Mmap::map(&file)?  };
-    ///
-    /// assert_eq!(&contents[..], &mmap[..]);
-    /// # Ok(())
-    /// # }
-    /// ```
-    pub unsafe fn map(file: &File) -> Result<Mmap> {
-        MmapOptions::new().map(file)
-    }
-
-    /// Transition the memory map to be writable.
-    ///
-    /// If the memory map is file-backed, the file must have been opened with write permissions.
-    ///
-    /// # Errors
-    ///
-    /// This method returns an error when the underlying system call fails, which can happen for a
-    /// variety of reasons, such as when the file is not open with writable permissions.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # extern crate memmap2;
-    /// # extern crate tempdir;
-    /// #
-    /// use memmap2::Mmap;
-    /// use std::ops::DerefMut;
-    /// use std::io::Write;
-    /// # use std::fs::OpenOptions;
-    ///
-    /// # fn main() -> std::io::Result<()> {
-    /// # let tempdir = tempdir::TempDir::new("mmap")?;
-    /// let file = /* file opened with write permissions */
-    /// #          OpenOptions::new()
-    /// #                      .read(true)
-    /// #                      .write(true)
-    /// #                      .create(true)
-    /// #                      .open(tempdir.path()
-    /// #                      .join("make_mut"))?;
-    /// # file.set_len(128)?;
-    /// let mmap = unsafe { Mmap::map(&file)? };
-    /// // ... use the read-only memory map ...
-    /// let mut mut_mmap = mmap.make_mut()?;
-    /// mut_mmap.deref_mut().write_all(b"hello, world!")?;
-    /// # Ok(())
-    /// # }
-    /// ```
-    pub fn make_mut(mut self) -> Result<MmapMut> {
-        self.inner.make_mut()?;
-        Ok(MmapMut { inner: self.inner })
-    }
-}
-
-impl Deref for Mmap {
-    type Target = [u8];
-
-    #[inline]
-    fn deref(&self) -> &[u8] {
-        unsafe { slice::from_raw_parts(self.inner.ptr(), self.inner.len()) }
-    }
-}
-
-impl AsRef<[u8]> for Mmap {
-    #[inline]
-    fn as_ref(&self) -> &[u8] {
-        self.deref()
-    }
-}
-
-impl fmt::Debug for Mmap {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        fmt.debug_struct("Mmap")
-            .field("ptr", &self.as_ptr())
-            .field("len", &self.len())
-            .finish()
-    }
-}
-
-/// A handle to a raw memory mapped buffer.
-///
-/// This struct never hands out references to its interior, only raw pointers.
-/// This can be helpful when creating shared memory maps between untrusted processes.
-pub struct MmapRaw {
-    inner: MmapInner,
-}
-
-impl MmapRaw {
-    /// Creates a writeable memory map backed by a file.
-    ///
-    /// This is equivalent to calling `MmapOptions::new().map_raw(file)`.
-    ///
-    /// # Errors
-    ///
-    /// This method returns an error when the underlying system call fails, which can happen for a
-    /// variety of reasons, such as when the file is not open with read and write permissions.
-    pub fn map_raw(file: &File) -> Result<MmapRaw> {
-        MmapOptions::new().map_raw(file)
-    }
-
-    /// Returns a raw pointer to the memory mapped file.
-    ///
-    /// Before dereferencing this pointer, you have to make sure that the file has not been
-    /// truncated since the memory map was created.
-    /// Avoiding this will not introduce memory safety issues in Rust terms,
-    /// but will cause SIGBUS (or equivalent) signal.
-    #[inline]
-    pub fn as_ptr(&self) -> *const u8 {
-        self.inner.ptr()
-    }
-
-    /// Returns an unsafe mutable pointer to the memory mapped file.
-    ///
-    /// Before dereferencing this pointer, you have to make sure that the file has not been
-    /// truncated since the memory map was created.
-    /// Avoiding this will not introduce memory safety issues in Rust terms,
-    /// but will cause SIGBUS (or equivalent) signal.
-    #[inline]
-    pub fn as_mut_ptr(&self) -> *mut u8 {
-        self.inner.ptr() as _
-    }
-
-    /// Returns the length in bytes of the memory map.
-    ///
-    /// Note that truncating the file can cause the length to change (and render this value unusable).
-    #[inline]
-    pub fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-
-impl fmt::Debug for MmapRaw {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        fmt.debug_struct("MmapRaw")
-            .field("ptr", &self.as_ptr())
-            .field("len", &self.len())
-            .finish()
-    }
-}
-
-/// A handle to a mutable memory mapped buffer.
-///
-/// A file-backed `MmapMut` buffer may be used to read from or write to a file. An anonymous
-/// `MmapMut` buffer may be used any place that an in-memory byte buffer is needed. Use
-/// [`MmapMut::map_mut()`] and [`MmapMut::map_anon()`] to create a mutable memory map of the
-/// respective types, or [`MmapOptions::map_mut()`] and [`MmapOptions::map_anon()`] if non-default
-/// options are required.
-///
-/// A file backed `MmapMut` is created by `&File` reference, and will remain valid even after the
-/// `File` is dropped. In other words, the `MmapMut` handle is completely independent of the `File`
-/// used to create it. For consistency, on some platforms this is achieved by duplicating the
-/// underlying file handle. The memory will be unmapped when the `MmapMut` handle is dropped.
-///
-/// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping
-/// the mapped pages into physical memory) though the details of this are platform specific.
-///
-/// `Mmap` is [`Sync`](std::marker::Sync) and [`Send`](std::marker::Send).
-///
-/// See [`Mmap`] for the immutable version.
-///
-/// ## Safety
-///
-/// All file-backed memory map constructors are marked `unsafe` because of the potential for
-/// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
-/// out of process. Applications must consider the risk and take appropriate precautions when using
-/// file-backed maps. Solutions such as file permissions, locks or process-private (e.g. unlinked)
-/// files exist but are platform specific and limited.
-pub struct MmapMut {
-    inner: MmapInner,
-}
-
-impl MmapMut {
-    /// Creates a writeable memory map backed by a file.
-    ///
-    /// This is equivalent to calling `MmapOptions::new().map_mut(file)`.
-    ///
-    /// # Errors
-    ///
-    /// This method returns an error when the underlying system call fails, which can happen for a
-    /// variety of reasons, such as when the file is not open with read and write permissions.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # extern crate memmap2;
-    /// # extern crate tempdir;
-    /// #
-    /// use std::fs::OpenOptions;
-    /// use std::path::PathBuf;
-    ///
-    /// use memmap2::MmapMut;
-    /// #
-    /// # fn main() -> std::io::Result<()> {
-    /// # let tempdir = tempdir::TempDir::new("mmap")?;
-    /// let path: PathBuf = /* path to file */
-    /// #   tempdir.path().join("map_mut");
-    /// let file = OpenOptions::new()
-    ///                        .read(true)
-    ///                        .write(true)
-    ///                        .create(true)
-    ///                        .open(&path)?;
-    /// file.set_len(13)?;
-    ///
-    /// let mut mmap = unsafe { MmapMut::map_mut(&file)? };
-    ///
-    /// mmap.copy_from_slice(b"Hello, world!");
-    /// # Ok(())
-    /// # }
-    /// ```
-    pub unsafe fn map_mut(file: &File) -> Result<MmapMut> {
-        MmapOptions::new().map_mut(file)
-    }
-
-    /// Creates an anonymous memory map.
-    ///
-    /// This is equivalent to calling `MmapOptions::new().len(length).map_anon()`.
-    ///
-    /// # Errors
-    ///
-    /// This method returns an error when the underlying system call fails.
-    pub fn map_anon(length: usize) -> Result<MmapMut> {
-        MmapOptions::new().len(length).map_anon()
-    }
-
-    /// Flushes outstanding memory map modifications to disk.
-    ///
-    /// When this method returns with a non-error result, all outstanding changes to a file-backed
-    /// memory map are guaranteed to be durably stored. The file's metadata (including last
-    /// modification timestamp) may not be updated.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # extern crate memmap2;
-    /// # extern crate tempdir;
-    /// #
-    /// use std::fs::OpenOptions;
-    /// use std::io::Write;
-    /// use std::path::PathBuf;
-    ///
-    /// use memmap2::MmapMut;
-    ///
-    /// # fn main() -> std::io::Result<()> {
-    /// # let tempdir = tempdir::TempDir::new("mmap")?;
-    /// let path: PathBuf = /* path to file */
-    /// #   tempdir.path().join("flush");
-    /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?;
-    /// file.set_len(128)?;
-    ///
-    /// let mut mmap = unsafe { MmapMut::map_mut(&file)? };
-    ///
-    /// (&mut mmap[..]).write_all(b"Hello, world!")?;
-    /// mmap.flush()?;
-    /// # Ok(())
-    /// # }
-    /// ```
-    pub fn flush(&self) -> Result<()> {
-        let len = self.len();
-        self.inner.flush(0, len)
-    }
-
-    /// Asynchronously flushes outstanding memory map modifications to disk.
-    ///
-    /// This method initiates flushing modified pages to durable storage, but it will not wait for
-    /// the operation to complete before returning. The file's metadata (including last
-    /// modification timestamp) may not be updated.
-    pub fn flush_async(&self) -> Result<()> {
-        let len = self.len();
-        self.inner.flush_async(0, len)
-    }
-
-    /// Flushes outstanding memory map modifications in the range to disk.
-    ///
-    /// The offset and length must be in the bounds of the memory map.
-    ///
-    /// When this method returns with a non-error result, all outstanding changes to a file-backed
-    /// memory in the range are guaranteed to be durable stored. The file's metadata (including
-    /// last modification timestamp) may not be updated. It is not guaranteed the only the changes
-    /// in the specified range are flushed; other outstanding changes to the memory map may be
-    /// flushed as well.
-    pub fn flush_range(&self, offset: usize, len: usize) -> Result<()> {
-        self.inner.flush(offset, len)
-    }
-
-    /// Asynchronously flushes outstanding memory map modifications in the range to disk.
-    ///
-    /// The offset and length must be in the bounds of the memory map.
-    ///
-    /// This method initiates flushing modified pages to durable storage, but it will not wait for
-    /// the operation to complete before returning. The file's metadata (including last
-    /// modification timestamp) may not be updated. It is not guaranteed that the only changes
-    /// flushed are those in the specified range; other outstanding changes to the memory map may
-    /// be flushed as well.
-    pub fn flush_async_range(&self, offset: usize, len: usize) -> Result<()> {
-        self.inner.flush_async(offset, len)
-    }
-
-    /// Returns an immutable version of this memory mapped buffer.
-    ///
-    /// If the memory map is file-backed, the file must have been opened with read permissions.
-    ///
-    /// # Errors
-    ///
-    /// This method returns an error when the underlying system call fails, which can happen for a
-    /// variety of reasons, such as when the file has not been opened with read permissions.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # extern crate memmap2;
-    /// #
-    /// use std::io::Write;
-    /// use std::path::PathBuf;
-    ///
-    /// use memmap2::{Mmap, MmapMut};
-    ///
-    /// # fn main() -> std::io::Result<()> {
-    /// let mut mmap = MmapMut::map_anon(128)?;
-    ///
-    /// (&mut mmap[..]).write(b"Hello, world!")?;
-    ///
-    /// let mmap: Mmap = mmap.make_read_only()?;
-    /// # Ok(())
-    /// # }
-    /// ```
-    pub fn make_read_only(mut self) -> Result<Mmap> {
-        self.inner.make_read_only()?;
-        Ok(Mmap { inner: self.inner })
-    }
-
-    /// Transition the memory map to be readable and executable.
-    ///
-    /// If the memory map is file-backed, the file must have been opened with execute permissions.
-    ///
-    /// # Errors
-    ///
-    /// This method returns an error when the underlying system call fails, which can happen for a
-    /// variety of reasons, such as when the file has not been opened with execute permissions.
-    pub fn make_exec(mut self) -> Result<Mmap> {
-        self.inner.make_exec()?;
-        Ok(Mmap { inner: self.inner })
-    }
-}
-
-impl Deref for MmapMut {
-    type Target = [u8];
-
-    #[inline]
-    fn deref(&self) -> &[u8] {
-        unsafe { slice::from_raw_parts(self.inner.ptr(), self.inner.len()) }
-    }
-}
-
-impl DerefMut for MmapMut {
-    #[inline]
-    fn deref_mut(&mut self) -> &mut [u8] {
-        unsafe { slice::from_raw_parts_mut(self.inner.mut_ptr(), self.inner.len()) }
-    }
-}
-
-impl AsRef<[u8]> for MmapMut {
-    #[inline]
-    fn as_ref(&self) -> &[u8] {
-        self.deref()
-    }
-}
-
-impl AsMut<[u8]> for MmapMut {
-    #[inline]
-    fn as_mut(&mut self) -> &mut [u8] {
-        self.deref_mut()
-    }
-}
-
-impl fmt::Debug for MmapMut {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        fmt.debug_struct("MmapMut")
-            .field("ptr", &self.as_ptr())
-            .field("len", &self.len())
-            .finish()
-    }
-}
-
-#[cfg(test)]
-mod test {
-    extern crate tempdir;
-
-    use std::fs::OpenOptions;
-    use std::io::{Read, Write};
-    #[cfg(windows)]
-    use std::os::windows::fs::OpenOptionsExt;
-
-    #[cfg(windows)]
-    const GENERIC_ALL: u32 = 0x10000000;
-
-    use super::{Mmap, MmapMut, MmapOptions};
-
-    #[test]
-    fn map_file() {
-        let expected_len = 128;
-        let tempdir = tempdir::TempDir::new("mmap").unwrap();
-        let path = tempdir.path().join("mmap");
-
-        let file = OpenOptions::new()
-            .read(true)
-            .write(true)
-            .create(true)
-            .open(&path)
-            .unwrap();
-
-        file.set_len(expected_len as u64).unwrap();
-
-        let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
-        let len = mmap.len();
-        assert_eq!(expected_len, len);
-
-        let zeros = vec![0; len];
-        let incr: Vec<u8> = (0..len as u8).collect();
-
-        // check that the mmap is empty
-        assert_eq!(&zeros[..], &mmap[..]);
-
-        // write values into the mmap
-        (&mut mmap[..]).write_all(&incr[..]).unwrap();
-
-        // read values back
-        assert_eq!(&incr[..], &mmap[..]);
-    }
-
-    /// Checks that a 0-length file will not be mapped.
-    #[test]
-    fn map_empty_file() {
-        let tempdir = tempdir::TempDir::new("mmap").unwrap();
-        let path = tempdir.path().join("mmap");
-
-        let file = OpenOptions::new()
-            .read(true)
-            .write(true)
-            .create(true)
-            .open(&path)
-            .unwrap();
-        let mmap = unsafe { Mmap::map(&file) };
-        assert!(mmap.is_err());
-    }
-
-    #[test]
-    fn map_anon() {
-        let expected_len = 128;
-        let mut mmap = MmapMut::map_anon(expected_len).unwrap();
-        let len = mmap.len();
-        assert_eq!(expected_len, len);
-
-        let zeros = vec![0; len];
-        let incr: Vec<u8> = (0..len as u8).collect();
-
-        // check that the mmap is empty
-        assert_eq!(&zeros[..], &mmap[..]);
-
-        // write values into the mmap
-        (&mut mmap[..]).write_all(&incr[..]).unwrap();
-
-        // read values back
-        assert_eq!(&incr[..], &mmap[..]);
-    }
-
-    #[test]
-    fn map_anon_zero_len() {
-        assert!(MmapOptions::new().map_anon().is_err())
-    }
-
-    #[test]
-    fn file_write() {
-        let tempdir = tempdir::TempDir::new("mmap").unwrap();
-        let path = tempdir.path().join("mmap");
-
-        let mut file = OpenOptions::new()
-            .read(true)
-            .write(true)
-            .create(true)
-            .open(&path)
-            .unwrap();
-        file.set_len(128).unwrap();
-
-        let write = b"abc123";
-        let mut read = [0u8; 6];
-
-        let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
-        (&mut mmap[..]).write_all(write).unwrap();
-        mmap.flush().unwrap();
-
-        file.read_exact(&mut read).unwrap();
-        assert_eq!(write, &read);
-    }
-
-    #[test]
-    fn flush_range() {
-        let tempdir = tempdir::TempDir::new("mmap").unwrap();
-        let path = tempdir.path().join("mmap");
-
-        let file = OpenOptions::new()
-            .read(true)
-            .write(true)
-            .create(true)
-            .open(&path)
-            .unwrap();
-        file.set_len(128).unwrap();
-        let write = b"abc123";
-
-        let mut mmap = unsafe {
-            MmapOptions::new()
-                .offset(2)
-                .len(write.len())
-                .map_mut(&file)
-                .unwrap()
-        };
-        (&mut mmap[..]).write_all(write).unwrap();
-        mmap.flush_async_range(0, write.len()).unwrap();
-        mmap.flush_range(0, write.len()).unwrap();
-    }
-
-    #[test]
-    fn map_copy() {
-        let tempdir = tempdir::TempDir::new("mmap").unwrap();
-        let path = tempdir.path().join("mmap");
-
-        let mut file = OpenOptions::new()
-            .read(true)
-            .write(true)
-            .create(true)
-            .open(&path)
-            .unwrap();
-        file.set_len(128).unwrap();
-
-        let nulls = b"\0\0\0\0\0\0";
-        let write = b"abc123";
-        let mut read = [0u8; 6];
-
-        let mut mmap = unsafe { MmapOptions::new().map_copy(&file).unwrap() };
-
-        (&mut mmap[..]).write_all(write).unwrap();
-        mmap.flush().unwrap();
-
-        // The mmap contains the write
-        (&mmap[..]).read_exact(&mut read).unwrap();
-        assert_eq!(write, &read);
-
-        // The file does not contain the write
-        file.read_exact(&mut read).unwrap();
-        assert_eq!(nulls, &read);
-
-        // another mmap does not contain the write
-        let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
-        (&mmap2[..]).read_exact(&mut read).unwrap();
-        assert_eq!(nulls, &read);
-    }
-
-    #[test]
-    fn map_copy_read_only() {
-        let tempdir = tempdir::TempDir::new("mmap").unwrap();
-        let path = tempdir.path().join("mmap");
-
-        let file = OpenOptions::new()
-            .read(true)
-            .write(true)
-            .create(true)
-            .open(&path)
-            .unwrap();
-        file.set_len(128).unwrap();
-
-        let nulls = b"\0\0\0\0\0\0";
-        let mut read = [0u8; 6];
-
-        let mmap = unsafe { MmapOptions::new().map_copy_read_only(&file).unwrap() };
-        (&mmap[..]).read_exact(&mut read).unwrap();
-        assert_eq!(nulls, &read);
-
-        let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
-        (&mmap2[..]).read_exact(&mut read).unwrap();
-        assert_eq!(nulls, &read);
-    }
-
-    #[test]
-    fn map_offset() {
-        let tempdir = tempdir::TempDir::new("mmap").unwrap();
-        let path = tempdir.path().join("mmap");
-
-        let file = OpenOptions::new()
-            .read(true)
-            .write(true)
-            .create(true)
-            .open(&path)
-            .unwrap();
-
-        let offset = u32::max_value() as u64 + 2;
-        let len = 5432;
-        file.set_len(offset + len as u64).unwrap();
-
-        // Check inferred length mmap.
-        let mmap = unsafe { MmapOptions::new().offset(offset).map_mut(&file).unwrap() };
-        assert_eq!(len, mmap.len());
-
-        // Check explicit length mmap.
-        let mut mmap = unsafe {
-            MmapOptions::new()
-                .offset(offset)
-                .len(len)
-                .map_mut(&file)
-                .unwrap()
-        };
-        assert_eq!(len, mmap.len());
-
-        let zeros = vec![0; len];
-        let incr: Vec<_> = (0..len).map(|i| i as u8).collect();
-
-        // check that the mmap is empty
-        assert_eq!(&zeros[..], &mmap[..]);
-
-        // write values into the mmap
-        (&mut mmap[..]).write_all(&incr[..]).unwrap();
-
-        // read values back
-        assert_eq!(&incr[..], &mmap[..]);
-    }
-
-    #[test]
-    fn index() {
-        let mut mmap = MmapMut::map_anon(128).unwrap();
-        mmap[0] = 42;
-        assert_eq!(42, mmap[0]);
-    }
-
-    #[test]
-    fn sync_send() {
-        let mmap = MmapMut::map_anon(129).unwrap();
-
-        fn is_sync_send<T>(_val: T)
-        where
-            T: Sync + Send,
-        {
-        }
-
-        is_sync_send(mmap);
-    }
-
-    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-    fn jit_x86(mut mmap: MmapMut) {
-        use std::mem;
-        mmap[0] = 0xB8; // mov eax, 0xAB
-        mmap[1] = 0xAB;
-        mmap[2] = 0x00;
-        mmap[3] = 0x00;
-        mmap[4] = 0x00;
-        mmap[5] = 0xC3; // ret
-
-        let mmap = mmap.make_exec().expect("make_exec");
-
-        let jitfn: extern "C" fn() -> u8 = unsafe { mem::transmute(mmap.as_ptr()) };
-        assert_eq!(jitfn(), 0xab);
-    }
-
-    #[test]
-    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-    fn jit_x86_anon() {
-        jit_x86(MmapMut::map_anon(4096).unwrap());
-    }
-
-    #[test]
-    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-    fn jit_x86_file() {
-        let tempdir = tempdir::TempDir::new("mmap").unwrap();
-        let mut options = OpenOptions::new();
-        #[cfg(windows)]
-        options.access_mode(GENERIC_ALL);
-
-        let file = options
-            .read(true)
-            .write(true)
-            .create(true)
-            .open(&tempdir.path().join("jit_x86"))
-            .expect("open");
-
-        file.set_len(4096).expect("set_len");
-        jit_x86(unsafe { MmapMut::map_mut(&file).expect("map_mut") });
-    }
-
-    #[test]
-    fn mprotect_file() {
-        let tempdir = tempdir::TempDir::new("mmap").unwrap();
-        let path = tempdir.path().join("mmap");
-
-        let mut options = OpenOptions::new();
-        #[cfg(windows)]
-        options.access_mode(GENERIC_ALL);
-
-        let mut file = options
-            .read(true)
-            .write(true)
-            .create(true)
-            .open(&path)
-            .expect("open");
-        file.set_len(256_u64).expect("set_len");
-
-        let mmap = unsafe { MmapMut::map_mut(&file).expect("map_mut") };
-
-        let mmap = mmap.make_read_only().expect("make_read_only");
-        let mut mmap = mmap.make_mut().expect("make_mut");
-
-        let write = b"abc123";
-        let mut read = [0u8; 6];
-
-        (&mut mmap[..]).write_all(write).unwrap();
-        mmap.flush().unwrap();
-
-        // The mmap contains the write
-        (&mmap[..]).read_exact(&mut read).unwrap();
-        assert_eq!(write, &read);
-
-        // The file should contain the write
-        file.read_exact(&mut read).unwrap();
-        assert_eq!(write, &read);
-
-        // another mmap should contain the write
-        let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
-        (&mmap2[..]).read_exact(&mut read).unwrap();
-        assert_eq!(write, &read);
-
-        let mmap = mmap.make_exec().expect("make_exec");
-
-        drop(mmap);
-    }
-
-    #[test]
-    fn mprotect_copy() {
-        let tempdir = tempdir::TempDir::new("mmap").unwrap();
-        let path = tempdir.path().join("mmap");
-
-        let mut options = OpenOptions::new();
-        #[cfg(windows)]
-        options.access_mode(GENERIC_ALL);
-
-        let mut file = options
-            .read(true)
-            .write(true)
-            .create(true)
-            .open(&path)
-            .expect("open");
-        file.set_len(256_u64).expect("set_len");
-
-        let mmap = unsafe { MmapOptions::new().map_copy(&file).expect("map_mut") };
-
-        let mmap = mmap.make_read_only().expect("make_read_only");
-        let mut mmap = mmap.make_mut().expect("make_mut");
-
-        let nulls = b"\0\0\0\0\0\0";
-        let write = b"abc123";
-        let mut read = [0u8; 6];
-
-        (&mut mmap[..]).write_all(write).unwrap();
-        mmap.flush().unwrap();
-
-        // The mmap contains the write
-        (&mmap[..]).read_exact(&mut read).unwrap();
-        assert_eq!(write, &read);
-
-        // The file does not contain the write
-        file.read_exact(&mut read).unwrap();
-        assert_eq!(nulls, &read);
-
-        // another mmap does not contain the write
-        let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
-        (&mmap2[..]).read_exact(&mut read).unwrap();
-        assert_eq!(nulls, &read);
-
-        let mmap = mmap.make_exec().expect("make_exec");
-
-        drop(mmap);
-    }
-
-    #[test]
-    fn mprotect_anon() {
-        let mmap = MmapMut::map_anon(256).expect("map_mut");
-
-        let mmap = mmap.make_read_only().expect("make_read_only");
-        let mmap = mmap.make_mut().expect("make_mut");
-        let mmap = mmap.make_exec().expect("make_exec");
-        drop(mmap);
-    }
-
-    #[test]
-    fn raw() {
-        let tempdir = tempdir::TempDir::new("mmap").unwrap();
-        let path = tempdir.path().join("mmapraw");
-
-        let mut options = OpenOptions::new();
-        let mut file = options
-            .read(true)
-            .write(true)
-            .create(true)
-            .open(&path)
-            .expect("open");
-        file.write_all(b"abc123").unwrap();
-        let mmap = MmapOptions::new().map_raw(&file).unwrap();
-        assert_eq!(mmap.len(), 6);
-        assert!(!mmap.as_ptr().is_null());
-        assert_eq!(unsafe { std::ptr::read(mmap.as_ptr()) }, b'a');
-    }
-}
diff --git a/vendor/memmap2/src/stub.rs b/vendor/memmap2/src/stub.rs
deleted file mode 100644 (file)
index 0825c41..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-use std::fs::File;
-use std::io;
-
-pub struct MmapInner {
-    // Private member to prevent external construction
-    // (might be nice to change the type to ! once that's stable)
-    __: (),
-}
-
-impl MmapInner {
-    fn new() -> io::Result<MmapInner> {
-        Err(io::Error::new(
-            io::ErrorKind::Other,
-            "platform not supported",
-        ))
-    }
-
-    pub fn map(_: usize, _: &File, _: u64) -> io::Result<MmapInner> {
-        MmapInner::new()
-    }
-
-    pub fn map_exec(_: usize, _: &File, _: u64) -> io::Result<MmapInner> {
-        MmapInner::new()
-    }
-
-    pub fn map_mut(_: usize, _: &File, _: u64) -> io::Result<MmapInner> {
-        MmapInner::new()
-    }
-
-    pub fn map_copy(_: usize, _: &File, _: u64) -> io::Result<MmapInner> {
-        MmapInner::new()
-    }
-
-    pub fn map_copy_read_only(_: usize, _: &File, _: u64) -> io::Result<MmapInner> {
-        MmapInner::new()
-    }
-
-    pub fn map_anon(_: usize, _: bool) -> io::Result<MmapInner> {
-        MmapInner::new()
-    }
-
-    pub fn flush(&self, _: usize, _: usize) -> io::Result<()> {
-        unreachable!("self unconstructable");
-    }
-
-    pub fn flush_async(&self, _: usize, _: usize) -> io::Result<()> {
-        unreachable!("self unconstructable");
-    }
-
-    pub fn make_read_only(&mut self) -> io::Result<()> {
-        unreachable!("self unconstructable");
-    }
-
-    pub fn make_exec(&mut self) -> io::Result<()> {
-        unreachable!("self unconstructable");
-    }
-
-    pub fn make_mut(&mut self) -> io::Result<()> {
-        unreachable!("self unconstructable");
-    }
-
-    #[inline]
-    pub fn ptr(&self) -> *const u8 {
-        unreachable!("self unconstructable");
-    }
-
-    #[inline]
-    pub fn mut_ptr(&mut self) -> *mut u8 {
-        unreachable!("self unconstructable");
-    }
-
-    #[inline]
-    pub fn len(&self) -> usize {
-        unreachable!("self unconstructable");
-    }
-}
diff --git a/vendor/memmap2/src/unix.rs b/vendor/memmap2/src/unix.rs
deleted file mode 100644 (file)
index 2d45e68..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-extern crate libc;
-
-use std::fs::File;
-use std::os::unix::io::{AsRawFd, RawFd};
-use std::{io, ptr};
-
-#[cfg(any(
-    all(target_os = "linux", not(target_arch = "mips")),
-    target_os = "freebsd",
-    target_os = "android"
-))]
-const MAP_STACK: libc::c_int = libc::MAP_STACK;
-
-#[cfg(not(any(
-    all(target_os = "linux", not(target_arch = "mips")),
-    target_os = "freebsd",
-    target_os = "android"
-)))]
-const MAP_STACK: libc::c_int = 0;
-
-#[cfg(any(target_os = "linux", target_os = "android"))]
-const MAP_POPULATE: libc::c_int = libc::MAP_POPULATE;
-
-#[cfg(not(any(target_os = "linux", target_os = "android")))]
-const MAP_POPULATE: libc::c_int = 0;
-
-pub struct MmapInner {
-    ptr: *mut libc::c_void,
-    len: usize,
-}
-
-impl MmapInner {
-    /// Creates a new `MmapInner`.
-    ///
-    /// This is a thin wrapper around the `mmap` sytem call.
-    fn new(
-        len: usize,
-        prot: libc::c_int,
-        flags: libc::c_int,
-        file: RawFd,
-        offset: u64,
-    ) -> io::Result<MmapInner> {
-        let alignment = offset % page_size() as u64;
-        let aligned_offset = offset - alignment;
-        let aligned_len = len + alignment as usize;
-        if aligned_len == 0 {
-            // Normally the OS would catch this, but it segfaults under QEMU.
-            return Err(io::Error::new(
-                io::ErrorKind::InvalidInput,
-                "memory map must have a non-zero length",
-            ));
-        }
-
-        unsafe {
-            let ptr = libc::mmap(
-                ptr::null_mut(),
-                aligned_len as libc::size_t,
-                prot,
-                flags,
-                file,
-                aligned_offset as libc::off_t,
-            );
-
-            if ptr == libc::MAP_FAILED {
-                Err(io::Error::last_os_error())
-            } else {
-                Ok(MmapInner {
-                    ptr: ptr.offset(alignment as isize),
-                    len,
-                })
-            }
-        }
-    }
-
-    pub fn map(len: usize, file: &File, offset: u64, populate: bool) -> io::Result<MmapInner> {
-        let populate = if populate { MAP_POPULATE } else { 0 };
-        MmapInner::new(
-            len,
-            libc::PROT_READ,
-            libc::MAP_SHARED | populate,
-            file.as_raw_fd(),
-            offset,
-        )
-    }
-
-    pub fn map_exec(len: usize, file: &File, offset: u64, populate: bool) -> io::Result<MmapInner> {
-        let populate = if populate { MAP_POPULATE } else { 0 };
-        MmapInner::new(
-            len,
-            libc::PROT_READ | libc::PROT_EXEC,
-            libc::MAP_SHARED | populate,
-            file.as_raw_fd(),
-            offset,
-        )
-    }
-
-    pub fn map_mut(len: usize, file: &File, offset: u64, populate: bool) -> io::Result<MmapInner> {
-        let populate = if populate { MAP_POPULATE } else { 0 };
-        MmapInner::new(
-            len,
-            libc::PROT_READ | libc::PROT_WRITE,
-            libc::MAP_SHARED | populate,
-            file.as_raw_fd(),
-            offset,
-        )
-    }
-
-    pub fn map_copy(len: usize, file: &File, offset: u64, populate: bool) -> io::Result<MmapInner> {
-        let populate = if populate { MAP_POPULATE } else { 0 };
-        MmapInner::new(
-            len,
-            libc::PROT_READ | libc::PROT_WRITE,
-            libc::MAP_PRIVATE | populate,
-            file.as_raw_fd(),
-            offset,
-        )
-    }
-
-    pub fn map_copy_read_only(
-        len: usize,
-        file: &File,
-        offset: u64,
-        populate: bool,
-    ) -> io::Result<MmapInner> {
-        let populate = if populate { MAP_POPULATE } else { 0 };
-        MmapInner::new(
-            len,
-            libc::PROT_READ,
-            libc::MAP_PRIVATE | populate,
-            file.as_raw_fd(),
-            offset,
-        )
-    }
-
-    /// Open an anonymous memory map.
-    pub fn map_anon(len: usize, stack: bool) -> io::Result<MmapInner> {
-        let stack = if stack { MAP_STACK } else { 0 };
-        MmapInner::new(
-            len,
-            libc::PROT_READ | libc::PROT_WRITE,
-            libc::MAP_PRIVATE | libc::MAP_ANON | stack,
-            -1,
-            0,
-        )
-    }
-
-    pub fn flush(&self, offset: usize, len: usize) -> io::Result<()> {
-        let alignment = (self.ptr as usize + offset) % page_size();
-        let offset = offset as isize - alignment as isize;
-        let len = len + alignment;
-        let result =
-            unsafe { libc::msync(self.ptr.offset(offset), len as libc::size_t, libc::MS_SYNC) };
-        if result == 0 {
-            Ok(())
-        } else {
-            Err(io::Error::last_os_error())
-        }
-    }
-
-    pub fn flush_async(&self, offset: usize, len: usize) -> io::Result<()> {
-        let alignment = (self.ptr as usize + offset) % page_size();
-        let offset = offset as isize - alignment as isize;
-        let len = len + alignment;
-        let result =
-            unsafe { libc::msync(self.ptr.offset(offset), len as libc::size_t, libc::MS_ASYNC) };
-        if result == 0 {
-            Ok(())
-        } else {
-            Err(io::Error::last_os_error())
-        }
-    }
-
-    fn mprotect(&mut self, prot: libc::c_int) -> io::Result<()> {
-        unsafe {
-            let alignment = self.ptr as usize % page_size();
-            let ptr = self.ptr.offset(-(alignment as isize));
-            let len = self.len + alignment;
-            if libc::mprotect(ptr, len, prot) == 0 {
-                Ok(())
-            } else {
-                Err(io::Error::last_os_error())
-            }
-        }
-    }
-
-    pub fn make_read_only(&mut self) -> io::Result<()> {
-        self.mprotect(libc::PROT_READ)
-    }
-
-    pub fn make_exec(&mut self) -> io::Result<()> {
-        self.mprotect(libc::PROT_READ | libc::PROT_EXEC)
-    }
-
-    pub fn make_mut(&mut self) -> io::Result<()> {
-        self.mprotect(libc::PROT_READ | libc::PROT_WRITE)
-    }
-
-    #[inline]
-    pub fn ptr(&self) -> *const u8 {
-        self.ptr as *const u8
-    }
-
-    #[inline]
-    pub fn mut_ptr(&mut self) -> *mut u8 {
-        self.ptr as *mut u8
-    }
-
-    #[inline]
-    pub fn len(&self) -> usize {
-        self.len
-    }
-}
-
-impl Drop for MmapInner {
-    fn drop(&mut self) {
-        let alignment = self.ptr as usize % page_size();
-        unsafe {
-            assert!(
-                libc::munmap(
-                    self.ptr.offset(-(alignment as isize)),
-                    (self.len + alignment) as libc::size_t
-                ) == 0,
-                "unable to unmap mmap: {}",
-                io::Error::last_os_error()
-            );
-        }
-    }
-}
-
-unsafe impl Sync for MmapInner {}
-unsafe impl Send for MmapInner {}
-
-fn page_size() -> usize {
-    unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
-}
diff --git a/vendor/memmap2/src/windows.rs b/vendor/memmap2/src/windows.rs
deleted file mode 100644 (file)
index df8d479..0000000
+++ /dev/null
@@ -1,436 +0,0 @@
-#![allow(non_camel_case_types)]
-#![allow(non_snake_case)]
-
-use std::fs::File;
-use std::os::raw::c_void;
-use std::os::windows::io::{AsRawHandle, RawHandle};
-use std::{io, mem, ptr};
-
-type BOOL = i32;
-type WORD = u16;
-type DWORD = u32;
-type WCHAR = u16;
-type HANDLE = *mut c_void;
-type LPVOID = *mut c_void;
-type LPCVOID = *const c_void;
-type ULONG_PTR = usize;
-type SIZE_T = ULONG_PTR;
-type LPCWSTR = *const WCHAR;
-type PDWORD = *mut DWORD;
-type DWORD_PTR = ULONG_PTR;
-type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES;
-type LPSYSTEM_INFO = *mut SYSTEM_INFO;
-
-const INVALID_HANDLE_VALUE: HANDLE = -1isize as HANDLE;
-
-const STANDARD_RIGHTS_REQUIRED: DWORD = 0x000F0000;
-
-const SECTION_QUERY: DWORD = 0x0001;
-const SECTION_MAP_WRITE: DWORD = 0x0002;
-const SECTION_MAP_READ: DWORD = 0x0004;
-const SECTION_MAP_EXECUTE: DWORD = 0x0008;
-const SECTION_EXTEND_SIZE: DWORD = 0x0010;
-const SECTION_MAP_EXECUTE_EXPLICIT: DWORD = 0x0020;
-const SECTION_ALL_ACCESS: DWORD = STANDARD_RIGHTS_REQUIRED
-    | SECTION_QUERY
-    | SECTION_MAP_WRITE
-    | SECTION_MAP_READ
-    | SECTION_MAP_EXECUTE
-    | SECTION_EXTEND_SIZE;
-
-const PAGE_READONLY: DWORD = 0x02;
-const PAGE_READWRITE: DWORD = 0x04;
-const PAGE_WRITECOPY: DWORD = 0x08;
-const PAGE_EXECUTE_READ: DWORD = 0x20;
-const PAGE_EXECUTE_READWRITE: DWORD = 0x40;
-const PAGE_EXECUTE_WRITECOPY: DWORD = 0x80;
-
-const FILE_MAP_WRITE: DWORD = SECTION_MAP_WRITE;
-const FILE_MAP_READ: DWORD = SECTION_MAP_READ;
-const FILE_MAP_ALL_ACCESS: DWORD = SECTION_ALL_ACCESS;
-const FILE_MAP_EXECUTE: DWORD = SECTION_MAP_EXECUTE_EXPLICIT;
-const FILE_MAP_COPY: DWORD = 0x00000001;
-
-#[repr(C)]
-#[derive(Clone, Copy)]
-struct SECURITY_ATTRIBUTES {
-    nLength: DWORD,
-    lpSecurityDescriptor: LPVOID,
-    bInheritHandle: BOOL,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy)]
-struct SYSTEM_INFO_u_s {
-    wProcessorArchitecture: WORD,
-    wReserved: WORD,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy)]
-struct SYSTEM_INFO_u([u32; 1]);
-
-#[repr(C)]
-#[derive(Clone, Copy)]
-struct SYSTEM_INFO {
-    u: SYSTEM_INFO_u,
-    dwPageSize: DWORD,
-    lpMinimumApplicationAddress: LPVOID,
-    lpMaximumApplicationAddress: LPVOID,
-    dwActiveProcessorMask: DWORD_PTR,
-    dwNumberOfProcessors: DWORD,
-    dwProcessorType: DWORD,
-    dwAllocationGranularity: DWORD,
-    wProcessorLevel: WORD,
-    wProcessorRevision: WORD,
-}
-
-extern "system" {
-    fn CloseHandle(hObject: HANDLE) -> BOOL;
-
-    fn CreateFileMappingW(
-        hFile: HANDLE,
-        lpFileMappingAttributes: LPSECURITY_ATTRIBUTES,
-        flProtect: DWORD,
-        dwMaximumSizeHigh: DWORD,
-        dwMaximumSizeLow: DWORD,
-        lpName: LPCWSTR,
-    ) -> HANDLE;
-
-    fn FlushViewOfFile(lpBaseAddress: LPCVOID, dwNumberOfBytesToFlush: SIZE_T) -> BOOL;
-
-    fn UnmapViewOfFile(lpBaseAddress: LPCVOID) -> BOOL;
-
-    fn MapViewOfFile(
-        hFileMappingObject: HANDLE,
-        dwDesiredAccess: DWORD,
-        dwFileOffsetHigh: DWORD,
-        dwFileOffsetLow: DWORD,
-        dwNumberOfBytesToMap: SIZE_T,
-    ) -> LPVOID;
-
-    fn VirtualProtect(
-        lpAddress: LPVOID,
-        dwSize: SIZE_T,
-        flNewProtect: DWORD,
-        lpflOldProtect: PDWORD,
-    ) -> BOOL;
-
-    fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO);
-}
-
-pub struct MmapInner {
-    file: Option<File>,
-    ptr: *mut c_void,
-    len: usize,
-    copy: bool,
-}
-
-impl MmapInner {
-    /// Creates a new `MmapInner`.
-    ///
-    /// This is a thin wrapper around the `CreateFileMappingW` and `MapViewOfFile` system calls.
-    pub fn new(
-        file: &File,
-        protect: DWORD,
-        access: DWORD,
-        offset: u64,
-        len: usize,
-        copy: bool,
-    ) -> io::Result<MmapInner> {
-        let alignment = offset % allocation_granularity() as u64;
-        let aligned_offset = offset - alignment as u64;
-        let aligned_len = len + alignment as usize;
-
-        unsafe {
-            let handle = CreateFileMappingW(
-                file.as_raw_handle(),
-                ptr::null_mut(),
-                protect,
-                0,
-                0,
-                ptr::null(),
-            );
-            if handle.is_null() {
-                return Err(io::Error::last_os_error());
-            }
-
-            let ptr = MapViewOfFile(
-                handle,
-                access,
-                (aligned_offset >> 16 >> 16) as DWORD,
-                (aligned_offset & 0xffffffff) as DWORD,
-                aligned_len as SIZE_T,
-            );
-            CloseHandle(handle);
-
-            if ptr.is_null() {
-                Err(io::Error::last_os_error())
-            } else {
-                Ok(MmapInner {
-                    file: Some(file.try_clone()?),
-                    ptr: ptr.offset(alignment as isize),
-                    len: len as usize,
-                    copy,
-                })
-            }
-        }
-    }
-
-    pub fn map(len: usize, file: &File, offset: u64, _populate: bool) -> io::Result<MmapInner> {
-        let write = protection_supported(file.as_raw_handle(), PAGE_READWRITE);
-        let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READ);
-        let mut access = FILE_MAP_READ;
-        let protection = match (write, exec) {
-            (true, true) => {
-                access |= FILE_MAP_WRITE | FILE_MAP_EXECUTE;
-                PAGE_EXECUTE_READWRITE
-            }
-            (true, false) => {
-                access |= FILE_MAP_WRITE;
-                PAGE_READWRITE
-            }
-            (false, true) => {
-                access |= FILE_MAP_EXECUTE;
-                PAGE_EXECUTE_READ
-            }
-            (false, false) => PAGE_READONLY,
-        };
-
-        let mut inner = MmapInner::new(file, protection, access, offset, len, false)?;
-        if write || exec {
-            inner.make_read_only()?;
-        }
-        Ok(inner)
-    }
-
-    pub fn map_exec(
-        len: usize,
-        file: &File,
-        offset: u64,
-        _populate: bool,
-    ) -> io::Result<MmapInner> {
-        let write = protection_supported(file.as_raw_handle(), PAGE_READWRITE);
-        let mut access = FILE_MAP_READ | FILE_MAP_EXECUTE;
-        let protection = if write {
-            access |= FILE_MAP_WRITE;
-            PAGE_EXECUTE_READWRITE
-        } else {
-            PAGE_EXECUTE_READ
-        };
-
-        let mut inner = MmapInner::new(file, protection, access, offset, len, false)?;
-        if write {
-            inner.make_exec()?;
-        }
-        Ok(inner)
-    }
-
-    pub fn map_mut(len: usize, file: &File, offset: u64, _populate: bool) -> io::Result<MmapInner> {
-        let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READ);
-        let mut access = FILE_MAP_READ | FILE_MAP_WRITE;
-        let protection = if exec {
-            access |= FILE_MAP_EXECUTE;
-            PAGE_EXECUTE_READWRITE
-        } else {
-            PAGE_READWRITE
-        };
-
-        let mut inner = MmapInner::new(file, protection, access, offset, len, false)?;
-        if exec {
-            inner.make_mut()?;
-        }
-        Ok(inner)
-    }
-
-    pub fn map_copy(
-        len: usize,
-        file: &File,
-        offset: u64,
-        _populate: bool,
-    ) -> io::Result<MmapInner> {
-        let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READWRITE);
-        let mut access = FILE_MAP_COPY;
-        let protection = if exec {
-            access |= FILE_MAP_EXECUTE;
-            PAGE_EXECUTE_WRITECOPY
-        } else {
-            PAGE_WRITECOPY
-        };
-
-        let mut inner = MmapInner::new(file, protection, access, offset, len, true)?;
-        if exec {
-            inner.make_mut()?;
-        }
-        Ok(inner)
-    }
-
-    pub fn map_copy_read_only(
-        len: usize,
-        file: &File,
-        offset: u64,
-        _populate: bool,
-    ) -> io::Result<MmapInner> {
-        let write = protection_supported(file.as_raw_handle(), PAGE_READWRITE);
-        let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READ);
-        let mut access = FILE_MAP_COPY;
-        let protection = if exec {
-            access |= FILE_MAP_EXECUTE;
-            PAGE_EXECUTE_WRITECOPY
-        } else {
-            PAGE_WRITECOPY
-        };
-
-        let mut inner = MmapInner::new(file, protection, access, offset, len, true)?;
-        if write || exec {
-            inner.make_read_only()?;
-        }
-        Ok(inner)
-    }
-
-    pub fn map_anon(len: usize, _stack: bool) -> io::Result<MmapInner> {
-        unsafe {
-            // Create a mapping and view with maximum access permissions, then use `VirtualProtect`
-            // to set the actual `Protection`. This way, we can set more permissive protection later
-            // on.
-            // Also see https://msdn.microsoft.com/en-us/library/windows/desktop/aa366537.aspx
-
-            let handle = CreateFileMappingW(
-                INVALID_HANDLE_VALUE,
-                ptr::null_mut(),
-                PAGE_EXECUTE_READWRITE,
-                (len >> 16 >> 16) as DWORD,
-                (len & 0xffffffff) as DWORD,
-                ptr::null(),
-            );
-            if handle.is_null() {
-                return Err(io::Error::last_os_error());
-            }
-            let access = FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE;
-            let ptr = MapViewOfFile(handle, access, 0, 0, len as SIZE_T);
-            CloseHandle(handle);
-
-            if ptr.is_null() {
-                return Err(io::Error::last_os_error());
-            }
-
-            let mut old = 0;
-            let result = VirtualProtect(ptr, len as SIZE_T, PAGE_READWRITE, &mut old);
-            if result != 0 {
-                Ok(MmapInner {
-                    file: None,
-                    ptr,
-                    len: len as usize,
-                    copy: false,
-                })
-            } else {
-                Err(io::Error::last_os_error())
-            }
-        }
-    }
-
-    pub fn flush(&self, offset: usize, len: usize) -> io::Result<()> {
-        self.flush_async(offset, len)?;
-        if let Some(ref file) = self.file {
-            file.sync_data()?;
-        }
-        Ok(())
-    }
-
-    pub fn flush_async(&self, offset: usize, len: usize) -> io::Result<()> {
-        let result = unsafe { FlushViewOfFile(self.ptr.add(offset), len as SIZE_T) };
-        if result != 0 {
-            Ok(())
-        } else {
-            Err(io::Error::last_os_error())
-        }
-    }
-
-    fn virtual_protect(&mut self, protect: DWORD) -> io::Result<()> {
-        unsafe {
-            let alignment = self.ptr as usize % allocation_granularity();
-            let ptr = self.ptr.offset(-(alignment as isize));
-            let aligned_len = self.len as SIZE_T + alignment as SIZE_T;
-
-            let mut old = 0;
-            let result = VirtualProtect(ptr, aligned_len, protect, &mut old);
-
-            if result != 0 {
-                Ok(())
-            } else {
-                Err(io::Error::last_os_error())
-            }
-        }
-    }
-
-    pub fn make_read_only(&mut self) -> io::Result<()> {
-        self.virtual_protect(PAGE_READONLY)
-    }
-
-    pub fn make_exec(&mut self) -> io::Result<()> {
-        if self.copy {
-            self.virtual_protect(PAGE_EXECUTE_WRITECOPY)
-        } else {
-            self.virtual_protect(PAGE_EXECUTE_READ)
-        }
-    }
-
-    pub fn make_mut(&mut self) -> io::Result<()> {
-        if self.copy {
-            self.virtual_protect(PAGE_WRITECOPY)
-        } else {
-            self.virtual_protect(PAGE_READWRITE)
-        }
-    }
-
-    #[inline]
-    pub fn ptr(&self) -> *const u8 {
-        self.ptr as *const u8
-    }
-
-    #[inline]
-    pub fn mut_ptr(&mut self) -> *mut u8 {
-        self.ptr as *mut u8
-    }
-
-    #[inline]
-    pub fn len(&self) -> usize {
-        self.len
-    }
-}
-
-impl Drop for MmapInner {
-    fn drop(&mut self) {
-        let alignment = self.ptr as usize % allocation_granularity();
-        unsafe {
-            let ptr = self.ptr.offset(-(alignment as isize));
-            assert!(
-                UnmapViewOfFile(ptr) != 0,
-                "unable to unmap mmap: {}",
-                io::Error::last_os_error()
-            );
-        }
-    }
-}
-
-unsafe impl Sync for MmapInner {}
-unsafe impl Send for MmapInner {}
-
-fn protection_supported(handle: RawHandle, protection: DWORD) -> bool {
-    unsafe {
-        let handle = CreateFileMappingW(handle, ptr::null_mut(), protection, 0, 0, ptr::null());
-        if handle.is_null() {
-            return false;
-        }
-        CloseHandle(handle);
-        true
-    }
-}
-
-fn allocation_granularity() -> usize {
-    unsafe {
-        let mut info = mem::zeroed();
-        GetSystemInfo(&mut info);
-        info.dwAllocationGranularity as usize
-    }
-}
index 7732a7dba78ecbaddcc959dcfdf5d5dd57094de4..135a6295d0724273861d28a9bc774bd777897ac1 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.toml":"bf0e4a51897e9586cffa4897f69bf7caee769cc9b0292f3dd7ebd4fd5ddcb8f3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"68f533703554b9130ea902776bd9eb20d1a2d32b213ebadebcd49ed0f1ef9728","RELEASES.md":"658b382f2358d6f6733021ecfdcc1fc1faf89d7106e0f72d0f3b34d35442d71b","benches/average.rs":"2a30b4ccd8ece8663d17583ae2e3623e654b5f401babef90f1634722824e6c2b","benches/gcd.rs":"9b5c0ae8ccd6c7fc8f8384fb351d10cfdd0be5fbea9365f9ea925d8915b015bf","benches/roots.rs":"79b4ab2d8fe7bbf43fe65314d2e1bc206165bc4cb34b3ceaa899f9ea7af31c09","build.rs":"575b157527243fe355a7c8d7d874a1f790c3fb0177beba9032076a7803c5b9dd","src/average.rs":"a66cf6a49f893e60697c17b2540258e69daa15ab97d8d444c6f2e8cac2f01ae9","src/lib.rs":"bf0ce9a09f92f606ca038288cde7a29670ccca480d42ec97e88f3c56b117e33c","src/roots.rs":"2a9b908bd3666b5cffc58c1b37d329e46ed02f71ad6d5deea1e8440c10660e1a","tests/average.rs":"5f26a31be042626e9af66f7b751798621561fa090da48b1ec5ab63e388288a91","tests/roots.rs":"a0caa4142899ec8cb806a7a0d3410c39d50de97cceadc4c2ceca707be91b1ddd"},"package":"d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"}
\ No newline at end of file
+{"files":{"Cargo.toml":"df725a7c5780368b03dbe14ac170989ddd987e2e3c8a69bfb47d34025e0e06ec","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"c49fdda3780903fa8c17bb5811ea3029e271e9e79a8f6c59aa3b2468eb9b203f","RELEASES.md":"756843fa25e29f642367b6b3fc161ce34a72d01ae0fb67d5531a280245d287c8","benches/average.rs":"2a30b4ccd8ece8663d17583ae2e3623e654b5f401babef90f1634722824e6c2b","benches/gcd.rs":"9b5c0ae8ccd6c7fc8f8384fb351d10cfdd0be5fbea9365f9ea925d8915b015bf","benches/roots.rs":"79b4ab2d8fe7bbf43fe65314d2e1bc206165bc4cb34b3ceaa899f9ea7af31c09","build.rs":"b4b2d0df90ca7570a339ca4d84a72e4ef00d9dced8927350424e666790c752d7","src/average.rs":"a66cf6a49f893e60697c17b2540258e69daa15ab97d8d444c6f2e8cac2f01ae9","src/lib.rs":"bf0ce9a09f92f606ca038288cde7a29670ccca480d42ec97e88f3c56b117e33c","src/roots.rs":"2a9b908bd3666b5cffc58c1b37d329e46ed02f71ad6d5deea1e8440c10660e1a","tests/average.rs":"5f26a31be042626e9af66f7b751798621561fa090da48b1ec5ab63e388288a91","tests/roots.rs":"a0caa4142899ec8cb806a7a0d3410c39d50de97cceadc4c2ceca707be91b1ddd"},"package":"8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"}
\ No newline at end of file
index 8f72e395981c2a77e7d1df85b0195d0a981a25dc..39d70f78905bdedc31ef2109377f33f304cca087 100644 (file)
@@ -12,7 +12,7 @@
 
 [package]
 name = "num-integer"
-version = "0.1.44"
+version = "0.1.43"
 authors = ["The Rust Project Developers"]
 build = "build.rs"
 exclude = ["/bors.toml", "/ci/*", "/.github/*"]
@@ -22,7 +22,7 @@ documentation = "https://docs.rs/num-integer"
 readme = "README.md"
 keywords = ["mathematics", "numerics"]
 categories = ["algorithms", "science", "no-std"]
-license = "MIT OR Apache-2.0"
+license = "MIT/Apache-2.0"
 repository = "https://github.com/rust-num/num-integer"
 [package.metadata.docs.rs]
 features = ["std"]
index 5f638cd0f42bd5289a44531484c57a09e32976ff..249d5f046170346640748a3d3ae43ea8ffce187a 100644 (file)
@@ -40,6 +40,7 @@ Implementations for `i128` and `u128` are only available with Rust 1.26 and
 later.  The build script automatically detects this, but you can make it
 mandatory by enabling the `i128` crate feature.
 
+
 ## Releases
 
 Release notes are available in [RELEASES.md](RELEASES.md).
@@ -47,18 +48,3 @@ Release notes are available in [RELEASES.md](RELEASES.md).
 ## Compatibility
 
 The `num-integer` crate is tested for rustc 1.8 and greater.
-
-## License
-
-Licensed under either of
-
- * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
- * [MIT license](http://opensource.org/licenses/MIT)
-
-at your option.
-
-### Contribution
-
-Unless you explicitly state otherwise, any contribution intentionally submitted
-for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
-dual licensed as above, without any additional terms or conditions.
index 05be073c35bd342de88a1367de673a0a71180550..727369661e5821ac658bee39b64e4954a8bb37d3 100644 (file)
@@ -1,13 +1,3 @@
-# Release 0.1.44 (2020-10-29)
-
-- [The "i128" feature now bypasses compiler probing][35]. The build script
-  used to probe anyway and panic if requested support wasn't found, but
-  sometimes this ran into bad corner cases with `autocfg`.
-
-**Contributors**: @cuviper
-
-[35]: https://github.com/rust-num/num-integer/pull/35
-
 # Release 0.1.43 (2020-06-11)
 
 - [The new `Average` trait][31] computes fast integer averages, rounded up or
index 37c985766a38418067bd900f7d39d9af9c7b8c34..e483c15fd7f68536573d1b44bf9c8c7e2b568448 100644 (file)
@@ -3,10 +3,11 @@ extern crate autocfg;
 use std::env;
 
 fn main() {
-    // If the "i128" feature is explicity requested, don't bother probing for it.
-    // It will still cause a build error if that was set improperly.
-    if env::var_os("CARGO_FEATURE_I128").is_some() || autocfg::new().probe_type("i128") {
-        autocfg::emit("has_i128");
+    let ac = autocfg::new();
+    if ac.probe_type("i128") {
+        println!("cargo:rustc-cfg=has_i128");
+    } else if env::var_os("CARGO_FEATURE_I128").is_some() {
+        panic!("i128 support was not detected!");
     }
 
     autocfg::rerun_path("build.rs");
index 01ee2a6feca78edb42a8f6b97c194b7565939bff..79d9eed9b6e0fbcd66376968615b604fd712fb3e 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.toml":"25ae881cd00d94ea9f9cb7844f32e3e58871fc9e45769ead9820d8d40c342ddb","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"dd03422a366071c147d9dec73f01ba8299ccf963a0b038eb85520908d9cd028c","RELEASES.md":"8be8fef421245ea7d9e8a4ab89056307095bfbc9730ca175a75968e6d01b68e4","build.rs":"14cb861026b2493f7b39e0f72ced0ccb95c9a5fd0bdce3158f23a27dac7577e8","src/bounds.rs":"4fbc6bf3550e4da7ef55c9eb96466c6e0aee7f7542d7c85cfd742f16e3b4729f","src/cast.rs":"8c8384dcdfaf926b9331399d528278fc73851f8b5e1105dee343f4f19557e932","src/float.rs":"73cc27228e7578d537c00b9b46e124e365c569a53a7e160fe0d1ad1dacf54fc8","src/identities.rs":"5b6238ebd52e1fadd5b405bc40ad81e45346bcb1c4b46cf1f0496a30be7c9bc4","src/int.rs":"c6e042ac4614529f07b0009271a6b97378451d6d3998e1dc407e76f9a050aa2d","src/lib.rs":"5ff4c0694c7db0538fdca2eb8290ecca4a05e0357607dd4bd078b2b762241094","src/macros.rs":"b589a98c2468ca98131c641a058601964c4e82d75129b1c16fdc17aca8779eca","src/ops/checked.rs":"b6dfae21fe1a5ce41e92074c57d204284975ec56d45e63cac5f0136b8c3643b4","src/ops/inv.rs":"dd80b9bd48d815f17855a25842287942317fa49d1fdcdd655b61bd20ef927cda","src/ops/mod.rs":"fd33030d6e5bd50b9797112b63d14e49ce53a61dd9cc88205c942fa79cb18cf5","src/ops/mul_add.rs":"368bdebb40b16f3b4b85cf50235954268ff601ec7a458a3a83fe433f47f86f6d","src/ops/overflowing.rs":"1b92882a5a738ea4cafdb0971101dc438be9043f540e1246f58f7c9ecf6348dc","src/ops/saturating.rs":"6fb4b2a2c78d9202152a84586d7b068444b78d3caed4b293980832672a234d4b","src/ops/wrapping.rs":"0acf88c0e5fc81a3c6790b31986ab9be5b16c720c9e27461fe5d69b710ffcaba","src/pow.rs":"9f78cb9c4d5987b59e16f4141723a33ff689781cc352f357b0cc0111d22cde3a","src/real.rs":"b5115bb2cfb752a59426bb3fcbabf9cff15521a00a3f8b5ef4dfc0b0b31bb1f4","src/sign.rs":"83562caa3501c6873558eb64c9e3bfe25b4b20d38562a7aa7cc9adafcb3ff037","tests/cast.rs":"0a41785611b3909ecb4a88d6d5264a85564f6de8fbfc761436d3c8baafc8e3d0"},"package":"9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"}
\ No newline at end of file
+{"files":{"Cargo.toml":"2dba1df8f54451f64f9e009cfe450da952b776e7ef501e7ac486a3b8777ef5a8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"198b40fa52bedfc43a9d77f6e66b53f3772550a4c1baf1140d72f44c1c8787c5","RELEASES.md":"a35240d247d49d53a59c1a9ffb17755746c01f06d7e759b2b26b2c15076bbd8c","build.rs":"8be12f3d765000d72bae7604e9e129c830dcfd5dea8d4541eccc81f2aa8d5beb","src/bounds.rs":"4fbc6bf3550e4da7ef55c9eb96466c6e0aee7f7542d7c85cfd742f16e3b4729f","src/cast.rs":"78adc1d0c015138bc96c18d75972b57ad5e9bc627070af8b7cde7e0613902652","src/float.rs":"73cc27228e7578d537c00b9b46e124e365c569a53a7e160fe0d1ad1dacf54fc8","src/identities.rs":"5b6238ebd52e1fadd5b405bc40ad81e45346bcb1c4b46cf1f0496a30be7c9bc4","src/int.rs":"c6e042ac4614529f07b0009271a6b97378451d6d3998e1dc407e76f9a050aa2d","src/lib.rs":"4a48c6674e95d77361da4578b4659b5119bdaf9d31b1add6cb1a6701fbc17c93","src/macros.rs":"b589a98c2468ca98131c641a058601964c4e82d75129b1c16fdc17aca8779eca","src/ops/checked.rs":"b6dfae21fe1a5ce41e92074c57d204284975ec56d45e63cac5f0136b8c3643b4","src/ops/inv.rs":"dd80b9bd48d815f17855a25842287942317fa49d1fdcdd655b61bd20ef927cda","src/ops/mod.rs":"036b2a1900dc8e7295a91060e660184b2bd98f33b5db81a62b08cf8d3df726cf","src/ops/mul_add.rs":"368bdebb40b16f3b4b85cf50235954268ff601ec7a458a3a83fe433f47f86f6d","src/ops/saturating.rs":"6fb4b2a2c78d9202152a84586d7b068444b78d3caed4b293980832672a234d4b","src/ops/wrapping.rs":"0acf88c0e5fc81a3c6790b31986ab9be5b16c720c9e27461fe5d69b710ffcaba","src/pow.rs":"9f78cb9c4d5987b59e16f4141723a33ff689781cc352f357b0cc0111d22cde3a","src/real.rs":"b5115bb2cfb752a59426bb3fcbabf9cff15521a00a3f8b5ef4dfc0b0b31bb1f4","src/sign.rs":"81b1116300b5787546852d9d04f0375fa24342f85c34f5bc1ce5360b53fa411a","tests/cast.rs":"2c4b4f2185ec0d687e1bde292731dbc5efec527ab393478b5adf26f6e1352231"},"package":"ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"}
\ No newline at end of file
index 685a784c0fdb6cff8cd1602b7db3d739f03a6201..30e0dd317c55cb0531cb0ff34516945160f7a2eb 100644 (file)
@@ -12,7 +12,7 @@
 
 [package]
 name = "num-traits"
-version = "0.2.14"
+version = "0.2.12"
 authors = ["The Rust Project Developers"]
 build = "build.rs"
 exclude = ["/bors.toml", "/ci/*", "/.github/*"]
@@ -22,7 +22,7 @@ documentation = "https://docs.rs/num-traits"
 readme = "README.md"
 keywords = ["mathematics", "numerics"]
 categories = ["algorithms", "science", "no-std"]
-license = "MIT OR Apache-2.0"
+license = "MIT/Apache-2.0"
 repository = "https://github.com/rust-num/num-traits"
 [package.metadata.docs.rs]
 features = ["std"]
index 1ee1e1e9d85b78bde529e7acd450c900beda7824..114c04430be4a01990255e3e6370b2cd04380972 100644 (file)
@@ -52,18 +52,3 @@ Release notes are available in [RELEASES.md](RELEASES.md).
 ## Compatibility
 
 The `num-traits` crate is tested for rustc 1.8 and greater.
-
-## License
-
-Licensed under either of
-
- * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
- * [MIT license](http://opensource.org/licenses/MIT)
-
-at your option.
-
-### Contribution
-
-Unless you explicitly state otherwise, any contribution intentionally submitted
-for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
-dual licensed as above, without any additional terms or conditions.
index 94449d694a801c7381b36ad2798ea4ca668136ec..75a74f915dfadc47fd30effcee048b3a278b55ba 100644 (file)
@@ -1,30 +1,3 @@
-# Release 0.2.14 (2020-10-29)
-
-- Clarify the license specification as "MIT OR Apache-2.0".
-
-**Contributors**: @cuviper
-
-# Release 0.2.13 (2020-10-29)
-
-- [The new `OverflowingAdd`, `OverflowingSub`, and `OverflowingMul` traits][180]
-  return a tuple with the operation result and a `bool` indicating overflow.
-- [The "i128" feature now overrides compiler probes for that support][185].
-  This may fix scenarios where `autocfg` probing doesn't work properly.
-- [Casts from large `f64` values to `f32` now saturate to infinity][186]. They
-  previously returned `None` because that was once thought to be undefined
-  behavior, but [rust#15536] resolved that such casts are fine.
-- [`Num::from_str_radix` documents requirements for radix support][192], which
-  are now more relaxed than previously implied. It is suggested to accept at
-  least `2..=36` without panicking, but `Err` may be returned otherwise.
-
-**Contributors**: @cuviper, @Enet4, @KaczuH, @martin-t, @newpavlov
-
-[180]: https://github.com/rust-num/num-traits/pull/180
-[185]: https://github.com/rust-num/num-traits/pull/185
-[186]: https://github.com/rust-num/num-traits/pull/186
-[192]: https://github.com/rust-num/num-traits/issues/192
-[rust#15536]: https://github.com/rust-lang/rust/issues/15536
-
 # Release 0.2.12 (2020-06-11)
 
 - [The new `WrappingNeg` trait][153] will wrap the result if it exceeds the
index 816ddadd721196a1c9838daa01e31c9844fc9046..891fa09b199e64e35b07ba4c933767f1e42ba7e1 100644 (file)
@@ -4,13 +4,11 @@ use std::env;
 
 fn main() {
     let ac = autocfg::new();
-
-    // If the "i128" feature is explicity requested, don't bother probing for it.
-    // It will still cause a build error if that was set improperly.
-    if env::var_os("CARGO_FEATURE_I128").is_some() || ac.probe_type("i128") {
-        autocfg::emit("has_i128");
+    if ac.probe_type("i128") {
+        println!("cargo:rustc-cfg=has_i128");
+    } else if env::var_os("CARGO_FEATURE_I128").is_some() {
+        panic!("i128 support was not detected!");
     }
-
     ac.emit_expression_cfg(
         "unsafe { 1f64.to_int_unchecked::<i32>() }",
         "has_to_int_unchecked",
index d38c338156b19bc8c218e2a55fcb88a611047ad0..b33f1a19f40b36f7d03b98da1d1062ef8bd0a730 100644 (file)
@@ -6,16 +6,9 @@ use core::{i128, u128};
 use core::{i16, i32, i64, i8, isize};
 use core::{u16, u32, u64, u8, usize};
 
+use float::FloatCore;
+
 /// A generic trait for converting a value to a number.
-///
-/// A value can be represented by the target type when it lies within
-/// the range of scalars supported by the target type.
-/// For example, a negative integer cannot be represented by an unsigned
-/// integer type, and an `i64` with a very high magnitude might not be
-/// convertible to an `i32`.
-/// On the other hand, conversions with possible precision loss or truncation
-/// are admitted, like an `f32` with a decimal part to an integer type, or
-/// even a large `f64` saturating to `f32` infinity.
 pub trait ToPrimitive {
     /// Converts the value of `self` to an `isize`. If the value cannot be
     /// represented by an `isize`, then `None` is returned.
@@ -101,7 +94,7 @@ pub trait ToPrimitive {
     ///
     /// This method is only available with feature `i128` enabled on Rust >= 1.26.
     ///
-    /// The default implementation converts through `to_u64()`. Types implementing
+    /// The default implementation converts through `to_u64()`.  Types implementing
     /// this trait should override this method if they can represent a greater range.
     #[inline]
     #[cfg(has_i128)]
@@ -109,21 +102,15 @@ pub trait ToPrimitive {
         self.to_u64().map(From::from)
     }
 
-    /// Converts the value of `self` to an `f32`. Overflows may map to positive
-    /// or negative inifinity, otherwise `None` is returned if the value cannot
-    /// be represented by an `f32`.
+    /// Converts the value of `self` to an `f32`. If the value cannot be
+    /// represented by an `f32`, then `None` is returned.
     #[inline]
     fn to_f32(&self) -> Option<f32> {
         self.to_f64().as_ref().and_then(ToPrimitive::to_f32)
     }
 
-    /// Converts the value of `self` to an `f64`. Overflows may map to positive
-    /// or negative inifinity, otherwise `None` is returned if the value cannot
-    /// be represented by an `f64`.
-    ///
-    /// The default implementation tries to convert through `to_i64()`, and
-    /// failing that through `to_u64()`. Types implementing this trait should
-    /// override this method if they can represent a greater range.
+    /// Converts the value of `self` to an `f64`. If the value cannot be
+    /// represented by an `f64`, then `None` is returned.
     #[inline]
     fn to_f64(&self) -> Option<f64> {
         match self.to_i64() {
@@ -284,8 +271,14 @@ macro_rules! impl_to_primitive_float_to_float {
     ($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
         #[inline]
         fn $method(&self) -> Option<$DstT> {
-            // We can safely cast all values, whether NaN, +-inf, or finite.
-            // Finite values that are reducing size may saturate to +-inf.
+            // Only finite values that are reducing size need to worry about overflow.
+            if size_of::<$SrcT>() > size_of::<$DstT>() && FloatCore::is_finite(*self) {
+                let n = *self as f64;
+                if n < $DstT::MIN as f64 || n > $DstT::MAX as f64 {
+                    return None;
+                }
+            }
+            // We can safely cast NaN, +-inf, and finite values in range.
             Some(*self as $DstT)
         }
     )*}
@@ -399,15 +392,6 @@ impl_to_primitive_float!(f32);
 impl_to_primitive_float!(f64);
 
 /// A generic trait for converting a number to a value.
-///
-/// A value can be represented by the target type when it lies within
-/// the range of scalars supported by the target type.
-/// For example, a negative integer cannot be represented by an unsigned
-/// integer type, and an `i64` with a very high magnitude might not be
-/// convertible to an `i32`.
-/// On the other hand, conversions with possible precision loss or truncation
-/// are admitted, like an `f32` with a decimal part to an integer type, or
-/// even a large `f64` saturating to `f32` infinity.
 pub trait FromPrimitive: Sized {
     /// Converts an `isize` to return an optional value of this type. If the
     /// value cannot be represented by this type, then `None` is returned.
@@ -508,10 +492,6 @@ pub trait FromPrimitive: Sized {
 
     /// Converts a `f64` to return an optional value of this type. If the
     /// value cannot be represented by this type, then `None` is returned.
-    ///
-    /// The default implementation tries to convert through `from_i64()`, and
-    /// failing that through `from_u64()`. Types implementing this trait should
-    /// override this method if they can represent a greater range.
     #[inline]
     fn from_f64(n: f64) -> Option<Self> {
         match n.to_i64() {
@@ -692,15 +672,6 @@ pub trait NumCast: Sized + ToPrimitive {
     /// Creates a number from another value that can be converted into
     /// a primitive via the `ToPrimitive` trait. If the source value cannot be
     /// represented by the target type, then `None` is returned.
-    ///
-    /// A value can be represented by the target type when it lies within
-    /// the range of scalars supported by the target type.
-    /// For example, a negative integer cannot be represented by an unsigned
-    /// integer type, and an `i64` with a very high magnitude might not be
-    /// convertible to an `i32`.
-    /// On the other hand, conversions with possible precision loss or truncation
-    /// are admitted, like an `f32` with a decimal part to an integer type, or
-    /// even a large `f64` saturating to `f32` infinity.
     fn from<T: ToPrimitive>(n: T) -> Option<Self>;
 }
 
@@ -757,16 +728,25 @@ impl<T: NumCast> NumCast for Wrapping<T> {
 ///
 /// # Safety
 ///
-/// **In Rust versions before 1.45.0**, some uses of the `as` operator were not entirely safe.
-/// In particular, it was undefined behavior if
-/// a truncated floating point value could not fit in the target integer
-/// type ([#10184](https://github.com/rust-lang/rust/issues/10184)).
+/// Currently, some uses of the `as` operator are not entirely safe.
+/// In particular, it is undefined behavior if:
+///
+/// - A truncated floating point value cannot fit in the target integer
+///   type ([#10184](https://github.com/rust-lang/rust/issues/10184));
 ///
 /// ```ignore
 /// # use num_traits::AsPrimitive;
 /// let x: u8 = (1.04E+17).as_(); // UB
 /// ```
 ///
+/// - Or a floating point value does not fit in another floating
+///   point type ([#15536](https://github.com/rust-lang/rust/issues/15536)).
+///
+/// ```ignore
+/// # use num_traits::AsPrimitive;
+/// let x: f32 = (1e300f64).as_(); // UB
+/// ```
+///
 pub trait AsPrimitive<T>: 'static + Copy
 where
     T: 'static + Copy,
index a6c202c95eeb4393ed1e222e531ca94879a14011..d9989467eb8f1eeb467f26b552e28707a3a7c63f 100644 (file)
@@ -67,7 +67,7 @@ pub mod sign;
 pub trait Num: PartialEq + Zero + One + NumOps {
     type FromStrRadixErr;
 
-    /// Convert from a string and radix (typically `2..=36`).
+    /// Convert from a string and radix <= 36.
     ///
     /// # Examples
     ///
@@ -80,18 +80,6 @@ pub trait Num: PartialEq + Zero + One + NumOps {
     /// let result = <i32 as Num>::from_str_radix("foo", 10);
     /// assert!(result.is_err());
     /// ```
-    ///
-    /// # Supported radices
-    ///
-    /// The exact range of supported radices is at the discretion of each type implementation. For
-    /// primitive integers, this is implemented by the inherent `from_str_radix` methods in the
-    /// standard library, which **panic** if the radix is not in the range from 2 to 36. The
-    /// implementation in this crate for primitive floats is similar.
-    ///
-    /// For third-party types, it is suggested that implementations should follow suit and at least
-    /// accept `2..=36` without panicking, but an `Err` may be returned for any unsupported radix.
-    /// It's possible that a type might not even support the common radix 10, nor any, if string
-    /// parsing doesn't make sense for that type.
     fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
 }
 
index 73c4f9025985a002170dfcc8ac8c8e3c6995e3f2..fd1695d993823db5fdfd46362c919658c10f51b4 100644 (file)
@@ -1,6 +1,5 @@
 pub mod checked;
 pub mod inv;
 pub mod mul_add;
-pub mod overflowing;
 pub mod saturating;
 pub mod wrapping;
diff --git a/vendor/num-traits/src/ops/overflowing.rs b/vendor/num-traits/src/ops/overflowing.rs
deleted file mode 100644 (file)
index 56118a0..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-use core::ops::{Add, Mul, Sub};
-#[cfg(has_i128)]
-use core::{i128, u128};
-use core::{i16, i32, i64, i8, isize};
-use core::{u16, u32, u64, u8, usize};
-
-macro_rules! overflowing_impl {
-    ($trait_name:ident, $method:ident, $t:ty) => {
-        impl $trait_name for $t {
-            #[inline]
-            fn $method(&self, v: &Self) -> (Self, bool) {
-                <$t>::$method(*self, *v)
-            }
-        }
-    };
-}
-
-/// Performs addition with a flag for overflow.
-pub trait OverflowingAdd: Sized + Add<Self, Output = Self> {
-    /// Returns a tuple of the sum along with a boolean indicating whether an arithmetic overflow would occur.
-    /// If an overflow would have occurred then the wrapped value is returned.
-    fn overflowing_add(&self, v: &Self) -> (Self, bool);
-}
-
-overflowing_impl!(OverflowingAdd, overflowing_add, u8);
-overflowing_impl!(OverflowingAdd, overflowing_add, u16);
-overflowing_impl!(OverflowingAdd, overflowing_add, u32);
-overflowing_impl!(OverflowingAdd, overflowing_add, u64);
-overflowing_impl!(OverflowingAdd, overflowing_add, usize);
-#[cfg(has_i128)]
-overflowing_impl!(OverflowingAdd, overflowing_add, u128);
-
-overflowing_impl!(OverflowingAdd, overflowing_add, i8);
-overflowing_impl!(OverflowingAdd, overflowing_add, i16);
-overflowing_impl!(OverflowingAdd, overflowing_add, i32);
-overflowing_impl!(OverflowingAdd, overflowing_add, i64);
-overflowing_impl!(OverflowingAdd, overflowing_add, isize);
-#[cfg(has_i128)]
-overflowing_impl!(OverflowingAdd, overflowing_add, i128);
-
-/// Performs substraction with a flag for overflow.
-pub trait OverflowingSub: Sized + Sub<Self, Output = Self> {
-    /// Returns a tuple of the difference along with a boolean indicating whether an arithmetic overflow would occur.
-    /// If an overflow would have occurred then the wrapped value is returned.
-    fn overflowing_sub(&self, v: &Self) -> (Self, bool);
-}
-
-overflowing_impl!(OverflowingSub, overflowing_sub, u8);
-overflowing_impl!(OverflowingSub, overflowing_sub, u16);
-overflowing_impl!(OverflowingSub, overflowing_sub, u32);
-overflowing_impl!(OverflowingSub, overflowing_sub, u64);
-overflowing_impl!(OverflowingSub, overflowing_sub, usize);
-#[cfg(has_i128)]
-overflowing_impl!(OverflowingSub, overflowing_sub, u128);
-
-overflowing_impl!(OverflowingSub, overflowing_sub, i8);
-overflowing_impl!(OverflowingSub, overflowing_sub, i16);
-overflowing_impl!(OverflowingSub, overflowing_sub, i32);
-overflowing_impl!(OverflowingSub, overflowing_sub, i64);
-overflowing_impl!(OverflowingSub, overflowing_sub, isize);
-#[cfg(has_i128)]
-overflowing_impl!(OverflowingSub, overflowing_sub, i128);
-
-/// Performs multiplication with a flag for overflow.
-pub trait OverflowingMul: Sized + Mul<Self, Output = Self> {
-    /// Returns a tuple of the product along with a boolean indicating whether an arithmetic overflow would occur.
-    /// If an overflow would have occurred then the wrapped value is returned.
-    fn overflowing_mul(&self, v: &Self) -> (Self, bool);
-}
-
-overflowing_impl!(OverflowingMul, overflowing_mul, u8);
-overflowing_impl!(OverflowingMul, overflowing_mul, u16);
-overflowing_impl!(OverflowingMul, overflowing_mul, u32);
-overflowing_impl!(OverflowingMul, overflowing_mul, u64);
-overflowing_impl!(OverflowingMul, overflowing_mul, usize);
-#[cfg(has_i128)]
-overflowing_impl!(OverflowingMul, overflowing_mul, u128);
-
-overflowing_impl!(OverflowingMul, overflowing_mul, i8);
-overflowing_impl!(OverflowingMul, overflowing_mul, i16);
-overflowing_impl!(OverflowingMul, overflowing_mul, i32);
-overflowing_impl!(OverflowingMul, overflowing_mul, i64);
-overflowing_impl!(OverflowingMul, overflowing_mul, isize);
-#[cfg(has_i128)]
-overflowing_impl!(OverflowingMul, overflowing_mul, i128);
-
-#[test]
-fn test_overflowing_traits() {
-    fn overflowing_add<T: OverflowingAdd>(a: T, b: T) -> (T, bool) {
-        a.overflowing_add(&b)
-    }
-    fn overflowing_sub<T: OverflowingSub>(a: T, b: T) -> (T, bool) {
-        a.overflowing_sub(&b)
-    }
-    fn overflowing_mul<T: OverflowingMul>(a: T, b: T) -> (T, bool) {
-        a.overflowing_mul(&b)
-    }
-    assert_eq!(overflowing_add(5i16, 2), (7, false));
-    assert_eq!(overflowing_add(i16::MAX, 1), (i16::MIN, true));
-    assert_eq!(overflowing_sub(5i16, 2), (3, false));
-    assert_eq!(overflowing_sub(i16::MIN, 1), (i16::MAX, true));
-    assert_eq!(overflowing_mul(5i16, 2), (10, false));
-    assert_eq!(overflowing_mul(1_000_000_000i32, 10), (1410065408, true));
-}
index 5c32071c2395c0afdc913b36c762ed6a918e5a49..26d44c500f4c563252b6eefb97e694a751a14d05 100644 (file)
@@ -213,12 +213,13 @@ fn unsigned_wrapping_is_unsigned() {
     fn require_unsigned<T: Unsigned>(_: &T) {}
     require_unsigned(&Wrapping(42_u32));
 }
-
+/*
 // Commenting this out since it doesn't compile on Rust 1.8,
 // because on this version Wrapping doesn't implement Neg and therefore can't
 // implement Signed.
-// #[test]
-// fn signed_wrapping_is_signed() {
-//     fn require_signed<T: Signed>(_: &T) {}
-//     require_signed(&Wrapping(-42));
-// }
+#[test]
+fn signed_wrapping_is_signed() {
+    fn require_signed<T: Signed>(_: &T) {}
+    require_signed(&Wrapping(-42));
+}
+*/
index 69310d0748703183c875e9e4902b56f48621a828..b3f3108e7ad1276cb5be60f9332f7f706ccd6bbf 100644 (file)
@@ -24,8 +24,7 @@ use core::num::Wrapping;
 #[test]
 fn to_primitive_float() {
     let f32_toolarge = 1e39f64;
-    assert_eq!(f32_toolarge.to_f32(), Some(f32::INFINITY));
-    assert_eq!((-f32_toolarge).to_f32(), Some(f32::NEG_INFINITY));
+    assert_eq!(f32_toolarge.to_f32(), None);
     assert_eq!((f32::MAX as f64).to_f32(), Some(f32::MAX));
     assert_eq!((-f32::MAX as f64).to_f32(), Some(-f32::MAX));
     assert_eq!(f64::INFINITY.to_f32(), Some(f32::INFINITY));
index 654238ed49eac5b04b9203aa079519fb01e060ab..1f76cb1fcc31b0e3b46cb96b89161545c429002c 100644 (file)
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"94e8e5afff5955ce2ecce2e97de75816ce922944cb20ae7810b94295da24cf2d","Cargo.lock":"da126826c98d6b106781a7837a1991cc51ffdbcbe2d53505cd2c8ebc0921f66f","Cargo.toml":"64f12c5d8ec0a1a3a7613adcb936bde7f8d2064e324e5acd401841e117c33e3c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b74dfa0bcee5c420c6b7f67b4b2658f9ab8388c97b8e733975f2cecbdd668a6","README.md":"08ecef6e47fb6709aa631a90280eca666f0375a1cf217b19fc3bc84ce2bbc3c5","clippy.toml":"50fd0cdaae995561b1d688c9410fe99335fc7ac3916a400dafd25ff63f8215f7","examples/ar.rs":"9846b618c70acfcb869895f1e1829a3b3824c04afd685ee7af289c91fcf0e420","examples/dyldcachedump.rs":"d30974ade7acbb13843ab5ffe74e825316f533b4bf7a6431799277d2340aad01","examples/nm.rs":"07b8dd510ad51640ffedba74ef3d05b290922d1a5ccf78237693e527124deb2d","examples/objcopy.rs":"e4e3a080733e877bd8024b3bd98dbf607e3ad9611db4f417a156c0f144f6b663","examples/objdump.rs":"1e0a27b2c3ac4dd85df9fc9a4463644de5f4762b3428e9b0d4f542c7084ff793","examples/objectmap.rs":"d36457d5334551a8d82880847a563ca619e022746e8ef3fd79f3a16193a5dd95","examples/readobj.rs":"87cce6f4a98347107378603ad195ddfd6dc90060439b739509adf77a0b5a7870","src/archive.rs":"7ca11076759d4b87b42657f866b0d2b1dd07d2536b19645da0a5da5dd713b77d","src/common.rs":"dc2c123d9b2173d09c342235dfdff09bf6339e8b781e503f0663b4bb53e2c2bd","src/elf.rs":"3ac9c73c4cc15a67f352168d749394dfebecca9e0a4d1ac02fef5ebff74e0bd7","src/endian.rs":"ceaad1b651627ad9e6218a168f87353ae651f5d76c9f61bc8099dff25007405e","src/lib.rs":"aaedbc362a7d35e3244975cdf66814c0901e9db283ae2c52a6b8b44850ef970c","src/macho.rs":"ef938fbfd5913711493ef4347a1b426b7ee661a2eb2038681552d7d8b7282e7a","src/pe.rs":"fdd11f2ad00276cf6016b230aa77bf20f0ca2ee243950a0a3bb923b92377d569","src/pod.rs":"9737170e72d630486e7677fd70675a78be08c33d005680e0d223bb93167d70e9","src/read/any.rs":"48edd49db782c03bd21644db5c8dca0c81911fc1233639210c5aecfe338613ce","src/read/archive.rs":"8932a671f32879c491b9d4b224c3b1b04185bd7b1d115cfd74be54f61839d428","src/read/coff/comdat.rs":"f4198dcdd2c270c9f1ba9efa30c6fb291913984079a45c02e6b6f57dce2700da","src/read/coff/file.rs":"2dc761a902dfd73700717d1e6016a95786a664187eb5efcc904ca7c3ccbdaa78","src/read/coff/mod.rs":"5eed1c0ca7cf044b3173223b06afacc4961a0515ef2478fffa35641f4ee364ee","src/read/coff/relocation.rs":"a9406980b89a33a16b4fa4f41f01d6db63096c46ff61bb8bd590f86f1d5ed5cf","src/read/coff/section.rs":"fd497c5e6d85634bba426c83ba62cc473cf86431d2ec811b49354a927945322c","src/read/coff/symbol.rs":"1a109b6e150e1515c25184f720167e910b8eed3d9543859ab715ef9d0c18ea8a","src/read/elf/comdat.rs":"340cccdea68c7ed77406ee45c4baa5f179588d77d90bb88b0cd9749d0d725cb1","src/read/elf/compression.rs":"097ff8bdc78d01a1532b11c1c0cae3b35905128c7d98b471de188d46da3ff970","src/read/elf/dynamic.rs":"2454551eb67757622b3d6660bc13ed39341be91f382eb8b1910095f58cf2bae2","src/read/elf/file.rs":"cd472c58f76264ba205b7628c4151dc7dccd2b3a935900bc4bbb6619886aaec3","src/read/elf/mod.rs":"7caed85a153a31b491fefd37d1182b63f0c8fa9764a933b6cc7a9f094602573b","src/read/elf/note.rs":"31c93ef1d1a9a9090fac6ba958a8990b243d1ee6c242212201d83ea11be3294a","src/read/elf/relocation.rs":"3993b2c62211bf58bd6e71fee6eafc560d8c5282f8e691daed9ee407888c2359","src/read/elf/section.rs":"0b8c43e593e862d3f4077f1b0a1ef4b044035a8f30ba5ec96a644facfd255b38","src/read/elf/segment.rs":"b0f2f81de3325bbb0370a2a579d901566f91c9166055f31f762b3351da74db19","src/read/elf/symbol.rs":"3d18909511887635b10b546c8d3dc554688be5a76047f73b99a205e4d9c35bfc","src/read/macho/dyld_cache.rs":"252516c47c5f1a1c5384b02a1a22b2f6ffa5632c9d1575ff2e9d436639d27aae","src/read/macho/fat.rs":"05e84f0a10958ef4e3828f388cd5d2fea95481ea89aeb80b76a2784c4208e4a1","src/read/macho/file.rs":"c88bb84cb131db1c09c02d689008628b7317be9f04d76eb807c78ce65eda1e86","src/read/macho/load_command.rs":"9140c38c92b89cab1a66b4ec0cd2ef52f02d0b572e9466ddfce9a366fc830128","src/read/macho/mod.rs":"23b353da3b7e076c68a067776e6a5b346a746116ac42c2c90bafd95ad54a90b3","src/read/macho/relocation.rs":"77fa3e65ccf5884433c96cdc39c457b8a0c430432e5ff9cad22a8becf13f0183","src/read/macho/section.rs":"59e70336d50f757d8d8daf44f23acca77de87cffcf2d62326e3b17c2ff9f672f","src/read/macho/segment.rs":"659b61a8cb563504f533c390fb901883b72c298f7bea037100a677cc9e4face4","src/read/macho/symbol.rs":"0baff8ee5080f8a7bf26d10428e065b066eb53b9d12f71abf239e32c71266dc5","src/read/mod.rs":"62a9285095acb57a0bf0b2260a0c611f766e4c0739c03065f31683ce274e9b3d","src/read/pe/file.rs":"2aeb0a1392291b20483850513730f7cd2ec6aeb02490973521dfdc4c2d66b0c0","src/read/pe/mod.rs":"05d9f3320596f9e567cbd791b68982d50a31e8d18f60c2c401c4a40eb50f1d94","src/read/pe/section.rs":"fa33839c461da36533a121a1f5e4394f41969c10dd4b3db1afca005f0e1f742b","src/read/read_cache.rs":"ba0030a22d4bac49f40ec3a0beee933733d9e56b3d41a9c243962fcea4862b93","src/read/read_ref.rs":"1cddf62981b69e8828b19ac155750d37d5f701313d2dbcf530a989f645607775","src/read/traits.rs":"5f29ae16bcf078c7089b22d7bd3ca9c6bc2eb637900a3b1cc70f9a45e5f8be09","src/read/util.rs":"2c1fd52b58f9fc16864bc5be0795f7e16f8f56413e11c92289a949c31a31237c","src/read/wasm.rs":"936ac6b218d23d7bb9ca6869f17cd8dafbed80ee0b267254c7a3ffe05bd46948","src/write/coff.rs":"61a180fe3fc15ab3ed965e2da719806142149d9d6cefa034232207f1de36d868","src/write/elf.rs":"73f568045d9c05c6d01b1327a66a47af4ad7f6bcc68b11bfdbd9bf2652cb781a","src/write/macho.rs":"c6e402de0f7069ca2f64c1281666798767401da9fa6a997cfa143fd614f744ba","src/write/mod.rs":"1bbb631b9592cb10feaa75c4a80a0a258555d4d745e0646ff4367aa83805b65f","src/write/string.rs":"920d71223a5a146ef516b6d5fb6d22bc86a7e456da369ae8a4d1ca6b63d59892","src/write/util.rs":"8b87ed680a21458bd3f1775d962fe92d85a2b85510ffd860e132be4928089754","tests/integration.rs":"d491a0ae0d50c3194cd7b81720262f55ccb234251346f188284ce29729823dc2","tests/parse_self.rs":"81b44b2dd1de9a5d8c18d9bd8926156e39fb83931837afa8ca344da0d309aeee","tests/round_trip/bss.rs":"849d69b063fd757fed02219dd81e9d13b82068a2025d2cc5cfd40cf557e31bda","tests/round_trip/comdat.rs":"2e3ef1aef466911646e5cbfe0b1a8c1543530baf8ca6102394519e701a1e2747","tests/round_trip/common.rs":"ced08ff559ca4d343ceef54bb4c581a3405cd96d6a1628ba43b7aab82070800b","tests/round_trip/elf.rs":"a1ff40266998321c75023cf76384f8ad03828c6d487421ea8b7774fce8173039","tests/round_trip/macho.rs":"b23931f506345b26ce3b4908dc2ce02f704603c622d39f5e9e7c8529f2882818","tests/round_trip/mod.rs":"b741ba432fdee2156699743962c64aaf2d1e9629c432e40953ac4d410688ea5a","tests/round_trip/tls.rs":"23a49a1036b9173ece82a3080745930e5925e745280ab38866c9d3c29f463e63"},"package":"f8bc1d42047cf336f0f939c99e97183cf31551bf0f2865a2ec9c8d91fd4ffb5e"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"52a47c66164f368e5a167f1732525583ec574cd7de8be91fac29d52997b1c632","Cargo.lock":"a1190887088da0ebf768d172d97a9c21519fe4adb72860e4c9d3826307a57ce6","Cargo.toml":"2481b73a96029b6409d582b026d901d04f5ef12c12ccb27f3c997fa567ce18a7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b74dfa0bcee5c420c6b7f67b4b2658f9ab8388c97b8e733975f2cecbdd668a6","README.md":"283c8881f81e647191130eea41b94fe877214e492fd35dd02a10c0698aaedcdf","clippy.toml":"50fd0cdaae995561b1d688c9410fe99335fc7ac3916a400dafd25ff63f8215f7","examples/ar.rs":"9846b618c70acfcb869895f1e1829a3b3824c04afd685ee7af289c91fcf0e420","examples/dyldcachedump.rs":"d30974ade7acbb13843ab5ffe74e825316f533b4bf7a6431799277d2340aad01","examples/nm.rs":"07b8dd510ad51640ffedba74ef3d05b290922d1a5ccf78237693e527124deb2d","examples/objcopy.rs":"e4e3a080733e877bd8024b3bd98dbf607e3ad9611db4f417a156c0f144f6b663","examples/objdump.rs":"1e0a27b2c3ac4dd85df9fc9a4463644de5f4762b3428e9b0d4f542c7084ff793","examples/objectmap.rs":"d36457d5334551a8d82880847a563ca619e022746e8ef3fd79f3a16193a5dd95","examples/readobj.rs":"49feba2fd34a6fb76e18763348e6ccf5a0c4ccf3779e5bc622df4d8ed14e82bf","src/archive.rs":"7ca11076759d4b87b42657f866b0d2b1dd07d2536b19645da0a5da5dd713b77d","src/common.rs":"9a16e67c321a6b35d35ce9d0611281f8f30b2c475cde68479d6a0fdd2b997a5e","src/elf.rs":"78df96810cb379e1dd8b4872ab90d2337855fa4d4d98fb09697d0750154dc40b","src/endian.rs":"ceaad1b651627ad9e6218a168f87353ae651f5d76c9f61bc8099dff25007405e","src/lib.rs":"fccca74e1e79d5d4dbb090a0103d91b5a0b4f71983d5e3ee3b139b13a9c7990d","src/macho.rs":"ef938fbfd5913711493ef4347a1b426b7ee661a2eb2038681552d7d8b7282e7a","src/pe.rs":"7a1b57131f43ed01472f4924f37657896880b82b127a153795388eb4577a640a","src/pod.rs":"9643a698e1388ad98d1e9ea074ca5b0b35599a2491a82e67a62ebcdc8cb19218","src/read/any.rs":"696a956935e7f1babb621ff71dec23154ca4bf906a8adfa5c02aac7a50117c69","src/read/archive.rs":"987eaf577ec47f5b4ac4e91c697abad31c00ead02f3241dde4f74ce24a884b20","src/read/coff/comdat.rs":"f4198dcdd2c270c9f1ba9efa30c6fb291913984079a45c02e6b6f57dce2700da","src/read/coff/file.rs":"3b15e43d5db9e3af025cda166dd731a5a10293c8d6a6a6f82e7ff4541a4b04a8","src/read/coff/mod.rs":"5eed1c0ca7cf044b3173223b06afacc4961a0515ef2478fffa35641f4ee364ee","src/read/coff/relocation.rs":"a9406980b89a33a16b4fa4f41f01d6db63096c46ff61bb8bd590f86f1d5ed5cf","src/read/coff/section.rs":"721e4f96c2de16f85192db0ad53ee34745bcbe8d551ad297d4f44ab13205ec06","src/read/coff/symbol.rs":"01a11c8f77c1b80d354d9437439cf4685b99bf254cc9eeadd19da2a394fc3c57","src/read/elf/comdat.rs":"340cccdea68c7ed77406ee45c4baa5f179588d77d90bb88b0cd9749d0d725cb1","src/read/elf/compression.rs":"097ff8bdc78d01a1532b11c1c0cae3b35905128c7d98b471de188d46da3ff970","src/read/elf/dynamic.rs":"2454551eb67757622b3d6660bc13ed39341be91f382eb8b1910095f58cf2bae2","src/read/elf/file.rs":"9d5958552ac3f590249c45795d40d8ffce0d41a6e4d9ae2f38f356ad4e46c05e","src/read/elf/hash.rs":"3a08046c78a6fd79bccfd1a0d4cc113da8d0664164576f290885b51d8110acca","src/read/elf/mod.rs":"98b5bd46778d3c33e9d19dee2d294f61677dec16b28f22aa73340008c241fe09","src/read/elf/note.rs":"33bf89a85bb7927fd0123cd6c2919f0b9b0f8935db1ae7b446b75ea2717a476d","src/read/elf/relocation.rs":"62b27c79964f7b037f4fb0b952afacd14790751828e82b67ed5890f143e2b2dc","src/read/elf/section.rs":"d692093ad195ccd0e4857c2f9c638543aa38a8179180e68d27a1f0784aa5e09a","src/read/elf/segment.rs":"d3cbb86cc9ca6eca93f9c17f36823dae0bd72ab2761f2b784dadd8f5b5c9dd9f","src/read/elf/symbol.rs":"9582039f44e82a3bbf225db12ddab9a3b3d5f4b0536d4125c18bb693da3c6db7","src/read/elf/version.rs":"c665034c90cb17e7bd1a6ba836966534fb2527698979908a704cf3b716c0dbdc","src/read/macho/dyld_cache.rs":"37330ba249226231b2e6ae7de80d60845c2eb7db854fd588c52fc706e13e49b8","src/read/macho/fat.rs":"05e84f0a10958ef4e3828f388cd5d2fea95481ea89aeb80b76a2784c4208e4a1","src/read/macho/file.rs":"c524be5be3447afb5aa9c68673f495de05e652687790397f6bf5617b9beea21a","src/read/macho/load_command.rs":"df976715bbc7699f7fdb8e9d388ba3e96a6d40c6a03b96c2696bd7c19786695a","src/read/macho/mod.rs":"23b353da3b7e076c68a067776e6a5b346a746116ac42c2c90bafd95ad54a90b3","src/read/macho/relocation.rs":"77fa3e65ccf5884433c96cdc39c457b8a0c430432e5ff9cad22a8becf13f0183","src/read/macho/section.rs":"59e70336d50f757d8d8daf44f23acca77de87cffcf2d62326e3b17c2ff9f672f","src/read/macho/segment.rs":"659b61a8cb563504f533c390fb901883b72c298f7bea037100a677cc9e4face4","src/read/macho/symbol.rs":"c0a615079779bf83bc3a6ae6d816f8d853099591f0b72e8646a624955bc5069e","src/read/mod.rs":"18ccc63d7acfc1af561d413738cafb1882368179257d36d2dc2496e21095bf7c","src/read/pe/file.rs":"f17836ac757dfd198323a2df1289b02dbb3ba85f2ceff0fdb7e565d30d555da3","src/read/pe/mod.rs":"05d9f3320596f9e567cbd791b68982d50a31e8d18f60c2c401c4a40eb50f1d94","src/read/pe/section.rs":"befd3c82fe6d9186b5802945853da9653649779989fd36cd2a835e3264156281","src/read/read_cache.rs":"939b66cfc11fc022c4e4b78fcad63b375516967da2274da78fb200271d934a53","src/read/read_ref.rs":"5fe6f717c79b07fecac9ee8ba15740c7a9581c36f1e356119e99dd669af6c39c","src/read/traits.rs":"5f29ae16bcf078c7089b22d7bd3ca9c6bc2eb637900a3b1cc70f9a45e5f8be09","src/read/util.rs":"c329a240689b177613049e00faf7928e6cd6aad021542cd708cc06b598c6900e","src/read/wasm.rs":"936ac6b218d23d7bb9ca6869f17cd8dafbed80ee0b267254c7a3ffe05bd46948","src/write/coff.rs":"16f52497fd18ec893c8f72903e9ea0bde6901e75acdfbc8be6a7305e13bccb8c","src/write/elf.rs":"2d6d3c4b014e9df7dd09e3ecf926a7d8fbac6e3cf3ab768e672b7c8ac1d38485","src/write/macho.rs":"fa058f9e7aa1e9895a3c4575fa527c3d5dbac186d994c9ba48801348a8428f35","src/write/mod.rs":"970620fba6e7b851981cda09929d93667a51d0c0be2c1491fdd8002d530515df","src/write/string.rs":"920d71223a5a146ef516b6d5fb6d22bc86a7e456da369ae8a4d1ca6b63d59892","src/write/util.rs":"3bf18004fd5cd25229e480856f36b3410f23b12c096de4c52ab13e11da75b2e3","tests/integration.rs":"d491a0ae0d50c3194cd7b81720262f55ccb234251346f188284ce29729823dc2","tests/parse_self.rs":"81b44b2dd1de9a5d8c18d9bd8926156e39fb83931837afa8ca344da0d309aeee","tests/round_trip/bss.rs":"849d69b063fd757fed02219dd81e9d13b82068a2025d2cc5cfd40cf557e31bda","tests/round_trip/comdat.rs":"2e3ef1aef466911646e5cbfe0b1a8c1543530baf8ca6102394519e701a1e2747","tests/round_trip/common.rs":"ced08ff559ca4d343ceef54bb4c581a3405cd96d6a1628ba43b7aab82070800b","tests/round_trip/elf.rs":"a1ff40266998321c75023cf76384f8ad03828c6d487421ea8b7774fce8173039","tests/round_trip/macho.rs":"b23931f506345b26ce3b4908dc2ce02f704603c622d39f5e9e7c8529f2882818","tests/round_trip/mod.rs":"b741ba432fdee2156699743962c64aaf2d1e9629c432e40953ac4d410688ea5a","tests/round_trip/tls.rs":"23a49a1036b9173ece82a3080745930e5925e745280ab38866c9d3c29f463e63"},"package":"39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"}
\ No newline at end of file
index dbc2694b80989f1c7e31c12a35f92044d627f616..429585bbfa099c96de09d6e848c8d8ceaf1ec0e6 100644 (file)
@@ -2,6 +2,91 @@
 
 --------------------------------------------------------------------------------
 
+## 0.26.2
+
+Released 2021/08/28.
+
+### Added
+
+* Added support for 64-bit symbol table names to `read::archive`.
+  [#366](https://github.com/gimli-rs/object/pull/366)
+
+--------------------------------------------------------------------------------
+
+## 0.26.1
+
+Released 2021/08/19.
+
+### Changed
+
+* Activate `memchr`'s `rustc-dep-of-std` feature
+  [#356](https://github.com/gimli-rs/object/pull/356)
+
+--------------------------------------------------------------------------------
+
+## 0.26.0
+
+Released 2021/07/26.
+
+### Breaking changes
+
+* Changed `ReadRef::read_bytes_at_until` to accept a range parameter.
+  [#326](https://github.com/gimli-rs/object/pull/326)
+
+* Added `ReadRef` type parameter to `read::StringTable` and types that
+  contain it. String table entries are now only read as required.
+  [#326](https://github.com/gimli-rs/object/pull/326)
+
+* Changed result type of `read::elf::SectionHeader::data` and `data_as_array`.
+  [#332](https://github.com/gimli-rs/object/pull/332)
+
+* Moved `pod::WritableBuffer` to `write::WritableBuffer`.
+  Renamed `WritableBuffer::extend` to `write_bytes`.
+  Added more provided methods to `WritableBuffer`.
+  [#335](https://github.com/gimli-rs/object/pull/335)
+
+* Moved `pod::Bytes` to `read::Bytes`.
+  [#336](https://github.com/gimli-rs/object/pull/336)
+
+* Added `is_mips64el` parameter to `elf::Rela64::r_info/set_r_info`.
+  [#337](https://github.com/gimli-rs/object/pull/337)
+
+### Changed
+
+* Removed `alloc` dependency when no features are enabled.
+  [#336](https://github.com/gimli-rs/object/pull/336)
+
+### Added
+
+* Added `read::pe::PeFile` methods: `section_table`, `data_directory`, and `data`.
+  [#324](https://github.com/gimli-rs/object/pull/324)
+
+* Added more ELF definitions.
+  [#332](https://github.com/gimli-rs/object/pull/332)
+
+* Added `read::elf::SectionTable` methods for hash tables and symbol version
+  information.
+  [#332](https://github.com/gimli-rs/object/pull/332)
+
+* Added PE RISC-V definitions.
+  [#333](https://github.com/gimli-rs/object/pull/333)
+
+* Added `WritableBuffer` implementation for `Vec`.
+  [#335](https://github.com/gimli-rs/object/pull/335)
+
+--------------------------------------------------------------------------------
+
+## 0.25.3
+
+Released 2021/06/12.
+
+### Added
+
+* Added `RelocationEncoding::AArch64Call`.
+  [#322](https://github.com/gimli-rs/object/pull/322)
+
+--------------------------------------------------------------------------------
+
 ## 0.25.2
 
 Released 2021/06/04.
index ad79d9ebf0ff7914cf52ac044e53bf7103566884..b42e1b04be516822154cdcec47cbfd2aac453233 100644 (file)
@@ -1,5 +1,7 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
+version = 3
+
 [[package]]
 name = "adler"
 version = "1.0.2"
@@ -20,9 +22,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.41"
+version = "0.1.49"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68448b4c6cee41f17bef42cbdad2fde55d05b91a6116c3a517e5389fb742758d"
+checksum = "20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2"
 
 [[package]]
 name = "crc32fast"
@@ -47,15 +49,15 @@ dependencies = [
 
 [[package]]
 name = "hashbrown"
-version = "0.9.1"
+version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
 
 [[package]]
 name = "indexmap"
-version = "1.6.2"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
+checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
 dependencies = [
  "autocfg",
  "hashbrown",
@@ -63,21 +65,25 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.94"
+version = "0.2.99"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
+checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
 
 [[package]]
 name = "memchr"
-version = "2.4.0"
+version = "2.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+dependencies = [
+ "compiler_builtins",
+ "rustc-std-workspace-core",
+]
 
 [[package]]
 name = "memmap2"
-version = "0.2.3"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "723e3ebdcdc5c023db1df315364573789f8857c11b631a2fdfad7c00f5c046b4"
+checksum = "00b6c2ebff6180198788f5db08d7ce3bc1d0b617176678831a7510825973e357"
 dependencies = [
  "libc",
 ]
@@ -94,7 +100,7 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.25.2"
+version = "0.26.2"
 dependencies = [
  "compiler_builtins",
  "crc32fast",
index 0fba802f16d6892ce2edab861c80717a18ca73e3..7ce7bdffdf0a2423633a4c829b11b4e58d883802 100644 (file)
@@ -13,8 +13,7 @@
 [package]
 edition = "2018"
 name = "object"
-version = "0.25.2"
-authors = ["Nick Fitzgerald <fitzgen@gmail.com>", "Philip Craig <philipjcraig@gmail.com>"]
+version = "0.26.2"
 exclude = ["/.coveralls.yml", "/.travis.yml"]
 description = "A unified interface for reading and writing object file formats."
 keywords = ["object", "elf", "mach-o", "pe", "coff"]
@@ -73,17 +72,17 @@ version = "1.1"
 optional = true
 
 [dependencies.memchr]
-version = "2.4"
+version = "2.4.1"
 default-features = false
 
 [dependencies.wasmparser]
 version = "0.57"
 optional = true
 [dev-dependencies.memmap2]
-version = "0.2.2"
+version = "0.3"
 
 [features]
-all = ["read", "write", "std", "compression", "default"]
+all = ["read", "write", "std", "compression", "wasm"]
 archive = []
 cargo-all = []
 coff = []
@@ -94,7 +93,7 @@ macho = []
 pe = ["coff"]
 read = ["read_core", "archive", "coff", "elf", "macho", "pe", "unaligned"]
 read_core = []
-rustc-dep-of-std = ["core", "compiler_builtins", "alloc"]
+rustc-dep-of-std = ["core", "compiler_builtins", "alloc", "memchr/rustc-dep-of-std"]
 std = ["memchr/std"]
 unaligned = []
 wasm = ["wasmparser"]
index e79f6e4728243bdeef52b4e57f03fc82f810a955..b6c753c3c0b3561b23304203de7865899b2f7907 100644 (file)
@@ -13,6 +13,25 @@ For reading files, it provides multiple levels of support:
 
 Supported file formats: ELF, Mach-O, Windows PE/COFF, Wasm, and Unix archive.
 
+## Example for unified read API
+```rust
+use object::{Object, ObjectSection};
+use std::error::Error;
+use std::fs;
+
+/// Reads a file and displays the content of the ".boot" section.
+fn main() -> Result<(), Box<dyn Error>> {
+  let bin_data = fs::read("./multiboot2-binary.elf")?;
+  let obj_file = object::File::parse(&*bin_data)?;
+  if let Some(section) = obj_file.section_by_name(".boot") {
+    println!("{:#x?}", section.data()?);
+  } else {
+    eprintln!("section not available");
+  }
+  Ok(())
+}
+```
+
 ## License
 
 Licensed under either of
index 8a2a5ac0c5311d73e70888562fcc765aa07cad80..bbcab143a927dcbd543408635e3ad03332451e15 100644 (file)
@@ -437,7 +437,7 @@ mod elf {
             let mut dynstr = object::StringTable::default();
             for s in segments {
                 if let Ok(Some(data)) = s.data_range(endian, data, strtab, strsz) {
-                    dynstr = object::StringTable::new(data);
+                    dynstr = object::StringTable::new(data, 0, data.len() as u64);
                     break;
                 }
             }
@@ -540,8 +540,12 @@ mod elf {
                     SHT_RELA => print_section_rela(p, endian, data, elf, sections, section),
                     SHT_NOTE => print_section_notes(p, endian, data, elf, section),
                     SHT_GROUP => print_section_group(p, endian, data, elf, sections, section),
+                    SHT_HASH => print_hash(p, endian, data, elf, sections, section),
+                    SHT_GNU_HASH => print_gnu_hash(p, endian, data, elf, sections, section),
+                    SHT_GNU_VERDEF => print_gnu_verdef(p, endian, data, elf, sections, section),
+                    SHT_GNU_VERNEED => print_gnu_verneed(p, endian, data, elf, sections, section),
+                    SHT_GNU_VERSYM => print_gnu_versym(p, endian, data, elf, sections, section),
                     // TODO:
-                    //SHT_HASH =>
                     //SHT_DYNAMIC =>
                     //SHT_SHLIB =>
                     //SHT_INIT_ARRAY =>
@@ -792,6 +796,153 @@ mod elf {
         }
     }
 
+    fn print_hash<Elf: FileHeader>(
+        p: &mut Printer<impl Write>,
+        endian: Elf::Endian,
+        data: &[u8],
+        _elf: &Elf,
+        _sections: &SectionTable<Elf>,
+        section: &Elf::SectionHeader,
+    ) {
+        if let Ok(Some(hash)) = section.hash_header(endian, data) {
+            p.group("Hash", |p| {
+                p.field("BucketCount", hash.bucket_count.get(endian));
+                p.field("ChainCount", hash.chain_count.get(endian));
+            });
+        }
+        /* TODO: add this in a test somewhere
+        if let Ok(Some(hash_table)) = section.hash(endian, data) {
+            if let Ok(symbols) = _sections.symbols(endian, data, SHT_DYNSYM) {
+                for symbol in symbols.symbols() {
+                    let name = symbols.symbol_name(endian, symbol).unwrap();
+                    if !symbol.is_definition(endian) {
+                        continue;
+                    }
+                    let hash = hash(name);
+                    let hash_symbol = hash_table.find(endian, name, hash, &symbols).unwrap();
+                    let hash_name = symbols.symbol_name(endian, hash_symbol).unwrap();
+                    assert_eq!(name, hash_name);
+                }
+            }
+        }
+        */
+    }
+
+    fn print_gnu_hash<Elf: FileHeader>(
+        p: &mut Printer<impl Write>,
+        endian: Elf::Endian,
+        data: &[u8],
+        _elf: &Elf,
+        _sections: &SectionTable<Elf>,
+        section: &Elf::SectionHeader,
+    ) {
+        if let Ok(Some(hash)) = section.gnu_hash_header(endian, data) {
+            p.group("GnuHash", |p| {
+                p.field("BucketCount", hash.bucket_count.get(endian));
+                p.field("SymbolBase", hash.symbol_base.get(endian));
+                p.field("BloomCount", hash.bloom_count.get(endian));
+                p.field("BloomShift", hash.bloom_shift.get(endian));
+            });
+        }
+        /* TODO: add this in a test somewhere
+        if let Ok(Some(hash_table)) = section.gnu_hash(endian, data) {
+            if let Ok(symbols) = _sections.symbols(endian, data, SHT_DYNSYM) {
+                for symbol in &symbols.symbols()[hash_table.symbol_base() as usize..] {
+                    let name = symbols.symbol_name(endian, symbol).unwrap();
+                    let hash = gnu_hash(name);
+                    let hash_symbol = hash_table.find(endian, name, hash, &symbols).unwrap();
+                    let hash_name = symbols.symbol_name(endian, hash_symbol).unwrap();
+                    assert_eq!(name, hash_name);
+                }
+            }
+        }
+        */
+    }
+
+    fn print_gnu_verdef<Elf: FileHeader>(
+        p: &mut Printer<impl Write>,
+        endian: Elf::Endian,
+        data: &[u8],
+        _elf: &Elf,
+        _sections: &SectionTable<Elf>,
+        section: &Elf::SectionHeader,
+    ) {
+        if let Ok(Some(mut verdefs)) = section.gnu_verdef(endian, data) {
+            while let Ok(Some((verdef, mut verdauxs))) = verdefs.next() {
+                p.group("VersionDefinition", |p| {
+                    // TODO: names
+                    p.field("Version", verdef.vd_version.get(endian));
+                    p.field_hex("Flags", verdef.vd_flags.get(endian));
+                    p.flags(verdef.vd_flags.get(endian), 0, FLAGS_VER_FLG);
+                    p.field("Index", verdef.vd_ndx.get(endian) & !VER_NDX_HIDDEN);
+                    p.flags(verdef.vd_ndx.get(endian), 0, FLAGS_VER_NDX);
+                    p.field("AuxCount", verdef.vd_cnt.get(endian));
+                    p.field_hex("Hash", verdef.vd_hash.get(endian));
+                    p.field("AuxOffset", verdef.vd_aux.get(endian));
+                    p.field("NextOffset", verdef.vd_next.get(endian));
+                    while let Ok(Some(verdaux)) = verdauxs.next() {
+                        p.group("Aux", |p| {
+                            p.field_hex("Name", verdaux.vda_name.get(endian));
+                            p.field("NextOffset", verdaux.vda_next.get(endian));
+                        });
+                    }
+                });
+            }
+        }
+    }
+
+    fn print_gnu_verneed<Elf: FileHeader>(
+        p: &mut Printer<impl Write>,
+        endian: Elf::Endian,
+        data: &[u8],
+        _elf: &Elf,
+        _sections: &SectionTable<Elf>,
+        section: &Elf::SectionHeader,
+    ) {
+        if let Ok(Some(mut verneeds)) = section.gnu_verneed(endian, data) {
+            while let Ok(Some((verneed, mut vernauxs))) = verneeds.next() {
+                p.group("VersionNeed", |p| {
+                    // TODO: names
+                    p.field("Version", verneed.vn_version.get(endian));
+                    p.field("AuxCount", verneed.vn_cnt.get(endian));
+                    p.field_hex("Filename", verneed.vn_file.get(endian));
+                    p.field("AuxOffset", verneed.vn_aux.get(endian));
+                    p.field("NextOffset", verneed.vn_next.get(endian));
+                    while let Ok(Some(vernaux)) = vernauxs.next() {
+                        p.group("Aux", |p| {
+                            p.field_hex("Hash", vernaux.vna_hash.get(endian));
+                            p.field_hex("Flags", vernaux.vna_flags.get(endian));
+                            p.flags(vernaux.vna_flags.get(endian), 0, FLAGS_VER_FLG);
+                            p.field("Index", vernaux.vna_other.get(endian) & !VER_NDX_HIDDEN);
+                            p.flags(vernaux.vna_other.get(endian), 0, FLAGS_VER_NDX);
+                            p.field_hex("Name", vernaux.vna_name.get(endian));
+                            p.field("NextOffset", vernaux.vna_next.get(endian));
+                        });
+                    }
+                });
+            }
+        }
+    }
+
+    fn print_gnu_versym<Elf: FileHeader>(
+        p: &mut Printer<impl Write>,
+        endian: Elf::Endian,
+        data: &[u8],
+        _elf: &Elf,
+        _sections: &SectionTable<Elf>,
+        section: &Elf::SectionHeader,
+    ) {
+        if let Ok(Some(syms)) = section.gnu_versym(endian, data) {
+            for sym in syms {
+                p.group("VersionSymbol", |p| {
+                    p.field("Version", sym.0.get(endian) & !VER_NDX_HIDDEN);
+                    p.flags(sym.0.get(endian), 0, FLAGS_VER_NDX);
+                    // TODO: version name
+                });
+            }
+        }
+    }
+
     static FLAGS_EI_CLASS: &[Flag<u8>] = &flags!(ELFCLASSNONE, ELFCLASS32, ELFCLASS64);
     static FLAGS_EI_DATA: &[Flag<u8>] = &flags!(ELFDATANONE, ELFDATA2LSB, ELFDATA2MSB);
     static FLAGS_EV: &[Flag<u8>] = &flags!(EV_NONE, EV_CURRENT);
@@ -1173,6 +1324,16 @@ mod elf {
         SHT_PREINIT_ARRAY,
         SHT_GROUP,
         SHT_SYMTAB_SHNDX,
+        SHT_GNU_ATTRIBUTES,
+        SHT_GNU_HASH,
+        SHT_GNU_LIBLIST,
+        SHT_CHECKSUM,
+        SHT_SUNW_move,
+        SHT_SUNW_COMDAT,
+        SHT_SUNW_syminfo,
+        SHT_GNU_VERDEF,
+        SHT_GNU_VERNEED,
+        SHT_GNU_VERSYM,
     );
     static FLAGS_SHT_MIPS: &[Flag<u32>] = &flags!(
         SHT_MIPS_LIBLIST,
@@ -3180,6 +3341,8 @@ mod elf {
         DF_1_STUB,
         DF_1_PIE,
     );
+    static FLAGS_VER_FLG: &[Flag<u16>] = &flags!(VER_FLG_BASE, VER_FLG_WEAK);
+    static FLAGS_VER_NDX: &[Flag<u16>] = &flags!(VER_NDX_HIDDEN);
 }
 
 mod macho {
@@ -4665,6 +4828,9 @@ mod pe {
         IMAGE_FILE_MACHINE_M32R,
         IMAGE_FILE_MACHINE_ARM64,
         IMAGE_FILE_MACHINE_CEE,
+        IMAGE_FILE_MACHINE_RISCV32,
+        IMAGE_FILE_MACHINE_RISCV64,
+        IMAGE_FILE_MACHINE_RISCV128,
     );
     static FLAGS_IMAGE_SCN: &[Flag<u32>] = &flags!(
         IMAGE_SCN_TYPE_NO_PAD,
index a7b01a3df1bc3c24b0c1f33317fe8b71ff82aada..c86665c216e20c9218d98a7c137742ede7e3b9fc 100644 (file)
@@ -336,6 +336,11 @@ pub enum RelocationEncoding {
     ///
     /// The `RelocationKind` must be PC relative.
     S390xDbl,
+
+    /// AArch64 call target.
+    ///
+    /// The `RelocationKind` must be PC relative.
+    AArch64Call,
 }
 
 /// File flags that are specific to each file format.
index 710f0ec834ad8a95ffb0e398548328756f8c389d..28ac16bbec6c36871098b20b9f8a87a8dcfffb24 100644 (file)
@@ -695,6 +695,33 @@ pub const SHT_GROUP: u32 = 17;
 pub const SHT_SYMTAB_SHNDX: u32 = 18;
 /// Start of OS-specific section types.
 pub const SHT_LOOS: u32 = 0x6000_0000;
+/// Object attributes.
+pub const SHT_GNU_ATTRIBUTES: u32 = 0x6fff_fff5;
+/// GNU-style hash table.
+pub const SHT_GNU_HASH: u32 = 0x6fff_fff6;
+/// Prelink library list
+pub const SHT_GNU_LIBLIST: u32 = 0x6fff_fff7;
+/// Checksum for DSO content.
+pub const SHT_CHECKSUM: u32 = 0x6fff_fff8;
+/// Sun-specific low bound.
+pub const SHT_LOSUNW: u32 = 0x6fff_fffa;
+#[allow(missing_docs, non_upper_case_globals)]
+pub const SHT_SUNW_move: u32 = 0x6fff_fffa;
+#[allow(missing_docs)]
+pub const SHT_SUNW_COMDAT: u32 = 0x6fff_fffb;
+#[allow(missing_docs, non_upper_case_globals)]
+pub const SHT_SUNW_syminfo: u32 = 0x6fff_fffc;
+/// Version definition section.
+#[allow(non_upper_case_globals)]
+pub const SHT_GNU_VERDEF: u32 = 0x6fff_fffd;
+/// Version needs section.
+#[allow(non_upper_case_globals)]
+pub const SHT_GNU_VERNEED: u32 = 0x6fff_fffe;
+/// Version symbol table.
+#[allow(non_upper_case_globals)]
+pub const SHT_GNU_VERSYM: u32 = 0x6fff_ffff;
+/// Sun-specific high bound.
+pub const SHT_HISUNW: u32 = 0x6fff_ffff;
 /// End of OS-specific section types.
 pub const SHT_HIOS: u32 = 0x6fff_ffff;
 /// Start of processor-specific section types.
@@ -1151,13 +1178,7 @@ impl<E: Endian> Rela64<E> {
     }
 
     /// Calculate the `r_info` field given the `r_sym` and `r_type` components.
-    // TODO: add is_mips64el parameter
-    pub fn r_info(endian: E, r_sym: u32, r_type: u32) -> U64<E> {
-        U64::new(endian, (u64::from(r_sym) << 32) | u64::from(r_type))
-    }
-
-    #[allow(dead_code)]
-    pub(crate) fn r_info2(endian: E, is_mips64el: bool, r_sym: u32, r_type: u32) -> U64<E> {
+    pub fn r_info(endian: E, is_mips64el: bool, r_sym: u32, r_type: u32) -> U64<E> {
         let mut t = (u64::from(r_sym) << 32) | u64::from(r_type);
         if is_mips64el {
             t = (t >> 32)
@@ -1170,9 +1191,8 @@ impl<E: Endian> Rela64<E> {
     }
 
     /// Set the `r_info` field given the `r_sym` and `r_type` components.
-    // TODO: add is_mips64el parameter
-    pub fn set_r_info(&mut self, endian: E, r_sym: u32, r_type: u32) {
-        self.r_info = Self::r_info(endian, r_sym, r_type);
+    pub fn set_r_info(&mut self, endian: E, is_mips64el: bool, r_sym: u32, r_type: u32) {
+        self.r_info = Self::r_info(endian, is_mips64el, r_sym, r_type);
     }
 }
 
@@ -1669,10 +1689,99 @@ pub const DF_1_STUB: u32 = 0x0400_0000;
 #[allow(missing_docs)]
 pub const DF_1_PIE: u32 = 0x0800_0000;
 
-// TODO: ELF*_Verdef, VER_DEF_*, VER_FLG_*, VER_NDX_*
-// TODO: Elf*_Verdaux
-// TODO: Elf*_Verneed, VER_NEED_*
-// TODO: Elf*_Vernaux, VER_FLG_*
+/// Version symbol information
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct Versym<E: Endian>(pub U16<E>);
+
+/// Version definition sections
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct Verdef<E: Endian> {
+    /// Version revision
+    pub vd_version: U16<E>,
+    /// Version information
+    pub vd_flags: U16<E>,
+    /// Version Index
+    pub vd_ndx: U16<E>,
+    /// Number of associated aux entries
+    pub vd_cnt: U16<E>,
+    /// Version name hash value
+    pub vd_hash: U32<E>,
+    /// Offset in bytes to verdaux array
+    pub vd_aux: U32<E>,
+    /// Offset in bytes to next verdef entry
+    pub vd_next: U32<E>,
+}
+
+// Legal values for vd_version (version revision).
+/// No version
+pub const VER_DEF_NONE: u16 = 0;
+/// Current version
+pub const VER_DEF_CURRENT: u16 = 1;
+
+// Legal values for vd_flags and vna_flags (version information flags).
+/// Version definition of file itself
+pub const VER_FLG_BASE: u16 = 0x1;
+/// Weak version identifier
+pub const VER_FLG_WEAK: u16 = 0x2;
+
+// Versym symbol index values.
+/// Symbol is local.
+pub const VER_NDX_LOCAL: u16 = 0;
+/// Symbol is global.
+pub const VER_NDX_GLOBAL: u16 = 1;
+/// Symbol is hidden.
+pub const VER_NDX_HIDDEN: u16 = 0x8000;
+
+/// Auxiliary version information.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct Verdaux<E: Endian> {
+    /// Version or dependency names
+    pub vda_name: U32<E>,
+    /// Offset in bytes to next verdaux
+    pub vda_next: U32<E>,
+}
+
+/// Version dependency.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct Verneed<E: Endian> {
+    /// Version of structure
+    pub vn_version: U16<E>,
+    /// Number of associated aux entries
+    pub vn_cnt: U16<E>,
+    /// Offset of filename for this dependency
+    pub vn_file: U32<E>,
+    /// Offset in bytes to vernaux array
+    pub vn_aux: U32<E>,
+    /// Offset in bytes to next verneed entry
+    pub vn_next: U32<E>,
+}
+
+// Legal values for vn_version (version revision).
+/// No version
+pub const VER_NEED_NONE: u16 = 0;
+/// Current version
+pub const VER_NEED_CURRENT: u16 = 1;
+
+/// Auxiliary needed version information.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct Vernaux<E: Endian> {
+    /// Hash value of dependency name
+    pub vna_hash: U32<E>,
+    /// Dependency specific information
+    pub vna_flags: U16<E>,
+    /// Version Index
+    pub vna_other: U16<E>,
+    /// Dependency name string offset
+    pub vna_name: U32<E>,
+    /// Offset in bytes to next vernaux entry
+    pub vna_next: U32<E>,
+}
+
 // TODO: Elf*_auxv_t, AT_*
 
 /// Note section entry header.
@@ -1769,6 +1878,65 @@ pub const NT_GNU_PROPERTY_TYPE_0: u32 = 5;
 // TODO: GNU_PROPERTY_*
 // TODO: Elf*_Move
 
+/// Header of `SHT_HASH` section.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct HashHeader<E: Endian> {
+    /// The number of hash buckets.
+    pub bucket_count: U32<E>,
+    /// The number of chain values.
+    pub chain_count: U32<E>,
+    // Array of hash bucket start indices.
+    // buckets: U32<E>[bucket_count]
+    // Array of hash chain links. An index of 0 terminates the chain.
+    // chains: U32<E>[chain_count]
+}
+
+/// Calculate the SysV hash for a symbol name.
+///
+/// Used for `SHT_HASH`.
+pub fn hash(name: &[u8]) -> u32 {
+    let mut hash = 0u32;
+    for byte in name {
+        hash = hash.wrapping_mul(16).wrapping_add(u32::from(*byte));
+        hash ^= (hash >> 24) & 0xf0;
+    }
+    hash & 0xfff_ffff
+}
+
+/// Header of `SHT_GNU_HASH` section.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct GnuHashHeader<E: Endian> {
+    /// The number of hash buckets.
+    pub bucket_count: U32<E>,
+    /// The symbol table index of the first symbol in the hash.
+    pub symbol_base: U32<E>,
+    /// The number of words in the bloom filter.
+    ///
+    /// Must be a non-zero power of 2.
+    pub bloom_count: U32<E>,
+    /// The bit shift count for the bloom filter.
+    pub bloom_shift: U32<E>,
+    // Array of bloom filter words.
+    // bloom_filters: U32<E>[bloom_count] or U64<E>[bloom_count]
+    // Array of hash bucket start indices.
+    // buckets: U32<E>[bucket_count]
+    // Array of hash values, one for each symbol starting at symbol_base.
+    // values: U32<E>[symbol_count]
+}
+
+/// Calculate the GNU hash for a symbol name.
+///
+/// Used for `SHT_GNU_HASH`.
+pub fn gnu_hash(name: &[u8]) -> u32 {
+    let mut hash = 5381u32;
+    for byte in name {
+        hash = hash.wrapping_mul(33).wrapping_add(u32::from(*byte));
+    }
+    hash
+}
+
 // Motorola 68k specific definitions.
 
 // m68k values for `Rel*::r_type`.
@@ -6068,6 +6236,13 @@ unsafe_impl_endian_pod!(
     ProgramHeader64,
     Dyn32,
     Dyn64,
+    Versym,
+    Verdef,
+    Verdaux,
+    Verneed,
+    Vernaux,
     NoteHeader32,
     NoteHeader64,
+    HashHeader,
+    GnuHashHeader,
 );
index 29ffe6f0ba9c0d32fd17fb27e89f0711933d895a..e62ad5ce5c0aae2f58dc95413eb3c489be797ea2 100644 (file)
 //! ## Unified write API
 //!
 //! [write::Object] allows building an object and then writing it out.
+//!
+//! ## Example for unified read API
+//!  ```no_run
+//! use object::{Object, ObjectSection};
+//! use std::error::Error;
+//! use std::fs;
+//!
+//! /// Reads a file and displays the content of the ".boot" section.
+//! fn main() -> Result<(), Box<dyn Error>> {
+//!   let bin_data = fs::read("./multiboot2-binary.elf")?;
+//!   let obj_file = object::File::parse(&*bin_data)?;
+//!   if let Some(section) = obj_file.section_by_name(".boot") {
+//!     println!("{:#x?}", section.data()?);
+//!   } else {
+//!     eprintln!("section not available");
+//!   }
+//!   Ok(())
+//! }
+//! ```
 
 #![deny(missing_docs)]
 #![deny(missing_debug_implementations)]
@@ -45,6 +64,7 @@
 #[cfg(feature = "cargo-all")]
 compile_error!("'--all-features' is not supported; use '--features all' instead");
 
+#[cfg(feature = "read_core")]
 #[allow(unused_imports)]
 #[macro_use]
 extern crate alloc;
index c4e1c53d42ea945b1d06937c559de3485ea29b3f..46daf533f12407523f19db570fe30d20f9a21536 100644 (file)
@@ -343,6 +343,12 @@ pub const IMAGE_FILE_MACHINE_M32R: u16 = 0x9041;
 /// ARM64 Little-Endian
 pub const IMAGE_FILE_MACHINE_ARM64: u16 = 0xAA64;
 pub const IMAGE_FILE_MACHINE_CEE: u16 = 0xC0EE;
+/// RISCV32
+pub const IMAGE_FILE_MACHINE_RISCV32: u16 = 0x5032;
+/// RISCV64
+pub const IMAGE_FILE_MACHINE_RISCV64: u16 = 0x5064;
+/// RISCV128
+pub const IMAGE_FILE_MACHINE_RISCV128: u16 = 0x5128;
 
 //
 // Directory format.
@@ -1732,6 +1738,10 @@ pub const IMAGE_REL_BASED_MIPS_JMPADDR16: u16 = 9;
 pub const IMAGE_REL_BASED_ARM_MOV32: u16 = 5;
 pub const IMAGE_REL_BASED_THUMB_MOV32: u16 = 7;
 
+pub const IMAGE_REL_BASED_RISCV_HIGH20: u16 = 5;
+pub const IMAGE_REL_BASED_RISCV_LOW12I: u16 = 7;
+pub const IMAGE_REL_BASED_RISCV_LOW12S: u16 = 8;
+
 //
 // Archive format.
 //
index 42737d1c834a40dea8eb24b2de793f49d68eaf2a..805cf82492d7e7d8df27a90d1c0457ebb1cf4e80 100644 (file)
@@ -8,9 +8,7 @@
     allow(dead_code)
 )]
 
-use alloc::string::String;
-use alloc::vec::Vec;
-use core::{fmt, mem, result, slice};
+use core::{mem, result, slice};
 
 type Result<T> = result::Result<T, ()>;
 
@@ -147,290 +145,6 @@ pub fn bytes_of_slice_mut<T: Pod>(val: &mut [T]) -> &mut [u8] {
     unsafe { slice::from_raw_parts_mut(val.as_mut_ptr().cast(), size) }
 }
 
-/// A newtype for byte slices.
-///
-/// It has these important features:
-/// - no methods that can panic, such as `Index`
-/// - convenience methods for `Pod` types
-/// - a useful `Debug` implementation
-#[derive(Default, Clone, Copy, PartialEq, Eq)]
-pub struct Bytes<'data>(pub &'data [u8]);
-
-impl<'data> fmt::Debug for Bytes<'data> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        debug_list_bytes(self.0, fmt)
-    }
-}
-
-impl<'data> Bytes<'data> {
-    /// Return the length of the byte slice.
-    #[inline]
-    pub fn len(&self) -> usize {
-        self.0.len()
-    }
-
-    /// Return true if the byte slice is empty.
-    #[inline]
-    pub fn is_empty(&self) -> bool {
-        self.0.is_empty()
-    }
-
-    /// Skip over the given number of bytes at the start of the byte slice.
-    ///
-    /// Modifies the byte slice to start after the bytes.
-    ///
-    /// Returns an error if there are too few bytes.
-    #[inline]
-    pub fn skip(&mut self, offset: usize) -> Result<()> {
-        match self.0.get(offset..) {
-            Some(tail) => {
-                self.0 = tail;
-                Ok(())
-            }
-            None => {
-                self.0 = &[];
-                Err(())
-            }
-        }
-    }
-
-    /// Return a reference to the given number of bytes at the start of the byte slice.
-    ///
-    /// Modifies the byte slice to start after the bytes.
-    ///
-    /// Returns an error if there are too few bytes.
-    #[inline]
-    pub fn read_bytes(&mut self, count: usize) -> Result<Bytes<'data>> {
-        match (self.0.get(..count), self.0.get(count..)) {
-            (Some(head), Some(tail)) => {
-                self.0 = tail;
-                Ok(Bytes(head))
-            }
-            _ => {
-                self.0 = &[];
-                Err(())
-            }
-        }
-    }
-
-    /// Return a reference to the given number of bytes at the given offset of the byte slice.
-    ///
-    /// Returns an error if the offset is invalid or there are too few bytes.
-    #[inline]
-    pub fn read_bytes_at(mut self, offset: usize, count: usize) -> Result<Bytes<'data>> {
-        self.skip(offset)?;
-        self.read_bytes(count)
-    }
-
-    /// Return a reference to a `Pod` struct at the start of the byte slice.
-    ///
-    /// Modifies the byte slice to start after the bytes.
-    ///
-    /// Returns an error if there are too few bytes or the slice is incorrectly aligned.
-    #[inline]
-    pub fn read<T: Pod>(&mut self) -> Result<&'data T> {
-        match from_bytes(self.0) {
-            Ok((value, tail)) => {
-                self.0 = tail;
-                Ok(value)
-            }
-            Err(()) => {
-                self.0 = &[];
-                Err(())
-            }
-        }
-    }
-
-    /// Return a reference to a `Pod` struct at the given offset of the byte slice.
-    ///
-    /// Returns an error if there are too few bytes or the offset is incorrectly aligned.
-    #[inline]
-    pub fn read_at<T: Pod>(mut self, offset: usize) -> Result<&'data T> {
-        self.skip(offset)?;
-        self.read()
-    }
-
-    /// Return a reference to a slice of `Pod` structs at the start of the byte slice.
-    ///
-    /// Modifies the byte slice to start after the bytes.
-    ///
-    /// Returns an error if there are too few bytes or the offset is incorrectly aligned.
-    #[inline]
-    pub fn read_slice<T: Pod>(&mut self, count: usize) -> Result<&'data [T]> {
-        match slice_from_bytes(self.0, count) {
-            Ok((value, tail)) => {
-                self.0 = tail;
-                Ok(value)
-            }
-            Err(()) => {
-                self.0 = &[];
-                Err(())
-            }
-        }
-    }
-
-    /// Return a reference to a slice of `Pod` structs at the given offset of the byte slice.
-    ///
-    /// Returns an error if there are too few bytes or the offset is incorrectly aligned.
-    #[inline]
-    pub fn read_slice_at<T: Pod>(mut self, offset: usize, count: usize) -> Result<&'data [T]> {
-        self.skip(offset)?;
-        self.read_slice(count)
-    }
-
-    /// Read a null terminated string.
-    ///
-    /// Does not assume any encoding.
-    /// Reads past the null byte, but doesn't return it.
-    #[inline]
-    pub fn read_string(&mut self) -> Result<&'data [u8]> {
-        match memchr::memchr(b'\0', self.0) {
-            Some(null) => {
-                // These will never fail.
-                let bytes = self.read_bytes(null)?;
-                self.skip(1)?;
-                Ok(bytes.0)
-            }
-            None => {
-                self.0 = &[];
-                Err(())
-            }
-        }
-    }
-
-    /// Read a null terminated string at an offset.
-    ///
-    /// Does not assume any encoding. Does not return the null byte.
-    #[inline]
-    pub fn read_string_at(mut self, offset: usize) -> Result<&'data [u8]> {
-        self.skip(offset)?;
-        self.read_string()
-    }
-}
-
-/// Trait for writable buffer.
-pub trait WritableBuffer {
-    /// Returns position/offset for data to be written at.
-    fn len(&self) -> usize;
-    /// Returns true if buffer contains no data.
-    fn is_empty(&self) -> bool;
-    /// Reserves specified number of bytes in the buffer.
-    fn reserve(&mut self, additional: usize) -> Result<()>;
-    /// Resizes buffer to the specified length, fills new items
-    /// with the specified value.
-    fn resize(&mut self, new_len: usize, value: u8);
-    /// Extends buffer with the specified slice of bytes.
-    fn extend(&mut self, val: &[u8]);
-}
-
-/// A newtype for byte vectors.
-///
-/// It provides convenience methods for `Pod` types.
-// TODO: should this be an extension trait for `Vec<u8>` instead?
-#[derive(Default, Clone, PartialEq, Eq)]
-pub(crate) struct BytesMut(pub Vec<u8>);
-
-impl fmt::Debug for BytesMut {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        debug_list_bytes(&self.0, fmt)
-    }
-}
-
-impl BytesMut {
-    #[inline]
-    pub fn new() -> Self {
-        BytesMut(Vec::new())
-    }
-
-    #[inline]
-    #[allow(dead_code)]
-    pub fn write<T: Pod>(&mut self, val: &T) {
-        self.0.extend_from_slice(bytes_of(val))
-    }
-
-    #[inline]
-    pub fn write_at<T: Pod>(&mut self, offset: usize, val: &T) -> Result<()> {
-        let src = bytes_of(val);
-        let dest = self.0.get_mut(offset..).ok_or(())?;
-        let dest = dest.get_mut(..src.len()).ok_or(())?;
-        dest.copy_from_slice(src);
-        Ok(())
-    }
-
-    #[inline]
-    pub fn as_slice(&self) -> &[u8] {
-        self.0.as_slice()
-    }
-}
-
-impl WritableBuffer for BytesMut {
-    #[inline]
-    fn len(&self) -> usize {
-        self.0.len()
-    }
-
-    #[inline]
-    fn is_empty(&self) -> bool {
-        self.0.is_empty()
-    }
-
-    #[inline]
-    fn reserve(&mut self, additional: usize) -> Result<()> {
-        self.0.reserve(additional);
-        Ok(())
-    }
-
-    #[inline]
-    fn resize(&mut self, new_len: usize, value: u8) {
-        self.0.resize(new_len, value);
-    }
-
-    #[inline]
-    fn extend(&mut self, val: &[u8]) {
-        self.0.extend_from_slice(val)
-    }
-}
-
-// Only for Debug impl of `Bytes/BytesMut`.
-fn debug_list_bytes(bytes: &[u8], fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-    let mut list = fmt.debug_list();
-    list.entries(bytes.iter().take(8).copied().map(DebugByte));
-    if bytes.len() > 8 {
-        list.entry(&DebugLen(bytes.len()));
-    }
-    list.finish()
-}
-
-struct DebugByte(u8);
-
-impl fmt::Debug for DebugByte {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(fmt, "0x{:02x}", self.0)
-    }
-}
-
-struct DebugLen(usize);
-
-impl fmt::Debug for DebugLen {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(fmt, "...; {}", self.0)
-    }
-}
-
-/// A newtype for byte strings.
-///
-/// For byte slices that are strings of an unknown encoding.
-///
-/// Provides a `Debug` implementation that interprets the bytes as UTF-8.
-#[derive(Default, Clone, Copy, PartialEq, Eq)]
-pub(crate) struct ByteString<'data>(pub &'data [u8]);
-
-impl<'data> fmt::Debug for ByteString<'data> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(fmt, "\"{}\"", String::from_utf8_lossy(self.0))
-    }
-}
-
 macro_rules! unsafe_impl_pod {
     ($($struct_name:ident),+ $(,)?) => {
         $(
@@ -521,140 +235,4 @@ mod tests {
         assert_eq!(slice_from_bytes_mut::<u16>(&mut bytes_mut[2..], 4), Err(()));
         assert_eq!(slice_from_bytes_mut::<u16>(&mut bytes_mut[1..], 2), Err(()));
     }
-
-    #[test]
-    fn bytes() {
-        let x = u32::to_be(0x0123_4567);
-        let data = Bytes(bytes_of(&x));
-
-        let mut bytes = data;
-        assert_eq!(bytes.skip(0), Ok(()));
-        assert_eq!(bytes, data);
-
-        let mut bytes = data;
-        assert_eq!(bytes.skip(4), Ok(()));
-        assert_eq!(bytes, Bytes(&[]));
-
-        let mut bytes = data;
-        assert_eq!(bytes.skip(5), Err(()));
-        assert_eq!(bytes, Bytes(&[]));
-
-        let mut bytes = data;
-        assert_eq!(bytes.read_bytes(0), Ok(Bytes(&[])));
-        assert_eq!(bytes, data);
-
-        let mut bytes = data;
-        assert_eq!(bytes.read_bytes(4), Ok(data));
-        assert_eq!(bytes, Bytes(&[]));
-
-        let mut bytes = data;
-        assert_eq!(bytes.read_bytes(5), Err(()));
-        assert_eq!(bytes, Bytes(&[]));
-
-        assert_eq!(data.read_bytes_at(0, 0), Ok(Bytes(&[])));
-        assert_eq!(data.read_bytes_at(4, 0), Ok(Bytes(&[])));
-        assert_eq!(data.read_bytes_at(0, 4), Ok(data));
-        assert_eq!(data.read_bytes_at(1, 4), Err(()));
-
-        let mut bytes = data;
-        assert_eq!(bytes.read::<u16>(), Ok(&u16::to_be(0x0123)));
-        assert_eq!(bytes, Bytes(&[0x45, 0x67]));
-        assert_eq!(data.read_at::<u16>(2), Ok(&u16::to_be(0x4567)));
-        assert_eq!(data.read_at::<u16>(3), Err(()));
-        assert_eq!(data.read_at::<u16>(4), Err(()));
-
-        let mut bytes = data;
-        assert_eq!(bytes.read::<u32>(), Ok(&x));
-        assert_eq!(bytes, Bytes(&[]));
-
-        let mut bytes = data;
-        assert_eq!(bytes.read::<u64>(), Err(()));
-        assert_eq!(bytes, Bytes(&[]));
-
-        let mut bytes = data;
-        assert_eq!(bytes.read_slice::<u8>(0), Ok(&[][..]));
-        assert_eq!(bytes, data);
-
-        let mut bytes = data;
-        assert_eq!(bytes.read_slice::<u8>(4), Ok(data.0));
-        assert_eq!(bytes, Bytes(&[]));
-
-        let mut bytes = data;
-        assert_eq!(bytes.read_slice::<u8>(5), Err(()));
-        assert_eq!(bytes, Bytes(&[]));
-
-        assert_eq!(data.read_slice_at::<u8>(0, 0), Ok(&[][..]));
-        assert_eq!(data.read_slice_at::<u8>(4, 0), Ok(&[][..]));
-        assert_eq!(data.read_slice_at::<u8>(0, 4), Ok(data.0));
-        assert_eq!(data.read_slice_at::<u8>(1, 4), Err(()));
-
-        let data = Bytes(&[0x01, 0x02, 0x00, 0x04]);
-
-        let mut bytes = data;
-        assert_eq!(bytes.read_string(), Ok(&data.0[..2]));
-        assert_eq!(bytes.0, &data.0[3..]);
-
-        let mut bytes = data;
-        bytes.skip(3).unwrap();
-        assert_eq!(bytes.read_string(), Err(()));
-        assert_eq!(bytes.0, &[]);
-
-        assert_eq!(data.read_string_at(0), Ok(&data.0[..2]));
-        assert_eq!(data.read_string_at(1), Ok(&data.0[1..2]));
-        assert_eq!(data.read_string_at(2), Ok(&[][..]));
-        assert_eq!(data.read_string_at(3), Err(()));
-    }
-
-    #[test]
-    fn bytes_mut() {
-        let data = BytesMut(vec![0x01, 0x23, 0x45, 0x67]);
-
-        let mut bytes = data.clone();
-        bytes.write(&u16::to_be(0x89ab));
-        assert_eq!(bytes.0, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab]);
-
-        let mut bytes = data.clone();
-        assert_eq!(bytes.write_at(0, &u16::to_be(0x89ab)), Ok(()));
-        assert_eq!(bytes.0, [0x89, 0xab, 0x45, 0x67]);
-
-        let mut bytes = data.clone();
-        assert_eq!(bytes.write_at(2, &u16::to_be(0x89ab)), Ok(()));
-        assert_eq!(bytes.0, [0x01, 0x23, 0x89, 0xab]);
-
-        assert_eq!(bytes.write_at(3, &u16::to_be(0x89ab)), Err(()));
-        assert_eq!(bytes.write_at(4, &u16::to_be(0x89ab)), Err(()));
-        assert_eq!(
-            BytesMut::default().write_at(0, &u32::to_be(0x89ab)),
-            Err(())
-        );
-    }
-
-    #[test]
-    fn bytes_debug() {
-        assert_eq!(format!("{:?}", Bytes(&[])), "[]");
-        assert_eq!(format!("{:?}", Bytes(&[0x01])), "[0x01]");
-        assert_eq!(
-            format!(
-                "{:?}",
-                Bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08])
-            ),
-            "[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]"
-        );
-        assert_eq!(
-            format!(
-                "{:?}",
-                Bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09])
-            ),
-            "[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, ...; 9]"
-        );
-
-        assert_eq!(format!("{:?}", BytesMut(vec![])), "[]");
-        assert_eq!(
-            format!(
-                "{:?}",
-                BytesMut(vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09])
-            ),
-            "[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, ...; 9]"
-        );
-    }
 }
index c87732452f1a7a3a87dad6ab96a58b089894cf10..80526e99430978d565195d7c8f0731b9c623dc08 100644 (file)
@@ -890,11 +890,21 @@ where
     R: ReadRef<'data>,
 {
     #[cfg(feature = "coff")]
-    Coff((coff::CoffSymbolTable<'data, 'file>, PhantomData<R>)),
+    Coff((coff::CoffSymbolTable<'data, 'file, R>, PhantomData<R>)),
     #[cfg(feature = "elf")]
-    Elf32((elf::ElfSymbolTable32<'data, 'file>, PhantomData<R>)),
+    Elf32(
+        (
+            elf::ElfSymbolTable32<'data, 'file, Endianness, R>,
+            PhantomData<R>,
+        ),
+    ),
     #[cfg(feature = "elf")]
-    Elf64((elf::ElfSymbolTable64<'data, 'file>, PhantomData<R>)),
+    Elf64(
+        (
+            elf::ElfSymbolTable64<'data, 'file, Endianness, R>,
+            PhantomData<R>,
+        ),
+    ),
     #[cfg(feature = "macho")]
     MachO32(
         (
@@ -910,9 +920,9 @@ where
         ),
     ),
     #[cfg(feature = "pe")]
-    Pe32((coff::CoffSymbolTable<'data, 'file>, PhantomData<R>)),
+    Pe32((coff::CoffSymbolTable<'data, 'file, R>, PhantomData<R>)),
     #[cfg(feature = "pe")]
-    Pe64((coff::CoffSymbolTable<'data, 'file>, PhantomData<R>)),
+    Pe64((coff::CoffSymbolTable<'data, 'file, R>, PhantomData<R>)),
     #[cfg(feature = "wasm")]
     Wasm((wasm::WasmSymbolTable<'data, 'file>, PhantomData<R>)),
 }
@@ -960,11 +970,21 @@ where
     R: ReadRef<'data>,
 {
     #[cfg(feature = "coff")]
-    Coff((coff::CoffSymbolIterator<'data, 'file>, PhantomData<R>)),
+    Coff((coff::CoffSymbolIterator<'data, 'file, R>, PhantomData<R>)),
     #[cfg(feature = "elf")]
-    Elf32((elf::ElfSymbolIterator32<'data, 'file>, PhantomData<R>)),
+    Elf32(
+        (
+            elf::ElfSymbolIterator32<'data, 'file, Endianness, R>,
+            PhantomData<R>,
+        ),
+    ),
     #[cfg(feature = "elf")]
-    Elf64((elf::ElfSymbolIterator64<'data, 'file>, PhantomData<R>)),
+    Elf64(
+        (
+            elf::ElfSymbolIterator64<'data, 'file, Endianness, R>,
+            PhantomData<R>,
+        ),
+    ),
     #[cfg(feature = "macho")]
     MachO32(
         (
@@ -980,9 +1000,9 @@ where
         ),
     ),
     #[cfg(feature = "pe")]
-    Pe32((coff::CoffSymbolIterator<'data, 'file>, PhantomData<R>)),
+    Pe32((coff::CoffSymbolIterator<'data, 'file, R>, PhantomData<R>)),
     #[cfg(feature = "pe")]
-    Pe64((coff::CoffSymbolIterator<'data, 'file>, PhantomData<R>)),
+    Pe64((coff::CoffSymbolIterator<'data, 'file, R>, PhantomData<R>)),
     #[cfg(feature = "wasm")]
     Wasm((wasm::WasmSymbolIterator<'data, 'file>, PhantomData<R>)),
 }
@@ -1013,11 +1033,21 @@ where
     R: ReadRef<'data>,
 {
     #[cfg(feature = "coff")]
-    Coff((coff::CoffSymbol<'data, 'file>, PhantomData<R>)),
+    Coff((coff::CoffSymbol<'data, 'file, R>, PhantomData<R>)),
     #[cfg(feature = "elf")]
-    Elf32((elf::ElfSymbol32<'data, 'file>, PhantomData<R>)),
+    Elf32(
+        (
+            elf::ElfSymbol32<'data, 'file, Endianness, R>,
+            PhantomData<R>,
+        ),
+    ),
     #[cfg(feature = "elf")]
-    Elf64((elf::ElfSymbol64<'data, 'file>, PhantomData<R>)),
+    Elf64(
+        (
+            elf::ElfSymbol64<'data, 'file, Endianness, R>,
+            PhantomData<R>,
+        ),
+    ),
     #[cfg(feature = "macho")]
     MachO32(
         (
@@ -1033,9 +1063,9 @@ where
         ),
     ),
     #[cfg(feature = "pe")]
-    Pe32((coff::CoffSymbol<'data, 'file>, PhantomData<R>)),
+    Pe32((coff::CoffSymbol<'data, 'file, R>, PhantomData<R>)),
     #[cfg(feature = "pe")]
-    Pe64((coff::CoffSymbol<'data, 'file>, PhantomData<R>)),
+    Pe64((coff::CoffSymbol<'data, 'file, R>, PhantomData<R>)),
     #[cfg(feature = "wasm")]
     Wasm((wasm::WasmSymbol<'data, 'file>, PhantomData<R>)),
 }
index 88ba8eee0e51f80d8a407e5306c1cd2430aca67a..0208878e4ca0c26ac732e12f91bc89996015b648 100644 (file)
@@ -6,7 +6,6 @@ use crate::archive;
 use crate::read::{self, Error, ReadError, ReadRef};
 
 /// The kind of archive format.
-// TODO: Gnu64 and Darwin64 (and Darwin for writing)
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 #[non_exhaustive]
 pub enum ArchiveKind {
@@ -14,8 +13,14 @@ pub enum ArchiveKind {
     Unknown,
     /// The GNU (or System V) archive format.
     Gnu,
+    /// The GNU (or System V) archive format with 64-bit symbol table.
+    Gnu64,
     /// The BSD archive format.
     Bsd,
+    /// The BSD archive format with 64-bit symbol table.
+    ///
+    /// This is used for Darwin.
+    Bsd64,
     /// The Windows COFF archive format.
     Coff,
 }
@@ -54,7 +59,7 @@ impl<'data, R: ReadRef<'data>> ArchiveFile<'data, R> {
 
         // The first few members may be special, so parse them.
         // GNU has:
-        // - "/": symbol table (optional)
+        // - "/" or "/SYM64/": symbol table (optional)
         // - "//": names table (optional)
         // COFF has:
         // - "/": first linker member
@@ -62,6 +67,10 @@ impl<'data, R: ReadRef<'data>> ArchiveFile<'data, R> {
         // - "//": names table
         // BSD has:
         // - "__.SYMDEF" or "__.SYMDEF SORTED": symbol table (optional)
+        // BSD 64-bit has:
+        // - "__.SYMDEF_64" or "__.SYMDEF_64 SORTED": symbol table (optional)
+        // BSD may use the extended name for the symbol table. This is handled
+        // by `ArchiveMember::parse`.
         if tail < len {
             let member = ArchiveMember::parse(data, &mut tail, &[])?;
             if member.name == b"/" {
@@ -92,6 +101,20 @@ impl<'data, R: ReadRef<'data>> ArchiveFile<'data, R> {
                         file.offset = tail;
                     }
                 }
+            } else if member.name == b"/SYM64/" {
+                // GNU 64-bit symbol table.
+                file.kind = ArchiveKind::Gnu64;
+                file.symbols = member.file_range();
+                file.offset = tail;
+
+                if tail < len {
+                    let member = ArchiveMember::parse(data, &mut tail, &[])?;
+                    if member.name == b"//" {
+                        // GNU names table.
+                        file.names = member.data(data)?;
+                        file.offset = tail;
+                    }
+                }
             } else if member.name == b"//" {
                 // GNU names table.
                 file.kind = ArchiveKind::Gnu;
@@ -102,6 +125,11 @@ impl<'data, R: ReadRef<'data>> ArchiveFile<'data, R> {
                 file.kind = ArchiveKind::Bsd;
                 file.symbols = member.file_range();
                 file.offset = tail;
+            } else if member.name == b"__.SYMDEF_64" || member.name == b"__.SYMDEF_64 SORTED" {
+                // BSD 64-bit symbol table.
+                file.kind = ArchiveKind::Bsd64;
+                file.symbols = member.file_range();
+                file.offset = tail;
             } else {
                 // TODO: This could still be a BSD file. We leave this as unknown for now.
             }
@@ -346,6 +374,22 @@ mod tests {
         let archive = ArchiveFile::parse(&data[..]).unwrap();
         assert_eq!(archive.kind(), ArchiveKind::Gnu);
 
+        let data = b"\
+            !<arch>\n\
+            /SYM64/                                         4         `\n\
+            0000";
+        let archive = ArchiveFile::parse(&data[..]).unwrap();
+        assert_eq!(archive.kind(), ArchiveKind::Gnu64);
+
+        let data = b"\
+            !<arch>\n\
+            /SYM64/                                         4         `\n\
+            0000\
+            //                                              4         `\n\
+            0000";
+        let archive = ArchiveFile::parse(&data[..]).unwrap();
+        assert_eq!(archive.kind(), ArchiveKind::Gnu64);
+
         let data = b"\
             !<arch>\n\
             __.SYMDEF                                       4         `\n\
@@ -367,6 +411,27 @@ mod tests {
         let archive = ArchiveFile::parse(&data[..]).unwrap();
         assert_eq!(archive.kind(), ArchiveKind::Bsd);
 
+        let data = b"\
+            !<arch>\n\
+            __.SYMDEF_64                                    4         `\n\
+            0000";
+        let archive = ArchiveFile::parse(&data[..]).unwrap();
+        assert_eq!(archive.kind(), ArchiveKind::Bsd64);
+
+        let data = b"\
+            !<arch>\n\
+            #1/12                                           16        `\n\
+            __.SYMDEF_640000";
+        let archive = ArchiveFile::parse(&data[..]).unwrap();
+        assert_eq!(archive.kind(), ArchiveKind::Bsd64);
+
+        let data = b"\
+            !<arch>\n\
+            #1/19                                           23        `\n\
+            __.SYMDEF_64 SORTED0000";
+        let archive = ArchiveFile::parse(&data[..]).unwrap();
+        assert_eq!(archive.kind(), ArchiveKind::Bsd64);
+
         let data = b"\
             !<arch>\n\
             /                                               4         `\n\
index 3ab92ce25073588095effe9debb4147bca87d8a9..fad2efd9a4a5886e21c60671643feab198eb0e3c 100644 (file)
@@ -15,10 +15,10 @@ use super::{
 
 /// The common parts of `PeFile` and `CoffFile`.
 #[derive(Debug)]
-pub(crate) struct CoffCommon<'data> {
+pub(crate) struct CoffCommon<'data, R: ReadRef<'data>> {
     pub(crate) sections: SectionTable<'data>,
     // TODO: ImageSymbolExBytes
-    pub(crate) symbols: SymbolTable<'data>,
+    pub(crate) symbols: SymbolTable<'data, R>,
     pub(crate) image_base: u64,
 }
 
@@ -26,7 +26,7 @@ pub(crate) struct CoffCommon<'data> {
 #[derive(Debug)]
 pub struct CoffFile<'data, R: ReadRef<'data> = &'data [u8]> {
     pub(super) header: &'data pe::ImageFileHeader,
-    pub(super) common: CoffCommon<'data>,
+    pub(super) common: CoffCommon<'data, R>,
     pub(super) data: R,
 }
 
@@ -63,9 +63,9 @@ where
     type SectionIterator = CoffSectionIterator<'data, 'file, R>;
     type Comdat = CoffComdat<'data, 'file, R>;
     type ComdatIterator = CoffComdatIterator<'data, 'file, R>;
-    type Symbol = CoffSymbol<'data, 'file>;
-    type SymbolIterator = CoffSymbolIterator<'data, 'file>;
-    type SymbolTable = CoffSymbolTable<'data, 'file>;
+    type Symbol = CoffSymbol<'data, 'file, R>;
+    type SymbolIterator = CoffSymbolIterator<'data, 'file, R>;
+    type SymbolTable = CoffSymbolTable<'data, 'file, R>;
     type DynamicRelocationIterator = NoDynamicRelocationIterator;
 
     fn architecture(&self) -> Architecture {
@@ -124,7 +124,7 @@ where
         }
     }
 
-    fn symbol_by_index(&'file self, index: SymbolIndex) -> Result<CoffSymbol<'data, 'file>> {
+    fn symbol_by_index(&'file self, index: SymbolIndex) -> Result<CoffSymbol<'data, 'file, R>> {
         let symbol = self.common.symbols.symbol(index.0)?;
         Ok(CoffSymbol {
             file: &self.common,
@@ -133,7 +133,7 @@ where
         })
     }
 
-    fn symbols(&'file self) -> CoffSymbolIterator<'data, 'file> {
+    fn symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R> {
         CoffSymbolIterator {
             file: &self.common,
             index: 0,
@@ -141,11 +141,11 @@ where
     }
 
     #[inline]
-    fn symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file>> {
+    fn symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R>> {
         Some(CoffSymbolTable { file: &self.common })
     }
 
-    fn dynamic_symbols(&'file self) -> CoffSymbolIterator<'data, 'file> {
+    fn dynamic_symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R> {
         CoffSymbolIterator {
             file: &self.common,
             // Hack: don't return any.
@@ -154,7 +154,7 @@ where
     }
 
     #[inline]
-    fn dynamic_symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file>> {
+    fn dynamic_symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R>> {
         None
     }
 
@@ -232,7 +232,10 @@ impl pe::ImageFileHeader {
     ///
     /// `data` must be the entire file data.
     #[inline]
-    pub fn symbols<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<SymbolTable<'data>> {
+    pub fn symbols<'data, R: ReadRef<'data>>(
+        &self,
+        data: R,
+    ) -> read::Result<SymbolTable<'data, R>> {
         SymbolTable::parse(self, data)
     }
 }
index 29d30969d6b76ada7a845422f9fef18529ab9e21..8762e24902d5e0f96e17ab3c7101910cf38f3b74 100644 (file)
@@ -66,9 +66,9 @@ impl<'data> SectionTable<'data> {
     /// The returned index is 1-based.
     ///
     /// Ignores sections with invalid names.
-    pub fn section_by_name(
+    pub fn section_by_name<R: ReadRef<'data>>(
         &self,
-        strings: StringTable<'data>,
+        strings: StringTable<'data, R>,
         name: &[u8],
     ) -> Option<(usize, &'data pe::ImageSectionHeader)> {
         self.sections
@@ -310,7 +310,10 @@ impl pe::ImageSectionHeader {
     /// Return the section name.
     ///
     /// This handles decoding names that are offsets into the symbol string table.
-    pub fn name<'data>(&'data self, strings: StringTable<'data>) -> Result<&'data [u8]> {
+    pub fn name<'data, R: ReadRef<'data>>(
+        &'data self,
+        strings: StringTable<'data, R>,
+    ) -> Result<&'data [u8]> {
         let bytes = &self.name;
         Ok(if bytes[0] == b'/' {
             let mut offset = 0;
index f638248ac011c7b0deb6c32cba34c3a432ccad0c..5af801f170042f1177c31e2bb16d36a7d00dc06d 100644 (file)
@@ -6,25 +6,28 @@ use core::str;
 use super::{CoffCommon, SectionTable};
 use crate::endian::{LittleEndian as LE, U32Bytes};
 use crate::pe;
-use crate::pod::{bytes_of_slice, Bytes, Pod};
+use crate::pod::{bytes_of_slice, Pod};
 use crate::read::util::StringTable;
 use crate::read::{
-    self, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, Result, SectionIndex, SymbolFlags,
-    SymbolIndex, SymbolKind, SymbolMap, SymbolMapEntry, SymbolScope, SymbolSection,
+    self, Bytes, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, Result, SectionIndex,
+    SymbolFlags, SymbolIndex, SymbolKind, SymbolMap, SymbolMapEntry, SymbolScope, SymbolSection,
 };
 
 /// A table of symbol entries in a COFF or PE file.
 ///
 /// Also includes the string table used for the symbol names.
 #[derive(Debug)]
-pub struct SymbolTable<'data> {
+pub struct SymbolTable<'data, R = &'data [u8]>
+where
+    R: ReadRef<'data>,
+{
     symbols: &'data [pe::ImageSymbolBytes],
-    strings: StringTable<'data>,
+    strings: StringTable<'data, R>,
 }
 
-impl<'data> SymbolTable<'data> {
+impl<'data, R: ReadRef<'data>> SymbolTable<'data, R> {
     /// Read the symbol table.
-    pub fn parse<R: ReadRef<'data>>(header: &pe::ImageFileHeader, data: R) -> Result<Self> {
+    pub fn parse(header: &pe::ImageFileHeader, data: R) -> Result<Self> {
         // The symbol table may not be present.
         let mut offset = header.pointer_to_symbol_table.get(LE).into();
         let (symbols, strings) = if offset != 0 {
@@ -37,24 +40,22 @@ impl<'data> SymbolTable<'data> {
                 .read_at::<U32Bytes<_>>(offset)
                 .read_error("Missing COFF string table")?
                 .get(LE);
-            let strings = data
-                .read_bytes(&mut offset, length.into())
+            let str_end = offset
+                .checked_add(length as u64)
                 .read_error("Invalid COFF string table length")?;
+            let strings = StringTable::new(data, offset, str_end);
 
             (symbols, strings)
         } else {
-            (&[][..], &[][..])
+            (&[][..], StringTable::default())
         };
 
-        Ok(SymbolTable {
-            symbols,
-            strings: StringTable::new(strings),
-        })
+        Ok(SymbolTable { symbols, strings })
     }
 
     /// Return the string table used for the symbol names.
     #[inline]
-    pub fn strings(&self) -> StringTable<'data> {
+    pub fn strings(&self) -> StringTable<'data, R> {
         self.strings
     }
 
@@ -74,7 +75,7 @@ impl<'data> SymbolTable<'data> {
 
     /// Iterate over the symbols.
     #[inline]
-    pub fn iter<'table>(&'table self) -> SymbolIterator<'data, 'table> {
+    pub fn iter<'table>(&'table self) -> SymbolIterator<'data, 'table, R> {
         SymbolIterator {
             symbols: self,
             index: 0,
@@ -153,12 +154,15 @@ impl<'data> SymbolTable<'data> {
 ///
 /// Yields the index and symbol structure for each symbol.
 #[derive(Debug)]
-pub struct SymbolIterator<'data, 'table> {
-    symbols: &'table SymbolTable<'data>,
+pub struct SymbolIterator<'data, 'table, R = &'data [u8]>
+where
+    R: ReadRef<'data>,
+{
+    symbols: &'table SymbolTable<'data, R>,
     index: usize,
 }
 
-impl<'data, 'table> Iterator for SymbolIterator<'data, 'table> {
+impl<'data, 'table, R: ReadRef<'data>> Iterator for SymbolIterator<'data, 'table, R> {
     type Item = (usize, &'data pe::ImageSymbol);
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -173,7 +177,10 @@ impl pe::ImageSymbol {
     /// Parse a COFF symbol name.
     ///
     /// `strings` must be the string table used for symbol names.
-    pub fn name<'data>(&'data self, strings: StringTable<'data>) -> Result<&'data [u8]> {
+    pub fn name<'data, R: ReadRef<'data>>(
+        &'data self,
+        strings: StringTable<'data, R>,
+    ) -> Result<&'data [u8]> {
         if self.name[0] == 0 {
             // If the name starts with 0 then the last 4 bytes are a string table offset.
             let offset = u32::from_le_bytes(self.name[4..8].try_into().unwrap());
@@ -236,15 +243,20 @@ impl pe::ImageSymbol {
 
 /// A symbol table of a `CoffFile`.
 #[derive(Debug, Clone, Copy)]
-pub struct CoffSymbolTable<'data, 'file> {
-    pub(crate) file: &'file CoffCommon<'data>,
+pub struct CoffSymbolTable<'data, 'file, R = &'data [u8]>
+where
+    R: ReadRef<'data>,
+{
+    pub(crate) file: &'file CoffCommon<'data, R>,
 }
 
-impl<'data, 'file> read::private::Sealed for CoffSymbolTable<'data, 'file> {}
+impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for CoffSymbolTable<'data, 'file, R> {}
 
-impl<'data, 'file> ObjectSymbolTable<'data> for CoffSymbolTable<'data, 'file> {
-    type Symbol = CoffSymbol<'data, 'file>;
-    type SymbolIterator = CoffSymbolIterator<'data, 'file>;
+impl<'data, 'file, R: ReadRef<'data>> ObjectSymbolTable<'data>
+    for CoffSymbolTable<'data, 'file, R>
+{
+    type Symbol = CoffSymbol<'data, 'file, R>;
+    type SymbolIterator = CoffSymbolIterator<'data, 'file, R>;
 
     fn symbols(&self) -> Self::SymbolIterator {
         CoffSymbolIterator {
@@ -264,19 +276,22 @@ impl<'data, 'file> ObjectSymbolTable<'data> for CoffSymbolTable<'data, 'file> {
 }
 
 /// An iterator over the symbols of a `CoffFile`.
-pub struct CoffSymbolIterator<'data, 'file> {
-    pub(crate) file: &'file CoffCommon<'data>,
+pub struct CoffSymbolIterator<'data, 'file, R = &'data [u8]>
+where
+    R: ReadRef<'data>,
+{
+    pub(crate) file: &'file CoffCommon<'data, R>,
     pub(crate) index: usize,
 }
 
-impl<'data, 'file> fmt::Debug for CoffSymbolIterator<'data, 'file> {
+impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for CoffSymbolIterator<'data, 'file, R> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("CoffSymbolIterator").finish()
     }
 }
 
-impl<'data, 'file> Iterator for CoffSymbolIterator<'data, 'file> {
-    type Item = CoffSymbol<'data, 'file>;
+impl<'data, 'file, R: ReadRef<'data>> Iterator for CoffSymbolIterator<'data, 'file, R> {
+    type Item = CoffSymbol<'data, 'file, R>;
 
     fn next(&mut self) -> Option<Self::Item> {
         let index = self.index;
@@ -292,15 +307,18 @@ impl<'data, 'file> Iterator for CoffSymbolIterator<'data, 'file> {
 
 /// A symbol of a `CoffFile`.
 #[derive(Debug, Clone, Copy)]
-pub struct CoffSymbol<'data, 'file> {
-    pub(crate) file: &'file CoffCommon<'data>,
+pub struct CoffSymbol<'data, 'file, R = &'data [u8]>
+where
+    R: ReadRef<'data>,
+{
+    pub(crate) file: &'file CoffCommon<'data, R>,
     pub(crate) index: SymbolIndex,
     pub(crate) symbol: &'data pe::ImageSymbol,
 }
 
-impl<'data, 'file> read::private::Sealed for CoffSymbol<'data, 'file> {}
+impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for CoffSymbol<'data, 'file, R> {}
 
-impl<'data, 'file> ObjectSymbol<'data> for CoffSymbol<'data, 'file> {
+impl<'data, 'file, R: ReadRef<'data>> ObjectSymbol<'data> for CoffSymbol<'data, 'file, R> {
     #[inline]
     fn index(&self) -> SymbolIndex {
         self.index
index e877e9f4cda6dc3e340e2cc0563618807732723d..91273ca4181b60b3b30744600e58f17bf494bc7a 100644 (file)
@@ -4,10 +4,10 @@ use core::fmt::Debug;
 use core::{mem, str};
 
 use crate::read::{
-    self, util, Architecture, Error, Export, FileFlags, Import, Object, ReadError, ReadRef,
-    SectionIndex, StringTable, SymbolIndex,
+    self, util, Architecture, ByteString, Bytes, Error, Export, FileFlags, Import, Object,
+    ReadError, ReadRef, SectionIndex, StringTable, SymbolIndex,
 };
-use crate::{elf, endian, ByteString, Bytes, Endian, Endianness, Pod, U32};
+use crate::{elf, endian, Endian, Endianness, Pod, U32};
 
 use super::{
     CompressionHeader, Dyn, ElfComdat, ElfComdatIterator, ElfDynamicRelocationIterator, ElfSection,
@@ -36,10 +36,10 @@ where
     pub(super) data: R,
     pub(super) header: &'data Elf,
     pub(super) segments: &'data [Elf::ProgramHeader],
-    pub(super) sections: SectionTable<'data, Elf>,
+    pub(super) sections: SectionTable<'data, Elf, R>,
     pub(super) relocations: RelocationSections,
-    pub(super) symbols: SymbolTable<'data, Elf>,
-    pub(super) dynamic_symbols: SymbolTable<'data, Elf>,
+    pub(super) symbols: SymbolTable<'data, Elf, R>,
+    pub(super) dynamic_symbols: SymbolTable<'data, Elf, R>,
 }
 
 impl<'data, Elf, R> ElfFile<'data, Elf, R>
@@ -143,9 +143,9 @@ where
     type SectionIterator = ElfSectionIterator<'data, 'file, Elf, R>;
     type Comdat = ElfComdat<'data, 'file, Elf, R>;
     type ComdatIterator = ElfComdatIterator<'data, 'file, Elf, R>;
-    type Symbol = ElfSymbol<'data, 'file, Elf>;
-    type SymbolIterator = ElfSymbolIterator<'data, 'file, Elf>;
-    type SymbolTable = ElfSymbolTable<'data, 'file, Elf>;
+    type Symbol = ElfSymbol<'data, 'file, Elf, R>;
+    type SymbolIterator = ElfSymbolIterator<'data, 'file, Elf, R>;
+    type SymbolTable = ElfSymbolTable<'data, 'file, Elf, R>;
     type DynamicRelocationIterator = ElfDynamicRelocationIterator<'data, 'file, Elf, R>;
 
     fn architecture(&self) -> Architecture {
@@ -230,7 +230,7 @@ where
     fn symbol_by_index(
         &'file self,
         index: SymbolIndex,
-    ) -> read::Result<ElfSymbol<'data, 'file, Elf>> {
+    ) -> read::Result<ElfSymbol<'data, 'file, Elf, R>> {
         let symbol = self.symbols.symbol(index.0)?;
         Ok(ElfSymbol {
             endian: self.endian,
@@ -240,7 +240,7 @@ where
         })
     }
 
-    fn symbols(&'file self) -> ElfSymbolIterator<'data, 'file, Elf> {
+    fn symbols(&'file self) -> ElfSymbolIterator<'data, 'file, Elf, R> {
         ElfSymbolIterator {
             endian: self.endian,
             symbols: &self.symbols,
@@ -248,14 +248,14 @@ where
         }
     }
 
-    fn symbol_table(&'file self) -> Option<ElfSymbolTable<'data, 'file, Elf>> {
+    fn symbol_table(&'file self) -> Option<ElfSymbolTable<'data, 'file, Elf, R>> {
         Some(ElfSymbolTable {
             endian: self.endian,
             symbols: &self.symbols,
         })
     }
 
-    fn dynamic_symbols(&'file self) -> ElfSymbolIterator<'data, 'file, Elf> {
+    fn dynamic_symbols(&'file self) -> ElfSymbolIterator<'data, 'file, Elf, R> {
         ElfSymbolIterator {
             endian: self.endian,
             symbols: &self.dynamic_symbols,
@@ -263,7 +263,7 @@ where
         }
     }
 
-    fn dynamic_symbol_table(&'file self) -> Option<ElfSymbolTable<'data, 'file, Elf>> {
+    fn dynamic_symbol_table(&'file self) -> Option<ElfSymbolTable<'data, 'file, Elf, R>> {
         Some(ElfSymbolTable {
             endian: self.endian,
             symbols: &self.dynamic_symbols,
@@ -646,16 +646,21 @@ pub trait FileHeader: Debug + Pod {
         endian: Self::Endian,
         data: R,
         sections: &[Self::SectionHeader],
-    ) -> read::Result<StringTable<'data>> {
+    ) -> read::Result<StringTable<'data, R>> {
         if sections.is_empty() {
             return Ok(StringTable::default());
         }
         let index = self.shstrndx(endian, data)? as usize;
         let shstrtab = sections.get(index).read_error("Invalid ELF e_shstrndx")?;
-        let data = shstrtab
-            .data(endian, data)
-            .read_error("Invalid ELF shstrtab data")?;
-        Ok(StringTable::new(data))
+        let strings = if let Some((shstrtab_offset, shstrtab_size)) = shstrtab.file_range(endian) {
+            let shstrtab_end = shstrtab_offset
+                .checked_add(shstrtab_size)
+                .read_error("Invalid ELF shstrtab size")?;
+            StringTable::new(data, shstrtab_offset, shstrtab_end)
+        } else {
+            StringTable::default()
+        };
+        Ok(strings)
     }
 
     /// Return the section table.
@@ -663,7 +668,7 @@ pub trait FileHeader: Debug + Pod {
         &self,
         endian: Self::Endian,
         data: R,
-    ) -> read::Result<SectionTable<'data, Self>> {
+    ) -> read::Result<SectionTable<'data, Self, R>> {
         let sections = self.section_headers(endian, data)?;
         let strings = self.section_strings(endian, data, sections)?;
         Ok(SectionTable::new(sections, strings))
diff --git a/vendor/object/src/read/elf/hash.rs b/vendor/object/src/read/elf/hash.rs
new file mode 100644 (file)
index 0000000..fab484e
--- /dev/null
@@ -0,0 +1,211 @@
+use core::mem;
+
+use crate::elf;
+use crate::read::{ReadError, ReadRef, Result};
+use crate::{U32, U64};
+
+use super::{FileHeader, Sym, SymbolTable};
+
+/// A SysV symbol hash table in an ELF file.
+#[derive(Debug)]
+pub struct HashTable<'data, Elf: FileHeader> {
+    buckets: &'data [U32<Elf::Endian>],
+    chains: &'data [U32<Elf::Endian>],
+}
+
+impl<'data, Elf: FileHeader> HashTable<'data, Elf> {
+    /// Parse a SysV hash table.
+    ///
+    /// `data` should be from a `SHT_HASH` section, or from a
+    /// segment pointed to via the `DT_HASH` entry.
+    ///
+    /// The header is read at offset 0 in the given `data`.
+    pub fn parse(endian: Elf::Endian, data: &'data [u8]) -> Result<Self> {
+        let mut offset = 0;
+        let header = data
+            .read::<elf::HashHeader<Elf::Endian>>(&mut offset)
+            .read_error("Invalid hash header")?;
+        let buckets = data
+            .read_slice(&mut offset, header.bucket_count.get(endian) as usize)
+            .read_error("Invalid hash buckets")?;
+        let chains = data
+            .read_slice(&mut offset, header.chain_count.get(endian) as usize)
+            .read_error("Invalid hash chains")?;
+        Ok(HashTable { buckets, chains })
+    }
+
+    /// Return the symbol table length.
+    pub fn symbol_table_length(&self) -> u32 {
+        self.chains.len() as u32
+    }
+
+    /// Use the hash table to find the symbol table entry with the given name and hash.
+    pub fn find<R: ReadRef<'data>>(
+        &self,
+        endian: Elf::Endian,
+        name: &[u8],
+        hash: u32,
+        symbols: &SymbolTable<'data, Elf, R>,
+    ) -> Option<&'data Elf::Sym> {
+        // Get the chain start from the bucket for this hash.
+        let mut index = self.buckets[(hash as usize) % self.buckets.len()].get(endian) as usize;
+        // Avoid infinite loop.
+        let mut i = 0;
+        let strings = symbols.strings();
+        while index != 0 && i < self.chains.len() {
+            if let Ok(symbol) = symbols.symbol(index) {
+                if symbol.name(endian, strings) == Ok(name) {
+                    return Some(symbol);
+                }
+            }
+            index = self.chains.get(index)?.get(endian) as usize;
+            i += 1;
+        }
+        None
+    }
+}
+
+/// A GNU symbol hash table in an ELF file.
+#[derive(Debug)]
+pub struct GnuHashTable<'data, Elf: FileHeader> {
+    symbol_base: u32,
+    bloom_shift: u32,
+    bloom_filters: &'data [u8],
+    buckets: &'data [U32<Elf::Endian>],
+    values: &'data [U32<Elf::Endian>],
+}
+
+impl<'data, Elf: FileHeader> GnuHashTable<'data, Elf> {
+    /// Parse a GNU hash table.
+    ///
+    /// `data` should be from a `SHT_GNU_HASH` section, or from a
+    /// segment pointed to via the `DT_GNU_HASH` entry.
+    ///
+    /// The header is read at offset 0 in the given `data`.
+    ///
+    /// The header does not contain a length field, and so all of `data`
+    /// will be used as the hash table values. It does not matter if this
+    /// is longer than needed, and this will often the case when accessing
+    /// the hash table via the `DT_GNU_HASH` entry.
+    pub fn parse(endian: Elf::Endian, data: &'data [u8]) -> Result<Self> {
+        let mut offset = 0;
+        let header = data
+            .read::<elf::GnuHashHeader<Elf::Endian>>(&mut offset)
+            .read_error("Invalid GNU hash header")?;
+        let bloom_len =
+            u64::from(header.bloom_count.get(endian)) * mem::size_of::<Elf::Word>() as u64;
+        let bloom_filters = data
+            .read_bytes(&mut offset, bloom_len)
+            .read_error("Invalid GNU hash bloom filters")?;
+        let buckets = data
+            .read_slice(&mut offset, header.bucket_count.get(endian) as usize)
+            .read_error("Invalid GNU hash buckets")?;
+        let chain_count = (data.len() - offset as usize) / 4;
+        let values = data
+            .read_slice(&mut offset, chain_count)
+            .read_error("Invalid GNU hash values")?;
+        Ok(GnuHashTable {
+            symbol_base: header.symbol_base.get(endian),
+            bloom_shift: header.bloom_shift.get(endian),
+            bloom_filters,
+            buckets,
+            values,
+        })
+    }
+
+    /// Return the symbol table index of the first symbol in the hash table.
+    pub fn symbol_base(&self) -> u32 {
+        self.symbol_base
+    }
+
+    /// Determine the symbol table length by finding the last entry in the hash table.
+    ///
+    /// Returns `None` if the hash table is empty or invalid.
+    pub fn symbol_table_length(&self, endian: Elf::Endian) -> Option<u32> {
+        // Ensure we find a non-empty bucket.
+        if self.symbol_base == 0 {
+            return None;
+        }
+
+        // Find the highest chain index in a bucket.
+        let mut max_symbol = 0;
+        for bucket in self.buckets {
+            let bucket = bucket.get(endian);
+            if max_symbol < bucket {
+                max_symbol = bucket;
+            }
+        }
+
+        // Find the end of the chain.
+        for value in self
+            .values
+            .get(max_symbol.checked_sub(self.symbol_base)? as usize..)?
+        {
+            max_symbol += 1;
+            if value.get(endian) & 1 != 0 {
+                return Some(max_symbol);
+            }
+        }
+
+        None
+    }
+
+    /// Use the hash table to find the symbol table entry with the given name and hash.
+    pub fn find<R: ReadRef<'data>>(
+        &self,
+        endian: Elf::Endian,
+        name: &[u8],
+        hash: u32,
+        symbols: &SymbolTable<'data, Elf, R>,
+    ) -> Option<&'data Elf::Sym> {
+        let word_bits = mem::size_of::<Elf::Word>() as u32 * 8;
+
+        // Test against bloom filter.
+        let bloom_count = self.bloom_filters.len() / mem::size_of::<Elf::Word>();
+        let offset =
+            ((hash / word_bits) & (bloom_count as u32 - 1)) * mem::size_of::<Elf::Word>() as u32;
+        let filter = if word_bits == 64 {
+            self.bloom_filters
+                .read_at::<U64<Elf::Endian>>(offset.into())
+                .ok()?
+                .get(endian)
+        } else {
+            self.bloom_filters
+                .read_at::<U32<Elf::Endian>>(offset.into())
+                .ok()?
+                .get(endian)
+                .into()
+        };
+        if filter & (1 << (hash % word_bits)) == 0 {
+            return None;
+        }
+        if filter & (1 << ((hash >> self.bloom_shift) % word_bits)) == 0 {
+            return None;
+        }
+
+        // Get the chain start from the bucket for this hash.
+        let index = self.buckets[(hash as usize) % self.buckets.len()].get(endian) as usize;
+        if index == 0 {
+            return None;
+        }
+
+        // Test symbols in the chain.
+        let strings = symbols.strings();
+        let symbols = symbols.symbols().get(index..)?;
+        let values = self
+            .values
+            .get(index.checked_sub(self.symbol_base as usize)?..)?;
+        for (symbol, value) in symbols.iter().zip(values.iter()) {
+            let value = value.get(endian);
+            if value | 1 == hash | 1 {
+                if symbol.name(endian, strings) == Ok(name) {
+                    return Some(symbol);
+                }
+            }
+            if value & 1 != 0 {
+                break;
+            }
+        }
+        None
+    }
+}
index ff6039a43e12a537661b0d7734f06eb04975044e..5b7d7f9f7f61e90401680dbad8ae8c4d0a1e6a81 100644 (file)
@@ -31,3 +31,9 @@ pub use compression::*;
 
 mod note;
 pub use note::*;
+
+mod hash;
+pub use hash::*;
+
+mod version;
+pub use version::*;
index 8f5cb5acba916e049e291fdb587bfe4fcd6f843e..34024dbb896504891f1beaa45aa4c13503389dea 100644 (file)
@@ -3,9 +3,9 @@ use core::mem;
 
 use crate::elf;
 use crate::endian;
-use crate::pod::{Bytes, Pod};
+use crate::pod::Pod;
 use crate::read::util;
-use crate::read::{self, Error, ReadError};
+use crate::read::{self, Bytes, Error, ReadError};
 
 use super::FileHeader;
 
index 6017d509088cb4fde119235cefeabfbc6a03cf92..d3e24b2e8db00b6f5c8dfe99fc0bbb30a1f9b561 100644 (file)
@@ -23,9 +23,9 @@ impl RelocationSections {
     /// Create a new mapping using the section table.
     ///
     /// Skips relocation sections that do not use the given symbol table section.
-    pub fn parse<Elf: FileHeader>(
+    pub fn parse<'data, Elf: FileHeader, R: ReadRef<'data>>(
         endian: Elf::Endian,
-        sections: &SectionTable<Elf>,
+        sections: &SectionTable<'data, Elf, R>,
         symbol_section: usize,
     ) -> read::Result<Self> {
         let mut relocations = vec![0; sections.len()];
@@ -247,6 +247,10 @@ fn parse_relocation<Elf: FileHeader>(
             elf::R_AARCH64_PREL64 => (RelocationKind::Relative, 64),
             elf::R_AARCH64_PREL32 => (RelocationKind::Relative, 32),
             elf::R_AARCH64_PREL16 => (RelocationKind::Relative, 16),
+            elf::R_AARCH64_CALL26 => {
+                encoding = RelocationEncoding::AArch64Call;
+                (RelocationKind::PltRelative, 26)
+            }
             r_type => (RelocationKind::Elf(r_type), 0),
         },
         elf::EM_ARM => match reloc.r_type(endian, false) {
index edbd10cb0290e71dcbdc4a44cc97c1990a773ce9..5d8999229751c5c8af6412174dab24b5bcf3ce46 100644 (file)
@@ -3,30 +3,33 @@ use core::{iter, mem, slice, str};
 
 use crate::elf;
 use crate::endian::{self, Endianness, U32Bytes};
-use crate::pod::{Bytes, Pod};
+use crate::pod::Pod;
 use crate::read::{
-    self, CompressedData, CompressedFileRange, CompressionFormat, Error, ObjectSection, ReadError,
-    ReadRef, SectionFlags, SectionIndex, SectionKind, StringTable,
+    self, Bytes, CompressedData, CompressedFileRange, CompressionFormat, Error, ObjectSection,
+    ReadError, ReadRef, SectionFlags, SectionIndex, SectionKind, StringTable,
 };
 
 use super::{
-    CompressionHeader, ElfFile, ElfSectionRelocationIterator, FileHeader, NoteIterator,
-    RelocationSections, SymbolTable,
+    CompressionHeader, ElfFile, ElfSectionRelocationIterator, FileHeader, GnuHashTable, HashTable,
+    NoteIterator, RelocationSections, SymbolTable, VerdefIterator, VerneedIterator,
 };
 
 /// The table of section headers in an ELF file.
 ///
 /// Also includes the string table used for the section names.
 #[derive(Debug, Default, Clone, Copy)]
-pub struct SectionTable<'data, Elf: FileHeader> {
+pub struct SectionTable<'data, Elf: FileHeader, R = &'data [u8]>
+where
+    R: ReadRef<'data>,
+{
     sections: &'data [Elf::SectionHeader],
-    strings: StringTable<'data>,
+    strings: StringTable<'data, R>,
 }
 
-impl<'data, Elf: FileHeader> SectionTable<'data, Elf> {
+impl<'data, Elf: FileHeader, R: ReadRef<'data>> SectionTable<'data, Elf, R> {
     /// Create a new section table.
     #[inline]
-    pub fn new(sections: &'data [Elf::SectionHeader], strings: StringTable<'data>) -> Self {
+    pub fn new(sections: &'data [Elf::SectionHeader], strings: StringTable<'data, R>) -> Self {
         SectionTable { sections, strings }
     }
 
@@ -82,12 +85,12 @@ impl<'data, Elf: FileHeader> SectionTable<'data, Elf> {
     ///
     /// Returns an empty symbol table if the symbol table does not exist.
     #[inline]
-    pub fn symbols<R: ReadRef<'data>>(
+    pub fn symbols(
         &self,
         endian: Elf::Endian,
         data: R,
         sh_type: u32,
-    ) -> read::Result<SymbolTable<'data, Elf>> {
+    ) -> read::Result<SymbolTable<'data, Elf, R>> {
         debug_assert!(sh_type == elf::SHT_DYNSYM || sh_type == elf::SHT_SYMTAB);
 
         let (index, section) = match self
@@ -106,12 +109,12 @@ impl<'data, Elf: FileHeader> SectionTable<'data, Elf> {
     ///
     /// Returns an error if the section is not a symbol table.
     #[inline]
-    pub fn symbol_table_by_index<R: ReadRef<'data>>(
+    pub fn symbol_table_by_index(
         &self,
         endian: Elf::Endian,
         data: R,
         index: usize,
-    ) -> read::Result<SymbolTable<'data, Elf>> {
+    ) -> read::Result<SymbolTable<'data, Elf, R>> {
         let section = self.section(index)?;
         match section.sh_type(endian) {
             elf::SHT_DYNSYM | elf::SHT_SYMTAB => {}
@@ -129,6 +132,125 @@ impl<'data, Elf: FileHeader> SectionTable<'data, Elf> {
     ) -> read::Result<RelocationSections> {
         RelocationSections::parse(endian, self, symbol_section)
     }
+
+    /// Return the header of a SysV hash section.
+    ///
+    /// Returns `Ok(None)` if there is no SysV GNU hash section.
+    /// Returns `Err` for invalid values.
+    pub fn hash_header(
+        &self,
+        endian: Elf::Endian,
+        data: R,
+    ) -> read::Result<Option<&'data elf::HashHeader<Elf::Endian>>> {
+        for section in self.sections {
+            if let Some(hash) = section.hash_header(endian, data)? {
+                return Ok(Some(hash));
+            }
+        }
+        Ok(None)
+    }
+
+    /// Return the contents of a SysV hash section.
+    ///
+    /// Returns `Ok(None)` if there is no SysV hash section.
+    /// Returns `Err` for invalid values.
+    pub fn hash(
+        &self,
+        endian: Elf::Endian,
+        data: R,
+    ) -> read::Result<Option<HashTable<'data, Elf>>> {
+        for section in self.sections {
+            if let Some(hash) = section.hash(endian, data)? {
+                return Ok(Some(hash));
+            }
+        }
+        Ok(None)
+    }
+
+    /// Return the header of a GNU hash section.
+    ///
+    /// Returns `Ok(None)` if there is no GNU hash section.
+    /// Returns `Err` for invalid values.
+    pub fn gnu_hash_header(
+        &self,
+        endian: Elf::Endian,
+        data: R,
+    ) -> read::Result<Option<&'data elf::GnuHashHeader<Elf::Endian>>> {
+        for section in self.sections {
+            if let Some(hash) = section.gnu_hash_header(endian, data)? {
+                return Ok(Some(hash));
+            }
+        }
+        Ok(None)
+    }
+
+    /// Return the contents of a GNU hash section.
+    ///
+    /// Returns `Ok(None)` if there is no GNU hash section.
+    /// Returns `Err` for invalid values.
+    pub fn gnu_hash(
+        &self,
+        endian: Elf::Endian,
+        data: R,
+    ) -> read::Result<Option<GnuHashTable<'data, Elf>>> {
+        for section in self.sections {
+            if let Some(hash) = section.gnu_hash(endian, data)? {
+                return Ok(Some(hash));
+            }
+        }
+        Ok(None)
+    }
+
+    /// Return the contents of a `SHT_GNU_VERSYM` section.
+    ///
+    /// Returns `Ok(None)` if there is no `SHT_GNU_VERSYM` section.
+    /// Returns `Err` for invalid values.
+    pub fn gnu_versym(
+        &self,
+        endian: Elf::Endian,
+        data: R,
+    ) -> read::Result<Option<&'data [elf::Versym<Elf::Endian>]>> {
+        for section in self.sections {
+            if let Some(syms) = section.gnu_versym(endian, data)? {
+                return Ok(Some(syms));
+            }
+        }
+        Ok(None)
+    }
+
+    /// Return the contents of a `SHT_GNU_VERDEF` section.
+    ///
+    /// Returns `Ok(None)` if there is no `SHT_GNU_VERDEF` section.
+    /// Returns `Err` for invalid values.
+    pub fn gnu_verdef(
+        &self,
+        endian: Elf::Endian,
+        data: R,
+    ) -> read::Result<Option<VerdefIterator<'data, Elf>>> {
+        for section in self.sections {
+            if let Some(defs) = section.gnu_verdef(endian, data)? {
+                return Ok(Some(defs));
+            }
+        }
+        Ok(None)
+    }
+
+    /// Return the contents of a `SHT_GNU_VERNEED` section.
+    ///
+    /// Returns `Ok(None)` if there is no `SHT_GNU_VERNEED` section.
+    /// Returns `Err` for invalid values.
+    pub fn gnu_verneed(
+        &self,
+        endian: Elf::Endian,
+        data: R,
+    ) -> read::Result<Option<VerneedIterator<'data, Elf>>> {
+        for section in self.sections {
+            if let Some(needs) = section.gnu_verneed(endian, data)? {
+                return Ok(Some(needs));
+            }
+        }
+        Ok(None)
+    }
 }
 
 /// An iterator over the sections of an `ElfFile32`.
@@ -425,10 +547,10 @@ pub trait SectionHeader: Debug + Pod {
     fn sh_entsize(&self, endian: Self::Endian) -> Self::Word;
 
     /// Parse the section name from the string table.
-    fn name<'data>(
+    fn name<'data, R: ReadRef<'data>>(
         &self,
         endian: Self::Endian,
-        strings: StringTable<'data>,
+        strings: StringTable<'data, R>,
     ) -> read::Result<&'data [u8]> {
         strings
             .get(self.sh_name(endian))
@@ -454,9 +576,10 @@ pub trait SectionHeader: Debug + Pod {
         &self,
         endian: Self::Endian,
         data: R,
-    ) -> Result<&'data [u8], ()> {
+    ) -> read::Result<&'data [u8]> {
         if let Some((offset, size)) = self.file_range(endian) {
             data.read_bytes_at(offset, size)
+                .read_error("Invalid ELF section size or offset")
         } else {
             Ok(&[])
         }
@@ -471,9 +594,10 @@ pub trait SectionHeader: Debug + Pod {
         &self,
         endian: Self::Endian,
         data: R,
-    ) -> Result<&'data [T], ()> {
+    ) -> read::Result<&'data [T]> {
         let mut data = self.data(endian, data).map(Bytes)?;
         data.read_slice(data.len() / mem::size_of::<T>())
+            .read_error("Invalid ELF section size or offset")
     }
 
     /// Return the symbols in the section.
@@ -489,9 +613,9 @@ pub trait SectionHeader: Debug + Pod {
         &self,
         endian: Self::Endian,
         data: R,
-        sections: &SectionTable<Self::Elf>,
+        sections: &SectionTable<'data, Self::Elf, R>,
         section_index: usize,
-    ) -> read::Result<Option<SymbolTable<'data, Self::Elf>>> {
+    ) -> read::Result<Option<SymbolTable<'data, Self::Elf, R>>> {
         let sh_type = self.sh_type(endian);
         if sh_type != elf::SHT_SYMTAB && sh_type != elf::SHT_DYNSYM {
             return Ok(None);
@@ -541,8 +665,8 @@ pub trait SectionHeader: Debug + Pod {
         &self,
         endian: Self::Endian,
         data: R,
-        sections: &SectionTable<'data, Self::Elf>,
-    ) -> read::Result<SymbolTable<'data, Self::Elf>> {
+        sections: &SectionTable<'data, Self::Elf, R>,
+    ) -> read::Result<SymbolTable<'data, Self::Elf, R>> {
         let sh_type = self.sh_type(endian);
         if sh_type != elf::SHT_REL && sh_type != elf::SHT_RELA {
             return Err(Error("Invalid ELF relocation section type"));
@@ -598,6 +722,139 @@ pub trait SectionHeader: Debug + Pod {
             .read_error("Invalid ELF group section offset or size")?;
         Ok(Some((flag, sections)))
     }
+
+    /// Return the header of a SysV hash section.
+    ///
+    /// Returns `Ok(None)` if the section does not contain a SysV hash.
+    /// Returns `Err` for invalid values.
+    fn hash_header<'data, R: ReadRef<'data>>(
+        &self,
+        endian: Self::Endian,
+        data: R,
+    ) -> read::Result<Option<&'data elf::HashHeader<Self::Endian>>> {
+        if self.sh_type(endian) != elf::SHT_HASH {
+            return Ok(None);
+        }
+        let data = self
+            .data(endian, data)
+            .read_error("Invalid ELF hash section offset or size")?;
+        let header = data
+            .read_at::<elf::HashHeader<Self::Endian>>(0)
+            .read_error("Invalid hash header")?;
+        Ok(Some(header))
+    }
+
+    /// Return the contents of a SysV hash section.
+    ///
+    /// Returns `Ok(None)` if the section does not contain a SysV hash.
+    /// Returns `Err` for invalid values.
+    fn hash<'data, R: ReadRef<'data>>(
+        &self,
+        endian: Self::Endian,
+        data: R,
+    ) -> read::Result<Option<HashTable<'data, Self::Elf>>> {
+        if self.sh_type(endian) != elf::SHT_HASH {
+            return Ok(None);
+        }
+        let data = self
+            .data(endian, data)
+            .read_error("Invalid ELF hash section offset or size")?;
+        let hash = HashTable::parse(endian, data)?;
+        Ok(Some(hash))
+    }
+
+    /// Return the header of a GNU hash section.
+    ///
+    /// Returns `Ok(None)` if the section does not contain a GNU hash.
+    /// Returns `Err` for invalid values.
+    fn gnu_hash_header<'data, R: ReadRef<'data>>(
+        &self,
+        endian: Self::Endian,
+        data: R,
+    ) -> read::Result<Option<&'data elf::GnuHashHeader<Self::Endian>>> {
+        if self.sh_type(endian) != elf::SHT_GNU_HASH {
+            return Ok(None);
+        }
+        let data = self
+            .data(endian, data)
+            .read_error("Invalid ELF GNU hash section offset or size")?;
+        let header = data
+            .read_at::<elf::GnuHashHeader<Self::Endian>>(0)
+            .read_error("Invalid GNU hash header")?;
+        Ok(Some(header))
+    }
+
+    /// Return the contents of a GNU hash section.
+    ///
+    /// Returns `Ok(None)` if the section does not contain a GNU hash.
+    /// Returns `Err` for invalid values.
+    fn gnu_hash<'data, R: ReadRef<'data>>(
+        &self,
+        endian: Self::Endian,
+        data: R,
+    ) -> read::Result<Option<GnuHashTable<'data, Self::Elf>>> {
+        if self.sh_type(endian) != elf::SHT_GNU_HASH {
+            return Ok(None);
+        }
+        let data = self
+            .data(endian, data)
+            .read_error("Invalid ELF GNU hash section offset or size")?;
+        let hash = GnuHashTable::parse(endian, data)?;
+        Ok(Some(hash))
+    }
+
+    /// Return the contents of a `SHT_GNU_VERSYM` section.
+    ///
+    /// Returns `Ok(None)` if the section type is not `SHT_GNU_VERSYM`.
+    /// Returns `Err` for invalid values.
+    fn gnu_versym<'data, R: ReadRef<'data>>(
+        &self,
+        endian: Self::Endian,
+        data: R,
+    ) -> read::Result<Option<&'data [elf::Versym<Self::Endian>]>> {
+        if self.sh_type(endian) != elf::SHT_GNU_VERSYM {
+            return Ok(None);
+        }
+        self.data_as_array(endian, data)
+            .read_error("Invalid ELF GNU versym section offset or size")
+            .map(Some)
+    }
+
+    /// Return an iterator for the entries of a `SHT_GNU_VERDEF` section.
+    ///
+    /// Returns `Ok(None)` if the section type is not `SHT_GNU_VERDEF`.
+    /// Returns `Err` for invalid values.
+    fn gnu_verdef<'data, R: ReadRef<'data>>(
+        &self,
+        endian: Self::Endian,
+        data: R,
+    ) -> read::Result<Option<VerdefIterator<'data, Self::Elf>>> {
+        if self.sh_type(endian) != elf::SHT_GNU_VERDEF {
+            return Ok(None);
+        }
+        let data = self
+            .data_as_array(endian, data)
+            .read_error("Invalid ELF GNU verdef section offset or size")?;
+        Ok(Some(VerdefIterator::new(endian, data)))
+    }
+
+    /// Return an iterator for the entries of a `SHT_GNU_VERNEED` section.
+    ///
+    /// Returns `Ok(None)` if the section type is not `SHT_GNU_VERNEED`.
+    /// Returns `Err` for invalid values.
+    fn gnu_verneed<'data, R: ReadRef<'data>>(
+        &self,
+        endian: Self::Endian,
+        data: R,
+    ) -> read::Result<Option<VerneedIterator<'data, Self::Elf>>> {
+        if self.sh_type(endian) != elf::SHT_GNU_VERNEED {
+            return Ok(None);
+        }
+        let data = self
+            .data_as_array(endian, data)
+            .read_error("Invalid ELF GNU verneed section offset or size")?;
+        Ok(Some(VerneedIterator::new(endian, data)))
+    }
 }
 
 impl<Endian: endian::Endian> SectionHeader for elf::SectionHeader32<Endian> {
index b75b39341547cb70e916c8612186de00f0d1d065..70528b59a1cecd6699020120a73216ab01c2768c 100644 (file)
@@ -3,8 +3,8 @@ use core::{mem, slice, str};
 
 use crate::elf;
 use crate::endian::{self, Endianness};
-use crate::pod::{Bytes, Pod};
-use crate::read::{self, ObjectSegment, ReadError, ReadRef};
+use crate::pod::Pod;
+use crate::read::{self, Bytes, ObjectSegment, ReadError, ReadRef};
 
 use super::{ElfFile, FileHeader, NoteIterator};
 
index 91a1349e5168efb6fde0f5a7099c334c4a2a8438..ff2ed199ad8d4671403a5ecbb61372a90562902f 100644 (file)
@@ -19,14 +19,17 @@ use super::{FileHeader, SectionHeader, SectionTable};
 ///
 /// Also includes the string table used for the symbol names.
 #[derive(Debug, Clone, Copy)]
-pub struct SymbolTable<'data, Elf: FileHeader> {
+pub struct SymbolTable<'data, Elf: FileHeader, R = &'data [u8]>
+where
+    R: ReadRef<'data>,
+{
     section: usize,
     symbols: &'data [Elf::Sym],
-    strings: StringTable<'data>,
+    strings: StringTable<'data, R>,
     shndx: &'data [u32],
 }
 
-impl<'data, Elf: FileHeader> Default for SymbolTable<'data, Elf> {
+impl<'data, Elf: FileHeader, R: ReadRef<'data>> Default for SymbolTable<'data, Elf, R> {
     fn default() -> Self {
         SymbolTable {
             section: 0,
@@ -37,15 +40,15 @@ impl<'data, Elf: FileHeader> Default for SymbolTable<'data, Elf> {
     }
 }
 
-impl<'data, Elf: FileHeader> SymbolTable<'data, Elf> {
+impl<'data, Elf: FileHeader, R: ReadRef<'data>> SymbolTable<'data, Elf, R> {
     /// Parse the given symbol table section.
-    pub fn parse<R: ReadRef<'data>>(
+    pub fn parse(
         endian: Elf::Endian,
         data: R,
-        sections: &SectionTable<Elf>,
+        sections: &SectionTable<'data, Elf, R>,
         section_index: usize,
         section: &Elf::SectionHeader,
-    ) -> read::Result<SymbolTable<'data, Elf>> {
+    ) -> read::Result<SymbolTable<'data, Elf, R>> {
         debug_assert!(
             section.sh_type(endian) == elf::SHT_DYNSYM
                 || section.sh_type(endian) == elf::SHT_SYMTAB
@@ -56,10 +59,14 @@ impl<'data, Elf: FileHeader> SymbolTable<'data, Elf> {
             .read_error("Invalid ELF symbol table data")?;
 
         let strtab = sections.section(section.sh_link(endian) as usize)?;
-        let strtab_data = strtab
-            .data(endian, data)
-            .read_error("Invalid ELF string table data")?;
-        let strings = StringTable::new(strtab_data);
+        let strings = if let Some((str_offset, str_size)) = strtab.file_range(endian) {
+            let str_end = str_offset
+                .checked_add(str_size)
+                .read_error("Invalid str_size")?;
+            StringTable::new(data, str_offset, str_end)
+        } else {
+            StringTable::default()
+        };
 
         let shndx = sections
             .iter()
@@ -91,10 +98,16 @@ impl<'data, Elf: FileHeader> SymbolTable<'data, Elf> {
 
     /// Return the string table used for the symbol names.
     #[inline]
-    pub fn strings(&self) -> StringTable<'data> {
+    pub fn strings(&self) -> StringTable<'data, R> {
         self.strings
     }
 
+    /// Return the symbol table.
+    #[inline]
+    pub fn symbols(&self) -> &'data [Elf::Sym] {
+        self.symbols
+    }
+
     /// Iterate over the symbols.
     #[inline]
     pub fn iter(&self) -> slice::Iter<'data, Elf::Sym> {
@@ -155,28 +168,34 @@ impl<'data, Elf: FileHeader> SymbolTable<'data, Elf> {
 }
 
 /// A symbol table of an `ElfFile32`.
-pub type ElfSymbolTable32<'data, 'file, Endian = Endianness> =
-    ElfSymbolTable<'data, 'file, elf::FileHeader32<Endian>>;
+pub type ElfSymbolTable32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
+    ElfSymbolTable<'data, 'file, elf::FileHeader32<Endian>, R>;
 /// A symbol table of an `ElfFile32`.
-pub type ElfSymbolTable64<'data, 'file, Endian = Endianness> =
-    ElfSymbolTable<'data, 'file, elf::FileHeader64<Endian>>;
+pub type ElfSymbolTable64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
+    ElfSymbolTable<'data, 'file, elf::FileHeader64<Endian>, R>;
 
 /// A symbol table of an `ElfFile`.
 #[derive(Debug, Clone, Copy)]
-pub struct ElfSymbolTable<'data, 'file, Elf>
+pub struct ElfSymbolTable<'data, 'file, Elf, R = &'data [u8]>
 where
     'data: 'file,
     Elf: FileHeader,
+    R: ReadRef<'data>,
 {
     pub(super) endian: Elf::Endian,
-    pub(super) symbols: &'file SymbolTable<'data, Elf>,
+    pub(super) symbols: &'file SymbolTable<'data, Elf, R>,
 }
 
-impl<'data, 'file, Elf: FileHeader> read::private::Sealed for ElfSymbolTable<'data, 'file, Elf> {}
+impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> read::private::Sealed
+    for ElfSymbolTable<'data, 'file, Elf, R>
+{
+}
 
-impl<'data, 'file, Elf: FileHeader> ObjectSymbolTable<'data> for ElfSymbolTable<'data, 'file, Elf> {
-    type Symbol = ElfSymbol<'data, 'file, Elf>;
-    type SymbolIterator = ElfSymbolIterator<'data, 'file, Elf>;
+impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ObjectSymbolTable<'data>
+    for ElfSymbolTable<'data, 'file, Elf, R>
+{
+    type Symbol = ElfSymbol<'data, 'file, Elf, R>;
+    type SymbolIterator = ElfSymbolIterator<'data, 'file, Elf, R>;
 
     fn symbols(&self) -> Self::SymbolIterator {
         ElfSymbolIterator {
@@ -198,31 +217,36 @@ impl<'data, 'file, Elf: FileHeader> ObjectSymbolTable<'data> for ElfSymbolTable<
 }
 
 /// An iterator over the symbols of an `ElfFile32`.
-pub type ElfSymbolIterator32<'data, 'file, Endian = Endianness> =
-    ElfSymbolIterator<'data, 'file, elf::FileHeader32<Endian>>;
+pub type ElfSymbolIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
+    ElfSymbolIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
 /// An iterator over the symbols of an `ElfFile64`.
-pub type ElfSymbolIterator64<'data, 'file, Endian = Endianness> =
-    ElfSymbolIterator<'data, 'file, elf::FileHeader64<Endian>>;
+pub type ElfSymbolIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
+    ElfSymbolIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
 
 /// An iterator over the symbols of an `ElfFile`.
-pub struct ElfSymbolIterator<'data, 'file, Elf>
+pub struct ElfSymbolIterator<'data, 'file, Elf, R = &'data [u8]>
 where
     'data: 'file,
     Elf: FileHeader,
+    R: ReadRef<'data>,
 {
     pub(super) endian: Elf::Endian,
-    pub(super) symbols: &'file SymbolTable<'data, Elf>,
+    pub(super) symbols: &'file SymbolTable<'data, Elf, R>,
     pub(super) index: usize,
 }
 
-impl<'data, 'file, Elf: FileHeader> fmt::Debug for ElfSymbolIterator<'data, 'file, Elf> {
+impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> fmt::Debug
+    for ElfSymbolIterator<'data, 'file, Elf, R>
+{
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("ElfSymbolIterator").finish()
     }
 }
 
-impl<'data, 'file, Elf: FileHeader> Iterator for ElfSymbolIterator<'data, 'file, Elf> {
-    type Item = ElfSymbol<'data, 'file, Elf>;
+impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> Iterator
+    for ElfSymbolIterator<'data, 'file, Elf, R>
+{
+    type Item = ElfSymbol<'data, 'file, Elf, R>;
 
     fn next(&mut self) -> Option<Self::Item> {
         let index = self.index;
@@ -238,28 +262,34 @@ impl<'data, 'file, Elf: FileHeader> Iterator for ElfSymbolIterator<'data, 'file,
 }
 
 /// A symbol of an `ElfFile32`.
-pub type ElfSymbol32<'data, 'file, Endian = Endianness> =
-    ElfSymbol<'data, 'file, elf::FileHeader32<Endian>>;
+pub type ElfSymbol32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
+    ElfSymbol<'data, 'file, elf::FileHeader32<Endian>, R>;
 /// A symbol of an `ElfFile64`.
-pub type ElfSymbol64<'data, 'file, Endian = Endianness> =
-    ElfSymbol<'data, 'file, elf::FileHeader64<Endian>>;
+pub type ElfSymbol64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
+    ElfSymbol<'data, 'file, elf::FileHeader64<Endian>, R>;
 
 /// A symbol of an `ElfFile`.
 #[derive(Debug, Clone, Copy)]
-pub struct ElfSymbol<'data, 'file, Elf>
+pub struct ElfSymbol<'data, 'file, Elf, R = &'data [u8]>
 where
     'data: 'file,
     Elf: FileHeader,
+    R: ReadRef<'data>,
 {
     pub(super) endian: Elf::Endian,
-    pub(super) symbols: &'file SymbolTable<'data, Elf>,
+    pub(super) symbols: &'file SymbolTable<'data, Elf, R>,
     pub(super) index: SymbolIndex,
     pub(super) symbol: &'data Elf::Sym,
 }
 
-impl<'data, 'file, Elf: FileHeader> read::private::Sealed for ElfSymbol<'data, 'file, Elf> {}
+impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> read::private::Sealed
+    for ElfSymbol<'data, 'file, Elf, R>
+{
+}
 
-impl<'data, 'file, Elf: FileHeader> ObjectSymbol<'data> for ElfSymbol<'data, 'file, Elf> {
+impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ObjectSymbol<'data>
+    for ElfSymbol<'data, 'file, Elf, R>
+{
     #[inline]
     fn index(&self) -> SymbolIndex {
         self.index
@@ -390,10 +420,10 @@ pub trait Sym: Debug + Pod {
     fn st_size(&self, endian: Self::Endian) -> Self::Word;
 
     /// Parse the symbol name from the string table.
-    fn name<'data>(
+    fn name<'data, R: ReadRef<'data>>(
         &self,
         endian: Self::Endian,
-        strings: StringTable<'data>,
+        strings: StringTable<'data, R>,
     ) -> read::Result<&'data [u8]> {
         strings
             .get(self.st_name(endian))
diff --git a/vendor/object/src/read/elf/version.rs b/vendor/object/src/read/elf/version.rs
new file mode 100644 (file)
index 0000000..099e27a
--- /dev/null
@@ -0,0 +1,175 @@
+use crate::elf;
+use crate::read::{Bytes, ReadError, Result};
+
+use super::FileHeader;
+
+/// An iterator over the entries in an ELF `SHT_GNU_verdef` section.
+#[derive(Debug, Clone)]
+pub struct VerdefIterator<'data, Elf: FileHeader> {
+    endian: Elf::Endian,
+    data: Bytes<'data>,
+}
+
+impl<'data, Elf: FileHeader> VerdefIterator<'data, Elf> {
+    pub(super) fn new(endian: Elf::Endian, data: &'data [u8]) -> Self {
+        VerdefIterator {
+            endian,
+            data: Bytes(data),
+        }
+    }
+
+    /// Return the next `Verdef` entry.
+    pub fn next(
+        &mut self,
+    ) -> Result<Option<(&'data elf::Verdef<Elf::Endian>, VerdauxIterator<'data, Elf>)>> {
+        if self.data.is_empty() {
+            return Ok(None);
+        }
+
+        let verdef = self
+            .data
+            .read_at::<elf::Verdef<_>>(0)
+            .read_error("ELF verdef is too short")?;
+
+        let mut verdaux_data = self.data;
+        verdaux_data
+            .skip(verdef.vd_aux.get(self.endian) as usize)
+            .read_error("Invalid ELF vd_aux")?;
+        let verdaux =
+            VerdauxIterator::new(self.endian, verdaux_data.0, verdef.vd_cnt.get(self.endian));
+
+        let next = verdef.vd_next.get(self.endian);
+        if next != 0 {
+            self.data
+                .skip(next as usize)
+                .read_error("Invalid ELF vd_next")?;
+        } else {
+            self.data = Bytes(&[]);
+        }
+        Ok(Some((verdef, verdaux)))
+    }
+}
+
+/// An iterator over the auxiliary records for an entry in an ELF `SHT_GNU_verdef` section.
+#[derive(Debug, Clone)]
+pub struct VerdauxIterator<'data, Elf: FileHeader> {
+    endian: Elf::Endian,
+    data: Bytes<'data>,
+    count: u16,
+}
+
+impl<'data, Elf: FileHeader> VerdauxIterator<'data, Elf> {
+    pub(super) fn new(endian: Elf::Endian, data: &'data [u8], count: u16) -> Self {
+        VerdauxIterator {
+            endian,
+            data: Bytes(data),
+            count,
+        }
+    }
+
+    /// Return the next `Verdaux` entry.
+    pub fn next(&mut self) -> Result<Option<&'data elf::Verdaux<Elf::Endian>>> {
+        if self.count == 0 {
+            return Ok(None);
+        }
+
+        let verdaux = self
+            .data
+            .read_at::<elf::Verdaux<_>>(0)
+            .read_error("ELF verdaux is too short")?;
+
+        self.data
+            .skip(verdaux.vda_next.get(self.endian) as usize)
+            .read_error("Invalid ELF vda_next")?;
+        self.count -= 1;
+        Ok(Some(verdaux))
+    }
+}
+
+/// An iterator over the entries in an ELF `SHT_GNU_verneed` section.
+#[derive(Debug, Clone)]
+pub struct VerneedIterator<'data, Elf: FileHeader> {
+    endian: Elf::Endian,
+    data: Bytes<'data>,
+}
+
+impl<'data, Elf: FileHeader> VerneedIterator<'data, Elf> {
+    pub(super) fn new(endian: Elf::Endian, data: &'data [u8]) -> Self {
+        VerneedIterator {
+            endian,
+            data: Bytes(data),
+        }
+    }
+
+    /// Return the next `Verneed` entry.
+    pub fn next(
+        &mut self,
+    ) -> Result<
+        Option<(
+            &'data elf::Verneed<Elf::Endian>,
+            VernauxIterator<'data, Elf>,
+        )>,
+    > {
+        if self.data.is_empty() {
+            return Ok(None);
+        }
+
+        let verneed = self
+            .data
+            .read_at::<elf::Verneed<_>>(0)
+            .read_error("ELF verneed is too short")?;
+
+        let mut vernaux_data = self.data;
+        vernaux_data
+            .skip(verneed.vn_aux.get(self.endian) as usize)
+            .read_error("Invalid ELF vn_aux")?;
+        let vernaux =
+            VernauxIterator::new(self.endian, vernaux_data.0, verneed.vn_cnt.get(self.endian));
+
+        let next = verneed.vn_next.get(self.endian);
+        if next != 0 {
+            self.data
+                .skip(next as usize)
+                .read_error("Invalid ELF vn_next")?;
+        } else {
+            self.data = Bytes(&[]);
+        }
+        Ok(Some((verneed, vernaux)))
+    }
+}
+
+/// An iterator over the auxiliary records for an entry in an ELF `SHT_GNU_verneed` section.
+#[derive(Debug, Clone)]
+pub struct VernauxIterator<'data, Elf: FileHeader> {
+    endian: Elf::Endian,
+    data: Bytes<'data>,
+    count: u16,
+}
+
+impl<'data, Elf: FileHeader> VernauxIterator<'data, Elf> {
+    pub(super) fn new(endian: Elf::Endian, data: &'data [u8], count: u16) -> Self {
+        VernauxIterator {
+            endian,
+            data: Bytes(data),
+            count,
+        }
+    }
+
+    /// Return the next `Vernaux` entry.
+    pub fn next(&mut self) -> Result<Option<&'data elf::Vernaux<Elf::Endian>>> {
+        if self.count == 0 {
+            return Ok(None);
+        }
+
+        let vernaux = self
+            .data
+            .read_at::<elf::Vernaux<_>>(0)
+            .read_error("ELF vernaux is too short")?;
+
+        self.data
+            .skip(vernaux.vna_next.get(self.endian) as usize)
+            .read_error("Invalid ELF vna_next")?;
+        self.count -= 1;
+        Ok(Some(vernaux))
+    }
+}
index b1e4b9a4c8acc76eb63964be2be2c26ec5359761..ee758ce0c2c1bf02f85a7e09d8c2a7738b4fc4ed 100644 (file)
@@ -192,7 +192,9 @@ impl<E: Endian> macho::DyldCacheHeader<E> {
 impl<E: Endian> macho::DyldCacheImageInfo<E> {
     /// The file system path of this image.
     pub fn path<'data, R: ReadRef<'data>>(&self, endian: E, data: R) -> Result<&'data [u8]> {
-        data.read_bytes_at_until(self.path_file_offset.get(endian).into(), 0)
+        let r_start = self.path_file_offset.get(endian).into();
+        let r_end = data.len().read_error("Couldn't get data len()")?;
+        data.read_bytes_at_until(r_start..r_end, 0)
             .read_error("Couldn't read dyld cache image path")
     }
 
index 8b2803922887c983c6e811e4d1973d8f45f62fc1..54ae2d83e4b2d2e2f345173d6ccc7120ff6c3e1a 100644 (file)
@@ -36,7 +36,7 @@ where
     pub(super) header_offset: u64,
     pub(super) header: &'data Mach,
     pub(super) sections: Vec<MachOSectionInternal<'data, Mach>>,
-    pub(super) symbols: SymbolTable<'data, Mach>,
+    pub(super) symbols: SymbolTable<'data, Mach, R>,
 }
 
 impl<'data, Mach, R> MachOFile<'data, Mach, R>
index 91e6649a2a009e145743323824bab58fb758c9b5..29fab6e0ed8267c810cc31028b99445113c972d0 100644 (file)
@@ -2,9 +2,9 @@ use core::marker::PhantomData;
 
 use crate::endian::Endian;
 use crate::macho;
-use crate::pod::{Bytes, Pod};
+use crate::pod::Pod;
 use crate::read::macho::{MachHeader, SymbolTable};
-use crate::read::{ReadError, ReadRef, Result, StringTable};
+use crate::read::{Bytes, ReadError, ReadRef, Result, StringTable};
 
 /// An iterator over the load commands of a `MachHeader`.
 #[derive(Debug, Default, Clone, Copy)]
@@ -331,20 +331,18 @@ impl<E: Endian> macho::SymtabCommand<E> {
         &self,
         endian: E,
         data: R,
-    ) -> Result<SymbolTable<'data, Mach>> {
+    ) -> Result<SymbolTable<'data, Mach, R>> {
         let symbols = data
             .read_slice_at(
                 self.symoff.get(endian).into(),
                 self.nsyms.get(endian) as usize,
             )
             .read_error("Invalid Mach-O symbol table offset or size")?;
-        let strings = data
-            .read_bytes_at(
-                self.stroff.get(endian).into(),
-                self.strsize.get(endian).into(),
-            )
-            .read_error("Invalid Mach-O string table offset or size")?;
-        let strings = StringTable::new(strings);
+        let str_start: u64 = self.stroff.get(endian).into();
+        let str_end = str_start
+            .checked_add(self.strsize.get(endian).into())
+            .read_error("Invalid Mach-O string table length")?;
+        let strings = StringTable::new(data, str_start, str_end);
         Ok(SymbolTable::new(symbols, strings))
     }
 }
index 686cc79c33e7f3f46422a46d5512a95d895b4b9e..1528d52ebf63aa0427422e471f57a6d15ff7ebb9 100644 (file)
@@ -18,12 +18,15 @@ use super::{MachHeader, MachOFile};
 ///
 /// Also includes the string table used for the symbol names.
 #[derive(Debug, Clone, Copy)]
-pub struct SymbolTable<'data, Mach: MachHeader> {
+pub struct SymbolTable<'data, Mach: MachHeader, R = &'data [u8]>
+where
+    R: ReadRef<'data>,
+{
     symbols: &'data [Mach::Nlist],
-    strings: StringTable<'data>,
+    strings: StringTable<'data, R>,
 }
 
-impl<'data, Mach: MachHeader> Default for SymbolTable<'data, Mach> {
+impl<'data, Mach: MachHeader, R: ReadRef<'data>> Default for SymbolTable<'data, Mach, R> {
     fn default() -> Self {
         SymbolTable {
             symbols: &[],
@@ -32,15 +35,15 @@ impl<'data, Mach: MachHeader> Default for SymbolTable<'data, Mach> {
     }
 }
 
-impl<'data, Mach: MachHeader> SymbolTable<'data, Mach> {
+impl<'data, Mach: MachHeader, R: ReadRef<'data>> SymbolTable<'data, Mach, R> {
     #[inline]
-    pub(super) fn new(symbols: &'data [Mach::Nlist], strings: StringTable<'data>) -> Self {
+    pub(super) fn new(symbols: &'data [Mach::Nlist], strings: StringTable<'data, R>) -> Self {
         SymbolTable { symbols, strings }
     }
 
     /// Return the string table used for the symbol names.
     #[inline]
-    pub fn strings(&self) -> StringTable<'data> {
+    pub fn strings(&self) -> StringTable<'data, R> {
         self.strings
     }
 
@@ -401,10 +404,10 @@ pub trait Nlist: Debug + Pod {
     fn n_desc(&self, endian: Self::Endian) -> u16;
     fn n_value(&self, endian: Self::Endian) -> Self::Word;
 
-    fn name<'data>(
+    fn name<'data, R: ReadRef<'data>>(
         &self,
         endian: Self::Endian,
-        strings: StringTable<'data>,
+        strings: StringTable<'data, R>,
     ) -> Result<&'data [u8]> {
         strings
             .get(self.n_strx(endian))
index 856ed4d84c6772b71bb848408dd92edf44aaf0df..75814eef657e64cd5b3032b14b176f01bba59f31 100644 (file)
@@ -5,7 +5,6 @@ use alloc::vec::Vec;
 use core::{fmt, result};
 
 use crate::common::*;
-use crate::ByteString;
 
 mod read_ref;
 pub use read_ref::*;
@@ -16,7 +15,7 @@ mod read_cache;
 pub use read_cache::*;
 
 mod util;
-pub use util::StringTable;
+pub use util::*;
 
 #[cfg(any(
     feature = "coff",
@@ -87,6 +86,12 @@ impl<T> ReadError<T> for result::Result<T, ()> {
     }
 }
 
+impl<T> ReadError<T> for result::Result<T, Error> {
+    fn read_error(self, error: &'static str) -> Result<T> {
+        self.map_err(|_| Error(error))
+    }
+}
+
 impl<T> ReadError<T> for Option<T> {
     fn read_error(self, error: &'static str) -> Result<T> {
         self.ok_or(Error(error))
index 3fb4920b7a7c5e1a990ec154a3d9d91305027a48..429db9b70e2dcc683a564e5b6c98c24dd9448c8e 100644 (file)
@@ -30,7 +30,7 @@ where
     pub(super) dos_header: &'data pe::ImageDosHeader,
     pub(super) nt_headers: &'data Pe,
     pub(super) data_directories: &'data [pe::ImageDataDirectory],
-    pub(super) common: CoffCommon<'data>,
+    pub(super) common: CoffCommon<'data, R>,
     pub(super) data: R,
 }
 
@@ -75,7 +75,13 @@ where
         self.nt_headers
     }
 
-    fn data_directory(&self, id: usize) -> Option<&'data pe::ImageDataDirectory> {
+    /// Returns the section table of this binary.
+    pub fn section_table(&self) -> SectionTable<'data> {
+        self.common.sections
+    }
+
+    /// Returns the data directory at the given index.
+    pub fn data_directory(&self, id: usize) -> Option<&'data pe::ImageDataDirectory> {
         self.data_directories
             .get(id)
             .filter(|d| d.size.get(LE) != 0)
@@ -84,6 +90,11 @@ where
     fn data_at(&self, va: u32) -> Option<Bytes<'data>> {
         self.common.sections.pe_data_at(self.data, va).map(Bytes)
     }
+
+    /// Returns this binary data.
+    pub fn data(&self) -> R {
+        self.data
+    }
 }
 
 impl<'data, Pe, R> read::private::Sealed for PeFile<'data, Pe, R>
@@ -105,9 +116,9 @@ where
     type SectionIterator = PeSectionIterator<'data, 'file, Pe, R>;
     type Comdat = PeComdat<'data, 'file, Pe, R>;
     type ComdatIterator = PeComdatIterator<'data, 'file, Pe, R>;
-    type Symbol = CoffSymbol<'data, 'file>;
-    type SymbolIterator = CoffSymbolIterator<'data, 'file>;
-    type SymbolTable = CoffSymbolTable<'data, 'file>;
+    type Symbol = CoffSymbol<'data, 'file, R>;
+    type SymbolIterator = CoffSymbolIterator<'data, 'file, R>;
+    type SymbolTable = CoffSymbolTable<'data, 'file, R>;
     type DynamicRelocationIterator = NoDynamicRelocationIterator;
 
     fn architecture(&self) -> Architecture {
@@ -172,7 +183,7 @@ where
         PeComdatIterator { file: self }
     }
 
-    fn symbol_by_index(&'file self, index: SymbolIndex) -> Result<CoffSymbol<'data, 'file>> {
+    fn symbol_by_index(&'file self, index: SymbolIndex) -> Result<CoffSymbol<'data, 'file, R>> {
         let symbol = self.common.symbols.symbol(index.0)?;
         Ok(CoffSymbol {
             file: &self.common,
@@ -181,18 +192,18 @@ where
         })
     }
 
-    fn symbols(&'file self) -> CoffSymbolIterator<'data, 'file> {
+    fn symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R> {
         CoffSymbolIterator {
             file: &self.common,
             index: 0,
         }
     }
 
-    fn symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file>> {
+    fn symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R>> {
         Some(CoffSymbolTable { file: &self.common })
     }
 
-    fn dynamic_symbols(&'file self) -> CoffSymbolIterator<'data, 'file> {
+    fn dynamic_symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R> {
         CoffSymbolIterator {
             file: &self.common,
             // Hack: don't return any.
@@ -200,7 +211,7 @@ where
         }
     }
 
-    fn dynamic_symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file>> {
+    fn dynamic_symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R>> {
         None
     }
 
@@ -636,7 +647,7 @@ pub trait ImageNtHeaders: Debug + Pod {
     ///
     /// `data` must be the entire file data.
     #[inline]
-    fn symbols<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<SymbolTable<'data>> {
+    fn symbols<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<SymbolTable<'data, R>> {
         SymbolTable::parse(self.file_header(), data)
     }
 }
index c36fbbce8bf5ef0419e433d0e54bcefa0ac8beff..32e0a825d7b1f81816a3f50764c512f88a6d7d0d 100644 (file)
@@ -25,7 +25,7 @@ where
     R: ReadRef<'data>,
 {
     pub(super) file: &'file PeFile<'data, Pe, R>,
-    pub(super) iter: slice::Iter<'file, pe::ImageSectionHeader>,
+    pub(super) iter: slice::Iter<'data, pe::ImageSectionHeader>,
 }
 
 impl<'data, 'file, Pe, R> Iterator for PeSegmentIterator<'data, 'file, Pe, R>
@@ -58,7 +58,7 @@ where
     R: ReadRef<'data>,
 {
     file: &'file PeFile<'data, Pe, R>,
-    section: &'file pe::ImageSectionHeader,
+    section: &'data pe::ImageSectionHeader,
 }
 
 impl<'data, 'file, Pe, R> PeSegment<'data, 'file, Pe, R>
@@ -146,7 +146,7 @@ where
     R: ReadRef<'data>,
 {
     pub(super) file: &'file PeFile<'data, Pe, R>,
-    pub(super) iter: iter::Enumerate<slice::Iter<'file, pe::ImageSectionHeader>>,
+    pub(super) iter: iter::Enumerate<slice::Iter<'data, pe::ImageSectionHeader>>,
 }
 
 impl<'data, 'file, Pe, R> Iterator for PeSectionIterator<'data, 'file, Pe, R>
@@ -182,7 +182,7 @@ where
 {
     pub(super) file: &'file PeFile<'data, Pe, R>,
     pub(super) index: SectionIndex,
-    pub(super) section: &'file pe::ImageSectionHeader,
+    pub(super) section: &'data pe::ImageSectionHeader,
 }
 
 impl<'data, 'file, Pe, R> PeSection<'data, 'file, Pe, R>
index 1eaacf697319665476bd87c6151324c7a6cb39b4..19a98a44da45d7c5315731137b837810644a5796 100644 (file)
@@ -1,3 +1,4 @@
+use core::ops::Range;
 use std::boxed::Box;
 use std::cell::RefCell;
 use std::collections::hash_map::Entry;
@@ -90,19 +91,25 @@ impl<'a, R: Read + Seek> ReadRef<'a> for &'a ReadCache<R> {
         Ok(unsafe { mem::transmute::<&[u8], &[u8]>(buf) })
     }
 
-    fn read_bytes_at_until(self, offset: u64, delimiter: u8) -> Result<&'a [u8], ()> {
+    fn read_bytes_at_until(self, range: Range<u64>, delimiter: u8) -> Result<&'a [u8], ()> {
         let cache = &mut *self.cache.borrow_mut();
-        let buf = match cache.strings.entry((offset, delimiter)) {
+        let buf = match cache.strings.entry((range.start, delimiter)) {
             Entry::Occupied(entry) => entry.into_mut(),
             Entry::Vacant(entry) => {
                 cache
                     .read
-                    .seek(SeekFrom::Start(offset as u64))
+                    .seek(SeekFrom::Start(range.start))
                     .map_err(|_| ())?;
+
+                let max_check: usize = (range.end - range.start).try_into().map_err(|_| ())?;
+                // Strings should be relatively small.
+                // TODO: make this configurable?
+                let max_check = max_check.min(4096);
+
                 let mut bytes = Vec::new();
                 let mut checked = 0;
                 loop {
-                    bytes.resize(checked + 256, 0);
+                    bytes.resize((checked + 256).min(max_check), 0);
                     let read = cache.read.read(&mut bytes[checked..]).map_err(|_| ())?;
                     if read == 0 {
                         return Err(());
@@ -112,9 +119,7 @@ impl<'a, R: Read + Seek> ReadRef<'a> for &'a ReadCache<R> {
                         break entry.insert(bytes.into_boxed_slice());
                     }
                     checked += read;
-                    // Strings should be relatively small.
-                    // TODO: make this configurable?
-                    if checked > 4096 {
+                    if checked >= max_check {
                         return Err(());
                     }
                 }
@@ -166,11 +171,12 @@ impl<'a, R: Read + Seek> ReadRef<'a> for ReadCacheRange<'a, R> {
         self.r.read_bytes_at(r_offset, size)
     }
 
-    fn read_bytes_at_until(self, offset: u64, delimiter: u8) -> Result<&'a [u8], ()> {
-        let r_offset = self.offset.checked_add(offset).ok_or(())?;
-        let bytes = self.r.read_bytes_at_until(r_offset, delimiter)?;
+    fn read_bytes_at_until(self, range: Range<u64>, delimiter: u8) -> Result<&'a [u8], ()> {
+        let r_start = self.offset.checked_add(range.start).ok_or(())?;
+        let r_end = self.offset.checked_add(range.end).ok_or(())?;
+        let bytes = self.r.read_bytes_at_until(r_start..r_end, delimiter)?;
         let size = bytes.len().try_into().map_err(|_| ())?;
-        let end = offset.checked_add(size).ok_or(())?;
+        let end = range.start.checked_add(size).ok_or(())?;
         if end > self.size {
             return Err(());
         }
index 55f58755c8e2194b9e7d2ce698bd1623f33babec..2f547a4e2c46403cd7015c16b31ccbd7f35412cc 100644 (file)
@@ -1,6 +1,7 @@
 #![allow(clippy::len_without_is_empty)]
 
 use core::convert::TryInto;
+use core::ops::Range;
 use core::{mem, result};
 
 use crate::pod::{from_bytes, slice_from_bytes, Pod};
@@ -42,13 +43,13 @@ pub trait ReadRef<'a>: Clone + Copy {
     /// Returns an error if offset or size are out of bounds.
     fn read_bytes_at(self, offset: u64, size: u64) -> Result<&'a [u8]>;
 
-    /// Get a reference to a delimited `u8` slice at the given offset.
+    /// Get a reference to a delimited `u8` slice which starts at range.start.
     ///
     /// Does not include the delimiter.
     ///
-    /// Returns an error if offset is out of bounds or the delimiter is
-    /// not found.
-    fn read_bytes_at_until(self, offset: u64, delimiter: u8) -> Result<&'a [u8]>;
+    /// Returns an error if the range is out of bounds or the delimiter is
+    /// not found in the range.
+    fn read_bytes_at_until(self, range: Range<u64>, delimiter: u8) -> Result<&'a [u8]>;
 
     /// Get a reference to a `u8` slice at the given offset, and update the offset.
     ///
@@ -121,9 +122,10 @@ impl<'a> ReadRef<'a> for &'a [u8] {
         self.get(offset..).ok_or(())?.get(..size).ok_or(())
     }
 
-    fn read_bytes_at_until(self, offset: u64, delimiter: u8) -> Result<&'a [u8]> {
-        let offset: usize = offset.try_into().map_err(|_| ())?;
-        let bytes = self.get(offset..).ok_or(())?;
+    fn read_bytes_at_until(self, range: Range<u64>, delimiter: u8) -> Result<&'a [u8]> {
+        let start: usize = range.start.try_into().map_err(|_| ())?;
+        let end: usize = range.end.try_into().map_err(|_| ())?;
+        let bytes = self.get(start..end).ok_or(())?;
         match memchr::memchr(delimiter, bytes) {
             Some(len) => {
                 // This will never fail.
index 1e303bc2ffb6bf8b2a018446aeedbabd290549dc..842bd6ca16b73da24be6b92d119837789f6d2f4c 100644 (file)
@@ -1,6 +1,211 @@
+use alloc::string::String;
 use core::convert::TryInto;
+use core::fmt;
+use core::marker::PhantomData;
 
-use crate::pod::Bytes;
+use crate::pod::{from_bytes, slice_from_bytes, Pod};
+use crate::ReadRef;
+
+/// A newtype for byte slices.
+///
+/// It has these important features:
+/// - no methods that can panic, such as `Index`
+/// - convenience methods for `Pod` types
+/// - a useful `Debug` implementation
+#[derive(Default, Clone, Copy, PartialEq, Eq)]
+pub struct Bytes<'data>(pub &'data [u8]);
+
+impl<'data> fmt::Debug for Bytes<'data> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        debug_list_bytes(self.0, fmt)
+    }
+}
+
+impl<'data> Bytes<'data> {
+    /// Return the length of the byte slice.
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.0.len()
+    }
+
+    /// Return true if the byte slice is empty.
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.0.is_empty()
+    }
+
+    /// Skip over the given number of bytes at the start of the byte slice.
+    ///
+    /// Modifies the byte slice to start after the bytes.
+    ///
+    /// Returns an error if there are too few bytes.
+    #[inline]
+    pub fn skip(&mut self, offset: usize) -> Result<(), ()> {
+        match self.0.get(offset..) {
+            Some(tail) => {
+                self.0 = tail;
+                Ok(())
+            }
+            None => {
+                self.0 = &[];
+                Err(())
+            }
+        }
+    }
+
+    /// Return a reference to the given number of bytes at the start of the byte slice.
+    ///
+    /// Modifies the byte slice to start after the bytes.
+    ///
+    /// Returns an error if there are too few bytes.
+    #[inline]
+    pub fn read_bytes(&mut self, count: usize) -> Result<Bytes<'data>, ()> {
+        match (self.0.get(..count), self.0.get(count..)) {
+            (Some(head), Some(tail)) => {
+                self.0 = tail;
+                Ok(Bytes(head))
+            }
+            _ => {
+                self.0 = &[];
+                Err(())
+            }
+        }
+    }
+
+    /// Return a reference to the given number of bytes at the given offset of the byte slice.
+    ///
+    /// Returns an error if the offset is invalid or there are too few bytes.
+    #[inline]
+    pub fn read_bytes_at(mut self, offset: usize, count: usize) -> Result<Bytes<'data>, ()> {
+        self.skip(offset)?;
+        self.read_bytes(count)
+    }
+
+    /// Return a reference to a `Pod` struct at the start of the byte slice.
+    ///
+    /// Modifies the byte slice to start after the bytes.
+    ///
+    /// Returns an error if there are too few bytes or the slice is incorrectly aligned.
+    #[inline]
+    pub fn read<T: Pod>(&mut self) -> Result<&'data T, ()> {
+        match from_bytes(self.0) {
+            Ok((value, tail)) => {
+                self.0 = tail;
+                Ok(value)
+            }
+            Err(()) => {
+                self.0 = &[];
+                Err(())
+            }
+        }
+    }
+
+    /// Return a reference to a `Pod` struct at the given offset of the byte slice.
+    ///
+    /// Returns an error if there are too few bytes or the offset is incorrectly aligned.
+    #[inline]
+    pub fn read_at<T: Pod>(mut self, offset: usize) -> Result<&'data T, ()> {
+        self.skip(offset)?;
+        self.read()
+    }
+
+    /// Return a reference to a slice of `Pod` structs at the start of the byte slice.
+    ///
+    /// Modifies the byte slice to start after the bytes.
+    ///
+    /// Returns an error if there are too few bytes or the offset is incorrectly aligned.
+    #[inline]
+    pub fn read_slice<T: Pod>(&mut self, count: usize) -> Result<&'data [T], ()> {
+        match slice_from_bytes(self.0, count) {
+            Ok((value, tail)) => {
+                self.0 = tail;
+                Ok(value)
+            }
+            Err(()) => {
+                self.0 = &[];
+                Err(())
+            }
+        }
+    }
+
+    /// Return a reference to a slice of `Pod` structs at the given offset of the byte slice.
+    ///
+    /// Returns an error if there are too few bytes or the offset is incorrectly aligned.
+    #[inline]
+    pub fn read_slice_at<T: Pod>(mut self, offset: usize, count: usize) -> Result<&'data [T], ()> {
+        self.skip(offset)?;
+        self.read_slice(count)
+    }
+
+    /// Read a null terminated string.
+    ///
+    /// Does not assume any encoding.
+    /// Reads past the null byte, but doesn't return it.
+    #[inline]
+    pub fn read_string(&mut self) -> Result<&'data [u8], ()> {
+        match memchr::memchr(b'\0', self.0) {
+            Some(null) => {
+                // These will never fail.
+                let bytes = self.read_bytes(null)?;
+                self.skip(1)?;
+                Ok(bytes.0)
+            }
+            None => {
+                self.0 = &[];
+                Err(())
+            }
+        }
+    }
+
+    /// Read a null terminated string at an offset.
+    ///
+    /// Does not assume any encoding. Does not return the null byte.
+    #[inline]
+    pub fn read_string_at(mut self, offset: usize) -> Result<&'data [u8], ()> {
+        self.skip(offset)?;
+        self.read_string()
+    }
+}
+
+// Only for Debug impl of `Bytes`.
+fn debug_list_bytes(bytes: &[u8], fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+    let mut list = fmt.debug_list();
+    list.entries(bytes.iter().take(8).copied().map(DebugByte));
+    if bytes.len() > 8 {
+        list.entry(&DebugLen(bytes.len()));
+    }
+    list.finish()
+}
+
+struct DebugByte(u8);
+
+impl fmt::Debug for DebugByte {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(fmt, "0x{:02x}", self.0)
+    }
+}
+
+struct DebugLen(usize);
+
+impl fmt::Debug for DebugLen {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(fmt, "...; {}", self.0)
+    }
+}
+
+/// A newtype for byte strings.
+///
+/// For byte slices that are strings of an unknown encoding.
+///
+/// Provides a `Debug` implementation that interprets the bytes as UTF-8.
+#[derive(Default, Clone, Copy, PartialEq, Eq)]
+pub(crate) struct ByteString<'data>(pub &'data [u8]);
+
+impl<'data> fmt::Debug for ByteString<'data> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(fmt, "\"{}\"", String::from_utf8_lossy(self.0))
+    }
+}
 
 #[allow(dead_code)]
 #[inline]
@@ -23,19 +228,156 @@ pub(crate) fn data_range(
 /// A table of zero-terminated strings.
 ///
 /// This is used for most file formats.
-#[derive(Debug, Default, Clone, Copy)]
-pub struct StringTable<'data> {
-    data: Bytes<'data>,
+#[derive(Debug, Clone, Copy)]
+pub struct StringTable<'data, R = &'data [u8]>
+where
+    R: ReadRef<'data>,
+{
+    data: Option<R>,
+    start: u64,
+    end: u64,
+    marker: PhantomData<&'data ()>,
 }
 
-impl<'data> StringTable<'data> {
+impl<'data, R: ReadRef<'data>> StringTable<'data, R> {
     /// Interpret the given data as a string table.
-    pub fn new(data: &'data [u8]) -> Self {
-        StringTable { data: Bytes(data) }
+    pub fn new(data: R, start: u64, end: u64) -> Self {
+        StringTable {
+            data: Some(data),
+            start,
+            end,
+            marker: PhantomData,
+        }
     }
 
     /// Return the string at the given offset.
     pub fn get(&self, offset: u32) -> Result<&'data [u8], ()> {
-        self.data.read_string_at(offset as usize)
+        match self.data {
+            Some(data) => {
+                let r_start = self.start.checked_add(offset.into()).ok_or(())?;
+                data.read_bytes_at_until(r_start..self.end, 0)
+            }
+            None => Err(()),
+        }
+    }
+}
+
+impl<'data, R: ReadRef<'data>> Default for StringTable<'data, R> {
+    fn default() -> Self {
+        StringTable {
+            data: None,
+            start: 0,
+            end: 0,
+            marker: PhantomData,
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::pod::bytes_of;
+
+    #[test]
+    fn bytes() {
+        let x = u32::to_be(0x0123_4567);
+        let data = Bytes(bytes_of(&x));
+
+        let mut bytes = data;
+        assert_eq!(bytes.skip(0), Ok(()));
+        assert_eq!(bytes, data);
+
+        let mut bytes = data;
+        assert_eq!(bytes.skip(4), Ok(()));
+        assert_eq!(bytes, Bytes(&[]));
+
+        let mut bytes = data;
+        assert_eq!(bytes.skip(5), Err(()));
+        assert_eq!(bytes, Bytes(&[]));
+
+        let mut bytes = data;
+        assert_eq!(bytes.read_bytes(0), Ok(Bytes(&[])));
+        assert_eq!(bytes, data);
+
+        let mut bytes = data;
+        assert_eq!(bytes.read_bytes(4), Ok(data));
+        assert_eq!(bytes, Bytes(&[]));
+
+        let mut bytes = data;
+        assert_eq!(bytes.read_bytes(5), Err(()));
+        assert_eq!(bytes, Bytes(&[]));
+
+        assert_eq!(data.read_bytes_at(0, 0), Ok(Bytes(&[])));
+        assert_eq!(data.read_bytes_at(4, 0), Ok(Bytes(&[])));
+        assert_eq!(data.read_bytes_at(0, 4), Ok(data));
+        assert_eq!(data.read_bytes_at(1, 4), Err(()));
+
+        let mut bytes = data;
+        assert_eq!(bytes.read::<u16>(), Ok(&u16::to_be(0x0123)));
+        assert_eq!(bytes, Bytes(&[0x45, 0x67]));
+        assert_eq!(data.read_at::<u16>(2), Ok(&u16::to_be(0x4567)));
+        assert_eq!(data.read_at::<u16>(3), Err(()));
+        assert_eq!(data.read_at::<u16>(4), Err(()));
+
+        let mut bytes = data;
+        assert_eq!(bytes.read::<u32>(), Ok(&x));
+        assert_eq!(bytes, Bytes(&[]));
+
+        let mut bytes = data;
+        assert_eq!(bytes.read::<u64>(), Err(()));
+        assert_eq!(bytes, Bytes(&[]));
+
+        let mut bytes = data;
+        assert_eq!(bytes.read_slice::<u8>(0), Ok(&[][..]));
+        assert_eq!(bytes, data);
+
+        let mut bytes = data;
+        assert_eq!(bytes.read_slice::<u8>(4), Ok(data.0));
+        assert_eq!(bytes, Bytes(&[]));
+
+        let mut bytes = data;
+        assert_eq!(bytes.read_slice::<u8>(5), Err(()));
+        assert_eq!(bytes, Bytes(&[]));
+
+        assert_eq!(data.read_slice_at::<u8>(0, 0), Ok(&[][..]));
+        assert_eq!(data.read_slice_at::<u8>(4, 0), Ok(&[][..]));
+        assert_eq!(data.read_slice_at::<u8>(0, 4), Ok(data.0));
+        assert_eq!(data.read_slice_at::<u8>(1, 4), Err(()));
+
+        let data = Bytes(&[0x01, 0x02, 0x00, 0x04]);
+
+        let mut bytes = data;
+        assert_eq!(bytes.read_string(), Ok(&data.0[..2]));
+        assert_eq!(bytes.0, &data.0[3..]);
+
+        let mut bytes = data;
+        bytes.skip(3).unwrap();
+        assert_eq!(bytes.read_string(), Err(()));
+        assert_eq!(bytes.0, &[]);
+
+        assert_eq!(data.read_string_at(0), Ok(&data.0[..2]));
+        assert_eq!(data.read_string_at(1), Ok(&data.0[1..2]));
+        assert_eq!(data.read_string_at(2), Ok(&[][..]));
+        assert_eq!(data.read_string_at(3), Err(()));
+    }
+
+    #[test]
+    fn bytes_debug() {
+        assert_eq!(format!("{:?}", Bytes(&[])), "[]");
+        assert_eq!(format!("{:?}", Bytes(&[0x01])), "[0x01]");
+        assert_eq!(
+            format!(
+                "{:?}",
+                Bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08])
+            ),
+            "[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]"
+        );
+        assert_eq!(
+            format!(
+                "{:?}",
+                Bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09])
+            ),
+            "[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, ...; 9]"
+        );
     }
 }
index b1b1e1bde683f2dfcfecea2f093ef841b9c1fb51..c8516c102796cff7c573080d2f3e270dce72c335 100644 (file)
@@ -3,7 +3,6 @@ use std::vec::Vec;
 
 use crate::endian::{LittleEndian as LE, U16Bytes, U32Bytes, U16, U32};
 use crate::pe as coff;
-use crate::pod::{bytes_of, WritableBuffer};
 use crate::write::string::*;
 use crate::write::util::*;
 use crate::write::*;
@@ -58,7 +57,7 @@ impl Object {
     pub(crate) fn coff_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8> {
         let mut name = section.to_vec();
         name.push(b'$');
-        name.extend(value);
+        name.extend_from_slice(value);
         name
     }
 
@@ -108,7 +107,7 @@ impl Object {
         let stub_size = self.architecture.address_size().unwrap().bytes();
 
         let mut name = b".rdata$.refptr.".to_vec();
-        name.extend(&self.symbols[symbol_id.0].name);
+        name.extend_from_slice(&self.symbols[symbol_id.0].name);
         let section_id = self.add_section(Vec::new(), name, SectionKind::ReadOnlyData);
         let section = self.section_mut(section_id);
         section.set_data(vec![0; stub_size as usize], u64::from(stub_size));
@@ -122,7 +121,7 @@ impl Object {
         }];
 
         let mut name = b".refptr.".to_vec();
-        name.extend(&self.symbol(symbol_id).name);
+        name.extend_from_slice(&self.symbol(symbol_id).name);
         let stub_id = self.add_raw_symbol(Symbol {
             name,
             value: 0,
@@ -289,7 +288,7 @@ impl Object {
                 _ => U16::default(),
             },
         };
-        buffer.extend(bytes_of(&header));
+        buffer.write(&header);
 
         // Write section headers.
         for (index, section) in self.sections.iter().enumerate() {
@@ -417,7 +416,7 @@ impl Object {
                     return Err(Error(format!("invalid section name offset {}", str_offset)));
                 }
             }
-            buffer.extend(bytes_of(&coff_section));
+            buffer.write(&coff_section);
         }
 
         // Write section data and relocations.
@@ -426,7 +425,7 @@ impl Object {
             if len != 0 {
                 write_align(buffer, 4);
                 debug_assert_eq!(section_offsets[index].offset, buffer.len());
-                buffer.extend(section.data.as_slice());
+                buffer.write_bytes(&section.data);
             }
 
             if !section.relocations.is_empty() {
@@ -481,7 +480,7 @@ impl Object {
                         ),
                         typ: U16Bytes::new(LE, typ),
                     };
-                    buffer.extend(bytes_of(&coff_relocation));
+                    buffer.write(&coff_relocation);
                 }
             }
         }
@@ -571,7 +570,7 @@ impl Object {
                 let str_offset = strtab.get_offset(symbol_offsets[index].str_id.unwrap());
                 coff_symbol.name[4..8].copy_from_slice(&u32::to_le_bytes(str_offset as u32));
             }
-            buffer.extend(bytes_of(&coff_symbol));
+            buffer.write(&coff_symbol);
 
             // Write auxiliary symbols.
             match symbol.kind {
@@ -579,7 +578,7 @@ impl Object {
                     let aux_len = number_of_aux_symbols as usize * coff::IMAGE_SIZEOF_SYMBOL;
                     debug_assert!(aux_len >= symbol.name.len());
                     let old_len = buffer.len();
-                    buffer.extend(&symbol.name);
+                    buffer.write_bytes(&symbol.name);
                     buffer.resize(old_len + aux_len, 0);
                 }
                 SymbolKind::Section => {
@@ -600,7 +599,7 @@ impl Object {
                         // TODO: bigobj
                         high_number: U16Bytes::default(),
                     };
-                    buffer.extend(bytes_of(&aux));
+                    buffer.write(&aux);
                 }
                 _ => {
                     debug_assert_eq!(number_of_aux_symbols, 0);
@@ -610,8 +609,8 @@ impl Object {
 
         // Write strtab section.
         debug_assert_eq!(strtab_offset, buffer.len());
-        buffer.extend(&u32::to_le_bytes(strtab_len as u32));
-        buffer.extend(&strtab_data);
+        buffer.write_bytes(&u32::to_le_bytes(strtab_len as u32));
+        buffer.write_bytes(&strtab_data);
 
         debug_assert_eq!(offset, buffer.len());
 
index 364b38089d18f27f1fd2acd5fa0fd8131934c036..34e0abc8540e2741ffbcc90a3cb574a20eec694e 100644 (file)
@@ -3,7 +3,6 @@ use std::vec::Vec;
 
 use crate::elf;
 use crate::endian::*;
-use crate::pod::{bytes_of, BytesMut, WritableBuffer};
 use crate::write::string::*;
 use crate::write::util::*;
 use crate::write::*;
@@ -66,7 +65,7 @@ impl Object {
     pub(crate) fn elf_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8> {
         let mut name = section.to_vec();
         name.push(b'.');
-        name.extend(value);
+        name.extend_from_slice(value);
         name
     }
 
@@ -417,23 +416,26 @@ impl Object {
 
         // Write section data.
         for (index, comdat) in self.comdats.iter().enumerate() {
-            let mut data = BytesMut::new();
-            data.write(&U32::new(endian, elf::GRP_COMDAT));
+            let mut data = Vec::new();
+            data.write_pod(&U32::new(self.endian, elf::GRP_COMDAT));
             for section in &comdat.sections {
-                data.write(&U32::new(endian, section_offsets[section.0].index as u32));
+                data.write_pod(&U32::new(
+                    self.endian,
+                    section_offsets[section.0].index as u32,
+                ));
             }
 
             write_align(buffer, 4);
             debug_assert_eq!(comdat_offsets[index].offset, buffer.len());
             debug_assert_eq!(comdat_offsets[index].len, data.len());
-            buffer.extend(data.as_slice());
+            buffer.write_bytes(&data);
         }
         for (index, section) in self.sections.iter().enumerate() {
             let len = section.data.len();
             if len != 0 {
                 write_align(buffer, section.align as usize);
                 debug_assert_eq!(section_offsets[index].offset, buffer.len());
-                buffer.extend(section.data.as_slice());
+                buffer.write_bytes(&section.data);
             }
         }
 
@@ -451,9 +453,9 @@ impl Object {
                 st_size: 0,
             },
         );
-        let mut symtab_shndx = BytesMut::new();
+        let mut symtab_shndx = Vec::new();
         if need_symtab_shndx {
-            symtab_shndx.write(&U32::new(endian, 0));
+            symtab_shndx.write_pod(&U32::new(endian, 0));
         }
         let mut write_symbol = |index: usize, symbol: &Symbol| -> Result<()> {
             let st_info = if let SymbolFlags::Elf { st_info, .. } = symbol.flags {
@@ -547,7 +549,7 @@ impl Object {
                 },
             );
             if need_symtab_shndx {
-                symtab_shndx.write(&U32::new(endian, xindex));
+                symtab_shndx.write_pod(&U32::new(endian, xindex));
             }
             Ok(())
         };
@@ -564,12 +566,12 @@ impl Object {
         if need_symtab_shndx {
             debug_assert_eq!(symtab_shndx_offset, buffer.len());
             debug_assert_eq!(symtab_shndx_len, symtab_shndx.len());
-            buffer.extend(symtab_shndx.as_slice());
+            buffer.write_bytes(&symtab_shndx);
         }
 
         // Write strtab section.
         debug_assert_eq!(strtab_offset, buffer.len());
-        buffer.extend(&strtab_data);
+        buffer.write_bytes(&strtab_data);
 
         // Write relocations.
         for (index, section) in self.sections.iter().enumerate() {
@@ -597,6 +599,10 @@ impl Object {
                             (RelocationKind::Relative, RelocationEncoding::Generic, 16) => {
                                 elf::R_AARCH64_PREL16
                             }
+                            (RelocationKind::Relative, RelocationEncoding::AArch64Call, 26)
+                            | (RelocationKind::PltRelative, RelocationEncoding::AArch64Call, 26) => {
+                                elf::R_AARCH64_CALL26
+                            }
                             (RelocationKind::Elf(x), _, _) => x,
                             _ => {
                                 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
@@ -827,7 +833,7 @@ impl Object {
 
         // Write shstrtab section.
         debug_assert_eq!(shstrtab_offset, buffer.len());
-        buffer.extend(&shstrtab_data);
+        buffer.write_bytes(&shstrtab_data);
 
         // Write section headers.
         write_align(buffer, pointer_align);
@@ -1148,7 +1154,7 @@ impl<E: Endian> Elf for Elf32<E> {
             e_shnum: U16::new(endian, file.e_shnum),
             e_shstrndx: U16::new(endian, file.e_shstrndx),
         };
-        buffer.extend(bytes_of(&file));
+        buffer.write(&file);
     }
 
     fn write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) {
@@ -1165,7 +1171,7 @@ impl<E: Endian> Elf for Elf32<E> {
             sh_addralign: U32::new(endian, section.sh_addralign as u32),
             sh_entsize: U32::new(endian, section.sh_entsize as u32),
         };
-        buffer.extend(bytes_of(&section));
+        buffer.write(&section);
     }
 
     fn write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym) {
@@ -1178,7 +1184,7 @@ impl<E: Endian> Elf for Elf32<E> {
             st_value: U32::new(endian, symbol.st_value as u32),
             st_size: U32::new(endian, symbol.st_size as u32),
         };
-        buffer.extend(bytes_of(&symbol));
+        buffer.write(&symbol);
     }
 
     fn write_rel(
@@ -1195,13 +1201,13 @@ impl<E: Endian> Elf for Elf32<E> {
                 r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8),
                 r_addend: I32::new(endian, rel.r_addend as i32),
             };
-            buffer.extend(bytes_of(&rel));
+            buffer.write(&rel);
         } else {
             let rel = elf::Rel32 {
                 r_offset: U32::new(endian, rel.r_offset as u32),
                 r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8),
             };
-            buffer.extend(bytes_of(&rel));
+            buffer.write(&rel);
         }
     }
 }
@@ -1249,7 +1255,7 @@ impl<E: Endian> Elf for Elf64<E> {
             e_shnum: U16::new(endian, file.e_shnum),
             e_shstrndx: U16::new(endian, file.e_shstrndx),
         };
-        buffer.extend(bytes_of(&file))
+        buffer.write(&file)
     }
 
     fn write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) {
@@ -1266,7 +1272,7 @@ impl<E: Endian> Elf for Elf64<E> {
             sh_addralign: U64::new(endian, section.sh_addralign),
             sh_entsize: U64::new(endian, section.sh_entsize),
         };
-        buffer.extend(bytes_of(&section));
+        buffer.write(&section);
     }
 
     fn write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym) {
@@ -1279,7 +1285,7 @@ impl<E: Endian> Elf for Elf64<E> {
             st_value: U64::new(endian, symbol.st_value),
             st_size: U64::new(endian, symbol.st_size),
         };
-        buffer.extend(bytes_of(&symbol));
+        buffer.write(&symbol);
     }
 
     fn write_rel(
@@ -1293,16 +1299,16 @@ impl<E: Endian> Elf for Elf64<E> {
         if is_rela {
             let rel = elf::Rela64 {
                 r_offset: U64::new(endian, rel.r_offset),
-                r_info: elf::Rela64::r_info2(endian, is_mips64el, rel.r_sym, rel.r_type),
+                r_info: elf::Rela64::r_info(endian, is_mips64el, rel.r_sym, rel.r_type),
                 r_addend: I64::new(endian, rel.r_addend),
             };
-            buffer.extend(bytes_of(&rel));
+            buffer.write(&rel);
         } else {
             let rel = elf::Rel64 {
                 r_offset: U64::new(endian, rel.r_offset),
                 r_info: elf::Rel64::r_info(endian, rel.r_sym, rel.r_type),
             };
-            buffer.extend(bytes_of(&rel));
+            buffer.write(&rel);
         }
     }
 }
index d102da3deae14e25321491dd33264ed87f4cb600..ed25950d985fc08107573f7db58648d8cddb7fe6 100644 (file)
@@ -2,7 +2,6 @@ use std::mem;
 
 use crate::endian::*;
 use crate::macho;
-use crate::pod::{bytes_of, WritableBuffer};
 use crate::write::string::*;
 use crate::write::util::*;
 use crate::write::*;
@@ -116,7 +115,7 @@ impl Object {
 
         // Create the initializer symbol.
         let mut name = symbol.name.clone();
-        name.extend(b"$tlv$init");
+        name.extend_from_slice(b"$tlv$init");
         let init_symbol_id = self.add_raw_symbol(Symbol {
             name,
             value: 0,
@@ -443,7 +442,7 @@ impl Object {
             stroff: U32::new(endian, strtab_offset as u32),
             strsize: U32::new(endian, strtab_data.len() as u32),
         };
-        buffer.extend(bytes_of(&symtab_command));
+        buffer.write(&symtab_command);
 
         // Write section data.
         for (index, section) in self.sections.iter().enumerate() {
@@ -451,7 +450,7 @@ impl Object {
             if len != 0 {
                 write_align(buffer, section.align as usize);
                 debug_assert_eq!(section_offsets[index].offset, buffer.len());
-                buffer.extend(section.data.as_slice());
+                buffer.write_bytes(&section.data);
             }
         }
         debug_assert_eq!(segment_file_offset + segment_file_size, buffer.len());
@@ -524,7 +523,7 @@ impl Object {
 
         // Write strtab.
         debug_assert_eq!(strtab_offset, buffer.len());
-        buffer.extend(&strtab_data);
+        buffer.write_bytes(&strtab_data);
 
         // Write relocations.
         for (index, section) in self.sections.iter().enumerate() {
@@ -600,7 +599,7 @@ impl Object {
                         r_extern,
                         r_type,
                     };
-                    buffer.extend(bytes_of(&reloc_info.relocation(endian)));
+                    buffer.write(&reloc_info.relocation(endian));
                 }
             }
         }
@@ -701,7 +700,7 @@ impl<E: Endian> MachO for MachO32<E> {
             sizeofcmds: U32::new(endian, header.sizeofcmds),
             flags: U32::new(endian, header.flags),
         };
-        buffer.extend(bytes_of(&header));
+        buffer.write(&header);
     }
 
     fn write_segment_command(&self, buffer: &mut dyn WritableBuffer, segment: SegmentCommand) {
@@ -719,7 +718,7 @@ impl<E: Endian> MachO for MachO32<E> {
             nsects: U32::new(endian, segment.nsects),
             flags: U32::new(endian, segment.flags),
         };
-        buffer.extend(bytes_of(&segment));
+        buffer.write(&segment);
     }
 
     fn write_section(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) {
@@ -737,7 +736,7 @@ impl<E: Endian> MachO for MachO32<E> {
             reserved1: U32::default(),
             reserved2: U32::default(),
         };
-        buffer.extend(bytes_of(&section));
+        buffer.write(&section);
     }
 
     fn write_nlist(&self, buffer: &mut dyn WritableBuffer, nlist: Nlist) {
@@ -749,7 +748,7 @@ impl<E: Endian> MachO for MachO32<E> {
             n_desc: U16::new(endian, nlist.n_desc),
             n_value: U32::new(endian, nlist.n_value as u32),
         };
-        buffer.extend(bytes_of(&nlist));
+        buffer.write(&nlist);
     }
 }
 
@@ -791,7 +790,7 @@ impl<E: Endian> MachO for MachO64<E> {
             flags: U32::new(endian, header.flags),
             reserved: U32::default(),
         };
-        buffer.extend(bytes_of(&header));
+        buffer.write(&header);
     }
 
     fn write_segment_command(&self, buffer: &mut dyn WritableBuffer, segment: SegmentCommand) {
@@ -809,7 +808,7 @@ impl<E: Endian> MachO for MachO64<E> {
             nsects: U32::new(endian, segment.nsects),
             flags: U32::new(endian, segment.flags),
         };
-        buffer.extend(bytes_of(&segment));
+        buffer.write(&segment);
     }
 
     fn write_section(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) {
@@ -828,7 +827,7 @@ impl<E: Endian> MachO for MachO64<E> {
             reserved2: U32::default(),
             reserved3: U32::default(),
         };
-        buffer.extend(bytes_of(&section));
+        buffer.write(&section);
     }
 
     fn write_nlist(&self, buffer: &mut dyn WritableBuffer, nlist: Nlist) {
@@ -840,6 +839,6 @@ impl<E: Endian> MachO for MachO64<E> {
             n_desc: U16::new(endian, nlist.n_desc),
             n_value: U64Bytes::new(endian, nlist.n_value),
         };
-        buffer.extend(bytes_of(&nlist));
+        buffer.write(&nlist);
     }
 }
index 4d6cb2bb50c6fc431c6983a5f8b3aff25dd6f24c..747e2a02e8ca5090d8ee54821a8cea8d7212a5d5 100644 (file)
@@ -6,7 +6,6 @@ use std::vec::Vec;
 use std::{error, fmt, result, str};
 
 use crate::endian::{Endianness, U32, U64};
-use crate::pod::{BytesMut, WritableBuffer};
 use crate::{
     Architecture, BinaryFormat, ComdatKind, FileFlags, RelocationEncoding, RelocationKind,
     SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope,
@@ -20,6 +19,7 @@ mod elf;
 mod macho;
 mod string;
 mod util;
+pub use util::*;
 
 /// The error type used within the write module.
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -162,7 +162,7 @@ impl Object {
             kind,
             size: 0,
             align: 1,
-            data: BytesMut::new(),
+            data: Vec::new(),
             relocations: Vec::new(),
             symbol: None,
             flags: SectionFlags::None,
@@ -520,9 +520,9 @@ impl Object {
 
     /// Write the object to a `Vec`.
     pub fn write(&self) -> Result<Vec<u8>> {
-        let mut buffer = BytesMut::new();
+        let mut buffer = Vec::new();
         self.emit(&mut buffer)?;
-        Ok(buffer.0)
+        Ok(buffer)
     }
 
     /// Write the object to a `WritableBuffer`.
@@ -616,7 +616,7 @@ pub struct Section {
     kind: SectionKind,
     size: u64,
     align: u64,
-    data: BytesMut,
+    data: Vec<u8>,
     relocations: Vec<Relocation>,
     symbol: Option<SymbolId>,
     /// Section flags that are specific to each file format.
@@ -650,7 +650,7 @@ impl Section {
         debug_assert_eq!(align & (align - 1), 0);
         debug_assert!(self.data.is_empty());
         self.size = data.len() as u64;
-        self.data = BytesMut(data);
+        self.data = data;
         self.align = align;
     }
 
@@ -669,7 +669,7 @@ impl Section {
             offset += align - (offset & (align - 1));
             self.data.resize(offset, 0);
         }
-        self.data.extend(data);
+        self.data.extend_from_slice(data);
         self.size = self.data.len() as u64;
         offset as u64
     }
index c108f47485a7e46931806bf742ccf06f07f4a453..bb6b8597bb872e04e6084ed707469b5122d8c3ed 100644 (file)
@@ -1,4 +1,92 @@
-use crate::pod::WritableBuffer;
+use std::vec::Vec;
+
+use crate::pod::{bytes_of, bytes_of_slice, Pod};
+
+/// Trait for writable buffer.
+#[allow(clippy::len_without_is_empty)]
+pub trait WritableBuffer {
+    /// Returns position/offset for data to be written at.
+    fn len(&self) -> usize;
+
+    /// Reserves specified number of bytes in the buffer.
+    fn reserve(&mut self, additional: usize) -> Result<(), ()>;
+
+    /// Writes the specified value at the end of the buffer
+    /// until the buffer has the specified length.
+    fn resize(&mut self, new_len: usize, value: u8);
+
+    /// Writes the specified slice of bytes at the end of the buffer.
+    fn write_bytes(&mut self, val: &[u8]);
+
+    /// Writes the specified `Pod` type at the end of the buffer.
+    fn write_pod<T: Pod>(&mut self, val: &T)
+    where
+        Self: Sized,
+    {
+        self.write_bytes(bytes_of(val))
+    }
+
+    /// Writes the specified `Pod` slice at the end of the buffer.
+    fn write_pod_slice<T: Pod>(&mut self, val: &[T])
+    where
+        Self: Sized,
+    {
+        self.write_bytes(bytes_of_slice(val))
+    }
+}
+
+impl<'a> dyn WritableBuffer + 'a {
+    /// Writes the specified `Pod` type at the end of the buffer.
+    pub fn write<T: Pod>(&mut self, val: &T) {
+        self.write_bytes(bytes_of(val))
+    }
+
+    /// Writes the specified `Pod` slice at the end of the buffer.
+    pub fn write_slice<T: Pod>(&mut self, val: &[T]) {
+        self.write_bytes(bytes_of_slice(val))
+    }
+}
+
+impl WritableBuffer for Vec<u8> {
+    #[inline]
+    fn len(&self) -> usize {
+        self.len()
+    }
+
+    #[inline]
+    fn reserve(&mut self, additional: usize) -> Result<(), ()> {
+        self.reserve(additional);
+        Ok(())
+    }
+
+    #[inline]
+    fn resize(&mut self, new_len: usize, value: u8) {
+        self.resize(new_len, value);
+    }
+
+    #[inline]
+    fn write_bytes(&mut self, val: &[u8]) {
+        self.extend_from_slice(val)
+    }
+}
+
+/// A trait for mutable byte slices.
+///
+/// It provides convenience methods for `Pod` types.
+pub(crate) trait BytesMut {
+    fn write_at<T: Pod>(self, offset: usize, val: &T) -> Result<(), ()>;
+}
+
+impl<'a> BytesMut for &'a mut [u8] {
+    #[inline]
+    fn write_at<T: Pod>(self, offset: usize, val: &T) -> Result<(), ()> {
+        let src = bytes_of(val);
+        let dest = self.get_mut(offset..).ok_or(())?;
+        let dest = dest.get_mut(..src.len()).ok_or(())?;
+        dest.copy_from_slice(src);
+        Ok(())
+    }
+}
 
 pub(crate) fn align(offset: usize, size: usize) -> usize {
     (offset + (size - 1)) & !(size - 1)
@@ -13,3 +101,29 @@ pub(crate) fn write_align(buffer: &mut dyn WritableBuffer, size: usize) {
     let new_len = align(buffer.len(), size);
     buffer.resize(new_len, 0);
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn bytes_mut() {
+        let data = vec![0x01, 0x23, 0x45, 0x67];
+
+        let mut bytes = data.clone();
+        bytes.extend_from_slice(bytes_of(&u16::to_be(0x89ab)));
+        assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab]);
+
+        let mut bytes = data.clone();
+        assert_eq!(bytes.write_at(0, &u16::to_be(0x89ab)), Ok(()));
+        assert_eq!(bytes, [0x89, 0xab, 0x45, 0x67]);
+
+        let mut bytes = data.clone();
+        assert_eq!(bytes.write_at(2, &u16::to_be(0x89ab)), Ok(()));
+        assert_eq!(bytes, [0x01, 0x23, 0x89, 0xab]);
+
+        assert_eq!(bytes.write_at(3, &u16::to_be(0x89ab)), Err(()));
+        assert_eq!(bytes.write_at(4, &u16::to_be(0x89ab)), Err(()));
+        assert_eq!(vec![].write_at(0, &u32::to_be(0x89ab)), Err(()));
+    }
+}
index 936194d14f42e4068b5466bde4e4d1d5f96d69b7..6956b597e0d1ce561647f2bc1b209f2ef986c97b 100644 (file)
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"007575511b35e14e9ebea4bf696ba331cd08d1cd2412ed43e74174ef4760133a","Cargo.lock":"383c174522aea65ff384ad388eff015380ef09581ef0785e9f0dcf8a9c0cc198","Cargo.toml":"20952c4f41d83412eccc2b3866e42e11e33331789bbc3939f4d7ef427e1f6781","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"7e93eec9a4c6c38db0eb3851c1e868c55e64ff2bacc86380d601a2ee08a11589","bors.toml":"ebd69f714a49dceb8fd10ebadfea6e2767be4732fdef49eddf6239151b4bc78c","examples/bench.rs":"1597a52529f75d6c5ad0b86759a775b1d723dfa810e2016317283b13594219da","examples/bench_acquire.rs":"9f4912ca262194cb55e893c33739c85c2f4868d07905b9dd3238552b6ce8a6e4","examples/bench_vs_lazy_static.rs":"d527294a2e73b53ac5faed8b316dfd1ae2a06adb31384134af21f10ce76333a5","examples/lazy_static.rs":"90541b093ed1d1cbb73f4097ff02cf80657e28264d281d6a31d96a708fdfea90","examples/reentrant_init_deadlocks.rs":"ff84929de27a848e5b155549caa96db5db5f030afca975f8ba3f3da640083001","examples/regex.rs":"4a2e0fb093c7f5bbe0fff8689fc0c670c5334344a1bfda376f5faa98a05d459f","examples/test_synchronization.rs":"88abd5c16275bb2f2d77eaecf369d97681404a77b8edd0021f24bfd377c46be3","src/imp_pl.rs":"cac67286119fcfa2b69ffb9ada51d5cb57c89e95a533d95d5d40b0ae4d38a6c2","src/imp_std.rs":"7a9b58444f71ca3025655f060dabc0f33a775d3b27916e9c22fe4182b286265d","src/lib.rs":"708696d9b70d2dd1ea57c6990c806bd53f13f5d1a5727254ca7620caabd77df5","src/race.rs":"b90a00d833919de2e1b03dee7b1b5c2fbfe246357c50b03643097860a95636e5","tests/it.rs":"ed9ff44665f29fa138055800d7199405740bce912f9c568c11aa2ff2249c17f8"},"package":"af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"abb8c3977a69e288097ac9e6d86c78b95170fabcaa4454ce3250e06f6fc388ab","Cargo.lock":"8904e3dc1908b63c1c81005d34a1e5e498c639a65f05d306b3388bc88a919f3a","Cargo.toml":"0ab421ab8c48cc6410965fd82a82dbaec19bb8b24adb7bf0cab07870fac472e9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"7e93eec9a4c6c38db0eb3851c1e868c55e64ff2bacc86380d601a2ee08a11589","bors.toml":"ebd69f714a49dceb8fd10ebadfea6e2767be4732fdef49eddf6239151b4bc78c","examples/bench.rs":"1597a52529f75d6c5ad0b86759a775b1d723dfa810e2016317283b13594219da","examples/bench_acquire.rs":"9f4912ca262194cb55e893c33739c85c2f4868d07905b9dd3238552b6ce8a6e4","examples/bench_vs_lazy_static.rs":"d527294a2e73b53ac5faed8b316dfd1ae2a06adb31384134af21f10ce76333a5","examples/lazy_static.rs":"90541b093ed1d1cbb73f4097ff02cf80657e28264d281d6a31d96a708fdfea90","examples/reentrant_init_deadlocks.rs":"ff84929de27a848e5b155549caa96db5db5f030afca975f8ba3f3da640083001","examples/regex.rs":"4a2e0fb093c7f5bbe0fff8689fc0c670c5334344a1bfda376f5faa98a05d459f","examples/test_synchronization.rs":"88abd5c16275bb2f2d77eaecf369d97681404a77b8edd0021f24bfd377c46be3","src/imp_pl.rs":"cac67286119fcfa2b69ffb9ada51d5cb57c89e95a533d95d5d40b0ae4d38a6c2","src/imp_std.rs":"7a9b58444f71ca3025655f060dabc0f33a775d3b27916e9c22fe4182b286265d","src/lib.rs":"80c30678f1583e6abf5105c704650564505556cf97e30ab507acf70d5e90d25a","src/race.rs":"4b19f459ac16605353e4b6559ea3b194f45c3812aa157e2c0e3a82f67ebacfeb","tests/it.rs":"ed9ff44665f29fa138055800d7199405740bce912f9c568c11aa2ff2249c17f8"},"package":"692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"}
\ No newline at end of file
index 53fdf6472e904dd598993a52ac7a6a7621a4a770..34725e96b08d88ef9f2263afe9e35bf2d97a5616 100644 (file)
@@ -1,5 +1,9 @@
 # Changelog
 
+## 1.8.0
+
+- Add `try_insert` API -- a version of `set` that returns a reference.
+
 ## 1.7.2
 
 - Improve code size when using parking_lot feature.
index c84a2ec7285b4d9dcbad3e24f069c9abd34e7ea1..40c72b664b58ef1be8734b8598443d2b9c653550 100644 (file)
@@ -53,12 +53,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libc"
-version = "0.2.87"
+version = "0.2.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "lock_api"
-version = "0.4.2"
+version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -71,7 +71,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "once_cell"
-version = "1.7.2"
+version = "1.8.0"
 dependencies = [
  "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -85,7 +85,7 @@ version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "instant 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "lock_api 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lock_api 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot_core 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -96,15 +96,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "instant 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.87 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.97 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "redox_syscall"
-version = "0.2.5"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -186,12 +186,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
 "checksum instant 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
 "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-"checksum libc 0.2.87 (registry+https://github.com/rust-lang/crates.io-index)" = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213"
-"checksum lock_api 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
+"checksum libc 0.2.97 (registry+https://github.com/rust-lang/crates.io-index)" = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
+"checksum lock_api 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb"
 "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
 "checksum parking_lot 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
 "checksum parking_lot_core 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
-"checksum redox_syscall 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
+"checksum redox_syscall 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc"
 "checksum regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc"
 "checksum regex-syntax 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bfaca88e749e19dffb60f77b55e5d87a872fac7e9e48598f7cf93b2d8c047b0a"
 "checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
index 0d3797b50dd6da6ca5fea6adb32bf8388be28a2f..3129cb3f038f146802661100e159a70200ce5905 100644 (file)
@@ -13,9 +13,9 @@
 [package]
 edition = "2018"
 name = "once_cell"
-version = "1.7.2"
+version = "1.8.0"
 authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
-exclude = ["*.png", "*.svg", "/Cargo.lock.min", "/.travis.yml", "/run-miri-tests.sh", "rustfmt.toml"]
+exclude = ["*.png", "*.svg", "/Cargo.lock.msrv", "/.travis.yml", "/run-miri-tests.sh", "rustfmt.toml"]
 description = "Single assignment cells and lazy values."
 documentation = "https://docs.rs/once_cell"
 readme = "README.md"
index a455cb46a7d2ff33108d69bf01cf2dfb89591d62..8fd9132cc91a5466000116100386236bf7793f4e 100644 (file)
@@ -6,7 +6,7 @@
 //!
 //! ```rust,ignore
 //! impl<T> OnceCell<T> {
-//!     fn new() -> OnceCell<T> { ... }
+//!     const fn new() -> OnceCell<T> { ... }
 //!     fn set(&self, value: T) -> Result<(), T> { ... }
 //!     fn get(&self) -> Option<&T> { ... }
 //! }
 //! [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
 //! [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
 //!
-//! # Patterns
+//! # Recipes
 //!
 //! `OnceCell` might be useful for a variety of patterns.
 //!
-//! ## Safe Initialization of global data
+//! ## Safe Initialization of Global Data
 //!
 //! ```rust
 //! use std::{env, io};
@@ -59,7 +59,7 @@
 //! }
 //! ```
 //!
-//! ## Lazy initialized global data
+//! ## Lazy Initialized Global Data
 //!
 //! This is essentially the `lazy_static!` macro, but without a macro.
 //!
@@ -97,6 +97,9 @@
 //! }
 //! ```
 //!
+//! Note that the variable that holds `Lazy` is declared as `static`, *not*
+//! `const`. This is important: using `const` instead compiles, but works wrong.
+//!
 //! [`sync::Lazy`]: sync/struct.Lazy.html
 //! [`unsync::Lazy`]: unsync/struct.Lazy.html
 //!
 //! }
 //! ```
 //!
-//! ## Building block
+//! ## Lazily Compiled Regex
 //!
-//! Naturally, it is  possible to build other abstractions on top of `OnceCell`.
-//! For example, this is a `regex!` macro which takes a string literal and returns an
+//! This is a `regex!` macro which takes a string literal and returns an
 //! *expression* that evaluates to a `&'static Regex`:
 //!
 //! ```
 //!
 //! This macro can be useful to avoid the "compile regex on every loop iteration" problem.
 //!
-//! Another pattern would be a `LateInit` type for delayed initialization:
+//! ## Runtime `include_bytes!`
+//!
+//! The `include_bytes` macro is useful to include test resources, but it slows
+//! down test compilation a lot. An alternative is to load the resources at
+//! runtime:
+//!
+//! ```
+//! use std::path::Path;
+//!
+//! use once_cell::sync::OnceCell;
+//!
+//! pub struct TestResource {
+//!     path: &'static str,
+//!     cell: OnceCell<Vec<u8>>,
+//! }
+//!
+//! impl TestResource {
+//!     pub const fn new(path: &'static str) -> TestResource {
+//!         TestResource { path, cell: OnceCell::new() }
+//!     }
+//!     pub fn bytes(&self) -> &[u8] {
+//!         self.cell.get_or_init(|| {
+//!             let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
+//!             let path = Path::new(dir.as_str()).join(self.path);
+//!             std::fs::read(&path).unwrap_or_else(|_err| {
+//!                 panic!("failed to load test resource: {}", path.display())
+//!             })
+//!         }).as_slice()
+//!     }
+//! }
+//!
+//! static TEST_IMAGE: TestResource = TestResource::new("test_data/lena.png");
+//!
+//! #[test]
+//! fn test_sobel_filter() {
+//!     let rgb: &[u8] = TEST_IMAGE.bytes();
+//!     // ...
+//! # drop(rgb);
+//! }
+//! ```
+//!
+//! ## `lateinit`
+//!
+//! `LateInit` type for delayed initialization. It is reminiscent of Kotlin's
+//! `lateinit` keyword and allows construction of cyclic data structures:
 //!
 //!
 //! ```
@@ -291,10 +337,11 @@ mod imp;
 #[path = "imp_std.rs"]
 mod imp;
 
+/// Single-threaded version of `OnceCell`.
 pub mod unsync {
     use core::{
         cell::{Cell, UnsafeCell},
-        fmt, mem,
+        fmt, hint, mem,
         ops::{Deref, DerefMut},
     };
 
@@ -417,9 +464,29 @@ pub mod unsync {
         /// assert!(cell.get().is_some());
         /// ```
         pub fn set(&self, value: T) -> Result<(), T> {
-            let slot = unsafe { &*self.inner.get() };
-            if slot.is_some() {
-                return Err(value);
+            match self.try_insert(value) {
+                Ok(_) => Ok(()),
+                Err((_, value)) => Err(value),
+            }
+        }
+
+        /// Like [`set`](Self::set), but also returns a referce to the final cell value.
+        ///
+        /// # Example
+        /// ```
+        /// use once_cell::unsync::OnceCell;
+        ///
+        /// let cell = OnceCell::new();
+        /// assert!(cell.get().is_none());
+        ///
+        /// assert_eq!(cell.try_insert(92), Ok(&92));
+        /// assert_eq!(cell.try_insert(62), Err((&92, 62)));
+        ///
+        /// assert!(cell.get().is_some());
+        /// ```
+        pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
+            if let Some(old) = self.get() {
+                return Err((old, value));
             }
             let slot = unsafe { &mut *self.inner.get() };
             // This is the only place where we set the slot, no races
@@ -427,7 +494,10 @@ pub mod unsync {
             // checked that slot is currently `None`, so this write
             // maintains the `inner`'s invariant.
             *slot = Some(value);
-            Ok(())
+            Ok(match &*slot {
+                Some(value) => value,
+                None => unsafe { hint::unreachable_unchecked() },
+            })
         }
 
         /// Gets the contents of the cell, initializing it with `f`
@@ -657,6 +727,7 @@ pub mod unsync {
     }
 }
 
+/// Thread-safe, blocking version of `OnceCell`.
 #[cfg(feature = "std")]
 pub mod sync {
     use std::{
@@ -803,11 +874,33 @@ pub mod sync {
         /// }
         /// ```
         pub fn set(&self, value: T) -> Result<(), T> {
+            match self.try_insert(value) {
+                Ok(_) => Ok(()),
+                Err((_, value)) => Err(value),
+            }
+        }
+
+        /// Like [`set`](Self::set), but also returns a reference to the final cell value.
+        ///
+        /// # Example
+        ///
+        /// ```
+        /// use once_cell::unsync::OnceCell;
+        ///
+        /// let cell = OnceCell::new();
+        /// assert!(cell.get().is_none());
+        ///
+        /// assert_eq!(cell.try_insert(92), Ok(&92));
+        /// assert_eq!(cell.try_insert(62), Err((&92, 62)));
+        ///
+        /// assert!(cell.get().is_some());
+        /// ```
+        pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
             let mut value = Some(value);
-            self.get_or_init(|| value.take().unwrap());
+            let res = self.get_or_init(|| value.take().unwrap());
             match value {
-                None => Ok(()),
-                Some(value) => Err(value),
+                None => Ok(res),
+                Some(value) => Err((res, value)),
             }
         }
 
@@ -974,11 +1067,10 @@ pub mod sync {
         }
     }
 
-    // We never create a `&F` from a `&Lazy<T, F>` so it is fine
-    // to not impl `Sync` for `F`
-    // we do create a `&mut Option<F>` in `force`, but this is
-    // properly synchronized, so it only happens once
-    // so it also does not contribute to this impl.
+    // We never create a `&F` from a `&Lazy<T, F>` so it is fine to not impl
+    // `Sync` for `F`. we do create a `&mut Option<F>` in `force`, but this is
+    // properly synchronized, so it only happens once so it also does not
+    // contribute to this impl.
     unsafe impl<T, F: Send> Sync for Lazy<T, F> where OnceCell<T>: Sync {}
     // auto-derived `Send` impl is OK.
 
index e0dc8fcfe1f0c21ed4ec3f8e1f29a4566656c1cf..e1f5cbaa781bb01bcde05a7abfa9b09d48109c68 100644 (file)
@@ -1,4 +1,4 @@
-//! "First one wins" flavor of `OnceCell`.
+//! Thread-safe, non-blocking, "first one wins" flavor of `OnceCell`.
 //!
 //! If two threads race to initialize a type from the `race` module, they
 //! don't block, execute initialization function together, but only one of
index 23bc2b9c5b4b3976b18da1fe8e44b02de70d1755..9f0ef06c4342dfc6d899b9bf27f51c0976ccb429 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.toml":"57ea604a587b8ee4f1f1b251ab98e8a80c440f385145612695bb803c92c28d18","LICENSE-APACHE":"154397a08d0cb342110281129971868cd562542d0780b0d10722788cd11a1399","LICENSE-MIT":"72af89a828df52a9dcc42512ed64663b3b8d7961dd7a5586d44478eede82bc7a","LICENSE-THIRD-PARTY":"0a22326fd75448038b10861d0abb270d607348458c875e9e774fbf8d7d5bd052","Makefile.toml":"a0a6939dcef14d99ea8dc04c4dd874c63e375ce3d6c9f0aeda1031439ffae438","release.toml":"58a518da7cd8a34b566ffbd875ed267acae0a2933b0999ed2872efc3e12bb28e","src/lib.rs":"a1f6814c0a79e8b802d0b42cce0112afff6189a2355f235c78ec39054da13ec6","src/xdg-open":"2dbade06e9e40c3052f2d0e74021b532dd556ac2d23ed801bd8376523d9e198a"},"package":"13117407ca9d0caf3a0e74f97b490a7e64c0ae3aa90a8b7085544d0c37b6f3ae"}
\ No newline at end of file
+{"files":{"Cargo.toml":"ee161809cf1f818ecb2952d86acfc4867224e9f6f1cf83a6828eee6316ad5271","Drakefile.ts":"e357716de020b86a99b96b0b345651f3b2654e77dcb5c7fa98edea4a2a374589","LICENSE-APACHE":"154397a08d0cb342110281129971868cd562542d0780b0d10722788cd11a1399","LICENSE-MIT":"72af89a828df52a9dcc42512ed64663b3b8d7961dd7a5586d44478eede82bc7a","LICENSE-THIRD-PARTY":"0a22326fd75448038b10861d0abb270d607348458c875e9e774fbf8d7d5bd052","src/lib.rs":"8981b76e1c5eae38418ac334c51993d9faf27775e7df800c680eb802883c41e2","src/linux_and_more.rs":"96912d2099ac0cad116160b9147d46c8c374f191796c2095a1c56519feed4909","src/macos.rs":"38e762e83064c2150a125b6e6c477640652f9dceeeadbeeda64d0edd4936cf01","src/windows.rs":"d0ed2e6ae1deb8ded4eb8cc9204a868290f390aa9078b7cd953b1dfbd2261c25","src/xdg-open":"a99799b070c39e9788d097f1057bdee688248c5f3df82353beebe90c561aeb75","tests/version-numbers.rs":"8069cb08b31531f8eb5e164089b1acbe7dc77e4ba87dcc0a3717205446847795"},"package":"4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952"}
\ No newline at end of file
index 06fe01e567428aeabda5ad061881b69a456c8aa2..bbc220c45e8e41b653efb7671310691e2475d18f 100644 (file)
 [package]
 edition = "2018"
 name = "opener"
-version = "0.4.1"
+version = "0.5.0"
 authors = ["Brian Bowman <seeker14491@gmail.com>"]
 description = "Open a file or link using the system default program."
 readme = "../README.md"
 keywords = ["open", "default", "launcher", "browser"]
+categories = ["os"]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/Seeker14491/opener"
-
-[dependencies]
+[dev-dependencies.version-sync]
+version = "0.9"
+[target."cfg(target_os = \"linux\")".dependencies.bstr]
+version = "0.2"
 [target."cfg(windows)".dependencies.winapi]
 version = "0.3"
 features = ["shellapi"]
diff --git a/vendor/opener/Drakefile.ts b/vendor/opener/Drakefile.ts
new file mode 100755 (executable)
index 0000000..476cb23
--- /dev/null
@@ -0,0 +1,79 @@
+import {
+  abort,
+  desc,
+  env,
+  run,
+  sh,
+  shCapture,
+  task,
+} from "https://deno.land/x/drake@v1.5.0/mod.ts";
+
+const SHOULD_CARGO_PUBLISH = true;
+const SHOULD_PUSH_DOCS_TO_GITHUB_PAGES = false;
+
+desc("Release a new version of the crate");
+task("release", [], async () => {
+  const version = env("version");
+  if (version == null) {
+    abort("The version to release was not specified");
+  }
+  if (!isValidSemVer(version)) {
+    abort("The given version is not a valid SemVer string");
+  }
+
+  await sh("cargo test --all-features");
+  await sh("cargo fmt -- --check");
+  await sh("git diff HEAD --exit-code --name-only");
+
+  if (SHOULD_CARGO_PUBLISH) {
+    await sh("cargo publish --dry-run");
+  }
+
+  const tagName = `v${version}`;
+  await sh(`git tag -a ${tagName} -m "Release ${tagName}"`);
+  await sh("git push origin master");
+  await sh(`git push origin ${tagName}`);
+
+  if (SHOULD_CARGO_PUBLISH) {
+    await sh("cargo publish");
+  }
+
+  if (SHOULD_PUSH_DOCS_TO_GITHUB_PAGES) {
+    await run("upload-docs");
+  }
+});
+
+desc("Upload docs to GitHub Pages");
+task("upload-docs", [], async () => {
+  let origin_url;
+  {
+    const { code, output, error } = await shCapture(
+      "git remote get-url origin",
+    );
+    if (code == 0) {
+      origin_url = output.trim();
+    } else {
+      abort("Error getting origin's url from git");
+    }
+  }
+
+  await sh("cargo clean --doc");
+  await sh("cargo doc --no-deps");
+
+  {
+    const run = (command: string) => sh(command, { cwd: "target/doc" });
+
+    await run("git init");
+    await run("git add .");
+    await run('git commit -am "(doc upload)"');
+    await run(`git push -f ${origin_url} master:gh-pages`);
+  }
+});
+
+run();
+
+function isValidSemVer(s: string): boolean {
+  return s.match(
+    /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/,
+  ) != null;
+}
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/vendor/opener/Makefile.toml b/vendor/opener/Makefile.toml
deleted file mode 100644 (file)
index 706ffd3..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-[tasks.clean-docs]
-command = "cargo"
-args = ["clean", "--doc"]
-
-[tasks.pre-release]
-dependencies = [
-    "check-format",
-    "test",
-    "clean-docs"
-]
diff --git a/vendor/opener/release.toml b/vendor/opener/release.toml
deleted file mode 100644 (file)
index a6356d5..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-pre-release-commit-message = "Release v{{version}}"
-tag-message = "{{crate_name}} version {{version}}"
-no-dev-version = true
-pre-release-hook = ["cargo", "make", "pre-release"]
index 93da550aefca03bd5e07cb1d2b49fc2368abc9be..a84f9491a8174775f5fc8bfea464f60d6932cd73 100644 (file)
@@ -1,5 +1,7 @@
+#![doc(html_root_url = "https://docs.rs/opener/0.5.0")]
+
 //! This crate provides the [`open`] function, which opens a file or link with the default program
-//! configured on the system.
+//! configured on the system:
 //!
 //! ```no_run
 //! # fn main() -> Result<(), ::opener::OpenError> {
 //! # }
 //! ```
 //!
-//! ## Platform Implementation Details
-//! On Windows the `ShellExecuteW` Windows API function is used. On Mac the system `open` command is
-//! used. On other platforms, the `xdg-open` script is used. The system `xdg-open` is not used;
-//! instead a version is embedded within this library.
+//! An [`open_browser`] function is also provided, for when you intend on opening a file or link in a
+//! browser, specifically. This function works like the [`open`] function, but explicitly allows
+//! overriding the browser launched by setting the `$BROWSER` environment variable.
 
 #![warn(
     rust_2018_idioms,
     deprecated_in_future,
     macro_use_extern_crate,
     missing_debug_implementations,
-    unused_labels,
-    unused_qualifications,
-    clippy::cast_possible_truncation
+    unused_qualifications
 )]
 
+#[cfg(not(any(target_os = "windows", target_os = "macos")))]
+mod linux_and_more;
+#[cfg(target_os = "macos")]
+mod macos;
 #[cfg(target_os = "windows")]
-use crate::windows::open_sys;
+mod windows;
+
+#[cfg(not(any(target_os = "windows", target_os = "macos")))]
+use crate::linux_and_more as sys;
+#[cfg(target_os = "macos")]
+use crate::macos as sys;
+#[cfg(target_os = "windows")]
+use crate::windows as sys;
+
+use std::error::Error;
+use std::ffi::{OsStr, OsString};
+use std::fmt::{self, Display, Formatter};
+use std::process::{Command, ExitStatus, Stdio};
+use std::{env, io};
+
+/// Opens a file or link with the system default program.
+///
+/// Note that a path like "rustup.rs" could potentially refer to either a file or a website. If you
+/// want to open the website, you should add the "http://" prefix, for example.
+///
+/// Also note that a result of `Ok(())` just means a way of opening the path was found, and no error
+/// occurred as a direct result of opening the path. Errors beyond that point aren't caught. For
+/// example, `Ok(())` would be returned even if a file was opened with a program that can't read the
+/// file, or a dead link was opened in a browser.
+///
+/// ## Platform Implementation Details
+///
+/// - On Windows the `ShellExecuteW` Windows API function is used.
+/// - On Mac the system `open` command is used.
+/// - On Windows Subsystem for Linux (WSL), the system `wslview` from [`wslu`] is used if available,
+/// otherwise the system `xdg-open` is used, if available.
+/// - On non-WSL Linux and other platforms,
+/// the system `xdg-open` script is used if available, otherwise an `xdg-open` script embedded in
+/// this library is used.
+///
+/// [`wslu`]: https://github.com/wslutilities/wslu/
+pub fn open<P>(path: P) -> Result<(), OpenError>
+where
+    P: AsRef<OsStr>,
+{
+    sys::open(path.as_ref())
+}
 
-use std::{
-    error::Error,
-    ffi::OsStr,
-    fmt::{self, Display, Formatter},
-    io,
-    process::ExitStatus,
-};
+/// Opens a file or link with the system default program, using the `BROWSER` environment variable
+/// when set.
+///
+/// If the `BROWSER` environment variable is set, the program specified by it is used to open the
+/// path. If not, behavior is identical to [`open()`].
+pub fn open_browser<P>(path: P) -> Result<(), OpenError>
+where
+    P: AsRef<OsStr>,
+{
+    let mut path = path.as_ref();
+    if let Ok(browser_var) = env::var("BROWSER") {
+        let windows_path;
+        if is_wsl() && browser_var.ends_with(".exe") {
+            if let Some(windows_path_2) = wsl_to_windows_path(path) {
+                windows_path = windows_path_2;
+                path = &windows_path;
+            }
+        };
+
+        Command::new(&browser_var)
+            .arg(path)
+            .stdin(Stdio::null())
+            .stdout(Stdio::null())
+            .stderr(Stdio::piped())
+            .spawn()
+            .map_err(OpenError::Io)?;
+
+        Ok(())
+    } else {
+        sys::open(path)
+    }
+}
 
 /// An error type representing the failure to open a path. Possibly returned by the [`open`]
 /// function.
@@ -47,7 +116,7 @@ pub enum OpenError {
     /// An IO error occurred.
     Io(io::Error),
 
-    /// The command exited with a non-zero exit status.
+    /// A command exited with a non-zero exit status.
     ExitStatus {
         /// A string that identifies the command.
         cmd: &'static str,
@@ -97,129 +166,59 @@ impl Error for OpenError {
     }
 }
 
-impl From<io::Error> for OpenError {
-    fn from(err: io::Error) -> Self {
-        OpenError::Io(err)
-    }
+#[cfg(target_os = "linux")]
+fn is_wsl() -> bool {
+    sys::is_wsl()
 }
 
-/// Opens a file or link with the system default program.
-///
-/// Note that a path like "rustup.rs" could potentially refer to either a file or a website. If you
-/// want to open the website, you should add the "http://" prefix, for example.
-///
-/// Also note that a result of `Ok(())` just means a way of opening the path was found, and no error
-/// occurred as a direct result of opening the path. Errors beyond that point aren't caught. For
-/// example, `Ok(())` would be returned even if a file was opened with a program that can't read the
-/// file, or a dead link was opened in a browser.
-pub fn open<P>(path: P) -> Result<(), OpenError>
-where
-    P: AsRef<OsStr>,
-{
-    open_sys(path.as_ref())
+#[cfg(not(target_os = "linux"))]
+fn is_wsl() -> bool {
+    false
 }
 
-#[cfg(target_os = "windows")]
-mod windows {
-    use super::OpenError;
-    use std::{ffi::OsStr, io, os::windows::ffi::OsStrExt, ptr};
-    use winapi::{ctypes::c_int, um::shellapi::ShellExecuteW};
-
-    pub fn open_sys(path: &OsStr) -> Result<(), OpenError> {
-        const SW_SHOW: c_int = 5;
-
-        let path = convert_path(path)?;
-        let operation: Vec<u16> = OsStr::new("open\0").encode_wide().collect();
-        let result = unsafe {
-            ShellExecuteW(
-                ptr::null_mut(),
-                operation.as_ptr(),
-                path.as_ptr(),
-                ptr::null(),
-                ptr::null(),
-                SW_SHOW,
-            )
-        };
-        if result as c_int > 32 {
-            Ok(())
-        } else {
-            Err(io::Error::last_os_error().into())
-        }
-    }
+#[cfg(target_os = "linux")]
+fn wsl_to_windows_path(path: &OsStr) -> Option<OsString> {
+    use bstr::ByteSlice;
+    use std::os::unix::ffi::OsStringExt;
 
-    fn convert_path(path: &OsStr) -> io::Result<Vec<u16>> {
-        let mut maybe_result: Vec<u16> = path.encode_wide().collect();
-        if maybe_result.iter().any(|&u| u == 0) {
-            return Err(io::Error::new(
-                io::ErrorKind::InvalidInput,
-                "path contains NUL byte(s)",
-            ));
-        }
-        maybe_result.push(0);
-        Ok(maybe_result)
+    let output = Command::new("wslpath")
+        .arg("-w")
+        .arg(path)
+        .stdin(Stdio::null())
+        .stdout(Stdio::piped())
+        .stderr(Stdio::null())
+        .output()
+        .ok()?;
+
+    if !output.status.success() {
+        return None;
     }
-}
 
-#[cfg(target_os = "macos")]
-fn open_sys(path: &OsStr) -> Result<(), OpenError> {
-    open_not_windows("open", path, &[], None, "open")
+    Some(OsString::from_vec(output.stdout.trim_end().to_vec()))
 }
 
-#[cfg(not(any(target_os = "windows", target_os = "macos")))]
-fn open_sys(path: &OsStr) -> Result<(), OpenError> {
-    const XDG_OPEN_SCRIPT: &[u8] = include_bytes!("xdg-open");
-
-    open_not_windows(
-        "sh",
-        path,
-        &["-s"],
-        Some(XDG_OPEN_SCRIPT),
-        "xdg-open (internal)",
-    )
+#[cfg(not(target_os = "linux"))]
+fn wsl_to_windows_path(_path: &OsStr) -> Option<OsString> {
+    unreachable!()
 }
 
 #[cfg(not(target_os = "windows"))]
-fn open_not_windows(
-    cmd: &str,
-    path: &OsStr,
-    extra_args: &[&str],
-    piped_input: Option<&[u8]>,
-    cmd_friendly_name: &'static str,
-) -> Result<(), OpenError> {
-    use std::{
-        io::{Read, Write},
-        process::{Command, Stdio},
-    };
-
-    let stdin_type = if piped_input.is_some() {
-        Stdio::piped()
-    } else {
-        Stdio::null()
-    };
-
-    let mut cmd = Command::new(cmd)
-        .args(extra_args)
-        .arg(path)
-        .stdin(stdin_type)
-        .stdout(Stdio::null())
-        .stderr(Stdio::piped())
-        .spawn()?;
-
-    if let Some(stdin) = cmd.stdin.as_mut() {
-        stdin.write_all(piped_input.unwrap())?;
-    }
+fn wait_child(child: &mut std::process::Child, cmd_name: &'static str) -> Result<(), OpenError> {
+    use std::io::Read;
 
-    let exit_status = cmd.wait()?;
+    let exit_status = child.wait().map_err(OpenError::Io)?;
     if exit_status.success() {
         Ok(())
     } else {
-        let mut stderr = String::new();
-        cmd.stderr.as_mut().unwrap().read_to_string(&mut stderr)?;
+        let mut stderr_output = String::new();
+        if let Some(stderr) = child.stderr.as_mut() {
+            stderr.read_to_string(&mut stderr_output).ok();
+        }
 
         Err(OpenError::ExitStatus {
-            cmd: cmd_friendly_name,
+            cmd: cmd_name,
             status: exit_status,
-            stderr,
+            stderr: stderr_output,
         })
     }
 }
diff --git a/vendor/opener/src/linux_and_more.rs b/vendor/opener/src/linux_and_more.rs
new file mode 100644 (file)
index 0000000..87be414
--- /dev/null
@@ -0,0 +1,108 @@
+use crate::OpenError;
+use std::ffi::OsStr;
+use std::io::Write;
+use std::process::{Child, Command, Stdio};
+use std::{fs, io};
+
+const XDG_OPEN_SCRIPT: &[u8] = include_bytes!("xdg-open");
+
+pub(crate) fn open(path: &OsStr) -> Result<(), OpenError> {
+    if crate::is_wsl() {
+        wsl_open(path)
+    } else {
+        non_wsl_open(path)
+    }
+}
+
+fn wsl_open(path: &OsStr) -> Result<(), OpenError> {
+    let result = open_with_wslview(path);
+    if let Ok(mut child) = result {
+        return crate::wait_child(&mut child, "wslview");
+    }
+
+    open_with_system_xdg_open(path).map_err(OpenError::Io)?;
+
+    Ok(())
+}
+
+fn non_wsl_open(path: &OsStr) -> Result<(), OpenError> {
+    if open_with_system_xdg_open(path).is_err() {
+        open_with_internal_xdg_open(path)?;
+    }
+
+    Ok(())
+}
+
+fn open_with_wslview(path: &OsStr) -> io::Result<Child> {
+    let converted_path = crate::wsl_to_windows_path(path);
+    let converted_path = converted_path.as_deref();
+    let path = match converted_path {
+        None => path,
+        Some(x) => x,
+    };
+
+    Command::new("wslview")
+        .arg(path)
+        .stdin(Stdio::null())
+        .stdout(Stdio::null())
+        .stderr(Stdio::piped())
+        .spawn()
+}
+
+fn open_with_system_xdg_open(path: &OsStr) -> io::Result<Child> {
+    Command::new("xdg-open")
+        .arg(path)
+        .stdin(Stdio::null())
+        .stdout(Stdio::null())
+        .stderr(Stdio::null())
+        .spawn()
+}
+
+fn open_with_internal_xdg_open(path: &OsStr) -> Result<Child, OpenError> {
+    let mut sh = Command::new("sh")
+        .arg("-s")
+        .arg(path)
+        .stdin(Stdio::piped())
+        .stdout(Stdio::null())
+        .stderr(Stdio::null())
+        .spawn()
+        .map_err(OpenError::Io)?;
+
+    sh.stdin
+        .as_mut()
+        .unwrap()
+        .write_all(XDG_OPEN_SCRIPT)
+        .map_err(OpenError::Io)?;
+
+    Ok(sh)
+}
+
+pub(crate) fn is_wsl() -> bool {
+    if is_docker() {
+        return false;
+    }
+
+    if let Ok(true) = fs::read_to_string("/proc/sys/kernel/osrelease")
+        .map(|osrelease| osrelease.to_ascii_lowercase().contains("microsoft"))
+    {
+        return true;
+    }
+
+    if let Ok(true) = fs::read_to_string("/proc/version")
+        .map(|version| version.to_ascii_lowercase().contains("microsoft"))
+    {
+        return true;
+    }
+
+    false
+}
+
+fn is_docker() -> bool {
+    let has_docker_env = fs::metadata("/.dockerenv").is_ok();
+
+    let has_docker_cgroup = fs::read_to_string("/proc/self/cgroup")
+        .map(|cgroup| cgroup.to_ascii_lowercase().contains("docker"))
+        .unwrap_or(false);
+
+    has_docker_env || has_docker_cgroup
+}
diff --git a/vendor/opener/src/macos.rs b/vendor/opener/src/macos.rs
new file mode 100644 (file)
index 0000000..0459ae8
--- /dev/null
@@ -0,0 +1,15 @@
+use crate::OpenError;
+use std::ffi::OsStr;
+use std::process::{Command, Stdio};
+
+pub(crate) fn open(path: &OsStr) -> Result<(), OpenError> {
+    let mut open = Command::new("open")
+        .arg(path)
+        .stdin(Stdio::null())
+        .stdout(Stdio::null())
+        .stderr(Stdio::piped())
+        .spawn()
+        .map_err(OpenError::Io)?;
+
+    crate::wait_child(&mut open, "open")
+}
diff --git a/vendor/opener/src/windows.rs b/vendor/opener/src/windows.rs
new file mode 100644 (file)
index 0000000..829bdb0
--- /dev/null
@@ -0,0 +1,41 @@
+use crate::OpenError;
+use std::ffi::OsStr;
+use std::os::windows::ffi::OsStrExt;
+use std::{io, ptr};
+use winapi::ctypes::c_int;
+use winapi::um::shellapi::ShellExecuteW;
+
+pub(crate) fn open(path: &OsStr) -> Result<(), OpenError> {
+    const SW_SHOW: c_int = 5;
+
+    let path = convert_path(path).map_err(OpenError::Io)?;
+    let operation: Vec<u16> = OsStr::new("open\0").encode_wide().collect();
+    let result = unsafe {
+        ShellExecuteW(
+            ptr::null_mut(),
+            operation.as_ptr(),
+            path.as_ptr(),
+            ptr::null(),
+            ptr::null(),
+            SW_SHOW,
+        )
+    };
+    if result as c_int > 32 {
+        Ok(())
+    } else {
+        Err(OpenError::Io(io::Error::last_os_error()))
+    }
+}
+
+fn convert_path(path: &OsStr) -> io::Result<Vec<u16>> {
+    let mut maybe_result: Vec<u16> = path.encode_wide().collect();
+    if maybe_result.iter().any(|&u| u == 0) {
+        return Err(io::Error::new(
+            io::ErrorKind::InvalidInput,
+            "path contains NUL byte(s)",
+        ));
+    }
+
+    maybe_result.push(0);
+    Ok(maybe_result)
+}
old mode 100644 (file)
new mode 100755 (executable)
index 535ca4b..db75e14
@@ -815,7 +815,7 @@ search_desktop_file()
         fi
     fi
 
-    for d in $dir/*/; do
+    for d in "$dir/"*/; do
         [ -d "$d" ] && search_desktop_file "$default" "$d" "$target"
     done
 }
diff --git a/vendor/opener/tests/version-numbers.rs b/vendor/opener/tests/version-numbers.rs
new file mode 100644 (file)
index 0000000..cfcb258
--- /dev/null
@@ -0,0 +1,4 @@
+#[test]\r
+fn test_html_root_url() {\r
+    version_sync::assert_html_root_url_updated!("src/lib.rs");\r
+}\r
index 1d25094fb4c471fd54062f98efb41fab45a4f786..e64dec6bdfc94d3c7015edf816427a2184d17681 100644 (file)
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"22171a2d3eb9a2463cb7241d2082a280eb61031921c3a5a831b7303ed3c9c7ed","Cargo.toml":"e48869c4019894d0458f0f70968c4da16c4af37ba98e1d3aaeece154e4063c1f","LICENSE-APACHE":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"94f60b0c293aaf34041640c7f407da96bc3824a9e1efe20bd12c23aee6c196f7","src/lib.rs":"675bded8e4b1eeff1594cf003bf2f470b80f68daaaa1cf398d844c23e4dfc3c4","tests/auxiliary/mod.rs":"7e263e987e09b77e384f734384a00a71c5b70230bb1b5376446ef003a8da9372","tests/compiletest.rs":"eb16ecdecd1c9d01534b749579ee6c03f9b829d5938dcb85ef9c2916176b5d1e","tests/drop_order.rs":"817c5a7aef9c149e7d09c8a26aeb3b9e333d79a60391c5badbc3e325cbabbd12","tests/expand/README.md":"060f1800da3356e601ba3995525cfa497b219930fe1dd9a2c5696d9a809b4268","tests/expand/default/enum.expanded.rs":"c3c209d45c02d22873e464a57d7342ec775b002e6f0056481909c8d56038e9be","tests/expand/default/enum.rs":"493d5752c4baa87ed4c48bd41b8e5e263fd5e3f43c4f9195818ef6d26951f63e","tests/expand/default/struct.expanded.rs":"c158632984eaf6ab8ae60b76ff2bf32b20ba10a3cbc4237c9a6ea28c614cdb01","tests/expand/default/struct.rs":"5a6e57d9b6d00cfd4e1e69f37ce0c9d5165a21230d0363f0791665b1015870ce","tests/expand/multifields/enum.expanded.rs":"194b02f37b170f297fa39375cca71c378acf66b1729e2799434c48a5c7e34ace","tests/expand/multifields/enum.rs":"9c79270a7d6d1d42cf8194b579d79e7d44a3fd003243742f0a568ecf0a4f3be3","tests/expand/multifields/struct.expanded.rs":"0c98b4d085237f123c5455d558e495b2754ca84048f63df6416ef271610ee1c0","tests/expand/multifields/struct.rs":"17f0447d522d48f14d516808bd66baacebdf3ac38188df72f649702a893cda68","tests/expand/naming/enum-all.expanded.rs":"c3c209d45c02d22873e464a57d7342ec775b002e6f0056481909c8d56038e9be","tests/expand/naming/enum-all.rs":"493d5752c4baa87ed4c48bd41b8e5e263fd5e3f43c4f9195818ef6d26951f63e","tests/expand/naming/enum-mut.expanded.rs":"ce1a12428d3906c8d98516b3afdcbbbda64776e2f0c039e90f3de8f734ab1878","tests/expand/naming/enum-mut.rs":"c1ff4ade049ebbceb2acb99dbc1af5db14de3ba9710ea1ff1b64348766a9e080","tests/expand/naming/enum-none.expanded.rs":"cf8ea074b8079af453a2f98e2217704e96174433e4ac0e07577f9242ad3d5de2","tests/expand/naming/enum-none.rs":"ff22be4ecf4168e2bc68ab249a0ed809a37e3b8e840ef8977d24209ef28ac839","tests/expand/naming/enum-ref.expanded.rs":"277e9642e49f4dc312ea09b4d9f8012994662f565529865102be0fe1657c2b13","tests/expand/naming/enum-ref.rs":"394cbd5d872449e9226cd0834ce7117c395a582567584218dabbef4eb2c1fbac","tests/expand/naming/struct-all.expanded.rs":"722a17838aa9734f58a23ee15ff478788af5998a1ffc97c28aa040bc50612118","tests/expand/naming/struct-all.rs":"c13c0aacee85b8fca58f85d2d75d2e3907b3e7642f8710ed8c8e54d6015881cc","tests/expand/naming/struct-mut.expanded.rs":"f08b34f7d49ad45ae0a1ae8b64995d63e7e4eed2910a912f6c622a0b8e410b89","tests/expand/naming/struct-mut.rs":"9a7752a6d30e0b7033f3577a72676676900a642cdaf59f942179d1f2a8ba2bb0","tests/expand/naming/struct-none.expanded.rs":"c158632984eaf6ab8ae60b76ff2bf32b20ba10a3cbc4237c9a6ea28c614cdb01","tests/expand/naming/struct-none.rs":"5a6e57d9b6d00cfd4e1e69f37ce0c9d5165a21230d0363f0791665b1015870ce","tests/expand/naming/struct-ref.expanded.rs":"dabc3fda847ab2f4e4ca0ec6f6dc4da43f8de087117dcafb3c15780cebc7af45","tests/expand/naming/struct-ref.rs":"33c4fd344b65650dee44087ada31d4b5acd9d122123360fb7d41718c46699574","tests/expand/pub/enum.expanded.rs":"56c81c0535f8fb9b83662fc3753f7c07b96eb12392669bb1ae23ffc82b7c4a2c","tests/expand/pub/enum.rs":"5b60dd354a489b0326f5c4f1026b89d1471ddbb45906bc3046a65425c4e5e160","tests/expand/pub/struct.expanded.rs":"525c52bf7185493046618ee0dc1b18bdc0c0a56383f5c7b11c98738211d024a7","tests/expand/pub/struct.rs":"15b7940ce0ad1d5d133dde1870319f2f96a000bfcf29508b8cce1a62876cbd80","tests/expandtest.rs":"a091cc8b0684358e327992a2acc7b7e4738d725b0e643a5ee3e8f5f1d7415608","tests/include/basic.rs":"9e399b682bc74c899d26924c2cab52a911f7392e29300defb6521e561fafafe4","tests/lint.rs":"13ccf3b5e464d6506915c2c57555a3f293bd7405fde5aac008af913df327ffa4","tests/proper_unpin.rs":"57a9e8c9029ba7920ec23670b66758916e067c9cecf4d3f8b0035bec25cdb570","tests/test.rs":"ef4efe0ce333e6a0d4c8574d139e522e408d2a48db07e0015e3e9bc8734f79d2","tests/ui/pin_project/conflict-drop.rs":"55e6809b5f59dd81e32c2c89b742c0c76db6b099a1d2621e5b882c0d20f92837","tests/ui/pin_project/conflict-drop.stderr":"b29a458533f0312b2b04e9a0dfea17fce2ba423ef764ec3e2996a315c00a4cf8","tests/ui/pin_project/conflict-unpin.rs":"51b3b6720fa581b63167d6ac941a1ea1bf739b09954931b2bc2f7abe2d934f26","tests/ui/pin_project/conflict-unpin.stderr":"ab8e9acab4ffcdff1d0065e9504d64a0220267ab9f18b2840c97da8c0bbbf984","tests/ui/pin_project/invalid-bounds.rs":"f86f23d377df015182f2f5dae6464a4f98c37f2198e0646f721fedc4017cb82c","tests/ui/pin_project/invalid-bounds.stderr":"e93d9bc35080dacb837f2e626947b7ec57fea36c0246d839c295a93c33bf7e5b","tests/ui/pin_project/invalid.rs":"7304bd4a5bac1419382742432cfa8af83535d7be8cfad52c661410e0e9e8207a","tests/ui/pin_project/invalid.stderr":"a9da7ba0d2dc729137c1736d355c52de1d34fdf10eb4fa35be07b2644d6dfad3","tests/ui/pin_project/overlapping_lifetime_names.rs":"a64c42cc56fa4751d73a1db80a7deb568427dc96f30c1a29665067d8c0ecb2c9","tests/ui/pin_project/overlapping_lifetime_names.stderr":"ebfd5c08e7c472f49d49d67de9308e647a6a6b1e289308bf2d60d79d72521457","tests/ui/pin_project/overlapping_unpin_struct.rs":"5fde23ef628d2dbd27377ffa472fc19b1c6873122f38c3fb1f84fda8602f55f3","tests/ui/pin_project/overlapping_unpin_struct.stderr":"e83e99bacdf6564727c77dafe5eaf000b4de6e784e6032b9b0ecca831ecc528c","tests/ui/pin_project/packed.rs":"1f1a34aafbff9a59b94cdf3a53df03e9fc661d9e27e0f9962bad7f9bdad03b14","tests/ui/pin_project/packed.stderr":"4acb1514ca0a2c3b9448b28a71ab81d1dce37ba42f1af8b3220f926f0ca556e4","tests/ui/pin_project/unpin_sneaky.rs":"12e97a387ce1af6ee6a567687674aab70e96962a48f2433c39976d0b3e2c3341","tests/ui/pin_project/unpin_sneaky.stderr":"7b2bc76faca39f77968c798674f2321111a74a5754512149320ea4cdd3e278d5","tests/ui/pin_project/unsupported.rs":"14defa90e736f314bbbc219973929b77bdd22e5f7e4c4c88403db764f4d167d6","tests/ui/pin_project/unsupported.stderr":"562db085e5e01dedaa3cb11c592f61f33c5a6388a31e6f1ed9554874cfa2c673"},"package":"dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"ec96e73a38410d7b26282cc53c41aecbbf65d5d799abc1438cb6dc6897188d15","Cargo.toml":"99321d72395cb43843563785603744c25500e127e3aa125c249ba631f0d2b5ee","LICENSE-APACHE":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"019a22e1809732ec43b9a5e4f664778ea7843173619041314b0b9f887a5df0d5","src/lib.rs":"34951f11e5586e6558a01a34225f2f6b7865c5f59f7378d445c81fd36f9acda6","tests/auxiliary/mod.rs":"7e263e987e09b77e384f734384a00a71c5b70230bb1b5376446ef003a8da9372","tests/compiletest.rs":"e68e2850534f1e590e92216835bbedaf4be2ebaa2371f18a766240dc3a14460a","tests/drop_order.rs":"2cb31a8cd5cf4d9a4ba9faf25f99f0e85f9bd7b4778649f843d9c617c6af43fc","tests/expand/README.md":"060f1800da3356e601ba3995525cfa497b219930fe1dd9a2c5696d9a809b4268","tests/expand/default/enum.expanded.rs":"c3c209d45c02d22873e464a57d7342ec775b002e6f0056481909c8d56038e9be","tests/expand/default/enum.rs":"493d5752c4baa87ed4c48bd41b8e5e263fd5e3f43c4f9195818ef6d26951f63e","tests/expand/default/struct.expanded.rs":"c158632984eaf6ab8ae60b76ff2bf32b20ba10a3cbc4237c9a6ea28c614cdb01","tests/expand/default/struct.rs":"5a6e57d9b6d00cfd4e1e69f37ce0c9d5165a21230d0363f0791665b1015870ce","tests/expand/multifields/enum.expanded.rs":"194b02f37b170f297fa39375cca71c378acf66b1729e2799434c48a5c7e34ace","tests/expand/multifields/enum.rs":"9c79270a7d6d1d42cf8194b579d79e7d44a3fd003243742f0a568ecf0a4f3be3","tests/expand/multifields/struct.expanded.rs":"0c98b4d085237f123c5455d558e495b2754ca84048f63df6416ef271610ee1c0","tests/expand/multifields/struct.rs":"17f0447d522d48f14d516808bd66baacebdf3ac38188df72f649702a893cda68","tests/expand/naming/enum-all.expanded.rs":"c3c209d45c02d22873e464a57d7342ec775b002e6f0056481909c8d56038e9be","tests/expand/naming/enum-all.rs":"493d5752c4baa87ed4c48bd41b8e5e263fd5e3f43c4f9195818ef6d26951f63e","tests/expand/naming/enum-mut.expanded.rs":"ce1a12428d3906c8d98516b3afdcbbbda64776e2f0c039e90f3de8f734ab1878","tests/expand/naming/enum-mut.rs":"c1ff4ade049ebbceb2acb99dbc1af5db14de3ba9710ea1ff1b64348766a9e080","tests/expand/naming/enum-none.expanded.rs":"cf8ea074b8079af453a2f98e2217704e96174433e4ac0e07577f9242ad3d5de2","tests/expand/naming/enum-none.rs":"ff22be4ecf4168e2bc68ab249a0ed809a37e3b8e840ef8977d24209ef28ac839","tests/expand/naming/enum-ref.expanded.rs":"277e9642e49f4dc312ea09b4d9f8012994662f565529865102be0fe1657c2b13","tests/expand/naming/enum-ref.rs":"394cbd5d872449e9226cd0834ce7117c395a582567584218dabbef4eb2c1fbac","tests/expand/naming/struct-all.expanded.rs":"722a17838aa9734f58a23ee15ff478788af5998a1ffc97c28aa040bc50612118","tests/expand/naming/struct-all.rs":"c13c0aacee85b8fca58f85d2d75d2e3907b3e7642f8710ed8c8e54d6015881cc","tests/expand/naming/struct-mut.expanded.rs":"f08b34f7d49ad45ae0a1ae8b64995d63e7e4eed2910a912f6c622a0b8e410b89","tests/expand/naming/struct-mut.rs":"9a7752a6d30e0b7033f3577a72676676900a642cdaf59f942179d1f2a8ba2bb0","tests/expand/naming/struct-none.expanded.rs":"c158632984eaf6ab8ae60b76ff2bf32b20ba10a3cbc4237c9a6ea28c614cdb01","tests/expand/naming/struct-none.rs":"5a6e57d9b6d00cfd4e1e69f37ce0c9d5165a21230d0363f0791665b1015870ce","tests/expand/naming/struct-ref.expanded.rs":"dabc3fda847ab2f4e4ca0ec6f6dc4da43f8de087117dcafb3c15780cebc7af45","tests/expand/naming/struct-ref.rs":"33c4fd344b65650dee44087ada31d4b5acd9d122123360fb7d41718c46699574","tests/expand/pinned_drop/enum.expanded.rs":"56d709a0cfc0c951fe303bf2b034e7fae4fc5271b9a11ade9c6a9c20c89471b3","tests/expand/pinned_drop/enum.rs":"d7e087b6852338fabe7edf39529c8f893a426b4d0c6aba2d2a6be0d95f739cdc","tests/expand/pinned_drop/struct.expanded.rs":"c9b26224339f126ce5f0d36cd8d6c6e84970bf39b94dc11bc42743ad5bdba6be","tests/expand/pinned_drop/struct.rs":"164a25e12b9898c093b5dee2c47a40dd549e6f49ba1c6bb22f4e4c4b98fe76b2","tests/expand/pub/enum.expanded.rs":"56c81c0535f8fb9b83662fc3753f7c07b96eb12392669bb1ae23ffc82b7c4a2c","tests/expand/pub/enum.rs":"5b60dd354a489b0326f5c4f1026b89d1471ddbb45906bc3046a65425c4e5e160","tests/expand/pub/struct.expanded.rs":"525c52bf7185493046618ee0dc1b18bdc0c0a56383f5c7b11c98738211d024a7","tests/expand/pub/struct.rs":"15b7940ce0ad1d5d133dde1870319f2f96a000bfcf29508b8cce1a62876cbd80","tests/expandtest.rs":"898df948c7ee82df0e0823cbde16ccc2b9dba455475665e6d2c7c0a84493e9fb","tests/include/basic.rs":"9e399b682bc74c899d26924c2cab52a911f7392e29300defb6521e561fafafe4","tests/lint.rs":"471a10989664d84bb5d1c8753585de4dd701b2cdc24b71c0cb5f9ea192597c61","tests/proper_unpin.rs":"57a9e8c9029ba7920ec23670b66758916e067c9cecf4d3f8b0035bec25cdb570","tests/test.rs":"b58a8a938938bf46f1f710ecd551292f896f00ff9cbf84987967ed00e5d5107c","tests/ui/pin_project/conflict-drop.rs":"55e6809b5f59dd81e32c2c89b742c0c76db6b099a1d2621e5b882c0d20f92837","tests/ui/pin_project/conflict-drop.stderr":"9bbab8ff00a43104ce46f4e6d8a17b520997fea5a8f1743bab4fa1a995dcd24d","tests/ui/pin_project/conflict-unpin.rs":"51b3b6720fa581b63167d6ac941a1ea1bf739b09954931b2bc2f7abe2d934f26","tests/ui/pin_project/conflict-unpin.stderr":"827cb36a769110dc2844ff5c85d387f96a92ff95ac0066a60465caacb762f100","tests/ui/pin_project/invalid-bounds.rs":"f86f23d377df015182f2f5dae6464a4f98c37f2198e0646f721fedc4017cb82c","tests/ui/pin_project/invalid-bounds.stderr":"27c7b439575503d16617c37e36f5478e3803a5c958c37e438c4f1ce84a3991fe","tests/ui/pin_project/invalid.rs":"7304bd4a5bac1419382742432cfa8af83535d7be8cfad52c661410e0e9e8207a","tests/ui/pin_project/invalid.stderr":"b95ca63870e7687e3b1a1f69e470692d5bc3875c1c27958c6ccec0f636d70ed0","tests/ui/pin_project/overlapping_lifetime_names.rs":"36c849a4570c8c0c32ca6c01aa75afbe1136ef73d45f17eb66175e1936678722","tests/ui/pin_project/overlapping_lifetime_names.stderr":"19d61fbcaa9061224cf0f911d236c3552a5ff93e3cc138f231f267ce4ab92b2e","tests/ui/pin_project/overlapping_unpin_struct.rs":"9a126182d1fe15a30ac60bb223b376aad747d11293d3cf512ad2dce546e3725c","tests/ui/pin_project/overlapping_unpin_struct.stderr":"eb79df698bf9aaca8cd200d0e1064277cf5c56ed833ba7214b7bc78d94d2839c","tests/ui/pin_project/packed.rs":"2ede405a0d101eb843ea83c2836cc8399da54c105776f2c795f3138e03a1e5ef","tests/ui/pin_project/packed.stderr":"2c02336ae457222d87fb28197a8582528051ca13fdb74a615798fdf3da2f3db0","tests/ui/pin_project/unpin_sneaky.rs":"12e97a387ce1af6ee6a567687674aab70e96962a48f2433c39976d0b3e2c3341","tests/ui/pin_project/unpin_sneaky.stderr":"7b2bc76faca39f77968c798674f2321111a74a5754512149320ea4cdd3e278d5","tests/ui/pin_project/unsupported.rs":"14defa90e736f314bbbc219973929b77bdd22e5f7e4c4c88403db764f4d167d6","tests/ui/pin_project/unsupported.stderr":"982da28433932d3ea9458bd543d1c589a81e6011d3be830bf23e26a6f2486e6e","tests/ui/pinned_drop/call-drop-inner.rs":"032260da1fc0e649d97167a8a4ac47eea915000efebdfdc490f050b6f9351027","tests/ui/pinned_drop/call-drop-inner.stderr":"c4998f39aa6a6d18941d0806b0ff693b9f2f0ec3a8056b678e2d78470926634c","tests/ui/pinned_drop/conditional-drop-impl.rs":"0b28c74213cee83e7b27223d7d37f903f79abd3dddcc0f969e14047674908085","tests/ui/pinned_drop/conditional-drop-impl.stderr":"8e416b2c01632c33cec611beb5ffb4817a50b15ad08ab9d0175ee45ba1311900"},"package":"8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"}
\ No newline at end of file
index 666dd6b91fe3bea1e14f0709df0e76eaa692f930..aaa107bbf302ddfb50dbfdb3e3acd34b504ae8cc 100644 (file)
@@ -10,6 +10,10 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com
 
 ## [Unreleased]
 
+## [0.2.7] - 2021-06-26
+
+- [Support custom Drop implementation.](https://github.com/taiki-e/pin-project-lite/pull/25) See [#25](https://github.com/taiki-e/pin-project-lite/pull/25) for details.
+
 ## [0.2.6] - 2021-03-04
 
 - [Support item attributes in any order.](https://github.com/taiki-e/pin-project-lite/pull/57)
@@ -184,7 +188,8 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com
 
 Initial release
 
-[Unreleased]: https://github.com/taiki-e/pin-project-lite/compare/v0.2.6...HEAD
+[Unreleased]: https://github.com/taiki-e/pin-project-lite/compare/v0.2.7...HEAD
+[0.2.7]: https://github.com/taiki-e/pin-project-lite/compare/v0.2.6...v0.2.7
 [0.2.6]: https://github.com/taiki-e/pin-project-lite/compare/v0.2.5...v0.2.6
 [0.2.5]: https://github.com/taiki-e/pin-project-lite/compare/v0.2.4...v0.2.5
 [0.2.4]: https://github.com/taiki-e/pin-project-lite/compare/v0.2.3...v0.2.4
index b24f836741b6c66e3ffca14038805deec206b06a..fab9dbcf93f31676805f8f349a1f9610de512ad8 100644 (file)
@@ -13,9 +13,9 @@
 [package]
 edition = "2018"
 name = "pin-project-lite"
-version = "0.2.6"
+version = "0.2.7"
 authors = ["Taiki Endo <te316e89@gmail.com>"]
-exclude = ["/.*", "/scripts"]
+exclude = ["/.*", "/tools"]
 description = "A lightweight version of pin-project written with declarative macros.\n"
 documentation = "https://docs.rs/pin-project-lite"
 keywords = ["pin", "macros"]
index fbdc9d1887e1c87ac6a7326b56faf3c87863b12b..e185993b928cad983e64193de99765e18a2c5d4c 100644 (file)
@@ -100,10 +100,6 @@ be useful in most cases. If you do need useful error messages, then upon
 error you can pass the same input to [pin-project] to receive a helpful
 description of the compile error.
 
-### Different: No support for custom Drop implementation
-
-pin-project supports this by [`#[pinned_drop]`][pinned-drop].
-
 ### Different: No support for custom Unpin implementation
 
 pin-project supports this by [`UnsafeUnpin`][unsafe-unpin] and [`!Unpin`][not-unpin].
@@ -115,7 +111,6 @@ pin-project supports this.
 [`pin_project!`]: https://docs.rs/pin-project-lite/0.2/pin_project_lite/macro.pin_project.html
 [not-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unpin
 [pin-project]: https://github.com/taiki-e/pin-project
-[pinned-drop]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#pinned_drop
 [unsafe-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unsafeunpin
 
 ## License
index 86163919f671256e1eb525221dec75a81d3b6980..9b69e64f22f444116a7c6746889fa20c993c5732 100644 (file)
 //! error you can pass the same input to [pin-project] to receive a helpful
 //! description of the compile error.
 //!
-//! ## Different: No support for custom Drop implementation
-//!
-//! pin-project supports this by [`#[pinned_drop]`][pinned-drop].
-//!
 //! ## Different: No support for custom Unpin implementation
 //!
 //! pin-project supports this by [`UnsafeUnpin`][unsafe-unpin] and [`!Unpin`][not-unpin].
@@ -96,7 +92,6 @@
 //!
 //! [not-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unpin
 //! [pin-project]: https://github.com/taiki-e/pin-project
-//! [pinned-drop]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#pinned_drop
 //! [unsafe-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unsafeunpin
 
 #![no_std]
     )
 ))]
 #![warn(future_incompatible, rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
-#![warn(clippy::all, clippy::default_trait_access)]
+#![warn(clippy::default_trait_access, clippy::wildcard_imports)]
 
 /// A macro that creates a projection type covering all the fields of struct.
 ///
@@ -331,6 +326,7 @@ macro_rules! __pin_project_internal {
                 $field_vis:vis $field:ident: $field_ty:ty
             ),+
         }
+        $(impl $($pinned_drop:tt)*)?
     ) => {
         $(#[$attrs])*
         $vis struct $ident $($def_generics)*
@@ -374,6 +370,7 @@ macro_rules! __pin_project_internal {
             [make_proj_field_replace]
             [$ident]
             [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+            [$(impl $($pinned_drop)*)?]
             {
                 $(
                     $(#[$pin])?
@@ -422,6 +419,7 @@ macro_rules! __pin_project_internal {
                 [make_proj_field_replace]
                 [$ident]
                 [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+                [$(impl $($pinned_drop)*)?]
                 {
                     $(
                         $(#[$pin])?
@@ -484,6 +482,7 @@ macro_rules! __pin_project_internal {
             $crate::__pin_project_internal! { @make_drop_impl;
                 [$ident]
                 [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+                $(impl $($pinned_drop)*)?
             }
 
             // Ensure that it's impossible to use pin projections on a #[repr(packed)] struct.
@@ -538,6 +537,7 @@ macro_rules! __pin_project_internal {
                 })?
             ),+
         }
+        $(impl $($pinned_drop:tt)*)?
     ) => {
         $(#[$attrs])*
         $vis enum $ident $($def_generics)*
@@ -594,6 +594,7 @@ macro_rules! __pin_project_internal {
             [make_proj_field_replace]
             [$ident]
             [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+            [$(impl $($pinned_drop)*)?]
             {
                 $(
                     $variant $({
@@ -682,6 +683,7 @@ macro_rules! __pin_project_internal {
             $crate::__pin_project_internal! { @make_drop_impl;
                 [$ident]
                 [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+                $(impl $($pinned_drop)*)?
             }
 
             // We don't need to check for '#[repr(packed)]',
@@ -765,6 +767,7 @@ macro_rules! __pin_project_internal {
         [$make_proj_field:ident]
         [$ident:ident]
         [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+        [$(impl $($pinned_drop:tt)*)?]
         $($field:tt)*
     ) => {};
     (@struct=>make_proj_replace_ty=>unnamed;
@@ -773,15 +776,16 @@ macro_rules! __pin_project_internal {
         [$make_proj_field:ident]
         [$ident:ident]
         [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+        [$(impl $($pinned_drop:tt)*)?]
         $($field:tt)*
-    ) => {
-    };
+    ) => {};
     (@struct=>make_proj_replace_ty=>named;
         [$proj_vis:vis]
         [$proj_ty_ident:ident]
         [$make_proj_field:ident]
         [$ident:ident]
         [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+        []
         {
             $(
                 $(#[$pin:ident])?
@@ -811,6 +815,7 @@ macro_rules! __pin_project_internal {
         [$make_proj_field:ident]
         [$ident:ident]
         [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+        [$(impl $($pinned_drop:tt)*)?]
         $($field:tt)*
     ) => {};
     // =============================================================================================
@@ -872,6 +877,7 @@ macro_rules! __pin_project_internal {
         [$make_proj_field:ident]
         [$ident:ident]
         [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+        []
         {
             $(
                 $variant:ident $({
@@ -909,6 +915,7 @@ macro_rules! __pin_project_internal {
         [$make_proj_field:ident]
         [$ident:ident]
         [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+        [$(impl $($pinned_drop:tt)*)?]
         $($variant:tt)*
     ) => {};
 
@@ -1164,11 +1171,11 @@ macro_rules! __pin_project_internal {
         // this will become a lint, rather then a hard error.
         //
         // As a workaround for this, we generate a new struct, containing all of the pinned
-        // fields from our #[pin_project] type. This struct is delcared within
+        // fields from our #[pin_project] type. This struct is declared within
         // a function, which makes it impossible to be named by user code.
-        // This guarnatees that it will use the default auto-trait impl for Unpin -
+        // This guarantees that it will use the default auto-trait impl for Unpin -
         // that is, it will implement Unpin iff all of its fields implement Unpin.
-        // This type can be safely declared as 'public', satisfiying the privacy
+        // This type can be safely declared as 'public', satisfying the privacy
         // checker without actually allowing user code to access it.
         //
         // This allows users to apply the #[pin_project] attribute to types
@@ -1193,6 +1200,90 @@ macro_rules! __pin_project_internal {
 
     // =============================================================================================
     // make_drop_impl
+    (@make_drop_impl;
+        [$_ident:ident]
+        [$($_impl_generics:tt)*] [$($_ty_generics:tt)*] [$(where $($_where_clause:tt)* )?]
+        impl $(<
+            $( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),* $(,)?
+            $( $generics:ident
+                $(: $generics_bound:path)?
+                $(: ?$generics_unsized_bound:path)?
+                $(: $generics_lifetime_bound:lifetime)?
+            ),*
+        >)? PinnedDrop for $self_ty:ty
+        $(where
+            $( $where_clause_ty:ty
+                $(: $where_clause_bound:path)?
+                $(: ?$where_clause_unsized_bound:path)?
+                $(: $where_clause_lifetime_bound:lifetime)?
+            ),*
+        )?
+        {
+            fn drop($($arg:ident)+: Pin<&mut Self>) {
+                $($tt:tt)*
+            }
+        }
+    ) => {
+        impl $(<
+            $( $lifetime $(: $lifetime_bound)? ,)*
+            $( $generics
+                $(: $generics_bound)?
+                $(: ?$generics_unsized_bound)?
+                $(: $generics_lifetime_bound)?
+            ),*
+        >)? $crate::__private::Drop for $self_ty
+        $(where
+            $( $where_clause_ty
+                $(: $where_clause_bound)?
+                $(: ?$where_clause_unsized_bound)?
+                $(: $where_clause_lifetime_bound)?
+            ),*
+        )?
+        {
+            fn drop(&mut self) {
+                // Implementing `__DropInner::__drop_inner` is safe, but calling it is not safe.
+                // This is because destructors can be called multiple times in safe code and
+                // [double dropping is unsound](https://github.com/rust-lang/rust/pull/62360).
+                //
+                // `__drop_inner` is defined as a safe method, but this is fine since
+                // `__drop_inner` is not accessible by the users and we call `__drop_inner` only
+                // once.
+                //
+                // Users can implement [`Drop`] safely using `pin_project!` and can drop a
+                // type that implements `PinnedDrop` using the [`drop`] function safely.
+                fn __drop_inner $(<
+                    $( $lifetime $(: $lifetime_bound)? ,)*
+                    $( $generics
+                        $(: $generics_bound)?
+                        $(: ?$generics_unsized_bound)?
+                        $(: $generics_lifetime_bound)?
+                    ),*
+                >)? (
+                    $($arg)+: $crate::__private::Pin<&mut $self_ty>,
+                )
+                $(where
+                    $( $where_clause_ty
+                        $(: $where_clause_bound)?
+                        $(: ?$where_clause_unsized_bound)?
+                        $(: $where_clause_lifetime_bound)?
+                    ),*
+                )?
+                {
+                    // A dummy `__drop_inner` function to prevent users call outer `__drop_inner`.
+                    fn __drop_inner() {}
+                    $($tt)*
+                }
+
+                // Safety - we're in 'drop', so we know that 'self' will
+                // never move again.
+                let pinned_self: $crate::__private::Pin<&mut Self>
+                    = unsafe { $crate::__private::Pin::new_unchecked(self) };
+                // We call `__drop_inner` only once. Since `__DropInner::__drop_inner`
+                // is not accessible by the users, it is never called again.
+                __drop_inner(pinned_self);
+            }
+        }
+    };
     (@make_drop_impl;
         [$ident:ident]
         [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
@@ -1204,7 +1295,7 @@ macro_rules! __pin_project_internal {
         // the first blanked impl will not apply to it. This code
         // will compile, as there is only one impl of MustNotImplDrop for the user type
         // 2. The user type does impl Drop. This will make the blanket impl applicable,
-        // which will then comflict with the explicit MustNotImplDrop impl below.
+        // which will then conflict with the explicit MustNotImplDrop impl below.
         // This will result in a compilation error, which is exactly what we want.
         trait MustNotImplDrop {}
         #[allow(clippy::drop_bounds, drop_bounds)]
@@ -1414,6 +1505,7 @@ macro_rules! __pin_project_internal {
                 $field_vis:vis $field:ident: $field_ty:ty
             ),+ $(,)?
         }
+        $(impl $($pinned_drop:tt)*)?
     ) => {
         $crate::__pin_project_internal! { @struct=>internal;
             [$($proj_mut_ident)?]
@@ -1450,6 +1542,7 @@ macro_rules! __pin_project_internal {
                     $field_vis $field: $field_ty
                 ),+
             }
+            $(impl $($pinned_drop)*)?
         }
     };
     (
@@ -1480,6 +1573,7 @@ macro_rules! __pin_project_internal {
                 $field_vis:vis $field:ident: $field_ty:ty
             ),+ $(,)?
         }
+        $(impl $($pinned_drop:tt)*)?
     ) => {
         $crate::__pin_project_internal! { @struct=>internal;
             [$($proj_mut_ident)?]
@@ -1516,6 +1610,7 @@ macro_rules! __pin_project_internal {
                     $field_vis $field: $field_ty
                 ),+
             }
+            $(impl $($pinned_drop)*)?
         }
     };
     // enum
@@ -1552,6 +1647,7 @@ macro_rules! __pin_project_internal {
                 })?
             ),+ $(,)?
         }
+        $(impl $($pinned_drop:tt)*)?
     ) => {
         $crate::__pin_project_internal! { @enum=>internal;
             [$($proj_mut_ident)?]
@@ -1593,6 +1689,7 @@ macro_rules! __pin_project_internal {
                     })?
                 ),+
             }
+            $(impl $($pinned_drop)*)?
         }
     };
     (
@@ -1628,6 +1725,7 @@ macro_rules! __pin_project_internal {
                 })?
             ),+ $(,)?
         }
+        $(impl $($pinned_drop:tt)*)?
     ) => {
         $crate::__pin_project_internal! { @enum=>internal;
             [$($proj_mut_ident)?]
@@ -1669,6 +1767,7 @@ macro_rules! __pin_project_internal {
                     })?
                 ),+
             }
+            $(impl $($pinned_drop)*)?
         }
     };
 }
index 77e913bc44ad21329a5634839352393725603785..8970215e7d22fd0ab7c2df5f29446964dc99ac83 100644 (file)
@@ -3,7 +3,7 @@
 
 use std::env;
 
-#[rustversion::attr(before(2020-12-03), ignore)] // Note: This date is commit-date and the day before the toolchain date.
+#[rustversion::attr(before(2021-05-15), ignore)] // Note: This date is commit-date and the day before the toolchain date.
 #[test]
 fn ui() {
     if env::var_os("CI").is_none() {
index 07120ccdb7f02ede2dfe18a96da31f0a65e7387c..6e5deaf1546474e628bb185cdd882534d75b2c22 100644 (file)
@@ -129,7 +129,7 @@ fn project_replace_panic() {
         fn drop(&mut self) {
             *self.0 = true;
             if self.1 {
-                panic!()
+                panic!();
             }
         }
     }
diff --git a/vendor/pin-project-lite/tests/expand/pinned_drop/enum.expanded.rs b/vendor/pin-project-lite/tests/expand/pinned_drop/enum.expanded.rs
new file mode 100644 (file)
index 0000000..665ff63
--- /dev/null
@@ -0,0 +1,95 @@
+use pin_project_lite::pin_project;
+use std::pin::Pin;
+enum Enum<T, U> {
+    Struct { pinned: T, unpinned: U },
+    Unit,
+}
+#[allow(dead_code)]
+#[allow(single_use_lifetimes)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::mut_mut)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::ref_option_ref)]
+#[allow(clippy::type_repetition_in_bounds)]
+enum EnumProj<'__pin, T, U>
+where
+    Enum<T, U>: '__pin,
+{
+    Struct {
+        pinned: ::pin_project_lite::__private::Pin<&'__pin mut (T)>,
+        unpinned: &'__pin mut (U),
+    },
+    Unit,
+}
+#[allow(dead_code)]
+#[allow(single_use_lifetimes)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::mut_mut)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::ref_option_ref)]
+#[allow(clippy::type_repetition_in_bounds)]
+enum EnumProjRef<'__pin, T, U>
+where
+    Enum<T, U>: '__pin,
+{
+    Struct {
+        pinned: ::pin_project_lite::__private::Pin<&'__pin (T)>,
+        unpinned: &'__pin (U),
+    },
+    Unit,
+}
+#[allow(single_use_lifetimes)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    impl<T, U> Enum<T, U> {
+        fn project<'__pin>(
+            self: ::pin_project_lite::__private::Pin<&'__pin mut Self>,
+        ) -> EnumProj<'__pin, T, U> {
+            unsafe {
+                match self.get_unchecked_mut() {
+                    Self::Struct { pinned, unpinned } => EnumProj::Struct {
+                        pinned: ::pin_project_lite::__private::Pin::new_unchecked(pinned),
+                        unpinned: unpinned,
+                    },
+                    Self::Unit => EnumProj::Unit,
+                }
+            }
+        }
+        fn project_ref<'__pin>(
+            self: ::pin_project_lite::__private::Pin<&'__pin Self>,
+        ) -> EnumProjRef<'__pin, T, U> {
+            unsafe {
+                match self.get_ref() {
+                    Self::Struct { pinned, unpinned } => EnumProjRef::Struct {
+                        pinned: ::pin_project_lite::__private::Pin::new_unchecked(pinned),
+                        unpinned: unpinned,
+                    },
+                    Self::Unit => EnumProjRef::Unit,
+                }
+            }
+        }
+    }
+    #[allow(non_snake_case)]
+    struct __Origin<'__pin, T, U> {
+        __dummy_lifetime: ::pin_project_lite::__private::PhantomData<&'__pin ()>,
+        Struct: (T, ::pin_project_lite::__private::AlwaysUnpin<U>),
+        Unit: (),
+    }
+    impl<'__pin, T, U> ::pin_project_lite::__private::Unpin for Enum<T, U> where
+        __Origin<'__pin, T, U>: ::pin_project_lite::__private::Unpin
+    {
+    }
+    impl<T, U> ::pin_project_lite::__private::Drop for Enum<T, U> {
+        fn drop(&mut self) {
+            fn __drop_inner<T, U>(this: ::pin_project_lite::__private::Pin<&mut Enum<T, U>>) {
+                fn __drop_inner() {}
+                let _ = this;
+            }
+            let pinned_self: ::pin_project_lite::__private::Pin<&mut Self> =
+                unsafe { ::pin_project_lite::__private::Pin::new_unchecked(self) };
+            __drop_inner(pinned_self);
+        }
+    }
+};
+fn main() {}
diff --git a/vendor/pin-project-lite/tests/expand/pinned_drop/enum.rs b/vendor/pin-project-lite/tests/expand/pinned_drop/enum.rs
new file mode 100644 (file)
index 0000000..1855cb7
--- /dev/null
@@ -0,0 +1,22 @@
+use pin_project_lite::pin_project;
+use std::pin::Pin;
+
+pin_project! {
+    #[project = EnumProj]
+    #[project_ref = EnumProjRef]
+    enum Enum<T, U> {
+        Struct {
+            #[pin]
+            pinned: T,
+            unpinned: U,
+        },
+        Unit,
+    }
+    impl<T, U> PinnedDrop for Enum<T, U> {
+        fn drop(this: Pin<&mut Self>) {
+            let _ = this;
+        }
+    }
+}
+
+fn main() {}
diff --git a/vendor/pin-project-lite/tests/expand/pinned_drop/struct.expanded.rs b/vendor/pin-project-lite/tests/expand/pinned_drop/struct.expanded.rs
new file mode 100644 (file)
index 0000000..5b82b7a
--- /dev/null
@@ -0,0 +1,92 @@
+use pin_project_lite::pin_project;
+use std::pin::Pin;
+struct Struct<T, U> {
+    pinned: T,
+    unpinned: U,
+}
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(dead_code)]
+    #[allow(single_use_lifetimes)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct Projection<'__pin, T, U>
+    where
+        Struct<T, U>: '__pin,
+    {
+        pinned: ::pin_project_lite::__private::Pin<&'__pin mut (T)>,
+        unpinned: &'__pin mut (U),
+    }
+    #[allow(dead_code)]
+    #[allow(single_use_lifetimes)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct ProjectionRef<'__pin, T, U>
+    where
+        Struct<T, U>: '__pin,
+    {
+        pinned: ::pin_project_lite::__private::Pin<&'__pin (T)>,
+        unpinned: &'__pin (U),
+    }
+    impl<T, U> Struct<T, U> {
+        fn project<'__pin>(
+            self: ::pin_project_lite::__private::Pin<&'__pin mut Self>,
+        ) -> Projection<'__pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                Projection {
+                    pinned: ::pin_project_lite::__private::Pin::new_unchecked(pinned),
+                    unpinned: unpinned,
+                }
+            }
+        }
+        fn project_ref<'__pin>(
+            self: ::pin_project_lite::__private::Pin<&'__pin Self>,
+        ) -> ProjectionRef<'__pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                ProjectionRef {
+                    pinned: ::pin_project_lite::__private::Pin::new_unchecked(pinned),
+                    unpinned: unpinned,
+                }
+            }
+        }
+    }
+    #[allow(non_snake_case)]
+    struct __Origin<'__pin, T, U> {
+        __dummy_lifetime: ::pin_project_lite::__private::PhantomData<&'__pin ()>,
+        pinned: T,
+        unpinned: ::pin_project_lite::__private::AlwaysUnpin<U>,
+    }
+    impl<'__pin, T, U> ::pin_project_lite::__private::Unpin for Struct<T, U> where
+        __Origin<'__pin, T, U>: ::pin_project_lite::__private::Unpin
+    {
+    }
+    impl<T, U> ::pin_project_lite::__private::Drop for Struct<T, U> {
+        fn drop(&mut self) {
+            fn __drop_inner<T, U>(this: ::pin_project_lite::__private::Pin<&mut Struct<T, U>>) {
+                fn __drop_inner() {}
+                let _ = this;
+            }
+            let pinned_self: ::pin_project_lite::__private::Pin<&mut Self> =
+                unsafe { ::pin_project_lite::__private::Pin::new_unchecked(self) };
+            __drop_inner(pinned_self);
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.unpinned;
+    }
+};
+fn main() {}
diff --git a/vendor/pin-project-lite/tests/expand/pinned_drop/struct.rs b/vendor/pin-project-lite/tests/expand/pinned_drop/struct.rs
new file mode 100644 (file)
index 0000000..0cc7567
--- /dev/null
@@ -0,0 +1,17 @@
+use pin_project_lite::pin_project;
+use std::pin::Pin;
+
+pin_project! {
+    struct Struct<T, U> {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    }
+    impl<T, U> PinnedDrop for Struct<T, U> {
+        fn drop(this: Pin<&mut Self>) {
+            let _ = this;
+        }
+    }
+}
+
+fn main() {}
index adf8dde40e8635a32d702c687b1b2477213e2e27..3f0d5c11214a25ecda0b1dbc0e7d3d870745f54d 100644 (file)
@@ -6,6 +6,8 @@ use std::{
     process::{Command, ExitStatus, Stdio},
 };
 
+const PATH: &str = "tests/expand/**/*.rs";
+
 #[rustversion::attr(not(nightly), ignore)]
 #[test]
 fn expandtest() {
@@ -13,17 +15,17 @@ fn expandtest() {
     let cargo = &*env::var("CARGO").unwrap_or_else(|_| "cargo".into());
     if !has_command(&[cargo, "expand"]) || !has_command(&[cargo, "fmt"]) {
         if is_ci {
-            panic!("expandtest requires rustfmt and cargo-expand")
+            panic!("expandtest requires rustfmt and cargo-expand");
         }
         return;
     }
 
-    let path = "tests/expand/*/*.rs";
+    let args = &["--all-features"];
     if is_ci {
-        macrotest::expand_without_refresh(path);
+        macrotest::expand_without_refresh_args(PATH, args);
     } else {
         env::set_var("MACROTEST", "overwrite");
-        macrotest::expand(path);
+        macrotest::expand_args(PATH, args);
     }
 }
 
index 381bb18cc80ab32380f8c0b84eb0851f5a5c46a5..2324cd5fd75e8ac061b0f225878d652a6b2079f5 100644 (file)
@@ -1,48 +1,44 @@
-#![forbid(unsafe_code)]
-#![warn(nonstandard_style, rust_2018_idioms, rustdoc, unused)]
+// Check interoperability with rustc and clippy lints.
+
+#![warn(nonstandard_style, rust_2018_idioms, unused)]
 // Note: This does not guarantee compatibility with forbidding these lints in the future.
 // If rustc adds a new lint, we may not be able to keep this.
-#![forbid(future_incompatible, rust_2018_compatibility)]
+#![forbid(future_incompatible)]
 #![allow(unknown_lints)] // for old compilers
+#![forbid(unsafe_code)]
 #![warn(
     box_pointers,
     deprecated_in_future,
-    disjoint_capture_drop_reorder,
-    elided_lifetimes_in_paths,
-    explicit_outlives_requirements,
+    disjoint_capture_migration,
     macro_use_extern_crate,
     meta_variable_misuse,
     missing_abi,
     missing_copy_implementations,
-    missing_crate_level_docs,
     missing_debug_implementations,
     missing_docs,
     non_ascii_idents,
+    noop_method_call,
     single_use_lifetimes,
     trivial_casts,
     trivial_numeric_casts,
-    unaligned_references,
     unreachable_pub,
-    unused_extern_crates,
     unused_import_braces,
     unused_lifetimes,
     unused_qualifications,
     unused_results,
     variant_size_differences
 )]
-// absolute_paths_not_starting_with_crate, anonymous_parameters, keyword_idents, pointer_structural_match, semicolon_in_expressions_from_macros: forbidden as a part of future_incompatible
-// missing_doc_code_examples, private_doc_tests, invalid_html_tags: warned as a part of rustdoc
-// unsafe_block_in_unsafe_fn: unstable
-// unsafe_code: forbidden
-// unstable_features: deprecated: https://doc.rust-lang.org/beta/rustc/lints/listing/allowed-by-default.html#unstable-features
+// rust_2018_compatibility, rust_2021_compatibility, absolute_paths_not_starting_with_crate, etc.: forbidden as a part of future_incompatible
+// elided_lifetimes_in_paths, explicit_outlives_requirements, unused_extern_crates: warned as a part of rust_2018_idioms
+// unsafe_block_in_unsafe_fn: unsafe_block_in_unsafe_fn: requires Rust 1.52. and, we don't generate unsafe fn.
+// unstable_features: no way to generate #![feature(..)] by macros, expect for unstable inner attribute. and this lint is deprecated: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unstable-features
 // unused_crate_dependencies: unrelated
+// unsafe_code: forbidden
 #![warn(clippy::all, clippy::pedantic, clippy::nursery)]
 #![warn(clippy::restriction)]
 #![allow(clippy::blanket_clippy_restriction_lints)] // this is a test, so enable all restriction lints intentionally.
 #![allow(clippy::exhaustive_structs, clippy::exhaustive_enums)] // TODO
 
-// Check interoperability with rustc and clippy lints.
-
 pub mod basic {
     include!("include/basic.rs");
 }
index d792bab46cf0fe1bf62c11f6735ab143a036b25f..162fc20bc16f175e36c2b4b20e0751568748fd96 100644 (file)
@@ -52,7 +52,7 @@ fn projection() {
 
     {
         let StructProjReplace { f1: PhantomData, f2 } =
-            s.as_mut().project_replace(Default::default());
+            s.as_mut().project_replace(Struct::default());
         assert_eq!(f2, 2);
         let StructProj { f1, f2 } = s.project();
         assert_eq!(*f1, 0);
@@ -633,3 +633,36 @@ fn attrs() {
         }
     }
 }
+
+#[test]
+fn pinned_drop() {
+    pin_project! {
+        pub struct Struct1<'a> {
+            was_dropped: &'a mut bool,
+            #[pin]
+            field: u8,
+        }
+        impl PinnedDrop for Struct1<'_> {
+            fn drop(this: Pin<&mut Self>) {
+                **this.project().was_dropped = true;
+            }
+        }
+    }
+
+    let mut was_dropped = false;
+    drop(Struct1 { was_dropped: &mut was_dropped, field: 42 });
+    assert!(was_dropped);
+
+    pin_project! {
+        pub struct Struct2<'a> {
+            was_dropped: &'a mut bool,
+            #[pin]
+            field: u8,
+        }
+        impl PinnedDrop for Struct2<'_> {
+            fn drop(mut this: Pin<&mut Self>) {
+                **this.as_mut().project().was_dropped = true;
+            }
+        }
+    }
+}
index f97c92b6739ad9b4125c7fe80b375c7fb6976183..bbfc9106ebfa624453f09b194c5551c59bdff660 100644 (file)
@@ -1,4 +1,4 @@
-error[E0119]: conflicting implementations of trait `_::MustNotImplDrop` for type `Foo<_, _>`:
+error[E0119]: conflicting implementations of trait `_::MustNotImplDrop` for type `Foo<_, _>`
  --> $DIR/conflict-drop.rs:3:1
   |
 3 | / pin_project! { //~ ERROR E0119
@@ -13,4 +13,4 @@ error[E0119]: conflicting implementations of trait `_::MustNotImplDrop` for type
   | |_first implementation here
   |   conflicting implementation for `Foo<_, _>`
   |
-  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
index 546dafdbbe03f71560b3ebd183d615a5e1c16539..18bdd9288be54e5ce8a17959cefcf58d348b882e 100644 (file)
@@ -1,4 +1,4 @@
-error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Foo<_, _>`:
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Foo<_, _>`
   --> $DIR/conflict-unpin.rs:5:1
    |
 5  | / pin_project! { //~ ERROR E0119
@@ -13,9 +13,9 @@ error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type
 14 |   impl<T, U> Unpin for Foo<T, U> where T: Unpin {} // Conditional Unpin impl
    |   --------------------------------------------- first implementation here
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Bar<_, _>`:
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Bar<_, _>`
   --> $DIR/conflict-unpin.rs:18:1
    |
 18 | / pin_project! { //~ ERROR E0119
@@ -30,9 +30,9 @@ error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type
 27 |   impl<T, U> Unpin for Bar<T, U> {} // Non-conditional Unpin impl
    |   ------------------------------ first implementation here
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Baz<_, _>`:
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Baz<_, _>`
   --> $DIR/conflict-unpin.rs:29:1
    |
 29 | / pin_project! { //~ ERROR E0119
@@ -47,4 +47,4 @@ error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type
 38 |   impl<T: Unpin, U: Unpin> Unpin for Baz<T, U> {} // Conditional Unpin impl
    |   -------------------------------------------- first implementation here
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
index a565cce9783675d7c8b8553d0684f814f12c0a0e..b27698915d79df9583e9158808e9dadf8999e985 100644 (file)
@@ -8,7 +8,7 @@ error: no rules expected the token `[`
 7 | | }
   | |_^ no rules expected this token in macro call
   |
-  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  = note: this error originates in the macro `pin_project` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: no rules expected the token `[`
   --> $DIR/invalid-bounds.rs:9:1
@@ -20,7 +20,7 @@ error: no rules expected the token `[`
 13 | | }
    | |_^ no rules expected this token in macro call
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `pin_project` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected one of `+`, `,`, `=`, or `>`, found `:`
   --> $DIR/invalid-bounds.rs:15:1
@@ -36,7 +36,7 @@ error: expected one of `+`, `,`, `=`, or `>`, found `:`
    | |_unexpected token
    |   in this macro invocation
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected one of `+`, `,`, `=`, or `>`, found `:`
   --> $DIR/invalid-bounds.rs:21:1
@@ -52,7 +52,7 @@ error: expected one of `+`, `,`, `=`, or `>`, found `:`
    | |_unexpected token
    |   in this macro invocation
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected one of `+`, `,`, `=`, or `>`, found `:`
   --> $DIR/invalid-bounds.rs:27:1
@@ -68,7 +68,7 @@ error: expected one of `+`, `,`, `=`, or `>`, found `:`
    | |_unexpected token
    |   in this macro invocation
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: no rules expected the token `[`
   --> $DIR/invalid-bounds.rs:33:1
@@ -80,7 +80,7 @@ error: no rules expected the token `[`
 37 | | }
    | |_^ no rules expected this token in macro call
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `pin_project` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: no rules expected the token `[`
   --> $DIR/invalid-bounds.rs:39:1
@@ -94,7 +94,7 @@ error: no rules expected the token `[`
 46 | | }
    | |_^ no rules expected this token in macro call
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `pin_project` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: no rules expected the token `[`
   --> $DIR/invalid-bounds.rs:48:1
@@ -108,7 +108,7 @@ error: no rules expected the token `[`
 55 | | }
    | |_^ no rules expected this token in macro call
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `pin_project` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected `where`, or `{` after struct name, found `:`
   --> $DIR/invalid-bounds.rs:57:1
@@ -125,7 +125,7 @@ error: expected `where`, or `{` after struct name, found `:`
    | |_expected `where`, or `{` after struct name
    |   in this macro invocation
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected `where`, or `{` after struct name, found `:`
   --> $DIR/invalid-bounds.rs:66:1
@@ -142,7 +142,7 @@ error: expected `where`, or `{` after struct name, found `:`
    | |_expected `where`, or `{` after struct name
    |   in this macro invocation
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected `where`, or `{` after struct name, found `:`
   --> $DIR/invalid-bounds.rs:75:1
@@ -159,7 +159,7 @@ error: expected `where`, or `{` after struct name, found `:`
    | |_expected `where`, or `{` after struct name
    |   in this macro invocation
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: no rules expected the token `[`
   --> $DIR/invalid-bounds.rs:84:1
@@ -173,4 +173,4 @@ error: no rules expected the token `[`
 91 | | }
    | |_^ no rules expected this token in macro call
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `pin_project` (in Nightly builds, run with -Z macro-backtrace for more info)
index 06f2d79e1a2ce801f52841d3e3e9f0ecad8cca2c..38df5178d55a72c542c6f46c44c0cc38793322e8 100644 (file)
@@ -9,7 +9,7 @@ error: no rules expected the token `[`
 8 | | }
   | |_^ no rules expected this token in macro call
   |
-  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  = note: this error originates in the macro `pin_project` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: no rules expected the token `[`
   --> $DIR/invalid.rs:17:1
@@ -23,7 +23,7 @@ error: no rules expected the token `[`
 23 | | }
    | |_^ no rules expected this token in macro call
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `pin_project` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: cannot find attribute `pin` in this scope
   --> $DIR/invalid.rs:11:7
index 87a737e2fa1d47b6f050748a3e76c6abf124193e..117c18d74c4d8441d9029e73e93cf85bdd6f42f1 100644 (file)
@@ -1,7 +1,7 @@
 use pin_project_lite::pin_project;
 
-pin_project! { //~ ERROR E0496
-    pub struct Foo<'__pin, T> { //~ ERROR E0263
+pin_project! { //~ ERROR E0263,E0496
+    pub struct Foo<'__pin, T> {
         #[pin]
         field: &'__pin mut T,
     }
index 8a9bb4fc91b1cd00bbb307e9d9efb3fab0ba909a..f87875d87633ff6f029e1aaea23cbd42651ea0f0 100644 (file)
@@ -1,36 +1,32 @@
-error[E0496]: lifetime name `'__pin` shadows a lifetime name that is already in scope
- --> $DIR/overlapping_lifetime_names.rs:3:1
+error[E0263]: lifetime name `'__pin` declared twice in the same scope
+ --> $DIR/overlapping_lifetime_names.rs:4:20
   |
-3 | / pin_project! { //~ ERROR E0496
-4 | |     pub struct Foo<'__pin, T> { //~ ERROR E0263
-  | |                    ------ first declared here
+3 | / pin_project! { //~ ERROR E0263,E0496
+4 | |     pub struct Foo<'__pin, T> {
+  | |                    ^^^^^^ declared twice
 5 | |         #[pin]
 6 | |         field: &'__pin mut T,
 7 | |     }
 8 | | }
-  | |_^ lifetime `'__pin` already in scope
-  |
-  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  | |_- previous declaration here
 
-error[E0496]: lifetime name `'__pin` shadows a lifetime name that is already in scope
- --> $DIR/overlapping_lifetime_names.rs:3:1
+error[E0263]: lifetime name `'__pin` declared twice in the same scope
+ --> $DIR/overlapping_lifetime_names.rs:4:20
   |
-3 | / pin_project! { //~ ERROR E0496
-4 | |     pub struct Foo<'__pin, T> { //~ ERROR E0263
-  | |                    ------ first declared here
+3 | / pin_project! { //~ ERROR E0263,E0496
+4 | |     pub struct Foo<'__pin, T> {
+  | |                    ^^^^^^ declared twice
 5 | |         #[pin]
 6 | |         field: &'__pin mut T,
 7 | |     }
 8 | | }
-  | |_^ lifetime `'__pin` already in scope
-  |
-  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  | |_- previous declaration here
 
 error[E0263]: lifetime name `'__pin` declared twice in the same scope
  --> $DIR/overlapping_lifetime_names.rs:4:20
   |
-3 | / pin_project! { //~ ERROR E0496
-4 | |     pub struct Foo<'__pin, T> { //~ ERROR E0263
+3 | / pin_project! { //~ ERROR E0263,E0496
+4 | |     pub struct Foo<'__pin, T> {
   | |                    ^^^^^^ declared twice
 5 | |         #[pin]
 6 | |         field: &'__pin mut T,
@@ -38,35 +34,39 @@ error[E0263]: lifetime name `'__pin` declared twice in the same scope
 8 | | }
   | |_- previous declaration here
 
-error[E0263]: lifetime name `'__pin` declared twice in the same scope
- --> $DIR/overlapping_lifetime_names.rs:4:20
+error[E0496]: lifetime name `'__pin` shadows a lifetime name that is already in scope
+ --> $DIR/overlapping_lifetime_names.rs:3:1
   |
-3 | / pin_project! { //~ ERROR E0496
-4 | |     pub struct Foo<'__pin, T> { //~ ERROR E0263
-  | |                    ^^^^^^ declared twice
+3 | / pin_project! { //~ ERROR E0263,E0496
+4 | |     pub struct Foo<'__pin, T> {
+  | |                    ------ first declared here
 5 | |         #[pin]
 6 | |         field: &'__pin mut T,
 7 | |     }
 8 | | }
-  | |_- previous declaration here
+  | |_^ lifetime `'__pin` already in scope
+  |
+  = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0263]: lifetime name `'__pin` declared twice in the same scope
- --> $DIR/overlapping_lifetime_names.rs:4:20
+error[E0496]: lifetime name `'__pin` shadows a lifetime name that is already in scope
+ --> $DIR/overlapping_lifetime_names.rs:3:1
   |
-3 | / pin_project! { //~ ERROR E0496
-4 | |     pub struct Foo<'__pin, T> { //~ ERROR E0263
-  | |                    ^^^^^^ declared twice
+3 | / pin_project! { //~ ERROR E0263,E0496
+4 | |     pub struct Foo<'__pin, T> {
+  | |                    ------ first declared here
 5 | |         #[pin]
 6 | |         field: &'__pin mut T,
 7 | |     }
 8 | | }
-  | |_- previous declaration here
+  | |_^ lifetime `'__pin` already in scope
+  |
+  = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0263]: lifetime name `'__pin` declared twice in the same scope
  --> $DIR/overlapping_lifetime_names.rs:4:20
   |
-3 | / pin_project! { //~ ERROR E0496
-4 | |     pub struct Foo<'__pin, T> { //~ ERROR E0263
+3 | / pin_project! { //~ ERROR E0263,E0496
+4 | |     pub struct Foo<'__pin, T> {
   | |                    ^^^^^^ declared twice
 5 | |         #[pin]
 6 | |         field: &'__pin mut T,
index 13385243073f82b79ee24961b7a2c7b5e4e957d7..25131d17d1bd4968f737d3642ed6318959babe5c 100644 (file)
@@ -1,6 +1,7 @@
-use pin_project_lite::pin_project;
 use std::marker::PhantomPinned;
 
+use pin_project_lite::pin_project;
+
 pin_project! {
     struct Foo<T> {
         #[pin]
index ab76f81d9bdf5a05573f4881a292da3a3667d5d0..9486f9d1fffa742dcfd5108734e0b88c869ebc1c 100644 (file)
@@ -1,11 +1,22 @@
 error[E0277]: `PhantomPinned` cannot be unpinned
-  --> $DIR/overlapping_unpin_struct.rs:18:5
+  --> $DIR/overlapping_unpin_struct.rs:19:5
    |
-15 | fn is_unpin<T: Unpin>() {}
+16 | fn is_unpin<T: Unpin>() {}
    |                ----- required by this bound in `is_unpin`
 ...
-18 |     is_unpin::<Foo<PhantomPinned>>(); //~ ERROR E0277
+19 |     is_unpin::<Foo<PhantomPinned>>(); //~ ERROR E0277
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `_::__Origin<'_, PhantomPinned>`, the trait `Unpin` is not implemented for `PhantomPinned`
    |
-   = note: required because it appears within the type `_::__Origin<'_, PhantomPinned>`
+   = note: consider using `Box::pin`
+note: required because it appears within the type `_::__Origin<'_, PhantomPinned>`
+  --> $DIR/overlapping_unpin_struct.rs:5:1
+   |
+5  | / pin_project! {
+6  | |     struct Foo<T> {
+7  | |         #[pin]
+8  | |         inner: T,
+9  | |     }
+10 | | }
+   | |_^
    = note: required because of the requirements on the impl of `Unpin` for `Foo<PhantomPinned>`
+   = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
index 507a0385fb161ed1a9d0fcb0e69529ec81d4eec0..50afb118c88863a0799ab7d5712474f79b174e98 100644 (file)
@@ -1,3 +1,5 @@
+#![allow(unaligned_references)]
+
 use pin_project_lite::pin_project;
 
 pin_project! { //~ ERROR reference to packed field is unaligned
index 14ffc86d4244c8e34c837973a2b3b4698126756b..85f84c21fc2bf5e0a449fc661175cbc3d8847fe4 100644 (file)
 error: reference to packed field is unaligned
- --> $DIR/packed.rs:3:1
-  |
-3 | / pin_project! { //~ ERROR reference to packed field is unaligned
-4 | |     #[repr(packed, C)]
-5 | |     struct Packed {
-6 | |         #[pin]
-7 | |         field: u16,
-8 | |     }
-9 | | }
-  | |_^
-  |
-note: the lint level is defined here
- --> $DIR/packed.rs:3:1
-  |
-3 | / pin_project! { //~ ERROR reference to packed field is unaligned
-4 | |     #[repr(packed, C)]
-5 | |     struct Packed {
-6 | |         #[pin]
-7 | |         field: u16,
-8 | |     }
-9 | | }
-  | |_^
-  = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
-  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: reference to packed field is unaligned
-  --> $DIR/packed.rs:11:1
+  --> $DIR/packed.rs:5:1
    |
-11 | / pin_project! { //~ ERROR reference to packed field is unaligned
-12 | |     #[repr(packed(2))]
-13 | |     struct PackedN {
-14 | |         #[pin]
-15 | |         field: u32,
-16 | |     }
-17 | | }
+ | / pin_project! { //~ ERROR reference to packed field is unaligned
+6  | |     #[repr(packed, C)]
+7  | |     struct Packed {
+ | |         #[pin]
+9  | |         field: u16,
+10 | |     }
+11 | | }
    | |_^
    |
 note: the lint level is defined here
-  --> $DIR/packed.rs:11:1
+  --> $DIR/packed.rs:5:1
    |
-11 | / pin_project! { //~ ERROR reference to packed field is unaligned
-12 | |     #[repr(packed(2))]
-13 | |     struct PackedN {
-14 | |         #[pin]
-15 | |         field: u32,
-16 | |     }
-17 | | }
+ | / pin_project! { //~ ERROR reference to packed field is unaligned
+6  | |     #[repr(packed, C)]
+7  | |     struct Packed {
+ | |         #[pin]
+9  | |         field: u16,
+10 | |     }
+11 | | }
    | |_^
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
- --> $DIR/packed.rs:3:1
-  |
-3 | / pin_project! { //~ ERROR reference to packed field is unaligned
-4 | |     #[repr(packed, C)]
-5 | |     struct Packed {
-6 | |         #[pin]
-7 | |         field: u16,
-8 | |     }
-9 | | }
-  | |_^
-  |
-note: the lint level is defined here
- --> $DIR/packed.rs:3:1
-  |
-3 | / pin_project! { //~ ERROR reference to packed field is unaligned
-4 | |     #[repr(packed, C)]
-5 | |     struct Packed {
-6 | |         #[pin]
-7 | |         field: u16,
-8 | |     }
-9 | | }
-  | |_^
-  = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
-  = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
-  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
-  --> $DIR/packed.rs:11:1
+error: reference to packed field is unaligned
+  --> $DIR/packed.rs:13:1
    |
-11 | / pin_project! { //~ ERROR reference to packed field is unaligned
-12 | |     #[repr(packed(2))]
-13 | |     struct PackedN {
-14 | |         #[pin]
-15 | |         field: u32,
-16 | |     }
-17 | | }
+13 | / pin_project! { //~ ERROR reference to packed field is unaligned
+14 | |     #[repr(packed(2))]
+15 | |     struct PackedN {
+16 | |         #[pin]
+17 | |         field: u32,
+18 | |     }
+19 | | }
    | |_^
    |
 note: the lint level is defined here
-  --> $DIR/packed.rs:11:1
+  --> $DIR/packed.rs:13:1
    |
-11 | / pin_project! { //~ ERROR reference to packed field is unaligned
-12 | |     #[repr(packed(2))]
-13 | |     struct PackedN {
-14 | |         #[pin]
-15 | |         field: u32,
-16 | |     }
-17 | | }
+13 | / pin_project! { //~ ERROR reference to packed field is unaligned
+14 | |     #[repr(packed(2))]
+15 | |     struct PackedN {
+16 | |         #[pin]
+17 | |         field: u32,
+18 | |     }
+19 | | }
    | |_^
    = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
-   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
index 2cd17df1ef7e2673486b6267377606cec5c98f4c..892e57c9000d7196381388a322d28b04dfa946c6 100644 (file)
@@ -6,7 +6,7 @@ error: no rules expected the token `[`
 5 | | }
   | |_^ no rules expected this token in macro call
   |
-  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  = note: this error originates in the macro `pin_project` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: no rules expected the token `[`
  --> $DIR/unsupported.rs:7:1
@@ -16,7 +16,7 @@ error: no rules expected the token `[`
 9 | | }
   | |_^ no rules expected this token in macro call
   |
-  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  = note: this error originates in the macro `pin_project` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: no rules expected the token `[`
   --> $DIR/unsupported.rs:11:1
@@ -26,7 +26,7 @@ error: no rules expected the token `[`
 13 | | }
    | |_^ no rules expected this token in macro call
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `pin_project` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: no rules expected the token `[`
   --> $DIR/unsupported.rs:15:1
@@ -38,7 +38,7 @@ error: no rules expected the token `[`
 19 | | }
    | |_^ no rules expected this token in macro call
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `pin_project` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: no rules expected the token `[`
   --> $DIR/unsupported.rs:21:1
@@ -50,4 +50,4 @@ error: no rules expected the token `[`
 25 | | }
    | |_^ no rules expected this token in macro call
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `pin_project` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/vendor/pin-project-lite/tests/ui/pinned_drop/call-drop-inner.rs b/vendor/pin-project-lite/tests/ui/pinned_drop/call-drop-inner.rs
new file mode 100644 (file)
index 0000000..609b3be
--- /dev/null
@@ -0,0 +1,17 @@
+use pin_project_lite::pin_project;
+
+pin_project! {
+    pub struct S {
+        #[pin]
+        field: u8,
+    }
+    impl PinnedDrop for S {
+        fn drop(this: Pin<&mut Self>) {
+            __drop_inner(this);
+        }
+    }
+}
+
+fn main() {
+    let _x = S { field: 0 };
+}
diff --git a/vendor/pin-project-lite/tests/ui/pinned_drop/call-drop-inner.stderr b/vendor/pin-project-lite/tests/ui/pinned_drop/call-drop-inner.stderr
new file mode 100644 (file)
index 0000000..576e417
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+  --> $DIR/call-drop-inner.rs:10:13
+   |
+10 |             __drop_inner(this);
+   |             ^^^^^^^^^^^^ ---- supplied 1 argument
+   |             |
+   |             expected 0 arguments
+   |
+note: function defined here
+  --> $DIR/call-drop-inner.rs:3:1
+   |
+3  | / pin_project! {
+4  | |     pub struct S {
+5  | |         #[pin]
+6  | |         field: u8,
+...  |
+12 | |     }
+13 | | }
+   | |_^
+   = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/vendor/pin-project-lite/tests/ui/pinned_drop/conditional-drop-impl.rs b/vendor/pin-project-lite/tests/ui/pinned_drop/conditional-drop-impl.rs
new file mode 100644 (file)
index 0000000..68b01b2
--- /dev/null
@@ -0,0 +1,26 @@
+use pin_project_lite::pin_project;
+
+// In `Drop` impl, the implementor must specify the same requirement as type definition.
+
+struct DropImpl<T> {
+    f: T,
+}
+
+impl<T: Unpin> Drop for DropImpl<T> {
+    //~^ ERROR E0367
+    fn drop(&mut self) {}
+}
+
+pin_project! {
+    //~^ ERROR E0367
+    struct PinnedDropImpl<T> {
+        #[pin]
+        f: T,
+    }
+
+    impl<T: Unpin> PinnedDrop for PinnedDropImpl<T> {
+        fn drop(_this: Pin<&mut Self>) {}
+    }
+}
+
+fn main() {}
diff --git a/vendor/pin-project-lite/tests/ui/pinned_drop/conditional-drop-impl.stderr b/vendor/pin-project-lite/tests/ui/pinned_drop/conditional-drop-impl.stderr
new file mode 100644 (file)
index 0000000..a67bc8d
--- /dev/null
@@ -0,0 +1,38 @@
+error[E0367]: `Drop` impl requires `T: Unpin` but the struct it is implemented for does not
+ --> $DIR/conditional-drop-impl.rs:9:9
+  |
+9 | impl<T: Unpin> Drop for DropImpl<T> {
+  |         ^^^^^
+  |
+note: the implementor must specify the same requirement
+ --> $DIR/conditional-drop-impl.rs:5:1
+  |
+5 | / struct DropImpl<T> {
+6 | |     f: T,
+7 | | }
+  | |_^
+
+error[E0367]: `Drop` impl requires `T: Unpin` but the struct it is implemented for does not
+  --> $DIR/conditional-drop-impl.rs:14:1
+   |
+14 | / pin_project! {
+15 | |     //~^ ERROR E0367
+16 | |     struct PinnedDropImpl<T> {
+17 | |         #[pin]
+...  |
+23 | |     }
+24 | | }
+   | |_^
+   |
+note: the implementor must specify the same requirement
+  --> $DIR/conditional-drop-impl.rs:14:1
+   |
+14 | / pin_project! {
+15 | |     //~^ ERROR E0367
+16 | |     struct PinnedDropImpl<T> {
+17 | |         #[pin]
+...  |
+23 | |     }
+24 | | }
+   | |_^
+   = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
index 6f8b88f0bc809eab91774511e7804c314395550c..3288dab96c7c4fe12ced1851502140c984ae50bb 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.toml":"4309bff79b64e8dc592402e3748ddcd98cadfae2b55f95f921c0902728e3c788","LICENSE":"efcfee7981ff72431fffb06925cad00a23dce079ed4354f61030ad5abdb78829","README.md":"9161f18ba7f69b4ca51e844aee8ffb8237513a468c5c3b1f3a5f989044f895ac","src/arch/aarch64.rs":"8c033147f6b21433e0cc1044040219d7f32fde918f17c81582381608f2f090ec","src/arch/arm.rs":"abc547bd2be32ff15f35032452e645668ec5050d2540e2dca073fc5670ca1a75","src/arch/nonredox.rs":"9eac0fa2cf9eae07f0cafa2dd63c4a820791897a3de9ad1a933ab4f53458dbd8","src/arch/riscv64.rs":"20bf9a8db779059773b113643d0cb3737fbb5d57f45ee39b8ae9d3396b6ef636","src/arch/x86.rs":"3a517a8f0a70ae1b513d7a44e7399ce47a2ca7aca72a8200662b9800b41455d6","src/arch/x86_64.rs":"ae2cec2079a36d3d3676c2431a55f19365d58545ed72748588679982a6619ab2","src/call.rs":"0d3e32e33ecdf75963e5d244f9e86e94047d155c5de5fa3c0085faf18ed97b33","src/data.rs":"bd4545d4c2fcc59ff26ae52ad7f773a697d5ccf639a2ffc253cece6b31e94d51","src/error.rs":"ef20f3817f997a1aeb7114628407f19cb8bc13c555d4e093918f38a5d098f798","src/flag.rs":"fbb6992383e68100339d854f15a1e7c6586474fac34d3b816778926f0809a015","src/io/dma.rs":"fbc46e924d5913f5a3fb723751d7a9dd1b079ccf058500fde4957aaf9fa7dd1c","src/io/io.rs":"1bcb36d1867e9bab6a8186cd6928efe70ae2655e9f9d0dd3def20bc0fb6a82f6","src/io/mmio.rs":"c71a956f57554b126080b14378f235f9e98c994648ba524231ceae841326251f","src/io/mod.rs":"4df12af3e82e6b5fe22112c9f51552112ee4811b7d1131d2a43d608d8d1cac09","src/io/pio.rs":"39f4176a2995c7acfb32204b065af0ec14d7ff0d45dc51eff2679f3195c36ee2","src/lib.rs":"b0ece8211be724a43d222255c4f118ec826d3952e409ced425f3c9c48516fc1e","src/number.rs":"fe7b47b06566aa1f8a75f50b685801259df03a1a5c85b91817b4552583cd7862","src/scheme/generate.sh":"dde4e30f4e0223fb1a24ed486a6c36e624c854dbf890862cb6866f4fa3c7a6eb","src/scheme/mod.rs":"cb622405deb0aef4ab04499ea1adfd338c9c5dd9c31a1fe9989786dbf69b49d8","src/scheme/scheme.rs":"30263996f0b4930edd76dace5f5750e48229066bc888bc13365846688d0a870b","src/scheme/scheme_block.rs":"b7a761e4349eb87d106c8af14894e8c4272769b9eb235cd500b075ac1f823683","src/scheme/scheme_block_mut.rs":"4a4fc03bce14757b64006b9bc3fa2779e95382b2d99579870146ee0c3be3f46c","src/scheme/scheme_mut.rs":"e6f0671b77f1bf5263e497c69dec553352249b75d52af62ac19477ba5127f803","src/scheme/seek.rs":"94e044de47b0f00eb0c2aea3fb21001ac2b9aa1e4b20d73fd54163fe92fa63f7","src/tests.rs":"416a428ba6a9c5f0d8f4c3dbe91d9aa940a04472ec9a2d17bc5a66c455b4416f"},"package":"742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc"}
\ No newline at end of file
+{"files":{"Cargo.toml":"f1d07e441a3caae69667a69b8cefd40e3838619ac8fe744329a648ec33cc583c","LICENSE":"efcfee7981ff72431fffb06925cad00a23dce079ed4354f61030ad5abdb78829","README.md":"9161f18ba7f69b4ca51e844aee8ffb8237513a468c5c3b1f3a5f989044f895ac","src/arch/aarch64.rs":"8c033147f6b21433e0cc1044040219d7f32fde918f17c81582381608f2f090ec","src/arch/arm.rs":"abc547bd2be32ff15f35032452e645668ec5050d2540e2dca073fc5670ca1a75","src/arch/nonredox.rs":"9eac0fa2cf9eae07f0cafa2dd63c4a820791897a3de9ad1a933ab4f53458dbd8","src/arch/riscv64.rs":"20bf9a8db779059773b113643d0cb3737fbb5d57f45ee39b8ae9d3396b6ef636","src/arch/x86.rs":"3a517a8f0a70ae1b513d7a44e7399ce47a2ca7aca72a8200662b9800b41455d6","src/arch/x86_64.rs":"ae2cec2079a36d3d3676c2431a55f19365d58545ed72748588679982a6619ab2","src/call.rs":"0d3e32e33ecdf75963e5d244f9e86e94047d155c5de5fa3c0085faf18ed97b33","src/data.rs":"bd4545d4c2fcc59ff26ae52ad7f773a697d5ccf639a2ffc253cece6b31e94d51","src/error.rs":"ef20f3817f997a1aeb7114628407f19cb8bc13c555d4e093918f38a5d098f798","src/flag.rs":"fbb6992383e68100339d854f15a1e7c6586474fac34d3b816778926f0809a015","src/io/dma.rs":"fbc46e924d5913f5a3fb723751d7a9dd1b079ccf058500fde4957aaf9fa7dd1c","src/io/io.rs":"e1d454ff47efac70fdaa709251a5a9c1c5637f931994ba3bf6a38c6db9145822","src/io/mmio.rs":"c71a956f57554b126080b14378f235f9e98c994648ba524231ceae841326251f","src/io/mod.rs":"4df12af3e82e6b5fe22112c9f51552112ee4811b7d1131d2a43d608d8d1cac09","src/io/pio.rs":"39f4176a2995c7acfb32204b065af0ec14d7ff0d45dc51eff2679f3195c36ee2","src/lib.rs":"d5b3fea867db8ad7cd7e142bdc06aa691225c768617af2391b53453560f4ab9b","src/number.rs":"fe7b47b06566aa1f8a75f50b685801259df03a1a5c85b91817b4552583cd7862","src/scheme/generate.sh":"dde4e30f4e0223fb1a24ed486a6c36e624c854dbf890862cb6866f4fa3c7a6eb","src/scheme/mod.rs":"cb622405deb0aef4ab04499ea1adfd338c9c5dd9c31a1fe9989786dbf69b49d8","src/scheme/scheme.rs":"30263996f0b4930edd76dace5f5750e48229066bc888bc13365846688d0a870b","src/scheme/scheme_block.rs":"b7a761e4349eb87d106c8af14894e8c4272769b9eb235cd500b075ac1f823683","src/scheme/scheme_block_mut.rs":"4a4fc03bce14757b64006b9bc3fa2779e95382b2d99579870146ee0c3be3f46c","src/scheme/scheme_mut.rs":"e6f0671b77f1bf5263e497c69dec553352249b75d52af62ac19477ba5127f803","src/scheme/seek.rs":"94e044de47b0f00eb0c2aea3fb21001ac2b9aa1e4b20d73fd54163fe92fa63f7","src/tests.rs":"416a428ba6a9c5f0d8f4c3dbe91d9aa940a04472ec9a2d17bc5a66c455b4416f"},"package":"5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee"}
\ No newline at end of file
index 381700e1846778290bd789383513fdf7d64cacea..5a82b9186ded21d937afa50bdae312c89dd3a4f2 100644 (file)
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "redox_syscall"
-version = "0.2.8"
+version = "0.2.9"
 authors = ["Jeremy Soller <jackpot51@gmail.com>"]
 description = "A Rust library to access raw Redox system calls"
 documentation = "https://docs.rs/redox_syscall"
index fb866b581b1b1ffcd8b5e1761147cb877e1c5450..2c4acd3883f07bfc23e7f419e5d0c9afbe535be2 100644 (file)
@@ -22,17 +22,19 @@ pub trait Io {
     }
 }
 
-pub struct ReadOnly<I: Io> {
+pub struct ReadOnly<I> {
     inner: I
 }
 
-impl<I: Io> ReadOnly<I> {
+impl<I> ReadOnly<I> {
     pub const fn new(inner: I) -> ReadOnly<I> {
         ReadOnly {
             inner: inner
         }
     }
+}
 
+impl<I: Io> ReadOnly<I> {
     #[inline(always)]
     pub fn read(&self) -> I::Value {
         self.inner.read()
@@ -44,17 +46,19 @@ impl<I: Io> ReadOnly<I> {
     }
 }
 
-pub struct WriteOnly<I: Io> {
+pub struct WriteOnly<I> {
     inner: I
 }
 
-impl<I: Io> WriteOnly<I> {
+impl<I> WriteOnly<I> {
     pub const fn new(inner: I) -> WriteOnly<I> {
         WriteOnly {
             inner: inner
         }
     }
+}
 
+impl<I: Io> WriteOnly<I> {
     #[inline(always)]
     pub fn write(&mut self, value: I::Value) {
         self.inner.write(value)
index 09ffda757807a9bcb8175a666ede91495fe8e1f4..60c0c6034070a8ce25e4d8376266b571fde63c60 100644 (file)
@@ -1,6 +1,5 @@
 #![feature(asm)]
 #![feature(llvm_asm)]
-#![feature(const_fn)] // see https://github.com/rust-lang/rfcs/pull/2632
 #![cfg_attr(not(test), no_std)]
 
 #[cfg(test)]
diff --git a/vendor/regex-1.4.3/.cargo-checksum.json b/vendor/regex-1.4.3/.cargo-checksum.json
deleted file mode 100644 (file)
index 502707a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"CHANGELOG.md":"df73666c0a3be12cc7dd17d42b949abddd1cc8108284926250d2871e307cca2d","Cargo.lock":"a27eb425904638394a6af5535f4ca7d37cd85669c4542ab523f6f45a4ff7b333","Cargo.toml":"50ad9be917228caef0c629a846d1ed4eb22cc2952ca4df841367563c680141e8","HACKING.md":"17818f7a17723608f6bdbe6388ad0a913d4f96f76a16649aaf4e274b1fa0ea97","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","PERFORMANCE.md":"c776b18758b6dc8f2f9d37e9a95261f75c5f744925e8ddf216b83953bf7467b7","README.md":"ea639f8259ae4ff721ea3792d3d0529975e7d5ca80d67d0a27bd82ef464f5d0a","UNICODE.md":"27be97e94d0819ae18ae71029559c3de21c8ffd343d4a791959d0fc22b06dfe6","examples/regexdna-input.txt":"156a49710bb3e1ed4bc2bbb0af0f383b747b3d0281453cfff39c296124c598f8","examples/regexdna-output.txt":"35e85b19b70a893d752fd43e54e1e9da08bac43559191cea85b33387c24c4cc1","examples/shootout-regex-dna-bytes.rs":"bfbb5b0751768d2914f3839b2f434e18c3df5a1db333b6c09c15d4c9f36e2362","examples/shootout-regex-dna-cheat.rs":"31153b19d6153e10a505bcefeaffc6ae5ec15c5b9e602ec1bdf1c008c71ac0fb","examples/shootout-regex-dna-replace.rs":"056e9ee51327a1cf9bd1da007e8c0af9c80a3e7fc2b3a3f63d0cf1b6b244ac74","examples/shootout-regex-dna-single-cheat.rs":"00d97b70df23236692d30d207d956e61896f6dba18fea0f6344bec6902a3490a","examples/shootout-regex-dna-single.rs":"81690e774c42899e6ab160580b30053531ec49678f088e1bc54cedf64e437b6c","examples/shootout-regex-dna.rs":"25c1c468238f0d45df1ff64748b1305ba2408b4102b8215a4e1a983e90221aef","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/backtrack.rs":"bb24a32bc0d2f2f1c94439d8d0879ad8d15c910d4b9ab86c2833d93945cb088c","src/cache.rs":"df7b83b4f7278705ad1ecdf1284b962cc3b145797f1676c9a59e32c5944c848c","src/compile.rs":"881e813fa99837d457e96bee18ec2f30965be2a12106700584829147f3b0036c","src/dfa.rs":"50decee8c2460fa66276ecbf968223b242dd17f02ab731539911c5d261524d11","src/error.rs":"4d03ca3205e373125a0c9a4270fc1c5aa7b5a661b11db3508b563945a0827301","src/exec.rs":"2489f96df3e21aa8a389e1012b03844f72dc42a19b1a5203f86655a71a641f5a","src/expand.rs":"6a1e012e84658f54ecefd6142173f1ca14eeeac52f4181a85ccc49eb94e5cd81","src/find_byte.rs":"b387247b77e3269f057c3399aefe5a815032c3af918c876f80eb4b282e4eb95e","src/freqs.rs":"255555f3d95b08a5bb3bc2f38d5a06cc100a39c0f0127fe4f50c33afa1cadc65","src/input.rs":"0bb20717cb630803f78b921260c96984a38a57685f07d9aee16b12deaa1d233b","src/lib.rs":"25235b9f137232fc388000576bde3b289b5b34cf67a5ea76f5d3a80360a6fa2a","src/literal/imp.rs":"db492e69b088cab9d25b65163f38a61684c5c86546266a81f556aea646a08342","src/literal/mod.rs":"46739643baa0cd5d1b8fc4521df3d727815c61e583af2ffca8b7b63bad3fa50e","src/pattern.rs":"e6124b403c18344675aa341faf9ae2f592193ef89f1c4a5e1cee135b8b34dd21","src/pikevm.rs":"3dd5794eecfe4ec80bee96d163025a417432c489732e84e125e51a4bc75d0235","src/prog.rs":"f47ac3accf7bd3456bd20902c6315f4063bbb6d9570c9b2f8309a0a1566d6323","src/re_builder.rs":"94ffcf23b009ff67f526dceede829fd02e7f5bf78bfc8ee1195ea571540b7a28","src/re_bytes.rs":"cfef05198d1c004ed5fe913413ac7d6b36e5c4eb6e0cae3259700652ea4f2da6","src/re_set.rs":"bd9b09bef7a571005d9a786466849f15717b6e660f1e8aaa9fc59e14a08a24d6","src/re_trait.rs":"49b027ac3f1b981f41bba1ea243e74aa94692837f7c2c10229c7cbd3277e03b4","src/re_unicode.rs":"0d561cd507b3f721a2f7623586346d0aa4f92f575ee570b3289c9c75a8f9dfd0","src/sparse.rs":"43a0ad1c058228121523a2392bb20126b36760228845db157c8819f835e9bfde","src/testdata/LICENSE":"58cf078acc03da3e280a938c2bd9943f554fc9b6ced89ad93ba35ca436872899","src/testdata/README":"45f869e37f798905c773bfbe0ef19a5fb7e585cbf0b7c21b5b5a784e8cec3c14","src/testdata/basic.dat":"b5b33aa89d48a61cd67cb1fbfd8f70e62c83e30b86256f9f915a5190dd38ff06","src/testdata/nullsubexpr.dat":"496ac0278eec3b6d9170faace14554569032dd3d909618364d9326156de39ecf","src/testdata/repetition.dat":"1f7959063015b284b18a4a2c1c8b416d438a2d6c4b1a362da43406b865f50e69","src/utf8.rs":"708615a4859110cc9766b342a9c1da6c5c4a8a04ad239046b2725385db977efe","test":"bd7ca64a788d1f622ae10c5ac77160b10fc5f0d6adb7f3ba1828637f0ca68c81","tests/api.rs":"7b2a0ef75e99b9776094967bd66e9cdeaa8e11359f5f0a12bd08ef0e8d0c11fc","tests/api_str.rs":"2ae38c04e7e8fac008b609a820d0b1561ba75f39b0edc0987d6d3d06132da77f","tests/bytes.rs":"edc50f526c5fee43df89d639ef18b237e4eb91e9d533bfc43f3cbab7417d38ba","tests/consistent.rs":"8dadc60727306de8a539325d1d2af84172e5da2cbf50a71bb0c53eafe8039912","tests/crates_regex.rs":"91a59d470e0700b4bcb3ff735d06799f3107b8ef4875a2e9904607b164be0326","tests/crazy.rs":"d18ebe88bfe0f61df2761710a5f2362187f071bc952b4c0c898e5a8bfb58cce6","tests/flags.rs":"05caace2c81a99d2168037f3a38035d4dffe9f85ef3ebd7ef18b1bc6612f1ea8","tests/fowler.rs":"d78cf914de40b1e125cc92b65ccb444d462586bd07b5e05de4e4a1b5de16aa76","tests/macros.rs":"6db70c16fc90df13e6b30d2b606f8b6dd4dc976697967f6ee001b15aab6d0b19","tests/macros_bytes.rs":"73e2979f60acb009066c3a9a6c5809a0069a60c67fff7db675ea4e59299a7292","tests/macros_str.rs":"4c79ff4f2f5c379503794dd7e4116b3e7d4ac7679e47b81959fa054110a76c1a","tests/misc.rs":"395f52793fa022e4cdda78675b6a6fba1a3106b4b99c834c39f7801574054bd1","tests/multiline.rs":"1b1a3326ed976437c1357f01d81833ece7ea244f38826246eab55cacd5d0862a","tests/noparse.rs":"12b6be0eff3d80779d33c6459396c74c0f6ebf4ddc9f1d33c3e747ea9e3bf268","tests/regression.rs":"4d4aecf57ce5accf73fe8818267e8d45c9a15896d40093a5b5e1a09007a121a1","tests/regression_fuzz.rs":"f57b63e5fcc602d4ca6997411af4a706a6cf307f24ab0b5340a08fd4721bf373","tests/replace.rs":"fb3dd97c2877b71973065a74916cdef40d65a19a92c1ecfc117edfcd9eab3ced","tests/searcher.rs":"ce35e47b0a276a7e8c9060c6a0b225ffba163aebc61fbc15555a6897fa0e552c","tests/set.rs":"f1e2af6baeeaed3cc99ed347ff516fe7b2eb0027ef64b891502e1486598eaf8a","tests/shortest_match.rs":"a2c94390c0d61bc24796b4c1288c924e90c8c9c6156fdebb858175177a194a42","tests/suffix_reverse.rs":"b95f89397404871227d9efe6df23b9ded147f183db81597e608f693955c668b5","tests/test_backtrack.rs":"1e286679d643887f7b78ef5a74f5392ff27fa462b99891ce31938db1eacb3842","tests/test_backtrack_bytes.rs":"f66f2ed407795e92ae66eaa3b4b946acfe00d9ea422944c86353dd28812df5bb","tests/test_backtrack_utf8bytes.rs":"9d8c236fbdfa5092230f19ca4d2a7d647f68811d9ffa0813899d924e11d8fc0b","tests/test_crates_regex.rs":"b385d7ca10ed308b8d57074adb9525e18d3faadb5aa883e831dfa4f6669ba58d","tests/test_default.rs":"bb8a7a61fdf05dc52f65cad9ec80c95807f5911c6a1e9fa67fbe6538653a7f01","tests/test_default_bytes.rs":"fb3310fc315f7282358dcd98d156c31d66ca2432199afe012cf8921f459167a2","tests/test_nfa.rs":"97266c5edb15e5cde1496049a3ad0be4de33352dc32492f086d5351411ebe1ab","tests/test_nfa_bytes.rs":"9aa510e9583f847467c26ce902bd7e1c66cdd610cd50da4a1c1379afa35d4a53","tests/test_nfa_utf8bytes.rs":"2c22e16fa75edb5dbd278f2b8619404404a95b0792b31c440c9751c4aa2f7086","tests/unicode.rs":"4bf85f5c3d547fa8b5623194a09b6413067499dfbe7c1d29d8b50bf1cddacf6b","tests/word_boundary.rs":"7081317ddcec1e82dd4a2090a571c6abf2ff4bbfa8cd10395e1eb3f386157fae","tests/word_boundary_ascii.rs":"cd0be5b5b485de0ba7994b42e2864585556c3d2d8bf5eab05b58931d9aaf4b87","tests/word_boundary_unicode.rs":"75dbcc35d3abc0f9795c2ea99e216dc227b0a5b58e9ca5eef767815ff0513921"},"package":"d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"}
\ No newline at end of file
diff --git a/vendor/regex-1.4.3/CHANGELOG.md b/vendor/regex-1.4.3/CHANGELOG.md
deleted file mode 100644 (file)
index cf020d2..0000000
+++ /dev/null
@@ -1,928 +0,0 @@
-1.4.3 (2021-01-08)
-==================
-This is a small patch release that adds some missing standard trait
-implementations for some types in the public API.
-
-Bug fixes:
-
-* [BUG #734](https://github.com/rust-lang/regex/pull/734):
-  Add `FusedIterator` and `ExactSizeIterator` impls to iterator types.
-* [BUG #735](https://github.com/rust-lang/regex/pull/735):
-  Add missing `Debug` impls to public API types.
-
-
-1.4.2 (2020-11-01)
-==================
-This is a small bug fix release that bans `\P{any}`. We previously banned empty
-classes like `[^\w\W]`, but missed the `\P{any}` case. In the future, we hope
-to permit empty classes.
-
-* [BUG #722](https://github.com/rust-lang/regex/issues/722):
-  Ban `\P{any}` to avoid a panic in the regex compiler. Found by OSS-Fuzz.
-
-
-1.4.1 (2020-10-13)
-==================
-This is a small bug fix release that makes `\p{cf}` work. Previously, it would
-report "property not found" even though `cf` is a valid abbreviation for the
-`Format` general category.
-
-* [BUG #719](https://github.com/rust-lang/regex/issues/719):
-  Fixes bug that prevented `\p{cf}` from working.
-
-
-1.4.0 (2020-10-11)
-==================
-This releases has a few minor documentation fixes as well as some very minor
-API additions. The MSRV remains at Rust 1.28 for now, but this is intended to
-increase to at least Rust 1.41.1 soon.
-
-This release also adds support for OSS-Fuzz. Kudos to
-[@DavidKorczynski](https://github.com/DavidKorczynski)
-for doing the heavy lifting for that!
-
-New features:
-
-* [FEATURE #649](https://github.com/rust-lang/regex/issues/649):
-  Support `[`, `]` and `.` in capture group names.
-* [FEATURE #687](https://github.com/rust-lang/regex/issues/687):
-  Add `is_empty` predicate to `RegexSet`.
-* [FEATURE #689](https://github.com/rust-lang/regex/issues/689):
-  Implement `Clone` for `SubCaptureMatches`.
-* [FEATURE #715](https://github.com/rust-lang/regex/issues/715):
-  Add `empty` constructor to `RegexSet` for convenience.
-
-Bug fixes:
-
-* [BUG #694](https://github.com/rust-lang/regex/issues/694):
-  Fix doc example for `Replacer::replace_append`.
-* [BUG #698](https://github.com/rust-lang/regex/issues/698):
-  Clarify docs for `s` flag when using a `bytes::Regex`.
-* [BUG #711](https://github.com/rust-lang/regex/issues/711):
-  Clarify `is_match` docs to indicate that it can match anywhere in string.
-
-
-1.3.9 (2020-05-28)
-==================
-This release fixes a MSRV (Minimum Support Rust Version) regression in the
-1.3.8 release. Namely, while 1.3.8 compiles on Rust 1.28, it actually does not
-compile on other Rust versions, such as Rust 1.39.
-
-Bug fixes:
-
-* [BUG #685](https://github.com/rust-lang/regex/issues/685):
-  Remove use of `doc_comment` crate, which cannot be used before Rust 1.43.
-
-
-1.3.8 (2020-05-28)
-==================
-This release contains a couple of important bug fixes driven
-by better support for empty-subexpressions in regexes. For
-example, regexes like `b|` are now allowed. Major thanks to
-[@sliquister](https://github.com/sliquister) for implementing support for this
-in [#677](https://github.com/rust-lang/regex/pull/677).
-
-Bug fixes:
-
-* [BUG #523](https://github.com/rust-lang/regex/pull/523):
-  Add note to documentation that spaces can be escaped in `x` mode.
-* [BUG #524](https://github.com/rust-lang/regex/issues/524):
-  Add support for empty sub-expressions, including empty alternations.
-* [BUG #659](https://github.com/rust-lang/regex/issues/659):
-  Fix match bug caused by an empty sub-expression miscompilation.
-
-
-1.3.7 (2020-04-17)
-==================
-This release contains a small bug fix that fixes how `regex` forwards crate
-features to `regex-syntax`. In particular, this will reduce recompilations in
-some cases.
-
-Bug fixes:
-
-* [BUG #665](https://github.com/rust-lang/regex/pull/665):
-  Fix feature forwarding to `regex-syntax`.
-
-
-1.3.6 (2020-03-24)
-==================
-This release contains a sizable (~30%) performance improvement when compiling
-some kinds of large regular expressions.
-
-Performance improvements:
-
-* [PERF #657](https://github.com/rust-lang/regex/pull/657):
-  Improvement performance of compiling large regular expressions.
-
-
-1.3.5 (2020-03-12)
-==================
-This release updates this crate to Unicode 13.
-
-New features:
-
-* [FEATURE #653](https://github.com/rust-lang/regex/pull/653):
-  Update `regex-syntax` to Unicode 13.
-
-
-1.3.4 (2020-01-30)
-==================
-This is a small bug fix release that fixes a bug related to the scoping of
-flags in a regex. Namely, before this fix, a regex like `((?i)a)b)` would
-match `aB` despite the fact that `b` should not be matched case insensitively.
-
-Bug fixes:
-
-* [BUG #640](https://github.com/rust-lang/regex/issues/640):
-  Fix bug related to the scoping of flags in a regex.
-
-
-1.3.3 (2020-01-09)
-==================
-This is a small maintenance release that upgrades the dependency on
-`thread_local` from `0.3` to `1.0`. The minimum supported Rust version remains
-at Rust 1.28.
-
-
-1.3.2 (2020-01-09)
-==================
-This is a small maintenance release with some house cleaning and bug fixes.
-
-New features:
-
-* [FEATURE #631](https://github.com/rust-lang/regex/issues/631):
-  Add a `Match::range` method an a `From<Match> for Range` impl.
-
-Bug fixes:
-
-* [BUG #521](https://github.com/rust-lang/regex/issues/521):
-  Corrects `/-/.splitn("a", 2)` to return `["a"]` instead of `["a", ""]`.
-* [BUG #594](https://github.com/rust-lang/regex/pull/594):
-  Improve error reporting when writing `\p\`.
-* [BUG #627](https://github.com/rust-lang/regex/issues/627):
-  Corrects `/-/.split("a-")` to return `["a", ""]` instead of `["a"]`.
-* [BUG #633](https://github.com/rust-lang/regex/pull/633):
-  Squash deprecation warnings for the `std::error::Error::description` method.
-
-
-1.3.1 (2019-09-04)
-==================
-This is a maintenance release with no changes in order to try to work-around
-a [docs.rs/Cargo issue](https://github.com/rust-lang/docs.rs/issues/400).
-
-
-1.3.0 (2019-09-03)
-==================
-This release adds a plethora of new crate features that permit users of regex
-to shrink its size considerably, in exchange for giving up either functionality
-(such as Unicode support) or runtime performance. When all such features are
-disabled, the dependency tree for `regex` shrinks to exactly 1 crate
-(`regex-syntax`). More information about the new crate features can be
-[found in the docs](https://docs.rs/regex/*/#crate-features).
-
-Note that while this is a new minor version release, the minimum supported
-Rust version for this crate remains at `1.28.0`.
-
-New features:
-
-* [FEATURE #474](https://github.com/rust-lang/regex/issues/474):
-  The `use_std` feature has been deprecated in favor of the `std` feature.
-  The `use_std` feature will be removed in regex 2. Until then, `use_std` will
-  remain as an alias for the `std` feature.
-* [FEATURE #583](https://github.com/rust-lang/regex/issues/583):
-  Add a substantial number of crate features shrinking `regex`.
-
-
-1.2.1 (2019-08-03)
-==================
-This release does a bit of house cleaning. Namely:
-
-* This repository is now using rustfmt.
-* License headers have been removed from all files, in following suit with the
-  Rust project.
-* Teddy has been removed from the `regex` crate, and is now part of the
-  `aho-corasick` crate.
-  [See `aho-corasick`'s new `packed` sub-module for details](https://docs.rs/aho-corasick/0.7.6/aho_corasick/packed/index.html).
-* The `utf8-ranges` crate has been deprecated, with its functionality moving
-  into the
-  [`utf8` sub-module of `regex-syntax`](https://docs.rs/regex-syntax/0.6.11/regex_syntax/utf8/index.html).
-* The `ucd-util` dependency has been dropped, in favor of implementing what
-  little we need inside of `regex-syntax` itself.
-
-In general, this is part of an ongoing (long term) effort to make optimizations
-in the regex engine easier to reason about. The current code is too convoluted
-and thus it is very easy to introduce new bugs. This simplification effort is
-the primary motivation behind re-working the `aho-corasick` crate to not only
-bundle algorithms like Teddy, but to also provide regex-like match semantics
-automatically.
-
-Moving forward, the plan is to join up with the `bstr` and `regex-automata`
-crates, with the former providing more sophisticated substring search
-algorithms (thereby deleting existing code in `regex`) and the latter providing
-ahead-of-time compiled DFAs for cases where they are inexpensive to compute.
-
-
-1.2.0 (2019-07-20)
-==================
-This release updates regex's minimum supported Rust version to 1.28, which was
-release almost 1 year ago. This release also updates regex's Unicode data
-tables to 12.1.0.
-
-
-1.1.9 (2019-07-06)
-==================
-This release contains a bug fix that caused regex's tests to fail, due to a
-dependency on an unreleased behavior in regex-syntax.
-
-* [BUG #593](https://github.com/rust-lang/regex/issues/593):
-  Move an integration-style test on error messages into regex-syntax.
-
-
-1.1.8 (2019-07-04)
-==================
-This release contains a few small internal refactorings. One of which fixes
-an instance of undefined behavior in a part of the SIMD code.
-
-Bug fixes:
-
-* [BUG #545](https://github.com/rust-lang/regex/issues/545):
-  Improves error messages when a repetition operator is used without a number.
-* [BUG #588](https://github.com/rust-lang/regex/issues/588):
-  Removes use of a repr(Rust) union used for type punning in the Teddy matcher.
-* [BUG #591](https://github.com/rust-lang/regex/issues/591):
-  Update docs for running benchmarks and improve failure modes.
-
-
-1.1.7 (2019-06-09)
-==================
-This release fixes up a few warnings as a result of recent deprecations.
-
-
-1.1.6 (2019-04-16)
-==================
-This release fixes a regression introduced by a bug fix (for
-[BUG #557](https://github.com/rust-lang/regex/issues/557)) which could cause
-the regex engine to enter an infinite loop. This bug was originally
-[reported against ripgrep](https://github.com/BurntSushi/ripgrep/issues/1247).
-
-
-1.1.5 (2019-04-01)
-==================
-This release fixes a bug in regex's dependency specification where it requires
-a newer version of regex-syntax, but this wasn't communicated correctly in the
-Cargo.toml. This would have been caught by a minimal version check, but this
-check was disabled because the `rand` crate itself advertises incorrect
-dependency specifications.
-
-Bug fixes:
-
-* [BUG #570](https://github.com/rust-lang/regex/pull/570):
-  Fix regex-syntax minimal version.
-
-
-1.1.4 (2019-03-31)
-==================
-This release fixes a backwards compatibility regression where Regex was no
-longer UnwindSafe. This was caused by the upgrade to aho-corasick 0.7, whose
-AhoCorasick type was itself not UnwindSafe. This has been fixed in aho-corasick
-0.7.4, which we now require.
-
-Bug fixes:
-
-* [BUG #568](https://github.com/rust-lang/regex/pull/568):
-  Fix an API regression where Regex was no longer UnwindSafe.
-
-
-1.1.3 (2019-03-30)
-==================
-This releases fixes a few bugs and adds a performance improvement when a regex
-is a simple alternation of literals.
-
-Performance improvements:
-
-* [OPT #566](https://github.com/rust-lang/regex/pull/566):
-  Upgrades `aho-corasick` to 0.7 and uses it for `foo|bar|...|quux` regexes.
-
-Bug fixes:
-
-* [BUG #527](https://github.com/rust-lang/regex/issues/527):
-  Fix a bug where the parser would panic on patterns like `((?x))`.
-* [BUG #555](https://github.com/rust-lang/regex/issues/555):
-  Fix a bug where the parser would panic on patterns like `(?m){1,1}`.
-* [BUG #557](https://github.com/rust-lang/regex/issues/557):
-  Fix a bug where captures could lead to an incorrect match.
-
-
-1.1.2 (2019-02-27)
-==================
-This release fixes a bug found in the fix introduced in 1.1.1.
-
-Bug fixes:
-
-* [BUG edf45e6f](https://github.com/rust-lang/regex/commit/edf45e6f):
-  Fix bug introduced in reverse suffix literal matcher in the 1.1.1 release.
-
-
-1.1.1 (2019-02-27)
-==================
-This is a small release with one fix for a bug caused by literal optimizations.
-
-Bug fixes:
-
-* [BUG 661bf53d](https://github.com/rust-lang/regex/commit/661bf53d):
-  Fixes a bug in the reverse suffix literal optimization. This was originally
-  reported
-  [against ripgrep](https://github.com/BurntSushi/ripgrep/issues/1203).
-
-
-1.1.0 (2018-11-30)
-==================
-This is a small release with a couple small enhancements. This release also
-increases the minimal supported Rust version (MSRV) to 1.24.1 (from 1.20.0). In
-accordance with this crate's MSRV policy, this release bumps the minor version
-number.
-
-Performance improvements:
-
-* [OPT #511](https://github.com/rust-lang/regex/pull/511),
-  [OPT #540](https://github.com/rust-lang/regex/pull/540):
-  Improve lazy DFA construction for large regex sets.
-
-New features:
-
-* [FEATURE #538](https://github.com/rust-lang/regex/pull/538):
-  Add Emoji and "break" Unicode properties. See [UNICODE.md](UNICODE.md).
-
-Bug fixes:
-
-* [BUG #530](https://github.com/rust-lang/regex/pull/530):
-  Add Unicode license (for data tables).
-* Various typo/doc fixups.
-
-
-1.0.6 (2018-11-06)
-==================
-This is a small release.
-
-Performance improvements:
-
-* [OPT #513](https://github.com/rust-lang/regex/pull/513):
-  Improve performance of compiling large Unicode classes by 8-10%.
-
-Bug fixes:
-
-* [BUG #533](https://github.com/rust-lang/regex/issues/533):
-  Fix definition of `[[:blank:]]` class that regressed in `regex-syntax 0.5`.
-
-
-1.0.5 (2018-09-06)
-==================
-This is a small release with an API enhancement.
-
-New features:
-
-* [FEATURE #509](https://github.com/rust-lang/regex/pull/509):
-  Generalize impls of the `Replacer` trait.
-
-
-1.0.4 (2018-08-25)
-==================
-This is a small release that bumps the quickcheck dependency.
-
-
-1.0.3 (2018-08-24)
-==================
-This is a small bug fix release.
-
-Bug fixes:
-
-* [BUG #504](https://github.com/rust-lang/regex/pull/504):
-  Fix for Cargo's "minimal version" support.
-* [BUG 1e39165f](https://github.com/rust-lang/regex/commit/1e39165f):
-  Fix doc examples for byte regexes.
-
-
-1.0.2 (2018-07-18)
-==================
-This release exposes some new lower level APIs on `Regex` that permit
-amortizing allocation and controlling the location at which a search is
-performed in a more granular way. Most users of the regex crate will not
-need or want to use these APIs.
-
-New features:
-
-* [FEATURE #493](https://github.com/rust-lang/regex/pull/493):
-  Add a few lower level APIs for amortizing allocation and more fine grained
-  searching.
-
-Bug fixes:
-
-* [BUG 3981d2ad](https://github.com/rust-lang/regex/commit/3981d2ad):
-  Correct outdated documentation on `RegexBuilder::dot_matches_new_line`.
-* [BUG 7ebe4ae0](https://github.com/rust-lang/regex/commit/7ebe4ae0):
-  Correct outdated documentation on `Parser::allow_invalid_utf8` in the
-  `regex-syntax` crate.
-* [BUG 24c7770b](https://github.com/rust-lang/regex/commit/24c7770b):
-  Fix a bug in the HIR printer where it wouldn't correctly escape meta
-  characters in character classes.
-
-
-1.0.1 (2018-06-19)
-==================
-This release upgrades regex's Unicode tables to Unicode 11, and enables SIMD
-optimizations automatically on Rust stable (1.27 or newer).
-
-New features:
-
-* [FEATURE #486](https://github.com/rust-lang/regex/pull/486):
-  Implement `size_hint` on `RegexSet` match iterators.
-* [FEATURE #488](https://github.com/rust-lang/regex/pull/488):
-  Update Unicode tables for Unicode 11.
-* [FEATURE #490](https://github.com/rust-lang/regex/pull/490):
-  SIMD optimizations are now enabled automatically in Rust stable, for versions
-  1.27 and up. No compilation flags or features need to be set. CPU support
-  SIMD is detected automatically at runtime.
-
-Bug fixes:
-
-* [BUG #482](https://github.com/rust-lang/regex/pull/482):
-  Present a better compilation error when the `use_std` feature isn't used.
-
-
-1.0.0 (2018-05-01)
-==================
-This release marks the 1.0 release of regex.
-
-While this release includes some breaking changes, most users of older versions
-of the regex library should be able to migrate to 1.0 by simply bumping the
-version number. The important changes are as follows:
-
-* We adopt Rust 1.20 as the new minimum supported version of Rust for regex.
-  We also tentativley adopt a policy that permits bumping the minimum supported
-  version of Rust in minor version releases of regex, but no patch releases.
-  That is, with respect to semver, we do not strictly consider bumping the
-  minimum version of Rust to be a breaking change, but adopt a conservative
-  stance as a compromise.
-* Octal syntax in regular expressions has been disabled by default. This
-  permits better error messages that inform users that backreferences aren't
-  available. Octal syntax can be re-enabled via the corresponding option on
-  `RegexBuilder`.
-* `(?-u:\B)` is no longer allowed in Unicode regexes since it can match at
-  invalid UTF-8 code unit boundaries. `(?-u:\b)` is still allowed in Unicode
-  regexes.
-* The `From<regex_syntax::Error>` impl has been removed. This formally removes
-  the public dependency on `regex-syntax`.
-* A new feature, `use_std`, has been added and enabled by default. Disabling
-  the feature will result in a compilation error. In the future, this may
-  permit us to support `no_std` environments (w/ `alloc`) in a backwards
-  compatible way.
-
-For more information and discussion, please see
-[1.0 release tracking issue](https://github.com/rust-lang/regex/issues/457).
-
-
-0.2.11 (2018-05-01)
-===================
-This release primarily contains bug fixes. Some of them resolve bugs where
-the parser could panic.
-
-New features:
-
-* [FEATURE #459](https://github.com/rust-lang/regex/pull/459):
-  Include C++'s standard regex library and Boost's regex library in the
-  benchmark harness. We now include D/libphobos, C++/std, C++/boost, Oniguruma,
-  PCRE1, PCRE2, RE2 and Tcl in the harness.
-
-Bug fixes:
-
-* [BUG #445](https://github.com/rust-lang/regex/issues/445):
-  Clarify order of indices returned by RegexSet match iterator.
-* [BUG #461](https://github.com/rust-lang/regex/issues/461):
-  Improve error messages for invalid regexes like `[\d-a]`.
-* [BUG #464](https://github.com/rust-lang/regex/issues/464):
-  Fix a bug in the error message pretty printer that could cause a panic when
-  a regex contained a literal `\n` character.
-* [BUG #465](https://github.com/rust-lang/regex/issues/465):
-  Fix a panic in the parser that was caused by applying a repetition operator
-  to `(?flags)`.
-* [BUG #466](https://github.com/rust-lang/regex/issues/466):
-  Fix a bug where `\pC` was not recognized as an alias for `\p{Other}`.
-* [BUG #470](https://github.com/rust-lang/regex/pull/470):
-  Fix a bug where literal searches did more work than necessary for anchored
-  regexes.
-
-
-0.2.10 (2018-03-16)
-===================
-This release primarily updates the regex crate to changes made in `std::arch`
-on nightly Rust.
-
-New features:
-
-* [FEATURE #458](https://github.com/rust-lang/regex/pull/458):
-  The `Hir` type in `regex-syntax` now has a printer.
-
-
-0.2.9 (2018-03-12)
-==================
-This release introduces a new nightly only feature, `unstable`, which enables
-SIMD optimizations for certain types of regexes. No additional compile time
-options are necessary, and the regex crate will automatically choose the
-best CPU features at run time. As a result, the `simd` (nightly only) crate
-dependency has been dropped.
-
-New features:
-
-* [FEATURE #456](https://github.com/rust-lang/regex/pull/456):
-  The regex crate now includes AVX2 optimizations in addition to the extant
-  SSSE3 optimization.
-
-Bug fixes:
-
-* [BUG #455](https://github.com/rust-lang/regex/pull/455):
-  Fix a bug where `(?x)[ / - ]` failed to parse.
-
-
-0.2.8 (2018-03-12)
-==================
-Bug gixes:
-
-* [BUG #454](https://github.com/rust-lang/regex/pull/454):
-  Fix a bug in the nest limit checker being too aggressive.
-
-
-0.2.7 (2018-03-07)
-==================
-This release includes a ground-up rewrite of the regex-syntax crate, which has
-been in development for over a year.
-
-New features:
-
-* Error messages for invalid regexes have been greatly improved. You get these
-  automatically; you don't need to do anything. In addition to better
-  formatting, error messages will now explicitly call out the use of look
-  around. When regex 1.0 is released, this will happen for backreferences as
-  well.
-* Full support for intersection, difference and symmetric difference of
-  character classes. These can be used via the `&&`, `--` and `~~` binary
-  operators within classes.
-* A Unicode Level 1 conformat implementation of `\p{..}` character classes.
-  Things like `\p{scx:Hira}`, `\p{age:3.2}` or `\p{Changes_When_Casefolded}`
-  now work. All property name and value aliases are supported, and properties
-  are selected via loose matching. e.g., `\p{Greek}` is the same as
-  `\p{G r E e K}`.
-* A new `UNICODE.md` document has been added to this repository that
-  exhaustively documents support for UTS#18.
-* Empty sub-expressions are now permitted in most places. That is, `()+` is
-  now a valid regex.
-* Almost everything in regex-syntax now uses constant stack space, even when
-  performing anaylsis that requires structural induction. This reduces the risk
-  of a user provided regular expression causing a stack overflow.
-* [FEATURE #174](https://github.com/rust-lang/regex/issues/174):
-  The `Ast` type in `regex-syntax` now contains span information.
-* [FEATURE #424](https://github.com/rust-lang/regex/issues/424):
-  Support `\u`, `\u{...}`, `\U` and `\U{...}` syntax for specifying code points
-  in a regular expression.
-* [FEATURE #449](https://github.com/rust-lang/regex/pull/449):
-  Add a `Replace::by_ref` adapter for use of a replacer without consuming it.
-
-Bug fixes:
-
-* [BUG #446](https://github.com/rust-lang/regex/issues/446):
-  We re-enable the Boyer-Moore literal matcher.
-
-
-0.2.6 (2018-02-08)
-==================
-Bug fixes:
-
-* [BUG #446](https://github.com/rust-lang/regex/issues/446):
-  Fixes a bug in the new Boyer-Moore searcher that results in a match failure.
-  We fix this bug by temporarily disabling Boyer-Moore.
-
-
-0.2.5 (2017-12-30)
-==================
-Bug fixes:
-
-* [BUG #437](https://github.com/rust-lang/regex/issues/437):
-  Fixes a bug in the new Boyer-Moore searcher that results in a panic.
-
-
-0.2.4 (2017-12-30)
-==================
-New features:
-
-* [FEATURE #348](https://github.com/rust-lang/regex/pull/348):
-  Improve performance for capture searches on anchored regex.
-  (Contributed by @ethanpailes. Nice work!)
-* [FEATURE #419](https://github.com/rust-lang/regex/pull/419):
-  Expand literal searching to include Tuned Boyer-Moore in some cases.
-  (Contributed by @ethanpailes. Nice work!)
-
-Bug fixes:
-
-* [BUG](https://github.com/rust-lang/regex/pull/436):
-  The regex compiler plugin has been removed.
-* [BUG](https://github.com/rust-lang/regex/pull/436):
-  `simd` has been bumped to `0.2.1`, which fixes a Rust nightly build error.
-* [BUG](https://github.com/rust-lang/regex/pull/436):
-  Bring the benchmark harness up to date.
-
-
-0.2.3 (2017-11-30)
-==================
-New features:
-
-* [FEATURE #374](https://github.com/rust-lang/regex/pull/374):
-  Add `impl From<Match> for &str`.
-* [FEATURE #380](https://github.com/rust-lang/regex/pull/380):
-  Derive `Clone` and `PartialEq` on `Error`.
-* [FEATURE #400](https://github.com/rust-lang/regex/pull/400):
-  Update to Unicode 10.
-
-Bug fixes:
-
-* [BUG #375](https://github.com/rust-lang/regex/issues/375):
-  Fix a bug that prevented the bounded backtracker from terminating.
-* [BUG #393](https://github.com/rust-lang/regex/issues/393),
-  [BUG #394](https://github.com/rust-lang/regex/issues/394):
-  Fix bug with `replace` methods for empty matches.
-
-
-0.2.2 (2017-05-21)
-==================
-New features:
-
-* [FEATURE #341](https://github.com/rust-lang/regex/issues/341):
-  Support nested character classes and intersection operation.
-  For example, `[\p{Greek}&&\pL]` matches greek letters and
-  `[[0-9]&&[^4]]` matches every decimal digit except `4`.
-  (Much thanks to @robinst, who contributed this awesome feature.)
-
-Bug fixes:
-
-* [BUG #321](https://github.com/rust-lang/regex/issues/321):
-  Fix bug in literal extraction and UTF-8 decoding.
-* [BUG #326](https://github.com/rust-lang/regex/issues/326):
-  Add documentation tip about the `(?x)` flag.
-* [BUG #333](https://github.com/rust-lang/regex/issues/333):
-  Show additional replacement example using curly braces.
-* [BUG #334](https://github.com/rust-lang/regex/issues/334):
-  Fix bug when resolving captures after a match.
-* [BUG #338](https://github.com/rust-lang/regex/issues/338):
-  Add example that uses `Captures::get` to API documentation.
-* [BUG #353](https://github.com/rust-lang/regex/issues/353):
-  Fix RegexSet bug that caused match failure in some cases.
-* [BUG #354](https://github.com/rust-lang/regex/pull/354):
-  Fix panic in parser when `(?x)` is used.
-* [BUG #358](https://github.com/rust-lang/regex/issues/358):
-  Fix literal optimization bug with RegexSet.
-* [BUG #359](https://github.com/rust-lang/regex/issues/359):
-  Fix example code in README.
-* [BUG #365](https://github.com/rust-lang/regex/pull/365):
-  Fix bug in `rure_captures_len` in the C binding.
-* [BUG #367](https://github.com/rust-lang/regex/issues/367):
-  Fix byte class bug that caused a panic.
-
-
-0.2.1
-=====
-One major bug with `replace_all` has been fixed along with a couple of other
-touchups.
-
-* [BUG #312](https://github.com/rust-lang/regex/issues/312):
-  Fix documentation for `NoExpand` to reference correct lifetime parameter.
-* [BUG #314](https://github.com/rust-lang/regex/issues/314):
-  Fix a bug with `replace_all` when replacing a match with the empty string.
-* [BUG #316](https://github.com/rust-lang/regex/issues/316):
-  Note a missing breaking change from the `0.2.0` CHANGELOG entry.
-  (`RegexBuilder::compile` was renamed to `RegexBuilder::build`.)
-* [BUG #324](https://github.com/rust-lang/regex/issues/324):
-  Compiling `regex` should only require one version of `memchr` crate.
-
-
-0.2.0
-=====
-This is a new major release of the regex crate, and is an implementation of the
-[regex 1.0 RFC](https://github.com/rust-lang/rfcs/blob/master/text/1620-regex-1.0.md).
-We are releasing a `0.2` first, and if there are no major problems, we will
-release a `1.0` shortly. For `0.2`, the minimum *supported* Rust version is
-1.12.
-
-There are a number of **breaking changes** in `0.2`. They are split into two
-types. The first type correspond to breaking changes in regular expression
-syntax. The second type correspond to breaking changes in the API.
-
-Breaking changes for regex syntax:
-
-* POSIX character classes now require double bracketing. Previously, the regex
-  `[:upper:]` would parse as the `upper` POSIX character class. Now it parses
-  as the character class containing the characters `:upper:`. The fix to this
-  change is to use `[[:upper:]]` instead. Note that variants like
-  `[[:upper:][:blank:]]` continue to work.
-* The character `[` must always be escaped inside a character class.
-* The characters `&`, `-` and `~` must be escaped if any one of them are
-  repeated consecutively. For example, `[&]`, `[\&]`, `[\&\&]`, `[&-&]` are all
-  equivalent while `[&&]` is illegal. (The motivation for this and the prior
-  change is to provide a backwards compatible path for adding character class
-  set notation.)
-* A `bytes::Regex` now has Unicode mode enabled by default (like the main
-  `Regex` type). This means regexes compiled with `bytes::Regex::new` that
-  don't have the Unicode flag set should add `(?-u)` to recover the original
-  behavior.
-
-Breaking changes for the regex API:
-
-* `find` and `find_iter` now **return `Match` values instead of
-  `(usize, usize)`.** `Match` values have `start` and `end` methods, which
-  return the match offsets. `Match` values also have an `as_str` method,
-  which returns the text of the match itself.
-* The `Captures` type now only provides a single iterator over all capturing
-  matches, which should replace uses of `iter` and `iter_pos`. Uses of
-  `iter_named` should use the `capture_names` method on `Regex`.
-* The `at` method on the `Captures` type has been renamed to `get`, and it
-  now returns a `Match`. Similarly, the `name` method on `Captures` now returns
-  a `Match`.
-* The `replace` methods now return `Cow` values. The `Cow::Borrowed` variant
-  is returned when no replacements are made.
-* The `Replacer` trait has been completely overhauled. This should only
-  impact clients that implement this trait explicitly. Standard uses of
-  the `replace` methods should continue to work unchanged. If you implement
-  the `Replacer` trait, please consult the new documentation.
-* The `quote` free function has been renamed to `escape`.
-* The `Regex::with_size_limit` method has been removed. It is replaced by
-  `RegexBuilder::size_limit`.
-* The `RegexBuilder` type has switched from owned `self` method receivers to
-  `&mut self` method receivers. Most uses will continue to work unchanged, but
-  some code may require naming an intermediate variable to hold the builder.
-* The `compile` method on `RegexBuilder` has been renamed to `build`.
-* The free `is_match` function has been removed. It is replaced by compiling
-  a `Regex` and calling its `is_match` method.
-* The `PartialEq` and `Eq` impls on `Regex` have been dropped. If you relied
-  on these impls, the fix is to define a wrapper type around `Regex`, impl
-  `Deref` on it and provide the necessary impls.
-* The `is_empty` method on `Captures` has been removed. This always returns
-  `false`, so its use is superfluous.
-* The `Syntax` variant of the `Error` type now contains a string instead of
-  a `regex_syntax::Error`. If you were examining syntax errors more closely,
-  you'll need to explicitly use the `regex_syntax` crate to re-parse the regex.
-* The `InvalidSet` variant of the `Error` type has been removed since it is
-  no longer used.
-* Most of the iterator types have been renamed to match conventions. If you
-  were using these iterator types explicitly, please consult the documentation
-  for its new name. For example, `RegexSplits` has been renamed to `Split`.
-
-A number of bugs have been fixed:
-
-* [BUG #151](https://github.com/rust-lang/regex/issues/151):
-  The `Replacer` trait has been changed to permit the caller to control
-  allocation.
-* [BUG #165](https://github.com/rust-lang/regex/issues/165):
-  Remove the free `is_match` function.
-* [BUG #166](https://github.com/rust-lang/regex/issues/166):
-  Expose more knobs (available in `0.1`) and remove `with_size_limit`.
-* [BUG #168](https://github.com/rust-lang/regex/issues/168):
-  Iterators produced by `Captures` now have the correct lifetime parameters.
-* [BUG #175](https://github.com/rust-lang/regex/issues/175):
-  Fix a corner case in the parsing of POSIX character classes.
-* [BUG #178](https://github.com/rust-lang/regex/issues/178):
-  Drop the `PartialEq` and `Eq` impls on `Regex`.
-* [BUG #179](https://github.com/rust-lang/regex/issues/179):
-  Remove `is_empty` from `Captures` since it always returns false.
-* [BUG #276](https://github.com/rust-lang/regex/issues/276):
-  Position of named capture can now be retrieved from a `Captures`.
-* [BUG #296](https://github.com/rust-lang/regex/issues/296):
-  Remove winapi/kernel32-sys dependency on UNIX.
-* [BUG #307](https://github.com/rust-lang/regex/issues/307):
-  Fix error on emscripten.
-
-
-0.1.80
-======
-* [PR #292](https://github.com/rust-lang/regex/pull/292):
-  Fixes bug #291, which was introduced by PR #290.
-
-0.1.79
-======
-* Require regex-syntax 0.3.8.
-
-0.1.78
-======
-* [PR #290](https://github.com/rust-lang/regex/pull/290):
-  Fixes bug #289, which caused some regexes with a certain combination
-  of literals to match incorrectly.
-
-0.1.77
-======
-* [PR #281](https://github.com/rust-lang/regex/pull/281):
-  Fixes bug #280 by disabling all literal optimizations when a pattern
-  is partially anchored.
-
-0.1.76
-======
-* Tweak criteria for using the Teddy literal matcher.
-
-0.1.75
-======
-* [PR #275](https://github.com/rust-lang/regex/pull/275):
-  Improves match verification performance in the Teddy SIMD searcher.
-* [PR #278](https://github.com/rust-lang/regex/pull/278):
-  Replaces slow substring loop in the Teddy SIMD searcher with Aho-Corasick.
-* Implemented DoubleEndedIterator on regex set match iterators.
-
-0.1.74
-======
-* Release regex-syntax 0.3.5 with a minor bug fix.
-* Fix bug #272.
-* Fix bug #277.
-* [PR #270](https://github.com/rust-lang/regex/pull/270):
-  Fixes bugs #264, #268 and an unreported where the DFA cache size could be
-  drastically under estimated in some cases (leading to high unexpected memory
-  usage).
-
-0.1.73
-======
-* Release `regex-syntax 0.3.4`.
-* Bump `regex-syntax` dependency version for `regex` to `0.3.4`.
-
-0.1.72
-======
-* [PR #262](https://github.com/rust-lang/regex/pull/262):
-  Fixes a number of small bugs caught by fuzz testing (AFL).
-
-0.1.71
-======
-* [PR #236](https://github.com/rust-lang/regex/pull/236):
-  Fix a bug in how suffix literals were extracted, which could lead
-  to invalid match behavior in some cases.
-
-0.1.70
-======
-* [PR #231](https://github.com/rust-lang/regex/pull/231):
-  Add SIMD accelerated multiple pattern search.
-* [PR #228](https://github.com/rust-lang/regex/pull/228):
-  Reintroduce the reverse suffix literal optimization.
-* [PR #226](https://github.com/rust-lang/regex/pull/226):
-  Implements NFA state compression in the lazy DFA.
-* [PR #223](https://github.com/rust-lang/regex/pull/223):
-  A fully anchored RegexSet can now short-circuit.
-
-0.1.69
-======
-* [PR #216](https://github.com/rust-lang/regex/pull/216):
-  Tweak the threshold for running backtracking.
-* [PR #217](https://github.com/rust-lang/regex/pull/217):
-  Add upper limit (from the DFA) to capture search (for the NFA).
-* [PR #218](https://github.com/rust-lang/regex/pull/218):
-  Add rure, a C API.
-
-0.1.68
-======
-* [PR #210](https://github.com/rust-lang/regex/pull/210):
-  Fixed a performance bug in `bytes::Regex::replace` where `extend` was used
-  instead of `extend_from_slice`.
-* [PR #211](https://github.com/rust-lang/regex/pull/211):
-  Fixed a bug in the handling of word boundaries in the DFA.
-* [PR #213](https://github.com/rust-lang/pull/213):
-  Added RE2 and Tcl to the benchmark harness. Also added a CLI utility from
-  running regexes using any of the following regex engines: PCRE1, PCRE2,
-  Oniguruma, RE2, Tcl and of course Rust's own regexes.
-
-0.1.67
-======
-* [PR #201](https://github.com/rust-lang/regex/pull/201):
-  Fix undefined behavior in the `regex!` compiler plugin macro.
-* [PR #205](https://github.com/rust-lang/regex/pull/205):
-  More improvements to DFA performance. Competitive with RE2. See PR for
-  benchmarks.
-* [PR #209](https://github.com/rust-lang/regex/pull/209):
-  Release 0.1.66 was semver incompatible since it required a newer version
-  of Rust than previous releases. This PR fixes that. (And `0.1.66` was
-  yanked.)
-
-0.1.66
-======
-* Speculative support for Unicode word boundaries was added to the DFA. This
-  should remove the last common case that disqualified use of the DFA.
-* An optimization that scanned for suffix literals and then matched the regular
-  expression in reverse was removed because it had worst case quadratic time
-  complexity. It was replaced with a more limited optimization where, given any
-  regex of the form `re$`, it will be matched in reverse from the end of the
-  haystack.
-* [PR #202](https://github.com/rust-lang/regex/pull/202):
-  The inner loop of the DFA was heavily optimized to improve cache locality
-  and reduce the overall number of instructions run on each iteration. This
-  represents the first use of `unsafe` in `regex` (to elide bounds checks).
-* [PR #200](https://github.com/rust-lang/regex/pull/200):
-  Use of the `mempool` crate (which used thread local storage) was replaced
-  with a faster version of a similar API in @Amanieu's `thread_local` crate.
-  It should reduce contention when using a regex from multiple threads
-  simultaneously.
-* PCRE2 JIT benchmarks were added. A benchmark comparison can be found
-  [here](https://gist.github.com/anonymous/14683c01993e91689f7206a18675901b).
-  (Includes a comparison with PCRE1's JIT and Oniguruma.)
-* A bug where word boundaries weren't being matched correctly in the DFA was
-  fixed. This only affected use of `bytes::Regex`.
-* [#160](https://github.com/rust-lang/regex/issues/160):
-  `Captures` now has a `Debug` impl.
diff --git a/vendor/regex-1.4.3/Cargo.lock b/vendor/regex-1.4.3/Cargo.lock
deleted file mode 100644 (file)
index eeaac4a..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-[[package]]
-name = "aho-corasick"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "autocfg"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
-
-[[package]]
-name = "bitflags"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
-
-[[package]]
-name = "cloudabi"
-version = "0.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "fuchsia-cprng"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
-
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
-name = "libc"
-version = "0.2.66"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
-
-[[package]]
-name = "memchr"
-version = "2.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223"
-
-[[package]]
-name = "quickcheck"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c35d9c36a562f37eca96e79f66d5fd56eefbc22560dacc4a864cabd2d277456"
-dependencies = [
- "rand",
- "rand_core 0.4.2",
-]
-
-[[package]]
-name = "rand"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
-dependencies = [
- "autocfg",
- "libc",
- "rand_chacha",
- "rand_core 0.4.2",
- "rand_hc",
- "rand_isaac",
- "rand_jitter",
- "rand_os",
- "rand_pcg",
- "rand_xorshift",
- "winapi",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
-dependencies = [
- "autocfg",
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
-dependencies = [
- "rand_core 0.4.2",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
-
-[[package]]
-name = "rand_hc"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
-dependencies = [
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "rand_isaac"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
-dependencies = [
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "rand_jitter"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
-dependencies = [
- "libc",
- "rand_core 0.4.2",
- "winapi",
-]
-
-[[package]]
-name = "rand_os"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
-dependencies = [
- "cloudabi",
- "fuchsia-cprng",
- "libc",
- "rand_core 0.4.2",
- "rdrand",
- "winapi",
-]
-
-[[package]]
-name = "rand_pcg"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
-dependencies = [
- "autocfg",
- "rand_core 0.4.2",
-]
-
-[[package]]
-name = "rand_xorshift"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
-dependencies = [
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "rdrand"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
-dependencies = [
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "regex"
-version = "1.4.3"
-dependencies = [
- "aho-corasick",
- "lazy_static",
- "memchr",
- "quickcheck",
- "rand",
- "regex-syntax",
- "thread_local",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
-
-[[package]]
-name = "thread_local"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
-dependencies = [
- "lazy_static",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/vendor/regex-1.4.3/Cargo.toml b/vendor/regex-1.4.3/Cargo.toml
deleted file mode 100644 (file)
index e43a1ba..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-name = "regex"
-version = "1.4.3"
-authors = ["The Rust Project Developers"]
-exclude = ["/scripts/*", "/.github/*"]
-autotests = false
-description = "An implementation of regular expressions for Rust. This implementation uses\nfinite automata and guarantees linear time matching on all inputs.\n"
-homepage = "https://github.com/rust-lang/regex"
-documentation = "https://docs.rs/regex"
-readme = "README.md"
-categories = ["text-processing"]
-license = "MIT OR Apache-2.0"
-repository = "https://github.com/rust-lang/regex"
-[profile.bench]
-debug = true
-
-[profile.release]
-debug = true
-
-[profile.test]
-debug = true
-
-[lib]
-doctest = false
-bench = false
-
-[[test]]
-name = "default"
-path = "tests/test_default.rs"
-
-[[test]]
-name = "default-bytes"
-path = "tests/test_default_bytes.rs"
-
-[[test]]
-name = "nfa"
-path = "tests/test_nfa.rs"
-
-[[test]]
-name = "nfa-utf8bytes"
-path = "tests/test_nfa_utf8bytes.rs"
-
-[[test]]
-name = "nfa-bytes"
-path = "tests/test_nfa_bytes.rs"
-
-[[test]]
-name = "backtrack"
-path = "tests/test_backtrack.rs"
-
-[[test]]
-name = "backtrack-utf8bytes"
-path = "tests/test_backtrack_utf8bytes.rs"
-
-[[test]]
-name = "backtrack-bytes"
-path = "tests/test_backtrack_bytes.rs"
-
-[[test]]
-name = "crates-regex"
-path = "tests/test_crates_regex.rs"
-[dependencies.aho-corasick]
-version = "0.7.6"
-optional = true
-
-[dependencies.memchr]
-version = "2.2.1"
-optional = true
-
-[dependencies.regex-syntax]
-version = "0.6.22"
-default-features = false
-
-[dependencies.thread_local]
-version = "1"
-optional = true
-[dev-dependencies.lazy_static]
-version = "1"
-
-[dev-dependencies.quickcheck]
-version = "0.8"
-default-features = false
-
-[dev-dependencies.rand]
-version = "0.6.5"
-
-[features]
-default = ["std", "perf", "unicode", "regex-syntax/default"]
-pattern = []
-perf = ["perf-cache", "perf-dfa", "perf-inline", "perf-literal"]
-perf-cache = ["thread_local"]
-perf-dfa = []
-perf-inline = []
-perf-literal = ["aho-corasick", "memchr"]
-std = []
-unicode = ["unicode-age", "unicode-bool", "unicode-case", "unicode-gencat", "unicode-perl", "unicode-script", "unicode-segment", "regex-syntax/unicode"]
-unicode-age = ["regex-syntax/unicode-age"]
-unicode-bool = ["regex-syntax/unicode-bool"]
-unicode-case = ["regex-syntax/unicode-case"]
-unicode-gencat = ["regex-syntax/unicode-gencat"]
-unicode-perl = ["regex-syntax/unicode-perl"]
-unicode-script = ["regex-syntax/unicode-script"]
-unicode-segment = ["regex-syntax/unicode-segment"]
-unstable = ["pattern"]
-use_std = ["std"]
diff --git a/vendor/regex-1.4.3/HACKING.md b/vendor/regex-1.4.3/HACKING.md
deleted file mode 100644 (file)
index 34af5b5..0000000
+++ /dev/null
@@ -1,341 +0,0 @@
-Your friendly guide to hacking and navigating the regex library.
-
-This guide assumes familiarity with Rust and Cargo, and at least a perusal of
-the user facing documentation for this crate.
-
-If you're looking for background on the implementation in this library, then
-you can do no better than Russ Cox's article series on implementing regular
-expressions using finite automata: https://swtch.com/~rsc/regexp/
-
-
-## Architecture overview
-
-As you probably already know, this library executes regular expressions using
-finite automata. In particular, a design goal is to make searching linear
-with respect to both the regular expression and the text being searched.
-Meeting that design goal on its own is not so hard and can be done with an
-implementation of the Pike VM (similar to Thompson's construction, but supports
-capturing groups), as described in: https://swtch.com/~rsc/regexp/regexp2.html
---- This library contains such an implementation in src/pikevm.rs.
-
-Making it fast is harder. One of the key problems with the Pike VM is that it
-can be in more than one state at any point in time, and must shuffle capture
-positions between them. The Pike VM also spends a lot of time following the
-same epsilon transitions over and over again. We can employ one trick to
-speed up the Pike VM: extract one or more literal prefixes from the regular
-expression and execute specialized code to quickly find matches of those
-prefixes in the search text. The Pike VM can then be avoided for most the
-search, and instead only executed when a prefix is found. The code to find
-prefixes is in the regex-syntax crate (in this repository). The code to search
-for literals is in src/literals.rs. When more than one literal prefix is found,
-we fall back to an Aho-Corasick DFA using the aho-corasick crate. For one
-literal, we use a variant of the Boyer-Moore algorithm. Both Aho-Corasick and
-Boyer-Moore use `memchr` when appropriate. The Boyer-Moore variant in this
-library also uses elementary frequency analysis to choose the right byte to run
-`memchr` with.
-
-Of course, detecting prefix literals can only take us so far. Not all regular
-expressions have literal prefixes. To remedy this, we try another approach
-to executing the Pike VM: backtracking, whose implementation can be found in
-src/backtrack.rs. One reason why backtracking can be faster is that it avoids
-excessive shuffling of capture groups. Of course, backtracking is susceptible
-to exponential runtimes, so we keep track of every state we've visited to make
-sure we never visit it again. This guarantees linear time execution, but we
-pay for it with the memory required to track visited states. Because of the
-memory requirement, we only use this engine on small search strings *and* small
-regular expressions.
-
-Lastly, the real workhorse of this library is the "lazy" DFA in src/dfa.rs.
-It is distinct from the Pike VM in that the DFA is explicitly represented in
-memory and is only ever in one state at a time. It is said to be "lazy" because
-the DFA is computed as text is searched, where each byte in the search text
-results in at most one new DFA state. It is made fast by caching states. DFAs
-are susceptible to exponential state blow up (where the worst case is computing
-a new state for every input byte, regardless of what's in the state cache). To
-avoid using a lot of memory, the lazy DFA uses a bounded cache. Once the cache
-is full, it is wiped and state computation starts over again. If the cache is
-wiped too frequently, then the DFA gives up and searching falls back to one of
-the aforementioned algorithms.
-
-All of the above matching engines expose precisely the same matching semantics.
-This is indeed tested. (See the section below about testing.)
-
-The following sub-sections describe the rest of the library and how each of the
-matching engines are actually used.
-
-### Parsing
-
-Regular expressions are parsed using the regex-syntax crate, which is
-maintained in this repository. The regex-syntax crate defines an abstract
-syntax and provides very detailed error messages when a parse error is
-encountered. Parsing is done in a separate crate so that others may benefit
-from its existence, and because it is relatively divorced from the rest of the
-regex library.
-
-The regex-syntax crate also provides sophisticated support for extracting
-prefix and suffix literals from regular expressions.
-
-### Compilation
-
-The compiler is in src/compile.rs. The input to the compiler is some abstract
-syntax for a regular expression and the output is a sequence of opcodes that
-matching engines use to execute a search. (One can think of matching engines as
-mini virtual machines.) The sequence of opcodes is a particular encoding of a
-non-deterministic finite automaton. In particular, the opcodes explicitly rely
-on epsilon transitions.
-
-Consider a simple regular expression like `a|b`. Its compiled form looks like
-this:
-
-    000 Save(0)
-    001 Split(2, 3)
-    002 'a' (goto: 4)
-    003 'b'
-    004 Save(1)
-    005 Match
-
-The first column is the instruction pointer and the second column is the
-instruction. Save instructions indicate that the current position in the input
-should be stored in a captured location. Split instructions represent a binary
-branch in the program (i.e., epsilon transitions). The instructions `'a'` and
-`'b'` indicate that the literal bytes `'a'` or `'b'` should match.
-
-In older versions of this library, the compilation looked like this:
-
-    000 Save(0)
-    001 Split(2, 3)
-    002 'a'
-    003 Jump(5)
-    004 'b'
-    005 Save(1)
-    006 Match
-
-In particular, empty instructions that merely served to move execution from one
-point in the program to another were removed. Instead, every instruction has a
-`goto` pointer embedded into it. This resulted in a small performance boost for
-the Pike VM, because it was one fewer epsilon transition that it had to follow.
-
-There exist more instructions and they are defined and documented in
-src/prog.rs.
-
-Compilation has several knobs and a few unfortunately complicated invariants.
-Namely, the output of compilation can be one of two types of programs: a
-program that executes on Unicode scalar values or a program that executes
-on raw bytes. In the former case, the matching engine is responsible for
-performing UTF-8 decoding and executing instructions using Unicode codepoints.
-In the latter case, the program handles UTF-8 decoding implicitly, so that the
-matching engine can execute on raw bytes. All matching engines can execute
-either Unicode or byte based programs except for the lazy DFA, which requires
-byte based programs. In general, both representations were kept because (1) the
-lazy DFA requires byte based programs so that states can be encoded in a memory
-efficient manner and (2) the Pike VM benefits greatly from inlining Unicode
-character classes into fewer instructions as it results in fewer epsilon
-transitions.
-
-N.B. UTF-8 decoding is built into the compiled program by making use of the
-utf8-ranges crate. The compiler in this library factors out common suffixes to
-reduce the size of huge character classes (e.g., `\pL`).
-
-A regrettable consequence of this split in instruction sets is we generally
-need to compile two programs; one for NFA execution and one for the lazy DFA.
-
-In fact, it is worse than that: the lazy DFA is not capable of finding the
-starting location of a match in a single scan, and must instead execute a
-backwards search after finding the end location. To execute a backwards search,
-we must have compiled the regular expression *in reverse*.
-
-This means that every compilation of a regular expression generally results in
-three distinct programs. It would be possible to lazily compile the Unicode
-program, since it is never needed if (1) the regular expression uses no word
-boundary assertions and (2) the caller never asks for sub-capture locations.
-
-### Execution
-
-At the time of writing, there are four matching engines in this library:
-
-1. The Pike VM (supports captures).
-2. Bounded backtracking (supports captures).
-3. Literal substring or multi-substring search.
-4. Lazy DFA (no support for Unicode word boundary assertions).
-
-Only the first two matching engines are capable of executing every regular
-expression program. They also happen to be the slowest, which means we need
-some logic that (1) knows various facts about the regular expression and (2)
-knows what the caller wants. Using this information, we can determine which
-engine (or engines) to use.
-
-The logic for choosing which engine to execute is in src/exec.rs and is
-documented on the Exec type. Exec values contain regular expression Programs
-(defined in src/prog.rs), which contain all the necessary tidbits for actually
-executing a regular expression on search text.
-
-For the most part, the execution logic is straight-forward and follows the
-limitations of each engine described above pretty faithfully. The hairiest
-part of src/exec.rs by far is the execution of the lazy DFA, since it requires
-a forwards and backwards search, and then falls back to either the Pike VM or
-backtracking if the caller requested capture locations.
-
-The Exec type also contains mutable scratch space for each type of matching
-engine. This scratch space is used during search (for example, for the lazy
-DFA, it contains compiled states that are reused on subsequent searches).
-
-### Programs
-
-A regular expression program is essentially a sequence of opcodes produced by
-the compiler plus various facts about the regular expression (such as whether
-it is anchored, its capture names, etc.).
-
-### The regex! macro
-
-The `regex!` macro no longer exists. It was developed in a bygone era as a
-compiler plugin during the infancy of the regex crate. Back then, then only
-matching engine in the crate was the Pike VM. The `regex!` macro was, itself,
-also a Pike VM. The only advantages it offered over the dynamic Pike VM that
-was built at runtime were the following:
-
-  1. Syntax checking was done at compile time. Your Rust program wouldn't
-     compile if your regex didn't compile.
-  2. Reduction of overhead that was proportional to the size of the regex.
-     For the most part, this overhead consisted of heap allocation, which
-     was nearly eliminated in the compiler plugin.
-
-The main takeaway here is that the compiler plugin was a marginally faster
-version of a slow regex engine. As the regex crate evolved, it grew other regex
-engines (DFA, bounded backtracker) and sophisticated literal optimizations.
-The regex macro didn't keep pace, and it therefore became (dramatically) slower
-than the dynamic engines. The only reason left to use it was for the compile
-time guarantee that your regex is correct. Fortunately, Clippy (the Rust lint
-tool) has a lint that checks your regular expression validity, which mostly
-replaces that use case.
-
-Additionally, the regex compiler plugin stopped receiving maintenance. Nobody
-complained. At that point, it seemed prudent to just remove it.
-
-Will a compiler plugin be brought back? The future is murky, but there is
-definitely an opportunity there to build something that is faster than the
-dynamic engines in some cases. But it will be challenging! As of now, there
-are no plans to work on this.
-
-
-## Testing
-
-A key aspect of any mature regex library is its test suite. A subset of the
-tests in this library come from Glenn Fowler's AT&T test suite (its online
-presence seems gone at the time of writing). The source of the test suite is
-located in src/testdata. The scripts/regex-match-tests.py takes the test suite
-in src/testdata and generates tests/matches.rs.
-
-There are also many other manually crafted tests and regression tests in
-tests/tests.rs. Some of these tests were taken from RE2.
-
-The biggest source of complexity in the tests is related to answering this
-question: how can we reuse the tests to check all of our matching engines? One
-approach would have been to encode every test into some kind of format (like
-the AT&T test suite) and code generate tests for each matching engine. The
-approach we use in this library is to create a Cargo.toml entry point for each
-matching engine we want to test. The entry points are:
-
-* `tests/test_default.rs` - tests `Regex::new`
-* `tests/test_default_bytes.rs` - tests `bytes::Regex::new`
-* `tests/test_nfa.rs` - tests `Regex::new`, forced to use the NFA
-  algorithm on every regex.
-* `tests/test_nfa_bytes.rs` - tests `Regex::new`, forced to use the NFA
-  algorithm on every regex and use *arbitrary* byte based programs.
-* `tests/test_nfa_utf8bytes.rs` - tests `Regex::new`, forced to use the NFA
-  algorithm on every regex and use *UTF-8* byte based programs.
-* `tests/test_backtrack.rs` - tests `Regex::new`, forced to use
-  backtracking on every regex.
-* `tests/test_backtrack_bytes.rs` - tests `Regex::new`, forced to use
-  backtracking on every regex and use *arbitrary* byte based programs.
-* `tests/test_backtrack_utf8bytes.rs` - tests `Regex::new`, forced to use
-  backtracking on every regex and use *UTF-8* byte based programs.
-* `tests/test_crates_regex.rs` - tests to make sure that all of the
-  backends behave in the same way against a number of quickcheck
-  generated random inputs. These tests need to be enabled through
-  the `RUST_REGEX_RANDOM_TEST` environment variable (see
-  below).
-
-The lazy DFA and pure literal engines are absent from this list because
-they cannot be used on every regular expression. Instead, we rely on
-`tests/test_dynamic.rs` to test the lazy DFA and literal engines when possible.
-
-Since the tests are repeated several times, and because `cargo test` runs all
-entry points, it can take a while to compile everything. To reduce compile
-times slightly, try using `cargo test --test default`, which will only use the
-`tests/test_default.rs` entry point.
-
-The random testing takes quite a while, so it is not enabled by default.
-In order to run the random testing you can set the
-`RUST_REGEX_RANDOM_TEST` environment variable to anything before
-invoking `cargo test`. Note that this variable is inspected at compile
-time, so if the tests don't seem to be running, you may need to run
-`cargo clean`.
-
-## Benchmarking
-
-The benchmarking in this crate is made up of many micro-benchmarks. Currently,
-there are two primary sets of benchmarks: the benchmarks that were adopted
-at this library's inception (in `bench/src/misc.rs`) and a newer set of
-benchmarks meant to test various optimizations. Specifically, the latter set
-contain some analysis and are in `bench/src/sherlock.rs`. Also, the latter
-set are all executed on the same lengthy input whereas the former benchmarks
-are executed on strings of varying length.
-
-There is also a smattering of benchmarks for parsing and compilation.
-
-Benchmarks are in a separate crate so that its dependencies can be managed
-separately from the main regex crate.
-
-Benchmarking follows a similarly wonky setup as tests. There are multiple entry
-points:
-
-* `bench_rust.rs` - benchmarks `Regex::new`
-* `bench_rust_bytes.rs` benchmarks `bytes::Regex::new`
-* `bench_pcre.rs` - benchmarks PCRE
-* `bench_onig.rs` - benchmarks Oniguruma
-
-The PCRE and Oniguruma benchmarks exist as a comparison point to a mature
-regular expression library. In general, this regex library compares favorably
-(there are even a few benchmarks that PCRE simply runs too slowly on or
-outright can't execute at all). I would love to add other regular expression
-library benchmarks (especially RE2).
-
-If you're hacking on one of the matching engines and just want to see
-benchmarks, then all you need to run is:
-
-    $ (cd bench && ./run rust)
-
-If you want to compare your results with older benchmarks, then try:
-
-    $ (cd bench && ./run rust | tee old)
-    $ ... make it faster
-    $ (cd bench && ./run rust | tee new)
-    $ cargo benchcmp old new --improvements
-
-The `cargo-benchcmp` utility is available here:
-https://github.com/BurntSushi/cargo-benchcmp
-
-The `./bench/run` utility can run benchmarks for PCRE and Oniguruma too. See
-`./bench/bench --help`.
-
-## Dev Docs
-
-When digging your teeth into the codebase for the first time, the
-crate documentation can be a great resource. By default `rustdoc`
-will strip out all documentation of private crate members in an
-effort to help consumers of the crate focus on the *interface*
-without having to concern themselves with the *implementation*.
-Normally this is a great thing, but if you want to start hacking
-on regex internals it is not what you want. Many of the private members
-of this crate are well documented with rustdoc style comments, and
-it would be a shame to miss out on the opportunity that presents.
-You can generate the private docs with:
-
-```
-$ rustdoc --crate-name docs src/lib.rs -o target/doc -L target/debug/deps --no-defaults --passes collapse-docs --passes unindent-comments
-```
-
-Then just point your browser at `target/doc/regex/index.html`.
-
-See https://github.com/rust-lang/rust/issues/15347 for more info
-about generating developer docs for internal use.
diff --git a/vendor/regex-1.4.3/LICENSE-APACHE b/vendor/regex-1.4.3/LICENSE-APACHE
deleted file mode 100644 (file)
index 16fe87b..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-                              Apache License
-                        Version 2.0, January 2004
-                     http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-   "License" shall mean the terms and conditions for use, reproduction,
-   and distribution as defined by Sections 1 through 9 of this document.
-
-   "Licensor" shall mean the copyright owner or entity authorized by
-   the copyright owner that is granting the License.
-
-   "Legal Entity" shall mean the union of the acting entity and all
-   other entities that control, are controlled by, or are under common
-   control with that entity. For the purposes of this definition,
-   "control" means (i) the power, direct or indirect, to cause the
-   direction or management of such entity, whether by contract or
-   otherwise, or (ii) ownership of fifty percent (50%) or more of the
-   outstanding shares, or (iii) beneficial ownership of such entity.
-
-   "You" (or "Your") shall mean an individual or Legal Entity
-   exercising permissions granted by this License.
-
-   "Source" form shall mean the preferred form for making modifications,
-   including but not limited to software source code, documentation
-   source, and configuration files.
-
-   "Object" form shall mean any form resulting from mechanical
-   transformation or translation of a Source form, including but
-   not limited to compiled object code, generated documentation,
-   and conversions to other media types.
-
-   "Work" shall mean the work of authorship, whether in Source or
-   Object form, made available under the License, as indicated by a
-   copyright notice that is included in or attached to the work
-   (an example is provided in the Appendix below).
-
-   "Derivative Works" shall mean any work, whether in Source or Object
-   form, that is based on (or derived from) the Work and for which the
-   editorial revisions, annotations, elaborations, or other modifications
-   represent, as a whole, an original work of authorship. For the purposes
-   of this License, Derivative Works shall not include works that remain
-   separable from, or merely link (or bind by name) to the interfaces of,
-   the Work and Derivative Works thereof.
-
-   "Contribution" shall mean any work of authorship, including
-   the original version of the Work and any modifications or additions
-   to that Work or Derivative Works thereof, that is intentionally
-   submitted to Licensor for inclusion in the Work by the copyright owner
-   or by an individual or Legal Entity authorized to submit on behalf of
-   the copyright owner. For the purposes of this definition, "submitted"
-   means any form of electronic, verbal, or written communication sent
-   to the Licensor or its representatives, including but not limited to
-   communication on electronic mailing lists, source code control systems,
-   and issue tracking systems that are managed by, or on behalf of, the
-   Licensor for the purpose of discussing and improving the Work, but
-   excluding communication that is conspicuously marked or otherwise
-   designated in writing by the copyright owner as "Not a Contribution."
-
-   "Contributor" shall mean Licensor and any individual or Legal Entity
-   on behalf of whom a Contribution has been received by Licensor and
-   subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   copyright license to reproduce, prepare Derivative Works of,
-   publicly display, publicly perform, sublicense, and distribute the
-   Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   (except as stated in this section) patent license to make, have made,
-   use, offer to sell, sell, import, and otherwise transfer the Work,
-   where such license applies only to those patent claims licensable
-   by such Contributor that are necessarily infringed by their
-   Contribution(s) alone or by combination of their Contribution(s)
-   with the Work to which such Contribution(s) was submitted. If You
-   institute patent litigation against any entity (including a
-   cross-claim or counterclaim in a lawsuit) alleging that the Work
-   or a Contribution incorporated within the Work constitutes direct
-   or contributory patent infringement, then any patent licenses
-   granted to You under this License for that Work shall terminate
-   as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
-   Work or Derivative Works thereof in any medium, with or without
-   modifications, and in Source or Object form, provided that You
-   meet the following conditions:
-
-   (a) You must give any other recipients of the Work or
-       Derivative Works a copy of this License; and
-
-   (b) You must cause any modified files to carry prominent notices
-       stating that You changed the files; and
-
-   (c) You must retain, in the Source form of any Derivative Works
-       that You distribute, all copyright, patent, trademark, and
-       attribution notices from the Source form of the Work,
-       excluding those notices that do not pertain to any part of
-       the Derivative Works; and
-
-   (d) If the Work includes a "NOTICE" text file as part of its
-       distribution, then any Derivative Works that You distribute must
-       include a readable copy of the attribution notices contained
-       within such NOTICE file, excluding those notices that do not
-       pertain to any part of the Derivative Works, in at least one
-       of the following places: within a NOTICE text file distributed
-       as part of the Derivative Works; within the Source form or
-       documentation, if provided along with the Derivative Works; or,
-       within a display generated by the Derivative Works, if and
-       wherever such third-party notices normally appear. The contents
-       of the NOTICE file are for informational purposes only and
-       do not modify the License. You may add Your own attribution
-       notices within Derivative Works that You distribute, alongside
-       or as an addendum to the NOTICE text from the Work, provided
-       that such additional attribution notices cannot be construed
-       as modifying the License.
-
-   You may add Your own copyright statement to Your modifications and
-   may provide additional or different license terms and conditions
-   for use, reproduction, or distribution of Your modifications, or
-   for any such Derivative Works as a whole, provided Your use,
-   reproduction, and distribution of the Work otherwise complies with
-   the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-   any Contribution intentionally submitted for inclusion in the Work
-   by You to the Licensor shall be under the terms and conditions of
-   this License, without any additional terms or conditions.
-   Notwithstanding the above, nothing herein shall supersede or modify
-   the terms of any separate license agreement you may have executed
-   with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-   names, trademarks, service marks, or product names of the Licensor,
-   except as required for reasonable and customary use in describing the
-   origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-   agreed to in writing, Licensor provides the Work (and each
-   Contributor provides its Contributions) on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-   implied, including, without limitation, any warranties or conditions
-   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-   PARTICULAR PURPOSE. You are solely responsible for determining the
-   appropriateness of using or redistributing the Work and assume any
-   risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-   whether in tort (including negligence), contract, or otherwise,
-   unless required by applicable law (such as deliberate and grossly
-   negligent acts) or agreed to in writing, shall any Contributor be
-   liable to You for damages, including any direct, indirect, special,
-   incidental, or consequential damages of any character arising as a
-   result of this License or out of the use or inability to use the
-   Work (including but not limited to damages for loss of goodwill,
-   work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses), even if such Contributor
-   has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-   the Work or Derivative Works thereof, You may choose to offer,
-   and charge a fee for, acceptance of support, warranty, indemnity,
-   or other liability obligations and/or rights consistent with this
-   License. However, in accepting such obligations, You may act only
-   on Your own behalf and on Your sole responsibility, not on behalf
-   of any other Contributor, and only if You agree to indemnify,
-   defend, and hold each Contributor harmless for any liability
-   incurred by, or claims asserted against, such Contributor by reason
-   of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-   To apply the Apache License to your work, attach the following
-   boilerplate notice, with the fields enclosed by brackets "[]"
-   replaced with your own identifying information. (Don't include
-   the brackets!)  The text should be enclosed in the appropriate
-   comment syntax for the file format. We also recommend that a
-   file or class name and description of purpose be included on the
-   same "printed page" as the copyright notice for easier
-   identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/vendor/regex-1.4.3/LICENSE-MIT b/vendor/regex-1.4.3/LICENSE-MIT
deleted file mode 100644 (file)
index 39d4bdb..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2014 The Rust Project Developers
-
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/vendor/regex-1.4.3/PERFORMANCE.md b/vendor/regex-1.4.3/PERFORMANCE.md
deleted file mode 100644 (file)
index b4aeb89..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-Your friendly guide to understanding the performance characteristics of this
-crate.
-
-This guide assumes some familiarity with the public API of this crate, which
-can be found here: https://docs.rs/regex
-
-## Theory vs. Practice
-
-One of the design goals of this crate is to provide worst case linear time
-behavior with respect to the text searched using finite state automata. This
-means that, *in theory*, the performance of this crate is much better than most
-regex implementations, which typically use backtracking which has worst case
-exponential time.
-
-For example, try opening a Python interpreter and typing this:
-
-    >>> import re
-    >>> re.search('(a*)*c', 'a' * 30).span()
-
-I'll wait.
-
-At some point, you'll figure out that it won't terminate any time soon. ^C it.
-
-The promise of this crate is that *this pathological behavior can't happen*.
-
-With that said, just because we have protected ourselves against worst case
-exponential behavior doesn't mean we are immune from large constant factors
-or places where the current regex engine isn't quite optimal. This guide will
-detail those cases and provide guidance on how to avoid them, among other
-bits of general advice.
-
-## Thou Shalt Not Compile Regular Expressions In A Loop
-
-**Advice**: Use `lazy_static` to amortize the cost of `Regex` compilation.
-
-Don't do it unless you really don't mind paying for it. Compiling a regular
-expression in this crate is quite expensive. It is conceivable that it may get
-faster some day, but I wouldn't hold out hope for, say, an order of magnitude
-improvement. In particular, compilation can take any where from a few dozen
-microseconds to a few dozen milliseconds. Yes, milliseconds. Unicode character
-classes, in particular, have the largest impact on compilation performance. At
-the time of writing, for example, `\pL{100}` takes around 44ms to compile. This
-is because `\pL` corresponds to every letter in Unicode and compilation must
-turn it into a proper automaton that decodes a subset of UTF-8 which
-corresponds to those letters. Compilation also spends some cycles shrinking the
-size of the automaton.
-
-This means that in order to realize efficient regex matching, one must
-*amortize the cost of compilation*. Trivially, if a call to `is_match` is
-inside a loop, then make sure your call to `Regex::new` is *outside* that loop.
-
-In many programming languages, regular expressions can be conveniently defined
-and compiled in a global scope, and code can reach out and use them as if
-they were global static variables. In Rust, there is really no concept of
-life-before-main, and therefore, one cannot utter this:
-
-    static MY_REGEX: Regex = Regex::new("...").unwrap();
-
-Unfortunately, this would seem to imply that one must pass `Regex` objects
-around to everywhere they are used, which can be especially painful depending
-on how your program is structured. Thankfully, the
-[`lazy_static`](https://crates.io/crates/lazy_static)
-crate provides an answer that works well:
-
-    #[macro_use] extern crate lazy_static;
-    extern crate regex;
-
-    use regex::Regex;
-
-    fn some_helper_function(text: &str) -> bool {
-        lazy_static! {
-            static ref MY_REGEX: Regex = Regex::new("...").unwrap();
-        }
-        MY_REGEX.is_match(text)
-    }
-
-In other words, the `lazy_static!` macro enables us to define a `Regex` *as if*
-it were a global static value. What is actually happening under the covers is
-that the code inside the macro (i.e., `Regex::new(...)`) is run on *first use*
-of `MY_REGEX` via a `Deref` impl. The implementation is admittedly magical, but
-it's self contained and everything works exactly as you expect. In particular,
-`MY_REGEX` can be used from multiple threads without wrapping it in an `Arc` or
-a `Mutex`. On that note...
-
-## Using a regex from multiple threads
-
-**Advice**: The performance impact from using a `Regex` from multiple threads
-is likely negligible. If necessary, clone the `Regex` so that each thread gets
-its own copy. Cloning a regex does not incur any additional memory overhead
-than what would be used by using a `Regex` from multiple threads
-simultaneously. *Its only cost is ergonomics.*
-
-It is supported and encouraged to define your regexes using `lazy_static!` as
-if they were global static values, and then use them to search text from
-multiple threads simultaneously.
-
-One might imagine that this is possible because a `Regex` represents a
-*compiled* program, so that any allocation or mutation is already done, and is
-therefore read-only. Unfortunately, this is not true. Each type of search
-strategy in this crate requires some kind of mutable scratch space to use
-*during search*. For example, when executing a DFA, its states are computed
-lazily and reused on subsequent searches. Those states go into that mutable
-scratch space.
-
-The mutable scratch space is an implementation detail, and in general, its
-mutation should not be observable from users of this crate. Therefore, it uses
-interior mutability. This implies that `Regex` can either only be used from one
-thread, or it must do some sort of synchronization. Either choice is
-reasonable, but this crate chooses the latter, in particular because it is
-ergonomic and makes use with `lazy_static!` straight forward.
-
-Synchronization implies *some* amount of overhead. When a `Regex` is used from
-a single thread, this overhead is negligible. When a `Regex` is used from
-multiple threads simultaneously, it is possible for the overhead of
-synchronization from contention to impact performance. The specific cases where
-contention may happen is if you are calling any of these methods repeatedly
-from multiple threads simultaneously:
-
-* shortest_match
-* is_match
-* find
-* captures
-
-In particular, every invocation of one of these methods must synchronize with
-other threads to retrieve its mutable scratch space before searching can start.
-If, however, you are using one of these methods:
-
-* find_iter
-* captures_iter
-
-Then you may not suffer from contention since the cost of synchronization is
-amortized on *construction of the iterator*. That is, the mutable scratch space
-is obtained when the iterator is created and retained throughout its lifetime.
-
-## Only ask for what you need
-
-**Advice**: Prefer in this order: `is_match`, `find`, `captures`.
-
-There are three primary search methods on a `Regex`:
-
-* is_match
-* find
-* captures
-
-In general, these are ordered from fastest to slowest.
-
-`is_match` is fastest because it doesn't actually need to find the start or the
-end of the leftmost-first match. It can quit immediately after it knows there
-is a match. For example, given the regex `a+` and the haystack, `aaaaa`, the
-search will quit after examing the first byte.
-
-In constrast, `find` must return both the start and end location of the
-leftmost-first match. It can use the DFA matcher for this, but must run it
-forwards once to find the end of the match *and then run it backwards* to find
-the start of the match. The two scans and the cost of finding the real end of
-the leftmost-first match make this more expensive than `is_match`.
-
-`captures` is the most expensive of them all because it must do what `find`
-does, and then run either the bounded backtracker or the Pike VM to fill in the
-capture group locations. Both of these are simulations of an NFA, which must
-spend a lot of time shuffling states around. The DFA limits the performance hit
-somewhat by restricting the amount of text that must be searched via an NFA
-simulation.
-
-One other method not mentioned is `shortest_match`. This method has precisely
-the same performance characteristics as `is_match`, except it will return the
-end location of when it discovered a match. For example, given the regex `a+`
-and the haystack `aaaaa`, `shortest_match` may return `1` as opposed to `5`,
-the latter of which being the correct end location of the leftmost-first match.
-
-## Literals in your regex may make it faster
-
-**Advice**: Literals can reduce the work that the regex engine needs to do. Use
-them if you can, especially as prefixes.
-
-In particular, if your regex starts with a prefix literal, the prefix is
-quickly searched before entering the (much slower) regex engine. For example,
-given the regex `foo\w+`, the literal `foo` will be searched for using
-Boyer-Moore. If there's no match, then no regex engine is ever used. Only when
-there's a match is the regex engine invoked at the location of the match, which
-effectively permits the regex engine to skip large portions of a haystack.
-If a regex is comprised entirely of literals (possibly more than one), then
-it's possible that the regex engine can be avoided entirely even when there's a
-match.
-
-When one literal is found, Boyer-Moore is used. When multiple literals are
-found, then an optimized version of Aho-Corasick is used.
-
-This optimization is in particular extended quite a bit in this crate. Here are
-a few examples of regexes that get literal prefixes detected:
-
-* `(foo|bar)` detects `foo` and `bar`
-* `(a|b)c` detects `ac` and `bc`
-* `[ab]foo[yz]` detects `afooy`, `afooz`, `bfooy` and `bfooz`
-* `a?b` detects `a` and `b`
-* `a*b` detects `a` and `b`
-* `(ab){3,6}` detects `ababab`
-
-Literals in anchored regexes can also be used for detecting non-matches very
-quickly. For example, `^foo\w+` and `\w+foo$` may be able to detect a non-match
-just by examing the first (or last) three bytes of the haystack.
-
-## Unicode word boundaries may prevent the DFA from being used
-
-**Advice**: In most cases, `\b` should work well. If not, use `(?-u:\b)`
-instead of `\b` if you care about consistent performance more than correctness.
-
-It's a sad state of the current implementation. At the moment, the DFA will try
-to interpret Unicode word boundaries as if they were ASCII word boundaries.
-If the DFA comes across any non-ASCII byte, it will quit and fall back to an
-alternative matching engine that can handle Unicode word boundaries correctly.
-The alternate matching engine is generally quite a bit slower (perhaps by an
-order of magnitude). If necessary, this can be ameliorated in two ways.
-
-The first way is to add some number of literal prefixes to your regular
-expression. Even though the DFA may not be used, specialized routines will
-still kick in to find prefix literals quickly, which limits how much work the
-NFA simulation will need to do.
-
-The second way is to give up on Unicode and use an ASCII word boundary instead.
-One can use an ASCII word boundary by disabling Unicode support. That is,
-instead of using `\b`, use `(?-u:\b)`.  Namely, given the regex `\b.+\b`, it
-can be transformed into a regex that uses the DFA with `(?-u:\b).+(?-u:\b)`. It
-is important to limit the scope of disabling the `u` flag, since it might lead
-to a syntax error if the regex could match arbitrary bytes. For example, if one
-wrote `(?-u)\b.+\b`, then a syntax error would be returned because `.` matches
-any *byte* when the Unicode flag is disabled.
-
-The second way isn't appreciably different than just using a Unicode word
-boundary in the first place, since the DFA will speculatively interpret it as
-an ASCII word boundary anyway. The key difference is that if an ASCII word
-boundary is used explicitly, then the DFA won't quit in the presence of
-non-ASCII UTF-8 bytes. This results in giving up correctness in exchange for
-more consistent performance.
-
-N.B. When using `bytes::Regex`, Unicode support is disabled by default, so one
-can simply write `\b` to get an ASCII word boundary.
-
-## Excessive counting can lead to exponential state blow up in the DFA
-
-**Advice**: Don't write regexes that cause DFA state blow up if you care about
-match performance.
-
-Wait, didn't I say that this crate guards against exponential worst cases?
-Well, it turns out that the process of converting an NFA to a DFA can lead to
-an exponential blow up in the number of states. This crate specifically guards
-against exponential blow up by doing two things:
-
-1. The DFA is computed lazily. That is, a state in the DFA only exists in
-   memory if it is visited. In particular, the lazy DFA guarantees that *at
-   most* one state is created for every byte of input. This, on its own,
-   guarantees linear time complexity.
-2. Of course, creating a new state for *every* byte of input means that search
-   will go incredibly slow because of very large constant factors. On top of
-   that, creating a state for every byte in a large haystack could result in
-   exorbitant memory usage. To ameliorate this, the DFA bounds the number of
-   states it can store. Once it reaches its limit, it flushes its cache. This
-   prevents reuse of states that it already computed. If the cache is flushed
-   too frequently, then the DFA will give up and execution will fall back to
-   one of the NFA simulations.
-
-In effect, this crate will detect exponential state blow up and fall back to
-a search routine with fixed memory requirements. This does, however, mean that
-searching will be much slower than one might expect. Regexes that rely on
-counting in particular are strong aggravators of this behavior. For example,
-matching `[01]*1[01]{20}$` against a random sequence of `0`s and `1`s.
-
-In the future, it may be possible to increase the bound that the DFA uses,
-which would allow the caller to choose how much memory they're willing to
-spend.
-
-## Resist the temptation to "optimize" regexes
-
-**Advice**: This ain't a backtracking engine.
-
-An entire book was written on how to optimize Perl-style regular expressions.
-Most of those techniques are not applicable for this library. For example,
-there is no problem with using non-greedy matching or having lots of
-alternations in your regex.
diff --git a/vendor/regex-1.4.3/README.md b/vendor/regex-1.4.3/README.md
deleted file mode 100644 (file)
index 8c05a90..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-regex
-=====
-A Rust library for parsing, compiling, and executing regular expressions. Its
-syntax is similar to Perl-style regular expressions, but lacks a few features
-like look around and backreferences. In exchange, all searches execute in
-linear time with respect to the size of the regular expression and search text.
-Much of the syntax and implementation is inspired
-by [RE2](https://github.com/google/re2).
-
-[![Build status](https://github.com/rust-lang/regex/workflows/ci/badge.svg)](https://github.com/rust-lang/regex/actions)
-[![](https://meritbadge.herokuapp.com/regex)](https://crates.io/crates/regex)
-[![Rust](https://img.shields.io/badge/rust-1.28.0%2B-blue.svg?maxAge=3600)](https://github.com/rust-lang/regex)
-
-### Documentation
-
-[Module documentation with examples](https://docs.rs/regex).
-The module documentation also includes a comprehensive description of the
-syntax supported.
-
-Documentation with examples for the various matching functions and iterators
-can be found on the
-[`Regex` type](https://docs.rs/regex/*/regex/struct.Regex.html).
-
-### Usage
-
-Add this to your `Cargo.toml`:
-
-```toml
-[dependencies]
-regex = "1"
-```
-
-and this to your crate root (if you're using Rust 2015):
-
-```rust
-extern crate regex;
-```
-
-Here's a simple example that matches a date in YYYY-MM-DD format and prints the
-year, month and day:
-
-```rust
-use regex::Regex;
-
-fn main() {
-    let re = Regex::new(r"(?x)
-(?P<year>\d{4})  # the year
--
-(?P<month>\d{2}) # the month
--
-(?P<day>\d{2})   # the day
-").unwrap();
-    let caps = re.captures("2010-03-14").unwrap();
-
-    assert_eq!("2010", &caps["year"]);
-    assert_eq!("03", &caps["month"]);
-    assert_eq!("14", &caps["day"]);
-}
-```
-
-If you have lots of dates in text that you'd like to iterate over, then it's
-easy to adapt the above example with an iterator:
-
-```rust
-use regex::Regex;
-
-const TO_SEARCH: &'static str = "
-On 2010-03-14, foo happened. On 2014-10-14, bar happened.
-";
-
-fn main() {
-    let re = Regex::new(r"(\d{4})-(\d{2})-(\d{2})").unwrap();
-
-    for caps in re.captures_iter(TO_SEARCH) {
-        // Note that all of the unwraps are actually OK for this regex
-        // because the only way for the regex to match is if all of the
-        // capture groups match. This is not true in general though!
-        println!("year: {}, month: {}, day: {}",
-                 caps.get(1).unwrap().as_str(),
-                 caps.get(2).unwrap().as_str(),
-                 caps.get(3).unwrap().as_str());
-    }
-}
-```
-
-This example outputs:
-
-```text
-year: 2010, month: 03, day: 14
-year: 2014, month: 10, day: 14
-```
-
-### Usage: Avoid compiling the same regex in a loop
-
-It is an anti-pattern to compile the same regular expression in a loop since
-compilation is typically expensive. (It takes anywhere from a few microseconds
-to a few **milliseconds** depending on the size of the regex.) Not only is
-compilation itself expensive, but this also prevents optimizations that reuse
-allocations internally to the matching engines.
-
-In Rust, it can sometimes be a pain to pass regular expressions around if
-they're used from inside a helper function. Instead, we recommend using the
-[`lazy_static`](https://crates.io/crates/lazy_static) crate to ensure that
-regular expressions are compiled exactly once.
-
-For example:
-
-```rust,ignore
-use regex::Regex;
-
-fn some_helper_function(text: &str) -> bool {
-    lazy_static! {
-        static ref RE: Regex = Regex::new("...").unwrap();
-    }
-    RE.is_match(text)
-}
-```
-
-Specifically, in this example, the regex will be compiled when it is used for
-the first time. On subsequent uses, it will reuse the previous compilation.
-
-### Usage: match regular expressions on `&[u8]`
-
-The main API of this crate (`regex::Regex`) requires the caller to pass a
-`&str` for searching. In Rust, an `&str` is required to be valid UTF-8, which
-means the main API can't be used for searching arbitrary bytes.
-
-To match on arbitrary bytes, use the `regex::bytes::Regex` API. The API
-is identical to the main API, except that it takes an `&[u8]` to search
-on instead of an `&str`. By default, `.` will match any *byte* using
-`regex::bytes::Regex`, while `.` will match any *UTF-8 encoded Unicode scalar
-value* using the main API.
-
-This example shows how to find all null-terminated strings in a slice of bytes:
-
-```rust
-use regex::bytes::Regex;
-
-let re = Regex::new(r"(?P<cstr>[^\x00]+)\x00").unwrap();
-let text = b"foo\x00bar\x00baz\x00";
-
-// Extract all of the strings without the null terminator from each match.
-// The unwrap is OK here since a match requires the `cstr` capture to match.
-let cstrs: Vec<&[u8]> =
-    re.captures_iter(text)
-      .map(|c| c.name("cstr").unwrap().as_bytes())
-      .collect();
-assert_eq!(vec![&b"foo"[..], &b"bar"[..], &b"baz"[..]], cstrs);
-```
-
-Notice here that the `[^\x00]+` will match any *byte* except for `NUL`. When
-using the main API, `[^\x00]+` would instead match any valid UTF-8 sequence
-except for `NUL`.
-
-### Usage: match multiple regular expressions simultaneously
-
-This demonstrates how to use a `RegexSet` to match multiple (possibly
-overlapping) regular expressions in a single scan of the search text:
-
-```rust
-use regex::RegexSet;
-
-let set = RegexSet::new(&[
-    r"\w+",
-    r"\d+",
-    r"\pL+",
-    r"foo",
-    r"bar",
-    r"barfoo",
-    r"foobar",
-]).unwrap();
-
-// Iterate over and collect all of the matches.
-let matches: Vec<_> = set.matches("foobar").into_iter().collect();
-assert_eq!(matches, vec![0, 2, 3, 4, 6]);
-
-// You can also test whether a particular regex matched:
-let matches = set.matches("foobar");
-assert!(!matches.matched(5));
-assert!(matches.matched(6));
-```
-
-### Usage: enable SIMD optimizations
-
-SIMD optimizations are enabled automatically on Rust stable 1.27 and newer.
-For nightly versions of Rust, this requires a recent version with the SIMD
-features stabilized.
-
-
-### Usage: a regular expression parser
-
-This repository contains a crate that provides a well tested regular expression
-parser, abstract syntax and a high-level intermediate representation for
-convenient analysis. It provides no facilities for compilation or execution.
-This may be useful if you're implementing your own regex engine or otherwise
-need to do analysis on the syntax of a regular expression. It is otherwise not
-recommended for general use.
-
-[Documentation `regex-syntax`.](https://docs.rs/regex-syntax)
-
-
-### Crate features
-
-This crate comes with several features that permit tweaking the trade off
-between binary size, compilation time and runtime performance. Users of this
-crate can selectively disable Unicode tables, or choose from a variety of
-optimizations performed by this crate to disable.
-
-When all of these features are disabled, runtime match performance may be much
-worse, but if you're matching on short strings, or if high performance isn't
-necessary, then such a configuration is perfectly serviceable. To disable
-all such features, use the following `Cargo.toml` dependency configuration:
-
-```toml
-[dependencies.regex]
-version = "1.3"
-default-features = false
-# regex currently requires the standard library, you must re-enable it.
-features = ["std"]
-```
-
-This will reduce the dependency tree of `regex` down to a single crate
-(`regex-syntax`).
-
-The full set of features one can disable are
-[in the "Crate features" section of the documentation](https://docs.rs/regex/*/#crate-features).
-
-
-### Minimum Rust version policy
-
-This crate's minimum supported `rustc` version is `1.28.0`.
-
-The current **tentative** policy is that the minimum Rust version required
-to use this crate can be increased in minor version updates. For example, if
-regex 1.0 requires Rust 1.20.0, then regex 1.0.z for all values of `z` will
-also require Rust 1.20.0 or newer. However, regex 1.y for `y > 0` may require a
-newer minimum version of Rust.
-
-In general, this crate will be conservative with respect to the minimum
-supported version of Rust.
-
-
-### License
-
-This project is licensed under either of
-
- * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
-   http://www.apache.org/licenses/LICENSE-2.0)
- * MIT license ([LICENSE-MIT](LICENSE-MIT) or
-   http://opensource.org/licenses/MIT)
-
-at your option.
-
-The data in `regex-syntax/src/unicode_tables/` is licensed under the Unicode
-License Agreement
-([LICENSE-UNICODE](http://www.unicode.org/copyright.html#License)).
diff --git a/vendor/regex-1.4.3/UNICODE.md b/vendor/regex-1.4.3/UNICODE.md
deleted file mode 100644 (file)
index 18fa9b1..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-# Unicode conformance
-
-This document describes the regex crate's conformance to Unicode's
-[UTS#18](http://unicode.org/reports/tr18/)
-report, which lays out 3 levels of support: Basic, Extended and Tailored.
-
-Full support for Level 1 ("Basic Unicode Support") is provided with two
-exceptions:
-
-1. Line boundaries are not Unicode aware. Namely, only the `\n`
-   (`END OF LINE`) character is recognized as a line boundary.
-2. The compatibility properties specified by
-   [RL1.2a](http://unicode.org/reports/tr18/#RL1.2a)
-   are ASCII-only definitions.
-
-Little to no support is provided for either Level 2 or Level 3. For the most
-part, this is because the features are either complex/hard to implement, or at
-the very least, very difficult to implement without sacrificing performance.
-For example, tackling canonical equivalence such that matching worked as one
-would expect regardless of normalization form would be a significant
-undertaking. This is at least partially a result of the fact that this regex
-engine is based on finite automata, which admits less flexibility normally
-associated with backtracking implementations.
-
-
-## RL1.1 Hex Notation
-
-[UTS#18 RL1.1](https://unicode.org/reports/tr18/#Hex_notation)
-
-Hex Notation refers to the ability to specify a Unicode code point in a regular
-expression via its hexadecimal code point representation. This is useful in
-environments that have poor Unicode font rendering or if you need to express a
-code point that is not normally displayable. All forms of hexadecimal notation
-are supported
-
-    \x7F        hex character code (exactly two digits)
-    \x{10FFFF}  any hex character code corresponding to a Unicode code point
-    \u007F      hex character code (exactly four digits)
-    \u{7F}      any hex character code corresponding to a Unicode code point
-    \U0000007F  hex character code (exactly eight digits)
-    \U{7F}      any hex character code corresponding to a Unicode code point
-
-Briefly, the `\x{...}`, `\u{...}` and `\U{...}` are all exactly equivalent ways
-of expressing hexadecimal code points. Any number of digits can be written
-within the brackets. In contrast, `\xNN`, `\uNNNN`, `\UNNNNNNNN` are all
-fixed-width variants of the same idea.
-
-Note that when Unicode mode is disabled, any non-ASCII Unicode codepoint is
-banned. Additionally, the `\xNN` syntax represents arbitrary bytes when Unicode
-mode is disabled. That is, the regex `\xFF` matches the Unicode codepoint
-U+00FF (encoded as `\xC3\xBF` in UTF-8) while the regex `(?-u)\xFF` matches
-the literal byte `\xFF`.
-
-
-## RL1.2 Properties
-
-[UTS#18 RL1.2](https://unicode.org/reports/tr18/#Categories)
-
-Full support for Unicode property syntax is provided. Unicode properties
-provide a convenient way to construct character classes of groups of code
-points specified by Unicode. The regex crate does not provide exhaustive
-support, but covers a useful subset. In particular:
-
-* [General categories](http://unicode.org/reports/tr18/#General_Category_Property)
-* [Scripts and Script Extensions](http://unicode.org/reports/tr18/#Script_Property)
-* [Age](http://unicode.org/reports/tr18/#Age)
-* A smattering of boolean properties, including all of those specified by
-  [RL1.2](http://unicode.org/reports/tr18/#RL1.2) explicitly.
-
-In all cases, property name and value abbreviations are supported, and all
-names/values are matched loosely without regard for case, whitespace or
-underscores. Property name aliases can be found in Unicode's
-[`PropertyAliases.txt`](http://www.unicode.org/Public/UCD/latest/ucd/PropertyAliases.txt)
-file, while property value aliases can be found in Unicode's
-[`PropertyValueAliases.txt`](http://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt)
-file.
-
-The syntax supported is also consistent with the UTS#18 recommendation:
-
-* `\p{Greek}` selects the `Greek` script. Equivalent expressions follow:
-  `\p{sc:Greek}`, `\p{Script:Greek}`, `\p{Sc=Greek}`, `\p{script=Greek}`,
-  `\P{sc!=Greek}`. Similarly for `General_Category` (or `gc` for short) and
-  `Script_Extensions` (or `scx` for short).
-* `\p{age:3.2}` selects all code points in Unicode 3.2.
-* `\p{Alphabetic}` selects the "alphabetic" property and can be abbreviated
-  via `\p{alpha}` (for example).
-* Single letter variants for properties with single letter abbreviations.
-  For example, `\p{Letter}` can be equivalently written as `\pL`.
-
-The following is a list of all properties supported by the regex crate (starred
-properties correspond to properties required by RL1.2):
-
-* `General_Category` \* (including `Any`, `ASCII` and `Assigned`)
-* `Script` \*
-* `Script_Extensions` \*
-* `Age`
-* `ASCII_Hex_Digit`
-* `Alphabetic` \*
-* `Bidi_Control`
-* `Case_Ignorable`
-* `Cased`
-* `Changes_When_Casefolded`
-* `Changes_When_Casemapped`
-* `Changes_When_Lowercased`
-* `Changes_When_Titlecased`
-* `Changes_When_Uppercased`
-* `Dash`
-* `Default_Ignorable_Code_Point` \*
-* `Deprecated`
-* `Diacritic`
-* `Emoji`
-* `Emoji_Presentation`
-* `Emoji_Modifier`
-* `Emoji_Modifier_Base`
-* `Emoji_Component`
-* `Extended_Pictographic`
-* `Extender`
-* `Grapheme_Base`
-* `Grapheme_Cluster_Break`
-* `Grapheme_Extend`
-* `Hex_Digit`
-* `IDS_Binary_Operator`
-* `IDS_Trinary_Operator`
-* `ID_Continue`
-* `ID_Start`
-* `Join_Control`
-* `Logical_Order_Exception`
-* `Lowercase` \*
-* `Math`
-* `Noncharacter_Code_Point` \*
-* `Pattern_Syntax`
-* `Pattern_White_Space`
-* `Prepended_Concatenation_Mark`
-* `Quotation_Mark`
-* `Radical`
-* `Regional_Indicator`
-* `Sentence_Break`
-* `Sentence_Terminal`
-* `Soft_Dotted`
-* `Terminal_Punctuation`
-* `Unified_Ideograph`
-* `Uppercase` \*
-* `Variation_Selector`
-* `White_Space` \*
-* `Word_Break`
-* `XID_Continue`
-* `XID_Start`
-
-
-## RL1.2a Compatibility Properties
-
-[UTS#18 RL1.2a](http://unicode.org/reports/tr18/#RL1.2a)
-
-The regex crate only provides ASCII definitions of the
-[compatibility properties documented in UTS#18 Annex C](http://unicode.org/reports/tr18/#Compatibility_Properties)
-(sans the `\X` class, for matching grapheme clusters, which isn't provided
-at all). This is because it seems to be consistent with most other regular
-expression engines, and in particular, because these are often referred to as
-"ASCII" or "POSIX" character classes.
-
-Note that the `\w`, `\s` and `\d` character classes **are** Unicode aware.
-Their traditional ASCII definition can be used by disabling Unicode. That is,
-`[[:word:]]` and `(?-u)\w` are equivalent.
-
-
-## RL1.3 Subtraction and Intersection
-
-[UTS#18 RL1.3](http://unicode.org/reports/tr18/#Subtraction_and_Intersection)
-
-The regex crate provides full support for nested character classes, along with
-union, intersection (`&&`), difference (`--`) and symmetric difference (`~~`)
-operations on arbitrary character classes.
-
-For example, to match all non-ASCII letters, you could use either
-`[\p{Letter}--\p{Ascii}]` (difference) or `[\p{Letter}&&[^\p{Ascii}]]`
-(intersecting the negation).
-
-
-## RL1.4 Simple Word Boundaries
-
-[UTS#18 RL1.4](http://unicode.org/reports/tr18/#Simple_Word_Boundaries)
-
-The regex crate provides basic Unicode aware word boundary assertions. A word
-boundary assertion can be written as `\b`, or `\B` as its negation. A word
-boundary negation corresponds to a zero-width match, where its adjacent
-characters correspond to word and non-word, or non-word and word characters.
-
-Conformance in this case chooses to define word character in the same way that
-the `\w` character class is defined: a code point that is a member of one of
-the following classes:
-
-* `\p{Alphabetic}`
-* `\p{Join_Control}`
-* `\p{gc:Mark}`
-* `\p{gc:Decimal_Number}`
-* `\p{gc:Connector_Punctuation}`
-
-In particular, this differs slightly from the
-[prescription given in RL1.4](http://unicode.org/reports/tr18/#Simple_Word_Boundaries)
-but is permissible according to
-[UTS#18 Annex C](http://unicode.org/reports/tr18/#Compatibility_Properties).
-Namely, it is convenient and simpler to have `\w` and `\b` be in sync with
-one another.
-
-Finally, Unicode word boundaries can be disabled, which will cause ASCII word
-boundaries to be used instead. That is, `\b` is a Unicode word boundary while
-`(?-u)\b` is an ASCII-only word boundary. This can occasionally be beneficial
-if performance is important, since the implementation of Unicode word
-boundaries is currently sub-optimal on non-ASCII text.
-
-
-## RL1.5 Simple Loose Matches
-
-[UTS#18 RL1.5](http://unicode.org/reports/tr18/#Simple_Loose_Matches)
-
-The regex crate provides full support for case insensitive matching in
-accordance with RL1.5. That is, it uses the "simple" case folding mapping. The
-"simple" mapping was chosen because of a key convenient property: every
-"simple" mapping is a mapping from exactly one code point to exactly one other
-code point. This makes case insensitive matching of character classes, for
-example, straight-forward to implement.
-
-When case insensitive mode is enabled (e.g., `(?i)[a]` is equivalent to `a|A`),
-then all characters classes are case folded as well.
-
-
-## RL1.6 Line Boundaries
-
-[UTS#18 RL1.6](http://unicode.org/reports/tr18/#Line_Boundaries)
-
-The regex crate only provides support for recognizing the `\n` (`END OF LINE`)
-character as a line boundary. This choice was made mostly for implementation
-convenience, and to avoid performance cliffs that Unicode word boundaries are
-subject to.
-
-Ideally, it would be nice to at least support `\r\n` as a line boundary as
-well, and in theory, this could be done efficiently.
-
-
-## RL1.7 Code Points
-
-[UTS#18 RL1.7](http://unicode.org/reports/tr18/#Supplementary_Characters)
-
-The regex crate provides full support for Unicode code point matching. Namely,
-the fundamental atom of any match is always a single code point.
-
-Given Rust's strong ties to UTF-8, the following guarantees are also provided:
-
-* All matches are reported on valid UTF-8 code unit boundaries. That is, any
-  match range returned by the public regex API is guaranteed to successfully
-  slice the string that was searched.
-* By consequence of the above, it is impossible to match surrogode code points.
-  No support for UTF-16 is provided, so this is never necessary.
-
-Note that when Unicode mode is disabled, the fundamental atom of matching is
-no longer a code point but a single byte. When Unicode mode is disabled, many
-Unicode features are disabled as well. For example, `(?-u)\pL` is not a valid
-regex but `\pL(?-u)\xFF` (matches any Unicode `Letter` followed by the literal
-byte `\xFF`) is, for example.
diff --git a/vendor/regex-1.4.3/examples/regexdna-input.txt b/vendor/regex-1.4.3/examples/regexdna-input.txt
deleted file mode 100644 (file)
index fb23263..0000000
+++ /dev/null
@@ -1,1671 +0,0 @@
->ONE Homo sapiens alu
-GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA
-TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT
-AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG
-GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG
-CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT
-GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA
-GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA
-TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG
-AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA
-GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT
-AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC
-AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG
-GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC
-CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG
-AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT
-TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA
-TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT
-GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG
-TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT
-CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG
-CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG
-TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA
-CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG
-AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG
-GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC
-TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA
-TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA
-GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT
-GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC
-ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT
-TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC
-CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG
-CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG
-GGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCC
-CAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCT
-GGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGC
-GCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGA
-GGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGA
-GACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGA
-GGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTG
-AAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT
-CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCA
-GTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAA
-AAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGC
-GGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCT
-ACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGG
-GAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATC
-GCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGC
-GGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGG
-TCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAA
-AAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAG
-GAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACT
-CCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCC
-TGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAG
-ACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGC
-GTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGA
-ACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGA
-CAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCA
-CTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCA
-ACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCG
-CCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGG
-AGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTC
-CGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCG
-AGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACC
-CCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAG
-CTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAG
-CCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGG
-CCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATC
-ACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAA
-AAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGC
-TGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCC
-ACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGG
-CTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGG
-AGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATT
-AGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAA
-TCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGC
-CTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAA
-TCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAG
-CCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGT
-GGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCG
-GGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAG
-CGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG
-GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATG
-GTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGT
-AATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTT
-GCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCT
-CAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCG
-GGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTC
-TCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACT
-CGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAG
-ATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGG
-CGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTG
-AGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATA
-CAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGG
-CAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGC
-ACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCAC
-GCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTC
-GAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCG
-GGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCT
-TGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGG
-CGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCA
-GCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGG
-CCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGC
-GCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGG
-CGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGA
-CTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGG
-CCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAA
-ACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCC
-CAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGT
-GAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAA
-AGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGG
-ATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTAC
-TAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGA
-GGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGC
-GCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGG
-TGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTC
-AGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAA
-ATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGA
-GAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC
-AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTG
-TAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGAC
-CAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGT
-GGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC
-CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACA
-GAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACT
-TTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAAC
-ATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCC
-TGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAG
-GTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCG
-TCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAG
-GCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCC
-GTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCT
-ACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCC
-GAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCC
-GGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCAC
-CTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAA
-ATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTG
-AGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCAC
-TGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCT
-CACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAG
-TTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAG
-CCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATC
-GCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCT
-GGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATC
-CCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCC
-TGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGG
-CGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG
-AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCG
-AGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGG
-AGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGT
-GAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAA
-TCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGC
-AGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCA
-AAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGG
-CGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTC
-TACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCG
-GGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGAT
-CGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCG
-CGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAG
-GTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACA
-AAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCA
-GGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCAC
-TCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGC
-CTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA
-GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGG
-CGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTG
-AACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCG
-ACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGC
-ACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCC
-AACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGC
-GCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCG
-GAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACT
-CCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCC
-GAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAAC
-CCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA
-GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGA
-GCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAG
-GCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGAT
-CACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTA
-AAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGG
-CTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGC
-CACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTG
-GCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAG
-GAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAAT
-TAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGA
-ATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAG
-CCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTA
-ATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCA
-GCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGG
-TGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCC
-GGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGA
-GCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTT
-GGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACAT
-GGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTG
-TAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGT
-TGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTC
-TCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGC
-GGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGT
-CTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTAC
-TCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGA
-GATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGG
-GCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCT
-GAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT
-ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAG
-GCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG
-CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCA
-CGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTT
-CGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCC
-GGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGC
-TTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGG
-GCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCC
-AGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTG
-GCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCG
-CGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAG
-GCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAG
-ACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAG
-GCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGA
-AACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATC
-CCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAG
-TGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAA
-AAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCG
-GATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTA
-CTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGG
-AGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCG
-CGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCG
-GTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGT
-CAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAA
-AATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGG
-AGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTC
-CAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCT
-GTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA
-CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCG
-TGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAA
-CCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGAC
-AGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCAC
-TTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAA
-CATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGC
-CTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGA
-GGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCC
-GTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGA
-GGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCC
-CGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGC
-TACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGC
-CGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGC
-CGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCA
-CCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA
-AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCT
-GAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCA
-CTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGC
-TCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGA
-GTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTA
-GCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAAT
-CGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCC
-TGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAAT
-CCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGC
-CTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTG
-GCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGG
-GAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGC
-GAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG
-GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGG
-TGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTA
-ATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTG
-CAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTC
-AAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGG
-GCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCT
-CTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTC
-GGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGA
-TCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGC
-GCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGA
-GGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATAC
-AAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGC
-AGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCA
-CTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACG
-CCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCG
-AGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGG
-GCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTT
-GAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGC
-GACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAG
-CACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGC
-CAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCG
-CGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGC
-GGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGAC
-TCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGC
-CGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAA
-CCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCC
-AGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTG
-AGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA
-GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA
-TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT
-AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG
-GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG
-CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT
-GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA
-GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA
-TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG
-AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA
-GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT
-AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC
-AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG
-GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC
-CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG
-AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT
-TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA
-TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT
-GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG
-TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT
-CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG
-CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG
-TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA
-CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG
-AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG
-GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC
-TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA
-TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA
-GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT
-GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC
-ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT
-TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC
-CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG
-CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG
-GGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCC
-CAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCT
-GGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGC
-GCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGA
-GGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGA
-GACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGA
-GGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTG
-AAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT
-CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCA
-GTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAA
-AAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGC
-GGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCT
-ACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGG
-GAGGCTGAGGCAGGAGAATC
->TWO IUB ambiguity codes
-cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg
-tactDtDagcctatttSVHtHttKtgtHMaSattgWaHKHttttagacatWatgtRgaaa
-NtactMcSMtYtcMgRtacttctWBacgaaatatagScDtttgaagacacatagtVgYgt
-cattHWtMMWcStgttaggKtSgaYaaccWStcgBttgcgaMttBYatcWtgacaYcaga
-gtaBDtRacttttcWatMttDBcatWtatcttactaBgaYtcttgttttttttYaaScYa
-HgtgttNtSatcMtcVaaaStccRcctDaataataStcYtRDSaMtDttgttSagtRRca
-tttHatSttMtWgtcgtatSSagactYaaattcaMtWatttaSgYttaRgKaRtccactt
-tattRggaMcDaWaWagttttgacatgttctacaaaRaatataataaMttcgDacgaSSt
-acaStYRctVaNMtMgtaggcKatcttttattaaaaagVWaHKYagtttttatttaacct
-tacgtVtcVaattVMBcttaMtttaStgacttagattWWacVtgWYagWVRctDattBYt
-gtttaagaagattattgacVatMaacattVctgtBSgaVtgWWggaKHaatKWcBScSWa
-accRVacacaaactaccScattRatatKVtactatatttHttaagtttSKtRtacaaagt
-RDttcaaaaWgcacatWaDgtDKacgaacaattacaRNWaatHtttStgttattaaMtgt
-tgDcgtMgcatBtgcttcgcgaDWgagctgcgaggggVtaaScNatttacttaatgacag
-cccccacatYScaMgtaggtYaNgttctgaMaacNaMRaacaaacaKctacatagYWctg
-ttWaaataaaataRattagHacacaagcgKatacBttRttaagtatttccgatctHSaat
-actcNttMaagtattMtgRtgaMgcataatHcMtaBSaRattagttgatHtMttaaKagg
-YtaaBataSaVatactWtataVWgKgttaaaacagtgcgRatatacatVtHRtVYataSa
-KtWaStVcNKHKttactatccctcatgWHatWaRcttactaggatctataDtDHBttata
-aaaHgtacVtagaYttYaKcctattcttcttaataNDaaggaaaDYgcggctaaWSctBa
-aNtgctggMBaKctaMVKagBaactaWaDaMaccYVtNtaHtVWtKgRtcaaNtYaNacg
-gtttNattgVtttctgtBaWgtaattcaagtcaVWtactNggattctttaYtaaagccgc
-tcttagHVggaYtgtNcDaVagctctctKgacgtatagYcctRYHDtgBattDaaDgccK
-tcHaaStttMcctagtattgcRgWBaVatHaaaataYtgtttagMDMRtaataaggatMt
-ttctWgtNtgtgaaaaMaatatRtttMtDgHHtgtcattttcWattRSHcVagaagtacg
-ggtaKVattKYagactNaatgtttgKMMgYNtcccgSKttctaStatatNVataYHgtNa
-BKRgNacaactgatttcctttaNcgatttctctataScaHtataRagtcRVttacDSDtt
-aRtSatacHgtSKacYagttMHtWataggatgactNtatSaNctataVtttRNKtgRacc
-tttYtatgttactttttcctttaaacatacaHactMacacggtWataMtBVacRaSaatc
-cgtaBVttccagccBcttaRKtgtgcctttttRtgtcagcRttKtaaacKtaaatctcac
-aattgcaNtSBaaccgggttattaaBcKatDagttactcttcattVtttHaaggctKKga
-tacatcBggScagtVcacattttgaHaDSgHatRMaHWggtatatRgccDttcgtatcga
-aacaHtaagttaRatgaVacttagattVKtaaYttaaatcaNatccRttRRaMScNaaaD
-gttVHWgtcHaaHgacVaWtgttScactaagSgttatcttagggDtaccagWattWtRtg
-ttHWHacgattBtgVcaYatcggttgagKcWtKKcaVtgaYgWctgYggVctgtHgaNcV
-taBtWaaYatcDRaaRtSctgaHaYRttagatMatgcatttNattaDttaattgttctaa
-ccctcccctagaWBtttHtBccttagaVaatMcBHagaVcWcagBVttcBtaYMccagat
-gaaaaHctctaacgttagNWRtcggattNatcRaNHttcagtKttttgWatWttcSaNgg
-gaWtactKKMaacatKatacNattgctWtatctaVgagctatgtRaHtYcWcttagccaa
-tYttWttaWSSttaHcaaaaagVacVgtaVaRMgattaVcDactttcHHggHRtgNcctt
-tYatcatKgctcctctatVcaaaaKaaaagtatatctgMtWtaaaacaStttMtcgactt
-taSatcgDataaactaaacaagtaaVctaggaSccaatMVtaaSKNVattttgHccatca
-cBVctgcaVatVttRtactgtVcaattHgtaaattaaattttYtatattaaRSgYtgBag
-aHSBDgtagcacRHtYcBgtcacttacactaYcgctWtattgSHtSatcataaatataHt
-cgtYaaMNgBaatttaRgaMaatatttBtttaaaHHKaatctgatWatYaacttMctctt
-ttVctagctDaaagtaVaKaKRtaacBgtatccaaccactHHaagaagaaggaNaaatBW
-attccgStaMSaMatBttgcatgRSacgttVVtaaDMtcSgVatWcaSatcttttVatag
-ttactttacgatcaccNtaDVgSRcgVcgtgaacgaNtaNatatagtHtMgtHcMtagaa
-attBgtataRaaaacaYKgtRccYtatgaagtaataKgtaaMttgaaRVatgcagaKStc
-tHNaaatctBBtcttaYaBWHgtVtgacagcaRcataWctcaBcYacYgatDgtDHccta
-aagacYRcaggattHaYgtKtaatgcVcaataMYacccatatcacgWDBtgaatcBaata
-cKcttRaRtgatgaBDacggtaattaaYtataStgVHDtDctgactcaaatKtacaatgc
-gYatBtRaDatHaactgtttatatDttttaaaKVccYcaaccNcBcgHaaVcattHctcg
-attaaatBtatgcaaaaatYMctSactHatacgaWacattacMBgHttcgaatVaaaaca
-BatatVtctgaaaaWtctRacgBMaatSgRgtgtcgactatcRtattaScctaStagKga
-DcWgtYtDDWKRgRtHatRtggtcgaHgggcgtattaMgtcagccaBggWVcWctVaaat
-tcgNaatcKWagcNaHtgaaaSaaagctcYctttRVtaaaatNtataaccKtaRgtttaM
-tgtKaBtRtNaggaSattHatatWactcagtgtactaKctatttgRYYatKatgtccgtR
-tttttatttaatatVgKtttgtatgtNtataRatWYNgtRtHggtaaKaYtKSDcatcKg
-taaYatcSRctaVtSMWtVtRWHatttagataDtVggacagVcgKWagBgatBtaaagNc
-aRtagcataBggactaacacRctKgttaatcctHgDgttKHHagttgttaatgHBtatHc
-DaagtVaBaRccctVgtgDtacRHSctaagagcggWYaBtSaKtHBtaaactYacgNKBa
-VYgtaacttagtVttcttaatgtBtatMtMtttaattaatBWccatRtttcatagVgMMt
-agctStKctaMactacDNYgKYHgaWcgaHgagattacVgtttgtRaSttaWaVgataat
-gtgtYtaStattattMtNgWtgttKaccaatagNYttattcgtatHcWtctaaaNVYKKt
-tWtggcDtcgaagtNcagatacgcattaagaccWctgcagcttggNSgaNcHggatgtVt
-catNtRaaBNcHVagagaaBtaaSggDaatWaatRccaVgggStctDaacataKttKatt
-tggacYtattcSatcttagcaatgaVBMcttDattctYaaRgatgcattttNgVHtKcYR
-aatRKctgtaaacRatVSagctgtWacBtKVatctgttttKcgtctaaDcaagtatcSat
-aWVgcKKataWaYttcccSaatgaaaacccWgcRctWatNcWtBRttYaattataaNgac
-acaatagtttVNtataNaYtaatRaVWKtBatKagtaatataDaNaaaaataMtaagaaS
-tccBcaatNgaataWtHaNactgtcDtRcYaaVaaaaaDgtttRatctatgHtgttKtga
-aNSgatactttcgagWaaatctKaaDaRttgtggKKagcDgataaattgSaacWaVtaNM
-acKtcaDaaatttctRaaVcagNacaScRBatatctRatcctaNatWgRtcDcSaWSgtt
-RtKaRtMtKaatgttBHcYaaBtgatSgaSWaScMgatNtctcctatttctYtatMatMt
-RRtSaattaMtagaaaaStcgVgRttSVaScagtgDtttatcatcatacRcatatDctta
-tcatVRtttataaHtattcYtcaaaatactttgVctagtaaYttagatagtSYacKaaac
-gaaKtaaatagataatSatatgaaatSgKtaatVtttatcctgKHaatHattagaaccgt
-YaaHactRcggSBNgtgctaaBagBttgtRttaaattYtVRaaaattgtaatVatttctc
-ttcatgBcVgtgKgaHaaatattYatagWacNctgaaMcgaattStagWaSgtaaKagtt
-ttaagaDgatKcctgtaHtcatggKttVDatcaaggtYcgccagNgtgcVttttagagat
-gctaccacggggtNttttaSHaNtatNcctcatSaaVgtactgBHtagcaYggYVKNgta
-KBcRttgaWatgaatVtagtcgattYgatgtaatttacDacSctgctaaaStttaWMagD
-aaatcaVYctccgggcgaVtaaWtStaKMgDtttcaaMtVgBaatccagNaaatcYRMBg
-gttWtaaScKttMWtYataRaDBMaDataatHBcacDaaKDactaMgagttDattaHatH
-taYatDtattDcRNStgaatattSDttggtattaaNSYacttcDMgYgBatWtaMagact
-VWttctttgYMaYaacRgHWaattgRtaagcattctMKVStatactacHVtatgatcBtV
-NataaBttYtSttacKgggWgYDtgaVtYgatDaacattYgatggtRDaVDttNactaSa
-MtgNttaacaaSaBStcDctaccacagacgcaHatMataWKYtaYattMcaMtgSttDag
-cHacgatcaHttYaKHggagttccgatYcaatgatRaVRcaagatcagtatggScctata
-ttaNtagcgacgtgKaaWaactSgagtMYtcttccaKtStaacggMtaagNttattatcg
-tctaRcactctctDtaacWYtgaYaSaagaWtNtatttRacatgNaatgttattgWDDcN
-aHcctgaaHacSgaataaRaataMHttatMtgaSDSKatatHHaNtacagtccaYatWtc
-actaactatKDacSaStcggataHgYatagKtaatKagStaNgtatactatggRHacttg
-tattatgtDVagDVaRctacMYattDgtttYgtctatggtKaRSttRccRtaaccttaga
-gRatagSaaMaacgcaNtatgaaatcaRaagataatagatactcHaaYKBctccaagaRa
-BaStNagataggcgaatgaMtagaatgtcaKttaaatgtaWcaBttaatRcggtgNcaca
-aKtttScRtWtgcatagtttWYaagBttDKgcctttatMggNttattBtctagVtacata
-aaYttacacaaRttcYtWttgHcaYYtaMgBaBatctNgcDtNttacgacDcgataaSat
-YaSttWtcctatKaatgcagHaVaacgctgcatDtgttaSataaaaYSNttatagtaNYt
-aDaaaNtggggacttaBggcHgcgtNtaaMcctggtVtaKcgNacNtatVaSWctWtgaW
-cggNaBagctctgaYataMgaagatBSttctatacttgtgtKtaattttRagtDtacata
-tatatgatNHVgBMtKtaKaNttDHaagatactHaccHtcatttaaagttVaMcNgHata
-tKtaNtgYMccttatcaaNagctggacStttcNtggcaVtattactHaSttatgNMVatt
-MMDtMactattattgWMSgtHBttStStgatatRaDaagattttctatMtaaaaaggtac
-taaVttaSacNaatactgMttgacHaHRttgMacaaaatagttaatatWKRgacDgaRta
-tatttattatcYttaWtgtBRtWatgHaaattHataagtVaDtWaVaWtgStcgtMSgaS
-RgMKtaaataVacataatgtaSaatttagtcgaaHtaKaatgcacatcggRaggSKctDc
-agtcSttcccStYtccRtctctYtcaaKcgagtaMttttcRaYDttgttatctaatcata
-NctctgctatcaMatactataggDaHaaSttMtaDtcNatataattctMcStaaBYtaNa
-gatgtaatHagagSttgWHVcttatKaYgDctcttggtgttMcRaVgSgggtagacaata
-aDtaattSaDaNaHaBctattgNtaccaaRgaVtKNtaaYggHtaKKgHcatctWtctDt
-ttctttggSDtNtaStagttataaacaattgcaBaBWggHgcaaaBtYgctaatgaaatW
-cDcttHtcMtWWattBHatcatcaaatctKMagtDNatttWaBtHaaaNgMttaaStagt
-tctctaatDtcRVaYttgttMtRtgtcaSaaYVgSWDRtaatagctcagDgcWWaaaBaa
-RaBctgVgggNgDWStNaNBKcBctaaKtttDcttBaaggBttgaccatgaaaNgttttt
-tttatctatgttataccaaDRaaSagtaVtDtcaWatBtacattaWacttaSgtattggD
-gKaaatScaattacgWcagKHaaccaYcRcaRttaDttRtttHgaHVggcttBaRgtccc
-tDatKaVtKtcRgYtaKttacgtatBtStaagcaattaagaRgBagSaattccSWYttta
-ttVaataNctgHgttaaNBgcVYgtRtcccagWNaaaacaDNaBcaaaaRVtcWMgBagM
-tttattacgDacttBtactatcattggaaatVccggttRttcatagttVYcatYaSHaHc
-ttaaagcNWaHataaaRWtctVtRYtagHtaaaYMataHYtNBctNtKaatattStgaMc
-BtRgctaKtgcScSttDgYatcVtggaaKtaagatWccHccgKYctaNNctacaWctttt
-gcRtgtVcgaKttcMRHgctaHtVaataaDtatgKDcttatBtDttggNtacttttMtga
-acRattaaNagaactcaaaBBVtcDtcgaStaDctgaaaSgttMaDtcgttcaccaaaag
-gWtcKcgSMtcDtatgtttStaaBtatagDcatYatWtaaaBacaKgcaDatgRggaaYc
-taRtccagattDaWtttggacBaVcHtHtaacDacYgtaatataMagaatgHMatcttat
-acgtatttttatattacHactgttataMgStYaattYaccaattgagtcaaattaYtgta
-tcatgMcaDcgggtcttDtKgcatgWRtataatatRacacNRBttcHtBgcRttgtgcgt
-catacMtttBctatctBaatcattMttMYgattaaVYatgDaatVagtattDacaacDMa
-tcMtHcccataagatgBggaccattVWtRtSacatgctcaaggggYtttDtaaNgNtaaB
-atggaatgtctRtaBgBtcNYatatNRtagaacMgagSaSDDSaDcctRagtVWSHtVSR
-ggaacaBVaccgtttaStagaacaMtactccagtttVctaaRaaHttNcttagcaattta
-ttaatRtaaaatctaacDaBttggSagagctacHtaaRWgattcaaBtctRtSHaNtgta
-cattVcaHaNaagtataccacaWtaRtaaVKgMYaWgttaKggKMtKcgWatcaDatYtK
-SttgtacgaccNctSaattcDcatcttcaaaDKttacHtggttHggRRaRcaWacaMtBW
-VHSHgaaMcKattgtaRWttScNattBBatYtaNRgcggaagacHSaattRtttcYgacc
-BRccMacccKgatgaacttcgDgHcaaaaaRtatatDtatYVtttttHgSHaSaatagct
-NYtaHYaVYttattNtttgaaaYtaKttWtctaNtgagaaaNctNDctaaHgttagDcRt
-tatagccBaacgcaRBtRctRtggtaMYYttWtgataatcgaataattattataVaaaaa
-ttacNRVYcaaMacNatRttcKatMctgaagactaattataaYgcKcaSYaatMNctcaa
-cgtgatttttBacNtgatDccaattattKWWcattttatatatgatBcDtaaaagttgaa
-VtaHtaHHtBtataRBgtgDtaataMttRtDgDcttattNtggtctatctaaBcatctaR
-atgNacWtaatgaagtcMNaacNgHttatactaWgcNtaStaRgttaaHacccgaYStac
-aaaatWggaYaWgaattattcMaactcBKaaaRVNcaNRDcYcgaBctKaacaaaaaSgc
-tccYBBHYaVagaatagaaaacagYtctVccaMtcgtttVatcaatttDRtgWctagtac
-RttMctgtDctttcKtWttttataaatgVttgBKtgtKWDaWagMtaaagaaattDVtag
-gttacatcatttatgtcgMHaVcttaBtVRtcgtaYgBRHatttHgaBcKaYWaatcNSc
-tagtaaaaatttacaatcactSWacgtaatgKttWattagttttNaggtctcaagtcact
-attcttctaagKggaataMgtttcataagataaaaatagattatDgcBVHWgaBKttDgc
-atRHaagcaYcRaattattatgtMatatattgHDtcaDtcaaaHctStattaatHaccga
-cNattgatatattttgtgtDtRatagSacaMtcRtcattcccgacacSattgttKaWatt
-NHcaacttccgtttSRtgtctgDcgctcaaMagVtBctBMcMcWtgtaacgactctcttR
-ggRKSttgYtYatDccagttDgaKccacgVatWcataVaaagaataMgtgataaKYaaat
-cHDaacgataYctRtcYatcgcaMgtNttaBttttgatttaRtStgcaacaaaataccVg
-aaDgtVgDcStctatatttattaaaaRKDatagaaagaKaaYYcaYSgKStctccSttac
-agtcNactttDVttagaaagMHttRaNcSaRaMgBttattggtttaRMggatggcKDgWR
-tNaataataWKKacttcKWaaagNaBttaBatMHtccattaacttccccYtcBcYRtaga
-ttaagctaaYBDttaNtgaaaccHcaRMtKtaaHMcNBttaNaNcVcgVttWNtDaBatg
-ataaVtcWKcttRggWatcattgaRagHgaattNtatttctctattaattaatgaDaaMa
-tacgttgggcHaYVaaNaDDttHtcaaHtcVVDgBVagcMacgtgttaaBRNtatRtcag
-taagaggtttaagacaVaaggttaWatctccgtVtaDtcDatttccVatgtacNtttccg
-tHttatKgScBatgtVgHtYcWagcaKtaMYaaHgtaattaSaHcgcagtWNaatNccNN
-YcacgVaagaRacttctcattcccRtgtgtaattagcSttaaStWaMtctNNcSMacatt
-ataaactaDgtatWgtagtttaagaaaattgtagtNagtcaataaatttgatMMYactaa
-tatcggBWDtVcYttcDHtVttatacYaRgaMaacaStaatcRttttVtagaDtcacWat
-ttWtgaaaagaaagNRacDtttStVatBaDNtaactatatcBSMcccaSttccggaMatg
-attaaWatKMaBaBatttgataNctgttKtVaagtcagScgaaaDggaWgtgttttKtWt
-atttHaatgtagttcactaaKMagttSYBtKtaYgaactcagagRtatagtVtatcaaaW
-YagcgNtaDagtacNSaaYDgatBgtcgataacYDtaaactacagWDcYKaagtttatta
-gcatcgagttKcatDaattgattatDtcagRtWSKtcgNtMaaaaacaMttKcaWcaaSV
-MaaaccagMVtaMaDtMaHaBgaacataBBVtaatVYaNSWcSgNtDNaaKacacBttta
-tKtgtttcaaHaMctcagtaacgtcgYtactDcgcctaNgagagcYgatattttaaattt
-ccattttacatttDaaRctattttWctttacgtDatYtttcagacgcaaVttagtaaKaa
-aRtgVtccataBggacttatttgtttaWNtgttVWtaWNVDaattgtatttBaagcBtaa
-BttaaVatcHcaVgacattccNggtcgacKttaaaRtagRtctWagaYggtgMtataatM
-tgaaRttattttgWcttNtDRRgMDKacagaaaaggaaaRStcccagtYccVattaNaaK
-StNWtgacaVtagaagcttSaaDtcacaacgDYacWDYtgtttKatcVtgcMaDaSKStV
-cgtagaaWaKaagtttcHaHgMgMtctataagBtKaaaKKcactggagRRttaagaBaaN
-atVVcgRcKSttDaactagtSttSattgttgaaRYatggttVttaataaHttccaagDtg
-atNWtaagHtgcYtaactRgcaatgMgtgtRaatRaNaacHKtagactactggaatttcg
-ccataacgMctRgatgttaccctaHgtgWaYcactcacYaattcttaBtgacttaaacct
-gYgaWatgBttcttVttcgttWttMcNYgtaaaatctYgMgaaattacNgaHgaacDVVM
-tttggtHtctaaRgtacagacgHtVtaBMNBgattagcttaRcttacaHcRctgttcaaD
-BggttKaacatgKtttYataVaNattccgMcgcgtagtRaVVaattaKaatggttRgaMc
-agtatcWBttNtHagctaatctagaaNaaacaYBctatcgcVctBtgcaaagDgttVtga
-HtactSNYtaaNccatgtgDacgaVtDcgKaRtacDcttgctaagggcagMDagggtBWR
-tttSgccttttttaacgtcHctaVtVDtagatcaNMaVtcVacatHctDWNaataRgcgt
-aVHaggtaaaaSgtttMtattDgBtctgatSgtRagagYtctSaKWaataMgattRKtaa
-catttYcgtaacacattRWtBtcggtaaatMtaaacBatttctKagtcDtttgcBtKYYB
-aKttctVttgttaDtgattttcttccacttgSaaacggaaaNDaattcYNNaWcgaaYat
-tttMgcBtcatRtgtaaagatgaWtgaccaYBHgaatagataVVtHtttVgYBtMctaMt
-cctgaDcYttgtccaaaRNtacagcMctKaaaggatttacatgtttaaWSaYaKttBtag
-DacactagctMtttNaKtctttcNcSattNacttggaacaatDagtattRtgSHaataat
-gccVgacccgatactatccctgtRctttgagaSgatcatatcgDcagWaaHSgctYYWta
-tHttggttctttatVattatcgactaagtgtagcatVgtgHMtttgtttcgttaKattcM
-atttgtttWcaaStNatgtHcaaaDtaagBaKBtRgaBgDtSagtatMtaacYaatYtVc
-KatgtgcaacVaaaatactKcRgtaYtgtNgBBNcKtcttaccttKgaRaYcaNKtactt
-tgagSBtgtRagaNgcaaaNcacagtVtttHWatgttaNatBgtttaatNgVtctgaata
-tcaRtattcttttttttRaaKcRStctcggDgKagattaMaaaKtcaHacttaataataK
-taRgDtKVBttttcgtKaggHHcatgttagHggttNctcgtatKKagVagRaaaggaaBt
-NatttVKcRttaHctaHtcaaatgtaggHccaBataNaNaggttgcWaatctgatYcaaa
-HaatWtaVgaaBttagtaagaKKtaaaKtRHatMaDBtBctagcatWtatttgWttVaaa
-ScMNattRactttgtYtttaaaagtaagtMtaMaSttMBtatgaBtttaKtgaatgagYg
-tNNacMtcNRacMMHcttWtgtRtctttaacaacattattcYaMagBaacYttMatcttK
-cRMtgMNccattaRttNatHaHNaSaaHMacacaVaatacaKaSttHatattMtVatWga
-ttttttaYctttKttHgScWaacgHtttcaVaaMgaacagNatcgttaacaaaaagtaca
-HBNaattgttKtcttVttaaBtctgctacgBgcWtttcaggacacatMgacatcccagcg
-gMgaVKaBattgacttaatgacacacaaaaaatRKaaBctacgtRaDcgtagcVBaacDS
-BHaaaaSacatatacagacRNatcttNaaVtaaaataHattagtaaaaSWccgtatWatg
-gDttaactattgcccatcttHaSgYataBttBaactattBtcHtgatcaataSttaBtat
-KSHYttWggtcYtttBttaataccRgVatStaHaKagaatNtagRMNgtcttYaaSaact
-cagDSgagaaYtMttDtMRVgWKWtgMaKtKaDttttgactatacataatcNtatNaHat
-tVagacgYgatatatttttgtStWaaatctWaMgagaRttRatacgStgattcttaagaD
-taWccaaatRcagcagaaNKagtaaDggcgccBtYtagSBMtactaaataMataBSacRM
-gDgattMMgtcHtcaYDtRaDaacggttDaggcMtttatgttaNctaattaVacgaaMMt
-aatDccSgtattgaRtWWaccaccgagtactMcgVNgctDctaMScatagcgtcaactat
-acRacgHRttgctatttaatgaattataYKttgtaagWgtYttgcHgMtaMattWaWVta
-RgcttgYgttBHtYataSccStBtgtagMgtDtggcVaaSBaatagDttgBgtctttctc
-attttaNagtHKtaMWcYactVcgcgtatMVtttRacVagDaatcttgctBBcRDgcaac
-KttgatSKtYtagBMagaRtcgBattHcBWcaactgatttaatttWDccatttatcgagS
-KaWttataHactaHMttaatHtggaHtHagaatgtKtaaRactgtttMatacgatcaagD
-gatKaDctataMggtHDtggHacctttRtatcttYattttgacttgaaSaataaatYcgB
-aaaaccgNatVBttMacHaKaataagtatKgtcaagactcttaHttcggaattgttDtct
-aaccHttttWaaatgaaatataaaWattccYDtKtaaaacggtgaggWVtctattagtga
-ctattaagtMgtttaagcatttgSgaaatatccHaaggMaaaattttcWtatKctagDtY
-tMcctagagHcactttactatacaaacattaacttaHatcVMYattYgVgtMttaaRtga
-aataaDatcaHgtHHatKcDYaatcttMtNcgatYatgSaMaNtcttKcWataScKggta
-tcttacgcttWaaagNatgMgHtctttNtaacVtgttcMaaRatccggggactcMtttaY
-MtcWRgNctgNccKatcttgYDcMgattNYaRagatHaaHgKctcataRDttacatBatc
-cattgDWttatttaWgtcggagaaaaatacaatacSNtgggtttccttacSMaagBatta
-caMaNcactMttatgaRBacYcYtcaaaWtagctSaacttWgDMHgaggatgBVgcHaDt
-ggaactttggtcNatNgtaKaBcccaNtaagttBaacagtatacDYttcctNgWgcgSMc
-acatStctHatgRcNcgtacacaatRttMggaNKKggataaaSaYcMVcMgtaMaHtgat
-tYMatYcggtcttcctHtcDccgtgRatcattgcgccgatatMaaYaataaYSggatagc
-gcBtNtaaaScaKgttBgagVagttaKagagtatVaactaSacWactSaKatWccaKaaa
-atBKgaaKtDMattttgtaaatcRctMatcaaMagMttDgVatggMaaWgttcgaWatga
-aatttgRtYtattaWHKcRgctacatKttctaccaaHttRatctaYattaaWatVNccat
-NgagtcKttKataStRaatatattcctRWatDctVagttYDgSBaatYgttttgtVaatt
-taatagcagMatRaacttBctattgtMagagattaaactaMatVtHtaaatctRgaaaaa
-aaatttWacaacaYccYDSaattMatgaccKtaBKWBattgtcaagcHKaagttMMtaat
-ttcKcMagNaaKagattggMagaggtaatttYacatcWaaDgatMgKHacMacgcVaaca
-DtaDatatYggttBcgtatgWgaSatttgtagaHYRVacaRtctHaaRtatgaactaata
-tctSSBgggaaHMWtcaagatKgagtDaSatagttgattVRatNtctMtcSaagaSHaat
-aNataataRaaRgattctttaataaagWaRHcYgcatgtWRcttgaaggaMcaataBRaa
-ccagStaaacNtttcaatataYtaatatgHaDgcStcWttaacctaRgtYaRtataKtgM
-ttttatgactaaaatttacYatcccRWtttHRtattaaatgtttatatttgttYaatMca
-RcSVaaDatcgtaYMcatgtagacatgaaattgRtcaaYaaYtRBatKacttataccaNa
-aattVaBtctggacaagKaaYaaatatWtMtatcYaaVNtcgHaactBaagKcHgtctac
-aatWtaDtSgtaHcataHtactgataNctRgttMtDcDttatHtcgtacatcccaggStt
-aBgtcacacWtccNMcNatMVaVgtccDYStatMaccDatggYaRKaaagataRatttHK
-tSaaatDgataaacttaHgttgVBtcttVttHgDacgaKatgtatatNYataactctSat
-atatattgcHRRYttStggaactHgttttYtttaWtatMcttttctatctDtagVHYgMR
-BgtHttcctaatYRttKtaagatggaVRataKDctaMtKBNtMtHNtWtttYcVtattMc
-gRaacMcctNSctcatttaaagDcaHtYccSgatgcaatYaaaaDcttcgtaWtaattct
-cgttttScttggtaatctttYgtctaactKataHacctMctcttacHtKataacacagcN
-RatgKatttttSaaatRYcgDttaMRcgaaattactMtgcgtaagcgttatBtttttaat
-taagtNacatHgttcRgacKcBBtVgatKttcgaBaatactDRgtRtgaNacWtcacYtt
-aaKcgttctHaKttaNaMgWgWaggtctRgaKgWttSttBtDcNtgtttacaaatYcDRt
-gVtgcctattcNtctaaaDMNttttNtggctgagaVctDaacVtWccaagtaacacaNct
-gaScattccDHcVBatcgatgtMtaatBgHaatDctMYgagaatgYWKcctaatNaStHa
-aaKccgHgcgtYaaYtattgtStgtgcaaRtattaKatattagaWVtcaMtBagttatta
-gNaWHcVgcaattttDcMtgtaRHVYtHtctgtaaaaHVtMKacatcgNaatttMatatg
-ttgttactagWYtaRacgataKagYNKcattataNaRtgaacKaYgcaaYYacaNccHat
-MatDcNgtHttRaWttagaaDcaaaaaatagggtKDtStaDaRtaVtHWKNtgtattVct
-SVgRgataDaRaWataBgaagaaKtaataaYgDcaStaNgtaDaaggtattHaRaWMYaY
-aWtggttHYgagVtgtgcttttcaaDKcagVcgttagacNaaWtagtaataDttctggtt
-VcatcataaagtgKaaaNaMtaBBaattaatWaattgctHaVKaSgDaaVKaHtatatat
-HatcatSBagNgHtatcHYMHgttDgtaHtBttWatcgtttaRaattgStKgSKNWKatc
-agDtctcagatttctRtYtBatBgHHtKaWtgYBgacVVWaKtacKcDttKMaKaVcggt
-gttataagaataaHaatattagtataatMHgttYgaRttagtaRtcaaVatacggtcMcg
-agtaaRttacWgactKRYataaaagSattYaWgagatYagKagatgSaagKgttaatMgg
-tataatgttWYttatgagaaacctNVataatHcccKtDctcctaatactggctHggaSag
-gRtKHaWaattcgSatMatttagaggcYtctaMcgctcataSatatgRagacNaaDagga
-VBagaYttKtacNaKgtSYtagttggaWcatcWttaatctatgaVtcgtgtMtatcaYcg
-tRccaaYgDctgcMgtgtWgacWtgataacacgcgctBtgttaKtYDtatDcatcagKaV
-MctaatcttgVcaaRgcRMtDcgattaHttcaNatgaatMtactacVgtRgatggaWttt
-actaaKatgagSaaKggtaNtactVaYtaaKRagaacccacaMtaaMtKtatBcttgtaa
-WBtMctaataaVcDaaYtcRHBtcgttNtaaHatttBNgRStVDattBatVtaagttaYa
-tVattaagaBcacggtSgtVtatttaRattgatgtaHDKgcaatattKtggcctatgaWD
-KRYcggattgRctatNgatacaatMNttctgtcRBYRaaaHctNYattcHtaWcaattct
-BtMKtVgYataatMgYtcagcttMDataVtggRtKtgaatgccNcRttcaMtRgattaac
-attRcagcctHtWMtgtDRagaKaBtgDttYaaaaKatKgatctVaaYaacWcgcatagB
-VtaNtRtYRaggBaaBtgKgttacataagagcatgtRattccacttaccatRaaatgWgD
-aMHaYVgVtaSctatcgKaatatattaDgacccYagtgtaYNaaatKcagtBRgagtcca
-tgKgaaaccBgaagBtgSttWtacgatWHaYatcgatttRaaNRgcaNaKVacaNtDgat
-tgHVaatcDaagcgtatgcNttaDataatcSataaKcaataaHWataBtttatBtcaKtK
-tatagttaDgSaYctacaRatNtaWctSaatatttYaKaKtaccWtatcRagacttaYtt
-VcKgSDcgagaagatccHtaattctSttatggtKYgtMaHagVaBRatttctgtRgtcta
-tgggtaHKgtHacHtSYacgtacacHatacKaaBaVaccaDtatcSaataaHaagagaat
-ScagactataaRttagcaaVcaHataKgDacatWccccaagcaBgagWatctaYttgaaa
-tctVNcYtttWagHcgcgcDcVaaatgttKcHtNtcaatagtgtNRaactttttcaatgg
-WgBcgDtgVgtttctacMtaaataaaRggaaacWaHttaRtNtgctaaRRtVBctYtVta
-tDcattDtgaccYatagatYRKatNYKttNgcctagtaWtgaactaMVaacctgaStttc
-tgaKVtaaVaRKDttVtVctaDNtataaaDtccccaagtWtcgatcactDgYaBcatcct
-MtVtacDaaBtYtMaKNatNtcaNacgDatYcatcgcaRatWBgaacWttKttagYtaat
-tcggttgSWttttDWctttacYtatatWtcatDtMgtBttgRtVDggttaacYtacgtac
-atgaattgaaWcttMStaDgtatattgaDtcRBcattSgaaVBRgagccaaKtttcDgcg
-aSMtatgWattaKttWtgDBMaggBBttBaatWttRtgcNtHcgttttHtKtcWtagHSt
-aacagttgatatBtaWSaWggtaataaMttaKacDaatactcBttcaatatHttcBaaSa
-aatYggtaRtatNtHcaatcaHtagVtgtattataNggaMtcttHtNagctaaaggtaga
-YctMattNaMVNtcKtactBKcaHHcBttaSagaKacataYgctaKaYgttYcgacWVtt
-WtSagcaacatcccHaccKtcttaacgaKttcacKtNtacHtatatRtaaatacactaBt
-ttgaHaRttggttWtatYagcatYDatcggagagcWBataagRtacctataRKgtBgatg
-aDatataSttagBaHtaatNtaDWcWtgtaattacagKttcNtMagtattaNgtctcgtc
-ctcttBaHaKcKccgtRcaaYagSattaagtKataDatatatagtcDtaacaWHcaKttD
-gaaRcgtgYttgtcatatNtatttttatggccHtgDtYHtWgttatYaacaattcaWtat
-NgctcaaaSttRgctaatcaaatNatcgtttaBtNNVtgttataagcaaagattBacgtD
-atttNatttaaaDcBgtaSKgacgtagataatttcHMVNttgttBtDtgtaWKaaRMcKM
-tHtaVtagataWctccNNaSWtVaHatctcMgggDgtNHtDaDttatatVWttgttattt
-aacctttcacaaggaSaDcggttttttatatVtctgVtaacaStDVaKactaMtttaSNa
-gtgaaattaNacttSKctattcctctaSagKcaVttaagNaVcttaVaaRNaHaaHttat
-gtHttgtgatMccaggtaDcgaccgtWgtWMtttaHcRtattgScctatttKtaaccaag
-tYagaHgtWcHaatgccKNRtttagtMYSgaDatctgtgaWDtccMNcgHgcaaacNDaa
-aRaStDWtcaaaaHKtaNBctagBtgtattaactaattttVctagaatggcWSatMaccc
-ttHttaSgSgtgMRcatRVKtatctgaaaccDNatYgaaVHNgatMgHRtacttaaaRta
-tStRtDtatDttYatattHggaBcttHgcgattgaKcKtttcRataMtcgaVttWacatN
-catacctRataDDatVaWNcggttgaHtgtMacVtttaBHtgagVttMaataattatgtt
-cttagtttgtgcDtSatttgBtcaacHattaaBagVWcgcaSYttMgcttacYKtVtatc
-aYaKctgBatgcgggcYcaaaaacgNtctagKBtattatctttKtaVttatagtaYtRag
-NtaYataaVtgaatatcHgcaaRataHtacacatgtaNtgtcgYatWMatttgaactacR
-ctaWtWtatacaatctBatatgYtaagtatgtgtatSttactVatcttYtaBcKgRaSgg
-RaaaaatgcagtaaaWgtaRgcgataatcBaataccgtatttttccatcNHtatWYgatH
-SaaaDHttgctgtccHtggggcctaataatttttctatattYWtcattBtgBRcVttaVM
-RSgctaatMagtYtttaaaaatBRtcBttcaaVtaacagctccSaaSttKNtHtKYcagc
-agaaaccccRtttttaaDcDtaStatccaagcgctHtatcttaDRYgatDHtWcaaaBcW
-gKWHttHataagHacgMNKttMKHccaYcatMVaacgttaKgYcaVaaBtacgcaacttt
-MctaaHaatgtBatgagaSatgtatgSRgHgWaVWgataaatatttccKagVgataattW
-aHNcYggaaatgctHtKtaDtctaaagtMaatVDVactWtSaaWaaMtaHtaSKtcBRaN
-cttStggtBttacNagcatagRgtKtgcgaacaacBcgKaatgataagatgaaaattgta
-ctgcgggtccHHWHaaNacaBttNKtKtcaaBatatgctaHNgtKcDWgtttatNgVDHg
-accaacWctKaaggHttgaRgYaatHcaBacaatgagcaaattactgtaVaaYaDtagat
-tgagNKggtggtgKtWKaatacagDRtatRaMRtgattDggtcaaYRtatttNtagaDtc
-acaaSDctDtataatcgtactaHttatacaatYaacaaHttHatHtgcgatRRttNgcat
-SVtacWWgaaggagtatVMaVaaattScDDKNcaYBYaDatHgtctatBagcaacaagaa
-tgagaaRcataaKNaRtBDatcaaacgcattttttaaBtcSgtacaRggatgtMNaattg
-gatatWtgagtattaaaVctgcaYMtatgatttttYgaHtgtcttaagWBttHttgtctt
-attDtcgtatWtataataSgctaHagcDVcNtaatcaagtaBDaWaDgtttagYctaNcc
-DtaKtaHcttaataacccaRKtacaVaatNgcWRaMgaattatgaBaaagattVYaHMDc
-aDHtcRcgYtcttaaaWaaaVKgatacRtttRRKYgaatacaWVacVcRtatMacaBtac
-tggMataaattttHggNagSctacHgtBagcgtcgtgattNtttgatSaaggMttctttc
-ttNtYNagBtaaacaaatttMgaccttacataattgYtcgacBtVMctgStgMDtagtaR
-ctHtatgttcatatVRNWataDKatWcgaaaaagttaaaagcacgHNacgtaatctttMR
-tgacttttDacctataaacgaaatatgattagaactccSYtaBctttaataacWgaaaYa
-tagatgWttcatKtNgatttttcaagHtaYgaaRaDaagtaggagcttatVtagtctttc
-attaaaatcgKtattaRttacagVaDatgcatVgattgggtctttHVtagKaaRBtaHta
-aggccccaaaaKatggtttaMWgtBtaaacttcactttKHtcgatctccctaYaBacMgt
-cttBaBaNgcgaaacaatctagtHccHtKttcRtRVttccVctttcatacYagMVtMcag
-aMaaacaataBctgYtaatRaaagattaaccatVRatHtaRagcgcaBcgDttStttttc
-VtttaDtKgcaaWaaaaatSccMcVatgtKgtaKgcgatatgtagtSaaaDttatacaaa
-catYaRRcVRHctKtcgacKttaaVctaDaatgttMggRcWaacttttHaDaKaDaBctg
-taggcgtttaHBccatccattcNHtDaYtaataMttacggctNVaacDattgatatttta
-cVttSaattacaaRtataNDgacVtgaacataVRttttaDtcaaacataYDBtttaatBa
-DtttYDaDaMccMttNBttatatgagaaMgaNtattHccNataattcaHagtgaaggDga
-tgtatatatgYatgaStcataaBStWacgtcccataRMaaDattggttaaattcMKtctM
-acaBSactcggaatDDgatDgcWctaacaccgggaVcacWKVacggtaNatatacctMta
-tgatagtgcaKagggVaDtgtaacttggagtcKatatcgMcttRaMagcattaBRaStct
-YSggaHYtacaactMBaagDcaBDRaaacMYacaHaattagcattaaaHgcgctaaggSc
-cKtgaaKtNaBtatDDcKBSaVtgatVYaagVtctSgMctacgttaacWaaattctSgtD
-actaaStaaattgcagBBRVctaatatacctNttMcRggctttMttagacRaHcaBaacV
-KgaataHttttMgYgattcYaNRgttMgcVaaacaVVcDHaatttgKtMYgtatBtVVct
-WgVtatHtacaaHttcacgatagcagtaaNattBatatatttcVgaDagcggttMaagtc
-ScHagaaatgcYNggcgtttttMtStggtRatctacttaaatVVtBacttHNttttaRca
-aatcacagHgagagtMgatcSWaNRacagDtatactaaDKaSRtgattctccatSaaRtt
-aaYctacacNtaRtaactggatgaccYtacactttaattaattgattYgttcagDtNKtt
-agDttaaaaaaaBtttaaNaYWKMBaaaacVcBMtatWtgBatatgaacVtattMtYatM
-NYDKNcKgDttDaVtaaaatgggatttctgtaaatWtctcWgtVVagtcgRgacttcccc
-taDcacagcRcagagtgtWSatgtacatgttaaSttgtaaHcgatgggMagtgaacttat
-RtttaVcaccaWaMgtactaatSSaHtcMgaaYtatcgaaggYgggcgtgaNDtgttMNg
-aNDMtaattcgVttttaacatgVatgtWVMatatcaKgaaattcaBcctccWcttgaaWH
-tWgHtcgNWgaRgctcBgSgaattgcaaHtgattgtgNagtDttHHgBttaaWcaaWagc
-aSaHHtaaaVctRaaMagtaDaatHtDMtcVaWMtagSagcttHSattaacaaagtRacM
-tRtctgttagcMtcaBatVKtKtKacgagaSNatSactgtatatcBctgagVtYactgta
-aattaaaggcYgDHgtaacatSRDatMMccHatKgttaacgactKtgKagtcttcaaHRV
-tccttKgtSataatttacaactggatDNgaacttcaRtVaagDcaWatcBctctHYatHa
-DaaatttagYatSatccaWtttagaaatVaacBatHcatcgtacaatatcgcNYRcaata
-YaRaYtgattVttgaatgaVaactcRcaNStgtgtattMtgaggtNttBaDRcgaaaagc
-tNgBcWaWgtSaDcVtgVaatMKBtttcgtttctaaHctaaagYactgMtatBDtcStga
-ccgtSDattYaataHctgggaYYttcggttaWaatctggtRagWMaDagtaacBccacta
-cgHWMKaatgatWatcctgHcaBaSctVtcMtgtDttacctaVgatYcWaDRaaaaRtag
-atcgaMagtggaRaWctctgMgcWttaagKBRtaaDaaWtctgtaagYMttactaHtaat
-cttcataacggcacBtSgcgttNHtgtHccatgttttaaagtatcgaKtMttVcataYBB
-aKtaMVaVgtattNDSataHcagtWMtaggtaSaaKgttgBtVtttgttatcatKcgHac
-acRtctHatNVagSBgatgHtgaRaSgttRcctaacaaattDNttgacctaaYtBgaaaa
-tagttattactcttttgatgtNNtVtgtatMgtcttRttcatttgatgacacttcHSaaa
-ccaWWDtWagtaRDDVNacVaRatgttBccttaatHtgtaaacStcVNtcacaSRttcYa
-gacagaMMttttgMcNttBcgWBtactgVtaRttctccaaYHBtaaagaBattaYacgat
-ttacatctgtaaMKaRYtttttactaaVatWgctBtttDVttctggcDaHaggDaagtcg
-aWcaagtagtWttHtgKtVataStccaMcWcaagataagatcactctHatgtcYgaKcat
-cagatactaagNSStHcctRRNtattgtccttagttagMVgtatagactaactctVcaat
-MctgtttgtgttgccttatWgtaBVtttctggMcaaKgDWtcgtaaYStgSactatttHg
-atctgKagtagBtVacRaagRtMctatgggcaaaKaaaatacttcHctaRtgtDcttDat
-taggaaatttcYHaRaaBttaatggcacKtgctHVcaDcaaaVDaaaVcgMttgtNagcg
-taDWgtcgttaatDgKgagcSatatcSHtagtagttggtgtHaWtaHKtatagctgtVga
-ttaBVaatgaataagtaatVatSttaHctttKtttgtagttaccttaatcgtagtcctgB
-cgactatttVcMacHaaaggaatgDatggKtaHtgStatattaaSagctWcctccRtata
-BaDYcgttgcNaagaggatRaaaYtaWgNtSMcaatttactaacatttaaWttHtatBat
-tgtcgacaatNgattgcNgtMaaaKaBDattHacttggtRtttaYaacgVactBtaBaKt
-gBttatgVttgtVttcaatcWcNctDBaaBgaDHacBttattNtgtDtatttVSaaacag
-gatgcRatSgtaSaNtgBatagttcHBgcBBaaattaHgtDattatDaKaatBaaYaaMa
-ataaataKtttYtagtBgMatNcatgtttgaNagtgttgtgKaNaSagtttgaSMaYBca
-aaacDStagttVacaaaaactaaWttBaagtctgtgcgtMgtaattctcctacctcaNtt
-taaccaaaaVtBcacataacaccccBcWMtatVtggaatgaWtcaaWaaaaaaaaWtDta
-atatRcctDWtcctaccMtVVatKttaWaaKaaatataaagScHBagaggBaSMtaWaVt
-atattactSaaaKNaactatNatccttgaYctattcaaaVgatttYHcRagattttaSat
-aggttattcVtaaagaKgtattattKtRttNcggcRgtgtgtWYtaacHgKatKgatYta
-cYagDtWcHBDctctgRaYKaYagcactKcacSaRtBttttBHKcMtNtcBatttatttt
-tgSatVgaaagaWtcDtagDatatgMacaacRgatatatgtttgtKtNRaatatNatgYc
-aHtgHataacKtgagtagtaacYttaNccaaatHcacaacaVDtagtaYtccagcattNt
-acKtBtactaaagaBatVtKaaHBctgStgtBgtatgaSNtgDataaccctgtagcaBgt
-gatcttaDataStgaMaccaSBBgWagtacKcgattgaDgNNaaaacacagtSatBacKD
-gcgtataBKcatacactaSaatYtYcDaactHttcatRtttaatcaattataRtttgtaa
-gMcgNttcatcBtYBagtNWNMtSHcattcRctttttRWgaKacKttgggagBcgttcgc
-MaWHtaatactgtctctatttataVgtttaBScttttaBMaNaatMacactYtBMggtHa
-cMagtaRtctgcatttaHtcaaaatttgagKtgNtactBacaHtcgtatttctMaSRagc
-agttaatgtNtaaattgagagWcKtaNttagVtacgatttgaatttcgRtgtWcVatcgt
-taaDVctgtttBWgaccagaaagtcSgtVtatagaBccttttcctaaattgHtatcggRa
-ttttcaaggcYSKaagWaWtRactaaaacccBatMtttBaatYtaagaactSttcgaaSc
-aatagtattgaccaagtgttttctaacatgtttNVaatcaaagagaaaNattaaRtttta
-VaaaccgcaggNMtatattVctcaagaggaacgBgtttaacaagttcKcYaatatactaa
-ccBaaaSggttcNtattctagttRtBacgScVctcaatttaatYtaaaaaaatgSaatga
-tagaMBRatgRcMcgttgaWHtcaVYgaatYtaatctttYttatRaWtctgBtDcgatNa
-tcKaBaDgatgtaNatWKctccgatattaacattNaaacDatgBgttctgtDtaaaMggt
-gaBaSHataacgccSctaBtttaRBtcNHcDatcDcctagagtcRtaBgWttDRVHagat
-tYatgtatcWtaHtttYcattWtaaagtctNgtStggRNcgcggagSSaaagaaaatYcH
-DtcgctttaatgYcKBVSgtattRaYBaDaaatBgtatgaHtaaRaRgcaSWNtagatHa
-acttNctBtcaccatctMcatattccaSatttgcgaDagDgtatYtaaaVDtaagtttWV
-aagtagYatRttaagDcNgacKBcScagHtattatcDaDactaaaaaYgHttBcgaDttg
-gataaaKSRcBMaBcgaBSttcWtgNBatRaccgattcatttataacggHVtaattcaca
-agagVttaaRaatVVRKcgWtVgacctgDgYaaHaWtctttcacMagggatVgactagMa
-aataKaaNWagKatagNaaWtaaaatttgaattttatttgctaaVgaHatBatcaaBWcB
-gttcMatcgBaaNgttcgSNaggSaRtttgHtRtattaNttcDcatSaVttttcgaaaaa
-ttgHatctaRaggSaNatMDaaatDcacgattttagaHgHaWtYgattaatHNSttatMS
-gggNtcKtYatRggtttgtMWVtttaYtagcagBagHaYagttatatggtBacYcattaR
-SataBatMtttaaatctHcaaaSaaaagttNSaaWcWRccRtKaagtBWtcaaattSttM
-tattggaaaccttaacgttBtWatttatatWcDaatagattcctScacctaagggRaaYt
-aNaatgVtBcttaaBaacaMVaaattatStYgRcctgtactatcMcVKatttcgSgatRH
-MaaaHtagtaaHtVgcaaataatatcgKKtgccaatBNgaaWcVttgagttaKatagttc
-aggKDatDtattgaKaVcaKtaataDataataHSaHcattagttaatRVYcNaHtaRcaa
-ggtNHcgtcaaccaBaaagYtHWaaaRcKgaYaaDttgcWYtataRgaatatgtYtgcKt
-aNttWacatYHctRaDtYtattcBttttatcSataYaYgttWaRagcacHMgtttHtYtt
-YaatcggtatStttcgtRSattaaDaKMaatatactaNBaWgctacacYtgaYVgtgHta
-aaRaaRgHtagtWattataaaSDaaWtgMattatcgaaaagtaYRSaWtSgNtBgagcRY
-aMDtactaacttaWgtatctagacaagNtattHggataatYttYatcataDcgHgttBtt
-ctttVttgccgaaWtaaaacgKgtatctaaaaaNtccDtaDatBMaMggaatNKtatBaa
-atVtccRaHtaSacataHattgtttKVYattcataVaattWtcgtgMttcttKtgtctaa
-cVtatctatatBRataactcgKatStatattcatHHRttKtccaacgtgggtgRgtgaMt
-attattggctatcgtgacMtRcBDtcttgtactaatRHttttaagatcgVMDStattatY
-BtttDttgtBtNttgRcMtYtgBacHaWaBaatDKctaagtgaaactaatgRaaKgatcc
-aagNaaaatattaggWNtaagtatacttttKcgtcggSYtcttgRctataYcttatataa
-agtatattaatttataVaacacaDHatctatttttKYVatHRactttaBHccaWagtact
-BtcacgaVgcgttRtttttttSVgtSagtBaaattctgaHgactcttgMcattttagVta
-agaattHctHtcaDaaNtaacRggWatagttcgtSttgaDatcNgNagctagDgatcNtt
-KgttgtaDtctttRaaYStRatDtgMggactSttaDtagSaVtBDttgtDgccatcacaM
-attaaaMtNacaVcgSWcVaaDatcaHaatgaattaMtatccVtctBtaattgtWattat
-BRcWcaatgNNtactWYtDaKttaaatcactcagtRaaRgatggtKgcgccaaHgaggat
-StattYcaNMtcaBttacttatgagDaNtaMgaaWtgtttcttctaHtMNgttatctaWW
-atMtBtaaatagDVatgtBYtatcggcttaagacMRtaHScgatatYgRDtcattatSDa
-HggaaataNgaWSRRaaaBaatagBattaDctttgHWNttacaataaaaaaatacggttt
-gHgVtaHtWMttNtBtctagtMcgKMgHgYtataHaNagWtcaacYattaataYRgtaWK
-gaBctataaccgatttaHaNBRaRaMtccggtNgacMtctcatttgcaattcWgMactta
-caaDaaNtactWatVtttagccttMaatcagVaagtctVaaDaBtattaattaYtNaYtg
-gattaKtaKctYaMtattYgatattataatKtVgDcttatatNBtcgttgtStttttMag
-aggttaHYSttcKgtcKtDNtataagttataagSgttatDtRttattgttttSNggRtca
-aKMNatgaatattgtBWtaMacctgggYgaSgaagYataagattacgagaatBtggtRcV
-HtgYggaDgaYaKagWagctatagacgaaHgtWaNgacttHRatVaWacKYtgRVNgVcS
-gRWctacatcKSactctgWYtBggtataagcttNRttVtgRcaWaaatDMatYattaact
-ttcgaagRatSctgccttgcRKaccHtttSNVagtagHagBagttagaccaRtataBcca
-taatSHatRtcHagacBWatagcaMtacaRtgtgaaBatctKRtScttccaNaatcNgta
-atatWtcaMgactctBtWtaaNactHaaaaRctcgcatggctMcaaNtcagaaaaacaca
-gtggggWttRttagtaagaVctVMtcgaatcttcMaaaHcaHBttcgattatgtcaDagc
-YRtBtYcgacMgtDcagcgaNgttaataatagcagKYYtcgtaBtYctMaRtaRtDagaa
-aacacatgYaBttgattattcgaaNttBctSataaMataWRgaHtttccgtDgaYtatgg
-tDgHKgMtatttVtMtVagttaRatMattRagataaccctKctMtSttgaHagtcStcta
-tttccSagatgttccacgaggYNttHRacgattcDatatDcataaaatBBttatcgaHtN
-HaaatatDNaggctgaNcaaggagttBttMgRagVatBcRtaWgatgBtSgaKtcgHttt
-gaatcaaDaHttcSBgHcagtVaaSttDcagccgttNBtgttHagYtattctttRWaaVt
-SttcatatKaaRaaaNacaVtVctMtSDtDtRHRcgtaatgctcttaaatSacacaatcg
-HattcaWcttaaaatHaaatcNctWttaNMcMtaKctVtcctaagYgatgatcYaaaRac
-tctaRDaYagtaacgtDgaggaaatctcaaacatcaScttcKttNtaccatNtaNataca
-tttHaaDHgcaDatMWaaBttcRggctMaagctVYcacgatcaDttatYtaatcKatWat
-caatVYtNagatttgattgaYttttYgacttVtcKaRagaaaHVgDtaMatKYagagttN
-atWttaccNtYtcDWgSatgaRgtMatgKtcgacaagWtacttaagtcgKtgatccttNc
-ttatagMatHVggtagcgHctatagccctYttggtaattKNaacgaaYatatVctaataM
-aaaYtgVtcKaYtaataacagaatHcacVagatYWHttagaaSMaatWtYtgtaaagNaa
-acaVgaWtcacNWgataNttcaSagctMDaRttgNactaccgataMaaatgtttattDtc
-aagacgctDHYYatggttcaagccNctccttcMctttagacBtaaWtaWVHggaaaaNat
-ttaDtDtgctaaHHtMtatNtMtagtcatttgcaaaRatacagRHtatDNtgtDgaatVg
-tVNtcaaatYBMaaaagcaKgtgatgatMgWWMaHttttMgMagatDtataaattaacca
-actMtacataaattgRataatacgBtKtaataattRgtatDagDtcRDacctatRcagag
-cSHatNtcaScNtttggacNtaaggaccgtgKNttgttNcttgaaRgYgRtNtcagttBc
-ttttcHtKtgcttYaaNgYagtaaatgaatggWaMattBHtatctatSgtcYtgcHtaat
-tHgaaMtHcagaaSatggtatgccaHBtYtcNattWtgtNgctttaggtttgtWatNtgH
-tgcDttactttttttgcNtactKtWRaVcttcatagtgSNKaNccgaataaBttataata
-YtSagctttaaatSttggctaaKSaatRccgWHgagDttaaatcatgagMtcgagtVtaD
-ggaBtatttgDacataaacgtagYRagBWtgDStKDgatgaagttcattatttaKWcata
-aatWRgatataRgttRacaaNKttNtKagaaYaStaactScattattaacgatttaaatg
-DtaattagatHgaYataaactatggggatVHtgccgtNgatNYcaStRtagaccacWcaM
-tatRagHgVactYtWHtcttcatgatWgagaKggagtatgaWtDtVtNaNtcgYYgtaaa
-ctttaDtBactagtaDctatagtaatatttatatataacgHaaaRagKattSagttYtSt
->THREE Homo sapiens frequency
-agagagacgatgaaaattaatcgtcaatacgctggcgaacactgagggggacccaatgct
-cttctcggtctaaaaaggaatgtgtcagaaattggtcagttcaaaagtagaccggatctt
-tgcggagaacaattcacggaacgtagcgttgggaaatatcctttctaccacacatcggat
-tttcgccctctcccattatttattgtgttctcacatagaattattgtttagacatccctc
-gttgtatggagagttgcccgagcgtaaaggcataatccatataccgccgggtgagtgacc
-tgaaattgtttttagttgggatttcgctatggattagcttacacgaagagattctaatgg
-tactataggataattataatgctgcgtggcgcagtacaccgttacaaacgtcgttcgcat
-atgtggctaacacggtgaaaatacctacatcgtatttgcaatttcggtcgtttcatagag
-cgcattgaattactcaaaaattatatatgttgattatttgattagactgcgtggaaagaa
-ggggtactcaagccatttgtaaaagctgcatctcgcttaagtttgagagcttacattagt
-ctatttcagtcttctaggaaatgtctgtgtgagtggttgtcgtccataggtcactggcat
-atgcgattcatgacatgctaaactaagaaagtagattactattaccggcatgcctaatgc
-gattgcactgctatgaaggtgcggacgtcgcgcccatgtagccctgataataccaatact
-tacatttggtcagcaattctgacattatacctagcacccataaatttactcagacttgag
-gacaggctcttggagtcgatcttctgtttgtatgcatgtgatcatatagatgaataagcg
-atgcgactagttagggcatagtatagatctgtgtatacagttcagctgaacgtccgcgag
-tggaagtacagctgagatctatcctaaaatgcaaccatatcgttcacacatgatatgaac
-ccagggggaaacattgagttcagttaaattggcagcgaatcccccaagaagaaggcggag
-tgacgttgaacgggcttatggtttttcagtacttcctccgtataagttgagcgaaatgta
-aacagaataatcgttgtgttaacaacattaaaatcgcggaatatgatgagaatacacagt
-gtgagcatttcacttgtaaaatatctttggtagaacttactttgctttaaatatgttaaa
-ccgatctaataatctacaaaacggtagattttgcctagcacattgcgtccttctctattc
-agatagaggcaatactcagaaggttttatccaaagcactgtgttgactaacctaagtttt
-agtctaataatcatgattgattataggtgccgtggactacatgactcgtccacaaataat
-acttagcagatcagcaattggccaagcacccgacttttatttaatggttgtgcaatagtc
-cagattcgtattcgggactctttcaaataatagtttcctggcatctaagtaagaaaagct
-cataaggaagcgatattatgacacgctcttccgccgctgttttgaaacttgagtattgct
-cgtccgaaattgagggtcacttcaaaatttactgagaagacgaagatcgactaaagttaa
-aatgctagtccacagttggtcaagttgaattcatccacgagttatatagctattttaatt
-tatagtcgagtgtacaaaaaacatccacaataagatttatcttagaataacaacccccgt
-atcatcgaaatcctccgttatggcctgactcctcgagcttatagcatttgtgctggcgct
-cttgccaggaacttgctcgcgaggtggtgacgagtgagatgatcagtttcattatgatga
-tacgattttatcgcgactagttaatcatcatagcaagtaaaatttgaattatgtcattat
-catgctccattaacaggttatttaattgatactgacgaaattttttcacaatgggttttc
-tagaatttaatatcagtaattgaagccttcataggggtcctactagtatcctacacgacg
-caggtccgcagtatcctggagggacgtgttactgattaaaagggtcaaaggaatgaaggc
-tcacaatgttacctgcttcaccatagtgagccgatgagttttacattagtactaaatccc
-aaatcatactttacgatgaggcttgctagcgctaaagagaatacatacaccaccacatag
-aattgttagcgatgatatcaaatagactcctggaagtgtcagggggaaactgttcaatat
-ttcgtccacaggactgaccaggcatggaaaagactgacgttggaaactataccatctcac
-gcccgacgcttcactaattgatgatccaaaaaatatagcccggattcctgattagcaaag
-ggttcacagagaaagatattatcgacgtatatcccaaaaaacagacgtaatgtgcatctt
-cgaatcgggatgaatacttgtatcataaaaatgtgacctctagtatacaggttaatgtta
-gtgatacacaatactcgtgggccatgggttctcaaataaaatgtaatattgcgtcgatca
-ctcacccacgtatttggtctaattatgttttatttagtgacaatccaatagataaccggt
-cctattaagggctatatttttagcgaccacgcgtttaaacaaaggattgtatgtagatgg
-taccagtttaattgccagtgggcaatcctaagcaaaatgagattctatcctaaagtttgg
-gcttgatataagatttcggatgtatgggttttataatcgttggagagctcaatcatgagc
-taatacatggatttcgctacctcaccgagagaccttgcatgaagaattctaaccaaaagt
-ttaataggccggattggattgagttaattaagaccttgttcagtcatagtaaaaaccctt
-aaattttaccgattgacaaagtgagcagtcgcaataccctatgcgaaacgcctcgatagt
-gactaggtatacaaggtttttgagttcctttgaaatagttaactaatttaaaattaatta
-acgacatggaaatcacagaacctaatgctttgtaggagttatttatgctgtttactgcct
-ctacaaccctaataaagcagtcctaagaatgaaacgcatcttttagttcagaaagtggta
-tccagggtggtcaatttaataaattcaacatcgggtctcaggatattcggtcatataatt
-tattaagggctcttcgagtcttactctgagtgaaattggaaacagtcatccttttcgttg
-tgaggcatcttacaccgctatcgatatacaatgcattccaccgcggtgtcccgtacacaa
-ggaaacttgttaccttggggatataagaaaactcacacgtctcattattaaactgagtac
-aatttttgcacgagaaagtaatgcaatacaatatgatgaaagccagctaatgaaaaggga
-tggaacgcacctcggatctgttgcactggattaaaatccgattatttttaaaaatattca
-gtgctagagcatatcaggtctacttttttatctggtatgtaaagcccacggagcgatagt
-gagatccttacgactcaacgaaaagttataacataactcccgttagccaaagcccaatcc
-cgattactgccctaccctaacgtctgccatctaaatatcgaacttgttatgatcaatgtg
-actacctcccaccctttccccttcatttgttccactggggataagctagcgttttcagaa
-tcaatgcaataagaatagccaattgtctcacttcatcagagctcttggcaattccaggcg
-ctacgtggttctggaatatattcatttttcaaatagtaatacgtttagtgttgctattgt
-ctacacgtttggatattacgttatgtgagcggacatcaatagttgtctaactctttagta
-agccagagatagcactcttagcgaatggataccatcttccataagtttagttaatagtcc
-gaaacaactgcttcgagcatatttgaacctccttgtaggcaaatagcctcttcaaagcaa
-tcttactaatagatagagtttgttttaagggactactagaaatgggacaatcttaatagt
-atgacctaaactgacatttaaagatatatccaggtggcaagcataaagatcattgcgcca
-cctccaccgtgggattacttatcagtcgatatcctatatgctaagtttgcgacggcagaa
-tacaaactaagctgagttgatgctaaccttacctatgataccccattggaccggttaaca
-gccctacttattccaaataaaagaacttttatgctgtagaagctattatagtgatgcctg
-gtaacttcagtatattaaaatgacacacatacgccatatagagctcctggaactttgaat
-aatgagcgaacttcgaagttgaagagcaagaaaccatatgtcacggttgcctaaagcccg
-gtaaccagacatgtgctatcattgatcattatcgaggttttcataaccttgacccattat
-cggctgtgcgcggacaagtacttaaatcactagtttcttcacctgcttatcggtaagaaa
-taaggttggcaaagaatcgcataagacggacgtagagccgcagcgttgtgcgagtccagg
-tgcatgcgcagcaataggattttaaattttgttccatttttaatttagccgtaaggatgt
-ccgtaaatgattgaaaattggattcaatctttgggcctatgctactggaacctgatcgac
-aaaatttcaaacatacgttaactccgaaagaccgtatttttgcggctagaatagtcagtc
-gcttggagccatataccttaccacttaaacgacgtgctcctgtagttgaaatataaacag
-aacacaaagactaccgatcatatcaactgaagatctttgtaactttgaggcgaagcaccc
-tcttcgagacaactaagagtaaagtaccgggcgccgcaaggagtcgattgggaccctaaa
-tcttgacgaattgctaagaggctcagagctaccactgtaatttctctagagcccataata
-aatgaacgatacatccgtaggtagcacctaagggattataatggaagccaaatgcagtta
-ataatattatatactggcgtacacgattcgacggatctctcacatagtgattcacgaccc
-ccccctttgattgacacagcgtcagcattttgcaagaacgatcttctgcatagggtgcgc
-caccgtaaggatgacgtcgaagctacaactgggtataatttaccatgcttccctgatgct
-gagtgcaatacactaagaatgagtttttaccccatatcaccagtatttgttctgttattg
-cgaagaaatggctatgctgagttggcgactaaagtcacccatcctttttattaggtaacc
-ccctcccttaaactaactgatttgctggagctgccctgcatacatatactttatcattta
-tggacgtccgtgacgcttattatccaccatagtcgatatgctacacggattcattaatgg
-atcgtaggagtttaagttatatttactaagatcggtctcggctactatcccgccttaccc
-ggcgctatttacggccatttttaatatattgacggtaattattcctatggtttcgaccgc
-acgtccttggacaagaaagaatggcaaaaaaaatgtaaaagaaaaaaaatattgagtccc
-taccatcatataaaaaatatgtgatgagtaacttgacgaaatgttagtggttattaaaga
-ctatctattacaccttttgttttctgtcgtagtatattaaagtctagaagccttacagga
-aaatcagggttatacagccgatactccgcagcatgaatcatcgaggaggtgtcctaccat
-cgcgccttgtaatcttgtctgtgtatactgtatttagaccttttatacaaagtaaatatc
-tcggctttatgtgattgggaggggcctactcaaacatgatgacttgacctaataatcact
-gtgcgggcgtcttatgactagctattccttgaaatccaccaccaaatggttaatatgtaa
-aaactttgacgatgaaacaaggtgaatgtgtagttactttgtgtaattagctgcgtcgag
-cattgcttgtaaaaccgtcaatcgcacacgttacttccataaaatttctacgaatacacc
-cttcttaaaaaaaacgtaggaattcacgagtttaacaaacgataactgtataaagtggaa
-gtccgaagaaagcagatgcccgaactactcgaagatgtttcgttttcttaaccatagggg
-cttcttaatggcccactacgcacattttgttcaagcccgagagggacatccccattacgg
-gagtattactaaaactgttccgtaatacgttcagcaagggatgaaaaaggccactgctca
-agttattgacgtgggagtattacatcggaagcctgaatcccacactatgatggtctgtac
-aggcctagggactgcgtctagacggtattaccggcttctaatcatacgatcgtgagtctt
-aacgggaagtaaggctcacacctaccccaaaccatttatctatgtaagtataaaattgtg
-cgtaagtgttcaaagtggacaataaagacgtggcaaaaacccccgcacataagccgcttt
-agatttcacaaataccaatgcggttaaaaacatccttgagtcgtacatacaccatactcg
-cgttaaacggatataacagaagataataaatccggatgtggagtcggtgtaactatagaa
-agccaagtgaaataatgcttaccagtcatttagctatacggctttcatttcatgtcaaga
-gggtggagtttgacctgtacagttgatatatcaccgatacttagaactcacctaaagcta
-aaattgctcgcagcgtgtaatccgcatattacaaacaatagatgggattcattatacata
-agacacgatgatctgctttttcaggttgcgagatgttgcctatcgtcaatcgagtcctgc
-cttacaccacttaaacaaaagtattgacagggaacctattttcgaggtattatatagtcc
-agcttgaatatcaatttgacagttaacctagtgaaaatcagtaagaggaaatacgccaca
-ttctccagtgaaattctacgggttatcgtctagtccaactatcaattataactcacgaga
-tataagtaaattctcgtacttggcctgatttttattatactttggatccttagtaaacag
-gaagggagaaaccttcaacgaaaaacactggattttgttttactctcaaagctcttatat
-gacggaaataccctgtcaagtcttaactttattactagactaatgaaatgggcttggggt
-ggccagaatcatagtacaatttagcggatacactattcggactttcctatcggctgtctg
-gttggataagtatggggactaataggctagacatacctatacttaaactatacaggcgtc
-atctatctctgcaactttggagttccctgatgttctcccgccctttgggttcacatcttc
-tataccgacacccctaataacgattagtttgtgggttagagtaaattaatacggttaata
-ttaatgtatcgttgaaaagctggtgtcgccaataaggtaaccggctaggcagagtatatg
-tcacgaagtataactaccctaatgataagctgtaggaataaaattaatgctgtctctaag
-cgaagagatatttccgactctgttttaatgacgaatctcattacttctgacttgcaaatg
-ttcaatatggcacggtttcacggcacctttgtgacgcatataatgaacttagaagattat
-aacgacggaactttatatgataatccgttacgattaaagaatctgttaaatatcataatg
-gcattcagttctagaccgtgcatcatggtaaacttactttctctgcatggcgacatacat
-ttcgctattcaaattcgcgtgtggttacacccactcgcacctttggaatattaagagaag
-atgatcagaaaatccattcgctcaatttttctgacgtacgtctaatttatcctaggagac
-aaatcgttttatgtctctcacatttttgaagaaaggttcgagagacaatactcaggtcct
-gaactgctagaagatactcggtggagcgtggcaacaatgaaaaactcgtgacataaatga
-atgatacttttccaagttcagttaagtgaatatgtttaacatacccggcttttcgatctt
-aagctgacgctggacgtgcgagtaatgtcagtctcttacatacactagtgactccaagtt
-tcgtcaaaaacgccccctcccttctcgagcccactcacgctatgtattgacgcgaacttg
-ttcgggatcagacttttcaggagttcggtcgcgtgtccctatgtgctaatatataagtta
-gatcgcattagatgctaatctgaatacttatagacgaccttcaacgagaacgggtaccac
-cttgaggctagagttaggtgtgaaacgacaggtagggacatataaaatttgagtgcggct
-ttagttaagggtttaattacctactcaaacatcacgctcgcgcccttcgtacgtaatcga
-ccatctagaggctaaggggactgtactaggtagtgattaatgatatcctagacgcacgtg
-ccttagatcttcagactctgatggtccgcgatcaccgtaattgtagtcctccaactcgat
-cactttgttggcgtcaaagaaattacgatatctaaatacttataatacaataaccaagga
-tgagaatgactcatcgcgttggagttatattgcttgaagttctatggaatgaaagcacgt
-tatctgccgtcccaatatctccagtgagctaattcattggacggtccactttgatcaatc
-cccgaggagatgttcggacactttagtctgtaacacttagcgttgagaccacgaacaatt
-gattactcagtcttgaaggtgttttccaaagttcattttaaataagactacgataggcct
-ttcctattgatataaactacccggctctgttgttcgtgtgagtcgtacttctctgtgttt
-ttctgattatagcaagattcgattcttagtgtaaacagcgatttttatttgacccgtcaa
-tgagaagcgcataggatctaagcaaaattatcaagttgtgccacaaggtaagatctttcc
-agttattgcaggtaggatgtatcccacgttgatagtatgaggtctgacgtcaactgtcta
-ggagagttgaccgcgtgcgggtacaccggatttgcatcgatgttgagaacgcagaactcc
-cactgtcgtggcggcgttcctgatatttagcaagaggcgttgataaagccctcatcatct
-agatctcgacctcatctgccctcttgctccatcattttctacacagactactttcctatc
-tacgttagtataattgctttctatcttagtatcatttagagcttctccgtcaacaggttc
-gtgctattaaagttagtacgaaagggacaacttgtagcaacgcatttaatcggttttcga
-ctacttcgcacaaaatcagataaagaagtttgtcattctattagacattgaattgcgcaa
-ttgacttgtaccacttatgatcgaacactgaatcaagactgtgattaactaaaatagaca
-agccactatatcaactaataaaaacgcccctggtggtcgaacatagttgactacaggata
-attaattggactggagccattacattctctacaatcgtatcacttcccaagtagacaact
-ttgaccttgtagtttcatgtacaaaaaaatgctttcgcaggagcacattggtagttcaat
-agtttcatgggaacctcttgagccgtcttctgtgggtgtgttcggatagtaggtactgat
-aaagtcgtgtcgctttcgatgagagggaattcaccggaaaacaccttggttaacaggata
-gtctatgtaaacttcgagacatgtttaagagttaccagcttaatccacggtgctctacta
-gtatcatcagctgtcttgcctcgcctagaaatatgcattctatcgttatcctatcaacgg
-ttgccgtactgagcagccttattgtggaagagtaatatataaatgtagtcttgtctttac
-gaagcagacgtaagtaataatgacttggaataccaaaactaaacatagtggattatcata
-ctcaagaactctccagataaataacagtttttacgatacgtcaccaatgagcttaaagat
-taggatcctcaaaactgatacaaacgctaattcatttgttattggatccagtatcagtta
-aactgaatggagtgaagattgtagaatgttgttctggcctcgcatggggtctaggtgata
-tacaatttctcatacttacacggtagtggaaatctgattctagcttcgtagctgactata
-ctcaaggaaccactgctcaaggtaggagactagttccgaccctacagtcaaagtggccga
-agcttaaactatagactagttgttaaatgctgatttcaagatatcatctatatacagttt
-ggacaattatgtgtgcgaaactaaaattcatgctattcagatggatttcacttatgcctt
-agaaacagatattgcccgagctcaatcaacagttttagccggaaacaatcgaagcatagg
-gacaatgtatcttttcctaaattgccatgtgcagatttctgagtgtcacgaagcgcataa
-tagaatcttgtgttgcctcaactcgttgaaaagtttaaaacaatcgcagcagtctttttg
-gggtctactgtgtgtttgcaaaataactgaaagaaacgcttgaacaactctgaagtagct
-cgagtactcattaaagtgtaacacattagtgaatatcggccaatgaaccaaacgcttccc
-ggtacgctatctctctcatcgggaggcgatgtgcaggttatctacgaaagcatcccttta
-cgttgagagtgtcgatgcatgaacctcattgtaacaatagcccagcaaattctcatacgt
-gcctcagggtccgggcgtactcctccatggaagggcgcgcatctagtgttataccaactc
-gctttttaactactatgctgtagttctacaggcatagtggccagtattttctaacttctc
-tggatagatgctctcactcctcatccatcacggcttcagtttacgtcttacttgcttgtt
-cagcaacggatggaggcattaagtatcttcactgttccctaaaattgctgttcaatatca
-aagtaaggacgatacagggaaagctcaagcacactcattgaatactgccccagttgcaac
-ctcacttaatctgacaaaaataatgactactctaagtgttgcggaagcagtctcttccac
-gagcttgtctgtatcacttcgtataggcatgtaactcgatagacacgaacaccgagtgag
-aaactatattcttgcttccgtgtgtgtgacaccaggtaattgatgcggatataagctgga
-gatcactcacgcccacacaaggcgctgctacctctttattccaatgtgtaagaatttgct
-aacttcatttctagaccgcagctttgcggtcataatttcacggtacggacccttgggtta
-gagacttgataacacacttcgcagtttccaccgcgcacatgttttagtggcttctaacat
-agaatttttgttgtgacataaagagtgcgtgggagacttgcccgaccgttaagccataat
-caattgaaagccccgtgagtcacatctaattggttgtactgcgcatttagctatccttta
-gctgactcgaagagattcgattcctaatataggttaattagatggctgccgcgcgaagta
-aaacgtgaaaaacgtagtgcgcagatctgcataactcgcgcttaattacttatgagtagt
-tccaagttcgctacgttatgagagagattggaattaagcaaatatgttttatggtgattt
-tgggatgagaaggactgctaagtacggctactaaacaaatttctaaaaccgccatctacc
-ttatcttggagacatttaagttgtatatgtcactagtctagcttttgtctgtgggacgcg
-ttctcggaatgagggaaatgcaagagccgattcatcaaatgcttatctaagaaagtagtg
-gactattacaccaagcacgaatgccagggaactgctttcttgctcaggacctcgcgacaa
-ggtaccccgcataagtcctagaattacatttggtcagcaatgctgacatttgaccgtgaa
-aacataattttaatcagaaggcagctcacccgcttgctctagatcttatctttgtatgaa
-tgtcagaatttactgcaatatccgttccgaatagtgagggcttagtatagttctctgtat
-acaggtcacatcaaactccccctgtcctagtacagctctgagctttaattaattgcatac
-atttccttcaatcatcagatgaaaacaccgcgaatcatgctcttctcgtatagggcaaga
-gaagcaacaaacaactagcccgactcacgttcatccgccgtatccttgttcagttcttac
-tccgtattaggtcagcgaaatctaatcagaataatcggtcgcgtatcaaaattaaaatcc
-cgcttgaggttgacaattaaaacgctgagcagttatcggctattagatagtggggtgaaa
-gtaattggctggaattatgttaaaacgtgatattaagctaaaatacgctacttgttgccg
-acctaattcagtcattcgatattcagttagagccaagaataacaagcttgtataaattga
-acggggtgcactaaacgatgtgttactctaatattcagcttggagtatacctgaaggcga
-attcatgtatcggccaataataagacgttgaagatcacaatttggactagcaaaagaagg
-tgatttatgcgtggggattgagtccactgtacgagtacggtctctggaaaattataggtt
-cagggaatataaggaagtaaagataattaccaagagatttttggtatcgctatgacccag
-aggtgttctaacgtctgttttgatccgcagaatttctgcctcaatgcatatttgacggac
-ttgaactagagcctctaaagttaaatggcgacgcaactgttcctaaacttcaattattac
-tactctttttttcctagggtattgtagaggccagtggacaaaataaatcaaatttaagat
-gtttcggacattaacatcccccgtagcatagaaatcatcagttatccaatctctcatcga
-gcttttacaatttctgctggcgctatggacagcatatgccgcgagacctccgcaagactc
-acttgatcactgtaagtatcttcattagaggttagagcctatagttaagctgctgaccta
-gtaaaattggtattttctaattttattgctcaagttaaaggttagtgaagggataatgac
-gttatttttgaacaatgggttgtattcaattttatatcacgaatggaacccttcattccc
-ggcataatactagacgacacgaacaagctccgatctatcagccaggcacgtgttaaggtt
-taattccggcaaaccaatgaagcatcaaaaggtgacctgatgcaacttagggtcacgatg
-agtttttcaggactacttattacctattaataagttaacatgagccttcataccccgtaa
-gacaatacatactccaccaattagaattctgagccatcttatctttttgtatcatcgaag
-ggtatggccgaataggttaattagttactcctaacgtctctacaggcatgcatttgacgc
-accttcgaaaatagtcaatctctcgccacacgcgtctagtatgcagcatcaaaaatatag
-tccacggtttccggattaccaaacgcggcaaagagaaacattgtatcgacggagataact
-taatacagaaggaaggggcatcttcgaatacggatgaataattctatctgtttattctga
-catcttgttttcaggttaatcttacgcattcaaatgacgcctgccccatgcgtgcgcaat
-tattttctaatattgacgagagcaatctcactccttttgggtctatttatgttttattga
-ggcacaagcctatacagaacaggtactattaaggccgtgagtgtgagactcaaaccgtgg
-aaacaaaggatgggttgttcttggtacaagttttagtgcatgtgggcaatccttaccaaa
-atcagatgctatccttaactttgggctgcatttaagatggcggttggaggcctgtgagaa
-tcctgcgtgtcatctttaatgaccgaattcatccatgtagattcagatcacacactcatt
-ccttgatgttgtctaaacaaaagttgttgtggacgcattggagggagttaagtaacaact
-tgggatcgcatacttataaaaattatatgttaaactttcacaaacgctgaagtccaaagt
-aactagcccaaacgcctcgagagtcactaggtattaatggtgtttgagttcctgtgaaat
-agtgttcgaaggtaaaatttatgtaccaaatcgaaagaacacttaataaggcttgcttgc
-acggaggtatgatgtttactgactctacaaccctaattttccagtacgtacattcattcc
-aataggttagttctcaaagtgctatacaggctcctcaattgatgatatgcttcagccgct
-ctatggatattagctcattttatttaggaagcccgcttagaggcttactatgagggaaat
-gccaaaatgtcatacttttcggtgtgtcccatatgacaccgctttacatagaatttgaat
-taaaacgcgctctcccgttcactaccatacttggtaccgtgcgcatattacatatagata
-taggatcattttttaaagctgtactaggtttgatcgacaatcttatgctatactatatga
-tgtaaccctcataatcaataccgatcgtacgatcctagcataggtggcaagcgattttat
-gccgattattgtgttaaatagtctgtgagtgtgattatcagggctacgttggtagagggg
-ttgtatagacctcgcacacattgtgacatacttaacaatatacgaaaactgatataataa
-atccccttacccaaacaccaatcccgttgaatcaactaccataacgtctcccatataaat
-tgcctacttgtttgcataaatctgaatacataacaccattgcaccttcttgtgttccaat
-cccgttaagattgccttgtcagatgatatgcaagaacaatagcatttgctagcaattatt
-aacagctcttcgaattgcctccacataacgcgggagggtatattttaatttggcaaatac
-taagtactgttggcgtcatatgctattaacggttggatattaagttatgtcagccgtaag
-caagagtgggcgaaatattttgttacccagtgagagcactcttagagtttggatacaata
-ggccatatgttgacttaagaggacgtaactacgccgtacaccattgttcaaccgacttct
-tggcaaatagaatcgtattagcaatcttaagaatagagacacgttcgtgttagggtatac
-tacaaatccgaaaatcttaagaggatcacctaaactgaaatttatacatatttcaacgtg
-gatagatttaacataattcagccacctccaacctgggagtaattttcagtagatttacta
-gatgattagtggcccaacgcacttgactatataagatctggggatcctaacctgacctat
-gagacaaaattggaaacgttaacagcccttatgtgtacaaagaaaagtaagttgttgctg
-ttcaacagatgatagtcatgacgcgtaacttcactatagtaaattgaaacaaatacgcaa
-tttagacagaatggtacggtcatgaatgacagtaattcgaagtgctagaccaacttaaaa
-taggtaaacgtgcccgaaaccccccttaacagaaagctgctatcatggtgcagtatcgac
-gtgttcagaaacttgtaacttttgagcaggtccgagcacatggaagtatatcacgtgttt
-ctgaaccggcttatccctaagatatatccgtcgcaaactttcgatttagtcccacgtaga
-gcccaagcgttgtgcgactccacgtgcatgcccagaaatacgagtttaaatttggttaca
-tggttaattttgaccgaagcatcgcactttatgattgataattggattcaatatgtcgcc
-ctatgcgaatgcaacatgatccacaatttggctataagacgtttaatccgtatcacactt
-tgtttgcggctagtatagtaacgcccgtgcaccaagagtcagtaacaattataagtactc
-cgcaggtacttcaaatataaaaactaatcaaacacgacccatatgatcatctgaagatat
-ttggaactttctcgacaaccaccctcgtactcaatacttacactaatcgacaggcacacg
-caacgtgtacagtcgcaccatattgagtcaagatttgcttagtggcgatgagcgtacacg
-cttatttctctagtcacaattagttatctacgagacatcacgagggagcaaataagcgat
-gttatggctacacataggcacgtatgaatatgatataagccagttaaacagtcgaaccat
-cgagcaaattctcatgcaccaacccacacgttgaggcacaaagagtaagctgtttgaatg
-taacttcttctgctgagcgggccccaacgtaaggatcaactagaagagaaaactcggtat
-tagtttaaatgcgtcacggagcatgagtgcatttcactaagaatgtctgtgtaaccaata
-taacatctatttgttatctgattgcctacttatggctttgcggtcgtggcgactaatgtc
-tccaatccttttgaggtcggtaccaactccctttaaattacgctgtgcaggctcatgcac
-tgcatacatatacggtagcaggtagggacctcacgcacccttattataatcaatagtagt
-tatcagtcaacgaggcaggaatgctgaggtcgaggtgttggtatattttctatgtgccgt
-ctaggcgactatcacgcattaccaggcgagatttaagccaattttgaatatagtcaacgt
-aatttttactatgggttccaccgaaacgccttgcacaactaagaatcccataaaatatcg
-atatcaaataaaagattgtgtcaataccttcatatatattttttcggttgactaacgtga
-actaaggttaggggttttgtatgtctatataggaaacagtttcttttctgtcctacttta
-gtaaagtcttcaagccttactccaaaatcacggtgattaagccgttactcagcagcatga
-ttctgcctgctcgggtcctaaaatccagccttgtaagagtcgctgtgtattagctaggga
-gacctttgttaaaaaggatatatcgcggcgggatgtgagtgcgtggcgcatactcaatct
-tcagctcgtgtcattataatatctctcccccacgcttttcactagatatgccgtgtaagc
-aaacaccttatgcttaatttcgaaaatattggtacttgaaaaaagctgtaggggtactta
-atgtctggtaggagatcaggagagaattgagtgtaaaaccgtaaagccctcacctgactt
-catgtaaatggcttagaagactccatgatttaataaatactacgaaggaaagactggatc
-taaagataactctagtaaggccaactcccttcaatgctgttgccagttataatccaagag
-ctgtccttttctgaaccatagcggcttctgaagcgaactagaagcaaagttggttctagc
-cagacagccacataccctgtacgggtgtattactaaaactggtccggtattagttcacca
-agggaggaattaggcaaaggatctaggtatgcaagtcggagtattacatccctaccctga
-atccatcaataggttcctctgtactggccttcgcaatgagtattcaaggttgtacagccg
-tataataataagatagtgactatgaacgggaagtaacccgctcaccttccccaaaacatt
-gttatatctaagtattaaagtctgccgtagtgttaatactcgaaaataaacaactggcaa
-attacaccgcacttaagccgcttttgatttatatttttccaatgcgcttttaaaaataat
-tcagtcctacatactaattaagacccttaaacggagatatcacaagttaagttttaacca
-tctcgactaggtggaactatagatacccaactcaatttatcattacctgtaatgttccta
-gaaggattgcatttcatgtcaagacggtggagtttcacagcgaaacttcagtgtgaacag
-attctgagaaatcacctaaacctattagtcagagcacccggttagaaccagttgtcaaaa
-aatagagcggttgcatgagacagaagtaacgatgagatccgttgtaacgttgagacatct
-ggcctatcgtcaatacagtcctcccttaaaaatatttttaaatactaggcaaacccaaca
-taggttagtcctatgtgatacgccacatggtatatcattttgtaacgttacctagggata
-atcaggaagtggaattacgcaaaagtagacagtgaaatgcttagggttatagtctagtcc
-aaagataaaggataaagcacgtcagagaactatattagccgaatgggaatcattgttagg
-agactgtggatcatgtctaaaaagcaacgcagaaacagtcatcgaaaaaatctcgttttt
-gtttgaatctaaaagagctttgatgaccgatagtacctgtatactagttactgtattacg
-tgtctaatgatttcggattggggtccccagaatcagacgtcattgtagacgattcaagtt
-taccaatttaatttcccagctctccttggagaactatcgccaataattgcagtcactttc
-cttttctgaaacgataaagccgtcagagttctctgcaacgttggacttacctgaggttct
-aacccactttcggttctaatagtagttaacgacacaacgaataacctttactgtggggct
-ttcacgatattttttcgcttattattaatggttacgtcataagctggtgtccaaattaag
-gttaccggcttcgcagagtagttgtatccaagtataacttccctaatcataagatcgagg
-tagaaaattaatgctgtctctaaccgaacagatatgtcccactatgtggtatggacgttg
-ctaattacttctgaagggaaattggtcattatggatacgtgtctaccatcaggtcggacg
-cagatatggttctgtcttcagttgatccaccgttctttataggataataactgacgatta
-aagattatggtaaatagattaagccaattctcttcttgtcagtgaagcatccttaactga
-cttgctctgcagcccctcatacatttagctattcaaagtaccggctcgtttcaaactctc
-ccacctttggaagaggttgtcaacttgataagtatatcatttacagcattttttcggacg
-tacctctaatgtttcattgcagaaaattagttttttctatcgcacattttgcaagtaacg
-ttagagacacaattatctgcgaatgaactgctagatctgacgaccgggagcctcgcaaat
-atcaaaaaagactgacatatatcaaggagtcgttgacaagtgctggtaagtcaattggtt
-tatctgtcccggcgtttcgatcttaagctgaccatgcacggcagagtaatgtcactctcg
-ttcttacaagtctgtctccaagggtcggcaaaaaagacccctccattctcgagcccactc
-acgatatgtagggacgacaacttgtgcggcttatgaattgtctggactgcgggcgagggt
-ccatatctccgaagttagaagggacatacctttagatgataagatcaattcttattgacg
-aaattcatccacaacggggaacaacttcaccctagacttacgtctgaaaagacacctagc
-gtcttataaaaggtcagtgccccgtttcgtaaggctggaattacctacgcaaacttaaac
-ctcgcgcccttccttacgtatcgacaagatagaggctatcgcgaatgtactacggaggca
-tgaatcatatactagaaccaagtgcctgtgatattaacaagatgatccgacgcgagcacc
-gtaattctaggcataaaactccagcaatttgggggccgaaaacaaatgacgttagctaat
-taattatatgacatgatcaaaggaggtcaatcacgcatcgagttcgacgtatattcattg
-aacttcgtgcgtttgaaagaaacttttatgaaggcaaaattgatcctgtctcctatttca
-tgcgtacctcctagttgataattccccgagcagtggttaggacacttttgtcggtatcaa
-gttccggtctcaaaacgtaaaattctgtaatctgtatggatggtctgtgaattagttaat
-ttttatgaagtcgtcgagacgcagttcctattgatttattctaaacggagatgtgcttcg
-tgggactcggaagtagatctgtgtttatgattattgctactttagatgctgactgttaac
-tccgtgttgtttttcaaccgtatatcacaaccgaattggatagaacctatagtttcaagt
-tctgccacaaggtatcatatttacagttagtgctggttgcttctttcaaacgtggtgagt
-ttgtgctatcacgtcaacggtagagctcagtggaccgagtgcgcgttcaaccctgttcca
-gagagggtgtgatagcacatataccacgctcgtcgaggcgttcatgatagtttgcaagag
-ccggtgttaaacacatattattattgttatccaactaatcggacctatgcataaagcatt
-gtctaaacagaataattgcctatatacggtagttttagtgatttatatcttagtatcagt
-tagagcttcgaactcttcaggttcctcatatttaacgttcttcgaaagcgaaaacttcta
-caaacgaatgtaagcggttttccaagtagtacctataaatcacagaaagatctgtctcag
-tatagttgaaatggtattcagctagtgacgtgtaccaattatcatagttcactcaagcaa
-gacgctcattaacgaatatagacaagacactatatcatataataaaaaagaacatggtgc
-tcgaacatagttgaattcaccatattgaaggggaatgctgacatgtaattcgctactaga
-cgatcaattccctacttgtcaaagttgaactggtacgttcttggaattaaatatgattgc
-gctggaccaaattgcgacttcttgagtttcagggcaaacgattgagccggaggatgtccg
-tctcttacctttcttgcttatgataaacgacggtccctgtacatcactgggaattctcag
-caaaaataattgggtaaatcgagactcgatgtattcggccacaaaggtgttagacgttaa
-agattattcaacggggcgataataggatcataaccggtatgcaagcgcattgaaagagcc
-atgagatccttatccgataaacgctgcacggtatgtgcagccttattgtcgatcacgaat
-ttataaatgtagtctgggctgtaagttgaagacctaagttataatgaagtgcaataccaa
-atcgattcatagtggattatcagactcaagatatctcctgataaattacagttgttaaga
-tacggataaaatgagatttaagattagcagcctctaatctgtttcaatcccgttggaatg
-tggtatgcgatcaaggttaagttaaaatcaagcctgtcttcagtcttgattcttgttctg
-ccatcgcatgcggtctacgtgagttaatatgtagcttacgttctagcttgtgctaatctg
-agtatagattcgtagaggaatattatcaagcttccacgcctcaacgtacgtgtattggtc
-acacaagacactaaaagtggaagtagcgtaaactatagtctagttgttaaatgctcagtt
-cttgttatattcgatatactcttggctaatttatgtctgagtatataaaattaatgatat
-taacttgcatttcacggatcccttagaaaaagattttgaccgagcgcattataaacggtt
-acaccgaatcaatagaagcatacccaatagctttctttgaatttattgcctgcgcaactt
-ggctgactctctagatccgaataattctatatggtcgtgacgaaactagttcattactgt
-ttaaaatgccaacatgtcttttgggccgataatggctctttgcaaaattactcaatgata
-cgattgatcaaagcggtagttgctagtggtagcatgtaagtctatcaaatgtctgattat
-ccgaaaatcttccaaaagagtccacgtaccatatctatctcatagcgacgcgaggggaac
-cttatctaactatcattccatttaccgggtgactctcgatgcaggatccgattgggataa
-attgcccagaaatggctcattcctgactaagggtaaggccgttctcagcaagggaacccc
-gcgaatctaggcttataccatctagattgttaactacttgcctgtagttctacagccata
-ctggacagttgtttctaaatgatcgggattcatgctagcactcctctgaatgcaccgcgt
-aagtttaactattacgtccgtgggcagataaggatggaggctgtatgtatcttaactgtt
-acctaatatggctggtaattatcaaagtaaggaccttaatgccatagcgctagcaatcgc
-tttgtatactgaccatgtgccaacctctcttaatctgtaaaatataatgtcttagctaac
-tgtggacgatcatgtctctgcctagagcttcgctgtatcaattcctatagccagcgtact
-agtgacacaacaacaccgtgtgagaaaagatattagtccttacgtctgtctctctacagc
-ttattgatgaggattgaacatggacatatagctccccctcaaaagcagatgctacctctt
-tattccattctcgaacatttgccgaacttaatttcgacaaacctgaggtcacgtcttaat
-ttatcggtaacgtcacgtccctttgagactggataaatatattaccaggggccaacgagc
-aattgttggaggcgcttctataatacaaggtgtcttgtcaaagaaagacggcgtgcgtct
-cgtgcaactcacttaaccaatattaatgtgaaacccccctctctcacatcttatgcggtg
-tactgccctggtacatttcctgtacaggactccaacagtgtagattcctaagatagctgt
-tggagttgcctcacgccagatcgaaaaactgaataaactagtgagctgagctgcagaaat
-accgcttaattacttatgactagttcaaagggacctacgtgatgtcagacattgcaagga
-agaaattaggtttgtgcgtcattttggctggactagcactccttacttcccctactattc
-aaatgtcgtaaacagcatgagacaggatcgtgctgacatttaaggtctattgggaacgag
-gctacctttggtcgcgcgctcgcgttctccgaatgaccgaaatgcatgagcacagtatgc
-aattgcttatagatctaaggtctggtcgttgaaaccaagcacgtaggcctgggaaatcag
-ttcttcctcagcaactacacaaaagcgtccaagcattagtacttgtagtaaatgtccgaa
-cctatgcgctcatttgaaagtcaaaaaatatttttaagcagtaggcacctaacccgattc
-ctctacttagtagctttctttgattctcagaattgactgcaatatcactgcacaattctg
-tgccattactagacttctctgtattaacgtctcatcttactaacactcgcctaggacaca
-tctgagagtgaagtatttcaatacatttactgaaatcttcagttctaaaatccccgaata
-aggctcttatcggtttggccaacacaagaaaaaaacttcttgcaccactcaccttcatac
-gcaggagcctggggaacttagtaataactatttcggcagacaaagcttataacaagttgc
-cggcgcgtataatatttaaaagaccccttgagctgctcaattaaaacgctcacctggtat
-aggctattagatagtgccgtcttagtaaggggcgggaattatcggataaactgatatttt
-gataaaataaccgacttgttcacgacataagtcactaaggagattttatctttctccaaa
-gtatatcttccttggataatttcaaagcgctgcaatttaagttctgttactagtttatgc
-tgctgggaggtgaccggaaggcgtagtaatctagaggcaaattataagaagttcatcata
-tcattttcgactacaaaaacaaggtgttgtatgccggcgcattgtgtaaactggacgagt
-accctagatggaaaattatacgttaagccaagatttcgatgtaatgataattacctacac
-atttttgctatccataggaacaagagctgttctataggctcgtggcatacgaacatttgc
-tgccgctatgaatattggaagctcttcaactacagactctattcttaattgccgtcgaaa
-atgggccgaatcggctattattaatactcggtttttccgaggggattgttgtcgacagtc
-gtaattattattaatattgatgttggtgaggtcatttaaatacaaccttgcagacaatga
-ataagggatccaatctctcatactccttttacaattgctcatgcccctatgcaaacctta
-tgccgccacacctccgcaactctctcttctgaactgtaagtagcttcattactggtttga
-gactatactgaagctgatgacattctaaaatggctattttcgaatgtgattcataatgtt
-tatcgtttgggatggcagaatcacgttatttttgatatagcccgggtattctattgtata
-gaacgtatgctacaagtcattccccgaagaagactagaagtaaacaacatgcgaccatcg
-ttaagccacgcaaggctgtagctttatttcccgataacctatcttccataaatagcggac
-agcaggatactgacgctcaacatcagtggttatggtctaatttttaacttttaataaggt
-aacttcagcaggcatacacagtaactctttaatttataatcaaattagaagtctgacact
-tcttatatttttctatcatccaacgcgatcgcccattagcttattgtgttactaataacg
-tatctaaaccaatccttttcaagctactgcctatattgtcaatatatacaaacaacagga
-tagtaggctgcttaaaaaatattgtcaaccgtgtacgctttacaatacccggaaatcaca
-aactttgtagacaacgagtgaaatttatacactacgaagggccagcgtacaagacccatg
-aattaggcgatatgtttattctgacatattggtttatccttaatctgtcgctgtaaaatg
-aagccgcccccatccctgcgaattttttttcgaagattcacgactgaaatataaatacgt
-ttggctatatttatgttggagggaggcaatagcctttactgttaaccgaagatttagcca
-gtgagtgtgacactaaaacactggaataaatgcaggcgttcttctgggtaaaaggtttag
-tcaatctcgcctataagttcatatagctctggatataattatctggcccatgcatttatc
-atggcgcttggtgccctgtgtgaagccggcctctcatattgaaggtccgaagtattccat
-gtacattaagatcactctctcattcatgcatcttggcttaacaaatctggttgtccaagc
-tttccaggcacgtatggtacaaattcggatcgaatacttataaaaatgatatgttaaact
-gtctaaaacgctcatctacaaagtaaagtgcactaaccaatagagtctcaagaccgtgta
-atgctggtgcactgaatgtgtaatacggttagaagggattagttatgttacaaatccatt
-gaaaacttaagaagcattgcgtgctcggagggtgcatcttttatcaagagactaacatta
-ttttcaacgacgtacatgctttacaatagggtacttatcaaacgccgagaaacgcgccta
-tagtgatgttatgattatgacccgatatccattggaccgaattttatgtaggttcccagc
-gtactcgcgtaatatctcggtattgccataatgtaatacttgtcggtctctcccagatga
-aaaagcgttacagagtatttcaatgaaaaacagcgcgcaacgtcaatacctttaggggta
-acggccgctgatttcatatagatatacgataagttggtatagctctactaggtggcatcc
-acaatcgttgcatttactatagctggttacaatcataatctataccgttccttacatact
-accatagcgggatagcgtttttttgccgttgattgggtttaagaggatgtcagtctcatt
-atatccgattcggtgggagagccgttgttttcaaatcgcacactttgtgacataatgtac
-aagataacaaaactgatataagatataaactgtcaatatcaccttgacacttgaatcaaa
-gtaaattaactcgcaaatataatttgactaattgggtgcagatttctcaattaataaaaa
-aatggcaccggatgggcttacaagccccttatcattcacttgtatcatgatttccaagaa
-caatagaatttgctagcaagtatgaacagagattcgaattgcatccacagtacgccggag
-cgtttattttaatgtggatatgacgatgtactgttggcggcatttgctagtaaccggtcc
-ttatttacgtagcgcacacgtaagcatgtctgggagaaatatggtggtacaatctcagag
-aaagattacagtttggtttaaataggacttatcgggtcggaagtggaacttaataagcag
-tacacaattgggcaacagacgtcttgcctattacaataggattacaatgcgttagatttc
-agacacgttcgtgtttggctattcgtcaattccctaaatagttagacgatcaactattat
-caaagtgattctttgttcatcctccattcatgtaacagatggcacactacgcataacgcc
-gaggaattttaacgagatttaagagagcagttcgggcacaacccacttgactttataaca
-gctcggcagcataaacggtaatatgtgacaaatttccaaacgttataagaacgtatgtgt
-acttagaaaactaagtggttcatgttcaacagatgtgacgcagcaagcctaacttatcta
-ttggttttgctataaaagaacaaagttacacagaatcctaagggcttgtttcacacttat
-gcctagtgcttcaccatcttaaaatagcgaaaccggcacgaatcaaaccttaaaacaatg
-cgcagatattggtgatggtgactccgggtatgataatggtaactgttgaccagcgcccac
-ctcatcgaagtatagaaagtggttaggataaggatgagaccgaacttatttccggccata
-actttagattttctacctagtacacaacatcagggcggacacgaaaccgccatcacatca
-tataccaggtttaatttgcttaatgggggaagtgtcaacgaaccttcgaactttagcagg
-catatggccattatatatggccccagagcagaatgctacagcagacaaaatttggattta
-tgtagtttaatacctatcaaacttggtgtgaccatacttgtctaacgacagtgcacaaag
-tgtaagttacaattattactactcagcagcttctgcaatgataaaatcttatcatacacg
-tcacatatgataatatctacttagggggaacgggctccacaacctacatagtactcaata
-cttacactattcgacaggcacaccaaacctgtacagtcccaaaagattgagtcaactttg
-cagtactgcagatcacagtaatagcttagttagcgagtcaaaattagttttctacgagac
-tgcacgaccgtgcaaatttccgatgtgttggctacaaatagcaacgtatgaatttgtttg
-aagccacgtaaactgtacaaccttagagataagtctcaggctactaaaaacacgttgtgg
-cactaacaggatcatggttgattcttacttattcggctgaccggcccaataagtaacctt
-caactagaacagaataatcgggagtagtttaattcagtcaaggtgcaggtctcattgtaa
-ctaacaagctctgtgtaaccaagttaaaatcgttttcttagcggattccctacttatgga
-tttgagctcgtccacaatattcgatacaagaagtttgtggtccgtaacaacgaaatttta
-attacgctgtgcagcctcatccaaggaattaatagaaggttgatggtaggctccgaacgc
-tccatgattataatcaagtggactgtgcagtaaacgaggaaggtatcctgacgtcgtggt
-gttcgtttttgttatttgtgccctatacgagtagataaaccatgaacagcacagtgtgaa
-cccatggttgattttaggctaccttatttttaatttccgttacacagaaacgaattccac
-aactaacatgccattaatttttcgatatcttataaaagatggtcgaaattcattcattta
-ttttttttcggttctcgaaagtcaactaagctgtcgcgttttgtttctctttagaggtaa
-aagtggctttgatctcctacgtttggatactagtcaaccattactccatttgatccgtga
-gtatcacctgtctaacatccagcattatgactcctcggcgaagaaaagacacacttctta
-gagtcgatgtgtattagctagggacacagttgtttaatacgatagtgagcccagggaggg
-cagtgcgtcccccagtagatttattcagctagtgtaagtataagatatctcacccacgag
-gttcaagtgatatgcagtcttagaataatacttatcctgaatttcgatattatgggtact
-tcaataatccgctagcgctactttatgtctcgttggacagcaggacacatggcagtctta
-aacactaaagacatcacctgaatgaatgtaatgggattacaagaatcaatgaggtattat
-atacgacgtaggaaactctggatatatacagtaatctagttacgccatcgcacttcattc
-ctctggaaacttagaagacatcagctgtacgtggaggaaccagacccccgtatgtagcca
-aatagaaccaaagttgcttatacaaacacacccaatgacaatggaccgctggagttcgta
-aactcggaacgtagtactgcacaaacccagcatttagcaataggagctacgtatgcaact
-cccacgtggtaataccttcaagctatcaatatataggtgcctagctaatcgcattcgcaa
-gcagtattcaagcttgtaaaccagtataataattacagaggctctatgaaacccaacttt
-ccagctaaaagtcccaattaaatggttatttcgtacttttaaagtcgcccgttctgttat
-tacgcgaattgattctactccaaaattaaacacaaattatcaaccgtttcatttatattt
-gtcaatgcagctgtttaaaataaggctctactaaattataattaagacacttattaccag
-atttctctagttaagtttgaaccagctcgactaccgcgaaagatacattcccttctctat
-ttttcagttcatctatgggtcagagaagcattgaatttattctattcaccctcgtcgttc
-acagcgaatcgtcagtgtgatcagtgtatgagaaatatcctaaaccgtttagtcagacca
-cacgcttagaacaagtggtctaaaaagactgccctggaaggagtaagaagtatacagctg
-atccggtgtatccttcagtcatctgccctatactaattacacgacgcaaggaaaaatagg
-tttattttctaggcaaacccttcataggtgactccgatgtgttacgaatcatgcttgaga
-atgtgctatcgttaccgacggataataacgatctccaatgaaccaaatgtagaatgtcta
-ttgattacccttttactattcgacttagagataggagatagaacctcagtgtactttttt
-agccgaatgggaatctttgggaggtgaatggccataaggtcgtaaatccaaccctcttaa
-agtcttccatattatatcgttgttcgtggaatcgataacagatttgttgacccatagtaa
-atgtatactagtttatgttgtaagtgtagattgttttccgattgccgtccaaactttatg
-tcgtaattgtagaccagtaaagttgaccaaggtaagtgcccagcgatcctgcgagatcga
-tcgccaatttttccagtcactgtaagtgtaggtttagataaagccgtatgagttatatca
-taagggcctcggaaagcagcttcgaaccaaagttcccttataatagtagtttaactataa
-aagtatatactggtctgtcgccctttcacgatttgttttaccggtttatgaagcgttacg
-tcattagagcggctccaatttaaggttaacggcttccatgtgtagttgtatacaaggata
-acttaaagtatctgttcagcgagctagttaagttatcctcgatagaacacaactcagagg
-tcccaagatcgggtttgcaacttgctaatttattctcaaggcaaattgggaattatcgat
-acctgtataccataaggtcgctcgatgtgatgcttatgtcttctggtgatcctaccttag
-ttagtgctgattaacggaacattaatgtttatcgttttgagatttagccaattctctgat
-tctaactcaagatgccttatctgacgtgctatgcagcccctaagtattttacattgtaat
-aggacacgctcctttaaaactcgccaaaaggtcgttgtggttctctactggttaactata
-taatttacagctttgttgagctagttcctctttggtttaagtcctcaatattagttggtt
-cgagcgataagttggctagttaccttagtcactatattagatccgaatgttatgcttcat
-ctgaagaccgccaccctccaaaatttcttttaagactcacttattgcaaggtgtaggtga
-attcggctcgtttctcaagtggtgtatctgtacacgagtttccatattttcatcaacagc
-caccgcacacttatgtcactctaggtattaaaagtcgctctacaaggggacgcaattaag
-aaacagacatgctagtcaaaaataaacatagcgaggcaccactaattcggccgcttatca
-atgggatgctctgcgcgagacgcgccagagctcagtagttagttcggacatacatttact
-tcagatgatcaattagttttctacaaatgcttactctaccccgaaaaaagtcaccagact
-cttacgtctctttagtatccttccgtcttatataaggtcagtcccccgtttcggtaccct
-ggaatttactaagaataatgaaacagcccccaaggacgtacgtttacaaatgatagacca
-gatcgcctagcttattccgacgcatgttgcatagaattgaaccaacggaatgtgagagta
-actagatgagccgaccacagcacccgtttgcgtcgcagaatacgcctgatagttcggcca
-cgaaatcatatgtcctttgagtattaagtatttgtaatgatcaatcgagctcaagcaagc
-ttacacttcctcggatattcagggaacttagtgcctttgaaagatacgttgatcaacgaa
-aaattgataatggctcatatggaatgcctacctcatagtgctgaattaacacagcactgc
-ggacctaacttttcgaggtttcaagttcacgtctcaaaacctaataggctggaatatgta
-gggatcctcggtgaatttgtgattgggtttgttgtagtactgaccaagtgaatattcttt
-ttttctaaaagcagatctgctgccgggcactacgaaggagatctctgtgtatcattattg
-cttcttgacatgatgactcttaaatcactgtgggtgtgcaaaacgatagcacaacccaat
-tcgatagtacatattgttgatacttcgcactaaaccgttcatatttaaaggttgtgctcc
-ttccttcgttaaatactggtgacttggtcctatctactattagctagacctctggggaac
-cacgcccccgtaaaacctgtgcaagagagggggtcatacatcttagacatcgcgcctcca
-ccagggaagcattgggtgattgaccaggtgtgtaacaaatatgattattcttatactaat
-attagcaaagatgcataatgatttgtattaaatgtataattgaattgataagggtctttt
-agtcagtgatagagtagtataaggtagacattagaactcttaaccggacgcagatttttc
-ggtcttagtaagccaattagtcgacaaaacaaggtaagagcggttactagtagtacctat
-aatgcactgaatcttcggtcgaagtatagttctaatgctatgcagattgtgacggcgaca
-aatgttcagacttatatcatgaaacaagctcttgtaagtattgacaaatgaaaagattga
-atatttttaaatacaaaatgcgcctacttattaggggaattaaccagattgaaggccaat
-cctcacatgtaatgagataatagacgataaatgaaattcttgtaatagttgaactgctac
-gtgatgggtattatatatgattgagatcctccaattgccgacgtcttgtcttgatgccca
-aaagattgtcaacgaggagctccctcgcgtacctgtcgtccgtatcataaacgacgcgac
-atgtacagcactccgaagtataagcaataataatgcgggtaatccagactagatcttttc
-ggactcaatgcggtttcacggtaaacatgattaataccggagagtagtcgagcttatcag
-cgatgcaagcgaattcattgtgccaggagatacgttgcagataaaaccggcaacgtatgt
-caacaagttttggcgatctcgttgtttgtattcgacgaggcgcgggaacttcaagaacta
-tcgtatattcaagtccattaccttttagtttcagactggtggagctgactaaagttatat
-catcattttgtacactggtttagttaacgataatttcagatttaacatgaccagacgata
-atcgctgtatatccagttggaatgtggtttgccagaaaggttaacttataatcaagcctc
-tcttcagtcttgattcgtcgtatcccatccattgcgctatacctcagtgtatttggagct
-gtagttataccgtgtgctaagatcagtagacatgacgagagcaatattatctaccttaca
-agcatcaacggacgtctagtcggaacaaaagactctaaaactcgaacttcaggttaatat
-actatagttctgtattcagcagttattcttatattcgatattatcttgcctattggatgt
-ctgactttagtatattaatcatagtatctgccatgtaaaggtgccagtactaaatctgtt
-tcacagtgcgaattataaacggttacaaccattaaagacaacaagaccctatagctttat
-ttgaattttgtcaatgcgcaacttggagctcgcgatacatcccaattagtctatagggtc
-gggacgattctacggcatttctggttataatgacaacatggattgtggcccgagaatcgc
-tctttcattaattaagcaatcattacagtcttataagcgctacttccgagtggtagcagg
-taactcgatataaggtcgcatgagccgaatagcttaaaaaacaggccaccgaacattgat
-agagaataccgaccacagcgcaacctttgattactttcattaaattgtacggctcactcg
-acatcaagcttaagattgcgataatgtgaactcaaatggatcagtactgaagaaccgtaa
-cccacttcgcagaaagcgtacccagagaagatacgctgttacaatatacagggtgaaatt
-attgcctgttcttcgtaaccatttcgccaaacttggttagaaatgatagccattcatgat
-agaaataagctgaatgataccagtatctttaactatgtagtcagggggaagataacgatg
-gtccatgtatgtttctgatatgtgacagtattggccgcgtaatttgctaacgaagctact
-taatgcctttgagcttcatatagatttctttaatcaaaatcggcaaaaagatagtatgag
-ctataatatatgctagtagagaactctggaccatcatctatatgaatactgattcgagcg
-tgcaattactttagcctgcgtactactgactctacaaaacactctgagataagtttgtag
-tcagtaagtcgctctctataaaccttttggatgaccattgtacagccacttatagatccc
-aataaatagcacaggagacagagtttttcaatgctcgatcatttgccgatagtattttcg
-tctaacctcagggcacctattatttgatacctaacctaacggccctttcacaatggagaa
-atatatgacatcgggacaaacacaaatggtgggtggccaggagatatgacatggtggcgt
-ctctaagaaacacggactccctctaggcaaactcacgtaaccaattttaatgtcaaacaa
-aacgctcgaaaagattttgccgtgtaatgacctggtacattgactggtcaggaatacatc
-actgtagttgccgtagtgtcctgttggtgttccatcaagacacatcgtataacgcaattt
-acgacggacatcagatcaagttatacagattatttaagtatcacgtgtgcattgggacat
-aagggatctcacacatgccttggaacatttttgctttgtgccgctttttcgctgcactac
-caatccttacttaccagtatattcaaaggtcgttaacagaatgagaaaggttagggctct
-aagttatcgtcgattgggatagacgagacatttgcgagcgccctccacggatacgaatct
-cccatatcaatgtgaactggatgctatgcagtttagttcttacgtctcctagtggtaaaa
-atcaaagtagcactcgcatagcagttattcagaacctaatacacaaaaccgtcaaacatt
-ttctaattctaggtatgggccgatcataggagctaaggtgaaactcataaatgttttgtt
-agatctagcatcctaaaaagatgcatatactgagtagctggcgtgcattctctcaattgt
-atcctttttaactgaactagtcggtcccatttcgtgactgagatctattaaccgataaga
-ttaataacactcgcattcgtatcagctcagagtgaagtttttcaataatttgactgatat
-attaacttctaaaataaccctttaagcctcggatccgtttcccaatcacatcaaaaattc
-ttattccaactatctacggattaacaacgtgcatggggatcgtagtaagaacttgttccg
-atcactttgagtatatcaagttgacggcccggttattattgaatagaaacattcacctgc
-taaattaaataccgcacatcggatacccgatttcagagggccgtcttactaagggcaggc
-tttgttcggtttaactgagatgttcattattttacagtatgcttcaactaatatgtaacg
-aaggacagtggatctgtctccatagtagatcttcagtcgtgaatttcataccgctcctat
-ttaagttcgcgttcgagttgttgatcatggcacgtgaaagcaacccctagtattctagac
-gaaaattttttctagttcatctgataatttgccaattcaaaaacaaccgctggtttcccg
-gcgcattctctaaaatggaagtcgaacctagagccattatttgtcggtaacccatgagtt
-ccttcttttcagaagttaatacactgtggtcctatacagaggaaaaacagcggttatata
-cgatcgtggcataacaacattggatcaagatagcaatttggctacctattctaattctca
-ctagattcggtattccactacaatatcggcagattaggattggatgaataatcggtgttt
-aagtccggttgcgtctccaatctcctaatttttattaatattgatcttggtgacctattg
-taaataaaaacttcaagactttgaataacggtgaaaagatagaagactcatttgaaaatg
-gatcatccacagatccaaacattagcaagacactaatccccaactagctattctgatcgc
-gatcgtgctgcagtactcctgtcacaatagtctgttcatgatctaattctttttgggctt
-tgttcgatggtgattcagaatctttatccggtcgcttccctgtagctactttgtggggat
-attgcccggggattatagggttgagatcgtttcctaaaagtatttaaaccaagtagactt
-caactaaactacatcagaacatcgtgaagacaccatacgcggtacctttatttaccgata
-acatttcttcaagaaataccggtaagcagcataatgaccctaaacagctcggggtatcgt
-cgtagttttaaattttatttaggttactgctcaaggaataaaaactaactatttaattta
-taataatattacaaggctcacactgattagatttgtctataagacttcgcgatcccccat
-taccggattgtcttaagaataaactagataaaccatgcattttctagataaggcctttag
-tctaattagatacaaaaaacacgatagttgcatccttaatttattgtgtcaaacctggaa
-ccttttaattacccgcaaatcactttatgtcgagactacctctgaaatttattatctacc
-taccgcatgaggacttgaaccatcttgtaggagttatgtttattagctaagattcgttta
-tcctgtagcggtccatgtatattcaacaagcaaaaagcactcagaattgtttttagttga
-gtcaagactgatatataaataagtttccctagttttttcgtggtgggacgatattgaatt
-gaatcttaaccgaagagtttcccactctgtcgcacaataatacacgccaatatttccagc
-cctgcttatgccttaatcggttactcaatctcccattgaagttcattttgatctgcatag
-aagtttcgggcccagccttttttctgccaccttcctccaagctctgtagacgcactctaa
-gattgatgctcacatgtattaattctacattaacataaatatataagtcatgcatcttcg
-agtaaaatatctggttctccaacatgtcctggcacgtatcgttataatgcccatacatgt
-agtattaaaatgattgggttaactggatattaagatcatcgaaattgtaaagtcaaatta
-acaatactgtctcaagaccgtgtattcctcgtgctcggaagggctattacgcttacttcc
-gttttggtatcttaatatgactttcaaaaattaagttgcagtgagtcctacctgcgtgca
-tcggttagcaagagtataaaagttgtttaaacgaactacttgctttacaataccggtcgt
-atatatcgccgtgaatccagaagattgtcttctttggattatcaaccgagatcctgtgga
-ccgatgttttgggaccttcacagaggactccaggtagagctcgcttttgcattaatctaa
-gaattgtacctctctaaaagatctaaaacagtgaatgtgtatttcatggaaaaacacaga
-gaaacgtaaattactttaggccgaaaggcacatgagttattatacatatacgagatggtg
-gtatacatcgaattcggggcatacactatagttgcattgtatttagctgctttaaataat
-atgatattaccttccttacataagacattaccggcataccctggttttcaacttgtgggg
-ctttttgacgatcgcactctcatttgatccgagtagggcggtgacccctgcttttcaaat
-acaaaaatttcgctatgaaggtaatagattacttttcgctgttatgatagaaacggtaaa
-tttaaaattgaaacttctagaaaagtaaagtaacgagaaatgattttgtgaataatgcgg
-tcatgattgcgcaagtaagaaaaaaaggcaaaaggatgcgcggaatagaaacttatcagt
-cacgggtatcttgatttcattcttcttgtcaattgccgacataggatgaaatcagattcc
-aatgcaatacacagtaacccccacccttgattgtaatgtcgatttgaagttgtacgcgtc
-gacgaagtggatagtatacgggccttttgtacggtgcgatcaactatgaatctcggcgag
-ttagatggtcgtacaatctcacacatagaggtcacttgcctgtaatgacgaattttcggc
-taggtactcgaactttattagaagtaaaaatgtgggcaaaagaaggattccattttacaa
-gacgattacaatgagttacatgtctctcaacgtagtctttccctagtagtctttgaacta
-tttaggtactccagaaaattttagcaaagggtttctgtgtgaatccgccattcatgttta
-tgatggaacaataagaataacgccctcgtatgttatcgacagtgaagtcagcagttcggc
-caaaaacatattcaatttagtacagatccccagaagttaagctaagtgctctaaaatggc
-ctaaacggttatcaaagtaggtctaattactatactaacgggtgcatcgtaataactgct
-gtcgatgcaacactatatgatagtgtcgttttgctatatatgtacaatgtgacaaagaag
-ccttagcgattcttgcaaacttaggacttcggattctcaatcttaaatgtccgaaaacgc
-aaagattcaaaaatttaatctatgagcagatatgcctgatggtgactacgcgtatgttaa
-ggctaaatgttgacaaccgcacacataatcgaactattgatagtcgggagcataaccagg
-tgaacgtactttgttcacgacatttattgacatgttctaaatacgtctcaaaatcacggc
-gcactagaaaacgcaatcaaatcattgtcctggtttaagggccgtaatgccggtagtgtc
-aaacttcatgagaactttagctggcttttggccagtatttagggaccaagagcactagcc
-ttaagctgaatattttgccatttatctactgttataactttaaaacttggtggcaccaga
-cttgtcgatacacacgcatcaatctgtaacgtaaaaggtttactaagaacaagcgtagga
-attgagtttatattatatttaaactaaaagatgatattagcttctgagggcgatagggct
-ccaaatcataaagaggaatatattattacacgattagaaacccacaacatacctcgaatc
-gcccaaaagtttgacgaaacttggcagtactccacatctcagtaatacagttgggagagt
-ctcaaatgttgttttattactcaatgaaccaccctcataatttcactgctgttccattaa
-atttgcaaacgatcatttgctttgaagaaacgtaaaatcgacaaaattacagataagtag
-atgcataataaaaaaaactgctcgctataacacgatcatcgtgcattcttacttaggagc
-atcacccgcacaataacgtaccttaaactacaacactattagaccgagtactgtaattca
-cgaaagctcaagctcgcattgtaaagaacttgctctctcgtaaaatgtgataatagtttg
-cggagaggattcaattattttccattgcacctactccactagattcgataaaagaaggtg
-gtcctcccttaaaaagaaatgttaagtaacatcggaaccataagcaaagcatgtaagtga
-accgtcatccttccctaagaaacataaaggtttttaataatgtcgactgtgaactataac
-tgcatcctttcctgacctactccggttccttgttgttatttctgaacgagaccagtagat
-aaacaatgtaaaccacagtgggtaccaatggtgcatgtgacgctaccgttgttttaagtg
-cccgtacaaacataagaagtcataatcttacttgaaattaattttgccttttattttttt
-tcaggctcgaaattaatgatttgttttttttgaccttctagttacgctaatatgcggtcg
-cctgtggtttctattgagtcctataacgggatgggatctaatacgtttggttactagtaa
-acaaggtataaatttgataccggagtatcaactgtataacatcaagctttatgactcata
-cgcgaagtaatgacacaaggctttcaggagatcgcgagtacagagccactaaggggtgta
-ttacgatagtgacaccaccgagcgcactcactccccaagtagatttatgatcctacgcta
-agtattagatatataaccaaagaggttctagtcagtgcaactcttagaataataattagc
-cggttttgcctttttaggcctaatgcaatattcagctagcccttatgtatctcgcgttcc
-acagcaccactcatggcacgcgtttaaactaatcaaatataatctatgaatgttatgcca
-gtacttgaataaatcaggttttttataagtccttgcatactctcgttatatactgttaga
-gtcttaccccatagaaattctttcatctgcaaacttagaagaattctcagctacggggag
-cataaagtccccaggatgttgacaaatacaacaaatgtggcttatacaaacactccatat
-gaaaatcgaaccctcgtggtagttttagccgaaccttgtacggataaatccctccatttt
-ccaatagcagatacctatcctactacctcgtggtattaaattaaagcttgaaatatagag
-ctgcatagcttatccaattcccaagcacgagtctaccgtcgtaaccacgatttgatttac
-agacgctagagcaaacccatctttaaacatataagtaaaaattaaagggtgagtgcgtac
-gtgtttactagcaacttcgcttattaagacaattgtttataagccataattaaaaacata
-tgttcaacaggttcattgatatttgtaattgcacaggtttttaataaggatctacgtaag
-tataatgaacaaactttttaccagagttatattctgtactttgaaaatgctcctctaccg
-ccttagagactttcaattagattttttgcagttaatctatgcgtaagtgaaccatgcaag
-ggatgcgattcaaccgcctcgtgctaaccctatcgtctgtctcataactgtaggtctaat
-ataattttcagttttcgaacacataaccctttgaaaatctgctatttaatgtctcacctg
-catgcactatcttctatactgctcagaacggctatacgtcactatgctccaagtgacgat
-ttaaacgaagcaaggaataataggtttattttagtgcaaaacaattaagtgcggactacg
-tgctctttacaataagccttgtgattgggctataggttaagtcccatattaacgatctcc
-aatgtacaaaatcgacaatcgctttgcattacccggttactagtcgaattacagatagct
-gttagatactcactctaattttggacaacaatcccaatcttggggtcgtctatcgcctga
-agctcgtaaatccttccatcttaaacgattacatattatagacttgttcggggtagagat
-atcacagttgtgcaaacattgtaaatcgatactagtttatgttggtagtctagttgcttt
-taccattccccgaaaaacttgatctactatttcgacaacagtaaacttgaactaggtaag
-tgaaaacagagaatgcctcatagtgccactatttgtccactatatgtaagtgtagcttta
-cataatccactatgactgagatcattacggcctaggaaagcagcgtagaaaaaaagggcc
-cggatattacgactgtaactataaaactagttactggtagcgcgccatgtatagatttgt
-tttaccggttgtggttgcgttaacgaatttcagccgcgaaaattgatccgttaaccagtc
-catctcgacttctataaaacgataaagtaaagttgatgttcagcctccttcttatggttg
-catcgagagtacactactcagtgggaaatagatcggggttcctacttcagattgtattat
-ctaggcaattgccgattgtgccatacctggataaaataagctacctacatgtgatgctta
-tctattatcgtcatactaccttagggtgtcctgttgaacgctacattaatctttagccgt
-ttgagatgttccaatggataggagtctaacgcatgatgaagtttaggaaggcagagcatc
-ccactaagtatgtgacagtgtatttcgaaacgagacgttataaatagaaaaaaggtcctt
-ctggttctattctgctgaactattgaatggaaagattggttgacctacgtactatttgct
-tgaagtcatcaatttgacggggtgagagacatatggtgcatactttacggactctatatt
-ttagatcagaagcttagcagtcttctctacaccccctcacgacataattgcttttaagaa
-tctatgtttgattcctctacgggaattcggatccgttcgcatgtgcggtttatctaaacc
-aggggacatatgttcagctaaagcatacgaacactttgctaactagacgtatgtatagta
-gctataaatcccgacgatatttacaaaaagaaatgagactcaaatatatacatagcgacc
-ctacacttattcgcaccctgatctaggcgatcctagcacccacacccgaaagtgagcact
-agtgtcttccgtattaaatttactgcagttgagattttagttgtctactaaggattactc
-taacccgtaataaggatcaagactcggtactagctttactatcattccctatgtgttttc
-ctaactcacaagggtacgtaccagcctatgtaattacaataatgataaagacacaaagga
-agtaactttacaaatgagtctccagttacactagcttagtccctcccatcttgctttgaa
-gtctaaatacgcaatctctgaggatatacagcagaagaacactcataacgttggagtcca
-agaattagactcatagggcccccaacatttaatatgtactgtgagtttgaaggtgttcta
-ttgttaattcctgctcttgatacatgacacgtactccgtgtttaaggcttcggactgact
-ttctttcataagttgagcaacgaaaatttcagaatcgataagttggattcactaactaat
-acggctgattgaaaactccactccggacctatatggtcgacctttatacgtaaccgatat
-aaaacttataggctggtatatcgagccttcctagcgcaatttcggatggggtttcttcta
-ctactcaacaacggaatagtctttgtttagtaaaccagagctcaggacgcccaatacgta
-ggagagcgctgtggagcatgtgtcattatggactggagcactcttaaatcactctgcgtg
-tgctaaacgatagatcataacatgtcctgagtaaattttcttgatacgtcgcaatatacc
-gttattagttaaacgttctcatccgtcatgcgtgaaatacggctgtcgtgctcagatata
-ctattagcgactcatctcgcctaacacgcacacgtataaactcggaatgactgccgctct
-tacatattagaaatacagactacaccacggaagcattgggtcattctcaaccgctgtata
-aaagatgattagtcttataataagattaccaaagaggcagaatcatgggtagtaaatcta
-ttattcaagtgattaccgtcgtgtaggcagggagtgaggacgagatggtactcaggacaa
-atattaaccggacgaagtggtttacgtcgtactttcactattagtagtaaatacaaggta
-acaccggggaatagtactaaatataatgatatctatcttcgggagaacgagtcgtctatt
-gctttgaacattctcaaggcgtaaaatgtgctgacttatagcatgatacaaccgattgtt
-acttttgtctattcaaaagattgaatagttttttatacaaaagccgcatacttatgacgg
-ctagtatacagtttcatcccctagcatcaatgctatggacagtattgaacttataggaaa
-ttcttctaatagggcaaatccgtcgtgatgcctattttttttcagtcacatcctcaaatg
-gcactagtattgtcgggatcccattaacaggctcaaccacgagctcacgcgaggacatgt
-agtccgtatctttaacgaagcgacagcgacagaactcccatggataaccaattataaggc
-ccgtaatcctctagacatcgtttaccaataaatccgctttctccgtaatcatgttgaata
-ccccagagtagtccagatgataaccgatgaaacacaagtctttctcaatgcacttacggt
-gaacttattaccgccaacgtagctcatcaaggttgcgacatctagttgtgtgtttgcgac
-gagcccagcgaacttcatcaactttcgtatattcaacgccttgtaattttactttaagac
-gcctggtgatgtagattcttagataatcagtttgttatcggctgtactttaccataattt
-cacaggtttcaggtcaagaagattatagctgtatatacagttccatgctcggtgcacaga
-aacgtgatcggataataatcaatcgcttatgtcgtctttaggcgtatccaatacatgccc
-cgataccgcagtgtatttcgacatgtaggtataccgtcgcatttgagctcgagtcaggac
-gtcagctagattagattccttaatagaatataccgacctctagtccgaactaaactatag
-ataacgccaacttcaggttaattgtctagtcgtctgtttgcagatgggattcttagatga
-gtgagtatcggccatattggttcgagcactttagtttttgatgcataggatatgcaatgt
-atagctgaaagtactttatctgtttcaaactcacattgattaaaccggtaaacctttaaa
-gactacaagaaaatattcagtgagggcaattttgtcaatcacaatcttccagctagagat
-acttcacaatttgtcttgaggctacgcaacattagacggattttcgcgttttattgaaat
-aatcgaggggcccaagagtatccatagttcattttgtaagatttctttacaggcttatta
-cagcttcttcagactcctacatgcttacgagttatatgctagcatgtgaacaatagatta
-atatacaggaaaacgtacattgagagagatgaccctacacagcgcaaccgttgagtactt
-tcattaaagggtaacgctctcgagacagcatccttaagatggccttattgtcaaatcatt
-tgcagaagtacgcaagatccctaaccaacgtagaagaatccctacaaacacatgagacgc
-ggtgaaaatagacagggtgttagtattcaatcttcggagtatcaatttcgccaatcttgg
-tgagaaagcataccctttcttcagagaaagaagatcaatcataacactatctttaacgag
-gtacgcacgcgcatcattacctgcctccatggatctttaggatagcggaaagtattggca
-gcgtattgtgatttcgttcctactttatcaatttcacattcatatacatgtcttttatca
-aaatcgccaataagataggatgagctatattagatgctagtagagttcgcgccaacatca
-tcgataggaatactcaggacagcgtgataggacttttcaatccctaatactctctataat
-tataactctctcttaagtttggaggcagtaacgcgctctatataatcagtttgctgcacc
-attcttcagcctctgatacatacaaataaattccacagcagtaagagggtttaattgaga
-catcttgggaacttaggattttactctaacatcaccgaaacgattattggataccgtacc
-taaacgaactttctcaaggcagtaatataggacatccgcaataacacaaatgctgcctcc
-ccaggagttatgtcttcctggaggctatatcttacacccactcactataggcaaactaaa
-gtttaaatgttgattgtctaaaaaaaagatagataagagttggccggcgtagcacatgcg
-aaagtgaatcgtaagctataattctctggacttgaagttctgtcctgttcctctgcaaga
-aacaaacttcctttaaagctatttacgacgcacatctcagcaagttataaacatgttgga
-agtttctagtcggaattcccaaagaacggatctatctaatgcattcctacatttttcctg
-tctgccgatggtgccatcctattcaaagaatttcttaaaagtagattaaatgggactttt
-aacaatgagtaaccttacgcctctaagggttcctcgagtgccatacaccagtcaggtccg
-agccacatacacggagaacattctaacatagcattctcaactcgatcatttgcaggttac
-ttctttcctatcctagtgctaaaaatcatacttgcaatcccatagcacggattaagaacc
-taagaaacaattcagtaaaacatgttcgaattcttggtatgggaacatcattgcagctat
-ggtctaacgcattaatgtttgggtacatcttccatcatataaacaggaagagtctgacga
-cagggagtgcttgcgatcatgtctatcattgtgaaatcaaattgtagctcacatgtcgtc
-tatgagagcgtgtatccgataagatttagaaaaatagaagtcgtataagatctcactgaa
-cttttgaatgaatgtgaagcatatatgatctgctttaataaaactttatccataggatac
-gtttccaaatcaattcaataattattagtcaaaatagataaggatgaacaacctgaaggc
-cgatcggacgtagaaagtggtcccatcactttgagttgatattgttgaaccacacgttat
-tatggttttcaaacagtctcaggatattgtatatacagataatccgataccagttgtctg
-acgcccctcttacgtaccccaccctttgtgacgtttaaagcagttgttcagtattttaaa
-ctaggcggcaactaatttggaaagaagcacagtggatatgtctaaattcttgttattcag
-gcctgaatttaatacaccgcatagttaacttcgcggtagagttgttcatcatgcctcctc
-taagctaccacttctatgatacaccaatagttgttctacggaatctgataattggccaag
-tcataaacttccgctgcgttcaacccccttgctcgaatatccaactcgaaaagacagcct
-tttggtgtccggaacaaatcagttacttcttttctgatgttaattctctgtggtcagata
-cagaccaaaaactccgcggatttaccatcctccaagaacaaatttgcatcaacatagcat
-tttggctacatattctaagtctcaatagtttaggttttcaactacattatcccaacatta
-ggattggaggaataatagctgggtaagtccccttgcgtctacaatcgactattttttatg
-aatatgcttctgccgcacctatggttattaaaaaagtcatgactttgaagaaccctgaaa
-agatagatgaatcaggtgtaatggcagcagccaaagagcatataattagcaacactctaa
-gaacattatagatatgatgatagcgatcgtcatgatgttatccggtcacaatagtagctt
-catcagctaattcgttttgccagtggtgacttgcgctggaagaatcgttatacggtccct
-tccctcttgatacggtgggggcttattcaaccgcgtggattgggttgtcatacttgcatt
-aaacgatgtaaaccatctagtagtcaactatactaaatcacaaaatagtgatcaatacat
-acccgcttcatggttttaaccatttaattgattaaagatattccgctaagaaccattatc
-tacctaaactgatcgccgtatcctagtagtttgaaatttgatgtaccgtaatgatcaacg
-aagtaaaacgttatattgtatgtagaataataggtcttggagctaaatgatgtgattggt
-agtgaagacttacccttacaactttaccggtttctcggaagaatatactagagaatcaat
-gcatgggctacataagcactttagtctaatgagataaaaaatacacgagtcttccatcat
-gaattttttgtcgaaaaactcgaacctggtaatttaaaccatatatctttatgtcgtcaa
-taactctcatatgttttatataacttcccaatcacgacttgtaactgcttgttcgactga
-gctgtttgagctatgaggccgggatccggttgagctacatctatttgctacaagaaaaat
-gaaagcacatttgttgggagttctggctacactcatagagaaataagtggcccgagtggg
-tgcggcctgcctccatattcaagtgtatcttaaaccaagtggttccaacgctcgcgctaa
-agaattaaagcctttatttcctccacggagtagcccgtaatccggttcgaaagagaccat
-tgaagttaattttcatatccagtgaagtttaggcacaagcatgtgttctgccacatgcct
-caaagcgctcttcaaccaagatatgattcatcctaacttcgatgaatgcgtctgtaacat
-aaatatagaaggaatgattcggcgagttaattttcgccttctccaacatggcatccctac
-gttcgttataaggaccatacatgtaggttttaaaggtttgcggttaatcgatatttacat
-catagaaattctatagtcaaatttacaagactctagatactcactcgttgcagccggcta
-ggaagcgctttgtaccttacttcccttttcgttgcgtaatatgaatttcatatagtaagt
-tcaaggcactcatacctccgtgaagagggtagatagactattaaagttgtttaatagtac
-gtattgatggaaatgacccgtaggagatttaccactcaatccacaagattcgctgctgtg
-cattatcaaaacagtgcatgtcgaaacatgggttgggtccttcaaacacgaatccaggta
-gagatacctttgcaattttt
diff --git a/vendor/regex-1.4.3/examples/regexdna-output.txt b/vendor/regex-1.4.3/examples/regexdna-output.txt
deleted file mode 100644 (file)
index d36baa5..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-agggtaaa|tttaccct 0
-[cgt]gggtaaa|tttaccc[acg] 3
-a[act]ggtaaa|tttacc[agt]t 9
-ag[act]gtaaa|tttac[agt]ct 8
-agg[act]taaa|ttta[agt]cct 10
-aggg[acg]aaa|ttt[cgt]ccct 3
-agggt[cgt]aa|tt[acg]accct 4
-agggta[cgt]a|t[acg]taccct 3
-agggtaa[cgt]|[acg]ttaccct 5
-
-101745
-100000
-133640
diff --git a/vendor/regex-1.4.3/examples/shootout-regex-dna-bytes.rs b/vendor/regex-1.4.3/examples/shootout-regex-dna-bytes.rs
deleted file mode 100644 (file)
index ac4c115..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-// The Computer Language Benchmarks Game
-// https://benchmarksgame-team.pages.debian.net/benchmarksgame/
-//
-// contributed by the Rust Project Developers
-// contributed by TeXitoi
-// contributed by BurntSushi
-
-extern crate regex;
-
-use std::io::{self, Read};
-use std::sync::Arc;
-use std::thread;
-
-macro_rules! regex {
-    ($re:expr) => {
-        ::regex::bytes::Regex::new($re).unwrap()
-    };
-}
-
-fn main() {
-    let mut seq = Vec::with_capacity(51 * (1 << 20));
-    io::stdin().read_to_end(&mut seq).unwrap();
-    let ilen = seq.len();
-
-    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, &b""[..]).into_owned();
-    let clen = seq.len();
-    let seq_arc = Arc::new(seq.clone());
-
-    let variants = vec![
-        regex!("agggtaaa|tttaccct"),
-        regex!("[cgt]gggtaaa|tttaccc[acg]"),
-        regex!("a[act]ggtaaa|tttacc[agt]t"),
-        regex!("ag[act]gtaaa|tttac[agt]ct"),
-        regex!("agg[act]taaa|ttta[agt]cct"),
-        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
-        regex!("agggt[cgt]aa|tt[acg]accct"),
-        regex!("agggta[cgt]a|t[acg]taccct"),
-        regex!("agggtaa[cgt]|[acg]ttaccct"),
-    ];
-    let mut counts = vec![];
-    for variant in variants {
-        let seq = seq_arc.clone();
-        let restr = variant.to_string();
-        let future = thread::spawn(move || variant.find_iter(&seq).count());
-        counts.push((restr, future));
-    }
-
-    let substs = vec![
-        (regex!("B"), &b"(c|g|t)"[..]),
-        (regex!("D"), &b"(a|g|t)"[..]),
-        (regex!("H"), &b"(a|c|t)"[..]),
-        (regex!("K"), &b"(g|t)"[..]),
-        (regex!("M"), &b"(a|c)"[..]),
-        (regex!("N"), &b"(a|c|g|t)"[..]),
-        (regex!("R"), &b"(a|g)"[..]),
-        (regex!("S"), &b"(c|g)"[..]),
-        (regex!("V"), &b"(a|c|g)"[..]),
-        (regex!("W"), &b"(a|t)"[..]),
-        (regex!("Y"), &b"(c|t)"[..]),
-    ];
-    let mut seq = seq;
-    for (re, replacement) in substs {
-        seq = re.replace_all(&seq, replacement).into_owned();
-    }
-
-    for (variant, count) in counts {
-        println!("{} {}", variant, count.join().unwrap());
-    }
-    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
-}
diff --git a/vendor/regex-1.4.3/examples/shootout-regex-dna-cheat.rs b/vendor/regex-1.4.3/examples/shootout-regex-dna-cheat.rs
deleted file mode 100644 (file)
index c7395b7..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-// The Computer Language Benchmarks Game
-// https://benchmarksgame-team.pages.debian.net/benchmarksgame/
-//
-// contributed by the Rust Project Developers
-// contributed by TeXitoi
-// contributed by BurntSushi
-
-// This technically solves the problem posed in the `regex-dna` benchmark, but
-// it cheats by combining all of the replacements into a single regex and
-// replacing them with a single linear scan. i.e., it re-implements
-// `replace_all`. As a result, this is around 25% faster. ---AG
-
-extern crate regex;
-
-use std::io::{self, Read};
-use std::sync::Arc;
-use std::thread;
-
-macro_rules! regex {
-    ($re:expr) => {
-        ::regex::Regex::new($re).unwrap()
-    };
-}
-
-fn main() {
-    let mut seq = String::with_capacity(50 * (1 << 20));
-    io::stdin().read_to_string(&mut seq).unwrap();
-    let ilen = seq.len();
-
-    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
-    let clen = seq.len();
-    let seq_arc = Arc::new(seq.clone());
-
-    let variants = vec![
-        regex!("agggtaaa|tttaccct"),
-        regex!("[cgt]gggtaaa|tttaccc[acg]"),
-        regex!("a[act]ggtaaa|tttacc[agt]t"),
-        regex!("ag[act]gtaaa|tttac[agt]ct"),
-        regex!("agg[act]taaa|ttta[agt]cct"),
-        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
-        regex!("agggt[cgt]aa|tt[acg]accct"),
-        regex!("agggta[cgt]a|t[acg]taccct"),
-        regex!("agggtaa[cgt]|[acg]ttaccct"),
-    ];
-    let mut counts = vec![];
-    for variant in variants {
-        let seq = seq_arc.clone();
-        let restr = variant.to_string();
-        let future = thread::spawn(move || variant.find_iter(&seq).count());
-        counts.push((restr, future));
-    }
-
-    let substs = vec![
-        (b'B', "(c|g|t)"),
-        (b'D', "(a|g|t)"),
-        (b'H', "(a|c|t)"),
-        (b'K', "(g|t)"),
-        (b'M', "(a|c)"),
-        (b'N', "(a|c|g|t)"),
-        (b'R', "(a|g)"),
-        (b'S', "(c|g)"),
-        (b'V', "(a|c|g)"),
-        (b'W', "(a|t)"),
-        (b'Y', "(c|t)"),
-    ]; // combined into one regex in `replace_all`
-    let seq = replace_all(&seq, substs);
-
-    for (variant, count) in counts {
-        println!("{} {}", variant, count.join().unwrap());
-    }
-    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
-}
-
-fn replace_all(text: &str, substs: Vec<(u8, &str)>) -> String {
-    let mut replacements = vec![""; 256];
-    let mut alternates = vec![];
-    for (re, replacement) in substs {
-        replacements[re as usize] = replacement;
-        alternates.push((re as char).to_string());
-    }
-
-    let re = regex!(&alternates.join("|"));
-    let mut new = String::with_capacity(text.len());
-    let mut last_match = 0;
-    for m in re.find_iter(text) {
-        new.push_str(&text[last_match..m.start()]);
-        new.push_str(replacements[text.as_bytes()[m.start()] as usize]);
-        last_match = m.end();
-    }
-    new.push_str(&text[last_match..]);
-    new
-}
diff --git a/vendor/regex-1.4.3/examples/shootout-regex-dna-replace.rs b/vendor/regex-1.4.3/examples/shootout-regex-dna-replace.rs
deleted file mode 100644 (file)
index 681e077..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-extern crate regex;
-
-use std::io::{self, Read};
-
-macro_rules! regex {
-    ($re:expr) => {{
-        use regex::internal::ExecBuilder;
-        ExecBuilder::new($re).build().unwrap().into_regex()
-    }};
-}
-
-fn main() {
-    let mut seq = String::with_capacity(50 * (1 << 20));
-    io::stdin().read_to_string(&mut seq).unwrap();
-    let ilen = seq.len();
-
-    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
-    println!("original: {}, replaced: {}", ilen, seq.len());
-}
diff --git a/vendor/regex-1.4.3/examples/shootout-regex-dna-single-cheat.rs b/vendor/regex-1.4.3/examples/shootout-regex-dna-single-cheat.rs
deleted file mode 100644 (file)
index 04ed05a..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-// The Computer Language Benchmarks Game
-// https://benchmarksgame-team.pages.debian.net/benchmarksgame/
-//
-// contributed by the Rust Project Developers
-// contributed by TeXitoi
-// contributed by BurntSushi
-
-extern crate regex;
-
-use std::io::{self, Read};
-
-macro_rules! regex {
-    ($re:expr) => {
-        ::regex::Regex::new($re).unwrap()
-    };
-}
-
-fn main() {
-    let mut seq = String::with_capacity(50 * (1 << 20));
-    io::stdin().read_to_string(&mut seq).unwrap();
-    let ilen = seq.len();
-
-    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
-    let clen = seq.len();
-
-    let variants = vec![
-        regex!("agggtaaa|tttaccct"),
-        regex!("[cgt]gggtaaa|tttaccc[acg]"),
-        regex!("a[act]ggtaaa|tttacc[agt]t"),
-        regex!("ag[act]gtaaa|tttac[agt]ct"),
-        regex!("agg[act]taaa|ttta[agt]cct"),
-        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
-        regex!("agggt[cgt]aa|tt[acg]accct"),
-        regex!("agggta[cgt]a|t[acg]taccct"),
-        regex!("agggtaa[cgt]|[acg]ttaccct"),
-    ];
-    for re in variants {
-        println!("{} {}", re.to_string(), re.find_iter(&seq).count());
-    }
-
-    let substs = vec![
-        (b'B', "(c|g|t)"),
-        (b'D', "(a|g|t)"),
-        (b'H', "(a|c|t)"),
-        (b'K', "(g|t)"),
-        (b'M', "(a|c)"),
-        (b'N', "(a|c|g|t)"),
-        (b'R', "(a|g)"),
-        (b'S', "(c|g)"),
-        (b'V', "(a|c|g)"),
-        (b'W', "(a|t)"),
-        (b'Y', "(c|t)"),
-    ]; // combined into one regex in `replace_all`
-    let seq = replace_all(&seq, substs);
-
-    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
-}
-
-fn replace_all(text: &str, substs: Vec<(u8, &str)>) -> String {
-    let mut replacements = vec![""; 256];
-    let mut alternates = vec![];
-    for (re, replacement) in substs {
-        replacements[re as usize] = replacement;
-        alternates.push((re as char).to_string());
-    }
-
-    let re = regex!(&alternates.join("|"));
-    let mut new = String::with_capacity(text.len());
-    let mut last_match = 0;
-    for m in re.find_iter(text) {
-        new.push_str(&text[last_match..m.start()]);
-        new.push_str(replacements[text.as_bytes()[m.start()] as usize]);
-        last_match = m.end();
-    }
-    new.push_str(&text[last_match..]);
-    new
-}
diff --git a/vendor/regex-1.4.3/examples/shootout-regex-dna-single.rs b/vendor/regex-1.4.3/examples/shootout-regex-dna-single.rs
deleted file mode 100644 (file)
index a70c711..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-// The Computer Language Benchmarks Game
-// https://benchmarksgame-team.pages.debian.net/benchmarksgame/
-//
-// contributed by the Rust Project Developers
-// contributed by TeXitoi
-// contributed by BurntSushi
-
-extern crate regex;
-
-use std::io::{self, Read};
-
-macro_rules! regex {
-    ($re:expr) => {
-        ::regex::Regex::new($re).unwrap()
-    };
-}
-
-fn main() {
-    let mut seq = String::with_capacity(50 * (1 << 20));
-    io::stdin().read_to_string(&mut seq).unwrap();
-    let ilen = seq.len();
-
-    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
-    let clen = seq.len();
-
-    let variants = vec![
-        regex!("agggtaaa|tttaccct"),
-        regex!("[cgt]gggtaaa|tttaccc[acg]"),
-        regex!("a[act]ggtaaa|tttacc[agt]t"),
-        regex!("ag[act]gtaaa|tttac[agt]ct"),
-        regex!("agg[act]taaa|ttta[agt]cct"),
-        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
-        regex!("agggt[cgt]aa|tt[acg]accct"),
-        regex!("agggta[cgt]a|t[acg]taccct"),
-        regex!("agggtaa[cgt]|[acg]ttaccct"),
-    ];
-    for re in variants {
-        println!("{} {}", re.to_string(), re.find_iter(&seq).count());
-    }
-
-    let substs = vec![
-        (regex!("B"), "(c|g|t)"),
-        (regex!("D"), "(a|g|t)"),
-        (regex!("H"), "(a|c|t)"),
-        (regex!("K"), "(g|t)"),
-        (regex!("M"), "(a|c)"),
-        (regex!("N"), "(a|c|g|t)"),
-        (regex!("R"), "(a|g)"),
-        (regex!("S"), "(c|g)"),
-        (regex!("V"), "(a|c|g)"),
-        (regex!("W"), "(a|t)"),
-        (regex!("Y"), "(c|t)"),
-    ];
-    let mut seq = seq;
-    for (re, replacement) in substs {
-        seq = re.replace_all(&seq, replacement).into_owned();
-    }
-    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
-}
diff --git a/vendor/regex-1.4.3/examples/shootout-regex-dna.rs b/vendor/regex-1.4.3/examples/shootout-regex-dna.rs
deleted file mode 100644 (file)
index 4527422..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-// The Computer Language Benchmarks Game
-// https://benchmarksgame-team.pages.debian.net/benchmarksgame/
-//
-// contributed by the Rust Project Developers
-// contributed by TeXitoi
-// contributed by BurntSushi
-
-extern crate regex;
-
-use std::io::{self, Read};
-use std::sync::Arc;
-use std::thread;
-
-macro_rules! regex {
-    ($re:expr) => {
-        ::regex::Regex::new($re).unwrap()
-    };
-}
-
-fn main() {
-    let mut seq = String::with_capacity(51 * (1 << 20));
-    io::stdin().read_to_string(&mut seq).unwrap();
-    let ilen = seq.len();
-
-    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
-    let clen = seq.len();
-    let seq_arc = Arc::new(seq.clone());
-
-    let variants = vec![
-        regex!("agggtaaa|tttaccct"),
-        regex!("[cgt]gggtaaa|tttaccc[acg]"),
-        regex!("a[act]ggtaaa|tttacc[agt]t"),
-        regex!("ag[act]gtaaa|tttac[agt]ct"),
-        regex!("agg[act]taaa|ttta[agt]cct"),
-        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
-        regex!("agggt[cgt]aa|tt[acg]accct"),
-        regex!("agggta[cgt]a|t[acg]taccct"),
-        regex!("agggtaa[cgt]|[acg]ttaccct"),
-    ];
-    let mut counts = vec![];
-    for variant in variants {
-        let seq = seq_arc.clone();
-        let restr = variant.to_string();
-        let future = thread::spawn(move || variant.find_iter(&seq).count());
-        counts.push((restr, future));
-    }
-
-    let substs = vec![
-        (regex!("B"), "(c|g|t)"),
-        (regex!("D"), "(a|g|t)"),
-        (regex!("H"), "(a|c|t)"),
-        (regex!("K"), "(g|t)"),
-        (regex!("M"), "(a|c)"),
-        (regex!("N"), "(a|c|g|t)"),
-        (regex!("R"), "(a|g)"),
-        (regex!("S"), "(c|g)"),
-        (regex!("V"), "(a|c|g)"),
-        (regex!("W"), "(a|t)"),
-        (regex!("Y"), "(c|t)"),
-    ];
-    let mut seq = seq;
-    for (re, replacement) in substs {
-        seq = re.replace_all(&seq, replacement).into_owned();
-    }
-
-    for (variant, count) in counts {
-        println!("{} {}", variant, count.join().unwrap());
-    }
-    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
-}
diff --git a/vendor/regex-1.4.3/rustfmt.toml b/vendor/regex-1.4.3/rustfmt.toml
deleted file mode 100644 (file)
index aa37a21..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-max_width = 79
-use_small_heuristics = "max"
diff --git a/vendor/regex-1.4.3/src/backtrack.rs b/vendor/regex-1.4.3/src/backtrack.rs
deleted file mode 100644 (file)
index 2eaeb72..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-// This is the backtracking matching engine. It has the same exact capability
-// as the full NFA simulation, except it is artificially restricted to small
-// regexes on small inputs because of its memory requirements.
-//
-// In particular, this is a *bounded* backtracking engine. It retains worst
-// case linear time by keeping track of the states that it has visited (using a
-// bitmap). Namely, once a state is visited, it is never visited again. Since a
-// state is keyed by `(instruction index, input index)`, we have that its time
-// complexity is `O(mn)` (i.e., linear in the size of the search text).
-//
-// The backtracking engine can beat out the NFA simulation on small
-// regexes/inputs because it doesn't have to keep track of multiple copies of
-// the capture groups. In benchmarks, the backtracking engine is roughly twice
-// as fast as the full NFA simulation. Note though that its performance doesn't
-// scale, even if you're willing to live with the memory requirements. Namely,
-// the bitset has to be zeroed on each execution, which becomes quite expensive
-// on large bitsets.
-
-use exec::ProgramCache;
-use input::{Input, InputAt};
-use prog::{InstPtr, Program};
-use re_trait::Slot;
-
-type Bits = u32;
-
-const BIT_SIZE: usize = 32;
-const MAX_SIZE_BYTES: usize = 256 * (1 << 10); // 256 KB
-
-/// Returns true iff the given regex and input should be executed by this
-/// engine with reasonable memory usage.
-pub fn should_exec(num_insts: usize, text_len: usize) -> bool {
-    // Total memory usage in bytes is determined by:
-    //
-    //   ((len(insts) * (len(input) + 1) + bits - 1) / bits) * (size_of(u32))
-    //
-    // The actual limit picked is pretty much a heuristic.
-    // See: https://github.com/rust-lang/regex/issues/215
-    let size = ((num_insts * (text_len + 1) + BIT_SIZE - 1) / BIT_SIZE) * 4;
-    size <= MAX_SIZE_BYTES
-}
-
-/// A backtracking matching engine.
-#[derive(Debug)]
-pub struct Bounded<'a, 'm, 'r, 's, I> {
-    prog: &'r Program,
-    input: I,
-    matches: &'m mut [bool],
-    slots: &'s mut [Slot],
-    m: &'a mut Cache,
-}
-
-/// Shared cached state between multiple invocations of a backtracking engine
-/// in the same thread.
-#[derive(Clone, Debug)]
-pub struct Cache {
-    jobs: Vec<Job>,
-    visited: Vec<Bits>,
-}
-
-impl Cache {
-    /// Create new empty cache for the backtracking engine.
-    pub fn new(_prog: &Program) -> Self {
-        Cache { jobs: vec![], visited: vec![] }
-    }
-}
-
-/// A job is an explicit unit of stack space in the backtracking engine.
-///
-/// The "normal" representation is a single state transition, which corresponds
-/// to an NFA state and a character in the input. However, the backtracking
-/// engine must keep track of old capture group values. We use the explicit
-/// stack to do it.
-#[derive(Clone, Copy, Debug)]
-enum Job {
-    Inst { ip: InstPtr, at: InputAt },
-    SaveRestore { slot: usize, old_pos: Option<usize> },
-}
-
-impl<'a, 'm, 'r, 's, I: Input> Bounded<'a, 'm, 'r, 's, I> {
-    /// Execute the backtracking matching engine.
-    ///
-    /// If there's a match, `exec` returns `true` and populates the given
-    /// captures accordingly.
-    pub fn exec(
-        prog: &'r Program,
-        cache: &ProgramCache,
-        matches: &'m mut [bool],
-        slots: &'s mut [Slot],
-        input: I,
-        start: usize,
-        end: usize,
-    ) -> bool {
-        let mut cache = cache.borrow_mut();
-        let cache = &mut cache.backtrack;
-        let start = input.at(start);
-        let mut b = Bounded {
-            prog: prog,
-            input: input,
-            matches: matches,
-            slots: slots,
-            m: cache,
-        };
-        b.exec_(start, end)
-    }
-
-    /// Clears the cache such that the backtracking engine can be executed
-    /// on some input of fixed length.
-    fn clear(&mut self) {
-        // Reset the job memory so that we start fresh.
-        self.m.jobs.clear();
-
-        // Now we need to clear the bit state set.
-        // We do this by figuring out how much space we need to keep track
-        // of the states we've visited.
-        // Then we reset all existing allocated space to 0.
-        // Finally, we request more space if we need it.
-        //
-        // This is all a little circuitous, but doing this unsafely
-        // doesn't seem to have a measurable impact on performance.
-        // (Probably because backtracking is limited to such small
-        // inputs/regexes in the first place.)
-        let visited_len =
-            (self.prog.len() * (self.input.len() + 1) + BIT_SIZE - 1)
-                / BIT_SIZE;
-        self.m.visited.truncate(visited_len);
-        for v in &mut self.m.visited {
-            *v = 0;
-        }
-        if visited_len > self.m.visited.len() {
-            let len = self.m.visited.len();
-            self.m.visited.reserve_exact(visited_len - len);
-            for _ in 0..(visited_len - len) {
-                self.m.visited.push(0);
-            }
-        }
-    }
-
-    /// Start backtracking at the given position in the input, but also look
-    /// for literal prefixes.
-    fn exec_(&mut self, mut at: InputAt, end: usize) -> bool {
-        self.clear();
-        // If this is an anchored regex at the beginning of the input, then
-        // we're either already done or we only need to try backtracking once.
-        if self.prog.is_anchored_start {
-            return if !at.is_start() { false } else { self.backtrack(at) };
-        }
-        let mut matched = false;
-        loop {
-            if !self.prog.prefixes.is_empty() {
-                at = match self.input.prefix_at(&self.prog.prefixes, at) {
-                    None => break,
-                    Some(at) => at,
-                };
-            }
-            matched = self.backtrack(at) || matched;
-            if matched && self.prog.matches.len() == 1 {
-                return true;
-            }
-            if at.pos() >= end {
-                break;
-            }
-            at = self.input.at(at.next_pos());
-        }
-        matched
-    }
-
-    /// The main backtracking loop starting at the given input position.
-    fn backtrack(&mut self, start: InputAt) -> bool {
-        // N.B. We use an explicit stack to avoid recursion.
-        // To avoid excessive pushing and popping, most transitions are handled
-        // in the `step` helper function, which only pushes to the stack when
-        // there's a capture or a branch.
-        let mut matched = false;
-        self.m.jobs.push(Job::Inst { ip: 0, at: start });
-        while let Some(job) = self.m.jobs.pop() {
-            match job {
-                Job::Inst { ip, at } => {
-                    if self.step(ip, at) {
-                        // Only quit if we're matching one regex.
-                        // If we're matching a regex set, then mush on and
-                        // try to find other matches (if we want them).
-                        if self.prog.matches.len() == 1 {
-                            return true;
-                        }
-                        matched = true;
-                    }
-                }
-                Job::SaveRestore { slot, old_pos } => {
-                    if slot < self.slots.len() {
-                        self.slots[slot] = old_pos;
-                    }
-                }
-            }
-        }
-        matched
-    }
-
-    fn step(&mut self, mut ip: InstPtr, mut at: InputAt) -> bool {
-        use prog::Inst::*;
-        loop {
-            // This loop is an optimization to avoid constantly pushing/popping
-            // from the stack. Namely, if we're pushing a job only to run it
-            // next, avoid the push and just mutate `ip` (and possibly `at`)
-            // in place.
-            if self.has_visited(ip, at) {
-                return false;
-            }
-            match self.prog[ip] {
-                Match(slot) => {
-                    if slot < self.matches.len() {
-                        self.matches[slot] = true;
-                    }
-                    return true;
-                }
-                Save(ref inst) => {
-                    if let Some(&old_pos) = self.slots.get(inst.slot) {
-                        // If this path doesn't work out, then we save the old
-                        // capture index (if one exists) in an alternate
-                        // job. If the next path fails, then the alternate
-                        // job is popped and the old capture index is restored.
-                        self.m.jobs.push(Job::SaveRestore {
-                            slot: inst.slot,
-                            old_pos: old_pos,
-                        });
-                        self.slots[inst.slot] = Some(at.pos());
-                    }
-                    ip = inst.goto;
-                }
-                Split(ref inst) => {
-                    self.m.jobs.push(Job::Inst { ip: inst.goto2, at: at });
-                    ip = inst.goto1;
-                }
-                EmptyLook(ref inst) => {
-                    if self.input.is_empty_match(at, inst) {
-                        ip = inst.goto;
-                    } else {
-                        return false;
-                    }
-                }
-                Char(ref inst) => {
-                    if inst.c == at.char() {
-                        ip = inst.goto;
-                        at = self.input.at(at.next_pos());
-                    } else {
-                        return false;
-                    }
-                }
-                Ranges(ref inst) => {
-                    if inst.matches(at.char()) {
-                        ip = inst.goto;
-                        at = self.input.at(at.next_pos());
-                    } else {
-                        return false;
-                    }
-                }
-                Bytes(ref inst) => {
-                    if let Some(b) = at.byte() {
-                        if inst.matches(b) {
-                            ip = inst.goto;
-                            at = self.input.at(at.next_pos());
-                            continue;
-                        }
-                    }
-                    return false;
-                }
-            }
-        }
-    }
-
-    fn has_visited(&mut self, ip: InstPtr, at: InputAt) -> bool {
-        let k = ip * (self.input.len() + 1) + at.pos();
-        let k1 = k / BIT_SIZE;
-        let k2 = usize_to_u32(1 << (k & (BIT_SIZE - 1)));
-        if self.m.visited[k1] & k2 == 0 {
-            self.m.visited[k1] |= k2;
-            false
-        } else {
-            true
-        }
-    }
-}
-
-fn usize_to_u32(n: usize) -> u32 {
-    if (n as u64) > (::std::u32::MAX as u64) {
-        panic!("BUG: {} is too big to fit into u32", n)
-    }
-    n as u32
-}
diff --git a/vendor/regex-1.4.3/src/cache.rs b/vendor/regex-1.4.3/src/cache.rs
deleted file mode 100644 (file)
index dbb7e64..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-// This module defines a common API for caching internal runtime state.
-// The `thread_local` crate provides an extremely optimized version of this.
-// However, if the perf-cache feature is disabled, then we drop the
-// thread_local dependency and instead use a pretty naive caching mechanism
-// with a mutex.
-//
-// Strictly speaking, the CachedGuard isn't necessary for the much more
-// flexible thread_local API, but implementing thread_local's API doesn't
-// seem possible in purely safe code.
-
-pub use self::imp::{Cached, CachedGuard};
-
-#[cfg(feature = "perf-cache")]
-mod imp {
-    use thread_local::CachedThreadLocal;
-
-    #[derive(Debug)]
-    pub struct Cached<T: Send>(CachedThreadLocal<T>);
-
-    #[derive(Debug)]
-    pub struct CachedGuard<'a, T: 'a>(&'a T);
-
-    impl<T: Send> Cached<T> {
-        pub fn new() -> Cached<T> {
-            Cached(CachedThreadLocal::new())
-        }
-
-        pub fn get_or(&self, create: impl FnOnce() -> T) -> CachedGuard<T> {
-            CachedGuard(self.0.get_or(|| create()))
-        }
-    }
-
-    impl<'a, T: Send> CachedGuard<'a, T> {
-        pub fn value(&self) -> &T {
-            self.0
-        }
-    }
-}
-
-#[cfg(not(feature = "perf-cache"))]
-mod imp {
-    use std::marker::PhantomData;
-    use std::panic::UnwindSafe;
-    use std::sync::Mutex;
-
-    #[derive(Debug)]
-    pub struct Cached<T: Send> {
-        stack: Mutex<Vec<T>>,
-        /// When perf-cache is enabled, the thread_local crate is used, and
-        /// its CachedThreadLocal impls Send, Sync and UnwindSafe, but NOT
-        /// RefUnwindSafe. However, a Mutex impls RefUnwindSafe. So in order
-        /// to keep the APIs consistent regardless of whether perf-cache is
-        /// enabled, we force this type to NOT impl RefUnwindSafe too.
-        ///
-        /// Ideally, we should always impl RefUnwindSafe, but it seems a little
-        /// tricky to do that right now.
-        ///
-        /// See also: https://github.com/rust-lang/regex/issues/576
-        _phantom: PhantomData<Box<dyn Send + Sync + UnwindSafe>>,
-    }
-
-    #[derive(Debug)]
-    pub struct CachedGuard<'a, T: 'a + Send> {
-        cache: &'a Cached<T>,
-        value: Option<T>,
-    }
-
-    impl<T: Send> Cached<T> {
-        pub fn new() -> Cached<T> {
-            Cached { stack: Mutex::new(vec![]), _phantom: PhantomData }
-        }
-
-        pub fn get_or(&self, create: impl FnOnce() -> T) -> CachedGuard<T> {
-            let mut stack = self.stack.lock().unwrap();
-            match stack.pop() {
-                None => CachedGuard { cache: self, value: Some(create()) },
-                Some(value) => CachedGuard { cache: self, value: Some(value) },
-            }
-        }
-
-        fn put(&self, value: T) {
-            let mut stack = self.stack.lock().unwrap();
-            stack.push(value);
-        }
-    }
-
-    impl<'a, T: Send> CachedGuard<'a, T> {
-        pub fn value(&self) -> &T {
-            self.value.as_ref().unwrap()
-        }
-    }
-
-    impl<'a, T: Send> Drop for CachedGuard<'a, T> {
-        fn drop(&mut self) {
-            if let Some(value) = self.value.take() {
-                self.cache.put(value);
-            }
-        }
-    }
-}
diff --git a/vendor/regex-1.4.3/src/compile.rs b/vendor/regex-1.4.3/src/compile.rs
deleted file mode 100644 (file)
index 9ffd347..0000000
+++ /dev/null
@@ -1,1226 +0,0 @@
-use std::collections::HashMap;
-use std::fmt;
-use std::iter;
-use std::result;
-use std::sync::Arc;
-
-use syntax::hir::{self, Hir};
-use syntax::is_word_byte;
-use syntax::utf8::{Utf8Range, Utf8Sequence, Utf8Sequences};
-
-use prog::{
-    EmptyLook, Inst, InstBytes, InstChar, InstEmptyLook, InstPtr, InstRanges,
-    InstSave, InstSplit, Program,
-};
-
-use Error;
-
-type Result = result::Result<Patch, Error>;
-type ResultOrEmpty = result::Result<Option<Patch>, Error>;
-
-#[derive(Debug)]
-struct Patch {
-    hole: Hole,
-    entry: InstPtr,
-}
-
-/// A compiler translates a regular expression AST to a sequence of
-/// instructions. The sequence of instructions represents an NFA.
-// `Compiler` is only public via the `internal` module, so avoid deriving
-// `Debug`.
-#[allow(missing_debug_implementations)]
-pub struct Compiler {
-    insts: Vec<MaybeInst>,
-    compiled: Program,
-    capture_name_idx: HashMap<String, usize>,
-    num_exprs: usize,
-    size_limit: usize,
-    suffix_cache: SuffixCache,
-    utf8_seqs: Option<Utf8Sequences>,
-    byte_classes: ByteClassSet,
-}
-
-impl Compiler {
-    /// Create a new regular expression compiler.
-    ///
-    /// Various options can be set before calling `compile` on an expression.
-    pub fn new() -> Self {
-        Compiler {
-            insts: vec![],
-            compiled: Program::new(),
-            capture_name_idx: HashMap::new(),
-            num_exprs: 0,
-            size_limit: 10 * (1 << 20),
-            suffix_cache: SuffixCache::new(1000),
-            utf8_seqs: Some(Utf8Sequences::new('\x00', '\x00')),
-            byte_classes: ByteClassSet::new(),
-        }
-    }
-
-    /// The size of the resulting program is limited by size_limit. If
-    /// the program approximately exceeds the given size (in bytes), then
-    /// compilation will stop and return an error.
-    pub fn size_limit(mut self, size_limit: usize) -> Self {
-        self.size_limit = size_limit;
-        self
-    }
-
-    /// If bytes is true, then the program is compiled as a byte based
-    /// automaton, which incorporates UTF-8 decoding into the machine. If it's
-    /// false, then the automaton is Unicode scalar value based, e.g., an
-    /// engine utilizing such an automaton is responsible for UTF-8 decoding.
-    ///
-    /// The specific invariant is that when returning a byte based machine,
-    /// the neither the `Char` nor `Ranges` instructions are produced.
-    /// Conversely, when producing a Unicode scalar value machine, the `Bytes`
-    /// instruction is never produced.
-    ///
-    /// Note that `dfa(true)` implies `bytes(true)`.
-    pub fn bytes(mut self, yes: bool) -> Self {
-        self.compiled.is_bytes = yes;
-        self
-    }
-
-    /// When disabled, the program compiled may match arbitrary bytes.
-    ///
-    /// When enabled (the default), all compiled programs exclusively match
-    /// valid UTF-8 bytes.
-    pub fn only_utf8(mut self, yes: bool) -> Self {
-        self.compiled.only_utf8 = yes;
-        self
-    }
-
-    /// When set, the machine returned is suitable for use in the DFA matching
-    /// engine.
-    ///
-    /// In particular, this ensures that if the regex is not anchored in the
-    /// beginning, then a preceding `.*?` is included in the program. (The NFA
-    /// based engines handle the preceding `.*?` explicitly, which is difficult
-    /// or impossible in the DFA engine.)
-    pub fn dfa(mut self, yes: bool) -> Self {
-        self.compiled.is_dfa = yes;
-        self
-    }
-
-    /// When set, the machine returned is suitable for matching text in
-    /// reverse. In particular, all concatenations are flipped.
-    pub fn reverse(mut self, yes: bool) -> Self {
-        self.compiled.is_reverse = yes;
-        self
-    }
-
-    /// Compile a regular expression given its AST.
-    ///
-    /// The compiler is guaranteed to succeed unless the program exceeds the
-    /// specified size limit. If the size limit is exceeded, then compilation
-    /// stops and returns an error.
-    pub fn compile(mut self, exprs: &[Hir]) -> result::Result<Program, Error> {
-        debug_assert!(!exprs.is_empty());
-        self.num_exprs = exprs.len();
-        if exprs.len() == 1 {
-            self.compile_one(&exprs[0])
-        } else {
-            self.compile_many(exprs)
-        }
-    }
-
-    fn compile_one(mut self, expr: &Hir) -> result::Result<Program, Error> {
-        // If we're compiling a forward DFA and we aren't anchored, then
-        // add a `.*?` before the first capture group.
-        // Other matching engines handle this by baking the logic into the
-        // matching engine itself.
-        let mut dotstar_patch = Patch { hole: Hole::None, entry: 0 };
-        self.compiled.is_anchored_start = expr.is_anchored_start();
-        self.compiled.is_anchored_end = expr.is_anchored_end();
-        if self.compiled.needs_dotstar() {
-            dotstar_patch = self.c_dotstar()?;
-            self.compiled.start = dotstar_patch.entry;
-        }
-        self.compiled.captures = vec![None];
-        let patch = self.c_capture(0, expr)?.unwrap_or(self.next_inst());
-        if self.compiled.needs_dotstar() {
-            self.fill(dotstar_patch.hole, patch.entry);
-        } else {
-            self.compiled.start = patch.entry;
-        }
-        self.fill_to_next(patch.hole);
-        self.compiled.matches = vec![self.insts.len()];
-        self.push_compiled(Inst::Match(0));
-        self.compile_finish()
-    }
-
-    fn compile_many(
-        mut self,
-        exprs: &[Hir],
-    ) -> result::Result<Program, Error> {
-        debug_assert!(exprs.len() > 1);
-
-        self.compiled.is_anchored_start =
-            exprs.iter().all(|e| e.is_anchored_start());
-        self.compiled.is_anchored_end =
-            exprs.iter().all(|e| e.is_anchored_end());
-        let mut dotstar_patch = Patch { hole: Hole::None, entry: 0 };
-        if self.compiled.needs_dotstar() {
-            dotstar_patch = self.c_dotstar()?;
-            self.compiled.start = dotstar_patch.entry;
-        } else {
-            self.compiled.start = 0; // first instruction is always split
-        }
-        self.fill_to_next(dotstar_patch.hole);
-
-        let mut prev_hole = Hole::None;
-        for (i, expr) in exprs[0..exprs.len() - 1].iter().enumerate() {
-            self.fill_to_next(prev_hole);
-            let split = self.push_split_hole();
-            let Patch { hole, entry } =
-                self.c_capture(0, expr)?.unwrap_or(self.next_inst());
-            self.fill_to_next(hole);
-            self.compiled.matches.push(self.insts.len());
-            self.push_compiled(Inst::Match(i));
-            prev_hole = self.fill_split(split, Some(entry), None);
-        }
-        let i = exprs.len() - 1;
-        let Patch { hole, entry } =
-            self.c_capture(0, &exprs[i])?.unwrap_or(self.next_inst());
-        self.fill(prev_hole, entry);
-        self.fill_to_next(hole);
-        self.compiled.matches.push(self.insts.len());
-        self.push_compiled(Inst::Match(i));
-        self.compile_finish()
-    }
-
-    fn compile_finish(mut self) -> result::Result<Program, Error> {
-        self.compiled.insts =
-            self.insts.into_iter().map(|inst| inst.unwrap()).collect();
-        self.compiled.byte_classes = self.byte_classes.byte_classes();
-        self.compiled.capture_name_idx = Arc::new(self.capture_name_idx);
-        Ok(self.compiled)
-    }
-
-    /// Compile expr into self.insts, returning a patch on success,
-    /// or an error if we run out of memory.
-    ///
-    /// All of the c_* methods of the compiler share the contract outlined
-    /// here.
-    ///
-    /// The main thing that a c_* method does is mutate `self.insts`
-    /// to add a list of mostly compiled instructions required to execute
-    /// the given expression. `self.insts` contains MaybeInsts rather than
-    /// Insts because there is some backpatching required.
-    ///
-    /// The `Patch` value returned by each c_* method provides metadata
-    /// about the compiled instructions emitted to `self.insts`. The
-    /// `entry` member of the patch refers to the first instruction
-    /// (the entry point), while the `hole` member contains zero or
-    /// more offsets to partial instructions that need to be backpatched.
-    /// The c_* routine can't know where its list of instructions are going to
-    /// jump to after execution, so it is up to the caller to patch
-    /// these jumps to point to the right place. So compiling some
-    /// expression, e, we would end up with a situation that looked like:
-    ///
-    /// ```text
-    /// self.insts = [ ..., i1, i2, ..., iexit1, ..., iexitn, ...]
-    ///                     ^              ^             ^
-    ///                     |                \         /
-    ///                   entry                \     /
-    ///                                         hole
-    /// ```
-    ///
-    /// To compile two expressions, e1 and e2, concatenated together we
-    /// would do:
-    ///
-    /// ```ignore
-    /// let patch1 = self.c(e1);
-    /// let patch2 = self.c(e2);
-    /// ```
-    ///
-    /// while leaves us with a situation that looks like
-    ///
-    /// ```text
-    /// self.insts = [ ..., i1, ..., iexit1, ..., i2, ..., iexit2 ]
-    ///                     ^        ^            ^        ^
-    ///                     |        |            |        |
-    ///                entry1        hole1   entry2        hole2
-    /// ```
-    ///
-    /// Then to merge the two patches together into one we would backpatch
-    /// hole1 with entry2 and return a new patch that enters at entry1
-    /// and has hole2 for a hole. In fact, if you look at the c_concat
-    /// method you will see that it does exactly this, though it handles
-    /// a list of expressions rather than just the two that we use for
-    /// an example.
-    ///
-    /// Ok(None) is returned when an expression is compiled to no
-    /// instruction, and so no patch.entry value makes sense.
-    fn c(&mut self, expr: &Hir) -> ResultOrEmpty {
-        use prog;
-        use syntax::hir::HirKind::*;
-
-        self.check_size()?;
-        match *expr.kind() {
-            Empty => Ok(None),
-            Literal(hir::Literal::Unicode(c)) => self.c_char(c),
-            Literal(hir::Literal::Byte(b)) => {
-                assert!(self.compiled.uses_bytes());
-                self.c_byte(b)
-            }
-            Class(hir::Class::Unicode(ref cls)) => self.c_class(cls.ranges()),
-            Class(hir::Class::Bytes(ref cls)) => {
-                if self.compiled.uses_bytes() {
-                    self.c_class_bytes(cls.ranges())
-                } else {
-                    assert!(cls.is_all_ascii());
-                    let mut char_ranges = vec![];
-                    for r in cls.iter() {
-                        let (s, e) = (r.start() as char, r.end() as char);
-                        char_ranges.push(hir::ClassUnicodeRange::new(s, e));
-                    }
-                    self.c_class(&char_ranges)
-                }
-            }
-            Anchor(hir::Anchor::StartLine) if self.compiled.is_reverse => {
-                self.byte_classes.set_range(b'\n', b'\n');
-                self.c_empty_look(prog::EmptyLook::EndLine)
-            }
-            Anchor(hir::Anchor::StartLine) => {
-                self.byte_classes.set_range(b'\n', b'\n');
-                self.c_empty_look(prog::EmptyLook::StartLine)
-            }
-            Anchor(hir::Anchor::EndLine) if self.compiled.is_reverse => {
-                self.byte_classes.set_range(b'\n', b'\n');
-                self.c_empty_look(prog::EmptyLook::StartLine)
-            }
-            Anchor(hir::Anchor::EndLine) => {
-                self.byte_classes.set_range(b'\n', b'\n');
-                self.c_empty_look(prog::EmptyLook::EndLine)
-            }
-            Anchor(hir::Anchor::StartText) if self.compiled.is_reverse => {
-                self.c_empty_look(prog::EmptyLook::EndText)
-            }
-            Anchor(hir::Anchor::StartText) => {
-                self.c_empty_look(prog::EmptyLook::StartText)
-            }
-            Anchor(hir::Anchor::EndText) if self.compiled.is_reverse => {
-                self.c_empty_look(prog::EmptyLook::StartText)
-            }
-            Anchor(hir::Anchor::EndText) => {
-                self.c_empty_look(prog::EmptyLook::EndText)
-            }
-            WordBoundary(hir::WordBoundary::Unicode) => {
-                if !cfg!(feature = "unicode-perl") {
-                    return Err(Error::Syntax(
-                        "Unicode word boundaries are unavailable when \
-                         the unicode-perl feature is disabled"
-                            .to_string(),
-                    ));
-                }
-                self.compiled.has_unicode_word_boundary = true;
-                self.byte_classes.set_word_boundary();
-                self.c_empty_look(prog::EmptyLook::WordBoundary)
-            }
-            WordBoundary(hir::WordBoundary::UnicodeNegate) => {
-                if !cfg!(feature = "unicode-perl") {
-                    return Err(Error::Syntax(
-                        "Unicode word boundaries are unavailable when \
-                         the unicode-perl feature is disabled"
-                            .to_string(),
-                    ));
-                }
-                self.compiled.has_unicode_word_boundary = true;
-                self.byte_classes.set_word_boundary();
-                self.c_empty_look(prog::EmptyLook::NotWordBoundary)
-            }
-            WordBoundary(hir::WordBoundary::Ascii) => {
-                self.byte_classes.set_word_boundary();
-                self.c_empty_look(prog::EmptyLook::WordBoundaryAscii)
-            }
-            WordBoundary(hir::WordBoundary::AsciiNegate) => {
-                self.byte_classes.set_word_boundary();
-                self.c_empty_look(prog::EmptyLook::NotWordBoundaryAscii)
-            }
-            Group(ref g) => match g.kind {
-                hir::GroupKind::NonCapturing => self.c(&g.hir),
-                hir::GroupKind::CaptureIndex(index) => {
-                    if index as usize >= self.compiled.captures.len() {
-                        self.compiled.captures.push(None);
-                    }
-                    self.c_capture(2 * index as usize, &g.hir)
-                }
-                hir::GroupKind::CaptureName { index, ref name } => {
-                    if index as usize >= self.compiled.captures.len() {
-                        let n = name.to_string();
-                        self.compiled.captures.push(Some(n.clone()));
-                        self.capture_name_idx.insert(n, index as usize);
-                    }
-                    self.c_capture(2 * index as usize, &g.hir)
-                }
-            },
-            Concat(ref es) => {
-                if self.compiled.is_reverse {
-                    self.c_concat(es.iter().rev())
-                } else {
-                    self.c_concat(es)
-                }
-            }
-            Alternation(ref es) => self.c_alternate(&**es),
-            Repetition(ref rep) => self.c_repeat(rep),
-        }
-    }
-
-    fn c_capture(&mut self, first_slot: usize, expr: &Hir) -> ResultOrEmpty {
-        if self.num_exprs > 1 || self.compiled.is_dfa {
-            // Don't ever compile Save instructions for regex sets because
-            // they are never used. They are also never used in DFA programs
-            // because DFAs can't handle captures.
-            self.c(expr)
-        } else {
-            let entry = self.insts.len();
-            let hole = self.push_hole(InstHole::Save { slot: first_slot });
-            let patch = self.c(expr)?.unwrap_or(self.next_inst());
-            self.fill(hole, patch.entry);
-            self.fill_to_next(patch.hole);
-            let hole = self.push_hole(InstHole::Save { slot: first_slot + 1 });
-            Ok(Some(Patch { hole: hole, entry: entry }))
-        }
-    }
-
-    fn c_dotstar(&mut self) -> Result {
-        Ok(if !self.compiled.only_utf8() {
-            self.c(&Hir::repetition(hir::Repetition {
-                kind: hir::RepetitionKind::ZeroOrMore,
-                greedy: false,
-                hir: Box::new(Hir::any(true)),
-            }))?
-            .unwrap()
-        } else {
-            self.c(&Hir::repetition(hir::Repetition {
-                kind: hir::RepetitionKind::ZeroOrMore,
-                greedy: false,
-                hir: Box::new(Hir::any(false)),
-            }))?
-            .unwrap()
-        })
-    }
-
-    fn c_char(&mut self, c: char) -> ResultOrEmpty {
-        if self.compiled.uses_bytes() {
-            if c.is_ascii() {
-                let b = c as u8;
-                let hole =
-                    self.push_hole(InstHole::Bytes { start: b, end: b });
-                self.byte_classes.set_range(b, b);
-                Ok(Some(Patch { hole, entry: self.insts.len() - 1 }))
-            } else {
-                self.c_class(&[hir::ClassUnicodeRange::new(c, c)])
-            }
-        } else {
-            let hole = self.push_hole(InstHole::Char { c: c });
-            Ok(Some(Patch { hole, entry: self.insts.len() - 1 }))
-        }
-    }
-
-    fn c_class(&mut self, ranges: &[hir::ClassUnicodeRange]) -> ResultOrEmpty {
-        assert!(!ranges.is_empty());
-        if self.compiled.uses_bytes() {
-            Ok(Some(CompileClass { c: self, ranges: ranges }.compile()?))
-        } else {
-            let ranges: Vec<(char, char)> =
-                ranges.iter().map(|r| (r.start(), r.end())).collect();
-            let hole = if ranges.len() == 1 && ranges[0].0 == ranges[0].1 {
-                self.push_hole(InstHole::Char { c: ranges[0].0 })
-            } else {
-                self.push_hole(InstHole::Ranges { ranges: ranges })
-            };
-            Ok(Some(Patch { hole: hole, entry: self.insts.len() - 1 }))
-        }
-    }
-
-    fn c_byte(&mut self, b: u8) -> ResultOrEmpty {
-        self.c_class_bytes(&[hir::ClassBytesRange::new(b, b)])
-    }
-
-    fn c_class_bytes(
-        &mut self,
-        ranges: &[hir::ClassBytesRange],
-    ) -> ResultOrEmpty {
-        debug_assert!(!ranges.is_empty());
-
-        let first_split_entry = self.insts.len();
-        let mut holes = vec![];
-        let mut prev_hole = Hole::None;
-        for r in &ranges[0..ranges.len() - 1] {
-            self.fill_to_next(prev_hole);
-            let split = self.push_split_hole();
-            let next = self.insts.len();
-            self.byte_classes.set_range(r.start(), r.end());
-            holes.push(self.push_hole(InstHole::Bytes {
-                start: r.start(),
-                end: r.end(),
-            }));
-            prev_hole = self.fill_split(split, Some(next), None);
-        }
-        let next = self.insts.len();
-        let r = &ranges[ranges.len() - 1];
-        self.byte_classes.set_range(r.start(), r.end());
-        holes.push(
-            self.push_hole(InstHole::Bytes { start: r.start(), end: r.end() }),
-        );
-        self.fill(prev_hole, next);
-        Ok(Some(Patch { hole: Hole::Many(holes), entry: first_split_entry }))
-    }
-
-    fn c_empty_look(&mut self, look: EmptyLook) -> ResultOrEmpty {
-        let hole = self.push_hole(InstHole::EmptyLook { look: look });
-        Ok(Some(Patch { hole: hole, entry: self.insts.len() - 1 }))
-    }
-
-    fn c_concat<'a, I>(&mut self, exprs: I) -> ResultOrEmpty
-    where
-        I: IntoIterator<Item = &'a Hir>,
-    {
-        let mut exprs = exprs.into_iter();
-        let Patch { mut hole, entry } = loop {
-            match exprs.next() {
-                None => return Ok(None),
-                Some(e) => {
-                    if let Some(p) = self.c(e)? {
-                        break p;
-                    }
-                }
-            }
-        };
-        for e in exprs {
-            if let Some(p) = self.c(e)? {
-                self.fill(hole, p.entry);
-                hole = p.hole;
-            }
-        }
-        Ok(Some(Patch { hole: hole, entry: entry }))
-    }
-
-    fn c_alternate(&mut self, exprs: &[Hir]) -> ResultOrEmpty {
-        debug_assert!(
-            exprs.len() >= 2,
-            "alternates must have at least 2 exprs"
-        );
-
-        // Initial entry point is always the first split.
-        let first_split_entry = self.insts.len();
-
-        // Save up all of the holes from each alternate. They will all get
-        // patched to point to the same location.
-        let mut holes = vec![];
-
-        // true indicates that the hole is a split where we want to fill
-        // the second branch.
-        let mut prev_hole = (Hole::None, false);
-        for e in &exprs[0..exprs.len() - 1] {
-            if prev_hole.1 {
-                let next = self.insts.len();
-                self.fill_split(prev_hole.0, None, Some(next));
-            } else {
-                self.fill_to_next(prev_hole.0);
-            }
-            let split = self.push_split_hole();
-            if let Some(Patch { hole, entry }) = self.c(e)? {
-                holes.push(hole);
-                prev_hole = (self.fill_split(split, Some(entry), None), false);
-            } else {
-                let (split1, split2) = split.dup_one();
-                holes.push(split1);
-                prev_hole = (split2, true);
-            }
-        }
-        if let Some(Patch { hole, entry }) = self.c(&exprs[exprs.len() - 1])? {
-            holes.push(hole);
-            if prev_hole.1 {
-                self.fill_split(prev_hole.0, None, Some(entry));
-            } else {
-                self.fill(prev_hole.0, entry);
-            }
-        } else {
-            // We ignore prev_hole.1. When it's true, it means we have two
-            // empty branches both pushing prev_hole.0 into holes, so both
-            // branches will go to the same place anyway.
-            holes.push(prev_hole.0);
-        }
-        Ok(Some(Patch { hole: Hole::Many(holes), entry: first_split_entry }))
-    }
-
-    fn c_repeat(&mut self, rep: &hir::Repetition) -> ResultOrEmpty {
-        use syntax::hir::RepetitionKind::*;
-        match rep.kind {
-            ZeroOrOne => self.c_repeat_zero_or_one(&rep.hir, rep.greedy),
-            ZeroOrMore => self.c_repeat_zero_or_more(&rep.hir, rep.greedy),
-            OneOrMore => self.c_repeat_one_or_more(&rep.hir, rep.greedy),
-            Range(hir::RepetitionRange::Exactly(min_max)) => {
-                self.c_repeat_range(&rep.hir, rep.greedy, min_max, min_max)
-            }
-            Range(hir::RepetitionRange::AtLeast(min)) => {
-                self.c_repeat_range_min_or_more(&rep.hir, rep.greedy, min)
-            }
-            Range(hir::RepetitionRange::Bounded(min, max)) => {
-                self.c_repeat_range(&rep.hir, rep.greedy, min, max)
-            }
-        }
-    }
-
-    fn c_repeat_zero_or_one(
-        &mut self,
-        expr: &Hir,
-        greedy: bool,
-    ) -> ResultOrEmpty {
-        let split_entry = self.insts.len();
-        let split = self.push_split_hole();
-        let Patch { hole: hole_rep, entry: entry_rep } = match self.c(expr)? {
-            Some(p) => p,
-            None => return self.pop_split_hole(),
-        };
-        let split_hole = if greedy {
-            self.fill_split(split, Some(entry_rep), None)
-        } else {
-            self.fill_split(split, None, Some(entry_rep))
-        };
-        let holes = vec![hole_rep, split_hole];
-        Ok(Some(Patch { hole: Hole::Many(holes), entry: split_entry }))
-    }
-
-    fn c_repeat_zero_or_more(
-        &mut self,
-        expr: &Hir,
-        greedy: bool,
-    ) -> ResultOrEmpty {
-        let split_entry = self.insts.len();
-        let split = self.push_split_hole();
-        let Patch { hole: hole_rep, entry: entry_rep } = match self.c(expr)? {
-            Some(p) => p,
-            None => return self.pop_split_hole(),
-        };
-
-        self.fill(hole_rep, split_entry);
-        let split_hole = if greedy {
-            self.fill_split(split, Some(entry_rep), None)
-        } else {
-            self.fill_split(split, None, Some(entry_rep))
-        };
-        Ok(Some(Patch { hole: split_hole, entry: split_entry }))
-    }
-
-    fn c_repeat_one_or_more(
-        &mut self,
-        expr: &Hir,
-        greedy: bool,
-    ) -> ResultOrEmpty {
-        let Patch { hole: hole_rep, entry: entry_rep } = match self.c(expr)? {
-            Some(p) => p,
-            None => return Ok(None),
-        };
-        self.fill_to_next(hole_rep);
-        let split = self.push_split_hole();
-
-        let split_hole = if greedy {
-            self.fill_split(split, Some(entry_rep), None)
-        } else {
-            self.fill_split(split, None, Some(entry_rep))
-        };
-        Ok(Some(Patch { hole: split_hole, entry: entry_rep }))
-    }
-
-    fn c_repeat_range_min_or_more(
-        &mut self,
-        expr: &Hir,
-        greedy: bool,
-        min: u32,
-    ) -> ResultOrEmpty {
-        let min = u32_to_usize(min);
-        // Using next_inst() is ok, because we can't return it (concat would
-        // have to return Some(_) while c_repeat_range_min_or_more returns
-        // None).
-        let patch_concat = self
-            .c_concat(iter::repeat(expr).take(min))?
-            .unwrap_or(self.next_inst());
-        if let Some(patch_rep) = self.c_repeat_zero_or_more(expr, greedy)? {
-            self.fill(patch_concat.hole, patch_rep.entry);
-            Ok(Some(Patch { hole: patch_rep.hole, entry: patch_concat.entry }))
-        } else {
-            Ok(None)
-        }
-    }
-
-    fn c_repeat_range(
-        &mut self,
-        expr: &Hir,
-        greedy: bool,
-        min: u32,
-        max: u32,
-    ) -> ResultOrEmpty {
-        let (min, max) = (u32_to_usize(min), u32_to_usize(max));
-        debug_assert!(min <= max);
-        let patch_concat = self.c_concat(iter::repeat(expr).take(min))?;
-        if min == max {
-            return Ok(patch_concat);
-        }
-        // Same reasoning as in c_repeat_range_min_or_more (we know that min <
-        // max at this point).
-        let patch_concat = patch_concat.unwrap_or(self.next_inst());
-        let initial_entry = patch_concat.entry;
-        // It is much simpler to compile, e.g., `a{2,5}` as:
-        //
-        //     aaa?a?a?
-        //
-        // But you end up with a sequence of instructions like this:
-        //
-        //     0: 'a'
-        //     1: 'a',
-        //     2: split(3, 4)
-        //     3: 'a'
-        //     4: split(5, 6)
-        //     5: 'a'
-        //     6: split(7, 8)
-        //     7: 'a'
-        //     8: MATCH
-        //
-        // This is *incredibly* inefficient because the splits end
-        // up forming a chain, which has to be resolved everything a
-        // transition is followed.
-        let mut holes = vec![];
-        let mut prev_hole = patch_concat.hole;
-        for _ in min..max {
-            self.fill_to_next(prev_hole);
-            let split = self.push_split_hole();
-            let Patch { hole, entry } = match self.c(expr)? {
-                Some(p) => p,
-                None => return self.pop_split_hole(),
-            };
-            prev_hole = hole;
-            if greedy {
-                holes.push(self.fill_split(split, Some(entry), None));
-            } else {
-                holes.push(self.fill_split(split, None, Some(entry)));
-            }
-        }
-        holes.push(prev_hole);
-        Ok(Some(Patch { hole: Hole::Many(holes), entry: initial_entry }))
-    }
-
-    /// Can be used as a default value for the c_* functions when the call to
-    /// c_function is followed by inserting at least one instruction that is
-    /// always executed after the ones written by the c* function.
-    fn next_inst(&self) -> Patch {
-        Patch { hole: Hole::None, entry: self.insts.len() }
-    }
-
-    fn fill(&mut self, hole: Hole, goto: InstPtr) {
-        match hole {
-            Hole::None => {}
-            Hole::One(pc) => {
-                self.insts[pc].fill(goto);
-            }
-            Hole::Many(holes) => {
-                for hole in holes {
-                    self.fill(hole, goto);
-                }
-            }
-        }
-    }
-
-    fn fill_to_next(&mut self, hole: Hole) {
-        let next = self.insts.len();
-        self.fill(hole, next);
-    }
-
-    fn fill_split(
-        &mut self,
-        hole: Hole,
-        goto1: Option<InstPtr>,
-        goto2: Option<InstPtr>,
-    ) -> Hole {
-        match hole {
-            Hole::None => Hole::None,
-            Hole::One(pc) => match (goto1, goto2) {
-                (Some(goto1), Some(goto2)) => {
-                    self.insts[pc].fill_split(goto1, goto2);
-                    Hole::None
-                }
-                (Some(goto1), None) => {
-                    self.insts[pc].half_fill_split_goto1(goto1);
-                    Hole::One(pc)
-                }
-                (None, Some(goto2)) => {
-                    self.insts[pc].half_fill_split_goto2(goto2);
-                    Hole::One(pc)
-                }
-                (None, None) => unreachable!(
-                    "at least one of the split \
-                     holes must be filled"
-                ),
-            },
-            Hole::Many(holes) => {
-                let mut new_holes = vec![];
-                for hole in holes {
-                    new_holes.push(self.fill_split(hole, goto1, goto2));
-                }
-                if new_holes.is_empty() {
-                    Hole::None
-                } else if new_holes.len() == 1 {
-                    new_holes.pop().unwrap()
-                } else {
-                    Hole::Many(new_holes)
-                }
-            }
-        }
-    }
-
-    fn push_compiled(&mut self, inst: Inst) {
-        self.insts.push(MaybeInst::Compiled(inst));
-    }
-
-    fn push_hole(&mut self, inst: InstHole) -> Hole {
-        let hole = self.insts.len();
-        self.insts.push(MaybeInst::Uncompiled(inst));
-        Hole::One(hole)
-    }
-
-    fn push_split_hole(&mut self) -> Hole {
-        let hole = self.insts.len();
-        self.insts.push(MaybeInst::Split);
-        Hole::One(hole)
-    }
-
-    fn pop_split_hole(&mut self) -> ResultOrEmpty {
-        self.insts.pop();
-        Ok(None)
-    }
-
-    fn check_size(&self) -> result::Result<(), Error> {
-        use std::mem::size_of;
-
-        if self.insts.len() * size_of::<Inst>() > self.size_limit {
-            Err(Error::CompiledTooBig(self.size_limit))
-        } else {
-            Ok(())
-        }
-    }
-}
-
-#[derive(Debug)]
-enum Hole {
-    None,
-    One(InstPtr),
-    Many(Vec<Hole>),
-}
-
-impl Hole {
-    fn dup_one(self) -> (Self, Self) {
-        match self {
-            Hole::One(pc) => (Hole::One(pc), Hole::One(pc)),
-            Hole::None | Hole::Many(_) => {
-                unreachable!("must be called on single hole")
-            }
-        }
-    }
-}
-
-#[derive(Clone, Debug)]
-enum MaybeInst {
-    Compiled(Inst),
-    Uncompiled(InstHole),
-    Split,
-    Split1(InstPtr),
-    Split2(InstPtr),
-}
-
-impl MaybeInst {
-    fn fill(&mut self, goto: InstPtr) {
-        let maybeinst = match *self {
-            MaybeInst::Split => MaybeInst::Split1(goto),
-            MaybeInst::Uncompiled(ref inst) => {
-                MaybeInst::Compiled(inst.fill(goto))
-            }
-            MaybeInst::Split1(goto1) => {
-                MaybeInst::Compiled(Inst::Split(InstSplit {
-                    goto1: goto1,
-                    goto2: goto,
-                }))
-            }
-            MaybeInst::Split2(goto2) => {
-                MaybeInst::Compiled(Inst::Split(InstSplit {
-                    goto1: goto,
-                    goto2: goto2,
-                }))
-            }
-            _ => unreachable!(
-                "not all instructions were compiled! \
-                 found uncompiled instruction: {:?}",
-                self
-            ),
-        };
-        *self = maybeinst;
-    }
-
-    fn fill_split(&mut self, goto1: InstPtr, goto2: InstPtr) {
-        let filled = match *self {
-            MaybeInst::Split => {
-                Inst::Split(InstSplit { goto1: goto1, goto2: goto2 })
-            }
-            _ => unreachable!(
-                "must be called on Split instruction, \
-                 instead it was called on: {:?}",
-                self
-            ),
-        };
-        *self = MaybeInst::Compiled(filled);
-    }
-
-    fn half_fill_split_goto1(&mut self, goto1: InstPtr) {
-        let half_filled = match *self {
-            MaybeInst::Split => goto1,
-            _ => unreachable!(
-                "must be called on Split instruction, \
-                 instead it was called on: {:?}",
-                self
-            ),
-        };
-        *self = MaybeInst::Split1(half_filled);
-    }
-
-    fn half_fill_split_goto2(&mut self, goto2: InstPtr) {
-        let half_filled = match *self {
-            MaybeInst::Split => goto2,
-            _ => unreachable!(
-                "must be called on Split instruction, \
-                 instead it was called on: {:?}",
-                self
-            ),
-        };
-        *self = MaybeInst::Split2(half_filled);
-    }
-
-    fn unwrap(self) -> Inst {
-        match self {
-            MaybeInst::Compiled(inst) => inst,
-            _ => unreachable!(
-                "must be called on a compiled instruction, \
-                 instead it was called on: {:?}",
-                self
-            ),
-        }
-    }
-}
-
-#[derive(Clone, Debug)]
-enum InstHole {
-    Save { slot: usize },
-    EmptyLook { look: EmptyLook },
-    Char { c: char },
-    Ranges { ranges: Vec<(char, char)> },
-    Bytes { start: u8, end: u8 },
-}
-
-impl InstHole {
-    fn fill(&self, goto: InstPtr) -> Inst {
-        match *self {
-            InstHole::Save { slot } => {
-                Inst::Save(InstSave { goto: goto, slot: slot })
-            }
-            InstHole::EmptyLook { look } => {
-                Inst::EmptyLook(InstEmptyLook { goto: goto, look: look })
-            }
-            InstHole::Char { c } => Inst::Char(InstChar { goto: goto, c: c }),
-            InstHole::Ranges { ref ranges } => {
-                Inst::Ranges(InstRanges { goto: goto, ranges: ranges.clone() })
-            }
-            InstHole::Bytes { start, end } => {
-                Inst::Bytes(InstBytes { goto: goto, start: start, end: end })
-            }
-        }
-    }
-}
-
-struct CompileClass<'a, 'b> {
-    c: &'a mut Compiler,
-    ranges: &'b [hir::ClassUnicodeRange],
-}
-
-impl<'a, 'b> CompileClass<'a, 'b> {
-    fn compile(mut self) -> Result {
-        let mut holes = vec![];
-        let mut initial_entry = None;
-        let mut last_split = Hole::None;
-        let mut utf8_seqs = self.c.utf8_seqs.take().unwrap();
-        self.c.suffix_cache.clear();
-
-        for (i, range) in self.ranges.iter().enumerate() {
-            let is_last_range = i + 1 == self.ranges.len();
-            utf8_seqs.reset(range.start(), range.end());
-            let mut it = (&mut utf8_seqs).peekable();
-            loop {
-                let utf8_seq = match it.next() {
-                    None => break,
-                    Some(utf8_seq) => utf8_seq,
-                };
-                if is_last_range && it.peek().is_none() {
-                    let Patch { hole, entry } = self.c_utf8_seq(&utf8_seq)?;
-                    holes.push(hole);
-                    self.c.fill(last_split, entry);
-                    last_split = Hole::None;
-                    if initial_entry.is_none() {
-                        initial_entry = Some(entry);
-                    }
-                } else {
-                    if initial_entry.is_none() {
-                        initial_entry = Some(self.c.insts.len());
-                    }
-                    self.c.fill_to_next(last_split);
-                    last_split = self.c.push_split_hole();
-                    let Patch { hole, entry } = self.c_utf8_seq(&utf8_seq)?;
-                    holes.push(hole);
-                    last_split =
-                        self.c.fill_split(last_split, Some(entry), None);
-                }
-            }
-        }
-        self.c.utf8_seqs = Some(utf8_seqs);
-        Ok(Patch { hole: Hole::Many(holes), entry: initial_entry.unwrap() })
-    }
-
-    fn c_utf8_seq(&mut self, seq: &Utf8Sequence) -> Result {
-        if self.c.compiled.is_reverse {
-            self.c_utf8_seq_(seq)
-        } else {
-            self.c_utf8_seq_(seq.into_iter().rev())
-        }
-    }
-
-    fn c_utf8_seq_<'r, I>(&mut self, seq: I) -> Result
-    where
-        I: IntoIterator<Item = &'r Utf8Range>,
-    {
-        // The initial instruction for each UTF-8 sequence should be the same.
-        let mut from_inst = ::std::usize::MAX;
-        let mut last_hole = Hole::None;
-        for byte_range in seq {
-            let key = SuffixCacheKey {
-                from_inst: from_inst,
-                start: byte_range.start,
-                end: byte_range.end,
-            };
-            {
-                let pc = self.c.insts.len();
-                if let Some(cached_pc) = self.c.suffix_cache.get(key, pc) {
-                    from_inst = cached_pc;
-                    continue;
-                }
-            }
-            self.c.byte_classes.set_range(byte_range.start, byte_range.end);
-            if from_inst == ::std::usize::MAX {
-                last_hole = self.c.push_hole(InstHole::Bytes {
-                    start: byte_range.start,
-                    end: byte_range.end,
-                });
-            } else {
-                self.c.push_compiled(Inst::Bytes(InstBytes {
-                    goto: from_inst,
-                    start: byte_range.start,
-                    end: byte_range.end,
-                }));
-            }
-            from_inst = self.c.insts.len().checked_sub(1).unwrap();
-            debug_assert!(from_inst < ::std::usize::MAX);
-        }
-        debug_assert!(from_inst < ::std::usize::MAX);
-        Ok(Patch { hole: last_hole, entry: from_inst })
-    }
-}
-
-/// `SuffixCache` is a simple bounded hash map for caching suffix entries in
-/// UTF-8 automata. For example, consider the Unicode range \u{0}-\u{FFFF}.
-/// The set of byte ranges looks like this:
-///
-/// [0-7F]
-/// [C2-DF][80-BF]
-/// [E0][A0-BF][80-BF]
-/// [E1-EC][80-BF][80-BF]
-/// [ED][80-9F][80-BF]
-/// [EE-EF][80-BF][80-BF]
-///
-/// Each line above translates to one alternate in the compiled regex program.
-/// However, all but one of the alternates end in the same suffix, which is
-/// a waste of an instruction. The suffix cache facilitates reusing them across
-/// alternates.
-///
-/// Note that a HashMap could be trivially used for this, but we don't need its
-/// overhead. Some small bounded space (LRU style) is more than enough.
-///
-/// This uses similar idea to [`SparseSet`](../sparse/struct.SparseSet.html),
-/// except it uses hashes as original indices and then compares full keys for
-/// validation against `dense` array.
-#[derive(Debug)]
-struct SuffixCache {
-    sparse: Box<[usize]>,
-    dense: Vec<SuffixCacheEntry>,
-}
-
-#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
-struct SuffixCacheEntry {
-    key: SuffixCacheKey,
-    pc: InstPtr,
-}
-
-#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
-struct SuffixCacheKey {
-    from_inst: InstPtr,
-    start: u8,
-    end: u8,
-}
-
-impl SuffixCache {
-    fn new(size: usize) -> Self {
-        SuffixCache {
-            sparse: vec![0usize; size].into(),
-            dense: Vec::with_capacity(size),
-        }
-    }
-
-    fn get(&mut self, key: SuffixCacheKey, pc: InstPtr) -> Option<InstPtr> {
-        let hash = self.hash(&key);
-        let pos = &mut self.sparse[hash];
-        if let Some(entry) = self.dense.get(*pos) {
-            if entry.key == key {
-                return Some(entry.pc);
-            }
-        }
-        *pos = self.dense.len();
-        self.dense.push(SuffixCacheEntry { key: key, pc: pc });
-        None
-    }
-
-    fn clear(&mut self) {
-        self.dense.clear();
-    }
-
-    fn hash(&self, suffix: &SuffixCacheKey) -> usize {
-        // Basic FNV-1a hash as described:
-        // https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
-        const FNV_PRIME: u64 = 1099511628211;
-        let mut h = 14695981039346656037;
-        h = (h ^ (suffix.from_inst as u64)).wrapping_mul(FNV_PRIME);
-        h = (h ^ (suffix.start as u64)).wrapping_mul(FNV_PRIME);
-        h = (h ^ (suffix.end as u64)).wrapping_mul(FNV_PRIME);
-        (h as usize) % self.sparse.len()
-    }
-}
-
-struct ByteClassSet([bool; 256]);
-
-impl ByteClassSet {
-    fn new() -> Self {
-        ByteClassSet([false; 256])
-    }
-
-    fn set_range(&mut self, start: u8, end: u8) {
-        debug_assert!(start <= end);
-        if start > 0 {
-            self.0[start as usize - 1] = true;
-        }
-        self.0[end as usize] = true;
-    }
-
-    fn set_word_boundary(&mut self) {
-        // We need to mark all ranges of bytes whose pairs result in
-        // evaluating \b differently.
-        let iswb = is_word_byte;
-        let mut b1: u16 = 0;
-        let mut b2: u16;
-        while b1 <= 255 {
-            b2 = b1 + 1;
-            while b2 <= 255 && iswb(b1 as u8) == iswb(b2 as u8) {
-                b2 += 1;
-            }
-            self.set_range(b1 as u8, (b2 - 1) as u8);
-            b1 = b2;
-        }
-    }
-
-    fn byte_classes(&self) -> Vec<u8> {
-        // N.B. If you're debugging the DFA, it's useful to simply return
-        // `(0..256).collect()`, which effectively removes the byte classes
-        // and makes the transitions easier to read.
-        // (0usize..256).map(|x| x as u8).collect()
-        let mut byte_classes = vec![0; 256];
-        let mut class = 0u8;
-        let mut i = 0;
-        loop {
-            byte_classes[i] = class as u8;
-            if i >= 255 {
-                break;
-            }
-            if self.0[i] {
-                class = class.checked_add(1).unwrap();
-            }
-            i += 1;
-        }
-        byte_classes
-    }
-}
-
-impl fmt::Debug for ByteClassSet {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple("ByteClassSet").field(&&self.0[..]).finish()
-    }
-}
-
-fn u32_to_usize(n: u32) -> usize {
-    // In case usize is less than 32 bits, we need to guard against overflow.
-    // On most platforms this compiles to nothing.
-    // TODO Use `std::convert::TryFrom` once it's stable.
-    if (n as u64) > (::std::usize::MAX as u64) {
-        panic!("BUG: {} is too big to be pointer sized", n)
-    }
-    n as usize
-}
-
-#[cfg(test)]
-mod tests {
-    use super::ByteClassSet;
-
-    #[test]
-    fn byte_classes() {
-        let mut set = ByteClassSet::new();
-        set.set_range(b'a', b'z');
-        let classes = set.byte_classes();
-        assert_eq!(classes[0], 0);
-        assert_eq!(classes[1], 0);
-        assert_eq!(classes[2], 0);
-        assert_eq!(classes[b'a' as usize - 1], 0);
-        assert_eq!(classes[b'a' as usize], 1);
-        assert_eq!(classes[b'm' as usize], 1);
-        assert_eq!(classes[b'z' as usize], 1);
-        assert_eq!(classes[b'z' as usize + 1], 2);
-        assert_eq!(classes[254], 2);
-        assert_eq!(classes[255], 2);
-
-        let mut set = ByteClassSet::new();
-        set.set_range(0, 2);
-        set.set_range(4, 6);
-        let classes = set.byte_classes();
-        assert_eq!(classes[0], 0);
-        assert_eq!(classes[1], 0);
-        assert_eq!(classes[2], 0);
-        assert_eq!(classes[3], 1);
-        assert_eq!(classes[4], 2);
-        assert_eq!(classes[5], 2);
-        assert_eq!(classes[6], 2);
-        assert_eq!(classes[7], 3);
-        assert_eq!(classes[255], 3);
-    }
-
-    #[test]
-    fn full_byte_classes() {
-        let mut set = ByteClassSet::new();
-        for i in 0..256u16 {
-            set.set_range(i as u8, i as u8);
-        }
-        assert_eq!(set.byte_classes().len(), 256);
-    }
-}
diff --git a/vendor/regex-1.4.3/src/dfa.rs b/vendor/regex-1.4.3/src/dfa.rs
deleted file mode 100644 (file)
index 2a365ee..0000000
+++ /dev/null
@@ -1,1942 +0,0 @@
-/*!
-The DFA matching engine.
-
-A DFA provides faster matching because the engine is in exactly one state at
-any point in time. In the NFA, there may be multiple active states, and
-considerable CPU cycles are spent shuffling them around. In finite automata
-speak, the DFA follows epsilon transitions in the regex far less than the NFA.
-
-A DFA is a classic trade off between time and space. The NFA is slower, but
-its memory requirements are typically small and predictable. The DFA is faster,
-but given the right regex and the right input, the number of states in the
-DFA can grow exponentially. To mitigate this space problem, we do two things:
-
-1. We implement an *online* DFA. That is, the DFA is constructed from the NFA
-   during a search. When a new state is computed, it is stored in a cache so
-   that it may be reused. An important consequence of this implementation
-   is that states that are never reached for a particular input are never
-   computed. (This is impossible in an "offline" DFA which needs to compute
-   all possible states up front.)
-2. If the cache gets too big, we wipe it and continue matching.
-
-In pathological cases, a new state can be created for every byte of input.
-(e.g., The regex `(a|b)*a(a|b){20}` on a long sequence of a's and b's.)
-In this case, performance regresses to slightly slower than the full NFA
-simulation, in large part because the cache becomes useless. If the cache
-is wiped too frequently, the DFA quits and control falls back to one of the
-NFA simulations.
-
-Because of the "lazy" nature of this DFA, the inner matching loop is
-considerably more complex than one might expect out of a DFA. A number of
-tricks are employed to make it fast. Tread carefully.
-
-N.B. While this implementation is heavily commented, Russ Cox's series of
-articles on regexes is strongly recommended: https://swtch.com/~rsc/regexp/
-(As is the DFA implementation in RE2, which heavily influenced this
-implementation.)
-*/
-
-use std::collections::HashMap;
-use std::fmt;
-use std::iter::repeat;
-use std::mem;
-use std::sync::Arc;
-
-use exec::ProgramCache;
-use prog::{Inst, Program};
-use sparse::SparseSet;
-
-/// Return true if and only if the given program can be executed by a DFA.
-///
-/// Generally, a DFA is always possible. A pathological case where it is not
-/// possible is if the number of NFA states exceeds `u32::MAX`, in which case,
-/// this function will return false.
-///
-/// This function will also return false if the given program has any Unicode
-/// instructions (Char or Ranges) since the DFA operates on bytes only.
-pub fn can_exec(insts: &Program) -> bool {
-    use prog::Inst::*;
-    // If for some reason we manage to allocate a regex program with more
-    // than i32::MAX instructions, then we can't execute the DFA because we
-    // use 32 bit instruction pointer deltas for memory savings.
-    // If i32::MAX is the largest positive delta,
-    // then -i32::MAX == i32::MIN + 1 is the largest negative delta,
-    // and we are OK to use 32 bits.
-    if insts.dfa_size_limit == 0 || insts.len() > ::std::i32::MAX as usize {
-        return false;
-    }
-    for inst in insts {
-        match *inst {
-            Char(_) | Ranges(_) => return false,
-            EmptyLook(_) | Match(_) | Save(_) | Split(_) | Bytes(_) => {}
-        }
-    }
-    true
-}
-
-/// A reusable cache of DFA states.
-///
-/// This cache is reused between multiple invocations of the same regex
-/// program. (It is not shared simultaneously between threads. If there is
-/// contention, then new caches are created.)
-#[derive(Debug)]
-pub struct Cache {
-    /// Group persistent DFA related cache state together. The sparse sets
-    /// listed below are used as scratch space while computing uncached states.
-    inner: CacheInner,
-    /// qcur and qnext are ordered sets with constant time
-    /// addition/membership/clearing-whole-set and linear time iteration. They
-    /// are used to manage the sets of NFA states in DFA states when computing
-    /// cached DFA states. In particular, the order of the NFA states matters
-    /// for leftmost-first style matching. Namely, when computing a cached
-    /// state, the set of NFA states stops growing as soon as the first Match
-    /// instruction is observed.
-    qcur: SparseSet,
-    qnext: SparseSet,
-}
-
-/// `CacheInner` is logically just a part of Cache, but groups together fields
-/// that aren't passed as function parameters throughout search. (This split
-/// is mostly an artifact of the borrow checker. It is happily paid.)
-#[derive(Debug)]
-struct CacheInner {
-    /// A cache of pre-compiled DFA states, keyed by the set of NFA states
-    /// and the set of empty-width flags set at the byte in the input when the
-    /// state was observed.
-    ///
-    /// A StatePtr is effectively a `*State`, but to avoid various inconvenient
-    /// things, we just pass indexes around manually. The performance impact of
-    /// this is probably an instruction or two in the inner loop. However, on
-    /// 64 bit, each StatePtr is half the size of a *State.
-    compiled: StateMap,
-    /// The transition table.
-    ///
-    /// The transition table is laid out in row-major order, where states are
-    /// rows and the transitions for each state are columns. At a high level,
-    /// given state `s` and byte `b`, the next state can be found at index
-    /// `s * 256 + b`.
-    ///
-    /// This is, of course, a lie. A StatePtr is actually a pointer to the
-    /// *start* of a row in this table. When indexing in the DFA's inner loop,
-    /// this removes the need to multiply the StatePtr by the stride. Yes, it
-    /// matters. This reduces the number of states we can store, but: the
-    /// stride is rarely 256 since we define transitions in terms of
-    /// *equivalence classes* of bytes. Each class corresponds to a set of
-    /// bytes that never discriminate a distinct path through the DFA from each
-    /// other.
-    trans: Transitions,
-    /// A set of cached start states, which are limited to the number of
-    /// permutations of flags set just before the initial byte of input. (The
-    /// index into this vec is a `EmptyFlags`.)
-    ///
-    /// N.B. A start state can be "dead" (i.e., no possible match), so we
-    /// represent it with a StatePtr.
-    start_states: Vec<StatePtr>,
-    /// Stack scratch space used to follow epsilon transitions in the NFA.
-    /// (This permits us to avoid recursion.)
-    ///
-    /// The maximum stack size is the number of NFA states.
-    stack: Vec<InstPtr>,
-    /// The total number of times this cache has been flushed by the DFA
-    /// because of space constraints.
-    flush_count: u64,
-    /// The total heap size of the DFA's cache. We use this to determine when
-    /// we should flush the cache.
-    size: usize,
-    /// Scratch space used when building instruction pointer lists for new
-    /// states. This helps amortize allocation.
-    insts_scratch_space: Vec<u8>,
-}
-
-/// The transition table.
-///
-/// It is laid out in row-major order, with states as rows and byte class
-/// transitions as columns.
-///
-/// The transition table is responsible for producing valid `StatePtrs`. A
-/// `StatePtr` points to the start of a particular row in this table. When
-/// indexing to find the next state this allows us to avoid a multiplication
-/// when computing an index into the table.
-#[derive(Clone)]
-struct Transitions {
-    /// The table.
-    table: Vec<StatePtr>,
-    /// The stride.
-    num_byte_classes: usize,
-}
-
-/// Fsm encapsulates the actual execution of the DFA.
-#[derive(Debug)]
-pub struct Fsm<'a> {
-    /// prog contains the NFA instruction opcodes. DFA execution uses either
-    /// the `dfa` instructions or the `dfa_reverse` instructions from
-    /// `exec::ExecReadOnly`. (It never uses `ExecReadOnly.nfa`, which may have
-    /// Unicode opcodes that cannot be executed by the DFA.)
-    prog: &'a Program,
-    /// The start state. We record it here because the pointer may change
-    /// when the cache is wiped.
-    start: StatePtr,
-    /// The current position in the input.
-    at: usize,
-    /// Should we quit after seeing the first match? e.g., When the caller
-    /// uses `is_match` or `shortest_match`.
-    quit_after_match: bool,
-    /// The last state that matched.
-    ///
-    /// When no match has occurred, this is set to STATE_UNKNOWN.
-    ///
-    /// This is only useful when matching regex sets. The last match state
-    /// is useful because it contains all of the match instructions seen,
-    /// thereby allowing us to enumerate which regexes in the set matched.
-    last_match_si: StatePtr,
-    /// The input position of the last cache flush. We use this to determine
-    /// if we're thrashing in the cache too often. If so, the DFA quits so
-    /// that we can fall back to the NFA algorithm.
-    last_cache_flush: usize,
-    /// All cached DFA information that is persisted between searches.
-    cache: &'a mut CacheInner,
-}
-
-/// The result of running the DFA.
-///
-/// Generally, the result is either a match or not a match, but sometimes the
-/// DFA runs too slowly because the cache size is too small. In that case, it
-/// gives up with the intent of falling back to the NFA algorithm.
-///
-/// The DFA can also give up if it runs out of room to create new states, or if
-/// it sees non-ASCII bytes in the presence of a Unicode word boundary.
-#[derive(Clone, Debug)]
-pub enum Result<T> {
-    Match(T),
-    NoMatch(usize),
-    Quit,
-}
-
-impl<T> Result<T> {
-    /// Returns true if this result corresponds to a match.
-    pub fn is_match(&self) -> bool {
-        match *self {
-            Result::Match(_) => true,
-            Result::NoMatch(_) | Result::Quit => false,
-        }
-    }
-
-    /// Maps the given function onto T and returns the result.
-    ///
-    /// If this isn't a match, then this is a no-op.
-    #[cfg(feature = "perf-literal")]
-    pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> Result<U> {
-        match self {
-            Result::Match(t) => Result::Match(f(t)),
-            Result::NoMatch(x) => Result::NoMatch(x),
-            Result::Quit => Result::Quit,
-        }
-    }
-
-    /// Sets the non-match position.
-    ///
-    /// If this isn't a non-match, then this is a no-op.
-    fn set_non_match(self, at: usize) -> Result<T> {
-        match self {
-            Result::NoMatch(_) => Result::NoMatch(at),
-            r => r,
-        }
-    }
-}
-
-/// `State` is a DFA state. It contains an ordered set of NFA states (not
-/// necessarily complete) and a smattering of flags.
-///
-/// The flags are packed into the first byte of data.
-///
-/// States don't carry their transitions. Instead, transitions are stored in
-/// a single row-major table.
-///
-/// Delta encoding is used to store the instruction pointers.
-/// The first instruction pointer is stored directly starting
-/// at data[1], and each following pointer is stored as an offset
-/// to the previous one. If a delta is in the range -127..127,
-/// it is packed into a single byte; Otherwise the byte 128 (-128 as an i8)
-/// is coded as a flag, followed by 4 bytes encoding the delta.
-#[derive(Clone, Eq, Hash, PartialEq)]
-struct State {
-    data: Arc<[u8]>,
-}
-
-/// `InstPtr` is a 32 bit pointer into a sequence of opcodes (i.e., it indexes
-/// an NFA state).
-///
-/// Throughout this library, this is usually set to `usize`, but we force a
-/// `u32` here for the DFA to save on space.
-type InstPtr = u32;
-
-/// Adds ip to data using delta encoding with respect to prev.
-///
-/// After completion, `data` will contain `ip` and `prev` will be set to `ip`.
-fn push_inst_ptr(data: &mut Vec<u8>, prev: &mut InstPtr, ip: InstPtr) {
-    let delta = (ip as i32) - (*prev as i32);
-    write_vari32(data, delta);
-    *prev = ip;
-}
-
-struct InstPtrs<'a> {
-    base: usize,
-    data: &'a [u8],
-}
-
-impl<'a> Iterator for InstPtrs<'a> {
-    type Item = usize;
-
-    fn next(&mut self) -> Option<usize> {
-        if self.data.is_empty() {
-            return None;
-        }
-        let (delta, nread) = read_vari32(self.data);
-        let base = self.base as i32 + delta;
-        debug_assert!(base >= 0);
-        debug_assert!(nread > 0);
-        self.data = &self.data[nread..];
-        self.base = base as usize;
-        Some(self.base)
-    }
-}
-
-impl State {
-    fn flags(&self) -> StateFlags {
-        StateFlags(self.data[0])
-    }
-
-    fn inst_ptrs(&self) -> InstPtrs {
-        InstPtrs { base: 0, data: &self.data[1..] }
-    }
-}
-
-/// `StatePtr` is a 32 bit pointer to the start of a row in the transition
-/// table.
-///
-/// It has many special values. There are two types of special values:
-/// sentinels and flags.
-///
-/// Sentinels corresponds to special states that carry some kind of
-/// significance. There are three such states: unknown, dead and quit states.
-///
-/// Unknown states are states that haven't been computed yet. They indicate
-/// that a transition should be filled in that points to either an existing
-/// cached state or a new state altogether. In general, an unknown state means
-/// "follow the NFA's epsilon transitions."
-///
-/// Dead states are states that can never lead to a match, no matter what
-/// subsequent input is observed. This means that the DFA should quit
-/// immediately and return the longest match it has found thus far.
-///
-/// Quit states are states that imply the DFA is not capable of matching the
-/// regex correctly. Currently, this is only used when a Unicode word boundary
-/// exists in the regex *and* a non-ASCII byte is observed.
-///
-/// The other type of state pointer is a state pointer with special flag bits.
-/// There are two flags: a start flag and a match flag. The lower bits of both
-/// kinds always contain a "valid" `StatePtr` (indicated by the `STATE_MAX`
-/// mask).
-///
-/// The start flag means that the state is a start state, and therefore may be
-/// subject to special prefix scanning optimizations.
-///
-/// The match flag means that the state is a match state, and therefore the
-/// current position in the input (while searching) should be recorded.
-///
-/// The above exists mostly in the service of making the inner loop fast.
-/// In particular, the inner *inner* loop looks something like this:
-///
-/// ```ignore
-/// while state <= STATE_MAX and i < len(text):
-///     state = state.next[i]
-/// ```
-///
-/// This is nice because it lets us execute a lazy DFA as if it were an
-/// entirely offline DFA (i.e., with very few instructions). The loop will
-/// quit only when we need to examine a case that needs special attention.
-type StatePtr = u32;
-
-/// An unknown state means that the state has not been computed yet, and that
-/// the only way to progress is to compute it.
-const STATE_UNKNOWN: StatePtr = 1 << 31;
-
-/// A dead state means that the state has been computed and it is known that
-/// once it is entered, no future match can ever occur.
-const STATE_DEAD: StatePtr = STATE_UNKNOWN + 1;
-
-/// A quit state means that the DFA came across some input that it doesn't
-/// know how to process correctly. The DFA should quit and another matching
-/// engine should be run in its place.
-const STATE_QUIT: StatePtr = STATE_DEAD + 1;
-
-/// A start state is a state that the DFA can start in.
-///
-/// Note that start states have their lower bits set to a state pointer.
-const STATE_START: StatePtr = 1 << 30;
-
-/// A match state means that the regex has successfully matched.
-///
-/// Note that match states have their lower bits set to a state pointer.
-const STATE_MATCH: StatePtr = 1 << 29;
-
-/// The maximum state pointer. This is useful to mask out the "valid" state
-/// pointer from a state with the "start" or "match" bits set.
-///
-/// It doesn't make sense to use this with unknown, dead or quit state
-/// pointers, since those pointers are sentinels and never have their lower
-/// bits set to anything meaningful.
-const STATE_MAX: StatePtr = STATE_MATCH - 1;
-
-/// Byte is a u8 in spirit, but a u16 in practice so that we can represent the
-/// special EOF sentinel value.
-#[derive(Copy, Clone, Debug)]
-struct Byte(u16);
-
-/// A set of flags for zero-width assertions.
-#[derive(Clone, Copy, Eq, Debug, Default, Hash, PartialEq)]
-struct EmptyFlags {
-    start: bool,
-    end: bool,
-    start_line: bool,
-    end_line: bool,
-    word_boundary: bool,
-    not_word_boundary: bool,
-}
-
-/// A set of flags describing various configurations of a DFA state. This is
-/// represented by a `u8` so that it is compact.
-#[derive(Clone, Copy, Eq, Default, Hash, PartialEq)]
-struct StateFlags(u8);
-
-impl Cache {
-    /// Create new empty cache for the DFA engine.
-    pub fn new(prog: &Program) -> Self {
-        // We add 1 to account for the special EOF byte.
-        let num_byte_classes = (prog.byte_classes[255] as usize + 1) + 1;
-        let starts = vec![STATE_UNKNOWN; 256];
-        let mut cache = Cache {
-            inner: CacheInner {
-                compiled: StateMap::new(num_byte_classes),
-                trans: Transitions::new(num_byte_classes),
-                start_states: starts,
-                stack: vec![],
-                flush_count: 0,
-                size: 0,
-                insts_scratch_space: vec![],
-            },
-            qcur: SparseSet::new(prog.insts.len()),
-            qnext: SparseSet::new(prog.insts.len()),
-        };
-        cache.inner.reset_size();
-        cache
-    }
-}
-
-impl CacheInner {
-    /// Resets the cache size to account for fixed costs, such as the program
-    /// and stack sizes.
-    fn reset_size(&mut self) {
-        self.size = (self.start_states.len() * mem::size_of::<StatePtr>())
-            + (self.stack.len() * mem::size_of::<InstPtr>());
-    }
-}
-
-impl<'a> Fsm<'a> {
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    pub fn forward(
-        prog: &'a Program,
-        cache: &ProgramCache,
-        quit_after_match: bool,
-        text: &[u8],
-        at: usize,
-    ) -> Result<usize> {
-        let mut cache = cache.borrow_mut();
-        let cache = &mut cache.dfa;
-        let mut dfa = Fsm {
-            prog: prog,
-            start: 0, // filled in below
-            at: at,
-            quit_after_match: quit_after_match,
-            last_match_si: STATE_UNKNOWN,
-            last_cache_flush: at,
-            cache: &mut cache.inner,
-        };
-        let (empty_flags, state_flags) = dfa.start_flags(text, at);
-        dfa.start =
-            match dfa.start_state(&mut cache.qcur, empty_flags, state_flags) {
-                None => return Result::Quit,
-                Some(STATE_DEAD) => return Result::NoMatch(at),
-                Some(si) => si,
-            };
-        debug_assert!(dfa.start != STATE_UNKNOWN);
-        dfa.exec_at(&mut cache.qcur, &mut cache.qnext, text)
-    }
-
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    pub fn reverse(
-        prog: &'a Program,
-        cache: &ProgramCache,
-        quit_after_match: bool,
-        text: &[u8],
-        at: usize,
-    ) -> Result<usize> {
-        let mut cache = cache.borrow_mut();
-        let cache = &mut cache.dfa_reverse;
-        let mut dfa = Fsm {
-            prog: prog,
-            start: 0, // filled in below
-            at: at,
-            quit_after_match: quit_after_match,
-            last_match_si: STATE_UNKNOWN,
-            last_cache_flush: at,
-            cache: &mut cache.inner,
-        };
-        let (empty_flags, state_flags) = dfa.start_flags_reverse(text, at);
-        dfa.start =
-            match dfa.start_state(&mut cache.qcur, empty_flags, state_flags) {
-                None => return Result::Quit,
-                Some(STATE_DEAD) => return Result::NoMatch(at),
-                Some(si) => si,
-            };
-        debug_assert!(dfa.start != STATE_UNKNOWN);
-        dfa.exec_at_reverse(&mut cache.qcur, &mut cache.qnext, text)
-    }
-
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    pub fn forward_many(
-        prog: &'a Program,
-        cache: &ProgramCache,
-        matches: &mut [bool],
-        text: &[u8],
-        at: usize,
-    ) -> Result<usize> {
-        debug_assert!(matches.len() == prog.matches.len());
-        let mut cache = cache.borrow_mut();
-        let cache = &mut cache.dfa;
-        let mut dfa = Fsm {
-            prog: prog,
-            start: 0, // filled in below
-            at: at,
-            quit_after_match: false,
-            last_match_si: STATE_UNKNOWN,
-            last_cache_flush: at,
-            cache: &mut cache.inner,
-        };
-        let (empty_flags, state_flags) = dfa.start_flags(text, at);
-        dfa.start =
-            match dfa.start_state(&mut cache.qcur, empty_flags, state_flags) {
-                None => return Result::Quit,
-                Some(STATE_DEAD) => return Result::NoMatch(at),
-                Some(si) => si,
-            };
-        debug_assert!(dfa.start != STATE_UNKNOWN);
-        let result = dfa.exec_at(&mut cache.qcur, &mut cache.qnext, text);
-        if result.is_match() {
-            if matches.len() == 1 {
-                matches[0] = true;
-            } else {
-                debug_assert!(dfa.last_match_si != STATE_UNKNOWN);
-                debug_assert!(dfa.last_match_si != STATE_DEAD);
-                for ip in dfa.state(dfa.last_match_si).inst_ptrs() {
-                    if let Inst::Match(slot) = dfa.prog[ip] {
-                        matches[slot] = true;
-                    }
-                }
-            }
-        }
-        result
-    }
-
-    /// Executes the DFA on a forward NFA.
-    ///
-    /// {qcur,qnext} are scratch ordered sets which may be non-empty.
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn exec_at(
-        &mut self,
-        qcur: &mut SparseSet,
-        qnext: &mut SparseSet,
-        text: &[u8],
-    ) -> Result<usize> {
-        // For the most part, the DFA is basically:
-        //
-        //   last_match = null
-        //   while current_byte != EOF:
-        //     si = current_state.next[current_byte]
-        //     if si is match
-        //       last_match = si
-        //   return last_match
-        //
-        // However, we need to deal with a few things:
-        //
-        //   1. This is an *online* DFA, so the current state's next list
-        //      may not point to anywhere yet, so we must go out and compute
-        //      them. (They are then cached into the current state's next list
-        //      to avoid re-computation.)
-        //   2. If we come across a state that is known to be dead (i.e., never
-        //      leads to a match), then we can quit early.
-        //   3. If the caller just wants to know if a match occurs, then we
-        //      can quit as soon as we know we have a match. (Full leftmost
-        //      first semantics require continuing on.)
-        //   4. If we're in the start state, then we can use a pre-computed set
-        //      of prefix literals to skip quickly along the input.
-        //   5. After the input is exhausted, we run the DFA on one symbol
-        //      that stands for EOF. This is useful for handling empty width
-        //      assertions.
-        //   6. We can't actually do state.next[byte]. Instead, we have to do
-        //      state.next[byte_classes[byte]], which permits us to keep the
-        //      'next' list very small.
-        //
-        // Since there's a bunch of extra stuff we need to consider, we do some
-        // pretty hairy tricks to get the inner loop to run as fast as
-        // possible.
-        debug_assert!(!self.prog.is_reverse);
-
-        // The last match is the currently known ending match position. It is
-        // reported as an index to the most recent byte that resulted in a
-        // transition to a match state and is always stored in capture slot `1`
-        // when searching forwards. Its maximum value is `text.len()`.
-        let mut result = Result::NoMatch(self.at);
-        let (mut prev_si, mut next_si) = (self.start, self.start);
-        let mut at = self.at;
-        while at < text.len() {
-            // This is the real inner loop. We take advantage of special bits
-            // set in the state pointer to determine whether a state is in the
-            // "common" case or not. Specifically, the common case is a
-            // non-match non-start non-dead state that has already been
-            // computed. So long as we remain in the common case, this inner
-            // loop will chew through the input.
-            //
-            // We also unroll the loop 4 times to amortize the cost of checking
-            // whether we've consumed the entire input. We are also careful
-            // to make sure that `prev_si` always represents the previous state
-            // and `next_si` always represents the next state after the loop
-            // exits, even if it isn't always true inside the loop.
-            while next_si <= STATE_MAX && at < text.len() {
-                // Argument for safety is in the definition of next_si.
-                prev_si = unsafe { self.next_si(next_si, text, at) };
-                at += 1;
-                if prev_si > STATE_MAX || at + 2 >= text.len() {
-                    mem::swap(&mut prev_si, &mut next_si);
-                    break;
-                }
-                next_si = unsafe { self.next_si(prev_si, text, at) };
-                at += 1;
-                if next_si > STATE_MAX {
-                    break;
-                }
-                prev_si = unsafe { self.next_si(next_si, text, at) };
-                at += 1;
-                if prev_si > STATE_MAX {
-                    mem::swap(&mut prev_si, &mut next_si);
-                    break;
-                }
-                next_si = unsafe { self.next_si(prev_si, text, at) };
-                at += 1;
-            }
-            if next_si & STATE_MATCH > 0 {
-                // A match state is outside of the common case because it needs
-                // special case analysis. In particular, we need to record the
-                // last position as having matched and possibly quit the DFA if
-                // we don't need to keep matching.
-                next_si &= !STATE_MATCH;
-                result = Result::Match(at - 1);
-                if self.quit_after_match {
-                    return result;
-                }
-                self.last_match_si = next_si;
-                prev_si = next_si;
-
-                // This permits short-circuiting when matching a regex set.
-                // In particular, if this DFA state contains only match states,
-                // then it's impossible to extend the set of matches since
-                // match states are final. Therefore, we can quit.
-                if self.prog.matches.len() > 1 {
-                    let state = self.state(next_si);
-                    let just_matches =
-                        state.inst_ptrs().all(|ip| self.prog[ip].is_match());
-                    if just_matches {
-                        return result;
-                    }
-                }
-
-                // Another inner loop! If the DFA stays in this particular
-                // match state, then we can rip through all of the input
-                // very quickly, and only recording the match location once
-                // we've left this particular state.
-                let cur = at;
-                while (next_si & !STATE_MATCH) == prev_si
-                    && at + 2 < text.len()
-                {
-                    // Argument for safety is in the definition of next_si.
-                    next_si = unsafe {
-                        self.next_si(next_si & !STATE_MATCH, text, at)
-                    };
-                    at += 1;
-                }
-                if at > cur {
-                    result = Result::Match(at - 2);
-                }
-            } else if next_si & STATE_START > 0 {
-                // A start state isn't in the common case because we may
-                // want to do quick prefix scanning. If the program doesn't
-                // have a detected prefix, then start states are actually
-                // considered common and this case is never reached.
-                debug_assert!(self.has_prefix());
-                next_si &= !STATE_START;
-                prev_si = next_si;
-                at = match self.prefix_at(text, at) {
-                    None => return Result::NoMatch(text.len()),
-                    Some(i) => i,
-                };
-            } else if next_si >= STATE_UNKNOWN {
-                if next_si == STATE_QUIT {
-                    return Result::Quit;
-                }
-                // Finally, this corresponds to the case where the transition
-                // entered a state that can never lead to a match or a state
-                // that hasn't been computed yet. The latter being the "slow"
-                // path.
-                let byte = Byte::byte(text[at - 1]);
-                // We no longer care about the special bits in the state
-                // pointer.
-                prev_si &= STATE_MAX;
-                // Record where we are. This is used to track progress for
-                // determining whether we should quit if we've flushed the
-                // cache too much.
-                self.at = at;
-                next_si = match self.next_state(qcur, qnext, prev_si, byte) {
-                    None => return Result::Quit,
-                    Some(STATE_DEAD) => return result.set_non_match(at),
-                    Some(si) => si,
-                };
-                debug_assert!(next_si != STATE_UNKNOWN);
-                if next_si & STATE_MATCH > 0 {
-                    next_si &= !STATE_MATCH;
-                    result = Result::Match(at - 1);
-                    if self.quit_after_match {
-                        return result;
-                    }
-                    self.last_match_si = next_si;
-                }
-                prev_si = next_si;
-            } else {
-                prev_si = next_si;
-            }
-        }
-
-        // Run the DFA once more on the special EOF sentinel value.
-        // We don't care about the special bits in the state pointer any more,
-        // so get rid of them.
-        prev_si &= STATE_MAX;
-        prev_si = match self.next_state(qcur, qnext, prev_si, Byte::eof()) {
-            None => return Result::Quit,
-            Some(STATE_DEAD) => return result.set_non_match(text.len()),
-            Some(si) => si & !STATE_START,
-        };
-        debug_assert!(prev_si != STATE_UNKNOWN);
-        if prev_si & STATE_MATCH > 0 {
-            prev_si &= !STATE_MATCH;
-            self.last_match_si = prev_si;
-            result = Result::Match(text.len());
-        }
-        result
-    }
-
-    /// Executes the DFA on a reverse NFA.
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn exec_at_reverse(
-        &mut self,
-        qcur: &mut SparseSet,
-        qnext: &mut SparseSet,
-        text: &[u8],
-    ) -> Result<usize> {
-        // The comments in `exec_at` above mostly apply here too. The main
-        // difference is that we move backwards over the input and we look for
-        // the longest possible match instead of the leftmost-first match.
-        //
-        // N.B. The code duplication here is regrettable. Efforts to improve
-        // it without sacrificing performance are welcome. ---AG
-        debug_assert!(self.prog.is_reverse);
-        let mut result = Result::NoMatch(self.at);
-        let (mut prev_si, mut next_si) = (self.start, self.start);
-        let mut at = self.at;
-        while at > 0 {
-            while next_si <= STATE_MAX && at > 0 {
-                // Argument for safety is in the definition of next_si.
-                at -= 1;
-                prev_si = unsafe { self.next_si(next_si, text, at) };
-                if prev_si > STATE_MAX || at <= 4 {
-                    mem::swap(&mut prev_si, &mut next_si);
-                    break;
-                }
-                at -= 1;
-                next_si = unsafe { self.next_si(prev_si, text, at) };
-                if next_si > STATE_MAX {
-                    break;
-                }
-                at -= 1;
-                prev_si = unsafe { self.next_si(next_si, text, at) };
-                if prev_si > STATE_MAX {
-                    mem::swap(&mut prev_si, &mut next_si);
-                    break;
-                }
-                at -= 1;
-                next_si = unsafe { self.next_si(prev_si, text, at) };
-            }
-            if next_si & STATE_MATCH > 0 {
-                next_si &= !STATE_MATCH;
-                result = Result::Match(at + 1);
-                if self.quit_after_match {
-                    return result;
-                }
-                self.last_match_si = next_si;
-                prev_si = next_si;
-                let cur = at;
-                while (next_si & !STATE_MATCH) == prev_si && at >= 2 {
-                    // Argument for safety is in the definition of next_si.
-                    at -= 1;
-                    next_si = unsafe {
-                        self.next_si(next_si & !STATE_MATCH, text, at)
-                    };
-                }
-                if at < cur {
-                    result = Result::Match(at + 2);
-                }
-            } else if next_si >= STATE_UNKNOWN {
-                if next_si == STATE_QUIT {
-                    return Result::Quit;
-                }
-                let byte = Byte::byte(text[at]);
-                prev_si &= STATE_MAX;
-                self.at = at;
-                next_si = match self.next_state(qcur, qnext, prev_si, byte) {
-                    None => return Result::Quit,
-                    Some(STATE_DEAD) => return result.set_non_match(at),
-                    Some(si) => si,
-                };
-                debug_assert!(next_si != STATE_UNKNOWN);
-                if next_si & STATE_MATCH > 0 {
-                    next_si &= !STATE_MATCH;
-                    result = Result::Match(at + 1);
-                    if self.quit_after_match {
-                        return result;
-                    }
-                    self.last_match_si = next_si;
-                }
-                prev_si = next_si;
-            } else {
-                prev_si = next_si;
-            }
-        }
-
-        // Run the DFA once more on the special EOF sentinel value.
-        prev_si = match self.next_state(qcur, qnext, prev_si, Byte::eof()) {
-            None => return Result::Quit,
-            Some(STATE_DEAD) => return result.set_non_match(0),
-            Some(si) => si,
-        };
-        debug_assert!(prev_si != STATE_UNKNOWN);
-        if prev_si & STATE_MATCH > 0 {
-            prev_si &= !STATE_MATCH;
-            self.last_match_si = prev_si;
-            result = Result::Match(0);
-        }
-        result
-    }
-
-    /// next_si transitions to the next state, where the transition input
-    /// corresponds to text[i].
-    ///
-    /// This elides bounds checks, and is therefore unsafe.
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    unsafe fn next_si(&self, si: StatePtr, text: &[u8], i: usize) -> StatePtr {
-        // What is the argument for safety here?
-        // We have three unchecked accesses that could possibly violate safety:
-        //
-        //   1. The given byte of input (`text[i]`).
-        //   2. The class of the byte of input (`classes[text[i]]`).
-        //   3. The transition for the class (`trans[si + cls]`).
-        //
-        // (1) is only safe when calling next_si is guarded by
-        // `i < text.len()`.
-        //
-        // (2) is the easiest case to guarantee since `text[i]` is always a
-        // `u8` and `self.prog.byte_classes` always has length `u8::MAX`.
-        // (See `ByteClassSet.byte_classes` in `compile.rs`.)
-        //
-        // (3) is only safe if (1)+(2) are safe. Namely, the transitions
-        // of every state are defined to have length equal to the number of
-        // byte classes in the program. Therefore, a valid class leads to a
-        // valid transition. (All possible transitions are valid lookups, even
-        // if it points to a state that hasn't been computed yet.) (3) also
-        // relies on `si` being correct, but StatePtrs should only ever be
-        // retrieved from the transition table, which ensures they are correct.
-        debug_assert!(i < text.len());
-        let b = *text.get_unchecked(i);
-        debug_assert!((b as usize) < self.prog.byte_classes.len());
-        let cls = *self.prog.byte_classes.get_unchecked(b as usize);
-        self.cache.trans.next_unchecked(si, cls as usize)
-    }
-
-    /// Computes the next state given the current state and the current input
-    /// byte (which may be EOF).
-    ///
-    /// If STATE_DEAD is returned, then there is no valid state transition.
-    /// This implies that no permutation of future input can lead to a match
-    /// state.
-    ///
-    /// STATE_UNKNOWN can never be returned.
-    fn exec_byte(
-        &mut self,
-        qcur: &mut SparseSet,
-        qnext: &mut SparseSet,
-        mut si: StatePtr,
-        b: Byte,
-    ) -> Option<StatePtr> {
-        use prog::Inst::*;
-
-        // Initialize a queue with the current DFA state's NFA states.
-        qcur.clear();
-        for ip in self.state(si).inst_ptrs() {
-            qcur.insert(ip);
-        }
-
-        // Before inspecting the current byte, we may need to also inspect
-        // whether the position immediately preceding the current byte
-        // satisfies the empty assertions found in the current state.
-        //
-        // We only need to do this step if there are any empty assertions in
-        // the current state.
-        let is_word_last = self.state(si).flags().is_word();
-        let is_word = b.is_ascii_word();
-        if self.state(si).flags().has_empty() {
-            // Compute the flags immediately preceding the current byte.
-            // This means we only care about the "end" or "end line" flags.
-            // (The "start" flags are computed immediately following the
-            // current byte and are handled below.)
-            let mut flags = EmptyFlags::default();
-            if b.is_eof() {
-                flags.end = true;
-                flags.end_line = true;
-            } else if b.as_byte().map_or(false, |b| b == b'\n') {
-                flags.end_line = true;
-            }
-            if is_word_last == is_word {
-                flags.not_word_boundary = true;
-            } else {
-                flags.word_boundary = true;
-            }
-            // Now follow epsilon transitions from every NFA state, but make
-            // sure we only follow transitions that satisfy our flags.
-            qnext.clear();
-            for &ip in &*qcur {
-                self.follow_epsilons(usize_to_u32(ip), qnext, flags);
-            }
-            mem::swap(qcur, qnext);
-        }
-
-        // Now we set flags for immediately after the current byte. Since start
-        // states are processed separately, and are the only states that can
-        // have the StartText flag set, we therefore only need to worry about
-        // the StartLine flag here.
-        //
-        // We do also keep track of whether this DFA state contains a NFA state
-        // that is a matching state. This is precisely how we delay the DFA
-        // matching by one byte in order to process the special EOF sentinel
-        // byte. Namely, if this DFA state containing a matching NFA state,
-        // then it is the *next* DFA state that is marked as a match.
-        let mut empty_flags = EmptyFlags::default();
-        let mut state_flags = StateFlags::default();
-        empty_flags.start_line = b.as_byte().map_or(false, |b| b == b'\n');
-        if b.is_ascii_word() {
-            state_flags.set_word();
-        }
-        // Now follow all epsilon transitions again, but only after consuming
-        // the current byte.
-        qnext.clear();
-        for &ip in &*qcur {
-            match self.prog[ip as usize] {
-                // These states never happen in a byte-based program.
-                Char(_) | Ranges(_) => unreachable!(),
-                // These states are handled when following epsilon transitions.
-                Save(_) | Split(_) | EmptyLook(_) => {}
-                Match(_) => {
-                    state_flags.set_match();
-                    if !self.continue_past_first_match() {
-                        break;
-                    } else if self.prog.matches.len() > 1
-                        && !qnext.contains(ip as usize)
-                    {
-                        // If we are continuing on to find other matches,
-                        // then keep a record of the match states we've seen.
-                        qnext.insert(ip);
-                    }
-                }
-                Bytes(ref inst) => {
-                    if b.as_byte().map_or(false, |b| inst.matches(b)) {
-                        self.follow_epsilons(
-                            inst.goto as InstPtr,
-                            qnext,
-                            empty_flags,
-                        );
-                    }
-                }
-            }
-        }
-
-        let cache = if b.is_eof() && self.prog.matches.len() > 1 {
-            // If we're processing the last byte of the input and we're
-            // matching a regex set, then make the next state contain the
-            // previous states transitions. We do this so that the main
-            // matching loop can extract all of the match instructions.
-            mem::swap(qcur, qnext);
-            // And don't cache this state because it's totally bunk.
-            false
-        } else {
-            true
-        };
-
-        // We've now built up the set of NFA states that ought to comprise the
-        // next DFA state, so try to find it in the cache, and if it doesn't
-        // exist, cache it.
-        //
-        // N.B. We pass `&mut si` here because the cache may clear itself if
-        // it has gotten too full. When that happens, the location of the
-        // current state may change.
-        let mut next =
-            match self.cached_state(qnext, state_flags, Some(&mut si)) {
-                None => return None,
-                Some(next) => next,
-            };
-        if (self.start & !STATE_START) == next {
-            // Start states can never be match states since all matches are
-            // delayed by one byte.
-            debug_assert!(!self.state(next).flags().is_match());
-            next = self.start_ptr(next);
-        }
-        if next <= STATE_MAX && self.state(next).flags().is_match() {
-            next |= STATE_MATCH;
-        }
-        debug_assert!(next != STATE_UNKNOWN);
-        // And now store our state in the current state's next list.
-        if cache {
-            let cls = self.byte_class(b);
-            self.cache.trans.set_next(si, cls, next);
-        }
-        Some(next)
-    }
-
-    /// Follows the epsilon transitions starting at (and including) `ip`. The
-    /// resulting states are inserted into the ordered set `q`.
-    ///
-    /// Conditional epsilon transitions (i.e., empty width assertions) are only
-    /// followed if they are satisfied by the given flags, which should
-    /// represent the flags set at the current location in the input.
-    ///
-    /// If the current location corresponds to the empty string, then only the
-    /// end line and/or end text flags may be set. If the current location
-    /// corresponds to a real byte in the input, then only the start line
-    /// and/or start text flags may be set.
-    ///
-    /// As an exception to the above, when finding the initial state, any of
-    /// the above flags may be set:
-    ///
-    /// If matching starts at the beginning of the input, then start text and
-    /// start line should be set. If the input is empty, then end text and end
-    /// line should also be set.
-    ///
-    /// If matching starts after the beginning of the input, then only start
-    /// line should be set if the preceding byte is `\n`. End line should never
-    /// be set in this case. (Even if the following byte is a `\n`, it will
-    /// be handled in a subsequent DFA state.)
-    fn follow_epsilons(
-        &mut self,
-        ip: InstPtr,
-        q: &mut SparseSet,
-        flags: EmptyFlags,
-    ) {
-        use prog::EmptyLook::*;
-        use prog::Inst::*;
-
-        // We need to traverse the NFA to follow epsilon transitions, so avoid
-        // recursion with an explicit stack.
-        self.cache.stack.push(ip);
-        while let Some(mut ip) = self.cache.stack.pop() {
-            // Try to munch through as many states as possible without
-            // pushes/pops to the stack.
-            loop {
-                // Don't visit states we've already added.
-                if q.contains(ip as usize) {
-                    break;
-                }
-                q.insert(ip as usize);
-                match self.prog[ip as usize] {
-                    Char(_) | Ranges(_) => unreachable!(),
-                    Match(_) | Bytes(_) => {
-                        break;
-                    }
-                    EmptyLook(ref inst) => {
-                        // Only follow empty assertion states if our flags
-                        // satisfy the assertion.
-                        match inst.look {
-                            StartLine if flags.start_line => {
-                                ip = inst.goto as InstPtr;
-                            }
-                            EndLine if flags.end_line => {
-                                ip = inst.goto as InstPtr;
-                            }
-                            StartText if flags.start => {
-                                ip = inst.goto as InstPtr;
-                            }
-                            EndText if flags.end => {
-                                ip = inst.goto as InstPtr;
-                            }
-                            WordBoundaryAscii if flags.word_boundary => {
-                                ip = inst.goto as InstPtr;
-                            }
-                            NotWordBoundaryAscii
-                                if flags.not_word_boundary =>
-                            {
-                                ip = inst.goto as InstPtr;
-                            }
-                            WordBoundary if flags.word_boundary => {
-                                ip = inst.goto as InstPtr;
-                            }
-                            NotWordBoundary if flags.not_word_boundary => {
-                                ip = inst.goto as InstPtr;
-                            }
-                            StartLine | EndLine | StartText | EndText
-                            | WordBoundaryAscii | NotWordBoundaryAscii
-                            | WordBoundary | NotWordBoundary => {
-                                break;
-                            }
-                        }
-                    }
-                    Save(ref inst) => {
-                        ip = inst.goto as InstPtr;
-                    }
-                    Split(ref inst) => {
-                        self.cache.stack.push(inst.goto2 as InstPtr);
-                        ip = inst.goto1 as InstPtr;
-                    }
-                }
-            }
-        }
-    }
-
-    /// Find a previously computed state matching the given set of instructions
-    /// and is_match bool.
-    ///
-    /// The given set of instructions should represent a single state in the
-    /// NFA along with all states reachable without consuming any input.
-    ///
-    /// The is_match bool should be true if and only if the preceding DFA state
-    /// contains an NFA matching state. The cached state produced here will
-    /// then signify a match. (This enables us to delay a match by one byte,
-    /// in order to account for the EOF sentinel byte.)
-    ///
-    /// If the cache is full, then it is wiped before caching a new state.
-    ///
-    /// The current state should be specified if it exists, since it will need
-    /// to be preserved if the cache clears itself. (Start states are
-    /// always saved, so they should not be passed here.) It takes a mutable
-    /// pointer to the index because if the cache is cleared, the state's
-    /// location may change.
-    fn cached_state(
-        &mut self,
-        q: &SparseSet,
-        mut state_flags: StateFlags,
-        current_state: Option<&mut StatePtr>,
-    ) -> Option<StatePtr> {
-        // If we couldn't come up with a non-empty key to represent this state,
-        // then it is dead and can never lead to a match.
-        //
-        // Note that inst_flags represent the set of empty width assertions
-        // in q. We use this as an optimization in exec_byte to determine when
-        // we should follow epsilon transitions at the empty string preceding
-        // the current byte.
-        let key = match self.cached_state_key(q, &mut state_flags) {
-            None => return Some(STATE_DEAD),
-            Some(v) => v,
-        };
-        // In the cache? Cool. Done.
-        if let Some(si) = self.cache.compiled.get_ptr(&key) {
-            return Some(si);
-        }
-        // If the cache has gotten too big, wipe it.
-        if self.approximate_size() > self.prog.dfa_size_limit
-            && !self.clear_cache_and_save(current_state)
-        {
-            // Ooops. DFA is giving up.
-            return None;
-        }
-        // Allocate room for our state and add it.
-        self.add_state(key)
-    }
-
-    /// Produces a key suitable for describing a state in the DFA cache.
-    ///
-    /// The key invariant here is that equivalent keys are produced for any two
-    /// sets of ordered NFA states (and toggling of whether the previous NFA
-    /// states contain a match state) that do not discriminate a match for any
-    /// input.
-    ///
-    /// Specifically, q should be an ordered set of NFA states and is_match
-    /// should be true if and only if the previous NFA states contained a match
-    /// state.
-    fn cached_state_key(
-        &mut self,
-        q: &SparseSet,
-        state_flags: &mut StateFlags,
-    ) -> Option<State> {
-        use prog::Inst::*;
-
-        // We need to build up enough information to recognize pre-built states
-        // in the DFA. Generally speaking, this includes every instruction
-        // except for those which are purely epsilon transitions, e.g., the
-        // Save and Split instructions.
-        //
-        // Empty width assertions are also epsilon transitions, but since they
-        // are conditional, we need to make them part of a state's key in the
-        // cache.
-
-        let mut insts =
-            mem::replace(&mut self.cache.insts_scratch_space, vec![]);
-        insts.clear();
-        // Reserve 1 byte for flags.
-        insts.push(0);
-
-        let mut prev = 0;
-        for &ip in q {
-            let ip = usize_to_u32(ip);
-            match self.prog[ip as usize] {
-                Char(_) | Ranges(_) => unreachable!(),
-                Save(_) | Split(_) => {}
-                Bytes(_) => push_inst_ptr(&mut insts, &mut prev, ip),
-                EmptyLook(_) => {
-                    state_flags.set_empty();
-                    push_inst_ptr(&mut insts, &mut prev, ip)
-                }
-                Match(_) => {
-                    push_inst_ptr(&mut insts, &mut prev, ip);
-                    if !self.continue_past_first_match() {
-                        break;
-                    }
-                }
-            }
-        }
-        // If we couldn't transition to any other instructions and we didn't
-        // see a match when expanding NFA states previously, then this is a
-        // dead state and no amount of additional input can transition out
-        // of this state.
-        let opt_state = if insts.len() == 1 && !state_flags.is_match() {
-            None
-        } else {
-            let StateFlags(f) = *state_flags;
-            insts[0] = f;
-            Some(State { data: Arc::from(&*insts) })
-        };
-        self.cache.insts_scratch_space = insts;
-        opt_state
-    }
-
-    /// Clears the cache, but saves and restores current_state if it is not
-    /// none.
-    ///
-    /// The current state must be provided here in case its location in the
-    /// cache changes.
-    ///
-    /// This returns false if the cache is not cleared and the DFA should
-    /// give up.
-    fn clear_cache_and_save(
-        &mut self,
-        current_state: Option<&mut StatePtr>,
-    ) -> bool {
-        if self.cache.compiled.is_empty() {
-            // Nothing to clear...
-            return true;
-        }
-        match current_state {
-            None => self.clear_cache(),
-            Some(si) => {
-                let cur = self.state(*si).clone();
-                if !self.clear_cache() {
-                    return false;
-                }
-                // The unwrap is OK because we just cleared the cache and
-                // therefore know that the next state pointer won't exceed
-                // STATE_MAX.
-                *si = self.restore_state(cur).unwrap();
-                true
-            }
-        }
-    }
-
-    /// Wipes the state cache, but saves and restores the current start state.
-    ///
-    /// This returns false if the cache is not cleared and the DFA should
-    /// give up.
-    fn clear_cache(&mut self) -> bool {
-        // Bail out of the DFA if we're moving too "slowly."
-        // A heuristic from RE2: assume the DFA is too slow if it is processing
-        // 10 or fewer bytes per state.
-        // Additionally, we permit the cache to be flushed a few times before
-        // caling it quits.
-        let nstates = self.cache.compiled.len();
-        if self.cache.flush_count >= 3
-            && self.at >= self.last_cache_flush
-            && (self.at - self.last_cache_flush) <= 10 * nstates
-        {
-            return false;
-        }
-        // Update statistics tracking cache flushes.
-        self.last_cache_flush = self.at;
-        self.cache.flush_count += 1;
-
-        // OK, actually flush the cache.
-        let start = self.state(self.start & !STATE_START).clone();
-        let last_match = if self.last_match_si <= STATE_MAX {
-            Some(self.state(self.last_match_si).clone())
-        } else {
-            None
-        };
-        self.cache.reset_size();
-        self.cache.trans.clear();
-        self.cache.compiled.clear();
-        for s in &mut self.cache.start_states {
-            *s = STATE_UNKNOWN;
-        }
-        // The unwraps are OK because we just cleared the cache and therefore
-        // know that the next state pointer won't exceed STATE_MAX.
-        let start_ptr = self.restore_state(start).unwrap();
-        self.start = self.start_ptr(start_ptr);
-        if let Some(last_match) = last_match {
-            self.last_match_si = self.restore_state(last_match).unwrap();
-        }
-        true
-    }
-
-    /// Restores the given state back into the cache, and returns a pointer
-    /// to it.
-    fn restore_state(&mut self, state: State) -> Option<StatePtr> {
-        // If we've already stored this state, just return a pointer to it.
-        // None will be the wiser.
-        if let Some(si) = self.cache.compiled.get_ptr(&state) {
-            return Some(si);
-        }
-        self.add_state(state)
-    }
-
-    /// Returns the next state given the current state si and current byte
-    /// b. {qcur,qnext} are used as scratch space for storing ordered NFA
-    /// states.
-    ///
-    /// This tries to fetch the next state from the cache, but if that fails,
-    /// it computes the next state, caches it and returns a pointer to it.
-    ///
-    /// The pointer can be to a real state, or it can be STATE_DEAD.
-    /// STATE_UNKNOWN cannot be returned.
-    ///
-    /// None is returned if a new state could not be allocated (i.e., the DFA
-    /// ran out of space and thinks it's running too slowly).
-    fn next_state(
-        &mut self,
-        qcur: &mut SparseSet,
-        qnext: &mut SparseSet,
-        si: StatePtr,
-        b: Byte,
-    ) -> Option<StatePtr> {
-        if si == STATE_DEAD {
-            return Some(STATE_DEAD);
-        }
-        match self.cache.trans.next(si, self.byte_class(b)) {
-            STATE_UNKNOWN => self.exec_byte(qcur, qnext, si, b),
-            STATE_QUIT => None,
-            STATE_DEAD => Some(STATE_DEAD),
-            nsi => Some(nsi),
-        }
-    }
-
-    /// Computes and returns the start state, where searching begins at
-    /// position `at` in `text`. If the state has already been computed,
-    /// then it is pulled from the cache. If the state hasn't been cached,
-    /// then it is computed, cached and a pointer to it is returned.
-    ///
-    /// This may return STATE_DEAD but never STATE_UNKNOWN.
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn start_state(
-        &mut self,
-        q: &mut SparseSet,
-        empty_flags: EmptyFlags,
-        state_flags: StateFlags,
-    ) -> Option<StatePtr> {
-        // Compute an index into our cache of start states based on the set
-        // of empty/state flags set at the current position in the input. We
-        // don't use every flag since not all flags matter. For example, since
-        // matches are delayed by one byte, start states can never be match
-        // states.
-        let flagi = {
-            (((empty_flags.start as u8) << 0)
-                | ((empty_flags.end as u8) << 1)
-                | ((empty_flags.start_line as u8) << 2)
-                | ((empty_flags.end_line as u8) << 3)
-                | ((empty_flags.word_boundary as u8) << 4)
-                | ((empty_flags.not_word_boundary as u8) << 5)
-                | ((state_flags.is_word() as u8) << 6)) as usize
-        };
-        match self.cache.start_states[flagi] {
-            STATE_UNKNOWN => {}
-            STATE_DEAD => return Some(STATE_DEAD),
-            si => return Some(si),
-        }
-        q.clear();
-        let start = usize_to_u32(self.prog.start);
-        self.follow_epsilons(start, q, empty_flags);
-        // Start states can never be match states because we delay every match
-        // by one byte. Given an empty string and an empty match, the match
-        // won't actually occur until the DFA processes the special EOF
-        // sentinel byte.
-        let sp = match self.cached_state(q, state_flags, None) {
-            None => return None,
-            Some(sp) => self.start_ptr(sp),
-        };
-        self.cache.start_states[flagi] = sp;
-        Some(sp)
-    }
-
-    /// Computes the set of starting flags for the given position in text.
-    ///
-    /// This should only be used when executing the DFA forwards over the
-    /// input.
-    fn start_flags(&self, text: &[u8], at: usize) -> (EmptyFlags, StateFlags) {
-        let mut empty_flags = EmptyFlags::default();
-        let mut state_flags = StateFlags::default();
-        empty_flags.start = at == 0;
-        empty_flags.end = text.is_empty();
-        empty_flags.start_line = at == 0 || text[at - 1] == b'\n';
-        empty_flags.end_line = text.is_empty();
-
-        let is_word_last = at > 0 && Byte::byte(text[at - 1]).is_ascii_word();
-        let is_word = at < text.len() && Byte::byte(text[at]).is_ascii_word();
-        if is_word_last {
-            state_flags.set_word();
-        }
-        if is_word == is_word_last {
-            empty_flags.not_word_boundary = true;
-        } else {
-            empty_flags.word_boundary = true;
-        }
-        (empty_flags, state_flags)
-    }
-
-    /// Computes the set of starting flags for the given position in text.
-    ///
-    /// This should only be used when executing the DFA in reverse over the
-    /// input.
-    fn start_flags_reverse(
-        &self,
-        text: &[u8],
-        at: usize,
-    ) -> (EmptyFlags, StateFlags) {
-        let mut empty_flags = EmptyFlags::default();
-        let mut state_flags = StateFlags::default();
-        empty_flags.start = at == text.len();
-        empty_flags.end = text.is_empty();
-        empty_flags.start_line = at == text.len() || text[at] == b'\n';
-        empty_flags.end_line = text.is_empty();
-
-        let is_word_last =
-            at < text.len() && Byte::byte(text[at]).is_ascii_word();
-        let is_word = at > 0 && Byte::byte(text[at - 1]).is_ascii_word();
-        if is_word_last {
-            state_flags.set_word();
-        }
-        if is_word == is_word_last {
-            empty_flags.not_word_boundary = true;
-        } else {
-            empty_flags.word_boundary = true;
-        }
-        (empty_flags, state_flags)
-    }
-
-    /// Returns a reference to a State given a pointer to it.
-    fn state(&self, si: StatePtr) -> &State {
-        self.cache.compiled.get_state(si).unwrap()
-    }
-
-    /// Adds the given state to the DFA.
-    ///
-    /// This allocates room for transitions out of this state in
-    /// self.cache.trans. The transitions can be set with the returned
-    /// StatePtr.
-    ///
-    /// If None is returned, then the state limit was reached and the DFA
-    /// should quit.
-    fn add_state(&mut self, state: State) -> Option<StatePtr> {
-        // This will fail if the next state pointer exceeds STATE_PTR. In
-        // practice, the cache limit will prevent us from ever getting here,
-        // but maybe callers will set the cache size to something ridiculous...
-        let si = match self.cache.trans.add() {
-            None => return None,
-            Some(si) => si,
-        };
-        // If the program has a Unicode word boundary, then set any transitions
-        // for non-ASCII bytes to STATE_QUIT. If the DFA stumbles over such a
-        // transition, then it will quit and an alternative matching engine
-        // will take over.
-        if self.prog.has_unicode_word_boundary {
-            for b in 128..256 {
-                let cls = self.byte_class(Byte::byte(b as u8));
-                self.cache.trans.set_next(si, cls, STATE_QUIT);
-            }
-        }
-        // Finally, put our actual state on to our heap of states and index it
-        // so we can find it later.
-        self.cache.size += self.cache.trans.state_heap_size()
-            + state.data.len()
-            + (2 * mem::size_of::<State>())
-            + mem::size_of::<StatePtr>();
-        self.cache.compiled.insert(state, si);
-        // Transition table and set of states and map should all be in sync.
-        debug_assert!(
-            self.cache.compiled.len() == self.cache.trans.num_states()
-        );
-        Some(si)
-    }
-
-    /// Quickly finds the next occurrence of any literal prefixes in the regex.
-    /// If there are no literal prefixes, then the current position is
-    /// returned. If there are literal prefixes and one could not be found,
-    /// then None is returned.
-    ///
-    /// This should only be called when the DFA is in a start state.
-    fn prefix_at(&self, text: &[u8], at: usize) -> Option<usize> {
-        self.prog.prefixes.find(&text[at..]).map(|(s, _)| at + s)
-    }
-
-    /// Returns the number of byte classes required to discriminate transitions
-    /// in each state.
-    ///
-    /// invariant: num_byte_classes() == len(State.next)
-    fn num_byte_classes(&self) -> usize {
-        // We add 1 to account for the special EOF byte.
-        (self.prog.byte_classes[255] as usize + 1) + 1
-    }
-
-    /// Given an input byte or the special EOF sentinel, return its
-    /// corresponding byte class.
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn byte_class(&self, b: Byte) -> usize {
-        match b.as_byte() {
-            None => self.num_byte_classes() - 1,
-            Some(b) => self.u8_class(b),
-        }
-    }
-
-    /// Like byte_class, but explicitly for u8s.
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn u8_class(&self, b: u8) -> usize {
-        self.prog.byte_classes[b as usize] as usize
-    }
-
-    /// Returns true if the DFA should continue searching past the first match.
-    ///
-    /// Leftmost first semantics in the DFA are preserved by not following NFA
-    /// transitions after the first match is seen.
-    ///
-    /// On occasion, we want to avoid leftmost first semantics to find either
-    /// the longest match (for reverse search) or all possible matches (for
-    /// regex sets).
-    fn continue_past_first_match(&self) -> bool {
-        self.prog.is_reverse || self.prog.matches.len() > 1
-    }
-
-    /// Returns true if there is a prefix we can quickly search for.
-    fn has_prefix(&self) -> bool {
-        !self.prog.is_reverse
-            && !self.prog.prefixes.is_empty()
-            && !self.prog.is_anchored_start
-    }
-
-    /// Sets the STATE_START bit in the given state pointer if and only if
-    /// we have a prefix to scan for.
-    ///
-    /// If there's no prefix, then it's a waste to treat the start state
-    /// specially.
-    fn start_ptr(&self, si: StatePtr) -> StatePtr {
-        if self.has_prefix() {
-            si | STATE_START
-        } else {
-            si
-        }
-    }
-
-    /// Approximate size returns the approximate heap space currently used by
-    /// the DFA. It is used to determine whether the DFA's state cache needs to
-    /// be wiped. Namely, it is possible that for certain regexes on certain
-    /// inputs, a new state could be created for every byte of input. (This is
-    /// bad for memory use, so we bound it with a cache.)
-    fn approximate_size(&self) -> usize {
-        self.cache.size + self.prog.approximate_size()
-    }
-}
-
-/// An abstraction for representing a map of states. The map supports two
-/// different ways of state lookup. One is fast constant time access via a
-/// state pointer. The other is a hashmap lookup based on the DFA's
-/// constituent NFA states.
-///
-/// A DFA state internally uses an Arc such that we only need to store the
-/// set of NFA states on the heap once, even though we support looking up
-/// states by two different means. A more natural way to express this might
-/// use raw pointers, but an Arc is safe and effectively achieves the same
-/// thing.
-#[derive(Debug)]
-struct StateMap {
-    /// The keys are not actually static but rely on always pointing to a
-    /// buffer in `states` which will never be moved except when clearing
-    /// the map or on drop, in which case the keys of this map will be
-    /// removed before
-    map: HashMap<State, StatePtr>,
-    /// Our set of states. Note that `StatePtr / num_byte_classes` indexes
-    /// this Vec rather than just a `StatePtr`.
-    states: Vec<State>,
-    /// The number of byte classes in the DFA. Used to index `states`.
-    num_byte_classes: usize,
-}
-
-impl StateMap {
-    fn new(num_byte_classes: usize) -> StateMap {
-        StateMap {
-            map: HashMap::new(),
-            states: vec![],
-            num_byte_classes: num_byte_classes,
-        }
-    }
-
-    fn len(&self) -> usize {
-        self.states.len()
-    }
-
-    fn is_empty(&self) -> bool {
-        self.states.is_empty()
-    }
-
-    fn get_ptr(&self, state: &State) -> Option<StatePtr> {
-        self.map.get(state).cloned()
-    }
-
-    fn get_state(&self, si: StatePtr) -> Option<&State> {
-        self.states.get(si as usize / self.num_byte_classes)
-    }
-
-    fn insert(&mut self, state: State, si: StatePtr) {
-        self.map.insert(state.clone(), si);
-        self.states.push(state);
-    }
-
-    fn clear(&mut self) {
-        self.map.clear();
-        self.states.clear();
-    }
-}
-
-impl Transitions {
-    /// Create a new transition table.
-    ///
-    /// The number of byte classes corresponds to the stride. Every state will
-    /// have `num_byte_classes` slots for transitions.
-    fn new(num_byte_classes: usize) -> Transitions {
-        Transitions { table: vec![], num_byte_classes: num_byte_classes }
-    }
-
-    /// Returns the total number of states currently in this table.
-    fn num_states(&self) -> usize {
-        self.table.len() / self.num_byte_classes
-    }
-
-    /// Allocates room for one additional state and returns a pointer to it.
-    ///
-    /// If there's no more room, None is returned.
-    fn add(&mut self) -> Option<StatePtr> {
-        let si = self.table.len();
-        if si > STATE_MAX as usize {
-            return None;
-        }
-        self.table.extend(repeat(STATE_UNKNOWN).take(self.num_byte_classes));
-        Some(usize_to_u32(si))
-    }
-
-    /// Clears the table of all states.
-    fn clear(&mut self) {
-        self.table.clear();
-    }
-
-    /// Sets the transition from (si, cls) to next.
-    fn set_next(&mut self, si: StatePtr, cls: usize, next: StatePtr) {
-        self.table[si as usize + cls] = next;
-    }
-
-    /// Returns the transition corresponding to (si, cls).
-    fn next(&self, si: StatePtr, cls: usize) -> StatePtr {
-        self.table[si as usize + cls]
-    }
-
-    /// The heap size, in bytes, of a single state in the transition table.
-    fn state_heap_size(&self) -> usize {
-        self.num_byte_classes * mem::size_of::<StatePtr>()
-    }
-
-    /// Like `next`, but uses unchecked access and is therefore unsafe.
-    unsafe fn next_unchecked(&self, si: StatePtr, cls: usize) -> StatePtr {
-        debug_assert!((si as usize) < self.table.len());
-        debug_assert!(cls < self.num_byte_classes);
-        *self.table.get_unchecked(si as usize + cls)
-    }
-}
-
-impl StateFlags {
-    fn is_match(&self) -> bool {
-        self.0 & 0b0000000_1 > 0
-    }
-
-    fn set_match(&mut self) {
-        self.0 |= 0b0000000_1;
-    }
-
-    fn is_word(&self) -> bool {
-        self.0 & 0b000000_1_0 > 0
-    }
-
-    fn set_word(&mut self) {
-        self.0 |= 0b000000_1_0;
-    }
-
-    fn has_empty(&self) -> bool {
-        self.0 & 0b00000_1_00 > 0
-    }
-
-    fn set_empty(&mut self) {
-        self.0 |= 0b00000_1_00;
-    }
-}
-
-impl Byte {
-    fn byte(b: u8) -> Self {
-        Byte(b as u16)
-    }
-    fn eof() -> Self {
-        Byte(256)
-    }
-    fn is_eof(&self) -> bool {
-        self.0 == 256
-    }
-
-    fn is_ascii_word(&self) -> bool {
-        let b = match self.as_byte() {
-            None => return false,
-            Some(b) => b,
-        };
-        match b {
-            b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'_' => true,
-            _ => false,
-        }
-    }
-
-    fn as_byte(&self) -> Option<u8> {
-        if self.is_eof() {
-            None
-        } else {
-            Some(self.0 as u8)
-        }
-    }
-}
-
-impl fmt::Debug for State {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let ips: Vec<usize> = self.inst_ptrs().collect();
-        f.debug_struct("State")
-            .field("flags", &self.flags())
-            .field("insts", &ips)
-            .finish()
-    }
-}
-
-impl fmt::Debug for Transitions {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let mut fmtd = f.debug_map();
-        for si in 0..self.num_states() {
-            let s = si * self.num_byte_classes;
-            let e = s + self.num_byte_classes;
-            fmtd.entry(&si.to_string(), &TransitionsRow(&self.table[s..e]));
-        }
-        fmtd.finish()
-    }
-}
-
-struct TransitionsRow<'a>(&'a [StatePtr]);
-
-impl<'a> fmt::Debug for TransitionsRow<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let mut fmtd = f.debug_map();
-        for (b, si) in self.0.iter().enumerate() {
-            match *si {
-                STATE_UNKNOWN => {}
-                STATE_DEAD => {
-                    fmtd.entry(&vb(b as usize), &"DEAD");
-                }
-                si => {
-                    fmtd.entry(&vb(b as usize), &si.to_string());
-                }
-            }
-        }
-        fmtd.finish()
-    }
-}
-
-impl fmt::Debug for StateFlags {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("StateFlags")
-            .field("is_match", &self.is_match())
-            .field("is_word", &self.is_word())
-            .field("has_empty", &self.has_empty())
-            .finish()
-    }
-}
-
-/// Helper function for formatting a byte as a nice-to-read escaped string.
-fn vb(b: usize) -> String {
-    use std::ascii::escape_default;
-
-    if b > ::std::u8::MAX as usize {
-        "EOF".to_owned()
-    } else {
-        let escaped = escape_default(b as u8).collect::<Vec<u8>>();
-        String::from_utf8_lossy(&escaped).into_owned()
-    }
-}
-
-fn usize_to_u32(n: usize) -> u32 {
-    if (n as u64) > (::std::u32::MAX as u64) {
-        panic!("BUG: {} is too big to fit into u32", n)
-    }
-    n as u32
-}
-
-#[allow(dead_code)] // useful for debugging
-fn show_state_ptr(si: StatePtr) -> String {
-    let mut s = format!("{:?}", si & STATE_MAX);
-    if si == STATE_UNKNOWN {
-        s = format!("{} (unknown)", s);
-    }
-    if si == STATE_DEAD {
-        s = format!("{} (dead)", s);
-    }
-    if si == STATE_QUIT {
-        s = format!("{} (quit)", s);
-    }
-    if si & STATE_START > 0 {
-        s = format!("{} (start)", s);
-    }
-    if si & STATE_MATCH > 0 {
-        s = format!("{} (match)", s);
-    }
-    s
-}
-
-/// https://developers.google.com/protocol-buffers/docs/encoding#varints
-fn write_vari32(data: &mut Vec<u8>, n: i32) {
-    let mut un = (n as u32) << 1;
-    if n < 0 {
-        un = !un;
-    }
-    write_varu32(data, un)
-}
-
-/// https://developers.google.com/protocol-buffers/docs/encoding#varints
-fn read_vari32(data: &[u8]) -> (i32, usize) {
-    let (un, i) = read_varu32(data);
-    let mut n = (un >> 1) as i32;
-    if un & 1 != 0 {
-        n = !n;
-    }
-    (n, i)
-}
-
-/// https://developers.google.com/protocol-buffers/docs/encoding#varints
-fn write_varu32(data: &mut Vec<u8>, mut n: u32) {
-    while n >= 0b1000_0000 {
-        data.push((n as u8) | 0b1000_0000);
-        n >>= 7;
-    }
-    data.push(n as u8);
-}
-
-/// https://developers.google.com/protocol-buffers/docs/encoding#varints
-fn read_varu32(data: &[u8]) -> (u32, usize) {
-    let mut n: u32 = 0;
-    let mut shift: u32 = 0;
-    for (i, &b) in data.iter().enumerate() {
-        if b < 0b1000_0000 {
-            return (n | ((b as u32) << shift), i + 1);
-        }
-        n |= ((b as u32) & 0b0111_1111) << shift;
-        shift += 7;
-    }
-    (0, 0)
-}
-
-#[cfg(test)]
-mod tests {
-    extern crate rand;
-
-    use super::{
-        push_inst_ptr, read_vari32, read_varu32, write_vari32, write_varu32,
-        State, StateFlags,
-    };
-    use quickcheck::{quickcheck, QuickCheck, StdGen};
-    use std::sync::Arc;
-
-    #[test]
-    fn prop_state_encode_decode() {
-        fn p(ips: Vec<u32>, flags: u8) -> bool {
-            let mut data = vec![flags];
-            let mut prev = 0;
-            for &ip in ips.iter() {
-                push_inst_ptr(&mut data, &mut prev, ip);
-            }
-            let state = State { data: Arc::from(&data[..]) };
-
-            let expected: Vec<usize> =
-                ips.into_iter().map(|ip| ip as usize).collect();
-            let got: Vec<usize> = state.inst_ptrs().collect();
-            expected == got && state.flags() == StateFlags(flags)
-        }
-        QuickCheck::new()
-            .gen(StdGen::new(self::rand::thread_rng(), 10_000))
-            .quickcheck(p as fn(Vec<u32>, u8) -> bool);
-    }
-
-    #[test]
-    fn prop_read_write_u32() {
-        fn p(n: u32) -> bool {
-            let mut buf = vec![];
-            write_varu32(&mut buf, n);
-            let (got, nread) = read_varu32(&buf);
-            nread == buf.len() && got == n
-        }
-        quickcheck(p as fn(u32) -> bool);
-    }
-
-    #[test]
-    fn prop_read_write_i32() {
-        fn p(n: i32) -> bool {
-            let mut buf = vec![];
-            write_vari32(&mut buf, n);
-            let (got, nread) = read_vari32(&buf);
-            nread == buf.len() && got == n
-        }
-        quickcheck(p as fn(i32) -> bool);
-    }
-}
diff --git a/vendor/regex-1.4.3/src/error.rs b/vendor/regex-1.4.3/src/error.rs
deleted file mode 100644 (file)
index 1c32c85..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-use std::fmt;
-use std::iter::repeat;
-
-/// An error that occurred during parsing or compiling a regular expression.
-#[derive(Clone, PartialEq)]
-pub enum Error {
-    /// A syntax error.
-    Syntax(String),
-    /// The compiled program exceeded the set size limit.
-    /// The argument is the size limit imposed.
-    CompiledTooBig(usize),
-    /// Hints that destructuring should not be exhaustive.
-    ///
-    /// This enum may grow additional variants, so this makes sure clients
-    /// don't count on exhaustive matching. (Otherwise, adding a new variant
-    /// could break existing code.)
-    #[doc(hidden)]
-    __Nonexhaustive,
-}
-
-impl ::std::error::Error for Error {
-    // TODO: Remove this method entirely on the next breaking semver release.
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        match *self {
-            Error::Syntax(ref err) => err,
-            Error::CompiledTooBig(_) => "compiled program too big",
-            Error::__Nonexhaustive => unreachable!(),
-        }
-    }
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Error::Syntax(ref err) => err.fmt(f),
-            Error::CompiledTooBig(limit) => write!(
-                f,
-                "Compiled regex exceeds size limit of {} bytes.",
-                limit
-            ),
-            Error::__Nonexhaustive => unreachable!(),
-        }
-    }
-}
-
-// We implement our own Debug implementation so that we show nicer syntax
-// errors when people use `Regex::new(...).unwrap()`. It's a little weird,
-// but the `Syntax` variant is already storing a `String` anyway, so we might
-// as well format it nicely.
-impl fmt::Debug for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Error::Syntax(ref err) => {
-                let hr: String = repeat('~').take(79).collect();
-                writeln!(f, "Syntax(")?;
-                writeln!(f, "{}", hr)?;
-                writeln!(f, "{}", err)?;
-                writeln!(f, "{}", hr)?;
-                write!(f, ")")?;
-                Ok(())
-            }
-            Error::CompiledTooBig(limit) => {
-                f.debug_tuple("CompiledTooBig").field(&limit).finish()
-            }
-            Error::__Nonexhaustive => {
-                f.debug_tuple("__Nonexhaustive").finish()
-            }
-        }
-    }
-}
diff --git a/vendor/regex-1.4.3/src/exec.rs b/vendor/regex-1.4.3/src/exec.rs
deleted file mode 100644 (file)
index e1aae87..0000000
+++ /dev/null
@@ -1,1637 +0,0 @@
-use std::cell::RefCell;
-use std::collections::HashMap;
-use std::sync::Arc;
-
-#[cfg(feature = "perf-literal")]
-use aho_corasick::{AhoCorasick, AhoCorasickBuilder, MatchKind};
-use syntax::hir::literal::Literals;
-use syntax::hir::Hir;
-use syntax::ParserBuilder;
-
-use backtrack;
-use cache::{Cached, CachedGuard};
-use compile::Compiler;
-#[cfg(feature = "perf-dfa")]
-use dfa;
-use error::Error;
-use input::{ByteInput, CharInput};
-use literal::LiteralSearcher;
-use pikevm;
-use prog::Program;
-use re_builder::RegexOptions;
-use re_bytes;
-use re_set;
-use re_trait::{Locations, RegularExpression, Slot};
-use re_unicode;
-use utf8::next_utf8;
-
-/// `Exec` manages the execution of a regular expression.
-///
-/// In particular, this manages the various compiled forms of a single regular
-/// expression and the choice of which matching engine to use to execute a
-/// regular expression.
-#[derive(Debug)]
-pub struct Exec {
-    /// All read only state.
-    ro: Arc<ExecReadOnly>,
-    /// Caches for the various matching engines.
-    cache: Cached<ProgramCache>,
-}
-
-/// `ExecNoSync` is like `Exec`, except it embeds a reference to a cache. This
-/// means it is no longer Sync, but we can now avoid the overhead of
-/// synchronization to fetch the cache.
-#[derive(Debug)]
-pub struct ExecNoSync<'c> {
-    /// All read only state.
-    ro: &'c Arc<ExecReadOnly>,
-    /// Caches for the various matching engines.
-    cache: CachedGuard<'c, ProgramCache>,
-}
-
-/// `ExecNoSyncStr` is like `ExecNoSync`, but matches on &str instead of &[u8].
-#[derive(Debug)]
-pub struct ExecNoSyncStr<'c>(ExecNoSync<'c>);
-
-/// `ExecReadOnly` comprises all read only state for a regex. Namely, all such
-/// state is determined at compile time and never changes during search.
-#[derive(Debug)]
-struct ExecReadOnly {
-    /// The original regular expressions given by the caller to compile.
-    res: Vec<String>,
-    /// A compiled program that is used in the NFA simulation and backtracking.
-    /// It can be byte-based or Unicode codepoint based.
-    ///
-    /// N.B. It is not possibly to make this byte-based from the public API.
-    /// It is only used for testing byte based programs in the NFA simulations.
-    nfa: Program,
-    /// A compiled byte based program for DFA execution. This is only used
-    /// if a DFA can be executed. (Currently, only word boundary assertions are
-    /// not supported.) Note that this program contains an embedded `.*?`
-    /// preceding the first capture group, unless the regex is anchored at the
-    /// beginning.
-    dfa: Program,
-    /// The same as above, except the program is reversed (and there is no
-    /// preceding `.*?`). This is used by the DFA to find the starting location
-    /// of matches.
-    dfa_reverse: Program,
-    /// A set of suffix literals extracted from the regex.
-    ///
-    /// Prefix literals are stored on the `Program`, since they are used inside
-    /// the matching engines.
-    suffixes: LiteralSearcher,
-    /// An Aho-Corasick automaton with leftmost-first match semantics.
-    ///
-    /// This is only set when the entire regex is a simple unanchored
-    /// alternation of literals. We could probably use it more circumstances,
-    /// but this is already hacky enough in this architecture.
-    ///
-    /// N.B. We use u32 as a state ID representation under the assumption that
-    /// if we were to exhaust the ID space, we probably would have long
-    /// surpassed the compilation size limit.
-    #[cfg(feature = "perf-literal")]
-    ac: Option<AhoCorasick<u32>>,
-    /// match_type encodes as much upfront knowledge about how we're going to
-    /// execute a search as possible.
-    match_type: MatchType,
-}
-
-/// Facilitates the construction of an executor by exposing various knobs
-/// to control how a regex is executed and what kinds of resources it's
-/// permitted to use.
-// `ExecBuilder` is only public via the `internal` module, so avoid deriving
-// `Debug`.
-#[allow(missing_debug_implementations)]
-pub struct ExecBuilder {
-    options: RegexOptions,
-    match_type: Option<MatchType>,
-    bytes: bool,
-    only_utf8: bool,
-}
-
-/// Parsed represents a set of parsed regular expressions and their detected
-/// literals.
-struct Parsed {
-    exprs: Vec<Hir>,
-    prefixes: Literals,
-    suffixes: Literals,
-    bytes: bool,
-}
-
-impl ExecBuilder {
-    /// Create a regex execution builder.
-    ///
-    /// This uses default settings for everything except the regex itself,
-    /// which must be provided. Further knobs can be set by calling methods,
-    /// and then finally, `build` to actually create the executor.
-    pub fn new(re: &str) -> Self {
-        Self::new_many(&[re])
-    }
-
-    /// Like new, but compiles the union of the given regular expressions.
-    ///
-    /// Note that when compiling 2 or more regular expressions, capture groups
-    /// are completely unsupported. (This means both `find` and `captures`
-    /// wont work.)
-    pub fn new_many<I, S>(res: I) -> Self
-    where
-        S: AsRef<str>,
-        I: IntoIterator<Item = S>,
-    {
-        let mut opts = RegexOptions::default();
-        opts.pats = res.into_iter().map(|s| s.as_ref().to_owned()).collect();
-        Self::new_options(opts)
-    }
-
-    /// Create a regex execution builder.
-    pub fn new_options(opts: RegexOptions) -> Self {
-        ExecBuilder {
-            options: opts,
-            match_type: None,
-            bytes: false,
-            only_utf8: true,
-        }
-    }
-
-    /// Set the matching engine to be automatically determined.
-    ///
-    /// This is the default state and will apply whatever optimizations are
-    /// possible, such as running a DFA.
-    ///
-    /// This overrides whatever was previously set via the `nfa` or
-    /// `bounded_backtracking` methods.
-    pub fn automatic(mut self) -> Self {
-        self.match_type = None;
-        self
-    }
-
-    /// Sets the matching engine to use the NFA algorithm no matter what
-    /// optimizations are possible.
-    ///
-    /// This overrides whatever was previously set via the `automatic` or
-    /// `bounded_backtracking` methods.
-    pub fn nfa(mut self) -> Self {
-        self.match_type = Some(MatchType::Nfa(MatchNfaType::PikeVM));
-        self
-    }
-
-    /// Sets the matching engine to use a bounded backtracking engine no
-    /// matter what optimizations are possible.
-    ///
-    /// One must use this with care, since the bounded backtracking engine
-    /// uses memory proportion to `len(regex) * len(text)`.
-    ///
-    /// This overrides whatever was previously set via the `automatic` or
-    /// `nfa` methods.
-    pub fn bounded_backtracking(mut self) -> Self {
-        self.match_type = Some(MatchType::Nfa(MatchNfaType::Backtrack));
-        self
-    }
-
-    /// Compiles byte based programs for use with the NFA matching engines.
-    ///
-    /// By default, the NFA engines match on Unicode scalar values. They can
-    /// be made to use byte based programs instead. In general, the byte based
-    /// programs are slower because of a less efficient encoding of character
-    /// classes.
-    ///
-    /// Note that this does not impact DFA matching engines, which always
-    /// execute on bytes.
-    pub fn bytes(mut self, yes: bool) -> Self {
-        self.bytes = yes;
-        self
-    }
-
-    /// When disabled, the program compiled may match arbitrary bytes.
-    ///
-    /// When enabled (the default), all compiled programs exclusively match
-    /// valid UTF-8 bytes.
-    pub fn only_utf8(mut self, yes: bool) -> Self {
-        self.only_utf8 = yes;
-        self
-    }
-
-    /// Set the Unicode flag.
-    pub fn unicode(mut self, yes: bool) -> Self {
-        self.options.unicode = yes;
-        self
-    }
-
-    /// Parse the current set of patterns into their AST and extract literals.
-    fn parse(&self) -> Result<Parsed, Error> {
-        let mut exprs = Vec::with_capacity(self.options.pats.len());
-        let mut prefixes = Some(Literals::empty());
-        let mut suffixes = Some(Literals::empty());
-        let mut bytes = false;
-        let is_set = self.options.pats.len() > 1;
-        // If we're compiling a regex set and that set has any anchored
-        // expressions, then disable all literal optimizations.
-        for pat in &self.options.pats {
-            let mut parser = ParserBuilder::new()
-                .octal(self.options.octal)
-                .case_insensitive(self.options.case_insensitive)
-                .multi_line(self.options.multi_line)
-                .dot_matches_new_line(self.options.dot_matches_new_line)
-                .swap_greed(self.options.swap_greed)
-                .ignore_whitespace(self.options.ignore_whitespace)
-                .unicode(self.options.unicode)
-                .allow_invalid_utf8(!self.only_utf8)
-                .nest_limit(self.options.nest_limit)
-                .build();
-            let expr =
-                parser.parse(pat).map_err(|e| Error::Syntax(e.to_string()))?;
-            bytes = bytes || !expr.is_always_utf8();
-
-            if cfg!(feature = "perf-literal") {
-                if !expr.is_anchored_start() && expr.is_any_anchored_start() {
-                    // Partial anchors unfortunately make it hard to use
-                    // prefixes, so disable them.
-                    prefixes = None;
-                } else if is_set && expr.is_anchored_start() {
-                    // Regex sets with anchors do not go well with literal
-                    // optimizations.
-                    prefixes = None;
-                }
-                prefixes = prefixes.and_then(|mut prefixes| {
-                    if !prefixes.union_prefixes(&expr) {
-                        None
-                    } else {
-                        Some(prefixes)
-                    }
-                });
-
-                if !expr.is_anchored_end() && expr.is_any_anchored_end() {
-                    // Partial anchors unfortunately make it hard to use
-                    // suffixes, so disable them.
-                    suffixes = None;
-                } else if is_set && expr.is_anchored_end() {
-                    // Regex sets with anchors do not go well with literal
-                    // optimizations.
-                    suffixes = None;
-                }
-                suffixes = suffixes.and_then(|mut suffixes| {
-                    if !suffixes.union_suffixes(&expr) {
-                        None
-                    } else {
-                        Some(suffixes)
-                    }
-                });
-            }
-            exprs.push(expr);
-        }
-        Ok(Parsed {
-            exprs: exprs,
-            prefixes: prefixes.unwrap_or_else(Literals::empty),
-            suffixes: suffixes.unwrap_or_else(Literals::empty),
-            bytes: bytes,
-        })
-    }
-
-    /// Build an executor that can run a regular expression.
-    pub fn build(self) -> Result<Exec, Error> {
-        // Special case when we have no patterns to compile.
-        // This can happen when compiling a regex set.
-        if self.options.pats.is_empty() {
-            let ro = Arc::new(ExecReadOnly {
-                res: vec![],
-                nfa: Program::new(),
-                dfa: Program::new(),
-                dfa_reverse: Program::new(),
-                suffixes: LiteralSearcher::empty(),
-                #[cfg(feature = "perf-literal")]
-                ac: None,
-                match_type: MatchType::Nothing,
-            });
-            return Ok(Exec { ro: ro, cache: Cached::new() });
-        }
-        let parsed = self.parse()?;
-        let mut nfa = Compiler::new()
-            .size_limit(self.options.size_limit)
-            .bytes(self.bytes || parsed.bytes)
-            .only_utf8(self.only_utf8)
-            .compile(&parsed.exprs)?;
-        let mut dfa = Compiler::new()
-            .size_limit(self.options.size_limit)
-            .dfa(true)
-            .only_utf8(self.only_utf8)
-            .compile(&parsed.exprs)?;
-        let mut dfa_reverse = Compiler::new()
-            .size_limit(self.options.size_limit)
-            .dfa(true)
-            .only_utf8(self.only_utf8)
-            .reverse(true)
-            .compile(&parsed.exprs)?;
-
-        #[cfg(feature = "perf-literal")]
-        let ac = self.build_aho_corasick(&parsed);
-        nfa.prefixes = LiteralSearcher::prefixes(parsed.prefixes);
-        dfa.prefixes = nfa.prefixes.clone();
-        dfa.dfa_size_limit = self.options.dfa_size_limit;
-        dfa_reverse.dfa_size_limit = self.options.dfa_size_limit;
-
-        let mut ro = ExecReadOnly {
-            res: self.options.pats,
-            nfa: nfa,
-            dfa: dfa,
-            dfa_reverse: dfa_reverse,
-            suffixes: LiteralSearcher::suffixes(parsed.suffixes),
-            #[cfg(feature = "perf-literal")]
-            ac: ac,
-            match_type: MatchType::Nothing,
-        };
-        ro.match_type = ro.choose_match_type(self.match_type);
-
-        let ro = Arc::new(ro);
-        Ok(Exec { ro: ro, cache: Cached::new() })
-    }
-
-    #[cfg(feature = "perf-literal")]
-    fn build_aho_corasick(&self, parsed: &Parsed) -> Option<AhoCorasick<u32>> {
-        if parsed.exprs.len() != 1 {
-            return None;
-        }
-        let lits = match alternation_literals(&parsed.exprs[0]) {
-            None => return None,
-            Some(lits) => lits,
-        };
-        // If we have a small number of literals, then let Teddy handle
-        // things (see literal/mod.rs).
-        if lits.len() <= 32 {
-            return None;
-        }
-        Some(
-            AhoCorasickBuilder::new()
-                .match_kind(MatchKind::LeftmostFirst)
-                .auto_configure(&lits)
-                // We always want this to reduce size, regardless
-                // of what auto-configure does.
-                .byte_classes(true)
-                .build_with_size::<u32, _, _>(&lits)
-                // This should never happen because we'd long exceed the
-                // compilation limit for regexes first.
-                .expect("AC automaton too big"),
-        )
-    }
-}
-
-impl<'c> RegularExpression for ExecNoSyncStr<'c> {
-    type Text = str;
-
-    fn slots_len(&self) -> usize {
-        self.0.slots_len()
-    }
-
-    fn next_after_empty(&self, text: &str, i: usize) -> usize {
-        next_utf8(text.as_bytes(), i)
-    }
-
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn shortest_match_at(&self, text: &str, start: usize) -> Option<usize> {
-        self.0.shortest_match_at(text.as_bytes(), start)
-    }
-
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn is_match_at(&self, text: &str, start: usize) -> bool {
-        self.0.is_match_at(text.as_bytes(), start)
-    }
-
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn find_at(&self, text: &str, start: usize) -> Option<(usize, usize)> {
-        self.0.find_at(text.as_bytes(), start)
-    }
-
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn captures_read_at(
-        &self,
-        locs: &mut Locations,
-        text: &str,
-        start: usize,
-    ) -> Option<(usize, usize)> {
-        self.0.captures_read_at(locs, text.as_bytes(), start)
-    }
-}
-
-impl<'c> RegularExpression for ExecNoSync<'c> {
-    type Text = [u8];
-
-    /// Returns the number of capture slots in the regular expression. (There
-    /// are two slots for every capture group, corresponding to possibly empty
-    /// start and end locations of the capture.)
-    fn slots_len(&self) -> usize {
-        self.ro.nfa.captures.len() * 2
-    }
-
-    fn next_after_empty(&self, _text: &[u8], i: usize) -> usize {
-        i + 1
-    }
-
-    /// Returns the end of a match location, possibly occurring before the
-    /// end location of the correct leftmost-first match.
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn shortest_match_at(&self, text: &[u8], start: usize) -> Option<usize> {
-        if !self.is_anchor_end_match(text) {
-            return None;
-        }
-        match self.ro.match_type {
-            #[cfg(feature = "perf-literal")]
-            MatchType::Literal(ty) => {
-                self.find_literals(ty, text, start).map(|(_, e)| e)
-            }
-            #[cfg(feature = "perf-dfa")]
-            MatchType::Dfa | MatchType::DfaMany => {
-                match self.shortest_dfa(text, start) {
-                    dfa::Result::Match(end) => Some(end),
-                    dfa::Result::NoMatch(_) => None,
-                    dfa::Result::Quit => self.shortest_nfa(text, start),
-                }
-            }
-            #[cfg(feature = "perf-dfa")]
-            MatchType::DfaAnchoredReverse => {
-                match dfa::Fsm::reverse(
-                    &self.ro.dfa_reverse,
-                    self.cache.value(),
-                    true,
-                    &text[start..],
-                    text.len(),
-                ) {
-                    dfa::Result::Match(_) => Some(text.len()),
-                    dfa::Result::NoMatch(_) => None,
-                    dfa::Result::Quit => self.shortest_nfa(text, start),
-                }
-            }
-            #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
-            MatchType::DfaSuffix => {
-                match self.shortest_dfa_reverse_suffix(text, start) {
-                    dfa::Result::Match(e) => Some(e),
-                    dfa::Result::NoMatch(_) => None,
-                    dfa::Result::Quit => self.shortest_nfa(text, start),
-                }
-            }
-            MatchType::Nfa(ty) => self.shortest_nfa_type(ty, text, start),
-            MatchType::Nothing => None,
-        }
-    }
-
-    /// Returns true if and only if the regex matches text.
-    ///
-    /// For single regular expressions, this is equivalent to calling
-    /// shortest_match(...).is_some().
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn is_match_at(&self, text: &[u8], start: usize) -> bool {
-        if !self.is_anchor_end_match(text) {
-            return false;
-        }
-        // We need to do this dance because shortest_match relies on the NFA
-        // filling in captures[1], but a RegexSet has no captures. In other
-        // words, a RegexSet can't (currently) use shortest_match. ---AG
-        match self.ro.match_type {
-            #[cfg(feature = "perf-literal")]
-            MatchType::Literal(ty) => {
-                self.find_literals(ty, text, start).is_some()
-            }
-            #[cfg(feature = "perf-dfa")]
-            MatchType::Dfa | MatchType::DfaMany => {
-                match self.shortest_dfa(text, start) {
-                    dfa::Result::Match(_) => true,
-                    dfa::Result::NoMatch(_) => false,
-                    dfa::Result::Quit => self.match_nfa(text, start),
-                }
-            }
-            #[cfg(feature = "perf-dfa")]
-            MatchType::DfaAnchoredReverse => {
-                match dfa::Fsm::reverse(
-                    &self.ro.dfa_reverse,
-                    self.cache.value(),
-                    true,
-                    &text[start..],
-                    text.len(),
-                ) {
-                    dfa::Result::Match(_) => true,
-                    dfa::Result::NoMatch(_) => false,
-                    dfa::Result::Quit => self.match_nfa(text, start),
-                }
-            }
-            #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
-            MatchType::DfaSuffix => {
-                match self.shortest_dfa_reverse_suffix(text, start) {
-                    dfa::Result::Match(_) => true,
-                    dfa::Result::NoMatch(_) => false,
-                    dfa::Result::Quit => self.match_nfa(text, start),
-                }
-            }
-            MatchType::Nfa(ty) => self.match_nfa_type(ty, text, start),
-            MatchType::Nothing => false,
-        }
-    }
-
-    /// Finds the start and end location of the leftmost-first match, starting
-    /// at the given location.
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn find_at(&self, text: &[u8], start: usize) -> Option<(usize, usize)> {
-        if !self.is_anchor_end_match(text) {
-            return None;
-        }
-        match self.ro.match_type {
-            #[cfg(feature = "perf-literal")]
-            MatchType::Literal(ty) => self.find_literals(ty, text, start),
-            #[cfg(feature = "perf-dfa")]
-            MatchType::Dfa => match self.find_dfa_forward(text, start) {
-                dfa::Result::Match((s, e)) => Some((s, e)),
-                dfa::Result::NoMatch(_) => None,
-                dfa::Result::Quit => {
-                    self.find_nfa(MatchNfaType::Auto, text, start)
-                }
-            },
-            #[cfg(feature = "perf-dfa")]
-            MatchType::DfaAnchoredReverse => {
-                match self.find_dfa_anchored_reverse(text, start) {
-                    dfa::Result::Match((s, e)) => Some((s, e)),
-                    dfa::Result::NoMatch(_) => None,
-                    dfa::Result::Quit => {
-                        self.find_nfa(MatchNfaType::Auto, text, start)
-                    }
-                }
-            }
-            #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
-            MatchType::DfaSuffix => {
-                match self.find_dfa_reverse_suffix(text, start) {
-                    dfa::Result::Match((s, e)) => Some((s, e)),
-                    dfa::Result::NoMatch(_) => None,
-                    dfa::Result::Quit => {
-                        self.find_nfa(MatchNfaType::Auto, text, start)
-                    }
-                }
-            }
-            MatchType::Nfa(ty) => self.find_nfa(ty, text, start),
-            MatchType::Nothing => None,
-            #[cfg(feature = "perf-dfa")]
-            MatchType::DfaMany => {
-                unreachable!("BUG: RegexSet cannot be used with find")
-            }
-        }
-    }
-
-    /// Finds the start and end location of the leftmost-first match and also
-    /// fills in all matching capture groups.
-    ///
-    /// The number of capture slots given should be equal to the total number
-    /// of capture slots in the compiled program.
-    ///
-    /// Note that the first two slots always correspond to the start and end
-    /// locations of the overall match.
-    fn captures_read_at(
-        &self,
-        locs: &mut Locations,
-        text: &[u8],
-        start: usize,
-    ) -> Option<(usize, usize)> {
-        let slots = locs.as_slots();
-        for slot in slots.iter_mut() {
-            *slot = None;
-        }
-        // If the caller unnecessarily uses this, then we try to save them
-        // from themselves.
-        match slots.len() {
-            0 => return self.find_at(text, start),
-            2 => {
-                return self.find_at(text, start).map(|(s, e)| {
-                    slots[0] = Some(s);
-                    slots[1] = Some(e);
-                    (s, e)
-                });
-            }
-            _ => {} // fallthrough
-        }
-        if !self.is_anchor_end_match(text) {
-            return None;
-        }
-        match self.ro.match_type {
-            #[cfg(feature = "perf-literal")]
-            MatchType::Literal(ty) => {
-                self.find_literals(ty, text, start).and_then(|(s, e)| {
-                    self.captures_nfa_type(
-                        MatchNfaType::Auto,
-                        slots,
-                        text,
-                        s,
-                        e,
-                    )
-                })
-            }
-            #[cfg(feature = "perf-dfa")]
-            MatchType::Dfa => {
-                if self.ro.nfa.is_anchored_start {
-                    self.captures_nfa(slots, text, start)
-                } else {
-                    match self.find_dfa_forward(text, start) {
-                        dfa::Result::Match((s, e)) => self.captures_nfa_type(
-                            MatchNfaType::Auto,
-                            slots,
-                            text,
-                            s,
-                            e,
-                        ),
-                        dfa::Result::NoMatch(_) => None,
-                        dfa::Result::Quit => {
-                            self.captures_nfa(slots, text, start)
-                        }
-                    }
-                }
-            }
-            #[cfg(feature = "perf-dfa")]
-            MatchType::DfaAnchoredReverse => {
-                match self.find_dfa_anchored_reverse(text, start) {
-                    dfa::Result::Match((s, e)) => self.captures_nfa_type(
-                        MatchNfaType::Auto,
-                        slots,
-                        text,
-                        s,
-                        e,
-                    ),
-                    dfa::Result::NoMatch(_) => None,
-                    dfa::Result::Quit => self.captures_nfa(slots, text, start),
-                }
-            }
-            #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
-            MatchType::DfaSuffix => {
-                match self.find_dfa_reverse_suffix(text, start) {
-                    dfa::Result::Match((s, e)) => self.captures_nfa_type(
-                        MatchNfaType::Auto,
-                        slots,
-                        text,
-                        s,
-                        e,
-                    ),
-                    dfa::Result::NoMatch(_) => None,
-                    dfa::Result::Quit => self.captures_nfa(slots, text, start),
-                }
-            }
-            MatchType::Nfa(ty) => {
-                self.captures_nfa_type(ty, slots, text, start, text.len())
-            }
-            MatchType::Nothing => None,
-            #[cfg(feature = "perf-dfa")]
-            MatchType::DfaMany => {
-                unreachable!("BUG: RegexSet cannot be used with captures")
-            }
-        }
-    }
-}
-
-impl<'c> ExecNoSync<'c> {
-    /// Finds the leftmost-first match using only literal search.
-    #[cfg(feature = "perf-literal")]
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn find_literals(
-        &self,
-        ty: MatchLiteralType,
-        text: &[u8],
-        start: usize,
-    ) -> Option<(usize, usize)> {
-        use self::MatchLiteralType::*;
-        match ty {
-            Unanchored => {
-                let lits = &self.ro.nfa.prefixes;
-                lits.find(&text[start..]).map(|(s, e)| (start + s, start + e))
-            }
-            AnchoredStart => {
-                let lits = &self.ro.nfa.prefixes;
-                if start == 0 || !self.ro.nfa.is_anchored_start {
-                    lits.find_start(&text[start..])
-                        .map(|(s, e)| (start + s, start + e))
-                } else {
-                    None
-                }
-            }
-            AnchoredEnd => {
-                let lits = &self.ro.suffixes;
-                lits.find_end(&text[start..])
-                    .map(|(s, e)| (start + s, start + e))
-            }
-            AhoCorasick => self
-                .ro
-                .ac
-                .as_ref()
-                .unwrap()
-                .find(&text[start..])
-                .map(|m| (start + m.start(), start + m.end())),
-        }
-    }
-
-    /// Finds the leftmost-first match (start and end) using only the DFA.
-    ///
-    /// If the result returned indicates that the DFA quit, then another
-    /// matching engine should be used.
-    #[cfg(feature = "perf-dfa")]
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn find_dfa_forward(
-        &self,
-        text: &[u8],
-        start: usize,
-    ) -> dfa::Result<(usize, usize)> {
-        use dfa::Result::*;
-        let end = match dfa::Fsm::forward(
-            &self.ro.dfa,
-            self.cache.value(),
-            false,
-            text,
-            start,
-        ) {
-            NoMatch(i) => return NoMatch(i),
-            Quit => return Quit,
-            Match(end) if start == end => return Match((start, start)),
-            Match(end) => end,
-        };
-        // Now run the DFA in reverse to find the start of the match.
-        match dfa::Fsm::reverse(
-            &self.ro.dfa_reverse,
-            self.cache.value(),
-            false,
-            &text[start..],
-            end - start,
-        ) {
-            Match(s) => Match((start + s, end)),
-            NoMatch(i) => NoMatch(i),
-            Quit => Quit,
-        }
-    }
-
-    /// Finds the leftmost-first match (start and end) using only the DFA,
-    /// but assumes the regex is anchored at the end and therefore starts at
-    /// the end of the regex and matches in reverse.
-    ///
-    /// If the result returned indicates that the DFA quit, then another
-    /// matching engine should be used.
-    #[cfg(feature = "perf-dfa")]
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn find_dfa_anchored_reverse(
-        &self,
-        text: &[u8],
-        start: usize,
-    ) -> dfa::Result<(usize, usize)> {
-        use dfa::Result::*;
-        match dfa::Fsm::reverse(
-            &self.ro.dfa_reverse,
-            self.cache.value(),
-            false,
-            &text[start..],
-            text.len() - start,
-        ) {
-            Match(s) => Match((start + s, text.len())),
-            NoMatch(i) => NoMatch(i),
-            Quit => Quit,
-        }
-    }
-
-    /// Finds the end of the shortest match using only the DFA.
-    #[cfg(feature = "perf-dfa")]
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn shortest_dfa(&self, text: &[u8], start: usize) -> dfa::Result<usize> {
-        dfa::Fsm::forward(&self.ro.dfa, self.cache.value(), true, text, start)
-    }
-
-    /// Finds the end of the shortest match using only the DFA by scanning for
-    /// suffix literals.
-    #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn shortest_dfa_reverse_suffix(
-        &self,
-        text: &[u8],
-        start: usize,
-    ) -> dfa::Result<usize> {
-        match self.exec_dfa_reverse_suffix(text, start) {
-            None => self.shortest_dfa(text, start),
-            Some(r) => r.map(|(_, end)| end),
-        }
-    }
-
-    /// Finds the end of the shortest match using only the DFA by scanning for
-    /// suffix literals. It also reports the start of the match.
-    ///
-    /// Note that if None is returned, then the optimization gave up to avoid
-    /// worst case quadratic behavior. A forward scanning DFA should be tried
-    /// next.
-    ///
-    /// If a match is returned and the full leftmost-first match is desired,
-    /// then a forward scan starting from the beginning of the match must be
-    /// done.
-    ///
-    /// If the result returned indicates that the DFA quit, then another
-    /// matching engine should be used.
-    #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn exec_dfa_reverse_suffix(
-        &self,
-        text: &[u8],
-        original_start: usize,
-    ) -> Option<dfa::Result<(usize, usize)>> {
-        use dfa::Result::*;
-
-        let lcs = self.ro.suffixes.lcs();
-        debug_assert!(lcs.len() >= 1);
-        let mut start = original_start;
-        let mut end = start;
-        let mut last_literal = start;
-        while end <= text.len() {
-            last_literal += match lcs.find(&text[last_literal..]) {
-                None => return Some(NoMatch(text.len())),
-                Some(i) => i,
-            };
-            end = last_literal + lcs.len();
-            match dfa::Fsm::reverse(
-                &self.ro.dfa_reverse,
-                self.cache.value(),
-                false,
-                &text[start..end],
-                end - start,
-            ) {
-                Match(0) | NoMatch(0) => return None,
-                Match(i) => return Some(Match((start + i, end))),
-                NoMatch(i) => {
-                    start += i;
-                    last_literal += 1;
-                    continue;
-                }
-                Quit => return Some(Quit),
-            };
-        }
-        Some(NoMatch(text.len()))
-    }
-
-    /// Finds the leftmost-first match (start and end) using only the DFA
-    /// by scanning for suffix literals.
-    ///
-    /// If the result returned indicates that the DFA quit, then another
-    /// matching engine should be used.
-    #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn find_dfa_reverse_suffix(
-        &self,
-        text: &[u8],
-        start: usize,
-    ) -> dfa::Result<(usize, usize)> {
-        use dfa::Result::*;
-
-        let match_start = match self.exec_dfa_reverse_suffix(text, start) {
-            None => return self.find_dfa_forward(text, start),
-            Some(Match((start, _))) => start,
-            Some(r) => return r,
-        };
-        // At this point, we've found a match. The only way to quit now
-        // without a match is if the DFA gives up (seems unlikely).
-        //
-        // Now run the DFA forwards to find the proper end of the match.
-        // (The suffix literal match can only indicate the earliest
-        // possible end location, which may appear before the end of the
-        // leftmost-first match.)
-        match dfa::Fsm::forward(
-            &self.ro.dfa,
-            self.cache.value(),
-            false,
-            text,
-            match_start,
-        ) {
-            NoMatch(_) => panic!("BUG: reverse match implies forward match"),
-            Quit => Quit,
-            Match(e) => Match((match_start, e)),
-        }
-    }
-
-    /// Executes the NFA engine to return whether there is a match or not.
-    ///
-    /// Ideally, we could use shortest_nfa(...).is_some() and get the same
-    /// performance characteristics, but regex sets don't have captures, which
-    /// shortest_nfa depends on.
-    #[cfg(feature = "perf-dfa")]
-    fn match_nfa(&self, text: &[u8], start: usize) -> bool {
-        self.match_nfa_type(MatchNfaType::Auto, text, start)
-    }
-
-    /// Like match_nfa, but allows specification of the type of NFA engine.
-    fn match_nfa_type(
-        &self,
-        ty: MatchNfaType,
-        text: &[u8],
-        start: usize,
-    ) -> bool {
-        self.exec_nfa(
-            ty,
-            &mut [false],
-            &mut [],
-            true,
-            false,
-            text,
-            start,
-            text.len(),
-        )
-    }
-
-    /// Finds the shortest match using an NFA.
-    #[cfg(feature = "perf-dfa")]
-    fn shortest_nfa(&self, text: &[u8], start: usize) -> Option<usize> {
-        self.shortest_nfa_type(MatchNfaType::Auto, text, start)
-    }
-
-    /// Like shortest_nfa, but allows specification of the type of NFA engine.
-    fn shortest_nfa_type(
-        &self,
-        ty: MatchNfaType,
-        text: &[u8],
-        start: usize,
-    ) -> Option<usize> {
-        let mut slots = [None, None];
-        if self.exec_nfa(
-            ty,
-            &mut [false],
-            &mut slots,
-            true,
-            true,
-            text,
-            start,
-            text.len(),
-        ) {
-            slots[1]
-        } else {
-            None
-        }
-    }
-
-    /// Like find, but executes an NFA engine.
-    fn find_nfa(
-        &self,
-        ty: MatchNfaType,
-        text: &[u8],
-        start: usize,
-    ) -> Option<(usize, usize)> {
-        let mut slots = [None, None];
-        if self.exec_nfa(
-            ty,
-            &mut [false],
-            &mut slots,
-            false,
-            false,
-            text,
-            start,
-            text.len(),
-        ) {
-            match (slots[0], slots[1]) {
-                (Some(s), Some(e)) => Some((s, e)),
-                _ => None,
-            }
-        } else {
-            None
-        }
-    }
-
-    /// Like find_nfa, but fills in captures.
-    ///
-    /// `slots` should have length equal to `2 * nfa.captures.len()`.
-    #[cfg(feature = "perf-dfa")]
-    fn captures_nfa(
-        &self,
-        slots: &mut [Slot],
-        text: &[u8],
-        start: usize,
-    ) -> Option<(usize, usize)> {
-        self.captures_nfa_type(
-            MatchNfaType::Auto,
-            slots,
-            text,
-            start,
-            text.len(),
-        )
-    }
-
-    /// Like captures_nfa, but allows specification of type of NFA engine.
-    fn captures_nfa_type(
-        &self,
-        ty: MatchNfaType,
-        slots: &mut [Slot],
-        text: &[u8],
-        start: usize,
-        end: usize,
-    ) -> Option<(usize, usize)> {
-        if self.exec_nfa(
-            ty,
-            &mut [false],
-            slots,
-            false,
-            false,
-            text,
-            start,
-            end,
-        ) {
-            match (slots[0], slots[1]) {
-                (Some(s), Some(e)) => Some((s, e)),
-                _ => None,
-            }
-        } else {
-            None
-        }
-    }
-
-    fn exec_nfa(
-        &self,
-        mut ty: MatchNfaType,
-        matches: &mut [bool],
-        slots: &mut [Slot],
-        quit_after_match: bool,
-        quit_after_match_with_pos: bool,
-        text: &[u8],
-        start: usize,
-        end: usize,
-    ) -> bool {
-        use self::MatchNfaType::*;
-        if let Auto = ty {
-            if backtrack::should_exec(self.ro.nfa.len(), text.len()) {
-                ty = Backtrack;
-            } else {
-                ty = PikeVM;
-            }
-        }
-        // The backtracker can't return the shortest match position as it is
-        // implemented today. So if someone calls `shortest_match` and we need
-        // to run an NFA, then use the PikeVM.
-        if quit_after_match_with_pos || ty == PikeVM {
-            self.exec_pikevm(
-                matches,
-                slots,
-                quit_after_match,
-                text,
-                start,
-                end,
-            )
-        } else {
-            self.exec_backtrack(matches, slots, text, start, end)
-        }
-    }
-
-    /// Always run the NFA algorithm.
-    fn exec_pikevm(
-        &self,
-        matches: &mut [bool],
-        slots: &mut [Slot],
-        quit_after_match: bool,
-        text: &[u8],
-        start: usize,
-        end: usize,
-    ) -> bool {
-        if self.ro.nfa.uses_bytes() {
-            pikevm::Fsm::exec(
-                &self.ro.nfa,
-                self.cache.value(),
-                matches,
-                slots,
-                quit_after_match,
-                ByteInput::new(text, self.ro.nfa.only_utf8),
-                start,
-                end,
-            )
-        } else {
-            pikevm::Fsm::exec(
-                &self.ro.nfa,
-                self.cache.value(),
-                matches,
-                slots,
-                quit_after_match,
-                CharInput::new(text),
-                start,
-                end,
-            )
-        }
-    }
-
-    /// Always runs the NFA using bounded backtracking.
-    fn exec_backtrack(
-        &self,
-        matches: &mut [bool],
-        slots: &mut [Slot],
-        text: &[u8],
-        start: usize,
-        end: usize,
-    ) -> bool {
-        if self.ro.nfa.uses_bytes() {
-            backtrack::Bounded::exec(
-                &self.ro.nfa,
-                self.cache.value(),
-                matches,
-                slots,
-                ByteInput::new(text, self.ro.nfa.only_utf8),
-                start,
-                end,
-            )
-        } else {
-            backtrack::Bounded::exec(
-                &self.ro.nfa,
-                self.cache.value(),
-                matches,
-                slots,
-                CharInput::new(text),
-                start,
-                end,
-            )
-        }
-    }
-
-    /// Finds which regular expressions match the given text.
-    ///
-    /// `matches` should have length equal to the number of regexes being
-    /// searched.
-    ///
-    /// This is only useful when one wants to know which regexes in a set
-    /// match some text.
-    pub fn many_matches_at(
-        &self,
-        matches: &mut [bool],
-        text: &[u8],
-        start: usize,
-    ) -> bool {
-        use self::MatchType::*;
-        if !self.is_anchor_end_match(text) {
-            return false;
-        }
-        match self.ro.match_type {
-            #[cfg(feature = "perf-literal")]
-            Literal(ty) => {
-                debug_assert_eq!(matches.len(), 1);
-                matches[0] = self.find_literals(ty, text, start).is_some();
-                matches[0]
-            }
-            #[cfg(feature = "perf-dfa")]
-            Dfa | DfaAnchoredReverse | DfaMany => {
-                match dfa::Fsm::forward_many(
-                    &self.ro.dfa,
-                    self.cache.value(),
-                    matches,
-                    text,
-                    start,
-                ) {
-                    dfa::Result::Match(_) => true,
-                    dfa::Result::NoMatch(_) => false,
-                    dfa::Result::Quit => self.exec_nfa(
-                        MatchNfaType::Auto,
-                        matches,
-                        &mut [],
-                        false,
-                        false,
-                        text,
-                        start,
-                        text.len(),
-                    ),
-                }
-            }
-            #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
-            DfaSuffix => {
-                match dfa::Fsm::forward_many(
-                    &self.ro.dfa,
-                    self.cache.value(),
-                    matches,
-                    text,
-                    start,
-                ) {
-                    dfa::Result::Match(_) => true,
-                    dfa::Result::NoMatch(_) => false,
-                    dfa::Result::Quit => self.exec_nfa(
-                        MatchNfaType::Auto,
-                        matches,
-                        &mut [],
-                        false,
-                        false,
-                        text,
-                        start,
-                        text.len(),
-                    ),
-                }
-            }
-            Nfa(ty) => self.exec_nfa(
-                ty,
-                matches,
-                &mut [],
-                false,
-                false,
-                text,
-                start,
-                text.len(),
-            ),
-            Nothing => false,
-        }
-    }
-
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn is_anchor_end_match(&self, text: &[u8]) -> bool {
-        #[cfg(not(feature = "perf-literal"))]
-        fn imp(_: &ExecReadOnly, _: &[u8]) -> bool {
-            true
-        }
-
-        #[cfg(feature = "perf-literal")]
-        fn imp(ro: &ExecReadOnly, text: &[u8]) -> bool {
-            // Only do this check if the haystack is big (>1MB).
-            if text.len() > (1 << 20) && ro.nfa.is_anchored_end {
-                let lcs = ro.suffixes.lcs();
-                if lcs.len() >= 1 && !lcs.is_suffix(text) {
-                    return false;
-                }
-            }
-            true
-        }
-
-        imp(&self.ro, text)
-    }
-
-    pub fn capture_name_idx(&self) -> &Arc<HashMap<String, usize>> {
-        &self.ro.nfa.capture_name_idx
-    }
-}
-
-impl<'c> ExecNoSyncStr<'c> {
-    pub fn capture_name_idx(&self) -> &Arc<HashMap<String, usize>> {
-        self.0.capture_name_idx()
-    }
-}
-
-impl Exec {
-    /// Get a searcher that isn't Sync.
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    pub fn searcher(&self) -> ExecNoSync {
-        let create = || RefCell::new(ProgramCacheInner::new(&self.ro));
-        ExecNoSync {
-            ro: &self.ro, // a clone is too expensive here! (and not needed)
-            cache: self.cache.get_or(create),
-        }
-    }
-
-    /// Get a searcher that isn't Sync and can match on &str.
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    pub fn searcher_str(&self) -> ExecNoSyncStr {
-        ExecNoSyncStr(self.searcher())
-    }
-
-    /// Build a Regex from this executor.
-    pub fn into_regex(self) -> re_unicode::Regex {
-        re_unicode::Regex::from(self)
-    }
-
-    /// Build a RegexSet from this executor.
-    pub fn into_regex_set(self) -> re_set::unicode::RegexSet {
-        re_set::unicode::RegexSet::from(self)
-    }
-
-    /// Build a Regex from this executor that can match arbitrary bytes.
-    pub fn into_byte_regex(self) -> re_bytes::Regex {
-        re_bytes::Regex::from(self)
-    }
-
-    /// Build a RegexSet from this executor that can match arbitrary bytes.
-    pub fn into_byte_regex_set(self) -> re_set::bytes::RegexSet {
-        re_set::bytes::RegexSet::from(self)
-    }
-
-    /// The original regular expressions given by the caller that were
-    /// compiled.
-    pub fn regex_strings(&self) -> &[String] {
-        &self.ro.res
-    }
-
-    /// Return a slice of capture names.
-    ///
-    /// Any capture that isn't named is None.
-    pub fn capture_names(&self) -> &[Option<String>] {
-        &self.ro.nfa.captures
-    }
-
-    /// Return a reference to named groups mapping (from group name to
-    /// group position).
-    pub fn capture_name_idx(&self) -> &Arc<HashMap<String, usize>> {
-        &self.ro.nfa.capture_name_idx
-    }
-}
-
-impl Clone for Exec {
-    fn clone(&self) -> Exec {
-        Exec { ro: self.ro.clone(), cache: Cached::new() }
-    }
-}
-
-impl ExecReadOnly {
-    fn choose_match_type(&self, hint: Option<MatchType>) -> MatchType {
-        if let Some(MatchType::Nfa(_)) = hint {
-            return hint.unwrap();
-        }
-        // If the NFA is empty, then we'll never match anything.
-        if self.nfa.insts.is_empty() {
-            return MatchType::Nothing;
-        }
-        if let Some(literalty) = self.choose_literal_match_type() {
-            return literalty;
-        }
-        if let Some(dfaty) = self.choose_dfa_match_type() {
-            return dfaty;
-        }
-        // We're so totally hosed.
-        MatchType::Nfa(MatchNfaType::Auto)
-    }
-
-    /// If a plain literal scan can be used, then a corresponding literal
-    /// search type is returned.
-    fn choose_literal_match_type(&self) -> Option<MatchType> {
-        #[cfg(not(feature = "perf-literal"))]
-        fn imp(_: &ExecReadOnly) -> Option<MatchType> {
-            None
-        }
-
-        #[cfg(feature = "perf-literal")]
-        fn imp(ro: &ExecReadOnly) -> Option<MatchType> {
-            // If our set of prefixes is complete, then we can use it to find
-            // a match in lieu of a regex engine. This doesn't quite work well
-            // in the presence of multiple regexes, so only do it when there's
-            // one.
-            //
-            // TODO(burntsushi): Also, don't try to match literals if the regex
-            // is partially anchored. We could technically do it, but we'd need
-            // to create two sets of literals: all of them and then the subset
-            // that aren't anchored. We would then only search for all of them
-            // when at the beginning of the input and use the subset in all
-            // other cases.
-            if ro.res.len() != 1 {
-                return None;
-            }
-            if ro.ac.is_some() {
-                return Some(MatchType::Literal(
-                    MatchLiteralType::AhoCorasick,
-                ));
-            }
-            if ro.nfa.prefixes.complete() {
-                return if ro.nfa.is_anchored_start {
-                    Some(MatchType::Literal(MatchLiteralType::AnchoredStart))
-                } else {
-                    Some(MatchType::Literal(MatchLiteralType::Unanchored))
-                };
-            }
-            if ro.suffixes.complete() {
-                return if ro.nfa.is_anchored_end {
-                    Some(MatchType::Literal(MatchLiteralType::AnchoredEnd))
-                } else {
-                    // This case shouldn't happen. When the regex isn't
-                    // anchored, then complete prefixes should imply complete
-                    // suffixes.
-                    Some(MatchType::Literal(MatchLiteralType::Unanchored))
-                };
-            }
-            None
-        }
-
-        imp(self)
-    }
-
-    /// If a DFA scan can be used, then choose the appropriate DFA strategy.
-    fn choose_dfa_match_type(&self) -> Option<MatchType> {
-        #[cfg(not(feature = "perf-dfa"))]
-        fn imp(_: &ExecReadOnly) -> Option<MatchType> {
-            None
-        }
-
-        #[cfg(feature = "perf-dfa")]
-        fn imp(ro: &ExecReadOnly) -> Option<MatchType> {
-            if !dfa::can_exec(&ro.dfa) {
-                return None;
-            }
-            // Regex sets require a slightly specialized path.
-            if ro.res.len() >= 2 {
-                return Some(MatchType::DfaMany);
-            }
-            // If the regex is anchored at the end but not the start, then
-            // just match in reverse from the end of the haystack.
-            if !ro.nfa.is_anchored_start && ro.nfa.is_anchored_end {
-                return Some(MatchType::DfaAnchoredReverse);
-            }
-            #[cfg(feature = "perf-literal")]
-            {
-                // If there's a longish suffix literal, then it might be faster
-                // to look for that first.
-                if ro.should_suffix_scan() {
-                    return Some(MatchType::DfaSuffix);
-                }
-            }
-            // Fall back to your garden variety forward searching lazy DFA.
-            Some(MatchType::Dfa)
-        }
-
-        imp(self)
-    }
-
-    /// Returns true if the program is amenable to suffix scanning.
-    ///
-    /// When this is true, as a heuristic, we assume it is OK to quickly scan
-    /// for suffix literals and then do a *reverse* DFA match from any matches
-    /// produced by the literal scan. (And then followed by a forward DFA
-    /// search, since the previously found suffix literal maybe not actually be
-    /// the end of a match.)
-    ///
-    /// This is a bit of a specialized optimization, but can result in pretty
-    /// big performance wins if 1) there are no prefix literals and 2) the
-    /// suffix literals are pretty rare in the text. (1) is obviously easy to
-    /// account for but (2) is harder. As a proxy, we assume that longer
-    /// strings are generally rarer, so we only enable this optimization when
-    /// we have a meaty suffix.
-    #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
-    fn should_suffix_scan(&self) -> bool {
-        if self.suffixes.is_empty() {
-            return false;
-        }
-        let lcs_len = self.suffixes.lcs().char_len();
-        lcs_len >= 3 && lcs_len > self.dfa.prefixes.lcp().char_len()
-    }
-}
-
-#[derive(Clone, Copy, Debug)]
-enum MatchType {
-    /// A single or multiple literal search. This is only used when the regex
-    /// can be decomposed into a literal search.
-    #[cfg(feature = "perf-literal")]
-    Literal(MatchLiteralType),
-    /// A normal DFA search.
-    #[cfg(feature = "perf-dfa")]
-    Dfa,
-    /// A reverse DFA search starting from the end of a haystack.
-    #[cfg(feature = "perf-dfa")]
-    DfaAnchoredReverse,
-    /// A reverse DFA search with suffix literal scanning.
-    #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
-    DfaSuffix,
-    /// Use the DFA on two or more regular expressions.
-    #[cfg(feature = "perf-dfa")]
-    DfaMany,
-    /// An NFA variant.
-    Nfa(MatchNfaType),
-    /// No match is ever possible, so don't ever try to search.
-    Nothing,
-}
-
-#[derive(Clone, Copy, Debug)]
-#[cfg(feature = "perf-literal")]
-enum MatchLiteralType {
-    /// Match literals anywhere in text.
-    Unanchored,
-    /// Match literals only at the start of text.
-    AnchoredStart,
-    /// Match literals only at the end of text.
-    AnchoredEnd,
-    /// Use an Aho-Corasick automaton. This requires `ac` to be Some on
-    /// ExecReadOnly.
-    AhoCorasick,
-}
-
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-enum MatchNfaType {
-    /// Choose between Backtrack and PikeVM.
-    Auto,
-    /// NFA bounded backtracking.
-    ///
-    /// (This is only set by tests, since it never makes sense to always want
-    /// backtracking.)
-    Backtrack,
-    /// The Pike VM.
-    ///
-    /// (This is only set by tests, since it never makes sense to always want
-    /// the Pike VM.)
-    PikeVM,
-}
-
-/// `ProgramCache` maintains reusable allocations for each matching engine
-/// available to a particular program.
-pub type ProgramCache = RefCell<ProgramCacheInner>;
-
-#[derive(Debug)]
-pub struct ProgramCacheInner {
-    pub pikevm: pikevm::Cache,
-    pub backtrack: backtrack::Cache,
-    #[cfg(feature = "perf-dfa")]
-    pub dfa: dfa::Cache,
-    #[cfg(feature = "perf-dfa")]
-    pub dfa_reverse: dfa::Cache,
-}
-
-impl ProgramCacheInner {
-    fn new(ro: &ExecReadOnly) -> Self {
-        ProgramCacheInner {
-            pikevm: pikevm::Cache::new(&ro.nfa),
-            backtrack: backtrack::Cache::new(&ro.nfa),
-            #[cfg(feature = "perf-dfa")]
-            dfa: dfa::Cache::new(&ro.dfa),
-            #[cfg(feature = "perf-dfa")]
-            dfa_reverse: dfa::Cache::new(&ro.dfa_reverse),
-        }
-    }
-}
-
-/// Alternation literals checks if the given HIR is a simple alternation of
-/// literals, and if so, returns them. Otherwise, this returns None.
-#[cfg(feature = "perf-literal")]
-fn alternation_literals(expr: &Hir) -> Option<Vec<Vec<u8>>> {
-    use syntax::hir::{HirKind, Literal};
-
-    // This is pretty hacky, but basically, if `is_alternation_literal` is
-    // true, then we can make several assumptions about the structure of our
-    // HIR. This is what justifies the `unreachable!` statements below.
-    //
-    // This code should be refactored once we overhaul this crate's
-    // optimization pipeline, because this is a terribly inflexible way to go
-    // about things.
-
-    if !expr.is_alternation_literal() {
-        return None;
-    }
-    let alts = match *expr.kind() {
-        HirKind::Alternation(ref alts) => alts,
-        _ => return None, // one literal isn't worth it
-    };
-
-    let extendlit = |lit: &Literal, dst: &mut Vec<u8>| match *lit {
-        Literal::Unicode(c) => {
-            let mut buf = [0; 4];
-            dst.extend_from_slice(c.encode_utf8(&mut buf).as_bytes());
-        }
-        Literal::Byte(b) => {
-            dst.push(b);
-        }
-    };
-
-    let mut lits = vec![];
-    for alt in alts {
-        let mut lit = vec![];
-        match *alt.kind() {
-            HirKind::Literal(ref x) => extendlit(x, &mut lit),
-            HirKind::Concat(ref exprs) => {
-                for e in exprs {
-                    match *e.kind() {
-                        HirKind::Literal(ref x) => extendlit(x, &mut lit),
-                        _ => unreachable!("expected literal, got {:?}", e),
-                    }
-                }
-            }
-            _ => unreachable!("expected literal or concat, got {:?}", alt),
-        }
-        lits.push(lit);
-    }
-    Some(lits)
-}
-
-#[cfg(test)]
-mod test {
-    #[test]
-    fn uppercut_s_backtracking_bytes_default_bytes_mismatch() {
-        use internal::ExecBuilder;
-
-        let backtrack_bytes_re = ExecBuilder::new("^S")
-            .bounded_backtracking()
-            .only_utf8(false)
-            .build()
-            .map(|exec| exec.into_byte_regex())
-            .map_err(|err| format!("{}", err))
-            .unwrap();
-
-        let default_bytes_re = ExecBuilder::new("^S")
-            .only_utf8(false)
-            .build()
-            .map(|exec| exec.into_byte_regex())
-            .map_err(|err| format!("{}", err))
-            .unwrap();
-
-        let input = vec![83, 83];
-
-        let s1 = backtrack_bytes_re.split(&input);
-        let s2 = default_bytes_re.split(&input);
-        for (chunk1, chunk2) in s1.zip(s2) {
-            assert_eq!(chunk1, chunk2);
-        }
-    }
-
-    #[test]
-    fn unicode_lit_star_backtracking_utf8bytes_default_utf8bytes_mismatch() {
-        use internal::ExecBuilder;
-
-        let backtrack_bytes_re = ExecBuilder::new(r"^(?u:\*)")
-            .bounded_backtracking()
-            .bytes(true)
-            .build()
-            .map(|exec| exec.into_regex())
-            .map_err(|err| format!("{}", err))
-            .unwrap();
-
-        let default_bytes_re = ExecBuilder::new(r"^(?u:\*)")
-            .bytes(true)
-            .build()
-            .map(|exec| exec.into_regex())
-            .map_err(|err| format!("{}", err))
-            .unwrap();
-
-        let input = "**";
-
-        let s1 = backtrack_bytes_re.split(input);
-        let s2 = default_bytes_re.split(input);
-        for (chunk1, chunk2) in s1.zip(s2) {
-            assert_eq!(chunk1, chunk2);
-        }
-    }
-}
diff --git a/vendor/regex-1.4.3/src/expand.rs b/vendor/regex-1.4.3/src/expand.rs
deleted file mode 100644 (file)
index fd2ab03..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-use std::str;
-
-use find_byte::find_byte;
-
-use re_bytes;
-use re_unicode;
-
-pub fn expand_str(
-    caps: &re_unicode::Captures,
-    mut replacement: &str,
-    dst: &mut String,
-) {
-    while !replacement.is_empty() {
-        match find_byte(b'$', replacement.as_bytes()) {
-            None => break,
-            Some(i) => {
-                dst.push_str(&replacement[..i]);
-                replacement = &replacement[i..];
-            }
-        }
-        if replacement.as_bytes().get(1).map_or(false, |&b| b == b'$') {
-            dst.push_str("$");
-            replacement = &replacement[2..];
-            continue;
-        }
-        debug_assert!(!replacement.is_empty());
-        let cap_ref = match find_cap_ref(replacement.as_bytes()) {
-            Some(cap_ref) => cap_ref,
-            None => {
-                dst.push_str("$");
-                replacement = &replacement[1..];
-                continue;
-            }
-        };
-        replacement = &replacement[cap_ref.end..];
-        match cap_ref.cap {
-            Ref::Number(i) => {
-                dst.push_str(caps.get(i).map(|m| m.as_str()).unwrap_or(""));
-            }
-            Ref::Named(name) => {
-                dst.push_str(
-                    caps.name(name).map(|m| m.as_str()).unwrap_or(""),
-                );
-            }
-        }
-    }
-    dst.push_str(replacement);
-}
-
-pub fn expand_bytes(
-    caps: &re_bytes::Captures,
-    mut replacement: &[u8],
-    dst: &mut Vec<u8>,
-) {
-    while !replacement.is_empty() {
-        match find_byte(b'$', replacement) {
-            None => break,
-            Some(i) => {
-                dst.extend(&replacement[..i]);
-                replacement = &replacement[i..];
-            }
-        }
-        if replacement.get(1).map_or(false, |&b| b == b'$') {
-            dst.push(b'$');
-            replacement = &replacement[2..];
-            continue;
-        }
-        debug_assert!(!replacement.is_empty());
-        let cap_ref = match find_cap_ref(replacement) {
-            Some(cap_ref) => cap_ref,
-            None => {
-                dst.push(b'$');
-                replacement = &replacement[1..];
-                continue;
-            }
-        };
-        replacement = &replacement[cap_ref.end..];
-        match cap_ref.cap {
-            Ref::Number(i) => {
-                dst.extend(caps.get(i).map(|m| m.as_bytes()).unwrap_or(b""));
-            }
-            Ref::Named(name) => {
-                dst.extend(
-                    caps.name(name).map(|m| m.as_bytes()).unwrap_or(b""),
-                );
-            }
-        }
-    }
-    dst.extend(replacement);
-}
-
-/// `CaptureRef` represents a reference to a capture group inside some text.
-/// The reference is either a capture group name or a number.
-///
-/// It is also tagged with the position in the text following the
-/// capture reference.
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-struct CaptureRef<'a> {
-    cap: Ref<'a>,
-    end: usize,
-}
-
-/// A reference to a capture group in some text.
-///
-/// e.g., `$2`, `$foo`, `${foo}`.
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-enum Ref<'a> {
-    Named(&'a str),
-    Number(usize),
-}
-
-impl<'a> From<&'a str> for Ref<'a> {
-    fn from(x: &'a str) -> Ref<'a> {
-        Ref::Named(x)
-    }
-}
-
-impl From<usize> for Ref<'static> {
-    fn from(x: usize) -> Ref<'static> {
-        Ref::Number(x)
-    }
-}
-
-/// Parses a possible reference to a capture group name in the given text,
-/// starting at the beginning of `replacement`.
-///
-/// If no such valid reference could be found, None is returned.
-fn find_cap_ref(replacement: &[u8]) -> Option<CaptureRef> {
-    let mut i = 0;
-    let rep: &[u8] = replacement.as_ref();
-    if rep.len() <= 1 || rep[0] != b'$' {
-        return None;
-    }
-    i += 1;
-    if rep[i] == b'{' {
-        return find_cap_ref_braced(rep, i + 1);
-    }
-    let mut cap_end = i;
-    while rep.get(cap_end).map_or(false, is_valid_cap_letter) {
-        cap_end += 1;
-    }
-    if cap_end == i {
-        return None;
-    }
-    // We just verified that the range 0..cap_end is valid ASCII, so it must
-    // therefore be valid UTF-8. If we really cared, we could avoid this UTF-8
-    // check with either unsafe or by parsing the number straight from &[u8].
-    let cap =
-        str::from_utf8(&rep[i..cap_end]).expect("valid UTF-8 capture name");
-    Some(CaptureRef {
-        cap: match cap.parse::<u32>() {
-            Ok(i) => Ref::Number(i as usize),
-            Err(_) => Ref::Named(cap),
-        },
-        end: cap_end,
-    })
-}
-
-fn find_cap_ref_braced(rep: &[u8], mut i: usize) -> Option<CaptureRef> {
-    let start = i;
-    while rep.get(i).map_or(false, |&b| b != b'}') {
-        i += 1;
-    }
-    if !rep.get(i).map_or(false, |&b| b == b'}') {
-        return None;
-    }
-    // When looking at braced names, we don't put any restrictions on the name,
-    // so it's possible it could be invalid UTF-8. But a capture group name
-    // can never be invalid UTF-8, so if we have invalid UTF-8, then we can
-    // safely return None.
-    let cap = match str::from_utf8(&rep[start..i]) {
-        Err(_) => return None,
-        Ok(cap) => cap,
-    };
-    Some(CaptureRef {
-        cap: match cap.parse::<u32>() {
-            Ok(i) => Ref::Number(i as usize),
-            Err(_) => Ref::Named(cap),
-        },
-        end: i + 1,
-    })
-}
-
-/// Returns true if and only if the given byte is allowed in a capture name.
-fn is_valid_cap_letter(b: &u8) -> bool {
-    match *b {
-        b'0'..=b'9' | b'a'..=b'z' | b'A'..=b'Z' | b'_' => true,
-        _ => false,
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::{find_cap_ref, CaptureRef};
-
-    macro_rules! find {
-        ($name:ident, $text:expr) => {
-            #[test]
-            fn $name() {
-                assert_eq!(None, find_cap_ref($text.as_bytes()));
-            }
-        };
-        ($name:ident, $text:expr, $capref:expr) => {
-            #[test]
-            fn $name() {
-                assert_eq!(Some($capref), find_cap_ref($text.as_bytes()));
-            }
-        };
-    }
-
-    macro_rules! c {
-        ($name_or_number:expr, $pos:expr) => {
-            CaptureRef { cap: $name_or_number.into(), end: $pos }
-        };
-    }
-
-    find!(find_cap_ref1, "$foo", c!("foo", 4));
-    find!(find_cap_ref2, "${foo}", c!("foo", 6));
-    find!(find_cap_ref3, "$0", c!(0, 2));
-    find!(find_cap_ref4, "$5", c!(5, 2));
-    find!(find_cap_ref5, "$10", c!(10, 3));
-    // See https://github.com/rust-lang/regex/pull/585
-    // for more on characters following numbers
-    find!(find_cap_ref6, "$42a", c!("42a", 4));
-    find!(find_cap_ref7, "${42}a", c!(42, 5));
-    find!(find_cap_ref8, "${42");
-    find!(find_cap_ref9, "${42 ");
-    find!(find_cap_ref10, " $0 ");
-    find!(find_cap_ref11, "$");
-    find!(find_cap_ref12, " ");
-    find!(find_cap_ref13, "");
-    find!(find_cap_ref14, "$1-$2", c!(1, 2));
-    find!(find_cap_ref15, "$1_$2", c!("1_", 3));
-    find!(find_cap_ref16, "$x-$y", c!("x", 2));
-    find!(find_cap_ref17, "$x_$y", c!("x_", 3));
-    find!(find_cap_ref18, "${#}", c!("#", 4));
-    find!(find_cap_ref19, "${Z[}", c!("Z[", 5));
-}
diff --git a/vendor/regex-1.4.3/src/find_byte.rs b/vendor/regex-1.4.3/src/find_byte.rs
deleted file mode 100644 (file)
index e95f72a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/// Searches for the given needle in the given haystack.
-///
-/// If the perf-literal feature is enabled, then this uses the super optimized
-/// memchr crate. Otherwise, it uses the naive byte-at-a-time implementation.
-pub fn find_byte(needle: u8, haystack: &[u8]) -> Option<usize> {
-    #[cfg(not(feature = "perf-literal"))]
-    fn imp(needle: u8, haystack: &[u8]) -> Option<usize> {
-        haystack.iter().position(|&b| b == needle)
-    }
-
-    #[cfg(feature = "perf-literal")]
-    fn imp(needle: u8, haystack: &[u8]) -> Option<usize> {
-        use memchr::memchr;
-        memchr(needle, haystack)
-    }
-
-    imp(needle, haystack)
-}
diff --git a/vendor/regex-1.4.3/src/freqs.rs b/vendor/regex-1.4.3/src/freqs.rs
deleted file mode 100644 (file)
index fcffa95..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-// NOTE: The following code was generated by "scripts/frequencies.py", do not
-// edit directly
-
-pub const BYTE_FREQUENCIES: [u8; 256] = [
-    55,  // '\x00'
-    52,  // '\x01'
-    51,  // '\x02'
-    50,  // '\x03'
-    49,  // '\x04'
-    48,  // '\x05'
-    47,  // '\x06'
-    46,  // '\x07'
-    45,  // '\x08'
-    103, // '\t'
-    242, // '\n'
-    66,  // '\x0b'
-    67,  // '\x0c'
-    229, // '\r'
-    44,  // '\x0e'
-    43,  // '\x0f'
-    42,  // '\x10'
-    41,  // '\x11'
-    40,  // '\x12'
-    39,  // '\x13'
-    38,  // '\x14'
-    37,  // '\x15'
-    36,  // '\x16'
-    35,  // '\x17'
-    34,  // '\x18'
-    33,  // '\x19'
-    56,  // '\x1a'
-    32,  // '\x1b'
-    31,  // '\x1c'
-    30,  // '\x1d'
-    29,  // '\x1e'
-    28,  // '\x1f'
-    255, // ' '
-    148, // '!'
-    164, // '"'
-    149, // '#'
-    136, // '$'
-    160, // '%'
-    155, // '&'
-    173, // "'"
-    221, // '('
-    222, // ')'
-    134, // '*'
-    122, // '+'
-    232, // ','
-    202, // '-'
-    215, // '.'
-    224, // '/'
-    208, // '0'
-    220, // '1'
-    204, // '2'
-    187, // '3'
-    183, // '4'
-    179, // '5'
-    177, // '6'
-    168, // '7'
-    178, // '8'
-    200, // '9'
-    226, // ':'
-    195, // ';'
-    154, // '<'
-    184, // '='
-    174, // '>'
-    126, // '?'
-    120, // '@'
-    191, // 'A'
-    157, // 'B'
-    194, // 'C'
-    170, // 'D'
-    189, // 'E'
-    162, // 'F'
-    161, // 'G'
-    150, // 'H'
-    193, // 'I'
-    142, // 'J'
-    137, // 'K'
-    171, // 'L'
-    176, // 'M'
-    185, // 'N'
-    167, // 'O'
-    186, // 'P'
-    112, // 'Q'
-    175, // 'R'
-    192, // 'S'
-    188, // 'T'
-    156, // 'U'
-    140, // 'V'
-    143, // 'W'
-    123, // 'X'
-    133, // 'Y'
-    128, // 'Z'
-    147, // '['
-    138, // '\\'
-    146, // ']'
-    114, // '^'
-    223, // '_'
-    151, // '`'
-    249, // 'a'
-    216, // 'b'
-    238, // 'c'
-    236, // 'd'
-    253, // 'e'
-    227, // 'f'
-    218, // 'g'
-    230, // 'h'
-    247, // 'i'
-    135, // 'j'
-    180, // 'k'
-    241, // 'l'
-    233, // 'm'
-    246, // 'n'
-    244, // 'o'
-    231, // 'p'
-    139, // 'q'
-    245, // 'r'
-    243, // 's'
-    251, // 't'
-    235, // 'u'
-    201, // 'v'
-    196, // 'w'
-    240, // 'x'
-    214, // 'y'
-    152, // 'z'
-    182, // '{'
-    205, // '|'
-    181, // '}'
-    127, // '~'
-    27,  // '\x7f'
-    212, // '\x80'
-    211, // '\x81'
-    210, // '\x82'
-    213, // '\x83'
-    228, // '\x84'
-    197, // '\x85'
-    169, // '\x86'
-    159, // '\x87'
-    131, // '\x88'
-    172, // '\x89'
-    105, // '\x8a'
-    80,  // '\x8b'
-    98,  // '\x8c'
-    96,  // '\x8d'
-    97,  // '\x8e'
-    81,  // '\x8f'
-    207, // '\x90'
-    145, // '\x91'
-    116, // '\x92'
-    115, // '\x93'
-    144, // '\x94'
-    130, // '\x95'
-    153, // '\x96'
-    121, // '\x97'
-    107, // '\x98'
-    132, // '\x99'
-    109, // '\x9a'
-    110, // '\x9b'
-    124, // '\x9c'
-    111, // '\x9d'
-    82,  // '\x9e'
-    108, // '\x9f'
-    118, // '\xa0'
-    141, // '¡'
-    113, // '¢'
-    129, // '£'
-    119, // '¤'
-    125, // '¥'
-    165, // '¦'
-    117, // '§'
-    92,  // '¨'
-    106, // '©'
-    83,  // 'ª'
-    72,  // '«'
-    99,  // '¬'
-    93,  // '\xad'
-    65,  // '®'
-    79,  // '¯'
-    166, // '°'
-    237, // '±'
-    163, // '²'
-    199, // '³'
-    190, // '´'
-    225, // 'µ'
-    209, // '¶'
-    203, // '·'
-    198, // '¸'
-    217, // '¹'
-    219, // 'º'
-    206, // '»'
-    234, // '¼'
-    248, // '½'
-    158, // '¾'
-    239, // '¿'
-    255, // 'À'
-    255, // 'Á'
-    255, // 'Â'
-    255, // 'Ã'
-    255, // 'Ä'
-    255, // 'Å'
-    255, // 'Æ'
-    255, // 'Ç'
-    255, // 'È'
-    255, // 'É'
-    255, // 'Ê'
-    255, // 'Ë'
-    255, // 'Ì'
-    255, // 'Í'
-    255, // 'Î'
-    255, // 'Ï'
-    255, // 'Ð'
-    255, // 'Ñ'
-    255, // 'Ò'
-    255, // 'Ó'
-    255, // 'Ô'
-    255, // 'Õ'
-    255, // 'Ö'
-    255, // '×'
-    255, // 'Ø'
-    255, // 'Ù'
-    255, // 'Ú'
-    255, // 'Û'
-    255, // 'Ü'
-    255, // 'Ý'
-    255, // 'Þ'
-    255, // 'ß'
-    255, // 'à'
-    255, // 'á'
-    255, // 'â'
-    255, // 'ã'
-    255, // 'ä'
-    255, // 'å'
-    255, // 'æ'
-    255, // 'ç'
-    255, // 'è'
-    255, // 'é'
-    255, // 'ê'
-    255, // 'ë'
-    255, // 'ì'
-    255, // 'í'
-    255, // 'î'
-    255, // 'ï'
-    255, // 'ð'
-    255, // 'ñ'
-    255, // 'ò'
-    255, // 'ó'
-    255, // 'ô'
-    255, // 'õ'
-    255, // 'ö'
-    255, // '÷'
-    255, // 'ø'
-    255, // 'ù'
-    255, // 'ú'
-    255, // 'û'
-    255, // 'ü'
-    255, // 'ý'
-    255, // 'þ'
-    255, // 'ÿ'
-];
diff --git a/vendor/regex-1.4.3/src/input.rs b/vendor/regex-1.4.3/src/input.rs
deleted file mode 100644 (file)
index 3afa2d0..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-use std::char;
-use std::cmp::Ordering;
-use std::fmt;
-use std::ops;
-use std::u32;
-
-use syntax;
-
-use literal::LiteralSearcher;
-use prog::InstEmptyLook;
-use utf8::{decode_last_utf8, decode_utf8};
-
-/// Represents a location in the input.
-#[derive(Clone, Copy, Debug)]
-pub struct InputAt {
-    pos: usize,
-    c: Char,
-    byte: Option<u8>,
-    len: usize,
-}
-
-impl InputAt {
-    /// Returns true iff this position is at the beginning of the input.
-    pub fn is_start(&self) -> bool {
-        self.pos == 0
-    }
-
-    /// Returns true iff this position is past the end of the input.
-    pub fn is_end(&self) -> bool {
-        self.c.is_none() && self.byte.is_none()
-    }
-
-    /// Returns the character at this position.
-    ///
-    /// If this position is just before or after the input, then an absent
-    /// character is returned.
-    pub fn char(&self) -> Char {
-        self.c
-    }
-
-    /// Returns the byte at this position.
-    pub fn byte(&self) -> Option<u8> {
-        self.byte
-    }
-
-    /// Returns the UTF-8 width of the character at this position.
-    pub fn len(&self) -> usize {
-        self.len
-    }
-
-    /// Returns whether the UTF-8 width of the character at this position
-    /// is zero.
-    pub fn is_empty(&self) -> bool {
-        self.len == 0
-    }
-
-    /// Returns the byte offset of this position.
-    pub fn pos(&self) -> usize {
-        self.pos
-    }
-
-    /// Returns the byte offset of the next position in the input.
-    pub fn next_pos(&self) -> usize {
-        self.pos + self.len
-    }
-}
-
-/// An abstraction over input used in the matching engines.
-pub trait Input: fmt::Debug {
-    /// Return an encoding of the position at byte offset `i`.
-    fn at(&self, i: usize) -> InputAt;
-
-    /// Return the Unicode character occurring next to `at`.
-    ///
-    /// If no such character could be decoded, then `Char` is absent.
-    fn next_char(&self, at: InputAt) -> Char;
-
-    /// Return the Unicode character occurring previous to `at`.
-    ///
-    /// If no such character could be decoded, then `Char` is absent.
-    fn previous_char(&self, at: InputAt) -> Char;
-
-    /// Return true if the given empty width instruction matches at the
-    /// input position given.
-    fn is_empty_match(&self, at: InputAt, empty: &InstEmptyLook) -> bool;
-
-    /// Scan the input for a matching prefix.
-    fn prefix_at(
-        &self,
-        prefixes: &LiteralSearcher,
-        at: InputAt,
-    ) -> Option<InputAt>;
-
-    /// The number of bytes in the input.
-    fn len(&self) -> usize;
-
-    /// Whether the input is empty.
-    fn is_empty(&self) -> bool {
-        self.len() == 0
-    }
-
-    /// Return the given input as a sequence of bytes.
-    fn as_bytes(&self) -> &[u8];
-}
-
-impl<'a, T: Input> Input for &'a T {
-    fn at(&self, i: usize) -> InputAt {
-        (**self).at(i)
-    }
-
-    fn next_char(&self, at: InputAt) -> Char {
-        (**self).next_char(at)
-    }
-
-    fn previous_char(&self, at: InputAt) -> Char {
-        (**self).previous_char(at)
-    }
-
-    fn is_empty_match(&self, at: InputAt, empty: &InstEmptyLook) -> bool {
-        (**self).is_empty_match(at, empty)
-    }
-
-    fn prefix_at(
-        &self,
-        prefixes: &LiteralSearcher,
-        at: InputAt,
-    ) -> Option<InputAt> {
-        (**self).prefix_at(prefixes, at)
-    }
-
-    fn len(&self) -> usize {
-        (**self).len()
-    }
-
-    fn as_bytes(&self) -> &[u8] {
-        (**self).as_bytes()
-    }
-}
-
-/// An input reader over characters.
-#[derive(Clone, Copy, Debug)]
-pub struct CharInput<'t>(&'t [u8]);
-
-impl<'t> CharInput<'t> {
-    /// Return a new character input reader for the given string.
-    pub fn new(s: &'t [u8]) -> CharInput<'t> {
-        CharInput(s)
-    }
-}
-
-impl<'t> ops::Deref for CharInput<'t> {
-    type Target = [u8];
-
-    fn deref(&self) -> &[u8] {
-        self.0
-    }
-}
-
-impl<'t> Input for CharInput<'t> {
-    fn at(&self, i: usize) -> InputAt {
-        if i >= self.len() {
-            InputAt { pos: self.len(), c: None.into(), byte: None, len: 0 }
-        } else {
-            let c = decode_utf8(&self[i..]).map(|(c, _)| c).into();
-            InputAt { pos: i, c: c, byte: None, len: c.len_utf8() }
-        }
-    }
-
-    fn next_char(&self, at: InputAt) -> Char {
-        at.char()
-    }
-
-    fn previous_char(&self, at: InputAt) -> Char {
-        decode_last_utf8(&self[..at.pos()]).map(|(c, _)| c).into()
-    }
-
-    fn is_empty_match(&self, at: InputAt, empty: &InstEmptyLook) -> bool {
-        use prog::EmptyLook::*;
-        match empty.look {
-            StartLine => {
-                let c = self.previous_char(at);
-                at.pos() == 0 || c == '\n'
-            }
-            EndLine => {
-                let c = self.next_char(at);
-                at.pos() == self.len() || c == '\n'
-            }
-            StartText => at.pos() == 0,
-            EndText => at.pos() == self.len(),
-            WordBoundary => {
-                let (c1, c2) = (self.previous_char(at), self.next_char(at));
-                c1.is_word_char() != c2.is_word_char()
-            }
-            NotWordBoundary => {
-                let (c1, c2) = (self.previous_char(at), self.next_char(at));
-                c1.is_word_char() == c2.is_word_char()
-            }
-            WordBoundaryAscii => {
-                let (c1, c2) = (self.previous_char(at), self.next_char(at));
-                c1.is_word_byte() != c2.is_word_byte()
-            }
-            NotWordBoundaryAscii => {
-                let (c1, c2) = (self.previous_char(at), self.next_char(at));
-                c1.is_word_byte() == c2.is_word_byte()
-            }
-        }
-    }
-
-    fn prefix_at(
-        &self,
-        prefixes: &LiteralSearcher,
-        at: InputAt,
-    ) -> Option<InputAt> {
-        prefixes.find(&self[at.pos()..]).map(|(s, _)| self.at(at.pos() + s))
-    }
-
-    fn len(&self) -> usize {
-        self.0.len()
-    }
-
-    fn as_bytes(&self) -> &[u8] {
-        self.0
-    }
-}
-
-/// An input reader over bytes.
-#[derive(Clone, Copy, Debug)]
-pub struct ByteInput<'t> {
-    text: &'t [u8],
-    only_utf8: bool,
-}
-
-impl<'t> ByteInput<'t> {
-    /// Return a new byte-based input reader for the given string.
-    pub fn new(text: &'t [u8], only_utf8: bool) -> ByteInput<'t> {
-        ByteInput { text: text, only_utf8: only_utf8 }
-    }
-}
-
-impl<'t> ops::Deref for ByteInput<'t> {
-    type Target = [u8];
-
-    fn deref(&self) -> &[u8] {
-        self.text
-    }
-}
-
-impl<'t> Input for ByteInput<'t> {
-    fn at(&self, i: usize) -> InputAt {
-        if i >= self.len() {
-            InputAt { pos: self.len(), c: None.into(), byte: None, len: 0 }
-        } else {
-            InputAt {
-                pos: i,
-                c: None.into(),
-                byte: self.get(i).cloned(),
-                len: 1,
-            }
-        }
-    }
-
-    fn next_char(&self, at: InputAt) -> Char {
-        decode_utf8(&self[at.pos()..]).map(|(c, _)| c).into()
-    }
-
-    fn previous_char(&self, at: InputAt) -> Char {
-        decode_last_utf8(&self[..at.pos()]).map(|(c, _)| c).into()
-    }
-
-    fn is_empty_match(&self, at: InputAt, empty: &InstEmptyLook) -> bool {
-        use prog::EmptyLook::*;
-        match empty.look {
-            StartLine => {
-                let c = self.previous_char(at);
-                at.pos() == 0 || c == '\n'
-            }
-            EndLine => {
-                let c = self.next_char(at);
-                at.pos() == self.len() || c == '\n'
-            }
-            StartText => at.pos() == 0,
-            EndText => at.pos() == self.len(),
-            WordBoundary => {
-                let (c1, c2) = (self.previous_char(at), self.next_char(at));
-                c1.is_word_char() != c2.is_word_char()
-            }
-            NotWordBoundary => {
-                let (c1, c2) = (self.previous_char(at), self.next_char(at));
-                c1.is_word_char() == c2.is_word_char()
-            }
-            WordBoundaryAscii => {
-                let (c1, c2) = (self.previous_char(at), self.next_char(at));
-                if self.only_utf8 {
-                    // If we must match UTF-8, then we can't match word
-                    // boundaries at invalid UTF-8.
-                    if c1.is_none() && !at.is_start() {
-                        return false;
-                    }
-                    if c2.is_none() && !at.is_end() {
-                        return false;
-                    }
-                }
-                c1.is_word_byte() != c2.is_word_byte()
-            }
-            NotWordBoundaryAscii => {
-                let (c1, c2) = (self.previous_char(at), self.next_char(at));
-                if self.only_utf8 {
-                    // If we must match UTF-8, then we can't match word
-                    // boundaries at invalid UTF-8.
-                    if c1.is_none() && !at.is_start() {
-                        return false;
-                    }
-                    if c2.is_none() && !at.is_end() {
-                        return false;
-                    }
-                }
-                c1.is_word_byte() == c2.is_word_byte()
-            }
-        }
-    }
-
-    fn prefix_at(
-        &self,
-        prefixes: &LiteralSearcher,
-        at: InputAt,
-    ) -> Option<InputAt> {
-        prefixes.find(&self[at.pos()..]).map(|(s, _)| self.at(at.pos() + s))
-    }
-
-    fn len(&self) -> usize {
-        self.text.len()
-    }
-
-    fn as_bytes(&self) -> &[u8] {
-        self.text
-    }
-}
-
-/// An inline representation of `Option<char>`.
-///
-/// This eliminates the need to do case analysis on `Option<char>` to determine
-/// ordinality with other characters.
-///
-/// (The `Option<char>` is not related to encoding. Instead, it is used in the
-/// matching engines to represent the beginning and ending boundaries of the
-/// search text.)
-#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Char(u32);
-
-impl fmt::Debug for Char {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match char::from_u32(self.0) {
-            None => write!(f, "Empty"),
-            Some(c) => write!(f, "{:?}", c),
-        }
-    }
-}
-
-impl Char {
-    /// Returns true iff the character is absent.
-    #[inline]
-    pub fn is_none(self) -> bool {
-        self.0 == u32::MAX
-    }
-
-    /// Returns the length of the character's UTF-8 encoding.
-    ///
-    /// If the character is absent, then `1` is returned.
-    #[inline]
-    pub fn len_utf8(self) -> usize {
-        char::from_u32(self.0).map_or(1, |c| c.len_utf8())
-    }
-
-    /// Returns true iff the character is a word character.
-    ///
-    /// If the character is absent, then false is returned.
-    pub fn is_word_char(self) -> bool {
-        // is_word_character can panic if the Unicode data for \w isn't
-        // available. However, our compiler ensures that if a Unicode word
-        // boundary is used, then the data must also be available. If it isn't,
-        // then the compiler returns an error.
-        char::from_u32(self.0).map_or(false, syntax::is_word_character)
-    }
-
-    /// Returns true iff the byte is a word byte.
-    ///
-    /// If the byte is absent, then false is returned.
-    pub fn is_word_byte(self) -> bool {
-        match char::from_u32(self.0) {
-            Some(c) if c <= '\u{7F}' => syntax::is_word_byte(c as u8),
-            None | Some(_) => false,
-        }
-    }
-}
-
-impl From<char> for Char {
-    fn from(c: char) -> Char {
-        Char(c as u32)
-    }
-}
-
-impl From<Option<char>> for Char {
-    fn from(c: Option<char>) -> Char {
-        c.map_or(Char(u32::MAX), |c| c.into())
-    }
-}
-
-impl PartialEq<char> for Char {
-    #[inline]
-    fn eq(&self, other: &char) -> bool {
-        self.0 == *other as u32
-    }
-}
-
-impl PartialEq<Char> for char {
-    #[inline]
-    fn eq(&self, other: &Char) -> bool {
-        *self as u32 == other.0
-    }
-}
-
-impl PartialOrd<char> for Char {
-    #[inline]
-    fn partial_cmp(&self, other: &char) -> Option<Ordering> {
-        self.0.partial_cmp(&(*other as u32))
-    }
-}
-
-impl PartialOrd<Char> for char {
-    #[inline]
-    fn partial_cmp(&self, other: &Char) -> Option<Ordering> {
-        (*self as u32).partial_cmp(&other.0)
-    }
-}
diff --git a/vendor/regex-1.4.3/src/lib.rs b/vendor/regex-1.4.3/src/lib.rs
deleted file mode 100644 (file)
index d3dc58d..0000000
+++ /dev/null
@@ -1,787 +0,0 @@
-/*!
-This crate provides a library for parsing, compiling, and executing regular
-expressions. Its syntax is similar to Perl-style regular expressions, but lacks
-a few features like look around and backreferences. In exchange, all searches
-execute in linear time with respect to the size of the regular expression and
-search text.
-
-This crate's documentation provides some simple examples, describes
-[Unicode support](#unicode) and exhaustively lists the
-[supported syntax](#syntax).
-
-For more specific details on the API for regular expressions, please see the
-documentation for the [`Regex`](struct.Regex.html) type.
-
-# Usage
-
-This crate is [on crates.io](https://crates.io/crates/regex) and can be
-used by adding `regex` to your dependencies in your project's `Cargo.toml`.
-
-```toml
-[dependencies]
-regex = "1"
-```
-
-If you're using Rust 2015, then you'll also need to add it to your crate root:
-
-```rust
-extern crate regex;
-```
-
-# Example: find a date
-
-General use of regular expressions in this package involves compiling an
-expression and then using it to search, split or replace text. For example,
-to confirm that some text resembles a date:
-
-```rust
-use regex::Regex;
-let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
-assert!(re.is_match("2014-01-01"));
-```
-
-Notice the use of the `^` and `$` anchors. In this crate, every expression
-is executed with an implicit `.*?` at the beginning and end, which allows
-it to match anywhere in the text. Anchors can be used to ensure that the
-full text matches an expression.
-
-This example also demonstrates the utility of
-[raw strings](https://doc.rust-lang.org/stable/reference/tokens.html#raw-string-literals)
-in Rust, which
-are just like regular strings except they are prefixed with an `r` and do
-not process any escape sequences. For example, `"\\d"` is the same
-expression as `r"\d"`.
-
-# Example: Avoid compiling the same regex in a loop
-
-It is an anti-pattern to compile the same regular expression in a loop
-since compilation is typically expensive. (It takes anywhere from a few
-microseconds to a few **milliseconds** depending on the size of the
-regex.) Not only is compilation itself expensive, but this also prevents
-optimizations that reuse allocations internally to the matching engines.
-
-In Rust, it can sometimes be a pain to pass regular expressions around if
-they're used from inside a helper function. Instead, we recommend using the
-[`lazy_static`](https://crates.io/crates/lazy_static) crate to ensure that
-regular expressions are compiled exactly once.
-
-For example:
-
-```rust
-#[macro_use] extern crate lazy_static;
-extern crate regex;
-
-use regex::Regex;
-
-fn some_helper_function(text: &str) -> bool {
-    lazy_static! {
-        static ref RE: Regex = Regex::new("...").unwrap();
-    }
-    RE.is_match(text)
-}
-
-fn main() {}
-```
-
-Specifically, in this example, the regex will be compiled when it is used for
-the first time. On subsequent uses, it will reuse the previous compilation.
-
-# Example: iterating over capture groups
-
-This crate provides convenient iterators for matching an expression
-repeatedly against a search string to find successive non-overlapping
-matches. For example, to find all dates in a string and be able to access
-them by their component pieces:
-
-```rust
-# extern crate regex; use regex::Regex;
-# fn main() {
-let re = Regex::new(r"(\d{4})-(\d{2})-(\d{2})").unwrap();
-let text = "2012-03-14, 2013-01-01 and 2014-07-05";
-for cap in re.captures_iter(text) {
-    println!("Month: {} Day: {} Year: {}", &cap[2], &cap[3], &cap[1]);
-}
-// Output:
-// Month: 03 Day: 14 Year: 2012
-// Month: 01 Day: 01 Year: 2013
-// Month: 07 Day: 05 Year: 2014
-# }
-```
-
-Notice that the year is in the capture group indexed at `1`. This is
-because the *entire match* is stored in the capture group at index `0`.
-
-# Example: replacement with named capture groups
-
-Building on the previous example, perhaps we'd like to rearrange the date
-formats. This can be done with text replacement. But to make the code
-clearer, we can *name*  our capture groups and use those names as variables
-in our replacement text:
-
-```rust
-# extern crate regex; use regex::Regex;
-# fn main() {
-let re = Regex::new(r"(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})").unwrap();
-let before = "2012-03-14, 2013-01-01 and 2014-07-05";
-let after = re.replace_all(before, "$m/$d/$y");
-assert_eq!(after, "03/14/2012, 01/01/2013 and 07/05/2014");
-# }
-```
-
-The `replace` methods are actually polymorphic in the replacement, which
-provides more flexibility than is seen here. (See the documentation for
-`Regex::replace` for more details.)
-
-Note that if your regex gets complicated, you can use the `x` flag to
-enable insignificant whitespace mode, which also lets you write comments:
-
-```rust
-# extern crate regex; use regex::Regex;
-# fn main() {
-let re = Regex::new(r"(?x)
-  (?P<y>\d{4}) # the year
-  -
-  (?P<m>\d{2}) # the month
-  -
-  (?P<d>\d{2}) # the day
-").unwrap();
-let before = "2012-03-14, 2013-01-01 and 2014-07-05";
-let after = re.replace_all(before, "$m/$d/$y");
-assert_eq!(after, "03/14/2012, 01/01/2013 and 07/05/2014");
-# }
-```
-
-If you wish to match against whitespace in this mode, you can still use `\s`,
-`\n`, `\t`, etc. For escaping a single space character, you can escape it
-directly with `\ `, use its hex character code `\x20` or temporarily disable
-the `x` flag, e.g., `(?-x: )`.
-
-# Example: match multiple regular expressions simultaneously
-
-This demonstrates how to use a `RegexSet` to match multiple (possibly
-overlapping) regular expressions in a single scan of the search text:
-
-```rust
-use regex::RegexSet;
-
-let set = RegexSet::new(&[
-    r"\w+",
-    r"\d+",
-    r"\pL+",
-    r"foo",
-    r"bar",
-    r"barfoo",
-    r"foobar",
-]).unwrap();
-
-// Iterate over and collect all of the matches.
-let matches: Vec<_> = set.matches("foobar").into_iter().collect();
-assert_eq!(matches, vec![0, 2, 3, 4, 6]);
-
-// You can also test whether a particular regex matched:
-let matches = set.matches("foobar");
-assert!(!matches.matched(5));
-assert!(matches.matched(6));
-```
-
-# Pay for what you use
-
-With respect to searching text with a regular expression, there are three
-questions that can be asked:
-
-1. Does the text match this expression?
-2. If so, where does it match?
-3. Where did the capturing groups match?
-
-Generally speaking, this crate could provide a function to answer only #3,
-which would subsume #1 and #2 automatically. However, it can be significantly
-more expensive to compute the location of capturing group matches, so it's best
-not to do it if you don't need to.
-
-Therefore, only use what you need. For example, don't use `find` if you
-only need to test if an expression matches a string. (Use `is_match`
-instead.)
-
-# Unicode
-
-This implementation executes regular expressions **only** on valid UTF-8
-while exposing match locations as byte indices into the search string. (To
-relax this restriction, use the [`bytes`](bytes/index.html) sub-module.)
-
-Only simple case folding is supported. Namely, when matching
-case-insensitively, the characters are first mapped using the "simple" case
-folding rules defined by Unicode.
-
-Regular expressions themselves are **only** interpreted as a sequence of
-Unicode scalar values. This means you can use Unicode characters directly
-in your expression:
-
-```rust
-# extern crate regex; use regex::Regex;
-# fn main() {
-let re = Regex::new(r"(?i)Δ+").unwrap();
-let mat = re.find("ΔδΔ").unwrap();
-assert_eq!((mat.start(), mat.end()), (0, 6));
-# }
-```
-
-Most features of the regular expressions in this crate are Unicode aware. Here
-are some examples:
-
-* `.` will match any valid UTF-8 encoded Unicode scalar value except for `\n`.
-  (To also match `\n`, enable the `s` flag, e.g., `(?s:.)`.)
-* `\w`, `\d` and `\s` are Unicode aware. For example, `\s` will match all forms
-  of whitespace categorized by Unicode.
-* `\b` matches a Unicode word boundary.
-* Negated character classes like `[^a]` match all Unicode scalar values except
-  for `a`.
-* `^` and `$` are **not** Unicode aware in multi-line mode. Namely, they only
-  recognize `\n` and not any of the other forms of line terminators defined
-  by Unicode.
-
-Unicode general categories, scripts, script extensions, ages and a smattering
-of boolean properties are available as character classes. For example, you can
-match a sequence of numerals, Greek or Cherokee letters:
-
-```rust
-# extern crate regex; use regex::Regex;
-# fn main() {
-let re = Regex::new(r"[\pN\p{Greek}\p{Cherokee}]+").unwrap();
-let mat = re.find("abcΔᎠβⅠᏴγδⅡxyz").unwrap();
-assert_eq!((mat.start(), mat.end()), (3, 23));
-# }
-```
-
-For a more detailed breakdown of Unicode support with respect to
-[UTS#18](http://unicode.org/reports/tr18/),
-please see the
-[UNICODE](https://github.com/rust-lang/regex/blob/master/UNICODE.md)
-document in the root of the regex repository.
-
-# Opt out of Unicode support
-
-The `bytes` sub-module provides a `Regex` type that can be used to match
-on `&[u8]`. By default, text is interpreted as UTF-8 just like it is with
-the main `Regex` type. However, this behavior can be disabled by turning
-off the `u` flag, even if doing so could result in matching invalid UTF-8.
-For example, when the `u` flag is disabled, `.` will match any byte instead
-of any Unicode scalar value.
-
-Disabling the `u` flag is also possible with the standard `&str`-based `Regex`
-type, but it is only allowed where the UTF-8 invariant is maintained. For
-example, `(?-u:\w)` is an ASCII-only `\w` character class and is legal in an
-`&str`-based `Regex`, but `(?-u:\xFF)` will attempt to match the raw byte
-`\xFF`, which is invalid UTF-8 and therefore is illegal in `&str`-based
-regexes.
-
-Finally, since Unicode support requires bundling large Unicode data
-tables, this crate exposes knobs to disable the compilation of those
-data tables, which can be useful for shrinking binary size and reducing
-compilation times. For details on how to do that, see the section on [crate
-features](#crate-features).
-
-# Syntax
-
-The syntax supported in this crate is documented below.
-
-Note that the regular expression parser and abstract syntax are exposed in
-a separate crate, [`regex-syntax`](https://docs.rs/regex-syntax).
-
-## Matching one character
-
-<pre class="rust">
-.             any character except new line (includes new line with s flag)
-\d            digit (\p{Nd})
-\D            not digit
-\pN           One-letter name Unicode character class
-\p{Greek}     Unicode character class (general category or script)
-\PN           Negated one-letter name Unicode character class
-\P{Greek}     negated Unicode character class (general category or script)
-</pre>
-
-### Character classes
-
-<pre class="rust">
-[xyz]         A character class matching either x, y or z (union).
-[^xyz]        A character class matching any character except x, y and z.
-[a-z]         A character class matching any character in range a-z.
-[[:alpha:]]   ASCII character class ([A-Za-z])
-[[:^alpha:]]  Negated ASCII character class ([^A-Za-z])
-[x[^xyz]]     Nested/grouping character class (matching any character except y and z)
-[a-y&&xyz]    Intersection (matching x or y)
-[0-9&&[^4]]   Subtraction using intersection and negation (matching 0-9 except 4)
-[0-9--4]      Direct subtraction (matching 0-9 except 4)
-[a-g~~b-h]    Symmetric difference (matching `a` and `h` only)
-[\[\]]        Escaping in character classes (matching [ or ])
-</pre>
-
-Any named character class may appear inside a bracketed `[...]` character
-class. For example, `[\p{Greek}[:digit:]]` matches any Greek or ASCII
-digit. `[\p{Greek}&&\pL]` matches Greek letters.
-
-Precedence in character classes, from most binding to least:
-
-1. Ranges: `a-cd` == `[a-c]d`
-2. Union: `ab&&bc` == `[ab]&&[bc]`
-3. Intersection: `^a-z&&b` == `^[a-z&&b]`
-4. Negation
-
-## Composites
-
-<pre class="rust">
-xy    concatenation (x followed by y)
-x|y   alternation (x or y, prefer x)
-</pre>
-
-## Repetitions
-
-<pre class="rust">
-x*        zero or more of x (greedy)
-x+        one or more of x (greedy)
-x?        zero or one of x (greedy)
-x*?       zero or more of x (ungreedy/lazy)
-x+?       one or more of x (ungreedy/lazy)
-x??       zero or one of x (ungreedy/lazy)
-x{n,m}    at least n x and at most m x (greedy)
-x{n,}     at least n x (greedy)
-x{n}      exactly n x
-x{n,m}?   at least n x and at most m x (ungreedy/lazy)
-x{n,}?    at least n x (ungreedy/lazy)
-x{n}?     exactly n x
-</pre>
-
-## Empty matches
-
-<pre class="rust">
-^     the beginning of text (or start-of-line with multi-line mode)
-$     the end of text (or end-of-line with multi-line mode)
-\A    only the beginning of text (even with multi-line mode enabled)
-\z    only the end of text (even with multi-line mode enabled)
-\b    a Unicode word boundary (\w on one side and \W, \A, or \z on other)
-\B    not a Unicode word boundary
-</pre>
-
-## Grouping and flags
-
-<pre class="rust">
-(exp)          numbered capture group (indexed by opening parenthesis)
-(?P&lt;name&gt;exp)  named (also numbered) capture group (allowed chars: [_0-9a-zA-Z.\[\]])
-(?:exp)        non-capturing group
-(?flags)       set flags within current group
-(?flags:exp)   set flags for exp (non-capturing)
-</pre>
-
-Flags are each a single character. For example, `(?x)` sets the flag `x`
-and `(?-x)` clears the flag `x`. Multiple flags can be set or cleared at
-the same time: `(?xy)` sets both the `x` and `y` flags and `(?x-y)` sets
-the `x` flag and clears the `y` flag.
-
-All flags are by default disabled unless stated otherwise. They are:
-
-<pre class="rust">
-i     case-insensitive: letters match both upper and lower case
-m     multi-line mode: ^ and $ match begin/end of line
-s     allow . to match \n
-U     swap the meaning of x* and x*?
-u     Unicode support (enabled by default)
-x     ignore whitespace and allow line comments (starting with `#`)
-</pre>
-
-Flags can be toggled within a pattern. Here's an example that matches
-case-insensitively for the first part but case-sensitively for the second part:
-
-```rust
-# extern crate regex; use regex::Regex;
-# fn main() {
-let re = Regex::new(r"(?i)a+(?-i)b+").unwrap();
-let cap = re.captures("AaAaAbbBBBb").unwrap();
-assert_eq!(&cap[0], "AaAaAbb");
-# }
-```
-
-Notice that the `a+` matches either `a` or `A`, but the `b+` only matches
-`b`.
-
-Multi-line mode means `^` and `$` no longer match just at the beginning/end of
-the input, but at the beginning/end of lines:
-
-```
-# use regex::Regex;
-let re = Regex::new(r"(?m)^line \d+").unwrap();
-let m = re.find("line one\nline 2\n").unwrap();
-assert_eq!(m.as_str(), "line 2");
-```
-
-Note that `^` matches after new lines, even at the end of input:
-
-```
-# use regex::Regex;
-let re = Regex::new(r"(?m)^").unwrap();
-let m = re.find_iter("test\n").last().unwrap();
-assert_eq!((m.start(), m.end()), (5, 5));
-```
-
-Here is an example that uses an ASCII word boundary instead of a Unicode
-word boundary:
-
-```rust
-# extern crate regex; use regex::Regex;
-# fn main() {
-let re = Regex::new(r"(?-u:\b).+(?-u:\b)").unwrap();
-let cap = re.captures("$$abc$$").unwrap();
-assert_eq!(&cap[0], "abc");
-# }
-```
-
-## Escape sequences
-
-<pre class="rust">
-\*          literal *, works for any punctuation character: \.+*?()|[]{}^$
-\a          bell (\x07)
-\f          form feed (\x0C)
-\t          horizontal tab
-\n          new line
-\r          carriage return
-\v          vertical tab (\x0B)
-\123        octal character code (up to three digits) (when enabled)
-\x7F        hex character code (exactly two digits)
-\x{10FFFF}  any hex character code corresponding to a Unicode code point
-\u007F      hex character code (exactly four digits)
-\u{7F}      any hex character code corresponding to a Unicode code point
-\U0000007F  hex character code (exactly eight digits)
-\U{7F}      any hex character code corresponding to a Unicode code point
-</pre>
-
-## Perl character classes (Unicode friendly)
-
-These classes are based on the definitions provided in
-[UTS#18](http://www.unicode.org/reports/tr18/#Compatibility_Properties):
-
-<pre class="rust">
-\d     digit (\p{Nd})
-\D     not digit
-\s     whitespace (\p{White_Space})
-\S     not whitespace
-\w     word character (\p{Alphabetic} + \p{M} + \d + \p{Pc} + \p{Join_Control})
-\W     not word character
-</pre>
-
-## ASCII character classes
-
-<pre class="rust">
-[[:alnum:]]    alphanumeric ([0-9A-Za-z])
-[[:alpha:]]    alphabetic ([A-Za-z])
-[[:ascii:]]    ASCII ([\x00-\x7F])
-[[:blank:]]    blank ([\t ])
-[[:cntrl:]]    control ([\x00-\x1F\x7F])
-[[:digit:]]    digits ([0-9])
-[[:graph:]]    graphical ([!-~])
-[[:lower:]]    lower case ([a-z])
-[[:print:]]    printable ([ -~])
-[[:punct:]]    punctuation ([!-/:-@\[-`{-~])
-[[:space:]]    whitespace ([\t\n\v\f\r ])
-[[:upper:]]    upper case ([A-Z])
-[[:word:]]     word characters ([0-9A-Za-z_])
-[[:xdigit:]]   hex digit ([0-9A-Fa-f])
-</pre>
-
-# Crate features
-
-By default, this crate tries pretty hard to make regex matching both as fast
-as possible and as correct as it can be, within reason. This means that there
-is a lot of code dedicated to performance, the handling of Unicode data and the
-Unicode data itself. Overall, this leads to more dependencies, larger binaries
-and longer compile times.  This trade off may not be appropriate in all cases,
-and indeed, even when all Unicode and performance features are disabled, one
-is still left with a perfectly serviceable regex engine that will work well
-in many cases.
-
-This crate exposes a number of features for controlling that trade off. Some
-of these features are strictly performance oriented, such that disabling them
-won't result in a loss of functionality, but may result in worse performance.
-Other features, such as the ones controlling the presence or absence of Unicode
-data, can result in a loss of functionality. For example, if one disables the
-`unicode-case` feature (described below), then compiling the regex `(?i)a`
-will fail since Unicode case insensitivity is enabled by default. Instead,
-callers must use `(?i-u)a` instead to disable Unicode case folding. Stated
-differently, enabling or disabling any of the features below can only add or
-subtract from the total set of valid regular expressions. Enabling or disabling
-a feature will never modify the match semantics of a regular expression.
-
-All features below are enabled by default.
-
-### Ecosystem features
-
-* **std** -
-  When enabled, this will cause `regex` to use the standard library. Currently,
-  disabling this feature will always result in a compilation error. It is
-  intended to add `alloc`-only support to regex in the future.
-
-### Performance features
-
-* **perf** -
-  Enables all performance related features. This feature is enabled by default
-  and will always cover all features that improve performance, even if more
-  are added in the future.
-* **perf-cache** -
-  Enables the use of very fast thread safe caching for internal match state.
-  When this is disabled, caching is still used, but with a slower and simpler
-  implementation. Disabling this drops the `thread_local` and `lazy_static`
-  dependencies.
-* **perf-dfa** -
-  Enables the use of a lazy DFA for matching. The lazy DFA is used to compile
-  portions of a regex to a very fast DFA on an as-needed basis. This can
-  result in substantial speedups, usually by an order of magnitude on large
-  haystacks. The lazy DFA does not bring in any new dependencies, but it can
-  make compile times longer.
-* **perf-inline** -
-  Enables the use of aggressive inlining inside match routines. This reduces
-  the overhead of each match. The aggressive inlining, however, increases
-  compile times and binary size.
-* **perf-literal** -
-  Enables the use of literal optimizations for speeding up matches. In some
-  cases, literal optimizations can result in speedups of _several_ orders of
-  magnitude. Disabling this drops the `aho-corasick` and `memchr` dependencies.
-
-### Unicode features
-
-* **unicode** -
-  Enables all Unicode features. This feature is enabled by default, and will
-  always cover all Unicode features, even if more are added in the future.
-* **unicode-age** -
-  Provide the data for the
-  [Unicode `Age` property](https://www.unicode.org/reports/tr44/tr44-24.html#Character_Age).
-  This makes it possible to use classes like `\p{Age:6.0}` to refer to all
-  codepoints first introduced in Unicode 6.0
-* **unicode-bool** -
-  Provide the data for numerous Unicode boolean properties. The full list
-  is not included here, but contains properties like `Alphabetic`, `Emoji`,
-  `Lowercase`, `Math`, `Uppercase` and `White_Space`.
-* **unicode-case** -
-  Provide the data for case insensitive matching using
-  [Unicode's "simple loose matches" specification](https://www.unicode.org/reports/tr18/#Simple_Loose_Matches).
-* **unicode-gencat** -
-  Provide the data for
-  [Unicode general categories](https://www.unicode.org/reports/tr44/tr44-24.html#General_Category_Values).
-  This includes, but is not limited to, `Decimal_Number`, `Letter`,
-  `Math_Symbol`, `Number` and `Punctuation`.
-* **unicode-perl** -
-  Provide the data for supporting the Unicode-aware Perl character classes,
-  corresponding to `\w`, `\s` and `\d`. This is also necessary for using
-  Unicode-aware word boundary assertions. Note that if this feature is
-  disabled, the `\s` and `\d` character classes are still available if the
-  `unicode-bool` and `unicode-gencat` features are enabled, respectively.
-* **unicode-script** -
-  Provide the data for
-  [Unicode scripts and script extensions](https://www.unicode.org/reports/tr24/).
-  This includes, but is not limited to, `Arabic`, `Cyrillic`, `Hebrew`,
-  `Latin` and `Thai`.
-* **unicode-segment** -
-  Provide the data necessary to provide the properties used to implement the
-  [Unicode text segmentation algorithms](https://www.unicode.org/reports/tr29/).
-  This enables using classes like `\p{gcb=Extend}`, `\p{wb=Katakana}` and
-  `\p{sb=ATerm}`.
-
-
-# Untrusted input
-
-This crate can handle both untrusted regular expressions and untrusted
-search text.
-
-Untrusted regular expressions are handled by capping the size of a compiled
-regular expression.
-(See [`RegexBuilder::size_limit`](struct.RegexBuilder.html#method.size_limit).)
-Without this, it would be trivial for an attacker to exhaust your system's
-memory with expressions like `a{100}{100}{100}`.
-
-Untrusted search text is allowed because the matching engine(s) in this
-crate have time complexity `O(mn)` (with `m ~ regex` and `n ~ search
-text`), which means there's no way to cause exponential blow-up like with
-some other regular expression engines. (We pay for this by disallowing
-features like arbitrary look-ahead and backreferences.)
-
-When a DFA is used, pathological cases with exponential state blow-up are
-avoided by constructing the DFA lazily or in an "online" manner. Therefore,
-at most one new state can be created for each byte of input. This satisfies
-our time complexity guarantees, but can lead to memory growth
-proportional to the size of the input. As a stopgap, the DFA is only
-allowed to store a fixed number of states. When the limit is reached, its
-states are wiped and continues on, possibly duplicating previous work. If
-the limit is reached too frequently, it gives up and hands control off to
-another matching engine with fixed memory requirements.
-(The DFA size limit can also be tweaked. See
-[`RegexBuilder::dfa_size_limit`](struct.RegexBuilder.html#method.dfa_size_limit).)
-*/
-
-#![deny(missing_docs)]
-#![cfg_attr(test, deny(warnings))]
-#![cfg_attr(feature = "pattern", feature(pattern))]
-#![warn(missing_debug_implementations)]
-
-#[cfg(not(feature = "std"))]
-compile_error!("`std` feature is currently required to build this crate");
-
-#[cfg(feature = "perf-literal")]
-extern crate aho_corasick;
-// #[cfg(doctest)]
-// extern crate doc_comment;
-#[cfg(feature = "perf-literal")]
-extern crate memchr;
-#[cfg(test)]
-#[cfg_attr(feature = "perf-literal", macro_use)]
-extern crate quickcheck;
-extern crate regex_syntax as syntax;
-#[cfg(feature = "perf-cache")]
-extern crate thread_local;
-
-// #[cfg(doctest)]
-// doc_comment::doctest!("../README.md");
-
-#[cfg(feature = "std")]
-pub use error::Error;
-#[cfg(feature = "std")]
-pub use re_builder::set_unicode::*;
-#[cfg(feature = "std")]
-pub use re_builder::unicode::*;
-#[cfg(feature = "std")]
-pub use re_set::unicode::*;
-#[cfg(feature = "std")]
-#[cfg(feature = "std")]
-pub use re_unicode::{
-    escape, CaptureLocations, CaptureMatches, CaptureNames, Captures,
-    Locations, Match, Matches, NoExpand, Regex, Replacer, ReplacerRef, Split,
-    SplitN, SubCaptureMatches,
-};
-
-/**
-Match regular expressions on arbitrary bytes.
-
-This module provides a nearly identical API to the one found in the
-top-level of this crate. There are two important differences:
-
-1. Matching is done on `&[u8]` instead of `&str`. Additionally, `Vec<u8>`
-is used where `String` would have been used.
-2. Unicode support can be disabled even when disabling it would result in
-matching invalid UTF-8 bytes.
-
-# Example: match null terminated string
-
-This shows how to find all null-terminated strings in a slice of bytes:
-
-```rust
-# use regex::bytes::Regex;
-let re = Regex::new(r"(?-u)(?P<cstr>[^\x00]+)\x00").unwrap();
-let text = b"foo\x00bar\x00baz\x00";
-
-// Extract all of the strings without the null terminator from each match.
-// The unwrap is OK here since a match requires the `cstr` capture to match.
-let cstrs: Vec<&[u8]> =
-    re.captures_iter(text)
-      .map(|c| c.name("cstr").unwrap().as_bytes())
-      .collect();
-assert_eq!(vec![&b"foo"[..], &b"bar"[..], &b"baz"[..]], cstrs);
-```
-
-# Example: selectively enable Unicode support
-
-This shows how to match an arbitrary byte pattern followed by a UTF-8 encoded
-string (e.g., to extract a title from a Matroska file):
-
-```rust
-# use std::str;
-# use regex::bytes::Regex;
-let re = Regex::new(
-    r"(?-u)\x7b\xa9(?:[\x80-\xfe]|[\x40-\xff].)(?u:(.*))"
-).unwrap();
-let text = b"\x12\xd0\x3b\x5f\x7b\xa9\x85\xe2\x98\x83\x80\x98\x54\x76\x68\x65";
-let caps = re.captures(text).unwrap();
-
-// Notice that despite the `.*` at the end, it will only match valid UTF-8
-// because Unicode mode was enabled with the `u` flag. Without the `u` flag,
-// the `.*` would match the rest of the bytes.
-let mat = caps.get(1).unwrap();
-assert_eq!((7, 10), (mat.start(), mat.end()));
-
-// If there was a match, Unicode mode guarantees that `title` is valid UTF-8.
-let title = str::from_utf8(&caps[1]).unwrap();
-assert_eq!("☃", title);
-```
-
-In general, if the Unicode flag is enabled in a capture group and that capture
-is part of the overall match, then the capture is *guaranteed* to be valid
-UTF-8.
-
-# Syntax
-
-The supported syntax is pretty much the same as the syntax for Unicode
-regular expressions with a few changes that make sense for matching arbitrary
-bytes:
-
-1. The `u` flag can be disabled even when disabling it might cause the regex to
-match invalid UTF-8. When the `u` flag is disabled, the regex is said to be in
-"ASCII compatible" mode.
-2. In ASCII compatible mode, neither Unicode scalar values nor Unicode
-character classes are allowed.
-3. In ASCII compatible mode, Perl character classes (`\w`, `\d` and `\s`)
-revert to their typical ASCII definition. `\w` maps to `[[:word:]]`, `\d` maps
-to `[[:digit:]]` and `\s` maps to `[[:space:]]`.
-4. In ASCII compatible mode, word boundaries use the ASCII compatible `\w` to
-determine whether a byte is a word byte or not.
-5. Hexadecimal notation can be used to specify arbitrary bytes instead of
-Unicode codepoints. For example, in ASCII compatible mode, `\xFF` matches the
-literal byte `\xFF`, while in Unicode mode, `\xFF` is a Unicode codepoint that
-matches its UTF-8 encoding of `\xC3\xBF`. Similarly for octal notation when
-enabled.
-6. In ASCII compatible mode, `.` matches any *byte* except for `\n`. When the
-`s` flag is additionally enabled, `.` matches any byte.
-
-# Performance
-
-In general, one should expect performance on `&[u8]` to be roughly similar to
-performance on `&str`.
-*/
-#[cfg(feature = "std")]
-pub mod bytes {
-    pub use re_builder::bytes::*;
-    pub use re_builder::set_bytes::*;
-    pub use re_bytes::*;
-    pub use re_set::bytes::*;
-}
-
-mod backtrack;
-mod cache;
-mod compile;
-#[cfg(feature = "perf-dfa")]
-mod dfa;
-mod error;
-mod exec;
-mod expand;
-mod find_byte;
-#[cfg(feature = "perf-literal")]
-mod freqs;
-mod input;
-mod literal;
-#[cfg(feature = "pattern")]
-mod pattern;
-mod pikevm;
-mod prog;
-mod re_builder;
-mod re_bytes;
-mod re_set;
-mod re_trait;
-mod re_unicode;
-mod sparse;
-mod utf8;
-
-/// The `internal` module exists to support suspicious activity, such as
-/// testing different matching engines and supporting the `regex-debug` CLI
-/// utility.
-#[doc(hidden)]
-#[cfg(feature = "std")]
-pub mod internal {
-    pub use compile::Compiler;
-    pub use exec::{Exec, ExecBuilder};
-    pub use input::{Char, CharInput, Input, InputAt};
-    pub use literal::LiteralSearcher;
-    pub use prog::{EmptyLook, Inst, InstRanges, Program};
-}
diff --git a/vendor/regex-1.4.3/src/literal/imp.rs b/vendor/regex-1.4.3/src/literal/imp.rs
deleted file mode 100644 (file)
index e4d04ed..0000000
+++ /dev/null
@@ -1,1122 +0,0 @@
-use std::cmp;
-use std::mem;
-
-use aho_corasick::{self, packed, AhoCorasick, AhoCorasickBuilder};
-use memchr::{memchr, memchr2, memchr3};
-use syntax::hir::literal::{Literal, Literals};
-
-use freqs::BYTE_FREQUENCIES;
-
-/// A prefix extracted from a compiled regular expression.
-///
-/// A regex prefix is a set of literal strings that *must* be matched at the
-/// beginning of a regex in order for the entire regex to match. Similarly
-/// for a regex suffix.
-#[derive(Clone, Debug)]
-pub struct LiteralSearcher {
-    complete: bool,
-    lcp: FreqyPacked,
-    lcs: FreqyPacked,
-    matcher: Matcher,
-}
-
-#[derive(Clone, Debug)]
-enum Matcher {
-    /// No literals. (Never advances through the input.)
-    Empty,
-    /// A set of four or more single byte literals.
-    Bytes(SingleByteSet),
-    /// A single substring, find using memchr and frequency analysis.
-    FreqyPacked(FreqyPacked),
-    /// A single substring, find using Boyer-Moore.
-    BoyerMoore(BoyerMooreSearch),
-    /// An Aho-Corasick automaton.
-    AC { ac: AhoCorasick<u32>, lits: Vec<Literal> },
-    /// A packed multiple substring searcher, using SIMD.
-    ///
-    /// Note that Aho-Corasick will actually use this packed searcher
-    /// internally automatically, however, there is some overhead associated
-    /// with going through the Aho-Corasick machinery. So using the packed
-    /// searcher directly results in some gains.
-    Packed { s: packed::Searcher, lits: Vec<Literal> },
-}
-
-impl LiteralSearcher {
-    /// Returns a matcher that never matches and never advances the input.
-    pub fn empty() -> Self {
-        Self::new(Literals::empty(), Matcher::Empty)
-    }
-
-    /// Returns a matcher for literal prefixes from the given set.
-    pub fn prefixes(lits: Literals) -> Self {
-        let matcher = Matcher::prefixes(&lits);
-        Self::new(lits, matcher)
-    }
-
-    /// Returns a matcher for literal suffixes from the given set.
-    pub fn suffixes(lits: Literals) -> Self {
-        let matcher = Matcher::suffixes(&lits);
-        Self::new(lits, matcher)
-    }
-
-    fn new(lits: Literals, matcher: Matcher) -> Self {
-        let complete = lits.all_complete();
-        LiteralSearcher {
-            complete: complete,
-            lcp: FreqyPacked::new(lits.longest_common_prefix().to_vec()),
-            lcs: FreqyPacked::new(lits.longest_common_suffix().to_vec()),
-            matcher: matcher,
-        }
-    }
-
-    /// Returns true if all matches comprise the entire regular expression.
-    ///
-    /// This does not necessarily mean that a literal match implies a match
-    /// of the regular expression. For example, the regular expression `^a`
-    /// is comprised of a single complete literal `a`, but the regular
-    /// expression demands that it only match at the beginning of a string.
-    pub fn complete(&self) -> bool {
-        self.complete && !self.is_empty()
-    }
-
-    /// Find the position of a literal in `haystack` if it exists.
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    pub fn find(&self, haystack: &[u8]) -> Option<(usize, usize)> {
-        use self::Matcher::*;
-        match self.matcher {
-            Empty => Some((0, 0)),
-            Bytes(ref sset) => sset.find(haystack).map(|i| (i, i + 1)),
-            FreqyPacked(ref s) => s.find(haystack).map(|i| (i, i + s.len())),
-            BoyerMoore(ref s) => s.find(haystack).map(|i| (i, i + s.len())),
-            AC { ref ac, .. } => {
-                ac.find(haystack).map(|m| (m.start(), m.end()))
-            }
-            Packed { ref s, .. } => {
-                s.find(haystack).map(|m| (m.start(), m.end()))
-            }
-        }
-    }
-
-    /// Like find, except matches must start at index `0`.
-    pub fn find_start(&self, haystack: &[u8]) -> Option<(usize, usize)> {
-        for lit in self.iter() {
-            if lit.len() > haystack.len() {
-                continue;
-            }
-            if lit == &haystack[0..lit.len()] {
-                return Some((0, lit.len()));
-            }
-        }
-        None
-    }
-
-    /// Like find, except matches must end at index `haystack.len()`.
-    pub fn find_end(&self, haystack: &[u8]) -> Option<(usize, usize)> {
-        for lit in self.iter() {
-            if lit.len() > haystack.len() {
-                continue;
-            }
-            if lit == &haystack[haystack.len() - lit.len()..] {
-                return Some((haystack.len() - lit.len(), haystack.len()));
-            }
-        }
-        None
-    }
-
-    /// Returns an iterator over all literals to be matched.
-    pub fn iter(&self) -> LiteralIter {
-        match self.matcher {
-            Matcher::Empty => LiteralIter::Empty,
-            Matcher::Bytes(ref sset) => LiteralIter::Bytes(&sset.dense),
-            Matcher::FreqyPacked(ref s) => LiteralIter::Single(&s.pat),
-            Matcher::BoyerMoore(ref s) => LiteralIter::Single(&s.pattern),
-            Matcher::AC { ref lits, .. } => LiteralIter::AC(lits),
-            Matcher::Packed { ref lits, .. } => LiteralIter::Packed(lits),
-        }
-    }
-
-    /// Returns a matcher for the longest common prefix of this matcher.
-    pub fn lcp(&self) -> &FreqyPacked {
-        &self.lcp
-    }
-
-    /// Returns a matcher for the longest common suffix of this matcher.
-    pub fn lcs(&self) -> &FreqyPacked {
-        &self.lcs
-    }
-
-    /// Returns true iff this prefix is empty.
-    pub fn is_empty(&self) -> bool {
-        self.len() == 0
-    }
-
-    /// Returns the number of prefixes in this machine.
-    pub fn len(&self) -> usize {
-        use self::Matcher::*;
-        match self.matcher {
-            Empty => 0,
-            Bytes(ref sset) => sset.dense.len(),
-            FreqyPacked(_) => 1,
-            BoyerMoore(_) => 1,
-            AC { ref ac, .. } => ac.pattern_count(),
-            Packed { ref lits, .. } => lits.len(),
-        }
-    }
-
-    /// Return the approximate heap usage of literals in bytes.
-    pub fn approximate_size(&self) -> usize {
-        use self::Matcher::*;
-        match self.matcher {
-            Empty => 0,
-            Bytes(ref sset) => sset.approximate_size(),
-            FreqyPacked(ref single) => single.approximate_size(),
-            BoyerMoore(ref single) => single.approximate_size(),
-            AC { ref ac, .. } => ac.heap_bytes(),
-            Packed { ref s, .. } => s.heap_bytes(),
-        }
-    }
-}
-
-impl Matcher {
-    fn prefixes(lits: &Literals) -> Self {
-        let sset = SingleByteSet::prefixes(lits);
-        Matcher::new(lits, sset)
-    }
-
-    fn suffixes(lits: &Literals) -> Self {
-        let sset = SingleByteSet::suffixes(lits);
-        Matcher::new(lits, sset)
-    }
-
-    fn new(lits: &Literals, sset: SingleByteSet) -> Self {
-        if lits.literals().is_empty() {
-            return Matcher::Empty;
-        }
-        if sset.dense.len() >= 26 {
-            // Avoid trying to match a large number of single bytes.
-            // This is *very* sensitive to a frequency analysis comparison
-            // between the bytes in sset and the composition of the haystack.
-            // No matter the size of sset, if its members all are rare in the
-            // haystack, then it'd be worth using it. How to tune this... IDK.
-            // ---AG
-            return Matcher::Empty;
-        }
-        if sset.complete {
-            return Matcher::Bytes(sset);
-        }
-        if lits.literals().len() == 1 {
-            let lit = lits.literals()[0].to_vec();
-            if BoyerMooreSearch::should_use(lit.as_slice()) {
-                return Matcher::BoyerMoore(BoyerMooreSearch::new(lit));
-            } else {
-                return Matcher::FreqyPacked(FreqyPacked::new(lit));
-            }
-        }
-
-        let pats = lits.literals().to_owned();
-        let is_aho_corasick_fast = sset.dense.len() <= 1 && sset.all_ascii;
-        if lits.literals().len() <= 100 && !is_aho_corasick_fast {
-            let mut builder = packed::Config::new()
-                .match_kind(packed::MatchKind::LeftmostFirst)
-                .builder();
-            if let Some(s) = builder.extend(&pats).build() {
-                return Matcher::Packed { s, lits: pats };
-            }
-        }
-        let ac = AhoCorasickBuilder::new()
-            .match_kind(aho_corasick::MatchKind::LeftmostFirst)
-            .dfa(true)
-            .build_with_size::<u32, _, _>(&pats)
-            .unwrap();
-        Matcher::AC { ac, lits: pats }
-    }
-}
-
-#[derive(Debug)]
-pub enum LiteralIter<'a> {
-    Empty,
-    Bytes(&'a [u8]),
-    Single(&'a [u8]),
-    AC(&'a [Literal]),
-    Packed(&'a [Literal]),
-}
-
-impl<'a> Iterator for LiteralIter<'a> {
-    type Item = &'a [u8];
-
-    fn next(&mut self) -> Option<Self::Item> {
-        match *self {
-            LiteralIter::Empty => None,
-            LiteralIter::Bytes(ref mut many) => {
-                if many.is_empty() {
-                    None
-                } else {
-                    let next = &many[0..1];
-                    *many = &many[1..];
-                    Some(next)
-                }
-            }
-            LiteralIter::Single(ref mut one) => {
-                if one.is_empty() {
-                    None
-                } else {
-                    let next = &one[..];
-                    *one = &[];
-                    Some(next)
-                }
-            }
-            LiteralIter::AC(ref mut lits) => {
-                if lits.is_empty() {
-                    None
-                } else {
-                    let next = &lits[0];
-                    *lits = &lits[1..];
-                    Some(&**next)
-                }
-            }
-            LiteralIter::Packed(ref mut lits) => {
-                if lits.is_empty() {
-                    None
-                } else {
-                    let next = &lits[0];
-                    *lits = &lits[1..];
-                    Some(&**next)
-                }
-            }
-        }
-    }
-}
-
-#[derive(Clone, Debug)]
-struct SingleByteSet {
-    sparse: Vec<bool>,
-    dense: Vec<u8>,
-    complete: bool,
-    all_ascii: bool,
-}
-
-impl SingleByteSet {
-    fn new() -> SingleByteSet {
-        SingleByteSet {
-            sparse: vec![false; 256],
-            dense: vec![],
-            complete: true,
-            all_ascii: true,
-        }
-    }
-
-    fn prefixes(lits: &Literals) -> SingleByteSet {
-        let mut sset = SingleByteSet::new();
-        for lit in lits.literals() {
-            sset.complete = sset.complete && lit.len() == 1;
-            if let Some(&b) = lit.get(0) {
-                if !sset.sparse[b as usize] {
-                    if b > 0x7F {
-                        sset.all_ascii = false;
-                    }
-                    sset.dense.push(b);
-                    sset.sparse[b as usize] = true;
-                }
-            }
-        }
-        sset
-    }
-
-    fn suffixes(lits: &Literals) -> SingleByteSet {
-        let mut sset = SingleByteSet::new();
-        for lit in lits.literals() {
-            sset.complete = sset.complete && lit.len() == 1;
-            if let Some(&b) = lit.get(lit.len().checked_sub(1).unwrap()) {
-                if !sset.sparse[b as usize] {
-                    if b > 0x7F {
-                        sset.all_ascii = false;
-                    }
-                    sset.dense.push(b);
-                    sset.sparse[b as usize] = true;
-                }
-            }
-        }
-        sset
-    }
-
-    /// Faster find that special cases certain sizes to use memchr.
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn find(&self, text: &[u8]) -> Option<usize> {
-        match self.dense.len() {
-            0 => None,
-            1 => memchr(self.dense[0], text),
-            2 => memchr2(self.dense[0], self.dense[1], text),
-            3 => memchr3(self.dense[0], self.dense[1], self.dense[2], text),
-            _ => self._find(text),
-        }
-    }
-
-    /// Generic find that works on any sized set.
-    fn _find(&self, haystack: &[u8]) -> Option<usize> {
-        for (i, &b) in haystack.iter().enumerate() {
-            if self.sparse[b as usize] {
-                return Some(i);
-            }
-        }
-        None
-    }
-
-    fn approximate_size(&self) -> usize {
-        (self.dense.len() * mem::size_of::<u8>())
-            + (self.sparse.len() * mem::size_of::<bool>())
-    }
-}
-
-/// Provides an implementation of fast subtring search using frequency
-/// analysis.
-///
-/// memchr is so fast that we do everything we can to keep the loop in memchr
-/// for as long as possible. The easiest way to do this is to intelligently
-/// pick the byte to send to memchr. The best byte is the byte that occurs
-/// least frequently in the haystack. Since doing frequency analysis on the
-/// haystack is far too expensive, we compute a set of fixed frequencies up
-/// front and hard code them in src/freqs.rs. Frequency analysis is done via
-/// scripts/frequencies.py.
-#[derive(Clone, Debug)]
-pub struct FreqyPacked {
-    /// The pattern.
-    pat: Vec<u8>,
-    /// The number of Unicode characters in the pattern. This is useful for
-    /// determining the effective length of a pattern when deciding which
-    /// optimizations to perform. A trailing incomplete UTF-8 sequence counts
-    /// as one character.
-    char_len: usize,
-    /// The rarest byte in the pattern, according to pre-computed frequency
-    /// analysis.
-    rare1: u8,
-    /// The offset of the rarest byte in `pat`.
-    rare1i: usize,
-    /// The second rarest byte in the pattern, according to pre-computed
-    /// frequency analysis. (This may be equivalent to the rarest byte.)
-    ///
-    /// The second rarest byte is used as a type of guard for quickly detecting
-    /// a mismatch after memchr locates an instance of the rarest byte. This
-    /// is a hedge against pathological cases where the pre-computed frequency
-    /// analysis may be off. (But of course, does not prevent *all*
-    /// pathological cases.)
-    rare2: u8,
-    /// The offset of the second rarest byte in `pat`.
-    rare2i: usize,
-}
-
-impl FreqyPacked {
-    fn new(pat: Vec<u8>) -> FreqyPacked {
-        if pat.is_empty() {
-            return FreqyPacked::empty();
-        }
-
-        // Find the rarest two bytes. Try to make them distinct (but it's not
-        // required).
-        let mut rare1 = pat[0];
-        let mut rare2 = pat[0];
-        for b in pat[1..].iter().cloned() {
-            if freq_rank(b) < freq_rank(rare1) {
-                rare1 = b;
-            }
-        }
-        for &b in &pat {
-            if rare1 == rare2 {
-                rare2 = b
-            } else if b != rare1 && freq_rank(b) < freq_rank(rare2) {
-                rare2 = b;
-            }
-        }
-
-        // And find the offsets of their last occurrences.
-        let rare1i = pat.iter().rposition(|&b| b == rare1).unwrap();
-        let rare2i = pat.iter().rposition(|&b| b == rare2).unwrap();
-
-        let char_len = char_len_lossy(&pat);
-        FreqyPacked {
-            pat: pat,
-            char_len: char_len,
-            rare1: rare1,
-            rare1i: rare1i,
-            rare2: rare2,
-            rare2i: rare2i,
-        }
-    }
-
-    fn empty() -> FreqyPacked {
-        FreqyPacked {
-            pat: vec![],
-            char_len: 0,
-            rare1: 0,
-            rare1i: 0,
-            rare2: 0,
-            rare2i: 0,
-        }
-    }
-
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    pub fn find(&self, haystack: &[u8]) -> Option<usize> {
-        let pat = &*self.pat;
-        if haystack.len() < pat.len() || pat.is_empty() {
-            return None;
-        }
-        let mut i = self.rare1i;
-        while i < haystack.len() {
-            i += match memchr(self.rare1, &haystack[i..]) {
-                None => return None,
-                Some(i) => i,
-            };
-            let start = i - self.rare1i;
-            let end = start + pat.len();
-            if end > haystack.len() {
-                return None;
-            }
-            let aligned = &haystack[start..end];
-            if aligned[self.rare2i] == self.rare2 && aligned == &*self.pat {
-                return Some(start);
-            }
-            i += 1;
-        }
-        None
-    }
-
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    pub fn is_suffix(&self, text: &[u8]) -> bool {
-        if text.len() < self.len() {
-            return false;
-        }
-        text[text.len() - self.len()..] == *self.pat
-    }
-
-    pub fn len(&self) -> usize {
-        self.pat.len()
-    }
-
-    pub fn char_len(&self) -> usize {
-        self.char_len
-    }
-
-    fn approximate_size(&self) -> usize {
-        self.pat.len() * mem::size_of::<u8>()
-    }
-}
-
-fn char_len_lossy(bytes: &[u8]) -> usize {
-    String::from_utf8_lossy(bytes).chars().count()
-}
-
-/// An implementation of Tuned Boyer-Moore as laid out by
-/// Andrew Hume and Daniel Sunday in "Fast String Searching".
-/// O(n) in the size of the input.
-///
-/// Fast string searching algorithms come in many variations,
-/// but they can generally be described in terms of three main
-/// components.
-///
-/// The skip loop is where the string searcher wants to spend
-/// as much time as possible. Exactly which character in the
-/// pattern the skip loop examines varies from algorithm to
-/// algorithm, but in the simplest case this loop repeated
-/// looks at the last character in the pattern and jumps
-/// forward in the input if it is not in the pattern.
-/// Robert Boyer and J Moore called this the "fast" loop in
-/// their original paper.
-///
-/// The match loop is responsible for actually examining the
-/// whole potentially matching substring. In order to fail
-/// faster, the match loop sometimes has a guard test attached.
-/// The guard test uses frequency analysis of the different
-/// characters in the pattern to choose the least frequency
-/// occurring character and use it to find match failures
-/// as quickly as possible.
-///
-/// The shift rule governs how the algorithm will shuffle its
-/// test window in the event of a failure during the match loop.
-/// Certain shift rules allow the worst-case run time of the
-/// algorithm to be shown to be O(n) in the size of the input
-/// rather than O(nm) in the size of the input and the size
-/// of the pattern (as naive Boyer-Moore is).
-///
-/// "Fast String Searching", in addition to presenting a tuned
-/// algorithm, provides a comprehensive taxonomy of the many
-/// different flavors of string searchers. Under that taxonomy
-/// TBM, the algorithm implemented here, uses an unrolled fast
-/// skip loop with memchr fallback, a forward match loop with guard,
-/// and the mini Sunday's delta shift rule. To unpack that you'll have to
-/// read the paper.
-#[derive(Clone, Debug)]
-pub struct BoyerMooreSearch {
-    /// The pattern we are going to look for in the haystack.
-    pattern: Vec<u8>,
-
-    /// The skip table for the skip loop.
-    ///
-    /// Maps the character at the end of the input
-    /// to a shift.
-    skip_table: Vec<usize>,
-
-    /// The guard character (least frequently occurring char).
-    guard: u8,
-    /// The reverse-index of the guard character in the pattern.
-    guard_reverse_idx: usize,
-
-    /// Daniel Sunday's mini generalized delta2 shift table.
-    ///
-    /// We use a skip loop, so we only have to provide a shift
-    /// for the skip char (last char). This is why it is a mini
-    /// shift rule.
-    md2_shift: usize,
-}
-
-impl BoyerMooreSearch {
-    /// Create a new string searcher, performing whatever
-    /// compilation steps are required.
-    fn new(pattern: Vec<u8>) -> Self {
-        debug_assert!(!pattern.is_empty());
-
-        let (g, gi) = Self::select_guard(pattern.as_slice());
-        let skip_table = Self::compile_skip_table(pattern.as_slice());
-        let md2_shift = Self::compile_md2_shift(pattern.as_slice());
-        BoyerMooreSearch {
-            pattern: pattern,
-            skip_table: skip_table,
-            guard: g,
-            guard_reverse_idx: gi,
-            md2_shift: md2_shift,
-        }
-    }
-
-    /// Find the pattern in `haystack`, returning the offset
-    /// of the start of the first occurrence of the pattern
-    /// in `haystack`.
-    #[inline]
-    fn find(&self, haystack: &[u8]) -> Option<usize> {
-        if haystack.len() < self.pattern.len() {
-            return None;
-        }
-
-        let mut window_end = self.pattern.len() - 1;
-
-        // Inspired by the grep source. It is a way
-        // to do correct loop unrolling without having to place
-        // a crashpad of terminating charicters at the end in
-        // the way described in the Fast String Searching paper.
-        const NUM_UNROLL: usize = 10;
-        // 1 for the initial position, and 1 for the md2 shift
-        let short_circut = (NUM_UNROLL + 2) * self.pattern.len();
-
-        if haystack.len() > short_circut {
-            // just 1 for the md2 shift
-            let backstop =
-                haystack.len() - ((NUM_UNROLL + 1) * self.pattern.len());
-            loop {
-                window_end =
-                    match self.skip_loop(haystack, window_end, backstop) {
-                        Some(i) => i,
-                        None => return None,
-                    };
-                if window_end >= backstop {
-                    break;
-                }
-
-                if self.check_match(haystack, window_end) {
-                    return Some(window_end - (self.pattern.len() - 1));
-                } else {
-                    let skip = self.skip_table[haystack[window_end] as usize];
-                    window_end +=
-                        if skip == 0 { self.md2_shift } else { skip };
-                    continue;
-                }
-            }
-        }
-
-        // now process the input after the backstop
-        while window_end < haystack.len() {
-            let mut skip = self.skip_table[haystack[window_end] as usize];
-            if skip == 0 {
-                if self.check_match(haystack, window_end) {
-                    return Some(window_end - (self.pattern.len() - 1));
-                } else {
-                    skip = self.md2_shift;
-                }
-            }
-            window_end += skip;
-        }
-
-        None
-    }
-
-    fn len(&self) -> usize {
-        return self.pattern.len();
-    }
-
-    /// The key heuristic behind which the BoyerMooreSearch lives.
-    ///
-    /// See `rust-lang/regex/issues/408`.
-    ///
-    /// Tuned Boyer-Moore is actually pretty slow! It turns out a handrolled
-    /// platform-specific memchr routine with a bit of frequency
-    /// analysis sprinkled on top actually wins most of the time.
-    /// However, there are a few cases where Tuned Boyer-Moore still
-    /// wins.
-    ///
-    /// If the haystack is random, frequency analysis doesn't help us,
-    /// so Boyer-Moore will win for sufficiently large needles.
-    /// Unfortunately, there is no obvious way to determine this
-    /// ahead of time.
-    ///
-    /// If the pattern itself consists of very common characters,
-    /// frequency analysis won't get us anywhere. The most extreme
-    /// example of this is a pattern like `eeeeeeeeeeeeeeee`. Fortunately,
-    /// this case is wholly determined by the pattern, so we can actually
-    /// implement the heuristic.
-    ///
-    /// A third case is if the pattern is sufficiently long. The idea
-    /// here is that once the pattern gets long enough the Tuned
-    /// Boyer-Moore skip loop will start making strides long enough
-    /// to beat the asm deep magic that is memchr.
-    fn should_use(pattern: &[u8]) -> bool {
-        // The minimum pattern length required to use TBM.
-        const MIN_LEN: usize = 9;
-        // The minimum frequency rank (lower is rarer) that every byte in the
-        // pattern must have in order to use TBM. That is, if the pattern
-        // contains _any_ byte with a lower rank, then TBM won't be used.
-        const MIN_CUTOFF: usize = 150;
-        // The maximum frequency rank for any byte.
-        const MAX_CUTOFF: usize = 255;
-        // The scaling factor used to determine the actual cutoff frequency
-        // to use (keeping in mind that the minimum frequency rank is bounded
-        // by MIN_CUTOFF). This scaling factor is an attempt to make TBM more
-        // likely to be used as the pattern grows longer. That is, longer
-        // patterns permit somewhat less frequent bytes than shorter patterns,
-        // under the assumption that TBM gets better as the pattern gets
-        // longer.
-        const LEN_CUTOFF_PROPORTION: usize = 4;
-
-        let scaled_rank = pattern.len().wrapping_mul(LEN_CUTOFF_PROPORTION);
-        let cutoff = cmp::max(
-            MIN_CUTOFF,
-            MAX_CUTOFF - cmp::min(MAX_CUTOFF, scaled_rank),
-        );
-        // The pattern must be long enough to be worthwhile. e.g., memchr will
-        // be faster on `e` because it is short even though e is quite common.
-        pattern.len() > MIN_LEN
-            // all the bytes must be more common than the cutoff.
-            && pattern.iter().all(|c| freq_rank(*c) >= cutoff)
-    }
-
-    /// Check to see if there is a match at the given position
-    #[inline]
-    fn check_match(&self, haystack: &[u8], window_end: usize) -> bool {
-        // guard test
-        if haystack[window_end - self.guard_reverse_idx] != self.guard {
-            return false;
-        }
-
-        // match loop
-        let window_start = window_end - (self.pattern.len() - 1);
-        for i in 0..self.pattern.len() {
-            if self.pattern[i] != haystack[window_start + i] {
-                return false;
-            }
-        }
-
-        true
-    }
-
-    /// Skip forward according to the shift table.
-    ///
-    /// Returns the offset of the next occurrence
-    /// of the last char in the pattern, or the none
-    /// if it never reappears. If `skip_loop` hits the backstop
-    /// it will leave early.
-    #[inline]
-    fn skip_loop(
-        &self,
-        haystack: &[u8],
-        mut window_end: usize,
-        backstop: usize,
-    ) -> Option<usize> {
-        let window_end_snapshot = window_end;
-        let skip_of = |we: usize| -> usize {
-            // Unsafe might make this faster, but the benchmarks
-            // were hard to interpret.
-            self.skip_table[haystack[we] as usize]
-        };
-
-        loop {
-            let mut skip = skip_of(window_end);
-            window_end += skip;
-            skip = skip_of(window_end);
-            window_end += skip;
-            if skip != 0 {
-                skip = skip_of(window_end);
-                window_end += skip;
-                skip = skip_of(window_end);
-                window_end += skip;
-                skip = skip_of(window_end);
-                window_end += skip;
-                if skip != 0 {
-                    skip = skip_of(window_end);
-                    window_end += skip;
-                    skip = skip_of(window_end);
-                    window_end += skip;
-                    skip = skip_of(window_end);
-                    window_end += skip;
-                    if skip != 0 {
-                        skip = skip_of(window_end);
-                        window_end += skip;
-                        skip = skip_of(window_end);
-                        window_end += skip;
-
-                        // If ten iterations did not make at least 16 words
-                        // worth of progress, we just fall back on memchr.
-                        if window_end - window_end_snapshot
-                            > 16 * mem::size_of::<usize>()
-                        {
-                            // Returning a window_end >= backstop will
-                            // immediatly break us out of the inner loop in
-                            // `find`.
-                            if window_end >= backstop {
-                                return Some(window_end);
-                            }
-
-                            continue; // we made enough progress
-                        } else {
-                            // In case we are already there, and so that
-                            // we will catch the guard char.
-                            window_end = window_end
-                                .checked_sub(1 + self.guard_reverse_idx)
-                                .unwrap_or(0);
-
-                            match memchr(self.guard, &haystack[window_end..]) {
-                                None => return None,
-                                Some(g_idx) => {
-                                    return Some(
-                                        window_end
-                                            + g_idx
-                                            + self.guard_reverse_idx,
-                                    );
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-
-            return Some(window_end);
-        }
-    }
-
-    /// Compute the ufast skip table.
-    fn compile_skip_table(pattern: &[u8]) -> Vec<usize> {
-        let mut tab = vec![pattern.len(); 256];
-
-        // For every char in the pattern, we write a skip
-        // that will line us up with the rightmost occurrence.
-        //
-        // N.B. the sentinel (0) is written by the last
-        // loop iteration.
-        for (i, c) in pattern.iter().enumerate() {
-            tab[*c as usize] = (pattern.len() - 1) - i;
-        }
-
-        tab
-    }
-
-    /// Select the guard character based off of the precomputed
-    /// frequency table.
-    fn select_guard(pattern: &[u8]) -> (u8, usize) {
-        let mut rarest = pattern[0];
-        let mut rarest_rev_idx = pattern.len() - 1;
-        for (i, c) in pattern.iter().enumerate() {
-            if freq_rank(*c) < freq_rank(rarest) {
-                rarest = *c;
-                rarest_rev_idx = (pattern.len() - 1) - i;
-            }
-        }
-
-        (rarest, rarest_rev_idx)
-    }
-
-    /// If there is another occurrence of the skip
-    /// char, shift to it, otherwise just shift to
-    /// the next window.
-    fn compile_md2_shift(pattern: &[u8]) -> usize {
-        let shiftc = *pattern.last().unwrap();
-
-        // For a pattern of length 1 we will never apply the
-        // shift rule, so we use a poison value on the principle
-        // that failing fast is a good thing.
-        if pattern.len() == 1 {
-            return 0xDEADBEAF;
-        }
-
-        let mut i = pattern.len() - 2;
-        while i > 0 {
-            if pattern[i] == shiftc {
-                return (pattern.len() - 1) - i;
-            }
-            i -= 1;
-        }
-
-        // The skip char never re-occurs in the pattern, so
-        // we can just shift the whole window length.
-        pattern.len() - 1
-    }
-
-    fn approximate_size(&self) -> usize {
-        (self.pattern.len() * mem::size_of::<u8>())
-            + (256 * mem::size_of::<usize>()) // skip table
-    }
-}
-
-fn freq_rank(b: u8) -> usize {
-    BYTE_FREQUENCIES[b as usize] as usize
-}
-
-#[cfg(test)]
-mod tests {
-    use super::{BoyerMooreSearch, FreqyPacked};
-
-    //
-    // Unit Tests
-    //
-
-    // The "hello, world" of string searching
-    #[test]
-    fn bm_find_subs() {
-        let searcher = BoyerMooreSearch::new(Vec::from(&b"pattern"[..]));
-        let haystack = b"I keep seeing patterns in this text";
-        assert_eq!(14, searcher.find(haystack).unwrap());
-    }
-
-    #[test]
-    fn bm_find_no_subs() {
-        let searcher = BoyerMooreSearch::new(Vec::from(&b"pattern"[..]));
-        let haystack = b"I keep seeing needles in this text";
-        assert_eq!(None, searcher.find(haystack));
-    }
-
-    //
-    // Regression Tests
-    //
-
-    #[test]
-    fn bm_skip_reset_bug() {
-        let haystack = vec![0, 0, 0, 0, 0, 1, 1, 0];
-        let needle = vec![0, 1, 1, 0];
-
-        let searcher = BoyerMooreSearch::new(needle);
-        let offset = searcher.find(haystack.as_slice()).unwrap();
-        assert_eq!(4, offset);
-    }
-
-    #[test]
-    fn bm_backstop_underflow_bug() {
-        let haystack = vec![0, 0];
-        let needle = vec![0, 0];
-
-        let searcher = BoyerMooreSearch::new(needle);
-        let offset = searcher.find(haystack.as_slice()).unwrap();
-        assert_eq!(0, offset);
-    }
-
-    #[test]
-    fn bm_naive_off_by_one_bug() {
-        let haystack = vec![91];
-        let needle = vec![91];
-
-        let naive_offset = naive_find(&needle, &haystack).unwrap();
-        assert_eq!(0, naive_offset);
-    }
-
-    #[test]
-    fn bm_memchr_fallback_indexing_bug() {
-        let mut haystack = vec![
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        ];
-        let needle = vec![1, 1, 1, 1, 32, 32, 87];
-        let needle_start = haystack.len();
-        haystack.extend(needle.clone());
-
-        let searcher = BoyerMooreSearch::new(needle);
-        assert_eq!(needle_start, searcher.find(haystack.as_slice()).unwrap());
-    }
-
-    #[test]
-    fn bm_backstop_boundary() {
-        let haystack = b"\
-// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-e_data.clone_created(entity_id, entity_to_add.entity_id);
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-"
-        .to_vec();
-        let needle = b"clone_created".to_vec();
-
-        let searcher = BoyerMooreSearch::new(needle);
-        let result = searcher.find(&haystack);
-        assert_eq!(Some(43), result);
-    }
-
-    #[test]
-    fn bm_win_gnu_indexing_bug() {
-        let haystack_raw = vec![
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        ];
-        let needle = vec![1, 1, 1, 1, 1, 1, 1];
-        let haystack = haystack_raw.as_slice();
-
-        BoyerMooreSearch::new(needle.clone()).find(haystack);
-    }
-
-    //
-    // QuickCheck Properties
-    //
-
-    use quickcheck::TestResult;
-
-    fn naive_find(needle: &[u8], haystack: &[u8]) -> Option<usize> {
-        assert!(needle.len() <= haystack.len());
-
-        for i in 0..(haystack.len() - (needle.len() - 1)) {
-            if haystack[i] == needle[0]
-                && &haystack[i..(i + needle.len())] == needle
-            {
-                return Some(i);
-            }
-        }
-
-        None
-    }
-
-    quickcheck! {
-        fn qc_bm_equals_nieve_find(pile1: Vec<u8>, pile2: Vec<u8>) -> TestResult {
-            if pile1.len() == 0 || pile2.len() == 0 {
-                return TestResult::discard();
-            }
-
-            let (needle, haystack) = if pile1.len() < pile2.len() {
-                (pile1, pile2.as_slice())
-            } else {
-                (pile2, pile1.as_slice())
-            };
-
-            let searcher = BoyerMooreSearch::new(needle.clone());
-            TestResult::from_bool(
-                searcher.find(haystack) == naive_find(&needle, haystack))
-        }
-
-        fn qc_bm_equals_single(pile1: Vec<u8>, pile2: Vec<u8>) -> TestResult {
-            if pile1.len() == 0 || pile2.len() == 0 {
-                return TestResult::discard();
-            }
-
-            let (needle, haystack) = if pile1.len() < pile2.len() {
-                (pile1, pile2.as_slice())
-            } else {
-                (pile2, pile1.as_slice())
-            };
-
-            let bm_searcher = BoyerMooreSearch::new(needle.clone());
-            let freqy_memchr = FreqyPacked::new(needle);
-            TestResult::from_bool(
-                bm_searcher.find(haystack) == freqy_memchr.find(haystack))
-        }
-
-        fn qc_bm_finds_trailing_needle(
-            haystack_pre: Vec<u8>,
-            needle: Vec<u8>
-        ) -> TestResult {
-            if needle.len() == 0 {
-                return TestResult::discard();
-            }
-
-            let mut haystack = haystack_pre.clone();
-            let searcher = BoyerMooreSearch::new(needle.clone());
-
-            if haystack.len() >= needle.len() &&
-                searcher.find(haystack.as_slice()).is_some() {
-                return TestResult::discard();
-            }
-
-            haystack.extend(needle.clone());
-
-            // What if the the tail of the haystack can start the
-            // needle?
-            let start = haystack_pre.len()
-                .checked_sub(needle.len())
-                .unwrap_or(0);
-            for i in 0..(needle.len() - 1) {
-                if searcher.find(&haystack[(i + start)..]).is_some() {
-                    return TestResult::discard();
-                }
-            }
-
-            TestResult::from_bool(
-                searcher.find(haystack.as_slice())
-                        .map(|x| x == haystack_pre.len())
-                        .unwrap_or(false))
-        }
-
-        // qc_equals_* is only testing the negative case as @burntsushi
-        // pointed out in https://github.com/rust-lang/regex/issues/446.
-        // This quickcheck prop represents an effort to force testing of
-        // the positive case. qc_bm_finds_first and qc_bm_finds_trailing_needle
-        // already check some of the positive cases, but they don't cover
-        // cases where the needle is in the middle of haystack. This prop
-        // fills that hole.
-        fn qc_bm_finds_subslice(
-            haystack: Vec<u8>,
-            needle_start: usize,
-            needle_length: usize
-        ) -> TestResult {
-            if haystack.len() == 0 {
-                return TestResult::discard();
-            }
-
-            let needle_start = needle_start % haystack.len();
-            let needle_length = needle_length % (haystack.len() - needle_start);
-
-            if needle_length == 0 {
-                return TestResult::discard();
-            }
-
-            let needle = &haystack[needle_start..(needle_start + needle_length)];
-
-            let bm_searcher = BoyerMooreSearch::new(needle.to_vec());
-
-            let start = naive_find(&needle, &haystack);
-            match start {
-                None => TestResult::from_bool(false),
-                Some(nf_start) =>
-                    TestResult::from_bool(
-                        nf_start <= needle_start
-                            && bm_searcher.find(&haystack) == start
-                    )
-            }
-        }
-
-        fn qc_bm_finds_first(needle: Vec<u8>) -> TestResult {
-            if needle.len() == 0 {
-                return TestResult::discard();
-            }
-
-            let mut haystack = needle.clone();
-            let searcher = BoyerMooreSearch::new(needle.clone());
-            haystack.extend(needle);
-
-            TestResult::from_bool(
-                searcher.find(haystack.as_slice())
-                        .map(|x| x == 0)
-                        .unwrap_or(false))
-        }
-    }
-}
diff --git a/vendor/regex-1.4.3/src/literal/mod.rs b/vendor/regex-1.4.3/src/literal/mod.rs
deleted file mode 100644 (file)
index 783c63b..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-pub use self::imp::*;
-
-#[cfg(feature = "perf-literal")]
-mod imp;
-
-#[allow(missing_docs)]
-#[cfg(not(feature = "perf-literal"))]
-mod imp {
-    use syntax::hir::literal::Literals;
-
-    #[derive(Clone, Debug)]
-    pub struct LiteralSearcher(());
-
-    impl LiteralSearcher {
-        pub fn empty() -> Self {
-            LiteralSearcher(())
-        }
-
-        pub fn prefixes(_: Literals) -> Self {
-            LiteralSearcher(())
-        }
-
-        pub fn suffixes(_: Literals) -> Self {
-            LiteralSearcher(())
-        }
-
-        pub fn complete(&self) -> bool {
-            false
-        }
-
-        pub fn find(&self, _: &[u8]) -> Option<(usize, usize)> {
-            unreachable!()
-        }
-
-        pub fn find_start(&self, _: &[u8]) -> Option<(usize, usize)> {
-            unreachable!()
-        }
-
-        pub fn find_end(&self, _: &[u8]) -> Option<(usize, usize)> {
-            unreachable!()
-        }
-
-        pub fn is_empty(&self) -> bool {
-            true
-        }
-
-        pub fn len(&self) -> usize {
-            0
-        }
-
-        pub fn approximate_size(&self) -> usize {
-            0
-        }
-    }
-}
diff --git a/vendor/regex-1.4.3/src/pattern.rs b/vendor/regex-1.4.3/src/pattern.rs
deleted file mode 100644 (file)
index e942667..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-use std::str::pattern::{Pattern, SearchStep, Searcher};
-
-use re_unicode::{Matches, Regex};
-
-pub struct RegexSearcher<'r, 't> {
-    haystack: &'t str,
-    it: Matches<'r, 't>,
-    last_step_end: usize,
-    next_match: Option<(usize, usize)>,
-}
-
-impl<'r, 't> Pattern<'t> for &'r Regex {
-    type Searcher = RegexSearcher<'r, 't>;
-
-    fn into_searcher(self, haystack: &'t str) -> RegexSearcher<'r, 't> {
-        RegexSearcher {
-            haystack: haystack,
-            it: self.find_iter(haystack),
-            last_step_end: 0,
-            next_match: None,
-        }
-    }
-}
-
-unsafe impl<'r, 't> Searcher<'t> for RegexSearcher<'r, 't> {
-    #[inline]
-    fn haystack(&self) -> &'t str {
-        self.haystack
-    }
-
-    #[inline]
-    fn next(&mut self) -> SearchStep {
-        if let Some((s, e)) = self.next_match {
-            self.next_match = None;
-            self.last_step_end = e;
-            return SearchStep::Match(s, e);
-        }
-        match self.it.next() {
-            None => {
-                if self.last_step_end < self.haystack().len() {
-                    let last = self.last_step_end;
-                    self.last_step_end = self.haystack().len();
-                    SearchStep::Reject(last, self.haystack().len())
-                } else {
-                    SearchStep::Done
-                }
-            }
-            Some(m) => {
-                let (s, e) = (m.start(), m.end());
-                if s == self.last_step_end {
-                    self.last_step_end = e;
-                    SearchStep::Match(s, e)
-                } else {
-                    self.next_match = Some((s, e));
-                    let last = self.last_step_end;
-                    self.last_step_end = s;
-                    SearchStep::Reject(last, s)
-                }
-            }
-        }
-    }
-}
diff --git a/vendor/regex-1.4.3/src/pikevm.rs b/vendor/regex-1.4.3/src/pikevm.rs
deleted file mode 100644 (file)
index 299087d..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-// This module implements the Pike VM. That is, it guarantees linear time
-// search of a regex on any text with memory use proportional to the size of
-// the regex.
-//
-// It is equal in power to the backtracking engine in this crate, except the
-// backtracking engine is typically faster on small regexes/texts at the
-// expense of a bigger memory footprint.
-//
-// It can do more than the DFA can (specifically, record capture locations
-// and execute Unicode word boundary assertions), but at a slower speed.
-// Specifically, the Pike VM executes a DFA implicitly by repeatedly expanding
-// epsilon transitions. That is, the Pike VM engine can be in multiple states
-// at once where as the DFA is only ever in one state at a time.
-//
-// Therefore, the Pike VM is generally treated as the fallback when the other
-// matching engines either aren't feasible to run or are insufficient.
-
-use std::mem;
-
-use exec::ProgramCache;
-use input::{Input, InputAt};
-use prog::{InstPtr, Program};
-use re_trait::Slot;
-use sparse::SparseSet;
-
-/// An NFA simulation matching engine.
-#[derive(Debug)]
-pub struct Fsm<'r, I> {
-    /// The sequence of opcodes (among other things) that is actually executed.
-    ///
-    /// The program may be byte oriented or Unicode codepoint oriented.
-    prog: &'r Program,
-    /// An explicit stack used for following epsilon transitions. (This is
-    /// borrowed from the cache.)
-    stack: &'r mut Vec<FollowEpsilon>,
-    /// The input to search.
-    input: I,
-}
-
-/// A cached allocation that can be reused on each execution.
-#[derive(Clone, Debug)]
-pub struct Cache {
-    /// A pair of ordered sets for tracking NFA states.
-    clist: Threads,
-    nlist: Threads,
-    /// An explicit stack used for following epsilon transitions.
-    stack: Vec<FollowEpsilon>,
-}
-
-/// An ordered set of NFA states and their captures.
-#[derive(Clone, Debug)]
-struct Threads {
-    /// An ordered set of opcodes (each opcode is an NFA state).
-    set: SparseSet,
-    /// Captures for every NFA state.
-    ///
-    /// It is stored in row-major order, where the columns are the capture
-    /// slots and the rows are the states.
-    caps: Vec<Slot>,
-    /// The number of capture slots stored per thread. (Every capture has
-    /// two slots.)
-    slots_per_thread: usize,
-}
-
-/// A representation of an explicit stack frame when following epsilon
-/// transitions. This is used to avoid recursion.
-#[derive(Clone, Debug)]
-enum FollowEpsilon {
-    /// Follow transitions at the given instruction pointer.
-    IP(InstPtr),
-    /// Restore the capture slot with the given position in the input.
-    Capture { slot: usize, pos: Slot },
-}
-
-impl Cache {
-    /// Create a new allocation used by the NFA machine to record execution
-    /// and captures.
-    pub fn new(_prog: &Program) -> Self {
-        Cache { clist: Threads::new(), nlist: Threads::new(), stack: vec![] }
-    }
-}
-
-impl<'r, I: Input> Fsm<'r, I> {
-    /// Execute the NFA matching engine.
-    ///
-    /// If there's a match, `exec` returns `true` and populates the given
-    /// captures accordingly.
-    pub fn exec(
-        prog: &'r Program,
-        cache: &ProgramCache,
-        matches: &mut [bool],
-        slots: &mut [Slot],
-        quit_after_match: bool,
-        input: I,
-        start: usize,
-        end: usize,
-    ) -> bool {
-        let mut cache = cache.borrow_mut();
-        let cache = &mut cache.pikevm;
-        cache.clist.resize(prog.len(), prog.captures.len());
-        cache.nlist.resize(prog.len(), prog.captures.len());
-        let at = input.at(start);
-        Fsm { prog: prog, stack: &mut cache.stack, input: input }.exec_(
-            &mut cache.clist,
-            &mut cache.nlist,
-            matches,
-            slots,
-            quit_after_match,
-            at,
-            end,
-        )
-    }
-
-    fn exec_(
-        &mut self,
-        mut clist: &mut Threads,
-        mut nlist: &mut Threads,
-        matches: &mut [bool],
-        slots: &mut [Slot],
-        quit_after_match: bool,
-        mut at: InputAt,
-        end: usize,
-    ) -> bool {
-        let mut matched = false;
-        let mut all_matched = false;
-        clist.set.clear();
-        nlist.set.clear();
-        'LOOP: loop {
-            if clist.set.is_empty() {
-                // Three ways to bail out when our current set of threads is
-                // empty.
-                //
-                // 1. We have a match---so we're done exploring any possible
-                //    alternatives. Time to quit. (We can't do this if we're
-                //    looking for matches for multiple regexes, unless we know
-                //    they all matched.)
-                //
-                // 2. If the expression starts with a '^' we can terminate as
-                //    soon as the last thread dies.
-                if (matched && matches.len() <= 1)
-                    || all_matched
-                    || (!at.is_start() && self.prog.is_anchored_start)
-                {
-                    break;
-                }
-
-                // 3. If there's a literal prefix for the program, try to
-                //    jump ahead quickly. If it can't be found, then we can
-                //    bail out early.
-                if !self.prog.prefixes.is_empty() {
-                    at = match self.input.prefix_at(&self.prog.prefixes, at) {
-                        None => break,
-                        Some(at) => at,
-                    };
-                }
-            }
-
-            // This simulates a preceding '.*?' for every regex by adding
-            // a state starting at the current position in the input for the
-            // beginning of the program only if we don't already have a match.
-            if clist.set.is_empty()
-                || (!self.prog.is_anchored_start && !all_matched)
-            {
-                self.add(&mut clist, slots, 0, at);
-            }
-            // The previous call to "add" actually inspects the position just
-            // before the current character. For stepping through the machine,
-            // we can to look at the current character, so we advance the
-            // input.
-            let at_next = self.input.at(at.next_pos());
-            for i in 0..clist.set.len() {
-                let ip = clist.set[i];
-                if self.step(
-                    &mut nlist,
-                    matches,
-                    slots,
-                    clist.caps(ip),
-                    ip,
-                    at,
-                    at_next,
-                ) {
-                    matched = true;
-                    all_matched = all_matched || matches.iter().all(|&b| b);
-                    if quit_after_match {
-                        // If we only care if a match occurs (not its
-                        // position), then we can quit right now.
-                        break 'LOOP;
-                    }
-                    if self.prog.matches.len() == 1 {
-                        // We don't need to check the rest of the threads
-                        // in this set because we've matched something
-                        // ("leftmost-first"). However, we still need to check
-                        // threads in the next set to support things like
-                        // greedy matching.
-                        //
-                        // This is only true on normal regexes. For regex sets,
-                        // we need to mush on to observe other matches.
-                        break;
-                    }
-                }
-            }
-            if at.pos() >= end {
-                break;
-            }
-            at = at_next;
-            mem::swap(clist, nlist);
-            nlist.set.clear();
-        }
-        matched
-    }
-
-    /// Step through the input, one token (byte or codepoint) at a time.
-    ///
-    /// nlist is the set of states that will be processed on the next token
-    /// in the input.
-    ///
-    /// caps is the set of captures passed by the caller of the NFA. They are
-    /// written to only when a match state is visited.
-    ///
-    /// thread_caps is the set of captures set for the current NFA state, ip.
-    ///
-    /// at and at_next are the current and next positions in the input. at or
-    /// at_next may be EOF.
-    fn step(
-        &mut self,
-        nlist: &mut Threads,
-        matches: &mut [bool],
-        slots: &mut [Slot],
-        thread_caps: &mut [Option<usize>],
-        ip: usize,
-        at: InputAt,
-        at_next: InputAt,
-    ) -> bool {
-        use prog::Inst::*;
-        match self.prog[ip] {
-            Match(match_slot) => {
-                if match_slot < matches.len() {
-                    matches[match_slot] = true;
-                }
-                for (slot, val) in slots.iter_mut().zip(thread_caps.iter()) {
-                    *slot = *val;
-                }
-                true
-            }
-            Char(ref inst) => {
-                if inst.c == at.char() {
-                    self.add(nlist, thread_caps, inst.goto, at_next);
-                }
-                false
-            }
-            Ranges(ref inst) => {
-                if inst.matches(at.char()) {
-                    self.add(nlist, thread_caps, inst.goto, at_next);
-                }
-                false
-            }
-            Bytes(ref inst) => {
-                if let Some(b) = at.byte() {
-                    if inst.matches(b) {
-                        self.add(nlist, thread_caps, inst.goto, at_next);
-                    }
-                }
-                false
-            }
-            EmptyLook(_) | Save(_) | Split(_) => false,
-        }
-    }
-
-    /// Follows epsilon transitions and adds them for processing to nlist,
-    /// starting at and including ip.
-    fn add(
-        &mut self,
-        nlist: &mut Threads,
-        thread_caps: &mut [Option<usize>],
-        ip: usize,
-        at: InputAt,
-    ) {
-        self.stack.push(FollowEpsilon::IP(ip));
-        while let Some(frame) = self.stack.pop() {
-            match frame {
-                FollowEpsilon::IP(ip) => {
-                    self.add_step(nlist, thread_caps, ip, at);
-                }
-                FollowEpsilon::Capture { slot, pos } => {
-                    thread_caps[slot] = pos;
-                }
-            }
-        }
-    }
-
-    /// A helper function for add that avoids excessive pushing to the stack.
-    fn add_step(
-        &mut self,
-        nlist: &mut Threads,
-        thread_caps: &mut [Option<usize>],
-        mut ip: usize,
-        at: InputAt,
-    ) {
-        // Instead of pushing and popping to the stack, we mutate ip as we
-        // traverse the set of states. We only push to the stack when we
-        // absolutely need recursion (restoring captures or following a
-        // branch).
-        use prog::Inst::*;
-        loop {
-            // Don't visit states we've already added.
-            if nlist.set.contains(ip) {
-                return;
-            }
-            nlist.set.insert(ip);
-            match self.prog[ip] {
-                EmptyLook(ref inst) => {
-                    if self.input.is_empty_match(at, inst) {
-                        ip = inst.goto;
-                    }
-                }
-                Save(ref inst) => {
-                    if inst.slot < thread_caps.len() {
-                        self.stack.push(FollowEpsilon::Capture {
-                            slot: inst.slot,
-                            pos: thread_caps[inst.slot],
-                        });
-                        thread_caps[inst.slot] = Some(at.pos());
-                    }
-                    ip = inst.goto;
-                }
-                Split(ref inst) => {
-                    self.stack.push(FollowEpsilon::IP(inst.goto2));
-                    ip = inst.goto1;
-                }
-                Match(_) | Char(_) | Ranges(_) | Bytes(_) => {
-                    let t = &mut nlist.caps(ip);
-                    for (slot, val) in t.iter_mut().zip(thread_caps.iter()) {
-                        *slot = *val;
-                    }
-                    return;
-                }
-            }
-        }
-    }
-}
-
-impl Threads {
-    fn new() -> Self {
-        Threads { set: SparseSet::new(0), caps: vec![], slots_per_thread: 0 }
-    }
-
-    fn resize(&mut self, num_insts: usize, ncaps: usize) {
-        if num_insts == self.set.capacity() {
-            return;
-        }
-        self.slots_per_thread = ncaps * 2;
-        self.set = SparseSet::new(num_insts);
-        self.caps = vec![None; self.slots_per_thread * num_insts];
-    }
-
-    fn caps(&mut self, pc: usize) -> &mut [Option<usize>] {
-        let i = pc * self.slots_per_thread;
-        &mut self.caps[i..i + self.slots_per_thread]
-    }
-}
diff --git a/vendor/regex-1.4.3/src/prog.rs b/vendor/regex-1.4.3/src/prog.rs
deleted file mode 100644 (file)
index 74e5f2f..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-use std::cmp::Ordering;
-use std::collections::HashMap;
-use std::fmt;
-use std::mem;
-use std::ops::Deref;
-use std::slice;
-use std::sync::Arc;
-
-use input::Char;
-use literal::LiteralSearcher;
-
-/// `InstPtr` represents the index of an instruction in a regex program.
-pub type InstPtr = usize;
-
-/// Program is a sequence of instructions and various facts about thos
-/// instructions.
-#[derive(Clone)]
-pub struct Program {
-    /// A sequence of instructions that represents an NFA.
-    pub insts: Vec<Inst>,
-    /// Pointers to each Match instruction in the sequence.
-    ///
-    /// This is always length 1 unless this program represents a regex set.
-    pub matches: Vec<InstPtr>,
-    /// The ordered sequence of all capture groups extracted from the AST.
-    /// Unnamed groups are `None`.
-    pub captures: Vec<Option<String>>,
-    /// Pointers to all named capture groups into `captures`.
-    pub capture_name_idx: Arc<HashMap<String, usize>>,
-    /// A pointer to the start instruction. This can vary depending on how
-    /// the program was compiled. For example, programs for use with the DFA
-    /// engine have a `.*?` inserted at the beginning of unanchored regular
-    /// expressions. The actual starting point of the program is after the
-    /// `.*?`.
-    pub start: InstPtr,
-    /// A set of equivalence classes for discriminating bytes in the compiled
-    /// program.
-    pub byte_classes: Vec<u8>,
-    /// When true, this program can only match valid UTF-8.
-    pub only_utf8: bool,
-    /// When true, this program uses byte range instructions instead of Unicode
-    /// range instructions.
-    pub is_bytes: bool,
-    /// When true, the program is compiled for DFA matching. For example, this
-    /// implies `is_bytes` and also inserts a preceding `.*?` for unanchored
-    /// regexes.
-    pub is_dfa: bool,
-    /// When true, the program matches text in reverse (for use only in the
-    /// DFA).
-    pub is_reverse: bool,
-    /// Whether the regex must match from the start of the input.
-    pub is_anchored_start: bool,
-    /// Whether the regex must match at the end of the input.
-    pub is_anchored_end: bool,
-    /// Whether this program contains a Unicode word boundary instruction.
-    pub has_unicode_word_boundary: bool,
-    /// A possibly empty machine for very quickly matching prefix literals.
-    pub prefixes: LiteralSearcher,
-    /// A limit on the size of the cache that the DFA is allowed to use while
-    /// matching.
-    ///
-    /// The cache limit specifies approximately how much space we're willing to
-    /// give to the state cache. Once the state cache exceeds the size, it is
-    /// wiped and all states must be re-computed.
-    ///
-    /// Note that this value does not impact correctness. It can be set to 0
-    /// and the DFA will run just fine. (It will only ever store exactly one
-    /// state in the cache, and will likely run very slowly, but it will work.)
-    ///
-    /// Also note that this limit is *per thread of execution*. That is,
-    /// if the same regex is used to search text across multiple threads
-    /// simultaneously, then the DFA cache is not shared. Instead, copies are
-    /// made.
-    pub dfa_size_limit: usize,
-}
-
-impl Program {
-    /// Creates an empty instruction sequence. Fields are given default
-    /// values.
-    pub fn new() -> Self {
-        Program {
-            insts: vec![],
-            matches: vec![],
-            captures: vec![],
-            capture_name_idx: Arc::new(HashMap::new()),
-            start: 0,
-            byte_classes: vec![0; 256],
-            only_utf8: true,
-            is_bytes: false,
-            is_dfa: false,
-            is_reverse: false,
-            is_anchored_start: false,
-            is_anchored_end: false,
-            has_unicode_word_boundary: false,
-            prefixes: LiteralSearcher::empty(),
-            dfa_size_limit: 2 * (1 << 20),
-        }
-    }
-
-    /// If pc is an index to a no-op instruction (like Save), then return the
-    /// next pc that is not a no-op instruction.
-    pub fn skip(&self, mut pc: usize) -> usize {
-        loop {
-            match self[pc] {
-                Inst::Save(ref i) => pc = i.goto,
-                _ => return pc,
-            }
-        }
-    }
-
-    /// Return true if and only if an execution engine at instruction `pc` will
-    /// always lead to a match.
-    pub fn leads_to_match(&self, pc: usize) -> bool {
-        if self.matches.len() > 1 {
-            // If we have a regex set, then we have more than one ending
-            // state, so leading to one of those states is generally
-            // meaningless.
-            return false;
-        }
-        match self[self.skip(pc)] {
-            Inst::Match(_) => true,
-            _ => false,
-        }
-    }
-
-    /// Returns true if the current configuration demands that an implicit
-    /// `.*?` be prepended to the instruction sequence.
-    pub fn needs_dotstar(&self) -> bool {
-        self.is_dfa && !self.is_reverse && !self.is_anchored_start
-    }
-
-    /// Returns true if this program uses Byte instructions instead of
-    /// Char/Range instructions.
-    pub fn uses_bytes(&self) -> bool {
-        self.is_bytes || self.is_dfa
-    }
-
-    /// Returns true if this program exclusively matches valid UTF-8 bytes.
-    ///
-    /// That is, if an invalid UTF-8 byte is seen, then no match is possible.
-    pub fn only_utf8(&self) -> bool {
-        self.only_utf8
-    }
-
-    /// Return the approximate heap usage of this instruction sequence in
-    /// bytes.
-    pub fn approximate_size(&self) -> usize {
-        // The only instruction that uses heap space is Ranges (for
-        // Unicode codepoint programs) to store non-overlapping codepoint
-        // ranges. To keep this operation constant time, we ignore them.
-        (self.len() * mem::size_of::<Inst>())
-            + (self.matches.len() * mem::size_of::<InstPtr>())
-            + (self.captures.len() * mem::size_of::<Option<String>>())
-            + (self.capture_name_idx.len()
-                * (mem::size_of::<String>() + mem::size_of::<usize>()))
-            + (self.byte_classes.len() * mem::size_of::<u8>())
-            + self.prefixes.approximate_size()
-    }
-}
-
-impl Deref for Program {
-    type Target = [Inst];
-
-    #[cfg_attr(feature = "perf-inline", inline(always))]
-    fn deref(&self) -> &Self::Target {
-        &*self.insts
-    }
-}
-
-impl fmt::Debug for Program {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        use self::Inst::*;
-
-        fn with_goto(cur: usize, goto: usize, fmtd: String) -> String {
-            if goto == cur + 1 {
-                fmtd
-            } else {
-                format!("{} (goto: {})", fmtd, goto)
-            }
-        }
-
-        fn visible_byte(b: u8) -> String {
-            use std::ascii::escape_default;
-            let escaped = escape_default(b).collect::<Vec<u8>>();
-            String::from_utf8_lossy(&escaped).into_owned()
-        }
-
-        for (pc, inst) in self.iter().enumerate() {
-            match *inst {
-                Match(slot) => write!(f, "{:04} Match({:?})", pc, slot)?,
-                Save(ref inst) => {
-                    let s = format!("{:04} Save({})", pc, inst.slot);
-                    write!(f, "{}", with_goto(pc, inst.goto, s))?;
-                }
-                Split(ref inst) => {
-                    write!(
-                        f,
-                        "{:04} Split({}, {})",
-                        pc, inst.goto1, inst.goto2
-                    )?;
-                }
-                EmptyLook(ref inst) => {
-                    let s = format!("{:?}", inst.look);
-                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
-                }
-                Char(ref inst) => {
-                    let s = format!("{:?}", inst.c);
-                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
-                }
-                Ranges(ref inst) => {
-                    let ranges = inst
-                        .ranges
-                        .iter()
-                        .map(|r| format!("{:?}-{:?}", r.0, r.1))
-                        .collect::<Vec<String>>()
-                        .join(", ");
-                    write!(
-                        f,
-                        "{:04} {}",
-                        pc,
-                        with_goto(pc, inst.goto, ranges)
-                    )?;
-                }
-                Bytes(ref inst) => {
-                    let s = format!(
-                        "Bytes({}, {})",
-                        visible_byte(inst.start),
-                        visible_byte(inst.end)
-                    );
-                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
-                }
-            }
-            if pc == self.start {
-                write!(f, " (start)")?;
-            }
-            write!(f, "\n")?;
-        }
-        Ok(())
-    }
-}
-
-impl<'a> IntoIterator for &'a Program {
-    type Item = &'a Inst;
-    type IntoIter = slice::Iter<'a, Inst>;
-    fn into_iter(self) -> Self::IntoIter {
-        self.iter()
-    }
-}
-
-/// Inst is an instruction code in a Regex program.
-///
-/// Regrettably, a regex program either contains Unicode codepoint
-/// instructions (Char and Ranges) or it contains byte instructions (Bytes).
-/// A regex program can never contain both.
-///
-/// It would be worth investigating splitting this into two distinct types and
-/// then figuring out how to make the matching engines polymorphic over those
-/// types without sacrificing performance.
-///
-/// Other than the benefit of moving invariants into the type system, another
-/// benefit is the decreased size. If we remove the `Char` and `Ranges`
-/// instructions from the `Inst` enum, then its size shrinks from 40 bytes to
-/// 24 bytes. (This is because of the removal of a `Vec` in the `Ranges`
-/// variant.) Given that byte based machines are typically much bigger than
-/// their Unicode analogues (because they can decode UTF-8 directly), this ends
-/// up being a pretty significant savings.
-#[derive(Clone, Debug)]
-pub enum Inst {
-    /// Match indicates that the program has reached a match state.
-    ///
-    /// The number in the match corresponds to the Nth logical regular
-    /// expression in this program. This index is always 0 for normal regex
-    /// programs. Values greater than 0 appear when compiling regex sets, and
-    /// each match instruction gets its own unique value. The value corresponds
-    /// to the Nth regex in the set.
-    Match(usize),
-    /// Save causes the program to save the current location of the input in
-    /// the slot indicated by InstSave.
-    Save(InstSave),
-    /// Split causes the program to diverge to one of two paths in the
-    /// program, preferring goto1 in InstSplit.
-    Split(InstSplit),
-    /// EmptyLook represents a zero-width assertion in a regex program. A
-    /// zero-width assertion does not consume any of the input text.
-    EmptyLook(InstEmptyLook),
-    /// Char requires the regex program to match the character in InstChar at
-    /// the current position in the input.
-    Char(InstChar),
-    /// Ranges requires the regex program to match the character at the current
-    /// position in the input with one of the ranges specified in InstRanges.
-    Ranges(InstRanges),
-    /// Bytes is like Ranges, except it expresses a single byte range. It is
-    /// used in conjunction with Split instructions to implement multi-byte
-    /// character classes.
-    Bytes(InstBytes),
-}
-
-impl Inst {
-    /// Returns true if and only if this is a match instruction.
-    pub fn is_match(&self) -> bool {
-        match *self {
-            Inst::Match(_) => true,
-            _ => false,
-        }
-    }
-}
-
-/// Representation of the Save instruction.
-#[derive(Clone, Debug)]
-pub struct InstSave {
-    /// The next location to execute in the program.
-    pub goto: InstPtr,
-    /// The capture slot (there are two slots for every capture in a regex,
-    /// including the zeroth capture for the entire match).
-    pub slot: usize,
-}
-
-/// Representation of the Split instruction.
-#[derive(Clone, Debug)]
-pub struct InstSplit {
-    /// The first instruction to try. A match resulting from following goto1
-    /// has precedence over a match resulting from following goto2.
-    pub goto1: InstPtr,
-    /// The second instruction to try. A match resulting from following goto1
-    /// has precedence over a match resulting from following goto2.
-    pub goto2: InstPtr,
-}
-
-/// Representation of the `EmptyLook` instruction.
-#[derive(Clone, Debug)]
-pub struct InstEmptyLook {
-    /// The next location to execute in the program if this instruction
-    /// succeeds.
-    pub goto: InstPtr,
-    /// The type of zero-width assertion to check.
-    pub look: EmptyLook,
-}
-
-/// The set of zero-width match instructions.
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum EmptyLook {
-    /// Start of line or input.
-    StartLine,
-    /// End of line or input.
-    EndLine,
-    /// Start of input.
-    StartText,
-    /// End of input.
-    EndText,
-    /// Word character on one side and non-word character on other.
-    WordBoundary,
-    /// Word character on both sides or non-word character on both sides.
-    NotWordBoundary,
-    /// ASCII word boundary.
-    WordBoundaryAscii,
-    /// Not ASCII word boundary.
-    NotWordBoundaryAscii,
-}
-
-/// Representation of the Char instruction.
-#[derive(Clone, Debug)]
-pub struct InstChar {
-    /// The next location to execute in the program if this instruction
-    /// succeeds.
-    pub goto: InstPtr,
-    /// The character to test.
-    pub c: char,
-}
-
-/// Representation of the Ranges instruction.
-#[derive(Clone, Debug)]
-pub struct InstRanges {
-    /// The next location to execute in the program if this instruction
-    /// succeeds.
-    pub goto: InstPtr,
-    /// The set of Unicode scalar value ranges to test.
-    pub ranges: Vec<(char, char)>,
-}
-
-impl InstRanges {
-    /// Tests whether the given input character matches this instruction.
-    pub fn matches(&self, c: Char) -> bool {
-        // This speeds up the `match_class_unicode` benchmark by checking
-        // some common cases quickly without binary search. e.g., Matching
-        // a Unicode class on predominantly ASCII text.
-        for r in self.ranges.iter().take(4) {
-            if c < r.0 {
-                return false;
-            }
-            if c <= r.1 {
-                return true;
-            }
-        }
-        self.ranges
-            .binary_search_by(|r| {
-                if r.1 < c {
-                    Ordering::Less
-                } else if r.0 > c {
-                    Ordering::Greater
-                } else {
-                    Ordering::Equal
-                }
-            })
-            .is_ok()
-    }
-
-    /// Return the number of distinct characters represented by all of the
-    /// ranges.
-    pub fn num_chars(&self) -> usize {
-        self.ranges
-            .iter()
-            .map(|&(s, e)| 1 + (e as u32) - (s as u32))
-            .sum::<u32>() as usize
-    }
-}
-
-/// Representation of the Bytes instruction.
-#[derive(Clone, Debug)]
-pub struct InstBytes {
-    /// The next location to execute in the program if this instruction
-    /// succeeds.
-    pub goto: InstPtr,
-    /// The start (inclusive) of this byte range.
-    pub start: u8,
-    /// The end (inclusive) of this byte range.
-    pub end: u8,
-}
-
-impl InstBytes {
-    /// Returns true if and only if the given byte is in this range.
-    pub fn matches(&self, byte: u8) -> bool {
-        self.start <= byte && byte <= self.end
-    }
-}
diff --git a/vendor/regex-1.4.3/src/re_builder.rs b/vendor/regex-1.4.3/src/re_builder.rs
deleted file mode 100644 (file)
index fc140f8..0000000
+++ /dev/null
@@ -1,421 +0,0 @@
-/// The set of user configurable options for compiling zero or more regexes.
-#[derive(Clone, Debug)]
-#[allow(missing_docs)]
-pub struct RegexOptions {
-    pub pats: Vec<String>,
-    pub size_limit: usize,
-    pub dfa_size_limit: usize,
-    pub nest_limit: u32,
-    pub case_insensitive: bool,
-    pub multi_line: bool,
-    pub dot_matches_new_line: bool,
-    pub swap_greed: bool,
-    pub ignore_whitespace: bool,
-    pub unicode: bool,
-    pub octal: bool,
-}
-
-impl Default for RegexOptions {
-    fn default() -> Self {
-        RegexOptions {
-            pats: vec![],
-            size_limit: 10 * (1 << 20),
-            dfa_size_limit: 2 * (1 << 20),
-            nest_limit: 250,
-            case_insensitive: false,
-            multi_line: false,
-            dot_matches_new_line: false,
-            swap_greed: false,
-            ignore_whitespace: false,
-            unicode: true,
-            octal: false,
-        }
-    }
-}
-
-macro_rules! define_builder {
-    ($name:ident, $regex_mod:ident, $only_utf8:expr) => {
-        pub mod $name {
-            use super::RegexOptions;
-            use error::Error;
-            use exec::ExecBuilder;
-
-            use $regex_mod::Regex;
-
-            /// A configurable builder for a regular expression.
-            ///
-            /// A builder can be used to configure how the regex is built, for example, by
-            /// setting the default flags (which can be overridden in the expression
-            /// itself) or setting various limits.
-            #[derive(Debug)]
-            pub struct RegexBuilder(RegexOptions);
-
-            impl RegexBuilder {
-                /// Create a new regular expression builder with the given pattern.
-                ///
-                /// If the pattern is invalid, then an error will be returned when
-                /// `build` is called.
-                pub fn new(pattern: &str) -> RegexBuilder {
-                    let mut builder = RegexBuilder(RegexOptions::default());
-                    builder.0.pats.push(pattern.to_owned());
-                    builder
-                }
-
-                /// Consume the builder and compile the regular expression.
-                ///
-                /// Note that calling `as_str` on the resulting `Regex` will produce the
-                /// pattern given to `new` verbatim. Notably, it will not incorporate any
-                /// of the flags set on this builder.
-                pub fn build(&self) -> Result<Regex, Error> {
-                    ExecBuilder::new_options(self.0.clone())
-                        .only_utf8($only_utf8)
-                        .build()
-                        .map(Regex::from)
-                }
-
-                /// Set the value for the case insensitive (`i`) flag.
-                ///
-                /// When enabled, letters in the pattern will match both upper case and
-                /// lower case variants.
-                pub fn case_insensitive(
-                    &mut self,
-                    yes: bool,
-                ) -> &mut RegexBuilder {
-                    self.0.case_insensitive = yes;
-                    self
-                }
-
-                /// Set the value for the multi-line matching (`m`) flag.
-                ///
-                /// When enabled, `^` matches the beginning of lines and `$` matches the
-                /// end of lines.
-                ///
-                /// By default, they match beginning/end of the input.
-                pub fn multi_line(&mut self, yes: bool) -> &mut RegexBuilder {
-                    self.0.multi_line = yes;
-                    self
-                }
-
-                /// Set the value for the any character (`s`) flag, where in `.` matches
-                /// anything when `s` is set and matches anything except for new line when
-                /// it is not set (the default).
-                ///
-                /// N.B. "matches anything" means "any byte" when Unicode is disabled and
-                /// means "any valid UTF-8 encoding of any Unicode scalar value" when
-                /// Unicode is enabled.
-                pub fn dot_matches_new_line(
-                    &mut self,
-                    yes: bool,
-                ) -> &mut RegexBuilder {
-                    self.0.dot_matches_new_line = yes;
-                    self
-                }
-
-                /// Set the value for the greedy swap (`U`) flag.
-                ///
-                /// When enabled, a pattern like `a*` is lazy (tries to find shortest
-                /// match) and `a*?` is greedy (tries to find longest match).
-                ///
-                /// By default, `a*` is greedy and `a*?` is lazy.
-                pub fn swap_greed(&mut self, yes: bool) -> &mut RegexBuilder {
-                    self.0.swap_greed = yes;
-                    self
-                }
-
-                /// Set the value for the ignore whitespace (`x`) flag.
-                ///
-                /// When enabled, whitespace such as new lines and spaces will be ignored
-                /// between expressions of the pattern, and `#` can be used to start a
-                /// comment until the next new line.
-                pub fn ignore_whitespace(
-                    &mut self,
-                    yes: bool,
-                ) -> &mut RegexBuilder {
-                    self.0.ignore_whitespace = yes;
-                    self
-                }
-
-                /// Set the value for the Unicode (`u`) flag.
-                ///
-                /// Enabled by default. When disabled, character classes such as `\w` only
-                /// match ASCII word characters instead of all Unicode word characters.
-                pub fn unicode(&mut self, yes: bool) -> &mut RegexBuilder {
-                    self.0.unicode = yes;
-                    self
-                }
-
-                /// Whether to support octal syntax or not.
-                ///
-                /// Octal syntax is a little-known way of uttering Unicode codepoints in
-                /// a regular expression. For example, `a`, `\x61`, `\u0061` and
-                /// `\141` are all equivalent regular expressions, where the last example
-                /// shows octal syntax.
-                ///
-                /// While supporting octal syntax isn't in and of itself a problem, it does
-                /// make good error messages harder. That is, in PCRE based regex engines,
-                /// syntax like `\0` invokes a backreference, which is explicitly
-                /// unsupported in Rust's regex engine. However, many users expect it to
-                /// be supported. Therefore, when octal support is disabled, the error
-                /// message will explicitly mention that backreferences aren't supported.
-                ///
-                /// Octal syntax is disabled by default.
-                pub fn octal(&mut self, yes: bool) -> &mut RegexBuilder {
-                    self.0.octal = yes;
-                    self
-                }
-
-                /// Set the approximate size limit of the compiled regular expression.
-                ///
-                /// This roughly corresponds to the number of bytes occupied by a single
-                /// compiled program. If the program exceeds this number, then a
-                /// compilation error is returned.
-                pub fn size_limit(
-                    &mut self,
-                    limit: usize,
-                ) -> &mut RegexBuilder {
-                    self.0.size_limit = limit;
-                    self
-                }
-
-                /// Set the approximate size of the cache used by the DFA.
-                ///
-                /// This roughly corresponds to the number of bytes that the DFA will
-                /// use while searching.
-                ///
-                /// Note that this is a *per thread* limit. There is no way to set a global
-                /// limit. In particular, if a regex is used from multiple threads
-                /// simultaneously, then each thread may use up to the number of bytes
-                /// specified here.
-                pub fn dfa_size_limit(
-                    &mut self,
-                    limit: usize,
-                ) -> &mut RegexBuilder {
-                    self.0.dfa_size_limit = limit;
-                    self
-                }
-
-                /// Set the nesting limit for this parser.
-                ///
-                /// The nesting limit controls how deep the abstract syntax tree is allowed
-                /// to be. If the AST exceeds the given limit (e.g., with too many nested
-                /// groups), then an error is returned by the parser.
-                ///
-                /// The purpose of this limit is to act as a heuristic to prevent stack
-                /// overflow for consumers that do structural induction on an `Ast` using
-                /// explicit recursion. While this crate never does this (instead using
-                /// constant stack space and moving the call stack to the heap), other
-                /// crates may.
-                ///
-                /// This limit is not checked until the entire Ast is parsed. Therefore,
-                /// if callers want to put a limit on the amount of heap space used, then
-                /// they should impose a limit on the length, in bytes, of the concrete
-                /// pattern string. In particular, this is viable since this parser
-                /// implementation will limit itself to heap space proportional to the
-                /// length of the pattern string.
-                ///
-                /// Note that a nest limit of `0` will return a nest limit error for most
-                /// patterns but not all. For example, a nest limit of `0` permits `a` but
-                /// not `ab`, since `ab` requires a concatenation, which results in a nest
-                /// depth of `1`. In general, a nest limit is not something that manifests
-                /// in an obvious way in the concrete syntax, therefore, it should not be
-                /// used in a granular way.
-                pub fn nest_limit(&mut self, limit: u32) -> &mut RegexBuilder {
-                    self.0.nest_limit = limit;
-                    self
-                }
-            }
-        }
-    };
-}
-
-define_builder!(bytes, re_bytes, false);
-define_builder!(unicode, re_unicode, true);
-
-macro_rules! define_set_builder {
-    ($name:ident, $regex_mod:ident, $only_utf8:expr) => {
-        pub mod $name {
-            use super::RegexOptions;
-            use error::Error;
-            use exec::ExecBuilder;
-
-            use re_set::$regex_mod::RegexSet;
-
-            /// A configurable builder for a set of regular expressions.
-            ///
-            /// A builder can be used to configure how the regexes are built, for example,
-            /// by setting the default flags (which can be overridden in the expression
-            /// itself) or setting various limits.
-            #[derive(Debug)]
-            pub struct RegexSetBuilder(RegexOptions);
-
-            impl RegexSetBuilder {
-                /// Create a new regular expression builder with the given pattern.
-                ///
-                /// If the pattern is invalid, then an error will be returned when
-                /// `build` is called.
-                pub fn new<I, S>(patterns: I) -> RegexSetBuilder
-                where
-                    S: AsRef<str>,
-                    I: IntoIterator<Item = S>,
-                {
-                    let mut builder = RegexSetBuilder(RegexOptions::default());
-                    for pat in patterns {
-                        builder.0.pats.push(pat.as_ref().to_owned());
-                    }
-                    builder
-                }
-
-                /// Consume the builder and compile the regular expressions into a set.
-                pub fn build(&self) -> Result<RegexSet, Error> {
-                    ExecBuilder::new_options(self.0.clone())
-                        .only_utf8($only_utf8)
-                        .build()
-                        .map(RegexSet::from)
-                }
-
-                /// Set the value for the case insensitive (`i`) flag.
-                pub fn case_insensitive(
-                    &mut self,
-                    yes: bool,
-                ) -> &mut RegexSetBuilder {
-                    self.0.case_insensitive = yes;
-                    self
-                }
-
-                /// Set the value for the multi-line matching (`m`) flag.
-                pub fn multi_line(
-                    &mut self,
-                    yes: bool,
-                ) -> &mut RegexSetBuilder {
-                    self.0.multi_line = yes;
-                    self
-                }
-
-                /// Set the value for the any character (`s`) flag, where in `.` matches
-                /// anything when `s` is set and matches anything except for new line when
-                /// it is not set (the default).
-                ///
-                /// N.B. "matches anything" means "any byte" for `regex::bytes::RegexSet`
-                /// expressions and means "any Unicode scalar value" for `regex::RegexSet`
-                /// expressions.
-                pub fn dot_matches_new_line(
-                    &mut self,
-                    yes: bool,
-                ) -> &mut RegexSetBuilder {
-                    self.0.dot_matches_new_line = yes;
-                    self
-                }
-
-                /// Set the value for the greedy swap (`U`) flag.
-                pub fn swap_greed(
-                    &mut self,
-                    yes: bool,
-                ) -> &mut RegexSetBuilder {
-                    self.0.swap_greed = yes;
-                    self
-                }
-
-                /// Set the value for the ignore whitespace (`x`) flag.
-                pub fn ignore_whitespace(
-                    &mut self,
-                    yes: bool,
-                ) -> &mut RegexSetBuilder {
-                    self.0.ignore_whitespace = yes;
-                    self
-                }
-
-                /// Set the value for the Unicode (`u`) flag.
-                pub fn unicode(&mut self, yes: bool) -> &mut RegexSetBuilder {
-                    self.0.unicode = yes;
-                    self
-                }
-
-                /// Whether to support octal syntax or not.
-                ///
-                /// Octal syntax is a little-known way of uttering Unicode codepoints in
-                /// a regular expression. For example, `a`, `\x61`, `\u0061` and
-                /// `\141` are all equivalent regular expressions, where the last example
-                /// shows octal syntax.
-                ///
-                /// While supporting octal syntax isn't in and of itself a problem, it does
-                /// make good error messages harder. That is, in PCRE based regex engines,
-                /// syntax like `\0` invokes a backreference, which is explicitly
-                /// unsupported in Rust's regex engine. However, many users expect it to
-                /// be supported. Therefore, when octal support is disabled, the error
-                /// message will explicitly mention that backreferences aren't supported.
-                ///
-                /// Octal syntax is disabled by default.
-                pub fn octal(&mut self, yes: bool) -> &mut RegexSetBuilder {
-                    self.0.octal = yes;
-                    self
-                }
-
-                /// Set the approximate size limit of the compiled regular expression.
-                ///
-                /// This roughly corresponds to the number of bytes occupied by a single
-                /// compiled program. If the program exceeds this number, then a
-                /// compilation error is returned.
-                pub fn size_limit(
-                    &mut self,
-                    limit: usize,
-                ) -> &mut RegexSetBuilder {
-                    self.0.size_limit = limit;
-                    self
-                }
-
-                /// Set the approximate size of the cache used by the DFA.
-                ///
-                /// This roughly corresponds to the number of bytes that the DFA will
-                /// use while searching.
-                ///
-                /// Note that this is a *per thread* limit. There is no way to set a global
-                /// limit. In particular, if a regex is used from multiple threads
-                /// simultaneously, then each thread may use up to the number of bytes
-                /// specified here.
-                pub fn dfa_size_limit(
-                    &mut self,
-                    limit: usize,
-                ) -> &mut RegexSetBuilder {
-                    self.0.dfa_size_limit = limit;
-                    self
-                }
-
-                /// Set the nesting limit for this parser.
-                ///
-                /// The nesting limit controls how deep the abstract syntax tree is allowed
-                /// to be. If the AST exceeds the given limit (e.g., with too many nested
-                /// groups), then an error is returned by the parser.
-                ///
-                /// The purpose of this limit is to act as a heuristic to prevent stack
-                /// overflow for consumers that do structural induction on an `Ast` using
-                /// explicit recursion. While this crate never does this (instead using
-                /// constant stack space and moving the call stack to the heap), other
-                /// crates may.
-                ///
-                /// This limit is not checked until the entire Ast is parsed. Therefore,
-                /// if callers want to put a limit on the amount of heap space used, then
-                /// they should impose a limit on the length, in bytes, of the concrete
-                /// pattern string. In particular, this is viable since this parser
-                /// implementation will limit itself to heap space proportional to the
-                /// length of the pattern string.
-                ///
-                /// Note that a nest limit of `0` will return a nest limit error for most
-                /// patterns but not all. For example, a nest limit of `0` permits `a` but
-                /// not `ab`, since `ab` requires a concatenation, which results in a nest
-                /// depth of `1`. In general, a nest limit is not something that manifests
-                /// in an obvious way in the concrete syntax, therefore, it should not be
-                /// used in a granular way.
-                pub fn nest_limit(
-                    &mut self,
-                    limit: u32,
-                ) -> &mut RegexSetBuilder {
-                    self.0.nest_limit = limit;
-                    self
-                }
-            }
-        }
-    };
-}
-
-define_set_builder!(set_bytes, bytes, false);
-define_set_builder!(set_unicode, unicode, true);
diff --git a/vendor/regex-1.4.3/src/re_bytes.rs b/vendor/regex-1.4.3/src/re_bytes.rs
deleted file mode 100644 (file)
index a091436..0000000
+++ /dev/null
@@ -1,1215 +0,0 @@
-use std::borrow::Cow;
-use std::collections::HashMap;
-use std::fmt;
-use std::iter::FusedIterator;
-use std::ops::{Index, Range};
-use std::str::FromStr;
-use std::sync::Arc;
-
-use find_byte::find_byte;
-
-use error::Error;
-use exec::{Exec, ExecNoSync};
-use expand::expand_bytes;
-use re_builder::bytes::RegexBuilder;
-use re_trait::{self, RegularExpression, SubCapturesPosIter};
-
-/// Match represents a single match of a regex in a haystack.
-///
-/// The lifetime parameter `'t` refers to the lifetime of the matched text.
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub struct Match<'t> {
-    text: &'t [u8],
-    start: usize,
-    end: usize,
-}
-
-impl<'t> Match<'t> {
-    /// Returns the starting byte offset of the match in the haystack.
-    #[inline]
-    pub fn start(&self) -> usize {
-        self.start
-    }
-
-    /// Returns the ending byte offset of the match in the haystack.
-    #[inline]
-    pub fn end(&self) -> usize {
-        self.end
-    }
-
-    /// Returns the range over the starting and ending byte offsets of the
-    /// match in the haystack.
-    #[inline]
-    pub fn range(&self) -> Range<usize> {
-        self.start..self.end
-    }
-
-    /// Returns the matched text.
-    #[inline]
-    pub fn as_bytes(&self) -> &'t [u8] {
-        &self.text[self.range()]
-    }
-
-    /// Creates a new match from the given haystack and byte offsets.
-    #[inline]
-    fn new(haystack: &'t [u8], start: usize, end: usize) -> Match<'t> {
-        Match { text: haystack, start: start, end: end }
-    }
-}
-
-impl<'t> From<Match<'t>> for Range<usize> {
-    fn from(m: Match<'t>) -> Range<usize> {
-        m.range()
-    }
-}
-
-/// A compiled regular expression for matching arbitrary bytes.
-///
-/// It can be used to search, split or replace text. All searching is done with
-/// an implicit `.*?` at the beginning and end of an expression. To force an
-/// expression to match the whole string (or a prefix or a suffix), you must
-/// use an anchor like `^` or `$` (or `\A` and `\z`).
-///
-/// Like the `Regex` type in the parent module, matches with this regex return
-/// byte offsets into the search text. **Unlike** the parent `Regex` type,
-/// these byte offsets may not correspond to UTF-8 sequence boundaries since
-/// the regexes in this module can match arbitrary bytes.
-#[derive(Clone)]
-pub struct Regex(Exec);
-
-impl fmt::Display for Regex {
-    /// Shows the original regular expression.
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.as_str())
-    }
-}
-
-impl fmt::Debug for Regex {
-    /// Shows the original regular expression.
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(self, f)
-    }
-}
-
-/// A constructor for Regex from an Exec.
-///
-/// This is hidden because Exec isn't actually part of the public API.
-#[doc(hidden)]
-impl From<Exec> for Regex {
-    fn from(exec: Exec) -> Regex {
-        Regex(exec)
-    }
-}
-
-impl FromStr for Regex {
-    type Err = Error;
-
-    /// Attempts to parse a string into a regular expression
-    fn from_str(s: &str) -> Result<Regex, Error> {
-        Regex::new(s)
-    }
-}
-
-/// Core regular expression methods.
-impl Regex {
-    /// Compiles a regular expression. Once compiled, it can be used repeatedly
-    /// to search, split or replace text in a string.
-    ///
-    /// If an invalid expression is given, then an error is returned.
-    pub fn new(re: &str) -> Result<Regex, Error> {
-        RegexBuilder::new(re).build()
-    }
-
-    /// Returns true if and only if there is a match for the regex in the
-    /// string given.
-    ///
-    /// It is recommended to use this method if all you need to do is test
-    /// a match, since the underlying matching engine may be able to do less
-    /// work.
-    ///
-    /// # Example
-    ///
-    /// Test if some text contains at least one word with exactly 13 ASCII word
-    /// bytes:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::bytes::Regex;
-    /// # fn main() {
-    /// let text = b"I categorically deny having triskaidekaphobia.";
-    /// assert!(Regex::new(r"\b\w{13}\b").unwrap().is_match(text));
-    /// # }
-    /// ```
-    pub fn is_match(&self, text: &[u8]) -> bool {
-        self.is_match_at(text, 0)
-    }
-
-    /// Returns the start and end byte range of the leftmost-first match in
-    /// `text`. If no match exists, then `None` is returned.
-    ///
-    /// Note that this should only be used if you want to discover the position
-    /// of the match. Testing the existence of a match is faster if you use
-    /// `is_match`.
-    ///
-    /// # Example
-    ///
-    /// Find the start and end location of the first word with exactly 13
-    /// ASCII word bytes:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::bytes::Regex;
-    /// # fn main() {
-    /// let text = b"I categorically deny having triskaidekaphobia.";
-    /// let mat = Regex::new(r"\b\w{13}\b").unwrap().find(text).unwrap();
-    /// assert_eq!((mat.start(), mat.end()), (2, 15));
-    /// # }
-    /// ```
-    pub fn find<'t>(&self, text: &'t [u8]) -> Option<Match<'t>> {
-        self.find_at(text, 0)
-    }
-
-    /// Returns an iterator for each successive non-overlapping match in
-    /// `text`, returning the start and end byte indices with respect to
-    /// `text`.
-    ///
-    /// # Example
-    ///
-    /// Find the start and end location of every word with exactly 13 ASCII
-    /// word bytes:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::bytes::Regex;
-    /// # fn main() {
-    /// let text = b"Retroactively relinquishing remunerations is reprehensible.";
-    /// for mat in Regex::new(r"\b\w{13}\b").unwrap().find_iter(text) {
-    ///     println!("{:?}", mat);
-    /// }
-    /// # }
-    /// ```
-    pub fn find_iter<'r, 't>(&'r self, text: &'t [u8]) -> Matches<'r, 't> {
-        Matches(self.0.searcher().find_iter(text))
-    }
-
-    /// Returns the capture groups corresponding to the leftmost-first
-    /// match in `text`. Capture group `0` always corresponds to the entire
-    /// match. If no match is found, then `None` is returned.
-    ///
-    /// You should only use `captures` if you need access to the location of
-    /// capturing group matches. Otherwise, `find` is faster for discovering
-    /// the location of the overall match.
-    ///
-    /// # Examples
-    ///
-    /// Say you have some text with movie names and their release years,
-    /// like "'Citizen Kane' (1941)". It'd be nice if we could search for text
-    /// looking like that, while also extracting the movie name and its release
-    /// year separately.
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::bytes::Regex;
-    /// # fn main() {
-    /// let re = Regex::new(r"'([^']+)'\s+\((\d{4})\)").unwrap();
-    /// let text = b"Not my favorite movie: 'Citizen Kane' (1941).";
-    /// let caps = re.captures(text).unwrap();
-    /// assert_eq!(caps.get(1).unwrap().as_bytes(), &b"Citizen Kane"[..]);
-    /// assert_eq!(caps.get(2).unwrap().as_bytes(), &b"1941"[..]);
-    /// assert_eq!(caps.get(0).unwrap().as_bytes(), &b"'Citizen Kane' (1941)"[..]);
-    /// // You can also access the groups by index using the Index notation.
-    /// // Note that this will panic on an invalid index.
-    /// assert_eq!(&caps[1], b"Citizen Kane");
-    /// assert_eq!(&caps[2], b"1941");
-    /// assert_eq!(&caps[0], b"'Citizen Kane' (1941)");
-    /// # }
-    /// ```
-    ///
-    /// Note that the full match is at capture group `0`. Each subsequent
-    /// capture group is indexed by the order of its opening `(`.
-    ///
-    /// We can make this example a bit clearer by using *named* capture groups:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::bytes::Regex;
-    /// # fn main() {
-    /// let re = Regex::new(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)")
-    ///                .unwrap();
-    /// let text = b"Not my favorite movie: 'Citizen Kane' (1941).";
-    /// let caps = re.captures(text).unwrap();
-    /// assert_eq!(caps.name("title").unwrap().as_bytes(), b"Citizen Kane");
-    /// assert_eq!(caps.name("year").unwrap().as_bytes(), b"1941");
-    /// assert_eq!(caps.get(0).unwrap().as_bytes(), &b"'Citizen Kane' (1941)"[..]);
-    /// // You can also access the groups by name using the Index notation.
-    /// // Note that this will panic on an invalid group name.
-    /// assert_eq!(&caps["title"], b"Citizen Kane");
-    /// assert_eq!(&caps["year"], b"1941");
-    /// assert_eq!(&caps[0], b"'Citizen Kane' (1941)");
-    ///
-    /// # }
-    /// ```
-    ///
-    /// Here we name the capture groups, which we can access with the `name`
-    /// method or the `Index` notation with a `&str`. Note that the named
-    /// capture groups are still accessible with `get` or the `Index` notation
-    /// with a `usize`.
-    ///
-    /// The `0`th capture group is always unnamed, so it must always be
-    /// accessed with `get(0)` or `[0]`.
-    pub fn captures<'t>(&self, text: &'t [u8]) -> Option<Captures<'t>> {
-        let mut locs = self.capture_locations();
-        self.captures_read_at(&mut locs, text, 0).map(move |_| Captures {
-            text: text,
-            locs: locs.0,
-            named_groups: self.0.capture_name_idx().clone(),
-        })
-    }
-
-    /// Returns an iterator over all the non-overlapping capture groups matched
-    /// in `text`. This is operationally the same as `find_iter`, except it
-    /// yields information about capturing group matches.
-    ///
-    /// # Example
-    ///
-    /// We can use this to find all movie titles and their release years in
-    /// some text, where the movie is formatted like "'Title' (xxxx)":
-    ///
-    /// ```rust
-    /// # extern crate regex; use std::str; use regex::bytes::Regex;
-    /// # fn main() {
-    /// let re = Regex::new(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)")
-    ///                .unwrap();
-    /// let text = b"'Citizen Kane' (1941), 'The Wizard of Oz' (1939), 'M' (1931).";
-    /// for caps in re.captures_iter(text) {
-    ///     let title = str::from_utf8(&caps["title"]).unwrap();
-    ///     let year = str::from_utf8(&caps["year"]).unwrap();
-    ///     println!("Movie: {:?}, Released: {:?}", title, year);
-    /// }
-    /// // Output:
-    /// // Movie: Citizen Kane, Released: 1941
-    /// // Movie: The Wizard of Oz, Released: 1939
-    /// // Movie: M, Released: 1931
-    /// # }
-    /// ```
-    pub fn captures_iter<'r, 't>(
-        &'r self,
-        text: &'t [u8],
-    ) -> CaptureMatches<'r, 't> {
-        CaptureMatches(self.0.searcher().captures_iter(text))
-    }
-
-    /// Returns an iterator of substrings of `text` delimited by a match of the
-    /// regular expression. Namely, each element of the iterator corresponds to
-    /// text that *isn't* matched by the regular expression.
-    ///
-    /// This method will *not* copy the text given.
-    ///
-    /// # Example
-    ///
-    /// To split a string delimited by arbitrary amounts of spaces or tabs:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::bytes::Regex;
-    /// # fn main() {
-    /// let re = Regex::new(r"[ \t]+").unwrap();
-    /// let fields: Vec<&[u8]> = re.split(b"a b \t  c\td    e").collect();
-    /// assert_eq!(fields, vec![
-    ///     &b"a"[..], &b"b"[..], &b"c"[..], &b"d"[..], &b"e"[..],
-    /// ]);
-    /// # }
-    /// ```
-    pub fn split<'r, 't>(&'r self, text: &'t [u8]) -> Split<'r, 't> {
-        Split { finder: self.find_iter(text), last: 0 }
-    }
-
-    /// Returns an iterator of at most `limit` substrings of `text` delimited
-    /// by a match of the regular expression. (A `limit` of `0` will return no
-    /// substrings.) Namely, each element of the iterator corresponds to text
-    /// that *isn't* matched by the regular expression. The remainder of the
-    /// string that is not split will be the last element in the iterator.
-    ///
-    /// This method will *not* copy the text given.
-    ///
-    /// # Example
-    ///
-    /// Get the first two words in some text:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::bytes::Regex;
-    /// # fn main() {
-    /// let re = Regex::new(r"\W+").unwrap();
-    /// let fields: Vec<&[u8]> = re.splitn(b"Hey! How are you?", 3).collect();
-    /// assert_eq!(fields, vec![&b"Hey"[..], &b"How"[..], &b"are you?"[..]]);
-    /// # }
-    /// ```
-    pub fn splitn<'r, 't>(
-        &'r self,
-        text: &'t [u8],
-        limit: usize,
-    ) -> SplitN<'r, 't> {
-        SplitN { splits: self.split(text), n: limit }
-    }
-
-    /// Replaces the leftmost-first match with the replacement provided. The
-    /// replacement can be a regular byte string (where `$N` and `$name` are
-    /// expanded to match capture groups) or a function that takes the matches'
-    /// `Captures` and returns the replaced byte string.
-    ///
-    /// If no match is found, then a copy of the byte string is returned
-    /// unchanged.
-    ///
-    /// # Replacement string syntax
-    ///
-    /// All instances of `$name` in the replacement text is replaced with the
-    /// corresponding capture group `name`.
-    ///
-    /// `name` may be an integer corresponding to the index of the
-    /// capture group (counted by order of opening parenthesis where `0` is the
-    /// entire match) or it can be a name (consisting of letters, digits or
-    /// underscores) corresponding to a named capture group.
-    ///
-    /// If `name` isn't a valid capture group (whether the name doesn't exist
-    /// or isn't a valid index), then it is replaced with the empty string.
-    ///
-    /// The longest possible name is used. e.g., `$1a` looks up the capture
-    /// group named `1a` and not the capture group at index `1`. To exert more
-    /// precise control over the name, use braces, e.g., `${1}a`.
-    ///
-    /// To write a literal `$` use `$$`.
-    ///
-    /// # Examples
-    ///
-    /// Note that this function is polymorphic with respect to the replacement.
-    /// In typical usage, this can just be a normal byte string:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::bytes::Regex;
-    /// # fn main() {
-    /// let re = Regex::new("[^01]+").unwrap();
-    /// assert_eq!(re.replace(b"1078910", &b""[..]), &b"1010"[..]);
-    /// # }
-    /// ```
-    ///
-    /// But anything satisfying the `Replacer` trait will work. For example, a
-    /// closure of type `|&Captures| -> Vec<u8>` provides direct access to the
-    /// captures corresponding to a match. This allows one to access capturing
-    /// group matches easily:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::bytes::Regex;
-    /// # use regex::bytes::Captures; fn main() {
-    /// let re = Regex::new(r"([^,\s]+),\s+(\S+)").unwrap();
-    /// let result = re.replace(b"Springsteen, Bruce", |caps: &Captures| {
-    ///     let mut replacement = caps[2].to_owned();
-    ///     replacement.push(b' ');
-    ///     replacement.extend(&caps[1]);
-    ///     replacement
-    /// });
-    /// assert_eq!(result, &b"Bruce Springsteen"[..]);
-    /// # }
-    /// ```
-    ///
-    /// But this is a bit cumbersome to use all the time. Instead, a simple
-    /// syntax is supported that expands `$name` into the corresponding capture
-    /// group. Here's the last example, but using this expansion technique
-    /// with named capture groups:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::bytes::Regex;
-    /// # fn main() {
-    /// let re = Regex::new(r"(?P<last>[^,\s]+),\s+(?P<first>\S+)").unwrap();
-    /// let result = re.replace(b"Springsteen, Bruce", &b"$first $last"[..]);
-    /// assert_eq!(result, &b"Bruce Springsteen"[..]);
-    /// # }
-    /// ```
-    ///
-    /// Note that using `$2` instead of `$first` or `$1` instead of `$last`
-    /// would produce the same result. To write a literal `$` use `$$`.
-    ///
-    /// Sometimes the replacement string requires use of curly braces to
-    /// delineate a capture group replacement and surrounding literal text.
-    /// For example, if we wanted to join two words together with an
-    /// underscore:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::bytes::Regex;
-    /// # fn main() {
-    /// let re = Regex::new(r"(?P<first>\w+)\s+(?P<second>\w+)").unwrap();
-    /// let result = re.replace(b"deep fried", &b"${first}_$second"[..]);
-    /// assert_eq!(result, &b"deep_fried"[..]);
-    /// # }
-    /// ```
-    ///
-    /// Without the curly braces, the capture group name `first_` would be
-    /// used, and since it doesn't exist, it would be replaced with the empty
-    /// string.
-    ///
-    /// Finally, sometimes you just want to replace a literal string with no
-    /// regard for capturing group expansion. This can be done by wrapping a
-    /// byte string with `NoExpand`:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::bytes::Regex;
-    /// # fn main() {
-    /// use regex::bytes::NoExpand;
-    ///
-    /// let re = Regex::new(r"(?P<last>[^,\s]+),\s+(\S+)").unwrap();
-    /// let result = re.replace(b"Springsteen, Bruce", NoExpand(b"$2 $last"));
-    /// assert_eq!(result, &b"$2 $last"[..]);
-    /// # }
-    /// ```
-    pub fn replace<'t, R: Replacer>(
-        &self,
-        text: &'t [u8],
-        rep: R,
-    ) -> Cow<'t, [u8]> {
-        self.replacen(text, 1, rep)
-    }
-
-    /// Replaces all non-overlapping matches in `text` with the replacement
-    /// provided. This is the same as calling `replacen` with `limit` set to
-    /// `0`.
-    ///
-    /// See the documentation for `replace` for details on how to access
-    /// capturing group matches in the replacement text.
-    pub fn replace_all<'t, R: Replacer>(
-        &self,
-        text: &'t [u8],
-        rep: R,
-    ) -> Cow<'t, [u8]> {
-        self.replacen(text, 0, rep)
-    }
-
-    /// Replaces at most `limit` non-overlapping matches in `text` with the
-    /// replacement provided. If `limit` is 0, then all non-overlapping matches
-    /// are replaced.
-    ///
-    /// See the documentation for `replace` for details on how to access
-    /// capturing group matches in the replacement text.
-    pub fn replacen<'t, R: Replacer>(
-        &self,
-        text: &'t [u8],
-        limit: usize,
-        mut rep: R,
-    ) -> Cow<'t, [u8]> {
-        if let Some(rep) = rep.no_expansion() {
-            let mut it = self.find_iter(text).enumerate().peekable();
-            if it.peek().is_none() {
-                return Cow::Borrowed(text);
-            }
-            let mut new = Vec::with_capacity(text.len());
-            let mut last_match = 0;
-            for (i, m) in it {
-                if limit > 0 && i >= limit {
-                    break;
-                }
-                new.extend_from_slice(&text[last_match..m.start()]);
-                new.extend_from_slice(&rep);
-                last_match = m.end();
-            }
-            new.extend_from_slice(&text[last_match..]);
-            return Cow::Owned(new);
-        }
-
-        // The slower path, which we use if the replacement needs access to
-        // capture groups.
-        let mut it = self.captures_iter(text).enumerate().peekable();
-        if it.peek().is_none() {
-            return Cow::Borrowed(text);
-        }
-        let mut new = Vec::with_capacity(text.len());
-        let mut last_match = 0;
-        for (i, cap) in it {
-            if limit > 0 && i >= limit {
-                break;
-            }
-            // unwrap on 0 is OK because captures only reports matches
-            let m = cap.get(0).unwrap();
-            new.extend_from_slice(&text[last_match..m.start()]);
-            rep.replace_append(&cap, &mut new);
-            last_match = m.end();
-        }
-        new.extend_from_slice(&text[last_match..]);
-        Cow::Owned(new)
-    }
-}
-
-/// Advanced or "lower level" search methods.
-impl Regex {
-    /// Returns the end location of a match in the text given.
-    ///
-    /// This method may have the same performance characteristics as
-    /// `is_match`, except it provides an end location for a match. In
-    /// particular, the location returned *may be shorter* than the proper end
-    /// of the leftmost-first match.
-    ///
-    /// # Example
-    ///
-    /// Typically, `a+` would match the entire first sequence of `a` in some
-    /// text, but `shortest_match` can give up as soon as it sees the first
-    /// `a`.
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::bytes::Regex;
-    /// # fn main() {
-    /// let text = b"aaaaa";
-    /// let pos = Regex::new(r"a+").unwrap().shortest_match(text);
-    /// assert_eq!(pos, Some(1));
-    /// # }
-    /// ```
-    pub fn shortest_match(&self, text: &[u8]) -> Option<usize> {
-        self.shortest_match_at(text, 0)
-    }
-
-    /// Returns the same as shortest_match, but starts the search at the given
-    /// offset.
-    ///
-    /// The significance of the starting point is that it takes the surrounding
-    /// context into consideration. For example, the `\A` anchor can only
-    /// match when `start == 0`.
-    pub fn shortest_match_at(
-        &self,
-        text: &[u8],
-        start: usize,
-    ) -> Option<usize> {
-        self.0.searcher().shortest_match_at(text, start)
-    }
-
-    /// Returns the same as is_match, but starts the search at the given
-    /// offset.
-    ///
-    /// The significance of the starting point is that it takes the surrounding
-    /// context into consideration. For example, the `\A` anchor can only
-    /// match when `start == 0`.
-    pub fn is_match_at(&self, text: &[u8], start: usize) -> bool {
-        self.shortest_match_at(text, start).is_some()
-    }
-
-    /// Returns the same as find, but starts the search at the given
-    /// offset.
-    ///
-    /// The significance of the starting point is that it takes the surrounding
-    /// context into consideration. For example, the `\A` anchor can only
-    /// match when `start == 0`.
-    pub fn find_at<'t>(
-        &self,
-        text: &'t [u8],
-        start: usize,
-    ) -> Option<Match<'t>> {
-        self.0
-            .searcher()
-            .find_at(text, start)
-            .map(|(s, e)| Match::new(text, s, e))
-    }
-
-    /// This is like `captures`, but uses
-    /// [`CaptureLocations`](struct.CaptureLocations.html)
-    /// instead of
-    /// [`Captures`](struct.Captures.html) in order to amortize allocations.
-    ///
-    /// To create a `CaptureLocations` value, use the
-    /// `Regex::capture_locations` method.
-    ///
-    /// This returns the overall match if this was successful, which is always
-    /// equivalence to the `0`th capture group.
-    pub fn captures_read<'t>(
-        &self,
-        locs: &mut CaptureLocations,
-        text: &'t [u8],
-    ) -> Option<Match<'t>> {
-        self.captures_read_at(locs, text, 0)
-    }
-
-    /// Returns the same as `captures_read`, but starts the search at the given
-    /// offset and populates the capture locations given.
-    ///
-    /// The significance of the starting point is that it takes the surrounding
-    /// context into consideration. For example, the `\A` anchor can only
-    /// match when `start == 0`.
-    pub fn captures_read_at<'t>(
-        &self,
-        locs: &mut CaptureLocations,
-        text: &'t [u8],
-        start: usize,
-    ) -> Option<Match<'t>> {
-        self.0
-            .searcher()
-            .captures_read_at(&mut locs.0, text, start)
-            .map(|(s, e)| Match::new(text, s, e))
-    }
-
-    /// An undocumented alias for `captures_read_at`.
-    ///
-    /// The `regex-capi` crate previously used this routine, so to avoid
-    /// breaking that crate, we continue to provide the name as an undocumented
-    /// alias.
-    #[doc(hidden)]
-    pub fn read_captures_at<'t>(
-        &self,
-        locs: &mut CaptureLocations,
-        text: &'t [u8],
-        start: usize,
-    ) -> Option<Match<'t>> {
-        self.captures_read_at(locs, text, start)
-    }
-}
-
-/// Auxiliary methods.
-impl Regex {
-    /// Returns the original string of this regex.
-    pub fn as_str(&self) -> &str {
-        &self.0.regex_strings()[0]
-    }
-
-    /// Returns an iterator over the capture names.
-    pub fn capture_names(&self) -> CaptureNames {
-        CaptureNames(self.0.capture_names().iter())
-    }
-
-    /// Returns the number of captures.
-    pub fn captures_len(&self) -> usize {
-        self.0.capture_names().len()
-    }
-
-    /// Returns an empty set of capture locations that can be reused in
-    /// multiple calls to `captures_read` or `captures_read_at`.
-    pub fn capture_locations(&self) -> CaptureLocations {
-        CaptureLocations(self.0.searcher().locations())
-    }
-
-    /// An alias for `capture_locations` to preserve backward compatibility.
-    ///
-    /// The `regex-capi` crate uses this method, so to avoid breaking that
-    /// crate, we continue to export it as an undocumented API.
-    #[doc(hidden)]
-    pub fn locations(&self) -> CaptureLocations {
-        CaptureLocations(self.0.searcher().locations())
-    }
-}
-
-/// An iterator over all non-overlapping matches for a particular string.
-///
-/// The iterator yields a tuple of integers corresponding to the start and end
-/// of the match. The indices are byte offsets. The iterator stops when no more
-/// matches can be found.
-///
-/// `'r` is the lifetime of the compiled regular expression and `'t` is the
-/// lifetime of the matched byte string.
-#[derive(Debug)]
-pub struct Matches<'r, 't>(re_trait::Matches<'t, ExecNoSync<'r>>);
-
-impl<'r, 't> Iterator for Matches<'r, 't> {
-    type Item = Match<'t>;
-
-    fn next(&mut self) -> Option<Match<'t>> {
-        let text = self.0.text();
-        self.0.next().map(|(s, e)| Match::new(text, s, e))
-    }
-}
-
-impl<'r, 't> FusedIterator for Matches<'r, 't> {}
-
-/// An iterator that yields all non-overlapping capture groups matching a
-/// particular regular expression.
-///
-/// The iterator stops when no more matches can be found.
-///
-/// `'r` is the lifetime of the compiled regular expression and `'t` is the
-/// lifetime of the matched byte string.
-#[derive(Debug)]
-pub struct CaptureMatches<'r, 't>(
-    re_trait::CaptureMatches<'t, ExecNoSync<'r>>,
-);
-
-impl<'r, 't> Iterator for CaptureMatches<'r, 't> {
-    type Item = Captures<'t>;
-
-    fn next(&mut self) -> Option<Captures<'t>> {
-        self.0.next().map(|locs| Captures {
-            text: self.0.text(),
-            locs: locs,
-            named_groups: self.0.regex().capture_name_idx().clone(),
-        })
-    }
-}
-
-impl<'r, 't> FusedIterator for CaptureMatches<'r, 't> {}
-
-/// Yields all substrings delimited by a regular expression match.
-///
-/// `'r` is the lifetime of the compiled regular expression and `'t` is the
-/// lifetime of the byte string being split.
-#[derive(Debug)]
-pub struct Split<'r, 't> {
-    finder: Matches<'r, 't>,
-    last: usize,
-}
-
-impl<'r, 't> Iterator for Split<'r, 't> {
-    type Item = &'t [u8];
-
-    fn next(&mut self) -> Option<&'t [u8]> {
-        let text = self.finder.0.text();
-        match self.finder.next() {
-            None => {
-                if self.last > text.len() {
-                    None
-                } else {
-                    let s = &text[self.last..];
-                    self.last = text.len() + 1; // Next call will return None
-                    Some(s)
-                }
-            }
-            Some(m) => {
-                let matched = &text[self.last..m.start()];
-                self.last = m.end();
-                Some(matched)
-            }
-        }
-    }
-}
-
-impl<'r, 't> FusedIterator for Split<'r, 't> {}
-
-/// Yields at most `N` substrings delimited by a regular expression match.
-///
-/// The last substring will be whatever remains after splitting.
-///
-/// `'r` is the lifetime of the compiled regular expression and `'t` is the
-/// lifetime of the byte string being split.
-#[derive(Debug)]
-pub struct SplitN<'r, 't> {
-    splits: Split<'r, 't>,
-    n: usize,
-}
-
-impl<'r, 't> Iterator for SplitN<'r, 't> {
-    type Item = &'t [u8];
-
-    fn next(&mut self) -> Option<&'t [u8]> {
-        if self.n == 0 {
-            return None;
-        }
-
-        self.n -= 1;
-        if self.n > 0 {
-            return self.splits.next();
-        }
-
-        let text = self.splits.finder.0.text();
-        if self.splits.last > text.len() {
-            // We've already returned all substrings.
-            None
-        } else {
-            // self.n == 0, so future calls will return None immediately
-            Some(&text[self.splits.last..])
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (0, Some(self.n))
-    }
-}
-
-impl<'r, 't> FusedIterator for SplitN<'r, 't> {}
-
-/// An iterator over the names of all possible captures.
-///
-/// `None` indicates an unnamed capture; the first element (capture 0, the
-/// whole matched region) is always unnamed.
-///
-/// `'r` is the lifetime of the compiled regular expression.
-#[derive(Clone, Debug)]
-pub struct CaptureNames<'r>(::std::slice::Iter<'r, Option<String>>);
-
-impl<'r> Iterator for CaptureNames<'r> {
-    type Item = Option<&'r str>;
-
-    fn next(&mut self) -> Option<Option<&'r str>> {
-        self.0
-            .next()
-            .as_ref()
-            .map(|slot| slot.as_ref().map(|name| name.as_ref()))
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.0.size_hint()
-    }
-
-    fn count(self) -> usize {
-        self.0.count()
-    }
-}
-
-impl<'r> ExactSizeIterator for CaptureNames<'r> {}
-
-impl<'r> FusedIterator for CaptureNames<'r> {}
-
-/// CaptureLocations is a low level representation of the raw offsets of each
-/// submatch.
-///
-/// You can think of this as a lower level
-/// [`Captures`](struct.Captures.html), where this type does not support
-/// named capturing groups directly and it does not borrow the text that these
-/// offsets were matched on.
-///
-/// Primarily, this type is useful when using the lower level `Regex` APIs
-/// such as `read_captures`, which permits amortizing the allocation in which
-/// capture match locations are stored.
-///
-/// In order to build a value of this type, you'll need to call the
-/// `capture_locations` method on the `Regex` being used to execute the search.
-/// The value returned can then be reused in subsequent searches.
-#[derive(Clone, Debug)]
-pub struct CaptureLocations(re_trait::Locations);
-
-/// A type alias for `CaptureLocations` for backwards compatibility.
-///
-/// Previously, we exported `CaptureLocations` as `Locations` in an
-/// undocumented API. To prevent breaking that code (e.g., in `regex-capi`),
-/// we continue re-exporting the same undocumented API.
-#[doc(hidden)]
-pub type Locations = CaptureLocations;
-
-impl CaptureLocations {
-    /// Returns the start and end positions of the Nth capture group. Returns
-    /// `None` if `i` is not a valid capture group or if the capture group did
-    /// not match anything. The positions returned are *always* byte indices
-    /// with respect to the original string matched.
-    #[inline]
-    pub fn get(&self, i: usize) -> Option<(usize, usize)> {
-        self.0.pos(i)
-    }
-
-    /// Returns the total number of capturing groups.
-    ///
-    /// This is always at least `1` since every regex has at least `1`
-    /// capturing group that corresponds to the entire match.
-    #[inline]
-    pub fn len(&self) -> usize {
-        self.0.len()
-    }
-
-    /// An alias for the `get` method for backwards compatibility.
-    ///
-    /// Previously, we exported `get` as `pos` in an undocumented API. To
-    /// prevent breaking that code (e.g., in `regex-capi`), we continue
-    /// re-exporting the same undocumented API.
-    #[doc(hidden)]
-    #[inline]
-    pub fn pos(&self, i: usize) -> Option<(usize, usize)> {
-        self.get(i)
-    }
-}
-
-/// Captures represents a group of captured byte strings for a single match.
-///
-/// The 0th capture always corresponds to the entire match. Each subsequent
-/// index corresponds to the next capture group in the regex. If a capture
-/// group is named, then the matched byte string is *also* available via the
-/// `name` method. (Note that the 0th capture is always unnamed and so must be
-/// accessed with the `get` method.)
-///
-/// Positions returned from a capture group are always byte indices.
-///
-/// `'t` is the lifetime of the matched text.
-pub struct Captures<'t> {
-    text: &'t [u8],
-    locs: re_trait::Locations,
-    named_groups: Arc<HashMap<String, usize>>,
-}
-
-impl<'t> Captures<'t> {
-    /// Returns the match associated with the capture group at index `i`. If
-    /// `i` does not correspond to a capture group, or if the capture group
-    /// did not participate in the match, then `None` is returned.
-    ///
-    /// # Examples
-    ///
-    /// Get the text of the match with a default of an empty string if this
-    /// group didn't participate in the match:
-    ///
-    /// ```rust
-    /// # use regex::bytes::Regex;
-    /// let re = Regex::new(r"[a-z]+(?:([0-9]+)|([A-Z]+))").unwrap();
-    /// let caps = re.captures(b"abc123").unwrap();
-    ///
-    /// let text1 = caps.get(1).map_or(&b""[..], |m| m.as_bytes());
-    /// let text2 = caps.get(2).map_or(&b""[..], |m| m.as_bytes());
-    /// assert_eq!(text1, &b"123"[..]);
-    /// assert_eq!(text2, &b""[..]);
-    /// ```
-    pub fn get(&self, i: usize) -> Option<Match<'t>> {
-        self.locs.pos(i).map(|(s, e)| Match::new(self.text, s, e))
-    }
-
-    /// Returns the match for the capture group named `name`. If `name` isn't a
-    /// valid capture group or didn't match anything, then `None` is returned.
-    pub fn name(&self, name: &str) -> Option<Match<'t>> {
-        self.named_groups.get(name).and_then(|&i| self.get(i))
-    }
-
-    /// An iterator that yields all capturing matches in the order in which
-    /// they appear in the regex. If a particular capture group didn't
-    /// participate in the match, then `None` is yielded for that capture.
-    ///
-    /// The first match always corresponds to the overall match of the regex.
-    pub fn iter<'c>(&'c self) -> SubCaptureMatches<'c, 't> {
-        SubCaptureMatches { caps: self, it: self.locs.iter() }
-    }
-
-    /// Expands all instances of `$name` in `replacement` to the corresponding
-    /// capture group `name`, and writes them to the `dst` buffer given.
-    ///
-    /// `name` may be an integer corresponding to the index of the capture
-    /// group (counted by order of opening parenthesis where `0` is the
-    /// entire match) or it can be a name (consisting of letters, digits or
-    /// underscores) corresponding to a named capture group.
-    ///
-    /// If `name` isn't a valid capture group (whether the name doesn't exist
-    /// or isn't a valid index), then it is replaced with the empty string.
-    ///
-    /// The longest possible name consisting of the characters `[_0-9A-Za-z]`
-    /// is used. e.g., `$1a` looks up the capture group named `1a` and not the
-    /// capture group at index `1`. To exert more precise control over the
-    /// name, or to refer to a capture group name that uses characters outside
-    /// of `[_0-9A-Za-z]`, use braces, e.g., `${1}a` or `${foo[bar].baz}`. When
-    /// using braces, any sequence of valid UTF-8 bytes is permitted. If the
-    /// sequence does not refer to a capture group name in the corresponding
-    /// regex, then it is replaced with an empty string.
-    ///
-    /// To write a literal `$` use `$$`.
-    pub fn expand(&self, replacement: &[u8], dst: &mut Vec<u8>) {
-        expand_bytes(self, replacement, dst)
-    }
-
-    /// Returns the number of captured groups.
-    ///
-    /// This is always at least `1`, since every regex has at least one capture
-    /// group that corresponds to the full match.
-    #[inline]
-    pub fn len(&self) -> usize {
-        self.locs.len()
-    }
-}
-
-impl<'t> fmt::Debug for Captures<'t> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_tuple("Captures").field(&CapturesDebug(self)).finish()
-    }
-}
-
-struct CapturesDebug<'c, 't: 'c>(&'c Captures<'t>);
-
-impl<'c, 't> fmt::Debug for CapturesDebug<'c, 't> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fn escape_bytes(bytes: &[u8]) -> String {
-            let mut s = String::new();
-            for &b in bytes {
-                s.push_str(&escape_byte(b));
-            }
-            s
-        }
-
-        fn escape_byte(byte: u8) -> String {
-            use std::ascii::escape_default;
-
-            let escaped: Vec<u8> = escape_default(byte).collect();
-            String::from_utf8_lossy(&escaped).into_owned()
-        }
-
-        // We'd like to show something nice here, even if it means an
-        // allocation to build a reverse index.
-        let slot_to_name: HashMap<&usize, &String> =
-            self.0.named_groups.iter().map(|(a, b)| (b, a)).collect();
-        let mut map = f.debug_map();
-        for (slot, m) in self.0.locs.iter().enumerate() {
-            let m = m.map(|(s, e)| escape_bytes(&self.0.text[s..e]));
-            if let Some(name) = slot_to_name.get(&slot) {
-                map.entry(&name, &m);
-            } else {
-                map.entry(&slot, &m);
-            }
-        }
-        map.finish()
-    }
-}
-
-/// Get a group by index.
-///
-/// `'t` is the lifetime of the matched text.
-///
-/// The text can't outlive the `Captures` object if this method is
-/// used, because of how `Index` is defined (normally `a[i]` is part
-/// of `a` and can't outlive it); to do that, use `get()` instead.
-///
-/// # Panics
-///
-/// If there is no group at the given index.
-impl<'t> Index<usize> for Captures<'t> {
-    type Output = [u8];
-
-    fn index(&self, i: usize) -> &[u8] {
-        self.get(i)
-            .map(|m| m.as_bytes())
-            .unwrap_or_else(|| panic!("no group at index '{}'", i))
-    }
-}
-
-/// Get a group by name.
-///
-/// `'t` is the lifetime of the matched text and `'i` is the lifetime
-/// of the group name (the index).
-///
-/// The text can't outlive the `Captures` object if this method is
-/// used, because of how `Index` is defined (normally `a[i]` is part
-/// of `a` and can't outlive it); to do that, use `name` instead.
-///
-/// # Panics
-///
-/// If there is no group named by the given value.
-impl<'t, 'i> Index<&'i str> for Captures<'t> {
-    type Output = [u8];
-
-    fn index<'a>(&'a self, name: &'i str) -> &'a [u8] {
-        self.name(name)
-            .map(|m| m.as_bytes())
-            .unwrap_or_else(|| panic!("no group named '{}'", name))
-    }
-}
-
-/// An iterator that yields all capturing matches in the order in which they
-/// appear in the regex.
-///
-/// If a particular capture group didn't participate in the match, then `None`
-/// is yielded for that capture. The first match always corresponds to the
-/// overall match of the regex.
-///
-/// The lifetime `'c` corresponds to the lifetime of the `Captures` value, and
-/// the lifetime `'t` corresponds to the originally matched text.
-#[derive(Clone, Debug)]
-pub struct SubCaptureMatches<'c, 't: 'c> {
-    caps: &'c Captures<'t>,
-    it: SubCapturesPosIter<'c>,
-}
-
-impl<'c, 't> Iterator for SubCaptureMatches<'c, 't> {
-    type Item = Option<Match<'t>>;
-
-    fn next(&mut self) -> Option<Option<Match<'t>>> {
-        self.it
-            .next()
-            .map(|cap| cap.map(|(s, e)| Match::new(self.caps.text, s, e)))
-    }
-}
-
-impl<'c, 't> FusedIterator for SubCaptureMatches<'c, 't> {}
-
-/// Replacer describes types that can be used to replace matches in a byte
-/// string.
-///
-/// In general, users of this crate shouldn't need to implement this trait,
-/// since implementations are already provided for `&[u8]` and
-/// `FnMut(&Captures) -> Vec<u8>` (or any `FnMut(&Captures) -> T`
-/// where `T: AsRef<[u8]>`), which covers most use cases.
-pub trait Replacer {
-    /// Appends text to `dst` to replace the current match.
-    ///
-    /// The current match is represented by `caps`, which is guaranteed to
-    /// have a match at capture group `0`.
-    ///
-    /// For example, a no-op replacement would be
-    /// `dst.extend(&caps[0])`.
-    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>);
-
-    /// Return a fixed unchanging replacement byte string.
-    ///
-    /// When doing replacements, if access to `Captures` is not needed (e.g.,
-    /// the replacement byte string does not need `$` expansion), then it can
-    /// be beneficial to avoid finding sub-captures.
-    ///
-    /// In general, this is called once for every call to `replacen`.
-    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
-        None
-    }
-
-    /// Return a `Replacer` that borrows and wraps this `Replacer`.
-    ///
-    /// This is useful when you want to take a generic `Replacer` (which might
-    /// not be cloneable) and use it without consuming it, so it can be used
-    /// more than once.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use regex::bytes::{Regex, Replacer};
-    ///
-    /// fn replace_all_twice<R: Replacer>(
-    ///     re: Regex,
-    ///     src: &[u8],
-    ///     mut rep: R,
-    /// ) -> Vec<u8> {
-    ///     let dst = re.replace_all(src, rep.by_ref());
-    ///     let dst = re.replace_all(&dst, rep.by_ref());
-    ///     dst.into_owned()
-    /// }
-    /// ```
-    fn by_ref<'r>(&'r mut self) -> ReplacerRef<'r, Self> {
-        ReplacerRef(self)
-    }
-}
-
-/// By-reference adaptor for a `Replacer`
-///
-/// Returned by [`Replacer::by_ref`](trait.Replacer.html#method.by_ref).
-#[derive(Debug)]
-pub struct ReplacerRef<'a, R: ?Sized + 'a>(&'a mut R);
-
-impl<'a, R: Replacer + ?Sized + 'a> Replacer for ReplacerRef<'a, R> {
-    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
-        self.0.replace_append(caps, dst)
-    }
-    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
-        self.0.no_expansion()
-    }
-}
-
-impl<'a> Replacer for &'a [u8] {
-    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
-        caps.expand(*self, dst);
-    }
-
-    fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
-        match find_byte(b'$', *self) {
-            Some(_) => None,
-            None => Some(Cow::Borrowed(*self)),
-        }
-    }
-}
-
-impl<F, T> Replacer for F
-where
-    F: FnMut(&Captures) -> T,
-    T: AsRef<[u8]>,
-{
-    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
-        dst.extend_from_slice((*self)(caps).as_ref());
-    }
-}
-
-/// `NoExpand` indicates literal byte string replacement.
-///
-/// It can be used with `replace` and `replace_all` to do a literal byte string
-/// replacement without expanding `$name` to their corresponding capture
-/// groups. This can be both convenient (to avoid escaping `$`, for example)
-/// and performant (since capture groups don't need to be found).
-///
-/// `'t` is the lifetime of the literal text.
-#[derive(Clone, Debug)]
-pub struct NoExpand<'t>(pub &'t [u8]);
-
-impl<'t> Replacer for NoExpand<'t> {
-    fn replace_append(&mut self, _: &Captures, dst: &mut Vec<u8>) {
-        dst.extend_from_slice(self.0);
-    }
-
-    fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
-        Some(Cow::Borrowed(self.0))
-    }
-}
diff --git a/vendor/regex-1.4.3/src/re_set.rs b/vendor/regex-1.4.3/src/re_set.rs
deleted file mode 100644 (file)
index 0a00229..0000000
+++ /dev/null
@@ -1,475 +0,0 @@
-macro_rules! define_set {
-    ($name:ident, $builder_mod:ident, $text_ty:ty, $as_bytes:expr,
-     $(#[$doc_regexset_example:meta])* ) => {
-        pub mod $name {
-            use std::fmt;
-            use std::iter;
-            use std::slice;
-            use std::vec;
-
-            use error::Error;
-            use exec::Exec;
-            use re_builder::$builder_mod::RegexSetBuilder;
-            use re_trait::RegularExpression;
-
-/// Match multiple (possibly overlapping) regular expressions in a single scan.
-///
-/// A regex set corresponds to the union of two or more regular expressions.
-/// That is, a regex set will match text where at least one of its
-/// constituent regular expressions matches. A regex set as its formulated here
-/// provides a touch more power: it will also report *which* regular
-/// expressions in the set match. Indeed, this is the key difference between
-/// regex sets and a single `Regex` with many alternates, since only one
-/// alternate can match at a time.
-///
-/// For example, consider regular expressions to match email addresses and
-/// domains: `[a-z]+@[a-z]+\.(com|org|net)` and `[a-z]+\.(com|org|net)`. If a
-/// regex set is constructed from those regexes, then searching the text
-/// `foo@example.com` will report both regexes as matching. Of course, one
-/// could accomplish this by compiling each regex on its own and doing two
-/// searches over the text. The key advantage of using a regex set is that it
-/// will report the matching regexes using a *single pass through the text*.
-/// If one has hundreds or thousands of regexes to match repeatedly (like a URL
-/// router for a complex web application or a user agent matcher), then a regex
-/// set can realize huge performance gains.
-///
-/// # Example
-///
-/// This shows how the above two regexes (for matching email addresses and
-/// domains) might work:
-///
-$(#[$doc_regexset_example])*
-///
-/// Note that it would be possible to adapt the above example to using `Regex`
-/// with an expression like:
-///
-/// ```ignore
-/// (?P<email>[a-z]+@(?P<email_domain>[a-z]+[.](com|org|net)))|(?P<domain>[a-z]+[.](com|org|net))
-/// ```
-///
-/// After a match, one could then inspect the capture groups to figure out
-/// which alternates matched. The problem is that it is hard to make this
-/// approach scale when there are many regexes since the overlap between each
-/// alternate isn't always obvious to reason about.
-///
-/// # Limitations
-///
-/// Regex sets are limited to answering the following two questions:
-///
-/// 1. Does any regex in the set match?
-/// 2. If so, which regexes in the set match?
-///
-/// As with the main `Regex` type, it is cheaper to ask (1) instead of (2)
-/// since the matching engines can stop after the first match is found.
-///
-/// Other features like finding the location of successive matches or their
-/// sub-captures aren't supported. If you need this functionality, the
-/// recommended approach is to compile each regex in the set independently and
-/// selectively match them based on which regexes in the set matched.
-///
-/// # Performance
-///
-/// A `RegexSet` has the same performance characteristics as `Regex`. Namely,
-/// search takes `O(mn)` time, where `m` is proportional to the size of the
-/// regex set and `n` is proportional to the length of the search text.
-#[derive(Clone)]
-pub struct RegexSet(Exec);
-
-impl RegexSet {
-    /// Create a new regex set with the given regular expressions.
-    ///
-    /// This takes an iterator of `S`, where `S` is something that can produce
-    /// a `&str`. If any of the strings in the iterator are not valid regular
-    /// expressions, then an error is returned.
-    ///
-    /// # Example
-    ///
-    /// Create a new regex set from an iterator of strings:
-    ///
-    /// ```rust
-    /// # use regex::RegexSet;
-    /// let set = RegexSet::new(&[r"\w+", r"\d+"]).unwrap();
-    /// assert!(set.is_match("foo"));
-    /// ```
-    pub fn new<I, S>(exprs: I) -> Result<RegexSet, Error>
-            where S: AsRef<str>, I: IntoIterator<Item=S> {
-        RegexSetBuilder::new(exprs).build()
-    }
-
-    /// Create a new empty regex set.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// # use regex::RegexSet;
-    /// let set = RegexSet::empty();
-    /// assert!(set.is_empty());
-    /// ```
-    pub fn empty() -> RegexSet {
-        RegexSetBuilder::new(&[""; 0]).build().unwrap()
-    }
-
-    /// Returns true if and only if one of the regexes in this set matches
-    /// the text given.
-    ///
-    /// This method should be preferred if you only need to test whether any
-    /// of the regexes in the set should match, but don't care about *which*
-    /// regexes matched. This is because the underlying matching engine will
-    /// quit immediately after seeing the first match instead of continuing to
-    /// find all matches.
-    ///
-    /// Note that as with searches using `Regex`, the expression is unanchored
-    /// by default. That is, if the regex does not start with `^` or `\A`, or
-    /// end with `$` or `\z`, then it is permitted to match anywhere in the
-    /// text.
-    ///
-    /// # Example
-    ///
-    /// Tests whether a set matches some text:
-    ///
-    /// ```rust
-    /// # use regex::RegexSet;
-    /// let set = RegexSet::new(&[r"\w+", r"\d+"]).unwrap();
-    /// assert!(set.is_match("foo"));
-    /// assert!(!set.is_match("☃"));
-    /// ```
-    pub fn is_match(&self, text: $text_ty) -> bool {
-        self.is_match_at(text, 0)
-    }
-
-    /// Returns the same as is_match, but starts the search at the given
-    /// offset.
-    ///
-    /// The significance of the starting point is that it takes the surrounding
-    /// context into consideration. For example, the `\A` anchor can only
-    /// match when `start == 0`.
-    #[doc(hidden)]
-    pub fn is_match_at(&self, text: $text_ty, start: usize) -> bool {
-        self.0.searcher().is_match_at($as_bytes(text), start)
-    }
-
-    /// Returns the set of regular expressions that match in the given text.
-    ///
-    /// The set returned contains the index of each regular expression that
-    /// matches in the given text. The index is in correspondence with the
-    /// order of regular expressions given to `RegexSet`'s constructor.
-    ///
-    /// The set can also be used to iterate over the matched indices.
-    ///
-    /// Note that as with searches using `Regex`, the expression is unanchored
-    /// by default. That is, if the regex does not start with `^` or `\A`, or
-    /// end with `$` or `\z`, then it is permitted to match anywhere in the
-    /// text.
-    ///
-    /// # Example
-    ///
-    /// Tests which regular expressions match the given text:
-    ///
-    /// ```rust
-    /// # use regex::RegexSet;
-    /// let set = RegexSet::new(&[
-    ///     r"\w+",
-    ///     r"\d+",
-    ///     r"\pL+",
-    ///     r"foo",
-    ///     r"bar",
-    ///     r"barfoo",
-    ///     r"foobar",
-    /// ]).unwrap();
-    /// let matches: Vec<_> = set.matches("foobar").into_iter().collect();
-    /// assert_eq!(matches, vec![0, 2, 3, 4, 6]);
-    ///
-    /// // You can also test whether a particular regex matched:
-    /// let matches = set.matches("foobar");
-    /// assert!(!matches.matched(5));
-    /// assert!(matches.matched(6));
-    /// ```
-    pub fn matches(&self, text: $text_ty) -> SetMatches {
-        let mut matches = vec![false; self.0.regex_strings().len()];
-        let any = self.read_matches_at(&mut matches, text, 0);
-        SetMatches {
-            matched_any: any,
-            matches: matches,
-        }
-    }
-
-    /// Returns the same as matches, but starts the search at the given
-    /// offset and stores the matches into the slice given.
-    ///
-    /// The significance of the starting point is that it takes the surrounding
-    /// context into consideration. For example, the `\A` anchor can only
-    /// match when `start == 0`.
-    ///
-    /// `matches` must have a length that is at least the number of regexes
-    /// in this set.
-    ///
-    /// This method returns true if and only if at least one member of
-    /// `matches` is true after executing the set against `text`.
-    #[doc(hidden)]
-    pub fn read_matches_at(
-        &self,
-        matches: &mut [bool],
-        text: $text_ty,
-        start: usize,
-    ) -> bool {
-        self.0.searcher().many_matches_at(matches, $as_bytes(text), start)
-    }
-
-    /// Returns the total number of regular expressions in this set.
-    pub fn len(&self) -> usize {
-        self.0.regex_strings().len()
-    }
-
-    /// Returns `true` if this set contains no regular expressions.
-    pub fn is_empty(&self) -> bool {
-        self.0.regex_strings().is_empty()
-    }
-
-    /// Returns the patterns that this set will match on.
-    ///
-    /// This function can be used to determine the pattern for a match. The
-    /// slice returned has exactly as many patterns givens to this regex set,
-    /// and the order of the slice is the same as the order of the patterns
-    /// provided to the set.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// # use regex::RegexSet;
-    /// let set = RegexSet::new(&[
-    ///     r"\w+",
-    ///     r"\d+",
-    ///     r"\pL+",
-    ///     r"foo",
-    ///     r"bar",
-    ///     r"barfoo",
-    ///     r"foobar",
-    /// ]).unwrap();
-    /// let matches: Vec<_> = set
-    ///     .matches("foobar")
-    ///     .into_iter()
-    ///     .map(|match_idx| &set.patterns()[match_idx])
-    ///     .collect();
-    /// assert_eq!(matches, vec![r"\w+", r"\pL+", r"foo", r"bar", r"foobar"]);
-    /// ```
-    pub fn patterns(&self) -> &[String] {
-        self.0.regex_strings()
-    }
-}
-
-/// A set of matches returned by a regex set.
-#[derive(Clone, Debug)]
-pub struct SetMatches {
-    matched_any: bool,
-    matches: Vec<bool>,
-}
-
-impl SetMatches {
-    /// Whether this set contains any matches.
-    pub fn matched_any(&self) -> bool {
-        self.matched_any
-    }
-
-    /// Whether the regex at the given index matched.
-    ///
-    /// The index for a regex is determined by its insertion order upon the
-    /// initial construction of a `RegexSet`, starting at `0`.
-    ///
-    /// # Panics
-    ///
-    /// If `regex_index` is greater than or equal to `self.len()`.
-    pub fn matched(&self, regex_index: usize) -> bool {
-        self.matches[regex_index]
-    }
-
-    /// The total number of regexes in the set that created these matches.
-    pub fn len(&self) -> usize {
-        self.matches.len()
-    }
-
-    /// Returns an iterator over indexes in the regex that matched.
-    ///
-    /// This will always produces matches in ascending order of index, where
-    /// the index corresponds to the index of the regex that matched with
-    /// respect to its position when initially building the set.
-    pub fn iter(&self) -> SetMatchesIter {
-        SetMatchesIter((&*self.matches).into_iter().enumerate())
-    }
-}
-
-impl IntoIterator for SetMatches {
-    type IntoIter = SetMatchesIntoIter;
-    type Item = usize;
-
-    fn into_iter(self) -> Self::IntoIter {
-        SetMatchesIntoIter(self.matches.into_iter().enumerate())
-    }
-}
-
-impl<'a> IntoIterator for &'a SetMatches {
-    type IntoIter = SetMatchesIter<'a>;
-    type Item = usize;
-
-    fn into_iter(self) -> Self::IntoIter {
-        self.iter()
-    }
-}
-
-/// An owned iterator over the set of matches from a regex set.
-///
-/// This will always produces matches in ascending order of index, where the
-/// index corresponds to the index of the regex that matched with respect to
-/// its position when initially building the set.
-#[derive(Debug)]
-pub struct SetMatchesIntoIter(iter::Enumerate<vec::IntoIter<bool>>);
-
-impl Iterator for SetMatchesIntoIter {
-    type Item = usize;
-
-    fn next(&mut self) -> Option<usize> {
-        loop {
-            match self.0.next() {
-                None => return None,
-                Some((_, false)) => {}
-                Some((i, true)) => return Some(i),
-            }
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.0.size_hint()
-    }
-}
-
-impl DoubleEndedIterator for SetMatchesIntoIter {
-    fn next_back(&mut self) -> Option<usize> {
-        loop {
-            match self.0.next_back() {
-                None => return None,
-                Some((_, false)) => {}
-                Some((i, true)) => return Some(i),
-            }
-        }
-    }
-}
-
-impl iter::FusedIterator for SetMatchesIntoIter {}
-
-/// A borrowed iterator over the set of matches from a regex set.
-///
-/// The lifetime `'a` refers to the lifetime of a `SetMatches` value.
-///
-/// This will always produces matches in ascending order of index, where the
-/// index corresponds to the index of the regex that matched with respect to
-/// its position when initially building the set.
-#[derive(Clone, Debug)]
-pub struct SetMatchesIter<'a>(iter::Enumerate<slice::Iter<'a, bool>>);
-
-impl<'a> Iterator for SetMatchesIter<'a> {
-    type Item = usize;
-
-    fn next(&mut self) -> Option<usize> {
-        loop {
-            match self.0.next() {
-                None => return None,
-                Some((_, &false)) => {}
-                Some((i, &true)) => return Some(i),
-            }
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.0.size_hint()
-    }
-}
-
-impl<'a> DoubleEndedIterator for SetMatchesIter<'a> {
-    fn next_back(&mut self) -> Option<usize> {
-        loop {
-            match self.0.next_back() {
-                None => return None,
-                Some((_, &false)) => {}
-                Some((i, &true)) => return Some(i),
-            }
-        }
-    }
-}
-
-impl<'a> iter::FusedIterator for SetMatchesIter<'a> {}
-
-#[doc(hidden)]
-impl From<Exec> for RegexSet {
-    fn from(exec: Exec) -> Self {
-        RegexSet(exec)
-    }
-}
-
-impl fmt::Debug for RegexSet {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "RegexSet({:?})", self.0.regex_strings())
-    }
-}
-
-#[allow(dead_code)] fn as_bytes_str(text: &str) -> &[u8] { text.as_bytes() }
-#[allow(dead_code)] fn as_bytes_bytes(text: &[u8]) -> &[u8] { text }
-        }
-    }
-}
-
-define_set! {
-    unicode,
-    set_unicode,
-    &str,
-    as_bytes_str,
-/// ```rust
-/// # use regex::RegexSet;
-/// let set = RegexSet::new(&[
-///     r"[a-z]+@[a-z]+\.(com|org|net)",
-///     r"[a-z]+\.(com|org|net)",
-/// ]).unwrap();
-///
-/// // Ask whether any regexes in the set match.
-/// assert!(set.is_match("foo@example.com"));
-///
-/// // Identify which regexes in the set match.
-/// let matches: Vec<_> = set.matches("foo@example.com").into_iter().collect();
-/// assert_eq!(vec![0, 1], matches);
-///
-/// // Try again, but with text that only matches one of the regexes.
-/// let matches: Vec<_> = set.matches("example.com").into_iter().collect();
-/// assert_eq!(vec![1], matches);
-///
-/// // Try again, but with text that doesn't match any regex in the set.
-/// let matches: Vec<_> = set.matches("example").into_iter().collect();
-/// assert!(matches.is_empty());
-/// ```
-}
-
-define_set! {
-    bytes,
-    set_bytes,
-    &[u8],
-    as_bytes_bytes,
-/// ```rust
-/// # use regex::bytes::RegexSet;
-/// let set = RegexSet::new(&[
-///     r"[a-z]+@[a-z]+\.(com|org|net)",
-///     r"[a-z]+\.(com|org|net)",
-/// ]).unwrap();
-///
-/// // Ask whether any regexes in the set match.
-/// assert!(set.is_match(b"foo@example.com"));
-///
-/// // Identify which regexes in the set match.
-/// let matches: Vec<_> = set.matches(b"foo@example.com").into_iter().collect();
-/// assert_eq!(vec![0, 1], matches);
-///
-/// // Try again, but with text that only matches one of the regexes.
-/// let matches: Vec<_> = set.matches(b"example.com").into_iter().collect();
-/// assert_eq!(vec![1], matches);
-///
-/// // Try again, but with text that doesn't match any regex in the set.
-/// let matches: Vec<_> = set.matches(b"example").into_iter().collect();
-/// assert!(matches.is_empty());
-/// ```
-}
diff --git a/vendor/regex-1.4.3/src/re_trait.rs b/vendor/regex-1.4.3/src/re_trait.rs
deleted file mode 100644 (file)
index ea6be9c..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-use std::fmt;
-use std::iter::FusedIterator;
-
-/// Slot is a single saved capture location. Note that there are two slots for
-/// every capture in a regular expression (one slot each for the start and end
-/// of the capture).
-pub type Slot = Option<usize>;
-
-/// Locations represents the offsets of each capturing group in a regex for
-/// a single match.
-///
-/// Unlike `Captures`, a `Locations` value only stores offsets.
-#[doc(hidden)]
-#[derive(Clone, Debug)]
-pub struct Locations(Vec<Slot>);
-
-impl Locations {
-    /// Returns the start and end positions of the Nth capture group. Returns
-    /// `None` if `i` is not a valid capture group or if the capture group did
-    /// not match anything. The positions returned are *always* byte indices
-    /// with respect to the original string matched.
-    pub fn pos(&self, i: usize) -> Option<(usize, usize)> {
-        let (s, e) = (i * 2, i * 2 + 1);
-        match (self.0.get(s), self.0.get(e)) {
-            (Some(&Some(s)), Some(&Some(e))) => Some((s, e)),
-            _ => None,
-        }
-    }
-
-    /// Creates an iterator of all the capture group positions in order of
-    /// appearance in the regular expression. Positions are byte indices
-    /// in terms of the original string matched.
-    pub fn iter(&self) -> SubCapturesPosIter {
-        SubCapturesPosIter { idx: 0, locs: self }
-    }
-
-    /// Returns the total number of capturing groups.
-    ///
-    /// This is always at least `1` since every regex has at least `1`
-    /// capturing group that corresponds to the entire match.
-    pub fn len(&self) -> usize {
-        self.0.len() / 2
-    }
-
-    /// Return the individual slots as a slice.
-    pub(crate) fn as_slots(&mut self) -> &mut [Slot] {
-        &mut self.0
-    }
-}
-
-/// An iterator over capture group positions for a particular match of a
-/// regular expression.
-///
-/// Positions are byte indices in terms of the original string matched.
-///
-/// `'c` is the lifetime of the captures.
-#[derive(Clone, Debug)]
-pub struct SubCapturesPosIter<'c> {
-    idx: usize,
-    locs: &'c Locations,
-}
-
-impl<'c> Iterator for SubCapturesPosIter<'c> {
-    type Item = Option<(usize, usize)>;
-
-    fn next(&mut self) -> Option<Option<(usize, usize)>> {
-        if self.idx >= self.locs.len() {
-            return None;
-        }
-        let x = match self.locs.pos(self.idx) {
-            None => Some(None),
-            Some((s, e)) => Some(Some((s, e))),
-        };
-        self.idx += 1;
-        x
-    }
-}
-
-impl<'c> FusedIterator for SubCapturesPosIter<'c> {}
-
-/// `RegularExpression` describes types that can implement regex searching.
-///
-/// This trait is my attempt at reducing code duplication and to standardize
-/// the internal API. Specific duplication that is avoided are the `find`
-/// and `capture` iterators, which are slightly tricky.
-///
-/// It's not clear whether this trait is worth it, and it also isn't
-/// clear whether it's useful as a public trait or not. Methods like
-/// `next_after_empty` reak of bad design, but the rest of the methods seem
-/// somewhat reasonable. One particular thing this trait would expose would be
-/// the ability to start the search of a regex anywhere in a haystack, which
-/// isn't possible in the current public API.
-pub trait RegularExpression: Sized + fmt::Debug {
-    /// The type of the haystack.
-    type Text: ?Sized + fmt::Debug;
-
-    /// The number of capture slots in the compiled regular expression. This is
-    /// always two times the number of capture groups (two slots per group).
-    fn slots_len(&self) -> usize;
-
-    /// Allocates fresh space for all capturing groups in this regex.
-    fn locations(&self) -> Locations {
-        Locations(vec![None; self.slots_len()])
-    }
-
-    /// Returns the position of the next character after `i`.
-    ///
-    /// For example, a haystack with type `&[u8]` probably returns `i+1`,
-    /// whereas a haystack with type `&str` probably returns `i` plus the
-    /// length of the next UTF-8 sequence.
-    fn next_after_empty(&self, text: &Self::Text, i: usize) -> usize;
-
-    /// Returns the location of the shortest match.
-    fn shortest_match_at(
-        &self,
-        text: &Self::Text,
-        start: usize,
-    ) -> Option<usize>;
-
-    /// Returns whether the regex matches the text given.
-    fn is_match_at(&self, text: &Self::Text, start: usize) -> bool;
-
-    /// Returns the leftmost-first match location if one exists.
-    fn find_at(
-        &self,
-        text: &Self::Text,
-        start: usize,
-    ) -> Option<(usize, usize)>;
-
-    /// Returns the leftmost-first match location if one exists, and also
-    /// fills in any matching capture slot locations.
-    fn captures_read_at(
-        &self,
-        locs: &mut Locations,
-        text: &Self::Text,
-        start: usize,
-    ) -> Option<(usize, usize)>;
-
-    /// Returns an iterator over all non-overlapping successive leftmost-first
-    /// matches.
-    fn find_iter(self, text: &Self::Text) -> Matches<Self> {
-        Matches { re: self, text: text, last_end: 0, last_match: None }
-    }
-
-    /// Returns an iterator over all non-overlapping successive leftmost-first
-    /// matches with captures.
-    fn captures_iter(self, text: &Self::Text) -> CaptureMatches<Self> {
-        CaptureMatches(self.find_iter(text))
-    }
-}
-
-/// An iterator over all non-overlapping successive leftmost-first matches.
-#[derive(Debug)]
-pub struct Matches<'t, R>
-where
-    R: RegularExpression,
-    R::Text: 't,
-{
-    re: R,
-    text: &'t R::Text,
-    last_end: usize,
-    last_match: Option<usize>,
-}
-
-impl<'t, R> Matches<'t, R>
-where
-    R: RegularExpression,
-    R::Text: 't,
-{
-    /// Return the text being searched.
-    pub fn text(&self) -> &'t R::Text {
-        self.text
-    }
-
-    /// Return the underlying regex.
-    pub fn regex(&self) -> &R {
-        &self.re
-    }
-}
-
-impl<'t, R> Iterator for Matches<'t, R>
-where
-    R: RegularExpression,
-    R::Text: 't + AsRef<[u8]>,
-{
-    type Item = (usize, usize);
-
-    fn next(&mut self) -> Option<(usize, usize)> {
-        if self.last_end > self.text.as_ref().len() {
-            return None;
-        }
-        let (s, e) = match self.re.find_at(self.text, self.last_end) {
-            None => return None,
-            Some((s, e)) => (s, e),
-        };
-        if s == e {
-            // This is an empty match. To ensure we make progress, start
-            // the next search at the smallest possible starting position
-            // of the next match following this one.
-            self.last_end = self.re.next_after_empty(self.text, e);
-            // Don't accept empty matches immediately following a match.
-            // Just move on to the next match.
-            if Some(e) == self.last_match {
-                return self.next();
-            }
-        } else {
-            self.last_end = e;
-        }
-        self.last_match = Some(e);
-        Some((s, e))
-    }
-}
-
-impl<'t, R> FusedIterator for Matches<'t, R>
-where
-    R: RegularExpression,
-    R::Text: 't + AsRef<[u8]>,
-{
-}
-
-/// An iterator over all non-overlapping successive leftmost-first matches with
-/// captures.
-#[derive(Debug)]
-pub struct CaptureMatches<'t, R>(Matches<'t, R>)
-where
-    R: RegularExpression,
-    R::Text: 't;
-
-impl<'t, R> CaptureMatches<'t, R>
-where
-    R: RegularExpression,
-    R::Text: 't,
-{
-    /// Return the text being searched.
-    pub fn text(&self) -> &'t R::Text {
-        self.0.text()
-    }
-
-    /// Return the underlying regex.
-    pub fn regex(&self) -> &R {
-        self.0.regex()
-    }
-}
-
-impl<'t, R> Iterator for CaptureMatches<'t, R>
-where
-    R: RegularExpression,
-    R::Text: 't + AsRef<[u8]>,
-{
-    type Item = Locations;
-
-    fn next(&mut self) -> Option<Locations> {
-        if self.0.last_end > self.0.text.as_ref().len() {
-            return None;
-        }
-        let mut locs = self.0.re.locations();
-        let (s, e) = match self.0.re.captures_read_at(
-            &mut locs,
-            self.0.text,
-            self.0.last_end,
-        ) {
-            None => return None,
-            Some((s, e)) => (s, e),
-        };
-        if s == e {
-            self.0.last_end = self.0.re.next_after_empty(self.0.text, e);
-            if Some(e) == self.0.last_match {
-                return self.next();
-            }
-        } else {
-            self.0.last_end = e;
-        }
-        self.0.last_match = Some(e);
-        Some(locs)
-    }
-}
-
-impl<'t, R> FusedIterator for CaptureMatches<'t, R>
-where
-    R: RegularExpression,
-    R::Text: 't + AsRef<[u8]>,
-{
-}
diff --git a/vendor/regex-1.4.3/src/re_unicode.rs b/vendor/regex-1.4.3/src/re_unicode.rs
deleted file mode 100644 (file)
index df87c34..0000000
+++ /dev/null
@@ -1,1257 +0,0 @@
-use std::borrow::Cow;
-use std::collections::HashMap;
-use std::fmt;
-use std::iter::FusedIterator;
-use std::ops::{Index, Range};
-use std::str::FromStr;
-use std::sync::Arc;
-
-use find_byte::find_byte;
-use syntax;
-
-use error::Error;
-use exec::{Exec, ExecNoSyncStr};
-use expand::expand_str;
-use re_builder::unicode::RegexBuilder;
-use re_trait::{self, RegularExpression, SubCapturesPosIter};
-
-/// Escapes all regular expression meta characters in `text`.
-///
-/// The string returned may be safely used as a literal in a regular
-/// expression.
-pub fn escape(text: &str) -> String {
-    syntax::escape(text)
-}
-
-/// Match represents a single match of a regex in a haystack.
-///
-/// The lifetime parameter `'t` refers to the lifetime of the matched text.
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub struct Match<'t> {
-    text: &'t str,
-    start: usize,
-    end: usize,
-}
-
-impl<'t> Match<'t> {
-    /// Returns the starting byte offset of the match in the haystack.
-    #[inline]
-    pub fn start(&self) -> usize {
-        self.start
-    }
-
-    /// Returns the ending byte offset of the match in the haystack.
-    #[inline]
-    pub fn end(&self) -> usize {
-        self.end
-    }
-
-    /// Returns the range over the starting and ending byte offsets of the
-    /// match in the haystack.
-    #[inline]
-    pub fn range(&self) -> Range<usize> {
-        self.start..self.end
-    }
-
-    /// Returns the matched text.
-    #[inline]
-    pub fn as_str(&self) -> &'t str {
-        &self.text[self.range()]
-    }
-
-    /// Creates a new match from the given haystack and byte offsets.
-    #[inline]
-    fn new(haystack: &'t str, start: usize, end: usize) -> Match<'t> {
-        Match { text: haystack, start: start, end: end }
-    }
-}
-
-impl<'t> From<Match<'t>> for &'t str {
-    fn from(m: Match<'t>) -> &'t str {
-        m.as_str()
-    }
-}
-
-impl<'t> From<Match<'t>> for Range<usize> {
-    fn from(m: Match<'t>) -> Range<usize> {
-        m.range()
-    }
-}
-
-/// A compiled regular expression for matching Unicode strings.
-///
-/// It is represented as either a sequence of bytecode instructions (dynamic)
-/// or as a specialized Rust function (native). It can be used to search, split
-/// or replace text. All searching is done with an implicit `.*?` at the
-/// beginning and end of an expression. To force an expression to match the
-/// whole string (or a prefix or a suffix), you must use an anchor like `^` or
-/// `$` (or `\A` and `\z`).
-///
-/// While this crate will handle Unicode strings (whether in the regular
-/// expression or in the search text), all positions returned are **byte
-/// indices**. Every byte index is guaranteed to be at a Unicode code point
-/// boundary.
-///
-/// The lifetimes `'r` and `'t` in this crate correspond to the lifetime of a
-/// compiled regular expression and text to search, respectively.
-///
-/// The only methods that allocate new strings are the string replacement
-/// methods. All other methods (searching and splitting) return borrowed
-/// pointers into the string given.
-///
-/// # Examples
-///
-/// Find the location of a US phone number:
-///
-/// ```rust
-/// # use regex::Regex;
-/// let re = Regex::new("[0-9]{3}-[0-9]{3}-[0-9]{4}").unwrap();
-/// let mat = re.find("phone: 111-222-3333").unwrap();
-/// assert_eq!((mat.start(), mat.end()), (7, 19));
-/// ```
-///
-/// # Using the `std::str::pattern` methods with `Regex`
-///
-/// > **Note**: This section requires that this crate is compiled with the
-/// > `pattern` Cargo feature enabled, which **requires nightly Rust**.
-///
-/// Since `Regex` implements `Pattern`, you can use regexes with methods
-/// defined on `&str`. For example, `is_match`, `find`, `find_iter`
-/// and `split` can be replaced with `str::contains`, `str::find`,
-/// `str::match_indices` and `str::split`.
-///
-/// Here are some examples:
-///
-/// ```rust,ignore
-/// # use regex::Regex;
-/// let re = Regex::new(r"\d+").unwrap();
-/// let haystack = "a111b222c";
-///
-/// assert!(haystack.contains(&re));
-/// assert_eq!(haystack.find(&re), Some(1));
-/// assert_eq!(haystack.match_indices(&re).collect::<Vec<_>>(),
-///            vec![(1, 4), (5, 8)]);
-/// assert_eq!(haystack.split(&re).collect::<Vec<_>>(), vec!["a", "b", "c"]);
-/// ```
-#[derive(Clone)]
-pub struct Regex(Exec);
-
-impl fmt::Display for Regex {
-    /// Shows the original regular expression.
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.as_str())
-    }
-}
-
-impl fmt::Debug for Regex {
-    /// Shows the original regular expression.
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(self, f)
-    }
-}
-
-#[doc(hidden)]
-impl From<Exec> for Regex {
-    fn from(exec: Exec) -> Regex {
-        Regex(exec)
-    }
-}
-
-impl FromStr for Regex {
-    type Err = Error;
-
-    /// Attempts to parse a string into a regular expression
-    fn from_str(s: &str) -> Result<Regex, Error> {
-        Regex::new(s)
-    }
-}
-
-/// Core regular expression methods.
-impl Regex {
-    /// Compiles a regular expression. Once compiled, it can be used repeatedly
-    /// to search, split or replace text in a string.
-    ///
-    /// If an invalid expression is given, then an error is returned.
-    pub fn new(re: &str) -> Result<Regex, Error> {
-        RegexBuilder::new(re).build()
-    }
-
-    /// Returns true if and only if there is a match for the regex in the
-    /// string given.
-    ///
-    /// It is recommended to use this method if all you need to do is test
-    /// a match, since the underlying matching engine may be able to do less
-    /// work.
-    ///
-    /// # Example
-    ///
-    /// Test if some text contains at least one word with exactly 13
-    /// Unicode word characters:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::Regex;
-    /// # fn main() {
-    /// let text = "I categorically deny having triskaidekaphobia.";
-    /// assert!(Regex::new(r"\b\w{13}\b").unwrap().is_match(text));
-    /// # }
-    /// ```
-    pub fn is_match(&self, text: &str) -> bool {
-        self.is_match_at(text, 0)
-    }
-
-    /// Returns the start and end byte range of the leftmost-first match in
-    /// `text`. If no match exists, then `None` is returned.
-    ///
-    /// Note that this should only be used if you want to discover the position
-    /// of the match. Testing the existence of a match is faster if you use
-    /// `is_match`.
-    ///
-    /// # Example
-    ///
-    /// Find the start and end location of the first word with exactly 13
-    /// Unicode word characters:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::Regex;
-    /// # fn main() {
-    /// let text = "I categorically deny having triskaidekaphobia.";
-    /// let mat = Regex::new(r"\b\w{13}\b").unwrap().find(text).unwrap();
-    /// assert_eq!(mat.start(), 2);
-    /// assert_eq!(mat.end(), 15);
-    /// # }
-    /// ```
-    pub fn find<'t>(&self, text: &'t str) -> Option<Match<'t>> {
-        self.find_at(text, 0)
-    }
-
-    /// Returns an iterator for each successive non-overlapping match in
-    /// `text`, returning the start and end byte indices with respect to
-    /// `text`.
-    ///
-    /// # Example
-    ///
-    /// Find the start and end location of every word with exactly 13 Unicode
-    /// word characters:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::Regex;
-    /// # fn main() {
-    /// let text = "Retroactively relinquishing remunerations is reprehensible.";
-    /// for mat in Regex::new(r"\b\w{13}\b").unwrap().find_iter(text) {
-    ///     println!("{:?}", mat);
-    /// }
-    /// # }
-    /// ```
-    pub fn find_iter<'r, 't>(&'r self, text: &'t str) -> Matches<'r, 't> {
-        Matches(self.0.searcher_str().find_iter(text))
-    }
-
-    /// Returns the capture groups corresponding to the leftmost-first
-    /// match in `text`. Capture group `0` always corresponds to the entire
-    /// match. If no match is found, then `None` is returned.
-    ///
-    /// You should only use `captures` if you need access to the location of
-    /// capturing group matches. Otherwise, `find` is faster for discovering
-    /// the location of the overall match.
-    ///
-    /// # Examples
-    ///
-    /// Say you have some text with movie names and their release years,
-    /// like "'Citizen Kane' (1941)". It'd be nice if we could search for text
-    /// looking like that, while also extracting the movie name and its release
-    /// year separately.
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::Regex;
-    /// # fn main() {
-    /// let re = Regex::new(r"'([^']+)'\s+\((\d{4})\)").unwrap();
-    /// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
-    /// let caps = re.captures(text).unwrap();
-    /// assert_eq!(caps.get(1).unwrap().as_str(), "Citizen Kane");
-    /// assert_eq!(caps.get(2).unwrap().as_str(), "1941");
-    /// assert_eq!(caps.get(0).unwrap().as_str(), "'Citizen Kane' (1941)");
-    /// // You can also access the groups by index using the Index notation.
-    /// // Note that this will panic on an invalid index.
-    /// assert_eq!(&caps[1], "Citizen Kane");
-    /// assert_eq!(&caps[2], "1941");
-    /// assert_eq!(&caps[0], "'Citizen Kane' (1941)");
-    /// # }
-    /// ```
-    ///
-    /// Note that the full match is at capture group `0`. Each subsequent
-    /// capture group is indexed by the order of its opening `(`.
-    ///
-    /// We can make this example a bit clearer by using *named* capture groups:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::Regex;
-    /// # fn main() {
-    /// let re = Regex::new(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)")
-    ///                .unwrap();
-    /// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
-    /// let caps = re.captures(text).unwrap();
-    /// assert_eq!(caps.name("title").unwrap().as_str(), "Citizen Kane");
-    /// assert_eq!(caps.name("year").unwrap().as_str(), "1941");
-    /// assert_eq!(caps.get(0).unwrap().as_str(), "'Citizen Kane' (1941)");
-    /// // You can also access the groups by name using the Index notation.
-    /// // Note that this will panic on an invalid group name.
-    /// assert_eq!(&caps["title"], "Citizen Kane");
-    /// assert_eq!(&caps["year"], "1941");
-    /// assert_eq!(&caps[0], "'Citizen Kane' (1941)");
-    ///
-    /// # }
-    /// ```
-    ///
-    /// Here we name the capture groups, which we can access with the `name`
-    /// method or the `Index` notation with a `&str`. Note that the named
-    /// capture groups are still accessible with `get` or the `Index` notation
-    /// with a `usize`.
-    ///
-    /// The `0`th capture group is always unnamed, so it must always be
-    /// accessed with `get(0)` or `[0]`.
-    pub fn captures<'t>(&self, text: &'t str) -> Option<Captures<'t>> {
-        let mut locs = self.capture_locations();
-        self.captures_read_at(&mut locs, text, 0).map(move |_| Captures {
-            text: text,
-            locs: locs.0,
-            named_groups: self.0.capture_name_idx().clone(),
-        })
-    }
-
-    /// Returns an iterator over all the non-overlapping capture groups matched
-    /// in `text`. This is operationally the same as `find_iter`, except it
-    /// yields information about capturing group matches.
-    ///
-    /// # Example
-    ///
-    /// We can use this to find all movie titles and their release years in
-    /// some text, where the movie is formatted like "'Title' (xxxx)":
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::Regex;
-    /// # fn main() {
-    /// let re = Regex::new(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)")
-    ///                .unwrap();
-    /// let text = "'Citizen Kane' (1941), 'The Wizard of Oz' (1939), 'M' (1931).";
-    /// for caps in re.captures_iter(text) {
-    ///     println!("Movie: {:?}, Released: {:?}",
-    ///              &caps["title"], &caps["year"]);
-    /// }
-    /// // Output:
-    /// // Movie: Citizen Kane, Released: 1941
-    /// // Movie: The Wizard of Oz, Released: 1939
-    /// // Movie: M, Released: 1931
-    /// # }
-    /// ```
-    pub fn captures_iter<'r, 't>(
-        &'r self,
-        text: &'t str,
-    ) -> CaptureMatches<'r, 't> {
-        CaptureMatches(self.0.searcher_str().captures_iter(text))
-    }
-
-    /// Returns an iterator of substrings of `text` delimited by a match of the
-    /// regular expression. Namely, each element of the iterator corresponds to
-    /// text that *isn't* matched by the regular expression.
-    ///
-    /// This method will *not* copy the text given.
-    ///
-    /// # Example
-    ///
-    /// To split a string delimited by arbitrary amounts of spaces or tabs:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::Regex;
-    /// # fn main() {
-    /// let re = Regex::new(r"[ \t]+").unwrap();
-    /// let fields: Vec<&str> = re.split("a b \t  c\td    e").collect();
-    /// assert_eq!(fields, vec!["a", "b", "c", "d", "e"]);
-    /// # }
-    /// ```
-    pub fn split<'r, 't>(&'r self, text: &'t str) -> Split<'r, 't> {
-        Split { finder: self.find_iter(text), last: 0 }
-    }
-
-    /// Returns an iterator of at most `limit` substrings of `text` delimited
-    /// by a match of the regular expression. (A `limit` of `0` will return no
-    /// substrings.) Namely, each element of the iterator corresponds to text
-    /// that *isn't* matched by the regular expression. The remainder of the
-    /// string that is not split will be the last element in the iterator.
-    ///
-    /// This method will *not* copy the text given.
-    ///
-    /// # Example
-    ///
-    /// Get the first two words in some text:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::Regex;
-    /// # fn main() {
-    /// let re = Regex::new(r"\W+").unwrap();
-    /// let fields: Vec<&str> = re.splitn("Hey! How are you?", 3).collect();
-    /// assert_eq!(fields, vec!("Hey", "How", "are you?"));
-    /// # }
-    /// ```
-    pub fn splitn<'r, 't>(
-        &'r self,
-        text: &'t str,
-        limit: usize,
-    ) -> SplitN<'r, 't> {
-        SplitN { splits: self.split(text), n: limit }
-    }
-
-    /// Replaces the leftmost-first match with the replacement provided.
-    /// The replacement can be a regular string (where `$N` and `$name` are
-    /// expanded to match capture groups) or a function that takes the matches'
-    /// `Captures` and returns the replaced string.
-    ///
-    /// If no match is found, then a copy of the string is returned unchanged.
-    ///
-    /// # Replacement string syntax
-    ///
-    /// All instances of `$name` in the replacement text is replaced with the
-    /// corresponding capture group `name`.
-    ///
-    /// `name` may be an integer corresponding to the index of the
-    /// capture group (counted by order of opening parenthesis where `0` is the
-    /// entire match) or it can be a name (consisting of letters, digits or
-    /// underscores) corresponding to a named capture group.
-    ///
-    /// If `name` isn't a valid capture group (whether the name doesn't exist
-    /// or isn't a valid index), then it is replaced with the empty string.
-    ///
-    /// The longest possible name is used. e.g., `$1a` looks up the capture
-    /// group named `1a` and not the capture group at index `1`. To exert more
-    /// precise control over the name, use braces, e.g., `${1}a`.
-    ///
-    /// To write a literal `$` use `$$`.
-    ///
-    /// # Examples
-    ///
-    /// Note that this function is polymorphic with respect to the replacement.
-    /// In typical usage, this can just be a normal string:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::Regex;
-    /// # fn main() {
-    /// let re = Regex::new("[^01]+").unwrap();
-    /// assert_eq!(re.replace("1078910", ""), "1010");
-    /// # }
-    /// ```
-    ///
-    /// But anything satisfying the `Replacer` trait will work. For example,
-    /// a closure of type `|&Captures| -> String` provides direct access to the
-    /// captures corresponding to a match. This allows one to access
-    /// capturing group matches easily:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::Regex;
-    /// # use regex::Captures; fn main() {
-    /// let re = Regex::new(r"([^,\s]+),\s+(\S+)").unwrap();
-    /// let result = re.replace("Springsteen, Bruce", |caps: &Captures| {
-    ///     format!("{} {}", &caps[2], &caps[1])
-    /// });
-    /// assert_eq!(result, "Bruce Springsteen");
-    /// # }
-    /// ```
-    ///
-    /// But this is a bit cumbersome to use all the time. Instead, a simple
-    /// syntax is supported that expands `$name` into the corresponding capture
-    /// group. Here's the last example, but using this expansion technique
-    /// with named capture groups:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::Regex;
-    /// # fn main() {
-    /// let re = Regex::new(r"(?P<last>[^,\s]+),\s+(?P<first>\S+)").unwrap();
-    /// let result = re.replace("Springsteen, Bruce", "$first $last");
-    /// assert_eq!(result, "Bruce Springsteen");
-    /// # }
-    /// ```
-    ///
-    /// Note that using `$2` instead of `$first` or `$1` instead of `$last`
-    /// would produce the same result. To write a literal `$` use `$$`.
-    ///
-    /// Sometimes the replacement string requires use of curly braces to
-    /// delineate a capture group replacement and surrounding literal text.
-    /// For example, if we wanted to join two words together with an
-    /// underscore:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::Regex;
-    /// # fn main() {
-    /// let re = Regex::new(r"(?P<first>\w+)\s+(?P<second>\w+)").unwrap();
-    /// let result = re.replace("deep fried", "${first}_$second");
-    /// assert_eq!(result, "deep_fried");
-    /// # }
-    /// ```
-    ///
-    /// Without the curly braces, the capture group name `first_` would be
-    /// used, and since it doesn't exist, it would be replaced with the empty
-    /// string.
-    ///
-    /// Finally, sometimes you just want to replace a literal string with no
-    /// regard for capturing group expansion. This can be done by wrapping a
-    /// byte string with `NoExpand`:
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::Regex;
-    /// # fn main() {
-    /// use regex::NoExpand;
-    ///
-    /// let re = Regex::new(r"(?P<last>[^,\s]+),\s+(\S+)").unwrap();
-    /// let result = re.replace("Springsteen, Bruce", NoExpand("$2 $last"));
-    /// assert_eq!(result, "$2 $last");
-    /// # }
-    /// ```
-    pub fn replace<'t, R: Replacer>(
-        &self,
-        text: &'t str,
-        rep: R,
-    ) -> Cow<'t, str> {
-        self.replacen(text, 1, rep)
-    }
-
-    /// Replaces all non-overlapping matches in `text` with the replacement
-    /// provided. This is the same as calling `replacen` with `limit` set to
-    /// `0`.
-    ///
-    /// See the documentation for `replace` for details on how to access
-    /// capturing group matches in the replacement string.
-    pub fn replace_all<'t, R: Replacer>(
-        &self,
-        text: &'t str,
-        rep: R,
-    ) -> Cow<'t, str> {
-        self.replacen(text, 0, rep)
-    }
-
-    /// Replaces at most `limit` non-overlapping matches in `text` with the
-    /// replacement provided. If `limit` is 0, then all non-overlapping matches
-    /// are replaced.
-    ///
-    /// See the documentation for `replace` for details on how to access
-    /// capturing group matches in the replacement string.
-    pub fn replacen<'t, R: Replacer>(
-        &self,
-        text: &'t str,
-        limit: usize,
-        mut rep: R,
-    ) -> Cow<'t, str> {
-        // If we know that the replacement doesn't have any capture expansions,
-        // then we can fast path. The fast path can make a tremendous
-        // difference:
-        //
-        //   1) We use `find_iter` instead of `captures_iter`. Not asking for
-        //      captures generally makes the regex engines faster.
-        //   2) We don't need to look up all of the capture groups and do
-        //      replacements inside the replacement string. We just push it
-        //      at each match and be done with it.
-        if let Some(rep) = rep.no_expansion() {
-            let mut it = self.find_iter(text).enumerate().peekable();
-            if it.peek().is_none() {
-                return Cow::Borrowed(text);
-            }
-            let mut new = String::with_capacity(text.len());
-            let mut last_match = 0;
-            for (i, m) in it {
-                if limit > 0 && i >= limit {
-                    break;
-                }
-                new.push_str(&text[last_match..m.start()]);
-                new.push_str(&rep);
-                last_match = m.end();
-            }
-            new.push_str(&text[last_match..]);
-            return Cow::Owned(new);
-        }
-
-        // The slower path, which we use if the replacement needs access to
-        // capture groups.
-        let mut it = self.captures_iter(text).enumerate().peekable();
-        if it.peek().is_none() {
-            return Cow::Borrowed(text);
-        }
-        let mut new = String::with_capacity(text.len());
-        let mut last_match = 0;
-        for (i, cap) in it {
-            if limit > 0 && i >= limit {
-                break;
-            }
-            // unwrap on 0 is OK because captures only reports matches
-            let m = cap.get(0).unwrap();
-            new.push_str(&text[last_match..m.start()]);
-            rep.replace_append(&cap, &mut new);
-            last_match = m.end();
-        }
-        new.push_str(&text[last_match..]);
-        Cow::Owned(new)
-    }
-}
-
-/// Advanced or "lower level" search methods.
-impl Regex {
-    /// Returns the end location of a match in the text given.
-    ///
-    /// This method may have the same performance characteristics as
-    /// `is_match`, except it provides an end location for a match. In
-    /// particular, the location returned *may be shorter* than the proper end
-    /// of the leftmost-first match.
-    ///
-    /// # Example
-    ///
-    /// Typically, `a+` would match the entire first sequence of `a` in some
-    /// text, but `shortest_match` can give up as soon as it sees the first
-    /// `a`.
-    ///
-    /// ```rust
-    /// # extern crate regex; use regex::Regex;
-    /// # fn main() {
-    /// let text = "aaaaa";
-    /// let pos = Regex::new(r"a+").unwrap().shortest_match(text);
-    /// assert_eq!(pos, Some(1));
-    /// # }
-    /// ```
-    pub fn shortest_match(&self, text: &str) -> Option<usize> {
-        self.shortest_match_at(text, 0)
-    }
-
-    /// Returns the same as shortest_match, but starts the search at the given
-    /// offset.
-    ///
-    /// The significance of the starting point is that it takes the surrounding
-    /// context into consideration. For example, the `\A` anchor can only
-    /// match when `start == 0`.
-    pub fn shortest_match_at(
-        &self,
-        text: &str,
-        start: usize,
-    ) -> Option<usize> {
-        self.0.searcher_str().shortest_match_at(text, start)
-    }
-
-    /// Returns the same as is_match, but starts the search at the given
-    /// offset.
-    ///
-    /// The significance of the starting point is that it takes the surrounding
-    /// context into consideration. For example, the `\A` anchor can only
-    /// match when `start == 0`.
-    pub fn is_match_at(&self, text: &str, start: usize) -> bool {
-        self.shortest_match_at(text, start).is_some()
-    }
-
-    /// Returns the same as find, but starts the search at the given
-    /// offset.
-    ///
-    /// The significance of the starting point is that it takes the surrounding
-    /// context into consideration. For example, the `\A` anchor can only
-    /// match when `start == 0`.
-    pub fn find_at<'t>(
-        &self,
-        text: &'t str,
-        start: usize,
-    ) -> Option<Match<'t>> {
-        self.0
-            .searcher_str()
-            .find_at(text, start)
-            .map(|(s, e)| Match::new(text, s, e))
-    }
-
-    /// This is like `captures`, but uses
-    /// [`CaptureLocations`](struct.CaptureLocations.html)
-    /// instead of
-    /// [`Captures`](struct.Captures.html) in order to amortize allocations.
-    ///
-    /// To create a `CaptureLocations` value, use the
-    /// `Regex::capture_locations` method.
-    ///
-    /// This returns the overall match if this was successful, which is always
-    /// equivalence to the `0`th capture group.
-    pub fn captures_read<'t>(
-        &self,
-        locs: &mut CaptureLocations,
-        text: &'t str,
-    ) -> Option<Match<'t>> {
-        self.captures_read_at(locs, text, 0)
-    }
-
-    /// Returns the same as captures, but starts the search at the given
-    /// offset and populates the capture locations given.
-    ///
-    /// The significance of the starting point is that it takes the surrounding
-    /// context into consideration. For example, the `\A` anchor can only
-    /// match when `start == 0`.
-    pub fn captures_read_at<'t>(
-        &self,
-        locs: &mut CaptureLocations,
-        text: &'t str,
-        start: usize,
-    ) -> Option<Match<'t>> {
-        self.0
-            .searcher_str()
-            .captures_read_at(&mut locs.0, text, start)
-            .map(|(s, e)| Match::new(text, s, e))
-    }
-
-    /// An undocumented alias for `captures_read_at`.
-    ///
-    /// The `regex-capi` crate previously used this routine, so to avoid
-    /// breaking that crate, we continue to provide the name as an undocumented
-    /// alias.
-    #[doc(hidden)]
-    pub fn read_captures_at<'t>(
-        &self,
-        locs: &mut CaptureLocations,
-        text: &'t str,
-        start: usize,
-    ) -> Option<Match<'t>> {
-        self.captures_read_at(locs, text, start)
-    }
-}
-
-/// Auxiliary methods.
-impl Regex {
-    /// Returns the original string of this regex.
-    pub fn as_str(&self) -> &str {
-        &self.0.regex_strings()[0]
-    }
-
-    /// Returns an iterator over the capture names.
-    pub fn capture_names(&self) -> CaptureNames {
-        CaptureNames(self.0.capture_names().iter())
-    }
-
-    /// Returns the number of captures.
-    pub fn captures_len(&self) -> usize {
-        self.0.capture_names().len()
-    }
-
-    /// Returns an empty set of capture locations that can be reused in
-    /// multiple calls to `captures_read` or `captures_read_at`.
-    pub fn capture_locations(&self) -> CaptureLocations {
-        CaptureLocations(self.0.searcher_str().locations())
-    }
-
-    /// An alias for `capture_locations` to preserve backward compatibility.
-    ///
-    /// The `regex-capi` crate uses this method, so to avoid breaking that
-    /// crate, we continue to export it as an undocumented API.
-    #[doc(hidden)]
-    pub fn locations(&self) -> CaptureLocations {
-        CaptureLocations(self.0.searcher_str().locations())
-    }
-}
-
-/// An iterator over the names of all possible captures.
-///
-/// `None` indicates an unnamed capture; the first element (capture 0, the
-/// whole matched region) is always unnamed.
-///
-/// `'r` is the lifetime of the compiled regular expression.
-#[derive(Clone, Debug)]
-pub struct CaptureNames<'r>(::std::slice::Iter<'r, Option<String>>);
-
-impl<'r> Iterator for CaptureNames<'r> {
-    type Item = Option<&'r str>;
-
-    fn next(&mut self) -> Option<Option<&'r str>> {
-        self.0
-            .next()
-            .as_ref()
-            .map(|slot| slot.as_ref().map(|name| name.as_ref()))
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.0.size_hint()
-    }
-
-    fn count(self) -> usize {
-        self.0.count()
-    }
-}
-
-impl<'r> ExactSizeIterator for CaptureNames<'r> {}
-
-impl<'r> FusedIterator for CaptureNames<'r> {}
-
-/// Yields all substrings delimited by a regular expression match.
-///
-/// `'r` is the lifetime of the compiled regular expression and `'t` is the
-/// lifetime of the string being split.
-#[derive(Debug)]
-pub struct Split<'r, 't> {
-    finder: Matches<'r, 't>,
-    last: usize,
-}
-
-impl<'r, 't> Iterator for Split<'r, 't> {
-    type Item = &'t str;
-
-    fn next(&mut self) -> Option<&'t str> {
-        let text = self.finder.0.text();
-        match self.finder.next() {
-            None => {
-                if self.last > text.len() {
-                    None
-                } else {
-                    let s = &text[self.last..];
-                    self.last = text.len() + 1; // Next call will return None
-                    Some(s)
-                }
-            }
-            Some(m) => {
-                let matched = &text[self.last..m.start()];
-                self.last = m.end();
-                Some(matched)
-            }
-        }
-    }
-}
-
-impl<'r, 't> FusedIterator for Split<'r, 't> {}
-
-/// Yields at most `N` substrings delimited by a regular expression match.
-///
-/// The last substring will be whatever remains after splitting.
-///
-/// `'r` is the lifetime of the compiled regular expression and `'t` is the
-/// lifetime of the string being split.
-#[derive(Debug)]
-pub struct SplitN<'r, 't> {
-    splits: Split<'r, 't>,
-    n: usize,
-}
-
-impl<'r, 't> Iterator for SplitN<'r, 't> {
-    type Item = &'t str;
-
-    fn next(&mut self) -> Option<&'t str> {
-        if self.n == 0 {
-            return None;
-        }
-
-        self.n -= 1;
-        if self.n > 0 {
-            return self.splits.next();
-        }
-
-        let text = self.splits.finder.0.text();
-        if self.splits.last > text.len() {
-            // We've already returned all substrings.
-            None
-        } else {
-            // self.n == 0, so future calls will return None immediately
-            Some(&text[self.splits.last..])
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (0, Some(self.n))
-    }
-}
-
-impl<'r, 't> FusedIterator for SplitN<'r, 't> {}
-
-/// CaptureLocations is a low level representation of the raw offsets of each
-/// submatch.
-///
-/// You can think of this as a lower level
-/// [`Captures`](struct.Captures.html), where this type does not support
-/// named capturing groups directly and it does not borrow the text that these
-/// offsets were matched on.
-///
-/// Primarily, this type is useful when using the lower level `Regex` APIs
-/// such as `read_captures`, which permits amortizing the allocation in which
-/// capture match locations are stored.
-///
-/// In order to build a value of this type, you'll need to call the
-/// `capture_locations` method on the `Regex` being used to execute the search.
-/// The value returned can then be reused in subsequent searches.
-#[derive(Clone, Debug)]
-pub struct CaptureLocations(re_trait::Locations);
-
-/// A type alias for `CaptureLocations` for backwards compatibility.
-///
-/// Previously, we exported `CaptureLocations` as `Locations` in an
-/// undocumented API. To prevent breaking that code (e.g., in `regex-capi`),
-/// we continue re-exporting the same undocumented API.
-#[doc(hidden)]
-pub type Locations = CaptureLocations;
-
-impl CaptureLocations {
-    /// Returns the start and end positions of the Nth capture group. Returns
-    /// `None` if `i` is not a valid capture group or if the capture group did
-    /// not match anything. The positions returned are *always* byte indices
-    /// with respect to the original string matched.
-    #[inline]
-    pub fn get(&self, i: usize) -> Option<(usize, usize)> {
-        self.0.pos(i)
-    }
-
-    /// Returns the total number of capturing groups.
-    ///
-    /// This is always at least `1` since every regex has at least `1`
-    /// capturing group that corresponds to the entire match.
-    #[inline]
-    pub fn len(&self) -> usize {
-        self.0.len()
-    }
-
-    /// An alias for the `get` method for backwards compatibility.
-    ///
-    /// Previously, we exported `get` as `pos` in an undocumented API. To
-    /// prevent breaking that code (e.g., in `regex-capi`), we continue
-    /// re-exporting the same undocumented API.
-    #[doc(hidden)]
-    #[inline]
-    pub fn pos(&self, i: usize) -> Option<(usize, usize)> {
-        self.get(i)
-    }
-}
-
-/// Captures represents a group of captured strings for a single match.
-///
-/// The 0th capture always corresponds to the entire match. Each subsequent
-/// index corresponds to the next capture group in the regex. If a capture
-/// group is named, then the matched string is *also* available via the `name`
-/// method. (Note that the 0th capture is always unnamed and so must be
-/// accessed with the `get` method.)
-///
-/// Positions returned from a capture group are always byte indices.
-///
-/// `'t` is the lifetime of the matched text.
-pub struct Captures<'t> {
-    text: &'t str,
-    locs: re_trait::Locations,
-    named_groups: Arc<HashMap<String, usize>>,
-}
-
-impl<'t> Captures<'t> {
-    /// Returns the match associated with the capture group at index `i`. If
-    /// `i` does not correspond to a capture group, or if the capture group
-    /// did not participate in the match, then `None` is returned.
-    ///
-    /// # Examples
-    ///
-    /// Get the text of the match with a default of an empty string if this
-    /// group didn't participate in the match:
-    ///
-    /// ```rust
-    /// # use regex::Regex;
-    /// let re = Regex::new(r"[a-z]+(?:([0-9]+)|([A-Z]+))").unwrap();
-    /// let caps = re.captures("abc123").unwrap();
-    ///
-    /// let text1 = caps.get(1).map_or("", |m| m.as_str());
-    /// let text2 = caps.get(2).map_or("", |m| m.as_str());
-    /// assert_eq!(text1, "123");
-    /// assert_eq!(text2, "");
-    /// ```
-    pub fn get(&self, i: usize) -> Option<Match<'t>> {
-        self.locs.pos(i).map(|(s, e)| Match::new(self.text, s, e))
-    }
-
-    /// Returns the match for the capture group named `name`. If `name` isn't a
-    /// valid capture group or didn't match anything, then `None` is returned.
-    pub fn name(&self, name: &str) -> Option<Match<'t>> {
-        self.named_groups.get(name).and_then(|&i| self.get(i))
-    }
-
-    /// An iterator that yields all capturing matches in the order in which
-    /// they appear in the regex. If a particular capture group didn't
-    /// participate in the match, then `None` is yielded for that capture.
-    ///
-    /// The first match always corresponds to the overall match of the regex.
-    pub fn iter<'c>(&'c self) -> SubCaptureMatches<'c, 't> {
-        SubCaptureMatches { caps: self, it: self.locs.iter() }
-    }
-
-    /// Expands all instances of `$name` in `replacement` to the corresponding
-    /// capture group `name`, and writes them to the `dst` buffer given.
-    ///
-    /// `name` may be an integer corresponding to the index of the capture
-    /// group (counted by order of opening parenthesis where `0` is the
-    /// entire match) or it can be a name (consisting of letters, digits or
-    /// underscores) corresponding to a named capture group.
-    ///
-    /// If `name` isn't a valid capture group (whether the name doesn't exist
-    /// or isn't a valid index), then it is replaced with the empty string.
-    ///
-    /// The longest possible name consisting of the characters `[_0-9A-Za-z]`
-    /// is used. e.g., `$1a` looks up the capture group named `1a` and not the
-    /// capture group at index `1`. To exert more precise control over the
-    /// name, or to refer to a capture group name that uses characters outside
-    /// of `[_0-9A-Za-z]`, use braces, e.g., `${1}a` or `${foo[bar].baz}`. When
-    /// using braces, any sequence of characters is permitted. If the sequence
-    /// does not refer to a capture group name in the corresponding regex, then
-    /// it is replaced with an empty string.
-    ///
-    /// To write a literal `$` use `$$`.
-    pub fn expand(&self, replacement: &str, dst: &mut String) {
-        expand_str(self, replacement, dst)
-    }
-
-    /// Returns the number of captured groups.
-    ///
-    /// This is always at least `1`, since every regex has at least one capture
-    /// group that corresponds to the full match.
-    #[inline]
-    pub fn len(&self) -> usize {
-        self.locs.len()
-    }
-}
-
-impl<'t> fmt::Debug for Captures<'t> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_tuple("Captures").field(&CapturesDebug(self)).finish()
-    }
-}
-
-struct CapturesDebug<'c, 't: 'c>(&'c Captures<'t>);
-
-impl<'c, 't> fmt::Debug for CapturesDebug<'c, 't> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        // We'd like to show something nice here, even if it means an
-        // allocation to build a reverse index.
-        let slot_to_name: HashMap<&usize, &String> =
-            self.0.named_groups.iter().map(|(a, b)| (b, a)).collect();
-        let mut map = f.debug_map();
-        for (slot, m) in self.0.locs.iter().enumerate() {
-            let m = m.map(|(s, e)| &self.0.text[s..e]);
-            if let Some(name) = slot_to_name.get(&slot) {
-                map.entry(&name, &m);
-            } else {
-                map.entry(&slot, &m);
-            }
-        }
-        map.finish()
-    }
-}
-
-/// Get a group by index.
-///
-/// `'t` is the lifetime of the matched text.
-///
-/// The text can't outlive the `Captures` object if this method is
-/// used, because of how `Index` is defined (normally `a[i]` is part
-/// of `a` and can't outlive it); to do that, use `get()` instead.
-///
-/// # Panics
-///
-/// If there is no group at the given index.
-impl<'t> Index<usize> for Captures<'t> {
-    type Output = str;
-
-    fn index(&self, i: usize) -> &str {
-        self.get(i)
-            .map(|m| m.as_str())
-            .unwrap_or_else(|| panic!("no group at index '{}'", i))
-    }
-}
-
-/// Get a group by name.
-///
-/// `'t` is the lifetime of the matched text and `'i` is the lifetime
-/// of the group name (the index).
-///
-/// The text can't outlive the `Captures` object if this method is
-/// used, because of how `Index` is defined (normally `a[i]` is part
-/// of `a` and can't outlive it); to do that, use `name` instead.
-///
-/// # Panics
-///
-/// If there is no group named by the given value.
-impl<'t, 'i> Index<&'i str> for Captures<'t> {
-    type Output = str;
-
-    fn index<'a>(&'a self, name: &'i str) -> &'a str {
-        self.name(name)
-            .map(|m| m.as_str())
-            .unwrap_or_else(|| panic!("no group named '{}'", name))
-    }
-}
-
-/// An iterator that yields all capturing matches in the order in which they
-/// appear in the regex.
-///
-/// If a particular capture group didn't participate in the match, then `None`
-/// is yielded for that capture. The first match always corresponds to the
-/// overall match of the regex.
-///
-/// The lifetime `'c` corresponds to the lifetime of the `Captures` value, and
-/// the lifetime `'t` corresponds to the originally matched text.
-#[derive(Clone, Debug)]
-pub struct SubCaptureMatches<'c, 't: 'c> {
-    caps: &'c Captures<'t>,
-    it: SubCapturesPosIter<'c>,
-}
-
-impl<'c, 't> Iterator for SubCaptureMatches<'c, 't> {
-    type Item = Option<Match<'t>>;
-
-    fn next(&mut self) -> Option<Option<Match<'t>>> {
-        self.it
-            .next()
-            .map(|cap| cap.map(|(s, e)| Match::new(self.caps.text, s, e)))
-    }
-}
-
-impl<'c, 't> FusedIterator for SubCaptureMatches<'c, 't> {}
-
-/// An iterator that yields all non-overlapping capture groups matching a
-/// particular regular expression.
-///
-/// The iterator stops when no more matches can be found.
-///
-/// `'r` is the lifetime of the compiled regular expression and `'t` is the
-/// lifetime of the matched string.
-#[derive(Debug)]
-pub struct CaptureMatches<'r, 't>(
-    re_trait::CaptureMatches<'t, ExecNoSyncStr<'r>>,
-);
-
-impl<'r, 't> Iterator for CaptureMatches<'r, 't> {
-    type Item = Captures<'t>;
-
-    fn next(&mut self) -> Option<Captures<'t>> {
-        self.0.next().map(|locs| Captures {
-            text: self.0.text(),
-            locs: locs,
-            named_groups: self.0.regex().capture_name_idx().clone(),
-        })
-    }
-}
-
-impl<'r, 't> FusedIterator for CaptureMatches<'r, 't> {}
-
-/// An iterator over all non-overlapping matches for a particular string.
-///
-/// The iterator yields a `Match` value. The iterator stops when no more
-/// matches can be found.
-///
-/// `'r` is the lifetime of the compiled regular expression and `'t` is the
-/// lifetime of the matched string.
-#[derive(Debug)]
-pub struct Matches<'r, 't>(re_trait::Matches<'t, ExecNoSyncStr<'r>>);
-
-impl<'r, 't> Iterator for Matches<'r, 't> {
-    type Item = Match<'t>;
-
-    fn next(&mut self) -> Option<Match<'t>> {
-        let text = self.0.text();
-        self.0.next().map(|(s, e)| Match::new(text, s, e))
-    }
-}
-
-impl<'r, 't> FusedIterator for Matches<'r, 't> {}
-
-/// Replacer describes types that can be used to replace matches in a string.
-///
-/// In general, users of this crate shouldn't need to implement this trait,
-/// since implementations are already provided for `&str` and
-/// `FnMut(&Captures) -> String` (or any `FnMut(&Captures) -> T`
-/// where `T: AsRef<str>`), which covers most use cases.
-pub trait Replacer {
-    /// Appends text to `dst` to replace the current match.
-    ///
-    /// The current match is represented by `caps`, which is guaranteed to
-    /// have a match at capture group `0`.
-    ///
-    /// For example, a no-op replacement would be
-    /// `dst.push_str(caps.get(0).unwrap().as_str())`.
-    fn replace_append(&mut self, caps: &Captures, dst: &mut String);
-
-    /// Return a fixed unchanging replacement string.
-    ///
-    /// When doing replacements, if access to `Captures` is not needed (e.g.,
-    /// the replacement byte string does not need `$` expansion), then it can
-    /// be beneficial to avoid finding sub-captures.
-    ///
-    /// In general, this is called once for every call to `replacen`.
-    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, str>> {
-        None
-    }
-
-    /// Return a `Replacer` that borrows and wraps this `Replacer`.
-    ///
-    /// This is useful when you want to take a generic `Replacer` (which might
-    /// not be cloneable) and use it without consuming it, so it can be used
-    /// more than once.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use regex::{Regex, Replacer};
-    ///
-    /// fn replace_all_twice<R: Replacer>(
-    ///     re: Regex,
-    ///     src: &str,
-    ///     mut rep: R,
-    /// ) -> String {
-    ///     let dst = re.replace_all(src, rep.by_ref());
-    ///     let dst = re.replace_all(&dst, rep.by_ref());
-    ///     dst.into_owned()
-    /// }
-    /// ```
-    fn by_ref<'r>(&'r mut self) -> ReplacerRef<'r, Self> {
-        ReplacerRef(self)
-    }
-}
-
-/// By-reference adaptor for a `Replacer`
-///
-/// Returned by [`Replacer::by_ref`](trait.Replacer.html#method.by_ref).
-#[derive(Debug)]
-pub struct ReplacerRef<'a, R: ?Sized + 'a>(&'a mut R);
-
-impl<'a, R: Replacer + ?Sized + 'a> Replacer for ReplacerRef<'a, R> {
-    fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
-        self.0.replace_append(caps, dst)
-    }
-    fn no_expansion(&mut self) -> Option<Cow<str>> {
-        self.0.no_expansion()
-    }
-}
-
-impl<'a> Replacer for &'a str {
-    fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
-        caps.expand(*self, dst);
-    }
-
-    fn no_expansion(&mut self) -> Option<Cow<str>> {
-        match find_byte(b'$', self.as_bytes()) {
-            Some(_) => None,
-            None => Some(Cow::Borrowed(*self)),
-        }
-    }
-}
-
-impl<F, T> Replacer for F
-where
-    F: FnMut(&Captures) -> T,
-    T: AsRef<str>,
-{
-    fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
-        dst.push_str((*self)(caps).as_ref());
-    }
-}
-
-/// `NoExpand` indicates literal string replacement.
-///
-/// It can be used with `replace` and `replace_all` to do a literal string
-/// replacement without expanding `$name` to their corresponding capture
-/// groups. This can be both convenient (to avoid escaping `$`, for example)
-/// and performant (since capture groups don't need to be found).
-///
-/// `'t` is the lifetime of the literal text.
-#[derive(Clone, Debug)]
-pub struct NoExpand<'t>(pub &'t str);
-
-impl<'t> Replacer for NoExpand<'t> {
-    fn replace_append(&mut self, _: &Captures, dst: &mut String) {
-        dst.push_str(self.0);
-    }
-
-    fn no_expansion(&mut self) -> Option<Cow<str>> {
-        Some(Cow::Borrowed(self.0))
-    }
-}
diff --git a/vendor/regex-1.4.3/src/sparse.rs b/vendor/regex-1.4.3/src/sparse.rs
deleted file mode 100644 (file)
index bc1b2b5..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-use std::fmt;
-use std::ops::Deref;
-use std::slice;
-
-/// A sparse set used for representing ordered NFA states.
-///
-/// This supports constant time addition and membership testing. Clearing an
-/// entire set can also be done in constant time. Iteration yields elements
-/// in the order in which they were inserted.
-///
-/// The data structure is based on: http://research.swtch.com/sparse
-/// Note though that we don't actually use uninitialized memory. We generally
-/// reuse allocations, so the initial allocation cost is bareable. However,
-/// its other properties listed above are extremely useful.
-#[derive(Clone)]
-pub struct SparseSet {
-    /// Dense contains the instruction pointers in the order in which they
-    /// were inserted.
-    dense: Vec<usize>,
-    /// Sparse maps instruction pointers to their location in dense.
-    ///
-    /// An instruction pointer is in the set if and only if
-    /// sparse[ip] < dense.len() && ip == dense[sparse[ip]].
-    sparse: Box<[usize]>,
-}
-
-impl SparseSet {
-    pub fn new(size: usize) -> SparseSet {
-        SparseSet {
-            dense: Vec::with_capacity(size),
-            sparse: vec![0; size].into_boxed_slice(),
-        }
-    }
-
-    pub fn len(&self) -> usize {
-        self.dense.len()
-    }
-
-    pub fn is_empty(&self) -> bool {
-        self.dense.is_empty()
-    }
-
-    pub fn capacity(&self) -> usize {
-        self.dense.capacity()
-    }
-
-    pub fn insert(&mut self, value: usize) {
-        let i = self.len();
-        assert!(i < self.capacity());
-        self.dense.push(value);
-        self.sparse[value] = i;
-    }
-
-    pub fn contains(&self, value: usize) -> bool {
-        let i = self.sparse[value];
-        self.dense.get(i) == Some(&value)
-    }
-
-    pub fn clear(&mut self) {
-        self.dense.clear();
-    }
-}
-
-impl fmt::Debug for SparseSet {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "SparseSet({:?})", self.dense)
-    }
-}
-
-impl Deref for SparseSet {
-    type Target = [usize];
-
-    fn deref(&self) -> &Self::Target {
-        &self.dense
-    }
-}
-
-impl<'a> IntoIterator for &'a SparseSet {
-    type Item = &'a usize;
-    type IntoIter = slice::Iter<'a, usize>;
-    fn into_iter(self) -> Self::IntoIter {
-        self.iter()
-    }
-}
diff --git a/vendor/regex-1.4.3/src/testdata/LICENSE b/vendor/regex-1.4.3/src/testdata/LICENSE
deleted file mode 100644 (file)
index f47dbf4..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-The following license covers testregex.c and all associated test data.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of THIS SOFTWARE FILE (the "Software"), to deal in the Software
-without restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, and/or sell copies of the
-Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following disclaimer:
-
-THIS SOFTWARE IS PROVIDED BY AT&T ``AS IS'' AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL AT&T BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/regex-1.4.3/src/testdata/README b/vendor/regex-1.4.3/src/testdata/README
deleted file mode 100644 (file)
index 6efc2da..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-Test data was taken from the Go distribution, which was in turn taken from the
-testregex test suite:
-
-  http://www2.research.att.com/~astopen/testregex/testregex.html
-
-The LICENSE in this directory corresponds to the LICENSE that the data was
-released under.
-
-The tests themselves were modified for RE2/Go. A couple were modified further
-by me (Andrew Gallant) (only in repetition.dat) so that RE2/Go would pass them.
-(Yes, it seems like RE2/Go includes failing test cases.) This may or may not
-have been a bad idea, but I think being consistent with an established Regex
-library is worth something.
-
-Note that these files are read by 'scripts/regex-match-tests.py' and turned
-into Rust tests found in 'regex_macros/tests/matches.rs'.
-
diff --git a/vendor/regex-1.4.3/src/testdata/basic.dat b/vendor/regex-1.4.3/src/testdata/basic.dat
deleted file mode 100644 (file)
index 632e1bb..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-NOTE   all standard compliant implementations should pass these : 2002-05-31
-
-BE     abracadabra$    abracadabracadabra      (7,18)
-BE     a...b           abababbb                (2,7)
-BE     XXXXXX          ..XXXXXX                (2,8)
-E      \)              ()      (1,2)
-BE     a]              a]a     (0,2)
-B      }               }       (0,1)
-E      \}              }       (0,1)
-BE     \]              ]       (0,1)
-B      ]               ]       (0,1)
-E      ]               ]       (0,1)
-B      {               {       (0,1)
-B      }               }       (0,1)
-BE     ^a              ax      (0,1)
-BE     \^a             a^a     (1,3)
-BE     a\^             a^      (0,2)
-BE     a$              aa      (1,2)
-BE     a\$             a$      (0,2)
-BE     ^$              NULL    (0,0)
-E      $^              NULL    (0,0)
-E      a($)            aa      (1,2)(2,2)
-E      a*(^a)          aa      (0,1)(0,1)
-E      (..)*(...)*             a       (0,0)
-E      (..)*(...)*             abcd    (0,4)(2,4)
-E      (ab|a)(bc|c)            abc     (0,3)(0,2)(2,3)
-E      (ab)c|abc               abc     (0,3)(0,2)
-E      a{0}b           ab                      (1,2)
-E      (a*)(b?)(b+)b{3}        aaabbbbbbb      (0,10)(0,3)(3,4)(4,7)
-E      (a*)(b{0,1})(b{1,})b{3} aaabbbbbbb      (0,10)(0,3)(3,4)(4,7)
-E      a{9876543210}   NULL    BADBR
-E      ((a|a)|a)                       a       (0,1)(0,1)(0,1)
-E      (a*)(a|aa)                      aaaa    (0,4)(0,3)(3,4)
-E      a*(a.|aa)                       aaaa    (0,4)(2,4)
-E      a(b)|c(d)|a(e)f                 aef     (0,3)(?,?)(?,?)(1,2)
-E      (a|b)?.*                        b       (0,1)(0,1)
-E      (a|b)c|a(b|c)                   ac      (0,2)(0,1)
-E      (a|b)c|a(b|c)                   ab      (0,2)(?,?)(1,2)
-E      (a|b)*c|(a|ab)*c                abc     (0,3)(1,2)
-E      (a|b)*c|(a|ab)*c                xc      (1,2)
-E      (.a|.b).*|.*(.a|.b)             xa      (0,2)(0,2)
-E      a?(ab|ba)ab                     abab    (0,4)(0,2)
-E      a?(ac{0}b|ba)ab                 abab    (0,4)(0,2)
-E      ab|abab                         abbabab (0,2)
-E      aba|bab|bba                     baaabbbaba      (5,8)
-E      aba|bab                         baaabbbaba      (6,9)
-E      (aa|aaa)*|(a|aaaaa)             aa      (0,2)(0,2)
-E      (a.|.a.)*|(a|.a...)             aa      (0,2)(0,2)
-E      ab|a                            xabc    (1,3)
-E      ab|a                            xxabc   (2,4)
-Ei     (?-u)(Ab|cD)*                   aBcD    (0,4)(2,4)
-BE     [^-]                    --a             (2,3)
-BE     [a-]*                   --a             (0,3)
-BE     [a-m-]*                 --amoma--       (0,4)
-E      :::1:::0:|:::1:1:0:     :::0:::1:::1:::0:       (8,17)
-E      :::1:::0:|:::1:1:1:     :::0:::1:::1:::0:       (8,17)
-{E     [[:upper:]]             A               (0,1)   [[<element>]] not supported
-E      [[:lower:]]+            `az{            (1,3)
-E      [[:upper:]]+            @AZ[            (1,3)
-# No collation in Go
-#BE    [[-]]                   [[-]]           (2,4)
-#BE    [[.NIL.]]       NULL    ECOLLATE
-#BE    [[=aleph=]]     NULL    ECOLLATE
-}
-BE$    \n              \n      (0,1)
-BEn$   \n              \n      (0,1)
-BE$    [^a]            \n      (0,1)
-BE$    \na             \na     (0,2)
-E      (a)(b)(c)       abc     (0,3)(0,1)(1,2)(2,3)
-BE     xxx             xxx     (0,3)
-E1     (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)      feb 6,  (0,6)
-E1     (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)      2/7     (0,3)
-E1     (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)      feb 1,Feb 6     (5,11)
-E3     ((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))   x       (0,1)(0,1)(0,1)
-E3     ((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))*  xx      (0,2)(1,2)(1,2)
-E      a?(ab|ba)*      ababababababababababababababababababababababababababababababababababababababababa       (0,81)(79,81)
-E      abaa|abbaa|abbbaa|abbbbaa       ababbabbbabbbabbbbabbbbaa       (18,25)
-E      abaa|abbaa|abbbaa|abbbbaa       ababbabbbabbbabbbbabaa  (18,22)
-E      aaac|aabc|abac|abbc|baac|babc|bbac|bbbc baaabbbabac     (7,11)
-BE$    .*                      \x01\x7f        (0,2)
-E      aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll            XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa       (53,57)
-L      aaaa\nbbbb\ncccc\nddddd\neeeeee\nfffffff\ngggg\nhhhh\niiiii\njjjjj\nkkkkk\nllll         XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa       NOMATCH
-E      a*a*a*a*a*b             aaaaaaaaab      (0,10)
-BE     ^                       NULL            (0,0)
-BE     $                       NULL            (0,0)
-BE     ^$                      NULL            (0,0)
-BE     ^a$                     a               (0,1)
-BE     abc                     abc             (0,3)
-BE     abc                     xabcy           (1,4)
-BE     abc                     ababc           (2,5)
-BE     ab*c                    abc             (0,3)
-BE     ab*bc                   abc             (0,3)
-BE     ab*bc                   abbc            (0,4)
-BE     ab*bc                   abbbbc          (0,6)
-E      ab+bc                   abbc            (0,4)
-E      ab+bc                   abbbbc          (0,6)
-E      ab?bc                   abbc            (0,4)
-E      ab?bc                   abc             (0,3)
-E      ab?c                    abc             (0,3)
-BE     ^abc$                   abc             (0,3)
-BE     ^abc                    abcc            (0,3)
-BE     abc$                    aabc            (1,4)
-BE     ^                       abc             (0,0)
-BE     $                       abc             (3,3)
-BE     a.c                     abc             (0,3)
-BE     a.c                     axc             (0,3)
-BE     a.*c                    axyzc           (0,5)
-BE     a[bc]d                  abd             (0,3)
-BE     a[b-d]e                 ace             (0,3)
-BE     a[b-d]                  aac             (1,3)
-BE     a[-b]                   a-              (0,2)
-BE     a[b-]                   a-              (0,2)
-BE     a]                      a]              (0,2)
-BE     a[]]b                   a]b             (0,3)
-BE     a[^bc]d                 aed             (0,3)
-BE     a[^-b]c                 adc             (0,3)
-BE     a[^]b]c                 adc             (0,3)
-E      ab|cd                   abc             (0,2)
-E      ab|cd                   abcd            (0,2)
-E      a\(b                    a(b             (0,3)
-E      a\(*b                   ab              (0,2)
-E      a\(*b                   a((b            (0,4)
-E      ((a))                   abc             (0,1)(0,1)(0,1)
-E      (a)b(c)                 abc             (0,3)(0,1)(2,3)
-E      a+b+c                   aabbabc         (4,7)
-E      a*                      aaa             (0,3)
-#E     (a*)*                   -               (0,0)(0,0)
-E      (a*)*                   -               (0,0)(?,?)      RE2/Go
-E      (a*)+                   -               (0,0)(0,0)
-#E     (a*|b)*                 -               (0,0)(0,0)
-E      (a*|b)*                 -               (0,0)(?,?)      RE2/Go
-E      (a+|b)*                 ab              (0,2)(1,2)
-E      (a+|b)+                 ab              (0,2)(1,2)
-E      (a+|b)?                 ab              (0,1)(0,1)
-BE     [^ab]*                  cde             (0,3)
-#E     (^)*                    -               (0,0)(0,0)
-E      (^)*                    -               (0,0)(?,?)      RE2/Go
-BE     a*                      NULL            (0,0)
-E      ([abc])*d               abbbcd          (0,6)(4,5)
-E      ([abc])*bcd             abcd            (0,4)(0,1)
-E      a|b|c|d|e               e               (0,1)
-E      (a|b|c|d|e)f            ef              (0,2)(0,1)
-#E     ((a*|b))*               -               (0,0)(0,0)(0,0)
-E      ((a*|b))*               -               (0,0)(?,?)(?,?) RE2/Go
-BE     abcd*efg                abcdefg         (0,7)
-BE     ab*                     xabyabbbz       (1,3)
-BE     ab*                     xayabbbz        (1,2)
-E      (ab|cd)e                abcde           (2,5)(2,4)
-BE     [abhgefdc]ij            hij             (0,3)
-E      (a|b)c*d                abcd            (1,4)(1,2)
-E      (ab|ab*)bc              abc             (0,3)(0,1)
-E      a([bc]*)c*              abc             (0,3)(1,3)
-E      a([bc]*)(c*d)           abcd            (0,4)(1,3)(3,4)
-E      a([bc]+)(c*d)           abcd            (0,4)(1,3)(3,4)
-E      a([bc]*)(c+d)           abcd            (0,4)(1,2)(2,4)
-E      a[bcd]*dcdcde           adcdcde         (0,7)
-E      (ab|a)b*c               abc             (0,3)(0,2)
-E      ((a)(b)c)(d)            abcd            (0,4)(0,3)(0,1)(1,2)(3,4)
-BE     [A-Za-z_][A-Za-z0-9_]*  alpha           (0,5)
-E      ^a(bc+|b[eh])g|.h$      abh             (1,3)
-E      (bc+d$|ef*g.|h?i(j|k))  effgz           (0,5)(0,5)
-E      (bc+d$|ef*g.|h?i(j|k))  ij              (0,2)(0,2)(1,2)
-E      (bc+d$|ef*g.|h?i(j|k))  reffgz          (1,6)(1,6)
-E      (((((((((a)))))))))     a               (0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)
-BE     multiple words          multiple words yeah     (0,14)
-E      (.*)c(.*)               abcde           (0,5)(0,2)(3,5)
-BE     abcd                    abcd            (0,4)
-E      a(bc)d                  abcd            (0,4)(1,3)
-E      a[\ 1-\ 3]?c                a\ 2c             (0,3)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Qaddafi (0,15)(?,?)(10,12)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Mo'ammar Gadhafi        (0,16)(?,?)(11,13)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Kaddafi (0,15)(?,?)(10,12)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Qadhafi (0,15)(?,?)(10,12)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Gadafi  (0,14)(?,?)(10,11)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Mu'ammar Qadafi (0,15)(?,?)(11,12)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Moamar Gaddafi  (0,14)(?,?)(9,11)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Mu'ammar Qadhdhafi      (0,18)(?,?)(13,15)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Khaddafi        (0,16)(?,?)(11,13)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Ghaddafy        (0,16)(?,?)(11,13)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Ghadafi (0,15)(?,?)(11,12)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Ghaddafi        (0,16)(?,?)(11,13)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muamar Kaddafi  (0,14)(?,?)(9,11)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Quathafi        (0,16)(?,?)(11,13)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Gheddafi        (0,16)(?,?)(11,13)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Moammar Khadafy (0,15)(?,?)(11,12)
-E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Moammar Qudhafi (0,15)(?,?)(10,12)
-E      a+(b|c)*d+              aabcdd                  (0,6)(3,4)
-E      ^.+$                    vivi                    (0,4)
-E      ^(.+)$                  vivi                    (0,4)(0,4)
-E      ^([^!.]+).att.com!(.+)$ gryphon.att.com!eby     (0,19)(0,7)(16,19)
-E      ^([^!]+!)?([^!]+)$      bas                     (0,3)(?,?)(0,3)
-E      ^([^!]+!)?([^!]+)$      bar!bas                 (0,7)(0,4)(4,7)
-E      ^([^!]+!)?([^!]+)$      foo!bas                 (0,7)(0,4)(4,7)
-E      ^.+!([^!]+!)([^!]+)$    foo!bar!bas             (0,11)(4,8)(8,11)
-E      ((foo)|(bar))!bas       bar!bas                 (0,7)(0,3)(?,?)(0,3)
-E      ((foo)|(bar))!bas       foo!bar!bas             (4,11)(4,7)(?,?)(4,7)
-E      ((foo)|(bar))!bas       foo!bas                 (0,7)(0,3)(0,3)
-E      ((foo)|bar)!bas         bar!bas                 (0,7)(0,3)
-E      ((foo)|bar)!bas         foo!bar!bas             (4,11)(4,7)
-E      ((foo)|bar)!bas         foo!bas                 (0,7)(0,3)(0,3)
-E      (foo|(bar))!bas         bar!bas                 (0,7)(0,3)(0,3)
-E      (foo|(bar))!bas         foo!bar!bas             (4,11)(4,7)(4,7)
-E      (foo|(bar))!bas         foo!bas                 (0,7)(0,3)
-E      (foo|bar)!bas           bar!bas                 (0,7)(0,3)
-E      (foo|bar)!bas           foo!bar!bas             (4,11)(4,7)
-E      (foo|bar)!bas           foo!bas                 (0,7)(0,3)
-E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas     (0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
-E      ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bas             (0,3)(?,?)(0,3)
-E      ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bar!bas         (0,7)(0,4)(4,7)
-E      ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bar!bas     (0,11)(?,?)(?,?)(4,8)(8,11)
-E      ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bas         (0,7)(0,4)(4,7)
-E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bas             (0,3)(0,3)(?,?)(0,3)
-E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bar!bas         (0,7)(0,7)(0,4)(4,7)
-E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas     (0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
-E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bas         (0,7)(0,7)(0,4)(4,7)
-E      .*(/XXX).*                      /XXX                    (0,4)(0,4)
-E      .*(\\XXX).*                     \XXX                    (0,4)(0,4)
-E      \\XXX                           \XXX                    (0,4)
-E      .*(/000).*                      /000                    (0,4)(0,4)
-E      .*(\\000).*                     \000                    (0,4)(0,4)
-E      \\000                           \000                    (0,4)
diff --git a/vendor/regex-1.4.3/src/testdata/nullsubexpr.dat b/vendor/regex-1.4.3/src/testdata/nullsubexpr.dat
deleted file mode 100644 (file)
index 2e18fbb..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-NOTE   null subexpression matches : 2002-06-06
-
-E      (a*)*           a               (0,1)(0,1)
-#E     SAME            x               (0,0)(0,0)
-E      SAME            x               (0,0)(?,?)      RE2/Go
-E      SAME            aaaaaa          (0,6)(0,6)
-E      SAME            aaaaaax         (0,6)(0,6)
-E      (a*)+           a               (0,1)(0,1)
-E      SAME            x               (0,0)(0,0)
-E      SAME            aaaaaa          (0,6)(0,6)
-E      SAME            aaaaaax         (0,6)(0,6)
-E      (a+)*           a               (0,1)(0,1)
-E      SAME            x               (0,0)
-E      SAME            aaaaaa          (0,6)(0,6)
-E      SAME            aaaaaax         (0,6)(0,6)
-E      (a+)+           a               (0,1)(0,1)
-E      SAME            x               NOMATCH
-E      SAME            aaaaaa          (0,6)(0,6)
-E      SAME            aaaaaax         (0,6)(0,6)
-
-E      ([a]*)*         a               (0,1)(0,1)
-#E     SAME            x               (0,0)(0,0)
-E      SAME            x               (0,0)(?,?)      RE2/Go
-E      SAME            aaaaaa          (0,6)(0,6)
-E      SAME            aaaaaax         (0,6)(0,6)
-E      ([a]*)+         a               (0,1)(0,1)
-E      SAME            x               (0,0)(0,0)
-E      SAME            aaaaaa          (0,6)(0,6)
-E      SAME            aaaaaax         (0,6)(0,6)
-E      ([^b]*)*        a               (0,1)(0,1)
-#E     SAME            b               (0,0)(0,0)
-E      SAME            b               (0,0)(?,?)      RE2/Go
-E      SAME            aaaaaa          (0,6)(0,6)
-E      SAME            aaaaaab         (0,6)(0,6)
-E      ([ab]*)*        a               (0,1)(0,1)
-E      SAME            aaaaaa          (0,6)(0,6)
-E      SAME            ababab          (0,6)(0,6)
-E      SAME            bababa          (0,6)(0,6)
-E      SAME            b               (0,1)(0,1)
-E      SAME            bbbbbb          (0,6)(0,6)
-E      SAME            aaaabcde        (0,5)(0,5)
-E      ([^a]*)*        b               (0,1)(0,1)
-E      SAME            bbbbbb          (0,6)(0,6)
-#E     SAME            aaaaaa          (0,0)(0,0)
-E      SAME            aaaaaa          (0,0)(?,?)      RE2/Go
-E      ([^ab]*)*       ccccxx          (0,6)(0,6)
-#E     SAME            ababab          (0,0)(0,0)
-E      SAME            ababab          (0,0)(?,?)      RE2/Go
-
-E      ((z)+|a)*       zabcde          (0,2)(1,2)
-
-#{E    a+?             aaaaaa          (0,1)   no *? +? mimimal match ops
-#E     (a)             aaa             (0,1)(0,1)
-#E     (a*?)           aaa             (0,0)(0,0)
-#E     (a)*?           aaa             (0,0)
-#E     (a*?)*?         aaa             (0,0)
-#}
-
-B      \(a*\)*\(x\)            x       (0,1)(0,0)(0,1)
-B      \(a*\)*\(x\)            ax      (0,2)(0,1)(1,2)
-B      \(a*\)*\(x\)            axa     (0,2)(0,1)(1,2)
-B      \(a*\)*\(x\)\(\1\)      x       (0,1)(0,0)(0,1)(1,1)
-B      \(a*\)*\(x\)\(\1\)      ax      (0,2)(1,1)(1,2)(2,2)
-B      \(a*\)*\(x\)\(\1\)      axa     (0,3)(0,1)(1,2)(2,3)
-B      \(a*\)*\(x\)\(\1\)\(x\) axax    (0,4)(0,1)(1,2)(2,3)(3,4)
-B      \(a*\)*\(x\)\(\1\)\(x\) axxa    (0,3)(1,1)(1,2)(2,2)(2,3)
-
-#E     (a*)*(x)                x       (0,1)(0,0)(0,1)
-E      (a*)*(x)                x       (0,1)(?,?)(0,1) RE2/Go
-E      (a*)*(x)                ax      (0,2)(0,1)(1,2)
-E      (a*)*(x)                axa     (0,2)(0,1)(1,2)
-
-E      (a*)+(x)                x       (0,1)(0,0)(0,1)
-E      (a*)+(x)                ax      (0,2)(0,1)(1,2)
-E      (a*)+(x)                axa     (0,2)(0,1)(1,2)
-
-E      (a*){2}(x)              x       (0,1)(0,0)(0,1)
-E      (a*){2}(x)              ax      (0,2)(1,1)(1,2)
-E      (a*){2}(x)              axa     (0,2)(1,1)(1,2)
diff --git a/vendor/regex-1.4.3/src/testdata/repetition.dat b/vendor/regex-1.4.3/src/testdata/repetition.dat
deleted file mode 100644 (file)
index 3bb2121..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-NOTE   implicit vs. explicit repetitions : 2009-02-02
-
-# Glenn Fowler <gsf@research.att.com>
-# conforming matches (column 4) must match one of the following BREs
-#      NOMATCH
-#      (0,.)\((\(.\),\(.\))(?,?)(\2,\3)\)*
-#      (0,.)\((\(.\),\(.\))(\2,\3)(?,?)\)*
-# i.e., each 3-tuple has two identical elements and one (?,?)
-
-E      ((..)|(.))                              NULL            NOMATCH
-E      ((..)|(.))((..)|(.))                    NULL            NOMATCH
-E      ((..)|(.))((..)|(.))((..)|(.))          NULL            NOMATCH
-
-E      ((..)|(.)){1}                           NULL            NOMATCH
-E      ((..)|(.)){2}                           NULL            NOMATCH
-E      ((..)|(.)){3}                           NULL            NOMATCH
-
-E      ((..)|(.))*                             NULL            (0,0)
-
-E      ((..)|(.))                              a               (0,1)(0,1)(?,?)(0,1)
-E      ((..)|(.))((..)|(.))                    a               NOMATCH
-E      ((..)|(.))((..)|(.))((..)|(.))          a               NOMATCH
-
-E      ((..)|(.)){1}                           a               (0,1)(0,1)(?,?)(0,1)
-E      ((..)|(.)){2}                           a               NOMATCH
-E      ((..)|(.)){3}                           a               NOMATCH
-
-E      ((..)|(.))*                             a               (0,1)(0,1)(?,?)(0,1)
-
-E      ((..)|(.))                              aa              (0,2)(0,2)(0,2)(?,?)
-E      ((..)|(.))((..)|(.))                    aa              (0,2)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)
-E      ((..)|(.))((..)|(.))((..)|(.))          aa              NOMATCH
-
-E      ((..)|(.)){1}                           aa              (0,2)(0,2)(0,2)(?,?)
-E      ((..)|(.)){2}                           aa              (0,2)(1,2)(?,?)(1,2)
-E      ((..)|(.)){3}                           aa              NOMATCH
-
-E      ((..)|(.))*                             aa              (0,2)(0,2)(0,2)(?,?)
-
-E      ((..)|(.))                              aaa             (0,2)(0,2)(0,2)(?,?)
-E      ((..)|(.))((..)|(.))                    aaa             (0,3)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)
-E      ((..)|(.))((..)|(.))((..)|(.))          aaa             (0,3)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)(2,3)(?,?)(2,3)
-
-E      ((..)|(.)){1}                           aaa             (0,2)(0,2)(0,2)(?,?)
-#E     ((..)|(.)){2}                           aaa             (0,3)(2,3)(?,?)(2,3)
-E      ((..)|(.)){2}                           aaa             (0,3)(2,3)(0,2)(2,3)    RE2/Go
-E      ((..)|(.)){3}                           aaa             (0,3)(2,3)(?,?)(2,3)
-
-#E     ((..)|(.))*                             aaa             (0,3)(2,3)(?,?)(2,3)
-E      ((..)|(.))*                             aaa             (0,3)(2,3)(0,2)(2,3)    RE2/Go
-
-E      ((..)|(.))                              aaaa            (0,2)(0,2)(0,2)(?,?)
-E      ((..)|(.))((..)|(.))                    aaaa            (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
-E      ((..)|(.))((..)|(.))((..)|(.))          aaaa            (0,4)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)(3,4)(?,?)(3,4)
-
-E      ((..)|(.)){1}                           aaaa            (0,2)(0,2)(0,2)(?,?)
-E      ((..)|(.)){2}                           aaaa            (0,4)(2,4)(2,4)(?,?)
-#E     ((..)|(.)){3}                           aaaa            (0,4)(3,4)(?,?)(3,4)
-E      ((..)|(.)){3}                           aaaa            (0,4)(3,4)(0,2)(3,4)    RE2/Go
-
-E      ((..)|(.))*                             aaaa            (0,4)(2,4)(2,4)(?,?)
-
-E      ((..)|(.))                              aaaaa           (0,2)(0,2)(0,2)(?,?)
-E      ((..)|(.))((..)|(.))                    aaaaa           (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
-E      ((..)|(.))((..)|(.))((..)|(.))          aaaaa           (0,5)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,5)(?,?)(4,5)
-
-E      ((..)|(.)){1}                           aaaaa           (0,2)(0,2)(0,2)(?,?)
-E      ((..)|(.)){2}                           aaaaa           (0,4)(2,4)(2,4)(?,?)
-#E     ((..)|(.)){3}                           aaaaa           (0,5)(4,5)(?,?)(4,5)
-E      ((..)|(.)){3}                           aaaaa           (0,5)(4,5)(2,4)(4,5)    RE2/Go
-
-#E     ((..)|(.))*                             aaaaa           (0,5)(4,5)(?,?)(4,5)
-E      ((..)|(.))*                             aaaaa           (0,5)(4,5)(2,4)(4,5)    RE2/Go
-
-E      ((..)|(.))                              aaaaaa          (0,2)(0,2)(0,2)(?,?)
-E      ((..)|(.))((..)|(.))                    aaaaaa          (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
-E      ((..)|(.))((..)|(.))((..)|(.))          aaaaaa          (0,6)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,6)(4,6)(?,?)
-
-E      ((..)|(.)){1}                           aaaaaa          (0,2)(0,2)(0,2)(?,?)
-E      ((..)|(.)){2}                           aaaaaa          (0,4)(2,4)(2,4)(?,?)
-E      ((..)|(.)){3}                           aaaaaa          (0,6)(4,6)(4,6)(?,?)
-
-E      ((..)|(.))*                             aaaaaa          (0,6)(4,6)(4,6)(?,?)
-
-NOTE   additional repetition tests graciously provided by Chris Kuklewicz www.haskell.org 2009-02-02
-
-# These test a bug in OS X / FreeBSD / NetBSD, and libtree. 
-# Linux/GLIBC gets the {8,} and {8,8} wrong.
-
-:HA#100:E      X(.?){0,}Y      X1234567Y       (0,9)(7,8)
-:HA#101:E      X(.?){1,}Y      X1234567Y       (0,9)(7,8)
-:HA#102:E      X(.?){2,}Y      X1234567Y       (0,9)(7,8)
-:HA#103:E      X(.?){3,}Y      X1234567Y       (0,9)(7,8)
-:HA#104:E      X(.?){4,}Y      X1234567Y       (0,9)(7,8)
-:HA#105:E      X(.?){5,}Y      X1234567Y       (0,9)(7,8)
-:HA#106:E      X(.?){6,}Y      X1234567Y       (0,9)(7,8)
-:HA#107:E      X(.?){7,}Y      X1234567Y       (0,9)(7,8)
-:HA#108:E      X(.?){8,}Y      X1234567Y       (0,9)(8,8)
-#:HA#110:E     X(.?){0,8}Y     X1234567Y       (0,9)(7,8)
-:HA#110:E      X(.?){0,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
-#:HA#111:E     X(.?){1,8}Y     X1234567Y       (0,9)(7,8)
-:HA#111:E      X(.?){1,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
-#:HA#112:E     X(.?){2,8}Y     X1234567Y       (0,9)(7,8)
-:HA#112:E      X(.?){2,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
-#:HA#113:E     X(.?){3,8}Y     X1234567Y       (0,9)(7,8)
-:HA#113:E      X(.?){3,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
-#:HA#114:E     X(.?){4,8}Y     X1234567Y       (0,9)(7,8)
-:HA#114:E      X(.?){4,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
-#:HA#115:E     X(.?){5,8}Y     X1234567Y       (0,9)(7,8)
-:HA#115:E      X(.?){5,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
-#:HA#116:E     X(.?){6,8}Y     X1234567Y       (0,9)(7,8)
-:HA#116:E      X(.?){6,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
-#:HA#117:E     X(.?){7,8}Y     X1234567Y       (0,9)(7,8)
-:HA#117:E      X(.?){7,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
-:HA#118:E      X(.?){8,8}Y     X1234567Y       (0,9)(8,8)
-
-# These test a fixed bug in my regex-tdfa that did not keep the expanded
-# form properly grouped, so right association did the wrong thing with
-# these ambiguous patterns (crafted just to test my code when I became
-# suspicious of my implementation).  The first subexpression should use
-# "ab" then "a" then "bcd".
-
-# OS X / FreeBSD / NetBSD badly fail many of these, with impossible
-# results like (0,6)(4,5)(6,6).
-
-:HA#260:E      (a|ab|c|bcd){0,}(d*)    ababcd  (0,1)(0,1)(1,1)
-:HA#261:E      (a|ab|c|bcd){1,}(d*)    ababcd  (0,1)(0,1)(1,1)
-:HA#262:E      (a|ab|c|bcd){2,}(d*)    ababcd  (0,6)(3,6)(6,6)
-:HA#263:E      (a|ab|c|bcd){3,}(d*)    ababcd  (0,6)(3,6)(6,6)
-:HA#264:E      (a|ab|c|bcd){4,}(d*)    ababcd  NOMATCH
-:HA#265:E      (a|ab|c|bcd){0,10}(d*)  ababcd  (0,1)(0,1)(1,1)
-:HA#266:E      (a|ab|c|bcd){1,10}(d*)  ababcd  (0,1)(0,1)(1,1)
-:HA#267:E      (a|ab|c|bcd){2,10}(d*)  ababcd  (0,6)(3,6)(6,6)
-:HA#268:E      (a|ab|c|bcd){3,10}(d*)  ababcd  (0,6)(3,6)(6,6)
-:HA#269:E      (a|ab|c|bcd){4,10}(d*)  ababcd  NOMATCH
-:HA#270:E      (a|ab|c|bcd)*(d*)       ababcd  (0,1)(0,1)(1,1)
-:HA#271:E      (a|ab|c|bcd)+(d*)       ababcd  (0,1)(0,1)(1,1)
-
-# The above worked on Linux/GLIBC but the following often fail.
-# They also trip up OS X / FreeBSD / NetBSD:
-
-#:HA#280:E     (ab|a|c|bcd){0,}(d*)    ababcd  (0,6)(3,6)(6,6)
-:HA#280:E      (ab|a|c|bcd){0,}(d*)    ababcd  (0,6)(4,5)(5,6) RE2/Go
-#:HA#281:E     (ab|a|c|bcd){1,}(d*)    ababcd  (0,6)(3,6)(6,6)
-:HA#281:E      (ab|a|c|bcd){1,}(d*)    ababcd  (0,6)(4,5)(5,6) RE2/Go
-#:HA#282:E     (ab|a|c|bcd){2,}(d*)    ababcd  (0,6)(3,6)(6,6)
-:HA#282:E      (ab|a|c|bcd){2,}(d*)    ababcd  (0,6)(4,5)(5,6) RE2/Go
-#:HA#283:E     (ab|a|c|bcd){3,}(d*)    ababcd  (0,6)(3,6)(6,6)
-:HA#283:E      (ab|a|c|bcd){3,}(d*)    ababcd  (0,6)(4,5)(5,6) RE2/Go
-:HA#284:E      (ab|a|c|bcd){4,}(d*)    ababcd  NOMATCH
-#:HA#285:E     (ab|a|c|bcd){0,10}(d*)  ababcd  (0,6)(3,6)(6,6)
-:HA#285:E      (ab|a|c|bcd){0,10}(d*)  ababcd  (0,6)(4,5)(5,6) RE2/Go
-#:HA#286:E     (ab|a|c|bcd){1,10}(d*)  ababcd  (0,6)(3,6)(6,6)
-:HA#286:E      (ab|a|c|bcd){1,10}(d*)  ababcd  (0,6)(4,5)(5,6) RE2/Go
-#:HA#287:E     (ab|a|c|bcd){2,10}(d*)  ababcd  (0,6)(3,6)(6,6)
-:HA#287:E      (ab|a|c|bcd){2,10}(d*)  ababcd  (0,6)(4,5)(5,6) RE2/Go
-#:HA#288:E     (ab|a|c|bcd){3,10}(d*)  ababcd  (0,6)(3,6)(6,6)
-:HA#288:E      (ab|a|c|bcd){3,10}(d*)  ababcd  (0,6)(4,5)(5,6) RE2/Go
-:HA#289:E      (ab|a|c|bcd){4,10}(d*)  ababcd  NOMATCH
-#:HA#290:E     (ab|a|c|bcd)*(d*)       ababcd  (0,6)(3,6)(6,6)
-:HA#290:E      (ab|a|c|bcd)*(d*)       ababcd  (0,6)(4,5)(5,6) RE2/Go
-#:HA#291:E     (ab|a|c|bcd)+(d*)       ababcd  (0,6)(3,6)(6,6)
-:HA#291:E      (ab|a|c|bcd)+(d*)       ababcd  (0,6)(4,5)(5,6) RE2/Go
diff --git a/vendor/regex-1.4.3/src/utf8.rs b/vendor/regex-1.4.3/src/utf8.rs
deleted file mode 100644 (file)
index 6e0608f..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-/// A few elementary UTF-8 encoding and decoding functions used by the matching
-/// engines.
-///
-/// In an ideal world, the matching engines operate on `&str` and we can just
-/// lean on the standard library for all our UTF-8 needs. However, to support
-/// byte based regexes (that can match on arbitrary bytes which may contain
-/// UTF-8), we need to be capable of searching and decoding UTF-8 on a `&[u8]`.
-/// The standard library doesn't really recognize this use case, so we have
-/// to build it out ourselves.
-///
-/// Should this be factored out into a separate crate? It seems independently
-/// useful. There are other crates that already exist (e.g., `utf-8`) that have
-/// overlapping use cases. Not sure what to do.
-use std::char;
-
-const TAG_CONT: u8 = 0b1000_0000;
-const TAG_TWO: u8 = 0b1100_0000;
-const TAG_THREE: u8 = 0b1110_0000;
-const TAG_FOUR: u8 = 0b1111_0000;
-
-/// Returns the smallest possible index of the next valid UTF-8 sequence
-/// starting after `i`.
-pub fn next_utf8(text: &[u8], i: usize) -> usize {
-    let b = match text.get(i) {
-        None => return i + 1,
-        Some(&b) => b,
-    };
-    let inc = if b <= 0x7F {
-        1
-    } else if b <= 0b110_11111 {
-        2
-    } else if b <= 0b1110_1111 {
-        3
-    } else {
-        4
-    };
-    i + inc
-}
-
-/// Decode a single UTF-8 sequence into a single Unicode codepoint from `src`.
-///
-/// If no valid UTF-8 sequence could be found, then `None` is returned.
-/// Otherwise, the decoded codepoint and the number of bytes read is returned.
-/// The number of bytes read (for a valid UTF-8 sequence) is guaranteed to be
-/// 1, 2, 3 or 4.
-///
-/// Note that a UTF-8 sequence is invalid if it is incorrect UTF-8, encodes a
-/// codepoint that is out of range (surrogate codepoints are out of range) or
-/// is not the shortest possible UTF-8 sequence for that codepoint.
-#[inline]
-pub fn decode_utf8(src: &[u8]) -> Option<(char, usize)> {
-    let b0 = match src.get(0) {
-        None => return None,
-        Some(&b) if b <= 0x7F => return Some((b as char, 1)),
-        Some(&b) => b,
-    };
-    match b0 {
-        0b110_00000..=0b110_11111 => {
-            if src.len() < 2 {
-                return None;
-            }
-            let b1 = src[1];
-            if 0b11_000000 & b1 != TAG_CONT {
-                return None;
-            }
-            let cp = ((b0 & !TAG_TWO) as u32) << 6 | ((b1 & !TAG_CONT) as u32);
-            match cp {
-                0x80..=0x7FF => char::from_u32(cp).map(|cp| (cp, 2)),
-                _ => None,
-            }
-        }
-        0b1110_0000..=0b1110_1111 => {
-            if src.len() < 3 {
-                return None;
-            }
-            let (b1, b2) = (src[1], src[2]);
-            if 0b11_000000 & b1 != TAG_CONT {
-                return None;
-            }
-            if 0b11_000000 & b2 != TAG_CONT {
-                return None;
-            }
-            let cp = ((b0 & !TAG_THREE) as u32) << 12
-                | ((b1 & !TAG_CONT) as u32) << 6
-                | ((b2 & !TAG_CONT) as u32);
-            match cp {
-                // char::from_u32 will disallow surrogate codepoints.
-                0x800..=0xFFFF => char::from_u32(cp).map(|cp| (cp, 3)),
-                _ => None,
-            }
-        }
-        0b11110_000..=0b11110_111 => {
-            if src.len() < 4 {
-                return None;
-            }
-            let (b1, b2, b3) = (src[1], src[2], src[3]);
-            if 0b11_000000 & b1 != TAG_CONT {
-                return None;
-            }
-            if 0b11_000000 & b2 != TAG_CONT {
-                return None;
-            }
-            if 0b11_000000 & b3 != TAG_CONT {
-                return None;
-            }
-            let cp = ((b0 & !TAG_FOUR) as u32) << 18
-                | ((b1 & !TAG_CONT) as u32) << 12
-                | ((b2 & !TAG_CONT) as u32) << 6
-                | ((b3 & !TAG_CONT) as u32);
-            match cp {
-                0x10000..=0x10FFFF => char::from_u32(cp).map(|cp| (cp, 4)),
-                _ => None,
-            }
-        }
-        _ => None,
-    }
-}
-
-/// Like `decode_utf8`, but decodes the last UTF-8 sequence in `src` instead
-/// of the first.
-pub fn decode_last_utf8(src: &[u8]) -> Option<(char, usize)> {
-    if src.is_empty() {
-        return None;
-    }
-    let mut start = src.len() - 1;
-    if src[start] <= 0x7F {
-        return Some((src[start] as char, 1));
-    }
-    while start > src.len().saturating_sub(4) {
-        start -= 1;
-        if is_start_byte(src[start]) {
-            break;
-        }
-    }
-    match decode_utf8(&src[start..]) {
-        None => None,
-        Some((_, n)) if n < src.len() - start => None,
-        Some((cp, n)) => Some((cp, n)),
-    }
-}
-
-fn is_start_byte(b: u8) -> bool {
-    b & 0b11_000000 != 0b1_0000000
-}
-
-#[cfg(test)]
-mod tests {
-    use std::str;
-
-    use quickcheck::quickcheck;
-
-    use super::{
-        decode_last_utf8, decode_utf8, TAG_CONT, TAG_FOUR, TAG_THREE, TAG_TWO,
-    };
-
-    #[test]
-    fn prop_roundtrip() {
-        fn p(given_cp: char) -> bool {
-            let mut tmp = [0; 4];
-            let encoded_len = given_cp.encode_utf8(&mut tmp).len();
-            let (got_cp, got_len) = decode_utf8(&tmp[..encoded_len]).unwrap();
-            encoded_len == got_len && given_cp == got_cp
-        }
-        quickcheck(p as fn(char) -> bool)
-    }
-
-    #[test]
-    fn prop_roundtrip_last() {
-        fn p(given_cp: char) -> bool {
-            let mut tmp = [0; 4];
-            let encoded_len = given_cp.encode_utf8(&mut tmp).len();
-            let (got_cp, got_len) =
-                decode_last_utf8(&tmp[..encoded_len]).unwrap();
-            encoded_len == got_len && given_cp == got_cp
-        }
-        quickcheck(p as fn(char) -> bool)
-    }
-
-    #[test]
-    fn prop_encode_matches_std() {
-        fn p(cp: char) -> bool {
-            let mut got = [0; 4];
-            let n = cp.encode_utf8(&mut got).len();
-            let expected = cp.to_string();
-            &got[..n] == expected.as_bytes()
-        }
-        quickcheck(p as fn(char) -> bool)
-    }
-
-    #[test]
-    fn prop_decode_matches_std() {
-        fn p(given_cp: char) -> bool {
-            let mut tmp = [0; 4];
-            let n = given_cp.encode_utf8(&mut tmp).len();
-            let (got_cp, _) = decode_utf8(&tmp[..n]).unwrap();
-            let expected_cp =
-                str::from_utf8(&tmp[..n]).unwrap().chars().next().unwrap();
-            got_cp == expected_cp
-        }
-        quickcheck(p as fn(char) -> bool)
-    }
-
-    #[test]
-    fn prop_decode_last_matches_std() {
-        fn p(given_cp: char) -> bool {
-            let mut tmp = [0; 4];
-            let n = given_cp.encode_utf8(&mut tmp).len();
-            let (got_cp, _) = decode_last_utf8(&tmp[..n]).unwrap();
-            let expected_cp = str::from_utf8(&tmp[..n])
-                .unwrap()
-                .chars()
-                .rev()
-                .next()
-                .unwrap();
-            got_cp == expected_cp
-        }
-        quickcheck(p as fn(char) -> bool)
-    }
-
-    #[test]
-    fn reject_invalid() {
-        // Invalid start byte
-        assert_eq!(decode_utf8(&[0xFF]), None);
-        // Surrogate pair
-        assert_eq!(decode_utf8(&[0xED, 0xA0, 0x81]), None);
-        // Invalid continuation byte.
-        assert_eq!(decode_utf8(&[0xD4, 0xC2]), None);
-        // Bad lengths
-        assert_eq!(decode_utf8(&[0xC3]), None); // 2 bytes
-        assert_eq!(decode_utf8(&[0xEF, 0xBF]), None); // 3 bytes
-        assert_eq!(decode_utf8(&[0xF4, 0x8F, 0xBF]), None); // 4 bytes
-                                                            // Not a minimal UTF-8 sequence
-        assert_eq!(decode_utf8(&[TAG_TWO, TAG_CONT | b'a']), None);
-        assert_eq!(decode_utf8(&[TAG_THREE, TAG_CONT, TAG_CONT | b'a']), None);
-        assert_eq!(
-            decode_utf8(&[TAG_FOUR, TAG_CONT, TAG_CONT, TAG_CONT | b'a',]),
-            None
-        );
-    }
-
-    #[test]
-    fn reject_invalid_last() {
-        // Invalid start byte
-        assert_eq!(decode_last_utf8(&[0xFF]), None);
-        // Surrogate pair
-        assert_eq!(decode_last_utf8(&[0xED, 0xA0, 0x81]), None);
-        // Bad lengths
-        assert_eq!(decode_last_utf8(&[0xC3]), None); // 2 bytes
-        assert_eq!(decode_last_utf8(&[0xEF, 0xBF]), None); // 3 bytes
-        assert_eq!(decode_last_utf8(&[0xF4, 0x8F, 0xBF]), None); // 4 bytes
-                                                                 // Not a minimal UTF-8 sequence
-        assert_eq!(decode_last_utf8(&[TAG_TWO, TAG_CONT | b'a']), None);
-        assert_eq!(
-            decode_last_utf8(&[TAG_THREE, TAG_CONT, TAG_CONT | b'a',]),
-            None
-        );
-        assert_eq!(
-            decode_last_utf8(
-                &[TAG_FOUR, TAG_CONT, TAG_CONT, TAG_CONT | b'a',]
-            ),
-            None
-        );
-    }
-}
diff --git a/vendor/regex-1.4.3/test b/vendor/regex-1.4.3/test
deleted file mode 100755 (executable)
index 3d1351c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash
-
-# This is a convenience script for running a broad swath of tests across
-# features. We don't test the complete space, since the complete space is quite
-# large. Hopefully once we migrate the test suite to better infrastructure
-# (like regex-automata), we'll be able to test more of the space.
-echo "===== DEFAULT FEATURES ==="
-cargo test
-
-echo "===== DOC TESTS ==="
-cargo test --doc
-
-features=(
-    "std"
-    "std unicode"
-    "std unicode-perl"
-    "std perf"
-    "std perf-cache"
-    "std perf-dfa"
-    "std perf-inline"
-    "std perf-literal"
-)
-for f in "${features[@]}"; do
-    echo "===== FEATURE: $f (default) ==="
-    cargo test --test default --no-default-features --features "$f"
-    echo "===== FEATURE: $f (default-bytes) ==="
-    cargo test --test default-bytes --no-default-features --features "$f"
-done
diff --git a/vendor/regex-1.4.3/tests/api.rs b/vendor/regex-1.4.3/tests/api.rs
deleted file mode 100644 (file)
index c7250a8..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-#[test]
-fn empty_regex_empty_match() {
-    let re = regex!("");
-    assert_eq!(vec![(0, 0)], findall!(re, ""));
-}
-
-#[test]
-fn empty_regex_nonempty_match() {
-    let re = regex!("");
-    assert_eq!(vec![(0, 0), (1, 1), (2, 2), (3, 3)], findall!(re, "abc"));
-}
-
-#[test]
-fn one_zero_length_match() {
-    let re = regex!(r"[0-9]*");
-    assert_eq!(vec![(0, 0), (1, 2), (3, 4)], findall!(re, "a1b2"));
-}
-
-#[test]
-fn many_zero_length_match() {
-    let re = regex!(r"[0-9]*");
-    assert_eq!(
-        vec![(0, 0), (1, 2), (3, 3), (4, 4), (5, 6)],
-        findall!(re, "a1bbb2")
-    );
-}
-
-#[test]
-fn many_sequential_zero_length_match() {
-    let re = regex!(r"[0-9]?");
-    assert_eq!(
-        vec![(0, 0), (1, 2), (2, 3), (4, 5), (6, 6)],
-        findall!(re, "a12b3c")
-    );
-}
-
-#[test]
-fn quoted_bracket_set() {
-    let re = regex!(r"([\x{5b}\x{5d}])");
-    assert_eq!(vec![(0, 1), (1, 2)], findall!(re, "[]"));
-    let re = regex!(r"([\[\]])");
-    assert_eq!(vec![(0, 1), (1, 2)], findall!(re, "[]"));
-}
-
-#[test]
-fn first_range_starts_with_left_bracket() {
-    let re = regex!(r"([\[-z])");
-    assert_eq!(vec![(0, 1), (1, 2)], findall!(re, "[]"));
-}
-
-#[test]
-fn range_ends_with_escape() {
-    let re = regex!(r"([\[-\x{5d}])");
-    assert_eq!(vec![(0, 1), (1, 2)], findall!(re, "[]"));
-}
-
-#[test]
-fn empty_match_find_iter() {
-    let re = regex!(r".*?");
-    assert_eq!(vec![(0, 0), (1, 1), (2, 2), (3, 3)], findall!(re, "abc"));
-}
-
-#[test]
-fn empty_match_captures_iter() {
-    let re = regex!(r".*?");
-    let ms: Vec<_> = re
-        .captures_iter(text!("abc"))
-        .map(|c| c.get(0).unwrap())
-        .map(|m| (m.start(), m.end()))
-        .collect();
-    assert_eq!(ms, vec![(0, 0), (1, 1), (2, 2), (3, 3)]);
-}
-
-#[test]
-fn capture_names() {
-    let re = regex!(r"(.)(?P<a>.)");
-    assert_eq!(3, re.captures_len());
-    assert_eq!((3, Some(3)), re.capture_names().size_hint());
-    assert_eq!(
-        vec![None, None, Some("a")],
-        re.capture_names().collect::<Vec<_>>()
-    );
-}
-
-#[test]
-fn regex_string() {
-    assert_eq!(r"[a-zA-Z0-9]+", regex!(r"[a-zA-Z0-9]+").as_str());
-    assert_eq!(r"[a-zA-Z0-9]+", &format!("{}", regex!(r"[a-zA-Z0-9]+")));
-    assert_eq!(r"[a-zA-Z0-9]+", &format!("{:?}", regex!(r"[a-zA-Z0-9]+")));
-}
-
-#[test]
-fn capture_index() {
-    let re = regex!(r"^(?P<name>.+)$");
-    let cap = re.captures(t!("abc")).unwrap();
-    assert_eq!(&cap[0], t!("abc"));
-    assert_eq!(&cap[1], t!("abc"));
-    assert_eq!(&cap["name"], t!("abc"));
-}
-
-#[test]
-#[should_panic]
-#[cfg_attr(all(target_env = "msvc", target_pointer_width = "32"), ignore)]
-fn capture_index_panic_usize() {
-    let re = regex!(r"^(?P<name>.+)$");
-    let cap = re.captures(t!("abc")).unwrap();
-    let _ = cap[2];
-}
-
-#[test]
-#[should_panic]
-#[cfg_attr(all(target_env = "msvc", target_pointer_width = "32"), ignore)]
-fn capture_index_panic_name() {
-    let re = regex!(r"^(?P<name>.+)$");
-    let cap = re.captures(t!("abc")).unwrap();
-    let _ = cap["bad name"];
-}
-
-#[test]
-fn capture_index_lifetime() {
-    // This is a test of whether the types on `caps["..."]` are general
-    // enough. If not, this will fail to typecheck.
-    fn inner(s: &str) -> usize {
-        let re = regex!(r"(?P<number>[0-9]+)");
-        let caps = re.captures(t!(s)).unwrap();
-        caps["number"].len()
-    }
-    assert_eq!(3, inner("123"));
-}
-
-#[test]
-fn capture_misc() {
-    let re = regex!(r"(.)(?P<a>a)?(.)(?P<b>.)");
-    let cap = re.captures(t!("abc")).unwrap();
-
-    assert_eq!(5, cap.len());
-
-    assert_eq!((0, 3), {
-        let m = cap.get(0).unwrap();
-        (m.start(), m.end())
-    });
-    assert_eq!(None, cap.get(2));
-    assert_eq!((2, 3), {
-        let m = cap.get(4).unwrap();
-        (m.start(), m.end())
-    });
-
-    assert_eq!(t!("abc"), match_text!(cap.get(0).unwrap()));
-    assert_eq!(None, cap.get(2));
-    assert_eq!(t!("c"), match_text!(cap.get(4).unwrap()));
-
-    assert_eq!(None, cap.name("a"));
-    assert_eq!(t!("c"), match_text!(cap.name("b").unwrap()));
-}
-
-#[test]
-fn sub_capture_matches() {
-    let re = regex!(r"([a-z])(([a-z])|([0-9]))");
-    let cap = re.captures(t!("a5")).unwrap();
-    let subs: Vec<_> = cap.iter().collect();
-
-    assert_eq!(5, subs.len());
-    assert!(subs[0].is_some());
-    assert!(subs[1].is_some());
-    assert!(subs[2].is_some());
-    assert!(subs[3].is_none());
-    assert!(subs[4].is_some());
-
-    assert_eq!(t!("a5"), match_text!(subs[0].unwrap()));
-    assert_eq!(t!("a"), match_text!(subs[1].unwrap()));
-    assert_eq!(t!("5"), match_text!(subs[2].unwrap()));
-    assert_eq!(t!("5"), match_text!(subs[4].unwrap()));
-}
-
-expand!(expand1, r"(?-u)(?P<foo>\w+)", "abc", "$foo", "abc");
-expand!(expand2, r"(?-u)(?P<foo>\w+)", "abc", "$0", "abc");
-expand!(expand3, r"(?-u)(?P<foo>\w+)", "abc", "$1", "abc");
-expand!(expand4, r"(?-u)(?P<foo>\w+)", "abc", "$$1", "$1");
-expand!(expand5, r"(?-u)(?P<foo>\w+)", "abc", "$$foo", "$foo");
-expand!(expand6, r"(?-u)(?P<a>\w+)\s+(?P<b>\d+)", "abc 123", "$b$a", "123abc");
-expand!(expand7, r"(?-u)(?P<a>\w+)\s+(?P<b>\d+)", "abc 123", "z$bz$az", "z");
-expand!(
-    expand8,
-    r"(?-u)(?P<a>\w+)\s+(?P<b>\d+)",
-    "abc 123",
-    ".$b.$a.",
-    ".123.abc."
-);
-expand!(
-    expand9,
-    r"(?-u)(?P<a>\w+)\s+(?P<b>\d+)",
-    "abc 123",
-    " $b $a ",
-    " 123 abc "
-);
-expand!(expand10, r"(?-u)(?P<a>\w+)\s+(?P<b>\d+)", "abc 123", "$bz$az", "");
-
-expand!(expand_name1, r"%(?P<Z>[a-z]+)", "%abc", "$Z%", "abc%");
-expand!(expand_name2, r"\[(?P<Z>[a-z]+)", "[abc", "$Z[", "abc[");
-expand!(expand_name3, r"\{(?P<Z>[a-z]+)", "{abc", "$Z{", "abc{");
-expand!(expand_name4, r"\}(?P<Z>[a-z]+)", "}abc", "$Z}", "abc}");
-expand!(expand_name5, r"%([a-z]+)", "%abc", "$1a%", "%");
-expand!(expand_name6, r"%([a-z]+)", "%abc", "${1}a%", "abca%");
-expand!(expand_name7, r"\[(?P<Z[>[a-z]+)", "[abc", "${Z[}[", "abc[");
-expand!(expand_name8, r"\[(?P<Z[>[a-z]+)", "[abc", "${foo}[", "[");
-expand!(expand_name9, r"\[(?P<Z[>[a-z]+)", "[abc", "${1a}[", "[");
-expand!(expand_name10, r"\[(?P<Z[>[a-z]+)", "[abc", "${#}[", "[");
-expand!(expand_name11, r"\[(?P<Z[>[a-z]+)", "[abc", "${$$}[", "[");
-
-split!(
-    split1,
-    r"(?-u)\s+",
-    "a b\nc\td\n\t e",
-    &[t!("a"), t!("b"), t!("c"), t!("d"), t!("e")]
-);
-split!(
-    split2,
-    r"(?-u)\b",
-    "a b c",
-    &[t!(""), t!("a"), t!(" "), t!("b"), t!(" "), t!("c"), t!("")]
-);
-split!(split3, r"a$", "a", &[t!(""), t!("")]);
-split!(split_none, r"-", r"a", &[t!("a")]);
-split!(split_trailing_blank, r"-", r"a-", &[t!("a"), t!("")]);
-split!(split_trailing_blanks, r"-", r"a--", &[t!("a"), t!(""), t!("")]);
-split!(split_empty, r"-", r"", &[t!("")]);
-
-splitn!(splitn_below_limit, r"-", r"a", 2, &[t!("a")]);
-splitn!(splitn_at_limit, r"-", r"a-b", 2, &[t!("a"), t!("b")]);
-splitn!(splitn_above_limit, r"-", r"a-b-c", 2, &[t!("a"), t!("b-c")]);
-splitn!(splitn_zero_limit, r"-", r"a-b", 0, empty_vec!());
-splitn!(splitn_trailing_blank, r"-", r"a-", 2, &[t!("a"), t!("")]);
-splitn!(splitn_trailing_separator, r"-", r"a--", 2, &[t!("a"), t!("-")]);
-splitn!(splitn_empty, r"-", r"", 1, &[t!("")]);
diff --git a/vendor/regex-1.4.3/tests/api_str.rs b/vendor/regex-1.4.3/tests/api_str.rs
deleted file mode 100644 (file)
index 480116d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// These tests don't really make sense with the bytes API, so we only test them
-// on the Unicode API.
-
-#[test]
-fn empty_match_unicode_find_iter() {
-    // Tests that we still yield byte ranges at valid UTF-8 sequence boundaries
-    // even when we're susceptible to empty width matches.
-    let re = regex!(r".*?");
-    assert_eq!(
-        vec![(0, 0), (3, 3), (4, 4), (7, 7), (8, 8)],
-        findall!(re, "Ⅰ1Ⅱ2")
-    );
-}
-
-#[test]
-fn empty_match_unicode_captures_iter() {
-    // Same as empty_match_unicode_find_iter, but tests capture iteration.
-    let re = regex!(r".*?");
-    let ms: Vec<_> = re
-        .captures_iter(text!("Ⅰ1Ⅱ2"))
-        .map(|c| c.get(0).unwrap())
-        .map(|m| (m.start(), m.end()))
-        .collect();
-    assert_eq!(vec![(0, 0), (3, 3), (4, 4), (7, 7), (8, 8)], ms);
-}
-
-#[test]
-fn match_as_str() {
-    let re = regex!(r"fo+");
-    let caps = re.captures("barfoobar").unwrap();
-    assert_eq!(caps.get(0).map(|m| m.as_str()), Some("foo"));
-    assert_eq!(caps.get(0).map(From::from), Some("foo"));
-    assert_eq!(caps.get(0).map(Into::into), Some("foo"));
-}
diff --git a/vendor/regex-1.4.3/tests/bytes.rs b/vendor/regex-1.4.3/tests/bytes.rs
deleted file mode 100644 (file)
index d05f138..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-// These are tests specifically crafted for regexes that can match arbitrary
-// bytes.
-
-// A silly wrapper to make it possible to write and match raw bytes.
-struct R<'a>(&'a [u8]);
-impl<'a> R<'a> {
-    fn as_bytes(&self) -> &'a [u8] {
-        self.0
-    }
-}
-
-mat!(word_boundary, r"(?-u) \b", " δ", None);
-#[cfg(feature = "unicode-perl")]
-mat!(word_boundary_unicode, r" \b", " δ", Some((0, 1)));
-mat!(word_not_boundary, r"(?-u) \B", " δ", Some((0, 1)));
-#[cfg(feature = "unicode-perl")]
-mat!(word_not_boundary_unicode, r" \B", " δ", None);
-
-mat!(perl_w_ascii, r"(?-u)\w+", "aδ", Some((0, 1)));
-#[cfg(feature = "unicode-perl")]
-mat!(perl_w_unicode, r"\w+", "aδ", Some((0, 3)));
-mat!(perl_d_ascii, r"(?-u)\d+", "1२३9", Some((0, 1)));
-#[cfg(feature = "unicode-perl")]
-mat!(perl_d_unicode, r"\d+", "1२३9", Some((0, 8)));
-mat!(perl_s_ascii, r"(?-u)\s+", " \u{1680}", Some((0, 1)));
-#[cfg(feature = "unicode-perl")]
-mat!(perl_s_unicode, r"\s+", " \u{1680}", Some((0, 4)));
-
-// The first `(.+)` matches two Unicode codepoints, but can't match the 5th
-// byte, which isn't valid UTF-8. The second (byte based) `(.+)` takes over and
-// matches.
-mat!(
-    mixed1,
-    r"(.+)(?-u)(.+)",
-    R(b"\xCE\x93\xCE\x94\xFF"),
-    Some((0, 5)),
-    Some((0, 4)),
-    Some((4, 5))
-);
-
-mat!(case_ascii_one, r"(?i-u)a", "A", Some((0, 1)));
-mat!(case_ascii_class, r"(?i-u)[a-z]+", "AaAaA", Some((0, 5)));
-#[cfg(feature = "unicode-case")]
-mat!(case_unicode, r"(?i)[a-z]+", "aA\u{212A}aA", Some((0, 7)));
-mat!(case_not_unicode, r"(?i-u)[a-z]+", "aA\u{212A}aA", Some((0, 2)));
-
-mat!(negate_unicode, r"[^a]", "δ", Some((0, 2)));
-mat!(negate_not_unicode, r"(?-u)[^a]", "δ", Some((0, 1)));
-
-// This doesn't match in a normal Unicode regex because the implicit preceding
-// `.*?` is Unicode aware.
-mat!(dotstar_prefix_not_unicode1, r"(?-u)a", R(b"\xFFa"), Some((1, 2)));
-mat!(dotstar_prefix_not_unicode2, r"a", R(b"\xFFa"), Some((1, 2)));
-
-// Have fun with null bytes.
-mat!(
-    null_bytes,
-    r"(?-u)(?P<cstr>[^\x00]+)\x00",
-    R(b"foo\x00"),
-    Some((0, 4)),
-    Some((0, 3))
-);
-
-// Test that lookahead operators work properly in the face of invalid UTF-8.
-// See: https://github.com/rust-lang/regex/issues/277
-matiter!(
-    invalidutf8_anchor1,
-    r"(?-u)\xcc?^",
-    R(b"\x8d#;\x1a\xa4s3\x05foobarX\\\x0f0t\xe4\x9b\xa4"),
-    (0, 0)
-);
-matiter!(
-    invalidutf8_anchor2,
-    r"(?-u)^\xf7|4\xff\d\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a##########[] d\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a##########\[] #####\x80\S7|$",
-    R(b"\x8d#;\x1a\xa4s3\x05foobarX\\\x0f0t\xe4\x9b\xa4"),
-    (22, 22)
-);
-matiter!(
-    invalidutf8_anchor3,
-    r"(?-u)^|ddp\xff\xffdddddlQd@\x80",
-    R(b"\x8d#;\x1a\xa4s3\x05foobarX\\\x0f0t\xe4\x9b\xa4"),
-    (0, 0)
-);
-
-// See https://github.com/rust-lang/regex/issues/303
-#[test]
-fn negated_full_byte_range() {
-    assert!(::regex::bytes::Regex::new(r#"(?-u)[^\x00-\xff]"#).is_err());
-}
-
-matiter!(word_boundary_ascii1, r"(?-u:\B)x(?-u:\B)", "áxβ");
-matiter!(
-    word_boundary_ascii2,
-    r"(?-u:\B)",
-    "0\u{7EF5E}",
-    (2, 2),
-    (3, 3),
-    (4, 4),
-    (5, 5)
-);
-
-// See: https://github.com/rust-lang/regex/issues/264
-mat!(ascii_boundary_no_capture, r"(?-u)\B", "\u{28f3e}", Some((0, 0)));
-mat!(ascii_boundary_capture, r"(?-u)(\B)", "\u{28f3e}", Some((0, 0)));
-
-// See: https://github.com/rust-lang/regex/issues/271
-mat!(end_not_wb, r"$(?-u:\B)", "\u{5c124}\u{b576c}", Some((8, 8)));
diff --git a/vendor/regex-1.4.3/tests/consistent.rs b/vendor/regex-1.4.3/tests/consistent.rs
deleted file mode 100644 (file)
index 0f9ea53..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-use regex::internal::ExecBuilder;
-
-/// Given a regex, check if all of the backends produce the same
-/// results on a number of different inputs.
-///
-/// For now this just throws quickcheck at the problem, which
-/// is not very good because it only really tests half of the
-/// problem space. It is pretty unlikely that a random string
-/// will match any given regex, so this will probably just
-/// be checking that the different backends fail in the same
-/// way. This is still worthwhile to test, but is definitely not
-/// the whole story.
-///
-/// TODO(ethan): In order to cover the other half of the problem
-/// space, we should generate a random matching string by inspecting
-/// the AST of the input regex. The right way to do this probably
-/// involves adding a custom Arbitrary instance around a couple
-/// of newtypes. That way we can respect the quickcheck size hinting
-/// and shrinking and whatnot.
-pub fn backends_are_consistent(re: &str) -> Result<u64, String> {
-    let standard_backends = vec![
-        (
-            "bounded_backtracking_re",
-            ExecBuilder::new(re)
-                .bounded_backtracking()
-                .build()
-                .map(|exec| exec.into_regex())
-                .map_err(|err| format!("{}", err))?,
-        ),
-        (
-            "pikevm_re",
-            ExecBuilder::new(re)
-                .nfa()
-                .build()
-                .map(|exec| exec.into_regex())
-                .map_err(|err| format!("{}", err))?,
-        ),
-        (
-            "default_re",
-            ExecBuilder::new(re)
-                .build()
-                .map(|exec| exec.into_regex())
-                .map_err(|err| format!("{}", err))?,
-        ),
-    ];
-
-    let utf8bytes_backends = vec![
-        (
-            "bounded_backtracking_utf8bytes_re",
-            ExecBuilder::new(re)
-                .bounded_backtracking()
-                .bytes(true)
-                .build()
-                .map(|exec| exec.into_regex())
-                .map_err(|err| format!("{}", err))?,
-        ),
-        (
-            "pikevm_utf8bytes_re",
-            ExecBuilder::new(re)
-                .nfa()
-                .bytes(true)
-                .build()
-                .map(|exec| exec.into_regex())
-                .map_err(|err| format!("{}", err))?,
-        ),
-        (
-            "default_utf8bytes_re",
-            ExecBuilder::new(re)
-                .bytes(true)
-                .build()
-                .map(|exec| exec.into_regex())
-                .map_err(|err| format!("{}", err))?,
-        ),
-    ];
-
-    let bytes_backends = vec![
-        (
-            "bounded_backtracking_bytes_re",
-            ExecBuilder::new(re)
-                .bounded_backtracking()
-                .only_utf8(false)
-                .build()
-                .map(|exec| exec.into_byte_regex())
-                .map_err(|err| format!("{}", err))?,
-        ),
-        (
-            "pikevm_bytes_re",
-            ExecBuilder::new(re)
-                .nfa()
-                .only_utf8(false)
-                .build()
-                .map(|exec| exec.into_byte_regex())
-                .map_err(|err| format!("{}", err))?,
-        ),
-        (
-            "default_bytes_re",
-            ExecBuilder::new(re)
-                .only_utf8(false)
-                .build()
-                .map(|exec| exec.into_byte_regex())
-                .map_err(|err| format!("{}", err))?,
-        ),
-    ];
-
-    Ok(string_checker::check_backends(&standard_backends)?
-        + string_checker::check_backends(&utf8bytes_backends)?
-        + bytes_checker::check_backends(&bytes_backends)?)
-}
-
-//
-// A consistency checker parameterized by the input type (&str or &[u8]).
-//
-
-macro_rules! checker {
-    ($module_name:ident, $regex_type:path, $mk_input:expr) => {
-        mod $module_name {
-            use quickcheck;
-            use quickcheck::{Arbitrary, TestResult};
-
-            pub fn check_backends(
-                backends: &[(&str, $regex_type)],
-            ) -> Result<u64, String> {
-                let mut total_passed = 0;
-                for regex in backends[1..].iter() {
-                    total_passed += quickcheck_regex_eq(&backends[0], regex)?;
-                }
-
-                Ok(total_passed)
-            }
-
-            fn quickcheck_regex_eq(
-                &(name1, ref re1): &(&str, $regex_type),
-                &(name2, ref re2): &(&str, $regex_type),
-            ) -> Result<u64, String> {
-                quickcheck::QuickCheck::new()
-                    .quicktest(RegexEqualityTest::new(
-                        re1.clone(),
-                        re2.clone(),
-                    ))
-                    .map_err(|err| {
-                        format!(
-                            "{}(/{}/) and {}(/{}/) are inconsistent.\
-                             QuickCheck Err: {:?}",
-                            name1, re1, name2, re2, err
-                        )
-                    })
-            }
-
-            struct RegexEqualityTest {
-                re1: $regex_type,
-                re2: $regex_type,
-            }
-            impl RegexEqualityTest {
-                fn new(re1: $regex_type, re2: $regex_type) -> Self {
-                    RegexEqualityTest { re1: re1, re2: re2 }
-                }
-            }
-
-            impl quickcheck::Testable for RegexEqualityTest {
-                fn result<G: quickcheck::Gen>(
-                    &self,
-                    gen: &mut G,
-                ) -> TestResult {
-                    let input = $mk_input(gen);
-                    let input = &input;
-
-                    if self.re1.find(&input) != self.re2.find(input) {
-                        return TestResult::error(format!(
-                            "find mismatch input={:?}",
-                            input
-                        ));
-                    }
-
-                    let cap1 = self.re1.captures(input);
-                    let cap2 = self.re2.captures(input);
-                    match (cap1, cap2) {
-                        (None, None) => {}
-                        (Some(cap1), Some(cap2)) => {
-                            for (c1, c2) in cap1.iter().zip(cap2.iter()) {
-                                if c1 != c2 {
-                                    return TestResult::error(format!(
-                                        "captures mismatch input={:?}",
-                                        input
-                                    ));
-                                }
-                            }
-                        }
-                        _ => {
-                            return TestResult::error(format!(
-                                "captures mismatch input={:?}",
-                                input
-                            ))
-                        }
-                    }
-
-                    let fi1 = self.re1.find_iter(input);
-                    let fi2 = self.re2.find_iter(input);
-                    for (m1, m2) in fi1.zip(fi2) {
-                        if m1 != m2 {
-                            return TestResult::error(format!(
-                                "find_iter mismatch input={:?}",
-                                input
-                            ));
-                        }
-                    }
-
-                    let ci1 = self.re1.captures_iter(input);
-                    let ci2 = self.re2.captures_iter(input);
-                    for (cap1, cap2) in ci1.zip(ci2) {
-                        for (c1, c2) in cap1.iter().zip(cap2.iter()) {
-                            if c1 != c2 {
-                                return TestResult::error(format!(
-                                    "captures_iter mismatch input={:?}",
-                                    input
-                                ));
-                            }
-                        }
-                    }
-
-                    let s1 = self.re1.split(input);
-                    let s2 = self.re2.split(input);
-                    for (chunk1, chunk2) in s1.zip(s2) {
-                        if chunk1 != chunk2 {
-                            return TestResult::error(format!(
-                                "split mismatch input={:?}",
-                                input
-                            ));
-                        }
-                    }
-
-                    TestResult::from_bool(true)
-                }
-            }
-        } // mod
-    }; // rule case
-} // macro_rules!
-
-checker!(string_checker, ::regex::Regex, |gen| String::arbitrary(gen));
-checker!(bytes_checker, ::regex::bytes::Regex, |gen| Vec::<u8>::arbitrary(
-    gen
-));
diff --git a/vendor/regex-1.4.3/tests/crates_regex.rs b/vendor/regex-1.4.3/tests/crates_regex.rs
deleted file mode 100644 (file)
index 200ec27..0000000
+++ /dev/null
@@ -1,3287 +0,0 @@
-// DO NOT EDIT. Automatically generated by 'scripts/scrape_crates_io.py'
-// on 2018-06-20 09:56:32.820354.
-
-// autoshutdown-0.1.0: r"\s*(\d+)(\w)\s*"
-consistent!(autoshutdown_0, r"\s*(\d+)(\w)\s*");
-
-// epub-1.1.1: r"/"
-consistent!(epub_0, r"/");
-
-// rpi-info-0.2.0: "^Revision\t+: ([0-9a-fA-F]+)"
-consistent!(rpi_info_0, "^Revision\t+: ([0-9a-fA-F]+)");
-
-// rpi-info-0.2.0: "Serial\t+: ([0-9a-fA-F]+)"
-consistent!(rpi_info_1, "Serial\t+: ([0-9a-fA-F]+)");
-
-// pnet_macros-0.21.0: r"^u([0-9]+)(be|le|he)?$"
-consistent!(pnet_macros_0, r"^u([0-9]+)(be|le|he)?$");
-
-// iban_validate-1.0.3: r"^[A-Z]{2}\d{2}[A-Z\d]{1,30}$"
-consistent!(iban_validate_0, r"^[A-Z]{2}\d{2}[A-Z\d]{1,30}$");
-
-// markifier-0.1.0: r".*\[(?P<percent>.+)%.*\].*"
-consistent!(markifier_0, r".*\[(?P<percent>.+)%.*\].*");
-
-// mallumo-0.3.0: r"(#include) (\S*)(.*)"
-consistent!(mallumo_0, r"(#include) (\S*)(.*)");
-
-// mallumo-0.3.0: r"(ERROR: \d+:)(\d+)(: )(.+)"
-consistent!(mallumo_1, r"(ERROR: \d+:)(\d+)(: )(.+)");
-
-// mallumo-0.3.0: r"(\d+\()(\d+)(?:\) : )(.+)"
-consistent!(mallumo_2, r"(\d+\()(\d+)(?:\) : )(.+)");
-
-// magnet_more-0.0.1: r"(.+?)(\[.*?\])?"
-consistent!(magnet_more_0, r"(.+?)(\[.*?\])?");
-
-// magnet_app-0.0.1: r":(?P<k>[a-zA-Z_]+)"
-consistent!(magnet_app_0, r":(?P<k>[a-zA-Z_]+)");
-
-// yubibomb-0.2.0: r"^\d{6}(?:\s*,\s*\d{6})*$"
-consistent!(yubibomb_0, r"^\d{6}(?:\s*,\s*\d{6})*$");
-
-// multirust-rs-0.0.4: r"[\\/]([^\\/?]+)(\?.*)?$"
-consistent!(multirust_rs_0, r"[\\/]([^\\/?]+)(\?.*)?$");
-
-// hueclient-0.3.2: "\"[a-z]*\":null"
-consistent!(hueclient_0, "\"[a-z]*\":null");
-
-// hueclient-0.3.2: ",+"
-consistent!(hueclient_1, ",+");
-
-// hueclient-0.3.2: ",\\}"
-consistent!(hueclient_2, ",\\}");
-
-// hueclient-0.3.2: "\\{,"
-consistent!(hueclient_3, "\\{,");
-
-// aerial-0.1.0: r"[a-zA-Z_\$][a-zA-Z_0-9]*"
-consistent!(aerial_0, r"[a-zA-Z_\$][a-zA-Z_0-9]*");
-
-// aerial-0.1.0: r"thi[sng]+"
-consistent!(aerial_1, r"thi[sng]+");
-
-// rvue-0.1.0: r"(.+)\s+\((.+?)\)"
-consistent!(rvue_0, r"(.+)\s+\((.+?)\)");
-
-// rvue-0.1.0: r"([\d\.]+)\s*out\s*of\s*([\d\.]+)"
-consistent!(rvue_1, r"([\d\.]+)\s*out\s*of\s*([\d\.]+)");
-
-// rvue-0.1.0: r"^([\d\.]+)\s*(?:\(\))?$"
-consistent!(rvue_2, r"^([\d\.]+)\s*(?:\(\))?$");
-
-// rvue-0.1.0: r"([\d\.]+)\s*Points\s*Possible"
-consistent!(rvue_3, r"([\d\.]+)\s*Points\s*Possible");
-
-// rvue-0.1.0: r"([\d\.]+)\s*/\s*([\d\.]+)"
-consistent!(rvue_4, r"([\d\.]+)\s*/\s*([\d\.]+)");
-
-// rvsim-0.1.0: r"_?([_a-z0-9]+)\s*:\s*([_a-z0-9]+)\s*[,)]"
-consistent!(rvsim_0, r"_?([_a-z0-9]+)\s*:\s*([_a-z0-9]+)\s*[,)]");
-
-// nereon-0.1.4: "(.*[^\\\\])\\{\\}(.*)"
-consistent!(nereon_0, "(.*[^\\\\])\\{\\}(.*)");
-
-// next_episode-0.3.0: r"((?i)^(.+).s(\d+)e(\d+).*)$"
-consistent!(next_episode_0, r"((?i)^(.+).s(\d+)e(\d+).*)$");
-
-// migrant_lib-0.19.2: r"[^a-z0-9-]+"
-consistent!(migrant_lib_0, r"[^a-z0-9-]+");
-
-// migrant_lib-0.19.2: r"[0-9]{14}_[a-z0-9-]+"
-consistent!(migrant_lib_1, r"[0-9]{14}_[a-z0-9-]+");
-
-// migrant_lib-0.19.2: r"([0-9]{14}_)?[a-z0-9-]+"
-consistent!(migrant_lib_2, r"([0-9]{14}_)?[a-z0-9-]+");
-
-// minipre-0.2.0: "$_"
-consistent!(minipre_0, "$_");
-
-// minifier-0.0.13: r">\s+<"
-consistent!(minifier_0, r">\s+<");
-
-// minifier-0.0.13: r"\s{2,}|[\r\n]"
-consistent!(minifier_1, r"\s{2,}|[\r\n]");
-
-// minifier-0.0.13: r"<(style|script)[\w|\s].*?>"
-consistent!(minifier_2, r"<(style|script)[\w|\s].*?>");
-
-// minifier-0.0.13: "<!--(.|\n)*?-->"
-consistent!(minifier_3, "<!--(.|\n)*?-->");
-
-// minifier-0.0.13: r"<\w.*?>"
-consistent!(minifier_4, r"<\w.*?>");
-
-// minifier-0.0.13: r" \s+|\s +"
-consistent!(minifier_5, r" \s+|\s +");
-
-// minifier-0.0.13: r"\w\s+\w"
-consistent!(minifier_6, r"\w\s+\w");
-
-// minifier-0.0.13: r"'\s+>"
-consistent!(minifier_7, r"'\s+>");
-
-// minifier-0.0.13: r"\d\s+>"
-consistent!(minifier_8, r"\d\s+>");
-
-// ggp-rs-0.1.2: r"(?P<relation>\([^)]+\))|(?P<prop>[a-zA-Z0-9_]+)"
-consistent!(ggp_rs_0, r"(?P<relation>\([^)]+\))|(?P<prop>[a-zA-Z0-9_]+)");
-
-// ggp-rs-0.1.2: r"\((.*)\)."
-consistent!(ggp_rs_1, r"\((.*)\).");
-
-// poe-superfilter-0.2.0: "[A-Za-z0-9_]"
-consistent!(poe_superfilter_0, "[A-Za-z0-9_]");
-
-// poke-a-mango-0.5.0: r"(\d+)x(\d+)"
-consistent!(poke_a_mango_0, r"(\d+)x(\d+)");
-
-// pop3-rs-0.1.0: r"(?P<nmsg>\d+) (?P<size>\d+)"
-consistent!(pop3_rs_0, r"(?P<nmsg>\d+) (?P<size>\d+)");
-
-// pop3-rs-0.1.0: r"(?P<msgid>\d+) (?P<uidl>[\x21-\x7E]{1,70})"
-consistent!(pop3_rs_1, r"(?P<msgid>\d+) (?P<uidl>[\x21-\x7E]{1,70})");
-
-// pop3-rs-0.1.0: r"(<.*>)\r\n$"
-consistent!(pop3_rs_2, r"(<.*>)\r\n$");
-
-// pop3-rs-0.1.0: r"^(?P<status>\+OK|-ERR) (?P<statustext>.*)"
-consistent!(pop3_rs_3, r"^(?P<status>\+OK|-ERR) (?P<statustext>.*)");
-
-// pop3-1.0.6: r"^\.\r\n$"
-consistent!(pop3_0, r"^\.\r\n$");
-
-// pop3-1.0.6: r"\+OK(.*)"
-consistent!(pop3_1, r"\+OK(.*)");
-
-// pop3-1.0.6: r"-ERR(.*)"
-consistent!(pop3_2, r"-ERR(.*)");
-
-// pop3-1.0.6: r"\+OK (\d+) (\d+)\r\n"
-consistent!(pop3_3, r"\+OK (\d+) (\d+)\r\n");
-
-// pop3-1.0.6: r"(\d+) ([\x21-\x7e]+)\r\n"
-consistent!(pop3_4, r"(\d+) ([\x21-\x7e]+)\r\n");
-
-// pop3-1.0.6: r"\+OK (\d+) ([\x21-\x7e]+)\r\n"
-consistent!(pop3_5, r"\+OK (\d+) ([\x21-\x7e]+)\r\n");
-
-// pop3-1.0.6: r"(\d+) (\d+)\r\n"
-consistent!(pop3_6, r"(\d+) (\d+)\r\n");
-
-// pop3-1.0.6: r"\+OK (\d+) (\d+)\r\n"
-consistent!(pop3_7, r"\+OK (\d+) (\d+)\r\n");
-
-// polk-1.1.3: "github:(\\w+)/?(\\w+)?"
-consistent!(polk_0, "github:(\\w+)/?(\\w+)?");
-
-// geochunk-0.1.5: "^[0-9]{5}"
-consistent!(geochunk_0, "^[0-9]{5}");
-
-// generic-dns-update-1.1.4: r"((?:(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?)\.){3}(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?))"
-consistent!(generic_dns_update_0, r"((?:(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?)\.){3}(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?))");
-
-// generic-dns-update-1.1.4: r"((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(([0-9A-Fa-f]{1,4}:){0,5}:((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(::([0-9A-Fa-f]{1,4}:){0,5}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))"
-consistent!(generic_dns_update_1, r"((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(([0-9A-Fa-f]{1,4}:){0,5}:((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(::([0-9A-Fa-f]{1,4}:){0,5}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))");
-
-// generic-dns-update-1.1.4: r"<value><string>([0-9.]*)</string></value>"
-consistent!(
-    generic_dns_update_2,
-    r"<value><string>([0-9.]*)</string></value>"
-);
-
-// generic-dns-update-1.1.4: r"<int>([0-9]+)</int>"
-consistent!(generic_dns_update_3, r"<int>([0-9]+)</int>");
-
-// generic-dns-update-1.1.4: r"<int>([0-9]+)</int>"
-consistent!(generic_dns_update_4, r"<int>([0-9]+)</int>");
-
-// generic-dns-update-1.1.4: r"<boolean>([0-1]*)</boolean>"
-consistent!(generic_dns_update_5, r"<boolean>([0-1]*)</boolean>");
-
-// generate-nix-pkg-0.3.0: r"(\d*)\.(\d*)\.(\d*)(-(\S*))?"
-consistent!(generate_nix_pkg_0, r"(\d*)\.(\d*)\.(\d*)(-(\S*))?");
-
-// generate-nix-pkg-0.3.0: r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?"
-consistent!(generate_nix_pkg_1, r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?");
-
-// genact-0.6.0: r"arch/([a-z0-9_])+/"
-consistent!(genact_0, r"arch/([a-z0-9_])+/");
-
-// genact-0.6.0: r"arch/([a-z0-9_])+/"
-consistent!(genact_1, r"arch/([a-z0-9_])+/");
-
-// cron_rs-0.1.6: r"^\s*((\*(/\d+)?)|[0-9-,/]+)(\s+((\*(/\d+)?)|[0-9-,/]+)){4,5}\s*$"
-consistent!(
-    cron_rs_0,
-    r"^\s*((\*(/\d+)?)|[0-9-,/]+)(\s+((\*(/\d+)?)|[0-9-,/]+)){4,5}\s*$"
-);
-
-// systemfd-0.3.0: r"^([a-zA-Z]+)::(.+)$"
-consistent!(systemfd_0, r"^([a-zA-Z]+)::(.+)$");
-
-// symbolic-debuginfo-5.0.2: "__?hidden#\\d+_"
-consistent!(symbolic_debuginfo_0, "__?hidden#\\d+_");
-
-// symbolic-minidump-5.0.2: r"^Linux ([^ ]+) (.*) \w+(?: GNU/Linux)?$"
-consistent!(symbolic_minidump_0, r"^Linux ([^ ]+) (.*) \w+(?: GNU/Linux)?$");
-
-// graphql-idl-parser-0.1.1: "^(?u:\\#)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+"
-consistent!(graphql_idl_parser_0, "^(?u:\\#)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+");
-
-// graphql-idl-parser-0.1.1: "^(?u:=)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+"
-consistent!(graphql_idl_parser_1, "^(?u:=)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+");
-
-// graphql-idl-parser-0.1.1: "^(?u:[A-Z_-_a-z])(?u:[0-9A-Z_-_a-z])*"
-consistent!(graphql_idl_parser_2, "^(?u:[A-Z_-_a-z])(?u:[0-9A-Z_-_a-z])*");
-
-// graphql-idl-parser-0.1.1: "^(?u:!)"
-consistent!(graphql_idl_parser_3, "^(?u:!)");
-
-// graphql-idl-parser-0.1.1: "^(?u:\\()"
-consistent!(graphql_idl_parser_4, "^(?u:\\()");
-
-// graphql-idl-parser-0.1.1: "^(?u:\\))"
-consistent!(graphql_idl_parser_5, "^(?u:\\))");
-
-// graphql-idl-parser-0.1.1: "^(?u:,)"
-consistent!(graphql_idl_parser_6, "^(?u:,)");
-
-// graphql-idl-parser-0.1.1: "^(?u::)"
-consistent!(graphql_idl_parser_7, "^(?u::)");
-
-// graphql-idl-parser-0.1.1: "^(?u:@)"
-consistent!(graphql_idl_parser_8, "^(?u:@)");
-
-// graphql-idl-parser-0.1.1: "^(?u:\\[)"
-consistent!(graphql_idl_parser_9, "^(?u:\\[)");
-
-// graphql-idl-parser-0.1.1: "^(?u:\\])"
-consistent!(graphql_idl_parser_10, "^(?u:\\])");
-
-// graphql-idl-parser-0.1.1: "^(?u:enum)"
-consistent!(graphql_idl_parser_11, "^(?u:enum)");
-
-// graphql-idl-parser-0.1.1: "^(?u:implements)"
-consistent!(graphql_idl_parser_12, "^(?u:implements)");
-
-// graphql-idl-parser-0.1.1: "^(?u:input)"
-consistent!(graphql_idl_parser_13, "^(?u:input)");
-
-// graphql-idl-parser-0.1.1: "^(?u:interface)"
-consistent!(graphql_idl_parser_14, "^(?u:interface)");
-
-// graphql-idl-parser-0.1.1: "^(?u:scalar)"
-consistent!(graphql_idl_parser_15, "^(?u:scalar)");
-
-// graphql-idl-parser-0.1.1: "^(?u:type)"
-consistent!(graphql_idl_parser_16, "^(?u:type)");
-
-// graphql-idl-parser-0.1.1: "^(?u:union)"
-consistent!(graphql_idl_parser_17, "^(?u:union)");
-
-// graphql-idl-parser-0.1.1: "^(?u:\\{)"
-consistent!(graphql_idl_parser_18, "^(?u:\\{)");
-
-// graphql-idl-parser-0.1.1: "^(?u:\\})"
-consistent!(graphql_idl_parser_19, "^(?u:\\})");
-
-// grimoire-0.1.0: r"(?s)/\*(?P<config>.*?)\*/"
-consistent!(grimoire_0, r"(?s)/\*(?P<config>.*?)\*/");
-
-// phonenumber-0.2.0+8.9.0: r"[\d]+(?:[~\x{2053}\x{223C}\x{FF5E}][\d]+)?"
-consistent!(phonenumber_0, r"[\d]+(?:[~\x{2053}\x{223C}\x{FF5E}][\d]+)?");
-
-// phonenumber-0.2.0+8.9.0: r"[, \[\]]"
-consistent!(phonenumber_1, r"[, \[\]]");
-
-// phonenumber-0.2.0+8.9.0: r"[\\/] *x"
-consistent!(phonenumber_2, r"[\\/] *x");
-
-// phonenumber-0.2.0+8.9.0: r"[[\P{N}&&\P{L}]&&[^#]]+$"
-consistent!(phonenumber_3, r"[[\P{N}&&\P{L}]&&[^#]]+$");
-
-// phonenumber-0.2.0+8.9.0: r"(?:.*?[A-Za-z]){3}.*"
-consistent!(phonenumber_4, r"(?:.*?[A-Za-z]){3}.*");
-
-// phonenumber-0.2.0+8.9.0: r"(\D+)"
-consistent!(phonenumber_5, r"(\D+)");
-
-// phonenumber-0.2.0+8.9.0: r"(\$\d)"
-consistent!(phonenumber_6, r"(\$\d)");
-
-// phonenumber-0.2.0+8.9.0: r"\(?\$1\)?"
-consistent!(phonenumber_7, r"\(?\$1\)?");
-
-// phone_number-0.1.0: r"\D"
-consistent!(phone_number_0, r"\D");
-
-// phone_number-0.1.0: r"^0+"
-consistent!(phone_number_1, r"^0+");
-
-// phone_number-0.1.0: r"^89"
-consistent!(phone_number_2, r"^89");
-
-// phone_number-0.1.0: r"^8+"
-consistent!(phone_number_3, r"^8+");
-
-// phile-0.1.4: r"^ *(\^_*\^) *$"
-consistent!(phile_0, r"^ *(\^_*\^) *$");
-
-// phile-0.1.4: r"^[_\p{XID_Start}]$"
-consistent!(phile_1, r"^[_\p{XID_Start}]$");
-
-// phile-0.1.4: r"^\p{XID_Continue}$"
-consistent!(phile_2, r"^\p{XID_Continue}$");
-
-// uritemplate-0.1.2: "%25(?P<hex>[0-9a-fA-F][0-9a-fA-F])"
-consistent!(uritemplate_0, "%25(?P<hex>[0-9a-fA-F][0-9a-fA-F])");
-
-// urdf-rs-0.4.2: "^package://(\\w+)/"
-consistent!(urdf_rs_0, "^package://(\\w+)/");
-
-// url-match-0.1.7: r"(?P<key>[?&.])"
-consistent!(url_match_0, r"(?P<key>[?&.])");
-
-// url-match-0.1.7: r":(?P<key>[a-zA-Z0-9_-]+)"
-consistent!(url_match_1, r":(?P<key>[a-zA-Z0-9_-]+)");
-
-// tsm-sys-0.1.0: r"hello world"
-consistent!(tsm_sys_0, r"hello world");
-
-// deb-version-0.1.0: "^(?:(?:(?:\\d+:).+)|(?:[^:]+))$"
-consistent!(deb_version_0, "^(?:(?:(?:\\d+:).+)|(?:[^:]+))$");
-
-// debcargo-2.1.0: r"^(?i)(a|an|the)\s+"
-consistent!(debcargo_0, r"^(?i)(a|an|the)\s+");
-
-// debcargo-2.1.0: r"^(?i)(rust\s+)?(implementation|library|tool|crate)\s+(of|to|for)\s+"
-consistent!(
-    debcargo_1,
-    r"^(?i)(rust\s+)?(implementation|library|tool|crate)\s+(of|to|for)\s+"
-);
-
-// feaders-0.2.0: r"^.*\.h$"
-consistent!(feaders_0, r"^.*\.h$");
-
-// feaders-0.2.0: r"^.*\.c$"
-consistent!(feaders_1, r"^.*\.c$");
-
-// feaders-0.2.0: r"^.*\.hpp$"
-consistent!(feaders_2, r"^.*\.hpp$");
-
-// feaders-0.2.0: r"^.*\.cc$"
-consistent!(feaders_3, r"^.*\.cc$");
-
-// feaders-0.2.0: r"^.*\.cpp$"
-consistent!(feaders_4, r"^.*\.cpp$");
-
-// hyperscan-0.1.6: r"CPtr\(\w+\)"
-consistent!(hyperscan_0, r"CPtr\(\w+\)");
-
-// hyperscan-0.1.6: r"^Version:\s(\d\.\d\.\d)\sFeatures:\s+(\w+)?\sMode:\s(\w+)$"
-consistent!(
-    hyperscan_1,
-    r"^Version:\s(\d\.\d\.\d)\sFeatures:\s+(\w+)?\sMode:\s(\w+)$"
-);
-
-// hyperscan-0.1.6: r"RawDatabase<Block>\{db: \w+\}"
-consistent!(hyperscan_2, r"RawDatabase<Block>\{db: \w+\}");
-
-// hyperscan-0.1.6: r"RawSerializedDatabase\{p: \w+, len: \d+\}"
-consistent!(hyperscan_3, r"RawSerializedDatabase\{p: \w+, len: \d+\}");
-
-// ucd-parse-0.1.1: r"[0-9A-F]+"
-consistent!(ucd_parse_0, r"[0-9A-F]+");
-
-// afsort-0.2.0: r".*"
-consistent!(afsort_0, r".*");
-
-// afsort-0.2.0: r".*"
-consistent!(afsort_1, r".*");
-
-// afsort-0.2.0: r".*"
-consistent!(afsort_2, r".*");
-
-// afsort-0.2.0: r".*"
-consistent!(afsort_3, r".*");
-
-// afsort-0.2.0: r".*"
-consistent!(afsort_4, r".*");
-
-// afsort-0.2.0: r".*"
-consistent!(afsort_5, r".*");
-
-// afsort-0.2.0: r"^[a-z]+$"
-consistent!(afsort_6, r"^[a-z]+$");
-
-// afsort-0.2.0: r"^[a-z]+$"
-consistent!(afsort_7, r"^[a-z]+$");
-
-// tin-summer-1.21.4: r"(\.git|\.pijul|_darcs|\.hg)$"
-consistent!(tin_summer_0, r"(\.git|\.pijul|_darcs|\.hg)$");
-
-// tin-drummer-1.0.1: r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
-consistent!(tin_drummer_0, r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
-
-// tin-drummer-1.0.1: r".*?\.(stats|conf|h|out|cache.*|dat|pc|info|\.js)$"
-consistent!(
-    tin_drummer_1,
-    r".*?\.(stats|conf|h|out|cache.*|dat|pc|info|\.js)$"
-);
-
-// tin-drummer-1.0.1: r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
-consistent!(tin_drummer_2, r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
-
-// tin-drummer-1.0.1: r".*?\.(stats|conf|h|out|cache.*|\.js)$"
-consistent!(tin_drummer_3, r".*?\.(stats|conf|h|out|cache.*|\.js)$");
-
-// tin-drummer-1.0.1: r"(\.git|\.pijul|_darcs|\.hg)$"
-consistent!(tin_drummer_4, r"(\.git|\.pijul|_darcs|\.hg)$");
-
-// tin-drummer-1.0.1: r".*?\.(dyn_o|out|d|hi|dyn_hi|dump-.*|p_hi|p_o|prof|tix)$"
-consistent!(
-    tin_drummer_5,
-    r".*?\.(dyn_o|out|d|hi|dyn_hi|dump-.*|p_hi|p_o|prof|tix)$"
-);
-
-// tin-drummer-1.0.1: r".*?\.(ibc)$"
-consistent!(tin_drummer_6, r".*?\.(ibc)$");
-
-// tin-drummer-1.0.1: r"\.stack-work|dist-newstyle"
-consistent!(tin_drummer_7, r"\.stack-work|dist-newstyle");
-
-// timmy-0.3.0: r"_NET_WM_PID\(CARDINAL\) = (\d+)"
-consistent!(timmy_0, r"_NET_WM_PID\(CARDINAL\) = (\d+)");
-
-// timmy-0.3.0: r"today|yesterday|now"
-consistent!(timmy_1, r"today|yesterday|now");
-
-// timmy-0.3.0: r"(?P<day>\d{1,2})/(?P<month>\d{1,2})(/(?P<year>\d{4}|\d{2}))?"
-consistent!(
-    timmy_2,
-    r"(?P<day>\d{1,2})/(?P<month>\d{1,2})(/(?P<year>\d{4}|\d{2}))?"
-);
-
-// timmy-0.3.0: r"(?P<n>\d+) (days?|ds?)(?P<ago>( ago)?)"
-consistent!(timmy_3, r"(?P<n>\d+) (days?|ds?)(?P<ago>( ago)?)");
-
-// timmy-0.3.0: r"(?P<hr>\d{2}):(?P<mins>\d{2})"
-consistent!(timmy_4, r"(?P<hr>\d{2}):(?P<mins>\d{2})");
-
-// tinfo-0.5.0: r"^(\d+): \d+ windows \(.*\) \[\d+x\d+\]( \(attached\))?"
-consistent!(
-    tinfo_0,
-    r"^(\d+): \d+ windows \(.*\) \[\d+x\d+\]( \(attached\))?"
-);
-
-// tinfo-0.5.0: r"^(\d+):(\d+): (.*) \((\d+) panes\) \[(\d+)x(\d+)\]"
-consistent!(tinfo_1, r"^(\d+):(\d+): (.*) \((\d+) panes\) \[(\d+)x(\d+)\]");
-
-// timespan-0.0.4: r"(?:\\\{start\\\}|\\\{end\\\})"
-consistent!(timespan_0, r"(?:\\\{start\\\}|\\\{end\\\})");
-
-// timespan-0.0.4: r"(.*)\s+-\s+(.*)"
-consistent!(timespan_1, r"(.*)\s+-\s+(.*)");
-
-// timespan-0.0.4: r"(.*)\s+(\w+)$"
-consistent!(timespan_2, r"(.*)\s+(\w+)$");
-
-// timespan-0.0.4: r"(.*)\s+(\w+)$"
-consistent!(timespan_3, r"(.*)\s+(\w+)$");
-
-// timespan-0.0.4: r"(.*)\s+-\s+(.*)"
-consistent!(timespan_4, r"(.*)\s+-\s+(.*)");
-
-// titlecase-0.10.0: r"[[:lower:]]"
-consistent!(titlecase_0, r"[[:lower:]]");
-
-// tight-0.1.3: r"^\d+ (day|week|month|year)s?$"
-consistent!(tight_0, r"^\d+ (day|week|month|year)s?$");
-
-// tight-0.1.3: r"^\d+ (day|week|month|year)s?$"
-consistent!(tight_1, r"^\d+ (day|week|month|year)s?$");
-
-// yaml-0.2.1: r"^[-+]?(0|[1-9][0-9_]*)$"
-consistent!(yaml_0, r"^[-+]?(0|[1-9][0-9_]*)$");
-
-// yaml-0.2.1: r"^([-+]?)0o?([0-7_]+)$"
-consistent!(yaml_1, r"^([-+]?)0o?([0-7_]+)$");
-
-// yaml-0.2.1: r"^([-+]?)0x([0-9a-fA-F_]+)$"
-consistent!(yaml_2, r"^([-+]?)0x([0-9a-fA-F_]+)$");
-
-// yaml-0.2.1: r"^([-+]?)0b([0-1_]+)$"
-consistent!(yaml_3, r"^([-+]?)0b([0-1_]+)$");
-
-// yaml-0.2.1: r"^([-+]?)(\.[0-9]+|[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?)$"
-consistent!(
-    yaml_4,
-    r"^([-+]?)(\.[0-9]+|[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?)$"
-);
-
-// yaml-0.2.1: r"^[+]?(\.inf|\.Inf|\.INF)$"
-consistent!(yaml_5, r"^[+]?(\.inf|\.Inf|\.INF)$");
-
-// yaml-0.2.1: r"^-(\.inf|\.Inf|\.INF)$"
-consistent!(yaml_6, r"^-(\.inf|\.Inf|\.INF)$");
-
-// yaml-0.2.1: r"^(\.nan|\.NaN|\.NAN)$"
-consistent!(yaml_7, r"^(\.nan|\.NaN|\.NAN)$");
-
-// yaml-0.2.1: r"^(null|Null|NULL|~)$"
-consistent!(yaml_8, r"^(null|Null|NULL|~)$");
-
-// yaml-0.2.1: r"^(true|True|TRUE|yes|Yes|YES)$"
-consistent!(yaml_9, r"^(true|True|TRUE|yes|Yes|YES)$");
-
-// yaml-0.2.1: r"^(false|False|FALSE|no|No|NO)$"
-consistent!(yaml_10, r"^(false|False|FALSE|no|No|NO)$");
-
-// kefia-0.1.0: r"(?m)^(\S+)/(\S+) (\S+)(?: \((.*)\))?$"
-consistent!(kefia_0, r"(?m)^(\S+)/(\S+) (\S+)(?: \((.*)\))?$");
-
-// risp-0.7.0: "^(\\s+|;.*?(\n|$))+"
-consistent!(risp_0, "^(\\s+|;.*?(\n|$))+");
-
-// risp-0.7.0: "^\".*?\""
-consistent!(risp_1, "^\".*?\"");
-
-// risp-0.7.0: r"^[^\s\{\}()\[\]]+"
-consistent!(risp_2, r"^[^\s\{\}()\[\]]+");
-
-// risp-0.7.0: r"^-?\d+"
-consistent!(risp_3, r"^-?\d+");
-
-// ripgrep-0.8.1: "^([0-9]+)([KMG])?$"
-consistent!(ripgrep_0, "^([0-9]+)([KMG])?$");
-
-// riquid-0.0.1: r"^\w+"
-consistent!(riquid_0, r"^\w+");
-
-// riquid-0.0.1: r"^\d+"
-consistent!(riquid_1, r"^\d+");
-
-// recursive_disassembler-2.1.2: r"\A(0x)?([a-fA-F0-9]+)\z"
-consistent!(recursive_disassembler_0, r"\A(0x)?([a-fA-F0-9]+)\z");
-
-// remake-0.1.0: r"^[a-zA-Z_][a-zA-Z0-9_]*"
-consistent!(remake_0, r"^[a-zA-Z_][a-zA-Z0-9_]*");
-
-// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
-consistent!(regex_decode_0, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
-
-// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
-consistent!(regex_decode_1, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
-
-// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
-consistent!(regex_decode_2, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
-
-// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
-consistent!(regex_decode_3, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
-
-// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
-consistent!(regex_decode_4, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
-
-// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
-consistent!(regex_decode_5, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
-
-// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{2})\)"
-consistent!(regex_decode_6, r"'(?P<title>[^']+)'\s+\((?P<year>\d{2})\)");
-
-// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
-consistent!(regex_decode_7, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
-
-// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
-consistent!(regex_decode_8, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
-
-// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
-consistent!(regex_decode_9, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
-
-// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
-consistent!(regex_decode_10, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
-
-// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
-consistent!(regex_decode_11, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
-
-// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
-consistent!(regex_decode_12, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
-
-// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
-consistent!(regex_decode_13, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
-
-// regex-cache-0.2.0: "[0-9]{3}-[0-9]{3}-[0-9]{4}"
-consistent!(regex_cache_0, "[0-9]{3}-[0-9]{3}-[0-9]{4}");
-
-// regex-cache-0.2.0: r"^\d+$"
-consistent!(regex_cache_1, r"^\d+$");
-
-// regex-cache-0.2.0: r"^[a-z]+$"
-consistent!(regex_cache_2, r"^[a-z]+$");
-
-// regex-cache-0.2.0: r"^\d+$"
-consistent!(regex_cache_3, r"^\d+$");
-
-// regex-cache-0.2.0: r"^\d+$"
-consistent!(regex_cache_4, r"^\d+$");
-
-// regex_dfa-0.5.0: r"\d{4}-\d{2}-\d{2}"
-consistent!(regex_dfa_0, r"\d{4}-\d{2}-\d{2}");
-
-// reaper-2.0.0: r"^[0-9\p{L} _\\.]{3,16}$"
-consistent!(reaper_0, r"^[0-9\p{L} _\\.]{3,16}$");
-
-// retdec-0.1.0: r"^attachment; filename=(.+)$"
-consistent!(retdec_0, r"^attachment; filename=(.+)$");
-
-// renvsubst-0.1.2: r"(\\)(?P<head>\$[0-9A-Za-z_{])"
-consistent!(renvsubst_0, r"(\\)(?P<head>\$[0-9A-Za-z_{])");
-
-// renvsubst-0.1.2: r"\$([[:word:]]+)"
-consistent!(renvsubst_1, r"\$([[:word:]]+)");
-
-// renvsubst-0.1.2: r"\$\{([[:word:]]+)\}"
-consistent!(renvsubst_2, r"\$\{([[:word:]]+)\}");
-
-// rexpect-0.3.0: r"'[a-z]+'"
-consistent!(rexpect_0, r"'[a-z]+'");
-
-// rexpect-0.3.0: r"^\d{4}-\d{2}-\d{2}$"
-consistent!(rexpect_1, r"^\d{4}-\d{2}-\d{2}$");
-
-// rexpect-0.3.0: r"-\d{2}-"
-consistent!(rexpect_2, r"-\d{2}-");
-
-// luther-0.1.0: "^a(b|c)c*$"
-consistent!(luther_0, "^a(b|c)c*$");
-
-// little_boxes-1.6.0: r"(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]"
-consistent!(little_boxes_0, r"(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]");
-
-// libimagentrytag-0.8.0: "^[a-zA-Z]([a-zA-Z0-9_-]*)$"
-consistent!(libimagentrytag_0, "^[a-zA-Z]([a-zA-Z0-9_-]*)$");
-
-// libimaginteraction-0.8.0: r"^[Yy](\n?)$"
-consistent!(libimaginteraction_0, r"^[Yy](\n?)$");
-
-// libimaginteraction-0.8.0: r"^[Nn](\n?)$"
-consistent!(libimaginteraction_1, r"^[Nn](\n?)$");
-
-// libimagutil-0.8.0: "^(?P<KEY>([^=]*))=(.*)$"
-consistent!(libimagutil_0, "^(?P<KEY>([^=]*))=(.*)$");
-
-// libimagutil-0.8.0: "(.*)=(\"(?P<QVALUE>([^\"]*))\"|(?P<VALUE>(.*)))$"
-consistent!(libimagutil_1, "(.*)=(\"(?P<QVALUE>([^\"]*))\"|(?P<VALUE>(.*)))$");
-
-// linux_ip-0.1.0: r"\s+"
-consistent!(linux_ip_0, r"\s+");
-
-// linux_ip-0.1.0: r"\s*[\n\r]+\s*"
-consistent!(linux_ip_1, r"\s*[\n\r]+\s*");
-
-// linux_ip-0.1.0: r"^([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$"
-consistent!(linux_ip_2, r"^([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$");
-
-// linux_ip-0.1.0: r"^([0-9a-fA-F\.:/]+|default)\s+via\s+([a-z0-9\.:]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$"
-consistent!(linux_ip_3, r"^([0-9a-fA-F\.:/]+|default)\s+via\s+([a-z0-9\.:]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$");
-
-// linux_ip-0.1.0: r"^(blackhole)\s+([0-9a-fA-F\.:/]+)$"
-consistent!(linux_ip_4, r"^(blackhole)\s+([0-9a-fA-F\.:/]+)$");
-
-// linux_ip-0.1.0: r"^(unreachable)\s+([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s+(.*)$"
-consistent!(
-    linux_ip_5,
-    r"^(unreachable)\s+([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s+(.*)$"
-);
-
-// linux_ip-0.1.0: r"\s*[\n\r]+\s*"
-consistent!(linux_ip_6, r"\s*[\n\r]+\s*");
-
-// linux_ip-0.1.0: r"^\d+:\s+([a-zA-Z0-9\.-]+)(@\S+)*:\s+(.*)$"
-consistent!(linux_ip_7, r"^\d+:\s+([a-zA-Z0-9\.-]+)(@\S+)*:\s+(.*)$");
-
-// linux_ip-0.1.0: r"\s*link/ether\s+([a-f0-9:]+)\s+.*"
-consistent!(linux_ip_8, r"\s*link/ether\s+([a-f0-9:]+)\s+.*");
-
-// linux_ip-0.1.0: r"\s*inet[6]*\s+([0-9a-f:\./]+)\s+.*"
-consistent!(linux_ip_9, r"\s*inet[6]*\s+([0-9a-f:\./]+)\s+.*");
-
-// linky-0.1.4: r"[^\w -]"
-consistent!(linky_0, r"[^\w -]");
-
-// linky-0.1.4: r"^(.*):(\d+): [^ ]* ([^ ]*)$"
-consistent!(linky_1, r"^(.*):(\d+): [^ ]* ([^ ]*)$");
-
-// limonite-0.2.1: r"^(\d{4}-\d{2}-\d{2})-(\d{3})-(.+)$"
-consistent!(limonite_0, r"^(\d{4}-\d{2}-\d{2})-(\d{3})-(.+)$");
-
-// process-queue-0.1.1: r"^[a-zA-Z]+$"
-consistent!(process_queue_0, r"^[a-zA-Z]+$");
-
-// pronghorn-0.1.2: r"^\{([a-zA-Z_]+)\}$"
-consistent!(pronghorn_0, r"^\{([a-zA-Z_]+)\}$");
-
-// protocol-ftp-client-0.1.1: "(?m:^(\\d{3}) (.+)\r$)"
-consistent!(protocol_ftp_client_0, "(?m:^(\\d{3}) (.+)\r$)");
-
-// protocol-ftp-client-0.1.1: "\"(.+)\""
-consistent!(protocol_ftp_client_1, "\"(.+)\"");
-
-// protocol-ftp-client-0.1.1: "(\\w+) [Tt]ype: (\\w+)"
-consistent!(protocol_ftp_client_2, "(\\w+) [Tt]ype: (\\w+)");
-
-// protocol-ftp-client-0.1.1: "(?m:^(\\d{3})-.+\r$)"
-consistent!(protocol_ftp_client_3, "(?m:^(\\d{3})-.+\r$)");
-
-// protocol-ftp-client-0.1.1: "Entering Passive Mode \\((\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+)\\)"
-consistent!(
-    protocol_ftp_client_4,
-    "Entering Passive Mode \\((\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+)\\)"
-);
-
-// protocol-ftp-client-0.1.1: "(?m:^(.+)\r$)"
-consistent!(protocol_ftp_client_5, "(?m:^(.+)\r$)");
-
-// protocol-ftp-client-0.1.1: "^([d-])(?:[rwx-]{3}){3} +\\d+ +\\w+ +\\w+ +(\\d+) +(.+) +(.+)$"
-consistent!(
-    protocol_ftp_client_6,
-    "^([d-])(?:[rwx-]{3}){3} +\\d+ +\\w+ +\\w+ +(\\d+) +(.+) +(.+)$"
-);
-
-// article-date-extractor-0.1.1: r"([\./\-_]{0,1}(19|20)\d{2})[\./\-_]{0,1}(([0-3]{0,1}[0-9][\./\-_])|(\w{3,5}[\./\-_]))([0-3]{0,1}[0-9][\./\-]{0,1})"
-consistent!(article_date_extractor_0, r"([\./\-_]{0,1}(19|20)\d{2})[\./\-_]{0,1}(([0-3]{0,1}[0-9][\./\-_])|(\w{3,5}[\./\-_]))([0-3]{0,1}[0-9][\./\-]{0,1})");
-
-// article-date-extractor-0.1.1: r"(?i)publishdate|pubdate|timestamp|article_date|articledate|date"
-consistent!(
-    article_date_extractor_1,
-    r"(?i)publishdate|pubdate|timestamp|article_date|articledate|date"
-);
-
-// arthas_plugin-0.1.1: r"type\((.*)\)"
-consistent!(arthas_plugin_0, r"type\((.*)\)");
-
-// arthas_plugin-0.1.1: r"Vec<(.*)>"
-consistent!(arthas_plugin_1, r"Vec<(.*)>");
-
-// arthas_plugin-0.1.1: r"Option<(.*)>"
-consistent!(arthas_plugin_2, r"Option<(.*)>");
-
-// arthas_plugin-0.1.1: r"HashMap<[a-z0-9A-Z]+, *(.*)>"
-consistent!(arthas_plugin_3, r"HashMap<[a-z0-9A-Z]+, *(.*)>");
-
-// arthas_derive-0.1.0: "Vec *< *(.*) *>"
-consistent!(arthas_derive_0, "Vec *< *(.*) *>");
-
-// arthas_derive-0.1.0: r"Option *< *(.*) *>"
-consistent!(arthas_derive_1, r"Option *< *(.*) *>");
-
-// arthas_derive-0.1.0: r"HashMap *< *[a-z0-9A-Z]+ *, *(.*) *>"
-consistent!(arthas_derive_2, r"HashMap *< *[a-z0-9A-Z]+ *, *(.*) *>");
-
-// arpabet-0.2.0: r"^([\w\-\(\)\.']+)\s+([^\s].*)\s*$"
-consistent!(arpabet_0, r"^([\w\-\(\)\.']+)\s+([^\s].*)\s*$");
-
-// arpabet-0.2.0: r"^;;;\s+"
-consistent!(arpabet_1, r"^;;;\s+");
-
-// glossy_codegen-0.2.0: r"/\*.*?\*/|//.*"
-consistent!(glossy_codegen_0, r"/\*.*?\*/|//.*");
-
-// glossy_codegen-0.2.0: "^\\s*#\\s*include\\s+<([:print:]+)>\\s*$"
-consistent!(glossy_codegen_1, "^\\s*#\\s*include\\s+<([:print:]+)>\\s*$");
-
-// glossy_codegen-0.2.0: "^\\s*#\\s*include\\s+\"([:print:]+)\"\\s*$"
-consistent!(glossy_codegen_2, "^\\s*#\\s*include\\s+\"([:print:]+)\"\\s*$");
-
-// glossy_codegen-0.2.0: r"^\s*#\s*version\s+(\d+)"
-consistent!(glossy_codegen_3, r"^\s*#\s*version\s+(\d+)");
-
-// glossy_codegen-0.2.0: r"^\s*$"
-consistent!(glossy_codegen_4, r"^\s*$");
-
-// gluster-1.0.1: r"(?P<addr>via \S+)"
-consistent!(gluster_0, r"(?P<addr>via \S+)");
-
-// gluster-1.0.1: r"(?P<src>src \S+)"
-consistent!(gluster_1, r"(?P<src>src \S+)");
-
-// gl_helpers-0.1.7: r"(.*)\[\d+\]"
-consistent!(gl_helpers_0, r"(.*)\[\d+\]");
-
-// gl_helpers-0.1.7: r"(\d+).(\d+)"
-consistent!(gl_helpers_1, r"(\d+).(\d+)");
-
-// glr-parser-0.0.1: r"(?P<c>[\\\.\+\*\?\(\)\|\[\]\{\}\^\$])"
-consistent!(glr_parser_0, r"(?P<c>[\\\.\+\*\?\(\)\|\[\]\{\}\^\$])");
-
-// glr-parser-0.0.1: r"^\w+$"
-consistent!(glr_parser_1, r"^\w+$");
-
-// glr-parser-0.0.1: "'[^']+'"
-consistent!(glr_parser_2, "'[^']+'");
-
-// hoodlum-0.5.0: r"(?m)//.*"
-consistent!(hoodlum_0, r"(?m)//.*");
-
-// form-checker-0.2.2: r"^1\d{10}$"
-consistent!(form_checker_0, r"^1\d{10}$");
-
-// form-checker-0.2.2: r"(?i)^[\w.%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$"
-consistent!(form_checker_1, r"(?i)^[\w.%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$");
-
-// wikibase-0.2.0: r"(?P<user_agent>[a-zA-Z0-9-_]+/[0-9\.]+)"
-consistent!(wikibase_0, r"(?P<user_agent>[a-zA-Z0-9-_]+/[0-9\.]+)");
-
-// wifiscanner-0.3.6: r"Cell [0-9]{2,} - Address:"
-consistent!(wifiscanner_0, r"Cell [0-9]{2,} - Address:");
-
-// wifiscanner-0.3.6: r"([0-9a-zA-Z]{1}[0-9a-zA-Z]{1}[:]{1}){5}[0-9a-zA-Z]{1}[0-9a-zA-Z]{1}"
-consistent!(
-    wifiscanner_1,
-    r"([0-9a-zA-Z]{1}[0-9a-zA-Z]{1}[:]{1}){5}[0-9a-zA-Z]{1}[0-9a-zA-Z]{1}"
-);
-
-// wifiscanner-0.3.6: r"Signal level=(\d+)/100"
-consistent!(wifiscanner_2, r"Signal level=(\d+)/100");
-
-// bbcode-1.0.2: r"(?s)\[b\](.*?)\[/b\]"
-consistent!(bbcode_0, r"(?s)\[b\](.*?)\[/b\]");
-
-// bbcode-1.0.2: r"(?s)\[i\](.*?)\[/i\]"
-consistent!(bbcode_1, r"(?s)\[i\](.*?)\[/i\]");
-
-// bbcode-1.0.2: r"(?s)\[u\](.*?)\[/u\]"
-consistent!(bbcode_2, r"(?s)\[u\](.*?)\[/u\]");
-
-// bbcode-1.0.2: r"(?s)\[s\](.*?)\[/s\]"
-consistent!(bbcode_3, r"(?s)\[s\](.*?)\[/s\]");
-
-// bbcode-1.0.2: r"(?s)\[size=(\d+)](.*?)\[/size\]"
-consistent!(bbcode_4, r"(?s)\[size=(\d+)](.*?)\[/size\]");
-
-// bbcode-1.0.2: r"(?s)\[color=(.+)](.*?)\[/color\]"
-consistent!(bbcode_5, r"(?s)\[color=(.+)](.*?)\[/color\]");
-
-// bbcode-1.0.2: r"(?s)\[center\](.*?)\[/center\]"
-consistent!(bbcode_6, r"(?s)\[center\](.*?)\[/center\]");
-
-// bbcode-1.0.2: r"(?s)\[left\](.*?)\[/left\]"
-consistent!(bbcode_7, r"(?s)\[left\](.*?)\[/left\]");
-
-// bbcode-1.0.2: r"(?s)\[right\](.*?)\[/right\]"
-consistent!(bbcode_8, r"(?s)\[right\](.*?)\[/right\]");
-
-// bbcode-1.0.2: r"(?s)\[table\](.*?)\[/table\]"
-consistent!(bbcode_9, r"(?s)\[table\](.*?)\[/table\]");
-
-// bbcode-1.0.2: r"(?s)\[td\](.*?)\[/td\]"
-consistent!(bbcode_10, r"(?s)\[td\](.*?)\[/td\]");
-
-// bbcode-1.0.2: r"(?s)\[tr\](.*?)\[/tr\]"
-consistent!(bbcode_11, r"(?s)\[tr\](.*?)\[/tr\]");
-
-// bbcode-1.0.2: r"(?s)\[th\](.*?)\[/th\]"
-consistent!(bbcode_12, r"(?s)\[th\](.*?)\[/th\]");
-
-// bbcode-1.0.2: r"(?s)\[url\](.*?)\[/url\]"
-consistent!(bbcode_13, r"(?s)\[url\](.*?)\[/url\]");
-
-// bbcode-1.0.2: r"(?s)\[url=(.+)\](.*?)\[/url\]"
-consistent!(bbcode_14, r"(?s)\[url=(.+)\](.*?)\[/url\]");
-
-// bbcode-1.0.2: r"(?s)\[quote\](.*?)\[/quote\]"
-consistent!(bbcode_15, r"(?s)\[quote\](.*?)\[/quote\]");
-
-// bbcode-1.0.2: r"(?s)\[quote=(.+)\](.*?)\[/quote\]"
-consistent!(bbcode_16, r"(?s)\[quote=(.+)\](.*?)\[/quote\]");
-
-// bbcode-1.0.2: r"(?s)\[img=(\d+)x(\d+)(\b.*)?\](.*?)\[/img\]"
-consistent!(bbcode_17, r"(?s)\[img=(\d+)x(\d+)(\b.*)?\](.*?)\[/img\]");
-
-// bbcode-1.0.2: r"(?s)\[img=(.+)(\b.*)?\](.*?)\[/img\]"
-consistent!(bbcode_18, r"(?s)\[img=(.+)(\b.*)?\](.*?)\[/img\]");
-
-// bbcode-1.0.2: r"(?s)\[img(\b.*)?\](.*?)\[/img\]"
-consistent!(bbcode_19, r"(?s)\[img(\b.*)?\](.*?)\[/img\]");
-
-// bbcode-1.0.2: r"(?s)\[ol\](.*?)\[/ol\]"
-consistent!(bbcode_20, r"(?s)\[ol\](.*?)\[/ol\]");
-
-// bbcode-1.0.2: r"(?s)\[ul\](.*?)\[/ul\]"
-consistent!(bbcode_21, r"(?s)\[ul\](.*?)\[/ul\]");
-
-// bbcode-1.0.2: r"(?s)\[list\](.*?)\[/list\]"
-consistent!(bbcode_22, r"(?s)\[list\](.*?)\[/list\]");
-
-// bbcode-1.0.2: r"(?s)\[youtube\](.*?)\[/youtube\]"
-consistent!(bbcode_23, r"(?s)\[youtube\](.*?)\[/youtube\]");
-
-// bbcode-1.0.2: r"(?s)\[youtube=(\d+)x(\d+)\](.*?)\[/youtube\]"
-consistent!(bbcode_24, r"(?s)\[youtube=(\d+)x(\d+)\](.*?)\[/youtube\]");
-
-// bbcode-1.0.2: r"(?s)\[li\](.*?)\[/li\]"
-consistent!(bbcode_25, r"(?s)\[li\](.*?)\[/li\]");
-
-// block-utils-0.5.0: r"loop\d+"
-consistent!(block_utils_0, r"loop\d+");
-
-// block-utils-0.5.0: r"ram\d+"
-consistent!(block_utils_1, r"ram\d+");
-
-// block-utils-0.5.0: r"md\d+"
-consistent!(block_utils_2, r"md\d+");
-
-// kvvliveapi-0.1.0: r"^([1-9]) min$"
-consistent!(kvvliveapi_0, r"^([1-9]) min$");
-
-// rfc822_sanitizer-0.3.3: r"(\d{2}):(\d{2}):(\d{2})"
-consistent!(rfc822_sanitizer_0, r"(\d{2}):(\d{2}):(\d{2})");
-
-// rfc822_sanitizer-0.3.3: r"(\d{1,2}):(\d{1,2}):(\d{1,2})"
-consistent!(rfc822_sanitizer_1, r"(\d{1,2}):(\d{1,2}):(\d{1,2})");
-
-// faker-0.0.4: r"[2-9]"
-consistent!(faker_0, r"[2-9]");
-
-// faker-0.0.4: r"[1-9]"
-consistent!(faker_1, r"[1-9]");
-
-// faker-0.0.4: r"[0-9]"
-consistent!(faker_2, r"[0-9]");
-
-// faker-0.0.4: r"\d{10}"
-consistent!(faker_3, r"\d{10}");
-
-// faker-0.0.4: r"\d{1}"
-consistent!(faker_4, r"\d{1}");
-
-// faker-0.0.4: r"^\w+"
-consistent!(faker_5, r"^\w+");
-
-// faker-0.0.4: r"^\w+"
-consistent!(faker_6, r"^\w+");
-
-// faker-0.0.4: r"^(\w+\.? ?){2,3}$"
-consistent!(faker_7, r"^(\w+\.? ?){2,3}$");
-
-// faker-0.0.4: r"^[A-Z][a-z]+\.?$"
-consistent!(faker_8, r"^[A-Z][a-z]+\.?$");
-
-// faker-0.0.4: r"^[A-Z][A-Za-z]*\.?$"
-consistent!(faker_9, r"^[A-Z][A-Za-z]*\.?$");
-
-// faker-0.0.4: r"http://lorempixel.com/100/100/\w+"
-consistent!(faker_10, r"http://lorempixel.com/100/100/\w+");
-
-// faker-0.0.4: r"http://lorempixel.com/100/100/cats"
-consistent!(faker_11, r"http://lorempixel.com/100/100/cats");
-
-// fancy-regex-0.1.0: "(?i:ß)"
-consistent!(fancy_regex_0, "(?i:ß)");
-
-// fancy-regex-0.1.0: "(?i:\\x{0587})"
-consistent!(fancy_regex_1, "(?i:\\x{0587})");
-
-// fancy-regex-0.1.0: "^\\\\([!-/:-@\\[-`\\{-~aftnrv]|[0-7]{1,3}|x[0-9a-fA-F]{2}|x\\{[0-9a-fA-F]{1,6}\\})"
-consistent!(fancy_regex_2, "^\\\\([!-/:-@\\[-`\\{-~aftnrv]|[0-7]{1,3}|x[0-9a-fA-F]{2}|x\\{[0-9a-fA-F]{1,6}\\})");
-
-// fancy-prompt-0.1.5: r"/([^/])[^/]+/"
-consistent!(fancy_prompt_0, r"/([^/])[^/]+/");
-
-// fancy-prompt-0.1.5: r"^([^:]+):.*?(?::([^:]+))?$"
-consistent!(fancy_prompt_1, r"^([^:]+):.*?(?::([^:]+))?$");
-
-// fanta-0.2.0: r"^(/?__\w+__)/(.*)"
-consistent!(fanta_0, r"^(/?__\w+__)/(.*)");
-
-// fanta-cli-0.1.1: r"(.)([A-Z])"
-consistent!(fanta_cli_0, r"(.)([A-Z])");
-
-// fanta-cli-0.1.1: "\\{:[^\\s]+\\}"
-consistent!(fanta_cli_1, "\\{:[^\\s]+\\}");
-
-// amethyst_tools-0.7.1: "(?P<last>[^\r])\n"
-consistent!(amethyst_tools_0, "(?P<last>[^\r])\n");
-
-// amigo-0.3.1: r"^-?\d+(\.\d)?"
-consistent!(amigo_0, r"^-?\d+(\.\d)?");
-
-// amigo-0.3.1: r"^[a-zA-Z_]+[\w-]*[!?_]?"
-consistent!(amigo_1, r"^[a-zA-Z_]+[\w-]*[!?_]?");
-
-// amigo-0.3.1: r"^\("
-consistent!(amigo_2, r"^\(");
-
-// amigo-0.3.1: r"^\)"
-consistent!(amigo_3, r"^\)");
-
-// amigo-0.3.1: r"^\s+"
-consistent!(amigo_4, r"^\s+");
-
-// ethcore-logger-1.12.0: "\x1b\\[[^m]+m"
-consistent!(ethcore_logger_0, "\x1b\\[[^m]+m");
-
-// dash2html-1.0.1: r"__.*?__"
-consistent!(dash2html_0, r"__.*?__");
-
-// dash2html-1.0.1: r"(?i)@(?:time|clipboard|cursor|date)"
-consistent!(dash2html_1, r"(?i)@(?:time|clipboard|cursor|date)");
-
-// os_type-2.0.0: r"^Microsoft Windows \[Version\s(\d+\.\d+\.\d+)\]$"
-consistent!(os_type_0, r"^Microsoft Windows \[Version\s(\d+\.\d+\.\d+)\]$");
-
-// os_type-2.0.0: r"ProductName:\s([\w\s]+)\n"
-consistent!(os_type_1, r"ProductName:\s([\w\s]+)\n");
-
-// os_type-2.0.0: r"ProductVersion:\s(\w+\.\w+\.\w+)"
-consistent!(os_type_2, r"ProductVersion:\s(\w+\.\w+\.\w+)");
-
-// os_type-2.0.0: r"BuildVersion:\s(\w+)"
-consistent!(os_type_3, r"BuildVersion:\s(\w+)");
-
-// os_type-2.0.0: r"(\w+) Linux release"
-consistent!(os_type_4, r"(\w+) Linux release");
-
-// os_type-2.0.0: r"release\s([\w\.]+)"
-consistent!(os_type_5, r"release\s([\w\.]+)");
-
-// os_type-2.0.0: r"Distributor ID:\s(\w+)"
-consistent!(os_type_6, r"Distributor ID:\s(\w+)");
-
-// os_type-2.0.0: r"Release:\s([\w\.]+)"
-consistent!(os_type_7, r"Release:\s([\w\.]+)");
-
-// bindgen-0.37.0: r"typename type\-parameter\-\d+\-\d+::.+"
-consistent!(bindgen_0, r"typename type\-parameter\-\d+\-\d+::.+");
-
-// imap-0.8.1: "^+(.*)\r\n"
-consistent!(imap_0, "^+(.*)\r\n");
-
-// image-base64-0.1.0: r"^ffd8ffe0"
-consistent!(image_base64_0, r"^ffd8ffe0");
-
-// image-base64-0.1.0: r"^89504e47"
-consistent!(image_base64_1, r"^89504e47");
-
-// image-base64-0.1.0: r"^47494638"
-consistent!(image_base64_2, r"^47494638");
-
-// json-pointer-0.3.2: "^(/([^/~]|~[01])*)*$"
-consistent!(json_pointer_0, "^(/([^/~]|~[01])*)*$");
-
-// json-pointer-0.3.2: "^#(/([^/~%]|~[01]|%[0-9a-fA-F]{2})*)*$"
-consistent!(json_pointer_1, "^#(/([^/~%]|~[01]|%[0-9a-fA-F]{2})*)*$");
-
-// mysql_common-0.7.0: r"^5.5.5-(\d{1,2})\.(\d{1,2})\.(\d{1,3})-MariaDB"
-consistent!(mysql_common_0, r"^5.5.5-(\d{1,2})\.(\d{1,2})\.(\d{1,3})-MariaDB");
-
-// mysql_common-0.7.0: r"^(\d{1,2})\.(\d{1,2})\.(\d{1,3})(.*)"
-consistent!(mysql_common_1, r"^(\d{1,2})\.(\d{1,2})\.(\d{1,3})(.*)");
-
-// government_id-0.1.0: r"^[0-9]{4}[0-9A-Z]{2}[0-9]{3}$"
-consistent!(government_id_0, r"^[0-9]{4}[0-9A-Z]{2}[0-9]{3}$");
-
-// ohmers-0.1.1: r"UniqueIndexViolation: (\w+)"
-consistent!(ohmers_0, r"UniqueIndexViolation: (\w+)");
-
-// eliza-1.0.0: r"(.*) you are (.*)"
-consistent!(eliza_0, r"(.*) you are (.*)");
-
-// eliza-1.0.0: r"(.*) you are (.*)"
-consistent!(eliza_1, r"(.*) you are (.*)");
-
-// eliza-1.0.0: r"(.*) you are (.*)"
-consistent!(eliza_2, r"(.*) you are (.*)");
-
-// chema-0.0.5: "^\\s*\\*"
-consistent!(chema_0, "^\\s*\\*");
-
-// chema-0.0.5: "^\\s*@(\\w+)\\s+(.*)"
-consistent!(chema_1, "^\\s*@(\\w+)\\s+(.*)");
-
-// chord3-0.3.0: r"^\s*#"
-consistent!(chord3_0, r"^\s*#");
-
-// chord3-0.3.0: r"\{(?P<cmd>\w+)(?::?\s*(?P<arg>.*))?\}"
-consistent!(chord3_1, r"\{(?P<cmd>\w+)(?::?\s*(?P<arg>.*))?\}");
-
-// chord3-0.3.0: r"\{(eot|end_of_tab):?\s*"
-consistent!(chord3_2, r"\{(eot|end_of_tab):?\s*");
-
-// chord3-0.3.0: r"([^\[]*)(?:\[([^\]]*)\])?"
-consistent!(chord3_3, r"([^\[]*)(?:\[([^\]]*)\])?");
-
-// checkmail-0.1.1: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
-consistent!(checkmail_0, "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$");
-
-// cntk-0.2.1: r"\b\w\w+\b"
-consistent!(cntk_0, r"\b\w\w+\b");
-
-// cntk-0.2.1: r"\b\w\w+\b"
-consistent!(cntk_1, r"\b\w\w+\b");
-
-// cniguru-0.1.0: r"\(id: (\d+)\)"
-consistent!(cniguru_0, r"\(id: (\d+)\)");
-
-// upm_lib-0.3.0: r"^(\d+)\.(\d+)\.(\d+)(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?$"
-consistent!(upm_lib_0, r"^(\d+)\.(\d+)\.(\d+)(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?$");
-
-// avro-0.2.1: r"^\s*(\*+(\s+))?"
-consistent!(avro_0, r"^\s*(\*+(\s+))?");
-
-// avro-0.2.1: r"^\s*(\*+)?"
-consistent!(avro_1, r"^\s*(\*+)?");
-
-// nomi-0.0.2: "[0-9]+"
-consistent!(nomi_0, "[0-9]+");
-
-// nodes-0.1.0: "([0-9]+)@(?:nodes|n)?:([^@]+)?"
-consistent!(nodes_0, "([0-9]+)@(?:nodes|n)?:([^@]+)?");
-
-// not-stakkr-1.0.0: r"(?i)in (\d+) (second|minute|hour|day|week)s?"
-consistent!(not_stakkr_0, r"(?i)in (\d+) (second|minute|hour|day|week)s?");
-
-// notetxt-0.0.1: "^([A-Za-z0-9 -_:]+)\n-+\n"
-consistent!(notetxt_0, "^([A-Za-z0-9 -_:]+)\n-+\n");
-
-// nail-0.1.0-pre.0: r"^-?[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?$"
-consistent!(nail_0, r"^-?[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?$");
-
-// nail-0.1.0-pre.0: r"^-?[0-9]+$"
-consistent!(nail_1, r"^-?[0-9]+$");
-
-// askalono-0.2.0: r"[^\w\s\pP]+"
-consistent!(askalono_0, r"[^\w\s\pP]+");
-
-// askalono-0.2.0: r"(?x)[ \t\p{Zs} \\ / \| \x2044 ]+"
-consistent!(askalono_1, r"(?x)[ \t\p{Zs} \\ / \| \x2044 ]+");
-
-// askalono-0.2.0: r"\p{Pd}+"
-consistent!(askalono_2, r"\p{Pd}+");
-
-// askalono-0.2.0: r"\p{Ps}+"
-consistent!(askalono_3, r"\p{Ps}+");
-
-// askalono-0.2.0: r"\p{Pe}+"
-consistent!(askalono_4, r"\p{Pe}+");
-
-// askalono-0.2.0: r"\p{Pc}+"
-consistent!(askalono_5, r"\p{Pc}+");
-
-// askalono-0.2.0: r"[©Ⓒⓒ]"
-consistent!(askalono_6, r"[©Ⓒⓒ]");
-
-// askalono-0.2.0: r"[\r\n\v\f]"
-consistent!(askalono_7, r"[\r\n\v\f]");
-
-// askalono-0.2.0: r"\n{3,}"
-consistent!(askalono_8, r"\n{3,}");
-
-// askalono-0.2.0: r"[^\w\s]+"
-consistent!(askalono_9, r"[^\w\s]+");
-
-// askalono-0.2.0: r"\s+"
-consistent!(askalono_10, r"\s+");
-
-// assembunny_plus-0.0.3: r"[^0-9a-zA-Z_]"
-consistent!(assembunny_plus_0, r"[^0-9a-zA-Z_]");
-
-// assembunny_plus-0.0.3: r"[0-9]"
-consistent!(assembunny_plus_1, r"[0-9]");
-
-// salt-compressor-0.4.0: r"(?m)^Minion (\S*) did not respond\. No job will be sent\.$"
-consistent!(
-    salt_compressor_0,
-    r"(?m)^Minion (\S*) did not respond\. No job will be sent\.$"
-);
-
-// sabisabi-0.4.1: r"</?[^>]+?>"
-consistent!(sabisabi_0, r"</?[^>]+?>");
-
-// sabisabi-0.4.1: r"\([^)]*\)"
-consistent!(sabisabi_1, r"\([^)]*\)");
-
-// sassers-0.13.5-h28: "@import \"([^\"]*)\";"
-consistent!(sassers_0, "@import \"([^\"]*)\";");
-
-// shadowsocks-0.6.2: r"[A-Za-z\d-]{1,63}$"
-consistent!(shadowsocks_0, r"[A-Za-z\d-]{1,63}$");
-
-// shkeleton-0.1.5: "[abc]+"
-consistent!(shkeleton_0, "[abc]+");
-
-// shellwords-0.1.0: r"([^A-Za-z0-9_\-.,:/@\n])"
-consistent!(shellwords_0, r"([^A-Za-z0-9_\-.,:/@\n])");
-
-// shellwords-0.1.0: r"\n"
-consistent!(shellwords_1, r"\n");
-
-// shush-0.1.5: "(?P<num>[0-9]+)(?P<units>[dhms])"
-consistent!(shush_0, "(?P<num>[0-9]+)(?P<units>[dhms])");
-
-// woothee-0.8.0: r"(?:Chrome|CrMo|CriOS)/([.0-9]+)"
-consistent!(woothee_0, r"(?:Chrome|CrMo|CriOS)/([.0-9]+)");
-
-// woothee-0.8.0: r"Vivaldi/([.0-9]+)"
-consistent!(woothee_1, r"Vivaldi/([.0-9]+)");
-
-// woothee-0.8.0: r"Firefox/([.0-9]+)"
-consistent!(woothee_2, r"Firefox/([.0-9]+)");
-
-// woothee-0.8.0: r"^Mozilla/[.0-9]+ \((?:Mobile|Tablet);(?:.*;)? rv:([.0-9]+)\) Gecko/[.0-9]+ Firefox/[.0-9]+$"
-consistent!(woothee_3, r"^Mozilla/[.0-9]+ \((?:Mobile|Tablet);(?:.*;)? rv:([.0-9]+)\) Gecko/[.0-9]+ Firefox/[.0-9]+$");
-
-// woothee-0.8.0: r"FxiOS/([.0-9]+)"
-consistent!(woothee_4, r"FxiOS/([.0-9]+)");
-
-// woothee-0.8.0: r"\(([^;)]+);FOMA;"
-consistent!(woothee_5, r"\(([^;)]+);FOMA;");
-
-// woothee-0.8.0: r"jig browser[^;]+; ([^);]+)"
-consistent!(woothee_6, r"jig browser[^;]+; ([^);]+)");
-
-// woothee-0.8.0: r"(?i)rss(?:reader|bar|[-_ /;()]|[ +]*/)"
-consistent!(woothee_7, r"(?i)rss(?:reader|bar|[-_ /;()]|[ +]*/)");
-
-// woothee-0.8.0: r"(?i)(?:bot|crawler|spider)(?:[-_ ./;@()]|$)"
-consistent!(woothee_8, r"(?i)(?:bot|crawler|spider)(?:[-_ ./;@()]|$)");
-
-// woothee-0.8.0: r"(?i)(?:feed|web) ?parser"
-consistent!(woothee_9, r"(?i)(?:feed|web) ?parser");
-
-// woothee-0.8.0: r"(?i)watch ?dog"
-consistent!(woothee_10, r"(?i)watch ?dog");
-
-// woothee-0.8.0: r"Edge/([.0-9]+)"
-consistent!(woothee_11, r"Edge/([.0-9]+)");
-
-// woothee-0.8.0: r"MSIE ([.0-9]+);"
-consistent!(woothee_12, r"MSIE ([.0-9]+);");
-
-// woothee-0.8.0: r"Version/([.0-9]+)"
-consistent!(woothee_13, r"Version/([.0-9]+)");
-
-// woothee-0.8.0: r"Opera[/ ]([.0-9]+)"
-consistent!(woothee_14, r"Opera[/ ]([.0-9]+)");
-
-// woothee-0.8.0: r"OPR/([.0-9]+)"
-consistent!(woothee_15, r"OPR/([.0-9]+)");
-
-// woothee-0.8.0: r"Version/([.0-9]+)"
-consistent!(woothee_16, r"Version/([.0-9]+)");
-
-// woothee-0.8.0: r"(?:SoftBank|Vodafone|J-PHONE)/[.0-9]+/([^ /;()]+)"
-consistent!(woothee_17, r"(?:SoftBank|Vodafone|J-PHONE)/[.0-9]+/([^ /;()]+)");
-
-// woothee-0.8.0: r"Trident/([.0-9]+);"
-consistent!(woothee_18, r"Trident/([.0-9]+);");
-
-// woothee-0.8.0: r" rv:([.0-9]+)"
-consistent!(woothee_19, r" rv:([.0-9]+)");
-
-// woothee-0.8.0: r"IEMobile/([.0-9]+);"
-consistent!(woothee_20, r"IEMobile/([.0-9]+);");
-
-// woothee-0.8.0: r"(?:WILLCOM|DDIPOCKET);[^/]+/([^ /;()]+)"
-consistent!(woothee_21, r"(?:WILLCOM|DDIPOCKET);[^/]+/([^ /;()]+)");
-
-// woothee-0.8.0: r"Windows ([ .a-zA-Z0-9]+)[;\\)]"
-consistent!(woothee_22, r"Windows ([ .a-zA-Z0-9]+)[;\\)]");
-
-// woothee-0.8.0: r"^Phone(?: OS)? ([.0-9]+)"
-consistent!(woothee_23, r"^Phone(?: OS)? ([.0-9]+)");
-
-// woothee-0.8.0: r"iP(hone;|ad;|od) .*like Mac OS X"
-consistent!(woothee_24, r"iP(hone;|ad;|od) .*like Mac OS X");
-
-// woothee-0.8.0: r"Version/([.0-9]+)"
-consistent!(woothee_25, r"Version/([.0-9]+)");
-
-// woothee-0.8.0: r"rv:(\d+\.\d+\.\d+)"
-consistent!(woothee_26, r"rv:(\d+\.\d+\.\d+)");
-
-// woothee-0.8.0: r"FreeBSD ([^;\)]+);"
-consistent!(woothee_27, r"FreeBSD ([^;\)]+);");
-
-// woothee-0.8.0: r"CrOS ([^\)]+)\)"
-consistent!(woothee_28, r"CrOS ([^\)]+)\)");
-
-// woothee-0.8.0: r"Android[- ](\d+\.\d+(?:\.\d+)?)"
-consistent!(woothee_29, r"Android[- ](\d+\.\d+(?:\.\d+)?)");
-
-// woothee-0.8.0: r"PSP \(PlayStation Portable\); ([.0-9]+)\)"
-consistent!(woothee_30, r"PSP \(PlayStation Portable\); ([.0-9]+)\)");
-
-// woothee-0.8.0: r"PLAYSTATION 3;? ([.0-9]+)\)"
-consistent!(woothee_31, r"PLAYSTATION 3;? ([.0-9]+)\)");
-
-// woothee-0.8.0: r"PlayStation Vita ([.0-9]+)\)"
-consistent!(woothee_32, r"PlayStation Vita ([.0-9]+)\)");
-
-// woothee-0.8.0: r"PlayStation 4 ([.0-9]+)\)"
-consistent!(woothee_33, r"PlayStation 4 ([.0-9]+)\)");
-
-// woothee-0.8.0: r"BB10(?:.+)Version/([.0-9]+) "
-consistent!(woothee_34, r"BB10(?:.+)Version/([.0-9]+) ");
-
-// woothee-0.8.0: r"BlackBerry(?:\d+)/([.0-9]+) "
-consistent!(woothee_35, r"BlackBerry(?:\d+)/([.0-9]+) ");
-
-// woothee-0.8.0: r"; CPU(?: iPhone)? OS (\d+_\d+(?:_\d+)?) like Mac OS X"
-consistent!(
-    woothee_36,
-    r"; CPU(?: iPhone)? OS (\d+_\d+(?:_\d+)?) like Mac OS X"
-);
-
-// woothee-0.8.0: r"Mac OS X (10[._]\d+(?:[._]\d+)?)(?:\)|;)"
-consistent!(woothee_37, r"Mac OS X (10[._]\d+(?:[._]\d+)?)(?:\)|;)");
-
-// woothee-0.8.0: r"^(?:Apache-HttpClient/|Jakarta Commons-HttpClient/|Java/)"
-consistent!(
-    woothee_38,
-    r"^(?:Apache-HttpClient/|Jakarta Commons-HttpClient/|Java/)"
-);
-
-// woothee-0.8.0: r"[- ]HttpClient(/|$)"
-consistent!(woothee_39, r"[- ]HttpClient(/|$)");
-
-// woothee-0.8.0: r"^(?:PHP|WordPress|CakePHP|PukiWiki|PECL::HTTP)(?:/| |$)"
-consistent!(
-    woothee_40,
-    r"^(?:PHP|WordPress|CakePHP|PukiWiki|PECL::HTTP)(?:/| |$)"
-);
-
-// woothee-0.8.0: r"(?:PEAR HTTP_Request|HTTP_Request)(?: class|2)"
-consistent!(woothee_41, r"(?:PEAR HTTP_Request|HTTP_Request)(?: class|2)");
-
-// woothee-0.8.0: r"(?:Rome Client |UnwindFetchor/|ia_archiver |Summify |PostRank/)"
-consistent!(
-    woothee_42,
-    r"(?:Rome Client |UnwindFetchor/|ia_archiver |Summify |PostRank/)"
-);
-
-// woothee-0.8.0: r"Sleipnir/([.0-9]+)"
-consistent!(woothee_43, r"Sleipnir/([.0-9]+)");
-
-// word_replace-0.0.3: r"@@[a-z|A-Z|\d]+@@"
-consistent!(word_replace_0, r"@@[a-z|A-Z|\d]+@@");
-
-// wordcount-0.1.0: r"\w+"
-consistent!(wordcount_0, r"\w+");
-
-// just-0.3.12: "^([^=]+)=(.*)$"
-consistent!(just_0, "^([^=]+)=(.*)$");
-
-// emote-0.1.0: r":[a-zA-Z_]+?:"
-consistent!(emote_0, r":[a-zA-Z_]+?:");
-
-// emojicons-1.0.1: r":([a-zA-Z0-9_+-]+):"
-consistent!(emojicons_0, r":([a-zA-Z0-9_+-]+):");
-
-// git2_codecommit-0.1.2: r"git-codecommit\.([a-z0-9-]+)\.amazonaws\.com"
-consistent!(
-    git2_codecommit_0,
-    r"git-codecommit\.([a-z0-9-]+)\.amazonaws\.com"
-);
-
-// git-workarea-3.1.2: r"^submodule\.(?P<name>.*)\.(?P<key>[^=]*)=(?P<value>.*)$"
-consistent!(
-    git_workarea_0,
-    r"^submodule\.(?P<name>.*)\.(?P<key>[^=]*)=(?P<value>.*)$"
-);
-
-// git-shell-enforce-directory-1.0.0: r"^(?P<command>git-(?:receive|upload)-pack) '(?P<path>.+)'$"
-consistent!(
-    git_shell_enforce_directory_0,
-    r"^(?P<command>git-(?:receive|upload)-pack) '(?P<path>.+)'$"
-);
-
-// git-journal-1.6.3: r"[ \n]:(.*?):"
-consistent!(git_journal_0, r"[ \n]:(.*?):");
-
-// git-find-0.3.2: r"^git@(?P<host>[[:alnum:]\._-]+):(?P<path>[[:alnum:]\._\-/]+).git$"
-consistent!(
-    git_find_0,
-    r"^git@(?P<host>[[:alnum:]\._-]+):(?P<path>[[:alnum:]\._\-/]+).git$"
-);
-
-// gitlab-api-0.6.0: r"private_token=\w{20}"
-consistent!(gitlab_api_0, r"private_token=\w{20}");
-
-// td-client-0.7.0: "^(http://|https://)"
-consistent!(td_client_0, "^(http://|https://)");
-
-// karaconv-0.3.0: r"--(?P<type>[a-zA-Z]+)-- (?P<contents>.*)"
-consistent!(karaconv_0, r"--(?P<type>[a-zA-Z]+)-- (?P<contents>.*)");
-
-// katana-1.0.2: r"(?P<comp>et al\.)(?:\.)"
-consistent!(katana_0, r"(?P<comp>et al\.)(?:\.)");
-
-// katana-1.0.2: r"\.{3}"
-consistent!(katana_1, r"\.{3}");
-
-// katana-1.0.2: r"(?P<number>[0-9]+)\.(?P<decimal>[0-9]+)"
-consistent!(katana_2, r"(?P<number>[0-9]+)\.(?P<decimal>[0-9]+)");
-
-// katana-1.0.2: r"\s\.(?P<nums>[0-9]+)"
-consistent!(katana_3, r"\s\.(?P<nums>[0-9]+)");
-
-// katana-1.0.2: r"(?:[A-Za-z]\.){2,}"
-consistent!(katana_4, r"(?:[A-Za-z]\.){2,}");
-
-// katana-1.0.2: r"(?P<init>[A-Z])(?P<point>\.)"
-consistent!(katana_5, r"(?P<init>[A-Z])(?P<point>\.)");
-
-// katana-1.0.2: r"(?P<title>[A-Z][a-z]{1,3})(\.)"
-consistent!(katana_6, r"(?P<title>[A-Z][a-z]{1,3})(\.)");
-
-// katana-1.0.2: r"&==&(?P<p>[.!?])"
-consistent!(katana_7, r"&==&(?P<p>[.!?])");
-
-// katana-1.0.2: r"&\^&(?P<p>[.!?])"
-consistent!(katana_8, r"&\^&(?P<p>[.!?])");
-
-// katana-1.0.2: r"&\*\*&(?P<p>[.!?])"
-consistent!(katana_9, r"&\*\*&(?P<p>[.!?])");
-
-// katana-1.0.2: r"&=&(?P<p>[.!?])"
-consistent!(katana_10, r"&=&(?P<p>[.!?])");
-
-// katana-1.0.2: r"&##&(?P<p>[.!?])"
-consistent!(katana_11, r"&##&(?P<p>[.!?])");
-
-// katana-1.0.2: r"&\$&(?P<p>[.!?])"
-consistent!(katana_12, r"&\$&(?P<p>[.!?])");
-
-// kailua_syntax-1.1.0: r"@(?:_|\d+(?:/\d+(?:-\d+)?)?)"
-consistent!(kailua_syntax_0, r"@(?:_|\d+(?:/\d+(?:-\d+)?)?)");
-
-// kailua_syntax-1.1.0: r"<(\d+)>"
-consistent!(kailua_syntax_1, r"<(\d+)>");
-
-// ftp-3.0.1: r"\((\d+),(\d+),(\d+),(\d+),(\d+),(\d+)\)"
-consistent!(ftp_0, r"\((\d+),(\d+),(\d+),(\d+),(\d+),(\d+)\)");
-
-// ftp-3.0.1: r"\b(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\b"
-consistent!(ftp_1, r"\b(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\b");
-
-// ftp-3.0.1: r"\s+(\d+)\s*$"
-consistent!(ftp_2, r"\s+(\d+)\s*$");
-
-// vat-0.1.0: r"<countryCode>(.*?)</countryCode>"
-consistent!(vat_0, r"<countryCode>(.*?)</countryCode>");
-
-// vat-0.1.0: r"<vatNumber>(.*?)</vatNumber>"
-consistent!(vat_1, r"<vatNumber>(.*?)</vatNumber>");
-
-// vat-0.1.0: r"<name>(.*?)</name>"
-consistent!(vat_2, r"<name>(.*?)</name>");
-
-// vat-0.1.0: r"<address>(?s)(.*?)(?-s)</address>"
-consistent!(vat_3, r"<address>(?s)(.*?)(?-s)</address>");
-
-// vat-0.1.0: r"<valid>(true|false)</valid>"
-consistent!(vat_4, r"<valid>(true|false)</valid>");
-
-// vat-0.1.0: r"^ATU\d{8}$"
-consistent!(vat_5, r"^ATU\d{8}$");
-
-// vat-0.1.0: r"^BE0?\d{9, 10}$"
-consistent!(vat_6, r"^BE0?\d{9, 10}$");
-
-// vat-0.1.0: r"^BG\d{9,10}$"
-consistent!(vat_7, r"^BG\d{9,10}$");
-
-// vat-0.1.0: r"^HR\d{11}$"
-consistent!(vat_8, r"^HR\d{11}$");
-
-// vat-0.1.0: r"^CY\d{8}[A-Z]$"
-consistent!(vat_9, r"^CY\d{8}[A-Z]$");
-
-// vat-0.1.0: r"^CZ\d{8,10}$"
-consistent!(vat_10, r"^CZ\d{8,10}$");
-
-// vat-0.1.0: r"^DK\d{8}$"
-consistent!(vat_11, r"^DK\d{8}$");
-
-// vat-0.1.0: r"^EE\d{9}$"
-consistent!(vat_12, r"^EE\d{9}$");
-
-// vat-0.1.0: r"^FI\d{8}$"
-consistent!(vat_13, r"^FI\d{8}$");
-
-// vat-0.1.0: r"^FR[A-HJ-NP-Z0-9][A-HJ-NP-Z0-9]\d{9}$"
-consistent!(vat_14, r"^FR[A-HJ-NP-Z0-9][A-HJ-NP-Z0-9]\d{9}$");
-
-// vat-0.1.0: r"^DE\d{9}$"
-consistent!(vat_15, r"^DE\d{9}$");
-
-// vat-0.1.0: r"^EL\d{9}$"
-consistent!(vat_16, r"^EL\d{9}$");
-
-// vat-0.1.0: r"^HU\d{8}$"
-consistent!(vat_17, r"^HU\d{8}$");
-
-// vat-0.1.0: r"^IE\d[A-Z0-9\+\*]\d{5}[A-Z]{1,2}$"
-consistent!(vat_18, r"^IE\d[A-Z0-9\+\*]\d{5}[A-Z]{1,2}$");
-
-// vat-0.1.0: r"^IT\d{11}$"
-consistent!(vat_19, r"^IT\d{11}$");
-
-// vat-0.1.0: r"^LV\d{11}$"
-consistent!(vat_20, r"^LV\d{11}$");
-
-// vat-0.1.0: r"^LT(\d{9}|\d{12})$"
-consistent!(vat_21, r"^LT(\d{9}|\d{12})$");
-
-// vat-0.1.0: r"^LU\d{8}$"
-consistent!(vat_22, r"^LU\d{8}$");
-
-// vat-0.1.0: r"^MT\d{8}$"
-consistent!(vat_23, r"^MT\d{8}$");
-
-// vat-0.1.0: r"^NL\d{9}B\d{2}$"
-consistent!(vat_24, r"^NL\d{9}B\d{2}$");
-
-// vat-0.1.0: r"^PL\d{10}$"
-consistent!(vat_25, r"^PL\d{10}$");
-
-// vat-0.1.0: r"^PT\d{9}$"
-consistent!(vat_26, r"^PT\d{9}$");
-
-// vat-0.1.0: r"^RO\d{2,10}$"
-consistent!(vat_27, r"^RO\d{2,10}$");
-
-// vat-0.1.0: r"^SK\d{10}$"
-consistent!(vat_28, r"^SK\d{10}$");
-
-// vat-0.1.0: r"^SI\d{8}$"
-consistent!(vat_29, r"^SI\d{8}$");
-
-// vat-0.1.0: r"^ES[A-Z0-9]\d{7}[A-Z0-9]$"
-consistent!(vat_30, r"^ES[A-Z0-9]\d{7}[A-Z0-9]$");
-
-// vat-0.1.0: r"^SE\d{10}01$"
-consistent!(vat_31, r"^SE\d{10}01$");
-
-// vat-0.1.0: r"^(GB(GD|HA)\d{3}|GB\d{9}|GB\d{12})$"
-consistent!(vat_32, r"^(GB(GD|HA)\d{3}|GB\d{9}|GB\d{12})$");
-
-// eve-0.1.1: r"\{\{(.*)\}\}"
-consistent!(eve_0, r"\{\{(.*)\}\}");
-
-// egc-0.1.2: "^mio"
-consistent!(egc_0, "^mio");
-
-// pew-0.2.3: ""
-consistent!(pew_0, "");
-
-// pew-0.2.3: ""
-consistent!(pew_1, "");
-
-// mob-0.4.3: "y"
-consistent!(mob_0, "y");
-
-// lit-0.2.8: "@([a-z]+)"
-consistent!(lit_0, "@([a-z]+)");
-
-// lit-0.2.8: "([A-Z-]+):(.*)"
-consistent!(lit_1, "([A-Z-]+):(.*)");
-
-// lit-0.2.8: "^[a-zA-Z_][a-zA-Z0-9_]*$"
-consistent!(lit_2, "^[a-zA-Z_][a-zA-Z0-9_]*$");
-
-// avm-1.0.1: r"\d+\.\d+\.\d+"
-consistent!(avm_0, r"\d+\.\d+\.\d+");
-
-// avm-1.0.1: r"\d+\.\d+\.\d+"
-consistent!(avm_1, r"\d+\.\d+\.\d+");
-
-// orm-0.2.0: r"^Vec<(.+)>$"
-consistent!(orm_0, r"^Vec<(.+)>$");
-
-// sgf-0.1.5: r"\\(\r\n|\n\r|\n|\r)"
-consistent!(sgf_0, r"\\(\r\n|\n\r|\n|\r)");
-
-// sgf-0.1.5: r"\\(.)"
-consistent!(sgf_1, r"\\(.)");
-
-// sgf-0.1.5: r"\r\n|\n\r|\n|\r"
-consistent!(sgf_2, r"\r\n|\n\r|\n|\r");
-
-// sgf-0.1.5: r"([\]\\:])"
-consistent!(sgf_3, r"([\]\\:])");
-
-// dok-0.2.0: "^Bearer realm=\"(.+?)\",service=\"(.+?)\",scope=\"(.+?)\"$"
-consistent!(
-    dok_0,
-    "^Bearer realm=\"(.+?)\",service=\"(.+?)\",scope=\"(.+?)\"$"
-);
-
-// d20-0.1.0: r"([+-]?\s*\d+[dD]\d+|[+-]?\s*\d+)"
-consistent!(d20_0, r"([+-]?\s*\d+[dD]\d+|[+-]?\s*\d+)");
-
-// dvb-0.3.0: "E"
-consistent!(dvb_0, "E");
-
-// dvb-0.3.0: "^F"
-consistent!(dvb_1, "^F");
-
-// dvb-0.3.0: "^S"
-consistent!(dvb_2, "^S");
-
-// ger-0.2.0: r"Change-Id: (I[a-f0-9]{40})$"
-consistent!(ger_0, r"Change-Id: (I[a-f0-9]{40})$");
-
-// ger-0.2.0: r"(refs|ref|fix|fixes|close|closes)\s+([A-Z]{2,5}-[0-9]{1,5})$"
-consistent!(
-    ger_1,
-    r"(refs|ref|fix|fixes|close|closes)\s+([A-Z]{2,5}-[0-9]{1,5})$"
-);
-
-// n5-0.2.1: r"(\d+)(\.(\d+))?(\.(\d+))?(.*)"
-consistent!(n5_0, r"(\d+)(\.(\d+))?(\.(\d+))?(.*)");
-
-// po-0.1.4: r"[A-Za-z0-9]"
-consistent!(po_0, r"[A-Za-z0-9]");
-
-// carnix-0.8.5: "path is (‘|')?([^’'\n]*)(’|')?"
-consistent!(carnix_0, "path is (‘|')?([^’'\n]*)(’|')?");
-
-// carnix-0.8.5: r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?(.*)?"
-consistent!(carnix_1, r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?(.*)?");
-
-// carnix-0.8.5: r"(\d*)\.(\d*)\.(\d*)(-(\S*))?"
-consistent!(carnix_2, r"(\d*)\.(\d*)\.(\d*)(-(\S*))?");
-
-// carnix-0.8.5: r"(\S*)-(\d*)\.(\d*)\.(\d*)(-(\S*))?"
-consistent!(carnix_3, r"(\S*)-(\d*)\.(\d*)\.(\d*)(-(\S*))?");
-
-// caseless-0.2.1: r"^# CaseFolding-(\d+)\.(\d+)\.(\d+).txt$"
-consistent!(caseless_0, r"^# CaseFolding-(\d+)\.(\d+)\.(\d+).txt$");
-
-// caseless-0.2.1: r"^([0-9A-F]+); [CF]; ([0-9A-F ]+);"
-consistent!(caseless_1, r"^([0-9A-F]+); [CF]; ([0-9A-F ]+);");
-
-// cabot-0.2.0: "\r?\n\r?\n"
-consistent!(cabot_0, "\r?\n\r?\n");
-
-// cabot-0.2.0: "\r?\n"
-consistent!(cabot_1, "\r?\n");
-
-// card-validate-2.2.1: r"^600"
-consistent!(card_validate_0, r"^600");
-
-// card-validate-2.2.1: r"^5019"
-consistent!(card_validate_1, r"^5019");
-
-// card-validate-2.2.1: r"^4"
-consistent!(card_validate_2, r"^4");
-
-// card-validate-2.2.1: r"^(5[1-5]|2[2-7])"
-consistent!(card_validate_3, r"^(5[1-5]|2[2-7])");
-
-// card-validate-2.2.1: r"^3[47]"
-consistent!(card_validate_4, r"^3[47]");
-
-// card-validate-2.2.1: r"^3[0689]"
-consistent!(card_validate_5, r"^3[0689]");
-
-// card-validate-2.2.1: r"^6([045]|22)"
-consistent!(card_validate_6, r"^6([045]|22)");
-
-// card-validate-2.2.1: r"^(62|88)"
-consistent!(card_validate_7, r"^(62|88)");
-
-// card-validate-2.2.1: r"^35"
-consistent!(card_validate_8, r"^35");
-
-// card-validate-2.2.1: r"^[0-9]+$"
-consistent!(card_validate_9, r"^[0-9]+$");
-
-// cargo-testify-0.3.0: r"\d{1,} passed.*filtered out"
-consistent!(cargo_testify_0, r"\d{1,} passed.*filtered out");
-
-// cargo-testify-0.3.0: r"error(:|\[).*"
-consistent!(cargo_testify_1, r"error(:|\[).*");
-
-// cargo-wix-0.0.5: r"<(.*?)>"
-consistent!(cargo_wix_0, r"<(.*?)>");
-
-// cargo-wix-0.0.5: r"<(.*?)>"
-consistent!(cargo_wix_1, r"<(.*?)>");
-
-// cargo-wix-0.0.5: r"<(.*?)>"
-consistent!(cargo_wix_2, r"<(.*?)>");
-
-// cargo-wix-0.0.5: r"<(.*?)>"
-consistent!(cargo_wix_3, r"<(.*?)>");
-
-// cargo-incremental-0.1.23: r"(?m)^incremental: re-using (\d+) out of (\d+) modules$"
-consistent!(
-    cargo_incremental_0,
-    r"(?m)^incremental: re-using (\d+) out of (\d+) modules$"
-);
-
-// cargo-incremental-0.1.23: "(?m)(warning|error): (.*)\n  --> ([^:]:\\d+:\\d+)$"
-consistent!(
-    cargo_incremental_1,
-    "(?m)(warning|error): (.*)\n  --> ([^:]:\\d+:\\d+)$"
-);
-
-// cargo-incremental-0.1.23: r"(?m)^test (.*) \.\.\. (\w+)"
-consistent!(cargo_incremental_2, r"(?m)^test (.*) \.\.\. (\w+)");
-
-// cargo-incremental-0.1.23: r"(?m)(\d+) passed; (\d+) failed; (\d+) ignored; \d+ measured"
-consistent!(
-    cargo_incremental_3,
-    r"(?m)(\d+) passed; (\d+) failed; (\d+) ignored; \d+ measured"
-);
-
-// cargo-testjs-0.1.2: r"^[^-]+-[0-9a-f]+\.js$"
-consistent!(cargo_testjs_0, r"^[^-]+-[0-9a-f]+\.js$");
-
-// cargo-tarpaulin-0.6.2: r"\s*//"
-consistent!(cargo_tarpaulin_0, r"\s*//");
-
-// cargo-tarpaulin-0.6.2: r"/\*"
-consistent!(cargo_tarpaulin_1, r"/\*");
-
-// cargo-tarpaulin-0.6.2: r"\*/"
-consistent!(cargo_tarpaulin_2, r"\*/");
-
-// cargo-culture-kit-0.1.0: r"^fo"
-consistent!(cargo_culture_kit_0, r"^fo");
-
-// cargo-screeps-0.1.3: "\\s+"
-consistent!(cargo_screeps_0, "\\s+");
-
-// cargo-brew-0.1.4: r"`(\S+) v([0-9.]+)"
-consistent!(cargo_brew_0, r"`(\S+) v([0-9.]+)");
-
-// cargo-release-0.10.2: "^\\[.+\\]"
-consistent!(cargo_release_0, "^\\[.+\\]");
-
-// cargo-release-0.10.2: "^\\[\\[.+\\]\\]"
-consistent!(cargo_release_1, "^\\[\\[.+\\]\\]");
-
-// cargo-edit-0.3.0-beta.1: r"^https://github.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$"
-consistent!(
-    cargo_edit_0,
-    r"^https://github.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$"
-);
-
-// cargo-edit-0.3.0-beta.1: r"^https://gitlab.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$"
-consistent!(
-    cargo_edit_1,
-    r"^https://gitlab.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$"
-);
-
-// cargo-disassemble-0.1.1: ".*"
-consistent!(cargo_disassemble_0, ".*");
-
-// cargo-demangle-0.1.2: r"(?m)(?P<symbol>_ZN[0-9]+.*E)"
-consistent!(cargo_demangle_0, r"(?m)(?P<symbol>_ZN[0-9]+.*E)");
-
-// cargo-coverage-annotations-0.1.5: r"^\s*\}(?:\)*;?|\s*else\s*\{)$"
-consistent!(cargo_coverage_annotations_0, r"^\s*\}(?:\)*;?|\s*else\s*\{)$");
-
-// cargo-urlcrate-1.0.1: "[\u{001b}\u{009b}][\\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]"
-consistent!(cargo_urlcrate_0, "[\u{001b}\u{009b}][\\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]");
-
-// cargo-script-0.2.8: r"^\s*\*( |$)"
-consistent!(cargo_script_0, r"^\s*\*( |$)");
-
-// cargo-script-0.2.8: r"^(\s+)"
-consistent!(cargo_script_1, r"^(\s+)");
-
-// cargo-script-0.2.8: r"/\*|\*/"
-consistent!(cargo_script_2, r"/\*|\*/");
-
-// cargo-script-0.2.8: r"^\s*//!"
-consistent!(cargo_script_3, r"^\s*//!");
-
-// cargo-script-0.2.8: r"^#![^\[].*?(\r\n|\n)"
-consistent!(cargo_script_4, r"^#![^\[].*?(\r\n|\n)");
-
-// cargo-update-1.5.2: r"cargo-install-update\.exe-v.+"
-consistent!(cargo_update_0, r"cargo-install-update\.exe-v.+");
-
-// canteen-0.4.1: r"^<(?:(int|uint|str|float|path):)?([\w_][a-zA-Z0-9_]*)>$"
-consistent!(
-    canteen_0,
-    r"^<(?:(int|uint|str|float|path):)?([\w_][a-zA-Z0-9_]*)>$"
-);
-
-// thruster-cli-0.1.3: r"(.)([A-Z])"
-consistent!(thruster_cli_0, r"(.)([A-Z])");
-
-// thieves-cant-0.1.0: "([Z]+)$"
-consistent!(thieves_cant_0, "([Z]+)$");
-
-// codeowners-0.1.3: r"^@\S+/\S+"
-consistent!(codeowners_0, r"^@\S+/\S+");
-
-// codeowners-0.1.3: r"^@\S+"
-consistent!(codeowners_1, r"^@\S+");
-
-// codeowners-0.1.3: r"^\S+@\S+"
-consistent!(codeowners_2, r"^\S+@\S+");
-
-// conserve-0.4.2: r"^b0000 {21} complete   20[-0-9T:+]+\s +\d+s\n$"
-consistent!(conserve_0, r"^b0000 {21} complete   20[-0-9T:+]+\s +\d+s\n$");
-
-// commodore-0.3.0: r"(?P<greeting>\S+?) (?P<name>\S+?)$"
-consistent!(commodore_0, r"(?P<greeting>\S+?) (?P<name>\S+?)$");
-
-// corollary-0.3.0: r"([ \t]*)```haskell([\s\S]*?)```"
-consistent!(corollary_0, r"([ \t]*)```haskell([\s\S]*?)```");
-
-// corollary-0.3.0: r"\b((?:a|b|t)\d*)\b"
-consistent!(corollary_1, r"\b((?:a|b|t)\d*)\b");
-
-// colorizex-0.1.3: "NB"
-consistent!(colorizex_0, "NB");
-
-// colorstring-0.0.1: r"(?i)\[[a-z0-9_-]+\]"
-consistent!(colorstring_0, r"(?i)\[[a-z0-9_-]+\]");
-
-// colorstring-0.0.1: r"^(?i)(\[[a-z0-9_-]+\])+"
-consistent!(colorstring_1, r"^(?i)(\[[a-z0-9_-]+\])+");
-
-// cosmogony-0.3.0: "name:(.+)"
-consistent!(cosmogony_0, "name:(.+)");
-
-// cobalt-bin-0.12.1: r"(?m:^ {0,3}\[[^\]]+\]:.+$)"
-consistent!(cobalt_bin_0, r"(?m:^ {0,3}\[[^\]]+\]:.+$)");
-
-// comrak-0.2.12: r"[^\p{L}\p{M}\p{N}\p{Pc} -]"
-consistent!(comrak_0, r"[^\p{L}\p{M}\p{N}\p{Pc} -]");
-
-// content-blocker-0.2.3: ""
-consistent!(content_blocker_0, "");
-
-// content-blocker-0.2.3: "(?i)hi"
-consistent!(content_blocker_1, "(?i)hi");
-
-// content-blocker-0.2.3: "http[s]?://domain.org"
-consistent!(content_blocker_2, "http[s]?://domain.org");
-
-// content-blocker-0.2.3: "(?i)http[s]?://domain.org"
-consistent!(content_blocker_3, "(?i)http[s]?://domain.org");
-
-// content-blocker-0.2.3: "http://domain.org"
-consistent!(content_blocker_4, "http://domain.org");
-
-// content-blocker-0.2.3: "http://domain.org"
-consistent!(content_blocker_5, "http://domain.org");
-
-// content-blocker-0.2.3: "ad.html"
-consistent!(content_blocker_6, "ad.html");
-
-// content-blocker-0.2.3: "ad.html"
-consistent!(content_blocker_7, "ad.html");
-
-// content-blocker-0.2.3: "http://domain.org"
-consistent!(content_blocker_8, "http://domain.org");
-
-// content-blocker-0.2.3: "http://domain.org/nocookies.sjs"
-consistent!(content_blocker_9, "http://domain.org/nocookies.sjs");
-
-// content-blocker-0.2.3: "http://domain.org/nocookies.sjs"
-consistent!(content_blocker_10, "http://domain.org/nocookies.sjs");
-
-// content-blocker-0.2.3: "http://domain.org/hideme.jpg"
-consistent!(content_blocker_11, "http://domain.org/hideme.jpg");
-
-// content-blocker-0.2.3: "http://domain.org/ok.html"
-consistent!(content_blocker_12, "http://domain.org/ok.html");
-
-// content-blocker-0.2.3: "http://domain.org/ok.html\\?except_this=1"
-consistent!(content_blocker_13, "http://domain.org/ok.html\\?except_this=1");
-
-// victoria-dom-0.1.2: "[A-Za-z0-9=]"
-consistent!(victoria_dom_0, "[A-Za-z0-9=]");
-
-// numbat-1.0.0: r"^nsq://"
-consistent!(numbat_0, r"^nsq://");
-
-// airkorea-0.1.2: r"[\s\t\r\n]"
-consistent!(airkorea_0, r"[\s\t\r\n]");
-
-// airkorea-0.1.2: r"([\{\[,])|([\}\]])"
-consistent!(airkorea_1, r"([\{\[,])|([\}\]])");
-
-// airkorea-0.1.2: r"[^.\d]+$"
-consistent!(airkorea_2, r"[^.\d]+$");
-
-// rofl-0.0.1: r"\b"
-// consistent!(rofl_0, r"\b");
-
-// rogcat-0.2.15: r"--------- beginning of.*"
-consistent!(rogcat_0, r"--------- beginning of.*");
-
-// rogcat-0.2.15: r"a|e|i|o|u"
-consistent!(rogcat_1, r"a|e|i|o|u");
-
-// rogcat-0.2.15: r"^(\d+)([kMG])$"
-consistent!(rogcat_2, r"^(\d+)([kMG])$");
-
-// media_filename-0.1.4: "\\.([A-Za-z0-9]{2,4})$"
-consistent!(media_filename_0, "\\.([A-Za-z0-9]{2,4})$");
-
-// media_filename-0.1.4: "([0-9]{3,4}p|[0-9]{3,4}x[0-9]{3,4})"
-consistent!(media_filename_1, "([0-9]{3,4}p|[0-9]{3,4}x[0-9]{3,4})");
-
-// media_filename-0.1.4: "(?:^\\[([^]]+)\\]|- ?([^-]+)$)"
-consistent!(media_filename_2, "(?:^\\[([^]]+)\\]|- ?([^-]+)$)");
-
-// media_filename-0.1.4: "(?:[eE]([0-9]{2,3})|[^0-9A-Za-z]([0-9]{2,3})(?:v[0-9])?[^0-9A-Za-z])"
-consistent!(
-    media_filename_3,
-    "(?:[eE]([0-9]{2,3})|[^0-9A-Za-z]([0-9]{2,3})(?:v[0-9])?[^0-9A-Za-z])"
-);
-
-// media_filename-0.1.4: "[sS]([0-9]{1,2})"
-consistent!(media_filename_4, "[sS]([0-9]{1,2})");
-
-// media_filename-0.1.4: "((?i)(?:PPV.)?[HP]DTV|(?:HD)?CAM|BRRIP|[^a-z]TS[^a-z]|(?:PPV )?WEB.?DL(?: DVDRip)?|HDRip|DVDRip|CamRip|W[EB]BRip|BluRay|BD|DVD|DvDScr|hdtv)"
-consistent!(media_filename_5, "((?i)(?:PPV.)?[HP]DTV|(?:HD)?CAM|BRRIP|[^a-z]TS[^a-z]|(?:PPV )?WEB.?DL(?: DVDRip)?|HDRip|DVDRip|CamRip|W[EB]BRip|BluRay|BD|DVD|DvDScr|hdtv)");
-
-// media_filename-0.1.4: "((19[0-9]|20[01])[0-9])"
-consistent!(media_filename_6, "((19[0-9]|20[01])[0-9])");
-
-// media_filename-0.1.4: "((?i)xvid|x264|h\\.?264)"
-consistent!(media_filename_7, "((?i)xvid|x264|h\\.?264)");
-
-// media_filename-0.1.4: "((?i)MP3|DD5\\.?1|Dual[- ]Audio|LiNE|DTS|AAC(?:\\.?2\\.0)?|AC3(?:\\.5\\.1)?)"
-consistent!(media_filename_8, "((?i)MP3|DD5\\.?1|Dual[- ]Audio|LiNE|DTS|AAC(?:\\.?2\\.0)?|AC3(?:\\.5\\.1)?)");
-
-// media_filename-0.1.4: "\\[([0-9A-F]{8})\\]"
-consistent!(media_filename_9, "\\[([0-9A-F]{8})\\]");
-
-// termimage-0.3.2: r"(\d+)[xX](\d+)"
-consistent!(termimage_0, r"(\d+)[xX](\d+)");
-
-// teensy-0.1.0: r".*(\d{4}-\d{2}-\d{2}).*"
-consistent!(teensy_0, r".*(\d{4}-\d{2}-\d{2}).*");
-
-// telescreen-0.1.3: r"<@(.+)>"
-consistent!(telescreen_0, r"<@(.+)>");
-
-// tempus_fugit-0.4.4: r"^(\d+)"
-consistent!(tempus_fugit_0, r"^(\d+)");
-
-// fselect-0.4.1: "(\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)"
-consistent!(fselect_0, "(\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)");
-
-// fselect-0.4.1: "(%|_|\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)"
-consistent!(fselect_1, "(%|_|\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)");
-
-// fs_eventbridge-0.1.0: r"^([A-Z]+)(?:\s(.+))?\s*"
-consistent!(fs_eventbridge_0, r"^([A-Z]+)(?:\s(.+))?\s*");
-
-// joseki-0.0.1: r"(\w{1,2})\[(.+?)\]"
-consistent!(joseki_0, r"(\w{1,2})\[(.+?)\]");
-
-// tweetr-0.2.1: r"(?i)in (\d+) (second|minute|hour|day|week)s?"
-consistent!(tweetr_0, r"(?i)in (\d+) (second|minute|hour|day|week)s?");
-
-// bullet_core-0.1.1: "^(?u:[0-9])+"
-consistent!(bullet_core_0, "^(?u:[0-9])+");
-
-// bullet_core-0.1.1: "^(?u:[0-9])+(?u:\\.)(?u:[0-9])+"
-consistent!(bullet_core_1, "^(?u:[0-9])+(?u:\\.)(?u:[0-9])+");
-
-// bullet_core-0.1.1: "^(?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+"
-consistent!(bullet_core_2, "^(?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+");
-
-// bullet_core-0.1.1: "^(?u:d/d)((?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+)"
-consistent!(bullet_core_3, "^(?u:d/d)((?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+)");
-
-// bullet_core-0.1.1: "^(?u:\\()"
-consistent!(bullet_core_4, "^(?u:\\()");
-
-// bullet_core-0.1.1: "^(?u:\\))"
-consistent!(bullet_core_5, "^(?u:\\))");
-
-// bullet_core-0.1.1: "^(?u:\\*)"
-consistent!(bullet_core_6, "^(?u:\\*)");
-
-// bullet_core-0.1.1: "^(?u:\\+)"
-consistent!(bullet_core_7, "^(?u:\\+)");
-
-// bullet_core-0.1.1: "^(?u:,)"
-consistent!(bullet_core_8, "^(?u:,)");
-
-// bullet_core-0.1.1: "^(?u:\\-)"
-consistent!(bullet_core_9, "^(?u:\\-)");
-
-// bullet_core-0.1.1: "^(?u:/)"
-consistent!(bullet_core_10, "^(?u:/)");
-
-// bullet_core-0.1.1: "^(?u:\\[)"
-consistent!(bullet_core_11, "^(?u:\\[)");
-
-// bullet_core-0.1.1: "^(?u:\\])"
-consistent!(bullet_core_12, "^(?u:\\])");
-
-// bullet_core-0.1.1: "^(?u:\\^)"
-consistent!(bullet_core_13, "^(?u:\\^)");
-
-// bullet_core-0.1.1: "^(?u:·)"
-consistent!(bullet_core_14, "^(?u:·)");
-
-// actix-web-0.6.13: "//+"
-consistent!(actix_web_0, "//+");
-
-// actix-web-0.6.13: "//+"
-consistent!(actix_web_1, "//+");
-
-// althea_kernel_interface-0.1.0: r"(\S*) .* (\S*) (REACHABLE|STALE|DELAY)"
-consistent!(
-    althea_kernel_interface_0,
-    r"(\S*) .* (\S*) (REACHABLE|STALE|DELAY)"
-);
-
-// althea_kernel_interface-0.1.0: r"-s (.*) --ip6-dst (.*)/.* bcnt = (.*)"
-consistent!(
-    althea_kernel_interface_1,
-    r"-s (.*) --ip6-dst (.*)/.* bcnt = (.*)"
-);
-
-// alcibiades-0.3.0: r"\buci(?:\s|$)"
-consistent!(alcibiades_0, r"\buci(?:\s|$)");
-
-// ruma-identifiers-0.11.0: r"\A[a-z0-9._=-]+\z"
-consistent!(ruma_identifiers_0, r"\A[a-z0-9._=-]+\z");
-
-// rusqbin-0.2.3: r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})$"
-consistent!(rusqbin_0, r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})$");
-
-// rusqbin-0.2.3: r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})/requests/?$"
-consistent!(rusqbin_1, r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})/requests/?$");
-
-// rust-install-0.0.4: r"^(nightly|beta|stable)(?:-(\d{4}-\d{2}-\d{2}))?$"
-consistent!(
-    rust_install_0,
-    r"^(nightly|beta|stable)(?:-(\d{4}-\d{2}-\d{2}))?$"
-);
-
-// rust_inbox-0.0.5: "^+(.*)\r\n"
-consistent!(rust_inbox_0, "^+(.*)\r\n");
-
-// rust_inbox-0.0.5: r"^\* CAPABILITY (.*)\r\n"
-consistent!(rust_inbox_1, r"^\* CAPABILITY (.*)\r\n");
-
-// rust_inbox-0.0.5: r"^([a-zA-Z0-9]+) (OK|NO|BAD)(.*)"
-consistent!(rust_inbox_2, r"^([a-zA-Z0-9]+) (OK|NO|BAD)(.*)");
-
-// rust_inbox-0.0.5: r"^\* (\d+) EXISTS\r\n"
-consistent!(rust_inbox_3, r"^\* (\d+) EXISTS\r\n");
-
-// rust_inbox-0.0.5: r"^\* (\d+) RECENT\r\n"
-consistent!(rust_inbox_4, r"^\* (\d+) RECENT\r\n");
-
-// rust_inbox-0.0.5: r"^\* FLAGS (.+)\r\n"
-consistent!(rust_inbox_5, r"^\* FLAGS (.+)\r\n");
-
-// rust_inbox-0.0.5: r"^\* OK \[UNSEEN (\d+)\](.*)\r\n"
-consistent!(rust_inbox_6, r"^\* OK \[UNSEEN (\d+)\](.*)\r\n");
-
-// rust_inbox-0.0.5: r"^\* OK \[UIDVALIDITY (\d+)\](.*)\r\n"
-consistent!(rust_inbox_7, r"^\* OK \[UIDVALIDITY (\d+)\](.*)\r\n");
-
-// rust_inbox-0.0.5: r"^\* OK \[UIDNEXT (\d+)\](.*)\r\n"
-consistent!(rust_inbox_8, r"^\* OK \[UIDNEXT (\d+)\](.*)\r\n");
-
-// rust_inbox-0.0.5: r"^\* OK \[PERMANENTFLAGS (.+)\](.*)\r\n"
-consistent!(rust_inbox_9, r"^\* OK \[PERMANENTFLAGS (.+)\](.*)\r\n");
-
-// rustml-0.0.7: r"^[a-z]+ (\d+)$"
-consistent!(rustml_0, r"^[a-z]+ (\d+)$");
-
-// rustml-0.0.7: r"^[a-z]+ (\d+)$"
-consistent!(rustml_1, r"^[a-z]+ (\d+)$");
-
-// rustml-0.0.7: r"^[a-z]+ (\d+)$"
-consistent!(rustml_2, r"^[a-z]+ (\d+)$");
-
-// rustfmt-0.10.0: r"([^\\](\\\\)*)\\[\n\r][[:space:]]*"
-consistent!(rustfmt_0, r"([^\\](\\\\)*)\\[\n\r][[:space:]]*");
-
-// rustfmt-core-0.4.0: r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)"
-consistent!(rustfmt_core_0, r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)");
-
-// rustfmt-core-0.4.0: r"^## `([^`]+)`"
-consistent!(rustfmt_core_1, r"^## `([^`]+)`");
-
-// rustfmt-core-0.4.0: r"([^\\](\\\\)*)\\[\n\r][[:space:]]*"
-consistent!(rustfmt_core_2, r"([^\\](\\\\)*)\\[\n\r][[:space:]]*");
-
-// rustfmt-core-0.4.0: r"\s;"
-consistent!(rustfmt_core_3, r"\s;");
-
-// rust-enum-derive-0.4.0: r"^(0x)?([:digit:]+)$"
-consistent!(rust_enum_derive_0, r"^(0x)?([:digit:]+)$");
-
-// rust-enum-derive-0.4.0: r"^([:digit:]+)[:space:]*<<[:space:]*([:digit:]+)$"
-consistent!(
-    rust_enum_derive_1,
-    r"^([:digit:]+)[:space:]*<<[:space:]*([:digit:]+)$"
-);
-
-// rust-enum-derive-0.4.0: r"^[:space:]*([[:alnum:]_]+)([:space:]*=[:space:]*([:graph:]+))?[:space:]*,"
-consistent!(rust_enum_derive_2, r"^[:space:]*([[:alnum:]_]+)([:space:]*=[:space:]*([:graph:]+))?[:space:]*,");
-
-// rust-enum-derive-0.4.0: r"^#define[:space:]+([:graph:]+)[:space:]+([:graph:]+)"
-consistent!(
-    rust_enum_derive_3,
-    r"^#define[:space:]+([:graph:]+)[:space:]+([:graph:]+)"
-);
-
-// rustsourcebundler-0.2.0: r"^\s*pub mod (.+);$"
-consistent!(rustsourcebundler_0, r"^\s*pub mod (.+);$");
-
-// rustsourcebundler-0.2.0: r"^\s*pub mod (.+);$"
-consistent!(rustsourcebundler_1, r"^\s*pub mod (.+);$");
-
-// rustfmt-nightly-0.8.2: r"([^\\](\\\\)*)\\[\n\r][[:space:]]*"
-consistent!(rustfmt_nightly_0, r"([^\\](\\\\)*)\\[\n\r][[:space:]]*");
-
-// rustfmt-nightly-0.8.2: r"\s;"
-consistent!(rustfmt_nightly_1, r"\s;");
-
-// rustache-0.1.0: r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)"
-consistent!(rustache_0, r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)");
-
-// rustfilt-0.2.0: r"_ZN[\$\._[:alnum:]]*"
-consistent!(rustfilt_0, r"_ZN[\$\._[:alnum:]]*");
-
-// rustache-lists-0.1.2: r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)"
-consistent!(rustache_lists_0, r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)");
-
-// rural-0.7.3: "(.+)=(.+)"
-consistent!(rural_0, "(.+)=(.+)");
-
-// rural-0.7.3: "(.*):(.+)"
-consistent!(rural_1, "(.*):(.+)");
-
-// rural-0.7.3: "(.+):=(.+)"
-consistent!(rural_2, "(.+):=(.+)");
-
-// rural-0.7.3: "(.*)==(.+)"
-consistent!(rural_3, "(.*)==(.+)");
-
-// rusoto_credential-0.11.0: r"^\[([^\]]+)\]$"
-consistent!(rusoto_credential_0, r"^\[([^\]]+)\]$");
-
-// rumblebars-0.3.0: "([:blank:]*)$"
-consistent!(rumblebars_0, "([:blank:]*)$");
-
-// rumblebars-0.3.0: "(\r?\n)[:blank:]*(\\{\\{~?[#!/](?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z"
-consistent!(rumblebars_1, "(\r?\n)[:blank:]*(\\{\\{~?[#!/](?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z");
-
-// rumblebars-0.3.0: "(\r?\n[:blank:]*)(\\{\\{~?>(?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z"
-consistent!(
-    rumblebars_2,
-    "(\r?\n[:blank:]*)(\\{\\{~?>(?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z"
-);
-
-// rumblebars-0.3.0: "((?:[:blank:]|\r?\n)*)(\r?\n)[:blank:]*$"
-consistent!(rumblebars_3, "((?:[:blank:]|\r?\n)*)(\r?\n)[:blank:]*$");
-
-// rumblebars-0.3.0: "^([:blank:]*\r?\n)(.*)"
-consistent!(rumblebars_4, "^([:blank:]*\r?\n)(.*)");
-
-// diesel_cli-1.3.1: r"(?P<stamp>[\d-]*)_hello"
-consistent!(diesel_cli_0, r"(?P<stamp>[\d-]*)_hello");
-
-// dishub-0.1.1: r"(\d+)s"
-consistent!(dishub_0, r"(\d+)s");
-
-// spreadsheet_textconv-0.1.0: r"\n"
-consistent!(spreadsheet_textconv_0, r"\n");
-
-// spreadsheet_textconv-0.1.0: r"\r"
-consistent!(spreadsheet_textconv_1, r"\r");
-
-// spreadsheet_textconv-0.1.0: r"\t"
-consistent!(spreadsheet_textconv_2, r"\t");
-
-// split_aud-0.1.0: r"DELAY (-?\d+)ms"
-consistent!(split_aud_0, r"DELAY (-?\d+)ms");
-
-// split_aud-0.1.0: r"Trim\((\d+), ?(\d+)\)"
-consistent!(split_aud_1, r"Trim\((\d+), ?(\d+)\)");
-
-// spotrust-0.0.5: r"spotify:[a-z]+:[a-zA-Z0-9]+"
-consistent!(spotrust_0, r"spotify:[a-z]+:[a-zA-Z0-9]+");
-
-// spaceslugs-0.1.0: r"[^\x00-\x7F]"
-consistent!(spaceslugs_0, r"[^\x00-\x7F]");
-
-// spaceslugs-0.1.0: r"[']+"
-consistent!(spaceslugs_1, r"[']+");
-
-// spaceslugs-0.1.0: r"\W+"
-consistent!(spaceslugs_2, r"\W+");
-
-// spaceslugs-0.1.0: r"[ ]+"
-consistent!(spaceslugs_3, r"[ ]+");
-
-// space_email_api-0.1.1: "PHPSESSID=([0-9a-f]+)"
-consistent!(space_email_api_0, "PHPSESSID=([0-9a-f]+)");
-
-// lorikeet-0.7.0: "[^0-9.,]"
-consistent!(lorikeet_0, "[^0-9.,]");
-
-// claude-0.3.0: r"^(?:\b|(-)?)(\p{Currency_Symbol})?((?:(?:\d{1,3}[\.,])+\d{3})|\d+)(?:[\.,](\d{2}))?\b$"
-consistent!(claude_0, r"^(?:\b|(-)?)(\p{Currency_Symbol})?((?:(?:\d{1,3}[\.,])+\d{3})|\d+)(?:[\.,](\d{2}))?\b$");
-
-// clam-0.1.6: r"<%=\s*(.+?)\s*%>"
-consistent!(clam_0, r"<%=\s*(.+?)\s*%>");
-
-// classifier-0.0.3: r"(\s)"
-consistent!(classifier_0, r"(\s)");
-
-// click-0.3.2: r"(-----BEGIN .*-----\n)((?:(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)*\n)+)(-----END .*-----)"
-consistent!(click_0, r"(-----BEGIN .*-----\n)((?:(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)*\n)+)(-----END .*-----)");
-
-// click-0.3.2: r"-----BEGIN PRIVATE KEY-----"
-consistent!(click_1, r"-----BEGIN PRIVATE KEY-----");
-
-// ultrastar-txt-0.1.2: r"#([A-Z3a-z]*):(.*)"
-consistent!(ultrastar_txt_0, r"#([A-Z3a-z]*):(.*)");
-
-// ultrastar-txt-0.1.2: "^-\\s?(-?[0-9]+)\\s*$"
-consistent!(ultrastar_txt_1, "^-\\s?(-?[0-9]+)\\s*$");
-
-// ultrastar-txt-0.1.2: "^-\\s?(-?[0-9]+)\\s+(-?[0-9]+)"
-consistent!(ultrastar_txt_2, "^-\\s?(-?[0-9]+)\\s+(-?[0-9]+)");
-
-// ultrastar-txt-0.1.2: "^(.)\\s*(-?[0-9]+)\\s+(-?[0-9]+)\\s+(-?[0-9]+)\\s?(.*)"
-consistent!(
-    ultrastar_txt_3,
-    "^(.)\\s*(-?[0-9]+)\\s+(-?[0-9]+)\\s+(-?[0-9]+)\\s?(.*)"
-);
-
-// ultrastar-txt-0.1.2: "^P\\s?(-?[0-9]+)"
-consistent!(ultrastar_txt_4, "^P\\s?(-?[0-9]+)");
-
-// db-accelerate-2.0.0: r"^template\.add($|\..+$)"
-consistent!(db_accelerate_0, r"^template\.add($|\..+$)");
-
-// db-accelerate-2.0.0: r"^template\.sub($|\..+$)"
-consistent!(db_accelerate_1, r"^template\.sub($|\..+$)");
-
-// sterling-0.3.0: r"(\d+)([cegps])"
-consistent!(sterling_0, r"(\d+)([cegps])");
-
-// stache-0.2.0: r"[^\w]"
-consistent!(stache_0, r"[^\w]");
-
-// strukt-0.1.0: "\"([<>]?)([xcbB\\?hHiIlLqQfdspP]*)\""
-consistent!(strukt_0, "\"([<>]?)([xcbB\\?hHiIlLqQfdspP]*)\"");
-
-// steamid-ng-0.3.1: r"^STEAM_([0-4]):([0-1]):([0-9]{1,10})$"
-consistent!(steamid_ng_0, r"^STEAM_([0-4]):([0-1]):([0-9]{1,10})$");
-
-// steamid-ng-0.3.1: r"^\[([AGMPCgcLTIUai]):([0-4]):([0-9]{1,10})(:([0-9]+))?\]$"
-consistent!(
-    steamid_ng_1,
-    r"^\[([AGMPCgcLTIUai]):([0-4]):([0-9]{1,10})(:([0-9]+))?\]$"
-);
-
-// strscan-0.1.1: r"^\w+"
-consistent!(strscan_0, r"^\w+");
-
-// strscan-0.1.1: r"^\s+"
-consistent!(strscan_1, r"^\s+");
-
-// strscan-0.1.1: r"^\w+"
-consistent!(strscan_2, r"^\w+");
-
-// strscan-0.1.1: r"^\s+"
-consistent!(strscan_3, r"^\s+");
-
-// strscan-0.1.1: r"^(\w+)\s+"
-consistent!(strscan_4, r"^(\w+)\s+");
-
-// tk-carbon-0.2.0: r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$"
-consistent!(tk_carbon_0, r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$");
-
-// tk-carbon-0.2.0: r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$"
-consistent!(tk_carbon_1, r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$");
-
-// evalrs-0.0.10: r"extern\s+crate\s+([a-z0-9_]+)\s*;(\s*//(.+))?"
-consistent!(evalrs_0, r"extern\s+crate\s+([a-z0-9_]+)\s*;(\s*//(.+))?");
-
-// evalrs-0.0.10: r"(?m)^# "
-consistent!(evalrs_1, r"(?m)^# ");
-
-// evalrs-0.0.10: r"(?m)^\s*fn +main *\( *\)"
-consistent!(evalrs_2, r"(?m)^\s*fn +main *\( *\)");
-
-// evalrs-0.0.10: r"(extern\s+crate\s+[a-z0-9_]+\s*;)"
-consistent!(evalrs_3, r"(extern\s+crate\s+[a-z0-9_]+\s*;)");
-
-// gate_build-0.5.0: "(.*)_t([0-9]+)"
-consistent!(gate_build_0, "(.*)_t([0-9]+)");
-
-// rake-0.1.1: r"[^\P{P}-]|\s+-\s+"
-consistent!(rake_0, r"[^\P{P}-]|\s+-\s+");
-
-// rafy-0.2.1: r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*"
-consistent!(rafy_0, r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*");
-
-// raven-0.2.1: r"^(?P<protocol>.*?)://(?P<public_key>.*?):(?P<secret_key>.*?)@(?P<host>.*?)/(?P<path>.*/)?(?P<project_id>.*)$"
-consistent!(raven_0, r"^(?P<protocol>.*?)://(?P<public_key>.*?):(?P<secret_key>.*?)@(?P<host>.*?)/(?P<path>.*/)?(?P<project_id>.*)$");
-
-// rargs-0.2.0: r"\{[[:space:]]*[^{}]*[[:space:]]*\}"
-consistent!(rargs_0, r"\{[[:space:]]*[^{}]*[[:space:]]*\}");
-
-// rargs-0.2.0: r"^\{[[:space:]]*(?P<name>[[:word:]]*)[[:space:]]*\}$"
-consistent!(rargs_1, r"^\{[[:space:]]*(?P<name>[[:word:]]*)[[:space:]]*\}$");
-
-// rargs-0.2.0: r"^\{[[:space:]]*(?P<num>-?\d+)[[:space:]]*\}$"
-consistent!(rargs_2, r"^\{[[:space:]]*(?P<num>-?\d+)[[:space:]]*\}$");
-
-// rargs-0.2.0: r"^\{(?P<left>-?\d*)?\.\.(?P<right>-?\d*)?(?::(?P<sep>.*))?\}$"
-consistent!(
-    rargs_3,
-    r"^\{(?P<left>-?\d*)?\.\.(?P<right>-?\d*)?(?::(?P<sep>.*))?\}$"
-);
-
-// rargs-0.2.0: r"(.*?)[[:space:]]+|(.*?)$"
-consistent!(rargs_4, r"(.*?)[[:space:]]+|(.*?)$");
-
-// indradb-lib-0.15.0: r"[a-zA-Z0-9]{8}"
-consistent!(indradb_lib_0, r"[a-zA-Z0-9]{8}");
-
-// fungi-lang-0.1.50: r"::"
-consistent!(fungi_lang_0, r"::");
-
-// nickel-0.10.1: "/hello/(?P<name>[a-zA-Z]+)"
-consistent!(nickel_0, "/hello/(?P<name>[a-zA-Z]+)");
-
-// nickel-0.10.1: "/hello/(?P<name>[a-zA-Z]+)"
-consistent!(nickel_1, "/hello/(?P<name>[a-zA-Z]+)");
-
-// pact_verifier-0.4.0: r"\{(\w+)\}"
-consistent!(pact_verifier_0, r"\{(\w+)\}");
-
-// pact_matching-0.4.1: "application/.*json"
-consistent!(pact_matching_0, "application/.*json");
-
-// pact_matching-0.4.1: "application/json.*"
-consistent!(pact_matching_1, "application/json.*");
-
-// pact_matching-0.4.1: "application/.*xml"
-consistent!(pact_matching_2, "application/.*xml");
-
-// pangu-0.2.0: "([\"'\\(\\[\\{{<\u{201c}])(\\s*)(.+?)(\\s*)([\"'\\)\\]\\}}>\u{201d}])"
-consistent!(
-    pangu_0,
-    "([\"'\\(\\[\\{{<\u{201c}])(\\s*)(.+?)(\\s*)([\"'\\)\\]\\}}>\u{201d}])"
-);
-
-// pangu-0.2.0: "([\\(\\[\\{{<\u{201c}]+)(\\s*)(.+?)(\\s*)([\\)\\]\\}}>\u{201d}]+)"
-consistent!(
-    pangu_1,
-    "([\\(\\[\\{{<\u{201c}]+)(\\s*)(.+?)(\\s*)([\\)\\]\\}}>\u{201d}]+)"
-);
-
-// parser-haskell-0.2.0: r"\{-[\s\S]*?-\}"
-consistent!(parser_haskell_0, r"\{-[\s\S]*?-\}");
-
-// parser-haskell-0.2.0: r"(?m);+\s*$"
-consistent!(parser_haskell_1, r"(?m);+\s*$");
-
-// parser-haskell-0.2.0: r"(?m)^#(if|ifn?def|endif|else|include|elif).*"
-consistent!(parser_haskell_2, r"(?m)^#(if|ifn?def|endif|else|include|elif).*");
-
-// parser-haskell-0.2.0: r"'([^'\\]|\\[A-Z]{1,3}|\\.)'"
-consistent!(parser_haskell_3, r"'([^'\\]|\\[A-Z]{1,3}|\\.)'");
-
-// parser-haskell-0.2.0: r"forall\s+(.*?)\."
-consistent!(parser_haskell_4, r"forall\s+(.*?)\.");
-
-// html2md-0.2.1: "\\s{2,}"
-consistent!(html2md_0, "\\s{2,}");
-
-// html2md-0.2.1: "\\n{2,}"
-consistent!(html2md_1, "\\n{2,}");
-
-// html2md-0.2.1: "(?m)(\\S) $"
-consistent!(html2md_2, "(?m)(\\S) $");
-
-// html2md-0.2.1: "(?m)^[-*] "
-consistent!(html2md_3, "(?m)^[-*] ");
-
-// ovpnfile-0.1.2: r"#.*$"
-consistent!(ovpnfile_0, r"#.*$");
-
-// ovpnfile-0.1.2: r"^<(\S+)>"
-consistent!(ovpnfile_1, r"^<(\S+)>");
-
-// ovpnfile-0.1.2: r"^</(\S+)>"
-consistent!(ovpnfile_2, r"^</(\S+)>");
-
-// screenruster-saver-fractal-0.1.1: r"#([:xdigit:]{2})([:xdigit:]{2})([:xdigit:]{2})"
-consistent!(
-    screenruster_saver_fractal_0,
-    r"#([:xdigit:]{2})([:xdigit:]{2})([:xdigit:]{2})"
-);
-
-// scarlet-0.2.2: r"rgb\((?: *(\d{1,3}),)(?: *(\d{1,3}),)(?: *(\d{1,3}))\)"
-consistent!(
-    scarlet_0,
-    r"rgb\((?: *(\d{1,3}),)(?: *(\d{1,3}),)(?: *(\d{1,3}))\)"
-);
-
-// cpp_to_rust_generator-0.2.0: r"^([\w:]+)<(.+)>$"
-consistent!(cpp_to_rust_generator_0, r"^([\w:]+)<(.+)>$");
-
-// cpp_to_rust_generator-0.2.0: r"^type-parameter-(\d+)-(\d+)$"
-consistent!(cpp_to_rust_generator_1, r"^type-parameter-(\d+)-(\d+)$");
-
-// cpp_to_rust_generator-0.2.0: r"^([\w~]+)<[^<>]+>$"
-consistent!(cpp_to_rust_generator_2, r"^([\w~]+)<[^<>]+>$");
-
-// cpp_to_rust_generator-0.2.0: r"(signals|Q_SIGNALS)\s*:"
-consistent!(cpp_to_rust_generator_3, r"(signals|Q_SIGNALS)\s*:");
-
-// cpp_to_rust_generator-0.2.0: r"(slots|Q_SLOTS)\s*:"
-consistent!(cpp_to_rust_generator_4, r"(slots|Q_SLOTS)\s*:");
-
-// cpp_to_rust_generator-0.2.0: r"(public|protected|private)\s*:"
-consistent!(cpp_to_rust_generator_5, r"(public|protected|private)\s*:");
-
-// cpp_to_rust-0.5.3: r"^([\w:]+)<(.+)>$"
-consistent!(cpp_to_rust_0, r"^([\w:]+)<(.+)>$");
-
-// cpp_to_rust-0.5.3: r"^type-parameter-(\d+)-(\d+)$"
-consistent!(cpp_to_rust_1, r"^type-parameter-(\d+)-(\d+)$");
-
-// cpp_to_rust-0.5.3: r"^([\w~]+)<[^<>]+>$"
-consistent!(cpp_to_rust_2, r"^([\w~]+)<[^<>]+>$");
-
-// cpp_to_rust-0.5.3: r"(signals|Q_SIGNALS)\s*:"
-consistent!(cpp_to_rust_3, r"(signals|Q_SIGNALS)\s*:");
-
-// cpp_to_rust-0.5.3: r"(slots|Q_SLOTS)\s*:"
-consistent!(cpp_to_rust_4, r"(slots|Q_SLOTS)\s*:");
-
-// cpp_to_rust-0.5.3: r"(public|protected|private)\s*:"
-consistent!(cpp_to_rust_5, r"(public|protected|private)\s*:");
-
-// fritzbox_logs-0.2.0: "(\\d{2}\\.\\d{2}\\.\\d{2}) (\\d{2}:\\d{2}:\\d{2}) (.*)"
-consistent!(
-    fritzbox_logs_0,
-    "(\\d{2}\\.\\d{2}\\.\\d{2}) (\\d{2}:\\d{2}:\\d{2}) (.*)"
-);
-
-// fractal-matrix-api-3.29.0: r"mxc://(?P<server>[^/]+)/(?P<media>.+)"
-consistent!(fractal_matrix_api_0, r"mxc://(?P<server>[^/]+)/(?P<media>.+)");
-
-// smtp2go-0.1.4: r"^api-[a-zA-Z0-9]{32}$"
-consistent!(smtp2go_0, r"^api-[a-zA-Z0-9]{32}$");
-
-// pusher-0.3.1: r"^[-a-zA-Z0-9_=@,.;]+$"
-consistent!(pusher_0, r"^[-a-zA-Z0-9_=@,.;]+$");
-
-// pusher-0.3.1: r"\A\d+\.\d+\z"
-consistent!(pusher_1, r"\A\d+\.\d+\z");
-
-// bakervm-0.9.0: r"^\.(.+?) +?(.+)$"
-consistent!(bakervm_0, r"^\.(.+?) +?(.+)$");
-
-// bakervm-0.9.0: r"^\.([^\s]+)$"
-consistent!(bakervm_1, r"^\.([^\s]+)$");
-
-// bakervm-0.9.0: r"^include! +([^\s]+)$"
-consistent!(bakervm_2, r"^include! +([^\s]+)$");
-
-// bakervm-0.9.0: r"^@(\d+)$"
-consistent!(bakervm_3, r"^@(\d+)$");
-
-// bakervm-0.9.0: r"^true|false$"
-consistent!(bakervm_4, r"^true|false$");
-
-// bakervm-0.9.0: r"^(-?\d+)?\.[0-9]+$"
-consistent!(bakervm_5, r"^(-?\d+)?\.[0-9]+$");
-
-// bakervm-0.9.0: r"^(-?\d+)?$"
-consistent!(bakervm_6, r"^(-?\d+)?$");
-
-// bakervm-0.9.0: r"^#([0-9abcdefABCDEF]{6})$"
-consistent!(bakervm_7, r"^#([0-9abcdefABCDEF]{6})$");
-
-// bakervm-0.9.0: r"^'(.)'$"
-consistent!(bakervm_8, r"^'(.)'$");
-
-// bakervm-0.9.0: r"^\$vi\((\d+)\)$"
-consistent!(bakervm_9, r"^\$vi\((\d+)\)$");
-
-// bakervm-0.9.0: r"^\$key\((\d+)\)$"
-consistent!(bakervm_10, r"^\$key\((\d+)\)$");
-
-// banana-0.0.2: "(?P<type>[A-Z^']+) (?P<route>[^']+) HTTP/(?P<http>[^']+)"
-consistent!(
-    banana_0,
-    "(?P<type>[A-Z^']+) (?P<route>[^']+) HTTP/(?P<http>[^']+)"
-);
-
-// serial-key-2.0.0: r"[A-F0-9]{8}"
-consistent!(serial_key_0, r"[A-F0-9]{8}");
-
-// serde-hjson-0.8.1: "[\\\\\"\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]"
-consistent!(serde_hjson_0, "[\\\\\"\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]");
-
-// serde-hjson-0.8.1: "[\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]"
-consistent!(serde_hjson_1, "[\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]");
-
-// serde-hjson-0.8.1: "'''|[\x00-\x09\x0b\x0c\x0e-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]"
-consistent!(serde_hjson_2, "'''|[\x00-\x09\x0b\x0c\x0e-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]");
-
-// serde-odbc-0.1.0: r"/todos/(?P<id>\d+)"
-consistent!(serde_odbc_0, r"/todos/(?P<id>\d+)");
-
-// sentry-0.6.0: r"^(?:_<)?([a-zA-Z0-9_]+?)(?:\.\.|::)"
-consistent!(sentry_0, r"^(?:_<)?([a-zA-Z0-9_]+?)(?:\.\.|::)");
-
-// sentiment-0.1.1: r"[^a-zA-Z0 -]+"
-consistent!(sentiment_0, r"[^a-zA-Z0 -]+");
-
-// sentiment-0.1.1: r" {2,}"
-consistent!(sentiment_1, r" {2,}");
-
-// verilog-0.0.1: r"(?m)//.*"
-consistent!(verilog_0, r"(?m)//.*");
-
-// verex-0.2.2: "(?P<robot>C3PO)"
-consistent!(verex_0, "(?P<robot>C3PO)");
-
-// handlebars-0.32.4: ">|<|\"|&"
-consistent!(handlebars_0, ">|<|\"|&");
-
-// haikunator-0.1.2: r"^\w+-\w+-[0123456789]{4}$"
-consistent!(haikunator_0, r"^\w+-\w+-[0123456789]{4}$");
-
-// haikunator-0.1.2: r"^\w+@\w+@[0123456789]{4}$"
-consistent!(haikunator_1, r"^\w+@\w+@[0123456789]{4}$");
-
-// haikunator-0.1.2: r"^\w+-\w+-[0123456789abcdef]{4}$"
-consistent!(haikunator_2, r"^\w+-\w+-[0123456789abcdef]{4}$");
-
-// haikunator-0.1.2: r"^\w+-\w+-[0123456789忠犬ハチ公]{10}$"
-consistent!(haikunator_3, r"^\w+-\w+-[0123456789忠犬ハチ公]{10}$");
-
-// haikunator-0.1.2: r"^\w+-\w+$"
-consistent!(haikunator_4, r"^\w+-\w+$");
-
-// haikunator-0.1.2: r"^\w+-\w+-[foo]{4}$"
-consistent!(haikunator_5, r"^\w+-\w+-[foo]{4}$");
-
-// haikunator-0.1.2: r"^\w+-\w+-[0123456789忠犬ハチ公]{5}$"
-consistent!(haikunator_6, r"^\w+-\w+-[0123456789忠犬ハチ公]{5}$");
-
-// bobbin-cli-0.8.3: r"(.*)"
-consistent!(bobbin_cli_0, r"(.*)");
-
-// bobbin-cli-0.8.3: r"rustc (.*)"
-consistent!(bobbin_cli_1, r"rustc (.*)");
-
-// bobbin-cli-0.8.3: r"cargo (.*)"
-consistent!(bobbin_cli_2, r"cargo (.*)");
-
-// bobbin-cli-0.8.3: r"xargo (.*)\n"
-consistent!(bobbin_cli_3, r"xargo (.*)\n");
-
-// bobbin-cli-0.8.3: r"Open On-Chip Debugger (.*)"
-consistent!(bobbin_cli_4, r"Open On-Chip Debugger (.*)");
-
-// bobbin-cli-0.8.3: r"arm-none-eabi-gcc \(GNU Tools for ARM Embedded Processors[^\)]*\) (.*)"
-consistent!(
-    bobbin_cli_5,
-    r"arm-none-eabi-gcc \(GNU Tools for ARM Embedded Processors[^\)]*\) (.*)"
-);
-
-// bobbin-cli-0.8.3: r"(?m).*\nBasic Open Source SAM-BA Application \(BOSSA\) Version (.*)\n"
-consistent!(
-    bobbin_cli_6,
-    r"(?m).*\nBasic Open Source SAM-BA Application \(BOSSA\) Version (.*)\n"
-);
-
-// bobbin-cli-0.8.3: r"(?m)SEGGER J-Link Commander (.*)\n"
-consistent!(bobbin_cli_7, r"(?m)SEGGER J-Link Commander (.*)\n");
-
-// bobbin-cli-0.8.3: r"(?m)Teensy Loader, Command Line, Version (.*)\n"
-consistent!(bobbin_cli_8, r"(?m)Teensy Loader, Command Line, Version (.*)\n");
-
-// bobbin-cli-0.8.3: r"dfu-util (.*)\n"
-consistent!(bobbin_cli_9, r"dfu-util (.*)\n");
-
-// borsholder-0.9.1: r"^/static/[\w.]+$"
-consistent!(borsholder_0, r"^/static/[\w.]+$");
-
-// borsholder-0.9.1: r"^/timeline/([0-9]+)$"
-consistent!(borsholder_1, r"^/timeline/([0-9]+)$");
-
-// fblog-1.0.1: "\u{001B}\\[[\\d;]*[^\\d;]"
-consistent!(fblog_0, "\u{001B}\\[[\\d;]*[^\\d;]");
-
-// fblog-1.0.1: "\u{001B}\\[[\\d;]*[^\\d;]"
-consistent!(fblog_1, "\u{001B}\\[[\\d;]*[^\\d;]");
-
-// toml-query-0.6.0: r"^\[\d+\]$"
-consistent!(toml_query_0, r"^\[\d+\]$");
-
-// todo-txt-1.1.0: r" (?P<key>[^\s]+):(?P<value>[^\s^/]+)"
-consistent!(todo_txt_0, r" (?P<key>[^\s]+):(?P<value>[^\s^/]+)");
-
-// findr-0.1.5: r"\band\b"
-consistent!(findr_0, r"\band\b");
-
-// findr-0.1.5: r"\bor\b"
-consistent!(findr_1, r"\bor\b");
-
-// findr-0.1.5: r"\bnot\b"
-consistent!(findr_2, r"\bnot\b");
-
-// file-sniffer-3.0.1: r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
-consistent!(file_sniffer_0, r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
-
-// file-sniffer-3.0.1: r".*?\.(stats|conf|h|cache.*|dat|pc|info)$"
-consistent!(file_sniffer_1, r".*?\.(stats|conf|h|cache.*|dat|pc|info)$");
-
-// file-sniffer-3.0.1: r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
-consistent!(file_sniffer_2, r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
-
-// file-sniffer-3.0.1: r".*?\.(stats|conf|h|cache.*)$"
-consistent!(file_sniffer_3, r".*?\.(stats|conf|h|cache.*)$");
-
-// file-sniffer-3.0.1: r"(\.git|\.pijul|_darcs|\.hg)$"
-consistent!(file_sniffer_4, r"(\.git|\.pijul|_darcs|\.hg)$");
-
-// file_logger-0.1.0: "test"
-consistent!(file_logger_0, "test");
-
-// file_scanner-0.2.0: r"foo"
-consistent!(file_scanner_0, r"foo");
-
-// file_scanner-0.2.0: r"a+b"
-consistent!(file_scanner_1, r"a+b");
-
-// file_scanner-0.2.0: r"a[ab]*b"
-consistent!(file_scanner_2, r"a[ab]*b");
-
-// file_scanner-0.2.0: r"\s+"
-consistent!(file_scanner_3, r"\s+");
-
-// file_scanner-0.2.0: r"\s+"
-consistent!(file_scanner_4, r"\s+");
-
-// cellsplit-0.2.1: r"^\s*([^\s]+) %cellsplit<\d+>$"
-consistent!(cellsplit_0, r"^\s*([^\s]+) %cellsplit<\d+>$");
-
-// cellsplit-0.2.1: r"^\s*([^\s]+) %cellsplit<\d+>$"
-consistent!(cellsplit_1, r"^\s*([^\s]+) %cellsplit<\d+>$");
-
-// aterm-0.20.0: r"^[+\-]?[0-9]+"
-consistent!(aterm_0, r"^[+\-]?[0-9]+");
-
-// aterm-0.20.0: r"^[+\-]?[0-9]+\.[0-9]*([eE][+\-]?[0-9]+)?"
-consistent!(aterm_1, r"^[+\-]?[0-9]+\.[0-9]*([eE][+\-]?[0-9]+)?");
-
-// atarashii_imap-0.3.0: r"^[*] OK"
-consistent!(atarashii_imap_0, r"^[*] OK");
-
-// atarashii_imap-0.3.0: r"FLAGS\s\((.+)\)"
-consistent!(atarashii_imap_1, r"FLAGS\s\((.+)\)");
-
-// atarashii_imap-0.3.0: r"\[PERMANENTFLAGS\s\((.+)\)\]"
-consistent!(atarashii_imap_2, r"\[PERMANENTFLAGS\s\((.+)\)\]");
-
-// atarashii_imap-0.3.0: r"\[UIDVALIDITY\s(\d+)\]"
-consistent!(atarashii_imap_3, r"\[UIDVALIDITY\s(\d+)\]");
-
-// atarashii_imap-0.3.0: r"(\d+)\sEXISTS"
-consistent!(atarashii_imap_4, r"(\d+)\sEXISTS");
-
-// atarashii_imap-0.3.0: r"(\d+)\sRECENT"
-consistent!(atarashii_imap_5, r"(\d+)\sRECENT");
-
-// atarashii_imap-0.3.0: r"\[UNSEEN\s(\d+)\]"
-consistent!(atarashii_imap_6, r"\[UNSEEN\s(\d+)\]");
-
-// atarashii_imap-0.3.0: r"\[UIDNEXT\s(\d+)\]"
-consistent!(atarashii_imap_7, r"\[UIDNEXT\s(\d+)\]");
-
-// editorconfig-1.0.0: r"\\(\{|\})"
-consistent!(editorconfig_0, r"\\(\{|\})");
-
-// editorconfig-1.0.0: r"(^|[^\\])\\\|"
-consistent!(editorconfig_1, r"(^|[^\\])\\\|");
-
-// editorconfig-1.0.0: r"\[([^\]]*)$"
-consistent!(editorconfig_2, r"\[([^\]]*)$");
-
-// editorconfig-1.0.0: r"\[(.*/.*)\]"
-consistent!(editorconfig_3, r"\[(.*/.*)\]");
-
-// editorconfig-1.0.0: r"\{(-?\d+\\\.\\\.-?\d+)\}"
-consistent!(editorconfig_4, r"\{(-?\d+\\\.\\\.-?\d+)\}");
-
-// editorconfig-1.0.0: r"\{([^,]+)\}"
-consistent!(editorconfig_5, r"\{([^,]+)\}");
-
-// editorconfig-1.0.0: r"\{(([^\}].*)?(,|\|)(.*[^\\])?)\}"
-consistent!(editorconfig_6, r"\{(([^\}].*)?(,|\|)(.*[^\\])?)\}");
-
-// editorconfig-1.0.0: r"^/"
-consistent!(editorconfig_7, r"^/");
-
-// editorconfig-1.0.0: r"(^|[^\\])(\{|\})"
-consistent!(editorconfig_8, r"(^|[^\\])(\{|\})");
-
-// edmunge-1.0.0: "^#!.*\n"
-consistent!(edmunge_0, "^#!.*\n");
-
-// unicode_names2_macros-0.2.0: r"\\N\{(.*?)(?:\}|$)"
-consistent!(unicode_names2_macros_0, r"\\N\{(.*?)(?:\}|$)");
-
-// unidiff-0.2.1: r"^--- (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?"
-consistent!(
-    unidiff_0,
-    r"^--- (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?"
-);
-
-// unidiff-0.2.1: r"^\+\+\+ (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?"
-consistent!(
-    unidiff_1,
-    r"^\+\+\+ (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?"
-);
-
-// unidiff-0.2.1: r"^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@[ ]?(.*)"
-consistent!(unidiff_2, r"^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@[ ]?(.*)");
-
-// unidiff-0.2.1: r"^(?P<line_type>[- \n\+\\]?)(?P<value>.*)"
-consistent!(unidiff_3, r"^(?P<line_type>[- \n\+\\]?)(?P<value>.*)");
-
-// slippy-map-tiles-0.13.1: "/?(?P<zoom>[0-9]?[0-9])/(?P<x>[0-9]{1,10})/(?P<y>[0-9]{1,10})(\\.[a-zA-Z]{3,4})?$"
-consistent!(slippy_map_tiles_0, "/?(?P<zoom>[0-9]?[0-9])/(?P<x>[0-9]{1,10})/(?P<y>[0-9]{1,10})(\\.[a-zA-Z]{3,4})?$");
-
-// slippy-map-tiles-0.13.1: r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$"
-consistent!(slippy_map_tiles_1, r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$");
-
-// slippy-map-tiles-0.13.1: r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$"
-consistent!(slippy_map_tiles_2, r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$");
-
-// sonos-0.1.2: r"^https?://(.+?):1400/xml"
-consistent!(sonos_0, r"^https?://(.+?):1400/xml");
-
-// validator_derive-0.7.0: r"^[a-z]{2}$"
-consistent!(validator_derive_0, r"^[a-z]{2}$");
-
-// validator_derive-0.7.0: r"[a-z]{2}"
-consistent!(validator_derive_1, r"[a-z]{2}");
-
-// validator_derive-0.7.0: r"[a-z]{2}"
-consistent!(validator_derive_2, r"[a-z]{2}");
-
-// nginx-config-0.8.0: r"one of \d+ options"
-consistent!(nginx_config_0, r"one of \d+ options");
-
-// waltz-0.4.0: r"[\s,]"
-consistent!(waltz_0, r"[\s,]");
-
-// warheadhateus-0.2.1: r"^aws_access_key_id = (.*)"
-consistent!(warheadhateus_0, r"^aws_access_key_id = (.*)");
-
-// warheadhateus-0.2.1: r"^aws_secret_access_key = (.*)"
-consistent!(warheadhateus_1, r"^aws_secret_access_key = (.*)");
-
-// warheadhateus-0.2.1: r"^aws_access_key_id = (.*)"
-consistent!(warheadhateus_2, r"^aws_access_key_id = (.*)");
-
-// warheadhateus-0.2.1: r"^aws_secret_access_key = (.*)"
-consistent!(warheadhateus_3, r"^aws_secret_access_key = (.*)");
-
-// jieba-rs-0.2.2: r"([\u{4E00}-\u{9FD5}a-zA-Z0-9+#&\._%]+)"
-consistent!(jieba_rs_0, r"([\u{4E00}-\u{9FD5}a-zA-Z0-9+#&\._%]+)");
-
-// jieba-rs-0.2.2: r"(\r\n|\s)"
-consistent!(jieba_rs_1, r"(\r\n|\s)");
-
-// jieba-rs-0.2.2: "([\u{4E00}-\u{9FD5}]+)"
-consistent!(jieba_rs_2, "([\u{4E00}-\u{9FD5}]+)");
-
-// jieba-rs-0.2.2: r"[^a-zA-Z0-9+#\n]"
-consistent!(jieba_rs_3, r"[^a-zA-Z0-9+#\n]");
-
-// jieba-rs-0.2.2: r"([\u{4E00}-\u{9FD5}]+)"
-consistent!(jieba_rs_4, r"([\u{4E00}-\u{9FD5}]+)");
-
-// jieba-rs-0.2.2: r"([a-zA-Z0-9]+(?:.\d+)?%?)"
-consistent!(jieba_rs_5, r"([a-zA-Z0-9]+(?:.\d+)?%?)");
-
-// lalrpop-0.15.2: r"Span\([0-9 ,]*\)"
-consistent!(lalrpop_0, r"Span\([0-9 ,]*\)");
-
-// lalrpop-snap-0.15.2: r"Span\([0-9 ,]*\)"
-consistent!(lalrpop_snap_0, r"Span\([0-9 ,]*\)");
-
-// nlp-tokenize-0.1.0: r"[\S]+"
-consistent!(nlp_tokenize_0, r"[\S]+");
-
-// kbgpg-0.1.2: "[[:xdigit:]][70]"
-consistent!(kbgpg_0, "[[:xdigit:]][70]");
-
-// cdbd-0.1.1: r"^((?P<address>.*):)?(?P<port>\d+)$"
-consistent!(cdbd_0, r"^((?P<address>.*):)?(?P<port>\d+)$");
-
-// mbutiles-0.1.1: r"[\w\s=+-/]+\((\{(.|\n)*\})\);?"
-consistent!(mbutiles_0, r"[\w\s=+-/]+\((\{(.|\n)*\})\);?");
-
-// extrahop-0.2.5: r"^-\d+(?:ms|s|m|h|d|w|y)?$"
-consistent!(extrahop_0, r"^-\d+(?:ms|s|m|h|d|w|y)?$");
-
-// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$"
-consistent!(pippin_0, "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$");
-
-// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$"
-consistent!(
-    pippin_1,
-    "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$"
-);
-
-// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$"
-consistent!(pippin_2, "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$");
-
-// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$"
-consistent!(
-    pippin_3,
-    "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$"
-);
-
-// pippin-0.1.0: "^.*pn(0|[1-9][0-9]*)(-ss(0|[1-9][0-9]*)(\\.pip|-cl(0|[1-9][0-9]*)\\.piplog))?$"
-consistent!(pippin_4, "^.*pn(0|[1-9][0-9]*)(-ss(0|[1-9][0-9]*)(\\.pip|-cl(0|[1-9][0-9]*)\\.piplog))?$");
-
-// pippin-0.1.0: "^(.*)-ss(?:0|[1-9][0-9]*)(?:\\.pip|-cl(?:0|[1-9][0-9]*)\\.piplog)$"
-consistent!(
-    pippin_5,
-    "^(.*)-ss(?:0|[1-9][0-9]*)(?:\\.pip|-cl(?:0|[1-9][0-9]*)\\.piplog)$"
-);
-
-// pinyin-0.3.0: r"(?i)[āáǎàēéěèōóǒòīíǐìūúǔùüǘǚǜńň]"
-consistent!(
-    pinyin_0,
-    r"(?i)[āáǎàēéěèōóǒòīíǐìūúǔùüǘǚǜńň]"
-);
-
-// pinyin-0.3.0: r"([aeoiuvnm])([0-4])$"
-consistent!(pinyin_1, r"([aeoiuvnm])([0-4])$");
-
-// duration-parser-0.2.0: r"(?P<value>\d+)(?P<units>[a-z])"
-consistent!(duration_parser_0, r"(?P<value>\d+)(?P<units>[a-z])");
-
-// dutree-0.2.7: r"^\d+\D?$"
-consistent!(dutree_0, r"^\d+\D?$");
-
-// djangohashers-0.3.0: r"^[A-Za-z0-9]*$"
-consistent!(djangohashers_0, r"^[A-Za-z0-9]*$");
-
-// rtag-0.3.5: r"^[A-Z][A-Z0-9]{2,}$"
-consistent!(rtag_0, r"^[A-Z][A-Z0-9]{2,}$");
-
-// rtag-0.3.5: r"^http://www\.emusic\.com"
-consistent!(rtag_1, r"^http://www\.emusic\.com");
-
-// rtag-0.3.5: r"^[A-Z][A-Z0-9]{2,}"
-consistent!(rtag_2, r"^[A-Z][A-Z0-9]{2,}");
-
-// rtag-0.3.5: r"(^[\x{0}|\x{feff}|\x{fffe}]*|[\x{0}|\x{feff}|\x{fffe}]*$)"
-consistent!(
-    rtag_3,
-    r"(^[\x{0}|\x{feff}|\x{fffe}]*|[\x{0}|\x{feff}|\x{fffe}]*$)"
-);
-
-// rtow-0.1.0: r"(\d+)[xX](\d+)"
-consistent!(rtow_0, r"(\d+)[xX](\d+)");
-
-// pleingres-sql-plugin-0.1.0: r"\$([a-zA-Z0-9_]+)"
-consistent!(pleingres_sql_plugin_0, r"\$([a-zA-Z0-9_]+)");
-
-// dono-2.0.0: "[\\n]+"
-consistent!(dono_0, "[\\n]+");
-
-// dono-2.0.0: "(?m)^\\n"
-consistent!(dono_1, "(?m)^\\n");
-
-// dono-2.0.0: "(?m)^\\n"
-consistent!(dono_2, "(?m)^\\n");
-
-// ssb-common-0.3.0: r"^[0-9A-Za-z\+/]{43}=\.ed25519$"
-consistent!(ssb_common_0, r"^[0-9A-Za-z\+/]{43}=\.ed25519$");
-
-// ssb-common-0.3.0: r"^[0-9A-Za-z\+/]{86}==\.ed25519$"
-consistent!(ssb_common_1, r"^[0-9A-Za-z\+/]{86}==\.ed25519$");
-
-// ssb-common-0.3.0: r"^[0-9A-Za-z\+/]{43}=\.sha256$"
-consistent!(ssb_common_2, r"^[0-9A-Za-z\+/]{43}=\.sha256$");
-
-// mozversion-0.1.3: r"^(?P<major>\d+)\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?(?:(?P<pre0>[a-z]+)(?P<pre1>\d*))?$"
-consistent!(mozversion_0, r"^(?P<major>\d+)\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?(?:(?P<pre0>[a-z]+)(?P<pre1>\d*))?$");
-
-// monger-0.5.6: r"^(\d+)\.(\d+)$"
-consistent!(monger_0, r"^(\d+)\.(\d+)$");
-
-// mongo_rub-0.0.2: r"^[rv]2\.6"
-consistent!(mongo_rub_0, r"^[rv]2\.6");
-
-// flow-0.3.5: "body value"
-consistent!(flow_0, "body value");
-
-// flow-0.3.5: "start marker"
-consistent!(flow_1, "start marker");
-
-// flow-0.3.5: "end marker"
-consistent!(flow_2, "end marker");
-
-// flow-0.3.5: "body value"
-consistent!(flow_3, "body value");
-
-// vobsub-0.2.3: "^([A-Za-z/ ]+): (.*)"
-consistent!(vobsub_0, "^([A-Za-z/ ]+): (.*)");
-
-// voidmap-1.1.2: r"#([^\s=]+)*"
-consistent!(voidmap_0, r"#([^\s=]+)*");
-
-// voidmap-1.1.2: r"#(\S+)*"
-consistent!(voidmap_1, r"#(\S+)*");
-
-// voidmap-1.1.2: r"#prio=(\d+)"
-consistent!(voidmap_2, r"#prio=(\d+)");
-
-// voidmap-1.1.2: r"\[(\S+)\]"
-consistent!(voidmap_3, r"\[(\S+)\]");
-
-// voidmap-1.1.2: r"#limit=(\d+)"
-consistent!(voidmap_4, r"#limit=(\d+)");
-
-// voidmap-1.1.2: r"#tagged=(\S+)"
-consistent!(voidmap_5, r"#tagged=(\S+)");
-
-// voidmap-1.1.2: r"#rev\b"
-consistent!(voidmap_6, r"#rev\b");
-
-// voidmap-1.1.2: r"#done\b"
-consistent!(voidmap_7, r"#done\b");
-
-// voidmap-1.1.2: r"#open\b"
-consistent!(voidmap_8, r"#open\b");
-
-// voidmap-1.1.2: r"#since=(\S+)"
-consistent!(voidmap_9, r"#since=(\S+)");
-
-// voidmap-1.1.2: r"#until=(\S+)"
-consistent!(voidmap_10, r"#until=(\S+)");
-
-// voidmap-1.1.2: r"#plot=(\S+)"
-consistent!(voidmap_11, r"#plot=(\S+)");
-
-// voidmap-1.1.2: r"#n=(\d+)"
-consistent!(voidmap_12, r"#n=(\d+)");
-
-// voidmap-1.1.2: r"(\S+)"
-consistent!(voidmap_13, r"(\S+)");
-
-// voidmap-1.1.2: r"(?P<y>\d+)y"
-consistent!(voidmap_14, r"(?P<y>\d+)y");
-
-// voidmap-1.1.2: r"(?P<m>\d+)m"
-consistent!(voidmap_15, r"(?P<m>\d+)m");
-
-// voidmap-1.1.2: r"(?P<w>\d+)w"
-consistent!(voidmap_16, r"(?P<w>\d+)w");
-
-// voidmap-1.1.2: r"(?P<d>\d+)d"
-consistent!(voidmap_17, r"(?P<d>\d+)d");
-
-// voidmap-1.1.2: r"(?P<h>\d+)h"
-consistent!(voidmap_18, r"(?P<h>\d+)h");
-
-// voidmap-1.1.2: r"C-(.)"
-consistent!(voidmap_19, r"C-(.)");
-
-// qt_generator-0.2.0: r"^\.\./qt[^/]+/"
-consistent!(qt_generator_0, r"^\.\./qt[^/]+/");
-
-// qt_generator-0.2.0: "(href|src)=\"([^\"]*)\""
-consistent!(qt_generator_1, "(href|src)=\"([^\"]*)\"");
-
-// kryptos-0.6.1: r"[01]{5}"
-consistent!(kryptos_0, r"[01]{5}");
-
-// cifar_10_loader-0.2.0: "data_batch_[1-5].bin"
-consistent!(cifar_10_loader_0, "data_batch_[1-5].bin");
-
-// cifar_10_loader-0.2.0: "test_batch.bin"
-consistent!(cifar_10_loader_1, "test_batch.bin");
-
-// circadian-0.6.0: r"^\d+.\d+s$"
-consistent!(circadian_0, r"^\d+.\d+s$");
-
-// circadian-0.6.0: r"^\d+:\d+$"
-consistent!(circadian_1, r"^\d+:\d+$");
-
-// circadian-0.6.0: r"^\d+:\d+m$"
-consistent!(circadian_2, r"^\d+:\d+m$");
-
-// cicada-0.8.1: r"!!"
-consistent!(cicada_0, r"!!");
-
-// cicada-0.8.1: r"^([^`]*)`([^`]+)`(.*)$"
-consistent!(cicada_1, r"^([^`]*)`([^`]+)`(.*)$");
-
-// cicada-0.8.1: r"\*+"
-consistent!(cicada_2, r"\*+");
-
-// cicada-0.8.1: r"([^\$]*)\$\{?([A-Za-z0-9\?\$_]+)\}?(.*)"
-consistent!(cicada_3, r"([^\$]*)\$\{?([A-Za-z0-9\?\$_]+)\}?(.*)");
-
-// cicada-0.8.1: r"^ *alias +([a-zA-Z0-9_\.-]+)=(.*)$"
-consistent!(cicada_4, r"^ *alias +([a-zA-Z0-9_\.-]+)=(.*)$");
-
-// vterm-sys-0.1.0: r"hi"
-consistent!(vterm_sys_0, r"hi");
-
-// skim-0.5.0: r".*?\t"
-consistent!(skim_0, r".*?\t");
-
-// skim-0.5.0: r".*?[\t ]"
-consistent!(skim_1, r".*?[\t ]");
-
-// skim-0.5.0: r"(\{-?[0-9.,q]*?})"
-consistent!(skim_2, r"(\{-?[0-9.,q]*?})");
-
-// skim-0.5.0: r"[ \t\n]+"
-consistent!(skim_3, r"[ \t\n]+");
-
-// skim-0.5.0: r"[ \t\n]+"
-consistent!(skim_4, r"[ \t\n]+");
-
-// skim-0.5.0: r"([^ |]+( +\| +[^ |]*)+)|( +)"
-consistent!(skim_5, r"([^ |]+( +\| +[^ |]*)+)|( +)");
-
-// skim-0.5.0: r" +\| +"
-consistent!(skim_6, r" +\| +");
-
-// skim-0.5.0: r"^(?P<left>-?\d+)?(?P<sep>\.\.)?(?P<right>-?\d+)?$"
-consistent!(skim_7, r"^(?P<left>-?\d+)?(?P<sep>\.\.)?(?P<right>-?\d+)?$");
-
-// skim-0.5.0: ","
-consistent!(skim_8, ",");
-
-// skim-0.5.0: ".*?,"
-consistent!(skim_9, ".*?,");
-
-// skim-0.5.0: ".*?,"
-consistent!(skim_10, ".*?,");
-
-// skim-0.5.0: ","
-consistent!(skim_11, ",");
-
-// skim-0.5.0: r"\x1B\[(?:([0-9]+;[0-9]+[Hf])|([0-9]+[ABCD])|(s|u|2J|K)|([0-9;]*m)|(=[0-9]+[hI]))"
-consistent!(skim_12, r"\x1B\[(?:([0-9]+;[0-9]+[Hf])|([0-9]+[ABCD])|(s|u|2J|K)|([0-9;]*m)|(=[0-9]+[hI]))");
-
-// egg-mode-text-1.14.7: r"[-_./]\z"
-consistent!(egg_mode_text_0, r"[-_./]\z");
-
-// java-properties-1.1.1: "^[ \t\r\n\x0c]*[#!]"
-consistent!(java_properties_0, "^[ \t\r\n\x0c]*[#!]");
-
-// java-properties-1.1.1: r"^[ \t\x0c]*[#!][^\r\n]*$"
-consistent!(java_properties_1, r"^[ \t\x0c]*[#!][^\r\n]*$");
-
-// java-properties-1.1.1: r"^([ \t\x0c]*[:=][ \t\x0c]*|[ \t\x0c]+)$"
-consistent!(java_properties_2, r"^([ \t\x0c]*[:=][ \t\x0c]*|[ \t\x0c]+)$");
-
-// ipaddress-0.1.2: r":.+\."
-consistent!(ipaddress_0, r":.+\.");
-
-// ipaddress-0.1.2: r"\."
-consistent!(ipaddress_1, r"\.");
-
-// ipaddress-0.1.2: r":"
-consistent!(ipaddress_2, r":");
-
-// iptables-0.2.2: r"v(\d+)\.(\d+)\.(\d+)"
-consistent!(iptables_0, r"v(\d+)\.(\d+)\.(\d+)");
-
-// rsure-0.8.1: r"^([^-]+)-(.*)\.dat\.gz$"
-consistent!(rsure_0, r"^([^-]+)-(.*)\.dat\.gz$");
-
-// rs-jsonpath-0.1.0: "^(.*?)(<=|<|==|>=|>)(.*?)$"
-consistent!(rs_jsonpath_0, "^(.*?)(<=|<|==|>=|>)(.*?)$");
-
-// oatie-0.3.0: r"(\n|^)(\w+):([\n\w\W]+?)(\n(?:\w)|(\n\]))"
-consistent!(oatie_0, r"(\n|^)(\w+):([\n\w\W]+?)(\n(?:\w)|(\n\]))");
-
-// weld-0.2.0: "#.*$"
-consistent!(weld_0, "#.*$");
-
-// weld-0.2.0: r"^[A-Za-z$_][A-Za-z0-9$_]*$"
-consistent!(weld_1, r"^[A-Za-z$_][A-Za-z0-9$_]*$");
-
-// weld-0.2.0: r"^[0-9]+[cC]$"
-consistent!(weld_2, r"^[0-9]+[cC]$");
-
-// weld-0.2.0: r"^0b[0-1]+[cC]$"
-consistent!(weld_3, r"^0b[0-1]+[cC]$");
-
-// weld-0.2.0: r"^0x[0-9a-fA-F]+[cC]$"
-consistent!(weld_4, r"^0x[0-9a-fA-F]+[cC]$");
-
-// weld-0.2.0: r"^[0-9]+$"
-consistent!(weld_5, r"^[0-9]+$");
-
-// weld-0.2.0: r"^0b[0-1]+$"
-consistent!(weld_6, r"^0b[0-1]+$");
-
-// weld-0.2.0: r"^0x[0-9a-fA-F]+$"
-consistent!(weld_7, r"^0x[0-9a-fA-F]+$");
-
-// weld-0.2.0: r"^[0-9]+[lL]$"
-consistent!(weld_8, r"^[0-9]+[lL]$");
-
-// weld-0.2.0: r"^0b[0-1]+[lL]$"
-consistent!(weld_9, r"^0b[0-1]+[lL]$");
-
-// weld-0.2.0: r"^0x[0-9a-fA-F]+[lL]$"
-consistent!(weld_10, r"^0x[0-9a-fA-F]+[lL]$");
-
-// webgl_generator-0.1.0: "([(, ])enum\\b"
-consistent!(webgl_generator_0, "([(, ])enum\\b");
-
-// webgl_generator-0.1.0: "\\bAcquireResourcesCallback\\b"
-consistent!(webgl_generator_1, "\\bAcquireResourcesCallback\\b");
-
-// weave-0.2.0: r"^(\d+)(,(\d+))?([acd]).*$"
-consistent!(weave_0, r"^(\d+)(,(\d+))?([acd]).*$");
-
-// wemo-0.0.12: r"<BinaryState>(\d)(\|-?\d+)*</BinaryState>"
-consistent!(wemo_0, r"<BinaryState>(\d)(\|-?\d+)*</BinaryState>");
-
-// webscale-0.9.4: r"(http[s]?://[^\s]+)"
-consistent!(webscale_0, r"(http[s]?://[^\s]+)");
-
-// svgrep-1.1.0: r"^\d+.*$"
-consistent!(svgrep_0, r"^\d+.*$");
-
-// ignore-0.4.2: r"^[\pL\pN]+$"
-consistent!(ignore_0, r"^[\pL\pN]+$");
-
-// ommui_string_patterns-0.1.2: r"^([A-Za-z][0-9A-Za-z_]*)?$"
-consistent!(ommui_string_patterns_0, r"^([A-Za-z][0-9A-Za-z_]*)?$");
-
-// ommui_string_patterns-0.1.2: r"^(\S+(?:.*\S)?)?$"
-consistent!(ommui_string_patterns_1, r"^(\S+(?:.*\S)?)?$");
-
-// opcua-types-0.3.0: "^(?P<min>[0-9]{1,10})(:(?P<max>[0-9]{1,10}))?$"
-consistent!(opcua_types_0, "^(?P<min>[0-9]{1,10})(:(?P<max>[0-9]{1,10}))?$");
-
-// opcua-types-0.3.0: r"^(ns=(?P<ns>[0-9]+);)?(?P<t>[isgb])=(?P<v>.+)$"
-consistent!(opcua_types_1, r"^(ns=(?P<ns>[0-9]+);)?(?P<t>[isgb])=(?P<v>.+)$");
-
-// open_read_later-1.1.1: r"^(.+?)\s*:\s*(.+)$"
-consistent!(open_read_later_0, r"^(.+?)\s*:\s*(.+)$");
-
-// youtube-downloader-0.1.0: r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*"
-consistent!(youtube_downloader_0, r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*");
-
-// yobot-0.1.1: "."
-consistent!(yobot_0, ".");
-
-// yobot-0.1.1: r"."
-consistent!(yobot_1, r".");
-
-// yobot-0.1.1: r".+"
-consistent!(yobot_2, r".+");
-
-// yobot-0.1.1: r"."
-consistent!(yobot_3, r".");
-
-// ubiquity-0.1.5: r"foo"
-consistent!(ubiquity_0, r"foo");
-
-// ubiquity-0.1.5: r"/target/"
-consistent!(ubiquity_1, r"/target/");
-
-// ubiquity-0.1.5: r".DS_Store"
-consistent!(ubiquity_2, r".DS_Store");
-
-// qasm-1.0.0: r"//.*"
-consistent!(qasm_0, r"//.*");
-
-// drill-0.3.5: r"\{\{ *([a-z\._]+) *\}\}"
-consistent!(drill_0, r"\{\{ *([a-z\._]+) *\}\}");
-
-// queryst-2.0.0: r"^([^\]\[]+)"
-consistent!(queryst_0, r"^([^\]\[]+)");
-
-// queryst-2.0.0: r"(\[[^\]\[]*\])"
-consistent!(queryst_1, r"(\[[^\]\[]*\])");
-
-// qui-vive-0.1.0: r"^/(\w+)$"
-consistent!(qui_vive_0, r"^/(\w+)$");
-
-// qui-vive-0.1.0: r"^/key$"
-consistent!(qui_vive_1, r"^/key$");
-
-// qui-vive-0.1.0: r"^/key/(\w+)$"
-consistent!(qui_vive_2, r"^/key/(\w+)$");
-
-// qui-vive-0.1.0: r"^/url$"
-consistent!(qui_vive_3, r"^/url$");
-
-// qui-vive-0.1.0: r"^/url/(\w+)$"
-consistent!(qui_vive_4, r"^/url/(\w+)$");
-
-// qui-vive-0.1.0: r"^/inv$"
-consistent!(qui_vive_5, r"^/inv$");
-
-// qui-vive-0.1.0: r"^/inv/(\w+)$"
-consistent!(qui_vive_6, r"^/inv/(\w+)$");
-
-// subdiff-0.1.0: r"\b"
-// consistent!(subdiff_0, r"\b");
-
-// substudy-0.4.5: r"^(\d+)/(\d+)$"
-consistent!(substudy_0, r"^(\d+)/(\d+)$");
-
-// substudy-0.4.5: r"\s+"
-consistent!(substudy_1, r"\s+");
-
-// substudy-0.4.5: r"<[a-z/][^>]*>"
-consistent!(substudy_2, r"<[a-z/][^>]*>");
-
-// substudy-0.4.5: r"(\([^)]*\)|♪[^♪]*♪|[A-Z]{2,} ?:)"
-consistent!(substudy_3, r"(\([^)]*\)|♪[^♪]*♪|[A-Z]{2,} ?:)");
-
-// substudy-0.4.5: r"\s+"
-consistent!(substudy_4, r"\s+");
-
-// isbnid-0.1.3: r"^(\d(-| )?){9}(x|X|\d|(\d(-| )?){3}\d)$"
-consistent!(isbnid_0, r"^(\d(-| )?){9}(x|X|\d|(\d(-| )?){3}\d)$");
-
-// isbnid-0.1.3: r"[^0-9X]"
-consistent!(isbnid_1, r"[^0-9X]");
-
-// ispc-0.3.5: r"Intel\(r\) SPMD Program Compiler \(ispc\), (\d+\.\d+\.\d+)"
-consistent!(
-    ispc_0,
-    r"Intel\(r\) SPMD Program Compiler \(ispc\), (\d+\.\d+\.\d+)"
-);
diff --git a/vendor/regex-1.4.3/tests/crazy.rs b/vendor/regex-1.4.3/tests/crazy.rs
deleted file mode 100644 (file)
index 56f6cad..0000000
+++ /dev/null
@@ -1,458 +0,0 @@
-mat!(ascii_literal, r"a", "a", Some((0, 1)));
-
-// Some crazy expressions from regular-expressions.info.
-mat!(
-    match_ranges,
-    r"(?-u)\b(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b",
-    "num: 255",
-    Some((5, 8))
-);
-mat!(
-    match_ranges_not,
-    r"(?-u)\b(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b",
-    "num: 256",
-    None
-);
-mat!(match_float1, r"[-+]?[0-9]*\.?[0-9]+", "0.1", Some((0, 3)));
-mat!(match_float2, r"[-+]?[0-9]*\.?[0-9]+", "0.1.2", Some((0, 3)));
-mat!(match_float3, r"[-+]?[0-9]*\.?[0-9]+", "a1.2", Some((1, 4)));
-mat!(match_float4, r"^[-+]?[0-9]*\.?[0-9]+$", "1.a", None);
-mat!(
-    match_email,
-    r"(?i-u)\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b",
-    "mine is jam.slam@gmail.com ",
-    Some((8, 26))
-);
-mat!(
-    match_email_not,
-    r"(?i-u)\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b",
-    "mine is jam.slam@gmail ",
-    None
-);
-mat!(
-    match_email_big,
-    r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
-    "mine is jam.slam@gmail.com ",
-    Some((8, 26))
-);
-mat!(
-    match_date1,
-    r"(?-u)^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$",
-    "1900-01-01",
-    Some((0, 10))
-);
-mat!(
-    match_date2,
-    r"(?-u)^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$",
-    "1900-00-01",
-    None
-);
-mat!(
-    match_date3,
-    r"(?-u)^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$",
-    "1900-13-01",
-    None
-);
-
-// Do some crazy dancing with the start/end assertions.
-matiter!(match_start_end_empty, r"^$", "", (0, 0));
-matiter!(match_start_end_empty_many_1, r"^$^$^$", "", (0, 0));
-matiter!(match_start_end_empty_many_2, r"^^^$$$", "", (0, 0));
-matiter!(match_start_end_empty_rev, r"$^", "", (0, 0));
-matiter!(
-    match_start_end_empty_rep,
-    r"(?:^$)*",
-    "a\nb\nc",
-    (0, 0),
-    (1, 1),
-    (2, 2),
-    (3, 3),
-    (4, 4),
-    (5, 5)
-);
-matiter!(
-    match_start_end_empty_rep_rev,
-    r"(?:$^)*",
-    "a\nb\nc",
-    (0, 0),
-    (1, 1),
-    (2, 2),
-    (3, 3),
-    (4, 4),
-    (5, 5)
-);
-
-// Test negated character classes.
-mat!(negclass_letters, r"[^ac]", "acx", Some((2, 3)));
-mat!(negclass_letter_comma, r"[^a,]", "a,x", Some((2, 3)));
-mat!(negclass_letter_space, r"[^a[:space:]]", "a x", Some((2, 3)));
-mat!(negclass_comma, r"[^,]", ",,x", Some((2, 3)));
-mat!(negclass_space, r"[^[:space:]]", " a", Some((1, 2)));
-mat!(negclass_space_comma, r"[^,[:space:]]", ", a", Some((2, 3)));
-mat!(negclass_comma_space, r"[^[:space:],]", " ,a", Some((2, 3)));
-mat!(negclass_ascii, r"[^[:alpha:]Z]", "A1", Some((1, 2)));
-
-// Test that repeated empty expressions don't loop forever.
-mat!(lazy_many_many, r"((?:.*)*?)=", "a=b", Some((0, 2)));
-mat!(lazy_many_optional, r"((?:.?)*?)=", "a=b", Some((0, 2)));
-mat!(lazy_one_many_many, r"((?:.*)+?)=", "a=b", Some((0, 2)));
-mat!(lazy_one_many_optional, r"((?:.?)+?)=", "a=b", Some((0, 2)));
-mat!(lazy_range_min_many, r"((?:.*){1,}?)=", "a=b", Some((0, 2)));
-mat!(lazy_range_many, r"((?:.*){1,2}?)=", "a=b", Some((0, 2)));
-mat!(greedy_many_many, r"((?:.*)*)=", "a=b", Some((0, 2)));
-mat!(greedy_many_optional, r"((?:.?)*)=", "a=b", Some((0, 2)));
-mat!(greedy_one_many_many, r"((?:.*)+)=", "a=b", Some((0, 2)));
-mat!(greedy_one_many_optional, r"((?:.?)+)=", "a=b", Some((0, 2)));
-mat!(greedy_range_min_many, r"((?:.*){1,})=", "a=b", Some((0, 2)));
-mat!(greedy_range_many, r"((?:.*){1,2})=", "a=b", Some((0, 2)));
-
-// Test that we handle various flavors of empty expressions.
-matiter!(match_empty1, r"", "", (0, 0));
-matiter!(match_empty2, r"", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty3, r"()", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty4, r"()*", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty5, r"()+", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty6, r"()?", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty7, r"()()", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty8, r"()+|z", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty9, r"z|()+", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty10, r"()+|b", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty11, r"b|()+", "abc", (0, 0), (1, 2), (3, 3));
-matiter!(match_empty12, r"|b", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty13, r"b|", "abc", (0, 0), (1, 2), (3, 3));
-matiter!(match_empty14, r"|z", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty15, r"z|", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty16, r"|", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty17, r"||", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty18, r"||z", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty19, r"(?:)|b", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty20, r"b|(?:)", "abc", (0, 0), (1, 2), (3, 3));
-matiter!(match_empty21, r"(?:|)", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty22, r"(?:|)|z", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
-matiter!(match_empty23, r"a(?:)|b", "abc", (0, 1), (1, 2));
-
-// Test that the DFA can handle pathological cases.
-// (This should result in the DFA's cache being flushed too frequently, which
-// should cause it to quit and fall back to the NFA algorithm.)
-#[test]
-fn dfa_handles_pathological_case() {
-    fn ones_and_zeroes(count: usize) -> String {
-        use rand::{thread_rng, Rng};
-
-        let mut rng = thread_rng();
-        let mut s = String::new();
-        for _ in 0..count {
-            if rng.gen() {
-                s.push('1');
-            } else {
-                s.push('0');
-            }
-        }
-        s
-    }
-
-    let re = regex!(r"[01]*1[01]{20}$");
-    let text = {
-        let mut pieces = ones_and_zeroes(100_000);
-        pieces.push('1');
-        pieces.push_str(&ones_and_zeroes(20));
-        pieces
-    };
-    assert!(re.is_match(text!(&*text)));
-}
-
-#[test]
-fn nest_limit_makes_it_parse() {
-    use regex::RegexBuilder;
-
-    RegexBuilder::new(
-        r#"(?-u)
-        2(?:
-          [45]\d{3}|
-          7(?:
-            1[0-267]|
-            2[0-289]|
-            3[0-29]|
-            4[01]|
-            5[1-3]|
-            6[013]|
-            7[0178]|
-            91
-          )|
-          8(?:
-            0[125]|
-            [139][1-6]|
-            2[0157-9]|
-            41|
-            6[1-35]|
-            7[1-5]|
-            8[1-8]|
-            90
-          )|
-          9(?:
-            0[0-2]|
-            1[0-4]|
-            2[568]|
-            3[3-6]|
-            5[5-7]|
-            6[0167]|
-            7[15]|
-            8[0146-9]
-          )
-        )\d{4}|
-        3(?:
-          12?[5-7]\d{2}|
-          0(?:
-            2(?:
-              [025-79]\d|
-              [348]\d{1,2}
-            )|
-            3(?:
-              [2-4]\d|
-              [56]\d?
-            )
-          )|
-          2(?:
-            1\d{2}|
-            2(?:
-              [12]\d|
-              [35]\d{1,2}|
-              4\d?
-            )
-          )|
-          3(?:
-            1\d{2}|
-            2(?:
-              [2356]\d|
-              4\d{1,2}
-            )
-          )|
-          4(?:
-            1\d{2}|
-            2(?:
-              2\d{1,2}|
-              [47]|
-              5\d{2}
-            )
-          )|
-          5(?:
-            1\d{2}|
-            29
-          )|
-          [67]1\d{2}|
-          8(?:
-            1\d{2}|
-            2(?:
-              2\d{2}|
-              3|
-              4\d
-            )
-          )
-        )\d{3}|
-        4(?:
-          0(?:
-            2(?:
-              [09]\d|
-              7
-            )|
-            33\d{2}
-          )|
-          1\d{3}|
-          2(?:
-            1\d{2}|
-            2(?:
-              [25]\d?|
-              [348]\d|
-              [67]\d{1,2}
-            )
-          )|
-          3(?:
-            1\d{2}(?:
-              \d{2}
-            )?|
-            2(?:
-              [045]\d|
-              [236-9]\d{1,2}
-            )|
-            32\d{2}
-          )|
-          4(?:
-            [18]\d{2}|
-            2(?:
-              [2-46]\d{2}|
-              3
-            )|
-            5[25]\d{2}
-          )|
-          5(?:
-            1\d{2}|
-            2(?:
-              3\d|
-              5
-            )
-          )|
-          6(?:
-            [18]\d{2}|
-            2(?:
-              3(?:
-                \d{2}
-              )?|
-              [46]\d{1,2}|
-              5\d{2}|
-              7\d
-            )|
-            5(?:
-              3\d?|
-              4\d|
-              [57]\d{1,2}|
-              6\d{2}|
-              8
-            )
-          )|
-          71\d{2}|
-          8(?:
-            [18]\d{2}|
-            23\d{2}|
-            54\d{2}
-          )|
-          9(?:
-            [18]\d{2}|
-            2[2-5]\d{2}|
-            53\d{1,2}
-          )
-        )\d{3}|
-        5(?:
-          02[03489]\d{2}|
-          1\d{2}|
-          2(?:
-            1\d{2}|
-            2(?:
-              2(?:
-                \d{2}
-              )?|
-              [457]\d{2}
-            )
-          )|
-          3(?:
-            1\d{2}|
-            2(?:
-              [37](?:
-                \d{2}
-              )?|
-              [569]\d{2}
-            )
-          )|
-          4(?:
-            1\d{2}|
-            2[46]\d{2}
-          )|
-          5(?:
-            1\d{2}|
-            26\d{1,2}
-          )|
-          6(?:
-            [18]\d{2}|
-            2|
-            53\d{2}
-          )|
-          7(?:
-            1|
-            24
-          )\d{2}|
-          8(?:
-            1|
-            26
-          )\d{2}|
-          91\d{2}
-        )\d{3}|
-        6(?:
-          0(?:
-            1\d{2}|
-            2(?:
-              3\d{2}|
-              4\d{1,2}
-            )
-          )|
-          2(?:
-            2[2-5]\d{2}|
-            5(?:
-              [3-5]\d{2}|
-              7
-            )|
-            8\d{2}
-          )|
-          3(?:
-            1|
-            2[3478]
-          )\d{2}|
-          4(?:
-            1|
-            2[34]
-          )\d{2}|
-          5(?:
-            1|
-            2[47]
-          )\d{2}|
-          6(?:
-            [18]\d{2}|
-            6(?:
-              2(?:
-                2\d|
-                [34]\d{2}
-              )|
-              5(?:
-                [24]\d{2}|
-                3\d|
-                5\d{1,2}
-              )
-            )
-          )|
-          72[2-5]\d{2}|
-          8(?:
-            1\d{2}|
-            2[2-5]\d{2}
-          )|
-          9(?:
-            1\d{2}|
-            2[2-6]\d{2}
-          )
-        )\d{3}|
-        7(?:
-          (?:
-            02|
-            [3-589]1|
-            6[12]|
-            72[24]
-          )\d{2}|
-          21\d{3}|
-          32
-        )\d{3}|
-        8(?:
-          (?:
-            4[12]|
-            [5-7]2|
-            1\d?
-          )|
-          (?:
-            0|
-            3[12]|
-            [5-7]1|
-            217
-          )\d
-        )\d{4}|
-        9(?:
-          [35]1|
-          (?:
-            [024]2|
-            81
-          )\d|
-          (?:
-            1|
-            [24]1
-          )\d{2}
-        )\d{3}
-        "#,
-    )
-    .build()
-    .unwrap();
-}
diff --git a/vendor/regex-1.4.3/tests/flags.rs b/vendor/regex-1.4.3/tests/flags.rs
deleted file mode 100644 (file)
index c33b82d..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-mat!(match_flag_case, "(?-u)(?i)abc", "ABC", Some((0, 3)));
-mat!(match_flag_weird_case, "(?-u)(?i)a(?-i)bc", "Abc", Some((0, 3)));
-mat!(match_flag_weird_case_not, "(?-u)(?i)a(?-i)bc", "ABC", None);
-mat!(match_flag_case_dotnl, "(?-u)(?is)a(?u:.)", "A\n", Some((0, 2)));
-mat!(
-    match_flag_case_dotnl_toggle,
-    "(?-u)(?is)a(?u:.)(?-is)a(?u:.)",
-    "A\nab",
-    Some((0, 4))
-);
-mat!(
-    match_flag_case_dotnl_toggle_not,
-    "(?-u)(?is)a(?u:.)(?-is)a(?u:.)",
-    "A\na\n",
-    None
-);
-mat!(
-    match_flag_case_dotnl_toggle_ok,
-    "(?-u)(?is)a(?u:.)(?-is:a(?u:.))?",
-    "A\na\n",
-    Some((0, 2))
-);
-mat!(
-    match_flag_multi,
-    r"(?-u)(?m)(?:^\d+$\n?)+",
-    "123\n456\n789",
-    Some((0, 11))
-);
-mat!(match_flag_ungreedy, "(?U)a+", "aa", Some((0, 1)));
-mat!(match_flag_ungreedy_greedy, "(?U)a+?", "aa", Some((0, 2)));
-mat!(match_flag_ungreedy_noop, "(?U)(?-U)a+", "aa", Some((0, 2)));
diff --git a/vendor/regex-1.4.3/tests/fowler.rs b/vendor/regex-1.4.3/tests/fowler.rs
deleted file mode 100644 (file)
index 7f56a75..0000000
+++ /dev/null
@@ -1,1588 +0,0 @@
-// DO NOT EDIT. Automatically generated by 'scripts/regex-match-tests.py'
-// on 2019-09-02 11:07:37.849994.
-
-// Tests from basic.dat
-mat!(match_basic_3, r"abracadabra$", r"abracadabracadabra", Some((7, 18)));
-mat!(match_basic_4, r"a...b", r"abababbb", Some((2, 7)));
-mat!(match_basic_5, r"XXXXXX", r"..XXXXXX", Some((2, 8)));
-mat!(match_basic_6, r"\)", r"()", Some((1, 2)));
-mat!(match_basic_7, r"a]", r"a]a", Some((0, 2)));
-mat!(match_basic_9, r"\}", r"}", Some((0, 1)));
-mat!(match_basic_10, r"\]", r"]", Some((0, 1)));
-mat!(match_basic_12, r"]", r"]", Some((0, 1)));
-mat!(match_basic_15, r"^a", r"ax", Some((0, 1)));
-mat!(match_basic_16, r"\^a", r"a^a", Some((1, 3)));
-mat!(match_basic_17, r"a\^", r"a^", Some((0, 2)));
-mat!(match_basic_18, r"a$", r"aa", Some((1, 2)));
-mat!(match_basic_19, r"a\$", r"a$", Some((0, 2)));
-mat!(match_basic_20, r"^$", r"", Some((0, 0)));
-mat!(match_basic_21, r"$^", r"", Some((0, 0)));
-mat!(match_basic_22, r"a($)", r"aa", Some((1, 2)), Some((2, 2)));
-mat!(match_basic_23, r"a*(^a)", r"aa", Some((0, 1)), Some((0, 1)));
-mat!(match_basic_24, r"(..)*(...)*", r"a", Some((0, 0)));
-mat!(match_basic_25, r"(..)*(...)*", r"abcd", Some((0, 4)), Some((2, 4)));
-mat!(
-    match_basic_26,
-    r"(ab|a)(bc|c)",
-    r"abc",
-    Some((0, 3)),
-    Some((0, 2)),
-    Some((2, 3))
-);
-mat!(match_basic_27, r"(ab)c|abc", r"abc", Some((0, 3)), Some((0, 2)));
-mat!(match_basic_28, r"a{0}b", r"ab", Some((1, 2)));
-mat!(
-    match_basic_29,
-    r"(a*)(b?)(b+)b{3}",
-    r"aaabbbbbbb",
-    Some((0, 10)),
-    Some((0, 3)),
-    Some((3, 4)),
-    Some((4, 7))
-);
-mat!(
-    match_basic_30,
-    r"(a*)(b{0,1})(b{1,})b{3}",
-    r"aaabbbbbbb",
-    Some((0, 10)),
-    Some((0, 3)),
-    Some((3, 4)),
-    Some((4, 7))
-);
-mat!(
-    match_basic_32,
-    r"((a|a)|a)",
-    r"a",
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((0, 1))
-);
-mat!(
-    match_basic_33,
-    r"(a*)(a|aa)",
-    r"aaaa",
-    Some((0, 4)),
-    Some((0, 3)),
-    Some((3, 4))
-);
-mat!(match_basic_34, r"a*(a.|aa)", r"aaaa", Some((0, 4)), Some((2, 4)));
-mat!(
-    match_basic_35,
-    r"a(b)|c(d)|a(e)f",
-    r"aef",
-    Some((0, 3)),
-    None,
-    None,
-    Some((1, 2))
-);
-mat!(match_basic_36, r"(a|b)?.*", r"b", Some((0, 1)), Some((0, 1)));
-mat!(match_basic_37, r"(a|b)c|a(b|c)", r"ac", Some((0, 2)), Some((0, 1)));
-mat!(
-    match_basic_38,
-    r"(a|b)c|a(b|c)",
-    r"ab",
-    Some((0, 2)),
-    None,
-    Some((1, 2))
-);
-mat!(match_basic_39, r"(a|b)*c|(a|ab)*c", r"abc", Some((0, 3)), Some((1, 2)));
-mat!(match_basic_40, r"(a|b)*c|(a|ab)*c", r"xc", Some((1, 2)));
-mat!(
-    match_basic_41,
-    r"(.a|.b).*|.*(.a|.b)",
-    r"xa",
-    Some((0, 2)),
-    Some((0, 2))
-);
-mat!(match_basic_42, r"a?(ab|ba)ab", r"abab", Some((0, 4)), Some((0, 2)));
-mat!(match_basic_43, r"a?(ac{0}b|ba)ab", r"abab", Some((0, 4)), Some((0, 2)));
-mat!(match_basic_44, r"ab|abab", r"abbabab", Some((0, 2)));
-mat!(match_basic_45, r"aba|bab|bba", r"baaabbbaba", Some((5, 8)));
-mat!(match_basic_46, r"aba|bab", r"baaabbbaba", Some((6, 9)));
-mat!(
-    match_basic_47,
-    r"(aa|aaa)*|(a|aaaaa)",
-    r"aa",
-    Some((0, 2)),
-    Some((0, 2))
-);
-mat!(
-    match_basic_48,
-    r"(a.|.a.)*|(a|.a...)",
-    r"aa",
-    Some((0, 2)),
-    Some((0, 2))
-);
-mat!(match_basic_49, r"ab|a", r"xabc", Some((1, 3)));
-mat!(match_basic_50, r"ab|a", r"xxabc", Some((2, 4)));
-mat!(
-    match_basic_51,
-    r"(?i)(?-u)(Ab|cD)*",
-    r"aBcD",
-    Some((0, 4)),
-    Some((2, 4))
-);
-mat!(match_basic_52, r"[^-]", r"--a", Some((2, 3)));
-mat!(match_basic_53, r"[a-]*", r"--a", Some((0, 3)));
-mat!(match_basic_54, r"[a-m-]*", r"--amoma--", Some((0, 4)));
-mat!(
-    match_basic_55,
-    r":::1:::0:|:::1:1:0:",
-    r":::0:::1:::1:::0:",
-    Some((8, 17))
-);
-mat!(
-    match_basic_56,
-    r":::1:::0:|:::1:1:1:",
-    r":::0:::1:::1:::0:",
-    Some((8, 17))
-);
-mat!(match_basic_57, r"[[:upper:]]", r"A", Some((0, 1)));
-mat!(match_basic_58, r"[[:lower:]]+", r"`az{", Some((1, 3)));
-mat!(match_basic_59, r"[[:upper:]]+", r"@AZ[", Some((1, 3)));
-mat!(
-    match_basic_65,
-    r"
-",
-    r"
-",
-    Some((0, 1))
-);
-mat!(
-    match_basic_66,
-    r"
-",
-    r"
-",
-    Some((0, 1))
-);
-mat!(
-    match_basic_67,
-    r"[^a]",
-    r"
-",
-    Some((0, 1))
-);
-mat!(
-    match_basic_68,
-    r"
-a",
-    r"
-a",
-    Some((0, 2))
-);
-mat!(
-    match_basic_69,
-    r"(a)(b)(c)",
-    r"abc",
-    Some((0, 3)),
-    Some((0, 1)),
-    Some((1, 2)),
-    Some((2, 3))
-);
-mat!(match_basic_70, r"xxx", r"xxx", Some((0, 3)));
-mat!(
-    match_basic_71,
-    r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)",
-    r"feb 6,",
-    Some((0, 6))
-);
-mat!(
-    match_basic_72,
-    r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)",
-    r"2/7",
-    Some((0, 3))
-);
-mat!(
-    match_basic_73,
-    r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)",
-    r"feb 1,Feb 6",
-    Some((5, 11))
-);
-mat!(
-    match_basic_74,
-    r"((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))",
-    r"x",
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((0, 1))
-);
-mat!(
-    match_basic_75,
-    r"((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))*",
-    r"xx",
-    Some((0, 2)),
-    Some((1, 2)),
-    Some((1, 2))
-);
-mat!(
-    match_basic_76,
-    r"a?(ab|ba)*",
-    r"ababababababababababababababababababababababababababababababababababababababababa",
-    Some((0, 81)),
-    Some((79, 81))
-);
-mat!(
-    match_basic_77,
-    r"abaa|abbaa|abbbaa|abbbbaa",
-    r"ababbabbbabbbabbbbabbbbaa",
-    Some((18, 25))
-);
-mat!(
-    match_basic_78,
-    r"abaa|abbaa|abbbaa|abbbbaa",
-    r"ababbabbbabbbabbbbabaa",
-    Some((18, 22))
-);
-mat!(
-    match_basic_79,
-    r"aaac|aabc|abac|abbc|baac|babc|bbac|bbbc",
-    r"baaabbbabac",
-    Some((7, 11))
-);
-mat!(match_basic_80, r".*", r"\ 1\7f", Some((0, 2)));
-mat!(
-    match_basic_81,
-    r"aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll",
-    r"XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa",
-    Some((53, 57))
-);
-mat!(match_basic_83, r"a*a*a*a*a*b", r"aaaaaaaaab", Some((0, 10)));
-mat!(match_basic_84, r"^", r"", Some((0, 0)));
-mat!(match_basic_85, r"$", r"", Some((0, 0)));
-mat!(match_basic_86, r"^$", r"", Some((0, 0)));
-mat!(match_basic_87, r"^a$", r"a", Some((0, 1)));
-mat!(match_basic_88, r"abc", r"abc", Some((0, 3)));
-mat!(match_basic_89, r"abc", r"xabcy", Some((1, 4)));
-mat!(match_basic_90, r"abc", r"ababc", Some((2, 5)));
-mat!(match_basic_91, r"ab*c", r"abc", Some((0, 3)));
-mat!(match_basic_92, r"ab*bc", r"abc", Some((0, 3)));
-mat!(match_basic_93, r"ab*bc", r"abbc", Some((0, 4)));
-mat!(match_basic_94, r"ab*bc", r"abbbbc", Some((0, 6)));
-mat!(match_basic_95, r"ab+bc", r"abbc", Some((0, 4)));
-mat!(match_basic_96, r"ab+bc", r"abbbbc", Some((0, 6)));
-mat!(match_basic_97, r"ab?bc", r"abbc", Some((0, 4)));
-mat!(match_basic_98, r"ab?bc", r"abc", Some((0, 3)));
-mat!(match_basic_99, r"ab?c", r"abc", Some((0, 3)));
-mat!(match_basic_100, r"^abc$", r"abc", Some((0, 3)));
-mat!(match_basic_101, r"^abc", r"abcc", Some((0, 3)));
-mat!(match_basic_102, r"abc$", r"aabc", Some((1, 4)));
-mat!(match_basic_103, r"^", r"abc", Some((0, 0)));
-mat!(match_basic_104, r"$", r"abc", Some((3, 3)));
-mat!(match_basic_105, r"a.c", r"abc", Some((0, 3)));
-mat!(match_basic_106, r"a.c", r"axc", Some((0, 3)));
-mat!(match_basic_107, r"a.*c", r"axyzc", Some((0, 5)));
-mat!(match_basic_108, r"a[bc]d", r"abd", Some((0, 3)));
-mat!(match_basic_109, r"a[b-d]e", r"ace", Some((0, 3)));
-mat!(match_basic_110, r"a[b-d]", r"aac", Some((1, 3)));
-mat!(match_basic_111, r"a[-b]", r"a-", Some((0, 2)));
-mat!(match_basic_112, r"a[b-]", r"a-", Some((0, 2)));
-mat!(match_basic_113, r"a]", r"a]", Some((0, 2)));
-mat!(match_basic_114, r"a[]]b", r"a]b", Some((0, 3)));
-mat!(match_basic_115, r"a[^bc]d", r"aed", Some((0, 3)));
-mat!(match_basic_116, r"a[^-b]c", r"adc", Some((0, 3)));
-mat!(match_basic_117, r"a[^]b]c", r"adc", Some((0, 3)));
-mat!(match_basic_118, r"ab|cd", r"abc", Some((0, 2)));
-mat!(match_basic_119, r"ab|cd", r"abcd", Some((0, 2)));
-mat!(match_basic_120, r"a\(b", r"a(b", Some((0, 3)));
-mat!(match_basic_121, r"a\(*b", r"ab", Some((0, 2)));
-mat!(match_basic_122, r"a\(*b", r"a((b", Some((0, 4)));
-mat!(
-    match_basic_123,
-    r"((a))",
-    r"abc",
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((0, 1))
-);
-mat!(
-    match_basic_124,
-    r"(a)b(c)",
-    r"abc",
-    Some((0, 3)),
-    Some((0, 1)),
-    Some((2, 3))
-);
-mat!(match_basic_125, r"a+b+c", r"aabbabc", Some((4, 7)));
-mat!(match_basic_126, r"a*", r"aaa", Some((0, 3)));
-mat!(match_basic_128, r"(a*)*", r"-", Some((0, 0)), None);
-mat!(match_basic_129, r"(a*)+", r"-", Some((0, 0)), Some((0, 0)));
-mat!(match_basic_131, r"(a*|b)*", r"-", Some((0, 0)), None);
-mat!(match_basic_132, r"(a+|b)*", r"ab", Some((0, 2)), Some((1, 2)));
-mat!(match_basic_133, r"(a+|b)+", r"ab", Some((0, 2)), Some((1, 2)));
-mat!(match_basic_134, r"(a+|b)?", r"ab", Some((0, 1)), Some((0, 1)));
-mat!(match_basic_135, r"[^ab]*", r"cde", Some((0, 3)));
-mat!(match_basic_137, r"(^)*", r"-", Some((0, 0)), None);
-mat!(match_basic_138, r"a*", r"", Some((0, 0)));
-mat!(match_basic_139, r"([abc])*d", r"abbbcd", Some((0, 6)), Some((4, 5)));
-mat!(match_basic_140, r"([abc])*bcd", r"abcd", Some((0, 4)), Some((0, 1)));
-mat!(match_basic_141, r"a|b|c|d|e", r"e", Some((0, 1)));
-mat!(match_basic_142, r"(a|b|c|d|e)f", r"ef", Some((0, 2)), Some((0, 1)));
-mat!(match_basic_144, r"((a*|b))*", r"-", Some((0, 0)), None, None);
-mat!(match_basic_145, r"abcd*efg", r"abcdefg", Some((0, 7)));
-mat!(match_basic_146, r"ab*", r"xabyabbbz", Some((1, 3)));
-mat!(match_basic_147, r"ab*", r"xayabbbz", Some((1, 2)));
-mat!(match_basic_148, r"(ab|cd)e", r"abcde", Some((2, 5)), Some((2, 4)));
-mat!(match_basic_149, r"[abhgefdc]ij", r"hij", Some((0, 3)));
-mat!(match_basic_150, r"(a|b)c*d", r"abcd", Some((1, 4)), Some((1, 2)));
-mat!(match_basic_151, r"(ab|ab*)bc", r"abc", Some((0, 3)), Some((0, 1)));
-mat!(match_basic_152, r"a([bc]*)c*", r"abc", Some((0, 3)), Some((1, 3)));
-mat!(
-    match_basic_153,
-    r"a([bc]*)(c*d)",
-    r"abcd",
-    Some((0, 4)),
-    Some((1, 3)),
-    Some((3, 4))
-);
-mat!(
-    match_basic_154,
-    r"a([bc]+)(c*d)",
-    r"abcd",
-    Some((0, 4)),
-    Some((1, 3)),
-    Some((3, 4))
-);
-mat!(
-    match_basic_155,
-    r"a([bc]*)(c+d)",
-    r"abcd",
-    Some((0, 4)),
-    Some((1, 2)),
-    Some((2, 4))
-);
-mat!(match_basic_156, r"a[bcd]*dcdcde", r"adcdcde", Some((0, 7)));
-mat!(match_basic_157, r"(ab|a)b*c", r"abc", Some((0, 3)), Some((0, 2)));
-mat!(
-    match_basic_158,
-    r"((a)(b)c)(d)",
-    r"abcd",
-    Some((0, 4)),
-    Some((0, 3)),
-    Some((0, 1)),
-    Some((1, 2)),
-    Some((3, 4))
-);
-mat!(match_basic_159, r"[A-Za-z_][A-Za-z0-9_]*", r"alpha", Some((0, 5)));
-mat!(match_basic_160, r"^a(bc+|b[eh])g|.h$", r"abh", Some((1, 3)));
-mat!(
-    match_basic_161,
-    r"(bc+d$|ef*g.|h?i(j|k))",
-    r"effgz",
-    Some((0, 5)),
-    Some((0, 5))
-);
-mat!(
-    match_basic_162,
-    r"(bc+d$|ef*g.|h?i(j|k))",
-    r"ij",
-    Some((0, 2)),
-    Some((0, 2)),
-    Some((1, 2))
-);
-mat!(
-    match_basic_163,
-    r"(bc+d$|ef*g.|h?i(j|k))",
-    r"reffgz",
-    Some((1, 6)),
-    Some((1, 6))
-);
-mat!(
-    match_basic_164,
-    r"(((((((((a)))))))))",
-    r"a",
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((0, 1))
-);
-mat!(
-    match_basic_165,
-    r"multiple words",
-    r"multiple words yeah",
-    Some((0, 14))
-);
-mat!(
-    match_basic_166,
-    r"(.*)c(.*)",
-    r"abcde",
-    Some((0, 5)),
-    Some((0, 2)),
-    Some((3, 5))
-);
-mat!(match_basic_167, r"abcd", r"abcd", Some((0, 4)));
-mat!(match_basic_168, r"a(bc)d", r"abcd", Some((0, 4)), Some((1, 3)));
-mat!(match_basic_169, r"a[\ 1-\ 3]?c", r"a\ 2c", Some((0, 3)));
-mat!(
-    match_basic_170,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Muammar Qaddafi",
-    Some((0, 15)),
-    None,
-    Some((10, 12))
-);
-mat!(
-    match_basic_171,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Mo'ammar Gadhafi",
-    Some((0, 16)),
-    None,
-    Some((11, 13))
-);
-mat!(
-    match_basic_172,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Muammar Kaddafi",
-    Some((0, 15)),
-    None,
-    Some((10, 12))
-);
-mat!(
-    match_basic_173,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Muammar Qadhafi",
-    Some((0, 15)),
-    None,
-    Some((10, 12))
-);
-mat!(
-    match_basic_174,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Muammar Gadafi",
-    Some((0, 14)),
-    None,
-    Some((10, 11))
-);
-mat!(
-    match_basic_175,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Mu'ammar Qadafi",
-    Some((0, 15)),
-    None,
-    Some((11, 12))
-);
-mat!(
-    match_basic_176,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Moamar Gaddafi",
-    Some((0, 14)),
-    None,
-    Some((9, 11))
-);
-mat!(
-    match_basic_177,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Mu'ammar Qadhdhafi",
-    Some((0, 18)),
-    None,
-    Some((13, 15))
-);
-mat!(
-    match_basic_178,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Muammar Khaddafi",
-    Some((0, 16)),
-    None,
-    Some((11, 13))
-);
-mat!(
-    match_basic_179,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Muammar Ghaddafy",
-    Some((0, 16)),
-    None,
-    Some((11, 13))
-);
-mat!(
-    match_basic_180,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Muammar Ghadafi",
-    Some((0, 15)),
-    None,
-    Some((11, 12))
-);
-mat!(
-    match_basic_181,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Muammar Ghaddafi",
-    Some((0, 16)),
-    None,
-    Some((11, 13))
-);
-mat!(
-    match_basic_182,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Muamar Kaddafi",
-    Some((0, 14)),
-    None,
-    Some((9, 11))
-);
-mat!(
-    match_basic_183,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Muammar Quathafi",
-    Some((0, 16)),
-    None,
-    Some((11, 13))
-);
-mat!(
-    match_basic_184,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Muammar Gheddafi",
-    Some((0, 16)),
-    None,
-    Some((11, 13))
-);
-mat!(
-    match_basic_185,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Moammar Khadafy",
-    Some((0, 15)),
-    None,
-    Some((11, 12))
-);
-mat!(
-    match_basic_186,
-    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
-    r"Moammar Qudhafi",
-    Some((0, 15)),
-    None,
-    Some((10, 12))
-);
-mat!(match_basic_187, r"a+(b|c)*d+", r"aabcdd", Some((0, 6)), Some((3, 4)));
-mat!(match_basic_188, r"^.+$", r"vivi", Some((0, 4)));
-mat!(match_basic_189, r"^(.+)$", r"vivi", Some((0, 4)), Some((0, 4)));
-mat!(
-    match_basic_190,
-    r"^([^!.]+).att.com!(.+)$",
-    r"gryphon.att.com!eby",
-    Some((0, 19)),
-    Some((0, 7)),
-    Some((16, 19))
-);
-mat!(
-    match_basic_191,
-    r"^([^!]+!)?([^!]+)$",
-    r"bas",
-    Some((0, 3)),
-    None,
-    Some((0, 3))
-);
-mat!(
-    match_basic_192,
-    r"^([^!]+!)?([^!]+)$",
-    r"bar!bas",
-    Some((0, 7)),
-    Some((0, 4)),
-    Some((4, 7))
-);
-mat!(
-    match_basic_193,
-    r"^([^!]+!)?([^!]+)$",
-    r"foo!bas",
-    Some((0, 7)),
-    Some((0, 4)),
-    Some((4, 7))
-);
-mat!(
-    match_basic_194,
-    r"^.+!([^!]+!)([^!]+)$",
-    r"foo!bar!bas",
-    Some((0, 11)),
-    Some((4, 8)),
-    Some((8, 11))
-);
-mat!(
-    match_basic_195,
-    r"((foo)|(bar))!bas",
-    r"bar!bas",
-    Some((0, 7)),
-    Some((0, 3)),
-    None,
-    Some((0, 3))
-);
-mat!(
-    match_basic_196,
-    r"((foo)|(bar))!bas",
-    r"foo!bar!bas",
-    Some((4, 11)),
-    Some((4, 7)),
-    None,
-    Some((4, 7))
-);
-mat!(
-    match_basic_197,
-    r"((foo)|(bar))!bas",
-    r"foo!bas",
-    Some((0, 7)),
-    Some((0, 3)),
-    Some((0, 3))
-);
-mat!(
-    match_basic_198,
-    r"((foo)|bar)!bas",
-    r"bar!bas",
-    Some((0, 7)),
-    Some((0, 3))
-);
-mat!(
-    match_basic_199,
-    r"((foo)|bar)!bas",
-    r"foo!bar!bas",
-    Some((4, 11)),
-    Some((4, 7))
-);
-mat!(
-    match_basic_200,
-    r"((foo)|bar)!bas",
-    r"foo!bas",
-    Some((0, 7)),
-    Some((0, 3)),
-    Some((0, 3))
-);
-mat!(
-    match_basic_201,
-    r"(foo|(bar))!bas",
-    r"bar!bas",
-    Some((0, 7)),
-    Some((0, 3)),
-    Some((0, 3))
-);
-mat!(
-    match_basic_202,
-    r"(foo|(bar))!bas",
-    r"foo!bar!bas",
-    Some((4, 11)),
-    Some((4, 7)),
-    Some((4, 7))
-);
-mat!(
-    match_basic_203,
-    r"(foo|(bar))!bas",
-    r"foo!bas",
-    Some((0, 7)),
-    Some((0, 3))
-);
-mat!(
-    match_basic_204,
-    r"(foo|bar)!bas",
-    r"bar!bas",
-    Some((0, 7)),
-    Some((0, 3))
-);
-mat!(
-    match_basic_205,
-    r"(foo|bar)!bas",
-    r"foo!bar!bas",
-    Some((4, 11)),
-    Some((4, 7))
-);
-mat!(
-    match_basic_206,
-    r"(foo|bar)!bas",
-    r"foo!bas",
-    Some((0, 7)),
-    Some((0, 3))
-);
-mat!(
-    match_basic_207,
-    r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$",
-    r"foo!bar!bas",
-    Some((0, 11)),
-    Some((0, 11)),
-    None,
-    None,
-    Some((4, 8)),
-    Some((8, 11))
-);
-mat!(
-    match_basic_208,
-    r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$",
-    r"bas",
-    Some((0, 3)),
-    None,
-    Some((0, 3))
-);
-mat!(
-    match_basic_209,
-    r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$",
-    r"bar!bas",
-    Some((0, 7)),
-    Some((0, 4)),
-    Some((4, 7))
-);
-mat!(
-    match_basic_210,
-    r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$",
-    r"foo!bar!bas",
-    Some((0, 11)),
-    None,
-    None,
-    Some((4, 8)),
-    Some((8, 11))
-);
-mat!(
-    match_basic_211,
-    r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$",
-    r"foo!bas",
-    Some((0, 7)),
-    Some((0, 4)),
-    Some((4, 7))
-);
-mat!(
-    match_basic_212,
-    r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$",
-    r"bas",
-    Some((0, 3)),
-    Some((0, 3)),
-    None,
-    Some((0, 3))
-);
-mat!(
-    match_basic_213,
-    r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$",
-    r"bar!bas",
-    Some((0, 7)),
-    Some((0, 7)),
-    Some((0, 4)),
-    Some((4, 7))
-);
-mat!(
-    match_basic_214,
-    r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$",
-    r"foo!bar!bas",
-    Some((0, 11)),
-    Some((0, 11)),
-    None,
-    None,
-    Some((4, 8)),
-    Some((8, 11))
-);
-mat!(
-    match_basic_215,
-    r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$",
-    r"foo!bas",
-    Some((0, 7)),
-    Some((0, 7)),
-    Some((0, 4)),
-    Some((4, 7))
-);
-mat!(match_basic_216, r".*(/XXX).*", r"/XXX", Some((0, 4)), Some((0, 4)));
-mat!(match_basic_217, r".*(\\XXX).*", r"\XXX", Some((0, 4)), Some((0, 4)));
-mat!(match_basic_218, r"\\XXX", r"\XXX", Some((0, 4)));
-mat!(match_basic_219, r".*(/000).*", r"/000", Some((0, 4)), Some((0, 4)));
-mat!(match_basic_220, r".*(\\000).*", r"\000", Some((0, 4)), Some((0, 4)));
-mat!(match_basic_221, r"\\000", r"\000", Some((0, 4)));
-
-// Tests from nullsubexpr.dat
-mat!(match_nullsubexpr_3, r"(a*)*", r"a", Some((0, 1)), Some((0, 1)));
-mat!(match_nullsubexpr_5, r"(a*)*", r"x", Some((0, 0)), None);
-mat!(match_nullsubexpr_6, r"(a*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_7, r"(a*)*", r"aaaaaax", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_8, r"(a*)+", r"a", Some((0, 1)), Some((0, 1)));
-mat!(match_nullsubexpr_9, r"(a*)+", r"x", Some((0, 0)), Some((0, 0)));
-mat!(match_nullsubexpr_10, r"(a*)+", r"aaaaaa", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_11, r"(a*)+", r"aaaaaax", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_12, r"(a+)*", r"a", Some((0, 1)), Some((0, 1)));
-mat!(match_nullsubexpr_13, r"(a+)*", r"x", Some((0, 0)));
-mat!(match_nullsubexpr_14, r"(a+)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_15, r"(a+)*", r"aaaaaax", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_16, r"(a+)+", r"a", Some((0, 1)), Some((0, 1)));
-mat!(match_nullsubexpr_17, r"(a+)+", r"x", None);
-mat!(match_nullsubexpr_18, r"(a+)+", r"aaaaaa", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_19, r"(a+)+", r"aaaaaax", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_21, r"([a]*)*", r"a", Some((0, 1)), Some((0, 1)));
-mat!(match_nullsubexpr_23, r"([a]*)*", r"x", Some((0, 0)), None);
-mat!(match_nullsubexpr_24, r"([a]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_25, r"([a]*)*", r"aaaaaax", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_26, r"([a]*)+", r"a", Some((0, 1)), Some((0, 1)));
-mat!(match_nullsubexpr_27, r"([a]*)+", r"x", Some((0, 0)), Some((0, 0)));
-mat!(match_nullsubexpr_28, r"([a]*)+", r"aaaaaa", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_29, r"([a]*)+", r"aaaaaax", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_30, r"([^b]*)*", r"a", Some((0, 1)), Some((0, 1)));
-mat!(match_nullsubexpr_32, r"([^b]*)*", r"b", Some((0, 0)), None);
-mat!(match_nullsubexpr_33, r"([^b]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
-mat!(
-    match_nullsubexpr_34,
-    r"([^b]*)*",
-    r"aaaaaab",
-    Some((0, 6)),
-    Some((0, 6))
-);
-mat!(match_nullsubexpr_35, r"([ab]*)*", r"a", Some((0, 1)), Some((0, 1)));
-mat!(match_nullsubexpr_36, r"([ab]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_37, r"([ab]*)*", r"ababab", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_38, r"([ab]*)*", r"bababa", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_39, r"([ab]*)*", r"b", Some((0, 1)), Some((0, 1)));
-mat!(match_nullsubexpr_40, r"([ab]*)*", r"bbbbbb", Some((0, 6)), Some((0, 6)));
-mat!(
-    match_nullsubexpr_41,
-    r"([ab]*)*",
-    r"aaaabcde",
-    Some((0, 5)),
-    Some((0, 5))
-);
-mat!(match_nullsubexpr_42, r"([^a]*)*", r"b", Some((0, 1)), Some((0, 1)));
-mat!(match_nullsubexpr_43, r"([^a]*)*", r"bbbbbb", Some((0, 6)), Some((0, 6)));
-mat!(match_nullsubexpr_45, r"([^a]*)*", r"aaaaaa", Some((0, 0)), None);
-mat!(
-    match_nullsubexpr_46,
-    r"([^ab]*)*",
-    r"ccccxx",
-    Some((0, 6)),
-    Some((0, 6))
-);
-mat!(match_nullsubexpr_48, r"([^ab]*)*", r"ababab", Some((0, 0)), None);
-mat!(
-    match_nullsubexpr_50,
-    r"((z)+|a)*",
-    r"zabcde",
-    Some((0, 2)),
-    Some((1, 2))
-);
-mat!(
-    match_nullsubexpr_69,
-    r"(a*)*(x)",
-    r"x",
-    Some((0, 1)),
-    None,
-    Some((0, 1))
-);
-mat!(
-    match_nullsubexpr_70,
-    r"(a*)*(x)",
-    r"ax",
-    Some((0, 2)),
-    Some((0, 1)),
-    Some((1, 2))
-);
-mat!(
-    match_nullsubexpr_71,
-    r"(a*)*(x)",
-    r"axa",
-    Some((0, 2)),
-    Some((0, 1)),
-    Some((1, 2))
-);
-mat!(
-    match_nullsubexpr_73,
-    r"(a*)+(x)",
-    r"x",
-    Some((0, 1)),
-    Some((0, 0)),
-    Some((0, 1))
-);
-mat!(
-    match_nullsubexpr_74,
-    r"(a*)+(x)",
-    r"ax",
-    Some((0, 2)),
-    Some((0, 1)),
-    Some((1, 2))
-);
-mat!(
-    match_nullsubexpr_75,
-    r"(a*)+(x)",
-    r"axa",
-    Some((0, 2)),
-    Some((0, 1)),
-    Some((1, 2))
-);
-mat!(
-    match_nullsubexpr_77,
-    r"(a*){2}(x)",
-    r"x",
-    Some((0, 1)),
-    Some((0, 0)),
-    Some((0, 1))
-);
-mat!(
-    match_nullsubexpr_78,
-    r"(a*){2}(x)",
-    r"ax",
-    Some((0, 2)),
-    Some((1, 1)),
-    Some((1, 2))
-);
-mat!(
-    match_nullsubexpr_79,
-    r"(a*){2}(x)",
-    r"axa",
-    Some((0, 2)),
-    Some((1, 1)),
-    Some((1, 2))
-);
-
-// Tests from repetition.dat
-mat!(match_repetition_10, r"((..)|(.))", r"", None);
-mat!(match_repetition_11, r"((..)|(.))((..)|(.))", r"", None);
-mat!(match_repetition_12, r"((..)|(.))((..)|(.))((..)|(.))", r"", None);
-mat!(match_repetition_14, r"((..)|(.)){1}", r"", None);
-mat!(match_repetition_15, r"((..)|(.)){2}", r"", None);
-mat!(match_repetition_16, r"((..)|(.)){3}", r"", None);
-mat!(match_repetition_18, r"((..)|(.))*", r"", Some((0, 0)));
-mat!(
-    match_repetition_20,
-    r"((..)|(.))",
-    r"a",
-    Some((0, 1)),
-    Some((0, 1)),
-    None,
-    Some((0, 1))
-);
-mat!(match_repetition_21, r"((..)|(.))((..)|(.))", r"a", None);
-mat!(match_repetition_22, r"((..)|(.))((..)|(.))((..)|(.))", r"a", None);
-mat!(
-    match_repetition_24,
-    r"((..)|(.)){1}",
-    r"a",
-    Some((0, 1)),
-    Some((0, 1)),
-    None,
-    Some((0, 1))
-);
-mat!(match_repetition_25, r"((..)|(.)){2}", r"a", None);
-mat!(match_repetition_26, r"((..)|(.)){3}", r"a", None);
-mat!(
-    match_repetition_28,
-    r"((..)|(.))*",
-    r"a",
-    Some((0, 1)),
-    Some((0, 1)),
-    None,
-    Some((0, 1))
-);
-mat!(
-    match_repetition_30,
-    r"((..)|(.))",
-    r"aa",
-    Some((0, 2)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None
-);
-mat!(
-    match_repetition_31,
-    r"((..)|(.))((..)|(.))",
-    r"aa",
-    Some((0, 2)),
-    Some((0, 1)),
-    None,
-    Some((0, 1)),
-    Some((1, 2)),
-    None,
-    Some((1, 2))
-);
-mat!(match_repetition_32, r"((..)|(.))((..)|(.))((..)|(.))", r"aa", None);
-mat!(
-    match_repetition_34,
-    r"((..)|(.)){1}",
-    r"aa",
-    Some((0, 2)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None
-);
-mat!(
-    match_repetition_35,
-    r"((..)|(.)){2}",
-    r"aa",
-    Some((0, 2)),
-    Some((1, 2)),
-    None,
-    Some((1, 2))
-);
-mat!(match_repetition_36, r"((..)|(.)){3}", r"aa", None);
-mat!(
-    match_repetition_38,
-    r"((..)|(.))*",
-    r"aa",
-    Some((0, 2)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None
-);
-mat!(
-    match_repetition_40,
-    r"((..)|(.))",
-    r"aaa",
-    Some((0, 2)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None
-);
-mat!(
-    match_repetition_41,
-    r"((..)|(.))((..)|(.))",
-    r"aaa",
-    Some((0, 3)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None,
-    Some((2, 3)),
-    None,
-    Some((2, 3))
-);
-mat!(
-    match_repetition_42,
-    r"((..)|(.))((..)|(.))((..)|(.))",
-    r"aaa",
-    Some((0, 3)),
-    Some((0, 1)),
-    None,
-    Some((0, 1)),
-    Some((1, 2)),
-    None,
-    Some((1, 2)),
-    Some((2, 3)),
-    None,
-    Some((2, 3))
-);
-mat!(
-    match_repetition_44,
-    r"((..)|(.)){1}",
-    r"aaa",
-    Some((0, 2)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None
-);
-mat!(
-    match_repetition_46,
-    r"((..)|(.)){2}",
-    r"aaa",
-    Some((0, 3)),
-    Some((2, 3)),
-    Some((0, 2)),
-    Some((2, 3))
-);
-mat!(
-    match_repetition_47,
-    r"((..)|(.)){3}",
-    r"aaa",
-    Some((0, 3)),
-    Some((2, 3)),
-    None,
-    Some((2, 3))
-);
-mat!(
-    match_repetition_50,
-    r"((..)|(.))*",
-    r"aaa",
-    Some((0, 3)),
-    Some((2, 3)),
-    Some((0, 2)),
-    Some((2, 3))
-);
-mat!(
-    match_repetition_52,
-    r"((..)|(.))",
-    r"aaaa",
-    Some((0, 2)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None
-);
-mat!(
-    match_repetition_53,
-    r"((..)|(.))((..)|(.))",
-    r"aaaa",
-    Some((0, 4)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None,
-    Some((2, 4)),
-    Some((2, 4)),
-    None
-);
-mat!(
-    match_repetition_54,
-    r"((..)|(.))((..)|(.))((..)|(.))",
-    r"aaaa",
-    Some((0, 4)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None,
-    Some((2, 3)),
-    None,
-    Some((2, 3)),
-    Some((3, 4)),
-    None,
-    Some((3, 4))
-);
-mat!(
-    match_repetition_56,
-    r"((..)|(.)){1}",
-    r"aaaa",
-    Some((0, 2)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None
-);
-mat!(
-    match_repetition_57,
-    r"((..)|(.)){2}",
-    r"aaaa",
-    Some((0, 4)),
-    Some((2, 4)),
-    Some((2, 4)),
-    None
-);
-mat!(
-    match_repetition_59,
-    r"((..)|(.)){3}",
-    r"aaaa",
-    Some((0, 4)),
-    Some((3, 4)),
-    Some((0, 2)),
-    Some((3, 4))
-);
-mat!(
-    match_repetition_61,
-    r"((..)|(.))*",
-    r"aaaa",
-    Some((0, 4)),
-    Some((2, 4)),
-    Some((2, 4)),
-    None
-);
-mat!(
-    match_repetition_63,
-    r"((..)|(.))",
-    r"aaaaa",
-    Some((0, 2)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None
-);
-mat!(
-    match_repetition_64,
-    r"((..)|(.))((..)|(.))",
-    r"aaaaa",
-    Some((0, 4)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None,
-    Some((2, 4)),
-    Some((2, 4)),
-    None
-);
-mat!(
-    match_repetition_65,
-    r"((..)|(.))((..)|(.))((..)|(.))",
-    r"aaaaa",
-    Some((0, 5)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None,
-    Some((2, 4)),
-    Some((2, 4)),
-    None,
-    Some((4, 5)),
-    None,
-    Some((4, 5))
-);
-mat!(
-    match_repetition_67,
-    r"((..)|(.)){1}",
-    r"aaaaa",
-    Some((0, 2)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None
-);
-mat!(
-    match_repetition_68,
-    r"((..)|(.)){2}",
-    r"aaaaa",
-    Some((0, 4)),
-    Some((2, 4)),
-    Some((2, 4)),
-    None
-);
-mat!(
-    match_repetition_70,
-    r"((..)|(.)){3}",
-    r"aaaaa",
-    Some((0, 5)),
-    Some((4, 5)),
-    Some((2, 4)),
-    Some((4, 5))
-);
-mat!(
-    match_repetition_73,
-    r"((..)|(.))*",
-    r"aaaaa",
-    Some((0, 5)),
-    Some((4, 5)),
-    Some((2, 4)),
-    Some((4, 5))
-);
-mat!(
-    match_repetition_75,
-    r"((..)|(.))",
-    r"aaaaaa",
-    Some((0, 2)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None
-);
-mat!(
-    match_repetition_76,
-    r"((..)|(.))((..)|(.))",
-    r"aaaaaa",
-    Some((0, 4)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None,
-    Some((2, 4)),
-    Some((2, 4)),
-    None
-);
-mat!(
-    match_repetition_77,
-    r"((..)|(.))((..)|(.))((..)|(.))",
-    r"aaaaaa",
-    Some((0, 6)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None,
-    Some((2, 4)),
-    Some((2, 4)),
-    None,
-    Some((4, 6)),
-    Some((4, 6)),
-    None
-);
-mat!(
-    match_repetition_79,
-    r"((..)|(.)){1}",
-    r"aaaaaa",
-    Some((0, 2)),
-    Some((0, 2)),
-    Some((0, 2)),
-    None
-);
-mat!(
-    match_repetition_80,
-    r"((..)|(.)){2}",
-    r"aaaaaa",
-    Some((0, 4)),
-    Some((2, 4)),
-    Some((2, 4)),
-    None
-);
-mat!(
-    match_repetition_81,
-    r"((..)|(.)){3}",
-    r"aaaaaa",
-    Some((0, 6)),
-    Some((4, 6)),
-    Some((4, 6)),
-    None
-);
-mat!(
-    match_repetition_83,
-    r"((..)|(.))*",
-    r"aaaaaa",
-    Some((0, 6)),
-    Some((4, 6)),
-    Some((4, 6)),
-    None
-);
-mat!(
-    match_repetition_90,
-    r"X(.?){0,}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((7, 8))
-);
-mat!(
-    match_repetition_91,
-    r"X(.?){1,}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((7, 8))
-);
-mat!(
-    match_repetition_92,
-    r"X(.?){2,}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((7, 8))
-);
-mat!(
-    match_repetition_93,
-    r"X(.?){3,}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((7, 8))
-);
-mat!(
-    match_repetition_94,
-    r"X(.?){4,}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((7, 8))
-);
-mat!(
-    match_repetition_95,
-    r"X(.?){5,}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((7, 8))
-);
-mat!(
-    match_repetition_96,
-    r"X(.?){6,}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((7, 8))
-);
-mat!(
-    match_repetition_97,
-    r"X(.?){7,}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((7, 8))
-);
-mat!(
-    match_repetition_98,
-    r"X(.?){8,}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((8, 8))
-);
-mat!(
-    match_repetition_100,
-    r"X(.?){0,8}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((8, 8))
-);
-mat!(
-    match_repetition_102,
-    r"X(.?){1,8}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((8, 8))
-);
-mat!(
-    match_repetition_104,
-    r"X(.?){2,8}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((8, 8))
-);
-mat!(
-    match_repetition_106,
-    r"X(.?){3,8}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((8, 8))
-);
-mat!(
-    match_repetition_108,
-    r"X(.?){4,8}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((8, 8))
-);
-mat!(
-    match_repetition_110,
-    r"X(.?){5,8}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((8, 8))
-);
-mat!(
-    match_repetition_112,
-    r"X(.?){6,8}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((8, 8))
-);
-mat!(
-    match_repetition_114,
-    r"X(.?){7,8}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((8, 8))
-);
-mat!(
-    match_repetition_115,
-    r"X(.?){8,8}Y",
-    r"X1234567Y",
-    Some((0, 9)),
-    Some((8, 8))
-);
-mat!(
-    match_repetition_126,
-    r"(a|ab|c|bcd){0,}(d*)",
-    r"ababcd",
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((1, 1))
-);
-mat!(
-    match_repetition_127,
-    r"(a|ab|c|bcd){1,}(d*)",
-    r"ababcd",
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((1, 1))
-);
-mat!(
-    match_repetition_128,
-    r"(a|ab|c|bcd){2,}(d*)",
-    r"ababcd",
-    Some((0, 6)),
-    Some((3, 6)),
-    Some((6, 6))
-);
-mat!(
-    match_repetition_129,
-    r"(a|ab|c|bcd){3,}(d*)",
-    r"ababcd",
-    Some((0, 6)),
-    Some((3, 6)),
-    Some((6, 6))
-);
-mat!(match_repetition_130, r"(a|ab|c|bcd){4,}(d*)", r"ababcd", None);
-mat!(
-    match_repetition_131,
-    r"(a|ab|c|bcd){0,10}(d*)",
-    r"ababcd",
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((1, 1))
-);
-mat!(
-    match_repetition_132,
-    r"(a|ab|c|bcd){1,10}(d*)",
-    r"ababcd",
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((1, 1))
-);
-mat!(
-    match_repetition_133,
-    r"(a|ab|c|bcd){2,10}(d*)",
-    r"ababcd",
-    Some((0, 6)),
-    Some((3, 6)),
-    Some((6, 6))
-);
-mat!(
-    match_repetition_134,
-    r"(a|ab|c|bcd){3,10}(d*)",
-    r"ababcd",
-    Some((0, 6)),
-    Some((3, 6)),
-    Some((6, 6))
-);
-mat!(match_repetition_135, r"(a|ab|c|bcd){4,10}(d*)", r"ababcd", None);
-mat!(
-    match_repetition_136,
-    r"(a|ab|c|bcd)*(d*)",
-    r"ababcd",
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((1, 1))
-);
-mat!(
-    match_repetition_137,
-    r"(a|ab|c|bcd)+(d*)",
-    r"ababcd",
-    Some((0, 1)),
-    Some((0, 1)),
-    Some((1, 1))
-);
-mat!(
-    match_repetition_143,
-    r"(ab|a|c|bcd){0,}(d*)",
-    r"ababcd",
-    Some((0, 6)),
-    Some((4, 5)),
-    Some((5, 6))
-);
-mat!(
-    match_repetition_145,
-    r"(ab|a|c|bcd){1,}(d*)",
-    r"ababcd",
-    Some((0, 6)),
-    Some((4, 5)),
-    Some((5, 6))
-);
-mat!(
-    match_repetition_147,
-    r"(ab|a|c|bcd){2,}(d*)",
-    r"ababcd",
-    Some((0, 6)),
-    Some((4, 5)),
-    Some((5, 6))
-);
-mat!(
-    match_repetition_149,
-    r"(ab|a|c|bcd){3,}(d*)",
-    r"ababcd",
-    Some((0, 6)),
-    Some((4, 5)),
-    Some((5, 6))
-);
-mat!(match_repetition_150, r"(ab|a|c|bcd){4,}(d*)", r"ababcd", None);
-mat!(
-    match_repetition_152,
-    r"(ab|a|c|bcd){0,10}(d*)",
-    r"ababcd",
-    Some((0, 6)),
-    Some((4, 5)),
-    Some((5, 6))
-);
-mat!(
-    match_repetition_154,
-    r"(ab|a|c|bcd){1,10}(d*)",
-    r"ababcd",
-    Some((0, 6)),
-    Some((4, 5)),
-    Some((5, 6))
-);
-mat!(
-    match_repetition_156,
-    r"(ab|a|c|bcd){2,10}(d*)",
-    r"ababcd",
-    Some((0, 6)),
-    Some((4, 5)),
-    Some((5, 6))
-);
-mat!(
-    match_repetition_158,
-    r"(ab|a|c|bcd){3,10}(d*)",
-    r"ababcd",
-    Some((0, 6)),
-    Some((4, 5)),
-    Some((5, 6))
-);
-mat!(match_repetition_159, r"(ab|a|c|bcd){4,10}(d*)", r"ababcd", None);
-mat!(
-    match_repetition_161,
-    r"(ab|a|c|bcd)*(d*)",
-    r"ababcd",
-    Some((0, 6)),
-    Some((4, 5)),
-    Some((5, 6))
-);
-mat!(
-    match_repetition_163,
-    r"(ab|a|c|bcd)+(d*)",
-    r"ababcd",
-    Some((0, 6)),
-    Some((4, 5)),
-    Some((5, 6))
-);
diff --git a/vendor/regex-1.4.3/tests/macros.rs b/vendor/regex-1.4.3/tests/macros.rs
deleted file mode 100644 (file)
index e70e948..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-// Convenience macros.
-
-macro_rules! findall {
-    ($re:expr, $text:expr) => {{
-        $re.find_iter(text!($text))
-           .map(|m| (m.start(), m.end())).collect::<Vec<_>>()
-    }}
-}
-
-// Macros for automatically producing tests.
-
-macro_rules! ismatch {
-    ($name:ident, $re:expr, $text:expr, $ismatch:expr) => {
-        #[test]
-        fn $name() {
-            let re = regex!($re);
-            assert_eq!($ismatch, re.is_match(text!($text)));
-        }
-    };
-}
-
-macro_rules! mat(
-    ($name:ident, $re:expr, $text:expr, $($loc:tt)+) => (
-        #[test]
-        fn $name() {
-            let text = text!($text);
-            let expected: Vec<Option<_>> = vec![$($loc)+];
-            let r = regex!($re);
-            let got: Vec<Option<_>> = match r.captures(text) {
-                Some(c) => {
-                    assert!(r.is_match(text));
-                    assert!(r.shortest_match(text).is_some());
-                    r.capture_names()
-                     .enumerate()
-                     .map(|(i, _)| c.get(i).map(|m| (m.start(), m.end())))
-                     .collect()
-                }
-                None => vec![None],
-            };
-            // The test set sometimes leave out capture groups, so truncate
-            // actual capture groups to match test set.
-            let mut sgot = &got[..];
-            if sgot.len() > expected.len() {
-                sgot = &sgot[0..expected.len()]
-            }
-            if expected != sgot {
-                panic!("For RE '{}' against '{:?}', \
-                        expected '{:?}' but got '{:?}'",
-                       $re, text, expected, sgot);
-            }
-        }
-    );
-);
-
-macro_rules! matiter(
-    ($name:ident, $re:expr, $text:expr) => (
-        #[test]
-        fn $name() {
-            let text = text!($text);
-            let expected: Vec<(usize, usize)> = vec![];
-            let r = regex!($re);
-            let got: Vec<_> =
-                r.find_iter(text).map(|m| (m.start(), m.end())).collect();
-            if expected != got {
-                panic!("For RE '{}' against '{:?}', \
-                        expected '{:?}' but got '{:?}'",
-                       $re, text, expected, got);
-            }
-            let captures_got: Vec<_> =
-                r.captures_iter(text)
-                 .map(|c| c.get(0).unwrap())
-                 .map(|m| (m.start(), m.end()))
-                 .collect();
-            if captures_got != got {
-                panic!("For RE '{}' against '{:?}', \
-                        got '{:?}' using find_iter but got '{:?}' \
-                        using captures_iter",
-                       $re, text, got, captures_got);
-            }
-        }
-    );
-    ($name:ident, $re:expr, $text:expr, $($loc:tt)+) => (
-        #[test]
-        fn $name() {
-            let text = text!($text);
-            let expected: Vec<_> = vec![$($loc)+];
-            let r = regex!($re);
-            let got: Vec<_> =
-                r.find_iter(text).map(|m| (m.start(), m.end())).collect();
-            if expected != got {
-                panic!("For RE '{}' against '{:?}', \
-                        expected '{:?}' but got '{:?}'",
-                       $re, text, expected, got);
-            }
-            let captures_got: Vec<_> =
-                r.captures_iter(text)
-                 .map(|c| c.get(0).unwrap())
-                 .map(|m| (m.start(), m.end()))
-                 .collect();
-            if captures_got != got {
-                panic!("For RE '{}' against '{:?}', \
-                        got '{:?}' using find_iter but got '{:?}' \
-                        using captures_iter",
-                       $re, text, got, captures_got);
-            }
-        }
-    );
-);
-
-macro_rules! matset {
-    ($name:ident, $res:expr, $text:expr, $($match_index:expr),*) => {
-        #[test]
-        fn $name() {
-            let text = text!($text);
-            let set = regex_set!($res);
-            assert!(set.is_match(text));
-            let expected = vec![$($match_index),*];
-            let matches = set.matches(text);
-            assert!(matches.matched_any());
-            let got: Vec<_> = matches.into_iter().collect();
-            assert_eq!(expected, got);
-        }
-    }
-}
-
-macro_rules! nomatset {
-    ($name:ident, $res:expr, $text:expr) => {
-        #[test]
-        fn $name() {
-            let text = text!($text);
-            let set = regex_set!($res);
-            assert!(!set.is_match(text));
-            let matches = set.matches(text);
-            assert!(!matches.matched_any());
-            assert_eq!(0, matches.into_iter().count());
-        }
-    }
-}
-
-macro_rules! split {
-    ($name:ident, $re:expr, $text:expr, $expected:expr) => {
-        #[test]
-        fn $name() {
-            let re = regex!($re);
-            let splitted: Vec<_> = re.split(t!($text)).collect();
-            assert_eq!($expected, &*splitted);
-        }
-    }
-}
-
-macro_rules! splitn {
-    ($name:ident, $re:expr, $text:expr, $limit:expr, $expected:expr) => {
-        #[test]
-        fn $name() {
-            let re = regex!($re);
-            let splitted: Vec<_> = re.splitn(t!($text), $limit).collect();
-            assert_eq!($expected, &*splitted);
-        }
-    }
-}
diff --git a/vendor/regex-1.4.3/tests/macros_bytes.rs b/vendor/regex-1.4.3/tests/macros_bytes.rs
deleted file mode 100644 (file)
index 03c370d..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// Macros for use in writing tests generic over &str/&[u8].
-macro_rules! text { ($text:expr) => { $text.as_bytes() } }
-macro_rules! t { ($re:expr) => { text!($re) } }
-macro_rules! match_text { ($text:expr) => { $text.as_bytes() } }
-macro_rules! use_ { ($($path: tt)*) => { use regex::bytes::$($path)*; } }
-macro_rules! empty_vec { () => { <Vec<&[u8]>>::new() } }
-
-macro_rules! bytes { ($text:expr) => { $text } }
-
-macro_rules! no_expand {
-    ($text:expr) => {{
-        use regex::bytes::NoExpand;
-        NoExpand(text!($text))
-    }}
-}
-
-macro_rules! show {
-    ($text:expr) => {{
-        use std::ascii::escape_default;
-        let mut s = vec![];
-        for &b in bytes!($text) {
-            s.extend(escape_default(b));
-        }
-        String::from_utf8(s).unwrap()
-    }}
-}
-
-macro_rules! expand {
-    ($name:ident, $re:expr, $text:expr, $expand:expr, $expected:expr) => {
-        #[test]
-        fn $name() {
-            let re = regex!($re);
-            let cap = re.captures(t!($text)).unwrap();
-
-            let mut got = vec![];
-            cap.expand(t!($expand), &mut got);
-            assert_eq!(show!(t!($expected)), show!(&*got));
-        }
-    }
-}
diff --git a/vendor/regex-1.4.3/tests/macros_str.rs b/vendor/regex-1.4.3/tests/macros_str.rs
deleted file mode 100644 (file)
index 9b996b3..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// Macros for use in writing tests generic over &str/&[u8].
-macro_rules! text { ($text:expr) => { $text } }
-macro_rules! t { ($text:expr) => { text!($text) } }
-macro_rules! match_text { ($text:expr) => { $text.as_str() } }
-macro_rules! use_ { ($($path: tt)*) => { use regex::$($path)*; } }
-macro_rules! empty_vec { () => { <Vec<&str>>::new() } }
-
-macro_rules! no_expand {
-    ($text:expr) => {{
-        use regex::NoExpand;
-        NoExpand(text!($text))
-    }}
-}
-
-macro_rules! show { ($text:expr) => { $text } }
-
-// N.B. The expansion API for &str and &[u8] APIs differs slightly for now,
-// but they should be unified in 1.0. Then we can move this macro back into
-// tests/api.rs where it is used. ---AG
-macro_rules! expand {
-    ($name:ident, $re:expr, $text:expr, $expand:expr, $expected:expr) => {
-        #[test]
-        fn $name() {
-            let re = regex!($re);
-            let cap = re.captures(t!($text)).unwrap();
-
-            let mut got = String::new();
-            cap.expand(t!($expand), &mut got);
-            assert_eq!(show!(t!($expected)), show!(&*got));
-        }
-    }
-}
-
-#[cfg(feature = "pattern")]
-macro_rules! searcher_expr { ($e:expr) => ($e) }
-#[cfg(not(feature = "pattern"))]
-macro_rules! searcher_expr { ($e:expr) => ({}) }
diff --git a/vendor/regex-1.4.3/tests/misc.rs b/vendor/regex-1.4.3/tests/misc.rs
deleted file mode 100644 (file)
index 314811e..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-mat!(prefix_literal_match, r"^abc", r"abc", Some((0, 3)));
-mat!(prefix_literal_nomatch, r"^abc", r"zabc", None);
-mat!(one_literal_edge, r"abc", r"xxxxxab", None);
-matiter!(terminates, r"a$", r"a", (0, 1));
diff --git a/vendor/regex-1.4.3/tests/multiline.rs b/vendor/regex-1.4.3/tests/multiline.rs
deleted file mode 100644 (file)
index 62ee47b..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-matiter!(
-    match_multi_1,
-    r"(?m)^[a-z]+$",
-    "abc\ndef\nxyz",
-    (0, 3),
-    (4, 7),
-    (8, 11)
-);
-matiter!(match_multi_2, r"(?m)^$", "abc\ndef\nxyz");
-matiter!(match_multi_3, r"(?m)^", "abc\ndef\nxyz", (0, 0), (4, 4), (8, 8));
-matiter!(match_multi_4, r"(?m)$", "abc\ndef\nxyz", (3, 3), (7, 7), (11, 11));
-matiter!(
-    match_multi_5,
-    r"(?m)^[a-z]",
-    "abc\ndef\nxyz",
-    (0, 1),
-    (4, 5),
-    (8, 9)
-);
-matiter!(match_multi_6, r"(?m)[a-z]^", "abc\ndef\nxyz");
-matiter!(
-    match_multi_7,
-    r"(?m)[a-z]$",
-    "abc\ndef\nxyz",
-    (2, 3),
-    (6, 7),
-    (10, 11)
-);
-matiter!(match_multi_8, r"(?m)$[a-z]", "abc\ndef\nxyz");
-matiter!(match_multi_9, r"(?m)^$", "", (0, 0));
-
-matiter!(
-    match_multi_rep_1,
-    r"(?m)(?:^$)*",
-    "a\nb\nc",
-    (0, 0),
-    (1, 1),
-    (2, 2),
-    (3, 3),
-    (4, 4),
-    (5, 5)
-);
-matiter!(
-    match_multi_rep_2,
-    r"(?m)(?:^|a)+",
-    "a\naaa\n",
-    (0, 0),
-    (2, 2),
-    (3, 5),
-    (6, 6)
-);
-matiter!(
-    match_multi_rep_3,
-    r"(?m)(?:^|a)*",
-    "a\naaa\n",
-    (0, 1),
-    (2, 5),
-    (6, 6)
-);
-matiter!(
-    match_multi_rep_4,
-    r"(?m)(?:^[a-z])+",
-    "abc\ndef\nxyz",
-    (0, 1),
-    (4, 5),
-    (8, 9)
-);
-matiter!(
-    match_multi_rep_5,
-    r"(?m)(?:^[a-z]{3}\n?)+",
-    "abc\ndef\nxyz",
-    (0, 11)
-);
-matiter!(
-    match_multi_rep_6,
-    r"(?m)(?:^[a-z]{3}\n?)*",
-    "abc\ndef\nxyz",
-    (0, 11)
-);
-matiter!(
-    match_multi_rep_7,
-    r"(?m)(?:\n?[a-z]{3}$)+",
-    "abc\ndef\nxyz",
-    (0, 11)
-);
-matiter!(
-    match_multi_rep_8,
-    r"(?m)(?:\n?[a-z]{3}$)*",
-    "abc\ndef\nxyz",
-    (0, 11)
-);
-matiter!(
-    match_multi_rep_9,
-    r"(?m)^*",
-    "\naa\n",
-    (0, 0),
-    (1, 1),
-    (2, 2),
-    (3, 3),
-    (4, 4)
-);
-matiter!(match_multi_rep_10, r"(?m)^+", "\naa\n", (0, 0), (1, 1), (4, 4));
-matiter!(
-    match_multi_rep_11,
-    r"(?m)$*",
-    "\naa\n",
-    (0, 0),
-    (1, 1),
-    (2, 2),
-    (3, 3),
-    (4, 4)
-);
-matiter!(match_multi_rep_12, r"(?m)$+", "\naa\n", (0, 0), (3, 3), (4, 4));
-matiter!(match_multi_rep_13, r"(?m)(?:$\n)+", "\n\naaa\n\n", (0, 2), (5, 7));
-matiter!(
-    match_multi_rep_14,
-    r"(?m)(?:$\n)*",
-    "\n\naaa\n\n",
-    (0, 2),
-    (3, 3),
-    (4, 4),
-    (5, 7)
-);
-matiter!(match_multi_rep_15, r"(?m)(?:$\n^)+", "\n\naaa\n\n", (0, 2), (5, 7));
-matiter!(
-    match_multi_rep_16,
-    r"(?m)(?:^|$)+",
-    "\n\naaa\n\n",
-    (0, 0),
-    (1, 1),
-    (2, 2),
-    (5, 5),
-    (6, 6),
-    (7, 7)
-);
-matiter!(
-    match_multi_rep_17,
-    r"(?m)(?:$\n)*",
-    "\n\naaa\n\n",
-    (0, 2),
-    (3, 3),
-    (4, 4),
-    (5, 7)
-);
diff --git a/vendor/regex-1.4.3/tests/noparse.rs b/vendor/regex-1.4.3/tests/noparse.rs
deleted file mode 100644 (file)
index 8ded1dc..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-macro_rules! noparse(
-    ($name:ident, $re:expr) => (
-        #[test]
-        fn $name() {
-            let re = $re;
-            match regex_new!(re) {
-                Err(_) => {},
-                Ok(_) => panic!("Regex '{}' should cause a parse error.", re),
-            }
-        }
-    );
-);
-
-noparse!(fail_no_repeat_arg, "*");
-noparse!(fail_incomplete_escape, "\\");
-noparse!(fail_class_incomplete, "[A-");
-noparse!(fail_class_not_closed, "[A");
-noparse!(fail_class_no_begin, r"[\A]");
-noparse!(fail_class_no_end, r"[\z]");
-noparse!(fail_class_no_boundary, r"[\b]");
-noparse!(fail_open_paren, "(");
-noparse!(fail_close_paren, ")");
-noparse!(fail_invalid_range, "[a-Z]");
-noparse!(fail_empty_capture_name, "(?P<>a)");
-noparse!(fail_bad_capture_name, "(?P<na-me>)");
-noparse!(fail_bad_flag, "(?a)a");
-noparse!(fail_too_big, "a{10000000}");
-noparse!(fail_counted_no_close, "a{1001");
-noparse!(fail_counted_decreasing, "a{2,1}");
-noparse!(fail_counted_nonnegative, "a{-1,1}");
-noparse!(fail_unfinished_cap, "(?");
-noparse!(fail_unfinished_escape, "\\");
-noparse!(fail_octal_digit, r"\8");
-noparse!(fail_hex_digit, r"\xG0");
-noparse!(fail_hex_short, r"\xF");
-noparse!(fail_hex_long_digits, r"\x{fffg}");
-noparse!(fail_flag_bad, "(?a)");
-noparse!(fail_flag_empty, "(?)");
-noparse!(fail_double_neg, "(?-i-i)");
-noparse!(fail_neg_empty, "(?i-)");
-noparse!(fail_dupe_named, "(?P<a>.)(?P<a>.)");
-noparse!(fail_range_end_no_class, "[a-[:lower:]]");
-noparse!(fail_range_end_no_begin, r"[a-\A]");
-noparse!(fail_range_end_no_end, r"[a-\z]");
-noparse!(fail_range_end_no_boundary, r"[a-\b]");
diff --git a/vendor/regex-1.4.3/tests/regression.rs b/vendor/regex-1.4.3/tests/regression.rs
deleted file mode 100644 (file)
index 44b9083..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-// See: https://github.com/rust-lang/regex/issues/48
-#[test]
-fn invalid_regexes_no_crash() {
-    assert!(regex_new!("(*)").is_err());
-    assert!(regex_new!("(?:?)").is_err());
-    assert!(regex_new!("(?)").is_err());
-    assert!(regex_new!("*").is_err());
-}
-
-// See: https://github.com/rust-lang/regex/issues/98
-#[test]
-fn regression_many_repeat_stack_overflow() {
-    let re = regex!("^.{1,2500}");
-    assert_eq!(vec![(0, 1)], findall!(re, "a"));
-}
-
-// See: https://github.com/rust-lang/regex/issues/555
-#[test]
-fn regression_invalid_repetition_expr() {
-    assert!(regex_new!("(?m){1,1}").is_err());
-}
-
-// See: https://github.com/rust-lang/regex/issues/527
-#[test]
-fn regression_invalid_flags_expression() {
-    assert!(regex_new!("(((?x)))").is_ok());
-}
-
-// See: https://github.com/rust-lang/regex/issues/75
-mat!(regression_unsorted_binary_search_1, r"(?i-u)[a_]+", "A_", Some((0, 2)));
-mat!(regression_unsorted_binary_search_2, r"(?i-u)[A_]+", "a_", Some((0, 2)));
-
-// See: https://github.com/rust-lang/regex/issues/99
-#[cfg(feature = "unicode-case")]
-mat!(regression_negated_char_class_1, r"(?i)[^x]", "x", None);
-#[cfg(feature = "unicode-case")]
-mat!(regression_negated_char_class_2, r"(?i)[^x]", "X", None);
-
-// See: https://github.com/rust-lang/regex/issues/101
-mat!(regression_ascii_word_underscore, r"[[:word:]]", "_", Some((0, 1)));
-
-// See: https://github.com/rust-lang/regex/issues/129
-#[test]
-fn regression_captures_rep() {
-    let re = regex!(r"([a-f]){2}(?P<foo>[x-z])");
-    let caps = re.captures(text!("abx")).unwrap();
-    assert_eq!(match_text!(caps.name("foo").unwrap()), text!("x"));
-}
-
-// See: https://github.com/rust-lang/regex/issues/153
-mat!(regression_alt_in_alt1, r"ab?|$", "az", Some((0, 1)));
-mat!(regression_alt_in_alt2, r"^(.*?)(\n|\r\n?|$)", "ab\rcd", Some((0, 3)));
-
-// See: https://github.com/rust-lang/regex/issues/169
-mat!(regression_leftmost_first_prefix, r"z*azb", "azb", Some((0, 3)));
-
-// See: https://github.com/rust-lang/regex/issues/76
-#[cfg(all(feature = "unicode-case", feature = "unicode-gencat"))]
-mat!(uni_case_lower_nocase_flag, r"(?i)\p{Ll}+", "ΛΘΓΔα", Some((0, 10)));
-
-// See: https://github.com/rust-lang/regex/issues/191
-mat!(many_alternates, r"1|2|3|4|5|6|7|8|9|10|int", "int", Some((0, 3)));
-
-// burntsushi was bad and didn't create an issue for this bug.
-mat!(anchored_prefix1, r"^a[[:^space:]]", "a ", None);
-mat!(anchored_prefix2, r"^a[[:^space:]]", "foo boo a ", None);
-mat!(anchored_prefix3, r"^-[a-z]", "r-f", None);
-
-// See: https://github.com/rust-lang/regex/issues/204
-#[cfg(feature = "unicode-perl")]
-split!(
-    split_on_word_boundary,
-    r"\b",
-    r"Should this (work?)",
-    &[
-        t!(""),
-        t!("Should"),
-        t!(" "),
-        t!("this"),
-        t!(" ("),
-        t!("work"),
-        t!("?)")
-    ]
-);
-#[cfg(feature = "unicode-perl")]
-matiter!(
-    word_boundary_dfa,
-    r"\b",
-    "a b c",
-    (0, 0),
-    (1, 1),
-    (2, 2),
-    (3, 3),
-    (4, 4),
-    (5, 5)
-);
-
-// See: https://github.com/rust-lang/regex/issues/268
-matiter!(partial_anchor, r"^a|b", "ba", (0, 1));
-
-// See: https://github.com/rust-lang/regex/issues/280
-ismatch!(partial_anchor_alternate_begin, r"^a|z", "yyyyya", false);
-ismatch!(partial_anchor_alternate_end, r"a$|z", "ayyyyy", false);
-
-// See: https://github.com/rust-lang/regex/issues/289
-mat!(lits_unambiguous1, r"(ABC|CDA|BC)X", "CDAX", Some((0, 4)));
-
-// See: https://github.com/rust-lang/regex/issues/291
-mat!(
-    lits_unambiguous2,
-    r"((IMG|CAM|MG|MB2)_|(DSCN|CIMG))(?P<n>[0-9]+)$",
-    "CIMG2341",
-    Some((0, 8)),
-    Some((0, 4)),
-    None,
-    Some((0, 4)),
-    Some((4, 8))
-);
-
-// See: https://github.com/rust-lang/regex/issues/271
-mat!(endl_or_wb, r"(?m:$)|(?-u:\b)", "\u{6084e}", Some((4, 4)));
-mat!(zero_or_end, r"(?i-u:\x00)|$", "\u{e682f}", Some((4, 4)));
-mat!(y_or_endl, r"(?i-u:y)|(?m:$)", "\u{b4331}", Some((4, 4)));
-#[cfg(feature = "unicode-perl")]
-mat!(wb_start_x, r"(?u:\b)^(?-u:X)", "X", Some((0, 1)));
-
-// See: https://github.com/rust-lang/regex/issues/321
-ismatch!(strange_anchor_non_complete_prefix, r"a^{2}", "", false);
-ismatch!(strange_anchor_non_complete_suffix, r"${2}a", "", false);
-
-// See: https://github.com/BurntSushi/ripgrep/issues/1203
-ismatch!(reverse_suffix1, r"[0-4][0-4][0-4]000", "153.230000", true);
-ismatch!(reverse_suffix2, r"[0-9][0-9][0-9]000", "153.230000\n", true);
-matiter!(reverse_suffix3, r"[0-9][0-9][0-9]000", "153.230000\n", (4, 10));
-
-// See: https://github.com/rust-lang/regex/issues/334
-// See: https://github.com/rust-lang/regex/issues/557
-mat!(
-    captures_after_dfa_premature_end1,
-    r"a(b*(X|$))?",
-    "abcbX",
-    Some((0, 1)),
-    None,
-    None
-);
-mat!(
-    captures_after_dfa_premature_end2,
-    r"a(bc*(X|$))?",
-    "abcbX",
-    Some((0, 1)),
-    None,
-    None
-);
-mat!(captures_after_dfa_premature_end3, r"(aa$)?", "aaz", Some((0, 0)));
-
-// See: https://github.com/rust-lang/regex/issues/437
-ismatch!(
-    literal_panic,
-    r"typename type\-parameter\-[0-9]+\-[0-9]+::.+",
-    "test",
-    false
-);
-
-// See: https://github.com/rust-lang/regex/issues/533
-ismatch!(
-    blank_matches_nothing_between_space_and_tab,
-    r"[[:blank:]]",
-    "\u{a}\u{b}\u{c}\u{d}\u{e}\u{f}\
-     \u{10}\u{11}\u{12}\u{13}\u{14}\u{15}\u{16}\u{17}\
-     \u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f}",
-    false
-);
-
-ismatch!(
-    inverted_blank_matches_everything_between_space_and_tab,
-    r"^[[:^blank:]]+$",
-    "\u{a}\u{b}\u{c}\u{d}\u{e}\u{f}\
-     \u{10}\u{11}\u{12}\u{13}\u{14}\u{15}\u{16}\u{17}\
-     \u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f}",
-    true
-);
-
-// Tests that our Aho-Corasick optimization works correctly. It only
-// kicks in when we have >32 literals. By "works correctly," we mean that
-// leftmost-first match semantics are properly respected. That is, samwise
-// should match, not sam.
-mat!(
-    ahocorasick1,
-    "samwise|sam|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|\
-     A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z",
-    "samwise",
-    Some((0, 7))
-);
-
-// See: https://github.com/BurntSushi/ripgrep/issues/1247
-#[test]
-#[cfg(feature = "unicode-perl")]
-fn regression_nfa_stops1() {
-    let re = ::regex::bytes::Regex::new(r"\bs(?:[ab])").unwrap();
-    assert_eq!(0, re.find_iter(b"s\xE4").count());
-}
-
-// See: https://github.com/rust-lang/regex/issues/640
-#[cfg(feature = "unicode-case")]
-matiter!(
-    flags_are_unset,
-    r"((?i)foo)|Bar",
-    "foo Foo bar Bar",
-    (0, 3),
-    (4, 7),
-    (12, 15)
-);
-
-// See: https://github.com/rust-lang/regex/issues/659
-//
-// Note that 'Ј' is not 'j', but cyrillic Je
-// https://en.wikipedia.org/wiki/Je_(Cyrillic)
-ismatch!(empty_group_match, r"()Ј01", "zЈ01", true);
-matiter!(empty_group_find, r"()Ј01", "zЈ01", (1, 5));
diff --git a/vendor/regex-1.4.3/tests/regression_fuzz.rs b/vendor/regex-1.4.3/tests/regression_fuzz.rs
deleted file mode 100644 (file)
index 5f92ed0..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// These tests are only run for the "default" test target because some of them
-// can take quite a long time. Some of them take long enough that it's not
-// practical to run them in debug mode. :-/
-
-// See: https://oss-fuzz.com/testcase-detail/5673225499181056
-//
-// Ignored by default since it takes too long in debug mode (almost a minute).
-#[test]
-#[ignore]
-fn fuzz1() {
-    regex!(r"1}{55}{0}*{1}{55}{55}{5}*{1}{55}+{56}|;**");
-}
-
-// See: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=26505
-// See: https://github.com/rust-lang/regex/issues/722
-#[test]
-fn empty_any_errors_no_panic() {
-    assert!(regex_new!(r"\P{any}").is_err());
-}
diff --git a/vendor/regex-1.4.3/tests/replace.rs b/vendor/regex-1.4.3/tests/replace.rs
deleted file mode 100644 (file)
index c156a39..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-macro_rules! replace(
-    ($name:ident, $which:ident, $re:expr,
-     $search:expr, $replace:expr, $result:expr) => (
-        #[test]
-        fn $name() {
-            let re = regex!($re);
-            assert_eq!(re.$which(text!($search), $replace), text!($result));
-        }
-    );
-);
-
-replace!(first, replace, r"[0-9]", "age: 26", t!("Z"), "age: Z6");
-replace!(plus, replace, r"[0-9]+", "age: 26", t!("Z"), "age: Z");
-replace!(all, replace_all, r"[0-9]", "age: 26", t!("Z"), "age: ZZ");
-replace!(
-    groups,
-    replace,
-    r"(?-u)(\S+)\s+(\S+)",
-    "w1 w2",
-    t!("$2 $1"),
-    "w2 w1"
-);
-replace!(
-    double_dollar,
-    replace,
-    r"(?-u)(\S+)\s+(\S+)",
-    "w1 w2",
-    t!("$2 $$1"),
-    "w2 $1"
-);
-// replace!(adjacent_index, replace,
-// r"([^aeiouy])ies$", "skies", t!("$1y"), "sky");
-replace!(
-    named,
-    replace_all,
-    r"(?-u)(?P<first>\S+)\s+(?P<last>\S+)(?P<space>\s*)",
-    "w1 w2 w3 w4",
-    t!("$last $first$space"),
-    "w2 w1 w4 w3"
-);
-replace!(
-    trim,
-    replace_all,
-    "^[ \t]+|[ \t]+$",
-    " \t  trim me\t   \t",
-    t!(""),
-    "trim me"
-);
-replace!(number_hypen, replace, r"(.)(.)", "ab", t!("$1-$2"), "a-b");
-// replace!(number_underscore, replace, r"(.)(.)", "ab", t!("$1_$2"), "a_b");
-replace!(
-    simple_expand,
-    replace_all,
-    r"(?-u)(\w) (\w)",
-    "a b",
-    t!("$2 $1"),
-    "b a"
-);
-replace!(
-    literal_dollar1,
-    replace_all,
-    r"(?-u)(\w+) (\w+)",
-    "a b",
-    t!("$$1"),
-    "$1"
-);
-replace!(
-    literal_dollar2,
-    replace_all,
-    r"(?-u)(\w+) (\w+)",
-    "a b",
-    t!("$2 $$c $1"),
-    "b $c a"
-);
-replace!(
-    no_expand1,
-    replace,
-    r"(?-u)(\S+)\s+(\S+)",
-    "w1 w2",
-    no_expand!("$2 $1"),
-    "$2 $1"
-);
-replace!(
-    no_expand2,
-    replace,
-    r"(?-u)(\S+)\s+(\S+)",
-    "w1 w2",
-    no_expand!("$$1"),
-    "$$1"
-);
-use_!(Captures);
-replace!(
-    closure_returning_reference,
-    replace,
-    r"([0-9]+)",
-    "age: 26",
-    |captures: &Captures| {
-        match_text!(captures.get(1).unwrap())[0..1].to_owned()
-    },
-    "age: 2"
-);
-replace!(
-    closure_returning_value,
-    replace,
-    r"[0-9]+",
-    "age: 26",
-    |_captures: &Captures| t!("Z").to_owned(),
-    "age: Z"
-);
-
-// See https://github.com/rust-lang/regex/issues/314
-replace!(
-    match_at_start_replace_with_empty,
-    replace_all,
-    r"foo",
-    "foobar",
-    t!(""),
-    "bar"
-);
-
-// See https://github.com/rust-lang/regex/issues/393
-replace!(single_empty_match, replace, r"^", "bar", t!("foo"), "foobar");
-
-// See https://github.com/rust-lang/regex/issues/399
-replace!(
-    capture_longest_possible_name,
-    replace_all,
-    r"(.)",
-    "b",
-    t!("${1}a $1a"),
-    "ba "
-);
diff --git a/vendor/regex-1.4.3/tests/searcher.rs b/vendor/regex-1.4.3/tests/searcher.rs
deleted file mode 100644 (file)
index 3779f54..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-macro_rules! searcher {
-    ($name:ident, $re:expr, $haystack:expr) => (
-        searcher!($name, $re, $haystack, vec vec![]);
-    );
-    ($name:ident, $re:expr, $haystack:expr, $($steps:expr,)*) => (
-        searcher!($name, $re, $haystack, vec vec![$($steps),*]);
-    );
-    ($name:ident, $re:expr, $haystack:expr, $($steps:expr),*) => (
-        searcher!($name, $re, $haystack, vec vec![$($steps),*]);
-    );
-    ($name:ident, $re:expr, $haystack:expr, vec $expect_steps:expr) => (
-        #[test]
-        #[allow(unused_imports)]
-        fn $name() {
-            searcher_expr! {{
-                use std::str::pattern::{Pattern, Searcher};
-                use std::str::pattern::SearchStep::{Match, Reject, Done};
-                let re = regex!($re);
-                let mut se = re.into_searcher($haystack);
-                let mut got_steps = vec![];
-                loop {
-                    match se.next() {
-                        Done => break,
-                        step => { got_steps.push(step); }
-                    }
-                }
-                assert_eq!(got_steps, $expect_steps);
-            }}
-        }
-    );
-}
-
-searcher!(searcher_empty_regex_empty_haystack, r"", "", Match(0, 0));
-searcher!(
-    searcher_empty_regex,
-    r"",
-    "ab",
-    Match(0, 0),
-    Reject(0, 1),
-    Match(1, 1),
-    Reject(1, 2),
-    Match(2, 2)
-);
-searcher!(searcher_empty_haystack, r"\d", "");
-searcher!(searcher_one_match, r"\d", "5", Match(0, 1));
-searcher!(searcher_no_match, r"\d", "a", Reject(0, 1));
-searcher!(
-    searcher_two_adjacent_matches,
-    r"\d",
-    "56",
-    Match(0, 1),
-    Match(1, 2)
-);
-searcher!(
-    searcher_two_non_adjacent_matches,
-    r"\d",
-    "5a6",
-    Match(0, 1),
-    Reject(1, 2),
-    Match(2, 3)
-);
-searcher!(searcher_reject_first, r"\d", "a6", Reject(0, 1), Match(1, 2));
-searcher!(
-    searcher_one_zero_length_matches,
-    r"\d*",
-    "a1b2",
-    Match(0, 0),  // ^
-    Reject(0, 1), // a
-    Match(1, 2),  // a1
-    Reject(2, 3), // a1b
-    Match(3, 4),  // a1b2
-);
-searcher!(
-    searcher_many_zero_length_matches,
-    r"\d*",
-    "a1bbb2",
-    Match(0, 0),  // ^
-    Reject(0, 1), // a
-    Match(1, 2),  // a1
-    Reject(2, 3), // a1b
-    Match(3, 3),  // a1bb
-    Reject(3, 4), // a1bb
-    Match(4, 4),  // a1bbb
-    Reject(4, 5), // a1bbb
-    Match(5, 6),  // a1bbba
-);
-searcher!(
-    searcher_unicode,
-    r".+?",
-    "Ⅰ1Ⅱ2",
-    Match(0, 3),
-    Match(3, 4),
-    Match(4, 7),
-    Match(7, 8)
-);
diff --git a/vendor/regex-1.4.3/tests/set.rs b/vendor/regex-1.4.3/tests/set.rs
deleted file mode 100644 (file)
index 37fcf87..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-matset!(set1, &["a", "a"], "a", 0, 1);
-matset!(set2, &["a", "a"], "ba", 0, 1);
-matset!(set3, &["a", "b"], "a", 0);
-matset!(set4, &["a", "b"], "b", 1);
-matset!(set5, &["a|b", "b|a"], "b", 0, 1);
-matset!(set6, &["foo", "oo"], "foo", 0, 1);
-matset!(set7, &["^foo", "bar$"], "foo", 0);
-matset!(set8, &["^foo", "bar$"], "foo bar", 0, 1);
-matset!(set9, &["^foo", "bar$"], "bar", 1);
-matset!(set10, &[r"[a-z]+$", "foo"], "01234 foo", 0, 1);
-matset!(set11, &[r"[a-z]+$", "foo"], "foo 01234", 1);
-matset!(set12, &[r".*?", "a"], "zzzzzza", 0, 1);
-matset!(set13, &[r".*", "a"], "zzzzzza", 0, 1);
-matset!(set14, &[r".*", "a"], "zzzzzz", 0);
-matset!(set15, &[r"(?-u)\ba\b"], "hello a bye", 0);
-matset!(set16, &["a"], "a", 0);
-matset!(set17, &[".*a"], "a", 0);
-matset!(set18, &["a", "β"], "β", 1);
-
-// regexes that match the empty string
-matset!(setempty1, &["", "a"], "abc", 0, 1);
-matset!(setempty2, &["", "b"], "abc", 0, 1);
-matset!(setempty3, &["", "z"], "abc", 0);
-matset!(setempty4, &["a", ""], "abc", 0, 1);
-matset!(setempty5, &["b", ""], "abc", 0, 1);
-matset!(setempty6, &["z", ""], "abc", 1);
-matset!(setempty7, &["b", "(?:)"], "abc", 0, 1);
-matset!(setempty8, &["(?:)", "b"], "abc", 0, 1);
-matset!(setempty9, &["c(?:)", "b"], "abc", 0, 1);
-
-nomatset!(nset1, &["a", "a"], "b");
-nomatset!(nset2, &["^foo", "bar$"], "bar foo");
-nomatset!(
-    nset3,
-    {
-        let xs: &[&str] = &[];
-        xs
-    },
-    "a"
-);
-nomatset!(nset4, &[r"^rooted$", r"\.log$"], "notrooted");
-
-// See: https://github.com/rust-lang/regex/issues/187
-#[test]
-fn regression_subsequent_matches() {
-    let set = regex_set!(&["ab", "b"]);
-    let text = text!("ba");
-    assert!(set.matches(text).matched(1));
-    assert!(set.matches(text).matched(1));
-}
-
-#[test]
-fn get_set_patterns() {
-    let set = regex_set!(&["a", "b"]);
-    assert_eq!(vec!["a", "b"], set.patterns());
-}
-
-#[test]
-fn len_and_empty() {
-    let empty = regex_set!(&[""; 0]);
-    assert_eq!(empty.len(), 0);
-    assert!(empty.is_empty());
-
-    let not_empty = regex_set!(&["ab", "b"]);
-    assert_eq!(not_empty.len(), 2);
-    assert!(!not_empty.is_empty());
-}
diff --git a/vendor/regex-1.4.3/tests/shortest_match.rs b/vendor/regex-1.4.3/tests/shortest_match.rs
deleted file mode 100644 (file)
index f8b4fed..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-macro_rules! shortmat {
-    ($name:ident, $re:expr, $text:expr, $shortest_match:expr) => {
-        #[test]
-        fn $name() {
-            let text = text!($text);
-            let re = regex!($re);
-            assert_eq!($shortest_match, re.shortest_match(text));
-        }
-    };
-}
-
-shortmat!(t01, r"a+", r"aa", Some(1));
-// Test that the reverse suffix optimization gets it right.
-shortmat!(t02, r".*(?:abcd)+", r"abcdabcd", Some(4));
diff --git a/vendor/regex-1.4.3/tests/suffix_reverse.rs b/vendor/regex-1.4.3/tests/suffix_reverse.rs
deleted file mode 100644 (file)
index 774c9e8..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-mat!(t01, r".*abcd", r"abcd", Some((0, 4)));
-mat!(t02, r".*(?:abcd)+", r"abcd", Some((0, 4)));
-mat!(t03, r".*(?:abcd)+", r"abcdabcd", Some((0, 8)));
-mat!(t04, r".*(?:abcd)+", r"abcdxabcd", Some((0, 9)));
-mat!(t05, r".*x(?:abcd)+", r"abcdxabcd", Some((0, 9)));
-mat!(t06, r"[^abcd]*x(?:abcd)+", r"abcdxabcd", Some((4, 9)));
diff --git a/vendor/regex-1.4.3/tests/test_backtrack.rs b/vendor/regex-1.4.3/tests/test_backtrack.rs
deleted file mode 100644 (file)
index 617185f..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#![cfg_attr(feature = "pattern", feature(pattern))]
-
-extern crate rand;
-extern crate regex;
-
-macro_rules! regex_new {
-    ($re:expr) => {{
-        use regex::internal::ExecBuilder;
-        ExecBuilder::new($re)
-            .bounded_backtracking()
-            .build()
-            .map(|e| e.into_regex())
-    }};
-}
-
-macro_rules! regex {
-    ($re:expr) => {
-        regex_new!($re).unwrap()
-    };
-}
-
-macro_rules! regex_set_new {
-    ($re:expr) => {{
-        use regex::internal::ExecBuilder;
-        ExecBuilder::new_many($re)
-            .bounded_backtracking()
-            .build()
-            .map(|e| e.into_regex_set())
-    }};
-}
-
-macro_rules! regex_set {
-    ($res:expr) => {
-        regex_set_new!($res).unwrap()
-    };
-}
-
-// Must come before other module definitions.
-include!("macros_str.rs");
-include!("macros.rs");
-
-mod api;
-mod api_str;
-mod crazy;
-mod flags;
-mod fowler;
-mod multiline;
-mod noparse;
-mod regression;
-mod replace;
-mod searcher;
-mod set;
-mod suffix_reverse;
-#[cfg(feature = "unicode")]
-mod unicode;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary_unicode;
diff --git a/vendor/regex-1.4.3/tests/test_backtrack_bytes.rs b/vendor/regex-1.4.3/tests/test_backtrack_bytes.rs
deleted file mode 100644 (file)
index 17df4d8..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-extern crate rand;
-extern crate regex;
-
-macro_rules! regex_new {
-    ($re:expr) => {{
-        use regex::internal::ExecBuilder;
-        ExecBuilder::new($re)
-            .bounded_backtracking()
-            .only_utf8(false)
-            .build()
-            .map(|e| e.into_byte_regex())
-    }};
-}
-
-macro_rules! regex {
-    ($re:expr) => {
-        regex_new!($re).unwrap()
-    };
-}
-
-macro_rules! regex_set_new {
-    ($re:expr) => {{
-        use regex::internal::ExecBuilder;
-        ExecBuilder::new_many($re)
-            .bounded_backtracking()
-            .only_utf8(false)
-            .build()
-            .map(|e| e.into_byte_regex_set())
-    }};
-}
-
-macro_rules! regex_set {
-    ($res:expr) => {
-        regex_set_new!($res).unwrap()
-    };
-}
-
-// Must come before other module definitions.
-include!("macros_bytes.rs");
-include!("macros.rs");
-
-mod api;
-mod bytes;
-mod crazy;
-mod flags;
-mod fowler;
-mod multiline;
-mod noparse;
-mod regression;
-mod replace;
-mod set;
-mod suffix_reverse;
-#[cfg(feature = "unicode")]
-mod unicode;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary_ascii;
diff --git a/vendor/regex-1.4.3/tests/test_backtrack_utf8bytes.rs b/vendor/regex-1.4.3/tests/test_backtrack_utf8bytes.rs
deleted file mode 100644 (file)
index 78a0135..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#![cfg_attr(feature = "pattern", feature(pattern))]
-
-extern crate rand;
-extern crate regex;
-
-macro_rules! regex_new {
-    ($re:expr) => {{
-        use regex::internal::ExecBuilder;
-        ExecBuilder::new($re)
-            .bounded_backtracking()
-            .bytes(true)
-            .build()
-            .map(|e| e.into_regex())
-    }};
-}
-
-macro_rules! regex {
-    ($re:expr) => {
-        regex_new!($re).unwrap()
-    };
-}
-
-macro_rules! regex_set_new {
-    ($re:expr) => {{
-        use regex::internal::ExecBuilder;
-        ExecBuilder::new_many($re)
-            .bounded_backtracking()
-            .bytes(true)
-            .build()
-            .map(|e| e.into_regex_set())
-    }};
-}
-
-macro_rules! regex_set {
-    ($res:expr) => {
-        regex_set_new!($res).unwrap()
-    };
-}
-
-// Must come before other module definitions.
-include!("macros_str.rs");
-include!("macros.rs");
-
-mod api;
-mod api_str;
-mod crazy;
-mod flags;
-mod fowler;
-mod multiline;
-mod noparse;
-mod regression;
-mod replace;
-mod searcher;
-mod set;
-mod suffix_reverse;
-#[cfg(feature = "unicode")]
-mod unicode;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary_unicode;
diff --git a/vendor/regex-1.4.3/tests/test_crates_regex.rs b/vendor/regex-1.4.3/tests/test_crates_regex.rs
deleted file mode 100644 (file)
index d697683..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-extern crate quickcheck;
-extern crate regex;
-
-/*
- * This test is a minimal version of <rofl_0> and <subdiff_0>
- *
- * Once this bug gets fixed, uncomment rofl_0 and subdiff_0
- * (in `tests/crates_regex.rs`).
-#[test]
-fn word_boundary_backtracking_default_mismatch() {
-    use regex::internal::ExecBuilder;
-
-    let backtrack_re = ExecBuilder::new(r"\b")
-        .bounded_backtracking()
-        .build()
-        .map(|exec| exec.into_regex())
-        .map_err(|err| format!("{}", err))
-        .unwrap();
-
-    let default_re = ExecBuilder::new(r"\b")
-        .build()
-        .map(|exec| exec.into_regex())
-        .map_err(|err| format!("{}", err))
-        .unwrap();
-
-    let input = "䅅\\u{a0}";
-
-    let fi1 = backtrack_re.find_iter(input);
-    let fi2 = default_re.find_iter(input);
-    for (m1, m2) in fi1.zip(fi2) {
-        assert_eq!(m1, m2);
-    }
-}
-*/
-
-mod consistent;
-
-mod crates_regex {
-
-    macro_rules! consistent {
-        ($test_name:ident, $regex_src:expr) => {
-            #[test]
-            fn $test_name() {
-                use super::consistent::backends_are_consistent;
-
-                if option_env!("RUST_REGEX_RANDOM_TEST").is_some() {
-                    match backends_are_consistent($regex_src) {
-                        Ok(_) => {}
-                        Err(err) => panic!("{}", err),
-                    }
-                }
-            }
-        };
-    }
-
-    include!("crates_regex.rs");
-}
diff --git a/vendor/regex-1.4.3/tests/test_default.rs b/vendor/regex-1.4.3/tests/test_default.rs
deleted file mode 100644 (file)
index 241e580..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-#![cfg_attr(feature = "pattern", feature(pattern))]
-
-extern crate rand;
-extern crate regex;
-
-// Due to macro scoping rules, this definition only applies for the modules
-// defined below. Effectively, it allows us to use the same tests for both
-// native and dynamic regexes.
-//
-// This is also used to test the various matching engines. This one exercises
-// the normal code path which automatically chooses the engine based on the
-// regex and the input. Other dynamic tests explicitly set the engine to use.
-macro_rules! regex_new {
-    ($re:expr) => {{
-        use regex::Regex;
-        Regex::new($re)
-    }};
-}
-
-macro_rules! regex {
-    ($re:expr) => {
-        regex_new!($re).unwrap()
-    };
-}
-
-macro_rules! regex_set_new {
-    ($re:expr) => {{
-        use regex::RegexSet;
-        RegexSet::new($re)
-    }};
-}
-
-macro_rules! regex_set {
-    ($res:expr) => {
-        regex_set_new!($res).unwrap()
-    };
-}
-
-// Must come before other module definitions.
-include!("macros_str.rs");
-include!("macros.rs");
-
-mod api;
-mod api_str;
-mod crazy;
-mod flags;
-mod fowler;
-mod misc;
-mod multiline;
-mod noparse;
-mod regression;
-mod regression_fuzz;
-mod replace;
-mod searcher;
-mod set;
-mod shortest_match;
-mod suffix_reverse;
-#[cfg(feature = "unicode")]
-mod unicode;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary_unicode;
-
-#[test]
-fn disallow_non_utf8() {
-    assert!(regex::Regex::new(r"(?-u)\xFF").is_err());
-    assert!(regex::Regex::new(r"(?-u).").is_err());
-    assert!(regex::Regex::new(r"(?-u)[\xFF]").is_err());
-    assert!(regex::Regex::new(r"(?-u)☃").is_err());
-}
-
-#[test]
-fn disallow_octal() {
-    assert!(regex::Regex::new(r"\0").is_err());
-}
-
-#[test]
-fn allow_octal() {
-    assert!(regex::RegexBuilder::new(r"\0").octal(true).build().is_ok());
-}
-
-#[test]
-fn oibits() {
-    use regex::bytes;
-    use regex::{Regex, RegexBuilder};
-    use std::panic::UnwindSafe;
-
-    fn assert_send<T: Send>() {}
-    fn assert_sync<T: Sync>() {}
-    fn assert_unwind_safe<T: UnwindSafe>() {}
-
-    assert_send::<Regex>();
-    assert_sync::<Regex>();
-    assert_unwind_safe::<Regex>();
-    assert_send::<RegexBuilder>();
-    assert_sync::<RegexBuilder>();
-    assert_unwind_safe::<RegexBuilder>();
-
-    assert_send::<bytes::Regex>();
-    assert_sync::<bytes::Regex>();
-    assert_unwind_safe::<bytes::Regex>();
-    assert_send::<bytes::RegexBuilder>();
-    assert_sync::<bytes::RegexBuilder>();
-    assert_unwind_safe::<bytes::RegexBuilder>();
-}
-
-// See: https://github.com/rust-lang/regex/issues/568
-#[test]
-fn oibits_regression() {
-    use regex::Regex;
-    use std::panic;
-
-    let _ = panic::catch_unwind(|| Regex::new("a").unwrap());
-}
diff --git a/vendor/regex-1.4.3/tests/test_default_bytes.rs b/vendor/regex-1.4.3/tests/test_default_bytes.rs
deleted file mode 100644 (file)
index e4a25dc..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-extern crate rand;
-extern crate regex;
-
-macro_rules! regex_new {
-    ($re:expr) => {{
-        use regex::bytes::Regex;
-        Regex::new($re)
-    }};
-}
-
-macro_rules! regex_set_new {
-    ($res:expr) => {{
-        use regex::bytes::RegexSet;
-        RegexSet::new($res)
-    }};
-}
-
-macro_rules! regex {
-    ($re:expr) => {
-        regex_new!($re).unwrap()
-    };
-}
-
-macro_rules! regex_set {
-    ($res:expr) => {
-        regex_set_new!($res).unwrap()
-    };
-}
-
-// Must come before other module definitions.
-include!("macros_bytes.rs");
-include!("macros.rs");
-
-// A silly wrapper to make it possible to write and match raw bytes.
-struct R<'a>(&'a [u8]);
-impl<'a> R<'a> {
-    fn as_bytes(&self) -> &'a [u8] {
-        self.0
-    }
-}
-
-// See: https://github.com/rust-lang/regex/issues/321
-//
-// These tests are here because they do not have the same behavior in every
-// regex engine.
-mat!(invalid_utf8_nfa1, r".", R(b"\xD4\xC2\x65\x2B\x0E\xFE"), Some((2, 3)));
-mat!(invalid_utf8_nfa2, r"${2}ä", R(b"\xD4\xC2\x65\x2B\x0E\xFE"), None);
-mat!(
-    invalid_utf8_nfa3,
-    r".",
-    R(b"\x0A\xDB\x82\x6E\x33\x01\xDD\x33\xCD"),
-    Some((1, 3))
-);
-mat!(
-    invalid_utf8_nfa4,
-    r"${2}ä",
-    R(b"\x0A\xDB\x82\x6E\x33\x01\xDD\x33\xCD"),
-    None
-);
-
-mod api;
-mod bytes;
-mod crazy;
-mod flags;
-mod fowler;
-mod multiline;
-mod noparse;
-mod regression;
-mod replace;
-mod set;
-mod shortest_match;
-mod suffix_reverse;
-#[cfg(feature = "unicode")]
-mod unicode;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary_unicode;
diff --git a/vendor/regex-1.4.3/tests/test_nfa.rs b/vendor/regex-1.4.3/tests/test_nfa.rs
deleted file mode 100644 (file)
index 05dad23..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#![cfg_attr(feature = "pattern", feature(pattern))]
-
-extern crate rand;
-extern crate regex;
-
-macro_rules! regex_new {
-    ($re:expr) => {{
-        use regex::internal::ExecBuilder;
-        ExecBuilder::new($re).nfa().build().map(|e| e.into_regex())
-    }};
-}
-
-macro_rules! regex {
-    ($re:expr) => {
-        regex_new!($re).unwrap()
-    };
-}
-
-macro_rules! regex_set_new {
-    ($re:expr) => {{
-        use regex::internal::ExecBuilder;
-        ExecBuilder::new_many($re).nfa().build().map(|e| e.into_regex_set())
-    }};
-}
-
-macro_rules! regex_set {
-    ($res:expr) => {
-        regex_set_new!($res).unwrap()
-    };
-}
-
-// Must come before other module definitions.
-include!("macros_str.rs");
-include!("macros.rs");
-
-mod api;
-mod api_str;
-mod crazy;
-mod flags;
-mod fowler;
-mod multiline;
-mod noparse;
-mod regression;
-mod replace;
-mod searcher;
-mod set;
-mod suffix_reverse;
-#[cfg(feature = "unicode")]
-mod unicode;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary_unicode;
diff --git a/vendor/regex-1.4.3/tests/test_nfa_bytes.rs b/vendor/regex-1.4.3/tests/test_nfa_bytes.rs
deleted file mode 100644 (file)
index 1042318..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-extern crate rand;
-extern crate regex;
-
-macro_rules! regex_new {
-    ($re:expr) => {{
-        use regex::internal::ExecBuilder;
-        ExecBuilder::new($re)
-            .nfa()
-            .only_utf8(false)
-            .build()
-            .map(|e| e.into_byte_regex())
-    }};
-}
-
-macro_rules! regex {
-    ($re:expr) => {
-        regex_new!($re).unwrap()
-    };
-}
-
-macro_rules! regex_set_new {
-    ($re:expr) => {{
-        use regex::internal::ExecBuilder;
-        ExecBuilder::new_many($re)
-            .nfa()
-            .only_utf8(false)
-            .build()
-            .map(|e| e.into_byte_regex_set())
-    }};
-}
-
-macro_rules! regex_set {
-    ($res:expr) => {
-        regex_set_new!($res).unwrap()
-    };
-}
-
-// Must come before other module definitions.
-include!("macros_bytes.rs");
-include!("macros.rs");
-
-mod api;
-mod bytes;
-mod crazy;
-mod flags;
-mod fowler;
-mod multiline;
-mod noparse;
-mod regression;
-mod replace;
-mod set;
-mod suffix_reverse;
-#[cfg(feature = "unicode")]
-mod unicode;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary_unicode;
diff --git a/vendor/regex-1.4.3/tests/test_nfa_utf8bytes.rs b/vendor/regex-1.4.3/tests/test_nfa_utf8bytes.rs
deleted file mode 100644 (file)
index 86487a1..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#![cfg_attr(feature = "pattern", feature(pattern))]
-
-extern crate rand;
-extern crate regex;
-
-macro_rules! regex_new {
-    ($re:expr) => {{
-        use regex::internal::ExecBuilder;
-        ExecBuilder::new($re).nfa().bytes(true).build().map(|e| e.into_regex())
-    }};
-}
-
-macro_rules! regex {
-    ($re:expr) => {
-        regex_new!($re).unwrap()
-    };
-}
-
-macro_rules! regex_set_new {
-    ($re:expr) => {{
-        use regex::internal::ExecBuilder;
-        ExecBuilder::new_many($re)
-            .nfa()
-            .bytes(true)
-            .build()
-            .map(|e| e.into_regex_set())
-    }};
-}
-
-macro_rules! regex_set {
-    ($res:expr) => {
-        regex_set_new!($res).unwrap()
-    };
-}
-
-// Must come before other module definitions.
-include!("macros_str.rs");
-include!("macros.rs");
-
-mod api;
-mod api_str;
-mod crazy;
-mod flags;
-mod fowler;
-mod multiline;
-mod noparse;
-mod regression;
-mod replace;
-mod searcher;
-mod set;
-mod suffix_reverse;
-#[cfg(feature = "unicode")]
-mod unicode;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary;
-#[cfg(feature = "unicode-perl")]
-mod word_boundary_unicode;
diff --git a/vendor/regex-1.4.3/tests/unicode.rs b/vendor/regex-1.4.3/tests/unicode.rs
deleted file mode 100644 (file)
index 9f1cd0c..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-mat!(uni_literal, r"☃", "☃", Some((0, 3)));
-mat!(uni_literal_plus, r"☃+", "☃", Some((0, 3)));
-mat!(uni_literal_casei_plus, r"(?i)☃+", "☃", Some((0, 3)));
-mat!(uni_class_plus, r"[☃Ⅰ]+", "☃", Some((0, 3)));
-mat!(uni_one, r"\pN", "Ⅰ", Some((0, 3)));
-mat!(uni_mixed, r"\pN+", "Ⅰ1Ⅱ2", Some((0, 8)));
-mat!(uni_not, r"\PN+", "abⅠ", Some((0, 2)));
-mat!(uni_not_class, r"[\PN]+", "abⅠ", Some((0, 2)));
-mat!(uni_not_class_neg, r"[^\PN]+", "abⅠ", Some((2, 5)));
-mat!(uni_case, r"(?i)Δ", "δ", Some((0, 2)));
-mat!(uni_case_upper, r"\p{Lu}+", "ΛΘΓΔα", Some((0, 8)));
-mat!(uni_case_upper_nocase_flag, r"(?i)\p{Lu}+", "ΛΘΓΔα", Some((0, 10)));
-mat!(uni_case_upper_nocase, r"\p{L}+", "ΛΘΓΔα", Some((0, 10)));
-mat!(uni_case_lower, r"\p{Ll}+", "ΛΘΓΔα", Some((8, 10)));
-
-// Test the Unicode friendliness of Perl character classes.
-mat!(uni_perl_w, r"\w+", "dδd", Some((0, 4)));
-mat!(uni_perl_w_not, r"\w+", "⥡", None);
-mat!(uni_perl_w_neg, r"\W+", "⥡", Some((0, 3)));
-mat!(uni_perl_d, r"\d+", "1२३9", Some((0, 8)));
-mat!(uni_perl_d_not, r"\d+", "Ⅱ", None);
-mat!(uni_perl_d_neg, r"\D+", "Ⅱ", Some((0, 3)));
-mat!(uni_perl_s, r"\s+", " ", Some((0, 3)));
-mat!(uni_perl_s_not, r"\s+", "☃", None);
-mat!(uni_perl_s_neg, r"\S+", "☃", Some((0, 3)));
-
-// And do the same for word boundaries.
-mat!(uni_boundary_none, r"\d\b", "6δ", None);
-mat!(uni_boundary_ogham, r"\d\b", "6 ", Some((0, 1)));
-mat!(uni_not_boundary_none, r"\d\B", "6δ", Some((0, 1)));
-mat!(uni_not_boundary_ogham, r"\d\B", "6 ", None);
-
-// Test general categories.
-//
-// We should test more, but there's a lot. Write a script to generate more of
-// these tests.
-mat!(uni_class_gencat_cased_letter, r"\p{Cased_Letter}", "A", Some((0, 3)));
-mat!(
-    uni_class_gencat_close_punctuation,
-    r"\p{Close_Punctuation}",
-    "❯",
-    Some((0, 3))
-);
-mat!(
-    uni_class_gencat_connector_punctuation,
-    r"\p{Connector_Punctuation}",
-    "⁀",
-    Some((0, 3))
-);
-mat!(uni_class_gencat_control, r"\p{Control}", "\u{9f}", Some((0, 2)));
-mat!(
-    uni_class_gencat_currency_symbol,
-    r"\p{Currency_Symbol}",
-    "£",
-    Some((0, 3))
-);
-mat!(
-    uni_class_gencat_dash_punctuation,
-    r"\p{Dash_Punctuation}",
-    "〰",
-    Some((0, 3))
-);
-mat!(uni_class_gencat_decimal_numer, r"\p{Decimal_Number}", "𑓙", Some((0, 4)));
-mat!(
-    uni_class_gencat_enclosing_mark,
-    r"\p{Enclosing_Mark}",
-    "\u{A672}",
-    Some((0, 3))
-);
-mat!(
-    uni_class_gencat_final_punctuation,
-    r"\p{Final_Punctuation}",
-    "⸡",
-    Some((0, 3))
-);
-mat!(uni_class_gencat_format, r"\p{Format}", "\u{E007F}", Some((0, 4)));
-// See: https://github.com/rust-lang/regex/issues/719
-mat!(uni_class_gencat_format_abbrev1, r"\p{cf}", "\u{E007F}", Some((0, 4)));
-mat!(uni_class_gencat_format_abbrev2, r"\p{gc=cf}", "\u{E007F}", Some((0, 4)));
-mat!(
-    uni_class_gencat_initial_punctuation,
-    r"\p{Initial_Punctuation}",
-    "⸜",
-    Some((0, 3))
-);
-mat!(uni_class_gencat_letter, r"\p{Letter}", "Έ", Some((0, 2)));
-mat!(uni_class_gencat_letter_number, r"\p{Letter_Number}", "ↂ", Some((0, 3)));
-mat!(
-    uni_class_gencat_line_separator,
-    r"\p{Line_Separator}",
-    "\u{2028}",
-    Some((0, 3))
-);
-mat!(
-    uni_class_gencat_lowercase_letter,
-    r"\p{Lowercase_Letter}",
-    "ϛ",
-    Some((0, 2))
-);
-mat!(uni_class_gencat_mark, r"\p{Mark}", "\u{E01EF}", Some((0, 4)));
-mat!(uni_class_gencat_math, r"\p{Math}", "⋿", Some((0, 3)));
-mat!(
-    uni_class_gencat_modifier_letter,
-    r"\p{Modifier_Letter}",
-    "𖭃",
-    Some((0, 4))
-);
-mat!(
-    uni_class_gencat_modifier_symbol,
-    r"\p{Modifier_Symbol}",
-    "🏿",
-    Some((0, 4))
-);
-mat!(
-    uni_class_gencat_nonspacing_mark,
-    r"\p{Nonspacing_Mark}",
-    "\u{1E94A}",
-    Some((0, 4))
-);
-mat!(uni_class_gencat_number, r"\p{Number}", "⓿", Some((0, 3)));
-mat!(
-    uni_class_gencat_open_punctuation,
-    r"\p{Open_Punctuation}",
-    "⦅",
-    Some((0, 3))
-);
-mat!(uni_class_gencat_other, r"\p{Other}", "\u{bc9}", Some((0, 3)));
-mat!(uni_class_gencat_other_letter, r"\p{Other_Letter}", "ꓷ", Some((0, 3)));
-mat!(uni_class_gencat_other_number, r"\p{Other_Number}", "㉏", Some((0, 3)));
-mat!(
-    uni_class_gencat_other_punctuation,
-    r"\p{Other_Punctuation}",
-    "𞥞",
-    Some((0, 4))
-);
-mat!(uni_class_gencat_other_symbol, r"\p{Other_Symbol}", "⅌", Some((0, 3)));
-mat!(
-    uni_class_gencat_paragraph_separator,
-    r"\p{Paragraph_Separator}",
-    "\u{2029}",
-    Some((0, 3))
-);
-mat!(
-    uni_class_gencat_private_use,
-    r"\p{Private_Use}",
-    "\u{10FFFD}",
-    Some((0, 4))
-);
-mat!(uni_class_gencat_punctuation, r"\p{Punctuation}", "𑁍", Some((0, 4)));
-mat!(uni_class_gencat_separator, r"\p{Separator}", "\u{3000}", Some((0, 3)));
-mat!(
-    uni_class_gencat_space_separator,
-    r"\p{Space_Separator}",
-    "\u{205F}",
-    Some((0, 3))
-);
-mat!(
-    uni_class_gencat_spacing_mark,
-    r"\p{Spacing_Mark}",
-    "\u{16F7E}",
-    Some((0, 4))
-);
-mat!(uni_class_gencat_symbol, r"\p{Symbol}", "⯈", Some((0, 3)));
-mat!(
-    uni_class_gencat_titlecase_letter,
-    r"\p{Titlecase_Letter}",
-    "ῼ",
-    Some((0, 3))
-);
-mat!(
-    uni_class_gencat_unassigned,
-    r"\p{Unassigned}",
-    "\u{10FFFF}",
-    Some((0, 4))
-);
-mat!(
-    uni_class_gencat_uppercase_letter,
-    r"\p{Uppercase_Letter}",
-    "Ꝋ",
-    Some((0, 3))
-);
-
-// Test a smattering of properties.
-mat!(uni_class_prop_emoji1, r"\p{Emoji}", "\u{23E9}", Some((0, 3)));
-mat!(uni_class_prop_emoji2, r"\p{emoji}", "\u{1F21A}", Some((0, 4)));
-mat!(
-    uni_class_prop_picto1,
-    r"\p{extendedpictographic}",
-    "\u{1FA6E}",
-    Some((0, 4))
-);
-mat!(
-    uni_class_prop_picto2,
-    r"\p{extendedpictographic}",
-    "\u{1FFFD}",
-    Some((0, 4))
-);
-
-// grapheme_cluster_break
-mat!(
-    uni_class_gcb_prepend,
-    r"\p{grapheme_cluster_break=prepend}",
-    "\u{11D46}",
-    Some((0, 4))
-);
-mat!(
-    uni_class_gcb_ri1,
-    r"\p{gcb=regional_indicator}",
-    "\u{1F1E6}",
-    Some((0, 4))
-);
-mat!(uni_class_gcb_ri2, r"\p{gcb=ri}", "\u{1F1E7}", Some((0, 4)));
-mat!(
-    uni_class_gcb_ri3,
-    r"\p{gcb=regionalindicator}",
-    "\u{1F1FF}",
-    Some((0, 4))
-);
-mat!(uni_class_gcb_lvt, r"\p{gcb=lvt}", "\u{C989}", Some((0, 3)));
-mat!(uni_class_gcb_zwj, r"\p{gcb=zwj}", "\u{200D}", Some((0, 3)));
-
-// word_break
-mat!(uni_class_wb1, r"\p{word_break=Hebrew_Letter}", "\u{FB46}", Some((0, 3)));
-mat!(uni_class_wb2, r"\p{wb=hebrewletter}", "\u{FB46}", Some((0, 3)));
-mat!(uni_class_wb3, r"\p{wb=ExtendNumLet}", "\u{FF3F}", Some((0, 3)));
-mat!(uni_class_wb4, r"\p{wb=WSegSpace}", "\u{3000}", Some((0, 3)));
-mat!(uni_class_wb5, r"\p{wb=numeric}", "\u{1E950}", Some((0, 4)));
-
-// sentence_break
-mat!(uni_class_sb1, r"\p{sentence_break=Lower}", "\u{0469}", Some((0, 2)));
-mat!(uni_class_sb2, r"\p{sb=lower}", "\u{0469}", Some((0, 2)));
-mat!(uni_class_sb3, r"\p{sb=Close}", "\u{FF60}", Some((0, 3)));
-mat!(uni_class_sb4, r"\p{sb=Close}", "\u{1F677}", Some((0, 4)));
-mat!(uni_class_sb5, r"\p{sb=SContinue}", "\u{FF64}", Some((0, 3)));
diff --git a/vendor/regex-1.4.3/tests/word_boundary.rs b/vendor/regex-1.4.3/tests/word_boundary.rs
deleted file mode 100644 (file)
index 7fe97a2..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-// Many of these are cribbed from RE2's test suite.
-
-matiter!(wb1, r"\b", "");
-matiter!(wb2, r"\b", "a", (0, 0), (1, 1));
-matiter!(wb3, r"\b", "ab", (0, 0), (2, 2));
-matiter!(wb4, r"^\b", "ab", (0, 0));
-matiter!(wb5, r"\b$", "ab", (2, 2));
-matiter!(wb6, r"^\b$", "ab");
-matiter!(wb7, r"\bbar\b", "nobar bar foo bar", (6, 9), (14, 17));
-matiter!(wb8, r"a\b", "faoa x", (3, 4));
-matiter!(wb9, r"\bbar", "bar x", (0, 3));
-matiter!(wb10, r"\bbar", "foo\nbar x", (4, 7));
-matiter!(wb11, r"bar\b", "foobar", (3, 6));
-matiter!(wb12, r"bar\b", "foobar\nxxx", (3, 6));
-matiter!(wb13, r"(foo|bar|[A-Z])\b", "foo", (0, 3));
-matiter!(wb14, r"(foo|bar|[A-Z])\b", "foo\n", (0, 3));
-matiter!(wb15, r"\b(foo|bar|[A-Z])", "foo", (0, 3));
-matiter!(wb16, r"\b(foo|bar|[A-Z])\b", "X", (0, 1));
-matiter!(wb17, r"\b(foo|bar|[A-Z])\b", "XY");
-matiter!(wb18, r"\b(foo|bar|[A-Z])\b", "bar", (0, 3));
-matiter!(wb19, r"\b(foo|bar|[A-Z])\b", "foo", (0, 3));
-matiter!(wb20, r"\b(foo|bar|[A-Z])\b", "foo\n", (0, 3));
-matiter!(wb21, r"\b(foo|bar|[A-Z])\b", "ffoo bbar N x", (10, 11));
-matiter!(wb22, r"\b(fo|foo)\b", "fo", (0, 2));
-matiter!(wb23, r"\b(fo|foo)\b", "foo", (0, 3));
-matiter!(wb24, r"\b\b", "");
-matiter!(wb25, r"\b\b", "a", (0, 0), (1, 1));
-matiter!(wb26, r"\b$", "");
-matiter!(wb27, r"\b$", "x", (1, 1));
-matiter!(wb28, r"\b$", "y x", (3, 3));
-matiter!(wb29, r"\b.$", "x", (0, 1));
-matiter!(wb30, r"^\b(fo|foo)\b", "fo", (0, 2));
-matiter!(wb31, r"^\b(fo|foo)\b", "foo", (0, 3));
-matiter!(wb32, r"^\b$", "");
-matiter!(wb33, r"^\b$", "x");
-matiter!(wb34, r"^\b.$", "x", (0, 1));
-matiter!(wb35, r"^\b.\b$", "x", (0, 1));
-matiter!(wb36, r"^^^^^\b$$$$$", "");
-matiter!(wb37, r"^^^^^\b.$$$$$", "x", (0, 1));
-matiter!(wb38, r"^^^^^\b$$$$$", "x");
-matiter!(wb39, r"^^^^^\b\b\b.\b\b\b$$$$$", "x", (0, 1));
-matiter!(wb40, r"\b.+\b", "$$abc$$", (2, 5));
-matiter!(wb41, r"\b", "a b c", (0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5));
-
-matiter!(nb1, r"\Bfoo\B", "n foo xfoox that", (7, 10));
-matiter!(nb2, r"a\B", "faoa x", (1, 2));
-matiter!(nb3, r"\Bbar", "bar x");
-matiter!(nb4, r"\Bbar", "foo\nbar x");
-matiter!(nb5, r"bar\B", "foobar");
-matiter!(nb6, r"bar\B", "foobar\nxxx");
-matiter!(nb7, r"(foo|bar|[A-Z])\B", "foox", (0, 3));
-matiter!(nb8, r"(foo|bar|[A-Z])\B", "foo\n");
-matiter!(nb9, r"\B", "", (0, 0));
-matiter!(nb10, r"\B", "x");
-matiter!(nb11, r"\B(foo|bar|[A-Z])", "foo");
-matiter!(nb12, r"\B(foo|bar|[A-Z])\B", "xXy", (1, 2));
-matiter!(nb13, r"\B(foo|bar|[A-Z])\B", "XY");
-matiter!(nb14, r"\B(foo|bar|[A-Z])\B", "XYZ", (1, 2));
-matiter!(nb15, r"\B(foo|bar|[A-Z])\B", "abara", (1, 4));
-matiter!(nb16, r"\B(foo|bar|[A-Z])\B", "xfoo_", (1, 4));
-matiter!(nb17, r"\B(foo|bar|[A-Z])\B", "xfoo\n");
-matiter!(nb18, r"\B(foo|bar|[A-Z])\B", "foo bar vNX", (9, 10));
-matiter!(nb19, r"\B(fo|foo)\B", "xfoo", (1, 3));
-matiter!(nb20, r"\B(foo|fo)\B", "xfooo", (1, 4));
-matiter!(nb21, r"\B\B", "", (0, 0));
-matiter!(nb22, r"\B\B", "x");
-matiter!(nb23, r"\B$", "", (0, 0));
-matiter!(nb24, r"\B$", "x");
-matiter!(nb25, r"\B$", "y x");
-matiter!(nb26, r"\B.$", "x");
-matiter!(nb27, r"^\B(fo|foo)\B", "fo");
-matiter!(nb28, r"^\B(fo|foo)\B", "foo");
-matiter!(nb29, r"^\B", "", (0, 0));
-matiter!(nb30, r"^\B", "x");
-matiter!(nb31, r"^\B\B", "", (0, 0));
-matiter!(nb32, r"^\B\B", "x");
-matiter!(nb33, r"^\B$", "", (0, 0));
-matiter!(nb34, r"^\B$", "x");
-matiter!(nb35, r"^\B.$", "x");
-matiter!(nb36, r"^\B.\B$", "x");
-matiter!(nb37, r"^^^^^\B$$$$$", "", (0, 0));
-matiter!(nb38, r"^^^^^\B.$$$$$", "x");
-matiter!(nb39, r"^^^^^\B$$$$$", "x");
-
-// These work for both Unicode and ASCII because all matches are reported as
-// byte offsets, and « and » do not correspond to word boundaries at either
-// the character or byte level.
-matiter!(unicode1, r"\bx\b", "«x", (2, 3));
-matiter!(unicode2, r"\bx\b", "x»", (0, 1));
diff --git a/vendor/regex-1.4.3/tests/word_boundary_ascii.rs b/vendor/regex-1.4.3/tests/word_boundary_ascii.rs
deleted file mode 100644 (file)
index 5a3cf11..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// ASCII word boundaries are completely oblivious to Unicode characters.
-// For Unicode word boundaries, the tests are precisely inverted.
-matiter!(ascii1, r"(?-u:\b)x(?-u:\b)", "áxβ", (2, 3));
-matiter!(ascii2, r"(?-u:\B)x(?-u:\B)", "áxβ");
-matiter!(ascii3, r"(?-u:\B)", "0\u{7EF5E}", (2, 2), (3, 3), (4, 4), (5, 5));
-
-// We still get Unicode word boundaries by default in byte regexes.
-matiter!(unicode1, r"\bx\b", "áxβ");
-matiter!(unicode2, r"\Bx\B", "áxβ", (2, 3));
diff --git a/vendor/regex-1.4.3/tests/word_boundary_unicode.rs b/vendor/regex-1.4.3/tests/word_boundary_unicode.rs
deleted file mode 100644 (file)
index c41355f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// Unicode word boundaries know about Unicode characters.
-// For ASCII word boundaries, the tests are precisely inverted.
-matiter!(unicode1, r"\bx\b", "áxβ");
-matiter!(unicode2, r"\Bx\B", "áxβ", (2, 3));
-
-matiter!(ascii1, r"(?-u:\b)x(?-u:\b)", "áxβ", (2, 3));
diff --git a/vendor/regex-1.4.6/.cargo-checksum.json b/vendor/regex-1.4.6/.cargo-checksum.json
new file mode 100644 (file)
index 0000000..37c81b5
--- /dev/null
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"5cda18bc4ea225d87f1427d82f2bd26eaecae5f3550ae4fe44ceea85697a89c1","Cargo.lock":"168062ef9ea00b70504bbaac06d5177d1e03783cf6326755a89942c48b347271","Cargo.toml":"85e0428042c25c7c60a4f0b5751a4551a567267196985603d6dfb6b806c5f0ea","HACKING.md":"17818f7a17723608f6bdbe6388ad0a913d4f96f76a16649aaf4e274b1fa0ea97","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","PERFORMANCE.md":"c776b18758b6dc8f2f9d37e9a95261f75c5f744925e8ddf216b83953bf7467b7","README.md":"05b8c25fbad8075308fbf1a20d4b0d2eb5825b7847a297b77e5453247885bd0f","UNICODE.md":"a8a8399540eed000d19420135a527f400247a04572e44d124c786b870f518776","examples/regexdna-input.txt":"156a49710bb3e1ed4bc2bbb0af0f383b747b3d0281453cfff39c296124c598f8","examples/regexdna-output.txt":"35e85b19b70a893d752fd43e54e1e9da08bac43559191cea85b33387c24c4cc1","examples/shootout-regex-dna-bytes.rs":"bfbb5b0751768d2914f3839b2f434e18c3df5a1db333b6c09c15d4c9f36e2362","examples/shootout-regex-dna-cheat.rs":"31153b19d6153e10a505bcefeaffc6ae5ec15c5b9e602ec1bdf1c008c71ac0fb","examples/shootout-regex-dna-replace.rs":"056e9ee51327a1cf9bd1da007e8c0af9c80a3e7fc2b3a3f63d0cf1b6b244ac74","examples/shootout-regex-dna-single-cheat.rs":"00d97b70df23236692d30d207d956e61896f6dba18fea0f6344bec6902a3490a","examples/shootout-regex-dna-single.rs":"81690e774c42899e6ab160580b30053531ec49678f088e1bc54cedf64e437b6c","examples/shootout-regex-dna.rs":"25c1c468238f0d45df1ff64748b1305ba2408b4102b8215a4e1a983e90221aef","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/backtrack.rs":"581820b2c08839832489d1ebb5beda637ca21c50bc0eabe6658a0aebbd73eebc","src/compile.rs":"4595fff25f5bf7853f320164ae194056f68f99238008dbf5aa8a53b2891fda17","src/dfa.rs":"c53c6d4f67f4dbe0577a310f155c12cf144a01b3a9e773158217892e8a9dc6b6","src/error.rs":"4d03ca3205e373125a0c9a4270fc1c5aa7b5a661b11db3508b563945a0827301","src/exec.rs":"ae8b553b0b5fabcafcbedabd610f81baa7b7451839eab18085cb580efaeddc4b","src/expand.rs":"07480cf505c2ac948a0520eaac11537f18d8afa9d3565e1e63f3dd9bbcfcde6e","src/find_byte.rs":"b387247b77e3269f057c3399aefe5a815032c3af918c876f80eb4b282e4eb95e","src/freqs.rs":"255555f3d95b08a5bb3bc2f38d5a06cc100a39c0f0127fe4f50c33afa1cadc65","src/input.rs":"0bb20717cb630803f78b921260c96984a38a57685f07d9aee16b12deaa1d233b","src/lib.rs":"06569d8daee7dc736e80fa8c5dfeb5ee39f47ec59c38157f8b86d609e8f19d66","src/literal/imp.rs":"db492e69b088cab9d25b65163f38a61684c5c86546266a81f556aea646a08342","src/literal/mod.rs":"46739643baa0cd5d1b8fc4521df3d727815c61e583af2ffca8b7b63bad3fa50e","src/pattern.rs":"e6124b403c18344675aa341faf9ae2f592193ef89f1c4a5e1cee135b8b34dd21","src/pikevm.rs":"3dd5794eecfe4ec80bee96d163025a417432c489732e84e125e51a4bc75d0235","src/pool.rs":"7d3408351f9c4cce491511c9636906f2827642a6483afc0dda32ca6287c2f69e","src/prog.rs":"74c87e774410c8eaf43a1010dfc094b6f8b5c76b3e3d6bd70a367ea2cb85682c","src/re_builder.rs":"94ffcf23b009ff67f526dceede829fd02e7f5bf78bfc8ee1195ea571540b7a28","src/re_bytes.rs":"48b0c449bf4864289f5f2250f4993ec26b328a3200743df32549e8f0e28f1888","src/re_set.rs":"bbb1c40725b3fe8533e0c693ac9dc985d03334def67d463604a9a23d610cbc2d","src/re_trait.rs":"49b027ac3f1b981f41bba1ea243e74aa94692837f7c2c10229c7cbd3277e03b4","src/re_unicode.rs":"efd0acf21b1253779ab1f3e6d34709eb1dd109ff93cb3e42d1152870ef390289","src/sparse.rs":"66845b4e8c1a6cb92bcd7973a5bd04d6873b6d669d6737b71bc4f9f04740b85b","src/testdata/LICENSE":"58cf078acc03da3e280a938c2bd9943f554fc9b6ced89ad93ba35ca436872899","src/testdata/README":"45f869e37f798905c773bfbe0ef19a5fb7e585cbf0b7c21b5b5a784e8cec3c14","src/testdata/basic.dat":"b5b33aa89d48a61cd67cb1fbfd8f70e62c83e30b86256f9f915a5190dd38ff06","src/testdata/nullsubexpr.dat":"496ac0278eec3b6d9170faace14554569032dd3d909618364d9326156de39ecf","src/testdata/repetition.dat":"1f7959063015b284b18a4a2c1c8b416d438a2d6c4b1a362da43406b865f50e69","src/utf8.rs":"708615a4859110cc9766b342a9c1da6c5c4a8a04ad239046b2725385db977efe","test":"bd7ca64a788d1f622ae10c5ac77160b10fc5f0d6adb7f3ba1828637f0ca68c81","tests/api.rs":"7b2a0ef75e99b9776094967bd66e9cdeaa8e11359f5f0a12bd08ef0e8d0c11fc","tests/api_str.rs":"2ae38c04e7e8fac008b609a820d0b1561ba75f39b0edc0987d6d3d06132da77f","tests/bytes.rs":"edc50f526c5fee43df89d639ef18b237e4eb91e9d533bfc43f3cbab7417d38ba","tests/consistent.rs":"d69435154c09478076497216e43081a835ac65147181a4fbddad7bff469605b2","tests/crates_regex.rs":"91a59d470e0700b4bcb3ff735d06799f3107b8ef4875a2e9904607b164be0326","tests/crazy.rs":"c0d56380dff19bdd5d7a3eb731d0e2dc564e169a1b73c81e1879b1e87f5f5f77","tests/flags.rs":"05caace2c81a99d2168037f3a38035d4dffe9f85ef3ebd7ef18b1bc6612f1ea8","tests/fowler.rs":"d78cf914de40b1e125cc92b65ccb444d462586bd07b5e05de4e4a1b5de16aa76","tests/macros.rs":"6db70c16fc90df13e6b30d2b606f8b6dd4dc976697967f6ee001b15aab6d0b19","tests/macros_bytes.rs":"a049f528a93173a1bb176cd46932dce1880679f4a1752e099be920f0e4546fd0","tests/macros_str.rs":"e585b1461374c45a2eca44ca045bc3c1fe984b2b4212e432b0c695b420e708b7","tests/misc.rs":"395f52793fa022e4cdda78675b6a6fba1a3106b4b99c834c39f7801574054bd1","tests/multiline.rs":"1b1a3326ed976437c1357f01d81833ece7ea244f38826246eab55cacd5d0862a","tests/noparse.rs":"12b6be0eff3d80779d33c6459396c74c0f6ebf4ddc9f1d33c3e747ea9e3bf268","tests/regression.rs":"4d4aecf57ce5accf73fe8818267e8d45c9a15896d40093a5b5e1a09007a121a1","tests/regression_fuzz.rs":"a504ec563e0d23bd2039493b7b1767fe1f831d7d668f6f4b2ecd124fc7899bcd","tests/replace.rs":"16ae4485901bde78c044225e0ff01560c11c765a8768ce43b9ce841a98a8eddc","tests/searcher.rs":"ce35e47b0a276a7e8c9060c6a0b225ffba163aebc61fbc15555a6897fa0e552c","tests/set.rs":"f1e2af6baeeaed3cc99ed347ff516fe7b2eb0027ef64b891502e1486598eaf8a","tests/shortest_match.rs":"a2c94390c0d61bc24796b4c1288c924e90c8c9c6156fdebb858175177a194a42","tests/suffix_reverse.rs":"b95f89397404871227d9efe6df23b9ded147f183db81597e608f693955c668b5","tests/test_backtrack.rs":"1e286679d643887f7b78ef5a74f5392ff27fa462b99891ce31938db1eacb3842","tests/test_backtrack_bytes.rs":"f66f2ed407795e92ae66eaa3b4b946acfe00d9ea422944c86353dd28812df5bb","tests/test_backtrack_utf8bytes.rs":"9d8c236fbdfa5092230f19ca4d2a7d647f68811d9ffa0813899d924e11d8fc0b","tests/test_crates_regex.rs":"b385d7ca10ed308b8d57074adb9525e18d3faadb5aa883e831dfa4f6669ba58d","tests/test_default.rs":"048640025e537fd74252e68a534a6fb43d7cf457998c05e7acda4fe511907de5","tests/test_default_bytes.rs":"fb3310fc315f7282358dcd98d156c31d66ca2432199afe012cf8921f459167a2","tests/test_nfa.rs":"97266c5edb15e5cde1496049a3ad0be4de33352dc32492f086d5351411ebe1ab","tests/test_nfa_bytes.rs":"9aa510e9583f847467c26ce902bd7e1c66cdd610cd50da4a1c1379afa35d4a53","tests/test_nfa_utf8bytes.rs":"2c22e16fa75edb5dbd278f2b8619404404a95b0792b31c440c9751c4aa2f7086","tests/unicode.rs":"4bf85f5c3d547fa8b5623194a09b6413067499dfbe7c1d29d8b50bf1cddacf6b","tests/word_boundary.rs":"7081317ddcec1e82dd4a2090a571c6abf2ff4bbfa8cd10395e1eb3f386157fae","tests/word_boundary_ascii.rs":"cd0be5b5b485de0ba7994b42e2864585556c3d2d8bf5eab05b58931d9aaf4b87","tests/word_boundary_unicode.rs":"75dbcc35d3abc0f9795c2ea99e216dc227b0a5b58e9ca5eef767815ff0513921"},"package":"2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759"}
\ No newline at end of file
diff --git a/vendor/regex-1.4.6/CHANGELOG.md b/vendor/regex-1.4.6/CHANGELOG.md
new file mode 100644 (file)
index 0000000..b925678
--- /dev/null
@@ -0,0 +1,969 @@
+1.4.6 (2021-04-22)
+==================
+This is a small patch release that fixes the compiler's size check on how much
+heap memory a regex uses. Previously, the compiler did not account for the
+heap usage of Unicode character classes. Now it does. It's possible that this
+may make some regexes fail to compile that previously did compile. If that
+happens, please file an issue.
+
+* [BUG OSS-fuzz#33579](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=33579):
+  Some regexes can use more heap memory than one would expect.
+
+
+1.4.5 (2021-03-14)
+==================
+This is a small patch release that fixes a regression in the size of a `Regex`
+in the 1.4.4 release. Prior to 1.4.4, a `Regex` was 552 bytes. In the 1.4.4
+release, it was 856 bytes due to internal changes. In this release, a `Regex`
+is now 16 bytes. In general, the size of a `Regex` was never something that was
+on my radar, but this increased size in the 1.4.4 release seems to have crossed
+a threshold and resulted in stack overflows in some programs.
+
+* [BUG #750](https://github.com/rust-lang/regex/pull/750):
+  Fixes stack overflows seemingly caused by a large `Regex` size by decreasing
+  its size.
+
+
+1.4.4 (2021-03-11)
+==================
+This is a small patch release that contains some bug fixes. Notably, it also
+drops the `thread_local` (and `lazy_static`, via transitivity) dependencies.
+
+Bug fixes:
+
+* [BUG #362](https://github.com/rust-lang/regex/pull/362):
+  Memory leaks caused by an internal caching strategy should now be fixed.
+* [BUG #576](https://github.com/rust-lang/regex/pull/576):
+  All regex types now implement `UnwindSafe` and `RefUnwindSafe`.
+* [BUG #728](https://github.com/rust-lang/regex/pull/749):
+  Add missing `Replacer` impls for `Vec<u8>`, `String`, `Cow`, etc.
+
+
+1.4.3 (2021-01-08)
+==================
+This is a small patch release that adds some missing standard trait
+implementations for some types in the public API.
+
+Bug fixes:
+
+* [BUG #734](https://github.com/rust-lang/regex/pull/734):
+  Add `FusedIterator` and `ExactSizeIterator` impls to iterator types.
+* [BUG #735](https://github.com/rust-lang/regex/pull/735):
+  Add missing `Debug` impls to public API types.
+
+
+1.4.2 (2020-11-01)
+==================
+This is a small bug fix release that bans `\P{any}`. We previously banned empty
+classes like `[^\w\W]`, but missed the `\P{any}` case. In the future, we hope
+to permit empty classes.
+
+* [BUG #722](https://github.com/rust-lang/regex/issues/722):
+  Ban `\P{any}` to avoid a panic in the regex compiler. Found by OSS-Fuzz.
+
+
+1.4.1 (2020-10-13)
+==================
+This is a small bug fix release that makes `\p{cf}` work. Previously, it would
+report "property not found" even though `cf` is a valid abbreviation for the
+`Format` general category.
+
+* [BUG #719](https://github.com/rust-lang/regex/issues/719):
+  Fixes bug that prevented `\p{cf}` from working.
+
+
+1.4.0 (2020-10-11)
+==================
+This releases has a few minor documentation fixes as well as some very minor
+API additions. The MSRV remains at Rust 1.28 for now, but this is intended to
+increase to at least Rust 1.41.1 soon.
+
+This release also adds support for OSS-Fuzz. Kudos to
+[@DavidKorczynski](https://github.com/DavidKorczynski)
+for doing the heavy lifting for that!
+
+New features:
+
+* [FEATURE #649](https://github.com/rust-lang/regex/issues/649):
+  Support `[`, `]` and `.` in capture group names.
+* [FEATURE #687](https://github.com/rust-lang/regex/issues/687):
+  Add `is_empty` predicate to `RegexSet`.
+* [FEATURE #689](https://github.com/rust-lang/regex/issues/689):
+  Implement `Clone` for `SubCaptureMatches`.
+* [FEATURE #715](https://github.com/rust-lang/regex/issues/715):
+  Add `empty` constructor to `RegexSet` for convenience.
+
+Bug fixes:
+
+* [BUG #694](https://github.com/rust-lang/regex/issues/694):
+  Fix doc example for `Replacer::replace_append`.
+* [BUG #698](https://github.com/rust-lang/regex/issues/698):
+  Clarify docs for `s` flag when using a `bytes::Regex`.
+* [BUG #711](https://github.com/rust-lang/regex/issues/711):
+  Clarify `is_match` docs to indicate that it can match anywhere in string.
+
+
+1.3.9 (2020-05-28)
+==================
+This release fixes a MSRV (Minimum Support Rust Version) regression in the
+1.3.8 release. Namely, while 1.3.8 compiles on Rust 1.28, it actually does not
+compile on other Rust versions, such as Rust 1.39.
+
+Bug fixes:
+
+* [BUG #685](https://github.com/rust-lang/regex/issues/685):
+  Remove use of `doc_comment` crate, which cannot be used before Rust 1.43.
+
+
+1.3.8 (2020-05-28)
+==================
+This release contains a couple of important bug fixes driven
+by better support for empty-subexpressions in regexes. For
+example, regexes like `b|` are now allowed. Major thanks to
+[@sliquister](https://github.com/sliquister) for implementing support for this
+in [#677](https://github.com/rust-lang/regex/pull/677).
+
+Bug fixes:
+
+* [BUG #523](https://github.com/rust-lang/regex/pull/523):
+  Add note to documentation that spaces can be escaped in `x` mode.
+* [BUG #524](https://github.com/rust-lang/regex/issues/524):
+  Add support for empty sub-expressions, including empty alternations.
+* [BUG #659](https://github.com/rust-lang/regex/issues/659):
+  Fix match bug caused by an empty sub-expression miscompilation.
+
+
+1.3.7 (2020-04-17)
+==================
+This release contains a small bug fix that fixes how `regex` forwards crate
+features to `regex-syntax`. In particular, this will reduce recompilations in
+some cases.
+
+Bug fixes:
+
+* [BUG #665](https://github.com/rust-lang/regex/pull/665):
+  Fix feature forwarding to `regex-syntax`.
+
+
+1.3.6 (2020-03-24)
+==================
+This release contains a sizable (~30%) performance improvement when compiling
+some kinds of large regular expressions.
+
+Performance improvements:
+
+* [PERF #657](https://github.com/rust-lang/regex/pull/657):
+  Improvement performance of compiling large regular expressions.
+
+
+1.3.5 (2020-03-12)
+==================
+This release updates this crate to Unicode 13.
+
+New features:
+
+* [FEATURE #653](https://github.com/rust-lang/regex/pull/653):
+  Update `regex-syntax` to Unicode 13.
+
+
+1.3.4 (2020-01-30)
+==================
+This is a small bug fix release that fixes a bug related to the scoping of
+flags in a regex. Namely, before this fix, a regex like `((?i)a)b)` would
+match `aB` despite the fact that `b` should not be matched case insensitively.
+
+Bug fixes:
+
+* [BUG #640](https://github.com/rust-lang/regex/issues/640):
+  Fix bug related to the scoping of flags in a regex.
+
+
+1.3.3 (2020-01-09)
+==================
+This is a small maintenance release that upgrades the dependency on
+`thread_local` from `0.3` to `1.0`. The minimum supported Rust version remains
+at Rust 1.28.
+
+
+1.3.2 (2020-01-09)
+==================
+This is a small maintenance release with some house cleaning and bug fixes.
+
+New features:
+
+* [FEATURE #631](https://github.com/rust-lang/regex/issues/631):
+  Add a `Match::range` method an a `From<Match> for Range` impl.
+
+Bug fixes:
+
+* [BUG #521](https://github.com/rust-lang/regex/issues/521):
+  Corrects `/-/.splitn("a", 2)` to return `["a"]` instead of `["a", ""]`.
+* [BUG #594](https://github.com/rust-lang/regex/pull/594):
+  Improve error reporting when writing `\p\`.
+* [BUG #627](https://github.com/rust-lang/regex/issues/627):
+  Corrects `/-/.split("a-")` to return `["a", ""]` instead of `["a"]`.
+* [BUG #633](https://github.com/rust-lang/regex/pull/633):
+  Squash deprecation warnings for the `std::error::Error::description` method.
+
+
+1.3.1 (2019-09-04)
+==================
+This is a maintenance release with no changes in order to try to work-around
+a [docs.rs/Cargo issue](https://github.com/rust-lang/docs.rs/issues/400).
+
+
+1.3.0 (2019-09-03)
+==================
+This release adds a plethora of new crate features that permit users of regex
+to shrink its size considerably, in exchange for giving up either functionality
+(such as Unicode support) or runtime performance. When all such features are
+disabled, the dependency tree for `regex` shrinks to exactly 1 crate
+(`regex-syntax`). More information about the new crate features can be
+[found in the docs](https://docs.rs/regex/*/#crate-features).
+
+Note that while this is a new minor version release, the minimum supported
+Rust version for this crate remains at `1.28.0`.
+
+New features:
+
+* [FEATURE #474](https://github.com/rust-lang/regex/issues/474):
+  The `use_std` feature has been deprecated in favor of the `std` feature.
+  The `use_std` feature will be removed in regex 2. Until then, `use_std` will
+  remain as an alias for the `std` feature.
+* [FEATURE #583](https://github.com/rust-lang/regex/issues/583):
+  Add a substantial number of crate features shrinking `regex`.
+
+
+1.2.1 (2019-08-03)
+==================
+This release does a bit of house cleaning. Namely:
+
+* This repository is now using rustfmt.
+* License headers have been removed from all files, in following suit with the
+  Rust project.
+* Teddy has been removed from the `regex` crate, and is now part of the
+  `aho-corasick` crate.
+  [See `aho-corasick`'s new `packed` sub-module for details](https://docs.rs/aho-corasick/0.7.6/aho_corasick/packed/index.html).
+* The `utf8-ranges` crate has been deprecated, with its functionality moving
+  into the
+  [`utf8` sub-module of `regex-syntax`](https://docs.rs/regex-syntax/0.6.11/regex_syntax/utf8/index.html).
+* The `ucd-util` dependency has been dropped, in favor of implementing what
+  little we need inside of `regex-syntax` itself.
+
+In general, this is part of an ongoing (long term) effort to make optimizations
+in the regex engine easier to reason about. The current code is too convoluted
+and thus it is very easy to introduce new bugs. This simplification effort is
+the primary motivation behind re-working the `aho-corasick` crate to not only
+bundle algorithms like Teddy, but to also provide regex-like match semantics
+automatically.
+
+Moving forward, the plan is to join up with the `bstr` and `regex-automata`
+crates, with the former providing more sophisticated substring search
+algorithms (thereby deleting existing code in `regex`) and the latter providing
+ahead-of-time compiled DFAs for cases where they are inexpensive to compute.
+
+
+1.2.0 (2019-07-20)
+==================
+This release updates regex's minimum supported Rust version to 1.28, which was
+release almost 1 year ago. This release also updates regex's Unicode data
+tables to 12.1.0.
+
+
+1.1.9 (2019-07-06)
+==================
+This release contains a bug fix that caused regex's tests to fail, due to a
+dependency on an unreleased behavior in regex-syntax.
+
+* [BUG #593](https://github.com/rust-lang/regex/issues/593):
+  Move an integration-style test on error messages into regex-syntax.
+
+
+1.1.8 (2019-07-04)
+==================
+This release contains a few small internal refactorings. One of which fixes
+an instance of undefined behavior in a part of the SIMD code.
+
+Bug fixes:
+
+* [BUG #545](https://github.com/rust-lang/regex/issues/545):
+  Improves error messages when a repetition operator is used without a number.
+* [BUG #588](https://github.com/rust-lang/regex/issues/588):
+  Removes use of a repr(Rust) union used for type punning in the Teddy matcher.
+* [BUG #591](https://github.com/rust-lang/regex/issues/591):
+  Update docs for running benchmarks and improve failure modes.
+
+
+1.1.7 (2019-06-09)
+==================
+This release fixes up a few warnings as a result of recent deprecations.
+
+
+1.1.6 (2019-04-16)
+==================
+This release fixes a regression introduced by a bug fix (for
+[BUG #557](https://github.com/rust-lang/regex/issues/557)) which could cause
+the regex engine to enter an infinite loop. This bug was originally
+[reported against ripgrep](https://github.com/BurntSushi/ripgrep/issues/1247).
+
+
+1.1.5 (2019-04-01)
+==================
+This release fixes a bug in regex's dependency specification where it requires
+a newer version of regex-syntax, but this wasn't communicated correctly in the
+Cargo.toml. This would have been caught by a minimal version check, but this
+check was disabled because the `rand` crate itself advertises incorrect
+dependency specifications.
+
+Bug fixes:
+
+* [BUG #570](https://github.com/rust-lang/regex/pull/570):
+  Fix regex-syntax minimal version.
+
+
+1.1.4 (2019-03-31)
+==================
+This release fixes a backwards compatibility regression where Regex was no
+longer UnwindSafe. This was caused by the upgrade to aho-corasick 0.7, whose
+AhoCorasick type was itself not UnwindSafe. This has been fixed in aho-corasick
+0.7.4, which we now require.
+
+Bug fixes:
+
+* [BUG #568](https://github.com/rust-lang/regex/pull/568):
+  Fix an API regression where Regex was no longer UnwindSafe.
+
+
+1.1.3 (2019-03-30)
+==================
+This releases fixes a few bugs and adds a performance improvement when a regex
+is a simple alternation of literals.
+
+Performance improvements:
+
+* [OPT #566](https://github.com/rust-lang/regex/pull/566):
+  Upgrades `aho-corasick` to 0.7 and uses it for `foo|bar|...|quux` regexes.
+
+Bug fixes:
+
+* [BUG #527](https://github.com/rust-lang/regex/issues/527):
+  Fix a bug where the parser would panic on patterns like `((?x))`.
+* [BUG #555](https://github.com/rust-lang/regex/issues/555):
+  Fix a bug where the parser would panic on patterns like `(?m){1,1}`.
+* [BUG #557](https://github.com/rust-lang/regex/issues/557):
+  Fix a bug where captures could lead to an incorrect match.
+
+
+1.1.2 (2019-02-27)
+==================
+This release fixes a bug found in the fix introduced in 1.1.1.
+
+Bug fixes:
+
+* [BUG edf45e6f](https://github.com/rust-lang/regex/commit/edf45e6f):
+  Fix bug introduced in reverse suffix literal matcher in the 1.1.1 release.
+
+
+1.1.1 (2019-02-27)
+==================
+This is a small release with one fix for a bug caused by literal optimizations.
+
+Bug fixes:
+
+* [BUG 661bf53d](https://github.com/rust-lang/regex/commit/661bf53d):
+  Fixes a bug in the reverse suffix literal optimization. This was originally
+  reported
+  [against ripgrep](https://github.com/BurntSushi/ripgrep/issues/1203).
+
+
+1.1.0 (2018-11-30)
+==================
+This is a small release with a couple small enhancements. This release also
+increases the minimal supported Rust version (MSRV) to 1.24.1 (from 1.20.0). In
+accordance with this crate's MSRV policy, this release bumps the minor version
+number.
+
+Performance improvements:
+
+* [OPT #511](https://github.com/rust-lang/regex/pull/511),
+  [OPT #540](https://github.com/rust-lang/regex/pull/540):
+  Improve lazy DFA construction for large regex sets.
+
+New features:
+
+* [FEATURE #538](https://github.com/rust-lang/regex/pull/538):
+  Add Emoji and "break" Unicode properties. See [UNICODE.md](UNICODE.md).
+
+Bug fixes:
+
+* [BUG #530](https://github.com/rust-lang/regex/pull/530):
+  Add Unicode license (for data tables).
+* Various typo/doc fixups.
+
+
+1.0.6 (2018-11-06)
+==================
+This is a small release.
+
+Performance improvements:
+
+* [OPT #513](https://github.com/rust-lang/regex/pull/513):
+  Improve performance of compiling large Unicode classes by 8-10%.
+
+Bug fixes:
+
+* [BUG #533](https://github.com/rust-lang/regex/issues/533):
+  Fix definition of `[[:blank:]]` class that regressed in `regex-syntax 0.5`.
+
+
+1.0.5 (2018-09-06)
+==================
+This is a small release with an API enhancement.
+
+New features:
+
+* [FEATURE #509](https://github.com/rust-lang/regex/pull/509):
+  Generalize impls of the `Replacer` trait.
+
+
+1.0.4 (2018-08-25)
+==================
+This is a small release that bumps the quickcheck dependency.
+
+
+1.0.3 (2018-08-24)
+==================
+This is a small bug fix release.
+
+Bug fixes:
+
+* [BUG #504](https://github.com/rust-lang/regex/pull/504):
+  Fix for Cargo's "minimal version" support.
+* [BUG 1e39165f](https://github.com/rust-lang/regex/commit/1e39165f):
+  Fix doc examples for byte regexes.
+
+
+1.0.2 (2018-07-18)
+==================
+This release exposes some new lower level APIs on `Regex` that permit
+amortizing allocation and controlling the location at which a search is
+performed in a more granular way. Most users of the regex crate will not
+need or want to use these APIs.
+
+New features:
+
+* [FEATURE #493](https://github.com/rust-lang/regex/pull/493):
+  Add a few lower level APIs for amortizing allocation and more fine grained
+  searching.
+
+Bug fixes:
+
+* [BUG 3981d2ad](https://github.com/rust-lang/regex/commit/3981d2ad):
+  Correct outdated documentation on `RegexBuilder::dot_matches_new_line`.
+* [BUG 7ebe4ae0](https://github.com/rust-lang/regex/commit/7ebe4ae0):
+  Correct outdated documentation on `Parser::allow_invalid_utf8` in the
+  `regex-syntax` crate.
+* [BUG 24c7770b](https://github.com/rust-lang/regex/commit/24c7770b):
+  Fix a bug in the HIR printer where it wouldn't correctly escape meta
+  characters in character classes.
+
+
+1.0.1 (2018-06-19)
+==================
+This release upgrades regex's Unicode tables to Unicode 11, and enables SIMD
+optimizations automatically on Rust stable (1.27 or newer).
+
+New features:
+
+* [FEATURE #486](https://github.com/rust-lang/regex/pull/486):
+  Implement `size_hint` on `RegexSet` match iterators.
+* [FEATURE #488](https://github.com/rust-lang/regex/pull/488):
+  Update Unicode tables for Unicode 11.
+* [FEATURE #490](https://github.com/rust-lang/regex/pull/490):
+  SIMD optimizations are now enabled automatically in Rust stable, for versions
+  1.27 and up. No compilation flags or features need to be set. CPU support
+  SIMD is detected automatically at runtime.
+
+Bug fixes:
+
+* [BUG #482](https://github.com/rust-lang/regex/pull/482):
+  Present a better compilation error when the `use_std` feature isn't used.
+
+
+1.0.0 (2018-05-01)
+==================
+This release marks the 1.0 release of regex.
+
+While this release includes some breaking changes, most users of older versions
+of the regex library should be able to migrate to 1.0 by simply bumping the
+version number. The important changes are as follows:
+
+* We adopt Rust 1.20 as the new minimum supported version of Rust for regex.
+  We also tentativley adopt a policy that permits bumping the minimum supported
+  version of Rust in minor version releases of regex, but no patch releases.
+  That is, with respect to semver, we do not strictly consider bumping the
+  minimum version of Rust to be a breaking change, but adopt a conservative
+  stance as a compromise.
+* Octal syntax in regular expressions has been disabled by default. This
+  permits better error messages that inform users that backreferences aren't
+  available. Octal syntax can be re-enabled via the corresponding option on
+  `RegexBuilder`.
+* `(?-u:\B)` is no longer allowed in Unicode regexes since it can match at
+  invalid UTF-8 code unit boundaries. `(?-u:\b)` is still allowed in Unicode
+  regexes.
+* The `From<regex_syntax::Error>` impl has been removed. This formally removes
+  the public dependency on `regex-syntax`.
+* A new feature, `use_std`, has been added and enabled by default. Disabling
+  the feature will result in a compilation error. In the future, this may
+  permit us to support `no_std` environments (w/ `alloc`) in a backwards
+  compatible way.
+
+For more information and discussion, please see
+[1.0 release tracking issue](https://github.com/rust-lang/regex/issues/457).
+
+
+0.2.11 (2018-05-01)
+===================
+This release primarily contains bug fixes. Some of them resolve bugs where
+the parser could panic.
+
+New features:
+
+* [FEATURE #459](https://github.com/rust-lang/regex/pull/459):
+  Include C++'s standard regex library and Boost's regex library in the
+  benchmark harness. We now include D/libphobos, C++/std, C++/boost, Oniguruma,
+  PCRE1, PCRE2, RE2 and Tcl in the harness.
+
+Bug fixes:
+
+* [BUG #445](https://github.com/rust-lang/regex/issues/445):
+  Clarify order of indices returned by RegexSet match iterator.
+* [BUG #461](https://github.com/rust-lang/regex/issues/461):
+  Improve error messages for invalid regexes like `[\d-a]`.
+* [BUG #464](https://github.com/rust-lang/regex/issues/464):
+  Fix a bug in the error message pretty printer that could cause a panic when
+  a regex contained a literal `\n` character.
+* [BUG #465](https://github.com/rust-lang/regex/issues/465):
+  Fix a panic in the parser that was caused by applying a repetition operator
+  to `(?flags)`.
+* [BUG #466](https://github.com/rust-lang/regex/issues/466):
+  Fix a bug where `\pC` was not recognized as an alias for `\p{Other}`.
+* [BUG #470](https://github.com/rust-lang/regex/pull/470):
+  Fix a bug where literal searches did more work than necessary for anchored
+  regexes.
+
+
+0.2.10 (2018-03-16)
+===================
+This release primarily updates the regex crate to changes made in `std::arch`
+on nightly Rust.
+
+New features:
+
+* [FEATURE #458](https://github.com/rust-lang/regex/pull/458):
+  The `Hir` type in `regex-syntax` now has a printer.
+
+
+0.2.9 (2018-03-12)
+==================
+This release introduces a new nightly only feature, `unstable`, which enables
+SIMD optimizations for certain types of regexes. No additional compile time
+options are necessary, and the regex crate will automatically choose the
+best CPU features at run time. As a result, the `simd` (nightly only) crate
+dependency has been dropped.
+
+New features:
+
+* [FEATURE #456](https://github.com/rust-lang/regex/pull/456):
+  The regex crate now includes AVX2 optimizations in addition to the extant
+  SSSE3 optimization.
+
+Bug fixes:
+
+* [BUG #455](https://github.com/rust-lang/regex/pull/455):
+  Fix a bug where `(?x)[ / - ]` failed to parse.
+
+
+0.2.8 (2018-03-12)
+==================
+Bug gixes:
+
+* [BUG #454](https://github.com/rust-lang/regex/pull/454):
+  Fix a bug in the nest limit checker being too aggressive.
+
+
+0.2.7 (2018-03-07)
+==================
+This release includes a ground-up rewrite of the regex-syntax crate, which has
+been in development for over a year.
+
+New features:
+
+* Error messages for invalid regexes have been greatly improved. You get these
+  automatically; you don't need to do anything. In addition to better
+  formatting, error messages will now explicitly call out the use of look
+  around. When regex 1.0 is released, this will happen for backreferences as
+  well.
+* Full support for intersection, difference and symmetric difference of
+  character classes. These can be used via the `&&`, `--` and `~~` binary
+  operators within classes.
+* A Unicode Level 1 conformat implementation of `\p{..}` character classes.
+  Things like `\p{scx:Hira}`, `\p{age:3.2}` or `\p{Changes_When_Casefolded}`
+  now work. All property name and value aliases are supported, and properties
+  are selected via loose matching. e.g., `\p{Greek}` is the same as
+  `\p{G r E e K}`.
+* A new `UNICODE.md` document has been added to this repository that
+  exhaustively documents support for UTS#18.
+* Empty sub-expressions are now permitted in most places. That is, `()+` is
+  now a valid regex.
+* Almost everything in regex-syntax now uses constant stack space, even when
+  performing anaylsis that requires structural induction. This reduces the risk
+  of a user provided regular expression causing a stack overflow.
+* [FEATURE #174](https://github.com/rust-lang/regex/issues/174):
+  The `Ast` type in `regex-syntax` now contains span information.
+* [FEATURE #424](https://github.com/rust-lang/regex/issues/424):
+  Support `\u`, `\u{...}`, `\U` and `\U{...}` syntax for specifying code points
+  in a regular expression.
+* [FEATURE #449](https://github.com/rust-lang/regex/pull/449):
+  Add a `Replace::by_ref` adapter for use of a replacer without consuming it.
+
+Bug fixes:
+
+* [BUG #446](https://github.com/rust-lang/regex/issues/446):
+  We re-enable the Boyer-Moore literal matcher.
+
+
+0.2.6 (2018-02-08)
+==================
+Bug fixes:
+
+* [BUG #446](https://github.com/rust-lang/regex/issues/446):
+  Fixes a bug in the new Boyer-Moore searcher that results in a match failure.
+  We fix this bug by temporarily disabling Boyer-Moore.
+
+
+0.2.5 (2017-12-30)
+==================
+Bug fixes:
+
+* [BUG #437](https://github.com/rust-lang/regex/issues/437):
+  Fixes a bug in the new Boyer-Moore searcher that results in a panic.
+
+
+0.2.4 (2017-12-30)
+==================
+New features:
+
+* [FEATURE #348](https://github.com/rust-lang/regex/pull/348):
+  Improve performance for capture searches on anchored regex.
+  (Contributed by @ethanpailes. Nice work!)
+* [FEATURE #419](https://github.com/rust-lang/regex/pull/419):
+  Expand literal searching to include Tuned Boyer-Moore in some cases.
+  (Contributed by @ethanpailes. Nice work!)
+
+Bug fixes:
+
+* [BUG](https://github.com/rust-lang/regex/pull/436):
+  The regex compiler plugin has been removed.
+* [BUG](https://github.com/rust-lang/regex/pull/436):
+  `simd` has been bumped to `0.2.1`, which fixes a Rust nightly build error.
+* [BUG](https://github.com/rust-lang/regex/pull/436):
+  Bring the benchmark harness up to date.
+
+
+0.2.3 (2017-11-30)
+==================
+New features:
+
+* [FEATURE #374](https://github.com/rust-lang/regex/pull/374):
+  Add `impl From<Match> for &str`.
+* [FEATURE #380](https://github.com/rust-lang/regex/pull/380):
+  Derive `Clone` and `PartialEq` on `Error`.
+* [FEATURE #400](https://github.com/rust-lang/regex/pull/400):
+  Update to Unicode 10.
+
+Bug fixes:
+
+* [BUG #375](https://github.com/rust-lang/regex/issues/375):
+  Fix a bug that prevented the bounded backtracker from terminating.
+* [BUG #393](https://github.com/rust-lang/regex/issues/393),
+  [BUG #394](https://github.com/rust-lang/regex/issues/394):
+  Fix bug with `replace` methods for empty matches.
+
+
+0.2.2 (2017-05-21)
+==================
+New features:
+
+* [FEATURE #341](https://github.com/rust-lang/regex/issues/341):
+  Support nested character classes and intersection operation.
+  For example, `[\p{Greek}&&\pL]` matches greek letters and
+  `[[0-9]&&[^4]]` matches every decimal digit except `4`.
+  (Much thanks to @robinst, who contributed this awesome feature.)
+
+Bug fixes:
+
+* [BUG #321](https://github.com/rust-lang/regex/issues/321):
+  Fix bug in literal extraction and UTF-8 decoding.
+* [BUG #326](https://github.com/rust-lang/regex/issues/326):
+  Add documentation tip about the `(?x)` flag.
+* [BUG #333](https://github.com/rust-lang/regex/issues/333):
+  Show additional replacement example using curly braces.
+* [BUG #334](https://github.com/rust-lang/regex/issues/334):
+  Fix bug when resolving captures after a match.
+* [BUG #338](https://github.com/rust-lang/regex/issues/338):
+  Add example that uses `Captures::get` to API documentation.
+* [BUG #353](https://github.com/rust-lang/regex/issues/353):
+  Fix RegexSet bug that caused match failure in some cases.
+* [BUG #354](https://github.com/rust-lang/regex/pull/354):
+  Fix panic in parser when `(?x)` is used.
+* [BUG #358](https://github.com/rust-lang/regex/issues/358):
+  Fix literal optimization bug with RegexSet.
+* [BUG #359](https://github.com/rust-lang/regex/issues/359):
+  Fix example code in README.
+* [BUG #365](https://github.com/rust-lang/regex/pull/365):
+  Fix bug in `rure_captures_len` in the C binding.
+* [BUG #367](https://github.com/rust-lang/regex/issues/367):
+  Fix byte class bug that caused a panic.
+
+
+0.2.1
+=====
+One major bug with `replace_all` has been fixed along with a couple of other
+touchups.
+
+* [BUG #312](https://github.com/rust-lang/regex/issues/312):
+  Fix documentation for `NoExpand` to reference correct lifetime parameter.
+* [BUG #314](https://github.com/rust-lang/regex/issues/314):
+  Fix a bug with `replace_all` when replacing a match with the empty string.
+* [BUG #316](https://github.com/rust-lang/regex/issues/316):
+  Note a missing breaking change from the `0.2.0` CHANGELOG entry.
+  (`RegexBuilder::compile` was renamed to `RegexBuilder::build`.)
+* [BUG #324](https://github.com/rust-lang/regex/issues/324):
+  Compiling `regex` should only require one version of `memchr` crate.
+
+
+0.2.0
+=====
+This is a new major release of the regex crate, and is an implementation of the
+[regex 1.0 RFC](https://github.com/rust-lang/rfcs/blob/master/text/1620-regex-1.0.md).
+We are releasing a `0.2` first, and if there are no major problems, we will
+release a `1.0` shortly. For `0.2`, the minimum *supported* Rust version is
+1.12.
+
+There are a number of **breaking changes** in `0.2`. They are split into two
+types. The first type correspond to breaking changes in regular expression
+syntax. The second type correspond to breaking changes in the API.
+
+Breaking changes for regex syntax:
+
+* POSIX character classes now require double bracketing. Previously, the regex
+  `[:upper:]` would parse as the `upper` POSIX character class. Now it parses
+  as the character class containing the characters `:upper:`. The fix to this
+  change is to use `[[:upper:]]` instead. Note that variants like
+  `[[:upper:][:blank:]]` continue to work.
+* The character `[` must always be escaped inside a character class.
+* The characters `&`, `-` and `~` must be escaped if any one of them are
+  repeated consecutively. For example, `[&]`, `[\&]`, `[\&\&]`, `[&-&]` are all
+  equivalent while `[&&]` is illegal. (The motivation for this and the prior
+  change is to provide a backwards compatible path for adding character class
+  set notation.)
+* A `bytes::Regex` now has Unicode mode enabled by default (like the main
+  `Regex` type). This means regexes compiled with `bytes::Regex::new` that
+  don't have the Unicode flag set should add `(?-u)` to recover the original
+  behavior.
+
+Breaking changes for the regex API:
+
+* `find` and `find_iter` now **return `Match` values instead of
+  `(usize, usize)`.** `Match` values have `start` and `end` methods, which
+  return the match offsets. `Match` values also have an `as_str` method,
+  which returns the text of the match itself.
+* The `Captures` type now only provides a single iterator over all capturing
+  matches, which should replace uses of `iter` and `iter_pos`. Uses of
+  `iter_named` should use the `capture_names` method on `Regex`.
+* The `at` method on the `Captures` type has been renamed to `get`, and it
+  now returns a `Match`. Similarly, the `name` method on `Captures` now returns
+  a `Match`.
+* The `replace` methods now return `Cow` values. The `Cow::Borrowed` variant
+  is returned when no replacements are made.
+* The `Replacer` trait has been completely overhauled. This should only
+  impact clients that implement this trait explicitly. Standard uses of
+  the `replace` methods should continue to work unchanged. If you implement
+  the `Replacer` trait, please consult the new documentation.
+* The `quote` free function has been renamed to `escape`.
+* The `Regex::with_size_limit` method has been removed. It is replaced by
+  `RegexBuilder::size_limit`.
+* The `RegexBuilder` type has switched from owned `self` method receivers to
+  `&mut self` method receivers. Most uses will continue to work unchanged, but
+  some code may require naming an intermediate variable to hold the builder.
+* The `compile` method on `RegexBuilder` has been renamed to `build`.
+* The free `is_match` function has been removed. It is replaced by compiling
+  a `Regex` and calling its `is_match` method.
+* The `PartialEq` and `Eq` impls on `Regex` have been dropped. If you relied
+  on these impls, the fix is to define a wrapper type around `Regex`, impl
+  `Deref` on it and provide the necessary impls.
+* The `is_empty` method on `Captures` has been removed. This always returns
+  `false`, so its use is superfluous.
+* The `Syntax` variant of the `Error` type now contains a string instead of
+  a `regex_syntax::Error`. If you were examining syntax errors more closely,
+  you'll need to explicitly use the `regex_syntax` crate to re-parse the regex.
+* The `InvalidSet` variant of the `Error` type has been removed since it is
+  no longer used.
+* Most of the iterator types have been renamed to match conventions. If you
+  were using these iterator types explicitly, please consult the documentation
+  for its new name. For example, `RegexSplits` has been renamed to `Split`.
+
+A number of bugs have been fixed:
+
+* [BUG #151](https://github.com/rust-lang/regex/issues/151):
+  The `Replacer` trait has been changed to permit the caller to control
+  allocation.
+* [BUG #165](https://github.com/rust-lang/regex/issues/165):
+  Remove the free `is_match` function.
+* [BUG #166](https://github.com/rust-lang/regex/issues/166):
+  Expose more knobs (available in `0.1`) and remove `with_size_limit`.
+* [BUG #168](https://github.com/rust-lang/regex/issues/168):
+  Iterators produced by `Captures` now have the correct lifetime parameters.
+* [BUG #175](https://github.com/rust-lang/regex/issues/175):
+  Fix a corner case in the parsing of POSIX character classes.
+* [BUG #178](https://github.com/rust-lang/regex/issues/178):
+  Drop the `PartialEq` and `Eq` impls on `Regex`.
+* [BUG #179](https://github.com/rust-lang/regex/issues/179):
+  Remove `is_empty` from `Captures` since it always returns false.
+* [BUG #276](https://github.com/rust-lang/regex/issues/276):
+  Position of named capture can now be retrieved from a `Captures`.
+* [BUG #296](https://github.com/rust-lang/regex/issues/296):
+  Remove winapi/kernel32-sys dependency on UNIX.
+* [BUG #307](https://github.com/rust-lang/regex/issues/307):
+  Fix error on emscripten.
+
+
+0.1.80
+======
+* [PR #292](https://github.com/rust-lang/regex/pull/292):
+  Fixes bug #291, which was introduced by PR #290.
+
+0.1.79
+======
+* Require regex-syntax 0.3.8.
+
+0.1.78
+======
+* [PR #290](https://github.com/rust-lang/regex/pull/290):
+  Fixes bug #289, which caused some regexes with a certain combination
+  of literals to match incorrectly.
+
+0.1.77
+======
+* [PR #281](https://github.com/rust-lang/regex/pull/281):
+  Fixes bug #280 by disabling all literal optimizations when a pattern
+  is partially anchored.
+
+0.1.76
+======
+* Tweak criteria for using the Teddy literal matcher.
+
+0.1.75
+======
+* [PR #275](https://github.com/rust-lang/regex/pull/275):
+  Improves match verification performance in the Teddy SIMD searcher.
+* [PR #278](https://github.com/rust-lang/regex/pull/278):
+  Replaces slow substring loop in the Teddy SIMD searcher with Aho-Corasick.
+* Implemented DoubleEndedIterator on regex set match iterators.
+
+0.1.74
+======
+* Release regex-syntax 0.3.5 with a minor bug fix.
+* Fix bug #272.
+* Fix bug #277.
+* [PR #270](https://github.com/rust-lang/regex/pull/270):
+  Fixes bugs #264, #268 and an unreported where the DFA cache size could be
+  drastically under estimated in some cases (leading to high unexpected memory
+  usage).
+
+0.1.73
+======
+* Release `regex-syntax 0.3.4`.
+* Bump `regex-syntax` dependency version for `regex` to `0.3.4`.
+
+0.1.72
+======
+* [PR #262](https://github.com/rust-lang/regex/pull/262):
+  Fixes a number of small bugs caught by fuzz testing (AFL).
+
+0.1.71
+======
+* [PR #236](https://github.com/rust-lang/regex/pull/236):
+  Fix a bug in how suffix literals were extracted, which could lead
+  to invalid match behavior in some cases.
+
+0.1.70
+======
+* [PR #231](https://github.com/rust-lang/regex/pull/231):
+  Add SIMD accelerated multiple pattern search.
+* [PR #228](https://github.com/rust-lang/regex/pull/228):
+  Reintroduce the reverse suffix literal optimization.
+* [PR #226](https://github.com/rust-lang/regex/pull/226):
+  Implements NFA state compression in the lazy DFA.
+* [PR #223](https://github.com/rust-lang/regex/pull/223):
+  A fully anchored RegexSet can now short-circuit.
+
+0.1.69
+======
+* [PR #216](https://github.com/rust-lang/regex/pull/216):
+  Tweak the threshold for running backtracking.
+* [PR #217](https://github.com/rust-lang/regex/pull/217):
+  Add upper limit (from the DFA) to capture search (for the NFA).
+* [PR #218](https://github.com/rust-lang/regex/pull/218):
+  Add rure, a C API.
+
+0.1.68
+======
+* [PR #210](https://github.com/rust-lang/regex/pull/210):
+  Fixed a performance bug in `bytes::Regex::replace` where `extend` was used
+  instead of `extend_from_slice`.
+* [PR #211](https://github.com/rust-lang/regex/pull/211):
+  Fixed a bug in the handling of word boundaries in the DFA.
+* [PR #213](https://github.com/rust-lang/pull/213):
+  Added RE2 and Tcl to the benchmark harness. Also added a CLI utility from
+  running regexes using any of the following regex engines: PCRE1, PCRE2,
+  Oniguruma, RE2, Tcl and of course Rust's own regexes.
+
+0.1.67
+======
+* [PR #201](https://github.com/rust-lang/regex/pull/201):
+  Fix undefined behavior in the `regex!` compiler plugin macro.
+* [PR #205](https://github.com/rust-lang/regex/pull/205):
+  More improvements to DFA performance. Competitive with RE2. See PR for
+  benchmarks.
+* [PR #209](https://github.com/rust-lang/regex/pull/209):
+  Release 0.1.66 was semver incompatible since it required a newer version
+  of Rust than previous releases. This PR fixes that. (And `0.1.66` was
+  yanked.)
+
+0.1.66
+======
+* Speculative support for Unicode word boundaries was added to the DFA. This
+  should remove the last common case that disqualified use of the DFA.
+* An optimization that scanned for suffix literals and then matched the regular
+  expression in reverse was removed because it had worst case quadratic time
+  complexity. It was replaced with a more limited optimization where, given any
+  regex of the form `re$`, it will be matched in reverse from the end of the
+  haystack.
+* [PR #202](https://github.com/rust-lang/regex/pull/202):
+  The inner loop of the DFA was heavily optimized to improve cache locality
+  and reduce the overall number of instructions run on each iteration. This
+  represents the first use of `unsafe` in `regex` (to elide bounds checks).
+* [PR #200](https://github.com/rust-lang/regex/pull/200):
+  Use of the `mempool` crate (which used thread local storage) was replaced
+  with a faster version of a similar API in @Amanieu's `thread_local` crate.
+  It should reduce contention when using a regex from multiple threads
+  simultaneously.
+* PCRE2 JIT benchmarks were added. A benchmark comparison can be found
+  [here](https://gist.github.com/anonymous/14683c01993e91689f7206a18675901b).
+  (Includes a comparison with PCRE1's JIT and Oniguruma.)
+* A bug where word boundaries weren't being matched correctly in the DFA was
+  fixed. This only affected use of `bytes::Regex`.
+* [#160](https://github.com/rust-lang/regex/issues/160):
+  `Captures` now has a `Debug` impl.
diff --git a/vendor/regex-1.4.6/Cargo.lock b/vendor/regex-1.4.6/Cargo.lock
new file mode 100644 (file)
index 0000000..1921931
--- /dev/null
@@ -0,0 +1,98 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b476ce7103678b0c6d3d395dbbae31d48ff910bd28be979ba5d48c6351131d0d"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "getrandom"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.80"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
+
+[[package]]
+name = "memchr"
+version = "2.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
+
+[[package]]
+name = "quickcheck"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
+dependencies = [
+ "rand",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "regex"
+version = "1.4.6"
+dependencies = [
+ "aho-corasick",
+ "lazy_static",
+ "memchr",
+ "quickcheck",
+ "rand",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
+
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
diff --git a/vendor/regex-1.4.6/Cargo.toml b/vendor/regex-1.4.6/Cargo.toml
new file mode 100644 (file)
index 0000000..bc4e58f
--- /dev/null
@@ -0,0 +1,115 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "regex"
+version = "1.4.6"
+authors = ["The Rust Project Developers"]
+exclude = ["/scripts/*", "/.github/*"]
+autotests = false
+description = "An implementation of regular expressions for Rust. This implementation uses\nfinite automata and guarantees linear time matching on all inputs.\n"
+homepage = "https://github.com/rust-lang/regex"
+documentation = "https://docs.rs/regex"
+readme = "README.md"
+categories = ["text-processing"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/rust-lang/regex"
+[profile.bench]
+debug = true
+
+[profile.release]
+debug = true
+
+[profile.test]
+debug = true
+
+[lib]
+doctest = false
+bench = false
+
+[[test]]
+name = "default"
+path = "tests/test_default.rs"
+
+[[test]]
+name = "default-bytes"
+path = "tests/test_default_bytes.rs"
+
+[[test]]
+name = "nfa"
+path = "tests/test_nfa.rs"
+
+[[test]]
+name = "nfa-utf8bytes"
+path = "tests/test_nfa_utf8bytes.rs"
+
+[[test]]
+name = "nfa-bytes"
+path = "tests/test_nfa_bytes.rs"
+
+[[test]]
+name = "backtrack"
+path = "tests/test_backtrack.rs"
+
+[[test]]
+name = "backtrack-utf8bytes"
+path = "tests/test_backtrack_utf8bytes.rs"
+
+[[test]]
+name = "backtrack-bytes"
+path = "tests/test_backtrack_bytes.rs"
+
+[[test]]
+name = "crates-regex"
+path = "tests/test_crates_regex.rs"
+[dependencies.aho-corasick]
+version = "0.7.6"
+optional = true
+
+[dependencies.memchr]
+version = "2.2.1"
+optional = true
+
+[dependencies.regex-syntax]
+version = "0.6.22"
+default-features = false
+[dev-dependencies.lazy_static]
+version = "1"
+
+[dev-dependencies.quickcheck]
+version = "1.0.3"
+default-features = false
+
+[dev-dependencies.rand]
+version = "0.8.3"
+features = ["getrandom", "small_rng"]
+default-features = false
+
+[features]
+default = ["std", "perf", "unicode", "regex-syntax/default"]
+pattern = []
+perf = ["perf-cache", "perf-dfa", "perf-inline", "perf-literal"]
+perf-cache = []
+perf-dfa = []
+perf-inline = []
+perf-literal = ["aho-corasick", "memchr"]
+std = []
+unicode = ["unicode-age", "unicode-bool", "unicode-case", "unicode-gencat", "unicode-perl", "unicode-script", "unicode-segment", "regex-syntax/unicode"]
+unicode-age = ["regex-syntax/unicode-age"]
+unicode-bool = ["regex-syntax/unicode-bool"]
+unicode-case = ["regex-syntax/unicode-case"]
+unicode-gencat = ["regex-syntax/unicode-gencat"]
+unicode-perl = ["regex-syntax/unicode-perl"]
+unicode-script = ["regex-syntax/unicode-script"]
+unicode-segment = ["regex-syntax/unicode-segment"]
+unstable = ["pattern"]
+use_std = ["std"]
diff --git a/vendor/regex-1.4.6/HACKING.md b/vendor/regex-1.4.6/HACKING.md
new file mode 100644 (file)
index 0000000..34af5b5
--- /dev/null
@@ -0,0 +1,341 @@
+Your friendly guide to hacking and navigating the regex library.
+
+This guide assumes familiarity with Rust and Cargo, and at least a perusal of
+the user facing documentation for this crate.
+
+If you're looking for background on the implementation in this library, then
+you can do no better than Russ Cox's article series on implementing regular
+expressions using finite automata: https://swtch.com/~rsc/regexp/
+
+
+## Architecture overview
+
+As you probably already know, this library executes regular expressions using
+finite automata. In particular, a design goal is to make searching linear
+with respect to both the regular expression and the text being searched.
+Meeting that design goal on its own is not so hard and can be done with an
+implementation of the Pike VM (similar to Thompson's construction, but supports
+capturing groups), as described in: https://swtch.com/~rsc/regexp/regexp2.html
+--- This library contains such an implementation in src/pikevm.rs.
+
+Making it fast is harder. One of the key problems with the Pike VM is that it
+can be in more than one state at any point in time, and must shuffle capture
+positions between them. The Pike VM also spends a lot of time following the
+same epsilon transitions over and over again. We can employ one trick to
+speed up the Pike VM: extract one or more literal prefixes from the regular
+expression and execute specialized code to quickly find matches of those
+prefixes in the search text. The Pike VM can then be avoided for most the
+search, and instead only executed when a prefix is found. The code to find
+prefixes is in the regex-syntax crate (in this repository). The code to search
+for literals is in src/literals.rs. When more than one literal prefix is found,
+we fall back to an Aho-Corasick DFA using the aho-corasick crate. For one
+literal, we use a variant of the Boyer-Moore algorithm. Both Aho-Corasick and
+Boyer-Moore use `memchr` when appropriate. The Boyer-Moore variant in this
+library also uses elementary frequency analysis to choose the right byte to run
+`memchr` with.
+
+Of course, detecting prefix literals can only take us so far. Not all regular
+expressions have literal prefixes. To remedy this, we try another approach
+to executing the Pike VM: backtracking, whose implementation can be found in
+src/backtrack.rs. One reason why backtracking can be faster is that it avoids
+excessive shuffling of capture groups. Of course, backtracking is susceptible
+to exponential runtimes, so we keep track of every state we've visited to make
+sure we never visit it again. This guarantees linear time execution, but we
+pay for it with the memory required to track visited states. Because of the
+memory requirement, we only use this engine on small search strings *and* small
+regular expressions.
+
+Lastly, the real workhorse of this library is the "lazy" DFA in src/dfa.rs.
+It is distinct from the Pike VM in that the DFA is explicitly represented in
+memory and is only ever in one state at a time. It is said to be "lazy" because
+the DFA is computed as text is searched, where each byte in the search text
+results in at most one new DFA state. It is made fast by caching states. DFAs
+are susceptible to exponential state blow up (where the worst case is computing
+a new state for every input byte, regardless of what's in the state cache). To
+avoid using a lot of memory, the lazy DFA uses a bounded cache. Once the cache
+is full, it is wiped and state computation starts over again. If the cache is
+wiped too frequently, then the DFA gives up and searching falls back to one of
+the aforementioned algorithms.
+
+All of the above matching engines expose precisely the same matching semantics.
+This is indeed tested. (See the section below about testing.)
+
+The following sub-sections describe the rest of the library and how each of the
+matching engines are actually used.
+
+### Parsing
+
+Regular expressions are parsed using the regex-syntax crate, which is
+maintained in this repository. The regex-syntax crate defines an abstract
+syntax and provides very detailed error messages when a parse error is
+encountered. Parsing is done in a separate crate so that others may benefit
+from its existence, and because it is relatively divorced from the rest of the
+regex library.
+
+The regex-syntax crate also provides sophisticated support for extracting
+prefix and suffix literals from regular expressions.
+
+### Compilation
+
+The compiler is in src/compile.rs. The input to the compiler is some abstract
+syntax for a regular expression and the output is a sequence of opcodes that
+matching engines use to execute a search. (One can think of matching engines as
+mini virtual machines.) The sequence of opcodes is a particular encoding of a
+non-deterministic finite automaton. In particular, the opcodes explicitly rely
+on epsilon transitions.
+
+Consider a simple regular expression like `a|b`. Its compiled form looks like
+this:
+
+    000 Save(0)
+    001 Split(2, 3)
+    002 'a' (goto: 4)
+    003 'b'
+    004 Save(1)
+    005 Match
+
+The first column is the instruction pointer and the second column is the
+instruction. Save instructions indicate that the current position in the input
+should be stored in a captured location. Split instructions represent a binary
+branch in the program (i.e., epsilon transitions). The instructions `'a'` and
+`'b'` indicate that the literal bytes `'a'` or `'b'` should match.
+
+In older versions of this library, the compilation looked like this:
+
+    000 Save(0)
+    001 Split(2, 3)
+    002 'a'
+    003 Jump(5)
+    004 'b'
+    005 Save(1)
+    006 Match
+
+In particular, empty instructions that merely served to move execution from one
+point in the program to another were removed. Instead, every instruction has a
+`goto` pointer embedded into it. This resulted in a small performance boost for
+the Pike VM, because it was one fewer epsilon transition that it had to follow.
+
+There exist more instructions and they are defined and documented in
+src/prog.rs.
+
+Compilation has several knobs and a few unfortunately complicated invariants.
+Namely, the output of compilation can be one of two types of programs: a
+program that executes on Unicode scalar values or a program that executes
+on raw bytes. In the former case, the matching engine is responsible for
+performing UTF-8 decoding and executing instructions using Unicode codepoints.
+In the latter case, the program handles UTF-8 decoding implicitly, so that the
+matching engine can execute on raw bytes. All matching engines can execute
+either Unicode or byte based programs except for the lazy DFA, which requires
+byte based programs. In general, both representations were kept because (1) the
+lazy DFA requires byte based programs so that states can be encoded in a memory
+efficient manner and (2) the Pike VM benefits greatly from inlining Unicode
+character classes into fewer instructions as it results in fewer epsilon
+transitions.
+
+N.B. UTF-8 decoding is built into the compiled program by making use of the
+utf8-ranges crate. The compiler in this library factors out common suffixes to
+reduce the size of huge character classes (e.g., `\pL`).
+
+A regrettable consequence of this split in instruction sets is we generally
+need to compile two programs; one for NFA execution and one for the lazy DFA.
+
+In fact, it is worse than that: the lazy DFA is not capable of finding the
+starting location of a match in a single scan, and must instead execute a
+backwards search after finding the end location. To execute a backwards search,
+we must have compiled the regular expression *in reverse*.
+
+This means that every compilation of a regular expression generally results in
+three distinct programs. It would be possible to lazily compile the Unicode
+program, since it is never needed if (1) the regular expression uses no word
+boundary assertions and (2) the caller never asks for sub-capture locations.
+
+### Execution
+
+At the time of writing, there are four matching engines in this library:
+
+1. The Pike VM (supports captures).
+2. Bounded backtracking (supports captures).
+3. Literal substring or multi-substring search.
+4. Lazy DFA (no support for Unicode word boundary assertions).
+
+Only the first two matching engines are capable of executing every regular
+expression program. They also happen to be the slowest, which means we need
+some logic that (1) knows various facts about the regular expression and (2)
+knows what the caller wants. Using this information, we can determine which
+engine (or engines) to use.
+
+The logic for choosing which engine to execute is in src/exec.rs and is
+documented on the Exec type. Exec values contain regular expression Programs
+(defined in src/prog.rs), which contain all the necessary tidbits for actually
+executing a regular expression on search text.
+
+For the most part, the execution logic is straight-forward and follows the
+limitations of each engine described above pretty faithfully. The hairiest
+part of src/exec.rs by far is the execution of the lazy DFA, since it requires
+a forwards and backwards search, and then falls back to either the Pike VM or
+backtracking if the caller requested capture locations.
+
+The Exec type also contains mutable scratch space for each type of matching
+engine. This scratch space is used during search (for example, for the lazy
+DFA, it contains compiled states that are reused on subsequent searches).
+
+### Programs
+
+A regular expression program is essentially a sequence of opcodes produced by
+the compiler plus various facts about the regular expression (such as whether
+it is anchored, its capture names, etc.).
+
+### The regex! macro
+
+The `regex!` macro no longer exists. It was developed in a bygone era as a
+compiler plugin during the infancy of the regex crate. Back then, then only
+matching engine in the crate was the Pike VM. The `regex!` macro was, itself,
+also a Pike VM. The only advantages it offered over the dynamic Pike VM that
+was built at runtime were the following:
+
+  1. Syntax checking was done at compile time. Your Rust program wouldn't
+     compile if your regex didn't compile.
+  2. Reduction of overhead that was proportional to the size of the regex.
+     For the most part, this overhead consisted of heap allocation, which
+     was nearly eliminated in the compiler plugin.
+
+The main takeaway here is that the compiler plugin was a marginally faster
+version of a slow regex engine. As the regex crate evolved, it grew other regex
+engines (DFA, bounded backtracker) and sophisticated literal optimizations.
+The regex macro didn't keep pace, and it therefore became (dramatically) slower
+than the dynamic engines. The only reason left to use it was for the compile
+time guarantee that your regex is correct. Fortunately, Clippy (the Rust lint
+tool) has a lint that checks your regular expression validity, which mostly
+replaces that use case.
+
+Additionally, the regex compiler plugin stopped receiving maintenance. Nobody
+complained. At that point, it seemed prudent to just remove it.
+
+Will a compiler plugin be brought back? The future is murky, but there is
+definitely an opportunity there to build something that is faster than the
+dynamic engines in some cases. But it will be challenging! As of now, there
+are no plans to work on this.
+
+
+## Testing
+
+A key aspect of any mature regex library is its test suite. A subset of the
+tests in this library come from Glenn Fowler's AT&T test suite (its online
+presence seems gone at the time of writing). The source of the test suite is
+located in src/testdata. The scripts/regex-match-tests.py takes the test suite
+in src/testdata and generates tests/matches.rs.
+
+There are also many other manually crafted tests and regression tests in
+tests/tests.rs. Some of these tests were taken from RE2.
+
+The biggest source of complexity in the tests is related to answering this
+question: how can we reuse the tests to check all of our matching engines? One
+approach would have been to encode every test into some kind of format (like
+the AT&T test suite) and code generate tests for each matching engine. The
+approach we use in this library is to create a Cargo.toml entry point for each
+matching engine we want to test. The entry points are:
+
+* `tests/test_default.rs` - tests `Regex::new`
+* `tests/test_default_bytes.rs` - tests `bytes::Regex::new`
+* `tests/test_nfa.rs` - tests `Regex::new`, forced to use the NFA
+  algorithm on every regex.
+* `tests/test_nfa_bytes.rs` - tests `Regex::new`, forced to use the NFA
+  algorithm on every regex and use *arbitrary* byte based programs.
+* `tests/test_nfa_utf8bytes.rs` - tests `Regex::new`, forced to use the NFA
+  algorithm on every regex and use *UTF-8* byte based programs.
+* `tests/test_backtrack.rs` - tests `Regex::new`, forced to use
+  backtracking on every regex.
+* `tests/test_backtrack_bytes.rs` - tests `Regex::new`, forced to use
+  backtracking on every regex and use *arbitrary* byte based programs.
+* `tests/test_backtrack_utf8bytes.rs` - tests `Regex::new`, forced to use
+  backtracking on every regex and use *UTF-8* byte based programs.
+* `tests/test_crates_regex.rs` - tests to make sure that all of the
+  backends behave in the same way against a number of quickcheck
+  generated random inputs. These tests need to be enabled through
+  the `RUST_REGEX_RANDOM_TEST` environment variable (see
+  below).
+
+The lazy DFA and pure literal engines are absent from this list because
+they cannot be used on every regular expression. Instead, we rely on
+`tests/test_dynamic.rs` to test the lazy DFA and literal engines when possible.
+
+Since the tests are repeated several times, and because `cargo test` runs all
+entry points, it can take a while to compile everything. To reduce compile
+times slightly, try using `cargo test --test default`, which will only use the
+`tests/test_default.rs` entry point.
+
+The random testing takes quite a while, so it is not enabled by default.
+In order to run the random testing you can set the
+`RUST_REGEX_RANDOM_TEST` environment variable to anything before
+invoking `cargo test`. Note that this variable is inspected at compile
+time, so if the tests don't seem to be running, you may need to run
+`cargo clean`.
+
+## Benchmarking
+
+The benchmarking in this crate is made up of many micro-benchmarks. Currently,
+there are two primary sets of benchmarks: the benchmarks that were adopted
+at this library's inception (in `bench/src/misc.rs`) and a newer set of
+benchmarks meant to test various optimizations. Specifically, the latter set
+contain some analysis and are in `bench/src/sherlock.rs`. Also, the latter
+set are all executed on the same lengthy input whereas the former benchmarks
+are executed on strings of varying length.
+
+There is also a smattering of benchmarks for parsing and compilation.
+
+Benchmarks are in a separate crate so that its dependencies can be managed
+separately from the main regex crate.
+
+Benchmarking follows a similarly wonky setup as tests. There are multiple entry
+points:
+
+* `bench_rust.rs` - benchmarks `Regex::new`
+* `bench_rust_bytes.rs` benchmarks `bytes::Regex::new`
+* `bench_pcre.rs` - benchmarks PCRE
+* `bench_onig.rs` - benchmarks Oniguruma
+
+The PCRE and Oniguruma benchmarks exist as a comparison point to a mature
+regular expression library. In general, this regex library compares favorably
+(there are even a few benchmarks that PCRE simply runs too slowly on or
+outright can't execute at all). I would love to add other regular expression
+library benchmarks (especially RE2).
+
+If you're hacking on one of the matching engines and just want to see
+benchmarks, then all you need to run is:
+
+    $ (cd bench && ./run rust)
+
+If you want to compare your results with older benchmarks, then try:
+
+    $ (cd bench && ./run rust | tee old)
+    $ ... make it faster
+    $ (cd bench && ./run rust | tee new)
+    $ cargo benchcmp old new --improvements
+
+The `cargo-benchcmp` utility is available here:
+https://github.com/BurntSushi/cargo-benchcmp
+
+The `./bench/run` utility can run benchmarks for PCRE and Oniguruma too. See
+`./bench/bench --help`.
+
+## Dev Docs
+
+When digging your teeth into the codebase for the first time, the
+crate documentation can be a great resource. By default `rustdoc`
+will strip out all documentation of private crate members in an
+effort to help consumers of the crate focus on the *interface*
+without having to concern themselves with the *implementation*.
+Normally this is a great thing, but if you want to start hacking
+on regex internals it is not what you want. Many of the private members
+of this crate are well documented with rustdoc style comments, and
+it would be a shame to miss out on the opportunity that presents.
+You can generate the private docs with:
+
+```
+$ rustdoc --crate-name docs src/lib.rs -o target/doc -L target/debug/deps --no-defaults --passes collapse-docs --passes unindent-comments
+```
+
+Then just point your browser at `target/doc/regex/index.html`.
+
+See https://github.com/rust-lang/rust/issues/15347 for more info
+about generating developer docs for internal use.
diff --git a/vendor/regex-1.4.6/LICENSE-APACHE b/vendor/regex-1.4.6/LICENSE-APACHE
new file mode 100644 (file)
index 0000000..16fe87b
--- /dev/null
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/vendor/regex-1.4.6/LICENSE-MIT b/vendor/regex-1.4.6/LICENSE-MIT
new file mode 100644 (file)
index 0000000..39d4bdb
--- /dev/null
@@ -0,0 +1,25 @@
+Copyright (c) 2014 The Rust Project Developers
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/vendor/regex-1.4.6/PERFORMANCE.md b/vendor/regex-1.4.6/PERFORMANCE.md
new file mode 100644 (file)
index 0000000..b4aeb89
--- /dev/null
@@ -0,0 +1,279 @@
+Your friendly guide to understanding the performance characteristics of this
+crate.
+
+This guide assumes some familiarity with the public API of this crate, which
+can be found here: https://docs.rs/regex
+
+## Theory vs. Practice
+
+One of the design goals of this crate is to provide worst case linear time
+behavior with respect to the text searched using finite state automata. This
+means that, *in theory*, the performance of this crate is much better than most
+regex implementations, which typically use backtracking which has worst case
+exponential time.
+
+For example, try opening a Python interpreter and typing this:
+
+    >>> import re
+    >>> re.search('(a*)*c', 'a' * 30).span()
+
+I'll wait.
+
+At some point, you'll figure out that it won't terminate any time soon. ^C it.
+
+The promise of this crate is that *this pathological behavior can't happen*.
+
+With that said, just because we have protected ourselves against worst case
+exponential behavior doesn't mean we are immune from large constant factors
+or places where the current regex engine isn't quite optimal. This guide will
+detail those cases and provide guidance on how to avoid them, among other
+bits of general advice.
+
+## Thou Shalt Not Compile Regular Expressions In A Loop
+
+**Advice**: Use `lazy_static` to amortize the cost of `Regex` compilation.
+
+Don't do it unless you really don't mind paying for it. Compiling a regular
+expression in this crate is quite expensive. It is conceivable that it may get
+faster some day, but I wouldn't hold out hope for, say, an order of magnitude
+improvement. In particular, compilation can take any where from a few dozen
+microseconds to a few dozen milliseconds. Yes, milliseconds. Unicode character
+classes, in particular, have the largest impact on compilation performance. At
+the time of writing, for example, `\pL{100}` takes around 44ms to compile. This
+is because `\pL` corresponds to every letter in Unicode and compilation must
+turn it into a proper automaton that decodes a subset of UTF-8 which
+corresponds to those letters. Compilation also spends some cycles shrinking the
+size of the automaton.
+
+This means that in order to realize efficient regex matching, one must
+*amortize the cost of compilation*. Trivially, if a call to `is_match` is
+inside a loop, then make sure your call to `Regex::new` is *outside* that loop.
+
+In many programming languages, regular expressions can be conveniently defined
+and compiled in a global scope, and code can reach out and use them as if
+they were global static variables. In Rust, there is really no concept of
+life-before-main, and therefore, one cannot utter this:
+
+    static MY_REGEX: Regex = Regex::new("...").unwrap();
+
+Unfortunately, this would seem to imply that one must pass `Regex` objects
+around to everywhere they are used, which can be especially painful depending
+on how your program is structured. Thankfully, the
+[`lazy_static`](https://crates.io/crates/lazy_static)
+crate provides an answer that works well:
+
+    #[macro_use] extern crate lazy_static;
+    extern crate regex;
+
+    use regex::Regex;
+
+    fn some_helper_function(text: &str) -> bool {
+        lazy_static! {
+            static ref MY_REGEX: Regex = Regex::new("...").unwrap();
+        }
+        MY_REGEX.is_match(text)
+    }
+
+In other words, the `lazy_static!` macro enables us to define a `Regex` *as if*
+it were a global static value. What is actually happening under the covers is
+that the code inside the macro (i.e., `Regex::new(...)`) is run on *first use*
+of `MY_REGEX` via a `Deref` impl. The implementation is admittedly magical, but
+it's self contained and everything works exactly as you expect. In particular,
+`MY_REGEX` can be used from multiple threads without wrapping it in an `Arc` or
+a `Mutex`. On that note...
+
+## Using a regex from multiple threads
+
+**Advice**: The performance impact from using a `Regex` from multiple threads
+is likely negligible. If necessary, clone the `Regex` so that each thread gets
+its own copy. Cloning a regex does not incur any additional memory overhead
+than what would be used by using a `Regex` from multiple threads
+simultaneously. *Its only cost is ergonomics.*
+
+It is supported and encouraged to define your regexes using `lazy_static!` as
+if they were global static values, and then use them to search text from
+multiple threads simultaneously.
+
+One might imagine that this is possible because a `Regex` represents a
+*compiled* program, so that any allocation or mutation is already done, and is
+therefore read-only. Unfortunately, this is not true. Each type of search
+strategy in this crate requires some kind of mutable scratch space to use
+*during search*. For example, when executing a DFA, its states are computed
+lazily and reused on subsequent searches. Those states go into that mutable
+scratch space.
+
+The mutable scratch space is an implementation detail, and in general, its
+mutation should not be observable from users of this crate. Therefore, it uses
+interior mutability. This implies that `Regex` can either only be used from one
+thread, or it must do some sort of synchronization. Either choice is
+reasonable, but this crate chooses the latter, in particular because it is
+ergonomic and makes use with `lazy_static!` straight forward.
+
+Synchronization implies *some* amount of overhead. When a `Regex` is used from
+a single thread, this overhead is negligible. When a `Regex` is used from
+multiple threads simultaneously, it is possible for the overhead of
+synchronization from contention to impact performance. The specific cases where
+contention may happen is if you are calling any of these methods repeatedly
+from multiple threads simultaneously:
+
+* shortest_match
+* is_match
+* find
+* captures
+
+In particular, every invocation of one of these methods must synchronize with
+other threads to retrieve its mutable scratch space before searching can start.
+If, however, you are using one of these methods:
+
+* find_iter
+* captures_iter
+
+Then you may not suffer from contention since the cost of synchronization is
+amortized on *construction of the iterator*. That is, the mutable scratch space
+is obtained when the iterator is created and retained throughout its lifetime.
+
+## Only ask for what you need
+
+**Advice**: Prefer in this order: `is_match`, `find`, `captures`.
+
+There are three primary search methods on a `Regex`:
+
+* is_match
+* find
+* captures
+
+In general, these are ordered from fastest to slowest.
+
+`is_match` is fastest because it doesn't actually need to find the start or the
+end of the leftmost-first match. It can quit immediately after it knows there
+is a match. For example, given the regex `a+` and the haystack, `aaaaa`, the
+search will quit after examing the first byte.
+
+In constrast, `find` must return both the start and end location of the
+leftmost-first match. It can use the DFA matcher for this, but must run it
+forwards once to find the end of the match *and then run it backwards* to find
+the start of the match. The two scans and the cost of finding the real end of
+the leftmost-first match make this more expensive than `is_match`.
+
+`captures` is the most expensive of them all because it must do what `find`
+does, and then run either the bounded backtracker or the Pike VM to fill in the
+capture group locations. Both of these are simulations of an NFA, which must
+spend a lot of time shuffling states around. The DFA limits the performance hit
+somewhat by restricting the amount of text that must be searched via an NFA
+simulation.
+
+One other method not mentioned is `shortest_match`. This method has precisely
+the same performance characteristics as `is_match`, except it will return the
+end location of when it discovered a match. For example, given the regex `a+`
+and the haystack `aaaaa`, `shortest_match` may return `1` as opposed to `5`,
+the latter of which being the correct end location of the leftmost-first match.
+
+## Literals in your regex may make it faster
+
+**Advice**: Literals can reduce the work that the regex engine needs to do. Use
+them if you can, especially as prefixes.
+
+In particular, if your regex starts with a prefix literal, the prefix is
+quickly searched before entering the (much slower) regex engine. For example,
+given the regex `foo\w+`, the literal `foo` will be searched for using
+Boyer-Moore. If there's no match, then no regex engine is ever used. Only when
+there's a match is the regex engine invoked at the location of the match, which
+effectively permits the regex engine to skip large portions of a haystack.
+If a regex is comprised entirely of literals (possibly more than one), then
+it's possible that the regex engine can be avoided entirely even when there's a
+match.
+
+When one literal is found, Boyer-Moore is used. When multiple literals are
+found, then an optimized version of Aho-Corasick is used.
+
+This optimization is in particular extended quite a bit in this crate. Here are
+a few examples of regexes that get literal prefixes detected:
+
+* `(foo|bar)` detects `foo` and `bar`
+* `(a|b)c` detects `ac` and `bc`
+* `[ab]foo[yz]` detects `afooy`, `afooz`, `bfooy` and `bfooz`
+* `a?b` detects `a` and `b`
+* `a*b` detects `a` and `b`
+* `(ab){3,6}` detects `ababab`
+
+Literals in anchored regexes can also be used for detecting non-matches very
+quickly. For example, `^foo\w+` and `\w+foo$` may be able to detect a non-match
+just by examing the first (or last) three bytes of the haystack.
+
+## Unicode word boundaries may prevent the DFA from being used
+
+**Advice**: In most cases, `\b` should work well. If not, use `(?-u:\b)`
+instead of `\b` if you care about consistent performance more than correctness.
+
+It's a sad state of the current implementation. At the moment, the DFA will try
+to interpret Unicode word boundaries as if they were ASCII word boundaries.
+If the DFA comes across any non-ASCII byte, it will quit and fall back to an
+alternative matching engine that can handle Unicode word boundaries correctly.
+The alternate matching engine is generally quite a bit slower (perhaps by an
+order of magnitude). If necessary, this can be ameliorated in two ways.
+
+The first way is to add some number of literal prefixes to your regular
+expression. Even though the DFA may not be used, specialized routines will
+still kick in to find prefix literals quickly, which limits how much work the
+NFA simulation will need to do.
+
+The second way is to give up on Unicode and use an ASCII word boundary instead.
+One can use an ASCII word boundary by disabling Unicode support. That is,
+instead of using `\b`, use `(?-u:\b)`.  Namely, given the regex `\b.+\b`, it
+can be transformed into a regex that uses the DFA with `(?-u:\b).+(?-u:\b)`. It
+is important to limit the scope of disabling the `u` flag, since it might lead
+to a syntax error if the regex could match arbitrary bytes. For example, if one
+wrote `(?-u)\b.+\b`, then a syntax error would be returned because `.` matches
+any *byte* when the Unicode flag is disabled.
+
+The second way isn't appreciably different than just using a Unicode word
+boundary in the first place, since the DFA will speculatively interpret it as
+an ASCII word boundary anyway. The key difference is that if an ASCII word
+boundary is used explicitly, then the DFA won't quit in the presence of
+non-ASCII UTF-8 bytes. This results in giving up correctness in exchange for
+more consistent performance.
+
+N.B. When using `bytes::Regex`, Unicode support is disabled by default, so one
+can simply write `\b` to get an ASCII word boundary.
+
+## Excessive counting can lead to exponential state blow up in the DFA
+
+**Advice**: Don't write regexes that cause DFA state blow up if you care about
+match performance.
+
+Wait, didn't I say that this crate guards against exponential worst cases?
+Well, it turns out that the process of converting an NFA to a DFA can lead to
+an exponential blow up in the number of states. This crate specifically guards
+against exponential blow up by doing two things:
+
+1. The DFA is computed lazily. That is, a state in the DFA only exists in
+   memory if it is visited. In particular, the lazy DFA guarantees that *at
+   most* one state is created for every byte of input. This, on its own,
+   guarantees linear time complexity.
+2. Of course, creating a new state for *every* byte of input means that search
+   will go incredibly slow because of very large constant factors. On top of
+   that, creating a state for every byte in a large haystack could result in
+   exorbitant memory usage. To ameliorate this, the DFA bounds the number of
+   states it can store. Once it reaches its limit, it flushes its cache. This
+   prevents reuse of states that it already computed. If the cache is flushed
+   too frequently, then the DFA will give up and execution will fall back to
+   one of the NFA simulations.
+
+In effect, this crate will detect exponential state blow up and fall back to
+a search routine with fixed memory requirements. This does, however, mean that
+searching will be much slower than one might expect. Regexes that rely on
+counting in particular are strong aggravators of this behavior. For example,
+matching `[01]*1[01]{20}$` against a random sequence of `0`s and `1`s.
+
+In the future, it may be possible to increase the bound that the DFA uses,
+which would allow the caller to choose how much memory they're willing to
+spend.
+
+## Resist the temptation to "optimize" regexes
+
+**Advice**: This ain't a backtracking engine.
+
+An entire book was written on how to optimize Perl-style regular expressions.
+Most of those techniques are not applicable for this library. For example,
+there is no problem with using non-greedy matching or having lots of
+alternations in your regex.
diff --git a/vendor/regex-1.4.6/README.md b/vendor/regex-1.4.6/README.md
new file mode 100644 (file)
index 0000000..f7a2554
--- /dev/null
@@ -0,0 +1,256 @@
+regex
+=====
+A Rust library for parsing, compiling, and executing regular expressions. Its
+syntax is similar to Perl-style regular expressions, but lacks a few features
+like look around and backreferences. In exchange, all searches execute in
+linear time with respect to the size of the regular expression and search text.
+Much of the syntax and implementation is inspired
+by [RE2](https://github.com/google/re2).
+
+[![Build status](https://github.com/rust-lang/regex/workflows/ci/badge.svg)](https://github.com/rust-lang/regex/actions)
+[![](https://meritbadge.herokuapp.com/regex)](https://crates.io/crates/regex)
+[![Rust](https://img.shields.io/badge/rust-1.28.0%2B-blue.svg?maxAge=3600)](https://github.com/rust-lang/regex)
+
+### Documentation
+
+[Module documentation with examples](https://docs.rs/regex).
+The module documentation also includes a comprehensive description of the
+syntax supported.
+
+Documentation with examples for the various matching functions and iterators
+can be found on the
+[`Regex` type](https://docs.rs/regex/*/regex/struct.Regex.html).
+
+### Usage
+
+Add this to your `Cargo.toml`:
+
+```toml
+[dependencies]
+regex = "1"
+```
+
+and this to your crate root (if you're using Rust 2015):
+
+```rust
+extern crate regex;
+```
+
+Here's a simple example that matches a date in YYYY-MM-DD format and prints the
+year, month and day:
+
+```rust
+use regex::Regex;
+
+fn main() {
+    let re = Regex::new(r"(?x)
+(?P<year>\d{4})  # the year
+-
+(?P<month>\d{2}) # the month
+-
+(?P<day>\d{2})   # the day
+").unwrap();
+    let caps = re.captures("2010-03-14").unwrap();
+
+    assert_eq!("2010", &caps["year"]);
+    assert_eq!("03", &caps["month"]);
+    assert_eq!("14", &caps["day"]);
+}
+```
+
+If you have lots of dates in text that you'd like to iterate over, then it's
+easy to adapt the above example with an iterator:
+
+```rust
+use regex::Regex;
+
+const TO_SEARCH: &'static str = "
+On 2010-03-14, foo happened. On 2014-10-14, bar happened.
+";
+
+fn main() {
+    let re = Regex::new(r"(\d{4})-(\d{2})-(\d{2})").unwrap();
+
+    for caps in re.captures_iter(TO_SEARCH) {
+        // Note that all of the unwraps are actually OK for this regex
+        // because the only way for the regex to match is if all of the
+        // capture groups match. This is not true in general though!
+        println!("year: {}, month: {}, day: {}",
+                 caps.get(1).unwrap().as_str(),
+                 caps.get(2).unwrap().as_str(),
+                 caps.get(3).unwrap().as_str());
+    }
+}
+```
+
+This example outputs:
+
+```text
+year: 2010, month: 03, day: 14
+year: 2014, month: 10, day: 14
+```
+
+### Usage: Avoid compiling the same regex in a loop
+
+It is an anti-pattern to compile the same regular expression in a loop since
+compilation is typically expensive. (It takes anywhere from a few microseconds
+to a few **milliseconds** depending on the size of the regex.) Not only is
+compilation itself expensive, but this also prevents optimizations that reuse
+allocations internally to the matching engines.
+
+In Rust, it can sometimes be a pain to pass regular expressions around if
+they're used from inside a helper function. Instead, we recommend using the
+[`lazy_static`](https://crates.io/crates/lazy_static) crate to ensure that
+regular expressions are compiled exactly once.
+
+For example:
+
+```rust,ignore
+use regex::Regex;
+
+fn some_helper_function(text: &str) -> bool {
+    lazy_static! {
+        static ref RE: Regex = Regex::new("...").unwrap();
+    }
+    RE.is_match(text)
+}
+```
+
+Specifically, in this example, the regex will be compiled when it is used for
+the first time. On subsequent uses, it will reuse the previous compilation.
+
+### Usage: match regular expressions on `&[u8]`
+
+The main API of this crate (`regex::Regex`) requires the caller to pass a
+`&str` for searching. In Rust, an `&str` is required to be valid UTF-8, which
+means the main API can't be used for searching arbitrary bytes.
+
+To match on arbitrary bytes, use the `regex::bytes::Regex` API. The API
+is identical to the main API, except that it takes an `&[u8]` to search
+on instead of an `&str`. By default, `.` will match any *byte* using
+`regex::bytes::Regex`, while `.` will match any *UTF-8 encoded Unicode scalar
+value* using the main API.
+
+This example shows how to find all null-terminated strings in a slice of bytes:
+
+```rust
+use regex::bytes::Regex;
+
+let re = Regex::new(r"(?P<cstr>[^\x00]+)\x00").unwrap();
+let text = b"foo\x00bar\x00baz\x00";
+
+// Extract all of the strings without the null terminator from each match.
+// The unwrap is OK here since a match requires the `cstr` capture to match.
+let cstrs: Vec<&[u8]> =
+    re.captures_iter(text)
+      .map(|c| c.name("cstr").unwrap().as_bytes())
+      .collect();
+assert_eq!(vec![&b"foo"[..], &b"bar"[..], &b"baz"[..]], cstrs);
+```
+
+Notice here that the `[^\x00]+` will match any *byte* except for `NUL`. When
+using the main API, `[^\x00]+` would instead match any valid UTF-8 sequence
+except for `NUL`.
+
+### Usage: match multiple regular expressions simultaneously
+
+This demonstrates how to use a `RegexSet` to match multiple (possibly
+overlapping) regular expressions in a single scan of the search text:
+
+```rust
+use regex::RegexSet;
+
+let set = RegexSet::new(&[
+    r"\w+",
+    r"\d+",
+    r"\pL+",
+    r"foo",
+    r"bar",
+    r"barfoo",
+    r"foobar",
+]).unwrap();
+
+// Iterate over and collect all of the matches.
+let matches: Vec<_> = set.matches("foobar").into_iter().collect();
+assert_eq!(matches, vec![0, 2, 3, 4, 6]);
+
+// You can also test whether a particular regex matched:
+let matches = set.matches("foobar");
+assert!(!matches.matched(5));
+assert!(matches.matched(6));
+```
+
+### Usage: enable SIMD optimizations
+
+SIMD optimizations are enabled automatically on Rust stable 1.27 and newer.
+For nightly versions of Rust, this requires a recent version with the SIMD
+features stabilized.
+
+
+### Usage: a regular expression parser
+
+This repository contains a crate that provides a well tested regular expression
+parser, abstract syntax and a high-level intermediate representation for
+convenient analysis. It provides no facilities for compilation or execution.
+This may be useful if you're implementing your own regex engine or otherwise
+need to do analysis on the syntax of a regular expression. It is otherwise not
+recommended for general use.
+
+[Documentation `regex-syntax`.](https://docs.rs/regex-syntax)
+
+
+### Crate features
+
+This crate comes with several features that permit tweaking the trade off
+between binary size, compilation time and runtime performance. Users of this
+crate can selectively disable Unicode tables, or choose from a variety of
+optimizations performed by this crate to disable.
+
+When all of these features are disabled, runtime match performance may be much
+worse, but if you're matching on short strings, or if high performance isn't
+necessary, then such a configuration is perfectly serviceable. To disable
+all such features, use the following `Cargo.toml` dependency configuration:
+
+```toml
+[dependencies.regex]
+version = "1.3"
+default-features = false
+# regex currently requires the standard library, you must re-enable it.
+features = ["std"]
+```
+
+This will reduce the dependency tree of `regex` down to a single crate
+(`regex-syntax`).
+
+The full set of features one can disable are
+[in the "Crate features" section of the documentation](https://docs.rs/regex/*/#crate-features).
+
+
+### Minimum Rust version policy
+
+This crate's minimum supported `rustc` version is `1.28.0`.
+
+The current **tentative** policy is that the minimum Rust version required
+to use this crate can be increased in minor version updates. For example, if
+regex 1.0 requires Rust 1.20.0, then regex 1.0.z for all values of `z` will
+also require Rust 1.20.0 or newer. However, regex 1.y for `y > 0` may require a
+newer minimum version of Rust.
+
+In general, this crate will be conservative with respect to the minimum
+supported version of Rust.
+
+
+### License
+
+This project is licensed under either of
+
+ * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
+   https://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or
+   https://opensource.org/licenses/MIT)
+
+at your option.
+
+The data in `regex-syntax/src/unicode_tables/` is licensed under the Unicode
+License Agreement
+([LICENSE-UNICODE](https://www.unicode.org/copyright.html#License)).
diff --git a/vendor/regex-1.4.6/UNICODE.md b/vendor/regex-1.4.6/UNICODE.md
new file mode 100644 (file)
index 0000000..df7d21e
--- /dev/null
@@ -0,0 +1,259 @@
+# Unicode conformance
+
+This document describes the regex crate's conformance to Unicode's
+[UTS#18](https://unicode.org/reports/tr18/)
+report, which lays out 3 levels of support: Basic, Extended and Tailored.
+
+Full support for Level 1 ("Basic Unicode Support") is provided with two
+exceptions:
+
+1. Line boundaries are not Unicode aware. Namely, only the `\n`
+   (`END OF LINE`) character is recognized as a line boundary.
+2. The compatibility properties specified by
+   [RL1.2a](https://unicode.org/reports/tr18/#RL1.2a)
+   are ASCII-only definitions.
+
+Little to no support is provided for either Level 2 or Level 3. For the most
+part, this is because the features are either complex/hard to implement, or at
+the very least, very difficult to implement without sacrificing performance.
+For example, tackling canonical equivalence such that matching worked as one
+would expect regardless of normalization form would be a significant
+undertaking. This is at least partially a result of the fact that this regex
+engine is based on finite automata, which admits less flexibility normally
+associated with backtracking implementations.
+
+
+## RL1.1 Hex Notation
+
+[UTS#18 RL1.1](https://unicode.org/reports/tr18/#Hex_notation)
+
+Hex Notation refers to the ability to specify a Unicode code point in a regular
+expression via its hexadecimal code point representation. This is useful in
+environments that have poor Unicode font rendering or if you need to express a
+code point that is not normally displayable. All forms of hexadecimal notation
+are supported
+
+    \x7F        hex character code (exactly two digits)
+    \x{10FFFF}  any hex character code corresponding to a Unicode code point
+    \u007F      hex character code (exactly four digits)
+    \u{7F}      any hex character code corresponding to a Unicode code point
+    \U0000007F  hex character code (exactly eight digits)
+    \U{7F}      any hex character code corresponding to a Unicode code point
+
+Briefly, the `\x{...}`, `\u{...}` and `\U{...}` are all exactly equivalent ways
+of expressing hexadecimal code points. Any number of digits can be written
+within the brackets. In contrast, `\xNN`, `\uNNNN`, `\UNNNNNNNN` are all
+fixed-width variants of the same idea.
+
+Note that when Unicode mode is disabled, any non-ASCII Unicode codepoint is
+banned. Additionally, the `\xNN` syntax represents arbitrary bytes when Unicode
+mode is disabled. That is, the regex `\xFF` matches the Unicode codepoint
+U+00FF (encoded as `\xC3\xBF` in UTF-8) while the regex `(?-u)\xFF` matches
+the literal byte `\xFF`.
+
+
+## RL1.2 Properties
+
+[UTS#18 RL1.2](https://unicode.org/reports/tr18/#Categories)
+
+Full support for Unicode property syntax is provided. Unicode properties
+provide a convenient way to construct character classes of groups of code
+points specified by Unicode. The regex crate does not provide exhaustive
+support, but covers a useful subset. In particular:
+
+* [General categories](https://unicode.org/reports/tr18/#General_Category_Property)
+* [Scripts and Script Extensions](https://unicode.org/reports/tr18/#Script_Property)
+* [Age](https://unicode.org/reports/tr18/#Age)
+* A smattering of boolean properties, including all of those specified by
+  [RL1.2](https://unicode.org/reports/tr18/#RL1.2) explicitly.
+
+In all cases, property name and value abbreviations are supported, and all
+names/values are matched loosely without regard for case, whitespace or
+underscores. Property name aliases can be found in Unicode's
+[`PropertyAliases.txt`](https://www.unicode.org/Public/UCD/latest/ucd/PropertyAliases.txt)
+file, while property value aliases can be found in Unicode's
+[`PropertyValueAliases.txt`](https://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt)
+file.
+
+The syntax supported is also consistent with the UTS#18 recommendation:
+
+* `\p{Greek}` selects the `Greek` script. Equivalent expressions follow:
+  `\p{sc:Greek}`, `\p{Script:Greek}`, `\p{Sc=Greek}`, `\p{script=Greek}`,
+  `\P{sc!=Greek}`. Similarly for `General_Category` (or `gc` for short) and
+  `Script_Extensions` (or `scx` for short).
+* `\p{age:3.2}` selects all code points in Unicode 3.2.
+* `\p{Alphabetic}` selects the "alphabetic" property and can be abbreviated
+  via `\p{alpha}` (for example).
+* Single letter variants for properties with single letter abbreviations.
+  For example, `\p{Letter}` can be equivalently written as `\pL`.
+
+The following is a list of all properties supported by the regex crate (starred
+properties correspond to properties required by RL1.2):
+
+* `General_Category` \* (including `Any`, `ASCII` and `Assigned`)
+* `Script` \*
+* `Script_Extensions` \*
+* `Age`
+* `ASCII_Hex_Digit`
+* `Alphabetic` \*
+* `Bidi_Control`
+* `Case_Ignorable`
+* `Cased`
+* `Changes_When_Casefolded`
+* `Changes_When_Casemapped`
+* `Changes_When_Lowercased`
+* `Changes_When_Titlecased`
+* `Changes_When_Uppercased`
+* `Dash`
+* `Default_Ignorable_Code_Point` \*
+* `Deprecated`
+* `Diacritic`
+* `Emoji`
+* `Emoji_Presentation`
+* `Emoji_Modifier`
+* `Emoji_Modifier_Base`
+* `Emoji_Component`
+* `Extended_Pictographic`
+* `Extender`
+* `Grapheme_Base`
+* `Grapheme_Cluster_Break`
+* `Grapheme_Extend`
+* `Hex_Digit`
+* `IDS_Binary_Operator`
+* `IDS_Trinary_Operator`
+* `ID_Continue`
+* `ID_Start`
+* `Join_Control`
+* `Logical_Order_Exception`
+* `Lowercase` \*
+* `Math`
+* `Noncharacter_Code_Point` \*
+* `Pattern_Syntax`
+* `Pattern_White_Space`
+* `Prepended_Concatenation_Mark`
+* `Quotation_Mark`
+* `Radical`
+* `Regional_Indicator`
+* `Sentence_Break`
+* `Sentence_Terminal`
+* `Soft_Dotted`
+* `Terminal_Punctuation`
+* `Unified_Ideograph`
+* `Uppercase` \*
+* `Variation_Selector`
+* `White_Space` \*
+* `Word_Break`
+* `XID_Continue`
+* `XID_Start`
+
+
+## RL1.2a Compatibility Properties
+
+[UTS#18 RL1.2a](https://unicode.org/reports/tr18/#RL1.2a)
+
+The regex crate only provides ASCII definitions of the
+[compatibility properties documented in UTS#18 Annex C](https://unicode.org/reports/tr18/#Compatibility_Properties)
+(sans the `\X` class, for matching grapheme clusters, which isn't provided
+at all). This is because it seems to be consistent with most other regular
+expression engines, and in particular, because these are often referred to as
+"ASCII" or "POSIX" character classes.
+
+Note that the `\w`, `\s` and `\d` character classes **are** Unicode aware.
+Their traditional ASCII definition can be used by disabling Unicode. That is,
+`[[:word:]]` and `(?-u)\w` are equivalent.
+
+
+## RL1.3 Subtraction and Intersection
+
+[UTS#18 RL1.3](https://unicode.org/reports/tr18/#Subtraction_and_Intersection)
+
+The regex crate provides full support for nested character classes, along with
+union, intersection (`&&`), difference (`--`) and symmetric difference (`~~`)
+operations on arbitrary character classes.
+
+For example, to match all non-ASCII letters, you could use either
+`[\p{Letter}--\p{Ascii}]` (difference) or `[\p{Letter}&&[^\p{Ascii}]]`
+(intersecting the negation).
+
+
+## RL1.4 Simple Word Boundaries
+
+[UTS#18 RL1.4](https://unicode.org/reports/tr18/#Simple_Word_Boundaries)
+
+The regex crate provides basic Unicode aware word boundary assertions. A word
+boundary assertion can be written as `\b`, or `\B` as its negation. A word
+boundary negation corresponds to a zero-width match, where its adjacent
+characters correspond to word and non-word, or non-word and word characters.
+
+Conformance in this case chooses to define word character in the same way that
+the `\w` character class is defined: a code point that is a member of one of
+the following classes:
+
+* `\p{Alphabetic}`
+* `\p{Join_Control}`
+* `\p{gc:Mark}`
+* `\p{gc:Decimal_Number}`
+* `\p{gc:Connector_Punctuation}`
+
+In particular, this differs slightly from the
+[prescription given in RL1.4](https://unicode.org/reports/tr18/#Simple_Word_Boundaries)
+but is permissible according to
+[UTS#18 Annex C](https://unicode.org/reports/tr18/#Compatibility_Properties).
+Namely, it is convenient and simpler to have `\w` and `\b` be in sync with
+one another.
+
+Finally, Unicode word boundaries can be disabled, which will cause ASCII word
+boundaries to be used instead. That is, `\b` is a Unicode word boundary while
+`(?-u)\b` is an ASCII-only word boundary. This can occasionally be beneficial
+if performance is important, since the implementation of Unicode word
+boundaries is currently sub-optimal on non-ASCII text.
+
+
+## RL1.5 Simple Loose Matches
+
+[UTS#18 RL1.5](https://unicode.org/reports/tr18/#Simple_Loose_Matches)
+
+The regex crate provides full support for case insensitive matching in
+accordance with RL1.5. That is, it uses the "simple" case folding mapping. The
+"simple" mapping was chosen because of a key convenient property: every
+"simple" mapping is a mapping from exactly one code point to exactly one other
+code point. This makes case insensitive matching of character classes, for
+example, straight-forward to implement.
+
+When case insensitive mode is enabled (e.g., `(?i)[a]` is equivalent to `a|A`),
+then all characters classes are case folded as well.
+
+
+## RL1.6 Line Boundaries
+
+[UTS#18 RL1.6](https://unicode.org/reports/tr18/#Line_Boundaries)
+
+The regex crate only provides support for recognizing the `\n` (`END OF LINE`)
+character as a line boundary. This choice was made mostly for implementation
+convenience, and to avoid performance cliffs that Unicode word boundaries are
+subject to.
+
+Ideally, it would be nice to at least support `\r\n` as a line boundary as
+well, and in theory, this could be done efficiently.
+
+
+## RL1.7 Code Points
+
+[UTS#18 RL1.7](https://unicode.org/reports/tr18/#Supplementary_Characters)
+
+The regex crate provides full support for Unicode code point matching. Namely,
+the fundamental atom of any match is always a single code point.
+
+Given Rust's strong ties to UTF-8, the following guarantees are also provided:
+
+* All matches are reported on valid UTF-8 code unit boundaries. That is, any
+  match range returned by the public regex API is guaranteed to successfully
+  slice the string that was searched.
+* By consequence of the above, it is impossible to match surrogode code points.
+  No support for UTF-16 is provided, so this is never necessary.
+
+Note that when Unicode mode is disabled, the fundamental atom of matching is
+no longer a code point but a single byte. When Unicode mode is disabled, many
+Unicode features are disabled as well. For example, `(?-u)\pL` is not a valid
+regex but `\pL(?-u)\xFF` (matches any Unicode `Letter` followed by the literal
+byte `\xFF`) is, for example.
diff --git a/vendor/regex-1.4.6/examples/regexdna-input.txt b/vendor/regex-1.4.6/examples/regexdna-input.txt
new file mode 100644 (file)
index 0000000..fb23263
--- /dev/null
@@ -0,0 +1,1671 @@
+>ONE Homo sapiens alu
+GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA
+TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT
+AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG
+GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG
+CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT
+GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA
+GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA
+TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG
+AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA
+GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT
+AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC
+AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG
+GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC
+CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG
+AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT
+TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA
+TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT
+GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG
+TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT
+CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG
+CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG
+TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA
+CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG
+AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG
+GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC
+TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA
+TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA
+GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT
+GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC
+ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT
+TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC
+CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG
+CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG
+GGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCC
+CAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCT
+GGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGC
+GCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGA
+GGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGA
+GACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGA
+GGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTG
+AAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT
+CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCA
+GTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAA
+AAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGC
+GGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCT
+ACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGG
+GAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATC
+GCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGC
+GGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGG
+TCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAA
+AAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAG
+GAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACT
+CCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCC
+TGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAG
+ACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGC
+GTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGA
+ACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGA
+CAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCA
+CTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCA
+ACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCG
+CCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGG
+AGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTC
+CGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCG
+AGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACC
+CCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAG
+CTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAG
+CCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGG
+CCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATC
+ACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAA
+AAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGC
+TGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCC
+ACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGG
+CTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGG
+AGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATT
+AGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAA
+TCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGC
+CTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAA
+TCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAG
+CCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGT
+GGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCG
+GGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAG
+CGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG
+GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATG
+GTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGT
+AATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTT
+GCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCT
+CAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCG
+GGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTC
+TCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACT
+CGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAG
+ATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGG
+CGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTG
+AGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATA
+CAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGG
+CAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGC
+ACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCAC
+GCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTC
+GAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCG
+GGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCT
+TGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGG
+CGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCA
+GCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGG
+CCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGC
+GCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGG
+CGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGA
+CTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGG
+CCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAA
+ACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCC
+CAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGT
+GAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAA
+AGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGG
+ATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTAC
+TAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGA
+GGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGC
+GCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGG
+TGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTC
+AGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAA
+ATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGA
+GAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC
+AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTG
+TAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGAC
+CAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGT
+GGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC
+CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACA
+GAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACT
+TTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAAC
+ATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCC
+TGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAG
+GTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCG
+TCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAG
+GCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCC
+GTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCT
+ACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCC
+GAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCC
+GGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCAC
+CTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAA
+ATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTG
+AGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCAC
+TGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCT
+CACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAG
+TTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAG
+CCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATC
+GCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCT
+GGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATC
+CCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCC
+TGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGG
+CGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG
+AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCG
+AGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGG
+AGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGT
+GAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAA
+TCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGC
+AGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCA
+AAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGG
+CGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTC
+TACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCG
+GGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGAT
+CGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCG
+CGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAG
+GTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACA
+AAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCA
+GGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCAC
+TCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGC
+CTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA
+GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGG
+CGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTG
+AACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCG
+ACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGC
+ACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCC
+AACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGC
+GCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCG
+GAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACT
+CCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCC
+GAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAAC
+CCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA
+GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGA
+GCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAG
+GCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGAT
+CACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTA
+AAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGG
+CTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGC
+CACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTG
+GCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAG
+GAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAAT
+TAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGA
+ATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAG
+CCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTA
+ATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCA
+GCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGG
+TGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCC
+GGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGA
+GCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTT
+GGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACAT
+GGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTG
+TAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGT
+TGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTC
+TCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGC
+GGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGT
+CTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTAC
+TCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGA
+GATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGG
+GCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCT
+GAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT
+ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAG
+GCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG
+CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCA
+CGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTT
+CGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCC
+GGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGC
+TTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGG
+GCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCC
+AGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTG
+GCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCG
+CGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAG
+GCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAG
+ACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAG
+GCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGA
+AACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATC
+CCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAG
+TGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAA
+AAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCG
+GATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTA
+CTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGG
+AGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCG
+CGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCG
+GTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGT
+CAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAA
+AATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGG
+AGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTC
+CAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCT
+GTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA
+CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCG
+TGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAA
+CCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGAC
+AGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCAC
+TTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAA
+CATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGC
+CTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGA
+GGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCC
+GTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGA
+GGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCC
+CGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGC
+TACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGC
+CGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGC
+CGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCA
+CCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA
+AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCT
+GAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCA
+CTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGC
+TCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGA
+GTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTA
+GCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAAT
+CGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCC
+TGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAAT
+CCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGC
+CTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTG
+GCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGG
+GAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGC
+GAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG
+GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGG
+TGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTA
+ATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTG
+CAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTC
+AAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGG
+GCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCT
+CTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTC
+GGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGA
+TCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGC
+GCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGA
+GGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATAC
+AAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGC
+AGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCA
+CTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACG
+CCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCG
+AGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGG
+GCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTT
+GAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGC
+GACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAG
+CACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGC
+CAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCG
+CGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGC
+GGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGAC
+TCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGC
+CGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAA
+CCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCC
+AGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTG
+AGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA
+GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA
+TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT
+AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG
+GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG
+CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT
+GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA
+GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA
+TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG
+AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA
+GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT
+AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC
+AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG
+GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC
+CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG
+AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT
+TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA
+TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT
+GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG
+TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT
+CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG
+CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG
+TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA
+CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG
+AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG
+GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC
+TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA
+TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA
+GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT
+GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC
+ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT
+TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC
+CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG
+CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG
+GGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCC
+CAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCT
+GGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGC
+GCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGA
+GGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGA
+GACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGA
+GGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTG
+AAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT
+CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCA
+GTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAA
+AAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGC
+GGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCT
+ACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGG
+GAGGCTGAGGCAGGAGAATC
+>TWO IUB ambiguity codes
+cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg
+tactDtDagcctatttSVHtHttKtgtHMaSattgWaHKHttttagacatWatgtRgaaa
+NtactMcSMtYtcMgRtacttctWBacgaaatatagScDtttgaagacacatagtVgYgt
+cattHWtMMWcStgttaggKtSgaYaaccWStcgBttgcgaMttBYatcWtgacaYcaga
+gtaBDtRacttttcWatMttDBcatWtatcttactaBgaYtcttgttttttttYaaScYa
+HgtgttNtSatcMtcVaaaStccRcctDaataataStcYtRDSaMtDttgttSagtRRca
+tttHatSttMtWgtcgtatSSagactYaaattcaMtWatttaSgYttaRgKaRtccactt
+tattRggaMcDaWaWagttttgacatgttctacaaaRaatataataaMttcgDacgaSSt
+acaStYRctVaNMtMgtaggcKatcttttattaaaaagVWaHKYagtttttatttaacct
+tacgtVtcVaattVMBcttaMtttaStgacttagattWWacVtgWYagWVRctDattBYt
+gtttaagaagattattgacVatMaacattVctgtBSgaVtgWWggaKHaatKWcBScSWa
+accRVacacaaactaccScattRatatKVtactatatttHttaagtttSKtRtacaaagt
+RDttcaaaaWgcacatWaDgtDKacgaacaattacaRNWaatHtttStgttattaaMtgt
+tgDcgtMgcatBtgcttcgcgaDWgagctgcgaggggVtaaScNatttacttaatgacag
+cccccacatYScaMgtaggtYaNgttctgaMaacNaMRaacaaacaKctacatagYWctg
+ttWaaataaaataRattagHacacaagcgKatacBttRttaagtatttccgatctHSaat
+actcNttMaagtattMtgRtgaMgcataatHcMtaBSaRattagttgatHtMttaaKagg
+YtaaBataSaVatactWtataVWgKgttaaaacagtgcgRatatacatVtHRtVYataSa
+KtWaStVcNKHKttactatccctcatgWHatWaRcttactaggatctataDtDHBttata
+aaaHgtacVtagaYttYaKcctattcttcttaataNDaaggaaaDYgcggctaaWSctBa
+aNtgctggMBaKctaMVKagBaactaWaDaMaccYVtNtaHtVWtKgRtcaaNtYaNacg
+gtttNattgVtttctgtBaWgtaattcaagtcaVWtactNggattctttaYtaaagccgc
+tcttagHVggaYtgtNcDaVagctctctKgacgtatagYcctRYHDtgBattDaaDgccK
+tcHaaStttMcctagtattgcRgWBaVatHaaaataYtgtttagMDMRtaataaggatMt
+ttctWgtNtgtgaaaaMaatatRtttMtDgHHtgtcattttcWattRSHcVagaagtacg
+ggtaKVattKYagactNaatgtttgKMMgYNtcccgSKttctaStatatNVataYHgtNa
+BKRgNacaactgatttcctttaNcgatttctctataScaHtataRagtcRVttacDSDtt
+aRtSatacHgtSKacYagttMHtWataggatgactNtatSaNctataVtttRNKtgRacc
+tttYtatgttactttttcctttaaacatacaHactMacacggtWataMtBVacRaSaatc
+cgtaBVttccagccBcttaRKtgtgcctttttRtgtcagcRttKtaaacKtaaatctcac
+aattgcaNtSBaaccgggttattaaBcKatDagttactcttcattVtttHaaggctKKga
+tacatcBggScagtVcacattttgaHaDSgHatRMaHWggtatatRgccDttcgtatcga
+aacaHtaagttaRatgaVacttagattVKtaaYttaaatcaNatccRttRRaMScNaaaD
+gttVHWgtcHaaHgacVaWtgttScactaagSgttatcttagggDtaccagWattWtRtg
+ttHWHacgattBtgVcaYatcggttgagKcWtKKcaVtgaYgWctgYggVctgtHgaNcV
+taBtWaaYatcDRaaRtSctgaHaYRttagatMatgcatttNattaDttaattgttctaa
+ccctcccctagaWBtttHtBccttagaVaatMcBHagaVcWcagBVttcBtaYMccagat
+gaaaaHctctaacgttagNWRtcggattNatcRaNHttcagtKttttgWatWttcSaNgg
+gaWtactKKMaacatKatacNattgctWtatctaVgagctatgtRaHtYcWcttagccaa
+tYttWttaWSSttaHcaaaaagVacVgtaVaRMgattaVcDactttcHHggHRtgNcctt
+tYatcatKgctcctctatVcaaaaKaaaagtatatctgMtWtaaaacaStttMtcgactt
+taSatcgDataaactaaacaagtaaVctaggaSccaatMVtaaSKNVattttgHccatca
+cBVctgcaVatVttRtactgtVcaattHgtaaattaaattttYtatattaaRSgYtgBag
+aHSBDgtagcacRHtYcBgtcacttacactaYcgctWtattgSHtSatcataaatataHt
+cgtYaaMNgBaatttaRgaMaatatttBtttaaaHHKaatctgatWatYaacttMctctt
+ttVctagctDaaagtaVaKaKRtaacBgtatccaaccactHHaagaagaaggaNaaatBW
+attccgStaMSaMatBttgcatgRSacgttVVtaaDMtcSgVatWcaSatcttttVatag
+ttactttacgatcaccNtaDVgSRcgVcgtgaacgaNtaNatatagtHtMgtHcMtagaa
+attBgtataRaaaacaYKgtRccYtatgaagtaataKgtaaMttgaaRVatgcagaKStc
+tHNaaatctBBtcttaYaBWHgtVtgacagcaRcataWctcaBcYacYgatDgtDHccta
+aagacYRcaggattHaYgtKtaatgcVcaataMYacccatatcacgWDBtgaatcBaata
+cKcttRaRtgatgaBDacggtaattaaYtataStgVHDtDctgactcaaatKtacaatgc
+gYatBtRaDatHaactgtttatatDttttaaaKVccYcaaccNcBcgHaaVcattHctcg
+attaaatBtatgcaaaaatYMctSactHatacgaWacattacMBgHttcgaatVaaaaca
+BatatVtctgaaaaWtctRacgBMaatSgRgtgtcgactatcRtattaScctaStagKga
+DcWgtYtDDWKRgRtHatRtggtcgaHgggcgtattaMgtcagccaBggWVcWctVaaat
+tcgNaatcKWagcNaHtgaaaSaaagctcYctttRVtaaaatNtataaccKtaRgtttaM
+tgtKaBtRtNaggaSattHatatWactcagtgtactaKctatttgRYYatKatgtccgtR
+tttttatttaatatVgKtttgtatgtNtataRatWYNgtRtHggtaaKaYtKSDcatcKg
+taaYatcSRctaVtSMWtVtRWHatttagataDtVggacagVcgKWagBgatBtaaagNc
+aRtagcataBggactaacacRctKgttaatcctHgDgttKHHagttgttaatgHBtatHc
+DaagtVaBaRccctVgtgDtacRHSctaagagcggWYaBtSaKtHBtaaactYacgNKBa
+VYgtaacttagtVttcttaatgtBtatMtMtttaattaatBWccatRtttcatagVgMMt
+agctStKctaMactacDNYgKYHgaWcgaHgagattacVgtttgtRaSttaWaVgataat
+gtgtYtaStattattMtNgWtgttKaccaatagNYttattcgtatHcWtctaaaNVYKKt
+tWtggcDtcgaagtNcagatacgcattaagaccWctgcagcttggNSgaNcHggatgtVt
+catNtRaaBNcHVagagaaBtaaSggDaatWaatRccaVgggStctDaacataKttKatt
+tggacYtattcSatcttagcaatgaVBMcttDattctYaaRgatgcattttNgVHtKcYR
+aatRKctgtaaacRatVSagctgtWacBtKVatctgttttKcgtctaaDcaagtatcSat
+aWVgcKKataWaYttcccSaatgaaaacccWgcRctWatNcWtBRttYaattataaNgac
+acaatagtttVNtataNaYtaatRaVWKtBatKagtaatataDaNaaaaataMtaagaaS
+tccBcaatNgaataWtHaNactgtcDtRcYaaVaaaaaDgtttRatctatgHtgttKtga
+aNSgatactttcgagWaaatctKaaDaRttgtggKKagcDgataaattgSaacWaVtaNM
+acKtcaDaaatttctRaaVcagNacaScRBatatctRatcctaNatWgRtcDcSaWSgtt
+RtKaRtMtKaatgttBHcYaaBtgatSgaSWaScMgatNtctcctatttctYtatMatMt
+RRtSaattaMtagaaaaStcgVgRttSVaScagtgDtttatcatcatacRcatatDctta
+tcatVRtttataaHtattcYtcaaaatactttgVctagtaaYttagatagtSYacKaaac
+gaaKtaaatagataatSatatgaaatSgKtaatVtttatcctgKHaatHattagaaccgt
+YaaHactRcggSBNgtgctaaBagBttgtRttaaattYtVRaaaattgtaatVatttctc
+ttcatgBcVgtgKgaHaaatattYatagWacNctgaaMcgaattStagWaSgtaaKagtt
+ttaagaDgatKcctgtaHtcatggKttVDatcaaggtYcgccagNgtgcVttttagagat
+gctaccacggggtNttttaSHaNtatNcctcatSaaVgtactgBHtagcaYggYVKNgta
+KBcRttgaWatgaatVtagtcgattYgatgtaatttacDacSctgctaaaStttaWMagD
+aaatcaVYctccgggcgaVtaaWtStaKMgDtttcaaMtVgBaatccagNaaatcYRMBg
+gttWtaaScKttMWtYataRaDBMaDataatHBcacDaaKDactaMgagttDattaHatH
+taYatDtattDcRNStgaatattSDttggtattaaNSYacttcDMgYgBatWtaMagact
+VWttctttgYMaYaacRgHWaattgRtaagcattctMKVStatactacHVtatgatcBtV
+NataaBttYtSttacKgggWgYDtgaVtYgatDaacattYgatggtRDaVDttNactaSa
+MtgNttaacaaSaBStcDctaccacagacgcaHatMataWKYtaYattMcaMtgSttDag
+cHacgatcaHttYaKHggagttccgatYcaatgatRaVRcaagatcagtatggScctata
+ttaNtagcgacgtgKaaWaactSgagtMYtcttccaKtStaacggMtaagNttattatcg
+tctaRcactctctDtaacWYtgaYaSaagaWtNtatttRacatgNaatgttattgWDDcN
+aHcctgaaHacSgaataaRaataMHttatMtgaSDSKatatHHaNtacagtccaYatWtc
+actaactatKDacSaStcggataHgYatagKtaatKagStaNgtatactatggRHacttg
+tattatgtDVagDVaRctacMYattDgtttYgtctatggtKaRSttRccRtaaccttaga
+gRatagSaaMaacgcaNtatgaaatcaRaagataatagatactcHaaYKBctccaagaRa
+BaStNagataggcgaatgaMtagaatgtcaKttaaatgtaWcaBttaatRcggtgNcaca
+aKtttScRtWtgcatagtttWYaagBttDKgcctttatMggNttattBtctagVtacata
+aaYttacacaaRttcYtWttgHcaYYtaMgBaBatctNgcDtNttacgacDcgataaSat
+YaSttWtcctatKaatgcagHaVaacgctgcatDtgttaSataaaaYSNttatagtaNYt
+aDaaaNtggggacttaBggcHgcgtNtaaMcctggtVtaKcgNacNtatVaSWctWtgaW
+cggNaBagctctgaYataMgaagatBSttctatacttgtgtKtaattttRagtDtacata
+tatatgatNHVgBMtKtaKaNttDHaagatactHaccHtcatttaaagttVaMcNgHata
+tKtaNtgYMccttatcaaNagctggacStttcNtggcaVtattactHaSttatgNMVatt
+MMDtMactattattgWMSgtHBttStStgatatRaDaagattttctatMtaaaaaggtac
+taaVttaSacNaatactgMttgacHaHRttgMacaaaatagttaatatWKRgacDgaRta
+tatttattatcYttaWtgtBRtWatgHaaattHataagtVaDtWaVaWtgStcgtMSgaS
+RgMKtaaataVacataatgtaSaatttagtcgaaHtaKaatgcacatcggRaggSKctDc
+agtcSttcccStYtccRtctctYtcaaKcgagtaMttttcRaYDttgttatctaatcata
+NctctgctatcaMatactataggDaHaaSttMtaDtcNatataattctMcStaaBYtaNa
+gatgtaatHagagSttgWHVcttatKaYgDctcttggtgttMcRaVgSgggtagacaata
+aDtaattSaDaNaHaBctattgNtaccaaRgaVtKNtaaYggHtaKKgHcatctWtctDt
+ttctttggSDtNtaStagttataaacaattgcaBaBWggHgcaaaBtYgctaatgaaatW
+cDcttHtcMtWWattBHatcatcaaatctKMagtDNatttWaBtHaaaNgMttaaStagt
+tctctaatDtcRVaYttgttMtRtgtcaSaaYVgSWDRtaatagctcagDgcWWaaaBaa
+RaBctgVgggNgDWStNaNBKcBctaaKtttDcttBaaggBttgaccatgaaaNgttttt
+tttatctatgttataccaaDRaaSagtaVtDtcaWatBtacattaWacttaSgtattggD
+gKaaatScaattacgWcagKHaaccaYcRcaRttaDttRtttHgaHVggcttBaRgtccc
+tDatKaVtKtcRgYtaKttacgtatBtStaagcaattaagaRgBagSaattccSWYttta
+ttVaataNctgHgttaaNBgcVYgtRtcccagWNaaaacaDNaBcaaaaRVtcWMgBagM
+tttattacgDacttBtactatcattggaaatVccggttRttcatagttVYcatYaSHaHc
+ttaaagcNWaHataaaRWtctVtRYtagHtaaaYMataHYtNBctNtKaatattStgaMc
+BtRgctaKtgcScSttDgYatcVtggaaKtaagatWccHccgKYctaNNctacaWctttt
+gcRtgtVcgaKttcMRHgctaHtVaataaDtatgKDcttatBtDttggNtacttttMtga
+acRattaaNagaactcaaaBBVtcDtcgaStaDctgaaaSgttMaDtcgttcaccaaaag
+gWtcKcgSMtcDtatgtttStaaBtatagDcatYatWtaaaBacaKgcaDatgRggaaYc
+taRtccagattDaWtttggacBaVcHtHtaacDacYgtaatataMagaatgHMatcttat
+acgtatttttatattacHactgttataMgStYaattYaccaattgagtcaaattaYtgta
+tcatgMcaDcgggtcttDtKgcatgWRtataatatRacacNRBttcHtBgcRttgtgcgt
+catacMtttBctatctBaatcattMttMYgattaaVYatgDaatVagtattDacaacDMa
+tcMtHcccataagatgBggaccattVWtRtSacatgctcaaggggYtttDtaaNgNtaaB
+atggaatgtctRtaBgBtcNYatatNRtagaacMgagSaSDDSaDcctRagtVWSHtVSR
+ggaacaBVaccgtttaStagaacaMtactccagtttVctaaRaaHttNcttagcaattta
+ttaatRtaaaatctaacDaBttggSagagctacHtaaRWgattcaaBtctRtSHaNtgta
+cattVcaHaNaagtataccacaWtaRtaaVKgMYaWgttaKggKMtKcgWatcaDatYtK
+SttgtacgaccNctSaattcDcatcttcaaaDKttacHtggttHggRRaRcaWacaMtBW
+VHSHgaaMcKattgtaRWttScNattBBatYtaNRgcggaagacHSaattRtttcYgacc
+BRccMacccKgatgaacttcgDgHcaaaaaRtatatDtatYVtttttHgSHaSaatagct
+NYtaHYaVYttattNtttgaaaYtaKttWtctaNtgagaaaNctNDctaaHgttagDcRt
+tatagccBaacgcaRBtRctRtggtaMYYttWtgataatcgaataattattataVaaaaa
+ttacNRVYcaaMacNatRttcKatMctgaagactaattataaYgcKcaSYaatMNctcaa
+cgtgatttttBacNtgatDccaattattKWWcattttatatatgatBcDtaaaagttgaa
+VtaHtaHHtBtataRBgtgDtaataMttRtDgDcttattNtggtctatctaaBcatctaR
+atgNacWtaatgaagtcMNaacNgHttatactaWgcNtaStaRgttaaHacccgaYStac
+aaaatWggaYaWgaattattcMaactcBKaaaRVNcaNRDcYcgaBctKaacaaaaaSgc
+tccYBBHYaVagaatagaaaacagYtctVccaMtcgtttVatcaatttDRtgWctagtac
+RttMctgtDctttcKtWttttataaatgVttgBKtgtKWDaWagMtaaagaaattDVtag
+gttacatcatttatgtcgMHaVcttaBtVRtcgtaYgBRHatttHgaBcKaYWaatcNSc
+tagtaaaaatttacaatcactSWacgtaatgKttWattagttttNaggtctcaagtcact
+attcttctaagKggaataMgtttcataagataaaaatagattatDgcBVHWgaBKttDgc
+atRHaagcaYcRaattattatgtMatatattgHDtcaDtcaaaHctStattaatHaccga
+cNattgatatattttgtgtDtRatagSacaMtcRtcattcccgacacSattgttKaWatt
+NHcaacttccgtttSRtgtctgDcgctcaaMagVtBctBMcMcWtgtaacgactctcttR
+ggRKSttgYtYatDccagttDgaKccacgVatWcataVaaagaataMgtgataaKYaaat
+cHDaacgataYctRtcYatcgcaMgtNttaBttttgatttaRtStgcaacaaaataccVg
+aaDgtVgDcStctatatttattaaaaRKDatagaaagaKaaYYcaYSgKStctccSttac
+agtcNactttDVttagaaagMHttRaNcSaRaMgBttattggtttaRMggatggcKDgWR
+tNaataataWKKacttcKWaaagNaBttaBatMHtccattaacttccccYtcBcYRtaga
+ttaagctaaYBDttaNtgaaaccHcaRMtKtaaHMcNBttaNaNcVcgVttWNtDaBatg
+ataaVtcWKcttRggWatcattgaRagHgaattNtatttctctattaattaatgaDaaMa
+tacgttgggcHaYVaaNaDDttHtcaaHtcVVDgBVagcMacgtgttaaBRNtatRtcag
+taagaggtttaagacaVaaggttaWatctccgtVtaDtcDatttccVatgtacNtttccg
+tHttatKgScBatgtVgHtYcWagcaKtaMYaaHgtaattaSaHcgcagtWNaatNccNN
+YcacgVaagaRacttctcattcccRtgtgtaattagcSttaaStWaMtctNNcSMacatt
+ataaactaDgtatWgtagtttaagaaaattgtagtNagtcaataaatttgatMMYactaa
+tatcggBWDtVcYttcDHtVttatacYaRgaMaacaStaatcRttttVtagaDtcacWat
+ttWtgaaaagaaagNRacDtttStVatBaDNtaactatatcBSMcccaSttccggaMatg
+attaaWatKMaBaBatttgataNctgttKtVaagtcagScgaaaDggaWgtgttttKtWt
+atttHaatgtagttcactaaKMagttSYBtKtaYgaactcagagRtatagtVtatcaaaW
+YagcgNtaDagtacNSaaYDgatBgtcgataacYDtaaactacagWDcYKaagtttatta
+gcatcgagttKcatDaattgattatDtcagRtWSKtcgNtMaaaaacaMttKcaWcaaSV
+MaaaccagMVtaMaDtMaHaBgaacataBBVtaatVYaNSWcSgNtDNaaKacacBttta
+tKtgtttcaaHaMctcagtaacgtcgYtactDcgcctaNgagagcYgatattttaaattt
+ccattttacatttDaaRctattttWctttacgtDatYtttcagacgcaaVttagtaaKaa
+aRtgVtccataBggacttatttgtttaWNtgttVWtaWNVDaattgtatttBaagcBtaa
+BttaaVatcHcaVgacattccNggtcgacKttaaaRtagRtctWagaYggtgMtataatM
+tgaaRttattttgWcttNtDRRgMDKacagaaaaggaaaRStcccagtYccVattaNaaK
+StNWtgacaVtagaagcttSaaDtcacaacgDYacWDYtgtttKatcVtgcMaDaSKStV
+cgtagaaWaKaagtttcHaHgMgMtctataagBtKaaaKKcactggagRRttaagaBaaN
+atVVcgRcKSttDaactagtSttSattgttgaaRYatggttVttaataaHttccaagDtg
+atNWtaagHtgcYtaactRgcaatgMgtgtRaatRaNaacHKtagactactggaatttcg
+ccataacgMctRgatgttaccctaHgtgWaYcactcacYaattcttaBtgacttaaacct
+gYgaWatgBttcttVttcgttWttMcNYgtaaaatctYgMgaaattacNgaHgaacDVVM
+tttggtHtctaaRgtacagacgHtVtaBMNBgattagcttaRcttacaHcRctgttcaaD
+BggttKaacatgKtttYataVaNattccgMcgcgtagtRaVVaattaKaatggttRgaMc
+agtatcWBttNtHagctaatctagaaNaaacaYBctatcgcVctBtgcaaagDgttVtga
+HtactSNYtaaNccatgtgDacgaVtDcgKaRtacDcttgctaagggcagMDagggtBWR
+tttSgccttttttaacgtcHctaVtVDtagatcaNMaVtcVacatHctDWNaataRgcgt
+aVHaggtaaaaSgtttMtattDgBtctgatSgtRagagYtctSaKWaataMgattRKtaa
+catttYcgtaacacattRWtBtcggtaaatMtaaacBatttctKagtcDtttgcBtKYYB
+aKttctVttgttaDtgattttcttccacttgSaaacggaaaNDaattcYNNaWcgaaYat
+tttMgcBtcatRtgtaaagatgaWtgaccaYBHgaatagataVVtHtttVgYBtMctaMt
+cctgaDcYttgtccaaaRNtacagcMctKaaaggatttacatgtttaaWSaYaKttBtag
+DacactagctMtttNaKtctttcNcSattNacttggaacaatDagtattRtgSHaataat
+gccVgacccgatactatccctgtRctttgagaSgatcatatcgDcagWaaHSgctYYWta
+tHttggttctttatVattatcgactaagtgtagcatVgtgHMtttgtttcgttaKattcM
+atttgtttWcaaStNatgtHcaaaDtaagBaKBtRgaBgDtSagtatMtaacYaatYtVc
+KatgtgcaacVaaaatactKcRgtaYtgtNgBBNcKtcttaccttKgaRaYcaNKtactt
+tgagSBtgtRagaNgcaaaNcacagtVtttHWatgttaNatBgtttaatNgVtctgaata
+tcaRtattcttttttttRaaKcRStctcggDgKagattaMaaaKtcaHacttaataataK
+taRgDtKVBttttcgtKaggHHcatgttagHggttNctcgtatKKagVagRaaaggaaBt
+NatttVKcRttaHctaHtcaaatgtaggHccaBataNaNaggttgcWaatctgatYcaaa
+HaatWtaVgaaBttagtaagaKKtaaaKtRHatMaDBtBctagcatWtatttgWttVaaa
+ScMNattRactttgtYtttaaaagtaagtMtaMaSttMBtatgaBtttaKtgaatgagYg
+tNNacMtcNRacMMHcttWtgtRtctttaacaacattattcYaMagBaacYttMatcttK
+cRMtgMNccattaRttNatHaHNaSaaHMacacaVaatacaKaSttHatattMtVatWga
+ttttttaYctttKttHgScWaacgHtttcaVaaMgaacagNatcgttaacaaaaagtaca
+HBNaattgttKtcttVttaaBtctgctacgBgcWtttcaggacacatMgacatcccagcg
+gMgaVKaBattgacttaatgacacacaaaaaatRKaaBctacgtRaDcgtagcVBaacDS
+BHaaaaSacatatacagacRNatcttNaaVtaaaataHattagtaaaaSWccgtatWatg
+gDttaactattgcccatcttHaSgYataBttBaactattBtcHtgatcaataSttaBtat
+KSHYttWggtcYtttBttaataccRgVatStaHaKagaatNtagRMNgtcttYaaSaact
+cagDSgagaaYtMttDtMRVgWKWtgMaKtKaDttttgactatacataatcNtatNaHat
+tVagacgYgatatatttttgtStWaaatctWaMgagaRttRatacgStgattcttaagaD
+taWccaaatRcagcagaaNKagtaaDggcgccBtYtagSBMtactaaataMataBSacRM
+gDgattMMgtcHtcaYDtRaDaacggttDaggcMtttatgttaNctaattaVacgaaMMt
+aatDccSgtattgaRtWWaccaccgagtactMcgVNgctDctaMScatagcgtcaactat
+acRacgHRttgctatttaatgaattataYKttgtaagWgtYttgcHgMtaMattWaWVta
+RgcttgYgttBHtYataSccStBtgtagMgtDtggcVaaSBaatagDttgBgtctttctc
+attttaNagtHKtaMWcYactVcgcgtatMVtttRacVagDaatcttgctBBcRDgcaac
+KttgatSKtYtagBMagaRtcgBattHcBWcaactgatttaatttWDccatttatcgagS
+KaWttataHactaHMttaatHtggaHtHagaatgtKtaaRactgtttMatacgatcaagD
+gatKaDctataMggtHDtggHacctttRtatcttYattttgacttgaaSaataaatYcgB
+aaaaccgNatVBttMacHaKaataagtatKgtcaagactcttaHttcggaattgttDtct
+aaccHttttWaaatgaaatataaaWattccYDtKtaaaacggtgaggWVtctattagtga
+ctattaagtMgtttaagcatttgSgaaatatccHaaggMaaaattttcWtatKctagDtY
+tMcctagagHcactttactatacaaacattaacttaHatcVMYattYgVgtMttaaRtga
+aataaDatcaHgtHHatKcDYaatcttMtNcgatYatgSaMaNtcttKcWataScKggta
+tcttacgcttWaaagNatgMgHtctttNtaacVtgttcMaaRatccggggactcMtttaY
+MtcWRgNctgNccKatcttgYDcMgattNYaRagatHaaHgKctcataRDttacatBatc
+cattgDWttatttaWgtcggagaaaaatacaatacSNtgggtttccttacSMaagBatta
+caMaNcactMttatgaRBacYcYtcaaaWtagctSaacttWgDMHgaggatgBVgcHaDt
+ggaactttggtcNatNgtaKaBcccaNtaagttBaacagtatacDYttcctNgWgcgSMc
+acatStctHatgRcNcgtacacaatRttMggaNKKggataaaSaYcMVcMgtaMaHtgat
+tYMatYcggtcttcctHtcDccgtgRatcattgcgccgatatMaaYaataaYSggatagc
+gcBtNtaaaScaKgttBgagVagttaKagagtatVaactaSacWactSaKatWccaKaaa
+atBKgaaKtDMattttgtaaatcRctMatcaaMagMttDgVatggMaaWgttcgaWatga
+aatttgRtYtattaWHKcRgctacatKttctaccaaHttRatctaYattaaWatVNccat
+NgagtcKttKataStRaatatattcctRWatDctVagttYDgSBaatYgttttgtVaatt
+taatagcagMatRaacttBctattgtMagagattaaactaMatVtHtaaatctRgaaaaa
+aaatttWacaacaYccYDSaattMatgaccKtaBKWBattgtcaagcHKaagttMMtaat
+ttcKcMagNaaKagattggMagaggtaatttYacatcWaaDgatMgKHacMacgcVaaca
+DtaDatatYggttBcgtatgWgaSatttgtagaHYRVacaRtctHaaRtatgaactaata
+tctSSBgggaaHMWtcaagatKgagtDaSatagttgattVRatNtctMtcSaagaSHaat
+aNataataRaaRgattctttaataaagWaRHcYgcatgtWRcttgaaggaMcaataBRaa
+ccagStaaacNtttcaatataYtaatatgHaDgcStcWttaacctaRgtYaRtataKtgM
+ttttatgactaaaatttacYatcccRWtttHRtattaaatgtttatatttgttYaatMca
+RcSVaaDatcgtaYMcatgtagacatgaaattgRtcaaYaaYtRBatKacttataccaNa
+aattVaBtctggacaagKaaYaaatatWtMtatcYaaVNtcgHaactBaagKcHgtctac
+aatWtaDtSgtaHcataHtactgataNctRgttMtDcDttatHtcgtacatcccaggStt
+aBgtcacacWtccNMcNatMVaVgtccDYStatMaccDatggYaRKaaagataRatttHK
+tSaaatDgataaacttaHgttgVBtcttVttHgDacgaKatgtatatNYataactctSat
+atatattgcHRRYttStggaactHgttttYtttaWtatMcttttctatctDtagVHYgMR
+BgtHttcctaatYRttKtaagatggaVRataKDctaMtKBNtMtHNtWtttYcVtattMc
+gRaacMcctNSctcatttaaagDcaHtYccSgatgcaatYaaaaDcttcgtaWtaattct
+cgttttScttggtaatctttYgtctaactKataHacctMctcttacHtKataacacagcN
+RatgKatttttSaaatRYcgDttaMRcgaaattactMtgcgtaagcgttatBtttttaat
+taagtNacatHgttcRgacKcBBtVgatKttcgaBaatactDRgtRtgaNacWtcacYtt
+aaKcgttctHaKttaNaMgWgWaggtctRgaKgWttSttBtDcNtgtttacaaatYcDRt
+gVtgcctattcNtctaaaDMNttttNtggctgagaVctDaacVtWccaagtaacacaNct
+gaScattccDHcVBatcgatgtMtaatBgHaatDctMYgagaatgYWKcctaatNaStHa
+aaKccgHgcgtYaaYtattgtStgtgcaaRtattaKatattagaWVtcaMtBagttatta
+gNaWHcVgcaattttDcMtgtaRHVYtHtctgtaaaaHVtMKacatcgNaatttMatatg
+ttgttactagWYtaRacgataKagYNKcattataNaRtgaacKaYgcaaYYacaNccHat
+MatDcNgtHttRaWttagaaDcaaaaaatagggtKDtStaDaRtaVtHWKNtgtattVct
+SVgRgataDaRaWataBgaagaaKtaataaYgDcaStaNgtaDaaggtattHaRaWMYaY
+aWtggttHYgagVtgtgcttttcaaDKcagVcgttagacNaaWtagtaataDttctggtt
+VcatcataaagtgKaaaNaMtaBBaattaatWaattgctHaVKaSgDaaVKaHtatatat
+HatcatSBagNgHtatcHYMHgttDgtaHtBttWatcgtttaRaattgStKgSKNWKatc
+agDtctcagatttctRtYtBatBgHHtKaWtgYBgacVVWaKtacKcDttKMaKaVcggt
+gttataagaataaHaatattagtataatMHgttYgaRttagtaRtcaaVatacggtcMcg
+agtaaRttacWgactKRYataaaagSattYaWgagatYagKagatgSaagKgttaatMgg
+tataatgttWYttatgagaaacctNVataatHcccKtDctcctaatactggctHggaSag
+gRtKHaWaattcgSatMatttagaggcYtctaMcgctcataSatatgRagacNaaDagga
+VBagaYttKtacNaKgtSYtagttggaWcatcWttaatctatgaVtcgtgtMtatcaYcg
+tRccaaYgDctgcMgtgtWgacWtgataacacgcgctBtgttaKtYDtatDcatcagKaV
+MctaatcttgVcaaRgcRMtDcgattaHttcaNatgaatMtactacVgtRgatggaWttt
+actaaKatgagSaaKggtaNtactVaYtaaKRagaacccacaMtaaMtKtatBcttgtaa
+WBtMctaataaVcDaaYtcRHBtcgttNtaaHatttBNgRStVDattBatVtaagttaYa
+tVattaagaBcacggtSgtVtatttaRattgatgtaHDKgcaatattKtggcctatgaWD
+KRYcggattgRctatNgatacaatMNttctgtcRBYRaaaHctNYattcHtaWcaattct
+BtMKtVgYataatMgYtcagcttMDataVtggRtKtgaatgccNcRttcaMtRgattaac
+attRcagcctHtWMtgtDRagaKaBtgDttYaaaaKatKgatctVaaYaacWcgcatagB
+VtaNtRtYRaggBaaBtgKgttacataagagcatgtRattccacttaccatRaaatgWgD
+aMHaYVgVtaSctatcgKaatatattaDgacccYagtgtaYNaaatKcagtBRgagtcca
+tgKgaaaccBgaagBtgSttWtacgatWHaYatcgatttRaaNRgcaNaKVacaNtDgat
+tgHVaatcDaagcgtatgcNttaDataatcSataaKcaataaHWataBtttatBtcaKtK
+tatagttaDgSaYctacaRatNtaWctSaatatttYaKaKtaccWtatcRagacttaYtt
+VcKgSDcgagaagatccHtaattctSttatggtKYgtMaHagVaBRatttctgtRgtcta
+tgggtaHKgtHacHtSYacgtacacHatacKaaBaVaccaDtatcSaataaHaagagaat
+ScagactataaRttagcaaVcaHataKgDacatWccccaagcaBgagWatctaYttgaaa
+tctVNcYtttWagHcgcgcDcVaaatgttKcHtNtcaatagtgtNRaactttttcaatgg
+WgBcgDtgVgtttctacMtaaataaaRggaaacWaHttaRtNtgctaaRRtVBctYtVta
+tDcattDtgaccYatagatYRKatNYKttNgcctagtaWtgaactaMVaacctgaStttc
+tgaKVtaaVaRKDttVtVctaDNtataaaDtccccaagtWtcgatcactDgYaBcatcct
+MtVtacDaaBtYtMaKNatNtcaNacgDatYcatcgcaRatWBgaacWttKttagYtaat
+tcggttgSWttttDWctttacYtatatWtcatDtMgtBttgRtVDggttaacYtacgtac
+atgaattgaaWcttMStaDgtatattgaDtcRBcattSgaaVBRgagccaaKtttcDgcg
+aSMtatgWattaKttWtgDBMaggBBttBaatWttRtgcNtHcgttttHtKtcWtagHSt
+aacagttgatatBtaWSaWggtaataaMttaKacDaatactcBttcaatatHttcBaaSa
+aatYggtaRtatNtHcaatcaHtagVtgtattataNggaMtcttHtNagctaaaggtaga
+YctMattNaMVNtcKtactBKcaHHcBttaSagaKacataYgctaKaYgttYcgacWVtt
+WtSagcaacatcccHaccKtcttaacgaKttcacKtNtacHtatatRtaaatacactaBt
+ttgaHaRttggttWtatYagcatYDatcggagagcWBataagRtacctataRKgtBgatg
+aDatataSttagBaHtaatNtaDWcWtgtaattacagKttcNtMagtattaNgtctcgtc
+ctcttBaHaKcKccgtRcaaYagSattaagtKataDatatatagtcDtaacaWHcaKttD
+gaaRcgtgYttgtcatatNtatttttatggccHtgDtYHtWgttatYaacaattcaWtat
+NgctcaaaSttRgctaatcaaatNatcgtttaBtNNVtgttataagcaaagattBacgtD
+atttNatttaaaDcBgtaSKgacgtagataatttcHMVNttgttBtDtgtaWKaaRMcKM
+tHtaVtagataWctccNNaSWtVaHatctcMgggDgtNHtDaDttatatVWttgttattt
+aacctttcacaaggaSaDcggttttttatatVtctgVtaacaStDVaKactaMtttaSNa
+gtgaaattaNacttSKctattcctctaSagKcaVttaagNaVcttaVaaRNaHaaHttat
+gtHttgtgatMccaggtaDcgaccgtWgtWMtttaHcRtattgScctatttKtaaccaag
+tYagaHgtWcHaatgccKNRtttagtMYSgaDatctgtgaWDtccMNcgHgcaaacNDaa
+aRaStDWtcaaaaHKtaNBctagBtgtattaactaattttVctagaatggcWSatMaccc
+ttHttaSgSgtgMRcatRVKtatctgaaaccDNatYgaaVHNgatMgHRtacttaaaRta
+tStRtDtatDttYatattHggaBcttHgcgattgaKcKtttcRataMtcgaVttWacatN
+catacctRataDDatVaWNcggttgaHtgtMacVtttaBHtgagVttMaataattatgtt
+cttagtttgtgcDtSatttgBtcaacHattaaBagVWcgcaSYttMgcttacYKtVtatc
+aYaKctgBatgcgggcYcaaaaacgNtctagKBtattatctttKtaVttatagtaYtRag
+NtaYataaVtgaatatcHgcaaRataHtacacatgtaNtgtcgYatWMatttgaactacR
+ctaWtWtatacaatctBatatgYtaagtatgtgtatSttactVatcttYtaBcKgRaSgg
+RaaaaatgcagtaaaWgtaRgcgataatcBaataccgtatttttccatcNHtatWYgatH
+SaaaDHttgctgtccHtggggcctaataatttttctatattYWtcattBtgBRcVttaVM
+RSgctaatMagtYtttaaaaatBRtcBttcaaVtaacagctccSaaSttKNtHtKYcagc
+agaaaccccRtttttaaDcDtaStatccaagcgctHtatcttaDRYgatDHtWcaaaBcW
+gKWHttHataagHacgMNKttMKHccaYcatMVaacgttaKgYcaVaaBtacgcaacttt
+MctaaHaatgtBatgagaSatgtatgSRgHgWaVWgataaatatttccKagVgataattW
+aHNcYggaaatgctHtKtaDtctaaagtMaatVDVactWtSaaWaaMtaHtaSKtcBRaN
+cttStggtBttacNagcatagRgtKtgcgaacaacBcgKaatgataagatgaaaattgta
+ctgcgggtccHHWHaaNacaBttNKtKtcaaBatatgctaHNgtKcDWgtttatNgVDHg
+accaacWctKaaggHttgaRgYaatHcaBacaatgagcaaattactgtaVaaYaDtagat
+tgagNKggtggtgKtWKaatacagDRtatRaMRtgattDggtcaaYRtatttNtagaDtc
+acaaSDctDtataatcgtactaHttatacaatYaacaaHttHatHtgcgatRRttNgcat
+SVtacWWgaaggagtatVMaVaaattScDDKNcaYBYaDatHgtctatBagcaacaagaa
+tgagaaRcataaKNaRtBDatcaaacgcattttttaaBtcSgtacaRggatgtMNaattg
+gatatWtgagtattaaaVctgcaYMtatgatttttYgaHtgtcttaagWBttHttgtctt
+attDtcgtatWtataataSgctaHagcDVcNtaatcaagtaBDaWaDgtttagYctaNcc
+DtaKtaHcttaataacccaRKtacaVaatNgcWRaMgaattatgaBaaagattVYaHMDc
+aDHtcRcgYtcttaaaWaaaVKgatacRtttRRKYgaatacaWVacVcRtatMacaBtac
+tggMataaattttHggNagSctacHgtBagcgtcgtgattNtttgatSaaggMttctttc
+ttNtYNagBtaaacaaatttMgaccttacataattgYtcgacBtVMctgStgMDtagtaR
+ctHtatgttcatatVRNWataDKatWcgaaaaagttaaaagcacgHNacgtaatctttMR
+tgacttttDacctataaacgaaatatgattagaactccSYtaBctttaataacWgaaaYa
+tagatgWttcatKtNgatttttcaagHtaYgaaRaDaagtaggagcttatVtagtctttc
+attaaaatcgKtattaRttacagVaDatgcatVgattgggtctttHVtagKaaRBtaHta
+aggccccaaaaKatggtttaMWgtBtaaacttcactttKHtcgatctccctaYaBacMgt
+cttBaBaNgcgaaacaatctagtHccHtKttcRtRVttccVctttcatacYagMVtMcag
+aMaaacaataBctgYtaatRaaagattaaccatVRatHtaRagcgcaBcgDttStttttc
+VtttaDtKgcaaWaaaaatSccMcVatgtKgtaKgcgatatgtagtSaaaDttatacaaa
+catYaRRcVRHctKtcgacKttaaVctaDaatgttMggRcWaacttttHaDaKaDaBctg
+taggcgtttaHBccatccattcNHtDaYtaataMttacggctNVaacDattgatatttta
+cVttSaattacaaRtataNDgacVtgaacataVRttttaDtcaaacataYDBtttaatBa
+DtttYDaDaMccMttNBttatatgagaaMgaNtattHccNataattcaHagtgaaggDga
+tgtatatatgYatgaStcataaBStWacgtcccataRMaaDattggttaaattcMKtctM
+acaBSactcggaatDDgatDgcWctaacaccgggaVcacWKVacggtaNatatacctMta
+tgatagtgcaKagggVaDtgtaacttggagtcKatatcgMcttRaMagcattaBRaStct
+YSggaHYtacaactMBaagDcaBDRaaacMYacaHaattagcattaaaHgcgctaaggSc
+cKtgaaKtNaBtatDDcKBSaVtgatVYaagVtctSgMctacgttaacWaaattctSgtD
+actaaStaaattgcagBBRVctaatatacctNttMcRggctttMttagacRaHcaBaacV
+KgaataHttttMgYgattcYaNRgttMgcVaaacaVVcDHaatttgKtMYgtatBtVVct
+WgVtatHtacaaHttcacgatagcagtaaNattBatatatttcVgaDagcggttMaagtc
+ScHagaaatgcYNggcgtttttMtStggtRatctacttaaatVVtBacttHNttttaRca
+aatcacagHgagagtMgatcSWaNRacagDtatactaaDKaSRtgattctccatSaaRtt
+aaYctacacNtaRtaactggatgaccYtacactttaattaattgattYgttcagDtNKtt
+agDttaaaaaaaBtttaaNaYWKMBaaaacVcBMtatWtgBatatgaacVtattMtYatM
+NYDKNcKgDttDaVtaaaatgggatttctgtaaatWtctcWgtVVagtcgRgacttcccc
+taDcacagcRcagagtgtWSatgtacatgttaaSttgtaaHcgatgggMagtgaacttat
+RtttaVcaccaWaMgtactaatSSaHtcMgaaYtatcgaaggYgggcgtgaNDtgttMNg
+aNDMtaattcgVttttaacatgVatgtWVMatatcaKgaaattcaBcctccWcttgaaWH
+tWgHtcgNWgaRgctcBgSgaattgcaaHtgattgtgNagtDttHHgBttaaWcaaWagc
+aSaHHtaaaVctRaaMagtaDaatHtDMtcVaWMtagSagcttHSattaacaaagtRacM
+tRtctgttagcMtcaBatVKtKtKacgagaSNatSactgtatatcBctgagVtYactgta
+aattaaaggcYgDHgtaacatSRDatMMccHatKgttaacgactKtgKagtcttcaaHRV
+tccttKgtSataatttacaactggatDNgaacttcaRtVaagDcaWatcBctctHYatHa
+DaaatttagYatSatccaWtttagaaatVaacBatHcatcgtacaatatcgcNYRcaata
+YaRaYtgattVttgaatgaVaactcRcaNStgtgtattMtgaggtNttBaDRcgaaaagc
+tNgBcWaWgtSaDcVtgVaatMKBtttcgtttctaaHctaaagYactgMtatBDtcStga
+ccgtSDattYaataHctgggaYYttcggttaWaatctggtRagWMaDagtaacBccacta
+cgHWMKaatgatWatcctgHcaBaSctVtcMtgtDttacctaVgatYcWaDRaaaaRtag
+atcgaMagtggaRaWctctgMgcWttaagKBRtaaDaaWtctgtaagYMttactaHtaat
+cttcataacggcacBtSgcgttNHtgtHccatgttttaaagtatcgaKtMttVcataYBB
+aKtaMVaVgtattNDSataHcagtWMtaggtaSaaKgttgBtVtttgttatcatKcgHac
+acRtctHatNVagSBgatgHtgaRaSgttRcctaacaaattDNttgacctaaYtBgaaaa
+tagttattactcttttgatgtNNtVtgtatMgtcttRttcatttgatgacacttcHSaaa
+ccaWWDtWagtaRDDVNacVaRatgttBccttaatHtgtaaacStcVNtcacaSRttcYa
+gacagaMMttttgMcNttBcgWBtactgVtaRttctccaaYHBtaaagaBattaYacgat
+ttacatctgtaaMKaRYtttttactaaVatWgctBtttDVttctggcDaHaggDaagtcg
+aWcaagtagtWttHtgKtVataStccaMcWcaagataagatcactctHatgtcYgaKcat
+cagatactaagNSStHcctRRNtattgtccttagttagMVgtatagactaactctVcaat
+MctgtttgtgttgccttatWgtaBVtttctggMcaaKgDWtcgtaaYStgSactatttHg
+atctgKagtagBtVacRaagRtMctatgggcaaaKaaaatacttcHctaRtgtDcttDat
+taggaaatttcYHaRaaBttaatggcacKtgctHVcaDcaaaVDaaaVcgMttgtNagcg
+taDWgtcgttaatDgKgagcSatatcSHtagtagttggtgtHaWtaHKtatagctgtVga
+ttaBVaatgaataagtaatVatSttaHctttKtttgtagttaccttaatcgtagtcctgB
+cgactatttVcMacHaaaggaatgDatggKtaHtgStatattaaSagctWcctccRtata
+BaDYcgttgcNaagaggatRaaaYtaWgNtSMcaatttactaacatttaaWttHtatBat
+tgtcgacaatNgattgcNgtMaaaKaBDattHacttggtRtttaYaacgVactBtaBaKt
+gBttatgVttgtVttcaatcWcNctDBaaBgaDHacBttattNtgtDtatttVSaaacag
+gatgcRatSgtaSaNtgBatagttcHBgcBBaaattaHgtDattatDaKaatBaaYaaMa
+ataaataKtttYtagtBgMatNcatgtttgaNagtgttgtgKaNaSagtttgaSMaYBca
+aaacDStagttVacaaaaactaaWttBaagtctgtgcgtMgtaattctcctacctcaNtt
+taaccaaaaVtBcacataacaccccBcWMtatVtggaatgaWtcaaWaaaaaaaaWtDta
+atatRcctDWtcctaccMtVVatKttaWaaKaaatataaagScHBagaggBaSMtaWaVt
+atattactSaaaKNaactatNatccttgaYctattcaaaVgatttYHcRagattttaSat
+aggttattcVtaaagaKgtattattKtRttNcggcRgtgtgtWYtaacHgKatKgatYta
+cYagDtWcHBDctctgRaYKaYagcactKcacSaRtBttttBHKcMtNtcBatttatttt
+tgSatVgaaagaWtcDtagDatatgMacaacRgatatatgtttgtKtNRaatatNatgYc
+aHtgHataacKtgagtagtaacYttaNccaaatHcacaacaVDtagtaYtccagcattNt
+acKtBtactaaagaBatVtKaaHBctgStgtBgtatgaSNtgDataaccctgtagcaBgt
+gatcttaDataStgaMaccaSBBgWagtacKcgattgaDgNNaaaacacagtSatBacKD
+gcgtataBKcatacactaSaatYtYcDaactHttcatRtttaatcaattataRtttgtaa
+gMcgNttcatcBtYBagtNWNMtSHcattcRctttttRWgaKacKttgggagBcgttcgc
+MaWHtaatactgtctctatttataVgtttaBScttttaBMaNaatMacactYtBMggtHa
+cMagtaRtctgcatttaHtcaaaatttgagKtgNtactBacaHtcgtatttctMaSRagc
+agttaatgtNtaaattgagagWcKtaNttagVtacgatttgaatttcgRtgtWcVatcgt
+taaDVctgtttBWgaccagaaagtcSgtVtatagaBccttttcctaaattgHtatcggRa
+ttttcaaggcYSKaagWaWtRactaaaacccBatMtttBaatYtaagaactSttcgaaSc
+aatagtattgaccaagtgttttctaacatgtttNVaatcaaagagaaaNattaaRtttta
+VaaaccgcaggNMtatattVctcaagaggaacgBgtttaacaagttcKcYaatatactaa
+ccBaaaSggttcNtattctagttRtBacgScVctcaatttaatYtaaaaaaatgSaatga
+tagaMBRatgRcMcgttgaWHtcaVYgaatYtaatctttYttatRaWtctgBtDcgatNa
+tcKaBaDgatgtaNatWKctccgatattaacattNaaacDatgBgttctgtDtaaaMggt
+gaBaSHataacgccSctaBtttaRBtcNHcDatcDcctagagtcRtaBgWttDRVHagat
+tYatgtatcWtaHtttYcattWtaaagtctNgtStggRNcgcggagSSaaagaaaatYcH
+DtcgctttaatgYcKBVSgtattRaYBaDaaatBgtatgaHtaaRaRgcaSWNtagatHa
+acttNctBtcaccatctMcatattccaSatttgcgaDagDgtatYtaaaVDtaagtttWV
+aagtagYatRttaagDcNgacKBcScagHtattatcDaDactaaaaaYgHttBcgaDttg
+gataaaKSRcBMaBcgaBSttcWtgNBatRaccgattcatttataacggHVtaattcaca
+agagVttaaRaatVVRKcgWtVgacctgDgYaaHaWtctttcacMagggatVgactagMa
+aataKaaNWagKatagNaaWtaaaatttgaattttatttgctaaVgaHatBatcaaBWcB
+gttcMatcgBaaNgttcgSNaggSaRtttgHtRtattaNttcDcatSaVttttcgaaaaa
+ttgHatctaRaggSaNatMDaaatDcacgattttagaHgHaWtYgattaatHNSttatMS
+gggNtcKtYatRggtttgtMWVtttaYtagcagBagHaYagttatatggtBacYcattaR
+SataBatMtttaaatctHcaaaSaaaagttNSaaWcWRccRtKaagtBWtcaaattSttM
+tattggaaaccttaacgttBtWatttatatWcDaatagattcctScacctaagggRaaYt
+aNaatgVtBcttaaBaacaMVaaattatStYgRcctgtactatcMcVKatttcgSgatRH
+MaaaHtagtaaHtVgcaaataatatcgKKtgccaatBNgaaWcVttgagttaKatagttc
+aggKDatDtattgaKaVcaKtaataDataataHSaHcattagttaatRVYcNaHtaRcaa
+ggtNHcgtcaaccaBaaagYtHWaaaRcKgaYaaDttgcWYtataRgaatatgtYtgcKt
+aNttWacatYHctRaDtYtattcBttttatcSataYaYgttWaRagcacHMgtttHtYtt
+YaatcggtatStttcgtRSattaaDaKMaatatactaNBaWgctacacYtgaYVgtgHta
+aaRaaRgHtagtWattataaaSDaaWtgMattatcgaaaagtaYRSaWtSgNtBgagcRY
+aMDtactaacttaWgtatctagacaagNtattHggataatYttYatcataDcgHgttBtt
+ctttVttgccgaaWtaaaacgKgtatctaaaaaNtccDtaDatBMaMggaatNKtatBaa
+atVtccRaHtaSacataHattgtttKVYattcataVaattWtcgtgMttcttKtgtctaa
+cVtatctatatBRataactcgKatStatattcatHHRttKtccaacgtgggtgRgtgaMt
+attattggctatcgtgacMtRcBDtcttgtactaatRHttttaagatcgVMDStattatY
+BtttDttgtBtNttgRcMtYtgBacHaWaBaatDKctaagtgaaactaatgRaaKgatcc
+aagNaaaatattaggWNtaagtatacttttKcgtcggSYtcttgRctataYcttatataa
+agtatattaatttataVaacacaDHatctatttttKYVatHRactttaBHccaWagtact
+BtcacgaVgcgttRtttttttSVgtSagtBaaattctgaHgactcttgMcattttagVta
+agaattHctHtcaDaaNtaacRggWatagttcgtSttgaDatcNgNagctagDgatcNtt
+KgttgtaDtctttRaaYStRatDtgMggactSttaDtagSaVtBDttgtDgccatcacaM
+attaaaMtNacaVcgSWcVaaDatcaHaatgaattaMtatccVtctBtaattgtWattat
+BRcWcaatgNNtactWYtDaKttaaatcactcagtRaaRgatggtKgcgccaaHgaggat
+StattYcaNMtcaBttacttatgagDaNtaMgaaWtgtttcttctaHtMNgttatctaWW
+atMtBtaaatagDVatgtBYtatcggcttaagacMRtaHScgatatYgRDtcattatSDa
+HggaaataNgaWSRRaaaBaatagBattaDctttgHWNttacaataaaaaaatacggttt
+gHgVtaHtWMttNtBtctagtMcgKMgHgYtataHaNagWtcaacYattaataYRgtaWK
+gaBctataaccgatttaHaNBRaRaMtccggtNgacMtctcatttgcaattcWgMactta
+caaDaaNtactWatVtttagccttMaatcagVaagtctVaaDaBtattaattaYtNaYtg
+gattaKtaKctYaMtattYgatattataatKtVgDcttatatNBtcgttgtStttttMag
+aggttaHYSttcKgtcKtDNtataagttataagSgttatDtRttattgttttSNggRtca
+aKMNatgaatattgtBWtaMacctgggYgaSgaagYataagattacgagaatBtggtRcV
+HtgYggaDgaYaKagWagctatagacgaaHgtWaNgacttHRatVaWacKYtgRVNgVcS
+gRWctacatcKSactctgWYtBggtataagcttNRttVtgRcaWaaatDMatYattaact
+ttcgaagRatSctgccttgcRKaccHtttSNVagtagHagBagttagaccaRtataBcca
+taatSHatRtcHagacBWatagcaMtacaRtgtgaaBatctKRtScttccaNaatcNgta
+atatWtcaMgactctBtWtaaNactHaaaaRctcgcatggctMcaaNtcagaaaaacaca
+gtggggWttRttagtaagaVctVMtcgaatcttcMaaaHcaHBttcgattatgtcaDagc
+YRtBtYcgacMgtDcagcgaNgttaataatagcagKYYtcgtaBtYctMaRtaRtDagaa
+aacacatgYaBttgattattcgaaNttBctSataaMataWRgaHtttccgtDgaYtatgg
+tDgHKgMtatttVtMtVagttaRatMattRagataaccctKctMtSttgaHagtcStcta
+tttccSagatgttccacgaggYNttHRacgattcDatatDcataaaatBBttatcgaHtN
+HaaatatDNaggctgaNcaaggagttBttMgRagVatBcRtaWgatgBtSgaKtcgHttt
+gaatcaaDaHttcSBgHcagtVaaSttDcagccgttNBtgttHagYtattctttRWaaVt
+SttcatatKaaRaaaNacaVtVctMtSDtDtRHRcgtaatgctcttaaatSacacaatcg
+HattcaWcttaaaatHaaatcNctWttaNMcMtaKctVtcctaagYgatgatcYaaaRac
+tctaRDaYagtaacgtDgaggaaatctcaaacatcaScttcKttNtaccatNtaNataca
+tttHaaDHgcaDatMWaaBttcRggctMaagctVYcacgatcaDttatYtaatcKatWat
+caatVYtNagatttgattgaYttttYgacttVtcKaRagaaaHVgDtaMatKYagagttN
+atWttaccNtYtcDWgSatgaRgtMatgKtcgacaagWtacttaagtcgKtgatccttNc
+ttatagMatHVggtagcgHctatagccctYttggtaattKNaacgaaYatatVctaataM
+aaaYtgVtcKaYtaataacagaatHcacVagatYWHttagaaSMaatWtYtgtaaagNaa
+acaVgaWtcacNWgataNttcaSagctMDaRttgNactaccgataMaaatgtttattDtc
+aagacgctDHYYatggttcaagccNctccttcMctttagacBtaaWtaWVHggaaaaNat
+ttaDtDtgctaaHHtMtatNtMtagtcatttgcaaaRatacagRHtatDNtgtDgaatVg
+tVNtcaaatYBMaaaagcaKgtgatgatMgWWMaHttttMgMagatDtataaattaacca
+actMtacataaattgRataatacgBtKtaataattRgtatDagDtcRDacctatRcagag
+cSHatNtcaScNtttggacNtaaggaccgtgKNttgttNcttgaaRgYgRtNtcagttBc
+ttttcHtKtgcttYaaNgYagtaaatgaatggWaMattBHtatctatSgtcYtgcHtaat
+tHgaaMtHcagaaSatggtatgccaHBtYtcNattWtgtNgctttaggtttgtWatNtgH
+tgcDttactttttttgcNtactKtWRaVcttcatagtgSNKaNccgaataaBttataata
+YtSagctttaaatSttggctaaKSaatRccgWHgagDttaaatcatgagMtcgagtVtaD
+ggaBtatttgDacataaacgtagYRagBWtgDStKDgatgaagttcattatttaKWcata
+aatWRgatataRgttRacaaNKttNtKagaaYaStaactScattattaacgatttaaatg
+DtaattagatHgaYataaactatggggatVHtgccgtNgatNYcaStRtagaccacWcaM
+tatRagHgVactYtWHtcttcatgatWgagaKggagtatgaWtDtVtNaNtcgYYgtaaa
+ctttaDtBactagtaDctatagtaatatttatatataacgHaaaRagKattSagttYtSt
+>THREE Homo sapiens frequency
+agagagacgatgaaaattaatcgtcaatacgctggcgaacactgagggggacccaatgct
+cttctcggtctaaaaaggaatgtgtcagaaattggtcagttcaaaagtagaccggatctt
+tgcggagaacaattcacggaacgtagcgttgggaaatatcctttctaccacacatcggat
+tttcgccctctcccattatttattgtgttctcacatagaattattgtttagacatccctc
+gttgtatggagagttgcccgagcgtaaaggcataatccatataccgccgggtgagtgacc
+tgaaattgtttttagttgggatttcgctatggattagcttacacgaagagattctaatgg
+tactataggataattataatgctgcgtggcgcagtacaccgttacaaacgtcgttcgcat
+atgtggctaacacggtgaaaatacctacatcgtatttgcaatttcggtcgtttcatagag
+cgcattgaattactcaaaaattatatatgttgattatttgattagactgcgtggaaagaa
+ggggtactcaagccatttgtaaaagctgcatctcgcttaagtttgagagcttacattagt
+ctatttcagtcttctaggaaatgtctgtgtgagtggttgtcgtccataggtcactggcat
+atgcgattcatgacatgctaaactaagaaagtagattactattaccggcatgcctaatgc
+gattgcactgctatgaaggtgcggacgtcgcgcccatgtagccctgataataccaatact
+tacatttggtcagcaattctgacattatacctagcacccataaatttactcagacttgag
+gacaggctcttggagtcgatcttctgtttgtatgcatgtgatcatatagatgaataagcg
+atgcgactagttagggcatagtatagatctgtgtatacagttcagctgaacgtccgcgag
+tggaagtacagctgagatctatcctaaaatgcaaccatatcgttcacacatgatatgaac
+ccagggggaaacattgagttcagttaaattggcagcgaatcccccaagaagaaggcggag
+tgacgttgaacgggcttatggtttttcagtacttcctccgtataagttgagcgaaatgta
+aacagaataatcgttgtgttaacaacattaaaatcgcggaatatgatgagaatacacagt
+gtgagcatttcacttgtaaaatatctttggtagaacttactttgctttaaatatgttaaa
+ccgatctaataatctacaaaacggtagattttgcctagcacattgcgtccttctctattc
+agatagaggcaatactcagaaggttttatccaaagcactgtgttgactaacctaagtttt
+agtctaataatcatgattgattataggtgccgtggactacatgactcgtccacaaataat
+acttagcagatcagcaattggccaagcacccgacttttatttaatggttgtgcaatagtc
+cagattcgtattcgggactctttcaaataatagtttcctggcatctaagtaagaaaagct
+cataaggaagcgatattatgacacgctcttccgccgctgttttgaaacttgagtattgct
+cgtccgaaattgagggtcacttcaaaatttactgagaagacgaagatcgactaaagttaa
+aatgctagtccacagttggtcaagttgaattcatccacgagttatatagctattttaatt
+tatagtcgagtgtacaaaaaacatccacaataagatttatcttagaataacaacccccgt
+atcatcgaaatcctccgttatggcctgactcctcgagcttatagcatttgtgctggcgct
+cttgccaggaacttgctcgcgaggtggtgacgagtgagatgatcagtttcattatgatga
+tacgattttatcgcgactagttaatcatcatagcaagtaaaatttgaattatgtcattat
+catgctccattaacaggttatttaattgatactgacgaaattttttcacaatgggttttc
+tagaatttaatatcagtaattgaagccttcataggggtcctactagtatcctacacgacg
+caggtccgcagtatcctggagggacgtgttactgattaaaagggtcaaaggaatgaaggc
+tcacaatgttacctgcttcaccatagtgagccgatgagttttacattagtactaaatccc
+aaatcatactttacgatgaggcttgctagcgctaaagagaatacatacaccaccacatag
+aattgttagcgatgatatcaaatagactcctggaagtgtcagggggaaactgttcaatat
+ttcgtccacaggactgaccaggcatggaaaagactgacgttggaaactataccatctcac
+gcccgacgcttcactaattgatgatccaaaaaatatagcccggattcctgattagcaaag
+ggttcacagagaaagatattatcgacgtatatcccaaaaaacagacgtaatgtgcatctt
+cgaatcgggatgaatacttgtatcataaaaatgtgacctctagtatacaggttaatgtta
+gtgatacacaatactcgtgggccatgggttctcaaataaaatgtaatattgcgtcgatca
+ctcacccacgtatttggtctaattatgttttatttagtgacaatccaatagataaccggt
+cctattaagggctatatttttagcgaccacgcgtttaaacaaaggattgtatgtagatgg
+taccagtttaattgccagtgggcaatcctaagcaaaatgagattctatcctaaagtttgg
+gcttgatataagatttcggatgtatgggttttataatcgttggagagctcaatcatgagc
+taatacatggatttcgctacctcaccgagagaccttgcatgaagaattctaaccaaaagt
+ttaataggccggattggattgagttaattaagaccttgttcagtcatagtaaaaaccctt
+aaattttaccgattgacaaagtgagcagtcgcaataccctatgcgaaacgcctcgatagt
+gactaggtatacaaggtttttgagttcctttgaaatagttaactaatttaaaattaatta
+acgacatggaaatcacagaacctaatgctttgtaggagttatttatgctgtttactgcct
+ctacaaccctaataaagcagtcctaagaatgaaacgcatcttttagttcagaaagtggta
+tccagggtggtcaatttaataaattcaacatcgggtctcaggatattcggtcatataatt
+tattaagggctcttcgagtcttactctgagtgaaattggaaacagtcatccttttcgttg
+tgaggcatcttacaccgctatcgatatacaatgcattccaccgcggtgtcccgtacacaa
+ggaaacttgttaccttggggatataagaaaactcacacgtctcattattaaactgagtac
+aatttttgcacgagaaagtaatgcaatacaatatgatgaaagccagctaatgaaaaggga
+tggaacgcacctcggatctgttgcactggattaaaatccgattatttttaaaaatattca
+gtgctagagcatatcaggtctacttttttatctggtatgtaaagcccacggagcgatagt
+gagatccttacgactcaacgaaaagttataacataactcccgttagccaaagcccaatcc
+cgattactgccctaccctaacgtctgccatctaaatatcgaacttgttatgatcaatgtg
+actacctcccaccctttccccttcatttgttccactggggataagctagcgttttcagaa
+tcaatgcaataagaatagccaattgtctcacttcatcagagctcttggcaattccaggcg
+ctacgtggttctggaatatattcatttttcaaatagtaatacgtttagtgttgctattgt
+ctacacgtttggatattacgttatgtgagcggacatcaatagttgtctaactctttagta
+agccagagatagcactcttagcgaatggataccatcttccataagtttagttaatagtcc
+gaaacaactgcttcgagcatatttgaacctccttgtaggcaaatagcctcttcaaagcaa
+tcttactaatagatagagtttgttttaagggactactagaaatgggacaatcttaatagt
+atgacctaaactgacatttaaagatatatccaggtggcaagcataaagatcattgcgcca
+cctccaccgtgggattacttatcagtcgatatcctatatgctaagtttgcgacggcagaa
+tacaaactaagctgagttgatgctaaccttacctatgataccccattggaccggttaaca
+gccctacttattccaaataaaagaacttttatgctgtagaagctattatagtgatgcctg
+gtaacttcagtatattaaaatgacacacatacgccatatagagctcctggaactttgaat
+aatgagcgaacttcgaagttgaagagcaagaaaccatatgtcacggttgcctaaagcccg
+gtaaccagacatgtgctatcattgatcattatcgaggttttcataaccttgacccattat
+cggctgtgcgcggacaagtacttaaatcactagtttcttcacctgcttatcggtaagaaa
+taaggttggcaaagaatcgcataagacggacgtagagccgcagcgttgtgcgagtccagg
+tgcatgcgcagcaataggattttaaattttgttccatttttaatttagccgtaaggatgt
+ccgtaaatgattgaaaattggattcaatctttgggcctatgctactggaacctgatcgac
+aaaatttcaaacatacgttaactccgaaagaccgtatttttgcggctagaatagtcagtc
+gcttggagccatataccttaccacttaaacgacgtgctcctgtagttgaaatataaacag
+aacacaaagactaccgatcatatcaactgaagatctttgtaactttgaggcgaagcaccc
+tcttcgagacaactaagagtaaagtaccgggcgccgcaaggagtcgattgggaccctaaa
+tcttgacgaattgctaagaggctcagagctaccactgtaatttctctagagcccataata
+aatgaacgatacatccgtaggtagcacctaagggattataatggaagccaaatgcagtta
+ataatattatatactggcgtacacgattcgacggatctctcacatagtgattcacgaccc
+ccccctttgattgacacagcgtcagcattttgcaagaacgatcttctgcatagggtgcgc
+caccgtaaggatgacgtcgaagctacaactgggtataatttaccatgcttccctgatgct
+gagtgcaatacactaagaatgagtttttaccccatatcaccagtatttgttctgttattg
+cgaagaaatggctatgctgagttggcgactaaagtcacccatcctttttattaggtaacc
+ccctcccttaaactaactgatttgctggagctgccctgcatacatatactttatcattta
+tggacgtccgtgacgcttattatccaccatagtcgatatgctacacggattcattaatgg
+atcgtaggagtttaagttatatttactaagatcggtctcggctactatcccgccttaccc
+ggcgctatttacggccatttttaatatattgacggtaattattcctatggtttcgaccgc
+acgtccttggacaagaaagaatggcaaaaaaaatgtaaaagaaaaaaaatattgagtccc
+taccatcatataaaaaatatgtgatgagtaacttgacgaaatgttagtggttattaaaga
+ctatctattacaccttttgttttctgtcgtagtatattaaagtctagaagccttacagga
+aaatcagggttatacagccgatactccgcagcatgaatcatcgaggaggtgtcctaccat
+cgcgccttgtaatcttgtctgtgtatactgtatttagaccttttatacaaagtaaatatc
+tcggctttatgtgattgggaggggcctactcaaacatgatgacttgacctaataatcact
+gtgcgggcgtcttatgactagctattccttgaaatccaccaccaaatggttaatatgtaa
+aaactttgacgatgaaacaaggtgaatgtgtagttactttgtgtaattagctgcgtcgag
+cattgcttgtaaaaccgtcaatcgcacacgttacttccataaaatttctacgaatacacc
+cttcttaaaaaaaacgtaggaattcacgagtttaacaaacgataactgtataaagtggaa
+gtccgaagaaagcagatgcccgaactactcgaagatgtttcgttttcttaaccatagggg
+cttcttaatggcccactacgcacattttgttcaagcccgagagggacatccccattacgg
+gagtattactaaaactgttccgtaatacgttcagcaagggatgaaaaaggccactgctca
+agttattgacgtgggagtattacatcggaagcctgaatcccacactatgatggtctgtac
+aggcctagggactgcgtctagacggtattaccggcttctaatcatacgatcgtgagtctt
+aacgggaagtaaggctcacacctaccccaaaccatttatctatgtaagtataaaattgtg
+cgtaagtgttcaaagtggacaataaagacgtggcaaaaacccccgcacataagccgcttt
+agatttcacaaataccaatgcggttaaaaacatccttgagtcgtacatacaccatactcg
+cgttaaacggatataacagaagataataaatccggatgtggagtcggtgtaactatagaa
+agccaagtgaaataatgcttaccagtcatttagctatacggctttcatttcatgtcaaga
+gggtggagtttgacctgtacagttgatatatcaccgatacttagaactcacctaaagcta
+aaattgctcgcagcgtgtaatccgcatattacaaacaatagatgggattcattatacata
+agacacgatgatctgctttttcaggttgcgagatgttgcctatcgtcaatcgagtcctgc
+cttacaccacttaaacaaaagtattgacagggaacctattttcgaggtattatatagtcc
+agcttgaatatcaatttgacagttaacctagtgaaaatcagtaagaggaaatacgccaca
+ttctccagtgaaattctacgggttatcgtctagtccaactatcaattataactcacgaga
+tataagtaaattctcgtacttggcctgatttttattatactttggatccttagtaaacag
+gaagggagaaaccttcaacgaaaaacactggattttgttttactctcaaagctcttatat
+gacggaaataccctgtcaagtcttaactttattactagactaatgaaatgggcttggggt
+ggccagaatcatagtacaatttagcggatacactattcggactttcctatcggctgtctg
+gttggataagtatggggactaataggctagacatacctatacttaaactatacaggcgtc
+atctatctctgcaactttggagttccctgatgttctcccgccctttgggttcacatcttc
+tataccgacacccctaataacgattagtttgtgggttagagtaaattaatacggttaata
+ttaatgtatcgttgaaaagctggtgtcgccaataaggtaaccggctaggcagagtatatg
+tcacgaagtataactaccctaatgataagctgtaggaataaaattaatgctgtctctaag
+cgaagagatatttccgactctgttttaatgacgaatctcattacttctgacttgcaaatg
+ttcaatatggcacggtttcacggcacctttgtgacgcatataatgaacttagaagattat
+aacgacggaactttatatgataatccgttacgattaaagaatctgttaaatatcataatg
+gcattcagttctagaccgtgcatcatggtaaacttactttctctgcatggcgacatacat
+ttcgctattcaaattcgcgtgtggttacacccactcgcacctttggaatattaagagaag
+atgatcagaaaatccattcgctcaatttttctgacgtacgtctaatttatcctaggagac
+aaatcgttttatgtctctcacatttttgaagaaaggttcgagagacaatactcaggtcct
+gaactgctagaagatactcggtggagcgtggcaacaatgaaaaactcgtgacataaatga
+atgatacttttccaagttcagttaagtgaatatgtttaacatacccggcttttcgatctt
+aagctgacgctggacgtgcgagtaatgtcagtctcttacatacactagtgactccaagtt
+tcgtcaaaaacgccccctcccttctcgagcccactcacgctatgtattgacgcgaacttg
+ttcgggatcagacttttcaggagttcggtcgcgtgtccctatgtgctaatatataagtta
+gatcgcattagatgctaatctgaatacttatagacgaccttcaacgagaacgggtaccac
+cttgaggctagagttaggtgtgaaacgacaggtagggacatataaaatttgagtgcggct
+ttagttaagggtttaattacctactcaaacatcacgctcgcgcccttcgtacgtaatcga
+ccatctagaggctaaggggactgtactaggtagtgattaatgatatcctagacgcacgtg
+ccttagatcttcagactctgatggtccgcgatcaccgtaattgtagtcctccaactcgat
+cactttgttggcgtcaaagaaattacgatatctaaatacttataatacaataaccaagga
+tgagaatgactcatcgcgttggagttatattgcttgaagttctatggaatgaaagcacgt
+tatctgccgtcccaatatctccagtgagctaattcattggacggtccactttgatcaatc
+cccgaggagatgttcggacactttagtctgtaacacttagcgttgagaccacgaacaatt
+gattactcagtcttgaaggtgttttccaaagttcattttaaataagactacgataggcct
+ttcctattgatataaactacccggctctgttgttcgtgtgagtcgtacttctctgtgttt
+ttctgattatagcaagattcgattcttagtgtaaacagcgatttttatttgacccgtcaa
+tgagaagcgcataggatctaagcaaaattatcaagttgtgccacaaggtaagatctttcc
+agttattgcaggtaggatgtatcccacgttgatagtatgaggtctgacgtcaactgtcta
+ggagagttgaccgcgtgcgggtacaccggatttgcatcgatgttgagaacgcagaactcc
+cactgtcgtggcggcgttcctgatatttagcaagaggcgttgataaagccctcatcatct
+agatctcgacctcatctgccctcttgctccatcattttctacacagactactttcctatc
+tacgttagtataattgctttctatcttagtatcatttagagcttctccgtcaacaggttc
+gtgctattaaagttagtacgaaagggacaacttgtagcaacgcatttaatcggttttcga
+ctacttcgcacaaaatcagataaagaagtttgtcattctattagacattgaattgcgcaa
+ttgacttgtaccacttatgatcgaacactgaatcaagactgtgattaactaaaatagaca
+agccactatatcaactaataaaaacgcccctggtggtcgaacatagttgactacaggata
+attaattggactggagccattacattctctacaatcgtatcacttcccaagtagacaact
+ttgaccttgtagtttcatgtacaaaaaaatgctttcgcaggagcacattggtagttcaat
+agtttcatgggaacctcttgagccgtcttctgtgggtgtgttcggatagtaggtactgat
+aaagtcgtgtcgctttcgatgagagggaattcaccggaaaacaccttggttaacaggata
+gtctatgtaaacttcgagacatgtttaagagttaccagcttaatccacggtgctctacta
+gtatcatcagctgtcttgcctcgcctagaaatatgcattctatcgttatcctatcaacgg
+ttgccgtactgagcagccttattgtggaagagtaatatataaatgtagtcttgtctttac
+gaagcagacgtaagtaataatgacttggaataccaaaactaaacatagtggattatcata
+ctcaagaactctccagataaataacagtttttacgatacgtcaccaatgagcttaaagat
+taggatcctcaaaactgatacaaacgctaattcatttgttattggatccagtatcagtta
+aactgaatggagtgaagattgtagaatgttgttctggcctcgcatggggtctaggtgata
+tacaatttctcatacttacacggtagtggaaatctgattctagcttcgtagctgactata
+ctcaaggaaccactgctcaaggtaggagactagttccgaccctacagtcaaagtggccga
+agcttaaactatagactagttgttaaatgctgatttcaagatatcatctatatacagttt
+ggacaattatgtgtgcgaaactaaaattcatgctattcagatggatttcacttatgcctt
+agaaacagatattgcccgagctcaatcaacagttttagccggaaacaatcgaagcatagg
+gacaatgtatcttttcctaaattgccatgtgcagatttctgagtgtcacgaagcgcataa
+tagaatcttgtgttgcctcaactcgttgaaaagtttaaaacaatcgcagcagtctttttg
+gggtctactgtgtgtttgcaaaataactgaaagaaacgcttgaacaactctgaagtagct
+cgagtactcattaaagtgtaacacattagtgaatatcggccaatgaaccaaacgcttccc
+ggtacgctatctctctcatcgggaggcgatgtgcaggttatctacgaaagcatcccttta
+cgttgagagtgtcgatgcatgaacctcattgtaacaatagcccagcaaattctcatacgt
+gcctcagggtccgggcgtactcctccatggaagggcgcgcatctagtgttataccaactc
+gctttttaactactatgctgtagttctacaggcatagtggccagtattttctaacttctc
+tggatagatgctctcactcctcatccatcacggcttcagtttacgtcttacttgcttgtt
+cagcaacggatggaggcattaagtatcttcactgttccctaaaattgctgttcaatatca
+aagtaaggacgatacagggaaagctcaagcacactcattgaatactgccccagttgcaac
+ctcacttaatctgacaaaaataatgactactctaagtgttgcggaagcagtctcttccac
+gagcttgtctgtatcacttcgtataggcatgtaactcgatagacacgaacaccgagtgag
+aaactatattcttgcttccgtgtgtgtgacaccaggtaattgatgcggatataagctgga
+gatcactcacgcccacacaaggcgctgctacctctttattccaatgtgtaagaatttgct
+aacttcatttctagaccgcagctttgcggtcataatttcacggtacggacccttgggtta
+gagacttgataacacacttcgcagtttccaccgcgcacatgttttagtggcttctaacat
+agaatttttgttgtgacataaagagtgcgtgggagacttgcccgaccgttaagccataat
+caattgaaagccccgtgagtcacatctaattggttgtactgcgcatttagctatccttta
+gctgactcgaagagattcgattcctaatataggttaattagatggctgccgcgcgaagta
+aaacgtgaaaaacgtagtgcgcagatctgcataactcgcgcttaattacttatgagtagt
+tccaagttcgctacgttatgagagagattggaattaagcaaatatgttttatggtgattt
+tgggatgagaaggactgctaagtacggctactaaacaaatttctaaaaccgccatctacc
+ttatcttggagacatttaagttgtatatgtcactagtctagcttttgtctgtgggacgcg
+ttctcggaatgagggaaatgcaagagccgattcatcaaatgcttatctaagaaagtagtg
+gactattacaccaagcacgaatgccagggaactgctttcttgctcaggacctcgcgacaa
+ggtaccccgcataagtcctagaattacatttggtcagcaatgctgacatttgaccgtgaa
+aacataattttaatcagaaggcagctcacccgcttgctctagatcttatctttgtatgaa
+tgtcagaatttactgcaatatccgttccgaatagtgagggcttagtatagttctctgtat
+acaggtcacatcaaactccccctgtcctagtacagctctgagctttaattaattgcatac
+atttccttcaatcatcagatgaaaacaccgcgaatcatgctcttctcgtatagggcaaga
+gaagcaacaaacaactagcccgactcacgttcatccgccgtatccttgttcagttcttac
+tccgtattaggtcagcgaaatctaatcagaataatcggtcgcgtatcaaaattaaaatcc
+cgcttgaggttgacaattaaaacgctgagcagttatcggctattagatagtggggtgaaa
+gtaattggctggaattatgttaaaacgtgatattaagctaaaatacgctacttgttgccg
+acctaattcagtcattcgatattcagttagagccaagaataacaagcttgtataaattga
+acggggtgcactaaacgatgtgttactctaatattcagcttggagtatacctgaaggcga
+attcatgtatcggccaataataagacgttgaagatcacaatttggactagcaaaagaagg
+tgatttatgcgtggggattgagtccactgtacgagtacggtctctggaaaattataggtt
+cagggaatataaggaagtaaagataattaccaagagatttttggtatcgctatgacccag
+aggtgttctaacgtctgttttgatccgcagaatttctgcctcaatgcatatttgacggac
+ttgaactagagcctctaaagttaaatggcgacgcaactgttcctaaacttcaattattac
+tactctttttttcctagggtattgtagaggccagtggacaaaataaatcaaatttaagat
+gtttcggacattaacatcccccgtagcatagaaatcatcagttatccaatctctcatcga
+gcttttacaatttctgctggcgctatggacagcatatgccgcgagacctccgcaagactc
+acttgatcactgtaagtatcttcattagaggttagagcctatagttaagctgctgaccta
+gtaaaattggtattttctaattttattgctcaagttaaaggttagtgaagggataatgac
+gttatttttgaacaatgggttgtattcaattttatatcacgaatggaacccttcattccc
+ggcataatactagacgacacgaacaagctccgatctatcagccaggcacgtgttaaggtt
+taattccggcaaaccaatgaagcatcaaaaggtgacctgatgcaacttagggtcacgatg
+agtttttcaggactacttattacctattaataagttaacatgagccttcataccccgtaa
+gacaatacatactccaccaattagaattctgagccatcttatctttttgtatcatcgaag
+ggtatggccgaataggttaattagttactcctaacgtctctacaggcatgcatttgacgc
+accttcgaaaatagtcaatctctcgccacacgcgtctagtatgcagcatcaaaaatatag
+tccacggtttccggattaccaaacgcggcaaagagaaacattgtatcgacggagataact
+taatacagaaggaaggggcatcttcgaatacggatgaataattctatctgtttattctga
+catcttgttttcaggttaatcttacgcattcaaatgacgcctgccccatgcgtgcgcaat
+tattttctaatattgacgagagcaatctcactccttttgggtctatttatgttttattga
+ggcacaagcctatacagaacaggtactattaaggccgtgagtgtgagactcaaaccgtgg
+aaacaaaggatgggttgttcttggtacaagttttagtgcatgtgggcaatccttaccaaa
+atcagatgctatccttaactttgggctgcatttaagatggcggttggaggcctgtgagaa
+tcctgcgtgtcatctttaatgaccgaattcatccatgtagattcagatcacacactcatt
+ccttgatgttgtctaaacaaaagttgttgtggacgcattggagggagttaagtaacaact
+tgggatcgcatacttataaaaattatatgttaaactttcacaaacgctgaagtccaaagt
+aactagcccaaacgcctcgagagtcactaggtattaatggtgtttgagttcctgtgaaat
+agtgttcgaaggtaaaatttatgtaccaaatcgaaagaacacttaataaggcttgcttgc
+acggaggtatgatgtttactgactctacaaccctaattttccagtacgtacattcattcc
+aataggttagttctcaaagtgctatacaggctcctcaattgatgatatgcttcagccgct
+ctatggatattagctcattttatttaggaagcccgcttagaggcttactatgagggaaat
+gccaaaatgtcatacttttcggtgtgtcccatatgacaccgctttacatagaatttgaat
+taaaacgcgctctcccgttcactaccatacttggtaccgtgcgcatattacatatagata
+taggatcattttttaaagctgtactaggtttgatcgacaatcttatgctatactatatga
+tgtaaccctcataatcaataccgatcgtacgatcctagcataggtggcaagcgattttat
+gccgattattgtgttaaatagtctgtgagtgtgattatcagggctacgttggtagagggg
+ttgtatagacctcgcacacattgtgacatacttaacaatatacgaaaactgatataataa
+atccccttacccaaacaccaatcccgttgaatcaactaccataacgtctcccatataaat
+tgcctacttgtttgcataaatctgaatacataacaccattgcaccttcttgtgttccaat
+cccgttaagattgccttgtcagatgatatgcaagaacaatagcatttgctagcaattatt
+aacagctcttcgaattgcctccacataacgcgggagggtatattttaatttggcaaatac
+taagtactgttggcgtcatatgctattaacggttggatattaagttatgtcagccgtaag
+caagagtgggcgaaatattttgttacccagtgagagcactcttagagtttggatacaata
+ggccatatgttgacttaagaggacgtaactacgccgtacaccattgttcaaccgacttct
+tggcaaatagaatcgtattagcaatcttaagaatagagacacgttcgtgttagggtatac
+tacaaatccgaaaatcttaagaggatcacctaaactgaaatttatacatatttcaacgtg
+gatagatttaacataattcagccacctccaacctgggagtaattttcagtagatttacta
+gatgattagtggcccaacgcacttgactatataagatctggggatcctaacctgacctat
+gagacaaaattggaaacgttaacagcccttatgtgtacaaagaaaagtaagttgttgctg
+ttcaacagatgatagtcatgacgcgtaacttcactatagtaaattgaaacaaatacgcaa
+tttagacagaatggtacggtcatgaatgacagtaattcgaagtgctagaccaacttaaaa
+taggtaaacgtgcccgaaaccccccttaacagaaagctgctatcatggtgcagtatcgac
+gtgttcagaaacttgtaacttttgagcaggtccgagcacatggaagtatatcacgtgttt
+ctgaaccggcttatccctaagatatatccgtcgcaaactttcgatttagtcccacgtaga
+gcccaagcgttgtgcgactccacgtgcatgcccagaaatacgagtttaaatttggttaca
+tggttaattttgaccgaagcatcgcactttatgattgataattggattcaatatgtcgcc
+ctatgcgaatgcaacatgatccacaatttggctataagacgtttaatccgtatcacactt
+tgtttgcggctagtatagtaacgcccgtgcaccaagagtcagtaacaattataagtactc
+cgcaggtacttcaaatataaaaactaatcaaacacgacccatatgatcatctgaagatat
+ttggaactttctcgacaaccaccctcgtactcaatacttacactaatcgacaggcacacg
+caacgtgtacagtcgcaccatattgagtcaagatttgcttagtggcgatgagcgtacacg
+cttatttctctagtcacaattagttatctacgagacatcacgagggagcaaataagcgat
+gttatggctacacataggcacgtatgaatatgatataagccagttaaacagtcgaaccat
+cgagcaaattctcatgcaccaacccacacgttgaggcacaaagagtaagctgtttgaatg
+taacttcttctgctgagcgggccccaacgtaaggatcaactagaagagaaaactcggtat
+tagtttaaatgcgtcacggagcatgagtgcatttcactaagaatgtctgtgtaaccaata
+taacatctatttgttatctgattgcctacttatggctttgcggtcgtggcgactaatgtc
+tccaatccttttgaggtcggtaccaactccctttaaattacgctgtgcaggctcatgcac
+tgcatacatatacggtagcaggtagggacctcacgcacccttattataatcaatagtagt
+tatcagtcaacgaggcaggaatgctgaggtcgaggtgttggtatattttctatgtgccgt
+ctaggcgactatcacgcattaccaggcgagatttaagccaattttgaatatagtcaacgt
+aatttttactatgggttccaccgaaacgccttgcacaactaagaatcccataaaatatcg
+atatcaaataaaagattgtgtcaataccttcatatatattttttcggttgactaacgtga
+actaaggttaggggttttgtatgtctatataggaaacagtttcttttctgtcctacttta
+gtaaagtcttcaagccttactccaaaatcacggtgattaagccgttactcagcagcatga
+ttctgcctgctcgggtcctaaaatccagccttgtaagagtcgctgtgtattagctaggga
+gacctttgttaaaaaggatatatcgcggcgggatgtgagtgcgtggcgcatactcaatct
+tcagctcgtgtcattataatatctctcccccacgcttttcactagatatgccgtgtaagc
+aaacaccttatgcttaatttcgaaaatattggtacttgaaaaaagctgtaggggtactta
+atgtctggtaggagatcaggagagaattgagtgtaaaaccgtaaagccctcacctgactt
+catgtaaatggcttagaagactccatgatttaataaatactacgaaggaaagactggatc
+taaagataactctagtaaggccaactcccttcaatgctgttgccagttataatccaagag
+ctgtccttttctgaaccatagcggcttctgaagcgaactagaagcaaagttggttctagc
+cagacagccacataccctgtacgggtgtattactaaaactggtccggtattagttcacca
+agggaggaattaggcaaaggatctaggtatgcaagtcggagtattacatccctaccctga
+atccatcaataggttcctctgtactggccttcgcaatgagtattcaaggttgtacagccg
+tataataataagatagtgactatgaacgggaagtaacccgctcaccttccccaaaacatt
+gttatatctaagtattaaagtctgccgtagtgttaatactcgaaaataaacaactggcaa
+attacaccgcacttaagccgcttttgatttatatttttccaatgcgcttttaaaaataat
+tcagtcctacatactaattaagacccttaaacggagatatcacaagttaagttttaacca
+tctcgactaggtggaactatagatacccaactcaatttatcattacctgtaatgttccta
+gaaggattgcatttcatgtcaagacggtggagtttcacagcgaaacttcagtgtgaacag
+attctgagaaatcacctaaacctattagtcagagcacccggttagaaccagttgtcaaaa
+aatagagcggttgcatgagacagaagtaacgatgagatccgttgtaacgttgagacatct
+ggcctatcgtcaatacagtcctcccttaaaaatatttttaaatactaggcaaacccaaca
+taggttagtcctatgtgatacgccacatggtatatcattttgtaacgttacctagggata
+atcaggaagtggaattacgcaaaagtagacagtgaaatgcttagggttatagtctagtcc
+aaagataaaggataaagcacgtcagagaactatattagccgaatgggaatcattgttagg
+agactgtggatcatgtctaaaaagcaacgcagaaacagtcatcgaaaaaatctcgttttt
+gtttgaatctaaaagagctttgatgaccgatagtacctgtatactagttactgtattacg
+tgtctaatgatttcggattggggtccccagaatcagacgtcattgtagacgattcaagtt
+taccaatttaatttcccagctctccttggagaactatcgccaataattgcagtcactttc
+cttttctgaaacgataaagccgtcagagttctctgcaacgttggacttacctgaggttct
+aacccactttcggttctaatagtagttaacgacacaacgaataacctttactgtggggct
+ttcacgatattttttcgcttattattaatggttacgtcataagctggtgtccaaattaag
+gttaccggcttcgcagagtagttgtatccaagtataacttccctaatcataagatcgagg
+tagaaaattaatgctgtctctaaccgaacagatatgtcccactatgtggtatggacgttg
+ctaattacttctgaagggaaattggtcattatggatacgtgtctaccatcaggtcggacg
+cagatatggttctgtcttcagttgatccaccgttctttataggataataactgacgatta
+aagattatggtaaatagattaagccaattctcttcttgtcagtgaagcatccttaactga
+cttgctctgcagcccctcatacatttagctattcaaagtaccggctcgtttcaaactctc
+ccacctttggaagaggttgtcaacttgataagtatatcatttacagcattttttcggacg
+tacctctaatgtttcattgcagaaaattagttttttctatcgcacattttgcaagtaacg
+ttagagacacaattatctgcgaatgaactgctagatctgacgaccgggagcctcgcaaat
+atcaaaaaagactgacatatatcaaggagtcgttgacaagtgctggtaagtcaattggtt
+tatctgtcccggcgtttcgatcttaagctgaccatgcacggcagagtaatgtcactctcg
+ttcttacaagtctgtctccaagggtcggcaaaaaagacccctccattctcgagcccactc
+acgatatgtagggacgacaacttgtgcggcttatgaattgtctggactgcgggcgagggt
+ccatatctccgaagttagaagggacatacctttagatgataagatcaattcttattgacg
+aaattcatccacaacggggaacaacttcaccctagacttacgtctgaaaagacacctagc
+gtcttataaaaggtcagtgccccgtttcgtaaggctggaattacctacgcaaacttaaac
+ctcgcgcccttccttacgtatcgacaagatagaggctatcgcgaatgtactacggaggca
+tgaatcatatactagaaccaagtgcctgtgatattaacaagatgatccgacgcgagcacc
+gtaattctaggcataaaactccagcaatttgggggccgaaaacaaatgacgttagctaat
+taattatatgacatgatcaaaggaggtcaatcacgcatcgagttcgacgtatattcattg
+aacttcgtgcgtttgaaagaaacttttatgaaggcaaaattgatcctgtctcctatttca
+tgcgtacctcctagttgataattccccgagcagtggttaggacacttttgtcggtatcaa
+gttccggtctcaaaacgtaaaattctgtaatctgtatggatggtctgtgaattagttaat
+ttttatgaagtcgtcgagacgcagttcctattgatttattctaaacggagatgtgcttcg
+tgggactcggaagtagatctgtgtttatgattattgctactttagatgctgactgttaac
+tccgtgttgtttttcaaccgtatatcacaaccgaattggatagaacctatagtttcaagt
+tctgccacaaggtatcatatttacagttagtgctggttgcttctttcaaacgtggtgagt
+ttgtgctatcacgtcaacggtagagctcagtggaccgagtgcgcgttcaaccctgttcca
+gagagggtgtgatagcacatataccacgctcgtcgaggcgttcatgatagtttgcaagag
+ccggtgttaaacacatattattattgttatccaactaatcggacctatgcataaagcatt
+gtctaaacagaataattgcctatatacggtagttttagtgatttatatcttagtatcagt
+tagagcttcgaactcttcaggttcctcatatttaacgttcttcgaaagcgaaaacttcta
+caaacgaatgtaagcggttttccaagtagtacctataaatcacagaaagatctgtctcag
+tatagttgaaatggtattcagctagtgacgtgtaccaattatcatagttcactcaagcaa
+gacgctcattaacgaatatagacaagacactatatcatataataaaaaagaacatggtgc
+tcgaacatagttgaattcaccatattgaaggggaatgctgacatgtaattcgctactaga
+cgatcaattccctacttgtcaaagttgaactggtacgttcttggaattaaatatgattgc
+gctggaccaaattgcgacttcttgagtttcagggcaaacgattgagccggaggatgtccg
+tctcttacctttcttgcttatgataaacgacggtccctgtacatcactgggaattctcag
+caaaaataattgggtaaatcgagactcgatgtattcggccacaaaggtgttagacgttaa
+agattattcaacggggcgataataggatcataaccggtatgcaagcgcattgaaagagcc
+atgagatccttatccgataaacgctgcacggtatgtgcagccttattgtcgatcacgaat
+ttataaatgtagtctgggctgtaagttgaagacctaagttataatgaagtgcaataccaa
+atcgattcatagtggattatcagactcaagatatctcctgataaattacagttgttaaga
+tacggataaaatgagatttaagattagcagcctctaatctgtttcaatcccgttggaatg
+tggtatgcgatcaaggttaagttaaaatcaagcctgtcttcagtcttgattcttgttctg
+ccatcgcatgcggtctacgtgagttaatatgtagcttacgttctagcttgtgctaatctg
+agtatagattcgtagaggaatattatcaagcttccacgcctcaacgtacgtgtattggtc
+acacaagacactaaaagtggaagtagcgtaaactatagtctagttgttaaatgctcagtt
+cttgttatattcgatatactcttggctaatttatgtctgagtatataaaattaatgatat
+taacttgcatttcacggatcccttagaaaaagattttgaccgagcgcattataaacggtt
+acaccgaatcaatagaagcatacccaatagctttctttgaatttattgcctgcgcaactt
+ggctgactctctagatccgaataattctatatggtcgtgacgaaactagttcattactgt
+ttaaaatgccaacatgtcttttgggccgataatggctctttgcaaaattactcaatgata
+cgattgatcaaagcggtagttgctagtggtagcatgtaagtctatcaaatgtctgattat
+ccgaaaatcttccaaaagagtccacgtaccatatctatctcatagcgacgcgaggggaac
+cttatctaactatcattccatttaccgggtgactctcgatgcaggatccgattgggataa
+attgcccagaaatggctcattcctgactaagggtaaggccgttctcagcaagggaacccc
+gcgaatctaggcttataccatctagattgttaactacttgcctgtagttctacagccata
+ctggacagttgtttctaaatgatcgggattcatgctagcactcctctgaatgcaccgcgt
+aagtttaactattacgtccgtgggcagataaggatggaggctgtatgtatcttaactgtt
+acctaatatggctggtaattatcaaagtaaggaccttaatgccatagcgctagcaatcgc
+tttgtatactgaccatgtgccaacctctcttaatctgtaaaatataatgtcttagctaac
+tgtggacgatcatgtctctgcctagagcttcgctgtatcaattcctatagccagcgtact
+agtgacacaacaacaccgtgtgagaaaagatattagtccttacgtctgtctctctacagc
+ttattgatgaggattgaacatggacatatagctccccctcaaaagcagatgctacctctt
+tattccattctcgaacatttgccgaacttaatttcgacaaacctgaggtcacgtcttaat
+ttatcggtaacgtcacgtccctttgagactggataaatatattaccaggggccaacgagc
+aattgttggaggcgcttctataatacaaggtgtcttgtcaaagaaagacggcgtgcgtct
+cgtgcaactcacttaaccaatattaatgtgaaacccccctctctcacatcttatgcggtg
+tactgccctggtacatttcctgtacaggactccaacagtgtagattcctaagatagctgt
+tggagttgcctcacgccagatcgaaaaactgaataaactagtgagctgagctgcagaaat
+accgcttaattacttatgactagttcaaagggacctacgtgatgtcagacattgcaagga
+agaaattaggtttgtgcgtcattttggctggactagcactccttacttcccctactattc
+aaatgtcgtaaacagcatgagacaggatcgtgctgacatttaaggtctattgggaacgag
+gctacctttggtcgcgcgctcgcgttctccgaatgaccgaaatgcatgagcacagtatgc
+aattgcttatagatctaaggtctggtcgttgaaaccaagcacgtaggcctgggaaatcag
+ttcttcctcagcaactacacaaaagcgtccaagcattagtacttgtagtaaatgtccgaa
+cctatgcgctcatttgaaagtcaaaaaatatttttaagcagtaggcacctaacccgattc
+ctctacttagtagctttctttgattctcagaattgactgcaatatcactgcacaattctg
+tgccattactagacttctctgtattaacgtctcatcttactaacactcgcctaggacaca
+tctgagagtgaagtatttcaatacatttactgaaatcttcagttctaaaatccccgaata
+aggctcttatcggtttggccaacacaagaaaaaaacttcttgcaccactcaccttcatac
+gcaggagcctggggaacttagtaataactatttcggcagacaaagcttataacaagttgc
+cggcgcgtataatatttaaaagaccccttgagctgctcaattaaaacgctcacctggtat
+aggctattagatagtgccgtcttagtaaggggcgggaattatcggataaactgatatttt
+gataaaataaccgacttgttcacgacataagtcactaaggagattttatctttctccaaa
+gtatatcttccttggataatttcaaagcgctgcaatttaagttctgttactagtttatgc
+tgctgggaggtgaccggaaggcgtagtaatctagaggcaaattataagaagttcatcata
+tcattttcgactacaaaaacaaggtgttgtatgccggcgcattgtgtaaactggacgagt
+accctagatggaaaattatacgttaagccaagatttcgatgtaatgataattacctacac
+atttttgctatccataggaacaagagctgttctataggctcgtggcatacgaacatttgc
+tgccgctatgaatattggaagctcttcaactacagactctattcttaattgccgtcgaaa
+atgggccgaatcggctattattaatactcggtttttccgaggggattgttgtcgacagtc
+gtaattattattaatattgatgttggtgaggtcatttaaatacaaccttgcagacaatga
+ataagggatccaatctctcatactccttttacaattgctcatgcccctatgcaaacctta
+tgccgccacacctccgcaactctctcttctgaactgtaagtagcttcattactggtttga
+gactatactgaagctgatgacattctaaaatggctattttcgaatgtgattcataatgtt
+tatcgtttgggatggcagaatcacgttatttttgatatagcccgggtattctattgtata
+gaacgtatgctacaagtcattccccgaagaagactagaagtaaacaacatgcgaccatcg
+ttaagccacgcaaggctgtagctttatttcccgataacctatcttccataaatagcggac
+agcaggatactgacgctcaacatcagtggttatggtctaatttttaacttttaataaggt
+aacttcagcaggcatacacagtaactctttaatttataatcaaattagaagtctgacact
+tcttatatttttctatcatccaacgcgatcgcccattagcttattgtgttactaataacg
+tatctaaaccaatccttttcaagctactgcctatattgtcaatatatacaaacaacagga
+tagtaggctgcttaaaaaatattgtcaaccgtgtacgctttacaatacccggaaatcaca
+aactttgtagacaacgagtgaaatttatacactacgaagggccagcgtacaagacccatg
+aattaggcgatatgtttattctgacatattggtttatccttaatctgtcgctgtaaaatg
+aagccgcccccatccctgcgaattttttttcgaagattcacgactgaaatataaatacgt
+ttggctatatttatgttggagggaggcaatagcctttactgttaaccgaagatttagcca
+gtgagtgtgacactaaaacactggaataaatgcaggcgttcttctgggtaaaaggtttag
+tcaatctcgcctataagttcatatagctctggatataattatctggcccatgcatttatc
+atggcgcttggtgccctgtgtgaagccggcctctcatattgaaggtccgaagtattccat
+gtacattaagatcactctctcattcatgcatcttggcttaacaaatctggttgtccaagc
+tttccaggcacgtatggtacaaattcggatcgaatacttataaaaatgatatgttaaact
+gtctaaaacgctcatctacaaagtaaagtgcactaaccaatagagtctcaagaccgtgta
+atgctggtgcactgaatgtgtaatacggttagaagggattagttatgttacaaatccatt
+gaaaacttaagaagcattgcgtgctcggagggtgcatcttttatcaagagactaacatta
+ttttcaacgacgtacatgctttacaatagggtacttatcaaacgccgagaaacgcgccta
+tagtgatgttatgattatgacccgatatccattggaccgaattttatgtaggttcccagc
+gtactcgcgtaatatctcggtattgccataatgtaatacttgtcggtctctcccagatga
+aaaagcgttacagagtatttcaatgaaaaacagcgcgcaacgtcaatacctttaggggta
+acggccgctgatttcatatagatatacgataagttggtatagctctactaggtggcatcc
+acaatcgttgcatttactatagctggttacaatcataatctataccgttccttacatact
+accatagcgggatagcgtttttttgccgttgattgggtttaagaggatgtcagtctcatt
+atatccgattcggtgggagagccgttgttttcaaatcgcacactttgtgacataatgtac
+aagataacaaaactgatataagatataaactgtcaatatcaccttgacacttgaatcaaa
+gtaaattaactcgcaaatataatttgactaattgggtgcagatttctcaattaataaaaa
+aatggcaccggatgggcttacaagccccttatcattcacttgtatcatgatttccaagaa
+caatagaatttgctagcaagtatgaacagagattcgaattgcatccacagtacgccggag
+cgtttattttaatgtggatatgacgatgtactgttggcggcatttgctagtaaccggtcc
+ttatttacgtagcgcacacgtaagcatgtctgggagaaatatggtggtacaatctcagag
+aaagattacagtttggtttaaataggacttatcgggtcggaagtggaacttaataagcag
+tacacaattgggcaacagacgtcttgcctattacaataggattacaatgcgttagatttc
+agacacgttcgtgtttggctattcgtcaattccctaaatagttagacgatcaactattat
+caaagtgattctttgttcatcctccattcatgtaacagatggcacactacgcataacgcc
+gaggaattttaacgagatttaagagagcagttcgggcacaacccacttgactttataaca
+gctcggcagcataaacggtaatatgtgacaaatttccaaacgttataagaacgtatgtgt
+acttagaaaactaagtggttcatgttcaacagatgtgacgcagcaagcctaacttatcta
+ttggttttgctataaaagaacaaagttacacagaatcctaagggcttgtttcacacttat
+gcctagtgcttcaccatcttaaaatagcgaaaccggcacgaatcaaaccttaaaacaatg
+cgcagatattggtgatggtgactccgggtatgataatggtaactgttgaccagcgcccac
+ctcatcgaagtatagaaagtggttaggataaggatgagaccgaacttatttccggccata
+actttagattttctacctagtacacaacatcagggcggacacgaaaccgccatcacatca
+tataccaggtttaatttgcttaatgggggaagtgtcaacgaaccttcgaactttagcagg
+catatggccattatatatggccccagagcagaatgctacagcagacaaaatttggattta
+tgtagtttaatacctatcaaacttggtgtgaccatacttgtctaacgacagtgcacaaag
+tgtaagttacaattattactactcagcagcttctgcaatgataaaatcttatcatacacg
+tcacatatgataatatctacttagggggaacgggctccacaacctacatagtactcaata
+cttacactattcgacaggcacaccaaacctgtacagtcccaaaagattgagtcaactttg
+cagtactgcagatcacagtaatagcttagttagcgagtcaaaattagttttctacgagac
+tgcacgaccgtgcaaatttccgatgtgttggctacaaatagcaacgtatgaatttgtttg
+aagccacgtaaactgtacaaccttagagataagtctcaggctactaaaaacacgttgtgg
+cactaacaggatcatggttgattcttacttattcggctgaccggcccaataagtaacctt
+caactagaacagaataatcgggagtagtttaattcagtcaaggtgcaggtctcattgtaa
+ctaacaagctctgtgtaaccaagttaaaatcgttttcttagcggattccctacttatgga
+tttgagctcgtccacaatattcgatacaagaagtttgtggtccgtaacaacgaaatttta
+attacgctgtgcagcctcatccaaggaattaatagaaggttgatggtaggctccgaacgc
+tccatgattataatcaagtggactgtgcagtaaacgaggaaggtatcctgacgtcgtggt
+gttcgtttttgttatttgtgccctatacgagtagataaaccatgaacagcacagtgtgaa
+cccatggttgattttaggctaccttatttttaatttccgttacacagaaacgaattccac
+aactaacatgccattaatttttcgatatcttataaaagatggtcgaaattcattcattta
+ttttttttcggttctcgaaagtcaactaagctgtcgcgttttgtttctctttagaggtaa
+aagtggctttgatctcctacgtttggatactagtcaaccattactccatttgatccgtga
+gtatcacctgtctaacatccagcattatgactcctcggcgaagaaaagacacacttctta
+gagtcgatgtgtattagctagggacacagttgtttaatacgatagtgagcccagggaggg
+cagtgcgtcccccagtagatttattcagctagtgtaagtataagatatctcacccacgag
+gttcaagtgatatgcagtcttagaataatacttatcctgaatttcgatattatgggtact
+tcaataatccgctagcgctactttatgtctcgttggacagcaggacacatggcagtctta
+aacactaaagacatcacctgaatgaatgtaatgggattacaagaatcaatgaggtattat
+atacgacgtaggaaactctggatatatacagtaatctagttacgccatcgcacttcattc
+ctctggaaacttagaagacatcagctgtacgtggaggaaccagacccccgtatgtagcca
+aatagaaccaaagttgcttatacaaacacacccaatgacaatggaccgctggagttcgta
+aactcggaacgtagtactgcacaaacccagcatttagcaataggagctacgtatgcaact
+cccacgtggtaataccttcaagctatcaatatataggtgcctagctaatcgcattcgcaa
+gcagtattcaagcttgtaaaccagtataataattacagaggctctatgaaacccaacttt
+ccagctaaaagtcccaattaaatggttatttcgtacttttaaagtcgcccgttctgttat
+tacgcgaattgattctactccaaaattaaacacaaattatcaaccgtttcatttatattt
+gtcaatgcagctgtttaaaataaggctctactaaattataattaagacacttattaccag
+atttctctagttaagtttgaaccagctcgactaccgcgaaagatacattcccttctctat
+ttttcagttcatctatgggtcagagaagcattgaatttattctattcaccctcgtcgttc
+acagcgaatcgtcagtgtgatcagtgtatgagaaatatcctaaaccgtttagtcagacca
+cacgcttagaacaagtggtctaaaaagactgccctggaaggagtaagaagtatacagctg
+atccggtgtatccttcagtcatctgccctatactaattacacgacgcaaggaaaaatagg
+tttattttctaggcaaacccttcataggtgactccgatgtgttacgaatcatgcttgaga
+atgtgctatcgttaccgacggataataacgatctccaatgaaccaaatgtagaatgtcta
+ttgattacccttttactattcgacttagagataggagatagaacctcagtgtactttttt
+agccgaatgggaatctttgggaggtgaatggccataaggtcgtaaatccaaccctcttaa
+agtcttccatattatatcgttgttcgtggaatcgataacagatttgttgacccatagtaa
+atgtatactagtttatgttgtaagtgtagattgttttccgattgccgtccaaactttatg
+tcgtaattgtagaccagtaaagttgaccaaggtaagtgcccagcgatcctgcgagatcga
+tcgccaatttttccagtcactgtaagtgtaggtttagataaagccgtatgagttatatca
+taagggcctcggaaagcagcttcgaaccaaagttcccttataatagtagtttaactataa
+aagtatatactggtctgtcgccctttcacgatttgttttaccggtttatgaagcgttacg
+tcattagagcggctccaatttaaggttaacggcttccatgtgtagttgtatacaaggata
+acttaaagtatctgttcagcgagctagttaagttatcctcgatagaacacaactcagagg
+tcccaagatcgggtttgcaacttgctaatttattctcaaggcaaattgggaattatcgat
+acctgtataccataaggtcgctcgatgtgatgcttatgtcttctggtgatcctaccttag
+ttagtgctgattaacggaacattaatgtttatcgttttgagatttagccaattctctgat
+tctaactcaagatgccttatctgacgtgctatgcagcccctaagtattttacattgtaat
+aggacacgctcctttaaaactcgccaaaaggtcgttgtggttctctactggttaactata
+taatttacagctttgttgagctagttcctctttggtttaagtcctcaatattagttggtt
+cgagcgataagttggctagttaccttagtcactatattagatccgaatgttatgcttcat
+ctgaagaccgccaccctccaaaatttcttttaagactcacttattgcaaggtgtaggtga
+attcggctcgtttctcaagtggtgtatctgtacacgagtttccatattttcatcaacagc
+caccgcacacttatgtcactctaggtattaaaagtcgctctacaaggggacgcaattaag
+aaacagacatgctagtcaaaaataaacatagcgaggcaccactaattcggccgcttatca
+atgggatgctctgcgcgagacgcgccagagctcagtagttagttcggacatacatttact
+tcagatgatcaattagttttctacaaatgcttactctaccccgaaaaaagtcaccagact
+cttacgtctctttagtatccttccgtcttatataaggtcagtcccccgtttcggtaccct
+ggaatttactaagaataatgaaacagcccccaaggacgtacgtttacaaatgatagacca
+gatcgcctagcttattccgacgcatgttgcatagaattgaaccaacggaatgtgagagta
+actagatgagccgaccacagcacccgtttgcgtcgcagaatacgcctgatagttcggcca
+cgaaatcatatgtcctttgagtattaagtatttgtaatgatcaatcgagctcaagcaagc
+ttacacttcctcggatattcagggaacttagtgcctttgaaagatacgttgatcaacgaa
+aaattgataatggctcatatggaatgcctacctcatagtgctgaattaacacagcactgc
+ggacctaacttttcgaggtttcaagttcacgtctcaaaacctaataggctggaatatgta
+gggatcctcggtgaatttgtgattgggtttgttgtagtactgaccaagtgaatattcttt
+ttttctaaaagcagatctgctgccgggcactacgaaggagatctctgtgtatcattattg
+cttcttgacatgatgactcttaaatcactgtgggtgtgcaaaacgatagcacaacccaat
+tcgatagtacatattgttgatacttcgcactaaaccgttcatatttaaaggttgtgctcc
+ttccttcgttaaatactggtgacttggtcctatctactattagctagacctctggggaac
+cacgcccccgtaaaacctgtgcaagagagggggtcatacatcttagacatcgcgcctcca
+ccagggaagcattgggtgattgaccaggtgtgtaacaaatatgattattcttatactaat
+attagcaaagatgcataatgatttgtattaaatgtataattgaattgataagggtctttt
+agtcagtgatagagtagtataaggtagacattagaactcttaaccggacgcagatttttc
+ggtcttagtaagccaattagtcgacaaaacaaggtaagagcggttactagtagtacctat
+aatgcactgaatcttcggtcgaagtatagttctaatgctatgcagattgtgacggcgaca
+aatgttcagacttatatcatgaaacaagctcttgtaagtattgacaaatgaaaagattga
+atatttttaaatacaaaatgcgcctacttattaggggaattaaccagattgaaggccaat
+cctcacatgtaatgagataatagacgataaatgaaattcttgtaatagttgaactgctac
+gtgatgggtattatatatgattgagatcctccaattgccgacgtcttgtcttgatgccca
+aaagattgtcaacgaggagctccctcgcgtacctgtcgtccgtatcataaacgacgcgac
+atgtacagcactccgaagtataagcaataataatgcgggtaatccagactagatcttttc
+ggactcaatgcggtttcacggtaaacatgattaataccggagagtagtcgagcttatcag
+cgatgcaagcgaattcattgtgccaggagatacgttgcagataaaaccggcaacgtatgt
+caacaagttttggcgatctcgttgtttgtattcgacgaggcgcgggaacttcaagaacta
+tcgtatattcaagtccattaccttttagtttcagactggtggagctgactaaagttatat
+catcattttgtacactggtttagttaacgataatttcagatttaacatgaccagacgata
+atcgctgtatatccagttggaatgtggtttgccagaaaggttaacttataatcaagcctc
+tcttcagtcttgattcgtcgtatcccatccattgcgctatacctcagtgtatttggagct
+gtagttataccgtgtgctaagatcagtagacatgacgagagcaatattatctaccttaca
+agcatcaacggacgtctagtcggaacaaaagactctaaaactcgaacttcaggttaatat
+actatagttctgtattcagcagttattcttatattcgatattatcttgcctattggatgt
+ctgactttagtatattaatcatagtatctgccatgtaaaggtgccagtactaaatctgtt
+tcacagtgcgaattataaacggttacaaccattaaagacaacaagaccctatagctttat
+ttgaattttgtcaatgcgcaacttggagctcgcgatacatcccaattagtctatagggtc
+gggacgattctacggcatttctggttataatgacaacatggattgtggcccgagaatcgc
+tctttcattaattaagcaatcattacagtcttataagcgctacttccgagtggtagcagg
+taactcgatataaggtcgcatgagccgaatagcttaaaaaacaggccaccgaacattgat
+agagaataccgaccacagcgcaacctttgattactttcattaaattgtacggctcactcg
+acatcaagcttaagattgcgataatgtgaactcaaatggatcagtactgaagaaccgtaa
+cccacttcgcagaaagcgtacccagagaagatacgctgttacaatatacagggtgaaatt
+attgcctgttcttcgtaaccatttcgccaaacttggttagaaatgatagccattcatgat
+agaaataagctgaatgataccagtatctttaactatgtagtcagggggaagataacgatg
+gtccatgtatgtttctgatatgtgacagtattggccgcgtaatttgctaacgaagctact
+taatgcctttgagcttcatatagatttctttaatcaaaatcggcaaaaagatagtatgag
+ctataatatatgctagtagagaactctggaccatcatctatatgaatactgattcgagcg
+tgcaattactttagcctgcgtactactgactctacaaaacactctgagataagtttgtag
+tcagtaagtcgctctctataaaccttttggatgaccattgtacagccacttatagatccc
+aataaatagcacaggagacagagtttttcaatgctcgatcatttgccgatagtattttcg
+tctaacctcagggcacctattatttgatacctaacctaacggccctttcacaatggagaa
+atatatgacatcgggacaaacacaaatggtgggtggccaggagatatgacatggtggcgt
+ctctaagaaacacggactccctctaggcaaactcacgtaaccaattttaatgtcaaacaa
+aacgctcgaaaagattttgccgtgtaatgacctggtacattgactggtcaggaatacatc
+actgtagttgccgtagtgtcctgttggtgttccatcaagacacatcgtataacgcaattt
+acgacggacatcagatcaagttatacagattatttaagtatcacgtgtgcattgggacat
+aagggatctcacacatgccttggaacatttttgctttgtgccgctttttcgctgcactac
+caatccttacttaccagtatattcaaaggtcgttaacagaatgagaaaggttagggctct
+aagttatcgtcgattgggatagacgagacatttgcgagcgccctccacggatacgaatct
+cccatatcaatgtgaactggatgctatgcagtttagttcttacgtctcctagtggtaaaa
+atcaaagtagcactcgcatagcagttattcagaacctaatacacaaaaccgtcaaacatt
+ttctaattctaggtatgggccgatcataggagctaaggtgaaactcataaatgttttgtt
+agatctagcatcctaaaaagatgcatatactgagtagctggcgtgcattctctcaattgt
+atcctttttaactgaactagtcggtcccatttcgtgactgagatctattaaccgataaga
+ttaataacactcgcattcgtatcagctcagagtgaagtttttcaataatttgactgatat
+attaacttctaaaataaccctttaagcctcggatccgtttcccaatcacatcaaaaattc
+ttattccaactatctacggattaacaacgtgcatggggatcgtagtaagaacttgttccg
+atcactttgagtatatcaagttgacggcccggttattattgaatagaaacattcacctgc
+taaattaaataccgcacatcggatacccgatttcagagggccgtcttactaagggcaggc
+tttgttcggtttaactgagatgttcattattttacagtatgcttcaactaatatgtaacg
+aaggacagtggatctgtctccatagtagatcttcagtcgtgaatttcataccgctcctat
+ttaagttcgcgttcgagttgttgatcatggcacgtgaaagcaacccctagtattctagac
+gaaaattttttctagttcatctgataatttgccaattcaaaaacaaccgctggtttcccg
+gcgcattctctaaaatggaagtcgaacctagagccattatttgtcggtaacccatgagtt
+ccttcttttcagaagttaatacactgtggtcctatacagaggaaaaacagcggttatata
+cgatcgtggcataacaacattggatcaagatagcaatttggctacctattctaattctca
+ctagattcggtattccactacaatatcggcagattaggattggatgaataatcggtgttt
+aagtccggttgcgtctccaatctcctaatttttattaatattgatcttggtgacctattg
+taaataaaaacttcaagactttgaataacggtgaaaagatagaagactcatttgaaaatg
+gatcatccacagatccaaacattagcaagacactaatccccaactagctattctgatcgc
+gatcgtgctgcagtactcctgtcacaatagtctgttcatgatctaattctttttgggctt
+tgttcgatggtgattcagaatctttatccggtcgcttccctgtagctactttgtggggat
+attgcccggggattatagggttgagatcgtttcctaaaagtatttaaaccaagtagactt
+caactaaactacatcagaacatcgtgaagacaccatacgcggtacctttatttaccgata
+acatttcttcaagaaataccggtaagcagcataatgaccctaaacagctcggggtatcgt
+cgtagttttaaattttatttaggttactgctcaaggaataaaaactaactatttaattta
+taataatattacaaggctcacactgattagatttgtctataagacttcgcgatcccccat
+taccggattgtcttaagaataaactagataaaccatgcattttctagataaggcctttag
+tctaattagatacaaaaaacacgatagttgcatccttaatttattgtgtcaaacctggaa
+ccttttaattacccgcaaatcactttatgtcgagactacctctgaaatttattatctacc
+taccgcatgaggacttgaaccatcttgtaggagttatgtttattagctaagattcgttta
+tcctgtagcggtccatgtatattcaacaagcaaaaagcactcagaattgtttttagttga
+gtcaagactgatatataaataagtttccctagttttttcgtggtgggacgatattgaatt
+gaatcttaaccgaagagtttcccactctgtcgcacaataatacacgccaatatttccagc
+cctgcttatgccttaatcggttactcaatctcccattgaagttcattttgatctgcatag
+aagtttcgggcccagccttttttctgccaccttcctccaagctctgtagacgcactctaa
+gattgatgctcacatgtattaattctacattaacataaatatataagtcatgcatcttcg
+agtaaaatatctggttctccaacatgtcctggcacgtatcgttataatgcccatacatgt
+agtattaaaatgattgggttaactggatattaagatcatcgaaattgtaaagtcaaatta
+acaatactgtctcaagaccgtgtattcctcgtgctcggaagggctattacgcttacttcc
+gttttggtatcttaatatgactttcaaaaattaagttgcagtgagtcctacctgcgtgca
+tcggttagcaagagtataaaagttgtttaaacgaactacttgctttacaataccggtcgt
+atatatcgccgtgaatccagaagattgtcttctttggattatcaaccgagatcctgtgga
+ccgatgttttgggaccttcacagaggactccaggtagagctcgcttttgcattaatctaa
+gaattgtacctctctaaaagatctaaaacagtgaatgtgtatttcatggaaaaacacaga
+gaaacgtaaattactttaggccgaaaggcacatgagttattatacatatacgagatggtg
+gtatacatcgaattcggggcatacactatagttgcattgtatttagctgctttaaataat
+atgatattaccttccttacataagacattaccggcataccctggttttcaacttgtgggg
+ctttttgacgatcgcactctcatttgatccgagtagggcggtgacccctgcttttcaaat
+acaaaaatttcgctatgaaggtaatagattacttttcgctgttatgatagaaacggtaaa
+tttaaaattgaaacttctagaaaagtaaagtaacgagaaatgattttgtgaataatgcgg
+tcatgattgcgcaagtaagaaaaaaaggcaaaaggatgcgcggaatagaaacttatcagt
+cacgggtatcttgatttcattcttcttgtcaattgccgacataggatgaaatcagattcc
+aatgcaatacacagtaacccccacccttgattgtaatgtcgatttgaagttgtacgcgtc
+gacgaagtggatagtatacgggccttttgtacggtgcgatcaactatgaatctcggcgag
+ttagatggtcgtacaatctcacacatagaggtcacttgcctgtaatgacgaattttcggc
+taggtactcgaactttattagaagtaaaaatgtgggcaaaagaaggattccattttacaa
+gacgattacaatgagttacatgtctctcaacgtagtctttccctagtagtctttgaacta
+tttaggtactccagaaaattttagcaaagggtttctgtgtgaatccgccattcatgttta
+tgatggaacaataagaataacgccctcgtatgttatcgacagtgaagtcagcagttcggc
+caaaaacatattcaatttagtacagatccccagaagttaagctaagtgctctaaaatggc
+ctaaacggttatcaaagtaggtctaattactatactaacgggtgcatcgtaataactgct
+gtcgatgcaacactatatgatagtgtcgttttgctatatatgtacaatgtgacaaagaag
+ccttagcgattcttgcaaacttaggacttcggattctcaatcttaaatgtccgaaaacgc
+aaagattcaaaaatttaatctatgagcagatatgcctgatggtgactacgcgtatgttaa
+ggctaaatgttgacaaccgcacacataatcgaactattgatagtcgggagcataaccagg
+tgaacgtactttgttcacgacatttattgacatgttctaaatacgtctcaaaatcacggc
+gcactagaaaacgcaatcaaatcattgtcctggtttaagggccgtaatgccggtagtgtc
+aaacttcatgagaactttagctggcttttggccagtatttagggaccaagagcactagcc
+ttaagctgaatattttgccatttatctactgttataactttaaaacttggtggcaccaga
+cttgtcgatacacacgcatcaatctgtaacgtaaaaggtttactaagaacaagcgtagga
+attgagtttatattatatttaaactaaaagatgatattagcttctgagggcgatagggct
+ccaaatcataaagaggaatatattattacacgattagaaacccacaacatacctcgaatc
+gcccaaaagtttgacgaaacttggcagtactccacatctcagtaatacagttgggagagt
+ctcaaatgttgttttattactcaatgaaccaccctcataatttcactgctgttccattaa
+atttgcaaacgatcatttgctttgaagaaacgtaaaatcgacaaaattacagataagtag
+atgcataataaaaaaaactgctcgctataacacgatcatcgtgcattcttacttaggagc
+atcacccgcacaataacgtaccttaaactacaacactattagaccgagtactgtaattca
+cgaaagctcaagctcgcattgtaaagaacttgctctctcgtaaaatgtgataatagtttg
+cggagaggattcaattattttccattgcacctactccactagattcgataaaagaaggtg
+gtcctcccttaaaaagaaatgttaagtaacatcggaaccataagcaaagcatgtaagtga
+accgtcatccttccctaagaaacataaaggtttttaataatgtcgactgtgaactataac
+tgcatcctttcctgacctactccggttccttgttgttatttctgaacgagaccagtagat
+aaacaatgtaaaccacagtgggtaccaatggtgcatgtgacgctaccgttgttttaagtg
+cccgtacaaacataagaagtcataatcttacttgaaattaattttgccttttattttttt
+tcaggctcgaaattaatgatttgttttttttgaccttctagttacgctaatatgcggtcg
+cctgtggtttctattgagtcctataacgggatgggatctaatacgtttggttactagtaa
+acaaggtataaatttgataccggagtatcaactgtataacatcaagctttatgactcata
+cgcgaagtaatgacacaaggctttcaggagatcgcgagtacagagccactaaggggtgta
+ttacgatagtgacaccaccgagcgcactcactccccaagtagatttatgatcctacgcta
+agtattagatatataaccaaagaggttctagtcagtgcaactcttagaataataattagc
+cggttttgcctttttaggcctaatgcaatattcagctagcccttatgtatctcgcgttcc
+acagcaccactcatggcacgcgtttaaactaatcaaatataatctatgaatgttatgcca
+gtacttgaataaatcaggttttttataagtccttgcatactctcgttatatactgttaga
+gtcttaccccatagaaattctttcatctgcaaacttagaagaattctcagctacggggag
+cataaagtccccaggatgttgacaaatacaacaaatgtggcttatacaaacactccatat
+gaaaatcgaaccctcgtggtagttttagccgaaccttgtacggataaatccctccatttt
+ccaatagcagatacctatcctactacctcgtggtattaaattaaagcttgaaatatagag
+ctgcatagcttatccaattcccaagcacgagtctaccgtcgtaaccacgatttgatttac
+agacgctagagcaaacccatctttaaacatataagtaaaaattaaagggtgagtgcgtac
+gtgtttactagcaacttcgcttattaagacaattgtttataagccataattaaaaacata
+tgttcaacaggttcattgatatttgtaattgcacaggtttttaataaggatctacgtaag
+tataatgaacaaactttttaccagagttatattctgtactttgaaaatgctcctctaccg
+ccttagagactttcaattagattttttgcagttaatctatgcgtaagtgaaccatgcaag
+ggatgcgattcaaccgcctcgtgctaaccctatcgtctgtctcataactgtaggtctaat
+ataattttcagttttcgaacacataaccctttgaaaatctgctatttaatgtctcacctg
+catgcactatcttctatactgctcagaacggctatacgtcactatgctccaagtgacgat
+ttaaacgaagcaaggaataataggtttattttagtgcaaaacaattaagtgcggactacg
+tgctctttacaataagccttgtgattgggctataggttaagtcccatattaacgatctcc
+aatgtacaaaatcgacaatcgctttgcattacccggttactagtcgaattacagatagct
+gttagatactcactctaattttggacaacaatcccaatcttggggtcgtctatcgcctga
+agctcgtaaatccttccatcttaaacgattacatattatagacttgttcggggtagagat
+atcacagttgtgcaaacattgtaaatcgatactagtttatgttggtagtctagttgcttt
+taccattccccgaaaaacttgatctactatttcgacaacagtaaacttgaactaggtaag
+tgaaaacagagaatgcctcatagtgccactatttgtccactatatgtaagtgtagcttta
+cataatccactatgactgagatcattacggcctaggaaagcagcgtagaaaaaaagggcc
+cggatattacgactgtaactataaaactagttactggtagcgcgccatgtatagatttgt
+tttaccggttgtggttgcgttaacgaatttcagccgcgaaaattgatccgttaaccagtc
+catctcgacttctataaaacgataaagtaaagttgatgttcagcctccttcttatggttg
+catcgagagtacactactcagtgggaaatagatcggggttcctacttcagattgtattat
+ctaggcaattgccgattgtgccatacctggataaaataagctacctacatgtgatgctta
+tctattatcgtcatactaccttagggtgtcctgttgaacgctacattaatctttagccgt
+ttgagatgttccaatggataggagtctaacgcatgatgaagtttaggaaggcagagcatc
+ccactaagtatgtgacagtgtatttcgaaacgagacgttataaatagaaaaaaggtcctt
+ctggttctattctgctgaactattgaatggaaagattggttgacctacgtactatttgct
+tgaagtcatcaatttgacggggtgagagacatatggtgcatactttacggactctatatt
+ttagatcagaagcttagcagtcttctctacaccccctcacgacataattgcttttaagaa
+tctatgtttgattcctctacgggaattcggatccgttcgcatgtgcggtttatctaaacc
+aggggacatatgttcagctaaagcatacgaacactttgctaactagacgtatgtatagta
+gctataaatcccgacgatatttacaaaaagaaatgagactcaaatatatacatagcgacc
+ctacacttattcgcaccctgatctaggcgatcctagcacccacacccgaaagtgagcact
+agtgtcttccgtattaaatttactgcagttgagattttagttgtctactaaggattactc
+taacccgtaataaggatcaagactcggtactagctttactatcattccctatgtgttttc
+ctaactcacaagggtacgtaccagcctatgtaattacaataatgataaagacacaaagga
+agtaactttacaaatgagtctccagttacactagcttagtccctcccatcttgctttgaa
+gtctaaatacgcaatctctgaggatatacagcagaagaacactcataacgttggagtcca
+agaattagactcatagggcccccaacatttaatatgtactgtgagtttgaaggtgttcta
+ttgttaattcctgctcttgatacatgacacgtactccgtgtttaaggcttcggactgact
+ttctttcataagttgagcaacgaaaatttcagaatcgataagttggattcactaactaat
+acggctgattgaaaactccactccggacctatatggtcgacctttatacgtaaccgatat
+aaaacttataggctggtatatcgagccttcctagcgcaatttcggatggggtttcttcta
+ctactcaacaacggaatagtctttgtttagtaaaccagagctcaggacgcccaatacgta
+ggagagcgctgtggagcatgtgtcattatggactggagcactcttaaatcactctgcgtg
+tgctaaacgatagatcataacatgtcctgagtaaattttcttgatacgtcgcaatatacc
+gttattagttaaacgttctcatccgtcatgcgtgaaatacggctgtcgtgctcagatata
+ctattagcgactcatctcgcctaacacgcacacgtataaactcggaatgactgccgctct
+tacatattagaaatacagactacaccacggaagcattgggtcattctcaaccgctgtata
+aaagatgattagtcttataataagattaccaaagaggcagaatcatgggtagtaaatcta
+ttattcaagtgattaccgtcgtgtaggcagggagtgaggacgagatggtactcaggacaa
+atattaaccggacgaagtggtttacgtcgtactttcactattagtagtaaatacaaggta
+acaccggggaatagtactaaatataatgatatctatcttcgggagaacgagtcgtctatt
+gctttgaacattctcaaggcgtaaaatgtgctgacttatagcatgatacaaccgattgtt
+acttttgtctattcaaaagattgaatagttttttatacaaaagccgcatacttatgacgg
+ctagtatacagtttcatcccctagcatcaatgctatggacagtattgaacttataggaaa
+ttcttctaatagggcaaatccgtcgtgatgcctattttttttcagtcacatcctcaaatg
+gcactagtattgtcgggatcccattaacaggctcaaccacgagctcacgcgaggacatgt
+agtccgtatctttaacgaagcgacagcgacagaactcccatggataaccaattataaggc
+ccgtaatcctctagacatcgtttaccaataaatccgctttctccgtaatcatgttgaata
+ccccagagtagtccagatgataaccgatgaaacacaagtctttctcaatgcacttacggt
+gaacttattaccgccaacgtagctcatcaaggttgcgacatctagttgtgtgtttgcgac
+gagcccagcgaacttcatcaactttcgtatattcaacgccttgtaattttactttaagac
+gcctggtgatgtagattcttagataatcagtttgttatcggctgtactttaccataattt
+cacaggtttcaggtcaagaagattatagctgtatatacagttccatgctcggtgcacaga
+aacgtgatcggataataatcaatcgcttatgtcgtctttaggcgtatccaatacatgccc
+cgataccgcagtgtatttcgacatgtaggtataccgtcgcatttgagctcgagtcaggac
+gtcagctagattagattccttaatagaatataccgacctctagtccgaactaaactatag
+ataacgccaacttcaggttaattgtctagtcgtctgtttgcagatgggattcttagatga
+gtgagtatcggccatattggttcgagcactttagtttttgatgcataggatatgcaatgt
+atagctgaaagtactttatctgtttcaaactcacattgattaaaccggtaaacctttaaa
+gactacaagaaaatattcagtgagggcaattttgtcaatcacaatcttccagctagagat
+acttcacaatttgtcttgaggctacgcaacattagacggattttcgcgttttattgaaat
+aatcgaggggcccaagagtatccatagttcattttgtaagatttctttacaggcttatta
+cagcttcttcagactcctacatgcttacgagttatatgctagcatgtgaacaatagatta
+atatacaggaaaacgtacattgagagagatgaccctacacagcgcaaccgttgagtactt
+tcattaaagggtaacgctctcgagacagcatccttaagatggccttattgtcaaatcatt
+tgcagaagtacgcaagatccctaaccaacgtagaagaatccctacaaacacatgagacgc
+ggtgaaaatagacagggtgttagtattcaatcttcggagtatcaatttcgccaatcttgg
+tgagaaagcataccctttcttcagagaaagaagatcaatcataacactatctttaacgag
+gtacgcacgcgcatcattacctgcctccatggatctttaggatagcggaaagtattggca
+gcgtattgtgatttcgttcctactttatcaatttcacattcatatacatgtcttttatca
+aaatcgccaataagataggatgagctatattagatgctagtagagttcgcgccaacatca
+tcgataggaatactcaggacagcgtgataggacttttcaatccctaatactctctataat
+tataactctctcttaagtttggaggcagtaacgcgctctatataatcagtttgctgcacc
+attcttcagcctctgatacatacaaataaattccacagcagtaagagggtttaattgaga
+catcttgggaacttaggattttactctaacatcaccgaaacgattattggataccgtacc
+taaacgaactttctcaaggcagtaatataggacatccgcaataacacaaatgctgcctcc
+ccaggagttatgtcttcctggaggctatatcttacacccactcactataggcaaactaaa
+gtttaaatgttgattgtctaaaaaaaagatagataagagttggccggcgtagcacatgcg
+aaagtgaatcgtaagctataattctctggacttgaagttctgtcctgttcctctgcaaga
+aacaaacttcctttaaagctatttacgacgcacatctcagcaagttataaacatgttgga
+agtttctagtcggaattcccaaagaacggatctatctaatgcattcctacatttttcctg
+tctgccgatggtgccatcctattcaaagaatttcttaaaagtagattaaatgggactttt
+aacaatgagtaaccttacgcctctaagggttcctcgagtgccatacaccagtcaggtccg
+agccacatacacggagaacattctaacatagcattctcaactcgatcatttgcaggttac
+ttctttcctatcctagtgctaaaaatcatacttgcaatcccatagcacggattaagaacc
+taagaaacaattcagtaaaacatgttcgaattcttggtatgggaacatcattgcagctat
+ggtctaacgcattaatgtttgggtacatcttccatcatataaacaggaagagtctgacga
+cagggagtgcttgcgatcatgtctatcattgtgaaatcaaattgtagctcacatgtcgtc
+tatgagagcgtgtatccgataagatttagaaaaatagaagtcgtataagatctcactgaa
+cttttgaatgaatgtgaagcatatatgatctgctttaataaaactttatccataggatac
+gtttccaaatcaattcaataattattagtcaaaatagataaggatgaacaacctgaaggc
+cgatcggacgtagaaagtggtcccatcactttgagttgatattgttgaaccacacgttat
+tatggttttcaaacagtctcaggatattgtatatacagataatccgataccagttgtctg
+acgcccctcttacgtaccccaccctttgtgacgtttaaagcagttgttcagtattttaaa
+ctaggcggcaactaatttggaaagaagcacagtggatatgtctaaattcttgttattcag
+gcctgaatttaatacaccgcatagttaacttcgcggtagagttgttcatcatgcctcctc
+taagctaccacttctatgatacaccaatagttgttctacggaatctgataattggccaag
+tcataaacttccgctgcgttcaacccccttgctcgaatatccaactcgaaaagacagcct
+tttggtgtccggaacaaatcagttacttcttttctgatgttaattctctgtggtcagata
+cagaccaaaaactccgcggatttaccatcctccaagaacaaatttgcatcaacatagcat
+tttggctacatattctaagtctcaatagtttaggttttcaactacattatcccaacatta
+ggattggaggaataatagctgggtaagtccccttgcgtctacaatcgactattttttatg
+aatatgcttctgccgcacctatggttattaaaaaagtcatgactttgaagaaccctgaaa
+agatagatgaatcaggtgtaatggcagcagccaaagagcatataattagcaacactctaa
+gaacattatagatatgatgatagcgatcgtcatgatgttatccggtcacaatagtagctt
+catcagctaattcgttttgccagtggtgacttgcgctggaagaatcgttatacggtccct
+tccctcttgatacggtgggggcttattcaaccgcgtggattgggttgtcatacttgcatt
+aaacgatgtaaaccatctagtagtcaactatactaaatcacaaaatagtgatcaatacat
+acccgcttcatggttttaaccatttaattgattaaagatattccgctaagaaccattatc
+tacctaaactgatcgccgtatcctagtagtttgaaatttgatgtaccgtaatgatcaacg
+aagtaaaacgttatattgtatgtagaataataggtcttggagctaaatgatgtgattggt
+agtgaagacttacccttacaactttaccggtttctcggaagaatatactagagaatcaat
+gcatgggctacataagcactttagtctaatgagataaaaaatacacgagtcttccatcat
+gaattttttgtcgaaaaactcgaacctggtaatttaaaccatatatctttatgtcgtcaa
+taactctcatatgttttatataacttcccaatcacgacttgtaactgcttgttcgactga
+gctgtttgagctatgaggccgggatccggttgagctacatctatttgctacaagaaaaat
+gaaagcacatttgttgggagttctggctacactcatagagaaataagtggcccgagtggg
+tgcggcctgcctccatattcaagtgtatcttaaaccaagtggttccaacgctcgcgctaa
+agaattaaagcctttatttcctccacggagtagcccgtaatccggttcgaaagagaccat
+tgaagttaattttcatatccagtgaagtttaggcacaagcatgtgttctgccacatgcct
+caaagcgctcttcaaccaagatatgattcatcctaacttcgatgaatgcgtctgtaacat
+aaatatagaaggaatgattcggcgagttaattttcgccttctccaacatggcatccctac
+gttcgttataaggaccatacatgtaggttttaaaggtttgcggttaatcgatatttacat
+catagaaattctatagtcaaatttacaagactctagatactcactcgttgcagccggcta
+ggaagcgctttgtaccttacttcccttttcgttgcgtaatatgaatttcatatagtaagt
+tcaaggcactcatacctccgtgaagagggtagatagactattaaagttgtttaatagtac
+gtattgatggaaatgacccgtaggagatttaccactcaatccacaagattcgctgctgtg
+cattatcaaaacagtgcatgtcgaaacatgggttgggtccttcaaacacgaatccaggta
+gagatacctttgcaattttt
diff --git a/vendor/regex-1.4.6/examples/regexdna-output.txt b/vendor/regex-1.4.6/examples/regexdna-output.txt
new file mode 100644 (file)
index 0000000..d36baa5
--- /dev/null
@@ -0,0 +1,13 @@
+agggtaaa|tttaccct 0
+[cgt]gggtaaa|tttaccc[acg] 3
+a[act]ggtaaa|tttacc[agt]t 9
+ag[act]gtaaa|tttac[agt]ct 8
+agg[act]taaa|ttta[agt]cct 10
+aggg[acg]aaa|ttt[cgt]ccct 3
+agggt[cgt]aa|tt[acg]accct 4
+agggta[cgt]a|t[acg]taccct 3
+agggtaa[cgt]|[acg]ttaccct 5
+
+101745
+100000
+133640
diff --git a/vendor/regex-1.4.6/examples/shootout-regex-dna-bytes.rs b/vendor/regex-1.4.6/examples/shootout-regex-dna-bytes.rs
new file mode 100644 (file)
index 0000000..ac4c115
--- /dev/null
@@ -0,0 +1,70 @@
+// The Computer Language Benchmarks Game
+// https://benchmarksgame-team.pages.debian.net/benchmarksgame/
+//
+// contributed by the Rust Project Developers
+// contributed by TeXitoi
+// contributed by BurntSushi
+
+extern crate regex;
+
+use std::io::{self, Read};
+use std::sync::Arc;
+use std::thread;
+
+macro_rules! regex {
+    ($re:expr) => {
+        ::regex::bytes::Regex::new($re).unwrap()
+    };
+}
+
+fn main() {
+    let mut seq = Vec::with_capacity(51 * (1 << 20));
+    io::stdin().read_to_end(&mut seq).unwrap();
+    let ilen = seq.len();
+
+    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, &b""[..]).into_owned();
+    let clen = seq.len();
+    let seq_arc = Arc::new(seq.clone());
+
+    let variants = vec![
+        regex!("agggtaaa|tttaccct"),
+        regex!("[cgt]gggtaaa|tttaccc[acg]"),
+        regex!("a[act]ggtaaa|tttacc[agt]t"),
+        regex!("ag[act]gtaaa|tttac[agt]ct"),
+        regex!("agg[act]taaa|ttta[agt]cct"),
+        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
+        regex!("agggt[cgt]aa|tt[acg]accct"),
+        regex!("agggta[cgt]a|t[acg]taccct"),
+        regex!("agggtaa[cgt]|[acg]ttaccct"),
+    ];
+    let mut counts = vec![];
+    for variant in variants {
+        let seq = seq_arc.clone();
+        let restr = variant.to_string();
+        let future = thread::spawn(move || variant.find_iter(&seq).count());
+        counts.push((restr, future));
+    }
+
+    let substs = vec![
+        (regex!("B"), &b"(c|g|t)"[..]),
+        (regex!("D"), &b"(a|g|t)"[..]),
+        (regex!("H"), &b"(a|c|t)"[..]),
+        (regex!("K"), &b"(g|t)"[..]),
+        (regex!("M"), &b"(a|c)"[..]),
+        (regex!("N"), &b"(a|c|g|t)"[..]),
+        (regex!("R"), &b"(a|g)"[..]),
+        (regex!("S"), &b"(c|g)"[..]),
+        (regex!("V"), &b"(a|c|g)"[..]),
+        (regex!("W"), &b"(a|t)"[..]),
+        (regex!("Y"), &b"(c|t)"[..]),
+    ];
+    let mut seq = seq;
+    for (re, replacement) in substs {
+        seq = re.replace_all(&seq, replacement).into_owned();
+    }
+
+    for (variant, count) in counts {
+        println!("{} {}", variant, count.join().unwrap());
+    }
+    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
+}
diff --git a/vendor/regex-1.4.6/examples/shootout-regex-dna-cheat.rs b/vendor/regex-1.4.6/examples/shootout-regex-dna-cheat.rs
new file mode 100644 (file)
index 0000000..c7395b7
--- /dev/null
@@ -0,0 +1,92 @@
+// The Computer Language Benchmarks Game
+// https://benchmarksgame-team.pages.debian.net/benchmarksgame/
+//
+// contributed by the Rust Project Developers
+// contributed by TeXitoi
+// contributed by BurntSushi
+
+// This technically solves the problem posed in the `regex-dna` benchmark, but
+// it cheats by combining all of the replacements into a single regex and
+// replacing them with a single linear scan. i.e., it re-implements
+// `replace_all`. As a result, this is around 25% faster. ---AG
+
+extern crate regex;
+
+use std::io::{self, Read};
+use std::sync::Arc;
+use std::thread;
+
+macro_rules! regex {
+    ($re:expr) => {
+        ::regex::Regex::new($re).unwrap()
+    };
+}
+
+fn main() {
+    let mut seq = String::with_capacity(50 * (1 << 20));
+    io::stdin().read_to_string(&mut seq).unwrap();
+    let ilen = seq.len();
+
+    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
+    let clen = seq.len();
+    let seq_arc = Arc::new(seq.clone());
+
+    let variants = vec![
+        regex!("agggtaaa|tttaccct"),
+        regex!("[cgt]gggtaaa|tttaccc[acg]"),
+        regex!("a[act]ggtaaa|tttacc[agt]t"),
+        regex!("ag[act]gtaaa|tttac[agt]ct"),
+        regex!("agg[act]taaa|ttta[agt]cct"),
+        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
+        regex!("agggt[cgt]aa|tt[acg]accct"),
+        regex!("agggta[cgt]a|t[acg]taccct"),
+        regex!("agggtaa[cgt]|[acg]ttaccct"),
+    ];
+    let mut counts = vec![];
+    for variant in variants {
+        let seq = seq_arc.clone();
+        let restr = variant.to_string();
+        let future = thread::spawn(move || variant.find_iter(&seq).count());
+        counts.push((restr, future));
+    }
+
+    let substs = vec![
+        (b'B', "(c|g|t)"),
+        (b'D', "(a|g|t)"),
+        (b'H', "(a|c|t)"),
+        (b'K', "(g|t)"),
+        (b'M', "(a|c)"),
+        (b'N', "(a|c|g|t)"),
+        (b'R', "(a|g)"),
+        (b'S', "(c|g)"),
+        (b'V', "(a|c|g)"),
+        (b'W', "(a|t)"),
+        (b'Y', "(c|t)"),
+    ]; // combined into one regex in `replace_all`
+    let seq = replace_all(&seq, substs);
+
+    for (variant, count) in counts {
+        println!("{} {}", variant, count.join().unwrap());
+    }
+    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
+}
+
+fn replace_all(text: &str, substs: Vec<(u8, &str)>) -> String {
+    let mut replacements = vec![""; 256];
+    let mut alternates = vec![];
+    for (re, replacement) in substs {
+        replacements[re as usize] = replacement;
+        alternates.push((re as char).to_string());
+    }
+
+    let re = regex!(&alternates.join("|"));
+    let mut new = String::with_capacity(text.len());
+    let mut last_match = 0;
+    for m in re.find_iter(text) {
+        new.push_str(&text[last_match..m.start()]);
+        new.push_str(replacements[text.as_bytes()[m.start()] as usize]);
+        last_match = m.end();
+    }
+    new.push_str(&text[last_match..]);
+    new
+}
diff --git a/vendor/regex-1.4.6/examples/shootout-regex-dna-replace.rs b/vendor/regex-1.4.6/examples/shootout-regex-dna-replace.rs
new file mode 100644 (file)
index 0000000..681e077
--- /dev/null
@@ -0,0 +1,19 @@
+extern crate regex;
+
+use std::io::{self, Read};
+
+macro_rules! regex {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new($re).build().unwrap().into_regex()
+    }};
+}
+
+fn main() {
+    let mut seq = String::with_capacity(50 * (1 << 20));
+    io::stdin().read_to_string(&mut seq).unwrap();
+    let ilen = seq.len();
+
+    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
+    println!("original: {}, replaced: {}", ilen, seq.len());
+}
diff --git a/vendor/regex-1.4.6/examples/shootout-regex-dna-single-cheat.rs b/vendor/regex-1.4.6/examples/shootout-regex-dna-single-cheat.rs
new file mode 100644 (file)
index 0000000..04ed05a
--- /dev/null
@@ -0,0 +1,77 @@
+// The Computer Language Benchmarks Game
+// https://benchmarksgame-team.pages.debian.net/benchmarksgame/
+//
+// contributed by the Rust Project Developers
+// contributed by TeXitoi
+// contributed by BurntSushi
+
+extern crate regex;
+
+use std::io::{self, Read};
+
+macro_rules! regex {
+    ($re:expr) => {
+        ::regex::Regex::new($re).unwrap()
+    };
+}
+
+fn main() {
+    let mut seq = String::with_capacity(50 * (1 << 20));
+    io::stdin().read_to_string(&mut seq).unwrap();
+    let ilen = seq.len();
+
+    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
+    let clen = seq.len();
+
+    let variants = vec![
+        regex!("agggtaaa|tttaccct"),
+        regex!("[cgt]gggtaaa|tttaccc[acg]"),
+        regex!("a[act]ggtaaa|tttacc[agt]t"),
+        regex!("ag[act]gtaaa|tttac[agt]ct"),
+        regex!("agg[act]taaa|ttta[agt]cct"),
+        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
+        regex!("agggt[cgt]aa|tt[acg]accct"),
+        regex!("agggta[cgt]a|t[acg]taccct"),
+        regex!("agggtaa[cgt]|[acg]ttaccct"),
+    ];
+    for re in variants {
+        println!("{} {}", re.to_string(), re.find_iter(&seq).count());
+    }
+
+    let substs = vec![
+        (b'B', "(c|g|t)"),
+        (b'D', "(a|g|t)"),
+        (b'H', "(a|c|t)"),
+        (b'K', "(g|t)"),
+        (b'M', "(a|c)"),
+        (b'N', "(a|c|g|t)"),
+        (b'R', "(a|g)"),
+        (b'S', "(c|g)"),
+        (b'V', "(a|c|g)"),
+        (b'W', "(a|t)"),
+        (b'Y', "(c|t)"),
+    ]; // combined into one regex in `replace_all`
+    let seq = replace_all(&seq, substs);
+
+    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
+}
+
+fn replace_all(text: &str, substs: Vec<(u8, &str)>) -> String {
+    let mut replacements = vec![""; 256];
+    let mut alternates = vec![];
+    for (re, replacement) in substs {
+        replacements[re as usize] = replacement;
+        alternates.push((re as char).to_string());
+    }
+
+    let re = regex!(&alternates.join("|"));
+    let mut new = String::with_capacity(text.len());
+    let mut last_match = 0;
+    for m in re.find_iter(text) {
+        new.push_str(&text[last_match..m.start()]);
+        new.push_str(replacements[text.as_bytes()[m.start()] as usize]);
+        last_match = m.end();
+    }
+    new.push_str(&text[last_match..]);
+    new
+}
diff --git a/vendor/regex-1.4.6/examples/shootout-regex-dna-single.rs b/vendor/regex-1.4.6/examples/shootout-regex-dna-single.rs
new file mode 100644 (file)
index 0000000..a70c711
--- /dev/null
@@ -0,0 +1,59 @@
+// The Computer Language Benchmarks Game
+// https://benchmarksgame-team.pages.debian.net/benchmarksgame/
+//
+// contributed by the Rust Project Developers
+// contributed by TeXitoi
+// contributed by BurntSushi
+
+extern crate regex;
+
+use std::io::{self, Read};
+
+macro_rules! regex {
+    ($re:expr) => {
+        ::regex::Regex::new($re).unwrap()
+    };
+}
+
+fn main() {
+    let mut seq = String::with_capacity(50 * (1 << 20));
+    io::stdin().read_to_string(&mut seq).unwrap();
+    let ilen = seq.len();
+
+    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
+    let clen = seq.len();
+
+    let variants = vec![
+        regex!("agggtaaa|tttaccct"),
+        regex!("[cgt]gggtaaa|tttaccc[acg]"),
+        regex!("a[act]ggtaaa|tttacc[agt]t"),
+        regex!("ag[act]gtaaa|tttac[agt]ct"),
+        regex!("agg[act]taaa|ttta[agt]cct"),
+        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
+        regex!("agggt[cgt]aa|tt[acg]accct"),
+        regex!("agggta[cgt]a|t[acg]taccct"),
+        regex!("agggtaa[cgt]|[acg]ttaccct"),
+    ];
+    for re in variants {
+        println!("{} {}", re.to_string(), re.find_iter(&seq).count());
+    }
+
+    let substs = vec![
+        (regex!("B"), "(c|g|t)"),
+        (regex!("D"), "(a|g|t)"),
+        (regex!("H"), "(a|c|t)"),
+        (regex!("K"), "(g|t)"),
+        (regex!("M"), "(a|c)"),
+        (regex!("N"), "(a|c|g|t)"),
+        (regex!("R"), "(a|g)"),
+        (regex!("S"), "(c|g)"),
+        (regex!("V"), "(a|c|g)"),
+        (regex!("W"), "(a|t)"),
+        (regex!("Y"), "(c|t)"),
+    ];
+    let mut seq = seq;
+    for (re, replacement) in substs {
+        seq = re.replace_all(&seq, replacement).into_owned();
+    }
+    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
+}
diff --git a/vendor/regex-1.4.6/examples/shootout-regex-dna.rs b/vendor/regex-1.4.6/examples/shootout-regex-dna.rs
new file mode 100644 (file)
index 0000000..4527422
--- /dev/null
@@ -0,0 +1,70 @@
+// The Computer Language Benchmarks Game
+// https://benchmarksgame-team.pages.debian.net/benchmarksgame/
+//
+// contributed by the Rust Project Developers
+// contributed by TeXitoi
+// contributed by BurntSushi
+
+extern crate regex;
+
+use std::io::{self, Read};
+use std::sync::Arc;
+use std::thread;
+
+macro_rules! regex {
+    ($re:expr) => {
+        ::regex::Regex::new($re).unwrap()
+    };
+}
+
+fn main() {
+    let mut seq = String::with_capacity(51 * (1 << 20));
+    io::stdin().read_to_string(&mut seq).unwrap();
+    let ilen = seq.len();
+
+    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
+    let clen = seq.len();
+    let seq_arc = Arc::new(seq.clone());
+
+    let variants = vec![
+        regex!("agggtaaa|tttaccct"),
+        regex!("[cgt]gggtaaa|tttaccc[acg]"),
+        regex!("a[act]ggtaaa|tttacc[agt]t"),
+        regex!("ag[act]gtaaa|tttac[agt]ct"),
+        regex!("agg[act]taaa|ttta[agt]cct"),
+        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
+        regex!("agggt[cgt]aa|tt[acg]accct"),
+        regex!("agggta[cgt]a|t[acg]taccct"),
+        regex!("agggtaa[cgt]|[acg]ttaccct"),
+    ];
+    let mut counts = vec![];
+    for variant in variants {
+        let seq = seq_arc.clone();
+        let restr = variant.to_string();
+        let future = thread::spawn(move || variant.find_iter(&seq).count());
+        counts.push((restr, future));
+    }
+
+    let substs = vec![
+        (regex!("B"), "(c|g|t)"),
+        (regex!("D"), "(a|g|t)"),
+        (regex!("H"), "(a|c|t)"),
+        (regex!("K"), "(g|t)"),
+        (regex!("M"), "(a|c)"),
+        (regex!("N"), "(a|c|g|t)"),
+        (regex!("R"), "(a|g)"),
+        (regex!("S"), "(c|g)"),
+        (regex!("V"), "(a|c|g)"),
+        (regex!("W"), "(a|t)"),
+        (regex!("Y"), "(c|t)"),
+    ];
+    let mut seq = seq;
+    for (re, replacement) in substs {
+        seq = re.replace_all(&seq, replacement).into_owned();
+    }
+
+    for (variant, count) in counts {
+        println!("{} {}", variant, count.join().unwrap());
+    }
+    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
+}
diff --git a/vendor/regex-1.4.6/rustfmt.toml b/vendor/regex-1.4.6/rustfmt.toml
new file mode 100644 (file)
index 0000000..aa37a21
--- /dev/null
@@ -0,0 +1,2 @@
+max_width = 79
+use_small_heuristics = "max"
diff --git a/vendor/regex-1.4.6/src/backtrack.rs b/vendor/regex-1.4.6/src/backtrack.rs
new file mode 100644 (file)
index 0000000..6100c17
--- /dev/null
@@ -0,0 +1,288 @@
+// This is the backtracking matching engine. It has the same exact capability
+// as the full NFA simulation, except it is artificially restricted to small
+// regexes on small inputs because of its memory requirements.
+//
+// In particular, this is a *bounded* backtracking engine. It retains worst
+// case linear time by keeping track of the states that it has visited (using a
+// bitmap). Namely, once a state is visited, it is never visited again. Since a
+// state is keyed by `(instruction index, input index)`, we have that its time
+// complexity is `O(mn)` (i.e., linear in the size of the search text).
+//
+// The backtracking engine can beat out the NFA simulation on small
+// regexes/inputs because it doesn't have to keep track of multiple copies of
+// the capture groups. In benchmarks, the backtracking engine is roughly twice
+// as fast as the full NFA simulation. Note though that its performance doesn't
+// scale, even if you're willing to live with the memory requirements. Namely,
+// the bitset has to be zeroed on each execution, which becomes quite expensive
+// on large bitsets.
+
+use exec::ProgramCache;
+use input::{Input, InputAt};
+use prog::{InstPtr, Program};
+use re_trait::Slot;
+
+type Bits = u32;
+
+const BIT_SIZE: usize = 32;
+const MAX_SIZE_BYTES: usize = 256 * (1 << 10); // 256 KB
+
+/// Returns true iff the given regex and input should be executed by this
+/// engine with reasonable memory usage.
+pub fn should_exec(num_insts: usize, text_len: usize) -> bool {
+    // Total memory usage in bytes is determined by:
+    //
+    //   ((len(insts) * (len(input) + 1) + bits - 1) / bits) * (size_of(u32))
+    //
+    // The actual limit picked is pretty much a heuristic.
+    // See: https://github.com/rust-lang/regex/issues/215
+    let size = ((num_insts * (text_len + 1) + BIT_SIZE - 1) / BIT_SIZE) * 4;
+    size <= MAX_SIZE_BYTES
+}
+
+/// A backtracking matching engine.
+#[derive(Debug)]
+pub struct Bounded<'a, 'm, 'r, 's, I> {
+    prog: &'r Program,
+    input: I,
+    matches: &'m mut [bool],
+    slots: &'s mut [Slot],
+    m: &'a mut Cache,
+}
+
+/// Shared cached state between multiple invocations of a backtracking engine
+/// in the same thread.
+#[derive(Clone, Debug)]
+pub struct Cache {
+    jobs: Vec<Job>,
+    visited: Vec<Bits>,
+}
+
+impl Cache {
+    /// Create new empty cache for the backtracking engine.
+    pub fn new(_prog: &Program) -> Self {
+        Cache { jobs: vec![], visited: vec![] }
+    }
+}
+
+/// A job is an explicit unit of stack space in the backtracking engine.
+///
+/// The "normal" representation is a single state transition, which corresponds
+/// to an NFA state and a character in the input. However, the backtracking
+/// engine must keep track of old capture group values. We use the explicit
+/// stack to do it.
+#[derive(Clone, Copy, Debug)]
+enum Job {
+    Inst { ip: InstPtr, at: InputAt },
+    SaveRestore { slot: usize, old_pos: Option<usize> },
+}
+
+impl<'a, 'm, 'r, 's, I: Input> Bounded<'a, 'm, 'r, 's, I> {
+    /// Execute the backtracking matching engine.
+    ///
+    /// If there's a match, `exec` returns `true` and populates the given
+    /// captures accordingly.
+    pub fn exec(
+        prog: &'r Program,
+        cache: &ProgramCache,
+        matches: &'m mut [bool],
+        slots: &'s mut [Slot],
+        input: I,
+        start: usize,
+        end: usize,
+    ) -> bool {
+        let mut cache = cache.borrow_mut();
+        let cache = &mut cache.backtrack;
+        let start = input.at(start);
+        let mut b = Bounded {
+            prog: prog,
+            input: input,
+            matches: matches,
+            slots: slots,
+            m: cache,
+        };
+        b.exec_(start, end)
+    }
+
+    /// Clears the cache such that the backtracking engine can be executed
+    /// on some input of fixed length.
+    fn clear(&mut self) {
+        // Reset the job memory so that we start fresh.
+        self.m.jobs.clear();
+
+        // Now we need to clear the bit state set.
+        // We do this by figuring out how much space we need to keep track
+        // of the states we've visited.
+        // Then we reset all existing allocated space to 0.
+        // Finally, we request more space if we need it.
+        //
+        // This is all a little circuitous, but doing this using unchecked
+        // operations doesn't seem to have a measurable impact on performance.
+        // (Probably because backtracking is limited to such small
+        // inputs/regexes in the first place.)
+        let visited_len =
+            (self.prog.len() * (self.input.len() + 1) + BIT_SIZE - 1)
+                / BIT_SIZE;
+        self.m.visited.truncate(visited_len);
+        for v in &mut self.m.visited {
+            *v = 0;
+        }
+        if visited_len > self.m.visited.len() {
+            let len = self.m.visited.len();
+            self.m.visited.reserve_exact(visited_len - len);
+            for _ in 0..(visited_len - len) {
+                self.m.visited.push(0);
+            }
+        }
+    }
+
+    /// Start backtracking at the given position in the input, but also look
+    /// for literal prefixes.
+    fn exec_(&mut self, mut at: InputAt, end: usize) -> bool {
+        self.clear();
+        // If this is an anchored regex at the beginning of the input, then
+        // we're either already done or we only need to try backtracking once.
+        if self.prog.is_anchored_start {
+            return if !at.is_start() { false } else { self.backtrack(at) };
+        }
+        let mut matched = false;
+        loop {
+            if !self.prog.prefixes.is_empty() {
+                at = match self.input.prefix_at(&self.prog.prefixes, at) {
+                    None => break,
+                    Some(at) => at,
+                };
+            }
+            matched = self.backtrack(at) || matched;
+            if matched && self.prog.matches.len() == 1 {
+                return true;
+            }
+            if at.pos() >= end {
+                break;
+            }
+            at = self.input.at(at.next_pos());
+        }
+        matched
+    }
+
+    /// The main backtracking loop starting at the given input position.
+    fn backtrack(&mut self, start: InputAt) -> bool {
+        // N.B. We use an explicit stack to avoid recursion.
+        // To avoid excessive pushing and popping, most transitions are handled
+        // in the `step` helper function, which only pushes to the stack when
+        // there's a capture or a branch.
+        let mut matched = false;
+        self.m.jobs.push(Job::Inst { ip: 0, at: start });
+        while let Some(job) = self.m.jobs.pop() {
+            match job {
+                Job::Inst { ip, at } => {
+                    if self.step(ip, at) {
+                        // Only quit if we're matching one regex.
+                        // If we're matching a regex set, then mush on and
+                        // try to find other matches (if we want them).
+                        if self.prog.matches.len() == 1 {
+                            return true;
+                        }
+                        matched = true;
+                    }
+                }
+                Job::SaveRestore { slot, old_pos } => {
+                    if slot < self.slots.len() {
+                        self.slots[slot] = old_pos;
+                    }
+                }
+            }
+        }
+        matched
+    }
+
+    fn step(&mut self, mut ip: InstPtr, mut at: InputAt) -> bool {
+        use prog::Inst::*;
+        loop {
+            // This loop is an optimization to avoid constantly pushing/popping
+            // from the stack. Namely, if we're pushing a job only to run it
+            // next, avoid the push and just mutate `ip` (and possibly `at`)
+            // in place.
+            if self.has_visited(ip, at) {
+                return false;
+            }
+            match self.prog[ip] {
+                Match(slot) => {
+                    if slot < self.matches.len() {
+                        self.matches[slot] = true;
+                    }
+                    return true;
+                }
+                Save(ref inst) => {
+                    if let Some(&old_pos) = self.slots.get(inst.slot) {
+                        // If this path doesn't work out, then we save the old
+                        // capture index (if one exists) in an alternate
+                        // job. If the next path fails, then the alternate
+                        // job is popped and the old capture index is restored.
+                        self.m.jobs.push(Job::SaveRestore {
+                            slot: inst.slot,
+                            old_pos: old_pos,
+                        });
+                        self.slots[inst.slot] = Some(at.pos());
+                    }
+                    ip = inst.goto;
+                }
+                Split(ref inst) => {
+                    self.m.jobs.push(Job::Inst { ip: inst.goto2, at: at });
+                    ip = inst.goto1;
+                }
+                EmptyLook(ref inst) => {
+                    if self.input.is_empty_match(at, inst) {
+                        ip = inst.goto;
+                    } else {
+                        return false;
+                    }
+                }
+                Char(ref inst) => {
+                    if inst.c == at.char() {
+                        ip = inst.goto;
+                        at = self.input.at(at.next_pos());
+                    } else {
+                        return false;
+                    }
+                }
+                Ranges(ref inst) => {
+                    if inst.matches(at.char()) {
+                        ip = inst.goto;
+                        at = self.input.at(at.next_pos());
+                    } else {
+                        return false;
+                    }
+                }
+                Bytes(ref inst) => {
+                    if let Some(b) = at.byte() {
+                        if inst.matches(b) {
+                            ip = inst.goto;
+                            at = self.input.at(at.next_pos());
+                            continue;
+                        }
+                    }
+                    return false;
+                }
+            }
+        }
+    }
+
+    fn has_visited(&mut self, ip: InstPtr, at: InputAt) -> bool {
+        let k = ip * (self.input.len() + 1) + at.pos();
+        let k1 = k / BIT_SIZE;
+        let k2 = usize_to_u32(1 << (k & (BIT_SIZE - 1)));
+        if self.m.visited[k1] & k2 == 0 {
+            self.m.visited[k1] |= k2;
+            false
+        } else {
+            true
+        }
+    }
+}
+
+fn usize_to_u32(n: usize) -> u32 {
+    if (n as u64) > (::std::u32::MAX as u64) {
+        panic!("BUG: {} is too big to fit into u32", n)
+    }
+    n as u32
+}
diff --git a/vendor/regex-1.4.6/src/compile.rs b/vendor/regex-1.4.6/src/compile.rs
new file mode 100644 (file)
index 0000000..9bbd464
--- /dev/null
@@ -0,0 +1,1235 @@
+use std::collections::HashMap;
+use std::fmt;
+use std::iter;
+use std::result;
+use std::sync::Arc;
+
+use syntax::hir::{self, Hir};
+use syntax::is_word_byte;
+use syntax::utf8::{Utf8Range, Utf8Sequence, Utf8Sequences};
+
+use prog::{
+    EmptyLook, Inst, InstBytes, InstChar, InstEmptyLook, InstPtr, InstRanges,
+    InstSave, InstSplit, Program,
+};
+
+use Error;
+
+type Result = result::Result<Patch, Error>;
+type ResultOrEmpty = result::Result<Option<Patch>, Error>;
+
+#[derive(Debug)]
+struct Patch {
+    hole: Hole,
+    entry: InstPtr,
+}
+
+/// A compiler translates a regular expression AST to a sequence of
+/// instructions. The sequence of instructions represents an NFA.
+// `Compiler` is only public via the `internal` module, so avoid deriving
+// `Debug`.
+#[allow(missing_debug_implementations)]
+pub struct Compiler {
+    insts: Vec<MaybeInst>,
+    compiled: Program,
+    capture_name_idx: HashMap<String, usize>,
+    num_exprs: usize,
+    size_limit: usize,
+    suffix_cache: SuffixCache,
+    utf8_seqs: Option<Utf8Sequences>,
+    byte_classes: ByteClassSet,
+    extra_inst_bytes: usize,
+}
+
+impl Compiler {
+    /// Create a new regular expression compiler.
+    ///
+    /// Various options can be set before calling `compile` on an expression.
+    pub fn new() -> Self {
+        Compiler {
+            insts: vec![],
+            compiled: Program::new(),
+            capture_name_idx: HashMap::new(),
+            num_exprs: 0,
+            size_limit: 10 * (1 << 20),
+            suffix_cache: SuffixCache::new(1000),
+            utf8_seqs: Some(Utf8Sequences::new('\x00', '\x00')),
+            byte_classes: ByteClassSet::new(),
+            extra_inst_bytes: 0,
+        }
+    }
+
+    /// The size of the resulting program is limited by size_limit. If
+    /// the program approximately exceeds the given size (in bytes), then
+    /// compilation will stop and return an error.
+    pub fn size_limit(mut self, size_limit: usize) -> Self {
+        self.size_limit = size_limit;
+        self
+    }
+
+    /// If bytes is true, then the program is compiled as a byte based
+    /// automaton, which incorporates UTF-8 decoding into the machine. If it's
+    /// false, then the automaton is Unicode scalar value based, e.g., an
+    /// engine utilizing such an automaton is responsible for UTF-8 decoding.
+    ///
+    /// The specific invariant is that when returning a byte based machine,
+    /// the neither the `Char` nor `Ranges` instructions are produced.
+    /// Conversely, when producing a Unicode scalar value machine, the `Bytes`
+    /// instruction is never produced.
+    ///
+    /// Note that `dfa(true)` implies `bytes(true)`.
+    pub fn bytes(mut self, yes: bool) -> Self {
+        self.compiled.is_bytes = yes;
+        self
+    }
+
+    /// When disabled, the program compiled may match arbitrary bytes.
+    ///
+    /// When enabled (the default), all compiled programs exclusively match
+    /// valid UTF-8 bytes.
+    pub fn only_utf8(mut self, yes: bool) -> Self {
+        self.compiled.only_utf8 = yes;
+        self
+    }
+
+    /// When set, the machine returned is suitable for use in the DFA matching
+    /// engine.
+    ///
+    /// In particular, this ensures that if the regex is not anchored in the
+    /// beginning, then a preceding `.*?` is included in the program. (The NFA
+    /// based engines handle the preceding `.*?` explicitly, which is difficult
+    /// or impossible in the DFA engine.)
+    pub fn dfa(mut self, yes: bool) -> Self {
+        self.compiled.is_dfa = yes;
+        self
+    }
+
+    /// When set, the machine returned is suitable for matching text in
+    /// reverse. In particular, all concatenations are flipped.
+    pub fn reverse(mut self, yes: bool) -> Self {
+        self.compiled.is_reverse = yes;
+        self
+    }
+
+    /// Compile a regular expression given its AST.
+    ///
+    /// The compiler is guaranteed to succeed unless the program exceeds the
+    /// specified size limit. If the size limit is exceeded, then compilation
+    /// stops and returns an error.
+    pub fn compile(mut self, exprs: &[Hir]) -> result::Result<Program, Error> {
+        debug_assert!(!exprs.is_empty());
+        self.num_exprs = exprs.len();
+        if exprs.len() == 1 {
+            self.compile_one(&exprs[0])
+        } else {
+            self.compile_many(exprs)
+        }
+    }
+
+    fn compile_one(mut self, expr: &Hir) -> result::Result<Program, Error> {
+        // If we're compiling a forward DFA and we aren't anchored, then
+        // add a `.*?` before the first capture group.
+        // Other matching engines handle this by baking the logic into the
+        // matching engine itself.
+        let mut dotstar_patch = Patch { hole: Hole::None, entry: 0 };
+        self.compiled.is_anchored_start = expr.is_anchored_start();
+        self.compiled.is_anchored_end = expr.is_anchored_end();
+        if self.compiled.needs_dotstar() {
+            dotstar_patch = self.c_dotstar()?;
+            self.compiled.start = dotstar_patch.entry;
+        }
+        self.compiled.captures = vec![None];
+        let patch = self.c_capture(0, expr)?.unwrap_or(self.next_inst());
+        if self.compiled.needs_dotstar() {
+            self.fill(dotstar_patch.hole, patch.entry);
+        } else {
+            self.compiled.start = patch.entry;
+        }
+        self.fill_to_next(patch.hole);
+        self.compiled.matches = vec![self.insts.len()];
+        self.push_compiled(Inst::Match(0));
+        self.compile_finish()
+    }
+
+    fn compile_many(
+        mut self,
+        exprs: &[Hir],
+    ) -> result::Result<Program, Error> {
+        debug_assert!(exprs.len() > 1);
+
+        self.compiled.is_anchored_start =
+            exprs.iter().all(|e| e.is_anchored_start());
+        self.compiled.is_anchored_end =
+            exprs.iter().all(|e| e.is_anchored_end());
+        let mut dotstar_patch = Patch { hole: Hole::None, entry: 0 };
+        if self.compiled.needs_dotstar() {
+            dotstar_patch = self.c_dotstar()?;
+            self.compiled.start = dotstar_patch.entry;
+        } else {
+            self.compiled.start = 0; // first instruction is always split
+        }
+        self.fill_to_next(dotstar_patch.hole);
+
+        let mut prev_hole = Hole::None;
+        for (i, expr) in exprs[0..exprs.len() - 1].iter().enumerate() {
+            self.fill_to_next(prev_hole);
+            let split = self.push_split_hole();
+            let Patch { hole, entry } =
+                self.c_capture(0, expr)?.unwrap_or(self.next_inst());
+            self.fill_to_next(hole);
+            self.compiled.matches.push(self.insts.len());
+            self.push_compiled(Inst::Match(i));
+            prev_hole = self.fill_split(split, Some(entry), None);
+        }
+        let i = exprs.len() - 1;
+        let Patch { hole, entry } =
+            self.c_capture(0, &exprs[i])?.unwrap_or(self.next_inst());
+        self.fill(prev_hole, entry);
+        self.fill_to_next(hole);
+        self.compiled.matches.push(self.insts.len());
+        self.push_compiled(Inst::Match(i));
+        self.compile_finish()
+    }
+
+    fn compile_finish(mut self) -> result::Result<Program, Error> {
+        self.compiled.insts =
+            self.insts.into_iter().map(|inst| inst.unwrap()).collect();
+        self.compiled.byte_classes = self.byte_classes.byte_classes();
+        self.compiled.capture_name_idx = Arc::new(self.capture_name_idx);
+        Ok(self.compiled)
+    }
+
+    /// Compile expr into self.insts, returning a patch on success,
+    /// or an error if we run out of memory.
+    ///
+    /// All of the c_* methods of the compiler share the contract outlined
+    /// here.
+    ///
+    /// The main thing that a c_* method does is mutate `self.insts`
+    /// to add a list of mostly compiled instructions required to execute
+    /// the given expression. `self.insts` contains MaybeInsts rather than
+    /// Insts because there is some backpatching required.
+    ///
+    /// The `Patch` value returned by each c_* method provides metadata
+    /// about the compiled instructions emitted to `self.insts`. The
+    /// `entry` member of the patch refers to the first instruction
+    /// (the entry point), while the `hole` member contains zero or
+    /// more offsets to partial instructions that need to be backpatched.
+    /// The c_* routine can't know where its list of instructions are going to
+    /// jump to after execution, so it is up to the caller to patch
+    /// these jumps to point to the right place. So compiling some
+    /// expression, e, we would end up with a situation that looked like:
+    ///
+    /// ```text
+    /// self.insts = [ ..., i1, i2, ..., iexit1, ..., iexitn, ...]
+    ///                     ^              ^             ^
+    ///                     |                \         /
+    ///                   entry                \     /
+    ///                                         hole
+    /// ```
+    ///
+    /// To compile two expressions, e1 and e2, concatenated together we
+    /// would do:
+    ///
+    /// ```ignore
+    /// let patch1 = self.c(e1);
+    /// let patch2 = self.c(e2);
+    /// ```
+    ///
+    /// while leaves us with a situation that looks like
+    ///
+    /// ```text
+    /// self.insts = [ ..., i1, ..., iexit1, ..., i2, ..., iexit2 ]
+    ///                     ^        ^            ^        ^
+    ///                     |        |            |        |
+    ///                entry1        hole1   entry2        hole2
+    /// ```
+    ///
+    /// Then to merge the two patches together into one we would backpatch
+    /// hole1 with entry2 and return a new patch that enters at entry1
+    /// and has hole2 for a hole. In fact, if you look at the c_concat
+    /// method you will see that it does exactly this, though it handles
+    /// a list of expressions rather than just the two that we use for
+    /// an example.
+    ///
+    /// Ok(None) is returned when an expression is compiled to no
+    /// instruction, and so no patch.entry value makes sense.
+    fn c(&mut self, expr: &Hir) -> ResultOrEmpty {
+        use prog;
+        use syntax::hir::HirKind::*;
+
+        self.check_size()?;
+        match *expr.kind() {
+            Empty => Ok(None),
+            Literal(hir::Literal::Unicode(c)) => self.c_char(c),
+            Literal(hir::Literal::Byte(b)) => {
+                assert!(self.compiled.uses_bytes());
+                self.c_byte(b)
+            }
+            Class(hir::Class::Unicode(ref cls)) => self.c_class(cls.ranges()),
+            Class(hir::Class::Bytes(ref cls)) => {
+                if self.compiled.uses_bytes() {
+                    self.c_class_bytes(cls.ranges())
+                } else {
+                    assert!(cls.is_all_ascii());
+                    let mut char_ranges = vec![];
+                    for r in cls.iter() {
+                        let (s, e) = (r.start() as char, r.end() as char);
+                        char_ranges.push(hir::ClassUnicodeRange::new(s, e));
+                    }
+                    self.c_class(&char_ranges)
+                }
+            }
+            Anchor(hir::Anchor::StartLine) if self.compiled.is_reverse => {
+                self.byte_classes.set_range(b'\n', b'\n');
+                self.c_empty_look(prog::EmptyLook::EndLine)
+            }
+            Anchor(hir::Anchor::StartLine) => {
+                self.byte_classes.set_range(b'\n', b'\n');
+                self.c_empty_look(prog::EmptyLook::StartLine)
+            }
+            Anchor(hir::Anchor::EndLine) if self.compiled.is_reverse => {
+                self.byte_classes.set_range(b'\n', b'\n');
+                self.c_empty_look(prog::EmptyLook::StartLine)
+            }
+            Anchor(hir::Anchor::EndLine) => {
+                self.byte_classes.set_range(b'\n', b'\n');
+                self.c_empty_look(prog::EmptyLook::EndLine)
+            }
+            Anchor(hir::Anchor::StartText) if self.compiled.is_reverse => {
+                self.c_empty_look(prog::EmptyLook::EndText)
+            }
+            Anchor(hir::Anchor::StartText) => {
+                self.c_empty_look(prog::EmptyLook::StartText)
+            }
+            Anchor(hir::Anchor::EndText) if self.compiled.is_reverse => {
+                self.c_empty_look(prog::EmptyLook::StartText)
+            }
+            Anchor(hir::Anchor::EndText) => {
+                self.c_empty_look(prog::EmptyLook::EndText)
+            }
+            WordBoundary(hir::WordBoundary::Unicode) => {
+                if !cfg!(feature = "unicode-perl") {
+                    return Err(Error::Syntax(
+                        "Unicode word boundaries are unavailable when \
+                         the unicode-perl feature is disabled"
+                            .to_string(),
+                    ));
+                }
+                self.compiled.has_unicode_word_boundary = true;
+                self.byte_classes.set_word_boundary();
+                self.c_empty_look(prog::EmptyLook::WordBoundary)
+            }
+            WordBoundary(hir::WordBoundary::UnicodeNegate) => {
+                if !cfg!(feature = "unicode-perl") {
+                    return Err(Error::Syntax(
+                        "Unicode word boundaries are unavailable when \
+                         the unicode-perl feature is disabled"
+                            .to_string(),
+                    ));
+                }
+                self.compiled.has_unicode_word_boundary = true;
+                self.byte_classes.set_word_boundary();
+                self.c_empty_look(prog::EmptyLook::NotWordBoundary)
+            }
+            WordBoundary(hir::WordBoundary::Ascii) => {
+                self.byte_classes.set_word_boundary();
+                self.c_empty_look(prog::EmptyLook::WordBoundaryAscii)
+            }
+            WordBoundary(hir::WordBoundary::AsciiNegate) => {
+                self.byte_classes.set_word_boundary();
+                self.c_empty_look(prog::EmptyLook::NotWordBoundaryAscii)
+            }
+            Group(ref g) => match g.kind {
+                hir::GroupKind::NonCapturing => self.c(&g.hir),
+                hir::GroupKind::CaptureIndex(index) => {
+                    if index as usize >= self.compiled.captures.len() {
+                        self.compiled.captures.push(None);
+                    }
+                    self.c_capture(2 * index as usize, &g.hir)
+                }
+                hir::GroupKind::CaptureName { index, ref name } => {
+                    if index as usize >= self.compiled.captures.len() {
+                        let n = name.to_string();
+                        self.compiled.captures.push(Some(n.clone()));
+                        self.capture_name_idx.insert(n, index as usize);
+                    }
+                    self.c_capture(2 * index as usize, &g.hir)
+                }
+            },
+            Concat(ref es) => {
+                if self.compiled.is_reverse {
+                    self.c_concat(es.iter().rev())
+                } else {
+                    self.c_concat(es)
+                }
+            }
+            Alternation(ref es) => self.c_alternate(&**es),
+            Repetition(ref rep) => self.c_repeat(rep),
+        }
+    }
+
+    fn c_capture(&mut self, first_slot: usize, expr: &Hir) -> ResultOrEmpty {
+        if self.num_exprs > 1 || self.compiled.is_dfa {
+            // Don't ever compile Save instructions for regex sets because
+            // they are never used. They are also never used in DFA programs
+            // because DFAs can't handle captures.
+            self.c(expr)
+        } else {
+            let entry = self.insts.len();
+            let hole = self.push_hole(InstHole::Save { slot: first_slot });
+            let patch = self.c(expr)?.unwrap_or(self.next_inst());
+            self.fill(hole, patch.entry);
+            self.fill_to_next(patch.hole);
+            let hole = self.push_hole(InstHole::Save { slot: first_slot + 1 });
+            Ok(Some(Patch { hole: hole, entry: entry }))
+        }
+    }
+
+    fn c_dotstar(&mut self) -> Result {
+        Ok(if !self.compiled.only_utf8() {
+            self.c(&Hir::repetition(hir::Repetition {
+                kind: hir::RepetitionKind::ZeroOrMore,
+                greedy: false,
+                hir: Box::new(Hir::any(true)),
+            }))?
+            .unwrap()
+        } else {
+            self.c(&Hir::repetition(hir::Repetition {
+                kind: hir::RepetitionKind::ZeroOrMore,
+                greedy: false,
+                hir: Box::new(Hir::any(false)),
+            }))?
+            .unwrap()
+        })
+    }
+
+    fn c_char(&mut self, c: char) -> ResultOrEmpty {
+        if self.compiled.uses_bytes() {
+            if c.is_ascii() {
+                let b = c as u8;
+                let hole =
+                    self.push_hole(InstHole::Bytes { start: b, end: b });
+                self.byte_classes.set_range(b, b);
+                Ok(Some(Patch { hole, entry: self.insts.len() - 1 }))
+            } else {
+                self.c_class(&[hir::ClassUnicodeRange::new(c, c)])
+            }
+        } else {
+            let hole = self.push_hole(InstHole::Char { c: c });
+            Ok(Some(Patch { hole, entry: self.insts.len() - 1 }))
+        }
+    }
+
+    fn c_class(&mut self, ranges: &[hir::ClassUnicodeRange]) -> ResultOrEmpty {
+        use std::mem::size_of;
+
+        assert!(!ranges.is_empty());
+        if self.compiled.uses_bytes() {
+            Ok(Some(CompileClass { c: self, ranges: ranges }.compile()?))
+        } else {
+            let ranges: Vec<(char, char)> =
+                ranges.iter().map(|r| (r.start(), r.end())).collect();
+            let hole = if ranges.len() == 1 && ranges[0].0 == ranges[0].1 {
+                self.push_hole(InstHole::Char { c: ranges[0].0 })
+            } else {
+                self.extra_inst_bytes +=
+                    ranges.len() * (size_of::<char>() * 2);
+                self.push_hole(InstHole::Ranges { ranges: ranges })
+            };
+            Ok(Some(Patch { hole: hole, entry: self.insts.len() - 1 }))
+        }
+    }
+
+    fn c_byte(&mut self, b: u8) -> ResultOrEmpty {
+        self.c_class_bytes(&[hir::ClassBytesRange::new(b, b)])
+    }
+
+    fn c_class_bytes(
+        &mut self,
+        ranges: &[hir::ClassBytesRange],
+    ) -> ResultOrEmpty {
+        debug_assert!(!ranges.is_empty());
+
+        let first_split_entry = self.insts.len();
+        let mut holes = vec![];
+        let mut prev_hole = Hole::None;
+        for r in &ranges[0..ranges.len() - 1] {
+            self.fill_to_next(prev_hole);
+            let split = self.push_split_hole();
+            let next = self.insts.len();
+            self.byte_classes.set_range(r.start(), r.end());
+            holes.push(self.push_hole(InstHole::Bytes {
+                start: r.start(),
+                end: r.end(),
+            }));
+            prev_hole = self.fill_split(split, Some(next), None);
+        }
+        let next = self.insts.len();
+        let r = &ranges[ranges.len() - 1];
+        self.byte_classes.set_range(r.start(), r.end());
+        holes.push(
+            self.push_hole(InstHole::Bytes { start: r.start(), end: r.end() }),
+        );
+        self.fill(prev_hole, next);
+        Ok(Some(Patch { hole: Hole::Many(holes), entry: first_split_entry }))
+    }
+
+    fn c_empty_look(&mut self, look: EmptyLook) -> ResultOrEmpty {
+        let hole = self.push_hole(InstHole::EmptyLook { look: look });
+        Ok(Some(Patch { hole: hole, entry: self.insts.len() - 1 }))
+    }
+
+    fn c_concat<'a, I>(&mut self, exprs: I) -> ResultOrEmpty
+    where
+        I: IntoIterator<Item = &'a Hir>,
+    {
+        let mut exprs = exprs.into_iter();
+        let Patch { mut hole, entry } = loop {
+            match exprs.next() {
+                None => return Ok(None),
+                Some(e) => {
+                    if let Some(p) = self.c(e)? {
+                        break p;
+                    }
+                }
+            }
+        };
+        for e in exprs {
+            if let Some(p) = self.c(e)? {
+                self.fill(hole, p.entry);
+                hole = p.hole;
+            }
+        }
+        Ok(Some(Patch { hole: hole, entry: entry }))
+    }
+
+    fn c_alternate(&mut self, exprs: &[Hir]) -> ResultOrEmpty {
+        debug_assert!(
+            exprs.len() >= 2,
+            "alternates must have at least 2 exprs"
+        );
+
+        // Initial entry point is always the first split.
+        let first_split_entry = self.insts.len();
+
+        // Save up all of the holes from each alternate. They will all get
+        // patched to point to the same location.
+        let mut holes = vec![];
+
+        // true indicates that the hole is a split where we want to fill
+        // the second branch.
+        let mut prev_hole = (Hole::None, false);
+        for e in &exprs[0..exprs.len() - 1] {
+            if prev_hole.1 {
+                let next = self.insts.len();
+                self.fill_split(prev_hole.0, None, Some(next));
+            } else {
+                self.fill_to_next(prev_hole.0);
+            }
+            let split = self.push_split_hole();
+            if let Some(Patch { hole, entry }) = self.c(e)? {
+                holes.push(hole);
+                prev_hole = (self.fill_split(split, Some(entry), None), false);
+            } else {
+                let (split1, split2) = split.dup_one();
+                holes.push(split1);
+                prev_hole = (split2, true);
+            }
+        }
+        if let Some(Patch { hole, entry }) = self.c(&exprs[exprs.len() - 1])? {
+            holes.push(hole);
+            if prev_hole.1 {
+                self.fill_split(prev_hole.0, None, Some(entry));
+            } else {
+                self.fill(prev_hole.0, entry);
+            }
+        } else {
+            // We ignore prev_hole.1. When it's true, it means we have two
+            // empty branches both pushing prev_hole.0 into holes, so both
+            // branches will go to the same place anyway.
+            holes.push(prev_hole.0);
+        }
+        Ok(Some(Patch { hole: Hole::Many(holes), entry: first_split_entry }))
+    }
+
+    fn c_repeat(&mut self, rep: &hir::Repetition) -> ResultOrEmpty {
+        use syntax::hir::RepetitionKind::*;
+        match rep.kind {
+            ZeroOrOne => self.c_repeat_zero_or_one(&rep.hir, rep.greedy),
+            ZeroOrMore => self.c_repeat_zero_or_more(&rep.hir, rep.greedy),
+            OneOrMore => self.c_repeat_one_or_more(&rep.hir, rep.greedy),
+            Range(hir::RepetitionRange::Exactly(min_max)) => {
+                self.c_repeat_range(&rep.hir, rep.greedy, min_max, min_max)
+            }
+            Range(hir::RepetitionRange::AtLeast(min)) => {
+                self.c_repeat_range_min_or_more(&rep.hir, rep.greedy, min)
+            }
+            Range(hir::RepetitionRange::Bounded(min, max)) => {
+                self.c_repeat_range(&rep.hir, rep.greedy, min, max)
+            }
+        }
+    }
+
+    fn c_repeat_zero_or_one(
+        &mut self,
+        expr: &Hir,
+        greedy: bool,
+    ) -> ResultOrEmpty {
+        let split_entry = self.insts.len();
+        let split = self.push_split_hole();
+        let Patch { hole: hole_rep, entry: entry_rep } = match self.c(expr)? {
+            Some(p) => p,
+            None => return self.pop_split_hole(),
+        };
+        let split_hole = if greedy {
+            self.fill_split(split, Some(entry_rep), None)
+        } else {
+            self.fill_split(split, None, Some(entry_rep))
+        };
+        let holes = vec![hole_rep, split_hole];
+        Ok(Some(Patch { hole: Hole::Many(holes), entry: split_entry }))
+    }
+
+    fn c_repeat_zero_or_more(
+        &mut self,
+        expr: &Hir,
+        greedy: bool,
+    ) -> ResultOrEmpty {
+        let split_entry = self.insts.len();
+        let split = self.push_split_hole();
+        let Patch { hole: hole_rep, entry: entry_rep } = match self.c(expr)? {
+            Some(p) => p,
+            None => return self.pop_split_hole(),
+        };
+
+        self.fill(hole_rep, split_entry);
+        let split_hole = if greedy {
+            self.fill_split(split, Some(entry_rep), None)
+        } else {
+            self.fill_split(split, None, Some(entry_rep))
+        };
+        Ok(Some(Patch { hole: split_hole, entry: split_entry }))
+    }
+
+    fn c_repeat_one_or_more(
+        &mut self,
+        expr: &Hir,
+        greedy: bool,
+    ) -> ResultOrEmpty {
+        let Patch { hole: hole_rep, entry: entry_rep } = match self.c(expr)? {
+            Some(p) => p,
+            None => return Ok(None),
+        };
+        self.fill_to_next(hole_rep);
+        let split = self.push_split_hole();
+
+        let split_hole = if greedy {
+            self.fill_split(split, Some(entry_rep), None)
+        } else {
+            self.fill_split(split, None, Some(entry_rep))
+        };
+        Ok(Some(Patch { hole: split_hole, entry: entry_rep }))
+    }
+
+    fn c_repeat_range_min_or_more(
+        &mut self,
+        expr: &Hir,
+        greedy: bool,
+        min: u32,
+    ) -> ResultOrEmpty {
+        let min = u32_to_usize(min);
+        // Using next_inst() is ok, because we can't return it (concat would
+        // have to return Some(_) while c_repeat_range_min_or_more returns
+        // None).
+        let patch_concat = self
+            .c_concat(iter::repeat(expr).take(min))?
+            .unwrap_or(self.next_inst());
+        if let Some(patch_rep) = self.c_repeat_zero_or_more(expr, greedy)? {
+            self.fill(patch_concat.hole, patch_rep.entry);
+            Ok(Some(Patch { hole: patch_rep.hole, entry: patch_concat.entry }))
+        } else {
+            Ok(None)
+        }
+    }
+
+    fn c_repeat_range(
+        &mut self,
+        expr: &Hir,
+        greedy: bool,
+        min: u32,
+        max: u32,
+    ) -> ResultOrEmpty {
+        let (min, max) = (u32_to_usize(min), u32_to_usize(max));
+        debug_assert!(min <= max);
+        let patch_concat = self.c_concat(iter::repeat(expr).take(min))?;
+        if min == max {
+            return Ok(patch_concat);
+        }
+        // Same reasoning as in c_repeat_range_min_or_more (we know that min <
+        // max at this point).
+        let patch_concat = patch_concat.unwrap_or(self.next_inst());
+        let initial_entry = patch_concat.entry;
+        // It is much simpler to compile, e.g., `a{2,5}` as:
+        //
+        //     aaa?a?a?
+        //
+        // But you end up with a sequence of instructions like this:
+        //
+        //     0: 'a'
+        //     1: 'a',
+        //     2: split(3, 4)
+        //     3: 'a'
+        //     4: split(5, 6)
+        //     5: 'a'
+        //     6: split(7, 8)
+        //     7: 'a'
+        //     8: MATCH
+        //
+        // This is *incredibly* inefficient because the splits end
+        // up forming a chain, which has to be resolved everything a
+        // transition is followed.
+        let mut holes = vec![];
+        let mut prev_hole = patch_concat.hole;
+        for _ in min..max {
+            self.fill_to_next(prev_hole);
+            let split = self.push_split_hole();
+            let Patch { hole, entry } = match self.c(expr)? {
+                Some(p) => p,
+                None => return self.pop_split_hole(),
+            };
+            prev_hole = hole;
+            if greedy {
+                holes.push(self.fill_split(split, Some(entry), None));
+            } else {
+                holes.push(self.fill_split(split, None, Some(entry)));
+            }
+        }
+        holes.push(prev_hole);
+        Ok(Some(Patch { hole: Hole::Many(holes), entry: initial_entry }))
+    }
+
+    /// Can be used as a default value for the c_* functions when the call to
+    /// c_function is followed by inserting at least one instruction that is
+    /// always executed after the ones written by the c* function.
+    fn next_inst(&self) -> Patch {
+        Patch { hole: Hole::None, entry: self.insts.len() }
+    }
+
+    fn fill(&mut self, hole: Hole, goto: InstPtr) {
+        match hole {
+            Hole::None => {}
+            Hole::One(pc) => {
+                self.insts[pc].fill(goto);
+            }
+            Hole::Many(holes) => {
+                for hole in holes {
+                    self.fill(hole, goto);
+                }
+            }
+        }
+    }
+
+    fn fill_to_next(&mut self, hole: Hole) {
+        let next = self.insts.len();
+        self.fill(hole, next);
+    }
+
+    fn fill_split(
+        &mut self,
+        hole: Hole,
+        goto1: Option<InstPtr>,
+        goto2: Option<InstPtr>,
+    ) -> Hole {
+        match hole {
+            Hole::None => Hole::None,
+            Hole::One(pc) => match (goto1, goto2) {
+                (Some(goto1), Some(goto2)) => {
+                    self.insts[pc].fill_split(goto1, goto2);
+                    Hole::None
+                }
+                (Some(goto1), None) => {
+                    self.insts[pc].half_fill_split_goto1(goto1);
+                    Hole::One(pc)
+                }
+                (None, Some(goto2)) => {
+                    self.insts[pc].half_fill_split_goto2(goto2);
+                    Hole::One(pc)
+                }
+                (None, None) => unreachable!(
+                    "at least one of the split \
+                     holes must be filled"
+                ),
+            },
+            Hole::Many(holes) => {
+                let mut new_holes = vec![];
+                for hole in holes {
+                    new_holes.push(self.fill_split(hole, goto1, goto2));
+                }
+                if new_holes.is_empty() {
+                    Hole::None
+                } else if new_holes.len() == 1 {
+                    new_holes.pop().unwrap()
+                } else {
+                    Hole::Many(new_holes)
+                }
+            }
+        }
+    }
+
+    fn push_compiled(&mut self, inst: Inst) {
+        self.insts.push(MaybeInst::Compiled(inst));
+    }
+
+    fn push_hole(&mut self, inst: InstHole) -> Hole {
+        let hole = self.insts.len();
+        self.insts.push(MaybeInst::Uncompiled(inst));
+        Hole::One(hole)
+    }
+
+    fn push_split_hole(&mut self) -> Hole {
+        let hole = self.insts.len();
+        self.insts.push(MaybeInst::Split);
+        Hole::One(hole)
+    }
+
+    fn pop_split_hole(&mut self) -> ResultOrEmpty {
+        self.insts.pop();
+        Ok(None)
+    }
+
+    fn check_size(&self) -> result::Result<(), Error> {
+        use std::mem::size_of;
+
+        let size =
+            self.extra_inst_bytes + (self.insts.len() * size_of::<Inst>());
+        if size > self.size_limit {
+            Err(Error::CompiledTooBig(self.size_limit))
+        } else {
+            Ok(())
+        }
+    }
+}
+
+#[derive(Debug)]
+enum Hole {
+    None,
+    One(InstPtr),
+    Many(Vec<Hole>),
+}
+
+impl Hole {
+    fn dup_one(self) -> (Self, Self) {
+        match self {
+            Hole::One(pc) => (Hole::One(pc), Hole::One(pc)),
+            Hole::None | Hole::Many(_) => {
+                unreachable!("must be called on single hole")
+            }
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+enum MaybeInst {
+    Compiled(Inst),
+    Uncompiled(InstHole),
+    Split,
+    Split1(InstPtr),
+    Split2(InstPtr),
+}
+
+impl MaybeInst {
+    fn fill(&mut self, goto: InstPtr) {
+        let maybeinst = match *self {
+            MaybeInst::Split => MaybeInst::Split1(goto),
+            MaybeInst::Uncompiled(ref inst) => {
+                MaybeInst::Compiled(inst.fill(goto))
+            }
+            MaybeInst::Split1(goto1) => {
+                MaybeInst::Compiled(Inst::Split(InstSplit {
+                    goto1: goto1,
+                    goto2: goto,
+                }))
+            }
+            MaybeInst::Split2(goto2) => {
+                MaybeInst::Compiled(Inst::Split(InstSplit {
+                    goto1: goto,
+                    goto2: goto2,
+                }))
+            }
+            _ => unreachable!(
+                "not all instructions were compiled! \
+                 found uncompiled instruction: {:?}",
+                self
+            ),
+        };
+        *self = maybeinst;
+    }
+
+    fn fill_split(&mut self, goto1: InstPtr, goto2: InstPtr) {
+        let filled = match *self {
+            MaybeInst::Split => {
+                Inst::Split(InstSplit { goto1: goto1, goto2: goto2 })
+            }
+            _ => unreachable!(
+                "must be called on Split instruction, \
+                 instead it was called on: {:?}",
+                self
+            ),
+        };
+        *self = MaybeInst::Compiled(filled);
+    }
+
+    fn half_fill_split_goto1(&mut self, goto1: InstPtr) {
+        let half_filled = match *self {
+            MaybeInst::Split => goto1,
+            _ => unreachable!(
+                "must be called on Split instruction, \
+                 instead it was called on: {:?}",
+                self
+            ),
+        };
+        *self = MaybeInst::Split1(half_filled);
+    }
+
+    fn half_fill_split_goto2(&mut self, goto2: InstPtr) {
+        let half_filled = match *self {
+            MaybeInst::Split => goto2,
+            _ => unreachable!(
+                "must be called on Split instruction, \
+                 instead it was called on: {:?}",
+                self
+            ),
+        };
+        *self = MaybeInst::Split2(half_filled);
+    }
+
+    fn unwrap(self) -> Inst {
+        match self {
+            MaybeInst::Compiled(inst) => inst,
+            _ => unreachable!(
+                "must be called on a compiled instruction, \
+                 instead it was called on: {:?}",
+                self
+            ),
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+enum InstHole {
+    Save { slot: usize },
+    EmptyLook { look: EmptyLook },
+    Char { c: char },
+    Ranges { ranges: Vec<(char, char)> },
+    Bytes { start: u8, end: u8 },
+}
+
+impl InstHole {
+    fn fill(&self, goto: InstPtr) -> Inst {
+        match *self {
+            InstHole::Save { slot } => {
+                Inst::Save(InstSave { goto: goto, slot: slot })
+            }
+            InstHole::EmptyLook { look } => {
+                Inst::EmptyLook(InstEmptyLook { goto: goto, look: look })
+            }
+            InstHole::Char { c } => Inst::Char(InstChar { goto: goto, c: c }),
+            InstHole::Ranges { ref ranges } => Inst::Ranges(InstRanges {
+                goto: goto,
+                ranges: ranges.clone().into_boxed_slice(),
+            }),
+            InstHole::Bytes { start, end } => {
+                Inst::Bytes(InstBytes { goto: goto, start: start, end: end })
+            }
+        }
+    }
+}
+
+struct CompileClass<'a, 'b> {
+    c: &'a mut Compiler,
+    ranges: &'b [hir::ClassUnicodeRange],
+}
+
+impl<'a, 'b> CompileClass<'a, 'b> {
+    fn compile(mut self) -> Result {
+        let mut holes = vec![];
+        let mut initial_entry = None;
+        let mut last_split = Hole::None;
+        let mut utf8_seqs = self.c.utf8_seqs.take().unwrap();
+        self.c.suffix_cache.clear();
+
+        for (i, range) in self.ranges.iter().enumerate() {
+            let is_last_range = i + 1 == self.ranges.len();
+            utf8_seqs.reset(range.start(), range.end());
+            let mut it = (&mut utf8_seqs).peekable();
+            loop {
+                let utf8_seq = match it.next() {
+                    None => break,
+                    Some(utf8_seq) => utf8_seq,
+                };
+                if is_last_range && it.peek().is_none() {
+                    let Patch { hole, entry } = self.c_utf8_seq(&utf8_seq)?;
+                    holes.push(hole);
+                    self.c.fill(last_split, entry);
+                    last_split = Hole::None;
+                    if initial_entry.is_none() {
+                        initial_entry = Some(entry);
+                    }
+                } else {
+                    if initial_entry.is_none() {
+                        initial_entry = Some(self.c.insts.len());
+                    }
+                    self.c.fill_to_next(last_split);
+                    last_split = self.c.push_split_hole();
+                    let Patch { hole, entry } = self.c_utf8_seq(&utf8_seq)?;
+                    holes.push(hole);
+                    last_split =
+                        self.c.fill_split(last_split, Some(entry), None);
+                }
+            }
+        }
+        self.c.utf8_seqs = Some(utf8_seqs);
+        Ok(Patch { hole: Hole::Many(holes), entry: initial_entry.unwrap() })
+    }
+
+    fn c_utf8_seq(&mut self, seq: &Utf8Sequence) -> Result {
+        if self.c.compiled.is_reverse {
+            self.c_utf8_seq_(seq)
+        } else {
+            self.c_utf8_seq_(seq.into_iter().rev())
+        }
+    }
+
+    fn c_utf8_seq_<'r, I>(&mut self, seq: I) -> Result
+    where
+        I: IntoIterator<Item = &'r Utf8Range>,
+    {
+        // The initial instruction for each UTF-8 sequence should be the same.
+        let mut from_inst = ::std::usize::MAX;
+        let mut last_hole = Hole::None;
+        for byte_range in seq {
+            let key = SuffixCacheKey {
+                from_inst: from_inst,
+                start: byte_range.start,
+                end: byte_range.end,
+            };
+            {
+                let pc = self.c.insts.len();
+                if let Some(cached_pc) = self.c.suffix_cache.get(key, pc) {
+                    from_inst = cached_pc;
+                    continue;
+                }
+            }
+            self.c.byte_classes.set_range(byte_range.start, byte_range.end);
+            if from_inst == ::std::usize::MAX {
+                last_hole = self.c.push_hole(InstHole::Bytes {
+                    start: byte_range.start,
+                    end: byte_range.end,
+                });
+            } else {
+                self.c.push_compiled(Inst::Bytes(InstBytes {
+                    goto: from_inst,
+                    start: byte_range.start,
+                    end: byte_range.end,
+                }));
+            }
+            from_inst = self.c.insts.len().checked_sub(1).unwrap();
+            debug_assert!(from_inst < ::std::usize::MAX);
+        }
+        debug_assert!(from_inst < ::std::usize::MAX);
+        Ok(Patch { hole: last_hole, entry: from_inst })
+    }
+}
+
+/// `SuffixCache` is a simple bounded hash map for caching suffix entries in
+/// UTF-8 automata. For example, consider the Unicode range \u{0}-\u{FFFF}.
+/// The set of byte ranges looks like this:
+///
+/// [0-7F]
+/// [C2-DF][80-BF]
+/// [E0][A0-BF][80-BF]
+/// [E1-EC][80-BF][80-BF]
+/// [ED][80-9F][80-BF]
+/// [EE-EF][80-BF][80-BF]
+///
+/// Each line above translates to one alternate in the compiled regex program.
+/// However, all but one of the alternates end in the same suffix, which is
+/// a waste of an instruction. The suffix cache facilitates reusing them across
+/// alternates.
+///
+/// Note that a HashMap could be trivially used for this, but we don't need its
+/// overhead. Some small bounded space (LRU style) is more than enough.
+///
+/// This uses similar idea to [`SparseSet`](../sparse/struct.SparseSet.html),
+/// except it uses hashes as original indices and then compares full keys for
+/// validation against `dense` array.
+#[derive(Debug)]
+struct SuffixCache {
+    sparse: Box<[usize]>,
+    dense: Vec<SuffixCacheEntry>,
+}
+
+#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
+struct SuffixCacheEntry {
+    key: SuffixCacheKey,
+    pc: InstPtr,
+}
+
+#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
+struct SuffixCacheKey {
+    from_inst: InstPtr,
+    start: u8,
+    end: u8,
+}
+
+impl SuffixCache {
+    fn new(size: usize) -> Self {
+        SuffixCache {
+            sparse: vec![0usize; size].into(),
+            dense: Vec::with_capacity(size),
+        }
+    }
+
+    fn get(&mut self, key: SuffixCacheKey, pc: InstPtr) -> Option<InstPtr> {
+        let hash = self.hash(&key);
+        let pos = &mut self.sparse[hash];
+        if let Some(entry) = self.dense.get(*pos) {
+            if entry.key == key {
+                return Some(entry.pc);
+            }
+        }
+        *pos = self.dense.len();
+        self.dense.push(SuffixCacheEntry { key: key, pc: pc });
+        None
+    }
+
+    fn clear(&mut self) {
+        self.dense.clear();
+    }
+
+    fn hash(&self, suffix: &SuffixCacheKey) -> usize {
+        // Basic FNV-1a hash as described:
+        // https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
+        const FNV_PRIME: u64 = 1099511628211;
+        let mut h = 14695981039346656037;
+        h = (h ^ (suffix.from_inst as u64)).wrapping_mul(FNV_PRIME);
+        h = (h ^ (suffix.start as u64)).wrapping_mul(FNV_PRIME);
+        h = (h ^ (suffix.end as u64)).wrapping_mul(FNV_PRIME);
+        (h as usize) % self.sparse.len()
+    }
+}
+
+struct ByteClassSet([bool; 256]);
+
+impl ByteClassSet {
+    fn new() -> Self {
+        ByteClassSet([false; 256])
+    }
+
+    fn set_range(&mut self, start: u8, end: u8) {
+        debug_assert!(start <= end);
+        if start > 0 {
+            self.0[start as usize - 1] = true;
+        }
+        self.0[end as usize] = true;
+    }
+
+    fn set_word_boundary(&mut self) {
+        // We need to mark all ranges of bytes whose pairs result in
+        // evaluating \b differently.
+        let iswb = is_word_byte;
+        let mut b1: u16 = 0;
+        let mut b2: u16;
+        while b1 <= 255 {
+            b2 = b1 + 1;
+            while b2 <= 255 && iswb(b1 as u8) == iswb(b2 as u8) {
+                b2 += 1;
+            }
+            self.set_range(b1 as u8, (b2 - 1) as u8);
+            b1 = b2;
+        }
+    }
+
+    fn byte_classes(&self) -> Vec<u8> {
+        // N.B. If you're debugging the DFA, it's useful to simply return
+        // `(0..256).collect()`, which effectively removes the byte classes
+        // and makes the transitions easier to read.
+        // (0usize..256).map(|x| x as u8).collect()
+        let mut byte_classes = vec![0; 256];
+        let mut class = 0u8;
+        let mut i = 0;
+        loop {
+            byte_classes[i] = class as u8;
+            if i >= 255 {
+                break;
+            }
+            if self.0[i] {
+                class = class.checked_add(1).unwrap();
+            }
+            i += 1;
+        }
+        byte_classes
+    }
+}
+
+impl fmt::Debug for ByteClassSet {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_tuple("ByteClassSet").field(&&self.0[..]).finish()
+    }
+}
+
+fn u32_to_usize(n: u32) -> usize {
+    // In case usize is less than 32 bits, we need to guard against overflow.
+    // On most platforms this compiles to nothing.
+    // TODO Use `std::convert::TryFrom` once it's stable.
+    if (n as u64) > (::std::usize::MAX as u64) {
+        panic!("BUG: {} is too big to be pointer sized", n)
+    }
+    n as usize
+}
+
+#[cfg(test)]
+mod tests {
+    use super::ByteClassSet;
+
+    #[test]
+    fn byte_classes() {
+        let mut set = ByteClassSet::new();
+        set.set_range(b'a', b'z');
+        let classes = set.byte_classes();
+        assert_eq!(classes[0], 0);
+        assert_eq!(classes[1], 0);
+        assert_eq!(classes[2], 0);
+        assert_eq!(classes[b'a' as usize - 1], 0);
+        assert_eq!(classes[b'a' as usize], 1);
+        assert_eq!(classes[b'm' as usize], 1);
+        assert_eq!(classes[b'z' as usize], 1);
+        assert_eq!(classes[b'z' as usize + 1], 2);
+        assert_eq!(classes[254], 2);
+        assert_eq!(classes[255], 2);
+
+        let mut set = ByteClassSet::new();
+        set.set_range(0, 2);
+        set.set_range(4, 6);
+        let classes = set.byte_classes();
+        assert_eq!(classes[0], 0);
+        assert_eq!(classes[1], 0);
+        assert_eq!(classes[2], 0);
+        assert_eq!(classes[3], 1);
+        assert_eq!(classes[4], 2);
+        assert_eq!(classes[5], 2);
+        assert_eq!(classes[6], 2);
+        assert_eq!(classes[7], 3);
+        assert_eq!(classes[255], 3);
+    }
+
+    #[test]
+    fn full_byte_classes() {
+        let mut set = ByteClassSet::new();
+        for i in 0..256u16 {
+            set.set_range(i as u8, i as u8);
+        }
+        assert_eq!(set.byte_classes().len(), 256);
+    }
+}
diff --git a/vendor/regex-1.4.6/src/dfa.rs b/vendor/regex-1.4.6/src/dfa.rs
new file mode 100644 (file)
index 0000000..9ac0c2c
--- /dev/null
@@ -0,0 +1,1952 @@
+/*!
+The DFA matching engine.
+
+A DFA provides faster matching because the engine is in exactly one state at
+any point in time. In the NFA, there may be multiple active states, and
+considerable CPU cycles are spent shuffling them around. In finite automata
+speak, the DFA follows epsilon transitions in the regex far less than the NFA.
+
+A DFA is a classic trade off between time and space. The NFA is slower, but
+its memory requirements are typically small and predictable. The DFA is faster,
+but given the right regex and the right input, the number of states in the
+DFA can grow exponentially. To mitigate this space problem, we do two things:
+
+1. We implement an *online* DFA. That is, the DFA is constructed from the NFA
+   during a search. When a new state is computed, it is stored in a cache so
+   that it may be reused. An important consequence of this implementation
+   is that states that are never reached for a particular input are never
+   computed. (This is impossible in an "offline" DFA which needs to compute
+   all possible states up front.)
+2. If the cache gets too big, we wipe it and continue matching.
+
+In pathological cases, a new state can be created for every byte of input.
+(e.g., The regex `(a|b)*a(a|b){20}` on a long sequence of a's and b's.)
+In this case, performance regresses to slightly slower than the full NFA
+simulation, in large part because the cache becomes useless. If the cache
+is wiped too frequently, the DFA quits and control falls back to one of the
+NFA simulations.
+
+Because of the "lazy" nature of this DFA, the inner matching loop is
+considerably more complex than one might expect out of a DFA. A number of
+tricks are employed to make it fast. Tread carefully.
+
+N.B. While this implementation is heavily commented, Russ Cox's series of
+articles on regexes is strongly recommended: https://swtch.com/~rsc/regexp/
+(As is the DFA implementation in RE2, which heavily influenced this
+implementation.)
+*/
+
+use std::collections::HashMap;
+use std::fmt;
+use std::iter::repeat;
+use std::mem;
+use std::sync::Arc;
+
+use exec::ProgramCache;
+use prog::{Inst, Program};
+use sparse::SparseSet;
+
+/// Return true if and only if the given program can be executed by a DFA.
+///
+/// Generally, a DFA is always possible. A pathological case where it is not
+/// possible is if the number of NFA states exceeds `u32::MAX`, in which case,
+/// this function will return false.
+///
+/// This function will also return false if the given program has any Unicode
+/// instructions (Char or Ranges) since the DFA operates on bytes only.
+pub fn can_exec(insts: &Program) -> bool {
+    use prog::Inst::*;
+    // If for some reason we manage to allocate a regex program with more
+    // than i32::MAX instructions, then we can't execute the DFA because we
+    // use 32 bit instruction pointer deltas for memory savings.
+    // If i32::MAX is the largest positive delta,
+    // then -i32::MAX == i32::MIN + 1 is the largest negative delta,
+    // and we are OK to use 32 bits.
+    if insts.dfa_size_limit == 0 || insts.len() > ::std::i32::MAX as usize {
+        return false;
+    }
+    for inst in insts {
+        match *inst {
+            Char(_) | Ranges(_) => return false,
+            EmptyLook(_) | Match(_) | Save(_) | Split(_) | Bytes(_) => {}
+        }
+    }
+    true
+}
+
+/// A reusable cache of DFA states.
+///
+/// This cache is reused between multiple invocations of the same regex
+/// program. (It is not shared simultaneously between threads. If there is
+/// contention, then new caches are created.)
+#[derive(Debug)]
+pub struct Cache {
+    /// Group persistent DFA related cache state together. The sparse sets
+    /// listed below are used as scratch space while computing uncached states.
+    inner: CacheInner,
+    /// qcur and qnext are ordered sets with constant time
+    /// addition/membership/clearing-whole-set and linear time iteration. They
+    /// are used to manage the sets of NFA states in DFA states when computing
+    /// cached DFA states. In particular, the order of the NFA states matters
+    /// for leftmost-first style matching. Namely, when computing a cached
+    /// state, the set of NFA states stops growing as soon as the first Match
+    /// instruction is observed.
+    qcur: SparseSet,
+    qnext: SparseSet,
+}
+
+/// `CacheInner` is logically just a part of Cache, but groups together fields
+/// that aren't passed as function parameters throughout search. (This split
+/// is mostly an artifact of the borrow checker. It is happily paid.)
+#[derive(Debug)]
+struct CacheInner {
+    /// A cache of pre-compiled DFA states, keyed by the set of NFA states
+    /// and the set of empty-width flags set at the byte in the input when the
+    /// state was observed.
+    ///
+    /// A StatePtr is effectively a `*State`, but to avoid various inconvenient
+    /// things, we just pass indexes around manually. The performance impact of
+    /// this is probably an instruction or two in the inner loop. However, on
+    /// 64 bit, each StatePtr is half the size of a *State.
+    compiled: StateMap,
+    /// The transition table.
+    ///
+    /// The transition table is laid out in row-major order, where states are
+    /// rows and the transitions for each state are columns. At a high level,
+    /// given state `s` and byte `b`, the next state can be found at index
+    /// `s * 256 + b`.
+    ///
+    /// This is, of course, a lie. A StatePtr is actually a pointer to the
+    /// *start* of a row in this table. When indexing in the DFA's inner loop,
+    /// this removes the need to multiply the StatePtr by the stride. Yes, it
+    /// matters. This reduces the number of states we can store, but: the
+    /// stride is rarely 256 since we define transitions in terms of
+    /// *equivalence classes* of bytes. Each class corresponds to a set of
+    /// bytes that never discriminate a distinct path through the DFA from each
+    /// other.
+    trans: Transitions,
+    /// A set of cached start states, which are limited to the number of
+    /// permutations of flags set just before the initial byte of input. (The
+    /// index into this vec is a `EmptyFlags`.)
+    ///
+    /// N.B. A start state can be "dead" (i.e., no possible match), so we
+    /// represent it with a StatePtr.
+    start_states: Vec<StatePtr>,
+    /// Stack scratch space used to follow epsilon transitions in the NFA.
+    /// (This permits us to avoid recursion.)
+    ///
+    /// The maximum stack size is the number of NFA states.
+    stack: Vec<InstPtr>,
+    /// The total number of times this cache has been flushed by the DFA
+    /// because of space constraints.
+    flush_count: u64,
+    /// The total heap size of the DFA's cache. We use this to determine when
+    /// we should flush the cache.
+    size: usize,
+    /// Scratch space used when building instruction pointer lists for new
+    /// states. This helps amortize allocation.
+    insts_scratch_space: Vec<u8>,
+}
+
+/// The transition table.
+///
+/// It is laid out in row-major order, with states as rows and byte class
+/// transitions as columns.
+///
+/// The transition table is responsible for producing valid `StatePtrs`. A
+/// `StatePtr` points to the start of a particular row in this table. When
+/// indexing to find the next state this allows us to avoid a multiplication
+/// when computing an index into the table.
+#[derive(Clone)]
+struct Transitions {
+    /// The table.
+    table: Vec<StatePtr>,
+    /// The stride.
+    num_byte_classes: usize,
+}
+
+/// Fsm encapsulates the actual execution of the DFA.
+#[derive(Debug)]
+pub struct Fsm<'a> {
+    /// prog contains the NFA instruction opcodes. DFA execution uses either
+    /// the `dfa` instructions or the `dfa_reverse` instructions from
+    /// `exec::ExecReadOnly`. (It never uses `ExecReadOnly.nfa`, which may have
+    /// Unicode opcodes that cannot be executed by the DFA.)
+    prog: &'a Program,
+    /// The start state. We record it here because the pointer may change
+    /// when the cache is wiped.
+    start: StatePtr,
+    /// The current position in the input.
+    at: usize,
+    /// Should we quit after seeing the first match? e.g., When the caller
+    /// uses `is_match` or `shortest_match`.
+    quit_after_match: bool,
+    /// The last state that matched.
+    ///
+    /// When no match has occurred, this is set to STATE_UNKNOWN.
+    ///
+    /// This is only useful when matching regex sets. The last match state
+    /// is useful because it contains all of the match instructions seen,
+    /// thereby allowing us to enumerate which regexes in the set matched.
+    last_match_si: StatePtr,
+    /// The input position of the last cache flush. We use this to determine
+    /// if we're thrashing in the cache too often. If so, the DFA quits so
+    /// that we can fall back to the NFA algorithm.
+    last_cache_flush: usize,
+    /// All cached DFA information that is persisted between searches.
+    cache: &'a mut CacheInner,
+}
+
+/// The result of running the DFA.
+///
+/// Generally, the result is either a match or not a match, but sometimes the
+/// DFA runs too slowly because the cache size is too small. In that case, it
+/// gives up with the intent of falling back to the NFA algorithm.
+///
+/// The DFA can also give up if it runs out of room to create new states, or if
+/// it sees non-ASCII bytes in the presence of a Unicode word boundary.
+#[derive(Clone, Debug)]
+pub enum Result<T> {
+    Match(T),
+    NoMatch(usize),
+    Quit,
+}
+
+impl<T> Result<T> {
+    /// Returns true if this result corresponds to a match.
+    pub fn is_match(&self) -> bool {
+        match *self {
+            Result::Match(_) => true,
+            Result::NoMatch(_) | Result::Quit => false,
+        }
+    }
+
+    /// Maps the given function onto T and returns the result.
+    ///
+    /// If this isn't a match, then this is a no-op.
+    #[cfg(feature = "perf-literal")]
+    pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> Result<U> {
+        match self {
+            Result::Match(t) => Result::Match(f(t)),
+            Result::NoMatch(x) => Result::NoMatch(x),
+            Result::Quit => Result::Quit,
+        }
+    }
+
+    /// Sets the non-match position.
+    ///
+    /// If this isn't a non-match, then this is a no-op.
+    fn set_non_match(self, at: usize) -> Result<T> {
+        match self {
+            Result::NoMatch(_) => Result::NoMatch(at),
+            r => r,
+        }
+    }
+}
+
+/// `State` is a DFA state. It contains an ordered set of NFA states (not
+/// necessarily complete) and a smattering of flags.
+///
+/// The flags are packed into the first byte of data.
+///
+/// States don't carry their transitions. Instead, transitions are stored in
+/// a single row-major table.
+///
+/// Delta encoding is used to store the instruction pointers.
+/// The first instruction pointer is stored directly starting
+/// at data[1], and each following pointer is stored as an offset
+/// to the previous one. If a delta is in the range -127..127,
+/// it is packed into a single byte; Otherwise the byte 128 (-128 as an i8)
+/// is coded as a flag, followed by 4 bytes encoding the delta.
+#[derive(Clone, Eq, Hash, PartialEq)]
+struct State {
+    data: Arc<[u8]>,
+}
+
+/// `InstPtr` is a 32 bit pointer into a sequence of opcodes (i.e., it indexes
+/// an NFA state).
+///
+/// Throughout this library, this is usually set to `usize`, but we force a
+/// `u32` here for the DFA to save on space.
+type InstPtr = u32;
+
+/// Adds ip to data using delta encoding with respect to prev.
+///
+/// After completion, `data` will contain `ip` and `prev` will be set to `ip`.
+fn push_inst_ptr(data: &mut Vec<u8>, prev: &mut InstPtr, ip: InstPtr) {
+    let delta = (ip as i32) - (*prev as i32);
+    write_vari32(data, delta);
+    *prev = ip;
+}
+
+struct InstPtrs<'a> {
+    base: usize,
+    data: &'a [u8],
+}
+
+impl<'a> Iterator for InstPtrs<'a> {
+    type Item = usize;
+
+    fn next(&mut self) -> Option<usize> {
+        if self.data.is_empty() {
+            return None;
+        }
+        let (delta, nread) = read_vari32(self.data);
+        let base = self.base as i32 + delta;
+        debug_assert!(base >= 0);
+        debug_assert!(nread > 0);
+        self.data = &self.data[nread..];
+        self.base = base as usize;
+        Some(self.base)
+    }
+}
+
+impl State {
+    fn flags(&self) -> StateFlags {
+        StateFlags(self.data[0])
+    }
+
+    fn inst_ptrs(&self) -> InstPtrs {
+        InstPtrs { base: 0, data: &self.data[1..] }
+    }
+}
+
+/// `StatePtr` is a 32 bit pointer to the start of a row in the transition
+/// table.
+///
+/// It has many special values. There are two types of special values:
+/// sentinels and flags.
+///
+/// Sentinels corresponds to special states that carry some kind of
+/// significance. There are three such states: unknown, dead and quit states.
+///
+/// Unknown states are states that haven't been computed yet. They indicate
+/// that a transition should be filled in that points to either an existing
+/// cached state or a new state altogether. In general, an unknown state means
+/// "follow the NFA's epsilon transitions."
+///
+/// Dead states are states that can never lead to a match, no matter what
+/// subsequent input is observed. This means that the DFA should quit
+/// immediately and return the longest match it has found thus far.
+///
+/// Quit states are states that imply the DFA is not capable of matching the
+/// regex correctly. Currently, this is only used when a Unicode word boundary
+/// exists in the regex *and* a non-ASCII byte is observed.
+///
+/// The other type of state pointer is a state pointer with special flag bits.
+/// There are two flags: a start flag and a match flag. The lower bits of both
+/// kinds always contain a "valid" `StatePtr` (indicated by the `STATE_MAX`
+/// mask).
+///
+/// The start flag means that the state is a start state, and therefore may be
+/// subject to special prefix scanning optimizations.
+///
+/// The match flag means that the state is a match state, and therefore the
+/// current position in the input (while searching) should be recorded.
+///
+/// The above exists mostly in the service of making the inner loop fast.
+/// In particular, the inner *inner* loop looks something like this:
+///
+/// ```ignore
+/// while state <= STATE_MAX and i < len(text):
+///     state = state.next[i]
+/// ```
+///
+/// This is nice because it lets us execute a lazy DFA as if it were an
+/// entirely offline DFA (i.e., with very few instructions). The loop will
+/// quit only when we need to examine a case that needs special attention.
+type StatePtr = u32;
+
+/// An unknown state means that the state has not been computed yet, and that
+/// the only way to progress is to compute it.
+const STATE_UNKNOWN: StatePtr = 1 << 31;
+
+/// A dead state means that the state has been computed and it is known that
+/// once it is entered, no future match can ever occur.
+const STATE_DEAD: StatePtr = STATE_UNKNOWN + 1;
+
+/// A quit state means that the DFA came across some input that it doesn't
+/// know how to process correctly. The DFA should quit and another matching
+/// engine should be run in its place.
+const STATE_QUIT: StatePtr = STATE_DEAD + 1;
+
+/// A start state is a state that the DFA can start in.
+///
+/// Note that start states have their lower bits set to a state pointer.
+const STATE_START: StatePtr = 1 << 30;
+
+/// A match state means that the regex has successfully matched.
+///
+/// Note that match states have their lower bits set to a state pointer.
+const STATE_MATCH: StatePtr = 1 << 29;
+
+/// The maximum state pointer. This is useful to mask out the "valid" state
+/// pointer from a state with the "start" or "match" bits set.
+///
+/// It doesn't make sense to use this with unknown, dead or quit state
+/// pointers, since those pointers are sentinels and never have their lower
+/// bits set to anything meaningful.
+const STATE_MAX: StatePtr = STATE_MATCH - 1;
+
+/// Byte is a u8 in spirit, but a u16 in practice so that we can represent the
+/// special EOF sentinel value.
+#[derive(Copy, Clone, Debug)]
+struct Byte(u16);
+
+/// A set of flags for zero-width assertions.
+#[derive(Clone, Copy, Eq, Debug, Default, Hash, PartialEq)]
+struct EmptyFlags {
+    start: bool,
+    end: bool,
+    start_line: bool,
+    end_line: bool,
+    word_boundary: bool,
+    not_word_boundary: bool,
+}
+
+/// A set of flags describing various configurations of a DFA state. This is
+/// represented by a `u8` so that it is compact.
+#[derive(Clone, Copy, Eq, Default, Hash, PartialEq)]
+struct StateFlags(u8);
+
+impl Cache {
+    /// Create new empty cache for the DFA engine.
+    pub fn new(prog: &Program) -> Self {
+        // We add 1 to account for the special EOF byte.
+        let num_byte_classes = (prog.byte_classes[255] as usize + 1) + 1;
+        let starts = vec![STATE_UNKNOWN; 256];
+        let mut cache = Cache {
+            inner: CacheInner {
+                compiled: StateMap::new(num_byte_classes),
+                trans: Transitions::new(num_byte_classes),
+                start_states: starts,
+                stack: vec![],
+                flush_count: 0,
+                size: 0,
+                insts_scratch_space: vec![],
+            },
+            qcur: SparseSet::new(prog.insts.len()),
+            qnext: SparseSet::new(prog.insts.len()),
+        };
+        cache.inner.reset_size();
+        cache
+    }
+}
+
+impl CacheInner {
+    /// Resets the cache size to account for fixed costs, such as the program
+    /// and stack sizes.
+    fn reset_size(&mut self) {
+        self.size = (self.start_states.len() * mem::size_of::<StatePtr>())
+            + (self.stack.len() * mem::size_of::<InstPtr>());
+    }
+}
+
+impl<'a> Fsm<'a> {
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    pub fn forward(
+        prog: &'a Program,
+        cache: &ProgramCache,
+        quit_after_match: bool,
+        text: &[u8],
+        at: usize,
+    ) -> Result<usize> {
+        let mut cache = cache.borrow_mut();
+        let cache = &mut cache.dfa;
+        let mut dfa = Fsm {
+            prog: prog,
+            start: 0, // filled in below
+            at: at,
+            quit_after_match: quit_after_match,
+            last_match_si: STATE_UNKNOWN,
+            last_cache_flush: at,
+            cache: &mut cache.inner,
+        };
+        let (empty_flags, state_flags) = dfa.start_flags(text, at);
+        dfa.start =
+            match dfa.start_state(&mut cache.qcur, empty_flags, state_flags) {
+                None => return Result::Quit,
+                Some(STATE_DEAD) => return Result::NoMatch(at),
+                Some(si) => si,
+            };
+        debug_assert!(dfa.start != STATE_UNKNOWN);
+        dfa.exec_at(&mut cache.qcur, &mut cache.qnext, text)
+    }
+
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    pub fn reverse(
+        prog: &'a Program,
+        cache: &ProgramCache,
+        quit_after_match: bool,
+        text: &[u8],
+        at: usize,
+    ) -> Result<usize> {
+        let mut cache = cache.borrow_mut();
+        let cache = &mut cache.dfa_reverse;
+        let mut dfa = Fsm {
+            prog: prog,
+            start: 0, // filled in below
+            at: at,
+            quit_after_match: quit_after_match,
+            last_match_si: STATE_UNKNOWN,
+            last_cache_flush: at,
+            cache: &mut cache.inner,
+        };
+        let (empty_flags, state_flags) = dfa.start_flags_reverse(text, at);
+        dfa.start =
+            match dfa.start_state(&mut cache.qcur, empty_flags, state_flags) {
+                None => return Result::Quit,
+                Some(STATE_DEAD) => return Result::NoMatch(at),
+                Some(si) => si,
+            };
+        debug_assert!(dfa.start != STATE_UNKNOWN);
+        dfa.exec_at_reverse(&mut cache.qcur, &mut cache.qnext, text)
+    }
+
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    pub fn forward_many(
+        prog: &'a Program,
+        cache: &ProgramCache,
+        matches: &mut [bool],
+        text: &[u8],
+        at: usize,
+    ) -> Result<usize> {
+        debug_assert!(matches.len() == prog.matches.len());
+        let mut cache = cache.borrow_mut();
+        let cache = &mut cache.dfa;
+        let mut dfa = Fsm {
+            prog: prog,
+            start: 0, // filled in below
+            at: at,
+            quit_after_match: false,
+            last_match_si: STATE_UNKNOWN,
+            last_cache_flush: at,
+            cache: &mut cache.inner,
+        };
+        let (empty_flags, state_flags) = dfa.start_flags(text, at);
+        dfa.start =
+            match dfa.start_state(&mut cache.qcur, empty_flags, state_flags) {
+                None => return Result::Quit,
+                Some(STATE_DEAD) => return Result::NoMatch(at),
+                Some(si) => si,
+            };
+        debug_assert!(dfa.start != STATE_UNKNOWN);
+        let result = dfa.exec_at(&mut cache.qcur, &mut cache.qnext, text);
+        if result.is_match() {
+            if matches.len() == 1 {
+                matches[0] = true;
+            } else {
+                debug_assert!(dfa.last_match_si != STATE_UNKNOWN);
+                debug_assert!(dfa.last_match_si != STATE_DEAD);
+                for ip in dfa.state(dfa.last_match_si).inst_ptrs() {
+                    if let Inst::Match(slot) = dfa.prog[ip] {
+                        matches[slot] = true;
+                    }
+                }
+            }
+        }
+        result
+    }
+
+    /// Executes the DFA on a forward NFA.
+    ///
+    /// {qcur,qnext} are scratch ordered sets which may be non-empty.
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn exec_at(
+        &mut self,
+        qcur: &mut SparseSet,
+        qnext: &mut SparseSet,
+        text: &[u8],
+    ) -> Result<usize> {
+        // For the most part, the DFA is basically:
+        //
+        //   last_match = null
+        //   while current_byte != EOF:
+        //     si = current_state.next[current_byte]
+        //     if si is match
+        //       last_match = si
+        //   return last_match
+        //
+        // However, we need to deal with a few things:
+        //
+        //   1. This is an *online* DFA, so the current state's next list
+        //      may not point to anywhere yet, so we must go out and compute
+        //      them. (They are then cached into the current state's next list
+        //      to avoid re-computation.)
+        //   2. If we come across a state that is known to be dead (i.e., never
+        //      leads to a match), then we can quit early.
+        //   3. If the caller just wants to know if a match occurs, then we
+        //      can quit as soon as we know we have a match. (Full leftmost
+        //      first semantics require continuing on.)
+        //   4. If we're in the start state, then we can use a pre-computed set
+        //      of prefix literals to skip quickly along the input.
+        //   5. After the input is exhausted, we run the DFA on one symbol
+        //      that stands for EOF. This is useful for handling empty width
+        //      assertions.
+        //   6. We can't actually do state.next[byte]. Instead, we have to do
+        //      state.next[byte_classes[byte]], which permits us to keep the
+        //      'next' list very small.
+        //
+        // Since there's a bunch of extra stuff we need to consider, we do some
+        // pretty hairy tricks to get the inner loop to run as fast as
+        // possible.
+        debug_assert!(!self.prog.is_reverse);
+
+        // The last match is the currently known ending match position. It is
+        // reported as an index to the most recent byte that resulted in a
+        // transition to a match state and is always stored in capture slot `1`
+        // when searching forwards. Its maximum value is `text.len()`.
+        let mut result = Result::NoMatch(self.at);
+        let (mut prev_si, mut next_si) = (self.start, self.start);
+        let mut at = self.at;
+        while at < text.len() {
+            // This is the real inner loop. We take advantage of special bits
+            // set in the state pointer to determine whether a state is in the
+            // "common" case or not. Specifically, the common case is a
+            // non-match non-start non-dead state that has already been
+            // computed. So long as we remain in the common case, this inner
+            // loop will chew through the input.
+            //
+            // We also unroll the loop 4 times to amortize the cost of checking
+            // whether we've consumed the entire input. We are also careful
+            // to make sure that `prev_si` always represents the previous state
+            // and `next_si` always represents the next state after the loop
+            // exits, even if it isn't always true inside the loop.
+            while next_si <= STATE_MAX && at < text.len() {
+                // Argument for safety is in the definition of next_si.
+                prev_si = unsafe { self.next_si(next_si, text, at) };
+                at += 1;
+                if prev_si > STATE_MAX || at + 2 >= text.len() {
+                    mem::swap(&mut prev_si, &mut next_si);
+                    break;
+                }
+                next_si = unsafe { self.next_si(prev_si, text, at) };
+                at += 1;
+                if next_si > STATE_MAX {
+                    break;
+                }
+                prev_si = unsafe { self.next_si(next_si, text, at) };
+                at += 1;
+                if prev_si > STATE_MAX {
+                    mem::swap(&mut prev_si, &mut next_si);
+                    break;
+                }
+                next_si = unsafe { self.next_si(prev_si, text, at) };
+                at += 1;
+            }
+            if next_si & STATE_MATCH > 0 {
+                // A match state is outside of the common case because it needs
+                // special case analysis. In particular, we need to record the
+                // last position as having matched and possibly quit the DFA if
+                // we don't need to keep matching.
+                next_si &= !STATE_MATCH;
+                result = Result::Match(at - 1);
+                if self.quit_after_match {
+                    return result;
+                }
+                self.last_match_si = next_si;
+                prev_si = next_si;
+
+                // This permits short-circuiting when matching a regex set.
+                // In particular, if this DFA state contains only match states,
+                // then it's impossible to extend the set of matches since
+                // match states are final. Therefore, we can quit.
+                if self.prog.matches.len() > 1 {
+                    let state = self.state(next_si);
+                    let just_matches =
+                        state.inst_ptrs().all(|ip| self.prog[ip].is_match());
+                    if just_matches {
+                        return result;
+                    }
+                }
+
+                // Another inner loop! If the DFA stays in this particular
+                // match state, then we can rip through all of the input
+                // very quickly, and only recording the match location once
+                // we've left this particular state.
+                let cur = at;
+                while (next_si & !STATE_MATCH) == prev_si
+                    && at + 2 < text.len()
+                {
+                    // Argument for safety is in the definition of next_si.
+                    next_si = unsafe {
+                        self.next_si(next_si & !STATE_MATCH, text, at)
+                    };
+                    at += 1;
+                }
+                if at > cur {
+                    result = Result::Match(at - 2);
+                }
+            } else if next_si & STATE_START > 0 {
+                // A start state isn't in the common case because we may
+                // want to do quick prefix scanning. If the program doesn't
+                // have a detected prefix, then start states are actually
+                // considered common and this case is never reached.
+                debug_assert!(self.has_prefix());
+                next_si &= !STATE_START;
+                prev_si = next_si;
+                at = match self.prefix_at(text, at) {
+                    None => return Result::NoMatch(text.len()),
+                    Some(i) => i,
+                };
+            } else if next_si >= STATE_UNKNOWN {
+                if next_si == STATE_QUIT {
+                    return Result::Quit;
+                }
+                // Finally, this corresponds to the case where the transition
+                // entered a state that can never lead to a match or a state
+                // that hasn't been computed yet. The latter being the "slow"
+                // path.
+                let byte = Byte::byte(text[at - 1]);
+                // We no longer care about the special bits in the state
+                // pointer.
+                prev_si &= STATE_MAX;
+                // Record where we are. This is used to track progress for
+                // determining whether we should quit if we've flushed the
+                // cache too much.
+                self.at = at;
+                next_si = match self.next_state(qcur, qnext, prev_si, byte) {
+                    None => return Result::Quit,
+                    Some(STATE_DEAD) => return result.set_non_match(at),
+                    Some(si) => si,
+                };
+                debug_assert!(next_si != STATE_UNKNOWN);
+                if next_si & STATE_MATCH > 0 {
+                    next_si &= !STATE_MATCH;
+                    result = Result::Match(at - 1);
+                    if self.quit_after_match {
+                        return result;
+                    }
+                    self.last_match_si = next_si;
+                }
+                prev_si = next_si;
+            } else {
+                prev_si = next_si;
+            }
+        }
+
+        // Run the DFA once more on the special EOF sentinel value.
+        // We don't care about the special bits in the state pointer any more,
+        // so get rid of them.
+        prev_si &= STATE_MAX;
+        prev_si = match self.next_state(qcur, qnext, prev_si, Byte::eof()) {
+            None => return Result::Quit,
+            Some(STATE_DEAD) => return result.set_non_match(text.len()),
+            Some(si) => si & !STATE_START,
+        };
+        debug_assert!(prev_si != STATE_UNKNOWN);
+        if prev_si & STATE_MATCH > 0 {
+            prev_si &= !STATE_MATCH;
+            self.last_match_si = prev_si;
+            result = Result::Match(text.len());
+        }
+        result
+    }
+
+    /// Executes the DFA on a reverse NFA.
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn exec_at_reverse(
+        &mut self,
+        qcur: &mut SparseSet,
+        qnext: &mut SparseSet,
+        text: &[u8],
+    ) -> Result<usize> {
+        // The comments in `exec_at` above mostly apply here too. The main
+        // difference is that we move backwards over the input and we look for
+        // the longest possible match instead of the leftmost-first match.
+        //
+        // N.B. The code duplication here is regrettable. Efforts to improve
+        // it without sacrificing performance are welcome. ---AG
+        debug_assert!(self.prog.is_reverse);
+        let mut result = Result::NoMatch(self.at);
+        let (mut prev_si, mut next_si) = (self.start, self.start);
+        let mut at = self.at;
+        while at > 0 {
+            while next_si <= STATE_MAX && at > 0 {
+                // Argument for safety is in the definition of next_si.
+                at -= 1;
+                prev_si = unsafe { self.next_si(next_si, text, at) };
+                if prev_si > STATE_MAX || at <= 4 {
+                    mem::swap(&mut prev_si, &mut next_si);
+                    break;
+                }
+                at -= 1;
+                next_si = unsafe { self.next_si(prev_si, text, at) };
+                if next_si > STATE_MAX {
+                    break;
+                }
+                at -= 1;
+                prev_si = unsafe { self.next_si(next_si, text, at) };
+                if prev_si > STATE_MAX {
+                    mem::swap(&mut prev_si, &mut next_si);
+                    break;
+                }
+                at -= 1;
+                next_si = unsafe { self.next_si(prev_si, text, at) };
+            }
+            if next_si & STATE_MATCH > 0 {
+                next_si &= !STATE_MATCH;
+                result = Result::Match(at + 1);
+                if self.quit_after_match {
+                    return result;
+                }
+                self.last_match_si = next_si;
+                prev_si = next_si;
+                let cur = at;
+                while (next_si & !STATE_MATCH) == prev_si && at >= 2 {
+                    // Argument for safety is in the definition of next_si.
+                    at -= 1;
+                    next_si = unsafe {
+                        self.next_si(next_si & !STATE_MATCH, text, at)
+                    };
+                }
+                if at < cur {
+                    result = Result::Match(at + 2);
+                }
+            } else if next_si >= STATE_UNKNOWN {
+                if next_si == STATE_QUIT {
+                    return Result::Quit;
+                }
+                let byte = Byte::byte(text[at]);
+                prev_si &= STATE_MAX;
+                self.at = at;
+                next_si = match self.next_state(qcur, qnext, prev_si, byte) {
+                    None => return Result::Quit,
+                    Some(STATE_DEAD) => return result.set_non_match(at),
+                    Some(si) => si,
+                };
+                debug_assert!(next_si != STATE_UNKNOWN);
+                if next_si & STATE_MATCH > 0 {
+                    next_si &= !STATE_MATCH;
+                    result = Result::Match(at + 1);
+                    if self.quit_after_match {
+                        return result;
+                    }
+                    self.last_match_si = next_si;
+                }
+                prev_si = next_si;
+            } else {
+                prev_si = next_si;
+            }
+        }
+
+        // Run the DFA once more on the special EOF sentinel value.
+        prev_si = match self.next_state(qcur, qnext, prev_si, Byte::eof()) {
+            None => return Result::Quit,
+            Some(STATE_DEAD) => return result.set_non_match(0),
+            Some(si) => si,
+        };
+        debug_assert!(prev_si != STATE_UNKNOWN);
+        if prev_si & STATE_MATCH > 0 {
+            prev_si &= !STATE_MATCH;
+            self.last_match_si = prev_si;
+            result = Result::Match(0);
+        }
+        result
+    }
+
+    /// next_si transitions to the next state, where the transition input
+    /// corresponds to text[i].
+    ///
+    /// This elides bounds checks, and is therefore not safe.
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    unsafe fn next_si(&self, si: StatePtr, text: &[u8], i: usize) -> StatePtr {
+        // What is the argument for safety here?
+        // We have three unchecked accesses that could possibly violate safety:
+        //
+        //   1. The given byte of input (`text[i]`).
+        //   2. The class of the byte of input (`classes[text[i]]`).
+        //   3. The transition for the class (`trans[si + cls]`).
+        //
+        // (1) is only safe when calling next_si is guarded by
+        // `i < text.len()`.
+        //
+        // (2) is the easiest case to guarantee since `text[i]` is always a
+        // `u8` and `self.prog.byte_classes` always has length `u8::MAX`.
+        // (See `ByteClassSet.byte_classes` in `compile.rs`.)
+        //
+        // (3) is only safe if (1)+(2) are safe. Namely, the transitions
+        // of every state are defined to have length equal to the number of
+        // byte classes in the program. Therefore, a valid class leads to a
+        // valid transition. (All possible transitions are valid lookups, even
+        // if it points to a state that hasn't been computed yet.) (3) also
+        // relies on `si` being correct, but StatePtrs should only ever be
+        // retrieved from the transition table, which ensures they are correct.
+        debug_assert!(i < text.len());
+        let b = *text.get_unchecked(i);
+        debug_assert!((b as usize) < self.prog.byte_classes.len());
+        let cls = *self.prog.byte_classes.get_unchecked(b as usize);
+        self.cache.trans.next_unchecked(si, cls as usize)
+    }
+
+    /// Computes the next state given the current state and the current input
+    /// byte (which may be EOF).
+    ///
+    /// If STATE_DEAD is returned, then there is no valid state transition.
+    /// This implies that no permutation of future input can lead to a match
+    /// state.
+    ///
+    /// STATE_UNKNOWN can never be returned.
+    fn exec_byte(
+        &mut self,
+        qcur: &mut SparseSet,
+        qnext: &mut SparseSet,
+        mut si: StatePtr,
+        b: Byte,
+    ) -> Option<StatePtr> {
+        use prog::Inst::*;
+
+        // Initialize a queue with the current DFA state's NFA states.
+        qcur.clear();
+        for ip in self.state(si).inst_ptrs() {
+            qcur.insert(ip);
+        }
+
+        // Before inspecting the current byte, we may need to also inspect
+        // whether the position immediately preceding the current byte
+        // satisfies the empty assertions found in the current state.
+        //
+        // We only need to do this step if there are any empty assertions in
+        // the current state.
+        let is_word_last = self.state(si).flags().is_word();
+        let is_word = b.is_ascii_word();
+        if self.state(si).flags().has_empty() {
+            // Compute the flags immediately preceding the current byte.
+            // This means we only care about the "end" or "end line" flags.
+            // (The "start" flags are computed immediately following the
+            // current byte and are handled below.)
+            let mut flags = EmptyFlags::default();
+            if b.is_eof() {
+                flags.end = true;
+                flags.end_line = true;
+            } else if b.as_byte().map_or(false, |b| b == b'\n') {
+                flags.end_line = true;
+            }
+            if is_word_last == is_word {
+                flags.not_word_boundary = true;
+            } else {
+                flags.word_boundary = true;
+            }
+            // Now follow epsilon transitions from every NFA state, but make
+            // sure we only follow transitions that satisfy our flags.
+            qnext.clear();
+            for &ip in &*qcur {
+                self.follow_epsilons(usize_to_u32(ip), qnext, flags);
+            }
+            mem::swap(qcur, qnext);
+        }
+
+        // Now we set flags for immediately after the current byte. Since start
+        // states are processed separately, and are the only states that can
+        // have the StartText flag set, we therefore only need to worry about
+        // the StartLine flag here.
+        //
+        // We do also keep track of whether this DFA state contains a NFA state
+        // that is a matching state. This is precisely how we delay the DFA
+        // matching by one byte in order to process the special EOF sentinel
+        // byte. Namely, if this DFA state containing a matching NFA state,
+        // then it is the *next* DFA state that is marked as a match.
+        let mut empty_flags = EmptyFlags::default();
+        let mut state_flags = StateFlags::default();
+        empty_flags.start_line = b.as_byte().map_or(false, |b| b == b'\n');
+        if b.is_ascii_word() {
+            state_flags.set_word();
+        }
+        // Now follow all epsilon transitions again, but only after consuming
+        // the current byte.
+        qnext.clear();
+        for &ip in &*qcur {
+            match self.prog[ip as usize] {
+                // These states never happen in a byte-based program.
+                Char(_) | Ranges(_) => unreachable!(),
+                // These states are handled when following epsilon transitions.
+                Save(_) | Split(_) | EmptyLook(_) => {}
+                Match(_) => {
+                    state_flags.set_match();
+                    if !self.continue_past_first_match() {
+                        break;
+                    } else if self.prog.matches.len() > 1
+                        && !qnext.contains(ip as usize)
+                    {
+                        // If we are continuing on to find other matches,
+                        // then keep a record of the match states we've seen.
+                        qnext.insert(ip);
+                    }
+                }
+                Bytes(ref inst) => {
+                    if b.as_byte().map_or(false, |b| inst.matches(b)) {
+                        self.follow_epsilons(
+                            inst.goto as InstPtr,
+                            qnext,
+                            empty_flags,
+                        );
+                    }
+                }
+            }
+        }
+
+        let cache = if b.is_eof() && self.prog.matches.len() > 1 {
+            // If we're processing the last byte of the input and we're
+            // matching a regex set, then make the next state contain the
+            // previous states transitions. We do this so that the main
+            // matching loop can extract all of the match instructions.
+            mem::swap(qcur, qnext);
+            // And don't cache this state because it's totally bunk.
+            false
+        } else {
+            true
+        };
+
+        // We've now built up the set of NFA states that ought to comprise the
+        // next DFA state, so try to find it in the cache, and if it doesn't
+        // exist, cache it.
+        //
+        // N.B. We pass `&mut si` here because the cache may clear itself if
+        // it has gotten too full. When that happens, the location of the
+        // current state may change.
+        let mut next =
+            match self.cached_state(qnext, state_flags, Some(&mut si)) {
+                None => return None,
+                Some(next) => next,
+            };
+        if (self.start & !STATE_START) == next {
+            // Start states can never be match states since all matches are
+            // delayed by one byte.
+            debug_assert!(!self.state(next).flags().is_match());
+            next = self.start_ptr(next);
+        }
+        if next <= STATE_MAX && self.state(next).flags().is_match() {
+            next |= STATE_MATCH;
+        }
+        debug_assert!(next != STATE_UNKNOWN);
+        // And now store our state in the current state's next list.
+        if cache {
+            let cls = self.byte_class(b);
+            self.cache.trans.set_next(si, cls, next);
+        }
+        Some(next)
+    }
+
+    /// Follows the epsilon transitions starting at (and including) `ip`. The
+    /// resulting states are inserted into the ordered set `q`.
+    ///
+    /// Conditional epsilon transitions (i.e., empty width assertions) are only
+    /// followed if they are satisfied by the given flags, which should
+    /// represent the flags set at the current location in the input.
+    ///
+    /// If the current location corresponds to the empty string, then only the
+    /// end line and/or end text flags may be set. If the current location
+    /// corresponds to a real byte in the input, then only the start line
+    /// and/or start text flags may be set.
+    ///
+    /// As an exception to the above, when finding the initial state, any of
+    /// the above flags may be set:
+    ///
+    /// If matching starts at the beginning of the input, then start text and
+    /// start line should be set. If the input is empty, then end text and end
+    /// line should also be set.
+    ///
+    /// If matching starts after the beginning of the input, then only start
+    /// line should be set if the preceding byte is `\n`. End line should never
+    /// be set in this case. (Even if the following byte is a `\n`, it will
+    /// be handled in a subsequent DFA state.)
+    fn follow_epsilons(
+        &mut self,
+        ip: InstPtr,
+        q: &mut SparseSet,
+        flags: EmptyFlags,
+    ) {
+        use prog::EmptyLook::*;
+        use prog::Inst::*;
+
+        // We need to traverse the NFA to follow epsilon transitions, so avoid
+        // recursion with an explicit stack.
+        self.cache.stack.push(ip);
+        while let Some(mut ip) = self.cache.stack.pop() {
+            // Try to munch through as many states as possible without
+            // pushes/pops to the stack.
+            loop {
+                // Don't visit states we've already added.
+                if q.contains(ip as usize) {
+                    break;
+                }
+                q.insert(ip as usize);
+                match self.prog[ip as usize] {
+                    Char(_) | Ranges(_) => unreachable!(),
+                    Match(_) | Bytes(_) => {
+                        break;
+                    }
+                    EmptyLook(ref inst) => {
+                        // Only follow empty assertion states if our flags
+                        // satisfy the assertion.
+                        match inst.look {
+                            StartLine if flags.start_line => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            EndLine if flags.end_line => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            StartText if flags.start => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            EndText if flags.end => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            WordBoundaryAscii if flags.word_boundary => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            NotWordBoundaryAscii
+                                if flags.not_word_boundary =>
+                            {
+                                ip = inst.goto as InstPtr;
+                            }
+                            WordBoundary if flags.word_boundary => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            NotWordBoundary if flags.not_word_boundary => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            StartLine | EndLine | StartText | EndText
+                            | WordBoundaryAscii | NotWordBoundaryAscii
+                            | WordBoundary | NotWordBoundary => {
+                                break;
+                            }
+                        }
+                    }
+                    Save(ref inst) => {
+                        ip = inst.goto as InstPtr;
+                    }
+                    Split(ref inst) => {
+                        self.cache.stack.push(inst.goto2 as InstPtr);
+                        ip = inst.goto1 as InstPtr;
+                    }
+                }
+            }
+        }
+    }
+
+    /// Find a previously computed state matching the given set of instructions
+    /// and is_match bool.
+    ///
+    /// The given set of instructions should represent a single state in the
+    /// NFA along with all states reachable without consuming any input.
+    ///
+    /// The is_match bool should be true if and only if the preceding DFA state
+    /// contains an NFA matching state. The cached state produced here will
+    /// then signify a match. (This enables us to delay a match by one byte,
+    /// in order to account for the EOF sentinel byte.)
+    ///
+    /// If the cache is full, then it is wiped before caching a new state.
+    ///
+    /// The current state should be specified if it exists, since it will need
+    /// to be preserved if the cache clears itself. (Start states are
+    /// always saved, so they should not be passed here.) It takes a mutable
+    /// pointer to the index because if the cache is cleared, the state's
+    /// location may change.
+    fn cached_state(
+        &mut self,
+        q: &SparseSet,
+        mut state_flags: StateFlags,
+        current_state: Option<&mut StatePtr>,
+    ) -> Option<StatePtr> {
+        // If we couldn't come up with a non-empty key to represent this state,
+        // then it is dead and can never lead to a match.
+        //
+        // Note that inst_flags represent the set of empty width assertions
+        // in q. We use this as an optimization in exec_byte to determine when
+        // we should follow epsilon transitions at the empty string preceding
+        // the current byte.
+        let key = match self.cached_state_key(q, &mut state_flags) {
+            None => return Some(STATE_DEAD),
+            Some(v) => v,
+        };
+        // In the cache? Cool. Done.
+        if let Some(si) = self.cache.compiled.get_ptr(&key) {
+            return Some(si);
+        }
+        // If the cache has gotten too big, wipe it.
+        if self.approximate_size() > self.prog.dfa_size_limit
+            && !self.clear_cache_and_save(current_state)
+        {
+            // Ooops. DFA is giving up.
+            return None;
+        }
+        // Allocate room for our state and add it.
+        self.add_state(key)
+    }
+
+    /// Produces a key suitable for describing a state in the DFA cache.
+    ///
+    /// The key invariant here is that equivalent keys are produced for any two
+    /// sets of ordered NFA states (and toggling of whether the previous NFA
+    /// states contain a match state) that do not discriminate a match for any
+    /// input.
+    ///
+    /// Specifically, q should be an ordered set of NFA states and is_match
+    /// should be true if and only if the previous NFA states contained a match
+    /// state.
+    fn cached_state_key(
+        &mut self,
+        q: &SparseSet,
+        state_flags: &mut StateFlags,
+    ) -> Option<State> {
+        use prog::Inst::*;
+
+        // We need to build up enough information to recognize pre-built states
+        // in the DFA. Generally speaking, this includes every instruction
+        // except for those which are purely epsilon transitions, e.g., the
+        // Save and Split instructions.
+        //
+        // Empty width assertions are also epsilon transitions, but since they
+        // are conditional, we need to make them part of a state's key in the
+        // cache.
+
+        let mut insts =
+            mem::replace(&mut self.cache.insts_scratch_space, vec![]);
+        insts.clear();
+        // Reserve 1 byte for flags.
+        insts.push(0);
+
+        let mut prev = 0;
+        for &ip in q {
+            let ip = usize_to_u32(ip);
+            match self.prog[ip as usize] {
+                Char(_) | Ranges(_) => unreachable!(),
+                Save(_) | Split(_) => {}
+                Bytes(_) => push_inst_ptr(&mut insts, &mut prev, ip),
+                EmptyLook(_) => {
+                    state_flags.set_empty();
+                    push_inst_ptr(&mut insts, &mut prev, ip)
+                }
+                Match(_) => {
+                    push_inst_ptr(&mut insts, &mut prev, ip);
+                    if !self.continue_past_first_match() {
+                        break;
+                    }
+                }
+            }
+        }
+        // If we couldn't transition to any other instructions and we didn't
+        // see a match when expanding NFA states previously, then this is a
+        // dead state and no amount of additional input can transition out
+        // of this state.
+        let opt_state = if insts.len() == 1 && !state_flags.is_match() {
+            None
+        } else {
+            let StateFlags(f) = *state_flags;
+            insts[0] = f;
+            Some(State { data: Arc::from(&*insts) })
+        };
+        self.cache.insts_scratch_space = insts;
+        opt_state
+    }
+
+    /// Clears the cache, but saves and restores current_state if it is not
+    /// none.
+    ///
+    /// The current state must be provided here in case its location in the
+    /// cache changes.
+    ///
+    /// This returns false if the cache is not cleared and the DFA should
+    /// give up.
+    fn clear_cache_and_save(
+        &mut self,
+        current_state: Option<&mut StatePtr>,
+    ) -> bool {
+        if self.cache.compiled.is_empty() {
+            // Nothing to clear...
+            return true;
+        }
+        match current_state {
+            None => self.clear_cache(),
+            Some(si) => {
+                let cur = self.state(*si).clone();
+                if !self.clear_cache() {
+                    return false;
+                }
+                // The unwrap is OK because we just cleared the cache and
+                // therefore know that the next state pointer won't exceed
+                // STATE_MAX.
+                *si = self.restore_state(cur).unwrap();
+                true
+            }
+        }
+    }
+
+    /// Wipes the state cache, but saves and restores the current start state.
+    ///
+    /// This returns false if the cache is not cleared and the DFA should
+    /// give up.
+    fn clear_cache(&mut self) -> bool {
+        // Bail out of the DFA if we're moving too "slowly."
+        // A heuristic from RE2: assume the DFA is too slow if it is processing
+        // 10 or fewer bytes per state.
+        // Additionally, we permit the cache to be flushed a few times before
+        // caling it quits.
+        let nstates = self.cache.compiled.len();
+        if self.cache.flush_count >= 3
+            && self.at >= self.last_cache_flush
+            && (self.at - self.last_cache_flush) <= 10 * nstates
+        {
+            return false;
+        }
+        // Update statistics tracking cache flushes.
+        self.last_cache_flush = self.at;
+        self.cache.flush_count += 1;
+
+        // OK, actually flush the cache.
+        let start = self.state(self.start & !STATE_START).clone();
+        let last_match = if self.last_match_si <= STATE_MAX {
+            Some(self.state(self.last_match_si).clone())
+        } else {
+            None
+        };
+        self.cache.reset_size();
+        self.cache.trans.clear();
+        self.cache.compiled.clear();
+        for s in &mut self.cache.start_states {
+            *s = STATE_UNKNOWN;
+        }
+        // The unwraps are OK because we just cleared the cache and therefore
+        // know that the next state pointer won't exceed STATE_MAX.
+        let start_ptr = self.restore_state(start).unwrap();
+        self.start = self.start_ptr(start_ptr);
+        if let Some(last_match) = last_match {
+            self.last_match_si = self.restore_state(last_match).unwrap();
+        }
+        true
+    }
+
+    /// Restores the given state back into the cache, and returns a pointer
+    /// to it.
+    fn restore_state(&mut self, state: State) -> Option<StatePtr> {
+        // If we've already stored this state, just return a pointer to it.
+        // None will be the wiser.
+        if let Some(si) = self.cache.compiled.get_ptr(&state) {
+            return Some(si);
+        }
+        self.add_state(state)
+    }
+
+    /// Returns the next state given the current state si and current byte
+    /// b. {qcur,qnext} are used as scratch space for storing ordered NFA
+    /// states.
+    ///
+    /// This tries to fetch the next state from the cache, but if that fails,
+    /// it computes the next state, caches it and returns a pointer to it.
+    ///
+    /// The pointer can be to a real state, or it can be STATE_DEAD.
+    /// STATE_UNKNOWN cannot be returned.
+    ///
+    /// None is returned if a new state could not be allocated (i.e., the DFA
+    /// ran out of space and thinks it's running too slowly).
+    fn next_state(
+        &mut self,
+        qcur: &mut SparseSet,
+        qnext: &mut SparseSet,
+        si: StatePtr,
+        b: Byte,
+    ) -> Option<StatePtr> {
+        if si == STATE_DEAD {
+            return Some(STATE_DEAD);
+        }
+        match self.cache.trans.next(si, self.byte_class(b)) {
+            STATE_UNKNOWN => self.exec_byte(qcur, qnext, si, b),
+            STATE_QUIT => None,
+            STATE_DEAD => Some(STATE_DEAD),
+            nsi => Some(nsi),
+        }
+    }
+
+    /// Computes and returns the start state, where searching begins at
+    /// position `at` in `text`. If the state has already been computed,
+    /// then it is pulled from the cache. If the state hasn't been cached,
+    /// then it is computed, cached and a pointer to it is returned.
+    ///
+    /// This may return STATE_DEAD but never STATE_UNKNOWN.
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn start_state(
+        &mut self,
+        q: &mut SparseSet,
+        empty_flags: EmptyFlags,
+        state_flags: StateFlags,
+    ) -> Option<StatePtr> {
+        // Compute an index into our cache of start states based on the set
+        // of empty/state flags set at the current position in the input. We
+        // don't use every flag since not all flags matter. For example, since
+        // matches are delayed by one byte, start states can never be match
+        // states.
+        let flagi = {
+            (((empty_flags.start as u8) << 0)
+                | ((empty_flags.end as u8) << 1)
+                | ((empty_flags.start_line as u8) << 2)
+                | ((empty_flags.end_line as u8) << 3)
+                | ((empty_flags.word_boundary as u8) << 4)
+                | ((empty_flags.not_word_boundary as u8) << 5)
+                | ((state_flags.is_word() as u8) << 6)) as usize
+        };
+        match self.cache.start_states[flagi] {
+            STATE_UNKNOWN => {}
+            STATE_DEAD => return Some(STATE_DEAD),
+            si => return Some(si),
+        }
+        q.clear();
+        let start = usize_to_u32(self.prog.start);
+        self.follow_epsilons(start, q, empty_flags);
+        // Start states can never be match states because we delay every match
+        // by one byte. Given an empty string and an empty match, the match
+        // won't actually occur until the DFA processes the special EOF
+        // sentinel byte.
+        let sp = match self.cached_state(q, state_flags, None) {
+            None => return None,
+            Some(sp) => self.start_ptr(sp),
+        };
+        self.cache.start_states[flagi] = sp;
+        Some(sp)
+    }
+
+    /// Computes the set of starting flags for the given position in text.
+    ///
+    /// This should only be used when executing the DFA forwards over the
+    /// input.
+    fn start_flags(&self, text: &[u8], at: usize) -> (EmptyFlags, StateFlags) {
+        let mut empty_flags = EmptyFlags::default();
+        let mut state_flags = StateFlags::default();
+        empty_flags.start = at == 0;
+        empty_flags.end = text.is_empty();
+        empty_flags.start_line = at == 0 || text[at - 1] == b'\n';
+        empty_flags.end_line = text.is_empty();
+
+        let is_word_last = at > 0 && Byte::byte(text[at - 1]).is_ascii_word();
+        let is_word = at < text.len() && Byte::byte(text[at]).is_ascii_word();
+        if is_word_last {
+            state_flags.set_word();
+        }
+        if is_word == is_word_last {
+            empty_flags.not_word_boundary = true;
+        } else {
+            empty_flags.word_boundary = true;
+        }
+        (empty_flags, state_flags)
+    }
+
+    /// Computes the set of starting flags for the given position in text.
+    ///
+    /// This should only be used when executing the DFA in reverse over the
+    /// input.
+    fn start_flags_reverse(
+        &self,
+        text: &[u8],
+        at: usize,
+    ) -> (EmptyFlags, StateFlags) {
+        let mut empty_flags = EmptyFlags::default();
+        let mut state_flags = StateFlags::default();
+        empty_flags.start = at == text.len();
+        empty_flags.end = text.is_empty();
+        empty_flags.start_line = at == text.len() || text[at] == b'\n';
+        empty_flags.end_line = text.is_empty();
+
+        let is_word_last =
+            at < text.len() && Byte::byte(text[at]).is_ascii_word();
+        let is_word = at > 0 && Byte::byte(text[at - 1]).is_ascii_word();
+        if is_word_last {
+            state_flags.set_word();
+        }
+        if is_word == is_word_last {
+            empty_flags.not_word_boundary = true;
+        } else {
+            empty_flags.word_boundary = true;
+        }
+        (empty_flags, state_flags)
+    }
+
+    /// Returns a reference to a State given a pointer to it.
+    fn state(&self, si: StatePtr) -> &State {
+        self.cache.compiled.get_state(si).unwrap()
+    }
+
+    /// Adds the given state to the DFA.
+    ///
+    /// This allocates room for transitions out of this state in
+    /// self.cache.trans. The transitions can be set with the returned
+    /// StatePtr.
+    ///
+    /// If None is returned, then the state limit was reached and the DFA
+    /// should quit.
+    fn add_state(&mut self, state: State) -> Option<StatePtr> {
+        // This will fail if the next state pointer exceeds STATE_PTR. In
+        // practice, the cache limit will prevent us from ever getting here,
+        // but maybe callers will set the cache size to something ridiculous...
+        let si = match self.cache.trans.add() {
+            None => return None,
+            Some(si) => si,
+        };
+        // If the program has a Unicode word boundary, then set any transitions
+        // for non-ASCII bytes to STATE_QUIT. If the DFA stumbles over such a
+        // transition, then it will quit and an alternative matching engine
+        // will take over.
+        if self.prog.has_unicode_word_boundary {
+            for b in 128..256 {
+                let cls = self.byte_class(Byte::byte(b as u8));
+                self.cache.trans.set_next(si, cls, STATE_QUIT);
+            }
+        }
+        // Finally, put our actual state on to our heap of states and index it
+        // so we can find it later.
+        self.cache.size += self.cache.trans.state_heap_size()
+            + state.data.len()
+            + (2 * mem::size_of::<State>())
+            + mem::size_of::<StatePtr>();
+        self.cache.compiled.insert(state, si);
+        // Transition table and set of states and map should all be in sync.
+        debug_assert!(
+            self.cache.compiled.len() == self.cache.trans.num_states()
+        );
+        Some(si)
+    }
+
+    /// Quickly finds the next occurrence of any literal prefixes in the regex.
+    /// If there are no literal prefixes, then the current position is
+    /// returned. If there are literal prefixes and one could not be found,
+    /// then None is returned.
+    ///
+    /// This should only be called when the DFA is in a start state.
+    fn prefix_at(&self, text: &[u8], at: usize) -> Option<usize> {
+        self.prog.prefixes.find(&text[at..]).map(|(s, _)| at + s)
+    }
+
+    /// Returns the number of byte classes required to discriminate transitions
+    /// in each state.
+    ///
+    /// invariant: num_byte_classes() == len(State.next)
+    fn num_byte_classes(&self) -> usize {
+        // We add 1 to account for the special EOF byte.
+        (self.prog.byte_classes[255] as usize + 1) + 1
+    }
+
+    /// Given an input byte or the special EOF sentinel, return its
+    /// corresponding byte class.
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn byte_class(&self, b: Byte) -> usize {
+        match b.as_byte() {
+            None => self.num_byte_classes() - 1,
+            Some(b) => self.u8_class(b),
+        }
+    }
+
+    /// Like byte_class, but explicitly for u8s.
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn u8_class(&self, b: u8) -> usize {
+        self.prog.byte_classes[b as usize] as usize
+    }
+
+    /// Returns true if the DFA should continue searching past the first match.
+    ///
+    /// Leftmost first semantics in the DFA are preserved by not following NFA
+    /// transitions after the first match is seen.
+    ///
+    /// On occasion, we want to avoid leftmost first semantics to find either
+    /// the longest match (for reverse search) or all possible matches (for
+    /// regex sets).
+    fn continue_past_first_match(&self) -> bool {
+        self.prog.is_reverse || self.prog.matches.len() > 1
+    }
+
+    /// Returns true if there is a prefix we can quickly search for.
+    fn has_prefix(&self) -> bool {
+        !self.prog.is_reverse
+            && !self.prog.prefixes.is_empty()
+            && !self.prog.is_anchored_start
+    }
+
+    /// Sets the STATE_START bit in the given state pointer if and only if
+    /// we have a prefix to scan for.
+    ///
+    /// If there's no prefix, then it's a waste to treat the start state
+    /// specially.
+    fn start_ptr(&self, si: StatePtr) -> StatePtr {
+        if self.has_prefix() {
+            si | STATE_START
+        } else {
+            si
+        }
+    }
+
+    /// Approximate size returns the approximate heap space currently used by
+    /// the DFA. It is used to determine whether the DFA's state cache needs to
+    /// be wiped. Namely, it is possible that for certain regexes on certain
+    /// inputs, a new state could be created for every byte of input. (This is
+    /// bad for memory use, so we bound it with a cache.)
+    fn approximate_size(&self) -> usize {
+        self.cache.size + self.prog.approximate_size()
+    }
+}
+
+/// An abstraction for representing a map of states. The map supports two
+/// different ways of state lookup. One is fast constant time access via a
+/// state pointer. The other is a hashmap lookup based on the DFA's
+/// constituent NFA states.
+///
+/// A DFA state internally uses an Arc such that we only need to store the
+/// set of NFA states on the heap once, even though we support looking up
+/// states by two different means. A more natural way to express this might
+/// use raw pointers, but an Arc is safe and effectively achieves the same
+/// thing.
+#[derive(Debug)]
+struct StateMap {
+    /// The keys are not actually static but rely on always pointing to a
+    /// buffer in `states` which will never be moved except when clearing
+    /// the map or on drop, in which case the keys of this map will be
+    /// removed before
+    map: HashMap<State, StatePtr>,
+    /// Our set of states. Note that `StatePtr / num_byte_classes` indexes
+    /// this Vec rather than just a `StatePtr`.
+    states: Vec<State>,
+    /// The number of byte classes in the DFA. Used to index `states`.
+    num_byte_classes: usize,
+}
+
+impl StateMap {
+    fn new(num_byte_classes: usize) -> StateMap {
+        StateMap {
+            map: HashMap::new(),
+            states: vec![],
+            num_byte_classes: num_byte_classes,
+        }
+    }
+
+    fn len(&self) -> usize {
+        self.states.len()
+    }
+
+    fn is_empty(&self) -> bool {
+        self.states.is_empty()
+    }
+
+    fn get_ptr(&self, state: &State) -> Option<StatePtr> {
+        self.map.get(state).cloned()
+    }
+
+    fn get_state(&self, si: StatePtr) -> Option<&State> {
+        self.states.get(si as usize / self.num_byte_classes)
+    }
+
+    fn insert(&mut self, state: State, si: StatePtr) {
+        self.map.insert(state.clone(), si);
+        self.states.push(state);
+    }
+
+    fn clear(&mut self) {
+        self.map.clear();
+        self.states.clear();
+    }
+}
+
+impl Transitions {
+    /// Create a new transition table.
+    ///
+    /// The number of byte classes corresponds to the stride. Every state will
+    /// have `num_byte_classes` slots for transitions.
+    fn new(num_byte_classes: usize) -> Transitions {
+        Transitions { table: vec![], num_byte_classes: num_byte_classes }
+    }
+
+    /// Returns the total number of states currently in this table.
+    fn num_states(&self) -> usize {
+        self.table.len() / self.num_byte_classes
+    }
+
+    /// Allocates room for one additional state and returns a pointer to it.
+    ///
+    /// If there's no more room, None is returned.
+    fn add(&mut self) -> Option<StatePtr> {
+        let si = self.table.len();
+        if si > STATE_MAX as usize {
+            return None;
+        }
+        self.table.extend(repeat(STATE_UNKNOWN).take(self.num_byte_classes));
+        Some(usize_to_u32(si))
+    }
+
+    /// Clears the table of all states.
+    fn clear(&mut self) {
+        self.table.clear();
+    }
+
+    /// Sets the transition from (si, cls) to next.
+    fn set_next(&mut self, si: StatePtr, cls: usize, next: StatePtr) {
+        self.table[si as usize + cls] = next;
+    }
+
+    /// Returns the transition corresponding to (si, cls).
+    fn next(&self, si: StatePtr, cls: usize) -> StatePtr {
+        self.table[si as usize + cls]
+    }
+
+    /// The heap size, in bytes, of a single state in the transition table.
+    fn state_heap_size(&self) -> usize {
+        self.num_byte_classes * mem::size_of::<StatePtr>()
+    }
+
+    /// Like `next`, but uses unchecked access and is therefore not safe.
+    unsafe fn next_unchecked(&self, si: StatePtr, cls: usize) -> StatePtr {
+        debug_assert!((si as usize) < self.table.len());
+        debug_assert!(cls < self.num_byte_classes);
+        *self.table.get_unchecked(si as usize + cls)
+    }
+}
+
+impl StateFlags {
+    fn is_match(&self) -> bool {
+        self.0 & 0b0000000_1 > 0
+    }
+
+    fn set_match(&mut self) {
+        self.0 |= 0b0000000_1;
+    }
+
+    fn is_word(&self) -> bool {
+        self.0 & 0b000000_1_0 > 0
+    }
+
+    fn set_word(&mut self) {
+        self.0 |= 0b000000_1_0;
+    }
+
+    fn has_empty(&self) -> bool {
+        self.0 & 0b00000_1_00 > 0
+    }
+
+    fn set_empty(&mut self) {
+        self.0 |= 0b00000_1_00;
+    }
+}
+
+impl Byte {
+    fn byte(b: u8) -> Self {
+        Byte(b as u16)
+    }
+    fn eof() -> Self {
+        Byte(256)
+    }
+    fn is_eof(&self) -> bool {
+        self.0 == 256
+    }
+
+    fn is_ascii_word(&self) -> bool {
+        let b = match self.as_byte() {
+            None => return false,
+            Some(b) => b,
+        };
+        match b {
+            b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'_' => true,
+            _ => false,
+        }
+    }
+
+    fn as_byte(&self) -> Option<u8> {
+        if self.is_eof() {
+            None
+        } else {
+            Some(self.0 as u8)
+        }
+    }
+}
+
+impl fmt::Debug for State {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let ips: Vec<usize> = self.inst_ptrs().collect();
+        f.debug_struct("State")
+            .field("flags", &self.flags())
+            .field("insts", &ips)
+            .finish()
+    }
+}
+
+impl fmt::Debug for Transitions {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut fmtd = f.debug_map();
+        for si in 0..self.num_states() {
+            let s = si * self.num_byte_classes;
+            let e = s + self.num_byte_classes;
+            fmtd.entry(&si.to_string(), &TransitionsRow(&self.table[s..e]));
+        }
+        fmtd.finish()
+    }
+}
+
+struct TransitionsRow<'a>(&'a [StatePtr]);
+
+impl<'a> fmt::Debug for TransitionsRow<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut fmtd = f.debug_map();
+        for (b, si) in self.0.iter().enumerate() {
+            match *si {
+                STATE_UNKNOWN => {}
+                STATE_DEAD => {
+                    fmtd.entry(&vb(b as usize), &"DEAD");
+                }
+                si => {
+                    fmtd.entry(&vb(b as usize), &si.to_string());
+                }
+            }
+        }
+        fmtd.finish()
+    }
+}
+
+impl fmt::Debug for StateFlags {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("StateFlags")
+            .field("is_match", &self.is_match())
+            .field("is_word", &self.is_word())
+            .field("has_empty", &self.has_empty())
+            .finish()
+    }
+}
+
+/// Helper function for formatting a byte as a nice-to-read escaped string.
+fn vb(b: usize) -> String {
+    use std::ascii::escape_default;
+
+    if b > ::std::u8::MAX as usize {
+        "EOF".to_owned()
+    } else {
+        let escaped = escape_default(b as u8).collect::<Vec<u8>>();
+        String::from_utf8_lossy(&escaped).into_owned()
+    }
+}
+
+fn usize_to_u32(n: usize) -> u32 {
+    if (n as u64) > (::std::u32::MAX as u64) {
+        panic!("BUG: {} is too big to fit into u32", n)
+    }
+    n as u32
+}
+
+#[allow(dead_code)] // useful for debugging
+fn show_state_ptr(si: StatePtr) -> String {
+    let mut s = format!("{:?}", si & STATE_MAX);
+    if si == STATE_UNKNOWN {
+        s = format!("{} (unknown)", s);
+    }
+    if si == STATE_DEAD {
+        s = format!("{} (dead)", s);
+    }
+    if si == STATE_QUIT {
+        s = format!("{} (quit)", s);
+    }
+    if si & STATE_START > 0 {
+        s = format!("{} (start)", s);
+    }
+    if si & STATE_MATCH > 0 {
+        s = format!("{} (match)", s);
+    }
+    s
+}
+
+/// https://developers.google.com/protocol-buffers/docs/encoding#varints
+fn write_vari32(data: &mut Vec<u8>, n: i32) {
+    let mut un = (n as u32) << 1;
+    if n < 0 {
+        un = !un;
+    }
+    write_varu32(data, un)
+}
+
+/// https://developers.google.com/protocol-buffers/docs/encoding#varints
+fn read_vari32(data: &[u8]) -> (i32, usize) {
+    let (un, i) = read_varu32(data);
+    let mut n = (un >> 1) as i32;
+    if un & 1 != 0 {
+        n = !n;
+    }
+    (n, i)
+}
+
+/// https://developers.google.com/protocol-buffers/docs/encoding#varints
+fn write_varu32(data: &mut Vec<u8>, mut n: u32) {
+    while n >= 0b1000_0000 {
+        data.push((n as u8) | 0b1000_0000);
+        n >>= 7;
+    }
+    data.push(n as u8);
+}
+
+/// https://developers.google.com/protocol-buffers/docs/encoding#varints
+fn read_varu32(data: &[u8]) -> (u32, usize) {
+    let mut n: u32 = 0;
+    let mut shift: u32 = 0;
+    for (i, &b) in data.iter().enumerate() {
+        if b < 0b1000_0000 {
+            return (n | ((b as u32) << shift), i + 1);
+        }
+        n |= ((b as u32) & 0b0111_1111) << shift;
+        shift += 7;
+    }
+    (0, 0)
+}
+
+#[cfg(test)]
+mod tests {
+    extern crate rand;
+
+    use super::{
+        push_inst_ptr, read_vari32, read_varu32, write_vari32, write_varu32,
+        State, StateFlags,
+    };
+    use quickcheck::{quickcheck, Gen, QuickCheck};
+    use std::sync::Arc;
+
+    #[test]
+    fn prop_state_encode_decode() {
+        fn p(mut ips: Vec<u32>, flags: u8) -> bool {
+            // It looks like our encoding scheme can't handle instruction
+            // pointers at or above 2**31. We should fix that, but it seems
+            // unlikely to occur in real code due to the amount of memory
+            // required for such a state machine. So for now, we just clamp
+            // our test data.
+            for ip in &mut ips {
+                if *ip >= 1 << 31 {
+                    *ip = (1 << 31) - 1;
+                }
+            }
+            let mut data = vec![flags];
+            let mut prev = 0;
+            for &ip in ips.iter() {
+                push_inst_ptr(&mut data, &mut prev, ip);
+            }
+            let state = State { data: Arc::from(&data[..]) };
+
+            let expected: Vec<usize> =
+                ips.into_iter().map(|ip| ip as usize).collect();
+            let got: Vec<usize> = state.inst_ptrs().collect();
+            expected == got && state.flags() == StateFlags(flags)
+        }
+        QuickCheck::new()
+            .gen(Gen::new(10_000))
+            .quickcheck(p as fn(Vec<u32>, u8) -> bool);
+    }
+
+    #[test]
+    fn prop_read_write_u32() {
+        fn p(n: u32) -> bool {
+            let mut buf = vec![];
+            write_varu32(&mut buf, n);
+            let (got, nread) = read_varu32(&buf);
+            nread == buf.len() && got == n
+        }
+        quickcheck(p as fn(u32) -> bool);
+    }
+
+    #[test]
+    fn prop_read_write_i32() {
+        fn p(n: i32) -> bool {
+            let mut buf = vec![];
+            write_vari32(&mut buf, n);
+            let (got, nread) = read_vari32(&buf);
+            nread == buf.len() && got == n
+        }
+        quickcheck(p as fn(i32) -> bool);
+    }
+}
diff --git a/vendor/regex-1.4.6/src/error.rs b/vendor/regex-1.4.6/src/error.rs
new file mode 100644 (file)
index 0000000..1c32c85
--- /dev/null
@@ -0,0 +1,71 @@
+use std::fmt;
+use std::iter::repeat;
+
+/// An error that occurred during parsing or compiling a regular expression.
+#[derive(Clone, PartialEq)]
+pub enum Error {
+    /// A syntax error.
+    Syntax(String),
+    /// The compiled program exceeded the set size limit.
+    /// The argument is the size limit imposed.
+    CompiledTooBig(usize),
+    /// Hints that destructuring should not be exhaustive.
+    ///
+    /// This enum may grow additional variants, so this makes sure clients
+    /// don't count on exhaustive matching. (Otherwise, adding a new variant
+    /// could break existing code.)
+    #[doc(hidden)]
+    __Nonexhaustive,
+}
+
+impl ::std::error::Error for Error {
+    // TODO: Remove this method entirely on the next breaking semver release.
+    #[allow(deprecated)]
+    fn description(&self) -> &str {
+        match *self {
+            Error::Syntax(ref err) => err,
+            Error::CompiledTooBig(_) => "compiled program too big",
+            Error::__Nonexhaustive => unreachable!(),
+        }
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Error::Syntax(ref err) => err.fmt(f),
+            Error::CompiledTooBig(limit) => write!(
+                f,
+                "Compiled regex exceeds size limit of {} bytes.",
+                limit
+            ),
+            Error::__Nonexhaustive => unreachable!(),
+        }
+    }
+}
+
+// We implement our own Debug implementation so that we show nicer syntax
+// errors when people use `Regex::new(...).unwrap()`. It's a little weird,
+// but the `Syntax` variant is already storing a `String` anyway, so we might
+// as well format it nicely.
+impl fmt::Debug for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Error::Syntax(ref err) => {
+                let hr: String = repeat('~').take(79).collect();
+                writeln!(f, "Syntax(")?;
+                writeln!(f, "{}", hr)?;
+                writeln!(f, "{}", err)?;
+                writeln!(f, "{}", hr)?;
+                write!(f, ")")?;
+                Ok(())
+            }
+            Error::CompiledTooBig(limit) => {
+                f.debug_tuple("CompiledTooBig").field(&limit).finish()
+            }
+            Error::__Nonexhaustive => {
+                f.debug_tuple("__Nonexhaustive").finish()
+            }
+        }
+    }
+}
diff --git a/vendor/regex-1.4.6/src/exec.rs b/vendor/regex-1.4.6/src/exec.rs
new file mode 100644 (file)
index 0000000..3d5a52b
--- /dev/null
@@ -0,0 +1,1658 @@
+use std::cell::RefCell;
+use std::collections::HashMap;
+use std::panic::AssertUnwindSafe;
+use std::sync::Arc;
+
+#[cfg(feature = "perf-literal")]
+use aho_corasick::{AhoCorasick, AhoCorasickBuilder, MatchKind};
+use syntax::hir::literal::Literals;
+use syntax::hir::Hir;
+use syntax::ParserBuilder;
+
+use backtrack;
+use compile::Compiler;
+#[cfg(feature = "perf-dfa")]
+use dfa;
+use error::Error;
+use input::{ByteInput, CharInput};
+use literal::LiteralSearcher;
+use pikevm;
+use pool::{Pool, PoolGuard};
+use prog::Program;
+use re_builder::RegexOptions;
+use re_bytes;
+use re_set;
+use re_trait::{Locations, RegularExpression, Slot};
+use re_unicode;
+use utf8::next_utf8;
+
+/// `Exec` manages the execution of a regular expression.
+///
+/// In particular, this manages the various compiled forms of a single regular
+/// expression and the choice of which matching engine to use to execute a
+/// regular expression.
+#[derive(Debug)]
+pub struct Exec {
+    /// All read only state.
+    ro: Arc<ExecReadOnly>,
+    /// A pool of reusable values for the various matching engines.
+    ///
+    /// Note that boxing this value is not strictly necessary, but it is an
+    /// easy way to ensure that T does not bloat the stack sized used by a pool
+    /// in the case where T is big. And this turns out to be the case at the
+    /// time of writing for regex's use of this pool. At the time of writing,
+    /// the size of a Regex on the stack is 856 bytes. Boxing this value
+    /// reduces that size to 16 bytes.
+    pool: Box<Pool<ProgramCache>>,
+}
+
+/// `ExecNoSync` is like `Exec`, except it embeds a reference to a cache. This
+/// means it is no longer Sync, but we can now avoid the overhead of
+/// synchronization to fetch the cache.
+#[derive(Debug)]
+pub struct ExecNoSync<'c> {
+    /// All read only state.
+    ro: &'c Arc<ExecReadOnly>,
+    /// Caches for the various matching engines.
+    cache: PoolGuard<'c, ProgramCache>,
+}
+
+/// `ExecNoSyncStr` is like `ExecNoSync`, but matches on &str instead of &[u8].
+#[derive(Debug)]
+pub struct ExecNoSyncStr<'c>(ExecNoSync<'c>);
+
+/// `ExecReadOnly` comprises all read only state for a regex. Namely, all such
+/// state is determined at compile time and never changes during search.
+#[derive(Debug)]
+struct ExecReadOnly {
+    /// The original regular expressions given by the caller to compile.
+    res: Vec<String>,
+    /// A compiled program that is used in the NFA simulation and backtracking.
+    /// It can be byte-based or Unicode codepoint based.
+    ///
+    /// N.B. It is not possibly to make this byte-based from the public API.
+    /// It is only used for testing byte based programs in the NFA simulations.
+    nfa: Program,
+    /// A compiled byte based program for DFA execution. This is only used
+    /// if a DFA can be executed. (Currently, only word boundary assertions are
+    /// not supported.) Note that this program contains an embedded `.*?`
+    /// preceding the first capture group, unless the regex is anchored at the
+    /// beginning.
+    dfa: Program,
+    /// The same as above, except the program is reversed (and there is no
+    /// preceding `.*?`). This is used by the DFA to find the starting location
+    /// of matches.
+    dfa_reverse: Program,
+    /// A set of suffix literals extracted from the regex.
+    ///
+    /// Prefix literals are stored on the `Program`, since they are used inside
+    /// the matching engines.
+    suffixes: LiteralSearcher,
+    /// An Aho-Corasick automaton with leftmost-first match semantics.
+    ///
+    /// This is only set when the entire regex is a simple unanchored
+    /// alternation of literals. We could probably use it more circumstances,
+    /// but this is already hacky enough in this architecture.
+    ///
+    /// N.B. We use u32 as a state ID representation under the assumption that
+    /// if we were to exhaust the ID space, we probably would have long
+    /// surpassed the compilation size limit.
+    #[cfg(feature = "perf-literal")]
+    ac: Option<AhoCorasick<u32>>,
+    /// match_type encodes as much upfront knowledge about how we're going to
+    /// execute a search as possible.
+    match_type: MatchType,
+}
+
+/// Facilitates the construction of an executor by exposing various knobs
+/// to control how a regex is executed and what kinds of resources it's
+/// permitted to use.
+// `ExecBuilder` is only public via the `internal` module, so avoid deriving
+// `Debug`.
+#[allow(missing_debug_implementations)]
+pub struct ExecBuilder {
+    options: RegexOptions,
+    match_type: Option<MatchType>,
+    bytes: bool,
+    only_utf8: bool,
+}
+
+/// Parsed represents a set of parsed regular expressions and their detected
+/// literals.
+struct Parsed {
+    exprs: Vec<Hir>,
+    prefixes: Literals,
+    suffixes: Literals,
+    bytes: bool,
+}
+
+impl ExecBuilder {
+    /// Create a regex execution builder.
+    ///
+    /// This uses default settings for everything except the regex itself,
+    /// which must be provided. Further knobs can be set by calling methods,
+    /// and then finally, `build` to actually create the executor.
+    pub fn new(re: &str) -> Self {
+        Self::new_many(&[re])
+    }
+
+    /// Like new, but compiles the union of the given regular expressions.
+    ///
+    /// Note that when compiling 2 or more regular expressions, capture groups
+    /// are completely unsupported. (This means both `find` and `captures`
+    /// wont work.)
+    pub fn new_many<I, S>(res: I) -> Self
+    where
+        S: AsRef<str>,
+        I: IntoIterator<Item = S>,
+    {
+        let mut opts = RegexOptions::default();
+        opts.pats = res.into_iter().map(|s| s.as_ref().to_owned()).collect();
+        Self::new_options(opts)
+    }
+
+    /// Create a regex execution builder.
+    pub fn new_options(opts: RegexOptions) -> Self {
+        ExecBuilder {
+            options: opts,
+            match_type: None,
+            bytes: false,
+            only_utf8: true,
+        }
+    }
+
+    /// Set the matching engine to be automatically determined.
+    ///
+    /// This is the default state and will apply whatever optimizations are
+    /// possible, such as running a DFA.
+    ///
+    /// This overrides whatever was previously set via the `nfa` or
+    /// `bounded_backtracking` methods.
+    pub fn automatic(mut self) -> Self {
+        self.match_type = None;
+        self
+    }
+
+    /// Sets the matching engine to use the NFA algorithm no matter what
+    /// optimizations are possible.
+    ///
+    /// This overrides whatever was previously set via the `automatic` or
+    /// `bounded_backtracking` methods.
+    pub fn nfa(mut self) -> Self {
+        self.match_type = Some(MatchType::Nfa(MatchNfaType::PikeVM));
+        self
+    }
+
+    /// Sets the matching engine to use a bounded backtracking engine no
+    /// matter what optimizations are possible.
+    ///
+    /// One must use this with care, since the bounded backtracking engine
+    /// uses memory proportion to `len(regex) * len(text)`.
+    ///
+    /// This overrides whatever was previously set via the `automatic` or
+    /// `nfa` methods.
+    pub fn bounded_backtracking(mut self) -> Self {
+        self.match_type = Some(MatchType::Nfa(MatchNfaType::Backtrack));
+        self
+    }
+
+    /// Compiles byte based programs for use with the NFA matching engines.
+    ///
+    /// By default, the NFA engines match on Unicode scalar values. They can
+    /// be made to use byte based programs instead. In general, the byte based
+    /// programs are slower because of a less efficient encoding of character
+    /// classes.
+    ///
+    /// Note that this does not impact DFA matching engines, which always
+    /// execute on bytes.
+    pub fn bytes(mut self, yes: bool) -> Self {
+        self.bytes = yes;
+        self
+    }
+
+    /// When disabled, the program compiled may match arbitrary bytes.
+    ///
+    /// When enabled (the default), all compiled programs exclusively match
+    /// valid UTF-8 bytes.
+    pub fn only_utf8(mut self, yes: bool) -> Self {
+        self.only_utf8 = yes;
+        self
+    }
+
+    /// Set the Unicode flag.
+    pub fn unicode(mut self, yes: bool) -> Self {
+        self.options.unicode = yes;
+        self
+    }
+
+    /// Parse the current set of patterns into their AST and extract literals.
+    fn parse(&self) -> Result<Parsed, Error> {
+        let mut exprs = Vec::with_capacity(self.options.pats.len());
+        let mut prefixes = Some(Literals::empty());
+        let mut suffixes = Some(Literals::empty());
+        let mut bytes = false;
+        let is_set = self.options.pats.len() > 1;
+        // If we're compiling a regex set and that set has any anchored
+        // expressions, then disable all literal optimizations.
+        for pat in &self.options.pats {
+            let mut parser = ParserBuilder::new()
+                .octal(self.options.octal)
+                .case_insensitive(self.options.case_insensitive)
+                .multi_line(self.options.multi_line)
+                .dot_matches_new_line(self.options.dot_matches_new_line)
+                .swap_greed(self.options.swap_greed)
+                .ignore_whitespace(self.options.ignore_whitespace)
+                .unicode(self.options.unicode)
+                .allow_invalid_utf8(!self.only_utf8)
+                .nest_limit(self.options.nest_limit)
+                .build();
+            let expr =
+                parser.parse(pat).map_err(|e| Error::Syntax(e.to_string()))?;
+            bytes = bytes || !expr.is_always_utf8();
+
+            if cfg!(feature = "perf-literal") {
+                if !expr.is_anchored_start() && expr.is_any_anchored_start() {
+                    // Partial anchors unfortunately make it hard to use
+                    // prefixes, so disable them.
+                    prefixes = None;
+                } else if is_set && expr.is_anchored_start() {
+                    // Regex sets with anchors do not go well with literal
+                    // optimizations.
+                    prefixes = None;
+                }
+                prefixes = prefixes.and_then(|mut prefixes| {
+                    if !prefixes.union_prefixes(&expr) {
+                        None
+                    } else {
+                        Some(prefixes)
+                    }
+                });
+
+                if !expr.is_anchored_end() && expr.is_any_anchored_end() {
+                    // Partial anchors unfortunately make it hard to use
+                    // suffixes, so disable them.
+                    suffixes = None;
+                } else if is_set && expr.is_anchored_end() {
+                    // Regex sets with anchors do not go well with literal
+                    // optimizations.
+                    suffixes = None;
+                }
+                suffixes = suffixes.and_then(|mut suffixes| {
+                    if !suffixes.union_suffixes(&expr) {
+                        None
+                    } else {
+                        Some(suffixes)
+                    }
+                });
+            }
+            exprs.push(expr);
+        }
+        Ok(Parsed {
+            exprs: exprs,
+            prefixes: prefixes.unwrap_or_else(Literals::empty),
+            suffixes: suffixes.unwrap_or_else(Literals::empty),
+            bytes: bytes,
+        })
+    }
+
+    /// Build an executor that can run a regular expression.
+    pub fn build(self) -> Result<Exec, Error> {
+        // Special case when we have no patterns to compile.
+        // This can happen when compiling a regex set.
+        if self.options.pats.is_empty() {
+            let ro = Arc::new(ExecReadOnly {
+                res: vec![],
+                nfa: Program::new(),
+                dfa: Program::new(),
+                dfa_reverse: Program::new(),
+                suffixes: LiteralSearcher::empty(),
+                #[cfg(feature = "perf-literal")]
+                ac: None,
+                match_type: MatchType::Nothing,
+            });
+            let pool = ExecReadOnly::new_pool(&ro);
+            return Ok(Exec { ro: ro, pool });
+        }
+        let parsed = self.parse()?;
+        let mut nfa = Compiler::new()
+            .size_limit(self.options.size_limit)
+            .bytes(self.bytes || parsed.bytes)
+            .only_utf8(self.only_utf8)
+            .compile(&parsed.exprs)?;
+        let mut dfa = Compiler::new()
+            .size_limit(self.options.size_limit)
+            .dfa(true)
+            .only_utf8(self.only_utf8)
+            .compile(&parsed.exprs)?;
+        let mut dfa_reverse = Compiler::new()
+            .size_limit(self.options.size_limit)
+            .dfa(true)
+            .only_utf8(self.only_utf8)
+            .reverse(true)
+            .compile(&parsed.exprs)?;
+
+        #[cfg(feature = "perf-literal")]
+        let ac = self.build_aho_corasick(&parsed);
+        nfa.prefixes = LiteralSearcher::prefixes(parsed.prefixes);
+        dfa.prefixes = nfa.prefixes.clone();
+        dfa.dfa_size_limit = self.options.dfa_size_limit;
+        dfa_reverse.dfa_size_limit = self.options.dfa_size_limit;
+
+        let mut ro = ExecReadOnly {
+            res: self.options.pats,
+            nfa: nfa,
+            dfa: dfa,
+            dfa_reverse: dfa_reverse,
+            suffixes: LiteralSearcher::suffixes(parsed.suffixes),
+            #[cfg(feature = "perf-literal")]
+            ac: ac,
+            match_type: MatchType::Nothing,
+        };
+        ro.match_type = ro.choose_match_type(self.match_type);
+
+        let ro = Arc::new(ro);
+        let pool = ExecReadOnly::new_pool(&ro);
+        Ok(Exec { ro, pool })
+    }
+
+    #[cfg(feature = "perf-literal")]
+    fn build_aho_corasick(&self, parsed: &Parsed) -> Option<AhoCorasick<u32>> {
+        if parsed.exprs.len() != 1 {
+            return None;
+        }
+        let lits = match alternation_literals(&parsed.exprs[0]) {
+            None => return None,
+            Some(lits) => lits,
+        };
+        // If we have a small number of literals, then let Teddy handle
+        // things (see literal/mod.rs).
+        if lits.len() <= 32 {
+            return None;
+        }
+        Some(
+            AhoCorasickBuilder::new()
+                .match_kind(MatchKind::LeftmostFirst)
+                .auto_configure(&lits)
+                // We always want this to reduce size, regardless
+                // of what auto-configure does.
+                .byte_classes(true)
+                .build_with_size::<u32, _, _>(&lits)
+                // This should never happen because we'd long exceed the
+                // compilation limit for regexes first.
+                .expect("AC automaton too big"),
+        )
+    }
+}
+
+impl<'c> RegularExpression for ExecNoSyncStr<'c> {
+    type Text = str;
+
+    fn slots_len(&self) -> usize {
+        self.0.slots_len()
+    }
+
+    fn next_after_empty(&self, text: &str, i: usize) -> usize {
+        next_utf8(text.as_bytes(), i)
+    }
+
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn shortest_match_at(&self, text: &str, start: usize) -> Option<usize> {
+        self.0.shortest_match_at(text.as_bytes(), start)
+    }
+
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn is_match_at(&self, text: &str, start: usize) -> bool {
+        self.0.is_match_at(text.as_bytes(), start)
+    }
+
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn find_at(&self, text: &str, start: usize) -> Option<(usize, usize)> {
+        self.0.find_at(text.as_bytes(), start)
+    }
+
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn captures_read_at(
+        &self,
+        locs: &mut Locations,
+        text: &str,
+        start: usize,
+    ) -> Option<(usize, usize)> {
+        self.0.captures_read_at(locs, text.as_bytes(), start)
+    }
+}
+
+impl<'c> RegularExpression for ExecNoSync<'c> {
+    type Text = [u8];
+
+    /// Returns the number of capture slots in the regular expression. (There
+    /// are two slots for every capture group, corresponding to possibly empty
+    /// start and end locations of the capture.)
+    fn slots_len(&self) -> usize {
+        self.ro.nfa.captures.len() * 2
+    }
+
+    fn next_after_empty(&self, _text: &[u8], i: usize) -> usize {
+        i + 1
+    }
+
+    /// Returns the end of a match location, possibly occurring before the
+    /// end location of the correct leftmost-first match.
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn shortest_match_at(&self, text: &[u8], start: usize) -> Option<usize> {
+        if !self.is_anchor_end_match(text) {
+            return None;
+        }
+        match self.ro.match_type {
+            #[cfg(feature = "perf-literal")]
+            MatchType::Literal(ty) => {
+                self.find_literals(ty, text, start).map(|(_, e)| e)
+            }
+            #[cfg(feature = "perf-dfa")]
+            MatchType::Dfa | MatchType::DfaMany => {
+                match self.shortest_dfa(text, start) {
+                    dfa::Result::Match(end) => Some(end),
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => self.shortest_nfa(text, start),
+                }
+            }
+            #[cfg(feature = "perf-dfa")]
+            MatchType::DfaAnchoredReverse => {
+                match dfa::Fsm::reverse(
+                    &self.ro.dfa_reverse,
+                    self.cache.value(),
+                    true,
+                    &text[start..],
+                    text.len(),
+                ) {
+                    dfa::Result::Match(_) => Some(text.len()),
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => self.shortest_nfa(text, start),
+                }
+            }
+            #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
+            MatchType::DfaSuffix => {
+                match self.shortest_dfa_reverse_suffix(text, start) {
+                    dfa::Result::Match(e) => Some(e),
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => self.shortest_nfa(text, start),
+                }
+            }
+            MatchType::Nfa(ty) => self.shortest_nfa_type(ty, text, start),
+            MatchType::Nothing => None,
+        }
+    }
+
+    /// Returns true if and only if the regex matches text.
+    ///
+    /// For single regular expressions, this is equivalent to calling
+    /// shortest_match(...).is_some().
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn is_match_at(&self, text: &[u8], start: usize) -> bool {
+        if !self.is_anchor_end_match(text) {
+            return false;
+        }
+        // We need to do this dance because shortest_match relies on the NFA
+        // filling in captures[1], but a RegexSet has no captures. In other
+        // words, a RegexSet can't (currently) use shortest_match. ---AG
+        match self.ro.match_type {
+            #[cfg(feature = "perf-literal")]
+            MatchType::Literal(ty) => {
+                self.find_literals(ty, text, start).is_some()
+            }
+            #[cfg(feature = "perf-dfa")]
+            MatchType::Dfa | MatchType::DfaMany => {
+                match self.shortest_dfa(text, start) {
+                    dfa::Result::Match(_) => true,
+                    dfa::Result::NoMatch(_) => false,
+                    dfa::Result::Quit => self.match_nfa(text, start),
+                }
+            }
+            #[cfg(feature = "perf-dfa")]
+            MatchType::DfaAnchoredReverse => {
+                match dfa::Fsm::reverse(
+                    &self.ro.dfa_reverse,
+                    self.cache.value(),
+                    true,
+                    &text[start..],
+                    text.len(),
+                ) {
+                    dfa::Result::Match(_) => true,
+                    dfa::Result::NoMatch(_) => false,
+                    dfa::Result::Quit => self.match_nfa(text, start),
+                }
+            }
+            #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
+            MatchType::DfaSuffix => {
+                match self.shortest_dfa_reverse_suffix(text, start) {
+                    dfa::Result::Match(_) => true,
+                    dfa::Result::NoMatch(_) => false,
+                    dfa::Result::Quit => self.match_nfa(text, start),
+                }
+            }
+            MatchType::Nfa(ty) => self.match_nfa_type(ty, text, start),
+            MatchType::Nothing => false,
+        }
+    }
+
+    /// Finds the start and end location of the leftmost-first match, starting
+    /// at the given location.
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn find_at(&self, text: &[u8], start: usize) -> Option<(usize, usize)> {
+        if !self.is_anchor_end_match(text) {
+            return None;
+        }
+        match self.ro.match_type {
+            #[cfg(feature = "perf-literal")]
+            MatchType::Literal(ty) => self.find_literals(ty, text, start),
+            #[cfg(feature = "perf-dfa")]
+            MatchType::Dfa => match self.find_dfa_forward(text, start) {
+                dfa::Result::Match((s, e)) => Some((s, e)),
+                dfa::Result::NoMatch(_) => None,
+                dfa::Result::Quit => {
+                    self.find_nfa(MatchNfaType::Auto, text, start)
+                }
+            },
+            #[cfg(feature = "perf-dfa")]
+            MatchType::DfaAnchoredReverse => {
+                match self.find_dfa_anchored_reverse(text, start) {
+                    dfa::Result::Match((s, e)) => Some((s, e)),
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => {
+                        self.find_nfa(MatchNfaType::Auto, text, start)
+                    }
+                }
+            }
+            #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
+            MatchType::DfaSuffix => {
+                match self.find_dfa_reverse_suffix(text, start) {
+                    dfa::Result::Match((s, e)) => Some((s, e)),
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => {
+                        self.find_nfa(MatchNfaType::Auto, text, start)
+                    }
+                }
+            }
+            MatchType::Nfa(ty) => self.find_nfa(ty, text, start),
+            MatchType::Nothing => None,
+            #[cfg(feature = "perf-dfa")]
+            MatchType::DfaMany => {
+                unreachable!("BUG: RegexSet cannot be used with find")
+            }
+        }
+    }
+
+    /// Finds the start and end location of the leftmost-first match and also
+    /// fills in all matching capture groups.
+    ///
+    /// The number of capture slots given should be equal to the total number
+    /// of capture slots in the compiled program.
+    ///
+    /// Note that the first two slots always correspond to the start and end
+    /// locations of the overall match.
+    fn captures_read_at(
+        &self,
+        locs: &mut Locations,
+        text: &[u8],
+        start: usize,
+    ) -> Option<(usize, usize)> {
+        let slots = locs.as_slots();
+        for slot in slots.iter_mut() {
+            *slot = None;
+        }
+        // If the caller unnecessarily uses this, then we try to save them
+        // from themselves.
+        match slots.len() {
+            0 => return self.find_at(text, start),
+            2 => {
+                return self.find_at(text, start).map(|(s, e)| {
+                    slots[0] = Some(s);
+                    slots[1] = Some(e);
+                    (s, e)
+                });
+            }
+            _ => {} // fallthrough
+        }
+        if !self.is_anchor_end_match(text) {
+            return None;
+        }
+        match self.ro.match_type {
+            #[cfg(feature = "perf-literal")]
+            MatchType::Literal(ty) => {
+                self.find_literals(ty, text, start).and_then(|(s, e)| {
+                    self.captures_nfa_type(
+                        MatchNfaType::Auto,
+                        slots,
+                        text,
+                        s,
+                        e,
+                    )
+                })
+            }
+            #[cfg(feature = "perf-dfa")]
+            MatchType::Dfa => {
+                if self.ro.nfa.is_anchored_start {
+                    self.captures_nfa(slots, text, start)
+                } else {
+                    match self.find_dfa_forward(text, start) {
+                        dfa::Result::Match((s, e)) => self.captures_nfa_type(
+                            MatchNfaType::Auto,
+                            slots,
+                            text,
+                            s,
+                            e,
+                        ),
+                        dfa::Result::NoMatch(_) => None,
+                        dfa::Result::Quit => {
+                            self.captures_nfa(slots, text, start)
+                        }
+                    }
+                }
+            }
+            #[cfg(feature = "perf-dfa")]
+            MatchType::DfaAnchoredReverse => {
+                match self.find_dfa_anchored_reverse(text, start) {
+                    dfa::Result::Match((s, e)) => self.captures_nfa_type(
+                        MatchNfaType::Auto,
+                        slots,
+                        text,
+                        s,
+                        e,
+                    ),
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => self.captures_nfa(slots, text, start),
+                }
+            }
+            #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
+            MatchType::DfaSuffix => {
+                match self.find_dfa_reverse_suffix(text, start) {
+                    dfa::Result::Match((s, e)) => self.captures_nfa_type(
+                        MatchNfaType::Auto,
+                        slots,
+                        text,
+                        s,
+                        e,
+                    ),
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => self.captures_nfa(slots, text, start),
+                }
+            }
+            MatchType::Nfa(ty) => {
+                self.captures_nfa_type(ty, slots, text, start, text.len())
+            }
+            MatchType::Nothing => None,
+            #[cfg(feature = "perf-dfa")]
+            MatchType::DfaMany => {
+                unreachable!("BUG: RegexSet cannot be used with captures")
+            }
+        }
+    }
+}
+
+impl<'c> ExecNoSync<'c> {
+    /// Finds the leftmost-first match using only literal search.
+    #[cfg(feature = "perf-literal")]
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn find_literals(
+        &self,
+        ty: MatchLiteralType,
+        text: &[u8],
+        start: usize,
+    ) -> Option<(usize, usize)> {
+        use self::MatchLiteralType::*;
+        match ty {
+            Unanchored => {
+                let lits = &self.ro.nfa.prefixes;
+                lits.find(&text[start..]).map(|(s, e)| (start + s, start + e))
+            }
+            AnchoredStart => {
+                let lits = &self.ro.nfa.prefixes;
+                if start == 0 || !self.ro.nfa.is_anchored_start {
+                    lits.find_start(&text[start..])
+                        .map(|(s, e)| (start + s, start + e))
+                } else {
+                    None
+                }
+            }
+            AnchoredEnd => {
+                let lits = &self.ro.suffixes;
+                lits.find_end(&text[start..])
+                    .map(|(s, e)| (start + s, start + e))
+            }
+            AhoCorasick => self
+                .ro
+                .ac
+                .as_ref()
+                .unwrap()
+                .find(&text[start..])
+                .map(|m| (start + m.start(), start + m.end())),
+        }
+    }
+
+    /// Finds the leftmost-first match (start and end) using only the DFA.
+    ///
+    /// If the result returned indicates that the DFA quit, then another
+    /// matching engine should be used.
+    #[cfg(feature = "perf-dfa")]
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn find_dfa_forward(
+        &self,
+        text: &[u8],
+        start: usize,
+    ) -> dfa::Result<(usize, usize)> {
+        use dfa::Result::*;
+        let end = match dfa::Fsm::forward(
+            &self.ro.dfa,
+            self.cache.value(),
+            false,
+            text,
+            start,
+        ) {
+            NoMatch(i) => return NoMatch(i),
+            Quit => return Quit,
+            Match(end) if start == end => return Match((start, start)),
+            Match(end) => end,
+        };
+        // Now run the DFA in reverse to find the start of the match.
+        match dfa::Fsm::reverse(
+            &self.ro.dfa_reverse,
+            self.cache.value(),
+            false,
+            &text[start..],
+            end - start,
+        ) {
+            Match(s) => Match((start + s, end)),
+            NoMatch(i) => NoMatch(i),
+            Quit => Quit,
+        }
+    }
+
+    /// Finds the leftmost-first match (start and end) using only the DFA,
+    /// but assumes the regex is anchored at the end and therefore starts at
+    /// the end of the regex and matches in reverse.
+    ///
+    /// If the result returned indicates that the DFA quit, then another
+    /// matching engine should be used.
+    #[cfg(feature = "perf-dfa")]
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn find_dfa_anchored_reverse(
+        &self,
+        text: &[u8],
+        start: usize,
+    ) -> dfa::Result<(usize, usize)> {
+        use dfa::Result::*;
+        match dfa::Fsm::reverse(
+            &self.ro.dfa_reverse,
+            self.cache.value(),
+            false,
+            &text[start..],
+            text.len() - start,
+        ) {
+            Match(s) => Match((start + s, text.len())),
+            NoMatch(i) => NoMatch(i),
+            Quit => Quit,
+        }
+    }
+
+    /// Finds the end of the shortest match using only the DFA.
+    #[cfg(feature = "perf-dfa")]
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn shortest_dfa(&self, text: &[u8], start: usize) -> dfa::Result<usize> {
+        dfa::Fsm::forward(&self.ro.dfa, self.cache.value(), true, text, start)
+    }
+
+    /// Finds the end of the shortest match using only the DFA by scanning for
+    /// suffix literals.
+    #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn shortest_dfa_reverse_suffix(
+        &self,
+        text: &[u8],
+        start: usize,
+    ) -> dfa::Result<usize> {
+        match self.exec_dfa_reverse_suffix(text, start) {
+            None => self.shortest_dfa(text, start),
+            Some(r) => r.map(|(_, end)| end),
+        }
+    }
+
+    /// Finds the end of the shortest match using only the DFA by scanning for
+    /// suffix literals. It also reports the start of the match.
+    ///
+    /// Note that if None is returned, then the optimization gave up to avoid
+    /// worst case quadratic behavior. A forward scanning DFA should be tried
+    /// next.
+    ///
+    /// If a match is returned and the full leftmost-first match is desired,
+    /// then a forward scan starting from the beginning of the match must be
+    /// done.
+    ///
+    /// If the result returned indicates that the DFA quit, then another
+    /// matching engine should be used.
+    #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn exec_dfa_reverse_suffix(
+        &self,
+        text: &[u8],
+        original_start: usize,
+    ) -> Option<dfa::Result<(usize, usize)>> {
+        use dfa::Result::*;
+
+        let lcs = self.ro.suffixes.lcs();
+        debug_assert!(lcs.len() >= 1);
+        let mut start = original_start;
+        let mut end = start;
+        let mut last_literal = start;
+        while end <= text.len() {
+            last_literal += match lcs.find(&text[last_literal..]) {
+                None => return Some(NoMatch(text.len())),
+                Some(i) => i,
+            };
+            end = last_literal + lcs.len();
+            match dfa::Fsm::reverse(
+                &self.ro.dfa_reverse,
+                self.cache.value(),
+                false,
+                &text[start..end],
+                end - start,
+            ) {
+                Match(0) | NoMatch(0) => return None,
+                Match(i) => return Some(Match((start + i, end))),
+                NoMatch(i) => {
+                    start += i;
+                    last_literal += 1;
+                    continue;
+                }
+                Quit => return Some(Quit),
+            };
+        }
+        Some(NoMatch(text.len()))
+    }
+
+    /// Finds the leftmost-first match (start and end) using only the DFA
+    /// by scanning for suffix literals.
+    ///
+    /// If the result returned indicates that the DFA quit, then another
+    /// matching engine should be used.
+    #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn find_dfa_reverse_suffix(
+        &self,
+        text: &[u8],
+        start: usize,
+    ) -> dfa::Result<(usize, usize)> {
+        use dfa::Result::*;
+
+        let match_start = match self.exec_dfa_reverse_suffix(text, start) {
+            None => return self.find_dfa_forward(text, start),
+            Some(Match((start, _))) => start,
+            Some(r) => return r,
+        };
+        // At this point, we've found a match. The only way to quit now
+        // without a match is if the DFA gives up (seems unlikely).
+        //
+        // Now run the DFA forwards to find the proper end of the match.
+        // (The suffix literal match can only indicate the earliest
+        // possible end location, which may appear before the end of the
+        // leftmost-first match.)
+        match dfa::Fsm::forward(
+            &self.ro.dfa,
+            self.cache.value(),
+            false,
+            text,
+            match_start,
+        ) {
+            NoMatch(_) => panic!("BUG: reverse match implies forward match"),
+            Quit => Quit,
+            Match(e) => Match((match_start, e)),
+        }
+    }
+
+    /// Executes the NFA engine to return whether there is a match or not.
+    ///
+    /// Ideally, we could use shortest_nfa(...).is_some() and get the same
+    /// performance characteristics, but regex sets don't have captures, which
+    /// shortest_nfa depends on.
+    #[cfg(feature = "perf-dfa")]
+    fn match_nfa(&self, text: &[u8], start: usize) -> bool {
+        self.match_nfa_type(MatchNfaType::Auto, text, start)
+    }
+
+    /// Like match_nfa, but allows specification of the type of NFA engine.
+    fn match_nfa_type(
+        &self,
+        ty: MatchNfaType,
+        text: &[u8],
+        start: usize,
+    ) -> bool {
+        self.exec_nfa(
+            ty,
+            &mut [false],
+            &mut [],
+            true,
+            false,
+            text,
+            start,
+            text.len(),
+        )
+    }
+
+    /// Finds the shortest match using an NFA.
+    #[cfg(feature = "perf-dfa")]
+    fn shortest_nfa(&self, text: &[u8], start: usize) -> Option<usize> {
+        self.shortest_nfa_type(MatchNfaType::Auto, text, start)
+    }
+
+    /// Like shortest_nfa, but allows specification of the type of NFA engine.
+    fn shortest_nfa_type(
+        &self,
+        ty: MatchNfaType,
+        text: &[u8],
+        start: usize,
+    ) -> Option<usize> {
+        let mut slots = [None, None];
+        if self.exec_nfa(
+            ty,
+            &mut [false],
+            &mut slots,
+            true,
+            true,
+            text,
+            start,
+            text.len(),
+        ) {
+            slots[1]
+        } else {
+            None
+        }
+    }
+
+    /// Like find, but executes an NFA engine.
+    fn find_nfa(
+        &self,
+        ty: MatchNfaType,
+        text: &[u8],
+        start: usize,
+    ) -> Option<(usize, usize)> {
+        let mut slots = [None, None];
+        if self.exec_nfa(
+            ty,
+            &mut [false],
+            &mut slots,
+            false,
+            false,
+            text,
+            start,
+            text.len(),
+        ) {
+            match (slots[0], slots[1]) {
+                (Some(s), Some(e)) => Some((s, e)),
+                _ => None,
+            }
+        } else {
+            None
+        }
+    }
+
+    /// Like find_nfa, but fills in captures.
+    ///
+    /// `slots` should have length equal to `2 * nfa.captures.len()`.
+    #[cfg(feature = "perf-dfa")]
+    fn captures_nfa(
+        &self,
+        slots: &mut [Slot],
+        text: &[u8],
+        start: usize,
+    ) -> Option<(usize, usize)> {
+        self.captures_nfa_type(
+            MatchNfaType::Auto,
+            slots,
+            text,
+            start,
+            text.len(),
+        )
+    }
+
+    /// Like captures_nfa, but allows specification of type of NFA engine.
+    fn captures_nfa_type(
+        &self,
+        ty: MatchNfaType,
+        slots: &mut [Slot],
+        text: &[u8],
+        start: usize,
+        end: usize,
+    ) -> Option<(usize, usize)> {
+        if self.exec_nfa(
+            ty,
+            &mut [false],
+            slots,
+            false,
+            false,
+            text,
+            start,
+            end,
+        ) {
+            match (slots[0], slots[1]) {
+                (Some(s), Some(e)) => Some((s, e)),
+                _ => None,
+            }
+        } else {
+            None
+        }
+    }
+
+    fn exec_nfa(
+        &self,
+        mut ty: MatchNfaType,
+        matches: &mut [bool],
+        slots: &mut [Slot],
+        quit_after_match: bool,
+        quit_after_match_with_pos: bool,
+        text: &[u8],
+        start: usize,
+        end: usize,
+    ) -> bool {
+        use self::MatchNfaType::*;
+        if let Auto = ty {
+            if backtrack::should_exec(self.ro.nfa.len(), text.len()) {
+                ty = Backtrack;
+            } else {
+                ty = PikeVM;
+            }
+        }
+        // The backtracker can't return the shortest match position as it is
+        // implemented today. So if someone calls `shortest_match` and we need
+        // to run an NFA, then use the PikeVM.
+        if quit_after_match_with_pos || ty == PikeVM {
+            self.exec_pikevm(
+                matches,
+                slots,
+                quit_after_match,
+                text,
+                start,
+                end,
+            )
+        } else {
+            self.exec_backtrack(matches, slots, text, start, end)
+        }
+    }
+
+    /// Always run the NFA algorithm.
+    fn exec_pikevm(
+        &self,
+        matches: &mut [bool],
+        slots: &mut [Slot],
+        quit_after_match: bool,
+        text: &[u8],
+        start: usize,
+        end: usize,
+    ) -> bool {
+        if self.ro.nfa.uses_bytes() {
+            pikevm::Fsm::exec(
+                &self.ro.nfa,
+                self.cache.value(),
+                matches,
+                slots,
+                quit_after_match,
+                ByteInput::new(text, self.ro.nfa.only_utf8),
+                start,
+                end,
+            )
+        } else {
+            pikevm::Fsm::exec(
+                &self.ro.nfa,
+                self.cache.value(),
+                matches,
+                slots,
+                quit_after_match,
+                CharInput::new(text),
+                start,
+                end,
+            )
+        }
+    }
+
+    /// Always runs the NFA using bounded backtracking.
+    fn exec_backtrack(
+        &self,
+        matches: &mut [bool],
+        slots: &mut [Slot],
+        text: &[u8],
+        start: usize,
+        end: usize,
+    ) -> bool {
+        if self.ro.nfa.uses_bytes() {
+            backtrack::Bounded::exec(
+                &self.ro.nfa,
+                self.cache.value(),
+                matches,
+                slots,
+                ByteInput::new(text, self.ro.nfa.only_utf8),
+                start,
+                end,
+            )
+        } else {
+            backtrack::Bounded::exec(
+                &self.ro.nfa,
+                self.cache.value(),
+                matches,
+                slots,
+                CharInput::new(text),
+                start,
+                end,
+            )
+        }
+    }
+
+    /// Finds which regular expressions match the given text.
+    ///
+    /// `matches` should have length equal to the number of regexes being
+    /// searched.
+    ///
+    /// This is only useful when one wants to know which regexes in a set
+    /// match some text.
+    pub fn many_matches_at(
+        &self,
+        matches: &mut [bool],
+        text: &[u8],
+        start: usize,
+    ) -> bool {
+        use self::MatchType::*;
+        if !self.is_anchor_end_match(text) {
+            return false;
+        }
+        match self.ro.match_type {
+            #[cfg(feature = "perf-literal")]
+            Literal(ty) => {
+                debug_assert_eq!(matches.len(), 1);
+                matches[0] = self.find_literals(ty, text, start).is_some();
+                matches[0]
+            }
+            #[cfg(feature = "perf-dfa")]
+            Dfa | DfaAnchoredReverse | DfaMany => {
+                match dfa::Fsm::forward_many(
+                    &self.ro.dfa,
+                    self.cache.value(),
+                    matches,
+                    text,
+                    start,
+                ) {
+                    dfa::Result::Match(_) => true,
+                    dfa::Result::NoMatch(_) => false,
+                    dfa::Result::Quit => self.exec_nfa(
+                        MatchNfaType::Auto,
+                        matches,
+                        &mut [],
+                        false,
+                        false,
+                        text,
+                        start,
+                        text.len(),
+                    ),
+                }
+            }
+            #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
+            DfaSuffix => {
+                match dfa::Fsm::forward_many(
+                    &self.ro.dfa,
+                    self.cache.value(),
+                    matches,
+                    text,
+                    start,
+                ) {
+                    dfa::Result::Match(_) => true,
+                    dfa::Result::NoMatch(_) => false,
+                    dfa::Result::Quit => self.exec_nfa(
+                        MatchNfaType::Auto,
+                        matches,
+                        &mut [],
+                        false,
+                        false,
+                        text,
+                        start,
+                        text.len(),
+                    ),
+                }
+            }
+            Nfa(ty) => self.exec_nfa(
+                ty,
+                matches,
+                &mut [],
+                false,
+                false,
+                text,
+                start,
+                text.len(),
+            ),
+            Nothing => false,
+        }
+    }
+
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn is_anchor_end_match(&self, text: &[u8]) -> bool {
+        #[cfg(not(feature = "perf-literal"))]
+        fn imp(_: &ExecReadOnly, _: &[u8]) -> bool {
+            true
+        }
+
+        #[cfg(feature = "perf-literal")]
+        fn imp(ro: &ExecReadOnly, text: &[u8]) -> bool {
+            // Only do this check if the haystack is big (>1MB).
+            if text.len() > (1 << 20) && ro.nfa.is_anchored_end {
+                let lcs = ro.suffixes.lcs();
+                if lcs.len() >= 1 && !lcs.is_suffix(text) {
+                    return false;
+                }
+            }
+            true
+        }
+
+        imp(&self.ro, text)
+    }
+
+    pub fn capture_name_idx(&self) -> &Arc<HashMap<String, usize>> {
+        &self.ro.nfa.capture_name_idx
+    }
+}
+
+impl<'c> ExecNoSyncStr<'c> {
+    pub fn capture_name_idx(&self) -> &Arc<HashMap<String, usize>> {
+        self.0.capture_name_idx()
+    }
+}
+
+impl Exec {
+    /// Get a searcher that isn't Sync.
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    pub fn searcher(&self) -> ExecNoSync {
+        ExecNoSync {
+            ro: &self.ro, // a clone is too expensive here! (and not needed)
+            cache: self.pool.get(),
+        }
+    }
+
+    /// Get a searcher that isn't Sync and can match on &str.
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    pub fn searcher_str(&self) -> ExecNoSyncStr {
+        ExecNoSyncStr(self.searcher())
+    }
+
+    /// Build a Regex from this executor.
+    pub fn into_regex(self) -> re_unicode::Regex {
+        re_unicode::Regex::from(self)
+    }
+
+    /// Build a RegexSet from this executor.
+    pub fn into_regex_set(self) -> re_set::unicode::RegexSet {
+        re_set::unicode::RegexSet::from(self)
+    }
+
+    /// Build a Regex from this executor that can match arbitrary bytes.
+    pub fn into_byte_regex(self) -> re_bytes::Regex {
+        re_bytes::Regex::from(self)
+    }
+
+    /// Build a RegexSet from this executor that can match arbitrary bytes.
+    pub fn into_byte_regex_set(self) -> re_set::bytes::RegexSet {
+        re_set::bytes::RegexSet::from(self)
+    }
+
+    /// The original regular expressions given by the caller that were
+    /// compiled.
+    pub fn regex_strings(&self) -> &[String] {
+        &self.ro.res
+    }
+
+    /// Return a slice of capture names.
+    ///
+    /// Any capture that isn't named is None.
+    pub fn capture_names(&self) -> &[Option<String>] {
+        &self.ro.nfa.captures
+    }
+
+    /// Return a reference to named groups mapping (from group name to
+    /// group position).
+    pub fn capture_name_idx(&self) -> &Arc<HashMap<String, usize>> {
+        &self.ro.nfa.capture_name_idx
+    }
+}
+
+impl Clone for Exec {
+    fn clone(&self) -> Exec {
+        let pool = ExecReadOnly::new_pool(&self.ro);
+        Exec { ro: self.ro.clone(), pool }
+    }
+}
+
+impl ExecReadOnly {
+    fn choose_match_type(&self, hint: Option<MatchType>) -> MatchType {
+        if let Some(MatchType::Nfa(_)) = hint {
+            return hint.unwrap();
+        }
+        // If the NFA is empty, then we'll never match anything.
+        if self.nfa.insts.is_empty() {
+            return MatchType::Nothing;
+        }
+        if let Some(literalty) = self.choose_literal_match_type() {
+            return literalty;
+        }
+        if let Some(dfaty) = self.choose_dfa_match_type() {
+            return dfaty;
+        }
+        // We're so totally hosed.
+        MatchType::Nfa(MatchNfaType::Auto)
+    }
+
+    /// If a plain literal scan can be used, then a corresponding literal
+    /// search type is returned.
+    fn choose_literal_match_type(&self) -> Option<MatchType> {
+        #[cfg(not(feature = "perf-literal"))]
+        fn imp(_: &ExecReadOnly) -> Option<MatchType> {
+            None
+        }
+
+        #[cfg(feature = "perf-literal")]
+        fn imp(ro: &ExecReadOnly) -> Option<MatchType> {
+            // If our set of prefixes is complete, then we can use it to find
+            // a match in lieu of a regex engine. This doesn't quite work well
+            // in the presence of multiple regexes, so only do it when there's
+            // one.
+            //
+            // TODO(burntsushi): Also, don't try to match literals if the regex
+            // is partially anchored. We could technically do it, but we'd need
+            // to create two sets of literals: all of them and then the subset
+            // that aren't anchored. We would then only search for all of them
+            // when at the beginning of the input and use the subset in all
+            // other cases.
+            if ro.res.len() != 1 {
+                return None;
+            }
+            if ro.ac.is_some() {
+                return Some(MatchType::Literal(
+                    MatchLiteralType::AhoCorasick,
+                ));
+            }
+            if ro.nfa.prefixes.complete() {
+                return if ro.nfa.is_anchored_start {
+                    Some(MatchType::Literal(MatchLiteralType::AnchoredStart))
+                } else {
+                    Some(MatchType::Literal(MatchLiteralType::Unanchored))
+                };
+            }
+            if ro.suffixes.complete() {
+                return if ro.nfa.is_anchored_end {
+                    Some(MatchType::Literal(MatchLiteralType::AnchoredEnd))
+                } else {
+                    // This case shouldn't happen. When the regex isn't
+                    // anchored, then complete prefixes should imply complete
+                    // suffixes.
+                    Some(MatchType::Literal(MatchLiteralType::Unanchored))
+                };
+            }
+            None
+        }
+
+        imp(self)
+    }
+
+    /// If a DFA scan can be used, then choose the appropriate DFA strategy.
+    fn choose_dfa_match_type(&self) -> Option<MatchType> {
+        #[cfg(not(feature = "perf-dfa"))]
+        fn imp(_: &ExecReadOnly) -> Option<MatchType> {
+            None
+        }
+
+        #[cfg(feature = "perf-dfa")]
+        fn imp(ro: &ExecReadOnly) -> Option<MatchType> {
+            if !dfa::can_exec(&ro.dfa) {
+                return None;
+            }
+            // Regex sets require a slightly specialized path.
+            if ro.res.len() >= 2 {
+                return Some(MatchType::DfaMany);
+            }
+            // If the regex is anchored at the end but not the start, then
+            // just match in reverse from the end of the haystack.
+            if !ro.nfa.is_anchored_start && ro.nfa.is_anchored_end {
+                return Some(MatchType::DfaAnchoredReverse);
+            }
+            #[cfg(feature = "perf-literal")]
+            {
+                // If there's a longish suffix literal, then it might be faster
+                // to look for that first.
+                if ro.should_suffix_scan() {
+                    return Some(MatchType::DfaSuffix);
+                }
+            }
+            // Fall back to your garden variety forward searching lazy DFA.
+            Some(MatchType::Dfa)
+        }
+
+        imp(self)
+    }
+
+    /// Returns true if the program is amenable to suffix scanning.
+    ///
+    /// When this is true, as a heuristic, we assume it is OK to quickly scan
+    /// for suffix literals and then do a *reverse* DFA match from any matches
+    /// produced by the literal scan. (And then followed by a forward DFA
+    /// search, since the previously found suffix literal maybe not actually be
+    /// the end of a match.)
+    ///
+    /// This is a bit of a specialized optimization, but can result in pretty
+    /// big performance wins if 1) there are no prefix literals and 2) the
+    /// suffix literals are pretty rare in the text. (1) is obviously easy to
+    /// account for but (2) is harder. As a proxy, we assume that longer
+    /// strings are generally rarer, so we only enable this optimization when
+    /// we have a meaty suffix.
+    #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
+    fn should_suffix_scan(&self) -> bool {
+        if self.suffixes.is_empty() {
+            return false;
+        }
+        let lcs_len = self.suffixes.lcs().char_len();
+        lcs_len >= 3 && lcs_len > self.dfa.prefixes.lcp().char_len()
+    }
+
+    fn new_pool(ro: &Arc<ExecReadOnly>) -> Box<Pool<ProgramCache>> {
+        let ro = ro.clone();
+        Box::new(Pool::new(Box::new(move || {
+            AssertUnwindSafe(RefCell::new(ProgramCacheInner::new(&ro)))
+        })))
+    }
+}
+
+#[derive(Clone, Copy, Debug)]
+enum MatchType {
+    /// A single or multiple literal search. This is only used when the regex
+    /// can be decomposed into a literal search.
+    #[cfg(feature = "perf-literal")]
+    Literal(MatchLiteralType),
+    /// A normal DFA search.
+    #[cfg(feature = "perf-dfa")]
+    Dfa,
+    /// A reverse DFA search starting from the end of a haystack.
+    #[cfg(feature = "perf-dfa")]
+    DfaAnchoredReverse,
+    /// A reverse DFA search with suffix literal scanning.
+    #[cfg(all(feature = "perf-dfa", feature = "perf-literal"))]
+    DfaSuffix,
+    /// Use the DFA on two or more regular expressions.
+    #[cfg(feature = "perf-dfa")]
+    DfaMany,
+    /// An NFA variant.
+    Nfa(MatchNfaType),
+    /// No match is ever possible, so don't ever try to search.
+    Nothing,
+}
+
+#[derive(Clone, Copy, Debug)]
+#[cfg(feature = "perf-literal")]
+enum MatchLiteralType {
+    /// Match literals anywhere in text.
+    Unanchored,
+    /// Match literals only at the start of text.
+    AnchoredStart,
+    /// Match literals only at the end of text.
+    AnchoredEnd,
+    /// Use an Aho-Corasick automaton. This requires `ac` to be Some on
+    /// ExecReadOnly.
+    AhoCorasick,
+}
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+enum MatchNfaType {
+    /// Choose between Backtrack and PikeVM.
+    Auto,
+    /// NFA bounded backtracking.
+    ///
+    /// (This is only set by tests, since it never makes sense to always want
+    /// backtracking.)
+    Backtrack,
+    /// The Pike VM.
+    ///
+    /// (This is only set by tests, since it never makes sense to always want
+    /// the Pike VM.)
+    PikeVM,
+}
+
+/// `ProgramCache` maintains reusable allocations for each matching engine
+/// available to a particular program.
+///
+/// We declare this as unwind safe since it's a cache that's only used for
+/// performance purposes. If a panic occurs, it is (or should be) always safe
+/// to continue using the same regex object.
+pub type ProgramCache = AssertUnwindSafe<RefCell<ProgramCacheInner>>;
+
+#[derive(Debug)]
+pub struct ProgramCacheInner {
+    pub pikevm: pikevm::Cache,
+    pub backtrack: backtrack::Cache,
+    #[cfg(feature = "perf-dfa")]
+    pub dfa: dfa::Cache,
+    #[cfg(feature = "perf-dfa")]
+    pub dfa_reverse: dfa::Cache,
+}
+
+impl ProgramCacheInner {
+    fn new(ro: &ExecReadOnly) -> Self {
+        ProgramCacheInner {
+            pikevm: pikevm::Cache::new(&ro.nfa),
+            backtrack: backtrack::Cache::new(&ro.nfa),
+            #[cfg(feature = "perf-dfa")]
+            dfa: dfa::Cache::new(&ro.dfa),
+            #[cfg(feature = "perf-dfa")]
+            dfa_reverse: dfa::Cache::new(&ro.dfa_reverse),
+        }
+    }
+}
+
+/// Alternation literals checks if the given HIR is a simple alternation of
+/// literals, and if so, returns them. Otherwise, this returns None.
+#[cfg(feature = "perf-literal")]
+fn alternation_literals(expr: &Hir) -> Option<Vec<Vec<u8>>> {
+    use syntax::hir::{HirKind, Literal};
+
+    // This is pretty hacky, but basically, if `is_alternation_literal` is
+    // true, then we can make several assumptions about the structure of our
+    // HIR. This is what justifies the `unreachable!` statements below.
+    //
+    // This code should be refactored once we overhaul this crate's
+    // optimization pipeline, because this is a terribly inflexible way to go
+    // about things.
+
+    if !expr.is_alternation_literal() {
+        return None;
+    }
+    let alts = match *expr.kind() {
+        HirKind::Alternation(ref alts) => alts,
+        _ => return None, // one literal isn't worth it
+    };
+
+    let extendlit = |lit: &Literal, dst: &mut Vec<u8>| match *lit {
+        Literal::Unicode(c) => {
+            let mut buf = [0; 4];
+            dst.extend_from_slice(c.encode_utf8(&mut buf).as_bytes());
+        }
+        Literal::Byte(b) => {
+            dst.push(b);
+        }
+    };
+
+    let mut lits = vec![];
+    for alt in alts {
+        let mut lit = vec![];
+        match *alt.kind() {
+            HirKind::Literal(ref x) => extendlit(x, &mut lit),
+            HirKind::Concat(ref exprs) => {
+                for e in exprs {
+                    match *e.kind() {
+                        HirKind::Literal(ref x) => extendlit(x, &mut lit),
+                        _ => unreachable!("expected literal, got {:?}", e),
+                    }
+                }
+            }
+            _ => unreachable!("expected literal or concat, got {:?}", alt),
+        }
+        lits.push(lit);
+    }
+    Some(lits)
+}
+
+#[cfg(test)]
+mod test {
+    #[test]
+    fn uppercut_s_backtracking_bytes_default_bytes_mismatch() {
+        use internal::ExecBuilder;
+
+        let backtrack_bytes_re = ExecBuilder::new("^S")
+            .bounded_backtracking()
+            .only_utf8(false)
+            .build()
+            .map(|exec| exec.into_byte_regex())
+            .map_err(|err| format!("{}", err))
+            .unwrap();
+
+        let default_bytes_re = ExecBuilder::new("^S")
+            .only_utf8(false)
+            .build()
+            .map(|exec| exec.into_byte_regex())
+            .map_err(|err| format!("{}", err))
+            .unwrap();
+
+        let input = vec![83, 83];
+
+        let s1 = backtrack_bytes_re.split(&input);
+        let s2 = default_bytes_re.split(&input);
+        for (chunk1, chunk2) in s1.zip(s2) {
+            assert_eq!(chunk1, chunk2);
+        }
+    }
+
+    #[test]
+    fn unicode_lit_star_backtracking_utf8bytes_default_utf8bytes_mismatch() {
+        use internal::ExecBuilder;
+
+        let backtrack_bytes_re = ExecBuilder::new(r"^(?u:\*)")
+            .bounded_backtracking()
+            .bytes(true)
+            .build()
+            .map(|exec| exec.into_regex())
+            .map_err(|err| format!("{}", err))
+            .unwrap();
+
+        let default_bytes_re = ExecBuilder::new(r"^(?u:\*)")
+            .bytes(true)
+            .build()
+            .map(|exec| exec.into_regex())
+            .map_err(|err| format!("{}", err))
+            .unwrap();
+
+        let input = "**";
+
+        let s1 = backtrack_bytes_re.split(input);
+        let s2 = default_bytes_re.split(input);
+        for (chunk1, chunk2) in s1.zip(s2) {
+            assert_eq!(chunk1, chunk2);
+        }
+    }
+}
diff --git a/vendor/regex-1.4.6/src/expand.rs b/vendor/regex-1.4.6/src/expand.rs
new file mode 100644 (file)
index 0000000..70dbf91
--- /dev/null
@@ -0,0 +1,239 @@
+use std::str;
+
+use find_byte::find_byte;
+
+use re_bytes;
+use re_unicode;
+
+pub fn expand_str(
+    caps: &re_unicode::Captures,
+    mut replacement: &str,
+    dst: &mut String,
+) {
+    while !replacement.is_empty() {
+        match find_byte(b'$', replacement.as_bytes()) {
+            None => break,
+            Some(i) => {
+                dst.push_str(&replacement[..i]);
+                replacement = &replacement[i..];
+            }
+        }
+        if replacement.as_bytes().get(1).map_or(false, |&b| b == b'$') {
+            dst.push_str("$");
+            replacement = &replacement[2..];
+            continue;
+        }
+        debug_assert!(!replacement.is_empty());
+        let cap_ref = match find_cap_ref(replacement.as_bytes()) {
+            Some(cap_ref) => cap_ref,
+            None => {
+                dst.push_str("$");
+                replacement = &replacement[1..];
+                continue;
+            }
+        };
+        replacement = &replacement[cap_ref.end..];
+        match cap_ref.cap {
+            Ref::Number(i) => {
+                dst.push_str(caps.get(i).map(|m| m.as_str()).unwrap_or(""));
+            }
+            Ref::Named(name) => {
+                dst.push_str(
+                    caps.name(name).map(|m| m.as_str()).unwrap_or(""),
+                );
+            }
+        }
+    }
+    dst.push_str(replacement);
+}
+
+pub fn expand_bytes(
+    caps: &re_bytes::Captures,
+    mut replacement: &[u8],
+    dst: &mut Vec<u8>,
+) {
+    while !replacement.is_empty() {
+        match find_byte(b'$', replacement) {
+            None => break,
+            Some(i) => {
+                dst.extend(&replacement[..i]);
+                replacement = &replacement[i..];
+            }
+        }
+        if replacement.get(1).map_or(false, |&b| b == b'$') {
+            dst.push(b'$');
+            replacement = &replacement[2..];
+            continue;
+        }
+        debug_assert!(!replacement.is_empty());
+        let cap_ref = match find_cap_ref(replacement) {
+            Some(cap_ref) => cap_ref,
+            None => {
+                dst.push(b'$');
+                replacement = &replacement[1..];
+                continue;
+            }
+        };
+        replacement = &replacement[cap_ref.end..];
+        match cap_ref.cap {
+            Ref::Number(i) => {
+                dst.extend(caps.get(i).map(|m| m.as_bytes()).unwrap_or(b""));
+            }
+            Ref::Named(name) => {
+                dst.extend(
+                    caps.name(name).map(|m| m.as_bytes()).unwrap_or(b""),
+                );
+            }
+        }
+    }
+    dst.extend(replacement);
+}
+
+/// `CaptureRef` represents a reference to a capture group inside some text.
+/// The reference is either a capture group name or a number.
+///
+/// It is also tagged with the position in the text following the
+/// capture reference.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+struct CaptureRef<'a> {
+    cap: Ref<'a>,
+    end: usize,
+}
+
+/// A reference to a capture group in some text.
+///
+/// e.g., `$2`, `$foo`, `${foo}`.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+enum Ref<'a> {
+    Named(&'a str),
+    Number(usize),
+}
+
+impl<'a> From<&'a str> for Ref<'a> {
+    fn from(x: &'a str) -> Ref<'a> {
+        Ref::Named(x)
+    }
+}
+
+impl From<usize> for Ref<'static> {
+    fn from(x: usize) -> Ref<'static> {
+        Ref::Number(x)
+    }
+}
+
+/// Parses a possible reference to a capture group name in the given text,
+/// starting at the beginning of `replacement`.
+///
+/// If no such valid reference could be found, None is returned.
+fn find_cap_ref(replacement: &[u8]) -> Option<CaptureRef> {
+    let mut i = 0;
+    let rep: &[u8] = replacement.as_ref();
+    if rep.len() <= 1 || rep[0] != b'$' {
+        return None;
+    }
+    i += 1;
+    if rep[i] == b'{' {
+        return find_cap_ref_braced(rep, i + 1);
+    }
+    let mut cap_end = i;
+    while rep.get(cap_end).map_or(false, is_valid_cap_letter) {
+        cap_end += 1;
+    }
+    if cap_end == i {
+        return None;
+    }
+    // We just verified that the range 0..cap_end is valid ASCII, so it must
+    // therefore be valid UTF-8. If we really cared, we could avoid this UTF-8
+    // check via an unchecked conversion or by parsing the number straight from
+    // &[u8].
+    let cap =
+        str::from_utf8(&rep[i..cap_end]).expect("valid UTF-8 capture name");
+    Some(CaptureRef {
+        cap: match cap.parse::<u32>() {
+            Ok(i) => Ref::Number(i as usize),
+            Err(_) => Ref::Named(cap),
+        },
+        end: cap_end,
+    })
+}
+
+fn find_cap_ref_braced(rep: &[u8], mut i: usize) -> Option<CaptureRef> {
+    let start = i;
+    while rep.get(i).map_or(false, |&b| b != b'}') {
+        i += 1;
+    }
+    if !rep.get(i).map_or(false, |&b| b == b'}') {
+        return None;
+    }
+    // When looking at braced names, we don't put any restrictions on the name,
+    // so it's possible it could be invalid UTF-8. But a capture group name
+    // can never be invalid UTF-8, so if we have invalid UTF-8, then we can
+    // safely return None.
+    let cap = match str::from_utf8(&rep[start..i]) {
+        Err(_) => return None,
+        Ok(cap) => cap,
+    };
+    Some(CaptureRef {
+        cap: match cap.parse::<u32>() {
+            Ok(i) => Ref::Number(i as usize),
+            Err(_) => Ref::Named(cap),
+        },
+        end: i + 1,
+    })
+}
+
+/// Returns true if and only if the given byte is allowed in a capture name.
+fn is_valid_cap_letter(b: &u8) -> bool {
+    match *b {
+        b'0'..=b'9' | b'a'..=b'z' | b'A'..=b'Z' | b'_' => true,
+        _ => false,
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::{find_cap_ref, CaptureRef};
+
+    macro_rules! find {
+        ($name:ident, $text:expr) => {
+            #[test]
+            fn $name() {
+                assert_eq!(None, find_cap_ref($text.as_bytes()));
+            }
+        };
+        ($name:ident, $text:expr, $capref:expr) => {
+            #[test]
+            fn $name() {
+                assert_eq!(Some($capref), find_cap_ref($text.as_bytes()));
+            }
+        };
+    }
+
+    macro_rules! c {
+        ($name_or_number:expr, $pos:expr) => {
+            CaptureRef { cap: $name_or_number.into(), end: $pos }
+        };
+    }
+
+    find!(find_cap_ref1, "$foo", c!("foo", 4));
+    find!(find_cap_ref2, "${foo}", c!("foo", 6));
+    find!(find_cap_ref3, "$0", c!(0, 2));
+    find!(find_cap_ref4, "$5", c!(5, 2));
+    find!(find_cap_ref5, "$10", c!(10, 3));
+    // See https://github.com/rust-lang/regex/pull/585
+    // for more on characters following numbers
+    find!(find_cap_ref6, "$42a", c!("42a", 4));
+    find!(find_cap_ref7, "${42}a", c!(42, 5));
+    find!(find_cap_ref8, "${42");
+    find!(find_cap_ref9, "${42 ");
+    find!(find_cap_ref10, " $0 ");
+    find!(find_cap_ref11, "$");
+    find!(find_cap_ref12, " ");
+    find!(find_cap_ref13, "");
+    find!(find_cap_ref14, "$1-$2", c!(1, 2));
+    find!(find_cap_ref15, "$1_$2", c!("1_", 3));
+    find!(find_cap_ref16, "$x-$y", c!("x", 2));
+    find!(find_cap_ref17, "$x_$y", c!("x_", 3));
+    find!(find_cap_ref18, "${#}", c!("#", 4));
+    find!(find_cap_ref19, "${Z[}", c!("Z[", 5));
+}
diff --git a/vendor/regex-1.4.6/src/find_byte.rs b/vendor/regex-1.4.6/src/find_byte.rs
new file mode 100644 (file)
index 0000000..e95f72a
--- /dev/null
@@ -0,0 +1,18 @@
+/// Searches for the given needle in the given haystack.
+///
+/// If the perf-literal feature is enabled, then this uses the super optimized
+/// memchr crate. Otherwise, it uses the naive byte-at-a-time implementation.
+pub fn find_byte(needle: u8, haystack: &[u8]) -> Option<usize> {
+    #[cfg(not(feature = "perf-literal"))]
+    fn imp(needle: u8, haystack: &[u8]) -> Option<usize> {
+        haystack.iter().position(|&b| b == needle)
+    }
+
+    #[cfg(feature = "perf-literal")]
+    fn imp(needle: u8, haystack: &[u8]) -> Option<usize> {
+        use memchr::memchr;
+        memchr(needle, haystack)
+    }
+
+    imp(needle, haystack)
+}
diff --git a/vendor/regex-1.4.6/src/freqs.rs b/vendor/regex-1.4.6/src/freqs.rs
new file mode 100644 (file)
index 0000000..fcffa95
--- /dev/null
@@ -0,0 +1,261 @@
+// NOTE: The following code was generated by "scripts/frequencies.py", do not
+// edit directly
+
+pub const BYTE_FREQUENCIES: [u8; 256] = [
+    55,  // '\x00'
+    52,  // '\x01'
+    51,  // '\x02'
+    50,  // '\x03'
+    49,  // '\x04'
+    48,  // '\x05'
+    47,  // '\x06'
+    46,  // '\x07'
+    45,  // '\x08'
+    103, // '\t'
+    242, // '\n'
+    66,  // '\x0b'
+    67,  // '\x0c'
+    229, // '\r'
+    44,  // '\x0e'
+    43,  // '\x0f'
+    42,  // '\x10'
+    41,  // '\x11'
+    40,  // '\x12'
+    39,  // '\x13'
+    38,  // '\x14'
+    37,  // '\x15'
+    36,  // '\x16'
+    35,  // '\x17'
+    34,  // '\x18'
+    33,  // '\x19'
+    56,  // '\x1a'
+    32,  // '\x1b'
+    31,  // '\x1c'
+    30,  // '\x1d'
+    29,  // '\x1e'
+    28,  // '\x1f'
+    255, // ' '
+    148, // '!'
+    164, // '"'
+    149, // '#'
+    136, // '$'
+    160, // '%'
+    155, // '&'
+    173, // "'"
+    221, // '('
+    222, // ')'
+    134, // '*'
+    122, // '+'
+    232, // ','
+    202, // '-'
+    215, // '.'
+    224, // '/'
+    208, // '0'
+    220, // '1'
+    204, // '2'
+    187, // '3'
+    183, // '4'
+    179, // '5'
+    177, // '6'
+    168, // '7'
+    178, // '8'
+    200, // '9'
+    226, // ':'
+    195, // ';'
+    154, // '<'
+    184, // '='
+    174, // '>'
+    126, // '?'
+    120, // '@'
+    191, // 'A'
+    157, // 'B'
+    194, // 'C'
+    170, // 'D'
+    189, // 'E'
+    162, // 'F'
+    161, // 'G'
+    150, // 'H'
+    193, // 'I'
+    142, // 'J'
+    137, // 'K'
+    171, // 'L'
+    176, // 'M'
+    185, // 'N'
+    167, // 'O'
+    186, // 'P'
+    112, // 'Q'
+    175, // 'R'
+    192, // 'S'
+    188, // 'T'
+    156, // 'U'
+    140, // 'V'
+    143, // 'W'
+    123, // 'X'
+    133, // 'Y'
+    128, // 'Z'
+    147, // '['
+    138, // '\\'
+    146, // ']'
+    114, // '^'
+    223, // '_'
+    151, // '`'
+    249, // 'a'
+    216, // 'b'
+    238, // 'c'
+    236, // 'd'
+    253, // 'e'
+    227, // 'f'
+    218, // 'g'
+    230, // 'h'
+    247, // 'i'
+    135, // 'j'
+    180, // 'k'
+    241, // 'l'
+    233, // 'm'
+    246, // 'n'
+    244, // 'o'
+    231, // 'p'
+    139, // 'q'
+    245, // 'r'
+    243, // 's'
+    251, // 't'
+    235, // 'u'
+    201, // 'v'
+    196, // 'w'
+    240, // 'x'
+    214, // 'y'
+    152, // 'z'
+    182, // '{'
+    205, // '|'
+    181, // '}'
+    127, // '~'
+    27,  // '\x7f'
+    212, // '\x80'
+    211, // '\x81'
+    210, // '\x82'
+    213, // '\x83'
+    228, // '\x84'
+    197, // '\x85'
+    169, // '\x86'
+    159, // '\x87'
+    131, // '\x88'
+    172, // '\x89'
+    105, // '\x8a'
+    80,  // '\x8b'
+    98,  // '\x8c'
+    96,  // '\x8d'
+    97,  // '\x8e'
+    81,  // '\x8f'
+    207, // '\x90'
+    145, // '\x91'
+    116, // '\x92'
+    115, // '\x93'
+    144, // '\x94'
+    130, // '\x95'
+    153, // '\x96'
+    121, // '\x97'
+    107, // '\x98'
+    132, // '\x99'
+    109, // '\x9a'
+    110, // '\x9b'
+    124, // '\x9c'
+    111, // '\x9d'
+    82,  // '\x9e'
+    108, // '\x9f'
+    118, // '\xa0'
+    141, // '¡'
+    113, // '¢'
+    129, // '£'
+    119, // '¤'
+    125, // '¥'
+    165, // '¦'
+    117, // '§'
+    92,  // '¨'
+    106, // '©'
+    83,  // 'ª'
+    72,  // '«'
+    99,  // '¬'
+    93,  // '\xad'
+    65,  // '®'
+    79,  // '¯'
+    166, // '°'
+    237, // '±'
+    163, // '²'
+    199, // '³'
+    190, // '´'
+    225, // 'µ'
+    209, // '¶'
+    203, // '·'
+    198, // '¸'
+    217, // '¹'
+    219, // 'º'
+    206, // '»'
+    234, // '¼'
+    248, // '½'
+    158, // '¾'
+    239, // '¿'
+    255, // 'À'
+    255, // 'Á'
+    255, // 'Â'
+    255, // 'Ã'
+    255, // 'Ä'
+    255, // 'Å'
+    255, // 'Æ'
+    255, // 'Ç'
+    255, // 'È'
+    255, // 'É'
+    255, // 'Ê'
+    255, // 'Ë'
+    255, // 'Ì'
+    255, // 'Í'
+    255, // 'Î'
+    255, // 'Ï'
+    255, // 'Ð'
+    255, // 'Ñ'
+    255, // 'Ò'
+    255, // 'Ó'
+    255, // 'Ô'
+    255, // 'Õ'
+    255, // 'Ö'
+    255, // '×'
+    255, // 'Ø'
+    255, // 'Ù'
+    255, // 'Ú'
+    255, // 'Û'
+    255, // 'Ü'
+    255, // 'Ý'
+    255, // 'Þ'
+    255, // 'ß'
+    255, // 'à'
+    255, // 'á'
+    255, // 'â'
+    255, // 'ã'
+    255, // 'ä'
+    255, // 'å'
+    255, // 'æ'
+    255, // 'ç'
+    255, // 'è'
+    255, // 'é'
+    255, // 'ê'
+    255, // 'ë'
+    255, // 'ì'
+    255, // 'í'
+    255, // 'î'
+    255, // 'ï'
+    255, // 'ð'
+    255, // 'ñ'
+    255, // 'ò'
+    255, // 'ó'
+    255, // 'ô'
+    255, // 'õ'
+    255, // 'ö'
+    255, // '÷'
+    255, // 'ø'
+    255, // 'ù'
+    255, // 'ú'
+    255, // 'û'
+    255, // 'ü'
+    255, // 'ý'
+    255, // 'þ'
+    255, // 'ÿ'
+];
diff --git a/vendor/regex-1.4.6/src/input.rs b/vendor/regex-1.4.6/src/input.rs
new file mode 100644 (file)
index 0000000..3afa2d0
--- /dev/null
@@ -0,0 +1,434 @@
+use std::char;
+use std::cmp::Ordering;
+use std::fmt;
+use std::ops;
+use std::u32;
+
+use syntax;
+
+use literal::LiteralSearcher;
+use prog::InstEmptyLook;
+use utf8::{decode_last_utf8, decode_utf8};
+
+/// Represents a location in the input.
+#[derive(Clone, Copy, Debug)]
+pub struct InputAt {
+    pos: usize,
+    c: Char,
+    byte: Option<u8>,
+    len: usize,
+}
+
+impl InputAt {
+    /// Returns true iff this position is at the beginning of the input.
+    pub fn is_start(&self) -> bool {
+        self.pos == 0
+    }
+
+    /// Returns true iff this position is past the end of the input.
+    pub fn is_end(&self) -> bool {
+        self.c.is_none() && self.byte.is_none()
+    }
+
+    /// Returns the character at this position.
+    ///
+    /// If this position is just before or after the input, then an absent
+    /// character is returned.
+    pub fn char(&self) -> Char {
+        self.c
+    }
+
+    /// Returns the byte at this position.
+    pub fn byte(&self) -> Option<u8> {
+        self.byte
+    }
+
+    /// Returns the UTF-8 width of the character at this position.
+    pub fn len(&self) -> usize {
+        self.len
+    }
+
+    /// Returns whether the UTF-8 width of the character at this position
+    /// is zero.
+    pub fn is_empty(&self) -> bool {
+        self.len == 0
+    }
+
+    /// Returns the byte offset of this position.
+    pub fn pos(&self) -> usize {
+        self.pos
+    }
+
+    /// Returns the byte offset of the next position in the input.
+    pub fn next_pos(&self) -> usize {
+        self.pos + self.len
+    }
+}
+
+/// An abstraction over input used in the matching engines.
+pub trait Input: fmt::Debug {
+    /// Return an encoding of the position at byte offset `i`.
+    fn at(&self, i: usize) -> InputAt;
+
+    /// Return the Unicode character occurring next to `at`.
+    ///
+    /// If no such character could be decoded, then `Char` is absent.
+    fn next_char(&self, at: InputAt) -> Char;
+
+    /// Return the Unicode character occurring previous to `at`.
+    ///
+    /// If no such character could be decoded, then `Char` is absent.
+    fn previous_char(&self, at: InputAt) -> Char;
+
+    /// Return true if the given empty width instruction matches at the
+    /// input position given.
+    fn is_empty_match(&self, at: InputAt, empty: &InstEmptyLook) -> bool;
+
+    /// Scan the input for a matching prefix.
+    fn prefix_at(
+        &self,
+        prefixes: &LiteralSearcher,
+        at: InputAt,
+    ) -> Option<InputAt>;
+
+    /// The number of bytes in the input.
+    fn len(&self) -> usize;
+
+    /// Whether the input is empty.
+    fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    /// Return the given input as a sequence of bytes.
+    fn as_bytes(&self) -> &[u8];
+}
+
+impl<'a, T: Input> Input for &'a T {
+    fn at(&self, i: usize) -> InputAt {
+        (**self).at(i)
+    }
+
+    fn next_char(&self, at: InputAt) -> Char {
+        (**self).next_char(at)
+    }
+
+    fn previous_char(&self, at: InputAt) -> Char {
+        (**self).previous_char(at)
+    }
+
+    fn is_empty_match(&self, at: InputAt, empty: &InstEmptyLook) -> bool {
+        (**self).is_empty_match(at, empty)
+    }
+
+    fn prefix_at(
+        &self,
+        prefixes: &LiteralSearcher,
+        at: InputAt,
+    ) -> Option<InputAt> {
+        (**self).prefix_at(prefixes, at)
+    }
+
+    fn len(&self) -> usize {
+        (**self).len()
+    }
+
+    fn as_bytes(&self) -> &[u8] {
+        (**self).as_bytes()
+    }
+}
+
+/// An input reader over characters.
+#[derive(Clone, Copy, Debug)]
+pub struct CharInput<'t>(&'t [u8]);
+
+impl<'t> CharInput<'t> {
+    /// Return a new character input reader for the given string.
+    pub fn new(s: &'t [u8]) -> CharInput<'t> {
+        CharInput(s)
+    }
+}
+
+impl<'t> ops::Deref for CharInput<'t> {
+    type Target = [u8];
+
+    fn deref(&self) -> &[u8] {
+        self.0
+    }
+}
+
+impl<'t> Input for CharInput<'t> {
+    fn at(&self, i: usize) -> InputAt {
+        if i >= self.len() {
+            InputAt { pos: self.len(), c: None.into(), byte: None, len: 0 }
+        } else {
+            let c = decode_utf8(&self[i..]).map(|(c, _)| c).into();
+            InputAt { pos: i, c: c, byte: None, len: c.len_utf8() }
+        }
+    }
+
+    fn next_char(&self, at: InputAt) -> Char {
+        at.char()
+    }
+
+    fn previous_char(&self, at: InputAt) -> Char {
+        decode_last_utf8(&self[..at.pos()]).map(|(c, _)| c).into()
+    }
+
+    fn is_empty_match(&self, at: InputAt, empty: &InstEmptyLook) -> bool {
+        use prog::EmptyLook::*;
+        match empty.look {
+            StartLine => {
+                let c = self.previous_char(at);
+                at.pos() == 0 || c == '\n'
+            }
+            EndLine => {
+                let c = self.next_char(at);
+                at.pos() == self.len() || c == '\n'
+            }
+            StartText => at.pos() == 0,
+            EndText => at.pos() == self.len(),
+            WordBoundary => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                c1.is_word_char() != c2.is_word_char()
+            }
+            NotWordBoundary => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                c1.is_word_char() == c2.is_word_char()
+            }
+            WordBoundaryAscii => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                c1.is_word_byte() != c2.is_word_byte()
+            }
+            NotWordBoundaryAscii => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                c1.is_word_byte() == c2.is_word_byte()
+            }
+        }
+    }
+
+    fn prefix_at(
+        &self,
+        prefixes: &LiteralSearcher,
+        at: InputAt,
+    ) -> Option<InputAt> {
+        prefixes.find(&self[at.pos()..]).map(|(s, _)| self.at(at.pos() + s))
+    }
+
+    fn len(&self) -> usize {
+        self.0.len()
+    }
+
+    fn as_bytes(&self) -> &[u8] {
+        self.0
+    }
+}
+
+/// An input reader over bytes.
+#[derive(Clone, Copy, Debug)]
+pub struct ByteInput<'t> {
+    text: &'t [u8],
+    only_utf8: bool,
+}
+
+impl<'t> ByteInput<'t> {
+    /// Return a new byte-based input reader for the given string.
+    pub fn new(text: &'t [u8], only_utf8: bool) -> ByteInput<'t> {
+        ByteInput { text: text, only_utf8: only_utf8 }
+    }
+}
+
+impl<'t> ops::Deref for ByteInput<'t> {
+    type Target = [u8];
+
+    fn deref(&self) -> &[u8] {
+        self.text
+    }
+}
+
+impl<'t> Input for ByteInput<'t> {
+    fn at(&self, i: usize) -> InputAt {
+        if i >= self.len() {
+            InputAt { pos: self.len(), c: None.into(), byte: None, len: 0 }
+        } else {
+            InputAt {
+                pos: i,
+                c: None.into(),
+                byte: self.get(i).cloned(),
+                len: 1,
+            }
+        }
+    }
+
+    fn next_char(&self, at: InputAt) -> Char {
+        decode_utf8(&self[at.pos()..]).map(|(c, _)| c).into()
+    }
+
+    fn previous_char(&self, at: InputAt) -> Char {
+        decode_last_utf8(&self[..at.pos()]).map(|(c, _)| c).into()
+    }
+
+    fn is_empty_match(&self, at: InputAt, empty: &InstEmptyLook) -> bool {
+        use prog::EmptyLook::*;
+        match empty.look {
+            StartLine => {
+                let c = self.previous_char(at);
+                at.pos() == 0 || c == '\n'
+            }
+            EndLine => {
+                let c = self.next_char(at);
+                at.pos() == self.len() || c == '\n'
+            }
+            StartText => at.pos() == 0,
+            EndText => at.pos() == self.len(),
+            WordBoundary => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                c1.is_word_char() != c2.is_word_char()
+            }
+            NotWordBoundary => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                c1.is_word_char() == c2.is_word_char()
+            }
+            WordBoundaryAscii => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                if self.only_utf8 {
+                    // If we must match UTF-8, then we can't match word
+                    // boundaries at invalid UTF-8.
+                    if c1.is_none() && !at.is_start() {
+                        return false;
+                    }
+                    if c2.is_none() && !at.is_end() {
+                        return false;
+                    }
+                }
+                c1.is_word_byte() != c2.is_word_byte()
+            }
+            NotWordBoundaryAscii => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                if self.only_utf8 {
+                    // If we must match UTF-8, then we can't match word
+                    // boundaries at invalid UTF-8.
+                    if c1.is_none() && !at.is_start() {
+                        return false;
+                    }
+                    if c2.is_none() && !at.is_end() {
+                        return false;
+                    }
+                }
+                c1.is_word_byte() == c2.is_word_byte()
+            }
+        }
+    }
+
+    fn prefix_at(
+        &self,
+        prefixes: &LiteralSearcher,
+        at: InputAt,
+    ) -> Option<InputAt> {
+        prefixes.find(&self[at.pos()..]).map(|(s, _)| self.at(at.pos() + s))
+    }
+
+    fn len(&self) -> usize {
+        self.text.len()
+    }
+
+    fn as_bytes(&self) -> &[u8] {
+        self.text
+    }
+}
+
+/// An inline representation of `Option<char>`.
+///
+/// This eliminates the need to do case analysis on `Option<char>` to determine
+/// ordinality with other characters.
+///
+/// (The `Option<char>` is not related to encoding. Instead, it is used in the
+/// matching engines to represent the beginning and ending boundaries of the
+/// search text.)
+#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Char(u32);
+
+impl fmt::Debug for Char {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match char::from_u32(self.0) {
+            None => write!(f, "Empty"),
+            Some(c) => write!(f, "{:?}", c),
+        }
+    }
+}
+
+impl Char {
+    /// Returns true iff the character is absent.
+    #[inline]
+    pub fn is_none(self) -> bool {
+        self.0 == u32::MAX
+    }
+
+    /// Returns the length of the character's UTF-8 encoding.
+    ///
+    /// If the character is absent, then `1` is returned.
+    #[inline]
+    pub fn len_utf8(self) -> usize {
+        char::from_u32(self.0).map_or(1, |c| c.len_utf8())
+    }
+
+    /// Returns true iff the character is a word character.
+    ///
+    /// If the character is absent, then false is returned.
+    pub fn is_word_char(self) -> bool {
+        // is_word_character can panic if the Unicode data for \w isn't
+        // available. However, our compiler ensures that if a Unicode word
+        // boundary is used, then the data must also be available. If it isn't,
+        // then the compiler returns an error.
+        char::from_u32(self.0).map_or(false, syntax::is_word_character)
+    }
+
+    /// Returns true iff the byte is a word byte.
+    ///
+    /// If the byte is absent, then false is returned.
+    pub fn is_word_byte(self) -> bool {
+        match char::from_u32(self.0) {
+            Some(c) if c <= '\u{7F}' => syntax::is_word_byte(c as u8),
+            None | Some(_) => false,
+        }
+    }
+}
+
+impl From<char> for Char {
+    fn from(c: char) -> Char {
+        Char(c as u32)
+    }
+}
+
+impl From<Option<char>> for Char {
+    fn from(c: Option<char>) -> Char {
+        c.map_or(Char(u32::MAX), |c| c.into())
+    }
+}
+
+impl PartialEq<char> for Char {
+    #[inline]
+    fn eq(&self, other: &char) -> bool {
+        self.0 == *other as u32
+    }
+}
+
+impl PartialEq<Char> for char {
+    #[inline]
+    fn eq(&self, other: &Char) -> bool {
+        *self as u32 == other.0
+    }
+}
+
+impl PartialOrd<char> for Char {
+    #[inline]
+    fn partial_cmp(&self, other: &char) -> Option<Ordering> {
+        self.0.partial_cmp(&(*other as u32))
+    }
+}
+
+impl PartialOrd<Char> for char {
+    #[inline]
+    fn partial_cmp(&self, other: &Char) -> Option<Ordering> {
+        (*self as u32).partial_cmp(&other.0)
+    }
+}
diff --git a/vendor/regex-1.4.6/src/lib.rs b/vendor/regex-1.4.6/src/lib.rs
new file mode 100644 (file)
index 0000000..357ac0d
--- /dev/null
@@ -0,0 +1,785 @@
+/*!
+This crate provides a library for parsing, compiling, and executing regular
+expressions. Its syntax is similar to Perl-style regular expressions, but lacks
+a few features like look around and backreferences. In exchange, all searches
+execute in linear time with respect to the size of the regular expression and
+search text.
+
+This crate's documentation provides some simple examples, describes
+[Unicode support](#unicode) and exhaustively lists the
+[supported syntax](#syntax).
+
+For more specific details on the API for regular expressions, please see the
+documentation for the [`Regex`](struct.Regex.html) type.
+
+# Usage
+
+This crate is [on crates.io](https://crates.io/crates/regex) and can be
+used by adding `regex` to your dependencies in your project's `Cargo.toml`.
+
+```toml
+[dependencies]
+regex = "1"
+```
+
+If you're using Rust 2015, then you'll also need to add it to your crate root:
+
+```rust
+extern crate regex;
+```
+
+# Example: find a date
+
+General use of regular expressions in this package involves compiling an
+expression and then using it to search, split or replace text. For example,
+to confirm that some text resembles a date:
+
+```rust
+use regex::Regex;
+let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
+assert!(re.is_match("2014-01-01"));
+```
+
+Notice the use of the `^` and `$` anchors. In this crate, every expression
+is executed with an implicit `.*?` at the beginning and end, which allows
+it to match anywhere in the text. Anchors can be used to ensure that the
+full text matches an expression.
+
+This example also demonstrates the utility of
+[raw strings](https://doc.rust-lang.org/stable/reference/tokens.html#raw-string-literals)
+in Rust, which
+are just like regular strings except they are prefixed with an `r` and do
+not process any escape sequences. For example, `"\\d"` is the same
+expression as `r"\d"`.
+
+# Example: Avoid compiling the same regex in a loop
+
+It is an anti-pattern to compile the same regular expression in a loop
+since compilation is typically expensive. (It takes anywhere from a few
+microseconds to a few **milliseconds** depending on the size of the
+regex.) Not only is compilation itself expensive, but this also prevents
+optimizations that reuse allocations internally to the matching engines.
+
+In Rust, it can sometimes be a pain to pass regular expressions around if
+they're used from inside a helper function. Instead, we recommend using the
+[`lazy_static`](https://crates.io/crates/lazy_static) crate to ensure that
+regular expressions are compiled exactly once.
+
+For example:
+
+```rust
+#[macro_use] extern crate lazy_static;
+extern crate regex;
+
+use regex::Regex;
+
+fn some_helper_function(text: &str) -> bool {
+    lazy_static! {
+        static ref RE: Regex = Regex::new("...").unwrap();
+    }
+    RE.is_match(text)
+}
+
+fn main() {}
+```
+
+Specifically, in this example, the regex will be compiled when it is used for
+the first time. On subsequent uses, it will reuse the previous compilation.
+
+# Example: iterating over capture groups
+
+This crate provides convenient iterators for matching an expression
+repeatedly against a search string to find successive non-overlapping
+matches. For example, to find all dates in a string and be able to access
+them by their component pieces:
+
+```rust
+# extern crate regex; use regex::Regex;
+# fn main() {
+let re = Regex::new(r"(\d{4})-(\d{2})-(\d{2})").unwrap();
+let text = "2012-03-14, 2013-01-01 and 2014-07-05";
+for cap in re.captures_iter(text) {
+    println!("Month: {} Day: {} Year: {}", &cap[2], &cap[3], &cap[1]);
+}
+// Output:
+// Month: 03 Day: 14 Year: 2012
+// Month: 01 Day: 01 Year: 2013
+// Month: 07 Day: 05 Year: 2014
+# }
+```
+
+Notice that the year is in the capture group indexed at `1`. This is
+because the *entire match* is stored in the capture group at index `0`.
+
+# Example: replacement with named capture groups
+
+Building on the previous example, perhaps we'd like to rearrange the date
+formats. This can be done with text replacement. But to make the code
+clearer, we can *name*  our capture groups and use those names as variables
+in our replacement text:
+
+```rust
+# extern crate regex; use regex::Regex;
+# fn main() {
+let re = Regex::new(r"(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})").unwrap();
+let before = "2012-03-14, 2013-01-01 and 2014-07-05";
+let after = re.replace_all(before, "$m/$d/$y");
+assert_eq!(after, "03/14/2012, 01/01/2013 and 07/05/2014");
+# }
+```
+
+The `replace` methods are actually polymorphic in the replacement, which
+provides more flexibility than is seen here. (See the documentation for
+`Regex::replace` for more details.)
+
+Note that if your regex gets complicated, you can use the `x` flag to
+enable insignificant whitespace mode, which also lets you write comments:
+
+```rust
+# extern crate regex; use regex::Regex;
+# fn main() {
+let re = Regex::new(r"(?x)
+  (?P<y>\d{4}) # the year
+  -
+  (?P<m>\d{2}) # the month
+  -
+  (?P<d>\d{2}) # the day
+").unwrap();
+let before = "2012-03-14, 2013-01-01 and 2014-07-05";
+let after = re.replace_all(before, "$m/$d/$y");
+assert_eq!(after, "03/14/2012, 01/01/2013 and 07/05/2014");
+# }
+```
+
+If you wish to match against whitespace in this mode, you can still use `\s`,
+`\n`, `\t`, etc. For escaping a single space character, you can escape it
+directly with `\ `, use its hex character code `\x20` or temporarily disable
+the `x` flag, e.g., `(?-x: )`.
+
+# Example: match multiple regular expressions simultaneously
+
+This demonstrates how to use a `RegexSet` to match multiple (possibly
+overlapping) regular expressions in a single scan of the search text:
+
+```rust
+use regex::RegexSet;
+
+let set = RegexSet::new(&[
+    r"\w+",
+    r"\d+",
+    r"\pL+",
+    r"foo",
+    r"bar",
+    r"barfoo",
+    r"foobar",
+]).unwrap();
+
+// Iterate over and collect all of the matches.
+let matches: Vec<_> = set.matches("foobar").into_iter().collect();
+assert_eq!(matches, vec![0, 2, 3, 4, 6]);
+
+// You can also test whether a particular regex matched:
+let matches = set.matches("foobar");
+assert!(!matches.matched(5));
+assert!(matches.matched(6));
+```
+
+# Pay for what you use
+
+With respect to searching text with a regular expression, there are three
+questions that can be asked:
+
+1. Does the text match this expression?
+2. If so, where does it match?
+3. Where did the capturing groups match?
+
+Generally speaking, this crate could provide a function to answer only #3,
+which would subsume #1 and #2 automatically. However, it can be significantly
+more expensive to compute the location of capturing group matches, so it's best
+not to do it if you don't need to.
+
+Therefore, only use what you need. For example, don't use `find` if you
+only need to test if an expression matches a string. (Use `is_match`
+instead.)
+
+# Unicode
+
+This implementation executes regular expressions **only** on valid UTF-8
+while exposing match locations as byte indices into the search string. (To
+relax this restriction, use the [`bytes`](bytes/index.html) sub-module.)
+
+Only simple case folding is supported. Namely, when matching
+case-insensitively, the characters are first mapped using the "simple" case
+folding rules defined by Unicode.
+
+Regular expressions themselves are **only** interpreted as a sequence of
+Unicode scalar values. This means you can use Unicode characters directly
+in your expression:
+
+```rust
+# extern crate regex; use regex::Regex;
+# fn main() {
+let re = Regex::new(r"(?i)Δ+").unwrap();
+let mat = re.find("ΔδΔ").unwrap();
+assert_eq!((mat.start(), mat.end()), (0, 6));
+# }
+```
+
+Most features of the regular expressions in this crate are Unicode aware. Here
+are some examples:
+
+* `.` will match any valid UTF-8 encoded Unicode scalar value except for `\n`.
+  (To also match `\n`, enable the `s` flag, e.g., `(?s:.)`.)
+* `\w`, `\d` and `\s` are Unicode aware. For example, `\s` will match all forms
+  of whitespace categorized by Unicode.
+* `\b` matches a Unicode word boundary.
+* Negated character classes like `[^a]` match all Unicode scalar values except
+  for `a`.
+* `^` and `$` are **not** Unicode aware in multi-line mode. Namely, they only
+  recognize `\n` and not any of the other forms of line terminators defined
+  by Unicode.
+
+Unicode general categories, scripts, script extensions, ages and a smattering
+of boolean properties are available as character classes. For example, you can
+match a sequence of numerals, Greek or Cherokee letters:
+
+```rust
+# extern crate regex; use regex::Regex;
+# fn main() {
+let re = Regex::new(r"[\pN\p{Greek}\p{Cherokee}]+").unwrap();
+let mat = re.find("abcΔᎠβⅠᏴγδⅡxyz").unwrap();
+assert_eq!((mat.start(), mat.end()), (3, 23));
+# }
+```
+
+For a more detailed breakdown of Unicode support with respect to
+[UTS#18](https://unicode.org/reports/tr18/),
+please see the
+[UNICODE](https://github.com/rust-lang/regex/blob/master/UNICODE.md)
+document in the root of the regex repository.
+
+# Opt out of Unicode support
+
+The `bytes` sub-module provides a `Regex` type that can be used to match
+on `&[u8]`. By default, text is interpreted as UTF-8 just like it is with
+the main `Regex` type. However, this behavior can be disabled by turning
+off the `u` flag, even if doing so could result in matching invalid UTF-8.
+For example, when the `u` flag is disabled, `.` will match any byte instead
+of any Unicode scalar value.
+
+Disabling the `u` flag is also possible with the standard `&str`-based `Regex`
+type, but it is only allowed where the UTF-8 invariant is maintained. For
+example, `(?-u:\w)` is an ASCII-only `\w` character class and is legal in an
+`&str`-based `Regex`, but `(?-u:\xFF)` will attempt to match the raw byte
+`\xFF`, which is invalid UTF-8 and therefore is illegal in `&str`-based
+regexes.
+
+Finally, since Unicode support requires bundling large Unicode data
+tables, this crate exposes knobs to disable the compilation of those
+data tables, which can be useful for shrinking binary size and reducing
+compilation times. For details on how to do that, see the section on [crate
+features](#crate-features).
+
+# Syntax
+
+The syntax supported in this crate is documented below.
+
+Note that the regular expression parser and abstract syntax are exposed in
+a separate crate, [`regex-syntax`](https://docs.rs/regex-syntax).
+
+## Matching one character
+
+<pre class="rust">
+.             any character except new line (includes new line with s flag)
+\d            digit (\p{Nd})
+\D            not digit
+\pN           One-letter name Unicode character class
+\p{Greek}     Unicode character class (general category or script)
+\PN           Negated one-letter name Unicode character class
+\P{Greek}     negated Unicode character class (general category or script)
+</pre>
+
+### Character classes
+
+<pre class="rust">
+[xyz]         A character class matching either x, y or z (union).
+[^xyz]        A character class matching any character except x, y and z.
+[a-z]         A character class matching any character in range a-z.
+[[:alpha:]]   ASCII character class ([A-Za-z])
+[[:^alpha:]]  Negated ASCII character class ([^A-Za-z])
+[x[^xyz]]     Nested/grouping character class (matching any character except y and z)
+[a-y&&xyz]    Intersection (matching x or y)
+[0-9&&[^4]]   Subtraction using intersection and negation (matching 0-9 except 4)
+[0-9--4]      Direct subtraction (matching 0-9 except 4)
+[a-g~~b-h]    Symmetric difference (matching `a` and `h` only)
+[\[\]]        Escaping in character classes (matching [ or ])
+</pre>
+
+Any named character class may appear inside a bracketed `[...]` character
+class. For example, `[\p{Greek}[:digit:]]` matches any Greek or ASCII
+digit. `[\p{Greek}&&\pL]` matches Greek letters.
+
+Precedence in character classes, from most binding to least:
+
+1. Ranges: `a-cd` == `[a-c]d`
+2. Union: `ab&&bc` == `[ab]&&[bc]`
+3. Intersection: `^a-z&&b` == `^[a-z&&b]`
+4. Negation
+
+## Composites
+
+<pre class="rust">
+xy    concatenation (x followed by y)
+x|y   alternation (x or y, prefer x)
+</pre>
+
+## Repetitions
+
+<pre class="rust">
+x*        zero or more of x (greedy)
+x+        one or more of x (greedy)
+x?        zero or one of x (greedy)
+x*?       zero or more of x (ungreedy/lazy)
+x+?       one or more of x (ungreedy/lazy)
+x??       zero or one of x (ungreedy/lazy)
+x{n,m}    at least n x and at most m x (greedy)
+x{n,}     at least n x (greedy)
+x{n}      exactly n x
+x{n,m}?   at least n x and at most m x (ungreedy/lazy)
+x{n,}?    at least n x (ungreedy/lazy)
+x{n}?     exactly n x
+</pre>
+
+## Empty matches
+
+<pre class="rust">
+^     the beginning of text (or start-of-line with multi-line mode)
+$     the end of text (or end-of-line with multi-line mode)
+\A    only the beginning of text (even with multi-line mode enabled)
+\z    only the end of text (even with multi-line mode enabled)
+\b    a Unicode word boundary (\w on one side and \W, \A, or \z on other)
+\B    not a Unicode word boundary
+</pre>
+
+## Grouping and flags
+
+<pre class="rust">
+(exp)          numbered capture group (indexed by opening parenthesis)
+(?P&lt;name&gt;exp)  named (also numbered) capture group (allowed chars: [_0-9a-zA-Z.\[\]])
+(?:exp)        non-capturing group
+(?flags)       set flags within current group
+(?flags:exp)   set flags for exp (non-capturing)
+</pre>
+
+Flags are each a single character. For example, `(?x)` sets the flag `x`
+and `(?-x)` clears the flag `x`. Multiple flags can be set or cleared at
+the same time: `(?xy)` sets both the `x` and `y` flags and `(?x-y)` sets
+the `x` flag and clears the `y` flag.
+
+All flags are by default disabled unless stated otherwise. They are:
+
+<pre class="rust">
+i     case-insensitive: letters match both upper and lower case
+m     multi-line mode: ^ and $ match begin/end of line
+s     allow . to match \n
+U     swap the meaning of x* and x*?
+u     Unicode support (enabled by default)
+x     ignore whitespace and allow line comments (starting with `#`)
+</pre>
+
+Flags can be toggled within a pattern. Here's an example that matches
+case-insensitively for the first part but case-sensitively for the second part:
+
+```rust
+# extern crate regex; use regex::Regex;
+# fn main() {
+let re = Regex::new(r"(?i)a+(?-i)b+").unwrap();
+let cap = re.captures("AaAaAbbBBBb").unwrap();
+assert_eq!(&cap[0], "AaAaAbb");
+# }
+```
+
+Notice that the `a+` matches either `a` or `A`, but the `b+` only matches
+`b`.
+
+Multi-line mode means `^` and `$` no longer match just at the beginning/end of
+the input, but at the beginning/end of lines:
+
+```
+# use regex::Regex;
+let re = Regex::new(r"(?m)^line \d+").unwrap();
+let m = re.find("line one\nline 2\n").unwrap();
+assert_eq!(m.as_str(), "line 2");
+```
+
+Note that `^` matches after new lines, even at the end of input:
+
+```
+# use regex::Regex;
+let re = Regex::new(r"(?m)^").unwrap();
+let m = re.find_iter("test\n").last().unwrap();
+assert_eq!((m.start(), m.end()), (5, 5));
+```
+
+Here is an example that uses an ASCII word boundary instead of a Unicode
+word boundary:
+
+```rust
+# extern crate regex; use regex::Regex;
+# fn main() {
+let re = Regex::new(r"(?-u:\b).+(?-u:\b)").unwrap();
+let cap = re.captures("$$abc$$").unwrap();
+assert_eq!(&cap[0], "abc");
+# }
+```
+
+## Escape sequences
+
+<pre class="rust">
+\*          literal *, works for any punctuation character: \.+*?()|[]{}^$
+\a          bell (\x07)
+\f          form feed (\x0C)
+\t          horizontal tab
+\n          new line
+\r          carriage return
+\v          vertical tab (\x0B)
+\123        octal character code (up to three digits) (when enabled)
+\x7F        hex character code (exactly two digits)
+\x{10FFFF}  any hex character code corresponding to a Unicode code point
+\u007F      hex character code (exactly four digits)
+\u{7F}      any hex character code corresponding to a Unicode code point
+\U0000007F  hex character code (exactly eight digits)
+\U{7F}      any hex character code corresponding to a Unicode code point
+</pre>
+
+## Perl character classes (Unicode friendly)
+
+These classes are based on the definitions provided in
+[UTS#18](https://www.unicode.org/reports/tr18/#Compatibility_Properties):
+
+<pre class="rust">
+\d     digit (\p{Nd})
+\D     not digit
+\s     whitespace (\p{White_Space})
+\S     not whitespace
+\w     word character (\p{Alphabetic} + \p{M} + \d + \p{Pc} + \p{Join_Control})
+\W     not word character
+</pre>
+
+## ASCII character classes
+
+<pre class="rust">
+[[:alnum:]]    alphanumeric ([0-9A-Za-z])
+[[:alpha:]]    alphabetic ([A-Za-z])
+[[:ascii:]]    ASCII ([\x00-\x7F])
+[[:blank:]]    blank ([\t ])
+[[:cntrl:]]    control ([\x00-\x1F\x7F])
+[[:digit:]]    digits ([0-9])
+[[:graph:]]    graphical ([!-~])
+[[:lower:]]    lower case ([a-z])
+[[:print:]]    printable ([ -~])
+[[:punct:]]    punctuation ([!-/:-@\[-`{-~])
+[[:space:]]    whitespace ([\t\n\v\f\r ])
+[[:upper:]]    upper case ([A-Z])
+[[:word:]]     word characters ([0-9A-Za-z_])
+[[:xdigit:]]   hex digit ([0-9A-Fa-f])
+</pre>
+
+# Crate features
+
+By default, this crate tries pretty hard to make regex matching both as fast
+as possible and as correct as it can be, within reason. This means that there
+is a lot of code dedicated to performance, the handling of Unicode data and the
+Unicode data itself. Overall, this leads to more dependencies, larger binaries
+and longer compile times.  This trade off may not be appropriate in all cases,
+and indeed, even when all Unicode and performance features are disabled, one
+is still left with a perfectly serviceable regex engine that will work well
+in many cases.
+
+This crate exposes a number of features for controlling that trade off. Some
+of these features are strictly performance oriented, such that disabling them
+won't result in a loss of functionality, but may result in worse performance.
+Other features, such as the ones controlling the presence or absence of Unicode
+data, can result in a loss of functionality. For example, if one disables the
+`unicode-case` feature (described below), then compiling the regex `(?i)a`
+will fail since Unicode case insensitivity is enabled by default. Instead,
+callers must use `(?i-u)a` instead to disable Unicode case folding. Stated
+differently, enabling or disabling any of the features below can only add or
+subtract from the total set of valid regular expressions. Enabling or disabling
+a feature will never modify the match semantics of a regular expression.
+
+All features below are enabled by default.
+
+### Ecosystem features
+
+* **std** -
+  When enabled, this will cause `regex` to use the standard library. Currently,
+  disabling this feature will always result in a compilation error. It is
+  intended to add `alloc`-only support to regex in the future.
+
+### Performance features
+
+* **perf** -
+  Enables all performance related features. This feature is enabled by default
+  and will always cover all features that improve performance, even if more
+  are added in the future.
+* **perf-dfa** -
+  Enables the use of a lazy DFA for matching. The lazy DFA is used to compile
+  portions of a regex to a very fast DFA on an as-needed basis. This can
+  result in substantial speedups, usually by an order of magnitude on large
+  haystacks. The lazy DFA does not bring in any new dependencies, but it can
+  make compile times longer.
+* **perf-inline** -
+  Enables the use of aggressive inlining inside match routines. This reduces
+  the overhead of each match. The aggressive inlining, however, increases
+  compile times and binary size.
+* **perf-literal** -
+  Enables the use of literal optimizations for speeding up matches. In some
+  cases, literal optimizations can result in speedups of _several_ orders of
+  magnitude. Disabling this drops the `aho-corasick` and `memchr` dependencies.
+* **perf-cache** -
+  This feature used to enable a faster internal cache at the cost of using
+  additional dependencies, but this is no longer an option. A fast internal
+  cache is now used unconditionally with no additional dependencies. This may
+  change in the future.
+
+### Unicode features
+
+* **unicode** -
+  Enables all Unicode features. This feature is enabled by default, and will
+  always cover all Unicode features, even if more are added in the future.
+* **unicode-age** -
+  Provide the data for the
+  [Unicode `Age` property](https://www.unicode.org/reports/tr44/tr44-24.html#Character_Age).
+  This makes it possible to use classes like `\p{Age:6.0}` to refer to all
+  codepoints first introduced in Unicode 6.0
+* **unicode-bool** -
+  Provide the data for numerous Unicode boolean properties. The full list
+  is not included here, but contains properties like `Alphabetic`, `Emoji`,
+  `Lowercase`, `Math`, `Uppercase` and `White_Space`.
+* **unicode-case** -
+  Provide the data for case insensitive matching using
+  [Unicode's "simple loose matches" specification](https://www.unicode.org/reports/tr18/#Simple_Loose_Matches).
+* **unicode-gencat** -
+  Provide the data for
+  [Unicode general categories](https://www.unicode.org/reports/tr44/tr44-24.html#General_Category_Values).
+  This includes, but is not limited to, `Decimal_Number`, `Letter`,
+  `Math_Symbol`, `Number` and `Punctuation`.
+* **unicode-perl** -
+  Provide the data for supporting the Unicode-aware Perl character classes,
+  corresponding to `\w`, `\s` and `\d`. This is also necessary for using
+  Unicode-aware word boundary assertions. Note that if this feature is
+  disabled, the `\s` and `\d` character classes are still available if the
+  `unicode-bool` and `unicode-gencat` features are enabled, respectively.
+* **unicode-script** -
+  Provide the data for
+  [Unicode scripts and script extensions](https://www.unicode.org/reports/tr24/).
+  This includes, but is not limited to, `Arabic`, `Cyrillic`, `Hebrew`,
+  `Latin` and `Thai`.
+* **unicode-segment** -
+  Provide the data necessary to provide the properties used to implement the
+  [Unicode text segmentation algorithms](https://www.unicode.org/reports/tr29/).
+  This enables using classes like `\p{gcb=Extend}`, `\p{wb=Katakana}` and
+  `\p{sb=ATerm}`.
+
+
+# Untrusted input
+
+This crate can handle both untrusted regular expressions and untrusted
+search text.
+
+Untrusted regular expressions are handled by capping the size of a compiled
+regular expression.
+(See [`RegexBuilder::size_limit`](struct.RegexBuilder.html#method.size_limit).)
+Without this, it would be trivial for an attacker to exhaust your system's
+memory with expressions like `a{100}{100}{100}`.
+
+Untrusted search text is allowed because the matching engine(s) in this
+crate have time complexity `O(mn)` (with `m ~ regex` and `n ~ search
+text`), which means there's no way to cause exponential blow-up like with
+some other regular expression engines. (We pay for this by disallowing
+features like arbitrary look-ahead and backreferences.)
+
+When a DFA is used, pathological cases with exponential state blow-up are
+avoided by constructing the DFA lazily or in an "online" manner. Therefore,
+at most one new state can be created for each byte of input. This satisfies
+our time complexity guarantees, but can lead to memory growth
+proportional to the size of the input. As a stopgap, the DFA is only
+allowed to store a fixed number of states. When the limit is reached, its
+states are wiped and continues on, possibly duplicating previous work. If
+the limit is reached too frequently, it gives up and hands control off to
+another matching engine with fixed memory requirements.
+(The DFA size limit can also be tweaked. See
+[`RegexBuilder::dfa_size_limit`](struct.RegexBuilder.html#method.dfa_size_limit).)
+*/
+
+#![deny(missing_docs)]
+#![cfg_attr(test, deny(warnings))]
+#![cfg_attr(feature = "pattern", feature(pattern))]
+#![warn(missing_debug_implementations)]
+
+#[cfg(not(feature = "std"))]
+compile_error!("`std` feature is currently required to build this crate");
+
+#[cfg(feature = "perf-literal")]
+extern crate aho_corasick;
+// #[cfg(doctest)]
+// extern crate doc_comment;
+#[cfg(feature = "perf-literal")]
+extern crate memchr;
+#[cfg(test)]
+#[cfg_attr(feature = "perf-literal", macro_use)]
+extern crate quickcheck;
+extern crate regex_syntax as syntax;
+
+// #[cfg(doctest)]
+// doc_comment::doctest!("../README.md");
+
+#[cfg(feature = "std")]
+pub use error::Error;
+#[cfg(feature = "std")]
+pub use re_builder::set_unicode::*;
+#[cfg(feature = "std")]
+pub use re_builder::unicode::*;
+#[cfg(feature = "std")]
+pub use re_set::unicode::*;
+#[cfg(feature = "std")]
+#[cfg(feature = "std")]
+pub use re_unicode::{
+    escape, CaptureLocations, CaptureMatches, CaptureNames, Captures,
+    Locations, Match, Matches, NoExpand, Regex, Replacer, ReplacerRef, Split,
+    SplitN, SubCaptureMatches,
+};
+
+/**
+Match regular expressions on arbitrary bytes.
+
+This module provides a nearly identical API to the one found in the
+top-level of this crate. There are two important differences:
+
+1. Matching is done on `&[u8]` instead of `&str`. Additionally, `Vec<u8>`
+is used where `String` would have been used.
+2. Unicode support can be disabled even when disabling it would result in
+matching invalid UTF-8 bytes.
+
+# Example: match null terminated string
+
+This shows how to find all null-terminated strings in a slice of bytes:
+
+```rust
+# use regex::bytes::Regex;
+let re = Regex::new(r"(?-u)(?P<cstr>[^\x00]+)\x00").unwrap();
+let text = b"foo\x00bar\x00baz\x00";
+
+// Extract all of the strings without the null terminator from each match.
+// The unwrap is OK here since a match requires the `cstr` capture to match.
+let cstrs: Vec<&[u8]> =
+    re.captures_iter(text)
+      .map(|c| c.name("cstr").unwrap().as_bytes())
+      .collect();
+assert_eq!(vec![&b"foo"[..], &b"bar"[..], &b"baz"[..]], cstrs);
+```
+
+# Example: selectively enable Unicode support
+
+This shows how to match an arbitrary byte pattern followed by a UTF-8 encoded
+string (e.g., to extract a title from a Matroska file):
+
+```rust
+# use std::str;
+# use regex::bytes::Regex;
+let re = Regex::new(
+    r"(?-u)\x7b\xa9(?:[\x80-\xfe]|[\x40-\xff].)(?u:(.*))"
+).unwrap();
+let text = b"\x12\xd0\x3b\x5f\x7b\xa9\x85\xe2\x98\x83\x80\x98\x54\x76\x68\x65";
+let caps = re.captures(text).unwrap();
+
+// Notice that despite the `.*` at the end, it will only match valid UTF-8
+// because Unicode mode was enabled with the `u` flag. Without the `u` flag,
+// the `.*` would match the rest of the bytes.
+let mat = caps.get(1).unwrap();
+assert_eq!((7, 10), (mat.start(), mat.end()));
+
+// If there was a match, Unicode mode guarantees that `title` is valid UTF-8.
+let title = str::from_utf8(&caps[1]).unwrap();
+assert_eq!("☃", title);
+```
+
+In general, if the Unicode flag is enabled in a capture group and that capture
+is part of the overall match, then the capture is *guaranteed* to be valid
+UTF-8.
+
+# Syntax
+
+The supported syntax is pretty much the same as the syntax for Unicode
+regular expressions with a few changes that make sense for matching arbitrary
+bytes:
+
+1. The `u` flag can be disabled even when disabling it might cause the regex to
+match invalid UTF-8. When the `u` flag is disabled, the regex is said to be in
+"ASCII compatible" mode.
+2. In ASCII compatible mode, neither Unicode scalar values nor Unicode
+character classes are allowed.
+3. In ASCII compatible mode, Perl character classes (`\w`, `\d` and `\s`)
+revert to their typical ASCII definition. `\w` maps to `[[:word:]]`, `\d` maps
+to `[[:digit:]]` and `\s` maps to `[[:space:]]`.
+4. In ASCII compatible mode, word boundaries use the ASCII compatible `\w` to
+determine whether a byte is a word byte or not.
+5. Hexadecimal notation can be used to specify arbitrary bytes instead of
+Unicode codepoints. For example, in ASCII compatible mode, `\xFF` matches the
+literal byte `\xFF`, while in Unicode mode, `\xFF` is a Unicode codepoint that
+matches its UTF-8 encoding of `\xC3\xBF`. Similarly for octal notation when
+enabled.
+6. In ASCII compatible mode, `.` matches any *byte* except for `\n`. When the
+`s` flag is additionally enabled, `.` matches any byte.
+
+# Performance
+
+In general, one should expect performance on `&[u8]` to be roughly similar to
+performance on `&str`.
+*/
+#[cfg(feature = "std")]
+pub mod bytes {
+    pub use re_builder::bytes::*;
+    pub use re_builder::set_bytes::*;
+    pub use re_bytes::*;
+    pub use re_set::bytes::*;
+}
+
+mod backtrack;
+mod compile;
+#[cfg(feature = "perf-dfa")]
+mod dfa;
+mod error;
+mod exec;
+mod expand;
+mod find_byte;
+#[cfg(feature = "perf-literal")]
+mod freqs;
+mod input;
+mod literal;
+#[cfg(feature = "pattern")]
+mod pattern;
+mod pikevm;
+mod pool;
+mod prog;
+mod re_builder;
+mod re_bytes;
+mod re_set;
+mod re_trait;
+mod re_unicode;
+mod sparse;
+mod utf8;
+
+/// The `internal` module exists to support suspicious activity, such as
+/// testing different matching engines and supporting the `regex-debug` CLI
+/// utility.
+#[doc(hidden)]
+#[cfg(feature = "std")]
+pub mod internal {
+    pub use compile::Compiler;
+    pub use exec::{Exec, ExecBuilder};
+    pub use input::{Char, CharInput, Input, InputAt};
+    pub use literal::LiteralSearcher;
+    pub use prog::{EmptyLook, Inst, InstRanges, Program};
+}
diff --git a/vendor/regex-1.4.6/src/literal/imp.rs b/vendor/regex-1.4.6/src/literal/imp.rs
new file mode 100644 (file)
index 0000000..e4d04ed
--- /dev/null
@@ -0,0 +1,1122 @@
+use std::cmp;
+use std::mem;
+
+use aho_corasick::{self, packed, AhoCorasick, AhoCorasickBuilder};
+use memchr::{memchr, memchr2, memchr3};
+use syntax::hir::literal::{Literal, Literals};
+
+use freqs::BYTE_FREQUENCIES;
+
+/// A prefix extracted from a compiled regular expression.
+///
+/// A regex prefix is a set of literal strings that *must* be matched at the
+/// beginning of a regex in order for the entire regex to match. Similarly
+/// for a regex suffix.
+#[derive(Clone, Debug)]
+pub struct LiteralSearcher {
+    complete: bool,
+    lcp: FreqyPacked,
+    lcs: FreqyPacked,
+    matcher: Matcher,
+}
+
+#[derive(Clone, Debug)]
+enum Matcher {
+    /// No literals. (Never advances through the input.)
+    Empty,
+    /// A set of four or more single byte literals.
+    Bytes(SingleByteSet),
+    /// A single substring, find using memchr and frequency analysis.
+    FreqyPacked(FreqyPacked),
+    /// A single substring, find using Boyer-Moore.
+    BoyerMoore(BoyerMooreSearch),
+    /// An Aho-Corasick automaton.
+    AC { ac: AhoCorasick<u32>, lits: Vec<Literal> },
+    /// A packed multiple substring searcher, using SIMD.
+    ///
+    /// Note that Aho-Corasick will actually use this packed searcher
+    /// internally automatically, however, there is some overhead associated
+    /// with going through the Aho-Corasick machinery. So using the packed
+    /// searcher directly results in some gains.
+    Packed { s: packed::Searcher, lits: Vec<Literal> },
+}
+
+impl LiteralSearcher {
+    /// Returns a matcher that never matches and never advances the input.
+    pub fn empty() -> Self {
+        Self::new(Literals::empty(), Matcher::Empty)
+    }
+
+    /// Returns a matcher for literal prefixes from the given set.
+    pub fn prefixes(lits: Literals) -> Self {
+        let matcher = Matcher::prefixes(&lits);
+        Self::new(lits, matcher)
+    }
+
+    /// Returns a matcher for literal suffixes from the given set.
+    pub fn suffixes(lits: Literals) -> Self {
+        let matcher = Matcher::suffixes(&lits);
+        Self::new(lits, matcher)
+    }
+
+    fn new(lits: Literals, matcher: Matcher) -> Self {
+        let complete = lits.all_complete();
+        LiteralSearcher {
+            complete: complete,
+            lcp: FreqyPacked::new(lits.longest_common_prefix().to_vec()),
+            lcs: FreqyPacked::new(lits.longest_common_suffix().to_vec()),
+            matcher: matcher,
+        }
+    }
+
+    /// Returns true if all matches comprise the entire regular expression.
+    ///
+    /// This does not necessarily mean that a literal match implies a match
+    /// of the regular expression. For example, the regular expression `^a`
+    /// is comprised of a single complete literal `a`, but the regular
+    /// expression demands that it only match at the beginning of a string.
+    pub fn complete(&self) -> bool {
+        self.complete && !self.is_empty()
+    }
+
+    /// Find the position of a literal in `haystack` if it exists.
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    pub fn find(&self, haystack: &[u8]) -> Option<(usize, usize)> {
+        use self::Matcher::*;
+        match self.matcher {
+            Empty => Some((0, 0)),
+            Bytes(ref sset) => sset.find(haystack).map(|i| (i, i + 1)),
+            FreqyPacked(ref s) => s.find(haystack).map(|i| (i, i + s.len())),
+            BoyerMoore(ref s) => s.find(haystack).map(|i| (i, i + s.len())),
+            AC { ref ac, .. } => {
+                ac.find(haystack).map(|m| (m.start(), m.end()))
+            }
+            Packed { ref s, .. } => {
+                s.find(haystack).map(|m| (m.start(), m.end()))
+            }
+        }
+    }
+
+    /// Like find, except matches must start at index `0`.
+    pub fn find_start(&self, haystack: &[u8]) -> Option<(usize, usize)> {
+        for lit in self.iter() {
+            if lit.len() > haystack.len() {
+                continue;
+            }
+            if lit == &haystack[0..lit.len()] {
+                return Some((0, lit.len()));
+            }
+        }
+        None
+    }
+
+    /// Like find, except matches must end at index `haystack.len()`.
+    pub fn find_end(&self, haystack: &[u8]) -> Option<(usize, usize)> {
+        for lit in self.iter() {
+            if lit.len() > haystack.len() {
+                continue;
+            }
+            if lit == &haystack[haystack.len() - lit.len()..] {
+                return Some((haystack.len() - lit.len(), haystack.len()));
+            }
+        }
+        None
+    }
+
+    /// Returns an iterator over all literals to be matched.
+    pub fn iter(&self) -> LiteralIter {
+        match self.matcher {
+            Matcher::Empty => LiteralIter::Empty,
+            Matcher::Bytes(ref sset) => LiteralIter::Bytes(&sset.dense),
+            Matcher::FreqyPacked(ref s) => LiteralIter::Single(&s.pat),
+            Matcher::BoyerMoore(ref s) => LiteralIter::Single(&s.pattern),
+            Matcher::AC { ref lits, .. } => LiteralIter::AC(lits),
+            Matcher::Packed { ref lits, .. } => LiteralIter::Packed(lits),
+        }
+    }
+
+    /// Returns a matcher for the longest common prefix of this matcher.
+    pub fn lcp(&self) -> &FreqyPacked {
+        &self.lcp
+    }
+
+    /// Returns a matcher for the longest common suffix of this matcher.
+    pub fn lcs(&self) -> &FreqyPacked {
+        &self.lcs
+    }
+
+    /// Returns true iff this prefix is empty.
+    pub fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    /// Returns the number of prefixes in this machine.
+    pub fn len(&self) -> usize {
+        use self::Matcher::*;
+        match self.matcher {
+            Empty => 0,
+            Bytes(ref sset) => sset.dense.len(),
+            FreqyPacked(_) => 1,
+            BoyerMoore(_) => 1,
+            AC { ref ac, .. } => ac.pattern_count(),
+            Packed { ref lits, .. } => lits.len(),
+        }
+    }
+
+    /// Return the approximate heap usage of literals in bytes.
+    pub fn approximate_size(&self) -> usize {
+        use self::Matcher::*;
+        match self.matcher {
+            Empty => 0,
+            Bytes(ref sset) => sset.approximate_size(),
+            FreqyPacked(ref single) => single.approximate_size(),
+            BoyerMoore(ref single) => single.approximate_size(),
+            AC { ref ac, .. } => ac.heap_bytes(),
+            Packed { ref s, .. } => s.heap_bytes(),
+        }
+    }
+}
+
+impl Matcher {
+    fn prefixes(lits: &Literals) -> Self {
+        let sset = SingleByteSet::prefixes(lits);
+        Matcher::new(lits, sset)
+    }
+
+    fn suffixes(lits: &Literals) -> Self {
+        let sset = SingleByteSet::suffixes(lits);
+        Matcher::new(lits, sset)
+    }
+
+    fn new(lits: &Literals, sset: SingleByteSet) -> Self {
+        if lits.literals().is_empty() {
+            return Matcher::Empty;
+        }
+        if sset.dense.len() >= 26 {
+            // Avoid trying to match a large number of single bytes.
+            // This is *very* sensitive to a frequency analysis comparison
+            // between the bytes in sset and the composition of the haystack.
+            // No matter the size of sset, if its members all are rare in the
+            // haystack, then it'd be worth using it. How to tune this... IDK.
+            // ---AG
+            return Matcher::Empty;
+        }
+        if sset.complete {
+            return Matcher::Bytes(sset);
+        }
+        if lits.literals().len() == 1 {
+            let lit = lits.literals()[0].to_vec();
+            if BoyerMooreSearch::should_use(lit.as_slice()) {
+                return Matcher::BoyerMoore(BoyerMooreSearch::new(lit));
+            } else {
+                return Matcher::FreqyPacked(FreqyPacked::new(lit));
+            }
+        }
+
+        let pats = lits.literals().to_owned();
+        let is_aho_corasick_fast = sset.dense.len() <= 1 && sset.all_ascii;
+        if lits.literals().len() <= 100 && !is_aho_corasick_fast {
+            let mut builder = packed::Config::new()
+                .match_kind(packed::MatchKind::LeftmostFirst)
+                .builder();
+            if let Some(s) = builder.extend(&pats).build() {
+                return Matcher::Packed { s, lits: pats };
+            }
+        }
+        let ac = AhoCorasickBuilder::new()
+            .match_kind(aho_corasick::MatchKind::LeftmostFirst)
+            .dfa(true)
+            .build_with_size::<u32, _, _>(&pats)
+            .unwrap();
+        Matcher::AC { ac, lits: pats }
+    }
+}
+
+#[derive(Debug)]
+pub enum LiteralIter<'a> {
+    Empty,
+    Bytes(&'a [u8]),
+    Single(&'a [u8]),
+    AC(&'a [Literal]),
+    Packed(&'a [Literal]),
+}
+
+impl<'a> Iterator for LiteralIter<'a> {
+    type Item = &'a [u8];
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match *self {
+            LiteralIter::Empty => None,
+            LiteralIter::Bytes(ref mut many) => {
+                if many.is_empty() {
+                    None
+                } else {
+                    let next = &many[0..1];
+                    *many = &many[1..];
+                    Some(next)
+                }
+            }
+            LiteralIter::Single(ref mut one) => {
+                if one.is_empty() {
+                    None
+                } else {
+                    let next = &one[..];
+                    *one = &[];
+                    Some(next)
+                }
+            }
+            LiteralIter::AC(ref mut lits) => {
+                if lits.is_empty() {
+                    None
+                } else {
+                    let next = &lits[0];
+                    *lits = &lits[1..];
+                    Some(&**next)
+                }
+            }
+            LiteralIter::Packed(ref mut lits) => {
+                if lits.is_empty() {
+                    None
+                } else {
+                    let next = &lits[0];
+                    *lits = &lits[1..];
+                    Some(&**next)
+                }
+            }
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+struct SingleByteSet {
+    sparse: Vec<bool>,
+    dense: Vec<u8>,
+    complete: bool,
+    all_ascii: bool,
+}
+
+impl SingleByteSet {
+    fn new() -> SingleByteSet {
+        SingleByteSet {
+            sparse: vec![false; 256],
+            dense: vec![],
+            complete: true,
+            all_ascii: true,
+        }
+    }
+
+    fn prefixes(lits: &Literals) -> SingleByteSet {
+        let mut sset = SingleByteSet::new();
+        for lit in lits.literals() {
+            sset.complete = sset.complete && lit.len() == 1;
+            if let Some(&b) = lit.get(0) {
+                if !sset.sparse[b as usize] {
+                    if b > 0x7F {
+                        sset.all_ascii = false;
+                    }
+                    sset.dense.push(b);
+                    sset.sparse[b as usize] = true;
+                }
+            }
+        }
+        sset
+    }
+
+    fn suffixes(lits: &Literals) -> SingleByteSet {
+        let mut sset = SingleByteSet::new();
+        for lit in lits.literals() {
+            sset.complete = sset.complete && lit.len() == 1;
+            if let Some(&b) = lit.get(lit.len().checked_sub(1).unwrap()) {
+                if !sset.sparse[b as usize] {
+                    if b > 0x7F {
+                        sset.all_ascii = false;
+                    }
+                    sset.dense.push(b);
+                    sset.sparse[b as usize] = true;
+                }
+            }
+        }
+        sset
+    }
+
+    /// Faster find that special cases certain sizes to use memchr.
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn find(&self, text: &[u8]) -> Option<usize> {
+        match self.dense.len() {
+            0 => None,
+            1 => memchr(self.dense[0], text),
+            2 => memchr2(self.dense[0], self.dense[1], text),
+            3 => memchr3(self.dense[0], self.dense[1], self.dense[2], text),
+            _ => self._find(text),
+        }
+    }
+
+    /// Generic find that works on any sized set.
+    fn _find(&self, haystack: &[u8]) -> Option<usize> {
+        for (i, &b) in haystack.iter().enumerate() {
+            if self.sparse[b as usize] {
+                return Some(i);
+            }
+        }
+        None
+    }
+
+    fn approximate_size(&self) -> usize {
+        (self.dense.len() * mem::size_of::<u8>())
+            + (self.sparse.len() * mem::size_of::<bool>())
+    }
+}
+
+/// Provides an implementation of fast subtring search using frequency
+/// analysis.
+///
+/// memchr is so fast that we do everything we can to keep the loop in memchr
+/// for as long as possible. The easiest way to do this is to intelligently
+/// pick the byte to send to memchr. The best byte is the byte that occurs
+/// least frequently in the haystack. Since doing frequency analysis on the
+/// haystack is far too expensive, we compute a set of fixed frequencies up
+/// front and hard code them in src/freqs.rs. Frequency analysis is done via
+/// scripts/frequencies.py.
+#[derive(Clone, Debug)]
+pub struct FreqyPacked {
+    /// The pattern.
+    pat: Vec<u8>,
+    /// The number of Unicode characters in the pattern. This is useful for
+    /// determining the effective length of a pattern when deciding which
+    /// optimizations to perform. A trailing incomplete UTF-8 sequence counts
+    /// as one character.
+    char_len: usize,
+    /// The rarest byte in the pattern, according to pre-computed frequency
+    /// analysis.
+    rare1: u8,
+    /// The offset of the rarest byte in `pat`.
+    rare1i: usize,
+    /// The second rarest byte in the pattern, according to pre-computed
+    /// frequency analysis. (This may be equivalent to the rarest byte.)
+    ///
+    /// The second rarest byte is used as a type of guard for quickly detecting
+    /// a mismatch after memchr locates an instance of the rarest byte. This
+    /// is a hedge against pathological cases where the pre-computed frequency
+    /// analysis may be off. (But of course, does not prevent *all*
+    /// pathological cases.)
+    rare2: u8,
+    /// The offset of the second rarest byte in `pat`.
+    rare2i: usize,
+}
+
+impl FreqyPacked {
+    fn new(pat: Vec<u8>) -> FreqyPacked {
+        if pat.is_empty() {
+            return FreqyPacked::empty();
+        }
+
+        // Find the rarest two bytes. Try to make them distinct (but it's not
+        // required).
+        let mut rare1 = pat[0];
+        let mut rare2 = pat[0];
+        for b in pat[1..].iter().cloned() {
+            if freq_rank(b) < freq_rank(rare1) {
+                rare1 = b;
+            }
+        }
+        for &b in &pat {
+            if rare1 == rare2 {
+                rare2 = b
+            } else if b != rare1 && freq_rank(b) < freq_rank(rare2) {
+                rare2 = b;
+            }
+        }
+
+        // And find the offsets of their last occurrences.
+        let rare1i = pat.iter().rposition(|&b| b == rare1).unwrap();
+        let rare2i = pat.iter().rposition(|&b| b == rare2).unwrap();
+
+        let char_len = char_len_lossy(&pat);
+        FreqyPacked {
+            pat: pat,
+            char_len: char_len,
+            rare1: rare1,
+            rare1i: rare1i,
+            rare2: rare2,
+            rare2i: rare2i,
+        }
+    }
+
+    fn empty() -> FreqyPacked {
+        FreqyPacked {
+            pat: vec![],
+            char_len: 0,
+            rare1: 0,
+            rare1i: 0,
+            rare2: 0,
+            rare2i: 0,
+        }
+    }
+
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    pub fn find(&self, haystack: &[u8]) -> Option<usize> {
+        let pat = &*self.pat;
+        if haystack.len() < pat.len() || pat.is_empty() {
+            return None;
+        }
+        let mut i = self.rare1i;
+        while i < haystack.len() {
+            i += match memchr(self.rare1, &haystack[i..]) {
+                None => return None,
+                Some(i) => i,
+            };
+            let start = i - self.rare1i;
+            let end = start + pat.len();
+            if end > haystack.len() {
+                return None;
+            }
+            let aligned = &haystack[start..end];
+            if aligned[self.rare2i] == self.rare2 && aligned == &*self.pat {
+                return Some(start);
+            }
+            i += 1;
+        }
+        None
+    }
+
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    pub fn is_suffix(&self, text: &[u8]) -> bool {
+        if text.len() < self.len() {
+            return false;
+        }
+        text[text.len() - self.len()..] == *self.pat
+    }
+
+    pub fn len(&self) -> usize {
+        self.pat.len()
+    }
+
+    pub fn char_len(&self) -> usize {
+        self.char_len
+    }
+
+    fn approximate_size(&self) -> usize {
+        self.pat.len() * mem::size_of::<u8>()
+    }
+}
+
+fn char_len_lossy(bytes: &[u8]) -> usize {
+    String::from_utf8_lossy(bytes).chars().count()
+}
+
+/// An implementation of Tuned Boyer-Moore as laid out by
+/// Andrew Hume and Daniel Sunday in "Fast String Searching".
+/// O(n) in the size of the input.
+///
+/// Fast string searching algorithms come in many variations,
+/// but they can generally be described in terms of three main
+/// components.
+///
+/// The skip loop is where the string searcher wants to spend
+/// as much time as possible. Exactly which character in the
+/// pattern the skip loop examines varies from algorithm to
+/// algorithm, but in the simplest case this loop repeated
+/// looks at the last character in the pattern and jumps
+/// forward in the input if it is not in the pattern.
+/// Robert Boyer and J Moore called this the "fast" loop in
+/// their original paper.
+///
+/// The match loop is responsible for actually examining the
+/// whole potentially matching substring. In order to fail
+/// faster, the match loop sometimes has a guard test attached.
+/// The guard test uses frequency analysis of the different
+/// characters in the pattern to choose the least frequency
+/// occurring character and use it to find match failures
+/// as quickly as possible.
+///
+/// The shift rule governs how the algorithm will shuffle its
+/// test window in the event of a failure during the match loop.
+/// Certain shift rules allow the worst-case run time of the
+/// algorithm to be shown to be O(n) in the size of the input
+/// rather than O(nm) in the size of the input and the size
+/// of the pattern (as naive Boyer-Moore is).
+///
+/// "Fast String Searching", in addition to presenting a tuned
+/// algorithm, provides a comprehensive taxonomy of the many
+/// different flavors of string searchers. Under that taxonomy
+/// TBM, the algorithm implemented here, uses an unrolled fast
+/// skip loop with memchr fallback, a forward match loop with guard,
+/// and the mini Sunday's delta shift rule. To unpack that you'll have to
+/// read the paper.
+#[derive(Clone, Debug)]
+pub struct BoyerMooreSearch {
+    /// The pattern we are going to look for in the haystack.
+    pattern: Vec<u8>,
+
+    /// The skip table for the skip loop.
+    ///
+    /// Maps the character at the end of the input
+    /// to a shift.
+    skip_table: Vec<usize>,
+
+    /// The guard character (least frequently occurring char).
+    guard: u8,
+    /// The reverse-index of the guard character in the pattern.
+    guard_reverse_idx: usize,
+
+    /// Daniel Sunday's mini generalized delta2 shift table.
+    ///
+    /// We use a skip loop, so we only have to provide a shift
+    /// for the skip char (last char). This is why it is a mini
+    /// shift rule.
+    md2_shift: usize,
+}
+
+impl BoyerMooreSearch {
+    /// Create a new string searcher, performing whatever
+    /// compilation steps are required.
+    fn new(pattern: Vec<u8>) -> Self {
+        debug_assert!(!pattern.is_empty());
+
+        let (g, gi) = Self::select_guard(pattern.as_slice());
+        let skip_table = Self::compile_skip_table(pattern.as_slice());
+        let md2_shift = Self::compile_md2_shift(pattern.as_slice());
+        BoyerMooreSearch {
+            pattern: pattern,
+            skip_table: skip_table,
+            guard: g,
+            guard_reverse_idx: gi,
+            md2_shift: md2_shift,
+        }
+    }
+
+    /// Find the pattern in `haystack`, returning the offset
+    /// of the start of the first occurrence of the pattern
+    /// in `haystack`.
+    #[inline]
+    fn find(&self, haystack: &[u8]) -> Option<usize> {
+        if haystack.len() < self.pattern.len() {
+            return None;
+        }
+
+        let mut window_end = self.pattern.len() - 1;
+
+        // Inspired by the grep source. It is a way
+        // to do correct loop unrolling without having to place
+        // a crashpad of terminating charicters at the end in
+        // the way described in the Fast String Searching paper.
+        const NUM_UNROLL: usize = 10;
+        // 1 for the initial position, and 1 for the md2 shift
+        let short_circut = (NUM_UNROLL + 2) * self.pattern.len();
+
+        if haystack.len() > short_circut {
+            // just 1 for the md2 shift
+            let backstop =
+                haystack.len() - ((NUM_UNROLL + 1) * self.pattern.len());
+            loop {
+                window_end =
+                    match self.skip_loop(haystack, window_end, backstop) {
+                        Some(i) => i,
+                        None => return None,
+                    };
+                if window_end >= backstop {
+                    break;
+                }
+
+                if self.check_match(haystack, window_end) {
+                    return Some(window_end - (self.pattern.len() - 1));
+                } else {
+                    let skip = self.skip_table[haystack[window_end] as usize];
+                    window_end +=
+                        if skip == 0 { self.md2_shift } else { skip };
+                    continue;
+                }
+            }
+        }
+
+        // now process the input after the backstop
+        while window_end < haystack.len() {
+            let mut skip = self.skip_table[haystack[window_end] as usize];
+            if skip == 0 {
+                if self.check_match(haystack, window_end) {
+                    return Some(window_end - (self.pattern.len() - 1));
+                } else {
+                    skip = self.md2_shift;
+                }
+            }
+            window_end += skip;
+        }
+
+        None
+    }
+
+    fn len(&self) -> usize {
+        return self.pattern.len();
+    }
+
+    /// The key heuristic behind which the BoyerMooreSearch lives.
+    ///
+    /// See `rust-lang/regex/issues/408`.
+    ///
+    /// Tuned Boyer-Moore is actually pretty slow! It turns out a handrolled
+    /// platform-specific memchr routine with a bit of frequency
+    /// analysis sprinkled on top actually wins most of the time.
+    /// However, there are a few cases where Tuned Boyer-Moore still
+    /// wins.
+    ///
+    /// If the haystack is random, frequency analysis doesn't help us,
+    /// so Boyer-Moore will win for sufficiently large needles.
+    /// Unfortunately, there is no obvious way to determine this
+    /// ahead of time.
+    ///
+    /// If the pattern itself consists of very common characters,
+    /// frequency analysis won't get us anywhere. The most extreme
+    /// example of this is a pattern like `eeeeeeeeeeeeeeee`. Fortunately,
+    /// this case is wholly determined by the pattern, so we can actually
+    /// implement the heuristic.
+    ///
+    /// A third case is if the pattern is sufficiently long. The idea
+    /// here is that once the pattern gets long enough the Tuned
+    /// Boyer-Moore skip loop will start making strides long enough
+    /// to beat the asm deep magic that is memchr.
+    fn should_use(pattern: &[u8]) -> bool {
+        // The minimum pattern length required to use TBM.
+        const MIN_LEN: usize = 9;
+        // The minimum frequency rank (lower is rarer) that every byte in the
+        // pattern must have in order to use TBM. That is, if the pattern
+        // contains _any_ byte with a lower rank, then TBM won't be used.
+        const MIN_CUTOFF: usize = 150;
+        // The maximum frequency rank for any byte.
+        const MAX_CUTOFF: usize = 255;
+        // The scaling factor used to determine the actual cutoff frequency
+        // to use (keeping in mind that the minimum frequency rank is bounded
+        // by MIN_CUTOFF). This scaling factor is an attempt to make TBM more
+        // likely to be used as the pattern grows longer. That is, longer
+        // patterns permit somewhat less frequent bytes than shorter patterns,
+        // under the assumption that TBM gets better as the pattern gets
+        // longer.
+        const LEN_CUTOFF_PROPORTION: usize = 4;
+
+        let scaled_rank = pattern.len().wrapping_mul(LEN_CUTOFF_PROPORTION);
+        let cutoff = cmp::max(
+            MIN_CUTOFF,
+            MAX_CUTOFF - cmp::min(MAX_CUTOFF, scaled_rank),
+        );
+        // The pattern must be long enough to be worthwhile. e.g., memchr will
+        // be faster on `e` because it is short even though e is quite common.
+        pattern.len() > MIN_LEN
+            // all the bytes must be more common than the cutoff.
+            && pattern.iter().all(|c| freq_rank(*c) >= cutoff)
+    }
+
+    /// Check to see if there is a match at the given position
+    #[inline]
+    fn check_match(&self, haystack: &[u8], window_end: usize) -> bool {
+        // guard test
+        if haystack[window_end - self.guard_reverse_idx] != self.guard {
+            return false;
+        }
+
+        // match loop
+        let window_start = window_end - (self.pattern.len() - 1);
+        for i in 0..self.pattern.len() {
+            if self.pattern[i] != haystack[window_start + i] {
+                return false;
+            }
+        }
+
+        true
+    }
+
+    /// Skip forward according to the shift table.
+    ///
+    /// Returns the offset of the next occurrence
+    /// of the last char in the pattern, or the none
+    /// if it never reappears. If `skip_loop` hits the backstop
+    /// it will leave early.
+    #[inline]
+    fn skip_loop(
+        &self,
+        haystack: &[u8],
+        mut window_end: usize,
+        backstop: usize,
+    ) -> Option<usize> {
+        let window_end_snapshot = window_end;
+        let skip_of = |we: usize| -> usize {
+            // Unsafe might make this faster, but the benchmarks
+            // were hard to interpret.
+            self.skip_table[haystack[we] as usize]
+        };
+
+        loop {
+            let mut skip = skip_of(window_end);
+            window_end += skip;
+            skip = skip_of(window_end);
+            window_end += skip;
+            if skip != 0 {
+                skip = skip_of(window_end);
+                window_end += skip;
+                skip = skip_of(window_end);
+                window_end += skip;
+                skip = skip_of(window_end);
+                window_end += skip;
+                if skip != 0 {
+                    skip = skip_of(window_end);
+                    window_end += skip;
+                    skip = skip_of(window_end);
+                    window_end += skip;
+                    skip = skip_of(window_end);
+                    window_end += skip;
+                    if skip != 0 {
+                        skip = skip_of(window_end);
+                        window_end += skip;
+                        skip = skip_of(window_end);
+                        window_end += skip;
+
+                        // If ten iterations did not make at least 16 words
+                        // worth of progress, we just fall back on memchr.
+                        if window_end - window_end_snapshot
+                            > 16 * mem::size_of::<usize>()
+                        {
+                            // Returning a window_end >= backstop will
+                            // immediatly break us out of the inner loop in
+                            // `find`.
+                            if window_end >= backstop {
+                                return Some(window_end);
+                            }
+
+                            continue; // we made enough progress
+                        } else {
+                            // In case we are already there, and so that
+                            // we will catch the guard char.
+                            window_end = window_end
+                                .checked_sub(1 + self.guard_reverse_idx)
+                                .unwrap_or(0);
+
+                            match memchr(self.guard, &haystack[window_end..]) {
+                                None => return None,
+                                Some(g_idx) => {
+                                    return Some(
+                                        window_end
+                                            + g_idx
+                                            + self.guard_reverse_idx,
+                                    );
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            return Some(window_end);
+        }
+    }
+
+    /// Compute the ufast skip table.
+    fn compile_skip_table(pattern: &[u8]) -> Vec<usize> {
+        let mut tab = vec![pattern.len(); 256];
+
+        // For every char in the pattern, we write a skip
+        // that will line us up with the rightmost occurrence.
+        //
+        // N.B. the sentinel (0) is written by the last
+        // loop iteration.
+        for (i, c) in pattern.iter().enumerate() {
+            tab[*c as usize] = (pattern.len() - 1) - i;
+        }
+
+        tab
+    }
+
+    /// Select the guard character based off of the precomputed
+    /// frequency table.
+    fn select_guard(pattern: &[u8]) -> (u8, usize) {
+        let mut rarest = pattern[0];
+        let mut rarest_rev_idx = pattern.len() - 1;
+        for (i, c) in pattern.iter().enumerate() {
+            if freq_rank(*c) < freq_rank(rarest) {
+                rarest = *c;
+                rarest_rev_idx = (pattern.len() - 1) - i;
+            }
+        }
+
+        (rarest, rarest_rev_idx)
+    }
+
+    /// If there is another occurrence of the skip
+    /// char, shift to it, otherwise just shift to
+    /// the next window.
+    fn compile_md2_shift(pattern: &[u8]) -> usize {
+        let shiftc = *pattern.last().unwrap();
+
+        // For a pattern of length 1 we will never apply the
+        // shift rule, so we use a poison value on the principle
+        // that failing fast is a good thing.
+        if pattern.len() == 1 {
+            return 0xDEADBEAF;
+        }
+
+        let mut i = pattern.len() - 2;
+        while i > 0 {
+            if pattern[i] == shiftc {
+                return (pattern.len() - 1) - i;
+            }
+            i -= 1;
+        }
+
+        // The skip char never re-occurs in the pattern, so
+        // we can just shift the whole window length.
+        pattern.len() - 1
+    }
+
+    fn approximate_size(&self) -> usize {
+        (self.pattern.len() * mem::size_of::<u8>())
+            + (256 * mem::size_of::<usize>()) // skip table
+    }
+}
+
+fn freq_rank(b: u8) -> usize {
+    BYTE_FREQUENCIES[b as usize] as usize
+}
+
+#[cfg(test)]
+mod tests {
+    use super::{BoyerMooreSearch, FreqyPacked};
+
+    //
+    // Unit Tests
+    //
+
+    // The "hello, world" of string searching
+    #[test]
+    fn bm_find_subs() {
+        let searcher = BoyerMooreSearch::new(Vec::from(&b"pattern"[..]));
+        let haystack = b"I keep seeing patterns in this text";
+        assert_eq!(14, searcher.find(haystack).unwrap());
+    }
+
+    #[test]
+    fn bm_find_no_subs() {
+        let searcher = BoyerMooreSearch::new(Vec::from(&b"pattern"[..]));
+        let haystack = b"I keep seeing needles in this text";
+        assert_eq!(None, searcher.find(haystack));
+    }
+
+    //
+    // Regression Tests
+    //
+
+    #[test]
+    fn bm_skip_reset_bug() {
+        let haystack = vec![0, 0, 0, 0, 0, 1, 1, 0];
+        let needle = vec![0, 1, 1, 0];
+
+        let searcher = BoyerMooreSearch::new(needle);
+        let offset = searcher.find(haystack.as_slice()).unwrap();
+        assert_eq!(4, offset);
+    }
+
+    #[test]
+    fn bm_backstop_underflow_bug() {
+        let haystack = vec![0, 0];
+        let needle = vec![0, 0];
+
+        let searcher = BoyerMooreSearch::new(needle);
+        let offset = searcher.find(haystack.as_slice()).unwrap();
+        assert_eq!(0, offset);
+    }
+
+    #[test]
+    fn bm_naive_off_by_one_bug() {
+        let haystack = vec![91];
+        let needle = vec![91];
+
+        let naive_offset = naive_find(&needle, &haystack).unwrap();
+        assert_eq!(0, naive_offset);
+    }
+
+    #[test]
+    fn bm_memchr_fallback_indexing_bug() {
+        let mut haystack = vec![
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        ];
+        let needle = vec![1, 1, 1, 1, 32, 32, 87];
+        let needle_start = haystack.len();
+        haystack.extend(needle.clone());
+
+        let searcher = BoyerMooreSearch::new(needle);
+        assert_eq!(needle_start, searcher.find(haystack.as_slice()).unwrap());
+    }
+
+    #[test]
+    fn bm_backstop_boundary() {
+        let haystack = b"\
+// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+e_data.clone_created(entity_id, entity_to_add.entity_id);
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+"
+        .to_vec();
+        let needle = b"clone_created".to_vec();
+
+        let searcher = BoyerMooreSearch::new(needle);
+        let result = searcher.find(&haystack);
+        assert_eq!(Some(43), result);
+    }
+
+    #[test]
+    fn bm_win_gnu_indexing_bug() {
+        let haystack_raw = vec![
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        ];
+        let needle = vec![1, 1, 1, 1, 1, 1, 1];
+        let haystack = haystack_raw.as_slice();
+
+        BoyerMooreSearch::new(needle.clone()).find(haystack);
+    }
+
+    //
+    // QuickCheck Properties
+    //
+
+    use quickcheck::TestResult;
+
+    fn naive_find(needle: &[u8], haystack: &[u8]) -> Option<usize> {
+        assert!(needle.len() <= haystack.len());
+
+        for i in 0..(haystack.len() - (needle.len() - 1)) {
+            if haystack[i] == needle[0]
+                && &haystack[i..(i + needle.len())] == needle
+            {
+                return Some(i);
+            }
+        }
+
+        None
+    }
+
+    quickcheck! {
+        fn qc_bm_equals_nieve_find(pile1: Vec<u8>, pile2: Vec<u8>) -> TestResult {
+            if pile1.len() == 0 || pile2.len() == 0 {
+                return TestResult::discard();
+            }
+
+            let (needle, haystack) = if pile1.len() < pile2.len() {
+                (pile1, pile2.as_slice())
+            } else {
+                (pile2, pile1.as_slice())
+            };
+
+            let searcher = BoyerMooreSearch::new(needle.clone());
+            TestResult::from_bool(
+                searcher.find(haystack) == naive_find(&needle, haystack))
+        }
+
+        fn qc_bm_equals_single(pile1: Vec<u8>, pile2: Vec<u8>) -> TestResult {
+            if pile1.len() == 0 || pile2.len() == 0 {
+                return TestResult::discard();
+            }
+
+            let (needle, haystack) = if pile1.len() < pile2.len() {
+                (pile1, pile2.as_slice())
+            } else {
+                (pile2, pile1.as_slice())
+            };
+
+            let bm_searcher = BoyerMooreSearch::new(needle.clone());
+            let freqy_memchr = FreqyPacked::new(needle);
+            TestResult::from_bool(
+                bm_searcher.find(haystack) == freqy_memchr.find(haystack))
+        }
+
+        fn qc_bm_finds_trailing_needle(
+            haystack_pre: Vec<u8>,
+            needle: Vec<u8>
+        ) -> TestResult {
+            if needle.len() == 0 {
+                return TestResult::discard();
+            }
+
+            let mut haystack = haystack_pre.clone();
+            let searcher = BoyerMooreSearch::new(needle.clone());
+
+            if haystack.len() >= needle.len() &&
+                searcher.find(haystack.as_slice()).is_some() {
+                return TestResult::discard();
+            }
+
+            haystack.extend(needle.clone());
+
+            // What if the the tail of the haystack can start the
+            // needle?
+            let start = haystack_pre.len()
+                .checked_sub(needle.len())
+                .unwrap_or(0);
+            for i in 0..(needle.len() - 1) {
+                if searcher.find(&haystack[(i + start)..]).is_some() {
+                    return TestResult::discard();
+                }
+            }
+
+            TestResult::from_bool(
+                searcher.find(haystack.as_slice())
+                        .map(|x| x == haystack_pre.len())
+                        .unwrap_or(false))
+        }
+
+        // qc_equals_* is only testing the negative case as @burntsushi
+        // pointed out in https://github.com/rust-lang/regex/issues/446.
+        // This quickcheck prop represents an effort to force testing of
+        // the positive case. qc_bm_finds_first and qc_bm_finds_trailing_needle
+        // already check some of the positive cases, but they don't cover
+        // cases where the needle is in the middle of haystack. This prop
+        // fills that hole.
+        fn qc_bm_finds_subslice(
+            haystack: Vec<u8>,
+            needle_start: usize,
+            needle_length: usize
+        ) -> TestResult {
+            if haystack.len() == 0 {
+                return TestResult::discard();
+            }
+
+            let needle_start = needle_start % haystack.len();
+            let needle_length = needle_length % (haystack.len() - needle_start);
+
+            if needle_length == 0 {
+                return TestResult::discard();
+            }
+
+            let needle = &haystack[needle_start..(needle_start + needle_length)];
+
+            let bm_searcher = BoyerMooreSearch::new(needle.to_vec());
+
+            let start = naive_find(&needle, &haystack);
+            match start {
+                None => TestResult::from_bool(false),
+                Some(nf_start) =>
+                    TestResult::from_bool(
+                        nf_start <= needle_start
+                            && bm_searcher.find(&haystack) == start
+                    )
+            }
+        }
+
+        fn qc_bm_finds_first(needle: Vec<u8>) -> TestResult {
+            if needle.len() == 0 {
+                return TestResult::discard();
+            }
+
+            let mut haystack = needle.clone();
+            let searcher = BoyerMooreSearch::new(needle.clone());
+            haystack.extend(needle);
+
+            TestResult::from_bool(
+                searcher.find(haystack.as_slice())
+                        .map(|x| x == 0)
+                        .unwrap_or(false))
+        }
+    }
+}
diff --git a/vendor/regex-1.4.6/src/literal/mod.rs b/vendor/regex-1.4.6/src/literal/mod.rs
new file mode 100644 (file)
index 0000000..783c63b
--- /dev/null
@@ -0,0 +1,55 @@
+pub use self::imp::*;
+
+#[cfg(feature = "perf-literal")]
+mod imp;
+
+#[allow(missing_docs)]
+#[cfg(not(feature = "perf-literal"))]
+mod imp {
+    use syntax::hir::literal::Literals;
+
+    #[derive(Clone, Debug)]
+    pub struct LiteralSearcher(());
+
+    impl LiteralSearcher {
+        pub fn empty() -> Self {
+            LiteralSearcher(())
+        }
+
+        pub fn prefixes(_: Literals) -> Self {
+            LiteralSearcher(())
+        }
+
+        pub fn suffixes(_: Literals) -> Self {
+            LiteralSearcher(())
+        }
+
+        pub fn complete(&self) -> bool {
+            false
+        }
+
+        pub fn find(&self, _: &[u8]) -> Option<(usize, usize)> {
+            unreachable!()
+        }
+
+        pub fn find_start(&self, _: &[u8]) -> Option<(usize, usize)> {
+            unreachable!()
+        }
+
+        pub fn find_end(&self, _: &[u8]) -> Option<(usize, usize)> {
+            unreachable!()
+        }
+
+        pub fn is_empty(&self) -> bool {
+            true
+        }
+
+        pub fn len(&self) -> usize {
+            0
+        }
+
+        pub fn approximate_size(&self) -> usize {
+            0
+        }
+    }
+}
diff --git a/vendor/regex-1.4.6/src/pattern.rs b/vendor/regex-1.4.6/src/pattern.rs
new file mode 100644 (file)
index 0000000..e942667
--- /dev/null
@@ -0,0 +1,62 @@
+use std::str::pattern::{Pattern, SearchStep, Searcher};
+
+use re_unicode::{Matches, Regex};
+
+pub struct RegexSearcher<'r, 't> {
+    haystack: &'t str,
+    it: Matches<'r, 't>,
+    last_step_end: usize,
+    next_match: Option<(usize, usize)>,
+}
+
+impl<'r, 't> Pattern<'t> for &'r Regex {
+    type Searcher = RegexSearcher<'r, 't>;
+
+    fn into_searcher(self, haystack: &'t str) -> RegexSearcher<'r, 't> {
+        RegexSearcher {
+            haystack: haystack,
+            it: self.find_iter(haystack),
+            last_step_end: 0,
+            next_match: None,
+        }
+    }
+}
+
+unsafe impl<'r, 't> Searcher<'t> for RegexSearcher<'r, 't> {
+    #[inline]
+    fn haystack(&self) -> &'t str {
+        self.haystack
+    }
+
+    #[inline]
+    fn next(&mut self) -> SearchStep {
+        if let Some((s, e)) = self.next_match {
+            self.next_match = None;
+            self.last_step_end = e;
+            return SearchStep::Match(s, e);
+        }
+        match self.it.next() {
+            None => {
+                if self.last_step_end < self.haystack().len() {
+                    let last = self.last_step_end;
+                    self.last_step_end = self.haystack().len();
+                    SearchStep::Reject(last, self.haystack().len())
+                } else {
+                    SearchStep::Done
+                }
+            }
+            Some(m) => {
+                let (s, e) = (m.start(), m.end());
+                if s == self.last_step_end {
+                    self.last_step_end = e;
+                    SearchStep::Match(s, e)
+                } else {
+                    self.next_match = Some((s, e));
+                    let last = self.last_step_end;
+                    self.last_step_end = s;
+                    SearchStep::Reject(last, s)
+                }
+            }
+        }
+    }
+}
diff --git a/vendor/regex-1.4.6/src/pikevm.rs b/vendor/regex-1.4.6/src/pikevm.rs
new file mode 100644 (file)
index 0000000..299087d
--- /dev/null
@@ -0,0 +1,360 @@
+// This module implements the Pike VM. That is, it guarantees linear time
+// search of a regex on any text with memory use proportional to the size of
+// the regex.
+//
+// It is equal in power to the backtracking engine in this crate, except the
+// backtracking engine is typically faster on small regexes/texts at the
+// expense of a bigger memory footprint.
+//
+// It can do more than the DFA can (specifically, record capture locations
+// and execute Unicode word boundary assertions), but at a slower speed.
+// Specifically, the Pike VM executes a DFA implicitly by repeatedly expanding
+// epsilon transitions. That is, the Pike VM engine can be in multiple states
+// at once where as the DFA is only ever in one state at a time.
+//
+// Therefore, the Pike VM is generally treated as the fallback when the other
+// matching engines either aren't feasible to run or are insufficient.
+
+use std::mem;
+
+use exec::ProgramCache;
+use input::{Input, InputAt};
+use prog::{InstPtr, Program};
+use re_trait::Slot;
+use sparse::SparseSet;
+
+/// An NFA simulation matching engine.
+#[derive(Debug)]
+pub struct Fsm<'r, I> {
+    /// The sequence of opcodes (among other things) that is actually executed.
+    ///
+    /// The program may be byte oriented or Unicode codepoint oriented.
+    prog: &'r Program,
+    /// An explicit stack used for following epsilon transitions. (This is
+    /// borrowed from the cache.)
+    stack: &'r mut Vec<FollowEpsilon>,
+    /// The input to search.
+    input: I,
+}
+
+/// A cached allocation that can be reused on each execution.
+#[derive(Clone, Debug)]
+pub struct Cache {
+    /// A pair of ordered sets for tracking NFA states.
+    clist: Threads,
+    nlist: Threads,
+    /// An explicit stack used for following epsilon transitions.
+    stack: Vec<FollowEpsilon>,
+}
+
+/// An ordered set of NFA states and their captures.
+#[derive(Clone, Debug)]
+struct Threads {
+    /// An ordered set of opcodes (each opcode is an NFA state).
+    set: SparseSet,
+    /// Captures for every NFA state.
+    ///
+    /// It is stored in row-major order, where the columns are the capture
+    /// slots and the rows are the states.
+    caps: Vec<Slot>,
+    /// The number of capture slots stored per thread. (Every capture has
+    /// two slots.)
+    slots_per_thread: usize,
+}
+
+/// A representation of an explicit stack frame when following epsilon
+/// transitions. This is used to avoid recursion.
+#[derive(Clone, Debug)]
+enum FollowEpsilon {
+    /// Follow transitions at the given instruction pointer.
+    IP(InstPtr),
+    /// Restore the capture slot with the given position in the input.
+    Capture { slot: usize, pos: Slot },
+}
+
+impl Cache {
+    /// Create a new allocation used by the NFA machine to record execution
+    /// and captures.
+    pub fn new(_prog: &Program) -> Self {
+        Cache { clist: Threads::new(), nlist: Threads::new(), stack: vec![] }
+    }
+}
+
+impl<'r, I: Input> Fsm<'r, I> {
+    /// Execute the NFA matching engine.
+    ///
+    /// If there's a match, `exec` returns `true` and populates the given
+    /// captures accordingly.
+    pub fn exec(
+        prog: &'r Program,
+        cache: &ProgramCache,
+        matches: &mut [bool],
+        slots: &mut [Slot],
+        quit_after_match: bool,
+        input: I,
+        start: usize,
+        end: usize,
+    ) -> bool {
+        let mut cache = cache.borrow_mut();
+        let cache = &mut cache.pikevm;
+        cache.clist.resize(prog.len(), prog.captures.len());
+        cache.nlist.resize(prog.len(), prog.captures.len());
+        let at = input.at(start);
+        Fsm { prog: prog, stack: &mut cache.stack, input: input }.exec_(
+            &mut cache.clist,
+            &mut cache.nlist,
+            matches,
+            slots,
+            quit_after_match,
+            at,
+            end,
+        )
+    }
+
+    fn exec_(
+        &mut self,
+        mut clist: &mut Threads,
+        mut nlist: &mut Threads,
+        matches: &mut [bool],
+        slots: &mut [Slot],
+        quit_after_match: bool,
+        mut at: InputAt,
+        end: usize,
+    ) -> bool {
+        let mut matched = false;
+        let mut all_matched = false;
+        clist.set.clear();
+        nlist.set.clear();
+        'LOOP: loop {
+            if clist.set.is_empty() {
+                // Three ways to bail out when our current set of threads is
+                // empty.
+                //
+                // 1. We have a match---so we're done exploring any possible
+                //    alternatives. Time to quit. (We can't do this if we're
+                //    looking for matches for multiple regexes, unless we know
+                //    they all matched.)
+                //
+                // 2. If the expression starts with a '^' we can terminate as
+                //    soon as the last thread dies.
+                if (matched && matches.len() <= 1)
+                    || all_matched
+                    || (!at.is_start() && self.prog.is_anchored_start)
+                {
+                    break;
+                }
+
+                // 3. If there's a literal prefix for the program, try to
+                //    jump ahead quickly. If it can't be found, then we can
+                //    bail out early.
+                if !self.prog.prefixes.is_empty() {
+                    at = match self.input.prefix_at(&self.prog.prefixes, at) {
+                        None => break,
+                        Some(at) => at,
+                    };
+                }
+            }
+
+            // This simulates a preceding '.*?' for every regex by adding
+            // a state starting at the current position in the input for the
+            // beginning of the program only if we don't already have a match.
+            if clist.set.is_empty()
+                || (!self.prog.is_anchored_start && !all_matched)
+            {
+                self.add(&mut clist, slots, 0, at);
+            }
+            // The previous call to "add" actually inspects the position just
+            // before the current character. For stepping through the machine,
+            // we can to look at the current character, so we advance the
+            // input.
+            let at_next = self.input.at(at.next_pos());
+            for i in 0..clist.set.len() {
+                let ip = clist.set[i];
+                if self.step(
+                    &mut nlist,
+                    matches,
+                    slots,
+                    clist.caps(ip),
+                    ip,
+                    at,
+                    at_next,
+                ) {
+                    matched = true;
+                    all_matched = all_matched || matches.iter().all(|&b| b);
+                    if quit_after_match {
+                        // If we only care if a match occurs (not its
+                        // position), then we can quit right now.
+                        break 'LOOP;
+                    }
+                    if self.prog.matches.len() == 1 {
+                        // We don't need to check the rest of the threads
+                        // in this set because we've matched something
+                        // ("leftmost-first"). However, we still need to check
+                        // threads in the next set to support things like
+                        // greedy matching.
+                        //
+                        // This is only true on normal regexes. For regex sets,
+                        // we need to mush on to observe other matches.
+                        break;
+                    }
+                }
+            }
+            if at.pos() >= end {
+                break;
+            }
+            at = at_next;
+            mem::swap(clist, nlist);
+            nlist.set.clear();
+        }
+        matched
+    }
+
+    /// Step through the input, one token (byte or codepoint) at a time.
+    ///
+    /// nlist is the set of states that will be processed on the next token
+    /// in the input.
+    ///
+    /// caps is the set of captures passed by the caller of the NFA. They are
+    /// written to only when a match state is visited.
+    ///
+    /// thread_caps is the set of captures set for the current NFA state, ip.
+    ///
+    /// at and at_next are the current and next positions in the input. at or
+    /// at_next may be EOF.
+    fn step(
+        &mut self,
+        nlist: &mut Threads,
+        matches: &mut [bool],
+        slots: &mut [Slot],
+        thread_caps: &mut [Option<usize>],
+        ip: usize,
+        at: InputAt,
+        at_next: InputAt,
+    ) -> bool {
+        use prog::Inst::*;
+        match self.prog[ip] {
+            Match(match_slot) => {
+                if match_slot < matches.len() {
+                    matches[match_slot] = true;
+                }
+                for (slot, val) in slots.iter_mut().zip(thread_caps.iter()) {
+                    *slot = *val;
+                }
+                true
+            }
+            Char(ref inst) => {
+                if inst.c == at.char() {
+                    self.add(nlist, thread_caps, inst.goto, at_next);
+                }
+                false
+            }
+            Ranges(ref inst) => {
+                if inst.matches(at.char()) {
+                    self.add(nlist, thread_caps, inst.goto, at_next);
+                }
+                false
+            }
+            Bytes(ref inst) => {
+                if let Some(b) = at.byte() {
+                    if inst.matches(b) {
+                        self.add(nlist, thread_caps, inst.goto, at_next);
+                    }
+                }
+                false
+            }
+            EmptyLook(_) | Save(_) | Split(_) => false,
+        }
+    }
+
+    /// Follows epsilon transitions and adds them for processing to nlist,
+    /// starting at and including ip.
+    fn add(
+        &mut self,
+        nlist: &mut Threads,
+        thread_caps: &mut [Option<usize>],
+        ip: usize,
+        at: InputAt,
+    ) {
+        self.stack.push(FollowEpsilon::IP(ip));
+        while let Some(frame) = self.stack.pop() {
+            match frame {
+                FollowEpsilon::IP(ip) => {
+                    self.add_step(nlist, thread_caps, ip, at);
+                }
+                FollowEpsilon::Capture { slot, pos } => {
+                    thread_caps[slot] = pos;
+                }
+            }
+        }
+    }
+
+    /// A helper function for add that avoids excessive pushing to the stack.
+    fn add_step(
+        &mut self,
+        nlist: &mut Threads,
+        thread_caps: &mut [Option<usize>],
+        mut ip: usize,
+        at: InputAt,
+    ) {
+        // Instead of pushing and popping to the stack, we mutate ip as we
+        // traverse the set of states. We only push to the stack when we
+        // absolutely need recursion (restoring captures or following a
+        // branch).
+        use prog::Inst::*;
+        loop {
+            // Don't visit states we've already added.
+            if nlist.set.contains(ip) {
+                return;
+            }
+            nlist.set.insert(ip);
+            match self.prog[ip] {
+                EmptyLook(ref inst) => {
+                    if self.input.is_empty_match(at, inst) {
+                        ip = inst.goto;
+                    }
+                }
+                Save(ref inst) => {
+                    if inst.slot < thread_caps.len() {
+                        self.stack.push(FollowEpsilon::Capture {
+                            slot: inst.slot,
+                            pos: thread_caps[inst.slot],
+                        });
+                        thread_caps[inst.slot] = Some(at.pos());
+                    }
+                    ip = inst.goto;
+                }
+                Split(ref inst) => {
+                    self.stack.push(FollowEpsilon::IP(inst.goto2));
+                    ip = inst.goto1;
+                }
+                Match(_) | Char(_) | Ranges(_) | Bytes(_) => {
+                    let t = &mut nlist.caps(ip);
+                    for (slot, val) in t.iter_mut().zip(thread_caps.iter()) {
+                        *slot = *val;
+                    }
+                    return;
+                }
+            }
+        }
+    }
+}
+
+impl Threads {
+    fn new() -> Self {
+        Threads { set: SparseSet::new(0), caps: vec![], slots_per_thread: 0 }
+    }
+
+    fn resize(&mut self, num_insts: usize, ncaps: usize) {
+        if num_insts == self.set.capacity() {
+            return;
+        }
+        self.slots_per_thread = ncaps * 2;
+        self.set = SparseSet::new(num_insts);
+        self.caps = vec![None; self.slots_per_thread * num_insts];
+    }
+
+    fn caps(&mut self, pc: usize) -> &mut [Option<usize>] {
+        let i = pc * self.slots_per_thread;
+        &mut self.caps[i..i + self.slots_per_thread]
+    }
+}
diff --git a/vendor/regex-1.4.6/src/pool.rs b/vendor/regex-1.4.6/src/pool.rs
new file mode 100644 (file)
index 0000000..a506ee9
--- /dev/null
@@ -0,0 +1,333 @@
+// This module provides a relatively simple thread-safe pool of reusable
+// objects. For the most part, it's implemented by a stack represented by a
+// Mutex<Vec<T>>. It has one small trick: because unlocking a mutex is somewhat
+// costly, in the case where a pool is accessed by the first thread that tried
+// to get a value, we bypass the mutex. Here are some benchmarks showing the
+// difference.
+//
+// 1) misc::anchored_literal_long_non_match    21 (18571 MB/s)
+// 2) misc::anchored_literal_long_non_match   107 (3644 MB/s)
+// 3) misc::anchored_literal_long_non_match    45 (8666 MB/s)
+// 4) misc::anchored_literal_long_non_match    19 (20526 MB/s)
+//
+// (1) represents our baseline: the master branch at the time of writing when
+// using the 'thread_local' crate to implement the pool below.
+//
+// (2) represents a naive pool implemented completely via Mutex<Vec<T>>. There
+// is no special trick for bypassing the mutex.
+//
+// (3) is the same as (2), except it uses Mutex<Vec<Box<T>>>. It is twice as
+// fast because a Box<T> is much smaller than the T we use with a Pool in this
+// crate. So pushing and popping a Box<T> from a Vec is quite a bit faster
+// than for T.
+//
+// (4) is the same as (3), but with the trick for bypassing the mutex in the
+// case of the first-to-get thread.
+//
+// Why move off of thread_local? Even though (4) is a hair faster than (1)
+// above, this was not the main goal. The main goal was to move off of
+// thread_local and find a way to *simply* re-capture some of its speed for
+// regex's specific case. So again, why move off of it? The *primary* reason is
+// because of memory leaks. See https://github.com/rust-lang/regex/issues/362
+// for example. (Why do I want it to be simple? Well, I suppose what I mean is,
+// "use as much safe code as possible to minimize risk and be as sure as I can
+// be that it is correct.")
+//
+// My guess is that the thread_local design is probably not appropriate for
+// regex since its memory usage scales to the number of active threads that
+// have used a regex, where as the pool below scales to the number of threads
+// that simultaneously use a regex. While neither case permits contraction,
+// since we own the pool data structure below, we can add contraction if a
+// clear use case pops up in the wild. More pressingly though, it seems that
+// there are at least some use case patterns where one might have many threads
+// sitting around that might have used a regex at one point. While thread_local
+// does try to reuse space previously used by a thread that has since stopped,
+// its maximal memory usage still scales with the total number of active
+// threads. In contrast, the pool below scales with the total number of threads
+// *simultaneously* using the pool. The hope is that this uses less memory
+// overall. And if it doesn't, we can hopefully tune it somehow.
+//
+// It seems that these sort of conditions happen frequently
+// in FFI inside of other more "managed" languages. This was
+// mentioned in the issue linked above, and also mentioned here:
+// https://github.com/BurntSushi/rure-go/issues/3. And in particular, users
+// confirm that disabling the use of thread_local resolves the leak.
+//
+// There were other weaker reasons for moving off of thread_local as well.
+// Namely, at the time, I was looking to reduce dependencies. And for something
+// like regex, maintenance can be simpler when we own the full dependency tree.
+
+use std::panic::{RefUnwindSafe, UnwindSafe};
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::Mutex;
+
+/// An atomic counter used to allocate thread IDs.
+static COUNTER: AtomicUsize = AtomicUsize::new(1);
+
+thread_local!(
+    /// A thread local used to assign an ID to a thread.
+    static THREAD_ID: usize = {
+        let next = COUNTER.fetch_add(1, Ordering::Relaxed);
+        // SAFETY: We cannot permit the reuse of thread IDs since reusing a
+        // thread ID might result in more than one thread "owning" a pool,
+        // and thus, permit accessing a mutable value from multiple threads
+        // simultaneously without synchronization. The intent of this panic is
+        // to be a sanity check. It is not expected that the thread ID space
+        // will actually be exhausted in practice.
+        //
+        // This checks that the counter never wraps around, since atomic
+        // addition wraps around on overflow.
+        if next == 0 {
+            panic!("regex: thread ID allocation space exhausted");
+        }
+        next
+    };
+);
+
+/// The type of the function used to create values in a pool when the pool is
+/// empty and the caller requests one.
+type CreateFn<T> =
+    Box<dyn Fn() -> T + Send + Sync + UnwindSafe + RefUnwindSafe + 'static>;
+
+/// A simple thread safe pool for reusing values.
+///
+/// Getting a value out comes with a guard. When that guard is dropped, the
+/// value is automatically put back in the pool.
+///
+/// A Pool<T> impls Sync when T is Send (even if it's not Sync). This means
+/// that T can use interior mutability. This is possible because a pool is
+/// guaranteed to provide a value to exactly one thread at any time.
+///
+/// Currently, a pool never contracts in size. Its size is proportional to the
+/// number of simultaneous uses.
+pub struct Pool<T> {
+    /// A stack of T values to hand out. These are used when a Pool is
+    /// accessed by a thread that didn't create it.
+    stack: Mutex<Vec<Box<T>>>,
+    /// A function to create more T values when stack is empty and a caller
+    /// has requested a T.
+    create: CreateFn<T>,
+    /// The ID of the thread that owns this pool. The owner is the thread
+    /// that makes the first call to 'get'. When the owner calls 'get', it
+    /// gets 'owner_val' directly instead of returning a T from 'stack'.
+    /// See comments elsewhere for details, but this is intended to be an
+    /// optimization for the common case that makes getting a T faster.
+    ///
+    /// It is initialized to a value of zero (an impossible thread ID) as a
+    /// sentinel to indicate that it is unowned.
+    owner: AtomicUsize,
+    /// A value to return when the caller is in the same thread that created
+    /// the Pool.
+    owner_val: T,
+}
+
+// SAFETY: Since we want to use a Pool from multiple threads simultaneously
+// behind an Arc, we need for it to be Sync. In cases where T is sync, Pool<T>
+// would be Sync. However, since we use a Pool to store mutable scratch space,
+// we wind up using a T that has interior mutability and is thus itself not
+// Sync. So what we *really* want is for our Pool<T> to by Sync even when T is
+// not Sync (but is at least Send).
+//
+// The only non-sync aspect of a Pool is its 'owner_val' field, which is used
+// to implement faster access to a pool value in the common case of a pool
+// being accessed in the same thread in which it was created. The 'stack' field
+// is also shared, but a Mutex<T> where T: Send is already Sync. So we only
+// need to worry about 'owner_val'.
+//
+// The key is to guarantee that 'owner_val' can only ever be accessed from one
+// thread. In our implementation below, we guarantee this by only returning the
+// 'owner_val' when the ID of the current thread matches the ID of the thread
+// that created the Pool. Since this can only ever be one thread, it follows
+// that only one thread can access 'owner_val' at any point in time. Thus, it
+// is safe to declare that Pool<T> is Sync when T is Send.
+//
+// NOTE: It would also be possible to make the owning thread be the *first*
+// thread that tries to get a value out of a Pool. However, the current
+// implementation is a little simpler and it's not clear if making the first
+// thread (rather than the creating thread) is meaningfully better.
+//
+// If there is a way to achieve our performance goals using safe code, then
+// I would very much welcome a patch. As it stands, the implementation below
+// tries to balance safety with performance. The case where a Regex is used
+// from multiple threads simultaneously will suffer a bit since getting a cache
+// will require unlocking a mutex.
+unsafe impl<T: Send> Sync for Pool<T> {}
+
+impl<T: ::std::fmt::Debug> ::std::fmt::Debug for Pool<T> {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+        f.debug_struct("Pool")
+            .field("stack", &self.stack)
+            .field("owner", &self.owner)
+            .field("owner_val", &self.owner_val)
+            .finish()
+    }
+}
+
+/// A guard that is returned when a caller requests a value from the pool.
+///
+/// The purpose of the guard is to use RAII to automatically put the value back
+/// in the pool once it's dropped.
+#[derive(Debug)]
+pub struct PoolGuard<'a, T: 'a + Send> {
+    /// The pool that this guard is attached to.
+    pool: &'a Pool<T>,
+    /// This is None when the guard represents the special "owned" value. In
+    /// which case, the value is retrieved from 'pool.owner_val'.
+    value: Option<Box<T>>,
+}
+
+impl<T: Send> Pool<T> {
+    /// Create a new pool. The given closure is used to create values in the
+    /// pool when necessary.
+    pub fn new(create: CreateFn<T>) -> Pool<T> {
+        let owner = AtomicUsize::new(0);
+        let owner_val = create();
+        Pool { stack: Mutex::new(vec![]), create, owner, owner_val }
+    }
+
+    /// Get a value from the pool. The caller is guaranteed to have exclusive
+    /// access to the given value.
+    ///
+    /// Note that there is no guarantee provided about which value in the
+    /// pool is returned. That is, calling get, dropping the guard (causing
+    /// the value to go back into the pool) and then calling get again is NOT
+    /// guaranteed to return the same value received in the first get call.
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    pub fn get(&self) -> PoolGuard<T> {
+        // Our fast path checks if the caller is the thread that "owns" this
+        // pool. Or stated differently, whether it is the first thread that
+        // tried to extract a value from the pool. If it is, then we can return
+        // a T to the caller without going through a mutex.
+        //
+        // SAFETY: We must guarantee that only one thread gets access to this
+        // value. Since a thread is uniquely identified by the THREAD_ID thread
+        // local, it follows that is the caller's thread ID is equal to the
+        // owner, then only one thread may receive this value.
+        let caller = THREAD_ID.with(|id| *id);
+        let owner = self.owner.load(Ordering::Relaxed);
+        if caller == owner {
+            return self.guard_owned();
+        }
+        self.get_slow(caller, owner)
+    }
+
+    /// This is the "slow" version that goes through a mutex to pop an
+    /// allocated value off a stack to return to the caller. (Or, if the stack
+    /// is empty, a new value is created.)
+    ///
+    /// If the pool has no owner, then this will set the owner.
+    #[cold]
+    fn get_slow(&self, caller: usize, owner: usize) -> PoolGuard<T> {
+        use std::sync::atomic::Ordering::Relaxed;
+
+        if owner == 0 {
+            // The sentinel 0 value means this pool is not yet owned. We
+            // try to atomically set the owner. If we do, then this thread
+            // becomes the owner and we can return a guard that represents
+            // the special T for the owner.
+            let res = self.owner.compare_exchange(0, caller, Relaxed, Relaxed);
+            if res.is_ok() {
+                return self.guard_owned();
+            }
+        }
+        let mut stack = self.stack.lock().unwrap();
+        let value = match stack.pop() {
+            None => Box::new((self.create)()),
+            Some(value) => value,
+        };
+        self.guard_stack(value)
+    }
+
+    /// Puts a value back into the pool. Callers don't need to call this. Once
+    /// the guard that's returned by 'get' is dropped, it is put back into the
+    /// pool automatically.
+    fn put(&self, value: Box<T>) {
+        let mut stack = self.stack.lock().unwrap();
+        stack.push(value);
+    }
+
+    /// Create a guard that represents the special owned T.
+    fn guard_owned(&self) -> PoolGuard<'_, T> {
+        PoolGuard { pool: self, value: None }
+    }
+
+    /// Create a guard that contains a value from the pool's stack.
+    fn guard_stack(&self, value: Box<T>) -> PoolGuard<'_, T> {
+        PoolGuard { pool: self, value: Some(value) }
+    }
+}
+
+impl<'a, T: Send> PoolGuard<'a, T> {
+    /// Return the underlying value.
+    pub fn value(&self) -> &T {
+        match self.value {
+            None => &self.pool.owner_val,
+            Some(ref v) => &**v,
+        }
+    }
+}
+
+impl<'a, T: Send> Drop for PoolGuard<'a, T> {
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn drop(&mut self) {
+        if let Some(value) = self.value.take() {
+            self.pool.put(value);
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use std::panic::{RefUnwindSafe, UnwindSafe};
+
+    use super::*;
+
+    #[test]
+    fn oibits() {
+        use exec::ProgramCache;
+
+        fn has_oibits<T: Send + Sync + UnwindSafe + RefUnwindSafe>() {}
+        has_oibits::<Pool<ProgramCache>>();
+    }
+
+    // Tests that Pool implements the "single owner" optimization. That is, the
+    // thread that first accesses the pool gets its own copy, while all other
+    // threads get distinct copies.
+    #[test]
+    fn thread_owner_optimization() {
+        use std::cell::RefCell;
+        use std::sync::Arc;
+
+        let pool: Arc<Pool<RefCell<Vec<char>>>> =
+            Arc::new(Pool::new(Box::new(|| RefCell::new(vec!['a']))));
+        pool.get().value().borrow_mut().push('x');
+
+        let pool1 = pool.clone();
+        let t1 = std::thread::spawn(move || {
+            let guard = pool1.get();
+            let v = guard.value();
+            v.borrow_mut().push('y');
+        });
+
+        let pool2 = pool.clone();
+        let t2 = std::thread::spawn(move || {
+            let guard = pool2.get();
+            let v = guard.value();
+            v.borrow_mut().push('z');
+        });
+
+        t1.join().unwrap();
+        t2.join().unwrap();
+
+        // If we didn't implement the single owner optimization, then one of
+        // the threads above is likely to have mutated the [a, x] vec that
+        // we stuffed in the pool before spawning the threads. But since
+        // neither thread was first to access the pool, and because of the
+        // optimization, we should be guaranteed that neither thread mutates
+        // the special owned pool value.
+        //
+        // (Technically this is an implementation detail and not a contract of
+        // Pool's API.)
+        assert_eq!(vec!['a', 'x'], *pool.get().value().borrow());
+    }
+}
diff --git a/vendor/regex-1.4.6/src/prog.rs b/vendor/regex-1.4.6/src/prog.rs
new file mode 100644 (file)
index 0000000..a2b89c9
--- /dev/null
@@ -0,0 +1,447 @@
+use std::cmp::Ordering;
+use std::collections::HashMap;
+use std::fmt;
+use std::mem;
+use std::ops::Deref;
+use std::slice;
+use std::sync::Arc;
+
+use input::Char;
+use literal::LiteralSearcher;
+
+/// `InstPtr` represents the index of an instruction in a regex program.
+pub type InstPtr = usize;
+
+/// Program is a sequence of instructions and various facts about thos
+/// instructions.
+#[derive(Clone)]
+pub struct Program {
+    /// A sequence of instructions that represents an NFA.
+    pub insts: Vec<Inst>,
+    /// Pointers to each Match instruction in the sequence.
+    ///
+    /// This is always length 1 unless this program represents a regex set.
+    pub matches: Vec<InstPtr>,
+    /// The ordered sequence of all capture groups extracted from the AST.
+    /// Unnamed groups are `None`.
+    pub captures: Vec<Option<String>>,
+    /// Pointers to all named capture groups into `captures`.
+    pub capture_name_idx: Arc<HashMap<String, usize>>,
+    /// A pointer to the start instruction. This can vary depending on how
+    /// the program was compiled. For example, programs for use with the DFA
+    /// engine have a `.*?` inserted at the beginning of unanchored regular
+    /// expressions. The actual starting point of the program is after the
+    /// `.*?`.
+    pub start: InstPtr,
+    /// A set of equivalence classes for discriminating bytes in the compiled
+    /// program.
+    pub byte_classes: Vec<u8>,
+    /// When true, this program can only match valid UTF-8.
+    pub only_utf8: bool,
+    /// When true, this program uses byte range instructions instead of Unicode
+    /// range instructions.
+    pub is_bytes: bool,
+    /// When true, the program is compiled for DFA matching. For example, this
+    /// implies `is_bytes` and also inserts a preceding `.*?` for unanchored
+    /// regexes.
+    pub is_dfa: bool,
+    /// When true, the program matches text in reverse (for use only in the
+    /// DFA).
+    pub is_reverse: bool,
+    /// Whether the regex must match from the start of the input.
+    pub is_anchored_start: bool,
+    /// Whether the regex must match at the end of the input.
+    pub is_anchored_end: bool,
+    /// Whether this program contains a Unicode word boundary instruction.
+    pub has_unicode_word_boundary: bool,
+    /// A possibly empty machine for very quickly matching prefix literals.
+    pub prefixes: LiteralSearcher,
+    /// A limit on the size of the cache that the DFA is allowed to use while
+    /// matching.
+    ///
+    /// The cache limit specifies approximately how much space we're willing to
+    /// give to the state cache. Once the state cache exceeds the size, it is
+    /// wiped and all states must be re-computed.
+    ///
+    /// Note that this value does not impact correctness. It can be set to 0
+    /// and the DFA will run just fine. (It will only ever store exactly one
+    /// state in the cache, and will likely run very slowly, but it will work.)
+    ///
+    /// Also note that this limit is *per thread of execution*. That is,
+    /// if the same regex is used to search text across multiple threads
+    /// simultaneously, then the DFA cache is not shared. Instead, copies are
+    /// made.
+    pub dfa_size_limit: usize,
+}
+
+impl Program {
+    /// Creates an empty instruction sequence. Fields are given default
+    /// values.
+    pub fn new() -> Self {
+        Program {
+            insts: vec![],
+            matches: vec![],
+            captures: vec![],
+            capture_name_idx: Arc::new(HashMap::new()),
+            start: 0,
+            byte_classes: vec![0; 256],
+            only_utf8: true,
+            is_bytes: false,
+            is_dfa: false,
+            is_reverse: false,
+            is_anchored_start: false,
+            is_anchored_end: false,
+            has_unicode_word_boundary: false,
+            prefixes: LiteralSearcher::empty(),
+            dfa_size_limit: 2 * (1 << 20),
+        }
+    }
+
+    /// If pc is an index to a no-op instruction (like Save), then return the
+    /// next pc that is not a no-op instruction.
+    pub fn skip(&self, mut pc: usize) -> usize {
+        loop {
+            match self[pc] {
+                Inst::Save(ref i) => pc = i.goto,
+                _ => return pc,
+            }
+        }
+    }
+
+    /// Return true if and only if an execution engine at instruction `pc` will
+    /// always lead to a match.
+    pub fn leads_to_match(&self, pc: usize) -> bool {
+        if self.matches.len() > 1 {
+            // If we have a regex set, then we have more than one ending
+            // state, so leading to one of those states is generally
+            // meaningless.
+            return false;
+        }
+        match self[self.skip(pc)] {
+            Inst::Match(_) => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if the current configuration demands that an implicit
+    /// `.*?` be prepended to the instruction sequence.
+    pub fn needs_dotstar(&self) -> bool {
+        self.is_dfa && !self.is_reverse && !self.is_anchored_start
+    }
+
+    /// Returns true if this program uses Byte instructions instead of
+    /// Char/Range instructions.
+    pub fn uses_bytes(&self) -> bool {
+        self.is_bytes || self.is_dfa
+    }
+
+    /// Returns true if this program exclusively matches valid UTF-8 bytes.
+    ///
+    /// That is, if an invalid UTF-8 byte is seen, then no match is possible.
+    pub fn only_utf8(&self) -> bool {
+        self.only_utf8
+    }
+
+    /// Return the approximate heap usage of this instruction sequence in
+    /// bytes.
+    pub fn approximate_size(&self) -> usize {
+        // The only instruction that uses heap space is Ranges (for
+        // Unicode codepoint programs) to store non-overlapping codepoint
+        // ranges. To keep this operation constant time, we ignore them.
+        (self.len() * mem::size_of::<Inst>())
+            + (self.matches.len() * mem::size_of::<InstPtr>())
+            + (self.captures.len() * mem::size_of::<Option<String>>())
+            + (self.capture_name_idx.len()
+                * (mem::size_of::<String>() + mem::size_of::<usize>()))
+            + (self.byte_classes.len() * mem::size_of::<u8>())
+            + self.prefixes.approximate_size()
+    }
+}
+
+impl Deref for Program {
+    type Target = [Inst];
+
+    #[cfg_attr(feature = "perf-inline", inline(always))]
+    fn deref(&self) -> &Self::Target {
+        &*self.insts
+    }
+}
+
+impl fmt::Debug for Program {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use self::Inst::*;
+
+        fn with_goto(cur: usize, goto: usize, fmtd: String) -> String {
+            if goto == cur + 1 {
+                fmtd
+            } else {
+                format!("{} (goto: {})", fmtd, goto)
+            }
+        }
+
+        fn visible_byte(b: u8) -> String {
+            use std::ascii::escape_default;
+            let escaped = escape_default(b).collect::<Vec<u8>>();
+            String::from_utf8_lossy(&escaped).into_owned()
+        }
+
+        for (pc, inst) in self.iter().enumerate() {
+            match *inst {
+                Match(slot) => write!(f, "{:04} Match({:?})", pc, slot)?,
+                Save(ref inst) => {
+                    let s = format!("{:04} Save({})", pc, inst.slot);
+                    write!(f, "{}", with_goto(pc, inst.goto, s))?;
+                }
+                Split(ref inst) => {
+                    write!(
+                        f,
+                        "{:04} Split({}, {})",
+                        pc, inst.goto1, inst.goto2
+                    )?;
+                }
+                EmptyLook(ref inst) => {
+                    let s = format!("{:?}", inst.look);
+                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
+                }
+                Char(ref inst) => {
+                    let s = format!("{:?}", inst.c);
+                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
+                }
+                Ranges(ref inst) => {
+                    let ranges = inst
+                        .ranges
+                        .iter()
+                        .map(|r| format!("{:?}-{:?}", r.0, r.1))
+                        .collect::<Vec<String>>()
+                        .join(", ");
+                    write!(
+                        f,
+                        "{:04} {}",
+                        pc,
+                        with_goto(pc, inst.goto, ranges)
+                    )?;
+                }
+                Bytes(ref inst) => {
+                    let s = format!(
+                        "Bytes({}, {})",
+                        visible_byte(inst.start),
+                        visible_byte(inst.end)
+                    );
+                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
+                }
+            }
+            if pc == self.start {
+                write!(f, " (start)")?;
+            }
+            write!(f, "\n")?;
+        }
+        Ok(())
+    }
+}
+
+impl<'a> IntoIterator for &'a Program {
+    type Item = &'a Inst;
+    type IntoIter = slice::Iter<'a, Inst>;
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter()
+    }
+}
+
+/// Inst is an instruction code in a Regex program.
+///
+/// Regrettably, a regex program either contains Unicode codepoint
+/// instructions (Char and Ranges) or it contains byte instructions (Bytes).
+/// A regex program can never contain both.
+///
+/// It would be worth investigating splitting this into two distinct types and
+/// then figuring out how to make the matching engines polymorphic over those
+/// types without sacrificing performance.
+///
+/// Other than the benefit of moving invariants into the type system, another
+/// benefit is the decreased size. If we remove the `Char` and `Ranges`
+/// instructions from the `Inst` enum, then its size shrinks from 32 bytes to
+/// 24 bytes. (This is because of the removal of a `Box<[]>` in the `Ranges`
+/// variant.) Given that byte based machines are typically much bigger than
+/// their Unicode analogues (because they can decode UTF-8 directly), this ends
+/// up being a pretty significant savings.
+#[derive(Clone, Debug)]
+pub enum Inst {
+    /// Match indicates that the program has reached a match state.
+    ///
+    /// The number in the match corresponds to the Nth logical regular
+    /// expression in this program. This index is always 0 for normal regex
+    /// programs. Values greater than 0 appear when compiling regex sets, and
+    /// each match instruction gets its own unique value. The value corresponds
+    /// to the Nth regex in the set.
+    Match(usize),
+    /// Save causes the program to save the current location of the input in
+    /// the slot indicated by InstSave.
+    Save(InstSave),
+    /// Split causes the program to diverge to one of two paths in the
+    /// program, preferring goto1 in InstSplit.
+    Split(InstSplit),
+    /// EmptyLook represents a zero-width assertion in a regex program. A
+    /// zero-width assertion does not consume any of the input text.
+    EmptyLook(InstEmptyLook),
+    /// Char requires the regex program to match the character in InstChar at
+    /// the current position in the input.
+    Char(InstChar),
+    /// Ranges requires the regex program to match the character at the current
+    /// position in the input with one of the ranges specified in InstRanges.
+    Ranges(InstRanges),
+    /// Bytes is like Ranges, except it expresses a single byte range. It is
+    /// used in conjunction with Split instructions to implement multi-byte
+    /// character classes.
+    Bytes(InstBytes),
+}
+
+impl Inst {
+    /// Returns true if and only if this is a match instruction.
+    pub fn is_match(&self) -> bool {
+        match *self {
+            Inst::Match(_) => true,
+            _ => false,
+        }
+    }
+}
+
+/// Representation of the Save instruction.
+#[derive(Clone, Debug)]
+pub struct InstSave {
+    /// The next location to execute in the program.
+    pub goto: InstPtr,
+    /// The capture slot (there are two slots for every capture in a regex,
+    /// including the zeroth capture for the entire match).
+    pub slot: usize,
+}
+
+/// Representation of the Split instruction.
+#[derive(Clone, Debug)]
+pub struct InstSplit {
+    /// The first instruction to try. A match resulting from following goto1
+    /// has precedence over a match resulting from following goto2.
+    pub goto1: InstPtr,
+    /// The second instruction to try. A match resulting from following goto1
+    /// has precedence over a match resulting from following goto2.
+    pub goto2: InstPtr,
+}
+
+/// Representation of the `EmptyLook` instruction.
+#[derive(Clone, Debug)]
+pub struct InstEmptyLook {
+    /// The next location to execute in the program if this instruction
+    /// succeeds.
+    pub goto: InstPtr,
+    /// The type of zero-width assertion to check.
+    pub look: EmptyLook,
+}
+
+/// The set of zero-width match instructions.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum EmptyLook {
+    /// Start of line or input.
+    StartLine,
+    /// End of line or input.
+    EndLine,
+    /// Start of input.
+    StartText,
+    /// End of input.
+    EndText,
+    /// Word character on one side and non-word character on other.
+    WordBoundary,
+    /// Word character on both sides or non-word character on both sides.
+    NotWordBoundary,
+    /// ASCII word boundary.
+    WordBoundaryAscii,
+    /// Not ASCII word boundary.
+    NotWordBoundaryAscii,
+}
+
+/// Representation of the Char instruction.
+#[derive(Clone, Debug)]
+pub struct InstChar {
+    /// The next location to execute in the program if this instruction
+    /// succeeds.
+    pub goto: InstPtr,
+    /// The character to test.
+    pub c: char,
+}
+
+/// Representation of the Ranges instruction.
+#[derive(Clone, Debug)]
+pub struct InstRanges {
+    /// The next location to execute in the program if this instruction
+    /// succeeds.
+    pub goto: InstPtr,
+    /// The set of Unicode scalar value ranges to test.
+    pub ranges: Box<[(char, char)]>,
+}
+
+impl InstRanges {
+    /// Tests whether the given input character matches this instruction.
+    pub fn matches(&self, c: Char) -> bool {
+        // This speeds up the `match_class_unicode` benchmark by checking
+        // some common cases quickly without binary search. e.g., Matching
+        // a Unicode class on predominantly ASCII text.
+        for r in self.ranges.iter().take(4) {
+            if c < r.0 {
+                return false;
+            }
+            if c <= r.1 {
+                return true;
+            }
+        }
+        self.ranges
+            .binary_search_by(|r| {
+                if r.1 < c {
+                    Ordering::Less
+                } else if r.0 > c {
+                    Ordering::Greater
+                } else {
+                    Ordering::Equal
+                }
+            })
+            .is_ok()
+    }
+
+    /// Return the number of distinct characters represented by all of the
+    /// ranges.
+    pub fn num_chars(&self) -> usize {
+        self.ranges
+            .iter()
+            .map(|&(s, e)| 1 + (e as u32) - (s as u32))
+            .sum::<u32>() as usize
+    }
+}
+
+/// Representation of the Bytes instruction.
+#[derive(Clone, Debug)]
+pub struct InstBytes {
+    /// The next location to execute in the program if this instruction
+    /// succeeds.
+    pub goto: InstPtr,
+    /// The start (inclusive) of this byte range.
+    pub start: u8,
+    /// The end (inclusive) of this byte range.
+    pub end: u8,
+}
+
+impl InstBytes {
+    /// Returns true if and only if the given byte is in this range.
+    pub fn matches(&self, byte: u8) -> bool {
+        self.start <= byte && byte <= self.end
+    }
+}
+
+#[cfg(test)]
+mod test {
+    #[test]
+    #[cfg(target_pointer_width = "64")]
+    fn test_size_of_inst() {
+        use std::mem::size_of;
+
+        use super::Inst;
+
+        assert_eq!(32, size_of::<Inst>());
+    }
+}
diff --git a/vendor/regex-1.4.6/src/re_builder.rs b/vendor/regex-1.4.6/src/re_builder.rs
new file mode 100644 (file)
index 0000000..fc140f8
--- /dev/null
@@ -0,0 +1,421 @@
+/// The set of user configurable options for compiling zero or more regexes.
+#[derive(Clone, Debug)]
+#[allow(missing_docs)]
+pub struct RegexOptions {
+    pub pats: Vec<String>,
+    pub size_limit: usize,
+    pub dfa_size_limit: usize,
+    pub nest_limit: u32,
+    pub case_insensitive: bool,
+    pub multi_line: bool,
+    pub dot_matches_new_line: bool,
+    pub swap_greed: bool,
+    pub ignore_whitespace: bool,
+    pub unicode: bool,
+    pub octal: bool,
+}
+
+impl Default for RegexOptions {
+    fn default() -> Self {
+        RegexOptions {
+            pats: vec![],
+            size_limit: 10 * (1 << 20),
+            dfa_size_limit: 2 * (1 << 20),
+            nest_limit: 250,
+            case_insensitive: false,
+            multi_line: false,
+            dot_matches_new_line: false,
+            swap_greed: false,
+            ignore_whitespace: false,
+            unicode: true,
+            octal: false,
+        }
+    }
+}
+
+macro_rules! define_builder {
+    ($name:ident, $regex_mod:ident, $only_utf8:expr) => {
+        pub mod $name {
+            use super::RegexOptions;
+            use error::Error;
+            use exec::ExecBuilder;
+
+            use $regex_mod::Regex;
+
+            /// A configurable builder for a regular expression.
+            ///
+            /// A builder can be used to configure how the regex is built, for example, by
+            /// setting the default flags (which can be overridden in the expression
+            /// itself) or setting various limits.
+            #[derive(Debug)]
+            pub struct RegexBuilder(RegexOptions);
+
+            impl RegexBuilder {
+                /// Create a new regular expression builder with the given pattern.
+                ///
+                /// If the pattern is invalid, then an error will be returned when
+                /// `build` is called.
+                pub fn new(pattern: &str) -> RegexBuilder {
+                    let mut builder = RegexBuilder(RegexOptions::default());
+                    builder.0.pats.push(pattern.to_owned());
+                    builder
+                }
+
+                /// Consume the builder and compile the regular expression.
+                ///
+                /// Note that calling `as_str` on the resulting `Regex` will produce the
+                /// pattern given to `new` verbatim. Notably, it will not incorporate any
+                /// of the flags set on this builder.
+                pub fn build(&self) -> Result<Regex, Error> {
+                    ExecBuilder::new_options(self.0.clone())
+                        .only_utf8($only_utf8)
+                        .build()
+                        .map(Regex::from)
+                }
+
+                /// Set the value for the case insensitive (`i`) flag.
+                ///
+                /// When enabled, letters in the pattern will match both upper case and
+                /// lower case variants.
+                pub fn case_insensitive(
+                    &mut self,
+                    yes: bool,
+                ) -> &mut RegexBuilder {
+                    self.0.case_insensitive = yes;
+                    self
+                }
+
+                /// Set the value for the multi-line matching (`m`) flag.
+                ///
+                /// When enabled, `^` matches the beginning of lines and `$` matches the
+                /// end of lines.
+                ///
+                /// By default, they match beginning/end of the input.
+                pub fn multi_line(&mut self, yes: bool) -> &mut RegexBuilder {
+                    self.0.multi_line = yes;
+                    self
+                }
+
+                /// Set the value for the any character (`s`) flag, where in `.` matches
+                /// anything when `s` is set and matches anything except for new line when
+                /// it is not set (the default).
+                ///
+                /// N.B. "matches anything" means "any byte" when Unicode is disabled and
+                /// means "any valid UTF-8 encoding of any Unicode scalar value" when
+                /// Unicode is enabled.
+                pub fn dot_matches_new_line(
+                    &mut self,
+                    yes: bool,
+                ) -> &mut RegexBuilder {
+                    self.0.dot_matches_new_line = yes;
+                    self
+                }
+
+                /// Set the value for the greedy swap (`U`) flag.
+                ///
+                /// When enabled, a pattern like `a*` is lazy (tries to find shortest
+                /// match) and `a*?` is greedy (tries to find longest match).
+                ///
+                /// By default, `a*` is greedy and `a*?` is lazy.
+                pub fn swap_greed(&mut self, yes: bool) -> &mut RegexBuilder {
+                    self.0.swap_greed = yes;
+                    self
+                }
+
+                /// Set the value for the ignore whitespace (`x`) flag.
+                ///
+                /// When enabled, whitespace such as new lines and spaces will be ignored
+                /// between expressions of the pattern, and `#` can be used to start a
+                /// comment until the next new line.
+                pub fn ignore_whitespace(
+                    &mut self,
+                    yes: bool,
+                ) -> &mut RegexBuilder {
+                    self.0.ignore_whitespace = yes;
+                    self
+                }
+
+                /// Set the value for the Unicode (`u`) flag.
+                ///
+                /// Enabled by default. When disabled, character classes such as `\w` only
+                /// match ASCII word characters instead of all Unicode word characters.
+                pub fn unicode(&mut self, yes: bool) -> &mut RegexBuilder {
+                    self.0.unicode = yes;
+                    self
+                }
+
+                /// Whether to support octal syntax or not.
+                ///
+                /// Octal syntax is a little-known way of uttering Unicode codepoints in
+                /// a regular expression. For example, `a`, `\x61`, `\u0061` and
+                /// `\141` are all equivalent regular expressions, where the last example
+                /// shows octal syntax.
+                ///
+                /// While supporting octal syntax isn't in and of itself a problem, it does
+                /// make good error messages harder. That is, in PCRE based regex engines,
+                /// syntax like `\0` invokes a backreference, which is explicitly
+                /// unsupported in Rust's regex engine. However, many users expect it to
+                /// be supported. Therefore, when octal support is disabled, the error
+                /// message will explicitly mention that backreferences aren't supported.
+                ///
+                /// Octal syntax is disabled by default.
+                pub fn octal(&mut self, yes: bool) -> &mut RegexBuilder {
+                    self.0.octal = yes;
+                    self
+                }
+
+                /// Set the approximate size limit of the compiled regular expression.
+                ///
+                /// This roughly corresponds to the number of bytes occupied by a single
+                /// compiled program. If the program exceeds this number, then a
+                /// compilation error is returned.
+                pub fn size_limit(
+                    &mut self,
+                    limit: usize,
+                ) -> &mut RegexBuilder {
+                    self.0.size_limit = limit;
+                    self
+                }
+
+                /// Set the approximate size of the cache used by the DFA.
+                ///
+                /// This roughly corresponds to the number of bytes that the DFA will
+                /// use while searching.
+                ///
+                /// Note that this is a *per thread* limit. There is no way to set a global
+                /// limit. In particular, if a regex is used from multiple threads
+                /// simultaneously, then each thread may use up to the number of bytes
+                /// specified here.
+                pub fn dfa_size_limit(
+                    &mut self,
+                    limit: usize,
+                ) -> &mut RegexBuilder {
+                    self.0.dfa_size_limit = limit;
+                    self
+                }
+
+                /// Set the nesting limit for this parser.
+                ///
+                /// The nesting limit controls how deep the abstract syntax tree is allowed
+                /// to be. If the AST exceeds the given limit (e.g., with too many nested
+                /// groups), then an error is returned by the parser.
+                ///
+                /// The purpose of this limit is to act as a heuristic to prevent stack
+                /// overflow for consumers that do structural induction on an `Ast` using
+                /// explicit recursion. While this crate never does this (instead using
+                /// constant stack space and moving the call stack to the heap), other
+                /// crates may.
+                ///
+                /// This limit is not checked until the entire Ast is parsed. Therefore,
+                /// if callers want to put a limit on the amount of heap space used, then
+                /// they should impose a limit on the length, in bytes, of the concrete
+                /// pattern string. In particular, this is viable since this parser
+                /// implementation will limit itself to heap space proportional to the
+                /// length of the pattern string.
+                ///
+                /// Note that a nest limit of `0` will return a nest limit error for most
+                /// patterns but not all. For example, a nest limit of `0` permits `a` but
+                /// not `ab`, since `ab` requires a concatenation, which results in a nest
+                /// depth of `1`. In general, a nest limit is not something that manifests
+                /// in an obvious way in the concrete syntax, therefore, it should not be
+                /// used in a granular way.
+                pub fn nest_limit(&mut self, limit: u32) -> &mut RegexBuilder {
+                    self.0.nest_limit = limit;
+                    self
+                }
+            }
+        }
+    };
+}
+
+define_builder!(bytes, re_bytes, false);
+define_builder!(unicode, re_unicode, true);
+
+macro_rules! define_set_builder {
+    ($name:ident, $regex_mod:ident, $only_utf8:expr) => {
+        pub mod $name {
+            use super::RegexOptions;
+            use error::Error;
+            use exec::ExecBuilder;
+
+            use re_set::$regex_mod::RegexSet;
+
+            /// A configurable builder for a set of regular expressions.
+            ///
+            /// A builder can be used to configure how the regexes are built, for example,
+            /// by setting the default flags (which can be overridden in the expression
+            /// itself) or setting various limits.
+            #[derive(Debug)]
+            pub struct RegexSetBuilder(RegexOptions);
+
+            impl RegexSetBuilder {
+                /// Create a new regular expression builder with the given pattern.
+                ///
+                /// If the pattern is invalid, then an error will be returned when
+                /// `build` is called.
+                pub fn new<I, S>(patterns: I) -> RegexSetBuilder
+                where
+                    S: AsRef<str>,
+                    I: IntoIterator<Item = S>,
+                {
+                    let mut builder = RegexSetBuilder(RegexOptions::default());
+                    for pat in patterns {
+                        builder.0.pats.push(pat.as_ref().to_owned());
+                    }
+                    builder
+                }
+
+                /// Consume the builder and compile the regular expressions into a set.
+                pub fn build(&self) -> Result<RegexSet, Error> {
+                    ExecBuilder::new_options(self.0.clone())
+                        .only_utf8($only_utf8)
+                        .build()
+                        .map(RegexSet::from)
+                }
+
+                /// Set the value for the case insensitive (`i`) flag.
+                pub fn case_insensitive(
+                    &mut self,
+                    yes: bool,
+                ) -> &mut RegexSetBuilder {
+                    self.0.case_insensitive = yes;
+                    self
+                }
+
+                /// Set the value for the multi-line matching (`m`) flag.
+                pub fn multi_line(
+                    &mut self,
+                    yes: bool,
+                ) -> &mut RegexSetBuilder {
+                    self.0.multi_line = yes;
+                    self
+                }
+
+                /// Set the value for the any character (`s`) flag, where in `.` matches
+                /// anything when `s` is set and matches anything except for new line when
+                /// it is not set (the default).
+                ///
+                /// N.B. "matches anything" means "any byte" for `regex::bytes::RegexSet`
+                /// expressions and means "any Unicode scalar value" for `regex::RegexSet`
+                /// expressions.
+                pub fn dot_matches_new_line(
+                    &mut self,
+                    yes: bool,
+                ) -> &mut RegexSetBuilder {
+                    self.0.dot_matches_new_line = yes;
+                    self
+                }
+
+                /// Set the value for the greedy swap (`U`) flag.
+                pub fn swap_greed(
+                    &mut self,
+                    yes: bool,
+                ) -> &mut RegexSetBuilder {
+                    self.0.swap_greed = yes;
+                    self
+                }
+
+                /// Set the value for the ignore whitespace (`x`) flag.
+                pub fn ignore_whitespace(
+                    &mut self,
+                    yes: bool,
+                ) -> &mut RegexSetBuilder {
+                    self.0.ignore_whitespace = yes;
+                    self
+                }
+
+                /// Set the value for the Unicode (`u`) flag.
+                pub fn unicode(&mut self, yes: bool) -> &mut RegexSetBuilder {
+                    self.0.unicode = yes;
+                    self
+                }
+
+                /// Whether to support octal syntax or not.
+                ///
+                /// Octal syntax is a little-known way of uttering Unicode codepoints in
+                /// a regular expression. For example, `a`, `\x61`, `\u0061` and
+                /// `\141` are all equivalent regular expressions, where the last example
+                /// shows octal syntax.
+                ///
+                /// While supporting octal syntax isn't in and of itself a problem, it does
+                /// make good error messages harder. That is, in PCRE based regex engines,
+                /// syntax like `\0` invokes a backreference, which is explicitly
+                /// unsupported in Rust's regex engine. However, many users expect it to
+                /// be supported. Therefore, when octal support is disabled, the error
+                /// message will explicitly mention that backreferences aren't supported.
+                ///
+                /// Octal syntax is disabled by default.
+                pub fn octal(&mut self, yes: bool) -> &mut RegexSetBuilder {
+                    self.0.octal = yes;
+                    self
+                }
+
+                /// Set the approximate size limit of the compiled regular expression.
+                ///
+                /// This roughly corresponds to the number of bytes occupied by a single
+                /// compiled program. If the program exceeds this number, then a
+                /// compilation error is returned.
+                pub fn size_limit(
+                    &mut self,
+                    limit: usize,
+                ) -> &mut RegexSetBuilder {
+                    self.0.size_limit = limit;
+                    self
+                }
+
+                /// Set the approximate size of the cache used by the DFA.
+                ///
+                /// This roughly corresponds to the number of bytes that the DFA will
+                /// use while searching.
+                ///
+                /// Note that this is a *per thread* limit. There is no way to set a global
+                /// limit. In particular, if a regex is used from multiple threads
+                /// simultaneously, then each thread may use up to the number of bytes
+                /// specified here.
+                pub fn dfa_size_limit(
+                    &mut self,
+                    limit: usize,
+                ) -> &mut RegexSetBuilder {
+                    self.0.dfa_size_limit = limit;
+                    self
+                }
+
+                /// Set the nesting limit for this parser.
+                ///
+                /// The nesting limit controls how deep the abstract syntax tree is allowed
+                /// to be. If the AST exceeds the given limit (e.g., with too many nested
+                /// groups), then an error is returned by the parser.
+                ///
+                /// The purpose of this limit is to act as a heuristic to prevent stack
+                /// overflow for consumers that do structural induction on an `Ast` using
+                /// explicit recursion. While this crate never does this (instead using
+                /// constant stack space and moving the call stack to the heap), other
+                /// crates may.
+                ///
+                /// This limit is not checked until the entire Ast is parsed. Therefore,
+                /// if callers want to put a limit on the amount of heap space used, then
+                /// they should impose a limit on the length, in bytes, of the concrete
+                /// pattern string. In particular, this is viable since this parser
+                /// implementation will limit itself to heap space proportional to the
+                /// length of the pattern string.
+                ///
+                /// Note that a nest limit of `0` will return a nest limit error for most
+                /// patterns but not all. For example, a nest limit of `0` permits `a` but
+                /// not `ab`, since `ab` requires a concatenation, which results in a nest
+                /// depth of `1`. In general, a nest limit is not something that manifests
+                /// in an obvious way in the concrete syntax, therefore, it should not be
+                /// used in a granular way.
+                pub fn nest_limit(
+                    &mut self,
+                    limit: u32,
+                ) -> &mut RegexSetBuilder {
+                    self.0.nest_limit = limit;
+                    self
+                }
+            }
+        }
+    };
+}
+
+define_set_builder!(set_bytes, bytes, false);
+define_set_builder!(set_unicode, unicode, true);
diff --git a/vendor/regex-1.4.6/src/re_bytes.rs b/vendor/regex-1.4.6/src/re_bytes.rs
new file mode 100644 (file)
index 0000000..204a70a
--- /dev/null
@@ -0,0 +1,1260 @@
+use std::borrow::Cow;
+use std::collections::HashMap;
+use std::fmt;
+use std::iter::FusedIterator;
+use std::ops::{Index, Range};
+use std::str::FromStr;
+use std::sync::Arc;
+
+use find_byte::find_byte;
+
+use error::Error;
+use exec::{Exec, ExecNoSync};
+use expand::expand_bytes;
+use re_builder::bytes::RegexBuilder;
+use re_trait::{self, RegularExpression, SubCapturesPosIter};
+
+/// Match represents a single match of a regex in a haystack.
+///
+/// The lifetime parameter `'t` refers to the lifetime of the matched text.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct Match<'t> {
+    text: &'t [u8],
+    start: usize,
+    end: usize,
+}
+
+impl<'t> Match<'t> {
+    /// Returns the starting byte offset of the match in the haystack.
+    #[inline]
+    pub fn start(&self) -> usize {
+        self.start
+    }
+
+    /// Returns the ending byte offset of the match in the haystack.
+    #[inline]
+    pub fn end(&self) -> usize {
+        self.end
+    }
+
+    /// Returns the range over the starting and ending byte offsets of the
+    /// match in the haystack.
+    #[inline]
+    pub fn range(&self) -> Range<usize> {
+        self.start..self.end
+    }
+
+    /// Returns the matched text.
+    #[inline]
+    pub fn as_bytes(&self) -> &'t [u8] {
+        &self.text[self.range()]
+    }
+
+    /// Creates a new match from the given haystack and byte offsets.
+    #[inline]
+    fn new(haystack: &'t [u8], start: usize, end: usize) -> Match<'t> {
+        Match { text: haystack, start: start, end: end }
+    }
+}
+
+impl<'t> From<Match<'t>> for Range<usize> {
+    fn from(m: Match<'t>) -> Range<usize> {
+        m.range()
+    }
+}
+
+/// A compiled regular expression for matching arbitrary bytes.
+///
+/// It can be used to search, split or replace text. All searching is done with
+/// an implicit `.*?` at the beginning and end of an expression. To force an
+/// expression to match the whole string (or a prefix or a suffix), you must
+/// use an anchor like `^` or `$` (or `\A` and `\z`).
+///
+/// Like the `Regex` type in the parent module, matches with this regex return
+/// byte offsets into the search text. **Unlike** the parent `Regex` type,
+/// these byte offsets may not correspond to UTF-8 sequence boundaries since
+/// the regexes in this module can match arbitrary bytes.
+#[derive(Clone)]
+pub struct Regex(Exec);
+
+impl fmt::Display for Regex {
+    /// Shows the original regular expression.
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.as_str())
+    }
+}
+
+impl fmt::Debug for Regex {
+    /// Shows the original regular expression.
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self, f)
+    }
+}
+
+/// A constructor for Regex from an Exec.
+///
+/// This is hidden because Exec isn't actually part of the public API.
+#[doc(hidden)]
+impl From<Exec> for Regex {
+    fn from(exec: Exec) -> Regex {
+        Regex(exec)
+    }
+}
+
+impl FromStr for Regex {
+    type Err = Error;
+
+    /// Attempts to parse a string into a regular expression
+    fn from_str(s: &str) -> Result<Regex, Error> {
+        Regex::new(s)
+    }
+}
+
+/// Core regular expression methods.
+impl Regex {
+    /// Compiles a regular expression. Once compiled, it can be used repeatedly
+    /// to search, split or replace text in a string.
+    ///
+    /// If an invalid expression is given, then an error is returned.
+    pub fn new(re: &str) -> Result<Regex, Error> {
+        RegexBuilder::new(re).build()
+    }
+
+    /// Returns true if and only if there is a match for the regex in the
+    /// string given.
+    ///
+    /// It is recommended to use this method if all you need to do is test
+    /// a match, since the underlying matching engine may be able to do less
+    /// work.
+    ///
+    /// # Example
+    ///
+    /// Test if some text contains at least one word with exactly 13 ASCII word
+    /// bytes:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let text = b"I categorically deny having triskaidekaphobia.";
+    /// assert!(Regex::new(r"\b\w{13}\b").unwrap().is_match(text));
+    /// # }
+    /// ```
+    pub fn is_match(&self, text: &[u8]) -> bool {
+        self.is_match_at(text, 0)
+    }
+
+    /// Returns the start and end byte range of the leftmost-first match in
+    /// `text`. If no match exists, then `None` is returned.
+    ///
+    /// Note that this should only be used if you want to discover the position
+    /// of the match. Testing the existence of a match is faster if you use
+    /// `is_match`.
+    ///
+    /// # Example
+    ///
+    /// Find the start and end location of the first word with exactly 13
+    /// ASCII word bytes:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let text = b"I categorically deny having triskaidekaphobia.";
+    /// let mat = Regex::new(r"\b\w{13}\b").unwrap().find(text).unwrap();
+    /// assert_eq!((mat.start(), mat.end()), (2, 15));
+    /// # }
+    /// ```
+    pub fn find<'t>(&self, text: &'t [u8]) -> Option<Match<'t>> {
+        self.find_at(text, 0)
+    }
+
+    /// Returns an iterator for each successive non-overlapping match in
+    /// `text`, returning the start and end byte indices with respect to
+    /// `text`.
+    ///
+    /// # Example
+    ///
+    /// Find the start and end location of every word with exactly 13 ASCII
+    /// word bytes:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let text = b"Retroactively relinquishing remunerations is reprehensible.";
+    /// for mat in Regex::new(r"\b\w{13}\b").unwrap().find_iter(text) {
+    ///     println!("{:?}", mat);
+    /// }
+    /// # }
+    /// ```
+    pub fn find_iter<'r, 't>(&'r self, text: &'t [u8]) -> Matches<'r, 't> {
+        Matches(self.0.searcher().find_iter(text))
+    }
+
+    /// Returns the capture groups corresponding to the leftmost-first
+    /// match in `text`. Capture group `0` always corresponds to the entire
+    /// match. If no match is found, then `None` is returned.
+    ///
+    /// You should only use `captures` if you need access to the location of
+    /// capturing group matches. Otherwise, `find` is faster for discovering
+    /// the location of the overall match.
+    ///
+    /// # Examples
+    ///
+    /// Say you have some text with movie names and their release years,
+    /// like "'Citizen Kane' (1941)". It'd be nice if we could search for text
+    /// looking like that, while also extracting the movie name and its release
+    /// year separately.
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"'([^']+)'\s+\((\d{4})\)").unwrap();
+    /// let text = b"Not my favorite movie: 'Citizen Kane' (1941).";
+    /// let caps = re.captures(text).unwrap();
+    /// assert_eq!(caps.get(1).unwrap().as_bytes(), &b"Citizen Kane"[..]);
+    /// assert_eq!(caps.get(2).unwrap().as_bytes(), &b"1941"[..]);
+    /// assert_eq!(caps.get(0).unwrap().as_bytes(), &b"'Citizen Kane' (1941)"[..]);
+    /// // You can also access the groups by index using the Index notation.
+    /// // Note that this will panic on an invalid index.
+    /// assert_eq!(&caps[1], b"Citizen Kane");
+    /// assert_eq!(&caps[2], b"1941");
+    /// assert_eq!(&caps[0], b"'Citizen Kane' (1941)");
+    /// # }
+    /// ```
+    ///
+    /// Note that the full match is at capture group `0`. Each subsequent
+    /// capture group is indexed by the order of its opening `(`.
+    ///
+    /// We can make this example a bit clearer by using *named* capture groups:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)")
+    ///                .unwrap();
+    /// let text = b"Not my favorite movie: 'Citizen Kane' (1941).";
+    /// let caps = re.captures(text).unwrap();
+    /// assert_eq!(caps.name("title").unwrap().as_bytes(), b"Citizen Kane");
+    /// assert_eq!(caps.name("year").unwrap().as_bytes(), b"1941");
+    /// assert_eq!(caps.get(0).unwrap().as_bytes(), &b"'Citizen Kane' (1941)"[..]);
+    /// // You can also access the groups by name using the Index notation.
+    /// // Note that this will panic on an invalid group name.
+    /// assert_eq!(&caps["title"], b"Citizen Kane");
+    /// assert_eq!(&caps["year"], b"1941");
+    /// assert_eq!(&caps[0], b"'Citizen Kane' (1941)");
+    ///
+    /// # }
+    /// ```
+    ///
+    /// Here we name the capture groups, which we can access with the `name`
+    /// method or the `Index` notation with a `&str`. Note that the named
+    /// capture groups are still accessible with `get` or the `Index` notation
+    /// with a `usize`.
+    ///
+    /// The `0`th capture group is always unnamed, so it must always be
+    /// accessed with `get(0)` or `[0]`.
+    pub fn captures<'t>(&self, text: &'t [u8]) -> Option<Captures<'t>> {
+        let mut locs = self.capture_locations();
+        self.captures_read_at(&mut locs, text, 0).map(move |_| Captures {
+            text: text,
+            locs: locs.0,
+            named_groups: self.0.capture_name_idx().clone(),
+        })
+    }
+
+    /// Returns an iterator over all the non-overlapping capture groups matched
+    /// in `text`. This is operationally the same as `find_iter`, except it
+    /// yields information about capturing group matches.
+    ///
+    /// # Example
+    ///
+    /// We can use this to find all movie titles and their release years in
+    /// some text, where the movie is formatted like "'Title' (xxxx)":
+    ///
+    /// ```rust
+    /// # extern crate regex; use std::str; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)")
+    ///                .unwrap();
+    /// let text = b"'Citizen Kane' (1941), 'The Wizard of Oz' (1939), 'M' (1931).";
+    /// for caps in re.captures_iter(text) {
+    ///     let title = str::from_utf8(&caps["title"]).unwrap();
+    ///     let year = str::from_utf8(&caps["year"]).unwrap();
+    ///     println!("Movie: {:?}, Released: {:?}", title, year);
+    /// }
+    /// // Output:
+    /// // Movie: Citizen Kane, Released: 1941
+    /// // Movie: The Wizard of Oz, Released: 1939
+    /// // Movie: M, Released: 1931
+    /// # }
+    /// ```
+    pub fn captures_iter<'r, 't>(
+        &'r self,
+        text: &'t [u8],
+    ) -> CaptureMatches<'r, 't> {
+        CaptureMatches(self.0.searcher().captures_iter(text))
+    }
+
+    /// Returns an iterator of substrings of `text` delimited by a match of the
+    /// regular expression. Namely, each element of the iterator corresponds to
+    /// text that *isn't* matched by the regular expression.
+    ///
+    /// This method will *not* copy the text given.
+    ///
+    /// # Example
+    ///
+    /// To split a string delimited by arbitrary amounts of spaces or tabs:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"[ \t]+").unwrap();
+    /// let fields: Vec<&[u8]> = re.split(b"a b \t  c\td    e").collect();
+    /// assert_eq!(fields, vec![
+    ///     &b"a"[..], &b"b"[..], &b"c"[..], &b"d"[..], &b"e"[..],
+    /// ]);
+    /// # }
+    /// ```
+    pub fn split<'r, 't>(&'r self, text: &'t [u8]) -> Split<'r, 't> {
+        Split { finder: self.find_iter(text), last: 0 }
+    }
+
+    /// Returns an iterator of at most `limit` substrings of `text` delimited
+    /// by a match of the regular expression. (A `limit` of `0` will return no
+    /// substrings.) Namely, each element of the iterator corresponds to text
+    /// that *isn't* matched by the regular expression. The remainder of the
+    /// string that is not split will be the last element in the iterator.
+    ///
+    /// This method will *not* copy the text given.
+    ///
+    /// # Example
+    ///
+    /// Get the first two words in some text:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"\W+").unwrap();
+    /// let fields: Vec<&[u8]> = re.splitn(b"Hey! How are you?", 3).collect();
+    /// assert_eq!(fields, vec![&b"Hey"[..], &b"How"[..], &b"are you?"[..]]);
+    /// # }
+    /// ```
+    pub fn splitn<'r, 't>(
+        &'r self,
+        text: &'t [u8],
+        limit: usize,
+    ) -> SplitN<'r, 't> {
+        SplitN { splits: self.split(text), n: limit }
+    }
+
+    /// Replaces the leftmost-first match with the replacement provided. The
+    /// replacement can be a regular byte string (where `$N` and `$name` are
+    /// expanded to match capture groups) or a function that takes the matches'
+    /// `Captures` and returns the replaced byte string.
+    ///
+    /// If no match is found, then a copy of the byte string is returned
+    /// unchanged.
+    ///
+    /// # Replacement string syntax
+    ///
+    /// All instances of `$name` in the replacement text is replaced with the
+    /// corresponding capture group `name`.
+    ///
+    /// `name` may be an integer corresponding to the index of the
+    /// capture group (counted by order of opening parenthesis where `0` is the
+    /// entire match) or it can be a name (consisting of letters, digits or
+    /// underscores) corresponding to a named capture group.
+    ///
+    /// If `name` isn't a valid capture group (whether the name doesn't exist
+    /// or isn't a valid index), then it is replaced with the empty string.
+    ///
+    /// The longest possible name is used. e.g., `$1a` looks up the capture
+    /// group named `1a` and not the capture group at index `1`. To exert more
+    /// precise control over the name, use braces, e.g., `${1}a`.
+    ///
+    /// To write a literal `$` use `$$`.
+    ///
+    /// # Examples
+    ///
+    /// Note that this function is polymorphic with respect to the replacement.
+    /// In typical usage, this can just be a normal byte string:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new("[^01]+").unwrap();
+    /// assert_eq!(re.replace(b"1078910", &b""[..]), &b"1010"[..]);
+    /// # }
+    /// ```
+    ///
+    /// But anything satisfying the `Replacer` trait will work. For example, a
+    /// closure of type `|&Captures| -> Vec<u8>` provides direct access to the
+    /// captures corresponding to a match. This allows one to access capturing
+    /// group matches easily:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # use regex::bytes::Captures; fn main() {
+    /// let re = Regex::new(r"([^,\s]+),\s+(\S+)").unwrap();
+    /// let result = re.replace(b"Springsteen, Bruce", |caps: &Captures| {
+    ///     let mut replacement = caps[2].to_owned();
+    ///     replacement.push(b' ');
+    ///     replacement.extend(&caps[1]);
+    ///     replacement
+    /// });
+    /// assert_eq!(result, &b"Bruce Springsteen"[..]);
+    /// # }
+    /// ```
+    ///
+    /// But this is a bit cumbersome to use all the time. Instead, a simple
+    /// syntax is supported that expands `$name` into the corresponding capture
+    /// group. Here's the last example, but using this expansion technique
+    /// with named capture groups:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"(?P<last>[^,\s]+),\s+(?P<first>\S+)").unwrap();
+    /// let result = re.replace(b"Springsteen, Bruce", &b"$first $last"[..]);
+    /// assert_eq!(result, &b"Bruce Springsteen"[..]);
+    /// # }
+    /// ```
+    ///
+    /// Note that using `$2` instead of `$first` or `$1` instead of `$last`
+    /// would produce the same result. To write a literal `$` use `$$`.
+    ///
+    /// Sometimes the replacement string requires use of curly braces to
+    /// delineate a capture group replacement and surrounding literal text.
+    /// For example, if we wanted to join two words together with an
+    /// underscore:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"(?P<first>\w+)\s+(?P<second>\w+)").unwrap();
+    /// let result = re.replace(b"deep fried", &b"${first}_$second"[..]);
+    /// assert_eq!(result, &b"deep_fried"[..]);
+    /// # }
+    /// ```
+    ///
+    /// Without the curly braces, the capture group name `first_` would be
+    /// used, and since it doesn't exist, it would be replaced with the empty
+    /// string.
+    ///
+    /// Finally, sometimes you just want to replace a literal string with no
+    /// regard for capturing group expansion. This can be done by wrapping a
+    /// byte string with `NoExpand`:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// use regex::bytes::NoExpand;
+    ///
+    /// let re = Regex::new(r"(?P<last>[^,\s]+),\s+(\S+)").unwrap();
+    /// let result = re.replace(b"Springsteen, Bruce", NoExpand(b"$2 $last"));
+    /// assert_eq!(result, &b"$2 $last"[..]);
+    /// # }
+    /// ```
+    pub fn replace<'t, R: Replacer>(
+        &self,
+        text: &'t [u8],
+        rep: R,
+    ) -> Cow<'t, [u8]> {
+        self.replacen(text, 1, rep)
+    }
+
+    /// Replaces all non-overlapping matches in `text` with the replacement
+    /// provided. This is the same as calling `replacen` with `limit` set to
+    /// `0`.
+    ///
+    /// See the documentation for `replace` for details on how to access
+    /// capturing group matches in the replacement text.
+    pub fn replace_all<'t, R: Replacer>(
+        &self,
+        text: &'t [u8],
+        rep: R,
+    ) -> Cow<'t, [u8]> {
+        self.replacen(text, 0, rep)
+    }
+
+    /// Replaces at most `limit` non-overlapping matches in `text` with the
+    /// replacement provided. If `limit` is 0, then all non-overlapping matches
+    /// are replaced.
+    ///
+    /// See the documentation for `replace` for details on how to access
+    /// capturing group matches in the replacement text.
+    pub fn replacen<'t, R: Replacer>(
+        &self,
+        text: &'t [u8],
+        limit: usize,
+        mut rep: R,
+    ) -> Cow<'t, [u8]> {
+        if let Some(rep) = rep.no_expansion() {
+            let mut it = self.find_iter(text).enumerate().peekable();
+            if it.peek().is_none() {
+                return Cow::Borrowed(text);
+            }
+            let mut new = Vec::with_capacity(text.len());
+            let mut last_match = 0;
+            for (i, m) in it {
+                if limit > 0 && i >= limit {
+                    break;
+                }
+                new.extend_from_slice(&text[last_match..m.start()]);
+                new.extend_from_slice(&rep);
+                last_match = m.end();
+            }
+            new.extend_from_slice(&text[last_match..]);
+            return Cow::Owned(new);
+        }
+
+        // The slower path, which we use if the replacement needs access to
+        // capture groups.
+        let mut it = self.captures_iter(text).enumerate().peekable();
+        if it.peek().is_none() {
+            return Cow::Borrowed(text);
+        }
+        let mut new = Vec::with_capacity(text.len());
+        let mut last_match = 0;
+        for (i, cap) in it {
+            if limit > 0 && i >= limit {
+                break;
+            }
+            // unwrap on 0 is OK because captures only reports matches
+            let m = cap.get(0).unwrap();
+            new.extend_from_slice(&text[last_match..m.start()]);
+            rep.replace_append(&cap, &mut new);
+            last_match = m.end();
+        }
+        new.extend_from_slice(&text[last_match..]);
+        Cow::Owned(new)
+    }
+}
+
+/// Advanced or "lower level" search methods.
+impl Regex {
+    /// Returns the end location of a match in the text given.
+    ///
+    /// This method may have the same performance characteristics as
+    /// `is_match`, except it provides an end location for a match. In
+    /// particular, the location returned *may be shorter* than the proper end
+    /// of the leftmost-first match.
+    ///
+    /// # Example
+    ///
+    /// Typically, `a+` would match the entire first sequence of `a` in some
+    /// text, but `shortest_match` can give up as soon as it sees the first
+    /// `a`.
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let text = b"aaaaa";
+    /// let pos = Regex::new(r"a+").unwrap().shortest_match(text);
+    /// assert_eq!(pos, Some(1));
+    /// # }
+    /// ```
+    pub fn shortest_match(&self, text: &[u8]) -> Option<usize> {
+        self.shortest_match_at(text, 0)
+    }
+
+    /// Returns the same as shortest_match, but starts the search at the given
+    /// offset.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    pub fn shortest_match_at(
+        &self,
+        text: &[u8],
+        start: usize,
+    ) -> Option<usize> {
+        self.0.searcher().shortest_match_at(text, start)
+    }
+
+    /// Returns the same as is_match, but starts the search at the given
+    /// offset.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    pub fn is_match_at(&self, text: &[u8], start: usize) -> bool {
+        self.shortest_match_at(text, start).is_some()
+    }
+
+    /// Returns the same as find, but starts the search at the given
+    /// offset.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    pub fn find_at<'t>(
+        &self,
+        text: &'t [u8],
+        start: usize,
+    ) -> Option<Match<'t>> {
+        self.0
+            .searcher()
+            .find_at(text, start)
+            .map(|(s, e)| Match::new(text, s, e))
+    }
+
+    /// This is like `captures`, but uses
+    /// [`CaptureLocations`](struct.CaptureLocations.html)
+    /// instead of
+    /// [`Captures`](struct.Captures.html) in order to amortize allocations.
+    ///
+    /// To create a `CaptureLocations` value, use the
+    /// `Regex::capture_locations` method.
+    ///
+    /// This returns the overall match if this was successful, which is always
+    /// equivalence to the `0`th capture group.
+    pub fn captures_read<'t>(
+        &self,
+        locs: &mut CaptureLocations,
+        text: &'t [u8],
+    ) -> Option<Match<'t>> {
+        self.captures_read_at(locs, text, 0)
+    }
+
+    /// Returns the same as `captures_read`, but starts the search at the given
+    /// offset and populates the capture locations given.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    pub fn captures_read_at<'t>(
+        &self,
+        locs: &mut CaptureLocations,
+        text: &'t [u8],
+        start: usize,
+    ) -> Option<Match<'t>> {
+        self.0
+            .searcher()
+            .captures_read_at(&mut locs.0, text, start)
+            .map(|(s, e)| Match::new(text, s, e))
+    }
+
+    /// An undocumented alias for `captures_read_at`.
+    ///
+    /// The `regex-capi` crate previously used this routine, so to avoid
+    /// breaking that crate, we continue to provide the name as an undocumented
+    /// alias.
+    #[doc(hidden)]
+    pub fn read_captures_at<'t>(
+        &self,
+        locs: &mut CaptureLocations,
+        text: &'t [u8],
+        start: usize,
+    ) -> Option<Match<'t>> {
+        self.captures_read_at(locs, text, start)
+    }
+}
+
+/// Auxiliary methods.
+impl Regex {
+    /// Returns the original string of this regex.
+    pub fn as_str(&self) -> &str {
+        &self.0.regex_strings()[0]
+    }
+
+    /// Returns an iterator over the capture names.
+    pub fn capture_names(&self) -> CaptureNames {
+        CaptureNames(self.0.capture_names().iter())
+    }
+
+    /// Returns the number of captures.
+    pub fn captures_len(&self) -> usize {
+        self.0.capture_names().len()
+    }
+
+    /// Returns an empty set of capture locations that can be reused in
+    /// multiple calls to `captures_read` or `captures_read_at`.
+    pub fn capture_locations(&self) -> CaptureLocations {
+        CaptureLocations(self.0.searcher().locations())
+    }
+
+    /// An alias for `capture_locations` to preserve backward compatibility.
+    ///
+    /// The `regex-capi` crate uses this method, so to avoid breaking that
+    /// crate, we continue to export it as an undocumented API.
+    #[doc(hidden)]
+    pub fn locations(&self) -> CaptureLocations {
+        CaptureLocations(self.0.searcher().locations())
+    }
+}
+
+/// An iterator over all non-overlapping matches for a particular string.
+///
+/// The iterator yields a tuple of integers corresponding to the start and end
+/// of the match. The indices are byte offsets. The iterator stops when no more
+/// matches can be found.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the matched byte string.
+#[derive(Debug)]
+pub struct Matches<'r, 't>(re_trait::Matches<'t, ExecNoSync<'r>>);
+
+impl<'r, 't> Iterator for Matches<'r, 't> {
+    type Item = Match<'t>;
+
+    fn next(&mut self) -> Option<Match<'t>> {
+        let text = self.0.text();
+        self.0.next().map(|(s, e)| Match::new(text, s, e))
+    }
+}
+
+impl<'r, 't> FusedIterator for Matches<'r, 't> {}
+
+/// An iterator that yields all non-overlapping capture groups matching a
+/// particular regular expression.
+///
+/// The iterator stops when no more matches can be found.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the matched byte string.
+#[derive(Debug)]
+pub struct CaptureMatches<'r, 't>(
+    re_trait::CaptureMatches<'t, ExecNoSync<'r>>,
+);
+
+impl<'r, 't> Iterator for CaptureMatches<'r, 't> {
+    type Item = Captures<'t>;
+
+    fn next(&mut self) -> Option<Captures<'t>> {
+        self.0.next().map(|locs| Captures {
+            text: self.0.text(),
+            locs: locs,
+            named_groups: self.0.regex().capture_name_idx().clone(),
+        })
+    }
+}
+
+impl<'r, 't> FusedIterator for CaptureMatches<'r, 't> {}
+
+/// Yields all substrings delimited by a regular expression match.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the byte string being split.
+#[derive(Debug)]
+pub struct Split<'r, 't> {
+    finder: Matches<'r, 't>,
+    last: usize,
+}
+
+impl<'r, 't> Iterator for Split<'r, 't> {
+    type Item = &'t [u8];
+
+    fn next(&mut self) -> Option<&'t [u8]> {
+        let text = self.finder.0.text();
+        match self.finder.next() {
+            None => {
+                if self.last > text.len() {
+                    None
+                } else {
+                    let s = &text[self.last..];
+                    self.last = text.len() + 1; // Next call will return None
+                    Some(s)
+                }
+            }
+            Some(m) => {
+                let matched = &text[self.last..m.start()];
+                self.last = m.end();
+                Some(matched)
+            }
+        }
+    }
+}
+
+impl<'r, 't> FusedIterator for Split<'r, 't> {}
+
+/// Yields at most `N` substrings delimited by a regular expression match.
+///
+/// The last substring will be whatever remains after splitting.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the byte string being split.
+#[derive(Debug)]
+pub struct SplitN<'r, 't> {
+    splits: Split<'r, 't>,
+    n: usize,
+}
+
+impl<'r, 't> Iterator for SplitN<'r, 't> {
+    type Item = &'t [u8];
+
+    fn next(&mut self) -> Option<&'t [u8]> {
+        if self.n == 0 {
+            return None;
+        }
+
+        self.n -= 1;
+        if self.n > 0 {
+            return self.splits.next();
+        }
+
+        let text = self.splits.finder.0.text();
+        if self.splits.last > text.len() {
+            // We've already returned all substrings.
+            None
+        } else {
+            // self.n == 0, so future calls will return None immediately
+            Some(&text[self.splits.last..])
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (0, Some(self.n))
+    }
+}
+
+impl<'r, 't> FusedIterator for SplitN<'r, 't> {}
+
+/// An iterator over the names of all possible captures.
+///
+/// `None` indicates an unnamed capture; the first element (capture 0, the
+/// whole matched region) is always unnamed.
+///
+/// `'r` is the lifetime of the compiled regular expression.
+#[derive(Clone, Debug)]
+pub struct CaptureNames<'r>(::std::slice::Iter<'r, Option<String>>);
+
+impl<'r> Iterator for CaptureNames<'r> {
+    type Item = Option<&'r str>;
+
+    fn next(&mut self) -> Option<Option<&'r str>> {
+        self.0
+            .next()
+            .as_ref()
+            .map(|slot| slot.as_ref().map(|name| name.as_ref()))
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint()
+    }
+
+    fn count(self) -> usize {
+        self.0.count()
+    }
+}
+
+impl<'r> ExactSizeIterator for CaptureNames<'r> {}
+
+impl<'r> FusedIterator for CaptureNames<'r> {}
+
+/// CaptureLocations is a low level representation of the raw offsets of each
+/// submatch.
+///
+/// You can think of this as a lower level
+/// [`Captures`](struct.Captures.html), where this type does not support
+/// named capturing groups directly and it does not borrow the text that these
+/// offsets were matched on.
+///
+/// Primarily, this type is useful when using the lower level `Regex` APIs
+/// such as `read_captures`, which permits amortizing the allocation in which
+/// capture match locations are stored.
+///
+/// In order to build a value of this type, you'll need to call the
+/// `capture_locations` method on the `Regex` being used to execute the search.
+/// The value returned can then be reused in subsequent searches.
+#[derive(Clone, Debug)]
+pub struct CaptureLocations(re_trait::Locations);
+
+/// A type alias for `CaptureLocations` for backwards compatibility.
+///
+/// Previously, we exported `CaptureLocations` as `Locations` in an
+/// undocumented API. To prevent breaking that code (e.g., in `regex-capi`),
+/// we continue re-exporting the same undocumented API.
+#[doc(hidden)]
+pub type Locations = CaptureLocations;
+
+impl CaptureLocations {
+    /// Returns the start and end positions of the Nth capture group. Returns
+    /// `None` if `i` is not a valid capture group or if the capture group did
+    /// not match anything. The positions returned are *always* byte indices
+    /// with respect to the original string matched.
+    #[inline]
+    pub fn get(&self, i: usize) -> Option<(usize, usize)> {
+        self.0.pos(i)
+    }
+
+    /// Returns the total number of capturing groups.
+    ///
+    /// This is always at least `1` since every regex has at least `1`
+    /// capturing group that corresponds to the entire match.
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.0.len()
+    }
+
+    /// An alias for the `get` method for backwards compatibility.
+    ///
+    /// Previously, we exported `get` as `pos` in an undocumented API. To
+    /// prevent breaking that code (e.g., in `regex-capi`), we continue
+    /// re-exporting the same undocumented API.
+    #[doc(hidden)]
+    #[inline]
+    pub fn pos(&self, i: usize) -> Option<(usize, usize)> {
+        self.get(i)
+    }
+}
+
+/// Captures represents a group of captured byte strings for a single match.
+///
+/// The 0th capture always corresponds to the entire match. Each subsequent
+/// index corresponds to the next capture group in the regex. If a capture
+/// group is named, then the matched byte string is *also* available via the
+/// `name` method. (Note that the 0th capture is always unnamed and so must be
+/// accessed with the `get` method.)
+///
+/// Positions returned from a capture group are always byte indices.
+///
+/// `'t` is the lifetime of the matched text.
+pub struct Captures<'t> {
+    text: &'t [u8],
+    locs: re_trait::Locations,
+    named_groups: Arc<HashMap<String, usize>>,
+}
+
+impl<'t> Captures<'t> {
+    /// Returns the match associated with the capture group at index `i`. If
+    /// `i` does not correspond to a capture group, or if the capture group
+    /// did not participate in the match, then `None` is returned.
+    ///
+    /// # Examples
+    ///
+    /// Get the text of the match with a default of an empty string if this
+    /// group didn't participate in the match:
+    ///
+    /// ```rust
+    /// # use regex::bytes::Regex;
+    /// let re = Regex::new(r"[a-z]+(?:([0-9]+)|([A-Z]+))").unwrap();
+    /// let caps = re.captures(b"abc123").unwrap();
+    ///
+    /// let text1 = caps.get(1).map_or(&b""[..], |m| m.as_bytes());
+    /// let text2 = caps.get(2).map_or(&b""[..], |m| m.as_bytes());
+    /// assert_eq!(text1, &b"123"[..]);
+    /// assert_eq!(text2, &b""[..]);
+    /// ```
+    pub fn get(&self, i: usize) -> Option<Match<'t>> {
+        self.locs.pos(i).map(|(s, e)| Match::new(self.text, s, e))
+    }
+
+    /// Returns the match for the capture group named `name`. If `name` isn't a
+    /// valid capture group or didn't match anything, then `None` is returned.
+    pub fn name(&self, name: &str) -> Option<Match<'t>> {
+        self.named_groups.get(name).and_then(|&i| self.get(i))
+    }
+
+    /// An iterator that yields all capturing matches in the order in which
+    /// they appear in the regex. If a particular capture group didn't
+    /// participate in the match, then `None` is yielded for that capture.
+    ///
+    /// The first match always corresponds to the overall match of the regex.
+    pub fn iter<'c>(&'c self) -> SubCaptureMatches<'c, 't> {
+        SubCaptureMatches { caps: self, it: self.locs.iter() }
+    }
+
+    /// Expands all instances of `$name` in `replacement` to the corresponding
+    /// capture group `name`, and writes them to the `dst` buffer given.
+    ///
+    /// `name` may be an integer corresponding to the index of the capture
+    /// group (counted by order of opening parenthesis where `0` is the
+    /// entire match) or it can be a name (consisting of letters, digits or
+    /// underscores) corresponding to a named capture group.
+    ///
+    /// If `name` isn't a valid capture group (whether the name doesn't exist
+    /// or isn't a valid index), then it is replaced with the empty string.
+    ///
+    /// The longest possible name consisting of the characters `[_0-9A-Za-z]`
+    /// is used. e.g., `$1a` looks up the capture group named `1a` and not the
+    /// capture group at index `1`. To exert more precise control over the
+    /// name, or to refer to a capture group name that uses characters outside
+    /// of `[_0-9A-Za-z]`, use braces, e.g., `${1}a` or `${foo[bar].baz}`. When
+    /// using braces, any sequence of valid UTF-8 bytes is permitted. If the
+    /// sequence does not refer to a capture group name in the corresponding
+    /// regex, then it is replaced with an empty string.
+    ///
+    /// To write a literal `$` use `$$`.
+    pub fn expand(&self, replacement: &[u8], dst: &mut Vec<u8>) {
+        expand_bytes(self, replacement, dst)
+    }
+
+    /// Returns the number of captured groups.
+    ///
+    /// This is always at least `1`, since every regex has at least one capture
+    /// group that corresponds to the full match.
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.locs.len()
+    }
+}
+
+impl<'t> fmt::Debug for Captures<'t> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("Captures").field(&CapturesDebug(self)).finish()
+    }
+}
+
+struct CapturesDebug<'c, 't: 'c>(&'c Captures<'t>);
+
+impl<'c, 't> fmt::Debug for CapturesDebug<'c, 't> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn escape_bytes(bytes: &[u8]) -> String {
+            let mut s = String::new();
+            for &b in bytes {
+                s.push_str(&escape_byte(b));
+            }
+            s
+        }
+
+        fn escape_byte(byte: u8) -> String {
+            use std::ascii::escape_default;
+
+            let escaped: Vec<u8> = escape_default(byte).collect();
+            String::from_utf8_lossy(&escaped).into_owned()
+        }
+
+        // We'd like to show something nice here, even if it means an
+        // allocation to build a reverse index.
+        let slot_to_name: HashMap<&usize, &String> =
+            self.0.named_groups.iter().map(|(a, b)| (b, a)).collect();
+        let mut map = f.debug_map();
+        for (slot, m) in self.0.locs.iter().enumerate() {
+            let m = m.map(|(s, e)| escape_bytes(&self.0.text[s..e]));
+            if let Some(name) = slot_to_name.get(&slot) {
+                map.entry(&name, &m);
+            } else {
+                map.entry(&slot, &m);
+            }
+        }
+        map.finish()
+    }
+}
+
+/// Get a group by index.
+///
+/// `'t` is the lifetime of the matched text.
+///
+/// The text can't outlive the `Captures` object if this method is
+/// used, because of how `Index` is defined (normally `a[i]` is part
+/// of `a` and can't outlive it); to do that, use `get()` instead.
+///
+/// # Panics
+///
+/// If there is no group at the given index.
+impl<'t> Index<usize> for Captures<'t> {
+    type Output = [u8];
+
+    fn index(&self, i: usize) -> &[u8] {
+        self.get(i)
+            .map(|m| m.as_bytes())
+            .unwrap_or_else(|| panic!("no group at index '{}'", i))
+    }
+}
+
+/// Get a group by name.
+///
+/// `'t` is the lifetime of the matched text and `'i` is the lifetime
+/// of the group name (the index).
+///
+/// The text can't outlive the `Captures` object if this method is
+/// used, because of how `Index` is defined (normally `a[i]` is part
+/// of `a` and can't outlive it); to do that, use `name` instead.
+///
+/// # Panics
+///
+/// If there is no group named by the given value.
+impl<'t, 'i> Index<&'i str> for Captures<'t> {
+    type Output = [u8];
+
+    fn index<'a>(&'a self, name: &'i str) -> &'a [u8] {
+        self.name(name)
+            .map(|m| m.as_bytes())
+            .unwrap_or_else(|| panic!("no group named '{}'", name))
+    }
+}
+
+/// An iterator that yields all capturing matches in the order in which they
+/// appear in the regex.
+///
+/// If a particular capture group didn't participate in the match, then `None`
+/// is yielded for that capture. The first match always corresponds to the
+/// overall match of the regex.
+///
+/// The lifetime `'c` corresponds to the lifetime of the `Captures` value, and
+/// the lifetime `'t` corresponds to the originally matched text.
+#[derive(Clone, Debug)]
+pub struct SubCaptureMatches<'c, 't: 'c> {
+    caps: &'c Captures<'t>,
+    it: SubCapturesPosIter<'c>,
+}
+
+impl<'c, 't> Iterator for SubCaptureMatches<'c, 't> {
+    type Item = Option<Match<'t>>;
+
+    fn next(&mut self) -> Option<Option<Match<'t>>> {
+        self.it
+            .next()
+            .map(|cap| cap.map(|(s, e)| Match::new(self.caps.text, s, e)))
+    }
+}
+
+impl<'c, 't> FusedIterator for SubCaptureMatches<'c, 't> {}
+
+/// Replacer describes types that can be used to replace matches in a byte
+/// string.
+///
+/// In general, users of this crate shouldn't need to implement this trait,
+/// since implementations are already provided for `&[u8]` along with other
+/// variants of bytes types and `FnMut(&Captures) -> Vec<u8>` (or any
+/// `FnMut(&Captures) -> T` where `T: AsRef<[u8]>`), which covers most use cases.
+pub trait Replacer {
+    /// Appends text to `dst` to replace the current match.
+    ///
+    /// The current match is represented by `caps`, which is guaranteed to
+    /// have a match at capture group `0`.
+    ///
+    /// For example, a no-op replacement would be
+    /// `dst.extend(&caps[0])`.
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>);
+
+    /// Return a fixed unchanging replacement byte string.
+    ///
+    /// When doing replacements, if access to `Captures` is not needed (e.g.,
+    /// the replacement byte string does not need `$` expansion), then it can
+    /// be beneficial to avoid finding sub-captures.
+    ///
+    /// In general, this is called once for every call to `replacen`.
+    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
+        None
+    }
+
+    /// Return a `Replacer` that borrows and wraps this `Replacer`.
+    ///
+    /// This is useful when you want to take a generic `Replacer` (which might
+    /// not be cloneable) and use it without consuming it, so it can be used
+    /// more than once.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use regex::bytes::{Regex, Replacer};
+    ///
+    /// fn replace_all_twice<R: Replacer>(
+    ///     re: Regex,
+    ///     src: &[u8],
+    ///     mut rep: R,
+    /// ) -> Vec<u8> {
+    ///     let dst = re.replace_all(src, rep.by_ref());
+    ///     let dst = re.replace_all(&dst, rep.by_ref());
+    ///     dst.into_owned()
+    /// }
+    /// ```
+    fn by_ref<'r>(&'r mut self) -> ReplacerRef<'r, Self> {
+        ReplacerRef(self)
+    }
+}
+
+/// By-reference adaptor for a `Replacer`
+///
+/// Returned by [`Replacer::by_ref`](trait.Replacer.html#method.by_ref).
+#[derive(Debug)]
+pub struct ReplacerRef<'a, R: ?Sized + 'a>(&'a mut R);
+
+impl<'a, R: Replacer + ?Sized + 'a> Replacer for ReplacerRef<'a, R> {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
+        self.0.replace_append(caps, dst)
+    }
+    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
+        self.0.no_expansion()
+    }
+}
+
+impl<'a> Replacer for &'a [u8] {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
+        caps.expand(*self, dst);
+    }
+
+    fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
+        no_expansion(self)
+    }
+}
+
+impl<'a> Replacer for &'a Vec<u8> {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
+        caps.expand(*self, dst);
+    }
+
+    fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
+        no_expansion(self)
+    }
+}
+
+impl Replacer for Vec<u8> {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
+        caps.expand(self, dst);
+    }
+
+    fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
+        no_expansion(self)
+    }
+}
+
+impl<'a> Replacer for Cow<'a, [u8]> {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
+        caps.expand(self.as_ref(), dst);
+    }
+
+    fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
+        no_expansion(self)
+    }
+}
+
+impl<'a> Replacer for &'a Cow<'a, [u8]> {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
+        caps.expand(self.as_ref(), dst);
+    }
+
+    fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
+        no_expansion(self)
+    }
+}
+
+fn no_expansion<T: AsRef<[u8]>>(t: &T) -> Option<Cow<[u8]>> {
+    let s = t.as_ref();
+    match find_byte(b'$', s) {
+        Some(_) => None,
+        None => Some(Cow::Borrowed(s)),
+    }
+}
+
+impl<F, T> Replacer for F
+where
+    F: FnMut(&Captures) -> T,
+    T: AsRef<[u8]>,
+{
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
+        dst.extend_from_slice((*self)(caps).as_ref());
+    }
+}
+
+/// `NoExpand` indicates literal byte string replacement.
+///
+/// It can be used with `replace` and `replace_all` to do a literal byte string
+/// replacement without expanding `$name` to their corresponding capture
+/// groups. This can be both convenient (to avoid escaping `$`, for example)
+/// and performant (since capture groups don't need to be found).
+///
+/// `'t` is the lifetime of the literal text.
+#[derive(Clone, Debug)]
+pub struct NoExpand<'t>(pub &'t [u8]);
+
+impl<'t> Replacer for NoExpand<'t> {
+    fn replace_append(&mut self, _: &Captures, dst: &mut Vec<u8>) {
+        dst.extend_from_slice(self.0);
+    }
+
+    fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
+        Some(Cow::Borrowed(self.0))
+    }
+}
diff --git a/vendor/regex-1.4.6/src/re_set.rs b/vendor/regex-1.4.6/src/re_set.rs
new file mode 100644 (file)
index 0000000..5cb47ad
--- /dev/null
@@ -0,0 +1,475 @@
+macro_rules! define_set {
+    ($name:ident, $builder_mod:ident, $text_ty:ty, $as_bytes:expr,
+     $(#[$doc_regexset_example:meta])* ) => {
+        pub mod $name {
+            use std::fmt;
+            use std::iter;
+            use std::slice;
+            use std::vec;
+
+            use error::Error;
+            use exec::Exec;
+            use re_builder::$builder_mod::RegexSetBuilder;
+            use re_trait::RegularExpression;
+
+/// Match multiple (possibly overlapping) regular expressions in a single scan.
+///
+/// A regex set corresponds to the union of two or more regular expressions.
+/// That is, a regex set will match text where at least one of its
+/// constituent regular expressions matches. A regex set as its formulated here
+/// provides a touch more power: it will also report *which* regular
+/// expressions in the set match. Indeed, this is the key difference between
+/// regex sets and a single `Regex` with many alternates, since only one
+/// alternate can match at a time.
+///
+/// For example, consider regular expressions to match email addresses and
+/// domains: `[a-z]+@[a-z]+\.(com|org|net)` and `[a-z]+\.(com|org|net)`. If a
+/// regex set is constructed from those regexes, then searching the text
+/// `foo@example.com` will report both regexes as matching. Of course, one
+/// could accomplish this by compiling each regex on its own and doing two
+/// searches over the text. The key advantage of using a regex set is that it
+/// will report the matching regexes using a *single pass through the text*.
+/// If one has hundreds or thousands of regexes to match repeatedly (like a URL
+/// router for a complex web application or a user agent matcher), then a regex
+/// set can realize huge performance gains.
+///
+/// # Example
+///
+/// This shows how the above two regexes (for matching email addresses and
+/// domains) might work:
+///
+$(#[$doc_regexset_example])*
+///
+/// Note that it would be possible to adapt the above example to using `Regex`
+/// with an expression like:
+///
+/// ```text
+/// (?P<email>[a-z]+@(?P<email_domain>[a-z]+[.](com|org|net)))|(?P<domain>[a-z]+[.](com|org|net))
+/// ```
+///
+/// After a match, one could then inspect the capture groups to figure out
+/// which alternates matched. The problem is that it is hard to make this
+/// approach scale when there are many regexes since the overlap between each
+/// alternate isn't always obvious to reason about.
+///
+/// # Limitations
+///
+/// Regex sets are limited to answering the following two questions:
+///
+/// 1. Does any regex in the set match?
+/// 2. If so, which regexes in the set match?
+///
+/// As with the main `Regex` type, it is cheaper to ask (1) instead of (2)
+/// since the matching engines can stop after the first match is found.
+///
+/// Other features like finding the location of successive matches or their
+/// sub-captures aren't supported. If you need this functionality, the
+/// recommended approach is to compile each regex in the set independently and
+/// selectively match them based on which regexes in the set matched.
+///
+/// # Performance
+///
+/// A `RegexSet` has the same performance characteristics as `Regex`. Namely,
+/// search takes `O(mn)` time, where `m` is proportional to the size of the
+/// regex set and `n` is proportional to the length of the search text.
+#[derive(Clone)]
+pub struct RegexSet(Exec);
+
+impl RegexSet {
+    /// Create a new regex set with the given regular expressions.
+    ///
+    /// This takes an iterator of `S`, where `S` is something that can produce
+    /// a `&str`. If any of the strings in the iterator are not valid regular
+    /// expressions, then an error is returned.
+    ///
+    /// # Example
+    ///
+    /// Create a new regex set from an iterator of strings:
+    ///
+    /// ```rust
+    /// # use regex::RegexSet;
+    /// let set = RegexSet::new(&[r"\w+", r"\d+"]).unwrap();
+    /// assert!(set.is_match("foo"));
+    /// ```
+    pub fn new<I, S>(exprs: I) -> Result<RegexSet, Error>
+            where S: AsRef<str>, I: IntoIterator<Item=S> {
+        RegexSetBuilder::new(exprs).build()
+    }
+
+    /// Create a new empty regex set.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// # use regex::RegexSet;
+    /// let set = RegexSet::empty();
+    /// assert!(set.is_empty());
+    /// ```
+    pub fn empty() -> RegexSet {
+        RegexSetBuilder::new(&[""; 0]).build().unwrap()
+    }
+
+    /// Returns true if and only if one of the regexes in this set matches
+    /// the text given.
+    ///
+    /// This method should be preferred if you only need to test whether any
+    /// of the regexes in the set should match, but don't care about *which*
+    /// regexes matched. This is because the underlying matching engine will
+    /// quit immediately after seeing the first match instead of continuing to
+    /// find all matches.
+    ///
+    /// Note that as with searches using `Regex`, the expression is unanchored
+    /// by default. That is, if the regex does not start with `^` or `\A`, or
+    /// end with `$` or `\z`, then it is permitted to match anywhere in the
+    /// text.
+    ///
+    /// # Example
+    ///
+    /// Tests whether a set matches some text:
+    ///
+    /// ```rust
+    /// # use regex::RegexSet;
+    /// let set = RegexSet::new(&[r"\w+", r"\d+"]).unwrap();
+    /// assert!(set.is_match("foo"));
+    /// assert!(!set.is_match("☃"));
+    /// ```
+    pub fn is_match(&self, text: $text_ty) -> bool {
+        self.is_match_at(text, 0)
+    }
+
+    /// Returns the same as is_match, but starts the search at the given
+    /// offset.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    #[doc(hidden)]
+    pub fn is_match_at(&self, text: $text_ty, start: usize) -> bool {
+        self.0.searcher().is_match_at($as_bytes(text), start)
+    }
+
+    /// Returns the set of regular expressions that match in the given text.
+    ///
+    /// The set returned contains the index of each regular expression that
+    /// matches in the given text. The index is in correspondence with the
+    /// order of regular expressions given to `RegexSet`'s constructor.
+    ///
+    /// The set can also be used to iterate over the matched indices.
+    ///
+    /// Note that as with searches using `Regex`, the expression is unanchored
+    /// by default. That is, if the regex does not start with `^` or `\A`, or
+    /// end with `$` or `\z`, then it is permitted to match anywhere in the
+    /// text.
+    ///
+    /// # Example
+    ///
+    /// Tests which regular expressions match the given text:
+    ///
+    /// ```rust
+    /// # use regex::RegexSet;
+    /// let set = RegexSet::new(&[
+    ///     r"\w+",
+    ///     r"\d+",
+    ///     r"\pL+",
+    ///     r"foo",
+    ///     r"bar",
+    ///     r"barfoo",
+    ///     r"foobar",
+    /// ]).unwrap();
+    /// let matches: Vec<_> = set.matches("foobar").into_iter().collect();
+    /// assert_eq!(matches, vec![0, 2, 3, 4, 6]);
+    ///
+    /// // You can also test whether a particular regex matched:
+    /// let matches = set.matches("foobar");
+    /// assert!(!matches.matched(5));
+    /// assert!(matches.matched(6));
+    /// ```
+    pub fn matches(&self, text: $text_ty) -> SetMatches {
+        let mut matches = vec![false; self.0.regex_strings().len()];
+        let any = self.read_matches_at(&mut matches, text, 0);
+        SetMatches {
+            matched_any: any,
+            matches: matches,
+        }
+    }
+
+    /// Returns the same as matches, but starts the search at the given
+    /// offset and stores the matches into the slice given.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    ///
+    /// `matches` must have a length that is at least the number of regexes
+    /// in this set.
+    ///
+    /// This method returns true if and only if at least one member of
+    /// `matches` is true after executing the set against `text`.
+    #[doc(hidden)]
+    pub fn read_matches_at(
+        &self,
+        matches: &mut [bool],
+        text: $text_ty,
+        start: usize,
+    ) -> bool {
+        self.0.searcher().many_matches_at(matches, $as_bytes(text), start)
+    }
+
+    /// Returns the total number of regular expressions in this set.
+    pub fn len(&self) -> usize {
+        self.0.regex_strings().len()
+    }
+
+    /// Returns `true` if this set contains no regular expressions.
+    pub fn is_empty(&self) -> bool {
+        self.0.regex_strings().is_empty()
+    }
+
+    /// Returns the patterns that this set will match on.
+    ///
+    /// This function can be used to determine the pattern for a match. The
+    /// slice returned has exactly as many patterns givens to this regex set,
+    /// and the order of the slice is the same as the order of the patterns
+    /// provided to the set.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// # use regex::RegexSet;
+    /// let set = RegexSet::new(&[
+    ///     r"\w+",
+    ///     r"\d+",
+    ///     r"\pL+",
+    ///     r"foo",
+    ///     r"bar",
+    ///     r"barfoo",
+    ///     r"foobar",
+    /// ]).unwrap();
+    /// let matches: Vec<_> = set
+    ///     .matches("foobar")
+    ///     .into_iter()
+    ///     .map(|match_idx| &set.patterns()[match_idx])
+    ///     .collect();
+    /// assert_eq!(matches, vec![r"\w+", r"\pL+", r"foo", r"bar", r"foobar"]);
+    /// ```
+    pub fn patterns(&self) -> &[String] {
+        self.0.regex_strings()
+    }
+}
+
+/// A set of matches returned by a regex set.
+#[derive(Clone, Debug)]
+pub struct SetMatches {
+    matched_any: bool,
+    matches: Vec<bool>,
+}
+
+impl SetMatches {
+    /// Whether this set contains any matches.
+    pub fn matched_any(&self) -> bool {
+        self.matched_any
+    }
+
+    /// Whether the regex at the given index matched.
+    ///
+    /// The index for a regex is determined by its insertion order upon the
+    /// initial construction of a `RegexSet`, starting at `0`.
+    ///
+    /// # Panics
+    ///
+    /// If `regex_index` is greater than or equal to `self.len()`.
+    pub fn matched(&self, regex_index: usize) -> bool {
+        self.matches[regex_index]
+    }
+
+    /// The total number of regexes in the set that created these matches.
+    pub fn len(&self) -> usize {
+        self.matches.len()
+    }
+
+    /// Returns an iterator over indexes in the regex that matched.
+    ///
+    /// This will always produces matches in ascending order of index, where
+    /// the index corresponds to the index of the regex that matched with
+    /// respect to its position when initially building the set.
+    pub fn iter(&self) -> SetMatchesIter {
+        SetMatchesIter((&*self.matches).into_iter().enumerate())
+    }
+}
+
+impl IntoIterator for SetMatches {
+    type IntoIter = SetMatchesIntoIter;
+    type Item = usize;
+
+    fn into_iter(self) -> Self::IntoIter {
+        SetMatchesIntoIter(self.matches.into_iter().enumerate())
+    }
+}
+
+impl<'a> IntoIterator for &'a SetMatches {
+    type IntoIter = SetMatchesIter<'a>;
+    type Item = usize;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter()
+    }
+}
+
+/// An owned iterator over the set of matches from a regex set.
+///
+/// This will always produces matches in ascending order of index, where the
+/// index corresponds to the index of the regex that matched with respect to
+/// its position when initially building the set.
+#[derive(Debug)]
+pub struct SetMatchesIntoIter(iter::Enumerate<vec::IntoIter<bool>>);
+
+impl Iterator for SetMatchesIntoIter {
+    type Item = usize;
+
+    fn next(&mut self) -> Option<usize> {
+        loop {
+            match self.0.next() {
+                None => return None,
+                Some((_, false)) => {}
+                Some((i, true)) => return Some(i),
+            }
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint()
+    }
+}
+
+impl DoubleEndedIterator for SetMatchesIntoIter {
+    fn next_back(&mut self) -> Option<usize> {
+        loop {
+            match self.0.next_back() {
+                None => return None,
+                Some((_, false)) => {}
+                Some((i, true)) => return Some(i),
+            }
+        }
+    }
+}
+
+impl iter::FusedIterator for SetMatchesIntoIter {}
+
+/// A borrowed iterator over the set of matches from a regex set.
+///
+/// The lifetime `'a` refers to the lifetime of a `SetMatches` value.
+///
+/// This will always produces matches in ascending order of index, where the
+/// index corresponds to the index of the regex that matched with respect to
+/// its position when initially building the set.
+#[derive(Clone, Debug)]
+pub struct SetMatchesIter<'a>(iter::Enumerate<slice::Iter<'a, bool>>);
+
+impl<'a> Iterator for SetMatchesIter<'a> {
+    type Item = usize;
+
+    fn next(&mut self) -> Option<usize> {
+        loop {
+            match self.0.next() {
+                None => return None,
+                Some((_, &false)) => {}
+                Some((i, &true)) => return Some(i),
+            }
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint()
+    }
+}
+
+impl<'a> DoubleEndedIterator for SetMatchesIter<'a> {
+    fn next_back(&mut self) -> Option<usize> {
+        loop {
+            match self.0.next_back() {
+                None => return None,
+                Some((_, &false)) => {}
+                Some((i, &true)) => return Some(i),
+            }
+        }
+    }
+}
+
+impl<'a> iter::FusedIterator for SetMatchesIter<'a> {}
+
+#[doc(hidden)]
+impl From<Exec> for RegexSet {
+    fn from(exec: Exec) -> Self {
+        RegexSet(exec)
+    }
+}
+
+impl fmt::Debug for RegexSet {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "RegexSet({:?})", self.0.regex_strings())
+    }
+}
+
+#[allow(dead_code)] fn as_bytes_str(text: &str) -> &[u8] { text.as_bytes() }
+#[allow(dead_code)] fn as_bytes_bytes(text: &[u8]) -> &[u8] { text }
+        }
+    }
+}
+
+define_set! {
+    unicode,
+    set_unicode,
+    &str,
+    as_bytes_str,
+/// ```rust
+/// # use regex::RegexSet;
+/// let set = RegexSet::new(&[
+///     r"[a-z]+@[a-z]+\.(com|org|net)",
+///     r"[a-z]+\.(com|org|net)",
+/// ]).unwrap();
+///
+/// // Ask whether any regexes in the set match.
+/// assert!(set.is_match("foo@example.com"));
+///
+/// // Identify which regexes in the set match.
+/// let matches: Vec<_> = set.matches("foo@example.com").into_iter().collect();
+/// assert_eq!(vec![0, 1], matches);
+///
+/// // Try again, but with text that only matches one of the regexes.
+/// let matches: Vec<_> = set.matches("example.com").into_iter().collect();
+/// assert_eq!(vec![1], matches);
+///
+/// // Try again, but with text that doesn't match any regex in the set.
+/// let matches: Vec<_> = set.matches("example").into_iter().collect();
+/// assert!(matches.is_empty());
+/// ```
+}
+
+define_set! {
+    bytes,
+    set_bytes,
+    &[u8],
+    as_bytes_bytes,
+/// ```rust
+/// # use regex::bytes::RegexSet;
+/// let set = RegexSet::new(&[
+///     r"[a-z]+@[a-z]+\.(com|org|net)",
+///     r"[a-z]+\.(com|org|net)",
+/// ]).unwrap();
+///
+/// // Ask whether any regexes in the set match.
+/// assert!(set.is_match(b"foo@example.com"));
+///
+/// // Identify which regexes in the set match.
+/// let matches: Vec<_> = set.matches(b"foo@example.com").into_iter().collect();
+/// assert_eq!(vec![0, 1], matches);
+///
+/// // Try again, but with text that only matches one of the regexes.
+/// let matches: Vec<_> = set.matches(b"example.com").into_iter().collect();
+/// assert_eq!(vec![1], matches);
+///
+/// // Try again, but with text that doesn't match any regex in the set.
+/// let matches: Vec<_> = set.matches(b"example").into_iter().collect();
+/// assert!(matches.is_empty());
+/// ```
+}
diff --git a/vendor/regex-1.4.6/src/re_trait.rs b/vendor/regex-1.4.6/src/re_trait.rs
new file mode 100644 (file)
index 0000000..ea6be9c
--- /dev/null
@@ -0,0 +1,283 @@
+use std::fmt;
+use std::iter::FusedIterator;
+
+/// Slot is a single saved capture location. Note that there are two slots for
+/// every capture in a regular expression (one slot each for the start and end
+/// of the capture).
+pub type Slot = Option<usize>;
+
+/// Locations represents the offsets of each capturing group in a regex for
+/// a single match.
+///
+/// Unlike `Captures`, a `Locations` value only stores offsets.
+#[doc(hidden)]
+#[derive(Clone, Debug)]
+pub struct Locations(Vec<Slot>);
+
+impl Locations {
+    /// Returns the start and end positions of the Nth capture group. Returns
+    /// `None` if `i` is not a valid capture group or if the capture group did
+    /// not match anything. The positions returned are *always* byte indices
+    /// with respect to the original string matched.
+    pub fn pos(&self, i: usize) -> Option<(usize, usize)> {
+        let (s, e) = (i * 2, i * 2 + 1);
+        match (self.0.get(s), self.0.get(e)) {
+            (Some(&Some(s)), Some(&Some(e))) => Some((s, e)),
+            _ => None,
+        }
+    }
+
+    /// Creates an iterator of all the capture group positions in order of
+    /// appearance in the regular expression. Positions are byte indices
+    /// in terms of the original string matched.
+    pub fn iter(&self) -> SubCapturesPosIter {
+        SubCapturesPosIter { idx: 0, locs: self }
+    }
+
+    /// Returns the total number of capturing groups.
+    ///
+    /// This is always at least `1` since every regex has at least `1`
+    /// capturing group that corresponds to the entire match.
+    pub fn len(&self) -> usize {
+        self.0.len() / 2
+    }
+
+    /// Return the individual slots as a slice.
+    pub(crate) fn as_slots(&mut self) -> &mut [Slot] {
+        &mut self.0
+    }
+}
+
+/// An iterator over capture group positions for a particular match of a
+/// regular expression.
+///
+/// Positions are byte indices in terms of the original string matched.
+///
+/// `'c` is the lifetime of the captures.
+#[derive(Clone, Debug)]
+pub struct SubCapturesPosIter<'c> {
+    idx: usize,
+    locs: &'c Locations,
+}
+
+impl<'c> Iterator for SubCapturesPosIter<'c> {
+    type Item = Option<(usize, usize)>;
+
+    fn next(&mut self) -> Option<Option<(usize, usize)>> {
+        if self.idx >= self.locs.len() {
+            return None;
+        }
+        let x = match self.locs.pos(self.idx) {
+            None => Some(None),
+            Some((s, e)) => Some(Some((s, e))),
+        };
+        self.idx += 1;
+        x
+    }
+}
+
+impl<'c> FusedIterator for SubCapturesPosIter<'c> {}
+
+/// `RegularExpression` describes types that can implement regex searching.
+///
+/// This trait is my attempt at reducing code duplication and to standardize
+/// the internal API. Specific duplication that is avoided are the `find`
+/// and `capture` iterators, which are slightly tricky.
+///
+/// It's not clear whether this trait is worth it, and it also isn't
+/// clear whether it's useful as a public trait or not. Methods like
+/// `next_after_empty` reak of bad design, but the rest of the methods seem
+/// somewhat reasonable. One particular thing this trait would expose would be
+/// the ability to start the search of a regex anywhere in a haystack, which
+/// isn't possible in the current public API.
+pub trait RegularExpression: Sized + fmt::Debug {
+    /// The type of the haystack.
+    type Text: ?Sized + fmt::Debug;
+
+    /// The number of capture slots in the compiled regular expression. This is
+    /// always two times the number of capture groups (two slots per group).
+    fn slots_len(&self) -> usize;
+
+    /// Allocates fresh space for all capturing groups in this regex.
+    fn locations(&self) -> Locations {
+        Locations(vec![None; self.slots_len()])
+    }
+
+    /// Returns the position of the next character after `i`.
+    ///
+    /// For example, a haystack with type `&[u8]` probably returns `i+1`,
+    /// whereas a haystack with type `&str` probably returns `i` plus the
+    /// length of the next UTF-8 sequence.
+    fn next_after_empty(&self, text: &Self::Text, i: usize) -> usize;
+
+    /// Returns the location of the shortest match.
+    fn shortest_match_at(
+        &self,
+        text: &Self::Text,
+        start: usize,
+    ) -> Option<usize>;
+
+    /// Returns whether the regex matches the text given.
+    fn is_match_at(&self, text: &Self::Text, start: usize) -> bool;
+
+    /// Returns the leftmost-first match location if one exists.
+    fn find_at(
+        &self,
+        text: &Self::Text,
+        start: usize,
+    ) -> Option<(usize, usize)>;
+
+    /// Returns the leftmost-first match location if one exists, and also
+    /// fills in any matching capture slot locations.
+    fn captures_read_at(
+        &self,
+        locs: &mut Locations,
+        text: &Self::Text,
+        start: usize,
+    ) -> Option<(usize, usize)>;
+
+    /// Returns an iterator over all non-overlapping successive leftmost-first
+    /// matches.
+    fn find_iter(self, text: &Self::Text) -> Matches<Self> {
+        Matches { re: self, text: text, last_end: 0, last_match: None }
+    }
+
+    /// Returns an iterator over all non-overlapping successive leftmost-first
+    /// matches with captures.
+    fn captures_iter(self, text: &Self::Text) -> CaptureMatches<Self> {
+        CaptureMatches(self.find_iter(text))
+    }
+}
+
+/// An iterator over all non-overlapping successive leftmost-first matches.
+#[derive(Debug)]
+pub struct Matches<'t, R>
+where
+    R: RegularExpression,
+    R::Text: 't,
+{
+    re: R,
+    text: &'t R::Text,
+    last_end: usize,
+    last_match: Option<usize>,
+}
+
+impl<'t, R> Matches<'t, R>
+where
+    R: RegularExpression,
+    R::Text: 't,
+{
+    /// Return the text being searched.
+    pub fn text(&self) -> &'t R::Text {
+        self.text
+    }
+
+    /// Return the underlying regex.
+    pub fn regex(&self) -> &R {
+        &self.re
+    }
+}
+
+impl<'t, R> Iterator for Matches<'t, R>
+where
+    R: RegularExpression,
+    R::Text: 't + AsRef<[u8]>,
+{
+    type Item = (usize, usize);
+
+    fn next(&mut self) -> Option<(usize, usize)> {
+        if self.last_end > self.text.as_ref().len() {
+            return None;
+        }
+        let (s, e) = match self.re.find_at(self.text, self.last_end) {
+            None => return None,
+            Some((s, e)) => (s, e),
+        };
+        if s == e {
+            // This is an empty match. To ensure we make progress, start
+            // the next search at the smallest possible starting position
+            // of the next match following this one.
+            self.last_end = self.re.next_after_empty(self.text, e);
+            // Don't accept empty matches immediately following a match.
+            // Just move on to the next match.
+            if Some(e) == self.last_match {
+                return self.next();
+            }
+        } else {
+            self.last_end = e;
+        }
+        self.last_match = Some(e);
+        Some((s, e))
+    }
+}
+
+impl<'t, R> FusedIterator for Matches<'t, R>
+where
+    R: RegularExpression,
+    R::Text: 't + AsRef<[u8]>,
+{
+}
+
+/// An iterator over all non-overlapping successive leftmost-first matches with
+/// captures.
+#[derive(Debug)]
+pub struct CaptureMatches<'t, R>(Matches<'t, R>)
+where
+    R: RegularExpression,
+    R::Text: 't;
+
+impl<'t, R> CaptureMatches<'t, R>
+where
+    R: RegularExpression,
+    R::Text: 't,
+{
+    /// Return the text being searched.
+    pub fn text(&self) -> &'t R::Text {
+        self.0.text()
+    }
+
+    /// Return the underlying regex.
+    pub fn regex(&self) -> &R {
+        self.0.regex()
+    }
+}
+
+impl<'t, R> Iterator for CaptureMatches<'t, R>
+where
+    R: RegularExpression,
+    R::Text: 't + AsRef<[u8]>,
+{
+    type Item = Locations;
+
+    fn next(&mut self) -> Option<Locations> {
+        if self.0.last_end > self.0.text.as_ref().len() {
+            return None;
+        }
+        let mut locs = self.0.re.locations();
+        let (s, e) = match self.0.re.captures_read_at(
+            &mut locs,
+            self.0.text,
+            self.0.last_end,
+        ) {
+            None => return None,
+            Some((s, e)) => (s, e),
+        };
+        if s == e {
+            self.0.last_end = self.0.re.next_after_empty(self.0.text, e);
+            if Some(e) == self.0.last_match {
+                return self.next();
+            }
+        } else {
+            self.0.last_end = e;
+        }
+        self.0.last_match = Some(e);
+        Some(locs)
+    }
+}
+
+impl<'t, R> FusedIterator for CaptureMatches<'t, R>
+where
+    R: RegularExpression,
+    R::Text: 't + AsRef<[u8]>,
+{
+}
diff --git a/vendor/regex-1.4.6/src/re_unicode.rs b/vendor/regex-1.4.6/src/re_unicode.rs
new file mode 100644 (file)
index 0000000..1b478cd
--- /dev/null
@@ -0,0 +1,1302 @@
+use std::borrow::Cow;
+use std::collections::HashMap;
+use std::fmt;
+use std::iter::FusedIterator;
+use std::ops::{Index, Range};
+use std::str::FromStr;
+use std::sync::Arc;
+
+use find_byte::find_byte;
+use syntax;
+
+use error::Error;
+use exec::{Exec, ExecNoSyncStr};
+use expand::expand_str;
+use re_builder::unicode::RegexBuilder;
+use re_trait::{self, RegularExpression, SubCapturesPosIter};
+
+/// Escapes all regular expression meta characters in `text`.
+///
+/// The string returned may be safely used as a literal in a regular
+/// expression.
+pub fn escape(text: &str) -> String {
+    syntax::escape(text)
+}
+
+/// Match represents a single match of a regex in a haystack.
+///
+/// The lifetime parameter `'t` refers to the lifetime of the matched text.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct Match<'t> {
+    text: &'t str,
+    start: usize,
+    end: usize,
+}
+
+impl<'t> Match<'t> {
+    /// Returns the starting byte offset of the match in the haystack.
+    #[inline]
+    pub fn start(&self) -> usize {
+        self.start
+    }
+
+    /// Returns the ending byte offset of the match in the haystack.
+    #[inline]
+    pub fn end(&self) -> usize {
+        self.end
+    }
+
+    /// Returns the range over the starting and ending byte offsets of the
+    /// match in the haystack.
+    #[inline]
+    pub fn range(&self) -> Range<usize> {
+        self.start..self.end
+    }
+
+    /// Returns the matched text.
+    #[inline]
+    pub fn as_str(&self) -> &'t str {
+        &self.text[self.range()]
+    }
+
+    /// Creates a new match from the given haystack and byte offsets.
+    #[inline]
+    fn new(haystack: &'t str, start: usize, end: usize) -> Match<'t> {
+        Match { text: haystack, start: start, end: end }
+    }
+}
+
+impl<'t> From<Match<'t>> for &'t str {
+    fn from(m: Match<'t>) -> &'t str {
+        m.as_str()
+    }
+}
+
+impl<'t> From<Match<'t>> for Range<usize> {
+    fn from(m: Match<'t>) -> Range<usize> {
+        m.range()
+    }
+}
+
+/// A compiled regular expression for matching Unicode strings.
+///
+/// It is represented as either a sequence of bytecode instructions (dynamic)
+/// or as a specialized Rust function (native). It can be used to search, split
+/// or replace text. All searching is done with an implicit `.*?` at the
+/// beginning and end of an expression. To force an expression to match the
+/// whole string (or a prefix or a suffix), you must use an anchor like `^` or
+/// `$` (or `\A` and `\z`).
+///
+/// While this crate will handle Unicode strings (whether in the regular
+/// expression or in the search text), all positions returned are **byte
+/// indices**. Every byte index is guaranteed to be at a Unicode code point
+/// boundary.
+///
+/// The lifetimes `'r` and `'t` in this crate correspond to the lifetime of a
+/// compiled regular expression and text to search, respectively.
+///
+/// The only methods that allocate new strings are the string replacement
+/// methods. All other methods (searching and splitting) return borrowed
+/// pointers into the string given.
+///
+/// # Examples
+///
+/// Find the location of a US phone number:
+///
+/// ```rust
+/// # use regex::Regex;
+/// let re = Regex::new("[0-9]{3}-[0-9]{3}-[0-9]{4}").unwrap();
+/// let mat = re.find("phone: 111-222-3333").unwrap();
+/// assert_eq!((mat.start(), mat.end()), (7, 19));
+/// ```
+///
+/// # Using the `std::str::pattern` methods with `Regex`
+///
+/// > **Note**: This section requires that this crate is compiled with the
+/// > `pattern` Cargo feature enabled, which **requires nightly Rust**.
+///
+/// Since `Regex` implements `Pattern`, you can use regexes with methods
+/// defined on `&str`. For example, `is_match`, `find`, `find_iter`
+/// and `split` can be replaced with `str::contains`, `str::find`,
+/// `str::match_indices` and `str::split`.
+///
+/// Here are some examples:
+///
+/// ```rust,ignore
+/// # use regex::Regex;
+/// let re = Regex::new(r"\d+").unwrap();
+/// let haystack = "a111b222c";
+///
+/// assert!(haystack.contains(&re));
+/// assert_eq!(haystack.find(&re), Some(1));
+/// assert_eq!(haystack.match_indices(&re).collect::<Vec<_>>(),
+///            vec![(1, 4), (5, 8)]);
+/// assert_eq!(haystack.split(&re).collect::<Vec<_>>(), vec!["a", "b", "c"]);
+/// ```
+#[derive(Clone)]
+pub struct Regex(Exec);
+
+impl fmt::Display for Regex {
+    /// Shows the original regular expression.
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.as_str())
+    }
+}
+
+impl fmt::Debug for Regex {
+    /// Shows the original regular expression.
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self, f)
+    }
+}
+
+#[doc(hidden)]
+impl From<Exec> for Regex {
+    fn from(exec: Exec) -> Regex {
+        Regex(exec)
+    }
+}
+
+impl FromStr for Regex {
+    type Err = Error;
+
+    /// Attempts to parse a string into a regular expression
+    fn from_str(s: &str) -> Result<Regex, Error> {
+        Regex::new(s)
+    }
+}
+
+/// Core regular expression methods.
+impl Regex {
+    /// Compiles a regular expression. Once compiled, it can be used repeatedly
+    /// to search, split or replace text in a string.
+    ///
+    /// If an invalid expression is given, then an error is returned.
+    pub fn new(re: &str) -> Result<Regex, Error> {
+        RegexBuilder::new(re).build()
+    }
+
+    /// Returns true if and only if there is a match for the regex in the
+    /// string given.
+    ///
+    /// It is recommended to use this method if all you need to do is test
+    /// a match, since the underlying matching engine may be able to do less
+    /// work.
+    ///
+    /// # Example
+    ///
+    /// Test if some text contains at least one word with exactly 13
+    /// Unicode word characters:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let text = "I categorically deny having triskaidekaphobia.";
+    /// assert!(Regex::new(r"\b\w{13}\b").unwrap().is_match(text));
+    /// # }
+    /// ```
+    pub fn is_match(&self, text: &str) -> bool {
+        self.is_match_at(text, 0)
+    }
+
+    /// Returns the start and end byte range of the leftmost-first match in
+    /// `text`. If no match exists, then `None` is returned.
+    ///
+    /// Note that this should only be used if you want to discover the position
+    /// of the match. Testing the existence of a match is faster if you use
+    /// `is_match`.
+    ///
+    /// # Example
+    ///
+    /// Find the start and end location of the first word with exactly 13
+    /// Unicode word characters:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let text = "I categorically deny having triskaidekaphobia.";
+    /// let mat = Regex::new(r"\b\w{13}\b").unwrap().find(text).unwrap();
+    /// assert_eq!(mat.start(), 2);
+    /// assert_eq!(mat.end(), 15);
+    /// # }
+    /// ```
+    pub fn find<'t>(&self, text: &'t str) -> Option<Match<'t>> {
+        self.find_at(text, 0)
+    }
+
+    /// Returns an iterator for each successive non-overlapping match in
+    /// `text`, returning the start and end byte indices with respect to
+    /// `text`.
+    ///
+    /// # Example
+    ///
+    /// Find the start and end location of every word with exactly 13 Unicode
+    /// word characters:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let text = "Retroactively relinquishing remunerations is reprehensible.";
+    /// for mat in Regex::new(r"\b\w{13}\b").unwrap().find_iter(text) {
+    ///     println!("{:?}", mat);
+    /// }
+    /// # }
+    /// ```
+    pub fn find_iter<'r, 't>(&'r self, text: &'t str) -> Matches<'r, 't> {
+        Matches(self.0.searcher_str().find_iter(text))
+    }
+
+    /// Returns the capture groups corresponding to the leftmost-first
+    /// match in `text`. Capture group `0` always corresponds to the entire
+    /// match. If no match is found, then `None` is returned.
+    ///
+    /// You should only use `captures` if you need access to the location of
+    /// capturing group matches. Otherwise, `find` is faster for discovering
+    /// the location of the overall match.
+    ///
+    /// # Examples
+    ///
+    /// Say you have some text with movie names and their release years,
+    /// like "'Citizen Kane' (1941)". It'd be nice if we could search for text
+    /// looking like that, while also extracting the movie name and its release
+    /// year separately.
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"'([^']+)'\s+\((\d{4})\)").unwrap();
+    /// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
+    /// let caps = re.captures(text).unwrap();
+    /// assert_eq!(caps.get(1).unwrap().as_str(), "Citizen Kane");
+    /// assert_eq!(caps.get(2).unwrap().as_str(), "1941");
+    /// assert_eq!(caps.get(0).unwrap().as_str(), "'Citizen Kane' (1941)");
+    /// // You can also access the groups by index using the Index notation.
+    /// // Note that this will panic on an invalid index.
+    /// assert_eq!(&caps[1], "Citizen Kane");
+    /// assert_eq!(&caps[2], "1941");
+    /// assert_eq!(&caps[0], "'Citizen Kane' (1941)");
+    /// # }
+    /// ```
+    ///
+    /// Note that the full match is at capture group `0`. Each subsequent
+    /// capture group is indexed by the order of its opening `(`.
+    ///
+    /// We can make this example a bit clearer by using *named* capture groups:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)")
+    ///                .unwrap();
+    /// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
+    /// let caps = re.captures(text).unwrap();
+    /// assert_eq!(caps.name("title").unwrap().as_str(), "Citizen Kane");
+    /// assert_eq!(caps.name("year").unwrap().as_str(), "1941");
+    /// assert_eq!(caps.get(0).unwrap().as_str(), "'Citizen Kane' (1941)");
+    /// // You can also access the groups by name using the Index notation.
+    /// // Note that this will panic on an invalid group name.
+    /// assert_eq!(&caps["title"], "Citizen Kane");
+    /// assert_eq!(&caps["year"], "1941");
+    /// assert_eq!(&caps[0], "'Citizen Kane' (1941)");
+    ///
+    /// # }
+    /// ```
+    ///
+    /// Here we name the capture groups, which we can access with the `name`
+    /// method or the `Index` notation with a `&str`. Note that the named
+    /// capture groups are still accessible with `get` or the `Index` notation
+    /// with a `usize`.
+    ///
+    /// The `0`th capture group is always unnamed, so it must always be
+    /// accessed with `get(0)` or `[0]`.
+    pub fn captures<'t>(&self, text: &'t str) -> Option<Captures<'t>> {
+        let mut locs = self.capture_locations();
+        self.captures_read_at(&mut locs, text, 0).map(move |_| Captures {
+            text: text,
+            locs: locs.0,
+            named_groups: self.0.capture_name_idx().clone(),
+        })
+    }
+
+    /// Returns an iterator over all the non-overlapping capture groups matched
+    /// in `text`. This is operationally the same as `find_iter`, except it
+    /// yields information about capturing group matches.
+    ///
+    /// # Example
+    ///
+    /// We can use this to find all movie titles and their release years in
+    /// some text, where the movie is formatted like "'Title' (xxxx)":
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)")
+    ///                .unwrap();
+    /// let text = "'Citizen Kane' (1941), 'The Wizard of Oz' (1939), 'M' (1931).";
+    /// for caps in re.captures_iter(text) {
+    ///     println!("Movie: {:?}, Released: {:?}",
+    ///              &caps["title"], &caps["year"]);
+    /// }
+    /// // Output:
+    /// // Movie: Citizen Kane, Released: 1941
+    /// // Movie: The Wizard of Oz, Released: 1939
+    /// // Movie: M, Released: 1931
+    /// # }
+    /// ```
+    pub fn captures_iter<'r, 't>(
+        &'r self,
+        text: &'t str,
+    ) -> CaptureMatches<'r, 't> {
+        CaptureMatches(self.0.searcher_str().captures_iter(text))
+    }
+
+    /// Returns an iterator of substrings of `text` delimited by a match of the
+    /// regular expression. Namely, each element of the iterator corresponds to
+    /// text that *isn't* matched by the regular expression.
+    ///
+    /// This method will *not* copy the text given.
+    ///
+    /// # Example
+    ///
+    /// To split a string delimited by arbitrary amounts of spaces or tabs:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"[ \t]+").unwrap();
+    /// let fields: Vec<&str> = re.split("a b \t  c\td    e").collect();
+    /// assert_eq!(fields, vec!["a", "b", "c", "d", "e"]);
+    /// # }
+    /// ```
+    pub fn split<'r, 't>(&'r self, text: &'t str) -> Split<'r, 't> {
+        Split { finder: self.find_iter(text), last: 0 }
+    }
+
+    /// Returns an iterator of at most `limit` substrings of `text` delimited
+    /// by a match of the regular expression. (A `limit` of `0` will return no
+    /// substrings.) Namely, each element of the iterator corresponds to text
+    /// that *isn't* matched by the regular expression. The remainder of the
+    /// string that is not split will be the last element in the iterator.
+    ///
+    /// This method will *not* copy the text given.
+    ///
+    /// # Example
+    ///
+    /// Get the first two words in some text:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"\W+").unwrap();
+    /// let fields: Vec<&str> = re.splitn("Hey! How are you?", 3).collect();
+    /// assert_eq!(fields, vec!("Hey", "How", "are you?"));
+    /// # }
+    /// ```
+    pub fn splitn<'r, 't>(
+        &'r self,
+        text: &'t str,
+        limit: usize,
+    ) -> SplitN<'r, 't> {
+        SplitN { splits: self.split(text), n: limit }
+    }
+
+    /// Replaces the leftmost-first match with the replacement provided.
+    /// The replacement can be a regular string (where `$N` and `$name` are
+    /// expanded to match capture groups) or a function that takes the matches'
+    /// `Captures` and returns the replaced string.
+    ///
+    /// If no match is found, then a copy of the string is returned unchanged.
+    ///
+    /// # Replacement string syntax
+    ///
+    /// All instances of `$name` in the replacement text is replaced with the
+    /// corresponding capture group `name`.
+    ///
+    /// `name` may be an integer corresponding to the index of the
+    /// capture group (counted by order of opening parenthesis where `0` is the
+    /// entire match) or it can be a name (consisting of letters, digits or
+    /// underscores) corresponding to a named capture group.
+    ///
+    /// If `name` isn't a valid capture group (whether the name doesn't exist
+    /// or isn't a valid index), then it is replaced with the empty string.
+    ///
+    /// The longest possible name is used. e.g., `$1a` looks up the capture
+    /// group named `1a` and not the capture group at index `1`. To exert more
+    /// precise control over the name, use braces, e.g., `${1}a`.
+    ///
+    /// To write a literal `$` use `$$`.
+    ///
+    /// # Examples
+    ///
+    /// Note that this function is polymorphic with respect to the replacement.
+    /// In typical usage, this can just be a normal string:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new("[^01]+").unwrap();
+    /// assert_eq!(re.replace("1078910", ""), "1010");
+    /// # }
+    /// ```
+    ///
+    /// But anything satisfying the `Replacer` trait will work. For example,
+    /// a closure of type `|&Captures| -> String` provides direct access to the
+    /// captures corresponding to a match. This allows one to access
+    /// capturing group matches easily:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # use regex::Captures; fn main() {
+    /// let re = Regex::new(r"([^,\s]+),\s+(\S+)").unwrap();
+    /// let result = re.replace("Springsteen, Bruce", |caps: &Captures| {
+    ///     format!("{} {}", &caps[2], &caps[1])
+    /// });
+    /// assert_eq!(result, "Bruce Springsteen");
+    /// # }
+    /// ```
+    ///
+    /// But this is a bit cumbersome to use all the time. Instead, a simple
+    /// syntax is supported that expands `$name` into the corresponding capture
+    /// group. Here's the last example, but using this expansion technique
+    /// with named capture groups:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"(?P<last>[^,\s]+),\s+(?P<first>\S+)").unwrap();
+    /// let result = re.replace("Springsteen, Bruce", "$first $last");
+    /// assert_eq!(result, "Bruce Springsteen");
+    /// # }
+    /// ```
+    ///
+    /// Note that using `$2` instead of `$first` or `$1` instead of `$last`
+    /// would produce the same result. To write a literal `$` use `$$`.
+    ///
+    /// Sometimes the replacement string requires use of curly braces to
+    /// delineate a capture group replacement and surrounding literal text.
+    /// For example, if we wanted to join two words together with an
+    /// underscore:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"(?P<first>\w+)\s+(?P<second>\w+)").unwrap();
+    /// let result = re.replace("deep fried", "${first}_$second");
+    /// assert_eq!(result, "deep_fried");
+    /// # }
+    /// ```
+    ///
+    /// Without the curly braces, the capture group name `first_` would be
+    /// used, and since it doesn't exist, it would be replaced with the empty
+    /// string.
+    ///
+    /// Finally, sometimes you just want to replace a literal string with no
+    /// regard for capturing group expansion. This can be done by wrapping a
+    /// byte string with `NoExpand`:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// use regex::NoExpand;
+    ///
+    /// let re = Regex::new(r"(?P<last>[^,\s]+),\s+(\S+)").unwrap();
+    /// let result = re.replace("Springsteen, Bruce", NoExpand("$2 $last"));
+    /// assert_eq!(result, "$2 $last");
+    /// # }
+    /// ```
+    pub fn replace<'t, R: Replacer>(
+        &self,
+        text: &'t str,
+        rep: R,
+    ) -> Cow<'t, str> {
+        self.replacen(text, 1, rep)
+    }
+
+    /// Replaces all non-overlapping matches in `text` with the replacement
+    /// provided. This is the same as calling `replacen` with `limit` set to
+    /// `0`.
+    ///
+    /// See the documentation for `replace` for details on how to access
+    /// capturing group matches in the replacement string.
+    pub fn replace_all<'t, R: Replacer>(
+        &self,
+        text: &'t str,
+        rep: R,
+    ) -> Cow<'t, str> {
+        self.replacen(text, 0, rep)
+    }
+
+    /// Replaces at most `limit` non-overlapping matches in `text` with the
+    /// replacement provided. If `limit` is 0, then all non-overlapping matches
+    /// are replaced.
+    ///
+    /// See the documentation for `replace` for details on how to access
+    /// capturing group matches in the replacement string.
+    pub fn replacen<'t, R: Replacer>(
+        &self,
+        text: &'t str,
+        limit: usize,
+        mut rep: R,
+    ) -> Cow<'t, str> {
+        // If we know that the replacement doesn't have any capture expansions,
+        // then we can fast path. The fast path can make a tremendous
+        // difference:
+        //
+        //   1) We use `find_iter` instead of `captures_iter`. Not asking for
+        //      captures generally makes the regex engines faster.
+        //   2) We don't need to look up all of the capture groups and do
+        //      replacements inside the replacement string. We just push it
+        //      at each match and be done with it.
+        if let Some(rep) = rep.no_expansion() {
+            let mut it = self.find_iter(text).enumerate().peekable();
+            if it.peek().is_none() {
+                return Cow::Borrowed(text);
+            }
+            let mut new = String::with_capacity(text.len());
+            let mut last_match = 0;
+            for (i, m) in it {
+                if limit > 0 && i >= limit {
+                    break;
+                }
+                new.push_str(&text[last_match..m.start()]);
+                new.push_str(&rep);
+                last_match = m.end();
+            }
+            new.push_str(&text[last_match..]);
+            return Cow::Owned(new);
+        }
+
+        // The slower path, which we use if the replacement needs access to
+        // capture groups.
+        let mut it = self.captures_iter(text).enumerate().peekable();
+        if it.peek().is_none() {
+            return Cow::Borrowed(text);
+        }
+        let mut new = String::with_capacity(text.len());
+        let mut last_match = 0;
+        for (i, cap) in it {
+            if limit > 0 && i >= limit {
+                break;
+            }
+            // unwrap on 0 is OK because captures only reports matches
+            let m = cap.get(0).unwrap();
+            new.push_str(&text[last_match..m.start()]);
+            rep.replace_append(&cap, &mut new);
+            last_match = m.end();
+        }
+        new.push_str(&text[last_match..]);
+        Cow::Owned(new)
+    }
+}
+
+/// Advanced or "lower level" search methods.
+impl Regex {
+    /// Returns the end location of a match in the text given.
+    ///
+    /// This method may have the same performance characteristics as
+    /// `is_match`, except it provides an end location for a match. In
+    /// particular, the location returned *may be shorter* than the proper end
+    /// of the leftmost-first match.
+    ///
+    /// # Example
+    ///
+    /// Typically, `a+` would match the entire first sequence of `a` in some
+    /// text, but `shortest_match` can give up as soon as it sees the first
+    /// `a`.
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let text = "aaaaa";
+    /// let pos = Regex::new(r"a+").unwrap().shortest_match(text);
+    /// assert_eq!(pos, Some(1));
+    /// # }
+    /// ```
+    pub fn shortest_match(&self, text: &str) -> Option<usize> {
+        self.shortest_match_at(text, 0)
+    }
+
+    /// Returns the same as shortest_match, but starts the search at the given
+    /// offset.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    pub fn shortest_match_at(
+        &self,
+        text: &str,
+        start: usize,
+    ) -> Option<usize> {
+        self.0.searcher_str().shortest_match_at(text, start)
+    }
+
+    /// Returns the same as is_match, but starts the search at the given
+    /// offset.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    pub fn is_match_at(&self, text: &str, start: usize) -> bool {
+        self.shortest_match_at(text, start).is_some()
+    }
+
+    /// Returns the same as find, but starts the search at the given
+    /// offset.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    pub fn find_at<'t>(
+        &self,
+        text: &'t str,
+        start: usize,
+    ) -> Option<Match<'t>> {
+        self.0
+            .searcher_str()
+            .find_at(text, start)
+            .map(|(s, e)| Match::new(text, s, e))
+    }
+
+    /// This is like `captures`, but uses
+    /// [`CaptureLocations`](struct.CaptureLocations.html)
+    /// instead of
+    /// [`Captures`](struct.Captures.html) in order to amortize allocations.
+    ///
+    /// To create a `CaptureLocations` value, use the
+    /// `Regex::capture_locations` method.
+    ///
+    /// This returns the overall match if this was successful, which is always
+    /// equivalence to the `0`th capture group.
+    pub fn captures_read<'t>(
+        &self,
+        locs: &mut CaptureLocations,
+        text: &'t str,
+    ) -> Option<Match<'t>> {
+        self.captures_read_at(locs, text, 0)
+    }
+
+    /// Returns the same as captures, but starts the search at the given
+    /// offset and populates the capture locations given.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    pub fn captures_read_at<'t>(
+        &self,
+        locs: &mut CaptureLocations,
+        text: &'t str,
+        start: usize,
+    ) -> Option<Match<'t>> {
+        self.0
+            .searcher_str()
+            .captures_read_at(&mut locs.0, text, start)
+            .map(|(s, e)| Match::new(text, s, e))
+    }
+
+    /// An undocumented alias for `captures_read_at`.
+    ///
+    /// The `regex-capi` crate previously used this routine, so to avoid
+    /// breaking that crate, we continue to provide the name as an undocumented
+    /// alias.
+    #[doc(hidden)]
+    pub fn read_captures_at<'t>(
+        &self,
+        locs: &mut CaptureLocations,
+        text: &'t str,
+        start: usize,
+    ) -> Option<Match<'t>> {
+        self.captures_read_at(locs, text, start)
+    }
+}
+
+/// Auxiliary methods.
+impl Regex {
+    /// Returns the original string of this regex.
+    pub fn as_str(&self) -> &str {
+        &self.0.regex_strings()[0]
+    }
+
+    /// Returns an iterator over the capture names.
+    pub fn capture_names(&self) -> CaptureNames {
+        CaptureNames(self.0.capture_names().iter())
+    }
+
+    /// Returns the number of captures.
+    pub fn captures_len(&self) -> usize {
+        self.0.capture_names().len()
+    }
+
+    /// Returns an empty set of capture locations that can be reused in
+    /// multiple calls to `captures_read` or `captures_read_at`.
+    pub fn capture_locations(&self) -> CaptureLocations {
+        CaptureLocations(self.0.searcher_str().locations())
+    }
+
+    /// An alias for `capture_locations` to preserve backward compatibility.
+    ///
+    /// The `regex-capi` crate uses this method, so to avoid breaking that
+    /// crate, we continue to export it as an undocumented API.
+    #[doc(hidden)]
+    pub fn locations(&self) -> CaptureLocations {
+        CaptureLocations(self.0.searcher_str().locations())
+    }
+}
+
+/// An iterator over the names of all possible captures.
+///
+/// `None` indicates an unnamed capture; the first element (capture 0, the
+/// whole matched region) is always unnamed.
+///
+/// `'r` is the lifetime of the compiled regular expression.
+#[derive(Clone, Debug)]
+pub struct CaptureNames<'r>(::std::slice::Iter<'r, Option<String>>);
+
+impl<'r> Iterator for CaptureNames<'r> {
+    type Item = Option<&'r str>;
+
+    fn next(&mut self) -> Option<Option<&'r str>> {
+        self.0
+            .next()
+            .as_ref()
+            .map(|slot| slot.as_ref().map(|name| name.as_ref()))
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint()
+    }
+
+    fn count(self) -> usize {
+        self.0.count()
+    }
+}
+
+impl<'r> ExactSizeIterator for CaptureNames<'r> {}
+
+impl<'r> FusedIterator for CaptureNames<'r> {}
+
+/// Yields all substrings delimited by a regular expression match.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the string being split.
+#[derive(Debug)]
+pub struct Split<'r, 't> {
+    finder: Matches<'r, 't>,
+    last: usize,
+}
+
+impl<'r, 't> Iterator for Split<'r, 't> {
+    type Item = &'t str;
+
+    fn next(&mut self) -> Option<&'t str> {
+        let text = self.finder.0.text();
+        match self.finder.next() {
+            None => {
+                if self.last > text.len() {
+                    None
+                } else {
+                    let s = &text[self.last..];
+                    self.last = text.len() + 1; // Next call will return None
+                    Some(s)
+                }
+            }
+            Some(m) => {
+                let matched = &text[self.last..m.start()];
+                self.last = m.end();
+                Some(matched)
+            }
+        }
+    }
+}
+
+impl<'r, 't> FusedIterator for Split<'r, 't> {}
+
+/// Yields at most `N` substrings delimited by a regular expression match.
+///
+/// The last substring will be whatever remains after splitting.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the string being split.
+#[derive(Debug)]
+pub struct SplitN<'r, 't> {
+    splits: Split<'r, 't>,
+    n: usize,
+}
+
+impl<'r, 't> Iterator for SplitN<'r, 't> {
+    type Item = &'t str;
+
+    fn next(&mut self) -> Option<&'t str> {
+        if self.n == 0 {
+            return None;
+        }
+
+        self.n -= 1;
+        if self.n > 0 {
+            return self.splits.next();
+        }
+
+        let text = self.splits.finder.0.text();
+        if self.splits.last > text.len() {
+            // We've already returned all substrings.
+            None
+        } else {
+            // self.n == 0, so future calls will return None immediately
+            Some(&text[self.splits.last..])
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (0, Some(self.n))
+    }
+}
+
+impl<'r, 't> FusedIterator for SplitN<'r, 't> {}
+
+/// CaptureLocations is a low level representation of the raw offsets of each
+/// submatch.
+///
+/// You can think of this as a lower level
+/// [`Captures`](struct.Captures.html), where this type does not support
+/// named capturing groups directly and it does not borrow the text that these
+/// offsets were matched on.
+///
+/// Primarily, this type is useful when using the lower level `Regex` APIs
+/// such as `read_captures`, which permits amortizing the allocation in which
+/// capture match locations are stored.
+///
+/// In order to build a value of this type, you'll need to call the
+/// `capture_locations` method on the `Regex` being used to execute the search.
+/// The value returned can then be reused in subsequent searches.
+#[derive(Clone, Debug)]
+pub struct CaptureLocations(re_trait::Locations);
+
+/// A type alias for `CaptureLocations` for backwards compatibility.
+///
+/// Previously, we exported `CaptureLocations` as `Locations` in an
+/// undocumented API. To prevent breaking that code (e.g., in `regex-capi`),
+/// we continue re-exporting the same undocumented API.
+#[doc(hidden)]
+pub type Locations = CaptureLocations;
+
+impl CaptureLocations {
+    /// Returns the start and end positions of the Nth capture group. Returns
+    /// `None` if `i` is not a valid capture group or if the capture group did
+    /// not match anything. The positions returned are *always* byte indices
+    /// with respect to the original string matched.
+    #[inline]
+    pub fn get(&self, i: usize) -> Option<(usize, usize)> {
+        self.0.pos(i)
+    }
+
+    /// Returns the total number of capturing groups.
+    ///
+    /// This is always at least `1` since every regex has at least `1`
+    /// capturing group that corresponds to the entire match.
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.0.len()
+    }
+
+    /// An alias for the `get` method for backwards compatibility.
+    ///
+    /// Previously, we exported `get` as `pos` in an undocumented API. To
+    /// prevent breaking that code (e.g., in `regex-capi`), we continue
+    /// re-exporting the same undocumented API.
+    #[doc(hidden)]
+    #[inline]
+    pub fn pos(&self, i: usize) -> Option<(usize, usize)> {
+        self.get(i)
+    }
+}
+
+/// Captures represents a group of captured strings for a single match.
+///
+/// The 0th capture always corresponds to the entire match. Each subsequent
+/// index corresponds to the next capture group in the regex. If a capture
+/// group is named, then the matched string is *also* available via the `name`
+/// method. (Note that the 0th capture is always unnamed and so must be
+/// accessed with the `get` method.)
+///
+/// Positions returned from a capture group are always byte indices.
+///
+/// `'t` is the lifetime of the matched text.
+pub struct Captures<'t> {
+    text: &'t str,
+    locs: re_trait::Locations,
+    named_groups: Arc<HashMap<String, usize>>,
+}
+
+impl<'t> Captures<'t> {
+    /// Returns the match associated with the capture group at index `i`. If
+    /// `i` does not correspond to a capture group, or if the capture group
+    /// did not participate in the match, then `None` is returned.
+    ///
+    /// # Examples
+    ///
+    /// Get the text of the match with a default of an empty string if this
+    /// group didn't participate in the match:
+    ///
+    /// ```rust
+    /// # use regex::Regex;
+    /// let re = Regex::new(r"[a-z]+(?:([0-9]+)|([A-Z]+))").unwrap();
+    /// let caps = re.captures("abc123").unwrap();
+    ///
+    /// let text1 = caps.get(1).map_or("", |m| m.as_str());
+    /// let text2 = caps.get(2).map_or("", |m| m.as_str());
+    /// assert_eq!(text1, "123");
+    /// assert_eq!(text2, "");
+    /// ```
+    pub fn get(&self, i: usize) -> Option<Match<'t>> {
+        self.locs.pos(i).map(|(s, e)| Match::new(self.text, s, e))
+    }
+
+    /// Returns the match for the capture group named `name`. If `name` isn't a
+    /// valid capture group or didn't match anything, then `None` is returned.
+    pub fn name(&self, name: &str) -> Option<Match<'t>> {
+        self.named_groups.get(name).and_then(|&i| self.get(i))
+    }
+
+    /// An iterator that yields all capturing matches in the order in which
+    /// they appear in the regex. If a particular capture group didn't
+    /// participate in the match, then `None` is yielded for that capture.
+    ///
+    /// The first match always corresponds to the overall match of the regex.
+    pub fn iter<'c>(&'c self) -> SubCaptureMatches<'c, 't> {
+        SubCaptureMatches { caps: self, it: self.locs.iter() }
+    }
+
+    /// Expands all instances of `$name` in `replacement` to the corresponding
+    /// capture group `name`, and writes them to the `dst` buffer given.
+    ///
+    /// `name` may be an integer corresponding to the index of the capture
+    /// group (counted by order of opening parenthesis where `0` is the
+    /// entire match) or it can be a name (consisting of letters, digits or
+    /// underscores) corresponding to a named capture group.
+    ///
+    /// If `name` isn't a valid capture group (whether the name doesn't exist
+    /// or isn't a valid index), then it is replaced with the empty string.
+    ///
+    /// The longest possible name consisting of the characters `[_0-9A-Za-z]`
+    /// is used. e.g., `$1a` looks up the capture group named `1a` and not the
+    /// capture group at index `1`. To exert more precise control over the
+    /// name, or to refer to a capture group name that uses characters outside
+    /// of `[_0-9A-Za-z]`, use braces, e.g., `${1}a` or `${foo[bar].baz}`. When
+    /// using braces, any sequence of characters is permitted. If the sequence
+    /// does not refer to a capture group name in the corresponding regex, then
+    /// it is replaced with an empty string.
+    ///
+    /// To write a literal `$` use `$$`.
+    pub fn expand(&self, replacement: &str, dst: &mut String) {
+        expand_str(self, replacement, dst)
+    }
+
+    /// Returns the number of captured groups.
+    ///
+    /// This is always at least `1`, since every regex has at least one capture
+    /// group that corresponds to the full match.
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.locs.len()
+    }
+}
+
+impl<'t> fmt::Debug for Captures<'t> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("Captures").field(&CapturesDebug(self)).finish()
+    }
+}
+
+struct CapturesDebug<'c, 't: 'c>(&'c Captures<'t>);
+
+impl<'c, 't> fmt::Debug for CapturesDebug<'c, 't> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // We'd like to show something nice here, even if it means an
+        // allocation to build a reverse index.
+        let slot_to_name: HashMap<&usize, &String> =
+            self.0.named_groups.iter().map(|(a, b)| (b, a)).collect();
+        let mut map = f.debug_map();
+        for (slot, m) in self.0.locs.iter().enumerate() {
+            let m = m.map(|(s, e)| &self.0.text[s..e]);
+            if let Some(name) = slot_to_name.get(&slot) {
+                map.entry(&name, &m);
+            } else {
+                map.entry(&slot, &m);
+            }
+        }
+        map.finish()
+    }
+}
+
+/// Get a group by index.
+///
+/// `'t` is the lifetime of the matched text.
+///
+/// The text can't outlive the `Captures` object if this method is
+/// used, because of how `Index` is defined (normally `a[i]` is part
+/// of `a` and can't outlive it); to do that, use `get()` instead.
+///
+/// # Panics
+///
+/// If there is no group at the given index.
+impl<'t> Index<usize> for Captures<'t> {
+    type Output = str;
+
+    fn index(&self, i: usize) -> &str {
+        self.get(i)
+            .map(|m| m.as_str())
+            .unwrap_or_else(|| panic!("no group at index '{}'", i))
+    }
+}
+
+/// Get a group by name.
+///
+/// `'t` is the lifetime of the matched text and `'i` is the lifetime
+/// of the group name (the index).
+///
+/// The text can't outlive the `Captures` object if this method is
+/// used, because of how `Index` is defined (normally `a[i]` is part
+/// of `a` and can't outlive it); to do that, use `name` instead.
+///
+/// # Panics
+///
+/// If there is no group named by the given value.
+impl<'t, 'i> Index<&'i str> for Captures<'t> {
+    type Output = str;
+
+    fn index<'a>(&'a self, name: &'i str) -> &'a str {
+        self.name(name)
+            .map(|m| m.as_str())
+            .unwrap_or_else(|| panic!("no group named '{}'", name))
+    }
+}
+
+/// An iterator that yields all capturing matches in the order in which they
+/// appear in the regex.
+///
+/// If a particular capture group didn't participate in the match, then `None`
+/// is yielded for that capture. The first match always corresponds to the
+/// overall match of the regex.
+///
+/// The lifetime `'c` corresponds to the lifetime of the `Captures` value, and
+/// the lifetime `'t` corresponds to the originally matched text.
+#[derive(Clone, Debug)]
+pub struct SubCaptureMatches<'c, 't: 'c> {
+    caps: &'c Captures<'t>,
+    it: SubCapturesPosIter<'c>,
+}
+
+impl<'c, 't> Iterator for SubCaptureMatches<'c, 't> {
+    type Item = Option<Match<'t>>;
+
+    fn next(&mut self) -> Option<Option<Match<'t>>> {
+        self.it
+            .next()
+            .map(|cap| cap.map(|(s, e)| Match::new(self.caps.text, s, e)))
+    }
+}
+
+impl<'c, 't> FusedIterator for SubCaptureMatches<'c, 't> {}
+
+/// An iterator that yields all non-overlapping capture groups matching a
+/// particular regular expression.
+///
+/// The iterator stops when no more matches can be found.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the matched string.
+#[derive(Debug)]
+pub struct CaptureMatches<'r, 't>(
+    re_trait::CaptureMatches<'t, ExecNoSyncStr<'r>>,
+);
+
+impl<'r, 't> Iterator for CaptureMatches<'r, 't> {
+    type Item = Captures<'t>;
+
+    fn next(&mut self) -> Option<Captures<'t>> {
+        self.0.next().map(|locs| Captures {
+            text: self.0.text(),
+            locs: locs,
+            named_groups: self.0.regex().capture_name_idx().clone(),
+        })
+    }
+}
+
+impl<'r, 't> FusedIterator for CaptureMatches<'r, 't> {}
+
+/// An iterator over all non-overlapping matches for a particular string.
+///
+/// The iterator yields a `Match` value. The iterator stops when no more
+/// matches can be found.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the matched string.
+#[derive(Debug)]
+pub struct Matches<'r, 't>(re_trait::Matches<'t, ExecNoSyncStr<'r>>);
+
+impl<'r, 't> Iterator for Matches<'r, 't> {
+    type Item = Match<'t>;
+
+    fn next(&mut self) -> Option<Match<'t>> {
+        let text = self.0.text();
+        self.0.next().map(|(s, e)| Match::new(text, s, e))
+    }
+}
+
+impl<'r, 't> FusedIterator for Matches<'r, 't> {}
+
+/// Replacer describes types that can be used to replace matches in a string.
+///
+/// In general, users of this crate shouldn't need to implement this trait,
+/// since implementations are already provided for `&str` along with other
+/// variants of string types and `FnMut(&Captures) -> String` (or any
+/// `FnMut(&Captures) -> T` where `T: AsRef<str>`), which covers most use cases.
+pub trait Replacer {
+    /// Appends text to `dst` to replace the current match.
+    ///
+    /// The current match is represented by `caps`, which is guaranteed to
+    /// have a match at capture group `0`.
+    ///
+    /// For example, a no-op replacement would be
+    /// `dst.push_str(caps.get(0).unwrap().as_str())`.
+    fn replace_append(&mut self, caps: &Captures, dst: &mut String);
+
+    /// Return a fixed unchanging replacement string.
+    ///
+    /// When doing replacements, if access to `Captures` is not needed (e.g.,
+    /// the replacement byte string does not need `$` expansion), then it can
+    /// be beneficial to avoid finding sub-captures.
+    ///
+    /// In general, this is called once for every call to `replacen`.
+    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, str>> {
+        None
+    }
+
+    /// Return a `Replacer` that borrows and wraps this `Replacer`.
+    ///
+    /// This is useful when you want to take a generic `Replacer` (which might
+    /// not be cloneable) and use it without consuming it, so it can be used
+    /// more than once.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use regex::{Regex, Replacer};
+    ///
+    /// fn replace_all_twice<R: Replacer>(
+    ///     re: Regex,
+    ///     src: &str,
+    ///     mut rep: R,
+    /// ) -> String {
+    ///     let dst = re.replace_all(src, rep.by_ref());
+    ///     let dst = re.replace_all(&dst, rep.by_ref());
+    ///     dst.into_owned()
+    /// }
+    /// ```
+    fn by_ref<'r>(&'r mut self) -> ReplacerRef<'r, Self> {
+        ReplacerRef(self)
+    }
+}
+
+/// By-reference adaptor for a `Replacer`
+///
+/// Returned by [`Replacer::by_ref`](trait.Replacer.html#method.by_ref).
+#[derive(Debug)]
+pub struct ReplacerRef<'a, R: ?Sized + 'a>(&'a mut R);
+
+impl<'a, R: Replacer + ?Sized + 'a> Replacer for ReplacerRef<'a, R> {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
+        self.0.replace_append(caps, dst)
+    }
+    fn no_expansion(&mut self) -> Option<Cow<str>> {
+        self.0.no_expansion()
+    }
+}
+
+impl<'a> Replacer for &'a str {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
+        caps.expand(*self, dst);
+    }
+
+    fn no_expansion(&mut self) -> Option<Cow<str>> {
+        no_expansion(self)
+    }
+}
+
+impl<'a> Replacer for &'a String {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
+        self.as_str().replace_append(caps, dst)
+    }
+
+    fn no_expansion(&mut self) -> Option<Cow<str>> {
+        no_expansion(self)
+    }
+}
+
+impl Replacer for String {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
+        self.as_str().replace_append(caps, dst)
+    }
+
+    fn no_expansion(&mut self) -> Option<Cow<str>> {
+        no_expansion(self)
+    }
+}
+
+impl<'a> Replacer for Cow<'a, str> {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
+        self.as_ref().replace_append(caps, dst)
+    }
+
+    fn no_expansion(&mut self) -> Option<Cow<str>> {
+        no_expansion(self)
+    }
+}
+
+impl<'a> Replacer for &'a Cow<'a, str> {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
+        self.as_ref().replace_append(caps, dst)
+    }
+
+    fn no_expansion(&mut self) -> Option<Cow<str>> {
+        no_expansion(self)
+    }
+}
+
+fn no_expansion<T: AsRef<str>>(t: &T) -> Option<Cow<str>> {
+    let s = t.as_ref();
+    match find_byte(b'$', s.as_bytes()) {
+        Some(_) => None,
+        None => Some(Cow::Borrowed(s)),
+    }
+}
+
+impl<F, T> Replacer for F
+where
+    F: FnMut(&Captures) -> T,
+    T: AsRef<str>,
+{
+    fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
+        dst.push_str((*self)(caps).as_ref());
+    }
+}
+
+/// `NoExpand` indicates literal string replacement.
+///
+/// It can be used with `replace` and `replace_all` to do a literal string
+/// replacement without expanding `$name` to their corresponding capture
+/// groups. This can be both convenient (to avoid escaping `$`, for example)
+/// and performant (since capture groups don't need to be found).
+///
+/// `'t` is the lifetime of the literal text.
+#[derive(Clone, Debug)]
+pub struct NoExpand<'t>(pub &'t str);
+
+impl<'t> Replacer for NoExpand<'t> {
+    fn replace_append(&mut self, _: &Captures, dst: &mut String) {
+        dst.push_str(self.0);
+    }
+
+    fn no_expansion(&mut self) -> Option<Cow<str>> {
+        Some(Cow::Borrowed(self.0))
+    }
+}
diff --git a/vendor/regex-1.4.6/src/sparse.rs b/vendor/regex-1.4.6/src/sparse.rs
new file mode 100644 (file)
index 0000000..421d6b6
--- /dev/null
@@ -0,0 +1,84 @@
+use std::fmt;
+use std::ops::Deref;
+use std::slice;
+
+/// A sparse set used for representing ordered NFA states.
+///
+/// This supports constant time addition and membership testing. Clearing an
+/// entire set can also be done in constant time. Iteration yields elements
+/// in the order in which they were inserted.
+///
+/// The data structure is based on: https://research.swtch.com/sparse
+/// Note though that we don't actually use uninitialized memory. We generally
+/// reuse allocations, so the initial allocation cost is bareable. However,
+/// its other properties listed above are extremely useful.
+#[derive(Clone)]
+pub struct SparseSet {
+    /// Dense contains the instruction pointers in the order in which they
+    /// were inserted.
+    dense: Vec<usize>,
+    /// Sparse maps instruction pointers to their location in dense.
+    ///
+    /// An instruction pointer is in the set if and only if
+    /// sparse[ip] < dense.len() && ip == dense[sparse[ip]].
+    sparse: Box<[usize]>,
+}
+
+impl SparseSet {
+    pub fn new(size: usize) -> SparseSet {
+        SparseSet {
+            dense: Vec::with_capacity(size),
+            sparse: vec![0; size].into_boxed_slice(),
+        }
+    }
+
+    pub fn len(&self) -> usize {
+        self.dense.len()
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.dense.is_empty()
+    }
+
+    pub fn capacity(&self) -> usize {
+        self.dense.capacity()
+    }
+
+    pub fn insert(&mut self, value: usize) {
+        let i = self.len();
+        assert!(i < self.capacity());
+        self.dense.push(value);
+        self.sparse[value] = i;
+    }
+
+    pub fn contains(&self, value: usize) -> bool {
+        let i = self.sparse[value];
+        self.dense.get(i) == Some(&value)
+    }
+
+    pub fn clear(&mut self) {
+        self.dense.clear();
+    }
+}
+
+impl fmt::Debug for SparseSet {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "SparseSet({:?})", self.dense)
+    }
+}
+
+impl Deref for SparseSet {
+    type Target = [usize];
+
+    fn deref(&self) -> &Self::Target {
+        &self.dense
+    }
+}
+
+impl<'a> IntoIterator for &'a SparseSet {
+    type Item = &'a usize;
+    type IntoIter = slice::Iter<'a, usize>;
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter()
+    }
+}
diff --git a/vendor/regex-1.4.6/src/testdata/LICENSE b/vendor/regex-1.4.6/src/testdata/LICENSE
new file mode 100644 (file)
index 0000000..f47dbf4
--- /dev/null
@@ -0,0 +1,19 @@
+The following license covers testregex.c and all associated test data.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of THIS SOFTWARE FILE (the "Software"), to deal in the Software
+without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, and/or sell copies of the
+Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following disclaimer:
+
+THIS SOFTWARE IS PROVIDED BY AT&T ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL AT&T BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/regex-1.4.6/src/testdata/README b/vendor/regex-1.4.6/src/testdata/README
new file mode 100644 (file)
index 0000000..6efc2da
--- /dev/null
@@ -0,0 +1,17 @@
+Test data was taken from the Go distribution, which was in turn taken from the
+testregex test suite:
+
+  http://www2.research.att.com/~astopen/testregex/testregex.html
+
+The LICENSE in this directory corresponds to the LICENSE that the data was
+released under.
+
+The tests themselves were modified for RE2/Go. A couple were modified further
+by me (Andrew Gallant) (only in repetition.dat) so that RE2/Go would pass them.
+(Yes, it seems like RE2/Go includes failing test cases.) This may or may not
+have been a bad idea, but I think being consistent with an established Regex
+library is worth something.
+
+Note that these files are read by 'scripts/regex-match-tests.py' and turned
+into Rust tests found in 'regex_macros/tests/matches.rs'.
+
diff --git a/vendor/regex-1.4.6/src/testdata/basic.dat b/vendor/regex-1.4.6/src/testdata/basic.dat
new file mode 100644 (file)
index 0000000..632e1bb
--- /dev/null
@@ -0,0 +1,221 @@
+NOTE   all standard compliant implementations should pass these : 2002-05-31
+
+BE     abracadabra$    abracadabracadabra      (7,18)
+BE     a...b           abababbb                (2,7)
+BE     XXXXXX          ..XXXXXX                (2,8)
+E      \)              ()      (1,2)
+BE     a]              a]a     (0,2)
+B      }               }       (0,1)
+E      \}              }       (0,1)
+BE     \]              ]       (0,1)
+B      ]               ]       (0,1)
+E      ]               ]       (0,1)
+B      {               {       (0,1)
+B      }               }       (0,1)
+BE     ^a              ax      (0,1)
+BE     \^a             a^a     (1,3)
+BE     a\^             a^      (0,2)
+BE     a$              aa      (1,2)
+BE     a\$             a$      (0,2)
+BE     ^$              NULL    (0,0)
+E      $^              NULL    (0,0)
+E      a($)            aa      (1,2)(2,2)
+E      a*(^a)          aa      (0,1)(0,1)
+E      (..)*(...)*             a       (0,0)
+E      (..)*(...)*             abcd    (0,4)(2,4)
+E      (ab|a)(bc|c)            abc     (0,3)(0,2)(2,3)
+E      (ab)c|abc               abc     (0,3)(0,2)
+E      a{0}b           ab                      (1,2)
+E      (a*)(b?)(b+)b{3}        aaabbbbbbb      (0,10)(0,3)(3,4)(4,7)
+E      (a*)(b{0,1})(b{1,})b{3} aaabbbbbbb      (0,10)(0,3)(3,4)(4,7)
+E      a{9876543210}   NULL    BADBR
+E      ((a|a)|a)                       a       (0,1)(0,1)(0,1)
+E      (a*)(a|aa)                      aaaa    (0,4)(0,3)(3,4)
+E      a*(a.|aa)                       aaaa    (0,4)(2,4)
+E      a(b)|c(d)|a(e)f                 aef     (0,3)(?,?)(?,?)(1,2)
+E      (a|b)?.*                        b       (0,1)(0,1)
+E      (a|b)c|a(b|c)                   ac      (0,2)(0,1)
+E      (a|b)c|a(b|c)                   ab      (0,2)(?,?)(1,2)
+E      (a|b)*c|(a|ab)*c                abc     (0,3)(1,2)
+E      (a|b)*c|(a|ab)*c                xc      (1,2)
+E      (.a|.b).*|.*(.a|.b)             xa      (0,2)(0,2)
+E      a?(ab|ba)ab                     abab    (0,4)(0,2)
+E      a?(ac{0}b|ba)ab                 abab    (0,4)(0,2)
+E      ab|abab                         abbabab (0,2)
+E      aba|bab|bba                     baaabbbaba      (5,8)
+E      aba|bab                         baaabbbaba      (6,9)
+E      (aa|aaa)*|(a|aaaaa)             aa      (0,2)(0,2)
+E      (a.|.a.)*|(a|.a...)             aa      (0,2)(0,2)
+E      ab|a                            xabc    (1,3)
+E      ab|a                            xxabc   (2,4)
+Ei     (?-u)(Ab|cD)*                   aBcD    (0,4)(2,4)
+BE     [^-]                    --a             (2,3)
+BE     [a-]*                   --a             (0,3)
+BE     [a-m-]*                 --amoma--       (0,4)
+E      :::1:::0:|:::1:1:0:     :::0:::1:::1:::0:       (8,17)
+E      :::1:::0:|:::1:1:1:     :::0:::1:::1:::0:       (8,17)
+{E     [[:upper:]]             A               (0,1)   [[<element>]] not supported
+E      [[:lower:]]+            `az{            (1,3)
+E      [[:upper:]]+            @AZ[            (1,3)
+# No collation in Go
+#BE    [[-]]                   [[-]]           (2,4)
+#BE    [[.NIL.]]       NULL    ECOLLATE
+#BE    [[=aleph=]]     NULL    ECOLLATE
+}
+BE$    \n              \n      (0,1)
+BEn$   \n              \n      (0,1)
+BE$    [^a]            \n      (0,1)
+BE$    \na             \na     (0,2)
+E      (a)(b)(c)       abc     (0,3)(0,1)(1,2)(2,3)
+BE     xxx             xxx     (0,3)
+E1     (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)      feb 6,  (0,6)
+E1     (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)      2/7     (0,3)
+E1     (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)      feb 1,Feb 6     (5,11)
+E3     ((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))   x       (0,1)(0,1)(0,1)
+E3     ((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))*  xx      (0,2)(1,2)(1,2)
+E      a?(ab|ba)*      ababababababababababababababababababababababababababababababababababababababababa       (0,81)(79,81)
+E      abaa|abbaa|abbbaa|abbbbaa       ababbabbbabbbabbbbabbbbaa       (18,25)
+E      abaa|abbaa|abbbaa|abbbbaa       ababbabbbabbbabbbbabaa  (18,22)
+E      aaac|aabc|abac|abbc|baac|babc|bbac|bbbc baaabbbabac     (7,11)
+BE$    .*                      \x01\x7f        (0,2)
+E      aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll            XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa       (53,57)
+L      aaaa\nbbbb\ncccc\nddddd\neeeeee\nfffffff\ngggg\nhhhh\niiiii\njjjjj\nkkkkk\nllll         XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa       NOMATCH
+E      a*a*a*a*a*b             aaaaaaaaab      (0,10)
+BE     ^                       NULL            (0,0)
+BE     $                       NULL            (0,0)
+BE     ^$                      NULL            (0,0)
+BE     ^a$                     a               (0,1)
+BE     abc                     abc             (0,3)
+BE     abc                     xabcy           (1,4)
+BE     abc                     ababc           (2,5)
+BE     ab*c                    abc             (0,3)
+BE     ab*bc                   abc             (0,3)
+BE     ab*bc                   abbc            (0,4)
+BE     ab*bc                   abbbbc          (0,6)
+E      ab+bc                   abbc            (0,4)
+E      ab+bc                   abbbbc          (0,6)
+E      ab?bc                   abbc            (0,4)
+E      ab?bc                   abc             (0,3)
+E      ab?c                    abc             (0,3)
+BE     ^abc$                   abc             (0,3)
+BE     ^abc                    abcc            (0,3)
+BE     abc$                    aabc            (1,4)
+BE     ^                       abc             (0,0)
+BE     $                       abc             (3,3)
+BE     a.c                     abc             (0,3)
+BE     a.c                     axc             (0,3)
+BE     a.*c                    axyzc           (0,5)
+BE     a[bc]d                  abd             (0,3)
+BE     a[b-d]e                 ace             (0,3)
+BE     a[b-d]                  aac             (1,3)
+BE     a[-b]                   a-              (0,2)
+BE     a[b-]                   a-              (0,2)
+BE     a]                      a]              (0,2)
+BE     a[]]b                   a]b             (0,3)
+BE     a[^bc]d                 aed             (0,3)
+BE     a[^-b]c                 adc             (0,3)
+BE     a[^]b]c                 adc             (0,3)
+E      ab|cd                   abc             (0,2)
+E      ab|cd                   abcd            (0,2)
+E      a\(b                    a(b             (0,3)
+E      a\(*b                   ab              (0,2)
+E      a\(*b                   a((b            (0,4)
+E      ((a))                   abc             (0,1)(0,1)(0,1)
+E      (a)b(c)                 abc             (0,3)(0,1)(2,3)
+E      a+b+c                   aabbabc         (4,7)
+E      a*                      aaa             (0,3)
+#E     (a*)*                   -               (0,0)(0,0)
+E      (a*)*                   -               (0,0)(?,?)      RE2/Go
+E      (a*)+                   -               (0,0)(0,0)
+#E     (a*|b)*                 -               (0,0)(0,0)
+E      (a*|b)*                 -               (0,0)(?,?)      RE2/Go
+E      (a+|b)*                 ab              (0,2)(1,2)
+E      (a+|b)+                 ab              (0,2)(1,2)
+E      (a+|b)?                 ab              (0,1)(0,1)
+BE     [^ab]*                  cde             (0,3)
+#E     (^)*                    -               (0,0)(0,0)
+E      (^)*                    -               (0,0)(?,?)      RE2/Go
+BE     a*                      NULL            (0,0)
+E      ([abc])*d               abbbcd          (0,6)(4,5)
+E      ([abc])*bcd             abcd            (0,4)(0,1)
+E      a|b|c|d|e               e               (0,1)
+E      (a|b|c|d|e)f            ef              (0,2)(0,1)
+#E     ((a*|b))*               -               (0,0)(0,0)(0,0)
+E      ((a*|b))*               -               (0,0)(?,?)(?,?) RE2/Go
+BE     abcd*efg                abcdefg         (0,7)
+BE     ab*                     xabyabbbz       (1,3)
+BE     ab*                     xayabbbz        (1,2)
+E      (ab|cd)e                abcde           (2,5)(2,4)
+BE     [abhgefdc]ij            hij             (0,3)
+E      (a|b)c*d                abcd            (1,4)(1,2)
+E      (ab|ab*)bc              abc             (0,3)(0,1)
+E      a([bc]*)c*              abc             (0,3)(1,3)
+E      a([bc]*)(c*d)           abcd            (0,4)(1,3)(3,4)
+E      a([bc]+)(c*d)           abcd            (0,4)(1,3)(3,4)
+E      a([bc]*)(c+d)           abcd            (0,4)(1,2)(2,4)
+E      a[bcd]*dcdcde           adcdcde         (0,7)
+E      (ab|a)b*c               abc             (0,3)(0,2)
+E      ((a)(b)c)(d)            abcd            (0,4)(0,3)(0,1)(1,2)(3,4)
+BE     [A-Za-z_][A-Za-z0-9_]*  alpha           (0,5)
+E      ^a(bc+|b[eh])g|.h$      abh             (1,3)
+E      (bc+d$|ef*g.|h?i(j|k))  effgz           (0,5)(0,5)
+E      (bc+d$|ef*g.|h?i(j|k))  ij              (0,2)(0,2)(1,2)
+E      (bc+d$|ef*g.|h?i(j|k))  reffgz          (1,6)(1,6)
+E      (((((((((a)))))))))     a               (0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)
+BE     multiple words          multiple words yeah     (0,14)
+E      (.*)c(.*)               abcde           (0,5)(0,2)(3,5)
+BE     abcd                    abcd            (0,4)
+E      a(bc)d                  abcd            (0,4)(1,3)
+E      a[\ 1-\ 3]?c                a\ 2c             (0,3)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Qaddafi (0,15)(?,?)(10,12)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Mo'ammar Gadhafi        (0,16)(?,?)(11,13)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Kaddafi (0,15)(?,?)(10,12)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Qadhafi (0,15)(?,?)(10,12)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Gadafi  (0,14)(?,?)(10,11)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Mu'ammar Qadafi (0,15)(?,?)(11,12)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Moamar Gaddafi  (0,14)(?,?)(9,11)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Mu'ammar Qadhdhafi      (0,18)(?,?)(13,15)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Khaddafi        (0,16)(?,?)(11,13)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Ghaddafy        (0,16)(?,?)(11,13)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Ghadafi (0,15)(?,?)(11,12)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Ghaddafi        (0,16)(?,?)(11,13)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muamar Kaddafi  (0,14)(?,?)(9,11)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Quathafi        (0,16)(?,?)(11,13)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Gheddafi        (0,16)(?,?)(11,13)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Moammar Khadafy (0,15)(?,?)(11,12)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Moammar Qudhafi (0,15)(?,?)(10,12)
+E      a+(b|c)*d+              aabcdd                  (0,6)(3,4)
+E      ^.+$                    vivi                    (0,4)
+E      ^(.+)$                  vivi                    (0,4)(0,4)
+E      ^([^!.]+).att.com!(.+)$ gryphon.att.com!eby     (0,19)(0,7)(16,19)
+E      ^([^!]+!)?([^!]+)$      bas                     (0,3)(?,?)(0,3)
+E      ^([^!]+!)?([^!]+)$      bar!bas                 (0,7)(0,4)(4,7)
+E      ^([^!]+!)?([^!]+)$      foo!bas                 (0,7)(0,4)(4,7)
+E      ^.+!([^!]+!)([^!]+)$    foo!bar!bas             (0,11)(4,8)(8,11)
+E      ((foo)|(bar))!bas       bar!bas                 (0,7)(0,3)(?,?)(0,3)
+E      ((foo)|(bar))!bas       foo!bar!bas             (4,11)(4,7)(?,?)(4,7)
+E      ((foo)|(bar))!bas       foo!bas                 (0,7)(0,3)(0,3)
+E      ((foo)|bar)!bas         bar!bas                 (0,7)(0,3)
+E      ((foo)|bar)!bas         foo!bar!bas             (4,11)(4,7)
+E      ((foo)|bar)!bas         foo!bas                 (0,7)(0,3)(0,3)
+E      (foo|(bar))!bas         bar!bas                 (0,7)(0,3)(0,3)
+E      (foo|(bar))!bas         foo!bar!bas             (4,11)(4,7)(4,7)
+E      (foo|(bar))!bas         foo!bas                 (0,7)(0,3)
+E      (foo|bar)!bas           bar!bas                 (0,7)(0,3)
+E      (foo|bar)!bas           foo!bar!bas             (4,11)(4,7)
+E      (foo|bar)!bas           foo!bas                 (0,7)(0,3)
+E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas     (0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
+E      ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bas             (0,3)(?,?)(0,3)
+E      ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bar!bas         (0,7)(0,4)(4,7)
+E      ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bar!bas     (0,11)(?,?)(?,?)(4,8)(8,11)
+E      ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bas         (0,7)(0,4)(4,7)
+E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bas             (0,3)(0,3)(?,?)(0,3)
+E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bar!bas         (0,7)(0,7)(0,4)(4,7)
+E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas     (0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
+E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bas         (0,7)(0,7)(0,4)(4,7)
+E      .*(/XXX).*                      /XXX                    (0,4)(0,4)
+E      .*(\\XXX).*                     \XXX                    (0,4)(0,4)
+E      \\XXX                           \XXX                    (0,4)
+E      .*(/000).*                      /000                    (0,4)(0,4)
+E      .*(\\000).*                     \000                    (0,4)(0,4)
+E      \\000                           \000                    (0,4)
diff --git a/vendor/regex-1.4.6/src/testdata/nullsubexpr.dat b/vendor/regex-1.4.6/src/testdata/nullsubexpr.dat
new file mode 100644 (file)
index 0000000..2e18fbb
--- /dev/null
@@ -0,0 +1,79 @@
+NOTE   null subexpression matches : 2002-06-06
+
+E      (a*)*           a               (0,1)(0,1)
+#E     SAME            x               (0,0)(0,0)
+E      SAME            x               (0,0)(?,?)      RE2/Go
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            aaaaaax         (0,6)(0,6)
+E      (a*)+           a               (0,1)(0,1)
+E      SAME            x               (0,0)(0,0)
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            aaaaaax         (0,6)(0,6)
+E      (a+)*           a               (0,1)(0,1)
+E      SAME            x               (0,0)
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            aaaaaax         (0,6)(0,6)
+E      (a+)+           a               (0,1)(0,1)
+E      SAME            x               NOMATCH
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            aaaaaax         (0,6)(0,6)
+
+E      ([a]*)*         a               (0,1)(0,1)
+#E     SAME            x               (0,0)(0,0)
+E      SAME            x               (0,0)(?,?)      RE2/Go
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            aaaaaax         (0,6)(0,6)
+E      ([a]*)+         a               (0,1)(0,1)
+E      SAME            x               (0,0)(0,0)
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            aaaaaax         (0,6)(0,6)
+E      ([^b]*)*        a               (0,1)(0,1)
+#E     SAME            b               (0,0)(0,0)
+E      SAME            b               (0,0)(?,?)      RE2/Go
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            aaaaaab         (0,6)(0,6)
+E      ([ab]*)*        a               (0,1)(0,1)
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            ababab          (0,6)(0,6)
+E      SAME            bababa          (0,6)(0,6)
+E      SAME            b               (0,1)(0,1)
+E      SAME            bbbbbb          (0,6)(0,6)
+E      SAME            aaaabcde        (0,5)(0,5)
+E      ([^a]*)*        b               (0,1)(0,1)
+E      SAME            bbbbbb          (0,6)(0,6)
+#E     SAME            aaaaaa          (0,0)(0,0)
+E      SAME            aaaaaa          (0,0)(?,?)      RE2/Go
+E      ([^ab]*)*       ccccxx          (0,6)(0,6)
+#E     SAME            ababab          (0,0)(0,0)
+E      SAME            ababab          (0,0)(?,?)      RE2/Go
+
+E      ((z)+|a)*       zabcde          (0,2)(1,2)
+
+#{E    a+?             aaaaaa          (0,1)   no *? +? mimimal match ops
+#E     (a)             aaa             (0,1)(0,1)
+#E     (a*?)           aaa             (0,0)(0,0)
+#E     (a)*?           aaa             (0,0)
+#E     (a*?)*?         aaa             (0,0)
+#}
+
+B      \(a*\)*\(x\)            x       (0,1)(0,0)(0,1)
+B      \(a*\)*\(x\)            ax      (0,2)(0,1)(1,2)
+B      \(a*\)*\(x\)            axa     (0,2)(0,1)(1,2)
+B      \(a*\)*\(x\)\(\1\)      x       (0,1)(0,0)(0,1)(1,1)
+B      \(a*\)*\(x\)\(\1\)      ax      (0,2)(1,1)(1,2)(2,2)
+B      \(a*\)*\(x\)\(\1\)      axa     (0,3)(0,1)(1,2)(2,3)
+B      \(a*\)*\(x\)\(\1\)\(x\) axax    (0,4)(0,1)(1,2)(2,3)(3,4)
+B      \(a*\)*\(x\)\(\1\)\(x\) axxa    (0,3)(1,1)(1,2)(2,2)(2,3)
+
+#E     (a*)*(x)                x       (0,1)(0,0)(0,1)
+E      (a*)*(x)                x       (0,1)(?,?)(0,1) RE2/Go
+E      (a*)*(x)                ax      (0,2)(0,1)(1,2)
+E      (a*)*(x)                axa     (0,2)(0,1)(1,2)
+
+E      (a*)+(x)                x       (0,1)(0,0)(0,1)
+E      (a*)+(x)                ax      (0,2)(0,1)(1,2)
+E      (a*)+(x)                axa     (0,2)(0,1)(1,2)
+
+E      (a*){2}(x)              x       (0,1)(0,0)(0,1)
+E      (a*){2}(x)              ax      (0,2)(1,1)(1,2)
+E      (a*){2}(x)              axa     (0,2)(1,1)(1,2)
diff --git a/vendor/regex-1.4.6/src/testdata/repetition.dat b/vendor/regex-1.4.6/src/testdata/repetition.dat
new file mode 100644 (file)
index 0000000..3bb2121
--- /dev/null
@@ -0,0 +1,163 @@
+NOTE   implicit vs. explicit repetitions : 2009-02-02
+
+# Glenn Fowler <gsf@research.att.com>
+# conforming matches (column 4) must match one of the following BREs
+#      NOMATCH
+#      (0,.)\((\(.\),\(.\))(?,?)(\2,\3)\)*
+#      (0,.)\((\(.\),\(.\))(\2,\3)(?,?)\)*
+# i.e., each 3-tuple has two identical elements and one (?,?)
+
+E      ((..)|(.))                              NULL            NOMATCH
+E      ((..)|(.))((..)|(.))                    NULL            NOMATCH
+E      ((..)|(.))((..)|(.))((..)|(.))          NULL            NOMATCH
+
+E      ((..)|(.)){1}                           NULL            NOMATCH
+E      ((..)|(.)){2}                           NULL            NOMATCH
+E      ((..)|(.)){3}                           NULL            NOMATCH
+
+E      ((..)|(.))*                             NULL            (0,0)
+
+E      ((..)|(.))                              a               (0,1)(0,1)(?,?)(0,1)
+E      ((..)|(.))((..)|(.))                    a               NOMATCH
+E      ((..)|(.))((..)|(.))((..)|(.))          a               NOMATCH
+
+E      ((..)|(.)){1}                           a               (0,1)(0,1)(?,?)(0,1)
+E      ((..)|(.)){2}                           a               NOMATCH
+E      ((..)|(.)){3}                           a               NOMATCH
+
+E      ((..)|(.))*                             a               (0,1)(0,1)(?,?)(0,1)
+
+E      ((..)|(.))                              aa              (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.))((..)|(.))                    aa              (0,2)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)
+E      ((..)|(.))((..)|(.))((..)|(.))          aa              NOMATCH
+
+E      ((..)|(.)){1}                           aa              (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.)){2}                           aa              (0,2)(1,2)(?,?)(1,2)
+E      ((..)|(.)){3}                           aa              NOMATCH
+
+E      ((..)|(.))*                             aa              (0,2)(0,2)(0,2)(?,?)
+
+E      ((..)|(.))                              aaa             (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.))((..)|(.))                    aaa             (0,3)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)
+E      ((..)|(.))((..)|(.))((..)|(.))          aaa             (0,3)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)(2,3)(?,?)(2,3)
+
+E      ((..)|(.)){1}                           aaa             (0,2)(0,2)(0,2)(?,?)
+#E     ((..)|(.)){2}                           aaa             (0,3)(2,3)(?,?)(2,3)
+E      ((..)|(.)){2}                           aaa             (0,3)(2,3)(0,2)(2,3)    RE2/Go
+E      ((..)|(.)){3}                           aaa             (0,3)(2,3)(?,?)(2,3)
+
+#E     ((..)|(.))*                             aaa             (0,3)(2,3)(?,?)(2,3)
+E      ((..)|(.))*                             aaa             (0,3)(2,3)(0,2)(2,3)    RE2/Go
+
+E      ((..)|(.))                              aaaa            (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.))((..)|(.))                    aaaa            (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E      ((..)|(.))((..)|(.))((..)|(.))          aaaa            (0,4)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)(3,4)(?,?)(3,4)
+
+E      ((..)|(.)){1}                           aaaa            (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.)){2}                           aaaa            (0,4)(2,4)(2,4)(?,?)
+#E     ((..)|(.)){3}                           aaaa            (0,4)(3,4)(?,?)(3,4)
+E      ((..)|(.)){3}                           aaaa            (0,4)(3,4)(0,2)(3,4)    RE2/Go
+
+E      ((..)|(.))*                             aaaa            (0,4)(2,4)(2,4)(?,?)
+
+E      ((..)|(.))                              aaaaa           (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.))((..)|(.))                    aaaaa           (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E      ((..)|(.))((..)|(.))((..)|(.))          aaaaa           (0,5)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,5)(?,?)(4,5)
+
+E      ((..)|(.)){1}                           aaaaa           (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.)){2}                           aaaaa           (0,4)(2,4)(2,4)(?,?)
+#E     ((..)|(.)){3}                           aaaaa           (0,5)(4,5)(?,?)(4,5)
+E      ((..)|(.)){3}                           aaaaa           (0,5)(4,5)(2,4)(4,5)    RE2/Go
+
+#E     ((..)|(.))*                             aaaaa           (0,5)(4,5)(?,?)(4,5)
+E      ((..)|(.))*                             aaaaa           (0,5)(4,5)(2,4)(4,5)    RE2/Go
+
+E      ((..)|(.))                              aaaaaa          (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.))((..)|(.))                    aaaaaa          (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E      ((..)|(.))((..)|(.))((..)|(.))          aaaaaa          (0,6)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,6)(4,6)(?,?)
+
+E      ((..)|(.)){1}                           aaaaaa          (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.)){2}                           aaaaaa          (0,4)(2,4)(2,4)(?,?)
+E      ((..)|(.)){3}                           aaaaaa          (0,6)(4,6)(4,6)(?,?)
+
+E      ((..)|(.))*                             aaaaaa          (0,6)(4,6)(4,6)(?,?)
+
+NOTE   additional repetition tests graciously provided by Chris Kuklewicz www.haskell.org 2009-02-02
+
+# These test a bug in OS X / FreeBSD / NetBSD, and libtree. 
+# Linux/GLIBC gets the {8,} and {8,8} wrong.
+
+:HA#100:E      X(.?){0,}Y      X1234567Y       (0,9)(7,8)
+:HA#101:E      X(.?){1,}Y      X1234567Y       (0,9)(7,8)
+:HA#102:E      X(.?){2,}Y      X1234567Y       (0,9)(7,8)
+:HA#103:E      X(.?){3,}Y      X1234567Y       (0,9)(7,8)
+:HA#104:E      X(.?){4,}Y      X1234567Y       (0,9)(7,8)
+:HA#105:E      X(.?){5,}Y      X1234567Y       (0,9)(7,8)
+:HA#106:E      X(.?){6,}Y      X1234567Y       (0,9)(7,8)
+:HA#107:E      X(.?){7,}Y      X1234567Y       (0,9)(7,8)
+:HA#108:E      X(.?){8,}Y      X1234567Y       (0,9)(8,8)
+#:HA#110:E     X(.?){0,8}Y     X1234567Y       (0,9)(7,8)
+:HA#110:E      X(.?){0,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+#:HA#111:E     X(.?){1,8}Y     X1234567Y       (0,9)(7,8)
+:HA#111:E      X(.?){1,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+#:HA#112:E     X(.?){2,8}Y     X1234567Y       (0,9)(7,8)
+:HA#112:E      X(.?){2,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+#:HA#113:E     X(.?){3,8}Y     X1234567Y       (0,9)(7,8)
+:HA#113:E      X(.?){3,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+#:HA#114:E     X(.?){4,8}Y     X1234567Y       (0,9)(7,8)
+:HA#114:E      X(.?){4,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+#:HA#115:E     X(.?){5,8}Y     X1234567Y       (0,9)(7,8)
+:HA#115:E      X(.?){5,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+#:HA#116:E     X(.?){6,8}Y     X1234567Y       (0,9)(7,8)
+:HA#116:E      X(.?){6,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+#:HA#117:E     X(.?){7,8}Y     X1234567Y       (0,9)(7,8)
+:HA#117:E      X(.?){7,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+:HA#118:E      X(.?){8,8}Y     X1234567Y       (0,9)(8,8)
+
+# These test a fixed bug in my regex-tdfa that did not keep the expanded
+# form properly grouped, so right association did the wrong thing with
+# these ambiguous patterns (crafted just to test my code when I became
+# suspicious of my implementation).  The first subexpression should use
+# "ab" then "a" then "bcd".
+
+# OS X / FreeBSD / NetBSD badly fail many of these, with impossible
+# results like (0,6)(4,5)(6,6).
+
+:HA#260:E      (a|ab|c|bcd){0,}(d*)    ababcd  (0,1)(0,1)(1,1)
+:HA#261:E      (a|ab|c|bcd){1,}(d*)    ababcd  (0,1)(0,1)(1,1)
+:HA#262:E      (a|ab|c|bcd){2,}(d*)    ababcd  (0,6)(3,6)(6,6)
+:HA#263:E      (a|ab|c|bcd){3,}(d*)    ababcd  (0,6)(3,6)(6,6)
+:HA#264:E      (a|ab|c|bcd){4,}(d*)    ababcd  NOMATCH
+:HA#265:E      (a|ab|c|bcd){0,10}(d*)  ababcd  (0,1)(0,1)(1,1)
+:HA#266:E      (a|ab|c|bcd){1,10}(d*)  ababcd  (0,1)(0,1)(1,1)
+:HA#267:E      (a|ab|c|bcd){2,10}(d*)  ababcd  (0,6)(3,6)(6,6)
+:HA#268:E      (a|ab|c|bcd){3,10}(d*)  ababcd  (0,6)(3,6)(6,6)
+:HA#269:E      (a|ab|c|bcd){4,10}(d*)  ababcd  NOMATCH
+:HA#270:E      (a|ab|c|bcd)*(d*)       ababcd  (0,1)(0,1)(1,1)
+:HA#271:E      (a|ab|c|bcd)+(d*)       ababcd  (0,1)(0,1)(1,1)
+
+# The above worked on Linux/GLIBC but the following often fail.
+# They also trip up OS X / FreeBSD / NetBSD:
+
+#:HA#280:E     (ab|a|c|bcd){0,}(d*)    ababcd  (0,6)(3,6)(6,6)
+:HA#280:E      (ab|a|c|bcd){0,}(d*)    ababcd  (0,6)(4,5)(5,6) RE2/Go
+#:HA#281:E     (ab|a|c|bcd){1,}(d*)    ababcd  (0,6)(3,6)(6,6)
+:HA#281:E      (ab|a|c|bcd){1,}(d*)    ababcd  (0,6)(4,5)(5,6) RE2/Go
+#:HA#282:E     (ab|a|c|bcd){2,}(d*)    ababcd  (0,6)(3,6)(6,6)
+:HA#282:E      (ab|a|c|bcd){2,}(d*)    ababcd  (0,6)(4,5)(5,6) RE2/Go
+#:HA#283:E     (ab|a|c|bcd){3,}(d*)    ababcd  (0,6)(3,6)(6,6)
+:HA#283:E      (ab|a|c|bcd){3,}(d*)    ababcd  (0,6)(4,5)(5,6) RE2/Go
+:HA#284:E      (ab|a|c|bcd){4,}(d*)    ababcd  NOMATCH
+#:HA#285:E     (ab|a|c|bcd){0,10}(d*)  ababcd  (0,6)(3,6)(6,6)
+:HA#285:E      (ab|a|c|bcd){0,10}(d*)  ababcd  (0,6)(4,5)(5,6) RE2/Go
+#:HA#286:E     (ab|a|c|bcd){1,10}(d*)  ababcd  (0,6)(3,6)(6,6)
+:HA#286:E      (ab|a|c|bcd){1,10}(d*)  ababcd  (0,6)(4,5)(5,6) RE2/Go
+#:HA#287:E     (ab|a|c|bcd){2,10}(d*)  ababcd  (0,6)(3,6)(6,6)
+:HA#287:E      (ab|a|c|bcd){2,10}(d*)  ababcd  (0,6)(4,5)(5,6) RE2/Go
+#:HA#288:E     (ab|a|c|bcd){3,10}(d*)  ababcd  (0,6)(3,6)(6,6)
+:HA#288:E      (ab|a|c|bcd){3,10}(d*)  ababcd  (0,6)(4,5)(5,6) RE2/Go
+:HA#289:E      (ab|a|c|bcd){4,10}(d*)  ababcd  NOMATCH
+#:HA#290:E     (ab|a|c|bcd)*(d*)       ababcd  (0,6)(3,6)(6,6)
+:HA#290:E      (ab|a|c|bcd)*(d*)       ababcd  (0,6)(4,5)(5,6) RE2/Go
+#:HA#291:E     (ab|a|c|bcd)+(d*)       ababcd  (0,6)(3,6)(6,6)
+:HA#291:E      (ab|a|c|bcd)+(d*)       ababcd  (0,6)(4,5)(5,6) RE2/Go
diff --git a/vendor/regex-1.4.6/src/utf8.rs b/vendor/regex-1.4.6/src/utf8.rs
new file mode 100644 (file)
index 0000000..6e0608f
--- /dev/null
@@ -0,0 +1,264 @@
+/// A few elementary UTF-8 encoding and decoding functions used by the matching
+/// engines.
+///
+/// In an ideal world, the matching engines operate on `&str` and we can just
+/// lean on the standard library for all our UTF-8 needs. However, to support
+/// byte based regexes (that can match on arbitrary bytes which may contain
+/// UTF-8), we need to be capable of searching and decoding UTF-8 on a `&[u8]`.
+/// The standard library doesn't really recognize this use case, so we have
+/// to build it out ourselves.
+///
+/// Should this be factored out into a separate crate? It seems independently
+/// useful. There are other crates that already exist (e.g., `utf-8`) that have
+/// overlapping use cases. Not sure what to do.
+use std::char;
+
+const TAG_CONT: u8 = 0b1000_0000;
+const TAG_TWO: u8 = 0b1100_0000;
+const TAG_THREE: u8 = 0b1110_0000;
+const TAG_FOUR: u8 = 0b1111_0000;
+
+/// Returns the smallest possible index of the next valid UTF-8 sequence
+/// starting after `i`.
+pub fn next_utf8(text: &[u8], i: usize) -> usize {
+    let b = match text.get(i) {
+        None => return i + 1,
+        Some(&b) => b,
+    };
+    let inc = if b <= 0x7F {
+        1
+    } else if b <= 0b110_11111 {
+        2
+    } else if b <= 0b1110_1111 {
+        3
+    } else {
+        4
+    };
+    i + inc
+}
+
+/// Decode a single UTF-8 sequence into a single Unicode codepoint from `src`.
+///
+/// If no valid UTF-8 sequence could be found, then `None` is returned.
+/// Otherwise, the decoded codepoint and the number of bytes read is returned.
+/// The number of bytes read (for a valid UTF-8 sequence) is guaranteed to be
+/// 1, 2, 3 or 4.
+///
+/// Note that a UTF-8 sequence is invalid if it is incorrect UTF-8, encodes a
+/// codepoint that is out of range (surrogate codepoints are out of range) or
+/// is not the shortest possible UTF-8 sequence for that codepoint.
+#[inline]
+pub fn decode_utf8(src: &[u8]) -> Option<(char, usize)> {
+    let b0 = match src.get(0) {
+        None => return None,
+        Some(&b) if b <= 0x7F => return Some((b as char, 1)),
+        Some(&b) => b,
+    };
+    match b0 {
+        0b110_00000..=0b110_11111 => {
+            if src.len() < 2 {
+                return None;
+            }
+            let b1 = src[1];
+            if 0b11_000000 & b1 != TAG_CONT {
+                return None;
+            }
+            let cp = ((b0 & !TAG_TWO) as u32) << 6 | ((b1 & !TAG_CONT) as u32);
+            match cp {
+                0x80..=0x7FF => char::from_u32(cp).map(|cp| (cp, 2)),
+                _ => None,
+            }
+        }
+        0b1110_0000..=0b1110_1111 => {
+            if src.len() < 3 {
+                return None;
+            }
+            let (b1, b2) = (src[1], src[2]);
+            if 0b11_000000 & b1 != TAG_CONT {
+                return None;
+            }
+            if 0b11_000000 & b2 != TAG_CONT {
+                return None;
+            }
+            let cp = ((b0 & !TAG_THREE) as u32) << 12
+                | ((b1 & !TAG_CONT) as u32) << 6
+                | ((b2 & !TAG_CONT) as u32);
+            match cp {
+                // char::from_u32 will disallow surrogate codepoints.
+                0x800..=0xFFFF => char::from_u32(cp).map(|cp| (cp, 3)),
+                _ => None,
+            }
+        }
+        0b11110_000..=0b11110_111 => {
+            if src.len() < 4 {
+                return None;
+            }
+            let (b1, b2, b3) = (src[1], src[2], src[3]);
+            if 0b11_000000 & b1 != TAG_CONT {
+                return None;
+            }
+            if 0b11_000000 & b2 != TAG_CONT {
+                return None;
+            }
+            if 0b11_000000 & b3 != TAG_CONT {
+                return None;
+            }
+            let cp = ((b0 & !TAG_FOUR) as u32) << 18
+                | ((b1 & !TAG_CONT) as u32) << 12
+                | ((b2 & !TAG_CONT) as u32) << 6
+                | ((b3 & !TAG_CONT) as u32);
+            match cp {
+                0x10000..=0x10FFFF => char::from_u32(cp).map(|cp| (cp, 4)),
+                _ => None,
+            }
+        }
+        _ => None,
+    }
+}
+
+/// Like `decode_utf8`, but decodes the last UTF-8 sequence in `src` instead
+/// of the first.
+pub fn decode_last_utf8(src: &[u8]) -> Option<(char, usize)> {
+    if src.is_empty() {
+        return None;
+    }
+    let mut start = src.len() - 1;
+    if src[start] <= 0x7F {
+        return Some((src[start] as char, 1));
+    }
+    while start > src.len().saturating_sub(4) {
+        start -= 1;
+        if is_start_byte(src[start]) {
+            break;
+        }
+    }
+    match decode_utf8(&src[start..]) {
+        None => None,
+        Some((_, n)) if n < src.len() - start => None,
+        Some((cp, n)) => Some((cp, n)),
+    }
+}
+
+fn is_start_byte(b: u8) -> bool {
+    b & 0b11_000000 != 0b1_0000000
+}
+
+#[cfg(test)]
+mod tests {
+    use std::str;
+
+    use quickcheck::quickcheck;
+
+    use super::{
+        decode_last_utf8, decode_utf8, TAG_CONT, TAG_FOUR, TAG_THREE, TAG_TWO,
+    };
+
+    #[test]
+    fn prop_roundtrip() {
+        fn p(given_cp: char) -> bool {
+            let mut tmp = [0; 4];
+            let encoded_len = given_cp.encode_utf8(&mut tmp).len();
+            let (got_cp, got_len) = decode_utf8(&tmp[..encoded_len]).unwrap();
+            encoded_len == got_len && given_cp == got_cp
+        }
+        quickcheck(p as fn(char) -> bool)
+    }
+
+    #[test]
+    fn prop_roundtrip_last() {
+        fn p(given_cp: char) -> bool {
+            let mut tmp = [0; 4];
+            let encoded_len = given_cp.encode_utf8(&mut tmp).len();
+            let (got_cp, got_len) =
+                decode_last_utf8(&tmp[..encoded_len]).unwrap();
+            encoded_len == got_len && given_cp == got_cp
+        }
+        quickcheck(p as fn(char) -> bool)
+    }
+
+    #[test]
+    fn prop_encode_matches_std() {
+        fn p(cp: char) -> bool {
+            let mut got = [0; 4];
+            let n = cp.encode_utf8(&mut got).len();
+            let expected = cp.to_string();
+            &got[..n] == expected.as_bytes()
+        }
+        quickcheck(p as fn(char) -> bool)
+    }
+
+    #[test]
+    fn prop_decode_matches_std() {
+        fn p(given_cp: char) -> bool {
+            let mut tmp = [0; 4];
+            let n = given_cp.encode_utf8(&mut tmp).len();
+            let (got_cp, _) = decode_utf8(&tmp[..n]).unwrap();
+            let expected_cp =
+                str::from_utf8(&tmp[..n]).unwrap().chars().next().unwrap();
+            got_cp == expected_cp
+        }
+        quickcheck(p as fn(char) -> bool)
+    }
+
+    #[test]
+    fn prop_decode_last_matches_std() {
+        fn p(given_cp: char) -> bool {
+            let mut tmp = [0; 4];
+            let n = given_cp.encode_utf8(&mut tmp).len();
+            let (got_cp, _) = decode_last_utf8(&tmp[..n]).unwrap();
+            let expected_cp = str::from_utf8(&tmp[..n])
+                .unwrap()
+                .chars()
+                .rev()
+                .next()
+                .unwrap();
+            got_cp == expected_cp
+        }
+        quickcheck(p as fn(char) -> bool)
+    }
+
+    #[test]
+    fn reject_invalid() {
+        // Invalid start byte
+        assert_eq!(decode_utf8(&[0xFF]), None);
+        // Surrogate pair
+        assert_eq!(decode_utf8(&[0xED, 0xA0, 0x81]), None);
+        // Invalid continuation byte.
+        assert_eq!(decode_utf8(&[0xD4, 0xC2]), None);
+        // Bad lengths
+        assert_eq!(decode_utf8(&[0xC3]), None); // 2 bytes
+        assert_eq!(decode_utf8(&[0xEF, 0xBF]), None); // 3 bytes
+        assert_eq!(decode_utf8(&[0xF4, 0x8F, 0xBF]), None); // 4 bytes
+                                                            // Not a minimal UTF-8 sequence
+        assert_eq!(decode_utf8(&[TAG_TWO, TAG_CONT | b'a']), None);
+        assert_eq!(decode_utf8(&[TAG_THREE, TAG_CONT, TAG_CONT | b'a']), None);
+        assert_eq!(
+            decode_utf8(&[TAG_FOUR, TAG_CONT, TAG_CONT, TAG_CONT | b'a',]),
+            None
+        );
+    }
+
+    #[test]
+    fn reject_invalid_last() {
+        // Invalid start byte
+        assert_eq!(decode_last_utf8(&[0xFF]), None);
+        // Surrogate pair
+        assert_eq!(decode_last_utf8(&[0xED, 0xA0, 0x81]), None);
+        // Bad lengths
+        assert_eq!(decode_last_utf8(&[0xC3]), None); // 2 bytes
+        assert_eq!(decode_last_utf8(&[0xEF, 0xBF]), None); // 3 bytes
+        assert_eq!(decode_last_utf8(&[0xF4, 0x8F, 0xBF]), None); // 4 bytes
+                                                                 // Not a minimal UTF-8 sequence
+        assert_eq!(decode_last_utf8(&[TAG_TWO, TAG_CONT | b'a']), None);
+        assert_eq!(
+            decode_last_utf8(&[TAG_THREE, TAG_CONT, TAG_CONT | b'a',]),
+            None
+        );
+        assert_eq!(
+            decode_last_utf8(
+                &[TAG_FOUR, TAG_CONT, TAG_CONT, TAG_CONT | b'a',]
+            ),
+            None
+        );
+    }
+}
diff --git a/vendor/regex-1.4.6/test b/vendor/regex-1.4.6/test
new file mode 100755 (executable)
index 0000000..3d1351c
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This is a convenience script for running a broad swath of tests across
+# features. We don't test the complete space, since the complete space is quite
+# large. Hopefully once we migrate the test suite to better infrastructure
+# (like regex-automata), we'll be able to test more of the space.
+echo "===== DEFAULT FEATURES ==="
+cargo test
+
+echo "===== DOC TESTS ==="
+cargo test --doc
+
+features=(
+    "std"
+    "std unicode"
+    "std unicode-perl"
+    "std perf"
+    "std perf-cache"
+    "std perf-dfa"
+    "std perf-inline"
+    "std perf-literal"
+)
+for f in "${features[@]}"; do
+    echo "===== FEATURE: $f (default) ==="
+    cargo test --test default --no-default-features --features "$f"
+    echo "===== FEATURE: $f (default-bytes) ==="
+    cargo test --test default-bytes --no-default-features --features "$f"
+done
diff --git a/vendor/regex-1.4.6/tests/api.rs b/vendor/regex-1.4.6/tests/api.rs
new file mode 100644 (file)
index 0000000..c7250a8
--- /dev/null
@@ -0,0 +1,234 @@
+#[test]
+fn empty_regex_empty_match() {
+    let re = regex!("");
+    assert_eq!(vec![(0, 0)], findall!(re, ""));
+}
+
+#[test]
+fn empty_regex_nonempty_match() {
+    let re = regex!("");
+    assert_eq!(vec![(0, 0), (1, 1), (2, 2), (3, 3)], findall!(re, "abc"));
+}
+
+#[test]
+fn one_zero_length_match() {
+    let re = regex!(r"[0-9]*");
+    assert_eq!(vec![(0, 0), (1, 2), (3, 4)], findall!(re, "a1b2"));
+}
+
+#[test]
+fn many_zero_length_match() {
+    let re = regex!(r"[0-9]*");
+    assert_eq!(
+        vec![(0, 0), (1, 2), (3, 3), (4, 4), (5, 6)],
+        findall!(re, "a1bbb2")
+    );
+}
+
+#[test]
+fn many_sequential_zero_length_match() {
+    let re = regex!(r"[0-9]?");
+    assert_eq!(
+        vec![(0, 0), (1, 2), (2, 3), (4, 5), (6, 6)],
+        findall!(re, "a12b3c")
+    );
+}
+
+#[test]
+fn quoted_bracket_set() {
+    let re = regex!(r"([\x{5b}\x{5d}])");
+    assert_eq!(vec![(0, 1), (1, 2)], findall!(re, "[]"));
+    let re = regex!(r"([\[\]])");
+    assert_eq!(vec![(0, 1), (1, 2)], findall!(re, "[]"));
+}
+
+#[test]
+fn first_range_starts_with_left_bracket() {
+    let re = regex!(r"([\[-z])");
+    assert_eq!(vec![(0, 1), (1, 2)], findall!(re, "[]"));
+}
+
+#[test]
+fn range_ends_with_escape() {
+    let re = regex!(r"([\[-\x{5d}])");
+    assert_eq!(vec![(0, 1), (1, 2)], findall!(re, "[]"));
+}
+
+#[test]
+fn empty_match_find_iter() {
+    let re = regex!(r".*?");
+    assert_eq!(vec![(0, 0), (1, 1), (2, 2), (3, 3)], findall!(re, "abc"));
+}
+
+#[test]
+fn empty_match_captures_iter() {
+    let re = regex!(r".*?");
+    let ms: Vec<_> = re
+        .captures_iter(text!("abc"))
+        .map(|c| c.get(0).unwrap())
+        .map(|m| (m.start(), m.end()))
+        .collect();
+    assert_eq!(ms, vec![(0, 0), (1, 1), (2, 2), (3, 3)]);
+}
+
+#[test]
+fn capture_names() {
+    let re = regex!(r"(.)(?P<a>.)");
+    assert_eq!(3, re.captures_len());
+    assert_eq!((3, Some(3)), re.capture_names().size_hint());
+    assert_eq!(
+        vec![None, None, Some("a")],
+        re.capture_names().collect::<Vec<_>>()
+    );
+}
+
+#[test]
+fn regex_string() {
+    assert_eq!(r"[a-zA-Z0-9]+", regex!(r"[a-zA-Z0-9]+").as_str());
+    assert_eq!(r"[a-zA-Z0-9]+", &format!("{}", regex!(r"[a-zA-Z0-9]+")));
+    assert_eq!(r"[a-zA-Z0-9]+", &format!("{:?}", regex!(r"[a-zA-Z0-9]+")));
+}
+
+#[test]
+fn capture_index() {
+    let re = regex!(r"^(?P<name>.+)$");
+    let cap = re.captures(t!("abc")).unwrap();
+    assert_eq!(&cap[0], t!("abc"));
+    assert_eq!(&cap[1], t!("abc"));
+    assert_eq!(&cap["name"], t!("abc"));
+}
+
+#[test]
+#[should_panic]
+#[cfg_attr(all(target_env = "msvc", target_pointer_width = "32"), ignore)]
+fn capture_index_panic_usize() {
+    let re = regex!(r"^(?P<name>.+)$");
+    let cap = re.captures(t!("abc")).unwrap();
+    let _ = cap[2];
+}
+
+#[test]
+#[should_panic]
+#[cfg_attr(all(target_env = "msvc", target_pointer_width = "32"), ignore)]
+fn capture_index_panic_name() {
+    let re = regex!(r"^(?P<name>.+)$");
+    let cap = re.captures(t!("abc")).unwrap();
+    let _ = cap["bad name"];
+}
+
+#[test]
+fn capture_index_lifetime() {
+    // This is a test of whether the types on `caps["..."]` are general
+    // enough. If not, this will fail to typecheck.
+    fn inner(s: &str) -> usize {
+        let re = regex!(r"(?P<number>[0-9]+)");
+        let caps = re.captures(t!(s)).unwrap();
+        caps["number"].len()
+    }
+    assert_eq!(3, inner("123"));
+}
+
+#[test]
+fn capture_misc() {
+    let re = regex!(r"(.)(?P<a>a)?(.)(?P<b>.)");
+    let cap = re.captures(t!("abc")).unwrap();
+
+    assert_eq!(5, cap.len());
+
+    assert_eq!((0, 3), {
+        let m = cap.get(0).unwrap();
+        (m.start(), m.end())
+    });
+    assert_eq!(None, cap.get(2));
+    assert_eq!((2, 3), {
+        let m = cap.get(4).unwrap();
+        (m.start(), m.end())
+    });
+
+    assert_eq!(t!("abc"), match_text!(cap.get(0).unwrap()));
+    assert_eq!(None, cap.get(2));
+    assert_eq!(t!("c"), match_text!(cap.get(4).unwrap()));
+
+    assert_eq!(None, cap.name("a"));
+    assert_eq!(t!("c"), match_text!(cap.name("b").unwrap()));
+}
+
+#[test]
+fn sub_capture_matches() {
+    let re = regex!(r"([a-z])(([a-z])|([0-9]))");
+    let cap = re.captures(t!("a5")).unwrap();
+    let subs: Vec<_> = cap.iter().collect();
+
+    assert_eq!(5, subs.len());
+    assert!(subs[0].is_some());
+    assert!(subs[1].is_some());
+    assert!(subs[2].is_some());
+    assert!(subs[3].is_none());
+    assert!(subs[4].is_some());
+
+    assert_eq!(t!("a5"), match_text!(subs[0].unwrap()));
+    assert_eq!(t!("a"), match_text!(subs[1].unwrap()));
+    assert_eq!(t!("5"), match_text!(subs[2].unwrap()));
+    assert_eq!(t!("5"), match_text!(subs[4].unwrap()));
+}
+
+expand!(expand1, r"(?-u)(?P<foo>\w+)", "abc", "$foo", "abc");
+expand!(expand2, r"(?-u)(?P<foo>\w+)", "abc", "$0", "abc");
+expand!(expand3, r"(?-u)(?P<foo>\w+)", "abc", "$1", "abc");
+expand!(expand4, r"(?-u)(?P<foo>\w+)", "abc", "$$1", "$1");
+expand!(expand5, r"(?-u)(?P<foo>\w+)", "abc", "$$foo", "$foo");
+expand!(expand6, r"(?-u)(?P<a>\w+)\s+(?P<b>\d+)", "abc 123", "$b$a", "123abc");
+expand!(expand7, r"(?-u)(?P<a>\w+)\s+(?P<b>\d+)", "abc 123", "z$bz$az", "z");
+expand!(
+    expand8,
+    r"(?-u)(?P<a>\w+)\s+(?P<b>\d+)",
+    "abc 123",
+    ".$b.$a.",
+    ".123.abc."
+);
+expand!(
+    expand9,
+    r"(?-u)(?P<a>\w+)\s+(?P<b>\d+)",
+    "abc 123",
+    " $b $a ",
+    " 123 abc "
+);
+expand!(expand10, r"(?-u)(?P<a>\w+)\s+(?P<b>\d+)", "abc 123", "$bz$az", "");
+
+expand!(expand_name1, r"%(?P<Z>[a-z]+)", "%abc", "$Z%", "abc%");
+expand!(expand_name2, r"\[(?P<Z>[a-z]+)", "[abc", "$Z[", "abc[");
+expand!(expand_name3, r"\{(?P<Z>[a-z]+)", "{abc", "$Z{", "abc{");
+expand!(expand_name4, r"\}(?P<Z>[a-z]+)", "}abc", "$Z}", "abc}");
+expand!(expand_name5, r"%([a-z]+)", "%abc", "$1a%", "%");
+expand!(expand_name6, r"%([a-z]+)", "%abc", "${1}a%", "abca%");
+expand!(expand_name7, r"\[(?P<Z[>[a-z]+)", "[abc", "${Z[}[", "abc[");
+expand!(expand_name8, r"\[(?P<Z[>[a-z]+)", "[abc", "${foo}[", "[");
+expand!(expand_name9, r"\[(?P<Z[>[a-z]+)", "[abc", "${1a}[", "[");
+expand!(expand_name10, r"\[(?P<Z[>[a-z]+)", "[abc", "${#}[", "[");
+expand!(expand_name11, r"\[(?P<Z[>[a-z]+)", "[abc", "${$$}[", "[");
+
+split!(
+    split1,
+    r"(?-u)\s+",
+    "a b\nc\td\n\t e",
+    &[t!("a"), t!("b"), t!("c"), t!("d"), t!("e")]
+);
+split!(
+    split2,
+    r"(?-u)\b",
+    "a b c",
+    &[t!(""), t!("a"), t!(" "), t!("b"), t!(" "), t!("c"), t!("")]
+);
+split!(split3, r"a$", "a", &[t!(""), t!("")]);
+split!(split_none, r"-", r"a", &[t!("a")]);
+split!(split_trailing_blank, r"-", r"a-", &[t!("a"), t!("")]);
+split!(split_trailing_blanks, r"-", r"a--", &[t!("a"), t!(""), t!("")]);
+split!(split_empty, r"-", r"", &[t!("")]);
+
+splitn!(splitn_below_limit, r"-", r"a", 2, &[t!("a")]);
+splitn!(splitn_at_limit, r"-", r"a-b", 2, &[t!("a"), t!("b")]);
+splitn!(splitn_above_limit, r"-", r"a-b-c", 2, &[t!("a"), t!("b-c")]);
+splitn!(splitn_zero_limit, r"-", r"a-b", 0, empty_vec!());
+splitn!(splitn_trailing_blank, r"-", r"a-", 2, &[t!("a"), t!("")]);
+splitn!(splitn_trailing_separator, r"-", r"a--", 2, &[t!("a"), t!("-")]);
+splitn!(splitn_empty, r"-", r"", 1, &[t!("")]);
diff --git a/vendor/regex-1.4.6/tests/api_str.rs b/vendor/regex-1.4.6/tests/api_str.rs
new file mode 100644 (file)
index 0000000..480116d
--- /dev/null
@@ -0,0 +1,34 @@
+// These tests don't really make sense with the bytes API, so we only test them
+// on the Unicode API.
+
+#[test]
+fn empty_match_unicode_find_iter() {
+    // Tests that we still yield byte ranges at valid UTF-8 sequence boundaries
+    // even when we're susceptible to empty width matches.
+    let re = regex!(r".*?");
+    assert_eq!(
+        vec![(0, 0), (3, 3), (4, 4), (7, 7), (8, 8)],
+        findall!(re, "Ⅰ1Ⅱ2")
+    );
+}
+
+#[test]
+fn empty_match_unicode_captures_iter() {
+    // Same as empty_match_unicode_find_iter, but tests capture iteration.
+    let re = regex!(r".*?");
+    let ms: Vec<_> = re
+        .captures_iter(text!("Ⅰ1Ⅱ2"))
+        .map(|c| c.get(0).unwrap())
+        .map(|m| (m.start(), m.end()))
+        .collect();
+    assert_eq!(vec![(0, 0), (3, 3), (4, 4), (7, 7), (8, 8)], ms);
+}
+
+#[test]
+fn match_as_str() {
+    let re = regex!(r"fo+");
+    let caps = re.captures("barfoobar").unwrap();
+    assert_eq!(caps.get(0).map(|m| m.as_str()), Some("foo"));
+    assert_eq!(caps.get(0).map(From::from), Some("foo"));
+    assert_eq!(caps.get(0).map(Into::into), Some("foo"));
+}
diff --git a/vendor/regex-1.4.6/tests/bytes.rs b/vendor/regex-1.4.6/tests/bytes.rs
new file mode 100644 (file)
index 0000000..d05f138
--- /dev/null
@@ -0,0 +1,107 @@
+// These are tests specifically crafted for regexes that can match arbitrary
+// bytes.
+
+// A silly wrapper to make it possible to write and match raw bytes.
+struct R<'a>(&'a [u8]);
+impl<'a> R<'a> {
+    fn as_bytes(&self) -> &'a [u8] {
+        self.0
+    }
+}
+
+mat!(word_boundary, r"(?-u) \b", " δ", None);
+#[cfg(feature = "unicode-perl")]
+mat!(word_boundary_unicode, r" \b", " δ", Some((0, 1)));
+mat!(word_not_boundary, r"(?-u) \B", " δ", Some((0, 1)));
+#[cfg(feature = "unicode-perl")]
+mat!(word_not_boundary_unicode, r" \B", " δ", None);
+
+mat!(perl_w_ascii, r"(?-u)\w+", "aδ", Some((0, 1)));
+#[cfg(feature = "unicode-perl")]
+mat!(perl_w_unicode, r"\w+", "aδ", Some((0, 3)));
+mat!(perl_d_ascii, r"(?-u)\d+", "1२३9", Some((0, 1)));
+#[cfg(feature = "unicode-perl")]
+mat!(perl_d_unicode, r"\d+", "1२३9", Some((0, 8)));
+mat!(perl_s_ascii, r"(?-u)\s+", " \u{1680}", Some((0, 1)));
+#[cfg(feature = "unicode-perl")]
+mat!(perl_s_unicode, r"\s+", " \u{1680}", Some((0, 4)));
+
+// The first `(.+)` matches two Unicode codepoints, but can't match the 5th
+// byte, which isn't valid UTF-8. The second (byte based) `(.+)` takes over and
+// matches.
+mat!(
+    mixed1,
+    r"(.+)(?-u)(.+)",
+    R(b"\xCE\x93\xCE\x94\xFF"),
+    Some((0, 5)),
+    Some((0, 4)),
+    Some((4, 5))
+);
+
+mat!(case_ascii_one, r"(?i-u)a", "A", Some((0, 1)));
+mat!(case_ascii_class, r"(?i-u)[a-z]+", "AaAaA", Some((0, 5)));
+#[cfg(feature = "unicode-case")]
+mat!(case_unicode, r"(?i)[a-z]+", "aA\u{212A}aA", Some((0, 7)));
+mat!(case_not_unicode, r"(?i-u)[a-z]+", "aA\u{212A}aA", Some((0, 2)));
+
+mat!(negate_unicode, r"[^a]", "δ", Some((0, 2)));
+mat!(negate_not_unicode, r"(?-u)[^a]", "δ", Some((0, 1)));
+
+// This doesn't match in a normal Unicode regex because the implicit preceding
+// `.*?` is Unicode aware.
+mat!(dotstar_prefix_not_unicode1, r"(?-u)a", R(b"\xFFa"), Some((1, 2)));
+mat!(dotstar_prefix_not_unicode2, r"a", R(b"\xFFa"), Some((1, 2)));
+
+// Have fun with null bytes.
+mat!(
+    null_bytes,
+    r"(?-u)(?P<cstr>[^\x00]+)\x00",
+    R(b"foo\x00"),
+    Some((0, 4)),
+    Some((0, 3))
+);
+
+// Test that lookahead operators work properly in the face of invalid UTF-8.
+// See: https://github.com/rust-lang/regex/issues/277
+matiter!(
+    invalidutf8_anchor1,
+    r"(?-u)\xcc?^",
+    R(b"\x8d#;\x1a\xa4s3\x05foobarX\\\x0f0t\xe4\x9b\xa4"),
+    (0, 0)
+);
+matiter!(
+    invalidutf8_anchor2,
+    r"(?-u)^\xf7|4\xff\d\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a##########[] d\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a##########\[] #####\x80\S7|$",
+    R(b"\x8d#;\x1a\xa4s3\x05foobarX\\\x0f0t\xe4\x9b\xa4"),
+    (22, 22)
+);
+matiter!(
+    invalidutf8_anchor3,
+    r"(?-u)^|ddp\xff\xffdddddlQd@\x80",
+    R(b"\x8d#;\x1a\xa4s3\x05foobarX\\\x0f0t\xe4\x9b\xa4"),
+    (0, 0)
+);
+
+// See https://github.com/rust-lang/regex/issues/303
+#[test]
+fn negated_full_byte_range() {
+    assert!(::regex::bytes::Regex::new(r#"(?-u)[^\x00-\xff]"#).is_err());
+}
+
+matiter!(word_boundary_ascii1, r"(?-u:\B)x(?-u:\B)", "áxβ");
+matiter!(
+    word_boundary_ascii2,
+    r"(?-u:\B)",
+    "0\u{7EF5E}",
+    (2, 2),
+    (3, 3),
+    (4, 4),
+    (5, 5)
+);
+
+// See: https://github.com/rust-lang/regex/issues/264
+mat!(ascii_boundary_no_capture, r"(?-u)\B", "\u{28f3e}", Some((0, 0)));
+mat!(ascii_boundary_capture, r"(?-u)(\B)", "\u{28f3e}", Some((0, 0)));
+
+// See: https://github.com/rust-lang/regex/issues/271
+mat!(end_not_wb, r"$(?-u:\B)", "\u{5c124}\u{b576c}", Some((8, 8)));
diff --git a/vendor/regex-1.4.6/tests/consistent.rs b/vendor/regex-1.4.6/tests/consistent.rs
new file mode 100644 (file)
index 0000000..722f2a5
--- /dev/null
@@ -0,0 +1,238 @@
+use regex::internal::ExecBuilder;
+
+/// Given a regex, check if all of the backends produce the same
+/// results on a number of different inputs.
+///
+/// For now this just throws quickcheck at the problem, which
+/// is not very good because it only really tests half of the
+/// problem space. It is pretty unlikely that a random string
+/// will match any given regex, so this will probably just
+/// be checking that the different backends fail in the same
+/// way. This is still worthwhile to test, but is definitely not
+/// the whole story.
+///
+/// TODO(ethan): In order to cover the other half of the problem
+/// space, we should generate a random matching string by inspecting
+/// the AST of the input regex. The right way to do this probably
+/// involves adding a custom Arbitrary instance around a couple
+/// of newtypes. That way we can respect the quickcheck size hinting
+/// and shrinking and whatnot.
+pub fn backends_are_consistent(re: &str) -> Result<u64, String> {
+    let standard_backends = vec![
+        (
+            "bounded_backtracking_re",
+            ExecBuilder::new(re)
+                .bounded_backtracking()
+                .build()
+                .map(|exec| exec.into_regex())
+                .map_err(|err| format!("{}", err))?,
+        ),
+        (
+            "pikevm_re",
+            ExecBuilder::new(re)
+                .nfa()
+                .build()
+                .map(|exec| exec.into_regex())
+                .map_err(|err| format!("{}", err))?,
+        ),
+        (
+            "default_re",
+            ExecBuilder::new(re)
+                .build()
+                .map(|exec| exec.into_regex())
+                .map_err(|err| format!("{}", err))?,
+        ),
+    ];
+
+    let utf8bytes_backends = vec![
+        (
+            "bounded_backtracking_utf8bytes_re",
+            ExecBuilder::new(re)
+                .bounded_backtracking()
+                .bytes(true)
+                .build()
+                .map(|exec| exec.into_regex())
+                .map_err(|err| format!("{}", err))?,
+        ),
+        (
+            "pikevm_utf8bytes_re",
+            ExecBuilder::new(re)
+                .nfa()
+                .bytes(true)
+                .build()
+                .map(|exec| exec.into_regex())
+                .map_err(|err| format!("{}", err))?,
+        ),
+        (
+            "default_utf8bytes_re",
+            ExecBuilder::new(re)
+                .bytes(true)
+                .build()
+                .map(|exec| exec.into_regex())
+                .map_err(|err| format!("{}", err))?,
+        ),
+    ];
+
+    let bytes_backends = vec![
+        (
+            "bounded_backtracking_bytes_re",
+            ExecBuilder::new(re)
+                .bounded_backtracking()
+                .only_utf8(false)
+                .build()
+                .map(|exec| exec.into_byte_regex())
+                .map_err(|err| format!("{}", err))?,
+        ),
+        (
+            "pikevm_bytes_re",
+            ExecBuilder::new(re)
+                .nfa()
+                .only_utf8(false)
+                .build()
+                .map(|exec| exec.into_byte_regex())
+                .map_err(|err| format!("{}", err))?,
+        ),
+        (
+            "default_bytes_re",
+            ExecBuilder::new(re)
+                .only_utf8(false)
+                .build()
+                .map(|exec| exec.into_byte_regex())
+                .map_err(|err| format!("{}", err))?,
+        ),
+    ];
+
+    Ok(string_checker::check_backends(&standard_backends)?
+        + string_checker::check_backends(&utf8bytes_backends)?
+        + bytes_checker::check_backends(&bytes_backends)?)
+}
+
+//
+// A consistency checker parameterized by the input type (&str or &[u8]).
+//
+
+macro_rules! checker {
+    ($module_name:ident, $regex_type:path, $mk_input:expr) => {
+        mod $module_name {
+            use quickcheck;
+            use quickcheck::{Arbitrary, TestResult};
+
+            pub fn check_backends(
+                backends: &[(&str, $regex_type)],
+            ) -> Result<u64, String> {
+                let mut total_passed = 0;
+                for regex in backends[1..].iter() {
+                    total_passed += quickcheck_regex_eq(&backends[0], regex)?;
+                }
+
+                Ok(total_passed)
+            }
+
+            fn quickcheck_regex_eq(
+                &(name1, ref re1): &(&str, $regex_type),
+                &(name2, ref re2): &(&str, $regex_type),
+            ) -> Result<u64, String> {
+                quickcheck::QuickCheck::new()
+                    .quicktest(RegexEqualityTest::new(
+                        re1.clone(),
+                        re2.clone(),
+                    ))
+                    .map_err(|err| {
+                        format!(
+                            "{}(/{}/) and {}(/{}/) are inconsistent.\
+                             QuickCheck Err: {:?}",
+                            name1, re1, name2, re2, err
+                        )
+                    })
+            }
+
+            struct RegexEqualityTest {
+                re1: $regex_type,
+                re2: $regex_type,
+            }
+            impl RegexEqualityTest {
+                fn new(re1: $regex_type, re2: $regex_type) -> Self {
+                    RegexEqualityTest { re1: re1, re2: re2 }
+                }
+            }
+
+            impl quickcheck::Testable for RegexEqualityTest {
+                fn result(&self, gen: &mut quickcheck::Gen) -> TestResult {
+                    let input = $mk_input(gen);
+                    let input = &input;
+
+                    if self.re1.find(&input) != self.re2.find(input) {
+                        return TestResult::error(format!(
+                            "find mismatch input={:?}",
+                            input
+                        ));
+                    }
+
+                    let cap1 = self.re1.captures(input);
+                    let cap2 = self.re2.captures(input);
+                    match (cap1, cap2) {
+                        (None, None) => {}
+                        (Some(cap1), Some(cap2)) => {
+                            for (c1, c2) in cap1.iter().zip(cap2.iter()) {
+                                if c1 != c2 {
+                                    return TestResult::error(format!(
+                                        "captures mismatch input={:?}",
+                                        input
+                                    ));
+                                }
+                            }
+                        }
+                        _ => {
+                            return TestResult::error(format!(
+                                "captures mismatch input={:?}",
+                                input
+                            ))
+                        }
+                    }
+
+                    let fi1 = self.re1.find_iter(input);
+                    let fi2 = self.re2.find_iter(input);
+                    for (m1, m2) in fi1.zip(fi2) {
+                        if m1 != m2 {
+                            return TestResult::error(format!(
+                                "find_iter mismatch input={:?}",
+                                input
+                            ));
+                        }
+                    }
+
+                    let ci1 = self.re1.captures_iter(input);
+                    let ci2 = self.re2.captures_iter(input);
+                    for (cap1, cap2) in ci1.zip(ci2) {
+                        for (c1, c2) in cap1.iter().zip(cap2.iter()) {
+                            if c1 != c2 {
+                                return TestResult::error(format!(
+                                    "captures_iter mismatch input={:?}",
+                                    input
+                                ));
+                            }
+                        }
+                    }
+
+                    let s1 = self.re1.split(input);
+                    let s2 = self.re2.split(input);
+                    for (chunk1, chunk2) in s1.zip(s2) {
+                        if chunk1 != chunk2 {
+                            return TestResult::error(format!(
+                                "split mismatch input={:?}",
+                                input
+                            ));
+                        }
+                    }
+
+                    TestResult::from_bool(true)
+                }
+            }
+        } // mod
+    }; // rule case
+} // macro_rules!
+
+checker!(string_checker, ::regex::Regex, |gen| String::arbitrary(gen));
+checker!(bytes_checker, ::regex::bytes::Regex, |gen| Vec::<u8>::arbitrary(
+    gen
+));
diff --git a/vendor/regex-1.4.6/tests/crates_regex.rs b/vendor/regex-1.4.6/tests/crates_regex.rs
new file mode 100644 (file)
index 0000000..200ec27
--- /dev/null
@@ -0,0 +1,3287 @@
+// DO NOT EDIT. Automatically generated by 'scripts/scrape_crates_io.py'
+// on 2018-06-20 09:56:32.820354.
+
+// autoshutdown-0.1.0: r"\s*(\d+)(\w)\s*"
+consistent!(autoshutdown_0, r"\s*(\d+)(\w)\s*");
+
+// epub-1.1.1: r"/"
+consistent!(epub_0, r"/");
+
+// rpi-info-0.2.0: "^Revision\t+: ([0-9a-fA-F]+)"
+consistent!(rpi_info_0, "^Revision\t+: ([0-9a-fA-F]+)");
+
+// rpi-info-0.2.0: "Serial\t+: ([0-9a-fA-F]+)"
+consistent!(rpi_info_1, "Serial\t+: ([0-9a-fA-F]+)");
+
+// pnet_macros-0.21.0: r"^u([0-9]+)(be|le|he)?$"
+consistent!(pnet_macros_0, r"^u([0-9]+)(be|le|he)?$");
+
+// iban_validate-1.0.3: r"^[A-Z]{2}\d{2}[A-Z\d]{1,30}$"
+consistent!(iban_validate_0, r"^[A-Z]{2}\d{2}[A-Z\d]{1,30}$");
+
+// markifier-0.1.0: r".*\[(?P<percent>.+)%.*\].*"
+consistent!(markifier_0, r".*\[(?P<percent>.+)%.*\].*");
+
+// mallumo-0.3.0: r"(#include) (\S*)(.*)"
+consistent!(mallumo_0, r"(#include) (\S*)(.*)");
+
+// mallumo-0.3.0: r"(ERROR: \d+:)(\d+)(: )(.+)"
+consistent!(mallumo_1, r"(ERROR: \d+:)(\d+)(: )(.+)");
+
+// mallumo-0.3.0: r"(\d+\()(\d+)(?:\) : )(.+)"
+consistent!(mallumo_2, r"(\d+\()(\d+)(?:\) : )(.+)");
+
+// magnet_more-0.0.1: r"(.+?)(\[.*?\])?"
+consistent!(magnet_more_0, r"(.+?)(\[.*?\])?");
+
+// magnet_app-0.0.1: r":(?P<k>[a-zA-Z_]+)"
+consistent!(magnet_app_0, r":(?P<k>[a-zA-Z_]+)");
+
+// yubibomb-0.2.0: r"^\d{6}(?:\s*,\s*\d{6})*$"
+consistent!(yubibomb_0, r"^\d{6}(?:\s*,\s*\d{6})*$");
+
+// multirust-rs-0.0.4: r"[\\/]([^\\/?]+)(\?.*)?$"
+consistent!(multirust_rs_0, r"[\\/]([^\\/?]+)(\?.*)?$");
+
+// hueclient-0.3.2: "\"[a-z]*\":null"
+consistent!(hueclient_0, "\"[a-z]*\":null");
+
+// hueclient-0.3.2: ",+"
+consistent!(hueclient_1, ",+");
+
+// hueclient-0.3.2: ",\\}"
+consistent!(hueclient_2, ",\\}");
+
+// hueclient-0.3.2: "\\{,"
+consistent!(hueclient_3, "\\{,");
+
+// aerial-0.1.0: r"[a-zA-Z_\$][a-zA-Z_0-9]*"
+consistent!(aerial_0, r"[a-zA-Z_\$][a-zA-Z_0-9]*");
+
+// aerial-0.1.0: r"thi[sng]+"
+consistent!(aerial_1, r"thi[sng]+");
+
+// rvue-0.1.0: r"(.+)\s+\((.+?)\)"
+consistent!(rvue_0, r"(.+)\s+\((.+?)\)");
+
+// rvue-0.1.0: r"([\d\.]+)\s*out\s*of\s*([\d\.]+)"
+consistent!(rvue_1, r"([\d\.]+)\s*out\s*of\s*([\d\.]+)");
+
+// rvue-0.1.0: r"^([\d\.]+)\s*(?:\(\))?$"
+consistent!(rvue_2, r"^([\d\.]+)\s*(?:\(\))?$");
+
+// rvue-0.1.0: r"([\d\.]+)\s*Points\s*Possible"
+consistent!(rvue_3, r"([\d\.]+)\s*Points\s*Possible");
+
+// rvue-0.1.0: r"([\d\.]+)\s*/\s*([\d\.]+)"
+consistent!(rvue_4, r"([\d\.]+)\s*/\s*([\d\.]+)");
+
+// rvsim-0.1.0: r"_?([_a-z0-9]+)\s*:\s*([_a-z0-9]+)\s*[,)]"
+consistent!(rvsim_0, r"_?([_a-z0-9]+)\s*:\s*([_a-z0-9]+)\s*[,)]");
+
+// nereon-0.1.4: "(.*[^\\\\])\\{\\}(.*)"
+consistent!(nereon_0, "(.*[^\\\\])\\{\\}(.*)");
+
+// next_episode-0.3.0: r"((?i)^(.+).s(\d+)e(\d+).*)$"
+consistent!(next_episode_0, r"((?i)^(.+).s(\d+)e(\d+).*)$");
+
+// migrant_lib-0.19.2: r"[^a-z0-9-]+"
+consistent!(migrant_lib_0, r"[^a-z0-9-]+");
+
+// migrant_lib-0.19.2: r"[0-9]{14}_[a-z0-9-]+"
+consistent!(migrant_lib_1, r"[0-9]{14}_[a-z0-9-]+");
+
+// migrant_lib-0.19.2: r"([0-9]{14}_)?[a-z0-9-]+"
+consistent!(migrant_lib_2, r"([0-9]{14}_)?[a-z0-9-]+");
+
+// minipre-0.2.0: "$_"
+consistent!(minipre_0, "$_");
+
+// minifier-0.0.13: r">\s+<"
+consistent!(minifier_0, r">\s+<");
+
+// minifier-0.0.13: r"\s{2,}|[\r\n]"
+consistent!(minifier_1, r"\s{2,}|[\r\n]");
+
+// minifier-0.0.13: r"<(style|script)[\w|\s].*?>"
+consistent!(minifier_2, r"<(style|script)[\w|\s].*?>");
+
+// minifier-0.0.13: "<!--(.|\n)*?-->"
+consistent!(minifier_3, "<!--(.|\n)*?-->");
+
+// minifier-0.0.13: r"<\w.*?>"
+consistent!(minifier_4, r"<\w.*?>");
+
+// minifier-0.0.13: r" \s+|\s +"
+consistent!(minifier_5, r" \s+|\s +");
+
+// minifier-0.0.13: r"\w\s+\w"
+consistent!(minifier_6, r"\w\s+\w");
+
+// minifier-0.0.13: r"'\s+>"
+consistent!(minifier_7, r"'\s+>");
+
+// minifier-0.0.13: r"\d\s+>"
+consistent!(minifier_8, r"\d\s+>");
+
+// ggp-rs-0.1.2: r"(?P<relation>\([^)]+\))|(?P<prop>[a-zA-Z0-9_]+)"
+consistent!(ggp_rs_0, r"(?P<relation>\([^)]+\))|(?P<prop>[a-zA-Z0-9_]+)");
+
+// ggp-rs-0.1.2: r"\((.*)\)."
+consistent!(ggp_rs_1, r"\((.*)\).");
+
+// poe-superfilter-0.2.0: "[A-Za-z0-9_]"
+consistent!(poe_superfilter_0, "[A-Za-z0-9_]");
+
+// poke-a-mango-0.5.0: r"(\d+)x(\d+)"
+consistent!(poke_a_mango_0, r"(\d+)x(\d+)");
+
+// pop3-rs-0.1.0: r"(?P<nmsg>\d+) (?P<size>\d+)"
+consistent!(pop3_rs_0, r"(?P<nmsg>\d+) (?P<size>\d+)");
+
+// pop3-rs-0.1.0: r"(?P<msgid>\d+) (?P<uidl>[\x21-\x7E]{1,70})"
+consistent!(pop3_rs_1, r"(?P<msgid>\d+) (?P<uidl>[\x21-\x7E]{1,70})");
+
+// pop3-rs-0.1.0: r"(<.*>)\r\n$"
+consistent!(pop3_rs_2, r"(<.*>)\r\n$");
+
+// pop3-rs-0.1.0: r"^(?P<status>\+OK|-ERR) (?P<statustext>.*)"
+consistent!(pop3_rs_3, r"^(?P<status>\+OK|-ERR) (?P<statustext>.*)");
+
+// pop3-1.0.6: r"^\.\r\n$"
+consistent!(pop3_0, r"^\.\r\n$");
+
+// pop3-1.0.6: r"\+OK(.*)"
+consistent!(pop3_1, r"\+OK(.*)");
+
+// pop3-1.0.6: r"-ERR(.*)"
+consistent!(pop3_2, r"-ERR(.*)");
+
+// pop3-1.0.6: r"\+OK (\d+) (\d+)\r\n"
+consistent!(pop3_3, r"\+OK (\d+) (\d+)\r\n");
+
+// pop3-1.0.6: r"(\d+) ([\x21-\x7e]+)\r\n"
+consistent!(pop3_4, r"(\d+) ([\x21-\x7e]+)\r\n");
+
+// pop3-1.0.6: r"\+OK (\d+) ([\x21-\x7e]+)\r\n"
+consistent!(pop3_5, r"\+OK (\d+) ([\x21-\x7e]+)\r\n");
+
+// pop3-1.0.6: r"(\d+) (\d+)\r\n"
+consistent!(pop3_6, r"(\d+) (\d+)\r\n");
+
+// pop3-1.0.6: r"\+OK (\d+) (\d+)\r\n"
+consistent!(pop3_7, r"\+OK (\d+) (\d+)\r\n");
+
+// polk-1.1.3: "github:(\\w+)/?(\\w+)?"
+consistent!(polk_0, "github:(\\w+)/?(\\w+)?");
+
+// geochunk-0.1.5: "^[0-9]{5}"
+consistent!(geochunk_0, "^[0-9]{5}");
+
+// generic-dns-update-1.1.4: r"((?:(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?)\.){3}(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?))"
+consistent!(generic_dns_update_0, r"((?:(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?)\.){3}(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?))");
+
+// generic-dns-update-1.1.4: r"((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(([0-9A-Fa-f]{1,4}:){0,5}:((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(::([0-9A-Fa-f]{1,4}:){0,5}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))"
+consistent!(generic_dns_update_1, r"((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(([0-9A-Fa-f]{1,4}:){0,5}:((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(::([0-9A-Fa-f]{1,4}:){0,5}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))");
+
+// generic-dns-update-1.1.4: r"<value><string>([0-9.]*)</string></value>"
+consistent!(
+    generic_dns_update_2,
+    r"<value><string>([0-9.]*)</string></value>"
+);
+
+// generic-dns-update-1.1.4: r"<int>([0-9]+)</int>"
+consistent!(generic_dns_update_3, r"<int>([0-9]+)</int>");
+
+// generic-dns-update-1.1.4: r"<int>([0-9]+)</int>"
+consistent!(generic_dns_update_4, r"<int>([0-9]+)</int>");
+
+// generic-dns-update-1.1.4: r"<boolean>([0-1]*)</boolean>"
+consistent!(generic_dns_update_5, r"<boolean>([0-1]*)</boolean>");
+
+// generate-nix-pkg-0.3.0: r"(\d*)\.(\d*)\.(\d*)(-(\S*))?"
+consistent!(generate_nix_pkg_0, r"(\d*)\.(\d*)\.(\d*)(-(\S*))?");
+
+// generate-nix-pkg-0.3.0: r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?"
+consistent!(generate_nix_pkg_1, r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?");
+
+// genact-0.6.0: r"arch/([a-z0-9_])+/"
+consistent!(genact_0, r"arch/([a-z0-9_])+/");
+
+// genact-0.6.0: r"arch/([a-z0-9_])+/"
+consistent!(genact_1, r"arch/([a-z0-9_])+/");
+
+// cron_rs-0.1.6: r"^\s*((\*(/\d+)?)|[0-9-,/]+)(\s+((\*(/\d+)?)|[0-9-,/]+)){4,5}\s*$"
+consistent!(
+    cron_rs_0,
+    r"^\s*((\*(/\d+)?)|[0-9-,/]+)(\s+((\*(/\d+)?)|[0-9-,/]+)){4,5}\s*$"
+);
+
+// systemfd-0.3.0: r"^([a-zA-Z]+)::(.+)$"
+consistent!(systemfd_0, r"^([a-zA-Z]+)::(.+)$");
+
+// symbolic-debuginfo-5.0.2: "__?hidden#\\d+_"
+consistent!(symbolic_debuginfo_0, "__?hidden#\\d+_");
+
+// symbolic-minidump-5.0.2: r"^Linux ([^ ]+) (.*) \w+(?: GNU/Linux)?$"
+consistent!(symbolic_minidump_0, r"^Linux ([^ ]+) (.*) \w+(?: GNU/Linux)?$");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\#)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+"
+consistent!(graphql_idl_parser_0, "^(?u:\\#)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+");
+
+// graphql-idl-parser-0.1.1: "^(?u:=)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+"
+consistent!(graphql_idl_parser_1, "^(?u:=)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+");
+
+// graphql-idl-parser-0.1.1: "^(?u:[A-Z_-_a-z])(?u:[0-9A-Z_-_a-z])*"
+consistent!(graphql_idl_parser_2, "^(?u:[A-Z_-_a-z])(?u:[0-9A-Z_-_a-z])*");
+
+// graphql-idl-parser-0.1.1: "^(?u:!)"
+consistent!(graphql_idl_parser_3, "^(?u:!)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\()"
+consistent!(graphql_idl_parser_4, "^(?u:\\()");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\))"
+consistent!(graphql_idl_parser_5, "^(?u:\\))");
+
+// graphql-idl-parser-0.1.1: "^(?u:,)"
+consistent!(graphql_idl_parser_6, "^(?u:,)");
+
+// graphql-idl-parser-0.1.1: "^(?u::)"
+consistent!(graphql_idl_parser_7, "^(?u::)");
+
+// graphql-idl-parser-0.1.1: "^(?u:@)"
+consistent!(graphql_idl_parser_8, "^(?u:@)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\[)"
+consistent!(graphql_idl_parser_9, "^(?u:\\[)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\])"
+consistent!(graphql_idl_parser_10, "^(?u:\\])");
+
+// graphql-idl-parser-0.1.1: "^(?u:enum)"
+consistent!(graphql_idl_parser_11, "^(?u:enum)");
+
+// graphql-idl-parser-0.1.1: "^(?u:implements)"
+consistent!(graphql_idl_parser_12, "^(?u:implements)");
+
+// graphql-idl-parser-0.1.1: "^(?u:input)"
+consistent!(graphql_idl_parser_13, "^(?u:input)");
+
+// graphql-idl-parser-0.1.1: "^(?u:interface)"
+consistent!(graphql_idl_parser_14, "^(?u:interface)");
+
+// graphql-idl-parser-0.1.1: "^(?u:scalar)"
+consistent!(graphql_idl_parser_15, "^(?u:scalar)");
+
+// graphql-idl-parser-0.1.1: "^(?u:type)"
+consistent!(graphql_idl_parser_16, "^(?u:type)");
+
+// graphql-idl-parser-0.1.1: "^(?u:union)"
+consistent!(graphql_idl_parser_17, "^(?u:union)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\{)"
+consistent!(graphql_idl_parser_18, "^(?u:\\{)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\})"
+consistent!(graphql_idl_parser_19, "^(?u:\\})");
+
+// grimoire-0.1.0: r"(?s)/\*(?P<config>.*?)\*/"
+consistent!(grimoire_0, r"(?s)/\*(?P<config>.*?)\*/");
+
+// phonenumber-0.2.0+8.9.0: r"[\d]+(?:[~\x{2053}\x{223C}\x{FF5E}][\d]+)?"
+consistent!(phonenumber_0, r"[\d]+(?:[~\x{2053}\x{223C}\x{FF5E}][\d]+)?");
+
+// phonenumber-0.2.0+8.9.0: r"[, \[\]]"
+consistent!(phonenumber_1, r"[, \[\]]");
+
+// phonenumber-0.2.0+8.9.0: r"[\\/] *x"
+consistent!(phonenumber_2, r"[\\/] *x");
+
+// phonenumber-0.2.0+8.9.0: r"[[\P{N}&&\P{L}]&&[^#]]+$"
+consistent!(phonenumber_3, r"[[\P{N}&&\P{L}]&&[^#]]+$");
+
+// phonenumber-0.2.0+8.9.0: r"(?:.*?[A-Za-z]){3}.*"
+consistent!(phonenumber_4, r"(?:.*?[A-Za-z]){3}.*");
+
+// phonenumber-0.2.0+8.9.0: r"(\D+)"
+consistent!(phonenumber_5, r"(\D+)");
+
+// phonenumber-0.2.0+8.9.0: r"(\$\d)"
+consistent!(phonenumber_6, r"(\$\d)");
+
+// phonenumber-0.2.0+8.9.0: r"\(?\$1\)?"
+consistent!(phonenumber_7, r"\(?\$1\)?");
+
+// phone_number-0.1.0: r"\D"
+consistent!(phone_number_0, r"\D");
+
+// phone_number-0.1.0: r"^0+"
+consistent!(phone_number_1, r"^0+");
+
+// phone_number-0.1.0: r"^89"
+consistent!(phone_number_2, r"^89");
+
+// phone_number-0.1.0: r"^8+"
+consistent!(phone_number_3, r"^8+");
+
+// phile-0.1.4: r"^ *(\^_*\^) *$"
+consistent!(phile_0, r"^ *(\^_*\^) *$");
+
+// phile-0.1.4: r"^[_\p{XID_Start}]$"
+consistent!(phile_1, r"^[_\p{XID_Start}]$");
+
+// phile-0.1.4: r"^\p{XID_Continue}$"
+consistent!(phile_2, r"^\p{XID_Continue}$");
+
+// uritemplate-0.1.2: "%25(?P<hex>[0-9a-fA-F][0-9a-fA-F])"
+consistent!(uritemplate_0, "%25(?P<hex>[0-9a-fA-F][0-9a-fA-F])");
+
+// urdf-rs-0.4.2: "^package://(\\w+)/"
+consistent!(urdf_rs_0, "^package://(\\w+)/");
+
+// url-match-0.1.7: r"(?P<key>[?&.])"
+consistent!(url_match_0, r"(?P<key>[?&.])");
+
+// url-match-0.1.7: r":(?P<key>[a-zA-Z0-9_-]+)"
+consistent!(url_match_1, r":(?P<key>[a-zA-Z0-9_-]+)");
+
+// tsm-sys-0.1.0: r"hello world"
+consistent!(tsm_sys_0, r"hello world");
+
+// deb-version-0.1.0: "^(?:(?:(?:\\d+:).+)|(?:[^:]+))$"
+consistent!(deb_version_0, "^(?:(?:(?:\\d+:).+)|(?:[^:]+))$");
+
+// debcargo-2.1.0: r"^(?i)(a|an|the)\s+"
+consistent!(debcargo_0, r"^(?i)(a|an|the)\s+");
+
+// debcargo-2.1.0: r"^(?i)(rust\s+)?(implementation|library|tool|crate)\s+(of|to|for)\s+"
+consistent!(
+    debcargo_1,
+    r"^(?i)(rust\s+)?(implementation|library|tool|crate)\s+(of|to|for)\s+"
+);
+
+// feaders-0.2.0: r"^.*\.h$"
+consistent!(feaders_0, r"^.*\.h$");
+
+// feaders-0.2.0: r"^.*\.c$"
+consistent!(feaders_1, r"^.*\.c$");
+
+// feaders-0.2.0: r"^.*\.hpp$"
+consistent!(feaders_2, r"^.*\.hpp$");
+
+// feaders-0.2.0: r"^.*\.cc$"
+consistent!(feaders_3, r"^.*\.cc$");
+
+// feaders-0.2.0: r"^.*\.cpp$"
+consistent!(feaders_4, r"^.*\.cpp$");
+
+// hyperscan-0.1.6: r"CPtr\(\w+\)"
+consistent!(hyperscan_0, r"CPtr\(\w+\)");
+
+// hyperscan-0.1.6: r"^Version:\s(\d\.\d\.\d)\sFeatures:\s+(\w+)?\sMode:\s(\w+)$"
+consistent!(
+    hyperscan_1,
+    r"^Version:\s(\d\.\d\.\d)\sFeatures:\s+(\w+)?\sMode:\s(\w+)$"
+);
+
+// hyperscan-0.1.6: r"RawDatabase<Block>\{db: \w+\}"
+consistent!(hyperscan_2, r"RawDatabase<Block>\{db: \w+\}");
+
+// hyperscan-0.1.6: r"RawSerializedDatabase\{p: \w+, len: \d+\}"
+consistent!(hyperscan_3, r"RawSerializedDatabase\{p: \w+, len: \d+\}");
+
+// ucd-parse-0.1.1: r"[0-9A-F]+"
+consistent!(ucd_parse_0, r"[0-9A-F]+");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_0, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_1, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_2, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_3, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_4, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_5, r".*");
+
+// afsort-0.2.0: r"^[a-z]+$"
+consistent!(afsort_6, r"^[a-z]+$");
+
+// afsort-0.2.0: r"^[a-z]+$"
+consistent!(afsort_7, r"^[a-z]+$");
+
+// tin-summer-1.21.4: r"(\.git|\.pijul|_darcs|\.hg)$"
+consistent!(tin_summer_0, r"(\.git|\.pijul|_darcs|\.hg)$");
+
+// tin-drummer-1.0.1: r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
+consistent!(tin_drummer_0, r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
+
+// tin-drummer-1.0.1: r".*?\.(stats|conf|h|out|cache.*|dat|pc|info|\.js)$"
+consistent!(
+    tin_drummer_1,
+    r".*?\.(stats|conf|h|out|cache.*|dat|pc|info|\.js)$"
+);
+
+// tin-drummer-1.0.1: r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
+consistent!(tin_drummer_2, r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
+
+// tin-drummer-1.0.1: r".*?\.(stats|conf|h|out|cache.*|\.js)$"
+consistent!(tin_drummer_3, r".*?\.(stats|conf|h|out|cache.*|\.js)$");
+
+// tin-drummer-1.0.1: r"(\.git|\.pijul|_darcs|\.hg)$"
+consistent!(tin_drummer_4, r"(\.git|\.pijul|_darcs|\.hg)$");
+
+// tin-drummer-1.0.1: r".*?\.(dyn_o|out|d|hi|dyn_hi|dump-.*|p_hi|p_o|prof|tix)$"
+consistent!(
+    tin_drummer_5,
+    r".*?\.(dyn_o|out|d|hi|dyn_hi|dump-.*|p_hi|p_o|prof|tix)$"
+);
+
+// tin-drummer-1.0.1: r".*?\.(ibc)$"
+consistent!(tin_drummer_6, r".*?\.(ibc)$");
+
+// tin-drummer-1.0.1: r"\.stack-work|dist-newstyle"
+consistent!(tin_drummer_7, r"\.stack-work|dist-newstyle");
+
+// timmy-0.3.0: r"_NET_WM_PID\(CARDINAL\) = (\d+)"
+consistent!(timmy_0, r"_NET_WM_PID\(CARDINAL\) = (\d+)");
+
+// timmy-0.3.0: r"today|yesterday|now"
+consistent!(timmy_1, r"today|yesterday|now");
+
+// timmy-0.3.0: r"(?P<day>\d{1,2})/(?P<month>\d{1,2})(/(?P<year>\d{4}|\d{2}))?"
+consistent!(
+    timmy_2,
+    r"(?P<day>\d{1,2})/(?P<month>\d{1,2})(/(?P<year>\d{4}|\d{2}))?"
+);
+
+// timmy-0.3.0: r"(?P<n>\d+) (days?|ds?)(?P<ago>( ago)?)"
+consistent!(timmy_3, r"(?P<n>\d+) (days?|ds?)(?P<ago>( ago)?)");
+
+// timmy-0.3.0: r"(?P<hr>\d{2}):(?P<mins>\d{2})"
+consistent!(timmy_4, r"(?P<hr>\d{2}):(?P<mins>\d{2})");
+
+// tinfo-0.5.0: r"^(\d+): \d+ windows \(.*\) \[\d+x\d+\]( \(attached\))?"
+consistent!(
+    tinfo_0,
+    r"^(\d+): \d+ windows \(.*\) \[\d+x\d+\]( \(attached\))?"
+);
+
+// tinfo-0.5.0: r"^(\d+):(\d+): (.*) \((\d+) panes\) \[(\d+)x(\d+)\]"
+consistent!(tinfo_1, r"^(\d+):(\d+): (.*) \((\d+) panes\) \[(\d+)x(\d+)\]");
+
+// timespan-0.0.4: r"(?:\\\{start\\\}|\\\{end\\\})"
+consistent!(timespan_0, r"(?:\\\{start\\\}|\\\{end\\\})");
+
+// timespan-0.0.4: r"(.*)\s+-\s+(.*)"
+consistent!(timespan_1, r"(.*)\s+-\s+(.*)");
+
+// timespan-0.0.4: r"(.*)\s+(\w+)$"
+consistent!(timespan_2, r"(.*)\s+(\w+)$");
+
+// timespan-0.0.4: r"(.*)\s+(\w+)$"
+consistent!(timespan_3, r"(.*)\s+(\w+)$");
+
+// timespan-0.0.4: r"(.*)\s+-\s+(.*)"
+consistent!(timespan_4, r"(.*)\s+-\s+(.*)");
+
+// titlecase-0.10.0: r"[[:lower:]]"
+consistent!(titlecase_0, r"[[:lower:]]");
+
+// tight-0.1.3: r"^\d+ (day|week|month|year)s?$"
+consistent!(tight_0, r"^\d+ (day|week|month|year)s?$");
+
+// tight-0.1.3: r"^\d+ (day|week|month|year)s?$"
+consistent!(tight_1, r"^\d+ (day|week|month|year)s?$");
+
+// yaml-0.2.1: r"^[-+]?(0|[1-9][0-9_]*)$"
+consistent!(yaml_0, r"^[-+]?(0|[1-9][0-9_]*)$");
+
+// yaml-0.2.1: r"^([-+]?)0o?([0-7_]+)$"
+consistent!(yaml_1, r"^([-+]?)0o?([0-7_]+)$");
+
+// yaml-0.2.1: r"^([-+]?)0x([0-9a-fA-F_]+)$"
+consistent!(yaml_2, r"^([-+]?)0x([0-9a-fA-F_]+)$");
+
+// yaml-0.2.1: r"^([-+]?)0b([0-1_]+)$"
+consistent!(yaml_3, r"^([-+]?)0b([0-1_]+)$");
+
+// yaml-0.2.1: r"^([-+]?)(\.[0-9]+|[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?)$"
+consistent!(
+    yaml_4,
+    r"^([-+]?)(\.[0-9]+|[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?)$"
+);
+
+// yaml-0.2.1: r"^[+]?(\.inf|\.Inf|\.INF)$"
+consistent!(yaml_5, r"^[+]?(\.inf|\.Inf|\.INF)$");
+
+// yaml-0.2.1: r"^-(\.inf|\.Inf|\.INF)$"
+consistent!(yaml_6, r"^-(\.inf|\.Inf|\.INF)$");
+
+// yaml-0.2.1: r"^(\.nan|\.NaN|\.NAN)$"
+consistent!(yaml_7, r"^(\.nan|\.NaN|\.NAN)$");
+
+// yaml-0.2.1: r"^(null|Null|NULL|~)$"
+consistent!(yaml_8, r"^(null|Null|NULL|~)$");
+
+// yaml-0.2.1: r"^(true|True|TRUE|yes|Yes|YES)$"
+consistent!(yaml_9, r"^(true|True|TRUE|yes|Yes|YES)$");
+
+// yaml-0.2.1: r"^(false|False|FALSE|no|No|NO)$"
+consistent!(yaml_10, r"^(false|False|FALSE|no|No|NO)$");
+
+// kefia-0.1.0: r"(?m)^(\S+)/(\S+) (\S+)(?: \((.*)\))?$"
+consistent!(kefia_0, r"(?m)^(\S+)/(\S+) (\S+)(?: \((.*)\))?$");
+
+// risp-0.7.0: "^(\\s+|;.*?(\n|$))+"
+consistent!(risp_0, "^(\\s+|;.*?(\n|$))+");
+
+// risp-0.7.0: "^\".*?\""
+consistent!(risp_1, "^\".*?\"");
+
+// risp-0.7.0: r"^[^\s\{\}()\[\]]+"
+consistent!(risp_2, r"^[^\s\{\}()\[\]]+");
+
+// risp-0.7.0: r"^-?\d+"
+consistent!(risp_3, r"^-?\d+");
+
+// ripgrep-0.8.1: "^([0-9]+)([KMG])?$"
+consistent!(ripgrep_0, "^([0-9]+)([KMG])?$");
+
+// riquid-0.0.1: r"^\w+"
+consistent!(riquid_0, r"^\w+");
+
+// riquid-0.0.1: r"^\d+"
+consistent!(riquid_1, r"^\d+");
+
+// recursive_disassembler-2.1.2: r"\A(0x)?([a-fA-F0-9]+)\z"
+consistent!(recursive_disassembler_0, r"\A(0x)?([a-fA-F0-9]+)\z");
+
+// remake-0.1.0: r"^[a-zA-Z_][a-zA-Z0-9_]*"
+consistent!(remake_0, r"^[a-zA-Z_][a-zA-Z0-9_]*");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_0, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_1, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_2, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_3, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_4, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_5, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{2})\)"
+consistent!(regex_decode_6, r"'(?P<title>[^']+)'\s+\((?P<year>\d{2})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_7, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_8, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_9, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_10, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_11, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_12, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_13, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-cache-0.2.0: "[0-9]{3}-[0-9]{3}-[0-9]{4}"
+consistent!(regex_cache_0, "[0-9]{3}-[0-9]{3}-[0-9]{4}");
+
+// regex-cache-0.2.0: r"^\d+$"
+consistent!(regex_cache_1, r"^\d+$");
+
+// regex-cache-0.2.0: r"^[a-z]+$"
+consistent!(regex_cache_2, r"^[a-z]+$");
+
+// regex-cache-0.2.0: r"^\d+$"
+consistent!(regex_cache_3, r"^\d+$");
+
+// regex-cache-0.2.0: r"^\d+$"
+consistent!(regex_cache_4, r"^\d+$");
+
+// regex_dfa-0.5.0: r"\d{4}-\d{2}-\d{2}"
+consistent!(regex_dfa_0, r"\d{4}-\d{2}-\d{2}");
+
+// reaper-2.0.0: r"^[0-9\p{L} _\\.]{3,16}$"
+consistent!(reaper_0, r"^[0-9\p{L} _\\.]{3,16}$");
+
+// retdec-0.1.0: r"^attachment; filename=(.+)$"
+consistent!(retdec_0, r"^attachment; filename=(.+)$");
+
+// renvsubst-0.1.2: r"(\\)(?P<head>\$[0-9A-Za-z_{])"
+consistent!(renvsubst_0, r"(\\)(?P<head>\$[0-9A-Za-z_{])");
+
+// renvsubst-0.1.2: r"\$([[:word:]]+)"
+consistent!(renvsubst_1, r"\$([[:word:]]+)");
+
+// renvsubst-0.1.2: r"\$\{([[:word:]]+)\}"
+consistent!(renvsubst_2, r"\$\{([[:word:]]+)\}");
+
+// rexpect-0.3.0: r"'[a-z]+'"
+consistent!(rexpect_0, r"'[a-z]+'");
+
+// rexpect-0.3.0: r"^\d{4}-\d{2}-\d{2}$"
+consistent!(rexpect_1, r"^\d{4}-\d{2}-\d{2}$");
+
+// rexpect-0.3.0: r"-\d{2}-"
+consistent!(rexpect_2, r"-\d{2}-");
+
+// luther-0.1.0: "^a(b|c)c*$"
+consistent!(luther_0, "^a(b|c)c*$");
+
+// little_boxes-1.6.0: r"(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]"
+consistent!(little_boxes_0, r"(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]");
+
+// libimagentrytag-0.8.0: "^[a-zA-Z]([a-zA-Z0-9_-]*)$"
+consistent!(libimagentrytag_0, "^[a-zA-Z]([a-zA-Z0-9_-]*)$");
+
+// libimaginteraction-0.8.0: r"^[Yy](\n?)$"
+consistent!(libimaginteraction_0, r"^[Yy](\n?)$");
+
+// libimaginteraction-0.8.0: r"^[Nn](\n?)$"
+consistent!(libimaginteraction_1, r"^[Nn](\n?)$");
+
+// libimagutil-0.8.0: "^(?P<KEY>([^=]*))=(.*)$"
+consistent!(libimagutil_0, "^(?P<KEY>([^=]*))=(.*)$");
+
+// libimagutil-0.8.0: "(.*)=(\"(?P<QVALUE>([^\"]*))\"|(?P<VALUE>(.*)))$"
+consistent!(libimagutil_1, "(.*)=(\"(?P<QVALUE>([^\"]*))\"|(?P<VALUE>(.*)))$");
+
+// linux_ip-0.1.0: r"\s+"
+consistent!(linux_ip_0, r"\s+");
+
+// linux_ip-0.1.0: r"\s*[\n\r]+\s*"
+consistent!(linux_ip_1, r"\s*[\n\r]+\s*");
+
+// linux_ip-0.1.0: r"^([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$"
+consistent!(linux_ip_2, r"^([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$");
+
+// linux_ip-0.1.0: r"^([0-9a-fA-F\.:/]+|default)\s+via\s+([a-z0-9\.:]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$"
+consistent!(linux_ip_3, r"^([0-9a-fA-F\.:/]+|default)\s+via\s+([a-z0-9\.:]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$");
+
+// linux_ip-0.1.0: r"^(blackhole)\s+([0-9a-fA-F\.:/]+)$"
+consistent!(linux_ip_4, r"^(blackhole)\s+([0-9a-fA-F\.:/]+)$");
+
+// linux_ip-0.1.0: r"^(unreachable)\s+([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s+(.*)$"
+consistent!(
+    linux_ip_5,
+    r"^(unreachable)\s+([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s+(.*)$"
+);
+
+// linux_ip-0.1.0: r"\s*[\n\r]+\s*"
+consistent!(linux_ip_6, r"\s*[\n\r]+\s*");
+
+// linux_ip-0.1.0: r"^\d+:\s+([a-zA-Z0-9\.-]+)(@\S+)*:\s+(.*)$"
+consistent!(linux_ip_7, r"^\d+:\s+([a-zA-Z0-9\.-]+)(@\S+)*:\s+(.*)$");
+
+// linux_ip-0.1.0: r"\s*link/ether\s+([a-f0-9:]+)\s+.*"
+consistent!(linux_ip_8, r"\s*link/ether\s+([a-f0-9:]+)\s+.*");
+
+// linux_ip-0.1.0: r"\s*inet[6]*\s+([0-9a-f:\./]+)\s+.*"
+consistent!(linux_ip_9, r"\s*inet[6]*\s+([0-9a-f:\./]+)\s+.*");
+
+// linky-0.1.4: r"[^\w -]"
+consistent!(linky_0, r"[^\w -]");
+
+// linky-0.1.4: r"^(.*):(\d+): [^ ]* ([^ ]*)$"
+consistent!(linky_1, r"^(.*):(\d+): [^ ]* ([^ ]*)$");
+
+// limonite-0.2.1: r"^(\d{4}-\d{2}-\d{2})-(\d{3})-(.+)$"
+consistent!(limonite_0, r"^(\d{4}-\d{2}-\d{2})-(\d{3})-(.+)$");
+
+// process-queue-0.1.1: r"^[a-zA-Z]+$"
+consistent!(process_queue_0, r"^[a-zA-Z]+$");
+
+// pronghorn-0.1.2: r"^\{([a-zA-Z_]+)\}$"
+consistent!(pronghorn_0, r"^\{([a-zA-Z_]+)\}$");
+
+// protocol-ftp-client-0.1.1: "(?m:^(\\d{3}) (.+)\r$)"
+consistent!(protocol_ftp_client_0, "(?m:^(\\d{3}) (.+)\r$)");
+
+// protocol-ftp-client-0.1.1: "\"(.+)\""
+consistent!(protocol_ftp_client_1, "\"(.+)\"");
+
+// protocol-ftp-client-0.1.1: "(\\w+) [Tt]ype: (\\w+)"
+consistent!(protocol_ftp_client_2, "(\\w+) [Tt]ype: (\\w+)");
+
+// protocol-ftp-client-0.1.1: "(?m:^(\\d{3})-.+\r$)"
+consistent!(protocol_ftp_client_3, "(?m:^(\\d{3})-.+\r$)");
+
+// protocol-ftp-client-0.1.1: "Entering Passive Mode \\((\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+)\\)"
+consistent!(
+    protocol_ftp_client_4,
+    "Entering Passive Mode \\((\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+)\\)"
+);
+
+// protocol-ftp-client-0.1.1: "(?m:^(.+)\r$)"
+consistent!(protocol_ftp_client_5, "(?m:^(.+)\r$)");
+
+// protocol-ftp-client-0.1.1: "^([d-])(?:[rwx-]{3}){3} +\\d+ +\\w+ +\\w+ +(\\d+) +(.+) +(.+)$"
+consistent!(
+    protocol_ftp_client_6,
+    "^([d-])(?:[rwx-]{3}){3} +\\d+ +\\w+ +\\w+ +(\\d+) +(.+) +(.+)$"
+);
+
+// article-date-extractor-0.1.1: r"([\./\-_]{0,1}(19|20)\d{2})[\./\-_]{0,1}(([0-3]{0,1}[0-9][\./\-_])|(\w{3,5}[\./\-_]))([0-3]{0,1}[0-9][\./\-]{0,1})"
+consistent!(article_date_extractor_0, r"([\./\-_]{0,1}(19|20)\d{2})[\./\-_]{0,1}(([0-3]{0,1}[0-9][\./\-_])|(\w{3,5}[\./\-_]))([0-3]{0,1}[0-9][\./\-]{0,1})");
+
+// article-date-extractor-0.1.1: r"(?i)publishdate|pubdate|timestamp|article_date|articledate|date"
+consistent!(
+    article_date_extractor_1,
+    r"(?i)publishdate|pubdate|timestamp|article_date|articledate|date"
+);
+
+// arthas_plugin-0.1.1: r"type\((.*)\)"
+consistent!(arthas_plugin_0, r"type\((.*)\)");
+
+// arthas_plugin-0.1.1: r"Vec<(.*)>"
+consistent!(arthas_plugin_1, r"Vec<(.*)>");
+
+// arthas_plugin-0.1.1: r"Option<(.*)>"
+consistent!(arthas_plugin_2, r"Option<(.*)>");
+
+// arthas_plugin-0.1.1: r"HashMap<[a-z0-9A-Z]+, *(.*)>"
+consistent!(arthas_plugin_3, r"HashMap<[a-z0-9A-Z]+, *(.*)>");
+
+// arthas_derive-0.1.0: "Vec *< *(.*) *>"
+consistent!(arthas_derive_0, "Vec *< *(.*) *>");
+
+// arthas_derive-0.1.0: r"Option *< *(.*) *>"
+consistent!(arthas_derive_1, r"Option *< *(.*) *>");
+
+// arthas_derive-0.1.0: r"HashMap *< *[a-z0-9A-Z]+ *, *(.*) *>"
+consistent!(arthas_derive_2, r"HashMap *< *[a-z0-9A-Z]+ *, *(.*) *>");
+
+// arpabet-0.2.0: r"^([\w\-\(\)\.']+)\s+([^\s].*)\s*$"
+consistent!(arpabet_0, r"^([\w\-\(\)\.']+)\s+([^\s].*)\s*$");
+
+// arpabet-0.2.0: r"^;;;\s+"
+consistent!(arpabet_1, r"^;;;\s+");
+
+// glossy_codegen-0.2.0: r"/\*.*?\*/|//.*"
+consistent!(glossy_codegen_0, r"/\*.*?\*/|//.*");
+
+// glossy_codegen-0.2.0: "^\\s*#\\s*include\\s+<([:print:]+)>\\s*$"
+consistent!(glossy_codegen_1, "^\\s*#\\s*include\\s+<([:print:]+)>\\s*$");
+
+// glossy_codegen-0.2.0: "^\\s*#\\s*include\\s+\"([:print:]+)\"\\s*$"
+consistent!(glossy_codegen_2, "^\\s*#\\s*include\\s+\"([:print:]+)\"\\s*$");
+
+// glossy_codegen-0.2.0: r"^\s*#\s*version\s+(\d+)"
+consistent!(glossy_codegen_3, r"^\s*#\s*version\s+(\d+)");
+
+// glossy_codegen-0.2.0: r"^\s*$"
+consistent!(glossy_codegen_4, r"^\s*$");
+
+// gluster-1.0.1: r"(?P<addr>via \S+)"
+consistent!(gluster_0, r"(?P<addr>via \S+)");
+
+// gluster-1.0.1: r"(?P<src>src \S+)"
+consistent!(gluster_1, r"(?P<src>src \S+)");
+
+// gl_helpers-0.1.7: r"(.*)\[\d+\]"
+consistent!(gl_helpers_0, r"(.*)\[\d+\]");
+
+// gl_helpers-0.1.7: r"(\d+).(\d+)"
+consistent!(gl_helpers_1, r"(\d+).(\d+)");
+
+// glr-parser-0.0.1: r"(?P<c>[\\\.\+\*\?\(\)\|\[\]\{\}\^\$])"
+consistent!(glr_parser_0, r"(?P<c>[\\\.\+\*\?\(\)\|\[\]\{\}\^\$])");
+
+// glr-parser-0.0.1: r"^\w+$"
+consistent!(glr_parser_1, r"^\w+$");
+
+// glr-parser-0.0.1: "'[^']+'"
+consistent!(glr_parser_2, "'[^']+'");
+
+// hoodlum-0.5.0: r"(?m)//.*"
+consistent!(hoodlum_0, r"(?m)//.*");
+
+// form-checker-0.2.2: r"^1\d{10}$"
+consistent!(form_checker_0, r"^1\d{10}$");
+
+// form-checker-0.2.2: r"(?i)^[\w.%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$"
+consistent!(form_checker_1, r"(?i)^[\w.%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$");
+
+// wikibase-0.2.0: r"(?P<user_agent>[a-zA-Z0-9-_]+/[0-9\.]+)"
+consistent!(wikibase_0, r"(?P<user_agent>[a-zA-Z0-9-_]+/[0-9\.]+)");
+
+// wifiscanner-0.3.6: r"Cell [0-9]{2,} - Address:"
+consistent!(wifiscanner_0, r"Cell [0-9]{2,} - Address:");
+
+// wifiscanner-0.3.6: r"([0-9a-zA-Z]{1}[0-9a-zA-Z]{1}[:]{1}){5}[0-9a-zA-Z]{1}[0-9a-zA-Z]{1}"
+consistent!(
+    wifiscanner_1,
+    r"([0-9a-zA-Z]{1}[0-9a-zA-Z]{1}[:]{1}){5}[0-9a-zA-Z]{1}[0-9a-zA-Z]{1}"
+);
+
+// wifiscanner-0.3.6: r"Signal level=(\d+)/100"
+consistent!(wifiscanner_2, r"Signal level=(\d+)/100");
+
+// bbcode-1.0.2: r"(?s)\[b\](.*?)\[/b\]"
+consistent!(bbcode_0, r"(?s)\[b\](.*?)\[/b\]");
+
+// bbcode-1.0.2: r"(?s)\[i\](.*?)\[/i\]"
+consistent!(bbcode_1, r"(?s)\[i\](.*?)\[/i\]");
+
+// bbcode-1.0.2: r"(?s)\[u\](.*?)\[/u\]"
+consistent!(bbcode_2, r"(?s)\[u\](.*?)\[/u\]");
+
+// bbcode-1.0.2: r"(?s)\[s\](.*?)\[/s\]"
+consistent!(bbcode_3, r"(?s)\[s\](.*?)\[/s\]");
+
+// bbcode-1.0.2: r"(?s)\[size=(\d+)](.*?)\[/size\]"
+consistent!(bbcode_4, r"(?s)\[size=(\d+)](.*?)\[/size\]");
+
+// bbcode-1.0.2: r"(?s)\[color=(.+)](.*?)\[/color\]"
+consistent!(bbcode_5, r"(?s)\[color=(.+)](.*?)\[/color\]");
+
+// bbcode-1.0.2: r"(?s)\[center\](.*?)\[/center\]"
+consistent!(bbcode_6, r"(?s)\[center\](.*?)\[/center\]");
+
+// bbcode-1.0.2: r"(?s)\[left\](.*?)\[/left\]"
+consistent!(bbcode_7, r"(?s)\[left\](.*?)\[/left\]");
+
+// bbcode-1.0.2: r"(?s)\[right\](.*?)\[/right\]"
+consistent!(bbcode_8, r"(?s)\[right\](.*?)\[/right\]");
+
+// bbcode-1.0.2: r"(?s)\[table\](.*?)\[/table\]"
+consistent!(bbcode_9, r"(?s)\[table\](.*?)\[/table\]");
+
+// bbcode-1.0.2: r"(?s)\[td\](.*?)\[/td\]"
+consistent!(bbcode_10, r"(?s)\[td\](.*?)\[/td\]");
+
+// bbcode-1.0.2: r"(?s)\[tr\](.*?)\[/tr\]"
+consistent!(bbcode_11, r"(?s)\[tr\](.*?)\[/tr\]");
+
+// bbcode-1.0.2: r"(?s)\[th\](.*?)\[/th\]"
+consistent!(bbcode_12, r"(?s)\[th\](.*?)\[/th\]");
+
+// bbcode-1.0.2: r"(?s)\[url\](.*?)\[/url\]"
+consistent!(bbcode_13, r"(?s)\[url\](.*?)\[/url\]");
+
+// bbcode-1.0.2: r"(?s)\[url=(.+)\](.*?)\[/url\]"
+consistent!(bbcode_14, r"(?s)\[url=(.+)\](.*?)\[/url\]");
+
+// bbcode-1.0.2: r"(?s)\[quote\](.*?)\[/quote\]"
+consistent!(bbcode_15, r"(?s)\[quote\](.*?)\[/quote\]");
+
+// bbcode-1.0.2: r"(?s)\[quote=(.+)\](.*?)\[/quote\]"
+consistent!(bbcode_16, r"(?s)\[quote=(.+)\](.*?)\[/quote\]");
+
+// bbcode-1.0.2: r"(?s)\[img=(\d+)x(\d+)(\b.*)?\](.*?)\[/img\]"
+consistent!(bbcode_17, r"(?s)\[img=(\d+)x(\d+)(\b.*)?\](.*?)\[/img\]");
+
+// bbcode-1.0.2: r"(?s)\[img=(.+)(\b.*)?\](.*?)\[/img\]"
+consistent!(bbcode_18, r"(?s)\[img=(.+)(\b.*)?\](.*?)\[/img\]");
+
+// bbcode-1.0.2: r"(?s)\[img(\b.*)?\](.*?)\[/img\]"
+consistent!(bbcode_19, r"(?s)\[img(\b.*)?\](.*?)\[/img\]");
+
+// bbcode-1.0.2: r"(?s)\[ol\](.*?)\[/ol\]"
+consistent!(bbcode_20, r"(?s)\[ol\](.*?)\[/ol\]");
+
+// bbcode-1.0.2: r"(?s)\[ul\](.*?)\[/ul\]"
+consistent!(bbcode_21, r"(?s)\[ul\](.*?)\[/ul\]");
+
+// bbcode-1.0.2: r"(?s)\[list\](.*?)\[/list\]"
+consistent!(bbcode_22, r"(?s)\[list\](.*?)\[/list\]");
+
+// bbcode-1.0.2: r"(?s)\[youtube\](.*?)\[/youtube\]"
+consistent!(bbcode_23, r"(?s)\[youtube\](.*?)\[/youtube\]");
+
+// bbcode-1.0.2: r"(?s)\[youtube=(\d+)x(\d+)\](.*?)\[/youtube\]"
+consistent!(bbcode_24, r"(?s)\[youtube=(\d+)x(\d+)\](.*?)\[/youtube\]");
+
+// bbcode-1.0.2: r"(?s)\[li\](.*?)\[/li\]"
+consistent!(bbcode_25, r"(?s)\[li\](.*?)\[/li\]");
+
+// block-utils-0.5.0: r"loop\d+"
+consistent!(block_utils_0, r"loop\d+");
+
+// block-utils-0.5.0: r"ram\d+"
+consistent!(block_utils_1, r"ram\d+");
+
+// block-utils-0.5.0: r"md\d+"
+consistent!(block_utils_2, r"md\d+");
+
+// kvvliveapi-0.1.0: r"^([1-9]) min$"
+consistent!(kvvliveapi_0, r"^([1-9]) min$");
+
+// rfc822_sanitizer-0.3.3: r"(\d{2}):(\d{2}):(\d{2})"
+consistent!(rfc822_sanitizer_0, r"(\d{2}):(\d{2}):(\d{2})");
+
+// rfc822_sanitizer-0.3.3: r"(\d{1,2}):(\d{1,2}):(\d{1,2})"
+consistent!(rfc822_sanitizer_1, r"(\d{1,2}):(\d{1,2}):(\d{1,2})");
+
+// faker-0.0.4: r"[2-9]"
+consistent!(faker_0, r"[2-9]");
+
+// faker-0.0.4: r"[1-9]"
+consistent!(faker_1, r"[1-9]");
+
+// faker-0.0.4: r"[0-9]"
+consistent!(faker_2, r"[0-9]");
+
+// faker-0.0.4: r"\d{10}"
+consistent!(faker_3, r"\d{10}");
+
+// faker-0.0.4: r"\d{1}"
+consistent!(faker_4, r"\d{1}");
+
+// faker-0.0.4: r"^\w+"
+consistent!(faker_5, r"^\w+");
+
+// faker-0.0.4: r"^\w+"
+consistent!(faker_6, r"^\w+");
+
+// faker-0.0.4: r"^(\w+\.? ?){2,3}$"
+consistent!(faker_7, r"^(\w+\.? ?){2,3}$");
+
+// faker-0.0.4: r"^[A-Z][a-z]+\.?$"
+consistent!(faker_8, r"^[A-Z][a-z]+\.?$");
+
+// faker-0.0.4: r"^[A-Z][A-Za-z]*\.?$"
+consistent!(faker_9, r"^[A-Z][A-Za-z]*\.?$");
+
+// faker-0.0.4: r"http://lorempixel.com/100/100/\w+"
+consistent!(faker_10, r"http://lorempixel.com/100/100/\w+");
+
+// faker-0.0.4: r"http://lorempixel.com/100/100/cats"
+consistent!(faker_11, r"http://lorempixel.com/100/100/cats");
+
+// fancy-regex-0.1.0: "(?i:ß)"
+consistent!(fancy_regex_0, "(?i:ß)");
+
+// fancy-regex-0.1.0: "(?i:\\x{0587})"
+consistent!(fancy_regex_1, "(?i:\\x{0587})");
+
+// fancy-regex-0.1.0: "^\\\\([!-/:-@\\[-`\\{-~aftnrv]|[0-7]{1,3}|x[0-9a-fA-F]{2}|x\\{[0-9a-fA-F]{1,6}\\})"
+consistent!(fancy_regex_2, "^\\\\([!-/:-@\\[-`\\{-~aftnrv]|[0-7]{1,3}|x[0-9a-fA-F]{2}|x\\{[0-9a-fA-F]{1,6}\\})");
+
+// fancy-prompt-0.1.5: r"/([^/])[^/]+/"
+consistent!(fancy_prompt_0, r"/([^/])[^/]+/");
+
+// fancy-prompt-0.1.5: r"^([^:]+):.*?(?::([^:]+))?$"
+consistent!(fancy_prompt_1, r"^([^:]+):.*?(?::([^:]+))?$");
+
+// fanta-0.2.0: r"^(/?__\w+__)/(.*)"
+consistent!(fanta_0, r"^(/?__\w+__)/(.*)");
+
+// fanta-cli-0.1.1: r"(.)([A-Z])"
+consistent!(fanta_cli_0, r"(.)([A-Z])");
+
+// fanta-cli-0.1.1: "\\{:[^\\s]+\\}"
+consistent!(fanta_cli_1, "\\{:[^\\s]+\\}");
+
+// amethyst_tools-0.7.1: "(?P<last>[^\r])\n"
+consistent!(amethyst_tools_0, "(?P<last>[^\r])\n");
+
+// amigo-0.3.1: r"^-?\d+(\.\d)?"
+consistent!(amigo_0, r"^-?\d+(\.\d)?");
+
+// amigo-0.3.1: r"^[a-zA-Z_]+[\w-]*[!?_]?"
+consistent!(amigo_1, r"^[a-zA-Z_]+[\w-]*[!?_]?");
+
+// amigo-0.3.1: r"^\("
+consistent!(amigo_2, r"^\(");
+
+// amigo-0.3.1: r"^\)"
+consistent!(amigo_3, r"^\)");
+
+// amigo-0.3.1: r"^\s+"
+consistent!(amigo_4, r"^\s+");
+
+// ethcore-logger-1.12.0: "\x1b\\[[^m]+m"
+consistent!(ethcore_logger_0, "\x1b\\[[^m]+m");
+
+// dash2html-1.0.1: r"__.*?__"
+consistent!(dash2html_0, r"__.*?__");
+
+// dash2html-1.0.1: r"(?i)@(?:time|clipboard|cursor|date)"
+consistent!(dash2html_1, r"(?i)@(?:time|clipboard|cursor|date)");
+
+// os_type-2.0.0: r"^Microsoft Windows \[Version\s(\d+\.\d+\.\d+)\]$"
+consistent!(os_type_0, r"^Microsoft Windows \[Version\s(\d+\.\d+\.\d+)\]$");
+
+// os_type-2.0.0: r"ProductName:\s([\w\s]+)\n"
+consistent!(os_type_1, r"ProductName:\s([\w\s]+)\n");
+
+// os_type-2.0.0: r"ProductVersion:\s(\w+\.\w+\.\w+)"
+consistent!(os_type_2, r"ProductVersion:\s(\w+\.\w+\.\w+)");
+
+// os_type-2.0.0: r"BuildVersion:\s(\w+)"
+consistent!(os_type_3, r"BuildVersion:\s(\w+)");
+
+// os_type-2.0.0: r"(\w+) Linux release"
+consistent!(os_type_4, r"(\w+) Linux release");
+
+// os_type-2.0.0: r"release\s([\w\.]+)"
+consistent!(os_type_5, r"release\s([\w\.]+)");
+
+// os_type-2.0.0: r"Distributor ID:\s(\w+)"
+consistent!(os_type_6, r"Distributor ID:\s(\w+)");
+
+// os_type-2.0.0: r"Release:\s([\w\.]+)"
+consistent!(os_type_7, r"Release:\s([\w\.]+)");
+
+// bindgen-0.37.0: r"typename type\-parameter\-\d+\-\d+::.+"
+consistent!(bindgen_0, r"typename type\-parameter\-\d+\-\d+::.+");
+
+// imap-0.8.1: "^+(.*)\r\n"
+consistent!(imap_0, "^+(.*)\r\n");
+
+// image-base64-0.1.0: r"^ffd8ffe0"
+consistent!(image_base64_0, r"^ffd8ffe0");
+
+// image-base64-0.1.0: r"^89504e47"
+consistent!(image_base64_1, r"^89504e47");
+
+// image-base64-0.1.0: r"^47494638"
+consistent!(image_base64_2, r"^47494638");
+
+// json-pointer-0.3.2: "^(/([^/~]|~[01])*)*$"
+consistent!(json_pointer_0, "^(/([^/~]|~[01])*)*$");
+
+// json-pointer-0.3.2: "^#(/([^/~%]|~[01]|%[0-9a-fA-F]{2})*)*$"
+consistent!(json_pointer_1, "^#(/([^/~%]|~[01]|%[0-9a-fA-F]{2})*)*$");
+
+// mysql_common-0.7.0: r"^5.5.5-(\d{1,2})\.(\d{1,2})\.(\d{1,3})-MariaDB"
+consistent!(mysql_common_0, r"^5.5.5-(\d{1,2})\.(\d{1,2})\.(\d{1,3})-MariaDB");
+
+// mysql_common-0.7.0: r"^(\d{1,2})\.(\d{1,2})\.(\d{1,3})(.*)"
+consistent!(mysql_common_1, r"^(\d{1,2})\.(\d{1,2})\.(\d{1,3})(.*)");
+
+// government_id-0.1.0: r"^[0-9]{4}[0-9A-Z]{2}[0-9]{3}$"
+consistent!(government_id_0, r"^[0-9]{4}[0-9A-Z]{2}[0-9]{3}$");
+
+// ohmers-0.1.1: r"UniqueIndexViolation: (\w+)"
+consistent!(ohmers_0, r"UniqueIndexViolation: (\w+)");
+
+// eliza-1.0.0: r"(.*) you are (.*)"
+consistent!(eliza_0, r"(.*) you are (.*)");
+
+// eliza-1.0.0: r"(.*) you are (.*)"
+consistent!(eliza_1, r"(.*) you are (.*)");
+
+// eliza-1.0.0: r"(.*) you are (.*)"
+consistent!(eliza_2, r"(.*) you are (.*)");
+
+// chema-0.0.5: "^\\s*\\*"
+consistent!(chema_0, "^\\s*\\*");
+
+// chema-0.0.5: "^\\s*@(\\w+)\\s+(.*)"
+consistent!(chema_1, "^\\s*@(\\w+)\\s+(.*)");
+
+// chord3-0.3.0: r"^\s*#"
+consistent!(chord3_0, r"^\s*#");
+
+// chord3-0.3.0: r"\{(?P<cmd>\w+)(?::?\s*(?P<arg>.*))?\}"
+consistent!(chord3_1, r"\{(?P<cmd>\w+)(?::?\s*(?P<arg>.*))?\}");
+
+// chord3-0.3.0: r"\{(eot|end_of_tab):?\s*"
+consistent!(chord3_2, r"\{(eot|end_of_tab):?\s*");
+
+// chord3-0.3.0: r"([^\[]*)(?:\[([^\]]*)\])?"
+consistent!(chord3_3, r"([^\[]*)(?:\[([^\]]*)\])?");
+
+// checkmail-0.1.1: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
+consistent!(checkmail_0, "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$");
+
+// cntk-0.2.1: r"\b\w\w+\b"
+consistent!(cntk_0, r"\b\w\w+\b");
+
+// cntk-0.2.1: r"\b\w\w+\b"
+consistent!(cntk_1, r"\b\w\w+\b");
+
+// cniguru-0.1.0: r"\(id: (\d+)\)"
+consistent!(cniguru_0, r"\(id: (\d+)\)");
+
+// upm_lib-0.3.0: r"^(\d+)\.(\d+)\.(\d+)(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?$"
+consistent!(upm_lib_0, r"^(\d+)\.(\d+)\.(\d+)(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?$");
+
+// avro-0.2.1: r"^\s*(\*+(\s+))?"
+consistent!(avro_0, r"^\s*(\*+(\s+))?");
+
+// avro-0.2.1: r"^\s*(\*+)?"
+consistent!(avro_1, r"^\s*(\*+)?");
+
+// nomi-0.0.2: "[0-9]+"
+consistent!(nomi_0, "[0-9]+");
+
+// nodes-0.1.0: "([0-9]+)@(?:nodes|n)?:([^@]+)?"
+consistent!(nodes_0, "([0-9]+)@(?:nodes|n)?:([^@]+)?");
+
+// not-stakkr-1.0.0: r"(?i)in (\d+) (second|minute|hour|day|week)s?"
+consistent!(not_stakkr_0, r"(?i)in (\d+) (second|minute|hour|day|week)s?");
+
+// notetxt-0.0.1: "^([A-Za-z0-9 -_:]+)\n-+\n"
+consistent!(notetxt_0, "^([A-Za-z0-9 -_:]+)\n-+\n");
+
+// nail-0.1.0-pre.0: r"^-?[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?$"
+consistent!(nail_0, r"^-?[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?$");
+
+// nail-0.1.0-pre.0: r"^-?[0-9]+$"
+consistent!(nail_1, r"^-?[0-9]+$");
+
+// askalono-0.2.0: r"[^\w\s\pP]+"
+consistent!(askalono_0, r"[^\w\s\pP]+");
+
+// askalono-0.2.0: r"(?x)[ \t\p{Zs} \\ / \| \x2044 ]+"
+consistent!(askalono_1, r"(?x)[ \t\p{Zs} \\ / \| \x2044 ]+");
+
+// askalono-0.2.0: r"\p{Pd}+"
+consistent!(askalono_2, r"\p{Pd}+");
+
+// askalono-0.2.0: r"\p{Ps}+"
+consistent!(askalono_3, r"\p{Ps}+");
+
+// askalono-0.2.0: r"\p{Pe}+"
+consistent!(askalono_4, r"\p{Pe}+");
+
+// askalono-0.2.0: r"\p{Pc}+"
+consistent!(askalono_5, r"\p{Pc}+");
+
+// askalono-0.2.0: r"[©Ⓒⓒ]"
+consistent!(askalono_6, r"[©Ⓒⓒ]");
+
+// askalono-0.2.0: r"[\r\n\v\f]"
+consistent!(askalono_7, r"[\r\n\v\f]");
+
+// askalono-0.2.0: r"\n{3,}"
+consistent!(askalono_8, r"\n{3,}");
+
+// askalono-0.2.0: r"[^\w\s]+"
+consistent!(askalono_9, r"[^\w\s]+");
+
+// askalono-0.2.0: r"\s+"
+consistent!(askalono_10, r"\s+");
+
+// assembunny_plus-0.0.3: r"[^0-9a-zA-Z_]"
+consistent!(assembunny_plus_0, r"[^0-9a-zA-Z_]");
+
+// assembunny_plus-0.0.3: r"[0-9]"
+consistent!(assembunny_plus_1, r"[0-9]");
+
+// salt-compressor-0.4.0: r"(?m)^Minion (\S*) did not respond\. No job will be sent\.$"
+consistent!(
+    salt_compressor_0,
+    r"(?m)^Minion (\S*) did not respond\. No job will be sent\.$"
+);
+
+// sabisabi-0.4.1: r"</?[^>]+?>"
+consistent!(sabisabi_0, r"</?[^>]+?>");
+
+// sabisabi-0.4.1: r"\([^)]*\)"
+consistent!(sabisabi_1, r"\([^)]*\)");
+
+// sassers-0.13.5-h28: "@import \"([^\"]*)\";"
+consistent!(sassers_0, "@import \"([^\"]*)\";");
+
+// shadowsocks-0.6.2: r"[A-Za-z\d-]{1,63}$"
+consistent!(shadowsocks_0, r"[A-Za-z\d-]{1,63}$");
+
+// shkeleton-0.1.5: "[abc]+"
+consistent!(shkeleton_0, "[abc]+");
+
+// shellwords-0.1.0: r"([^A-Za-z0-9_\-.,:/@\n])"
+consistent!(shellwords_0, r"([^A-Za-z0-9_\-.,:/@\n])");
+
+// shellwords-0.1.0: r"\n"
+consistent!(shellwords_1, r"\n");
+
+// shush-0.1.5: "(?P<num>[0-9]+)(?P<units>[dhms])"
+consistent!(shush_0, "(?P<num>[0-9]+)(?P<units>[dhms])");
+
+// woothee-0.8.0: r"(?:Chrome|CrMo|CriOS)/([.0-9]+)"
+consistent!(woothee_0, r"(?:Chrome|CrMo|CriOS)/([.0-9]+)");
+
+// woothee-0.8.0: r"Vivaldi/([.0-9]+)"
+consistent!(woothee_1, r"Vivaldi/([.0-9]+)");
+
+// woothee-0.8.0: r"Firefox/([.0-9]+)"
+consistent!(woothee_2, r"Firefox/([.0-9]+)");
+
+// woothee-0.8.0: r"^Mozilla/[.0-9]+ \((?:Mobile|Tablet);(?:.*;)? rv:([.0-9]+)\) Gecko/[.0-9]+ Firefox/[.0-9]+$"
+consistent!(woothee_3, r"^Mozilla/[.0-9]+ \((?:Mobile|Tablet);(?:.*;)? rv:([.0-9]+)\) Gecko/[.0-9]+ Firefox/[.0-9]+$");
+
+// woothee-0.8.0: r"FxiOS/([.0-9]+)"
+consistent!(woothee_4, r"FxiOS/([.0-9]+)");
+
+// woothee-0.8.0: r"\(([^;)]+);FOMA;"
+consistent!(woothee_5, r"\(([^;)]+);FOMA;");
+
+// woothee-0.8.0: r"jig browser[^;]+; ([^);]+)"
+consistent!(woothee_6, r"jig browser[^;]+; ([^);]+)");
+
+// woothee-0.8.0: r"(?i)rss(?:reader|bar|[-_ /;()]|[ +]*/)"
+consistent!(woothee_7, r"(?i)rss(?:reader|bar|[-_ /;()]|[ +]*/)");
+
+// woothee-0.8.0: r"(?i)(?:bot|crawler|spider)(?:[-_ ./;@()]|$)"
+consistent!(woothee_8, r"(?i)(?:bot|crawler|spider)(?:[-_ ./;@()]|$)");
+
+// woothee-0.8.0: r"(?i)(?:feed|web) ?parser"
+consistent!(woothee_9, r"(?i)(?:feed|web) ?parser");
+
+// woothee-0.8.0: r"(?i)watch ?dog"
+consistent!(woothee_10, r"(?i)watch ?dog");
+
+// woothee-0.8.0: r"Edge/([.0-9]+)"
+consistent!(woothee_11, r"Edge/([.0-9]+)");
+
+// woothee-0.8.0: r"MSIE ([.0-9]+);"
+consistent!(woothee_12, r"MSIE ([.0-9]+);");
+
+// woothee-0.8.0: r"Version/([.0-9]+)"
+consistent!(woothee_13, r"Version/([.0-9]+)");
+
+// woothee-0.8.0: r"Opera[/ ]([.0-9]+)"
+consistent!(woothee_14, r"Opera[/ ]([.0-9]+)");
+
+// woothee-0.8.0: r"OPR/([.0-9]+)"
+consistent!(woothee_15, r"OPR/([.0-9]+)");
+
+// woothee-0.8.0: r"Version/([.0-9]+)"
+consistent!(woothee_16, r"Version/([.0-9]+)");
+
+// woothee-0.8.0: r"(?:SoftBank|Vodafone|J-PHONE)/[.0-9]+/([^ /;()]+)"
+consistent!(woothee_17, r"(?:SoftBank|Vodafone|J-PHONE)/[.0-9]+/([^ /;()]+)");
+
+// woothee-0.8.0: r"Trident/([.0-9]+);"
+consistent!(woothee_18, r"Trident/([.0-9]+);");
+
+// woothee-0.8.0: r" rv:([.0-9]+)"
+consistent!(woothee_19, r" rv:([.0-9]+)");
+
+// woothee-0.8.0: r"IEMobile/([.0-9]+);"
+consistent!(woothee_20, r"IEMobile/([.0-9]+);");
+
+// woothee-0.8.0: r"(?:WILLCOM|DDIPOCKET);[^/]+/([^ /;()]+)"
+consistent!(woothee_21, r"(?:WILLCOM|DDIPOCKET);[^/]+/([^ /;()]+)");
+
+// woothee-0.8.0: r"Windows ([ .a-zA-Z0-9]+)[;\\)]"
+consistent!(woothee_22, r"Windows ([ .a-zA-Z0-9]+)[;\\)]");
+
+// woothee-0.8.0: r"^Phone(?: OS)? ([.0-9]+)"
+consistent!(woothee_23, r"^Phone(?: OS)? ([.0-9]+)");
+
+// woothee-0.8.0: r"iP(hone;|ad;|od) .*like Mac OS X"
+consistent!(woothee_24, r"iP(hone;|ad;|od) .*like Mac OS X");
+
+// woothee-0.8.0: r"Version/([.0-9]+)"
+consistent!(woothee_25, r"Version/([.0-9]+)");
+
+// woothee-0.8.0: r"rv:(\d+\.\d+\.\d+)"
+consistent!(woothee_26, r"rv:(\d+\.\d+\.\d+)");
+
+// woothee-0.8.0: r"FreeBSD ([^;\)]+);"
+consistent!(woothee_27, r"FreeBSD ([^;\)]+);");
+
+// woothee-0.8.0: r"CrOS ([^\)]+)\)"
+consistent!(woothee_28, r"CrOS ([^\)]+)\)");
+
+// woothee-0.8.0: r"Android[- ](\d+\.\d+(?:\.\d+)?)"
+consistent!(woothee_29, r"Android[- ](\d+\.\d+(?:\.\d+)?)");
+
+// woothee-0.8.0: r"PSP \(PlayStation Portable\); ([.0-9]+)\)"
+consistent!(woothee_30, r"PSP \(PlayStation Portable\); ([.0-9]+)\)");
+
+// woothee-0.8.0: r"PLAYSTATION 3;? ([.0-9]+)\)"
+consistent!(woothee_31, r"PLAYSTATION 3;? ([.0-9]+)\)");
+
+// woothee-0.8.0: r"PlayStation Vita ([.0-9]+)\)"
+consistent!(woothee_32, r"PlayStation Vita ([.0-9]+)\)");
+
+// woothee-0.8.0: r"PlayStation 4 ([.0-9]+)\)"
+consistent!(woothee_33, r"PlayStation 4 ([.0-9]+)\)");
+
+// woothee-0.8.0: r"BB10(?:.+)Version/([.0-9]+) "
+consistent!(woothee_34, r"BB10(?:.+)Version/([.0-9]+) ");
+
+// woothee-0.8.0: r"BlackBerry(?:\d+)/([.0-9]+) "
+consistent!(woothee_35, r"BlackBerry(?:\d+)/([.0-9]+) ");
+
+// woothee-0.8.0: r"; CPU(?: iPhone)? OS (\d+_\d+(?:_\d+)?) like Mac OS X"
+consistent!(
+    woothee_36,
+    r"; CPU(?: iPhone)? OS (\d+_\d+(?:_\d+)?) like Mac OS X"
+);
+
+// woothee-0.8.0: r"Mac OS X (10[._]\d+(?:[._]\d+)?)(?:\)|;)"
+consistent!(woothee_37, r"Mac OS X (10[._]\d+(?:[._]\d+)?)(?:\)|;)");
+
+// woothee-0.8.0: r"^(?:Apache-HttpClient/|Jakarta Commons-HttpClient/|Java/)"
+consistent!(
+    woothee_38,
+    r"^(?:Apache-HttpClient/|Jakarta Commons-HttpClient/|Java/)"
+);
+
+// woothee-0.8.0: r"[- ]HttpClient(/|$)"
+consistent!(woothee_39, r"[- ]HttpClient(/|$)");
+
+// woothee-0.8.0: r"^(?:PHP|WordPress|CakePHP|PukiWiki|PECL::HTTP)(?:/| |$)"
+consistent!(
+    woothee_40,
+    r"^(?:PHP|WordPress|CakePHP|PukiWiki|PECL::HTTP)(?:/| |$)"
+);
+
+// woothee-0.8.0: r"(?:PEAR HTTP_Request|HTTP_Request)(?: class|2)"
+consistent!(woothee_41, r"(?:PEAR HTTP_Request|HTTP_Request)(?: class|2)");
+
+// woothee-0.8.0: r"(?:Rome Client |UnwindFetchor/|ia_archiver |Summify |PostRank/)"
+consistent!(
+    woothee_42,
+    r"(?:Rome Client |UnwindFetchor/|ia_archiver |Summify |PostRank/)"
+);
+
+// woothee-0.8.0: r"Sleipnir/([.0-9]+)"
+consistent!(woothee_43, r"Sleipnir/([.0-9]+)");
+
+// word_replace-0.0.3: r"@@[a-z|A-Z|\d]+@@"
+consistent!(word_replace_0, r"@@[a-z|A-Z|\d]+@@");
+
+// wordcount-0.1.0: r"\w+"
+consistent!(wordcount_0, r"\w+");
+
+// just-0.3.12: "^([^=]+)=(.*)$"
+consistent!(just_0, "^([^=]+)=(.*)$");
+
+// emote-0.1.0: r":[a-zA-Z_]+?:"
+consistent!(emote_0, r":[a-zA-Z_]+?:");
+
+// emojicons-1.0.1: r":([a-zA-Z0-9_+-]+):"
+consistent!(emojicons_0, r":([a-zA-Z0-9_+-]+):");
+
+// git2_codecommit-0.1.2: r"git-codecommit\.([a-z0-9-]+)\.amazonaws\.com"
+consistent!(
+    git2_codecommit_0,
+    r"git-codecommit\.([a-z0-9-]+)\.amazonaws\.com"
+);
+
+// git-workarea-3.1.2: r"^submodule\.(?P<name>.*)\.(?P<key>[^=]*)=(?P<value>.*)$"
+consistent!(
+    git_workarea_0,
+    r"^submodule\.(?P<name>.*)\.(?P<key>[^=]*)=(?P<value>.*)$"
+);
+
+// git-shell-enforce-directory-1.0.0: r"^(?P<command>git-(?:receive|upload)-pack) '(?P<path>.+)'$"
+consistent!(
+    git_shell_enforce_directory_0,
+    r"^(?P<command>git-(?:receive|upload)-pack) '(?P<path>.+)'$"
+);
+
+// git-journal-1.6.3: r"[ \n]:(.*?):"
+consistent!(git_journal_0, r"[ \n]:(.*?):");
+
+// git-find-0.3.2: r"^git@(?P<host>[[:alnum:]\._-]+):(?P<path>[[:alnum:]\._\-/]+).git$"
+consistent!(
+    git_find_0,
+    r"^git@(?P<host>[[:alnum:]\._-]+):(?P<path>[[:alnum:]\._\-/]+).git$"
+);
+
+// gitlab-api-0.6.0: r"private_token=\w{20}"
+consistent!(gitlab_api_0, r"private_token=\w{20}");
+
+// td-client-0.7.0: "^(http://|https://)"
+consistent!(td_client_0, "^(http://|https://)");
+
+// karaconv-0.3.0: r"--(?P<type>[a-zA-Z]+)-- (?P<contents>.*)"
+consistent!(karaconv_0, r"--(?P<type>[a-zA-Z]+)-- (?P<contents>.*)");
+
+// katana-1.0.2: r"(?P<comp>et al\.)(?:\.)"
+consistent!(katana_0, r"(?P<comp>et al\.)(?:\.)");
+
+// katana-1.0.2: r"\.{3}"
+consistent!(katana_1, r"\.{3}");
+
+// katana-1.0.2: r"(?P<number>[0-9]+)\.(?P<decimal>[0-9]+)"
+consistent!(katana_2, r"(?P<number>[0-9]+)\.(?P<decimal>[0-9]+)");
+
+// katana-1.0.2: r"\s\.(?P<nums>[0-9]+)"
+consistent!(katana_3, r"\s\.(?P<nums>[0-9]+)");
+
+// katana-1.0.2: r"(?:[A-Za-z]\.){2,}"
+consistent!(katana_4, r"(?:[A-Za-z]\.){2,}");
+
+// katana-1.0.2: r"(?P<init>[A-Z])(?P<point>\.)"
+consistent!(katana_5, r"(?P<init>[A-Z])(?P<point>\.)");
+
+// katana-1.0.2: r"(?P<title>[A-Z][a-z]{1,3})(\.)"
+consistent!(katana_6, r"(?P<title>[A-Z][a-z]{1,3})(\.)");
+
+// katana-1.0.2: r"&==&(?P<p>[.!?])"
+consistent!(katana_7, r"&==&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&\^&(?P<p>[.!?])"
+consistent!(katana_8, r"&\^&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&\*\*&(?P<p>[.!?])"
+consistent!(katana_9, r"&\*\*&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&=&(?P<p>[.!?])"
+consistent!(katana_10, r"&=&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&##&(?P<p>[.!?])"
+consistent!(katana_11, r"&##&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&\$&(?P<p>[.!?])"
+consistent!(katana_12, r"&\$&(?P<p>[.!?])");
+
+// kailua_syntax-1.1.0: r"@(?:_|\d+(?:/\d+(?:-\d+)?)?)"
+consistent!(kailua_syntax_0, r"@(?:_|\d+(?:/\d+(?:-\d+)?)?)");
+
+// kailua_syntax-1.1.0: r"<(\d+)>"
+consistent!(kailua_syntax_1, r"<(\d+)>");
+
+// ftp-3.0.1: r"\((\d+),(\d+),(\d+),(\d+),(\d+),(\d+)\)"
+consistent!(ftp_0, r"\((\d+),(\d+),(\d+),(\d+),(\d+),(\d+)\)");
+
+// ftp-3.0.1: r"\b(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\b"
+consistent!(ftp_1, r"\b(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\b");
+
+// ftp-3.0.1: r"\s+(\d+)\s*$"
+consistent!(ftp_2, r"\s+(\d+)\s*$");
+
+// vat-0.1.0: r"<countryCode>(.*?)</countryCode>"
+consistent!(vat_0, r"<countryCode>(.*?)</countryCode>");
+
+// vat-0.1.0: r"<vatNumber>(.*?)</vatNumber>"
+consistent!(vat_1, r"<vatNumber>(.*?)</vatNumber>");
+
+// vat-0.1.0: r"<name>(.*?)</name>"
+consistent!(vat_2, r"<name>(.*?)</name>");
+
+// vat-0.1.0: r"<address>(?s)(.*?)(?-s)</address>"
+consistent!(vat_3, r"<address>(?s)(.*?)(?-s)</address>");
+
+// vat-0.1.0: r"<valid>(true|false)</valid>"
+consistent!(vat_4, r"<valid>(true|false)</valid>");
+
+// vat-0.1.0: r"^ATU\d{8}$"
+consistent!(vat_5, r"^ATU\d{8}$");
+
+// vat-0.1.0: r"^BE0?\d{9, 10}$"
+consistent!(vat_6, r"^BE0?\d{9, 10}$");
+
+// vat-0.1.0: r"^BG\d{9,10}$"
+consistent!(vat_7, r"^BG\d{9,10}$");
+
+// vat-0.1.0: r"^HR\d{11}$"
+consistent!(vat_8, r"^HR\d{11}$");
+
+// vat-0.1.0: r"^CY\d{8}[A-Z]$"
+consistent!(vat_9, r"^CY\d{8}[A-Z]$");
+
+// vat-0.1.0: r"^CZ\d{8,10}$"
+consistent!(vat_10, r"^CZ\d{8,10}$");
+
+// vat-0.1.0: r"^DK\d{8}$"
+consistent!(vat_11, r"^DK\d{8}$");
+
+// vat-0.1.0: r"^EE\d{9}$"
+consistent!(vat_12, r"^EE\d{9}$");
+
+// vat-0.1.0: r"^FI\d{8}$"
+consistent!(vat_13, r"^FI\d{8}$");
+
+// vat-0.1.0: r"^FR[A-HJ-NP-Z0-9][A-HJ-NP-Z0-9]\d{9}$"
+consistent!(vat_14, r"^FR[A-HJ-NP-Z0-9][A-HJ-NP-Z0-9]\d{9}$");
+
+// vat-0.1.0: r"^DE\d{9}$"
+consistent!(vat_15, r"^DE\d{9}$");
+
+// vat-0.1.0: r"^EL\d{9}$"
+consistent!(vat_16, r"^EL\d{9}$");
+
+// vat-0.1.0: r"^HU\d{8}$"
+consistent!(vat_17, r"^HU\d{8}$");
+
+// vat-0.1.0: r"^IE\d[A-Z0-9\+\*]\d{5}[A-Z]{1,2}$"
+consistent!(vat_18, r"^IE\d[A-Z0-9\+\*]\d{5}[A-Z]{1,2}$");
+
+// vat-0.1.0: r"^IT\d{11}$"
+consistent!(vat_19, r"^IT\d{11}$");
+
+// vat-0.1.0: r"^LV\d{11}$"
+consistent!(vat_20, r"^LV\d{11}$");
+
+// vat-0.1.0: r"^LT(\d{9}|\d{12})$"
+consistent!(vat_21, r"^LT(\d{9}|\d{12})$");
+
+// vat-0.1.0: r"^LU\d{8}$"
+consistent!(vat_22, r"^LU\d{8}$");
+
+// vat-0.1.0: r"^MT\d{8}$"
+consistent!(vat_23, r"^MT\d{8}$");
+
+// vat-0.1.0: r"^NL\d{9}B\d{2}$"
+consistent!(vat_24, r"^NL\d{9}B\d{2}$");
+
+// vat-0.1.0: r"^PL\d{10}$"
+consistent!(vat_25, r"^PL\d{10}$");
+
+// vat-0.1.0: r"^PT\d{9}$"
+consistent!(vat_26, r"^PT\d{9}$");
+
+// vat-0.1.0: r"^RO\d{2,10}$"
+consistent!(vat_27, r"^RO\d{2,10}$");
+
+// vat-0.1.0: r"^SK\d{10}$"
+consistent!(vat_28, r"^SK\d{10}$");
+
+// vat-0.1.0: r"^SI\d{8}$"
+consistent!(vat_29, r"^SI\d{8}$");
+
+// vat-0.1.0: r"^ES[A-Z0-9]\d{7}[A-Z0-9]$"
+consistent!(vat_30, r"^ES[A-Z0-9]\d{7}[A-Z0-9]$");
+
+// vat-0.1.0: r"^SE\d{10}01$"
+consistent!(vat_31, r"^SE\d{10}01$");
+
+// vat-0.1.0: r"^(GB(GD|HA)\d{3}|GB\d{9}|GB\d{12})$"
+consistent!(vat_32, r"^(GB(GD|HA)\d{3}|GB\d{9}|GB\d{12})$");
+
+// eve-0.1.1: r"\{\{(.*)\}\}"
+consistent!(eve_0, r"\{\{(.*)\}\}");
+
+// egc-0.1.2: "^mio"
+consistent!(egc_0, "^mio");
+
+// pew-0.2.3: ""
+consistent!(pew_0, "");
+
+// pew-0.2.3: ""
+consistent!(pew_1, "");
+
+// mob-0.4.3: "y"
+consistent!(mob_0, "y");
+
+// lit-0.2.8: "@([a-z]+)"
+consistent!(lit_0, "@([a-z]+)");
+
+// lit-0.2.8: "([A-Z-]+):(.*)"
+consistent!(lit_1, "([A-Z-]+):(.*)");
+
+// lit-0.2.8: "^[a-zA-Z_][a-zA-Z0-9_]*$"
+consistent!(lit_2, "^[a-zA-Z_][a-zA-Z0-9_]*$");
+
+// avm-1.0.1: r"\d+\.\d+\.\d+"
+consistent!(avm_0, r"\d+\.\d+\.\d+");
+
+// avm-1.0.1: r"\d+\.\d+\.\d+"
+consistent!(avm_1, r"\d+\.\d+\.\d+");
+
+// orm-0.2.0: r"^Vec<(.+)>$"
+consistent!(orm_0, r"^Vec<(.+)>$");
+
+// sgf-0.1.5: r"\\(\r\n|\n\r|\n|\r)"
+consistent!(sgf_0, r"\\(\r\n|\n\r|\n|\r)");
+
+// sgf-0.1.5: r"\\(.)"
+consistent!(sgf_1, r"\\(.)");
+
+// sgf-0.1.5: r"\r\n|\n\r|\n|\r"
+consistent!(sgf_2, r"\r\n|\n\r|\n|\r");
+
+// sgf-0.1.5: r"([\]\\:])"
+consistent!(sgf_3, r"([\]\\:])");
+
+// dok-0.2.0: "^Bearer realm=\"(.+?)\",service=\"(.+?)\",scope=\"(.+?)\"$"
+consistent!(
+    dok_0,
+    "^Bearer realm=\"(.+?)\",service=\"(.+?)\",scope=\"(.+?)\"$"
+);
+
+// d20-0.1.0: r"([+-]?\s*\d+[dD]\d+|[+-]?\s*\d+)"
+consistent!(d20_0, r"([+-]?\s*\d+[dD]\d+|[+-]?\s*\d+)");
+
+// dvb-0.3.0: "E"
+consistent!(dvb_0, "E");
+
+// dvb-0.3.0: "^F"
+consistent!(dvb_1, "^F");
+
+// dvb-0.3.0: "^S"
+consistent!(dvb_2, "^S");
+
+// ger-0.2.0: r"Change-Id: (I[a-f0-9]{40})$"
+consistent!(ger_0, r"Change-Id: (I[a-f0-9]{40})$");
+
+// ger-0.2.0: r"(refs|ref|fix|fixes|close|closes)\s+([A-Z]{2,5}-[0-9]{1,5})$"
+consistent!(
+    ger_1,
+    r"(refs|ref|fix|fixes|close|closes)\s+([A-Z]{2,5}-[0-9]{1,5})$"
+);
+
+// n5-0.2.1: r"(\d+)(\.(\d+))?(\.(\d+))?(.*)"
+consistent!(n5_0, r"(\d+)(\.(\d+))?(\.(\d+))?(.*)");
+
+// po-0.1.4: r"[A-Za-z0-9]"
+consistent!(po_0, r"[A-Za-z0-9]");
+
+// carnix-0.8.5: "path is (‘|')?([^’'\n]*)(’|')?"
+consistent!(carnix_0, "path is (‘|')?([^’'\n]*)(’|')?");
+
+// carnix-0.8.5: r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?(.*)?"
+consistent!(carnix_1, r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?(.*)?");
+
+// carnix-0.8.5: r"(\d*)\.(\d*)\.(\d*)(-(\S*))?"
+consistent!(carnix_2, r"(\d*)\.(\d*)\.(\d*)(-(\S*))?");
+
+// carnix-0.8.5: r"(\S*)-(\d*)\.(\d*)\.(\d*)(-(\S*))?"
+consistent!(carnix_3, r"(\S*)-(\d*)\.(\d*)\.(\d*)(-(\S*))?");
+
+// caseless-0.2.1: r"^# CaseFolding-(\d+)\.(\d+)\.(\d+).txt$"
+consistent!(caseless_0, r"^# CaseFolding-(\d+)\.(\d+)\.(\d+).txt$");
+
+// caseless-0.2.1: r"^([0-9A-F]+); [CF]; ([0-9A-F ]+);"
+consistent!(caseless_1, r"^([0-9A-F]+); [CF]; ([0-9A-F ]+);");
+
+// cabot-0.2.0: "\r?\n\r?\n"
+consistent!(cabot_0, "\r?\n\r?\n");
+
+// cabot-0.2.0: "\r?\n"
+consistent!(cabot_1, "\r?\n");
+
+// card-validate-2.2.1: r"^600"
+consistent!(card_validate_0, r"^600");
+
+// card-validate-2.2.1: r"^5019"
+consistent!(card_validate_1, r"^5019");
+
+// card-validate-2.2.1: r"^4"
+consistent!(card_validate_2, r"^4");
+
+// card-validate-2.2.1: r"^(5[1-5]|2[2-7])"
+consistent!(card_validate_3, r"^(5[1-5]|2[2-7])");
+
+// card-validate-2.2.1: r"^3[47]"
+consistent!(card_validate_4, r"^3[47]");
+
+// card-validate-2.2.1: r"^3[0689]"
+consistent!(card_validate_5, r"^3[0689]");
+
+// card-validate-2.2.1: r"^6([045]|22)"
+consistent!(card_validate_6, r"^6([045]|22)");
+
+// card-validate-2.2.1: r"^(62|88)"
+consistent!(card_validate_7, r"^(62|88)");
+
+// card-validate-2.2.1: r"^35"
+consistent!(card_validate_8, r"^35");
+
+// card-validate-2.2.1: r"^[0-9]+$"
+consistent!(card_validate_9, r"^[0-9]+$");
+
+// cargo-testify-0.3.0: r"\d{1,} passed.*filtered out"
+consistent!(cargo_testify_0, r"\d{1,} passed.*filtered out");
+
+// cargo-testify-0.3.0: r"error(:|\[).*"
+consistent!(cargo_testify_1, r"error(:|\[).*");
+
+// cargo-wix-0.0.5: r"<(.*?)>"
+consistent!(cargo_wix_0, r"<(.*?)>");
+
+// cargo-wix-0.0.5: r"<(.*?)>"
+consistent!(cargo_wix_1, r"<(.*?)>");
+
+// cargo-wix-0.0.5: r"<(.*?)>"
+consistent!(cargo_wix_2, r"<(.*?)>");
+
+// cargo-wix-0.0.5: r"<(.*?)>"
+consistent!(cargo_wix_3, r"<(.*?)>");
+
+// cargo-incremental-0.1.23: r"(?m)^incremental: re-using (\d+) out of (\d+) modules$"
+consistent!(
+    cargo_incremental_0,
+    r"(?m)^incremental: re-using (\d+) out of (\d+) modules$"
+);
+
+// cargo-incremental-0.1.23: "(?m)(warning|error): (.*)\n  --> ([^:]:\\d+:\\d+)$"
+consistent!(
+    cargo_incremental_1,
+    "(?m)(warning|error): (.*)\n  --> ([^:]:\\d+:\\d+)$"
+);
+
+// cargo-incremental-0.1.23: r"(?m)^test (.*) \.\.\. (\w+)"
+consistent!(cargo_incremental_2, r"(?m)^test (.*) \.\.\. (\w+)");
+
+// cargo-incremental-0.1.23: r"(?m)(\d+) passed; (\d+) failed; (\d+) ignored; \d+ measured"
+consistent!(
+    cargo_incremental_3,
+    r"(?m)(\d+) passed; (\d+) failed; (\d+) ignored; \d+ measured"
+);
+
+// cargo-testjs-0.1.2: r"^[^-]+-[0-9a-f]+\.js$"
+consistent!(cargo_testjs_0, r"^[^-]+-[0-9a-f]+\.js$");
+
+// cargo-tarpaulin-0.6.2: r"\s*//"
+consistent!(cargo_tarpaulin_0, r"\s*//");
+
+// cargo-tarpaulin-0.6.2: r"/\*"
+consistent!(cargo_tarpaulin_1, r"/\*");
+
+// cargo-tarpaulin-0.6.2: r"\*/"
+consistent!(cargo_tarpaulin_2, r"\*/");
+
+// cargo-culture-kit-0.1.0: r"^fo"
+consistent!(cargo_culture_kit_0, r"^fo");
+
+// cargo-screeps-0.1.3: "\\s+"
+consistent!(cargo_screeps_0, "\\s+");
+
+// cargo-brew-0.1.4: r"`(\S+) v([0-9.]+)"
+consistent!(cargo_brew_0, r"`(\S+) v([0-9.]+)");
+
+// cargo-release-0.10.2: "^\\[.+\\]"
+consistent!(cargo_release_0, "^\\[.+\\]");
+
+// cargo-release-0.10.2: "^\\[\\[.+\\]\\]"
+consistent!(cargo_release_1, "^\\[\\[.+\\]\\]");
+
+// cargo-edit-0.3.0-beta.1: r"^https://github.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$"
+consistent!(
+    cargo_edit_0,
+    r"^https://github.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$"
+);
+
+// cargo-edit-0.3.0-beta.1: r"^https://gitlab.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$"
+consistent!(
+    cargo_edit_1,
+    r"^https://gitlab.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$"
+);
+
+// cargo-disassemble-0.1.1: ".*"
+consistent!(cargo_disassemble_0, ".*");
+
+// cargo-demangle-0.1.2: r"(?m)(?P<symbol>_ZN[0-9]+.*E)"
+consistent!(cargo_demangle_0, r"(?m)(?P<symbol>_ZN[0-9]+.*E)");
+
+// cargo-coverage-annotations-0.1.5: r"^\s*\}(?:\)*;?|\s*else\s*\{)$"
+consistent!(cargo_coverage_annotations_0, r"^\s*\}(?:\)*;?|\s*else\s*\{)$");
+
+// cargo-urlcrate-1.0.1: "[\u{001b}\u{009b}][\\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]"
+consistent!(cargo_urlcrate_0, "[\u{001b}\u{009b}][\\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]");
+
+// cargo-script-0.2.8: r"^\s*\*( |$)"
+consistent!(cargo_script_0, r"^\s*\*( |$)");
+
+// cargo-script-0.2.8: r"^(\s+)"
+consistent!(cargo_script_1, r"^(\s+)");
+
+// cargo-script-0.2.8: r"/\*|\*/"
+consistent!(cargo_script_2, r"/\*|\*/");
+
+// cargo-script-0.2.8: r"^\s*//!"
+consistent!(cargo_script_3, r"^\s*//!");
+
+// cargo-script-0.2.8: r"^#![^\[].*?(\r\n|\n)"
+consistent!(cargo_script_4, r"^#![^\[].*?(\r\n|\n)");
+
+// cargo-update-1.5.2: r"cargo-install-update\.exe-v.+"
+consistent!(cargo_update_0, r"cargo-install-update\.exe-v.+");
+
+// canteen-0.4.1: r"^<(?:(int|uint|str|float|path):)?([\w_][a-zA-Z0-9_]*)>$"
+consistent!(
+    canteen_0,
+    r"^<(?:(int|uint|str|float|path):)?([\w_][a-zA-Z0-9_]*)>$"
+);
+
+// thruster-cli-0.1.3: r"(.)([A-Z])"
+consistent!(thruster_cli_0, r"(.)([A-Z])");
+
+// thieves-cant-0.1.0: "([Z]+)$"
+consistent!(thieves_cant_0, "([Z]+)$");
+
+// codeowners-0.1.3: r"^@\S+/\S+"
+consistent!(codeowners_0, r"^@\S+/\S+");
+
+// codeowners-0.1.3: r"^@\S+"
+consistent!(codeowners_1, r"^@\S+");
+
+// codeowners-0.1.3: r"^\S+@\S+"
+consistent!(codeowners_2, r"^\S+@\S+");
+
+// conserve-0.4.2: r"^b0000 {21} complete   20[-0-9T:+]+\s +\d+s\n$"
+consistent!(conserve_0, r"^b0000 {21} complete   20[-0-9T:+]+\s +\d+s\n$");
+
+// commodore-0.3.0: r"(?P<greeting>\S+?) (?P<name>\S+?)$"
+consistent!(commodore_0, r"(?P<greeting>\S+?) (?P<name>\S+?)$");
+
+// corollary-0.3.0: r"([ \t]*)```haskell([\s\S]*?)```"
+consistent!(corollary_0, r"([ \t]*)```haskell([\s\S]*?)```");
+
+// corollary-0.3.0: r"\b((?:a|b|t)\d*)\b"
+consistent!(corollary_1, r"\b((?:a|b|t)\d*)\b");
+
+// colorizex-0.1.3: "NB"
+consistent!(colorizex_0, "NB");
+
+// colorstring-0.0.1: r"(?i)\[[a-z0-9_-]+\]"
+consistent!(colorstring_0, r"(?i)\[[a-z0-9_-]+\]");
+
+// colorstring-0.0.1: r"^(?i)(\[[a-z0-9_-]+\])+"
+consistent!(colorstring_1, r"^(?i)(\[[a-z0-9_-]+\])+");
+
+// cosmogony-0.3.0: "name:(.+)"
+consistent!(cosmogony_0, "name:(.+)");
+
+// cobalt-bin-0.12.1: r"(?m:^ {0,3}\[[^\]]+\]:.+$)"
+consistent!(cobalt_bin_0, r"(?m:^ {0,3}\[[^\]]+\]:.+$)");
+
+// comrak-0.2.12: r"[^\p{L}\p{M}\p{N}\p{Pc} -]"
+consistent!(comrak_0, r"[^\p{L}\p{M}\p{N}\p{Pc} -]");
+
+// content-blocker-0.2.3: ""
+consistent!(content_blocker_0, "");
+
+// content-blocker-0.2.3: "(?i)hi"
+consistent!(content_blocker_1, "(?i)hi");
+
+// content-blocker-0.2.3: "http[s]?://domain.org"
+consistent!(content_blocker_2, "http[s]?://domain.org");
+
+// content-blocker-0.2.3: "(?i)http[s]?://domain.org"
+consistent!(content_blocker_3, "(?i)http[s]?://domain.org");
+
+// content-blocker-0.2.3: "http://domain.org"
+consistent!(content_blocker_4, "http://domain.org");
+
+// content-blocker-0.2.3: "http://domain.org"
+consistent!(content_blocker_5, "http://domain.org");
+
+// content-blocker-0.2.3: "ad.html"
+consistent!(content_blocker_6, "ad.html");
+
+// content-blocker-0.2.3: "ad.html"
+consistent!(content_blocker_7, "ad.html");
+
+// content-blocker-0.2.3: "http://domain.org"
+consistent!(content_blocker_8, "http://domain.org");
+
+// content-blocker-0.2.3: "http://domain.org/nocookies.sjs"
+consistent!(content_blocker_9, "http://domain.org/nocookies.sjs");
+
+// content-blocker-0.2.3: "http://domain.org/nocookies.sjs"
+consistent!(content_blocker_10, "http://domain.org/nocookies.sjs");
+
+// content-blocker-0.2.3: "http://domain.org/hideme.jpg"
+consistent!(content_blocker_11, "http://domain.org/hideme.jpg");
+
+// content-blocker-0.2.3: "http://domain.org/ok.html"
+consistent!(content_blocker_12, "http://domain.org/ok.html");
+
+// content-blocker-0.2.3: "http://domain.org/ok.html\\?except_this=1"
+consistent!(content_blocker_13, "http://domain.org/ok.html\\?except_this=1");
+
+// victoria-dom-0.1.2: "[A-Za-z0-9=]"
+consistent!(victoria_dom_0, "[A-Za-z0-9=]");
+
+// numbat-1.0.0: r"^nsq://"
+consistent!(numbat_0, r"^nsq://");
+
+// airkorea-0.1.2: r"[\s\t\r\n]"
+consistent!(airkorea_0, r"[\s\t\r\n]");
+
+// airkorea-0.1.2: r"([\{\[,])|([\}\]])"
+consistent!(airkorea_1, r"([\{\[,])|([\}\]])");
+
+// airkorea-0.1.2: r"[^.\d]+$"
+consistent!(airkorea_2, r"[^.\d]+$");
+
+// rofl-0.0.1: r"\b"
+// consistent!(rofl_0, r"\b");
+
+// rogcat-0.2.15: r"--------- beginning of.*"
+consistent!(rogcat_0, r"--------- beginning of.*");
+
+// rogcat-0.2.15: r"a|e|i|o|u"
+consistent!(rogcat_1, r"a|e|i|o|u");
+
+// rogcat-0.2.15: r"^(\d+)([kMG])$"
+consistent!(rogcat_2, r"^(\d+)([kMG])$");
+
+// media_filename-0.1.4: "\\.([A-Za-z0-9]{2,4})$"
+consistent!(media_filename_0, "\\.([A-Za-z0-9]{2,4})$");
+
+// media_filename-0.1.4: "([0-9]{3,4}p|[0-9]{3,4}x[0-9]{3,4})"
+consistent!(media_filename_1, "([0-9]{3,4}p|[0-9]{3,4}x[0-9]{3,4})");
+
+// media_filename-0.1.4: "(?:^\\[([^]]+)\\]|- ?([^-]+)$)"
+consistent!(media_filename_2, "(?:^\\[([^]]+)\\]|- ?([^-]+)$)");
+
+// media_filename-0.1.4: "(?:[eE]([0-9]{2,3})|[^0-9A-Za-z]([0-9]{2,3})(?:v[0-9])?[^0-9A-Za-z])"
+consistent!(
+    media_filename_3,
+    "(?:[eE]([0-9]{2,3})|[^0-9A-Za-z]([0-9]{2,3})(?:v[0-9])?[^0-9A-Za-z])"
+);
+
+// media_filename-0.1.4: "[sS]([0-9]{1,2})"
+consistent!(media_filename_4, "[sS]([0-9]{1,2})");
+
+// media_filename-0.1.4: "((?i)(?:PPV.)?[HP]DTV|(?:HD)?CAM|BRRIP|[^a-z]TS[^a-z]|(?:PPV )?WEB.?DL(?: DVDRip)?|HDRip|DVDRip|CamRip|W[EB]BRip|BluRay|BD|DVD|DvDScr|hdtv)"
+consistent!(media_filename_5, "((?i)(?:PPV.)?[HP]DTV|(?:HD)?CAM|BRRIP|[^a-z]TS[^a-z]|(?:PPV )?WEB.?DL(?: DVDRip)?|HDRip|DVDRip|CamRip|W[EB]BRip|BluRay|BD|DVD|DvDScr|hdtv)");
+
+// media_filename-0.1.4: "((19[0-9]|20[01])[0-9])"
+consistent!(media_filename_6, "((19[0-9]|20[01])[0-9])");
+
+// media_filename-0.1.4: "((?i)xvid|x264|h\\.?264)"
+consistent!(media_filename_7, "((?i)xvid|x264|h\\.?264)");
+
+// media_filename-0.1.4: "((?i)MP3|DD5\\.?1|Dual[- ]Audio|LiNE|DTS|AAC(?:\\.?2\\.0)?|AC3(?:\\.5\\.1)?)"
+consistent!(media_filename_8, "((?i)MP3|DD5\\.?1|Dual[- ]Audio|LiNE|DTS|AAC(?:\\.?2\\.0)?|AC3(?:\\.5\\.1)?)");
+
+// media_filename-0.1.4: "\\[([0-9A-F]{8})\\]"
+consistent!(media_filename_9, "\\[([0-9A-F]{8})\\]");
+
+// termimage-0.3.2: r"(\d+)[xX](\d+)"
+consistent!(termimage_0, r"(\d+)[xX](\d+)");
+
+// teensy-0.1.0: r".*(\d{4}-\d{2}-\d{2}).*"
+consistent!(teensy_0, r".*(\d{4}-\d{2}-\d{2}).*");
+
+// telescreen-0.1.3: r"<@(.+)>"
+consistent!(telescreen_0, r"<@(.+)>");
+
+// tempus_fugit-0.4.4: r"^(\d+)"
+consistent!(tempus_fugit_0, r"^(\d+)");
+
+// fselect-0.4.1: "(\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)"
+consistent!(fselect_0, "(\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)");
+
+// fselect-0.4.1: "(%|_|\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)"
+consistent!(fselect_1, "(%|_|\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)");
+
+// fs_eventbridge-0.1.0: r"^([A-Z]+)(?:\s(.+))?\s*"
+consistent!(fs_eventbridge_0, r"^([A-Z]+)(?:\s(.+))?\s*");
+
+// joseki-0.0.1: r"(\w{1,2})\[(.+?)\]"
+consistent!(joseki_0, r"(\w{1,2})\[(.+?)\]");
+
+// tweetr-0.2.1: r"(?i)in (\d+) (second|minute|hour|day|week)s?"
+consistent!(tweetr_0, r"(?i)in (\d+) (second|minute|hour|day|week)s?");
+
+// bullet_core-0.1.1: "^(?u:[0-9])+"
+consistent!(bullet_core_0, "^(?u:[0-9])+");
+
+// bullet_core-0.1.1: "^(?u:[0-9])+(?u:\\.)(?u:[0-9])+"
+consistent!(bullet_core_1, "^(?u:[0-9])+(?u:\\.)(?u:[0-9])+");
+
+// bullet_core-0.1.1: "^(?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+"
+consistent!(bullet_core_2, "^(?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+");
+
+// bullet_core-0.1.1: "^(?u:d/d)((?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+)"
+consistent!(bullet_core_3, "^(?u:d/d)((?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+)");
+
+// bullet_core-0.1.1: "^(?u:\\()"
+consistent!(bullet_core_4, "^(?u:\\()");
+
+// bullet_core-0.1.1: "^(?u:\\))"
+consistent!(bullet_core_5, "^(?u:\\))");
+
+// bullet_core-0.1.1: "^(?u:\\*)"
+consistent!(bullet_core_6, "^(?u:\\*)");
+
+// bullet_core-0.1.1: "^(?u:\\+)"
+consistent!(bullet_core_7, "^(?u:\\+)");
+
+// bullet_core-0.1.1: "^(?u:,)"
+consistent!(bullet_core_8, "^(?u:,)");
+
+// bullet_core-0.1.1: "^(?u:\\-)"
+consistent!(bullet_core_9, "^(?u:\\-)");
+
+// bullet_core-0.1.1: "^(?u:/)"
+consistent!(bullet_core_10, "^(?u:/)");
+
+// bullet_core-0.1.1: "^(?u:\\[)"
+consistent!(bullet_core_11, "^(?u:\\[)");
+
+// bullet_core-0.1.1: "^(?u:\\])"
+consistent!(bullet_core_12, "^(?u:\\])");
+
+// bullet_core-0.1.1: "^(?u:\\^)"
+consistent!(bullet_core_13, "^(?u:\\^)");
+
+// bullet_core-0.1.1: "^(?u:·)"
+consistent!(bullet_core_14, "^(?u:·)");
+
+// actix-web-0.6.13: "//+"
+consistent!(actix_web_0, "//+");
+
+// actix-web-0.6.13: "//+"
+consistent!(actix_web_1, "//+");
+
+// althea_kernel_interface-0.1.0: r"(\S*) .* (\S*) (REACHABLE|STALE|DELAY)"
+consistent!(
+    althea_kernel_interface_0,
+    r"(\S*) .* (\S*) (REACHABLE|STALE|DELAY)"
+);
+
+// althea_kernel_interface-0.1.0: r"-s (.*) --ip6-dst (.*)/.* bcnt = (.*)"
+consistent!(
+    althea_kernel_interface_1,
+    r"-s (.*) --ip6-dst (.*)/.* bcnt = (.*)"
+);
+
+// alcibiades-0.3.0: r"\buci(?:\s|$)"
+consistent!(alcibiades_0, r"\buci(?:\s|$)");
+
+// ruma-identifiers-0.11.0: r"\A[a-z0-9._=-]+\z"
+consistent!(ruma_identifiers_0, r"\A[a-z0-9._=-]+\z");
+
+// rusqbin-0.2.3: r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})$"
+consistent!(rusqbin_0, r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})$");
+
+// rusqbin-0.2.3: r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})/requests/?$"
+consistent!(rusqbin_1, r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})/requests/?$");
+
+// rust-install-0.0.4: r"^(nightly|beta|stable)(?:-(\d{4}-\d{2}-\d{2}))?$"
+consistent!(
+    rust_install_0,
+    r"^(nightly|beta|stable)(?:-(\d{4}-\d{2}-\d{2}))?$"
+);
+
+// rust_inbox-0.0.5: "^+(.*)\r\n"
+consistent!(rust_inbox_0, "^+(.*)\r\n");
+
+// rust_inbox-0.0.5: r"^\* CAPABILITY (.*)\r\n"
+consistent!(rust_inbox_1, r"^\* CAPABILITY (.*)\r\n");
+
+// rust_inbox-0.0.5: r"^([a-zA-Z0-9]+) (OK|NO|BAD)(.*)"
+consistent!(rust_inbox_2, r"^([a-zA-Z0-9]+) (OK|NO|BAD)(.*)");
+
+// rust_inbox-0.0.5: r"^\* (\d+) EXISTS\r\n"
+consistent!(rust_inbox_3, r"^\* (\d+) EXISTS\r\n");
+
+// rust_inbox-0.0.5: r"^\* (\d+) RECENT\r\n"
+consistent!(rust_inbox_4, r"^\* (\d+) RECENT\r\n");
+
+// rust_inbox-0.0.5: r"^\* FLAGS (.+)\r\n"
+consistent!(rust_inbox_5, r"^\* FLAGS (.+)\r\n");
+
+// rust_inbox-0.0.5: r"^\* OK \[UNSEEN (\d+)\](.*)\r\n"
+consistent!(rust_inbox_6, r"^\* OK \[UNSEEN (\d+)\](.*)\r\n");
+
+// rust_inbox-0.0.5: r"^\* OK \[UIDVALIDITY (\d+)\](.*)\r\n"
+consistent!(rust_inbox_7, r"^\* OK \[UIDVALIDITY (\d+)\](.*)\r\n");
+
+// rust_inbox-0.0.5: r"^\* OK \[UIDNEXT (\d+)\](.*)\r\n"
+consistent!(rust_inbox_8, r"^\* OK \[UIDNEXT (\d+)\](.*)\r\n");
+
+// rust_inbox-0.0.5: r"^\* OK \[PERMANENTFLAGS (.+)\](.*)\r\n"
+consistent!(rust_inbox_9, r"^\* OK \[PERMANENTFLAGS (.+)\](.*)\r\n");
+
+// rustml-0.0.7: r"^[a-z]+ (\d+)$"
+consistent!(rustml_0, r"^[a-z]+ (\d+)$");
+
+// rustml-0.0.7: r"^[a-z]+ (\d+)$"
+consistent!(rustml_1, r"^[a-z]+ (\d+)$");
+
+// rustml-0.0.7: r"^[a-z]+ (\d+)$"
+consistent!(rustml_2, r"^[a-z]+ (\d+)$");
+
+// rustfmt-0.10.0: r"([^\\](\\\\)*)\\[\n\r][[:space:]]*"
+consistent!(rustfmt_0, r"([^\\](\\\\)*)\\[\n\r][[:space:]]*");
+
+// rustfmt-core-0.4.0: r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)"
+consistent!(rustfmt_core_0, r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)");
+
+// rustfmt-core-0.4.0: r"^## `([^`]+)`"
+consistent!(rustfmt_core_1, r"^## `([^`]+)`");
+
+// rustfmt-core-0.4.0: r"([^\\](\\\\)*)\\[\n\r][[:space:]]*"
+consistent!(rustfmt_core_2, r"([^\\](\\\\)*)\\[\n\r][[:space:]]*");
+
+// rustfmt-core-0.4.0: r"\s;"
+consistent!(rustfmt_core_3, r"\s;");
+
+// rust-enum-derive-0.4.0: r"^(0x)?([:digit:]+)$"
+consistent!(rust_enum_derive_0, r"^(0x)?([:digit:]+)$");
+
+// rust-enum-derive-0.4.0: r"^([:digit:]+)[:space:]*<<[:space:]*([:digit:]+)$"
+consistent!(
+    rust_enum_derive_1,
+    r"^([:digit:]+)[:space:]*<<[:space:]*([:digit:]+)$"
+);
+
+// rust-enum-derive-0.4.0: r"^[:space:]*([[:alnum:]_]+)([:space:]*=[:space:]*([:graph:]+))?[:space:]*,"
+consistent!(rust_enum_derive_2, r"^[:space:]*([[:alnum:]_]+)([:space:]*=[:space:]*([:graph:]+))?[:space:]*,");
+
+// rust-enum-derive-0.4.0: r"^#define[:space:]+([:graph:]+)[:space:]+([:graph:]+)"
+consistent!(
+    rust_enum_derive_3,
+    r"^#define[:space:]+([:graph:]+)[:space:]+([:graph:]+)"
+);
+
+// rustsourcebundler-0.2.0: r"^\s*pub mod (.+);$"
+consistent!(rustsourcebundler_0, r"^\s*pub mod (.+);$");
+
+// rustsourcebundler-0.2.0: r"^\s*pub mod (.+);$"
+consistent!(rustsourcebundler_1, r"^\s*pub mod (.+);$");
+
+// rustfmt-nightly-0.8.2: r"([^\\](\\\\)*)\\[\n\r][[:space:]]*"
+consistent!(rustfmt_nightly_0, r"([^\\](\\\\)*)\\[\n\r][[:space:]]*");
+
+// rustfmt-nightly-0.8.2: r"\s;"
+consistent!(rustfmt_nightly_1, r"\s;");
+
+// rustache-0.1.0: r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)"
+consistent!(rustache_0, r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)");
+
+// rustfilt-0.2.0: r"_ZN[\$\._[:alnum:]]*"
+consistent!(rustfilt_0, r"_ZN[\$\._[:alnum:]]*");
+
+// rustache-lists-0.1.2: r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)"
+consistent!(rustache_lists_0, r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)");
+
+// rural-0.7.3: "(.+)=(.+)"
+consistent!(rural_0, "(.+)=(.+)");
+
+// rural-0.7.3: "(.*):(.+)"
+consistent!(rural_1, "(.*):(.+)");
+
+// rural-0.7.3: "(.+):=(.+)"
+consistent!(rural_2, "(.+):=(.+)");
+
+// rural-0.7.3: "(.*)==(.+)"
+consistent!(rural_3, "(.*)==(.+)");
+
+// rusoto_credential-0.11.0: r"^\[([^\]]+)\]$"
+consistent!(rusoto_credential_0, r"^\[([^\]]+)\]$");
+
+// rumblebars-0.3.0: "([:blank:]*)$"
+consistent!(rumblebars_0, "([:blank:]*)$");
+
+// rumblebars-0.3.0: "(\r?\n)[:blank:]*(\\{\\{~?[#!/](?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z"
+consistent!(rumblebars_1, "(\r?\n)[:blank:]*(\\{\\{~?[#!/](?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z");
+
+// rumblebars-0.3.0: "(\r?\n[:blank:]*)(\\{\\{~?>(?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z"
+consistent!(
+    rumblebars_2,
+    "(\r?\n[:blank:]*)(\\{\\{~?>(?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z"
+);
+
+// rumblebars-0.3.0: "((?:[:blank:]|\r?\n)*)(\r?\n)[:blank:]*$"
+consistent!(rumblebars_3, "((?:[:blank:]|\r?\n)*)(\r?\n)[:blank:]*$");
+
+// rumblebars-0.3.0: "^([:blank:]*\r?\n)(.*)"
+consistent!(rumblebars_4, "^([:blank:]*\r?\n)(.*)");
+
+// diesel_cli-1.3.1: r"(?P<stamp>[\d-]*)_hello"
+consistent!(diesel_cli_0, r"(?P<stamp>[\d-]*)_hello");
+
+// dishub-0.1.1: r"(\d+)s"
+consistent!(dishub_0, r"(\d+)s");
+
+// spreadsheet_textconv-0.1.0: r"\n"
+consistent!(spreadsheet_textconv_0, r"\n");
+
+// spreadsheet_textconv-0.1.0: r"\r"
+consistent!(spreadsheet_textconv_1, r"\r");
+
+// spreadsheet_textconv-0.1.0: r"\t"
+consistent!(spreadsheet_textconv_2, r"\t");
+
+// split_aud-0.1.0: r"DELAY (-?\d+)ms"
+consistent!(split_aud_0, r"DELAY (-?\d+)ms");
+
+// split_aud-0.1.0: r"Trim\((\d+), ?(\d+)\)"
+consistent!(split_aud_1, r"Trim\((\d+), ?(\d+)\)");
+
+// spotrust-0.0.5: r"spotify:[a-z]+:[a-zA-Z0-9]+"
+consistent!(spotrust_0, r"spotify:[a-z]+:[a-zA-Z0-9]+");
+
+// spaceslugs-0.1.0: r"[^\x00-\x7F]"
+consistent!(spaceslugs_0, r"[^\x00-\x7F]");
+
+// spaceslugs-0.1.0: r"[']+"
+consistent!(spaceslugs_1, r"[']+");
+
+// spaceslugs-0.1.0: r"\W+"
+consistent!(spaceslugs_2, r"\W+");
+
+// spaceslugs-0.1.0: r"[ ]+"
+consistent!(spaceslugs_3, r"[ ]+");
+
+// space_email_api-0.1.1: "PHPSESSID=([0-9a-f]+)"
+consistent!(space_email_api_0, "PHPSESSID=([0-9a-f]+)");
+
+// lorikeet-0.7.0: "[^0-9.,]"
+consistent!(lorikeet_0, "[^0-9.,]");
+
+// claude-0.3.0: r"^(?:\b|(-)?)(\p{Currency_Symbol})?((?:(?:\d{1,3}[\.,])+\d{3})|\d+)(?:[\.,](\d{2}))?\b$"
+consistent!(claude_0, r"^(?:\b|(-)?)(\p{Currency_Symbol})?((?:(?:\d{1,3}[\.,])+\d{3})|\d+)(?:[\.,](\d{2}))?\b$");
+
+// clam-0.1.6: r"<%=\s*(.+?)\s*%>"
+consistent!(clam_0, r"<%=\s*(.+?)\s*%>");
+
+// classifier-0.0.3: r"(\s)"
+consistent!(classifier_0, r"(\s)");
+
+// click-0.3.2: r"(-----BEGIN .*-----\n)((?:(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)*\n)+)(-----END .*-----)"
+consistent!(click_0, r"(-----BEGIN .*-----\n)((?:(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)*\n)+)(-----END .*-----)");
+
+// click-0.3.2: r"-----BEGIN PRIVATE KEY-----"
+consistent!(click_1, r"-----BEGIN PRIVATE KEY-----");
+
+// ultrastar-txt-0.1.2: r"#([A-Z3a-z]*):(.*)"
+consistent!(ultrastar_txt_0, r"#([A-Z3a-z]*):(.*)");
+
+// ultrastar-txt-0.1.2: "^-\\s?(-?[0-9]+)\\s*$"
+consistent!(ultrastar_txt_1, "^-\\s?(-?[0-9]+)\\s*$");
+
+// ultrastar-txt-0.1.2: "^-\\s?(-?[0-9]+)\\s+(-?[0-9]+)"
+consistent!(ultrastar_txt_2, "^-\\s?(-?[0-9]+)\\s+(-?[0-9]+)");
+
+// ultrastar-txt-0.1.2: "^(.)\\s*(-?[0-9]+)\\s+(-?[0-9]+)\\s+(-?[0-9]+)\\s?(.*)"
+consistent!(
+    ultrastar_txt_3,
+    "^(.)\\s*(-?[0-9]+)\\s+(-?[0-9]+)\\s+(-?[0-9]+)\\s?(.*)"
+);
+
+// ultrastar-txt-0.1.2: "^P\\s?(-?[0-9]+)"
+consistent!(ultrastar_txt_4, "^P\\s?(-?[0-9]+)");
+
+// db-accelerate-2.0.0: r"^template\.add($|\..+$)"
+consistent!(db_accelerate_0, r"^template\.add($|\..+$)");
+
+// db-accelerate-2.0.0: r"^template\.sub($|\..+$)"
+consistent!(db_accelerate_1, r"^template\.sub($|\..+$)");
+
+// sterling-0.3.0: r"(\d+)([cegps])"
+consistent!(sterling_0, r"(\d+)([cegps])");
+
+// stache-0.2.0: r"[^\w]"
+consistent!(stache_0, r"[^\w]");
+
+// strukt-0.1.0: "\"([<>]?)([xcbB\\?hHiIlLqQfdspP]*)\""
+consistent!(strukt_0, "\"([<>]?)([xcbB\\?hHiIlLqQfdspP]*)\"");
+
+// steamid-ng-0.3.1: r"^STEAM_([0-4]):([0-1]):([0-9]{1,10})$"
+consistent!(steamid_ng_0, r"^STEAM_([0-4]):([0-1]):([0-9]{1,10})$");
+
+// steamid-ng-0.3.1: r"^\[([AGMPCgcLTIUai]):([0-4]):([0-9]{1,10})(:([0-9]+))?\]$"
+consistent!(
+    steamid_ng_1,
+    r"^\[([AGMPCgcLTIUai]):([0-4]):([0-9]{1,10})(:([0-9]+))?\]$"
+);
+
+// strscan-0.1.1: r"^\w+"
+consistent!(strscan_0, r"^\w+");
+
+// strscan-0.1.1: r"^\s+"
+consistent!(strscan_1, r"^\s+");
+
+// strscan-0.1.1: r"^\w+"
+consistent!(strscan_2, r"^\w+");
+
+// strscan-0.1.1: r"^\s+"
+consistent!(strscan_3, r"^\s+");
+
+// strscan-0.1.1: r"^(\w+)\s+"
+consistent!(strscan_4, r"^(\w+)\s+");
+
+// tk-carbon-0.2.0: r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$"
+consistent!(tk_carbon_0, r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$");
+
+// tk-carbon-0.2.0: r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$"
+consistent!(tk_carbon_1, r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$");
+
+// evalrs-0.0.10: r"extern\s+crate\s+([a-z0-9_]+)\s*;(\s*//(.+))?"
+consistent!(evalrs_0, r"extern\s+crate\s+([a-z0-9_]+)\s*;(\s*//(.+))?");
+
+// evalrs-0.0.10: r"(?m)^# "
+consistent!(evalrs_1, r"(?m)^# ");
+
+// evalrs-0.0.10: r"(?m)^\s*fn +main *\( *\)"
+consistent!(evalrs_2, r"(?m)^\s*fn +main *\( *\)");
+
+// evalrs-0.0.10: r"(extern\s+crate\s+[a-z0-9_]+\s*;)"
+consistent!(evalrs_3, r"(extern\s+crate\s+[a-z0-9_]+\s*;)");
+
+// gate_build-0.5.0: "(.*)_t([0-9]+)"
+consistent!(gate_build_0, "(.*)_t([0-9]+)");
+
+// rake-0.1.1: r"[^\P{P}-]|\s+-\s+"
+consistent!(rake_0, r"[^\P{P}-]|\s+-\s+");
+
+// rafy-0.2.1: r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*"
+consistent!(rafy_0, r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*");
+
+// raven-0.2.1: r"^(?P<protocol>.*?)://(?P<public_key>.*?):(?P<secret_key>.*?)@(?P<host>.*?)/(?P<path>.*/)?(?P<project_id>.*)$"
+consistent!(raven_0, r"^(?P<protocol>.*?)://(?P<public_key>.*?):(?P<secret_key>.*?)@(?P<host>.*?)/(?P<path>.*/)?(?P<project_id>.*)$");
+
+// rargs-0.2.0: r"\{[[:space:]]*[^{}]*[[:space:]]*\}"
+consistent!(rargs_0, r"\{[[:space:]]*[^{}]*[[:space:]]*\}");
+
+// rargs-0.2.0: r"^\{[[:space:]]*(?P<name>[[:word:]]*)[[:space:]]*\}$"
+consistent!(rargs_1, r"^\{[[:space:]]*(?P<name>[[:word:]]*)[[:space:]]*\}$");
+
+// rargs-0.2.0: r"^\{[[:space:]]*(?P<num>-?\d+)[[:space:]]*\}$"
+consistent!(rargs_2, r"^\{[[:space:]]*(?P<num>-?\d+)[[:space:]]*\}$");
+
+// rargs-0.2.0: r"^\{(?P<left>-?\d*)?\.\.(?P<right>-?\d*)?(?::(?P<sep>.*))?\}$"
+consistent!(
+    rargs_3,
+    r"^\{(?P<left>-?\d*)?\.\.(?P<right>-?\d*)?(?::(?P<sep>.*))?\}$"
+);
+
+// rargs-0.2.0: r"(.*?)[[:space:]]+|(.*?)$"
+consistent!(rargs_4, r"(.*?)[[:space:]]+|(.*?)$");
+
+// indradb-lib-0.15.0: r"[a-zA-Z0-9]{8}"
+consistent!(indradb_lib_0, r"[a-zA-Z0-9]{8}");
+
+// fungi-lang-0.1.50: r"::"
+consistent!(fungi_lang_0, r"::");
+
+// nickel-0.10.1: "/hello/(?P<name>[a-zA-Z]+)"
+consistent!(nickel_0, "/hello/(?P<name>[a-zA-Z]+)");
+
+// nickel-0.10.1: "/hello/(?P<name>[a-zA-Z]+)"
+consistent!(nickel_1, "/hello/(?P<name>[a-zA-Z]+)");
+
+// pact_verifier-0.4.0: r"\{(\w+)\}"
+consistent!(pact_verifier_0, r"\{(\w+)\}");
+
+// pact_matching-0.4.1: "application/.*json"
+consistent!(pact_matching_0, "application/.*json");
+
+// pact_matching-0.4.1: "application/json.*"
+consistent!(pact_matching_1, "application/json.*");
+
+// pact_matching-0.4.1: "application/.*xml"
+consistent!(pact_matching_2, "application/.*xml");
+
+// pangu-0.2.0: "([\"'\\(\\[\\{{<\u{201c}])(\\s*)(.+?)(\\s*)([\"'\\)\\]\\}}>\u{201d}])"
+consistent!(
+    pangu_0,
+    "([\"'\\(\\[\\{{<\u{201c}])(\\s*)(.+?)(\\s*)([\"'\\)\\]\\}}>\u{201d}])"
+);
+
+// pangu-0.2.0: "([\\(\\[\\{{<\u{201c}]+)(\\s*)(.+?)(\\s*)([\\)\\]\\}}>\u{201d}]+)"
+consistent!(
+    pangu_1,
+    "([\\(\\[\\{{<\u{201c}]+)(\\s*)(.+?)(\\s*)([\\)\\]\\}}>\u{201d}]+)"
+);
+
+// parser-haskell-0.2.0: r"\{-[\s\S]*?-\}"
+consistent!(parser_haskell_0, r"\{-[\s\S]*?-\}");
+
+// parser-haskell-0.2.0: r"(?m);+\s*$"
+consistent!(parser_haskell_1, r"(?m);+\s*$");
+
+// parser-haskell-0.2.0: r"(?m)^#(if|ifn?def|endif|else|include|elif).*"
+consistent!(parser_haskell_2, r"(?m)^#(if|ifn?def|endif|else|include|elif).*");
+
+// parser-haskell-0.2.0: r"'([^'\\]|\\[A-Z]{1,3}|\\.)'"
+consistent!(parser_haskell_3, r"'([^'\\]|\\[A-Z]{1,3}|\\.)'");
+
+// parser-haskell-0.2.0: r"forall\s+(.*?)\."
+consistent!(parser_haskell_4, r"forall\s+(.*?)\.");
+
+// html2md-0.2.1: "\\s{2,}"
+consistent!(html2md_0, "\\s{2,}");
+
+// html2md-0.2.1: "\\n{2,}"
+consistent!(html2md_1, "\\n{2,}");
+
+// html2md-0.2.1: "(?m)(\\S) $"
+consistent!(html2md_2, "(?m)(\\S) $");
+
+// html2md-0.2.1: "(?m)^[-*] "
+consistent!(html2md_3, "(?m)^[-*] ");
+
+// ovpnfile-0.1.2: r"#.*$"
+consistent!(ovpnfile_0, r"#.*$");
+
+// ovpnfile-0.1.2: r"^<(\S+)>"
+consistent!(ovpnfile_1, r"^<(\S+)>");
+
+// ovpnfile-0.1.2: r"^</(\S+)>"
+consistent!(ovpnfile_2, r"^</(\S+)>");
+
+// screenruster-saver-fractal-0.1.1: r"#([:xdigit:]{2})([:xdigit:]{2})([:xdigit:]{2})"
+consistent!(
+    screenruster_saver_fractal_0,
+    r"#([:xdigit:]{2})([:xdigit:]{2})([:xdigit:]{2})"
+);
+
+// scarlet-0.2.2: r"rgb\((?: *(\d{1,3}),)(?: *(\d{1,3}),)(?: *(\d{1,3}))\)"
+consistent!(
+    scarlet_0,
+    r"rgb\((?: *(\d{1,3}),)(?: *(\d{1,3}),)(?: *(\d{1,3}))\)"
+);
+
+// cpp_to_rust_generator-0.2.0: r"^([\w:]+)<(.+)>$"
+consistent!(cpp_to_rust_generator_0, r"^([\w:]+)<(.+)>$");
+
+// cpp_to_rust_generator-0.2.0: r"^type-parameter-(\d+)-(\d+)$"
+consistent!(cpp_to_rust_generator_1, r"^type-parameter-(\d+)-(\d+)$");
+
+// cpp_to_rust_generator-0.2.0: r"^([\w~]+)<[^<>]+>$"
+consistent!(cpp_to_rust_generator_2, r"^([\w~]+)<[^<>]+>$");
+
+// cpp_to_rust_generator-0.2.0: r"(signals|Q_SIGNALS)\s*:"
+consistent!(cpp_to_rust_generator_3, r"(signals|Q_SIGNALS)\s*:");
+
+// cpp_to_rust_generator-0.2.0: r"(slots|Q_SLOTS)\s*:"
+consistent!(cpp_to_rust_generator_4, r"(slots|Q_SLOTS)\s*:");
+
+// cpp_to_rust_generator-0.2.0: r"(public|protected|private)\s*:"
+consistent!(cpp_to_rust_generator_5, r"(public|protected|private)\s*:");
+
+// cpp_to_rust-0.5.3: r"^([\w:]+)<(.+)>$"
+consistent!(cpp_to_rust_0, r"^([\w:]+)<(.+)>$");
+
+// cpp_to_rust-0.5.3: r"^type-parameter-(\d+)-(\d+)$"
+consistent!(cpp_to_rust_1, r"^type-parameter-(\d+)-(\d+)$");
+
+// cpp_to_rust-0.5.3: r"^([\w~]+)<[^<>]+>$"
+consistent!(cpp_to_rust_2, r"^([\w~]+)<[^<>]+>$");
+
+// cpp_to_rust-0.5.3: r"(signals|Q_SIGNALS)\s*:"
+consistent!(cpp_to_rust_3, r"(signals|Q_SIGNALS)\s*:");
+
+// cpp_to_rust-0.5.3: r"(slots|Q_SLOTS)\s*:"
+consistent!(cpp_to_rust_4, r"(slots|Q_SLOTS)\s*:");
+
+// cpp_to_rust-0.5.3: r"(public|protected|private)\s*:"
+consistent!(cpp_to_rust_5, r"(public|protected|private)\s*:");
+
+// fritzbox_logs-0.2.0: "(\\d{2}\\.\\d{2}\\.\\d{2}) (\\d{2}:\\d{2}:\\d{2}) (.*)"
+consistent!(
+    fritzbox_logs_0,
+    "(\\d{2}\\.\\d{2}\\.\\d{2}) (\\d{2}:\\d{2}:\\d{2}) (.*)"
+);
+
+// fractal-matrix-api-3.29.0: r"mxc://(?P<server>[^/]+)/(?P<media>.+)"
+consistent!(fractal_matrix_api_0, r"mxc://(?P<server>[^/]+)/(?P<media>.+)");
+
+// smtp2go-0.1.4: r"^api-[a-zA-Z0-9]{32}$"
+consistent!(smtp2go_0, r"^api-[a-zA-Z0-9]{32}$");
+
+// pusher-0.3.1: r"^[-a-zA-Z0-9_=@,.;]+$"
+consistent!(pusher_0, r"^[-a-zA-Z0-9_=@,.;]+$");
+
+// pusher-0.3.1: r"\A\d+\.\d+\z"
+consistent!(pusher_1, r"\A\d+\.\d+\z");
+
+// bakervm-0.9.0: r"^\.(.+?) +?(.+)$"
+consistent!(bakervm_0, r"^\.(.+?) +?(.+)$");
+
+// bakervm-0.9.0: r"^\.([^\s]+)$"
+consistent!(bakervm_1, r"^\.([^\s]+)$");
+
+// bakervm-0.9.0: r"^include! +([^\s]+)$"
+consistent!(bakervm_2, r"^include! +([^\s]+)$");
+
+// bakervm-0.9.0: r"^@(\d+)$"
+consistent!(bakervm_3, r"^@(\d+)$");
+
+// bakervm-0.9.0: r"^true|false$"
+consistent!(bakervm_4, r"^true|false$");
+
+// bakervm-0.9.0: r"^(-?\d+)?\.[0-9]+$"
+consistent!(bakervm_5, r"^(-?\d+)?\.[0-9]+$");
+
+// bakervm-0.9.0: r"^(-?\d+)?$"
+consistent!(bakervm_6, r"^(-?\d+)?$");
+
+// bakervm-0.9.0: r"^#([0-9abcdefABCDEF]{6})$"
+consistent!(bakervm_7, r"^#([0-9abcdefABCDEF]{6})$");
+
+// bakervm-0.9.0: r"^'(.)'$"
+consistent!(bakervm_8, r"^'(.)'$");
+
+// bakervm-0.9.0: r"^\$vi\((\d+)\)$"
+consistent!(bakervm_9, r"^\$vi\((\d+)\)$");
+
+// bakervm-0.9.0: r"^\$key\((\d+)\)$"
+consistent!(bakervm_10, r"^\$key\((\d+)\)$");
+
+// banana-0.0.2: "(?P<type>[A-Z^']+) (?P<route>[^']+) HTTP/(?P<http>[^']+)"
+consistent!(
+    banana_0,
+    "(?P<type>[A-Z^']+) (?P<route>[^']+) HTTP/(?P<http>[^']+)"
+);
+
+// serial-key-2.0.0: r"[A-F0-9]{8}"
+consistent!(serial_key_0, r"[A-F0-9]{8}");
+
+// serde-hjson-0.8.1: "[\\\\\"\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]"
+consistent!(serde_hjson_0, "[\\\\\"\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]");
+
+// serde-hjson-0.8.1: "[\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]"
+consistent!(serde_hjson_1, "[\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]");
+
+// serde-hjson-0.8.1: "'''|[\x00-\x09\x0b\x0c\x0e-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]"
+consistent!(serde_hjson_2, "'''|[\x00-\x09\x0b\x0c\x0e-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]");
+
+// serde-odbc-0.1.0: r"/todos/(?P<id>\d+)"
+consistent!(serde_odbc_0, r"/todos/(?P<id>\d+)");
+
+// sentry-0.6.0: r"^(?:_<)?([a-zA-Z0-9_]+?)(?:\.\.|::)"
+consistent!(sentry_0, r"^(?:_<)?([a-zA-Z0-9_]+?)(?:\.\.|::)");
+
+// sentiment-0.1.1: r"[^a-zA-Z0 -]+"
+consistent!(sentiment_0, r"[^a-zA-Z0 -]+");
+
+// sentiment-0.1.1: r" {2,}"
+consistent!(sentiment_1, r" {2,}");
+
+// verilog-0.0.1: r"(?m)//.*"
+consistent!(verilog_0, r"(?m)//.*");
+
+// verex-0.2.2: "(?P<robot>C3PO)"
+consistent!(verex_0, "(?P<robot>C3PO)");
+
+// handlebars-0.32.4: ">|<|\"|&"
+consistent!(handlebars_0, ">|<|\"|&");
+
+// haikunator-0.1.2: r"^\w+-\w+-[0123456789]{4}$"
+consistent!(haikunator_0, r"^\w+-\w+-[0123456789]{4}$");
+
+// haikunator-0.1.2: r"^\w+@\w+@[0123456789]{4}$"
+consistent!(haikunator_1, r"^\w+@\w+@[0123456789]{4}$");
+
+// haikunator-0.1.2: r"^\w+-\w+-[0123456789abcdef]{4}$"
+consistent!(haikunator_2, r"^\w+-\w+-[0123456789abcdef]{4}$");
+
+// haikunator-0.1.2: r"^\w+-\w+-[0123456789忠犬ハチ公]{10}$"
+consistent!(haikunator_3, r"^\w+-\w+-[0123456789忠犬ハチ公]{10}$");
+
+// haikunator-0.1.2: r"^\w+-\w+$"
+consistent!(haikunator_4, r"^\w+-\w+$");
+
+// haikunator-0.1.2: r"^\w+-\w+-[foo]{4}$"
+consistent!(haikunator_5, r"^\w+-\w+-[foo]{4}$");
+
+// haikunator-0.1.2: r"^\w+-\w+-[0123456789忠犬ハチ公]{5}$"
+consistent!(haikunator_6, r"^\w+-\w+-[0123456789忠犬ハチ公]{5}$");
+
+// bobbin-cli-0.8.3: r"(.*)"
+consistent!(bobbin_cli_0, r"(.*)");
+
+// bobbin-cli-0.8.3: r"rustc (.*)"
+consistent!(bobbin_cli_1, r"rustc (.*)");
+
+// bobbin-cli-0.8.3: r"cargo (.*)"
+consistent!(bobbin_cli_2, r"cargo (.*)");
+
+// bobbin-cli-0.8.3: r"xargo (.*)\n"
+consistent!(bobbin_cli_3, r"xargo (.*)\n");
+
+// bobbin-cli-0.8.3: r"Open On-Chip Debugger (.*)"
+consistent!(bobbin_cli_4, r"Open On-Chip Debugger (.*)");
+
+// bobbin-cli-0.8.3: r"arm-none-eabi-gcc \(GNU Tools for ARM Embedded Processors[^\)]*\) (.*)"
+consistent!(
+    bobbin_cli_5,
+    r"arm-none-eabi-gcc \(GNU Tools for ARM Embedded Processors[^\)]*\) (.*)"
+);
+
+// bobbin-cli-0.8.3: r"(?m).*\nBasic Open Source SAM-BA Application \(BOSSA\) Version (.*)\n"
+consistent!(
+    bobbin_cli_6,
+    r"(?m).*\nBasic Open Source SAM-BA Application \(BOSSA\) Version (.*)\n"
+);
+
+// bobbin-cli-0.8.3: r"(?m)SEGGER J-Link Commander (.*)\n"
+consistent!(bobbin_cli_7, r"(?m)SEGGER J-Link Commander (.*)\n");
+
+// bobbin-cli-0.8.3: r"(?m)Teensy Loader, Command Line, Version (.*)\n"
+consistent!(bobbin_cli_8, r"(?m)Teensy Loader, Command Line, Version (.*)\n");
+
+// bobbin-cli-0.8.3: r"dfu-util (.*)\n"
+consistent!(bobbin_cli_9, r"dfu-util (.*)\n");
+
+// borsholder-0.9.1: r"^/static/[\w.]+$"
+consistent!(borsholder_0, r"^/static/[\w.]+$");
+
+// borsholder-0.9.1: r"^/timeline/([0-9]+)$"
+consistent!(borsholder_1, r"^/timeline/([0-9]+)$");
+
+// fblog-1.0.1: "\u{001B}\\[[\\d;]*[^\\d;]"
+consistent!(fblog_0, "\u{001B}\\[[\\d;]*[^\\d;]");
+
+// fblog-1.0.1: "\u{001B}\\[[\\d;]*[^\\d;]"
+consistent!(fblog_1, "\u{001B}\\[[\\d;]*[^\\d;]");
+
+// toml-query-0.6.0: r"^\[\d+\]$"
+consistent!(toml_query_0, r"^\[\d+\]$");
+
+// todo-txt-1.1.0: r" (?P<key>[^\s]+):(?P<value>[^\s^/]+)"
+consistent!(todo_txt_0, r" (?P<key>[^\s]+):(?P<value>[^\s^/]+)");
+
+// findr-0.1.5: r"\band\b"
+consistent!(findr_0, r"\band\b");
+
+// findr-0.1.5: r"\bor\b"
+consistent!(findr_1, r"\bor\b");
+
+// findr-0.1.5: r"\bnot\b"
+consistent!(findr_2, r"\bnot\b");
+
+// file-sniffer-3.0.1: r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
+consistent!(file_sniffer_0, r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
+
+// file-sniffer-3.0.1: r".*?\.(stats|conf|h|cache.*|dat|pc|info)$"
+consistent!(file_sniffer_1, r".*?\.(stats|conf|h|cache.*|dat|pc|info)$");
+
+// file-sniffer-3.0.1: r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
+consistent!(file_sniffer_2, r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
+
+// file-sniffer-3.0.1: r".*?\.(stats|conf|h|cache.*)$"
+consistent!(file_sniffer_3, r".*?\.(stats|conf|h|cache.*)$");
+
+// file-sniffer-3.0.1: r"(\.git|\.pijul|_darcs|\.hg)$"
+consistent!(file_sniffer_4, r"(\.git|\.pijul|_darcs|\.hg)$");
+
+// file_logger-0.1.0: "test"
+consistent!(file_logger_0, "test");
+
+// file_scanner-0.2.0: r"foo"
+consistent!(file_scanner_0, r"foo");
+
+// file_scanner-0.2.0: r"a+b"
+consistent!(file_scanner_1, r"a+b");
+
+// file_scanner-0.2.0: r"a[ab]*b"
+consistent!(file_scanner_2, r"a[ab]*b");
+
+// file_scanner-0.2.0: r"\s+"
+consistent!(file_scanner_3, r"\s+");
+
+// file_scanner-0.2.0: r"\s+"
+consistent!(file_scanner_4, r"\s+");
+
+// cellsplit-0.2.1: r"^\s*([^\s]+) %cellsplit<\d+>$"
+consistent!(cellsplit_0, r"^\s*([^\s]+) %cellsplit<\d+>$");
+
+// cellsplit-0.2.1: r"^\s*([^\s]+) %cellsplit<\d+>$"
+consistent!(cellsplit_1, r"^\s*([^\s]+) %cellsplit<\d+>$");
+
+// aterm-0.20.0: r"^[+\-]?[0-9]+"
+consistent!(aterm_0, r"^[+\-]?[0-9]+");
+
+// aterm-0.20.0: r"^[+\-]?[0-9]+\.[0-9]*([eE][+\-]?[0-9]+)?"
+consistent!(aterm_1, r"^[+\-]?[0-9]+\.[0-9]*([eE][+\-]?[0-9]+)?");
+
+// atarashii_imap-0.3.0: r"^[*] OK"
+consistent!(atarashii_imap_0, r"^[*] OK");
+
+// atarashii_imap-0.3.0: r"FLAGS\s\((.+)\)"
+consistent!(atarashii_imap_1, r"FLAGS\s\((.+)\)");
+
+// atarashii_imap-0.3.0: r"\[PERMANENTFLAGS\s\((.+)\)\]"
+consistent!(atarashii_imap_2, r"\[PERMANENTFLAGS\s\((.+)\)\]");
+
+// atarashii_imap-0.3.0: r"\[UIDVALIDITY\s(\d+)\]"
+consistent!(atarashii_imap_3, r"\[UIDVALIDITY\s(\d+)\]");
+
+// atarashii_imap-0.3.0: r"(\d+)\sEXISTS"
+consistent!(atarashii_imap_4, r"(\d+)\sEXISTS");
+
+// atarashii_imap-0.3.0: r"(\d+)\sRECENT"
+consistent!(atarashii_imap_5, r"(\d+)\sRECENT");
+
+// atarashii_imap-0.3.0: r"\[UNSEEN\s(\d+)\]"
+consistent!(atarashii_imap_6, r"\[UNSEEN\s(\d+)\]");
+
+// atarashii_imap-0.3.0: r"\[UIDNEXT\s(\d+)\]"
+consistent!(atarashii_imap_7, r"\[UIDNEXT\s(\d+)\]");
+
+// editorconfig-1.0.0: r"\\(\{|\})"
+consistent!(editorconfig_0, r"\\(\{|\})");
+
+// editorconfig-1.0.0: r"(^|[^\\])\\\|"
+consistent!(editorconfig_1, r"(^|[^\\])\\\|");
+
+// editorconfig-1.0.0: r"\[([^\]]*)$"
+consistent!(editorconfig_2, r"\[([^\]]*)$");
+
+// editorconfig-1.0.0: r"\[(.*/.*)\]"
+consistent!(editorconfig_3, r"\[(.*/.*)\]");
+
+// editorconfig-1.0.0: r"\{(-?\d+\\\.\\\.-?\d+)\}"
+consistent!(editorconfig_4, r"\{(-?\d+\\\.\\\.-?\d+)\}");
+
+// editorconfig-1.0.0: r"\{([^,]+)\}"
+consistent!(editorconfig_5, r"\{([^,]+)\}");
+
+// editorconfig-1.0.0: r"\{(([^\}].*)?(,|\|)(.*[^\\])?)\}"
+consistent!(editorconfig_6, r"\{(([^\}].*)?(,|\|)(.*[^\\])?)\}");
+
+// editorconfig-1.0.0: r"^/"
+consistent!(editorconfig_7, r"^/");
+
+// editorconfig-1.0.0: r"(^|[^\\])(\{|\})"
+consistent!(editorconfig_8, r"(^|[^\\])(\{|\})");
+
+// edmunge-1.0.0: "^#!.*\n"
+consistent!(edmunge_0, "^#!.*\n");
+
+// unicode_names2_macros-0.2.0: r"\\N\{(.*?)(?:\}|$)"
+consistent!(unicode_names2_macros_0, r"\\N\{(.*?)(?:\}|$)");
+
+// unidiff-0.2.1: r"^--- (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?"
+consistent!(
+    unidiff_0,
+    r"^--- (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?"
+);
+
+// unidiff-0.2.1: r"^\+\+\+ (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?"
+consistent!(
+    unidiff_1,
+    r"^\+\+\+ (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?"
+);
+
+// unidiff-0.2.1: r"^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@[ ]?(.*)"
+consistent!(unidiff_2, r"^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@[ ]?(.*)");
+
+// unidiff-0.2.1: r"^(?P<line_type>[- \n\+\\]?)(?P<value>.*)"
+consistent!(unidiff_3, r"^(?P<line_type>[- \n\+\\]?)(?P<value>.*)");
+
+// slippy-map-tiles-0.13.1: "/?(?P<zoom>[0-9]?[0-9])/(?P<x>[0-9]{1,10})/(?P<y>[0-9]{1,10})(\\.[a-zA-Z]{3,4})?$"
+consistent!(slippy_map_tiles_0, "/?(?P<zoom>[0-9]?[0-9])/(?P<x>[0-9]{1,10})/(?P<y>[0-9]{1,10})(\\.[a-zA-Z]{3,4})?$");
+
+// slippy-map-tiles-0.13.1: r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$"
+consistent!(slippy_map_tiles_1, r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$");
+
+// slippy-map-tiles-0.13.1: r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$"
+consistent!(slippy_map_tiles_2, r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$");
+
+// sonos-0.1.2: r"^https?://(.+?):1400/xml"
+consistent!(sonos_0, r"^https?://(.+?):1400/xml");
+
+// validator_derive-0.7.0: r"^[a-z]{2}$"
+consistent!(validator_derive_0, r"^[a-z]{2}$");
+
+// validator_derive-0.7.0: r"[a-z]{2}"
+consistent!(validator_derive_1, r"[a-z]{2}");
+
+// validator_derive-0.7.0: r"[a-z]{2}"
+consistent!(validator_derive_2, r"[a-z]{2}");
+
+// nginx-config-0.8.0: r"one of \d+ options"
+consistent!(nginx_config_0, r"one of \d+ options");
+
+// waltz-0.4.0: r"[\s,]"
+consistent!(waltz_0, r"[\s,]");
+
+// warheadhateus-0.2.1: r"^aws_access_key_id = (.*)"
+consistent!(warheadhateus_0, r"^aws_access_key_id = (.*)");
+
+// warheadhateus-0.2.1: r"^aws_secret_access_key = (.*)"
+consistent!(warheadhateus_1, r"^aws_secret_access_key = (.*)");
+
+// warheadhateus-0.2.1: r"^aws_access_key_id = (.*)"
+consistent!(warheadhateus_2, r"^aws_access_key_id = (.*)");
+
+// warheadhateus-0.2.1: r"^aws_secret_access_key = (.*)"
+consistent!(warheadhateus_3, r"^aws_secret_access_key = (.*)");
+
+// jieba-rs-0.2.2: r"([\u{4E00}-\u{9FD5}a-zA-Z0-9+#&\._%]+)"
+consistent!(jieba_rs_0, r"([\u{4E00}-\u{9FD5}a-zA-Z0-9+#&\._%]+)");
+
+// jieba-rs-0.2.2: r"(\r\n|\s)"
+consistent!(jieba_rs_1, r"(\r\n|\s)");
+
+// jieba-rs-0.2.2: "([\u{4E00}-\u{9FD5}]+)"
+consistent!(jieba_rs_2, "([\u{4E00}-\u{9FD5}]+)");
+
+// jieba-rs-0.2.2: r"[^a-zA-Z0-9+#\n]"
+consistent!(jieba_rs_3, r"[^a-zA-Z0-9+#\n]");
+
+// jieba-rs-0.2.2: r"([\u{4E00}-\u{9FD5}]+)"
+consistent!(jieba_rs_4, r"([\u{4E00}-\u{9FD5}]+)");
+
+// jieba-rs-0.2.2: r"([a-zA-Z0-9]+(?:.\d+)?%?)"
+consistent!(jieba_rs_5, r"([a-zA-Z0-9]+(?:.\d+)?%?)");
+
+// lalrpop-0.15.2: r"Span\([0-9 ,]*\)"
+consistent!(lalrpop_0, r"Span\([0-9 ,]*\)");
+
+// lalrpop-snap-0.15.2: r"Span\([0-9 ,]*\)"
+consistent!(lalrpop_snap_0, r"Span\([0-9 ,]*\)");
+
+// nlp-tokenize-0.1.0: r"[\S]+"
+consistent!(nlp_tokenize_0, r"[\S]+");
+
+// kbgpg-0.1.2: "[[:xdigit:]][70]"
+consistent!(kbgpg_0, "[[:xdigit:]][70]");
+
+// cdbd-0.1.1: r"^((?P<address>.*):)?(?P<port>\d+)$"
+consistent!(cdbd_0, r"^((?P<address>.*):)?(?P<port>\d+)$");
+
+// mbutiles-0.1.1: r"[\w\s=+-/]+\((\{(.|\n)*\})\);?"
+consistent!(mbutiles_0, r"[\w\s=+-/]+\((\{(.|\n)*\})\);?");
+
+// extrahop-0.2.5: r"^-\d+(?:ms|s|m|h|d|w|y)?$"
+consistent!(extrahop_0, r"^-\d+(?:ms|s|m|h|d|w|y)?$");
+
+// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$"
+consistent!(pippin_0, "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$");
+
+// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$"
+consistent!(
+    pippin_1,
+    "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$"
+);
+
+// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$"
+consistent!(pippin_2, "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$");
+
+// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$"
+consistent!(
+    pippin_3,
+    "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$"
+);
+
+// pippin-0.1.0: "^.*pn(0|[1-9][0-9]*)(-ss(0|[1-9][0-9]*)(\\.pip|-cl(0|[1-9][0-9]*)\\.piplog))?$"
+consistent!(pippin_4, "^.*pn(0|[1-9][0-9]*)(-ss(0|[1-9][0-9]*)(\\.pip|-cl(0|[1-9][0-9]*)\\.piplog))?$");
+
+// pippin-0.1.0: "^(.*)-ss(?:0|[1-9][0-9]*)(?:\\.pip|-cl(?:0|[1-9][0-9]*)\\.piplog)$"
+consistent!(
+    pippin_5,
+    "^(.*)-ss(?:0|[1-9][0-9]*)(?:\\.pip|-cl(?:0|[1-9][0-9]*)\\.piplog)$"
+);
+
+// pinyin-0.3.0: r"(?i)[āáǎàēéěèōóǒòīíǐìūúǔùüǘǚǜńň]"
+consistent!(
+    pinyin_0,
+    r"(?i)[āáǎàēéěèōóǒòīíǐìūúǔùüǘǚǜńň]"
+);
+
+// pinyin-0.3.0: r"([aeoiuvnm])([0-4])$"
+consistent!(pinyin_1, r"([aeoiuvnm])([0-4])$");
+
+// duration-parser-0.2.0: r"(?P<value>\d+)(?P<units>[a-z])"
+consistent!(duration_parser_0, r"(?P<value>\d+)(?P<units>[a-z])");
+
+// dutree-0.2.7: r"^\d+\D?$"
+consistent!(dutree_0, r"^\d+\D?$");
+
+// djangohashers-0.3.0: r"^[A-Za-z0-9]*$"
+consistent!(djangohashers_0, r"^[A-Za-z0-9]*$");
+
+// rtag-0.3.5: r"^[A-Z][A-Z0-9]{2,}$"
+consistent!(rtag_0, r"^[A-Z][A-Z0-9]{2,}$");
+
+// rtag-0.3.5: r"^http://www\.emusic\.com"
+consistent!(rtag_1, r"^http://www\.emusic\.com");
+
+// rtag-0.3.5: r"^[A-Z][A-Z0-9]{2,}"
+consistent!(rtag_2, r"^[A-Z][A-Z0-9]{2,}");
+
+// rtag-0.3.5: r"(^[\x{0}|\x{feff}|\x{fffe}]*|[\x{0}|\x{feff}|\x{fffe}]*$)"
+consistent!(
+    rtag_3,
+    r"(^[\x{0}|\x{feff}|\x{fffe}]*|[\x{0}|\x{feff}|\x{fffe}]*$)"
+);
+
+// rtow-0.1.0: r"(\d+)[xX](\d+)"
+consistent!(rtow_0, r"(\d+)[xX](\d+)");
+
+// pleingres-sql-plugin-0.1.0: r"\$([a-zA-Z0-9_]+)"
+consistent!(pleingres_sql_plugin_0, r"\$([a-zA-Z0-9_]+)");
+
+// dono-2.0.0: "[\\n]+"
+consistent!(dono_0, "[\\n]+");
+
+// dono-2.0.0: "(?m)^\\n"
+consistent!(dono_1, "(?m)^\\n");
+
+// dono-2.0.0: "(?m)^\\n"
+consistent!(dono_2, "(?m)^\\n");
+
+// ssb-common-0.3.0: r"^[0-9A-Za-z\+/]{43}=\.ed25519$"
+consistent!(ssb_common_0, r"^[0-9A-Za-z\+/]{43}=\.ed25519$");
+
+// ssb-common-0.3.0: r"^[0-9A-Za-z\+/]{86}==\.ed25519$"
+consistent!(ssb_common_1, r"^[0-9A-Za-z\+/]{86}==\.ed25519$");
+
+// ssb-common-0.3.0: r"^[0-9A-Za-z\+/]{43}=\.sha256$"
+consistent!(ssb_common_2, r"^[0-9A-Za-z\+/]{43}=\.sha256$");
+
+// mozversion-0.1.3: r"^(?P<major>\d+)\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?(?:(?P<pre0>[a-z]+)(?P<pre1>\d*))?$"
+consistent!(mozversion_0, r"^(?P<major>\d+)\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?(?:(?P<pre0>[a-z]+)(?P<pre1>\d*))?$");
+
+// monger-0.5.6: r"^(\d+)\.(\d+)$"
+consistent!(monger_0, r"^(\d+)\.(\d+)$");
+
+// mongo_rub-0.0.2: r"^[rv]2\.6"
+consistent!(mongo_rub_0, r"^[rv]2\.6");
+
+// flow-0.3.5: "body value"
+consistent!(flow_0, "body value");
+
+// flow-0.3.5: "start marker"
+consistent!(flow_1, "start marker");
+
+// flow-0.3.5: "end marker"
+consistent!(flow_2, "end marker");
+
+// flow-0.3.5: "body value"
+consistent!(flow_3, "body value");
+
+// vobsub-0.2.3: "^([A-Za-z/ ]+): (.*)"
+consistent!(vobsub_0, "^([A-Za-z/ ]+): (.*)");
+
+// voidmap-1.1.2: r"#([^\s=]+)*"
+consistent!(voidmap_0, r"#([^\s=]+)*");
+
+// voidmap-1.1.2: r"#(\S+)*"
+consistent!(voidmap_1, r"#(\S+)*");
+
+// voidmap-1.1.2: r"#prio=(\d+)"
+consistent!(voidmap_2, r"#prio=(\d+)");
+
+// voidmap-1.1.2: r"\[(\S+)\]"
+consistent!(voidmap_3, r"\[(\S+)\]");
+
+// voidmap-1.1.2: r"#limit=(\d+)"
+consistent!(voidmap_4, r"#limit=(\d+)");
+
+// voidmap-1.1.2: r"#tagged=(\S+)"
+consistent!(voidmap_5, r"#tagged=(\S+)");
+
+// voidmap-1.1.2: r"#rev\b"
+consistent!(voidmap_6, r"#rev\b");
+
+// voidmap-1.1.2: r"#done\b"
+consistent!(voidmap_7, r"#done\b");
+
+// voidmap-1.1.2: r"#open\b"
+consistent!(voidmap_8, r"#open\b");
+
+// voidmap-1.1.2: r"#since=(\S+)"
+consistent!(voidmap_9, r"#since=(\S+)");
+
+// voidmap-1.1.2: r"#until=(\S+)"
+consistent!(voidmap_10, r"#until=(\S+)");
+
+// voidmap-1.1.2: r"#plot=(\S+)"
+consistent!(voidmap_11, r"#plot=(\S+)");
+
+// voidmap-1.1.2: r"#n=(\d+)"
+consistent!(voidmap_12, r"#n=(\d+)");
+
+// voidmap-1.1.2: r"(\S+)"
+consistent!(voidmap_13, r"(\S+)");
+
+// voidmap-1.1.2: r"(?P<y>\d+)y"
+consistent!(voidmap_14, r"(?P<y>\d+)y");
+
+// voidmap-1.1.2: r"(?P<m>\d+)m"
+consistent!(voidmap_15, r"(?P<m>\d+)m");
+
+// voidmap-1.1.2: r"(?P<w>\d+)w"
+consistent!(voidmap_16, r"(?P<w>\d+)w");
+
+// voidmap-1.1.2: r"(?P<d>\d+)d"
+consistent!(voidmap_17, r"(?P<d>\d+)d");
+
+// voidmap-1.1.2: r"(?P<h>\d+)h"
+consistent!(voidmap_18, r"(?P<h>\d+)h");
+
+// voidmap-1.1.2: r"C-(.)"
+consistent!(voidmap_19, r"C-(.)");
+
+// qt_generator-0.2.0: r"^\.\./qt[^/]+/"
+consistent!(qt_generator_0, r"^\.\./qt[^/]+/");
+
+// qt_generator-0.2.0: "(href|src)=\"([^\"]*)\""
+consistent!(qt_generator_1, "(href|src)=\"([^\"]*)\"");
+
+// kryptos-0.6.1: r"[01]{5}"
+consistent!(kryptos_0, r"[01]{5}");
+
+// cifar_10_loader-0.2.0: "data_batch_[1-5].bin"
+consistent!(cifar_10_loader_0, "data_batch_[1-5].bin");
+
+// cifar_10_loader-0.2.0: "test_batch.bin"
+consistent!(cifar_10_loader_1, "test_batch.bin");
+
+// circadian-0.6.0: r"^\d+.\d+s$"
+consistent!(circadian_0, r"^\d+.\d+s$");
+
+// circadian-0.6.0: r"^\d+:\d+$"
+consistent!(circadian_1, r"^\d+:\d+$");
+
+// circadian-0.6.0: r"^\d+:\d+m$"
+consistent!(circadian_2, r"^\d+:\d+m$");
+
+// cicada-0.8.1: r"!!"
+consistent!(cicada_0, r"!!");
+
+// cicada-0.8.1: r"^([^`]*)`([^`]+)`(.*)$"
+consistent!(cicada_1, r"^([^`]*)`([^`]+)`(.*)$");
+
+// cicada-0.8.1: r"\*+"
+consistent!(cicada_2, r"\*+");
+
+// cicada-0.8.1: r"([^\$]*)\$\{?([A-Za-z0-9\?\$_]+)\}?(.*)"
+consistent!(cicada_3, r"([^\$]*)\$\{?([A-Za-z0-9\?\$_]+)\}?(.*)");
+
+// cicada-0.8.1: r"^ *alias +([a-zA-Z0-9_\.-]+)=(.*)$"
+consistent!(cicada_4, r"^ *alias +([a-zA-Z0-9_\.-]+)=(.*)$");
+
+// vterm-sys-0.1.0: r"hi"
+consistent!(vterm_sys_0, r"hi");
+
+// skim-0.5.0: r".*?\t"
+consistent!(skim_0, r".*?\t");
+
+// skim-0.5.0: r".*?[\t ]"
+consistent!(skim_1, r".*?[\t ]");
+
+// skim-0.5.0: r"(\{-?[0-9.,q]*?})"
+consistent!(skim_2, r"(\{-?[0-9.,q]*?})");
+
+// skim-0.5.0: r"[ \t\n]+"
+consistent!(skim_3, r"[ \t\n]+");
+
+// skim-0.5.0: r"[ \t\n]+"
+consistent!(skim_4, r"[ \t\n]+");
+
+// skim-0.5.0: r"([^ |]+( +\| +[^ |]*)+)|( +)"
+consistent!(skim_5, r"([^ |]+( +\| +[^ |]*)+)|( +)");
+
+// skim-0.5.0: r" +\| +"
+consistent!(skim_6, r" +\| +");
+
+// skim-0.5.0: r"^(?P<left>-?\d+)?(?P<sep>\.\.)?(?P<right>-?\d+)?$"
+consistent!(skim_7, r"^(?P<left>-?\d+)?(?P<sep>\.\.)?(?P<right>-?\d+)?$");
+
+// skim-0.5.0: ","
+consistent!(skim_8, ",");
+
+// skim-0.5.0: ".*?,"
+consistent!(skim_9, ".*?,");
+
+// skim-0.5.0: ".*?,"
+consistent!(skim_10, ".*?,");
+
+// skim-0.5.0: ","
+consistent!(skim_11, ",");
+
+// skim-0.5.0: r"\x1B\[(?:([0-9]+;[0-9]+[Hf])|([0-9]+[ABCD])|(s|u|2J|K)|([0-9;]*m)|(=[0-9]+[hI]))"
+consistent!(skim_12, r"\x1B\[(?:([0-9]+;[0-9]+[Hf])|([0-9]+[ABCD])|(s|u|2J|K)|([0-9;]*m)|(=[0-9]+[hI]))");
+
+// egg-mode-text-1.14.7: r"[-_./]\z"
+consistent!(egg_mode_text_0, r"[-_./]\z");
+
+// java-properties-1.1.1: "^[ \t\r\n\x0c]*[#!]"
+consistent!(java_properties_0, "^[ \t\r\n\x0c]*[#!]");
+
+// java-properties-1.1.1: r"^[ \t\x0c]*[#!][^\r\n]*$"
+consistent!(java_properties_1, r"^[ \t\x0c]*[#!][^\r\n]*$");
+
+// java-properties-1.1.1: r"^([ \t\x0c]*[:=][ \t\x0c]*|[ \t\x0c]+)$"
+consistent!(java_properties_2, r"^([ \t\x0c]*[:=][ \t\x0c]*|[ \t\x0c]+)$");
+
+// ipaddress-0.1.2: r":.+\."
+consistent!(ipaddress_0, r":.+\.");
+
+// ipaddress-0.1.2: r"\."
+consistent!(ipaddress_1, r"\.");
+
+// ipaddress-0.1.2: r":"
+consistent!(ipaddress_2, r":");
+
+// iptables-0.2.2: r"v(\d+)\.(\d+)\.(\d+)"
+consistent!(iptables_0, r"v(\d+)\.(\d+)\.(\d+)");
+
+// rsure-0.8.1: r"^([^-]+)-(.*)\.dat\.gz$"
+consistent!(rsure_0, r"^([^-]+)-(.*)\.dat\.gz$");
+
+// rs-jsonpath-0.1.0: "^(.*?)(<=|<|==|>=|>)(.*?)$"
+consistent!(rs_jsonpath_0, "^(.*?)(<=|<|==|>=|>)(.*?)$");
+
+// oatie-0.3.0: r"(\n|^)(\w+):([\n\w\W]+?)(\n(?:\w)|(\n\]))"
+consistent!(oatie_0, r"(\n|^)(\w+):([\n\w\W]+?)(\n(?:\w)|(\n\]))");
+
+// weld-0.2.0: "#.*$"
+consistent!(weld_0, "#.*$");
+
+// weld-0.2.0: r"^[A-Za-z$_][A-Za-z0-9$_]*$"
+consistent!(weld_1, r"^[A-Za-z$_][A-Za-z0-9$_]*$");
+
+// weld-0.2.0: r"^[0-9]+[cC]$"
+consistent!(weld_2, r"^[0-9]+[cC]$");
+
+// weld-0.2.0: r"^0b[0-1]+[cC]$"
+consistent!(weld_3, r"^0b[0-1]+[cC]$");
+
+// weld-0.2.0: r"^0x[0-9a-fA-F]+[cC]$"
+consistent!(weld_4, r"^0x[0-9a-fA-F]+[cC]$");
+
+// weld-0.2.0: r"^[0-9]+$"
+consistent!(weld_5, r"^[0-9]+$");
+
+// weld-0.2.0: r"^0b[0-1]+$"
+consistent!(weld_6, r"^0b[0-1]+$");
+
+// weld-0.2.0: r"^0x[0-9a-fA-F]+$"
+consistent!(weld_7, r"^0x[0-9a-fA-F]+$");
+
+// weld-0.2.0: r"^[0-9]+[lL]$"
+consistent!(weld_8, r"^[0-9]+[lL]$");
+
+// weld-0.2.0: r"^0b[0-1]+[lL]$"
+consistent!(weld_9, r"^0b[0-1]+[lL]$");
+
+// weld-0.2.0: r"^0x[0-9a-fA-F]+[lL]$"
+consistent!(weld_10, r"^0x[0-9a-fA-F]+[lL]$");
+
+// webgl_generator-0.1.0: "([(, ])enum\\b"
+consistent!(webgl_generator_0, "([(, ])enum\\b");
+
+// webgl_generator-0.1.0: "\\bAcquireResourcesCallback\\b"
+consistent!(webgl_generator_1, "\\bAcquireResourcesCallback\\b");
+
+// weave-0.2.0: r"^(\d+)(,(\d+))?([acd]).*$"
+consistent!(weave_0, r"^(\d+)(,(\d+))?([acd]).*$");
+
+// wemo-0.0.12: r"<BinaryState>(\d)(\|-?\d+)*</BinaryState>"
+consistent!(wemo_0, r"<BinaryState>(\d)(\|-?\d+)*</BinaryState>");
+
+// webscale-0.9.4: r"(http[s]?://[^\s]+)"
+consistent!(webscale_0, r"(http[s]?://[^\s]+)");
+
+// svgrep-1.1.0: r"^\d+.*$"
+consistent!(svgrep_0, r"^\d+.*$");
+
+// ignore-0.4.2: r"^[\pL\pN]+$"
+consistent!(ignore_0, r"^[\pL\pN]+$");
+
+// ommui_string_patterns-0.1.2: r"^([A-Za-z][0-9A-Za-z_]*)?$"
+consistent!(ommui_string_patterns_0, r"^([A-Za-z][0-9A-Za-z_]*)?$");
+
+// ommui_string_patterns-0.1.2: r"^(\S+(?:.*\S)?)?$"
+consistent!(ommui_string_patterns_1, r"^(\S+(?:.*\S)?)?$");
+
+// opcua-types-0.3.0: "^(?P<min>[0-9]{1,10})(:(?P<max>[0-9]{1,10}))?$"
+consistent!(opcua_types_0, "^(?P<min>[0-9]{1,10})(:(?P<max>[0-9]{1,10}))?$");
+
+// opcua-types-0.3.0: r"^(ns=(?P<ns>[0-9]+);)?(?P<t>[isgb])=(?P<v>.+)$"
+consistent!(opcua_types_1, r"^(ns=(?P<ns>[0-9]+);)?(?P<t>[isgb])=(?P<v>.+)$");
+
+// open_read_later-1.1.1: r"^(.+?)\s*:\s*(.+)$"
+consistent!(open_read_later_0, r"^(.+?)\s*:\s*(.+)$");
+
+// youtube-downloader-0.1.0: r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*"
+consistent!(youtube_downloader_0, r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*");
+
+// yobot-0.1.1: "."
+consistent!(yobot_0, ".");
+
+// yobot-0.1.1: r"."
+consistent!(yobot_1, r".");
+
+// yobot-0.1.1: r".+"
+consistent!(yobot_2, r".+");
+
+// yobot-0.1.1: r"."
+consistent!(yobot_3, r".");
+
+// ubiquity-0.1.5: r"foo"
+consistent!(ubiquity_0, r"foo");
+
+// ubiquity-0.1.5: r"/target/"
+consistent!(ubiquity_1, r"/target/");
+
+// ubiquity-0.1.5: r".DS_Store"
+consistent!(ubiquity_2, r".DS_Store");
+
+// qasm-1.0.0: r"//.*"
+consistent!(qasm_0, r"//.*");
+
+// drill-0.3.5: r"\{\{ *([a-z\._]+) *\}\}"
+consistent!(drill_0, r"\{\{ *([a-z\._]+) *\}\}");
+
+// queryst-2.0.0: r"^([^\]\[]+)"
+consistent!(queryst_0, r"^([^\]\[]+)");
+
+// queryst-2.0.0: r"(\[[^\]\[]*\])"
+consistent!(queryst_1, r"(\[[^\]\[]*\])");
+
+// qui-vive-0.1.0: r"^/(\w+)$"
+consistent!(qui_vive_0, r"^/(\w+)$");
+
+// qui-vive-0.1.0: r"^/key$"
+consistent!(qui_vive_1, r"^/key$");
+
+// qui-vive-0.1.0: r"^/key/(\w+)$"
+consistent!(qui_vive_2, r"^/key/(\w+)$");
+
+// qui-vive-0.1.0: r"^/url$"
+consistent!(qui_vive_3, r"^/url$");
+
+// qui-vive-0.1.0: r"^/url/(\w+)$"
+consistent!(qui_vive_4, r"^/url/(\w+)$");
+
+// qui-vive-0.1.0: r"^/inv$"
+consistent!(qui_vive_5, r"^/inv$");
+
+// qui-vive-0.1.0: r"^/inv/(\w+)$"
+consistent!(qui_vive_6, r"^/inv/(\w+)$");
+
+// subdiff-0.1.0: r"\b"
+// consistent!(subdiff_0, r"\b");
+
+// substudy-0.4.5: r"^(\d+)/(\d+)$"
+consistent!(substudy_0, r"^(\d+)/(\d+)$");
+
+// substudy-0.4.5: r"\s+"
+consistent!(substudy_1, r"\s+");
+
+// substudy-0.4.5: r"<[a-z/][^>]*>"
+consistent!(substudy_2, r"<[a-z/][^>]*>");
+
+// substudy-0.4.5: r"(\([^)]*\)|♪[^♪]*♪|[A-Z]{2,} ?:)"
+consistent!(substudy_3, r"(\([^)]*\)|♪[^♪]*♪|[A-Z]{2,} ?:)");
+
+// substudy-0.4.5: r"\s+"
+consistent!(substudy_4, r"\s+");
+
+// isbnid-0.1.3: r"^(\d(-| )?){9}(x|X|\d|(\d(-| )?){3}\d)$"
+consistent!(isbnid_0, r"^(\d(-| )?){9}(x|X|\d|(\d(-| )?){3}\d)$");
+
+// isbnid-0.1.3: r"[^0-9X]"
+consistent!(isbnid_1, r"[^0-9X]");
+
+// ispc-0.3.5: r"Intel\(r\) SPMD Program Compiler \(ispc\), (\d+\.\d+\.\d+)"
+consistent!(
+    ispc_0,
+    r"Intel\(r\) SPMD Program Compiler \(ispc\), (\d+\.\d+\.\d+)"
+);
diff --git a/vendor/regex-1.4.6/tests/crazy.rs b/vendor/regex-1.4.6/tests/crazy.rs
new file mode 100644 (file)
index 0000000..293ac1a
--- /dev/null
@@ -0,0 +1,459 @@
+mat!(ascii_literal, r"a", "a", Some((0, 1)));
+
+// Some crazy expressions from regular-expressions.info.
+mat!(
+    match_ranges,
+    r"(?-u)\b(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b",
+    "num: 255",
+    Some((5, 8))
+);
+mat!(
+    match_ranges_not,
+    r"(?-u)\b(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b",
+    "num: 256",
+    None
+);
+mat!(match_float1, r"[-+]?[0-9]*\.?[0-9]+", "0.1", Some((0, 3)));
+mat!(match_float2, r"[-+]?[0-9]*\.?[0-9]+", "0.1.2", Some((0, 3)));
+mat!(match_float3, r"[-+]?[0-9]*\.?[0-9]+", "a1.2", Some((1, 4)));
+mat!(match_float4, r"^[-+]?[0-9]*\.?[0-9]+$", "1.a", None);
+mat!(
+    match_email,
+    r"(?i-u)\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b",
+    "mine is jam.slam@gmail.com ",
+    Some((8, 26))
+);
+mat!(
+    match_email_not,
+    r"(?i-u)\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b",
+    "mine is jam.slam@gmail ",
+    None
+);
+mat!(
+    match_email_big,
+    r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
+    "mine is jam.slam@gmail.com ",
+    Some((8, 26))
+);
+mat!(
+    match_date1,
+    r"(?-u)^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$",
+    "1900-01-01",
+    Some((0, 10))
+);
+mat!(
+    match_date2,
+    r"(?-u)^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$",
+    "1900-00-01",
+    None
+);
+mat!(
+    match_date3,
+    r"(?-u)^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$",
+    "1900-13-01",
+    None
+);
+
+// Do some crazy dancing with the start/end assertions.
+matiter!(match_start_end_empty, r"^$", "", (0, 0));
+matiter!(match_start_end_empty_many_1, r"^$^$^$", "", (0, 0));
+matiter!(match_start_end_empty_many_2, r"^^^$$$", "", (0, 0));
+matiter!(match_start_end_empty_rev, r"$^", "", (0, 0));
+matiter!(
+    match_start_end_empty_rep,
+    r"(?:^$)*",
+    "a\nb\nc",
+    (0, 0),
+    (1, 1),
+    (2, 2),
+    (3, 3),
+    (4, 4),
+    (5, 5)
+);
+matiter!(
+    match_start_end_empty_rep_rev,
+    r"(?:$^)*",
+    "a\nb\nc",
+    (0, 0),
+    (1, 1),
+    (2, 2),
+    (3, 3),
+    (4, 4),
+    (5, 5)
+);
+
+// Test negated character classes.
+mat!(negclass_letters, r"[^ac]", "acx", Some((2, 3)));
+mat!(negclass_letter_comma, r"[^a,]", "a,x", Some((2, 3)));
+mat!(negclass_letter_space, r"[^a[:space:]]", "a x", Some((2, 3)));
+mat!(negclass_comma, r"[^,]", ",,x", Some((2, 3)));
+mat!(negclass_space, r"[^[:space:]]", " a", Some((1, 2)));
+mat!(negclass_space_comma, r"[^,[:space:]]", ", a", Some((2, 3)));
+mat!(negclass_comma_space, r"[^[:space:],]", " ,a", Some((2, 3)));
+mat!(negclass_ascii, r"[^[:alpha:]Z]", "A1", Some((1, 2)));
+
+// Test that repeated empty expressions don't loop forever.
+mat!(lazy_many_many, r"((?:.*)*?)=", "a=b", Some((0, 2)));
+mat!(lazy_many_optional, r"((?:.?)*?)=", "a=b", Some((0, 2)));
+mat!(lazy_one_many_many, r"((?:.*)+?)=", "a=b", Some((0, 2)));
+mat!(lazy_one_many_optional, r"((?:.?)+?)=", "a=b", Some((0, 2)));
+mat!(lazy_range_min_many, r"((?:.*){1,}?)=", "a=b", Some((0, 2)));
+mat!(lazy_range_many, r"((?:.*){1,2}?)=", "a=b", Some((0, 2)));
+mat!(greedy_many_many, r"((?:.*)*)=", "a=b", Some((0, 2)));
+mat!(greedy_many_optional, r"((?:.?)*)=", "a=b", Some((0, 2)));
+mat!(greedy_one_many_many, r"((?:.*)+)=", "a=b", Some((0, 2)));
+mat!(greedy_one_many_optional, r"((?:.?)+)=", "a=b", Some((0, 2)));
+mat!(greedy_range_min_many, r"((?:.*){1,})=", "a=b", Some((0, 2)));
+mat!(greedy_range_many, r"((?:.*){1,2})=", "a=b", Some((0, 2)));
+
+// Test that we handle various flavors of empty expressions.
+matiter!(match_empty1, r"", "", (0, 0));
+matiter!(match_empty2, r"", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty3, r"()", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty4, r"()*", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty5, r"()+", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty6, r"()?", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty7, r"()()", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty8, r"()+|z", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty9, r"z|()+", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty10, r"()+|b", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty11, r"b|()+", "abc", (0, 0), (1, 2), (3, 3));
+matiter!(match_empty12, r"|b", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty13, r"b|", "abc", (0, 0), (1, 2), (3, 3));
+matiter!(match_empty14, r"|z", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty15, r"z|", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty16, r"|", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty17, r"||", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty18, r"||z", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty19, r"(?:)|b", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty20, r"b|(?:)", "abc", (0, 0), (1, 2), (3, 3));
+matiter!(match_empty21, r"(?:|)", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty22, r"(?:|)|z", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty23, r"a(?:)|b", "abc", (0, 1), (1, 2));
+
+// Test that the DFA can handle pathological cases.
+// (This should result in the DFA's cache being flushed too frequently, which
+// should cause it to quit and fall back to the NFA algorithm.)
+#[test]
+fn dfa_handles_pathological_case() {
+    fn ones_and_zeroes(count: usize) -> String {
+        use rand::rngs::SmallRng;
+        use rand::{Rng, SeedableRng};
+
+        let mut rng = SmallRng::from_entropy();
+        let mut s = String::new();
+        for _ in 0..count {
+            if rng.gen() {
+                s.push('1');
+            } else {
+                s.push('0');
+            }
+        }
+        s
+    }
+
+    let re = regex!(r"[01]*1[01]{20}$");
+    let text = {
+        let mut pieces = ones_and_zeroes(100_000);
+        pieces.push('1');
+        pieces.push_str(&ones_and_zeroes(20));
+        pieces
+    };
+    assert!(re.is_match(text!(&*text)));
+}
+
+#[test]
+fn nest_limit_makes_it_parse() {
+    use regex::RegexBuilder;
+
+    RegexBuilder::new(
+        r#"(?-u)
+        2(?:
+          [45]\d{3}|
+          7(?:
+            1[0-267]|
+            2[0-289]|
+            3[0-29]|
+            4[01]|
+            5[1-3]|
+            6[013]|
+            7[0178]|
+            91
+          )|
+          8(?:
+            0[125]|
+            [139][1-6]|
+            2[0157-9]|
+            41|
+            6[1-35]|
+            7[1-5]|
+            8[1-8]|
+            90
+          )|
+          9(?:
+            0[0-2]|
+            1[0-4]|
+            2[568]|
+            3[3-6]|
+            5[5-7]|
+            6[0167]|
+            7[15]|
+            8[0146-9]
+          )
+        )\d{4}|
+        3(?:
+          12?[5-7]\d{2}|
+          0(?:
+            2(?:
+              [025-79]\d|
+              [348]\d{1,2}
+            )|
+            3(?:
+              [2-4]\d|
+              [56]\d?
+            )
+          )|
+          2(?:
+            1\d{2}|
+            2(?:
+              [12]\d|
+              [35]\d{1,2}|
+              4\d?
+            )
+          )|
+          3(?:
+            1\d{2}|
+            2(?:
+              [2356]\d|
+              4\d{1,2}
+            )
+          )|
+          4(?:
+            1\d{2}|
+            2(?:
+              2\d{1,2}|
+              [47]|
+              5\d{2}
+            )
+          )|
+          5(?:
+            1\d{2}|
+            29
+          )|
+          [67]1\d{2}|
+          8(?:
+            1\d{2}|
+            2(?:
+              2\d{2}|
+              3|
+              4\d
+            )
+          )
+        )\d{3}|
+        4(?:
+          0(?:
+            2(?:
+              [09]\d|
+              7
+            )|
+            33\d{2}
+          )|
+          1\d{3}|
+          2(?:
+            1\d{2}|
+            2(?:
+              [25]\d?|
+              [348]\d|
+              [67]\d{1,2}
+            )
+          )|
+          3(?:
+            1\d{2}(?:
+              \d{2}
+            )?|
+            2(?:
+              [045]\d|
+              [236-9]\d{1,2}
+            )|
+            32\d{2}
+          )|
+          4(?:
+            [18]\d{2}|
+            2(?:
+              [2-46]\d{2}|
+              3
+            )|
+            5[25]\d{2}
+          )|
+          5(?:
+            1\d{2}|
+            2(?:
+              3\d|
+              5
+            )
+          )|
+          6(?:
+            [18]\d{2}|
+            2(?:
+              3(?:
+                \d{2}
+              )?|
+              [46]\d{1,2}|
+              5\d{2}|
+              7\d
+            )|
+            5(?:
+              3\d?|
+              4\d|
+              [57]\d{1,2}|
+              6\d{2}|
+              8
+            )
+          )|
+          71\d{2}|
+          8(?:
+            [18]\d{2}|
+            23\d{2}|
+            54\d{2}
+          )|
+          9(?:
+            [18]\d{2}|
+            2[2-5]\d{2}|
+            53\d{1,2}
+          )
+        )\d{3}|
+        5(?:
+          02[03489]\d{2}|
+          1\d{2}|
+          2(?:
+            1\d{2}|
+            2(?:
+              2(?:
+                \d{2}
+              )?|
+              [457]\d{2}
+            )
+          )|
+          3(?:
+            1\d{2}|
+            2(?:
+              [37](?:
+                \d{2}
+              )?|
+              [569]\d{2}
+            )
+          )|
+          4(?:
+            1\d{2}|
+            2[46]\d{2}
+          )|
+          5(?:
+            1\d{2}|
+            26\d{1,2}
+          )|
+          6(?:
+            [18]\d{2}|
+            2|
+            53\d{2}
+          )|
+          7(?:
+            1|
+            24
+          )\d{2}|
+          8(?:
+            1|
+            26
+          )\d{2}|
+          91\d{2}
+        )\d{3}|
+        6(?:
+          0(?:
+            1\d{2}|
+            2(?:
+              3\d{2}|
+              4\d{1,2}
+            )
+          )|
+          2(?:
+            2[2-5]\d{2}|
+            5(?:
+              [3-5]\d{2}|
+              7
+            )|
+            8\d{2}
+          )|
+          3(?:
+            1|
+            2[3478]
+          )\d{2}|
+          4(?:
+            1|
+            2[34]
+          )\d{2}|
+          5(?:
+            1|
+            2[47]
+          )\d{2}|
+          6(?:
+            [18]\d{2}|
+            6(?:
+              2(?:
+                2\d|
+                [34]\d{2}
+              )|
+              5(?:
+                [24]\d{2}|
+                3\d|
+                5\d{1,2}
+              )
+            )
+          )|
+          72[2-5]\d{2}|
+          8(?:
+            1\d{2}|
+            2[2-5]\d{2}
+          )|
+          9(?:
+            1\d{2}|
+            2[2-6]\d{2}
+          )
+        )\d{3}|
+        7(?:
+          (?:
+            02|
+            [3-589]1|
+            6[12]|
+            72[24]
+          )\d{2}|
+          21\d{3}|
+          32
+        )\d{3}|
+        8(?:
+          (?:
+            4[12]|
+            [5-7]2|
+            1\d?
+          )|
+          (?:
+            0|
+            3[12]|
+            [5-7]1|
+            217
+          )\d
+        )\d{4}|
+        9(?:
+          [35]1|
+          (?:
+            [024]2|
+            81
+          )\d|
+          (?:
+            1|
+            [24]1
+          )\d{2}
+        )\d{3}
+        "#,
+    )
+    .build()
+    .unwrap();
+}
diff --git a/vendor/regex-1.4.6/tests/flags.rs b/vendor/regex-1.4.6/tests/flags.rs
new file mode 100644 (file)
index 0000000..c33b82d
--- /dev/null
@@ -0,0 +1,31 @@
+mat!(match_flag_case, "(?-u)(?i)abc", "ABC", Some((0, 3)));
+mat!(match_flag_weird_case, "(?-u)(?i)a(?-i)bc", "Abc", Some((0, 3)));
+mat!(match_flag_weird_case_not, "(?-u)(?i)a(?-i)bc", "ABC", None);
+mat!(match_flag_case_dotnl, "(?-u)(?is)a(?u:.)", "A\n", Some((0, 2)));
+mat!(
+    match_flag_case_dotnl_toggle,
+    "(?-u)(?is)a(?u:.)(?-is)a(?u:.)",
+    "A\nab",
+    Some((0, 4))
+);
+mat!(
+    match_flag_case_dotnl_toggle_not,
+    "(?-u)(?is)a(?u:.)(?-is)a(?u:.)",
+    "A\na\n",
+    None
+);
+mat!(
+    match_flag_case_dotnl_toggle_ok,
+    "(?-u)(?is)a(?u:.)(?-is:a(?u:.))?",
+    "A\na\n",
+    Some((0, 2))
+);
+mat!(
+    match_flag_multi,
+    r"(?-u)(?m)(?:^\d+$\n?)+",
+    "123\n456\n789",
+    Some((0, 11))
+);
+mat!(match_flag_ungreedy, "(?U)a+", "aa", Some((0, 1)));
+mat!(match_flag_ungreedy_greedy, "(?U)a+?", "aa", Some((0, 2)));
+mat!(match_flag_ungreedy_noop, "(?U)(?-U)a+", "aa", Some((0, 2)));
diff --git a/vendor/regex-1.4.6/tests/fowler.rs b/vendor/regex-1.4.6/tests/fowler.rs
new file mode 100644 (file)
index 0000000..7f56a75
--- /dev/null
@@ -0,0 +1,1588 @@
+// DO NOT EDIT. Automatically generated by 'scripts/regex-match-tests.py'
+// on 2019-09-02 11:07:37.849994.
+
+// Tests from basic.dat
+mat!(match_basic_3, r"abracadabra$", r"abracadabracadabra", Some((7, 18)));
+mat!(match_basic_4, r"a...b", r"abababbb", Some((2, 7)));
+mat!(match_basic_5, r"XXXXXX", r"..XXXXXX", Some((2, 8)));
+mat!(match_basic_6, r"\)", r"()", Some((1, 2)));
+mat!(match_basic_7, r"a]", r"a]a", Some((0, 2)));
+mat!(match_basic_9, r"\}", r"}", Some((0, 1)));
+mat!(match_basic_10, r"\]", r"]", Some((0, 1)));
+mat!(match_basic_12, r"]", r"]", Some((0, 1)));
+mat!(match_basic_15, r"^a", r"ax", Some((0, 1)));
+mat!(match_basic_16, r"\^a", r"a^a", Some((1, 3)));
+mat!(match_basic_17, r"a\^", r"a^", Some((0, 2)));
+mat!(match_basic_18, r"a$", r"aa", Some((1, 2)));
+mat!(match_basic_19, r"a\$", r"a$", Some((0, 2)));
+mat!(match_basic_20, r"^$", r"", Some((0, 0)));
+mat!(match_basic_21, r"$^", r"", Some((0, 0)));
+mat!(match_basic_22, r"a($)", r"aa", Some((1, 2)), Some((2, 2)));
+mat!(match_basic_23, r"a*(^a)", r"aa", Some((0, 1)), Some((0, 1)));
+mat!(match_basic_24, r"(..)*(...)*", r"a", Some((0, 0)));
+mat!(match_basic_25, r"(..)*(...)*", r"abcd", Some((0, 4)), Some((2, 4)));
+mat!(
+    match_basic_26,
+    r"(ab|a)(bc|c)",
+    r"abc",
+    Some((0, 3)),
+    Some((0, 2)),
+    Some((2, 3))
+);
+mat!(match_basic_27, r"(ab)c|abc", r"abc", Some((0, 3)), Some((0, 2)));
+mat!(match_basic_28, r"a{0}b", r"ab", Some((1, 2)));
+mat!(
+    match_basic_29,
+    r"(a*)(b?)(b+)b{3}",
+    r"aaabbbbbbb",
+    Some((0, 10)),
+    Some((0, 3)),
+    Some((3, 4)),
+    Some((4, 7))
+);
+mat!(
+    match_basic_30,
+    r"(a*)(b{0,1})(b{1,})b{3}",
+    r"aaabbbbbbb",
+    Some((0, 10)),
+    Some((0, 3)),
+    Some((3, 4)),
+    Some((4, 7))
+);
+mat!(
+    match_basic_32,
+    r"((a|a)|a)",
+    r"a",
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((0, 1))
+);
+mat!(
+    match_basic_33,
+    r"(a*)(a|aa)",
+    r"aaaa",
+    Some((0, 4)),
+    Some((0, 3)),
+    Some((3, 4))
+);
+mat!(match_basic_34, r"a*(a.|aa)", r"aaaa", Some((0, 4)), Some((2, 4)));
+mat!(
+    match_basic_35,
+    r"a(b)|c(d)|a(e)f",
+    r"aef",
+    Some((0, 3)),
+    None,
+    None,
+    Some((1, 2))
+);
+mat!(match_basic_36, r"(a|b)?.*", r"b", Some((0, 1)), Some((0, 1)));
+mat!(match_basic_37, r"(a|b)c|a(b|c)", r"ac", Some((0, 2)), Some((0, 1)));
+mat!(
+    match_basic_38,
+    r"(a|b)c|a(b|c)",
+    r"ab",
+    Some((0, 2)),
+    None,
+    Some((1, 2))
+);
+mat!(match_basic_39, r"(a|b)*c|(a|ab)*c", r"abc", Some((0, 3)), Some((1, 2)));
+mat!(match_basic_40, r"(a|b)*c|(a|ab)*c", r"xc", Some((1, 2)));
+mat!(
+    match_basic_41,
+    r"(.a|.b).*|.*(.a|.b)",
+    r"xa",
+    Some((0, 2)),
+    Some((0, 2))
+);
+mat!(match_basic_42, r"a?(ab|ba)ab", r"abab", Some((0, 4)), Some((0, 2)));
+mat!(match_basic_43, r"a?(ac{0}b|ba)ab", r"abab", Some((0, 4)), Some((0, 2)));
+mat!(match_basic_44, r"ab|abab", r"abbabab", Some((0, 2)));
+mat!(match_basic_45, r"aba|bab|bba", r"baaabbbaba", Some((5, 8)));
+mat!(match_basic_46, r"aba|bab", r"baaabbbaba", Some((6, 9)));
+mat!(
+    match_basic_47,
+    r"(aa|aaa)*|(a|aaaaa)",
+    r"aa",
+    Some((0, 2)),
+    Some((0, 2))
+);
+mat!(
+    match_basic_48,
+    r"(a.|.a.)*|(a|.a...)",
+    r"aa",
+    Some((0, 2)),
+    Some((0, 2))
+);
+mat!(match_basic_49, r"ab|a", r"xabc", Some((1, 3)));
+mat!(match_basic_50, r"ab|a", r"xxabc", Some((2, 4)));
+mat!(
+    match_basic_51,
+    r"(?i)(?-u)(Ab|cD)*",
+    r"aBcD",
+    Some((0, 4)),
+    Some((2, 4))
+);
+mat!(match_basic_52, r"[^-]", r"--a", Some((2, 3)));
+mat!(match_basic_53, r"[a-]*", r"--a", Some((0, 3)));
+mat!(match_basic_54, r"[a-m-]*", r"--amoma--", Some((0, 4)));
+mat!(
+    match_basic_55,
+    r":::1:::0:|:::1:1:0:",
+    r":::0:::1:::1:::0:",
+    Some((8, 17))
+);
+mat!(
+    match_basic_56,
+    r":::1:::0:|:::1:1:1:",
+    r":::0:::1:::1:::0:",
+    Some((8, 17))
+);
+mat!(match_basic_57, r"[[:upper:]]", r"A", Some((0, 1)));
+mat!(match_basic_58, r"[[:lower:]]+", r"`az{", Some((1, 3)));
+mat!(match_basic_59, r"[[:upper:]]+", r"@AZ[", Some((1, 3)));
+mat!(
+    match_basic_65,
+    r"
+",
+    r"
+",
+    Some((0, 1))
+);
+mat!(
+    match_basic_66,
+    r"
+",
+    r"
+",
+    Some((0, 1))
+);
+mat!(
+    match_basic_67,
+    r"[^a]",
+    r"
+",
+    Some((0, 1))
+);
+mat!(
+    match_basic_68,
+    r"
+a",
+    r"
+a",
+    Some((0, 2))
+);
+mat!(
+    match_basic_69,
+    r"(a)(b)(c)",
+    r"abc",
+    Some((0, 3)),
+    Some((0, 1)),
+    Some((1, 2)),
+    Some((2, 3))
+);
+mat!(match_basic_70, r"xxx", r"xxx", Some((0, 3)));
+mat!(
+    match_basic_71,
+    r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)",
+    r"feb 6,",
+    Some((0, 6))
+);
+mat!(
+    match_basic_72,
+    r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)",
+    r"2/7",
+    Some((0, 3))
+);
+mat!(
+    match_basic_73,
+    r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)",
+    r"feb 1,Feb 6",
+    Some((5, 11))
+);
+mat!(
+    match_basic_74,
+    r"((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))",
+    r"x",
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((0, 1))
+);
+mat!(
+    match_basic_75,
+    r"((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))*",
+    r"xx",
+    Some((0, 2)),
+    Some((1, 2)),
+    Some((1, 2))
+);
+mat!(
+    match_basic_76,
+    r"a?(ab|ba)*",
+    r"ababababababababababababababababababababababababababababababababababababababababa",
+    Some((0, 81)),
+    Some((79, 81))
+);
+mat!(
+    match_basic_77,
+    r"abaa|abbaa|abbbaa|abbbbaa",
+    r"ababbabbbabbbabbbbabbbbaa",
+    Some((18, 25))
+);
+mat!(
+    match_basic_78,
+    r"abaa|abbaa|abbbaa|abbbbaa",
+    r"ababbabbbabbbabbbbabaa",
+    Some((18, 22))
+);
+mat!(
+    match_basic_79,
+    r"aaac|aabc|abac|abbc|baac|babc|bbac|bbbc",
+    r"baaabbbabac",
+    Some((7, 11))
+);
+mat!(match_basic_80, r".*", r"\ 1\7f", Some((0, 2)));
+mat!(
+    match_basic_81,
+    r"aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll",
+    r"XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa",
+    Some((53, 57))
+);
+mat!(match_basic_83, r"a*a*a*a*a*b", r"aaaaaaaaab", Some((0, 10)));
+mat!(match_basic_84, r"^", r"", Some((0, 0)));
+mat!(match_basic_85, r"$", r"", Some((0, 0)));
+mat!(match_basic_86, r"^$", r"", Some((0, 0)));
+mat!(match_basic_87, r"^a$", r"a", Some((0, 1)));
+mat!(match_basic_88, r"abc", r"abc", Some((0, 3)));
+mat!(match_basic_89, r"abc", r"xabcy", Some((1, 4)));
+mat!(match_basic_90, r"abc", r"ababc", Some((2, 5)));
+mat!(match_basic_91, r"ab*c", r"abc", Some((0, 3)));
+mat!(match_basic_92, r"ab*bc", r"abc", Some((0, 3)));
+mat!(match_basic_93, r"ab*bc", r"abbc", Some((0, 4)));
+mat!(match_basic_94, r"ab*bc", r"abbbbc", Some((0, 6)));
+mat!(match_basic_95, r"ab+bc", r"abbc", Some((0, 4)));
+mat!(match_basic_96, r"ab+bc", r"abbbbc", Some((0, 6)));
+mat!(match_basic_97, r"ab?bc", r"abbc", Some((0, 4)));
+mat!(match_basic_98, r"ab?bc", r"abc", Some((0, 3)));
+mat!(match_basic_99, r"ab?c", r"abc", Some((0, 3)));
+mat!(match_basic_100, r"^abc$", r"abc", Some((0, 3)));
+mat!(match_basic_101, r"^abc", r"abcc", Some((0, 3)));
+mat!(match_basic_102, r"abc$", r"aabc", Some((1, 4)));
+mat!(match_basic_103, r"^", r"abc", Some((0, 0)));
+mat!(match_basic_104, r"$", r"abc", Some((3, 3)));
+mat!(match_basic_105, r"a.c", r"abc", Some((0, 3)));
+mat!(match_basic_106, r"a.c", r"axc", Some((0, 3)));
+mat!(match_basic_107, r"a.*c", r"axyzc", Some((0, 5)));
+mat!(match_basic_108, r"a[bc]d", r"abd", Some((0, 3)));
+mat!(match_basic_109, r"a[b-d]e", r"ace", Some((0, 3)));
+mat!(match_basic_110, r"a[b-d]", r"aac", Some((1, 3)));
+mat!(match_basic_111, r"a[-b]", r"a-", Some((0, 2)));
+mat!(match_basic_112, r"a[b-]", r"a-", Some((0, 2)));
+mat!(match_basic_113, r"a]", r"a]", Some((0, 2)));
+mat!(match_basic_114, r"a[]]b", r"a]b", Some((0, 3)));
+mat!(match_basic_115, r"a[^bc]d", r"aed", Some((0, 3)));
+mat!(match_basic_116, r"a[^-b]c", r"adc", Some((0, 3)));
+mat!(match_basic_117, r"a[^]b]c", r"adc", Some((0, 3)));
+mat!(match_basic_118, r"ab|cd", r"abc", Some((0, 2)));
+mat!(match_basic_119, r"ab|cd", r"abcd", Some((0, 2)));
+mat!(match_basic_120, r"a\(b", r"a(b", Some((0, 3)));
+mat!(match_basic_121, r"a\(*b", r"ab", Some((0, 2)));
+mat!(match_basic_122, r"a\(*b", r"a((b", Some((0, 4)));
+mat!(
+    match_basic_123,
+    r"((a))",
+    r"abc",
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((0, 1))
+);
+mat!(
+    match_basic_124,
+    r"(a)b(c)",
+    r"abc",
+    Some((0, 3)),
+    Some((0, 1)),
+    Some((2, 3))
+);
+mat!(match_basic_125, r"a+b+c", r"aabbabc", Some((4, 7)));
+mat!(match_basic_126, r"a*", r"aaa", Some((0, 3)));
+mat!(match_basic_128, r"(a*)*", r"-", Some((0, 0)), None);
+mat!(match_basic_129, r"(a*)+", r"-", Some((0, 0)), Some((0, 0)));
+mat!(match_basic_131, r"(a*|b)*", r"-", Some((0, 0)), None);
+mat!(match_basic_132, r"(a+|b)*", r"ab", Some((0, 2)), Some((1, 2)));
+mat!(match_basic_133, r"(a+|b)+", r"ab", Some((0, 2)), Some((1, 2)));
+mat!(match_basic_134, r"(a+|b)?", r"ab", Some((0, 1)), Some((0, 1)));
+mat!(match_basic_135, r"[^ab]*", r"cde", Some((0, 3)));
+mat!(match_basic_137, r"(^)*", r"-", Some((0, 0)), None);
+mat!(match_basic_138, r"a*", r"", Some((0, 0)));
+mat!(match_basic_139, r"([abc])*d", r"abbbcd", Some((0, 6)), Some((4, 5)));
+mat!(match_basic_140, r"([abc])*bcd", r"abcd", Some((0, 4)), Some((0, 1)));
+mat!(match_basic_141, r"a|b|c|d|e", r"e", Some((0, 1)));
+mat!(match_basic_142, r"(a|b|c|d|e)f", r"ef", Some((0, 2)), Some((0, 1)));
+mat!(match_basic_144, r"((a*|b))*", r"-", Some((0, 0)), None, None);
+mat!(match_basic_145, r"abcd*efg", r"abcdefg", Some((0, 7)));
+mat!(match_basic_146, r"ab*", r"xabyabbbz", Some((1, 3)));
+mat!(match_basic_147, r"ab*", r"xayabbbz", Some((1, 2)));
+mat!(match_basic_148, r"(ab|cd)e", r"abcde", Some((2, 5)), Some((2, 4)));
+mat!(match_basic_149, r"[abhgefdc]ij", r"hij", Some((0, 3)));
+mat!(match_basic_150, r"(a|b)c*d", r"abcd", Some((1, 4)), Some((1, 2)));
+mat!(match_basic_151, r"(ab|ab*)bc", r"abc", Some((0, 3)), Some((0, 1)));
+mat!(match_basic_152, r"a([bc]*)c*", r"abc", Some((0, 3)), Some((1, 3)));
+mat!(
+    match_basic_153,
+    r"a([bc]*)(c*d)",
+    r"abcd",
+    Some((0, 4)),
+    Some((1, 3)),
+    Some((3, 4))
+);
+mat!(
+    match_basic_154,
+    r"a([bc]+)(c*d)",
+    r"abcd",
+    Some((0, 4)),
+    Some((1, 3)),
+    Some((3, 4))
+);
+mat!(
+    match_basic_155,
+    r"a([bc]*)(c+d)",
+    r"abcd",
+    Some((0, 4)),
+    Some((1, 2)),
+    Some((2, 4))
+);
+mat!(match_basic_156, r"a[bcd]*dcdcde", r"adcdcde", Some((0, 7)));
+mat!(match_basic_157, r"(ab|a)b*c", r"abc", Some((0, 3)), Some((0, 2)));
+mat!(
+    match_basic_158,
+    r"((a)(b)c)(d)",
+    r"abcd",
+    Some((0, 4)),
+    Some((0, 3)),
+    Some((0, 1)),
+    Some((1, 2)),
+    Some((3, 4))
+);
+mat!(match_basic_159, r"[A-Za-z_][A-Za-z0-9_]*", r"alpha", Some((0, 5)));
+mat!(match_basic_160, r"^a(bc+|b[eh])g|.h$", r"abh", Some((1, 3)));
+mat!(
+    match_basic_161,
+    r"(bc+d$|ef*g.|h?i(j|k))",
+    r"effgz",
+    Some((0, 5)),
+    Some((0, 5))
+);
+mat!(
+    match_basic_162,
+    r"(bc+d$|ef*g.|h?i(j|k))",
+    r"ij",
+    Some((0, 2)),
+    Some((0, 2)),
+    Some((1, 2))
+);
+mat!(
+    match_basic_163,
+    r"(bc+d$|ef*g.|h?i(j|k))",
+    r"reffgz",
+    Some((1, 6)),
+    Some((1, 6))
+);
+mat!(
+    match_basic_164,
+    r"(((((((((a)))))))))",
+    r"a",
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((0, 1))
+);
+mat!(
+    match_basic_165,
+    r"multiple words",
+    r"multiple words yeah",
+    Some((0, 14))
+);
+mat!(
+    match_basic_166,
+    r"(.*)c(.*)",
+    r"abcde",
+    Some((0, 5)),
+    Some((0, 2)),
+    Some((3, 5))
+);
+mat!(match_basic_167, r"abcd", r"abcd", Some((0, 4)));
+mat!(match_basic_168, r"a(bc)d", r"abcd", Some((0, 4)), Some((1, 3)));
+mat!(match_basic_169, r"a[\ 1-\ 3]?c", r"a\ 2c", Some((0, 3)));
+mat!(
+    match_basic_170,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Muammar Qaddafi",
+    Some((0, 15)),
+    None,
+    Some((10, 12))
+);
+mat!(
+    match_basic_171,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Mo'ammar Gadhafi",
+    Some((0, 16)),
+    None,
+    Some((11, 13))
+);
+mat!(
+    match_basic_172,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Muammar Kaddafi",
+    Some((0, 15)),
+    None,
+    Some((10, 12))
+);
+mat!(
+    match_basic_173,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Muammar Qadhafi",
+    Some((0, 15)),
+    None,
+    Some((10, 12))
+);
+mat!(
+    match_basic_174,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Muammar Gadafi",
+    Some((0, 14)),
+    None,
+    Some((10, 11))
+);
+mat!(
+    match_basic_175,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Mu'ammar Qadafi",
+    Some((0, 15)),
+    None,
+    Some((11, 12))
+);
+mat!(
+    match_basic_176,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Moamar Gaddafi",
+    Some((0, 14)),
+    None,
+    Some((9, 11))
+);
+mat!(
+    match_basic_177,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Mu'ammar Qadhdhafi",
+    Some((0, 18)),
+    None,
+    Some((13, 15))
+);
+mat!(
+    match_basic_178,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Muammar Khaddafi",
+    Some((0, 16)),
+    None,
+    Some((11, 13))
+);
+mat!(
+    match_basic_179,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Muammar Ghaddafy",
+    Some((0, 16)),
+    None,
+    Some((11, 13))
+);
+mat!(
+    match_basic_180,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Muammar Ghadafi",
+    Some((0, 15)),
+    None,
+    Some((11, 12))
+);
+mat!(
+    match_basic_181,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Muammar Ghaddafi",
+    Some((0, 16)),
+    None,
+    Some((11, 13))
+);
+mat!(
+    match_basic_182,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Muamar Kaddafi",
+    Some((0, 14)),
+    None,
+    Some((9, 11))
+);
+mat!(
+    match_basic_183,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Muammar Quathafi",
+    Some((0, 16)),
+    None,
+    Some((11, 13))
+);
+mat!(
+    match_basic_184,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Muammar Gheddafi",
+    Some((0, 16)),
+    None,
+    Some((11, 13))
+);
+mat!(
+    match_basic_185,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Moammar Khadafy",
+    Some((0, 15)),
+    None,
+    Some((11, 12))
+);
+mat!(
+    match_basic_186,
+    r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+    r"Moammar Qudhafi",
+    Some((0, 15)),
+    None,
+    Some((10, 12))
+);
+mat!(match_basic_187, r"a+(b|c)*d+", r"aabcdd", Some((0, 6)), Some((3, 4)));
+mat!(match_basic_188, r"^.+$", r"vivi", Some((0, 4)));
+mat!(match_basic_189, r"^(.+)$", r"vivi", Some((0, 4)), Some((0, 4)));
+mat!(
+    match_basic_190,
+    r"^([^!.]+).att.com!(.+)$",
+    r"gryphon.att.com!eby",
+    Some((0, 19)),
+    Some((0, 7)),
+    Some((16, 19))
+);
+mat!(
+    match_basic_191,
+    r"^([^!]+!)?([^!]+)$",
+    r"bas",
+    Some((0, 3)),
+    None,
+    Some((0, 3))
+);
+mat!(
+    match_basic_192,
+    r"^([^!]+!)?([^!]+)$",
+    r"bar!bas",
+    Some((0, 7)),
+    Some((0, 4)),
+    Some((4, 7))
+);
+mat!(
+    match_basic_193,
+    r"^([^!]+!)?([^!]+)$",
+    r"foo!bas",
+    Some((0, 7)),
+    Some((0, 4)),
+    Some((4, 7))
+);
+mat!(
+    match_basic_194,
+    r"^.+!([^!]+!)([^!]+)$",
+    r"foo!bar!bas",
+    Some((0, 11)),
+    Some((4, 8)),
+    Some((8, 11))
+);
+mat!(
+    match_basic_195,
+    r"((foo)|(bar))!bas",
+    r"bar!bas",
+    Some((0, 7)),
+    Some((0, 3)),
+    None,
+    Some((0, 3))
+);
+mat!(
+    match_basic_196,
+    r"((foo)|(bar))!bas",
+    r"foo!bar!bas",
+    Some((4, 11)),
+    Some((4, 7)),
+    None,
+    Some((4, 7))
+);
+mat!(
+    match_basic_197,
+    r"((foo)|(bar))!bas",
+    r"foo!bas",
+    Some((0, 7)),
+    Some((0, 3)),
+    Some((0, 3))
+);
+mat!(
+    match_basic_198,
+    r"((foo)|bar)!bas",
+    r"bar!bas",
+    Some((0, 7)),
+    Some((0, 3))
+);
+mat!(
+    match_basic_199,
+    r"((foo)|bar)!bas",
+    r"foo!bar!bas",
+    Some((4, 11)),
+    Some((4, 7))
+);
+mat!(
+    match_basic_200,
+    r"((foo)|bar)!bas",
+    r"foo!bas",
+    Some((0, 7)),
+    Some((0, 3)),
+    Some((0, 3))
+);
+mat!(
+    match_basic_201,
+    r"(foo|(bar))!bas",
+    r"bar!bas",
+    Some((0, 7)),
+    Some((0, 3)),
+    Some((0, 3))
+);
+mat!(
+    match_basic_202,
+    r"(foo|(bar))!bas",
+    r"foo!bar!bas",
+    Some((4, 11)),
+    Some((4, 7)),
+    Some((4, 7))
+);
+mat!(
+    match_basic_203,
+    r"(foo|(bar))!bas",
+    r"foo!bas",
+    Some((0, 7)),
+    Some((0, 3))
+);
+mat!(
+    match_basic_204,
+    r"(foo|bar)!bas",
+    r"bar!bas",
+    Some((0, 7)),
+    Some((0, 3))
+);
+mat!(
+    match_basic_205,
+    r"(foo|bar)!bas",
+    r"foo!bar!bas",
+    Some((4, 11)),
+    Some((4, 7))
+);
+mat!(
+    match_basic_206,
+    r"(foo|bar)!bas",
+    r"foo!bas",
+    Some((0, 7)),
+    Some((0, 3))
+);
+mat!(
+    match_basic_207,
+    r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$",
+    r"foo!bar!bas",
+    Some((0, 11)),
+    Some((0, 11)),
+    None,
+    None,
+    Some((4, 8)),
+    Some((8, 11))
+);
+mat!(
+    match_basic_208,
+    r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$",
+    r"bas",
+    Some((0, 3)),
+    None,
+    Some((0, 3))
+);
+mat!(
+    match_basic_209,
+    r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$",
+    r"bar!bas",
+    Some((0, 7)),
+    Some((0, 4)),
+    Some((4, 7))
+);
+mat!(
+    match_basic_210,
+    r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$",
+    r"foo!bar!bas",
+    Some((0, 11)),
+    None,
+    None,
+    Some((4, 8)),
+    Some((8, 11))
+);
+mat!(
+    match_basic_211,
+    r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$",
+    r"foo!bas",
+    Some((0, 7)),
+    Some((0, 4)),
+    Some((4, 7))
+);
+mat!(
+    match_basic_212,
+    r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$",
+    r"bas",
+    Some((0, 3)),
+    Some((0, 3)),
+    None,
+    Some((0, 3))
+);
+mat!(
+    match_basic_213,
+    r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$",
+    r"bar!bas",
+    Some((0, 7)),
+    Some((0, 7)),
+    Some((0, 4)),
+    Some((4, 7))
+);
+mat!(
+    match_basic_214,
+    r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$",
+    r"foo!bar!bas",
+    Some((0, 11)),
+    Some((0, 11)),
+    None,
+    None,
+    Some((4, 8)),
+    Some((8, 11))
+);
+mat!(
+    match_basic_215,
+    r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$",
+    r"foo!bas",
+    Some((0, 7)),
+    Some((0, 7)),
+    Some((0, 4)),
+    Some((4, 7))
+);
+mat!(match_basic_216, r".*(/XXX).*", r"/XXX", Some((0, 4)), Some((0, 4)));
+mat!(match_basic_217, r".*(\\XXX).*", r"\XXX", Some((0, 4)), Some((0, 4)));
+mat!(match_basic_218, r"\\XXX", r"\XXX", Some((0, 4)));
+mat!(match_basic_219, r".*(/000).*", r"/000", Some((0, 4)), Some((0, 4)));
+mat!(match_basic_220, r".*(\\000).*", r"\000", Some((0, 4)), Some((0, 4)));
+mat!(match_basic_221, r"\\000", r"\000", Some((0, 4)));
+
+// Tests from nullsubexpr.dat
+mat!(match_nullsubexpr_3, r"(a*)*", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_5, r"(a*)*", r"x", Some((0, 0)), None);
+mat!(match_nullsubexpr_6, r"(a*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_7, r"(a*)*", r"aaaaaax", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_8, r"(a*)+", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_9, r"(a*)+", r"x", Some((0, 0)), Some((0, 0)));
+mat!(match_nullsubexpr_10, r"(a*)+", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_11, r"(a*)+", r"aaaaaax", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_12, r"(a+)*", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_13, r"(a+)*", r"x", Some((0, 0)));
+mat!(match_nullsubexpr_14, r"(a+)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_15, r"(a+)*", r"aaaaaax", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_16, r"(a+)+", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_17, r"(a+)+", r"x", None);
+mat!(match_nullsubexpr_18, r"(a+)+", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_19, r"(a+)+", r"aaaaaax", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_21, r"([a]*)*", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_23, r"([a]*)*", r"x", Some((0, 0)), None);
+mat!(match_nullsubexpr_24, r"([a]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_25, r"([a]*)*", r"aaaaaax", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_26, r"([a]*)+", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_27, r"([a]*)+", r"x", Some((0, 0)), Some((0, 0)));
+mat!(match_nullsubexpr_28, r"([a]*)+", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_29, r"([a]*)+", r"aaaaaax", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_30, r"([^b]*)*", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_32, r"([^b]*)*", r"b", Some((0, 0)), None);
+mat!(match_nullsubexpr_33, r"([^b]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(
+    match_nullsubexpr_34,
+    r"([^b]*)*",
+    r"aaaaaab",
+    Some((0, 6)),
+    Some((0, 6))
+);
+mat!(match_nullsubexpr_35, r"([ab]*)*", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_36, r"([ab]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_37, r"([ab]*)*", r"ababab", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_38, r"([ab]*)*", r"bababa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_39, r"([ab]*)*", r"b", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_40, r"([ab]*)*", r"bbbbbb", Some((0, 6)), Some((0, 6)));
+mat!(
+    match_nullsubexpr_41,
+    r"([ab]*)*",
+    r"aaaabcde",
+    Some((0, 5)),
+    Some((0, 5))
+);
+mat!(match_nullsubexpr_42, r"([^a]*)*", r"b", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_43, r"([^a]*)*", r"bbbbbb", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_45, r"([^a]*)*", r"aaaaaa", Some((0, 0)), None);
+mat!(
+    match_nullsubexpr_46,
+    r"([^ab]*)*",
+    r"ccccxx",
+    Some((0, 6)),
+    Some((0, 6))
+);
+mat!(match_nullsubexpr_48, r"([^ab]*)*", r"ababab", Some((0, 0)), None);
+mat!(
+    match_nullsubexpr_50,
+    r"((z)+|a)*",
+    r"zabcde",
+    Some((0, 2)),
+    Some((1, 2))
+);
+mat!(
+    match_nullsubexpr_69,
+    r"(a*)*(x)",
+    r"x",
+    Some((0, 1)),
+    None,
+    Some((0, 1))
+);
+mat!(
+    match_nullsubexpr_70,
+    r"(a*)*(x)",
+    r"ax",
+    Some((0, 2)),
+    Some((0, 1)),
+    Some((1, 2))
+);
+mat!(
+    match_nullsubexpr_71,
+    r"(a*)*(x)",
+    r"axa",
+    Some((0, 2)),
+    Some((0, 1)),
+    Some((1, 2))
+);
+mat!(
+    match_nullsubexpr_73,
+    r"(a*)+(x)",
+    r"x",
+    Some((0, 1)),
+    Some((0, 0)),
+    Some((0, 1))
+);
+mat!(
+    match_nullsubexpr_74,
+    r"(a*)+(x)",
+    r"ax",
+    Some((0, 2)),
+    Some((0, 1)),
+    Some((1, 2))
+);
+mat!(
+    match_nullsubexpr_75,
+    r"(a*)+(x)",
+    r"axa",
+    Some((0, 2)),
+    Some((0, 1)),
+    Some((1, 2))
+);
+mat!(
+    match_nullsubexpr_77,
+    r"(a*){2}(x)",
+    r"x",
+    Some((0, 1)),
+    Some((0, 0)),
+    Some((0, 1))
+);
+mat!(
+    match_nullsubexpr_78,
+    r"(a*){2}(x)",
+    r"ax",
+    Some((0, 2)),
+    Some((1, 1)),
+    Some((1, 2))
+);
+mat!(
+    match_nullsubexpr_79,
+    r"(a*){2}(x)",
+    r"axa",
+    Some((0, 2)),
+    Some((1, 1)),
+    Some((1, 2))
+);
+
+// Tests from repetition.dat
+mat!(match_repetition_10, r"((..)|(.))", r"", None);
+mat!(match_repetition_11, r"((..)|(.))((..)|(.))", r"", None);
+mat!(match_repetition_12, r"((..)|(.))((..)|(.))((..)|(.))", r"", None);
+mat!(match_repetition_14, r"((..)|(.)){1}", r"", None);
+mat!(match_repetition_15, r"((..)|(.)){2}", r"", None);
+mat!(match_repetition_16, r"((..)|(.)){3}", r"", None);
+mat!(match_repetition_18, r"((..)|(.))*", r"", Some((0, 0)));
+mat!(
+    match_repetition_20,
+    r"((..)|(.))",
+    r"a",
+    Some((0, 1)),
+    Some((0, 1)),
+    None,
+    Some((0, 1))
+);
+mat!(match_repetition_21, r"((..)|(.))((..)|(.))", r"a", None);
+mat!(match_repetition_22, r"((..)|(.))((..)|(.))((..)|(.))", r"a", None);
+mat!(
+    match_repetition_24,
+    r"((..)|(.)){1}",
+    r"a",
+    Some((0, 1)),
+    Some((0, 1)),
+    None,
+    Some((0, 1))
+);
+mat!(match_repetition_25, r"((..)|(.)){2}", r"a", None);
+mat!(match_repetition_26, r"((..)|(.)){3}", r"a", None);
+mat!(
+    match_repetition_28,
+    r"((..)|(.))*",
+    r"a",
+    Some((0, 1)),
+    Some((0, 1)),
+    None,
+    Some((0, 1))
+);
+mat!(
+    match_repetition_30,
+    r"((..)|(.))",
+    r"aa",
+    Some((0, 2)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None
+);
+mat!(
+    match_repetition_31,
+    r"((..)|(.))((..)|(.))",
+    r"aa",
+    Some((0, 2)),
+    Some((0, 1)),
+    None,
+    Some((0, 1)),
+    Some((1, 2)),
+    None,
+    Some((1, 2))
+);
+mat!(match_repetition_32, r"((..)|(.))((..)|(.))((..)|(.))", r"aa", None);
+mat!(
+    match_repetition_34,
+    r"((..)|(.)){1}",
+    r"aa",
+    Some((0, 2)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None
+);
+mat!(
+    match_repetition_35,
+    r"((..)|(.)){2}",
+    r"aa",
+    Some((0, 2)),
+    Some((1, 2)),
+    None,
+    Some((1, 2))
+);
+mat!(match_repetition_36, r"((..)|(.)){3}", r"aa", None);
+mat!(
+    match_repetition_38,
+    r"((..)|(.))*",
+    r"aa",
+    Some((0, 2)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None
+);
+mat!(
+    match_repetition_40,
+    r"((..)|(.))",
+    r"aaa",
+    Some((0, 2)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None
+);
+mat!(
+    match_repetition_41,
+    r"((..)|(.))((..)|(.))",
+    r"aaa",
+    Some((0, 3)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None,
+    Some((2, 3)),
+    None,
+    Some((2, 3))
+);
+mat!(
+    match_repetition_42,
+    r"((..)|(.))((..)|(.))((..)|(.))",
+    r"aaa",
+    Some((0, 3)),
+    Some((0, 1)),
+    None,
+    Some((0, 1)),
+    Some((1, 2)),
+    None,
+    Some((1, 2)),
+    Some((2, 3)),
+    None,
+    Some((2, 3))
+);
+mat!(
+    match_repetition_44,
+    r"((..)|(.)){1}",
+    r"aaa",
+    Some((0, 2)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None
+);
+mat!(
+    match_repetition_46,
+    r"((..)|(.)){2}",
+    r"aaa",
+    Some((0, 3)),
+    Some((2, 3)),
+    Some((0, 2)),
+    Some((2, 3))
+);
+mat!(
+    match_repetition_47,
+    r"((..)|(.)){3}",
+    r"aaa",
+    Some((0, 3)),
+    Some((2, 3)),
+    None,
+    Some((2, 3))
+);
+mat!(
+    match_repetition_50,
+    r"((..)|(.))*",
+    r"aaa",
+    Some((0, 3)),
+    Some((2, 3)),
+    Some((0, 2)),
+    Some((2, 3))
+);
+mat!(
+    match_repetition_52,
+    r"((..)|(.))",
+    r"aaaa",
+    Some((0, 2)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None
+);
+mat!(
+    match_repetition_53,
+    r"((..)|(.))((..)|(.))",
+    r"aaaa",
+    Some((0, 4)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None,
+    Some((2, 4)),
+    Some((2, 4)),
+    None
+);
+mat!(
+    match_repetition_54,
+    r"((..)|(.))((..)|(.))((..)|(.))",
+    r"aaaa",
+    Some((0, 4)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None,
+    Some((2, 3)),
+    None,
+    Some((2, 3)),
+    Some((3, 4)),
+    None,
+    Some((3, 4))
+);
+mat!(
+    match_repetition_56,
+    r"((..)|(.)){1}",
+    r"aaaa",
+    Some((0, 2)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None
+);
+mat!(
+    match_repetition_57,
+    r"((..)|(.)){2}",
+    r"aaaa",
+    Some((0, 4)),
+    Some((2, 4)),
+    Some((2, 4)),
+    None
+);
+mat!(
+    match_repetition_59,
+    r"((..)|(.)){3}",
+    r"aaaa",
+    Some((0, 4)),
+    Some((3, 4)),
+    Some((0, 2)),
+    Some((3, 4))
+);
+mat!(
+    match_repetition_61,
+    r"((..)|(.))*",
+    r"aaaa",
+    Some((0, 4)),
+    Some((2, 4)),
+    Some((2, 4)),
+    None
+);
+mat!(
+    match_repetition_63,
+    r"((..)|(.))",
+    r"aaaaa",
+    Some((0, 2)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None
+);
+mat!(
+    match_repetition_64,
+    r"((..)|(.))((..)|(.))",
+    r"aaaaa",
+    Some((0, 4)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None,
+    Some((2, 4)),
+    Some((2, 4)),
+    None
+);
+mat!(
+    match_repetition_65,
+    r"((..)|(.))((..)|(.))((..)|(.))",
+    r"aaaaa",
+    Some((0, 5)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None,
+    Some((2, 4)),
+    Some((2, 4)),
+    None,
+    Some((4, 5)),
+    None,
+    Some((4, 5))
+);
+mat!(
+    match_repetition_67,
+    r"((..)|(.)){1}",
+    r"aaaaa",
+    Some((0, 2)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None
+);
+mat!(
+    match_repetition_68,
+    r"((..)|(.)){2}",
+    r"aaaaa",
+    Some((0, 4)),
+    Some((2, 4)),
+    Some((2, 4)),
+    None
+);
+mat!(
+    match_repetition_70,
+    r"((..)|(.)){3}",
+    r"aaaaa",
+    Some((0, 5)),
+    Some((4, 5)),
+    Some((2, 4)),
+    Some((4, 5))
+);
+mat!(
+    match_repetition_73,
+    r"((..)|(.))*",
+    r"aaaaa",
+    Some((0, 5)),
+    Some((4, 5)),
+    Some((2, 4)),
+    Some((4, 5))
+);
+mat!(
+    match_repetition_75,
+    r"((..)|(.))",
+    r"aaaaaa",
+    Some((0, 2)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None
+);
+mat!(
+    match_repetition_76,
+    r"((..)|(.))((..)|(.))",
+    r"aaaaaa",
+    Some((0, 4)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None,
+    Some((2, 4)),
+    Some((2, 4)),
+    None
+);
+mat!(
+    match_repetition_77,
+    r"((..)|(.))((..)|(.))((..)|(.))",
+    r"aaaaaa",
+    Some((0, 6)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None,
+    Some((2, 4)),
+    Some((2, 4)),
+    None,
+    Some((4, 6)),
+    Some((4, 6)),
+    None
+);
+mat!(
+    match_repetition_79,
+    r"((..)|(.)){1}",
+    r"aaaaaa",
+    Some((0, 2)),
+    Some((0, 2)),
+    Some((0, 2)),
+    None
+);
+mat!(
+    match_repetition_80,
+    r"((..)|(.)){2}",
+    r"aaaaaa",
+    Some((0, 4)),
+    Some((2, 4)),
+    Some((2, 4)),
+    None
+);
+mat!(
+    match_repetition_81,
+    r"((..)|(.)){3}",
+    r"aaaaaa",
+    Some((0, 6)),
+    Some((4, 6)),
+    Some((4, 6)),
+    None
+);
+mat!(
+    match_repetition_83,
+    r"((..)|(.))*",
+    r"aaaaaa",
+    Some((0, 6)),
+    Some((4, 6)),
+    Some((4, 6)),
+    None
+);
+mat!(
+    match_repetition_90,
+    r"X(.?){0,}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((7, 8))
+);
+mat!(
+    match_repetition_91,
+    r"X(.?){1,}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((7, 8))
+);
+mat!(
+    match_repetition_92,
+    r"X(.?){2,}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((7, 8))
+);
+mat!(
+    match_repetition_93,
+    r"X(.?){3,}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((7, 8))
+);
+mat!(
+    match_repetition_94,
+    r"X(.?){4,}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((7, 8))
+);
+mat!(
+    match_repetition_95,
+    r"X(.?){5,}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((7, 8))
+);
+mat!(
+    match_repetition_96,
+    r"X(.?){6,}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((7, 8))
+);
+mat!(
+    match_repetition_97,
+    r"X(.?){7,}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((7, 8))
+);
+mat!(
+    match_repetition_98,
+    r"X(.?){8,}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((8, 8))
+);
+mat!(
+    match_repetition_100,
+    r"X(.?){0,8}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((8, 8))
+);
+mat!(
+    match_repetition_102,
+    r"X(.?){1,8}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((8, 8))
+);
+mat!(
+    match_repetition_104,
+    r"X(.?){2,8}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((8, 8))
+);
+mat!(
+    match_repetition_106,
+    r"X(.?){3,8}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((8, 8))
+);
+mat!(
+    match_repetition_108,
+    r"X(.?){4,8}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((8, 8))
+);
+mat!(
+    match_repetition_110,
+    r"X(.?){5,8}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((8, 8))
+);
+mat!(
+    match_repetition_112,
+    r"X(.?){6,8}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((8, 8))
+);
+mat!(
+    match_repetition_114,
+    r"X(.?){7,8}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((8, 8))
+);
+mat!(
+    match_repetition_115,
+    r"X(.?){8,8}Y",
+    r"X1234567Y",
+    Some((0, 9)),
+    Some((8, 8))
+);
+mat!(
+    match_repetition_126,
+    r"(a|ab|c|bcd){0,}(d*)",
+    r"ababcd",
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((1, 1))
+);
+mat!(
+    match_repetition_127,
+    r"(a|ab|c|bcd){1,}(d*)",
+    r"ababcd",
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((1, 1))
+);
+mat!(
+    match_repetition_128,
+    r"(a|ab|c|bcd){2,}(d*)",
+    r"ababcd",
+    Some((0, 6)),
+    Some((3, 6)),
+    Some((6, 6))
+);
+mat!(
+    match_repetition_129,
+    r"(a|ab|c|bcd){3,}(d*)",
+    r"ababcd",
+    Some((0, 6)),
+    Some((3, 6)),
+    Some((6, 6))
+);
+mat!(match_repetition_130, r"(a|ab|c|bcd){4,}(d*)", r"ababcd", None);
+mat!(
+    match_repetition_131,
+    r"(a|ab|c|bcd){0,10}(d*)",
+    r"ababcd",
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((1, 1))
+);
+mat!(
+    match_repetition_132,
+    r"(a|ab|c|bcd){1,10}(d*)",
+    r"ababcd",
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((1, 1))
+);
+mat!(
+    match_repetition_133,
+    r"(a|ab|c|bcd){2,10}(d*)",
+    r"ababcd",
+    Some((0, 6)),
+    Some((3, 6)),
+    Some((6, 6))
+);
+mat!(
+    match_repetition_134,
+    r"(a|ab|c|bcd){3,10}(d*)",
+    r"ababcd",
+    Some((0, 6)),
+    Some((3, 6)),
+    Some((6, 6))
+);
+mat!(match_repetition_135, r"(a|ab|c|bcd){4,10}(d*)", r"ababcd", None);
+mat!(
+    match_repetition_136,
+    r"(a|ab|c|bcd)*(d*)",
+    r"ababcd",
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((1, 1))
+);
+mat!(
+    match_repetition_137,
+    r"(a|ab|c|bcd)+(d*)",
+    r"ababcd",
+    Some((0, 1)),
+    Some((0, 1)),
+    Some((1, 1))
+);
+mat!(
+    match_repetition_143,
+    r"(ab|a|c|bcd){0,}(d*)",
+    r"ababcd",
+    Some((0, 6)),
+    Some((4, 5)),
+    Some((5, 6))
+);
+mat!(
+    match_repetition_145,
+    r"(ab|a|c|bcd){1,}(d*)",
+    r"ababcd",
+    Some((0, 6)),
+    Some((4, 5)),
+    Some((5, 6))
+);
+mat!(
+    match_repetition_147,
+    r"(ab|a|c|bcd){2,}(d*)",
+    r"ababcd",
+    Some((0, 6)),
+    Some((4, 5)),
+    Some((5, 6))
+);
+mat!(
+    match_repetition_149,
+    r"(ab|a|c|bcd){3,}(d*)",
+    r"ababcd",
+    Some((0, 6)),
+    Some((4, 5)),
+    Some((5, 6))
+);
+mat!(match_repetition_150, r"(ab|a|c|bcd){4,}(d*)", r"ababcd", None);
+mat!(
+    match_repetition_152,
+    r"(ab|a|c|bcd){0,10}(d*)",
+    r"ababcd",
+    Some((0, 6)),
+    Some((4, 5)),
+    Some((5, 6))
+);
+mat!(
+    match_repetition_154,
+    r"(ab|a|c|bcd){1,10}(d*)",
+    r"ababcd",
+    Some((0, 6)),
+    Some((4, 5)),
+    Some((5, 6))
+);
+mat!(
+    match_repetition_156,
+    r"(ab|a|c|bcd){2,10}(d*)",
+    r"ababcd",
+    Some((0, 6)),
+    Some((4, 5)),
+    Some((5, 6))
+);
+mat!(
+    match_repetition_158,
+    r"(ab|a|c|bcd){3,10}(d*)",
+    r"ababcd",
+    Some((0, 6)),
+    Some((4, 5)),
+    Some((5, 6))
+);
+mat!(match_repetition_159, r"(ab|a|c|bcd){4,10}(d*)", r"ababcd", None);
+mat!(
+    match_repetition_161,
+    r"(ab|a|c|bcd)*(d*)",
+    r"ababcd",
+    Some((0, 6)),
+    Some((4, 5)),
+    Some((5, 6))
+);
+mat!(
+    match_repetition_163,
+    r"(ab|a|c|bcd)+(d*)",
+    r"ababcd",
+    Some((0, 6)),
+    Some((4, 5)),
+    Some((5, 6))
+);
diff --git a/vendor/regex-1.4.6/tests/macros.rs b/vendor/regex-1.4.6/tests/macros.rs
new file mode 100644 (file)
index 0000000..e70e948
--- /dev/null
@@ -0,0 +1,160 @@
+// Convenience macros.
+
+macro_rules! findall {
+    ($re:expr, $text:expr) => {{
+        $re.find_iter(text!($text))
+           .map(|m| (m.start(), m.end())).collect::<Vec<_>>()
+    }}
+}
+
+// Macros for automatically producing tests.
+
+macro_rules! ismatch {
+    ($name:ident, $re:expr, $text:expr, $ismatch:expr) => {
+        #[test]
+        fn $name() {
+            let re = regex!($re);
+            assert_eq!($ismatch, re.is_match(text!($text)));
+        }
+    };
+}
+
+macro_rules! mat(
+    ($name:ident, $re:expr, $text:expr, $($loc:tt)+) => (
+        #[test]
+        fn $name() {
+            let text = text!($text);
+            let expected: Vec<Option<_>> = vec![$($loc)+];
+            let r = regex!($re);
+            let got: Vec<Option<_>> = match r.captures(text) {
+                Some(c) => {
+                    assert!(r.is_match(text));
+                    assert!(r.shortest_match(text).is_some());
+                    r.capture_names()
+                     .enumerate()
+                     .map(|(i, _)| c.get(i).map(|m| (m.start(), m.end())))
+                     .collect()
+                }
+                None => vec![None],
+            };
+            // The test set sometimes leave out capture groups, so truncate
+            // actual capture groups to match test set.
+            let mut sgot = &got[..];
+            if sgot.len() > expected.len() {
+                sgot = &sgot[0..expected.len()]
+            }
+            if expected != sgot {
+                panic!("For RE '{}' against '{:?}', \
+                        expected '{:?}' but got '{:?}'",
+                       $re, text, expected, sgot);
+            }
+        }
+    );
+);
+
+macro_rules! matiter(
+    ($name:ident, $re:expr, $text:expr) => (
+        #[test]
+        fn $name() {
+            let text = text!($text);
+            let expected: Vec<(usize, usize)> = vec![];
+            let r = regex!($re);
+            let got: Vec<_> =
+                r.find_iter(text).map(|m| (m.start(), m.end())).collect();
+            if expected != got {
+                panic!("For RE '{}' against '{:?}', \
+                        expected '{:?}' but got '{:?}'",
+                       $re, text, expected, got);
+            }
+            let captures_got: Vec<_> =
+                r.captures_iter(text)
+                 .map(|c| c.get(0).unwrap())
+                 .map(|m| (m.start(), m.end()))
+                 .collect();
+            if captures_got != got {
+                panic!("For RE '{}' against '{:?}', \
+                        got '{:?}' using find_iter but got '{:?}' \
+                        using captures_iter",
+                       $re, text, got, captures_got);
+            }
+        }
+    );
+    ($name:ident, $re:expr, $text:expr, $($loc:tt)+) => (
+        #[test]
+        fn $name() {
+            let text = text!($text);
+            let expected: Vec<_> = vec![$($loc)+];
+            let r = regex!($re);
+            let got: Vec<_> =
+                r.find_iter(text).map(|m| (m.start(), m.end())).collect();
+            if expected != got {
+                panic!("For RE '{}' against '{:?}', \
+                        expected '{:?}' but got '{:?}'",
+                       $re, text, expected, got);
+            }
+            let captures_got: Vec<_> =
+                r.captures_iter(text)
+                 .map(|c| c.get(0).unwrap())
+                 .map(|m| (m.start(), m.end()))
+                 .collect();
+            if captures_got != got {
+                panic!("For RE '{}' against '{:?}', \
+                        got '{:?}' using find_iter but got '{:?}' \
+                        using captures_iter",
+                       $re, text, got, captures_got);
+            }
+        }
+    );
+);
+
+macro_rules! matset {
+    ($name:ident, $res:expr, $text:expr, $($match_index:expr),*) => {
+        #[test]
+        fn $name() {
+            let text = text!($text);
+            let set = regex_set!($res);
+            assert!(set.is_match(text));
+            let expected = vec![$($match_index),*];
+            let matches = set.matches(text);
+            assert!(matches.matched_any());
+            let got: Vec<_> = matches.into_iter().collect();
+            assert_eq!(expected, got);
+        }
+    }
+}
+
+macro_rules! nomatset {
+    ($name:ident, $res:expr, $text:expr) => {
+        #[test]
+        fn $name() {
+            let text = text!($text);
+            let set = regex_set!($res);
+            assert!(!set.is_match(text));
+            let matches = set.matches(text);
+            assert!(!matches.matched_any());
+            assert_eq!(0, matches.into_iter().count());
+        }
+    }
+}
+
+macro_rules! split {
+    ($name:ident, $re:expr, $text:expr, $expected:expr) => {
+        #[test]
+        fn $name() {
+            let re = regex!($re);
+            let splitted: Vec<_> = re.split(t!($text)).collect();
+            assert_eq!($expected, &*splitted);
+        }
+    }
+}
+
+macro_rules! splitn {
+    ($name:ident, $re:expr, $text:expr, $limit:expr, $expected:expr) => {
+        #[test]
+        fn $name() {
+            let re = regex!($re);
+            let splitted: Vec<_> = re.splitn(t!($text), $limit).collect();
+            assert_eq!($expected, &*splitted);
+        }
+    }
+}
diff --git a/vendor/regex-1.4.6/tests/macros_bytes.rs b/vendor/regex-1.4.6/tests/macros_bytes.rs
new file mode 100644 (file)
index 0000000..3d6c8c3
--- /dev/null
@@ -0,0 +1,39 @@
+// Macros for use in writing tests generic over &str/&[u8].
+macro_rules! text { ($text:expr) => { $text.as_bytes() } }
+macro_rules! t { ($re:expr) => { text!($re) } }
+macro_rules! match_text { ($text:expr) => { $text.as_bytes() } }
+macro_rules! use_ { ($($path: tt)*) => { use regex::bytes::$($path)*; } }
+macro_rules! empty_vec { () => { <Vec<&[u8]>>::new() } }
+macro_rules! bytes { ($text:expr) => { $text } }
+
+macro_rules! no_expand {
+    ($text:expr) => {{
+        use regex::bytes::NoExpand;
+        NoExpand(text!($text))
+    }}
+}
+
+macro_rules! show {
+    ($text:expr) => {{
+        use std::ascii::escape_default;
+        let mut s = vec![];
+        for &b in bytes!($text) {
+            s.extend(escape_default(b));
+        }
+        String::from_utf8(s).unwrap()
+    }}
+}
+
+macro_rules! expand {
+    ($name:ident, $re:expr, $text:expr, $expand:expr, $expected:expr) => {
+        #[test]
+        fn $name() {
+            let re = regex!($re);
+            let cap = re.captures(t!($text)).unwrap();
+
+            let mut got = vec![];
+            cap.expand(t!($expand), &mut got);
+            assert_eq!(show!(t!($expected)), show!(&*got));
+        }
+    }
+}
diff --git a/vendor/regex-1.4.6/tests/macros_str.rs b/vendor/regex-1.4.6/tests/macros_str.rs
new file mode 100644 (file)
index 0000000..7b7eb11
--- /dev/null
@@ -0,0 +1,38 @@
+// Macros for use in writing tests generic over &str/&[u8].
+macro_rules! text { ($text:expr) => { $text } }
+macro_rules! t { ($text:expr) => { text!($text) } }
+macro_rules! match_text { ($text:expr) => { $text.as_str() } }
+macro_rules! use_ { ($($path: tt)*) => { use regex::$($path)*; } }
+macro_rules! empty_vec { () => { <Vec<&str>>::new() } }
+macro_rules! bytes { ($text:expr) => { std::str::from_utf8($text.as_ref()).unwrap() } }
+
+macro_rules! no_expand {
+    ($text:expr) => {{
+        use regex::NoExpand;
+        NoExpand(text!($text))
+    }}
+}
+
+macro_rules! show { ($text:expr) => { $text } }
+
+// N.B. The expansion API for &str and &[u8] APIs differs slightly for now,
+// but they should be unified in 1.0. Then we can move this macro back into
+// tests/api.rs where it is used. ---AG
+macro_rules! expand {
+    ($name:ident, $re:expr, $text:expr, $expand:expr, $expected:expr) => {
+        #[test]
+        fn $name() {
+            let re = regex!($re);
+            let cap = re.captures(t!($text)).unwrap();
+
+            let mut got = String::new();
+            cap.expand(t!($expand), &mut got);
+            assert_eq!(show!(t!($expected)), show!(&*got));
+        }
+    }
+}
+
+#[cfg(feature = "pattern")]
+macro_rules! searcher_expr { ($e:expr) => ($e) }
+#[cfg(not(feature = "pattern"))]
+macro_rules! searcher_expr { ($e:expr) => ({}) }
diff --git a/vendor/regex-1.4.6/tests/misc.rs b/vendor/regex-1.4.6/tests/misc.rs
new file mode 100644 (file)
index 0000000..314811e
--- /dev/null
@@ -0,0 +1,4 @@
+mat!(prefix_literal_match, r"^abc", r"abc", Some((0, 3)));
+mat!(prefix_literal_nomatch, r"^abc", r"zabc", None);
+mat!(one_literal_edge, r"abc", r"xxxxxab", None);
+matiter!(terminates, r"a$", r"a", (0, 1));
diff --git a/vendor/regex-1.4.6/tests/multiline.rs b/vendor/regex-1.4.6/tests/multiline.rs
new file mode 100644 (file)
index 0000000..62ee47b
--- /dev/null
@@ -0,0 +1,144 @@
+matiter!(
+    match_multi_1,
+    r"(?m)^[a-z]+$",
+    "abc\ndef\nxyz",
+    (0, 3),
+    (4, 7),
+    (8, 11)
+);
+matiter!(match_multi_2, r"(?m)^$", "abc\ndef\nxyz");
+matiter!(match_multi_3, r"(?m)^", "abc\ndef\nxyz", (0, 0), (4, 4), (8, 8));
+matiter!(match_multi_4, r"(?m)$", "abc\ndef\nxyz", (3, 3), (7, 7), (11, 11));
+matiter!(
+    match_multi_5,
+    r"(?m)^[a-z]",
+    "abc\ndef\nxyz",
+    (0, 1),
+    (4, 5),
+    (8, 9)
+);
+matiter!(match_multi_6, r"(?m)[a-z]^", "abc\ndef\nxyz");
+matiter!(
+    match_multi_7,
+    r"(?m)[a-z]$",
+    "abc\ndef\nxyz",
+    (2, 3),
+    (6, 7),
+    (10, 11)
+);
+matiter!(match_multi_8, r"(?m)$[a-z]", "abc\ndef\nxyz");
+matiter!(match_multi_9, r"(?m)^$", "", (0, 0));
+
+matiter!(
+    match_multi_rep_1,
+    r"(?m)(?:^$)*",
+    "a\nb\nc",
+    (0, 0),
+    (1, 1),
+    (2, 2),
+    (3, 3),
+    (4, 4),
+    (5, 5)
+);
+matiter!(
+    match_multi_rep_2,
+    r"(?m)(?:^|a)+",
+    "a\naaa\n",
+    (0, 0),
+    (2, 2),
+    (3, 5),
+    (6, 6)
+);
+matiter!(
+    match_multi_rep_3,
+    r"(?m)(?:^|a)*",
+    "a\naaa\n",
+    (0, 1),
+    (2, 5),
+    (6, 6)
+);
+matiter!(
+    match_multi_rep_4,
+    r"(?m)(?:^[a-z])+",
+    "abc\ndef\nxyz",
+    (0, 1),
+    (4, 5),
+    (8, 9)
+);
+matiter!(
+    match_multi_rep_5,
+    r"(?m)(?:^[a-z]{3}\n?)+",
+    "abc\ndef\nxyz",
+    (0, 11)
+);
+matiter!(
+    match_multi_rep_6,
+    r"(?m)(?:^[a-z]{3}\n?)*",
+    "abc\ndef\nxyz",
+    (0, 11)
+);
+matiter!(
+    match_multi_rep_7,
+    r"(?m)(?:\n?[a-z]{3}$)+",
+    "abc\ndef\nxyz",
+    (0, 11)
+);
+matiter!(
+    match_multi_rep_8,
+    r"(?m)(?:\n?[a-z]{3}$)*",
+    "abc\ndef\nxyz",
+    (0, 11)
+);
+matiter!(
+    match_multi_rep_9,
+    r"(?m)^*",
+    "\naa\n",
+    (0, 0),
+    (1, 1),
+    (2, 2),
+    (3, 3),
+    (4, 4)
+);
+matiter!(match_multi_rep_10, r"(?m)^+", "\naa\n", (0, 0), (1, 1), (4, 4));
+matiter!(
+    match_multi_rep_11,
+    r"(?m)$*",
+    "\naa\n",
+    (0, 0),
+    (1, 1),
+    (2, 2),
+    (3, 3),
+    (4, 4)
+);
+matiter!(match_multi_rep_12, r"(?m)$+", "\naa\n", (0, 0), (3, 3), (4, 4));
+matiter!(match_multi_rep_13, r"(?m)(?:$\n)+", "\n\naaa\n\n", (0, 2), (5, 7));
+matiter!(
+    match_multi_rep_14,
+    r"(?m)(?:$\n)*",
+    "\n\naaa\n\n",
+    (0, 2),
+    (3, 3),
+    (4, 4),
+    (5, 7)
+);
+matiter!(match_multi_rep_15, r"(?m)(?:$\n^)+", "\n\naaa\n\n", (0, 2), (5, 7));
+matiter!(
+    match_multi_rep_16,
+    r"(?m)(?:^|$)+",
+    "\n\naaa\n\n",
+    (0, 0),
+    (1, 1),
+    (2, 2),
+    (5, 5),
+    (6, 6),
+    (7, 7)
+);
+matiter!(
+    match_multi_rep_17,
+    r"(?m)(?:$\n)*",
+    "\n\naaa\n\n",
+    (0, 2),
+    (3, 3),
+    (4, 4),
+    (5, 7)
+);
diff --git a/vendor/regex-1.4.6/tests/noparse.rs b/vendor/regex-1.4.6/tests/noparse.rs
new file mode 100644 (file)
index 0000000..8ded1dc
--- /dev/null
@@ -0,0 +1,45 @@
+macro_rules! noparse(
+    ($name:ident, $re:expr) => (
+        #[test]
+        fn $name() {
+            let re = $re;
+            match regex_new!(re) {
+                Err(_) => {},
+                Ok(_) => panic!("Regex '{}' should cause a parse error.", re),
+            }
+        }
+    );
+);
+
+noparse!(fail_no_repeat_arg, "*");
+noparse!(fail_incomplete_escape, "\\");
+noparse!(fail_class_incomplete, "[A-");
+noparse!(fail_class_not_closed, "[A");
+noparse!(fail_class_no_begin, r"[\A]");
+noparse!(fail_class_no_end, r"[\z]");
+noparse!(fail_class_no_boundary, r"[\b]");
+noparse!(fail_open_paren, "(");
+noparse!(fail_close_paren, ")");
+noparse!(fail_invalid_range, "[a-Z]");
+noparse!(fail_empty_capture_name, "(?P<>a)");
+noparse!(fail_bad_capture_name, "(?P<na-me>)");
+noparse!(fail_bad_flag, "(?a)a");
+noparse!(fail_too_big, "a{10000000}");
+noparse!(fail_counted_no_close, "a{1001");
+noparse!(fail_counted_decreasing, "a{2,1}");
+noparse!(fail_counted_nonnegative, "a{-1,1}");
+noparse!(fail_unfinished_cap, "(?");
+noparse!(fail_unfinished_escape, "\\");
+noparse!(fail_octal_digit, r"\8");
+noparse!(fail_hex_digit, r"\xG0");
+noparse!(fail_hex_short, r"\xF");
+noparse!(fail_hex_long_digits, r"\x{fffg}");
+noparse!(fail_flag_bad, "(?a)");
+noparse!(fail_flag_empty, "(?)");
+noparse!(fail_double_neg, "(?-i-i)");
+noparse!(fail_neg_empty, "(?i-)");
+noparse!(fail_dupe_named, "(?P<a>.)(?P<a>.)");
+noparse!(fail_range_end_no_class, "[a-[:lower:]]");
+noparse!(fail_range_end_no_begin, r"[a-\A]");
+noparse!(fail_range_end_no_end, r"[a-\z]");
+noparse!(fail_range_end_no_boundary, r"[a-\b]");
diff --git a/vendor/regex-1.4.6/tests/regression.rs b/vendor/regex-1.4.6/tests/regression.rs
new file mode 100644 (file)
index 0000000..44b9083
--- /dev/null
@@ -0,0 +1,219 @@
+// See: https://github.com/rust-lang/regex/issues/48
+#[test]
+fn invalid_regexes_no_crash() {
+    assert!(regex_new!("(*)").is_err());
+    assert!(regex_new!("(?:?)").is_err());
+    assert!(regex_new!("(?)").is_err());
+    assert!(regex_new!("*").is_err());
+}
+
+// See: https://github.com/rust-lang/regex/issues/98
+#[test]
+fn regression_many_repeat_stack_overflow() {
+    let re = regex!("^.{1,2500}");
+    assert_eq!(vec![(0, 1)], findall!(re, "a"));
+}
+
+// See: https://github.com/rust-lang/regex/issues/555
+#[test]
+fn regression_invalid_repetition_expr() {
+    assert!(regex_new!("(?m){1,1}").is_err());
+}
+
+// See: https://github.com/rust-lang/regex/issues/527
+#[test]
+fn regression_invalid_flags_expression() {
+    assert!(regex_new!("(((?x)))").is_ok());
+}
+
+// See: https://github.com/rust-lang/regex/issues/75
+mat!(regression_unsorted_binary_search_1, r"(?i-u)[a_]+", "A_", Some((0, 2)));
+mat!(regression_unsorted_binary_search_2, r"(?i-u)[A_]+", "a_", Some((0, 2)));
+
+// See: https://github.com/rust-lang/regex/issues/99
+#[cfg(feature = "unicode-case")]
+mat!(regression_negated_char_class_1, r"(?i)[^x]", "x", None);
+#[cfg(feature = "unicode-case")]
+mat!(regression_negated_char_class_2, r"(?i)[^x]", "X", None);
+
+// See: https://github.com/rust-lang/regex/issues/101
+mat!(regression_ascii_word_underscore, r"[[:word:]]", "_", Some((0, 1)));
+
+// See: https://github.com/rust-lang/regex/issues/129
+#[test]
+fn regression_captures_rep() {
+    let re = regex!(r"([a-f]){2}(?P<foo>[x-z])");
+    let caps = re.captures(text!("abx")).unwrap();
+    assert_eq!(match_text!(caps.name("foo").unwrap()), text!("x"));
+}
+
+// See: https://github.com/rust-lang/regex/issues/153
+mat!(regression_alt_in_alt1, r"ab?|$", "az", Some((0, 1)));
+mat!(regression_alt_in_alt2, r"^(.*?)(\n|\r\n?|$)", "ab\rcd", Some((0, 3)));
+
+// See: https://github.com/rust-lang/regex/issues/169
+mat!(regression_leftmost_first_prefix, r"z*azb", "azb", Some((0, 3)));
+
+// See: https://github.com/rust-lang/regex/issues/76
+#[cfg(all(feature = "unicode-case", feature = "unicode-gencat"))]
+mat!(uni_case_lower_nocase_flag, r"(?i)\p{Ll}+", "ΛΘΓΔα", Some((0, 10)));
+
+// See: https://github.com/rust-lang/regex/issues/191
+mat!(many_alternates, r"1|2|3|4|5|6|7|8|9|10|int", "int", Some((0, 3)));
+
+// burntsushi was bad and didn't create an issue for this bug.
+mat!(anchored_prefix1, r"^a[[:^space:]]", "a ", None);
+mat!(anchored_prefix2, r"^a[[:^space:]]", "foo boo a ", None);
+mat!(anchored_prefix3, r"^-[a-z]", "r-f", None);
+
+// See: https://github.com/rust-lang/regex/issues/204
+#[cfg(feature = "unicode-perl")]
+split!(
+    split_on_word_boundary,
+    r"\b",
+    r"Should this (work?)",
+    &[
+        t!(""),
+        t!("Should"),
+        t!(" "),
+        t!("this"),
+        t!(" ("),
+        t!("work"),
+        t!("?)")
+    ]
+);
+#[cfg(feature = "unicode-perl")]
+matiter!(
+    word_boundary_dfa,
+    r"\b",
+    "a b c",
+    (0, 0),
+    (1, 1),
+    (2, 2),
+    (3, 3),
+    (4, 4),
+    (5, 5)
+);
+
+// See: https://github.com/rust-lang/regex/issues/268
+matiter!(partial_anchor, r"^a|b", "ba", (0, 1));
+
+// See: https://github.com/rust-lang/regex/issues/280
+ismatch!(partial_anchor_alternate_begin, r"^a|z", "yyyyya", false);
+ismatch!(partial_anchor_alternate_end, r"a$|z", "ayyyyy", false);
+
+// See: https://github.com/rust-lang/regex/issues/289
+mat!(lits_unambiguous1, r"(ABC|CDA|BC)X", "CDAX", Some((0, 4)));
+
+// See: https://github.com/rust-lang/regex/issues/291
+mat!(
+    lits_unambiguous2,
+    r"((IMG|CAM|MG|MB2)_|(DSCN|CIMG))(?P<n>[0-9]+)$",
+    "CIMG2341",
+    Some((0, 8)),
+    Some((0, 4)),
+    None,
+    Some((0, 4)),
+    Some((4, 8))
+);
+
+// See: https://github.com/rust-lang/regex/issues/271
+mat!(endl_or_wb, r"(?m:$)|(?-u:\b)", "\u{6084e}", Some((4, 4)));
+mat!(zero_or_end, r"(?i-u:\x00)|$", "\u{e682f}", Some((4, 4)));
+mat!(y_or_endl, r"(?i-u:y)|(?m:$)", "\u{b4331}", Some((4, 4)));
+#[cfg(feature = "unicode-perl")]
+mat!(wb_start_x, r"(?u:\b)^(?-u:X)", "X", Some((0, 1)));
+
+// See: https://github.com/rust-lang/regex/issues/321
+ismatch!(strange_anchor_non_complete_prefix, r"a^{2}", "", false);
+ismatch!(strange_anchor_non_complete_suffix, r"${2}a", "", false);
+
+// See: https://github.com/BurntSushi/ripgrep/issues/1203
+ismatch!(reverse_suffix1, r"[0-4][0-4][0-4]000", "153.230000", true);
+ismatch!(reverse_suffix2, r"[0-9][0-9][0-9]000", "153.230000\n", true);
+matiter!(reverse_suffix3, r"[0-9][0-9][0-9]000", "153.230000\n", (4, 10));
+
+// See: https://github.com/rust-lang/regex/issues/334
+// See: https://github.com/rust-lang/regex/issues/557
+mat!(
+    captures_after_dfa_premature_end1,
+    r"a(b*(X|$))?",
+    "abcbX",
+    Some((0, 1)),
+    None,
+    None
+);
+mat!(
+    captures_after_dfa_premature_end2,
+    r"a(bc*(X|$))?",
+    "abcbX",
+    Some((0, 1)),
+    None,
+    None
+);
+mat!(captures_after_dfa_premature_end3, r"(aa$)?", "aaz", Some((0, 0)));
+
+// See: https://github.com/rust-lang/regex/issues/437
+ismatch!(
+    literal_panic,
+    r"typename type\-parameter\-[0-9]+\-[0-9]+::.+",
+    "test",
+    false
+);
+
+// See: https://github.com/rust-lang/regex/issues/533
+ismatch!(
+    blank_matches_nothing_between_space_and_tab,
+    r"[[:blank:]]",
+    "\u{a}\u{b}\u{c}\u{d}\u{e}\u{f}\
+     \u{10}\u{11}\u{12}\u{13}\u{14}\u{15}\u{16}\u{17}\
+     \u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f}",
+    false
+);
+
+ismatch!(
+    inverted_blank_matches_everything_between_space_and_tab,
+    r"^[[:^blank:]]+$",
+    "\u{a}\u{b}\u{c}\u{d}\u{e}\u{f}\
+     \u{10}\u{11}\u{12}\u{13}\u{14}\u{15}\u{16}\u{17}\
+     \u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f}",
+    true
+);
+
+// Tests that our Aho-Corasick optimization works correctly. It only
+// kicks in when we have >32 literals. By "works correctly," we mean that
+// leftmost-first match semantics are properly respected. That is, samwise
+// should match, not sam.
+mat!(
+    ahocorasick1,
+    "samwise|sam|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|\
+     A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z",
+    "samwise",
+    Some((0, 7))
+);
+
+// See: https://github.com/BurntSushi/ripgrep/issues/1247
+#[test]
+#[cfg(feature = "unicode-perl")]
+fn regression_nfa_stops1() {
+    let re = ::regex::bytes::Regex::new(r"\bs(?:[ab])").unwrap();
+    assert_eq!(0, re.find_iter(b"s\xE4").count());
+}
+
+// See: https://github.com/rust-lang/regex/issues/640
+#[cfg(feature = "unicode-case")]
+matiter!(
+    flags_are_unset,
+    r"((?i)foo)|Bar",
+    "foo Foo bar Bar",
+    (0, 3),
+    (4, 7),
+    (12, 15)
+);
+
+// See: https://github.com/rust-lang/regex/issues/659
+//
+// Note that 'Ј' is not 'j', but cyrillic Je
+// https://en.wikipedia.org/wiki/Je_(Cyrillic)
+ismatch!(empty_group_match, r"()Ј01", "zЈ01", true);
+matiter!(empty_group_find, r"()Ј01", "zЈ01", (1, 5));
diff --git a/vendor/regex-1.4.6/tests/regression_fuzz.rs b/vendor/regex-1.4.6/tests/regression_fuzz.rs
new file mode 100644 (file)
index 0000000..4e76704
--- /dev/null
@@ -0,0 +1,31 @@
+// These tests are only run for the "default" test target because some of them
+// can take quite a long time. Some of them take long enough that it's not
+// practical to run them in debug mode. :-/
+
+// See: https://oss-fuzz.com/testcase-detail/5673225499181056
+//
+// Ignored by default since it takes too long in debug mode (almost a minute).
+#[test]
+#[ignore]
+fn fuzz1() {
+    regex!(r"1}{55}{0}*{1}{55}{55}{5}*{1}{55}+{56}|;**");
+}
+
+// See: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=26505
+// See: https://github.com/rust-lang/regex/issues/722
+#[test]
+fn empty_any_errors_no_panic() {
+    assert!(regex_new!(r"\P{any}").is_err());
+}
+
+// This tests that a very large regex errors during compilation instead of
+// using gratuitous amounts of memory. The specific problem is that the
+// compiler wasn't accounting for the memory used by Unicode character classes
+// correctly.
+//
+// See: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=33579
+#[test]
+fn big_regex_fails_to_compile() {
+    let pat = "[\u{0}\u{e}\u{2}\\w~~>[l\t\u{0}]p?<]{971158}";
+    assert!(regex_new!(pat).is_err());
+}
diff --git a/vendor/regex-1.4.6/tests/replace.rs b/vendor/regex-1.4.6/tests/replace.rs
new file mode 100644 (file)
index 0000000..700aff2
--- /dev/null
@@ -0,0 +1,230 @@
+macro_rules! replace(
+    ($name:ident, $which:ident, $re:expr,
+     $search:expr, $replace:expr, $result:expr) => (
+        #[test]
+        fn $name() {
+            let re = regex!($re);
+            assert_eq!(re.$which(text!($search), $replace), text!($result));
+        }
+    );
+);
+
+replace!(first, replace, r"[0-9]", "age: 26", t!("Z"), "age: Z6");
+replace!(plus, replace, r"[0-9]+", "age: 26", t!("Z"), "age: Z");
+replace!(all, replace_all, r"[0-9]", "age: 26", t!("Z"), "age: ZZ");
+replace!(
+    groups,
+    replace,
+    r"(?-u)(\S+)\s+(\S+)",
+    "w1 w2",
+    t!("$2 $1"),
+    "w2 w1"
+);
+replace!(
+    double_dollar,
+    replace,
+    r"(?-u)(\S+)\s+(\S+)",
+    "w1 w2",
+    t!("$2 $$1"),
+    "w2 $1"
+);
+// replace!(adjacent_index, replace,
+// r"([^aeiouy])ies$", "skies", t!("$1y"), "sky");
+replace!(
+    named,
+    replace_all,
+    r"(?-u)(?P<first>\S+)\s+(?P<last>\S+)(?P<space>\s*)",
+    "w1 w2 w3 w4",
+    t!("$last $first$space"),
+    "w2 w1 w4 w3"
+);
+replace!(
+    trim,
+    replace_all,
+    "^[ \t]+|[ \t]+$",
+    " \t  trim me\t   \t",
+    t!(""),
+    "trim me"
+);
+replace!(number_hypen, replace, r"(.)(.)", "ab", t!("$1-$2"), "a-b");
+// replace!(number_underscore, replace, r"(.)(.)", "ab", t!("$1_$2"), "a_b");
+replace!(
+    simple_expand,
+    replace_all,
+    r"(?-u)(\w) (\w)",
+    "a b",
+    t!("$2 $1"),
+    "b a"
+);
+replace!(
+    literal_dollar1,
+    replace_all,
+    r"(?-u)(\w+) (\w+)",
+    "a b",
+    t!("$$1"),
+    "$1"
+);
+replace!(
+    literal_dollar2,
+    replace_all,
+    r"(?-u)(\w+) (\w+)",
+    "a b",
+    t!("$2 $$c $1"),
+    "b $c a"
+);
+replace!(
+    no_expand1,
+    replace,
+    r"(?-u)(\S+)\s+(\S+)",
+    "w1 w2",
+    no_expand!("$2 $1"),
+    "$2 $1"
+);
+replace!(
+    no_expand2,
+    replace,
+    r"(?-u)(\S+)\s+(\S+)",
+    "w1 w2",
+    no_expand!("$$1"),
+    "$$1"
+);
+use_!(Captures);
+replace!(
+    closure_returning_reference,
+    replace,
+    r"([0-9]+)",
+    "age: 26",
+    |captures: &Captures| {
+        match_text!(captures.get(1).unwrap())[0..1].to_owned()
+    },
+    "age: 2"
+);
+replace!(
+    closure_returning_value,
+    replace,
+    r"[0-9]+",
+    "age: 26",
+    |_captures: &Captures| t!("Z").to_owned(),
+    "age: Z"
+);
+
+// See https://github.com/rust-lang/regex/issues/314
+replace!(
+    match_at_start_replace_with_empty,
+    replace_all,
+    r"foo",
+    "foobar",
+    t!(""),
+    "bar"
+);
+
+// See https://github.com/rust-lang/regex/issues/393
+replace!(single_empty_match, replace, r"^", "bar", t!("foo"), "foobar");
+
+// See https://github.com/rust-lang/regex/issues/399
+replace!(
+    capture_longest_possible_name,
+    replace_all,
+    r"(.)",
+    "b",
+    t!("${1}a $1a"),
+    "ba "
+);
+
+replace!(
+    impl_string,
+    replace,
+    r"[0-9]",
+    "age: 26",
+    t!("Z".to_string()),
+    "age: Z6"
+);
+replace!(
+    impl_string_ref,
+    replace,
+    r"[0-9]",
+    "age: 26",
+    t!(&"Z".to_string()),
+    "age: Z6"
+);
+replace!(
+    impl_cow_str_borrowed,
+    replace,
+    r"[0-9]",
+    "age: 26",
+    t!(std::borrow::Cow::<'_, str>::Borrowed("Z")),
+    "age: Z6"
+);
+replace!(
+    impl_cow_str_borrowed_ref,
+    replace,
+    r"[0-9]",
+    "age: 26",
+    t!(&std::borrow::Cow::<'_, str>::Borrowed("Z")),
+    "age: Z6"
+);
+replace!(
+    impl_cow_str_owned,
+    replace,
+    r"[0-9]",
+    "age: 26",
+    t!(std::borrow::Cow::<'_, str>::Owned("Z".to_string())),
+    "age: Z6"
+);
+replace!(
+    impl_cow_str_owned_ref,
+    replace,
+    r"[0-9]",
+    "age: 26",
+    t!(&std::borrow::Cow::<'_, str>::Owned("Z".to_string())),
+    "age: Z6"
+);
+
+replace!(
+    impl_vec_u8,
+    replace,
+    r"[0-9]",
+    "age: 26",
+    bytes!(vec![b'Z']),
+    "age: Z6"
+);
+replace!(
+    impl_vec_u8_ref,
+    replace,
+    r"[0-9]",
+    "age: 26",
+    bytes!(&vec![b'Z']),
+    "age: Z6"
+);
+replace!(
+    impl_cow_slice_borrowed,
+    replace,
+    r"[0-9]",
+    "age: 26",
+    bytes!(std::borrow::Cow::<'_, [u8]>::Borrowed(&[b'Z'])),
+    "age: Z6"
+);
+replace!(
+    impl_cow_slice_borrowed_ref,
+    replace,
+    r"[0-9]",
+    "age: 26",
+    bytes!(&std::borrow::Cow::<'_, [u8]>::Borrowed(&[b'Z'])),
+    "age: Z6"
+);
+replace!(
+    impl_cow_slice_owned,
+    replace,
+    r"[0-9]",
+    "age: 26",
+    bytes!(std::borrow::Cow::<'_, [u8]>::Owned(vec![b'Z'])),
+    "age: Z6"
+);
+replace!(
+    impl_cow_slice_owned_ref,
+    replace,
+    r"[0-9]",
+    "age: 26",
+    bytes!(&std::borrow::Cow::<'_, [u8]>::Owned(vec![b'Z'])),
+    "age: Z6"
+);
diff --git a/vendor/regex-1.4.6/tests/searcher.rs b/vendor/regex-1.4.6/tests/searcher.rs
new file mode 100644 (file)
index 0000000..3779f54
--- /dev/null
@@ -0,0 +1,95 @@
+macro_rules! searcher {
+    ($name:ident, $re:expr, $haystack:expr) => (
+        searcher!($name, $re, $haystack, vec vec![]);
+    );
+    ($name:ident, $re:expr, $haystack:expr, $($steps:expr,)*) => (
+        searcher!($name, $re, $haystack, vec vec![$($steps),*]);
+    );
+    ($name:ident, $re:expr, $haystack:expr, $($steps:expr),*) => (
+        searcher!($name, $re, $haystack, vec vec![$($steps),*]);
+    );
+    ($name:ident, $re:expr, $haystack:expr, vec $expect_steps:expr) => (
+        #[test]
+        #[allow(unused_imports)]
+        fn $name() {
+            searcher_expr! {{
+                use std::str::pattern::{Pattern, Searcher};
+                use std::str::pattern::SearchStep::{Match, Reject, Done};
+                let re = regex!($re);
+                let mut se = re.into_searcher($haystack);
+                let mut got_steps = vec![];
+                loop {
+                    match se.next() {
+                        Done => break,
+                        step => { got_steps.push(step); }
+                    }
+                }
+                assert_eq!(got_steps, $expect_steps);
+            }}
+        }
+    );
+}
+
+searcher!(searcher_empty_regex_empty_haystack, r"", "", Match(0, 0));
+searcher!(
+    searcher_empty_regex,
+    r"",
+    "ab",
+    Match(0, 0),
+    Reject(0, 1),
+    Match(1, 1),
+    Reject(1, 2),
+    Match(2, 2)
+);
+searcher!(searcher_empty_haystack, r"\d", "");
+searcher!(searcher_one_match, r"\d", "5", Match(0, 1));
+searcher!(searcher_no_match, r"\d", "a", Reject(0, 1));
+searcher!(
+    searcher_two_adjacent_matches,
+    r"\d",
+    "56",
+    Match(0, 1),
+    Match(1, 2)
+);
+searcher!(
+    searcher_two_non_adjacent_matches,
+    r"\d",
+    "5a6",
+    Match(0, 1),
+    Reject(1, 2),
+    Match(2, 3)
+);
+searcher!(searcher_reject_first, r"\d", "a6", Reject(0, 1), Match(1, 2));
+searcher!(
+    searcher_one_zero_length_matches,
+    r"\d*",
+    "a1b2",
+    Match(0, 0),  // ^
+    Reject(0, 1), // a
+    Match(1, 2),  // a1
+    Reject(2, 3), // a1b
+    Match(3, 4),  // a1b2
+);
+searcher!(
+    searcher_many_zero_length_matches,
+    r"\d*",
+    "a1bbb2",
+    Match(0, 0),  // ^
+    Reject(0, 1), // a
+    Match(1, 2),  // a1
+    Reject(2, 3), // a1b
+    Match(3, 3),  // a1bb
+    Reject(3, 4), // a1bb
+    Match(4, 4),  // a1bbb
+    Reject(4, 5), // a1bbb
+    Match(5, 6),  // a1bbba
+);
+searcher!(
+    searcher_unicode,
+    r".+?",
+    "Ⅰ1Ⅱ2",
+    Match(0, 3),
+    Match(3, 4),
+    Match(4, 7),
+    Match(7, 8)
+);
diff --git a/vendor/regex-1.4.6/tests/set.rs b/vendor/regex-1.4.6/tests/set.rs
new file mode 100644 (file)
index 0000000..37fcf87
--- /dev/null
@@ -0,0 +1,67 @@
+matset!(set1, &["a", "a"], "a", 0, 1);
+matset!(set2, &["a", "a"], "ba", 0, 1);
+matset!(set3, &["a", "b"], "a", 0);
+matset!(set4, &["a", "b"], "b", 1);
+matset!(set5, &["a|b", "b|a"], "b", 0, 1);
+matset!(set6, &["foo", "oo"], "foo", 0, 1);
+matset!(set7, &["^foo", "bar$"], "foo", 0);
+matset!(set8, &["^foo", "bar$"], "foo bar", 0, 1);
+matset!(set9, &["^foo", "bar$"], "bar", 1);
+matset!(set10, &[r"[a-z]+$", "foo"], "01234 foo", 0, 1);
+matset!(set11, &[r"[a-z]+$", "foo"], "foo 01234", 1);
+matset!(set12, &[r".*?", "a"], "zzzzzza", 0, 1);
+matset!(set13, &[r".*", "a"], "zzzzzza", 0, 1);
+matset!(set14, &[r".*", "a"], "zzzzzz", 0);
+matset!(set15, &[r"(?-u)\ba\b"], "hello a bye", 0);
+matset!(set16, &["a"], "a", 0);
+matset!(set17, &[".*a"], "a", 0);
+matset!(set18, &["a", "β"], "β", 1);
+
+// regexes that match the empty string
+matset!(setempty1, &["", "a"], "abc", 0, 1);
+matset!(setempty2, &["", "b"], "abc", 0, 1);
+matset!(setempty3, &["", "z"], "abc", 0);
+matset!(setempty4, &["a", ""], "abc", 0, 1);
+matset!(setempty5, &["b", ""], "abc", 0, 1);
+matset!(setempty6, &["z", ""], "abc", 1);
+matset!(setempty7, &["b", "(?:)"], "abc", 0, 1);
+matset!(setempty8, &["(?:)", "b"], "abc", 0, 1);
+matset!(setempty9, &["c(?:)", "b"], "abc", 0, 1);
+
+nomatset!(nset1, &["a", "a"], "b");
+nomatset!(nset2, &["^foo", "bar$"], "bar foo");
+nomatset!(
+    nset3,
+    {
+        let xs: &[&str] = &[];
+        xs
+    },
+    "a"
+);
+nomatset!(nset4, &[r"^rooted$", r"\.log$"], "notrooted");
+
+// See: https://github.com/rust-lang/regex/issues/187
+#[test]
+fn regression_subsequent_matches() {
+    let set = regex_set!(&["ab", "b"]);
+    let text = text!("ba");
+    assert!(set.matches(text).matched(1));
+    assert!(set.matches(text).matched(1));
+}
+
+#[test]
+fn get_set_patterns() {
+    let set = regex_set!(&["a", "b"]);
+    assert_eq!(vec!["a", "b"], set.patterns());
+}
+
+#[test]
+fn len_and_empty() {
+    let empty = regex_set!(&[""; 0]);
+    assert_eq!(empty.len(), 0);
+    assert!(empty.is_empty());
+
+    let not_empty = regex_set!(&["ab", "b"]);
+    assert_eq!(not_empty.len(), 2);
+    assert!(!not_empty.is_empty());
+}
diff --git a/vendor/regex-1.4.6/tests/shortest_match.rs b/vendor/regex-1.4.6/tests/shortest_match.rs
new file mode 100644 (file)
index 0000000..f8b4fed
--- /dev/null
@@ -0,0 +1,14 @@
+macro_rules! shortmat {
+    ($name:ident, $re:expr, $text:expr, $shortest_match:expr) => {
+        #[test]
+        fn $name() {
+            let text = text!($text);
+            let re = regex!($re);
+            assert_eq!($shortest_match, re.shortest_match(text));
+        }
+    };
+}
+
+shortmat!(t01, r"a+", r"aa", Some(1));
+// Test that the reverse suffix optimization gets it right.
+shortmat!(t02, r".*(?:abcd)+", r"abcdabcd", Some(4));
diff --git a/vendor/regex-1.4.6/tests/suffix_reverse.rs b/vendor/regex-1.4.6/tests/suffix_reverse.rs
new file mode 100644 (file)
index 0000000..774c9e8
--- /dev/null
@@ -0,0 +1,6 @@
+mat!(t01, r".*abcd", r"abcd", Some((0, 4)));
+mat!(t02, r".*(?:abcd)+", r"abcd", Some((0, 4)));
+mat!(t03, r".*(?:abcd)+", r"abcdabcd", Some((0, 8)));
+mat!(t04, r".*(?:abcd)+", r"abcdxabcd", Some((0, 9)));
+mat!(t05, r".*x(?:abcd)+", r"abcdxabcd", Some((0, 9)));
+mat!(t06, r"[^abcd]*x(?:abcd)+", r"abcdxabcd", Some((4, 9)));
diff --git a/vendor/regex-1.4.6/tests/test_backtrack.rs b/vendor/regex-1.4.6/tests/test_backtrack.rs
new file mode 100644 (file)
index 0000000..617185f
--- /dev/null
@@ -0,0 +1,59 @@
+#![cfg_attr(feature = "pattern", feature(pattern))]
+
+extern crate rand;
+extern crate regex;
+
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new($re)
+            .bounded_backtracking()
+            .build()
+            .map(|e| e.into_regex())
+    }};
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    };
+}
+
+macro_rules! regex_set_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new_many($re)
+            .bounded_backtracking()
+            .build()
+            .map(|e| e.into_regex_set())
+    }};
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    };
+}
+
+// Must come before other module definitions.
+include!("macros_str.rs");
+include!("macros.rs");
+
+mod api;
+mod api_str;
+mod crazy;
+mod flags;
+mod fowler;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod searcher;
+mod set;
+mod suffix_reverse;
+#[cfg(feature = "unicode")]
+mod unicode;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary_unicode;
diff --git a/vendor/regex-1.4.6/tests/test_backtrack_bytes.rs b/vendor/regex-1.4.6/tests/test_backtrack_bytes.rs
new file mode 100644 (file)
index 0000000..17df4d8
--- /dev/null
@@ -0,0 +1,58 @@
+extern crate rand;
+extern crate regex;
+
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new($re)
+            .bounded_backtracking()
+            .only_utf8(false)
+            .build()
+            .map(|e| e.into_byte_regex())
+    }};
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    };
+}
+
+macro_rules! regex_set_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new_many($re)
+            .bounded_backtracking()
+            .only_utf8(false)
+            .build()
+            .map(|e| e.into_byte_regex_set())
+    }};
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    };
+}
+
+// Must come before other module definitions.
+include!("macros_bytes.rs");
+include!("macros.rs");
+
+mod api;
+mod bytes;
+mod crazy;
+mod flags;
+mod fowler;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod set;
+mod suffix_reverse;
+#[cfg(feature = "unicode")]
+mod unicode;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary_ascii;
diff --git a/vendor/regex-1.4.6/tests/test_backtrack_utf8bytes.rs b/vendor/regex-1.4.6/tests/test_backtrack_utf8bytes.rs
new file mode 100644 (file)
index 0000000..78a0135
--- /dev/null
@@ -0,0 +1,61 @@
+#![cfg_attr(feature = "pattern", feature(pattern))]
+
+extern crate rand;
+extern crate regex;
+
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new($re)
+            .bounded_backtracking()
+            .bytes(true)
+            .build()
+            .map(|e| e.into_regex())
+    }};
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    };
+}
+
+macro_rules! regex_set_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new_many($re)
+            .bounded_backtracking()
+            .bytes(true)
+            .build()
+            .map(|e| e.into_regex_set())
+    }};
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    };
+}
+
+// Must come before other module definitions.
+include!("macros_str.rs");
+include!("macros.rs");
+
+mod api;
+mod api_str;
+mod crazy;
+mod flags;
+mod fowler;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod searcher;
+mod set;
+mod suffix_reverse;
+#[cfg(feature = "unicode")]
+mod unicode;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary_unicode;
diff --git a/vendor/regex-1.4.6/tests/test_crates_regex.rs b/vendor/regex-1.4.6/tests/test_crates_regex.rs
new file mode 100644 (file)
index 0000000..d697683
--- /dev/null
@@ -0,0 +1,57 @@
+extern crate quickcheck;
+extern crate regex;
+
+/*
+ * This test is a minimal version of <rofl_0> and <subdiff_0>
+ *
+ * Once this bug gets fixed, uncomment rofl_0 and subdiff_0
+ * (in `tests/crates_regex.rs`).
+#[test]
+fn word_boundary_backtracking_default_mismatch() {
+    use regex::internal::ExecBuilder;
+
+    let backtrack_re = ExecBuilder::new(r"\b")
+        .bounded_backtracking()
+        .build()
+        .map(|exec| exec.into_regex())
+        .map_err(|err| format!("{}", err))
+        .unwrap();
+
+    let default_re = ExecBuilder::new(r"\b")
+        .build()
+        .map(|exec| exec.into_regex())
+        .map_err(|err| format!("{}", err))
+        .unwrap();
+
+    let input = "䅅\\u{a0}";
+
+    let fi1 = backtrack_re.find_iter(input);
+    let fi2 = default_re.find_iter(input);
+    for (m1, m2) in fi1.zip(fi2) {
+        assert_eq!(m1, m2);
+    }
+}
+*/
+
+mod consistent;
+
+mod crates_regex {
+
+    macro_rules! consistent {
+        ($test_name:ident, $regex_src:expr) => {
+            #[test]
+            fn $test_name() {
+                use super::consistent::backends_are_consistent;
+
+                if option_env!("RUST_REGEX_RANDOM_TEST").is_some() {
+                    match backends_are_consistent($regex_src) {
+                        Ok(_) => {}
+                        Err(err) => panic!("{}", err),
+                    }
+                }
+            }
+        };
+    }
+
+    include!("crates_regex.rs");
+}
diff --git a/vendor/regex-1.4.6/tests/test_default.rs b/vendor/regex-1.4.6/tests/test_default.rs
new file mode 100644 (file)
index 0000000..af634a0
--- /dev/null
@@ -0,0 +1,153 @@
+#![cfg_attr(feature = "pattern", feature(pattern))]
+
+extern crate rand;
+extern crate regex;
+
+// Due to macro scoping rules, this definition only applies for the modules
+// defined below. Effectively, it allows us to use the same tests for both
+// native and dynamic regexes.
+//
+// This is also used to test the various matching engines. This one exercises
+// the normal code path which automatically chooses the engine based on the
+// regex and the input. Other dynamic tests explicitly set the engine to use.
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::Regex;
+        Regex::new($re)
+    }};
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    };
+}
+
+macro_rules! regex_set_new {
+    ($re:expr) => {{
+        use regex::RegexSet;
+        RegexSet::new($re)
+    }};
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    };
+}
+
+// Must come before other module definitions.
+include!("macros_str.rs");
+include!("macros.rs");
+
+mod api;
+mod api_str;
+mod crazy;
+mod flags;
+mod fowler;
+mod misc;
+mod multiline;
+mod noparse;
+mod regression;
+mod regression_fuzz;
+mod replace;
+mod searcher;
+mod set;
+mod shortest_match;
+mod suffix_reverse;
+#[cfg(feature = "unicode")]
+mod unicode;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary_unicode;
+
+#[test]
+fn disallow_non_utf8() {
+    assert!(regex::Regex::new(r"(?-u)\xFF").is_err());
+    assert!(regex::Regex::new(r"(?-u).").is_err());
+    assert!(regex::Regex::new(r"(?-u)[\xFF]").is_err());
+    assert!(regex::Regex::new(r"(?-u)☃").is_err());
+}
+
+#[test]
+fn disallow_octal() {
+    assert!(regex::Regex::new(r"\0").is_err());
+}
+
+#[test]
+fn allow_octal() {
+    assert!(regex::RegexBuilder::new(r"\0").octal(true).build().is_ok());
+}
+
+#[test]
+fn oibits() {
+    use regex::bytes;
+    use regex::{Regex, RegexBuilder, RegexSet, RegexSetBuilder};
+    use std::panic::{RefUnwindSafe, UnwindSafe};
+
+    fn assert_send<T: Send>() {}
+    fn assert_sync<T: Sync>() {}
+    fn assert_unwind_safe<T: UnwindSafe>() {}
+    fn assert_ref_unwind_safe<T: RefUnwindSafe>() {}
+
+    assert_send::<Regex>();
+    assert_sync::<Regex>();
+    assert_unwind_safe::<Regex>();
+    assert_ref_unwind_safe::<Regex>();
+    assert_send::<RegexBuilder>();
+    assert_sync::<RegexBuilder>();
+    assert_unwind_safe::<RegexBuilder>();
+    assert_ref_unwind_safe::<RegexBuilder>();
+
+    assert_send::<bytes::Regex>();
+    assert_sync::<bytes::Regex>();
+    assert_unwind_safe::<bytes::Regex>();
+    assert_ref_unwind_safe::<bytes::Regex>();
+    assert_send::<bytes::RegexBuilder>();
+    assert_sync::<bytes::RegexBuilder>();
+    assert_unwind_safe::<bytes::RegexBuilder>();
+    assert_ref_unwind_safe::<bytes::RegexBuilder>();
+
+    assert_send::<RegexSet>();
+    assert_sync::<RegexSet>();
+    assert_unwind_safe::<RegexSet>();
+    assert_ref_unwind_safe::<RegexSet>();
+    assert_send::<RegexSetBuilder>();
+    assert_sync::<RegexSetBuilder>();
+    assert_unwind_safe::<RegexSetBuilder>();
+    assert_ref_unwind_safe::<RegexSetBuilder>();
+
+    assert_send::<bytes::RegexSet>();
+    assert_sync::<bytes::RegexSet>();
+    assert_unwind_safe::<bytes::RegexSet>();
+    assert_ref_unwind_safe::<bytes::RegexSet>();
+    assert_send::<bytes::RegexSetBuilder>();
+    assert_sync::<bytes::RegexSetBuilder>();
+    assert_unwind_safe::<bytes::RegexSetBuilder>();
+    assert_ref_unwind_safe::<bytes::RegexSetBuilder>();
+}
+
+// See: https://github.com/rust-lang/regex/issues/568
+#[test]
+fn oibits_regression() {
+    use regex::Regex;
+    use std::panic;
+
+    let _ = panic::catch_unwind(|| Regex::new("a").unwrap());
+}
+
+// See: https://github.com/rust-lang/regex/issues/750
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn regex_is_reasonably_small() {
+    use std::mem::size_of;
+
+    use regex::bytes;
+    use regex::{Regex, RegexSet};
+
+    assert_eq!(16, size_of::<Regex>());
+    assert_eq!(16, size_of::<RegexSet>());
+    assert_eq!(16, size_of::<bytes::Regex>());
+    assert_eq!(16, size_of::<bytes::RegexSet>());
+}
diff --git a/vendor/regex-1.4.6/tests/test_default_bytes.rs b/vendor/regex-1.4.6/tests/test_default_bytes.rs
new file mode 100644 (file)
index 0000000..e4a25dc
--- /dev/null
@@ -0,0 +1,78 @@
+extern crate rand;
+extern crate regex;
+
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::bytes::Regex;
+        Regex::new($re)
+    }};
+}
+
+macro_rules! regex_set_new {
+    ($res:expr) => {{
+        use regex::bytes::RegexSet;
+        RegexSet::new($res)
+    }};
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    };
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    };
+}
+
+// Must come before other module definitions.
+include!("macros_bytes.rs");
+include!("macros.rs");
+
+// A silly wrapper to make it possible to write and match raw bytes.
+struct R<'a>(&'a [u8]);
+impl<'a> R<'a> {
+    fn as_bytes(&self) -> &'a [u8] {
+        self.0
+    }
+}
+
+// See: https://github.com/rust-lang/regex/issues/321
+//
+// These tests are here because they do not have the same behavior in every
+// regex engine.
+mat!(invalid_utf8_nfa1, r".", R(b"\xD4\xC2\x65\x2B\x0E\xFE"), Some((2, 3)));
+mat!(invalid_utf8_nfa2, r"${2}ä", R(b"\xD4\xC2\x65\x2B\x0E\xFE"), None);
+mat!(
+    invalid_utf8_nfa3,
+    r".",
+    R(b"\x0A\xDB\x82\x6E\x33\x01\xDD\x33\xCD"),
+    Some((1, 3))
+);
+mat!(
+    invalid_utf8_nfa4,
+    r"${2}ä",
+    R(b"\x0A\xDB\x82\x6E\x33\x01\xDD\x33\xCD"),
+    None
+);
+
+mod api;
+mod bytes;
+mod crazy;
+mod flags;
+mod fowler;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod set;
+mod shortest_match;
+mod suffix_reverse;
+#[cfg(feature = "unicode")]
+mod unicode;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary_unicode;
diff --git a/vendor/regex-1.4.6/tests/test_nfa.rs b/vendor/regex-1.4.6/tests/test_nfa.rs
new file mode 100644 (file)
index 0000000..05dad23
--- /dev/null
@@ -0,0 +1,53 @@
+#![cfg_attr(feature = "pattern", feature(pattern))]
+
+extern crate rand;
+extern crate regex;
+
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new($re).nfa().build().map(|e| e.into_regex())
+    }};
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    };
+}
+
+macro_rules! regex_set_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new_many($re).nfa().build().map(|e| e.into_regex_set())
+    }};
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    };
+}
+
+// Must come before other module definitions.
+include!("macros_str.rs");
+include!("macros.rs");
+
+mod api;
+mod api_str;
+mod crazy;
+mod flags;
+mod fowler;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod searcher;
+mod set;
+mod suffix_reverse;
+#[cfg(feature = "unicode")]
+mod unicode;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary_unicode;
diff --git a/vendor/regex-1.4.6/tests/test_nfa_bytes.rs b/vendor/regex-1.4.6/tests/test_nfa_bytes.rs
new file mode 100644 (file)
index 0000000..1042318
--- /dev/null
@@ -0,0 +1,58 @@
+extern crate rand;
+extern crate regex;
+
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new($re)
+            .nfa()
+            .only_utf8(false)
+            .build()
+            .map(|e| e.into_byte_regex())
+    }};
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    };
+}
+
+macro_rules! regex_set_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new_many($re)
+            .nfa()
+            .only_utf8(false)
+            .build()
+            .map(|e| e.into_byte_regex_set())
+    }};
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    };
+}
+
+// Must come before other module definitions.
+include!("macros_bytes.rs");
+include!("macros.rs");
+
+mod api;
+mod bytes;
+mod crazy;
+mod flags;
+mod fowler;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod set;
+mod suffix_reverse;
+#[cfg(feature = "unicode")]
+mod unicode;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary_unicode;
diff --git a/vendor/regex-1.4.6/tests/test_nfa_utf8bytes.rs b/vendor/regex-1.4.6/tests/test_nfa_utf8bytes.rs
new file mode 100644 (file)
index 0000000..86487a1
--- /dev/null
@@ -0,0 +1,57 @@
+#![cfg_attr(feature = "pattern", feature(pattern))]
+
+extern crate rand;
+extern crate regex;
+
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new($re).nfa().bytes(true).build().map(|e| e.into_regex())
+    }};
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    };
+}
+
+macro_rules! regex_set_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new_many($re)
+            .nfa()
+            .bytes(true)
+            .build()
+            .map(|e| e.into_regex_set())
+    }};
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    };
+}
+
+// Must come before other module definitions.
+include!("macros_str.rs");
+include!("macros.rs");
+
+mod api;
+mod api_str;
+mod crazy;
+mod flags;
+mod fowler;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod searcher;
+mod set;
+mod suffix_reverse;
+#[cfg(feature = "unicode")]
+mod unicode;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary;
+#[cfg(feature = "unicode-perl")]
+mod word_boundary_unicode;
diff --git a/vendor/regex-1.4.6/tests/unicode.rs b/vendor/regex-1.4.6/tests/unicode.rs
new file mode 100644 (file)
index 0000000..9f1cd0c
--- /dev/null
@@ -0,0 +1,234 @@
+mat!(uni_literal, r"☃", "☃", Some((0, 3)));
+mat!(uni_literal_plus, r"☃+", "☃", Some((0, 3)));
+mat!(uni_literal_casei_plus, r"(?i)☃+", "☃", Some((0, 3)));
+mat!(uni_class_plus, r"[☃Ⅰ]+", "☃", Some((0, 3)));
+mat!(uni_one, r"\pN", "Ⅰ", Some((0, 3)));
+mat!(uni_mixed, r"\pN+", "Ⅰ1Ⅱ2", Some((0, 8)));
+mat!(uni_not, r"\PN+", "abⅠ", Some((0, 2)));
+mat!(uni_not_class, r"[\PN]+", "abⅠ", Some((0, 2)));
+mat!(uni_not_class_neg, r"[^\PN]+", "abⅠ", Some((2, 5)));
+mat!(uni_case, r"(?i)Δ", "δ", Some((0, 2)));
+mat!(uni_case_upper, r"\p{Lu}+", "ΛΘΓΔα", Some((0, 8)));
+mat!(uni_case_upper_nocase_flag, r"(?i)\p{Lu}+", "ΛΘΓΔα", Some((0, 10)));
+mat!(uni_case_upper_nocase, r"\p{L}+", "ΛΘΓΔα", Some((0, 10)));
+mat!(uni_case_lower, r"\p{Ll}+", "ΛΘΓΔα", Some((8, 10)));
+
+// Test the Unicode friendliness of Perl character classes.
+mat!(uni_perl_w, r"\w+", "dδd", Some((0, 4)));
+mat!(uni_perl_w_not, r"\w+", "⥡", None);
+mat!(uni_perl_w_neg, r"\W+", "⥡", Some((0, 3)));
+mat!(uni_perl_d, r"\d+", "1२३9", Some((0, 8)));
+mat!(uni_perl_d_not, r"\d+", "Ⅱ", None);
+mat!(uni_perl_d_neg, r"\D+", "Ⅱ", Some((0, 3)));
+mat!(uni_perl_s, r"\s+", " ", Some((0, 3)));
+mat!(uni_perl_s_not, r"\s+", "☃", None);
+mat!(uni_perl_s_neg, r"\S+", "☃", Some((0, 3)));
+
+// And do the same for word boundaries.
+mat!(uni_boundary_none, r"\d\b", "6δ", None);
+mat!(uni_boundary_ogham, r"\d\b", "6 ", Some((0, 1)));
+mat!(uni_not_boundary_none, r"\d\B", "6δ", Some((0, 1)));
+mat!(uni_not_boundary_ogham, r"\d\B", "6 ", None);
+
+// Test general categories.
+//
+// We should test more, but there's a lot. Write a script to generate more of
+// these tests.
+mat!(uni_class_gencat_cased_letter, r"\p{Cased_Letter}", "A", Some((0, 3)));
+mat!(
+    uni_class_gencat_close_punctuation,
+    r"\p{Close_Punctuation}",
+    "❯",
+    Some((0, 3))
+);
+mat!(
+    uni_class_gencat_connector_punctuation,
+    r"\p{Connector_Punctuation}",
+    "⁀",
+    Some((0, 3))
+);
+mat!(uni_class_gencat_control, r"\p{Control}", "\u{9f}", Some((0, 2)));
+mat!(
+    uni_class_gencat_currency_symbol,
+    r"\p{Currency_Symbol}",
+    "£",
+    Some((0, 3))
+);
+mat!(
+    uni_class_gencat_dash_punctuation,
+    r"\p{Dash_Punctuation}",
+    "〰",
+    Some((0, 3))
+);
+mat!(uni_class_gencat_decimal_numer, r"\p{Decimal_Number}", "𑓙", Some((0, 4)));
+mat!(
+    uni_class_gencat_enclosing_mark,
+    r"\p{Enclosing_Mark}",
+    "\u{A672}",
+    Some((0, 3))
+);
+mat!(
+    uni_class_gencat_final_punctuation,
+    r"\p{Final_Punctuation}",
+    "⸡",
+    Some((0, 3))
+);
+mat!(uni_class_gencat_format, r"\p{Format}", "\u{E007F}", Some((0, 4)));
+// See: https://github.com/rust-lang/regex/issues/719
+mat!(uni_class_gencat_format_abbrev1, r"\p{cf}", "\u{E007F}", Some((0, 4)));
+mat!(uni_class_gencat_format_abbrev2, r"\p{gc=cf}", "\u{E007F}", Some((0, 4)));
+mat!(
+    uni_class_gencat_initial_punctuation,
+    r"\p{Initial_Punctuation}",
+    "⸜",
+    Some((0, 3))
+);
+mat!(uni_class_gencat_letter, r"\p{Letter}", "Έ", Some((0, 2)));
+mat!(uni_class_gencat_letter_number, r"\p{Letter_Number}", "ↂ", Some((0, 3)));
+mat!(
+    uni_class_gencat_line_separator,
+    r"\p{Line_Separator}",
+    "\u{2028}",
+    Some((0, 3))
+);
+mat!(
+    uni_class_gencat_lowercase_letter,
+    r"\p{Lowercase_Letter}",
+    "ϛ",
+    Some((0, 2))
+);
+mat!(uni_class_gencat_mark, r"\p{Mark}", "\u{E01EF}", Some((0, 4)));
+mat!(uni_class_gencat_math, r"\p{Math}", "⋿", Some((0, 3)));
+mat!(
+    uni_class_gencat_modifier_letter,
+    r"\p{Modifier_Letter}",
+    "𖭃",
+    Some((0, 4))
+);
+mat!(
+    uni_class_gencat_modifier_symbol,
+    r"\p{Modifier_Symbol}",
+    "🏿",
+    Some((0, 4))
+);
+mat!(
+    uni_class_gencat_nonspacing_mark,
+    r"\p{Nonspacing_Mark}",
+    "\u{1E94A}",
+    Some((0, 4))
+);
+mat!(uni_class_gencat_number, r"\p{Number}", "⓿", Some((0, 3)));
+mat!(
+    uni_class_gencat_open_punctuation,
+    r"\p{Open_Punctuation}",
+    "⦅",
+    Some((0, 3))
+);
+mat!(uni_class_gencat_other, r"\p{Other}", "\u{bc9}", Some((0, 3)));
+mat!(uni_class_gencat_other_letter, r"\p{Other_Letter}", "ꓷ", Some((0, 3)));
+mat!(uni_class_gencat_other_number, r"\p{Other_Number}", "㉏", Some((0, 3)));
+mat!(
+    uni_class_gencat_other_punctuation,
+    r"\p{Other_Punctuation}",
+    "𞥞",
+    Some((0, 4))
+);
+mat!(uni_class_gencat_other_symbol, r"\p{Other_Symbol}", "⅌", Some((0, 3)));
+mat!(
+    uni_class_gencat_paragraph_separator,
+    r"\p{Paragraph_Separator}",
+    "\u{2029}",
+    Some((0, 3))
+);
+mat!(
+    uni_class_gencat_private_use,
+    r"\p{Private_Use}",
+    "\u{10FFFD}",
+    Some((0, 4))
+);
+mat!(uni_class_gencat_punctuation, r"\p{Punctuation}", "𑁍", Some((0, 4)));
+mat!(uni_class_gencat_separator, r"\p{Separator}", "\u{3000}", Some((0, 3)));
+mat!(
+    uni_class_gencat_space_separator,
+    r"\p{Space_Separator}",
+    "\u{205F}",
+    Some((0, 3))
+);
+mat!(
+    uni_class_gencat_spacing_mark,
+    r"\p{Spacing_Mark}",
+    "\u{16F7E}",
+    Some((0, 4))
+);
+mat!(uni_class_gencat_symbol, r"\p{Symbol}", "⯈", Some((0, 3)));
+mat!(
+    uni_class_gencat_titlecase_letter,
+    r"\p{Titlecase_Letter}",
+    "ῼ",
+    Some((0, 3))
+);
+mat!(
+    uni_class_gencat_unassigned,
+    r"\p{Unassigned}",
+    "\u{10FFFF}",
+    Some((0, 4))
+);
+mat!(
+    uni_class_gencat_uppercase_letter,
+    r"\p{Uppercase_Letter}",
+    "Ꝋ",
+    Some((0, 3))
+);
+
+// Test a smattering of properties.
+mat!(uni_class_prop_emoji1, r"\p{Emoji}", "\u{23E9}", Some((0, 3)));
+mat!(uni_class_prop_emoji2, r"\p{emoji}", "\u{1F21A}", Some((0, 4)));
+mat!(
+    uni_class_prop_picto1,
+    r"\p{extendedpictographic}",
+    "\u{1FA6E}",
+    Some((0, 4))
+);
+mat!(
+    uni_class_prop_picto2,
+    r"\p{extendedpictographic}",
+    "\u{1FFFD}",
+    Some((0, 4))
+);
+
+// grapheme_cluster_break
+mat!(
+    uni_class_gcb_prepend,
+    r"\p{grapheme_cluster_break=prepend}",
+    "\u{11D46}",
+    Some((0, 4))
+);
+mat!(
+    uni_class_gcb_ri1,
+    r"\p{gcb=regional_indicator}",
+    "\u{1F1E6}",
+    Some((0, 4))
+);
+mat!(uni_class_gcb_ri2, r"\p{gcb=ri}", "\u{1F1E7}", Some((0, 4)));
+mat!(
+    uni_class_gcb_ri3,
+    r"\p{gcb=regionalindicator}",
+    "\u{1F1FF}",
+    Some((0, 4))
+);
+mat!(uni_class_gcb_lvt, r"\p{gcb=lvt}", "\u{C989}", Some((0, 3)));
+mat!(uni_class_gcb_zwj, r"\p{gcb=zwj}", "\u{200D}", Some((0, 3)));
+
+// word_break
+mat!(uni_class_wb1, r"\p{word_break=Hebrew_Letter}", "\u{FB46}", Some((0, 3)));
+mat!(uni_class_wb2, r"\p{wb=hebrewletter}", "\u{FB46}", Some((0, 3)));
+mat!(uni_class_wb3, r"\p{wb=ExtendNumLet}", "\u{FF3F}", Some((0, 3)));
+mat!(uni_class_wb4, r"\p{wb=WSegSpace}", "\u{3000}", Some((0, 3)));
+mat!(uni_class_wb5, r"\p{wb=numeric}", "\u{1E950}", Some((0, 4)));
+
+// sentence_break
+mat!(uni_class_sb1, r"\p{sentence_break=Lower}", "\u{0469}", Some((0, 2)));
+mat!(uni_class_sb2, r"\p{sb=lower}", "\u{0469}", Some((0, 2)));
+mat!(uni_class_sb3, r"\p{sb=Close}", "\u{FF60}", Some((0, 3)));
+mat!(uni_class_sb4, r"\p{sb=Close}", "\u{1F677}", Some((0, 4)));
+mat!(uni_class_sb5, r"\p{sb=SContinue}", "\u{FF64}", Some((0, 3)));
diff --git a/vendor/regex-1.4.6/tests/word_boundary.rs b/vendor/regex-1.4.6/tests/word_boundary.rs
new file mode 100644 (file)
index 0000000..7fe97a2
--- /dev/null
@@ -0,0 +1,89 @@
+// Many of these are cribbed from RE2's test suite.
+
+matiter!(wb1, r"\b", "");
+matiter!(wb2, r"\b", "a", (0, 0), (1, 1));
+matiter!(wb3, r"\b", "ab", (0, 0), (2, 2));
+matiter!(wb4, r"^\b", "ab", (0, 0));
+matiter!(wb5, r"\b$", "ab", (2, 2));
+matiter!(wb6, r"^\b$", "ab");
+matiter!(wb7, r"\bbar\b", "nobar bar foo bar", (6, 9), (14, 17));
+matiter!(wb8, r"a\b", "faoa x", (3, 4));
+matiter!(wb9, r"\bbar", "bar x", (0, 3));
+matiter!(wb10, r"\bbar", "foo\nbar x", (4, 7));
+matiter!(wb11, r"bar\b", "foobar", (3, 6));
+matiter!(wb12, r"bar\b", "foobar\nxxx", (3, 6));
+matiter!(wb13, r"(foo|bar|[A-Z])\b", "foo", (0, 3));
+matiter!(wb14, r"(foo|bar|[A-Z])\b", "foo\n", (0, 3));
+matiter!(wb15, r"\b(foo|bar|[A-Z])", "foo", (0, 3));
+matiter!(wb16, r"\b(foo|bar|[A-Z])\b", "X", (0, 1));
+matiter!(wb17, r"\b(foo|bar|[A-Z])\b", "XY");
+matiter!(wb18, r"\b(foo|bar|[A-Z])\b", "bar", (0, 3));
+matiter!(wb19, r"\b(foo|bar|[A-Z])\b", "foo", (0, 3));
+matiter!(wb20, r"\b(foo|bar|[A-Z])\b", "foo\n", (0, 3));
+matiter!(wb21, r"\b(foo|bar|[A-Z])\b", "ffoo bbar N x", (10, 11));
+matiter!(wb22, r"\b(fo|foo)\b", "fo", (0, 2));
+matiter!(wb23, r"\b(fo|foo)\b", "foo", (0, 3));
+matiter!(wb24, r"\b\b", "");
+matiter!(wb25, r"\b\b", "a", (0, 0), (1, 1));
+matiter!(wb26, r"\b$", "");
+matiter!(wb27, r"\b$", "x", (1, 1));
+matiter!(wb28, r"\b$", "y x", (3, 3));
+matiter!(wb29, r"\b.$", "x", (0, 1));
+matiter!(wb30, r"^\b(fo|foo)\b", "fo", (0, 2));
+matiter!(wb31, r"^\b(fo|foo)\b", "foo", (0, 3));
+matiter!(wb32, r"^\b$", "");
+matiter!(wb33, r"^\b$", "x");
+matiter!(wb34, r"^\b.$", "x", (0, 1));
+matiter!(wb35, r"^\b.\b$", "x", (0, 1));
+matiter!(wb36, r"^^^^^\b$$$$$", "");
+matiter!(wb37, r"^^^^^\b.$$$$$", "x", (0, 1));
+matiter!(wb38, r"^^^^^\b$$$$$", "x");
+matiter!(wb39, r"^^^^^\b\b\b.\b\b\b$$$$$", "x", (0, 1));
+matiter!(wb40, r"\b.+\b", "$$abc$$", (2, 5));
+matiter!(wb41, r"\b", "a b c", (0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5));
+
+matiter!(nb1, r"\Bfoo\B", "n foo xfoox that", (7, 10));
+matiter!(nb2, r"a\B", "faoa x", (1, 2));
+matiter!(nb3, r"\Bbar", "bar x");
+matiter!(nb4, r"\Bbar", "foo\nbar x");
+matiter!(nb5, r"bar\B", "foobar");
+matiter!(nb6, r"bar\B", "foobar\nxxx");
+matiter!(nb7, r"(foo|bar|[A-Z])\B", "foox", (0, 3));
+matiter!(nb8, r"(foo|bar|[A-Z])\B", "foo\n");
+matiter!(nb9, r"\B", "", (0, 0));
+matiter!(nb10, r"\B", "x");
+matiter!(nb11, r"\B(foo|bar|[A-Z])", "foo");
+matiter!(nb12, r"\B(foo|bar|[A-Z])\B", "xXy", (1, 2));
+matiter!(nb13, r"\B(foo|bar|[A-Z])\B", "XY");
+matiter!(nb14, r"\B(foo|bar|[A-Z])\B", "XYZ", (1, 2));
+matiter!(nb15, r"\B(foo|bar|[A-Z])\B", "abara", (1, 4));
+matiter!(nb16, r"\B(foo|bar|[A-Z])\B", "xfoo_", (1, 4));
+matiter!(nb17, r"\B(foo|bar|[A-Z])\B", "xfoo\n");
+matiter!(nb18, r"\B(foo|bar|[A-Z])\B", "foo bar vNX", (9, 10));
+matiter!(nb19, r"\B(fo|foo)\B", "xfoo", (1, 3));
+matiter!(nb20, r"\B(foo|fo)\B", "xfooo", (1, 4));
+matiter!(nb21, r"\B\B", "", (0, 0));
+matiter!(nb22, r"\B\B", "x");
+matiter!(nb23, r"\B$", "", (0, 0));
+matiter!(nb24, r"\B$", "x");
+matiter!(nb25, r"\B$", "y x");
+matiter!(nb26, r"\B.$", "x");
+matiter!(nb27, r"^\B(fo|foo)\B", "fo");
+matiter!(nb28, r"^\B(fo|foo)\B", "foo");
+matiter!(nb29, r"^\B", "", (0, 0));
+matiter!(nb30, r"^\B", "x");
+matiter!(nb31, r"^\B\B", "", (0, 0));
+matiter!(nb32, r"^\B\B", "x");
+matiter!(nb33, r"^\B$", "", (0, 0));
+matiter!(nb34, r"^\B$", "x");
+matiter!(nb35, r"^\B.$", "x");
+matiter!(nb36, r"^\B.\B$", "x");
+matiter!(nb37, r"^^^^^\B$$$$$", "", (0, 0));
+matiter!(nb38, r"^^^^^\B.$$$$$", "x");
+matiter!(nb39, r"^^^^^\B$$$$$", "x");
+
+// These work for both Unicode and ASCII because all matches are reported as
+// byte offsets, and « and » do not correspond to word boundaries at either
+// the character or byte level.
+matiter!(unicode1, r"\bx\b", "«x", (2, 3));
+matiter!(unicode2, r"\bx\b", "x»", (0, 1));
diff --git a/vendor/regex-1.4.6/tests/word_boundary_ascii.rs b/vendor/regex-1.4.6/tests/word_boundary_ascii.rs
new file mode 100644 (file)
index 0000000..5a3cf11
--- /dev/null
@@ -0,0 +1,9 @@
+// ASCII word boundaries are completely oblivious to Unicode characters.
+// For Unicode word boundaries, the tests are precisely inverted.
+matiter!(ascii1, r"(?-u:\b)x(?-u:\b)", "áxβ", (2, 3));
+matiter!(ascii2, r"(?-u:\B)x(?-u:\B)", "áxβ");
+matiter!(ascii3, r"(?-u:\B)", "0\u{7EF5E}", (2, 2), (3, 3), (4, 4), (5, 5));
+
+// We still get Unicode word boundaries by default in byte regexes.
+matiter!(unicode1, r"\bx\b", "áxβ");
+matiter!(unicode2, r"\Bx\B", "áxβ", (2, 3));
diff --git a/vendor/regex-1.4.6/tests/word_boundary_unicode.rs b/vendor/regex-1.4.6/tests/word_boundary_unicode.rs
new file mode 100644 (file)
index 0000000..c41355f
--- /dev/null
@@ -0,0 +1,6 @@
+// Unicode word boundaries know about Unicode characters.
+// For ASCII word boundaries, the tests are precisely inverted.
+matiter!(unicode1, r"\bx\b", "áxβ");
+matiter!(unicode2, r"\Bx\B", "áxβ", (2, 3));
+
+matiter!(ascii1, r"(?-u:\b)x(?-u:\b)", "áxβ", (2, 3));
index 2914bb7794fc2a5b0f1ec90c44c164c854e24d64..a8c689c8bb1d704ce3789140648c9689684369b9 100644 (file)
@@ -1 +1 @@
-{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"81498a2a004852b0bf2549f5ee9fd2dc600f3e3419205268762d6ec054bbf702","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"3f715f49b56b3e84a2547150d3bd988f427808f451df8a064ffa9781b09406a2","TODO":"daea9f7378f543311d657e6ef3d2a09d51e82b9e70d0026140130862c32b3c08","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","data/fowler-tests/LICENSE":"58cf078acc03da3e280a938c2bd9943f554fc9b6ced89ad93ba35ca436872899","data/fowler-tests/README":"45f869e37f798905c773bfbe0ef19a5fb7e585cbf0b7c21b5b5a784e8cec3c14","data/fowler-tests/basic.dat":"3756a5bdd6f387ed34731197fbdaab8521b0ae1726250100ba235756cb42b4b1","data/fowler-tests/nullsubexpr.dat":"496ac0278eec3b6d9170faace14554569032dd3d909618364d9326156de39ecf","data/fowler-tests/repetition.dat":"1f7959063015b284b18a4a2c1c8b416d438a2d6c4b1a362da43406b865f50e69","data/tests/crazy.toml":"b6e644a74b990a4344b15e7366da36e5b3f73a183944e249082f74c23ff01e5f","data/tests/flags.toml":"aefd9483c1c9c52c3669a9f2e88cd494c293f2e14c59aecb1d94dbb82546a705","data/tests/fowler/LICENSE":"58cf078acc03da3e280a938c2bd9943f554fc9b6ced89ad93ba35ca436872899","data/tests/fowler/README":"e9f049297023d5a81c5c600280016fe0271e7d0eda898c41399eb61431820404","data/tests/fowler/basic.dat":"3756a5bdd6f387ed34731197fbdaab8521b0ae1726250100ba235756cb42b4b1","data/tests/fowler/basic.toml":"7b043231ca8c89dbd10cef0de3b0be18c9ae442be1e99a657cd412b8b7edec21","data/tests/fowler/fowler-to-toml":"5bb78b924f3b6b1c27278b37baae556115fe03c864c1d33a7c53718b99885515","data/tests/fowler/nullsubexpr.dat":"496ac0278eec3b6d9170faace14554569032dd3d909618364d9326156de39ecf","data/tests/fowler/nullsubexpr.toml":"7e4bf9fec1c4a8aca04cc96e74b3f51ed6b8c3f85e4bfc7acc9c74ab95166976","data/tests/fowler/repetition-long.dat":"040b869c8c3a02ed0497943af1860094fd8437892811180fb9624a41eb491f23","data/tests/fowler/repetition-long.toml":"3eb7199d936b3f7eb9863ebc3b0c94648cfc32192f626dcfa33ddf352918c1c0","data/tests/fowler/repetition.dat":"d8fa959c2be524c90f2092f7c41ff3a7b48232b4378cb3b090625e74e76fc625","data/tests/fowler/repetition.toml":"ccf21430a325c4e1dae4eb6c52e3cea5d3c1847559ba6e75466bdb6bbd98204d","data/tests/iter.toml":"99adc397fe0a00c759eb659531d3e69445b43f5ecd5771c549117933b73bd43e","data/tests/no-unicode.toml":"f329ee939c2d07a17e51f0090d9f2431395e47dac8e0b982fb5e16e0555b75e3","data/tests/unicode.toml":"0ff418de5bc238e4595956b66981fe02018938d57d76d11cab840606b9da60ba","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/classes.rs":"706c8a8a9bf70260b9c92ff865891fc26de0453495afca7b325afdf5e6a3e242","src/codegen.rs":"5686b97fec69158c7264183a71ad9a1ff8e74db02fa0fcfccaa0a516cbfc7d1d","src/dense.rs":"7561f35019b20642f2ee75fd20365e21a4c8260deb7cee84fa3f8264b9fd9a4b","src/determinize.rs":"f11a12ec4664cb5529f12720eb1e8b3856e43710cb5ad43345c8d008460f3ffb","src/dfa.rs":"032f09d187ec8dd06ef09940515690af045ca9f7ef7f819c31a97607df1432e5","src/error.rs":"d07ecdc617e243a43a99e911398b9c37721afd2b9548153c5f359b8c4605c749","src/lib.rs":"4186ee04bde12b982f70cee6af8c1f68594d0cc5fadf47923cf36b99c2d70dab","src/minimize.rs":"dfa7b6a6f36bb2dedaee8bfc5c4bb943f59e0cf98cde5358822e70cbdb284a7e","src/nfa/compiler.rs":"f43901929f44efa420e441cbff8687e05059ceae88492a2ed6c49fdd5a6a6b04","src/nfa/map.rs":"b7e2e561d6fe5775716e27eded1ae3e2277a50073a2e182f3dabedcda5c30d27","src/nfa/mod.rs":"93e7dee804751fcf66d48ca48b3467a4ab5155063461e69c428e46bcf977711d","src/nfa/range_trie.rs":"3a3d2853987619688ab5b61acef575f216d5bdd7b9e15fa508e0ba6f29c641a9","src/regex.rs":"2f3868a3fa52b2a040fd0fb9f12386b1af1f0f650d948e821c7ba83f087826f0","src/sparse.rs":"976540bcd134a225e5d39e1aef688f63b02b3d745249a3a95fec387a7ffb88cc","src/sparse_set.rs":"a8500fba63ae3c866ec89ab3486aa75ad96911103538727fadab7358449a4d1e","src/state_id.rs":"44c4bf1a5d091b97e8c1ce872bafe45d806905b07a73a6f82b1655b7897e7b5f","src/transducer.rs":"28c728ef45a3f6177d5a3ac589f166764c11d6c66bd5d916bcf30ad2be187a0c","tests/collection.rs":"2907cc0a32e5e59ceca4b34fe582f9275c12ee1a8d6e73d689056bdfd5357b9a","tests/regression.rs":"5a9b2654f88b1b07401c5b1fe925f62421bff67be7d80cae7a985eb66ed9886b","tests/suite.rs":"8148247667b34b370855c247ffcc9c6339f8f72d6fe481b79936afbb165dd6bd","tests/tests.rs":"f1b407d3d288a9c2b1500151205f9d0bcc0668b2ab38c5094ee459d6d4893e18","tests/unescape.rs":"67a7c466ba5c873a3c29f7e00649535ddc2921fcc14ac92cb207f43b4b6e461d"},"package":"ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"}
\ No newline at end of file
+{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"674fda607d585e7a9d1d07e6fee2807e6a1a3709ca8d5a507dac051cac84dcf1","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"34ebd8d165fbd934198653a6d619d62788ff72f0e058139459d4369683423551","TODO":"daea9f7378f543311d657e6ef3d2a09d51e82b9e70d0026140130862c32b3c08","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","data/fowler-tests/LICENSE":"58cf078acc03da3e280a938c2bd9943f554fc9b6ced89ad93ba35ca436872899","data/fowler-tests/README":"45f869e37f798905c773bfbe0ef19a5fb7e585cbf0b7c21b5b5a784e8cec3c14","data/fowler-tests/basic.dat":"3756a5bdd6f387ed34731197fbdaab8521b0ae1726250100ba235756cb42b4b1","data/fowler-tests/nullsubexpr.dat":"496ac0278eec3b6d9170faace14554569032dd3d909618364d9326156de39ecf","data/fowler-tests/repetition.dat":"1f7959063015b284b18a4a2c1c8b416d438a2d6c4b1a362da43406b865f50e69","data/tests/crazy.toml":"b6e644a74b990a4344b15e7366da36e5b3f73a183944e249082f74c23ff01e5f","data/tests/flags.toml":"aefd9483c1c9c52c3669a9f2e88cd494c293f2e14c59aecb1d94dbb82546a705","data/tests/fowler/LICENSE":"58cf078acc03da3e280a938c2bd9943f554fc9b6ced89ad93ba35ca436872899","data/tests/fowler/README":"e9f049297023d5a81c5c600280016fe0271e7d0eda898c41399eb61431820404","data/tests/fowler/basic.dat":"3756a5bdd6f387ed34731197fbdaab8521b0ae1726250100ba235756cb42b4b1","data/tests/fowler/basic.toml":"7b043231ca8c89dbd10cef0de3b0be18c9ae442be1e99a657cd412b8b7edec21","data/tests/fowler/fowler-to-toml":"5bb78b924f3b6b1c27278b37baae556115fe03c864c1d33a7c53718b99885515","data/tests/fowler/nullsubexpr.dat":"496ac0278eec3b6d9170faace14554569032dd3d909618364d9326156de39ecf","data/tests/fowler/nullsubexpr.toml":"7e4bf9fec1c4a8aca04cc96e74b3f51ed6b8c3f85e4bfc7acc9c74ab95166976","data/tests/fowler/repetition-long.dat":"040b869c8c3a02ed0497943af1860094fd8437892811180fb9624a41eb491f23","data/tests/fowler/repetition-long.toml":"3eb7199d936b3f7eb9863ebc3b0c94648cfc32192f626dcfa33ddf352918c1c0","data/tests/fowler/repetition.dat":"d8fa959c2be524c90f2092f7c41ff3a7b48232b4378cb3b090625e74e76fc625","data/tests/fowler/repetition.toml":"ccf21430a325c4e1dae4eb6c52e3cea5d3c1847559ba6e75466bdb6bbd98204d","data/tests/iter.toml":"99adc397fe0a00c759eb659531d3e69445b43f5ecd5771c549117933b73bd43e","data/tests/no-unicode.toml":"f329ee939c2d07a17e51f0090d9f2431395e47dac8e0b982fb5e16e0555b75e3","data/tests/unicode.toml":"0ff418de5bc238e4595956b66981fe02018938d57d76d11cab840606b9da60ba","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/byteorder.rs":"0827852aa563e3c5b3ffaf484ce8a34537e82719a3606d4b948bc8a1e21d8b18","src/classes.rs":"706c8a8a9bf70260b9c92ff865891fc26de0453495afca7b325afdf5e6a3e242","src/codegen.rs":"5686b97fec69158c7264183a71ad9a1ff8e74db02fa0fcfccaa0a516cbfc7d1d","src/dense.rs":"7561f35019b20642f2ee75fd20365e21a4c8260deb7cee84fa3f8264b9fd9a4b","src/determinize.rs":"876c844d0470854dbbe3eb4386611fd57d95a5a4ae38ee937fbb14676f0a383a","src/dfa.rs":"032f09d187ec8dd06ef09940515690af045ca9f7ef7f819c31a97607df1432e5","src/error.rs":"d07ecdc617e243a43a99e911398b9c37721afd2b9548153c5f359b8c4605c749","src/lib.rs":"520781bdd60d425b16ef72f03330362e7c2aec274338e73f309d730bea4d7ab0","src/minimize.rs":"dfa7b6a6f36bb2dedaee8bfc5c4bb943f59e0cf98cde5358822e70cbdb284a7e","src/nfa/compiler.rs":"f43901929f44efa420e441cbff8687e05059ceae88492a2ed6c49fdd5a6a6b04","src/nfa/map.rs":"b7e2e561d6fe5775716e27eded1ae3e2277a50073a2e182f3dabedcda5c30d27","src/nfa/mod.rs":"93e7dee804751fcf66d48ca48b3467a4ab5155063461e69c428e46bcf977711d","src/nfa/range_trie.rs":"3a3d2853987619688ab5b61acef575f216d5bdd7b9e15fa508e0ba6f29c641a9","src/regex.rs":"2f3868a3fa52b2a040fd0fb9f12386b1af1f0f650d948e821c7ba83f087826f0","src/sparse.rs":"976540bcd134a225e5d39e1aef688f63b02b3d745249a3a95fec387a7ffb88cc","src/sparse_set.rs":"81bef5057781e26da39855b0f38b02ddfd09183bc62d30cf454ec706885e3a70","src/state_id.rs":"44c4bf1a5d091b97e8c1ce872bafe45d806905b07a73a6f82b1655b7897e7b5f","src/transducer.rs":"28c728ef45a3f6177d5a3ac589f166764c11d6c66bd5d916bcf30ad2be187a0c","tests/collection.rs":"2907cc0a32e5e59ceca4b34fe582f9275c12ee1a8d6e73d689056bdfd5357b9a","tests/regression.rs":"5a9b2654f88b1b07401c5b1fe925f62421bff67be7d80cae7a985eb66ed9886b","tests/suite.rs":"8148247667b34b370855c247ffcc9c6339f8f72d6fe481b79936afbb165dd6bd","tests/tests.rs":"f1b407d3d288a9c2b1500151205f9d0bcc0668b2ab38c5094ee459d6d4893e18","tests/unescape.rs":"67a7c466ba5c873a3c29f7e00649535ddc2921fcc14ac92cb207f43b4b6e461d"},"package":"6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"}
\ No newline at end of file
index 7ef891adbc1dcd1b973e2895e829e265b053ad3f..b4fcd7a0d3df73958868e7a84c83ca9d3f007212 100644 (file)
@@ -12,7 +12,7 @@
 
 [package]
 name = "regex-automata"
-version = "0.1.9"
+version = "0.1.10"
 authors = ["Andrew Gallant <jamslam@gmail.com>"]
 exclude = ["/.travis.yml", "/appveyor.yml", "/ci/*", "/scripts/*", "/regex-automata-debug"]
 autoexamples = false
@@ -45,10 +45,6 @@ bench = false
 [[test]]
 name = "default"
 path = "tests/tests.rs"
-[dependencies.byteorder]
-version = "1.2.7"
-default-features = false
-
 [dependencies.fst]
 version = "0.4.0"
 optional = true
index 2acf06567703fa351c6491d665c6d6277de435a2..8eaf03f04680266967648215734bbae70a99cea5 100644 (file)
@@ -6,9 +6,10 @@ configuring the best space vs time trade off for your use case and provides
 support for cheap deserialization of automata for use in `no_std` environments.
 
 [![Build status](https://github.com/BurntSushi/regex-automata/workflows/ci/badge.svg)](https://github.com/BurntSushi/regex-automata/actions)
-[![](http://meritbadge.herokuapp.com/regex-automata)](https://crates.io/crates/regex-automata)
+[![on crates.io](https://meritbadge.herokuapp.com/regex-automata)](https://crates.io/crates/regex-automata)
+![Minimum Supported Rust Version 1.41](https://img.shields.io/badge/rustc-1.41-green)
 
-Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
+Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
 
 
 ### Documentation
@@ -182,10 +183,10 @@ With some of the downsides out of the way, here are some positive differences:
 * Stretch goal: support capturing groups by implementing "tagged" DFA
   (transducers). Laurikari's paper is the usual reference here, but Trofimovich
   has a much more thorough treatment here:
-  http://re2c.org/2017_trofimovich_tagged_deterministic_finite_automata_with_lookahead.pdf
+  https://re2c.org/2017_trofimovich_tagged_deterministic_finite_automata_with_lookahead.pdf
   I've only read the paper once. I suspect it will require at least a few more
   read throughs before I understand it.
-  See also: http://re2c.org/
+  See also: https://re2c.org
 * Possibly less ambitious goal: can we select a portion of Trofimovich's work
   to make small fixed length look-around work? It would be really nice to
   support ^, $ and \b, especially the Unicode variant of \b and CRLF aware $.
@@ -219,4 +220,4 @@ With some of the downsides out of the way, here are some positive differences:
   If we could know whether a regex will exhibit state explosion or not, then
   we could make an intelligent decision about whether to ahead-of-time compile
   a DFA.
-  See: https://www.researchgate.net/profile/XU_Shutu/publication/229032602_Characterization_of_a_global_germplasm_collection_and_its_potential_utilization_for_analysis_of_complex_quantitative_traits_in_maize/links/02bfe50f914d04c837000000.pdf
+  See: https://www.researchgate.net/profile/Xu-Shutu/publication/229032602_Characterization_of_a_global_germplasm_collection_and_its_potential_utilization_for_analysis_of_complex_quantitative_traits_in_maize/links/02bfe50f914d04c837000000/Characterization-of-a-global-germplasm-collection-and-its-potential-utilization-for-analysis-of-complex-quantitative-traits-in-maize.pdf
diff --git a/vendor/regex-automata/src/byteorder.rs b/vendor/regex-automata/src/byteorder.rs
new file mode 100644 (file)
index 0000000..e909f93
--- /dev/null
@@ -0,0 +1,76 @@
+use core::convert::TryInto;
+
+pub trait ByteOrder {
+    fn read_u16(buf: &[u8]) -> u16;
+    fn read_u32(buf: &[u8]) -> u32;
+    fn read_u64(buf: &[u8]) -> u64;
+    fn read_uint(buf: &[u8], nbytes: usize) -> u64;
+    fn write_u16(buf: &mut [u8], n: u16);
+    fn write_u32(buf: &mut [u8], n: u32);
+    fn write_u64(buf: &mut [u8], n: u64);
+    fn write_uint(buf: &mut [u8], n: u64, nbytes: usize);
+}
+
+pub enum BigEndian {}
+pub enum LittleEndian {}
+pub enum NativeEndian {}
+
+macro_rules! impl_endian {
+    ($t:ty, $from_endian:ident, $to_endian:ident) => {
+        impl ByteOrder for $t {
+            #[inline]
+            fn read_u16(buf: &[u8]) -> u16 {
+                u16::$from_endian(buf[0..2].try_into().unwrap())
+            }
+
+            #[inline]
+            fn read_u32(buf: &[u8]) -> u32 {
+                u32::$from_endian(buf[0..4].try_into().unwrap())
+            }
+
+            #[inline]
+            fn read_u64(buf: &[u8]) -> u64 {
+                u64::$from_endian(buf[0..8].try_into().unwrap())
+            }
+
+            #[inline]
+            fn read_uint(buf: &[u8], nbytes: usize) -> u64 {
+                let mut dst = [0u8; 8];
+                dst[..nbytes].copy_from_slice(&buf[..nbytes]);
+                u64::$from_endian(dst)
+            }
+
+            #[inline]
+            fn write_u16(buf: &mut [u8], n: u16) {
+                buf[0..2].copy_from_slice(&n.$to_endian()[..]);
+            }
+
+            #[inline]
+            fn write_u32(buf: &mut [u8], n: u32) {
+                buf[0..4].copy_from_slice(&n.$to_endian()[..]);
+            }
+
+            #[inline]
+            fn write_u64(buf: &mut [u8], n: u64) {
+                buf[0..8].copy_from_slice(&n.$to_endian()[..]);
+            }
+
+            #[inline]
+            fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) {
+                buf[..nbytes].copy_from_slice(&n.$to_endian()[..nbytes]);
+            }
+        }
+    };
+}
+
+impl_endian! {
+    BigEndian, from_be_bytes, to_be_bytes
+}
+
+impl_endian! {
+    LittleEndian, from_le_bytes, to_le_bytes
+}
+
+impl_endian! {
+    NativeEndian, from_ne_bytes, to_ne_bytes
+}
index f3003161a96078e74d8022afa723b99b811a1d21..cf0c285857ca92ab84cc11eb22a2ab4fc9d36f8f 100644 (file)
@@ -148,7 +148,8 @@ impl<'a, S: StateID> Determinizer<'a, S> {
         if let Some(&cached_id) = self.cache.get(&state) {
             // Since we have a cached state, put the constructed state's
             // memory back into our scratch space, so that it can be reused.
-            mem::replace(&mut self.scratch_nfa_states, state.nfa_states);
+            let _ =
+                mem::replace(&mut self.scratch_nfa_states, state.nfa_states);
             return Ok((cached_id, false));
         }
         // Nothing was in the cache, so add this state to the cache.
index 4d3e9c1e19dec22536dfbc081bb77f072286ab69..7894eccea6e467858ac49dba75db0e3defa68752 100644 (file)
@@ -290,7 +290,6 @@ extern crate core;
 
 #[cfg(all(test, feature = "transducer"))]
 extern crate bstr;
-extern crate byteorder;
 #[cfg(feature = "transducer")]
 extern crate fst;
 #[cfg(feature = "std")]
@@ -306,6 +305,7 @@ pub use regex::RegexBuilder;
 pub use sparse::SparseDFA;
 pub use state_id::StateID;
 
+mod byteorder;
 mod classes;
 #[path = "dense.rs"]
 mod dense_imp;
index 6f145ba0cb562bee6901b198c6783eb823568933..56743b033e4d357ba6a7c16769c7e9aa88879bb8 100644 (file)
@@ -6,7 +6,7 @@ use std::slice;
 /// entire set can also be done in constant time. Iteration yields elements
 /// in the order in which they were inserted.
 ///
-/// The data structure is based on: http://research.swtch.com/sparse
+/// The data structure is based on: https://research.swtch.com/sparse
 /// Note though that we don't actually use uninitialized memory. We generally
 /// reuse sparse sets, so the initial allocation cost is bareable. However, its
 /// other properties listed above are extremely useful.
index 4b8dbff64d751c1eadd08c22d25ee740178cd7c7..2e02d8e45d0d88d0680d674c3a5a7e0610701452 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.toml":"14e6ccb02b4ad07261df1dfd0325460a546c049249f01fc49589543071f70402","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"3bb7af78423e95b207beebd452cdd973d65663cf25a0fc9358c588f53783293c","src/legacy.rs":"b4d5a140ed0bf2d792431961d6fd44a21c99235489a2c9f6717d1577a42c09ce","src/lib.rs":"84d6a85f1f1d5a68904a814b3bc59fcba00caafce83208cc4d6d53ed8c3e4cc3","src/v0.rs":"8d4e4862942045210bae59e4458526ca0784f7504447f74197870df3254c6489"},"package":"410f7acf3cb3a44527c5d9546bad4bf4e6c460915d5f9f2fc524498bfe8f70ce"}
\ No newline at end of file
+{"files":{"Cargo.toml":"5f0432ab22a4809cd3519a7de6304ccb4a564d9ee0b46dd22e2f92e826ed0ed7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"3bb7af78423e95b207beebd452cdd973d65663cf25a0fc9358c588f53783293c","src/legacy.rs":"b4d5a140ed0bf2d792431961d6fd44a21c99235489a2c9f6717d1577a42c09ce","src/lib.rs":"84d6a85f1f1d5a68904a814b3bc59fcba00caafce83208cc4d6d53ed8c3e4cc3","src/v0.rs":"ee720dba121497c390ae979073d46a14aead25d1c0b03b00ae7d7f56b01ee846"},"package":"dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49"}
\ No newline at end of file
index 5b4dcb03e2f20a1adb2523d723eb590c2e0d772b..c8133759cbaa198fea092396bca88418c02d0157 100644 (file)
@@ -12,7 +12,7 @@
 
 [package]
 name = "rustc-demangle"
-version = "0.1.19"
+version = "0.1.20"
 authors = ["Alex Crichton <alex@alexcrichton.com>"]
 description = "Rust compiler symbol demangling.\n"
 homepage = "https://github.com/alexcrichton/rustc-demangle"
index f8696c84e774c0592c595d81ea998cb2dba3a683..163686be6edc28ed8097995b1026cb8a0d2f708a 100644 (file)
@@ -2,9 +2,9 @@ use core::char;
 use core::fmt;
 use core::fmt::{Display, Write};
 
-// Maximum recursion depth when printing symbols before we just bail out saying
+// Maximum recursion depth when parsing symbols before we just bail out saying
 // "this symbol is invalid"
-const MAX_DEPTH: u32 = 1_000;
+const MAX_DEPTH: u32 = 500;
 
 // Approximately the maximum size of the symbol that we'll print. This is
 // approximate because it only limits calls writing to `LimitedFormatter`, but
@@ -56,6 +56,7 @@ pub fn demangle(s: &str) -> Result<(Demangle, &str), Invalid> {
     let mut parser = Parser {
         sym: inner,
         next: 0,
+        depth: 0,
     };
     parser.skip_path()?;
 
@@ -74,13 +75,13 @@ impl<'s> Display for Demangle<'s> {
             parser: Ok(Parser {
                 sym: self.inner,
                 next: 0,
+                depth: 0,
             }),
             out: LimitedFormatter {
                 remaining: &mut remaining,
                 inner: f,
             },
             bound_lifetime_depth: 0,
-            depth: 0,
         };
         printer.print_path(true)
     }
@@ -280,9 +281,23 @@ fn basic_type(tag: u8) -> Option<&'static str> {
 struct Parser<'s> {
     sym: &'s str,
     next: usize,
+    depth: u32,
 }
 
 impl<'s> Parser<'s> {
+    fn push_depth(&mut self) -> Result<(), Invalid> {
+        self.depth += 1;
+        if self.depth > MAX_DEPTH {
+            Err(Invalid)
+        } else {
+            Ok(())
+        }
+    }
+
+    fn pop_depth(&mut self) {
+        self.depth -= 1;
+    }
+
     fn peek(&self) -> Option<u8> {
         self.sym.as_bytes().get(self.next).cloned()
     }
@@ -377,10 +392,13 @@ impl<'s> Parser<'s> {
         if i >= s_start as u64 {
             return Err(Invalid);
         }
-        Ok(Parser {
+        let mut new_parser = Parser {
             sym: self.sym,
             next: i as usize,
-        })
+            depth: self.depth,
+        };
+        new_parser.push_depth()?;
+        Ok(new_parser)
     }
 
     fn ident(&mut self) -> Result<Ident<'s>, Invalid> {
@@ -428,6 +446,8 @@ impl<'s> Parser<'s> {
     }
 
     fn skip_path(&mut self) -> Result<(), Invalid> {
+        self.push_depth()?;
+
         match self.next()? {
             b'C' => {
                 self.disambiguator()?;
@@ -469,6 +489,8 @@ impl<'s> Parser<'s> {
     }
 
     fn skip_generic_arg(&mut self) -> Result<(), Invalid> {
+        self.push_depth()?;
+
         if self.eat(b'L') {
             self.integer_62()?;
             Ok(())
@@ -480,6 +502,8 @@ impl<'s> Parser<'s> {
     }
 
     fn skip_type(&mut self) -> Result<(), Invalid> {
+        self.push_depth()?;
+
         match self.next()? {
             tag if basic_type(tag).is_some() => {}
 
@@ -543,6 +567,8 @@ impl<'s> Parser<'s> {
     }
 
     fn skip_const(&mut self) -> Result<(), Invalid> {
+        self.push_depth()?;
+
         if self.eat(b'B') {
             self.backref()?;
             return Ok(());
@@ -581,7 +607,6 @@ struct Printer<'a, 'b: 'a, 's> {
     parser: Result<Parser<'s>, Invalid>,
     out: LimitedFormatter<'a, 'b>,
     bound_lifetime_depth: u32,
-    depth: u32,
 }
 
 /// Mark the parser as errored, print `?` and return early.
@@ -620,15 +645,6 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
         self.parser_mut().map(|p| p.eat(b)) == Ok(true)
     }
 
-    fn bump_depth(&mut self) -> fmt::Result {
-        self.depth += 1;
-        if self.depth > MAX_DEPTH {
-            Err(fmt::Error)
-        } else {
-            Ok(())
-        }
-    }
-
     /// Return a nested parser for a backref.
     fn backref_printer<'c>(&'c mut self) -> Printer<'c, 'b, 's> {
         Printer {
@@ -638,7 +654,22 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
                 inner: self.out.inner,
             },
             bound_lifetime_depth: self.bound_lifetime_depth,
-            depth: self.depth,
+        }
+    }
+
+    fn push_depth(&mut self) -> bool {
+        match self.parser {
+            Err(_) => false,
+            Ok(ref mut parser) => {
+                let _ = parser.push_depth();
+                true
+            }
+        }
+    }
+
+    fn pop_depth(&mut self) {
+        if let Ok(ref mut parser) = self.parser {
+            parser.pop_depth();
         }
     }
 
@@ -674,7 +705,6 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
         F: FnOnce(&mut Self) -> fmt::Result,
     {
         let bound_lifetimes = parse!(self, opt_integer_62(b'G'));
-
         if bound_lifetimes > 0 {
             self.out.write_str("for<")?;
             for i in 0..bound_lifetimes {
@@ -714,7 +744,6 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
     }
 
     fn print_path(&mut self, in_value: bool) -> fmt::Result {
-        self.bump_depth()?;
         let tag = parse!(self, next);
         match tag {
             b'C' => {
@@ -788,11 +817,14 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
                 self.out.write_str(">")?;
             }
             b'B' => {
-                self.backref_printer().print_path(in_value)?;
+                let mut backref_printer = self.backref_printer();
+                backref_printer.print_path(in_value)?;
+                if backref_printer.parser.is_err() {
+                    return Err(fmt::Error);
+                }
             }
             _ => invalid!(self),
         }
-        self.depth -= 1;
         Ok(())
     }
 
@@ -814,7 +846,8 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
             return self.out.write_str(ty);
         }
 
-        self.bump_depth()?;
+        self.push_depth();
+
         match tag {
             b'R' | b'Q' => {
                 self.out.write_str("&")?;
@@ -931,7 +964,8 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
                 self.print_path(false)?;
             }
         }
-        self.depth -= 1;
+
+        self.pop_depth();
         Ok(())
     }
 
@@ -1189,6 +1223,574 @@ mod tests {
             "rand::rngs::adapter::reseeding::fork::FORK_HANDLER_REGISTERED.0.0"
         );
     }
+
+    #[test]
+    fn demangling_limits() {
+        // Stress tests found via fuzzing.
+
+        format!(
+            "{:?}",
+            ::demangle(
+                "RICu4$TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOSOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTT\
+TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTO\
+OOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTOOOOOOOOOOOOOOOOOOOO\
+OTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOO\
+TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\
+TTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTT\
+TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOO\
+OOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOO\
+OOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTT\
+TTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\
+TOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxx\
+xxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOTTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOO\
+OOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOT\
+TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOTTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\
+TTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOTTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOTTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOO\
+OOOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOTTTTTTTTTTOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTYTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\
+TTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOO\
+OOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTO\
+OOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOO\
+TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOT\
+TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOO\
+OOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTT\
+TTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\
+TTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTT\
+TTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxxxxRICu4\
+\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+TTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOO\
+OOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTT\
+TTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxxxxR\
+ICu5\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTT\
+TTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOO\
+OOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTT\
+TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxxxxRICu3\u{0005}\u{002c}\u{002d}xOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTO\
+OOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOxxxRICu4\u{002c}\u{002d}xxxxffff\u{0001}\u{0012}ffffffffffffffffffffffffffffffffffffffffffffff\
+ffffffffffxxxxxxxxxxxxxxxxxxxRaRBRaR\u{003e}R\u{003e}xxxu2IC\u{002c}\u{002d}xxxxxxRIC4xxxOOOOOOOOO\
+OOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\
+OOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxxxxRICu4\
+\u{0005}\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTT\
+TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOO\
+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOxxxRICu4\u{002c}\u{002d}xxxxffff\u{0001}\u{0012}fffffffffffffff\
+fffffffffffffffffffffffffffffffffffffffffxxxxxxxxxxxxxxxxxxxRaRBRaR\u{003e}R\u{003e}xxxu2IC\
+\u{002c}\u{002d}xxxxxxRIC4xxx\u{0001}\u{0000}K\u{0000}\u{0000}xRBRaR\u{003e}RICu6$\u{002d}RBKIQARI\
+Cu6$\u{002d}RBKIQAA\u{0001}\u{0000}\u{0000}\u{0000}\u{0000}\u{0000}\u{0000}\u{0004}TvvKKKKKKKKKxxx\
+xxxxxxxxxxxxBKIQARICu6$\u{002d}RBKIQAA\u{0001}\u{0000}\u{0000}\u{0000}_\u{0000}xxx"
+            )
+        );
+
+        format!(
+            "{:?}",
+            ::demangle(
+                "RIYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYRYYYYYYYYYXB_RXB_lYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYXYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYY\
+YYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyY\
+YYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYYYYYYYYYXB_RXB_lYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYFhhhhYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYNYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYRYYYYYYYYYXB_RXB_lYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYXYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYYYYYYYYYXB_R\
+XB_lYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYXYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYNYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYRYYYYYYYYYXB_RXB_lYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYY\
+YYXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYYYYYYYYYXB_RXB_lYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYFhhhhYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYyYYYYYYMYYYYNYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYYYYYYYYYXB_R\
+XB_lYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYXYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+MYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYYYYYYYYYXB_RXB_lYYYYYYYYYYYYYYYYYYYYYYYMYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYYYYYYYYYXB_RXB_lYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYIBRIIRIIBRCIByEEj_ByEEj_EEj"
+            )
+        );
+
+        format!(
+            "{:?}",
+            ::demangle(
+                "RYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRSSSSSSRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYY\
+YYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYY\
+YYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYY\
+YYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYR\
+YYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYY\
+YYYYYYYRYYYYYYYYYYYYYYYYYYSSSYYYYSSSSSSSSSSSSSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYSSSSRRRRRRRRRRRRRRRRRYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YY\
+YYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYY\
+YYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYY\
+YYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYY\
+YYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmY\
+YYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu\
+3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRR\
+RRRRRRRRRRRRRRRSSSSSSSRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYY\
+YYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSS\
+SSSSSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYY\
+YYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYY\
+YYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYY\
+YYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSS\
+SSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYY\
+YYYYYSSSSSSSSSSSSRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYY\
+YYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+PYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYY\
+YYSSSSSSSSSSSSSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRR\
+RRSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYR\
+YYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYb\
+YYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYY\
+YYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYY\
+YYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYY\
+YYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRSSSSSSSRRRRRRRRRRRRRRRRRYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3\
+YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYY\
+YYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYY\
+YYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYY\
+YYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYY\
+mYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYY\
+YYYYYYYYYSSSSSSSSSSSSRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYY\
+YYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSS\
+SSSSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYY\
+YYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYY\
+YYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYY\
+YYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRY\
+YYYYYYYYYYYYYYYYYSSSSSSSSSSSSRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSS\
+SSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYY\
+YYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYY\
+YYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYY\
+YYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYY\
+YYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYY\
+mYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYY\
+YYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSS\
+SSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyY\
+YYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYY\
+YYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYY\
+YRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSS\
+SSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYY\
+YYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSS\
+SSRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYY\
+YYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSS"
+            )
+        );
+
+        format!(
+            "{:?}",
+            ::demangle(
+                "RYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\
+R\u{003b}"
+            )
+        );
+
+        format!(
+            "{:?}",
+            ::demangle(
+                "RIC20tRYIMYNRYFG05_EB5_B_B6_RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
+RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRB_E"
+            )
+        );
+    }
 }
 
 struct LimitedFormatter<'a, 'b> {
diff --git a/vendor/rustfix-0.5.1/.cargo-checksum.json b/vendor/rustfix-0.5.1/.cargo-checksum.json
new file mode 100644 (file)
index 0000000..1f696d2
--- /dev/null
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"c23b7bf2ce467b70362c3124c52eb59b20491ad738cb5524ef060bf5241dc4a8","Changelog.md":"78b0b218038a68313eaf853aea4dd704efaea95d8c5b9a4590aeecd39564bc3b","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"06a5d0a2bfba711b0c19fa86c481bf08b38a84bd31a86648d9e207287d941e36","Readme.md":"bb47dd5f422a24973d4ad3fc368a7f5db9eaf4d5985ebe2287a5f3eca4b34f04","proptest-regressions/replace.txt":"9335379703ca7f8aa978c88d40c966cad42a592fed3e0b56513e9686f661232d","src/diagnostics.rs":"2d375d54d3648026402a298f68a29740bdb5c4bee5f49574cc0486f6ac0f369d","src/lib.rs":"32709660fc62235b7dceb9bc0369643def42267ea647cff638a8733e8981ccec","src/replace.rs":"f5ea534e99cde6d3a1bb89f6fdc1d9eca545efb25418ac4207854a9a6003376c"},"package":"f2c50b74badcddeb8f7652fa8323ce440b95286f8e4b64ebfd871c609672704e"}
\ No newline at end of file
diff --git a/vendor/rustfix-0.5.1/Cargo.toml b/vendor/rustfix-0.5.1/Cargo.toml
new file mode 100644 (file)
index 0000000..b22d85d
--- /dev/null
@@ -0,0 +1,52 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "rustfix"
+version = "0.5.1"
+authors = ["Pascal Hertleif <killercup@gmail.com>", "Oliver Schneider <oli-obk@users.noreply.github.com>"]
+exclude = ["etc/*", "examples/*", "tests/*"]
+description = "Automatically apply the suggestions made by rustc"
+documentation = "https://docs.rs/rustfix"
+readme = "Readme.md"
+license = "Apache-2.0/MIT"
+repository = "https://github.com/rust-lang-nursery/rustfix"
+[dependencies.anyhow]
+version = "1.0.0"
+
+[dependencies.log]
+version = "0.4.1"
+
+[dependencies.serde]
+version = "1.0"
+features = ["derive"]
+
+[dependencies.serde_json]
+version = "1.0"
+[dev-dependencies.difference]
+version = "2.0.0"
+
+[dev-dependencies.duct]
+version = "0.9"
+
+[dev-dependencies.env_logger]
+version = "0.5.0-rc.1"
+
+[dev-dependencies.log]
+version = "0.4.1"
+
+[dev-dependencies.proptest]
+version = "0.7.0"
+
+[dev-dependencies.tempdir]
+version = "0.3.5"
diff --git a/vendor/rustfix-0.5.1/Changelog.md b/vendor/rustfix-0.5.1/Changelog.md
new file mode 100644 (file)
index 0000000..1b57320
--- /dev/null
@@ -0,0 +1,79 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]
+
+## [0.4.6] - 2019-07-16
+
+### Changed
+
+Internal changes:
+
+- Change example to automatically determine filename
+- Migrate to Rust 2018
+- use `derive` feature over `serde_derive` crate
+
+## [0.4.5] - 2019-03-26
+
+### Added
+
+- Implement common traits for Diagnostic and related types
+
+### Fixed
+
+- Fix out of bounds access in parse_snippet
+
+## [0.4.4] - 2018-12-13
+
+### Added
+
+- Make Diagnostic::rendered public.
+
+### Changed
+
+- Revert faulty "Allow multiple solutions in a suggestion"
+
+## [0.4.3] - 2018-12-09 - *yanked!*
+
+### Added
+
+- Allow multiple solutions in a suggestion
+
+### Changed
+
+- use `RUSTC` environment var if present
+
+## [0.4.2] - 2018-07-31
+
+### Added
+
+- Expose an interface to apply fixes on-by-one
+
+### Changed
+
+- Handle invalid snippets instead of panicking
+
+## [0.4.1] - 2018-07-26
+
+### Changed
+
+- Ignore duplicate replacements
+
+## [0.4.0] - 2018-05-23
+
+### Changed
+
+- Filter by machine applicability by default
+
+[Unreleased]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.6...HEAD
+[0.4.6]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.5...rustfix-0.4.6
+[0.4.5]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.4...rustfix-0.4.5
+[0.4.4]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.3...rustfix-0.4.4
+[0.4.3]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.2...rustfix-0.4.3
+[0.4.2]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.1...rustfix-0.4.2
+[0.4.1]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.0...rustfix-0.4.1
+[0.4.0]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.0
diff --git a/vendor/rustfix-0.5.1/LICENSE-APACHE b/vendor/rustfix-0.5.1/LICENSE-APACHE
new file mode 100644 (file)
index 0000000..8f71f43
--- /dev/null
@@ -0,0 +1,202 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
diff --git a/vendor/rustfix-0.5.1/LICENSE-MIT b/vendor/rustfix-0.5.1/LICENSE-MIT
new file mode 100644 (file)
index 0000000..458e9c6
--- /dev/null
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Pascal Hertleif
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/rustfix-0.5.1/Readme.md b/vendor/rustfix-0.5.1/Readme.md
new file mode 100644 (file)
index 0000000..fb5eda8
--- /dev/null
@@ -0,0 +1,41 @@
+# rustfix
+
+The goal of this tool is to read and apply the suggestions made by rustc.
+
+## Current status
+
+Currently, rustfix is split into two crates:
+
+- `rustfix`, a library for consuming and applying suggestions in the format that `rustc` outputs
+- and `cargo-fix`, a binary that works as cargo subcommand and that end users will use to fix their code.
+
+The magic of rustfix is entirely dependent on the diagnostics implement in the Rust compiler (and external lints, like [clippy]).
+
+[clippy]: https://github.com/rust-lang-nursery/rust-clippy
+
+## Installation
+
+To use the rustfix library, add it to your `Cargo.toml`.
+
+To get the tool to automatically fix warnings in, run `cargo install cargo-fix`. This will give you `cargo fix`.
+
+## Using `cargo fix` to transition to Rust 2018
+
+Instructions on how to use this tool to transition a crate to Rust 2018 can be
+found [in the Rust Edition Guide.](https://rust-lang-nursery.github.io/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html)
+
+## License
+
+Licensed under either of
+
+- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
+- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally
+submitted for inclusion in the work by you, as defined in the Apache-2.0
+license, shall be dual licensed as above, without any additional terms or
+conditions.
diff --git a/vendor/rustfix-0.5.1/proptest-regressions/replace.txt b/vendor/rustfix-0.5.1/proptest-regressions/replace.txt
new file mode 100644 (file)
index 0000000..fc5bd1a
--- /dev/null
@@ -0,0 +1,8 @@
+# Seeds for failure cases proptest has generated in the past. It is
+# automatically read and these particular cases re-run before any
+# novel cases are generated.
+#
+# It is recommended to check this file in to source control so that
+# everyone who runs the test benefits from these saved cases.
+xs 358148376 3634975642 2528447681 3675516813 # shrinks to ref s = ""
+xs 3127423015 3362740891 2605681441 2390162043 # shrinks to ref data = "", ref replacements = [(0..0, [])]
diff --git a/vendor/rustfix-0.5.1/src/diagnostics.rs b/vendor/rustfix-0.5.1/src/diagnostics.rs
new file mode 100644 (file)
index 0000000..9e0be81
--- /dev/null
@@ -0,0 +1,89 @@
+//! Rustc Diagnostic JSON Output
+//!
+//! The following data types are copied from [rust-lang/rust](https://github.com/rust-lang/rust/blob/de78655bca47cac8e783dbb563e7e5c25c1fae40/src/libsyntax/json.rs)
+
+use serde::Deserialize;
+
+#[derive(Clone, Deserialize, Debug, Hash, Eq, PartialEq)]
+pub struct Diagnostic {
+    /// The primary error message.
+    pub message: String,
+    pub code: Option<DiagnosticCode>,
+    /// "error: internal compiler error", "error", "warning", "note", "help".
+    level: String,
+    pub spans: Vec<DiagnosticSpan>,
+    /// Associated diagnostic messages.
+    pub children: Vec<Diagnostic>,
+    /// The message as rustc would render it. Currently this is only
+    /// `Some` for "suggestions", but eventually it will include all
+    /// snippets.
+    pub rendered: Option<String>,
+}
+
+#[derive(Clone, Deserialize, Debug, Hash, Eq, PartialEq)]
+pub struct DiagnosticSpan {
+    pub file_name: String,
+    pub byte_start: u32,
+    pub byte_end: u32,
+    /// 1-based.
+    pub line_start: usize,
+    pub line_end: usize,
+    /// 1-based, character offset.
+    pub column_start: usize,
+    pub column_end: usize,
+    /// Is this a "primary" span -- meaning the point, or one of the points,
+    /// where the error occurred?
+    is_primary: bool,
+    /// Source text from the start of line_start to the end of line_end.
+    pub text: Vec<DiagnosticSpanLine>,
+    /// Label that should be placed at this location (if any)
+    label: Option<String>,
+    /// If we are suggesting a replacement, this will contain text
+    /// that should be sliced in atop this span. You may prefer to
+    /// load the fully rendered version from the parent `Diagnostic`,
+    /// however.
+    pub suggested_replacement: Option<String>,
+    pub suggestion_applicability: Option<Applicability>,
+    /// Macro invocations that created the code at this span, if any.
+    expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Deserialize, Hash, Eq)]
+pub enum Applicability {
+    MachineApplicable,
+    HasPlaceholders,
+    MaybeIncorrect,
+    Unspecified,
+}
+
+#[derive(Clone, Deserialize, Debug, Eq, PartialEq, Hash)]
+pub struct DiagnosticSpanLine {
+    pub text: String,
+
+    /// 1-based, character offset in self.text.
+    pub highlight_start: usize,
+
+    pub highlight_end: usize,
+}
+
+#[derive(Clone, Deserialize, Debug, Eq, PartialEq, Hash)]
+struct DiagnosticSpanMacroExpansion {
+    /// span where macro was applied to generate this code; note that
+    /// this may itself derive from a macro (if
+    /// `span.expansion.is_some()`)
+    span: DiagnosticSpan,
+
+    /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]")
+    macro_decl_name: String,
+
+    /// span where macro was defined (if known)
+    def_site_span: Option<DiagnosticSpan>,
+}
+
+#[derive(Clone, Deserialize, Debug, Eq, PartialEq, Hash)]
+pub struct DiagnosticCode {
+    /// The code itself.
+    pub code: String,
+    /// An explanation for the code.
+    explanation: Option<String>,
+}
diff --git a/vendor/rustfix-0.5.1/src/lib.rs b/vendor/rustfix-0.5.1/src/lib.rs
new file mode 100644 (file)
index 0000000..8304047
--- /dev/null
@@ -0,0 +1,268 @@
+#![warn(rust_2018_idioms)]
+
+#[macro_use]
+extern crate log;
+#[cfg(test)]
+#[macro_use]
+extern crate proptest;
+use serde_json;
+
+use std::collections::HashSet;
+use std::ops::Range;
+
+use anyhow::Error;
+
+pub mod diagnostics;
+use crate::diagnostics::{Diagnostic, DiagnosticSpan};
+mod replace;
+
+#[derive(Debug, Clone, Copy)]
+pub enum Filter {
+    MachineApplicableOnly,
+    Everything,
+}
+
+pub fn get_suggestions_from_json<S: ::std::hash::BuildHasher>(
+    input: &str,
+    only: &HashSet<String, S>,
+    filter: Filter,
+) -> serde_json::error::Result<Vec<Suggestion>> {
+    let mut result = Vec::new();
+    for cargo_msg in serde_json::Deserializer::from_str(input).into_iter::<Diagnostic>() {
+        // One diagnostic line might have multiple suggestions
+        result.extend(collect_suggestions(&cargo_msg?, only, filter));
+    }
+    Ok(result)
+}
+
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct LinePosition {
+    pub line: usize,
+    pub column: usize,
+}
+
+impl std::fmt::Display for LinePosition {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}:{}", self.line, self.column)
+    }
+}
+
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct LineRange {
+    pub start: LinePosition,
+    pub end: LinePosition,
+}
+
+impl std::fmt::Display for LineRange {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}-{}", self.start, self.end)
+    }
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+/// An error/warning and possible solutions for fixing it
+pub struct Suggestion {
+    pub message: String,
+    pub snippets: Vec<Snippet>,
+    pub solutions: Vec<Solution>,
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct Solution {
+    pub message: String,
+    pub replacements: Vec<Replacement>,
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct Snippet {
+    pub file_name: String,
+    pub line_range: LineRange,
+    pub range: Range<usize>,
+    /// leading surrounding text, text to replace, trailing surrounding text
+    ///
+    /// This split is useful for higlighting the part that gets replaced
+    pub text: (String, String, String),
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct Replacement {
+    pub snippet: Snippet,
+    pub replacement: String,
+}
+
+fn parse_snippet(span: &DiagnosticSpan) -> Option<Snippet> {
+    // unindent the snippet
+    let indent = span
+        .text
+        .iter()
+        .map(|line| {
+            let indent = line
+                .text
+                .chars()
+                .take_while(|&c| char::is_whitespace(c))
+                .count();
+            std::cmp::min(indent, line.highlight_start)
+        })
+        .min()?;
+
+    let text_slice = span.text[0].text.chars().collect::<Vec<char>>();
+
+    // We subtract `1` because these highlights are 1-based
+    // Check the `min` so that it doesn't attempt to index out-of-bounds when
+    // the span points to the "end" of the line. For example, a line of
+    // "foo\n" with a highlight_start of 5 is intended to highlight *after*
+    // the line. This needs to compensate since the newline has been removed
+    // from the text slice.
+    let start = (span.text[0].highlight_start - 1).min(text_slice.len());
+    let end = (span.text[0].highlight_end - 1).min(text_slice.len());
+    let lead = text_slice[indent..start].iter().collect();
+    let mut body: String = text_slice[start..end].iter().collect();
+
+    for line in span.text.iter().take(span.text.len() - 1).skip(1) {
+        body.push('\n');
+        body.push_str(&line.text[indent..]);
+    }
+    let mut tail = String::new();
+    let last = &span.text[span.text.len() - 1];
+
+    // If we get a DiagnosticSpanLine where highlight_end > text.len(), we prevent an 'out of
+    // bounds' access by making sure the index is within the array bounds.
+    // `saturating_sub` is used in case of an empty file
+    let last_tail_index = last.highlight_end.min(last.text.len()).saturating_sub(1);
+    let last_slice = last.text.chars().collect::<Vec<char>>();
+
+    if span.text.len() > 1 {
+        body.push('\n');
+        body.push_str(
+            &last_slice[indent..last_tail_index]
+                .iter()
+                .collect::<String>(),
+        );
+    }
+    tail.push_str(&last_slice[last_tail_index..].iter().collect::<String>());
+    Some(Snippet {
+        file_name: span.file_name.clone(),
+        line_range: LineRange {
+            start: LinePosition {
+                line: span.line_start,
+                column: span.column_start,
+            },
+            end: LinePosition {
+                line: span.line_end,
+                column: span.column_end,
+            },
+        },
+        range: (span.byte_start as usize)..(span.byte_end as usize),
+        text: (lead, body, tail),
+    })
+}
+
+fn collect_span(span: &DiagnosticSpan) -> Option<Replacement> {
+    let snippet = parse_snippet(span)?;
+    let replacement = span.suggested_replacement.clone()?;
+    Some(Replacement {
+        snippet,
+        replacement,
+    })
+}
+
+pub fn collect_suggestions<S: ::std::hash::BuildHasher>(
+    diagnostic: &Diagnostic,
+    only: &HashSet<String, S>,
+    filter: Filter,
+) -> Option<Suggestion> {
+    if !only.is_empty() {
+        if let Some(ref code) = diagnostic.code {
+            if !only.contains(&code.code) {
+                // This is not the code we are looking for
+                return None;
+            }
+        } else {
+            // No code, probably a weird builtin warning/error
+            return None;
+        }
+    }
+
+    let snippets = diagnostic
+        .spans
+        .iter()
+        .filter_map(|span| parse_snippet(span))
+        .collect();
+
+    let solutions: Vec<_> = diagnostic
+        .children
+        .iter()
+        .filter_map(|child| {
+            let replacements: Vec<_> = child
+                .spans
+                .iter()
+                .filter(|span| {
+                    use crate::diagnostics::Applicability::*;
+                    use crate::Filter::*;
+
+                    match (filter, &span.suggestion_applicability) {
+                        (MachineApplicableOnly, Some(MachineApplicable)) => true,
+                        (MachineApplicableOnly, _) => false,
+                        (Everything, _) => true,
+                    }
+                })
+                .filter_map(collect_span)
+                .collect();
+            if replacements.len() == 1 {
+                Some(Solution {
+                    message: child.message.clone(),
+                    replacements,
+                })
+            } else {
+                None
+            }
+        })
+        .collect();
+
+    if solutions.is_empty() {
+        None
+    } else {
+        Some(Suggestion {
+            message: diagnostic.message.clone(),
+            snippets,
+            solutions,
+        })
+    }
+}
+
+pub struct CodeFix {
+    data: replace::Data,
+}
+
+impl CodeFix {
+    pub fn new(s: &str) -> CodeFix {
+        CodeFix {
+            data: replace::Data::new(s.as_bytes()),
+        }
+    }
+
+    pub fn apply(&mut self, suggestion: &Suggestion) -> Result<(), Error> {
+        for sol in &suggestion.solutions {
+            for r in &sol.replacements {
+                self.data.replace_range(
+                    r.snippet.range.start,
+                    r.snippet.range.end.saturating_sub(1),
+                    r.replacement.as_bytes(),
+                )?;
+            }
+        }
+        Ok(())
+    }
+
+    pub fn finish(&self) -> Result<String, Error> {
+        Ok(String::from_utf8(self.data.to_vec())?)
+    }
+}
+
+pub fn apply_suggestions(code: &str, suggestions: &[Suggestion]) -> Result<String, Error> {
+    let mut fix = CodeFix::new(code);
+    for suggestion in suggestions.iter().rev() {
+        fix.apply(suggestion)?;
+    }
+    fix.finish()
+}
diff --git a/vendor/rustfix-0.5.1/src/replace.rs b/vendor/rustfix-0.5.1/src/replace.rs
new file mode 100644 (file)
index 0000000..8071049
--- /dev/null
@@ -0,0 +1,327 @@
+//! A small module giving you a simple container that allows easy and cheap
+//! replacement of parts of its content, with the ability to prevent changing
+//! the same parts multiple times.
+
+use anyhow::{anyhow, ensure, Error};
+use std::rc::Rc;
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+enum State {
+    Initial,
+    Replaced(Rc<[u8]>),
+    Inserted(Rc<[u8]>),
+}
+
+impl State {
+    fn is_inserted(&self) -> bool {
+        if let State::Inserted(..) = *self {
+            true
+        } else {
+            false
+        }
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+struct Span {
+    /// Start of this span in parent data
+    start: usize,
+    /// up to end including
+    end: usize,
+    data: State,
+}
+
+/// A container that allows easily replacing chunks of its data
+#[derive(Debug, Clone, Default)]
+pub struct Data {
+    original: Vec<u8>,
+    parts: Vec<Span>,
+}
+
+impl Data {
+    /// Create a new data container from a slice of bytes
+    pub fn new(data: &[u8]) -> Self {
+        Data {
+            original: data.into(),
+            parts: vec![Span {
+                data: State::Initial,
+                start: 0,
+                end: data.len().saturating_sub(1),
+            }],
+        }
+    }
+
+    /// Render this data as a vector of bytes
+    pub fn to_vec(&self) -> Vec<u8> {
+        if self.original.is_empty() {
+            return Vec::new();
+        }
+
+        self.parts.iter().fold(Vec::new(), |mut acc, d| {
+            match d.data {
+                State::Initial => acc.extend_from_slice(&self.original[d.start..=d.end]),
+                State::Replaced(ref d) | State::Inserted(ref d) => acc.extend_from_slice(&d),
+            };
+            acc
+        })
+    }
+
+    /// Replace a chunk of data with the given slice, erroring when this part
+    /// was already changed previously.
+    pub fn replace_range(
+        &mut self,
+        from: usize,
+        up_to_and_including: usize,
+        data: &[u8],
+    ) -> Result<(), Error> {
+        let exclusive_end = up_to_and_including + 1;
+
+        ensure!(
+            from <= exclusive_end,
+            "Invalid range {}...{}, start is larger than end",
+            from,
+            up_to_and_including
+        );
+
+        ensure!(
+            up_to_and_including <= self.original.len(),
+            "Invalid range {}...{} given, original data is only {} byte long",
+            from,
+            up_to_and_including,
+            self.original.len()
+        );
+
+        let insert_only = from == exclusive_end;
+
+        // Since we error out when replacing an already replaced chunk of data,
+        // we can take some shortcuts here. For example, there can be no
+        // overlapping replacements -- we _always_ split a chunk of 'initial'
+        // data into three[^empty] parts, and there can't ever be two 'initial'
+        // parts touching.
+        //
+        // [^empty]: Leading and trailing ones might be empty if we replace
+        // the whole chunk. As an optimization and without loss of generality we
+        // don't add empty parts.
+        let new_parts = {
+            let index_of_part_to_split = self
+                .parts
+                .iter()
+                .position(|p| {
+                    !p.data.is_inserted() && p.start <= from && p.end >= up_to_and_including
+                })
+                .ok_or_else(|| {
+                    use log::Level::Debug;
+                    if log_enabled!(Debug) {
+                        let slices = self
+                            .parts
+                            .iter()
+                            .map(|p| {
+                                (
+                                    p.start,
+                                    p.end,
+                                    match p.data {
+                                        State::Initial => "initial",
+                                        State::Replaced(..) => "replaced",
+                                        State::Inserted(..) => "inserted",
+                                    },
+                                )
+                            })
+                            .collect::<Vec<_>>();
+                        debug!(
+                            "no single slice covering {}...{}, current slices: {:?}",
+                            from, up_to_and_including, slices,
+                        );
+                    }
+
+                    anyhow!(
+                        "Could not replace range {}...{} in file \
+                         -- maybe parts of it were already replaced?",
+                        from,
+                        up_to_and_including
+                    )
+                })?;
+
+            let part_to_split = &self.parts[index_of_part_to_split];
+
+            // If this replacement matches exactly the part that we would
+            // otherwise split then we ignore this for now. This means that you
+            // can replace the exact same range with the exact same content
+            // multiple times and we'll process and allow it.
+            //
+            // This is currently done to alleviate issues like
+            // rust-lang/rust#51211 although this clause likely wants to be
+            // removed if that's fixed deeper in the compiler.
+            if part_to_split.start == from && part_to_split.end == up_to_and_including {
+                if let State::Replaced(ref replacement) = part_to_split.data {
+                    if &**replacement == data {
+                        return Ok(());
+                    }
+                }
+            }
+
+            ensure!(
+                part_to_split.data == State::Initial,
+                "Cannot replace slice of data that was already replaced"
+            );
+
+            let mut new_parts = Vec::with_capacity(self.parts.len() + 2);
+
+            // Previous parts
+            if let Some(ps) = self.parts.get(..index_of_part_to_split) {
+                new_parts.extend_from_slice(&ps);
+            }
+
+            // Keep initial data on left side of part
+            if from > part_to_split.start {
+                new_parts.push(Span {
+                    start: part_to_split.start,
+                    end: from.saturating_sub(1),
+                    data: State::Initial,
+                });
+            }
+
+            // New part
+            new_parts.push(Span {
+                start: from,
+                end: up_to_and_including,
+                data: if insert_only {
+                    State::Inserted(data.into())
+                } else {
+                    State::Replaced(data.into())
+                },
+            });
+
+            // Keep initial data on right side of part
+            if up_to_and_including < part_to_split.end {
+                new_parts.push(Span {
+                    start: up_to_and_including + 1,
+                    end: part_to_split.end,
+                    data: State::Initial,
+                });
+            }
+
+            // Following parts
+            if let Some(ps) = self.parts.get(index_of_part_to_split + 1..) {
+                new_parts.extend_from_slice(&ps);
+            }
+
+            new_parts
+        };
+
+        self.parts = new_parts;
+
+        Ok(())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use proptest::prelude::*;
+
+    fn str(i: &[u8]) -> &str {
+        ::std::str::from_utf8(i).unwrap()
+    }
+
+    #[test]
+    fn replace_some_stuff() {
+        let mut d = Data::new(b"foo bar baz");
+        d.replace_range(4, 6, b"lol").unwrap();
+        assert_eq!("foo lol baz", str(&d.to_vec()));
+    }
+
+    #[test]
+    fn replace_a_single_char() {
+        let mut d = Data::new(b"let y = true;");
+        d.replace_range(4, 4, b"mut y").unwrap();
+        assert_eq!("let mut y = true;", str(&d.to_vec()));
+    }
+
+    #[test]
+    fn replace_multiple_lines() {
+        let mut d = Data::new(b"lorem\nipsum\ndolor");
+
+        d.replace_range(6, 10, b"lol").unwrap();
+        assert_eq!("lorem\nlol\ndolor", str(&d.to_vec()));
+
+        d.replace_range(12, 16, b"lol").unwrap();
+        assert_eq!("lorem\nlol\nlol", str(&d.to_vec()));
+    }
+
+    #[test]
+    fn replace_multiple_lines_with_insert_only() {
+        let mut d = Data::new(b"foo!");
+
+        d.replace_range(3, 2, b"bar").unwrap();
+        assert_eq!("foobar!", str(&d.to_vec()));
+
+        d.replace_range(0, 2, b"baz").unwrap();
+        assert_eq!("bazbar!", str(&d.to_vec()));
+
+        d.replace_range(3, 3, b"?").unwrap();
+        assert_eq!("bazbar?", str(&d.to_vec()));
+    }
+
+    #[test]
+    fn replace_invalid_range() {
+        let mut d = Data::new(b"foo!");
+
+        assert!(d.replace_range(2, 0, b"bar").is_err());
+        assert!(d.replace_range(0, 2, b"bar").is_ok());
+    }
+
+    #[test]
+    fn empty_to_vec_roundtrip() {
+        let s = "";
+        assert_eq!(s.as_bytes(), Data::new(s.as_bytes()).to_vec().as_slice());
+    }
+
+    #[test]
+    #[should_panic(expected = "Cannot replace slice of data that was already replaced")]
+    fn replace_overlapping_stuff_errs() {
+        let mut d = Data::new(b"foo bar baz");
+
+        d.replace_range(4, 6, b"lol").unwrap();
+        assert_eq!("foo lol baz", str(&d.to_vec()));
+
+        d.replace_range(4, 6, b"lol2").unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "original data is only 3 byte long")]
+    fn broken_replacements() {
+        let mut d = Data::new(b"foo");
+        d.replace_range(4, 7, b"lol").unwrap();
+    }
+
+    #[test]
+    fn replace_same_twice() {
+        let mut d = Data::new(b"foo");
+        d.replace_range(0, 0, b"b").unwrap();
+        d.replace_range(0, 0, b"b").unwrap();
+        assert_eq!("boo", str(&d.to_vec()));
+    }
+
+    proptest! {
+        #[test]
+        #[ignore]
+        fn new_to_vec_roundtrip(ref s in "\\PC*") {
+            assert_eq!(s.as_bytes(), Data::new(s.as_bytes()).to_vec().as_slice());
+        }
+
+        #[test]
+        #[ignore]
+        fn replace_random_chunks(
+            ref data in "\\PC*",
+            ref replacements in prop::collection::vec(
+                (any::<::std::ops::Range<usize>>(), any::<Vec<u8>>()),
+                1..1337,
+            )
+        ) {
+            let mut d = Data::new(data.as_bytes());
+            for &(ref range, ref bytes) in replacements {
+                let _ = d.replace_range(range.start, range.end, bytes);
+            }
+        }
+    }
+}
index 1f696d240edfb59cdee66a415d87ca994e441499..bbcaebebd2ffe844b9f21cf22eba3bab87e3917c 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.toml":"c23b7bf2ce467b70362c3124c52eb59b20491ad738cb5524ef060bf5241dc4a8","Changelog.md":"78b0b218038a68313eaf853aea4dd704efaea95d8c5b9a4590aeecd39564bc3b","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"06a5d0a2bfba711b0c19fa86c481bf08b38a84bd31a86648d9e207287d941e36","Readme.md":"bb47dd5f422a24973d4ad3fc368a7f5db9eaf4d5985ebe2287a5f3eca4b34f04","proptest-regressions/replace.txt":"9335379703ca7f8aa978c88d40c966cad42a592fed3e0b56513e9686f661232d","src/diagnostics.rs":"2d375d54d3648026402a298f68a29740bdb5c4bee5f49574cc0486f6ac0f369d","src/lib.rs":"32709660fc62235b7dceb9bc0369643def42267ea647cff638a8733e8981ccec","src/replace.rs":"f5ea534e99cde6d3a1bb89f6fdc1d9eca545efb25418ac4207854a9a6003376c"},"package":"f2c50b74badcddeb8f7652fa8323ce440b95286f8e4b64ebfd871c609672704e"}
\ No newline at end of file
+{"files":{"Cargo.toml":"f0de4b9ea573329a4cd79e731eab045cbcc2adee82734328187b244a7ccaa439","Changelog.md":"78b0b218038a68313eaf853aea4dd704efaea95d8c5b9a4590aeecd39564bc3b","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"06a5d0a2bfba711b0c19fa86c481bf08b38a84bd31a86648d9e207287d941e36","Readme.md":"09bdc5d9182bc18afb3574d9c8e668c32293e2be25c5e363e13d3b1ddddf092b","proptest-regressions/replace.txt":"9335379703ca7f8aa978c88d40c966cad42a592fed3e0b56513e9686f661232d","src/diagnostics.rs":"2d375d54d3648026402a298f68a29740bdb5c4bee5f49574cc0486f6ac0f369d","src/lib.rs":"16afd7b1bb29e61015d8a62b9e3031dbf5b7f3091b4b47797ad73942600d7011","src/replace.rs":"3f2acd70e45b208ec3af25d88bdbc11ca8b73539f0a46e4538848ecedc19335e"},"package":"6f0be05fc0675ef4f47119dc39cfc46636bb77d4fc4ef1bd851b9c3f7697f32a"}
\ No newline at end of file
index b22d85daf2376d59991db36d573403eb8c9d39b4..823e09b13188399143f1dd862e7d08b4c4c61c33 100644 (file)
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "rustfix"
-version = "0.5.1"
+version = "0.6.0"
 authors = ["Pascal Hertleif <killercup@gmail.com>", "Oliver Schneider <oli-obk@users.noreply.github.com>"]
 exclude = ["etc/*", "examples/*", "tests/*"]
 description = "Automatically apply the suggestions made by rustc"
@@ -33,9 +33,6 @@ features = ["derive"]
 
 [dependencies.serde_json]
 version = "1.0"
-[dev-dependencies.difference]
-version = "2.0.0"
-
 [dev-dependencies.duct]
 version = "0.9"
 
@@ -48,5 +45,8 @@ version = "0.4.1"
 [dev-dependencies.proptest]
 version = "0.7.0"
 
+[dev-dependencies.similar]
+version = "0.4.0"
+
 [dev-dependencies.tempdir]
 version = "0.3.5"
index fb5eda843bdc3f8935f159f7cda704c0649bdf24..ce9021ac90c22ae27485e0ca13eb85dea9ab3ab2 100644 (file)
@@ -9,7 +9,7 @@ Currently, rustfix is split into two crates:
 - `rustfix`, a library for consuming and applying suggestions in the format that `rustc` outputs
 - and `cargo-fix`, a binary that works as cargo subcommand and that end users will use to fix their code.
 
-The magic of rustfix is entirely dependent on the diagnostics implement in the Rust compiler (and external lints, like [clippy]).
+The magic of rustfix is entirely dependent on the diagnostics implemented in the Rust compiler (and external lints, like [clippy]).
 
 [clippy]: https://github.com/rust-lang-nursery/rust-clippy
 
index 83040477e566020d72b16ca38a57bb69eb19335c..0be5f52abc448fe4a8bcca78645f76a145b5b96e 100644 (file)
@@ -5,7 +5,6 @@ extern crate log;
 #[cfg(test)]
 #[macro_use]
 extern crate proptest;
-use serde_json;
 
 use std::collections::HashSet;
 use std::ops::Range;
@@ -208,7 +207,7 @@ pub fn collect_suggestions<S: ::std::hash::BuildHasher>(
                 })
                 .filter_map(collect_span)
                 .collect();
-            if replacements.len() == 1 {
+            if replacements.len() >= 1 {
                 Some(Solution {
                     message: child.message.clone(),
                     replacements,
index 80710493965e53c424fa2dd0c69a2d863a38413b..ff5e58ad7c7a38915dd59ba477683d1a80087bf3 100644 (file)
@@ -14,11 +14,7 @@ enum State {
 
 impl State {
     fn is_inserted(&self) -> bool {
-        if let State::Inserted(..) = *self {
-            true
-        } else {
-            false
-        }
+        matches!(*self, State::Inserted(..))
     }
 }
 
index e1277df7b59572cb40793987fcc794bde5728a13..0a134695aaf806f11a7c6f31009194eef7bc5510 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.toml":"1a91782510461d54726e816ae776042b95c79c9949d49c11b8782caefc22ead2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"01dc6a1bf499a12bd0bfbbfe4db2ca8460b2c151235bcf2aad2356de4c2ec50a","build/build.rs":"481daf363b7004c90ffc3e012863a4102e9f26b9aaa2a4a295c2dd78f690be28","build/rustc.rs":"4dc8f1764672137bd15758cc19242740b0d6ab99e4a69171ad0999f9112a15a6","src/attr.rs":"9301cd4aff5a9648c057d5d8de9eb66921f0c3a715c51ada4459576bd49c8b19","src/bound.rs":"44bda74d3aacfeeeac9dae2f7eef3acc844d4c3c7eaa9d3e6288e5aeff269dff","src/constfn.rs":"613b8f53b21cc06b4f619fce9000993d3e7873b650701ca01cef1e53bed5b40a","src/date.rs":"454c749a60db8144a706a813e06fe3ae39c981920ba9832ef82f3f9debe1f052","src/error.rs":"cb37102f03ebbaca313d80f9714fe08dfef92fe956789ee87d93eb6121705f4f","src/expr.rs":"8e8ca76f4f5838436d9d7273f499c698bb41f6c15bc07d32ec5c1cb8bd3dd731","src/iter.rs":"8d4b817b9abc4e817105b673e15f29ef9bb8284a010ce01ac2d83387fe136947","src/lib.rs":"f8347832d8072058dbb4af6b8d67a834a02fe9c5460bbaa26defec4b66317f1b","src/release.rs":"abb8ddd877c39a023bf5e7bd67063d6e4144e79758a8bafa338167f9d15b89f1","src/time.rs":"45fb48ff0a0046a5a1b108b9ce53b14885637ad868ede1d66970379c2b7f16ef","src/token.rs":"824ce765f692db73afa02d3ebb0281c750748035efc98fa547be29d3072665ce","src/version.rs":"afdb048bba95bbb885945eba5527b6bf0eca0105642bfc304c2f82a8b7d556df","tests/compiletest.rs":"0a52a44786aea1c299c695bf948b2ed2081e4cc344e5c2cadceab4eb03d0010d","tests/test_const.rs":"a8297ca6559f895a3b2664964a42b6f82bbbc3c8faa9556a513006e6e1827995","tests/test_eval.rs":"6f0ee3f49c9a0d0c374a4d0e9a9dce753cd9fc2ca7725e000a435dbd5f4a9ce3","tests/test_parse.rs":"fbf9695f4208263743715e6c8b6294dfffee21462a65dfeb9339a70c0e18dbc6","tests/ui/bad-bound.rs":"25bde278fcaabf62868417148a5e5f2006bf589d7ebd7bf6004fb8d78e47594f","tests/ui/bad-bound.stderr":"bc9297f758c2541fb0a8b48d5785f4bbcd0d2a07d876ba0baf2fc9de9275e7e6","tests/ui/bad-date.rs":"6e23714dae8b6346fefe50dacd4abba3265248bbadfdd60c739138aa8a0037ba","tests/ui/bad-date.stderr":"1ac3cab13ee900fc8344e8fab21ff4d9cad476aca44925a4c1b2293a6b59b742","tests/ui/bad-not.rs":"f003df8bd245e9dd8edc3a6d94078ee5162fac7a98db881271f0f5b6db98d45d","tests/ui/bad-not.stderr":"d4ef78fae4a82419e737757158796cb103a5920df498956eaf57ed201797b463","tests/ui/bad-version.rs":"f4ea2cd038e6c63deb9c2e3ceffce93dbf179d9ce18c16d88f3b6cd7138a8c8e","tests/ui/bad-version.stderr":"60ed51c62f4c2fb6ff95cff7523cfca379ed434f319da9d82704318588792338","tests/ui/const-not-fn.rs":"10bbe38f0d89391fff0698756e4cfd4e72a41090360393a0c951b67df14d1c35","tests/ui/const-not-fn.stderr":"9551f7f222445b31d7af2415d467301c332d55bb3d5a143846484f2f00047a01"},"package":"cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd"}
\ No newline at end of file
+{"files":{"Cargo.toml":"a09ee758f816eddff8a8c7fb5be54dd95e74caad18a207251faedd251ecfaf1c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"01dc6a1bf499a12bd0bfbbfe4db2ca8460b2c151235bcf2aad2356de4c2ec50a","build/build.rs":"bae427f344972e6e0e348ec48dce0947274b3ec6cac0938497a8d3da5c9834e5","build/rustc.rs":"3e4acf7ea679f9331dd4e8dbe42a08a312f58379ea1eee5898793a9848d06d8c","src/attr.rs":"9301cd4aff5a9648c057d5d8de9eb66921f0c3a715c51ada4459576bd49c8b19","src/bound.rs":"44bda74d3aacfeeeac9dae2f7eef3acc844d4c3c7eaa9d3e6288e5aeff269dff","src/constfn.rs":"613b8f53b21cc06b4f619fce9000993d3e7873b650701ca01cef1e53bed5b40a","src/date.rs":"454c749a60db8144a706a813e06fe3ae39c981920ba9832ef82f3f9debe1f052","src/error.rs":"cb37102f03ebbaca313d80f9714fe08dfef92fe956789ee87d93eb6121705f4f","src/expr.rs":"8e8ca76f4f5838436d9d7273f499c698bb41f6c15bc07d32ec5c1cb8bd3dd731","src/iter.rs":"8d4b817b9abc4e817105b673e15f29ef9bb8284a010ce01ac2d83387fe136947","src/lib.rs":"5652f6f84fc80136bd29b2125f7676e80e0df7d40aac274b0658c99cecbd871d","src/release.rs":"abb8ddd877c39a023bf5e7bd67063d6e4144e79758a8bafa338167f9d15b89f1","src/time.rs":"bdd05a743b07a6bbfa0dbc9d4e415e051aba4a51a430c3be1e23447eae298c8b","src/token.rs":"824ce765f692db73afa02d3ebb0281c750748035efc98fa547be29d3072665ce","src/version.rs":"afdb048bba95bbb885945eba5527b6bf0eca0105642bfc304c2f82a8b7d556df","tests/compiletest.rs":"0a52a44786aea1c299c695bf948b2ed2081e4cc344e5c2cadceab4eb03d0010d","tests/test_const.rs":"a8297ca6559f895a3b2664964a42b6f82bbbc3c8faa9556a513006e6e1827995","tests/test_eval.rs":"6f0ee3f49c9a0d0c374a4d0e9a9dce753cd9fc2ca7725e000a435dbd5f4a9ce3","tests/test_parse.rs":"cdfe376020b9391330292968046117b0935c828d73385e8faeb2e333ec897088","tests/ui/bad-bound.rs":"25bde278fcaabf62868417148a5e5f2006bf589d7ebd7bf6004fb8d78e47594f","tests/ui/bad-bound.stderr":"a03dc78b380191c10d3b3406b1fd3208bb2609d4c26b9c33ccd335721e3cd072","tests/ui/bad-date.rs":"6e23714dae8b6346fefe50dacd4abba3265248bbadfdd60c739138aa8a0037ba","tests/ui/bad-date.stderr":"3a607fb950a69f7dc1b503295bce53541f9dee9f4674edc5d13ee3a69ff0e8cd","tests/ui/bad-not.rs":"f003df8bd245e9dd8edc3a6d94078ee5162fac7a98db881271f0f5b6db98d45d","tests/ui/bad-not.stderr":"d4ef78fae4a82419e737757158796cb103a5920df498956eaf57ed201797b463","tests/ui/bad-version.rs":"f4ea2cd038e6c63deb9c2e3ceffce93dbf179d9ce18c16d88f3b6cd7138a8c8e","tests/ui/bad-version.stderr":"60ed51c62f4c2fb6ff95cff7523cfca379ed434f319da9d82704318588792338","tests/ui/const-not-fn.rs":"10bbe38f0d89391fff0698756e4cfd4e72a41090360393a0c951b67df14d1c35","tests/ui/const-not-fn.stderr":"9551f7f222445b31d7af2415d467301c332d55bb3d5a143846484f2f00047a01"},"package":"61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"}
\ No newline at end of file
index 56995ff07922c8b36130fd02116aef350baee6eb..c72b1b2b343e9ede4211668893a2eaf65e068217 100644 (file)
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "rustversion"
-version = "1.0.4"
+version = "1.0.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 build = "build/build.rs"
 description = "Conditional compilation according to rustc compiler version"
index 2a8bc4af39fd2ea1530a525e89fd6002d63a9cc5..15312510d683629d98fbbb866b85099fb6462265 100644 (file)
@@ -1,3 +1,9 @@
+#![allow(
+    clippy::enum_glob_use,
+    clippy::must_use_candidate,
+    clippy::single_match_else
+)]
+
 mod rustc;
 
 use std::env;
index 723e6bdd0e2690650b6b60bdffe07c1bd1acb027..dfc6a05166f9a4f81d9249ac42d608b3d3a94daf 100644 (file)
@@ -48,23 +48,21 @@ pub fn parse(string: &str) -> Option<Version> {
         Some(channel) if channel == "dev" => Dev,
         Some(channel) if channel.starts_with("beta") => Beta,
         Some(channel) if channel == "nightly" => match words.next() {
-            Some(hash) => {
-                if !hash.starts_with('(') {
-                    return None;
+            Some(hash) if hash.starts_with('(') => match words.next() {
+                None if hash.ends_with(')') => Dev,
+                Some(date) if date.ends_with(')') => {
+                    let mut date = date[..date.len() - 1].split('-');
+                    let year = date.next()?.parse().ok()?;
+                    let month = date.next()?.parse().ok()?;
+                    let day = date.next()?.parse().ok()?;
+                    match date.next() {
+                        None => Nightly(Date { year, month, day }),
+                        Some(_) => return None,
+                    }
                 }
-                let date = words.next()?;
-                if !date.ends_with(')') {
-                    return None;
-                }
-                let mut date = date[..date.len() - 1].split('-');
-                let year = date.next()?.parse().ok()?;
-                let month = date.next()?.parse().ok()?;
-                let day = date.next()?.parse().ok()?;
-                match date.next() {
-                    None => Nightly(Date { year, month, day }),
-                    Some(_) => return None,
-                }
-            }
+                None | Some(_) => return None,
+            },
+            Some(_) => return None,
             None => Dev,
         },
         Some(_) => return None,
index 2614105dd1ab6cec7028ea08e8daa52e512f77a7..172eb89382f61b2b456b10bee5942730db035683 100644 (file)
 //!
 //! <br>
 
+#![allow(
+    clippy::cast_lossless,
+    clippy::cast_possible_truncation,
+    clippy::doc_markdown,
+    clippy::enum_glob_use,
+    clippy::from_iter_instead_of_collect,
+    clippy::module_name_repetitions,
+    clippy::must_use_candidate,
+    clippy::needless_doctest_main,
+    clippy::needless_pass_by_value,
+    clippy::redundant_else,
+    clippy::toplevel_ref_arg,
+    clippy::unreadable_literal
+)]
+
 extern crate proc_macro;
 
 mod attr;
index 1e6dd9066b48d945a0a9698b0eb737f00460b5ba..3c21463dd80b5d0b230b579875939fd630125f08 100644 (file)
@@ -1,4 +1,5 @@
 use crate::date::Date;
+use std::env;
 use std::time::{SystemTime, UNIX_EPOCH};
 
 // Timestamp of 2016-03-01 00:00:00 in UTC.
@@ -13,14 +14,20 @@ const DAYS_BY_MONTH: [u8; 12] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
 
 pub fn today() -> Date {
     let default = Date {
-        year: 2019,
-        month: 1,
-        day: 1,
+        year: 2020,
+        month: 2,
+        day: 25,
     };
     try_today().unwrap_or(default)
 }
 
 fn try_today() -> Option<Date> {
+    if let Some(pkg_name) = env::var_os("CARGO_PKG_NAME") {
+        if pkg_name.to_str() == Some("rustversion-tests") {
+            return None; // Stable date for ui testing.
+        }
+    }
+
     let now = SystemTime::now();
     let since_epoch = now.duration_since(UNIX_EPOCH).ok()?;
     let secs = since_epoch.as_secs();
index 843bd73d3e59d8d38d75adba4795dec46651a67a..cb39b3179f57ef90d94a682b275718fc99175065 100644 (file)
@@ -1,3 +1,5 @@
+#![allow(clippy::enum_glob_use, clippy::must_use_candidate)]
+
 include!("../build/rustc.rs");
 
 #[test]
@@ -76,6 +78,14 @@ fn test_parse() {
                 }),
             },
         ),
+        (
+            "rustc 1.52.1-nightly (gentoo)",
+            Version {
+                minor: 52,
+                patch: 1,
+                channel: Dev,
+            },
+        ),
     ];
 
     for (string, expected) in cases {
index f8c498c85771ff035637c063c9f2fef7238e4488..2c56acbdb33698da37f7c8611b2581f074c619a1 100644 (file)
@@ -1,10 +1,10 @@
-error: expected rustc release number like 1.31, or nightly date like 2020-10-26
+error: expected rustc release number like 1.31, or nightly date like 2020-02-25
  --> $DIR/bad-bound.rs:1:22
   |
 1 | #[rustversion::since(stable)]
   |                      ^^^^^^
 
-error: expected rustc release number like 1.31, or nightly date like 2020-10-26
+error: expected rustc release number like 1.31, or nightly date like 2020-02-25
  --> $DIR/bad-bound.rs:4:26
   |
 4 | #[rustversion::any(since(stable))]
index 734d7889075d9f675d1b4a620c7ccdcd6b423655..c523ccc02bf96b51c64d6d9245e0f67f4a018fd4 100644 (file)
@@ -1,10 +1,10 @@
-error: expected nightly date, like 2020-10-26
+error: expected nightly date, like 2020-02-25
  --> $DIR/bad-date.rs:1:24
   |
 1 | #[rustversion::nightly(stable)]
   |                        ^^^^^^
 
-error: expected nightly date, like 2020-10-26
+error: expected nightly date, like 2020-02-25
  --> $DIR/bad-date.rs:4:28
   |
 4 | #[rustversion::any(nightly(stable))]
diff --git a/vendor/semver-0.10.0/.cargo-checksum.json b/vendor/semver-0.10.0/.cargo-checksum.json
deleted file mode 100644 (file)
index 27535e0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"992610e30320fc405f36d0ec380c4735047770b8b05054797667c493b3fd0d16","LICENSE-APACHE":"7cfd738c53d61c79f07e348f622bf7707c9084237054d37fbe07788a75f5881c","LICENSE-MIT":"705aaaaecefa087c187bd2eacdb01b8ac1c5ee95b1d5d04d8d7efe0363207df8","README.md":"eb709d3b48283852fabf0b4cb4cceb4196442b69bf52a9ff3f99c653471d9162","src/diesel_impls.rs":"cd464d4d6e2a83f9c4bf7b84af565b6b6543e95555869c3186eb3bc2de6b54e9","src/lib.rs":"4a4b2db5e45d31f99c0c5f1befbb9fde91fa39007625a026e7f10a1f69c8556b","src/version.rs":"832fd1abcfa1d8aacaed09f6034dea76e024fe7c8b63d2547cf6d862c98f6732","src/version_req.rs":"be40b4eac3352bce7b6e8bd5ba3d64fc7476ad2ac9b33213c1fa7697090b3e71","tests/deprecation.rs":"c7159e7760a43ef786b595513134ab5657729ff766f3880e0e6340f7b1c822dd","tests/diesel.rs":"02538cea9d97e1fff59c3130b1ae5ae9df4149e5074fb9a707822e5dc083a83b","tests/serde.rs":"ddab1bde99a7a8aec23b1e7ee8a1ef563084201d00c53322cc9ae9fb972b71c4"},"package":"394cec28fa623e00903caf7ba4fa6fb9a0e260280bb8cdbbba029611108a0190"}
\ No newline at end of file
diff --git a/vendor/semver-0.10.0/Cargo.toml b/vendor/semver-0.10.0/Cargo.toml
deleted file mode 100644 (file)
index b04b424..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-name = "semver"
-version = "0.10.0"
-authors = ["Steve Klabnik <steve@steveklabnik.com>", "The Rust Project Developers"]
-description = "Semantic version parsing and comparison.\n"
-homepage = "https://docs.rs/crate/semver/"
-documentation = "https://docs.rs/crate/semver/"
-readme = "README.md"
-keywords = ["version", "semantic", "compare"]
-categories = ["development-tools", "parser-implementations"]
-license = "MIT/Apache-2.0"
-repository = "https://github.com/steveklabnik/semver"
-[dependencies.diesel]
-version = "1.1"
-optional = true
-
-[dependencies.semver-parser]
-version = "0.7.0"
-
-[dependencies.serde]
-version = "1.0"
-optional = true
-[dev-dependencies.serde_derive]
-version = "1.0"
-
-[dev-dependencies.serde_json]
-version = "1.0"
-
-[features]
-ci = ["serde", "diesel/sqlite"]
-default = []
diff --git a/vendor/semver-0.10.0/LICENSE-APACHE b/vendor/semver-0.10.0/LICENSE-APACHE
deleted file mode 100644 (file)
index f47c941..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-                              Apache License\r
-                        Version 2.0, January 2004\r
-                     http://www.apache.org/licenses/\r
-\r
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\r
-\r
-1. Definitions.\r
-\r
-   "License" shall mean the terms and conditions for use, reproduction,\r
-   and distribution as defined by Sections 1 through 9 of this document.\r
-\r
-   "Licensor" shall mean the copyright owner or entity authorized by\r
-   the copyright owner that is granting the License.\r
-\r
-   "Legal Entity" shall mean the union of the acting entity and all\r
-   other entities that control, are controlled by, or are under common\r
-   control with that entity. For the purposes of this definition,\r
-   "control" means (i) the power, direct or indirect, to cause the\r
-   direction or management of such entity, whether by contract or\r
-   otherwise, or (ii) ownership of fifty percent (50%) or more of the\r
-   outstanding shares, or (iii) beneficial ownership of such entity.\r
-\r
-   "You" (or "Your") shall mean an individual or Legal Entity\r
-   exercising permissions granted by this License.\r
-\r
-   "Source" form shall mean the preferred form for making modifications,\r
-   including but not limited to software source code, documentation\r
-   source, and configuration files.\r
-\r
-   "Object" form shall mean any form resulting from mechanical\r
-   transformation or translation of a Source form, including but\r
-   not limited to compiled object code, generated documentation,\r
-   and conversions to other media types.\r
-\r
-   "Work" shall mean the work of authorship, whether in Source or\r
-   Object form, made available under the License, as indicated by a\r
-   copyright notice that is included in or attached to the work\r
-   (an example is provided in the Appendix below).\r
-\r
-   "Derivative Works" shall mean any work, whether in Source or Object\r
-   form, that is based on (or derived from) the Work and for which the\r
-   editorial revisions, annotations, elaborations, or other modifications\r
-   represent, as a whole, an original work of authorship. For the purposes\r
-   of this License, Derivative Works shall not include works that remain\r
-   separable from, or merely link (or bind by name) to the interfaces of,\r
-   the Work and Derivative Works thereof.\r
-\r
-   "Contribution" shall mean any work of authorship, including\r
-   the original version of the Work and any modifications or additions\r
-   to that Work or Derivative Works thereof, that is intentionally\r
-   submitted to Licensor for inclusion in the Work by the copyright owner\r
-   or by an individual or Legal Entity authorized to submit on behalf of\r
-   the copyright owner. For the purposes of this definition, "submitted"\r
-   means any form of electronic, verbal, or written communication sent\r
-   to the Licensor or its representatives, including but not limited to\r
-   communication on electronic mailing lists, source code control systems,\r
-   and issue tracking systems that are managed by, or on behalf of, the\r
-   Licensor for the purpose of discussing and improving the Work, but\r
-   excluding communication that is conspicuously marked or otherwise\r
-   designated in writing by the copyright owner as "Not a Contribution."\r
-\r
-   "Contributor" shall mean Licensor and any individual or Legal Entity\r
-   on behalf of whom a Contribution has been received by Licensor and\r
-   subsequently incorporated within the Work.\r
-\r
-2. Grant of Copyright License. Subject to the terms and conditions of\r
-   this License, each Contributor hereby grants to You a perpetual,\r
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
-   copyright license to reproduce, prepare Derivative Works of,\r
-   publicly display, publicly perform, sublicense, and distribute the\r
-   Work and such Derivative Works in Source or Object form.\r
-\r
-3. Grant of Patent License. Subject to the terms and conditions of\r
-   this License, each Contributor hereby grants to You a perpetual,\r
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
-   (except as stated in this section) patent license to make, have made,\r
-   use, offer to sell, sell, import, and otherwise transfer the Work,\r
-   where such license applies only to those patent claims licensable\r
-   by such Contributor that are necessarily infringed by their\r
-   Contribution(s) alone or by combination of their Contribution(s)\r
-   with the Work to which such Contribution(s) was submitted. If You\r
-   institute patent litigation against any entity (including a\r
-   cross-claim or counterclaim in a lawsuit) alleging that the Work\r
-   or a Contribution incorporated within the Work constitutes direct\r
-   or contributory patent infringement, then any patent licenses\r
-   granted to You under this License for that Work shall terminate\r
-   as of the date such litigation is filed.\r
-\r
-4. Redistribution. You may reproduce and distribute copies of the\r
-   Work or Derivative Works thereof in any medium, with or without\r
-   modifications, and in Source or Object form, provided that You\r
-   meet the following conditions:\r
-\r
-   (a) You must give any other recipients of the Work or\r
-       Derivative Works a copy of this License; and\r
-\r
-   (b) You must cause any modified files to carry prominent notices\r
-       stating that You changed the files; and\r
-\r
-   (c) You must retain, in the Source form of any Derivative Works\r
-       that You distribute, all copyright, patent, trademark, and\r
-       attribution notices from the Source form of the Work,\r
-       excluding those notices that do not pertain to any part of\r
-       the Derivative Works; and\r
-\r
-   (d) If the Work includes a "NOTICE" text file as part of its\r
-       distribution, then any Derivative Works that You distribute must\r
-       include a readable copy of the attribution notices contained\r
-       within such NOTICE file, excluding those notices that do not\r
-       pertain to any part of the Derivative Works, in at least one\r
-       of the following places: within a NOTICE text file distributed\r
-       as part of the Derivative Works; within the Source form or\r
-       documentation, if provided along with the Derivative Works; or,\r
-       within a display generated by the Derivative Works, if and\r
-       wherever such third-party notices normally appear. The contents\r
-       of the NOTICE file are for informational purposes only and\r
-       do not modify the License. You may add Your own attribution\r
-       notices within Derivative Works that You distribute, alongside\r
-       or as an addendum to the NOTICE text from the Work, provided\r
-       that such additional attribution notices cannot be construed\r
-       as modifying the License.\r
-\r
-   You may add Your own copyright statement to Your modifications and\r
-   may provide additional or different license terms and conditions\r
-   for use, reproduction, or distribution of Your modifications, or\r
-   for any such Derivative Works as a whole, provided Your use,\r
-   reproduction, and distribution of the Work otherwise complies with\r
-   the conditions stated in this License.\r
-\r
-5. Submission of Contributions. Unless You explicitly state otherwise,\r
-   any Contribution intentionally submitted for inclusion in the Work\r
-   by You to the Licensor shall be under the terms and conditions of\r
-   this License, without any additional terms or conditions.\r
-   Notwithstanding the above, nothing herein shall supersede or modify\r
-   the terms of any separate license agreement you may have executed\r
-   with Licensor regarding such Contributions.\r
-\r
-6. Trademarks. This License does not grant permission to use the trade\r
-   names, trademarks, service marks, or product names of the Licensor,\r
-   except as required for reasonable and customary use in describing the\r
-   origin of the Work and reproducing the content of the NOTICE file.\r
-\r
-7. Disclaimer of Warranty. Unless required by applicable law or\r
-   agreed to in writing, Licensor provides the Work (and each\r
-   Contributor provides its Contributions) on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\r
-   implied, including, without limitation, any warranties or conditions\r
-   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\r
-   PARTICULAR PURPOSE. You are solely responsible for determining the\r
-   appropriateness of using or redistributing the Work and assume any\r
-   risks associated with Your exercise of permissions under this License.\r
-\r
-8. Limitation of Liability. In no event and under no legal theory,\r
-   whether in tort (including negligence), contract, or otherwise,\r
-   unless required by applicable law (such as deliberate and grossly\r
-   negligent acts) or agreed to in writing, shall any Contributor be\r
-   liable to You for damages, including any direct, indirect, special,\r
-   incidental, or consequential damages of any character arising as a\r
-   result of this License or out of the use or inability to use the\r
-   Work (including but not limited to damages for loss of goodwill,\r
-   work stoppage, computer failure or malfunction, or any and all\r
-   other commercial damages or losses), even if such Contributor\r
-   has been advised of the possibility of such damages.\r
-\r
-9. Accepting Warranty or Additional Liability. While redistributing\r
-   the Work or Derivative Works thereof, You may choose to offer,\r
-   and charge a fee for, acceptance of support, warranty, indemnity,\r
-   or other liability obligations and/or rights consistent with this\r
-   License. However, in accepting such obligations, You may act only\r
-   on Your own behalf and on Your sole responsibility, not on behalf\r
-   of any other Contributor, and only if You agree to indemnify,\r
-   defend, and hold each Contributor harmless for any liability\r
-   incurred by, or claims asserted against, such Contributor by reason\r
-   of your accepting any such warranty or additional liability.\r
-\r
-END OF TERMS AND CONDITIONS\r
-\r
-APPENDIX: How to apply the Apache License to your work.\r
-\r
-   To apply the Apache License to your work, attach the following\r
-   boilerplate notice, with the fields enclosed by brackets "[]"\r
-   replaced with your own identifying information. (Don't include\r
-   the brackets!)  The text should be enclosed in the appropriate\r
-   comment syntax for the file format. We also recommend that a\r
-   file or class name and description of purpose be included on the\r
-   same "printed page" as the copyright notice for easier\r
-   identification within third-party archives.\r
-\r
-Copyright [yyyy] [name of copyright owner]\r
-\r
-Licensed under the Apache License, Version 2.0 (the "License");\r
-you may not use this file except in compliance with the License.\r
-You may obtain a copy of the License at\r
-\r
-       http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-Unless required by applicable law or agreed to in writing, software\r
-distributed under the License is distributed on an "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-See the License for the specific language governing permissions and\r
-limitations under the License.\r
diff --git a/vendor/semver-0.10.0/LICENSE-MIT b/vendor/semver-0.10.0/LICENSE-MIT
deleted file mode 100644 (file)
index c0428e2..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2014 The Rust Project Developers\r
-\r
-Permission is hereby granted, free of charge, to any\r
-person obtaining a copy of this software and associated\r
-documentation files (the "Software"), to deal in the\r
-Software without restriction, including without\r
-limitation the rights to use, copy, modify, merge,\r
-publish, distribute, sublicense, and/or sell copies of\r
-the Software, and to permit persons to whom the Software\r
-is furnished to do so, subject to the following\r
-conditions:\r
-\r
-The above copyright notice and this permission notice\r
-shall be included in all copies or substantial portions\r
-of the Software.\r
-\r
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF\r
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\r
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\r
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\r
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\r
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\r
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
-DEALINGS IN THE SOFTWARE.\r
diff --git a/vendor/semver-0.10.0/README.md b/vendor/semver-0.10.0/README.md
deleted file mode 100644 (file)
index dbb2b8f..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-semver\r
-======\r
-\r
-Semantic version parsing and comparison.\r
-\r
-![Build Status](https://github.com/steveklabnik/semver/workflows/CI/badge.svg)\r
-\r
-[Documentation](https://steveklabnik.github.io/semver)\r
-\r
-Semantic versioning (see https://semver.org/) is a set of rules for\r
-assigning version numbers.\r
-\r
-## SemVer and the Rust ecosystem\r
-\r
-Rust itself follows the SemVer specification, as does its standard libraries. The two are\r
-not tied together.\r
-\r
-[Cargo](https://crates.io), Rust's package manager, uses SemVer to determine which versions of\r
-packages you need installed.\r
-\r
-## Installation\r
-\r
-To use `semver`, add this to your `[dependencies]` section:\r
-\r
-```toml\r
-semver = "0.9.0"\r
-```\r
-\r
-And this to your crate root:\r
-\r
-```rust\r
-extern crate semver;\r
-```\r
-\r
-## Versions\r
-\r
-At its simplest, the `semver` crate allows you to construct `Version` objects using the `parse`\r
-method:\r
-\r
-```rust\r
-use semver::Version;\r
-\r
-assert!(Version::parse("1.2.3") == Ok(Version {\r
-   major: 1,\r
-   minor: 2,\r
-   patch: 3,\r
-   pre: vec!(),\r
-   build: vec!(),\r
-}));\r
-```\r
-\r
-If you have multiple `Version`s, you can use the usual comparison operators to compare them:\r
-\r
-```rust\r
-use semver::Version;\r
-\r
-assert!(Version::parse("1.2.3-alpha")  != Version::parse("1.2.3-beta"));\r
-assert!(Version::parse("1.2.3-alpha2") >  Version::parse("1.2.0"));\r
-```\r
-\r
-## Requirements\r
-\r
-The `semver` crate also provides the ability to compare requirements, which are more complex\r
-comparisons.\r
-\r
-For example, creating a requirement that only matches versions greater than or\r
-equal to 1.0.0:\r
-\r
-```rust\r
-use semver::Version;\r
-use semver::VersionReq;\r
-\r
-let r = VersionReq::parse(">= 1.0.0").unwrap();\r
-let v = Version::parse("1.0.0").unwrap();\r
-\r
-assert!(r.to_string() == ">= 1.0.0".to_string());\r
-assert!(r.matches(&v))\r
-```\r
-\r
-It also allows parsing of `~x.y.z` and `^x.y.z` requirements as defined at\r
-https://www.npmjs.com/package/semver\r
-\r
-**Tilde requirements** specify a minimal version with some updates:\r
-\r
-```notrust\r
-~1.2.3 := >=1.2.3 <1.3.0\r
-~1.2   := >=1.2.0 <1.3.0\r
-~1     := >=1.0.0 <2.0.0\r
-```\r
-\r
-**Caret requirements** allow SemVer compatible updates to a specified version,\r
-`0.x` and `0.x+1` are not considered compatible, but `1.x` and `1.x+1` are.\r
-\r
-`0.0.x` is not considered compatible with any other version.\r
-Missing minor and patch versions are desugared to `0` but allow flexibility for that value.\r
-\r
-```notrust\r
-^1.2.3 := >=1.2.3 <2.0.0\r
-^0.2.3 := >=0.2.3 <0.3.0\r
-^0.0.3 := >=0.0.3 <0.0.4\r
-^0.0   := >=0.0.0 <0.1.0\r
-^0     := >=0.0.0 <1.0.0\r
-```\r
diff --git a/vendor/semver-0.10.0/src/diesel_impls.rs b/vendor/semver-0.10.0/src/diesel_impls.rs
deleted file mode 100644 (file)
index 25e145f..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-use diesel::backend::Backend;\r
-use diesel::deserialize::{self, FromSql};\r
-use diesel::serialize::{self, IsNull, Output, ToSql};\r
-use diesel::sql_types::Text;\r
-use std::io::Write;\r
-\r
-use {Version, VersionReq};\r
-\r
-impl<DB> FromSql<Text, DB> for Version\r
-where\r
-    DB: Backend,\r
-    *const str: FromSql<Text, DB>,\r
-{\r
-    fn from_sql(input: Option<&DB::RawValue>) -> deserialize::Result<Self> {\r
-        let str_ptr = <*const str as FromSql<Text, DB>>::from_sql(input)?;\r
-        let s = unsafe { &*str_ptr };\r
-        s.parse().map_err(Into::into)\r
-    }\r
-}\r
-\r
-impl<DB: Backend> ToSql<Text, DB> for Version {\r
-    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {\r
-        write!(out, "{}", self)?;\r
-        Ok(IsNull::No)\r
-    }\r
-}\r
-\r
-impl<DB> FromSql<Text, DB> for VersionReq\r
-where\r
-    DB: Backend,\r
-    *const str: FromSql<Text, DB>,\r
-{\r
-    fn from_sql(input: Option<&DB::RawValue>) -> deserialize::Result<Self> {\r
-        let str_ptr = <*const str as FromSql<Text, DB>>::from_sql(input)?;\r
-        let s = unsafe { &*str_ptr };\r
-        s.parse().map_err(Into::into)\r
-    }\r
-}\r
-\r
-impl<DB: Backend> ToSql<Text, DB> for VersionReq {\r
-    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {\r
-        write!(out, "{}", self)?;\r
-        Ok(IsNull::No)\r
-    }\r
-}\r
diff --git a/vendor/semver-0.10.0/src/lib.rs b/vendor/semver-0.10.0/src/lib.rs
deleted file mode 100644 (file)
index bc32f69..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT\r
-// file at the top-level directory of this distribution and at\r
-// http://rust-lang.org/COPYRIGHT.\r
-//\r
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or\r
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\r
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your\r
-// option. This file may not be copied, modified, or distributed\r
-// except according to those terms.\r
-\r
-//! Semantic version parsing and comparison.\r
-//!\r
-//! Semantic versioning (see http://semver.org/) is a set of rules for\r
-//! assigning version numbers.\r
-//!\r
-//! ## SemVer overview\r
-//!\r
-//! Given a version number MAJOR.MINOR.PATCH, increment the:\r
-//!\r
-//! 1. MAJOR version when you make incompatible API changes,\r
-//! 2. MINOR version when you add functionality in a backwards-compatible\r
-//!    manner, and\r
-//! 3. PATCH version when you make backwards-compatible bug fixes.\r
-//!\r
-//! Additional labels for pre-release and build metadata are available as\r
-//! extensions to the MAJOR.MINOR.PATCH format.\r
-//!\r
-//! Any references to 'the spec' in this documentation refer to [version 2.0 of\r
-//! the SemVer spec](http://semver.org/spec/v2.0.0.html).\r
-//!\r
-//! ## SemVer and the Rust ecosystem\r
-//!\r
-//! Rust itself follows the SemVer specification, as does its standard\r
-//! libraries. The two are not tied together.\r
-//!\r
-//! [Cargo](http://crates.io), Rust's package manager, uses SemVer to determine\r
-//! which versions of packages you need installed.\r
-//!\r
-//! ## Versions\r
-//!\r
-//! [`Version`]: struct.Version.html\r
-//!\r
-//! At its simplest, the `semver` crate allows you to construct [`Version`]\r
-//! objects using the [`parse`] method:\r
-//!\r
-//! [`parse`]: struct.Version.html#method.parse\r
-//!\r
-//! ```{rust}\r
-//! use semver::Version;\r
-//!\r
-//! assert!(Version::parse("1.2.3") == Ok(Version {\r
-//!    major: 1,\r
-//!    minor: 2,\r
-//!    patch: 3,\r
-//!    pre: vec!(),\r
-//!    build: vec!(),\r
-//! }));\r
-//! ```\r
-//!\r
-//! If you have multiple [`Version`]s, you can use the usual comparison operators\r
-//! to compare them:\r
-//!\r
-//! ```{rust}\r
-//! use semver::Version;\r
-//!\r
-//! assert!(Version::parse("1.2.3-alpha") != Version::parse("1.2.3-beta"));\r
-//! assert!(Version::parse("1.2.3-alpha2") >  Version::parse("1.2.0"));\r
-//! ```\r
-//!\r
-//! If you explicitly need to modify a [`Version`], SemVer also allows you to\r
-//! increment the major, minor, and patch numbers in accordance with the spec.\r
-//!\r
-//! Please note that in order to do this, you must use a mutable Version:\r
-//!\r
-//! ```{rust}\r
-//! use semver::Version;\r
-//!\r
-//! # fn try_increment_patch() -> Result<(), Box<::std::error::Error>> {\r
-//! let mut bugfix_release = Version::parse("1.0.0")?;\r
-//! bugfix_release.increment_patch();\r
-//!\r
-//! assert_eq!(Ok(bugfix_release), Version::parse("1.0.1"));\r
-//! #    Ok(())\r
-//! # }\r
-//! # fn main() {\r
-//! #    try_increment_patch().unwrap();\r
-//! # }\r
-//! ```\r
-//!\r
-//! When incrementing the minor version number, the patch number resets to zero\r
-//! (in accordance with section 7 of the spec)\r
-//!\r
-//! ```{rust}\r
-//! use semver::Version;\r
-//!\r
-//! # fn try_increment_minor() -> Result<(), Box<::std::error::Error>> {\r
-//! let mut feature_release = Version::parse("1.4.6")?;\r
-//! feature_release.increment_minor();\r
-//!\r
-//! assert_eq!(Ok(feature_release), Version::parse("1.5.0"));\r
-//! #   Ok(())\r
-//! # }\r
-//! # fn main() {\r
-//! #    try_increment_minor().unwrap();\r
-//! # }\r
-//! ```\r
-//!\r
-//! Similarly, when incrementing the major version number, the patch and minor\r
-//! numbers reset to zero (in accordance with section 8 of the spec)\r
-//!\r
-//! ```{rust}\r
-//! use semver::Version;\r
-//!\r
-//! # fn try_increment_major() -> Result<(), Box<::std::error::Error>> {\r
-//! let mut chrome_release = Version::parse("41.5.5377")?;\r
-//! chrome_release.increment_major();\r
-//!\r
-//! assert_eq!(Ok(chrome_release), Version::parse("42.0.0"));\r
-//! #    Ok(())\r
-//! # }\r
-//! # fn main() {\r
-//! #    try_increment_major().unwrap();\r
-//! # }\r
-//! ```\r
-//!\r
-//! ## Requirements\r
-//!\r
-//! The `semver` crate also provides the ability to compare requirements, which\r
-//! are more complex comparisons.\r
-//!\r
-//! For example, creating a requirement that only matches versions greater than\r
-//! or equal to 1.0.0:\r
-//!\r
-//! ```{rust}\r
-//! # #![allow(unstable)]\r
-//! use semver::Version;\r
-//! use semver::VersionReq;\r
-//!\r
-//! # fn try_compare() -> Result<(), Box<::std::error::Error>> {\r
-//! let r = VersionReq::parse(">= 1.0.0")?;\r
-//! let v = Version::parse("1.0.0")?;\r
-//!\r
-//! assert!(r.to_string() == ">=1.0.0".to_string());\r
-//! assert!(r.matches(&v));\r
-//! #    Ok(())\r
-//! # }\r
-//! # fn main() {\r
-//! #    try_compare().unwrap();\r
-//! # }\r
-//! ```\r
-//!\r
-//! It also allows parsing of `~x.y.z` and `^x.y.z` requirements as defined at\r
-//! https://www.npmjs.com/package/semver\r
-//!\r
-//! **Tilde requirements** specify a minimal version with some updates:\r
-//!\r
-//! ```notrust\r
-//! ~1.2.3 := >=1.2.3 <1.3.0\r
-//! ~1.2   := >=1.2.0 <1.3.0\r
-//! ~1     := >=1.0.0 <2.0.0\r
-//! ```\r
-//!\r
-//! **Caret requirements** allow SemVer compatible updates to a specified\r
-//! verion, `0.x` and `0.x+1` are not considered compatible, but `1.x` and\r
-//! `1.x+1` are.\r
-//!\r
-//! `0.0.x` is not considered compatible with any other version.\r
-//! Missing minor and patch versions are desugared to `0` but allow flexibility\r
-//! for that value.\r
-//!\r
-//! ```notrust\r
-//! ^1.2.3 := >=1.2.3 <2.0.0\r
-//! ^0.2.3 := >=0.2.3 <0.3.0\r
-//! ^0.0.3 := >=0.0.3 <0.0.4\r
-//! ^0.0   := >=0.0.0 <0.1.0\r
-//! ^0     := >=0.0.0 <1.0.0\r
-//! ```\r
-//!\r
-//! **Wildcard requirements** allows parsing of version requirements of the\r
-//! formats `*`, `x.*` and `x.y.*`.\r
-//!\r
-//! ```notrust\r
-//! *     := >=0.0.0\r
-//! 1.*   := >=1.0.0 <2.0.0\r
-//! 1.2.* := >=1.2.0 <1.3.0\r
-//! ```\r
-\r
-#![doc(\r
-    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",\r
-    html_favicon_url = "https://www.rust-lang.org/favicon.ico",\r
-    html_root_url = "https://docs.rs/semver"\r
-)]\r
-#![deny(missing_docs)]\r
-#![cfg_attr(test, deny(warnings))]\r
-\r
-extern crate semver_parser;\r
-\r
-// Serialization and deserialization support for version numbers\r
-#[cfg(feature = "serde")]\r
-extern crate serde;\r
-\r
-// Database support for version numbers\r
-#[cfg(feature = "diesel")]\r
-#[macro_use]\r
-extern crate diesel;\r
-\r
-// We take the common approach of keeping our own module system private, and\r
-// just re-exporting the interface that we want.\r
-\r
-pub use version::Identifier::{AlphaNumeric, Numeric};\r
-pub use version::{Identifier, SemVerError, Version};\r
-pub use version_req::{ReqParseError, VersionReq};\r
-\r
-// SemVer-compliant versions.\r
-mod version;\r
-\r
-// advanced version comparisons\r
-mod version_req;\r
-\r
-#[cfg(feature = "diesel")]\r
-// Diesel support\r
-mod diesel_impls;\r
diff --git a/vendor/semver-0.10.0/src/version.rs b/vendor/semver-0.10.0/src/version.rs
deleted file mode 100644 (file)
index e87e32f..0000000
+++ /dev/null
@@ -1,871 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT\r
-// file at the top-level directory of this distribution and at\r
-// http://rust-lang.org/COPYRIGHT.\r
-//\r
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or\r
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\r
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your\r
-// option. This file may not be copied, modified, or distributed\r
-// except according to those terms.\r
-\r
-//! The `version` module gives you tools to create and compare SemVer-compliant\r
-//! versions.\r
-\r
-use std::cmp::{self, Ordering};\r
-use std::error::Error;\r
-use std::fmt;\r
-use std::hash;\r
-\r
-use std::result;\r
-use std::str;\r
-\r
-use semver_parser;\r
-\r
-#[cfg(feature = "serde")]\r
-use serde::de::{self, Deserialize, Deserializer, Visitor};\r
-#[cfg(feature = "serde")]\r
-use serde::ser::{Serialize, Serializer};\r
-\r
-/// An identifier in the pre-release or build metadata.\r
-///\r
-/// See sections 9 and 10 of the spec for more about pre-release identifers and\r
-/// build metadata.\r
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]\r
-pub enum Identifier {\r
-    /// An identifier that's solely numbers.\r
-    Numeric(u64),\r
-    /// An identifier with letters and numbers.\r
-    AlphaNumeric(String),\r
-}\r
-\r
-impl From<semver_parser::version::Identifier> for Identifier {\r
-    fn from(other: semver_parser::version::Identifier) -> Identifier {\r
-        match other {\r
-            semver_parser::version::Identifier::Numeric(n) => Identifier::Numeric(n),\r
-            semver_parser::version::Identifier::AlphaNumeric(s) => Identifier::AlphaNumeric(s),\r
-        }\r
-    }\r
-}\r
-\r
-impl fmt::Display for Identifier {\r
-    #[inline]\r
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\r
-        match *self {\r
-            Identifier::Numeric(ref n) => fmt::Display::fmt(n, f),\r
-            Identifier::AlphaNumeric(ref s) => fmt::Display::fmt(s, f),\r
-        }\r
-    }\r
-}\r
-\r
-#[cfg(feature = "serde")]\r
-impl Serialize for Identifier {\r
-    fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>\r
-    where\r
-        S: Serializer,\r
-    {\r
-        // Serialize Identifier as a number or string.\r
-        match *self {\r
-            Identifier::Numeric(n) => serializer.serialize_u64(n),\r
-            Identifier::AlphaNumeric(ref s) => serializer.serialize_str(s),\r
-        }\r
-    }\r
-}\r
-\r
-#[cfg(feature = "serde")]\r
-impl<'de> Deserialize<'de> for Identifier {\r
-    fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>\r
-    where\r
-        D: Deserializer<'de>,\r
-    {\r
-        struct IdentifierVisitor;\r
-\r
-        // Deserialize Identifier from a number or string.\r
-        impl<'de> Visitor<'de> for IdentifierVisitor {\r
-            type Value = Identifier;\r
-\r
-            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {\r
-                formatter.write_str("a SemVer pre-release or build identifier")\r
-            }\r
-\r
-            fn visit_u64<E>(self, numeric: u64) -> result::Result<Self::Value, E>\r
-            where\r
-                E: de::Error,\r
-            {\r
-                Ok(Identifier::Numeric(numeric))\r
-            }\r
-\r
-            fn visit_str<E>(self, alphanumeric: &str) -> result::Result<Self::Value, E>\r
-            where\r
-                E: de::Error,\r
-            {\r
-                Ok(Identifier::AlphaNumeric(alphanumeric.to_owned()))\r
-            }\r
-        }\r
-\r
-        deserializer.deserialize_any(IdentifierVisitor)\r
-    }\r
-}\r
-\r
-/// Represents a version number conforming to the semantic versioning scheme.\r
-#[derive(Clone, Eq, Debug)]\r
-#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]\r
-#[cfg_attr(feature = "diesel", sql_type = "diesel::sql_types::Text")]\r
-pub struct Version {\r
-    /// The major version, to be incremented on incompatible changes.\r
-    pub major: u64,\r
-    /// The minor version, to be incremented when functionality is added in a\r
-    /// backwards-compatible manner.\r
-    pub minor: u64,\r
-    /// The patch version, to be incremented when backwards-compatible bug\r
-    /// fixes are made.\r
-    pub patch: u64,\r
-    /// The pre-release version identifier, if one exists.\r
-    pub pre: Vec<Identifier>,\r
-    /// The build metadata, ignored when determining version precedence.\r
-    pub build: Vec<Identifier>,\r
-}\r
-\r
-impl From<semver_parser::version::Version> for Version {\r
-    fn from(other: semver_parser::version::Version) -> Version {\r
-        Version {\r
-            major: other.major,\r
-            minor: other.minor,\r
-            patch: other.patch,\r
-            pre: other.pre.into_iter().map(From::from).collect(),\r
-            build: other.build.into_iter().map(From::from).collect(),\r
-        }\r
-    }\r
-}\r
-\r
-#[cfg(feature = "serde")]\r
-impl Serialize for Version {\r
-    fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>\r
-    where\r
-        S: Serializer,\r
-    {\r
-        // Serialize Version as a string.\r
-        serializer.collect_str(self)\r
-    }\r
-}\r
-\r
-#[cfg(feature = "serde")]\r
-impl<'de> Deserialize<'de> for Version {\r
-    fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>\r
-    where\r
-        D: Deserializer<'de>,\r
-    {\r
-        struct VersionVisitor;\r
-\r
-        // Deserialize Version from a string.\r
-        impl<'de> Visitor<'de> for VersionVisitor {\r
-            type Value = Version;\r
-\r
-            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {\r
-                formatter.write_str("a SemVer version as a string")\r
-            }\r
-\r
-            fn visit_str<E>(self, v: &str) -> result::Result<Self::Value, E>\r
-            where\r
-                E: de::Error,\r
-            {\r
-                Version::parse(v).map_err(de::Error::custom)\r
-            }\r
-        }\r
-\r
-        deserializer.deserialize_str(VersionVisitor)\r
-    }\r
-}\r
-\r
-/// An error type for this crate\r
-///\r
-/// Currently, just a generic error. Will make this nicer later.\r
-#[derive(Clone, PartialEq, Debug, PartialOrd)]\r
-pub enum SemVerError {\r
-    /// An error ocurred while parsing.\r
-    ParseError(String),\r
-}\r
-\r
-impl fmt::Display for SemVerError {\r
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\r
-        match self {\r
-            SemVerError::ParseError(ref m) => write!(f, "{}", m),\r
-        }\r
-    }\r
-}\r
-\r
-impl Error for SemVerError {}\r
-\r
-/// A Result type for errors\r
-pub type Result<T> = result::Result<T, SemVerError>;\r
-\r
-impl Version {\r
-    /// Contructs the simple case without pre or build.\r
-    pub fn new(major: u64, minor: u64, patch: u64) -> Version {\r
-        Version {\r
-            major,\r
-            minor,\r
-            patch,\r
-            pre: Vec::new(),\r
-            build: Vec::new(),\r
-        }\r
-    }\r
-\r
-    /// Parse a string into a semver object.\r
-    ///\r
-    /// # Errors\r
-    ///\r
-    /// Returns an error variant if the input could not be parsed as a semver object.\r
-    ///\r
-    /// In general, this means that the provided string does not conform to the\r
-    /// [semver spec][semver].\r
-    ///\r
-    /// An error for overflow is returned if any numeric component is larger than what can be\r
-    /// stored in `u64`.\r
-    ///\r
-    /// The following are examples for other common error causes:\r
-    ///\r
-    /// * `1.0` - too few numeric components are used. Exactly 3 are expected.\r
-    /// * `1.0.01` - a numeric component has a leading zero.\r
-    /// * `1.0.foo` - uses a non-numeric components where one is expected.\r
-    /// * `1.0.0foo` - metadata is not separated using a legal character like, `+` or `-`.\r
-    /// * `1.0.0+foo_123` - contains metadata with an illegal character (`_`).\r
-    ///   Legal characters for metadata include `a-z`, `A-Z`, `0-9`, `-`, and `.` (dot).\r
-    ///\r
-    /// [semver]: https://semver.org\r
-    pub fn parse(version: &str) -> Result<Version> {\r
-        let res = semver_parser::version::parse(version);\r
-\r
-        match res {\r
-            // Convert plain String error into proper ParseError\r
-            Err(e) => Err(SemVerError::ParseError(e)),\r
-            Ok(v) => Ok(From::from(v)),\r
-        }\r
-    }\r
-\r
-    /// Clears the build metadata\r
-    fn clear_metadata(&mut self) {\r
-        self.build = Vec::new();\r
-        self.pre = Vec::new();\r
-    }\r
-\r
-    /// Increments the patch number for this Version (Must be mutable)\r
-    pub fn increment_patch(&mut self) {\r
-        self.patch += 1;\r
-        self.clear_metadata();\r
-    }\r
-\r
-    /// Increments the minor version number for this Version (Must be mutable)\r
-    ///\r
-    /// As instructed by section 7 of the spec, the patch number is reset to 0.\r
-    pub fn increment_minor(&mut self) {\r
-        self.minor += 1;\r
-        self.patch = 0;\r
-        self.clear_metadata();\r
-    }\r
-\r
-    /// Increments the major version number for this Version (Must be mutable)\r
-    ///\r
-    /// As instructed by section 8 of the spec, the minor and patch numbers are\r
-    /// reset to 0\r
-    pub fn increment_major(&mut self) {\r
-        self.major += 1;\r
-        self.minor = 0;\r
-        self.patch = 0;\r
-        self.clear_metadata();\r
-    }\r
-\r
-    /// Checks to see if the current Version is in pre-release status\r
-    pub fn is_prerelease(&self) -> bool {\r
-        !self.pre.is_empty()\r
-    }\r
-}\r
-\r
-impl str::FromStr for Version {\r
-    type Err = SemVerError;\r
-\r
-    fn from_str(s: &str) -> Result<Version> {\r
-        Version::parse(s)\r
-    }\r
-}\r
-\r
-impl fmt::Display for Version {\r
-    #[inline]\r
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\r
-        let mut result = format!("{}.{}.{}", self.major, self.minor, self.patch);\r
-\r
-        if !self.pre.is_empty() {\r
-            result.push_str("-");\r
-            for (i, x) in self.pre.iter().enumerate() {\r
-                if i != 0 {\r
-                    result.push_str(".");\r
-                }\r
-                result.push_str(format!("{}", x).as_ref());\r
-            }\r
-        }\r
-        if !self.build.is_empty() {\r
-            result.push_str("+");\r
-            for (i, x) in self.build.iter().enumerate() {\r
-                if i != 0 {\r
-                    result.push_str(".");\r
-                }\r
-                result.push_str(format!("{}", x).as_ref());\r
-            }\r
-        }\r
-\r
-        f.pad(result.as_ref())?;\r
-        Ok(())\r
-    }\r
-}\r
-\r
-impl cmp::PartialEq for Version {\r
-    #[inline]\r
-    fn eq(&self, other: &Version) -> bool {\r
-        // We should ignore build metadata here, otherwise versions v1 and v2\r
-        // can exist such that !(v1 < v2) && !(v1 > v2) && v1 != v2, which\r
-        // violate strict total ordering rules.\r
-        self.major == other.major\r
-            && self.minor == other.minor\r
-            && self.patch == other.patch\r
-            && self.pre == other.pre\r
-    }\r
-}\r
-\r
-impl cmp::PartialOrd for Version {\r
-    fn partial_cmp(&self, other: &Version) -> Option<Ordering> {\r
-        Some(self.cmp(other))\r
-    }\r
-}\r
-\r
-impl cmp::Ord for Version {\r
-    fn cmp(&self, other: &Version) -> Ordering {\r
-        match self.major.cmp(&other.major) {\r
-            Ordering::Equal => {}\r
-            r => return r,\r
-        }\r
-\r
-        match self.minor.cmp(&other.minor) {\r
-            Ordering::Equal => {}\r
-            r => return r,\r
-        }\r
-\r
-        match self.patch.cmp(&other.patch) {\r
-            Ordering::Equal => {}\r
-            r => return r,\r
-        }\r
-\r
-        // NB: semver spec says 0.0.0-pre < 0.0.0\r
-        // but the version of ord defined for vec\r
-        // says that [] < [pre] so we alter it here\r
-        match (self.pre.len(), other.pre.len()) {\r
-            (0, 0) => Ordering::Equal,\r
-            (0, _) => Ordering::Greater,\r
-            (_, 0) => Ordering::Less,\r
-            (_, _) => self.pre.cmp(&other.pre),\r
-        }\r
-    }\r
-}\r
-\r
-impl hash::Hash for Version {\r
-    fn hash<H: hash::Hasher>(&self, into: &mut H) {\r
-        self.major.hash(into);\r
-        self.minor.hash(into);\r
-        self.patch.hash(into);\r
-        self.pre.hash(into);\r
-    }\r
-}\r
-\r
-impl From<(u64, u64, u64)> for Version {\r
-    fn from(tuple: (u64, u64, u64)) -> Version {\r
-        let (major, minor, patch) = tuple;\r
-        Version::new(major, minor, patch)\r
-    }\r
-}\r
-\r
-#[cfg(test)]\r
-mod tests {\r
-    use super::Identifier;\r
-    use super::SemVerError;\r
-    use super::Version;\r
-    use std::result;\r
-\r
-    #[test]\r
-    fn test_parse() {\r
-        fn parse_error(e: &str) -> result::Result<Version, SemVerError> {\r
-            return Err(SemVerError::ParseError(e.to_string()));\r
-        }\r
-\r
-        assert_eq!(\r
-            Version::parse(""),\r
-            parse_error("Error parsing major identifier")\r
-        );\r
-        assert_eq!(\r
-            Version::parse("  "),\r
-            parse_error("Error parsing major identifier")\r
-        );\r
-        assert_eq!(Version::parse("1"), parse_error("Expected dot"));\r
-        assert_eq!(Version::parse("1.2"), parse_error("Expected dot"));\r
-        assert_eq!(\r
-            Version::parse("1.2.3-"),\r
-            parse_error("Error parsing prerelease")\r
-        );\r
-        assert_eq!(\r
-            Version::parse("a.b.c"),\r
-            parse_error("Error parsing major identifier")\r
-        );\r
-        assert_eq!(\r
-            Version::parse("1.2.3 abc"),\r
-            parse_error("Extra junk after valid version:  abc")\r
-        );\r
-\r
-        assert_eq!(\r
-            Version::parse("1.2.3"),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: Vec::new(),\r
-                build: Vec::new(),\r
-            })\r
-        );\r
-\r
-        assert_eq!(Version::parse("1.2.3"), Ok(Version::new(1, 2, 3)));\r
-\r
-        assert_eq!(\r
-            Version::parse("  1.2.3  "),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: Vec::new(),\r
-                build: Vec::new(),\r
-            })\r
-        );\r
-        assert_eq!(\r
-            Version::parse("1.2.3-alpha1"),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],\r
-                build: Vec::new(),\r
-            })\r
-        );\r
-        assert_eq!(\r
-            Version::parse("  1.2.3-alpha1  "),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],\r
-                build: Vec::new(),\r
-            })\r
-        );\r
-        assert_eq!(\r
-            Version::parse("1.2.3+build5"),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: Vec::new(),\r
-                build: vec![Identifier::AlphaNumeric(String::from("build5"))],\r
-            })\r
-        );\r
-        assert_eq!(\r
-            Version::parse("  1.2.3+build5  "),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: Vec::new(),\r
-                build: vec![Identifier::AlphaNumeric(String::from("build5"))],\r
-            })\r
-        );\r
-        assert_eq!(\r
-            Version::parse("1.2.3-alpha1+build5"),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],\r
-                build: vec![Identifier::AlphaNumeric(String::from("build5"))],\r
-            })\r
-        );\r
-        assert_eq!(\r
-            Version::parse("  1.2.3-alpha1+build5  "),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],\r
-                build: vec![Identifier::AlphaNumeric(String::from("build5"))],\r
-            })\r
-        );\r
-        assert_eq!(\r
-            Version::parse("1.2.3-1.alpha1.9+build5.7.3aedf  "),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: vec![\r
-                    Identifier::Numeric(1),\r
-                    Identifier::AlphaNumeric(String::from("alpha1")),\r
-                    Identifier::Numeric(9),\r
-                ],\r
-                build: vec![\r
-                    Identifier::AlphaNumeric(String::from("build5")),\r
-                    Identifier::Numeric(7),\r
-                    Identifier::AlphaNumeric(String::from("3aedf")),\r
-                ],\r
-            })\r
-        );\r
-        assert_eq!(\r
-            Version::parse("0.4.0-beta.1+0851523"),\r
-            Ok(Version {\r
-                major: 0,\r
-                minor: 4,\r
-                patch: 0,\r
-                pre: vec![\r
-                    Identifier::AlphaNumeric(String::from("beta")),\r
-                    Identifier::Numeric(1),\r
-                ],\r
-                build: vec![Identifier::AlphaNumeric(String::from("0851523"))],\r
-            })\r
-        );\r
-    }\r
-\r
-    #[test]\r
-    fn test_increment_patch() {\r
-        let mut buggy_release = Version::parse("0.1.0").unwrap();\r
-        buggy_release.increment_patch();\r
-        assert_eq!(buggy_release, Version::parse("0.1.1").unwrap());\r
-    }\r
-\r
-    #[test]\r
-    fn test_increment_minor() {\r
-        let mut feature_release = Version::parse("1.4.6").unwrap();\r
-        feature_release.increment_minor();\r
-        assert_eq!(feature_release, Version::parse("1.5.0").unwrap());\r
-    }\r
-\r
-    #[test]\r
-    fn test_increment_major() {\r
-        let mut chrome_release = Version::parse("46.1.246773").unwrap();\r
-        chrome_release.increment_major();\r
-        assert_eq!(chrome_release, Version::parse("47.0.0").unwrap());\r
-    }\r
-\r
-    #[test]\r
-    fn test_increment_keep_prerelease() {\r
-        let mut release = Version::parse("1.0.0-alpha").unwrap();\r
-        release.increment_patch();\r
-\r
-        assert_eq!(release, Version::parse("1.0.1").unwrap());\r
-\r
-        release.increment_minor();\r
-\r
-        assert_eq!(release, Version::parse("1.1.0").unwrap());\r
-\r
-        release.increment_major();\r
-\r
-        assert_eq!(release, Version::parse("2.0.0").unwrap());\r
-    }\r
-\r
-    #[test]\r
-    fn test_increment_clear_metadata() {\r
-        let mut release = Version::parse("1.0.0+4442").unwrap();\r
-        release.increment_patch();\r
-\r
-        assert_eq!(release, Version::parse("1.0.1").unwrap());\r
-        release = Version::parse("1.0.1+hello").unwrap();\r
-\r
-        release.increment_minor();\r
-\r
-        assert_eq!(release, Version::parse("1.1.0").unwrap());\r
-        release = Version::parse("1.1.3747+hello").unwrap();\r
-\r
-        release.increment_major();\r
-\r
-        assert_eq!(release, Version::parse("2.0.0").unwrap());\r
-    }\r
-\r
-    #[test]\r
-    fn test_eq() {\r
-        assert_eq!(Version::parse("1.2.3"), Version::parse("1.2.3"));\r
-        assert_eq!(\r
-            Version::parse("1.2.3-alpha1"),\r
-            Version::parse("1.2.3-alpha1")\r
-        );\r
-        assert_eq!(\r
-            Version::parse("1.2.3+build.42"),\r
-            Version::parse("1.2.3+build.42")\r
-        );\r
-        assert_eq!(\r
-            Version::parse("1.2.3-alpha1+42"),\r
-            Version::parse("1.2.3-alpha1+42")\r
-        );\r
-        assert_eq!(Version::parse("1.2.3+23"), Version::parse("1.2.3+42"));\r
-    }\r
-\r
-    #[test]\r
-    fn test_ne() {\r
-        assert!(Version::parse("0.0.0") != Version::parse("0.0.1"));\r
-        assert!(Version::parse("0.0.0") != Version::parse("0.1.0"));\r
-        assert!(Version::parse("0.0.0") != Version::parse("1.0.0"));\r
-        assert!(Version::parse("1.2.3-alpha") != Version::parse("1.2.3-beta"));\r
-    }\r
-\r
-    #[test]\r
-    fn test_show() {\r
-        assert_eq!(\r
-            format!("{}", Version::parse("1.2.3").unwrap()),\r
-            "1.2.3".to_string()\r
-        );\r
-        assert_eq!(\r
-            format!("{}", Version::parse("1.2.3-alpha1").unwrap()),\r
-            "1.2.3-alpha1".to_string()\r
-        );\r
-        assert_eq!(\r
-            format!("{}", Version::parse("1.2.3+build.42").unwrap()),\r
-            "1.2.3+build.42".to_string()\r
-        );\r
-        assert_eq!(\r
-            format!("{}", Version::parse("1.2.3-alpha1+42").unwrap()),\r
-            "1.2.3-alpha1+42".to_string()\r
-        );\r
-    }\r
-\r
-    #[test]\r
-    fn test_display() {\r
-        let version = Version::parse("1.2.3-rc1").unwrap();\r
-        assert_eq!(format!("{:20}", version), "1.2.3-rc1           ");\r
-        assert_eq!(format!("{:*^20}", version), "*****1.2.3-rc1******");\r
-        assert_eq!(format!("{:.4}", version), "1.2.");\r
-    }\r
-\r
-    #[test]\r
-    fn test_to_string() {\r
-        assert_eq!(\r
-            Version::parse("1.2.3").unwrap().to_string(),\r
-            "1.2.3".to_string()\r
-        );\r
-        assert_eq!(\r
-            Version::parse("1.2.3-alpha1").unwrap().to_string(),\r
-            "1.2.3-alpha1".to_string()\r
-        );\r
-        assert_eq!(\r
-            Version::parse("1.2.3+build.42").unwrap().to_string(),\r
-            "1.2.3+build.42".to_string()\r
-        );\r
-        assert_eq!(\r
-            Version::parse("1.2.3-alpha1+42").unwrap().to_string(),\r
-            "1.2.3-alpha1+42".to_string()\r
-        );\r
-    }\r
-\r
-    #[test]\r
-    fn test_lt() {\r
-        assert!(Version::parse("0.0.0") < Version::parse("1.2.3-alpha2"));\r
-        assert!(Version::parse("1.0.0") < Version::parse("1.2.3-alpha2"));\r
-        assert!(Version::parse("1.2.0") < Version::parse("1.2.3-alpha2"));\r
-        assert!(Version::parse("1.2.3-alpha1") < Version::parse("1.2.3"));\r
-        assert!(Version::parse("1.2.3-alpha1") < Version::parse("1.2.3-alpha2"));\r
-        assert!(!(Version::parse("1.2.3-alpha2") < Version::parse("1.2.3-alpha2")));\r
-        assert!(!(Version::parse("1.2.3+23") < Version::parse("1.2.3+42")));\r
-    }\r
-\r
-    #[test]\r
-    fn test_le() {\r
-        assert!(Version::parse("0.0.0") <= Version::parse("1.2.3-alpha2"));\r
-        assert!(Version::parse("1.0.0") <= Version::parse("1.2.3-alpha2"));\r
-        assert!(Version::parse("1.2.0") <= Version::parse("1.2.3-alpha2"));\r
-        assert!(Version::parse("1.2.3-alpha1") <= Version::parse("1.2.3-alpha2"));\r
-        assert!(Version::parse("1.2.3-alpha2") <= Version::parse("1.2.3-alpha2"));\r
-        assert!(Version::parse("1.2.3+23") <= Version::parse("1.2.3+42"));\r
-    }\r
-\r
-    #[test]\r
-    fn test_gt() {\r
-        assert!(Version::parse("1.2.3-alpha2") > Version::parse("0.0.0"));\r
-        assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.0.0"));\r
-        assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.0"));\r
-        assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.3-alpha1"));\r
-        assert!(Version::parse("1.2.3") > Version::parse("1.2.3-alpha2"));\r
-        assert!(!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.3-alpha2")));\r
-        assert!(!(Version::parse("1.2.3+23") > Version::parse("1.2.3+42")));\r
-    }\r
-\r
-    #[test]\r
-    fn test_ge() {\r
-        assert!(Version::parse("1.2.3-alpha2") >= Version::parse("0.0.0"));\r
-        assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.0.0"));\r
-        assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.0"));\r
-        assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.3-alpha1"));\r
-        assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.3-alpha2"));\r
-        assert!(Version::parse("1.2.3+23") >= Version::parse("1.2.3+42"));\r
-    }\r
-\r
-    #[test]\r
-    fn test_prerelease_check() {\r
-        assert!(Version::parse("1.0.0").unwrap().is_prerelease() == false);\r
-        assert!(Version::parse("0.0.1").unwrap().is_prerelease() == false);\r
-        assert!(Version::parse("4.1.4-alpha").unwrap().is_prerelease());\r
-        assert!(Version::parse("1.0.0-beta294296").unwrap().is_prerelease());\r
-    }\r
-\r
-    #[test]\r
-    fn test_spec_order() {\r
-        let vs = [\r
-            "1.0.0-alpha",\r
-            "1.0.0-alpha.1",\r
-            "1.0.0-alpha.beta",\r
-            "1.0.0-beta",\r
-            "1.0.0-beta.2",\r
-            "1.0.0-beta.11",\r
-            "1.0.0-rc.1",\r
-            "1.0.0",\r
-        ];\r
-        let mut i = 1;\r
-        while i < vs.len() {\r
-            let a = Version::parse(vs[i - 1]);\r
-            let b = Version::parse(vs[i]);\r
-            assert!(a < b, "nope {:?} < {:?}", a, b);\r
-            i += 1;\r
-        }\r
-    }\r
-\r
-    #[test]\r
-    fn test_from_str() {\r
-        assert_eq!(\r
-            "1.2.3".parse(),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: Vec::new(),\r
-                build: Vec::new(),\r
-            })\r
-        );\r
-        assert_eq!(\r
-            "  1.2.3  ".parse(),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: Vec::new(),\r
-                build: Vec::new(),\r
-            })\r
-        );\r
-        assert_eq!(\r
-            "1.2.3-alpha1".parse(),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],\r
-                build: Vec::new(),\r
-            })\r
-        );\r
-        assert_eq!(\r
-            "  1.2.3-alpha1  ".parse(),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],\r
-                build: Vec::new(),\r
-            })\r
-        );\r
-        assert_eq!(\r
-            "1.2.3+build5".parse(),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: Vec::new(),\r
-                build: vec![Identifier::AlphaNumeric(String::from("build5"))],\r
-            })\r
-        );\r
-        assert_eq!(\r
-            "  1.2.3+build5  ".parse(),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: Vec::new(),\r
-                build: vec![Identifier::AlphaNumeric(String::from("build5"))],\r
-            })\r
-        );\r
-        assert_eq!(\r
-            "1.2.3-alpha1+build5".parse(),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],\r
-                build: vec![Identifier::AlphaNumeric(String::from("build5"))],\r
-            })\r
-        );\r
-        assert_eq!(\r
-            "  1.2.3-alpha1+build5  ".parse(),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],\r
-                build: vec![Identifier::AlphaNumeric(String::from("build5"))],\r
-            })\r
-        );\r
-        assert_eq!(\r
-            "1.2.3-1.alpha1.9+build5.7.3aedf  ".parse(),\r
-            Ok(Version {\r
-                major: 1,\r
-                minor: 2,\r
-                patch: 3,\r
-                pre: vec![\r
-                    Identifier::Numeric(1),\r
-                    Identifier::AlphaNumeric(String::from("alpha1")),\r
-                    Identifier::Numeric(9),\r
-                ],\r
-                build: vec![\r
-                    Identifier::AlphaNumeric(String::from("build5")),\r
-                    Identifier::Numeric(7),\r
-                    Identifier::AlphaNumeric(String::from("3aedf")),\r
-                ],\r
-            })\r
-        );\r
-        assert_eq!(\r
-            "0.4.0-beta.1+0851523".parse(),\r
-            Ok(Version {\r
-                major: 0,\r
-                minor: 4,\r
-                patch: 0,\r
-                pre: vec![\r
-                    Identifier::AlphaNumeric(String::from("beta")),\r
-                    Identifier::Numeric(1),\r
-                ],\r
-                build: vec![Identifier::AlphaNumeric(String::from("0851523"))],\r
-            })\r
-        );\r
-    }\r
-\r
-    #[test]\r
-    fn test_from_str_errors() {\r
-        fn parse_error(e: &str) -> result::Result<Version, SemVerError> {\r
-            return Err(SemVerError::ParseError(e.to_string()));\r
-        }\r
-\r
-        assert_eq!("".parse(), parse_error("Error parsing major identifier"));\r
-        assert_eq!("  ".parse(), parse_error("Error parsing major identifier"));\r
-        assert_eq!("1".parse(), parse_error("Expected dot"));\r
-        assert_eq!("1.2".parse(), parse_error("Expected dot"));\r
-        assert_eq!("1.2.3-".parse(), parse_error("Error parsing prerelease"));\r
-        assert_eq!(\r
-            "a.b.c".parse(),\r
-            parse_error("Error parsing major identifier")\r
-        );\r
-        assert_eq!(\r
-            "1.2.3 abc".parse(),\r
-            parse_error("Extra junk after valid version:  abc")\r
-        );\r
-    }\r
-}\r
diff --git a/vendor/semver-0.10.0/src/version_req.rs b/vendor/semver-0.10.0/src/version_req.rs
deleted file mode 100644 (file)
index d915b21..0000000
+++ /dev/null
@@ -1,1031 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT\r
-// file at the top-level directory of this distribution and at\r
-// http://rust-lang.org/COPYRIGHT.\r
-//\r
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or\r
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\r
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your\r
-// option. This file may not be copied, modified, or distributed\r
-// except according to those terms.\r
-\r
-use std::error::Error;\r
-use std::fmt;\r
-use std::str;\r
-\r
-use semver_parser;\r
-use version::Identifier;\r
-use Version;\r
-\r
-#[cfg(feature = "serde")]\r
-use serde::de::{self, Deserialize, Deserializer, Visitor};\r
-#[cfg(feature = "serde")]\r
-use serde::ser::{Serialize, Serializer};\r
-\r
-use self::Op::{Compatible, Ex, Gt, GtEq, Lt, LtEq, Tilde, Wildcard};\r
-use self::ReqParseError::*;\r
-use self::WildcardVersion::{Major, Minor, Patch};\r
-\r
-/// A `VersionReq` is a struct containing a list of predicates that can apply to ranges of version\r
-/// numbers. Matching operations can then be done with the `VersionReq` against a particular\r
-/// version to see if it satisfies some or all of the constraints.\r
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]\r
-#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]\r
-#[cfg_attr(feature = "diesel", sql_type = "diesel::sql_types::Text")]\r
-pub struct VersionReq {\r
-    predicates: Vec<Predicate>,\r
-}\r
-\r
-impl From<semver_parser::range::VersionReq> for VersionReq {\r
-    fn from(other: semver_parser::range::VersionReq) -> VersionReq {\r
-        VersionReq {\r
-            predicates: other.predicates.into_iter().map(From::from).collect(),\r
-        }\r
-    }\r
-}\r
-\r
-#[cfg(feature = "serde")]\r
-impl Serialize for VersionReq {\r
-    fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>\r
-    where\r
-        S: Serializer,\r
-    {\r
-        // Serialize VersionReq as a string.\r
-        serializer.collect_str(self)\r
-    }\r
-}\r
-\r
-#[cfg(feature = "serde")]\r
-impl<'de> Deserialize<'de> for VersionReq {\r
-    fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>\r
-    where\r
-        D: Deserializer<'de>,\r
-    {\r
-        struct VersionReqVisitor;\r
-\r
-        /// Deserialize `VersionReq` from a string.\r
-        impl<'de> Visitor<'de> for VersionReqVisitor {\r
-            type Value = VersionReq;\r
-\r
-            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {\r
-                formatter.write_str("a SemVer version requirement as a string")\r
-            }\r
-\r
-            fn visit_str<E>(self, v: &str) -> ::std::result::Result<Self::Value, E>\r
-            where\r
-                E: de::Error,\r
-            {\r
-                VersionReq::parse(v).map_err(de::Error::custom)\r
-            }\r
-        }\r
-\r
-        deserializer.deserialize_str(VersionReqVisitor)\r
-    }\r
-}\r
-\r
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]\r
-enum WildcardVersion {\r
-    Major,\r
-    Minor,\r
-    Patch,\r
-}\r
-\r
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]\r
-enum Op {\r
-    Ex,                        // Exact\r
-    Gt,                        // Greater than\r
-    GtEq,                      // Greater than or equal to\r
-    Lt,                        // Less than\r
-    LtEq,                      // Less than or equal to\r
-    Tilde,                     // e.g. ~1.0.0\r
-    Compatible,                // compatible by definition of semver, indicated by ^\r
-    Wildcard(WildcardVersion), // x.y.*, x.*, *\r
-}\r
-\r
-impl From<semver_parser::range::Op> for Op {\r
-    fn from(other: semver_parser::range::Op) -> Op {\r
-        use semver_parser::range;\r
-        match other {\r
-            range::Op::Ex => Op::Ex,\r
-            range::Op::Gt => Op::Gt,\r
-            range::Op::GtEq => Op::GtEq,\r
-            range::Op::Lt => Op::Lt,\r
-            range::Op::LtEq => Op::LtEq,\r
-            range::Op::Tilde => Op::Tilde,\r
-            range::Op::Compatible => Op::Compatible,\r
-            range::Op::Wildcard(version) => match version {\r
-                range::WildcardVersion::Major => Op::Wildcard(WildcardVersion::Major),\r
-                range::WildcardVersion::Minor => Op::Wildcard(WildcardVersion::Minor),\r
-                range::WildcardVersion::Patch => Op::Wildcard(WildcardVersion::Patch),\r
-            },\r
-        }\r
-    }\r
-}\r
-\r
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]\r
-struct Predicate {\r
-    op: Op,\r
-    major: u64,\r
-    minor: Option<u64>,\r
-    patch: Option<u64>,\r
-    pre: Vec<Identifier>,\r
-}\r
-\r
-impl From<semver_parser::range::Predicate> for Predicate {\r
-    fn from(other: semver_parser::range::Predicate) -> Predicate {\r
-        Predicate {\r
-            op: From::from(other.op),\r
-            major: other.major,\r
-            minor: other.minor,\r
-            patch: other.patch,\r
-            pre: other.pre.into_iter().map(From::from).collect(),\r
-        }\r
-    }\r
-}\r
-\r
-/// A `ReqParseError` is returned from methods which parse a string into a [`VersionReq`]. Each\r
-/// enumeration is one of the possible errors that can occur.\r
-/// [`VersionReq`]: struct.VersionReq.html\r
-#[derive(Clone, Debug, PartialEq)]\r
-pub enum ReqParseError {\r
-    /// The given version requirement is invalid.\r
-    InvalidVersionRequirement,\r
-    /// You have already provided an operation, such as `=`, `~`, or `^`. Only use one.\r
-    OpAlreadySet,\r
-    /// The sigil you have written is not correct.\r
-    InvalidSigil,\r
-    /// All components of a version must be numeric.\r
-    VersionComponentsMustBeNumeric,\r
-    /// There was an error parsing an identifier.\r
-    InvalidIdentifier,\r
-    /// At least a major version is required.\r
-    MajorVersionRequired,\r
-    /// An unimplemented version requirement.\r
-    UnimplementedVersionRequirement,\r
-    /// This form of requirement is deprecated.\r
-    DeprecatedVersionRequirement(VersionReq),\r
-}\r
-\r
-impl fmt::Display for ReqParseError {\r
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\r
-        let msg = match self {\r
-            InvalidVersionRequirement => "the given version requirement is invalid",\r
-            OpAlreadySet => {\r
-                "you have already provided an operation, such as =, ~, or ^; only use one"\r
-            }\r
-            InvalidSigil => "the sigil you have written is not correct",\r
-            VersionComponentsMustBeNumeric => "version components must be numeric",\r
-            InvalidIdentifier => "invalid identifier",\r
-            MajorVersionRequired => "at least a major version number is required",\r
-            UnimplementedVersionRequirement => {\r
-                "the given version requirement is not implemented, yet"\r
-            }\r
-            DeprecatedVersionRequirement(_) => "This requirement is deprecated",\r
-        };\r
-        msg.fmt(f)\r
-    }\r
-}\r
-\r
-impl Error for ReqParseError {}\r
-\r
-impl From<String> for ReqParseError {\r
-    fn from(other: String) -> ReqParseError {\r
-        match &*other {\r
-            "Null is not a valid VersionReq" => ReqParseError::InvalidVersionRequirement,\r
-            "VersionReq did not parse properly." => ReqParseError::OpAlreadySet,\r
-            _ => ReqParseError::InvalidVersionRequirement,\r
-        }\r
-    }\r
-}\r
-\r
-impl VersionReq {\r
-    /// `any()` is a factory method which creates a `VersionReq` with no constraints. In other\r
-    /// words, any version will match against it.\r
-    ///\r
-    /// # Examples\r
-    ///\r
-    /// ```\r
-    /// use semver::VersionReq;\r
-    ///\r
-    /// let anything = VersionReq::any();\r
-    /// ```\r
-    pub fn any() -> VersionReq {\r
-        VersionReq { predicates: vec![] }\r
-    }\r
-\r
-    /// `parse()` is the main constructor of a `VersionReq`. It takes a string like `"^1.2.3"`\r
-    /// and turns it into a `VersionReq` that matches that particular constraint.\r
-    ///\r
-    /// A `Result` is returned which contains a [`ReqParseError`] if there was a problem parsing the\r
-    /// `VersionReq`.\r
-    /// [`ReqParseError`]: enum.ReqParseError.html\r
-    ///\r
-    /// # Examples\r
-    ///\r
-    /// ```\r
-    /// use semver::VersionReq;\r
-    ///\r
-    /// let version = VersionReq::parse("=1.2.3");\r
-    /// let version = VersionReq::parse(">1.2.3");\r
-    /// let version = VersionReq::parse("<1.2.3");\r
-    /// let version = VersionReq::parse("~1.2.3");\r
-    /// let version = VersionReq::parse("^1.2.3");\r
-    /// let version = VersionReq::parse("1.2.3"); // synonym for ^1.2.3\r
-    /// let version = VersionReq::parse("<=1.2.3");\r
-    /// let version = VersionReq::parse(">=1.2.3");\r
-    /// ```\r
-    ///\r
-    /// This example demonstrates error handling, and will panic.\r
-    ///\r
-    /// ```should_panic\r
-    /// use semver::VersionReq;\r
-    ///\r
-    /// let version = match VersionReq::parse("not a version") {\r
-    ///     Ok(version) => version,\r
-    ///     Err(e) => panic!("There was a problem parsing: {}", e),\r
-    /// };\r
-    /// ```\r
-    ///\r
-    /// # Errors\r
-    ///\r
-    /// Returns an error variant if the input could not be parsed as a semver requirement.\r
-    ///\r
-    /// Examples of common error causes are as follows:\r
-    ///\r
-    /// * `\0` - an invalid version requirement is used.\r
-    /// * `>= >= 1.2.3` - multiple operations are used. Only use one.\r
-    /// * `>== 1.2.3` - an invalid operation is used.\r
-    /// * `a.0.0` - version components are not numeric.\r
-    /// * `1.2.3-` - an invalid identifier is present.\r
-    /// * `>=` - major version was not specified. At least a major version is required.\r
-    /// * `0.2*` - deprecated requirement syntax. Equivalent would be `0.2.*`.\r
-    ///\r
-    /// You may also encounter an `UnimplementedVersionRequirement` error, which indicates that a\r
-    /// given requirement syntax is not yet implemented in this crate.\r
-    pub fn parse(input: &str) -> Result<VersionReq, ReqParseError> {\r
-        let res = semver_parser::range::parse(input);\r
-\r
-        if let Ok(v) = res {\r
-            return Ok(From::from(v));\r
-        }\r
-\r
-        match VersionReq::parse_deprecated(input) {\r
-            Some(v) => Err(ReqParseError::DeprecatedVersionRequirement(v)),\r
-            None => Err(From::from(res.err().unwrap())),\r
-        }\r
-    }\r
-\r
-    fn parse_deprecated(version: &str) -> Option<VersionReq> {\r
-        match version {\r
-            ".*" => Some(VersionReq::any()),\r
-            "0.1.0." => Some(VersionReq::parse("0.1.0").unwrap()),\r
-            "0.3.1.3" => Some(VersionReq::parse("0.3.13").unwrap()),\r
-            "0.2*" => Some(VersionReq::parse("0.2.*").unwrap()),\r
-            "*.0" => Some(VersionReq::any()),\r
-            _ => None,\r
-        }\r
-    }\r
-\r
-    /// `exact()` is a factory method which creates a `VersionReq` with one exact constraint.\r
-    ///\r
-    /// # Examples\r
-    ///\r
-    /// ```\r
-    /// use semver::VersionReq;\r
-    /// use semver::Version;\r
-    ///\r
-    /// let version = Version { major: 1, minor: 1, patch: 1, pre: vec![], build: vec![] };\r
-    /// let exact = VersionReq::exact(&version);\r
-    /// ```\r
-    pub fn exact(version: &Version) -> VersionReq {\r
-        VersionReq {\r
-            predicates: vec![Predicate::exact(version)],\r
-        }\r
-    }\r
-\r
-    /// `matches()` matches a given [`Version`] against this `VersionReq`.\r
-    /// [`Version`]: struct.Version.html\r
-    ///\r
-    /// # Examples\r
-    ///\r
-    /// ```\r
-    /// use semver::VersionReq;\r
-    /// use semver::Version;\r
-    ///\r
-    /// let version = Version { major: 1, minor: 1, patch: 1, pre: vec![], build: vec![] };\r
-    /// let exact = VersionReq::exact(&version);\r
-    ///\r
-    /// assert!(exact.matches(&version));\r
-    /// ```\r
-    pub fn matches(&self, version: &Version) -> bool {\r
-        // no predicates means anything matches\r
-        if self.predicates.is_empty() {\r
-            return true;\r
-        }\r
-\r
-        self.predicates.iter().all(|p| p.matches(version))\r
-            && self\r
-                .predicates\r
-                .iter()\r
-                .any(|p| p.pre_tag_is_compatible(version))\r
-    }\r
-\r
-    /// `is_exact()` returns `true` if there is exactly one version which could match this\r
-    /// `VersionReq`. If `false` is returned, it is possible that there may still only be exactly\r
-    /// one version which could match this `VersionReq`. This function is intended do allow\r
-    /// short-circuiting more complex logic where being able to handle only the possibility of a\r
-    /// single exact version may be cheaper.\r
-    ///\r
-    /// # Examples\r
-    ///\r
-    /// ```\r
-    /// use semver::ReqParseError;\r
-    /// use semver::VersionReq;\r
-    ///\r
-    /// fn use_is_exact() -> Result<(), ReqParseError> {\r
-    ///   assert!(VersionReq::parse("=1.0.0")?.is_exact());\r
-    ///   assert!(!VersionReq::parse("=1.0")?.is_exact());\r
-    ///   assert!(!VersionReq::parse(">=1.0.0")?.is_exact());\r
-    ///   Ok(())\r
-    /// }\r
-    ///\r
-    /// use_is_exact().unwrap();\r
-    /// ```\r
-    pub fn is_exact(&self) -> bool {\r
-        if let [predicate] = self.predicates.as_slice() {\r
-            predicate.has_exactly_one_match()\r
-        } else {\r
-            false\r
-        }\r
-    }\r
-}\r
-\r
-impl str::FromStr for VersionReq {\r
-    type Err = ReqParseError;\r
-\r
-    fn from_str(s: &str) -> Result<VersionReq, ReqParseError> {\r
-        VersionReq::parse(s)\r
-    }\r
-}\r
-\r
-impl Predicate {\r
-    fn exact(version: &Version) -> Predicate {\r
-        Predicate {\r
-            op: Ex,\r
-            major: version.major,\r
-            minor: Some(version.minor),\r
-            patch: Some(version.patch),\r
-            pre: version.pre.clone(),\r
-        }\r
-    }\r
-\r
-    /// `matches()` takes a `Version` and determines if it matches this particular `Predicate`.\r
-    pub fn matches(&self, ver: &Version) -> bool {\r
-        match self.op {\r
-            Ex => self.matches_exact(ver),\r
-            Gt => self.matches_greater(ver),\r
-            GtEq => self.matches_exact(ver) || self.matches_greater(ver),\r
-            Lt => !self.matches_exact(ver) && !self.matches_greater(ver),\r
-            LtEq => !self.matches_greater(ver),\r
-            Tilde => self.matches_tilde(ver),\r
-            Compatible => self.is_compatible(ver),\r
-            Wildcard(_) => self.matches_wildcard(ver),\r
-        }\r
-    }\r
-\r
-    fn matches_exact(&self, ver: &Version) -> bool {\r
-        if self.major != ver.major {\r
-            return false;\r
-        }\r
-\r
-        match self.minor {\r
-            Some(minor) => {\r
-                if minor != ver.minor {\r
-                    return false;\r
-                }\r
-            }\r
-            None => return true,\r
-        }\r
-\r
-        match self.patch {\r
-            Some(patch) => {\r
-                if patch != ver.patch {\r
-                    return false;\r
-                }\r
-            }\r
-            None => return true,\r
-        }\r
-\r
-        if self.pre != ver.pre {\r
-            return false;\r
-        }\r
-\r
-        true\r
-    }\r
-\r
-    // https://docs.npmjs.com/misc/semver#prerelease-tags\r
-    fn pre_tag_is_compatible(&self, ver: &Version) -> bool {\r
-        // If a version has a prerelease tag (for example, 1.2.3-alpha.3) then it will\r
-        // only be\r
-        // allowed to satisfy comparator sets if at least one comparator with the same\r
-        // [major,\r
-        // minor, patch] tuple also has a prerelease tag.\r
-        !ver.is_prerelease()\r
-            || (self.major == ver.major\r
-                && self.minor == Some(ver.minor)\r
-                && self.patch == Some(ver.patch)\r
-                && !self.pre.is_empty())\r
-    }\r
-\r
-    fn matches_greater(&self, ver: &Version) -> bool {\r
-        if self.major != ver.major {\r
-            return ver.major > self.major;\r
-        }\r
-\r
-        match self.minor {\r
-            Some(minor) => {\r
-                if minor != ver.minor {\r
-                    return ver.minor > minor;\r
-                }\r
-            }\r
-            None => return false,\r
-        }\r
-\r
-        match self.patch {\r
-            Some(patch) => {\r
-                if patch != ver.patch {\r
-                    return ver.patch > patch;\r
-                }\r
-            }\r
-            None => return false,\r
-        }\r
-\r
-        if !self.pre.is_empty() {\r
-            return ver.pre.is_empty() || ver.pre > self.pre;\r
-        }\r
-\r
-        false\r
-    }\r
-\r
-    // see https://www.npmjs.com/package/semver for behavior\r
-    fn matches_tilde(&self, ver: &Version) -> bool {\r
-        let minor = match self.minor {\r
-            Some(n) => n,\r
-            None => return self.major == ver.major,\r
-        };\r
-\r
-        match self.patch {\r
-            Some(patch) => {\r
-                self.major == ver.major\r
-                    && minor == ver.minor\r
-                    && (ver.patch > patch || (ver.patch == patch && self.pre_is_compatible(ver)))\r
-            }\r
-            None => self.major == ver.major && minor == ver.minor,\r
-        }\r
-    }\r
-\r
-    // see https://www.npmjs.com/package/semver for behavior\r
-    fn is_compatible(&self, ver: &Version) -> bool {\r
-        if self.major != ver.major {\r
-            return false;\r
-        }\r
-\r
-        let minor = match self.minor {\r
-            Some(n) => n,\r
-            None => return self.major == ver.major,\r
-        };\r
-\r
-        match self.patch {\r
-            Some(patch) => {\r
-                if self.major == 0 {\r
-                    if minor == 0 {\r
-                        ver.minor == minor && ver.patch == patch && self.pre_is_compatible(ver)\r
-                    } else {\r
-                        ver.minor == minor\r
-                            && (ver.patch > patch\r
-                                || (ver.patch == patch && self.pre_is_compatible(ver)))\r
-                    }\r
-                } else {\r
-                    ver.minor > minor\r
-                        || (ver.minor == minor\r
-                            && (ver.patch > patch\r
-                                || (ver.patch == patch && self.pre_is_compatible(ver))))\r
-                }\r
-            }\r
-            None => {\r
-                if self.major == 0 {\r
-                    ver.minor == minor\r
-                } else {\r
-                    ver.minor >= minor\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-    fn pre_is_compatible(&self, ver: &Version) -> bool {\r
-        ver.pre.is_empty() || ver.pre >= self.pre\r
-    }\r
-\r
-    // see https://www.npmjs.com/package/semver for behavior\r
-    fn matches_wildcard(&self, ver: &Version) -> bool {\r
-        match self.op {\r
-            Wildcard(Major) => true,\r
-            Wildcard(Minor) => self.major == ver.major,\r
-            Wildcard(Patch) => {\r
-                match self.minor {\r
-                    Some(minor) => self.major == ver.major && minor == ver.minor,\r
-                    None => {\r
-                        // minor and patch version astericks mean match on major\r
-                        self.major == ver.major\r
-                    }\r
-                }\r
-            }\r
-            _ => false, // unreachable\r
-        }\r
-    }\r
-\r
-    fn has_exactly_one_match(&self) -> bool {\r
-        self.op == Ex && self.minor.is_some() && self.patch.is_some()\r
-    }\r
-}\r
-\r
-impl fmt::Display for VersionReq {\r
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {\r
-        if self.predicates.is_empty() {\r
-            write!(fmt, "*")?;\r
-        } else {\r
-            for (i, ref pred) in self.predicates.iter().enumerate() {\r
-                if i == 0 {\r
-                    write!(fmt, "{}", pred)?;\r
-                } else {\r
-                    write!(fmt, ", {}", pred)?;\r
-                }\r
-            }\r
-        }\r
-\r
-        Ok(())\r
-    }\r
-}\r
-\r
-impl fmt::Display for Predicate {\r
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {\r
-        match self.op {\r
-            Wildcard(Major) => write!(fmt, "*")?,\r
-            Wildcard(Minor) => write!(fmt, "{}.*", self.major)?,\r
-            Wildcard(Patch) => {\r
-                if let Some(minor) = self.minor {\r
-                    write!(fmt, "{}.{}.*", self.major, minor)?\r
-                } else {\r
-                    write!(fmt, "{}.*.*", self.major)?\r
-                }\r
-            }\r
-            _ => {\r
-                write!(fmt, "{}{}", self.op, self.major)?;\r
-\r
-                if let Some(v) = self.minor {\r
-                    write!(fmt, ".{}", v)?;\r
-                }\r
-\r
-                if let Some(v) = self.patch {\r
-                    write!(fmt, ".{}", v)?;\r
-                }\r
-\r
-                if !self.pre.is_empty() {\r
-                    write!(fmt, "-")?;\r
-                    for (i, x) in self.pre.iter().enumerate() {\r
-                        if i != 0 {\r
-                            write!(fmt, ".")?\r
-                        }\r
-                        write!(fmt, "{}", x)?;\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        Ok(())\r
-    }\r
-}\r
-\r
-impl fmt::Display for Op {\r
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {\r
-        match *self {\r
-            Ex => write!(fmt, "=")?,\r
-            Gt => write!(fmt, ">")?,\r
-            GtEq => write!(fmt, ">=")?,\r
-            Lt => write!(fmt, "<")?,\r
-            LtEq => write!(fmt, "<=")?,\r
-            Tilde => write!(fmt, "~")?,\r
-            Compatible => write!(fmt, "^")?,\r
-            // gets handled specially in Predicate::fmt\r
-            Wildcard(_) => write!(fmt, "")?,\r
-        }\r
-        Ok(())\r
-    }\r
-}\r
-\r
-#[cfg(test)]\r
-mod test {\r
-    use super::super::version::Version;\r
-    use super::{Op, VersionReq};\r
-    use std::hash::{Hash, Hasher};\r
-\r
-    fn req(s: &str) -> VersionReq {\r
-        VersionReq::parse(s).unwrap()\r
-    }\r
-\r
-    fn version(s: &str) -> Version {\r
-        match Version::parse(s) {\r
-            Ok(v) => v,\r
-            Err(e) => panic!("`{}` is not a valid version. Reason: {:?}", s, e),\r
-        }\r
-    }\r
-\r
-    fn assert_match(req: &VersionReq, vers: &[&str]) {\r
-        for ver in vers.iter() {\r
-            assert!(req.matches(&version(*ver)), "did not match {}", ver);\r
-        }\r
-    }\r
-\r
-    fn assert_not_match(req: &VersionReq, vers: &[&str]) {\r
-        for ver in vers.iter() {\r
-            assert!(!req.matches(&version(*ver)), "matched {}", ver);\r
-        }\r
-    }\r
-\r
-    fn calculate_hash<T: Hash>(t: T) -> u64 {\r
-        use std::collections::hash_map::DefaultHasher;\r
-\r
-        let mut s = DefaultHasher::new();\r
-        t.hash(&mut s);\r
-        s.finish()\r
-    }\r
-\r
-    #[test]\r
-    fn test_parsing_default() {\r
-        let r = req("1.0.0");\r
-\r
-        assert_eq!(r.to_string(), "^1.0.0".to_string());\r
-\r
-        assert_match(&r, &["1.0.0", "1.0.1"]);\r
-        assert_not_match(&r, &["0.9.9", "0.10.0", "0.1.0"]);\r
-    }\r
-\r
-    #[test]\r
-    fn test_parsing_exact() {\r
-        let r = req("=1.0.0");\r
-\r
-        assert!(r.to_string() == "=1.0.0".to_string());\r
-        assert_eq!(r.to_string(), "=1.0.0".to_string());\r
-\r
-        assert_match(&r, &["1.0.0"]);\r
-        assert_not_match(&r, &["1.0.1", "0.9.9", "0.10.0", "0.1.0", "1.0.0-pre"]);\r
-\r
-        let r = req("=0.9.0");\r
-\r
-        assert_eq!(r.to_string(), "=0.9.0".to_string());\r
-\r
-        assert_match(&r, &["0.9.0"]);\r
-        assert_not_match(&r, &["0.9.1", "1.9.0", "0.0.9"]);\r
-\r
-        let r = req("=0.1.0-beta2.a");\r
-\r
-        assert_eq!(r.to_string(), "=0.1.0-beta2.a".to_string());\r
-\r
-        assert_match(&r, &["0.1.0-beta2.a"]);\r
-        assert_not_match(&r, &["0.9.1", "0.1.0", "0.1.1-beta2.a", "0.1.0-beta2"]);\r
-    }\r
-\r
-    #[test]\r
-    fn test_parse_metadata_see_issue_88_see_issue_88() {\r
-        for op in &[\r
-            Op::Compatible,\r
-            Op::Ex,\r
-            Op::Gt,\r
-            Op::GtEq,\r
-            Op::Lt,\r
-            Op::LtEq,\r
-            Op::Tilde,\r
-        ] {\r
-            req(&format!("{} 1.2.3+meta", op));\r
-        }\r
-    }\r
-\r
-    #[test]\r
-    pub fn test_parsing_greater_than() {\r
-        let r = req(">= 1.0.0");\r
-\r
-        assert_eq!(r.to_string(), ">=1.0.0".to_string());\r
-\r
-        assert_match(&r, &["1.0.0", "2.0.0"]);\r
-        assert_not_match(&r, &["0.1.0", "0.0.1", "1.0.0-pre", "2.0.0-pre"]);\r
-\r
-        let r = req(">= 2.1.0-alpha2");\r
-\r
-        assert_match(&r, &["2.1.0-alpha2", "2.1.0-alpha3", "2.1.0", "3.0.0"]);\r
-        assert_not_match(\r
-            &r,\r
-            &["2.0.0", "2.1.0-alpha1", "2.0.0-alpha2", "3.0.0-alpha2"],\r
-        );\r
-    }\r
-\r
-    #[test]\r
-    pub fn test_parsing_less_than() {\r
-        let r = req("< 1.0.0");\r
-\r
-        assert_eq!(r.to_string(), "<1.0.0".to_string());\r
-\r
-        assert_match(&r, &["0.1.0", "0.0.1"]);\r
-        assert_not_match(&r, &["1.0.0", "1.0.0-beta", "1.0.1", "0.9.9-alpha"]);\r
-\r
-        let r = req("<= 2.1.0-alpha2");\r
-\r
-        assert_match(&r, &["2.1.0-alpha2", "2.1.0-alpha1", "2.0.0", "1.0.0"]);\r
-        assert_not_match(\r
-            &r,\r
-            &["2.1.0", "2.2.0-alpha1", "2.0.0-alpha2", "1.0.0-alpha2"],\r
-        );\r
-    }\r
-\r
-    #[test]\r
-    pub fn test_multiple() {\r
-        let r = req("> 0.0.9, <= 2.5.3");\r
-        assert_eq!(r.to_string(), ">0.0.9, <=2.5.3".to_string());\r
-        assert_match(&r, &["0.0.10", "1.0.0", "2.5.3"]);\r
-        assert_not_match(&r, &["0.0.8", "2.5.4"]);\r
-\r
-        let r = req("0.3.0, 0.4.0");\r
-        assert_eq!(r.to_string(), "^0.3.0, ^0.4.0".to_string());\r
-        assert_not_match(&r, &["0.0.8", "0.3.0", "0.4.0"]);\r
-\r
-        let r = req("<= 0.2.0, >= 0.5.0");\r
-        assert_eq!(r.to_string(), "<=0.2.0, >=0.5.0".to_string());\r
-        assert_not_match(&r, &["0.0.8", "0.3.0", "0.5.1"]);\r
-\r
-        let r = req("0.1.0, 0.1.4, 0.1.6");\r
-        assert_eq!(r.to_string(), "^0.1.0, ^0.1.4, ^0.1.6".to_string());\r
-        assert_match(&r, &["0.1.6", "0.1.9"]);\r
-        assert_not_match(&r, &["0.1.0", "0.1.4", "0.2.0"]);\r
-\r
-        assert!(VersionReq::parse("> 0.1.0,").is_err());\r
-        assert!(VersionReq::parse("> 0.3.0, ,").is_err());\r
-\r
-        let r = req(">=0.5.1-alpha3, <0.6");\r
-        assert_eq!(r.to_string(), ">=0.5.1-alpha3, <0.6".to_string());\r
-        assert_match(\r
-            &r,\r
-            &[\r
-                "0.5.1-alpha3",\r
-                "0.5.1-alpha4",\r
-                "0.5.1-beta",\r
-                "0.5.1",\r
-                "0.5.5",\r
-            ],\r
-        );\r
-        assert_not_match(\r
-            &r,\r
-            &["0.5.1-alpha1", "0.5.2-alpha3", "0.5.5-pre", "0.5.0-pre"],\r
-        );\r
-        assert_not_match(&r, &["0.6.0", "0.6.0-pre"]);\r
-    }\r
-\r
-    #[test]\r
-    pub fn test_parsing_tilde() {\r
-        let r = req("~1");\r
-        assert_match(&r, &["1.0.0", "1.0.1", "1.1.1"]);\r
-        assert_not_match(&r, &["0.9.1", "2.9.0", "0.0.9"]);\r
-\r
-        let r = req("~1.2");\r
-        assert_match(&r, &["1.2.0", "1.2.1"]);\r
-        assert_not_match(&r, &["1.1.1", "1.3.0", "0.0.9"]);\r
-\r
-        let r = req("~1.2.2");\r
-        assert_match(&r, &["1.2.2", "1.2.4"]);\r
-        assert_not_match(&r, &["1.2.1", "1.9.0", "1.0.9", "2.0.1", "0.1.3"]);\r
-\r
-        let r = req("~1.2.3-beta.2");\r
-        assert_match(&r, &["1.2.3", "1.2.4", "1.2.3-beta.2", "1.2.3-beta.4"]);\r
-        assert_not_match(&r, &["1.3.3", "1.1.4", "1.2.3-beta.1", "1.2.4-beta.2"]);\r
-    }\r
-\r
-    #[test]\r
-    pub fn test_parsing_compatible() {\r
-        let r = req("^1");\r
-        assert_match(&r, &["1.1.2", "1.1.0", "1.2.1", "1.0.1"]);\r
-        assert_not_match(&r, &["0.9.1", "2.9.0", "0.1.4"]);\r
-        assert_not_match(&r, &["1.0.0-beta1", "0.1.0-alpha", "1.0.1-pre"]);\r
-\r
-        let r = req("^1.1");\r
-        assert_match(&r, &["1.1.2", "1.1.0", "1.2.1"]);\r
-        assert_not_match(&r, &["0.9.1", "2.9.0", "1.0.1", "0.1.4"]);\r
-\r
-        let r = req("^1.1.2");\r
-        assert_match(&r, &["1.1.2", "1.1.4", "1.2.1"]);\r
-        assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]);\r
-        assert_not_match(&r, &["1.1.2-alpha1", "1.1.3-alpha1", "2.9.0-alpha1"]);\r
-\r
-        let r = req("^0.1.2");\r
-        assert_match(&r, &["0.1.2", "0.1.4"]);\r
-        assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]);\r
-        assert_not_match(&r, &["0.1.2-beta", "0.1.3-alpha", "0.2.0-pre"]);\r
-\r
-        let r = req("^0.5.1-alpha3");\r
-        assert_match(\r
-            &r,\r
-            &[\r
-                "0.5.1-alpha3",\r
-                "0.5.1-alpha4",\r
-                "0.5.1-beta",\r
-                "0.5.1",\r
-                "0.5.5",\r
-            ],\r
-        );\r
-        assert_not_match(\r
-            &r,\r
-            &[\r
-                "0.5.1-alpha1",\r
-                "0.5.2-alpha3",\r
-                "0.5.5-pre",\r
-                "0.5.0-pre",\r
-                "0.6.0",\r
-            ],\r
-        );\r
-\r
-        let r = req("^0.0.2");\r
-        assert_match(&r, &["0.0.2"]);\r
-        assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1", "0.1.4"]);\r
-\r
-        let r = req("^0.0");\r
-        assert_match(&r, &["0.0.2", "0.0.0"]);\r
-        assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.1.4"]);\r
-\r
-        let r = req("^0");\r
-        assert_match(&r, &["0.9.1", "0.0.2", "0.0.0"]);\r
-        assert_not_match(&r, &["2.9.0", "1.1.1"]);\r
-\r
-        let r = req("^1.4.2-beta.5");\r
-        assert_match(\r
-            &r,\r
-            &["1.4.2", "1.4.3", "1.4.2-beta.5", "1.4.2-beta.6", "1.4.2-c"],\r
-        );\r
-        assert_not_match(\r
-            &r,\r
-            &[\r
-                "0.9.9",\r
-                "2.0.0",\r
-                "1.4.2-alpha",\r
-                "1.4.2-beta.4",\r
-                "1.4.3-beta.5",\r
-            ],\r
-        );\r
-    }\r
-\r
-    #[test]\r
-    pub fn test_parsing_wildcard() {\r
-        let r = req("");\r
-        assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]);\r
-        assert_not_match(&r, &[]);\r
-        let r = req("*");\r
-        assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]);\r
-        assert_not_match(&r, &[]);\r
-        let r = req("x");\r
-        assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]);\r
-        assert_not_match(&r, &[]);\r
-        let r = req("X");\r
-        assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]);\r
-        assert_not_match(&r, &[]);\r
-\r
-        let r = req("1.*");\r
-        assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]);\r
-        assert_not_match(&r, &["0.0.9"]);\r
-        let r = req("1.x");\r
-        assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]);\r
-        assert_not_match(&r, &["0.0.9"]);\r
-        let r = req("1.X");\r
-        assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]);\r
-        assert_not_match(&r, &["0.0.9"]);\r
-\r
-        let r = req("1.2.*");\r
-        assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]);\r
-        assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]);\r
-        let r = req("1.2.x");\r
-        assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]);\r
-        assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]);\r
-        let r = req("1.2.X");\r
-        assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]);\r
-        assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]);\r
-    }\r
-\r
-    #[test]\r
-    pub fn test_any() {\r
-        let r = VersionReq::any();\r
-        assert_match(&r, &["0.0.1", "0.1.0", "1.0.0"]);\r
-    }\r
-\r
-    #[test]\r
-    pub fn test_pre() {\r
-        let r = req("=2.1.1-really.0");\r
-        assert_match(&r, &["2.1.1-really.0"]);\r
-    }\r
-\r
-    // #[test]\r
-    // pub fn test_parse_errors() {\r
-    //    assert_eq!(Err(InvalidVersionRequirement), VersionReq::parse("\0"));\r
-    //    assert_eq!(Err(OpAlreadySet), VersionReq::parse(">= >= 0.0.2"));\r
-    //    assert_eq!(Err(InvalidSigil), VersionReq::parse(">== 0.0.2"));\r
-    //    assert_eq!(Err(VersionComponentsMustBeNumeric),\r
-    //               VersionReq::parse("a.0.0"));\r
-    //    assert_eq!(Err(InvalidIdentifier), VersionReq::parse("1.0.0-"));\r
-    //    assert_eq!(Err(MajorVersionRequired), VersionReq::parse(">="));\r
-    // }\r
-\r
-    #[test]\r
-    pub fn test_from_str() {\r
-        assert_eq!(\r
-            "1.0.0".parse::<VersionReq>().unwrap().to_string(),\r
-            "^1.0.0".to_string()\r
-        );\r
-        assert_eq!(\r
-            "=1.0.0".parse::<VersionReq>().unwrap().to_string(),\r
-            "=1.0.0".to_string()\r
-        );\r
-        assert_eq!(\r
-            "~1".parse::<VersionReq>().unwrap().to_string(),\r
-            "~1".to_string()\r
-        );\r
-        assert_eq!(\r
-            "~1.2".parse::<VersionReq>().unwrap().to_string(),\r
-            "~1.2".to_string()\r
-        );\r
-        assert_eq!(\r
-            "^1".parse::<VersionReq>().unwrap().to_string(),\r
-            "^1".to_string()\r
-        );\r
-        assert_eq!(\r
-            "^1.1".parse::<VersionReq>().unwrap().to_string(),\r
-            "^1.1".to_string()\r
-        );\r
-        assert_eq!(\r
-            "*".parse::<VersionReq>().unwrap().to_string(),\r
-            "*".to_string()\r
-        );\r
-        assert_eq!(\r
-            "1.*".parse::<VersionReq>().unwrap().to_string(),\r
-            "1.*".to_string()\r
-        );\r
-        assert_eq!(\r
-            "< 1.0.0".parse::<VersionReq>().unwrap().to_string(),\r
-            "<1.0.0".to_string()\r
-        );\r
-    }\r
-\r
-    // #[test]\r
-    // pub fn test_from_str_errors() {\r
-    //    assert_eq!(Err(InvalidVersionRequirement), "\0".parse::<VersionReq>());\r
-    //    assert_eq!(Err(OpAlreadySet), ">= >= 0.0.2".parse::<VersionReq>());\r
-    //    assert_eq!(Err(InvalidSigil), ">== 0.0.2".parse::<VersionReq>());\r
-    //    assert_eq!(Err(VersionComponentsMustBeNumeric),\r
-    //               "a.0.0".parse::<VersionReq>());\r
-    //    assert_eq!(Err(InvalidIdentifier), "1.0.0-".parse::<VersionReq>());\r
-    //    assert_eq!(Err(MajorVersionRequired), ">=".parse::<VersionReq>());\r
-    // }\r
-\r
-    #[test]\r
-    fn test_cargo3202() {\r
-        let v = "0.*.*".parse::<VersionReq>().unwrap();\r
-        assert_eq!("0.*.*", format!("{}", v.predicates[0]));\r
-\r
-        let v = "0.0.*".parse::<VersionReq>().unwrap();\r
-        assert_eq!("0.0.*", format!("{}", v.predicates[0]));\r
-\r
-        let r = req("0.*.*");\r
-        assert_match(&r, &["0.5.0"]);\r
-    }\r
-\r
-    #[test]\r
-    fn test_eq_hash() {\r
-        assert!(req("^1") == req("^1"));\r
-        assert!(calculate_hash(req("^1")) == calculate_hash(req("^1")));\r
-        assert!(req("^1") != req("^2"));\r
-    }\r
-\r
-    #[test]\r
-    fn test_ordering() {\r
-        assert!(req("=1") < req("*"));\r
-        assert!(req(">1") < req("*"));\r
-        assert!(req(">=1") < req("*"));\r
-        assert!(req("<1") < req("*"));\r
-        assert!(req("<=1") < req("*"));\r
-        assert!(req("~1") < req("*"));\r
-        assert!(req("^1") < req("*"));\r
-        assert!(req("*") == req("*"));\r
-    }\r
-\r
-    #[test]\r
-    fn is_exact() {\r
-        assert!(req("=1.0.0").is_exact());\r
-        assert!(req("=1.0.0-alpha").is_exact());\r
-\r
-        assert!(!req("=1").is_exact());\r
-        assert!(!req(">=1.0.0").is_exact());\r
-        assert!(!req(">=1.0.0, <2.0.0").is_exact());\r
-    }\r
-}\r
diff --git a/vendor/semver-0.10.0/tests/deprecation.rs b/vendor/semver-0.10.0/tests/deprecation.rs
deleted file mode 100644 (file)
index 7f3c7ad..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-extern crate semver;\r
-\r
-#[test]\r
-fn test_regressions() {\r
-    use semver::ReqParseError;\r
-    use semver::VersionReq;\r
-\r
-    let versions = vec![\r
-        (".*", VersionReq::any()),\r
-        ("0.1.0.", VersionReq::parse("0.1.0").unwrap()),\r
-        ("0.3.1.3", VersionReq::parse("0.3.13").unwrap()),\r
-        ("0.2*", VersionReq::parse("0.2.*").unwrap()),\r
-        ("*.0", VersionReq::any()),\r
-    ];\r
-\r
-    for (version, requirement) in versions.into_iter() {\r
-        let parsed = VersionReq::parse(version);\r
-        let error = parsed.err().unwrap();\r
-\r
-        assert_eq!(\r
-            ReqParseError::DeprecatedVersionRequirement(requirement),\r
-            error\r
-        );\r
-    }\r
-}\r
diff --git a/vendor/semver-0.10.0/tests/diesel.rs b/vendor/semver-0.10.0/tests/diesel.rs
deleted file mode 100644 (file)
index c07cc78..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-#![cfg(feature = "diesel")]\r
-\r
-#[macro_use]\r
-extern crate diesel;\r
-extern crate semver;\r
-\r
-use diesel::connection::SimpleConnection;\r
-use diesel::sql_types::Text;\r
-use diesel::*;\r
-use semver::{Version, VersionReq};\r
-\r
-table! {\r
-    versions (name) {\r
-        name -> Text,\r
-        vers -> Text,\r
-    }\r
-}\r
-\r
-table! {\r
-    version_reqs (name) {\r
-        name -> Text,\r
-        req -> Text,\r
-    }\r
-}\r
-\r
-fn connection() -> SqliteConnection {\r
-    let conn = SqliteConnection::establish(":memory:").unwrap();\r
-    conn.batch_execute(\r
-        "\r
-        CREATE TABLE versions (name TEXT PRIMARY KEY NOT NULL, vers TEXT NOT NULL);\r
-        CREATE TABLE version_reqs (name TEXT PRIMARY KEY NOT NULL, req TEXT NOT NULL);\r
-    ",\r
-    )\r
-    .unwrap();\r
-    conn\r
-}\r
-\r
-const VERSIONS_TO_TEST: &[&str] = &[\r
-    "0.0.1",\r
-    "0.1.0",\r
-    "1.0.0",\r
-    "1.0.0-beta1",\r
-    "1.0.0-beta.1",\r
-    "1.0.0+129384712983",\r
-    "1.0.0-beta.1+1234.5678",\r
-];\r
-\r
-#[test]\r
-fn version_round_trips() {\r
-    let conn = connection();\r
-    for version in VERSIONS_TO_TEST {\r
-        let version = version.parse::<Version>().unwrap();\r
-        let result = select(version.as_sql::<Text>()).get_result(&conn);\r
-        assert_eq!(Ok(version), result);\r
-    }\r
-}\r
-\r
-#[test]\r
-fn version_inserts_and_loads() {\r
-    use self::versions::dsl::*;\r
-\r
-    let conn = connection();\r
-    let semver_versions = VERSIONS_TO_TEST\r
-        .iter()\r
-        .enumerate()\r
-        .map(|(i, v)| (format!("Version {}", i), v.parse::<Version>().unwrap()))\r
-        .collect::<Vec<_>>();\r
-\r
-    let new_versions = semver_versions\r
-        .iter()\r
-        .map(|&(ref n, ref v)| (name.eq(n), vers.eq(v)))\r
-        .collect::<Vec<_>>();\r
-    let inserted_rows = insert_into(versions).values(&new_versions).execute(&conn);\r
-    assert_eq!(Ok(VERSIONS_TO_TEST.len()), inserted_rows);\r
-\r
-    let actual_data = versions.load(&conn);\r
-    assert_eq!(Ok(semver_versions.clone()), actual_data);\r
-}\r
-\r
-#[test]\r
-fn version_inserts_and_loads_on_struct() {\r
-    #[derive(Debug, PartialEq, Queryable, Insertable)]\r
-    #[table_name = "versions"]\r
-    struct Versioned {\r
-        name: String,\r
-        vers: Version,\r
-    }\r
-\r
-    let conn = connection();\r
-    let semver_versions = VERSIONS_TO_TEST\r
-        .iter()\r
-        .enumerate()\r
-        .map(|(i, v)| Versioned {\r
-            name: format!("Version {}", i),\r
-            vers: v.parse::<Version>().unwrap(),\r
-        })\r
-        .collect::<Vec<_>>();\r
-\r
-    let inserted_rows = insert_into(versions::table)\r
-        .values(&semver_versions)\r
-        .execute(&conn);\r
-    assert_eq!(Ok(VERSIONS_TO_TEST.len()), inserted_rows);\r
-\r
-    let actual_data = versions::table.load(&conn);\r
-    assert_eq!(Ok(semver_versions), actual_data);\r
-}\r
-\r
-const VERSION_REQS_TO_TEST: &[&str] = &[\r
-    "^1.0.0",\r
-    "= 1.0.0",\r
-    "= 0.9.0",\r
-    "= 0.1.0-beta2.a",\r
-    ">= 1.0.0",\r
-    ">= 2.1.0-alpha2",\r
-    "< 1.0.0",\r
-    "<= 2.1.0-alpha2",\r
-    "^ 1.2.3+meta",\r
-    "= 1.2.3+meta",\r
-    "> 1.2.3+meta",\r
-    ">= 1.2.3+meta",\r
-    "< 1.2.3+meta",\r
-    "<= 1.2.3+meta",\r
-    "~ 1.2.3+meta",\r
-    "> 0.0.9, <= 2.5.3",\r
-    "0.3.0, 0.4.0",\r
-    "<= 0.2.0, >= 0.5.0",\r
-    "0.1.0, 0.1.4, 0.1.6",\r
-    ">=0.5.1-alpha3, <0.6",\r
-    "~1",\r
-    "~1.2",\r
-    "~1.2.2",\r
-    "~1.2.3-beta.2",\r
-    "^1",\r
-    "^1.1",\r
-    "^1.1.2",\r
-    "^0.1.2",\r
-    "^0.5.1-alpha3",\r
-    "",\r
-    "*",\r
-    "x",\r
-    "1.*",\r
-];\r
-\r
-#[test]\r
-fn version_req_round_trips() {\r
-    let conn = connection();\r
-    for version_req in VERSION_REQS_TO_TEST {\r
-        let version_req = version_req.parse::<VersionReq>().unwrap();\r
-        let result = select(version_req.as_sql::<Text>()).get_result(&conn);\r
-        assert_eq!(Ok(version_req), result);\r
-    }\r
-}\r
-\r
-#[test]\r
-fn version_req_inserts_and_loads() {\r
-    use self::version_reqs::dsl::*;\r
-\r
-    let conn = connection();\r
-    let semver_version_reqs = VERSION_REQS_TO_TEST\r
-        .iter()\r
-        .enumerate()\r
-        .map(|(i, v)| {\r
-            (\r
-                format!("VersionReq {}", i),\r
-                v.parse::<VersionReq>().unwrap(),\r
-            )\r
-        })\r
-        .collect::<Vec<_>>();\r
-\r
-    let new_version_reqs = semver_version_reqs\r
-        .iter()\r
-        .map(|&(ref n, ref v)| (name.eq(n), req.eq(v)))\r
-        .collect::<Vec<_>>();\r
-    let inserted_rows = insert_into(version_reqs)\r
-        .values(&new_version_reqs)\r
-        .execute(&conn);\r
-    assert_eq!(Ok(VERSION_REQS_TO_TEST.len()), inserted_rows);\r
-\r
-    let actual_data = version_reqs.load(&conn);\r
-    assert_eq!(Ok(semver_version_reqs.clone()), actual_data);\r
-}\r
-\r
-#[test]\r
-fn version_req_inserts_and_loads_on_struct() {\r
-    #[derive(Debug, PartialEq, Queryable, Insertable)]\r
-    #[table_name = "version_reqs"]\r
-    struct VersionReqed {\r
-        name: String,\r
-        req: VersionReq,\r
-    }\r
-\r
-    let conn = connection();\r
-    let semver_version_reqs = VERSION_REQS_TO_TEST\r
-        .iter()\r
-        .enumerate()\r
-        .map(|(i, v)| VersionReqed {\r
-            name: format!("VersionReq {}", i),\r
-            req: v.parse::<VersionReq>().unwrap(),\r
-        })\r
-        .collect::<Vec<_>>();\r
-\r
-    let inserted_rows = insert_into(version_reqs::table)\r
-        .values(&semver_version_reqs)\r
-        .execute(&conn);\r
-    assert_eq!(Ok(VERSION_REQS_TO_TEST.len()), inserted_rows);\r
-\r
-    let actual_data = version_reqs::table.load(&conn);\r
-    assert_eq!(Ok(semver_version_reqs), actual_data);\r
-}\r
diff --git a/vendor/semver-0.10.0/tests/serde.rs b/vendor/semver-0.10.0/tests/serde.rs
deleted file mode 100644 (file)
index 31bd10d..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-#![cfg(feature = "serde")]\r
-\r
-#[macro_use]\r
-extern crate serde_derive;\r
-\r
-extern crate semver;\r
-extern crate serde_json;\r
-\r
-use semver::{Identifier, Version, VersionReq};\r
-\r
-#[derive(Serialize, Deserialize, PartialEq, Debug)]\r
-struct Identified {\r
-    name: String,\r
-    identifier: Identifier,\r
-}\r
-\r
-#[derive(Serialize, Deserialize, PartialEq, Debug)]\r
-struct Versioned {\r
-    name: String,\r
-    vers: Version,\r
-}\r
-\r
-#[test]\r
-fn serialize_identifier() {\r
-    let id = Identified {\r
-        name: "serde".to_owned(),\r
-        identifier: Identifier::Numeric(100),\r
-    };\r
-    let j = serde_json::to_string(&id).unwrap();\r
-    assert_eq!(j, r#"{"name":"serde","identifier":100}"#);\r
-\r
-    let id = Identified {\r
-        name: "serde".to_owned(),\r
-        identifier: Identifier::AlphaNumeric("b100".to_owned()),\r
-    };\r
-    let j = serde_json::to_string(&id).unwrap();\r
-    assert_eq!(j, r#"{"name":"serde","identifier":"b100"}"#);\r
-}\r
-\r
-#[test]\r
-fn deserialize_identifier() {\r
-    let j = r#"{"name":"serde","identifier":100}"#;\r
-    let id = serde_json::from_str::<Identified>(j).unwrap();\r
-    let expected = Identified {\r
-        name: "serde".to_owned(),\r
-        identifier: Identifier::Numeric(100),\r
-    };\r
-    assert_eq!(id, expected);\r
-\r
-    let j = r#"{"name":"serde","identifier":"b100"}"#;\r
-    let id = serde_json::from_str::<Identified>(j).unwrap();\r
-    let expected = Identified {\r
-        name: "serde".to_owned(),\r
-        identifier: Identifier::AlphaNumeric("b100".to_owned()),\r
-    };\r
-    assert_eq!(id, expected);\r
-}\r
-\r
-#[test]\r
-fn serialize_version() {\r
-    let v = Versioned {\r
-        name: "serde".to_owned(),\r
-        vers: Version::parse("1.0.0").unwrap(),\r
-    };\r
-    let j = serde_json::to_string(&v).unwrap();\r
-    assert_eq!(j, r#"{"name":"serde","vers":"1.0.0"}"#);\r
-}\r
-\r
-#[test]\r
-fn deserialize_version() {\r
-    let j = r#"{"name":"serde","vers":"1.0.0"}"#;\r
-    let v = serde_json::from_str::<Versioned>(j).unwrap();\r
-    let expected = Versioned {\r
-        name: "serde".to_owned(),\r
-        vers: Version::parse("1.0.0").unwrap(),\r
-    };\r
-    assert_eq!(v, expected);\r
-}\r
-\r
-#[test]\r
-fn serialize_versionreq() {\r
-    let v = VersionReq::exact(&Version::parse("1.0.0").unwrap());\r
-\r
-    assert_eq!(serde_json::to_string(&v).unwrap(), r#""= 1.0.0""#);\r
-}\r
-\r
-#[test]\r
-fn deserialize_versionreq() {\r
-    assert_eq!(\r
-        "1.0.0".parse::<VersionReq>().unwrap(),\r
-        serde_json::from_str(r#""1.0.0""#).unwrap()\r
-    );\r
-}\r
diff --git a/vendor/semver-parser-0.7.0/.cargo-checksum.json b/vendor/semver-parser-0.7.0/.cargo-checksum.json
deleted file mode 100644 (file)
index 73575fe..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"67597114802114d2a7fdb457c1cf5f7e0c951b21e287c6a47b9a86b9028cf64d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"d38feaa4f9468cd1e0ece22e0ad2eadfe6195a9a0a3843b7c722d5c7d81804fb","src/common.rs":"dc42336abd34e19ca9f732f33657e106f98dcc8c10d4c2564bc4f160cb31926e","src/lib.rs":"3ac8ef5a280344a25cb18ac386034c0fee8d64060fa14af5e25ed49f0cb2fd9e","src/range.rs":"3596f048d466d43887aff1e8c8c834476672a4627631ed35379c35466b5f02ec","src/recognize.rs":"9f16eda9fcd7d8af7eee4c3b89c611bd648040273fde6b35778f8a50b004c8b1","src/version.rs":"dbd91a4e4fd92a0aa9eb4f858ecbc1ecd680aa60572cc2ad2085e5c5c30e5b77"},"package":"388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"}
\ No newline at end of file
diff --git a/vendor/semver-parser-0.7.0/Cargo.toml b/vendor/semver-parser-0.7.0/Cargo.toml
deleted file mode 100644 (file)
index c2be878..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "semver-parser"
-version = "0.7.0"
-authors = ["Steve Klabnik <steve@steveklabnik.com>"]
-license = "MIT/Apache-2.0"
-repository = "https://github.com/steveklabnik/semver-parser"
-homepage = "https://github.com/steveklabnik/semver-parser"
-documentation = "https://docs.rs/semver-parser"
-description = """
-Parsing of the semver spec.
-"""
diff --git a/vendor/semver-parser-0.7.0/LICENSE-APACHE b/vendor/semver-parser-0.7.0/LICENSE-APACHE
deleted file mode 100644 (file)
index 16fe87b..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-                              Apache License
-                        Version 2.0, January 2004
-                     http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-   "License" shall mean the terms and conditions for use, reproduction,
-   and distribution as defined by Sections 1 through 9 of this document.
-
-   "Licensor" shall mean the copyright owner or entity authorized by
-   the copyright owner that is granting the License.
-
-   "Legal Entity" shall mean the union of the acting entity and all
-   other entities that control, are controlled by, or are under common
-   control with that entity. For the purposes of this definition,
-   "control" means (i) the power, direct or indirect, to cause the
-   direction or management of such entity, whether by contract or
-   otherwise, or (ii) ownership of fifty percent (50%) or more of the
-   outstanding shares, or (iii) beneficial ownership of such entity.
-
-   "You" (or "Your") shall mean an individual or Legal Entity
-   exercising permissions granted by this License.
-
-   "Source" form shall mean the preferred form for making modifications,
-   including but not limited to software source code, documentation
-   source, and configuration files.
-
-   "Object" form shall mean any form resulting from mechanical
-   transformation or translation of a Source form, including but
-   not limited to compiled object code, generated documentation,
-   and conversions to other media types.
-
-   "Work" shall mean the work of authorship, whether in Source or
-   Object form, made available under the License, as indicated by a
-   copyright notice that is included in or attached to the work
-   (an example is provided in the Appendix below).
-
-   "Derivative Works" shall mean any work, whether in Source or Object
-   form, that is based on (or derived from) the Work and for which the
-   editorial revisions, annotations, elaborations, or other modifications
-   represent, as a whole, an original work of authorship. For the purposes
-   of this License, Derivative Works shall not include works that remain
-   separable from, or merely link (or bind by name) to the interfaces of,
-   the Work and Derivative Works thereof.
-
-   "Contribution" shall mean any work of authorship, including
-   the original version of the Work and any modifications or additions
-   to that Work or Derivative Works thereof, that is intentionally
-   submitted to Licensor for inclusion in the Work by the copyright owner
-   or by an individual or Legal Entity authorized to submit on behalf of
-   the copyright owner. For the purposes of this definition, "submitted"
-   means any form of electronic, verbal, or written communication sent
-   to the Licensor or its representatives, including but not limited to
-   communication on electronic mailing lists, source code control systems,
-   and issue tracking systems that are managed by, or on behalf of, the
-   Licensor for the purpose of discussing and improving the Work, but
-   excluding communication that is conspicuously marked or otherwise
-   designated in writing by the copyright owner as "Not a Contribution."
-
-   "Contributor" shall mean Licensor and any individual or Legal Entity
-   on behalf of whom a Contribution has been received by Licensor and
-   subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   copyright license to reproduce, prepare Derivative Works of,
-   publicly display, publicly perform, sublicense, and distribute the
-   Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   (except as stated in this section) patent license to make, have made,
-   use, offer to sell, sell, import, and otherwise transfer the Work,
-   where such license applies only to those patent claims licensable
-   by such Contributor that are necessarily infringed by their
-   Contribution(s) alone or by combination of their Contribution(s)
-   with the Work to which such Contribution(s) was submitted. If You
-   institute patent litigation against any entity (including a
-   cross-claim or counterclaim in a lawsuit) alleging that the Work
-   or a Contribution incorporated within the Work constitutes direct
-   or contributory patent infringement, then any patent licenses
-   granted to You under this License for that Work shall terminate
-   as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
-   Work or Derivative Works thereof in any medium, with or without
-   modifications, and in Source or Object form, provided that You
-   meet the following conditions:
-
-   (a) You must give any other recipients of the Work or
-       Derivative Works a copy of this License; and
-
-   (b) You must cause any modified files to carry prominent notices
-       stating that You changed the files; and
-
-   (c) You must retain, in the Source form of any Derivative Works
-       that You distribute, all copyright, patent, trademark, and
-       attribution notices from the Source form of the Work,
-       excluding those notices that do not pertain to any part of
-       the Derivative Works; and
-
-   (d) If the Work includes a "NOTICE" text file as part of its
-       distribution, then any Derivative Works that You distribute must
-       include a readable copy of the attribution notices contained
-       within such NOTICE file, excluding those notices that do not
-       pertain to any part of the Derivative Works, in at least one
-       of the following places: within a NOTICE text file distributed
-       as part of the Derivative Works; within the Source form or
-       documentation, if provided along with the Derivative Works; or,
-       within a display generated by the Derivative Works, if and
-       wherever such third-party notices normally appear. The contents
-       of the NOTICE file are for informational purposes only and
-       do not modify the License. You may add Your own attribution
-       notices within Derivative Works that You distribute, alongside
-       or as an addendum to the NOTICE text from the Work, provided
-       that such additional attribution notices cannot be construed
-       as modifying the License.
-
-   You may add Your own copyright statement to Your modifications and
-   may provide additional or different license terms and conditions
-   for use, reproduction, or distribution of Your modifications, or
-   for any such Derivative Works as a whole, provided Your use,
-   reproduction, and distribution of the Work otherwise complies with
-   the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-   any Contribution intentionally submitted for inclusion in the Work
-   by You to the Licensor shall be under the terms and conditions of
-   this License, without any additional terms or conditions.
-   Notwithstanding the above, nothing herein shall supersede or modify
-   the terms of any separate license agreement you may have executed
-   with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-   names, trademarks, service marks, or product names of the Licensor,
-   except as required for reasonable and customary use in describing the
-   origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-   agreed to in writing, Licensor provides the Work (and each
-   Contributor provides its Contributions) on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-   implied, including, without limitation, any warranties or conditions
-   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-   PARTICULAR PURPOSE. You are solely responsible for determining the
-   appropriateness of using or redistributing the Work and assume any
-   risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-   whether in tort (including negligence), contract, or otherwise,
-   unless required by applicable law (such as deliberate and grossly
-   negligent acts) or agreed to in writing, shall any Contributor be
-   liable to You for damages, including any direct, indirect, special,
-   incidental, or consequential damages of any character arising as a
-   result of this License or out of the use or inability to use the
-   Work (including but not limited to damages for loss of goodwill,
-   work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses), even if such Contributor
-   has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-   the Work or Derivative Works thereof, You may choose to offer,
-   and charge a fee for, acceptance of support, warranty, indemnity,
-   or other liability obligations and/or rights consistent with this
-   License. However, in accepting such obligations, You may act only
-   on Your own behalf and on Your sole responsibility, not on behalf
-   of any other Contributor, and only if You agree to indemnify,
-   defend, and hold each Contributor harmless for any liability
-   incurred by, or claims asserted against, such Contributor by reason
-   of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-   To apply the Apache License to your work, attach the following
-   boilerplate notice, with the fields enclosed by brackets "[]"
-   replaced with your own identifying information. (Don't include
-   the brackets!)  The text should be enclosed in the appropriate
-   comment syntax for the file format. We also recommend that a
-   file or class name and description of purpose be included on the
-   same "printed page" as the copyright notice for easier
-   identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/vendor/semver-parser-0.7.0/LICENSE-MIT b/vendor/semver-parser-0.7.0/LICENSE-MIT
deleted file mode 100644 (file)
index fb7494a..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2016 Steve Klabnik
-
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/vendor/semver-parser-0.7.0/src/common.rs b/vendor/semver-parser-0.7.0/src/common.rs
deleted file mode 100644 (file)
index 267b4d9..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-use version::Identifier;
-use recognize::{Recognize, Alt, OneOrMore, Inclusive, OneByte};
-use std::str::from_utf8;
-
-// by the time we get here, we know that it's all valid characters, so this doesn't need to return
-// a result or anything
-fn parse_meta(s: &str) -> Vec<Identifier> {
-    // Originally, I wanted to implement this method via calling parse, but parse is tolerant of
-    // leading zeroes, and we want anything with leading zeroes to be considered alphanumeric, not
-    // numeric. So the strategy is to check with a recognizer first, and then call parse once
-    // we've determined that it's a number without a leading zero.
-    s.split(".")
-        .map(|part| {
-            // another wrinkle: we made sure that any number starts with a
-            // non-zero. But there's a problem: an actual zero is a number, yet
-            // gets left out by this heuristic. So let's also check for the
-            // single, lone zero.
-            if is_alpha_numeric(part) {
-                Identifier::AlphaNumeric(part.to_string())
-            } else {
-                // we can unwrap here because we know it is only digits due to the regex
-                Identifier::Numeric(part.parse().unwrap())
-            }
-        }).collect()
-}
-
-// parse optional metadata (preceded by the prefix character)
-pub fn parse_optional_meta(s: &[u8], prefix_char: u8)-> Result<(Vec<Identifier>, usize), String> {
-    if let Some(len) = prefix_char.p(s) {
-        let start = len;
-        if let Some(len) = letters_numbers_dash_dot(&s[start..]) {
-            let end = start + len;
-            Ok((parse_meta(from_utf8(&s[start..end]).unwrap()), end))
-        } else {
-            Err("Error parsing prerelease".to_string())
-        }
-    } else {
-        Ok((Vec::new(), 0))
-    }
-}
-
-pub fn is_alpha_numeric(s: &str) -> bool {
-    if let Some((_val, len)) = numeric_identifier(s.as_bytes()) {
-        // Return true for number with leading zero
-        // Note: doing it this way also handily makes overflow fail over.
-        len != s.len()
-    } else {
-        true
-    }
-}
-
-// Note: could plumb overflow error up to return value as Result
-pub fn numeric_identifier(s: &[u8]) -> Option<(u64, usize)> {
-    if let Some(len) = Alt(b'0', OneOrMore(Inclusive(b'0'..b'9'))).p(s) {
-        from_utf8(&s[0..len]).unwrap().parse().ok().map(|val| (val, len))
-    } else {
-        None
-    }
-}
-
-pub fn letters_numbers_dash_dot(s: &[u8]) -> Option<usize> {
-    OneOrMore(OneByte(|c| c == b'-' || c == b'.' ||
-        (b'0' <= c && c <= b'9') ||
-        (b'a' <= c && c <= b'z') ||
-        (b'A' <= c && c <= b'Z'))).p(s)
-}
diff --git a/vendor/semver-parser-0.7.0/src/lib.rs b/vendor/semver-parser-0.7.0/src/lib.rs
deleted file mode 100644 (file)
index 3b0d8f0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-pub mod version;
-pub mod range;
-
-// for private stuff the two share
-mod common;
-
-// for recognizer combinators
-mod recognize;
diff --git a/vendor/semver-parser-0.7.0/src/range.rs b/vendor/semver-parser-0.7.0/src/range.rs
deleted file mode 100644 (file)
index 858be9f..0000000
+++ /dev/null
@@ -1,696 +0,0 @@
-use common::{self, numeric_identifier, letters_numbers_dash_dot};
-use version::Identifier;
-use std::str::{FromStr, from_utf8};
-use recognize::*;
-
-#[derive(Debug)]
-pub struct VersionReq {
-    pub predicates: Vec<Predicate>,
-}
-
-#[derive(PartialEq,Debug)]
-pub enum WildcardVersion {
-    Major,
-    Minor,
-    Patch,
-}
-
-#[derive(PartialEq,Debug)]
-pub enum Op {
-    Ex, // Exact
-    Gt, // Greater than
-    GtEq, // Greater than or equal to
-    Lt, // Less than
-    LtEq, // Less than or equal to
-    Tilde, // e.g. ~1.0.0
-    Compatible, // compatible by definition of semver, indicated by ^
-    Wildcard(WildcardVersion), // x.y.*, x.*, *
-}
-
-impl FromStr for Op {
-    type Err = String;
-
-    fn from_str(s: &str) -> Result<Op, String> {
-        match s {
-            "=" => Ok(Op::Ex),
-            ">" => Ok(Op::Gt),
-            ">=" => Ok(Op::GtEq),
-            "<" => Ok(Op::Lt),
-            "<=" => Ok(Op::LtEq),
-            "~" => Ok(Op::Tilde),
-            "^" => Ok(Op::Compatible),
-            _ => Err(String::from("Could not parse Op")),
-        }
-    }
-}
-
-#[derive(PartialEq,Debug)]
-pub struct Predicate {
-    pub op: Op,
-    pub major: u64,
-    pub minor: Option<u64>,
-    pub patch: Option<u64>,
-    pub pre: Vec<Identifier>,
-}
-
-fn numeric_or_wild(s: &[u8]) -> Option<(Option<u64>, usize)> {
-    if let Some((val, len)) = numeric_identifier(s) {
-        Some((Some(val), len))
-    } else if let Some(len) = OneOf(b"*xX").p(s) {
-        Some((None, len))
-    } else {
-        None
-    }
-}
-
-fn dot_numeric_or_wild(s: &[u8]) -> Option<(Option<u64>, usize)> {
-    b'.'.p(s).and_then(|len|
-        numeric_or_wild(&s[len..]).map(|(val, len2)| (val, len + len2))
-    )
-}
-
-fn operation(s: &[u8]) -> Option<(Op, usize)> {
-    if let Some(len) = "=".p(s) {
-        Some((Op::Ex, len))
-    } else if let Some(len) = ">=".p(s) {
-        Some((Op::GtEq, len))
-    } else if let Some(len) = ">".p(s) {
-        Some((Op::Gt, len))
-    } else if let Some(len) = "<=".p(s) {
-        Some((Op::LtEq, len))
-    } else if let Some(len) = "<".p(s) {
-        Some((Op::Lt, len))
-    } else if let Some(len) = "~".p(s) {
-        Some((Op::Tilde, len))
-    } else if let Some(len) = "^".p(s) {
-        Some((Op::Compatible, len))
-    } else {
-        None
-    }
-}
-
-fn whitespace(s: &[u8]) -> Option<usize> {
-    ZeroOrMore(OneOf(b"\t\r\n ")).p(s)
-}
-
-pub fn parse_predicate(range: &str) -> Result<Predicate, String> {
-    let s = range.trim().as_bytes();
-    let mut i = 0;
-    let mut operation = if let Some((op, len)) = operation(&s[i..]) {
-        i += len;
-        op
-    } else {
-        // operations default to Compatible
-        Op::Compatible
-    };
-    if let Some(len) = whitespace.p(&s[i..]) {
-        i += len;
-    }
-    let major = if let Some((major, len)) = numeric_identifier(&s[i..]) {
-        i += len;
-        major
-    } else {
-        return Err("Error parsing major version number: ".to_string());
-    };
-    let minor = if let Some((minor, len)) = dot_numeric_or_wild(&s[i..]) {
-        i += len;
-        if minor.is_none() {
-            operation = Op::Wildcard(WildcardVersion::Minor);
-        }
-        minor
-    } else {
-        None
-    };
-    let patch = if let Some((patch, len)) = dot_numeric_or_wild(&s[i..]) {
-        i += len;
-        if patch.is_none() {
-            operation = Op::Wildcard(WildcardVersion::Patch);
-        }
-        patch
-    } else {
-        None
-    };
-    let (pre, pre_len) = common::parse_optional_meta(&s[i..], b'-')?;
-    i += pre_len;
-    if let Some(len) = (b'+', letters_numbers_dash_dot).p(&s[i..]) {
-        i += len;
-    }
-    if i != s.len() {
-        return Err("Extra junk after valid predicate: ".to_string() +
-            from_utf8(&s[i..]).unwrap());
-    }
-    Ok(Predicate {
-        op: operation,
-        major: major,
-        minor: minor,
-        patch: patch,
-        pre: pre,
-    })
-}
-
-pub fn parse(ranges: &str) -> Result<VersionReq, String> {
-    // null is an error
-    if ranges == "\0" {
-        return Err(String::from("Null is not a valid VersionReq"));
-    }
-
-    // an empty range is a major version wildcard
-    // so is a lone * or x of either capitalization
-    if (ranges == "")
-    || (ranges == "*")
-    || (ranges == "x")
-    || (ranges == "X") {
-        return Ok(VersionReq {
-            predicates: vec![Predicate {
-                op: Op::Wildcard(WildcardVersion::Major),
-                major: 0,
-                minor: None,
-                patch: None,
-                pre: Vec::new(),
-            }],
-        });
-    }
-
-
-    let ranges = ranges.trim();
-
-    let predicates: Result<Vec<_>, String> = ranges
-        .split(",")
-        .map(|range| {
-            parse_predicate(range)
-        })
-        .collect();
-
-    let predicates = try!(predicates);
-
-    if predicates.len() == 0 {
-        return Err(String::from("VersionReq did not parse properly"));
-    }
-
-    Ok(VersionReq {
-        predicates: predicates,
-    })
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use range;
-    use version::Identifier;
-
-    #[test]
-    fn test_parsing_default() {
-        let r = range::parse("1.0.0").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Compatible,
-                major: 1,
-                minor: Some(0),
-                patch: Some(0),
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    fn test_parsing_exact_01() {
-        let r = range::parse("=1.0.0").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Ex,
-                major: 1,
-                minor: Some(0),
-                patch: Some(0),
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    fn test_parsing_exact_02() {
-        let r = range::parse("=0.9.0").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Ex,
-                major: 0,
-                minor: Some(9),
-                patch: Some(0),
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    fn test_parsing_exact_03() {
-        let r = range::parse("=0.1.0-beta2.a").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Ex,
-                major: 0,
-                minor: Some(1),
-                patch: Some(0),
-                pre: vec![Identifier::AlphaNumeric(String::from("beta2")),
-                          Identifier::AlphaNumeric(String::from("a"))],
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    pub fn test_parsing_greater_than() {
-        let r = range::parse("> 1.0.0").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Gt,
-                major: 1,
-                minor: Some(0),
-                patch: Some(0),
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    pub fn test_parsing_greater_than_01() {
-        let r = range::parse(">= 1.0.0").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::GtEq,
-                major: 1,
-                minor: Some(0),
-                patch: Some(0),
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    pub fn test_parsing_greater_than_02() {
-        let r = range::parse(">= 2.1.0-alpha2").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::GtEq,
-                major: 2,
-                minor: Some(1),
-                patch: Some(0),
-                pre: vec![Identifier::AlphaNumeric(String::from("alpha2"))],
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    pub fn test_parsing_less_than() {
-        let r = range::parse("< 1.0.0").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Lt,
-                major: 1,
-                minor: Some(0),
-                patch: Some(0),
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    pub fn test_parsing_less_than_eq() {
-        let r = range::parse("<= 2.1.0-alpha2").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::LtEq,
-                major: 2,
-                minor: Some(1),
-                patch: Some(0),
-                pre: vec![Identifier::AlphaNumeric(String::from("alpha2"))],
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    pub fn test_parsing_tilde() {
-        let r = range::parse("~1").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Tilde,
-                major: 1,
-                minor: None,
-                patch: None,
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    pub fn test_parsing_compatible() {
-        let r = range::parse("^0").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Compatible,
-                major: 0,
-                minor: None,
-                patch: None,
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    fn test_parsing_blank() {
-        let r = range::parse("").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Wildcard(WildcardVersion::Major),
-                major: 0,
-                minor: None,
-                patch: None,
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    fn test_parsing_wildcard() {
-        let r = range::parse("*").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Wildcard(WildcardVersion::Major),
-                major: 0,
-                minor: None,
-                patch: None,
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    fn test_parsing_x() {
-        let r = range::parse("x").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Wildcard(WildcardVersion::Major),
-                major: 0,
-                minor: None,
-                patch: None,
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    fn test_parsing_capital_x() {
-        let r = range::parse("X").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Wildcard(WildcardVersion::Major),
-                major: 0,
-                minor: None,
-                patch: None,
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    fn test_parsing_minor_wildcard_star() {
-        let r = range::parse("1.*").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Wildcard(WildcardVersion::Minor),
-                major: 1,
-                minor: None,
-                patch: None,
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    fn test_parsing_minor_wildcard_x() {
-        let r = range::parse("1.x").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Wildcard(WildcardVersion::Minor),
-                major: 1,
-                minor: None,
-                patch: None,
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    fn test_parsing_minor_wildcard_capital_x() {
-        let r = range::parse("1.X").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Wildcard(WildcardVersion::Minor),
-                major: 1,
-                minor: None,
-                patch: None,
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    fn test_parsing_patch_wildcard_star() {
-        let r = range::parse("1.2.*").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Wildcard(WildcardVersion::Patch),
-                major: 1,
-                minor: Some(2),
-                patch: None,
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    fn test_parsing_patch_wildcard_x() {
-        let r = range::parse("1.2.x").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Wildcard(WildcardVersion::Patch),
-                major: 1,
-                minor: Some(2),
-                patch: None,
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    fn test_parsing_patch_wildcard_capital_x() {
-        let r = range::parse("1.2.X").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Wildcard(WildcardVersion::Patch),
-                major: 1,
-                minor: Some(2),
-                patch: None,
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-    }
-
-    #[test]
-    pub fn test_multiple_01() {
-        let r = range::parse("> 0.0.9, <= 2.5.3").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Gt,
-                major: 0,
-                minor: Some(0),
-                patch: Some(9),
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-
-        assert_eq!(Predicate {
-                op: Op::LtEq,
-                major: 2,
-                minor: Some(5),
-                patch: Some(3),
-                pre: Vec::new(),
-            },
-            r.predicates[1]
-        );
-    }
-
-    #[test]
-    pub fn test_multiple_02() {
-        let r = range::parse("0.3.0, 0.4.0").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Compatible,
-                major: 0,
-                minor: Some(3),
-                patch: Some(0),
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-
-        assert_eq!(Predicate {
-                op: Op::Compatible,
-                major: 0,
-                minor: Some(4),
-                patch: Some(0),
-                pre: Vec::new(),
-            },
-            r.predicates[1]
-        );
-    }
-
-    #[test]
-    pub fn test_multiple_03() {
-        let r = range::parse("<= 0.2.0, >= 0.5.0").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::LtEq,
-                major: 0,
-                minor: Some(2),
-                patch: Some(0),
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-
-        assert_eq!(Predicate {
-                op: Op::GtEq,
-                major: 0,
-                minor: Some(5),
-                patch: Some(0),
-                pre: Vec::new(),
-            },
-            r.predicates[1]
-        );
-    }
-
-    #[test]
-    pub fn test_multiple_04() {
-        let r = range::parse("0.1.0, 0.1.4, 0.1.6").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::Compatible,
-                major: 0,
-                minor: Some(1),
-                patch: Some(0),
-                pre: Vec::new(),
-            },
-            r.predicates[0]
-        );
-
-        assert_eq!(Predicate {
-                op: Op::Compatible,
-                major: 0,
-                minor: Some(1),
-                patch: Some(4),
-                pre: Vec::new(),
-            },
-            r.predicates[1]
-        );
-
-        assert_eq!(Predicate {
-                op: Op::Compatible,
-                major: 0,
-                minor: Some(1),
-                patch: Some(6),
-                pre: Vec::new(),
-            },
-            r.predicates[2]
-        );
-    }
-
-    #[test]
-    pub fn test_multiple_05() {
-        let r = range::parse(">=0.5.1-alpha3, <0.6").unwrap();
-
-        assert_eq!(Predicate {
-                op: Op::GtEq,
-                major: 0,
-                minor: Some(5),
-                patch: Some(1),
-                pre: vec![Identifier::AlphaNumeric(String::from("alpha3"))],
-            },
-            r.predicates[0]
-        );
-
-        assert_eq!(Predicate {
-                op: Op::Lt,
-                major: 0,
-                minor: Some(6),
-                patch: None,
-                pre: Vec::new(),
-            },
-            r.predicates[1]
-        );
-    }
-
-    #[test]
-    fn test_parse_build_metadata_with_predicate() {
-        assert_eq!(range::parse("^1.2.3+meta").unwrap().predicates[0].op,
-                   Op::Compatible);
-        assert_eq!(range::parse("~1.2.3+meta").unwrap().predicates[0].op,
-                   Op::Tilde);
-        assert_eq!(range::parse("=1.2.3+meta").unwrap().predicates[0].op,
-                   Op::Ex);
-        assert_eq!(range::parse("<=1.2.3+meta").unwrap().predicates[0].op,
-                   Op::LtEq);
-        assert_eq!(range::parse(">=1.2.3+meta").unwrap().predicates[0].op,
-                   Op::GtEq);
-        assert_eq!(range::parse("<1.2.3+meta").unwrap().predicates[0].op,
-                   Op::Lt);
-        assert_eq!(range::parse(">1.2.3+meta").unwrap().predicates[0].op,
-                   Op::Gt);
-    }
-
-    #[test]
-    pub fn test_parse_errors() {
-        assert!(range::parse("\0").is_err());
-        assert!(range::parse(">= >= 0.0.2").is_err());
-        assert!(range::parse(">== 0.0.2").is_err());
-        assert!(range::parse("a.0.0").is_err());
-        assert!(range::parse("1.0.0-").is_err());
-        assert!(range::parse(">=").is_err());
-        assert!(range::parse("> 0.1.0,").is_err());
-        assert!(range::parse("> 0.3.0, ,").is_err());
-    }
-
-    #[test]
-    pub fn test_large_major_version() {
-        assert!(range::parse("18446744073709551617.0.0").is_err());
-    }
-
-    #[test]
-    pub fn test_large_minor_version() {
-        assert!(range::parse("0.18446744073709551617.0").is_err());
-    }
-
-    #[test]
-    pub fn test_large_patch_version() {
-        assert!(range::parse("0.0.18446744073709551617").is_err());
-    }
-}
diff --git a/vendor/semver-parser-0.7.0/src/recognize.rs b/vendor/semver-parser-0.7.0/src/recognize.rs
deleted file mode 100644 (file)
index c0dd771..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2017 Google Inc. All rights reserved.
-//
-// Licensed under either of MIT or Apache License, Version 2.0,
-// at your option.
-//
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file or at
-// https://opensource.org/licenses/MIT.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//! Simple recognizer combinators.
-
-// This version is similar to a similar one in the "lang" module of
-// xi-editor, but is stripped down to only the needed combinators.
-
-use std::ops;
-
-pub trait Recognize {
-    fn p(&self, s: &[u8]) -> Option<usize>;
-}
-
-impl<F: Fn(&[u8]) -> Option<usize>> Recognize for F {
-    #[inline(always)]
-    fn p(&self, s: &[u8]) -> Option<usize> {
-        self(s)
-    }
-}
-
-pub struct OneByte<F>(pub F);
-
-impl<F: Fn(u8) -> bool> Recognize for OneByte<F> {
-    #[inline(always)]
-    fn p(&self, s: &[u8]) -> Option<usize> {
-        if s.is_empty() || !self.0(s[0]) {
-            None
-        } else {
-            Some(1)
-        }
-    }
-}
-
-impl Recognize for u8 {
-    #[inline(always)]
-    fn p(&self, s: &[u8]) -> Option<usize> {
-        OneByte(|b| b == *self).p(s)
-    }
-}
-
-/// Use Inclusive(a..b) to indicate an inclusive range. When a...b syntax becomes
-/// stable, we can get rid of this and switch to that.
-pub struct Inclusive<T>(pub T);
-
-impl Recognize for Inclusive<ops::Range<u8>> {
-    #[inline(always)]
-    fn p(&self, s: &[u8]) -> Option<usize> {
-        OneByte(|x| x >= self.0.start && x <= self.0.end).p(s)
-    }
-}
-
-impl<'a> Recognize for &'a [u8] {
-    #[inline(always)]
-    fn p(&self, s: &[u8]) -> Option<usize> {
-        let len = self.len();
-        if s.len() >= len && &s[..len] == *self {
-            Some(len)
-        } else {
-            None
-        }
-    }
-}
-
-impl<'a> Recognize for &'a str {
-    #[inline(always)]
-    fn p(&self, s: &[u8]) -> Option<usize> {
-        self.as_bytes().p(s)
-    }
-}
-
-impl<P1: Recognize, P2: Recognize> Recognize for (P1, P2) {
-    #[inline(always)]
-    fn p(&self, s: &[u8]) -> Option<usize> {
-        self.0.p(s).and_then(|len1|
-            self.1.p(&s[len1..]).map(|len2|
-                len1 + len2))
-    }
-}
-
-/// Choice from two heterogeneous alternatives.
-pub struct Alt<P1, P2>(pub P1, pub P2);
-
-impl<P1: Recognize, P2: Recognize> Recognize for Alt<P1, P2> {
-    #[inline(always)]
-    fn p(&self, s: &[u8]) -> Option<usize> {
-        self.0.p(s).or_else(|| self.1.p(s))
-    }
-}
-
-/// Choice from a homogenous slice of parsers.
-pub struct OneOf<'a, P: 'a>(pub &'a [P]);
-
-impl<'a, P: Recognize> Recognize for OneOf<'a, P> {
-    #[inline]
-    fn p(&self, s: &[u8]) -> Option<usize> {
-        for ref p in self.0 {
-            if let Some(len) = p.p(s) {
-                return Some(len);
-            }
-        }
-        None
-    }
-}
-
-pub struct OneOrMore<P>(pub P);
-
-impl<P: Recognize> Recognize for OneOrMore<P> {
-    #[inline]
-    fn p(&self, s: &[u8]) -> Option<usize> {
-        let mut i = 0;
-        let mut count = 0;
-        while let Some(len) = self.0.p(&s[i..]) {
-            i += len;
-            count += 1;
-        }
-        if count >= 1 {
-            Some(i)
-        } else {
-            None
-        }
-    }
-}
-
-pub struct ZeroOrMore<P>(pub P);
-
-impl<P: Recognize> Recognize for ZeroOrMore<P> {
-    #[inline]
-    fn p(&self, s: &[u8]) -> Option<usize> {
-        let mut i = 0;
-        while let Some(len) = self.0.p(&s[i..]) {
-            i += len;
-        }
-        Some(i)
-    }
-}
diff --git a/vendor/semver-parser-0.7.0/src/version.rs b/vendor/semver-parser-0.7.0/src/version.rs
deleted file mode 100644 (file)
index 570f947..0000000
+++ /dev/null
@@ -1,365 +0,0 @@
-use std::fmt;
-use std::str::from_utf8;
-
-use recognize::*;
-
-use common::{self, numeric_identifier};
-
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct Version {
-    pub major: u64,
-    pub minor: u64,
-    pub patch: u64,
-    pub pre: Vec<Identifier>,
-    pub build: Vec<Identifier>,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum Identifier {
-    /// An identifier that's solely numbers.
-    Numeric(u64),
-    /// An identifier with letters and numbers.
-    AlphaNumeric(String),
-}
-
-pub fn parse(version: &str) -> Result<Version, String> {
-    let s = version.trim().as_bytes();
-    let mut i = 0;
-    let major = if let Some((major, len)) = numeric_identifier(&s[i..]) {
-        i += len;
-        major
-    } else {
-        return Err("Error parsing major identifier".to_string());
-    };
-    if let Some(len) = b'.'.p(&s[i..]) {
-        i += len;
-    } else {
-        return Err("Expected dot".to_string());
-    }
-    let minor = if let Some((minor, len)) = numeric_identifier(&s[i..]) {
-        i += len;
-        minor
-    } else {
-        return Err("Error parsing minor identifier".to_string());
-    };
-    if let Some(len) = b'.'.p(&s[i..]) {
-        i += len;
-    } else {
-        return Err("Expected dot".to_string());
-    }
-    let patch = if let Some((patch, len)) = numeric_identifier(&s[i..]) {
-        i += len;
-        patch
-    } else {
-        return Err("Error parsing patch identifier".to_string());
-    };
-    let (pre, pre_len) = common::parse_optional_meta(&s[i..], b'-')?;
-    i += pre_len;
-    let (build, build_len) = common::parse_optional_meta(&s[i..], b'+')?;
-    i += build_len;
-    if i != s.len() {
-        return Err("Extra junk after valid version: ".to_string() +
-            from_utf8(&s[i..]).unwrap());
-    }
-    Ok(Version {
-        major: major,
-        minor: minor,
-        patch: patch,
-        pre: pre,
-        build: build,
-    })
-}
-
-impl fmt::Display for Version {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "{}.{}.{}", self.major, self.minor, self.patch));
-        if !self.pre.is_empty() {
-            let strs: Vec<_> =
-                self.pre.iter().map(ToString::to_string).collect();
-            try!(write!(f, "-{}", strs.join(".")));
-        }
-        if !self.build.is_empty() {
-            let strs: Vec<_> =
-                self.build.iter().map(ToString::to_string).collect();
-            try!(write!(f, "+{}", strs.join(".")));
-        }
-        Ok(())
-    }
-}
-
-impl fmt::Display for Identifier {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Identifier::Numeric(ref id) => id.fmt(f),
-            Identifier::AlphaNumeric(ref id) => id.fmt(f),
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use version;
-    use super::*;
-
-    #[test]
-    fn parse_empty() {
-        let version = "";
-
-        let parsed = version::parse(version);
-
-        assert!(parsed.is_err(), "empty string incorrectly considered a valid parse");
-    }
-
-    #[test]
-    fn parse_blank() {
-        let version = "  ";
-
-        let parsed = version::parse(version);
-
-        assert!(parsed.is_err(), "blank string incorrectly considered a valid parse");
-    }
-
-    #[test]
-    fn parse_no_minor_patch() {
-        let version = "1";
-
-        let parsed = version::parse(version);
-
-        assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version));
-    }
-
-    #[test]
-    fn parse_no_patch() {
-        let version = "1.2";
-
-        let parsed = version::parse(version);
-
-        assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version));
-    }
-
-    #[test]
-    fn parse_empty_pre() {
-        let version = "1.2.3-";
-
-        let parsed = version::parse(version);
-
-        assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version));
-    }
-
-    #[test]
-    fn parse_letters() {
-        let version = "a.b.c";
-
-        let parsed = version::parse(version);
-
-        assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version));
-    }
-
-    #[test]
-    fn parse_with_letters() {
-        let version = "1.2.3 a.b.c";
-
-        let parsed = version::parse(version);
-
-        assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version));
-    }
-
-    #[test]
-    fn parse_basic_version() {
-        let version = "1.2.3";
-
-        let parsed = version::parse(version).unwrap();
-
-        assert_eq!(1, parsed.major);
-        assert_eq!(2, parsed.minor);
-        assert_eq!(3, parsed.patch);
-    }
-
-    #[test]
-    fn parse_trims_input() {
-        let version = "  1.2.3  ";
-
-        let parsed = version::parse(version).unwrap();
-
-        assert_eq!(1, parsed.major);
-        assert_eq!(2, parsed.minor);
-        assert_eq!(3, parsed.patch);
-    }
-
-    #[test]
-    fn parse_no_major_leading_zeroes() {
-        let version = "01.0.0";
-
-        let parsed = version::parse(version);
-
-        assert!(parsed.is_err(), "01 incorrectly considered a valid major version");
-    }
-
-    #[test]
-    fn parse_no_minor_leading_zeroes() {
-        let version = "0.01.0";
-
-        let parsed = version::parse(version);
-
-        assert!(parsed.is_err(), "01 incorrectly considered a valid minor version");
-    }
-
-    #[test]
-    fn parse_no_patch_leading_zeroes() {
-        let version = "0.0.01";
-
-        let parsed = version::parse(version);
-
-        assert!(parsed.is_err(), "01 incorrectly considered a valid patch version");
-    }
-
-    #[test]
-    fn parse_no_major_overflow() {
-        let version = "98765432109876543210.0.0";
-
-        let parsed = version::parse(version);
-
-        assert!(parsed.is_err(), "98765432109876543210 incorrectly considered a valid major version");
-    }
-
-    #[test]
-    fn parse_no_minor_overflow() {
-        let version = "0.98765432109876543210.0";
-
-        let parsed = version::parse(version);
-
-        assert!(parsed.is_err(), "98765432109876543210 incorrectly considered a valid minor version");
-    }
-
-    #[test]
-    fn parse_no_patch_overflow() {
-        let version = "0.0.98765432109876543210";
-
-        let parsed = version::parse(version);
-
-        assert!(parsed.is_err(), "98765432109876543210 incorrectly considered a valid patch version");
-    }
-
-    #[test]
-    fn parse_basic_prerelease() {
-        let version = "1.2.3-pre";
-
-        let parsed = version::parse(version).unwrap();
-
-        let expected_pre = vec![Identifier::AlphaNumeric(String::from("pre"))];
-        assert_eq!(expected_pre, parsed.pre);
-    }
-
-    #[test]
-    fn parse_prerelease_alphanumeric() {
-        let version = "1.2.3-alpha1";
-
-        let parsed = version::parse(version).unwrap();
-
-        let expected_pre = vec![Identifier::AlphaNumeric(String::from("alpha1"))];
-        assert_eq!(expected_pre, parsed.pre);
-    }
-
-    #[test]
-    fn parse_prerelease_zero() {
-        let version = "1.2.3-pre.0";
-
-        let parsed = version::parse(version).unwrap();
-
-        let expected_pre = vec![Identifier::AlphaNumeric(String::from("pre")),
-                                Identifier::Numeric(0)];
-        assert_eq!(expected_pre, parsed.pre);
-    }
-
-    #[test]
-    fn parse_basic_build() {
-        let version = "1.2.3+build";
-
-        let parsed = version::parse(version).unwrap();
-
-        let expected_build = vec![Identifier::AlphaNumeric(String::from("build"))];
-        assert_eq!(expected_build, parsed.build);
-    }
-
-    #[test]
-    fn parse_build_alphanumeric() {
-        let version = "1.2.3+build5";
-
-        let parsed = version::parse(version).unwrap();
-
-        let expected_build = vec![Identifier::AlphaNumeric(String::from("build5"))];
-        assert_eq!(expected_build, parsed.build);
-    }
-
-    #[test]
-    fn parse_pre_and_build() {
-        let version = "1.2.3-alpha1+build5";
-
-        let parsed = version::parse(version).unwrap();
-
-        let expected_pre = vec![Identifier::AlphaNumeric(String::from("alpha1"))];
-        assert_eq!(expected_pre, parsed.pre);
-
-        let expected_build = vec![Identifier::AlphaNumeric(String::from("build5"))];
-        assert_eq!(expected_build, parsed.build);
-    }
-
-    #[test]
-    fn parse_complex_metadata_01() {
-        let version = "1.2.3-1.alpha1.9+build5.7.3aedf  ";
-
-        let parsed = version::parse(version).unwrap();
-
-        let expected_pre = vec![Identifier::Numeric(1),
-                                Identifier::AlphaNumeric(String::from("alpha1")),
-                                Identifier::Numeric(9)];
-        assert_eq!(expected_pre, parsed.pre);
-
-        let expected_build = vec![Identifier::AlphaNumeric(String::from("build5")),
-                                  Identifier::Numeric(7),
-                                  Identifier::AlphaNumeric(String::from("3aedf"))];
-        assert_eq!(expected_build, parsed.build);
-    }
-
-    #[test]
-    fn parse_complex_metadata_02() {
-        let version = "0.4.0-beta.1+0851523";
-
-        let parsed = version::parse(version).unwrap();
-
-        let expected_pre = vec![Identifier::AlphaNumeric(String::from("beta")),
-                                Identifier::Numeric(1)];
-        assert_eq!(expected_pre, parsed.pre);
-
-        let expected_build = vec![Identifier::AlphaNumeric(String::from("0851523"))];
-        assert_eq!(expected_build, parsed.build);
-    }
-
-    #[test]
-    fn parse_metadata_overflow() {
-        let version = "0.4.0-beta.1+98765432109876543210";
-
-        let parsed = version::parse(version).unwrap();
-
-        let expected_pre = vec![Identifier::AlphaNumeric(String::from("beta")),
-                                Identifier::Numeric(1)];
-        assert_eq!(expected_pre, parsed.pre);
-
-        let expected_build = vec![Identifier::AlphaNumeric(String::from("98765432109876543210"))];
-        assert_eq!(expected_build, parsed.build);
-    }
-
-    #[test]
-    fn parse_regression_01() {
-        let version = "0.0.0-WIP";
-
-        let parsed = version::parse(version).unwrap();
-
-        assert_eq!(0, parsed.major);
-        assert_eq!(0, parsed.minor);
-        assert_eq!(0, parsed.patch);
-
-        let expected_pre = vec![Identifier::AlphaNumeric(String::from("WIP"))];
-        assert_eq!(expected_pre, parsed.pre);
-    }
-}
index 90c4bca07e3c1e714b66c47e30fe9546752bfcdd..71fdf594e94fdf7c5232bd3ccfc899edf5038265 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.toml":"96f4717615430a917b8e8f6fbf22876228179dfba36830c0c69abfcc1d10a0d0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"417bb33dc685fb0036f91229dd0d828b104a4c35010d362f2a6e5d8b4cf1e36d","benches/file.rs":"b4724fc7c0f48b8f488e2632a1064f6c0bf16ded3969680fc3f4a2369536269b","benches/rust.rs":"ea6291ef2d2a83d94a3312fe179d48259f8ec0b04c961993ddd181d0a4ab740e","build.rs":"241f9e3af93b32d2d928ef9251d8ed2e67c6c64acc4aacce81f3aca58778e655","src/attr.rs":"b0eeacb3e55df4f9d66782d87fc8a13e58d358f95ac886e557a670720ceec519","src/await.rs":"8aa22e3c201cb2bdb6b4817fa00901f308ab06817607aa7b884c58c957705969","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"a5d6692938c2ec6ec140f70ec89fa93659fa227b52e8d381e9da7dd440f0249e","src/custom_keyword.rs":"a834c617b4a0aa87c21275ded72a4e04d7fac2d2255cfc037c0690d21488fc31","src/custom_punctuation.rs":"8a666298e774b0d326642f0f73284f6677d0d0a7c9e4a712c9c98d010b4d8a2c","src/data.rs":"5f333d1fa03be07a80a8f9975f794be0d4c56a5a0a59249c7993a9b92b9819e1","src/derive.rs":"d4205fb2b699e784c0889bcde7e80b77ab222ee74ec3c349b5b1fa63a5f3b0b0","src/discouraged.rs":"a1f3d85e20dedf50b1b7b4571d970a3a6e9b2de4afde7dd0c986fe240df2ba46","src/error.rs":"72dae49d360326a1d1079a3a6dc4b22f8a304f84e0b90d70b73a02dfdc9f49da","src/export.rs":"d18438464c7ee1de7092c7c5d48dd9d114bdf184c1ea452c4fa709265cd19469","src/expr.rs":"66caed7b925dac873df8d457a9a71363638ca1b5278180936f409e1fc42b83a7","src/ext.rs":"1f648cff1d705a1cea64b32b77482b97a82d2fe0aaf63b40cade91e5c02dc969","src/file.rs":"f86697655222ae294215114f4eae8e6b0b5e2a935d6c479ff8f8f889c4efd2e2","src/gen/clone.rs":"8db60fc2bf515f9a65f4e98669427ce02ed0ccc9ffdad25d8fb39b38768ecaf1","src/gen/debug.rs":"facf4fb5c7e017dd890c4a9531f337659d7b55475aa44124abf48e088ad56fc5","src/gen/eq.rs":"576a4f1e4030434b0f0170f4d681d2c46292fda64ad5f3913623e1c6e858c24f","src/gen/fold.rs":"3f59e59ed8ad2ab5dd347bfbe41bbc785c2aabd8ae902087a584a6daed597182","src/gen/hash.rs":"458052bb0d64b2a722eaeef4461af80bce109cd97d19bd44dbd608e4c53a6520","src/gen/visit.rs":"23008c170d4dd3975232876a0a654921d9b6af57372cb9fcc133ca740588d666","src/gen/visit_mut.rs":"42886c3ee02ded72d9c3eec006e20431eaee0c6b90ddefc1a36ec7bf50c6a24a","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"c8272a8010b378c09eac33e9904299797aee3a879832e6a37a580b518f2a641a","src/group.rs":"d9cd30ea5bd4d453293e8e8debbe388a0360c3c766f67c8499fec453a9a43cdc","src/ident.rs":"d67975d3dd89becde96579c0454a1357aa7c62da11bdf94f29ccf63514ffbc9d","src/item.rs":"b42e2ea6d24dfc4bacc1325f3f59044abd9441a8e70bf22a1f47eae34a7ed68a","src/lib.rs":"c17a33348995ecbb171f4121d202a3c9b4299105ddbf242cac08433eb484a22a","src/lifetime.rs":"bd206f4471091498a8ac270c5f99d7d4b10eb614f452cd3ee614cab9e1b2f5e3","src/lit.rs":"b3cfe9d5a15e07f99d44270a84f4ad7a991d7c701244da1828dcaf7ddc97771d","src/lookahead.rs":"92ee63b48de02d3f6f1b09121f0fbac41d55cebc5771c8320e27df8482906152","src/mac.rs":"004cb89f9697564f6c9ee837e08ead68463ef946fb4c13c6c105adf2ba364b2b","src/macros.rs":"266590fd63a4a9d8637c6f8d36702acaace4ba59ab74c0883859efd1e260bae5","src/op.rs":"9d499022902743a6a0a19223b356449a979b90e60552d0446497d72750e646a4","src/parse.rs":"8b4aa518660dfd6310a5455b5624de01ad7ba42d11527b217f811b687b26e1fc","src/parse_macro_input.rs":"88929a1a7e5e72aa2d0b3459e52d8975afea856d159047ba4ab02ecbc5878a9c","src/parse_quote.rs":"80db945403d9731c5f3299a5819a5e2bb726c19fd9f256d50240bc32703c96b1","src/pat.rs":"397b02e0a6f6af8e87c2b3d70cc5b65f5428f9154f09b1006a51b31aaea65038","src/path.rs":"6e890d2d1ceb3d70ede5825d1d74eb98f8c716f444c7eb6ef5026dd610baa202","src/print.rs":"da6529c1d9d21aaf6c835f66b4e67eacb7cf91a10eb5e9a2143b49bf99b3b5e1","src/punctuated.rs":"ac2b0bd8ffa6ce6d07ed6e0af7384a1120db7a0918406da89a45e929feac49ba","src/reserved.rs":"e70e028bd55cfa43e23cab4ba29e4dc53a3d91eff685ef2b6e57efc2b87a3428","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"3ca016a943637653ab98e373dfb826a120f3c159867346fa38a844439944eb39","src/stmt.rs":"e68f76530606aab24e3587aa697fcd862c176e1cca0a50ab883c76bb91464f3d","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"5e423a696f80e281c322f37c87577f9fdc28607e9c007e24896a2b12da62d5ad","src/tt.rs":"32402645b6e82ef1e882945721b59b5fb7b0ee337d1972876362ecacef643d0f","src/ty.rs":"2027a2f1600c5cfdeba51d0a1ae6b035e82c0e8c19b7fb2ed121cbfc8e99e52a","src/verbatim.rs":"802a97df997432f18cac6e6200ff6ea29fb2474986005e0fcdbc2b65197f87f7","src/whitespace.rs":"e63dd0aa3d34029f17766a8b09c1a6e4479e36c552c8b7023d710a399333aace","tests/.gitignore":"22e782449a3c216db3f7215d5fb8882e316768e40beeec3833aae419ad8941db","tests/common/eq.rs":"df7b7538a95bee12d7f4a812371bbe88972e743a465b314516e61a8c6d84ae4b","tests/common/mod.rs":"25ef6d7daa09bad3198a0e9e91b2812425f92db7c585c1e34a03a84d7362ccd8","tests/common/parse.rs":"81580f23583723f7a2a337c4d13ebc021057cd825562fb4e474caa7cc641fed9","tests/debug/gen.rs":"e30e2b6c61feb15abe11cee86c4edff9f7e7c9c79080447d44be97869c9a3adb","tests/debug/mod.rs":"868763d0ef1609a3ad5e05e9f1bfa0f813e91e7e9a36653414a188bb2fdaa425","tests/macros/mod.rs":"a93136b172377ffebe8b68fd596a86d6625f64ed6c3d5e7f5d6ad859e25d5623","tests/repo/mod.rs":"3978e2a9ee2eafe28d6b2383cb84b0ee3f7686ac9ee248b8e6946faa7b5db27a","tests/repo/progress.rs":"c08d0314a7f3ecf760d471f27da3cd2a500aeb9f1c8331bffb2aa648f9fabf3f","tests/test_asyncness.rs":"cff01db49d28ab23b0b258bc6c0a5cc4071be4fe7248eef344a5d79d2fb649b7","tests/test_attribute.rs":"0ffd99384e1a52ae17d9fed5c4053e411e8f9018decef07ffa621d1faa7329d8","tests/test_derive_input.rs":"610444351e3bf99366976bbf1da109c334a70ac9500caef366bcf9b68819829f","tests/test_expr.rs":"e68b5827415471ccfb7efd91bbfba2f025f1cb8f993c417e7b3c0c3bec6a1fa6","tests/test_generics.rs":"9d713f90a79d6145efc89fb6f946029ca03486c632219950889da39940152ba0","tests/test_grouping.rs":"6276c3c73bba649dec5c97904ad2492879f918bc887a2c425d095c654ca0d925","tests/test_ident.rs":"9eb53d1e21edf23e7c9e14dc74dcc2b2538e9221e19dbcc0a44e3acc2e90f3f6","tests/test_item.rs":"2a8ba326963d758b5a3395bfa07375844f8e043885bb752b69be84a2fe6b4e17","tests/test_iterators.rs":"53ed6078d37550bd6765d2411e3660be401aef8a31a407350cc064a7d08c7c33","tests/test_lit.rs":"ef3f39da6ed67ba73b05eab3dda299887a455bac8e97701a90a94b636681588f","tests/test_meta.rs":"bd6910ec0eba05e814dad27dda0ea65e1f8b483e64d943213066ffd114a82b45","tests/test_parse_buffer.rs":"8bbe2d24ca8a3788f72c6908fc96c26d546f11c69687bf8d72727f851d5e2d27","tests/test_parse_stream.rs":"2f449a2c41a3dee6fd14bee24e1666a453cb808eda17332fd91afd127fcdd2a6","tests/test_pat.rs":"d4465f4fc3fd5d6e534ba8efabe1e0ed6da89de4ac7c96effa6bfb880c4287cf","tests/test_path.rs":"13ae78e958f0d7334d11f32519f593968e5503d46e29ec345feede025f16113d","tests/test_precedence.rs":"cd979febe0b00efcc6baf397a7ff573b03c849c1dd92a282ae9af6627acf6760","tests/test_receiver.rs":"084eca59984b9a18651da52f2c4407355da3de1335916a12477652999e2d01cc","tests/test_round_trip.rs":"e5a9e8c546f43fba741028716f1f34596822accdbc52d0eccb92f98d98bad804","tests/test_shebang.rs":"f5772cadad5b56e3112cb16308b779f92bce1c3a48091fc9933deb2276a69331","tests/test_should_parse.rs":"1d3535698a446e2755bfc360676bdb161841a1f454cdef6e7556c6d06a95c89d","tests/test_size.rs":"5fae772bab66809d6708232f35cfb4a287882486763b0f763feec2ad79fbb68b","tests/test_stmt.rs":"ff6f6f447f46a52fb544353b7dcd2cd9e60781b297dcc86551bee613beaf2280","tests/test_token_trees.rs":"43e56a701817e3c3bfd0cae54a457dd7a38ccb3ca19da41e2b995fdf20e6ed18","tests/test_ty.rs":"01d33c67a72d0e030736b1be22cea916fde14681ee0253b8183905bccfcc5798","tests/test_visibility.rs":"7456fcb3a6634db509748aededff9c2d8b242d511a3e5ee3022e40b232892704","tests/zzz_stable.rs":"2a862e59cb446235ed99aec0e6ada8e16d3ecc30229b29d825b7c0bbc2602989"},"package":"a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"}
\ No newline at end of file
+{"files":{"Cargo.toml":"922256feb4d35aeabcbee9534f7257bb14f033af8dda3f19f77fba0703ba3586","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"417bb33dc685fb0036f91229dd0d828b104a4c35010d362f2a6e5d8b4cf1e36d","benches/file.rs":"b4724fc7c0f48b8f488e2632a1064f6c0bf16ded3969680fc3f4a2369536269b","benches/rust.rs":"ea6291ef2d2a83d94a3312fe179d48259f8ec0b04c961993ddd181d0a4ab740e","build.rs":"241f9e3af93b32d2d928ef9251d8ed2e67c6c64acc4aacce81f3aca58778e655","src/attr.rs":"bab811535308771df407b36c9c9d442c413cfc40cce557e7505c85a2875bf41d","src/await.rs":"8aa22e3c201cb2bdb6b4817fa00901f308ab06817607aa7b884c58c957705969","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"a5d6692938c2ec6ec140f70ec89fa93659fa227b52e8d381e9da7dd440f0249e","src/custom_keyword.rs":"a834c617b4a0aa87c21275ded72a4e04d7fac2d2255cfc037c0690d21488fc31","src/custom_punctuation.rs":"8a666298e774b0d326642f0f73284f6677d0d0a7c9e4a712c9c98d010b4d8a2c","src/data.rs":"6774795445345360208e2ddc932acd33bbf96e9ac8407e1e4d7e45d44f174ebf","src/derive.rs":"d4205fb2b699e784c0889bcde7e80b77ab222ee74ec3c349b5b1fa63a5f3b0b0","src/discouraged.rs":"6c6a9298f8d24f578da119557bc588f3bd928f7b79fca27d6bdfe3e786dd005f","src/error.rs":"30ed3ab35ba852ac2cfc1f5f388845bf0d0576aa485f045c7da3af0fb24b9f84","src/export.rs":"d18438464c7ee1de7092c7c5d48dd9d114bdf184c1ea452c4fa709265cd19469","src/expr.rs":"29ab61a3ef4f50b7ae5b6c7efe16d3a5ad4bc45b3ff18f8a67f20c1953cd6901","src/ext.rs":"1f648cff1d705a1cea64b32b77482b97a82d2fe0aaf63b40cade91e5c02dc969","src/file.rs":"f86697655222ae294215114f4eae8e6b0b5e2a935d6c479ff8f8f889c4efd2e2","src/gen/clone.rs":"8db60fc2bf515f9a65f4e98669427ce02ed0ccc9ffdad25d8fb39b38768ecaf1","src/gen/debug.rs":"facf4fb5c7e017dd890c4a9531f337659d7b55475aa44124abf48e088ad56fc5","src/gen/eq.rs":"576a4f1e4030434b0f0170f4d681d2c46292fda64ad5f3913623e1c6e858c24f","src/gen/fold.rs":"3f59e59ed8ad2ab5dd347bfbe41bbc785c2aabd8ae902087a584a6daed597182","src/gen/hash.rs":"458052bb0d64b2a722eaeef4461af80bce109cd97d19bd44dbd608e4c53a6520","src/gen/visit.rs":"94f2c6bed4ef1cd0e83d91dddaa95730619fa48fdd4a0be2fd8740e730ff744d","src/gen/visit_mut.rs":"abc8cb67ad3300d0667761daf1e057b80b4d3f3980d94e8d6f3ed68bdcda3776","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"c8272a8010b378c09eac33e9904299797aee3a879832e6a37a580b518f2a641a","src/group.rs":"d9cd30ea5bd4d453293e8e8debbe388a0360c3c766f67c8499fec453a9a43cdc","src/ident.rs":"d67975d3dd89becde96579c0454a1357aa7c62da11bdf94f29ccf63514ffbc9d","src/item.rs":"ed58a8a5c1aaea823394c394fe18e77e7a039f718260e6a5028e3d88c4c213c1","src/lib.rs":"cf194a4e9d78ee5773036714f7aa546fd8a65cf86226d8f03ac819107ca31451","src/lifetime.rs":"b18862ef1e690037a4f308ea897debad7bc5038584e3b26c6d8809752ea0e3c2","src/lit.rs":"1cf2700ff9b992bfbe660654abb2af4c816765f901451a359ce450c3dd5f2651","src/lookahead.rs":"92ee63b48de02d3f6f1b09121f0fbac41d55cebc5771c8320e27df8482906152","src/mac.rs":"004cb89f9697564f6c9ee837e08ead68463ef946fb4c13c6c105adf2ba364b2b","src/macros.rs":"266590fd63a4a9d8637c6f8d36702acaace4ba59ab74c0883859efd1e260bae5","src/op.rs":"9d499022902743a6a0a19223b356449a979b90e60552d0446497d72750e646a4","src/parse.rs":"8b4aa518660dfd6310a5455b5624de01ad7ba42d11527b217f811b687b26e1fc","src/parse_macro_input.rs":"88929a1a7e5e72aa2d0b3459e52d8975afea856d159047ba4ab02ecbc5878a9c","src/parse_quote.rs":"80db945403d9731c5f3299a5819a5e2bb726c19fd9f256d50240bc32703c96b1","src/pat.rs":"397b02e0a6f6af8e87c2b3d70cc5b65f5428f9154f09b1006a51b31aaea65038","src/path.rs":"6e890d2d1ceb3d70ede5825d1d74eb98f8c716f444c7eb6ef5026dd610baa202","src/print.rs":"da6529c1d9d21aaf6c835f66b4e67eacb7cf91a10eb5e9a2143b49bf99b3b5e1","src/punctuated.rs":"f389f99adafde96e6d9cc5a00fe95acbaf1ea556191dde2cce98bbd8155aed23","src/reserved.rs":"e70e028bd55cfa43e23cab4ba29e4dc53a3d91eff685ef2b6e57efc2b87a3428","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"3ca016a943637653ab98e373dfb826a120f3c159867346fa38a844439944eb39","src/stmt.rs":"e68f76530606aab24e3587aa697fcd862c176e1cca0a50ab883c76bb91464f3d","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"5e423a696f80e281c322f37c87577f9fdc28607e9c007e24896a2b12da62d5ad","src/tt.rs":"32402645b6e82ef1e882945721b59b5fb7b0ee337d1972876362ecacef643d0f","src/ty.rs":"2027a2f1600c5cfdeba51d0a1ae6b035e82c0e8c19b7fb2ed121cbfc8e99e52a","src/verbatim.rs":"802a97df997432f18cac6e6200ff6ea29fb2474986005e0fcdbc2b65197f87f7","src/whitespace.rs":"e63dd0aa3d34029f17766a8b09c1a6e4479e36c552c8b7023d710a399333aace","tests/.gitignore":"22e782449a3c216db3f7215d5fb8882e316768e40beeec3833aae419ad8941db","tests/common/eq.rs":"524398ca8f867376c40b1f8c7a5a525e631bb5c858fe589e37447df22e7d76b5","tests/common/mod.rs":"25ef6d7daa09bad3198a0e9e91b2812425f92db7c585c1e34a03a84d7362ccd8","tests/common/parse.rs":"81580f23583723f7a2a337c4d13ebc021057cd825562fb4e474caa7cc641fed9","tests/debug/gen.rs":"e30e2b6c61feb15abe11cee86c4edff9f7e7c9c79080447d44be97869c9a3adb","tests/debug/mod.rs":"868763d0ef1609a3ad5e05e9f1bfa0f813e91e7e9a36653414a188bb2fdaa425","tests/macros/mod.rs":"a93136b172377ffebe8b68fd596a86d6625f64ed6c3d5e7f5d6ad859e25d5623","tests/repo/mod.rs":"3978e2a9ee2eafe28d6b2383cb84b0ee3f7686ac9ee248b8e6946faa7b5db27a","tests/repo/progress.rs":"c08d0314a7f3ecf760d471f27da3cd2a500aeb9f1c8331bffb2aa648f9fabf3f","tests/test_asyncness.rs":"cff01db49d28ab23b0b258bc6c0a5cc4071be4fe7248eef344a5d79d2fb649b7","tests/test_attribute.rs":"0ffd99384e1a52ae17d9fed5c4053e411e8f9018decef07ffa621d1faa7329d8","tests/test_derive_input.rs":"610444351e3bf99366976bbf1da109c334a70ac9500caef366bcf9b68819829f","tests/test_expr.rs":"e68b5827415471ccfb7efd91bbfba2f025f1cb8f993c417e7b3c0c3bec6a1fa6","tests/test_generics.rs":"9d713f90a79d6145efc89fb6f946029ca03486c632219950889da39940152ba0","tests/test_grouping.rs":"6276c3c73bba649dec5c97904ad2492879f918bc887a2c425d095c654ca0d925","tests/test_ident.rs":"9eb53d1e21edf23e7c9e14dc74dcc2b2538e9221e19dbcc0a44e3acc2e90f3f6","tests/test_item.rs":"2a8ba326963d758b5a3395bfa07375844f8e043885bb752b69be84a2fe6b4e17","tests/test_iterators.rs":"53ed6078d37550bd6765d2411e3660be401aef8a31a407350cc064a7d08c7c33","tests/test_lit.rs":"ef3f39da6ed67ba73b05eab3dda299887a455bac8e97701a90a94b636681588f","tests/test_meta.rs":"bd6910ec0eba05e814dad27dda0ea65e1f8b483e64d943213066ffd114a82b45","tests/test_parse_buffer.rs":"8bbe2d24ca8a3788f72c6908fc96c26d546f11c69687bf8d72727f851d5e2d27","tests/test_parse_stream.rs":"2f449a2c41a3dee6fd14bee24e1666a453cb808eda17332fd91afd127fcdd2a6","tests/test_pat.rs":"d4465f4fc3fd5d6e534ba8efabe1e0ed6da89de4ac7c96effa6bfb880c4287cf","tests/test_path.rs":"13ae78e958f0d7334d11f32519f593968e5503d46e29ec345feede025f16113d","tests/test_precedence.rs":"cd979febe0b00efcc6baf397a7ff573b03c849c1dd92a282ae9af6627acf6760","tests/test_receiver.rs":"084eca59984b9a18651da52f2c4407355da3de1335916a12477652999e2d01cc","tests/test_round_trip.rs":"e5a9e8c546f43fba741028716f1f34596822accdbc52d0eccb92f98d98bad804","tests/test_shebang.rs":"f5772cadad5b56e3112cb16308b779f92bce1c3a48091fc9933deb2276a69331","tests/test_should_parse.rs":"1d3535698a446e2755bfc360676bdb161841a1f454cdef6e7556c6d06a95c89d","tests/test_size.rs":"5fae772bab66809d6708232f35cfb4a287882486763b0f763feec2ad79fbb68b","tests/test_stmt.rs":"ff6f6f447f46a52fb544353b7dcd2cd9e60781b297dcc86551bee613beaf2280","tests/test_token_trees.rs":"43e56a701817e3c3bfd0cae54a457dd7a38ccb3ca19da41e2b995fdf20e6ed18","tests/test_ty.rs":"01d33c67a72d0e030736b1be22cea916fde14681ee0253b8183905bccfcc5798","tests/test_visibility.rs":"7456fcb3a6634db509748aededff9c2d8b242d511a3e5ee3022e40b232892704","tests/zzz_stable.rs":"2a862e59cb446235ed99aec0e6ada8e16d3ecc30229b29d825b7c0bbc2602989"},"package":"f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"}
\ No newline at end of file
index dabb66dfbb92b69cca5eb5bd24c30c2ad7d258fa..c5c347f77e71e105ada6918311432f0180561001 100644 (file)
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "syn"
-version = "1.0.72"
+version = "1.0.73"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 include = ["/benches/**", "/build.rs", "/Cargo.toml", "/LICENSE-APACHE", "/LICENSE-MIT", "/README.md", "/src/**", "/tests/**"]
 description = "Parser for Rust source code"
index 505ffeb7a2c5a3af26ca7356078034d815daeb96..5d6877aea765877f23b0d1b5c26e6383bd67366c 100644 (file)
@@ -649,7 +649,7 @@ mod printing {
             self.path.to_tokens(tokens);
             self.paren_token.surround(tokens, |tokens| {
                 self.nested.to_tokens(tokens);
-            })
+            });
         }
     }
 
index b0258ca0684b09715ed9606c1841c7f5e2a1e0f0..837224e154a41a6e1204c49cf2e8deb8900f0dcb 100644 (file)
@@ -475,7 +475,7 @@ mod printing {
     #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
     impl ToTokens for VisPublic {
         fn to_tokens(&self, tokens: &mut TokenStream) {
-            self.pub_token.to_tokens(tokens)
+            self.pub_token.to_tokens(tokens);
         }
     }
 
index 76c9fce6f8ac0422fc0bc3c3378daa400d06219f..a46129b6a159b56b53d21b93368cd53016cd98d3 100644 (file)
@@ -189,6 +189,6 @@ impl<'a> Speculative for ParseBuffer<'a> {
 
         // See comment on `cell` in the struct definition.
         self.cell
-            .set(unsafe { mem::transmute::<Cursor, Cursor<'static>>(fork.cursor()) })
+            .set(unsafe { mem::transmute::<Cursor, Cursor<'static>>(fork.cursor()) });
     }
 }
index 780731c86c246da411226fc96d14d4d786d9c991..e2f2382182a799bf8d53e01d11b3825e0a567b0b 100644 (file)
@@ -236,7 +236,7 @@ impl Error {
     /// Add another error message to self such that when `to_compile_error()` is
     /// called, both errors will be emitted together.
     pub fn combine(&mut self, another: Error) {
-        self.messages.extend(another.messages)
+        self.messages.extend(another.messages);
     }
 }
 
index ef629ecdb50900c7cedf267541e7d3e73a4ea0eb..24f79117e19a0220e1a2bca948972b9d91cd7e0b 100644 (file)
@@ -851,6 +851,24 @@ ast_enum! {
     }
 }
 
+impl From<Ident> for Member {
+    fn from(ident: Ident) -> Member {
+        Member::Named(ident)
+    }
+}
+
+impl From<Index> for Member {
+    fn from(index: Index) -> Member {
+        Member::Unnamed(index)
+    }
+}
+
+impl From<usize> for Member {
+    fn from(index: usize) -> Member {
+        Member::Unnamed(Index::from(index))
+    }
+}
+
 impl Eq for Member {}
 
 impl PartialEq for Member {
@@ -2926,7 +2944,7 @@ pub(crate) mod printing {
             self.bracket_token.surround(tokens, |tokens| {
                 inner_attrs_to_tokens(&self.attrs, tokens);
                 self.elems.to_tokens(tokens);
-            })
+            });
         }
     }
 
@@ -2937,7 +2955,7 @@ pub(crate) mod printing {
             self.func.to_tokens(tokens);
             self.paren_token.surround(tokens, |tokens| {
                 self.args.to_tokens(tokens);
-            })
+            });
         }
     }
 
@@ -2991,7 +3009,7 @@ pub(crate) mod printing {
                 if self.elems.len() == 1 && !self.elems.trailing_punct() {
                     <Token![,]>::default().to_tokens(tokens);
                 }
-            })
+            });
         }
     }
 
@@ -3389,7 +3407,7 @@ pub(crate) mod printing {
                     Token![..](Span::call_site()).to_tokens(tokens);
                 }
                 self.rest.to_tokens(tokens);
-            })
+            });
         }
     }
 
@@ -3403,7 +3421,7 @@ pub(crate) mod printing {
                 self.expr.to_tokens(tokens);
                 self.semi_token.to_tokens(tokens);
                 self.len.to_tokens(tokens);
-            })
+            });
         }
     }
 
index 24d34b74804803c6bb2287eac8b8efe546ff6f54..6eaee24c0ea48967292b74801a4e99f4758a78c4 100644 (file)
@@ -33,740 +33,740 @@ macro_rules! skip {
 pub trait Visit<'ast> {
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_abi(&mut self, i: &'ast Abi) {
-        visit_abi(self, i)
+        visit_abi(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_angle_bracketed_generic_arguments(&mut self, i: &'ast AngleBracketedGenericArguments) {
-        visit_angle_bracketed_generic_arguments(self, i)
+        visit_angle_bracketed_generic_arguments(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_arm(&mut self, i: &'ast Arm) {
-        visit_arm(self, i)
+        visit_arm(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_attr_style(&mut self, i: &'ast AttrStyle) {
-        visit_attr_style(self, i)
+        visit_attr_style(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_attribute(&mut self, i: &'ast Attribute) {
-        visit_attribute(self, i)
+        visit_attribute(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_bare_fn_arg(&mut self, i: &'ast BareFnArg) {
-        visit_bare_fn_arg(self, i)
+        visit_bare_fn_arg(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_bin_op(&mut self, i: &'ast BinOp) {
-        visit_bin_op(self, i)
+        visit_bin_op(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_binding(&mut self, i: &'ast Binding) {
-        visit_binding(self, i)
+        visit_binding(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_block(&mut self, i: &'ast Block) {
-        visit_block(self, i)
+        visit_block(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_bound_lifetimes(&mut self, i: &'ast BoundLifetimes) {
-        visit_bound_lifetimes(self, i)
+        visit_bound_lifetimes(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_const_param(&mut self, i: &'ast ConstParam) {
-        visit_const_param(self, i)
+        visit_const_param(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_constraint(&mut self, i: &'ast Constraint) {
-        visit_constraint(self, i)
+        visit_constraint(self, i);
     }
     #[cfg(feature = "derive")]
     fn visit_data(&mut self, i: &'ast Data) {
-        visit_data(self, i)
+        visit_data(self, i);
     }
     #[cfg(feature = "derive")]
     fn visit_data_enum(&mut self, i: &'ast DataEnum) {
-        visit_data_enum(self, i)
+        visit_data_enum(self, i);
     }
     #[cfg(feature = "derive")]
     fn visit_data_struct(&mut self, i: &'ast DataStruct) {
-        visit_data_struct(self, i)
+        visit_data_struct(self, i);
     }
     #[cfg(feature = "derive")]
     fn visit_data_union(&mut self, i: &'ast DataUnion) {
-        visit_data_union(self, i)
+        visit_data_union(self, i);
     }
     #[cfg(feature = "derive")]
     fn visit_derive_input(&mut self, i: &'ast DeriveInput) {
-        visit_derive_input(self, i)
+        visit_derive_input(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr(&mut self, i: &'ast Expr) {
-        visit_expr(self, i)
+        visit_expr(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_array(&mut self, i: &'ast ExprArray) {
-        visit_expr_array(self, i)
+        visit_expr_array(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_assign(&mut self, i: &'ast ExprAssign) {
-        visit_expr_assign(self, i)
+        visit_expr_assign(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_assign_op(&mut self, i: &'ast ExprAssignOp) {
-        visit_expr_assign_op(self, i)
+        visit_expr_assign_op(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_async(&mut self, i: &'ast ExprAsync) {
-        visit_expr_async(self, i)
+        visit_expr_async(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_await(&mut self, i: &'ast ExprAwait) {
-        visit_expr_await(self, i)
+        visit_expr_await(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_binary(&mut self, i: &'ast ExprBinary) {
-        visit_expr_binary(self, i)
+        visit_expr_binary(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_block(&mut self, i: &'ast ExprBlock) {
-        visit_expr_block(self, i)
+        visit_expr_block(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_box(&mut self, i: &'ast ExprBox) {
-        visit_expr_box(self, i)
+        visit_expr_box(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_break(&mut self, i: &'ast ExprBreak) {
-        visit_expr_break(self, i)
+        visit_expr_break(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_call(&mut self, i: &'ast ExprCall) {
-        visit_expr_call(self, i)
+        visit_expr_call(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_cast(&mut self, i: &'ast ExprCast) {
-        visit_expr_cast(self, i)
+        visit_expr_cast(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_closure(&mut self, i: &'ast ExprClosure) {
-        visit_expr_closure(self, i)
+        visit_expr_closure(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_continue(&mut self, i: &'ast ExprContinue) {
-        visit_expr_continue(self, i)
+        visit_expr_continue(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_field(&mut self, i: &'ast ExprField) {
-        visit_expr_field(self, i)
+        visit_expr_field(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_for_loop(&mut self, i: &'ast ExprForLoop) {
-        visit_expr_for_loop(self, i)
+        visit_expr_for_loop(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_group(&mut self, i: &'ast ExprGroup) {
-        visit_expr_group(self, i)
+        visit_expr_group(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_if(&mut self, i: &'ast ExprIf) {
-        visit_expr_if(self, i)
+        visit_expr_if(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_index(&mut self, i: &'ast ExprIndex) {
-        visit_expr_index(self, i)
+        visit_expr_index(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_let(&mut self, i: &'ast ExprLet) {
-        visit_expr_let(self, i)
+        visit_expr_let(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_lit(&mut self, i: &'ast ExprLit) {
-        visit_expr_lit(self, i)
+        visit_expr_lit(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_loop(&mut self, i: &'ast ExprLoop) {
-        visit_expr_loop(self, i)
+        visit_expr_loop(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_macro(&mut self, i: &'ast ExprMacro) {
-        visit_expr_macro(self, i)
+        visit_expr_macro(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_match(&mut self, i: &'ast ExprMatch) {
-        visit_expr_match(self, i)
+        visit_expr_match(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_method_call(&mut self, i: &'ast ExprMethodCall) {
-        visit_expr_method_call(self, i)
+        visit_expr_method_call(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_paren(&mut self, i: &'ast ExprParen) {
-        visit_expr_paren(self, i)
+        visit_expr_paren(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_path(&mut self, i: &'ast ExprPath) {
-        visit_expr_path(self, i)
+        visit_expr_path(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_range(&mut self, i: &'ast ExprRange) {
-        visit_expr_range(self, i)
+        visit_expr_range(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_reference(&mut self, i: &'ast ExprReference) {
-        visit_expr_reference(self, i)
+        visit_expr_reference(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_repeat(&mut self, i: &'ast ExprRepeat) {
-        visit_expr_repeat(self, i)
+        visit_expr_repeat(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_return(&mut self, i: &'ast ExprReturn) {
-        visit_expr_return(self, i)
+        visit_expr_return(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_struct(&mut self, i: &'ast ExprStruct) {
-        visit_expr_struct(self, i)
+        visit_expr_struct(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_try(&mut self, i: &'ast ExprTry) {
-        visit_expr_try(self, i)
+        visit_expr_try(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_try_block(&mut self, i: &'ast ExprTryBlock) {
-        visit_expr_try_block(self, i)
+        visit_expr_try_block(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_tuple(&mut self, i: &'ast ExprTuple) {
-        visit_expr_tuple(self, i)
+        visit_expr_tuple(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_type(&mut self, i: &'ast ExprType) {
-        visit_expr_type(self, i)
+        visit_expr_type(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_unary(&mut self, i: &'ast ExprUnary) {
-        visit_expr_unary(self, i)
+        visit_expr_unary(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_unsafe(&mut self, i: &'ast ExprUnsafe) {
-        visit_expr_unsafe(self, i)
+        visit_expr_unsafe(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_while(&mut self, i: &'ast ExprWhile) {
-        visit_expr_while(self, i)
+        visit_expr_while(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_yield(&mut self, i: &'ast ExprYield) {
-        visit_expr_yield(self, i)
+        visit_expr_yield(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_field(&mut self, i: &'ast Field) {
-        visit_field(self, i)
+        visit_field(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_field_pat(&mut self, i: &'ast FieldPat) {
-        visit_field_pat(self, i)
+        visit_field_pat(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_field_value(&mut self, i: &'ast FieldValue) {
-        visit_field_value(self, i)
+        visit_field_value(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_fields(&mut self, i: &'ast Fields) {
-        visit_fields(self, i)
+        visit_fields(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_fields_named(&mut self, i: &'ast FieldsNamed) {
-        visit_fields_named(self, i)
+        visit_fields_named(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_fields_unnamed(&mut self, i: &'ast FieldsUnnamed) {
-        visit_fields_unnamed(self, i)
+        visit_fields_unnamed(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_file(&mut self, i: &'ast File) {
-        visit_file(self, i)
+        visit_file(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_fn_arg(&mut self, i: &'ast FnArg) {
-        visit_fn_arg(self, i)
+        visit_fn_arg(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_foreign_item(&mut self, i: &'ast ForeignItem) {
-        visit_foreign_item(self, i)
+        visit_foreign_item(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_foreign_item_fn(&mut self, i: &'ast ForeignItemFn) {
-        visit_foreign_item_fn(self, i)
+        visit_foreign_item_fn(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_foreign_item_macro(&mut self, i: &'ast ForeignItemMacro) {
-        visit_foreign_item_macro(self, i)
+        visit_foreign_item_macro(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_foreign_item_static(&mut self, i: &'ast ForeignItemStatic) {
-        visit_foreign_item_static(self, i)
+        visit_foreign_item_static(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_foreign_item_type(&mut self, i: &'ast ForeignItemType) {
-        visit_foreign_item_type(self, i)
+        visit_foreign_item_type(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_generic_argument(&mut self, i: &'ast GenericArgument) {
-        visit_generic_argument(self, i)
+        visit_generic_argument(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_generic_method_argument(&mut self, i: &'ast GenericMethodArgument) {
-        visit_generic_method_argument(self, i)
+        visit_generic_method_argument(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_generic_param(&mut self, i: &'ast GenericParam) {
-        visit_generic_param(self, i)
+        visit_generic_param(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_generics(&mut self, i: &'ast Generics) {
-        visit_generics(self, i)
+        visit_generics(self, i);
     }
     fn visit_ident(&mut self, i: &'ast Ident) {
-        visit_ident(self, i)
+        visit_ident(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_impl_item(&mut self, i: &'ast ImplItem) {
-        visit_impl_item(self, i)
+        visit_impl_item(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_impl_item_const(&mut self, i: &'ast ImplItemConst) {
-        visit_impl_item_const(self, i)
+        visit_impl_item_const(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_impl_item_macro(&mut self, i: &'ast ImplItemMacro) {
-        visit_impl_item_macro(self, i)
+        visit_impl_item_macro(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_impl_item_method(&mut self, i: &'ast ImplItemMethod) {
-        visit_impl_item_method(self, i)
+        visit_impl_item_method(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_impl_item_type(&mut self, i: &'ast ImplItemType) {
-        visit_impl_item_type(self, i)
+        visit_impl_item_type(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_index(&mut self, i: &'ast Index) {
-        visit_index(self, i)
+        visit_index(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item(&mut self, i: &'ast Item) {
-        visit_item(self, i)
+        visit_item(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_const(&mut self, i: &'ast ItemConst) {
-        visit_item_const(self, i)
+        visit_item_const(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_enum(&mut self, i: &'ast ItemEnum) {
-        visit_item_enum(self, i)
+        visit_item_enum(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_extern_crate(&mut self, i: &'ast ItemExternCrate) {
-        visit_item_extern_crate(self, i)
+        visit_item_extern_crate(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_fn(&mut self, i: &'ast ItemFn) {
-        visit_item_fn(self, i)
+        visit_item_fn(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_foreign_mod(&mut self, i: &'ast ItemForeignMod) {
-        visit_item_foreign_mod(self, i)
+        visit_item_foreign_mod(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_impl(&mut self, i: &'ast ItemImpl) {
-        visit_item_impl(self, i)
+        visit_item_impl(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_macro(&mut self, i: &'ast ItemMacro) {
-        visit_item_macro(self, i)
+        visit_item_macro(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_macro2(&mut self, i: &'ast ItemMacro2) {
-        visit_item_macro2(self, i)
+        visit_item_macro2(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_mod(&mut self, i: &'ast ItemMod) {
-        visit_item_mod(self, i)
+        visit_item_mod(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_static(&mut self, i: &'ast ItemStatic) {
-        visit_item_static(self, i)
+        visit_item_static(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_struct(&mut self, i: &'ast ItemStruct) {
-        visit_item_struct(self, i)
+        visit_item_struct(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_trait(&mut self, i: &'ast ItemTrait) {
-        visit_item_trait(self, i)
+        visit_item_trait(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_trait_alias(&mut self, i: &'ast ItemTraitAlias) {
-        visit_item_trait_alias(self, i)
+        visit_item_trait_alias(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_type(&mut self, i: &'ast ItemType) {
-        visit_item_type(self, i)
+        visit_item_type(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_union(&mut self, i: &'ast ItemUnion) {
-        visit_item_union(self, i)
+        visit_item_union(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_use(&mut self, i: &'ast ItemUse) {
-        visit_item_use(self, i)
+        visit_item_use(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_label(&mut self, i: &'ast Label) {
-        visit_label(self, i)
+        visit_label(self, i);
     }
     fn visit_lifetime(&mut self, i: &'ast Lifetime) {
-        visit_lifetime(self, i)
+        visit_lifetime(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_lifetime_def(&mut self, i: &'ast LifetimeDef) {
-        visit_lifetime_def(self, i)
+        visit_lifetime_def(self, i);
     }
     fn visit_lit(&mut self, i: &'ast Lit) {
-        visit_lit(self, i)
+        visit_lit(self, i);
     }
     fn visit_lit_bool(&mut self, i: &'ast LitBool) {
-        visit_lit_bool(self, i)
+        visit_lit_bool(self, i);
     }
     fn visit_lit_byte(&mut self, i: &'ast LitByte) {
-        visit_lit_byte(self, i)
+        visit_lit_byte(self, i);
     }
     fn visit_lit_byte_str(&mut self, i: &'ast LitByteStr) {
-        visit_lit_byte_str(self, i)
+        visit_lit_byte_str(self, i);
     }
     fn visit_lit_char(&mut self, i: &'ast LitChar) {
-        visit_lit_char(self, i)
+        visit_lit_char(self, i);
     }
     fn visit_lit_float(&mut self, i: &'ast LitFloat) {
-        visit_lit_float(self, i)
+        visit_lit_float(self, i);
     }
     fn visit_lit_int(&mut self, i: &'ast LitInt) {
-        visit_lit_int(self, i)
+        visit_lit_int(self, i);
     }
     fn visit_lit_str(&mut self, i: &'ast LitStr) {
-        visit_lit_str(self, i)
+        visit_lit_str(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_local(&mut self, i: &'ast Local) {
-        visit_local(self, i)
+        visit_local(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_macro(&mut self, i: &'ast Macro) {
-        visit_macro(self, i)
+        visit_macro(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_macro_delimiter(&mut self, i: &'ast MacroDelimiter) {
-        visit_macro_delimiter(self, i)
+        visit_macro_delimiter(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_member(&mut self, i: &'ast Member) {
-        visit_member(self, i)
+        visit_member(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_meta(&mut self, i: &'ast Meta) {
-        visit_meta(self, i)
+        visit_meta(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_meta_list(&mut self, i: &'ast MetaList) {
-        visit_meta_list(self, i)
+        visit_meta_list(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_meta_name_value(&mut self, i: &'ast MetaNameValue) {
-        visit_meta_name_value(self, i)
+        visit_meta_name_value(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_method_turbofish(&mut self, i: &'ast MethodTurbofish) {
-        visit_method_turbofish(self, i)
+        visit_method_turbofish(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_nested_meta(&mut self, i: &'ast NestedMeta) {
-        visit_nested_meta(self, i)
+        visit_nested_meta(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_parenthesized_generic_arguments(&mut self, i: &'ast ParenthesizedGenericArguments) {
-        visit_parenthesized_generic_arguments(self, i)
+        visit_parenthesized_generic_arguments(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat(&mut self, i: &'ast Pat) {
-        visit_pat(self, i)
+        visit_pat(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_box(&mut self, i: &'ast PatBox) {
-        visit_pat_box(self, i)
+        visit_pat_box(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_ident(&mut self, i: &'ast PatIdent) {
-        visit_pat_ident(self, i)
+        visit_pat_ident(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_lit(&mut self, i: &'ast PatLit) {
-        visit_pat_lit(self, i)
+        visit_pat_lit(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_macro(&mut self, i: &'ast PatMacro) {
-        visit_pat_macro(self, i)
+        visit_pat_macro(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_or(&mut self, i: &'ast PatOr) {
-        visit_pat_or(self, i)
+        visit_pat_or(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_path(&mut self, i: &'ast PatPath) {
-        visit_pat_path(self, i)
+        visit_pat_path(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_range(&mut self, i: &'ast PatRange) {
-        visit_pat_range(self, i)
+        visit_pat_range(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_reference(&mut self, i: &'ast PatReference) {
-        visit_pat_reference(self, i)
+        visit_pat_reference(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_rest(&mut self, i: &'ast PatRest) {
-        visit_pat_rest(self, i)
+        visit_pat_rest(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_slice(&mut self, i: &'ast PatSlice) {
-        visit_pat_slice(self, i)
+        visit_pat_slice(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_struct(&mut self, i: &'ast PatStruct) {
-        visit_pat_struct(self, i)
+        visit_pat_struct(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_tuple(&mut self, i: &'ast PatTuple) {
-        visit_pat_tuple(self, i)
+        visit_pat_tuple(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_tuple_struct(&mut self, i: &'ast PatTupleStruct) {
-        visit_pat_tuple_struct(self, i)
+        visit_pat_tuple_struct(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_type(&mut self, i: &'ast PatType) {
-        visit_pat_type(self, i)
+        visit_pat_type(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_wild(&mut self, i: &'ast PatWild) {
-        visit_pat_wild(self, i)
+        visit_pat_wild(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_path(&mut self, i: &'ast Path) {
-        visit_path(self, i)
+        visit_path(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_path_arguments(&mut self, i: &'ast PathArguments) {
-        visit_path_arguments(self, i)
+        visit_path_arguments(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_path_segment(&mut self, i: &'ast PathSegment) {
-        visit_path_segment(self, i)
+        visit_path_segment(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_predicate_eq(&mut self, i: &'ast PredicateEq) {
-        visit_predicate_eq(self, i)
+        visit_predicate_eq(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_predicate_lifetime(&mut self, i: &'ast PredicateLifetime) {
-        visit_predicate_lifetime(self, i)
+        visit_predicate_lifetime(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_predicate_type(&mut self, i: &'ast PredicateType) {
-        visit_predicate_type(self, i)
+        visit_predicate_type(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_qself(&mut self, i: &'ast QSelf) {
-        visit_qself(self, i)
+        visit_qself(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_range_limits(&mut self, i: &'ast RangeLimits) {
-        visit_range_limits(self, i)
+        visit_range_limits(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_receiver(&mut self, i: &'ast Receiver) {
-        visit_receiver(self, i)
+        visit_receiver(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_return_type(&mut self, i: &'ast ReturnType) {
-        visit_return_type(self, i)
+        visit_return_type(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_signature(&mut self, i: &'ast Signature) {
-        visit_signature(self, i)
+        visit_signature(self, i);
     }
     fn visit_span(&mut self, i: &Span) {
-        visit_span(self, i)
+        visit_span(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_stmt(&mut self, i: &'ast Stmt) {
-        visit_stmt(self, i)
+        visit_stmt(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_trait_bound(&mut self, i: &'ast TraitBound) {
-        visit_trait_bound(self, i)
+        visit_trait_bound(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_trait_bound_modifier(&mut self, i: &'ast TraitBoundModifier) {
-        visit_trait_bound_modifier(self, i)
+        visit_trait_bound_modifier(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_trait_item(&mut self, i: &'ast TraitItem) {
-        visit_trait_item(self, i)
+        visit_trait_item(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_trait_item_const(&mut self, i: &'ast TraitItemConst) {
-        visit_trait_item_const(self, i)
+        visit_trait_item_const(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_trait_item_macro(&mut self, i: &'ast TraitItemMacro) {
-        visit_trait_item_macro(self, i)
+        visit_trait_item_macro(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_trait_item_method(&mut self, i: &'ast TraitItemMethod) {
-        visit_trait_item_method(self, i)
+        visit_trait_item_method(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_trait_item_type(&mut self, i: &'ast TraitItemType) {
-        visit_trait_item_type(self, i)
+        visit_trait_item_type(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type(&mut self, i: &'ast Type) {
-        visit_type(self, i)
+        visit_type(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_array(&mut self, i: &'ast TypeArray) {
-        visit_type_array(self, i)
+        visit_type_array(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_bare_fn(&mut self, i: &'ast TypeBareFn) {
-        visit_type_bare_fn(self, i)
+        visit_type_bare_fn(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_group(&mut self, i: &'ast TypeGroup) {
-        visit_type_group(self, i)
+        visit_type_group(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_impl_trait(&mut self, i: &'ast TypeImplTrait) {
-        visit_type_impl_trait(self, i)
+        visit_type_impl_trait(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_infer(&mut self, i: &'ast TypeInfer) {
-        visit_type_infer(self, i)
+        visit_type_infer(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_macro(&mut self, i: &'ast TypeMacro) {
-        visit_type_macro(self, i)
+        visit_type_macro(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_never(&mut self, i: &'ast TypeNever) {
-        visit_type_never(self, i)
+        visit_type_never(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_param(&mut self, i: &'ast TypeParam) {
-        visit_type_param(self, i)
+        visit_type_param(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_param_bound(&mut self, i: &'ast TypeParamBound) {
-        visit_type_param_bound(self, i)
+        visit_type_param_bound(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_paren(&mut self, i: &'ast TypeParen) {
-        visit_type_paren(self, i)
+        visit_type_paren(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_path(&mut self, i: &'ast TypePath) {
-        visit_type_path(self, i)
+        visit_type_path(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_ptr(&mut self, i: &'ast TypePtr) {
-        visit_type_ptr(self, i)
+        visit_type_ptr(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_reference(&mut self, i: &'ast TypeReference) {
-        visit_type_reference(self, i)
+        visit_type_reference(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_slice(&mut self, i: &'ast TypeSlice) {
-        visit_type_slice(self, i)
+        visit_type_slice(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_trait_object(&mut self, i: &'ast TypeTraitObject) {
-        visit_type_trait_object(self, i)
+        visit_type_trait_object(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_tuple(&mut self, i: &'ast TypeTuple) {
-        visit_type_tuple(self, i)
+        visit_type_tuple(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_un_op(&mut self, i: &'ast UnOp) {
-        visit_un_op(self, i)
+        visit_un_op(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_use_glob(&mut self, i: &'ast UseGlob) {
-        visit_use_glob(self, i)
+        visit_use_glob(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_use_group(&mut self, i: &'ast UseGroup) {
-        visit_use_group(self, i)
+        visit_use_group(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_use_name(&mut self, i: &'ast UseName) {
-        visit_use_name(self, i)
+        visit_use_name(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_use_path(&mut self, i: &'ast UsePath) {
-        visit_use_path(self, i)
+        visit_use_path(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_use_rename(&mut self, i: &'ast UseRename) {
-        visit_use_rename(self, i)
+        visit_use_rename(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_use_tree(&mut self, i: &'ast UseTree) {
-        visit_use_tree(self, i)
+        visit_use_tree(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_variadic(&mut self, i: &'ast Variadic) {
-        visit_variadic(self, i)
+        visit_variadic(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_variant(&mut self, i: &'ast Variant) {
-        visit_variant(self, i)
+        visit_variant(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_vis_crate(&mut self, i: &'ast VisCrate) {
-        visit_vis_crate(self, i)
+        visit_vis_crate(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_vis_public(&mut self, i: &'ast VisPublic) {
-        visit_vis_public(self, i)
+        visit_vis_public(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_vis_restricted(&mut self, i: &'ast VisRestricted) {
-        visit_vis_restricted(self, i)
+        visit_vis_restricted(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_visibility(&mut self, i: &'ast Visibility) {
-        visit_visibility(self, i)
+        visit_visibility(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_where_clause(&mut self, i: &'ast WhereClause) {
-        visit_where_clause(self, i)
+        visit_where_clause(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_where_predicate(&mut self, i: &'ast WherePredicate) {
-        visit_where_predicate(self, i)
+        visit_where_predicate(self, i);
     }
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -776,7 +776,7 @@ where
 {
     tokens_helper(v, &node.extern_token.span);
     if let Some(it) = &node.name {
-        v.visit_lit_str(it)
+        v.visit_lit_str(it);
     };
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -787,7 +787,7 @@ pub fn visit_angle_bracketed_generic_arguments<'ast, V>(
     V: Visit<'ast> + ?Sized,
 {
     if let Some(it) = &node.colon2_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     tokens_helper(v, &node.lt_token.spans);
     for el in Punctuated::pairs(&node.args) {
@@ -805,7 +805,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_pat(&node.pat);
     if let Some(it) = &node.guard {
@@ -815,7 +815,7 @@ where
     tokens_helper(v, &node.fat_arrow_token.spans);
     v.visit_expr(&*node.body);
     if let Some(it) = &node.comma {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -847,7 +847,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     if let Some(it) = &node.name {
         v.visit_ident(&(it).0);
@@ -963,7 +963,7 @@ where
 {
     tokens_helper(v, &node.brace_token.span);
     for it in &node.stmts {
-        v.visit_stmt(it)
+        v.visit_stmt(it);
     }
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -988,17 +988,17 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.const_token.span);
     v.visit_ident(&node.ident);
     tokens_helper(v, &node.colon_token.spans);
     v.visit_type(&node.ty);
     if let Some(it) = &node.eq_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     if let Some(it) = &node.default {
-        v.visit_expr(it)
+        v.visit_expr(it);
     };
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -1056,7 +1056,7 @@ where
     tokens_helper(v, &node.struct_token.span);
     v.visit_fields(&node.fields);
     if let Some(it) = &node.semi_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
 }
 #[cfg(feature = "derive")]
@@ -1073,7 +1073,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     v.visit_ident(&node.ident);
@@ -1215,7 +1215,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.bracket_token.span);
     for el in Punctuated::pairs(&node.elems) {
@@ -1232,7 +1232,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_expr(&*node.left);
     tokens_helper(v, &node.eq_token.spans);
@@ -1244,7 +1244,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_expr(&*node.left);
     v.visit_bin_op(&node.op);
@@ -1256,11 +1256,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.async_token.span);
     if let Some(it) = &node.capture {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     v.visit_block(&node.block);
 }
@@ -1270,7 +1270,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_expr(&*node.base);
     tokens_helper(v, &node.dot_token.spans);
@@ -1282,7 +1282,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_expr(&*node.left);
     v.visit_bin_op(&node.op);
@@ -1294,10 +1294,10 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     if let Some(it) = &node.label {
-        v.visit_label(it)
+        v.visit_label(it);
     };
     v.visit_block(&node.block);
 }
@@ -1307,7 +1307,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.box_token.span);
     v.visit_expr(&*node.expr);
@@ -1318,14 +1318,14 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.break_token.span);
     if let Some(it) = &node.label {
-        v.visit_lifetime(it)
+        v.visit_lifetime(it);
     };
     if let Some(it) = &node.expr {
-        v.visit_expr(&**it)
+        v.visit_expr(&**it);
     };
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -1334,7 +1334,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_expr(&*node.func);
     tokens_helper(v, &node.paren_token.span);
@@ -1352,7 +1352,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_expr(&*node.expr);
     tokens_helper(v, &node.as_token.span);
@@ -1364,16 +1364,16 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     if let Some(it) = &node.asyncness {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     if let Some(it) = &node.movability {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     if let Some(it) = &node.capture {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     tokens_helper(v, &node.or1_token.spans);
     for el in Punctuated::pairs(&node.inputs) {
@@ -1393,11 +1393,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.continue_token.span);
     if let Some(it) = &node.label {
-        v.visit_lifetime(it)
+        v.visit_lifetime(it);
     };
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -1406,7 +1406,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_expr(&*node.base);
     tokens_helper(v, &node.dot_token.spans);
@@ -1418,10 +1418,10 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     if let Some(it) = &node.label {
-        v.visit_label(it)
+        v.visit_label(it);
     };
     tokens_helper(v, &node.for_token.span);
     v.visit_pat(&node.pat);
@@ -1435,7 +1435,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.group_token.span);
     v.visit_expr(&*node.expr);
@@ -1446,7 +1446,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.if_token.span);
     v.visit_expr(&*node.cond);
@@ -1462,7 +1462,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_expr(&*node.expr);
     tokens_helper(v, &node.bracket_token.span);
@@ -1474,7 +1474,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.let_token.span);
     v.visit_pat(&node.pat);
@@ -1487,7 +1487,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_lit(&node.lit);
 }
@@ -1497,10 +1497,10 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     if let Some(it) = &node.label {
-        v.visit_label(it)
+        v.visit_label(it);
     };
     tokens_helper(v, &node.loop_token.span);
     v.visit_block(&node.body);
@@ -1511,7 +1511,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_macro(&node.mac);
 }
@@ -1521,13 +1521,13 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.match_token.span);
     v.visit_expr(&*node.expr);
     tokens_helper(v, &node.brace_token.span);
     for it in &node.arms {
-        v.visit_arm(it)
+        v.visit_arm(it);
     }
 }
 #[cfg(feature = "full")]
@@ -1536,13 +1536,13 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_expr(&*node.receiver);
     tokens_helper(v, &node.dot_token.spans);
     v.visit_ident(&node.method);
     if let Some(it) = &node.turbofish {
-        v.visit_method_turbofish(it)
+        v.visit_method_turbofish(it);
     };
     tokens_helper(v, &node.paren_token.span);
     for el in Punctuated::pairs(&node.args) {
@@ -1559,7 +1559,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.paren_token.span);
     v.visit_expr(&*node.expr);
@@ -1570,10 +1570,10 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     if let Some(it) = &node.qself {
-        v.visit_qself(it)
+        v.visit_qself(it);
     };
     v.visit_path(&node.path);
 }
@@ -1583,14 +1583,14 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     if let Some(it) = &node.from {
-        v.visit_expr(&**it)
+        v.visit_expr(&**it);
     };
     v.visit_range_limits(&node.limits);
     if let Some(it) = &node.to {
-        v.visit_expr(&**it)
+        v.visit_expr(&**it);
     };
 }
 #[cfg(feature = "full")]
@@ -1599,11 +1599,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.and_token.spans);
     if let Some(it) = &node.mutability {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     v.visit_expr(&*node.expr);
 }
@@ -1613,7 +1613,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.bracket_token.span);
     v.visit_expr(&*node.expr);
@@ -1626,11 +1626,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.return_token.span);
     if let Some(it) = &node.expr {
-        v.visit_expr(&**it)
+        v.visit_expr(&**it);
     };
 }
 #[cfg(feature = "full")]
@@ -1639,7 +1639,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_path(&node.path);
     tokens_helper(v, &node.brace_token.span);
@@ -1651,10 +1651,10 @@ where
         }
     }
     if let Some(it) = &node.dot2_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     if let Some(it) = &node.rest {
-        v.visit_expr(&**it)
+        v.visit_expr(&**it);
     };
 }
 #[cfg(feature = "full")]
@@ -1663,7 +1663,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_expr(&*node.expr);
     tokens_helper(v, &node.question_token.spans);
@@ -1674,7 +1674,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.try_token.span);
     v.visit_block(&node.block);
@@ -1685,7 +1685,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.paren_token.span);
     for el in Punctuated::pairs(&node.elems) {
@@ -1702,7 +1702,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_expr(&*node.expr);
     tokens_helper(v, &node.colon_token.spans);
@@ -1714,7 +1714,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_un_op(&node.op);
     v.visit_expr(&*node.expr);
@@ -1725,7 +1725,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.unsafe_token.span);
     v.visit_block(&node.block);
@@ -1736,10 +1736,10 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     if let Some(it) = &node.label {
-        v.visit_label(it)
+        v.visit_label(it);
     };
     tokens_helper(v, &node.while_token.span);
     v.visit_expr(&*node.cond);
@@ -1751,11 +1751,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.yield_token.span);
     if let Some(it) = &node.expr {
-        v.visit_expr(&**it)
+        v.visit_expr(&**it);
     };
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -1764,14 +1764,14 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     if let Some(it) = &node.ident {
-        v.visit_ident(it)
+        v.visit_ident(it);
     };
     if let Some(it) = &node.colon_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     v.visit_type(&node.ty);
 }
@@ -1781,11 +1781,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_member(&node.member);
     if let Some(it) = &node.colon_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     v.visit_pat(&*node.pat);
 }
@@ -1795,11 +1795,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_member(&node.member);
     if let Some(it) = &node.colon_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     v.visit_expr(&node.expr);
 }
@@ -1853,10 +1853,10 @@ where
 {
     skip!(node.shebang);
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     for it in &node.items {
-        v.visit_item(it)
+        v.visit_item(it);
     }
 }
 #[cfg(feature = "full")]
@@ -1903,7 +1903,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     v.visit_signature(&node.sig);
@@ -1915,11 +1915,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_macro(&node.mac);
     if let Some(it) = &node.semi_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -1928,12 +1928,12 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     tokens_helper(v, &node.static_token.span);
     if let Some(it) = &node.mutability {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     v.visit_ident(&node.ident);
     tokens_helper(v, &node.colon_token.spans);
@@ -1946,7 +1946,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     tokens_helper(v, &node.type_token.span);
@@ -2013,7 +2013,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     if let Some(it) = &node.lt_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     for el in Punctuated::pairs(&node.params) {
         let (it, p) = el.into_tuple();
@@ -2023,10 +2023,10 @@ where
         }
     }
     if let Some(it) = &node.gt_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     if let Some(it) = &node.where_clause {
-        v.visit_where_clause(it)
+        v.visit_where_clause(it);
     };
 }
 pub fn visit_ident<'ast, V>(v: &mut V, node: &'ast Ident)
@@ -2065,11 +2065,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     if let Some(it) = &node.defaultness {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     tokens_helper(v, &node.const_token.span);
     v.visit_ident(&node.ident);
@@ -2085,11 +2085,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_macro(&node.mac);
     if let Some(it) = &node.semi_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -2098,11 +2098,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     if let Some(it) = &node.defaultness {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     v.visit_signature(&node.sig);
     v.visit_block(&node.block);
@@ -2113,11 +2113,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     if let Some(it) = &node.defaultness {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     tokens_helper(v, &node.type_token.span);
     v.visit_ident(&node.ident);
@@ -2200,7 +2200,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     tokens_helper(v, &node.const_token.span);
@@ -2217,7 +2217,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     tokens_helper(v, &node.enum_token.span);
@@ -2238,7 +2238,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     tokens_helper(v, &node.extern_token.span);
@@ -2256,7 +2256,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     v.visit_signature(&node.sig);
@@ -2268,12 +2268,12 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_abi(&node.abi);
     tokens_helper(v, &node.brace_token.span);
     for it in &node.items {
-        v.visit_foreign_item(it)
+        v.visit_foreign_item(it);
     }
 }
 #[cfg(feature = "full")]
@@ -2282,19 +2282,19 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     if let Some(it) = &node.defaultness {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     if let Some(it) = &node.unsafety {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     tokens_helper(v, &node.impl_token.span);
     v.visit_generics(&node.generics);
     if let Some(it) = &node.trait_ {
         if let Some(it) = &(it).0 {
-            tokens_helper(v, &it.spans)
+            tokens_helper(v, &it.spans);
         };
         v.visit_path(&(it).1);
         tokens_helper(v, &(it).2.span);
@@ -2302,7 +2302,7 @@ where
     v.visit_type(&*node.self_ty);
     tokens_helper(v, &node.brace_token.span);
     for it in &node.items {
-        v.visit_impl_item(it)
+        v.visit_impl_item(it);
     }
 }
 #[cfg(feature = "full")]
@@ -2311,14 +2311,14 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     if let Some(it) = &node.ident {
-        v.visit_ident(it)
+        v.visit_ident(it);
     };
     v.visit_macro(&node.mac);
     if let Some(it) = &node.semi_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -2327,7 +2327,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     tokens_helper(v, &node.macro_token.span);
@@ -2340,7 +2340,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     tokens_helper(v, &node.mod_token.span);
@@ -2348,11 +2348,11 @@ where
     if let Some(it) = &node.content {
         tokens_helper(v, &(it).0.span);
         for it in &(it).1 {
-            v.visit_item(it)
+            v.visit_item(it);
         }
     };
     if let Some(it) = &node.semi {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -2361,12 +2361,12 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     tokens_helper(v, &node.static_token.span);
     if let Some(it) = &node.mutability {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     v.visit_ident(&node.ident);
     tokens_helper(v, &node.colon_token.spans);
@@ -2381,7 +2381,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     tokens_helper(v, &node.struct_token.span);
@@ -2389,7 +2389,7 @@ where
     v.visit_generics(&node.generics);
     v.visit_fields(&node.fields);
     if let Some(it) = &node.semi_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -2398,20 +2398,20 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     if let Some(it) = &node.unsafety {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     if let Some(it) = &node.auto_token {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     tokens_helper(v, &node.trait_token.span);
     v.visit_ident(&node.ident);
     v.visit_generics(&node.generics);
     if let Some(it) = &node.colon_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     for el in Punctuated::pairs(&node.supertraits) {
         let (it, p) = el.into_tuple();
@@ -2422,7 +2422,7 @@ where
     }
     tokens_helper(v, &node.brace_token.span);
     for it in &node.items {
-        v.visit_trait_item(it)
+        v.visit_trait_item(it);
     }
 }
 #[cfg(feature = "full")]
@@ -2431,7 +2431,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     tokens_helper(v, &node.trait_token.span);
@@ -2453,7 +2453,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     tokens_helper(v, &node.type_token.span);
@@ -2469,7 +2469,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     tokens_helper(v, &node.union_token.span);
@@ -2483,12 +2483,12 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_visibility(&node.vis);
     tokens_helper(v, &node.use_token.span);
     if let Some(it) = &node.leading_colon {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     v.visit_use_tree(&node.tree);
     tokens_helper(v, &node.semi_token.spans);
@@ -2514,11 +2514,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_lifetime(&node.lifetime);
     if let Some(it) = &node.colon_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     for el in Punctuated::pairs(&node.bounds) {
         let (it, p) = el.into_tuple();
@@ -2602,7 +2602,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.let_token.span);
     v.visit_pat(&node.pat);
@@ -2804,7 +2804,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.box_token.span);
     v.visit_pat(&*node.pat);
@@ -2815,13 +2815,13 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     if let Some(it) = &node.by_ref {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     if let Some(it) = &node.mutability {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     v.visit_ident(&node.ident);
     if let Some(it) = &node.subpat {
@@ -2835,7 +2835,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_expr(&*node.expr);
 }
@@ -2845,7 +2845,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_macro(&node.mac);
 }
@@ -2855,10 +2855,10 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     if let Some(it) = &node.leading_vert {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     for el in Punctuated::pairs(&node.cases) {
         let (it, p) = el.into_tuple();
@@ -2874,10 +2874,10 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     if let Some(it) = &node.qself {
-        v.visit_qself(it)
+        v.visit_qself(it);
     };
     v.visit_path(&node.path);
 }
@@ -2887,7 +2887,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_expr(&*node.lo);
     v.visit_range_limits(&node.limits);
@@ -2899,11 +2899,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.and_token.spans);
     if let Some(it) = &node.mutability {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     v.visit_pat(&*node.pat);
 }
@@ -2913,7 +2913,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.dot2_token.spans);
 }
@@ -2923,7 +2923,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.bracket_token.span);
     for el in Punctuated::pairs(&node.elems) {
@@ -2940,7 +2940,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_path(&node.path);
     tokens_helper(v, &node.brace_token.span);
@@ -2952,7 +2952,7 @@ where
         }
     }
     if let Some(it) = &node.dot2_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -2961,7 +2961,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.paren_token.span);
     for el in Punctuated::pairs(&node.elems) {
@@ -2978,7 +2978,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_path(&node.path);
     v.visit_pat_tuple(&node.pat);
@@ -2989,7 +2989,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_pat(&*node.pat);
     tokens_helper(v, &node.colon_token.spans);
@@ -3001,7 +3001,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.underscore_token.spans);
 }
@@ -3011,7 +3011,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     if let Some(it) = &node.leading_colon {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     for el in Punctuated::pairs(&node.segments) {
         let (it, p) = el.into_tuple();
@@ -3074,7 +3074,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     if let Some(it) = &node.lifetimes {
-        v.visit_bound_lifetimes(it)
+        v.visit_bound_lifetimes(it);
     };
     v.visit_type(&node.bounded_ty);
     tokens_helper(v, &node.colon_token.spans);
@@ -3095,7 +3095,7 @@ where
     v.visit_type(&*node.ty);
     skip!(node.position);
     if let Some(it) = &node.as_token {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     tokens_helper(v, &node.gt_token.spans);
 }
@@ -3119,16 +3119,16 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     if let Some(it) = &node.reference {
         tokens_helper(v, &(it).0.spans);
         if let Some(it) = &(it).1 {
-            v.visit_lifetime(it)
+            v.visit_lifetime(it);
         };
     };
     if let Some(it) = &node.mutability {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     tokens_helper(v, &node.self_token.span);
 }
@@ -3151,16 +3151,16 @@ where
     V: Visit<'ast> + ?Sized,
 {
     if let Some(it) = &node.constness {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     if let Some(it) = &node.asyncness {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     if let Some(it) = &node.unsafety {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     if let Some(it) = &node.abi {
-        v.visit_abi(it)
+        v.visit_abi(it);
     };
     tokens_helper(v, &node.fn_token.span);
     v.visit_ident(&node.ident);
@@ -3174,7 +3174,7 @@ where
         }
     }
     if let Some(it) = &node.variadic {
-        v.visit_variadic(it)
+        v.visit_variadic(it);
     };
     v.visit_return_type(&node.output);
 }
@@ -3210,11 +3210,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     if let Some(it) = &node.paren_token {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     v.visit_trait_bound_modifier(&node.modifier);
     if let Some(it) = &node.lifetimes {
-        v.visit_bound_lifetimes(it)
+        v.visit_bound_lifetimes(it);
     };
     v.visit_path(&node.path);
 }
@@ -3260,7 +3260,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.const_token.span);
     v.visit_ident(&node.ident);
@@ -3278,11 +3278,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_macro(&node.mac);
     if let Some(it) = &node.semi_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -3291,14 +3291,14 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_signature(&node.sig);
     if let Some(it) = &node.default {
-        v.visit_block(it)
+        v.visit_block(it);
     };
     if let Some(it) = &node.semi_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -3307,13 +3307,13 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.type_token.span);
     v.visit_ident(&node.ident);
     v.visit_generics(&node.generics);
     if let Some(it) = &node.colon_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     for el in Punctuated::pairs(&node.bounds) {
         let (it, p) = el.into_tuple();
@@ -3398,13 +3398,13 @@ where
     V: Visit<'ast> + ?Sized,
 {
     if let Some(it) = &node.lifetimes {
-        v.visit_bound_lifetimes(it)
+        v.visit_bound_lifetimes(it);
     };
     if let Some(it) = &node.unsafety {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     if let Some(it) = &node.abi {
-        v.visit_abi(it)
+        v.visit_abi(it);
     };
     tokens_helper(v, &node.fn_token.span);
     tokens_helper(v, &node.paren_token.span);
@@ -3416,7 +3416,7 @@ where
         }
     }
     if let Some(it) = &node.variadic {
-        v.visit_variadic(it)
+        v.visit_variadic(it);
     };
     v.visit_return_type(&node.output);
 }
@@ -3469,11 +3469,11 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_ident(&node.ident);
     if let Some(it) = &node.colon_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     for el in Punctuated::pairs(&node.bounds) {
         let (it, p) = el.into_tuple();
@@ -3483,10 +3483,10 @@ where
         }
     }
     if let Some(it) = &node.eq_token {
-        tokens_helper(v, &it.spans)
+        tokens_helper(v, &it.spans);
     };
     if let Some(it) = &node.default {
-        v.visit_type(it)
+        v.visit_type(it);
     };
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -3517,7 +3517,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     if let Some(it) = &node.qself {
-        v.visit_qself(it)
+        v.visit_qself(it);
     };
     v.visit_path(&node.path);
 }
@@ -3528,10 +3528,10 @@ where
 {
     tokens_helper(v, &node.star_token.spans);
     if let Some(it) = &node.const_token {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     if let Some(it) = &node.mutability {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     v.visit_type(&*node.elem);
 }
@@ -3542,10 +3542,10 @@ where
 {
     tokens_helper(v, &node.and_token.spans);
     if let Some(it) = &node.lifetime {
-        v.visit_lifetime(it)
+        v.visit_lifetime(it);
     };
     if let Some(it) = &node.mutability {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     v.visit_type(&*node.elem);
 }
@@ -3563,7 +3563,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     if let Some(it) = &node.dyn_token {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     for el in Punctuated::pairs(&node.bounds) {
         let (it, p) = el.into_tuple();
@@ -3679,7 +3679,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     tokens_helper(v, &node.dots.spans);
 }
@@ -3689,7 +3689,7 @@ where
     V: Visit<'ast> + ?Sized,
 {
     for it in &node.attrs {
-        v.visit_attribute(it)
+        v.visit_attribute(it);
     }
     v.visit_ident(&node.ident);
     v.visit_fields(&node.fields);
@@ -3720,7 +3720,7 @@ where
     tokens_helper(v, &node.pub_token.span);
     tokens_helper(v, &node.paren_token.span);
     if let Some(it) = &node.in_token {
-        tokens_helper(v, &it.span)
+        tokens_helper(v, &it.span);
     };
     v.visit_path(&*node.path);
 }
index 5ce11f0b2e1983a2a550725caac62c0d48cd2895..1de0c95eb935a15571bb2ce69105c25b96e0bbee 100644 (file)
@@ -34,743 +34,743 @@ macro_rules! skip {
 pub trait VisitMut {
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_abi_mut(&mut self, i: &mut Abi) {
-        visit_abi_mut(self, i)
+        visit_abi_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_angle_bracketed_generic_arguments_mut(
         &mut self,
         i: &mut AngleBracketedGenericArguments,
     ) {
-        visit_angle_bracketed_generic_arguments_mut(self, i)
+        visit_angle_bracketed_generic_arguments_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_arm_mut(&mut self, i: &mut Arm) {
-        visit_arm_mut(self, i)
+        visit_arm_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_attr_style_mut(&mut self, i: &mut AttrStyle) {
-        visit_attr_style_mut(self, i)
+        visit_attr_style_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_attribute_mut(&mut self, i: &mut Attribute) {
-        visit_attribute_mut(self, i)
+        visit_attribute_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_bare_fn_arg_mut(&mut self, i: &mut BareFnArg) {
-        visit_bare_fn_arg_mut(self, i)
+        visit_bare_fn_arg_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_bin_op_mut(&mut self, i: &mut BinOp) {
-        visit_bin_op_mut(self, i)
+        visit_bin_op_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_binding_mut(&mut self, i: &mut Binding) {
-        visit_binding_mut(self, i)
+        visit_binding_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_block_mut(&mut self, i: &mut Block) {
-        visit_block_mut(self, i)
+        visit_block_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_bound_lifetimes_mut(&mut self, i: &mut BoundLifetimes) {
-        visit_bound_lifetimes_mut(self, i)
+        visit_bound_lifetimes_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_const_param_mut(&mut self, i: &mut ConstParam) {
-        visit_const_param_mut(self, i)
+        visit_const_param_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_constraint_mut(&mut self, i: &mut Constraint) {
-        visit_constraint_mut(self, i)
+        visit_constraint_mut(self, i);
     }
     #[cfg(feature = "derive")]
     fn visit_data_mut(&mut self, i: &mut Data) {
-        visit_data_mut(self, i)
+        visit_data_mut(self, i);
     }
     #[cfg(feature = "derive")]
     fn visit_data_enum_mut(&mut self, i: &mut DataEnum) {
-        visit_data_enum_mut(self, i)
+        visit_data_enum_mut(self, i);
     }
     #[cfg(feature = "derive")]
     fn visit_data_struct_mut(&mut self, i: &mut DataStruct) {
-        visit_data_struct_mut(self, i)
+        visit_data_struct_mut(self, i);
     }
     #[cfg(feature = "derive")]
     fn visit_data_union_mut(&mut self, i: &mut DataUnion) {
-        visit_data_union_mut(self, i)
+        visit_data_union_mut(self, i);
     }
     #[cfg(feature = "derive")]
     fn visit_derive_input_mut(&mut self, i: &mut DeriveInput) {
-        visit_derive_input_mut(self, i)
+        visit_derive_input_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_mut(&mut self, i: &mut Expr) {
-        visit_expr_mut(self, i)
+        visit_expr_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_array_mut(&mut self, i: &mut ExprArray) {
-        visit_expr_array_mut(self, i)
+        visit_expr_array_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_assign_mut(&mut self, i: &mut ExprAssign) {
-        visit_expr_assign_mut(self, i)
+        visit_expr_assign_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_assign_op_mut(&mut self, i: &mut ExprAssignOp) {
-        visit_expr_assign_op_mut(self, i)
+        visit_expr_assign_op_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_async_mut(&mut self, i: &mut ExprAsync) {
-        visit_expr_async_mut(self, i)
+        visit_expr_async_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_await_mut(&mut self, i: &mut ExprAwait) {
-        visit_expr_await_mut(self, i)
+        visit_expr_await_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_binary_mut(&mut self, i: &mut ExprBinary) {
-        visit_expr_binary_mut(self, i)
+        visit_expr_binary_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_block_mut(&mut self, i: &mut ExprBlock) {
-        visit_expr_block_mut(self, i)
+        visit_expr_block_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_box_mut(&mut self, i: &mut ExprBox) {
-        visit_expr_box_mut(self, i)
+        visit_expr_box_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_break_mut(&mut self, i: &mut ExprBreak) {
-        visit_expr_break_mut(self, i)
+        visit_expr_break_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_call_mut(&mut self, i: &mut ExprCall) {
-        visit_expr_call_mut(self, i)
+        visit_expr_call_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_cast_mut(&mut self, i: &mut ExprCast) {
-        visit_expr_cast_mut(self, i)
+        visit_expr_cast_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_closure_mut(&mut self, i: &mut ExprClosure) {
-        visit_expr_closure_mut(self, i)
+        visit_expr_closure_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_continue_mut(&mut self, i: &mut ExprContinue) {
-        visit_expr_continue_mut(self, i)
+        visit_expr_continue_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_field_mut(&mut self, i: &mut ExprField) {
-        visit_expr_field_mut(self, i)
+        visit_expr_field_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_for_loop_mut(&mut self, i: &mut ExprForLoop) {
-        visit_expr_for_loop_mut(self, i)
+        visit_expr_for_loop_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_group_mut(&mut self, i: &mut ExprGroup) {
-        visit_expr_group_mut(self, i)
+        visit_expr_group_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_if_mut(&mut self, i: &mut ExprIf) {
-        visit_expr_if_mut(self, i)
+        visit_expr_if_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_index_mut(&mut self, i: &mut ExprIndex) {
-        visit_expr_index_mut(self, i)
+        visit_expr_index_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_let_mut(&mut self, i: &mut ExprLet) {
-        visit_expr_let_mut(self, i)
+        visit_expr_let_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_lit_mut(&mut self, i: &mut ExprLit) {
-        visit_expr_lit_mut(self, i)
+        visit_expr_lit_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_loop_mut(&mut self, i: &mut ExprLoop) {
-        visit_expr_loop_mut(self, i)
+        visit_expr_loop_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_macro_mut(&mut self, i: &mut ExprMacro) {
-        visit_expr_macro_mut(self, i)
+        visit_expr_macro_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_match_mut(&mut self, i: &mut ExprMatch) {
-        visit_expr_match_mut(self, i)
+        visit_expr_match_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_method_call_mut(&mut self, i: &mut ExprMethodCall) {
-        visit_expr_method_call_mut(self, i)
+        visit_expr_method_call_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_paren_mut(&mut self, i: &mut ExprParen) {
-        visit_expr_paren_mut(self, i)
+        visit_expr_paren_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_path_mut(&mut self, i: &mut ExprPath) {
-        visit_expr_path_mut(self, i)
+        visit_expr_path_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_range_mut(&mut self, i: &mut ExprRange) {
-        visit_expr_range_mut(self, i)
+        visit_expr_range_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_reference_mut(&mut self, i: &mut ExprReference) {
-        visit_expr_reference_mut(self, i)
+        visit_expr_reference_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_repeat_mut(&mut self, i: &mut ExprRepeat) {
-        visit_expr_repeat_mut(self, i)
+        visit_expr_repeat_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_return_mut(&mut self, i: &mut ExprReturn) {
-        visit_expr_return_mut(self, i)
+        visit_expr_return_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_struct_mut(&mut self, i: &mut ExprStruct) {
-        visit_expr_struct_mut(self, i)
+        visit_expr_struct_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_try_mut(&mut self, i: &mut ExprTry) {
-        visit_expr_try_mut(self, i)
+        visit_expr_try_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_try_block_mut(&mut self, i: &mut ExprTryBlock) {
-        visit_expr_try_block_mut(self, i)
+        visit_expr_try_block_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_tuple_mut(&mut self, i: &mut ExprTuple) {
-        visit_expr_tuple_mut(self, i)
+        visit_expr_tuple_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_type_mut(&mut self, i: &mut ExprType) {
-        visit_expr_type_mut(self, i)
+        visit_expr_type_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_expr_unary_mut(&mut self, i: &mut ExprUnary) {
-        visit_expr_unary_mut(self, i)
+        visit_expr_unary_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_unsafe_mut(&mut self, i: &mut ExprUnsafe) {
-        visit_expr_unsafe_mut(self, i)
+        visit_expr_unsafe_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_while_mut(&mut self, i: &mut ExprWhile) {
-        visit_expr_while_mut(self, i)
+        visit_expr_while_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_expr_yield_mut(&mut self, i: &mut ExprYield) {
-        visit_expr_yield_mut(self, i)
+        visit_expr_yield_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_field_mut(&mut self, i: &mut Field) {
-        visit_field_mut(self, i)
+        visit_field_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_field_pat_mut(&mut self, i: &mut FieldPat) {
-        visit_field_pat_mut(self, i)
+        visit_field_pat_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_field_value_mut(&mut self, i: &mut FieldValue) {
-        visit_field_value_mut(self, i)
+        visit_field_value_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_fields_mut(&mut self, i: &mut Fields) {
-        visit_fields_mut(self, i)
+        visit_fields_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_fields_named_mut(&mut self, i: &mut FieldsNamed) {
-        visit_fields_named_mut(self, i)
+        visit_fields_named_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_fields_unnamed_mut(&mut self, i: &mut FieldsUnnamed) {
-        visit_fields_unnamed_mut(self, i)
+        visit_fields_unnamed_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_file_mut(&mut self, i: &mut File) {
-        visit_file_mut(self, i)
+        visit_file_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_fn_arg_mut(&mut self, i: &mut FnArg) {
-        visit_fn_arg_mut(self, i)
+        visit_fn_arg_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_foreign_item_mut(&mut self, i: &mut ForeignItem) {
-        visit_foreign_item_mut(self, i)
+        visit_foreign_item_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_foreign_item_fn_mut(&mut self, i: &mut ForeignItemFn) {
-        visit_foreign_item_fn_mut(self, i)
+        visit_foreign_item_fn_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_foreign_item_macro_mut(&mut self, i: &mut ForeignItemMacro) {
-        visit_foreign_item_macro_mut(self, i)
+        visit_foreign_item_macro_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_foreign_item_static_mut(&mut self, i: &mut ForeignItemStatic) {
-        visit_foreign_item_static_mut(self, i)
+        visit_foreign_item_static_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_foreign_item_type_mut(&mut self, i: &mut ForeignItemType) {
-        visit_foreign_item_type_mut(self, i)
+        visit_foreign_item_type_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_generic_argument_mut(&mut self, i: &mut GenericArgument) {
-        visit_generic_argument_mut(self, i)
+        visit_generic_argument_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_generic_method_argument_mut(&mut self, i: &mut GenericMethodArgument) {
-        visit_generic_method_argument_mut(self, i)
+        visit_generic_method_argument_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_generic_param_mut(&mut self, i: &mut GenericParam) {
-        visit_generic_param_mut(self, i)
+        visit_generic_param_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_generics_mut(&mut self, i: &mut Generics) {
-        visit_generics_mut(self, i)
+        visit_generics_mut(self, i);
     }
     fn visit_ident_mut(&mut self, i: &mut Ident) {
-        visit_ident_mut(self, i)
+        visit_ident_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_impl_item_mut(&mut self, i: &mut ImplItem) {
-        visit_impl_item_mut(self, i)
+        visit_impl_item_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_impl_item_const_mut(&mut self, i: &mut ImplItemConst) {
-        visit_impl_item_const_mut(self, i)
+        visit_impl_item_const_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_impl_item_macro_mut(&mut self, i: &mut ImplItemMacro) {
-        visit_impl_item_macro_mut(self, i)
+        visit_impl_item_macro_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_impl_item_method_mut(&mut self, i: &mut ImplItemMethod) {
-        visit_impl_item_method_mut(self, i)
+        visit_impl_item_method_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_impl_item_type_mut(&mut self, i: &mut ImplItemType) {
-        visit_impl_item_type_mut(self, i)
+        visit_impl_item_type_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_index_mut(&mut self, i: &mut Index) {
-        visit_index_mut(self, i)
+        visit_index_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_mut(&mut self, i: &mut Item) {
-        visit_item_mut(self, i)
+        visit_item_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_const_mut(&mut self, i: &mut ItemConst) {
-        visit_item_const_mut(self, i)
+        visit_item_const_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_enum_mut(&mut self, i: &mut ItemEnum) {
-        visit_item_enum_mut(self, i)
+        visit_item_enum_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_extern_crate_mut(&mut self, i: &mut ItemExternCrate) {
-        visit_item_extern_crate_mut(self, i)
+        visit_item_extern_crate_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_fn_mut(&mut self, i: &mut ItemFn) {
-        visit_item_fn_mut(self, i)
+        visit_item_fn_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_foreign_mod_mut(&mut self, i: &mut ItemForeignMod) {
-        visit_item_foreign_mod_mut(self, i)
+        visit_item_foreign_mod_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_impl_mut(&mut self, i: &mut ItemImpl) {
-        visit_item_impl_mut(self, i)
+        visit_item_impl_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_macro_mut(&mut self, i: &mut ItemMacro) {
-        visit_item_macro_mut(self, i)
+        visit_item_macro_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_macro2_mut(&mut self, i: &mut ItemMacro2) {
-        visit_item_macro2_mut(self, i)
+        visit_item_macro2_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_mod_mut(&mut self, i: &mut ItemMod) {
-        visit_item_mod_mut(self, i)
+        visit_item_mod_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_static_mut(&mut self, i: &mut ItemStatic) {
-        visit_item_static_mut(self, i)
+        visit_item_static_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_struct_mut(&mut self, i: &mut ItemStruct) {
-        visit_item_struct_mut(self, i)
+        visit_item_struct_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_trait_mut(&mut self, i: &mut ItemTrait) {
-        visit_item_trait_mut(self, i)
+        visit_item_trait_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_trait_alias_mut(&mut self, i: &mut ItemTraitAlias) {
-        visit_item_trait_alias_mut(self, i)
+        visit_item_trait_alias_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_type_mut(&mut self, i: &mut ItemType) {
-        visit_item_type_mut(self, i)
+        visit_item_type_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_union_mut(&mut self, i: &mut ItemUnion) {
-        visit_item_union_mut(self, i)
+        visit_item_union_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_item_use_mut(&mut self, i: &mut ItemUse) {
-        visit_item_use_mut(self, i)
+        visit_item_use_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_label_mut(&mut self, i: &mut Label) {
-        visit_label_mut(self, i)
+        visit_label_mut(self, i);
     }
     fn visit_lifetime_mut(&mut self, i: &mut Lifetime) {
-        visit_lifetime_mut(self, i)
+        visit_lifetime_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_lifetime_def_mut(&mut self, i: &mut LifetimeDef) {
-        visit_lifetime_def_mut(self, i)
+        visit_lifetime_def_mut(self, i);
     }
     fn visit_lit_mut(&mut self, i: &mut Lit) {
-        visit_lit_mut(self, i)
+        visit_lit_mut(self, i);
     }
     fn visit_lit_bool_mut(&mut self, i: &mut LitBool) {
-        visit_lit_bool_mut(self, i)
+        visit_lit_bool_mut(self, i);
     }
     fn visit_lit_byte_mut(&mut self, i: &mut LitByte) {
-        visit_lit_byte_mut(self, i)
+        visit_lit_byte_mut(self, i);
     }
     fn visit_lit_byte_str_mut(&mut self, i: &mut LitByteStr) {
-        visit_lit_byte_str_mut(self, i)
+        visit_lit_byte_str_mut(self, i);
     }
     fn visit_lit_char_mut(&mut self, i: &mut LitChar) {
-        visit_lit_char_mut(self, i)
+        visit_lit_char_mut(self, i);
     }
     fn visit_lit_float_mut(&mut self, i: &mut LitFloat) {
-        visit_lit_float_mut(self, i)
+        visit_lit_float_mut(self, i);
     }
     fn visit_lit_int_mut(&mut self, i: &mut LitInt) {
-        visit_lit_int_mut(self, i)
+        visit_lit_int_mut(self, i);
     }
     fn visit_lit_str_mut(&mut self, i: &mut LitStr) {
-        visit_lit_str_mut(self, i)
+        visit_lit_str_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_local_mut(&mut self, i: &mut Local) {
-        visit_local_mut(self, i)
+        visit_local_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_macro_mut(&mut self, i: &mut Macro) {
-        visit_macro_mut(self, i)
+        visit_macro_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_macro_delimiter_mut(&mut self, i: &mut MacroDelimiter) {
-        visit_macro_delimiter_mut(self, i)
+        visit_macro_delimiter_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_member_mut(&mut self, i: &mut Member) {
-        visit_member_mut(self, i)
+        visit_member_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_meta_mut(&mut self, i: &mut Meta) {
-        visit_meta_mut(self, i)
+        visit_meta_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_meta_list_mut(&mut self, i: &mut MetaList) {
-        visit_meta_list_mut(self, i)
+        visit_meta_list_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_meta_name_value_mut(&mut self, i: &mut MetaNameValue) {
-        visit_meta_name_value_mut(self, i)
+        visit_meta_name_value_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_method_turbofish_mut(&mut self, i: &mut MethodTurbofish) {
-        visit_method_turbofish_mut(self, i)
+        visit_method_turbofish_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_nested_meta_mut(&mut self, i: &mut NestedMeta) {
-        visit_nested_meta_mut(self, i)
+        visit_nested_meta_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_parenthesized_generic_arguments_mut(&mut self, i: &mut ParenthesizedGenericArguments) {
-        visit_parenthesized_generic_arguments_mut(self, i)
+        visit_parenthesized_generic_arguments_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_mut(&mut self, i: &mut Pat) {
-        visit_pat_mut(self, i)
+        visit_pat_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_box_mut(&mut self, i: &mut PatBox) {
-        visit_pat_box_mut(self, i)
+        visit_pat_box_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_ident_mut(&mut self, i: &mut PatIdent) {
-        visit_pat_ident_mut(self, i)
+        visit_pat_ident_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_lit_mut(&mut self, i: &mut PatLit) {
-        visit_pat_lit_mut(self, i)
+        visit_pat_lit_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_macro_mut(&mut self, i: &mut PatMacro) {
-        visit_pat_macro_mut(self, i)
+        visit_pat_macro_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_or_mut(&mut self, i: &mut PatOr) {
-        visit_pat_or_mut(self, i)
+        visit_pat_or_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_path_mut(&mut self, i: &mut PatPath) {
-        visit_pat_path_mut(self, i)
+        visit_pat_path_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_range_mut(&mut self, i: &mut PatRange) {
-        visit_pat_range_mut(self, i)
+        visit_pat_range_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_reference_mut(&mut self, i: &mut PatReference) {
-        visit_pat_reference_mut(self, i)
+        visit_pat_reference_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_rest_mut(&mut self, i: &mut PatRest) {
-        visit_pat_rest_mut(self, i)
+        visit_pat_rest_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_slice_mut(&mut self, i: &mut PatSlice) {
-        visit_pat_slice_mut(self, i)
+        visit_pat_slice_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_struct_mut(&mut self, i: &mut PatStruct) {
-        visit_pat_struct_mut(self, i)
+        visit_pat_struct_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_tuple_mut(&mut self, i: &mut PatTuple) {
-        visit_pat_tuple_mut(self, i)
+        visit_pat_tuple_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_tuple_struct_mut(&mut self, i: &mut PatTupleStruct) {
-        visit_pat_tuple_struct_mut(self, i)
+        visit_pat_tuple_struct_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_type_mut(&mut self, i: &mut PatType) {
-        visit_pat_type_mut(self, i)
+        visit_pat_type_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_pat_wild_mut(&mut self, i: &mut PatWild) {
-        visit_pat_wild_mut(self, i)
+        visit_pat_wild_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_path_mut(&mut self, i: &mut Path) {
-        visit_path_mut(self, i)
+        visit_path_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_path_arguments_mut(&mut self, i: &mut PathArguments) {
-        visit_path_arguments_mut(self, i)
+        visit_path_arguments_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_path_segment_mut(&mut self, i: &mut PathSegment) {
-        visit_path_segment_mut(self, i)
+        visit_path_segment_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_predicate_eq_mut(&mut self, i: &mut PredicateEq) {
-        visit_predicate_eq_mut(self, i)
+        visit_predicate_eq_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_predicate_lifetime_mut(&mut self, i: &mut PredicateLifetime) {
-        visit_predicate_lifetime_mut(self, i)
+        visit_predicate_lifetime_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_predicate_type_mut(&mut self, i: &mut PredicateType) {
-        visit_predicate_type_mut(self, i)
+        visit_predicate_type_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_qself_mut(&mut self, i: &mut QSelf) {
-        visit_qself_mut(self, i)
+        visit_qself_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_range_limits_mut(&mut self, i: &mut RangeLimits) {
-        visit_range_limits_mut(self, i)
+        visit_range_limits_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_receiver_mut(&mut self, i: &mut Receiver) {
-        visit_receiver_mut(self, i)
+        visit_receiver_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_return_type_mut(&mut self, i: &mut ReturnType) {
-        visit_return_type_mut(self, i)
+        visit_return_type_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_signature_mut(&mut self, i: &mut Signature) {
-        visit_signature_mut(self, i)
+        visit_signature_mut(self, i);
     }
     fn visit_span_mut(&mut self, i: &mut Span) {
-        visit_span_mut(self, i)
+        visit_span_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_stmt_mut(&mut self, i: &mut Stmt) {
-        visit_stmt_mut(self, i)
+        visit_stmt_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_trait_bound_mut(&mut self, i: &mut TraitBound) {
-        visit_trait_bound_mut(self, i)
+        visit_trait_bound_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_trait_bound_modifier_mut(&mut self, i: &mut TraitBoundModifier) {
-        visit_trait_bound_modifier_mut(self, i)
+        visit_trait_bound_modifier_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_trait_item_mut(&mut self, i: &mut TraitItem) {
-        visit_trait_item_mut(self, i)
+        visit_trait_item_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_trait_item_const_mut(&mut self, i: &mut TraitItemConst) {
-        visit_trait_item_const_mut(self, i)
+        visit_trait_item_const_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_trait_item_macro_mut(&mut self, i: &mut TraitItemMacro) {
-        visit_trait_item_macro_mut(self, i)
+        visit_trait_item_macro_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_trait_item_method_mut(&mut self, i: &mut TraitItemMethod) {
-        visit_trait_item_method_mut(self, i)
+        visit_trait_item_method_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_trait_item_type_mut(&mut self, i: &mut TraitItemType) {
-        visit_trait_item_type_mut(self, i)
+        visit_trait_item_type_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_mut(&mut self, i: &mut Type) {
-        visit_type_mut(self, i)
+        visit_type_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_array_mut(&mut self, i: &mut TypeArray) {
-        visit_type_array_mut(self, i)
+        visit_type_array_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_bare_fn_mut(&mut self, i: &mut TypeBareFn) {
-        visit_type_bare_fn_mut(self, i)
+        visit_type_bare_fn_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_group_mut(&mut self, i: &mut TypeGroup) {
-        visit_type_group_mut(self, i)
+        visit_type_group_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_impl_trait_mut(&mut self, i: &mut TypeImplTrait) {
-        visit_type_impl_trait_mut(self, i)
+        visit_type_impl_trait_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_infer_mut(&mut self, i: &mut TypeInfer) {
-        visit_type_infer_mut(self, i)
+        visit_type_infer_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_macro_mut(&mut self, i: &mut TypeMacro) {
-        visit_type_macro_mut(self, i)
+        visit_type_macro_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_never_mut(&mut self, i: &mut TypeNever) {
-        visit_type_never_mut(self, i)
+        visit_type_never_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_param_mut(&mut self, i: &mut TypeParam) {
-        visit_type_param_mut(self, i)
+        visit_type_param_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_param_bound_mut(&mut self, i: &mut TypeParamBound) {
-        visit_type_param_bound_mut(self, i)
+        visit_type_param_bound_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_paren_mut(&mut self, i: &mut TypeParen) {
-        visit_type_paren_mut(self, i)
+        visit_type_paren_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_path_mut(&mut self, i: &mut TypePath) {
-        visit_type_path_mut(self, i)
+        visit_type_path_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_ptr_mut(&mut self, i: &mut TypePtr) {
-        visit_type_ptr_mut(self, i)
+        visit_type_ptr_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_reference_mut(&mut self, i: &mut TypeReference) {
-        visit_type_reference_mut(self, i)
+        visit_type_reference_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_slice_mut(&mut self, i: &mut TypeSlice) {
-        visit_type_slice_mut(self, i)
+        visit_type_slice_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_trait_object_mut(&mut self, i: &mut TypeTraitObject) {
-        visit_type_trait_object_mut(self, i)
+        visit_type_trait_object_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_type_tuple_mut(&mut self, i: &mut TypeTuple) {
-        visit_type_tuple_mut(self, i)
+        visit_type_tuple_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_un_op_mut(&mut self, i: &mut UnOp) {
-        visit_un_op_mut(self, i)
+        visit_un_op_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_use_glob_mut(&mut self, i: &mut UseGlob) {
-        visit_use_glob_mut(self, i)
+        visit_use_glob_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_use_group_mut(&mut self, i: &mut UseGroup) {
-        visit_use_group_mut(self, i)
+        visit_use_group_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_use_name_mut(&mut self, i: &mut UseName) {
-        visit_use_name_mut(self, i)
+        visit_use_name_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_use_path_mut(&mut self, i: &mut UsePath) {
-        visit_use_path_mut(self, i)
+        visit_use_path_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_use_rename_mut(&mut self, i: &mut UseRename) {
-        visit_use_rename_mut(self, i)
+        visit_use_rename_mut(self, i);
     }
     #[cfg(feature = "full")]
     fn visit_use_tree_mut(&mut self, i: &mut UseTree) {
-        visit_use_tree_mut(self, i)
+        visit_use_tree_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_variadic_mut(&mut self, i: &mut Variadic) {
-        visit_variadic_mut(self, i)
+        visit_variadic_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_variant_mut(&mut self, i: &mut Variant) {
-        visit_variant_mut(self, i)
+        visit_variant_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_vis_crate_mut(&mut self, i: &mut VisCrate) {
-        visit_vis_crate_mut(self, i)
+        visit_vis_crate_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_vis_public_mut(&mut self, i: &mut VisPublic) {
-        visit_vis_public_mut(self, i)
+        visit_vis_public_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_vis_restricted_mut(&mut self, i: &mut VisRestricted) {
-        visit_vis_restricted_mut(self, i)
+        visit_vis_restricted_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_visibility_mut(&mut self, i: &mut Visibility) {
-        visit_visibility_mut(self, i)
+        visit_visibility_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_where_clause_mut(&mut self, i: &mut WhereClause) {
-        visit_where_clause_mut(self, i)
+        visit_where_clause_mut(self, i);
     }
     #[cfg(any(feature = "derive", feature = "full"))]
     fn visit_where_predicate_mut(&mut self, i: &mut WherePredicate) {
-        visit_where_predicate_mut(self, i)
+        visit_where_predicate_mut(self, i);
     }
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -780,7 +780,7 @@ where
 {
     tokens_helper(v, &mut node.extern_token.span);
     if let Some(it) = &mut node.name {
-        v.visit_lit_str_mut(it)
+        v.visit_lit_str_mut(it);
     };
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -791,7 +791,7 @@ pub fn visit_angle_bracketed_generic_arguments_mut<V>(
     V: VisitMut + ?Sized,
 {
     if let Some(it) = &mut node.colon2_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     tokens_helper(v, &mut node.lt_token.spans);
     for el in Punctuated::pairs_mut(&mut node.args) {
@@ -809,7 +809,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_pat_mut(&mut node.pat);
     if let Some(it) = &mut node.guard {
@@ -819,7 +819,7 @@ where
     tokens_helper(v, &mut node.fat_arrow_token.spans);
     v.visit_expr_mut(&mut *node.body);
     if let Some(it) = &mut node.comma {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -851,7 +851,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     if let Some(it) = &mut node.name {
         v.visit_ident_mut(&mut (it).0);
@@ -967,7 +967,7 @@ where
 {
     tokens_helper(v, &mut node.brace_token.span);
     for it in &mut node.stmts {
-        v.visit_stmt_mut(it)
+        v.visit_stmt_mut(it);
     }
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -992,17 +992,17 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.const_token.span);
     v.visit_ident_mut(&mut node.ident);
     tokens_helper(v, &mut node.colon_token.spans);
     v.visit_type_mut(&mut node.ty);
     if let Some(it) = &mut node.eq_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     if let Some(it) = &mut node.default {
-        v.visit_expr_mut(it)
+        v.visit_expr_mut(it);
     };
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -1060,7 +1060,7 @@ where
     tokens_helper(v, &mut node.struct_token.span);
     v.visit_fields_mut(&mut node.fields);
     if let Some(it) = &mut node.semi_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
 }
 #[cfg(feature = "derive")]
@@ -1077,7 +1077,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     v.visit_ident_mut(&mut node.ident);
@@ -1219,7 +1219,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.bracket_token.span);
     for el in Punctuated::pairs_mut(&mut node.elems) {
@@ -1236,7 +1236,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_expr_mut(&mut *node.left);
     tokens_helper(v, &mut node.eq_token.spans);
@@ -1248,7 +1248,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_expr_mut(&mut *node.left);
     v.visit_bin_op_mut(&mut node.op);
@@ -1260,11 +1260,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.async_token.span);
     if let Some(it) = &mut node.capture {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     v.visit_block_mut(&mut node.block);
 }
@@ -1274,7 +1274,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_expr_mut(&mut *node.base);
     tokens_helper(v, &mut node.dot_token.spans);
@@ -1286,7 +1286,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_expr_mut(&mut *node.left);
     v.visit_bin_op_mut(&mut node.op);
@@ -1298,10 +1298,10 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     if let Some(it) = &mut node.label {
-        v.visit_label_mut(it)
+        v.visit_label_mut(it);
     };
     v.visit_block_mut(&mut node.block);
 }
@@ -1311,7 +1311,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.box_token.span);
     v.visit_expr_mut(&mut *node.expr);
@@ -1322,14 +1322,14 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.break_token.span);
     if let Some(it) = &mut node.label {
-        v.visit_lifetime_mut(it)
+        v.visit_lifetime_mut(it);
     };
     if let Some(it) = &mut node.expr {
-        v.visit_expr_mut(&mut **it)
+        v.visit_expr_mut(&mut **it);
     };
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -1338,7 +1338,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_expr_mut(&mut *node.func);
     tokens_helper(v, &mut node.paren_token.span);
@@ -1356,7 +1356,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_expr_mut(&mut *node.expr);
     tokens_helper(v, &mut node.as_token.span);
@@ -1368,16 +1368,16 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     if let Some(it) = &mut node.asyncness {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     if let Some(it) = &mut node.movability {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     if let Some(it) = &mut node.capture {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     tokens_helper(v, &mut node.or1_token.spans);
     for el in Punctuated::pairs_mut(&mut node.inputs) {
@@ -1397,11 +1397,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.continue_token.span);
     if let Some(it) = &mut node.label {
-        v.visit_lifetime_mut(it)
+        v.visit_lifetime_mut(it);
     };
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -1410,7 +1410,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_expr_mut(&mut *node.base);
     tokens_helper(v, &mut node.dot_token.spans);
@@ -1422,10 +1422,10 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     if let Some(it) = &mut node.label {
-        v.visit_label_mut(it)
+        v.visit_label_mut(it);
     };
     tokens_helper(v, &mut node.for_token.span);
     v.visit_pat_mut(&mut node.pat);
@@ -1439,7 +1439,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.group_token.span);
     v.visit_expr_mut(&mut *node.expr);
@@ -1450,7 +1450,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.if_token.span);
     v.visit_expr_mut(&mut *node.cond);
@@ -1466,7 +1466,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_expr_mut(&mut *node.expr);
     tokens_helper(v, &mut node.bracket_token.span);
@@ -1478,7 +1478,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.let_token.span);
     v.visit_pat_mut(&mut node.pat);
@@ -1491,7 +1491,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_lit_mut(&mut node.lit);
 }
@@ -1501,10 +1501,10 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     if let Some(it) = &mut node.label {
-        v.visit_label_mut(it)
+        v.visit_label_mut(it);
     };
     tokens_helper(v, &mut node.loop_token.span);
     v.visit_block_mut(&mut node.body);
@@ -1515,7 +1515,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_macro_mut(&mut node.mac);
 }
@@ -1525,13 +1525,13 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.match_token.span);
     v.visit_expr_mut(&mut *node.expr);
     tokens_helper(v, &mut node.brace_token.span);
     for it in &mut node.arms {
-        v.visit_arm_mut(it)
+        v.visit_arm_mut(it);
     }
 }
 #[cfg(feature = "full")]
@@ -1540,13 +1540,13 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_expr_mut(&mut *node.receiver);
     tokens_helper(v, &mut node.dot_token.spans);
     v.visit_ident_mut(&mut node.method);
     if let Some(it) = &mut node.turbofish {
-        v.visit_method_turbofish_mut(it)
+        v.visit_method_turbofish_mut(it);
     };
     tokens_helper(v, &mut node.paren_token.span);
     for el in Punctuated::pairs_mut(&mut node.args) {
@@ -1563,7 +1563,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.paren_token.span);
     v.visit_expr_mut(&mut *node.expr);
@@ -1574,10 +1574,10 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     if let Some(it) = &mut node.qself {
-        v.visit_qself_mut(it)
+        v.visit_qself_mut(it);
     };
     v.visit_path_mut(&mut node.path);
 }
@@ -1587,14 +1587,14 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     if let Some(it) = &mut node.from {
-        v.visit_expr_mut(&mut **it)
+        v.visit_expr_mut(&mut **it);
     };
     v.visit_range_limits_mut(&mut node.limits);
     if let Some(it) = &mut node.to {
-        v.visit_expr_mut(&mut **it)
+        v.visit_expr_mut(&mut **it);
     };
 }
 #[cfg(feature = "full")]
@@ -1603,11 +1603,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.and_token.spans);
     if let Some(it) = &mut node.mutability {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     v.visit_expr_mut(&mut *node.expr);
 }
@@ -1617,7 +1617,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.bracket_token.span);
     v.visit_expr_mut(&mut *node.expr);
@@ -1630,11 +1630,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.return_token.span);
     if let Some(it) = &mut node.expr {
-        v.visit_expr_mut(&mut **it)
+        v.visit_expr_mut(&mut **it);
     };
 }
 #[cfg(feature = "full")]
@@ -1643,7 +1643,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_path_mut(&mut node.path);
     tokens_helper(v, &mut node.brace_token.span);
@@ -1655,10 +1655,10 @@ where
         }
     }
     if let Some(it) = &mut node.dot2_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     if let Some(it) = &mut node.rest {
-        v.visit_expr_mut(&mut **it)
+        v.visit_expr_mut(&mut **it);
     };
 }
 #[cfg(feature = "full")]
@@ -1667,7 +1667,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_expr_mut(&mut *node.expr);
     tokens_helper(v, &mut node.question_token.spans);
@@ -1678,7 +1678,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.try_token.span);
     v.visit_block_mut(&mut node.block);
@@ -1689,7 +1689,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.paren_token.span);
     for el in Punctuated::pairs_mut(&mut node.elems) {
@@ -1706,7 +1706,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_expr_mut(&mut *node.expr);
     tokens_helper(v, &mut node.colon_token.spans);
@@ -1718,7 +1718,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_un_op_mut(&mut node.op);
     v.visit_expr_mut(&mut *node.expr);
@@ -1729,7 +1729,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.unsafe_token.span);
     v.visit_block_mut(&mut node.block);
@@ -1740,10 +1740,10 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     if let Some(it) = &mut node.label {
-        v.visit_label_mut(it)
+        v.visit_label_mut(it);
     };
     tokens_helper(v, &mut node.while_token.span);
     v.visit_expr_mut(&mut *node.cond);
@@ -1755,11 +1755,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.yield_token.span);
     if let Some(it) = &mut node.expr {
-        v.visit_expr_mut(&mut **it)
+        v.visit_expr_mut(&mut **it);
     };
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -1768,14 +1768,14 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     if let Some(it) = &mut node.ident {
-        v.visit_ident_mut(it)
+        v.visit_ident_mut(it);
     };
     if let Some(it) = &mut node.colon_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     v.visit_type_mut(&mut node.ty);
 }
@@ -1785,11 +1785,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_member_mut(&mut node.member);
     if let Some(it) = &mut node.colon_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     v.visit_pat_mut(&mut *node.pat);
 }
@@ -1799,11 +1799,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_member_mut(&mut node.member);
     if let Some(it) = &mut node.colon_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     v.visit_expr_mut(&mut node.expr);
 }
@@ -1857,10 +1857,10 @@ where
 {
     skip!(node.shebang);
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     for it in &mut node.items {
-        v.visit_item_mut(it)
+        v.visit_item_mut(it);
     }
 }
 #[cfg(feature = "full")]
@@ -1907,7 +1907,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     v.visit_signature_mut(&mut node.sig);
@@ -1919,11 +1919,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_macro_mut(&mut node.mac);
     if let Some(it) = &mut node.semi_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -1932,12 +1932,12 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     tokens_helper(v, &mut node.static_token.span);
     if let Some(it) = &mut node.mutability {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     v.visit_ident_mut(&mut node.ident);
     tokens_helper(v, &mut node.colon_token.spans);
@@ -1950,7 +1950,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     tokens_helper(v, &mut node.type_token.span);
@@ -2017,7 +2017,7 @@ where
     V: VisitMut + ?Sized,
 {
     if let Some(it) = &mut node.lt_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     for el in Punctuated::pairs_mut(&mut node.params) {
         let (it, p) = el.into_tuple();
@@ -2027,10 +2027,10 @@ where
         }
     }
     if let Some(it) = &mut node.gt_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     if let Some(it) = &mut node.where_clause {
-        v.visit_where_clause_mut(it)
+        v.visit_where_clause_mut(it);
     };
 }
 pub fn visit_ident_mut<V>(v: &mut V, node: &mut Ident)
@@ -2071,11 +2071,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     if let Some(it) = &mut node.defaultness {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     tokens_helper(v, &mut node.const_token.span);
     v.visit_ident_mut(&mut node.ident);
@@ -2091,11 +2091,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_macro_mut(&mut node.mac);
     if let Some(it) = &mut node.semi_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -2104,11 +2104,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     if let Some(it) = &mut node.defaultness {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     v.visit_signature_mut(&mut node.sig);
     v.visit_block_mut(&mut node.block);
@@ -2119,11 +2119,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     if let Some(it) = &mut node.defaultness {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     tokens_helper(v, &mut node.type_token.span);
     v.visit_ident_mut(&mut node.ident);
@@ -2206,7 +2206,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     tokens_helper(v, &mut node.const_token.span);
@@ -2223,7 +2223,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     tokens_helper(v, &mut node.enum_token.span);
@@ -2244,7 +2244,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     tokens_helper(v, &mut node.extern_token.span);
@@ -2262,7 +2262,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     v.visit_signature_mut(&mut node.sig);
@@ -2274,12 +2274,12 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_abi_mut(&mut node.abi);
     tokens_helper(v, &mut node.brace_token.span);
     for it in &mut node.items {
-        v.visit_foreign_item_mut(it)
+        v.visit_foreign_item_mut(it);
     }
 }
 #[cfg(feature = "full")]
@@ -2288,19 +2288,19 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     if let Some(it) = &mut node.defaultness {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     if let Some(it) = &mut node.unsafety {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     tokens_helper(v, &mut node.impl_token.span);
     v.visit_generics_mut(&mut node.generics);
     if let Some(it) = &mut node.trait_ {
         if let Some(it) = &mut (it).0 {
-            tokens_helper(v, &mut it.spans)
+            tokens_helper(v, &mut it.spans);
         };
         v.visit_path_mut(&mut (it).1);
         tokens_helper(v, &mut (it).2.span);
@@ -2308,7 +2308,7 @@ where
     v.visit_type_mut(&mut *node.self_ty);
     tokens_helper(v, &mut node.brace_token.span);
     for it in &mut node.items {
-        v.visit_impl_item_mut(it)
+        v.visit_impl_item_mut(it);
     }
 }
 #[cfg(feature = "full")]
@@ -2317,14 +2317,14 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     if let Some(it) = &mut node.ident {
-        v.visit_ident_mut(it)
+        v.visit_ident_mut(it);
     };
     v.visit_macro_mut(&mut node.mac);
     if let Some(it) = &mut node.semi_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -2333,7 +2333,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     tokens_helper(v, &mut node.macro_token.span);
@@ -2346,7 +2346,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     tokens_helper(v, &mut node.mod_token.span);
@@ -2354,11 +2354,11 @@ where
     if let Some(it) = &mut node.content {
         tokens_helper(v, &mut (it).0.span);
         for it in &mut (it).1 {
-            v.visit_item_mut(it)
+            v.visit_item_mut(it);
         }
     };
     if let Some(it) = &mut node.semi {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -2367,12 +2367,12 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     tokens_helper(v, &mut node.static_token.span);
     if let Some(it) = &mut node.mutability {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     v.visit_ident_mut(&mut node.ident);
     tokens_helper(v, &mut node.colon_token.spans);
@@ -2387,7 +2387,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     tokens_helper(v, &mut node.struct_token.span);
@@ -2395,7 +2395,7 @@ where
     v.visit_generics_mut(&mut node.generics);
     v.visit_fields_mut(&mut node.fields);
     if let Some(it) = &mut node.semi_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -2404,20 +2404,20 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     if let Some(it) = &mut node.unsafety {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     if let Some(it) = &mut node.auto_token {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     tokens_helper(v, &mut node.trait_token.span);
     v.visit_ident_mut(&mut node.ident);
     v.visit_generics_mut(&mut node.generics);
     if let Some(it) = &mut node.colon_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     for el in Punctuated::pairs_mut(&mut node.supertraits) {
         let (it, p) = el.into_tuple();
@@ -2428,7 +2428,7 @@ where
     }
     tokens_helper(v, &mut node.brace_token.span);
     for it in &mut node.items {
-        v.visit_trait_item_mut(it)
+        v.visit_trait_item_mut(it);
     }
 }
 #[cfg(feature = "full")]
@@ -2437,7 +2437,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     tokens_helper(v, &mut node.trait_token.span);
@@ -2459,7 +2459,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     tokens_helper(v, &mut node.type_token.span);
@@ -2475,7 +2475,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     tokens_helper(v, &mut node.union_token.span);
@@ -2489,12 +2489,12 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_visibility_mut(&mut node.vis);
     tokens_helper(v, &mut node.use_token.span);
     if let Some(it) = &mut node.leading_colon {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     v.visit_use_tree_mut(&mut node.tree);
     tokens_helper(v, &mut node.semi_token.spans);
@@ -2520,11 +2520,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_lifetime_mut(&mut node.lifetime);
     if let Some(it) = &mut node.colon_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     for el in Punctuated::pairs_mut(&mut node.bounds) {
         let (it, p) = el.into_tuple();
@@ -2608,7 +2608,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.let_token.span);
     v.visit_pat_mut(&mut node.pat);
@@ -2810,7 +2810,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.box_token.span);
     v.visit_pat_mut(&mut *node.pat);
@@ -2821,13 +2821,13 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     if let Some(it) = &mut node.by_ref {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     if let Some(it) = &mut node.mutability {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     v.visit_ident_mut(&mut node.ident);
     if let Some(it) = &mut node.subpat {
@@ -2841,7 +2841,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_expr_mut(&mut *node.expr);
 }
@@ -2851,7 +2851,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_macro_mut(&mut node.mac);
 }
@@ -2861,10 +2861,10 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     if let Some(it) = &mut node.leading_vert {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     for el in Punctuated::pairs_mut(&mut node.cases) {
         let (it, p) = el.into_tuple();
@@ -2880,10 +2880,10 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     if let Some(it) = &mut node.qself {
-        v.visit_qself_mut(it)
+        v.visit_qself_mut(it);
     };
     v.visit_path_mut(&mut node.path);
 }
@@ -2893,7 +2893,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_expr_mut(&mut *node.lo);
     v.visit_range_limits_mut(&mut node.limits);
@@ -2905,11 +2905,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.and_token.spans);
     if let Some(it) = &mut node.mutability {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     v.visit_pat_mut(&mut *node.pat);
 }
@@ -2919,7 +2919,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.dot2_token.spans);
 }
@@ -2929,7 +2929,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.bracket_token.span);
     for el in Punctuated::pairs_mut(&mut node.elems) {
@@ -2946,7 +2946,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_path_mut(&mut node.path);
     tokens_helper(v, &mut node.brace_token.span);
@@ -2958,7 +2958,7 @@ where
         }
     }
     if let Some(it) = &mut node.dot2_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -2967,7 +2967,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.paren_token.span);
     for el in Punctuated::pairs_mut(&mut node.elems) {
@@ -2984,7 +2984,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_path_mut(&mut node.path);
     v.visit_pat_tuple_mut(&mut node.pat);
@@ -2995,7 +2995,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_pat_mut(&mut *node.pat);
     tokens_helper(v, &mut node.colon_token.spans);
@@ -3007,7 +3007,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.underscore_token.spans);
 }
@@ -3017,7 +3017,7 @@ where
     V: VisitMut + ?Sized,
 {
     if let Some(it) = &mut node.leading_colon {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     for el in Punctuated::pairs_mut(&mut node.segments) {
         let (it, p) = el.into_tuple();
@@ -3080,7 +3080,7 @@ where
     V: VisitMut + ?Sized,
 {
     if let Some(it) = &mut node.lifetimes {
-        v.visit_bound_lifetimes_mut(it)
+        v.visit_bound_lifetimes_mut(it);
     };
     v.visit_type_mut(&mut node.bounded_ty);
     tokens_helper(v, &mut node.colon_token.spans);
@@ -3101,7 +3101,7 @@ where
     v.visit_type_mut(&mut *node.ty);
     skip!(node.position);
     if let Some(it) = &mut node.as_token {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     tokens_helper(v, &mut node.gt_token.spans);
 }
@@ -3125,16 +3125,16 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     if let Some(it) = &mut node.reference {
         tokens_helper(v, &mut (it).0.spans);
         if let Some(it) = &mut (it).1 {
-            v.visit_lifetime_mut(it)
+            v.visit_lifetime_mut(it);
         };
     };
     if let Some(it) = &mut node.mutability {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     tokens_helper(v, &mut node.self_token.span);
 }
@@ -3157,16 +3157,16 @@ where
     V: VisitMut + ?Sized,
 {
     if let Some(it) = &mut node.constness {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     if let Some(it) = &mut node.asyncness {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     if let Some(it) = &mut node.unsafety {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     if let Some(it) = &mut node.abi {
-        v.visit_abi_mut(it)
+        v.visit_abi_mut(it);
     };
     tokens_helper(v, &mut node.fn_token.span);
     v.visit_ident_mut(&mut node.ident);
@@ -3180,7 +3180,7 @@ where
         }
     }
     if let Some(it) = &mut node.variadic {
-        v.visit_variadic_mut(it)
+        v.visit_variadic_mut(it);
     };
     v.visit_return_type_mut(&mut node.output);
 }
@@ -3216,11 +3216,11 @@ where
     V: VisitMut + ?Sized,
 {
     if let Some(it) = &mut node.paren_token {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     v.visit_trait_bound_modifier_mut(&mut node.modifier);
     if let Some(it) = &mut node.lifetimes {
-        v.visit_bound_lifetimes_mut(it)
+        v.visit_bound_lifetimes_mut(it);
     };
     v.visit_path_mut(&mut node.path);
 }
@@ -3266,7 +3266,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.const_token.span);
     v.visit_ident_mut(&mut node.ident);
@@ -3284,11 +3284,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_macro_mut(&mut node.mac);
     if let Some(it) = &mut node.semi_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -3297,14 +3297,14 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_signature_mut(&mut node.sig);
     if let Some(it) = &mut node.default {
-        v.visit_block_mut(it)
+        v.visit_block_mut(it);
     };
     if let Some(it) = &mut node.semi_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
 }
 #[cfg(feature = "full")]
@@ -3313,13 +3313,13 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.type_token.span);
     v.visit_ident_mut(&mut node.ident);
     v.visit_generics_mut(&mut node.generics);
     if let Some(it) = &mut node.colon_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     for el in Punctuated::pairs_mut(&mut node.bounds) {
         let (it, p) = el.into_tuple();
@@ -3404,13 +3404,13 @@ where
     V: VisitMut + ?Sized,
 {
     if let Some(it) = &mut node.lifetimes {
-        v.visit_bound_lifetimes_mut(it)
+        v.visit_bound_lifetimes_mut(it);
     };
     if let Some(it) = &mut node.unsafety {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     if let Some(it) = &mut node.abi {
-        v.visit_abi_mut(it)
+        v.visit_abi_mut(it);
     };
     tokens_helper(v, &mut node.fn_token.span);
     tokens_helper(v, &mut node.paren_token.span);
@@ -3422,7 +3422,7 @@ where
         }
     }
     if let Some(it) = &mut node.variadic {
-        v.visit_variadic_mut(it)
+        v.visit_variadic_mut(it);
     };
     v.visit_return_type_mut(&mut node.output);
 }
@@ -3475,11 +3475,11 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_ident_mut(&mut node.ident);
     if let Some(it) = &mut node.colon_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     for el in Punctuated::pairs_mut(&mut node.bounds) {
         let (it, p) = el.into_tuple();
@@ -3489,10 +3489,10 @@ where
         }
     }
     if let Some(it) = &mut node.eq_token {
-        tokens_helper(v, &mut it.spans)
+        tokens_helper(v, &mut it.spans);
     };
     if let Some(it) = &mut node.default {
-        v.visit_type_mut(it)
+        v.visit_type_mut(it);
     };
 }
 #[cfg(any(feature = "derive", feature = "full"))]
@@ -3523,7 +3523,7 @@ where
     V: VisitMut + ?Sized,
 {
     if let Some(it) = &mut node.qself {
-        v.visit_qself_mut(it)
+        v.visit_qself_mut(it);
     };
     v.visit_path_mut(&mut node.path);
 }
@@ -3534,10 +3534,10 @@ where
 {
     tokens_helper(v, &mut node.star_token.spans);
     if let Some(it) = &mut node.const_token {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     if let Some(it) = &mut node.mutability {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     v.visit_type_mut(&mut *node.elem);
 }
@@ -3548,10 +3548,10 @@ where
 {
     tokens_helper(v, &mut node.and_token.spans);
     if let Some(it) = &mut node.lifetime {
-        v.visit_lifetime_mut(it)
+        v.visit_lifetime_mut(it);
     };
     if let Some(it) = &mut node.mutability {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     v.visit_type_mut(&mut *node.elem);
 }
@@ -3569,7 +3569,7 @@ where
     V: VisitMut + ?Sized,
 {
     if let Some(it) = &mut node.dyn_token {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     for el in Punctuated::pairs_mut(&mut node.bounds) {
         let (it, p) = el.into_tuple();
@@ -3685,7 +3685,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     tokens_helper(v, &mut node.dots.spans);
 }
@@ -3695,7 +3695,7 @@ where
     V: VisitMut + ?Sized,
 {
     for it in &mut node.attrs {
-        v.visit_attribute_mut(it)
+        v.visit_attribute_mut(it);
     }
     v.visit_ident_mut(&mut node.ident);
     v.visit_fields_mut(&mut node.fields);
@@ -3726,7 +3726,7 @@ where
     tokens_helper(v, &mut node.pub_token.span);
     tokens_helper(v, &mut node.paren_token.span);
     if let Some(it) = &mut node.in_token {
-        tokens_helper(v, &mut it.span)
+        tokens_helper(v, &mut it.span);
     };
     v.visit_path_mut(&mut *node.path);
 }
index 28ccf8dd9a4ec9d4c71284ab32d378ac86e8e0c4..acc56f86161b898c50780840ef2000af9988177b 100644 (file)
@@ -2512,7 +2512,7 @@ pub mod parsing {
                 if let Type::Path(TypePath { qself: None, path }) = first_ty {
                     trait_ = Some((polarity, path, for_token));
                 } else {
-                    unreachable!()
+                    unreachable!();
                 }
             } else if !allow_verbatim_impl {
                 #[cfg(feature = "printing")]
index 6816025a3e050d39999fe575aa1c3f6f24d55265..fa302ad18be682285abb58a7ad862d294960528b 100644 (file)
 //!   dynamic library libproc_macro from rustc toolchain.
 
 // Syn types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/syn/1.0.72")]
+#![doc(html_root_url = "https://docs.rs/syn/1.0.73")]
 #![cfg_attr(doc_cfg, feature(doc_cfg))]
 #![allow(non_camel_case_types)]
 // Ignored clippy lints.
index 28cd7e36222126ca8859c968bf841ec8462c8ed5..5dc1753a84fa49851efbf996224895cf16a5b02e 100644 (file)
@@ -108,7 +108,7 @@ impl Ord for Lifetime {
 
 impl Hash for Lifetime {
     fn hash<H: Hasher>(&self, h: &mut H) {
-        self.ident.hash(h)
+        self.ident.hash(h);
     }
 }
 
index d74e1225c472592d9c26d1e57d377210e71d3376..9ea2e8c0780481ab35c8596dd1af50e883261c35 100644 (file)
@@ -238,7 +238,7 @@ impl LitStr {
     }
 
     pub fn set_span(&mut self, span: Span) {
-        self.repr.token.set_span(span)
+        self.repr.token.set_span(span);
     }
 
     pub fn suffix(&self) -> &str {
@@ -269,7 +269,7 @@ impl LitByteStr {
     }
 
     pub fn set_span(&mut self, span: Span) {
-        self.repr.token.set_span(span)
+        self.repr.token.set_span(span);
     }
 
     pub fn suffix(&self) -> &str {
@@ -300,7 +300,7 @@ impl LitByte {
     }
 
     pub fn set_span(&mut self, span: Span) {
-        self.repr.token.set_span(span)
+        self.repr.token.set_span(span);
     }
 
     pub fn suffix(&self) -> &str {
@@ -331,7 +331,7 @@ impl LitChar {
     }
 
     pub fn set_span(&mut self, span: Span) {
-        self.repr.token.set_span(span)
+        self.repr.token.set_span(span);
     }
 
     pub fn suffix(&self) -> &str {
@@ -406,7 +406,7 @@ impl LitInt {
     }
 
     pub fn set_span(&mut self, span: Span) {
-        self.repr.token.set_span(span)
+        self.repr.token.set_span(span);
     }
 }
 
@@ -478,7 +478,7 @@ impl LitFloat {
     }
 
     pub fn set_span(&mut self, span: Span) {
-        self.repr.token.set_span(span)
+        self.repr.token.set_span(span);
     }
 }
 
@@ -1437,7 +1437,7 @@ mod value {
         }
 
         let suffix = s;
-        if suffix.is_empty() || crate::ident::xid_ok(&suffix) {
+        if suffix.is_empty() || crate::ident::xid_ok(suffix) {
             let mut repr = value.to_string();
             if negative {
                 repr.insert(0, '-');
index f94edc291552d43678beb8a00f67ea789ed85646..5cf5235e5bfb503e6b7e1cb69357825f23bf3942 100644 (file)
@@ -1017,7 +1017,7 @@ mod printing {
         P: ToTokens,
     {
         fn to_tokens(&self, tokens: &mut TokenStream) {
-            tokens.append_all(self.pairs())
+            tokens.append_all(self.pairs());
         }
     }
 
index d632db83242cb89ce1a62bd983aece597e8dfe86..3c283ca4ada549e5e952bfd6888bf2cdb9005079 100644 (file)
@@ -8,7 +8,7 @@ use rustc_ast::ast::{
     BinOpKind, BindingMode, Block, BlockCheckMode, BorrowKind, CaptureBy, Const, Crate, CrateSugar,
     Defaultness, EnumDef, Expr, ExprField, ExprKind, Extern, FieldDef, FloatTy, FnDecl, FnHeader,
     FnKind, FnRetTy, FnSig, ForeignItemKind, ForeignMod, GenericArg, GenericArgs, GenericBound,
-    GenericParam, GenericParamKind, Generics, GlobalAsm, ImplKind, ImplPolarity, Inline, InlineAsm,
+    GenericParam, GenericParamKind, Generics, ImplKind, ImplPolarity, Inline, InlineAsm,
     InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass, InlineAsmTemplatePiece, IntTy,
     IsAuto, Item, ItemKind, Label, Lifetime, Lit, LitFloatType, LitIntType, LitKind,
     LlvmAsmDialect, LlvmInlineAsm, LlvmInlineAsmOutput, Local, MacArgs, MacCall, MacCallStmt,
@@ -307,7 +307,6 @@ spanless_eq_struct!(FnSig; header decl span);
 spanless_eq_struct!(ForeignMod; unsafety abi items);
 spanless_eq_struct!(GenericParam; id ident attrs bounds is_placeholder kind);
 spanless_eq_struct!(Generics; params where_clause span);
-spanless_eq_struct!(GlobalAsm; asm);
 spanless_eq_struct!(ImplKind; unsafety polarity defaultness constness generics of_trait self_ty items);
 spanless_eq_struct!(InlineAsm; template operands options line_spans);
 spanless_eq_struct!(Item<K>; attrs id span vis ident kind !tokens);
@@ -417,8 +416,9 @@ spanless_eq_enum!(PatKind; Wild Ident(0 1 2) Struct(0 1 2) TupleStruct(0 1)
     Or(0) Path(0 1) Tuple(0) Box(0) Ref(0 1) Lit(0) Range(0 1 2) Slice(0) Rest
     Paren(0) MacCall(0));
 spanless_eq_enum!(TyKind; Slice(0) Array(0 1) Ptr(0) Rptr(0 1) BareFn(0) Never
-    Tup(0) Path(0 1) TraitObject(0 1) ImplTrait(0 1) Paren(0) Typeof(0) Infer
-    ImplicitSelf MacCall(0) Err CVarArgs);
+    Tup(0) AnonymousStruct(0 1) AnonymousUnion(0 1) Path(0 1) TraitObject(0 1)
+    ImplTrait(0 1) Paren(0) Typeof(0) Infer ImplicitSelf MacCall(0) Err
+    CVarArgs);
 
 impl SpanlessEq for Ident {
     fn eq(&self, other: &Self) -> bool {
diff --git a/vendor/tera/.cargo-checksum.json b/vendor/tera/.cargo-checksum.json
new file mode 100644 (file)
index 0000000..926cbc0
--- /dev/null
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"a57c0512444a55682bcacb7f7f50601f54e8a5e39a075cdf1a1c4ed21622c290","Cargo.toml":"22665b5cf4c00012a129cfb4226af8d00adc60842c6321109a7fec32e7c1caf7","LICENSE":"8a51762984f85322bcd303a36eb0108a4bc9314e8f060a6794e2f2777b05eed5","README.md":"c6994f6115e0b85de1a4d63dc72184f427fcfdcf92a97edfc2c852dfb732893f","docs/README.md":"28c2521cfc7778b26ddeacc213aa8d53a210c28ea6930ca6d86782ac1a6b0c18","docs/node_modules/@types/glob/LICENSE":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","docs/node_modules/@types/glob/README.md":"8bd4625cf4d723a42ec420d9ae9e5d2c752f67974018773987499282496aa4a9","docs/node_modules/@types/minimatch/LICENSE":"27ebda9d51f0a56b7e281ccd8230a27236dcb51c05f64b07869ecf6e965d68b0","docs/node_modules/@types/minimatch/README.md":"6e28848a3ee4958b117b9768f6a637830b7364632fc5bc34191caaff129dbd68","docs/node_modules/@types/node/LICENSE":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","docs/node_modules/@types/node/README.md":"a74039636518ac796efc54653cd61b6ab6681581935bbb99572c608db0b4729f","docs/node_modules/@webassemblyjs/ast/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/ast/README.md":"f4d41f461de86dd29a6f31c5a6ea06a16e5b676f0834d9dd890aaa09990e1a86","docs/node_modules/@webassemblyjs/floating-point-hex-parser/LICENSE":"8eba52066621ef20c89c488812ed5cae70f36a84c071fa5dc198c7f25e18b3ad","docs/node_modules/@webassemblyjs/floating-point-hex-parser/README.md":"46b034f7c5063f9496a7333d40bcb5c1d5f4045b05dc44540bca6e3d2a3a1147","docs/node_modules/@webassemblyjs/helper-api-error/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/helper-buffer/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/helper-code-frame/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/helper-fsm/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/helper-module-context/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/helper-wasm-bytecode/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/helper-wasm-section/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/ieee754/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/utf8/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/wasm-edit/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/wasm-edit/README.md":"b91753384cafcdec8a430ca7b1f6870b649eb91380653a01350f2260c484a911","docs/node_modules/@webassemblyjs/wasm-gen/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/wasm-opt/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/wasm-parser/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/wasm-parser/README.md":"2f32b46c73a8c4c6276641c0b76a2683baea906ea41e3bd72e50ef7d81cc5c75","docs/node_modules/@webassemblyjs/wast-parser/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/wast-parser/README.md":"e0c2ac793eb70bafc946fc99040c8c1af3ba1312eef106bc275a2f74c779ed31","docs/node_modules/@webassemblyjs/wast-printer/LICENSE":"6d651b5b749b483278531be91623014bdfc12951278a33d6e43477db60a620ef","docs/node_modules/@webassemblyjs/wast-printer/README.md":"81a76f87f5fbb94b99bf3291310fadc2d52481a8fadb58d474ccf7f1e6c41059","docs/node_modules/@xtuc/ieee754/LICENSE":"6d5ef6dcbcc2d08589c716a674536afe8a23ac2499a814afb5b14b39cc415126","docs/node_modules/@xtuc/ieee754/README.md":"27827383727dcc6bb9f6f591e4b9204e35b6389bfba60df7a400371dac23b3ed","docs/node_modules/@xtuc/long/LICENSE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","docs/node_modules/@xtuc/long/README.md":"9108f0d40582b128776d4ccec95ee21ade5892f0772f7c5a2802f3594db6250a","docs/node_modules/accepts/LICENSE":"71f83c4c0621102a56d9853812777b85751bce7e9726f686f5b056c1f8a4b0e6","docs/node_modules/accepts/README.md":"3e76fd7c24dbf300adc385e47ac4b8112adb712480dc6d469ae5e46e3ffb2606","docs/node_modules/acorn/CHANGELOG.md":"0db7b444a1e0aaf43acc0e1b4317de2bc72f4d34bf8f8058337b2dd3e48de5c0","docs/node_modules/acorn/LICENSE":"7cdb44aabddbdd78998119d68a39c87424119b663945c79891fc1b022301824c","docs/node_modules/acorn/README.md":"ff0ef03770e5efa59cc919db12cecf839c6b3a1228bcc8eb8b655715a2af3405","docs/node_modules/ajv-errors/LICENSE":"7bf9b2de73a6b356761c948d0e9eeb4be6c1270bd04c79cd489c1e400ffdfc1a","docs/node_modules/ajv-errors/README.md":"769e3802b78ac54c890871d351f9c9d3bbd5de0f5ab232b15989f37f0db982e4","docs/node_modules/ajv-errors/lib/dotjs/README.md":"587f5696cb1a8c8952c94efb24d80253618c0ace187323e476d0ceb14af381c5","docs/node_modules/ajv-keywords/LICENSE":"a25dce9c94c3ad622574cffbefd4b8845b418aa65df966d97e3204ad276ed240","docs/node_modules/ajv-keywords/README.md":"ee2165f6b9ccc4f3a6c3f54b9df0f9bbc1e0f4d2e928396319cdc5d2d0890503","docs/node_modules/ajv-keywords/keywords/dotjs/README.md":"587f5696cb1a8c8952c94efb24d80253618c0ace187323e476d0ceb14af381c5","docs/node_modules/ajv/LICENSE":"e85e131fa4ed25538ff1f4962ced1fb6f68b079bd9164a790597a0f30b8fd030","docs/node_modules/ajv/README.md":"649e54ad952919a13334054605287c8f614228557d5763dfc1f1b8adf8b17fad","docs/node_modules/ajv/lib/dotjs/README.md":"30eeee72a46d849c941e3e9446e0bca66ed905a72ade2716119ef26c14c0dac9","docs/node_modules/ansi-colors/LICENSE":"94e1923e52409cfd50e97988d9772c0de15f65700097e3227fec367a39e82b94","docs/node_modules/ansi-colors/README.md":"d9354cb386d70e38a51fe92219d7bf1c2b434ef7ce4858a5c0c2d29a0bb42838","docs/node_modules/ansi-html/LICENSE":"cb5e8e7e5f4a3988e1063c142c60dc2df75605f4c46515e776e3aca6df976e14","docs/node_modules/ansi-html/README.md":"53b1604c716739b4ee6da7f961b040f4e109bc12015c29dc82d63b33be8ac3f7","docs/node_modules/anymatch/LICENSE":"765ad7d16f05b2a0c77d78e23822c3daddb0c5aa71b2db7bac663deba77d5b2c","docs/node_modules/anymatch/README.md":"703d53d8e2660386e2dc503ccd1761885ea24724070323e914d7eea9df495733","docs/node_modules/anymatch/node_modules/normalize-path/LICENSE":"f4a48aa8354a257785aa534bab2ac5ff2c2a98cd59cdf4a637bb68ee185683f7","docs/node_modules/anymatch/node_modules/normalize-path/README.md":"406764773e3c2651a668faa47c9ecc8ef16c373522805ae7c7c9902772ee4314","docs/node_modules/aproba/LICENSE":"0cef05dfff8b6aa7f35596984f5709f0d17c2582924a751efa471a76de7cdc11","docs/node_modules/aproba/README.md":"91e012b91670c56796138b7372c6b9e046176a717a776117e960dc6a9fcb5763","docs/node_modules/arr-diff/LICENSE":"f4a48aa8354a257785aa534bab2ac5ff2c2a98cd59cdf4a637bb68ee185683f7","docs/node_modules/arr-diff/README.md":"e3431f3dfde2c7f83f17734e85fffe371532c1b41aea21c1180a2ac72dbea939","docs/node_modules/arr-flatten/LICENSE":"4cd903859549d4b20b571041f96dfae1136ed079c476126268f9d7cc1b611150","docs/node_modules/arr-flatten/README.md":"85197f06375662bdce0f9e1b7626be08e934849eaa9510a6097565d9faf82271","docs/node_modules/arr-union/LICENSE":"3672fb6ef1c214578dfee689643516c2685f61ab08d130517ca8ea24f383a840","docs/node_modules/arr-union/README.md":"1186490d6a51ffbbaa0075d2fc009063ea9b8e3ff088c4e7da9d9827ceec710b","docs/node_modules/array-flatten/LICENSE":"4eeb3271453a891df609e5a9f4ee79a68307f730c13417a3bfeffa604ac8cf25","docs/node_modules/array-flatten/README.md":"071dd896356da12269508f361958ec622e47b27a96d7efdba23b671bc3470416","docs/node_modules/array-unique/LICENSE":"73b5283588baa142c5baaef5f56d3e8fdea7a30b214e8c5737e87640f882453a","docs/node_modules/array-unique/README.md":"0620ba115978744ea20385728d27eca51b627f276a0e4e0ec189a1575cad058e","docs/node_modules/asn1.js/LICENSE":"251ecdcdb2bafa7b106187a8cce96f322d0074c66e557c3c94cb49c769970408","docs/node_modules/asn1.js/README.md":"6e462debebf95fecbf06c0888ffcf07b304df0c6d1ff09f5b36e70d7398d29db","docs/node_modules/assert/CHANGELOG.md":"f3dd1c3b48d77ca8f6e057474c07554cabb00f837c9c033366ecab5f499a3828","docs/node_modules/assert/LICENSE":"6239c6144c31e58cf925c34483606969c555574d64ffa96518ab5d7f45c75d43","docs/node_modules/assert/README.md":"c3426a86d21b5c00f4608948d2755d75d60f57e0182e32387d7ff2a95271d180","docs/node_modules/assert/node_modules/inherits/LICENSE":"5ffe28e7ade7d8f10d85d5337a73fd793dac5c462fb9a28fbf8c5046c7fbca3b","docs/node_modules/assert/node_modules/inherits/README.md":"b33c8be1ca837d9e4c9b0e04a550feacbc101556164d3cdbb875aed6ccbb8a29","docs/node_modules/assert/node_modules/util/LICENSE":"6239c6144c31e58cf925c34483606969c555574d64ffa96518ab5d7f45c75d43","docs/node_modules/assert/node_modules/util/README.md":"b747cd55e4db80060bf8a4aee8a216c2ae5b90f7f30f3371ea093f725ff2315d","docs/node_modules/assign-symbols/LICENSE":"0798f37cff4a3f438c071316e41f94ffe110116a313ab0fc4f8caa07218f1f0f","docs/node_modules/assign-symbols/README.md":"053ed2505c6603f0ab00fa55c0d176d8bbead16993da06e7cab53302e12d84e3","docs/node_modules/async-each/README.md":"7cb1b0ed2e73816693c708f7b3c0736d99455c3bba99e1fd75f7b07e23bf7898","docs/node_modules/async-limiter/LICENSE":"e5a57cdd72e279910183799153134d0e749a5664fc459c8eacbecf72532b7db3","docs/node_modules/async/CHANGELOG.md":"95d4954f75af74cef8fde08462b3df1d8303658b50ce9a64517df32c74c49394","docs/node_modules/async/LICENSE":"d9fed24f132985934fca621c4dc1dfb53e03377a24d0568d424383d7eaa9c0ac","docs/node_modules/async/README.md":"0358732777cfb20648c3e31b94f76ac68aa6b4ea6d10bf88494dcc0dc63f3846","docs/node_modules/atob/LICENSE":"21426d8b8bcbfd772a7d0a382f0e1eea935d32906b0f2deec2f4d457ea4e9606","docs/node_modules/atob/README.md":"ae798c53e74e16710d62dc8750e53ea6c54eea0ebb3d895903b2c86d1311e2a1","docs/node_modules/balanced-match/README.md":"01e858e92c252f1a1d20842c9925e2ad2ff94bd588c49c4ae30c60ea332efb90","docs/node_modules/base/LICENSE":"f2274cb4b0e7ce5e4d6e9049a44981dd49cbd7b4b0a71aaaeb7b96a0d8d3439d","docs/node_modules/base/README.md":"04fda588951728c0f94ff252757f737f2b3fa883fe64b101d0eba0a64ce1a5df","docs/node_modules/base/node_modules/define-property/LICENSE":"aab63d733edfbb74393d94d75ece4ca89577d9f4a852a4cb18fb25cc8e254209","docs/node_modules/base/node_modules/define-property/README.md":"2fb9b56813d7f28460b6a657ccef9ef29188e781b894ed5a2547026653e27280","docs/node_modules/base64-js/LICENSE":"5b37224c080cdcc97c871ada971c224e9926370fe74f11b539aa1cf9f3b1aca1","docs/node_modules/base64-js/README.md":"057ef3ae4f4b4c9d3dcd257d3b2f38632de3c3a2ff068e5be14cb56a61d6daba","docs/node_modules/batch/LICENSE":"f5e20e95bf3528d3ed9b5a6edbb84da9bb2c0bed1ab356203fb4002efc8cc58c","docs/node_modules/big.js/CHANGELOG.md":"197acf8fb6ed68b5f7b52fad1ff89a8ac53f1bba43ef2a9d0d29ff80762de53b","docs/node_modules/big.js/README.md":"01fbb3a88569cb080317b9a65ec6c4512a01f5985f515c755acfa69d63ad95cd","docs/node_modules/bindings/README.md":"a5552f138725ba2768610c9362f5c7387c8ac80c61fc68477a4f97b7412bba86","docs/node_modules/bluebird/LICENSE":"87092fe7ffd1e92eba5d1dd39b73a73fdb4fdd4df3474beacc3d9f6b08ece82c","docs/node_modules/bluebird/README.md":"d6b367eb8ea0ec7248647f8b83fe2375f96c67ec8e4c7a1ab304c3b773290323","docs/node_modules/bn.js/LICENSE":"445739f5b5eb63e5aeff5aeb0f35a45080a421615dce0d97f9939aeea498acdd","docs/node_modules/bn.js/README.md":"0fc89d35ff8bced5f11a412d0d6fc8858f5083282d053a52be82a107f8e1ebf6","docs/node_modules/body-parser/LICENSE":"23d466b1b134b415b66fa50c6526b4cf3e7b9258554da88d3abb371721e7ce68","docs/node_modules/body-parser/README.md":"6a99b516086b69f5b815b0886e72d5d9a7d7867de08d698d98d0ede3955cbb44","docs/node_modules/bonjour/LICENSE":"608d17763dad0c4d94cda781d498241a5b13ab9fbe9bb7bf6c239ab823e90a36","docs/node_modules/bonjour/README.md":"d475d287915386d29a2a0bc26a30fefd2825a7e419f5b559d65d785a6ff94f0f","docs/node_modules/bonjour/node_modules/array-flatten/LICENSE":"4eeb3271453a891df609e5a9f4ee79a68307f730c13417a3bfeffa604ac8cf25","docs/node_modules/bonjour/node_modules/array-flatten/README.md":"567710b29b0cf2b872c928706da1861912679715a999a9d5234de5c9da8f244f","docs/node_modules/brace-expansion/LICENSE":"68f12f6e2c33688699249c01d8f9623c534da20aa71989c57b061b7bc1676d14","docs/node_modules/brace-expansion/README.md":"cf9c5d39a56cdc3178fe7872cbf5d00439f8e14fb939ddbda9d6b5c5852ec4c3","docs/node_modules/braces/LICENSE":"e70ff771504ba41f2be55de812a017ff46433d7a250c862e38fc419159e44500","docs/node_modules/braces/README.md":"fc86aafa4fd36e9743aab1ed5a994985e4ba4bfc7a30c7f6ad28c6bd262a4de0","docs/node_modules/brorand/README.md":"d506a235e27d2912c7c93be50beaaffaa9cd11e5c3852acc08362005108b61dc","docs/node_modules/browserify-aes/LICENSE":"82ba430b068b75a41438568e1e4ed1f96e02699c9b51735154af03e9b59d6b0d","docs/node_modules/browserify-aes/README.md":"4be82a2cf63d2dfb75d598abb23275e9adf47b24bd78c035edb7f508159e28b1","docs/node_modules/browserify-cipher/LICENSE":"dc09aa476634db0dbae1a296f099d5bd39e27c96b876d4d20b236fa565002bb6","docs/node_modules/browserify-cipher/README.md":"c338d8374fa5b17ccc78d79f5b023fa5086f7b882440e6d00d51a2419fa9e3ac","docs/node_modules/browserify-rsa/LICENSE":"d7314f44f0873f703b3cbaad5d60b947eb252a70072df586488e20a236c1223f","docs/node_modules/browserify-rsa/README.md":"5d837f5b7cc0d5736f618293c871224bd0e0b9304dec4cd2f57baf8a46ea6442","docs/node_modules/browserify-rsa/node_modules/bn.js/CHANGELOG.md":"bcda1f2ac360d9d840d7e52cda879e6003111a26295731fde63b82fab8cf9686","docs/node_modules/browserify-rsa/node_modules/bn.js/LICENSE":"445739f5b5eb63e5aeff5aeb0f35a45080a421615dce0d97f9939aeea498acdd","docs/node_modules/browserify-rsa/node_modules/bn.js/README.md":"356aa83e6a0a14f2adffe8e2395f3c142861679b621081de6a4ce6de99cf1e6d","docs/node_modules/browserify-sign/LICENSE":"a0e06d86a5a17341fa6134ee30ef18d73251cf32b8a577cdfd6aad6ad34af61d","docs/node_modules/browserify-sign/README.md":"8192fea22533c365ac28a1f175d8901c291dcbe7765222359c966939e144810d","docs/node_modules/browserify-sign/node_modules/bn.js/CHANGELOG.md":"bcda1f2ac360d9d840d7e52cda879e6003111a26295731fde63b82fab8cf9686","docs/node_modules/browserify-sign/node_modules/bn.js/LICENSE":"445739f5b5eb63e5aeff5aeb0f35a45080a421615dce0d97f9939aeea498acdd","docs/node_modules/browserify-sign/node_modules/bn.js/README.md":"356aa83e6a0a14f2adffe8e2395f3c142861679b621081de6a4ce6de99cf1e6d","docs/node_modules/browserify-sign/node_modules/readable-stream/LICENSE":"ec62dc96da0099b87f4511736c87309335527fb7031639493e06c95728dc8c54","docs/node_modules/browserify-sign/node_modules/readable-stream/README.md":"2bdaf66bb4ba368e12d7f8fe42eeee6956efdfe589403bfb25c1e2bcc9d98d55","docs/node_modules/browserify-zlib/LICENSE":"ddd770379e07bf0574dfaa4485be80a23b3248b36d09f33ec79276c09b829daf","docs/node_modules/browserify-zlib/README.md":"a3609bb29c032ee93f470ca3df5daeb4559536720fb41436c24f8992c14fdf64","docs/node_modules/buffer-from/LICENSE":"14275f5c8139d02054c5259d52a88ccbba662a86af18c30f071c8d082dc6004c","docs/node_modules/buffer-indexof/LICENSE":"7e13db436c0a802ef58d0096cc07323e53ad64ab9a5f3260c53e003e6dcd77d6","docs/node_modules/buffer-indexof/README.md":"2e14998566730ad4a57d6d046de9769a9213b39ece4218b4bb9a4a912092ceef","docs/node_modules/buffer-xor/LICENSE":"51ad9defd71911dbe413daf277bcb2e1077743f5ee5ae48d0a3b90a5b7486f55","docs/node_modules/buffer-xor/README.md":"5ac090d1d4c7f56967119d676f078cdad897347a6bc3b2032a92e709d2eb99e3","docs/node_modules/buffer/LICENSE":"06bafa45fdad2579ba0e43b0c9b2c6290287c99c4203c300254a462b38a307f6","docs/node_modules/buffer/README.md":"35d0699b5d6b64dc2fe60558f0e0c2a92e56ba57f346f547e062bb8f204b7ef7","docs/node_modules/bytes/LICENSE":"e3b44af066615de2ea48d18d852d0762f18c0b2efcea714fa48a6f729d405b85","docs/node_modules/cacache/CHANGELOG.md":"240b6cc59a6af6645895ab186fecc99786b1b1ff5559dcdd80bc24b9159904d8","docs/node_modules/cacache/README.md":"68108aae9e653e21720ac3edf411cb3a57321e48e9727c9a72eaf1d617041d20","docs/node_modules/cache-base/LICENSE":"0ead7e8cd8b0bc66a981ee69acaf1297ffa838cfce1b156a039bb24f997c0a27","docs/node_modules/cache-base/README.md":"e7c22e896860c49cde097774a57d20bfb9a3a20edef4512bc0b4291cc48fef05","docs/node_modules/call-bind/CHANGELOG.md":"d14fde3eb9bf11a617757fa500405afa78efcd1374c87975c3d36ab05e86f539","docs/node_modules/call-bind/LICENSE":"39c5ec504cf6bd5cd782a7c695828e09189df79f5d94840e4f08feb97b9fd416","docs/node_modules/call-bind/README.md":"82023dee4f3bbd058e0a2f1aa5529d3788728fb54a1510ce370c4b4160015e89","docs/node_modules/chokidar/CHANGELOG.md":"eabb990bc7aa7804706c3d1f91b9ed55e234c238e5fb64c6ed3c735763a66140","docs/node_modules/chokidar/README.md":"67a5485bd3d5cea42c062a7d2ad613fca70ac360ba8052b62eaa11a1372de8fd","docs/node_modules/chownr/LICENSE":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","docs/node_modules/chownr/README.md":"cafe18aeaf5d10a590bc8ffdcfb2f4e6120438a2364964aba4d8968693124984","docs/node_modules/chrome-trace-event/README.md":"4a9e90282b744c2887fa4ac39fb9eec0d2e94d223056c554a60b371b1f15db8e","docs/node_modules/cipher-base/LICENSE":"cf93ad78cfd5f3523248675aeb2a46e003367596883d4fa26a0c38d553ab0f61","docs/node_modules/cipher-base/README.md":"605953b751880632877907d029c775ee5c0532b4744373814612f2996db403ba","docs/node_modules/class-utils/LICENSE":"e83834436cadded044f9533764eb1c10304f53d6417db79ef7f5e28f243e4aa1","docs/node_modules/class-utils/README.md":"5d6f53113a8841264e10ed6a0d63573bf88b1c2ca2263f623dd5bea2b3fa37ca","docs/node_modules/cliui/CHANGELOG.md":"4f882861adc651c5643723b79f5ecc1a86cdf641209d40b511389fda2b903ecd","docs/node_modules/cliui/README.md":"37f25fb12e21a84615cc819111e06c3bf480221ff4ad20fcbf492096392bf421","docs/node_modules/collection-visit/LICENSE":"aab63d733edfbb74393d94d75ece4ca89577d9f4a852a4cb18fb25cc8e254209","docs/node_modules/collection-visit/README.md":"880abc6d120cbb97205f52496d92c4dd3aadde4315fa90ff551d76d6ab3863e1","docs/node_modules/color-convert/CHANGELOG.md":"ee2ea4fe91d043ec4214aa60aeaff595009acdfdbb9ed4030896191126d70849","docs/node_modules/color-convert/LICENSE":"693866fc419c6f61c8570438ec00659d156ec2b4d4a4d04091711f5f11a365d4","docs/node_modules/color-convert/README.md":"8cb35dae3a64e6edf1a680fecb9a850ea866795715aa46e09e211a1ba662d1c2","docs/node_modules/color-name/LICENSE":"c064f7a3e353bc1bc977f3c897941c75ef763f44f41677e0a15370ca0853d6e2","docs/node_modules/color-name/README.md":"796aef7006b975d2a8a5bad00219c9884e67a51ef96d36b3a0df622e60924c1c","docs/node_modules/commander/CHANGELOG.md":"4402fac21504d9cba177c90d5bc91746c4ffc0f29ac311de56e1de5199fa9883","docs/node_modules/commander/LICENSE":"04512a63dce4d2d506ad612dc0bd7681ccf6e3655f7b6eaef7dfac8323d1ec0b","docs/node_modules/commondir/LICENSE":"8bb16db1b047019e4395965f2cf3611b06c34bf86dc2d0210b3c3f91b53c21fe","docs/node_modules/component-emitter/LICENSE":"bf9b8053dead389db16aaf9a2634abc99297f2cdb72144f474af0cae5aa72c32","docs/node_modules/compressible/LICENSE":"b6be1b6c4e8c0441448a70fc6517c8d1ad62ad6a614b1fd049f74aa86c8b9820","docs/node_modules/compressible/README.md":"ae4b8303209fe715dbdf0b12eb73235e491598917a013d4a13bdad67e1a89570","docs/node_modules/compression/LICENSE":"23d466b1b134b415b66fa50c6526b4cf3e7b9258554da88d3abb371721e7ce68","docs/node_modules/compression/README.md":"4fc6743d0e4b7f9534975d7ed5ed848a3abb0e13c81c366def4ee3a91492e80a","docs/node_modules/compression/node_modules/bytes/LICENSE":"e3b44af066615de2ea48d18d852d0762f18c0b2efcea714fa48a6f729d405b85","docs/node_modules/compression/node_modules/safe-buffer/LICENSE":"c7cc929b57080f4b9d0c6cf57669f0463fc5b39906344dfc8d3bc43426b30eac","docs/node_modules/compression/node_modules/safe-buffer/README.md":"d301a850808775718ddb510d4bf2a922d9b0afa72894e67137daa20fbeafac05","docs/node_modules/concat-map/LICENSE":"435a6722c786b0a56fbe7387028f1d9d3f3a2d0fb615bb8fee118727c3f59b7b","docs/node_modules/concat-stream/LICENSE":"96b29c9aaa611a05349b362d48c2ffce0966fe408401a2d1a157be312c035b5f","docs/node_modules/connect-history-api-fallback/CHANGELOG.md":"e04a3c8d4526c8cf34ff456fb5e501e3e8cbfc5c4ec361c3706b01491c3041c6","docs/node_modules/connect-history-api-fallback/LICENSE":"69f2cff408d11bce328d04447832102c6ab1373dc44c2f89c9e69cdce8b1dd8c","docs/node_modules/connect-history-api-fallback/README.md":"e2b25f4164fd836d37530c28cbf03dc2c9e27814b11d8d78cb2ff761337a0def","docs/node_modules/console-browserify/CHANGELOG.md":"c17adeed223f3e927fd96ca756acf7a0fab45cf8fbfcbcc4a5a13d5a6837f37d","docs/node_modules/console-browserify/README.md":"8f2116766543e4e323385206c10d220ae66dbd6aa46efe6a55b6d7c0b685b9ac","docs/node_modules/constants-browserify/README.md":"b06569bf170a015c56cbad9b45756519d0b8a682770fe30d66bc1e235e26196a","docs/node_modules/content-disposition/LICENSE":"bd47ce7b88c7759630d1e2b9fcfa170a0f1fde522be09e13fb1581a79d090400","docs/node_modules/content-disposition/README.md":"6f5d183b1ee0c80f341b2b56188c6e12d6273ac9eeca6c2f081bb8148756244f","docs/node_modules/content-disposition/node_modules/safe-buffer/LICENSE":"c7cc929b57080f4b9d0c6cf57669f0463fc5b39906344dfc8d3bc43426b30eac","docs/node_modules/content-disposition/node_modules/safe-buffer/README.md":"d301a850808775718ddb510d4bf2a922d9b0afa72894e67137daa20fbeafac05","docs/node_modules/content-type/LICENSE":"257aed98914108e91a337912727b6a802eef218248507f74b76faffaff517a38","docs/node_modules/content-type/README.md":"63480bcc6c339579d3c1de04bf57957cf658da76913dc5418776a7748a887f93","docs/node_modules/cookie/LICENSE":"c02110eedc16c7114f1a9bdc026c65626ce1d9c7e27fd51a8e0feee8a48a6858","docs/node_modules/cookie/README.md":"b8aa9d0717067726bd7c404289554330e775cd59c2d39b2ca9704a17b4d3790e","docs/node_modules/copy-concurrently/LICENSE":"51ff8bfb2f9f25978427f17d2b65cae0f23fc6bfc9060e96fb2f5a7eac141631","docs/node_modules/copy-concurrently/README.md":"69404e42db026698562670a5cb58f34c933e9c929be0de73b25f63ab3bcebb73","docs/node_modules/copy-descriptor/LICENSE":"a91e1093d7fb934a4982016df082ddbf0d715549f0c94e2c878f8613bd7044e2","docs/node_modules/core-util-is/LICENSE":"33b734d60042d0fe0c92dd1fc1e874193a1c899ec3e276a2eb935d2d0bf5b710","docs/node_modules/core-util-is/README.md":"57072548a79553ec5a930b370f5f37f2b86f57ab39357dc63e097c7e8ba7412a","docs/node_modules/create-ecdh/LICENSE":"d4ad87ad0bb7d57c17ae73b46e064243b972edc3036c38c222172c9600a20b56","docs/node_modules/create-hash/LICENSE":"cf93ad78cfd5f3523248675aeb2a46e003367596883d4fa26a0c38d553ab0f61","docs/node_modules/create-hash/README.md":"71000c2ebf1795de130b69f46e32a8ef0d144cae317af0aabfda22e32c898b37","docs/node_modules/create-hmac/LICENSE":"cf93ad78cfd5f3523248675aeb2a46e003367596883d4fa26a0c38d553ab0f61","docs/node_modules/create-hmac/README.md":"01c5dbab58281b399035be8900268b0b4f39e588a6e68ee9cbaeb3dc76dac821","docs/node_modules/cross-spawn/CHANGELOG.md":"96b9f3f1a147f8ba8e92b8937e81c05d8cbf1cb9f8f9375bbfdf16886a3b40e0","docs/node_modules/cross-spawn/LICENSE":"aaa78451b6fecd1b9c4594c796c133c0e90cad100372ff8bc6de615e9ef9adf1","docs/node_modules/cross-spawn/README.md":"0fb18eafa39e5c716089475dd90808fe43d0f8b12a861d2132b57cb53e6d7251","docs/node_modules/crypto-browserify/LICENSE":"6134c69bc22c8289252e70de3af20bd67071233459055be74d83acfcc4865e7e","docs/node_modules/crypto-browserify/README.md":"b85c7d97dced5923a92e4138d9aa6b34e74ad753b9b5994cf45261f6f25fac25","docs/node_modules/cyclist/LICENSE":"0aa9add6a9158efad3e6649e3affd607c7e2629f6677af19f9988c8fbb0757b0","docs/node_modules/cyclist/README.md":"33c2d4a82b3e02ab4cd1dcea58aef12c2db3c59f05d033c802b3103f0b802edb","docs/node_modules/debug/CHANGELOG.md":"d8c1b0717964e189010b13521379c3b970eecc889cb8b788ac21d8dd85247165","docs/node_modules/debug/LICENSE":"98c970de440dcfc77471610aec2377c9d9b0db2b3be6d1add524a586e1d7f422","docs/node_modules/debug/README.md":"cda3dbd285a2b65894758565a565e7bc2e7c3696225af7b5bd01454240df0aea","docs/node_modules/deep-equal/CHANGELOG.md":"a7cc1c2b7fdc472356eedb5a75c67b57535e699b099f8dc26741004d1ebf3808","docs/node_modules/deep-equal/LICENSE":"4839125439c51ef70db530780f90cfa90e3a09b7e18694fc914d5daa2e463d14","docs/node_modules/default-gateway/LICENSE":"23e60503dc06abf04b9e535e17797b4e0f9224e6c5abf9207317d5a67c88c743","docs/node_modules/default-gateway/README.md":"a4222f8f29e9571cf038910facbe432c74d2fc5af9c8c897acbc6162cf6a67fd","docs/node_modules/define-properties/CHANGELOG.md":"992d7c97497adabd5d5a3838340dd0f705550046353ce8811feecf2098ebe594","docs/node_modules/define-properties/LICENSE":"00d402c2bbe7c67369bd01ce2c16b8ed46ccc949a1ee2d6bb8f9606afa8c7434","docs/node_modules/define-properties/README.md":"b8ff3791ad59fd6b71b25d8371396cbacf24a309fe22452484e4825f69de69ec","docs/node_modules/define-property/LICENSE":"0798f37cff4a3f438c071316e41f94ffe110116a313ab0fc4f8caa07218f1f0f","docs/node_modules/define-property/README.md":"7d5cf74ac9212240c52649384d08c31fa18ec2c288167e82d9f6789cc5636a07","docs/node_modules/define-property/node_modules/is-accessor-descriptor/LICENSE":"0798f37cff4a3f438c071316e41f94ffe110116a313ab0fc4f8caa07218f1f0f","docs/node_modules/define-property/node_modules/is-accessor-descriptor/README.md":"c7942b1902cb440a99cde862342b41e43a3d6089fd8f615c697a6ca2a13703b3","docs/node_modules/define-property/node_modules/is-accessor-descriptor/node_modules/kind-of/LICENSE":"f4a48aa8354a257785aa534bab2ac5ff2c2a98cd59cdf4a637bb68ee185683f7","docs/node_modules/define-property/node_modules/is-accessor-descriptor/node_modules/kind-of/README.md":"cb137461712cbd44841bcf77aa2d588fa518e19d2c40d4acdc7715a7caf90b18","docs/node_modules/define-property/node_modules/is-data-descriptor/LICENSE":"0798f37cff4a3f438c071316e41f94ffe110116a313ab0fc4f8caa07218f1f0f","docs/node_modules/define-property/node_modules/is-data-descriptor/README.md":"7f8526a1d461b0180cfb4bde865e20299959bf83b68fd201a151938bd579002d","docs/node_modules/define-property/node_modules/is-data-descriptor/node_modules/kind-of/LICENSE":"f4a48aa8354a257785aa534bab2ac5ff2c2a98cd59cdf4a637bb68ee185683f7","docs/node_modules/define-property/node_modules/is-data-descriptor/node_modules/kind-of/README.md":"cb137461712cbd44841bcf77aa2d588fa518e19d2c40d4acdc7715a7caf90b18","docs/node_modules/define-property/node_modules/is-descriptor/LICENSE":"4922620a5741e9d1bb43dde132021a982ae7c545eed1c6e00b555d6fe978005f","docs/node_modules/define-property/node_modules/is-descriptor/README.md":"03b096ed0c9ac7ae695829b476cd459a87003816378ab81035197769482673c9","docs/node_modules/define-property/node_modules/kind-of/LICENSE":"4cd903859549d4b20b571041f96dfae1136ed079c476126268f9d7cc1b611150","docs/node_modules/define-property/node_modules/kind-of/README.md":"636a60e60f3b067f6c0dc035e26477da2a01b0704177b9f96968eda239824057","docs/node_modules/depd/LICENSE":"bd47ce7b88c7759630d1e2b9fcfa170a0f1fde522be09e13fb1581a79d090400","docs/node_modules/des.js/README.md":"7bd8e5c11d17eac3766b25d421e158cdb7bacb0bcc520ac4a614520b7fd56c08","docs/node_modules/destroy/LICENSE":"965ef284f7f4c176842ec2e87fa13e79feed777d56d7a21a5a3b38f1bb6dc288","docs/node_modules/destroy/README.md":"49bc5aff60afdf0c1709e73207a302ff33fb45c74ccc63b3139c5a539877cf3e","docs/node_modules/detect-file/LICENSE":"2af5c9e1efd29da2a1409206627d8deed339dc59cd52f30223694d7acf548f11","docs/node_modules/detect-file/README.md":"7306d97232605279ec6c77ee2e668b12cc8391a7cb8dee57034d5a5604139db7","docs/node_modules/detect-node/LICENSE":"54b32293ea560d22cd9b62af9b2cda1a030d910a48c6601d227c5ff2338d95f8","docs/node_modules/diffie-hellman/LICENSE":"db6109f994692150ed82cd904bb053c73b97b23678bf52047f747bfec11e1934","docs/node_modules/dns-equal/LICENSE":"f58943cb354fb2707fea2f7b26b04e6014ddb56835cdfd414c9d2c6c59165b64","docs/node_modules/dns-equal/README.md":"a541f73736f756ac02038dc4335ca325fba2d7baaa28939f7bbd26952a8b0f4e","docs/node_modules/dns-packet/LICENSE":"6a134e51aa31496c15a741592fc5d782b2dbf8d8b6b8524e15c8520ae0cd6374","docs/node_modules/dns-packet/README.md":"f8b76ad33bef5a4c12524417a3f6ad9cbb8c85d4cd28179191eab17d127eab3d","docs/node_modules/dns-txt/LICENSE":"6e601d2a9fa081addb4d51191561510ad6f9594f6834b2f37d66c0fd8fdebb87","docs/node_modules/dns-txt/README.md":"2c58799ea240bc86935fde0985606f42618ade187fe893718b624af4e1392f9d","docs/node_modules/domain-browser/README.md":"e905374007bc6583833802f58b476b1d6310f8707a2d5c2552a6b56aa351d933","docs/node_modules/duplexify/LICENSE":"3fe8d55a98dbf260eace67c00cf9bc53edb46234e840098a0b93df3096b97fb6","docs/node_modules/duplexify/README.md":"ebacd0e68864940b7350889536c5231c0d0f8519b66794c2af93c28cc9aebf1c","docs/node_modules/ee-first/LICENSE":"965ef284f7f4c176842ec2e87fa13e79feed777d56d7a21a5a3b38f1bb6dc288","docs/node_modules/ee-first/README.md":"4480e03d020436e665886a99120abb2ee7fb422850e1b53ccbdbdbd251414c23","docs/node_modules/elliptic/README.md":"361389f7c5c5e493c2af0e89333b4dce12cf6f4c8901b30f035475d2c0215473","docs/node_modules/emoji-regex/README.md":"5dc36028590a85e84bc4cb777e29a3f33309b5e3b8d1ddbc957e7709ae83d0c2","docs/node_modules/emojis-list/CHANGELOG.md":"2662d81149cc49b72ede13b642d9de640fa2784f486e7a939542b7adc5ca331f","docs/node_modules/emojis-list/README.md":"03708433cb41d975ab2686e596bc027758e715d5167e9f0a69e6a7e888798ce0","docs/node_modules/encodeurl/LICENSE":"7585ea7bba616ccbbe43cb54ecb67956688c3c5641bb84f3099a652a73193afe","docs/node_modules/encodeurl/README.md":"c034db4c4433ac44bbc3ba626d1d2d1b02a6b6b76e0a8c92b6760dae39c5c59a","docs/node_modules/end-of-stream/LICENSE":"3fe8d55a98dbf260eace67c00cf9bc53edb46234e840098a0b93df3096b97fb6","docs/node_modules/end-of-stream/README.md":"177b2368d761e70733e06bbc2ff58f59360e49643aa86b99bc3114ba7ee2fe0c","docs/node_modules/enhanced-resolve/LICENSE":"9068a8782d2fb4c6e432cfa25334efa56f722822180570802bf86e71b6003b1e","docs/node_modules/enhanced-resolve/README.md":"faa61c3274d98022dec10b2d5862ca8463ec660bebf390f95e6bf3e99ae73f7b","docs/node_modules/enhanced-resolve/node_modules/memory-fs/LICENSE":"9068a8782d2fb4c6e432cfa25334efa56f722822180570802bf86e71b6003b1e","docs/node_modules/enhanced-resolve/node_modules/memory-fs/README.md":"2af8fee8f77e5008d2f68aa79404b214c94e19d123ae59cc0e6c9782140cda04","docs/node_modules/errno/README.md":"b530cc53597453de3c27ea6f782dafe40957aa4f2403b4109135db0a88372c1d","docs/node_modules/escape-html/LICENSE":"255aa557a1f55224ce522f311629c0bf20854740a67955cefd798fbd1d3d1ded","docs/node_modules/eslint-scope/CHANGELOG.md":"35287305e3fa392cd69a47cd8fe1bf15a5f7d5f36a122276f03844557fefad51","docs/node_modules/eslint-scope/LICENSE":"d3a724e2ed749f172ff70b62a1d0631b7d4b0ea273782365a3464d4e2d6b6dbd","docs/node_modules/eslint-scope/README.md":"85cb0606704bc29940ec3133e1b58739299e0db3c89f9c4eb3d8eb7b5bc847a4","docs/node_modules/esrecurse/README.md":"a7007c78c9d9da690ef6cdb0e7a3427d05832edb00abd1f5a9882700d73be4ad","docs/node_modules/esrecurse/node_modules/estraverse/README.md":"623a48ac487901c20b18ff241617efb3adf6a3b8c077073fccdddc770404c991","docs/node_modules/estraverse/README.md":"623a48ac487901c20b18ff241617efb3adf6a3b8c077073fccdddc770404c991","docs/node_modules/etag/LICENSE":"a7996721249a136fbcfc1c201bcb5f414f38a701d4a24f28abe65e16cfcce813","docs/node_modules/etag/README.md":"8a982db264a205206e5f2c18b0dc2fbb3a46762e997e89fcebf439e390d0cf65","docs/node_modules/eventemitter3/LICENSE":"3aecc12b1cb28832b5f65ab64291de96568c3f236a74d646281b4491f7bcadbf","docs/node_modules/eventemitter3/README.md":"e11daa4e946cc9f178661314fb18beb235c60a9aac6762f9347fc614ee2c4a17","docs/node_modules/events/LICENSE":"631987b7616a325a5b97566c232418481ddf7dbb5ecadefb991e791876cc2599","docs/node_modules/eventsource/LICENSE":"f683a72ffe6a9675b5507af22fe0f448d8c8de3da1e14f139d370a7e6a54a23e","docs/node_modules/eventsource/README.md":"faefde8ca4c53e5472d1999930890c4c4ec695934f1e41e1d0eb9727f8d372c3","docs/node_modules/evp_bytestokey/LICENSE":"cf93ad78cfd5f3523248675aeb2a46e003367596883d4fa26a0c38d553ab0f61","docs/node_modules/evp_bytestokey/README.md":"bb0e0da27ed64c090a9d4ee50685fee998ff45261b6e357bac333b4876863ef2","docs/node_modules/expand-brackets/LICENSE":"a91e1093d7fb934a4982016df082ddbf0d715549f0c94e2c878f8613bd7044e2","docs/node_modules/expand-brackets/README.md":"b6b8afa64851a36f7b43168eb2289311576176d8ed0d15cea5ccfd0a3991f259","docs/node_modules/expand-tilde/LICENSE":"7c780ed6eea810915c06e5db8718d6fa770c251824ea2578562f68b7becfc528","docs/node_modules/expand-tilde/README.md":"faa3c5fc4320cdf0903d0bb0b96605cc332c83964488a6521894a5acbdb43d40","docs/node_modules/express/LICENSE":"95a5762890e5c1c9808921cef095661fc482c5e1f0bba31446ac85595df6237c","docs/node_modules/express/node_modules/safe-buffer/LICENSE":"c7cc929b57080f4b9d0c6cf57669f0463fc5b39906344dfc8d3bc43426b30eac","docs/node_modules/express/node_modules/safe-buffer/README.md":"d301a850808775718ddb510d4bf2a922d9b0afa72894e67137daa20fbeafac05","docs/node_modules/extend-shallow/LICENSE":"daca23d50b0f54d36d6da1b16c82dfea6461e2ae20de0e869957e44cc6d34781","docs/node_modules/extend-shallow/README.md":"45b4a37695e699648cfa97d958655364332691a506fd9a1dbfd4c6d51f3fcc2e","docs/node_modules/extglob/LICENSE":"f2274cb4b0e7ce5e4d6e9049a44981dd49cbd7b4b0a71aaaeb7b96a0d8d3439d","docs/node_modules/extglob/README.md":"ac95665176d89ae7db6d1e5622645d1be3cb974e802fe59b14ea0e8b45a6cbbc","docs/node_modules/extglob/node_modules/define-property/LICENSE":"aab63d733edfbb74393d94d75ece4ca89577d9f4a852a4cb18fb25cc8e254209","docs/node_modules/extglob/node_modules/define-property/README.md":"2fb9b56813d7f28460b6a657ccef9ef29188e781b894ed5a2547026653e27280","docs/node_modules/fast-deep-equal/LICENSE":"7bf9b2de73a6b356761c948d0e9eeb4be6c1270bd04c79cd489c1e400ffdfc1a","docs/node_modules/fast-deep-equal/README.md":"ada32c1b53bd74640a22806e99b25c2b8ab2946eed338f325114be87bd5b9fce","docs/node_modules/fast-json-stable-stringify/LICENSE":"a833d366242c298cf1b10263516572fb8dcbe68eb5072cdcac2b4546e2b4eb36","docs/node_modules/fast-json-stable-stringify/README.md":"6f9ef416a3605e2a65ddacf76d820fc4d18664117bbd49ffba4bbfc999f74f11","docs/node_modules/faye-websocket/CHANGELOG.md":"56754b83513ac8e9ef6d72700cf37607c0a853484ba7308c83bcb03405f28ad0","docs/node_modules/faye-websocket/README.md":"aed26788e8a1660ff11eba0fd32a1252095fe872fd60d9bfe1490632e822ef26","docs/node_modules/figgy-pudding/CHANGELOG.md":"84281941b3cd2319eb8f2e8073f375c7645b2b926f088f12db017337fe75fab8","docs/node_modules/figgy-pudding/README.md":"8f14cbc3984d0fc6afbaef8bc905dc00b467540ca20f7dc9b7be12245f28e867","docs/node_modules/file-uri-to-path/LICENSE":"75070206e4ee2a749be52444cecc05101ca8d314c9d6d335ff914046cbf086a0","docs/node_modules/file-uri-to-path/README.md":"a801a028d69327433eb397e69fd0aea3f58b80a76222ffbae129d8808913251a","docs/node_modules/fill-range/LICENSE":"f4a48aa8354a257785aa534bab2ac5ff2c2a98cd59cdf4a637bb68ee185683f7","docs/node_modules/fill-range/README.md":"c54ded4c328ef5e308143d5d419d22fe5a678faed8f4c13608b580365802185c","docs/node_modules/finalhandler/LICENSE":"24973d5320410e565ec92f18f73f12af7d97c634d414ba170d119fe3f98904c8","docs/node_modules/finalhandler/README.md":"3f1da56c6d2bcc1b6945968d58744a1c21b38ec78371a09dc964ec4f11a7b4a7","docs/node_modules/findup-sync/LICENSE":"bba7a6545c88baa15993273aa93759f519915e4a6d0016a7b8060f8ac8e7f053","docs/node_modules/findup-sync/README.md":"e183e24d8ef44561011bcfe1899a2cc250e81195569cfb15d75d5e1a0584783a","docs/node_modules/flush-write-stream/LICENSE":"0aa9add6a9158efad3e6649e3affd607c7e2629f6677af19f9988c8fbb0757b0","docs/node_modules/flush-write-stream/README.md":"b5ba25a3b8cef77a3676cc72d977b3ffdee302ac9bef031255a795e07b0fc295","docs/node_modules/follow-redirects/LICENSE":"bfa8a54bb952ccda79f0f1889721d108f5b605babbb2b8a3705ffb52f4132eb7","docs/node_modules/follow-redirects/README.md":"98b1d0f7233555fc417c955245d381b56e20309447777c405a1fce14ad02a3c4","docs/node_modules/for-in/LICENSE":"f4a48aa8354a257785aa534bab2ac5ff2c2a98cd59cdf4a637bb68ee185683f7","docs/node_modules/for-in/README.md":"9b61de1685fd1688b6616b56e3a383cf6be6adc7e6cf2c46edeae66ee110733f","docs/node_modules/forwarded/LICENSE":"bd47ce7b88c7759630d1e2b9fcfa170a0f1fde522be09e13fb1581a79d090400","docs/node_modules/forwarded/README.md":"07438c4c25d8a64e08f08c90c02004d0615e293fb80652854bc5349e683374fc","docs/node_modules/fragment-cache/LICENSE":"d1a8c05367d9bf8f4fe511a04ff699a72ceccf694ac6260fa79dc8649475816d","docs/node_modules/fragment-cache/README.md":"f23dbad66b3324ef00dfa9240f15f600d729fece42521038a9efdb99ca2b9be9","docs/node_modules/fresh/LICENSE":"a0ec0dab16b3666f24950f86d257930ac2ad475557b4bfe245620e0817d8a45d","docs/node_modules/fresh/README.md":"ae9229e6a75e3f63f9cc1f651c6e1cafaedcc26852afe5ffed8a79c107b54aa5","docs/node_modules/from2/README.md":"d0cedd2864670f06fb44803c890bb03973219faacc358b5c3d67ead8ddacc799","docs/node_modules/fs-write-stream-atomic/LICENSE":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","docs/node_modules/fs-write-stream-atomic/README.md":"28cf97c59d2d1642ace39370ff3c6d7b3b90e7798b316d7e50f2f9f3ca2044cc","docs/node_modules/fs.realpath/LICENSE":"8465b04b67f473341171b5c9c8b2c741a4a395b3f6ed58339b3a4f4db3db7472","docs/node_modules/fs.realpath/README.md":"fb5cf635902e9c47d767a1de8334dfc19f171c38b6d14585204a50ab294a52eb","docs/node_modules/fsevents/LICENSE":"446daf038f1d819446a34ec3b0ced1119edd37a942310e7f375a577573b9f47b","docs/node_modules/function-bind/LICENSE":"773e131a7684726005a7e4688a80b4620033bc08499bc1404dd1a1eb3bca725e","docs/node_modules/function-bind/README.md":"24b54ff2732cdbe47af762519f8cd9e64bdfe9b691c1da631d82d9a384970178","docs/node_modules/get-caller-file/README.md":"de7b6d277d23b5b8a3cc7d31c7a0ba19972363df2818b88573b4a29e3e89ba07","docs/node_modules/get-intrinsic/CHANGELOG.md":"fe2384cd0074d8b7003eccb3221af8fa6f4a2b171c5ac8b8369b5749462ddbd4","docs/node_modules/get-intrinsic/LICENSE":"39c5ec504cf6bd5cd782a7c695828e09189df79f5d94840e4f08feb97b9fd416","docs/node_modules/get-intrinsic/README.md":"672f173b8204b392f283b092fb3b5bae0aba29f1d417a4289bbd740f6bcc74f6","docs/node_modules/get-value/LICENSE":"3672fb6ef1c214578dfee689643516c2685f61ab08d130517ca8ea24f383a840","docs/node_modules/glob-parent/LICENSE":"a2a19c04f527f7582fb2e58887f0a90f403732fc6accd7322287f0f5949b489e","docs/node_modules/glob-parent/README.md":"87eeb171639d2233d73417376209dbe3c16122e87e38441659274e22064d892c","docs/node_modules/glob-parent/node_modules/is-glob/LICENSE":"3672fb6ef1c214578dfee689643516c2685f61ab08d130517ca8ea24f383a840","docs/node_modules/glob-parent/node_modules/is-glob/README.md":"19b662622a67c4d0b0b3246106448e91e930c57a75b804b0492035aa5cfbf06c","docs/node_modules/glob/LICENSE":"6236fa0b88a4a0cce3dda0367979491b2052b3c8d6b1c10b3668de083e86a7f0","docs/node_modules/glob/README.md":"e0f10d0cb7a122c16e08227399c0178442d6c1ca8c1a6d66d0858e9220974035","docs/node_modules/global-modules/LICENSE":"e7d1fee7347ffddccc5fd03327ffdb50f8c112be0d5016d62388a92c4ae6e7a9","docs/node_modules/global-modules/README.md":"323340f50d3cf6fd37df7ac55643222f799acb14143ffa065d803d46d814a796","docs/node_modules/global-prefix/LICENSE":"e7d1fee7347ffddccc5fd03327ffdb50f8c112be0d5016d62388a92c4ae6e7a9","docs/node_modules/global-prefix/README.md":"3100b6ba20b582b75da07c733fa0d60dd2353172f0293e333d3b0eb996f12495","docs/node_modules/global-prefix/node_modules/kind-of/CHANGELOG.md":"6c50d6e44593afb0d79d22ae4a2e04fcaa9e28eed797e96a6a3242a41bfd30f8","docs/node_modules/global-prefix/node_modules/kind-of/LICENSE":"4cd903859549d4b20b571041f96dfae1136ed079c476126268f9d7cc1b611150","docs/node_modules/global-prefix/node_modules/kind-of/README.md":"fff406e21589c3563fa9b1f8f0b21c64be19745a5206e1da2e2402f6d43bd5f2","docs/node_modules/graceful-fs/LICENSE":"2fc5460f1526810979054ecd18cd01349b57f38ea56d1e920afdea34d104540c","docs/node_modules/graceful-fs/README.md":"53c74972f5203298f7c58a1f8739da499cc17020c3bf0b9fba6e00b01bf9ac4e","docs/node_modules/handle-thing/README.md":"5b69760438459b6e7411a2a99ee369c5d76e0fa82044124367d701d82e5d8428","docs/node_modules/has-symbols/CHANGELOG.md":"650d0ab7aa3a20f2d84ee59869cad43769a9e435c7568ef0d5c4eb32819846c0","docs/node_modules/has-symbols/LICENSE":"206c1adcf206dc0031b11232f5b054ec5f1662407ab1ca415247921cab2068ab","docs/node_modules/has-symbols/README.md":"b9133402765a0f78ef8bc643967bf969f9c7a4c76793732f46a4bccd6bad93c4","docs/node_modules/has-value/LICENSE":"f4a48aa8354a257785aa534bab2ac5ff2c2a98cd59cdf4a637bb68ee185683f7","docs/node_modules/has-value/README.md":"373fda7d03447f7623202df8d887e68a2406cb4ee01193825927d25e444ee043","docs/node_modules/has-values/LICENSE":"f4a48aa8354a257785aa534bab2ac5ff2c2a98cd59cdf4a637bb68ee185683f7","docs/node_modules/has-values/README.md":"c3c17f9e929b64eb50b55d118c7c0cf9ce41448ebf6f04970fbb250e94a356cf","docs/node_modules/has-values/node_modules/kind-of/LICENSE":"f4a48aa8354a257785aa534bab2ac5ff2c2a98cd59cdf4a637bb68ee185683f7","docs/node_modules/has-values/node_modules/kind-of/README.md":"f5831634d9cfb10d2d352f8388f30bced7964560093d2cbd236629dea2ad6e2c","docs/node_modules/has/README.md":"bb55f35abf9c3eda02020041eddd1fba1d29dafb4c348a14731f0d78410e87a2","docs/node_modules/hash-base/LICENSE":"898f204abbbbde58c6230a31842c59aeb8040fbcffa924db28e6d0b1d7631a3a","docs/node_modules/hash-base/README.md":"d923f17a3d6ed111b72acf4c636ed46b89692faeaf45ebc882c57bcd876f73db","docs/node_modules/hash-base/node_modules/readable-stream/LICENSE":"ec62dc96da0099b87f4511736c87309335527fb7031639493e06c95728dc8c54","docs/node_modules/hash-base/node_modules/readable-stream/README.md":"2bdaf66bb4ba368e12d7f8fe42eeee6956efdfe589403bfb25c1e2bcc9d98d55","docs/node_modules/hash.js/README.md":"5df660fe115c8ddcdb81c5d733c117b94abb706b91c26dac3ab7dc817dd9ba71","docs/node_modules/hmac-drbg/README.md":"31de905f4580f7a7f0eef6f2f09be85b261c64560bd072bc58d9b61ae225551f","docs/node_modules/homedir-polyfill/LICENSE":"56fcf95d730e2697b3c1cb64fb8d1981d86fd95f80af3f7829034995f7312942","docs/node_modules/homedir-polyfill/README.md":"fa424d2e9849effcb838c928cecfde4e48622c29cfe7b40d44da318d0fccb0eb","docs/node_modules/hpack.js/README.md":"75feefabeda8181959649921b06976c8e047f50d31955fb6bebc66b39afcb2e6","docs/node_modules/html-entities/LICENSE":"f8bcf3c7ea910a266c97007a3b93a11a4a9d735c2d1a86b71132a4dffd7cf8e8","docs/node_modules/html-entities/README.md":"dbc0cbfcc98b94b8250b1f58365da58902017f4fa0ac6ffae99e7520c9a3f8f1","docs/node_modules/http-deceiver/README.md":"067cc44062be2274732fdc07f5ab41ad8ec5439410714da70a92521be0757ed7","docs/node_modules/http-errors/LICENSE":"dcb94ff9b1e037a847bc20589dc81a1066d041fd4c16deb18b0fa968c66cf395","docs/node_modules/http-errors/README.md":"b6227d2316f01419ad18f74e0811d8eb75115e54f162e00634ce70fe1ee416f6","docs/node_modules/http-errors/node_modules/inherits/LICENSE":"5ffe28e7ade7d8f10d85d5337a73fd793dac5c462fb9a28fbf8c5046c7fbca3b","docs/node_modules/http-errors/node_modules/inherits/README.md":"b33c8be1ca837d9e4c9b0e04a550feacbc101556164d3cdbb875aed6ccbb8a29","docs/node_modules/http-parser-js/CHANGELOG.md":"04de9f7ded1aa61e3d12d3860e309dc6fa7ed39489e06ba14f63700a821e6d07","docs/node_modules/http-parser-js/README.md":"5b6198f8ea38476196b1d5157110a2d819972f3abb4cc6d40ecd2b55497f309b","docs/node_modules/http-proxy-middleware/CHANGELOG.md":"b1c96d8ffd170628e87b7ebf9fb5d54af7f7812b7ce92bcc62d7252bf1849df0","docs/node_modules/http-proxy-middleware/LICENSE":"055a5aff6eb633954d747443104ffa0652d04db950ef47aa70e17f15d2ced001","docs/node_modules/http-proxy-middleware/README.md":"175c5a6d4029cc10c39537bcb8f9ba862400a790652a31b37597f02bd7ca1427","docs/node_modules/http-proxy/CHANGELOG.md":"f11b5f2bf87478d0528705e52460d87b1aa4b1bb6a306c1c45ec666ee1819ff4","docs/node_modules/http-proxy/LICENSE":"589850dfc0a1d39a97c592d618d5772f84aec2b11c6898e020acb985299f3bab","docs/node_modules/http-proxy/README.md":"700d84a730fbfd21833efec6aa59cefdcac88ca26fe19812a04dc886e252da5e","docs/node_modules/https-browserify/LICENSE":"ff151c00207c908581639851dd8504ce4255be0650b2b236edec2aa90342b0cd","docs/node_modules/iconv-lite/LICENSE":"ac779f7314c74f232ef847ea86e714abe25cf6eeb5cc97b69451b74e2af6492d","docs/node_modules/iconv-lite/README.md":"a417c996ceb04e8dbaca5d18187820afe34ce5105ffd4b7c3ef3c5beae298eba","docs/node_modules/ieee754/LICENSE":"18d45466ba3253deae04667e267a91ea8de8548f18c1125264d1c9db28194cc1","docs/node_modules/ieee754/README.md":"27827383727dcc6bb9f6f591e4b9204e35b6389bfba60df7a400371dac23b3ed","docs/node_modules/iferr/LICENSE":"082096f8765abf72504dfc30f28cbdc28d0382ea564bffc1d7a376eb0e56c8a0","docs/node_modules/iferr/README.md":"1ce5e27f458fe681c376f095a86e1a283baa44497d919fcd17de0ed6a05b4655","docs/node_modules/imurmurhash/README.md":"4491517f7deb68d0b2a3bb590e785e276a60f12448447a9650d0bd50161a101c","docs/node_modules/infer-owner/LICENSE":"ec361617c0473d39347b020eaa6dceedaebab43879fa1cd8b8f0f97a8e80a475","docs/node_modules/infer-owner/README.md":"8149f269ff0b2e5e98f6242a6eb04e5e5872fd80cf8d26a8bfa3ddc41cbd9492","docs/node_modules/inflight/LICENSE":"05dc4d785ac3a488676d3ed10e901b75ad89dafcc63f8e66610fd4a39cc5c7e8","docs/node_modules/inflight/README.md":"7287d41cefa8c790b6a3bd8a802614f93acf2fd0eaca3d2fc7b6fef0c5e2ce47","docs/node_modules/inherits/LICENSE":"5ffe28e7ade7d8f10d85d5337a73fd793dac5c462fb9a28fbf8c5046c7fbca3b","docs/node_modules/inherits/README.md":"b33c8be1ca837d9e4c9b0e04a550feacbc101556164d3cdbb875aed6ccbb8a29","docs/node_modules/ini/LICENSE":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","docs/node_modules/ini/README.md":"128be3868807fd5a92bc4f681edb235435763fa4ed91aa838f838efd77fd82ec","docs/node_modules/interpret/LICENSE":"fd38dc17a3cb39babd4b75402d2abd31e34073cd8bae7b52c007917ddabefcfb","docs/node_modules/interpret/README.md":"9bf1d13f0afd1677bab20d341e234ec7ad7126c78dde0add1d7dcfca6f367da7","docs/node_modules/ip/README.md":"059fcdeafb68ab683a956378f222e85f71554ebe456f328f01632db760c266fd","docs/node_modules/ipaddr.js/LICENSE":"62568a2d1337b77171ecca9db10579163446de1ba6151678e81f06cdc199971b","docs/node_modules/ipaddr.js/README.md":"025b1282fbbc2f7f270e08b29414b7bbde469284564477f38b3519446aa16220","docs/node_modules/is-accessor-descriptor/LICENSE":"f2274cb4b0e7ce5e4d6e9049a44981dd49cbd7b4b0a71aaaeb7b96a0d8d3439d","docs/node_modules/is-accessor-descriptor/README.md":"57642a655821b643d86746cde08acda230a26269c6dd6d6934cd14151602dfb9","docs/node_modules/is-accessor-descriptor/node_modules/kind-of/CHANGELOG.md":"6c50d6e44593afb0d79d22ae4a2e04fcaa9e28eed797e96a6a3242a41bfd30f8","docs/node_modules/is-accessor-descriptor/node_modules/kind-of/LICENSE":"4cd903859549d4b20b571041f96dfae1136ed079c476126268f9d7cc1b611150","docs/node_modules/is-accessor-descriptor/node_modules/kind-of/README.md":"fff406e21589c3563fa9b1f8f0b21c64be19745a5206e1da2e2402f6d43bd5f2","docs/node_modules/is-arguments/CHANGELOG.md":"5ced612239d109f42eeb20ef38c4c17e543bcd8248e9ba17668b956cfac96b62","docs/node_modules/is-arguments/LICENSE":"dc0fe5a22d9336f345ee984f9bf56f11f22877a3aa5fd16a1db9a8ca0e23a5d1","docs/node_modules/is-arguments/README.md":"8cbd3eecefa0f6b74af9db06f00861a6cf1eb38616db59bdf54725e8db29264a","docs/node_modules/is-buffer/LICENSE":"c7cc929b57080f4b9d0c6cf57669f0463fc5b39906344dfc8d3bc43426b30eac","docs/node_modules/is-buffer/README.md":"33069316d7c498af3024becae7e9071054cdf88059c7033d2b1cdbdd9f8b82d8","docs/node_modules/is-data-descriptor/LICENSE":"f2274cb4b0e7ce5e4d6e9049a44981dd49cbd7b4b0a71aaaeb7b96a0d8d3439d","docs/node_modules/is-data-descriptor/README.md":"0b766cd4deada31b8e77c3bd374b001044186f2f6dce1f814f1ccf937cfe90d5","docs/node_modules/is-data-descriptor/node_modules/kind-of/CHANGELOG.md":"6c50d6e44593afb0d79d22ae4a2e04fcaa9e28eed797e96a6a3242a41bfd30f8","docs/node_modules/is-data-descriptor/node_modules/kind-of/LICENSE":"4cd903859549d4b20b571041f96dfae1136ed079c476126268f9d7cc1b611150","docs/node_modules/is-data-descriptor/node_modules/kind-of/README.md":"fff406e21589c3563fa9b1f8f0b21c64be19745a5206e1da2e2402f6d43bd5f2","docs/node_modules/is-date-object/CHANGELOG.md":"856c78907c51ff3ed9ce6c13672eacd0bc78607eb6ccf192dc5c1e18151f05e1","docs/node_modules/is-date-object/LICENSE":"c61652db3d2808f667b48af0a358f0d85fd07ad4a0d0b1a50882dec3b764c522","docs/node_modules/is-date-object/README.md":"1467176edee3535184b1add589486440e2138456b1c87b185b0c3ca3af116d0f","docs/node_modules/is-descriptor/LICENSE":"4922620a5741e9d1bb43dde132021a982ae7c545eed1c6e00b555d6fe978005f","docs/node_modules/is-descriptor/README.md":"03b096ed0c9ac7ae695829b476cd459a87003816378ab81035197769482673c9","docs/node_modules/is-descriptor/node_modules/kind-of/CHANGELOG.md":"6c50d6e44593afb0d79d22ae4a2e04fcaa9e28eed797e96a6a3242a41bfd30f8","docs/node_modules/is-descriptor/node_modules/kind-of/LICENSE":"4cd903859549d4b20b571041f96dfae1136ed079c476126268f9d7cc1b611150","docs/node_modules/is-descriptor/node_modules/kind-of/README.md":"fff406e21589c3563fa9b1f8f0b21c64be19745a5206e1da2e2402f6d43bd5f2","docs/node_modules/is-extendable/LICENSE":"0798f37cff4a3f438c071316e41f94ffe110116a313ab0fc4f8caa07218f1f0f","docs/node_modules/is-extendable/README.md":"d316c204459cf81a68ca1140663f96d002a9ce9a948deb2b172cfdc07d8c16f6","docs/node_modules/is-extglob/LICENSE":"73b5283588baa142c5baaef5f56d3e8fdea7a30b214e8c5737e87640f882453a","docs/node_modules/is-extglob/README.md":"bb36a84b32da3f9cc24ba6e08713013e85afdc31f7d98ed051321356fe55d4f3","docs/node_modules/is-glob/LICENSE":"4cd903859549d4b20b571041f96dfae1136ed079c476126268f9d7cc1b611150","docs/node_modules/is-glob/README.md":"557b8564b751e33aa3d41c372f17478c88f33f055070c17c9abb5979be6b5ad0","docs/node_modules/is-number/LICENSE":"73b5283588baa142c5baaef5f56d3e8fdea7a30b214e8c5737e87640f882453a","docs/node_modules/is-number/README.md":"ca4b1fda79e0318660cb0b7babc0bcc4f8ef265b5413fef6532a6c2a97397791","docs/node_modules/is-plain-object/LICENSE":"4cd903859549d4b20b571041f96dfae1136ed079c476126268f9d7cc1b611150","docs/node_modules/is-plain-object/README.md":"7d0311a33b64c6ab6bebd0b03f412c5e71becf52cad1e0ceb75db77be75f54a0","docs/node_modules/is-regex/CHANGELOG.md":"eeb885c4f4968d2b96dd851267142e597cabece57c20f8db8a2a84bcf3c24499","docs/node_modules/is-regex/LICENSE":"dc0fe5a22d9336f345ee984f9bf56f11f22877a3aa5fd16a1db9a8ca0e23a5d1","docs/node_modules/is-regex/README.md":"277bdddd60a8ef16247150c6684026f8791b45127ce4353b8268792aa64d639f","docs/node_modules/is-windows/LICENSE":"6b8eac57398e657431675649c722902adbbd3058e3af382f6bc4fd1c05325df6","docs/node_modules/is-windows/README.md":"5ff0eb82464220b28d2f2e4b5df5128062c1fac431c44bb3dc08f7ac1c6c2e71","docs/node_modules/isarray/README.md":"ff138e683771b187f3629c383db72ee7d632009010a36d08e18e8d2a34222ec7","docs/node_modules/isexe/LICENSE":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","docs/node_modules/isexe/README.md":"ab12ff031a831156ebd4f4253c2e8047d37547fb95fde416be524c8b8cfe4c74","docs/node_modules/isobject/LICENSE":"0ead7e8cd8b0bc66a981ee69acaf1297ffa838cfce1b156a039bb24f997c0a27","docs/node_modules/isobject/README.md":"c2ec6f02848c014fa8fa33338641db81b0ad3c12bfc94aefbf85878bbd9ba6b5","docs/node_modules/json-parse-better-errors/CHANGELOG.md":"0f9dd077518e9f7d1810cc5cd015f8e829352f51cd55f40e3109921332fadc31","docs/node_modules/json-parse-better-errors/README.md":"d948f026f62ae88e331253b3a4b2312dc9b85d6be59f2cf7a4350b185ab8513a","docs/node_modules/json-schema-traverse/LICENSE":"7bf9b2de73a6b356761c948d0e9eeb4be6c1270bd04c79cd489c1e400ffdfc1a","docs/node_modules/json-schema-traverse/README.md":"0baa52e8b3bc88a8b9ce83437aad7714d1b41b4b29bb0af72bcabfecfea2fbb2","docs/node_modules/json3/CHANGELOG.md":"e055aeb69adb65a302ea52be6b8269b609a22cf0e8fb65af256b71ea3f87c6de","docs/node_modules/json3/LICENSE":"3e87de4a390a5a4299207f48ff1831a0e3f70d25fd53ce348753966277c51b32","docs/node_modules/json3/README.md":"b482396bd8d274ba5115254c2ed9494d1eba38b705282af9383a3ba8f630ff73","docs/node_modules/json5/CHANGELOG.md":"fe324df1c9a7c9f08424e64fefebb8f1e23a96bf066dff8666ca716e0ce762fa","docs/node_modules/json5/README.md":"36b7a84da310e33f1abcc8713bc66f2b1b96b4fa8c64b493ff4740440e0a4197","docs/node_modules/killable/LICENSE":"f37f93994f52d2d7b596cb06dad24b485c1c007638271336d3f5ecdbce1bb729","docs/node_modules/killable/README.md":"2185f5ada80053c39bb6593a57a555f795eb8ef0340372e0b08e8ab1c816ed85","docs/node_modules/kind-of/LICENSE":"f4a48aa8354a257785aa534bab2ac5ff2c2a98cd59cdf4a637bb68ee185683f7","docs/node_modules/kind-of/README.md":"cb137461712cbd44841bcf77aa2d588fa518e19d2c40d4acdc7715a7caf90b18","docs/node_modules/loader-runner/LICENSE":"498d39c83164cf8de195090f5564fc0308ab271344ca2f95484a7f1020952d00","docs/node_modules/loader-runner/README.md":"df8592de92c391301ead257681e88565776ea66e36d71ef7d6a58f282d49d19b","docs/node_modules/loader-utils/CHANGELOG.md":"9bfc35c01cc74b4b1e76d5b8f2132d03b1433cdae8a7a6b712c1b3daef8a4ec9","docs/node_modules/loader-utils/LICENSE":"9068a8782d2fb4c6e432cfa25334efa56f722822180570802bf86e71b6003b1e","docs/node_modules/loader-utils/README.md":"d597d3e0c8c4c36260c2cdfe4d4fb26da319cb498e60831ea6ece0c1a615157f","docs/node_modules/lodash/LICENSE":"f71e8ed126b46346494aad5486874cd8f0aafe95092ed67d2e3cb6110f939abc","docs/node_modules/lodash/README.md":"aa8223fc6ac03beb61e9e1d55587c6a77bef133a3687b7bc85b61a738ad76740","docs/node_modules/loglevel/README.md":"1540043d947dd67b6ab4e8757bb7aa149d98d478190dccffa5d9821e211369bb","docs/node_modules/lru-cache/LICENSE":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","docs/node_modules/lru-cache/README.md":"981a9b1f5cffb2d70e9e4f085d98d651ef8b83384b7f6c845a12fa941dd58b43","docs/node_modules/map-cache/LICENSE":"7c780ed6eea810915c06e5db8718d6fa770c251824ea2578562f68b7becfc528","docs/node_modules/map-cache/README.md":"7e1072db0efe6ffcf1347f464a150afed9e4bb873a9bda147d89a8fb183a2770","docs/node_modules/map-visit/LICENSE":"f9f40678b97b1a6aa62cb1f2166d8169bd7ee0616e48db2cdc4618feea9f97f6","docs/node_modules/map-visit/README.md":"7ac7ddf7506d6e8c947a712740260a388dab2b88b9b834d71a6bac38d5c183bd","docs/node_modules/md5.js/LICENSE":"898f204abbbbde58c6230a31842c59aeb8040fbcffa924db28e6d0b1d7631a3a","docs/node_modules/md5.js/README.md":"9ecd2f8a6e1de41a5d4854c320ed4a14447be767b15f66c3bf5d6a9be10d8831","docs/node_modules/media-typer/LICENSE":"74d8054d56d522bdaa340d3d71130cb204997d523a5292c85ac1264dd77c8d06","docs/node_modules/media-typer/README.md":"12b47b8b2e2a0f70289b2f3fd9f810422f918b78024e0019e86c2c9bc4af695a","docs/node_modules/memory-fs/README.md":"d25b39e52c84a0748d6435fa9308e7fd0004fdb23e4bfb0407507294a9c95fc8","docs/node_modules/merge-descriptors/LICENSE":"62fb7d7c1822fe783895866057247bbd50164b00631fce9e4981d3897bdee4d9","docs/node_modules/merge-descriptors/README.md":"ace60d05b7af34523eefd407449e52f2b9ea33e26e212cf4f4b389ce60186320","docs/node_modules/methods/LICENSE":"1da7f0788d14d545b2b953f78a27b916d320dfa174c2fcfa124c5aaffa81056e","docs/node_modules/methods/README.md":"118d134e8bcd8b81d0a3596e0ded6d10372f9ec1e5df5a5b8b4295923973c7f4","docs/node_modules/micromatch/CHANGELOG.md":"0585d1395341c39009b9958e92e473542197fe2f6bbb1e60d83e22f69f46aaa6","docs/node_modules/micromatch/LICENSE":"e70ff771504ba41f2be55de812a017ff46433d7a250c862e38fc419159e44500","docs/node_modules/micromatch/README.md":"b24e025b843bbc990668f74d16e995e12c374d83d170dfaa075c1d81b300c1ed","docs/node_modules/micromatch/node_modules/define-property/CHANGELOG.md":"2dde114bd1bef55ba42c4dc510abd207c61582f70aa8f2383d1762982ee5dcb9","docs/node_modules/micromatch/node_modules/define-property/LICENSE":"6b8eac57398e657431675649c722902adbbd3058e3af382f6bc4fd1c05325df6","docs/node_modules/micromatch/node_modules/define-property/README.md":"edac4b6d9217e11a1bad4f2da900db1ff1560224953398bce870789c3f0936da","docs/node_modules/micromatch/node_modules/extend-shallow/LICENSE":"9580cc528a1c38d1560a9d36e34404fe1ea9d8e6f44c596dac2a3104ef63cdab","docs/node_modules/micromatch/node_modules/extend-shallow/README.md":"3b5fb3c4b4471d2bb8616b4ce0db6b470a368c0d4a508fee84886b611aaba4af","docs/node_modules/micromatch/node_modules/is-extendable/LICENSE":"4922620a5741e9d1bb43dde132021a982ae7c545eed1c6e00b555d6fe978005f","docs/node_modules/micromatch/node_modules/is-extendable/README.md":"527e291fe7c7095b00f0d3624eb1daec48d316eb13e4aa367f1cd738ae15a727","docs/node_modules/micromatch/node_modules/kind-of/CHANGELOG.md":"6c50d6e44593afb0d79d22ae4a2e04fcaa9e28eed797e96a6a3242a41bfd30f8","docs/node_modules/micromatch/node_modules/kind-of/LICENSE":"4cd903859549d4b20b571041f96dfae1136ed079c476126268f9d7cc1b611150","docs/node_modules/micromatch/node_modules/kind-of/README.md":"fff406e21589c3563fa9b1f8f0b21c64be19745a5206e1da2e2402f6d43bd5f2","docs/node_modules/miller-rabin/README.md":"cca039d99212195a60c68f10f717c22fb53089df8eefca0aaab77515e858019a","docs/node_modules/mime-db/LICENSE":"965ef284f7f4c176842ec2e87fa13e79feed777d56d7a21a5a3b38f1bb6dc288","docs/node_modules/mime-db/README.md":"df2aa39afd8daa94d1debd1e1802a1b5b2cc534fddec4cb227a3cb675ae4f992","docs/node_modules/mime-types/LICENSE":"71f83c4c0621102a56d9853812777b85751bce7e9726f686f5b056c1f8a4b0e6","docs/node_modules/mime-types/README.md":"dde89d240e3be84d9567dff0339ac52d22dbef7144051abc7c4aa39cfddd0897","docs/node_modules/mime/CHANGELOG.md":"40dadd07eacc0a92e0342a3e08c489e3b6db8168d53996cc07e42f7e5cbc997f","docs/node_modules/mime/LICENSE":"8f2658c03422c408b2b2ce4d151decc3b1a6fd3d86e5ca9433777bccdcdf75a2","docs/node_modules/mime/README.md":"fa7944ab894225a977e11a351ba3e3d826c77a6e69cf5fee090818b1b9c2f39c","docs/node_modules/minimalistic-assert/LICENSE":"136fee1129ea96ce18b41c26a72f5d4ba196ee41bfd73b55d0b8509cdda148e9","docs/node_modules/minimalistic-crypto-utils/README.md":"64608431631207282f74532d8b9eeda5cb42fced09c663f21e1462987270950c","docs/node_modules/minimatch/LICENSE":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","docs/node_modules/minimatch/README.md":"ff0e4686037f2e36056433e0a07c7018ab85cb6a665edefaa666e4af55bfaba6","docs/node_modules/minimist/LICENSE":"435a6722c786b0a56fbe7387028f1d9d3f3a2d0fb615bb8fee118727c3f59b7b","docs/node_modules/mixin-deep/LICENSE":"9580cc528a1c38d1560a9d36e34404fe1ea9d8e6f44c596dac2a3104ef63cdab","docs/node_modules/mixin-deep/README.md":"a0438d2f02e8dc4af69a09c88a9457e202ed0e3459df28d378e10e06d2dae157","docs/node_modules/mixin-deep/node_modules/is-extendable/LICENSE":"4922620a5741e9d1bb43dde132021a982ae7c545eed1c6e00b555d6fe978005f","docs/node_modules/mixin-deep/node_modules/is-extendable/README.md":"527e291fe7c7095b00f0d3624eb1daec48d316eb13e4aa367f1cd738ae15a727","docs/node_modules/mkdirp/LICENSE":"05991c2e8f070b69ec5b656c2c12fd07cd0153dd157d39b050b82af59b319a01","docs/node_modules/move-concurrently/LICENSE":"51ff8bfb2f9f25978427f17d2b65cae0f23fc6bfc9060e96fb2f5a7eac141631","docs/node_modules/move-concurrently/README.md":"90ea3797622ba0ad95ff4e6c2b36f2625f088da425a7403f3aa131e710bb8bf5","docs/node_modules/multicast-dns-service-types/LICENSE":"0aa9add6a9158efad3e6649e3affd607c7e2629f6677af19f9988c8fbb0757b0","docs/node_modules/multicast-dns-service-types/README.md":"96ed3c31773eacdec2e0209441c38c1ca821a680cadb7f1d1324b8b23dc3711e","docs/node_modules/multicast-dns/LICENSE":"0aa9add6a9158efad3e6649e3affd607c7e2629f6677af19f9988c8fbb0757b0","docs/node_modules/multicast-dns/README.md":"ec716cafeb399991575e5ec1240ed4c8588e40450a0b72a4b9cc41677b4337aa","docs/node_modules/nan/CHANGELOG.md":"72c8e5e31762cee8670c4d7edc1cf84de4d8880690ad705f11e40471eb02f3f2","docs/node_modules/nan/README.md":"4456f758f60820f51bb679e04bda0f8eb836bdf4cf4eeab3c545a0d1366d7d69","docs/node_modules/nan/tools/README.md":"a5e5b621d84fb9b98c84d5276f0b14ac022b752d2258388c2a1f56af7d830859","docs/node_modules/nanomatch/CHANGELOG.md":"8441b70ab29a284cfb20e2d480dc8627d29c197f7999f3508b8160df5f400267","docs/node_modules/nanomatch/LICENSE":"79ee8fb0e2dab906712344a3ad8a7a4a9b5bb6f3be8767ecfba2d2cb10155d29","docs/node_modules/nanomatch/README.md":"bf0b0f8f6f2e4b9a73cea153e06b9f5152f646454419ad0a967c986a7c9952ba","docs/node_modules/nanomatch/node_modules/define-property/CHANGELOG.md":"2dde114bd1bef55ba42c4dc510abd207c61582f70aa8f2383d1762982ee5dcb9","docs/node_modules/nanomatch/node_modules/define-property/LICENSE":"6b8eac57398e657431675649c722902adbbd3058e3af382f6bc4fd1c05325df6","docs/node_modules/nanomatch/node_modules/define-property/README.md":"edac4b6d9217e11a1bad4f2da900db1ff1560224953398bce870789c3f0936da","docs/node_modules/nanomatch/node_modules/extend-shallow/LICENSE":"9580cc528a1c38d1560a9d36e34404fe1ea9d8e6f44c596dac2a3104ef63cdab","docs/node_modules/nanomatch/node_modules/extend-shallow/README.md":"3b5fb3c4b4471d2bb8616b4ce0db6b470a368c0d4a508fee84886b611aaba4af","docs/node_modules/nanomatch/node_modules/is-extendable/LICENSE":"4922620a5741e9d1bb43dde132021a982ae7c545eed1c6e00b555d6fe978005f","docs/node_modules/nanomatch/node_modules/is-extendable/README.md":"527e291fe7c7095b00f0d3624eb1daec48d316eb13e4aa367f1cd738ae15a727","docs/node_modules/nanomatch/node_modules/kind-of/CHANGELOG.md":"6c50d6e44593afb0d79d22ae4a2e04fcaa9e28eed797e96a6a3242a41bfd30f8","docs/node_modules/nanomatch/node_modules/kind-of/LICENSE":"4cd903859549d4b20b571041f96dfae1136ed079c476126268f9d7cc1b611150","docs/node_modules/nanomatch/node_modules/kind-of/README.md":"fff406e21589c3563fa9b1f8f0b21c64be19745a5206e1da2e2402f6d43bd5f2","docs/node_modules/negotiator/LICENSE":"553d4d20029a24e315b428a1a54a9e109eaa340f2e958a4f50a92362c2c4070b","docs/node_modules/negotiator/README.md":"80b6570713fec66524839a271e942f9c1528e2552c96fed1e04d115953954ee1","docs/node_modules/neo-async/LICENSE":"811238ba7d85f6fe6b820703a32f92705bcf77bc352ddc3476783491c64a129a","docs/node_modules/neo-async/README.md":"4dfcf4a85bb8fca63c94d439e20fc4730722cfdccec210686c6c376a38ccf2d9","docs/node_modules/nice-try/CHANGELOG.md":"dcea91082962a0f3a0d1c9690b5bd44f41e850cc841a8b715d1a256f4fda43d8","docs/node_modules/nice-try/LICENSE":"bd220c219b05e6c22b7c23613ca926f60932d07c9fe141dd6e04b80dbc4b4e52","docs/node_modules/nice-try/README.md":"7be269f39491599d041e3dd17b769729a731f23108bcc199da7dd634ba0c1f3b","docs/node_modules/node-forge/CHANGELOG.md":"96a6e422ec7b548b581395ac1d4dc2911acb715a6b4ef90eb2c631a61ad4816f","docs/node_modules/node-forge/LICENSE":"f63ff0e4e239244aa79280da2dd4811a0469e5e201caf5cbc0d97c3a1dff8e82","docs/node_modules/node-forge/README.md":"54eed5a5c7b1a2d5fcaf7c0ba34289e21340375a8e794596ebc851445bdd1b29","docs/node_modules/node-forge/flash/README.md":"5e205d637ad5a5be1404f8640934fb792ff5480aa5b5f3c28123e62f5390806f","docs/node_modules/node-libs-browser/LICENSE":"ee663df5bd50f59b8a967b7ebd4db26c5eb6ffcbc7669937f6a8c185f7287a0c","docs/node_modules/node-libs-browser/README.md":"b5cb946237d15b074ced2ac38d2f6b63c0856087e1e496cd5e7e40fcd4f6d2b3","docs/node_modules/node-libs-browser/node_modules/punycode/README.md":"85b8008f11796b6af4a19abc9de892494a05000db7429420dcf3167f5c7ac338","docs/node_modules/normalize-path/LICENSE":"e70ff771504ba41f2be55de812a017ff46433d7a250c862e38fc419159e44500","docs/node_modules/normalize-path/README.md":"af3e56f394e970e17051724817e0b8b0c6b98f3376681cf48973180074a9e83b","docs/node_modules/object-copy/LICENSE":"5464e84783e7c02e6c19eaf8a364869a1b1f83205e1a7dd95b1da9ef7d7ab304","docs/node_modules/object-is/CHANGELOG.md":"725938abeec8e8b6527e36fb0bd4c7e061da7eff8e82708620a2dfb62a05ffe7","docs/node_modules/object-is/LICENSE":"dc0fe5a22d9336f345ee984f9bf56f11f22877a3aa5fd16a1db9a8ca0e23a5d1","docs/node_modules/object-is/README.md":"4a4c92e3150a7e150816010ef248f4abf5506200f356045355f8aaf64083a497","docs/node_modules/object-keys/CHANGELOG.md":"4cbf1c85307be4041f726a425294a3819c226bc03ad1f8f0b6e49673d5221570","docs/node_modules/object-keys/LICENSE":"5640e5cbe2e9f57f6ccfdd8dbfbeadb875495bdbcb69d2666ce3177ccd0942e4","docs/node_modules/object-keys/README.md":"fc894570536f2623e395fd319e3df738837323649ea2e2d430f8e6b96431e6a1","docs/node_modules/object-visit/LICENSE":"aab63d733edfbb74393d94d75ece4ca89577d9f4a852a4cb18fb25cc8e254209","docs/node_modules/object-visit/README.md":"f7c19b01e8beffe93499ae9d4ee1764c3c60d03677ad365348f94fff2a2f56b3","docs/node_modules/object.pick/LICENSE":"3672fb6ef1c214578dfee689643516c2685f61ab08d130517ca8ea24f383a840","docs/node_modules/object.pick/README.md":"ec6392075bbdfd08acc94ab43171ad19a64dfcbc4e15934eda263cdde7a9960e","docs/node_modules/obuf/LICENSE":"f404969f6f57c327403f94884aeb60448a0188c379edb78f329d546f8d16905f","docs/node_modules/obuf/README.md":"de8bdee39bf85a31e1941ee5341d7149e68fa5d1c56221f764ad4742f5c4b6e2","docs/node_modules/on-finished/LICENSE":"8089bcc08845ec143e5761f4a101a65b8c792a0dedbfeeb90a15560c0b77f768","docs/node_modules/on-finished/README.md":"3aafb4787ac3436273f87c49f7e0b6207e7a93421e43f6749cc39a5d6ac2fb94","docs/node_modules/on-headers/LICENSE":"74d8054d56d522bdaa340d3d71130cb204997d523a5292c85ac1264dd77c8d06","docs/node_modules/on-headers/README.md":"f2a152a391fdb1db8344b764427538a25811fe4bc3dcad3cd9f3276520899a62","docs/node_modules/once/LICENSE":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","docs/node_modules/once/README.md":"43b6d72bb23aff98af3243ab7e8d23d9af339ec46cdbdc81ded537c9899fa650","docs/node_modules/original/LICENSE":"3b2a6a268aa815dec121d614245e03b5c68db1f044d5b525e36db7d5dc7fb9c3","docs/node_modules/original/README.md":"739760f054e376dc933a4eaba248def9bcf90636e222f8bdf9272e55883f26fd","docs/node_modules/os-browserify/LICENSE":"d25d1d6d28c35cb6f358e2833e405c4e53fec2fa24d156323ddea5cd438d3407","docs/node_modules/os-browserify/README.md":"eb2dbf41216063ce9facde31f1100a2f04826dddfe0d16eb520870f57af31957","docs/node_modules/pako/CHANGELOG.md":"8d3b2a5ff30f052a33ff5a2a0d32fea9c22228a2eff08deb76856eac3bd31090","docs/node_modules/pako/LICENSE":"a04665b3b2de56c66730c1f720f528175739e4104f79073614aa611da1e85539","docs/node_modules/pako/README.md":"8174ca473d9df9da15064d199064e8e3ff88d46beb66b545e048756e6f0fb469","docs/node_modules/parallel-transform/LICENSE":"b0859c084893cbc3159dbf09a1ad0a72598cb2cde78f88156d63f2d4508ed77b","docs/node_modules/parallel-transform/README.md":"56d6e5a697315e5ca3c8d6e2c49d38b6e3883bf49c0a1220c42597da5309a036","docs/node_modules/parse-asn1/LICENSE":"bc5ed4eed738303bf403ec3b7e0a8e76760ef60664ad050a0ff61db23da77e66","docs/node_modules/parse-asn1/README.md":"baca90a0fa48dd77d6c05018de2b00dc96bf0fe273a10777fbe9272aea954cf7","docs/node_modules/parse-passwd/LICENSE":"56fcf95d730e2697b3c1cb64fb8d1981d86fd95f80af3f7829034995f7312942","docs/node_modules/parse-passwd/README.md":"95bb25575f49b6e008976b8d5d775699fc03cf973b429ae2ad0fd327d1bcb637","docs/node_modules/parseurl/LICENSE":"11d017c3b9f1ee3f44caf7203035f0461d5b57e0db8ce1bc03a9af34fa7d3f6b","docs/node_modules/parseurl/README.md":"2d37d38021aa9eb04b9915958140a7e79350672555f60f4b271384de1c0cfb81","docs/node_modules/pascalcase/LICENSE":"0798f37cff4a3f438c071316e41f94ffe110116a313ab0fc4f8caa07218f1f0f","docs/node_modules/pascalcase/README.md":"66557085bf54feb971ae04675ae4acf4e6233272cbb8fb764366404d31bdf388","docs/node_modules/path-browserify/LICENSE":"435a6722c786b0a56fbe7387028f1d9d3f3a2d0fb615bb8fee118727c3f59b7b","docs/node_modules/path-to-regexp/LICENSE":"4eeb3271453a891df609e5a9f4ee79a68307f730c13417a3bfeffa604ac8cf25","docs/node_modules/pbkdf2/LICENSE":"a9667a8bf55e7f20cf894cb47774f94ebd4eb366408aafb980f1f6547bcdc10a","docs/node_modules/pbkdf2/README.md":"a8a07adb420ca5c6f4fb7443e41083d2d005afda23b28a41da15ce40851583c2","docs/node_modules/picomatch/CHANGELOG.md":"7c977deaa019a637a9d4f21757653e31755e5d1b51636faa8474fb83dbb80b75","docs/node_modules/picomatch/LICENSE":"d0cd141b0c322fded5dfad1d4645bb2fedfc05b7321fe1009469638190d59ef9","docs/node_modules/picomatch/README.md":"58029607bb6d282ccd1cda6578bc82ed5e8f02f6ebbbffd5bee40ae9b81bf138","docs/node_modules/portfinder/LICENSE":"30b605694b1208e69ea711c41d4ffdf08657252b782501de54f0a5adfea8acb1","docs/node_modules/portfinder/README.md":"678334f330586c9c5879ced886fb9f6a380588f1e39a876b9824e1343b8d43fc","docs/node_modules/portfinder/node_modules/debug/CHANGELOG.md":"7a4879d2b37c50ed15d18a51c07905f993588873d7730b1584db386f81588d34","docs/node_modules/portfinder/node_modules/debug/LICENSE":"98c970de440dcfc77471610aec2377c9d9b0db2b3be6d1add524a586e1d7f422","docs/node_modules/portfinder/node_modules/debug/README.md":"5653c9afaeafddf749a831e6cd20051bc5a6f993dd141bf078d81970515d88ab","docs/node_modules/posix-character-classes/LICENSE":"d1a8c05367d9bf8f4fe511a04ff699a72ceccf694ac6260fa79dc8649475816d","docs/node_modules/posix-character-classes/README.md":"ca04588ff4cc87471acaeda36247775f1c50b48a4e8b209dc247ea6df65a8e5f","docs/node_modules/process/LICENSE":"59a400d04c5078579acc27ddd6452c1bdf763f9506e01364700935fbb1a7c91b","docs/node_modules/process/README.md":"f0d9aa902c0aa262b7443cede10b98b29244cbe4780dc6ba0343a404b9b4bebc","docs/node_modules/promise-inflight/LICENSE":"51ff8bfb2f9f25978427f17d2b65cae0f23fc6bfc9060e96fb2f5a7eac141631","docs/node_modules/promise-inflight/README.md":"64004d2af3846a48d1e82e3da0679e3c3059f9785750e6ab9f3399d74cdb525f","docs/node_modules/proxy-addr/LICENSE":"a7996721249a136fbcfc1c201bcb5f414f38a701d4a24f28abe65e16cfcce813","docs/node_modules/proxy-addr/README.md":"5479f545770a5bb3d901c08232ea66e5538e5e79730e1401ad5f2a40164dcb53","docs/node_modules/prr/README.md":"714b4755ec0168d6dd69f92fdc4682e1e9226d5d85ddea1fe43f42f57909d93d","docs/node_modules/public-encrypt/LICENSE":"db6109f994692150ed82cd904bb053c73b97b23678bf52047f747bfec11e1934","docs/node_modules/pump/LICENSE":"3fe8d55a98dbf260eace67c00cf9bc53edb46234e840098a0b93df3096b97fb6","docs/node_modules/pump/README.md":"7479c903505203fd92301e3b27501048d5aee1452378e64f1700d697244282c0","docs/node_modules/pumpify/LICENSE":"3fe8d55a98dbf260eace67c00cf9bc53edb46234e840098a0b93df3096b97fb6","docs/node_modules/pumpify/README.md":"f876637031e2234928389aa6511a0328a483f73ff2732cfdfa9e5ccaf0bb6eef","docs/node_modules/pumpify/node_modules/pump/LICENSE":"3fe8d55a98dbf260eace67c00cf9bc53edb46234e840098a0b93df3096b97fb6","docs/node_modules/pumpify/node_modules/pump/README.md":"f97f713a83538724513d50faa561ba6aa5fb452b81a9bf1dc937efc20fcafec7","docs/node_modules/punycode/README.md":"66df766a0ae9b972bdabc7df98a39ad0754f9b57d590d3c2922ba58c7aec97bc","docs/node_modules/qs/CHANGELOG.md":"2c0eb6789007b0d3e32c2c48c92764f55feed66f81cde0dc93ef697483239306","docs/node_modules/qs/LICENSE":"d2f9d2835eb09ccf673e118e4fdc372075437c1787e66c2202912fbe3e5ee9e1","docs/node_modules/qs/README.md":"948a2f411f283395c6499de064e262334e9ec2bd49f2e321c367d59b30685696","docs/node_modules/querystringify/LICENSE":"3b2a6a268aa815dec121d614245e03b5c68db1f044d5b525e36db7d5dc7fb9c3","docs/node_modules/querystringify/README.md":"6cc5bede0aa399657ae4cb76f0bea5d4051e3a8299f469ec2dd3870acdc1121d","docs/node_modules/randombytes/LICENSE":"ddc0dd5947bd2966b9a4cfde098566b011de0acfbe7814536955636ce9e3eced","docs/node_modules/randombytes/README.md":"d923f18c53d7031c5fc70ba39cfc22a94f4d39e8513dc096e4deb16c8c849885","docs/node_modules/randomfill/LICENSE":"ddc0dd5947bd2966b9a4cfde098566b011de0acfbe7814536955636ce9e3eced","docs/node_modules/randomfill/README.md":"266e07a64b3fa6f14e354d9c6c7105be48f21347171411c78ef9d94555ea8f21","docs/node_modules/range-parser/LICENSE":"f655e6291356ec0de7a8f0e69f294961a2cea86678ec94588be1e6a492e278ab","docs/node_modules/range-parser/README.md":"886bf556a8a88adc2aac86da3c8d63106e1c8e7854eb14bc1c095edc074163f8","docs/node_modules/raw-body/LICENSE":"c8e6bca7230689d536a3bd7158f66e9c4f89f95d0748743a0370ac229e9023ad","docs/node_modules/raw-body/README.md":"2afa081b2abe70f3f1ab0c137344bdefcb8a6598f89bc16e7e871ac1662b2299","docs/node_modules/readable-stream/LICENSE":"ec62dc96da0099b87f4511736c87309335527fb7031639493e06c95728dc8c54","docs/node_modules/readable-stream/README.md":"fb6579524007ebf9872f16601fe7cd7419bd9994f8ebc65dc0c304714a0d1541","docs/node_modules/readable-stream/node_modules/safe-buffer/LICENSE":"c7cc929b57080f4b9d0c6cf57669f0463fc5b39906344dfc8d3bc43426b30eac","docs/node_modules/readable-stream/node_modules/safe-buffer/README.md":"d301a850808775718ddb510d4bf2a922d9b0afa72894e67137daa20fbeafac05","docs/node_modules/readable-stream/node_modules/string_decoder/LICENSE":"11f2aafb37d06b3ee5bdaf06e9811141d0da05263c316f3d627f45c20d43261b","docs/node_modules/readable-stream/node_modules/string_decoder/README.md":"64417fec74bed1e4160c792189c85e6f37f4232a179e2beb04f32d80df76c4cf","docs/node_modules/readdirp/LICENSE":"fd8e193cc5249d8a1812de96e1bc4ea95807c6d1151a2d0a3c6d6f3988d25384","docs/node_modules/readdirp/README.md":"0bd10379c6c3b4c9b9526a2435cf45314fe455f12056c340aa687f16f04eae72","docs/node_modules/regex-not/LICENSE":"29b396fbfc4042f461034807ee195f93278f16b7bcaad896f6dd961137cab89d","docs/node_modules/regex-not/README.md":"f086f9f4ef202828a699646cb235f60fe52e4c4b210af9d2a79731bad45203cb","docs/node_modules/regex-not/node_modules/extend-shallow/LICENSE":"9580cc528a1c38d1560a9d36e34404fe1ea9d8e6f44c596dac2a3104ef63cdab","docs/node_modules/regex-not/node_modules/extend-shallow/README.md":"3b5fb3c4b4471d2bb8616b4ce0db6b470a368c0d4a508fee84886b611aaba4af","docs/node_modules/regex-not/node_modules/is-extendable/LICENSE":"4922620a5741e9d1bb43dde132021a982ae7c545eed1c6e00b555d6fe978005f","docs/node_modules/regex-not/node_modules/is-extendable/README.md":"527e291fe7c7095b00f0d3624eb1daec48d316eb13e4aa367f1cd738ae15a727","docs/node_modules/regexp.prototype.flags/CHANGELOG.md":"e4f245dbcce1592d779760eed770c4a47643daa1e8af81c040da4ac9a09c99f4","docs/node_modules/regexp.prototype.flags/LICENSE":"0c3fb74dd54705869d561cb765495b64c4dada8a127e9cd3390303cd7cb8a770","docs/node_modules/regexp.prototype.flags/README.md":"13a1d22bb74f9f65471ead6054d5013161fc8eb85b9ac978e4400b28afe9f0f1","docs/node_modules/repeat-element/LICENSE":"e7d1fee7347ffddccc5fd03327ffdb50f8c112be0d5016d62388a92c4ae6e7a9","docs/node_modules/repeat-element/README.md":"74dc0d88d4aa53ea530d3a2452c91d9fb839192eeb71f724c09ff45dcb63794c","docs/node_modules/repeat-string/LICENSE":"3672fb6ef1c214578dfee689643516c2685f61ab08d130517ca8ea24f383a840","docs/node_modules/repeat-string/README.md":"81f84248a49a14a5d0f0429cf29612aa27882ba3e14af7a373460fe96aa82917","docs/node_modules/require-directory/LICENSE":"a92e52eb1fa7cd746e3827bf01d3a3589bbc8e1e51348b1da042aad165525ad1","docs/node_modules/require-main-filename/CHANGELOG.md":"c34727bb46dcdc250b1b2403bbe733a961f4e1afedb192d05ee1b3aa7e5add6c","docs/node_modules/require-main-filename/README.md":"5c71d0b3841b668697cea30d8ad369a695e54add095cee40fdd8db3e37d27013","docs/node_modules/requires-port/LICENSE":"3b2a6a268aa815dec121d614245e03b5c68db1f044d5b525e36db7d5dc7fb9c3","docs/node_modules/requires-port/README.md":"ead11261c3a1c020cabd85e60c66cf7fdb21469a4ec55b38d21728179aed4ab5","docs/node_modules/resolve-dir/LICENSE":"a91e1093d7fb934a4982016df082ddbf0d715549f0c94e2c878f8613bd7044e2","docs/node_modules/resolve-dir/README.md":"14023117abd4771a6b1fcca3d61a15a8320fc78a9978469961fb25d3daf6e1d3","docs/node_modules/resolve-dir/node_modules/global-modules/LICENSE":"4922620a5741e9d1bb43dde132021a982ae7c545eed1c6e00b555d6fe978005f","docs/node_modules/resolve-dir/node_modules/global-modules/README.md":"99005d93ef085a177038bdc7adeb7fc721a4ca102d3709a04fb224aa651bc0b0","docs/node_modules/resolve-dir/node_modules/global-prefix/LICENSE":"4922620a5741e9d1bb43dde132021a982ae7c545eed1c6e00b555d6fe978005f","docs/node_modules/resolve-dir/node_modules/global-prefix/README.md":"3b86e4f622ccf7f9520af0f08358eefbab95ad88b981586b8d00d6eefdfedf90","docs/node_modules/resolve-url/LICENSE":"e1c2cb717f96dce44101960354e25cf7799051b2756a63ff01d7044ec762a67d","docs/node_modules/ret/LICENSE":"c7b6718db5ace1d13eb030d29c53eb2b02f90e84ba21ba59eee63dfd4fcbefee","docs/node_modules/ret/README.md":"3c8fd456b4043df596cc7f2d5fa6e63634ff01bb89b2b84b8553c7dc5a13b291","docs/node_modules/retry/README.md":"7f39755e8946f5cac7dea12c7a39717b966b319201562e09cf937fdcaa6cfb1f","docs/node_modules/rimraf/LICENSE":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","docs/node_modules/rimraf/README.md":"5813eb0ba88550585a8a0f50aac5182303aa911737a4409b4f0ace422be8485d","docs/node_modules/ripemd160/CHANGELOG.md":"8c46f89fc57c877b09f7d447a1ddf63f8000cd1b638cd6f897f22ad8cf679851","docs/node_modules/ripemd160/LICENSE":"4847d2fd9ed54cc006dd79f5a14fa5dd35eb8274dca511418166e195e277c05b","docs/node_modules/ripemd160/README.md":"58fec9d72327446f09feaf5dc42227f37ba3ed6d44de4f5a00202f448dc140f4","docs/node_modules/run-queue/README.md":"0fc7d594626a15c1303b295e99bb653f00448ed46090df7f40c23f90b6eb40fa","docs/node_modules/safe-buffer/LICENSE":"c7cc929b57080f4b9d0c6cf57669f0463fc5b39906344dfc8d3bc43426b30eac","docs/node_modules/safe-buffer/README.md":"d301a850808775718ddb510d4bf2a922d9b0afa72894e67137daa20fbeafac05","docs/node_modules/safe-regex/LICENSE":"435a6722c786b0a56fbe7387028f1d9d3f3a2d0fb615bb8fee118727c3f59b7b","docs/node_modules/safer-buffer/LICENSE":"4bc935e71be198c67ddf3c2b5fddb195f6edc182bfc155a96a6db61b44b494b9","docs/node_modules/schema-utils/CHANGELOG.md":"82c659d22ca72926cd598db9283949df34b04ee3504c795377bcd1a7c065c6b5","docs/node_modules/schema-utils/LICENSE":"9068a8782d2fb4c6e432cfa25334efa56f722822180570802bf86e71b6003b1e","docs/node_modules/schema-utils/README.md":"cb5f46df8d6a85ea13d6fa96a51f44197a289d001a259249149fef26d07169c0","docs/node_modules/select-hose/README.md":"d8dc58b1fb145e5fbe619d2766be24379ff6554ced097bcc6428f0716d638fe2","docs/node_modules/selfsigned/LICENSE":"cce91643d3456176ba7870772e107f28f54d51948086339522e3c31fb49f2f34","docs/node_modules/selfsigned/README.md":"388ff1ae88474576769f394a08f801a3b78b3a4cbb61db1e507709b5561eb390","docs/node_modules/semver/CHANGELOG.md":"33dadafd51d9364d07325b4ccf8ee51c986d4fbfabb5c193895070536420138b","docs/node_modules/semver/LICENSE":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","docs/node_modules/semver/README.md":"fb882cec291aada2f0ba15c319fa532146f45993382f7d45b094b0a58b7f8407","docs/node_modules/send/LICENSE":"8c3a3bc340c55f113097a35647235b8c0a9f0181d024a7ed1d116e202af68a07","docs/node_modules/send/README.md":"fef7c36e9cef791f40932790b459db9ef7babbdbaabd5811fd2d7adb66553372","docs/node_modules/send/node_modules/http-errors/LICENSE":"dcb94ff9b1e037a847bc20589dc81a1066d041fd4c16deb18b0fa968c66cf395","docs/node_modules/send/node_modules/http-errors/README.md":"b6227d2316f01419ad18f74e0811d8eb75115e54f162e00634ce70fe1ee416f6","docs/node_modules/send/node_modules/mime/CHANGELOG.md":"cb69ab3f4934b6970aabc64fdbcc37d8c53ee2e3010b00f37688ce017d212ff7","docs/node_modules/send/node_modules/mime/LICENSE":"8f2658c03422c408b2b2ce4d151decc3b1a6fd3d86e5ca9433777bccdcdf75a2","docs/node_modules/send/node_modules/mime/README.md":"3d645cf326552be680b89152865a5648e0ddae647ffa02a325980a1cdbd774a5","docs/node_modules/serialize-javascript/LICENSE":"d3dfa68a3c80e64eb10e46cef10e4208502da5ffb1387b11db00e42a507ab8f7","docs/node_modules/serialize-javascript/README.md":"ebb4ab71706998163312e8013564d1e2c25f71143abb4094cd6322229fa3bd99","docs/node_modules/serve-index/LICENSE":"ea26b04c550f3fca73ca1f24f2175ce3094e96b71870203755613e71364d22c9","docs/node_modules/serve-index/README.md":"25d86fb1e3d40f98b5b61ddcec21ac5aa28baa8c18f124480fc9d21a349f9615","docs/node_modules/serve-index/node_modules/http-errors/LICENSE":"dcb94ff9b1e037a847bc20589dc81a1066d041fd4c16deb18b0fa968c66cf395","docs/node_modules/serve-index/node_modules/http-errors/README.md":"cd804d2e2351bcc675148be7c47b14210cb95ea034486767f0bb01413183e806","docs/node_modules/serve-index/node_modules/inherits/LICENSE":"5ffe28e7ade7d8f10d85d5337a73fd793dac5c462fb9a28fbf8c5046c7fbca3b","docs/node_modules/serve-index/node_modules/inherits/README.md":"b33c8be1ca837d9e4c9b0e04a550feacbc101556164d3cdbb875aed6ccbb8a29","docs/node_modules/serve-index/node_modules/setprototypeof/LICENSE":"76d6d1ea0c268da37dd3c961b4fcfb23dee8417fff9e8786d4d44c585b781b69","docs/node_modules/serve-index/node_modules/setprototypeof/README.md":"16313d5e1a1c1686235057bdfd2b458359939d97b8bae4702a37d4f8d4ded117","docs/node_modules/serve-static/LICENSE":"63b9a188d7d43e64b0558b7115255045b9fe20a5fc3ff483421cb899e7f52bcb","docs/node_modules/serve-static/README.md":"e20ce151a46b602a6b128ed0e36c205557f9738fca90789389fd5e5c10e16136","docs/node_modules/set-blocking/CHANGELOG.md":"d3b4a111a1f1849b18cfeeffdc5d69f06522f37257b97db1041a7cb2186f6629","docs/node_modules/set-blocking/README.md":"e07ef2948101128a2273a88cd0ddd30b90f7c0d8e5de12ab59cffa9ec873c4f1","docs/node_modules/set-value/LICENSE":"f4a48aa8354a257785aa534bab2ac5ff2c2a98cd59cdf4a637bb68ee185683f7","docs/node_modules/set-value/README.md":"5ac389ff97fb2fffdc9797ec64c99c0c0bd0217750b94e3866f72e3af4cfac95","docs/node_modules/setprototypeof/LICENSE":"76d6d1ea0c268da37dd3c961b4fcfb23dee8417fff9e8786d4d44c585b781b69","docs/node_modules/setprototypeof/README.md":"62f93e306f36911e8cf8644b2b93f24e6eb324b548b36bcff3ea50774b9ed71b","docs/node_modules/sha.js/LICENSE":"58dcf38be1438f739412b87eb70d64bf00e9976d529bb119f700d8b3167924f0","docs/node_modules/sha.js/README.md":"1ca479077e9c8ab116b6095e3a1963c80adc21c5f48dd757b32268fdaff6acd7","docs/node_modules/signal-exit/CHANGELOG.md":"4275e182481a105af4608f1f6cd3a3f4f9396294a3781063f3fdb7a24997ea0a","docs/node_modules/signal-exit/README.md":"eb2ef4979680f1cd322d5ecf34b6df2eb906e6d64c1ea18101d2bafcfe069132","docs/node_modules/snapdragon-node/LICENSE":"d4a190ec206bae01d90ecbc7d6b62196c525cf5353e2283f2ba9b846727a2895","docs/node_modules/snapdragon-node/README.md":"42437ddb44dba4d5435692560f71ef91fc45ca8b0dd12f4c29b2c6c8af770c46","docs/node_modules/snapdragon-node/node_modules/define-property/LICENSE":"aab63d733edfbb74393d94d75ece4ca89577d9f4a852a4cb18fb25cc8e254209","docs/node_modules/snapdragon-node/node_modules/define-property/README.md":"2fb9b56813d7f28460b6a657ccef9ef29188e781b894ed5a2547026653e27280","docs/node_modules/snapdragon-util/LICENSE":"d4a190ec206bae01d90ecbc7d6b62196c525cf5353e2283f2ba9b846727a2895","docs/node_modules/snapdragon-util/README.md":"3b6a2f67ff1243b8bba5fa668a68cdef81953215fb8333b296287b4c37f80902","docs/node_modules/snapdragon/LICENSE":"7c780ed6eea810915c06e5db8718d6fa770c251824ea2578562f68b7becfc528","docs/node_modules/snapdragon/README.md":"e3721283fae359808354b9b61ab019b3d56916e343a189ce6f92a73b5320093f","docs/node_modules/snapdragon/node_modules/source-map/CHANGELOG.md":"e425d36553476d66611f2929534ac33c8b77aa8d77ccbe8b0d1d172eab129c59","docs/node_modules/snapdragon/node_modules/source-map/LICENSE":"6cb0631f71c7749763fd3dd1d5bee52dd1070ec17f2edc1710079ad070bd2fbd","docs/node_modules/snapdragon/node_modules/source-map/README.md":"647bdcc7186e20e91a3865cc0b7e86f1152d5627002692f1f41eb28c2aefb585","docs/node_modules/sockjs-client/LICENSE":"8ed26c0901535830e357f6ab802d0e6c4ff889d79c00dcebd4251eceecacd57e","docs/node_modules/sockjs-client/README.md":"31555e830287a48845e30435c955bfa04b6645ddaf550f8853ad8ccd209cbfd9","docs/node_modules/sockjs-client/node_modules/debug/CHANGELOG.md":"7a4879d2b37c50ed15d18a51c07905f993588873d7730b1584db386f81588d34","docs/node_modules/sockjs-client/node_modules/debug/LICENSE":"98c970de440dcfc77471610aec2377c9d9b0db2b3be6d1add524a586e1d7f422","docs/node_modules/sockjs-client/node_modules/debug/README.md":"5653c9afaeafddf749a831e6cd20051bc5a6f993dd141bf078d81970515d88ab","docs/node_modules/sockjs/LICENSE":"76d9aec61d97f3248686282555a8cb1ffc15459903a1654b8f522b475c32b645","docs/node_modules/sockjs/README.md":"81fd02f21a9ee17472412a20a0236d27279e7bf44ef537f53c4174ed24685fec","docs/node_modules/source-list-map/LICENSE":"e507b4af7432283b318a2b14690b8d46ed0a7cc64f5aca7209ed92a17554c47b","docs/node_modules/source-list-map/README.md":"b21234d6c82d7c43fddb54c210c6d02297b3cf7813b1bf85647334a6450d5989","docs/node_modules/source-map-resolve/LICENSE":"3c78dad6a73137a152a78f545eb0fe897c6828785368379a1218cc3d21d45e25","docs/node_modules/source-map-support/README.md":"d01ee9820a11dbac333dcdf932e1af57649adbbe24e0c477a22c52e49084451b","docs/node_modules/source-map-url/LICENSE":"c6a06b557de55e1ef10173b0c63411951c1909650aeeba9e41365a1ec97e3e8e","docs/node_modules/source-map/CHANGELOG.md":"e425d36553476d66611f2929534ac33c8b77aa8d77ccbe8b0d1d172eab129c59","docs/node_modules/source-map/LICENSE":"6cb0631f71c7749763fd3dd1d5bee52dd1070ec17f2edc1710079ad070bd2fbd","docs/node_modules/source-map/README.md":"635d9a9d385ee32d4d9cf2db1bdb8773b9d02219870dab16cf3ad1b9a6930854","docs/node_modules/spdy-transport/README.md":"2c755439e435c32a487c46b03c08d2bc56e357641bcee66135d3d0e769ac129c","docs/node_modules/spdy-transport/node_modules/debug/LICENSE":"98c970de440dcfc77471610aec2377c9d9b0db2b3be6d1add524a586e1d7f422","docs/node_modules/spdy-transport/node_modules/debug/README.md":"b592fa5e0de558dcfe3957a31dcad3ac914063e8dbba379ce15c45e59fe82403","docs/node_modules/spdy-transport/node_modules/readable-stream/LICENSE":"ec62dc96da0099b87f4511736c87309335527fb7031639493e06c95728dc8c54","docs/node_modules/spdy-transport/node_modules/readable-stream/README.md":"2bdaf66bb4ba368e12d7f8fe42eeee6956efdfe589403bfb25c1e2bcc9d98d55","docs/node_modules/spdy/README.md":"7f9908e43926bb78af94ff700f8536fa6a57a2c3a16f2885ba6cdbac5a8eb7d1","docs/node_modules/spdy/node_modules/debug/LICENSE":"98c970de440dcfc77471610aec2377c9d9b0db2b3be6d1add524a586e1d7f422","docs/node_modules/spdy/node_modules/debug/README.md":"b592fa5e0de558dcfe3957a31dcad3ac914063e8dbba379ce15c45e59fe82403","docs/node_modules/split-string/LICENSE":"f2274cb4b0e7ce5e4d6e9049a44981dd49cbd7b4b0a71aaaeb7b96a0d8d3439d","docs/node_modules/split-string/README.md":"976c7e4c336ac1551c32739a3bda1b9b605babb5214c2c02c54be1a96d3065bb","docs/node_modules/split-string/node_modules/extend-shallow/LICENSE":"9580cc528a1c38d1560a9d36e34404fe1ea9d8e6f44c596dac2a3104ef63cdab","docs/node_modules/split-string/node_modules/extend-shallow/README.md":"3b5fb3c4b4471d2bb8616b4ce0db6b470a368c0d4a508fee84886b611aaba4af","docs/node_modules/split-string/node_modules/is-extendable/LICENSE":"4922620a5741e9d1bb43dde132021a982ae7c545eed1c6e00b555d6fe978005f","docs/node_modules/split-string/node_modules/is-extendable/README.md":"527e291fe7c7095b00f0d3624eb1daec48d316eb13e4aa367f1cd738ae15a727","docs/node_modules/ssri/CHANGELOG.md":"02216353fd02a303810c87bc55badf2415a6aade3a3c3bf5e13c66835e5f102a","docs/node_modules/ssri/README.md":"81f8c8e3a3294cdd88b5e5896aadc9069af46624ffbf843e5b17691d1ef3178f","docs/node_modules/static-extend/LICENSE":"5464e84783e7c02e6c19eaf8a364869a1b1f83205e1a7dd95b1da9ef7d7ab304","docs/node_modules/statuses/LICENSE":"512cfa4d5e7a7569c7ae4dd95241cb6ae2aaf648ef9ebd080c01bd24868d26e9","docs/node_modules/statuses/README.md":"e45b966cb23afff7bb3b438192b4a0271ddc0f301006b061e71f956c8065778f","docs/node_modules/stream-browserify/LICENSE":"ff151c00207c908581639851dd8504ce4255be0650b2b236edec2aa90342b0cd","docs/node_modules/stream-each/LICENSE":"0aa9add6a9158efad3e6649e3affd607c7e2629f6677af19f9988c8fbb0757b0","docs/node_modules/stream-each/README.md":"270f0120200fa8cb5c1aacf250bcc1bbbe92fe889f1a3e8b59d673ffbb514ee0","docs/node_modules/stream-http/LICENSE":"a0e6357a5e8ea65827addeb383e0948a1874d2f46bc7feaf6349b7a376ed6e98","docs/node_modules/stream-http/README.md":"e0738b046340793980b76e859f454f51d5b560c42e58c6e481d0d5d9ac27ac2e","docs/node_modules/stream-shift/LICENSE":"6a134e51aa31496c15a741592fc5d782b2dbf8d8b6b8524e15c8520ae0cd6374","docs/node_modules/stream-shift/README.md":"731ceeb99dc3c505655cf148b264b080e2e552f1c68c487a41a94fe4e1711aff","docs/node_modules/string_decoder/LICENSE":"11f2aafb37d06b3ee5bdaf06e9811141d0da05263c316f3d627f45c20d43261b","docs/node_modules/string_decoder/README.md":"64417fec74bed1e4160c792189c85e6f37f4232a179e2beb04f32d80df76c4cf","docs/node_modules/tapable/LICENSE":"498d39c83164cf8de195090f5564fc0308ab271344ca2f95484a7f1020952d00","docs/node_modules/tapable/README.md":"7fcb17b78307480ad5fb233949c9cec201eae8567a00dd7e927843ed5b320972","docs/node_modules/tera-web/README.md":"8e79c3eac004b26ba4c112a90f365263b68bb924deaa628516d527c6496d802e","docs/node_modules/terser-webpack-plugin/CHANGELOG.md":"97bd209feb94eea67333dfdf4bb9b0d0f45664c3589b28ffab08a6214273214e","docs/node_modules/terser-webpack-plugin/LICENSE":"9068a8782d2fb4c6e432cfa25334efa56f722822180570802bf86e71b6003b1e","docs/node_modules/terser-webpack-plugin/README.md":"b210881def6e9d9cdf498e2a5db9fc2f246ff15e0b5625585aaab152bf39507d","docs/node_modules/terser/CHANGELOG.md":"ad2e8362ee9866fb9a8c1338554449627fde24b95f925bbcd032b4632a1f7cbd","docs/node_modules/terser/LICENSE":"68335488ef8f917c0feb901ace385f8c919bc81b0b60448a92928a3769fcec8f","docs/node_modules/terser/README.md":"eced96663d33383350a0a6b9689c9160a7db04c01d354600392748a91ceb4409","docs/node_modules/through2/README.md":"b855cc86157900ef46b1b898518e4f3931deb025f725a2dfd007251e81d61f90","docs/node_modules/thunky/LICENSE":"2281f2db407bdbb54f069eec38128b2dee2c0c952f52b786ef1faecb81767b3c","docs/node_modules/thunky/README.md":"bde4eb0f51e7c885e3f55ef6b34bd06497aa6b175137a751112873fda9db3775","docs/node_modules/timers-browserify/CHANGELOG.md":"580f59b2e64880b5d22f8267fb958dc280e1b773a750b0d68afa72f31691bdd3","docs/node_modules/timers-browserify/README.md":"94a7fa542db78ae188043fe9081f66bd28f9d5bbd8a592a45092945bf66ee605","docs/node_modules/to-arraybuffer/LICENSE":"22944ae65e0494100f74400ae6298ad4c3b607776f2724590029bb83c928b0ee","docs/node_modules/to-arraybuffer/README.md":"f530a901191a96f13dcc8acfd7cb55a912d8bfb330ebb21b16f12152faf49d9c","docs/node_modules/to-object-path/LICENSE":"7c780ed6eea810915c06e5db8718d6fa770c251824ea2578562f68b7becfc528","docs/node_modules/to-object-path/README.md":"e1bc74a8ed6bcc3ebd259d9ce692a97654e051145ca34f190ffdc0272a5b38b5","docs/node_modules/to-regex-range/LICENSE":"f9f40678b97b1a6aa62cb1f2166d8169bd7ee0616e48db2cdc4618feea9f97f6","docs/node_modules/to-regex-range/README.md":"064d905024497f1fad2c6ae86c6f96dc22df10b927dfe31e5630caa3d1035cbb","docs/node_modules/to-regex/LICENSE":"79ee8fb0e2dab906712344a3ad8a7a4a9b5bb6f3be8767ecfba2d2cb10155d29","docs/node_modules/to-regex/README.md":"d6b57235700a00715d9c8fd5ad7b19dbf16b1636240ddbde9d6b4ef54097e433","docs/node_modules/to-regex/node_modules/define-property/CHANGELOG.md":"2dde114bd1bef55ba42c4dc510abd207c61582f70aa8f2383d1762982ee5dcb9","docs/node_modules/to-regex/node_modules/define-property/LICENSE":"6b8eac57398e657431675649c722902adbbd3058e3af382f6bc4fd1c05325df6","docs/node_modules/to-regex/node_modules/define-property/README.md":"edac4b6d9217e11a1bad4f2da900db1ff1560224953398bce870789c3f0936da","docs/node_modules/to-regex/node_modules/extend-shallow/LICENSE":"9580cc528a1c38d1560a9d36e34404fe1ea9d8e6f44c596dac2a3104ef63cdab","docs/node_modules/to-regex/node_modules/extend-shallow/README.md":"3b5fb3c4b4471d2bb8616b4ce0db6b470a368c0d4a508fee84886b611aaba4af","docs/node_modules/to-regex/node_modules/is-extendable/LICENSE":"4922620a5741e9d1bb43dde132021a982ae7c545eed1c6e00b555d6fe978005f","docs/node_modules/to-regex/node_modules/is-extendable/README.md":"527e291fe7c7095b00f0d3624eb1daec48d316eb13e4aa367f1cd738ae15a727","docs/node_modules/toidentifier/LICENSE":"a832d679750e49ab433626ab196350b89964b60eb0d3edd3341887c7d5f4c128","docs/node_modules/toidentifier/README.md":"8c3316da94f3cb18b838ba2233613290321ab3d9e2eddcaf61d2fe77b81d1c68","docs/node_modules/tslib/README.md":"54f35179f2036fd5b0ec8644da382d8b7bff7bacad270fccf1551ebd87bacdfc","docs/node_modules/tty-browserify/LICENSE":"435a6722c786b0a56fbe7387028f1d9d3f3a2d0fb615bb8fee118727c3f59b7b","docs/node_modules/type-is/LICENSE":"23d466b1b134b415b66fa50c6526b4cf3e7b9258554da88d3abb371721e7ce68","docs/node_modules/type-is/README.md":"ffcb49607e72eba2ed8b37c854762381e7d2df2714cbda5b921ced25841581ad","docs/node_modules/typedarray/LICENSE":"26181ebee1063f3dc6766a3b6d05999a0da058f172eadf2ca5d15105ffd9735a","docs/node_modules/union-value/LICENSE":"f9f40678b97b1a6aa62cb1f2166d8169bd7ee0616e48db2cdc4618feea9f97f6","docs/node_modules/union-value/README.md":"067fa60cd626386340d9615bd2db5ee5b0ea0df28ed1bbb50ca2b7b7a87a80a5","docs/node_modules/unique-filename/LICENSE":"11734bf6e540e2c021413451205315e5053932de9df9e81279cf2acad6f135ed","docs/node_modules/unique-filename/README.md":"ffd9d326a806c3a5178552852368c03b19b3c2b013e2d7f826952fe728f9ae39","docs/node_modules/unique-slug/LICENSE":"8e8b31dd3582eb47f1b28bd6f009b54cd926adb9431e8424db7c2eae7c4af437","docs/node_modules/unique-slug/README.md":"ded8897e4eb050165ce008d19e80d7936f6191df1deca4b9ed5925de16517b08","docs/node_modules/unpipe/LICENSE":"1a526fbe8d8577f5a4b1c2821842b55b7c0e18862531c62ae4ce69c9b19b74b6","docs/node_modules/unpipe/README.md":"b091938be61f002fc626c4dfabf66cf14ff0b5a8fa9758c9dbbdc37ab818cb5d","docs/node_modules/unset-value/LICENSE":"aab63d733edfbb74393d94d75ece4ca89577d9f4a852a4cb18fb25cc8e254209","docs/node_modules/unset-value/README.md":"c9835c0d64f5de176a06cd944451827eb60efbe90f87338ed2d9c433e1722979","docs/node_modules/unset-value/node_modules/has-value/LICENSE":"3672fb6ef1c214578dfee689643516c2685f61ab08d130517ca8ea24f383a840","docs/node_modules/unset-value/node_modules/has-value/README.md":"7103951b92bb02966e09536fb43b4e7d1808de98e5ee9c3744c3cf4c841ddf1d","docs/node_modules/unset-value/node_modules/has-value/node_modules/isobject/LICENSE":"3672fb6ef1c214578dfee689643516c2685f61ab08d130517ca8ea24f383a840","docs/node_modules/unset-value/node_modules/has-value/node_modules/isobject/README.md":"67f9d7482724821613e416615144d15282e0eb119b5ef8da79c2a2fe033a9573","docs/node_modules/unset-value/node_modules/has-values/LICENSE":"3672fb6ef1c214578dfee689643516c2685f61ab08d130517ca8ea24f383a840","docs/node_modules/unset-value/node_modules/has-values/README.md":"58e8ad7b0adf64d8f440e5e8a374b9739ab43466a392c9b159523ca22adf7ef1","docs/node_modules/upath/LICENSE":"f7032bfd2007196bdac0910ef82c3eaafe72be152a9131ecb05d52431f1c4335","docs/node_modules/uri-js/LICENSE":"0af366eff4c01ec147c9c61ea9e8ffad64a4294754c9d79355f3fd1b97cb2fb9","docs/node_modules/uri-js/README.md":"237f52ec3b63511c1885e4271748a3a246813f605c028e05923a1dad2db2e62d","docs/node_modules/uri-js/node_modules/punycode/README.md":"ab3707ebd86575735ef8f23910a802d94a608cb7973433cedd3da3a11271b76a","docs/node_modules/urix/LICENSE":"e1c2cb717f96dce44101960354e25cf7799051b2756a63ff01d7044ec762a67d","docs/node_modules/url-parse/LICENSE":"3b2a6a268aa815dec121d614245e03b5c68db1f044d5b525e36db7d5dc7fb9c3","docs/node_modules/url-parse/README.md":"2fff696f535c3047991304a5a735d7a3749ecf3aeedc99826e6b0eb47ad26791","docs/node_modules/url/LICENSE":"97f780d3c79a42236f2b3435860f284c0ac6b958622f6bc9f1ac43fd49689b7b","docs/node_modules/url/README.md":"9dd0f9f49be606f7326c28c7579b2d1271eb984ab1697602f70ad068e7198052","docs/node_modules/use/LICENSE":"e7d1fee7347ffddccc5fd03327ffdb50f8c112be0d5016d62388a92c4ae6e7a9","docs/node_modules/use/README.md":"dd28cc5573f41c3d64098f63f476a7315eb52a337d22965342c48933d5d4b898","docs/node_modules/util-deprecate/LICENSE":"0154425673db15cdfa80ecba2c9b1f1a867f7197a006764712849bfc3a93cbb7","docs/node_modules/util-deprecate/README.md":"d30a5eca847bc6edc7b9723884def8942a66f89d12a5735dc22d1ee1216ff2ea","docs/node_modules/util/CHANGELOG.md":"79fc18a755f07688ba39a38e0b79ea7f0ab10b4e0e9366b712e31dd510a411b5","docs/node_modules/util/LICENSE":"6239c6144c31e58cf925c34483606969c555574d64ffa96518ab5d7f45c75d43","docs/node_modules/util/README.md":"67cfd3895ba720289377958e24270988911bc519eee0bfeb0609daffba26ed49","docs/node_modules/util/node_modules/inherits/LICENSE":"5ffe28e7ade7d8f10d85d5337a73fd793dac5c462fb9a28fbf8c5046c7fbca3b","docs/node_modules/util/node_modules/inherits/README.md":"b33c8be1ca837d9e4c9b0e04a550feacbc101556164d3cdbb875aed6ccbb8a29","docs/node_modules/utils-merge/LICENSE":"6e7d699cdd1e4fa837ba7718ea49841aa67201b449ea8b3f9cf274be15974a64","docs/node_modules/utils-merge/README.md":"f6672db98c83976565016569515c4fe33d8d9f0ea1f41044fcb1c91b1155fda8","docs/node_modules/uuid/CHANGELOG.md":"83a4b8f1660bb0ed5aac1b5ec44adde3d2108d4d3520c208a9a92c09b7c46605","docs/node_modules/uuid/README.md":"77662e63d7095338a4a150cc695d4bbe734c8b7307efed4cecd87dd8052008d4","docs/node_modules/v8-compile-cache/CHANGELOG.md":"21c714eb4293ed529fc85d25972ad2c4300b4b95d9d193e030c9928f363f7418","docs/node_modules/v8-compile-cache/LICENSE":"c77674258a3fdf3036a5d13d2aecd30d7a25aa6191cb0a9a7dd45b975dc7fe69","docs/node_modules/v8-compile-cache/README.md":"b995c87f1bbc5202c48fe7aca8cf435e563505bc5b1c0eb77b49783794011822","docs/node_modules/vary/LICENSE":"bd47ce7b88c7759630d1e2b9fcfa170a0f1fde522be09e13fb1581a79d090400","docs/node_modules/vary/README.md":"03444f916ddb9a1c692c329f88b83b1a21d016dce46656091f21e903109dd65c","docs/node_modules/vm-browserify/CHANGELOG.md":"98671fe369ad6303e71d9a3984e7d65bdabefb01681968ef7d33d6fade67d17c","docs/node_modules/vm-browserify/LICENSE":"3a62887f73cd035ac1068bc0127ce94291f7a03843391f56df3520e2ca2037f8","docs/node_modules/watchpack/LICENSE":"9068a8782d2fb4c6e432cfa25334efa56f722822180570802bf86e71b6003b1e","docs/node_modules/watchpack/README.md":"590db06fe2d4af1a3d86a8b5796a9071641a3deb94bf17bae8944b09b1b1cba9","docs/node_modules/watchpack/node_modules/anymatch/LICENSE":"5a3b0007c4203f10fe11b3fe8747253eb994f135e10b73e1f88ada941af09c6e","docs/node_modules/watchpack/node_modules/anymatch/README.md":"dde55ac85d7df17bd51f715302f7c81582d1c962a932b296d3f37cbfeffb0da2","docs/node_modules/watchpack/node_modules/braces/CHANGELOG.md":"5b18667ce44b445bccdc0aca63dde4017a4336419efad4d343ab133a20f22d9d","docs/node_modules/watchpack/node_modules/braces/LICENSE":"e70ff771504ba41f2be55de812a017ff46433d7a250c862e38fc419159e44500","docs/node_modules/watchpack/node_modules/braces/README.md":"c9bd7a70ec20c7ea5476b0ce17127c777cceb6339e56972ab4c8993ec6ea3da4","docs/node_modules/watchpack/node_modules/chokidar/LICENSE":"db9ba183d4cbfbaf6c27db2effddbb84b46340c33ed32a066bc0b144a3ea1298","docs/node_modules/watchpack/node_modules/chokidar/README.md":"76264bd5c358e64b85056db81c0c887e5d1e6969e97e00196ba6975c03a6f232","docs/node_modules/watchpack/node_modules/fill-range/LICENSE":"35bdd8a44339719441900fb50fbefc5e2dca1ca662cbaed7a687de842c8b70f2","docs/node_modules/watchpack/node_modules/fill-range/README.md":"e78ddba4ae383a98df6b4a644571c1fe8a0f8e1d25b0ddb389e4b35602194c60","docs/node_modules/watchpack/node_modules/fsevents/LICENSE":"2a8a5d6197bb97a018b8a190dd3ed853d750ca87c8e80c17aad41d6c6ff448e1","docs/node_modules/watchpack/node_modules/fsevents/README.md":"7be285dd5b0f38dad41f7d9601c438c0e2e564f50e4f7d8f8b68cc97b9295f5e","docs/node_modules/watchpack/node_modules/glob-parent/LICENSE":"2c46f1325bd3822a33c1e2c1e49c18d13127ac00f9c8b3b79196c7a126f73cd9","docs/node_modules/watchpack/node_modules/glob-parent/README.md":"3fdaad1cc34c596cd5c76892f613d3c09f89663d9f21bdc1ce045ddac57fe07c","docs/node_modules/watchpack/node_modules/is-number/LICENSE":"35bdd8a44339719441900fb50fbefc5e2dca1ca662cbaed7a687de842c8b70f2","docs/node_modules/watchpack/node_modules/is-number/README.md":"8e676a0587ba350889df0a5fb883aeab26609ee36432e29441f55af3a0cb16ba","docs/node_modules/watchpack/node_modules/readdirp/LICENSE":"dffec71d93f273d2af7b54c6c7e7e70b3289c632ec0d7253210ec21ac336d5ac","docs/node_modules/watchpack/node_modules/readdirp/README.md":"9666a18b43006dcaac8cac314ff3ee6f3695ec7d417df435249da7b23d9d3f76","docs/node_modules/watchpack/node_modules/to-regex-range/LICENSE":"e7d1fee7347ffddccc5fd03327ffdb50f8c112be0d5016d62388a92c4ae6e7a9","docs/node_modules/watchpack/node_modules/to-regex-range/README.md":"abab275498571b39763f746da015c0d702ae6b965255b30bca3724bdc6d3812e","docs/node_modules/wbuf/README.md":"f9145947f3aa2a55daa1b3ccff7bfc0c7c8a4ec4899813821461e6db866f2a8e","docs/node_modules/webpack-cli/CHANGELOG.md":"3a4e5ea6e5acc4fec3299fc34c9fafb8d9d8d4e4612c9bff60572c4c34c1400f","docs/node_modules/webpack-cli/LICENSE":"2af12ca8b612a22e6659ae68e0e59ee7ac792718c45524a989b512c49c5f5879","docs/node_modules/webpack-cli/README.md":"4c3b1e52aeeb49788f9d413d8b43cc1136f6d2aba56da2d8327ab121153541df","docs/node_modules/webpack-dev-middleware/CHANGELOG.md":"3fb46532e895dd3524f43532d7f4fc1388e6a6dc058771da7d5af768b62b198b","docs/node_modules/webpack-dev-middleware/LICENSE":"9068a8782d2fb4c6e432cfa25334efa56f722822180570802bf86e71b6003b1e","docs/node_modules/webpack-dev-middleware/README.md":"0ad0cc71801966bab6244e182c0d75658f717dc42a0e90cd97f81fe51d950de1","docs/node_modules/webpack-dev-server/CHANGELOG.md":"6cca77ca041e396d8b952f66e0e89e5dd68c3ba1e954340a6e3cfbc5e07c8db3","docs/node_modules/webpack-dev-server/LICENSE":"9068a8782d2fb4c6e432cfa25334efa56f722822180570802bf86e71b6003b1e","docs/node_modules/webpack-dev-server/README.md":"833397ad5299fb2b6ae8a856e1f34c22b8ddd56d75beb6da3b4e3dc2b89b9f84","docs/node_modules/webpack-dev-server/node_modules/debug/LICENSE":"98c970de440dcfc77471610aec2377c9d9b0db2b3be6d1add524a586e1d7f422","docs/node_modules/webpack-dev-server/node_modules/debug/README.md":"b592fa5e0de558dcfe3957a31dcad3ac914063e8dbba379ce15c45e59fe82403","docs/node_modules/webpack-dev-server/node_modules/semver/CHANGELOG.md":"ed92c9e44749a22cc5b8640fb034c2e86de2a4e4619f22c5261452fab22918b3","docs/node_modules/webpack-dev-server/node_modules/semver/LICENSE":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","docs/node_modules/webpack-dev-server/node_modules/semver/README.md":"c7d817091c6747e4f4fb7006bf60bd2040fd955ab7c37520f834c2af265876c6","docs/node_modules/webpack-log/CHANGELOG.md":"a11f739e8d17b7ddc987a7a3ddcae2d5898bc9b84e32fa4cfac4aef0468f4c2c","docs/node_modules/webpack-log/LICENSE":"cb6180469886d4c3c15b04f8bf316ac90abb55888d4e07b522da1f8c0ecc7468","docs/node_modules/webpack-log/README.md":"239f1c8da534875a75f115c64414b711055a24af19c7e00ea762c16aeabde25c","docs/node_modules/webpack-sources/LICENSE":"214d0ac13edb475ec426df1979d96fd46b443debc466c0fb592e32152ae5a940","docs/node_modules/webpack-sources/README.md":"0b5c9fa9616a7a96a1092e5c49822c96f20f3b9c61a4defbade3c96dab1566f2","docs/node_modules/webpack/LICENSE":"9068a8782d2fb4c6e432cfa25334efa56f722822180570802bf86e71b6003b1e","docs/node_modules/webpack/README.md":"51b2eb04f4efbab2fcfb689d5e3cf84011a6e95c55128792f72b8e061fd3f65a","docs/node_modules/websocket-driver/CHANGELOG.md":"73f5b1a7ea245f261711a9475937109048fb23cac4db7fa8c0bd4cf47b2d6c2e","docs/node_modules/websocket-driver/README.md":"7f6c4595bda5064a700474f882304be2109b10175c6057bcaf7cbb093c1c50f9","docs/node_modules/websocket-extensions/CHANGELOG.md":"f1a3b095721f3b756ff40d208b65096bc72d6ea733c5249889ab6cb2f7b82a29","docs/node_modules/websocket-extensions/README.md":"445477c28c42082354ed9d28eeb83c65badc047f2858cd6f1532df93237a7bc9","docs/node_modules/websocket-extensions/lib/pipeline/README.md":"5fb640dc0716f1969f0a4f104058abfeb7d2f6efd75b45721f70f876256d35ca","docs/node_modules/which-module/CHANGELOG.md":"e4a81c17bac10ae49129a89dfc5d750d0c9ffabaffd81f226e353cf1a203af04","docs/node_modules/which-module/LICENSE":"852bf81203aa93aa89afc9f881ebb035322dc7334aaceff435c557634c94a815","docs/node_modules/which-module/README.md":"ab478445afb6c181d829c5c2edf8a0de8dbc6dac0f7fe8a9f385fa936e5897fa","docs/node_modules/which/CHANGELOG.md":"0915c4c8496f278bff95b1fb6c8998df43e00587ee44327760852624d43ec5e4","docs/node_modules/which/LICENSE":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","docs/node_modules/which/README.md":"0484e57c045cfa67288fa1bd96b5e5ab849441c4fb75c602f25365dc86babbf2","docs/node_modules/worker-farm/README.md":"99433ec40606197d34af20dcdbc41a556800cec559ba075ebf171b336137067c","docs/node_modules/wrappy/LICENSE":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","docs/node_modules/wrappy/README.md":"0d2537e86a9e5ae85d8e53910d779895179035c9daa35555874ec19f1225c224","docs/node_modules/ws/LICENSE":"3de284c8e6fa7e8437eff6f53695471e0332129a5b42a79361e17b7637de94b3","docs/node_modules/ws/README.md":"dc0df537682fe3be61af2ba199cc82e809536d940d388570cb5ceeeba7f3af31","docs/node_modules/xtend/LICENSE":"82e67379203d5794e7c44549847d8d64ae6904591381682360470898bd306821","docs/node_modules/xtend/README.md":"fe5fb4d83470799709c32207fc1fff3e522070b2c625a9818f191125406cd360","docs/node_modules/y18n/CHANGELOG.md":"c965c534e68985f629c8c26703b05967fed23e4fcce4247c580ba95694ecaec5","docs/node_modules/y18n/LICENSE":"2034cce3b6fafcddd642c4175e01d3ddfc332a53b9f20fdc46b1466dc89ac469","docs/node_modules/y18n/README.md":"230eff3f840c6d29b3f03293d37c446e0cc30148ab72843893cd91720b27027f","docs/node_modules/yallist/LICENSE":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","docs/node_modules/yallist/README.md":"cf293896dc0c704e9ed655ebb43341cc1ac5d0b2214f78377bed4370b7c6dd0f","docs/node_modules/yargs-parser/CHANGELOG.md":"82cfdb55b22f53ee7a797303f950f59c7a26c33b69e3a4d9bab8e7931e7c919b","docs/node_modules/yargs-parser/README.md":"4c43072e7e9160c49ac655bc1e9d21a42a68bd2ccf0339e498f1aa7f31e67be5","docs/node_modules/yargs/CHANGELOG.md":"f5f82923bd41cb07fc243222c9a701d178fb94943edb956735f390aa6bfb5ae9","docs/node_modules/yargs/LICENSE":"fe71524a15f30aab0f39af7165d38fc64a4269b7d2a0caffebc907355aec9c92","docs/node_modules/yargs/README.md":"5f7e42fede5217a3e6017f08868e8743790e8afe1009824e97d89eff66206e5b","src/builtins/filters/array.rs":"e0536e7871df1a636a49e6799025878de7aa6789961fe1d7b146ae379370e4ff","src/builtins/filters/common.rs":"81c5b8dbcef276605f151b286cd8b50631633e42cded58a3c937a2780bcc43be","src/builtins/filters/mod.rs":"c43a98c02fb6fd6a004a83a4ec354776f607e06ea49455cbf2244d8e2eae0813","src/builtins/filters/number.rs":"a11e58df392214c9a79ac6407d8342ddee63650d714fdb1c017de3d9440c789c","src/builtins/filters/object.rs":"0830e336162f9b2c087d5f7c3c93397d36f8f4006325397e2cb2125e9f74b5f8","src/builtins/filters/string.rs":"efd58d85e7f24e5519754178ebfa766ccae75eaa93bc296c171a1ca142c65ada","src/builtins/functions.rs":"f6909e6bf01f83a92fe2dc83e9b3f2cf89421fe460459a1e0638aff5ae1cfb7f","src/builtins/mod.rs":"c4ceef5b71551ba03d13fbd13c38fac8bbd400a876c2231bf0c147be5aff7961","src/builtins/testers.rs":"59b2e01b95f54e3f8d071b80b6ca6fcdb9037c97cc3a049bbd53130d8fd8252a","src/context.rs":"24ca24b1bafa20f4216c73b7dcdd41447859c8bff0b82a04e373dc589212a5db","src/errors.rs":"d11430e398fa5fb1b15dd83d9c857c6609fad3d31b32dd17e6d13f31462422fd","src/filter_utils.rs":"47537ac679b8ce44f92f33dd76f42c29429187957a0d26fc84bf1fa0bf586713","src/lib.rs":"a40af2e5da00e749e231b162db6983287a20bac0146392d2c8a723b5d2c0ec7a","src/macros.rs":"528c909760c0335cbf0763455256789d274e23d8e4990db905db283680fdd3b0","src/parser/ast.rs":"53b00e928834422c5fc00c68354857ebe7472ddbd90728379729c11f436f1d20","src/parser/mod.rs":"0816dc78bf881f2f451be31e491c51029c6e5e35e4dd53332212a80bd4aa1e70","src/parser/tera.pest":"22f76275442cdff803d81485cbfa43bff3041ae6cef97ff8bc0fb3f3afa4aab1","src/parser/tests/errors.rs":"18f86f7159e2b1bb97121d031662ffbdf9617c5629930b24d7918e2cca2144e6","src/parser/tests/lexer.rs":"74108004ba3c6ab7d657c9184b8a15a4ad96dbe4f5c863141ae2b50da6a99d55","src/parser/tests/mod.rs":"a1f1580db6a0d5b45d1ae15dfed8fad1a50fd9d57c763a87566b6695fccab889","src/parser/tests/parser.rs":"e57e4801b45f4a418407cfba4d49146744296787483707bacbbe6e2dbfd890d1","src/parser/tests/whitespace.rs":"31ba16aebfd9f231080e6d62253a843b465fda2fb602622797f7852849f04c53","src/parser/whitespace.rs":"696bc5eb68526431643cce25740854fa1dd28e92e5f78c5381635ff776e59351","src/renderer/call_stack.rs":"61b8c066a4ccd1f39e4ed5579eac02778cc174906484fffcd3fd9bde3ded1669","src/renderer/for_loop.rs":"891c41d8d5b7fde85fe3bd3d77965d9eda872b1b1102f77a04bfc84a8db96728","src/renderer/macros.rs":"b6e09a21a7e2b7aa7d8e202794be51b448d803df8be0f5c36690a87a07943da8","src/renderer/mod.rs":"b50d68009d92177e8fda94c8c8495b50f015291a6e1fbf09ae002aa2e6d59e67","src/renderer/processor.rs":"0e006ad41a9bfbd193bb770d05ba15b9b87e97347f59a4b1bceda5eab30eaf77","src/renderer/square_brackets.rs":"69b21dd48e2520b3360111f6c6f125b8ab702cc52affe5b047fccb3eda38e07d","src/renderer/stack_frame.rs":"c443d1c041ad908e1e77f8d94dda712b32022b45b5ebee44c0b94f3360f9d275","src/renderer/tests/basic.rs":"e6e998975dee9bca439ee6d215646c698a8eefff0b0b3eeefc39adf8efef4487","src/renderer/tests/errors.rs":"26e5c75ff94b92ea0f5e01f365650f5e8626134a32c076e089534875ed885c69","src/renderer/tests/inheritance.rs":"14475f5bcbae86a0acc1d1547a8f20177b839ec09341758a82525ef71fc7d366","src/renderer/tests/macros.rs":"a5521c238eb14331b6fea44b81f6b1e0f50d84a263fc7cbedd87f6c18fae2545","src/renderer/tests/mod.rs":"1ca5a8f0a0921517519844cf79cd86f302e91d284d3866b733397982589a25cd","src/renderer/tests/square_brackets.rs":"0d0c2387c9680bd40ddff9a5ab3ce89a24bc9b1a12e335c9311500cd1aa9182f","src/renderer/tests/whitespace.rs":"849b1098e868522af69c5c97614a695182a54a505241d8c5ccf3b9f240f40742","src/template.rs":"727be805f5859344270627f188f61ac65990f320e79961d0a616694819b65e92","src/tera.rs":"6c851cc2fcd90fe08cd5a72f60c4470a0ab9b092acd144f2a92e29429016aabd","src/utils.rs":"d1ab843cd3ab5893207970b3913609817cda7fb57b3d22bd719574a71f7a788b"},"package":"81060acb882480c8793782eb96bc86f5c83d2fc7175ad46c375c6956ef7afa62"}
\ No newline at end of file
diff --git a/vendor/tera/CHANGELOG.md b/vendor/tera/CHANGELOG.md
new file mode 100644 (file)
index 0000000..2d9184d
--- /dev/null
@@ -0,0 +1,466 @@
+# Changelog
+
+## 1.10.0 (2021-05-21)
+
+- Add `Tera::get_template_names`
+
+## 1.9.0 (2021-05-16)
+
+- Add `Context::remove`
+
+## 1.8.0 (2021-04-21)
+
+- Add `linebreaksbr` filter from Django
+- Allow dots in context object key names
+
+## 1.7.1 (2021-04-12)
+
+- Fix parsing of filter arguments separated by whitespaces
+
+## 1.7.0 (2021-03-07)
+
+- Allow rendering to `std::io::Write`
+- Follow symlinks in glob
+- Allow including lists of templates
+- Comment tags can now use whitespace control
+
+## 1.6.1 (2020-12-29)
+
+- Fix date filter sometimes panicking with some format input
+
+## 1.6.0 (2020-12-19)
+
+- Allow multiline function kwargs with trailing comma
+- Add `Context::try_insert`
+
+## 1.5.0 (2020-08-10)
+
+- Add the concept of safe functions and filters
+- Allow negative index on `slice` filter
+
+## 1.4.0 (2020-07-24)
+
+- Add `Context::get` and `Context::contains_key`
+
+## 1.3.1 (2020-06-09)
+
+- Fix `raw` tag swallowing all whitespace at beginning and end
+- Make batch template sources generic
+- Automatically add function/test/filter function name to their error message
+
+## 1.3.0 (2020-05-16)
+
+- Add a `urlencode_strict` filter
+- Add more array literals feature in templates
+- Make `filter` filter value argument optional
+
+## 1.2.0 (2020-03-29)
+
+- Add `trim_start`, `trim_end`, `trim_start_matches` and `trim_end_matches` filters
+- Allow blocks in filter sections
+
+## 1.1.0 (2020-03-08)
+
+- Add Tera::render_str, like Tera::one_off but can use an existing Tera instance
+
+## 1.0.2 (2020-01-13)
+
+- Length filter now errors for things other than array, objects and strings. The fact that it was returning 0 before
+for other types was something that should have been fixed before 1.0 but got forgotten and was considered a bug.
+
+
+## 1.0.1 (2019-12-18)
+
+- Fix filter sections not keeping whitespaces
+- The filesizeformat filter now takes a usize instead of a i64: no changes to behaviour
+
+## 1.0.0 (2019-12-07)
+
+### Breaking changes
+
+- Now requires Rust 1.34
+- Removed error-chain errors and added rich Error enum instead
+- Filter, Tester and Function are now traits and now take borrowed values instead of owned
+- Updated for 2018 edition
+- Require macros import to be at the top of the files along with `extends` as it is fairly cheap and
+the code already only really look there.
+- Enforce spacing in tags at the parser, before `ifsomething` was considered ok
+- Pluralize filter now uses `singular` and `plural` arguments instead of `suffix`
+- Add a test for checking whether a variable is an object
+- Escaping now happens before inserting the final result of an expression: no need anymore to add `| safe` everywhere,
+only at the last position
+- Remove `safe` argument of the urlencode filter, `/` is still escaped by default
+- The `compile_templates!` macro has been removed
+
+### Others
+
+- Tests can now use `value is not defined` order for negation (https://github.com/Keats/tera/issues/308)
+- Add `nth` filter to get the nth value in an array
+- You can now use glob patterns in `Tera::new`
+- `default` filter now works on Null values
+- Literal numbers in template overflowing i64/f64 will now be an error instead of panicking
+- Allow arrays as test arguments
+- Add the `in` operator to check if a left operand is contained in a right one. Also supports negation as `not in`
+- Add `Context::from_value` to instantiate a `Context` from a serde_json `Value`
+- Add `Context::from_serialize` to instantiate a `Context` from something that impl `Serialize`
+- Make tests helper fns `number_args_allowed`, `value_defined` and `extract_string` public
+- Add `else` clause to for loops
+- Filters are now evaluated when checking if/elif conditions
+- Allow `{{-` and `-}}` for whitespace management
+- Add `xml_escape` filter
+- Grave accent is no longer escaped in HTML, it is not really needed anymore
+- Add a `builtins` default feature that gate all filters/functions requiring additional dependencies
+- Add `unique` and `map` filter
+- Add a `timezone` attribute to the `date` filter
+- Add a `get_random` function to get a random number in a range
+- Add a `get_env` function to get the value of an environment variable
+
+## 0.11.20 (2018-11-14)
+
+- Fix bugs in `filter` and `get` filters
+
+## 0.11.19 (2018-10-31)
+
+- Allow function calls in math expressions
+- Allow string concatenation to start with a number
+- Allow function calls in string concatenations
+- Add a `concat` filter to concat arrays or push an element to an array
+
+## 0.11.18 (2018-10-16)
+
+- Allow concatenation of strings and numbers
+
+## 0.11.17 (2018-10-09)
+
+- Clear local context on each forloop iteration
+- Fix variable lookup with `.` that was completely wrong
+- Now requires Rust 1.26 because of some dependencies update
+
+## 0.11.16 (2018-09-12)
+
+- Fix `set`/`set_global` not working correctly in macros
+- Deprecate `register_global_function` for `register_function`
+
+## 0.11.15 (2018-09-09)
+
+- Remove invalid `unreachable!` call causing panic in some combination or for loop and specific filters
+- Fix macros loading in parent templates and using them in child ones
+- Fix macros loading other macros not working when called in inheritance
+- Mark `Context::add` as deprecated and do not display it in the docs anymore (aka TIL the `deprecated` attribute)
+- Fix `__tera_context` not getting all the available context (`set`, `forloop` etc)
+- Better error message when variable indexing fails
+
+## 0.11.14 (2018-09-02)
+
+- Remove stray println
+
+## 0.11.13 (2018-09-02)
+
+- Add `as_str` filter
+- Way fewer allocations and significant speedup (2-5x) for templates with large objects/loops
+- Checks that all macro files are accounted for at compile time and errors if it's not the case
+
+## 0.11.12 (2018-08-04)
+
+- `filter` filter was not properly registered (╯°□°)╯︵ ┻━┻
+
+## 0.11.11 (2018-08-01)
+
+- `truncate` filter now works correctly on multichar graphemes
+
+## 0.11.10 (2018-08-01)
+
+- Add a `throw` global function to fail rendering from inside a template
+
+## 0.11.9 (2018-07-16)
+
+- Add a `matching` tester
+- Register `now` global function so it is available
+- Update `error-chain`
+
+## 0.11.8 (2018-06-20)
+
+- Add `True` and `False` as boolean values to match Python
+- Allow user to define their own escape function, if you want to generate JSON for example
+- Add `end` argument to the `truncate` filter to override the default ellipsis
+- Add a `group_by` filter
+- Add a `filter` filter
+- Add the `~` operator to concatenate strings
+- Add a `now` global function to get local and UTC datetimes
+- Add feature to enable the `preserve_order` feature of serde_json
+- Less confusing behaviour with math arithmetics
+
+## 0.11.7 (2018-04-24)
+
+- Add array literal instantiation from inside Tera for set, set_global, kwargs
+and for loop container
+- Fix panic on truncate filter
+
+## 0.11.6 (2018-03-25)
+
+- Add `break` and `continue` to forloops
+- Fix strings delimited by single quote and backtick not removing the delimiters
+
+
+## 0.11.5 (2018-03-01)
+
+- Re-export `serde_json::Number` as well
+
+## 0.11.4 (2018-02-28)
+
+- Re-export `serde_json::Map` as well
+- You can now access inside a variable using index notation: `{{ arr[0] }}`, `{{ arr[idx] }}` etc
+thanks to @bootandy
+- Add `Context::insert` identical to `Context::add` to mirror Rust HashMap/BTreeMap syntax
+
+
+## 0.11.3 (2018-02-15)
+
+- Add a `slice` filter for arrays
+- Fix macro files importing other macro files not loading properly
+- Fix forloop container being allowed logic expressions
+- Much improved parsing error messages
+
+## 0.11.2 (2018-02-01)
+
+- Fix regression when including templates that import macros
+- Fix `pluralize` filter for real this time!
+
+## 0.11.1 (2018-01-25)
+
+- Fix regression with expressions in comparisons
+
+## 0.11.0 (2018-01-22)
+
+### Breaking changes
+
+- Tests parentheses are now mandatory if there are arguments (`divisibleby 2` -> `divisibleby(2)`)
+- Tests can be only used on variables now, not on expressions
+- Escaping happens immediately now instead of waiting for the filters to be called, unless `safe` is first.
+If you want the old behaviour you will need to start the a chain of filters with `| safe` as the first one
+
+### Others
+
+- Tests, global functions calls and macro calls are now expressions and can be combined like so: `if x is divisibleby(2) and x > 10`
+- Add default arguments for macro arguments
+- Add whitespace management similar to Liquid and Jinja2
+- Add parentheses to expressions to remove ambiguities
+- Block & macro end tag name are no longer mandatory and it doesn't error on mismatched names between
+the start and end tag anymore
+- Filters can now be applied to expressions
+- Add modulo operator `%` for math expressions
+- Allow comment tags before the extend tag
+- Make `NaiveDateTime` work with the `date` filter
+- `pluralize` filter now returns the plural suffix for 0 thing as it's apparently what English does
+- Add a `set_global` tag that allows you to set something in the global context: meant to be used in forloops where
+the normal `set` would put the value into the loop context
+- Add `starting_with`, `ending_with` and `containing` tests
+- Add `json_encode`, `default` and `sort` filters
+- Strings can now also be contained in backticks and single quotes in templates
+
+## 0.10.10 (2017-08-24)
+
+- Add `Tera::parse` for some niche use-cases
+
+## 0.10.9 (2017-08-02)
+
+- Handle path to templates starting with "./"
+- Fix loop and macro context overlaps
+- Fix variables being escaped when given to `set` or as arguments to filters/macros/global fns
+
+## 0.10.8 (2017-06-24)
+
+- Update chrono
+
+## 0.10.7 (2017-06-16)
+
+- Fix not being able to use variables starting with `or`, `and` and `not`
+- Fix `<=` and `>=` not being recognised properly
+- Fix if/elif conditions falling through: only the first valid one will be rendered
+- Handle NaN results in `{% set %}` instead of panicking
+- Allow math node on if/elif conditions & fix f64 truthiness
+
+## 0.10.6 (2017-05-23)
+
+- Fix not being able to call global functions without arguments
+- Fix multiple inheritance not rendering blocks as expected for nested blocks
+- Allow filters on key/value for loop containers
+
+## 0.10.5 (2017-05-13)
+
+- Fix bug with `{% set %}` in forloops
+
+## 0.10.4 (2017-05-09)
+
+- Add `Send` to `GlobalFn` return type
+
+## 0.10.3 (2017-05-09)
+
+- Add global functions, see README
+- Add set tag, see README
+- Add get filter
+
+## 0.10.2 (2017-05-03)
+
+- Fix bug with section filter swallowing all content after the end tag
+- Allow whitespace in function args
+
+## 0.10.1 (2017-04-25)
+
+- Fix bug with variable in loop using starting with the container name (#165)
+- Allow whitespace in macros/filters params
+
+## 0.10.0 (2017-04-21)
+
+### Breaking changes
+- Update Serde to 1.0.0
+
+### Others
+- Fix date filter converting everything to UTC
+- Fix panic when using filters on forloop container
+
+## 0.9.0 (2017-04-05)
+
+### Breaking changes
+- Fix bug in Windows where the glob path was not removed correctly
+
+### Others
+- `Tera::extend` now also copy filters and testers
+
+
+## 0.8.1 (2017-03-15)
+
+- Macro rendering perf improved and general code cleanup thanks to @Peternator7
+- Fix bug in parser with floats
+- Make `date` filter work with string input in `YYYY-MM-DD` format
+- Big parsing improvement (~20-40%) for projects with macros and inheritance
+- Add `Tera::extend` to extend another instance of Tera
+- Add `Tera::full_reload` that will re-run the glob and parse all templates found.
+- Make `Tera::add_raw_template{s}` and `Tera::add_template_file{s}` part of the public API
+- Fix location in error message when erroring in a child template
+
+
+## 0.8.0 (2017-03-03)
+
+### Breaking changes
+- Remove `value_render` and `value_one_off`, you can now use `render` and `one_off`
+for both values and context
+
+### Others
+- Speed improvements on both parsing and rendering (~20-40% faster)
+- Better error message on variable lookup failure in loops
+- Can now iterate on maps/struct using the `{% for key, val in my_object %}` construct
+
+
+## 0.7.2 (2017-02-18)
+
+- Update chrono version
+- Make variable block like `{{ "hey" }}` render correctly
+
+## 0.7.1 (2017-02-05)
+
+- Support filter sections
+- Fix path prefix trimming on Windows
+
+## 0.7.0 (2017-02-01)
+
+### Breaking changes
+
+- `Tera::add_template` -> `Tera::add_raw_template`
+- `Tera::add_templates` -> `Tera::add_raw_templates`
+
+### Others
+
+- Performance improvement thanks to @clarcharr
+- Better error message for `value_render`. Thanks to @SilverWingedSeraph for the report
+- Hide `add_raw_template` and `add_raw_templates` from docs, they were meant for internal use
+- Exported macros now use the `$crate` variable, which means you don't need to import anything from Tera to have
+them working
+- Expose AST (not covered by semver)
+- Add a `Context::extend` method to merge a context object into another one
+
+## 0.6.2 (2017-01-08)
+
+- Performance improvements thanks to @wdv4758h
+- Correctly register `date` filter and make it work on a RFC3339 string as well thanks to @philwhineray
+
+## 0.6.1 (2016-12-28)
+
+- Added `Tera::value_one_off` to parse and render a single template using a
+Json value as context
+
+## 0.6.0 (2016-12-26)
+
+### BREAKING CHANGES
+- `not` is now a Tera keyword
+
+### Others
+- Added `#![deny(missing_docs)]` to the crate
+- Added `Tera::one_off` to parse and render a single template
+- Added `not` operator in conditions to mean falsiness (equivalent to `!` in Rust)
+- Remove specific error message when using `||` or `&&`
+- Improved performances for parsing and rendering (~5-20%)
+- Added `precision` arg to `round` filter
+- Added `date` filter to format a timestamp to a date(time) string
+
+## 0.5.0 (2016-12-19)
+
+A few breaking changes in this one
+
+### BREAKING CHANGES
+- Tera no longer panics when parsing templates, it returns an error instead
+- Tester fn signature changes from `fn(&str, Option<Value>, Vec<Value>) -> Result<bool>` to `fn(Option<Value>, Vec<Value>) -> Result<bool>`
+- Rename `TeraResult` export to `Result`
+
+### Others
+- Stabilized `Tera::add_template` and `Tera::add_templates`
+- Added `compile_templates!` macro to try to compile all templates and, in case of errors,
+print them and exit the process
+- Much improved error messages
+- Add a magical variable `__tera_context` that will pretty print the current context
+- More documentation inside the crate itself
+- Actually register the `filesizeformat`, `slugify`, `addslashes`, good thing no one noticed
+- Add `divisibleby` and `iterable` test
+- Made `try_get_value!` macro work outside of Tera
+
+## 0.4.1 (2016/12/07)
+
+- Remove println! left behind
+- Fix macros not being found in child templates
+- Export `Value` and `to_value` (currently from serde-json)
+
+## 0.4.0 (2016/12/02)
+- Add macros
+- Add `filesizeformat` filter
+- Add autoescape
+- Add multiple level inheritance
+- Add nested blocks
+- Add `{{ super() }}`
+
+Thanks to @SergioBenitez and @yonran for the help!
+
+
+## 0.3.1 (2016/10/11)
+- Fix regression when using variables in forloops + add test for it
+
+## 0.3.0 (2016/10/11)
+
+- Change signature of tests functions (BREAKING CHANGE)
+- Add more tests: `undefined`, `odd`, `even`, `number` and `string`
+- Add `include` directive to include another file
+- Indexed array/tuple access using the `.x` where `x` is an integer
+
+Thanks to @SergioBenitez and @andrelmartins for the contributions!
+
+
+## 0.2.0 (2016/09/27)
+
+- Added filters, see README for current list
+- Added tests, only `defined` for now
+
+Thanks to @SergioBenitez, @orhanbalci, @foophoof and @Peternator7 for the
+contribution!
+
+## 0.1.3 (2016/08/14)
+- Completely new parser
+- Expose TeraError
diff --git a/vendor/tera/Cargo.toml b/vendor/tera/Cargo.toml
new file mode 100644 (file)
index 0000000..4c675dc
--- /dev/null
@@ -0,0 +1,88 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "tera"
+version = "1.10.0"
+authors = ["Vincent Prouillet <hello@prouilletvincent.com>"]
+include = ["src/**/*", "LICENSE", "README.md", "CHANGELOG.md"]
+description = "Template engine based on Jinja2/Django templates"
+homepage = "https://tera.netlify.com/"
+readme = "README.md"
+keywords = ["template", "html", "django", "markup", "jinja2"]
+categories = ["template-engine"]
+license = "MIT"
+repository = "https://github.com/Keats/tera"
+[dependencies.chrono]
+version = "0.4.1"
+optional = true
+
+[dependencies.chrono-tz]
+version = "0.5"
+optional = true
+
+[dependencies.globwalk]
+version = "0.8.1"
+
+[dependencies.humansize]
+version = "1"
+optional = true
+
+[dependencies.lazy_static]
+version = "1.0"
+
+[dependencies.percent-encoding]
+version = "2.1"
+optional = true
+
+[dependencies.pest]
+version = "2.0.2"
+
+[dependencies.pest_derive]
+version = "2.0.2"
+
+[dependencies.rand]
+version = "0.8"
+optional = true
+
+[dependencies.regex]
+version = "1.0"
+
+[dependencies.serde]
+version = "1.0"
+
+[dependencies.serde_json]
+version = "1.0.11"
+
+[dependencies.slug]
+version = "0.1.1"
+optional = true
+
+[dependencies.unic-segment]
+version = "0.9"
+optional = true
+[dev-dependencies.pretty_assertions]
+version = "0.7"
+
+[dev-dependencies.serde_derive]
+version = "1.0"
+
+[dev-dependencies.tempfile]
+version = "3"
+
+[features]
+builtins = ["slug", "percent-encoding", "humansize", "chrono", "chrono-tz", "unic-segment", "rand"]
+default = ["builtins"]
+preserve_order = ["serde_json/preserve_order"]
+[badges.maintenance]
+status = "actively-developed"
diff --git a/vendor/tera/LICENSE b/vendor/tera/LICENSE
new file mode 100644 (file)
index 0000000..d7cee1a
--- /dev/null
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Vincent Prouillet
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/vendor/tera/README.md b/vendor/tera/README.md
new file mode 100644 (file)
index 0000000..6ca9b6c
--- /dev/null
@@ -0,0 +1,31 @@
+# Tera
+
+[![Actions Status](https://github.com/Keats/tera/workflows/ci/badge.svg)](https://github.com/Keats/tera/actions)
+[![Crates.io](https://img.shields.io/crates/v/tera.svg)](https://crates.io/crates/tera)
+[![Docs](https://docs.rs/tera/badge.svg)](https://docs.rs/crate/tera/)
+[![Gitter](https://badges.gitter.im/Tera-templates/community.svg)](https://gitter.im/Tera-templates/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
+
+Tera is a template engine inspired by [Jinja2](http://jinja.pocoo.org/) and the [Django template language](https://docs.djangoproject.com/en/3.1/topics/templates/).
+
+```jinja2
+<title>{% block title %}{% endblock title %}</title>
+<ul>
+{% for user in users %}
+  <li><a href="{{ user.url }}">{{ user.username }}</a></li>
+{% endfor %}
+</ul>
+```
+
+It does not aim to be 100% compatible with them but has many of the Jinja2/Django filters and testers.
+
+## Documentation
+API documentation is available on [docs.rs](https://docs.rs/crate/tera/).
+
+Tera documentation is available on its [site](https://tera.netlify.app/docs).
+
+## Community
+There's a gitter community chat (not managed/used by @Keats): https://gitter.im/Tera-templates/community
+
+## SemVer
+This project follows SemVer only for the public API, public API here meaning functions appearing in the docs.
+Some features, like accessing the AST, are also available but breaking changes in them can happen in any versions.
diff --git a/vendor/tera/docs/README.md b/vendor/tera/docs/README.md
new file mode 100644 (file)
index 0000000..1f91851
--- /dev/null
@@ -0,0 +1,4 @@
+# Tera documentation
+
+Uses [Zola](https://www.getzola.org/), see `netlify.toml` for
+the exact version
diff --git a/vendor/tera/src/builtins/filters/array.rs b/vendor/tera/src/builtins/filters/array.rs
new file mode 100644 (file)
index 0000000..91f8c27
--- /dev/null
@@ -0,0 +1,835 @@
+/// Filters operating on array
+use std::collections::HashMap;
+
+use crate::context::{get_json_pointer, ValueRender};
+use crate::errors::{Error, Result};
+use crate::filter_utils::{get_sort_strategy_for_type, get_unique_strategy_for_type};
+use crate::utils::render_to_string;
+use serde_json::value::{to_value, Map, Value};
+
+/// Returns the nth value of an array
+/// If the array is empty, returns empty string
+pub fn nth(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let arr = try_get_value!("nth", "value", Vec<Value>, value);
+
+    if arr.is_empty() {
+        return Ok(to_value("").unwrap());
+    }
+
+    let index = match args.get("n") {
+        Some(val) => try_get_value!("nth", "n", usize, val),
+        None => return Err(Error::msg("The `nth` filter has to have an `n` argument")),
+    };
+
+    Ok(arr.get(index).unwrap_or(&to_value("").unwrap()).to_owned())
+}
+
+/// Returns the first value of an array
+/// If the array is empty, returns empty string
+pub fn first(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let mut arr = try_get_value!("first", "value", Vec<Value>, value);
+
+    if arr.is_empty() {
+        Ok(to_value("").unwrap())
+    } else {
+        Ok(arr.swap_remove(0))
+    }
+}
+
+/// Returns the last value of an array
+/// If the array is empty, returns empty string
+pub fn last(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let mut arr = try_get_value!("last", "value", Vec<Value>, value);
+
+    Ok(arr.pop().unwrap_or_else(|| to_value("").unwrap()))
+}
+
+/// Joins all values in the array by the `sep` argument given
+/// If no separator is given, it will use `""` (empty string) as separator
+/// If the array is empty, returns empty string
+pub fn join(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let arr = try_get_value!("join", "value", Vec<Value>, value);
+    let sep = match args.get("sep") {
+        Some(val) => try_get_value!("truncate", "sep", String, val),
+        None => String::new(),
+    };
+
+    // Convert all the values to strings before we join them together.
+    let rendered = arr
+        .iter()
+        .map(|v| render_to_string(|| "joining array".to_string(), |w| v.render(w)))
+        .collect::<Result<Vec<_>>>()?;
+    to_value(&rendered.join(&sep)).map_err(Error::json)
+}
+
+/// Sorts the array in ascending order.
+/// Use the 'attribute' argument to define a field to sort by.
+pub fn sort(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let arr = try_get_value!("sort", "value", Vec<Value>, value);
+    if arr.is_empty() {
+        return Ok(arr.into());
+    }
+
+    let attribute = match args.get("attribute") {
+        Some(val) => try_get_value!("sort", "attribute", String, val),
+        None => String::new(),
+    };
+    let ptr = match attribute.as_str() {
+        "" => "".to_string(),
+        s => get_json_pointer(s),
+    };
+
+    let first = arr[0].pointer(&ptr).ok_or_else(|| {
+        Error::msg(format!("attribute '{}' does not reference a field", attribute))
+    })?;
+
+    let mut strategy = get_sort_strategy_for_type(first)?;
+    for v in &arr {
+        let key = v.pointer(&ptr).ok_or_else(|| {
+            Error::msg(format!("attribute '{}' does not reference a field", attribute))
+        })?;
+        strategy.try_add_pair(v, key)?;
+    }
+    let sorted = strategy.sort();
+
+    Ok(sorted.into())
+}
+
+/// Remove duplicates from an array.
+/// Use the 'attribute' argument to define a field to filter on.
+/// For strings, use the 'case_sensitive' argument (defaults to false) to control the comparison.
+pub fn unique(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let arr = try_get_value!("unique", "value", Vec<Value>, value);
+    if arr.is_empty() {
+        return Ok(arr.into());
+    }
+
+    let case_sensitive = match args.get("case_sensitive") {
+        Some(val) => try_get_value!("unique", "case_sensitive", bool, val),
+        None => false,
+    };
+
+    let attribute = match args.get("attribute") {
+        Some(val) => try_get_value!("unique", "attribute", String, val),
+        None => String::new(),
+    };
+    let ptr = match attribute.as_str() {
+        "" => "".to_string(),
+        s => get_json_pointer(s),
+    };
+
+    let first = arr[0].pointer(&ptr).ok_or_else(|| {
+        Error::msg(format!("attribute '{}' does not reference a field", attribute))
+    })?;
+
+    let disc = std::mem::discriminant(first);
+    let mut strategy = get_unique_strategy_for_type(first, case_sensitive)?;
+
+    let arr = arr
+        .into_iter()
+        .filter_map(|v| match v.pointer(&ptr) {
+            Some(key) => {
+                if disc == std::mem::discriminant(key) {
+                    match strategy.insert(key) {
+                        Ok(false) => None,
+                        Ok(true) => Some(Ok(v)),
+                        Err(e) => Some(Err(e)),
+                    }
+                } else {
+                    Some(Err(Error::msg("unique filter can't compare multiple types")))
+                }
+            }
+            None => None,
+        })
+        .collect::<Result<Vec<_>>>();
+
+    Ok(to_value(arr?).unwrap())
+}
+
+/// Group the array values by the `attribute` given
+/// Returns a hashmap of key => values, items without the `attribute` or where `attribute` is `null` are discarded.
+/// The returned keys are stringified
+pub fn group_by(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let arr = try_get_value!("group_by", "value", Vec<Value>, value);
+    if arr.is_empty() {
+        return Ok(Map::new().into());
+    }
+
+    let key = match args.get("attribute") {
+        Some(val) => try_get_value!("group_by", "attribute", String, val),
+        None => {
+            return Err(Error::msg("The `group_by` filter has to have an `attribute` argument"))
+        }
+    };
+
+    let mut grouped = Map::new();
+    let json_pointer = get_json_pointer(&key);
+
+    for val in arr {
+        if let Some(key_val) = val.pointer(&json_pointer).cloned() {
+            if key_val.is_null() {
+                continue;
+            }
+
+            let str_key = match key_val.as_str() {
+                Some(key) => key.to_owned(),
+                None => format!("{}", key_val),
+            };
+
+            if let Some(vals) = grouped.get_mut(&str_key) {
+                vals.as_array_mut().unwrap().push(val);
+                continue;
+            }
+
+            grouped.insert(str_key, Value::Array(vec![val]));
+        }
+    }
+
+    Ok(to_value(grouped).unwrap())
+}
+
+/// Filter the array values, returning only the values where the `attribute` is equal to the `value`
+/// Values without the `attribute` or with a null `attribute` are discarded
+/// If the `value` is not passed, discard all elements where the attribute is null.
+pub fn filter(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let mut arr = try_get_value!("filter", "value", Vec<Value>, value);
+    if arr.is_empty() {
+        return Ok(arr.into());
+    }
+
+    let key = match args.get("attribute") {
+        Some(val) => try_get_value!("filter", "attribute", String, val),
+        None => return Err(Error::msg("The `filter` filter has to have an `attribute` argument")),
+    };
+    let value = args.get("value").unwrap_or(&Value::Null);
+
+    let json_pointer = get_json_pointer(&key);
+    arr = arr
+        .into_iter()
+        .filter(|v| {
+            let val = v.pointer(&json_pointer).unwrap_or(&Value::Null);
+            if value.is_null() {
+                !val.is_null()
+            } else {
+                val == value
+            }
+        })
+        .collect::<Vec<_>>();
+
+    Ok(to_value(arr).unwrap())
+}
+
+/// Map retrieves an attribute from a list of objects.
+/// The 'attribute' argument specifies what to retrieve.
+pub fn map(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let arr = try_get_value!("map", "value", Vec<Value>, value);
+    if arr.is_empty() {
+        return Ok(arr.into());
+    }
+
+    let attribute = match args.get("attribute") {
+        Some(val) => try_get_value!("map", "attribute", String, val),
+        None => return Err(Error::msg("The `map` filter has to have an `attribute` argument")),
+    };
+
+    let json_pointer = get_json_pointer(&attribute);
+    let arr = arr
+        .into_iter()
+        .filter_map(|v| match v.pointer(&json_pointer) {
+            Some(val) if !val.is_null() => Some(val.clone()),
+            _ => None,
+        })
+        .collect::<Vec<_>>();
+
+    Ok(to_value(arr).unwrap())
+}
+
+#[inline]
+fn get_index(i: f64, array: &[Value]) -> usize {
+    if i >= 0.0 {
+        i as usize
+    } else {
+        (array.len() as f64 + i) as usize
+    }
+}
+
+/// Slice the array
+/// Use the `start` argument to define where to start (inclusive, default to `0`)
+/// and `end` argument to define where to stop (exclusive, default to the length of the array)
+/// `start` and `end` are 0-indexed
+pub fn slice(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let arr = try_get_value!("slice", "value", Vec<Value>, value);
+    if arr.is_empty() {
+        return Ok(arr.into());
+    }
+
+    let start = match args.get("start") {
+        Some(val) => get_index(try_get_value!("slice", "start", f64, val), &arr),
+        None => 0,
+    };
+
+    // Not an error, but returns an empty Vec
+    if start > arr.len() {
+        return Ok(Vec::<Value>::new().into());
+    }
+
+    let mut end = match args.get("end") {
+        Some(val) => get_index(try_get_value!("slice", "end", f64, val), &arr),
+        None => arr.len(),
+    };
+
+    if end > arr.len() {
+        end = arr.len();
+    }
+
+    Ok(arr[start..end].into())
+}
+
+/// Concat the array with another one if the `with` parameter is an array or
+/// just append it otherwise
+pub fn concat(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let mut arr = try_get_value!("concat", "value", Vec<Value>, value);
+
+    let value = match args.get("with") {
+        Some(val) => val,
+        None => return Err(Error::msg("The `concat` filter has to have a `with` argument")),
+    };
+
+    if value.is_array() {
+        match value {
+            Value::Array(vals) => {
+                for val in vals {
+                    arr.push(val.clone());
+                }
+            }
+            _ => unreachable!("Got something other than an array??"),
+        }
+    } else {
+        arr.push(value.clone());
+    }
+
+    Ok(to_value(arr).unwrap())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use serde_derive::{Deserialize, Serialize};
+    use serde_json::json;
+    use serde_json::value::{to_value, Value};
+    use std::collections::HashMap;
+
+    #[test]
+    fn test_nth() {
+        let mut args = HashMap::new();
+        args.insert("n".to_string(), to_value(1).unwrap());
+        let result = nth(&to_value(&vec![1, 2, 3, 4]).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(&2).unwrap());
+    }
+
+    #[test]
+    fn test_nth_empty() {
+        let v: Vec<Value> = Vec::new();
+        let mut args = HashMap::new();
+        args.insert("n".to_string(), to_value(1).unwrap());
+        let result = nth(&to_value(&v).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("").unwrap());
+    }
+
+    #[test]
+    fn test_first() {
+        let result = first(&to_value(&vec![1, 2, 3, 4]).unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(&1).unwrap());
+    }
+
+    #[test]
+    fn test_first_empty() {
+        let v: Vec<Value> = Vec::new();
+
+        let result = first(&to_value(&v).unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.ok().unwrap(), to_value("").unwrap());
+    }
+
+    #[test]
+    fn test_last() {
+        let result = last(&to_value(&vec!["Hello", "World"]).unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("World").unwrap());
+    }
+
+    #[test]
+    fn test_last_empty() {
+        let v: Vec<Value> = Vec::new();
+
+        let result = last(&to_value(&v).unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.ok().unwrap(), to_value("").unwrap());
+    }
+
+    #[test]
+    fn test_join_sep() {
+        let mut args = HashMap::new();
+        args.insert("sep".to_owned(), to_value(&"==").unwrap());
+
+        let result = join(&to_value(&vec!["Cats", "Dogs"]).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(&"Cats==Dogs").unwrap());
+    }
+
+    #[test]
+    fn test_join_sep_omitted() {
+        let result = join(&to_value(&vec![1.2, 3.4]).unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(&"1.23.4").unwrap());
+    }
+
+    #[test]
+    fn test_join_empty() {
+        let v: Vec<Value> = Vec::new();
+        let mut args = HashMap::new();
+        args.insert("sep".to_owned(), to_value(&"==").unwrap());
+
+        let result = join(&to_value(&v).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(&"").unwrap());
+    }
+
+    #[test]
+    fn test_sort() {
+        let v = to_value(vec![3, -1, 2, 5, 4]).unwrap();
+        let args = HashMap::new();
+        let result = sort(&v, &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(vec![-1, 2, 3, 4, 5]).unwrap());
+    }
+
+    #[test]
+    fn test_sort_empty() {
+        let v = to_value(Vec::<f64>::new()).unwrap();
+        let args = HashMap::new();
+        let result = sort(&v, &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(Vec::<f64>::new()).unwrap());
+    }
+
+    #[derive(Deserialize, Eq, Hash, PartialEq, Serialize)]
+    struct Foo {
+        a: i32,
+        b: i32,
+    }
+
+    #[test]
+    fn test_sort_attribute() {
+        let v = to_value(vec![
+            Foo { a: 3, b: 5 },
+            Foo { a: 2, b: 8 },
+            Foo { a: 4, b: 7 },
+            Foo { a: 1, b: 6 },
+        ])
+        .unwrap();
+        let mut args = HashMap::new();
+        args.insert("attribute".to_string(), to_value(&"a").unwrap());
+
+        let result = sort(&v, &args);
+        assert!(result.is_ok());
+        assert_eq!(
+            result.unwrap(),
+            to_value(vec![
+                Foo { a: 1, b: 6 },
+                Foo { a: 2, b: 8 },
+                Foo { a: 3, b: 5 },
+                Foo { a: 4, b: 7 },
+            ])
+            .unwrap()
+        );
+    }
+
+    #[test]
+    fn test_sort_invalid_attribute() {
+        let v = to_value(vec![Foo { a: 3, b: 5 }]).unwrap();
+        let mut args = HashMap::new();
+        args.insert("attribute".to_string(), to_value(&"invalid_field").unwrap());
+
+        let result = sort(&v, &args);
+        assert!(result.is_err());
+        assert_eq!(
+            result.unwrap_err().to_string(),
+            "attribute 'invalid_field' does not reference a field"
+        );
+    }
+
+    #[test]
+    fn test_sort_multiple_types() {
+        let v = to_value(vec![Value::Number(12.into()), Value::Array(vec![])]).unwrap();
+        let args = HashMap::new();
+
+        let result = sort(&v, &args);
+        assert!(result.is_err());
+        assert_eq!(result.unwrap_err().to_string(), "expected number got []");
+    }
+
+    #[test]
+    fn test_sort_non_finite_numbers() {
+        let v = to_value(vec![
+            ::std::f64::NEG_INFINITY, // NaN and friends get deserialized as Null by serde.
+            ::std::f64::NAN,
+        ])
+        .unwrap();
+        let args = HashMap::new();
+
+        let result = sort(&v, &args);
+        assert!(result.is_err());
+        assert_eq!(result.unwrap_err().to_string(), "Null is not a sortable value");
+    }
+
+    #[derive(Deserialize, Eq, Hash, PartialEq, Serialize)]
+    struct TupleStruct(i32, i32);
+
+    #[test]
+    fn test_sort_tuple() {
+        let v = to_value(vec![
+            TupleStruct(0, 1),
+            TupleStruct(7, 0),
+            TupleStruct(-1, 12),
+            TupleStruct(18, 18),
+        ])
+        .unwrap();
+        let mut args = HashMap::new();
+        args.insert("attribute".to_string(), to_value("0").unwrap());
+
+        let result = sort(&v, &args);
+        assert!(result.is_ok());
+        assert_eq!(
+            result.unwrap(),
+            to_value(vec![
+                TupleStruct(-1, 12),
+                TupleStruct(0, 1),
+                TupleStruct(7, 0),
+                TupleStruct(18, 18),
+            ])
+            .unwrap()
+        );
+    }
+
+    #[test]
+    fn test_unique_numbers() {
+        let v = to_value(vec![3, -1, 3, 3, 5, 2, 5, 4]).unwrap();
+        let args = HashMap::new();
+        let result = unique(&v, &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(vec![3, -1, 5, 2, 4]).unwrap());
+    }
+
+    #[test]
+    fn test_unique_strings() {
+        let v = to_value(vec!["One", "Two", "Three", "one", "Two"]).unwrap();
+        let mut args = HashMap::new();
+        let result = unique(&v, &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(vec!["One", "Two", "Three"]).unwrap());
+
+        args.insert("case_sensitive".to_string(), to_value(true).unwrap());
+        let result = unique(&v, &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(vec!["One", "Two", "Three", "one"]).unwrap());
+    }
+
+    #[test]
+    fn test_unique_empty() {
+        let v = to_value(Vec::<f64>::new()).unwrap();
+        let args = HashMap::new();
+        let result = sort(&v, &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(Vec::<f64>::new()).unwrap());
+    }
+
+    #[test]
+    fn test_unique_attribute() {
+        let v = to_value(vec![
+            Foo { a: 1, b: 2 },
+            Foo { a: 3, b: 3 },
+            Foo { a: 1, b: 3 },
+            Foo { a: 0, b: 4 },
+        ])
+        .unwrap();
+        let mut args = HashMap::new();
+        args.insert("attribute".to_string(), to_value(&"a").unwrap());
+
+        let result = unique(&v, &args);
+        assert!(result.is_ok());
+        assert_eq!(
+            result.unwrap(),
+            to_value(vec![Foo { a: 1, b: 2 }, Foo { a: 3, b: 3 }, Foo { a: 0, b: 4 },]).unwrap()
+        );
+    }
+
+    #[test]
+    fn test_unique_invalid_attribute() {
+        let v = to_value(vec![Foo { a: 3, b: 5 }]).unwrap();
+        let mut args = HashMap::new();
+        args.insert("attribute".to_string(), to_value(&"invalid_field").unwrap());
+
+        let result = unique(&v, &args);
+        assert!(result.is_err());
+        assert_eq!(
+            result.unwrap_err().to_string(),
+            "attribute 'invalid_field' does not reference a field"
+        );
+    }
+
+    #[test]
+    fn test_unique_multiple_types() {
+        let v = to_value(vec![Value::Number(12.into()), Value::Array(vec![])]).unwrap();
+        let args = HashMap::new();
+
+        let result = unique(&v, &args);
+        assert!(result.is_err());
+        assert_eq!(result.unwrap_err().to_string(), "unique filter can't compare multiple types");
+    }
+
+    #[test]
+    fn test_unique_non_finite_numbers() {
+        let v = to_value(vec![
+            ::std::f64::NEG_INFINITY, // NaN and friends get deserialized as Null by serde.
+            ::std::f64::NAN,
+        ])
+        .unwrap();
+        let args = HashMap::new();
+
+        let result = unique(&v, &args);
+        assert!(result.is_err());
+        assert_eq!(result.unwrap_err().to_string(), "Null is not a unique value");
+    }
+
+    #[test]
+    fn test_unique_tuple() {
+        let v = to_value(vec![
+            TupleStruct(0, 1),
+            TupleStruct(-7, -1),
+            TupleStruct(-1, 1),
+            TupleStruct(18, 18),
+        ])
+        .unwrap();
+        let mut args = HashMap::new();
+        args.insert("attribute".to_string(), to_value("1").unwrap());
+
+        let result = unique(&v, &args);
+        assert!(result.is_ok());
+        assert_eq!(
+            result.unwrap(),
+            to_value(vec![TupleStruct(0, 1), TupleStruct(-7, -1), TupleStruct(18, 18),]).unwrap()
+        );
+    }
+
+    #[test]
+    fn test_slice() {
+        fn make_args(start: Option<usize>, end: Option<f64>) -> HashMap<String, Value> {
+            let mut args = HashMap::new();
+            if let Some(s) = start {
+                args.insert("start".to_string(), to_value(s).unwrap());
+            }
+            if let Some(e) = end {
+                args.insert("end".to_string(), to_value(e).unwrap());
+            }
+            args
+        }
+
+        let v = to_value(vec![1, 2, 3, 4, 5]).unwrap();
+
+        let inputs = vec![
+            (make_args(Some(1), None), vec![2, 3, 4, 5]),
+            (make_args(None, Some(2.0)), vec![1, 2]),
+            (make_args(Some(1), Some(2.0)), vec![2]),
+            (make_args(None, Some(-2.0)), vec![1, 2, 3]),
+            (make_args(None, None), vec![1, 2, 3, 4, 5]),
+        ];
+
+        for (args, expected) in inputs {
+            let res = slice(&v, &args);
+            assert!(res.is_ok());
+            assert_eq!(res.unwrap(), to_value(expected).unwrap());
+        }
+    }
+
+    #[test]
+    fn test_group_by() {
+        let input = json!([
+            {"id": 1, "year": 2015},
+            {"id": 2, "year": 2015},
+            {"id": 3, "year": 2016},
+            {"id": 4, "year": 2017},
+            {"id": 5, "year": 2017},
+            {"id": 6, "year": 2017},
+            {"id": 7, "year": 2018},
+            {"id": 8},
+            {"id": 9, "year": null},
+        ]);
+        let mut args = HashMap::new();
+        args.insert("attribute".to_string(), to_value("year").unwrap());
+
+        let expected = json!({
+            "2015": [{"id": 1, "year": 2015}, {"id": 2, "year": 2015}],
+            "2016": [{"id": 3, "year": 2016}],
+            "2017": [{"id": 4, "year": 2017}, {"id": 5, "year": 2017}, {"id": 6, "year": 2017}],
+            "2018": [{"id": 7, "year": 2018}],
+        });
+
+        let res = group_by(&input, &args);
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), to_value(expected).unwrap());
+    }
+
+    #[test]
+    fn test_group_by_nested_key() {
+        let input = json!([
+            {"id": 1, "company": {"id": 1}},
+            {"id": 2, "company": {"id": 2}},
+            {"id": 3, "company": {"id": 3}},
+            {"id": 4, "company": {"id": 4}},
+            {"id": 5, "company": {"id": 4}},
+            {"id": 6, "company": {"id": 5}},
+            {"id": 7, "company": {"id": 5}},
+            {"id": 8},
+            {"id": 9, "company": null},
+        ]);
+        let mut args = HashMap::new();
+        args.insert("attribute".to_string(), to_value("company.id").unwrap());
+
+        let expected = json!({
+            "1": [{"id": 1, "company": {"id": 1}}],
+            "2": [{"id": 2, "company": {"id": 2}}],
+            "3": [{"id": 3, "company": {"id": 3}}],
+            "4": [{"id": 4, "company": {"id": 4}}, {"id": 5, "company": {"id": 4}}],
+            "5": [{"id": 6, "company": {"id": 5}}, {"id": 7, "company": {"id": 5}}],
+        });
+
+        let res = group_by(&input, &args);
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), to_value(expected).unwrap());
+    }
+
+    #[test]
+    fn test_filter_empty() {
+        let res = filter(&json!([]), &HashMap::new());
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), json!([]));
+    }
+
+    #[test]
+    fn test_filter() {
+        let input = json!([
+            {"id": 1, "year": 2015},
+            {"id": 2, "year": 2015},
+            {"id": 3, "year": 2016},
+            {"id": 4, "year": 2017},
+            {"id": 5, "year": 2017},
+            {"id": 6, "year": 2017},
+            {"id": 7, "year": 2018},
+            {"id": 8},
+            {"id": 9, "year": null},
+        ]);
+        let mut args = HashMap::new();
+        args.insert("attribute".to_string(), to_value("year").unwrap());
+        args.insert("value".to_string(), to_value(2015).unwrap());
+
+        let expected = json!([
+            {"id": 1, "year": 2015},
+            {"id": 2, "year": 2015},
+        ]);
+
+        let res = filter(&input, &args);
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), to_value(expected).unwrap());
+    }
+
+    #[test]
+    fn test_filter_no_value() {
+        let input = json!([
+            {"id": 1, "year": 2015},
+            {"id": 2, "year": 2015},
+            {"id": 3, "year": 2016},
+            {"id": 4, "year": 2017},
+            {"id": 5, "year": 2017},
+            {"id": 6, "year": 2017},
+            {"id": 7, "year": 2018},
+            {"id": 8},
+            {"id": 9, "year": null},
+        ]);
+        let mut args = HashMap::new();
+        args.insert("attribute".to_string(), to_value("year").unwrap());
+
+        let expected = json!([
+            {"id": 1, "year": 2015},
+            {"id": 2, "year": 2015},
+            {"id": 3, "year": 2016},
+            {"id": 4, "year": 2017},
+            {"id": 5, "year": 2017},
+            {"id": 6, "year": 2017},
+            {"id": 7, "year": 2018},
+        ]);
+
+        let res = filter(&input, &args);
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), to_value(expected).unwrap());
+    }
+
+    #[test]
+    fn test_map_empty() {
+        let res = map(&json!([]), &HashMap::new());
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), json!([]));
+    }
+
+    #[test]
+    fn test_map() {
+        let input = json!([
+            {"id": 1, "year": 2015},
+            {"id": 2, "year": true},
+            {"id": 3, "year": 2016.5},
+            {"id": 4, "year": "2017"},
+            {"id": 5, "year": 2017},
+            {"id": 6, "year": 2017},
+            {"id": 7, "year": [1900, 1901]},
+            {"id": 8, "year": {"a": 2018, "b": 2019}},
+            {"id": 9},
+            {"id": 10, "year": null},
+        ]);
+        let mut args = HashMap::new();
+        args.insert("attribute".to_string(), to_value("year").unwrap());
+
+        let expected =
+            json!([2015, true, 2016.5, "2017", 2017, 2017, [1900, 1901], {"a": 2018, "b": 2019}]);
+
+        let res = map(&input, &args);
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), to_value(expected).unwrap());
+    }
+
+    #[test]
+    fn test_concat_array() {
+        let input = json!([1, 2, 3,]);
+        let mut args = HashMap::new();
+        args.insert("with".to_string(), json!([3, 4]));
+        let expected = json!([1, 2, 3, 3, 4,]);
+
+        let res = concat(&input, &args);
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), to_value(expected).unwrap());
+    }
+
+    #[test]
+    fn test_concat_single_value() {
+        let input = json!([1, 2, 3,]);
+        let mut args = HashMap::new();
+        args.insert("with".to_string(), json!(4));
+        let expected = json!([1, 2, 3, 4,]);
+
+        let res = concat(&input, &args);
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), to_value(expected).unwrap());
+    }
+}
diff --git a/vendor/tera/src/builtins/filters/common.rs b/vendor/tera/src/builtins/filters/common.rs
new file mode 100644 (file)
index 0000000..a5c7244
--- /dev/null
@@ -0,0 +1,357 @@
+/// Filters operating on multiple types
+use std::collections::HashMap;
+use std::iter::FromIterator;
+
+use crate::errors::{Error, Result};
+use crate::utils::render_to_string;
+#[cfg(feature = "builtins")]
+use chrono::{
+    format::{Item, StrftimeItems},
+    DateTime, FixedOffset, NaiveDate, NaiveDateTime, Utc,
+};
+#[cfg(feature = "builtins")]
+use chrono_tz::Tz;
+use serde_json::value::{to_value, Value};
+use serde_json::{to_string, to_string_pretty};
+
+use crate::context::ValueRender;
+
+// Returns the number of items in an array or an object, or the number of characters in a string.
+pub fn length(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    match value {
+        Value::Array(arr) => Ok(to_value(&arr.len()).unwrap()),
+        Value::Object(m) => Ok(to_value(&m.len()).unwrap()),
+        Value::String(s) => Ok(to_value(&s.chars().count()).unwrap()),
+        _ => Err(Error::msg(
+            "Filter `length` was used on a value that isn't an array, an object, or a string.",
+        )),
+    }
+}
+
+// Reverses the elements of an array or the characters in a string.
+pub fn reverse(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    match value {
+        Value::Array(arr) => {
+            let mut rev = arr.clone();
+            rev.reverse();
+            to_value(&rev).map_err(Error::json)
+        }
+        Value::String(s) => to_value(&String::from_iter(s.chars().rev())).map_err(Error::json),
+        _ => Err(Error::msg(format!(
+            "Filter `reverse` received an incorrect type for arg `value`: \
+             got `{}` but expected Array|String",
+            value
+        ))),
+    }
+}
+
+// Encodes a value of any type into json, optionally `pretty`-printing it
+// `pretty` can be true to enable pretty-print, or omitted for compact printing
+pub fn json_encode(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let pretty = args.get("pretty").and_then(Value::as_bool).unwrap_or(false);
+
+    if pretty {
+        to_string_pretty(&value).map(Value::String).map_err(Error::json)
+    } else {
+        to_string(&value).map(Value::String).map_err(Error::json)
+    }
+}
+
+/// Returns a formatted time according to the given `format` argument.
+/// `format` defaults to the ISO 8601 `YYYY-MM-DD` format.
+///
+/// Input can be an i64 timestamp (seconds since epoch) or an RFC3339 string
+/// (default serialization format for `chrono::DateTime`).
+///
+/// a full reference for the time formatting syntax is available
+/// on [chrono docs](https://lifthrasiir.github.io/rust-chrono/chrono/format/strftime/index.html)
+#[cfg(feature = "builtins")]
+pub fn date(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let format = match args.get("format") {
+        Some(val) => try_get_value!("date", "format", String, val),
+        None => "%Y-%m-%d".to_string(),
+    };
+
+    let items: Vec<Item> = StrftimeItems::new(&format)
+        .filter(|item| match item {
+            Item::Error => true,
+            _ => false,
+        })
+        .collect();
+    if !items.is_empty() {
+        return Err(Error::msg(format!("Invalid date format `{}`", format)));
+    }
+
+    let timezone = match args.get("timezone") {
+        Some(val) => {
+            let timezone = try_get_value!("date", "timezone", String, val);
+            match timezone.parse::<Tz>() {
+                Ok(timezone) => Some(timezone),
+                Err(_) => {
+                    return Err(Error::msg(format!("Error parsing `{}` as a timezone", timezone)))
+                }
+            }
+        }
+        None => None,
+    };
+
+    let formatted = match value {
+        Value::Number(n) => match n.as_i64() {
+            Some(i) => NaiveDateTime::from_timestamp(i, 0).format(&format),
+            None => return Err(Error::msg(format!("Filter `date` was invoked on a float: {}", n))),
+        },
+        Value::String(s) => {
+            if s.contains('T') {
+                match s.parse::<DateTime<FixedOffset>>() {
+                    Ok(val) => match timezone {
+                        Some(timezone) => val.with_timezone(&timezone).format(&format),
+                        None => val.format(&format),
+                    },
+                    Err(_) => match s.parse::<NaiveDateTime>() {
+                        Ok(val) => DateTime::<Utc>::from_utc(val, Utc).format(&format),
+                        Err(_) => {
+                            return Err(Error::msg(format!(
+                                "Error parsing `{:?}` as rfc3339 date or naive datetime",
+                                s
+                            )));
+                        }
+                    },
+                }
+            } else {
+                match NaiveDate::parse_from_str(&s, "%Y-%m-%d") {
+                    Ok(val) => DateTime::<Utc>::from_utc(val.and_hms(0, 0, 0), Utc).format(&format),
+                    Err(_) => {
+                        return Err(Error::msg(format!(
+                            "Error parsing `{:?}` as YYYY-MM-DD date",
+                            s
+                        )));
+                    }
+                }
+            }
+        }
+        _ => {
+            return Err(Error::msg(format!(
+                "Filter `date` received an incorrect type for arg `value`: \
+                 got `{:?}` but expected i64|u64|String",
+                value
+            )));
+        }
+    };
+
+    to_value(&formatted.to_string()).map_err(Error::json)
+}
+
+// Returns the given value as a string.
+pub fn as_str(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let value =
+        render_to_string(|| format!("as_str for value of kind {}", value), |w| value.render(w))?;
+    to_value(value).map_err(Error::json)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    #[cfg(feature = "builtins")]
+    use chrono::{DateTime, Local};
+    use serde_json;
+    use serde_json::value::to_value;
+    use std::collections::HashMap;
+
+    #[test]
+    fn as_str_object() {
+        let map: HashMap<String, String> = HashMap::new();
+        let result = as_str(&to_value(&map).unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(&"[object]").unwrap());
+    }
+
+    #[test]
+    fn as_str_vec() {
+        let result = as_str(&to_value(&vec![1, 2, 3, 4]).unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(&"[1, 2, 3, 4]").unwrap());
+    }
+
+    #[test]
+    fn length_vec() {
+        let result = length(&to_value(&vec![1, 2, 3, 4]).unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(&4).unwrap());
+    }
+
+    #[test]
+    fn length_object() {
+        let mut map: HashMap<String, String> = HashMap::new();
+        map.insert("foo".to_string(), "bar".to_string());
+        let result = length(&to_value(&map).unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(&1).unwrap());
+    }
+
+    #[test]
+    fn length_str() {
+        let result = length(&to_value(&"Hello World").unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(&11).unwrap());
+    }
+
+    #[test]
+    fn length_str_nonascii() {
+        let result = length(&to_value(&"日本語").unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(&3).unwrap());
+    }
+
+    #[test]
+    fn length_num() {
+        let result = length(&to_value(&15).unwrap(), &HashMap::new());
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn reverse_vec() {
+        let result = reverse(&to_value(&vec![1, 2, 3, 4]).unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(&vec![4, 3, 2, 1]).unwrap());
+    }
+
+    #[test]
+    fn reverse_str() {
+        let result = reverse(&to_value(&"Hello World").unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(&"dlroW olleH").unwrap());
+    }
+
+    #[test]
+    fn reverse_num() {
+        let result = reverse(&to_value(&1.23).unwrap(), &HashMap::new());
+        assert!(result.is_err());
+        assert_eq!(
+            result.err().unwrap().to_string(),
+            "Filter `reverse` received an incorrect type for arg `value`: got `1.23` but expected Array|String"
+        );
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn date_default() {
+        let args = HashMap::new();
+        let result = date(&to_value(1482720453).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("2016-12-26").unwrap());
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn date_custom_format() {
+        let mut args = HashMap::new();
+        args.insert("format".to_string(), to_value("%Y-%m-%d %H:%M").unwrap());
+        let result = date(&to_value(1482720453).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("2016-12-26 02:47").unwrap());
+    }
+
+    // https://zola.discourse.group/t/can-i-generate-a-random-number-within-a-range/238?u=keats
+    // https://github.com/chronotope/chrono/issues/47
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn date_errors_on_incorrect_format() {
+        let mut args = HashMap::new();
+        args.insert("format".to_string(), to_value("%2f").unwrap());
+        let result = date(&to_value(1482720453).unwrap(), &args);
+        assert!(result.is_err());
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn date_rfc3339() {
+        let args = HashMap::new();
+        let dt: DateTime<Local> = Local::now();
+        let result = date(&to_value(dt.to_rfc3339()).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(dt.format("%Y-%m-%d").to_string()).unwrap());
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn date_rfc3339_preserves_timezone() {
+        let mut args = HashMap::new();
+        args.insert("format".to_string(), to_value("%Y-%m-%d %z").unwrap());
+        let result = date(&to_value("1996-12-19T16:39:57-08:00").unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("1996-12-19 -0800").unwrap());
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn date_yyyy_mm_dd() {
+        let mut args = HashMap::new();
+        args.insert("format".to_string(), to_value("%a, %d %b %Y %H:%M:%S %z").unwrap());
+        let result = date(&to_value("2017-03-05").unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("Sun, 05 Mar 2017 00:00:00 +0000").unwrap());
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn date_from_naive_datetime() {
+        let mut args = HashMap::new();
+        args.insert("format".to_string(), to_value("%a, %d %b %Y %H:%M:%S").unwrap());
+        let result = date(&to_value("2017-03-05T00:00:00.602").unwrap(), &args);
+        println!("{:?}", result);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("Sun, 05 Mar 2017 00:00:00").unwrap());
+    }
+
+    // https://github.com/getzola/zola/issues/1279
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn date_format_doesnt_panic() {
+        let mut args = HashMap::new();
+        args.insert("format".to_string(), to_value("%+S").unwrap());
+        let result = date(&to_value("2017-01-01T00:00:00").unwrap(), &args);
+        assert!(result.is_ok());
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn date_with_timezone() {
+        let mut args = HashMap::new();
+        args.insert("timezone".to_string(), to_value("America/New_York").unwrap());
+        let result = date(&to_value("2019-09-19T01:48:44.581Z").unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("2019-09-18").unwrap());
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn date_with_invalid_timezone() {
+        let mut args = HashMap::new();
+        args.insert("timezone".to_string(), to_value("Narnia").unwrap());
+        let result = date(&to_value("2019-09-19T01:48:44.581Z").unwrap(), &args);
+        assert!(result.is_err());
+        assert_eq!(result.err().unwrap().to_string(), "Error parsing `Narnia` as a timezone");
+    }
+
+    #[test]
+    fn test_json_encode() {
+        let args = HashMap::new();
+        let result =
+            json_encode(&serde_json::from_str("{\"key\": [\"value1\", 2, true]}").unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("{\"key\":[\"value1\",2,true]}").unwrap());
+    }
+
+    #[test]
+    fn test_json_encode_pretty() {
+        let mut args = HashMap::new();
+        args.insert("pretty".to_string(), to_value(true).unwrap());
+        let result =
+            json_encode(&serde_json::from_str("{\"key\": [\"value1\", 2, true]}").unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(
+            result.unwrap(),
+            to_value("{\n  \"key\": [\n    \"value1\",\n    2,\n    true\n  ]\n}").unwrap()
+        );
+    }
+}
diff --git a/vendor/tera/src/builtins/filters/mod.rs b/vendor/tera/src/builtins/filters/mod.rs
new file mode 100644 (file)
index 0000000..03a6d45
--- /dev/null
@@ -0,0 +1,30 @@
+use std::collections::HashMap;
+
+use crate::errors::Result;
+use serde_json::value::Value;
+
+pub mod array;
+pub mod common;
+pub mod number;
+pub mod object;
+pub mod string;
+
+/// The filter function type definition
+pub trait Filter: Sync + Send {
+    /// The filter function type definition
+    fn filter(&self, value: &Value, args: &HashMap<String, Value>) -> Result<Value>;
+
+    /// Whether the current filter's output should be treated as safe, defaults to `false`
+    fn is_safe(&self) -> bool {
+        false
+    }
+}
+
+impl<F> Filter for F
+where
+    F: Fn(&Value, &HashMap<String, Value>) -> Result<Value> + Sync + Send,
+{
+    fn filter(&self, value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+        self(value, args)
+    }
+}
diff --git a/vendor/tera/src/builtins/filters/number.rs b/vendor/tera/src/builtins/filters/number.rs
new file mode 100644 (file)
index 0000000..09f1915
--- /dev/null
@@ -0,0 +1,181 @@
+/// Filters operating on numbers
+use std::collections::HashMap;
+
+#[cfg(feature = "builtins")]
+use humansize::{file_size_opts, FileSize};
+use serde_json::value::{to_value, Value};
+
+use crate::errors::{Error, Result};
+
+/// Returns a plural suffix if the value is not equal to ±1, or a singular
+/// suffix otherwise. The plural suffix defaults to `s` and the singular suffix
+/// defaults to the empty string (i.e nothing).
+pub fn pluralize(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let num = try_get_value!("pluralize", "value", f64, value);
+
+    let plural = match args.get("plural") {
+        Some(val) => try_get_value!("pluralize", "plural", String, val),
+        None => "s".to_string(),
+    };
+
+    let singular = match args.get("singular") {
+        Some(val) => try_get_value!("pluralize", "singular", String, val),
+        None => "".to_string(),
+    };
+
+    // English uses plural when it isn't one
+    if (num.abs() - 1.).abs() > ::std::f64::EPSILON {
+        Ok(to_value(&plural).unwrap())
+    } else {
+        Ok(to_value(&singular).unwrap())
+    }
+}
+
+/// Returns a rounded number using the `method` arg and `precision` given.
+/// `method` defaults to `common` which will round to the nearest number.
+/// `ceil` and `floor` are also available as method.
+/// `precision` defaults to `0`, meaning it will round to an integer
+pub fn round(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let num = try_get_value!("round", "value", f64, value);
+    let method = match args.get("method") {
+        Some(val) => try_get_value!("round", "method", String, val),
+        None => "common".to_string(),
+    };
+    let precision = match args.get("precision") {
+        Some(val) => try_get_value!("round", "precision", i32, val),
+        None => 0,
+    };
+    let multiplier = if precision == 0 { 1.0 } else { 10.0_f64.powi(precision) };
+
+    match method.as_ref() {
+        "common" => Ok(to_value((multiplier * num).round() / multiplier).unwrap()),
+        "ceil" => Ok(to_value((multiplier * num).ceil() / multiplier).unwrap()),
+        "floor" => Ok(to_value((multiplier * num).floor() / multiplier).unwrap()),
+        _ => Err(Error::msg(format!(
+            "Filter `round` received an incorrect value for arg `method`: got `{:?}`, \
+             only common, ceil and floor are allowed",
+            method
+        ))),
+    }
+}
+
+/// Returns a human-readable file size (i.e. '110 MB') from an integer
+#[cfg(feature = "builtins")]
+pub fn filesizeformat(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let num = try_get_value!("filesizeformat", "value", usize, value);
+    num.file_size(file_size_opts::CONVENTIONAL)
+        .map_err(|_| {
+            Error::msg(format!("Filter `filesizeformat` was called on a negative number: {}", num))
+        })
+        .map(to_value)
+        .map(std::result::Result::unwrap)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use serde_json::value::to_value;
+    use std::collections::HashMap;
+
+    #[test]
+    fn test_pluralize_single() {
+        let result = pluralize(&to_value(1).unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("").unwrap());
+    }
+
+    #[test]
+    fn test_pluralize_multiple() {
+        let result = pluralize(&to_value(2).unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("s").unwrap());
+    }
+
+    #[test]
+    fn test_pluralize_zero() {
+        let result = pluralize(&to_value(0).unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("s").unwrap());
+    }
+
+    #[test]
+    fn test_pluralize_multiple_custom_plural() {
+        let mut args = HashMap::new();
+        args.insert("plural".to_string(), to_value("es").unwrap());
+        let result = pluralize(&to_value(2).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("es").unwrap());
+    }
+
+    #[test]
+    fn test_pluralize_multiple_custom_singular() {
+        let mut args = HashMap::new();
+        args.insert("singular".to_string(), to_value("y").unwrap());
+        let result = pluralize(&to_value(1).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("y").unwrap());
+    }
+
+    #[test]
+    fn test_round_default() {
+        let result = round(&to_value(2.1).unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(2.0).unwrap());
+    }
+
+    #[test]
+    fn test_round_default_precision() {
+        let mut args = HashMap::new();
+        args.insert("precision".to_string(), to_value(2).unwrap());
+        let result = round(&to_value(3.15159265359).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(3.15).unwrap());
+    }
+
+    #[test]
+    fn test_round_ceil() {
+        let mut args = HashMap::new();
+        args.insert("method".to_string(), to_value("ceil").unwrap());
+        let result = round(&to_value(2.1).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(3.0).unwrap());
+    }
+
+    #[test]
+    fn test_round_ceil_precision() {
+        let mut args = HashMap::new();
+        args.insert("method".to_string(), to_value("ceil").unwrap());
+        args.insert("precision".to_string(), to_value(1).unwrap());
+        let result = round(&to_value(2.11).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(2.2).unwrap());
+    }
+
+    #[test]
+    fn test_round_floor() {
+        let mut args = HashMap::new();
+        args.insert("method".to_string(), to_value("floor").unwrap());
+        let result = round(&to_value(2.1).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(2.0).unwrap());
+    }
+
+    #[test]
+    fn test_round_floor_precision() {
+        let mut args = HashMap::new();
+        args.insert("method".to_string(), to_value("floor").unwrap());
+        args.insert("precision".to_string(), to_value(1).unwrap());
+        let result = round(&to_value(2.91).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(2.9).unwrap());
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn test_filesizeformat() {
+        let args = HashMap::new();
+        let result = filesizeformat(&to_value(123456789).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("117.74 MB").unwrap());
+    }
+}
diff --git a/vendor/tera/src/builtins/filters/object.rs b/vendor/tera/src/builtins/filters/object.rs
new file mode 100644 (file)
index 0000000..3f3e09d
--- /dev/null
@@ -0,0 +1,53 @@
+/// Filters operating on numbers
+use std::collections::HashMap;
+
+use serde_json::value::Value;
+
+use crate::errors::{Error, Result};
+
+/// Returns a value by a `key` argument from a given object
+pub fn get(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let key = match args.get("key") {
+        Some(val) => try_get_value!("get", "key", String, val),
+        None => return Err(Error::msg("The `get` filter has to have an `key` argument")),
+    };
+
+    match value.as_object() {
+        Some(o) => o.get(&key).cloned().ok_or_else(|| {
+            Error::msg(format!("Filter `get` tried to get key `{}` but it wasn't found", &key))
+        }),
+        None => Err(Error::msg("Filter `get` was used on a value that isn't an object")),
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::get;
+    use serde_json::value::to_value;
+    use std::collections::HashMap;
+
+    #[test]
+    fn test_get_filter_exists() {
+        let mut obj = HashMap::new();
+        obj.insert("1".to_string(), "first".to_string());
+        obj.insert("2".to_string(), "second".to_string());
+
+        let mut args = HashMap::new();
+        args.insert("key".to_string(), to_value("1").unwrap());
+        let result = get(&to_value(&obj).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("first").unwrap());
+    }
+
+    #[test]
+    fn test_get_filter_doesnt_exist() {
+        let mut obj = HashMap::new();
+        obj.insert("1".to_string(), "first".to_string());
+        obj.insert("2".to_string(), "second".to_string());
+
+        let mut args = HashMap::new();
+        args.insert("key".to_string(), to_value("3").unwrap());
+        let result = get(&to_value(&obj).unwrap(), &args);
+        assert!(result.is_err());
+    }
+}
diff --git a/vendor/tera/src/builtins/filters/string.rs b/vendor/tera/src/builtins/filters/string.rs
new file mode 100644 (file)
index 0000000..cfd97db
--- /dev/null
@@ -0,0 +1,848 @@
+/// Filters operating on string
+use std::collections::HashMap;
+
+use lazy_static::lazy_static;
+use regex::{Captures, Regex};
+use serde_json::value::{to_value, Value};
+
+#[cfg(feature = "builtins")]
+use percent_encoding::{percent_encode, AsciiSet, NON_ALPHANUMERIC};
+#[cfg(feature = "builtins")]
+use unic_segment::GraphemeIndices;
+
+use crate::errors::{Error, Result};
+use crate::utils;
+
+/// https://url.spec.whatwg.org/#fragment-percent-encode-set
+#[cfg(feature = "builtins")]
+const FRAGMENT_ENCODE_SET: &AsciiSet =
+    &percent_encoding::CONTROLS.add(b' ').add(b'"').add(b'<').add(b'>').add(b'`');
+
+/// https://url.spec.whatwg.org/#path-percent-encode-set
+#[cfg(feature = "builtins")]
+const PATH_ENCODE_SET: &AsciiSet = &FRAGMENT_ENCODE_SET.add(b'#').add(b'?').add(b'{').add(b'}');
+
+/// https://url.spec.whatwg.org/#userinfo-percent-encode-set
+#[cfg(feature = "builtins")]
+const USERINFO_ENCODE_SET: &AsciiSet = &PATH_ENCODE_SET
+    .add(b'/')
+    .add(b':')
+    .add(b';')
+    .add(b'=')
+    .add(b'@')
+    .add(b'[')
+    .add(b'\\')
+    .add(b']')
+    .add(b'^')
+    .add(b'|');
+
+/// Same as Python quote
+/// https://github.com/python/cpython/blob/da27d9b9dc44913ffee8f28d9638985eaaa03755/Lib/urllib/parse.py#L787
+/// with `/` not escaped
+#[cfg(feature = "builtins")]
+const PYTHON_ENCODE_SET: &AsciiSet = &USERINFO_ENCODE_SET
+    .remove(b'/')
+    .add(b':')
+    .add(b'?')
+    .add(b'#')
+    .add(b'[')
+    .add(b']')
+    .add(b'@')
+    .add(b'!')
+    .add(b'$')
+    .add(b'&')
+    .add(b'\'')
+    .add(b'(')
+    .add(b')')
+    .add(b'*')
+    .add(b'+')
+    .add(b',')
+    .add(b';')
+    .add(b'=');
+
+lazy_static! {
+    static ref STRIPTAGS_RE: Regex = Regex::new(r"(<!--.*?-->|<[^>]*>)").unwrap();
+    static ref WORDS_RE: Regex = Regex::new(r"\b(?P<first>\w)(?P<rest>\w*)\b").unwrap();
+}
+
+/// Convert a value to uppercase.
+pub fn upper(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("upper", "value", String, value);
+
+    Ok(to_value(&s.to_uppercase()).unwrap())
+}
+
+/// Convert a value to lowercase.
+pub fn lower(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("lower", "value", String, value);
+
+    Ok(to_value(&s.to_lowercase()).unwrap())
+}
+
+/// Strip leading and trailing whitespace.
+pub fn trim(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("trim", "value", String, value);
+
+    Ok(to_value(&s.trim()).unwrap())
+}
+
+/// Strip leading whitespace.
+pub fn trim_start(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("trim_start", "value", String, value);
+
+    Ok(to_value(&s.trim_start()).unwrap())
+}
+
+/// Strip trailing whitespace.
+pub fn trim_end(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("trim_end", "value", String, value);
+
+    Ok(to_value(&s.trim_end()).unwrap())
+}
+
+/// Strip leading characters that match the given pattern.
+pub fn trim_start_matches(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("trim_start_matches", "value", String, value);
+
+    let pat = match args.get("pat") {
+        Some(pat) => {
+            let p = try_get_value!("trim_start_matches", "pat", String, pat);
+            // When reading from a file, it will escape `\n` to `\\n` for example so we need
+            // to replace double escape. In practice it might cause issues if someone wants to split
+            // by `\\n` for real but that seems pretty unlikely
+            p.replace("\\n", "\n").replace("\\t", "\t")
+        }
+        None => return Err(Error::msg("Filter `trim_start_matches` expected an arg called `pat`")),
+    };
+
+    Ok(to_value(s.trim_start_matches(&pat)).unwrap())
+}
+
+/// Strip trailing characters that match the given pattern.
+pub fn trim_end_matches(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("trim_end_matches", "value", String, value);
+
+    let pat = match args.get("pat") {
+        Some(pat) => {
+            let p = try_get_value!("trim_end_matches", "pat", String, pat);
+            // When reading from a file, it will escape `\n` to `\\n` for example so we need
+            // to replace double escape. In practice it might cause issues if someone wants to split
+            // by `\\n` for real but that seems pretty unlikely
+            p.replace("\\n", "\n").replace("\\t", "\t")
+        }
+        None => return Err(Error::msg("Filter `trim_end_matches` expected an arg called `pat`")),
+    };
+
+    Ok(to_value(s.trim_end_matches(&pat)).unwrap())
+}
+
+/// Truncates a string to the indicated length.
+///
+/// # Arguments
+///
+/// * `value`   - The string that needs to be truncated.
+/// * `args`    - A set of key/value arguments that can take the following
+///   keys.
+/// * `length`  - The length at which the string needs to be truncated. If
+///   the length is larger than the length of the string, the string is
+///   returned untouched. The default value is 255.
+/// * `end`     - The ellipsis string to be used if the given string is
+///   truncated. The default value is "…".
+///
+/// # Remarks
+///
+/// The return value of this function might be longer than `length`: the `end`
+/// string is *added* after the truncation occurs.
+///
+#[cfg(feature = "builtins")]
+pub fn truncate(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("truncate", "value", String, value);
+    let length = match args.get("length") {
+        Some(l) => try_get_value!("truncate", "length", usize, l),
+        None => 255,
+    };
+    let end = match args.get("end") {
+        Some(l) => try_get_value!("truncate", "end", String, l),
+        None => "…".to_string(),
+    };
+
+    let graphemes = GraphemeIndices::new(&s).collect::<Vec<(usize, &str)>>();
+
+    // Nothing to truncate?
+    if length >= graphemes.len() {
+        return Ok(to_value(&s).unwrap());
+    }
+
+    let result = s[..graphemes[length].0].to_string() + &end;
+    Ok(to_value(&result).unwrap())
+}
+
+/// Gets the number of words in a string.
+pub fn wordcount(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("wordcount", "value", String, value);
+
+    Ok(to_value(&s.split_whitespace().count()).unwrap())
+}
+
+/// Replaces given `from` substring with `to` string.
+pub fn replace(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("replace", "value", String, value);
+
+    let from = match args.get("from") {
+        Some(val) => try_get_value!("replace", "from", String, val),
+        None => return Err(Error::msg("Filter `replace` expected an arg called `from`")),
+    };
+
+    let to = match args.get("to") {
+        Some(val) => try_get_value!("replace", "to", String, val),
+        None => return Err(Error::msg("Filter `replace` expected an arg called `to`")),
+    };
+
+    Ok(to_value(&s.replace(&from, &to)).unwrap())
+}
+
+/// First letter of the string is uppercase rest is lowercase
+pub fn capitalize(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("capitalize", "value", String, value);
+    let mut chars = s.chars();
+    match chars.next() {
+        None => Ok(to_value("").unwrap()),
+        Some(f) => {
+            let res = f.to_uppercase().collect::<String>() + &chars.as_str().to_lowercase();
+            Ok(to_value(&res).unwrap())
+        }
+    }
+}
+
+/// Percent-encodes reserved URI characters
+#[cfg(feature = "builtins")]
+pub fn urlencode(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("urlencode", "value", String, value);
+    let encoded = percent_encode(s.as_bytes(), &PYTHON_ENCODE_SET).to_string();
+    Ok(Value::String(encoded))
+}
+
+/// Percent-encodes all non-alphanumeric characters
+#[cfg(feature = "builtins")]
+pub fn urlencode_strict(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("urlencode_strict", "value", String, value);
+    let encoded = percent_encode(s.as_bytes(), &NON_ALPHANUMERIC).to_string();
+    Ok(Value::String(encoded))
+}
+
+/// Escapes quote characters
+pub fn addslashes(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("addslashes", "value", String, value);
+    Ok(to_value(&s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\'", "\\\'")).unwrap())
+}
+
+/// Transform a string into a slug
+#[cfg(feature = "builtins")]
+pub fn slugify(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("slugify", "value", String, value);
+    Ok(to_value(&slug::slugify(s)).unwrap())
+}
+
+/// Capitalizes each word in the string
+pub fn title(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("title", "value", String, value);
+
+    Ok(to_value(&WORDS_RE.replace_all(&s, |caps: &Captures| {
+        let first = caps["first"].to_uppercase();
+        let rest = caps["rest"].to_lowercase();
+        format!("{}{}", first, rest)
+    }))
+    .unwrap())
+}
+
+/// Convert line breaks (`\n` or `\r\n`) to HTML linebreaks (`<br>`).
+///
+/// Example: The input "Hello\nWorld" turns into "Hello<br>World".
+pub fn linebreaksbr(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("title", "value", String, value);
+    Ok(to_value(&s.replace("\r\n", "<br>").replace("\n", "<br>")).unwrap())
+}
+
+/// Removes html tags from string
+pub fn striptags(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("striptags", "value", String, value);
+    Ok(to_value(&STRIPTAGS_RE.replace_all(&s, "")).unwrap())
+}
+
+/// Returns the given text with all special HTML characters encoded
+pub fn escape_html(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("escape_html", "value", String, value);
+    Ok(Value::String(utils::escape_html(&s)))
+}
+
+/// Returns the given text with all special XML characters encoded
+/// Very similar to `escape_html`, just a few characters less are encoded
+pub fn escape_xml(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("escape_html", "value", String, value);
+
+    let mut output = String::with_capacity(s.len() * 2);
+    for c in s.chars() {
+        match c {
+            '&' => output.push_str("&amp;"),
+            '<' => output.push_str("&lt;"),
+            '>' => output.push_str("&gt;"),
+            '"' => output.push_str("&quot;"),
+            '\'' => output.push_str("&apos;"),
+            _ => output.push(c),
+        }
+    }
+    Ok(Value::String(output))
+}
+
+/// Split the given string by the given pattern.
+pub fn split(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let s = try_get_value!("split", "value", String, value);
+
+    let pat = match args.get("pat") {
+        Some(pat) => {
+            let p = try_get_value!("split", "pat", String, pat);
+            // When reading from a file, it will escape `\n` to `\\n` for example so we need
+            // to replace double escape. In practice it might cause issues if someone wants to split
+            // by `\\n` for real but that seems pretty unlikely
+            p.replace("\\n", "\n").replace("\\t", "\t")
+        }
+        None => return Err(Error::msg("Filter `split` expected an arg called `pat`")),
+    };
+
+    Ok(to_value(s.split(&pat).collect::<Vec<_>>()).unwrap())
+}
+
+/// Convert the value to a signed integer number
+pub fn int(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let default = match args.get("default") {
+        Some(d) => try_get_value!("int", "default", i64, d),
+        None => 0,
+    };
+    let base = match args.get("base") {
+        Some(b) => try_get_value!("int", "base", u32, b),
+        None => 10,
+    };
+
+    let v = match value {
+        Value::String(s) => {
+            let s = s.trim();
+            let s = match base {
+                2 => s.trim_start_matches("0b"),
+                8 => s.trim_start_matches("0o"),
+                16 => s.trim_start_matches("0x"),
+                _ => s,
+            };
+
+            match i64::from_str_radix(s, base) {
+                Ok(v) => v,
+                Err(_) => {
+                    if s.contains('.') {
+                        match s.parse::<f64>() {
+                            Ok(f) => f as i64,
+                            Err(_) => default,
+                        }
+                    } else {
+                        default
+                    }
+                }
+            }
+        }
+        Value::Number(n) => match n.as_f64() {
+            Some(f) => f as i64,
+            None => match n.as_i64() {
+                Some(i) => i,
+                None => default,
+            },
+        },
+        _ => return Err(Error::msg("Filter `int` received an unexpected type")),
+    };
+
+    Ok(to_value(v).unwrap())
+}
+
+/// Convert the value to a floating point number
+pub fn float(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
+    let default = match args.get("default") {
+        Some(d) => try_get_value!("float", "default", f64, d),
+        None => 0.0,
+    };
+
+    let v = match value {
+        Value::String(s) => {
+            let s = s.trim();
+            s.parse::<f64>().unwrap_or(default)
+        }
+        Value::Number(n) => match n.as_f64() {
+            Some(f) => f,
+            None => match n.as_i64() {
+                Some(i) => i as f64,
+                None => default,
+            },
+        },
+        _ => return Err(Error::msg("Filter `float` received an unexpected type")),
+    };
+
+    Ok(to_value(v).unwrap())
+}
+
+#[cfg(test)]
+mod tests {
+    use std::collections::HashMap;
+
+    use serde_json::value::to_value;
+
+    use super::*;
+
+    #[test]
+    fn test_upper() {
+        let result = upper(&to_value("hello").unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("HELLO").unwrap());
+    }
+
+    #[test]
+    fn test_upper_error() {
+        let result = upper(&to_value(&50).unwrap(), &HashMap::new());
+        assert!(result.is_err());
+        assert_eq!(
+            result.err().unwrap().to_string(),
+            "Filter `upper` was called on an incorrect value: got `50` but expected a String"
+        );
+    }
+
+    #[test]
+    fn test_trim() {
+        let result = trim(&to_value("  hello  ").unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("hello").unwrap());
+    }
+
+    #[test]
+    fn test_trim_start() {
+        let result = trim_start(&to_value("  hello  ").unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("hello  ").unwrap());
+    }
+
+    #[test]
+    fn test_trim_end() {
+        let result = trim_end(&to_value("  hello  ").unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("  hello").unwrap());
+    }
+
+    #[test]
+    fn test_trim_start_matches() {
+        let tests: Vec<(_, _, _)> = vec![
+            ("/a/b/cde/", "/", "a/b/cde/"),
+            ("\nhello\nworld\n", "\n", "hello\nworld\n"),
+            (", hello, world, ", ", ", "hello, world, "),
+        ];
+        for (input, pat, expected) in tests {
+            let mut args = HashMap::new();
+            args.insert("pat".to_string(), to_value(pat).unwrap());
+            let result = trim_start_matches(&to_value(input).unwrap(), &args);
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+    }
+
+    #[test]
+    fn test_trim_end_matches() {
+        let tests: Vec<(_, _, _)> = vec![
+            ("/a/b/cde/", "/", "/a/b/cde"),
+            ("\nhello\nworld\n", "\n", "\nhello\nworld"),
+            (", hello, world, ", ", ", ", hello, world"),
+        ];
+        for (input, pat, expected) in tests {
+            let mut args = HashMap::new();
+            args.insert("pat".to_string(), to_value(pat).unwrap());
+            let result = trim_end_matches(&to_value(input).unwrap(), &args);
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn test_truncate_smaller_than_length() {
+        let mut args = HashMap::new();
+        args.insert("length".to_string(), to_value(&255).unwrap());
+        let result = truncate(&to_value("hello").unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("hello").unwrap());
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn test_truncate_when_required() {
+        let mut args = HashMap::new();
+        args.insert("length".to_string(), to_value(&2).unwrap());
+        let result = truncate(&to_value("日本語").unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("日本…").unwrap());
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn test_truncate_custom_end() {
+        let mut args = HashMap::new();
+        args.insert("length".to_string(), to_value(&2).unwrap());
+        args.insert("end".to_string(), to_value(&"").unwrap());
+        let result = truncate(&to_value("日本語").unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("日本").unwrap());
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn test_truncate_multichar_grapheme() {
+        let mut args = HashMap::new();
+        args.insert("length".to_string(), to_value(&5).unwrap());
+        args.insert("end".to_string(), to_value(&"…").unwrap());
+        let result = truncate(&to_value("👨‍👩‍👧‍👦 family").unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("👨‍👩‍👧‍👦 fam…").unwrap());
+    }
+
+    #[test]
+    fn test_lower() {
+        let result = lower(&to_value("HELLO").unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("hello").unwrap());
+    }
+
+    #[test]
+    fn test_wordcount() {
+        let result = wordcount(&to_value("Joel is a slug").unwrap(), &HashMap::new());
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(&4).unwrap());
+    }
+
+    #[test]
+    fn test_replace() {
+        let mut args = HashMap::new();
+        args.insert("from".to_string(), to_value(&"Hello").unwrap());
+        args.insert("to".to_string(), to_value(&"Goodbye").unwrap());
+        let result = replace(&to_value(&"Hello world!").unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("Goodbye world!").unwrap());
+    }
+
+    // https://github.com/Keats/tera/issues/435
+    #[test]
+    fn test_replace_newline() {
+        let mut args = HashMap::new();
+        args.insert("from".to_string(), to_value(&"\n").unwrap());
+        args.insert("to".to_string(), to_value(&"<br>").unwrap());
+        let result = replace(&to_value(&"Animal Alphabets\nB is for Bee-Eater").unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value("Animal Alphabets<br>B is for Bee-Eater").unwrap());
+    }
+
+    #[test]
+    fn test_replace_missing_arg() {
+        let mut args = HashMap::new();
+        args.insert("from".to_string(), to_value(&"Hello").unwrap());
+        let result = replace(&to_value(&"Hello world!").unwrap(), &args);
+        assert!(result.is_err());
+        assert_eq!(
+            result.err().unwrap().to_string(),
+            "Filter `replace` expected an arg called `to`"
+        );
+    }
+
+    #[test]
+    fn test_capitalize() {
+        let tests = vec![("CAPITAL IZE", "Capital ize"), ("capital ize", "Capital ize")];
+        for (input, expected) in tests {
+            let result = capitalize(&to_value(input).unwrap(), &HashMap::new());
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+    }
+
+    #[test]
+    fn test_addslashes() {
+        let tests = vec![
+            (r#"I'm so happy"#, r#"I\'m so happy"#),
+            (r#"Let "me" help you"#, r#"Let \"me\" help you"#),
+            (r#"<a>'"#, r#"<a>\'"#),
+            (
+                r#""double quotes" and \'single quotes\'"#,
+                r#"\"double quotes\" and \\\'single quotes\\\'"#,
+            ),
+            (r#"\ : backslashes too"#, r#"\\ : backslashes too"#),
+        ];
+        for (input, expected) in tests {
+            let result = addslashes(&to_value(input).unwrap(), &HashMap::new());
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn test_slugify() {
+        // slug crate already has tests for general slugification so we just
+        // check our function works
+        let tests =
+            vec![(r#"Hello world"#, r#"hello-world"#), (r#"Hello 世界"#, r#"hello-shi-jie"#)];
+        for (input, expected) in tests {
+            let result = slugify(&to_value(input).unwrap(), &HashMap::new());
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn test_urlencode() {
+        let tests = vec![
+            (
+                r#"https://www.example.org/foo?a=b&c=d"#,
+                r#"https%3A//www.example.org/foo%3Fa%3Db%26c%3Dd"#,
+            ),
+            (
+                r#"https://www.example.org/apples-&-oranges/"#,
+                r#"https%3A//www.example.org/apples-%26-oranges/"#,
+            ),
+            (r#"https://www.example.org/"#, r#"https%3A//www.example.org/"#),
+            (r#"/test&"/me?/"#, r#"/test%26%22/me%3F/"#),
+            (r#"escape/slash"#, r#"escape/slash"#),
+        ];
+        for (input, expected) in tests {
+            let args = HashMap::new();
+            let result = urlencode(&to_value(input).unwrap(), &args);
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn test_urlencode_strict() {
+        let tests = vec![
+            (
+                r#"https://www.example.org/foo?a=b&c=d"#,
+                r#"https%3A%2F%2Fwww%2Eexample%2Eorg%2Ffoo%3Fa%3Db%26c%3Dd"#,
+            ),
+            (
+                r#"https://www.example.org/apples-&-oranges/"#,
+                r#"https%3A%2F%2Fwww%2Eexample%2Eorg%2Fapples%2D%26%2Doranges%2F"#,
+            ),
+            (r#"https://www.example.org/"#, r#"https%3A%2F%2Fwww%2Eexample%2Eorg%2F"#),
+            (r#"/test&"/me?/"#, r#"%2Ftest%26%22%2Fme%3F%2F"#),
+            (r#"escape/slash"#, r#"escape%2Fslash"#),
+        ];
+        for (input, expected) in tests {
+            let args = HashMap::new();
+            let result = urlencode_strict(&to_value(input).unwrap(), &args);
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+    }
+
+    #[test]
+    fn test_title() {
+        let tests = vec![
+            ("foo bar", "Foo Bar"),
+            ("foo\tbar", "Foo\tBar"),
+            ("foo  bar", "Foo  Bar"),
+            ("f bar f", "F Bar F"),
+            ("foo-bar", "Foo-Bar"),
+            ("FOO\tBAR", "Foo\tBar"),
+            ("foo (bar)", "Foo (Bar)"),
+            ("foo (bar) ", "Foo (Bar) "),
+            ("foo {bar}", "Foo {Bar}"),
+            ("foo [bar]", "Foo [Bar]"),
+            ("foo <bar>", "Foo <Bar>"),
+            ("  foo  bar", "  Foo  Bar"),
+            ("\tfoo\tbar\t", "\tFoo\tBar\t"),
+            ("foo bar ", "Foo Bar "),
+            ("foo bar\t", "Foo Bar\t"),
+        ];
+        for (input, expected) in tests {
+            let result = title(&to_value(input).unwrap(), &HashMap::new());
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+    }
+
+    #[test]
+    fn test_striptags() {
+        let tests = vec![
+            (r"<b>Joel</b> <button>is</button> a <span>slug</span>", "Joel is a slug"),
+            (
+                r#"<p>just a small   \n <a href="x"> example</a> link</p>\n<p>to a webpage</p><!-- <p>and some commented stuff</p> -->"#,
+                r#"just a small   \n  example link\nto a webpage"#,
+            ),
+            (
+                r"<p>See: &#39;&eacute; is an apostrophe followed by e acute</p>",
+                r"See: &#39;&eacute; is an apostrophe followed by e acute",
+            ),
+            (r"<adf>a", "a"),
+            (r"</adf>a", "a"),
+            (r"<asdf><asdf>e", "e"),
+            (r"hi, <f x", "hi, <f x"),
+            ("234<235, right?", "234<235, right?"),
+            ("a4<a5 right?", "a4<a5 right?"),
+            ("b7>b2!", "b7>b2!"),
+            ("</fe", "</fe"),
+            ("<x>b<y>", "b"),
+            (r#"a<p a >b</p>c"#, "abc"),
+            (r#"d<a:b c:d>e</p>f"#, "def"),
+            (r#"<strong>foo</strong><a href="http://example.com">bar</a>"#, "foobar"),
+        ];
+        for (input, expected) in tests {
+            let result = striptags(&to_value(input).unwrap(), &HashMap::new());
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+    }
+
+    #[test]
+    fn test_split() {
+        let tests: Vec<(_, _, &[&str])> = vec![
+            ("a/b/cde", "/", &["a", "b", "cde"]),
+            ("hello\nworld", "\n", &["hello", "world"]),
+            ("hello, world", ", ", &["hello", "world"]),
+        ];
+        for (input, pat, expected) in tests {
+            let mut args = HashMap::new();
+            args.insert("pat".to_string(), to_value(pat).unwrap());
+            let result = split(&to_value(input).unwrap(), &args).unwrap();
+            let result = result.as_array().unwrap();
+            assert_eq!(result.len(), expected.len());
+            for (result, expected) in result.iter().zip(expected.iter()) {
+                assert_eq!(result, expected);
+            }
+        }
+    }
+
+    #[test]
+    fn test_xml_escape() {
+        let tests = vec![
+            (r"hey-&-ho", "hey-&amp;-ho"),
+            (r"hey-'-ho", "hey-&apos;-ho"),
+            (r"hey-&'-ho", "hey-&amp;&apos;-ho"),
+            (r#"hey-&'"-ho"#, "hey-&amp;&apos;&quot;-ho"),
+            (r#"hey-&'"<-ho"#, "hey-&amp;&apos;&quot;&lt;-ho"),
+            (r#"hey-&'"<>-ho"#, "hey-&amp;&apos;&quot;&lt;&gt;-ho"),
+        ];
+        for (input, expected) in tests {
+            let result = escape_xml(&to_value(input).unwrap(), &HashMap::new());
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+    }
+
+    #[test]
+    fn test_int_decimal_strings() {
+        let tests: Vec<(&str, i64)> = vec![
+            ("0", 0),
+            ("-5", -5),
+            ("9223372036854775807", i64::max_value()),
+            ("0b1010", 0),
+            ("1.23", 1),
+        ];
+        for (input, expected) in tests {
+            let args = HashMap::new();
+            let result = int(&to_value(input).unwrap(), &args);
+
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+    }
+
+    #[test]
+    fn test_int_others() {
+        let mut args = HashMap::new();
+
+        let result = int(&to_value(1.23).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(1).unwrap());
+
+        let result = int(&to_value(-5).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(-5).unwrap());
+
+        args.insert("default".to_string(), to_value(5).unwrap());
+        args.insert("base".to_string(), to_value(2).unwrap());
+        let tests: Vec<(&str, i64)> =
+            vec![("0", 0), ("-3", 5), ("1010", 10), ("0b1010", 10), ("0xF00", 5)];
+        for (input, expected) in tests {
+            let result = int(&to_value(input).unwrap(), &args);
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+
+        args.insert("default".to_string(), to_value(-4).unwrap());
+        args.insert("base".to_string(), to_value(8).unwrap());
+        let tests: Vec<(&str, i64)> =
+            vec![("21", 17), ("-3", -3), ("9OO", -4), ("0o567", 375), ("0b101", -4)];
+        for (input, expected) in tests {
+            let result = int(&to_value(input).unwrap(), &args);
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+
+        args.insert("default".to_string(), to_value(0).unwrap());
+        args.insert("base".to_string(), to_value(16).unwrap());
+        let tests: Vec<(&str, i64)> = vec![("1011", 4113), ("0xC3", 195)];
+        for (input, expected) in tests {
+            let result = int(&to_value(input).unwrap(), &args);
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+
+        args.insert("default".to_string(), to_value(0).unwrap());
+        args.insert("base".to_string(), to_value(5).unwrap());
+        let tests: Vec<(&str, i64)> = vec![("4321", 586), ("-100", -25), ("0b100", 0)];
+        for (input, expected) in tests {
+            let result = int(&to_value(input).unwrap(), &args);
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+    }
+
+    #[test]
+    fn test_float() {
+        let mut args = HashMap::new();
+
+        let tests: Vec<(&str, f64)> = vec![("0", 0.0), ("-5.3", -5.3)];
+        for (input, expected) in tests {
+            let result = float(&to_value(input).unwrap(), &args);
+
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+
+        args.insert("default".to_string(), to_value(3.14).unwrap());
+        let result = float(&to_value("bad_val").unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(3.14).unwrap());
+
+        let result = float(&to_value(1.23).unwrap(), &args);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), to_value(1.23).unwrap());
+    }
+
+    #[test]
+    fn test_linebreaksbr() {
+        let args = HashMap::new();
+        let tests: Vec<(&str, &str)> = vec![
+            ("hello world", "hello world"),
+            ("hello\nworld", "hello<br>world"),
+            ("hello\r\nworld", "hello<br>world"),
+            ("hello\n\rworld", "hello<br>\rworld"),
+            ("hello\r\n\nworld", "hello<br><br>world"),
+            ("hello<br>world\n", "hello<br>world<br>"),
+        ];
+        for (input, expected) in tests {
+            let result = linebreaksbr(&to_value(input).unwrap(), &args);
+            assert!(result.is_ok());
+            assert_eq!(result.unwrap(), to_value(expected).unwrap());
+        }
+    }
+}
diff --git a/vendor/tera/src/builtins/functions.rs b/vendor/tera/src/builtins/functions.rs
new file mode 100644 (file)
index 0000000..c3b9fef
--- /dev/null
@@ -0,0 +1,341 @@
+use std::collections::HashMap;
+
+#[cfg(feature = "builtins")]
+use chrono::prelude::*;
+#[cfg(feature = "builtins")]
+use rand::Rng;
+use serde_json::value::{from_value, to_value, Value};
+
+use crate::errors::{Error, Result};
+
+/// The global function type definition
+pub trait Function: Sync + Send {
+    /// The global function type definition
+    fn call(&self, args: &HashMap<String, Value>) -> Result<Value>;
+
+    /// Whether the current function's output should be treated as safe, defaults to `false`
+    fn is_safe(&self) -> bool {
+        false
+    }
+}
+
+impl<F> Function for F
+where
+    F: Fn(&HashMap<String, Value>) -> Result<Value> + Sync + Send,
+{
+    fn call(&self, args: &HashMap<String, Value>) -> Result<Value> {
+        self(args)
+    }
+}
+
+pub fn range(args: &HashMap<String, Value>) -> Result<Value> {
+    let start = match args.get("start") {
+        Some(val) => match from_value::<usize>(val.clone()) {
+            Ok(v) => v,
+            Err(_) => {
+                return Err(Error::msg(format!(
+                    "Function `range` received start={} but `start` can only be a number",
+                    val
+                )));
+            }
+        },
+        None => 0,
+    };
+    let step_by = match args.get("step_by") {
+        Some(val) => match from_value::<usize>(val.clone()) {
+            Ok(v) => v,
+            Err(_) => {
+                return Err(Error::msg(format!(
+                    "Function `range` received step_by={} but `step` can only be a number",
+                    val
+                )));
+            }
+        },
+        None => 1,
+    };
+    let end = match args.get("end") {
+        Some(val) => match from_value::<usize>(val.clone()) {
+            Ok(v) => v,
+            Err(_) => {
+                return Err(Error::msg(format!(
+                    "Function `range` received end={} but `end` can only be a number",
+                    val
+                )));
+            }
+        },
+        None => {
+            return Err(Error::msg("Function `range` was called without a `end` argument"));
+        }
+    };
+
+    if start > end {
+        return Err(Error::msg(
+            "Function `range` was called with a `start` argument greater than the `end` one",
+        ));
+    }
+
+    let mut i = start;
+    let mut res = vec![];
+    while i < end {
+        res.push(i);
+        i += step_by;
+    }
+    Ok(to_value(res).unwrap())
+}
+
+#[cfg(feature = "builtins")]
+pub fn now(args: &HashMap<String, Value>) -> Result<Value> {
+    let utc = match args.get("utc") {
+        Some(val) => match from_value::<bool>(val.clone()) {
+            Ok(v) => v,
+            Err(_) => {
+                return Err(Error::msg(format!(
+                    "Function `now` received utc={} but `utc` can only be a boolean",
+                    val
+                )));
+            }
+        },
+        None => false,
+    };
+    let timestamp = match args.get("timestamp") {
+        Some(val) => match from_value::<bool>(val.clone()) {
+            Ok(v) => v,
+            Err(_) => {
+                return Err(Error::msg(format!(
+                    "Function `now` received timestamp={} but `timestamp` can only be a boolean",
+                    val
+                )));
+            }
+        },
+        None => false,
+    };
+
+    if utc {
+        let datetime = Utc::now();
+        if timestamp {
+            return Ok(to_value(datetime.timestamp()).unwrap());
+        }
+        Ok(to_value(datetime.to_rfc3339()).unwrap())
+    } else {
+        let datetime = Local::now();
+        if timestamp {
+            return Ok(to_value(datetime.timestamp()).unwrap());
+        }
+        Ok(to_value(datetime.to_rfc3339()).unwrap())
+    }
+}
+
+pub fn throw(args: &HashMap<String, Value>) -> Result<Value> {
+    match args.get("message") {
+        Some(val) => match from_value::<String>(val.clone()) {
+            Ok(v) => Err(Error::msg(v)),
+            Err(_) => Err(Error::msg(format!(
+                "Function `throw` received message={} but `message` can only be a string",
+                val
+            ))),
+        },
+        None => Err(Error::msg("Function `throw` was called without a `message` argument")),
+    }
+}
+
+#[cfg(feature = "builtins")]
+pub fn get_random(args: &HashMap<String, Value>) -> Result<Value> {
+    let start = match args.get("start") {
+        Some(val) => match from_value::<i32>(val.clone()) {
+            Ok(v) => v,
+            Err(_) => {
+                return Err(Error::msg(format!(
+                    "Function `get_random` received start={} but `start` can only be a boolean",
+                    val
+                )));
+            }
+        },
+        None => 0,
+    };
+
+    let end = match args.get("end") {
+        Some(val) => match from_value::<i32>(val.clone()) {
+            Ok(v) => v,
+            Err(_) => {
+                return Err(Error::msg(format!(
+                    "Function `get_random` received end={} but `end` can only be a boolean",
+                    val
+                )));
+            }
+        },
+        None => return Err(Error::msg("Function `get_random` didn't receive an `end` argument")),
+    };
+    let mut rng = rand::thread_rng();
+    let res = rng.gen_range(start..end);
+
+    Ok(Value::Number(res.into()))
+}
+
+pub fn get_env(args: &HashMap<String, Value>) -> Result<Value> {
+    let name = match args.get("name") {
+        Some(val) => match from_value::<String>(val.clone()) {
+            Ok(v) => v,
+            Err(_) => {
+                return Err(Error::msg(format!(
+                    "Function `get_env` received name={} but `name` can only be a string",
+                    val
+                )));
+            }
+        },
+        None => return Err(Error::msg("Function `get_env` didn't receive a `name` argument")),
+    };
+
+    match std::env::var(&name).ok() {
+        Some(res) => Ok(Value::String(res)),
+        None => match args.get("default") {
+            Some(default) => Ok(default.clone()),
+            None => Err(Error::msg(format!("Environment variable `{}` not found", &name))),
+        },
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use std::collections::HashMap;
+
+    use serde_json::value::to_value;
+
+    use super::*;
+
+    #[test]
+    fn range_default() {
+        let mut args = HashMap::new();
+        args.insert("end".to_string(), to_value(5).unwrap());
+
+        let res = range(&args).unwrap();
+        assert_eq!(res, to_value(vec![0, 1, 2, 3, 4]).unwrap());
+    }
+
+    #[test]
+    fn range_start() {
+        let mut args = HashMap::new();
+        args.insert("end".to_string(), to_value(5).unwrap());
+        args.insert("start".to_string(), to_value(1).unwrap());
+
+        let res = range(&args).unwrap();
+        assert_eq!(res, to_value(vec![1, 2, 3, 4]).unwrap());
+    }
+
+    #[test]
+    fn range_start_greater_than_end() {
+        let mut args = HashMap::new();
+        args.insert("end".to_string(), to_value(5).unwrap());
+        args.insert("start".to_string(), to_value(6).unwrap());
+
+        assert!(range(&args).is_err());
+    }
+
+    #[test]
+    fn range_step_by() {
+        let mut args = HashMap::new();
+        args.insert("end".to_string(), to_value(10).unwrap());
+        args.insert("step_by".to_string(), to_value(2).unwrap());
+
+        let res = range(&args).unwrap();
+        assert_eq!(res, to_value(vec![0, 2, 4, 6, 8]).unwrap());
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn now_default() {
+        let args = HashMap::new();
+
+        let res = now(&args).unwrap();
+        assert!(res.is_string());
+        assert!(res.as_str().unwrap().contains("T"));
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn now_datetime_utc() {
+        let mut args = HashMap::new();
+        args.insert("utc".to_string(), to_value(true).unwrap());
+
+        let res = now(&args).unwrap();
+        assert!(res.is_string());
+        let val = res.as_str().unwrap();
+        println!("{}", val);
+        assert!(val.contains("T"));
+        assert!(val.contains("+00:00"));
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn now_timestamp() {
+        let mut args = HashMap::new();
+        args.insert("timestamp".to_string(), to_value(true).unwrap());
+
+        let res = now(&args).unwrap();
+        assert!(res.is_number());
+    }
+
+    #[test]
+    fn throw_errors_with_message() {
+        let mut args = HashMap::new();
+        args.insert("message".to_string(), to_value("Hello").unwrap());
+
+        let res = throw(&args);
+        assert!(res.is_err());
+        let err = res.unwrap_err();
+        assert_eq!(err.to_string(), "Hello");
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn get_random_no_start() {
+        let mut args = HashMap::new();
+        args.insert("end".to_string(), to_value(10).unwrap());
+        let res = get_random(&args).unwrap();
+        println!("{}", res);
+        assert!(res.is_number());
+        assert!(res.as_i64().unwrap() >= 0);
+        assert!(res.as_i64().unwrap() < 10);
+    }
+
+    #[cfg(feature = "builtins")]
+    #[test]
+    fn get_random_with_start() {
+        let mut args = HashMap::new();
+        args.insert("start".to_string(), to_value(5).unwrap());
+        args.insert("end".to_string(), to_value(10).unwrap());
+        let res = get_random(&args).unwrap();
+        println!("{}", res);
+        assert!(res.is_number());
+        assert!(res.as_i64().unwrap() >= 5);
+        assert!(res.as_i64().unwrap() < 10);
+    }
+
+    #[test]
+    fn get_env_existing() {
+        std::env::set_var("TERA_TEST", "true");
+        let mut args = HashMap::new();
+        args.insert("name".to_string(), to_value("TERA_TEST").unwrap());
+        let res = get_env(&args).unwrap();
+        assert!(res.is_string());
+        assert_eq!(res.as_str().unwrap(), "true");
+        std::env::remove_var("TERA_TEST");
+    }
+
+    #[test]
+    fn get_env_non_existing_no_default() {
+        let mut args = HashMap::new();
+        args.insert("name".to_string(), to_value("UNKNOWN_VAR").unwrap());
+        let res = get_env(&args);
+        assert!(res.is_err());
+    }
+
+    #[test]
+    fn get_env_non_existing_with_default() {
+        let mut args = HashMap::new();
+        args.insert("name".to_string(), to_value("UNKNOWN_VAR").unwrap());
+        args.insert("default".to_string(), to_value("false").unwrap());
+        let res = get_env(&args).unwrap();
+        assert!(res.is_string());
+        assert_eq!(res.as_str().unwrap(), "false");
+    }
+}
diff --git a/vendor/tera/src/builtins/mod.rs b/vendor/tera/src/builtins/mod.rs
new file mode 100644 (file)
index 0000000..792e591
--- /dev/null
@@ -0,0 +1,3 @@
+pub mod filters;
+pub mod functions;
+pub mod testers;
diff --git a/vendor/tera/src/builtins/testers.rs b/vendor/tera/src/builtins/testers.rs
new file mode 100644 (file)
index 0000000..158a91e
--- /dev/null
@@ -0,0 +1,348 @@
+use crate::context::ValueNumber;
+use crate::errors::{Error, Result};
+use regex::Regex;
+use serde_json::value::Value;
+
+/// The tester function type definition
+pub trait Test: Sync + Send {
+    /// The tester function type definition
+    fn test(&self, value: Option<&Value>, args: &[Value]) -> Result<bool>;
+}
+
+impl<F> Test for F
+where
+    F: Fn(Option<&Value>, &[Value]) -> Result<bool> + Sync + Send,
+{
+    fn test(&self, value: Option<&Value>, args: &[Value]) -> Result<bool> {
+        self(value, args)
+    }
+}
+
+/// Check that the number of args match what was expected
+pub fn number_args_allowed(tester_name: &str, max: usize, args_len: usize) -> Result<()> {
+    if max == 0 && args_len > max {
+        return Err(Error::msg(format!(
+            "Tester `{}` was called with some args but this test doesn't take args",
+            tester_name
+        )));
+    }
+
+    if args_len > max {
+        return Err(Error::msg(format!(
+            "Tester `{}` was called with {} args, the max number is {}",
+            tester_name, args_len, max
+        )));
+    }
+
+    Ok(())
+}
+
+/// Called to check if the Value is defined and return an Err if not
+pub fn value_defined(tester_name: &str, value: Option<&Value>) -> Result<()> {
+    if value.is_none() {
+        return Err(Error::msg(format!(
+            "Tester `{}` was called on an undefined variable",
+            tester_name
+        )));
+    }
+
+    Ok(())
+}
+
+/// Helper function to extract string from an Option<Value> to remove boilerplate
+/// with tester error handling
+pub fn extract_string<'a>(
+    tester_name: &str,
+    part: &str,
+    value: Option<&'a Value>,
+) -> Result<&'a str> {
+    match value.and_then(Value::as_str) {
+        Some(s) => Ok(s),
+        None => Err(Error::msg(format!(
+            "Tester `{}` was called {} that isn't a string",
+            tester_name, part
+        ))),
+    }
+}
+
+/// Returns true if `value` is defined. Otherwise, returns false.
+pub fn defined(value: Option<&Value>, params: &[Value]) -> Result<bool> {
+    number_args_allowed("defined", 0, params.len())?;
+
+    Ok(value.is_some())
+}
+
+/// Returns true if `value` is undefined. Otherwise, returns false.
+pub fn undefined(value: Option<&Value>, params: &[Value]) -> Result<bool> {
+    number_args_allowed("undefined", 0, params.len())?;
+
+    Ok(value.is_none())
+}
+
+/// Returns true if `value` is a string. Otherwise, returns false.
+pub fn string(value: Option<&Value>, params: &[Value]) -> Result<bool> {
+    number_args_allowed("string", 0, params.len())?;
+    value_defined("string", value)?;
+
+    match value {
+        Some(Value::String(_)) => Ok(true),
+        _ => Ok(false),
+    }
+}
+
+/// Returns true if `value` is a number. Otherwise, returns false.
+pub fn number(value: Option<&Value>, params: &[Value]) -> Result<bool> {
+    number_args_allowed("number", 0, params.len())?;
+    value_defined("number", value)?;
+
+    match value {
+        Some(Value::Number(_)) => Ok(true),
+        _ => Ok(false),
+    }
+}
+
+/// Returns true if `value` is an odd number. Otherwise, returns false.
+pub fn odd(value: Option<&Value>, params: &[Value]) -> Result<bool> {
+    number_args_allowed("odd", 0, params.len())?;
+    value_defined("odd", value)?;
+
+    match value.and_then(|v| v.to_number().ok()) {
+        Some(f) => Ok(f % 2.0 != 0.0),
+        _ => Err(Error::msg("Tester `odd` was called on a variable that isn't a number")),
+    }
+}
+
+/// Returns true if `value` is an even number. Otherwise, returns false.
+pub fn even(value: Option<&Value>, params: &[Value]) -> Result<bool> {
+    number_args_allowed("even", 0, params.len())?;
+    value_defined("even", value)?;
+
+    let is_odd = odd(value, params)?;
+    Ok(!is_odd)
+}
+
+/// Returns true if `value` is divisible by the first param. Otherwise, returns false.
+pub fn divisible_by(value: Option<&Value>, params: &[Value]) -> Result<bool> {
+    number_args_allowed("divisibleby", 1, params.len())?;
+    value_defined("divisibleby", value)?;
+
+    match value.and_then(|v| v.to_number().ok()) {
+        Some(val) => match params.first().and_then(|v| v.to_number().ok()) {
+            Some(p) => Ok(val % p == 0.0),
+            None => Err(Error::msg(
+                "Tester `divisibleby` was called with a parameter that isn't a number",
+            )),
+        },
+        None => {
+            Err(Error::msg("Tester `divisibleby` was called on a variable that isn't a number"))
+        }
+    }
+}
+
+/// Returns true if `value` can be iterated over in Tera (ie is an array/tuple or an object).
+/// Otherwise, returns false.
+pub fn iterable(value: Option<&Value>, params: &[Value]) -> Result<bool> {
+    number_args_allowed("iterable", 0, params.len())?;
+    value_defined("iterable", value)?;
+
+    Ok(value.unwrap().is_array() || value.unwrap().is_object())
+}
+
+/// Returns true if the given variable is an object (ie can be iterated over key, value).
+/// Otherwise, returns false.
+pub fn object(value: Option<&Value>, params: &[Value]) -> Result<bool> {
+    number_args_allowed("object", 0, params.len())?;
+    value_defined("object", value)?;
+
+    Ok(value.unwrap().is_object())
+}
+
+/// Returns true if `value` starts with the given string. Otherwise, returns false.
+pub fn starting_with(value: Option<&Value>, params: &[Value]) -> Result<bool> {
+    number_args_allowed("starting_with", 1, params.len())?;
+    value_defined("starting_with", value)?;
+
+    let value = extract_string("starting_with", "on a variable", value)?;
+    let needle = extract_string("starting_with", "with a parameter", params.first())?;
+    Ok(value.starts_with(needle))
+}
+
+/// Returns true if `value` ends with the given string. Otherwise, returns false.
+pub fn ending_with(value: Option<&Value>, params: &[Value]) -> Result<bool> {
+    number_args_allowed("ending_with", 1, params.len())?;
+    value_defined("ending_with", value)?;
+
+    let value = extract_string("ending_with", "on a variable", value)?;
+    let needle = extract_string("ending_with", "with a parameter", params.first())?;
+    Ok(value.ends_with(needle))
+}
+
+/// Returns true if `value` contains the given argument. Otherwise, returns false.
+pub fn containing(value: Option<&Value>, params: &[Value]) -> Result<bool> {
+    number_args_allowed("containing", 1, params.len())?;
+    value_defined("containing", value)?;
+
+    match value.unwrap() {
+        Value::String(v) => {
+            let needle = extract_string("containing", "with a parameter", params.first())?;
+            Ok(v.contains(needle))
+        }
+        Value::Array(v) => Ok(v.contains(params.first().unwrap())),
+        Value::Object(v) => {
+            let needle = extract_string("containing", "with a parameter", params.first())?;
+            Ok(v.contains_key(needle))
+        }
+        _ => Err(Error::msg("Tester `containing` can only be used on string, array or map")),
+    }
+}
+
+/// Returns true if `value` is a string and matches the regex in the argument. Otherwise, returns false.
+pub fn matching(value: Option<&Value>, params: &[Value]) -> Result<bool> {
+    number_args_allowed("matching", 1, params.len())?;
+    value_defined("matching", value)?;
+
+    let value = extract_string("matching", "on a variable", value)?;
+    let regex = extract_string("matching", "with a parameter", params.first())?;
+
+    let regex = match Regex::new(regex) {
+        Ok(regex) => regex,
+        Err(err) => {
+            return Err(Error::msg(format!(
+                "Tester `matching`: Invalid regular expression: {}",
+                err
+            )));
+        }
+    };
+
+    Ok(regex.is_match(value))
+}
+
+#[cfg(test)]
+mod tests {
+    use std::collections::HashMap;
+
+    use super::{
+        containing, defined, divisible_by, ending_with, iterable, matching, object, starting_with,
+        string,
+    };
+
+    use serde_json::value::to_value;
+
+    #[test]
+    fn test_number_args_ok() {
+        assert!(defined(None, &vec![]).is_ok())
+    }
+
+    #[test]
+    fn test_too_many_args() {
+        assert!(defined(None, &vec![to_value(1).unwrap()]).is_err())
+    }
+
+    #[test]
+    fn test_value_defined() {
+        assert!(string(None, &[]).is_err())
+    }
+
+    #[test]
+    fn test_divisible_by() {
+        let tests = vec![
+            (1.0, 2.0, false),
+            (4.0, 2.0, true),
+            (4.0, 2.1, false),
+            (10.0, 2.0, true),
+            (10.0, 0.0, false),
+        ];
+
+        for (val, divisor, expected) in tests {
+            assert_eq!(
+                divisible_by(Some(&to_value(val).unwrap()), &[to_value(divisor).unwrap()],)
+                    .unwrap(),
+                expected
+            );
+        }
+    }
+
+    #[test]
+    fn test_iterable() {
+        assert_eq!(iterable(Some(&to_value(vec!["1"]).unwrap()), &[]).unwrap(), true);
+        assert_eq!(iterable(Some(&to_value(1).unwrap()), &[]).unwrap(), false);
+        assert_eq!(iterable(Some(&to_value("hello").unwrap()), &[]).unwrap(), false);
+    }
+
+    #[test]
+    fn test_object() {
+        let mut h = HashMap::new();
+        h.insert("a", 1);
+        assert_eq!(object(Some(&to_value(h).unwrap()), &[]).unwrap(), true);
+        assert_eq!(object(Some(&to_value(1).unwrap()), &[]).unwrap(), false);
+        assert_eq!(object(Some(&to_value("hello").unwrap()), &[]).unwrap(), false);
+    }
+
+    #[test]
+    fn test_starting_with() {
+        assert!(starting_with(
+            Some(&to_value("helloworld").unwrap()),
+            &[to_value("hello").unwrap()],
+        )
+        .unwrap());
+        assert!(
+            !starting_with(Some(&to_value("hello").unwrap()), &[to_value("hi").unwrap()],).unwrap()
+        );
+    }
+
+    #[test]
+    fn test_ending_with() {
+        assert!(
+            ending_with(Some(&to_value("helloworld").unwrap()), &[to_value("world").unwrap()],)
+                .unwrap()
+        );
+        assert!(
+            !ending_with(Some(&to_value("hello").unwrap()), &[to_value("hi").unwrap()],).unwrap()
+        );
+    }
+
+    #[test]
+    fn test_containing() {
+        let mut map = HashMap::new();
+        map.insert("hey", 1);
+
+        let tests = vec![
+            (to_value("hello world").unwrap(), to_value("hel").unwrap(), true),
+            (to_value("hello world").unwrap(), to_value("hol").unwrap(), false),
+            (to_value(vec![1, 2, 3]).unwrap(), to_value(3).unwrap(), true),
+            (to_value(vec![1, 2, 3]).unwrap(), to_value(4).unwrap(), false),
+            (to_value(map.clone()).unwrap(), to_value("hey").unwrap(), true),
+            (to_value(map.clone()).unwrap(), to_value("ho").unwrap(), false),
+        ];
+
+        for (container, needle, expected) in tests {
+            assert_eq!(containing(Some(&container), &[needle]).unwrap(), expected);
+        }
+    }
+
+    #[test]
+    fn test_matching() {
+        let tests = vec![
+            (to_value("abc").unwrap(), to_value("b").unwrap(), true),
+            (to_value("abc").unwrap(), to_value("^b$").unwrap(), false),
+            (
+                to_value("Hello, World!").unwrap(),
+                to_value(r"(?i)(hello\W\sworld\W)").unwrap(),
+                true,
+            ),
+            (
+                to_value("The date was 2018-06-28").unwrap(),
+                to_value(r"\d{4}-\d{2}-\d{2}$").unwrap(),
+                true,
+            ),
+        ];
+
+        for (container, needle, expected) in tests {
+            assert_eq!(matching(Some(&container), &[needle]).unwrap(), expected);
+        }
+
+        assert!(
+            matching(Some(&to_value("").unwrap()), &[to_value("(Invalid regex").unwrap()]).is_err()
+        );
+    }
+}
diff --git a/vendor/tera/src/context.rs b/vendor/tera/src/context.rs
new file mode 100644 (file)
index 0000000..e8f84d3
--- /dev/null
@@ -0,0 +1,287 @@
+use std::collections::BTreeMap;
+use std::io::Write;
+
+use serde::ser::Serialize;
+use serde_json::value::{to_value, Map, Value};
+
+use crate::errors::{Error, Result as TeraResult};
+
+/// The struct that holds the context of a template rendering.
+///
+/// Light wrapper around a `BTreeMap` for easier insertions of Serializable
+/// values
+#[derive(Debug, Clone, PartialEq)]
+pub struct Context {
+    data: BTreeMap<String, Value>,
+}
+
+impl Context {
+    /// Initializes an empty context
+    pub fn new() -> Self {
+        Context { data: BTreeMap::new() }
+    }
+
+    /// Converts the `val` parameter to `Value` and insert it into the context.
+    ///
+    /// Panics if the serialization fails.
+    ///
+    /// ```rust
+    /// # use tera::Context;
+    /// let mut context = tera::Context::new();
+    /// context.insert("number_users", &42);
+    /// ```
+    pub fn insert<T: Serialize + ?Sized, S: Into<String>>(&mut self, key: S, val: &T) {
+        self.data.insert(key.into(), to_value(val).unwrap());
+    }
+
+    /// Converts the `val` parameter to `Value` and insert it into the context.
+    ///
+    /// Returns an error if the serialization fails.
+    ///
+    /// ```rust
+    /// # use tera::Context;
+    /// # struct CannotBeSerialized;
+    /// # impl serde::Serialize for CannotBeSerialized {
+    /// #     fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+    /// #         Err(serde::ser::Error::custom("Error"))
+    /// #     }
+    /// # }
+    /// # let user = CannotBeSerialized;
+    /// let mut context = Context::new();
+    /// // user is an instance of a struct implementing `Serialize`
+    /// if let Err(_) = context.try_insert("number_users", &user) {
+    ///     // Serialization failed
+    /// }
+    /// ```
+    pub fn try_insert<T: Serialize + ?Sized, S: Into<String>>(
+        &mut self,
+        key: S,
+        val: &T,
+    ) -> TeraResult<()> {
+        self.data.insert(key.into(), to_value(val)?);
+
+        Ok(())
+    }
+
+    /// Appends the data of the `source` parameter to `self`, overwriting existing keys.
+    /// The source context will be dropped.
+    ///
+    /// ```rust
+    /// # use tera::Context;
+    /// let mut target = Context::new();
+    /// target.insert("a", &1);
+    /// target.insert("b", &2);
+    /// let mut source = Context::new();
+    /// source.insert("b", &3);
+    /// source.insert("d", &4);
+    /// target.extend(source);
+    /// ```
+    pub fn extend(&mut self, mut source: Context) {
+        self.data.append(&mut source.data);
+    }
+
+    /// Converts the context to a `serde_json::Value` consuming the context.
+    pub fn into_json(self) -> Value {
+        let mut m = Map::new();
+        for (key, value) in self.data {
+            m.insert(key, value);
+        }
+        Value::Object(m)
+    }
+
+    /// Takes a serde-json `Value` and convert it into a `Context` with no overhead/cloning.
+    pub fn from_value(obj: Value) -> TeraResult<Self> {
+        match obj {
+            Value::Object(m) => {
+                let mut data = BTreeMap::new();
+                for (key, value) in m {
+                    data.insert(key, value);
+                }
+                Ok(Context { data })
+            }
+            _ => Err(Error::msg(
+                "Creating a Context from a Value/Serialize requires it being a JSON object",
+            )),
+        }
+    }
+
+    /// Takes something that impl Serialize and create a context with it.
+    /// Meant to be used if you have a hashmap or a struct and don't want to insert values
+    /// one by one in the context.
+    pub fn from_serialize(value: impl Serialize) -> TeraResult<Self> {
+        let obj = to_value(value).map_err(Error::json)?;
+        Context::from_value(obj)
+    }
+
+    /// Returns the value at a given key index.
+    pub fn get(&self, index: &str) -> Option<&Value> {
+        self.data.get(index)
+    }
+
+    /// Remove a key from the context, returning the value at the key if the key was previously inserted into the context.
+    pub fn remove(&mut self, index: &str) -> Option<Value> {
+        self.data.remove(index)
+    }
+
+    /// Checks if a value exists at a specific index.
+    pub fn contains_key(&self, index: &str) -> bool {
+        self.data.contains_key(index)
+    }
+}
+
+impl Default for Context {
+    fn default() -> Context {
+        Context::new()
+    }
+}
+
+pub trait ValueRender {
+    fn render(&self, write: &mut impl Write) -> std::io::Result<()>;
+}
+
+// Convert serde Value to String.
+impl ValueRender for Value {
+    fn render(&self, write: &mut impl Write) -> std::io::Result<()> {
+        match *self {
+            Value::String(ref s) => write!(write, "{}", s),
+            Value::Number(ref i) => write!(write, "{}", i),
+            Value::Bool(i) => write!(write, "{}", i),
+            Value::Null => Ok(()),
+            Value::Array(ref a) => {
+                let mut first = true;
+                write!(write, "[")?;
+                for i in a.iter() {
+                    if !first {
+                        write!(write, ", ")?;
+                    }
+                    first = false;
+                    i.render(write)?;
+                }
+                write!(write, "]")?;
+                Ok(())
+            }
+            Value::Object(_) => write!(write, "[object]"),
+        }
+    }
+}
+
+pub trait ValueNumber {
+    fn to_number(&self) -> Result<f64, ()>;
+}
+// Needed for all the maths
+// Convert everything to f64, seems like a terrible idea
+impl ValueNumber for Value {
+    fn to_number(&self) -> Result<f64, ()> {
+        match *self {
+            Value::Number(ref i) => Ok(i.as_f64().unwrap()),
+            _ => Err(()),
+        }
+    }
+}
+
+// From handlebars-rust
+pub trait ValueTruthy {
+    fn is_truthy(&self) -> bool;
+}
+
+impl ValueTruthy for Value {
+    fn is_truthy(&self) -> bool {
+        match *self {
+            Value::Number(ref i) => {
+                if i.is_i64() {
+                    return i.as_i64().unwrap() != 0;
+                }
+                if i.is_u64() {
+                    return i.as_u64().unwrap() != 0;
+                }
+                let f = i.as_f64().unwrap();
+                f != 0.0 && !f.is_nan()
+            }
+            Value::Bool(ref i) => *i,
+            Value::Null => false,
+            Value::String(ref i) => !i.is_empty(),
+            Value::Array(ref i) => !i.is_empty(),
+            Value::Object(ref i) => !i.is_empty(),
+        }
+    }
+}
+
+/// Converts a dotted path to a json pointer one
+#[inline]
+pub fn get_json_pointer(key: &str) -> String {
+    lazy_static::lazy_static! {
+        // Split the key into dot-separated segments, respecting quoted strings as single units
+        // to fix https://github.com/Keats/tera/issues/590
+        static ref JSON_POINTER_REGEX: regex::Regex = regex::Regex::new("\"[^\"]*\"|[^.]+").unwrap();
+    }
+
+    let mut segments = vec![""];
+    segments.extend(JSON_POINTER_REGEX.find_iter(key).map(|mat| mat.as_str().trim_matches('"')));
+    segments.join("/")
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    use serde_json::json;
+    use std::collections::HashMap;
+
+    #[test]
+    fn can_extend_context() {
+        let mut target = Context::new();
+        target.insert("a", &1);
+        target.insert("b", &2);
+        let mut source = Context::new();
+        source.insert("b", &3);
+        source.insert("c", &4);
+        target.extend(source);
+        assert_eq!(*target.data.get("a").unwrap(), to_value(1).unwrap());
+        assert_eq!(*target.data.get("b").unwrap(), to_value(3).unwrap());
+        assert_eq!(*target.data.get("c").unwrap(), to_value(4).unwrap());
+    }
+
+    #[test]
+    fn can_create_context_from_value() {
+        let obj = json!({
+            "name": "bob",
+            "age": 25
+        });
+        let context_from_value = Context::from_value(obj).unwrap();
+        let mut context = Context::new();
+        context.insert("name", "bob");
+        context.insert("age", &25);
+        assert_eq!(context_from_value, context);
+    }
+
+    #[test]
+    fn can_create_context_from_impl_serialize() {
+        let mut map = HashMap::new();
+        map.insert("name", "bob");
+        map.insert("last_name", "something");
+        let context_from_serialize = Context::from_serialize(&map).unwrap();
+        let mut context = Context::new();
+        context.insert("name", "bob");
+        context.insert("last_name", "something");
+        assert_eq!(context_from_serialize, context);
+    }
+
+    #[test]
+    fn can_remove_a_key() {
+        let mut context = Context::new();
+        context.insert("name", "foo");
+        context.insert("bio", "Hi, I'm foo.");
+
+        let mut expected = Context::new();
+        expected.insert("name", "foo");
+        assert_eq!(context.remove("bio"), Some(to_value("Hi, I'm foo.").unwrap()));
+        assert_eq!(context.get("bio"), None);
+        assert_eq!(context, expected);
+    }
+
+    #[test]
+    fn remove_return_none_with_unknown_index() {
+        let mut context = Context::new();
+        assert_eq!(context.remove("unknown"), None);
+    }
+}
diff --git a/vendor/tera/src/errors.rs b/vendor/tera/src/errors.rs
new file mode 100644 (file)
index 0000000..253377f
--- /dev/null
@@ -0,0 +1,234 @@
+use std::convert::Into;
+use std::error::Error as StdError;
+use std::fmt;
+
+/// The kind of an error (non-exhaustive)
+#[derive(Debug)]
+pub enum ErrorKind {
+    /// Generic error
+    Msg(String),
+    /// A loop was found while looking up the inheritance chain
+    CircularExtend {
+        /// Name of the template with the loop
+        tpl: String,
+        /// All the parents templates we found so far
+        inheritance_chain: Vec<String>,
+    },
+    /// A template is extending a template that wasn't found in the Tera instance
+    MissingParent {
+        /// The template we are currently looking at
+        current: String,
+        /// The missing template
+        parent: String,
+    },
+    /// A template was missing (more generic version of MissingParent)
+    TemplateNotFound(String),
+    /// A filter wasn't found
+    FilterNotFound(String),
+    /// A test wasn't found
+    TestNotFound(String),
+    /// A macro was defined in the middle of a template
+    InvalidMacroDefinition(String),
+    /// A function wasn't found
+    FunctionNotFound(String),
+    /// An error happened while serializing JSON
+    Json(serde_json::Error),
+    /// An error occured while executing a function.
+    CallFunction(String),
+    /// An error occured while executing a filter.
+    CallFilter(String),
+    /// An error occured while executing a test.
+    CallTest(String),
+    /// An IO error occured
+    Io(std::io::ErrorKind),
+    /// UTF-8 conversion error
+    ///
+    /// This should not occur unless invalid UTF8 chars are rendered
+    Utf8Conversion {
+        /// The context that indicates where the error occurs in the rendering process
+        context: String,
+    },
+    /// This enum may grow additional variants, so this makes sure clients
+    /// don't count on exhaustive matching. (Otherwise, adding a new variant
+    /// could break existing code.)
+    #[doc(hidden)]
+    __Nonexhaustive,
+}
+
+/// The Error type
+#[derive(Debug)]
+pub struct Error {
+    /// Kind of error
+    pub kind: ErrorKind,
+    source: Option<Box<dyn StdError + Sync + Send>>,
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self.kind {
+            ErrorKind::Msg(ref message) => write!(f, "{}", message),
+            ErrorKind::CircularExtend { ref tpl, ref inheritance_chain } => write!(
+                f,
+                "Circular extend detected for template '{}'. Inheritance chain: `{:?}`",
+                tpl, inheritance_chain
+            ),
+            ErrorKind::MissingParent { ref current, ref parent } => write!(
+                f,
+                "Template '{}' is inheriting from '{}', which doesn't exist or isn't loaded.",
+                current, parent
+            ),
+            ErrorKind::TemplateNotFound(ref name) => write!(f, "Template '{}' not found", name),
+            ErrorKind::FilterNotFound(ref name) => write!(f, "Filter '{}' not found", name),
+            ErrorKind::TestNotFound(ref name) => write!(f, "Test '{}' not found", name),
+            ErrorKind::FunctionNotFound(ref name) => write!(f, "Function '{}' not found", name),
+            ErrorKind::InvalidMacroDefinition(ref info) => {
+                write!(f, "Invalid macro definition: `{}`", info)
+            }
+            ErrorKind::Json(ref e) => write!(f, "{}", e),
+            ErrorKind::CallFunction(ref name) => write!(f, "Function call '{}' failed", name),
+            ErrorKind::CallFilter(ref name) => write!(f, "Filter call '{}' failed", name),
+            ErrorKind::CallTest(ref name) => write!(f, "Test call '{}' failed", name),
+            ErrorKind::Io(ref io_error) => {
+                write!(f, "Io error while writing rendered value to output: {:?}", io_error)
+            }
+            ErrorKind::Utf8Conversion { ref context } => {
+                write!(f, "UTF-8 conversion error occured while rendering template: {}", context)
+            }
+            ErrorKind::__Nonexhaustive => write!(f, "Nonexhaustive"),
+        }
+    }
+}
+
+impl StdError for Error {
+    fn source(&self) -> Option<&(dyn StdError + 'static)> {
+        self.source.as_ref().map(|c| &**c as &(dyn StdError + 'static))
+    }
+}
+
+impl Error {
+    /// Creates generic error
+    pub fn msg(value: impl ToString) -> Self {
+        Self { kind: ErrorKind::Msg(value.to_string()), source: None }
+    }
+
+    /// Creates a circular extend error
+    pub fn circular_extend(tpl: impl ToString, inheritance_chain: Vec<String>) -> Self {
+        Self {
+            kind: ErrorKind::CircularExtend { tpl: tpl.to_string(), inheritance_chain },
+            source: None,
+        }
+    }
+
+    /// Creates a missing parent error
+    pub fn missing_parent(current: impl ToString, parent: impl ToString) -> Self {
+        Self {
+            kind: ErrorKind::MissingParent {
+                current: current.to_string(),
+                parent: parent.to_string(),
+            },
+            source: None,
+        }
+    }
+
+    /// Creates a template not found error
+    pub fn template_not_found(tpl: impl ToString) -> Self {
+        Self { kind: ErrorKind::TemplateNotFound(tpl.to_string()), source: None }
+    }
+
+    /// Creates a filter not found error
+    pub fn filter_not_found(name: impl ToString) -> Self {
+        Self { kind: ErrorKind::FilterNotFound(name.to_string()), source: None }
+    }
+
+    /// Creates a test not found error
+    pub fn test_not_found(name: impl ToString) -> Self {
+        Self { kind: ErrorKind::TestNotFound(name.to_string()), source: None }
+    }
+
+    /// Creates a function not found error
+    pub fn function_not_found(name: impl ToString) -> Self {
+        Self { kind: ErrorKind::FunctionNotFound(name.to_string()), source: None }
+    }
+
+    /// Creates generic error with a source
+    pub fn chain(value: impl ToString, source: impl Into<Box<dyn StdError + Send + Sync>>) -> Self {
+        Self { kind: ErrorKind::Msg(value.to_string()), source: Some(source.into()) }
+    }
+
+    /// Creates an error wrapping a failed function call.
+    pub fn call_function(
+        name: impl ToString,
+        source: impl Into<Box<dyn StdError + Send + Sync>>,
+    ) -> Self {
+        Self { kind: ErrorKind::CallFunction(name.to_string()), source: Some(source.into()) }
+    }
+
+    /// Creates an error wrapping a failed filter call.
+    pub fn call_filter(
+        name: impl ToString,
+        source: impl Into<Box<dyn StdError + Send + Sync>>,
+    ) -> Self {
+        Self { kind: ErrorKind::CallFilter(name.to_string()), source: Some(source.into()) }
+    }
+
+    /// Creates an error wrapping a failed test call.
+    pub fn call_test(
+        name: impl ToString,
+        source: impl Into<Box<dyn StdError + Send + Sync>>,
+    ) -> Self {
+        Self { kind: ErrorKind::CallTest(name.to_string()), source: Some(source.into()) }
+    }
+
+    /// Creates JSON error
+    pub fn json(value: serde_json::Error) -> Self {
+        Self { kind: ErrorKind::Json(value), source: None }
+    }
+
+    /// Creates an invalid macro definition error
+    pub fn invalid_macro_def(name: impl ToString) -> Self {
+        Self { kind: ErrorKind::InvalidMacroDefinition(name.to_string()), source: None }
+    }
+
+    /// Creates an IO error
+    pub fn io_error(error: std::io::Error) -> Self {
+        Self { kind: ErrorKind::Io(error.kind()), source: Some(Box::new(error)) }
+    }
+
+    /// Creates an utf8 conversion error
+    pub fn utf8_conversion_error(error: std::string::FromUtf8Error, context: String) -> Self {
+        Self { kind: ErrorKind::Utf8Conversion { context }, source: Some(Box::new(error)) }
+    }
+}
+
+impl From<std::io::Error> for Error {
+    fn from(error: std::io::Error) -> Self {
+        Self::io_error(error)
+    }
+}
+impl From<&str> for Error {
+    fn from(e: &str) -> Self {
+        Self::msg(e)
+    }
+}
+impl From<String> for Error {
+    fn from(e: String) -> Self {
+        Self::msg(e)
+    }
+}
+impl From<serde_json::Error> for Error {
+    fn from(e: serde_json::Error) -> Self {
+        Self::json(e)
+    }
+}
+/// Convenient wrapper around std::Result.
+pub type Result<T> = ::std::result::Result<T, Error>;
+
+#[cfg(test)]
+mod tests {
+    #[test]
+    fn test_error_is_send_and_sync() {
+        fn test_send_sync<T: Send + Sync>() {}
+
+        test_send_sync::<super::Error>();
+    }
+}
diff --git a/vendor/tera/src/filter_utils.rs b/vendor/tera/src/filter_utils.rs
new file mode 100644 (file)
index 0000000..49e2871
--- /dev/null
@@ -0,0 +1,176 @@
+use crate::errors::{Error, Result};
+use serde_json::Value;
+use std::cmp::Ordering;
+
+#[derive(PartialEq, PartialOrd, Default, Copy, Clone)]
+pub struct OrderedF64(f64);
+
+impl OrderedF64 {
+    fn new(n: f64) -> Result<Self> {
+        if n.is_finite() {
+            Ok(OrderedF64(n))
+        } else {
+            Err(Error::msg(format!("{} cannot be sorted", n)))
+        }
+    }
+}
+
+impl Eq for OrderedF64 {}
+
+impl Ord for OrderedF64 {
+    fn cmp(&self, other: &OrderedF64) -> Ordering {
+        // unwrap is safe because self.0 is finite.
+        self.partial_cmp(other).unwrap()
+    }
+}
+
+#[derive(Default, Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
+pub struct ArrayLen(usize);
+
+pub trait GetValue: Ord + Sized + Clone {
+    fn get_value(val: &Value) -> Result<Self>;
+}
+
+impl GetValue for OrderedF64 {
+    fn get_value(val: &Value) -> Result<Self> {
+        let n = val.as_f64().ok_or_else(|| Error::msg(format!("expected number got {}", val)))?;
+        OrderedF64::new(n)
+    }
+}
+
+impl GetValue for i64 {
+    fn get_value(val: &Value) -> Result<Self> {
+        val.as_i64().ok_or_else(|| Error::msg(format!("expected number got {}", val)))
+    }
+}
+
+impl GetValue for bool {
+    fn get_value(val: &Value) -> Result<Self> {
+        val.as_bool().ok_or_else(|| Error::msg(format!("expected bool got {}", val)))
+    }
+}
+
+impl GetValue for String {
+    fn get_value(val: &Value) -> Result<Self> {
+        let str: Result<&str> =
+            val.as_str().ok_or_else(|| Error::msg(format!("expected string got {}", val)));
+        Ok(str?.to_owned())
+    }
+}
+
+impl GetValue for ArrayLen {
+    fn get_value(val: &Value) -> Result<Self> {
+        let arr =
+            val.as_array().ok_or_else(|| Error::msg(format!("expected array got {}", val)))?;
+        Ok(ArrayLen(arr.len()))
+    }
+}
+
+#[derive(Default)]
+pub struct SortPairs<K: Ord> {
+    pairs: Vec<(Value, K)>,
+}
+
+type SortNumbers = SortPairs<OrderedF64>;
+type SortBools = SortPairs<bool>;
+type SortStrings = SortPairs<String>;
+type SortArrays = SortPairs<ArrayLen>;
+
+impl<K: GetValue> SortPairs<K> {
+    fn try_add_pair(&mut self, val: &Value, key: &Value) -> Result<()> {
+        let key = K::get_value(key)?;
+        self.pairs.push((val.clone(), key));
+        Ok(())
+    }
+
+    fn sort(&mut self) -> Vec<Value> {
+        self.pairs.sort_by_key(|a| a.1.clone());
+        self.pairs.iter().map(|a| a.0.clone()).collect()
+    }
+}
+
+pub trait SortStrategy {
+    fn try_add_pair(&mut self, val: &Value, key: &Value) -> Result<()>;
+    fn sort(&mut self) -> Vec<Value>;
+}
+
+impl<K: GetValue> SortStrategy for SortPairs<K> {
+    fn try_add_pair(&mut self, val: &Value, key: &Value) -> Result<()> {
+        SortPairs::try_add_pair(self, val, key)
+    }
+
+    fn sort(&mut self) -> Vec<Value> {
+        SortPairs::sort(self)
+    }
+}
+
+pub fn get_sort_strategy_for_type(ty: &Value) -> Result<Box<dyn SortStrategy>> {
+    use crate::Value::*;
+    match *ty {
+        Null => Err(Error::msg("Null is not a sortable value")),
+        Bool(_) => Ok(Box::new(SortBools::default())),
+        Number(_) => Ok(Box::new(SortNumbers::default())),
+        String(_) => Ok(Box::new(SortStrings::default())),
+        Array(_) => Ok(Box::new(SortArrays::default())),
+        Object(_) => Err(Error::msg("Object is not a sortable value")),
+    }
+}
+
+#[derive(Default)]
+pub struct Unique<K: Eq + std::hash::Hash> {
+    unique: std::collections::HashSet<K>,
+}
+
+type UniqueNumbers = Unique<i64>;
+type UniqueBools = Unique<bool>;
+struct UniqueStrings {
+    u: Unique<String>,
+    case_sensitive: bool,
+}
+
+pub trait UniqueStrategy {
+    fn insert(&mut self, val: &Value) -> Result<bool>;
+}
+
+impl<K: GetValue + Eq + std::hash::Hash> UniqueStrategy for Unique<K> {
+    fn insert(&mut self, val: &Value) -> Result<bool> {
+        Ok(self.unique.insert(K::get_value(val)?))
+    }
+}
+
+impl UniqueStrings {
+    fn new(case_sensitive: bool) -> UniqueStrings {
+        UniqueStrings { u: Unique::<String>::default(), case_sensitive }
+    }
+}
+
+impl UniqueStrategy for UniqueStrings {
+    fn insert(&mut self, val: &Value) -> Result<bool> {
+        let mut key = String::get_value(val)?;
+        if !self.case_sensitive {
+            key = key.to_lowercase()
+        }
+        Ok(self.u.unique.insert(key))
+    }
+}
+
+pub fn get_unique_strategy_for_type(
+    ty: &Value,
+    case_sensitive: bool,
+) -> Result<Box<dyn UniqueStrategy>> {
+    use crate::Value::*;
+    match *ty {
+        Null => Err(Error::msg("Null is not a unique value")),
+        Bool(_) => Ok(Box::new(UniqueBools::default())),
+        Number(ref val) => {
+            if val.is_f64() {
+                Err(Error::msg("Unique floats are not implemented"))
+            } else {
+                Ok(Box::new(UniqueNumbers::default()))
+            }
+        }
+        String(_) => Ok(Box::new(UniqueStrings::new(case_sensitive))),
+        Array(_) => Err(Error::msg("Unique arrays are not implemented")),
+        Object(_) => Err(Error::msg("Unique objects are not implemented")),
+    }
+}
diff --git a/vendor/tera/src/lib.rs b/vendor/tera/src/lib.rs
new file mode 100644 (file)
index 0000000..1147613
--- /dev/null
@@ -0,0 +1,50 @@
+#![doc(html_root_url = "https://docs.rs/tera")]
+
+//! # Tera
+//! Tera is a template engine based on [Jinja2](http://jinja.pocoo.org/)
+//! and the [Django template language](https://docs.djangoproject.com/en/3.1/topics/templates/).
+//!
+//! See the [site](https://tera.netlify.com) for features and to get started.
+
+#![deny(missing_docs)]
+
+#[macro_use]
+mod macros;
+mod builtins;
+mod context;
+mod errors;
+mod filter_utils;
+mod parser;
+mod renderer;
+mod template;
+mod tera;
+mod utils;
+
+// Library exports.
+
+// Template is meant to be used internally only but is exported for test/bench.
+pub use crate::builtins::filters::Filter;
+pub use crate::builtins::functions::Function;
+pub use crate::builtins::testers::Test;
+pub use crate::context::Context;
+pub use crate::errors::{Error, ErrorKind, Result};
+#[doc(hidden)]
+pub use crate::template::Template;
+pub use crate::tera::Tera;
+pub use crate::utils::escape_html;
+/// Re-export Value and other useful things from serde
+/// so apps/tools can encode data in Tera types
+pub use serde_json::value::{from_value, to_value, Map, Number, Value};
+
+// Exposes the AST if one needs it but changing the AST is not considered
+// a breaking change so it isn't public
+#[doc(hidden)]
+pub use crate::parser::ast;
+
+/// Re-export some helper fns useful to write filters/fns/tests
+pub mod helpers {
+    /// Functions helping writing tests
+    pub mod tests {
+        pub use crate::builtins::testers::{extract_string, number_args_allowed, value_defined};
+    }
+}
diff --git a/vendor/tera/src/macros.rs b/vendor/tera/src/macros.rs
new file mode 100644 (file)
index 0000000..86ac4b4
--- /dev/null
@@ -0,0 +1,35 @@
+/// Helper macro to get real values out of Value while retaining
+/// proper errors in filters
+///
+/// Takes 4 args:
+///
+/// - the filter name,
+/// - the variable name: use "value" if you are using it on the variable the filter is ran on
+/// - the expected type
+/// - the actual variable
+///
+/// ```rust,ignore
+/// let arr = try_get_value!("first", "value", Vec<Value>, value);
+/// let val = try_get_value!("pluralize", "suffix", String, val.clone());
+/// ```
+#[macro_export]
+macro_rules! try_get_value {
+    ($filter_name:expr, $var_name:expr, $ty:ty, $val:expr) => {{
+        match $crate::from_value::<$ty>($val.clone()) {
+            Ok(s) => s,
+            Err(_) => {
+                if $var_name == "value" {
+                    return Err($crate::Error::msg(format!(
+                        "Filter `{}` was called on an incorrect value: got `{}` but expected a {}",
+                        $filter_name, $val, stringify!($ty)
+                    )));
+                } else {
+                    return Err($crate::Error::msg(format!(
+                        "Filter `{}` received an incorrect type for arg `{}`: got `{}` but expected a {}",
+                        $filter_name, $var_name, $val, stringify!($ty)
+                    )));
+                }
+            }
+        }
+    }};
+}
diff --git a/vendor/tera/src/parser/ast.rs b/vendor/tera/src/parser/ast.rs
new file mode 100644 (file)
index 0000000..609c7eb
--- /dev/null
@@ -0,0 +1,353 @@
+use std::collections::HashMap;
+use std::fmt;
+
+/// Whether to remove the whitespace of a `{% %}` tag
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub struct WS {
+    /// `true` if the tag is `{%-`
+    pub left: bool,
+    /// `true` if the tag is `-%}`
+    pub right: bool,
+}
+
+impl Default for WS {
+    fn default() -> Self {
+        WS { left: false, right: false }
+    }
+}
+
+/// All math operators
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum MathOperator {
+    /// +
+    Add,
+    /// -
+    Sub,
+    /// *
+    Mul,
+    /// /
+    Div,
+    /// %
+    Modulo,
+}
+
+impl fmt::Display for MathOperator {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "{}",
+            match *self {
+                MathOperator::Add => "+",
+                MathOperator::Sub => "-",
+                MathOperator::Mul => "*",
+                MathOperator::Div => "/",
+                MathOperator::Modulo => "%",
+            }
+        )
+    }
+}
+
+/// All logic operators
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum LogicOperator {
+    /// >
+    Gt,
+    /// >=
+    Gte,
+    /// <
+    Lt,
+    /// <=
+    Lte,
+    /// ==
+    Eq,
+    /// !=
+    NotEq,
+    /// and
+    And,
+    /// or
+    Or,
+}
+
+impl fmt::Display for LogicOperator {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "{}",
+            match *self {
+                LogicOperator::Gt => ">",
+                LogicOperator::Gte => ">=",
+                LogicOperator::Lt => "<",
+                LogicOperator::Lte => "<=",
+                LogicOperator::Eq => "==",
+                LogicOperator::NotEq => "!=",
+                LogicOperator::And => "and",
+                LogicOperator::Or => "or",
+            }
+        )
+    }
+}
+
+/// A function call, can be a filter or a global function
+#[derive(Clone, Debug, PartialEq)]
+pub struct FunctionCall {
+    /// The name of the function
+    pub name: String,
+    /// The args of the function: key -> value
+    pub args: HashMap<String, Expr>,
+}
+
+/// A mathematical expression
+#[derive(Clone, Debug, PartialEq)]
+pub struct MathExpr {
+    /// The left hand side of the expression
+    pub lhs: Box<Expr>,
+    /// The right hand side of the expression
+    pub rhs: Box<Expr>,
+    /// The operator used
+    pub operator: MathOperator,
+}
+
+/// A logical expression
+#[derive(Clone, Debug, PartialEq)]
+pub struct LogicExpr {
+    /// The left hand side of the expression
+    pub lhs: Box<Expr>,
+    /// The right hand side of the expression
+    pub rhs: Box<Expr>,
+    /// The operator used
+    pub operator: LogicOperator,
+}
+
+/// Can only be a combination of string + ident or ident + ident
+#[derive(Clone, Debug, PartialEq)]
+pub struct StringConcat {
+    /// All the values we're concatening into a string
+    pub values: Vec<ExprVal>,
+}
+
+impl StringConcat {
+    pub(crate) fn to_template_string(&self) -> String {
+        let mut res = Vec::new();
+        for value in &self.values {
+            match value {
+                ExprVal::String(ref s) => res.push(format!("'{}'", s)),
+                ExprVal::Ident(ref s) => res.push(s.to_string()),
+                _ => res.push("unknown".to_string()),
+            }
+        }
+
+        res.join(" ~ ")
+    }
+}
+
+/// Something that checks whether the left side is contained in the right side
+#[derive(Clone, Debug, PartialEq)]
+pub struct In {
+    /// The needle, a string or a basic expression/literal
+    pub lhs: Box<Expr>,
+    /// The haystack, can be a string, an array or an ident only currently
+    pub rhs: Box<Expr>,
+    /// Is it using `not` as in `b` not in `...`?
+    pub negated: bool,
+}
+
+/// An expression is the node found in variable block, kwargs and conditions.
+#[derive(Clone, Debug, PartialEq)]
+#[allow(missing_docs)]
+pub enum ExprVal {
+    String(String),
+    Int(i64),
+    Float(f64),
+    Bool(bool),
+    Ident(String),
+    Math(MathExpr),
+    Logic(LogicExpr),
+    Test(Test),
+    MacroCall(MacroCall),
+    FunctionCall(FunctionCall),
+    // A vec of Expr, not ExprVal since filters are allowed
+    // on values inside arrays
+    Array(Vec<Expr>),
+    StringConcat(StringConcat),
+    In(In),
+}
+
+/// An expression is a value that can be negated and followed by
+/// optional filters
+#[derive(Clone, Debug, PartialEq)]
+pub struct Expr {
+    /// The expression we are evaluating
+    pub val: ExprVal,
+    /// Is it using `not`?
+    pub negated: bool,
+    /// List of filters used on that value
+    pub filters: Vec<FunctionCall>,
+}
+
+impl Expr {
+    /// Create a new basic Expr
+    pub fn new(val: ExprVal) -> Expr {
+        Expr { val, negated: false, filters: vec![] }
+    }
+
+    /// Create a new negated Expr
+    pub fn new_negated(val: ExprVal) -> Expr {
+        Expr { val, negated: true, filters: vec![] }
+    }
+
+    /// Create a new basic Expr with some filters
+    pub fn with_filters(val: ExprVal, filters: Vec<FunctionCall>) -> Expr {
+        Expr { val, filters, negated: false }
+    }
+
+    /// Check if the expr has a default filter as first filter
+    pub fn has_default_filter(&self) -> bool {
+        if self.filters.is_empty() {
+            return false;
+        }
+
+        self.filters[0].name == "default"
+    }
+
+    /// Check if the last filter is `safe`
+    pub fn is_marked_safe(&self) -> bool {
+        if self.filters.is_empty() {
+            return false;
+        }
+
+        self.filters[self.filters.len() - 1].name == "safe"
+    }
+}
+
+/// A test node `if my_var is odd`
+#[derive(Clone, Debug, PartialEq)]
+pub struct Test {
+    /// Which variable is evaluated
+    pub ident: String,
+    /// Is it using `not`?
+    pub negated: bool,
+    /// Name of the test
+    pub name: String,
+    /// Any optional arg given to the test
+    pub args: Vec<Expr>,
+}
+
+/// A filter section node `{{ filter name(param="value") }} content {{ endfilter }}`
+#[derive(Clone, Debug, PartialEq)]
+pub struct FilterSection {
+    /// The filter call itsel
+    pub filter: FunctionCall,
+    /// The filter body
+    pub body: Vec<Node>,
+}
+
+/// Set a variable in the context `{% set val = "hey" %}`
+#[derive(Clone, Debug, PartialEq)]
+pub struct Set {
+    /// The name for that value in the context
+    pub key: String,
+    /// The value to assign
+    pub value: Expr,
+    /// Whether we want to set the variable globally or locally
+    /// global_set is only useful in loops
+    pub global: bool,
+}
+
+/// A call to a namespaced macro `macros::my_macro()`
+#[derive(Clone, Debug, PartialEq)]
+pub struct MacroCall {
+    /// The namespace we're looking for that macro in
+    pub namespace: String,
+    /// The macro name
+    pub name: String,
+    /// The args for that macro: name -> value
+    pub args: HashMap<String, Expr>,
+}
+
+/// A Macro definition
+#[derive(Clone, Debug, PartialEq)]
+pub struct MacroDefinition {
+    /// The macro name
+    pub name: String,
+    /// The args for that macro: name -> optional default value
+    pub args: HashMap<String, Option<Expr>>,
+    /// The macro content
+    pub body: Vec<Node>,
+}
+
+/// A block definition
+#[derive(Clone, Debug, PartialEq)]
+pub struct Block {
+    /// The block name
+    pub name: String,
+    /// The block content
+    pub body: Vec<Node>,
+}
+
+/// A forloop: can be over values or key/values
+#[derive(Clone, Debug, PartialEq)]
+pub struct Forloop {
+    /// Name of the key in the loop (only when iterating on map-like objects)
+    pub key: Option<String>,
+    /// Name of the local variable for the value in the loop
+    pub value: String,
+    /// Expression being iterated on
+    pub container: Expr,
+    /// What's in the forloop itself
+    pub body: Vec<Node>,
+    /// The body to execute in case of an empty object
+    pub empty_body: Option<Vec<Node>>,
+}
+
+/// An if/elif/else condition with their respective body
+#[derive(Clone, Debug, PartialEq)]
+pub struct If {
+    /// First item if the if, all the ones after are elif
+    pub conditions: Vec<(WS, Expr, Vec<Node>)>,
+    /// The optional `else` block
+    pub otherwise: Option<(WS, Vec<Node>)>,
+}
+
+/// All Tera nodes that can be encountered
+#[derive(Clone, Debug, PartialEq)]
+pub enum Node {
+    /// A call to `{{ super() }}` in a block
+    Super,
+
+    /// Some actual text
+    Text(String),
+    /// A `{{ }}` block
+    VariableBlock(WS, Expr),
+    /// A `{% macro hello() %}...{% endmacro %}`
+    MacroDefinition(WS, MacroDefinition, WS),
+
+    /// The `{% extends "blabla.html" %}` node, contains the template name
+    Extends(WS, String),
+    /// The `{% include "blabla.html" %}` node, contains the template name
+    Include(WS, Vec<String>, bool),
+    /// The `{% import "macros.html" as macros %}`
+    ImportMacro(WS, String, String),
+    /// The `{% set val = something %}` tag
+    Set(WS, Set),
+
+    /// The text between `{% raw %}` and `{% endraw %}`
+    Raw(WS, String, WS),
+
+    /// A filter section node `{{ filter name(param="value") }} content {{ endfilter }}`
+    FilterSection(WS, FilterSection, WS),
+    /// A `{% block name %}...{% endblock %}`
+    Block(WS, Block, WS),
+    /// A `{% for i in items %}...{% endfor %}`
+    Forloop(WS, Forloop, WS),
+
+    /// A if/elif/else block, WS for the if/elif/else is directly in the struct
+    If(If, WS),
+
+    /// The `{% break %}` tag
+    Break(WS),
+    /// The `{% continue %}` tag
+    Continue(WS),
+
+    /// The `{# #} `comment tag and its content
+    Comment(WS, String),
+}
diff --git a/vendor/tera/src/parser/mod.rs b/vendor/tera/src/parser/mod.rs
new file mode 100644 (file)
index 0000000..bef5b11
--- /dev/null
@@ -0,0 +1,1223 @@
+use std::collections::HashMap;
+
+use lazy_static::lazy_static;
+use pest::iterators::Pair;
+use pest::prec_climber::{Assoc, Operator, PrecClimber};
+use pest::Parser;
+use pest_derive::Parser;
+
+use crate::errors::{Error, Result as TeraResult};
+
+// This include forces recompiling this source file if the grammar file changes.
+// Uncomment it when doing changes to the .pest file
+const _GRAMMAR: &str = include_str!("tera.pest");
+
+#[derive(Parser)]
+#[grammar = "parser/tera.pest"]
+pub struct TeraParser;
+
+/// The AST of Tera
+pub mod ast;
+mod whitespace;
+
+#[cfg(test)]
+mod tests;
+
+use self::ast::*;
+pub use self::whitespace::remove_whitespace;
+
+lazy_static! {
+    static ref MATH_CLIMBER: PrecClimber<Rule> = PrecClimber::new(vec![
+        // +, -
+        Operator::new(Rule::op_plus, Assoc::Left) | Operator::new(Rule::op_minus, Assoc::Left),
+        // *, /, %
+        Operator::new(Rule::op_times, Assoc::Left) |
+        Operator::new(Rule::op_slash, Assoc::Left) |
+        Operator::new(Rule::op_modulo, Assoc::Left),
+    ]);
+    static ref COMPARISON_EXPR_CLIMBER: PrecClimber<Rule> = PrecClimber::new(vec![
+        // <, <=, >, >=, ==, !=
+        Operator::new(Rule::op_lt, Assoc::Left) | Operator::new(Rule::op_lte, Assoc::Left)
+        | Operator::new(Rule::op_gt, Assoc::Left) | Operator::new(Rule::op_gte, Assoc::Left)
+        | Operator::new(Rule::op_eq, Assoc::Left) | Operator::new(Rule::op_ineq, Assoc::Left),
+    ]);
+    static ref LOGIC_EXPR_CLIMBER: PrecClimber<Rule> = PrecClimber::new(vec![
+        Operator::new(Rule::op_or, Assoc::Left),
+        Operator::new(Rule::op_and, Assoc::Left),
+    ]);
+}
+
+/// Strings are delimited by double quotes, single quotes and backticks
+/// We need to remove those before putting them in the AST
+fn replace_string_markers(input: &str) -> String {
+    match input.chars().next().unwrap() {
+        '"' => input.replace('"', ""),
+        '\'' => input.replace('\'', ""),
+        '`' => input.replace('`', ""),
+        _ => unreachable!("How did you even get there"),
+    }
+}
+
+fn parse_kwarg(pair: Pair<Rule>) -> TeraResult<(String, Expr)> {
+    let mut name = None;
+    let mut val = None;
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::ident => name = Some(p.as_span().as_str().to_string()),
+            Rule::logic_expr => val = Some(parse_logic_expr(p)?),
+            Rule::array_filter => val = Some(parse_array_with_filters(p)?),
+            _ => unreachable!("{:?} not supposed to get there (parse_kwarg)!", p.as_rule()),
+        };
+    }
+
+    Ok((name.unwrap(), val.unwrap()))
+}
+
+fn parse_fn_call(pair: Pair<Rule>) -> TeraResult<FunctionCall> {
+    let mut name = None;
+    let mut args = HashMap::new();
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::ident => name = Some(p.as_span().as_str().to_string()),
+            Rule::kwarg => {
+                let (name, val) = parse_kwarg(p)?;
+                args.insert(name, val);
+            }
+            _ => unreachable!("{:?} not supposed to get there (parse_fn_call)!", p.as_rule()),
+        };
+    }
+
+    Ok(FunctionCall { name: name.unwrap(), args })
+}
+
+fn parse_filter(pair: Pair<Rule>) -> TeraResult<FunctionCall> {
+    let mut name = None;
+    let mut args = HashMap::new();
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::ident => name = Some(p.as_span().as_str().to_string()),
+            Rule::kwarg => {
+                let (name, val) = parse_kwarg(p)?;
+                args.insert(name, val);
+            }
+            Rule::fn_call => {
+                return parse_fn_call(p);
+            }
+            _ => unreachable!("{:?} not supposed to get there (parse_filter)!", p.as_rule()),
+        };
+    }
+
+    Ok(FunctionCall { name: name.unwrap(), args })
+}
+
+fn parse_test_call(pair: Pair<Rule>) -> TeraResult<(String, Vec<Expr>)> {
+    let mut name = None;
+    let mut args = vec![];
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::ident => name = Some(p.as_span().as_str().to_string()),
+            Rule::test_arg =>
+            // iterate on the test_arg rule
+            {
+                for p2 in p.into_inner() {
+                    match p2.as_rule() {
+                        Rule::logic_expr => {
+                            args.push(parse_logic_expr(p2)?);
+                        }
+                        Rule::array => {
+                            args.push(Expr::new(parse_array(p2)?));
+                        }
+                        _ => unreachable!("Invalid arg type for test {:?}", p2.as_rule()),
+                    }
+                }
+            }
+            _ => unreachable!("{:?} not supposed to get there (parse_test_call)!", p.as_rule()),
+        };
+    }
+
+    Ok((name.unwrap(), args))
+}
+
+fn parse_test(pair: Pair<Rule>) -> TeraResult<Test> {
+    let mut ident = None;
+    let mut name = None;
+    let mut args = vec![];
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::dotted_ident => ident = Some(p.as_str().to_string()),
+            Rule::test_call => {
+                let (_name, _args) = parse_test_call(p)?;
+                name = Some(_name);
+                args = _args;
+            }
+            _ => unreachable!("{:?} not supposed to get there (parse_ident)!", p.as_rule()),
+        };
+    }
+
+    Ok(Test { ident: ident.unwrap(), negated: false, name: name.unwrap(), args })
+}
+
+fn parse_string_concat(pair: Pair<Rule>) -> TeraResult<ExprVal> {
+    let mut values = vec![];
+    let mut current_str = String::new();
+
+    // Can we fold it into a simple string?
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::string => {
+                current_str.push_str(&replace_string_markers(p.as_str()));
+            }
+            Rule::int => {
+                if !current_str.is_empty() {
+                    values.push(ExprVal::String(current_str));
+                    current_str = String::new();
+                }
+                values.push(ExprVal::Int(p.as_str().parse().map_err(|_| {
+                    Error::msg(format!("Integer out of bounds: `{}`", p.as_str()))
+                })?));
+            }
+            Rule::float => {
+                if !current_str.is_empty() {
+                    values.push(ExprVal::String(current_str));
+                    current_str = String::new();
+                }
+                values.push(ExprVal::Float(
+                    p.as_str().parse().map_err(|_| {
+                        Error::msg(format!("Float out of bounds: `{}`", p.as_str()))
+                    })?,
+                ));
+            }
+            Rule::dotted_square_bracket_ident => {
+                if !current_str.is_empty() {
+                    values.push(ExprVal::String(current_str));
+                    current_str = String::new();
+                }
+                values.push(ExprVal::Ident(p.as_str().to_string()))
+            }
+            Rule::fn_call => {
+                if !current_str.is_empty() {
+                    values.push(ExprVal::String(current_str));
+                    current_str = String::new();
+                }
+                values.push(ExprVal::FunctionCall(parse_fn_call(p)?))
+            }
+            _ => unreachable!("Got {:?} in parse_string_concat", p),
+        };
+    }
+
+    if values.is_empty() {
+        // we only got a string
+        return Ok(ExprVal::String(current_str));
+    }
+
+    if !current_str.is_empty() {
+        values.push(ExprVal::String(current_str));
+    }
+
+    Ok(ExprVal::StringConcat(StringConcat { values }))
+}
+
+fn parse_basic_expression(pair: Pair<Rule>) -> TeraResult<ExprVal> {
+    let primary = |pair| parse_basic_expression(pair);
+
+    let infix = |lhs: TeraResult<ExprVal>, op: Pair<Rule>, rhs: TeraResult<ExprVal>| {
+        Ok(ExprVal::Math(MathExpr {
+            lhs: Box::new(Expr::new(lhs?)),
+            operator: match op.as_rule() {
+                Rule::op_plus => MathOperator::Add,
+                Rule::op_minus => MathOperator::Sub,
+                Rule::op_times => MathOperator::Mul,
+                Rule::op_slash => MathOperator::Div,
+                Rule::op_modulo => MathOperator::Modulo,
+                _ => unreachable!(),
+            },
+            rhs: Box::new(Expr::new(rhs?)),
+        }))
+    };
+
+    let expr = match pair.as_rule() {
+        Rule::int => ExprVal::Int(
+            pair.as_str()
+                .parse()
+                .map_err(|_| Error::msg(format!("Integer out of bounds: `{}`", pair.as_str())))?,
+        ),
+        Rule::float => ExprVal::Float(
+            pair.as_str()
+                .parse()
+                .map_err(|_| Error::msg(format!("Float out of bounds: `{}`", pair.as_str())))?,
+        ),
+        Rule::boolean => match pair.as_str() {
+            "true" => ExprVal::Bool(true),
+            "True" => ExprVal::Bool(true),
+            "false" => ExprVal::Bool(false),
+            "False" => ExprVal::Bool(false),
+            _ => unreachable!(),
+        },
+        Rule::test => ExprVal::Test(parse_test(pair)?),
+        Rule::test_not => {
+            let mut test = parse_test(pair)?;
+            test.negated = true;
+            ExprVal::Test(test)
+        }
+        Rule::fn_call => ExprVal::FunctionCall(parse_fn_call(pair)?),
+        Rule::macro_call => ExprVal::MacroCall(parse_macro_call(pair)?),
+        Rule::dotted_square_bracket_ident => ExprVal::Ident(pair.as_str().to_string()),
+        Rule::basic_expr => MATH_CLIMBER.climb(pair.into_inner(), primary, infix)?,
+        _ => unreachable!("Got {:?} in parse_basic_expression: {}", pair.as_rule(), pair.as_str()),
+    };
+    Ok(expr)
+}
+
+/// A basic expression with optional filters
+fn parse_basic_expr_with_filters(pair: Pair<Rule>) -> TeraResult<Expr> {
+    let mut expr_val = None;
+    let mut filters = vec![];
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::basic_expr => expr_val = Some(parse_basic_expression(p)?),
+            Rule::filter => filters.push(parse_filter(p)?),
+            _ => unreachable!("Got {:?}", p),
+        };
+    }
+
+    Ok(Expr { val: expr_val.unwrap(), negated: false, filters })
+}
+
+/// A string expression with optional filters
+fn parse_string_expr_with_filters(pair: Pair<Rule>) -> TeraResult<Expr> {
+    let mut expr_val = None;
+    let mut filters = vec![];
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::string => expr_val = Some(ExprVal::String(replace_string_markers(p.as_str()))),
+            Rule::string_concat => expr_val = Some(parse_string_concat(p)?),
+            Rule::filter => filters.push(parse_filter(p)?),
+            _ => unreachable!("Got {:?}", p),
+        };
+    }
+
+    Ok(Expr { val: expr_val.unwrap(), negated: false, filters })
+}
+
+/// An array with optional filters
+fn parse_array_with_filters(pair: Pair<Rule>) -> TeraResult<Expr> {
+    let mut array = None;
+    let mut filters = vec![];
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::array => array = Some(parse_array(p)?),
+            Rule::filter => filters.push(parse_filter(p)?),
+            _ => unreachable!("Got {:?}", p),
+        };
+    }
+
+    Ok(Expr { val: array.unwrap(), negated: false, filters })
+}
+
+fn parse_in_condition_container(pair: Pair<Rule>) -> TeraResult<Expr> {
+    let mut expr = None;
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::array_filter => expr = Some(parse_array_with_filters(p)?),
+            Rule::dotted_square_bracket_ident => {
+                expr = Some(Expr::new(ExprVal::Ident(p.as_str().to_string())))
+            }
+            Rule::string_expr_filter => expr = Some(parse_string_expr_with_filters(p)?),
+            _ => unreachable!("Got {:?} in parse_in_condition_container", p),
+        };
+    }
+    Ok(expr.unwrap())
+}
+
+fn parse_in_condition(pair: Pair<Rule>) -> TeraResult<Expr> {
+    let mut lhs = None;
+    let mut rhs = None;
+    let mut negated = false;
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            // lhs
+            Rule::string_expr_filter => lhs = Some(parse_string_expr_with_filters(p)?),
+            Rule::basic_expr_filter => lhs = Some(parse_basic_expr_with_filters(p)?),
+            // rhs
+            Rule::in_cond_container => rhs = Some(parse_in_condition_container(p)?),
+            Rule::op_not => negated = true,
+            _ => unreachable!("Got {:?} in parse_in_condition", p),
+        };
+    }
+
+    Ok(Expr::new(ExprVal::In(In {
+        lhs: Box::new(lhs.unwrap()),
+        rhs: Box::new(rhs.unwrap()),
+        negated,
+    })))
+}
+
+/// A basic expression with optional filters with prece
+fn parse_comparison_val(pair: Pair<Rule>) -> TeraResult<Expr> {
+    let primary = |pair| parse_comparison_val(pair);
+
+    let infix = |lhs: TeraResult<Expr>, op: Pair<Rule>, rhs: TeraResult<Expr>| {
+        Ok(Expr::new(ExprVal::Math(MathExpr {
+            lhs: Box::new(lhs?),
+            operator: match op.as_rule() {
+                Rule::op_plus => MathOperator::Add,
+                Rule::op_minus => MathOperator::Sub,
+                Rule::op_times => MathOperator::Mul,
+                Rule::op_slash => MathOperator::Div,
+                Rule::op_modulo => MathOperator::Modulo,
+                _ => unreachable!(),
+            },
+            rhs: Box::new(rhs?),
+        })))
+    };
+
+    let expr = match pair.as_rule() {
+        Rule::basic_expr_filter => parse_basic_expr_with_filters(pair)?,
+        Rule::comparison_val => MATH_CLIMBER.climb(pair.into_inner(), primary, infix)?,
+        _ => unreachable!("Got {:?} in parse_comparison_val", pair.as_rule()),
+    };
+    Ok(expr)
+}
+
+fn parse_comparison_expression(pair: Pair<Rule>) -> TeraResult<Expr> {
+    let primary = |pair| parse_comparison_expression(pair);
+
+    let infix = |lhs: TeraResult<Expr>, op: Pair<Rule>, rhs: TeraResult<Expr>| {
+        Ok(Expr::new(ExprVal::Logic(LogicExpr {
+            lhs: Box::new(lhs?),
+            operator: match op.as_rule() {
+                Rule::op_lt => LogicOperator::Lt,
+                Rule::op_lte => LogicOperator::Lte,
+                Rule::op_gt => LogicOperator::Gt,
+                Rule::op_gte => LogicOperator::Gte,
+                Rule::op_ineq => LogicOperator::NotEq,
+                Rule::op_eq => LogicOperator::Eq,
+                _ => unreachable!(),
+            },
+            rhs: Box::new(rhs?),
+        })))
+    };
+
+    let expr = match pair.as_rule() {
+        Rule::comparison_val => parse_comparison_val(pair)?,
+        Rule::string_expr_filter => parse_string_expr_with_filters(pair)?,
+        Rule::comparison_expr => {
+            COMPARISON_EXPR_CLIMBER.climb(pair.into_inner(), primary, infix)?
+        }
+        _ => unreachable!("Got {:?} in parse_comparison_expression", pair.as_rule()),
+    };
+    Ok(expr)
+}
+
+/// An expression that can be negated
+fn parse_logic_val(pair: Pair<Rule>) -> TeraResult<Expr> {
+    let mut negated = false;
+    let mut expr = None;
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::op_not => negated = true,
+            Rule::in_cond => expr = Some(parse_in_condition(p)?),
+            Rule::comparison_expr => expr = Some(parse_comparison_expression(p)?),
+            Rule::string_expr_filter => expr = Some(parse_string_expr_with_filters(p)?),
+            _ => unreachable!(),
+        };
+    }
+
+    let mut e = expr.unwrap();
+    e.negated = negated;
+    Ok(e)
+}
+
+fn parse_logic_expr(pair: Pair<Rule>) -> TeraResult<Expr> {
+    let primary = |pair: Pair<Rule>| parse_logic_expr(pair);
+
+    let infix = |lhs: TeraResult<Expr>, op: Pair<Rule>, rhs: TeraResult<Expr>| match op.as_rule() {
+        Rule::op_or => Ok(Expr::new(ExprVal::Logic(LogicExpr {
+            lhs: Box::new(lhs?),
+            operator: LogicOperator::Or,
+            rhs: Box::new(rhs?),
+        }))),
+        Rule::op_and => Ok(Expr::new(ExprVal::Logic(LogicExpr {
+            lhs: Box::new(lhs?),
+            operator: LogicOperator::And,
+            rhs: Box::new(rhs?),
+        }))),
+        _ => unreachable!(
+            "{:?} not supposed to get there (infix of logic_expression)!",
+            op.as_rule()
+        ),
+    };
+
+    let expr = match pair.as_rule() {
+        Rule::logic_val => parse_logic_val(pair)?,
+        Rule::logic_expr => LOGIC_EXPR_CLIMBER.climb(pair.into_inner(), primary, infix)?,
+        _ => unreachable!("Got {:?} in parse_logic_expr", pair.as_rule()),
+    };
+    Ok(expr)
+}
+
+fn parse_array(pair: Pair<Rule>) -> TeraResult<ExprVal> {
+    let mut vals = vec![];
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::logic_val => {
+                vals.push(parse_logic_val(p)?);
+            }
+            _ => unreachable!("Got {:?} in parse_array", p.as_rule()),
+        }
+    }
+
+    Ok(ExprVal::Array(vals))
+}
+
+fn parse_string_array(pair: Pair<Rule>) -> Vec<String> {
+    let mut vals = vec![];
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::string => {
+                vals.push(replace_string_markers(p.as_span().as_str()));
+            }
+            _ => unreachable!("Got {:?} in parse_string_array", p.as_rule()),
+        }
+    }
+
+    vals
+}
+
+fn parse_macro_call(pair: Pair<Rule>) -> TeraResult<MacroCall> {
+    let mut namespace = None;
+    let mut name = None;
+    let mut args = HashMap::new();
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::ident => {
+                // namespace comes first
+                if namespace.is_none() {
+                    namespace = Some(p.as_span().as_str().to_string());
+                } else {
+                    name = Some(p.as_span().as_str().to_string());
+                }
+            }
+            Rule::kwarg => {
+                let (key, val) = parse_kwarg(p)?;
+                args.insert(key, val);
+            }
+            _ => unreachable!("Got {:?} in parse_macro_call", p.as_rule()),
+        }
+    }
+
+    Ok(MacroCall { namespace: namespace.unwrap(), name: name.unwrap(), args })
+}
+
+fn parse_variable_tag(pair: Pair<Rule>) -> TeraResult<Node> {
+    let mut ws = WS::default();
+    let mut expr = None;
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::variable_start => {
+                ws.left = p.as_span().as_str() == "{{-";
+            }
+            Rule::variable_end => {
+                ws.right = p.as_span().as_str() == "-}}";
+            }
+            Rule::logic_expr => expr = Some(parse_logic_expr(p)?),
+            Rule::array_filter => expr = Some(parse_array_with_filters(p)?),
+            _ => unreachable!("unexpected {:?} rule in parse_variable_tag", p.as_rule()),
+        }
+    }
+    Ok(Node::VariableBlock(ws, expr.unwrap()))
+}
+
+fn parse_import_macro(pair: Pair<Rule>) -> Node {
+    let mut ws = WS::default();
+    let mut file = None;
+    let mut ident = None;
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::tag_start => {
+                ws.left = p.as_span().as_str() == "{%-";
+            }
+            Rule::string => file = Some(replace_string_markers(p.as_span().as_str())),
+            Rule::ident => ident = Some(p.as_span().as_str().to_string()),
+            Rule::tag_end => {
+                ws.right = p.as_span().as_str() == "-%}";
+            }
+            _ => unreachable!(),
+        };
+    }
+
+    Node::ImportMacro(ws, file.unwrap(), ident.unwrap())
+}
+
+fn parse_extends(pair: Pair<Rule>) -> Node {
+    let mut ws = WS::default();
+    let mut file = None;
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::tag_start => {
+                ws.left = p.as_span().as_str() == "{%-";
+            }
+            Rule::string => file = Some(replace_string_markers(p.as_span().as_str())),
+            Rule::tag_end => {
+                ws.right = p.as_span().as_str() == "-%}";
+            }
+            _ => unreachable!(),
+        };
+    }
+
+    Node::Extends(ws, file.unwrap())
+}
+
+fn parse_include(pair: Pair<Rule>) -> Node {
+    let mut ws = WS::default();
+    let mut files = vec![];
+    let mut ignore_missing = false;
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::tag_start => {
+                ws.left = p.as_span().as_str() == "{%-";
+            }
+            Rule::string => {
+                files.push(replace_string_markers(p.as_span().as_str()));
+            }
+            Rule::string_array => files.extend(parse_string_array(p)),
+            Rule::ignore_missing => ignore_missing = true,
+            Rule::tag_end => {
+                ws.right = p.as_span().as_str() == "-%}";
+            }
+            _ => unreachable!(),
+        };
+    }
+
+    Node::Include(ws, files, ignore_missing)
+}
+
+fn parse_set_tag(pair: Pair<Rule>, global: bool) -> TeraResult<Node> {
+    let mut ws = WS::default();
+    let mut key = None;
+    let mut expr = None;
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::tag_start => {
+                ws.left = p.as_span().as_str() == "{%-";
+            }
+            Rule::tag_end => {
+                ws.right = p.as_span().as_str() == "-%}";
+            }
+            Rule::ident => key = Some(p.as_str().to_string()),
+            Rule::logic_expr => expr = Some(parse_logic_expr(p)?),
+            Rule::array_filter => expr = Some(parse_array_with_filters(p)?),
+            _ => unreachable!("unexpected {:?} rule in parse_set_tag", p.as_rule()),
+        }
+    }
+
+    Ok(Node::Set(ws, Set { key: key.unwrap(), value: expr.unwrap(), global }))
+}
+
+fn parse_raw_tag(pair: Pair<Rule>) -> Node {
+    let mut start_ws = WS::default();
+    let mut end_ws = WS::default();
+    let mut text = None;
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::raw_tag => {
+                for p2 in p.into_inner() {
+                    match p2.as_rule() {
+                        Rule::tag_start => start_ws.left = p2.as_span().as_str() == "{%-",
+                        Rule::tag_end => start_ws.right = p2.as_span().as_str() == "-%}",
+                        _ => unreachable!(),
+                    }
+                }
+            }
+            Rule::raw_text => text = Some(p.as_str().to_string()),
+            Rule::endraw_tag => {
+                for p2 in p.into_inner() {
+                    match p2.as_rule() {
+                        Rule::tag_start => end_ws.left = p2.as_span().as_str() == "{%-",
+                        Rule::tag_end => end_ws.right = p2.as_span().as_str() == "-%}",
+                        _ => unreachable!(),
+                    }
+                }
+            }
+            _ => unreachable!("unexpected {:?} rule in parse_raw_tag", p.as_rule()),
+        };
+    }
+
+    Node::Raw(start_ws, text.unwrap(), end_ws)
+}
+
+fn parse_filter_section(pair: Pair<Rule>) -> TeraResult<Node> {
+    let mut start_ws = WS::default();
+    let mut end_ws = WS::default();
+    let mut filter = None;
+    let mut body = vec![];
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::filter_tag => {
+                for p2 in p.into_inner() {
+                    match p2.as_rule() {
+                        Rule::tag_start => start_ws.left = p2.as_span().as_str() == "{%-",
+                        Rule::tag_end => start_ws.right = p2.as_span().as_str() == "-%}",
+                        Rule::fn_call => filter = Some(parse_fn_call(p2)?),
+                        Rule::ident => {
+                            filter = Some(FunctionCall {
+                                name: p2.as_str().to_string(),
+                                args: HashMap::new(),
+                            });
+                        }
+                        _ => unreachable!("Got {:?} while parsing filter_tag", p2),
+                    }
+                }
+            }
+            Rule::content
+            | Rule::macro_content
+            | Rule::block_content
+            | Rule::filter_section_content
+            | Rule::for_content => {
+                body.extend(parse_content(p)?);
+            }
+            Rule::endfilter_tag => {
+                for p2 in p.into_inner() {
+                    match p2.as_rule() {
+                        Rule::tag_start => end_ws.left = p2.as_span().as_str() == "{%-",
+                        Rule::tag_end => end_ws.right = p2.as_span().as_str() == "-%}",
+                        _ => unreachable!(),
+                    }
+                }
+            }
+            _ => unreachable!("unexpected {:?} rule in parse_filter_section", p.as_rule()),
+        };
+    }
+    Ok(Node::FilterSection(start_ws, FilterSection { filter: filter.unwrap(), body }, end_ws))
+}
+
+fn parse_block(pair: Pair<Rule>) -> TeraResult<Node> {
+    let mut start_ws = WS::default();
+    let mut end_ws = WS::default();
+    let mut name = None;
+    let mut body = vec![];
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::block_tag => {
+                for p2 in p.into_inner() {
+                    match p2.as_rule() {
+                        Rule::tag_start => start_ws.left = p2.as_span().as_str() == "{%-",
+                        Rule::tag_end => start_ws.right = p2.as_span().as_str() == "-%}",
+                        Rule::ident => name = Some(p2.as_span().as_str().to_string()),
+                        _ => unreachable!(),
+                    };
+                }
+            }
+            Rule::block_content => body.extend(parse_content(p)?),
+            Rule::endblock_tag => {
+                for p2 in p.into_inner() {
+                    match p2.as_rule() {
+                        Rule::tag_start => end_ws.left = p2.as_span().as_str() == "{%-",
+                        Rule::tag_end => end_ws.right = p2.as_span().as_str() == "-%}",
+                        Rule::ident => (),
+                        _ => unreachable!(),
+                    };
+                }
+            }
+            _ => unreachable!("unexpected {:?} rule in parse_filter_section", p.as_rule()),
+        };
+    }
+
+    Ok(Node::Block(start_ws, Block { name: name.unwrap(), body }, end_ws))
+}
+
+fn parse_macro_arg(p: Pair<Rule>) -> TeraResult<ExprVal> {
+    let val = match p.as_rule() {
+        Rule::int => Some(ExprVal::Int(
+            p.as_str()
+                .parse()
+                .map_err(|_| Error::msg(format!("Integer out of bounds: `{}`", p.as_str())))?,
+        )),
+        Rule::float => Some(ExprVal::Float(
+            p.as_str()
+                .parse()
+                .map_err(|_| Error::msg(format!("Float out of bounds: `{}`", p.as_str())))?,
+        )),
+        Rule::boolean => match p.as_str() {
+            "true" => Some(ExprVal::Bool(true)),
+            "True" => Some(ExprVal::Bool(true)),
+            "false" => Some(ExprVal::Bool(false)),
+            "False" => Some(ExprVal::Bool(false)),
+            _ => unreachable!(),
+        },
+        Rule::string => Some(ExprVal::String(replace_string_markers(&p.as_str()))),
+        _ => unreachable!("Got {:?} in parse_macro_arg: {}", p.as_rule(), p.as_str()),
+    };
+
+    Ok(val.unwrap())
+}
+
+fn parse_macro_fn(pair: Pair<Rule>) -> TeraResult<(String, HashMap<String, Option<Expr>>)> {
+    let mut name = String::new();
+    let mut args = HashMap::new();
+
+    for p2 in pair.into_inner() {
+        match p2.as_rule() {
+            Rule::ident => name = p2.as_str().to_string(),
+            Rule::macro_def_arg => {
+                let mut arg_name = None;
+                let mut default_val = None;
+                for p3 in p2.into_inner() {
+                    match p3.as_rule() {
+                        Rule::ident => arg_name = Some(p3.as_str().to_string()),
+                        _ => default_val = Some(Expr::new(parse_macro_arg(p3)?)),
+                    };
+                }
+                args.insert(arg_name.unwrap(), default_val);
+            }
+            _ => continue,
+        }
+    }
+
+    Ok((name, args))
+}
+
+fn parse_macro_definition(pair: Pair<Rule>) -> TeraResult<Node> {
+    let mut start_ws = WS::default();
+    let mut end_ws = WS::default();
+    let mut name = String::new();
+    let mut args = HashMap::new();
+    let mut body = vec![];
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::macro_tag => {
+                for p2 in p.into_inner() {
+                    match p2.as_rule() {
+                        Rule::tag_start => start_ws.left = p2.as_span().as_str() == "{%-",
+                        Rule::tag_end => start_ws.right = p2.as_span().as_str() == "-%}",
+                        Rule::macro_fn_wrapper => {
+                            let macro_fn = parse_macro_fn(p2)?;
+                            name = macro_fn.0;
+                            args = macro_fn.1;
+                        }
+                        _ => continue,
+                    };
+                }
+            }
+            Rule::macro_content => body.extend(parse_content(p)?),
+            Rule::endmacro_tag => {
+                for p2 in p.into_inner() {
+                    match p2.as_rule() {
+                        Rule::tag_start => end_ws.left = p2.as_span().as_str() == "{%-",
+                        Rule::tag_end => end_ws.right = p2.as_span().as_str() == "-%}",
+                        Rule::ident => (),
+                        _ => unreachable!(),
+                    };
+                }
+            }
+            _ => unreachable!("unexpected {:?} rule in parse_macro_definition", p.as_rule()),
+        }
+    }
+
+    Ok(Node::MacroDefinition(start_ws, MacroDefinition { name, args, body }, end_ws))
+}
+
+fn parse_forloop(pair: Pair<Rule>) -> TeraResult<Node> {
+    let mut start_ws = WS::default();
+    let mut end_ws = WS::default();
+
+    let mut key = None;
+    let mut value = None;
+    let mut container = None;
+    let mut body = vec![];
+    let mut empty_body: Option<Vec<Node>> = None;
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::for_tag => {
+                let mut idents = vec![];
+                for p2 in p.into_inner() {
+                    match p2.as_rule() {
+                        Rule::tag_start => start_ws.left = p2.as_span().as_str() == "{%-",
+                        Rule::tag_end => start_ws.right = p2.as_span().as_str() == "-%}",
+                        Rule::ident => idents.push(p2.as_str().to_string()),
+                        Rule::basic_expr_filter => {
+                            container = Some(parse_basic_expr_with_filters(p2)?);
+                        }
+                        Rule::array_filter => container = Some(parse_array_with_filters(p2)?),
+                        _ => unreachable!(),
+                    };
+                }
+
+                if idents.len() == 1 {
+                    value = Some(idents[0].clone());
+                } else {
+                    key = Some(idents[0].clone());
+                    value = Some(idents[1].clone());
+                }
+            }
+            Rule::content
+            | Rule::macro_content
+            | Rule::block_content
+            | Rule::filter_section_content
+            | Rule::for_content => {
+                match empty_body {
+                    Some(ref mut empty_body) => empty_body.extend(parse_content(p)?),
+                    None => body.extend(parse_content(p)?),
+                };
+            }
+            Rule::else_tag => {
+                empty_body = Some(vec![]);
+            }
+            Rule::endfor_tag => {
+                for p2 in p.into_inner() {
+                    match p2.as_rule() {
+                        Rule::tag_start => end_ws.left = p2.as_span().as_str() == "{%-",
+                        Rule::tag_end => end_ws.right = p2.as_span().as_str() == "-%}",
+                        Rule::ident => (),
+                        _ => unreachable!(),
+                    };
+                }
+            }
+            _ => unreachable!("unexpected {:?} rule in parse_forloop", p.as_rule()),
+        };
+    }
+
+    Ok(Node::Forloop(
+        start_ws,
+        Forloop { key, value: value.unwrap(), container: container.unwrap(), body, empty_body },
+        end_ws,
+    ))
+}
+
+fn parse_break_tag(pair: Pair<Rule>) -> Node {
+    let mut ws = WS::default();
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::tag_start => {
+                ws.left = p.as_span().as_str() == "{%-";
+            }
+            Rule::tag_end => {
+                ws.right = p.as_span().as_str() == "-%}";
+            }
+            _ => unreachable!(),
+        };
+    }
+
+    Node::Break(ws)
+}
+
+fn parse_continue_tag(pair: Pair<Rule>) -> Node {
+    let mut ws = WS::default();
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::tag_start => {
+                ws.left = p.as_span().as_str() == "{%-";
+            }
+            Rule::tag_end => {
+                ws.right = p.as_span().as_str() == "-%}";
+            }
+            _ => unreachable!(),
+        };
+    }
+
+    Node::Continue(ws)
+}
+
+fn parse_comment_tag(pair: Pair<Rule>) -> Node {
+    let mut ws = WS::default();
+    let mut content = String::new();
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::comment_start => {
+                ws.left = p.as_span().as_str() == "{#-";
+            }
+            Rule::comment_end => {
+                ws.right = p.as_span().as_str() == "-#}";
+            }
+            Rule::comment_text => {
+                content = p.as_str().to_owned();
+            }
+            _ => unreachable!(),
+        };
+    }
+
+    Node::Comment(ws, content)
+}
+
+fn parse_if(pair: Pair<Rule>) -> TeraResult<Node> {
+    // the `endif` tag ws handling
+    let mut end_ws = WS::default();
+    let mut conditions = vec![];
+    let mut otherwise = None;
+
+    // the current node we're exploring
+    let mut current_ws = WS::default();
+    let mut expr = None;
+    let mut current_body = vec![];
+    let mut in_else = false;
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::if_tag | Rule::elif_tag => {
+                // Reset everything for elifs
+                if p.as_rule() == Rule::elif_tag {
+                    conditions.push((current_ws, expr.unwrap(), current_body));
+                    expr = None;
+                    current_ws = WS::default();
+                    current_body = vec![];
+                }
+
+                for p2 in p.into_inner() {
+                    match p2.as_rule() {
+                        Rule::tag_start => current_ws.left = p2.as_span().as_str() == "{%-",
+                        Rule::tag_end => current_ws.right = p2.as_span().as_str() == "-%}",
+                        Rule::logic_expr => expr = Some(parse_logic_expr(p2)?),
+                        _ => unreachable!(),
+                    };
+                }
+            }
+            Rule::content
+            | Rule::macro_content
+            | Rule::block_content
+            | Rule::for_content
+            | Rule::filter_section_content => current_body.extend(parse_content(p)?),
+            Rule::else_tag => {
+                // had an elif before the else
+                if expr.is_some() {
+                    conditions.push((current_ws, expr.unwrap(), current_body));
+                    expr = None;
+                    current_ws = WS::default();
+                    current_body = vec![];
+                }
+                in_else = true;
+                for p2 in p.into_inner() {
+                    match p2.as_rule() {
+                        Rule::tag_start => current_ws.left = p2.as_span().as_str() == "{%-",
+                        Rule::tag_end => current_ws.right = p2.as_span().as_str() == "-%}",
+                        _ => unreachable!(),
+                    };
+                }
+            }
+            Rule::endif_tag => {
+                if in_else {
+                    otherwise = Some((current_ws, current_body));
+                } else {
+                    // the last elif
+                    conditions.push((current_ws, expr.unwrap(), current_body));
+                }
+
+                for p2 in p.into_inner() {
+                    match p2.as_rule() {
+                        Rule::tag_start => end_ws.left = p2.as_span().as_str() == "{%-",
+                        Rule::tag_end => end_ws.right = p2.as_span().as_str() == "-%}",
+                        _ => unreachable!(),
+                    };
+                }
+                break;
+            }
+            _ => unreachable!("unreachable rule in parse_if: {:?}", p.as_rule()),
+        }
+    }
+
+    Ok(Node::If(If { conditions, otherwise }, end_ws))
+}
+
+fn parse_content(pair: Pair<Rule>) -> TeraResult<Vec<Node>> {
+    let mut nodes = vec![];
+
+    for p in pair.into_inner() {
+        match p.as_rule() {
+            Rule::include_tag => nodes.push(parse_include(p)),
+            Rule::comment_tag => nodes.push(parse_comment_tag(p)),
+            Rule::super_tag => nodes.push(Node::Super),
+            Rule::set_tag => nodes.push(parse_set_tag(p, false)?),
+            Rule::set_global_tag => nodes.push(parse_set_tag(p, true)?),
+            Rule::raw => nodes.push(parse_raw_tag(p)),
+            Rule::variable_tag => nodes.push(parse_variable_tag(p)?),
+            Rule::macro_definition => nodes.push(parse_macro_definition(p)?),
+            Rule::forloop => nodes.push(parse_forloop(p)?),
+            Rule::break_tag => nodes.push(parse_break_tag(p)),
+            Rule::continue_tag => nodes.push(parse_continue_tag(p)),
+            Rule::content_if
+            | Rule::macro_if
+            | Rule::block_if
+            | Rule::for_if
+            | Rule::filter_section_if => nodes.push(parse_if(p)?),
+            Rule::filter_section => nodes.push(parse_filter_section(p)?),
+            Rule::text => nodes.push(Node::Text(p.as_span().as_str().to_string())),
+            Rule::block => nodes.push(parse_block(p)?),
+            _ => unreachable!("unreachable content rule: {:?}", p.as_rule()),
+        };
+    }
+
+    Ok(nodes)
+}
+
+pub fn parse(input: &str) -> TeraResult<Vec<Node>> {
+    let mut pairs = match TeraParser::parse(Rule::template, input) {
+        Ok(p) => p,
+        Err(e) => {
+            let fancy_e = e.renamed_rules(|rule| {
+                match *rule {
+                    Rule::EOI => "end of input".to_string(),
+                    Rule::int => "an integer".to_string(),
+                    Rule::float => "a float".to_string(),
+                    Rule::string
+                    | Rule::double_quoted_string
+                    | Rule::single_quoted_string
+                    | Rule::backquoted_quoted_string => {
+                        "a string".to_string()
+                    }
+                    Rule::string_concat => "a concatenation of strings".to_string(),
+                    Rule::string_expr_filter => "a string or a concatenation of strings".to_string(),
+                    Rule::all_chars => "a character".to_string(),
+                    Rule::array => "an array of values".to_string(),
+                    Rule::array_filter => "an array of values with an optional filter".to_string(),
+                    Rule::string_array => "an array of strings".to_string(),
+                    Rule::basic_val => "a value".to_string(),
+                    Rule::basic_op => "a mathematical operator".to_string(),
+                    Rule::comparison_op => "a comparison operator".to_string(),
+                    Rule::boolean => "`true` or `false`".to_string(),
+                    Rule::ident => "an identifier (must start with a-z)".to_string(),
+                    Rule::dotted_ident => "a dotted identifier (identifiers separated by `.`)".to_string(),
+                    Rule::dotted_square_bracket_ident => "a square bracketed identifier (identifiers separated by `.` or `[]`s)".to_string(),
+                    Rule::square_brackets => "an identifier, string or integer inside `[]`s".to_string(),
+                    Rule::basic_expr_filter => "an expression with an optional filter".to_string(),
+                    Rule::comparison_val => "a comparison value".to_string(),
+                    Rule::basic_expr | Rule::comparison_expr => "an expression".to_string(),
+                    Rule::logic_val => "a value that can be negated".to_string(),
+                    Rule::logic_expr => "any expressions".to_string(),
+                    Rule::fn_call => "a function call".to_string(),
+                    Rule::kwarg => "a keyword argument: `key=value` where `value` can be any expressions".to_string(),
+                    Rule::kwargs => "a list of keyword arguments: `key=value` where `value` can be any expressions and separated by `,`".to_string(),
+                    Rule::op_or => "`or`".to_string(),
+                    Rule::op_and => "`and`".to_string(),
+                    Rule::op_not => "`not`".to_string(),
+                    Rule::op_lte => "`<=`".to_string(),
+                    Rule::op_gte => "`>=`".to_string(),
+                    Rule::op_lt => "`<`".to_string(),
+                    Rule::op_gt => "`>`".to_string(),
+                    Rule::op_ineq => "`!=`".to_string(),
+                    Rule::op_eq => "`==`".to_string(),
+                    Rule::op_plus => "`+`".to_string(),
+                    Rule::op_minus => "`-`".to_string(),
+                    Rule::op_times => "`*`".to_string(),
+                    Rule::op_slash => "`/`".to_string(),
+                    Rule::op_modulo => "`%`".to_string(),
+                    Rule::filter => "a filter".to_string(),
+                    Rule::test => "a test".to_string(),
+                    Rule::test_not => "a negated test".to_string(),
+                    Rule::test_call => "a test call".to_string(),
+                    Rule::test_arg => "a test argument (any expressions including arrays)".to_string(),
+                    Rule::test_args => "a list of test arguments (any expression including arrayss)".to_string(),
+                    Rule::macro_fn | Rule::macro_fn_wrapper => "a macro function".to_string(),
+                    Rule::macro_call => "a macro function call".to_string(),
+                    Rule::macro_def_arg => {
+                        "an argument name with an optional default literal value: `id`, `key=1`".to_string()
+                    }
+                    Rule::macro_def_args => {
+                        "a list of argument names with an optional default literal value: `id`, `key=1`".to_string()
+                    }
+                    Rule::endmacro_tag => "`{% endmacro %}`".to_string(),
+                    Rule::macro_content => "the macro content".to_string(),
+                    Rule::filter_section_content => "the filter section content".to_string(),
+                    Rule::set_tag => "a `set` tag`".to_string(),
+                    Rule::set_global_tag => "a `set_global` tag`".to_string(),
+                    Rule::block_content | Rule::content | Rule::for_content => {
+                        "some content".to_string()
+                    },
+                    Rule::text => "some text".to_string(),
+                    // Pest will error an unexpected tag as Rule::tag_start
+                    // and just showing `{%` is not clear as some other valid
+                    // tags will also start with `{%`
+                    Rule::tag_start => "tag".to_string(),
+                    Rule::tag_end => "`%}` or `-%}`".to_string(),
+                    Rule::super_tag => "`{{ super() }}`".to_string(),
+                    Rule::raw_tag => "`{% raw %}`".to_string(),
+                    Rule::raw_text => "some raw text".to_string(),
+                    Rule::raw => "a raw block (`{% raw %}...{% endraw %}`".to_string(),
+                    Rule::endraw_tag => "`{% endraw %}`".to_string(),
+                    Rule::ignore_missing => "ignore missing mark for include tag".to_string(),
+                    Rule::include_tag => r#"an include tag (`{% include "..." %}`)"#.to_string(),
+                    Rule::comment_tag => "a comment tag (`{#...#}`)".to_string(),
+                    Rule::comment_text => "the context of a comment (`{# ... #}`)".to_string(),
+                    Rule::variable_tag => "a variable tag (`{{ ... }}`)".to_string(),
+                    Rule::filter_tag | Rule::filter_section => {
+                        "a filter section (`{% filter something %}...{% endfilter %}`)".to_string()
+                    }
+                    Rule::for_tag | Rule::forloop => {
+                        "a forloop (`{% for i in something %}...{% endfor %}".to_string()
+                    },
+                    Rule::endfilter_tag => "an endfilter tag (`{% endfilter %}`)".to_string(),
+                    Rule::endfor_tag => "an endfor tag (`{% endfor %}`)".to_string(),
+                    Rule::if_tag
+                    | Rule::content_if
+                    | Rule::block_if
+                    | Rule::macro_if
+                    | Rule::for_if
+                    | Rule::filter_section_if => {
+                        "a `if` tag".to_string()
+                    }
+                    Rule::elif_tag => "an `elif` tag".to_string(),
+                    Rule::else_tag => "an `else` tag".to_string(),
+                    Rule::endif_tag => "an endif tag (`{% endif %}`)".to_string(),
+                    Rule::WHITESPACE => "whitespace".to_string(),
+                    Rule::variable_start => "a variable start (`{{`)".to_string(),
+                    Rule::variable_end => "a variable end (`}}`)".to_string(),
+                    Rule::comment_start => "a comment start (`{#`)".to_string(),
+                    Rule::comment_end => "a comment end (`#}`)".to_string(),
+                    Rule::block_start => "`{{`, `{%` or `{#`".to_string(),
+                    Rule::import_macro_tag => r#"an import macro tag (`{% import "filename" as namespace %}`"#.to_string(),
+                    Rule::block | Rule::block_tag => r#"a block tag (`{% block block_name %}`"#.to_string(),
+                    Rule::endblock_tag => r#"an endblock tag (`{% endblock block_name %}`"#.to_string(),
+                    Rule::macro_definition
+                    | Rule::macro_tag => r#"a macro definition tag (`{% macro my_macro() %}`"#.to_string(),
+                    Rule::extends_tag => r#"an extends tag (`{% extends "myfile" %}`"#.to_string(),
+                    Rule::template => "a template".to_string(),
+                    Rule::break_tag => "a break tag".to_string(),
+                    Rule::continue_tag => "a continue tag".to_string(),
+                    Rule::top_imports => "top imports".to_string(),
+                    Rule::in_cond => "a `in` condition".to_string(),
+                    Rule::in_cond_container => "a `in` condition container: a string, an array or an ident".to_string(),
+                }
+            });
+            return Err(Error::msg(fancy_e));
+        }
+    };
+
+    let mut nodes = vec![];
+
+    // We must have at least a `template` pair if we got there
+    for p in pairs.next().unwrap().into_inner() {
+        match p.as_rule() {
+            Rule::extends_tag => nodes.push(parse_extends(p)),
+            Rule::import_macro_tag => nodes.push(parse_import_macro(p)),
+            Rule::content => nodes.extend(parse_content(p)?),
+            Rule::comment_tag => (),
+            Rule::EOI => (),
+            _ => unreachable!("unknown tpl rule: {:?}", p.as_rule()),
+        }
+    }
+
+    Ok(nodes)
+}
diff --git a/vendor/tera/src/parser/tera.pest b/vendor/tera/src/parser/tera.pest
new file mode 100644 (file)
index 0000000..4effd43
--- /dev/null
@@ -0,0 +1,316 @@
+WHITESPACE = _{ " " | "\t" | "\r" | "\n" }
+
+/// LITERALS
+int   = @{ "-" ? ~ ("0" | '1'..'9' ~ '0'..'9' * ) }
+float = @{
+    "-" ? ~
+    (
+        "0" ~ "." ~ '0'..'9' + |
+        '1'..'9' ~ '0'..'9' * ~ "." ~ '0'..'9' +
+    )
+}
+// matches anything between 2 double quotes
+double_quoted_string  = @{ "\"" ~ (!("\"") ~ ANY)* ~ "\""}
+// matches anything between 2 single quotes
+single_quoted_string  = @{ "\'" ~ (!("\'") ~ ANY)* ~ "\'"}
+// matches anything between 2 backquotes\backticks
+backquoted_quoted_string  = @{ "`" ~ (!("`") ~ ANY)* ~ "`"}
+
+string = @{
+    double_quoted_string |
+    single_quoted_string |
+    backquoted_quoted_string
+}
+
+boolean = { "true" | "false" | "True" | "False" }
+
+// -----------------------------------------------
+
+/// OPERATORS
+op_or        = @{ "or" ~ WHITESPACE }
+op_and       = @{ "and" ~ WHITESPACE }
+op_not       = @{ "not" ~ WHITESPACE }
+op_lte       = { "<=" }
+op_gte       = { ">=" }
+op_lt        = { "<" }
+op_gt        = { ">" }
+op_eq        = { "==" }
+op_ineq      = { "!=" }
+op_plus      = { "+" }
+op_minus     = { "-" }
+op_times     = { "*" }
+op_slash     = { "/" }
+op_modulo    = { "%" }
+
+// -------------------------------------------------
+
+/// Idents
+
+all_chars = _{'a'..'z' | 'A'..'Z' | "_" | '0'..'9'}
+// Used everywhere where an ident is used, except when accessing
+// data from the context.
+// Eg block name, argument name, macro name etc
+ident = @{
+    ('a'..'z' | 'A'..'Z' | "_") ~
+    all_chars*
+}
+
+// The context_ident used to get data from the context.
+// Same as ident but allows `.` in it
+dotted_ident = @{
+    ('a'..'z' | 'A'..'Z' | "_") ~
+    all_chars* ~
+    ("." ~ all_chars+)*
+}
+
+square_brackets = @{
+    "[" ~ (int | string | dotted_square_bracket_ident) ~ "]"
+}
+
+dotted_square_bracket_ident = @{
+    dotted_ident ~ ( ("." ~ all_chars+) | square_brackets )*
+}
+
+string_concat = { (fn_call | float | int | string | dotted_square_bracket_ident) ~ ("~" ~ (fn_call | float | int | string | dotted_square_bracket_ident))+ }
+
+// ----------------------------------------------------
+
+/// EXPRESSIONS
+/// We'll use precedence climbing on those in the parser phase
+
+// boolean first so they are not caught as identifiers
+basic_val  = _{ boolean | test_not | test | macro_call | fn_call | dotted_square_bracket_ident | float | int }
+basic_op   = _{ op_plus | op_minus | op_times | op_slash | op_modulo }
+basic_expr = { ("(" ~ basic_expr ~ ")" | basic_val) ~ (basic_op ~ basic_val)* }
+basic_expr_filter = !{ basic_expr ~ filter* }
+string_expr_filter = !{ (string_concat | string) ~ filter* }
+
+comparison_val  = { basic_expr_filter ~ (basic_op ~ basic_expr_filter)* }
+comparison_op   = _{ op_lte | op_gte | op_gt | op_lt | op_eq | op_ineq }
+comparison_expr = { (string_expr_filter | comparison_val) ~ (comparison_op ~ (string_expr_filter | comparison_val))? }
+
+// The `in` operator
+in_cond_container = {string_expr_filter | array_filter | dotted_square_bracket_ident}
+in_cond = !{ (string_expr_filter | basic_expr_filter) ~ op_not? ~ "in" ~ in_cond_container }
+
+logic_val  = !{ op_not? ~ (in_cond | comparison_expr) }
+logic_expr = !{ logic_val ~ ((op_or | op_and) ~ logic_val)* }
+
+array = !{ "[" ~ (logic_val ~ ",")* ~ logic_val? ~ "]"}
+array_filter = !{ array ~ filter* }
+
+string_array = !{ "[" ~ (string ~ ",")* ~ string? ~ "]"}
+
+// ----------------------------------------------------
+
+/// FUNCTIONS & FILTERS
+
+// A keyword argument: something=10, something="a value", something=1+10 etc
+kwarg   = { ident ~ "=" ~ (logic_expr | array_filter) }
+kwargs  = _{ kwarg ~ ("," ~ kwarg )* ~ ","? }
+fn_call = !{ ident ~ "(" ~ kwargs? ~ ")" }
+filter  = { "|" ~ (fn_call | ident) }
+
+
+// ------------------------------------------------------
+
+/// MACROS
+
+// A macro argument can have default value, only a literal though
+macro_def_arg   = ${ (ident ~ "=" ~ (boolean | string | float | int)) | ident }
+macro_def_args  = _{ macro_def_arg ~ ("," ~ macro_def_arg)* }
+macro_fn        = _{ ident ~ "(" ~ macro_def_args? ~ ")" }
+macro_fn_wrapper = !{ macro_fn }
+macro_call      = { ident ~ "::" ~ ident ~ "(" ~ kwargs? ~ ")" }
+
+
+// -------------------------------------------------------
+
+/// TESTS
+
+// It's a bit weird that tests are the only thing in Tera not using kwargs
+// but at the same time it's one arg most of the time so...
+test_arg  = { logic_expr | array_filter }
+test_args = _{ test_arg ~ ("," ~ test_arg)* }
+test_call = !{ ident ~ ("(" ~ test_args ~ ")")? }
+test_not  = { dotted_ident ~ "is" ~ "not" ~ test_call }
+test      = { dotted_ident ~ "is" ~ test_call }
+
+// -------------------------------------------------------
+
+/// TERA
+
+// All the blocks that Tera recognises
+variable_start = { "{{-" | "{{" }
+variable_end   = { "-}}" | "}}" }
+// whitespace control
+tag_start      = { "{%-" | "{%" }
+tag_end        = { "-%}" | "%}" }
+comment_start  = { "{#-" | "{#" }
+comment_end    = { "-#}" | "#}" }
+block_start    = _{ variable_start | tag_start | comment_start }
+
+comment_text       = ${ (!(comment_end) ~ ANY)+ }
+
+// Tag marks
+ignore_missing = { "ignore" ~ WHITESPACE* ~ "missing" }
+
+
+// Actual tags
+include_tag      = ${ tag_start ~ WHITESPACE* ~ "include" ~ WHITESPACE+ ~ (string | string_array) ~ WHITESPACE* ~ ignore_missing? ~ WHITESPACE* ~ tag_end }
+comment_tag      = ${ comment_start ~ comment_text ~ comment_end }
+block_tag        = ${ tag_start ~ WHITESPACE* ~ "block" ~ WHITESPACE+ ~ ident ~ WHITESPACE* ~ tag_end }
+macro_tag        = ${ tag_start ~ WHITESPACE* ~ "macro" ~ WHITESPACE+ ~ macro_fn_wrapper ~ WHITESPACE* ~ tag_end }
+if_tag           = ${ tag_start ~ WHITESPACE* ~ "if" ~ WHITESPACE+ ~ logic_expr ~ WHITESPACE* ~ tag_end }
+elif_tag         = ${ tag_start ~ WHITESPACE* ~ "elif" ~ WHITESPACE+ ~ logic_expr ~ WHITESPACE* ~ tag_end }
+else_tag         = !{ tag_start ~ "else" ~ tag_end }
+for_tag          = ${
+    tag_start ~ WHITESPACE*
+    ~ "for"~ WHITESPACE+ ~ ident ~ ("," ~ WHITESPACE* ~ ident)? ~ WHITESPACE+ ~ "in" ~ WHITESPACE+ ~ (basic_expr_filter | array_filter)
+    ~ WHITESPACE* ~ tag_end
+}
+filter_tag       = ${
+    tag_start ~ WHITESPACE*
+    ~ "filter" ~ WHITESPACE+ ~ (fn_call | ident)
+    ~ WHITESPACE* ~ tag_end
+}
+set_tag          = ${
+    tag_start ~ WHITESPACE*
+    ~ "set" ~ WHITESPACE+ ~ ident ~ WHITESPACE* ~ "=" ~ WHITESPACE* ~ (logic_expr | array_filter)
+    ~ WHITESPACE* ~ tag_end
+}
+set_global_tag   = ${
+    tag_start ~ WHITESPACE*
+    ~ "set_global" ~ WHITESPACE+ ~ ident ~ WHITESPACE* ~ "=" ~ WHITESPACE* ~ (logic_expr | array_filter)
+    ~ WHITESPACE* ~ tag_end
+}
+endblock_tag     = !{ tag_start ~ "endblock" ~ ident? ~ tag_end }
+endmacro_tag     = !{ tag_start ~ "endmacro" ~ ident? ~ tag_end }
+endif_tag        = !{ tag_start ~ "endif" ~ tag_end }
+endfor_tag       = !{ tag_start ~ "endfor" ~ tag_end }
+endfilter_tag    = !{ tag_start ~ "endfilter" ~ tag_end }
+break_tag        = !{ tag_start ~ "break" ~ tag_end }
+continue_tag     = !{ tag_start ~ "continue" ~ tag_end }
+
+variable_tag     = !{ variable_start ~ (logic_expr | array_filter) ~ variable_end }
+super_tag        = !{ variable_start ~ "super()" ~ variable_end }
+
+text       = ${ (!(block_start) ~ ANY)+ }
+
+raw_tag    = !{ tag_start ~ "raw" ~ tag_end }
+endraw_tag = !{ tag_start ~ "endraw" ~ tag_end }
+raw_text   = ${ (!endraw_tag ~ ANY)* }
+raw        = ${ raw_tag ~ raw_text ~ endraw_tag }
+
+filter_section = ${ filter_tag ~ filter_section_content* ~ endfilter_tag }
+
+forloop = ${ for_tag ~ for_content* ~ (else_tag ~ for_content*)* ~ endfor_tag }
+
+macro_if          = ${ if_tag ~ macro_content* ~ (elif_tag ~ macro_content*)* ~ (else_tag ~ macro_content*)? ~ endif_tag }
+block_if          = ${ if_tag ~ block_content* ~ (elif_tag ~ block_content*)* ~ (else_tag ~ block_content*)? ~ endif_tag }
+for_if            = ${ if_tag ~ for_content* ~ (elif_tag ~ for_content*)* ~ (else_tag ~ for_content*)? ~ endif_tag }
+filter_section_if = ${ if_tag ~ filter_section_content* ~ (elif_tag ~ filter_section_content*)* ~ (else_tag ~ filter_section_content*)? ~ endif_tag }
+content_if        = ${ if_tag ~ content* ~ (elif_tag ~ content*)* ~ (else_tag ~ content*)? ~ endif_tag }
+
+block            = ${ block_tag ~ block_content* ~ endblock_tag }
+macro_definition = ${ macro_tag ~ macro_content* ~ endmacro_tag }
+
+filter_section_content = @{
+    include_tag |
+    variable_tag |
+    comment_tag |
+    set_tag |
+    set_global_tag |
+    block |
+    forloop |
+    filter_section_if |
+    raw |
+    filter_section |
+    text
+}
+
+// smaller sets of allowed content in macros
+macro_content = @{
+    include_tag |
+    variable_tag |
+    comment_tag |
+    set_tag |
+    set_global_tag |
+    macro_if |
+    forloop |
+    filter_section |
+    raw |
+    text
+}
+
+// smaller set of allowed content in block
+block_content = @{
+    include_tag |
+    super_tag |
+    variable_tag |
+    comment_tag |
+    set_tag |
+    set_global_tag |
+    block |
+    block_if |
+    forloop |
+    filter_section |
+    raw |
+    text
+}
+
+// set of allowed content inside for loops
+for_content = @{
+    include_tag |
+    variable_tag |
+    comment_tag |
+    set_tag |
+    set_global_tag |
+    for_if |
+    forloop |
+    break_tag |
+    continue_tag |
+    filter_section |
+    raw |
+    text
+}
+
+content = @{
+    include_tag |
+    variable_tag |
+    comment_tag |
+    set_tag |
+    set_global_tag |
+    macro_definition |
+    block |
+    content_if |
+    forloop |
+    filter_section |
+    raw |
+    text
+}
+
+extends_tag = ${
+    WHITESPACE* ~ tag_start ~ WHITESPACE*
+    ~ "extends" ~ WHITESPACE+ ~ string
+    ~ WHITESPACE* ~ tag_end ~ WHITESPACE*
+}
+import_macro_tag = ${
+    WHITESPACE* ~ tag_start ~ WHITESPACE*
+    ~ "import" ~ WHITESPACE+ ~ string ~ WHITESPACE+ ~ "as" ~ WHITESPACE+ ~ ident
+    ~ WHITESPACE* ~ tag_end ~ WHITESPACE*
+}
+top_imports = _{
+    (extends_tag ~ import_macro_tag*)
+    |
+    (import_macro_tag+ ~ extends_tag?)
+}
+
+// top level rule
+template = ${
+    SOI
+    ~ comment_tag*
+    ~ top_imports?
+    ~ content*
+    ~ EOI
+}
diff --git a/vendor/tera/src/parser/tests/errors.rs b/vendor/tera/src/parser/tests/errors.rs
new file mode 100644 (file)
index 0000000..2538c41
--- /dev/null
@@ -0,0 +1,290 @@
+use crate::parser::parse;
+
+fn assert_err_msg(input: &str, needles: &[&str]) {
+    let res = parse(input);
+    assert!(res.is_err());
+    let err = res.unwrap_err();
+    let err_msg = err.to_string();
+    println!("{}", err_msg);
+    println!("Looking for:");
+    for needle in needles {
+        println!("{}", needle);
+        assert!(err_msg.contains(needle));
+    }
+}
+
+#[test]
+fn invalid_number() {
+    assert_err_msg(
+        "{{ 1.2.2 }}",
+        &[
+            "1:7",
+            "expected `or`, `and`, `not`, `<=`, `>=`, `<`, `>`, `==`, `!=`, `+`, `-`, `*`, `/`, `%`, a filter, or a variable end (`}}`)"
+        ],
+    );
+}
+
+#[test]
+fn invalid_op() {
+    assert_err_msg("{{ 1.2 >+ 3 }}", &["1:9", "expected an expression"]);
+}
+
+#[test]
+fn wrong_start_block() {
+    assert_err_msg(
+        "{{ if true %}",
+        &[
+            "1:7",
+            "expected `or`, `and`, `not`, `<=`, `>=`, `<`, `>`, `==`, `!=`, `+`, `-`, `*`, `/`, `%`, a filter, or a variable end (`}}`)"
+        ],
+    );
+}
+
+#[test]
+fn wrong_end_block() {
+    assert_err_msg(
+        "{{ hey %}",
+        &[
+            "1:9",
+            "expected an integer, a float, `true` or `false`, an identifier (must start with a-z), a dotted identifier (identifiers separated by `.`), a square bracketed identifier (identifiers separated by `.` or `[]`s), or an expression"
+        ],
+    );
+}
+
+#[test]
+fn unterminated_variable_block() {
+    assert_err_msg(
+        "{{ hey",
+        &[
+            "1:7",
+            "expected `or`, `and`, `not`, `<=`, `>=`, `<`, `>`, `==`, `!=`, `+`, `-`, `*`, `/`, `%`, a filter, or a variable end (`}}`)"
+        ],
+    );
+}
+
+#[test]
+fn unterminated_string() {
+    assert_err_msg(r#"{{ "hey }}"#, &["1:4", "expected a value that can be negated"]);
+}
+
+#[test]
+fn unterminated_if_tag() {
+    assert_err_msg(r#"{% if true %}sd"#, &["1:16", r#"expected tag or some content"#]);
+}
+
+#[test]
+fn unterminated_filter_section() {
+    assert_err_msg(
+        r#"{% filter uppercase %}sd"#,
+        &["1:25", r#"expected tag or the filter section content"#],
+    );
+}
+
+#[test]
+fn invalid_filter_section_missing_name() {
+    assert_err_msg(
+        r#"{% filter %}sd{% endfilter %}"#,
+        &["1:11", "expected an identifier (must start with a-z)"],
+    );
+}
+
+#[test]
+fn invalid_macro_content() {
+    assert_err_msg(
+        r#"
+{% macro input(label, type) %}
+    {% macro nested() %}
+    {% endmacro nested %}
+{% endmacro input %}
+    "#,
+        &["3:5", "unexpected tag; expected `{% endmacro %}` or the macro content"],
+    );
+}
+
+#[test]
+fn invalid_macro_default_arg_value() {
+    assert_err_msg(
+        r#"
+{% macro input(label=something) %}
+{% endmacro input %}
+    "#,
+        &["2:22", "expected an integer, a float, a string, or `true` or `false`"],
+    );
+}
+
+#[test]
+fn invalid_elif() {
+    assert_err_msg(
+        r#"
+{% if true %}
+{% else %}
+{% elif false %}
+{% endif %}
+    "#,
+        &["4:1", "unexpected tag; expected an endif tag (`{% endif %}`) or some content"],
+    );
+}
+
+#[test]
+fn invalid_else() {
+    assert_err_msg(
+        r#"
+{% if true %}
+{% else %}
+{% else %}
+{% endif %}
+    "#,
+        &["4:1", "unexpected tag; expected an endif tag (`{% endif %}`) or some content"],
+    );
+}
+
+#[test]
+fn invalid_extends_position() {
+    assert_err_msg(
+        r#"
+hello
+{% extends "hey.html" %}
+    "#,
+        &["3:1", "unexpected tag; expected end of input or some content"],
+    );
+}
+
+#[test]
+fn invalid_operator() {
+    assert_err_msg(
+        "{{ hey =! }}",
+        &[
+            "1:8",
+            "expected `or`, `and`, `not`, `<=`, `>=`, `<`, `>`, `==`, `!=`, `+`, `-`, `*`, `/`, `%`, a filter, or a variable end (`}}`)"
+        ],
+    );
+}
+
+#[test]
+fn missing_expression_with_not() {
+    assert_err_msg("{% if not %}", &["1:11", "expected an expression"]);
+}
+
+#[test]
+fn missing_expression_in_if() {
+    assert_err_msg("{% if %}", &["1:7", "expected a value that can be negated"]);
+}
+
+#[test]
+fn missing_container_name_in_forloop() {
+    assert_err_msg("{% for i in %}", &["1:13", "expected an expression or an array of values"]);
+}
+
+#[test]
+fn missing_variable_name_in_set() {
+    assert_err_msg("{% set = 1 %}", &["1:8", "expected an identifier (must start with a-z)"]);
+}
+
+#[test]
+fn missing_value_in_set() {
+    assert_err_msg(
+        "{% set a =  %}",
+        &["1:13", "expected a value that can be negated or an array of values"],
+    );
+}
+
+#[test]
+fn unterminated_fn_call() {
+    assert_err_msg("{{ a | slice( }}", &["1:15", "expected an identifier (must start with a-z)"]);
+}
+
+#[test]
+fn invalid_fn_call_missing_value() {
+    assert_err_msg(
+        "{{ a | slice(start=) }}",
+        &["1:20", "expected a value that can be negated or an array of values"],
+    );
+}
+
+#[test]
+fn unterminated_macro_call() {
+    assert_err_msg("{{ my::macro( }}", &["1:15", "expected an identifier (must start with a-z)"]);
+}
+
+#[test]
+fn invalid_macro_call() {
+    assert_err_msg(
+        "{{ my:macro() }}",
+        &[
+            "1:6",
+            "expected `or`, `and`, `not`, `<=`, `>=`, `<`, `>`, `==`, `!=`, `+`, `-`, `*`, `/`, `%`, a filter, or a variable end (`}}`)"
+        ],
+    );
+}
+
+#[test]
+fn unterminated_include() {
+    assert_err_msg("{% include %}", &["1:12", "expected a string"]);
+}
+
+#[test]
+fn invalid_include_no_string() {
+    assert_err_msg("{% include 1 %}", &["1:12", "expected a string"]);
+}
+
+#[test]
+fn unterminated_extends() {
+    assert_err_msg("{% extends %}", &["1:12", "expected a string"]);
+}
+
+#[test]
+fn invalid_extends_no_string() {
+    assert_err_msg("{% extends 1 %}", &["1:12", "expected a string"]);
+}
+
+#[test]
+fn invalid_import_macros_missing_filename() {
+    assert_err_msg("{% import as macros %}", &["1:11", "expected a string"]);
+}
+
+#[test]
+fn invalid_import_macros_missing_namespace() {
+    assert_err_msg(
+        r#"{% import "hello" as %}"#,
+        &["1:22", "expected an identifier (must start with a-z)"],
+    );
+}
+
+#[test]
+fn invalid_block_missing_name() {
+    assert_err_msg(r#"{% block %}"#, &["1:10", "expected an identifier (must start with a-z)"]);
+}
+
+#[test]
+fn unterminated_test() {
+    assert_err_msg(
+        r#"{% if a is odd( %}"#,
+        &["1:17", "a test argument (any expressions including arrays)"],
+    );
+}
+
+#[test]
+fn invalid_test_argument() {
+    assert_err_msg(
+        r#"{% if a is odd(key=1) %}"#,
+        &[
+            "1:19",
+            "expected `or`, `and`, `not`, `<=`, `>=`, `<`, `>`, `==`, `!=`, `+`, `-`, `*`, `/`, `%`, or a filter"
+        ],
+    );
+}
+
+#[test]
+fn unterminated_raw_tag() {
+    assert_err_msg(r#"{% raw %}sd"#, &["1:12", "expected tag"]);
+}
+
+#[test]
+fn invalid_break_outside_loop() {
+    assert_err_msg(r#"{% break %}"#, &["1:1", "{% break %}", "expected a template"]);
+}
+
+#[test]
+fn invalid_continue_outside_loop() {
+    assert_err_msg(r#"{% continue %}"#, &["1:1", "{% continue %}", "expected a template"]);
+}
diff --git a/vendor/tera/src/parser/tests/lexer.rs b/vendor/tera/src/parser/tests/lexer.rs
new file mode 100644 (file)
index 0000000..45b3fda
--- /dev/null
@@ -0,0 +1,688 @@
+use pest::Parser;
+
+use crate::parser::{Rule, TeraParser};
+
+macro_rules! assert_lex_rule {
+    ($rule: expr, $input: expr) => {
+        let res = TeraParser::parse($rule, $input);
+        println!("{:?}", $input);
+        println!("{:#?}", res);
+        if res.is_err() {
+            println!("{}", res.unwrap_err());
+            panic!();
+        }
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap().last().unwrap().as_span().end(), $input.len());
+    };
+}
+
+#[test]
+fn lex_boolean() {
+    let inputs = vec!["true", "false", "True", "False"];
+    for i in inputs {
+        assert_lex_rule!(Rule::boolean, i);
+    }
+}
+
+#[test]
+fn lex_int() {
+    let inputs = vec!["-10", "0", "100", "250000"];
+    for i in inputs {
+        assert_lex_rule!(Rule::int, i);
+    }
+}
+
+#[test]
+fn lex_float() {
+    let inputs = vec!["123.5", "123.5", "0.1", "-1.1"];
+    for i in inputs {
+        assert_lex_rule!(Rule::float, i);
+    }
+}
+
+#[test]
+fn lex_string() {
+    let inputs = vec![
+        "\"Blabla\"",
+        "\"123\"",
+        "\'123\'",
+        "\'This is still a string\'",
+        "`this is backquted`",
+        "`and this too`",
+    ];
+    for i in inputs {
+        assert_lex_rule!(Rule::string, i);
+    }
+}
+
+#[test]
+fn lex_ident() {
+    let inputs = vec!["hello", "hello_", "hello_1", "HELLO", "_1"];
+    for i in inputs {
+        assert_lex_rule!(Rule::ident, i);
+    }
+
+    assert!(TeraParser::parse(Rule::ident, "909").is_err());
+}
+
+#[test]
+fn lex_dotted_ident() {
+    let inputs = vec![
+        "hello",
+        "hello_",
+        "hello_1",
+        "HELLO",
+        "_1",
+        "hey.ho",
+        "h",
+        "ho",
+        "hey.ho.hu",
+        "hey.0",
+        "h.u",
+    ];
+    for i in inputs {
+        assert_lex_rule!(Rule::dotted_ident, i);
+    }
+
+    let invalid_inputs = vec![".", "9.w"];
+    for i in invalid_inputs {
+        assert!(TeraParser::parse(Rule::dotted_ident, i).is_err());
+    }
+}
+
+#[test]
+fn lex_dotted_square_bracket_ident() {
+    let inputs = vec![
+        "hey.ho.hu",
+        "hey.0",
+        "h.u.x.0",
+        "hey['ho'][\"hu\"]",
+        "hey[0]",
+        "h['u'].x[0]",
+        "hey[a[0]]",
+    ];
+    for i in inputs {
+        assert_lex_rule!(Rule::dotted_square_bracket_ident, i);
+    }
+
+    let invalid_inputs = vec![".", "9.w"];
+    for i in invalid_inputs {
+        assert!(TeraParser::parse(Rule::dotted_square_bracket_ident, i).is_err());
+    }
+}
+
+#[test]
+fn lex_string_concat() {
+    let inputs = vec![
+        "'hello' ~ `hey`",
+        "'hello' ~ 1",
+        "'hello' ~ 3.14",
+        "1 ~ 'hello'",
+        "3.14 ~ 'hello'",
+        "'hello' ~ ident",
+        "ident ~ 'hello'",
+        "'hello' ~ ident[0]",
+        "'hello' ~ a_function()",
+        "a_function() ~ 'hello'",
+        r#"'hello' ~ "hey""#,
+        r#"a_string ~ " world""#,
+        "'hello' ~ ident ~ `ho`",
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::string_concat, i);
+    }
+}
+
+#[test]
+fn lex_array() {
+    let inputs = vec![
+        "[]",
+        "[1,2,3]",
+        "[1, 2,3,]",
+        "[1 + 1, 2,3 * 2,]",
+        "[\"foo\", \"bar\"]",
+        "[1,true,'string', 0.5, hello(), macros::hey(arg=1)]",
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::array, i);
+    }
+}
+
+#[test]
+fn lex_basic_expr() {
+    let inputs = vec![
+        "admin",
+        "true",
+        "macros::something()",
+        "something()",
+        "a is defined",
+        "a is defined(2)",
+        "1 + 1",
+        "1 + counts",
+        "1 + counts.first",
+        "1 + 2 + 3 * 9/2 + 2.1",
+        "(1 + 2 + 3) * 9/2 + 2.1",
+        "10 * 2 % 5",
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::basic_expr, i);
+    }
+}
+
+#[test]
+fn lex_basic_expr_with_filter() {
+    let inputs = vec![
+        "admin | hello",
+        "true | ho",
+        "macros::something() | hey",
+        "something() | hey",
+        "a is defined | ho",
+        "a is defined(2) | ho",
+        "1 + 1 | round",
+        "1 + counts | round",
+        "1 + counts.first | round",
+        "1 + 2 + 3 * 9/2 + 2.1 | round",
+        "(1 + 2 + 3) * 9/2 + 2.1 | round",
+        "10 * 2 % 5 | round",
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::basic_expr_filter, i);
+    }
+}
+
+#[test]
+fn lex_string_expr_with_filter() {
+    let inputs = vec![
+        r#""hey" | capitalize"#,
+        r#""hey""#,
+        r#""hey" ~ 'ho' | capitalize"#,
+        r#""hey" ~ ho | capitalize"#,
+        r#"ho ~ ho ~ ho | capitalize"#,
+        r#"ho ~ 'ho' ~ ho | capitalize"#,
+        r#"ho ~ 'ho' ~ ho"#,
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::string_expr_filter, i);
+    }
+}
+
+#[test]
+fn lex_comparison_val() {
+    let inputs = vec![
+        // all the basic expr still work
+        "admin",
+        "true",
+        "macros::something()",
+        "something()",
+        "a is defined",
+        "a is defined(2)",
+        "1 + 1",
+        "1 + counts",
+        "1 + counts.first",
+        "1 + 2 + 3 * 9/2 + 2.1",
+        "(1 + 2 + 3) * 9/2 + 2.1",
+        "10 * 2 % 5",
+        // but now ones with filters also work
+        "admin | upper",
+        "admin | upper | round",
+        "admin | upper | round(var=2)",
+        "1.5 + a | round(var=2)",
+        // and maths after filters is ok
+        "a | length - 1",
+        "1.5 + a | round - 1",
+        "1.5 + a | round - (1 + 1.5) | round",
+        "1.5 + a | round - (1 + 1.5) | round",
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::comparison_val, i);
+    }
+}
+
+#[test]
+fn lex_in_cond() {
+    let inputs = vec![
+        "a in b",
+        "1 in b",
+        "'b' in b",
+        "'b' in b",
+        "a in request.path",
+        "'index.html' in request.build_absolute_uri",
+        "a in [1, 2, 3]",
+        "a | capitalize in [1, 2, 3]",
+        "a | capitalize in [1, 'hey']",
+        "a | capitalize in [ho, 1, 'hey']",
+        "'e' in 'hello'",
+        "'e' in 'hello' | capitalize",
+        "e in 'hello'",
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::in_cond, i);
+    }
+}
+
+#[test]
+fn lex_comparison_expr() {
+    let inputs = vec![
+        "1.5 + a | round(var=2) > 10",
+        "1.5 + a | round(var=2) > a | round",
+        "a == b",
+        "a + 1 == b",
+        "a != b",
+        "a % 2 == 0",
+        "a == 'admin'",
+        "a != 'admin'",
+        "a == 'admin' | capitalize",
+        "a != 'admin' | capitalize",
+        "a > b",
+        "a >= b",
+        "a < b",
+        "a <= b",
+        "true > false",
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::comparison_expr, i);
+    }
+}
+
+#[test]
+fn lex_logic_val() {
+    let inputs = vec![
+        // all the basic expr still work
+        "admin",
+        "true",
+        "macros::something()",
+        "something()",
+        r#""hey""#,
+        "a is defined",
+        "a is defined(2)",
+        "a is not defined",
+        "1 + 1",
+        "1 + counts",
+        "1 + counts.first",
+        "1 + 2 + 3 * 9/2 + 2.1",
+        "(1 + 2 + 3) * 9/2 + 2.1",
+        "10 * 2 % 5",
+        // filters still work
+        "admin | upper",
+        "admin | upper | round",
+        "admin | upper | round(var=2)",
+        "1.5 + a | round(var=2)",
+        // but now we can negate things
+        "not true",
+        "not admin",
+        "not num + 1 == 0",
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::logic_val, i);
+    }
+}
+
+#[test]
+fn lex_logic_expr() {
+    let inputs = vec![
+        "1.5 + a | round(var=2) > 10 and admin",
+        "1.5 + a | round(var=2) > a | round or true",
+        "1 > 0 and 2 < 3",
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::logic_expr, i);
+    }
+}
+
+#[test]
+fn lex_kwarg() {
+    let inputs = vec![
+        "hello=1",
+        "hello=1+1",
+        "hello=[]",
+        "hello=[true, false]",
+        "hello1=true",
+        "hello=name",
+        "hello=name|filter",
+        "hello=name|filter(with_arg=true)",
+    ];
+    for i in inputs {
+        assert_lex_rule!(Rule::kwarg, i);
+    }
+}
+
+#[test]
+fn lex_kwargs() {
+    let inputs = vec![
+        "hello=1",
+        "hello=1+1,hey=1",
+        "hello1=true,name=name,admin=true",
+        "hello=name",
+        "hello=name|filter,id=1",
+        "hello=name|filter(with_arg=true),id=1",
+    ];
+    for i in inputs {
+        assert_lex_rule!(Rule::kwargs, i);
+    }
+}
+
+#[test]
+fn lex_fn_call() {
+    let inputs = vec![
+        "fn(hello=1)",
+        "fn(hello=1+1,hey=1)",
+        "fn(hello1=true,name=name,admin=true)",
+        "fn(hello=name)",
+        "fn(hello=name,)",
+        "fn(\n  hello=name,\n)",
+        "fn(hello=name|filter,id=1)",
+    ];
+    for i in inputs {
+        assert_lex_rule!(Rule::fn_call, i);
+    }
+}
+
+#[test]
+fn lex_filter() {
+    let inputs = vec![
+        "|attr",
+        "|attr()",
+        "|attr(key=1)",
+        "|attr(key=1, more=true)",
+        "|attr(key=1,more=true)",
+    ];
+    for i in inputs {
+        assert_lex_rule!(Rule::filter, i);
+    }
+}
+
+#[test]
+fn lex_macro_definition() {
+    let inputs = vec![
+        "hello()",
+        "hello(name, admin)",
+        "hello(name, admin=1)",
+        "hello(name=\"bob\", admin)",
+        "hello(name=\"bob\",admin=true)",
+    ];
+    for i in inputs {
+        // The () are not counted as tokens for some reasons so can't use the macro
+        assert!(TeraParser::parse(Rule::macro_fn, i).is_ok());
+    }
+}
+
+#[test]
+fn lex_test() {
+    let inputs =
+        vec!["a is defined", "a is defined()", "a is divisibleby(2)", "a is in([1, 2, something])"];
+    for i in inputs {
+        // The () are not counted as tokens for some reasons so can't use the macro
+        assert!(TeraParser::parse(Rule::test, i).is_ok());
+    }
+}
+
+#[test]
+fn lex_include_tag() {
+    assert!(TeraParser::parse(Rule::include_tag, "{% include \"index.html\" %}").is_ok());
+    assert!(TeraParser::parse(Rule::include_tag, "{% include [\"index.html\"] %}").is_ok());
+    assert!(TeraParser::parse(Rule::include_tag, "{% include [\"index.html\"] ignore missing %}")
+        .is_ok());
+}
+
+#[test]
+fn lex_import_macro_tag() {
+    assert!(TeraParser::parse(Rule::import_macro_tag, "{% import \"macros.html\" as macros %}",)
+        .is_ok());
+}
+
+#[test]
+fn lex_extends_tag() {
+    assert!(TeraParser::parse(Rule::extends_tag, "{% extends \"index.html\" %}").is_ok());
+}
+
+#[test]
+fn lex_comment_tag() {
+    let inputs = vec![
+        "{# #comment# {{}} {%%} #}",
+        "{# #comment# {{}} {%%} #}",
+        "{#- #comment# {{}} {%%} #}",
+        "{# #comment# {{}} {%%} -#}",
+        "{#- #comment# {{}} {%%} -#}",
+    ];
+    for i in inputs {
+        assert_lex_rule!(Rule::comment_tag, i);
+    }
+}
+
+#[test]
+fn lex_block_tag() {
+    let inputs = vec!["{% block tag %}", "{% block my_block %}"];
+    for i in inputs {
+        assert_lex_rule!(Rule::block_tag, i);
+    }
+}
+
+#[test]
+fn lex_filter_tag() {
+    let inputs = vec![
+        "{%- filter tag() %}",
+        "{% filter foo(bar=baz) -%}",
+        "{% filter foo(bar=42) %}",
+        "{% filter foo(bar=baz,qux=quz) %}",
+        "{% filter foo(bar=baz, qux=quz) %}",
+        "{% filter foo ( bar=\"baz\", qux=42 ) %}",
+    ];
+    for i in inputs {
+        assert_lex_rule!(Rule::filter_tag, i);
+    }
+}
+
+#[test]
+fn lex_macro_tag() {
+    let inputs = vec![
+        "{%- macro tag() %}",
+        "{% macro my_block(name) -%}",
+        "{% macro my_block(name=42) %}",
+        "{% macro foo ( bar=\"baz\", qux=42 ) %}",
+    ];
+    for i in inputs {
+        assert_lex_rule!(Rule::macro_tag, i);
+    }
+}
+
+#[test]
+fn lex_if_tag() {
+    let inputs = vec![
+        "{%- if name %}",
+        "{% if true -%}",
+        "{% if admin or show %}",
+        "{% if 1 + 2 == 2 and true %}",
+        "{% if 1 + 2 == 2 and admin is defined %}",
+    ];
+    for i in inputs {
+        assert_lex_rule!(Rule::if_tag, i);
+    }
+}
+
+#[test]
+fn lex_elif_tag() {
+    let inputs = vec![
+        "{%- elif name %}",
+        "{% elif true -%}",
+        "{% elif admin or show %}",
+        "{% elif 1 + 2 == 2 and true %}",
+        "{% elif 1 + 2 == 2 and admin is defined %}",
+    ];
+    for i in inputs {
+        assert_lex_rule!(Rule::elif_tag, i);
+    }
+}
+
+#[test]
+fn lex_else_tag() {
+    assert!(TeraParser::parse(Rule::else_tag, "{% else %}").is_ok());
+}
+
+#[test]
+fn lex_for_tag() {
+    let inputs = vec![
+        "{%- for a in array %}",
+        "{% for a, b in object -%}",
+        "{% for a, b in fn_call() %}",
+        "{% for a in fn_call() %}",
+        "{% for a in [] %}",
+        "{% for a in [1,2,3,] %}",
+        "{% for a,b in fn_call(with_args=true, name=name) %}",
+        "{% for client in clients | slice(start=1, end=9) %}",
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::for_tag, i);
+    }
+}
+
+#[test]
+fn lex_break_tag() {
+    assert!(TeraParser::parse(Rule::break_tag, "{% break %}").is_ok());
+}
+
+#[test]
+fn lex_continue_tag() {
+    assert!(TeraParser::parse(Rule::continue_tag, "{% continue %}").is_ok());
+}
+
+#[test]
+fn lex_set_tag() {
+    let inputs = vec![
+        "{%- set a = true %}",
+        "{% set a = object -%}",
+        "{% set a = [1,2,3, 'hey'] -%}",
+        "{% set a = fn_call() %}",
+        "{% set a = fn_call(with_args=true, name=name) %}",
+        "{% set a = macros::fn_call(with_args=true, name=name) %}",
+        "{% set a = var | caps %}",
+        "{% set a = var +1 >= 2%}",
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::set_tag, i);
+    }
+}
+
+#[test]
+fn lex_set_global_tag() {
+    let inputs = vec![
+        "{% set_global a = 1 %}",
+        "{% set_global a = [1,2,3, 'hey'] -%}",
+        "{% set_global a = another_var %}",
+        "{% set_global a = another_var | filter %}",
+        "{% set_global a = var +1 >= 2%}",
+        "{%- set_global a = var +1 >= 2 -%}",
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::set_global_tag, i);
+    }
+}
+
+#[test]
+fn lex_variable_tag() {
+    let inputs = vec![
+        "{{ a }}",
+        "{{ a | caps }}",
+        r#"{{ "hey" }}"#,
+        r#"{{ 'hey' }}"#,
+        r#"{{ `hey` }}"#,
+        "{{ fn_call() }}",
+        "{{ macros::fn() }}",
+        "{{ name + 42 }}",
+        "{{ loop.index + 1 }}",
+        "{{ name is defined and name >= 42 }}",
+        "{{ my_macros::macro1(hello=\"world\", foo=bar, hey=1+2) }}",
+        "{{ 'hello' ~ `ho` }}",
+        r#"{{ hello ~ `ho` }}"#,
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::variable_tag, i);
+    }
+}
+
+#[test]
+fn lex_content() {
+    let inputs = vec![
+        "some text",
+        "{{ name }}",
+        "{# comment #}",
+        "{% filter upper %}hey{% endfilter %}",
+        "{% filter upper() %}hey{% endfilter %}",
+        "{% raw %}{{ hey }}{% endraw %}",
+        "{% for a in b %}{{a}}{% endfor %}",
+        "{% if i18n %}世界{% else %}world{% endif %}",
+    ];
+
+    for i in inputs {
+        assert_lex_rule!(Rule::content, i);
+    }
+}
+
+#[test]
+fn lex_template() {
+    assert!(TeraParser::parse(
+        Rule::template,
+        "{# Greeter template #}
+            Hello {% if i18n %}世界{% else %}world{% endif %}
+            {% for country in countries %}
+                {{ loop.index }}.{{ country }}
+            {% endfor %}",
+    )
+    .is_ok());
+}
+
+#[test]
+fn lex_extends_with_imports() {
+    let sample = r#"
+{% extends "base.html" %}
+
+{% import "macros/image.html" as image %}
+{% import "macros/masonry.html" as masonry %}
+{% import "macros/breadcrumb.html" as breadcrumb %}
+{% import "macros/ul_links.html" as ul_links %}
+{% import "macros/location.html" as location %}
+         "#;
+    assert_lex_rule!(Rule::template, sample);
+}
+
+// https://github.com/Keats/tera/issues/379
+#[test]
+fn lex_requires_whitespace_between_things() {
+    // All the ones below should fail parsing
+    let inputs = vec![
+        "{% filterupper %}hey{% endfilter %}",
+        "{% blockhey %}{%endblock%}",
+        "{% macrohey() %}{%endmacro%}",
+        "{% setident = 1 %}",
+        "{% set_globalident = 1 %}",
+        "{% extends'base.html' %}",
+        "{% import 'macros/image.html' asimage %}",
+        "{% import'macros/image.html' as image %}",
+        "{% fora in b %}{{a}}{% endfor %}",
+        "{% for a inb %}{{a}}{% endfor %}",
+        "{% for a,bin c %}{{a}}{% endfor %}",
+        "{% for a,b inc %}{{a}}{% endfor %}",
+        "{% ifi18n %}世界{% else %}world{% endif %}",
+        "{% if i18n %}世界{% eliftrue %}world{% endif %}",
+        "{% include'base.html' %}",
+    ];
+
+    for i in inputs {
+        let res = TeraParser::parse(Rule::template, i);
+        println!("{:?}", i);
+        assert!(res.is_err());
+    }
+}
diff --git a/vendor/tera/src/parser/tests/mod.rs b/vendor/tera/src/parser/tests/mod.rs
new file mode 100644 (file)
index 0000000..5a11d2d
--- /dev/null
@@ -0,0 +1,4 @@
+mod errors;
+mod lexer;
+mod parser;
+mod whitespace;
diff --git a/vendor/tera/src/parser/tests/parser.rs b/vendor/tera/src/parser/tests/parser.rs
new file mode 100644 (file)
index 0000000..fa40ad1
--- /dev/null
@@ -0,0 +1,1114 @@
+use std::collections::HashMap;
+
+use crate::parser::ast::*;
+use crate::parser::parse;
+
+#[test]
+fn parse_empty_template() {
+    let ast = parse("").unwrap();
+    assert_eq!(ast.len(), 0);
+}
+
+#[test]
+fn parse_text() {
+    let ast = parse("hello world").unwrap();
+    assert_eq!(ast[0], Node::Text("hello world".to_string()));
+}
+
+#[test]
+fn parse_text_with_whitespace() {
+    let ast = parse(" hello world ").unwrap();
+    assert_eq!(ast[0], Node::Text(" hello world ".to_string()));
+}
+
+#[test]
+fn parse_include_tag() {
+    let ast = parse("{% include \"index.html\" -%}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::Include(WS { left: false, right: true }, vec!["index.html".to_string()], false,),
+    );
+    let ast =
+        parse("{% include [\"custom/index.html\", \"index.html\"] ignore missing %}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::Include(
+            WS { left: false, right: false },
+            vec!["custom/index.html".to_string(), "index.html".to_string()],
+            true,
+        ),
+    );
+}
+
+#[test]
+fn parse_extends() {
+    let ast = parse("{% extends \"index.html\" -%}").unwrap();
+    assert_eq!(ast[0], Node::Extends(WS { left: false, right: true }, "index.html".to_string(),),);
+}
+
+#[test]
+fn parse_comments_before_extends() {
+    let ast = parse("{# A comment #}{% extends \"index.html\" -%}").unwrap();
+    assert_eq!(ast[0], Node::Extends(WS { left: false, right: true }, "index.html".to_string(),),);
+}
+
+#[test]
+fn parse_import_macro() {
+    let ast = parse("\n{% import \"macros.html\" as macros -%}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::ImportMacro(
+            WS { left: false, right: true },
+            "macros.html".to_string(),
+            "macros".to_string(),
+        ),
+    );
+}
+
+#[test]
+fn parse_variable_with_whitespace_trimming() {
+    let ast = parse("{{- id }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS { left: true, right: false },
+            Expr::new(ExprVal::Ident("id".to_string()))
+        ),
+    );
+}
+
+#[test]
+fn parse_variable_tag_ident() {
+    let ast = parse("{{ id }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(WS::default(), Expr::new(ExprVal::Ident("id".to_string()))),
+    );
+}
+
+#[test]
+fn parse_variable_tag_ident_with_simple_filters() {
+    let ast = parse("{{ arr | first | join(n=2) }}").unwrap();
+    let mut join_args = HashMap::new();
+    join_args.insert("n".to_string(), Expr::new(ExprVal::Int(2)));
+
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::with_filters(
+                ExprVal::Ident("arr".to_string()),
+                vec![
+                    FunctionCall { name: "first".to_string(), args: HashMap::new() },
+                    FunctionCall { name: "join".to_string(), args: join_args },
+                ],
+            )
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_lit() {
+    let ast = parse("{{ 2 }}{{ 3.14 }}{{ \"hey\" }}{{ true }}").unwrap();
+    assert_eq!(ast[0], Node::VariableBlock(WS::default(), Expr::new(ExprVal::Int(2))));
+    assert_eq!(ast[1], Node::VariableBlock(WS::default(), Expr::new(ExprVal::Float(3.14))));
+    assert_eq!(
+        ast[2],
+        Node::VariableBlock(WS::default(), Expr::new(ExprVal::String("hey".to_string()))),
+    );
+    assert_eq!(ast[3], Node::VariableBlock(WS::default(), Expr::new(ExprVal::Bool(true))));
+}
+
+#[test]
+fn parse_variable_tag_array_lit() {
+    let ast = parse("{{ [1, 2, 3] }}").unwrap();
+    let mut join_args = HashMap::new();
+    join_args.insert("n".to_string(), Expr::new(ExprVal::Int(2)));
+
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::Array(vec![
+                Expr::new(ExprVal::Int(1)),
+                Expr::new(ExprVal::Int(2)),
+                Expr::new(ExprVal::Int(3))
+            ]),)
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_array_lit_with_filter() {
+    let ast = parse("{{ [1, 2, 3] | length }}").unwrap();
+    let mut join_args = HashMap::new();
+    join_args.insert("n".to_string(), Expr::new(ExprVal::Int(2)));
+
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::with_filters(
+                ExprVal::Array(vec![
+                    Expr::new(ExprVal::Int(1)),
+                    Expr::new(ExprVal::Int(2)),
+                    Expr::new(ExprVal::Int(3))
+                ]),
+                vec![FunctionCall { name: "length".to_string(), args: HashMap::new() },],
+            )
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_lit_math_expression() {
+    let ast = parse("{{ count + 1 * 2.5 }}").unwrap();
+
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::Math(MathExpr {
+                lhs: Box::new(Expr::new(ExprVal::Ident("count".to_string()))),
+                operator: MathOperator::Add,
+                rhs: Box::new(Expr::new(ExprVal::Math(MathExpr {
+                    lhs: Box::new(Expr::new(ExprVal::Int(1))),
+                    operator: MathOperator::Mul,
+                    rhs: Box::new(Expr::new(ExprVal::Float(2.5))),
+                },))),
+            },))
+        ),
+    );
+}
+
+#[test]
+fn parse_variable_tag_lit_math_expression_with_parentheses() {
+    let ast = parse("{{ (count + 1) * 2.5 }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::Math(MathExpr {
+                lhs: Box::new(Expr::new(ExprVal::Math(MathExpr {
+                    lhs: Box::new(Expr::new(ExprVal::Ident("count".to_string()))),
+                    operator: MathOperator::Add,
+                    rhs: Box::new(Expr::new(ExprVal::Int(1))),
+                },))),
+                operator: MathOperator::Mul,
+                rhs: Box::new(Expr::new(ExprVal::Float(2.5))),
+            },))
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_lit_math_expression_with_parentheses_and_filter() {
+    let ast = parse("{{ (count + 1) * 2.5 | round }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::with_filters(
+                ExprVal::Math(MathExpr {
+                    lhs: Box::new(Expr::new(ExprVal::Math(MathExpr {
+                        lhs: Box::new(Expr::new(ExprVal::Ident("count".to_string()))),
+                        operator: MathOperator::Add,
+                        rhs: Box::new(Expr::new(ExprVal::Int(1))),
+                    },))),
+                    operator: MathOperator::Mul,
+                    rhs: Box::new(Expr::new(ExprVal::Float(2.5))),
+                },),
+                vec![FunctionCall { name: "round".to_string(), args: HashMap::new() },],
+            )
+        )
+    );
+}
+
+#[test]
+fn parse_variable_math_on_filter() {
+    let ast = parse("{{ a | length - 1 }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::Math(MathExpr {
+                lhs: Box::new(Expr::with_filters(
+                    ExprVal::Ident("a".to_string()),
+                    vec![FunctionCall { name: "length".to_string(), args: HashMap::new() },],
+                )),
+                operator: MathOperator::Sub,
+                rhs: Box::new(Expr::new(ExprVal::Int(1))),
+            },))
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_simple_logic_expression() {
+    let ast = parse("{{ 1 > 2 }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::Logic(LogicExpr {
+                lhs: Box::new(Expr::new(ExprVal::Int(1))),
+                operator: LogicOperator::Gt,
+                rhs: Box::new(Expr::new(ExprVal::Int(2))),
+            },))
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_math_and_logic_expression() {
+    let ast = parse("{{ count + 1 * 2.5 and admin }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::Logic(LogicExpr {
+                lhs: Box::new(Expr::new(ExprVal::Math(MathExpr {
+                    lhs: Box::new(Expr::new(ExprVal::Ident("count".to_string()))),
+                    operator: MathOperator::Add,
+                    rhs: Box::new(Expr::new(ExprVal::Math(MathExpr {
+                        lhs: Box::new(Expr::new(ExprVal::Int(1))),
+                        operator: MathOperator::Mul,
+                        rhs: Box::new(Expr::new(ExprVal::Float(2.5))),
+                    },))),
+                },))),
+                operator: LogicOperator::And,
+                rhs: Box::new(Expr::new(ExprVal::Ident("admin".to_string()))),
+            },))
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_math_with_filters_and_logic_expression() {
+    let ast = parse("{{ count + 1 * 2.5 | round and admin }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::Logic(LogicExpr {
+                lhs: Box::new(Expr::with_filters(
+                    ExprVal::Math(MathExpr {
+                        lhs: Box::new(Expr::new(ExprVal::Ident("count".to_string()))),
+                        operator: MathOperator::Add,
+                        rhs: Box::new(Expr::new(ExprVal::Math(MathExpr {
+                            lhs: Box::new(Expr::new(ExprVal::Int(1))),
+                            operator: MathOperator::Mul,
+                            rhs: Box::new(Expr::new(ExprVal::Float(2.5))),
+                        },))),
+                    },),
+                    vec![FunctionCall { name: "round".to_string(), args: HashMap::new() },],
+                )),
+                operator: LogicOperator::And,
+                rhs: Box::new(Expr::new(ExprVal::Ident("admin".to_string()))),
+            },))
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_simple_negated_expr() {
+    let ast = parse("{{ not id }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(WS::default(), Expr::new_negated(ExprVal::Ident("id".to_string())))
+    );
+}
+
+#[test]
+fn parse_test() {
+    let ast = parse("{{ a is divisibleby(2) }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::Test(Test {
+                ident: "a".to_string(),
+                negated: false,
+                name: "divisibleby".to_string(),
+                args: vec![Expr::new(ExprVal::Int(2))]
+            }))
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_negated_expr() {
+    let ast = parse("{{ not id and not true and not 1 + 1 }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::Logic(LogicExpr {
+                lhs: Box::new(Expr::new(ExprVal::Logic(LogicExpr {
+                    lhs: Box::new(Expr::new_negated(ExprVal::Ident("id".to_string()))),
+                    operator: LogicOperator::And,
+                    rhs: Box::new(Expr::new_negated(ExprVal::Bool(true))),
+                },))),
+                operator: LogicOperator::And,
+                rhs: Box::new(Expr::new_negated(ExprVal::Math(MathExpr {
+                    lhs: Box::new(Expr::new(ExprVal::Int(1))),
+                    operator: MathOperator::Add,
+                    rhs: Box::new(Expr::new(ExprVal::Int(1))),
+                },))),
+            },))
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_simple_test() {
+    let ast = parse("{{ id is defined }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::Test(Test {
+                ident: "id".to_string(),
+                negated: false,
+                name: "defined".to_string(),
+                args: vec![],
+            },))
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_simple_negated_test() {
+    let ast = parse("{{ id is not defined }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::Test(Test {
+                ident: "id".to_string(),
+                negated: true,
+                name: "defined".to_string(),
+                args: vec![],
+            },))
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_test_as_expression() {
+    let ast = parse("{{ user is defined and user.admin }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::Logic(LogicExpr {
+                lhs: Box::new(Expr::new(ExprVal::Test(Test {
+                    ident: "user".to_string(),
+                    negated: false,
+                    name: "defined".to_string(),
+                    args: vec![],
+                },))),
+                operator: LogicOperator::And,
+                rhs: Box::new(Expr::new(ExprVal::Ident("user.admin".to_string()))),
+            },))
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_macro_call() {
+    let ast = parse("{{ macros::get_time(some=1) }}").unwrap();
+    let mut args = HashMap::new();
+    args.insert("some".to_string(), Expr::new(ExprVal::Int(1)));
+
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::MacroCall(MacroCall {
+                namespace: "macros".to_string(),
+                name: "get_time".to_string(),
+                args,
+            },)),
+        )
+    );
+}
+
+#[test]
+fn parse_allow_block_in_filter_section() {
+    let ast =
+        parse("{% filter upper %}{% block content %}Hello{% endblock %}{% endfilter %}").unwrap();
+
+    assert_eq!(
+        ast[0],
+        Node::FilterSection(
+            WS::default(),
+            FilterSection {
+                filter: FunctionCall { name: "upper".to_owned(), args: HashMap::default() },
+                body: vec![Node::Block(
+                    WS::default(),
+                    Block {
+                        name: "content".to_owned(),
+                        body: vec![Node::Text("Hello".to_owned())]
+                    },
+                    WS::default(),
+                )],
+            },
+            WS::default(),
+        )
+    );
+}
+
+// smoke test for array in kwargs
+#[test]
+fn parse_variable_tag_macro_call_with_array() {
+    let ast = parse("{{ macros::get_time(some=[1, 2]) }}").unwrap();
+    let mut args = HashMap::new();
+    args.insert(
+        "some".to_string(),
+        Expr::new(ExprVal::Array(vec![Expr::new(ExprVal::Int(1)), Expr::new(ExprVal::Int(2))])),
+    );
+
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::MacroCall(MacroCall {
+                namespace: "macros".to_string(),
+                name: "get_time".to_string(),
+                args,
+            },))
+        )
+    );
+}
+
+// smoke test for array in kwargs
+#[test]
+fn parse_variable_tag_macro_call_with_array_with_filters() {
+    let ast = parse("{{ macros::get_time(some=[1, 2] | reverse) }}").unwrap();
+    let mut args = HashMap::new();
+    args.insert(
+        "some".to_string(),
+        Expr::with_filters(
+            ExprVal::Array(vec![Expr::new(ExprVal::Int(1)), Expr::new(ExprVal::Int(2))]),
+            vec![FunctionCall { name: "reverse".to_string(), args: HashMap::new() }],
+        ),
+    );
+
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::MacroCall(MacroCall {
+                namespace: "macros".to_string(),
+                name: "get_time".to_string(),
+                args,
+            },))
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_macro_call_with_filter() {
+    let ast = parse("{{ macros::get_time(some=1) | round }}").unwrap();
+    let mut args = HashMap::new();
+    args.insert("some".to_string(), Expr::new(ExprVal::Int(1)));
+
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::with_filters(
+                ExprVal::MacroCall(MacroCall {
+                    namespace: "macros".to_string(),
+                    name: "get_time".to_string(),
+                    args,
+                },),
+                vec![FunctionCall { name: "round".to_string(), args: HashMap::new() },],
+            )
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_global_function() {
+    let ast = parse("{{ get_time(some=1) }}").unwrap();
+    let mut args = HashMap::new();
+    args.insert("some".to_string(), Expr::new(ExprVal::Int(1)));
+
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::FunctionCall(FunctionCall { name: "get_time".to_string(), args },))
+        )
+    );
+}
+
+#[test]
+fn parse_in_condition() {
+    let ast = parse("{{ b in c }}").unwrap();
+    let mut args = HashMap::new();
+    args.insert("some".to_string(), Expr::new(ExprVal::Int(1)));
+
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::In(In {
+                lhs: Box::new(Expr::new(ExprVal::Ident("b".to_string()))),
+                rhs: Box::new(Expr::new(ExprVal::Ident("c".to_string()))),
+                negated: false,
+            }))
+        )
+    );
+}
+
+#[test]
+fn parse_negated_in_condition() {
+    let ast = parse("{{ b not in c }}").unwrap();
+    let mut args = HashMap::new();
+    args.insert("some".to_string(), Expr::new(ExprVal::Int(1)));
+
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::In(In {
+                lhs: Box::new(Expr::new(ExprVal::Ident("b".to_string()))),
+                rhs: Box::new(Expr::new(ExprVal::Ident("c".to_string()))),
+                negated: true,
+            }))
+        )
+    );
+}
+
+#[test]
+fn parse_variable_tag_global_function_with_filter() {
+    let ast = parse("{{ get_time(some=1) | round | upper }}").unwrap();
+    let mut args = HashMap::new();
+    args.insert("some".to_string(), Expr::new(ExprVal::Int(1)));
+
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::with_filters(
+                ExprVal::FunctionCall(FunctionCall { name: "get_time".to_string(), args },),
+                vec![
+                    FunctionCall { name: "round".to_string(), args: HashMap::new() },
+                    FunctionCall { name: "upper".to_string(), args: HashMap::new() },
+                ],
+            )
+        )
+    );
+}
+
+#[test]
+fn parse_comment_tag() {
+    let ast = parse("{# hey #}").unwrap();
+    assert!(ast.is_empty());
+}
+
+#[test]
+fn parse_set_tag_lit() {
+    let ast = parse("{% set hello = \"hi\" %}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::Set(
+            WS::default(),
+            Set {
+                key: "hello".to_string(),
+                value: Expr::new(ExprVal::String("hi".to_string())),
+                global: false,
+            },
+        )
+    );
+}
+
+#[test]
+fn parse_set_tag_macro_call() {
+    let ast = parse("{% set hello = macros::something() %}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::Set(
+            WS::default(),
+            Set {
+                key: "hello".to_string(),
+                value: Expr::new(ExprVal::MacroCall(MacroCall {
+                    namespace: "macros".to_string(),
+                    name: "something".to_string(),
+                    args: HashMap::new(),
+                },)),
+                global: false,
+            },
+        )
+    );
+}
+
+#[test]
+fn parse_set_tag_fn_call() {
+    let ast = parse("{% set hello = utcnow() %}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::Set(
+            WS::default(),
+            Set {
+                key: "hello".to_string(),
+                value: Expr::new(ExprVal::FunctionCall(FunctionCall {
+                    name: "utcnow".to_string(),
+                    args: HashMap::new(),
+                },)),
+                global: false,
+            },
+        )
+    );
+}
+
+#[test]
+fn parse_set_array() {
+    let ast = parse("{% set hello = [1, true, 'hello'] %}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::Set(
+            WS::default(),
+            Set {
+                key: "hello".to_string(),
+                value: Expr::new(ExprVal::Array(vec![
+                    Expr::new(ExprVal::Int(1)),
+                    Expr::new(ExprVal::Bool(true)),
+                    Expr::new(ExprVal::String("hello".to_string())),
+                ])),
+                global: false,
+            },
+        )
+    );
+}
+
+#[test]
+fn parse_set_array_with_filter() {
+    let ast = parse("{% set hello = [1, true, 'hello'] | length %}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::Set(
+            WS::default(),
+            Set {
+                key: "hello".to_string(),
+                value: Expr::with_filters(
+                    ExprVal::Array(vec![
+                        Expr::new(ExprVal::Int(1)),
+                        Expr::new(ExprVal::Bool(true)),
+                        Expr::new(ExprVal::String("hello".to_string())),
+                    ]),
+                    vec![FunctionCall { name: "length".to_string(), args: HashMap::new() },],
+                ),
+                global: false,
+            },
+        )
+    );
+}
+
+#[test]
+fn parse_set_global_tag() {
+    let ast = parse("{% set_global hello = utcnow() %}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::Set(
+            WS::default(),
+            Set {
+                key: "hello".to_string(),
+                value: Expr::new(ExprVal::FunctionCall(FunctionCall {
+                    name: "utcnow".to_string(),
+                    args: HashMap::new(),
+                },)),
+                global: true,
+            },
+        )
+    );
+}
+
+#[test]
+fn parse_raw_tag() {
+    let ast = parse("{% raw -%}{{hey}}{%- endraw %}").unwrap();
+    let mut start_ws = WS::default();
+    start_ws.right = true;
+    let mut end_ws = WS::default();
+    end_ws.left = true;
+
+    assert_eq!(ast[0], Node::Raw(start_ws, "{{hey}}".to_string(), end_ws));
+}
+
+// https://github.com/Keats/tera/issues/513
+#[test]
+fn parse_raw_tag_with_ws() {
+    // println!("{}", parse("{% raw %}    yaml_test:     {% endraw %}").unwrap_err());
+    let ast = parse("{% raw %}    yaml_test:     {% endraw %}").unwrap();
+    let start_ws = WS::default();
+    let end_ws = WS::default();
+
+    assert_eq!(ast[0], Node::Raw(start_ws, "    yaml_test:     ".to_string(), end_ws));
+}
+
+#[test]
+fn parse_filter_section_without_args() {
+    let ast = parse("{% filter upper -%}A{%- endfilter %}").unwrap();
+    let mut start_ws = WS::default();
+    start_ws.right = true;
+    let mut end_ws = WS::default();
+    end_ws.left = true;
+
+    assert_eq!(
+        ast[0],
+        Node::FilterSection(
+            start_ws,
+            FilterSection {
+                filter: FunctionCall { name: "upper".to_string(), args: HashMap::new() },
+                body: vec![Node::Text("A".to_string())],
+            },
+            end_ws,
+        )
+    );
+}
+
+#[test]
+fn parse_filter_section_with_args() {
+    let ast = parse("{% filter upper(attr=1) -%}A{%- endfilter %}").unwrap();
+    let mut start_ws = WS::default();
+    start_ws.right = true;
+    let mut end_ws = WS::default();
+    end_ws.left = true;
+
+    let mut args = HashMap::new();
+    args.insert("attr".to_string(), Expr::new(ExprVal::Int(1)));
+
+    assert_eq!(
+        ast[0],
+        Node::FilterSection(
+            start_ws,
+            FilterSection {
+                filter: FunctionCall { name: "upper".to_string(), args },
+                body: vec![Node::Text("A".to_string())],
+            },
+            end_ws,
+        )
+    );
+}
+
+#[test]
+fn parse_filter_section_preserves_ws() {
+    let ast = parse("{% filter upper %}  {{a}}  B  {% endfilter %}").unwrap();
+
+    assert_eq!(
+        ast[0],
+        Node::FilterSection(
+            WS::default(),
+            FilterSection {
+                filter: FunctionCall { name: "upper".to_string(), args: HashMap::new() },
+                body: vec![
+                    Node::Text("  ".to_string()),
+                    Node::VariableBlock(WS::default(), Expr::new(ExprVal::Ident("a".to_string()))),
+                    Node::Text("  B  ".to_string())
+                ]
+            },
+            WS::default(),
+        )
+    );
+}
+
+#[test]
+fn parse_block() {
+    let ast = parse("{% block hello %}{{super()}} hey{%- endblock hello %}").unwrap();
+    let start_ws = WS::default();
+    let mut end_ws = WS::default();
+    end_ws.left = true;
+
+    assert_eq!(
+        ast[0],
+        Node::Block(
+            start_ws,
+            Block {
+                name: "hello".to_string(),
+                body: vec![Node::Super, Node::Text(" hey".to_string())],
+            },
+            end_ws,
+        )
+    );
+}
+
+#[test]
+fn parse_simple_macro_definition() {
+    let ast = parse("{% macro hello(a=1, b='hello', c) %}A: {{a}}{% endmacro %}").unwrap();
+    let mut args = HashMap::new();
+    args.insert("a".to_string(), Some(Expr::new(ExprVal::Int(1))));
+    args.insert("b".to_string(), Some(Expr::new(ExprVal::String("hello".to_string()))));
+    args.insert("c".to_string(), None);
+
+    assert_eq!(
+        ast[0],
+        Node::MacroDefinition(
+            WS::default(),
+            MacroDefinition {
+                name: "hello".to_string(),
+                args,
+                body: vec![
+                    Node::Text("A: ".to_string()),
+                    Node::VariableBlock(WS::default(), Expr::new(ExprVal::Ident("a".to_string()))),
+                ],
+            },
+            WS::default(),
+        )
+    );
+}
+
+#[test]
+fn parse_value_forloop() {
+    let ast = parse("{% for item in items | reverse %}A{%- endfor %}").unwrap();
+    let start_ws = WS::default();
+    let mut end_ws = WS::default();
+    end_ws.left = true;
+
+    assert_eq!(
+        ast[0],
+        Node::Forloop(
+            start_ws,
+            Forloop {
+                key: None,
+                value: "item".to_string(),
+                container: Expr::with_filters(
+                    ExprVal::Ident("items".to_string()),
+                    vec![FunctionCall { name: "reverse".to_string(), args: HashMap::new() },],
+                ),
+                body: vec![Node::Text("A".to_string())],
+                empty_body: None,
+            },
+            end_ws,
+        )
+    );
+}
+
+#[test]
+fn parse_key_value_forloop() {
+    let ast = parse("{% for key, item in get_map() %}A{%- endfor %}").unwrap();
+    let start_ws = WS::default();
+    let mut end_ws = WS::default();
+    end_ws.left = true;
+
+    assert_eq!(
+        ast[0],
+        Node::Forloop(
+            start_ws,
+            Forloop {
+                key: Some("key".to_string()),
+                value: "item".to_string(),
+                container: Expr::new(ExprVal::FunctionCall(FunctionCall {
+                    name: "get_map".to_string(),
+                    args: HashMap::new(),
+                },)),
+                body: vec![Node::Text("A".to_string())],
+                empty_body: None,
+            },
+            end_ws,
+        )
+    );
+}
+
+#[test]
+fn parse_value_forloop_array() {
+    let ast = parse("{% for item in [1,2,] %}A{%- endfor %}").unwrap();
+    let start_ws = WS::default();
+    let mut end_ws = WS::default();
+    end_ws.left = true;
+
+    assert_eq!(
+        ast[0],
+        Node::Forloop(
+            start_ws,
+            Forloop {
+                key: None,
+                value: "item".to_string(),
+                container: Expr::new(ExprVal::Array(vec![
+                    Expr::new(ExprVal::Int(1)),
+                    Expr::new(ExprVal::Int(2)),
+                ])),
+                body: vec![Node::Text("A".to_string())],
+                empty_body: None,
+            },
+            end_ws,
+        )
+    );
+}
+
+#[test]
+fn parse_value_forloop_array_with_filter() {
+    let ast = parse("{% for item in [1,2,] | reverse %}A{%- endfor %}").unwrap();
+    let start_ws = WS::default();
+    let mut end_ws = WS::default();
+    end_ws.left = true;
+
+    assert_eq!(
+        ast[0],
+        Node::Forloop(
+            start_ws,
+            Forloop {
+                key: None,
+                value: "item".to_string(),
+                container: Expr::with_filters(
+                    ExprVal::Array(vec![Expr::new(ExprVal::Int(1)), Expr::new(ExprVal::Int(2)),]),
+                    vec![FunctionCall { name: "reverse".to_string(), args: HashMap::new() },],
+                ),
+                body: vec![Node::Text("A".to_string())],
+                empty_body: None,
+            },
+            end_ws,
+        )
+    );
+}
+
+#[test]
+fn parse_value_forloop_empty() {
+    let ast = parse("{% for item in [1,2,] %}A{% else %}B{%- endfor %}").unwrap();
+    let start_ws = WS::default();
+    let mut end_ws = WS::default();
+    end_ws.left = true;
+
+    assert_eq!(
+        ast[0],
+        Node::Forloop(
+            start_ws,
+            Forloop {
+                key: None,
+                value: "item".to_string(),
+                container: Expr::new(ExprVal::Array(vec![
+                    Expr::new(ExprVal::Int(1)),
+                    Expr::new(ExprVal::Int(2)),
+                ])),
+                body: vec![Node::Text("A".to_string())],
+                empty_body: Some(vec![Node::Text("B".to_string())]),
+            },
+            end_ws,
+        )
+    );
+}
+
+#[test]
+fn parse_if() {
+    let ast = parse("{% if item or admin %}A {%- elif 1 > 2 %}B{% else -%} C{%- endif %}").unwrap();
+    let mut end_ws = WS::default();
+    end_ws.left = true;
+
+    let mut else_ws = WS::default();
+    else_ws.right = true;
+
+    assert_eq!(
+        ast[0],
+        Node::If(
+            If {
+                conditions: vec![
+                    (
+                        WS::default(),
+                        Expr::new(ExprVal::Logic(LogicExpr {
+                            lhs: Box::new(Expr::new(ExprVal::Ident("item".to_string()))),
+                            operator: LogicOperator::Or,
+                            rhs: Box::new(Expr::new(ExprVal::Ident("admin".to_string()))),
+                        })),
+                        vec![Node::Text("A ".to_string())],
+                    ),
+                    (
+                        end_ws.clone(),
+                        Expr::new(ExprVal::Logic(LogicExpr {
+                            lhs: Box::new(Expr::new(ExprVal::Int(1))),
+                            operator: LogicOperator::Gt,
+                            rhs: Box::new(Expr::new(ExprVal::Int(2))),
+                        })),
+                        vec![Node::Text("B".to_string())],
+                    ),
+                ],
+                otherwise: Some((else_ws, vec![Node::Text(" C".to_string())])),
+            },
+            end_ws,
+        )
+    );
+}
+
+#[test]
+fn parse_break() {
+    let ast = parse("{% for item in items %}{% break -%}{% endfor %}").unwrap();
+    let for_ws = WS::default();
+    assert_eq!(
+        ast[0],
+        Node::Forloop(
+            for_ws,
+            Forloop {
+                key: None,
+                value: "item".to_string(),
+                container: Expr::new(ExprVal::Ident("items".to_string())),
+                body: vec![Node::Break(WS { left: false, right: true }),],
+                empty_body: None,
+            },
+            for_ws,
+        )
+    );
+}
+
+#[test]
+fn parse_continue() {
+    let ast = parse("{% for item in items %}{% continue -%}{% endfor %}").unwrap();
+    let for_ws = WS::default();
+    assert_eq!(
+        ast[0],
+        Node::Forloop(
+            for_ws,
+            Forloop {
+                key: None,
+                value: "item".to_string(),
+                container: Expr::new(ExprVal::Ident("items".to_string())),
+                body: vec![Node::Continue(WS { left: false, right: true }),],
+                empty_body: None,
+            },
+            for_ws,
+        )
+    );
+}
+
+#[test]
+fn parse_string_concat_can_merge() {
+    let ast = parse("{{ `hello` ~ 'hey' }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(WS::default(), Expr::new(ExprVal::String("hellohey".to_string()))),
+    );
+}
+#[test]
+fn parse_string_concat() {
+    let ast = parse("{{ `hello` ~ ident }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::StringConcat(StringConcat {
+                values: vec![
+                    ExprVal::String("hello".to_string()),
+                    ExprVal::Ident("ident".to_string()),
+                ]
+            }))
+        ),
+    );
+}
+
+#[test]
+fn parse_string_concat_multiple() {
+    let ast = parse("{{ `hello` ~ ident ~ 'ho' }}").unwrap();
+    assert_eq!(
+        ast[0],
+        Node::VariableBlock(
+            WS::default(),
+            Expr::new(ExprVal::StringConcat(StringConcat {
+                values: vec![
+                    ExprVal::String("hello".to_string()),
+                    ExprVal::Ident("ident".to_string()),
+                    ExprVal::String("ho".to_string()),
+                ]
+            }))
+        ),
+    );
+}
diff --git a/vendor/tera/src/parser/tests/whitespace.rs b/vendor/tera/src/parser/tests/whitespace.rs
new file mode 100644 (file)
index 0000000..32b1f99
--- /dev/null
@@ -0,0 +1,264 @@
+use crate::parser::ast::*;
+use crate::parser::remove_whitespace;
+use std::collections::HashMap;
+
+#[test]
+fn do_nothing_if_unneeded() {
+    let ast = vec![Node::Text("hey ".to_string())];
+    assert_eq!(remove_whitespace(ast.clone(), None), ast);
+}
+
+#[test]
+fn remove_previous_ws_if_single_opening_tag_requires_it() {
+    let ws = WS { left: true, right: false };
+    let ast = vec![
+        Node::Text("hey ".to_string()),
+        Node::ImportMacro(ws, "hey ".to_string(), "ho".to_string()),
+    ];
+
+    assert_eq!(
+        remove_whitespace(ast.clone(), None),
+        vec![
+            Node::Text("hey".to_string()), // it removed the trailing space
+            Node::ImportMacro(ws, "hey ".to_string(), "ho".to_string()),
+        ]
+    );
+}
+
+#[test]
+fn remove_next_ws_if_single_opening_tag_requires_it() {
+    let ws = WS { left: true, right: true };
+    let ast = vec![
+        Node::ImportMacro(ws, "hey ".to_string(), "ho".to_string()),
+        Node::Text("  hey".to_string()),
+    ];
+
+    assert_eq!(
+        remove_whitespace(ast.clone(), None),
+        vec![
+            Node::ImportMacro(ws, "hey ".to_string(), "ho".to_string()),
+            Node::Text("hey".to_string()), // it removed the leading space
+        ]
+    );
+}
+
+#[test]
+fn handle_ws_both_sides_for_raw_tag() {
+    let start_ws = WS { left: true, right: false };
+    let end_ws = WS { left: true, right: true };
+    let ast =
+        vec![Node::Raw(start_ws, "  hey ".to_string(), end_ws), Node::Text("  hey".to_string())];
+
+    assert_eq!(
+        remove_whitespace(ast.clone(), None),
+        vec![
+            // it removed only the space at the end
+            Node::Raw(start_ws, "  hey".to_string(), end_ws),
+            Node::Text("hey".to_string()),
+        ]
+    );
+}
+
+#[test]
+fn handle_ws_both_sides_for_macro_definitions() {
+    let start_ws = WS { left: true, right: true };
+    let end_ws = WS { left: true, right: true };
+    let ast = vec![Node::MacroDefinition(
+        start_ws,
+        MacroDefinition {
+            name: "something".to_string(),
+            args: HashMap::new(),
+            body: vec![
+                Node::Text("\n  ".to_string()),
+                Node::Text("hey".to_string()),
+                Node::Text("  ".to_string()),
+            ],
+        },
+        end_ws,
+    )];
+
+    assert_eq!(
+        remove_whitespace(ast.clone(), None),
+        vec![Node::MacroDefinition(
+            start_ws,
+            MacroDefinition {
+                name: "something".to_string(),
+                args: HashMap::new(),
+                body: vec![Node::Text("hey".to_string())],
+            },
+            end_ws,
+        ),]
+    );
+}
+
+#[test]
+fn handle_ws_both_sides_for_forloop_tag_and_remove_empty_node() {
+    let start_ws = WS { left: true, right: true };
+    let end_ws = WS { left: true, right: true };
+    let ast = vec![
+        Node::Forloop(
+            start_ws,
+            Forloop {
+                key: None,
+                value: "item".to_string(),
+                container: Expr::new(ExprVal::Int(1)),
+                // not valid but we don't care about it here
+                body: vec![Node::Text("   ".to_string()), Node::Text("hey   ".to_string())],
+                empty_body: None,
+            },
+            end_ws,
+        ),
+        Node::Text("  hey".to_string()),
+    ];
+
+    assert_eq!(
+        remove_whitespace(ast.clone(), None),
+        vec![
+            Node::Forloop(
+                start_ws,
+                Forloop {
+                    key: None,
+                    value: "item".to_string(),
+                    container: Expr::new(ExprVal::Int(1)),
+                    // not valid but we don't care about it here
+                    body: vec![Node::Text("hey".to_string())],
+                    empty_body: None,
+                },
+                end_ws,
+            ),
+            Node::Text("hey".to_string()),
+        ]
+    );
+}
+
+#[test]
+fn handle_ws_for_if_nodes() {
+    let end_ws = WS { left: false, right: true };
+    let ast = vec![
+        Node::Text("C ".to_string()),
+        Node::If(
+            If {
+                conditions: vec![
+                    (
+                        WS { left: true, right: true },
+                        Expr::new(ExprVal::Int(1)),
+                        vec![Node::Text(" a ".to_string())],
+                    ),
+                    (
+                        WS { left: true, right: false },
+                        Expr::new(ExprVal::Int(1)),
+                        vec![Node::Text(" a ".to_string())],
+                    ),
+                    (
+                        WS { left: true, right: true },
+                        Expr::new(ExprVal::Int(1)),
+                        vec![Node::Text(" a ".to_string())],
+                    ),
+                ],
+                otherwise: None,
+            },
+            end_ws,
+        ),
+        Node::Text("  hey".to_string()),
+    ];
+
+    assert_eq!(
+        remove_whitespace(ast.clone(), None),
+        vec![
+            Node::Text("C".to_string()),
+            Node::If(
+                If {
+                    conditions: vec![
+                        (
+                            WS { left: true, right: true },
+                            Expr::new(ExprVal::Int(1)),
+                            vec![Node::Text("a".to_string())],
+                        ),
+                        (
+                            WS { left: true, right: false },
+                            Expr::new(ExprVal::Int(1)),
+                            vec![Node::Text(" a".to_string())],
+                        ),
+                        (
+                            WS { left: true, right: true },
+                            Expr::new(ExprVal::Int(1)),
+                            vec![Node::Text("a ".to_string())],
+                        ),
+                    ],
+                    otherwise: None,
+                },
+                end_ws,
+            ),
+            Node::Text("hey".to_string()),
+        ]
+    );
+}
+
+#[test]
+fn handle_ws_for_if_nodes_with_else() {
+    let end_ws = WS { left: true, right: true };
+    let ast = vec![
+        Node::Text("C ".to_string()),
+        Node::If(
+            If {
+                conditions: vec![
+                    (
+                        WS { left: true, right: true },
+                        Expr::new(ExprVal::Int(1)),
+                        vec![Node::Text(" a ".to_string())],
+                    ),
+                    (
+                        WS { left: true, right: false },
+                        Expr::new(ExprVal::Int(1)),
+                        vec![Node::Text(" a ".to_string())],
+                    ),
+                    (
+                        WS { left: true, right: true },
+                        Expr::new(ExprVal::Int(1)),
+                        vec![Node::Text(" a ".to_string())],
+                    ),
+                ],
+                otherwise: Some((
+                    WS { left: true, right: true },
+                    vec![Node::Text(" a ".to_string())],
+                )),
+            },
+            end_ws,
+        ),
+        Node::Text("  hey".to_string()),
+    ];
+
+    assert_eq!(
+        remove_whitespace(ast.clone(), None),
+        vec![
+            Node::Text("C".to_string()),
+            Node::If(
+                If {
+                    conditions: vec![
+                        (
+                            WS { left: true, right: true },
+                            Expr::new(ExprVal::Int(1)),
+                            vec![Node::Text("a".to_string())],
+                        ),
+                        (
+                            WS { left: true, right: false },
+                            Expr::new(ExprVal::Int(1)),
+                            vec![Node::Text(" a".to_string())],
+                        ),
+                        (
+                            WS { left: true, right: true },
+                            Expr::new(ExprVal::Int(1)),
+                            vec![Node::Text("a".to_string())],
+                        ),
+                    ],
+                    otherwise: Some((
+                        WS { left: true, right: true },
+                        vec![Node::Text("a".to_string())],
+                    )),
+                },
+                end_ws,
+            ),
+            Node::Text("hey".to_string()),
+        ]
+    );
+}
diff --git a/vendor/tera/src/parser/whitespace.rs b/vendor/tera/src/parser/whitespace.rs
new file mode 100644 (file)
index 0000000..1c7c54c
--- /dev/null
@@ -0,0 +1,188 @@
+use crate::parser::ast::*;
+
+macro_rules! trim_right_previous {
+    ($vec: expr) => {
+        if let Some(last) = $vec.pop() {
+            if let Node::Text(mut s) = last {
+                s = s.trim_end().to_string();
+                if !s.is_empty() {
+                    $vec.push(Node::Text(s));
+                }
+            } else {
+                $vec.push(last);
+            }
+        }
+    };
+    ($cond: expr, $vec: expr) => {
+        if $cond {
+            trim_right_previous!($vec);
+        }
+    };
+}
+
+/// Removes whitespace from the AST nodes according to the `{%-` and `-%}` defined in the template.
+/// Empty string nodes will be discarded.
+///
+/// The `ws` param is used when recursing through nested bodies to know whether to know
+/// how to handle the whitespace for that whole body:
+/// - set the initial `trim_left_next` to `ws.left`
+/// - trim last node if it is a text node if `ws.right == true`
+pub fn remove_whitespace(nodes: Vec<Node>, body_ws: Option<WS>) -> Vec<Node> {
+    let mut res = Vec::with_capacity(nodes.len());
+
+    // Whether the node we just added to res is a Text node
+    let mut previous_was_text = false;
+    // Whether the previous block ended wth `-%}` and we need to trim left the next text node
+    let mut trim_left_next = body_ws.map_or(false, |ws| ws.left);
+
+    for n in nodes {
+        match n {
+            Node::Text(s) => {
+                previous_was_text = true;
+
+                if !trim_left_next {
+                    res.push(Node::Text(s));
+                    continue;
+                }
+                trim_left_next = false;
+
+                let new_val = s.trim_start();
+                if !new_val.is_empty() {
+                    res.push(Node::Text(new_val.to_string()));
+                }
+                // empty text nodes will be skipped
+                continue;
+            }
+            Node::VariableBlock(ws, _)
+            | Node::ImportMacro(ws, _, _)
+            | Node::Extends(ws, _)
+            | Node::Include(ws, _, _)
+            | Node::Set(ws, _)
+            | Node::Break(ws)
+            | Node::Comment(ws, _)
+            | Node::Continue(ws) => {
+                trim_right_previous!(previous_was_text && ws.left, res);
+                trim_left_next = ws.right;
+            }
+            Node::Raw(start_ws, ref s, end_ws) => {
+                trim_right_previous!(previous_was_text && start_ws.left, res);
+                previous_was_text = false;
+                trim_left_next = end_ws.right;
+
+                if start_ws.right || end_ws.left {
+                    let val = if start_ws.right && end_ws.left {
+                        s.trim()
+                    } else if start_ws.right {
+                        s.trim_start()
+                    } else {
+                        s.trim_end()
+                    };
+
+                    res.push(Node::Raw(start_ws, val.to_string(), end_ws));
+                    continue;
+                }
+            }
+            // Those nodes have a body surrounded by 2 tags
+            Node::Forloop(start_ws, _, end_ws)
+            | Node::MacroDefinition(start_ws, _, end_ws)
+            | Node::FilterSection(start_ws, _, end_ws)
+            | Node::Block(start_ws, _, end_ws) => {
+                trim_right_previous!(previous_was_text && start_ws.left, res);
+                previous_was_text = false;
+                trim_left_next = end_ws.right;
+
+                // let's remove ws from the bodies now and append the cleaned up node
+                let body_ws = WS { left: start_ws.right, right: end_ws.left };
+                match n {
+                    Node::Forloop(_, mut forloop, _) => {
+                        forloop.body = remove_whitespace(forloop.body, Some(body_ws));
+                        res.push(Node::Forloop(start_ws, forloop, end_ws));
+                    }
+                    Node::MacroDefinition(_, mut macro_def, _) => {
+                        macro_def.body = remove_whitespace(macro_def.body, Some(body_ws));
+                        res.push(Node::MacroDefinition(start_ws, macro_def, end_ws));
+                    }
+                    Node::FilterSection(_, mut filter_section, _) => {
+                        filter_section.body = remove_whitespace(filter_section.body, Some(body_ws));
+                        res.push(Node::FilterSection(start_ws, filter_section, end_ws));
+                    }
+                    Node::Block(_, mut block, _) => {
+                        block.body = remove_whitespace(block.body, Some(body_ws));
+                        res.push(Node::Block(start_ws, block, end_ws));
+                    }
+                    _ => unreachable!(),
+                };
+                continue;
+            }
+            // The ugly one
+            Node::If(If { conditions, otherwise }, end_ws) => {
+                trim_left_next = end_ws.right;
+                let mut new_conditions: Vec<(_, _, Vec<_>)> = Vec::with_capacity(conditions.len());
+
+                for mut condition in conditions {
+                    if condition.0.left {
+                        // We need to trim the text node before the if tag
+                        if new_conditions.is_empty() && previous_was_text {
+                            trim_right_previous!(res);
+                        } else if let Some(&mut (_, _, ref mut body)) = new_conditions.last_mut() {
+                            trim_right_previous!(body);
+                        }
+                    }
+
+                    // we can't peek at the next one to know whether we need to trim right since
+                    // are consuming conditions. We'll find out at the next iteration.
+                    condition.2 = remove_whitespace(
+                        condition.2,
+                        Some(WS { left: condition.0.right, right: false }),
+                    );
+                    new_conditions.push(condition);
+                }
+
+                previous_was_text = false;
+
+                // We now need to look for the last potential `{%-` bit for if/elif
+
+                // That can be a `{%- else`
+                if let Some((else_ws, body)) = otherwise {
+                    if else_ws.left {
+                        if let Some(&mut (_, _, ref mut body)) = new_conditions.last_mut() {
+                            trim_right_previous!(body);
+                        }
+                    }
+                    let mut else_body =
+                        remove_whitespace(body, Some(WS { left: else_ws.right, right: false }));
+                    // if we have an `else`, the `endif` will affect the else node so we need to check
+                    if end_ws.left {
+                        trim_right_previous!(else_body);
+                    }
+                    res.push(Node::If(
+                        If { conditions: new_conditions, otherwise: Some((else_ws, else_body)) },
+                        end_ws,
+                    ));
+                    continue;
+                }
+
+                // Or `{%- endif`
+                if end_ws.left {
+                    if let Some(&mut (_, _, ref mut body)) = new_conditions.last_mut() {
+                        trim_right_previous!(true, body);
+                    }
+                }
+
+                res.push(Node::If(If { conditions: new_conditions, otherwise }, end_ws));
+                continue;
+            }
+            Node::Super => (),
+        };
+
+        // If we are there, that means it's not a text node and we didn't have to modify the node
+        previous_was_text = false;
+        res.push(n);
+    }
+
+    if let Some(whitespace) = body_ws {
+        trim_right_previous!(whitespace.right, res);
+    }
+
+    res
+}
diff --git a/vendor/tera/src/renderer/call_stack.rs b/vendor/tera/src/renderer/call_stack.rs
new file mode 100644 (file)
index 0000000..11253a9
--- /dev/null
@@ -0,0 +1,234 @@
+use std::borrow::Cow;
+use std::collections::HashMap;
+
+use serde_json::{to_value, Value};
+
+use crate::context::get_json_pointer;
+use crate::errors::{Error, Result};
+use crate::renderer::for_loop::{ForLoop, ForLoopState};
+use crate::renderer::stack_frame::{FrameContext, FrameType, StackFrame, Val};
+use crate::template::Template;
+use crate::Context;
+
+/// Contains the user data and allows no mutation
+#[derive(Debug)]
+pub struct UserContext<'a> {
+    /// Read-only context
+    inner: &'a Context,
+}
+
+impl<'a> UserContext<'a> {
+    /// Create an immutable user context to be used in the call stack
+    pub fn new(context: &'a Context) -> Self {
+        UserContext { inner: context }
+    }
+
+    pub fn find_value(&self, key: &str) -> Option<&'a Value> {
+        self.inner.get(key)
+    }
+
+    pub fn find_value_by_pointer(&self, pointer: &str) -> Option<&'a Value> {
+        assert!(pointer.starts_with('/'));
+        let root = pointer.split('/').nth(1).unwrap().replace("~1", "/").replace("~0", "~");
+        let rest = &pointer[root.len() + 1..];
+        self.inner.get(&root).and_then(|val| val.pointer(rest))
+    }
+}
+
+/// Contains the stack of frames
+#[derive(Debug)]
+pub struct CallStack<'a> {
+    /// The stack of frames
+    stack: Vec<StackFrame<'a>>,
+    /// User supplied context for the render
+    context: UserContext<'a>,
+}
+
+impl<'a> CallStack<'a> {
+    /// Create the initial call stack
+    pub fn new(context: &'a Context, template: &'a Template) -> CallStack<'a> {
+        CallStack {
+            stack: vec![StackFrame::new(FrameType::Origin, "ORIGIN", template)],
+            context: UserContext::new(context),
+        }
+    }
+
+    pub fn push_for_loop_frame(&mut self, name: &'a str, for_loop: ForLoop<'a>) {
+        let tpl = self.stack.last().expect("Stack frame").active_template;
+        self.stack.push(StackFrame::new_for_loop(name, tpl, for_loop));
+    }
+
+    pub fn push_macro_frame(
+        &mut self,
+        namespace: &'a str,
+        name: &'a str,
+        context: FrameContext<'a>,
+        tpl: &'a Template,
+    ) {
+        self.stack.push(StackFrame::new_macro(name, tpl, namespace, context));
+    }
+
+    pub fn push_include_frame(&mut self, name: &'a str, tpl: &'a Template) {
+        self.stack.push(StackFrame::new_include(name, tpl));
+    }
+
+    /// Returns mutable reference to global `StackFrame`
+    /// i.e gets first stack outside current for loops
+    pub fn global_frame_mut(&mut self) -> &mut StackFrame<'a> {
+        if self.current_frame().kind == FrameType::ForLoop {
+            for stack_frame in self.stack.iter_mut().rev() {
+                // walk up the parent stacks until we meet the current template
+                if stack_frame.kind != FrameType::ForLoop {
+                    return stack_frame;
+                }
+            }
+            unreachable!("Global frame not found when trying to break out of for loop");
+        } else {
+            // Macro, Origin, or Include
+            self.current_frame_mut()
+        }
+    }
+
+    /// Returns mutable reference to current `StackFrame`
+    pub fn current_frame_mut(&mut self) -> &mut StackFrame<'a> {
+        self.stack.last_mut().expect("No current frame exists")
+    }
+
+    /// Returns immutable reference to current `StackFrame`
+    pub fn current_frame(&self) -> &StackFrame<'a> {
+        self.stack.last().expect("No current frame exists")
+    }
+
+    /// Pop the last frame
+    pub fn pop(&mut self) {
+        self.stack.pop().expect("Mistakenly popped Origin frame");
+    }
+
+    pub fn lookup(&self, key: &str) -> Option<Val<'a>> {
+        for stack_frame in self.stack.iter().rev() {
+            let found = stack_frame.find_value(key);
+            if found.is_some() {
+                return found;
+            }
+
+            // If we looked in a macro or origin frame, no point continuing
+            // Origin is the last one and macro frame don't have access to parent frames
+            if stack_frame.kind == FrameType::Macro || stack_frame.kind == FrameType::Origin {
+                break;
+            }
+        }
+
+        // Not in stack frame, look in user supplied context
+        if key.contains('.') {
+            return self
+                .context
+                .find_value_by_pointer(&get_json_pointer(key))
+                .map(|v| Cow::Borrowed(v));
+        } else if let Some(value) = self.context.find_value(key) {
+            return Some(Cow::Borrowed(value));
+        }
+
+        None
+    }
+
+    /// Add an assignment value (via {% set ... %} and {% set_global ... %} )
+    pub fn add_assignment(&mut self, key: &'a str, global: bool, value: Val<'a>) {
+        if global {
+            self.global_frame_mut().insert(key, value);
+        } else {
+            self.current_frame_mut().insert(key, value);
+        }
+    }
+
+    /// Breaks current for loop
+    pub fn break_for_loop(&mut self) -> Result<()> {
+        match self.current_frame_mut().for_loop {
+            Some(ref mut for_loop) => {
+                for_loop.break_loop();
+                Ok(())
+            }
+            None => Err(Error::msg("Attempted `break` while not in `for loop`")),
+        }
+    }
+
+    /// Continues current for loop
+    pub fn increment_for_loop(&mut self) -> Result<()> {
+        let frame = self.current_frame_mut();
+        frame.clear_context();
+        match frame.for_loop {
+            Some(ref mut for_loop) => {
+                for_loop.increment();
+                Ok(())
+            }
+            None => Err(Error::msg("Attempted `increment` while not in `for loop`")),
+        }
+    }
+
+    /// Continues current for loop
+    pub fn continue_for_loop(&mut self) -> Result<()> {
+        match self.current_frame_mut().for_loop {
+            Some(ref mut for_loop) => {
+                for_loop.continue_loop();
+                Ok(())
+            }
+            None => Err(Error::msg("Attempted `continue` while not in `for loop`")),
+        }
+    }
+
+    /// True if should break body, applicable to `break` and `continue`
+    pub fn should_break_body(&self) -> bool {
+        match self.current_frame().for_loop {
+            Some(ref for_loop) => {
+                for_loop.state == ForLoopState::Break || for_loop.state == ForLoopState::Continue
+            }
+            None => false,
+        }
+    }
+
+    /// True if should break loop, applicable to `break` only
+    pub fn should_break_for_loop(&self) -> bool {
+        match self.current_frame().for_loop {
+            Some(ref for_loop) => for_loop.state == ForLoopState::Break,
+            None => false,
+        }
+    }
+
+    /// Grab the current frame template
+    pub fn active_template(&self) -> &'a Template {
+        self.current_frame().active_template
+    }
+
+    pub fn current_context_cloned(&self) -> Value {
+        let mut context = HashMap::new();
+
+        // Go back the stack in reverse to see what we have access to
+        for frame in self.stack.iter().rev() {
+            context.extend(frame.context_owned());
+            if let Some(ref for_loop) = frame.for_loop {
+                context.insert(
+                    for_loop.value_name.to_string(),
+                    for_loop.get_current_value().into_owned(),
+                );
+                if for_loop.is_key_value() {
+                    context.insert(
+                        for_loop.key_name.clone().unwrap(),
+                        Value::String(for_loop.get_current_key()),
+                    );
+                }
+            }
+            // Macros don't have access to the user context, we're done
+            if frame.kind == FrameType::Macro {
+                return to_value(&context).unwrap();
+            }
+        }
+
+        // If we are here we take the user context
+        // and add the values found in the stack to it.
+        // We do it this way as we can override global variable temporarily in forloops
+        let mut new_ctx = self.context.inner.clone();
+        for (key, val) in context {
+            new_ctx.insert(key, &val)
+        }
+        new_ctx.into_json()
+    }
+}
diff --git a/vendor/tera/src/renderer/for_loop.rs b/vendor/tera/src/renderer/for_loop.rs
new file mode 100644 (file)
index 0000000..2bb6e88
--- /dev/null
@@ -0,0 +1,181 @@
+use std::borrow::Cow;
+
+use serde_json::Value;
+
+use crate::renderer::stack_frame::Val;
+
+/// Enumerates the two types of for loops
+#[derive(Debug, PartialEq)]
+pub enum ForLoopKind {
+    /// Loop over values, eg an `Array`
+    Value,
+    /// Loop over key value pairs, eg a `HashMap` or `Object` style iteration
+    KeyValue,
+}
+
+/// Enumerates the states of a for loop
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum ForLoopState {
+    /// State during iteration
+    Normal,
+    /// State on encountering *break* statement
+    Break,
+    /// State on encountering *continue* statement
+    Continue,
+}
+
+/// Enumerates on the two types of values to be iterated, scalars and pairs
+#[derive(Debug)]
+pub enum ForLoopValues<'a> {
+    /// Values for an array style iteration
+    Array(Val<'a>),
+    /// Values for an object style iteration
+    Object(Vec<(String, Val<'a>)>),
+}
+
+impl<'a> ForLoopValues<'a> {
+    pub fn current_key(&self, i: usize) -> String {
+        match *self {
+            ForLoopValues::Array(_) => unreachable!("No key in array list"),
+            ForLoopValues::Object(ref values) => {
+                values.get(i).expect("Failed getting current key").0.clone()
+            }
+        }
+    }
+    pub fn current_value(&self, i: usize) -> Val<'a> {
+        match *self {
+            ForLoopValues::Array(ref values) => match *values {
+                Cow::Borrowed(v) => {
+                    Cow::Borrowed(v.as_array().expect("Is array").get(i).expect("Value"))
+                }
+                Cow::Owned(_) => {
+                    Cow::Owned(values.as_array().expect("Is array").get(i).expect("Value").clone())
+                }
+            },
+            ForLoopValues::Object(ref values) => values.get(i).expect("Value").1.clone(),
+        }
+    }
+}
+
+// We need to have some data in the renderer for when we are in a ForLoop
+// For example, accessing the local variable would fail when
+// looking it up in the global context
+#[derive(Debug)]
+pub struct ForLoop<'a> {
+    /// The key name when iterate as a Key-Value, ie in `{% for i, person in people %}` it would be `i`
+    pub key_name: Option<String>,
+    /// The value name, ie in `{% for person in people %}` it would be `person`
+    pub value_name: String,
+    /// What's the current loop index (0-indexed)
+    pub current: usize,
+    /// A list of (key, value) for the forloop. The key is `None` for `ForLoopKind::Value`
+    pub values: ForLoopValues<'a>,
+    /// Value or KeyValue?
+    pub kind: ForLoopKind,
+    /// Has the for loop encountered break or continue?
+    pub state: ForLoopState,
+}
+
+impl<'a> ForLoop<'a> {
+    pub fn from_array(value_name: &str, values: Val<'a>) -> Self {
+        ForLoop {
+            key_name: None,
+            value_name: value_name.to_string(),
+            current: 0,
+            values: ForLoopValues::Array(values),
+            kind: ForLoopKind::Value,
+            state: ForLoopState::Normal,
+        }
+    }
+
+    pub fn from_object(key_name: &str, value_name: &str, object: &'a Value) -> Self {
+        let object_values = object.as_object().unwrap();
+        let mut values = Vec::with_capacity(object_values.len());
+        for (k, v) in object_values {
+            values.push((k.to_string(), Cow::Borrowed(v)));
+        }
+
+        ForLoop {
+            key_name: Some(key_name.to_string()),
+            value_name: value_name.to_string(),
+            current: 0,
+            values: ForLoopValues::Object(values),
+            kind: ForLoopKind::KeyValue,
+            state: ForLoopState::Normal,
+        }
+    }
+
+    pub fn from_object_owned(key_name: &str, value_name: &str, object: Value) -> Self {
+        let object_values = match object {
+            Value::Object(c) => c,
+            _ => unreachable!(
+                "Tried to create a Forloop from an object owned but it wasn't an object"
+            ),
+        };
+        let mut values = Vec::with_capacity(object_values.len());
+        for (k, v) in object_values {
+            values.push((k.to_string(), Cow::Owned(v)));
+        }
+
+        ForLoop {
+            key_name: Some(key_name.to_string()),
+            value_name: value_name.to_string(),
+            current: 0,
+            values: ForLoopValues::Object(values),
+            kind: ForLoopKind::KeyValue,
+            state: ForLoopState::Normal,
+        }
+    }
+
+    #[inline]
+    pub fn increment(&mut self) {
+        self.current += 1;
+        self.state = ForLoopState::Normal;
+    }
+
+    pub fn is_key_value(&self) -> bool {
+        self.kind == ForLoopKind::KeyValue
+    }
+
+    #[inline]
+    pub fn break_loop(&mut self) {
+        self.state = ForLoopState::Break;
+    }
+
+    #[inline]
+    pub fn continue_loop(&mut self) {
+        self.state = ForLoopState::Continue;
+    }
+
+    #[inline]
+    pub fn get_current_value(&self) -> Val<'a> {
+        self.values.current_value(self.current)
+    }
+
+    /// Only called in `ForLoopKind::KeyValue`
+    #[inline]
+    pub fn get_current_key(&self) -> String {
+        self.values.current_key(self.current)
+    }
+
+    /// Checks whether the key string given is the variable used as key for
+    /// the current forloop
+    pub fn is_key(&self, name: &str) -> bool {
+        if self.kind == ForLoopKind::Value {
+            return false;
+        }
+
+        if let Some(ref key_name) = self.key_name {
+            return key_name == name;
+        }
+
+        false
+    }
+
+    pub fn len(&self) -> usize {
+        match self.values {
+            ForLoopValues::Array(ref values) => values.as_array().expect("Value is array").len(),
+            ForLoopValues::Object(ref values) => values.len(),
+        }
+    }
+}
diff --git a/vendor/tera/src/renderer/macros.rs b/vendor/tera/src/renderer/macros.rs
new file mode 100644 (file)
index 0000000..5affafa
--- /dev/null
@@ -0,0 +1,119 @@
+use crate::errors::{Error, Result};
+use crate::parser::ast::MacroDefinition;
+use crate::template::Template;
+use crate::tera::Tera;
+use std::collections::HashMap;
+
+// Types around Macros get complicated, simplify it a bit by using aliases
+
+/// Maps { macro => macro_definition }
+pub type MacroDefinitionMap = HashMap<String, MacroDefinition>;
+/// Maps { namespace => ( macro_template, { macro => macro_definition }) }
+pub type MacroNamespaceMap<'a> = HashMap<&'a str, (&'a str, &'a MacroDefinitionMap)>;
+/// Maps { template => { namespace => ( macro_template, { macro => macro_definition }) }
+pub type MacroTemplateMap<'a> = HashMap<&'a str, MacroNamespaceMap<'a>>;
+
+/// Collection of all macro templates by file
+#[derive(Clone, Debug, Default)]
+pub struct MacroCollection<'a> {
+    macros: MacroTemplateMap<'a>,
+}
+
+impl<'a> MacroCollection<'a> {
+    pub fn from_original_template(tpl: &'a Template, tera: &'a Tera) -> MacroCollection<'a> {
+        let mut macro_collection = MacroCollection { macros: MacroTemplateMap::new() };
+
+        macro_collection
+            .add_macros_from_template(tera, tpl)
+            .expect("Couldn't load macros from base template");
+
+        macro_collection
+    }
+
+    /// Add macros from parsed template to `MacroCollection`
+    ///
+    /// Macro templates can import other macro templates so the macro loading needs to
+    /// happen recursively. We need all of the macros loaded in one go to be in the same
+    /// HashMap for easy popping as well, otherwise there could be stray macro
+    /// definitions remaining
+    pub fn add_macros_from_template(
+        &mut self,
+        tera: &'a Tera,
+        template: &'a Template,
+    ) -> Result<()> {
+        let template_name = &template.name[..];
+        if self.macros.contains_key(template_name) {
+            return Ok(());
+        }
+
+        let mut macro_namespace_map = MacroNamespaceMap::new();
+
+        if !template.macros.is_empty() {
+            macro_namespace_map.insert("self", (template_name, &template.macros));
+        }
+
+        for &(ref filename, ref namespace) in &template.imported_macro_files {
+            let macro_tpl = tera.get_template(filename)?;
+            macro_namespace_map.insert(namespace, (filename, &macro_tpl.macros));
+            self.add_macros_from_template(tera, macro_tpl)?;
+
+            // We need to load the macros loaded in our macros in our namespace as well, unless we override it
+            for (namespace, m) in &self.macros[&macro_tpl.name.as_ref()].clone() {
+                if macro_namespace_map.contains_key(namespace) {
+                    continue;
+                }
+                // We inserted before so we're safe
+                macro_namespace_map.insert(namespace, *m);
+            }
+        }
+
+        self.macros.insert(template_name, macro_namespace_map);
+
+        for parent in &template.parents {
+            let parent = &parent[..];
+            let parent_template = tera.get_template(parent)?;
+            self.add_macros_from_template(tera, parent_template)?;
+
+            // We need to load the parent macros in our namespace as well, unless we override it
+            for (namespace, m) in &self.macros[parent].clone() {
+                if self.macros[template_name].contains_key(namespace) {
+                    continue;
+                }
+                // We inserted before so we're safe
+                self.macros.get_mut(template_name).unwrap().insert(namespace, *m);
+            }
+        }
+
+        Ok(())
+    }
+
+    pub fn lookup_macro(
+        &self,
+        template_name: &'a str,
+        macro_namespace: &'a str,
+        macro_name: &'a str,
+    ) -> Result<(&'a str, &'a MacroDefinition)> {
+        let namespace = self
+            .macros
+            .get(template_name)
+            .and_then(|namespace_map| namespace_map.get(macro_namespace));
+
+        if let Some(n) = namespace {
+            let &(macro_template, macro_definition_map) = n;
+
+            if let Some(m) = macro_definition_map.get(macro_name).map(|md| (macro_template, md)) {
+                Ok(m)
+            } else {
+                Err(Error::msg(format!(
+                    "Macro `{}::{}` not found in template `{}`",
+                    macro_namespace, macro_name, template_name
+                )))
+            }
+        } else {
+            Err(Error::msg(format!(
+                "Macro namespace `{}` was not found in template `{}`. Have you maybe forgotten to import it, or misspelled it?",
+                macro_namespace, template_name
+            )))
+        }
+    }
+}
diff --git a/vendor/tera/src/renderer/mod.rs b/vendor/tera/src/renderer/mod.rs
new file mode 100644 (file)
index 0000000..d49cf4b
--- /dev/null
@@ -0,0 +1,62 @@
+mod square_brackets;
+#[cfg(test)]
+mod tests;
+
+mod call_stack;
+mod for_loop;
+mod macros;
+mod processor;
+mod stack_frame;
+
+use std::io::Write;
+
+use self::processor::Processor;
+use crate::errors::Result;
+use crate::template::Template;
+use crate::tera::Tera;
+use crate::utils::buffer_to_string;
+use crate::Context;
+
+/// Given a `Tera` and reference to `Template` and a `Context`, renders text
+#[derive(Debug)]
+pub struct Renderer<'a> {
+    /// Template to render
+    template: &'a Template,
+    /// Houses other templates, filters, global functions, etc
+    tera: &'a Tera,
+    /// Read-only context to be bound to template˝
+    context: &'a Context,
+    /// If set rendering should be escaped
+    should_escape: bool,
+}
+
+impl<'a> Renderer<'a> {
+    /// Create a new `Renderer`
+    #[inline]
+    pub fn new(template: &'a Template, tera: &'a Tera, context: &'a Context) -> Renderer<'a> {
+        let should_escape = tera.autoescape_suffixes.iter().any(|ext| {
+            // We prefer a `path` if set, otherwise use the `name`
+            if let Some(ref p) = template.path {
+                return p.ends_with(ext);
+            }
+            template.name.ends_with(ext)
+        });
+
+        Renderer { template, tera, context, should_escape }
+    }
+
+    /// Combines the context with the Template to generate the end result
+    pub fn render(&self) -> Result<String> {
+        let mut output = Vec::with_capacity(2000);
+        self.render_to(&mut output)?;
+        buffer_to_string(|| "converting rendered buffer to string".to_string(), output)
+    }
+
+    /// Combines the context with the Template to write the end result to output
+    pub fn render_to(&self, mut output: impl Write) -> Result<()> {
+        let mut processor =
+            Processor::new(self.template, self.tera, &self.context, self.should_escape);
+
+        processor.render(&mut output)
+    }
+}
diff --git a/vendor/tera/src/renderer/processor.rs b/vendor/tera/src/renderer/processor.rs
new file mode 100644 (file)
index 0000000..100be2d
--- /dev/null
@@ -0,0 +1,1060 @@
+use std::borrow::Cow;
+use std::collections::HashMap;
+use std::io::Write;
+
+use serde_json::{to_string_pretty, to_value, Number, Value};
+
+use crate::context::{ValueRender, ValueTruthy};
+use crate::errors::{Error, Result};
+use crate::parser::ast::*;
+use crate::renderer::call_stack::CallStack;
+use crate::renderer::for_loop::ForLoop;
+use crate::renderer::macros::MacroCollection;
+use crate::renderer::square_brackets::pull_out_square_bracket;
+use crate::renderer::stack_frame::{FrameContext, FrameType, Val};
+use crate::template::Template;
+use crate::tera::Tera;
+use crate::utils::render_to_string;
+use crate::Context;
+
+/// Special string indicating request to dump context
+static MAGICAL_DUMP_VAR: &str = "__tera_context";
+
+/// This will convert a Tera variable to a json pointer if it is possible by replacing
+/// the index with their evaluated stringified value
+fn evaluate_sub_variables<'a>(key: &str, call_stack: &CallStack<'a>) -> Result<String> {
+    let sub_vars_to_calc = pull_out_square_bracket(key);
+    let mut new_key = key.to_string();
+
+    for sub_var in &sub_vars_to_calc {
+        // Translate from variable name to variable value
+        match process_path(sub_var.as_ref(), call_stack) {
+            Err(e) => {
+                return Err(Error::msg(format!(
+                    "Variable {} can not be evaluated because: {}",
+                    key, e
+                )));
+            }
+            Ok(post_var) => {
+                let post_var_as_str = match *post_var {
+                    Value::String(ref s) => s.to_string(),
+                    Value::Number(ref n) => n.to_string(),
+                    _ => {
+                        return Err(Error::msg(format!(
+                            "Only variables evaluating to String or Number can be used as \
+                             index (`{}` of `{}`)",
+                            sub_var, key,
+                        )));
+                    }
+                };
+
+                // Rebuild the original key String replacing variable name with value
+                let nk = new_key.clone();
+                let divider = "[".to_string() + sub_var + "]";
+                let mut the_parts = nk.splitn(2, divider.as_str());
+
+                new_key = the_parts.next().unwrap().to_string()
+                    + "."
+                    + post_var_as_str.as_ref()
+                    + the_parts.next().unwrap_or("");
+            }
+        }
+    }
+
+    Ok(new_key
+        .replace("/", "~1") // https://tools.ietf.org/html/rfc6901#section-3
+        .replace("['", ".\"")
+        .replace("[\"", ".\"")
+        .replace("[", ".")
+        .replace("']", "\"")
+        .replace("\"]", "\"")
+        .replace("]", ""))
+}
+
+fn process_path<'a>(path: &str, call_stack: &CallStack<'a>) -> Result<Val<'a>> {
+    if !path.contains('[') {
+        match call_stack.lookup(path) {
+            Some(v) => Ok(v),
+            None => Err(Error::msg(format!(
+                "Variable `{}` not found in context while rendering '{}'",
+                path,
+                call_stack.active_template().name
+            ))),
+        }
+    } else {
+        let full_path = evaluate_sub_variables(path, call_stack)?;
+
+        match call_stack.lookup(full_path.as_ref()) {
+            Some(v) => Ok(v),
+            None => Err(Error::msg(format!(
+                "Variable `{}` not found in context while rendering '{}': \
+                 the evaluated version was `{}`. Maybe the index is out of bounds?",
+                path,
+                call_stack.active_template().name,
+                full_path,
+            ))),
+        }
+    }
+}
+
+/// Processes the ast and renders the output
+pub struct Processor<'a> {
+    /// The template we're trying to render
+    template: &'a Template,
+    /// Root template of template to render - contains ast to use for rendering
+    /// Can be the same as `template` if a template has no inheritance
+    template_root: &'a Template,
+    /// The Tera object with template details
+    tera: &'a Tera,
+    /// The call stack for processing
+    call_stack: CallStack<'a>,
+    /// The macros organised by template and namespaces
+    macros: MacroCollection<'a>,
+    /// If set, rendering should be escaped
+    should_escape: bool,
+    /// Used when super() is used in a block, to know where we are in our stack of
+    /// definitions and for which block
+    /// Vec<(block name, tpl_name, level)>
+    blocks: Vec<(&'a str, &'a str, usize)>,
+}
+
+impl<'a> Processor<'a> {
+    /// Create a new `Processor` that will do the rendering
+    pub fn new(
+        template: &'a Template,
+        tera: &'a Tera,
+        context: &'a Context,
+        should_escape: bool,
+    ) -> Self {
+        // Gets the root template if we are rendering something with inheritance or just return
+        // the template we're dealing with otherwise
+        let template_root = template
+            .parents
+            .last()
+            .map(|parent| tera.get_template(parent).unwrap())
+            .unwrap_or(template);
+
+        let call_stack = CallStack::new(&context, template);
+
+        Processor {
+            template,
+            template_root,
+            tera,
+            call_stack,
+            macros: MacroCollection::from_original_template(&template, &tera),
+            should_escape,
+            blocks: Vec::new(),
+        }
+    }
+
+    fn render_body(&mut self, body: &'a [Node], write: &mut impl Write) -> Result<()> {
+        for n in body {
+            self.render_node(n, write)?;
+
+            if self.call_stack.should_break_body() {
+                break;
+            }
+        }
+
+        Ok(())
+    }
+
+    fn render_for_loop(&mut self, for_loop: &'a Forloop, write: &mut impl Write) -> Result<()> {
+        let container_name = match for_loop.container.val {
+            ExprVal::Ident(ref ident) => ident,
+            ExprVal::FunctionCall(FunctionCall { ref name, .. }) => name,
+            ExprVal::Array(_) => "an array literal",
+            _ => return Err(Error::msg(format!(
+                "Forloop containers have to be an ident or a function call (tried to iterate on '{:?}')",
+                for_loop.container.val,
+            ))),
+        };
+
+        let for_loop_name = &for_loop.value;
+        let for_loop_body = &for_loop.body;
+        let for_loop_empty_body = &for_loop.empty_body;
+
+        let container_val = self.safe_eval_expression(&for_loop.container)?;
+
+        let for_loop = match *container_val {
+            Value::Array(_) => {
+                if for_loop.key.is_some() {
+                    return Err(Error::msg(format!(
+                        "Tried to iterate using key value on variable `{}`, but it isn't an object/map",
+                        container_name,
+                    )));
+                }
+                ForLoop::from_array(&for_loop.value, container_val)
+            }
+            Value::Object(_) => {
+                if for_loop.key.is_none() {
+                    return Err(Error::msg(format!(
+                        "Tried to iterate using key value on variable `{}`, but it is missing a key",
+                        container_name,
+                    )));
+                }
+                match container_val {
+                    Cow::Borrowed(c) => {
+                        ForLoop::from_object(&for_loop.key.as_ref().unwrap(), &for_loop.value, c)
+                    }
+                    Cow::Owned(c) => ForLoop::from_object_owned(
+                        &for_loop.key.as_ref().unwrap(),
+                        &for_loop.value,
+                        c,
+                    ),
+                }
+            }
+            _ => {
+                return Err(Error::msg(format!(
+                    "Tried to iterate on a container (`{}`) that has a unsupported type",
+                    container_name,
+                )));
+            }
+        };
+
+        let len = for_loop.len();
+        match (len, for_loop_empty_body) {
+            (0, Some(empty_body)) => self.render_body(&empty_body, write),
+            (0, _) => Ok(()),
+            (_, _) => {
+                self.call_stack.push_for_loop_frame(for_loop_name, for_loop);
+
+                for _ in 0..len {
+                    self.render_body(&for_loop_body, write)?;
+
+                    if self.call_stack.should_break_for_loop() {
+                        break;
+                    }
+
+                    self.call_stack.increment_for_loop()?;
+                }
+
+                self.call_stack.pop();
+
+                Ok(())
+            }
+        }
+    }
+
+    fn render_if_node(&mut self, if_node: &'a If, write: &mut impl Write) -> Result<()> {
+        for &(_, ref expr, ref body) in &if_node.conditions {
+            if self.eval_as_bool(expr)? {
+                return self.render_body(body, write);
+            }
+        }
+
+        if let Some((_, ref body)) = if_node.otherwise {
+            return self.render_body(body, write);
+        }
+
+        Ok(())
+    }
+
+    /// The way inheritance work is that the top parent will be rendered by the renderer so for blocks
+    /// we want to look from the bottom (`level = 0`, the template the user is actually rendering)
+    /// to the top (the base template).
+    fn render_block(
+        &mut self,
+        block: &'a Block,
+        level: usize,
+        write: &mut impl Write,
+    ) -> Result<()> {
+        let level_template = match level {
+            0 => self.call_stack.active_template(),
+            _ => self
+                .tera
+                .get_template(&self.call_stack.active_template().parents[level - 1])
+                .unwrap(),
+        };
+
+        let blocks_definitions = &level_template.blocks_definitions;
+
+        // Can we find this one block in these definitions? If so render it
+        if let Some(block_def) = blocks_definitions.get(&block.name) {
+            let (_, Block { ref body, .. }) = block_def[0];
+            self.blocks.push((&block.name[..], &level_template.name[..], level));
+            return self.render_body(body, write);
+        }
+
+        // Do we have more parents to look through?
+        if level < self.call_stack.active_template().parents.len() {
+            return self.render_block(block, level + 1, write);
+        }
+
+        // Nope, just render the body we got
+        self.render_body(&block.body, write)
+    }
+
+    fn get_default_value(&mut self, expr: &'a Expr) -> Result<Val<'a>> {
+        if let Some(default_expr) = expr.filters[0].args.get("value") {
+            self.eval_expression(default_expr)
+        } else {
+            Err(Error::msg("The `default` filter requires a `value` argument."))
+        }
+    }
+
+    fn eval_in_condition(&mut self, in_cond: &'a In) -> Result<bool> {
+        let lhs = self.eval_expression(&in_cond.lhs)?;
+        let rhs = self.eval_expression(&in_cond.rhs)?;
+
+        let present = match *rhs {
+            Value::Array(ref v) => v.contains(&lhs),
+            Value::String(ref s) => match *lhs {
+                Value::String(ref s2) => s.contains(s2),
+                _ => {
+                    return Err(Error::msg(format!(
+                        "Tried to check if {:?} is in a string, but it isn't a string",
+                        lhs
+                    )))
+                }
+            },
+            Value::Object(ref map) => match *lhs {
+                Value::String(ref s2) => map.contains_key(s2),
+                _ => {
+                    return Err(Error::msg(format!(
+                        "Tried to check if {:?} is in a object, but it isn't a string",
+                        lhs
+                    )))
+                }
+            },
+            _ => {
+                return Err(Error::msg(
+                    "The `in` operator only supports strings, arrays and objects.",
+                ))
+            }
+        };
+
+        Ok(if in_cond.negated { !present } else { present })
+    }
+
+    fn eval_expression(&mut self, expr: &'a Expr) -> Result<Val<'a>> {
+        let mut needs_escape = false;
+
+        let mut res = match expr.val {
+            ExprVal::Array(ref arr) => {
+                let mut values = vec![];
+                for v in arr {
+                    values.push(self.eval_expression(v)?.into_owned());
+                }
+                Cow::Owned(Value::Array(values))
+            }
+            ExprVal::In(ref in_cond) => Cow::Owned(Value::Bool(self.eval_in_condition(in_cond)?)),
+            ExprVal::String(ref val) => {
+                needs_escape = true;
+                Cow::Owned(Value::String(val.to_string()))
+            }
+            ExprVal::StringConcat(ref str_concat) => {
+                let mut res = String::new();
+                for s in &str_concat.values {
+                    match *s {
+                        ExprVal::String(ref v) => res.push_str(&v),
+                        ExprVal::Int(ref v) => res.push_str(&format!("{}", v)),
+                        ExprVal::Float(ref v) => res.push_str(&format!("{}", v)),
+                        ExprVal::Ident(ref i) => match *self.lookup_ident(i)? {
+                            Value::String(ref v) => res.push_str(&v),
+                            Value::Number(ref v) => res.push_str(&v.to_string()),
+                            _ => return Err(Error::msg(format!(
+                                "Tried to concat a value that is not a string or a number from ident {}",
+                                i
+                            ))),
+                        },
+                        ExprVal::FunctionCall(ref fn_call) => match *self.eval_tera_fn_call(fn_call, &mut needs_escape)? {
+                            Value::String(ref v) => res.push_str(&v),
+                            Value::Number(ref v) => res.push_str(&v.to_string()),
+                            _ => return Err(Error::msg(format!(
+                                "Tried to concat a value that is not a string or a number from function call {}",
+                                fn_call.name
+                            ))),
+                        },
+                        _ => unreachable!(),
+                    };
+                }
+
+                Cow::Owned(Value::String(res))
+            }
+            ExprVal::Int(val) => Cow::Owned(Value::Number(val.into())),
+            ExprVal::Float(val) => Cow::Owned(Value::Number(Number::from_f64(val).unwrap())),
+            ExprVal::Bool(val) => Cow::Owned(Value::Bool(val)),
+            ExprVal::Ident(ref ident) => {
+                needs_escape = ident != MAGICAL_DUMP_VAR;
+                // Negated idents are special cased as `not undefined_ident` should not
+                // error but instead be falsy values
+                match self.lookup_ident(ident) {
+                    Ok(val) => {
+                        if val.is_null() && expr.has_default_filter() {
+                            self.get_default_value(expr)?
+                        } else {
+                            val
+                        }
+                    }
+                    Err(e) => {
+                        if expr.has_default_filter() {
+                            self.get_default_value(expr)?
+                        } else {
+                            if !expr.negated {
+                                return Err(e);
+                            }
+                            // A negative undefined ident is !false so truthy
+                            return Ok(Cow::Owned(Value::Bool(true)));
+                        }
+                    }
+                }
+            }
+            ExprVal::FunctionCall(ref fn_call) => {
+                self.eval_tera_fn_call(fn_call, &mut needs_escape)?
+            }
+            ExprVal::MacroCall(ref macro_call) => {
+                let val = render_to_string(
+                    || format!("macro {}", macro_call.name),
+                    |w| self.eval_macro_call(macro_call, w),
+                )?;
+                Cow::Owned(Value::String(val))
+            }
+            ExprVal::Test(ref test) => Cow::Owned(Value::Bool(self.eval_test(test)?)),
+            ExprVal::Logic(_) => Cow::Owned(Value::Bool(self.eval_as_bool(expr)?)),
+            ExprVal::Math(_) => match self.eval_as_number(&expr.val) {
+                Ok(Some(n)) => Cow::Owned(Value::Number(n)),
+                Ok(None) => Cow::Owned(Value::String("NaN".to_owned())),
+                Err(e) => return Err(Error::msg(e)),
+            },
+        };
+
+        for filter in &expr.filters {
+            if filter.name == "safe" || filter.name == "default" {
+                continue;
+            }
+            res = self.eval_filter(&res, filter, &mut needs_escape)?;
+        }
+
+        // Lastly, we need to check if the expression is negated, thus turning it into a bool
+        if expr.negated {
+            return Ok(Cow::Owned(Value::Bool(!res.is_truthy())));
+        }
+
+        // Checks if it's a string and we need to escape it (if the last filter is `safe` we don't)
+        if self.should_escape && needs_escape && res.is_string() && !expr.is_marked_safe() {
+            res = Cow::Owned(
+                to_value(self.tera.get_escape_fn()(res.as_str().unwrap())).map_err(Error::json)?,
+            );
+        }
+
+        Ok(res)
+    }
+
+    /// Render an expression and never escape its result
+    fn safe_eval_expression(&mut self, expr: &'a Expr) -> Result<Val<'a>> {
+        let should_escape = self.should_escape;
+        self.should_escape = false;
+        let res = self.eval_expression(expr);
+        self.should_escape = should_escape;
+        res
+    }
+
+    /// Evaluate a set tag and add the value to the right context
+    fn eval_set(&mut self, set: &'a Set) -> Result<()> {
+        let assigned_value = self.safe_eval_expression(&set.value)?;
+        self.call_stack.add_assignment(&set.key[..], set.global, assigned_value);
+        Ok(())
+    }
+
+    fn eval_test(&mut self, test: &'a Test) -> Result<bool> {
+        let tester_fn = self.tera.get_tester(&test.name)?;
+        let err_wrap = |e| Error::call_test(&test.name, e);
+
+        let mut tester_args = vec![];
+        for arg in &test.args {
+            tester_args
+                .push(self.safe_eval_expression(arg).map_err(err_wrap)?.clone().into_owned());
+        }
+
+        let found = self.lookup_ident(&test.ident).map(|found| found.clone().into_owned()).ok();
+
+        let result = tester_fn.test(found.as_ref(), &tester_args).map_err(err_wrap)?;
+        if test.negated {
+            Ok(!result)
+        } else {
+            Ok(result)
+        }
+    }
+
+    fn eval_tera_fn_call(
+        &mut self,
+        function_call: &'a FunctionCall,
+        needs_escape: &mut bool,
+    ) -> Result<Val<'a>> {
+        let tera_fn = self.tera.get_function(&function_call.name)?;
+        *needs_escape = !tera_fn.is_safe();
+
+        let err_wrap = |e| Error::call_function(&function_call.name, e);
+
+        let mut args = HashMap::new();
+        for (arg_name, expr) in &function_call.args {
+            args.insert(
+                arg_name.to_string(),
+                self.safe_eval_expression(expr).map_err(err_wrap)?.clone().into_owned(),
+            );
+        }
+
+        Ok(Cow::Owned(tera_fn.call(&args).map_err(err_wrap)?))
+    }
+
+    fn eval_macro_call(&mut self, macro_call: &'a MacroCall, write: &mut impl Write) -> Result<()> {
+        let active_template_name = if let Some(block) = self.blocks.last() {
+            block.1
+        } else if self.template.name != self.template_root.name {
+            &self.template_root.name
+        } else {
+            &self.call_stack.active_template().name
+        };
+
+        let (macro_template_name, macro_definition) = self.macros.lookup_macro(
+            active_template_name,
+            &macro_call.namespace[..],
+            &macro_call.name[..],
+        )?;
+
+        let mut frame_context = FrameContext::with_capacity(macro_definition.args.len());
+
+        // First the default arguments
+        for (arg_name, default_value) in &macro_definition.args {
+            let value = match macro_call.args.get(arg_name) {
+                Some(val) => self.safe_eval_expression(val)?,
+                None => match *default_value {
+                    Some(ref val) => self.safe_eval_expression(val)?,
+                    None => {
+                        return Err(Error::msg(format!(
+                            "Macro `{}` is missing the argument `{}`",
+                            macro_call.name, arg_name
+                        )));
+                    }
+                },
+            };
+            frame_context.insert(&arg_name, value);
+        }
+
+        self.call_stack.push_macro_frame(
+            &macro_call.namespace,
+            &macro_call.name,
+            frame_context,
+            self.tera.get_template(macro_template_name)?,
+        );
+
+        self.render_body(&macro_definition.body, write)?;
+
+        self.call_stack.pop();
+
+        Ok(())
+    }
+
+    fn eval_filter(
+        &mut self,
+        value: &Val<'a>,
+        fn_call: &'a FunctionCall,
+        needs_escape: &mut bool,
+    ) -> Result<Val<'a>> {
+        let filter_fn = self.tera.get_filter(&fn_call.name)?;
+        *needs_escape = !filter_fn.is_safe();
+
+        let err_wrap = |e| Error::call_filter(&fn_call.name, e);
+
+        let mut args = HashMap::new();
+        for (arg_name, expr) in &fn_call.args {
+            args.insert(
+                arg_name.to_string(),
+                self.safe_eval_expression(expr).map_err(err_wrap)?.clone().into_owned(),
+            );
+        }
+
+        Ok(Cow::Owned(filter_fn.filter(&value, &args).map_err(err_wrap)?))
+    }
+
+    fn eval_as_bool(&mut self, bool_expr: &'a Expr) -> Result<bool> {
+        let res = match bool_expr.val {
+            ExprVal::Logic(LogicExpr { ref lhs, ref rhs, ref operator }) => {
+                match *operator {
+                    LogicOperator::Or => self.eval_as_bool(lhs)? || self.eval_as_bool(rhs)?,
+                    LogicOperator::And => self.eval_as_bool(lhs)? && self.eval_as_bool(rhs)?,
+                    LogicOperator::Gt
+                    | LogicOperator::Gte
+                    | LogicOperator::Lt
+                    | LogicOperator::Lte => {
+                        let l = self.eval_expr_as_number(lhs)?;
+                        let r = self.eval_expr_as_number(rhs)?;
+                        let (ll, rr) = match (l, r) {
+                            (Some(nl), Some(nr)) => (nl, nr),
+                            _ => return Err(Error::msg("Comparison to NaN")),
+                        };
+
+                        match *operator {
+                            LogicOperator::Gte => ll.as_f64().unwrap() >= rr.as_f64().unwrap(),
+                            LogicOperator::Gt => ll.as_f64().unwrap() > rr.as_f64().unwrap(),
+                            LogicOperator::Lte => ll.as_f64().unwrap() <= rr.as_f64().unwrap(),
+                            LogicOperator::Lt => ll.as_f64().unwrap() < rr.as_f64().unwrap(),
+                            _ => unreachable!(),
+                        }
+                    }
+                    LogicOperator::Eq | LogicOperator::NotEq => {
+                        let mut lhs_val = self.eval_expression(lhs)?;
+                        let mut rhs_val = self.eval_expression(rhs)?;
+
+                        // Monomorphize number vals.
+                        if lhs_val.is_number() || rhs_val.is_number() {
+                            // We're not implementing JS so can't compare things of different types
+                            if !lhs_val.is_number() || !rhs_val.is_number() {
+                                return Ok(false);
+                            }
+
+                            lhs_val = Cow::Owned(Value::Number(
+                                Number::from_f64(lhs_val.as_f64().unwrap()).unwrap(),
+                            ));
+                            rhs_val = Cow::Owned(Value::Number(
+                                Number::from_f64(rhs_val.as_f64().unwrap()).unwrap(),
+                            ));
+                        }
+
+                        match *operator {
+                            LogicOperator::Eq => *lhs_val == *rhs_val,
+                            LogicOperator::NotEq => *lhs_val != *rhs_val,
+                            _ => unreachable!(),
+                        }
+                    }
+                }
+            }
+            ExprVal::Ident(_) => {
+                let mut res = self
+                    .eval_expression(&bool_expr)
+                    .unwrap_or(Cow::Owned(Value::Bool(false)))
+                    .is_truthy();
+                if bool_expr.negated {
+                    res = !res;
+                }
+                res
+            }
+            ExprVal::Math(_) | ExprVal::Int(_) | ExprVal::Float(_) => {
+                match self.eval_as_number(&bool_expr.val)? {
+                    Some(n) => n.as_f64().unwrap() != 0.0,
+                    None => false,
+                }
+            }
+            ExprVal::In(ref in_cond) => self.eval_in_condition(&in_cond)?,
+            ExprVal::Test(ref test) => self.eval_test(test)?,
+            ExprVal::Bool(val) => val,
+            ExprVal::String(ref string) => !string.is_empty(),
+            ExprVal::FunctionCall(ref fn_call) => {
+                let v = self.eval_tera_fn_call(fn_call, &mut false)?;
+                match v.as_bool() {
+                    Some(val) => val,
+                    None => {
+                        return Err(Error::msg(format!(
+                            "Function `{}` was used in a logic operation but is not returning a bool",
+                            fn_call.name,
+                        )));
+                    }
+                }
+            }
+            ExprVal::StringConcat(_) => {
+                let res = self.eval_expression(bool_expr)?;
+                !res.as_str().unwrap().is_empty()
+            }
+            ExprVal::MacroCall(ref macro_call) => {
+                let mut buf = Vec::new();
+                self.eval_macro_call(&macro_call, &mut buf)?;
+                !buf.is_empty()
+            }
+            _ => unreachable!("unimplemented logic operation for {:?}", bool_expr),
+        };
+
+        if bool_expr.negated {
+            return Ok(!res);
+        }
+
+        Ok(res)
+    }
+
+    /// In some cases, we will have filters in lhs/rhs of a math expression
+    /// `eval_as_number` only works on ExprVal rather than Expr
+    fn eval_expr_as_number(&mut self, expr: &'a Expr) -> Result<Option<Number>> {
+        if !expr.filters.is_empty() {
+            match *self.eval_expression(expr)? {
+                Value::Number(ref s) => Ok(Some(s.clone())),
+                _ => {
+                    Err(Error::msg("Tried to do math with an expression not resulting in a number"))
+                }
+            }
+        } else {
+            self.eval_as_number(&expr.val)
+        }
+    }
+
+    /// Return the value of an expression as a number
+    fn eval_as_number(&mut self, expr: &'a ExprVal) -> Result<Option<Number>> {
+        let result = match *expr {
+            ExprVal::Ident(ref ident) => {
+                let v = &*self.lookup_ident(ident)?;
+                if v.is_i64() {
+                    Some(Number::from(v.as_i64().unwrap()))
+                } else if v.is_u64() {
+                    Some(Number::from(v.as_u64().unwrap()))
+                } else if v.is_f64() {
+                    Some(Number::from_f64(v.as_f64().unwrap()).unwrap())
+                } else {
+                    return Err(Error::msg(format!(
+                        "Variable `{}` was used in a math operation but is not a number",
+                        ident
+                    )));
+                }
+            }
+            ExprVal::Int(val) => Some(Number::from(val)),
+            ExprVal::Float(val) => Some(Number::from_f64(val).unwrap()),
+            ExprVal::Math(MathExpr { ref lhs, ref rhs, ref operator }) => {
+                let (l, r) = match (self.eval_expr_as_number(lhs)?, self.eval_expr_as_number(rhs)?)
+                {
+                    (Some(l), Some(r)) => (l, r),
+                    _ => return Ok(None),
+                };
+
+                match *operator {
+                    MathOperator::Mul => {
+                        if l.is_i64() && r.is_i64() {
+                            let ll = l.as_i64().unwrap();
+                            let rr = r.as_i64().unwrap();
+                            let res = match ll.checked_mul(rr) {
+                                Some(s) => s,
+                                None => {
+                                    return Err(Error::msg(format!(
+                                        "{} x {} results in an out of bounds i64",
+                                        ll, rr
+                                    )));
+                                }
+                            };
+
+                            Some(Number::from(res))
+                        } else if l.is_u64() && r.is_u64() {
+                            let ll = l.as_u64().unwrap();
+                            let rr = r.as_u64().unwrap();
+                            let res = match ll.checked_mul(rr) {
+                                Some(s) => s,
+                                None => {
+                                    return Err(Error::msg(format!(
+                                        "{} x {} results in an out of bounds u64",
+                                        ll, rr
+                                    )));
+                                }
+                            };
+                            Some(Number::from(res))
+                        } else {
+                            let ll = l.as_f64().unwrap();
+                            let rr = r.as_f64().unwrap();
+                            Number::from_f64(ll * rr)
+                        }
+                    }
+                    MathOperator::Div => {
+                        let ll = l.as_f64().unwrap();
+                        let rr = r.as_f64().unwrap();
+                        let res = ll / rr;
+                        if res.is_nan() {
+                            None
+                        } else {
+                            Number::from_f64(res)
+                        }
+                    }
+                    MathOperator::Add => {
+                        if l.is_i64() && r.is_i64() {
+                            let ll = l.as_i64().unwrap();
+                            let rr = r.as_i64().unwrap();
+                            let res = match ll.checked_add(rr) {
+                                Some(s) => s,
+                                None => {
+                                    return Err(Error::msg(format!(
+                                        "{} + {} results in an out of bounds i64",
+                                        ll, rr
+                                    )));
+                                }
+                            };
+                            Some(Number::from(res))
+                        } else if l.is_u64() && r.is_u64() {
+                            let ll = l.as_u64().unwrap();
+                            let rr = r.as_u64().unwrap();
+                            let res = match ll.checked_add(rr) {
+                                Some(s) => s,
+                                None => {
+                                    return Err(Error::msg(format!(
+                                        "{} + {} results in an out of bounds u64",
+                                        ll, rr
+                                    )));
+                                }
+                            };
+                            Some(Number::from(res))
+                        } else {
+                            let ll = l.as_f64().unwrap();
+                            let rr = r.as_f64().unwrap();
+                            Some(Number::from_f64(ll + rr).unwrap())
+                        }
+                    }
+                    MathOperator::Sub => {
+                        if l.is_i64() && r.is_i64() {
+                            let ll = l.as_i64().unwrap();
+                            let rr = r.as_i64().unwrap();
+                            let res = match ll.checked_sub(rr) {
+                                Some(s) => s,
+                                None => {
+                                    return Err(Error::msg(format!(
+                                        "{} - {} results in an out of bounds i64",
+                                        ll, rr
+                                    )));
+                                }
+                            };
+                            Some(Number::from(res))
+                        } else if l.is_u64() && r.is_u64() {
+                            let ll = l.as_u64().unwrap();
+                            let rr = r.as_u64().unwrap();
+                            let res = match ll.checked_sub(rr) {
+                                Some(s) => s,
+                                None => {
+                                    return Err(Error::msg(format!(
+                                        "{} - {} results in an out of bounds u64",
+                                        ll, rr
+                                    )));
+                                }
+                            };
+                            Some(Number::from(res))
+                        } else {
+                            let ll = l.as_f64().unwrap();
+                            let rr = r.as_f64().unwrap();
+                            Some(Number::from_f64(ll - rr).unwrap())
+                        }
+                    }
+                    MathOperator::Modulo => {
+                        if l.is_i64() && r.is_i64() {
+                            let ll = l.as_i64().unwrap();
+                            let rr = r.as_i64().unwrap();
+                            if rr == 0 {
+                                return Err(Error::msg(format!(
+                                    "Tried to do a modulo by zero: {:?}/{:?}",
+                                    lhs, rhs
+                                )));
+                            }
+                            Some(Number::from(ll % rr))
+                        } else if l.is_u64() && r.is_u64() {
+                            let ll = l.as_u64().unwrap();
+                            let rr = r.as_u64().unwrap();
+                            if rr == 0 {
+                                return Err(Error::msg(format!(
+                                    "Tried to do a modulo by zero: {:?}/{:?}",
+                                    lhs, rhs
+                                )));
+                            }
+                            Some(Number::from(ll % rr))
+                        } else {
+                            let ll = l.as_f64().unwrap();
+                            let rr = r.as_f64().unwrap();
+                            Number::from_f64(ll % rr)
+                        }
+                    }
+                }
+            }
+            ExprVal::FunctionCall(ref fn_call) => {
+                let v = self.eval_tera_fn_call(fn_call, &mut false)?;
+                if v.is_i64() {
+                    Some(Number::from(v.as_i64().unwrap()))
+                } else if v.is_u64() {
+                    Some(Number::from(v.as_u64().unwrap()))
+                } else if v.is_f64() {
+                    Some(Number::from_f64(v.as_f64().unwrap()).unwrap())
+                } else {
+                    return Err(Error::msg(format!(
+                        "Function `{}` was used in a math operation but is not returning a number",
+                        fn_call.name
+                    )));
+                }
+            }
+            ExprVal::String(ref val) => {
+                return Err(Error::msg(format!("Tried to do math with a string: `{}`", val)));
+            }
+            ExprVal::Bool(val) => {
+                return Err(Error::msg(format!("Tried to do math with a boolean: `{}`", val)));
+            }
+            ExprVal::StringConcat(ref val) => {
+                return Err(Error::msg(format!(
+                    "Tried to do math with a string concatenation: {}",
+                    val.to_template_string()
+                )));
+            }
+            ExprVal::Test(ref test) => {
+                return Err(Error::msg(format!("Tried to do math with a test: {}", test.name)));
+            }
+            _ => unreachable!("unimplemented math expression for {:?}", expr),
+        };
+
+        Ok(result)
+    }
+
+    /// Only called while rendering a block.
+    /// This will look up the block we are currently rendering and its level and try to render
+    /// the block at level + n, where would be the next template in the hierarchy the block is present
+    fn do_super(&mut self, write: &mut impl Write) -> Result<()> {
+        let &(block_name, _, level) = self.blocks.last().unwrap();
+        let mut next_level = level + 1;
+
+        while next_level <= self.template.parents.len() {
+            let blocks_definitions = &self
+                .tera
+                .get_template(&self.template.parents[next_level - 1])
+                .unwrap()
+                .blocks_definitions;
+
+            if let Some(block_def) = blocks_definitions.get(block_name) {
+                let (ref tpl_name, Block { ref body, .. }) = block_def[0];
+                self.blocks.push((block_name, tpl_name, next_level));
+
+                self.render_body(body, write)?;
+                self.blocks.pop();
+
+                // Can't go any higher for that block anymore?
+                if next_level >= self.template.parents.len() {
+                    // then remove it from the stack, we're done with it
+                    self.blocks.pop();
+                }
+                return Ok(());
+            } else {
+                next_level += 1;
+            }
+        }
+
+        Err(Error::msg("Tried to use super() in the top level block"))
+    }
+
+    /// Looks up identifier and returns its value
+    fn lookup_ident(&self, key: &str) -> Result<Val<'a>> {
+        // Magical variable that just dumps the context
+        if key == MAGICAL_DUMP_VAR {
+            // Unwraps are safe since we are dealing with things that are already Value
+            return Ok(Cow::Owned(
+                to_value(
+                    to_string_pretty(&self.call_stack.current_context_cloned().take()).unwrap(),
+                )
+                .unwrap(),
+            ));
+        }
+
+        process_path(key, &self.call_stack)
+    }
+
+    /// Process the given node, appending the string result to the buffer
+    /// if it is possible
+    fn render_node(&mut self, node: &'a Node, write: &mut impl Write) -> Result<()> {
+        match *node {
+            // Comments are ignored when rendering
+            Node::Comment(_, _) => (),
+            Node::Text(ref s) | Node::Raw(_, ref s, _) => write!(write, "{}", s)?,
+            Node::VariableBlock(_, ref expr) => self.eval_expression(expr)?.render(write)?,
+            Node::Set(_, ref set) => self.eval_set(set)?,
+            Node::FilterSection(_, FilterSection { ref filter, ref body }, _) => {
+                let body = render_to_string(
+                    || format!("filter {}", filter.name),
+                    |w| self.render_body(body, w),
+                )?;
+                // the safe filter doesn't actually exist
+                if filter.name == "safe" {
+                    write!(write, "{}", body)?;
+                } else {
+                    self.eval_filter(&Cow::Owned(Value::String(body)), filter, &mut false)?
+                        .render(write)?;
+                }
+            }
+            // Macros have been imported at the beginning
+            Node::ImportMacro(_, _, _) => (),
+            Node::If(ref if_node, _) => self.render_if_node(if_node, write)?,
+            Node::Forloop(_, ref forloop, _) => self.render_for_loop(forloop, write)?,
+            Node::Break(_) => {
+                self.call_stack.break_for_loop()?;
+            }
+            Node::Continue(_) => {
+                self.call_stack.continue_for_loop()?;
+            }
+            Node::Block(_, ref block, _) => self.render_block(block, 0, write)?,
+            Node::Super => self.do_super(write)?,
+            Node::Include(_, ref tpl_names, ignore_missing) => {
+                let mut found = false;
+                for tpl_name in tpl_names {
+                    let template = self.tera.get_template(tpl_name);
+                    if template.is_err() {
+                        continue;
+                    }
+                    let template = template.unwrap();
+                    self.macros.add_macros_from_template(&self.tera, template)?;
+                    self.call_stack.push_include_frame(tpl_name, template);
+                    self.render_body(&template.ast, write)?;
+                    self.call_stack.pop();
+                    found = true;
+                    break;
+                }
+                if !found && !ignore_missing {
+                    return Err(Error::template_not_found(
+                        vec!["[", &tpl_names.join(", "), "]"].join(""),
+                    ));
+                }
+            }
+            Node::Extends(_, ref name) => {
+                return Err(Error::msg(format!(
+                    "Inheritance in included templates is currently not supported: extended `{}`",
+                    name
+                )));
+            }
+            // TODO: make that a compile time error
+            Node::MacroDefinition(_, ref def, _) => {
+                return Err(Error::invalid_macro_def(&def.name));
+            }
+        };
+
+        Ok(())
+    }
+
+    /// Helper fn that tries to find the current context: are we in a macro? in a parent template?
+    /// in order to give the best possible error when getting an error when rendering a tpl
+    fn get_error_location(&self) -> String {
+        let mut error_location = format!("Failed to render '{}'", self.template.name);
+
+        // in a macro?
+        if self.call_stack.current_frame().kind == FrameType::Macro {
+            let frame = self.call_stack.current_frame();
+            error_location += &format!(
+                ": error while rendering macro `{}::{}`",
+                frame.macro_namespace.expect("Macro namespace"),
+                frame.name,
+            );
+        }
+
+        // which template are we in?
+        if let Some(&(ref name, ref _template, ref level)) = self.blocks.last() {
+            let block_def = self
+                .template
+                .blocks_definitions
+                .get(&(*name).to_string())
+                .and_then(|b| b.get(*level));
+
+            if let Some(&(ref tpl_name, _)) = block_def {
+                if tpl_name != &self.template.name {
+                    error_location += &format!(" (error happened in '{}').", tpl_name);
+                }
+            } else {
+                error_location += " (error happened in a parent template)";
+            }
+        } else if let Some(parent) = self.template.parents.last() {
+            // Error happened in the base template, outside of blocks
+            error_location += &format!(" (error happened in '{}').", parent);
+        }
+
+        error_location
+    }
+
+    /// Entry point for the rendering
+    pub fn render(&mut self, write: &mut impl Write) -> Result<()> {
+        for node in &self.template_root.ast {
+            self.render_node(node, write)
+                .map_err(|e| Error::chain(self.get_error_location(), e))?;
+        }
+
+        Ok(())
+    }
+}
diff --git a/vendor/tera/src/renderer/square_brackets.rs b/vendor/tera/src/renderer/square_brackets.rs
new file mode 100644 (file)
index 0000000..9f97f0d
--- /dev/null
@@ -0,0 +1,51 @@
+/// Return a Vec of all substrings contained in '[ ]'s
+/// Ignore quoted strings and integers.
+pub fn pull_out_square_bracket(s: &str) -> Vec<String> {
+    let mut chars = s.chars();
+    let mut results = vec![];
+    loop {
+        match chars.next() {
+            Some('[') => {
+                let c = chars.next().unwrap();
+                if c != '"' && c != '\'' {
+                    let mut inside_bracket = vec![c];
+                    let mut bracket_count = 1;
+                    loop {
+                        let c = chars.next();
+                        match c {
+                            Some(']') => bracket_count -= 1,
+                            Some('[') => bracket_count += 1,
+                            Some(_) => (),
+                            None => break,
+                        };
+                        if bracket_count == 0 {
+                            // Only store results which aren't numbers
+                            let sub: String = inside_bracket.into_iter().collect();
+                            if sub.parse::<usize>().is_err() {
+                                results.push(sub);
+                            }
+                            break;
+                        }
+                        inside_bracket.push(c.unwrap());
+                    }
+                }
+            }
+            None => break,
+            _ => (),
+        }
+    }
+    results
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn can_pull_out_square_bracket() {
+        assert_eq!(pull_out_square_bracket("hi"), Vec::<String>::new());
+        assert_eq!(pull_out_square_bracket("['hi']"), Vec::<String>::new());
+        assert_eq!(pull_out_square_bracket("[hi] a[0]"), vec!["hi"]);
+        assert_eq!(pull_out_square_bracket("hi [th[e]['r']e] [fish]"), vec!["th[e]['r']e", "fish"]);
+    }
+}
diff --git a/vendor/tera/src/renderer/stack_frame.rs b/vendor/tera/src/renderer/stack_frame.rs
new file mode 100644 (file)
index 0000000..aefcc35
--- /dev/null
@@ -0,0 +1,202 @@
+use std::borrow::Cow;
+use std::collections::HashMap;
+
+use serde_json::Value;
+
+use crate::context::get_json_pointer;
+use crate::renderer::for_loop::ForLoop;
+use crate::template::Template;
+
+pub type Val<'a> = Cow<'a, Value>;
+pub type FrameContext<'a> = HashMap<&'a str, Val<'a>>;
+
+/// Gets a value within a value by pointer, keeping lifetime
+#[inline]
+pub fn value_by_pointer<'a>(pointer: &str, val: &Val<'a>) -> Option<Val<'a>> {
+    match *val {
+        Cow::Borrowed(r) => r.pointer(&get_json_pointer(pointer)).map(|found| Cow::Borrowed(found)),
+        Cow::Owned(ref r) => {
+            r.pointer(&get_json_pointer(pointer)).map(|found| Cow::Owned(found.clone()))
+        }
+    }
+}
+
+/// Enumerates the types of stack frames
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum FrameType {
+    /// Original frame
+    Origin,
+    /// New frame for macro call
+    Macro,
+    /// New frame for for loop
+    ForLoop,
+    /// Include template
+    Include,
+}
+
+/// Entry in the stack frame
+#[derive(Debug)]
+pub struct StackFrame<'a> {
+    /// Type of stack frame
+    pub kind: FrameType,
+    /// Frame name for context/debugging
+    pub name: &'a str,
+    /// Assigned value (via {% set ... %}, {% for ... %}, {% namespace::macro(a=a, b=b) %})
+    ///
+    /// - {% set ... %} adds to current frame_context
+    /// - {% for ... %} builds frame_context before iteration
+    /// - {% namespace::macro(a=a, b=b)} builds frame_context before invocation
+    context: FrameContext<'a>,
+    /// Active template for frame
+    pub active_template: &'a Template,
+    /// `ForLoop` if frame is for a for loop
+    pub for_loop: Option<ForLoop<'a>>,
+    /// Macro namespace if MacroFrame
+    pub macro_namespace: Option<&'a str>,
+}
+
+impl<'a> StackFrame<'a> {
+    pub fn new(kind: FrameType, name: &'a str, tpl: &'a Template) -> Self {
+        StackFrame {
+            kind,
+            name,
+            context: FrameContext::new(),
+            active_template: tpl,
+            for_loop: None,
+            macro_namespace: None,
+        }
+    }
+
+    pub fn new_for_loop(name: &'a str, tpl: &'a Template, for_loop: ForLoop<'a>) -> Self {
+        StackFrame {
+            kind: FrameType::ForLoop,
+            name,
+            context: FrameContext::new(),
+            active_template: tpl,
+            for_loop: Some(for_loop),
+            macro_namespace: None,
+        }
+    }
+
+    pub fn new_macro(
+        name: &'a str,
+        tpl: &'a Template,
+        macro_namespace: &'a str,
+        context: FrameContext<'a>,
+    ) -> Self {
+        StackFrame {
+            kind: FrameType::Macro,
+            name,
+            context,
+            active_template: tpl,
+            for_loop: None,
+            macro_namespace: Some(macro_namespace),
+        }
+    }
+
+    pub fn new_include(name: &'a str, tpl: &'a Template) -> Self {
+        StackFrame {
+            kind: FrameType::Include,
+            name,
+            context: FrameContext::new(),
+            active_template: tpl,
+            for_loop: None,
+            macro_namespace: None,
+        }
+    }
+
+    /// Finds a value in the stack frame.
+    /// Looks first in `frame_context`, then compares to for_loop key_name and value_name.
+    pub fn find_value(&self, key: &str) -> Option<Val<'a>> {
+        self.find_value_in_frame(key).or_else(|| self.find_value_in_for_loop(key))
+    }
+
+    /// Finds a value in `frame_context`.
+    pub fn find_value_in_frame(&self, key: &str) -> Option<Val<'a>> {
+        if let Some(dot) = key.find('.') {
+            if dot < key.len() + 1 {
+                if let Some(found_value) =
+                    self.context.get(&key[0..dot]).map(|v| value_by_pointer(&key[dot + 1..], v))
+                {
+                    return found_value;
+                }
+            }
+        } else if let Some(found) = self.context.get(key) {
+            return Some(found.clone());
+        }
+
+        None
+    }
+    /// Finds a value in the `for_loop` if there is one
+    pub fn find_value_in_for_loop(&self, key: &str) -> Option<Val<'a>> {
+        if let Some(ref for_loop) = self.for_loop {
+            // 1st case: the variable is the key of a KeyValue for loop
+            if for_loop.is_key(key) {
+                return Some(Cow::Owned(Value::String(for_loop.get_current_key())));
+            }
+
+            let (real_key, tail) = if let Some(tail_pos) = key.find('.') {
+                (&key[..tail_pos], &key[tail_pos + 1..])
+            } else {
+                (key, "")
+            };
+
+            // 2nd case: one of Tera loop built-in variable
+            if real_key == "loop" {
+                match tail {
+                    "index" => {
+                        return Some(Cow::Owned(Value::Number((for_loop.current + 1).into())));
+                    }
+                    "index0" => {
+                        return Some(Cow::Owned(Value::Number(for_loop.current.into())));
+                    }
+                    "first" => {
+                        return Some(Cow::Owned(Value::Bool(for_loop.current == 0)));
+                    }
+                    "last" => {
+                        return Some(Cow::Owned(Value::Bool(
+                            for_loop.current == for_loop.len() - 1,
+                        )));
+                    }
+                    _ => return None,
+                };
+            }
+
+            // Last case: the variable is/starts with the value name of the for loop
+            // The `set` case will have been taken into account before
+            let v = for_loop.get_current_value();
+            // Exact match to the loop value and no tail
+            if key == for_loop.value_name {
+                return Some(v);
+            }
+
+            if real_key == for_loop.value_name && !tail.is_empty() {
+                return value_by_pointer(tail, &v);
+            }
+        }
+
+        None
+    }
+
+    /// Insert a value in the context
+    pub fn insert(&mut self, key: &'a str, value: Val<'a>) {
+        self.context.insert(key, value);
+    }
+
+    /// Context is cleared on each loop
+    pub fn clear_context(&mut self) {
+        if self.for_loop.is_some() {
+            self.context.clear();
+        }
+    }
+
+    pub fn context_owned(&self) -> HashMap<String, Value> {
+        let mut context = HashMap::new();
+
+        for (key, val) in &self.context {
+            context.insert((*key).to_string(), val.clone().into_owned());
+        }
+
+        context
+    }
+}
diff --git a/vendor/tera/src/renderer/tests/basic.rs b/vendor/tera/src/renderer/tests/basic.rs
new file mode 100644 (file)
index 0000000..d9e1b34
--- /dev/null
@@ -0,0 +1,972 @@
+use std::collections::{BTreeMap, HashMap};
+use std::error::Error;
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::Arc;
+
+use lazy_static::lazy_static;
+use serde_derive::Serialize;
+use serde_json::{json, Value};
+
+use crate::builtins::functions::Function;
+use crate::context::Context;
+use crate::errors::Result;
+use crate::tera::Tera;
+
+use super::Review;
+
+fn render_template(content: &str, context: &Context) -> Result<String> {
+    let mut tera = Tera::default();
+    tera.add_raw_template("hello.html", content).unwrap();
+    tera.register_function("get_number", |_: &HashMap<String, Value>| Ok(Value::Number(10.into())));
+    tera.register_function("get_true", |_: &HashMap<String, Value>| Ok(Value::Bool(true.into())));
+    tera.register_function("get_string", |_: &HashMap<String, Value>| {
+        Ok(Value::String("Hello".to_string()))
+    });
+
+    tera.render("hello.html", context)
+}
+
+#[test]
+fn render_simple_string() {
+    let result = render_template("<h1>Hello world</h1>", &Context::new());
+    assert_eq!(result.unwrap(), "<h1>Hello world</h1>".to_owned());
+}
+
+#[test]
+fn render_variable_block_lit_expr() {
+    let inputs = vec![
+        ("{{ 1 }}", "1"),
+        ("{{ 3.14 }}", "3.14"),
+        ("{{ \"hey\" }}", "hey"),
+        (r#"{{ "{{ hey }}" }}"#, "{{ hey }}"),
+        ("{{ true }}", "true"),
+        ("{{ false }}", "false"),
+        ("{{ false and true or true }}", "true"),
+        ("{{ 1 + 1 }}", "2"),
+        ("{{ 1 + 1.1 }}", "2.1"),
+        ("{{ 3 - 1 }}", "2"),
+        ("{{ 3 - 1.1 }}", "1.9"),
+        ("{{ 2 * 5 }}", "10"),
+        ("{{ 10 / 5 }}", "2"),
+        ("{{ 2.1 * 5 }}", "10.5"),
+        ("{{ 2.1 * 5.05 }}", "10.605"),
+        ("{{ 2 / 0.5 }}", "4"),
+        ("{{ 2.1 / 0.5 }}", "4.2"),
+        ("{{ 2 + 1 * 2 }}", "4"),
+        ("{{ (2 + 1) * 2 }}", "6"),
+        ("{{ 2 * 4 % 8 }}", "0"),
+        ("{{ 2.8 * 2 | round }}", "6"),
+        ("{{ 1 / 0 }}", "NaN"),
+        ("{{ true and 10 }}", "true"),
+        ("{{ true and not 10 }}", "false"),
+        ("{{ not true }}", "false"),
+        ("{{ [1, 2, 3] }}", "[1, 2, 3]"),
+    ];
+
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(render_template(input, &Context::new()).unwrap(), expected);
+    }
+}
+
+#[test]
+fn render_variable_block_ident() {
+    let mut context = Context::new();
+    context.insert("name", &"john");
+    context.insert("malicious", &"<html>");
+    context.insert("a", &2);
+    context.insert("b", &3);
+    context.insert("numbers", &vec![1, 2, 3]);
+    context.insert("tuple_list", &vec![(1, 2, 3), (1, 2, 3)]);
+    context.insert("review", &Review::new());
+    context.insert("with_newline", &"Animal Alphabets\nB is for Bee-Eater");
+
+    let inputs = vec![
+        ("{{ name }}", "john"),
+        ("{{ malicious }}", "&lt;html&gt;"),
+        ("{{ \"<html>\" }}", "&lt;html&gt;"),
+        ("{{ \" html \" | upper | trim }}", "HTML"),
+        ("{{ 'html' }}", "html"),
+        ("{{ `html` }}", "html"),
+        // https://github.com/Keats/tera/issues/273
+        (
+            r#"{{ 'hangar new "Will Smoth <will_s@example.com>"' | safe }}"#,
+            r#"hangar new "Will Smoth <will_s@example.com>""#,
+        ),
+        ("{{ malicious | safe }}", "<html>"),
+        ("{{ malicious | upper }}", "&lt;HTML&gt;"),
+        ("{{ malicious | upper | safe }}", "<HTML>"),
+        ("{{ malicious | safe | upper }}", "&lt;HTML&gt;"),
+        ("{{ review | length }}", "2"),
+        ("{{ review.paragraphs.1 }}", "B"),
+        ("{{ numbers }}", "[1, 2, 3]"),
+        ("{{ numbers.0 }}", "1"),
+        ("{{ tuple_list.1.1 }}", "2"),
+        ("{{ name and true }}", "true"),
+        ("{{ name | length }}", "4"),
+        ("{{ name is defined }}", "true"),
+        ("{{ not name is defined }}", "false"),
+        ("{{ name is not defined }}", "false"),
+        ("{{ not name is not defined }}", "true"),
+        ("{{ a is odd }}", "false"),
+        ("{{ a is odd or b is odd  }}", "true"),
+        ("{{ range(start=1, end=4) }}", "[1, 2, 3]"),
+        ("{{ a + b }}", "5"),
+        ("{{ a + 1.5 }}", "3.5"),
+        ("{{ 1 + 1 + 1 }}", "3"),
+        ("{{ 2 - 2 - 1 }}", "-1"),
+        ("{{ 1 - 1 + 1 }}", "1"),
+        ("{{ 1 + get_number() }}", "11"),
+        ("{{ get_number() + 1 }}", "11"),
+        ("{{ (1.9 + a) | round }}", "4"),
+        ("{{ 1.9 + a | round }}", "4"),
+        ("{{ numbers | length - 1 }}", "2"),
+        ("{{ 1.9 + a | round - 1 }}", "3"),
+        ("{{ 1.9 + a | round - 1.8 + a | round }}", "0"),
+        ("{{ 1.9 + a | round - 1.8 + a | round - 1 }}", "-1"),
+        // https://github.com/Keats/tera/issues/435
+        (
+            "{{ with_newline | replace(from='\n', to='<br>') | safe }}",
+            "Animal Alphabets<br>B is for Bee-Eater",
+        ),
+    ];
+
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(render_template(input, &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn render_variable_block_logic_expr() {
+    let mut context = Context::new();
+    context.insert("name", &"john");
+    context.insert("malicious", &"<html>");
+    context.insert("a", &2);
+    context.insert("b", &3);
+    context.insert("numbers", &vec![1, 2, 3]);
+    context.insert("tuple_list", &vec![(1, 2, 3), (1, 2, 3)]);
+    let mut hashmap = HashMap::new();
+    hashmap.insert("a", 1);
+    hashmap.insert("b", 10);
+    hashmap.insert("john", 100);
+    context.insert("object", &hashmap);
+
+    let inputs = vec![
+        ("{{ (1.9 + a) | round > 10 }}", "false"),
+        ("{{ (1.9 + a) | round > 10 or b > a }}", "true"),
+        ("{{ 1.9 + a | round == 4 and numbers | length == 3}}", "true"),
+        ("{{ numbers | length > 1 }}", "true"),
+        ("{{ numbers | length == 1 }}", "false"),
+        ("{{ numbers | length - 2 == 1 }}", "true"),
+        ("{{ not name }}", "false"),
+        ("{{ not true }}", "false"),
+        ("{{ not undefined }}", "true"),
+        ("{{ name == 'john' }}", "true"),
+        ("{{ name != 'john' }}", "false"),
+        ("{{ name == 'john' | capitalize }}", "false"),
+        ("{{ name != 'john' | capitalize }}", "true"),
+        ("{{ 1 in numbers }}", "true"),
+        ("{{ 1 not in numbers }}", "false"),
+        ("{{ 40 not in numbers }}", "true"),
+        ("{{ 'e' in 'hello' }}", "true"),
+        ("{{ 'e' not in 'hello' }}", "false"),
+        ("{{ 'x' not in 'hello' }}", "true"),
+        ("{{ name in 'hello john' }}", "true"),
+        ("{{ name not in 'hello john' }}", "false"),
+        ("{{ name not in 'hello' }}", "true"),
+        ("{{ name in ['bob', 2, 'john'] }}", "true"),
+        ("{{ a in ['bob', 2, 'john'] }}", "true"),
+        ("{{ 'n' in name }}", "true"),
+        ("{{ '<' in malicious }}", "true"),
+        ("{{ 'a' in object }}", "true"),
+        ("{{ name in object }}", "true"),
+    ];
+
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(render_template(input, &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn render_variable_block_autoescaping_disabled() {
+    let mut context = Context::new();
+    context.insert("name", &"john");
+    context.insert("malicious", &"<html>");
+
+    let inputs = vec![
+        ("{{ name }}", "john"),
+        ("{{ malicious }}", "<html>"),
+        ("{{ malicious | safe }}", "<html>"),
+        ("{{ malicious | upper }}", "<HTML>"),
+        ("{{ malicious | upper | safe }}", "<HTML>"),
+        ("{{ malicious | safe | upper }}", "<HTML>"),
+    ];
+
+    for (input, expected) in inputs {
+        let mut tera = Tera::default();
+        tera.add_raw_template("hello.sql", input).unwrap();
+        assert_eq!(tera.render("hello.sql", &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn comments_are_ignored() {
+    let inputs = vec![
+        ("Hello {# comment #}world", "Hello world"),
+        ("Hello {# comment {# nested #}world", "Hello world"),
+        ("My name {# was {{ name }} #}is No One.", "My name is No One."),
+    ];
+
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(render_template(input, &Context::new()).unwrap(), expected);
+    }
+}
+
+#[test]
+fn escaping_happens_at_the_end() {
+    let inputs = vec![
+        #[cfg(feature = "builtins")]
+        ("{{ url | urlencode | safe }}", "https%3A//www.example.org/apples-%26-oranges/"),
+        ("{{ '<html>' }}", "&lt;html&gt;"),
+        ("{{ '<html>' | safe }}", "<html>"),
+        ("{{ 'hello' | safe | replace(from='h', to='&') }}", "&amp;ello"),
+        ("{{ 'hello' | replace(from='h', to='&') | safe }}", "&ello"),
+    ];
+
+    for (input, expected) in inputs {
+        let mut context = Context::new();
+        context.insert("url", "https://www.example.org/apples-&-oranges/");
+        assert_eq!(render_template(input, &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn filter_args_are_not_escaped() {
+    let mut context = Context::new();
+    context.insert("my_var", &"hey");
+    context.insert("to", &"&");
+    let input = r#"{{ my_var | replace(from="h", to=to) }}"#;
+
+    assert_eq!(render_template(input, &context).unwrap(), "&amp;ey");
+}
+
+#[test]
+fn render_include_tag() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("world", "world"),
+        ("hello", "<h1>Hello {% include \"world\" %}</h1>"),
+    ])
+    .unwrap();
+    let result = tera.render("hello", &Context::new()).unwrap();
+    assert_eq!(result, "<h1>Hello world</h1>".to_owned());
+}
+
+#[test]
+fn render_include_array_tag() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("world", "world"),
+        ("hello", "<h1>Hello {% include [\"custom/world\", \"world\"] %}</h1>"),
+    ])
+    .unwrap();
+    let result = tera.render("hello", &Context::new()).unwrap();
+    assert_eq!(result, "<h1>Hello world</h1>".to_owned());
+
+    tera.add_raw_template("custom/world", "custom world").unwrap();
+    let result = tera.render("hello", &Context::new()).unwrap();
+    assert_eq!(result, "<h1>Hello custom world</h1>".to_owned());
+}
+
+#[test]
+fn render_include_tag_missing() {
+    let mut tera = Tera::default();
+    tera.add_raw_template("hello", "<h1>Hello {% include \"world\" %}</h1>").unwrap();
+    let result = tera.render("hello", &Context::new());
+    assert!(result.is_err());
+
+    let mut tera = Tera::default();
+    tera.add_raw_template("hello", "<h1>Hello {% include \"world\" ignore missing %}</h1>")
+        .unwrap();
+    let result = tera.render("hello", &Context::new()).unwrap();
+    assert_eq!(result, "<h1>Hello </h1>".to_owned());
+}
+
+#[test]
+fn can_set_variables_in_included_templates() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("world", r#"{% set a = "world" %}{{a}}"#),
+        ("hello", "<h1>Hello {% include \"world\" %}</h1>"),
+    ])
+    .unwrap();
+    let result = tera.render("hello", &Context::new()).unwrap();
+    assert_eq!(result, "<h1>Hello world</h1>".to_owned());
+}
+
+#[test]
+fn render_raw_tag() {
+    let inputs = vec![
+        ("{% raw %}hey{% endraw %}", "hey"),
+        ("{% raw %}{{hey}}{% endraw %}", "{{hey}}"),
+        ("{% raw %}{% if true %}{% endraw %}", "{% if true %}"),
+    ];
+
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(render_template(input, &Context::new()).unwrap(), expected);
+    }
+}
+
+#[test]
+fn add_set_values_in_context() {
+    let mut context = Context::new();
+    context.insert("my_var", &"hey");
+    context.insert("malicious", &"<html>");
+    context.insert("admin", &true);
+    context.insert("num", &1);
+
+    let inputs = vec![
+        ("{% set i = 1 %}{{ i }}", "1"),
+        ("{% set i = 1 + 2 %}{{ i }}", "3"),
+        (r#"{% set i = "hey" %}{{ i }}"#, "hey"),
+        (r#"{% set i = "<html>" %}{{ i | safe }}"#, "<html>"),
+        (r#"{% set i = "<html>" %}{{ i }}"#, "&lt;html&gt;"),
+        ("{% set i = my_var %}{{ i }}", "hey"),
+        ("{% set i = malicious %}{{ i | safe }}", "<html>"),
+        ("{% set i = malicious %}{{ i }}", "&lt;html&gt;"),
+        ("{% set i = my_var | upper %}{{ i }}", "HEY"),
+        ("{% set i = range(end=3) %}{{ i }}", "[0, 1, 2]"),
+        ("{% set i = admin or true %}{{ i }}", "true"),
+        ("{% set i = admin and num > 0 %}{{ i }}", "true"),
+        ("{% set i = 0 / 0 %}{{ i }}", "NaN"),
+        ("{% set i = [1,2] %}{{ i }}", "[1, 2]"),
+    ];
+
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(render_template(input, &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn render_filter_section() {
+    let inputs = vec![
+        ("{% filter upper %}Hello{% endfilter %}", "HELLO"),
+        ("{% filter upper %}Hello{% if true %} world{% endif %}{% endfilter %}", "HELLO WORLD"),
+        ("{% filter upper %}Hello {% for i in range(end=3) %}i{% endfor %}{% endfilter %}", "HELLO III"),
+        (
+            "{% filter upper %}Hello {% for i in range(end=3) %}{% if i == 1 %}{% break %} {% endif %}i{% endfor %}{% endfilter %}",
+            "HELLO I",
+        ),
+        ("{% filter title %}Hello {% if true %}{{ 'world' | upper | safe }}{% endif %}{% endfilter %}", "Hello World"),
+        ("{% filter safe %}{% filter upper %}<Hello>{% endfilter %}{% endfilter%}", "<HELLO>")
+    ];
+
+    let context = Context::new();
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(render_template(input, &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn render_tests() {
+    let mut context = Context::new();
+    context.insert("is_true", &true);
+    context.insert("is_false", &false);
+    context.insert("age", &18);
+    context.insert("name", &"john");
+    let mut map = HashMap::new();
+    map.insert(0, 1);
+    context.insert("map", &map);
+    context.insert("numbers", &vec![1, 2, 3]);
+    context.insert::<Option<usize>, _>("maybe", &None);
+
+    let inputs = vec![
+        ("{% if is_true is defined %}Admin{% endif %}", "Admin"),
+        ("{% if hello is undefined %}Admin{% endif %}", "Admin"),
+        ("{% if name is string %}Admin{% endif %}", "Admin"),
+        ("{% if age is number %}Admin{% endif %}", "Admin"),
+        ("{% if age is even %}Admin{% endif %}", "Admin"),
+        ("{% if age is odd %}Admin{%else%}even{% endif %}", "even"),
+        ("{% if age is divisibleby(2) %}Admin{% endif %}", "Admin"),
+        ("{% if numbers is iterable %}Admin{% endif %}", "Admin"),
+        ("{% if map is iterable %}Admin{% endif %}", "Admin"),
+        ("{% if map is object %}Admin{% endif %}", "Admin"),
+        ("{% if name is starting_with('j') %}Admin{% endif %}", "Admin"),
+        ("{% if name is ending_with('n') %}Admin{% endif %}", "Admin"),
+        ("{% if numbers is containing(2) %}Admin{% endif %}", "Admin"),
+        ("{% if name is matching('^j.*') %}Admin{% endif %}", "Admin"),
+        ("{% if maybe is defined %}Admin{% endif %}", "Admin"),
+    ];
+
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(render_template(input, &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn render_if_elif_else() {
+    let mut context = Context::new();
+    context.insert("is_true", &true);
+    context.insert("is_false", &false);
+    context.insert("age", &18);
+    context.insert("name", &"john");
+    context.insert("empty_string", &"");
+    context.insert("numbers", &vec![1, 2, 3]);
+
+    let inputs = vec![
+        ("{% if is_true %}Admin{% endif %}", "Admin"),
+        ("{% if is_true or age + 1 > 18 %}Adult{% endif %}", "Adult"),
+        ("{% if is_true and age == 18 %}Adult{% endif %}", "Adult"),
+        // https://github.com/Keats/tera/issues/187
+        ("{% if 1 <= 2 %}a{% endif %}", "a"),
+        ("{% if 2 >= 1 %}a{% endif %}", "a"),
+        ("{% if 1 < 2 %}a{% endif %}", "a"),
+        ("{% if 2 > 1 %}a{% endif %}", "a"),
+        ("{% if 1 == 1 %}a{% endif %}", "a"),
+        ("{% if 1 != 2 %}a{% endif %}", "a"),
+        // testing string conditions
+        ("{% if 'true' %}a{% endif %}", "a"),
+        ("{% if name %}a{% endif %}", "a"),
+        ("{% if '' %}a{% endif %}", ""),
+        ("{% if empty_string %}a{% endif %}", ""),
+        ("{% if '' ~ name %}a{% endif %}", "a"),
+        ("{% if '' ~ empty_string %}a{% endif %}", ""),
+        // some not conditions
+        ("{% if not is_false %}a{% endif %}", "a"),
+        ("{% if not is_true %}a{% endif %}", ""),
+        ("{% if undefined %}a{% endif %}", ""),
+        ("{% if not undefined %}a{% endif %}", "a"),
+        ("{% if not is_false and is_true %}a{% endif %}", "a"),
+        ("{% if not is_false or numbers | length > 0 %}a{% endif %}", "a"),
+        // doesn't panic with NaN results
+        ("{% if 0 / 0 %}a{% endif %}", ""),
+        // if and else
+        ("{% if is_true %}Admin{% else %}User{% endif %}", "Admin"),
+        ("{% if is_false %}Admin{% else %}User{% endif %}", "User"),
+        // if and elifs
+        ("{% if is_true %}Admin{% elif is_false %}User{% endif %}", "Admin"),
+        ("{% if is_true %}Admin{% elif is_true %}User{% endif %}", "Admin"),
+        ("{% if is_true %}Admin{% elif numbers | length > 0 %}User{% endif %}", "Admin"),
+        // if, elifs and else
+        ("{% if is_true %}Admin{% elif is_false %}User{% else %}Hmm{% endif %}", "Admin"),
+        ("{% if false %}Admin{% elif is_false %}User{% else %}Hmm{% endif %}", "Hmm"),
+        // doesn't fallthrough elifs
+        // https://github.com/Keats/tera/issues/188
+        ("{% if 1 < 4 %}a{% elif 2 < 4 %}b{% elif 3 < 4 %}c{% else %}d{% endif %}", "a"),
+        // with in operator
+        (
+            "{% if 1 in numbers %}Admin{% elif 100 in numbers %}User{% else %}Hmm{% endif %}",
+            "Admin",
+        ),
+        ("{% if 100 in numbers %}Admin{% elif 1 in numbers %}User{% else %}Hmm{% endif %}", "User"),
+        ("{% if 'n' in name %}Admin{% else %}Hmm{% endif %}", "Admin"),
+        // function in if
+        ("{% if get_true() %}Truth{% endif %}", "Truth"),
+    ];
+
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(render_template(input, &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn render_for() {
+    let mut context = Context::new();
+    let mut map = BTreeMap::new();
+    map.insert("name", "bob");
+    map.insert("age", "18");
+
+    context.insert("data", &vec![1, 2, 3]);
+    context.insert("notes", &vec![1, 2, 3]);
+    context.insert("vectors", &vec![vec![0, 3, 6], vec![1, 4, 7]]);
+    context.insert("vectors_some_empty", &vec![vec![0, 3, 6], vec![], vec![1, 4, 7]]);
+    context.insert("map", &map);
+    context.insert("truthy", &2);
+
+    let inputs = vec![
+        ("{% for i in data %}{{i}}{% endfor %}", "123"),
+        ("{% for key, val in map %}{{key}}:{{val}} {% endfor %}", "age:18 name:bob "),
+        (
+            "{% for i in data %}{{loop.index}}{{loop.index0}}{{loop.first}}{{loop.last}}{% endfor %}",
+            "10truefalse21falsefalse32falsetrue"
+        ),
+        (
+            "{% for vector in vectors %}{% for j in vector %}{{ j }}{% endfor %}{% endfor %}",
+            "036147"
+        ),
+        (
+            "{% for vector in vectors_some_empty %}{% for j in vector %}{{ j }}{% endfor %}{% endfor %}",
+            "036147"
+        ),
+        (
+            "{% for val in data %}{% if val == truthy %}on{% else %}off{% endif %}{% endfor %}",
+            "offonoff"
+        ),
+        ("{% for i in range(end=5) %}{{i}}{% endfor %}", "01234"),
+        ("{% for i in range(end=5) | reverse %}{{i}}{% endfor %}", "43210"),
+        (
+            "{% set looped = 0 %}{% for i in range(end=5) %}{% set looped = i %}{{looped}}{% endfor%}{{looped}}",
+            "012340"
+        ),
+        // https://github.com/Keats/tera/issues/184
+        ("{% for note in notes %}{{ note }}{% endfor %}", "123"),
+        ("{% for note in notes | reverse %}{{ note }}{% endfor %}", "321"),
+        ("{% for v in vectors %}{{ v.0 }}{% endfor %}", "01"),
+        // Loop control (`break` and `continue`)
+        // https://github.com/Keats/tera/issues/267
+        (
+            "{% for i in data %}{{ i }}{% if i == 2 %}{% break %}{% endif %}{% endfor %}",
+            "12"
+        ),
+        (
+            "{% for i in data %}{% if i == 2 %}{% continue %}{% endif %}{{ i }}{% endfor %}",
+            "13"
+        ),
+        (
+            "{% for v in vectors %}{% for i in v %}{% if i == 3 %}{% break %}{% endif %}{{ i }}{% endfor %}{% endfor %}",
+            "0147"
+        ),
+        (
+            "{% for v in vectors %}{% for i in v %}{% if i == 3 %}{% continue %}{% endif %}{{ i }}{% endfor %}{% endfor %}",
+            "06147"
+        ),
+        (
+            "{% for a in [1, true, 1.1, 'hello'] %}{{a}}{% endfor %}",
+            "1true1.1hello"
+        ),
+        // https://github.com/Keats/tera/issues/301
+        (
+            "{% set start = 0 %}{% set end = start + 3 %}{% for i in range(start=start, end=end) %}{{ i }}{% endfor%}",
+            "012"
+        ),
+        // https://github.com/Keats/tera/issues/395
+        (
+            "{% for a in [] %}{{a}}{% else %}hello{% endfor %}",
+            "hello"
+        ),
+        (
+            "{% for a in undefined_variable | default(value=[]) %}{{a}}{% else %}hello{% endfor %}",
+            "hello"
+        ),
+        (
+            "{% for a in [] %}{{a}}{% else %}{% if 1 == 2 %}A{% else %}B{% endif %}{% endfor %}",
+            "B"
+        ),
+    ];
+
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(render_template(input, &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn render_magic_variable_isnt_escaped() {
+    let mut context = Context::new();
+    context.insert("html", &"<html>");
+
+    let result = render_template("{{ __tera_context }}", &context);
+
+    assert_eq!(
+        result.unwrap(),
+        r#"{
+  "html": "<html>"
+}"#
+        .to_owned()
+    );
+}
+
+// https://github.com/Keats/tera/issues/185
+#[test]
+fn ok_many_variable_blocks() {
+    let mut context = Context::new();
+    context.insert("username", &"bob");
+
+    let mut tpl = String::new();
+    for _ in 0..200 {
+        tpl.push_str("{{ username }}")
+    }
+    let mut expected = String::new();
+    for _ in 0..200 {
+        expected.push_str("bob")
+    }
+    assert_eq!(render_template(&tpl, &context).unwrap(), expected);
+}
+
+#[test]
+fn can_set_variable_in_global_context_in_forloop() {
+    let mut context = Context::new();
+    context.insert("tags", &vec![1, 2, 3]);
+    context.insert("default", &"default");
+
+    let result = render_template(
+        r#"
+{%- for i in tags -%}
+{%- set default = 1 -%}
+{%- set_global global_val = i -%}
+{%- endfor -%}
+{{ default }}{{ global_val }}"#,
+        &context,
+    );
+
+    assert_eq!(result.unwrap(), "default3");
+}
+
+#[test]
+fn default_filter_works() {
+    let mut context = Context::new();
+    let i: Option<usize> = None;
+    context.insert("existing", "hello");
+    context.insert("null", &i);
+
+    let inputs = vec![
+        (r#"{{ existing | default(value="hey") }}"#, "hello"),
+        (r#"{{ val | default(value=1) }}"#, "1"),
+        (r#"{{ val | default(value="hey") | capitalize }}"#, "Hey"),
+        (r#"{{ obj.val | default(value="hey") | capitalize }}"#, "Hey"),
+        (r#"{{ obj.val | default(value="hey") | capitalize }}"#, "Hey"),
+        (r#"{{ not admin | default(value=false) }}"#, "true"),
+        (r#"{{ not admin | default(value=true) }}"#, "false"),
+        (r#"{{ null | default(value=true) }}"#, "true"),
+        (r#"{{ null | default(value="hey") | capitalize }}"#, "Hey"),
+    ];
+
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(render_template(input, &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn filter_filter_works() {
+    #[derive(Debug, Serialize)]
+    struct Author {
+        id: u8,
+    }
+
+    let mut context = Context::new();
+    context.insert("authors", &vec![Author { id: 1 }, Author { id: 2 }, Author { id: 3 }]);
+
+    let inputs =
+        vec![(r#"{{ authors | filter(attribute="id", value=1) | first | get(key="id") }}"#, "1")];
+
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(render_template(input, &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn filter_on_array_literal_works() {
+    let mut context = Context::new();
+    let i: Option<usize> = None;
+    context.insert("existing", "hello");
+    context.insert("null", &i);
+
+    let inputs = vec![
+        (r#"{{ [1, 2, 3] | length }}"#, "3"),
+        (r#"{% set a = [1, 2, 3] | length %}{{ a }}"#, "3"),
+        (r#"{% for a in [1, 2, 3] | slice(start=1) %}{{ a }}{% endfor %}"#, "23"),
+    ];
+
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(render_template(input, &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn can_do_string_concat() {
+    let mut context = Context::new();
+    context.insert("a_string", "hello");
+    context.insert("another_string", "xXx");
+    context.insert("an_int", &1);
+    context.insert("a_float", &3.14);
+
+    let inputs = vec![
+        (r#"{{ "hello" ~ " world" }}"#, "hello world"),
+        (r#"{{ "hello" ~ 1 }}"#, "hello1"),
+        (r#"{{ "hello" ~ 3.14 }}"#, "hello3.14"),
+        (r#"{{ 3.14 ~ "hello"}}"#, "3.14hello"),
+        (r#"{{ "hello" ~ get_string() }}"#, "helloHello"),
+        (r#"{{ get_string() ~ "hello" }}"#, "Hellohello"),
+        (r#"{{ get_string() ~ 3.14 }}"#, "Hello3.14"),
+        (r#"{{ a_string ~ " world" }}"#, "hello world"),
+        (r#"{{ a_string ~ ' world ' ~ another_string }}"#, "hello world xXx"),
+        (r#"{{ a_string ~ another_string }}"#, "helloxXx"),
+        (r#"{{ a_string ~ an_int }}"#, "hello1"),
+        (r#"{{ a_string ~ a_float }}"#, "hello3.14"),
+    ];
+
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(render_template(input, &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn can_fail_rendering_from_template() {
+    let mut context = Context::new();
+    context.insert("title", "hello");
+
+    let res = render_template(
+        r#"{{ throw(message="Error: " ~ title ~ " did not include a summary") }}"#,
+        &context,
+    );
+
+    let err = res.expect_err("This should always fail to render");
+    let source = err.source().expect("Must have a source");
+    assert_eq!(source.to_string(), "Function call 'throw' failed");
+
+    let source = source.source().expect("Should have a nested error");
+    assert_eq!(source.to_string(), "Error: hello did not include a summary");
+}
+
+#[test]
+fn does_render_owned_for_loop_with_objects() {
+    let mut context = Context::new();
+    let data = json!([
+        {"id": 1, "year": 2015},
+        {"id": 2, "year": 2015},
+        {"id": 3, "year": 2016},
+        {"id": 4, "year": 2017},
+        {"id": 5, "year": 2017},
+        {"id": 6, "year": 2017},
+        {"id": 7, "year": 2018},
+        {"id": 8},
+        {"id": 9, "year": null},
+    ]);
+    context.insert("something", &data);
+
+    let tpl =
+        r#"{% for year, things in something | group_by(attribute="year") %}{{year}},{% endfor %}"#;
+    let expected = "2015,2016,2017,2018,";
+    assert_eq!(render_template(tpl, &context).unwrap(), expected);
+}
+
+#[test]
+fn does_render_owned_for_loop_with_objects_string_keys() {
+    let mut context = Context::new();
+    let data = json!([
+        {"id": 1, "group": "a"},
+        {"id": 2, "group": "b"},
+        {"id": 3, "group": "c"},
+        {"id": 4, "group": "a"},
+        {"id": 5, "group": "b"},
+        {"id": 6, "group": "c"},
+        {"id": 7, "group": "a"},
+        {"id": 8},
+        {"id": 9, "year": null},
+    ]);
+    context.insert("something", &data);
+
+    let tpl = r#"{% for group, things in something | group_by(attribute="group") %}{{group}},{% endfor %}"#;
+    let expected = "a,b,c,";
+    assert_eq!(render_template(tpl, &context).unwrap(), expected);
+}
+
+#[test]
+fn render_magic_variable_gets_all_contexts() {
+    let mut context = Context::new();
+    context.insert("html", &"<html>");
+    context.insert("num", &1);
+    context.insert("i", &10);
+
+    let result = render_template(
+        "{% set some_val = 1 %}{% for i in range(start=0, end=1) %}{% set for_val = i %}{{ __tera_context }}{% endfor %}",
+        &context
+    );
+
+    assert_eq!(
+        result.unwrap(),
+        r#"{
+  "for_val": 0,
+  "html": "<html>",
+  "i": 0,
+  "num": 1,
+  "some_val": 1
+}"#
+        .to_owned()
+    );
+}
+
+#[test]
+fn render_magic_variable_macro_doesnt_leak() {
+    let mut context = Context::new();
+    context.insert("html", &"<html>");
+    context.insert("num", &1);
+    context.insert("i", &10);
+
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello(arg=1) %}{{ __tera_context }}{% endmacro hello %}"),
+        ("tpl", "{% import \"macros\" as macros %}{{macros::hello()}}"),
+    ])
+    .unwrap();
+    let result = tera.render("tpl", &context);
+
+    assert_eq!(
+        result.unwrap(),
+        r#"{
+  "arg": 1
+}"#
+        .to_owned()
+    );
+}
+
+// https://github.com/Keats/tera/issues/342
+#[test]
+fn redefining_loop_value_doesnt_break_loop() {
+    let mut tera = Tera::default();
+    tera.add_raw_template(
+        "tpl",
+        r#"
+{%- set string = "abcdefghdijklm" | split(pat="d") -%}
+{% for i in string -%}
+    {%- set j = i ~ "lol" ~ " " -%}
+    {{ j }}
+{%- endfor -%}
+        "#,
+    )
+    .unwrap();
+    let context = Context::new();
+    let result = tera.render("tpl", &context);
+
+    assert_eq!(result.unwrap(), "abclol efghlol ijklmlol ");
+}
+
+#[test]
+fn can_use_concat_to_push_to_array() {
+    let mut tera = Tera::default();
+    tera.add_raw_template(
+        "tpl",
+        r#"
+{%- set ids = [] -%}
+{% for i in range(end=5) -%}
+{%- set_global ids = ids | concat(with=i) -%}
+{%- endfor -%}
+{{ids}}"#,
+    )
+    .unwrap();
+    let context = Context::new();
+    let result = tera.render("tpl", &context);
+
+    assert_eq!(result.unwrap(), "[0, 1, 2, 3, 4]");
+}
+
+struct Next(AtomicUsize);
+
+impl Function for Next {
+    fn call(&self, _args: &HashMap<String, Value>) -> Result<Value> {
+        Ok(Value::Number(self.0.fetch_add(1, Ordering::Relaxed).into()))
+    }
+}
+
+#[derive(Clone)]
+struct SharedNext(Arc<Next>);
+
+impl Function for SharedNext {
+    fn call(&self, args: &HashMap<String, Value>) -> Result<Value> {
+        self.0.call(args)
+    }
+}
+
+lazy_static! {
+    static ref NEXT_GLOBAL: SharedNext = SharedNext(Arc::new(Next(AtomicUsize::new(1))));
+}
+
+#[test]
+fn stateful_global_fn() {
+    fn make_tera() -> Tera {
+        let mut tera = Tera::default();
+        tera.add_raw_template(
+            "fn.html",
+            "<h1>{{ get_next() }}, {{ get_next_shared() }}, {{ get_next() }}...</h1>",
+        )
+        .unwrap();
+
+        tera.register_function("get_next", Next(AtomicUsize::new(1)));
+        tera.register_function("get_next_shared", NEXT_GLOBAL.clone());
+        tera
+    }
+
+    assert_eq!(
+        make_tera().render("fn.html", &Context::new()).unwrap(),
+        "<h1>1, 1, 2...</h1>".to_owned()
+    );
+    assert_eq!(
+        make_tera().render("fn.html", &Context::new()).unwrap(),
+        "<h1>1, 2, 2...</h1>".to_owned()
+    );
+}
+
+// https://github.com/Keats/tera/issues/373
+#[test]
+fn split_on_context_value() {
+    let mut tera = Tera::default();
+    tera.add_raw_template("split.html", r#"{{ body | split(pat="\n") }}"#).unwrap();
+    let mut context = Context::new();
+    context.insert("body", "multi\nple\nlines");
+    let res = tera.render("split.html", &context);
+    assert_eq!(res.unwrap(), "[multi, ple, lines]");
+}
+
+// https://github.com/Keats/tera/issues/422
+#[test]
+fn default_filter_works_in_condition() {
+    let mut tera = Tera::default();
+    tera.add_raw_template("test.html", r#"{% if frobnicate|default(value=True) %}here{% endif %}"#)
+        .unwrap();
+    let res = tera.render("test.html", &Context::new());
+    assert_eq!(res.unwrap(), "here");
+}
+
+#[test]
+fn safe_filter_works() {
+    struct Safe;
+    impl crate::Filter for Safe {
+        fn filter(&self, value: &Value, _args: &HashMap<String, Value>) -> Result<Value> {
+            Ok(Value::String(format!("<div>{}</div>", value.as_str().unwrap())))
+        }
+
+        fn is_safe(&self) -> bool {
+            true
+        }
+    }
+
+    let mut tera = Tera::default();
+    tera.register_filter("safe_filter", Safe);
+    tera.add_raw_template("test.html", r#"{{ "Hello" | safe_filter }}"#).unwrap();
+
+    let res = tera.render("test.html", &Context::new());
+    assert_eq!(res.unwrap(), "<div>Hello</div>");
+}
+
+#[test]
+fn safe_function_works() {
+    struct Safe;
+    impl crate::Function for Safe {
+        fn call(&self, _args: &HashMap<String, Value>) -> Result<Value> {
+            Ok(Value::String("<div>Hello</div>".to_owned()))
+        }
+
+        fn is_safe(&self) -> bool {
+            true
+        }
+    }
+
+    let mut tera = Tera::default();
+    tera.register_function("safe_function", Safe);
+    tera.add_raw_template("test.html", "{{ safe_function() }}").unwrap();
+
+    let res = tera.render("test.html", &Context::new());
+    assert_eq!(res.unwrap(), "<div>Hello</div>");
+}
diff --git a/vendor/tera/src/renderer/tests/errors.rs b/vendor/tera/src/renderer/tests/errors.rs
new file mode 100644 (file)
index 0000000..3aa72c8
--- /dev/null
@@ -0,0 +1,284 @@
+use std::collections::HashMap;
+use std::error::Error;
+
+use crate::context::Context;
+use crate::tera::Tera;
+
+#[test]
+fn error_location_basic() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![("tpl", "{{ 1 + true }}")]).unwrap();
+
+    let result = tera.render("tpl", &Context::new());
+
+    assert_eq!(result.unwrap_err().to_string(), "Failed to render \'tpl\'");
+}
+
+#[test]
+fn error_location_inside_macro() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello()%}{{ 1 + true }}{% endmacro hello %}"),
+        ("tpl", "{% import \"macros\" as macros %}{{ macros::hello() }}"),
+    ])
+    .unwrap();
+
+    let result = tera.render("tpl", &Context::new());
+
+    assert_eq!(
+        result.unwrap_err().to_string(),
+        "Failed to render \'tpl\': error while rendering macro `macros::hello`"
+    );
+}
+
+#[test]
+fn error_loading_macro_from_unloaded_namespace() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello()%}{{ 1 + true }}{% endmacro hello %}"),
+        ("tpl", "{% import \"macros\" as macros %}{{ macro::hello() }}"),
+    ])
+    .unwrap();
+
+    let result = tera.render("tpl", &Context::new());
+    println!("{:#?}", result);
+    assert_eq!(
+        result.unwrap_err().source().unwrap().to_string(),
+        "Macro namespace `macro` was not found in template `tpl`. Have you maybe forgotten to import it, or misspelled it?"
+    );
+}
+
+#[test]
+fn error_location_base_template() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("parent", "Hello {{ greeting + 1}} {% block bob %}{% endblock bob %}"),
+        ("child", "{% extends \"parent\" %}{% block bob %}Hey{% endblock bob %}"),
+    ])
+    .unwrap();
+
+    let result = tera.render("child", &Context::new());
+
+    assert_eq!(
+        result.unwrap_err().to_string(),
+        "Failed to render \'child\' (error happened in 'parent')."
+    );
+}
+
+#[test]
+fn error_location_in_parent_block() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("parent", "Hello {{ greeting }} {% block bob %}{{ 1 + true }}{% endblock bob %}"),
+        ("child", "{% extends \"parent\" %}{% block bob %}{{ super() }}Hey{% endblock bob %}"),
+    ])
+    .unwrap();
+
+    let result = tera.render("child", &Context::new());
+
+    assert_eq!(
+        result.unwrap_err().to_string(),
+        "Failed to render \'child\' (error happened in 'parent')."
+    );
+}
+
+#[test]
+fn error_location_in_parent_in_macro() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello()%}{{ 1 + true }}{% endmacro hello %}"),
+        ("parent", "{% import \"macros\" as macros %}{{ macros::hello() }}{% block bob %}{% endblock bob %}"),
+        ("child", "{% extends \"parent\" %}{% block bob %}{{ super() }}Hey{% endblock bob %}"),
+    ]).unwrap();
+
+    let result = tera.render("child", &Context::new());
+
+    assert_eq!(
+        result.unwrap_err().to_string(),
+        "Failed to render \'child\': error while rendering macro `macros::hello` (error happened in \'parent\')."
+    );
+}
+
+#[test]
+fn error_out_of_range_index() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![("tpl", "{{ arr[10] }}")]).unwrap();
+    let mut context = Context::new();
+    context.insert("arr", &[1, 2, 3]);
+
+    let result = tera.render("tpl", &Context::new());
+
+    assert_eq!(
+        result.unwrap_err().source().unwrap().to_string(),
+        "Variable `arr[10]` not found in context while rendering \'tpl\': the evaluated version was `arr.10`. Maybe the index is out of bounds?"
+    );
+}
+
+#[test]
+fn error_unknown_index_variable() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![("tpl", "{{ arr[a] }}")]).unwrap();
+    let mut context = Context::new();
+    context.insert("arr", &[1, 2, 3]);
+
+    let result = tera.render("tpl", &context);
+
+    assert_eq!(
+        result.unwrap_err().source().unwrap().to_string(),
+        "Variable arr[a] can not be evaluated because: Variable `a` not found in context while rendering \'tpl\'"
+    );
+}
+
+#[test]
+fn error_invalid_type_index_variable() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![("tpl", "{{ arr[a] }}")]).unwrap();
+
+    let mut context = Context::new();
+    context.insert("arr", &[1, 2, 3]);
+    context.insert("a", &true);
+
+    let result = tera.render("tpl", &context);
+
+    assert_eq!(
+        result.unwrap_err().source().unwrap().to_string(),
+        "Only variables evaluating to String or Number can be used as index (`a` of `arr[a]`)"
+    );
+}
+
+#[test]
+fn error_when_missing_macro_templates() {
+    let mut tera = Tera::default();
+    let result = tera.add_raw_templates(vec![(
+        "parent",
+        "{% import \"macros\" as macros %}{{ macros::hello() }}{% block bob %}{% endblock bob %}",
+    )]);
+    assert_eq!(
+        result.unwrap_err().to_string(),
+        "Template `parent` loads macros from `macros` which isn\'t present in Tera"
+    );
+}
+
+#[test]
+fn error_when_using_variable_set_in_included_templates_outside() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("included", r#"{{a}}{% set b = "hi" %}-{{b}}"#),
+        ("base", r#"{{a}}{% include "included" %}{{b}}"#),
+    ])
+    .unwrap();
+    let mut context = Context::new();
+    context.insert("a", &10);
+    let result = tera.render("base", &context);
+
+    assert_eq!(
+        result.unwrap_err().source().unwrap().to_string(),
+        "Variable `b` not found in context while rendering \'base\'"
+    );
+}
+
+// https://github.com/Keats/tera/issues/344
+// Yes it is as silly as it sounds
+#[test]
+fn right_variable_name_is_needed_in_for_loop() {
+    let mut data = HashMap::new();
+    data.insert("content", "hello");
+    let mut context = Context::new();
+    context.insert("comments", &vec![data]);
+    let mut tera = Tera::default();
+    tera.add_raw_template(
+        "tpl",
+        r#"
+{%- for comment in comments -%}
+<p>{{ comment.content }}</p>
+<p>{{ whocares.content }}</p>
+<p>{{ doesntmatter.content }}</p>
+{% endfor -%}"#,
+    )
+    .unwrap();
+    let result = tera.render("tpl", &context);
+
+    assert_eq!(
+        result.unwrap_err().source().unwrap().to_string(),
+        "Variable `whocares.content` not found in context while rendering \'tpl\'"
+    );
+}
+
+// https://github.com/Keats/tera/issues/370#issuecomment-453893826
+#[test]
+fn errors_when_calling_macros_defined_in_file() {
+    let mut tera = Tera::default();
+    tera.add_raw_template(
+        "tpl",
+        r#"
+{% macro path_item(path) %}
+    <span class="path" title="{{ path }}">{{ path }}</span>
+{% endmacro path_item %}
+
+...
+
+<td>{{ self::path_item(path=hello) }}</td>
+        "#,
+    )
+    .unwrap();
+    let mut context = Context::new();
+    context.insert("hello", &true);
+    let result = tera.render("tpl", &context);
+    assert_eq!(
+        result.unwrap_err().source().unwrap().to_string(),
+        "Invalid macro definition: `path_item`"
+    );
+}
+
+// https://github.com/Keats/tera/issues/385
+// https://github.com/Keats/tera/issues/370
+#[test]
+fn errors_with_inheritance_in_included_template() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("base", "Base - {% include \"child\" %}"),
+        ("parent", "{% block title %}Parent{% endblock %}"),
+        ("child", "{% extends \"parent\" %}{% block title %}{{ super() }} - Child{% endblock %}"),
+    ])
+    .unwrap();
+
+    let result = tera.render("base", &Context::new());
+
+    assert_eq!(
+        result.unwrap_err().source().unwrap().to_string(),
+        "Inheritance in included templates is currently not supported: extended `parent`"
+    );
+}
+
+#[test]
+fn error_string_concat_math_logic() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![("tpl", "{{ 'ho' ~ name < 10 }}")]).unwrap();
+    let mut context = Context::new();
+    context.insert("name", &"john");
+
+    let result = tera.render("tpl", &context);
+
+    assert_eq!(
+        result.unwrap_err().source().unwrap().to_string(),
+        "Tried to do math with a string concatenation: 'ho' ~ name"
+    );
+}
+
+#[test]
+fn error_gives_source_on_tests() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![("tpl", "{% if a is undefined(1) %}-{% endif %}")]).unwrap();
+    let result = tera.render("tpl", &Context::new());
+    println!("{:?}", result);
+    let err = result.unwrap_err();
+
+    let source = err.source().unwrap();
+    assert_eq!(source.to_string(), "Test call \'undefined\' failed");
+    let source2 = source.source().unwrap();
+
+    assert_eq!(
+        source2.to_string(),
+        "Tester `undefined` was called with some args but this test doesn\'t take args"
+    );
+}
diff --git a/vendor/tera/src/renderer/tests/inheritance.rs b/vendor/tera/src/renderer/tests/inheritance.rs
new file mode 100644 (file)
index 0000000..6dc5d69
--- /dev/null
@@ -0,0 +1,176 @@
+use crate::context::Context;
+use crate::tera::Tera;
+
+#[test]
+fn render_simple_inheritance() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("top", "{% block pre %}{% endblock pre %}{% block main %}{% endblock main %}"),
+        ("bottom", "{% extends \"top\" %}{% block main %}MAIN{% endblock %}"),
+    ])
+    .unwrap();
+    let result = tera.render("bottom", &Context::new());
+
+    assert_eq!(result.unwrap(), "MAIN".to_string());
+}
+
+#[test]
+fn render_simple_inheritance_super() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("top", "{% block main %}TOP{% endblock main %}"),
+        ("bottom", "{% extends \"top\" %}{% block main %}{{ super() }}MAIN{% endblock %}"),
+    ])
+    .unwrap();
+    let result = tera.render("bottom", &Context::new());
+
+    assert_eq!(result.unwrap(), "TOPMAIN".to_string());
+}
+
+#[test]
+fn render_multiple_inheritance() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("top", "{% block pre %}{% endblock pre %}{% block main %}{% endblock main %}"),
+        ("mid", "{% extends \"top\" %}{% block pre %}PRE{% endblock pre %}"),
+        ("bottom", "{% extends \"mid\" %}{% block main %}MAIN{% endblock main %}"),
+    ])
+    .unwrap();
+    let result = tera.render("bottom", &Context::new());
+
+    assert_eq!(result.unwrap(), "PREMAIN".to_string());
+}
+
+#[test]
+fn render_multiple_inheritance_with_super() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        (
+            "grandparent",
+            "{% block hey %}hello{% endblock hey %} {% block ending %}sincerely{% endblock ending %}",
+        ),
+        (
+            "parent",
+            "{% extends \"grandparent\" %}{% block hey %}hi and grandma says {{ super() }}{% endblock hey %}",
+        ),
+        (
+            "child",
+            "{% extends \"parent\" %}{% block hey %}dad says {{ super() }}{% endblock hey %}{% block ending %}{{ super() }} with love{% endblock ending %}",
+        ),
+    ]).unwrap();
+    let result = tera.render("child", &Context::new());
+
+    assert_eq!(
+        result.unwrap(),
+        "dad says hi and grandma says hello sincerely with love".to_string()
+    );
+}
+
+#[test]
+fn render_filter_section_inheritance_no_override() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("top", "{% filter upper %}hello {% block main %}top{% endblock main %}{% endfilter %}"),
+        ("bottom", "{% extends 'top' %}"),
+    ])
+    .unwrap();
+    let result = tera.render("bottom", &Context::new());
+
+    assert_eq!(result.unwrap(), "HELLO TOP".to_string());
+}
+
+#[test]
+fn render_filter_section_inheritance() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("top", "{% filter upper %}hello {% block main %}top{% endblock main %}{% endfilter %}"),
+        ("bottom", "{% extends 'top' %}{% block main %}bottom{% endblock %}"),
+    ])
+    .unwrap();
+    let result = tera.render("bottom", &Context::new());
+
+    assert_eq!(result.unwrap(), "HELLO BOTTOM".to_string());
+}
+
+#[test]
+fn render_super_multiple_inheritance_nested_block() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        (
+            "grandparent",
+            "{% block hey %}hello{% endblock hey %}",
+        ),
+        (
+            "parent",
+            "{% extends \"grandparent\" %}{% block hey %}hi and grandma says {{ super() }} {% block ending %}sincerely{% endblock ending %}{% endblock hey %}",
+        ),
+        (
+            "child", "{% extends \"parent\" %}{% block hey %}dad says {{ super() }}{% endblock hey %}{% block ending %}{{ super() }} with love{% endblock ending %}",
+        ),
+    ]).unwrap();
+    let result = tera.render("child", &Context::new());
+
+    assert_eq!(
+        result.unwrap(),
+        "dad says hi and grandma says hello sincerely with love".to_string()
+    );
+}
+
+#[test]
+fn render_nested_block_multiple_inheritance_no_super() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("index", "{% block content%}INDEX{% endblock content %}"),
+        (
+            "docs",
+            "{% extends \"index\" %}{% block content%}DOCS{% block more %}MORE{% endblock more %}{% endblock content %}",
+        ),
+        ("page", "{% extends \"docs\" %}{% block more %}PAGE{% endblock more %}"),
+    ]).unwrap();
+
+    let result = tera.render("page", &Context::new());
+
+    assert_eq!(result.unwrap(), "DOCSPAGE".to_string());
+}
+
+#[test]
+fn render_super_in_top_block_errors() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![("index", "{% block content%}{{super()}}{% endblock content %}")])
+        .unwrap();
+
+    let result = tera.render("index", &Context::new());
+    assert!(result.is_err());
+}
+
+// https://github.com/Keats/tera/issues/215
+#[test]
+fn render_super_in_grandchild_without_redefining_works() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("grandparent", "{% block title %}Title{% endblock %}"),
+        (
+            "parent",
+            "{% extends \"grandparent\" %}{% block title %}{{ super() }} - More{% endblock %}",
+        ),
+        ("child", "{% extends \"parent\" %}"),
+    ])
+    .unwrap();
+
+    let result = tera.render("child", &Context::new());
+    assert_eq!(result.unwrap(), "Title - More".to_string());
+}
+
+#[test]
+fn render_super_in_grandchild_without_redefining_in_parent_works() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("grandparent", "{% block title %}Title{% endblock %}"),
+        ("parent", "{% extends \"grandparent\" %}"),
+        ("child", "{% extends \"parent\" %}{% block title %}{{ super() }} - More{% endblock %}"),
+    ])
+    .unwrap();
+
+    let result = tera.render("child", &Context::new());
+    assert_eq!(result.unwrap(), "Title - More".to_string());
+}
diff --git a/vendor/tera/src/renderer/tests/macros.rs b/vendor/tera/src/renderer/tests/macros.rs
new file mode 100644 (file)
index 0000000..817f97d
--- /dev/null
@@ -0,0 +1,356 @@
+use crate::context::Context;
+use crate::tera::Tera;
+
+use super::NestedObject;
+
+#[test]
+fn render_macros() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
+        (
+            "tpl",
+            "{% import \"macros\" as macros %}{% block hey %}{{macros::hello()}}{% endblock hey %}",
+        ),
+    ])
+    .unwrap();
+
+    let result = tera.render("tpl", &Context::new());
+
+    assert_eq!(result.unwrap(), "Hello".to_string());
+}
+
+#[test]
+fn render_macros_expression_arg() {
+    let mut context = Context::new();
+    context.insert("pages", &vec![1, 2, 3, 4, 5]);
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello(val)%}{{val}}{% endmacro hello %}"),
+        ("tpl", "{% import \"macros\" as macros %}{{macros::hello(val=pages|last)}}"),
+    ])
+    .unwrap();
+
+    let result = tera.render("tpl", &context);
+
+    assert_eq!(result.unwrap(), "5".to_string());
+}
+
+#[test]
+fn render_macros_in_child_templates_same_namespace() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("grandparent", "{% block hey %}hello{% endblock hey %}"),
+        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
+        ("macros2", "{% macro hi()%}Hi{% endmacro hi %}"),
+        ("parent", "{% extends \"grandparent\" %}{% import \"macros\" as macros %}{% block hey %}{{macros::hello()}}{% endblock hey %}"),
+        ("child", "{% extends \"parent\" %}{% import \"macros2\" as macros %}{% block hey %}{{super()}}/{{macros::hi()}}{% endblock hey %}"),
+    ]).unwrap();
+
+    let result = tera.render("child", &Context::new());
+
+    assert_eq!(result.unwrap(), "Hello/Hi".to_string());
+}
+
+#[test]
+fn render_macros_in_child_templates_different_namespace() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("grandparent", "{% block hey %}hello{% endblock hey %}"),
+        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
+        ("macros2", "{% macro hi()%}Hi{% endmacro hi %}"),
+        ("parent", "{% extends \"grandparent\" %}{% import \"macros\" as macros %}{% block hey %}{{macros::hello()}}{% endblock hey %}"),
+        ("child", "{% extends \"parent\" %}{% import \"macros2\" as macros2 %}{% block hey %}{{super()}}/{{macros2::hi()}}{% endblock hey %}"),
+    ]).unwrap();
+
+    let result = tera.render("child", &Context::new());
+
+    assert_eq!(result.unwrap(), "Hello/Hi".to_string());
+}
+
+#[test]
+fn render_macros_in_parent_template_with_inheritance() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
+        ("grandparent", "{% import \"macros\" as macros %}{% block hey %}{{macros::hello()}}{% endblock hey %}"),
+        ("child", "{% extends \"grandparent\" %}{% import \"macros\" as macros %}{% block hey %}{{super()}}/{{macros::hello()}}{% endblock hey %}"),
+    ]).unwrap();
+
+    let result = tera.render("child", &Context::new());
+
+    assert_eq!(result.unwrap(), "Hello/Hello".to_string());
+}
+
+#[test]
+fn macro_param_arent_escaped() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros.html", r#"{% macro print(val) %}{{val|safe}}{% endmacro print %}"#),
+        ("hello.html", r#"{% import "macros.html" as macros %}{{ macros::print(val=my_var)}}"#),
+    ])
+    .unwrap();
+    let mut context = Context::new();
+    context.insert("my_var", &"&");
+    let result = tera.render("hello.html", &context);
+
+    assert_eq!(result.unwrap(), "&".to_string());
+}
+
+#[test]
+fn render_set_tag_macro() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello()%}Hello{% endmacro hello %}"),
+        (
+            "hello.html",
+            "{% import \"macros\" as macros %}{% set my_var = macros::hello() %}{{my_var}}",
+        ),
+    ])
+    .unwrap();
+    let result = tera.render("hello.html", &Context::new());
+
+    assert_eq!(result.unwrap(), "Hello".to_string());
+}
+
+#[test]
+fn render_macros_with_default_args() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello(val=1) %}{{val}}{% endmacro hello %}"),
+        ("hello.html", "{% import \"macros\" as macros %}{{macros::hello()}}"),
+    ])
+    .unwrap();
+    let result = tera.render("hello.html", &Context::new());
+
+    assert_eq!(result.unwrap(), "1".to_string());
+}
+
+#[test]
+fn render_macros_override_default_args() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello(val=1) %}{{val}}{% endmacro hello %}"),
+        ("hello.html", "{% import \"macros\" as macros %}{{macros::hello(val=2)}}"),
+    ])
+    .unwrap();
+    let result = tera.render("hello.html", &Context::new());
+
+    assert_eq!(result.unwrap(), "2".to_string());
+}
+
+#[test]
+fn render_recursive_macro() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        (
+            "macros",
+            "{% macro factorial(n) %}{% if n > 1 %}{{ n }} - {{ self::factorial(n=n-1) }}{% else %}1{% endif %}{{ n }}{% endmacro factorial %}",
+        ),
+        ("hello.html", "{% import \"macros\" as macros %}{{macros::factorial(n=7)}}"),
+    ]).unwrap();
+    let result = tera.render("hello.html", &Context::new());
+
+    assert_eq!(result.unwrap(), "7 - 6 - 5 - 4 - 3 - 2 - 11234567".to_string());
+}
+
+// https://github.com/Keats/tera/issues/202
+#[test]
+fn recursive_macro_with_loops() {
+    let parent = NestedObject { label: "Parent".to_string(), parent: None, numbers: vec![1, 2, 3] };
+    let child = NestedObject {
+        label: "Child".to_string(),
+        parent: Some(Box::new(parent)),
+        numbers: vec![1, 2, 3],
+    };
+    let mut context = Context::new();
+    context.insert("objects", &vec![child]);
+    let mut tera = Tera::default();
+
+    tera.add_raw_templates(vec![
+        (
+            "macros.html",
+            r#"
+{% macro label_for(obj, sep) -%}
+  {%- if obj.parent -%}
+    {{ self::label_for(obj=obj.parent, sep=sep) }}{{sep}}
+  {%- endif -%}
+  {{obj.label}}
+  {%- for i in obj.numbers -%}{{ i }}{%- endfor -%}
+{%- endmacro label_for %}
+            "#,
+        ),
+        (
+            "recursive",
+            r#"
+{%- import "macros.html" as macros -%}
+{%- for obj in objects -%}
+    {{ macros::label_for(obj=obj, sep="|") }}
+{%- endfor -%}
+"#,
+        ),
+    ])
+    .unwrap();
+
+    let result = tera.render("recursive", &context);
+
+    assert_eq!(result.unwrap(), "Parent123|Child123".to_string());
+}
+
+// https://github.com/Keats/tera/issues/250
+#[test]
+fn render_macros_in_included() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro my_macro() %}my macro{% endmacro %}"),
+        ("includeme", r#"{% import "macros" as macros %}{{ macros::my_macro() }}"#),
+        ("example", r#"{% include "includeme" %}"#),
+    ])
+    .unwrap();
+    let result = tera.render("example", &Context::new());
+
+    assert_eq!(result.unwrap(), "my macro".to_string());
+}
+
+// https://github.com/Keats/tera/issues/255
+#[test]
+fn import_macros_into_other_macro_files() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("submacros", "{% macro test() %}Success!{% endmacro %}"),
+        (
+            "macros",
+            r#"{% import "submacros" as sub %}{% macro test() %}{{ sub::test() }}{% endmacro %}"#,
+        ),
+        ("index", r#"{% import "macros" as macros %}{{ macros::test() }}"#),
+    ])
+    .unwrap();
+    let result = tera.render("index", &Context::new());
+
+    assert_eq!(result.unwrap(), "Success!".to_string());
+}
+
+#[test]
+fn can_load_parent_macro_in_child() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello()%}{{ 1 }}{% endmacro hello %}"),
+        ("parent", "{% import \"macros\" as macros %}{{ macros::hello() }}{% block bob %}{% endblock bob %}"),
+        ("child", "{% extends \"parent\" %}{% block bob %}{{ super() }}Hey{% endblock bob %}"),
+    ]).unwrap();
+
+    let result = tera.render("child", &Context::new());
+
+    assert_eq!(result.unwrap(), "1Hey".to_string());
+}
+
+#[test]
+fn can_load_macro_in_child() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello()%}{{ 1 }}{% endmacro hello %}"),
+        ("parent", "{% block bob %}{% endblock bob %}"),
+        ("child", "{% extends \"parent\" %}{% import \"macros\" as macros %}{% block bob %}{{ macros::hello() }}{% endblock bob %}"),
+    ]).unwrap();
+
+    let result = tera.render("child", &Context::new());
+
+    assert_eq!(result.unwrap(), "1".to_string());
+}
+
+// https://github.com/Keats/tera/issues/333
+// this test fails in 0.11.14, worked in 0.11.10
+#[test]
+fn can_inherit_macro_import_from_parent() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello()%}HELLO{% endmacro hello %}"),
+        ("parent", "{% import \"macros\" as macros %}{% block bob %}parent{% endblock bob %}"),
+        ("child", "{% extends \"parent\" %}{% block bob %}{{macros::hello()}}{% endblock bob %}"),
+    ])
+    .unwrap();
+
+    let result = tera.render("child", &Context::default());
+    assert_eq!(result.unwrap(), "HELLO".to_string());
+}
+
+#[test]
+fn can_inherit_macro_import_from_grandparent() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello()%}HELLO{% endmacro hello %}"),
+        ("grandparent", "{% import \"macros\" as macros %}{% block bob %}grandparent{% endblock bob %}"),
+        ("parent", "{% extends \"grandparent\" %}{% import \"macros\" as macros2 %}{% block bob %}parent{% endblock bob %}"),
+        ("child", "{% extends \"parent\" %}{% block bob %}{{macros::hello()}}-{{macros2::hello()}}{% endblock bob %}"),
+    ]).unwrap();
+
+    let result = tera.render("child", &Context::default());
+    assert_eq!(result.unwrap(), "HELLO-HELLO".to_string());
+}
+
+#[test]
+fn can_load_macro_in_parent_with_grandparent() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("macros", "{% macro hello()%}{{ 1 }}{% endmacro hello %}"),
+        ("grandparent", "{% block bob %}{% endblock bob %}"),
+        ("parent", "{% extends \"grandparent\" %}{% import \"macros\" as macros %}{% block bob %}{{ macros::hello() }} - Hey{% endblock bob %}"),
+        ("child", "{% extends \"parent\" %}{% block bob %}{{ super() }}{% endblock bob %}"),
+    ]).unwrap();
+
+    let result = tera.render("child", &Context::new());
+
+    assert_eq!(result.unwrap(), "1 - Hey".to_string());
+}
+
+#[test]
+fn macro_can_load_macro_from_macro_files() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("submacros", "{% macro emma() %}Emma{% endmacro emma %}"),
+        ("macros", "{% import \"submacros\" as submacros %}{% macro hommage() %}{{ submacros::emma() }} was an amazing person!{% endmacro hommage %}"),
+        ("parent", "{% block main %}Someone was a terrible person!{% endblock main %} Don't you think?"),
+        ("child", "{% extends \"parent\" %}{% import \"macros\" as macros %}{% block main %}{{ macros::hommage() }}{% endblock main %}")
+    ]).unwrap();
+
+    let result = tera.render("child", &Context::new());
+    //println!("{:#?}", result);
+    assert_eq!(result.unwrap(), "Emma was an amazing person! Don't you think?".to_string());
+}
+
+#[test]
+fn macro_can_access_global_context() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("parent", r#"{% import "macros" as macros %}{{ macros::test_global() }}"#),
+        ("macros", r#"{% macro test_global() %}{% set_global value1 = "42" %}{% for i in range(end=1) %}{% set_global value2 = " is the truth." %}{% endfor %}{{ value1 }}{% endmacro test_global %}"#)
+    ]).unwrap();
+
+    let result = tera.render("parent", &Context::new());
+    assert_eq!(result.unwrap(), "42".to_string());
+}
+
+#[test]
+fn template_cant_access_macros_context() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("parent", r#"{% import "macros" as macros %}{{ macros::empty() }}{{ quote | default(value="I'd rather have roses on my table than diamonds on my neck.") }}"#),
+        ("macros", r#"{% macro empty() %}{% set_global quote = "This should not reachable from the calling template!" %}{% endmacro empty %}"#)
+    ]).unwrap();
+
+    let result = tera.render("parent", &Context::new());
+    assert_eq!(result.unwrap(), "I'd rather have roses on my table than diamonds on my neck.");
+}
+
+#[test]
+fn parent_macro_cant_access_child_macro_context() {
+    let mut tera = Tera::default();
+    tera.add_raw_templates(vec![
+        ("parent", "{% import \"macros\" as macros %}{{ macros::test_global() }}"),
+        ("macros", r#"{% import "moremacros" as moremacros %}{% macro test_global() %}{% set_global value1 = "ACAB" %}{{ moremacros::another_one() }}{{ value1 }}-{{ value2 | default(value="ACAB") }}{% endmacro test_global %}"#),
+        ("moremacros", r#"{% macro another_one() %}{% set_global value2 = "1312" %}{% endmacro another_one %}"#)
+    ]).unwrap();
+
+    let result = tera.render("parent", &Context::new());
+    assert_eq!(result.unwrap(), "ACAB-ACAB".to_string());
+}
diff --git a/vendor/tera/src/renderer/tests/mod.rs b/vendor/tera/src/renderer/tests/mod.rs
new file mode 100644 (file)
index 0000000..5f6bb9c
--- /dev/null
@@ -0,0 +1,32 @@
+use serde_derive::Serialize;
+
+mod basic;
+mod errors;
+mod inheritance;
+mod macros;
+mod square_brackets;
+mod whitespace;
+
+#[allow(dead_code)]
+#[derive(Debug, Serialize)]
+pub struct NestedObject {
+    pub label: String,
+    pub parent: Option<Box<NestedObject>>,
+    pub numbers: Vec<usize>,
+}
+
+#[derive(Debug, Serialize)]
+pub struct Review {
+    title: String,
+    paragraphs: Vec<String>,
+}
+
+impl Review {
+    #[allow(dead_code)]
+    pub fn new() -> Review {
+        Review {
+            title: "My review".to_owned(),
+            paragraphs: vec!["A".to_owned(), "B".to_owned(), "C".to_owned()],
+        }
+    }
+}
diff --git a/vendor/tera/src/renderer/tests/square_brackets.rs b/vendor/tera/src/renderer/tests/square_brackets.rs
new file mode 100644 (file)
index 0000000..cac8d9d
--- /dev/null
@@ -0,0 +1,94 @@
+use std::collections::HashMap;
+
+use crate::context::Context;
+use crate::tera::Tera;
+use serde_derive::Serialize;
+
+#[derive(Serialize)]
+struct Test {
+    a: String,
+    b: String,
+    c: Vec<String>,
+}
+
+#[test]
+fn var_access_by_square_brackets() {
+    let mut context = Context::new();
+    context.insert(
+        "var",
+        &Test { a: "hi".into(), b: "i_am_actually_b".into(), c: vec!["fred".into()] },
+    );
+    context.insert("zero", &0);
+    context.insert("a", "b");
+
+    let mut map = HashMap::new();
+    map.insert("true", "yes");
+    map.insert("false", "no");
+    map.insert("with space", "works");
+    map.insert("with/slash", "works");
+    let mut deep_map = HashMap::new();
+    deep_map.insert("inner_map", &map);
+    context.insert("map", &map);
+    context.insert("deep_map", &deep_map);
+    context.insert("bool_vec", &vec!["true", "false"]);
+
+    let inputs = vec![
+        ("{{var.a}}", "hi"),
+        ("{{var['a']}}", "hi"),
+        ("{{var[\"a\"]}}", "hi"),
+        ("{{var['c'][0]}}", "fred"),
+        ("{{var['c'][zero]}}", "fred"),
+        ("{{var[a]}}", "i_am_actually_b"),
+        ("{{map['with space']}}", "works"),
+        ("{{map['with/slash']}}", "works"),
+        ("{{deep_map['inner_map'][bool_vec[zero]]}}", "yes"),
+    ];
+
+    for (input, expected) in inputs {
+        println!("{:?} -> {:?}", input, expected);
+        assert_eq!(Tera::one_off(input, &context, true).unwrap(), expected);
+    }
+}
+
+#[test]
+fn var_access_by_square_brackets_errors() {
+    let mut context = Context::new();
+    context.insert("var", &Test { a: "hi".into(), b: "there".into(), c: vec![] });
+    let t = Tera::one_off("{{var[csd]}}", &context, true);
+    assert!(t.is_err(), "Access of csd should be impossible");
+}
+
+// https://github.com/Keats/tera/issues/334
+#[test]
+fn var_access_by_loop_index() {
+    let context = Context::new();
+    let res = Tera::one_off(
+        r#"
+{% set ics = ["fa-rocket","fa-paper-plane","fa-diamond","fa-signal"] %}
+{% for a in ics %}
+{{ ics[loop.index0] }}
+{% endfor %}
+    "#,
+        &context,
+        true,
+    );
+    assert!(res.is_ok());
+}
+
+// https://github.com/Keats/tera/issues/334
+#[test]
+fn var_access_by_loop_index_with_set() {
+    let context = Context::new();
+    let res = Tera::one_off(
+        r#"
+{% set ics = ["fa-rocket","fa-paper-plane","fa-diamond","fa-signal"] %}
+{% for a in ics %}
+    {% set i = loop.index - 1 %}
+    {{ ics[i] }}
+{% endfor %}
+    "#,
+        &context,
+        true,
+    );
+    assert!(res.is_ok());
+}
diff --git a/vendor/tera/src/renderer/tests/whitespace.rs b/vendor/tera/src/renderer/tests/whitespace.rs
new file mode 100644 (file)
index 0000000..92ab624
--- /dev/null
@@ -0,0 +1,118 @@
+use crate::context::Context;
+use crate::tera::Tera;
+
+#[test]
+fn can_remove_whitespace_basic() {
+    let mut context = Context::new();
+    context.insert("numbers", &vec![1, 2, 3]);
+
+    let inputs = vec![
+        ("  {%- for n in numbers %}{{n}}{% endfor -%} ", "123"),
+        ("{%- for n in numbers %} {{n}}{%- endfor -%} ", " 1 2 3"),
+        ("{%- for n in numbers -%}\n {{n}}\n {%- endfor -%} ", "123"),
+        ("{%- if true -%}\n {{numbers}}\n {%- endif -%} ", "[1, 2, 3]"),
+        ("{%- if false -%}\n {{numbers}}\n {% else %} Nope{%- endif -%} ", " Nope"),
+        ("  {%- if false -%}\n {{numbers}}\n {% else -%} Nope {%- endif -%} ", "Nope"),
+        ("  {%- if false -%}\n {{numbers}}\n {% elif true -%} Nope {%- endif -%} ", "Nope"),
+        ("  {%- if false -%}\n {{numbers}}\n {% elif false -%} Nope {% else %} else {%- endif -%} ", " else"),
+        ("  {%- set var = 2 -%} {{var}}", "2"),
+        ("  {% set var = 2 -%} {{var}}", "  2"),
+        (" {% raw -%} {{2}} {% endraw -%} ", " {{2}} "),
+        ("  {% filter upper -%} hey {%- endfilter -%} ", "  HEY"),
+        ("  {{ \"hello\" -}} ", "  hello"),
+        ("  {{- \"hello\" }} ", "hello "),
+        ("  {{- \"hello\" -}} ", "hello"),
+        // Comments are not rendered so it should be just whitespace if anything
+        ("  {#- \"hello\" -#} ", ""),
+        ("  {# \"hello\" -#} ", "  "),
+        ("  {#- \"hello\" #} ", " "),
+    ];
+
+    for (input, expected) in inputs {
+        let mut tera = Tera::default();
+        tera.add_raw_template("tpl", input).unwrap();
+        println!("{} -> {:?}", input, expected);
+        assert_eq!(tera.render("tpl", &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn can_remove_whitespace_include() {
+    let mut context = Context::new();
+    context.insert("numbers", &vec![1, 2, 3]);
+
+    let inputs = vec![
+        (r#"Hi {%- include "include" -%} "#, "HiIncluded"),
+        (r#"Hi {% include "include" -%} "#, "Hi Included"),
+        (r#"Hi {% include "include" %} "#, "Hi Included "),
+    ];
+
+    for (input, expected) in inputs {
+        let mut tera = Tera::default();
+        tera.add_raw_templates(vec![("include", "Included"), ("tpl", input)]).unwrap();
+        assert_eq!(tera.render("tpl", &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn can_remove_whitespace_macros() {
+    let mut context = Context::new();
+    context.insert("numbers", &vec![1, 2, 3]);
+
+    let inputs = vec![
+        (r#" {%- import "macros" as macros -%} {{macros::hey()}}"#, "Hey!"),
+        (r#" {% import "macros" as macros %} {{macros::hey()}}"#, "Hey!"),
+        (r#" {%- import "macros" as macros %} {%- set hey = macros::hey() -%} {{hey}}"#, "Hey!"),
+    ];
+
+    for (input, expected) in inputs {
+        let mut tera = Tera::default();
+        tera.add_raw_templates(vec![
+            ("macros", "{% macro hey() -%} Hey! {%- endmacro %}"),
+            ("tpl", input),
+        ])
+        .unwrap();
+        assert_eq!(tera.render("tpl", &context).unwrap(), expected);
+    }
+}
+
+#[test]
+fn can_remove_whitespace_inheritance() {
+    let mut context = Context::new();
+    context.insert("numbers", &vec![1, 2, 3]);
+
+    let inputs = vec![
+        (r#"{%- extends "base" -%} {% block content %}{{super()}}{% endblock %}"#, " Hey! "),
+        (r#"{%- extends "base" -%} {% block content -%}{{super()}}{%- endblock %}"#, " Hey! "),
+        (r#"{%- extends "base" %} {%- block content -%}{{super()}}{%- endblock -%} "#, " Hey! "),
+    ];
+
+    for (input, expected) in inputs {
+        let mut tera = Tera::default();
+        tera.add_raw_templates(vec![
+            ("base", "{% block content %} Hey! {% endblock %}"),
+            ("tpl", input),
+        ])
+        .unwrap();
+        assert_eq!(tera.render("tpl", &context).unwrap(), expected);
+    }
+}
+
+// https://github.com/Keats/tera/issues/475
+#[test]
+fn works_with_filter_section() {
+    let mut context = Context::new();
+    context.insert("d", "d");
+    let input = r#"{% filter upper %}  {{ "c" }}   d{% endfilter %}"#;
+    let res = Tera::one_off(input, &context, true).unwrap();
+    assert_eq!(res, "  C   D");
+}
+
+#[test]
+fn make_sure_not_to_delete_whitespaces() {
+    let mut context = Context::new();
+    context.insert("d", "d");
+    let input = r#"{% raw %}    yaml_test:     {% endraw %}"#;
+    let res = Tera::one_off(input, &context, true).unwrap();
+    assert_eq!(res, "    yaml_test:     ");
+}
diff --git a/vendor/tera/src/template.rs b/vendor/tera/src/template.rs
new file mode 100644 (file)
index 0000000..2eca0e1
--- /dev/null
@@ -0,0 +1,170 @@
+use std::collections::HashMap;
+
+use crate::errors::{Error, Result};
+use crate::parser::ast::{Block, MacroDefinition, Node};
+use crate::parser::{parse, remove_whitespace};
+
+/// This is the parsed equivalent of a template file.
+/// It also does some pre-processing to ensure it does as little as possible at runtime
+/// Not meant to be used directly.
+#[derive(Debug, Clone)]
+pub struct Template {
+    /// Name of the template, usually very similar to the path
+    pub name: String,
+    /// Original path of the file. A template doesn't necessarily have
+    /// a file associated with it though so it's optional.
+    pub path: Option<String>,
+    /// Parsed AST, after whitespace removal
+    pub ast: Vec<Node>,
+    /// Whether this template came from a call to `Tera::extend`, so we do
+    /// not remove it when we are doing a template reload
+    pub from_extend: bool,
+
+    /// Macros defined in that file: name -> definition ast
+    pub macros: HashMap<String, MacroDefinition>,
+    /// (filename, namespace) for the macros imported in that file
+    pub imported_macro_files: Vec<(String, String)>,
+
+    /// Only used during initial parsing. Rendering will use `self.parents`
+    pub parent: Option<String>,
+    /// Only used during initial parsing. Rendering will use `self.blocks_definitions`
+    pub blocks: HashMap<String, Block>,
+
+    // Below are filled when all templates have been parsed so we know the full hierarchy of templates
+    /// The full list of parent templates
+    pub parents: Vec<String>,
+    /// The definition of all the blocks for the current template and the definition of those blocks
+    /// in parent templates if there are some.
+    /// Needed for super() to work without having to find them each time.
+    /// The type corresponds to the following `block_name -> [(template name, definition)]`
+    /// The order of the Vec is from the first in hierarchy to the current template and the template
+    /// name is needed in order to load its macros if necessary.
+    pub blocks_definitions: HashMap<String, Vec<(String, Block)>>,
+}
+
+impl Template {
+    /// Parse the template string given
+    pub fn new(tpl_name: &str, tpl_path: Option<String>, input: &str) -> Result<Template> {
+        let ast = remove_whitespace(parse(input)?, None);
+
+        // First we want all the blocks used in that template
+        // This is recursive as we can have blocks inside blocks
+        let mut blocks = HashMap::new();
+        fn find_blocks(ast: &[Node], blocks: &mut HashMap<String, Block>) -> Result<()> {
+            for node in ast {
+                match *node {
+                    Node::Block(_, ref block, _) => {
+                        if blocks.contains_key(&block.name) {
+                            return Err(Error::msg(format!(
+                                "Block `{}` is duplicated",
+                                block.name
+                            )));
+                        }
+
+                        blocks.insert(block.name.to_string(), block.clone());
+                        find_blocks(&block.body, blocks)?;
+                    }
+                    _ => continue,
+                };
+            }
+
+            Ok(())
+        }
+        find_blocks(&ast, &mut blocks)?;
+
+        // And now we find the potential parent and everything macro related (definition, import)
+        let mut macros = HashMap::new();
+        let mut imported_macro_files = vec![];
+        let mut parent = None;
+
+        for node in &ast {
+            match *node {
+                Node::Extends(_, ref name) => parent = Some(name.to_string()),
+                Node::MacroDefinition(_, ref macro_def, _) => {
+                    if macros.contains_key(&macro_def.name) {
+                        return Err(Error::msg(format!(
+                            "Macro `{}` is duplicated",
+                            macro_def.name
+                        )));
+                    }
+                    macros.insert(macro_def.name.clone(), macro_def.clone());
+                }
+                Node::ImportMacro(_, ref tpl_name, ref namespace) => {
+                    imported_macro_files.push((tpl_name.to_string(), namespace.to_string()));
+                }
+                _ => continue,
+            }
+        }
+
+        Ok(Template {
+            name: tpl_name.to_string(),
+            path: tpl_path,
+            ast,
+            parent,
+            blocks,
+            macros,
+            imported_macro_files,
+            parents: vec![],
+            blocks_definitions: HashMap::new(),
+            from_extend: false,
+        })
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::Template;
+
+    #[test]
+    fn can_parse_ok_template() {
+        Template::new("hello", None, "Hello {{ world }}.").unwrap();
+    }
+
+    #[test]
+    fn can_find_parent_template() {
+        let tpl = Template::new("hello", None, "{% extends \"base.html\" %}").unwrap();
+
+        assert_eq!(tpl.parent.unwrap(), "base.html".to_string());
+    }
+
+    #[test]
+    fn can_find_blocks() {
+        let tpl = Template::new(
+            "hello",
+            None,
+            "{% extends \"base.html\" %}{% block hey %}{% endblock hey %}",
+        )
+        .unwrap();
+
+        assert_eq!(tpl.parent.unwrap(), "base.html".to_string());
+        assert_eq!(tpl.blocks.contains_key("hey"), true);
+    }
+
+    #[test]
+    fn can_find_nested_blocks() {
+        let tpl = Template::new(
+            "hello",
+            None,
+            "{% extends \"base.html\" %}{% block hey %}{% block extrahey %}{% endblock extrahey %}{% endblock hey %}",
+        ).unwrap();
+
+        assert_eq!(tpl.parent.unwrap(), "base.html".to_string());
+        assert_eq!(tpl.blocks.contains_key("hey"), true);
+        assert_eq!(tpl.blocks.contains_key("extrahey"), true);
+    }
+
+    #[test]
+    fn can_find_macros() {
+        let tpl = Template::new("hello", None, "{% macro hey() %}{% endmacro hey %}").unwrap();
+        assert_eq!(tpl.macros.contains_key("hey"), true);
+    }
+
+    #[test]
+    fn can_find_imported_macros() {
+        let tpl = Template::new("hello", None, "{% import \"macros.html\" as macros %}").unwrap();
+        assert_eq!(
+            tpl.imported_macro_files,
+            vec![("macros.html".to_string(), "macros".to_string())]
+        );
+    }
+}
diff --git a/vendor/tera/src/tera.rs b/vendor/tera/src/tera.rs
new file mode 100644 (file)
index 0000000..7614f7c
--- /dev/null
@@ -0,0 +1,1183 @@
+use std::collections::HashMap;
+use std::fmt;
+use std::fs::File;
+use std::io::prelude::*;
+use std::path::Path;
+use std::sync::Arc;
+
+use globwalk::glob_builder;
+
+use crate::builtins::filters::{array, common, number, object, string, Filter};
+use crate::builtins::functions::{self, Function};
+use crate::builtins::testers::{self, Test};
+use crate::context::Context;
+use crate::errors::{Error, Result};
+use crate::renderer::Renderer;
+use crate::template::Template;
+use crate::utils::escape_html;
+
+/// The of the the template used for `Tera::render_str` and `Tera::one_off`.
+const ONE_OFF_TEMPLATE_NAME: &str = "__tera_one_off";
+
+/// The escape function type definition
+pub type EscapeFn = fn(&str) -> String;
+
+/// The main point of interaction in this library.
+#[derive(Clone)]
+pub struct Tera {
+    // The glob used in `Tera::new`, None if Tera was instantiated differently
+    #[doc(hidden)]
+    glob: Option<String>,
+    #[doc(hidden)]
+    pub templates: HashMap<String, Template>,
+    #[doc(hidden)]
+    pub filters: HashMap<String, Arc<dyn Filter>>,
+    #[doc(hidden)]
+    pub testers: HashMap<String, Arc<dyn Test>>,
+    #[doc(hidden)]
+    pub functions: HashMap<String, Arc<dyn Function>>,
+    // Which extensions does Tera automatically autoescape on.
+    // Defaults to [".html", ".htm", ".xml"]
+    #[doc(hidden)]
+    pub autoescape_suffixes: Vec<&'static str>,
+    #[doc(hidden)]
+    escape_fn: EscapeFn,
+}
+
+impl Tera {
+    fn create(dir: &str, parse_only: bool) -> Result<Tera> {
+        if dir.find('*').is_none() {
+            return Err(Error::msg(format!(
+                "Tera expects a glob as input, no * were found in `{}`",
+                dir
+            )));
+        }
+
+        let mut tera = Tera {
+            glob: Some(dir.to_string()),
+            templates: HashMap::new(),
+            filters: HashMap::new(),
+            functions: HashMap::new(),
+            testers: HashMap::new(),
+            autoescape_suffixes: vec![".html", ".htm", ".xml"],
+            escape_fn: escape_html,
+        };
+
+        tera.load_from_glob()?;
+        if !parse_only {
+            tera.build_inheritance_chains()?;
+            tera.check_macro_files()?;
+        }
+        tera.register_tera_filters();
+        tera.register_tera_testers();
+        tera.register_tera_functions();
+        Ok(tera)
+    }
+
+    /// Create a new instance of Tera, containing all the parsed templates found in the `dir` glob
+    ///
+    ///```ignore
+    ///match Tera::new("templates/**/*") {
+    ///    Ok(t) => t,
+    ///    Err(e) => {
+    ///        println!("Parsing error(s): {}", e);
+    ///        ::std::process::exit(1);
+    ///    }
+    ///}
+    ///```
+    pub fn new(dir: &str) -> Result<Tera> {
+        Self::create(dir, false)
+    }
+
+    /// Create a new instance of Tera, containing all the parsed templates found in the `dir` glob
+    /// The difference with `Tera::new` is that it won't build the inheritance chains automatically
+    /// so you are free to modify the templates if you need to.
+    /// You will NOT get a working Tera instance using `Tera::parse`, you will need to call
+    /// `tera.build_inheritance_chains()` to make it usable
+    ///
+    ///```ignore
+    ///let mut tera = match Tera::parse("templates/**/*") {
+    ///    Ok(t) => t,
+    ///    Err(e) => {
+    ///        println!("Parsing error(s): {}", e);
+    ///        ::std::process::exit(1);
+    ///    }
+    ///};
+    ///tera.build_inheritance_chains()?;
+    ///```
+    pub fn parse(dir: &str) -> Result<Tera> {
+        Self::create(dir, true)
+    }
+
+    /// Loads all the templates found in the glob that was given to Tera::new
+    fn load_from_glob(&mut self) -> Result<()> {
+        if self.glob.is_none() {
+            return Err(Error::msg("Tera can only load from glob if a glob is provided"));
+        }
+        // We want to preserve templates that have been added through
+        // Tera::extend so we only keep those
+        self.templates = self
+            .templates
+            .iter()
+            .filter(|&(_, t)| t.from_extend)
+            .map(|(n, t)| (n.clone(), t.clone())) // TODO: avoid that clone
+            .collect();
+
+        let mut errors = String::new();
+
+        let dir = self.glob.clone().unwrap();
+        // We clean the filename by removing the dir given
+        // to Tera so users don't have to prefix everytime
+        let mut parent_dir = dir.split_at(dir.find('*').unwrap()).0;
+        // Remove `./` from the glob if used as it would cause an error in strip_prefix
+        if parent_dir.starts_with("./") {
+            parent_dir = &parent_dir[2..];
+        }
+
+        // We are parsing all the templates on instantiation
+        for entry in glob_builder(&dir)
+            .follow_links(true)
+            .build()
+            .unwrap()
+            .filter_map(std::result::Result::ok)
+        {
+            let mut path = entry.into_path();
+            // We only care about actual files
+            if path.is_file() {
+                if path.starts_with("./") {
+                    path = path.strip_prefix("./").unwrap().to_path_buf();
+                }
+
+                let filepath = path
+                    .strip_prefix(&parent_dir)
+                    .unwrap()
+                    .to_string_lossy()
+                    // unify on forward slash
+                    .replace("\\", "/");
+
+                if let Err(e) = self.add_file(Some(&filepath), path) {
+                    use std::error::Error;
+
+                    errors += &format!("\n* {}", e);
+                    let mut cause = e.source();
+                    while let Some(e) = cause {
+                        errors += &format!("\n{}", e);
+                        cause = e.source();
+                    }
+                }
+            }
+        }
+
+        if !errors.is_empty() {
+            return Err(Error::msg(errors));
+        }
+
+        Ok(())
+    }
+
+    // Add a template from a path: reads the file and parses it.
+    // This will return an error if the template is invalid and doesn't check the validity of
+    // inheritance chains.
+    fn add_file<P: AsRef<Path>>(&mut self, name: Option<&str>, path: P) -> Result<()> {
+        let path = path.as_ref();
+        let tpl_name = name.unwrap_or_else(|| path.to_str().unwrap());
+
+        let mut f = File::open(path)
+            .map_err(|e| Error::chain(format!("Couldn't open template '{:?}'", path), e))?;
+
+        let mut input = String::new();
+        f.read_to_string(&mut input)
+            .map_err(|e| Error::chain(format!("Failed to read template '{:?}'", path), e))?;
+
+        let tpl = Template::new(tpl_name, Some(path.to_str().unwrap().to_string()), &input)
+            .map_err(|e| Error::chain(format!("Failed to parse {:?}", path), e))?;
+
+        self.templates.insert(tpl_name.to_string(), tpl);
+        Ok(())
+    }
+
+    /// We need to know the hierarchy of templates to be able to render multiple extends level
+    /// This happens at compile-time to avoid checking it every time we want to render a template
+    /// This also checks for soundness issues in the inheritance chains, such as missing template or
+    /// circular extends.
+    /// It also builds the block inheritance chain and detects when super() is called in a place
+    /// where it can't possibly work
+    ///
+    /// You generally don't need to call that yourself, unless you used `Tera::parse`
+    pub fn build_inheritance_chains(&mut self) -> Result<()> {
+        // Recursive fn that finds all the parents and put them in an ordered Vec from closest to first parent
+        // parent template
+        fn build_chain(
+            templates: &HashMap<String, Template>,
+            start: &Template,
+            template: &Template,
+            mut parents: Vec<String>,
+        ) -> Result<Vec<String>> {
+            if !parents.is_empty() && start.name == template.name {
+                return Err(Error::circular_extend(&start.name, parents));
+            }
+
+            match template.parent {
+                Some(ref p) => match templates.get(p) {
+                    Some(parent) => {
+                        parents.push(parent.name.clone());
+                        build_chain(templates, start, parent, parents)
+                    }
+                    None => Err(Error::missing_parent(&template.name, &p)),
+                },
+                None => Ok(parents),
+            }
+        }
+
+        // TODO: if we can rewrite the 2 loops below to be only one loop, that'd be great
+        let mut tpl_parents = HashMap::new();
+        let mut tpl_block_definitions = HashMap::new();
+        for (name, template) in &self.templates {
+            if template.parent.is_none() && template.blocks.is_empty() {
+                continue;
+            }
+
+            let parents = build_chain(&self.templates, template, template, vec![])?;
+
+            let mut blocks_definitions = HashMap::new();
+            for (block_name, def) in &template.blocks {
+                // push our own block first
+                let mut definitions = vec![(template.name.clone(), def.clone())];
+
+                // and then see if our parents have it
+                for parent in &parents {
+                    let t = self.get_template(parent)?;
+
+                    if let Some(b) = t.blocks.get(block_name) {
+                        definitions.push((t.name.clone(), b.clone()));
+                    }
+                }
+                blocks_definitions.insert(block_name.clone(), definitions);
+            }
+            tpl_parents.insert(name.clone(), parents);
+            tpl_block_definitions.insert(name.clone(), blocks_definitions);
+        }
+
+        for template in self.templates.values_mut() {
+            // Simple template: no inheritance or blocks -> nothing to do
+            if template.parent.is_none() && template.blocks.is_empty() {
+                continue;
+            }
+
+            template.parents = match tpl_parents.remove(&template.name) {
+                Some(parents) => parents,
+                None => vec![],
+            };
+            template.blocks_definitions = match tpl_block_definitions.remove(&template.name) {
+                Some(blocks) => blocks,
+                None => HashMap::new(),
+            };
+        }
+
+        Ok(())
+    }
+
+    /// We keep track of macro files loaded in each Template so we can know whether one or them
+    /// is missing and error accordingly before the user tries to render a template.
+    ///
+    /// As with `self::build_inheritance_chains`, you don't usually need to call that yourself.
+    pub fn check_macro_files(&self) -> Result<()> {
+        for template in self.templates.values() {
+            for &(ref tpl_name, _) in &template.imported_macro_files {
+                if !self.templates.contains_key(tpl_name) {
+                    return Err(Error::msg(format!(
+                        "Template `{}` loads macros from `{}` which isn't present in Tera",
+                        template.name, tpl_name
+                    )));
+                }
+            }
+        }
+
+        Ok(())
+    }
+
+    /// Renders a Tera template given a `tera::Context`,
+    ///
+    /// To render a template with an empty context, simply pass a new `tera::Context` object
+    ///
+    /// ```rust,ignore
+    /// // Rendering a template with a normal context
+    /// let mut context = Context::new();
+    /// context.insert("age", 18);
+    /// tera.render("hello.html", context);
+    /// // Rendering a template with an empty context
+    /// tera.render("hello.html", Context::new());
+    /// ```
+    pub fn render(&self, template_name: &str, context: &Context) -> Result<String> {
+        let template = self.get_template(template_name)?;
+        let renderer = Renderer::new(template, self, context);
+        renderer.render()
+    }
+
+    /// Renders a Tera template given a `tera::Context` to a [std::io::Write],
+    ///
+    /// The only difference from [Self::render] is that this version doesn't convert buffer to a String,
+    /// allowing to render directly to anything that implements [std::io::Write].
+    ///
+    /// Any i/o error will be reported in the result.
+    ///
+    /// ```rust,ignore
+    /// // Rendering a template to an internal buffer
+    /// let mut buffer = Vec::new();
+    /// let mut context = Context::new();
+    /// context.insert("age", 18);
+    /// tera.render_to("hello.html", context, &mut buffer);
+    /// ```
+    pub fn render_to(
+        &self,
+        template_name: &str,
+        context: &Context,
+        write: impl Write,
+    ) -> Result<()> {
+        let template = self.get_template(template_name)?;
+        let renderer = Renderer::new(template, self, context);
+        renderer.render_to(write)
+    }
+
+    /// Renders a one off template (for example a template coming from a user
+    /// input) given a `Context` and an instance of Tera. This allows you to
+    /// render templates using custom filters or functions.
+    ///
+    /// Any errors will mention the `__tera_one_off` template: this is the name
+    /// given to the template by Tera.
+    ///
+    /// ```rust,ignore
+    /// let mut context = Context::new();
+    /// context.insert("greeting", &"Hello");
+    /// let string = tera.render_str("{{ greeting }} World!", &context)?;
+    /// assert_eq!(string, "Hello World!");
+    /// ```
+    pub fn render_str(&mut self, input: &str, context: &Context) -> Result<String> {
+        self.add_raw_template(ONE_OFF_TEMPLATE_NAME, input)?;
+        let result = self.render(ONE_OFF_TEMPLATE_NAME, &context);
+        self.templates.remove(ONE_OFF_TEMPLATE_NAME);
+        result
+    }
+
+    /// Renders a one off template (for example a template coming from a user input) given a `Context`
+    ///
+    /// This creates a separate instance of Tera with no possibilities of adding custom filters
+    /// or testers, parses the template and render it immediately.
+    /// Any errors will mention the `__tera_one_off` template: this is the name given to the template by
+    /// Tera
+    ///
+    /// ```rust,ignore
+    /// let mut context = Context::new();
+    /// context.insert("greeting", &"hello");
+    /// Tera::one_off("{{ greeting }} world", &context, true);
+    /// ```
+    pub fn one_off(input: &str, context: &Context, autoescape: bool) -> Result<String> {
+        let mut tera = Tera::default();
+
+        if autoescape {
+            tera.autoescape_on(vec![ONE_OFF_TEMPLATE_NAME]);
+        }
+
+        tera.render_str(input, context)
+    }
+
+    #[doc(hidden)]
+    #[inline]
+    pub fn get_template(&self, template_name: &str) -> Result<&Template> {
+        match self.templates.get(template_name) {
+            Some(tpl) => Ok(tpl),
+            None => Err(Error::template_not_found(template_name)),
+        }
+    }
+
+    /// Returns an iterator over the names of all registered templates in an
+    /// unspecified order.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use tera::Tera;
+    ///
+    /// let mut tera = Tera::default();
+    /// tera.add_raw_template("foo", "{{ hello }}");
+    /// tera.add_raw_template("another-one.html", "contents go here");
+    ///
+    /// let names: Vec<_> = tera.get_template_names().collect();
+    /// assert_eq!(names.len(), 2);
+    /// assert!(names.contains(&"foo"));
+    /// assert!(names.contains(&"another-one.html"));
+    /// ```
+    #[inline]
+    pub fn get_template_names(&self) -> impl Iterator<Item = &str> {
+        self.templates.keys().map(|s| s.as_str())
+    }
+
+    /// Add a single template to the Tera instance
+    ///
+    /// This will error if the inheritance chain can't be built, such as adding a child
+    /// template without the parent one.
+    /// If you want to add several templates, use [Tera::add_templates](struct.Tera.html#method.add_raw_templates)
+    ///
+    /// ```rust,ignore
+    /// tera.add_raw_template("new.html", "Blabla");
+    /// ```
+    pub fn add_raw_template(&mut self, name: &str, content: &str) -> Result<()> {
+        let tpl = Template::new(name, None, content)
+            .map_err(|e| Error::chain(format!("Failed to parse '{}'", name), e))?;
+        self.templates.insert(name.to_string(), tpl);
+        self.build_inheritance_chains()?;
+        self.check_macro_files()?;
+        Ok(())
+    }
+
+    /// Add all the templates given to the Tera instance
+    ///
+    /// This will error if the inheritance chain can't be built, such as adding a child
+    /// template without the parent one.
+    ///
+    /// ```rust,ignore
+    /// tera.add_raw_templates(vec![
+    ///     ("new.html", "blabla"),
+    ///     ("new2.html", "hello"),
+    /// ]);
+    /// ```
+    pub fn add_raw_templates<I, N, C>(&mut self, templates: I) -> Result<()>
+    where
+        I: IntoIterator<Item = (N, C)>,
+        N: AsRef<str>,
+        C: AsRef<str>,
+    {
+        for (name, content) in templates {
+            let name = name.as_ref();
+            let tpl = Template::new(name, None, content.as_ref())
+                .map_err(|e| Error::chain(format!("Failed to parse '{}'", name), e))?;
+            self.templates.insert(name.to_string(), tpl);
+        }
+        self.build_inheritance_chains()?;
+        self.check_macro_files()?;
+        Ok(())
+    }
+
+    /// Add a single template from a path to the Tera instance. The default name for the template is
+    /// the path given, but this can be renamed with the `name` parameter
+    ///
+    /// This will error if the inheritance chain can't be built, such as adding a child
+    /// template without the parent one.
+    /// If you want to add several file, use [Tera::add_template_files](struct.Tera.html#method.add_template_files)
+    ///
+    /// ```rust,ignore
+    /// // Use path as name
+    /// tera.add_template_file(path, None);
+    /// // Rename
+    /// tera.add_template_file(path, Some("index"));
+    /// ```
+    pub fn add_template_file<P: AsRef<Path>>(&mut self, path: P, name: Option<&str>) -> Result<()> {
+        self.add_file(name, path)?;
+        self.build_inheritance_chains()?;
+        self.check_macro_files()?;
+        Ok(())
+    }
+
+    /// Add several templates from paths to the Tera instance. The default name for the template is
+    /// the path given, but this can be renamed with the second parameter of the tuple
+    ///
+    /// This will error if the inheritance chain can't be built, such as adding a child
+    /// template without the parent one.
+    ///
+    /// ```rust,ignore
+    /// tera.add_template_files(vec![
+    ///     (path1, None), // this template will have the value of path1 as name
+    ///     (path2, Some("hey")), // this template will have `hey` as name
+    /// ]);
+    /// ```
+    pub fn add_template_files<I, P, N>(&mut self, files: I) -> Result<()>
+    where
+        I: IntoIterator<Item = (P, Option<N>)>,
+        P: AsRef<Path>,
+        N: AsRef<str>,
+    {
+        for (path, name) in files {
+            self.add_file(name.as_ref().map(AsRef::as_ref), path)?;
+        }
+        self.build_inheritance_chains()?;
+        self.check_macro_files()?;
+        Ok(())
+    }
+
+    #[doc(hidden)]
+    #[inline]
+    pub fn get_filter(&self, filter_name: &str) -> Result<&dyn Filter> {
+        match self.filters.get(filter_name) {
+            Some(fil) => Ok(&**fil),
+            None => Err(Error::filter_not_found(filter_name)),
+        }
+    }
+
+    /// Register a filter with Tera.
+    ///
+    /// If a filter with that name already exists, it will be overwritten
+    ///
+    /// ```rust,ignore
+    /// tera.register_filter("upper", string::upper);
+    /// ```
+    pub fn register_filter<F: Filter + 'static>(&mut self, name: &str, filter: F) {
+        self.filters.insert(name.to_string(), Arc::new(filter));
+    }
+
+    #[doc(hidden)]
+    #[inline]
+    pub fn get_tester(&self, tester_name: &str) -> Result<&dyn Test> {
+        match self.testers.get(tester_name) {
+            Some(t) => Ok(&**t),
+            None => Err(Error::test_not_found(tester_name)),
+        }
+    }
+
+    /// Register a tester with Tera.
+    ///
+    /// If a tester with that name already exists, it will be overwritten
+    ///
+    /// ```rust,ignore
+    /// tera.register_tester("odd", testers::odd);
+    /// ```
+    pub fn register_tester<T: Test + 'static>(&mut self, name: &str, tester: T) {
+        self.testers.insert(name.to_string(), Arc::new(tester));
+    }
+
+    #[doc(hidden)]
+    #[inline]
+    pub fn get_function(&self, fn_name: &str) -> Result<&dyn Function> {
+        match self.functions.get(fn_name) {
+            Some(t) => Ok(&**t),
+            None => Err(Error::function_not_found(fn_name)),
+        }
+    }
+
+    /// Register a function with Tera.
+    ///
+    /// If a function with that name already exists, it will be overwritten
+    ///
+    /// ```rust,ignore
+    /// tera.register_function("range", range);
+    /// ```
+    pub fn register_function<F: Function + 'static>(&mut self, name: &str, function: F) {
+        self.functions.insert(name.to_string(), Arc::new(function));
+    }
+
+    fn register_tera_filters(&mut self) {
+        self.register_filter("upper", string::upper);
+        self.register_filter("lower", string::lower);
+        self.register_filter("trim", string::trim);
+        self.register_filter("trim_start", string::trim_start);
+        self.register_filter("trim_end", string::trim_end);
+        self.register_filter("trim_start_matches", string::trim_start_matches);
+        self.register_filter("trim_end_matches", string::trim_end_matches);
+        #[cfg(feature = "builtins")]
+        self.register_filter("truncate", string::truncate);
+        self.register_filter("wordcount", string::wordcount);
+        self.register_filter("replace", string::replace);
+        self.register_filter("capitalize", string::capitalize);
+        self.register_filter("title", string::title);
+        self.register_filter("linebreaksbr", string::linebreaksbr);
+        self.register_filter("striptags", string::striptags);
+        #[cfg(feature = "builtins")]
+        self.register_filter("urlencode", string::urlencode);
+        #[cfg(feature = "builtins")]
+        self.register_filter("urlencode_strict", string::urlencode_strict);
+        self.register_filter("escape", string::escape_html);
+        self.register_filter("escape_xml", string::escape_xml);
+        #[cfg(feature = "builtins")]
+        self.register_filter("slugify", string::slugify);
+        self.register_filter("addslashes", string::addslashes);
+        self.register_filter("split", string::split);
+        self.register_filter("int", string::int);
+        self.register_filter("float", string::float);
+
+        self.register_filter("first", array::first);
+        self.register_filter("last", array::last);
+        self.register_filter("nth", array::nth);
+        self.register_filter("join", array::join);
+        self.register_filter("sort", array::sort);
+        self.register_filter("unique", array::unique);
+        self.register_filter("slice", array::slice);
+        self.register_filter("group_by", array::group_by);
+        self.register_filter("filter", array::filter);
+        self.register_filter("map", array::map);
+        self.register_filter("concat", array::concat);
+
+        self.register_filter("pluralize", number::pluralize);
+        self.register_filter("round", number::round);
+
+        #[cfg(feature = "builtins")]
+        self.register_filter("filesizeformat", number::filesizeformat);
+
+        self.register_filter("length", common::length);
+        self.register_filter("reverse", common::reverse);
+        #[cfg(feature = "builtins")]
+        self.register_filter("date", common::date);
+        self.register_filter("json_encode", common::json_encode);
+        self.register_filter("as_str", common::as_str);
+
+        self.register_filter("get", object::get);
+    }
+
+    fn register_tera_testers(&mut self) {
+        self.register_tester("defined", testers::defined);
+        self.register_tester("undefined", testers::undefined);
+        self.register_tester("odd", testers::odd);
+        self.register_tester("even", testers::even);
+        self.register_tester("string", testers::string);
+        self.register_tester("number", testers::number);
+        self.register_tester("divisibleby", testers::divisible_by);
+        self.register_tester("iterable", testers::iterable);
+        self.register_tester("object", testers::object);
+        self.register_tester("starting_with", testers::starting_with);
+        self.register_tester("ending_with", testers::ending_with);
+        self.register_tester("containing", testers::containing);
+        self.register_tester("matching", testers::matching);
+    }
+
+    fn register_tera_functions(&mut self) {
+        self.register_function("range", functions::range);
+        #[cfg(feature = "builtins")]
+        self.register_function("now", functions::now);
+        self.register_function("throw", functions::throw);
+        #[cfg(feature = "builtins")]
+        self.register_function("get_random", functions::get_random);
+        self.register_function("get_env", functions::get_env);
+    }
+
+    /// Select which suffix(es) to automatically do HTML escaping on,
+    ///`[".html", ".htm", ".xml"]` by default.
+    ///
+    /// Only call this function if you wish to change the defaults.
+    ///
+    ///
+    ///```ignore
+    /// // escape only files ending with `.php.html`
+    /// tera.autoescape_on(vec![".php.html"]);
+    /// // disable autoescaping completely
+    /// tera.autoescape_on(vec![]);
+    ///```
+    pub fn autoescape_on(&mut self, suffixes: Vec<&'static str>) {
+        self.autoescape_suffixes = suffixes;
+    }
+
+    #[doc(hidden)]
+    #[inline]
+    pub fn get_escape_fn(&self) -> &EscapeFn {
+        &self.escape_fn
+    }
+
+    /// Set user-defined function which applied to a rendered content.
+    ///
+    ///```rust,ignore
+    /// fn escape_c_string(input: &str) -> String { ... }
+    ///
+    /// // make valid C string literal
+    /// tera.set_escape_fn(escape_c_string);
+    /// tera.add_raw_template("foo", "\"{{ content }}\"").unwrap();
+    /// tera.autoescape_on(vec!["foo"]);
+    /// let mut context = Context::new();
+    /// context.insert("content", &"Hello\n\'world\"!");
+    /// let result = tera.render("foo", &context).unwrap();
+    /// assert_eq!(result, r#""Hello\n\'world\"!""#);
+    ///```
+    pub fn set_escape_fn(&mut self, function: EscapeFn) {
+        self.escape_fn = function;
+    }
+
+    /// Reset escape function to default `tera::escape_html`.
+    pub fn reset_escape_fn(&mut self) {
+        self.escape_fn = escape_html;
+    }
+
+    /// Re-parse all templates found in the glob given to Tera
+    /// Use this when you are watching a directory and want to reload everything,
+    /// for example when a file is added.
+    ///
+    /// If you are adding templates without using a glob, we can't know when a template
+    /// is deleted, which would result in an error if we are trying to reload that file
+    pub fn full_reload(&mut self) -> Result<()> {
+        if self.glob.is_some() {
+            self.load_from_glob()?;
+        } else {
+            return Err(Error::msg("Reloading is only available if you are using a glob"));
+        }
+
+        self.build_inheritance_chains()?;
+        self.check_macro_files()
+    }
+
+    /// Use that method when you want to add a given Tera instance templates/filters/testers
+    /// to your own. If a template/filter/tester with the same name already exists in your instance,
+    /// it will not be overwritten.
+    ///
+    ///```rust,ignore
+    /// // add all the templates from FRAMEWORK_TERA
+    /// // except the ones that have an identical name to the ones in `my_tera`
+    /// my_tera.extend(&FRAMEWORK_TERA);
+    ///```
+    pub fn extend(&mut self, other: &Tera) -> Result<()> {
+        for (name, template) in &other.templates {
+            if !self.templates.contains_key(name) {
+                let mut tpl = template.clone();
+                tpl.from_extend = true;
+                self.templates.insert(name.to_string(), tpl);
+            }
+        }
+
+        for (name, filter) in &other.filters {
+            if !self.filters.contains_key(name) {
+                self.filters.insert(name.to_string(), filter.clone());
+            }
+        }
+
+        for (name, tester) in &other.testers {
+            if !self.testers.contains_key(name) {
+                self.testers.insert(name.to_string(), tester.clone());
+            }
+        }
+
+        self.build_inheritance_chains()?;
+        self.check_macro_files()
+    }
+}
+
+impl Default for Tera {
+    fn default() -> Tera {
+        let mut tera = Tera {
+            glob: None,
+            templates: HashMap::new(),
+            filters: HashMap::new(),
+            testers: HashMap::new(),
+            functions: HashMap::new(),
+            autoescape_suffixes: vec![".html", ".htm", ".xml"],
+            escape_fn: escape_html,
+        };
+
+        tera.register_tera_filters();
+        tera.register_tera_testers();
+        tera.register_tera_functions();
+        tera
+    }
+}
+
+// Needs a manual implementation since borrows in Fn's don't implement Debug.
+impl fmt::Debug for Tera {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Tera {{")?;
+        writeln!(f, "\n\ttemplates: [")?;
+
+        for template in self.templates.keys() {
+            writeln!(f, "\t\t{},", template)?;
+        }
+        write!(f, "\t]")?;
+        writeln!(f, "\n\tfilters: [")?;
+
+        for filter in self.filters.keys() {
+            writeln!(f, "\t\t{},", filter)?;
+        }
+        write!(f, "\t]")?;
+        writeln!(f, "\n\ttesters: [")?;
+
+        for tester in self.testers.keys() {
+            writeln!(f, "\t\t{},", tester)?;
+        }
+        writeln!(f, "\t]")?;
+
+        writeln!(f, "}}")
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use tempfile::tempdir;
+
+    use std::collections::HashMap;
+    use std::fs::File;
+
+    use super::Tera;
+    use crate::context::Context;
+    use serde_json::{json, Value as JsonValue};
+
+    #[test]
+    fn test_get_inheritance_chain() {
+        let mut tera = Tera::default();
+        tera.add_raw_templates(vec![
+            ("a", "{% extends \"b\" %}"),
+            ("b", "{% extends \"c\" %}"),
+            ("c", "{% extends \"d\" %}"),
+            ("d", ""),
+        ])
+        .unwrap();
+
+        assert_eq!(
+            tera.get_template("a").unwrap().parents,
+            vec!["b".to_string(), "c".to_string(), "d".to_string()]
+        );
+        assert_eq!(tera.get_template("b").unwrap().parents, vec!["c".to_string(), "d".to_string()]);
+        assert_eq!(tera.get_template("c").unwrap().parents, vec!["d".to_string()]);
+        assert_eq!(tera.get_template("d").unwrap().parents.len(), 0);
+    }
+
+    #[test]
+    fn test_missing_parent_template() {
+        let mut tera = Tera::default();
+        assert_eq!(
+            tera.add_raw_template("a", "{% extends \"b\" %}").unwrap_err().to_string(),
+            "Template \'a\' is inheriting from \'b\', which doesn\'t exist or isn\'t loaded."
+        );
+    }
+
+    #[test]
+    fn test_circular_extends() {
+        let mut tera = Tera::default();
+        let err = tera
+            .add_raw_templates(vec![("a", "{% extends \"b\" %}"), ("b", "{% extends \"a\" %}")])
+            .unwrap_err();
+
+        assert!(err.to_string().contains("Circular extend detected for template"));
+    }
+
+    #[test]
+    fn test_get_parent_blocks_definition() {
+        let mut tera = Tera::default();
+        tera.add_raw_templates(vec![
+            (
+                "grandparent",
+                "{% block hey %}hello{% endblock hey %} {% block ending %}sincerely{% endblock ending %}",
+            ),
+            (
+                "parent",
+                "{% extends \"grandparent\" %}{% block hey %}hi and grandma says {{ super() }}{% endblock hey %}",
+            ),
+            (
+                "child",
+                "{% extends \"parent\" %}{% block hey %}dad says {{ super() }}{% endblock hey %}{% block ending %}{{ super() }} with love{% endblock ending %}",
+            ),
+        ]).unwrap();
+
+        let hey_definitions =
+            tera.get_template("child").unwrap().blocks_definitions.get("hey").unwrap();
+        assert_eq!(hey_definitions.len(), 3);
+
+        let ending_definitions =
+            tera.get_template("child").unwrap().blocks_definitions.get("ending").unwrap();
+        assert_eq!(ending_definitions.len(), 2);
+    }
+
+    #[test]
+    fn test_get_parent_blocks_definition_nested_block() {
+        let mut tera = Tera::default();
+        tera.add_raw_templates(vec![
+            ("grandparent", "{% block hey %}hello{% endblock hey %}"),
+            (
+                "parent",
+                "{% extends \"grandparent\" %}{% block hey %}hi and grandma says {{ super() }} {% block ending %}sincerely{% endblock ending %}{% endblock hey %}",
+            ),
+            (
+                "child",
+                "{% extends \"parent\" %}{% block hey %}dad says {{ super() }}{% endblock hey %}{% block ending %}{{ super() }} with love{% endblock ending %}",
+            ),
+        ]).unwrap();
+
+        let hey_definitions =
+            tera.get_template("child").unwrap().blocks_definitions.get("hey").unwrap();
+        assert_eq!(hey_definitions.len(), 3);
+
+        let ending_definitions =
+            tera.get_template("parent").unwrap().blocks_definitions.get("ending").unwrap();
+        assert_eq!(ending_definitions.len(), 1);
+    }
+
+    #[test]
+    fn test_can_autoescape_one_off_template() {
+        let mut context = Context::new();
+        context.insert("greeting", &"<p>");
+        let result = Tera::one_off("{{ greeting }} world", &context, true).unwrap();
+
+        assert_eq!(result, "&lt;p&gt; world");
+    }
+
+    #[test]
+    fn test_can_disable_autoescape_one_off_template() {
+        let mut context = Context::new();
+        context.insert("greeting", &"<p>");
+        let result = Tera::one_off("{{ greeting }} world", &context, false).unwrap();
+
+        assert_eq!(result, "<p> world");
+    }
+
+    #[test]
+    fn test_set_escape_function() {
+        let escape_c_string: super::EscapeFn = |input| {
+            let mut output = String::with_capacity(input.len() * 2);
+            for c in input.chars() {
+                match c {
+                    '\'' => output.push_str("\\'"),
+                    '\"' => output.push_str("\\\""),
+                    '\\' => output.push_str("\\\\"),
+                    '\n' => output.push_str("\\n"),
+                    '\r' => output.push_str("\\r"),
+                    '\t' => output.push_str("\\t"),
+                    _ => output.push(c),
+                }
+            }
+            output
+        };
+        let mut tera = Tera::default();
+        tera.add_raw_template("foo", "\"{{ content }}\"").unwrap();
+        tera.autoescape_on(vec!["foo"]);
+        tera.set_escape_fn(escape_c_string);
+        let mut context = Context::new();
+        context.insert("content", &"Hello\n\'world\"!");
+        let result = tera.render("foo", &context).unwrap();
+        assert_eq!(result, r#""Hello\n\'world\"!""#);
+    }
+
+    #[test]
+    fn test_reset_escape_function() {
+        let no_escape: super::EscapeFn = |input| input.to_string();
+        let mut tera = Tera::default();
+        tera.add_raw_template("foo", "{{ content }}").unwrap();
+        tera.autoescape_on(vec!["foo"]);
+        tera.set_escape_fn(no_escape);
+        tera.reset_escape_fn();
+        let mut context = Context::new();
+        context.insert("content", &"Hello\n\'world\"!");
+        let result = tera.render("foo", &context).unwrap();
+        assert_eq!(result, "Hello\n&#x27;world&quot;!");
+    }
+
+    #[test]
+    fn test_value_one_off_template() {
+        let m = json!({
+            "greeting": "Good morning"
+        });
+        let result =
+            Tera::one_off("{{ greeting }} world", &Context::from_value(m).unwrap(), true).unwrap();
+
+        assert_eq!(result, "Good morning world");
+    }
+
+    #[test]
+    fn test_render_str_with_custom_function() {
+        let mut tera = Tera::default();
+        tera.register_function("echo", |args: &HashMap<_, JsonValue>| {
+            Ok(args.get("greeting").map(JsonValue::to_owned).unwrap())
+        });
+
+        let result =
+            tera.render_str("{{ echo(greeting='Hello') }} world", &Context::default()).unwrap();
+
+        assert_eq!(result, "Hello world");
+    }
+
+    #[test]
+    fn test_render_map_with_dotted_keys() {
+        let mut my_tera = Tera::default();
+        my_tera
+            .add_raw_templates(vec![
+                ("dots", r#"{{ map["a.b.c"] }}"#),
+                ("urls", r#"{{ map["https://example.com"] }}"#),
+            ])
+            .unwrap();
+
+        let mut map = HashMap::new();
+        map.insert("a.b.c", "success");
+        map.insert("https://example.com", "success");
+
+        let mut tera_context = Context::new();
+        tera_context.insert("map", &map);
+
+        my_tera.render("dots", &tera_context).unwrap();
+        my_tera.render("urls", &tera_context).unwrap();
+    }
+
+    #[test]
+    fn test_extend_no_overlap() {
+        let mut my_tera = Tera::default();
+        my_tera
+            .add_raw_templates(vec![
+                ("one", "{% block hey %}1{% endblock hey %}"),
+                ("two", "{% block hey %}2{% endblock hey %}"),
+                ("three", "{% block hey %}3{% endblock hey %}"),
+            ])
+            .unwrap();
+
+        let mut framework_tera = Tera::default();
+        framework_tera.add_raw_templates(vec![("four", "Framework X")]).unwrap();
+
+        my_tera.extend(&framework_tera).unwrap();
+        assert_eq!(my_tera.templates.len(), 4);
+        let result = my_tera.render("four", &Context::default()).unwrap();
+        assert_eq!(result, "Framework X");
+    }
+
+    #[test]
+    fn test_extend_with_overlap() {
+        let mut my_tera = Tera::default();
+        my_tera
+            .add_raw_templates(vec![
+                ("one", "MINE"),
+                ("two", "{% block hey %}2{% endblock hey %}"),
+                ("three", "{% block hey %}3{% endblock hey %}"),
+            ])
+            .unwrap();
+
+        let mut framework_tera = Tera::default();
+        framework_tera
+            .add_raw_templates(vec![("one", "FRAMEWORK"), ("four", "Framework X")])
+            .unwrap();
+
+        my_tera.extend(&framework_tera).unwrap();
+        assert_eq!(my_tera.templates.len(), 4);
+        let result = my_tera.render("one", &Context::default()).unwrap();
+        assert_eq!(result, "MINE");
+    }
+
+    #[test]
+    fn test_extend_new_filter() {
+        let mut my_tera = Tera::default();
+        let mut framework_tera = Tera::default();
+        framework_tera.register_filter("hello", |_: &JsonValue, _: &HashMap<String, JsonValue>| {
+            Ok(JsonValue::Number(10.into()))
+        });
+        my_tera.extend(&framework_tera).unwrap();
+        assert!(my_tera.filters.contains_key("hello"));
+    }
+
+    #[test]
+    fn test_extend_new_tester() {
+        let mut my_tera = Tera::default();
+        let mut framework_tera = Tera::default();
+        framework_tera.register_tester("hello", |_: Option<&JsonValue>, _: &[JsonValue]| Ok(true));
+        my_tera.extend(&framework_tera).unwrap();
+        assert!(my_tera.testers.contains_key("hello"));
+    }
+
+    #[test]
+    fn can_load_from_glob() {
+        let tera = Tera::new("examples/basic/templates/**/*").unwrap();
+        assert!(tera.get_template("base.html").is_ok());
+    }
+
+    #[test]
+    fn can_load_from_glob_with_patterns() {
+        let tera = Tera::new("examples/basic/templates/**/*.{html, xml}").unwrap();
+        assert!(tera.get_template("base.html").is_ok());
+    }
+
+    #[test]
+    fn full_reload_with_glob() {
+        let mut tera = Tera::new("examples/basic/templates/**/*").unwrap();
+        tera.full_reload().unwrap();
+
+        assert!(tera.get_template("base.html").is_ok());
+    }
+
+    #[test]
+    fn full_reload_with_glob_after_extending() {
+        let mut tera = Tera::new("examples/basic/templates/**/*").unwrap();
+        let mut framework_tera = Tera::default();
+        framework_tera
+            .add_raw_templates(vec![("one", "FRAMEWORK"), ("four", "Framework X")])
+            .unwrap();
+        tera.extend(&framework_tera).unwrap();
+        tera.full_reload().unwrap();
+
+        assert!(tera.get_template("base.html").is_ok());
+        assert!(tera.get_template("one").is_ok());
+    }
+
+    #[should_panic]
+    #[test]
+    fn test_can_only_parse_templates() {
+        let mut tera = Tera::parse("examples/basic/templates/**/*").unwrap();
+        for tpl in tera.templates.values_mut() {
+            tpl.name = format!("a-theme/templates/{}", tpl.name);
+            if let Some(ref parent) = tpl.parent.clone() {
+                tpl.parent = Some(format!("a-theme/templates/{}", parent));
+            }
+        }
+        // Will panic here as we changed the parent and it won't be able
+        // to build the inheritance chain in this case
+        tera.build_inheritance_chains().unwrap();
+    }
+
+    // https://github.com/Keats/tera/issues/380
+    #[test]
+    fn glob_work_with_absolute_paths() {
+        let tmp_dir = tempdir().expect("create temp dir");
+        let cwd = tmp_dir.path().canonicalize().unwrap();
+        File::create(cwd.join("hey.html")).expect("Failed to create a test file");
+        File::create(cwd.join("ho.html")).expect("Failed to create a test file");
+        let glob = cwd.join("*.html").into_os_string().into_string().unwrap();
+        let tera = Tera::new(&glob).expect("Couldn't build Tera instance");
+        assert_eq!(tera.templates.len(), 2);
+    }
+
+    #[test]
+    fn glob_work_with_absolute_paths_and_double_star() {
+        let tmp_dir = tempdir().expect("create temp dir");
+        let cwd = tmp_dir.path().canonicalize().unwrap();
+        File::create(cwd.join("hey.html")).expect("Failed to create a test file");
+        File::create(cwd.join("ho.html")).expect("Failed to create a test file");
+        let glob = cwd.join("**").join("*.html").into_os_string().into_string().unwrap();
+        let tera = Tera::new(&glob).expect("Couldn't build Tera instance");
+        assert_eq!(tera.templates.len(), 2);
+    }
+
+    // https://github.com/Keats/tera/issues/396
+    #[test]
+    fn issues_found_fuzzing_expressions_are_fixed() {
+        let samples: Vec<(&str, Option<&str>)> = vec![
+            // sample, expected result if it isn't an error
+            ("{{0%0}}", None),
+            ("{{W>W>vv}}{", None),
+            ("{{22220222222022222220}}", None),
+            ("{_{{W~1+11}}k{", None),
+            ("{{n~n<n.11}}}", None),
+            ("{{266314325266577770*4167}}7}}7", None),
+            ("{{0~1~``~0~0~177777777777777777777~``~0~0~h}}", None),
+        ];
+
+        for (sample, expected_output) in samples {
+            let res = Tera::one_off(sample, &Context::new(), true);
+            if let Some(output) = expected_output {
+                assert!(res.is_ok());
+                assert_eq!(res.unwrap(), output);
+            } else {
+                assert!(res.is_err());
+            }
+        }
+    }
+
+    #[test]
+    fn issues_found_fuzzing_conditions_are_fixed() {
+        let samples: Vec<(&str, Option<&str>)> = vec![
+            // (sample, expected result if it isn't an error)
+            ("C~Q", None),
+            ("s is V*0", None),
+            ("x0x::N()", None),
+            // this is an issue in pest itself: https://github.com/pest-parser/pest/issues/402
+            //            ("_(p=__(p=[_(p=__(p=[_(p=[_(p=[_1", None),
+        ];
+
+        for (sample, expected_output) in samples {
+            println!("{}, {:?}", sample, expected_output);
+            let res = Tera::one_off(
+                &format!("{{% if {} %}}true{{% endif %}}", sample),
+                &Context::new(),
+                true,
+            );
+            if let Some(output) = expected_output {
+                assert!(res.is_ok());
+                assert_eq!(res.unwrap(), output);
+            } else {
+                assert!(res.is_err());
+            }
+        }
+    }
+}
diff --git a/vendor/tera/src/utils.rs b/vendor/tera/src/utils.rs
new file mode 100644 (file)
index 0000000..67a39fe
--- /dev/null
@@ -0,0 +1,85 @@
+use crate::errors::Error;
+
+/// Escape HTML following [OWASP](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet)
+///
+/// Escape the following characters with HTML entity encoding to prevent switching
+/// into any execution context, such as script, style, or event handlers. Using
+/// hex entities is recommended in the spec. In addition to the 5 characters
+/// significant in XML (&, <, >, ", '), the forward slash is included as it helps
+/// to end an HTML entity.
+///
+/// ```text
+/// & --> &amp;
+/// < --> &lt;
+/// > --> &gt;
+/// " --> &quot;
+/// ' --> &#x27;     &apos; is not recommended
+/// / --> &#x2F;     forward slash is included as it helps end an HTML entity
+/// ```
+#[inline]
+pub fn escape_html(input: &str) -> String {
+    let mut output = String::with_capacity(input.len() * 2);
+    for c in input.chars() {
+        match c {
+            '&' => output.push_str("&amp;"),
+            '<' => output.push_str("&lt;"),
+            '>' => output.push_str("&gt;"),
+            '"' => output.push_str("&quot;"),
+            '\'' => output.push_str("&#x27;"),
+            '/' => output.push_str("&#x2F;"),
+            _ => output.push(c),
+        }
+    }
+
+    // Not using shrink_to_fit() on purpose
+    output
+}
+
+pub(crate) fn render_to_string<C, F, E>(context: C, render: F) -> Result<String, Error>
+where
+    C: FnOnce() -> String,
+    F: FnOnce(&mut Vec<u8>) -> Result<(), E>,
+    Error: From<E>,
+{
+    let mut buffer = Vec::new();
+    render(&mut buffer).map_err(Error::from)?;
+    buffer_to_string(context, buffer)
+}
+
+pub(crate) fn buffer_to_string<F>(context: F, buffer: Vec<u8>) -> Result<String, Error>
+where
+    F: FnOnce() -> String,
+{
+    String::from_utf8(buffer).map_err(|error| Error::utf8_conversion_error(error, context()))
+}
+
+#[cfg(test)]
+mod tests {
+    use super::escape_html;
+    use super::render_to_string;
+
+    #[test]
+    fn test_escape_html() {
+        let tests = vec![
+            (r"", ""),
+            (r"a&b", "a&amp;b"),
+            (r"<a", "&lt;a"),
+            (r">a", "&gt;a"),
+            (r#"""#, "&quot;"),
+            (r#"'"#, "&#x27;"),
+            (r#"大阪"#, "大阪"),
+        ];
+        for (input, expected) in tests {
+            assert_eq!(escape_html(input), expected);
+        }
+        let empty = String::new();
+        assert_eq!(escape_html(&empty), empty);
+    }
+
+    #[test]
+    fn test_render_to_string() {
+        use std::io::Write;
+        let string = render_to_string(|| panic!(), |w| write!(w, "test")).unwrap();
+        assert_eq!(string, "test".to_owned());
+    }
+}
index aaec8f9c36eb31d7b3ccf6868260c6b5feda7e6c..90027d93aa0921fcac9e1d07c3cc5ca95a9aefcb 100644 (file)
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"0a4162254a226c8f9b59e6ab362caaef44d5d1a5a5d1353b7d30c87f31e4d9fd","Cargo.toml":"75962c8dca587562d8e47cb915c25d26b21eafab119586d32f274d19542da76a","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"ed7303f47e55e0236b056bcb8eca39b4f4a404dce0db7b1bcdc9f666621d8965","benches/enter.rs":"4a94a04e2abd07950ef2f0b646f4dcdf4ff00abf6396edb5a53c8b41b7691b1a","benches/filter.rs":"6374005ffa47fa19880bb95e3e37406f40ea72a02c5136f4d5eb4c663d452b18","benches/filter_log.rs":"612716bdf9a188093e84d014a4847f18157f148f7d64e54150cd5c91ac709a8a","benches/fmt.rs":"5a0ff37967ffef3a221eebb78855d031e2e883a8a67528c8e794cc6f16cbee8a","benches/support/mod.rs":"72bef51154da9c9b3d81300195c1929a818858fa4b4fc2aa07b49ca586f4cd39","src/field/debug.rs":"852bae8f62a867d518a5e27a03922059e68ddca63ab432eb67d045013bc0bc9f","src/field/delimited.rs":"cfafcad5b3e9a3f018149ec4803ce53277ebc54a92a8eaf05bbb191b2058d691","src/field/display.rs":"8af1b6e78e33e77415a89bf40aa1414797c8d3b1f62f4609b5ddef6c90faa038","src/field/mod.rs":"f2ca796d2bff95289d1b7f451b31e7ff85ceacb5247bc59c06569b05cf870e84","src/filter/env/directive.rs":"43fbf21331f36bcca845807777eaa8a7f492f69a431e26538f5a69ba467263d7","src/filter/env/field.rs":"1199ce273e012eaadc9c0c51727fbd97d7700ce90f6e186218a3096898fc6bbb","src/filter/env/mod.rs":"8818cc04c16ea652e31e5114471890b2d45689012491bdaf6093aa32d4712ca3","src/filter/level.rs":"51715f375c439fb5e7e3f73b1669a34631b07eb90f12a992618dece8e641a485","src/filter/mod.rs":"e88b2e0b8f1d1931d099ad7f3116fd784de586afff1412f273929af4f914da9b","src/fmt/fmt_layer.rs":"0e2ab3f67bad0fc050dc726e0330192cc39791902e8d85b9efe4a84bf3c53a6b","src/fmt/format/json.rs":"864a156c1add83cec2b2863726c481864db520636a9e898237f32b9489f15c7d","src/fmt/format/mod.rs":"bbeef2a1cfd529d899da2ec0792586190a27bd75b5160c58ae8785a4c00fb2ba","src/fmt/format/pretty.rs":"e97188ec3184f6b28774af1eb5860d23ec9eedf877940a3f67dd37097fc63411","src/fmt/mod.rs":"284c36c4684f5c33e75c7c870111f31406c3afc73efa80031bb58e527d4d7305","src/fmt/time/datetime.rs":"1e77f550fa9bf9d019f8337aedb84a1077bd4d054a89080c3babf97a88ca6911","src/fmt/time/mod.rs":"7f3f5f72cdab40c463a0b02ff05f12e749982d29b0dedb44e4d2256aa15fb381","src/fmt/writer.rs":"71b61c68bafe872a86b63e772a6d13d37a4694cb21c23716478d428a8af7d869","src/layer.rs":"c8a9b3fe87a38fcd2fd18b88023522222d53f431bc9d9ea26a47d25815a8b2cf","src/lib.rs":"f2ee2133bc8f6657dba06b4d2cdfc0acd097630f5c617fb961964d2d8ccaf76c","src/prelude.rs":"021efd74aa80979fb23e8d4818a21ee1c4609566c32fcb3a3810d19c29c908b8","src/registry/extensions.rs":"7a6b001491308540abba6ae56dc8b93ab216469165253c1f45647a22bfc58cac","src/registry/mod.rs":"4e5b4b413969594b11ee873771f705a88d71049fd9d2501b1dabab782b3dfad6","src/registry/sharded.rs":"166091c80e6de66f96a7ff5f617351419b5aa0011862f775b8c3c19671f2f876","src/registry/stack.rs":"e992ba71d66d6dbd6524c7ce65087a8fe374a8b1e9281527910c37c38b88764e","src/reload.rs":"4ac190528a0a2471ec88d2a44aa8cf6abcecfe017defe3b843dc40f9bddbe7d0","src/sync.rs":"b837a6d9352982920d192933d0abe7cd17f90fed07f0da3a0cd807e770ebe336","src/thread.rs":"32f03a56d68c494c999f58a5d242a5e43b82b00d40ffde424280a4343945099d","src/util.rs":"119e16eb0423eacebc10bc9b1952ad24b698c5054e68cf74a076d12935e78961","tests/duplicate_spans.rs":"802d28d567815613a4d8c28b58169b8117297c2ae82f89900516d55f34ef1735","tests/field_filter.rs":"db49fc805069422f5465d69d7178742739425283c8cf8dc72c2a3c08c9aa1ef1","tests/filter.rs":"97eee1b5b6684badef3649815eafe52f0e8a6e0268792d207ea4ce1b7df8fd2a","tests/filter_log.rs":"f79092e7b42a1fc15ee0ff86349bd6d1604d65be66752e95792d25195f70eff7","tests/fmt_max_level_hint.rs":"abb09add1492d54e2766b2db035036952bc3c4f38a6c9c7aefb07ea0cf85c744","tests/registry_max_level_hint.rs":"a11d7a42672494b309d5ba10fcd5aa3b5c2ba45f4d1a31435da408f8caab59f0","tests/registry_with_subscriber.rs":"06427f7d2848edb6c584351cc1ed5c43a1620db070bdd6105dd1e7dc57baeca3","tests/reload.rs":"463705d3850ca512c672a80a44fd0339b0ac834b2fa510ec8279cfef2cc3d594","tests/same_len_filters.rs":"a6eeac01fc1079fe747e14e481d78c76a190f6140b0616fac0ac037697af92f1","tests/support.rs":"2c5664c5bf285ed188bff045d2d0fef4638126e6b1a83f769a0d42773cc0eee4","tests/utils.rs":"07ac1c4b6e8a051352375c1f9e9b4d99ce3a0d0627b15dd3253e870498d275aa"},"package":"aa5553bf0883ba7c9cbe493b085c29926bd41b66afc31ff72cf17ff4fb60dcd5"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"2931deb517e7670aa398ab7034734d7c57d067487d6293ec783c129abe7a8a9b","Cargo.toml":"e464d2ff3926bd839598902d77e8943169b0dd5045510318007d82b134920239","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"ed7303f47e55e0236b056bcb8eca39b4f4a404dce0db7b1bcdc9f666621d8965","benches/enter.rs":"4a94a04e2abd07950ef2f0b646f4dcdf4ff00abf6396edb5a53c8b41b7691b1a","benches/filter.rs":"6374005ffa47fa19880bb95e3e37406f40ea72a02c5136f4d5eb4c663d452b18","benches/filter_log.rs":"612716bdf9a188093e84d014a4847f18157f148f7d64e54150cd5c91ac709a8a","benches/fmt.rs":"5a0ff37967ffef3a221eebb78855d031e2e883a8a67528c8e794cc6f16cbee8a","benches/support/mod.rs":"72bef51154da9c9b3d81300195c1929a818858fa4b4fc2aa07b49ca586f4cd39","src/field/debug.rs":"852bae8f62a867d518a5e27a03922059e68ddca63ab432eb67d045013bc0bc9f","src/field/delimited.rs":"cfafcad5b3e9a3f018149ec4803ce53277ebc54a92a8eaf05bbb191b2058d691","src/field/display.rs":"8af1b6e78e33e77415a89bf40aa1414797c8d3b1f62f4609b5ddef6c90faa038","src/field/mod.rs":"f2ca796d2bff95289d1b7f451b31e7ff85ceacb5247bc59c06569b05cf870e84","src/filter/env/directive.rs":"43fbf21331f36bcca845807777eaa8a7f492f69a431e26538f5a69ba467263d7","src/filter/env/field.rs":"1199ce273e012eaadc9c0c51727fbd97d7700ce90f6e186218a3096898fc6bbb","src/filter/env/mod.rs":"909bc8a935daa92849a3c54beac38466a19a05f5954b4c9596e6288ff45f936c","src/filter/level.rs":"cc449757aac47caaf19dd5ba4d74c8efbcd7531fcd6c13da0c5f6fdda12cc9ca","src/filter/mod.rs":"e88b2e0b8f1d1931d099ad7f3116fd784de586afff1412f273929af4f914da9b","src/fmt/fmt_layer.rs":"dbe024bdff435c3dd55d77927637008a4881a9f867288cb1c21e14aa24564679","src/fmt/format/json.rs":"d024cc1d230ea0fe2ce3345f3d26233526d46fa2e8205127ec6b0ac08a334ffe","src/fmt/format/mod.rs":"f9034b37f34aec8978ff4c217f9ab4661af6837fa61560ab62dbbd8e3fa4ba22","src/fmt/format/pretty.rs":"779943bf6959ac1a79ebcfe94286387b691c3aed0d7463e79d80fa52e619fe8e","src/fmt/mod.rs":"f178fb3646d37b1a1ae08d95ed988df6cf3b41c7c73e01754e6763211f970714","src/fmt/time/datetime.rs":"1e77f550fa9bf9d019f8337aedb84a1077bd4d054a89080c3babf97a88ca6911","src/fmt/time/mod.rs":"7f3f5f72cdab40c463a0b02ff05f12e749982d29b0dedb44e4d2256aa15fb381","src/fmt/writer.rs":"631f935418e426e5f0c779014cbca98ef3d23878d4be896bbae4981cda381825","src/layer.rs":"982f99ee1f96daa175cc38ae05f2303027968d593040cafcb1a22f9f7abcceab","src/lib.rs":"948a206a12af571938a9f49caee448d23ac3b65cec831d4c1ac8bf120b4cd738","src/prelude.rs":"33de6bc8a5482763c67a0d39859535572f4565b7ff74add9f2de007713ce77f8","src/registry/extensions.rs":"7a6b001491308540abba6ae56dc8b93ab216469165253c1f45647a22bfc58cac","src/registry/mod.rs":"e854da98ca8bb73c8a072c6436a2fbc6dd9606b98112a51ec342fcef3616b3ab","src/registry/sharded.rs":"166091c80e6de66f96a7ff5f617351419b5aa0011862f775b8c3c19671f2f876","src/registry/stack.rs":"e992ba71d66d6dbd6524c7ce65087a8fe374a8b1e9281527910c37c38b88764e","src/reload.rs":"4ac190528a0a2471ec88d2a44aa8cf6abcecfe017defe3b843dc40f9bddbe7d0","src/sync.rs":"b837a6d9352982920d192933d0abe7cd17f90fed07f0da3a0cd807e770ebe336","src/thread.rs":"32f03a56d68c494c999f58a5d242a5e43b82b00d40ffde424280a4343945099d","src/util.rs":"119e16eb0423eacebc10bc9b1952ad24b698c5054e68cf74a076d12935e78961","tests/duplicate_spans.rs":"802d28d567815613a4d8c28b58169b8117297c2ae82f89900516d55f34ef1735","tests/field_filter.rs":"db49fc805069422f5465d69d7178742739425283c8cf8dc72c2a3c08c9aa1ef1","tests/filter.rs":"97eee1b5b6684badef3649815eafe52f0e8a6e0268792d207ea4ce1b7df8fd2a","tests/filter_log.rs":"f79092e7b42a1fc15ee0ff86349bd6d1604d65be66752e95792d25195f70eff7","tests/fmt_max_level_hint.rs":"abb09add1492d54e2766b2db035036952bc3c4f38a6c9c7aefb07ea0cf85c744","tests/registry_max_level_hint.rs":"a11d7a42672494b309d5ba10fcd5aa3b5c2ba45f4d1a31435da408f8caab59f0","tests/registry_with_subscriber.rs":"06427f7d2848edb6c584351cc1ed5c43a1620db070bdd6105dd1e7dc57baeca3","tests/reload.rs":"463705d3850ca512c672a80a44fd0339b0ac834b2fa510ec8279cfef2cc3d594","tests/same_len_filters.rs":"a6eeac01fc1079fe747e14e481d78c76a190f6140b0616fac0ac037697af92f1","tests/support.rs":"2c5664c5bf285ed188bff045d2d0fef4638126e6b1a83f769a0d42773cc0eee4","tests/utils.rs":"07ac1c4b6e8a051352375c1f9e9b4d99ce3a0d0627b15dd3253e870498d275aa"},"package":"ab69019741fca4d98be3c62d2b75254528b5432233fd8a4d2739fec20278de48"}
\ No newline at end of file
index 5be111014ec8e84653c2ce74c497ca4b14785e21..2ea2b0a121944d3e44cc5a8807e97d6e49ca467c 100644 (file)
@@ -1,3 +1,35 @@
+# 0.2.19 (June 25, 2021)
+
+### Deprecated
+
+- **registry**: `SpanRef::parents`, `SpanRef::from_root`, and `Context::scope`
+  iterators, which are replaced by new `SpanRef::scope` and `Scope::from_root`
+  iterators ([#1413])
+
+### Added
+
+- **registry**: `SpanRef::scope` method, which returns a leaf-to-root `Iterator`
+  including the leaf span ([#1413])
+- **registry**: `Scope::from_root` method, which reverses the `scope` iterator
+  to iterate root-to-leaf ([#1413])
+- **registry**: `Context::event_span` method, which looks up the parent span of
+  an event ([#1434])
+- **registry**: `Context::event_scope` method, returning a `Scope` iterator over
+  the span scope of an event ([#1434])
+- **fmt**: `MakeWriter::make_writer_for` method, which allows returning a
+  different writer based on a span or event's metadata ([#1141])
+- **fmt**: `MakeWriterExt` trait, with `with_max_level`, `with_min_level`,
+  `with_filter`, `and`, and `or_else` combinators ([#1274])
+- **fmt**: `MakeWriter` implementation for `Arc<W> where &W: io::Write`
+  ([#1274])
+  
+Thanks to @teozkr and @Folyd for contributing to this release!
+
+[#1413]: https://github.com/tokio-rs/tracing/pull/1413
+[#1434]: https://github.com/tokio-rs/tracing/pull/1434
+[#1141]: https://github.com/tokio-rs/tracing/pull/1141
+[#1274]: https://github.com/tokio-rs/tracing/pull/1274
+
 # 0.2.18 (April 30, 2021)
 
 ### Deprecated
index 8d88d7af662a593390fa471f35c1cb621674cf5c..f1d9334a4d8e630e62d0303fd684767737d062c5 100644 (file)
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "tracing-subscriber"
-version = "0.2.18"
+version = "0.2.19"
 authors = ["Eliza Weisman <eliza@buoyant.io>", "David Barsky <me@davidbarsky.com>", "Tokio Contributors <team@tokio.rs>"]
 description = "Utilities for implementing and composing `tracing` subscribers.\n"
 homepage = "https://tokio.rs"
index f1c71416e0d2ea1f04555757722d59f9655b96a3..4ae87697dc8e91286400510a424e20e2682def04 100644 (file)
@@ -271,7 +271,7 @@ impl EnvFilter {
                     let bold = Style::new().bold();
                     let mut warning = Color::Yellow.paint("warning");
                     warning.style_ref_mut().is_bold = true;
-                    format!("{}{} {}", warning, bold.clone().paint(":"), bold.paint(msg))
+                    format!("{}{} {}", warning, bold.paint(":"), bold.paint(msg))
                 };
                 eprintln!("{}", msg);
             };
@@ -308,7 +308,6 @@ impl EnvFilter {
                 };
                 let level = directive
                     .level
-                    .clone()
                     .into_level()
                     .expect("=off would not have enabled any filters");
                 ctx(&format!(
@@ -396,8 +395,8 @@ impl<S: Subscriber> Layer<S> for EnvFilter {
             return Some(LevelFilter::TRACE);
         }
         std::cmp::max(
-            self.statics.max_level.clone().into(),
-            self.dynamics.max_level.clone().into(),
+            self.statics.max_level.into(),
+            self.dynamics.max_level.into(),
         )
     }
 
index 0c981f347550356f2835f831220cc7e64067b23c..0fa601260ad5a3ef48d5cb7e965a8f1a6e1b5c03 100644 (file)
@@ -22,6 +22,6 @@ impl<S: Subscriber> crate::Layer<S> for LevelFilter {
     }
 
     fn max_level_hint(&self) -> Option<LevelFilter> {
-        self.clone().into()
+        Some(*self)
     }
 }
index eeddabd4719953c965978da616fd0082c738f075..12dfd8af00542e229fd106949942128301e59e89 100644 (file)
@@ -1,7 +1,7 @@
 use crate::{
     field::RecordFields,
     fmt::{format, FormatEvent, FormatFields, MakeWriter, TestWriter},
-    layer::{self, Context, Scope},
+    layer::{self, Context},
     registry::{LookupSpan, SpanRef},
 };
 use format::{FmtSpan, TimingDisplay};
@@ -740,7 +740,7 @@ where
 
             let ctx = self.make_ctx(ctx);
             if self.fmt_event.format_event(&ctx, &mut buf, event).is_ok() {
-                let mut writer = self.make_writer.make_writer();
+                let mut writer = self.make_writer.make_writer_for(event.metadata());
                 let _ = io::Write::write_all(&mut writer, buf.as_bytes());
             }
 
@@ -804,8 +804,10 @@ where
         F: FnMut(&SpanRef<'_, S>) -> Result<(), E>,
     {
         // visit all the current spans
-        for span in self.ctx.scope() {
-            f(&span)?;
+        if let Some(leaf) = self.ctx.lookup_current() {
+            for span in leaf.scope().from_root() {
+                f(&span)?;
+            }
         }
         Ok(())
     }
@@ -864,7 +866,12 @@ where
     /// the current span.
     ///
     /// [stored data]: ../registry/struct.SpanRef.html
-    pub fn scope(&self) -> Scope<'_, S>
+    #[deprecated(
+        note = "wraps layer::Context::scope, which is deprecated",
+        since = "0.2.19"
+    )]
+    #[allow(deprecated)]
+    pub fn scope(&self) -> crate::layer::Scope<'_, S>
     where
         S: for<'lookup> LookupSpan<'lookup>,
     {
@@ -906,11 +913,12 @@ impl Timings {
 
 #[cfg(test)]
 mod test {
+    use super::*;
     use crate::fmt::{
         self,
         format::{self, test::MockTime, Format},
         layer::Layer as _,
-        test::MockWriter,
+        test::{MockMakeWriter, MockWriter},
         time,
     };
     use crate::Registry;
@@ -1103,4 +1111,70 @@ mod test {
             actual.as_str()
         );
     }
+
+    #[test]
+    fn make_writer_based_on_meta() {
+        lazy_static! {
+            static ref BUF1: Mutex<Vec<u8>> = Mutex::new(vec![]);
+            static ref BUF2: Mutex<Vec<u8>> = Mutex::new(vec![]);
+        }
+        struct MakeByTarget<'a> {
+            make_writer1: MockMakeWriter<'a>,
+            make_writer2: MockMakeWriter<'a>,
+        }
+
+        impl<'a> MakeWriter for MakeByTarget<'a> {
+            type Writer = MockWriter<'a>;
+
+            fn make_writer(&self) -> Self::Writer {
+                self.make_writer1.make_writer()
+            }
+
+            fn make_writer_for(&self, meta: &Metadata<'_>) -> Self::Writer {
+                if meta.target() == "writer2" {
+                    return self.make_writer2.make_writer();
+                }
+                self.make_writer()
+            }
+        }
+
+        let make_writer1 = MockMakeWriter::new(&BUF1);
+        let make_writer2 = MockMakeWriter::new(&BUF2);
+
+        let make_writer = MakeByTarget {
+            make_writer1: make_writer1.clone(),
+            make_writer2: make_writer2.clone(),
+        };
+
+        let subscriber = crate::fmt::Subscriber::builder()
+            .with_writer(make_writer)
+            .with_level(false)
+            .with_target(false)
+            .with_ansi(false)
+            .with_timer(MockTime)
+            .with_span_events(FmtSpan::CLOSE)
+            .finish();
+
+        with_default(subscriber, || {
+            let span1 = tracing::info_span!("writer1_span", x = 42);
+            let _e = span1.enter();
+            tracing::info!(target: "writer2", "hello writer2!");
+            let span2 = tracing::info_span!(target: "writer2", "writer2_span");
+            let _e = span2.enter();
+            tracing::warn!(target: "writer1", "hello writer1!");
+        });
+
+        let actual = sanitize_timings(make_writer1.get_string());
+        assert_eq!(
+            "fake time writer1_span{x=42}:writer2_span: hello writer1!\n\
+             fake time writer1_span{x=42}: close timing timing\n",
+            actual.as_str()
+        );
+        let actual = sanitize_timings(make_writer2.get_string());
+        assert_eq!(
+            "fake time writer1_span{x=42}: hello writer2!\n\
+             fake time writer1_span{x=42}:writer2_span: close timing timing\n",
+            actual.as_str()
+        );
+    }
 }
index 5cc522f6a42c8672e8df566e898e29e7a01a6e37..c2a0ced8f467eec19f42bc35f78b691ed45a1b90 100644 (file)
@@ -98,8 +98,10 @@ where
         use serde::ser::SerializeSeq;
         let mut serializer = serializer_o.serialize_seq(None)?;
 
-        for span in self.0.scope() {
-            serializer.serialize_element(&SerializableSpan(&span, self.1))?;
+        if let Some(leaf_span) = self.0.lookup_current() {
+            for span in leaf_span.scope().from_root() {
+                serializer.serialize_element(&SerializableSpan(&span, self.1))?;
+            }
         }
 
         serializer.end()
index 67acc9377cb997f106eadef7d1e80908b5dd96a2..7a551bee468698b209c3f60171b60185bbd3255c 100644 (file)
@@ -7,10 +7,7 @@ use crate::{
     registry::LookupSpan,
 };
 
-use std::{
-    fmt::{self, Write},
-    iter,
-};
+use std::fmt::{self, Write};
 use tracing_core::{
     field::{self, Field, Visit},
     span, Event, Level, Subscriber,
@@ -827,7 +824,7 @@ where
         span: Option<&'a span::Id>,
         ansi: bool,
     ) -> Self {
-        Self { ctx, ansi, span }
+        Self { ctx, span, ansi }
     }
 
     #[cfg(not(feature = "ansi"))]
@@ -861,9 +858,7 @@ where
             .and_then(|id| self.ctx.ctx.span(&id))
             .or_else(|| self.ctx.ctx.lookup_current());
 
-        let scope = span
-            .into_iter()
-            .flat_map(|span| span.from_root().chain(iter::once(span)));
+        let scope = span.into_iter().flat_map(|span| span.scope().from_root());
 
         for span in scope {
             seen = true;
@@ -933,9 +928,7 @@ where
             .and_then(|id| self.ctx.ctx.span(&id))
             .or_else(|| self.ctx.ctx.lookup_current());
 
-        let scope = span
-            .into_iter()
-            .flat_map(|span| span.from_root().chain(iter::once(span)));
+        let scope = span.into_iter().flat_map(|span| span.scope().from_root());
 
         for span in scope {
             write!(f, "{}", bold.paint(span.metadata().name()))?;
@@ -1510,27 +1503,27 @@ pub(super) mod test {
     #[test]
     fn fmt_span_combinations() {
         let f = FmtSpan::NONE;
-        assert_eq!(f.contains(FmtSpan::NEW), false);
-        assert_eq!(f.contains(FmtSpan::ENTER), false);
-        assert_eq!(f.contains(FmtSpan::EXIT), false);
-        assert_eq!(f.contains(FmtSpan::CLOSE), false);
+        assert!(!f.contains(FmtSpan::NEW));
+        assert!(!f.contains(FmtSpan::ENTER));
+        assert!(!f.contains(FmtSpan::EXIT));
+        assert!(!f.contains(FmtSpan::CLOSE));
 
         let f = FmtSpan::ACTIVE;
-        assert_eq!(f.contains(FmtSpan::NEW), false);
-        assert_eq!(f.contains(FmtSpan::ENTER), true);
-        assert_eq!(f.contains(FmtSpan::EXIT), true);
-        assert_eq!(f.contains(FmtSpan::CLOSE), false);
+        assert!(!f.contains(FmtSpan::NEW));
+        assert!(f.contains(FmtSpan::ENTER));
+        assert!(f.contains(FmtSpan::EXIT));
+        assert!(!f.contains(FmtSpan::CLOSE));
 
         let f = FmtSpan::FULL;
-        assert_eq!(f.contains(FmtSpan::NEW), true);
-        assert_eq!(f.contains(FmtSpan::ENTER), true);
-        assert_eq!(f.contains(FmtSpan::EXIT), true);
-        assert_eq!(f.contains(FmtSpan::CLOSE), true);
+        assert!(f.contains(FmtSpan::NEW));
+        assert!(f.contains(FmtSpan::ENTER));
+        assert!(f.contains(FmtSpan::EXIT));
+        assert!(f.contains(FmtSpan::CLOSE));
 
         let f = FmtSpan::NEW | FmtSpan::CLOSE;
-        assert_eq!(f.contains(FmtSpan::NEW), true);
-        assert_eq!(f.contains(FmtSpan::ENTER), false);
-        assert_eq!(f.contains(FmtSpan::EXIT), false);
-        assert_eq!(f.contains(FmtSpan::CLOSE), true);
+        assert!(f.contains(FmtSpan::NEW));
+        assert!(!f.contains(FmtSpan::ENTER));
+        assert!(!f.contains(FmtSpan::EXIT));
+        assert!(f.contains(FmtSpan::CLOSE));
     }
 }
index d98cef813d8e05f06ac6cfbb895ee3538cd152b9..ab1180823f9fad0cb6f4e4234416aa1d6f24d5a9 100644 (file)
@@ -5,10 +5,7 @@ use crate::{
     registry::LookupSpan,
 };
 
-use std::{
-    fmt::{self, Write},
-    iter,
-};
+use std::fmt::{self, Write};
 use tracing_core::{
     field::{self, Field},
     Event, Level, Subscriber,
@@ -187,10 +184,7 @@ where
             .and_then(|id| ctx.span(&id))
             .or_else(|| ctx.lookup_current());
 
-        let scope = span.into_iter().flat_map(|span| {
-            let parents = span.parents();
-            iter::once(span).chain(parents)
-        });
+        let scope = span.into_iter().flat_map(|span| span.scope());
 
         for span in scope {
             let meta = span.metadata();
index db6f2629e61ca37f7af1145fd3f3451097b11241..1bc8ef6fd265f59358924a4454a9b97927f139a3 100644 (file)
@@ -1189,6 +1189,11 @@ mod test {
         pub(crate) fn buf(&self) -> MutexGuard<'a, Vec<u8>> {
             self.buf.lock().unwrap()
         }
+
+        pub(crate) fn get_string(&self) -> String {
+            String::from_utf8(self.buf.lock().unwrap().clone())
+                .expect("subscriber must write valid UTF-8")
+        }
     }
 
     impl<'a> MakeWriter for MockMakeWriter<'a> {
index d437e5f5dc42a7d682e0d91114240fe5e92561e6..ba04ba817df12e4f1691e5439056210506256089 100644 (file)
@@ -1,9 +1,12 @@
 //! Abstractions for creating [`io::Write`] instances.
 //!
 //! [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
-
-use io::Write;
-use std::{fmt::Debug, io};
+use std::{
+    fmt::Debug,
+    io::{self, Write},
+    sync::Arc,
+};
+use tracing_core::Metadata;
 
 /// A type that can create [`io::Write`] instances.
 ///
@@ -13,12 +16,75 @@ use std::{fmt::Debug, io};
 /// This trait is already implemented for function pointers and immutably-borrowing closures that
 /// return an instance of [`io::Write`], such as [`io::stdout`] and [`io::stderr`].
 ///
-/// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
-/// [`fmt::Subscriber`]: ../../fmt/struct.Subscriber.html
-/// [`fmt::Layer`]: ../../fmt/struct.Layer.html
-/// [`Event`]: https://docs.rs/tracing-core/0.1.5/tracing_core/event/struct.Event.html
-/// [`io::stdout`]: https://doc.rust-lang.org/std/io/fn.stdout.html
-/// [`io::stderr`]: https://doc.rust-lang.org/std/io/fn.stderr.html
+/// The [`MakeWriter::make_writer_for`] method takes [`Metadata`] describing a
+/// span or event and returns a writer. `MakeWriter`s can optionally provide
+/// implementations of this method with behaviors that differ based on the span
+/// or event being written. For example, events at different [levels] might be
+/// written to different output streams, or data from different [targets] might
+/// be written to separate log files. When the `MakeWriter` has no custom
+/// behavior based on metadata, the default implementation of `make_writer_for`
+/// simply calls `self.make_writer()`, ignoring the metadata. Therefore, when
+/// metadata _is_ available, callers should prefer to call `make_writer_for`,
+/// passing in that metadata, so that the `MakeWriter` implementation can choose
+/// the appropriate behavior.
+///
+/// # Examples
+///
+/// The simplest usage is to pass in a named function that returns a writer. For
+/// example, to log all events to stderr, we could write:
+/// ```
+/// let subscriber = tracing_subscriber::fmt()
+///     .with_writer(std::io::stderr)
+///     .finish();
+/// # drop(subscriber);
+/// ```
+///
+/// Any function that returns a writer can be used:
+///
+/// ```
+/// fn make_my_great_writer() -> impl std::io::Write {
+///     // ...
+///     # std::io::stdout()
+/// }
+///
+/// let subscriber = tracing_subscriber::fmt()
+///     .with_writer(make_my_great_writer)
+///     .finish();
+/// # drop(subscriber);
+/// ```
+///
+/// A closure can be used to introduce arbitrary logic into how the writer is
+/// created. Consider the (admittedly rather silly) example of sending every 5th
+/// event to stderr, and all other events to stdout:
+///
+/// ```
+/// use std::io;
+/// use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
+///
+/// let n = AtomicUsize::new(0);
+/// let subscriber = tracing_subscriber::fmt()
+///     .with_writer(move || -> Box<dyn io::Write> {
+///         if n.fetch_add(1, Relaxed) % 5 == 0 {
+///             Box::new(io::stderr())
+///         } else {
+///             Box::new(io::stdout())
+///        }
+///     })
+///     .finish();
+/// # drop(subscriber);
+/// ```
+///
+/// [`io::Write`]: std::io::Write
+/// [`fmt::Collector`]: super::super::fmt::Collector
+/// [`fmt::Subscriber`]: super::super::fmt::Subscriber
+/// [`Event`]: tracing_core::event::Event
+/// [`io::stdout`]: std::io::stdout()
+/// [`io::stderr`]: std::io::stderr()
+/// [mutex]: std::sync::Mutex
+/// [`MakeWriter::make_writer_for`]: MakeWriter::make_writer_for
+/// [`Metadata`]: tracing_core::Metadata
+/// [levels]: tracing_core::Level
+/// [targets]: tracing_core::Metadata::target
 pub trait MakeWriter {
     /// The concrete [`io::Write`] implementation returned by [`make_writer`].
     ///
@@ -36,22 +102,352 @@ pub trait MakeWriter {
     /// [`MakeWriter`] to improve performance.
     ///
     /// [`Writer`]: #associatedtype.Writer
-    /// [`fmt::Layer`]: ../../fmt/struct.Layer.html
-    /// [`fmt::Subscriber`]: ../../fmt/struct.Subscriber.html
-    /// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
-    /// [`MakeWriter`]: trait.MakeWriter.html
+    /// [`fmt::Layer`]: crate::fmt::Layer
+    /// [`fmt::Subscriber`]: crate::fmt::Subscriber
+    /// [`io::Write`]: std::io::Write
     fn make_writer(&self) -> Self::Writer;
+
+    /// Returns a [`Writer`] for writing data from the span or event described
+    /// by the provided [`Metadata`].
+    ///
+    /// By default, this calls [`self.make_writer()`][make_writer], ignoring
+    /// the provided metadata, but implementations can override this to provide
+    /// metadata-specific behaviors.
+    ///
+    /// This method allows `MakeWriter` implementations to implement different
+    /// behaviors based on the span or event being written. The `MakeWriter`
+    /// type might return different writers based on the provided metadata, or
+    /// might write some values to the writer before or after providing it to
+    /// the caller.
+    ///
+    /// For example, we might want to write data from spans and events at the
+    /// [`ERROR`] and [`WARN`] levels to `stderr`, and data from spans or events
+    /// at lower levels to stdout:
+    ///
+    /// ```
+    /// use std::io::{self, Stdout, Stderr};
+    /// use tracing_subscriber::fmt::writer::MakeWriter;
+    /// use tracing_core::{Metadata, Level};
+    ///
+    /// pub struct MyMakeWriter {}
+    ///
+    /// /// A lock on either stdout or stderr, depending on the verbosity level
+    /// /// of the event being written.
+    /// pub enum Stdio {
+    ///     Stdout(Stdout),
+    ///     Stderr(Stderr),
+    /// }
+    ///
+    /// impl io::Write for Stdio {
+    ///     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+    ///         match self {
+    ///             Stdio::Stdout(io) => io.write(buf),
+    ///             Stdio::Stderr(io) => io.write(buf),
+    ///         }
+    ///     }
+    ///
+    ///     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+    ///         // ...
+    ///         # match self {
+    ///         #     Stdio::Stdout(io) => io.write_all(buf),
+    ///         #     Stdio::Stderr(io) => io.write_all(buf),
+    ///         # }
+    ///     }
+    ///
+    ///     fn flush(&mut self) -> io::Result<()> {
+    ///         // ...
+    ///         # match self {
+    ///         #     Stdio::Stdout(io) => io.flush(),
+    ///         #     Stdio::Stderr(io) => io.flush(),
+    ///         # }
+    ///     }
+    /// }
+    ///
+    /// impl MakeWriter for MyMakeWriter {
+    ///     type Writer = Stdio;
+    ///
+    ///     fn make_writer(&self) -> Self::Writer {
+    ///         // We must have an implementation of `make_writer` that makes
+    ///         // a "default" writer without any configuring metadata. Let's
+    ///         // just return stdout in that case.
+    ///         Stdio::Stdout(io::stdout())
+    ///     }
+    ///
+    ///     fn make_writer_for(&self, meta: &Metadata<'_>) -> Self::Writer {
+    ///         // Here's where we can implement our special behavior. We'll
+    ///         // check if the metadata's verbosity level is WARN or ERROR,
+    ///         // and return stderr in that case.
+    ///         if meta.level() <= &Level::WARN {
+    ///             return Stdio::Stderr(io::stderr());
+    ///         }
+    ///
+    ///         // Otherwise, we'll return stdout.
+    ///         Stdio::Stdout(io::stdout())
+    ///     }
+    /// }
+    /// ```
+    ///
+    /// [`Writer`]: MakeWriter::Writer
+    /// [`Metadata`]: tracing_core::Metadata
+    /// [make_writer]: MakeWriter::make_writer
+    /// [`WARN`]: tracing_core::Level::WARN
+    /// [`ERROR`]: tracing_core::Level::ERROR
+    fn make_writer_for(&self, meta: &Metadata<'_>) -> Self::Writer {
+        let _ = meta;
+        self.make_writer()
+    }
 }
 
-impl<F, W> MakeWriter for F
-where
-    F: Fn() -> W,
-    W: io::Write,
-{
-    type Writer = W;
+/// Extension trait adding combinators for working with types implementing
+/// [`MakeWriter`].
+///
+/// This is not intended to be implemented directly for user-defined
+/// [`MakeWriter`]s; instead, it should be imported when the desired methods are
+/// used.
+pub trait MakeWriterExt: MakeWriter {
+    /// Wraps `self` and returns a [`MakeWriter`] that will only write output
+    /// for events at or below the provided verbosity [`Level`]. For instance,
+    /// `Level::TRACE` is considered to be _more verbose` than `Level::INFO`.
+    ///
+    /// Events whose level is more verbose than `level` will be ignored, and no
+    /// output will be written.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use tracing::Level;
+    /// use tracing_subscriber::fmt::writer::MakeWriterExt;
+    ///
+    /// // Construct a writer that outputs events to `stderr` only if the span or
+    /// // event's level is >= WARN (WARN and ERROR).
+    /// let mk_writer = std::io::stderr.with_max_level(Level::WARN);
+    ///
+    /// tracing_subscriber::fmt().with_writer(mk_writer).init();
+    /// ```
+    ///
+    /// Writing the `ERROR` and `WARN` levels to `stderr`, and everything else
+    /// to `stdout`:
+    ///
+    /// ```
+    /// # use tracing::Level;
+    /// # use tracing_subscriber::fmt::writer::MakeWriterExt;
+    ///
+    /// let mk_writer = std::io::stderr
+    ///     .with_max_level(Level::WARN)
+    ///     .or_else(std::io::stdout);
+    ///
+    /// tracing_subscriber::fmt().with_writer(mk_writer).init();
+    /// ```
+    ///
+    /// Writing the `ERROR` level to `stderr`, the `INFO` and `WARN` levels to
+    /// `stdout`, and the `INFO` and DEBUG` levels to a file:
+    ///
+    /// ```
+    /// # use tracing::Level;
+    /// # use tracing_subscriber::fmt::writer::MakeWriterExt;
+    /// use std::{sync::Arc, fs::File};
+    /// # // don't actually create the file when running the tests.
+    /// # fn docs() -> std::io::Result<()> {
+    /// let debug_log = Arc::new(File::create("debug.log")?);
+    ///
+    /// let mk_writer = std::io::stderr
+    ///     .with_max_level(Level::ERROR)
+    ///     .or_else(std::io::stdout
+    ///         .with_max_level(Level::INFO)
+    ///         .and(debug_log.with_max_level(Level::DEBUG))
+    ///     );
+    ///
+    /// tracing_subscriber::fmt().with_writer(mk_writer).init();
+    /// # Ok(()) }
+    /// ```
+    ///
+    /// [`Level`]: tracing_core::Level
+    /// [`io::Write`]: std::io::Write
+    fn with_max_level(self, level: tracing_core::Level) -> WithMaxLevel<Self>
+    where
+        Self: Sized,
+    {
+        WithMaxLevel::new(self, level)
+    }
 
-    fn make_writer(&self) -> Self::Writer {
-        (self)()
+    /// Wraps `self` and returns a [`MakeWriter`] that will only write output
+    /// for events at or above the provided verbosity [`Level`].
+    ///
+    /// Events whose level is less verbose than `level` will be ignored, and no
+    /// output will be written.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use tracing::Level;
+    /// use tracing_subscriber::fmt::writer::MakeWriterExt;
+    ///
+    /// // Construct a writer that outputs events to `stdout` only if the span or
+    /// // event's level is <= DEBUG (DEBUG and TRACE).
+    /// let mk_writer = std::io::stdout.with_min_level(Level::DEBUG);
+    ///
+    /// tracing_subscriber::fmt().with_writer(mk_writer).init();
+    /// ```
+    /// This can be combined with [`MakeWriterExt::with_max_level`] to write
+    /// only within a range of levels:
+    ///
+    /// ```
+    /// # use tracing::Level;
+    /// # use tracing_subscriber::fmt::writer::MakeWriterExt;
+    /// // Only write the `DEBUG` and `INFO` levels to stdout.
+    /// let mk_writer = std::io::stdout
+    ///     .with_max_level(Level::DEBUG)
+    ///     .with_min_level(Level::INFO)
+    ///     // Write the `WARN` and `ERROR` levels to stderr.
+    ///     .and(std::io::stderr.with_min_level(Level::WARN));
+    ///
+    /// tracing_subscriber::fmt().with_writer(mk_writer).init();
+    /// ```
+    /// [`Level`]: tracing_core::Level
+    /// [`io::Write`]: std::io::Write
+    fn with_min_level(self, level: tracing_core::Level) -> WithMinLevel<Self>
+    where
+        Self: Sized,
+    {
+        WithMinLevel::new(self, level)
+    }
+
+    /// Wraps `self` with a predicate that takes a span or event's [`Metadata`]
+    /// and returns a `bool`. The returned [`MakeWriter`]'s
+    /// [`MakeWriter::make_writer_for`][mwf] method will check the predicate to
+    /// determine if  a writer should be produced for a given span or event.
+    ///
+    /// If the predicate returns `false`, the wrapped [`MakeWriter`]'s
+    /// [`make_writer_for`][mwf] will return [`OptionalWriter::none`].
+    /// Otherwise, it calls the wrapped [`MakeWriter`]'s
+    /// [`make_writer_for`][mwf] method, and returns the produced writer.
+    ///
+    /// This can be used to filter an output based on arbitrary [`Metadata`]
+    /// parameters.
+    ///
+    /// # Examples
+    ///
+    /// Writing events with a specific target to an HTTP access log, and other
+    /// events to stdout:
+    ///
+    /// ```
+    /// use tracing_subscriber::fmt::writer::MakeWriterExt;
+    /// use std::{sync::Arc, fs::File};
+    /// # // don't actually create the file when running the tests.
+    /// # fn docs() -> std::io::Result<()> {
+    /// let access_log = Arc::new(File::create("access.log")?);
+    ///
+    /// let mk_writer = access_log
+    ///     // Only write events with the target "http::access_log" to the
+    ///     // access log file.
+    ///     .with_filter(|meta| meta.target() == "http::access_log")
+    ///     // Write events with all other targets to stdout.
+    ///     .or_else(std::io::stdout);
+    ///
+    /// tracing_subscriber::fmt().with_writer(mk_writer).init();
+    /// # Ok(())
+    /// # }
+    /// ```
+    ///
+    /// Conditionally enabling or disabling a log file:
+    /// ```
+    /// use tracing_subscriber::fmt::writer::MakeWriterExt;
+    /// use std::{
+    ///     sync::{Arc, atomic::{AtomicBool, Ordering}},
+    ///     fs::File,
+    /// };
+    ///
+    /// static DEBUG_LOG_ENABLED: AtomicBool = AtomicBool::new(false);
+    ///
+    /// # // don't actually create the file when running the tests.
+    /// # fn docs() -> std::io::Result<()> {
+    /// // Create the debug log file
+    /// let debug_file = Arc::new(File::create("debug.log")?)
+    ///     // Enable the debug log only if the flag is enabled.
+    ///     .with_filter(|_| DEBUG_LOG_ENABLED.load(Ordering::Acquire));
+    ///
+    /// // Always write to stdout
+    /// let mk_writer = std::io::stdout
+    ///     // Write to the debug file if it's enabled
+    ///     .and(debug_file);
+    ///
+    /// tracing_subscriber::fmt().with_writer(mk_writer).init();
+    ///
+    /// // ...
+    ///
+    /// // Later, we can toggle on or off the debug log file.
+    /// DEBUG_LOG_ENABLED.store(true, Ordering::Release);
+    /// # Ok(())
+    /// # }
+    /// ```
+    ///
+    /// [`Metadata`]: tracing_core::Metadata
+    /// [mwf]: MakeWriter::make_writer_for
+    fn with_filter<F>(self, filter: F) -> WithFilter<Self, F>
+    where
+        Self: Sized,
+        F: Fn(&Metadata<'_>) -> bool,
+    {
+        WithFilter::new(self, filter)
+    }
+
+    /// Combines `self` with another type implementing [`MakeWriter`], returning
+    /// a new [`MakeWriter`] that produces [writers] that write to *both*
+    /// outputs.
+    ///
+    /// If writing to either writer returns an error, the returned writer will
+    /// return that error. However, both writers will still be written to before
+    /// the error is returned, so it is possible for one writer to fail while
+    /// the other is written to successfully.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use tracing_subscriber::fmt::writer::MakeWriterExt;
+    ///
+    /// // Construct a writer that outputs events to `stdout` *and* `stderr`.
+    /// let mk_writer = std::io::stdout.and(std::io::stderr);
+    ///
+    /// tracing_subscriber::fmt().with_writer(mk_writer).init();
+    /// ```
+    ///
+    /// `and` can be used in conjunction with filtering combinators. For
+    /// example, if we want to write to a number of outputs depending on
+    fn and<B>(self, other: B) -> Tee<Self, B>
+    where
+        Self: Sized,
+        B: MakeWriter + Sized,
+    {
+        Tee::new(self, other)
+    }
+
+    /// Combines `self` with another type implementing [`MakeWriter`], returning
+    /// a new [`MakeWriter`] that calls `other`'s [`make_writer`] if `self`'s
+    /// `make_writer` returns [`OptionalWriter::none`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use tracing::Level;
+    /// use tracing_subscriber::fmt::writer::MakeWriterExt;
+    ///
+    /// // Produces a writer that writes to `stderr` if the level is >= WARN,
+    /// // or returns `OptionalWriter::none()` otherwise.
+    /// let stderr = std::io::stderr.with_max_level(Level::WARN);
+    ///
+    /// // If the `stderr` `MakeWriter` is disabled by the max level filter,
+    /// // write to stdout instead:
+    /// let mk_writer = stderr.or_else(std::io::stdout);
+    ///
+    /// tracing_subscriber::fmt().with_writer(mk_writer).init();
+    /// ```
+    fn or_else<W, B>(self, other: B) -> OrElse<Self, B>
+    where
+        Self: MakeWriter<Writer = OptionalWriter<W>> + Sized,
+        B: MakeWriter + Sized,
+        W: Write,
+    {
+        OrElse::new(self, other)
     }
 }
 
@@ -77,6 +473,156 @@ pub struct TestWriter {
     _p: (),
 }
 
+/// A writer that erases the specific [`io::Write`] and [`MakeWriter`] types being used.
+///
+/// This is useful in cases where the concrete type of the writer cannot be known
+/// until runtime.
+///
+/// # Examples
+///
+/// A function that returns a [`Subscriber`] that will write to either stdout or stderr:
+///
+/// ```rust
+/// # use tracing::Subscriber;
+/// # use tracing_subscriber::fmt::writer::BoxMakeWriter;
+///
+/// fn dynamic_writer(use_stderr: bool) -> impl Subscriber {
+///     let writer = if use_stderr {
+///         BoxMakeWriter::new(std::io::stderr)
+///     } else {
+///         BoxMakeWriter::new(std::io::stdout)
+///     };
+///
+///     tracing_subscriber::fmt().with_writer(writer).finish()
+/// }
+/// ```
+///
+/// [`Subscriber`]: tracing::Subscriber
+/// [`io::Write`]: std::io::Write
+pub struct BoxMakeWriter {
+    inner: Box<dyn MakeWriter<Writer = Box<dyn Write + 'static>> + Send + Sync>,
+    name: &'static str,
+}
+
+/// A [writer] that is one of two types implementing [`io::Write`][writer].
+///
+/// This may be used by [`MakeWriter`] implementations that may conditionally
+/// return one of two writers.
+///
+/// [writer]: std::io::Write
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum EitherWriter<A, B> {
+    /// A writer of type `A`.
+    A(A),
+    /// A writer of type `B`.
+    B(B),
+}
+
+/// A [writer] which may or may not be enabled.
+///
+/// This may be used by [`MakeWriter`] implementations that wish to
+/// conditionally enable or disable the returned writer based on a span or
+/// event's [`Metadata`].
+///
+/// [writer]: std::io::Write
+pub type OptionalWriter<T> = EitherWriter<T, std::io::Sink>;
+
+/// A [`MakeWriter`] combinator that only returns an enabled [writer] for spans
+/// and events with metadata at or below a specified verbosity [`Level`].
+///
+/// This is returned by the [`MakeWriterExt::with_max_level] method. See the
+/// method documentation for details.
+///
+/// [writer]: std::io::Write
+/// [`Level`]: tracing_core::Level
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct WithMaxLevel<M> {
+    make: M,
+    level: tracing_core::Level,
+}
+
+/// A [`MakeWriter`] combinator that only returns an enabled [writer] for spans
+/// and events with metadata at or above a specified verbosity [`Level`].
+///
+/// This is returned by the [`MakeWriterExt::with_min_level] method. See the
+/// method documentation for details.
+///
+/// [writer]: std::io::Write
+/// [`Level`]: tracing_core::Level
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct WithMinLevel<M> {
+    make: M,
+    level: tracing_core::Level,
+}
+
+/// A [`MakeWriter`] combinator that wraps a [`MakeWriter`] with a predicate for
+/// span and event [`Metadata`], so that the [`MakeWriterExt::make_writer_for`]
+/// method returns [`OptionalWriter::some`] when the predicate returns `true`,
+/// and [`OptionalWriter::none`] when the predicate returns `false`.
+///
+/// This is returned by the [`MakeWriterExt::with_filter`] method. See the
+/// method documentation for details.
+///
+/// [`Metadata`]: tracing_core::Metadata
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct WithFilter<M, F> {
+    make: M,
+    filter: F,
+}
+
+/// Combines a [`MakeWriter`] that returns an [`OptionalWriter`] with another
+/// [`MakeWriter`], so that the second [`MakeWriter`] is used when the first
+/// [`MakeWriter`] returns [`OptionalWriter::none`].
+///
+/// This is returned by the [`MakeWriterExt::or_else] method. See the
+/// method documentation for details.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct OrElse<A, B> {
+    inner: A,
+    or_else: B,
+}
+
+/// Combines two types implementing [`MakeWriter`] (or [`std::io::Write`]) to
+/// produce a writer that writes to both [`MakeWriter`]'s returned writers.
+///
+/// This is returned by the [`MakeWriterExt::and`] method. See the method
+/// documentation for details.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct Tee<A, B> {
+    a: A,
+    b: B,
+}
+
+impl<F, W> MakeWriter for F
+where
+    F: Fn() -> W,
+    W: io::Write,
+{
+    type Writer = W;
+
+    fn make_writer(&self) -> Self::Writer {
+        (self)()
+    }
+}
+
+impl<W> MakeWriter for Arc<W>
+where
+    for<'a> &'a W: io::Write,
+{
+    type Writer = ArcWriter<W>;
+    fn make_writer(&self) -> Self::Writer {
+        ArcWriter(self.clone())
+    }
+}
+
+/// Implements [`std::io::Write`] for an [`Arc`]<W> where `&W: Write`.
+///
+/// This is an implementation detail of the [`MakeWriter`] impl for [`Arc`].
+#[derive(Clone, Debug)]
+pub struct ArcWriter<W>(Arc<W>);
+
+// === impl TestWriter ===
+
 impl TestWriter {
     /// Returns a new `TestWriter` with the default configuration.
     pub fn new() -> Self {
@@ -104,37 +650,6 @@ impl MakeWriter for TestWriter {
     }
 }
 
-/// A writer that erases the specific [`io::Write`] and [`Makewriter`] types being used.
-///
-/// This is useful in cases where the concrete type of the writer cannot be known
-/// until runtime.
-///
-/// # Examples
-///
-/// A function that returns a [`Subscriber`] that will write to either stdout or stderr:
-///
-/// ```rust
-/// # use tracing::Subscriber;
-/// # use tracing_subscriber::fmt::writer::BoxMakeWriter;
-///
-/// fn dynamic_writer(use_stderr: bool) -> impl Subscriber {
-///     let writer = if use_stderr {
-///         BoxMakeWriter::new(std::io::stderr)
-///     } else {
-///         BoxMakeWriter::new(std::io::stdout)
-///     };
-///
-///     tracing_subscriber::fmt().with_writer(writer).finish()
-/// }
-/// ```
-///
-/// [`MakeWriter`]: trait.MakeWriter.html
-/// [`Subscriber`]: https://docs.rs/tracing/latest/tracing/trait.Subscriber.html
-/// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
-pub struct BoxMakeWriter {
-    inner: Box<dyn MakeWriter<Writer = Box<dyn Write>> + Send + Sync>,
-}
-
 impl BoxMakeWriter {
     /// Constructs a `BoxMakeWriter` wrapping a type implementing [`MakeWriter`].
     ///
@@ -146,13 +661,16 @@ impl BoxMakeWriter {
     {
         Self {
             inner: Box::new(Boxed(make_writer)),
+            name: std::any::type_name::<M>(),
         }
     }
 }
 
 impl Debug for BoxMakeWriter {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        f.pad("BoxMakeWriter { ... }")
+        f.debug_tuple("BoxMakeWriter")
+            .field(&format_args!("<{}>", self.name))
+            .finish()
     }
 }
 
@@ -162,6 +680,10 @@ impl MakeWriter for BoxMakeWriter {
     fn make_writer(&self) -> Self::Writer {
         self.inner.make_writer()
     }
+
+    fn make_writer_for(&self, meta: &Metadata<'_>) -> Self::Writer {
+        self.inner.make_writer_for(meta)
+    }
 }
 
 struct Boxed<M>(M);
@@ -174,19 +696,367 @@ where
     type Writer = Box<dyn Write>;
 
     fn make_writer(&self) -> Self::Writer {
-        Box::new(self.0.make_writer())
+        let w = self.0.make_writer();
+        Box::new(w)
+    }
+
+    fn make_writer_for(&self, meta: &Metadata<'_>) -> Self::Writer {
+        let w = self.0.make_writer_for(meta);
+        Box::new(w)
+    }
+}
+
+// === impl EitherWriter ===
+
+impl<A, B> io::Write for EitherWriter<A, B>
+where
+    A: io::Write,
+    B: io::Write,
+{
+    #[inline]
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        match self {
+            EitherWriter::A(a) => a.write(buf),
+            EitherWriter::B(b) => b.write(buf),
+        }
+    }
+
+    #[inline]
+    fn flush(&mut self) -> io::Result<()> {
+        match self {
+            EitherWriter::A(a) => a.flush(),
+            EitherWriter::B(b) => b.flush(),
+        }
+    }
+
+    #[inline]
+    fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
+        match self {
+            EitherWriter::A(a) => a.write_vectored(bufs),
+            EitherWriter::B(b) => b.write_vectored(bufs),
+        }
+    }
+
+    #[inline]
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        match self {
+            EitherWriter::A(a) => a.write_all(buf),
+            EitherWriter::B(b) => b.write_all(buf),
+        }
+    }
+
+    #[inline]
+    fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()> {
+        match self {
+            EitherWriter::A(a) => a.write_fmt(fmt),
+            EitherWriter::B(b) => b.write_fmt(fmt),
+        }
+    }
+}
+
+impl<T> OptionalWriter<T> {
+    /// Returns a [disabled writer].
+    ///
+    /// Any bytes written to the returned writer are discarded.
+    ///
+    /// This is equivalent to returning [`Option::None`].
+    ///
+    /// [disabled writer]: std::io::sink
+    #[inline]
+    pub fn none() -> Self {
+        EitherWriter::B(std::io::sink())
+    }
+
+    /// Returns an enabled writer of type `T`.
+    ///
+    /// This is equivalent to returning [`Option::Some`].
+    #[inline]
+    pub fn some(t: T) -> Self {
+        EitherWriter::A(t)
+    }
+}
+
+impl<T> From<Option<T>> for OptionalWriter<T> {
+    #[inline]
+    fn from(opt: Option<T>) -> Self {
+        match opt {
+            Some(writer) => Self::some(writer),
+            None => Self::none(),
+        }
+    }
+}
+
+// === impl WithMaxLevel ===
+
+impl<M> WithMaxLevel<M> {
+    /// Wraps the provided [`MakeWriter`] with a maximum [`Level`], so that it
+    /// returns [`OptionalWriter::none`] for spans and events whose level is
+    /// more verbose than the maximum level.
+    ///
+    /// See [`MakeWriterExt::with_max_level`] for details.
+    ///
+    /// [`Level`]: tracing_core::Level
+    pub fn new(make: M, level: tracing_core::Level) -> Self {
+        Self { make, level }
+    }
+}
+
+impl<M: MakeWriter> MakeWriter for WithMaxLevel<M> {
+    type Writer = OptionalWriter<M::Writer>;
+
+    #[inline]
+    fn make_writer(&self) -> Self::Writer {
+        // If we don't know the level, assume it's disabled.
+        OptionalWriter::none()
+    }
+
+    #[inline]
+    fn make_writer_for(&self, meta: &Metadata<'_>) -> Self::Writer {
+        if meta.level() <= &self.level {
+            return OptionalWriter::some(self.make.make_writer_for(meta));
+        }
+        OptionalWriter::none()
+    }
+}
+
+// === impl WithMinLevel ===
+
+impl<M> WithMinLevel<M> {
+    /// Wraps the provided [`MakeWriter`] with a minimum [`Level`], so that it
+    /// returns [`OptionalWriter::none`] for spans and events whose level is
+    /// less verbose than the maximum level.
+    ///
+    /// See [`MakeWriterExt::with_min_level`] for details.
+    ///
+    /// [`Level`]: tracing_core::Level
+    pub fn new(make: M, level: tracing_core::Level) -> Self {
+        Self { make, level }
+    }
+}
+
+impl<M: MakeWriter> MakeWriter for WithMinLevel<M> {
+    type Writer = OptionalWriter<M::Writer>;
+
+    #[inline]
+    fn make_writer(&self) -> Self::Writer {
+        // If we don't know the level, assume it's disabled.
+        OptionalWriter::none()
+    }
+
+    #[inline]
+    fn make_writer_for(&self, meta: &Metadata<'_>) -> Self::Writer {
+        if meta.level() >= &self.level {
+            return OptionalWriter::some(self.make.make_writer_for(meta));
+        }
+        OptionalWriter::none()
+    }
+}
+
+// ==== impl WithFilter ===
+
+impl<M, F> WithFilter<M, F> {
+    /// Wraps `make` with the provided `filter`, returning a [`MakeWriter`] that
+    /// will call `make.make_writer_for()` when `filter` returns `true` for a
+    /// span or event's [`Metadata`], and returns a [`sink`] otherwise.
+    ///
+    /// See [`MakeWriterExt::with_filter`] for details.
+    ///
+    /// [`Metadata`]: tracing_core::Metadata
+    /// [`sink`]: std::io::sink
+    pub fn new(make: M, filter: F) -> Self
+    where
+        F: Fn(&Metadata<'_>) -> bool,
+    {
+        Self { make, filter }
+    }
+}
+
+impl<M, F> MakeWriter for WithFilter<M, F>
+where
+    M: MakeWriter,
+    F: Fn(&Metadata<'_>) -> bool,
+{
+    type Writer = OptionalWriter<M::Writer>;
+
+    #[inline]
+    fn make_writer(&self) -> Self::Writer {
+        OptionalWriter::some(self.make.make_writer())
+    }
+
+    #[inline]
+    fn make_writer_for(&self, meta: &Metadata<'_>) -> Self::Writer {
+        if (self.filter)(meta) {
+            OptionalWriter::some(self.make.make_writer_for(meta))
+        } else {
+            OptionalWriter::none()
+        }
+    }
+}
+
+// === impl Tee ===
+
+impl<A, B> Tee<A, B> {
+    /// Combines two types implementing [`MakeWriter`], returning
+    /// a new [`MakeWriter`] that produces [writers] that write to *both*
+    /// outputs.
+    ///
+    /// See the documentation for [`MakeWriterExt::and`] for details.
+    pub fn new(a: A, b: B) -> Self {
+        Self { a, b }
+    }
+}
+
+impl<A, B> MakeWriter for Tee<A, B>
+where
+    A: MakeWriter,
+    B: MakeWriter,
+{
+    type Writer = Tee<A::Writer, B::Writer>;
+
+    #[inline]
+    fn make_writer(&self) -> Self::Writer {
+        Tee::new(self.a.make_writer(), self.b.make_writer())
+    }
+
+    #[inline]
+    fn make_writer_for(&self, meta: &Metadata<'_>) -> Self::Writer {
+        Tee::new(self.a.make_writer_for(meta), self.b.make_writer_for(meta))
+    }
+}
+
+macro_rules! impl_tee {
+    ($self_:ident.$f:ident($($arg:ident),*)) => {
+        {
+            let res_a = $self_.a.$f($($arg),*);
+            let res_b = $self_.b.$f($($arg),*);
+            (res_a?, res_b?)
+        }
+    }
+}
+
+impl<A, B> io::Write for Tee<A, B>
+where
+    A: io::Write,
+    B: io::Write,
+{
+    #[inline]
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        let (a, b) = impl_tee!(self.write(buf));
+        Ok(std::cmp::max(a, b))
+    }
+
+    #[inline]
+    fn flush(&mut self) -> io::Result<()> {
+        impl_tee!(self.flush());
+        Ok(())
+    }
+
+    #[inline]
+    fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
+        let (a, b) = impl_tee!(self.write_vectored(bufs));
+        Ok(std::cmp::max(a, b))
+    }
+
+    #[inline]
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        impl_tee!(self.write_all(buf));
+        Ok(())
+    }
+
+    #[inline]
+    fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()> {
+        impl_tee!(self.write_fmt(fmt));
+        Ok(())
+    }
+}
+
+// === impl OrElse ===
+
+impl<A, B> OrElse<A, B> {
+    /// Combines
+    pub fn new<W>(inner: A, or_else: B) -> Self
+    where
+        A: MakeWriter<Writer = OptionalWriter<W>>,
+        B: MakeWriter,
+        W: Write,
+    {
+        Self { inner, or_else }
+    }
+}
+
+impl<A, B, W> MakeWriter for OrElse<A, B>
+where
+    A: MakeWriter<Writer = OptionalWriter<W>>,
+    B: MakeWriter,
+    W: io::Write,
+{
+    type Writer = EitherWriter<W, B::Writer>;
+
+    #[inline]
+    fn make_writer(&self) -> Self::Writer {
+        match self.inner.make_writer() {
+            EitherWriter::A(writer) => EitherWriter::A(writer),
+            EitherWriter::B(_) => EitherWriter::B(self.or_else.make_writer()),
+        }
+    }
+
+    #[inline]
+    fn make_writer_for(&self, meta: &Metadata<'_>) -> Self::Writer {
+        match self.inner.make_writer_for(meta) {
+            EitherWriter::A(writer) => EitherWriter::A(writer),
+            EitherWriter::B(_) => EitherWriter::B(self.or_else.make_writer_for(meta)),
+        }
+    }
+}
+
+// === impl ArcWriter ===
+
+impl<W> io::Write for ArcWriter<W>
+where
+    for<'a> &'a W: io::Write,
+{
+    #[inline]
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        (&*self.0).write(buf)
+    }
+
+    #[inline]
+    fn flush(&mut self) -> io::Result<()> {
+        (&*self.0).flush()
+    }
+
+    #[inline]
+    fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
+        (&*self.0).write_vectored(bufs)
+    }
+
+    #[inline]
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        (&*self.0).write_all(buf)
+    }
+
+    #[inline]
+    fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()> {
+        (&*self.0).write_fmt(fmt)
     }
 }
 
+// === blanket impls ===
+
+impl<M> MakeWriterExt for M where M: MakeWriter {}
+
 #[cfg(test)]
 mod test {
-    use super::MakeWriter;
+    use super::*;
     use crate::fmt::format::Format;
     use crate::fmt::test::{MockMakeWriter, MockWriter};
     use crate::fmt::Subscriber;
     use lazy_static::lazy_static;
-    use std::sync::Mutex;
-    use tracing::error;
+    use std::sync::{
+        atomic::{AtomicBool, Ordering},
+        Mutex,
+    };
+    use tracing::{debug, error, info, trace, warn, Level};
     use tracing_core::dispatcher::{self, Dispatch};
 
     fn test_writer<T>(make_writer: T, msg: &str, buf: &Mutex<Vec<u8>>)
@@ -222,6 +1092,19 @@ mod test {
         assert!(actual.contains(expected.as_str()));
     }
 
+    fn has_lines(buf: &Mutex<Vec<u8>>, msgs: &[(tracing::Level, &str)]) {
+        let actual = String::from_utf8(buf.try_lock().unwrap().to_vec()).unwrap();
+        let mut expected_lines = msgs.iter();
+        for line in actual.lines() {
+            let line = dbg!(line).trim();
+            let (level, msg) = expected_lines
+                .next()
+                .unwrap_or_else(|| panic!("expected no more lines, but got: {:?}", line));
+            let expected = format!("{} {}: {}", level, module_path!(), msg);
+            assert_eq!(line, expected.as_str());
+        }
+    }
+
     #[test]
     fn custom_writer_closure() {
         lazy_static! {
@@ -243,4 +1126,195 @@ mod test {
         let msg = "my custom writer struct error";
         test_writer(make_writer, msg, &BUF);
     }
+
+    #[test]
+    fn combinators_level_filters() {
+        lazy_static! {
+            static ref INFO_BUF: Mutex<Vec<u8>> = Mutex::new(vec![]);
+            static ref DEBUG_BUF: Mutex<Vec<u8>> = Mutex::new(vec![]);
+            static ref WARN_BUF: Mutex<Vec<u8>> = Mutex::new(vec![]);
+            static ref ERR_BUF: Mutex<Vec<u8>> = Mutex::new(vec![]);
+        }
+
+        let info = MockMakeWriter::new(&INFO_BUF);
+        let debug = MockMakeWriter::new(&DEBUG_BUF);
+        let warn = MockMakeWriter::new(&WARN_BUF);
+        let err = MockMakeWriter::new(&ERR_BUF);
+
+        let make_writer = info
+            .with_max_level(Level::INFO)
+            .and(debug.with_max_level(Level::DEBUG))
+            .and(warn.with_max_level(Level::WARN))
+            .and(err.with_max_level(Level::ERROR));
+
+        let c = {
+            #[cfg(feature = "ansi")]
+            let f = Format::default().without_time().with_ansi(false);
+            #[cfg(not(feature = "ansi"))]
+            let f = Format::default().without_time();
+            Subscriber::builder()
+                .event_format(f)
+                .with_writer(make_writer)
+                .with_max_level(Level::TRACE)
+                .finish()
+        };
+
+        let _s = tracing::subscriber::set_default(c);
+
+        trace!("trace");
+        debug!("debug");
+        info!("info");
+        warn!("warn");
+        error!("error");
+
+        let all_lines = [
+            (Level::TRACE, "trace"),
+            (Level::DEBUG, "debug"),
+            (Level::INFO, "info"),
+            (Level::WARN, "warn"),
+            (Level::ERROR, "error"),
+        ];
+
+        println!("max level debug");
+        has_lines(&DEBUG_BUF, &all_lines[1..]);
+
+        println!("max level info");
+        has_lines(&INFO_BUF, &all_lines[2..]);
+
+        println!("max level warn");
+        has_lines(&WARN_BUF, &all_lines[3..]);
+
+        println!("max level error");
+        has_lines(&ERR_BUF, &all_lines[4..]);
+    }
+
+    #[test]
+    fn combinators_or_else() {
+        lazy_static! {
+            static ref SOME_BUF: Mutex<Vec<u8>> = Mutex::new(vec![]);
+            static ref OR_ELSE_BUF: Mutex<Vec<u8>> = Mutex::new(vec![]);
+        }
+
+        let some = MockMakeWriter::new(&SOME_BUF);
+        let or_else = MockMakeWriter::new(&OR_ELSE_BUF);
+
+        let return_some = AtomicBool::new(true);
+        let make_writer = move || {
+            if return_some.swap(false, Ordering::Relaxed) {
+                OptionalWriter::some(some.make_writer())
+            } else {
+                OptionalWriter::none()
+            }
+        };
+        let make_writer = make_writer.or_else(or_else);
+        let c = {
+            #[cfg(feature = "ansi")]
+            let f = Format::default().without_time().with_ansi(false);
+            #[cfg(not(feature = "ansi"))]
+            let f = Format::default().without_time();
+            Subscriber::builder()
+                .event_format(f)
+                .with_writer(make_writer)
+                .with_max_level(Level::TRACE)
+                .finish()
+        };
+
+        let _s = tracing::subscriber::set_default(c);
+        info!("hello");
+        info!("world");
+        info!("goodbye");
+
+        has_lines(&SOME_BUF, &[(Level::INFO, "hello")]);
+        has_lines(
+            &OR_ELSE_BUF,
+            &[(Level::INFO, "world"), (Level::INFO, "goodbye")],
+        );
+    }
+
+    #[test]
+    fn combinators_or_else_chain() {
+        lazy_static! {
+            static ref INFO_BUF: Mutex<Vec<u8>> = Mutex::new(vec![]);
+            static ref DEBUG_BUF: Mutex<Vec<u8>> = Mutex::new(vec![]);
+            static ref WARN_BUF: Mutex<Vec<u8>> = Mutex::new(vec![]);
+            static ref ERR_BUF: Mutex<Vec<u8>> = Mutex::new(vec![]);
+        }
+
+        let info = MockMakeWriter::new(&INFO_BUF);
+        let debug = MockMakeWriter::new(&DEBUG_BUF);
+        let warn = MockMakeWriter::new(&WARN_BUF);
+        let err = MockMakeWriter::new(&ERR_BUF);
+
+        let make_writer = err.with_max_level(Level::ERROR).or_else(
+            warn.with_max_level(Level::WARN).or_else(
+                info.with_max_level(Level::INFO)
+                    .or_else(debug.with_max_level(Level::DEBUG)),
+            ),
+        );
+
+        let c = {
+            #[cfg(feature = "ansi")]
+            let f = Format::default().without_time().with_ansi(false);
+            #[cfg(not(feature = "ansi"))]
+            let f = Format::default().without_time();
+            Subscriber::builder()
+                .event_format(f)
+                .with_writer(make_writer)
+                .with_max_level(Level::TRACE)
+                .finish()
+        };
+
+        let _s = tracing::subscriber::set_default(c);
+
+        trace!("trace");
+        debug!("debug");
+        info!("info");
+        warn!("warn");
+        error!("error");
+
+        println!("max level debug");
+        has_lines(&DEBUG_BUF, &[(Level::DEBUG, "debug")]);
+
+        println!("max level info");
+        has_lines(&INFO_BUF, &[(Level::INFO, "info")]);
+
+        println!("max level warn");
+        has_lines(&WARN_BUF, &[(Level::WARN, "warn")]);
+
+        println!("max level error");
+        has_lines(&ERR_BUF, &[(Level::ERROR, "error")]);
+    }
+
+    #[test]
+    fn combinators_and() {
+        lazy_static! {
+            static ref A_BUF: Mutex<Vec<u8>> = Mutex::new(vec![]);
+            static ref B_BUF: Mutex<Vec<u8>> = Mutex::new(vec![]);
+        }
+
+        let a = MockMakeWriter::new(&A_BUF);
+        let b = MockMakeWriter::new(&B_BUF);
+
+        let lines = &[(Level::INFO, "hello"), (Level::INFO, "world")];
+
+        let make_writer = a.and(b);
+        let c = {
+            #[cfg(feature = "ansi")]
+            let f = Format::default().without_time().with_ansi(false);
+            #[cfg(not(feature = "ansi"))]
+            let f = Format::default().without_time();
+            Subscriber::builder()
+                .event_format(f)
+                .with_writer(make_writer)
+                .with_max_level(Level::TRACE)
+                .finish()
+        };
+
+        let _s = tracing::subscriber::set_default(c);
+        info!("hello");
+        info!("world");
+
+        has_lines(&A_BUF, &lines[..]);
+        has_lines(&B_BUF, &lines[..]);
+    }
 }
index e3609c9b1876c6bb445dbb9651874492ed864d71..c886ade9bc9630fc27599679797f8d32decdef85 100644 (file)
@@ -90,8 +90,7 @@ use std::{any::TypeId, marker::PhantomData};
 ///
 /// Multiple `Layer`s may be composed in the same manner:
 /// ```rust
-/// # use tracing_subscriber::Layer;
-/// # use tracing_subscriber::prelude::*;
+/// # use tracing_subscriber::{Layer, layer::SubscriberExt};
 /// # use tracing::Subscriber;
 /// pub struct MyOtherLayer {
 ///     // ...
@@ -212,9 +211,6 @@ where
     /// By default, this returns [`Interest::always()`] if [`self.enabled`] returns
     /// true, or [`Interest::never()`] if it returns false.
     ///
-    /// <div class="information">
-    ///     <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div>
-    /// </div>
     /// <div class="example-wrap" style="display:inline-block">
     /// <pre class="ignore" style="white-space:normal;font:inherit;">
     /// <strong>Note</strong>: This method (and <a href="#method.enabled">
@@ -264,9 +260,6 @@ where
     /// By default, this always returns `true`, allowing the wrapped subscriber
     /// to choose to disable the span.
     ///
-    /// <div class="information">
-    ///     <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div>
-    /// </div>
     /// <div class="example-wrap" style="display:inline-block">
     /// <pre class="ignore" style="white-space:normal;font:inherit;">
     /// <strong>Note</strong>: This method (and <a href="#method.register_callsite">
@@ -586,9 +579,24 @@ pub struct Identity {
 /// [`Context::scope`]: struct.Context.html#method.scope
 #[cfg(feature = "registry")]
 #[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
-pub struct Scope<'a, L: LookupSpan<'a>>(
-    Option<std::iter::Chain<registry::FromRoot<'a, L>, std::iter::Once<SpanRef<'a, L>>>>,
-);
+#[deprecated(note = "renamed to crate::registry::ScopeFromRoot", since = "0.2.19")]
+#[derive(Debug)]
+pub struct Scope<'a, L>(std::iter::Flatten<std::option::IntoIter<registry::ScopeFromRoot<'a, L>>>)
+where
+    L: LookupSpan<'a>;
+
+#[cfg(feature = "registry")]
+#[allow(deprecated)]
+impl<'a, L> Iterator for Scope<'a, L>
+where
+    L: LookupSpan<'a>,
+{
+    type Item = SpanRef<'a, L>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
 
 // === impl Layered ===
 
@@ -728,6 +736,9 @@ where
             return outer;
         }
 
+        // The intention behind calling `inner.register_callsite()` before the if statement
+        // is to ensure that the inner subscriber is informed that the callsite exists
+        // regardless of the outer subscriber's filtering decision.
         let inner = self.inner.register_callsite(metadata);
         if outer.is_sometimes() {
             // if this interest is "sometimes", return "sometimes" to ensure that
@@ -994,6 +1005,78 @@ where
         }
     }
 
+    /// Returns a [`SpanRef`] for the parent span of the given [`Event`], if
+    /// it has a parent.
+    ///
+    /// If the event has an explicitly overridden parent, this method returns
+    /// a reference to that span. If the event's parent is the current span,
+    /// this returns a reference to the current span, if there is one. If this
+    /// returns `None`, then either the event's parent was explicitly set to
+    /// `None`, or the event's parent was defined contextually, but no span
+    /// is currently entered.
+    ///
+    /// Compared to [`Context::current_span`] and [`Context::lookup_current`],
+    /// this respects overrides provided by the [`Event`].
+    ///
+    /// Compared to [`Event::parent`], this automatically falls back to the contextual
+    /// span, if required.
+    ///
+    /// ```rust
+    /// use tracing::{Event, Subscriber};
+    /// use tracing_subscriber::{
+    ///     layer::{Context, Layer},
+    ///     prelude::*,
+    ///     registry::LookupSpan,
+    /// };
+    ///
+    /// struct PrintingLayer;
+    /// impl<S> Layer<S> for PrintingLayer
+    /// where
+    ///     S: Subscriber + for<'lookup> LookupSpan<'lookup>,
+    /// {
+    ///     fn on_event(&self, event: &Event, ctx: Context<S>) {
+    ///         let span = ctx.event_span(event);
+    ///         println!("Event in span: {:?}", span.map(|s| s.name()));
+    ///     }
+    /// }
+    ///
+    /// tracing::subscriber::with_default(tracing_subscriber::registry().with(PrintingLayer), || {
+    ///     tracing::info!("no span");
+    ///     // Prints: Event in span: None
+    ///
+    ///     let span = tracing::info_span!("span");
+    ///     tracing::info!(parent: &span, "explicitly specified");
+    ///     // Prints: Event in span: Some("span")
+    ///
+    ///     let _guard = span.enter();
+    ///     tracing::info!("contextual span");
+    ///     // Prints: Event in span: Some("span")
+    /// });
+    /// ```
+    ///
+    /// <div class="example-wrap" style="display:inline-block">
+    /// <pre class="ignore" style="white-space:normal;font:inherit;">
+    /// <strong>Note</strong>: This requires the wrapped subscriber to implement the
+    /// <a href="../registry/trait.LookupSpan.html"><code>LookupSpan</code></a> trait.
+    /// See the documentation on <a href="./struct.Context.html"><code>Context</code>'s
+    /// declaration</a> for details.
+    /// </pre></div>
+    #[inline]
+    #[cfg(feature = "registry")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
+    pub fn event_span(&self, event: &Event<'_>) -> Option<SpanRef<'_, S>>
+    where
+        S: for<'lookup> LookupSpan<'lookup>,
+    {
+        if event.is_root() {
+            None
+        } else if event.is_contextual() {
+            self.lookup_current()
+        } else {
+            event.parent().and_then(|id| self.span(id))
+        }
+    }
+
     /// Returns metadata for the span with the given `id`, if it exists.
     ///
     /// If this returns `None`, then no span exists for that ID (either it has
@@ -1014,9 +1097,6 @@ where
     /// If this returns `None`, then no span exists for that ID (either it has
     /// closed or the ID is invalid).
     ///
-    /// <div class="information">
-    ///     <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div>
-    /// </div>
     /// <div class="example-wrap" style="display:inline-block">
     /// <pre class="ignore" style="white-space:normal;font:inherit;">
     /// <strong>Note</strong>: This requires the wrapped subscriber to implement the
@@ -1038,9 +1118,6 @@ where
 
     /// Returns `true` if an active span exists for the given `Id`.
     ///
-    /// <div class="information">
-    ///     <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div>
-    /// </div>
     /// <div class="example-wrap" style="display:inline-block">
     /// <pre class="ignore" style="white-space:normal;font:inherit;">
     /// <strong>Note</strong>: This requires the wrapped subscriber to implement the
@@ -1063,9 +1140,6 @@ where
     ///
     /// If this returns `None`, then we are not currently within a span.
     ///
-    /// <div class="information">
-    ///     <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div>
-    /// </div>
     /// <div class="example-wrap" style="display:inline-block">
     /// <pre class="ignore" style="white-space:normal;font:inherit;">
     /// <strong>Note</strong>: This requires the wrapped subscriber to implement the
@@ -1100,6 +1174,51 @@ where
     ///
     /// If this iterator is empty, then there are no spans in the current context.
     ///
+    /// <div class="example-wrap" style="display:inline-block">
+    /// <pre class="ignore" style="white-space:normal;font:inherit;">
+    /// <strong>Note</strong>: This requires the wrapped subscriber to implement the
+    /// <a href="../registry/trait.LookupSpan.html"><code>LookupSpan</code></a> trait.
+    /// See the documentation on <a href="./struct.Context.html"><code>Context</code>'s
+    /// declaration</a> for details.
+    /// </pre></div>
+    ///
+    /// [stored data]: ../registry/struct.SpanRef.html
+    #[cfg(feature = "registry")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
+    #[deprecated(
+        note = "equivalent to `self.current_span().id().and_then(|id| self.span_scope(id).from_root())` but consider passing an explicit ID instead of relying on the contextual span",
+        since = "0.2.19"
+    )]
+    #[allow(deprecated)]
+    pub fn scope(&self) -> Scope<'_, S>
+    where
+        S: for<'lookup> registry::LookupSpan<'lookup>,
+    {
+        Scope(
+            self.lookup_current()
+                .as_ref()
+                .map(registry::SpanRef::scope)
+                .map(registry::Scope::from_root)
+                .into_iter()
+                .flatten(),
+        )
+    }
+
+    /// Returns an iterator over the [stored data] for all the spans in the
+    /// current context, starting with the specified span and ending with the
+    /// root of the trace tree and ending with the current span.
+    ///
+    /// <div class="information">
+    ///     <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div>
+    /// </div>
+    /// <div class="example-wrap" style="display:inline-block">
+    /// <pre class="ignore" style="white-space:normal;font:inherit;">
+    /// <strong>Note</strong>: Compared to <a href="#method.scope"><code>scope</code></a> this
+    /// returns the spans in reverse order (from leaf to root). Use
+    /// <a href="../registry/struct.Scope.html#method.from_root"><code>Scope::from_root</code></a>
+    /// in case root-to-leaf ordering is desired.
+    /// </pre></div>
+    ///
     /// <div class="information">
     ///     <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div>
     /// </div>
@@ -1114,15 +1233,41 @@ where
     /// [stored data]: ../registry/struct.SpanRef.html
     #[cfg(feature = "registry")]
     #[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
-    pub fn scope(&self) -> Scope<'_, S>
+    pub fn span_scope(&self, id: &span::Id) -> Option<registry::Scope<'_, S>>
     where
         S: for<'lookup> registry::LookupSpan<'lookup>,
     {
-        let scope = self.lookup_current().map(|span| {
-            let parents = span.from_root();
-            parents.chain(std::iter::once(span))
-        });
-        Scope(scope)
+        Some(self.span(id)?.scope())
+    }
+
+    /// Returns an iterator over the [stored data] for all the spans in the
+    /// current context, starting with the parent span of the specified event,
+    /// and ending with the root of the trace tree and ending with the current span.
+    ///
+    /// <div class="example-wrap" style="display:inline-block">
+    /// <pre class="ignore" style="white-space:normal;font:inherit;">
+    /// <strong>Note</strong>: Compared to <a href="#method.scope"><code>scope</code></a> this
+    /// returns the spans in reverse order (from leaf to root). Use
+    /// <a href="../registry/struct.Scope.html#method.from_root"><code>Scope::from_root</code></a>
+    /// in case root-to-leaf ordering is desired.
+    /// </pre></div>
+    ///
+    /// <div class="example-wrap" style="display:inline-block">
+    /// <pre class="ignore" style="white-space:normal;font:inherit;">
+    /// <strong>Note</strong>: This requires the wrapped subscriber to implement the
+    /// <a href="../registry/trait.LookupSpan.html"><code>LookupSpan</code></a> trait.
+    /// See the documentation on <a href="./struct.Context.html"><code>Context</code>'s
+    /// declaration</a> for details.
+    /// </pre></div>
+    ///
+    /// [stored data]: ../registry/struct.SpanRef.html
+    #[cfg(feature = "registry")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
+    pub fn event_scope(&self, event: &Event<'_>) -> Option<registry::Scope<'_, S>>
+    where
+        S: for<'lookup> registry::LookupSpan<'lookup>,
+    {
+        Some(self.event_span(event)?.scope())
     }
 }
 
@@ -1135,11 +1280,7 @@ impl<'a, S> Context<'a, S> {
 impl<'a, S> Clone for Context<'a, S> {
     #[inline]
     fn clone(&self) -> Self {
-        let subscriber = if let Some(ref subscriber) = self.subscriber {
-            Some(*subscriber)
-        } else {
-            None
-        };
+        let subscriber = self.subscriber.as_ref().copied();
         Context { subscriber }
     }
 }
@@ -1155,29 +1296,10 @@ impl Identity {
     }
 }
 
-// === impl Scope ===
-
-#[cfg(feature = "registry")]
-#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
-impl<'a, L: LookupSpan<'a>> Iterator for Scope<'a, L> {
-    type Item = SpanRef<'a, L>;
-
-    #[inline]
-    fn next(&mut self) -> Option<Self::Item> {
-        self.0.as_mut()?.next()
-    }
-}
-
-#[cfg(feature = "registry")]
-#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
-impl<'a, L: LookupSpan<'a>> std::fmt::Debug for Scope<'a, L> {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        f.pad("Scope { .. }")
-    }
-}
-
 #[cfg(test)]
 pub(crate) mod tests {
+    use std::sync::{Arc, Mutex};
+
     use super::*;
 
     pub(crate) struct NopSubscriber;
@@ -1271,8 +1393,8 @@ pub(crate) mod tests {
             .and_then(NopLayer)
             .and_then(NopLayer)
             .with_subscriber(StringSubscriber("subscriber".into()));
-        let subscriber =
-            Subscriber::downcast_ref::<StringSubscriber>(&s).expect("subscriber should downcast");
+        let subscriber = <dyn Subscriber>::downcast_ref::<StringSubscriber>(&s)
+            .expect("subscriber should downcast");
         assert_eq!(&subscriber.0, "subscriber");
     }
 
@@ -1282,11 +1404,51 @@ pub(crate) mod tests {
             .and_then(StringLayer2("layer_2".into()))
             .and_then(StringLayer3("layer_3".into()))
             .with_subscriber(NopSubscriber);
-        let layer = Subscriber::downcast_ref::<StringLayer>(&s).expect("layer 1 should downcast");
+        let layer =
+            <dyn Subscriber>::downcast_ref::<StringLayer>(&s).expect("layer 1 should downcast");
         assert_eq!(&layer.0, "layer_1");
-        let layer = Subscriber::downcast_ref::<StringLayer2>(&s).expect("layer 2 should downcast");
+        let layer =
+            <dyn Subscriber>::downcast_ref::<StringLayer2>(&s).expect("layer 2 should downcast");
         assert_eq!(&layer.0, "layer_2");
-        let layer = Subscriber::downcast_ref::<StringLayer3>(&s).expect("layer 3 should downcast");
+        let layer =
+            <dyn Subscriber>::downcast_ref::<StringLayer3>(&s).expect("layer 3 should downcast");
         assert_eq!(&layer.0, "layer_3");
     }
+
+    #[test]
+    fn context_event_span() {
+        let last_event_span = Arc::new(Mutex::new(None));
+
+        struct RecordingLayer {
+            last_event_span: Arc<Mutex<Option<&'static str>>>,
+        }
+
+        impl<S> Layer<S> for RecordingLayer
+        where
+            S: Subscriber + for<'lookup> LookupSpan<'lookup>,
+        {
+            fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
+                let span = ctx.event_span(event);
+                *self.last_event_span.lock().unwrap() = span.map(|s| s.name());
+            }
+        }
+
+        tracing::subscriber::with_default(
+            crate::registry().with(RecordingLayer {
+                last_event_span: last_event_span.clone(),
+            }),
+            || {
+                tracing::info!("no span");
+                assert_eq!(*last_event_span.lock().unwrap(), None);
+
+                let parent = tracing::info_span!("explicit");
+                tracing::info!(parent: &parent, "explicit span");
+                assert_eq!(*last_event_span.lock().unwrap(), Some("explicit"));
+
+                let _guard = tracing::info_span!("contextual").entered();
+                tracing::info!("contextual span");
+                assert_eq!(*last_event_span.lock().unwrap(), Some("contextual"));
+            },
+        );
+    }
 }
index de866af002560036cf1decc683f7d8937fb03c6b..041a387410465b6124dedeb20cb62bdc5466655e 100644 (file)
@@ -67,7 +67,7 @@
 //! [`env_logger` crate]: https://crates.io/crates/env_logger
 //! [`parking_lot`]: https://crates.io/crates/parking_lot
 //! [`registry`]: registry/index.html
-#![doc(html_root_url = "https://docs.rs/tracing-subscriber/0.2.18")]
+#![doc(html_root_url = "https://docs.rs/tracing-subscriber/0.2.19")]
 #![doc(
     html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
     issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
index 0264c2d5087afbb5eb013aba59839fe30d570b92..396825a6fb171aaa529e7eced55f28b155ebeb57 100644 (file)
@@ -12,3 +12,7 @@ pub use crate::layer::{
 };
 
 pub use crate::util::SubscriberInitExt as _;
+
+#[cfg(feature = "fmt")]
+#[cfg_attr(docsrs, doc(cfg(feature = "fmt")))]
+pub use crate::fmt::writer::MakeWriterExt as _;
index cc84e5fb5c1bc509bfb1f7f8e9bee8448bd51c86..0761c528a8e662362dcec3f209230f8fe495723a 100644 (file)
@@ -62,6 +62,8 @@
 //! [lookup]: ../layer/struct.Context.html#method.span
 //! [`LookupSpan`]: trait.LookupSpan.html
 //! [`SpanData`]: trait.SpanData.html
+use std::fmt::Debug;
+
 use tracing_core::{field::FieldSet, span::Id, Metadata};
 
 /// A module containing a type map of span extensions.
@@ -94,9 +96,6 @@ pub trait LookupSpan<'a> {
 
     /// Returns the [`SpanData`] for a given `Id`, if it exists.
     ///
-    /// <div class="information">
-    ///     <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div>
-    /// </div>
     /// <div class="example-wrap" style="display:inline-block">
     /// <pre class="ignore" style="white-space:normal;font:inherit;">
     /// <strong>Note</strong>: users of the <code>LookupSpan</code> trait should
@@ -171,15 +170,112 @@ pub struct SpanRef<'a, R: LookupSpan<'a>> {
     data: R::Data,
 }
 
+/// An iterator over the parents of a span, ordered from leaf to root.
+///
+/// This is returned by the [`SpanRef::scope`] method.
+#[derive(Debug)]
+pub struct Scope<'a, R> {
+    registry: &'a R,
+    next: Option<Id>,
+}
+
+impl<'a, R> Scope<'a, R>
+where
+    R: LookupSpan<'a>,
+{
+    /// Flips the order of the iterator, so that it is ordered from root to leaf.
+    ///
+    /// The iterator will first return the root span, then that span's immediate child,
+    /// and so on until it finally returns the span that [`SpanRef::scope`] was called on.
+    ///
+    /// If any items were consumed from the [`Scope`] before calling this method then they
+    /// will *not* be returned from the [`ScopeFromRoot`].
+    ///
+    /// **Note**: this will allocate if there are many spans remaining, or if the
+    /// "smallvec" feature flag is not enabled.
+    #[allow(clippy::wrong_self_convention)]
+    pub fn from_root(self) -> ScopeFromRoot<'a, R> {
+        #[cfg(feature = "smallvec")]
+        type Buf<T> = smallvec::SmallVec<T>;
+        #[cfg(not(feature = "smallvec"))]
+        type Buf<T> = Vec<T>;
+        ScopeFromRoot {
+            spans: self.collect::<Buf<_>>().into_iter().rev(),
+        }
+    }
+}
+
+impl<'a, R> Iterator for Scope<'a, R>
+where
+    R: LookupSpan<'a>,
+{
+    type Item = SpanRef<'a, R>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let curr = self.registry.span(self.next.as_ref()?)?;
+        self.next = curr.parent_id().cloned();
+        Some(curr)
+    }
+}
+
+/// An iterator over the parents of a span, ordered from root to leaf.
+///
+/// This is returned by the [`Scope::from_root`] method.
+pub struct ScopeFromRoot<'a, R>
+where
+    R: LookupSpan<'a>,
+{
+    #[cfg(feature = "smallvec")]
+    spans: std::iter::Rev<smallvec::IntoIter<SpanRefVecArray<'a, R>>>,
+    #[cfg(not(feature = "smallvec"))]
+    spans: std::iter::Rev<std::vec::IntoIter<SpanRef<'a, R>>>,
+}
+
+impl<'a, R> Iterator for ScopeFromRoot<'a, R>
+where
+    R: LookupSpan<'a>,
+{
+    type Item = SpanRef<'a, R>;
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        self.spans.next()
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.spans.size_hint()
+    }
+}
+
+impl<'a, R> Debug for ScopeFromRoot<'a, R>
+where
+    R: LookupSpan<'a>,
+{
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.pad("ScopeFromRoot { .. }")
+    }
+}
+
 /// An iterator over the parents of a span.
 ///
 /// This is returned by the [`SpanRef::parents`] method.
 ///
 /// [`SpanRef::parents`]: struct.SpanRef.html#method.parents
+#[deprecated(note = "replaced by `Scope`")]
 #[derive(Debug)]
-pub struct Parents<'a, R> {
-    registry: &'a R,
-    next: Option<Id>,
+pub struct Parents<'a, R>(Scope<'a, R>);
+
+#[allow(deprecated)]
+impl<'a, R> Iterator for Parents<'a, R>
+where
+    R: LookupSpan<'a>,
+{
+    type Item = SpanRef<'a, R>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
 }
 
 /// An iterator over a span's parents, starting with the root of the trace
@@ -188,11 +284,22 @@ pub struct Parents<'a, R> {
 /// For additonal details, see [`SpanRef::from_root`].
 ///
 /// [`Span::from_root`]: struct.SpanRef.html#method.from_root
-pub struct FromRoot<'a, R: LookupSpan<'a>> {
-    #[cfg(feature = "smallvec")]
-    inner: std::iter::Rev<smallvec::IntoIter<SpanRefVecArray<'a, R>>>,
-    #[cfg(not(feature = "smallvec"))]
-    inner: std::iter::Rev<std::vec::IntoIter<SpanRef<'a, R>>>,
+#[deprecated(note = "replaced by `ScopeFromRoot`", since = "0.2.19")]
+#[derive(Debug)]
+pub struct FromRoot<'a, R>(ScopeFromRoot<'a, R>)
+where
+    R: LookupSpan<'a>;
+
+#[allow(deprecated)]
+impl<'a, R> Iterator for FromRoot<'a, R>
+where
+    R: LookupSpan<'a>,
+{
+    type Item = SpanRef<'a, R>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
 }
 
 #[cfg(feature = "smallvec")]
@@ -241,17 +348,95 @@ where
         })
     }
 
+    /// Returns an iterator over all parents of this span, starting with this span,
+    /// ordered from leaf to root.
+    ///
+    /// The iterator will first return the span, then the span's immediate parent,
+    /// followed by that span's parent, and so on, until it reaches a root span.
+    ///
+    /// ```rust
+    /// use tracing::{span, Subscriber};
+    /// use tracing_subscriber::{
+    ///     layer::{Context, Layer},
+    ///     prelude::*,
+    ///     registry::LookupSpan,
+    /// };
+    ///
+    /// struct PrintingLayer;
+    /// impl<S> Layer<S> for PrintingLayer
+    /// where
+    ///     S: Subscriber + for<'lookup> LookupSpan<'lookup>,
+    /// {
+    ///     fn on_enter(&self, id: &span::Id, ctx: Context<S>) {
+    ///         let span = ctx.span(id).unwrap();
+    ///         let scope = span.scope().map(|span| span.name()).collect::<Vec<_>>();
+    ///         println!("Entering span: {:?}", scope);
+    ///     }
+    /// }
+    ///
+    /// tracing::subscriber::with_default(tracing_subscriber::registry().with(PrintingLayer), || {
+    ///     let _root = tracing::info_span!("root").entered();
+    ///     // Prints: Entering span: ["root"]
+    ///     let _child = tracing::info_span!("child").entered();
+    ///     // Prints: Entering span: ["child", "root"]
+    ///     let _leaf = tracing::info_span!("leaf").entered();
+    ///     // Prints: Entering span: ["leaf", "child", "root"]
+    /// });
+    /// ```
+    ///
+    /// If the opposite order (from the root to this span) is desired, calling [`Scope::from_root`] on
+    /// the returned iterator reverses the order.
+    ///
+    /// ```rust
+    /// # use tracing::{span, Subscriber};
+    /// # use tracing_subscriber::{
+    /// #     layer::{Context, Layer},
+    /// #     prelude::*,
+    /// #     registry::LookupSpan,
+    /// # };
+    /// # struct PrintingLayer;
+    /// impl<S> Layer<S> for PrintingLayer
+    /// where
+    ///     S: Subscriber + for<'lookup> LookupSpan<'lookup>,
+    /// {
+    ///     fn on_enter(&self, id: &span::Id, ctx: Context<S>) {
+    ///         let span = ctx.span(id).unwrap();
+    ///         let scope = span.scope().from_root().map(|span| span.name()).collect::<Vec<_>>();
+    ///         println!("Entering span: {:?}", scope);
+    ///     }
+    /// }
+    ///
+    /// tracing::subscriber::with_default(tracing_subscriber::registry().with(PrintingLayer), || {
+    ///     let _root = tracing::info_span!("root").entered();
+    ///     // Prints: Entering span: ["root"]
+    ///     let _child = tracing::info_span!("child").entered();
+    ///     // Prints: Entering span: ["root", "child"]
+    ///     let _leaf = tracing::info_span!("leaf").entered();
+    ///     // Prints: Entering span: ["root", "child", "leaf"]
+    /// });
+    /// ```
+    pub fn scope(&self) -> Scope<'a, R> {
+        Scope {
+            registry: self.registry,
+            next: Some(self.id()),
+        }
+    }
+
     /// Returns an iterator over all parents of this span, starting with the
     /// immediate parent.
     ///
     /// The iterator will first return the span's immediate parent, followed by
     /// that span's parent, followed by _that_ span's parent, and so on, until a
     /// it reaches a root span.
+    #[deprecated(
+        note = "equivalent to `self.parent().into_iter().flat_map(SpanRef::scope)`, but consider whether excluding `self` is actually intended"
+    )]
+    #[allow(deprecated)]
     pub fn parents(&self) -> Parents<'a, R> {
-        Parents {
+        Parents(Scope {
             registry: self.registry,
-            next: self.parent().map(|parent| parent.id()),
-        }
+            next: self.parent_id().cloned(),
+        })
     }
 
     /// Returns an iterator over all parents of this span, starting with the
@@ -261,20 +446,15 @@ where
     /// next span, and then the next, until this span's immediate parent is
     /// returned.
     ///
-    /// **Note**: if the "smallvec" feature flag is not enabled, this may
-    /// allocate.
+    /// **Note**: this will allocate if there are many spans remaining, or if the
+    /// "smallvec" feature flag is not enabled.
+    #[deprecated(
+        note = "equivalent to `self.parent().into_iter().flat_map(|span| span.scope().from_root())`, but consider whether excluding `self` is actually intended",
+        since = "0.2.19"
+    )]
+    #[allow(deprecated)]
     pub fn from_root(&self) -> FromRoot<'a, R> {
-        #[cfg(feature = "smallvec")]
-        type SpanRefVec<'span, L> = smallvec::SmallVec<SpanRefVecArray<'span, L>>;
-        #[cfg(not(feature = "smallvec"))]
-        type SpanRefVec<'span, L> = Vec<SpanRef<'span, L>>;
-
-        // an alternative way to handle this would be to the recursive approach that
-        // `fmt` uses that _does not_ entail any allocation in this fmt'ing
-        // spans path.
-        let parents = self.parents().collect::<SpanRefVec<'a, _>>();
-        let inner = parents.into_iter().rev();
-        FromRoot { inner }
+        FromRoot(self.parents().0.from_root())
     }
 
     /// Returns a reference to this span's `Extensions`.
@@ -294,43 +474,87 @@ where
     }
 }
 
-impl<'a, R> Iterator for Parents<'a, R>
-where
-    R: LookupSpan<'a>,
-{
-    type Item = SpanRef<'a, R>;
-    fn next(&mut self) -> Option<Self::Item> {
-        let id = self.next.take()?;
-        let span = self.registry.span(&id)?;
-        self.next = span.parent().map(|parent| parent.id());
-        Some(span)
-    }
-}
+#[cfg(test)]
+mod tests {
+    use crate::{
+        layer::{Context, Layer},
+        prelude::*,
+        registry::LookupSpan,
+    };
+    use std::sync::{Arc, Mutex};
+    use tracing::{span, Subscriber};
 
-// === impl FromRoot ===
+    #[test]
+    fn spanref_scope_iteration_order() {
+        let last_entered_scope = Arc::new(Mutex::new(Vec::new()));
 
-impl<'span, R> Iterator for FromRoot<'span, R>
-where
-    R: LookupSpan<'span>,
-{
-    type Item = SpanRef<'span, R>;
+        #[derive(Default)]
+        struct PrintingLayer {
+            last_entered_scope: Arc<Mutex<Vec<&'static str>>>,
+        }
 
-    #[inline]
-    fn next(&mut self) -> Option<Self::Item> {
-        self.inner.next()
-    }
+        impl<S> Layer<S> for PrintingLayer
+        where
+            S: Subscriber + for<'lookup> LookupSpan<'lookup>,
+        {
+            fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
+                let span = ctx.span(id).unwrap();
+                let scope = span.scope().map(|span| span.name()).collect::<Vec<_>>();
+                *self.last_entered_scope.lock().unwrap() = scope;
+            }
+        }
 
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
+        let _guard = tracing::subscriber::set_default(crate::registry().with(PrintingLayer {
+            last_entered_scope: last_entered_scope.clone(),
+        }));
+
+        let _root = tracing::info_span!("root").entered();
+        assert_eq!(&*last_entered_scope.lock().unwrap(), &["root"]);
+        let _child = tracing::info_span!("child").entered();
+        assert_eq!(&*last_entered_scope.lock().unwrap(), &["child", "root"]);
+        let _leaf = tracing::info_span!("leaf").entered();
+        assert_eq!(
+            &*last_entered_scope.lock().unwrap(),
+            &["leaf", "child", "root"]
+        );
     }
-}
 
-impl<'span, R> std::fmt::Debug for FromRoot<'span, R>
-where
-    R: LookupSpan<'span>,
-{
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        f.pad("FromRoot { .. }")
+    #[test]
+    fn spanref_scope_fromroot_iteration_order() {
+        let last_entered_scope = Arc::new(Mutex::new(Vec::new()));
+
+        #[derive(Default)]
+        struct PrintingLayer {
+            last_entered_scope: Arc<Mutex<Vec<&'static str>>>,
+        }
+
+        impl<S> Layer<S> for PrintingLayer
+        where
+            S: Subscriber + for<'lookup> LookupSpan<'lookup>,
+        {
+            fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
+                let span = ctx.span(id).unwrap();
+                let scope = span
+                    .scope()
+                    .from_root()
+                    .map(|span| span.name())
+                    .collect::<Vec<_>>();
+                *self.last_entered_scope.lock().unwrap() = scope;
+            }
+        }
+
+        let _guard = tracing::subscriber::set_default(crate::registry().with(PrintingLayer {
+            last_entered_scope: last_entered_scope.clone(),
+        }));
+
+        let _root = tracing::info_span!("root").entered();
+        assert_eq!(&*last_entered_scope.lock().unwrap(), &["root"]);
+        let _child = tracing::info_span!("child").entered();
+        assert_eq!(&*last_entered_scope.lock().unwrap(), &["root", "child",]);
+        let _leaf = tracing::info_span!("leaf").entered();
+        assert_eq!(
+            &*last_entered_scope.lock().unwrap(),
+            &["root", "child", "leaf"]
+        );
     }
 }
index fab3fbc65c82008fdcba1fe48e0bfc49dc3712f5..b5356d6fb697973cb01875706898416a10ad5c3f 100644 (file)
@@ -1 +1 @@
-{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"8452340e67a2d103187a46f09e9c9a981120479bd70085c028a571569efc4290","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"71bd3581953027c1fd8c82f794ffb373e7b7eed704cdebeb02a870396379ca2f","benches/bench.rs":"827e5343b059a732904be29717c2797203bfd0a633edf08042afea65372a3e2c","scripts/unicode.py":"7b716876b745a624d3c78e8fec66524b4d50447c9337395b133691198c3cd3d2","src/__test_api.rs":"78e21bfa0b98894f545c8ed3e31cec20d7a48951a7f3ed69a6130c4b3d463aee","src/decompose.rs":"c0eb774843a545356e63bbcd7fb926f80d3c97ef4601ca3701fc34154f2e9905","src/lib.rs":"a93a99fa75e3ad0116a662243119ad0a4efaa72e8a1cf02ce6115ba4fa5f6959","src/lookups.rs":"ca7022bf19a82108df1f5bd78c7fc30806f931d932a65538be818caaa5f7049d","src/no_std_prelude.rs":"602e81e67b8952b6571826f431e3b6787be3073bc10f38a0d3374278f81a6a1f","src/normalize.rs":"de2670b4437d335d42884af844a750f70e541467ecd34077dfe032103cb9b041","src/perfect_hash.rs":"400c84e2f467f61bd55d55d08672da6a9ad7a57c938ce5d0c701a6994b1b273b","src/quick_check.rs":"9756312d75fc31b67fca954e44a4812945a7e436b03ba18b9a2441f6de570f6f","src/recompose.rs":"a6228ad7561a5c7a1ef1d510159bdde1eea8a161007c80e470432e9b844d5536","src/replace.rs":"b24c904f3e00851a78820e30ddfa4ff10c795f8925fd0ee7f5870f31fdfa770b","src/stream_safe.rs":"383d71f0da401af8e735877e43855c7e16cb06deb2263539cdec2a407dbe257d","src/tables.rs":"adb2c5098f1ebcb76a580f99b00c1f368ed140b7e5707284639605d9ace9605a","src/test.rs":"0def2cb0a013fba29938262b3cd3533fbb10eacaf6bcd82eef1f91759fe0a2eb"},"package":"33717dca7ac877f497014e10d73f3acf948c342bee31b5ca7892faf94ccc6b49"}
\ No newline at end of file
+{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"34370ae727c107ec51fd6809e01ff76220a1bcc2b849b8d277bf9c7bf1875abd","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"80e4415e2f0941aac11b7e5c1db946d00139db2f1a67774fcd0c0bfde52217fe","benches/bench.rs":"827e5343b059a732904be29717c2797203bfd0a633edf08042afea65372a3e2c","scripts/unicode.py":"c00cb48507e4564a2dcf17a95a5fb1206830f748a8444d296f95b5d2dd09b72c","src/__test_api.rs":"78e21bfa0b98894f545c8ed3e31cec20d7a48951a7f3ed69a6130c4b3d463aee","src/decompose.rs":"c0eb774843a545356e63bbcd7fb926f80d3c97ef4601ca3701fc34154f2e9905","src/lib.rs":"3eaa16b8b4d2d8e15d38b56760fb432ec7665e22360fd4c587c9b724486ba90e","src/lookups.rs":"ca7022bf19a82108df1f5bd78c7fc30806f931d932a65538be818caaa5f7049d","src/no_std_prelude.rs":"602e81e67b8952b6571826f431e3b6787be3073bc10f38a0d3374278f81a6a1f","src/normalize.rs":"de2670b4437d335d42884af844a750f70e541467ecd34077dfe032103cb9b041","src/perfect_hash.rs":"400c84e2f467f61bd55d55d08672da6a9ad7a57c938ce5d0c701a6994b1b273b","src/quick_check.rs":"9756312d75fc31b67fca954e44a4812945a7e436b03ba18b9a2441f6de570f6f","src/recompose.rs":"a6228ad7561a5c7a1ef1d510159bdde1eea8a161007c80e470432e9b844d5536","src/replace.rs":"b24c904f3e00851a78820e30ddfa4ff10c795f8925fd0ee7f5870f31fdfa770b","src/stream_safe.rs":"383d71f0da401af8e735877e43855c7e16cb06deb2263539cdec2a407dbe257d","src/tables.rs":"d24cf5a2a6d5059543b39eec6806c93fa8c314b52b251ddd354affcf91ef7f0b","src/test.rs":"0def2cb0a013fba29938262b3cd3533fbb10eacaf6bcd82eef1f91759fe0a2eb"},"package":"d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"}
\ No newline at end of file
index 2270a1b9ce2fe70de17660df420ef453ca01c837..d941fb39f5a9520c33918eecfc406d5148bde9a1 100644 (file)
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "unicode-normalization"
-version = "0.1.18"
+version = "0.1.19"
 authors = ["kwantam <kwantam@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>"]
 exclude = ["target/*", "Cargo.lock", "scripts/tmp", "*.txt", "tests/*"]
 description = "This crate provides functions for normalization of\nUnicode strings, including Canonical and Compatible\nDecomposition and Recomposition, as described in\nUnicode Standard Annex #15.\n"
index bb9a8ce9561d358ba354cdd4325285677fd46c49..746a7e024df5111b0819ba83278567abe70230cb 100644 (file)
@@ -31,7 +31,7 @@ to your `Cargo.toml`:
 
 ```toml
 [dependencies]
-unicode-normalization = "0.1.18"
+unicode-normalization = "0.1.19"
 ```
 
 ## `no_std` + `alloc` support
index e81784e98ef1a4f036d712e455259af05ef660ea..c4a1a2b43d176a41bfe10c9e75dff262974a6615 100644 (file)
@@ -102,12 +102,13 @@ class UnicodeData(object):
 
         assigned_start = 0;
         prev_char_int = -1;
+        prev_name = "";
 
         for line in self._fetch("UnicodeData.txt").splitlines():
             # See ftp://ftp.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.html
             pieces = line.split(';')
             assert len(pieces) == 15
-            char, category, cc, decomp = pieces[0], pieces[2], pieces[3], pieces[5]
+            char, name, category, cc, decomp = pieces[0], pieces[1], pieces[2], pieces[3], pieces[5]
             char_int = int(char, 16)
 
             name = pieces[1].strip()
@@ -126,10 +127,11 @@ class UnicodeData(object):
 
             assert category != 'Cn', "Unexpected: Unassigned codepoint in UnicodeData.txt"
             if category not in ['Co', 'Cs']:
-                if char_int != prev_char_int + 1:
+                if char_int != prev_char_int + 1 and not is_first_and_last(prev_name, name):
                     self.general_category_public_assigned.append((assigned_start, prev_char_int))
                     assigned_start = char_int
                 prev_char_int = char_int
+                prev_name = name;
 
         self.general_category_public_assigned.append((assigned_start, prev_char_int))
 
@@ -343,6 +345,15 @@ class UnicodeData(object):
 
 hexify = lambda c: '{:04X}'.format(c)
 
+# Test whether `first` and `last` are corresponding "<..., First>" and
+# "<..., Last>" markers.
+def is_first_and_last(first, last):
+    if not first.startswith('<') or not first.endswith(', First>'):
+        return False
+    if not last.startswith('<') or not last.endswith(', Last>'):
+        return False
+    return first[1:-8] == last[1:-7]
+
 def gen_mph_data(name, d, kv_type, kv_callback):
     (salt, keys) = minimal_perfect_hash(d)
     out.write("pub(crate) const %s_SALT: &[u16] = &[\n" % name.upper())
index 306884c9282c691e644a6af9e511cb8d8ebd565f..2c3a0902b41943a90da137cfd4465c2fd36344f9 100644 (file)
@@ -34,7 +34,7 @@
 //!
 //! ```toml
 //! [dependencies]
-//! unicode-normalization = "0.1.18"
+//! unicode-normalization = "0.1.19"
 //! ```
 
 #![deny(missing_docs, unsafe_code)]
index 87f26158c4475e5c5c7755d79f7ede9b5136f838..0477b5099d736c7617bdf4281a19caf3436c0a6c 100644 (file)
@@ -22051,9 +22051,7 @@ pub fn is_public_assigned(c: char) -> bool {
         | '\u{3131}'..='\u{318E}'
         | '\u{3190}'..='\u{31E3}'
         | '\u{31F0}'..='\u{321E}'
-        | '\u{3220}'..='\u{3400}'
-        | '\u{4DBF}'..='\u{4E00}'
-        | '\u{9FFC}'
+        | '\u{3220}'..='\u{9FFC}'
         | '\u{A000}'..='\u{A48C}'
         | '\u{A490}'..='\u{A4C6}'
         | '\u{A4D0}'..='\u{A62B}'
@@ -22083,8 +22081,7 @@ pub fn is_public_assigned(c: char) -> bool {
         | '\u{AB30}'..='\u{AB6B}'
         | '\u{AB70}'..='\u{ABED}'
         | '\u{ABF0}'..='\u{ABF9}'
-        | '\u{AC00}'
-        | '\u{D7A3}'
+        | '\u{AC00}'..='\u{D7A3}'
         | '\u{D7B0}'..='\u{D7C6}'
         | '\u{D7CB}'..='\u{D7FB}'
         | '\u{F900}'..='\u{FA6D}'
@@ -22305,11 +22302,9 @@ pub fn is_public_assigned(c: char) -> bool {
         | '\u{16F8F}'..='\u{16F9F}'
         | '\u{16FE0}'..='\u{16FE4}'
         | '\u{16FF0}'..='\u{16FF1}'
-        | '\u{17000}'
-        | '\u{187F7}'
+        | '\u{17000}'..='\u{187F7}'
         | '\u{18800}'..='\u{18CD5}'
-        | '\u{18D00}'
-        | '\u{18D08}'
+        | '\u{18D00}'..='\u{18D08}'
         | '\u{1B000}'..='\u{1B11E}'
         | '\u{1B150}'..='\u{1B152}'
         | '\u{1B164}'..='\u{1B167}'
@@ -22439,19 +22434,13 @@ pub fn is_public_assigned(c: char) -> bool {
         | '\u{1FB00}'..='\u{1FB92}'
         | '\u{1FB94}'..='\u{1FBCA}'
         | '\u{1FBF0}'..='\u{1FBF9}'
-        | '\u{20000}'
-        | '\u{2A6DD}'
-        | '\u{2A700}'
-        | '\u{2B734}'
-        | '\u{2B740}'
-        | '\u{2B81D}'
-        | '\u{2B820}'
-        | '\u{2CEA1}'
-        | '\u{2CEB0}'
-        | '\u{2EBE0}'
+        | '\u{20000}'..='\u{2A6DD}'
+        | '\u{2A700}'..='\u{2B734}'
+        | '\u{2B740}'..='\u{2B81D}'
+        | '\u{2B820}'..='\u{2CEA1}'
+        | '\u{2CEB0}'..='\u{2EBE0}'
         | '\u{2F800}'..='\u{2FA1D}'
-        | '\u{30000}'
-        | '\u{3134A}'
+        | '\u{30000}'..='\u{3134A}'
         | '\u{E0001}'
         | '\u{E0020}'..='\u{E007F}'
         | '\u{E0100}'..='\u{E01EF}'
index 23095fda1f999cdfb1b43430de7de8bcdc1f51dd..44c6c80d27d000c730bbf21eb5e2fa00796e21fc 100644 (file)
@@ -1 +1 @@
-{"files":{"Cargo.toml":"2075a4c7ee09fc661e19b5fc312568f294aff59942595920b8956d54669bc9cd","README.md":"14f5fffdc485176a2ab2e04555231042d0f7d818dbf1a0749a1ecbd8a0d4d500","scripts/unicode.py":"bf8a81cd85e692f36807f784ffd05cd9713b363e068cabd5c5e88a9026748109","src/lib.rs":"4ec3bd6b34e4a957ab875e3c71e5d1130923c976aff327f2de5ae02a0eaa9ad4","src/tables.rs":"9d2696f563cee5ab3c231fd9b68772758675951611e7d2f5f483445dcd4a9b7e"},"package":"79bf4d5fc96546fdb73f9827097810bbda93b11a6770ff3a54e1f445d4135787"}
\ No newline at end of file
+{"files":{"Cargo.toml":"3b6e9ba98b2f20b8b8a13f2e961a78691a064dcd1ae0d5bcfaf26216b2bb9c68","README.md":"14f5fffdc485176a2ab2e04555231042d0f7d818dbf1a0749a1ecbd8a0d4d500","scripts/unicode.py":"53803e407327679983929fbbdaf874c44c21b6f775eb48690dd52528dd3f4a51","src/lib.rs":"1e67da407be73a423a1de030f1397864aa454925a8582e027e9a9246529bf0b6","src/tables.rs":"6303916c60cee9abfa380b345536177415f042f36df3479d35c17b3587e65479"},"package":"098ec66172ce21cd55f8bcc786ee209dd20e04eff70acfca30cb79924d173ae9"}
\ No newline at end of file
index 452894e08982ed23f7dd0dc1de0ba62db3971f6b..6dfc011485499ff37f24178d30a441290152d796 100644 (file)
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "unicode-script"
-version = "0.5.2"
+version = "0.5.3"
 authors = ["Manish Goregaokar <manishsmail@gmail.com>"]
 exclude = ["target/*", "Cargo.lock", "scripts/tmp", "*.txt"]
 description = "This crate exposes the Unicode `Script` and `Script_Extension` properties from [UAX #24](http://www.unicode.org/reports/tr24/)\n"
index 26761642a1088e0ff5a4688d909bb11cc921aa61..e40a92c6df43cf6c4196ce182e3cb23f3e9c8820 100644 (file)
@@ -34,7 +34,16 @@ preamble = '''// Copyright 2012-2018 The Rust Project Developers. See the COPYRI
 
 #![allow(missing_docs, non_upper_case_globals, non_snake_case)]
 
-use super::ScriptExtension;
+pub use tables_impl::*;
+
+#[rustfmt::skip]
+mod tables_impl {
+use crate::ScriptExtension;
+'''
+
+# Close `mod impl {`
+ending='''
+}
 '''
 
 UNICODE_VERSION = (13, 0, 0)
@@ -239,7 +248,21 @@ pub mod script_extensions {
         f.write("    /// %s\n    pub const %s: ScriptExtension = %s;\n" % (longform, name, expr))
     f.write("""}
 
-impl Script {
+""")
+
+    # Generate implementation for the `Script`
+    generate_script_impl(f)
+
+
+def generate_script_impl(f):
+    """Generates an `impl Script { ... }` section with all the required functions"""
+
+    # Open `impl Script` section.
+    f.write("""impl Script {
+""")
+
+    # Generate impl of `inner_full_name`.
+    f.write("""
     #[inline]
     pub(crate) fn inner_full_name(self) -> &'static str {
         match self {
@@ -251,7 +274,26 @@ impl Script {
         f.write("            Script::%s => \"%s\",\n" % (longforms[script], longforms[script]))
     f.write("""        }
     }
+""")
+
+    # Generate impl of `inner_from_full_name`.
+    f.write("""
+    #[inline]
+    pub(crate) fn inner_from_full_name(input: &str) -> Option<Self> {
+        match input {
+            "Unknown" => Some(Script::Unknown),
+            "Common" => Some(Script::Common),
+            "Inherited" => Some(Script::Inherited),
+""")
+    for script in script_list:
+        f.write("            \"%s\" => Some(Script::%s),\n" % (longforms[script], longforms[script]))
+    f.write("            _ => None,\n" )
+    f.write("""        }
+    }
+""")
 
+    # Generate impl of `inner_short_name`
+    f.write("""
     #[inline]
     pub(crate) fn inner_short_name(self) -> &'static str {
         match self {
@@ -263,7 +305,25 @@ impl Script {
         f.write("            Script::%s => \"%s\",\n" % (longforms[script], script))
     f.write("""        }
     }
+""")
 
+    # Generate impl of `inner_from_short_name`
+    f.write("""
+    #[inline]
+    pub(crate) fn inner_from_short_name(input: &str) -> Option<Self> {
+        match input {
+            "Zyyy" => Some(Script::Common),
+            "Zinh" => Some(Script::Inherited),
+""")
+    for script in script_list:
+        f.write("            \"%s\" => Some(Script::%s),\n" % (script, longforms[script]))
+    f.write("""        _ => None,\n""")
+    f.write("""        }
+    }
+""")
+
+    # Generate impl of `for_integer`
+    f.write("""
     #[inline]
     pub(crate) fn for_integer(value: u8) -> Self {
         match value {
@@ -273,6 +333,10 @@ impl Script {
     f.write("""            _ => unreachable!(),
         }
     }
+""")
+
+    # Close `impl Script` section
+    f.write("""
 }
 """)
 
@@ -281,8 +345,6 @@ def extension_name(ext):
     return "script_extensions::%s" % "_".join([e.upper() for e in ext])
 
 
-
-
 if __name__ == "__main__":
     r = "tables.rs"
     if os.path.exists(r):
@@ -336,3 +398,5 @@ pub const UNICODE_VERSION: (u64, u64, u64) = (%s, %s, %s);
                    is_pub=False , pfun=lambda x: "(%s,%s,%s)" % (escape_char(x[0]), escape_char(x[1]), extension_name(x[2])))
 
         # emit_table(rf, "FOObar", properties)
+
+        rf.write(ending)
index 3b68a55256790ce6ef45440fb9ed1fb8cad525c0..d650ee0b21933e947c79f25639463cf869b33d69 100644 (file)
@@ -4,7 +4,6 @@
 #![cfg_attr(not(test), no_std)]
 #![cfg_attr(feature = "bench", feature(test))]
 
-#[rustfmt::skip]
 mod tables;
 
 use core::convert::TryFrom;
@@ -15,16 +14,30 @@ use tables::{get_script, get_script_extension, NEXT_SCRIPT};
 pub use tables::{Script, UNICODE_VERSION};
 
 impl Script {
-    /// Get the full name of a script
+    /// Get the full name of a script.
     pub fn full_name(self) -> &'static str {
         self.inner_full_name()
     }
 
-    /// Get the four-character short name of a script
+    /// Attempts to parse script name from the provided string.
+    /// Returns `None` if the provided string does not represent a valid
+    /// script full name.
+    pub fn from_full_name(input: &str) -> Option<Self> {
+        Self::inner_from_full_name(input)
+    }
+
+    /// Get the four-character short name of a script.
     pub fn short_name(self) -> &'static str {
         self.inner_short_name()
     }
 
+    /// Attempts to parse script name from the provided string.
+    /// Returns `None` if the provided string does not represent a valid
+    /// script four-character short name.
+    pub fn from_short_name(input: &str) -> Option<Self> {
+        Self::inner_from_short_name(input)
+    }
+
     /// Is this script "Recommended" according to
     /// [UAX #31](www.unicode.org/reports/tr31/#Table_Recommended_Scripts)?
     pub fn is_recommended(self) -> bool {
index c7cf53c3aec8a593848eb8ab713b1ce3cc445957..e31a7229febd4c177f8d6c96667c9cc6d69097c5 100644 (file)
 
 #![allow(missing_docs, non_upper_case_globals, non_snake_case)]
 
-use super::ScriptExtension;
+pub use tables_impl::*;
+
+#[rustfmt::skip]
+mod tables_impl {
+use crate::ScriptExtension;
 
 /// The version of [Unicode](http://www.unicode.org/)
 /// that this version of unicode-script is based on.
@@ -1053,6 +1057,7 @@ pub mod script_extensions {
 }
 
 impl Script {
+
     #[inline]
     pub(crate) fn inner_full_name(self) -> &'static str {
         match self {
@@ -1216,6 +1221,170 @@ impl Script {
         }
     }
 
+    #[inline]
+    pub(crate) fn inner_from_full_name(input: &str) -> Option<Self> {
+        match input {
+            "Unknown" => Some(Script::Unknown),
+            "Common" => Some(Script::Common),
+            "Inherited" => Some(Script::Inherited),
+            "Adlam" => Some(Script::Adlam),
+            "Caucasian_Albanian" => Some(Script::Caucasian_Albanian),
+            "Ahom" => Some(Script::Ahom),
+            "Arabic" => Some(Script::Arabic),
+            "Imperial_Aramaic" => Some(Script::Imperial_Aramaic),
+            "Armenian" => Some(Script::Armenian),
+            "Avestan" => Some(Script::Avestan),
+            "Balinese" => Some(Script::Balinese),
+            "Bamum" => Some(Script::Bamum),
+            "Bassa_Vah" => Some(Script::Bassa_Vah),
+            "Batak" => Some(Script::Batak),
+            "Bengali" => Some(Script::Bengali),
+            "Bhaiksuki" => Some(Script::Bhaiksuki),
+            "Bopomofo" => Some(Script::Bopomofo),
+            "Brahmi" => Some(Script::Brahmi),
+            "Braille" => Some(Script::Braille),
+            "Buginese" => Some(Script::Buginese),
+            "Buhid" => Some(Script::Buhid),
+            "Chakma" => Some(Script::Chakma),
+            "Canadian_Aboriginal" => Some(Script::Canadian_Aboriginal),
+            "Carian" => Some(Script::Carian),
+            "Cham" => Some(Script::Cham),
+            "Cherokee" => Some(Script::Cherokee),
+            "Chorasmian" => Some(Script::Chorasmian),
+            "Coptic" => Some(Script::Coptic),
+            "Cypriot" => Some(Script::Cypriot),
+            "Cyrillic" => Some(Script::Cyrillic),
+            "Devanagari" => Some(Script::Devanagari),
+            "Dives_Akuru" => Some(Script::Dives_Akuru),
+            "Dogra" => Some(Script::Dogra),
+            "Deseret" => Some(Script::Deseret),
+            "Duployan" => Some(Script::Duployan),
+            "Egyptian_Hieroglyphs" => Some(Script::Egyptian_Hieroglyphs),
+            "Elbasan" => Some(Script::Elbasan),
+            "Elymaic" => Some(Script::Elymaic),
+            "Ethiopic" => Some(Script::Ethiopic),
+            "Georgian" => Some(Script::Georgian),
+            "Glagolitic" => Some(Script::Glagolitic),
+            "Gunjala_Gondi" => Some(Script::Gunjala_Gondi),
+            "Masaram_Gondi" => Some(Script::Masaram_Gondi),
+            "Gothic" => Some(Script::Gothic),
+            "Grantha" => Some(Script::Grantha),
+            "Greek" => Some(Script::Greek),
+            "Gujarati" => Some(Script::Gujarati),
+            "Gurmukhi" => Some(Script::Gurmukhi),
+            "Hangul" => Some(Script::Hangul),
+            "Han" => Some(Script::Han),
+            "Hanunoo" => Some(Script::Hanunoo),
+            "Hatran" => Some(Script::Hatran),
+            "Hebrew" => Some(Script::Hebrew),
+            "Hiragana" => Some(Script::Hiragana),
+            "Anatolian_Hieroglyphs" => Some(Script::Anatolian_Hieroglyphs),
+            "Pahawh_Hmong" => Some(Script::Pahawh_Hmong),
+            "Nyiakeng_Puachue_Hmong" => Some(Script::Nyiakeng_Puachue_Hmong),
+            "Old_Hungarian" => Some(Script::Old_Hungarian),
+            "Old_Italic" => Some(Script::Old_Italic),
+            "Javanese" => Some(Script::Javanese),
+            "Kayah_Li" => Some(Script::Kayah_Li),
+            "Katakana" => Some(Script::Katakana),
+            "Kharoshthi" => Some(Script::Kharoshthi),
+            "Khmer" => Some(Script::Khmer),
+            "Khojki" => Some(Script::Khojki),
+            "Khitan_Small_Script" => Some(Script::Khitan_Small_Script),
+            "Kannada" => Some(Script::Kannada),
+            "Kaithi" => Some(Script::Kaithi),
+            "Tai_Tham" => Some(Script::Tai_Tham),
+            "Lao" => Some(Script::Lao),
+            "Latin" => Some(Script::Latin),
+            "Lepcha" => Some(Script::Lepcha),
+            "Limbu" => Some(Script::Limbu),
+            "Linear_A" => Some(Script::Linear_A),
+            "Linear_B" => Some(Script::Linear_B),
+            "Lisu" => Some(Script::Lisu),
+            "Lycian" => Some(Script::Lycian),
+            "Lydian" => Some(Script::Lydian),
+            "Mahajani" => Some(Script::Mahajani),
+            "Makasar" => Some(Script::Makasar),
+            "Mandaic" => Some(Script::Mandaic),
+            "Manichaean" => Some(Script::Manichaean),
+            "Marchen" => Some(Script::Marchen),
+            "Medefaidrin" => Some(Script::Medefaidrin),
+            "Mende_Kikakui" => Some(Script::Mende_Kikakui),
+            "Meroitic_Cursive" => Some(Script::Meroitic_Cursive),
+            "Meroitic_Hieroglyphs" => Some(Script::Meroitic_Hieroglyphs),
+            "Malayalam" => Some(Script::Malayalam),
+            "Modi" => Some(Script::Modi),
+            "Mongolian" => Some(Script::Mongolian),
+            "Mro" => Some(Script::Mro),
+            "Meetei_Mayek" => Some(Script::Meetei_Mayek),
+            "Multani" => Some(Script::Multani),
+            "Myanmar" => Some(Script::Myanmar),
+            "Nandinagari" => Some(Script::Nandinagari),
+            "Old_North_Arabian" => Some(Script::Old_North_Arabian),
+            "Nabataean" => Some(Script::Nabataean),
+            "Newa" => Some(Script::Newa),
+            "Nko" => Some(Script::Nko),
+            "Nushu" => Some(Script::Nushu),
+            "Ogham" => Some(Script::Ogham),
+            "Ol_Chiki" => Some(Script::Ol_Chiki),
+            "Old_Turkic" => Some(Script::Old_Turkic),
+            "Oriya" => Some(Script::Oriya),
+            "Osage" => Some(Script::Osage),
+            "Osmanya" => Some(Script::Osmanya),
+            "Palmyrene" => Some(Script::Palmyrene),
+            "Pau_Cin_Hau" => Some(Script::Pau_Cin_Hau),
+            "Old_Permic" => Some(Script::Old_Permic),
+            "Phags_Pa" => Some(Script::Phags_Pa),
+            "Inscriptional_Pahlavi" => Some(Script::Inscriptional_Pahlavi),
+            "Psalter_Pahlavi" => Some(Script::Psalter_Pahlavi),
+            "Phoenician" => Some(Script::Phoenician),
+            "Miao" => Some(Script::Miao),
+            "Inscriptional_Parthian" => Some(Script::Inscriptional_Parthian),
+            "Rejang" => Some(Script::Rejang),
+            "Hanifi_Rohingya" => Some(Script::Hanifi_Rohingya),
+            "Runic" => Some(Script::Runic),
+            "Samaritan" => Some(Script::Samaritan),
+            "Old_South_Arabian" => Some(Script::Old_South_Arabian),
+            "Saurashtra" => Some(Script::Saurashtra),
+            "SignWriting" => Some(Script::SignWriting),
+            "Shavian" => Some(Script::Shavian),
+            "Sharada" => Some(Script::Sharada),
+            "Siddham" => Some(Script::Siddham),
+            "Khudawadi" => Some(Script::Khudawadi),
+            "Sinhala" => Some(Script::Sinhala),
+            "Sogdian" => Some(Script::Sogdian),
+            "Old_Sogdian" => Some(Script::Old_Sogdian),
+            "Sora_Sompeng" => Some(Script::Sora_Sompeng),
+            "Soyombo" => Some(Script::Soyombo),
+            "Sundanese" => Some(Script::Sundanese),
+            "Syloti_Nagri" => Some(Script::Syloti_Nagri),
+            "Syriac" => Some(Script::Syriac),
+            "Tagbanwa" => Some(Script::Tagbanwa),
+            "Takri" => Some(Script::Takri),
+            "Tai_Le" => Some(Script::Tai_Le),
+            "New_Tai_Lue" => Some(Script::New_Tai_Lue),
+            "Tamil" => Some(Script::Tamil),
+            "Tangut" => Some(Script::Tangut),
+            "Tai_Viet" => Some(Script::Tai_Viet),
+            "Telugu" => Some(Script::Telugu),
+            "Tifinagh" => Some(Script::Tifinagh),
+            "Tagalog" => Some(Script::Tagalog),
+            "Thaana" => Some(Script::Thaana),
+            "Thai" => Some(Script::Thai),
+            "Tibetan" => Some(Script::Tibetan),
+            "Tirhuta" => Some(Script::Tirhuta),
+            "Ugaritic" => Some(Script::Ugaritic),
+            "Vai" => Some(Script::Vai),
+            "Warang_Citi" => Some(Script::Warang_Citi),
+            "Wancho" => Some(Script::Wancho),
+            "Old_Persian" => Some(Script::Old_Persian),
+            "Cuneiform" => Some(Script::Cuneiform),
+            "Yezidi" => Some(Script::Yezidi),
+            "Yi" => Some(Script::Yi),
+            "Zanabazar_Square" => Some(Script::Zanabazar_Square),
+            _ => None,
+        }
+    }
+
     #[inline]
     pub(crate) fn inner_short_name(self) -> &'static str {
         match self {
@@ -1379,6 +1548,169 @@ impl Script {
         }
     }
 
+    #[inline]
+    pub(crate) fn inner_from_short_name(input: &str) -> Option<Self> {
+        match input {
+            "Zyyy" => Some(Script::Common),
+            "Zinh" => Some(Script::Inherited),
+            "Adlm" => Some(Script::Adlam),
+            "Aghb" => Some(Script::Caucasian_Albanian),
+            "Ahom" => Some(Script::Ahom),
+            "Arab" => Some(Script::Arabic),
+            "Armi" => Some(Script::Imperial_Aramaic),
+            "Armn" => Some(Script::Armenian),
+            "Avst" => Some(Script::Avestan),
+            "Bali" => Some(Script::Balinese),
+            "Bamu" => Some(Script::Bamum),
+            "Bass" => Some(Script::Bassa_Vah),
+            "Batk" => Some(Script::Batak),
+            "Beng" => Some(Script::Bengali),
+            "Bhks" => Some(Script::Bhaiksuki),
+            "Bopo" => Some(Script::Bopomofo),
+            "Brah" => Some(Script::Brahmi),
+            "Brai" => Some(Script::Braille),
+            "Bugi" => Some(Script::Buginese),
+            "Buhd" => Some(Script::Buhid),
+            "Cakm" => Some(Script::Chakma),
+            "Cans" => Some(Script::Canadian_Aboriginal),
+            "Cari" => Some(Script::Carian),
+            "Cham" => Some(Script::Cham),
+            "Cher" => Some(Script::Cherokee),
+            "Chrs" => Some(Script::Chorasmian),
+            "Copt" => Some(Script::Coptic),
+            "Cprt" => Some(Script::Cypriot),
+            "Cyrl" => Some(Script::Cyrillic),
+            "Deva" => Some(Script::Devanagari),
+            "Diak" => Some(Script::Dives_Akuru),
+            "Dogr" => Some(Script::Dogra),
+            "Dsrt" => Some(Script::Deseret),
+            "Dupl" => Some(Script::Duployan),
+            "Egyp" => Some(Script::Egyptian_Hieroglyphs),
+            "Elba" => Some(Script::Elbasan),
+            "Elym" => Some(Script::Elymaic),
+            "Ethi" => Some(Script::Ethiopic),
+            "Geor" => Some(Script::Georgian),
+            "Glag" => Some(Script::Glagolitic),
+            "Gong" => Some(Script::Gunjala_Gondi),
+            "Gonm" => Some(Script::Masaram_Gondi),
+            "Goth" => Some(Script::Gothic),
+            "Gran" => Some(Script::Grantha),
+            "Grek" => Some(Script::Greek),
+            "Gujr" => Some(Script::Gujarati),
+            "Guru" => Some(Script::Gurmukhi),
+            "Hang" => Some(Script::Hangul),
+            "Hani" => Some(Script::Han),
+            "Hano" => Some(Script::Hanunoo),
+            "Hatr" => Some(Script::Hatran),
+            "Hebr" => Some(Script::Hebrew),
+            "Hira" => Some(Script::Hiragana),
+            "Hluw" => Some(Script::Anatolian_Hieroglyphs),
+            "Hmng" => Some(Script::Pahawh_Hmong),
+            "Hmnp" => Some(Script::Nyiakeng_Puachue_Hmong),
+            "Hung" => Some(Script::Old_Hungarian),
+            "Ital" => Some(Script::Old_Italic),
+            "Java" => Some(Script::Javanese),
+            "Kali" => Some(Script::Kayah_Li),
+            "Kana" => Some(Script::Katakana),
+            "Khar" => Some(Script::Kharoshthi),
+            "Khmr" => Some(Script::Khmer),
+            "Khoj" => Some(Script::Khojki),
+            "Kits" => Some(Script::Khitan_Small_Script),
+            "Knda" => Some(Script::Kannada),
+            "Kthi" => Some(Script::Kaithi),
+            "Lana" => Some(Script::Tai_Tham),
+            "Laoo" => Some(Script::Lao),
+            "Latn" => Some(Script::Latin),
+            "Lepc" => Some(Script::Lepcha),
+            "Limb" => Some(Script::Limbu),
+            "Lina" => Some(Script::Linear_A),
+            "Linb" => Some(Script::Linear_B),
+            "Lisu" => Some(Script::Lisu),
+            "Lyci" => Some(Script::Lycian),
+            "Lydi" => Some(Script::Lydian),
+            "Mahj" => Some(Script::Mahajani),
+            "Maka" => Some(Script::Makasar),
+            "Mand" => Some(Script::Mandaic),
+            "Mani" => Some(Script::Manichaean),
+            "Marc" => Some(Script::Marchen),
+            "Medf" => Some(Script::Medefaidrin),
+            "Mend" => Some(Script::Mende_Kikakui),
+            "Merc" => Some(Script::Meroitic_Cursive),
+            "Mero" => Some(Script::Meroitic_Hieroglyphs),
+            "Mlym" => Some(Script::Malayalam),
+            "Modi" => Some(Script::Modi),
+            "Mong" => Some(Script::Mongolian),
+            "Mroo" => Some(Script::Mro),
+            "Mtei" => Some(Script::Meetei_Mayek),
+            "Mult" => Some(Script::Multani),
+            "Mymr" => Some(Script::Myanmar),
+            "Nand" => Some(Script::Nandinagari),
+            "Narb" => Some(Script::Old_North_Arabian),
+            "Nbat" => Some(Script::Nabataean),
+            "Newa" => Some(Script::Newa),
+            "Nkoo" => Some(Script::Nko),
+            "Nshu" => Some(Script::Nushu),
+            "Ogam" => Some(Script::Ogham),
+            "Olck" => Some(Script::Ol_Chiki),
+            "Orkh" => Some(Script::Old_Turkic),
+            "Orya" => Some(Script::Oriya),
+            "Osge" => Some(Script::Osage),
+            "Osma" => Some(Script::Osmanya),
+            "Palm" => Some(Script::Palmyrene),
+            "Pauc" => Some(Script::Pau_Cin_Hau),
+            "Perm" => Some(Script::Old_Permic),
+            "Phag" => Some(Script::Phags_Pa),
+            "Phli" => Some(Script::Inscriptional_Pahlavi),
+            "Phlp" => Some(Script::Psalter_Pahlavi),
+            "Phnx" => Some(Script::Phoenician),
+            "Plrd" => Some(Script::Miao),
+            "Prti" => Some(Script::Inscriptional_Parthian),
+            "Rjng" => Some(Script::Rejang),
+            "Rohg" => Some(Script::Hanifi_Rohingya),
+            "Runr" => Some(Script::Runic),
+            "Samr" => Some(Script::Samaritan),
+            "Sarb" => Some(Script::Old_South_Arabian),
+            "Saur" => Some(Script::Saurashtra),
+            "Sgnw" => Some(Script::SignWriting),
+            "Shaw" => Some(Script::Shavian),
+            "Shrd" => Some(Script::Sharada),
+            "Sidd" => Some(Script::Siddham),
+            "Sind" => Some(Script::Khudawadi),
+            "Sinh" => Some(Script::Sinhala),
+            "Sogd" => Some(Script::Sogdian),
+            "Sogo" => Some(Script::Old_Sogdian),
+            "Sora" => Some(Script::Sora_Sompeng),
+            "Soyo" => Some(Script::Soyombo),
+            "Sund" => Some(Script::Sundanese),
+            "Sylo" => Some(Script::Syloti_Nagri),
+            "Syrc" => Some(Script::Syriac),
+            "Tagb" => Some(Script::Tagbanwa),
+            "Takr" => Some(Script::Takri),
+            "Tale" => Some(Script::Tai_Le),
+            "Talu" => Some(Script::New_Tai_Lue),
+            "Taml" => Some(Script::Tamil),
+            "Tang" => Some(Script::Tangut),
+            "Tavt" => Some(Script::Tai_Viet),
+            "Telu" => Some(Script::Telugu),
+            "Tfng" => Some(Script::Tifinagh),
+            "Tglg" => Some(Script::Tagalog),
+            "Thaa" => Some(Script::Thaana),
+            "Thai" => Some(Script::Thai),
+            "Tibt" => Some(Script::Tibetan),
+            "Tirh" => Some(Script::Tirhuta),
+            "Ugar" => Some(Script::Ugaritic),
+            "Vaii" => Some(Script::Vai),
+            "Wara" => Some(Script::Warang_Citi),
+            "Wcho" => Some(Script::Wancho),
+            "Xpeo" => Some(Script::Old_Persian),
+            "Xsux" => Some(Script::Cuneiform),
+            "Yezi" => Some(Script::Yezidi),
+            "Yiii" => Some(Script::Yi),
+            "Zanb" => Some(Script::Zanabazar_Square),
+        _ => None,
+        }
+    }
+
     #[inline]
     pub(crate) fn for_integer(value: u8) -> Self {
         match value {
@@ -1539,6 +1871,7 @@ impl Script {
             _ => unreachable!(),
         }
     }
+
 }
 
 pub fn bsearch_range_value_table<T: Copy>(c: char, r: &'static [(char, char, T)]) -> Option<T> {
@@ -2774,3 +3107,5 @@ pub fn get_script_extension(c: char) -> Option<ScriptExtension> {
         script_extensions::HANI), ('\u{1f250}', '\u{1f251}', script_extensions::HANI)
     ];
 
+
+}
index 0637aede930a1923079c98c6e1960c5d120a17d1..d1c574e8fb4f337bb7fb5c0693ae532289c5c92a 100644 (file)
@@ -1 +1 @@
-{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"7e287fc35f0e805cd03caf785de11fd8b5fc4aeff93e6f905c11b7195cbbe85d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"3c05436a2c9c04e3ea9692c1e9b189c2977a2e7a4b71c0641ebc8ed620894d28","benches/graphemes.rs":"d555b6e8cdfcb66b4d9ac4b35e250683922a15018fa1cd3a34111d3ee19b4221","scripts/unicode.py":"fa86bbf3dc3e0cc942592152a238305236fb7e96d8c1d5c7739168772d6f43f4","scripts/unicode_gen_breaktests.py":"ee96982d8959bec75c2382233cfca7e239f12a89a1be5fbf942601a215bb9283","src/grapheme.rs":"3e216182f92c2e4ac29ab4013884157bee8fb80ef8968725ae183fc5cfdb944c","src/lib.rs":"84c0b3acfa6527f1212c2a4cbea043d17e46ea7ae4bb1371c8816a843f99f142","src/sentence.rs":"de7968a54c387683a9e8369b6bd91b80752cefb9f772ce308dc7509829624c8b","src/tables.rs":"e5a5c04776f84f109a9005cc59df3709e2f1a3f0f27aa8f947f35aa87b499c91","src/test.rs":"0c9281ed39b4f94c1e4e7093d1342cfa54712c5a679b2fca3ee632b675b35f18","src/testdata.rs":"45f1877163fde1d801b41fcf13d7754437bb0a0f83e4b0b4fa3f37048ed6f12a","src/word.rs":"6166007c32233b52729aa726488878c0b39616aff351686e633ac0001ce52b17"},"package":"bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"}
\ No newline at end of file
+{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"02dd3f5519451193013b5df144d0f99e540112bb33d236fe8b9a036e2a3201c1","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"b8e6a4e1d40dde69fba80fa6335c15392d6c99b508f45969fc494cdae4ae73fe","benches/graphemes.rs":"189bb618682c9749e75634d21270fa0983994af94e41f4ba6934aae18029f8f5","benches/unicode_words.rs":"4661395ee20443651d3dd8d8e3a27f12853cfbd69c070479971ecd5a554a9b8d","benches/word_bounds.rs":"c0e88ba4189e18e147f3ca5eb6508ae6d2f150e65fccff1ee6c603df1b4b8680","scripts/unicode.py":"5bc2d5bc88a8b8c43fcb36ad24f9e2fe9d5733fcf827c592c63dac2d2cab8c78","scripts/unicode_gen_breaktests.py":"ee96982d8959bec75c2382233cfca7e239f12a89a1be5fbf942601a215bb9283","src/grapheme.rs":"9ceef75d9213073b09be9a769e4a1f7806d7c3ef7b7983553ec91324570bc3b1","src/lib.rs":"dd4dbcd94a90ec4f5cfceaedf54296530e78c7a9da382b41c801261fa6f3928e","src/sentence.rs":"b83793ff7540a457c49cd1ffd2a2fead4e584e31eac255f832da352d9eda3816","src/tables.rs":"6ddaa67756dbaa666b8704ea5bdeab2aee3a67ca125110bb7fb79d686878ffb2","src/test.rs":"eb63e48b8b594eec8c1ac35ea0a87de4f2dfde157689f2c90e2a63518dbc810a","src/testdata.rs":"45f1877163fde1d801b41fcf13d7754437bb0a0f83e4b0b4fa3f37048ed6f12a","src/word.rs":"b1d837116e6661825256c3722dfbca2e01a949fb19b622fcac713c8a3a8b96e0"},"package":"8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"}
\ No newline at end of file
index 0f21309c8774552ac3a2ce2cf19e36a9a8a6278d..583df10fca6b41d53525ab22015eddc20617ee1e 100644 (file)
@@ -11,8 +11,9 @@
 # will likely look very different (and much more reasonable)
 
 [package]
+edition = "2018"
 name = "unicode-segmentation"
-version = "1.7.1"
+version = "1.8.0"
 authors = ["kwantam <kwantam@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>"]
 exclude = ["target/*", "Cargo.lock", "scripts/tmp", "benches/texts/*", "*.txt"]
 description = "This crate provides Grapheme Cluster, Word and Sentence boundaries\naccording to Unicode Standard Annex #29 rules.\n"
@@ -26,8 +27,16 @@ repository = "https://github.com/unicode-rs/unicode-segmentation"
 [[bench]]
 name = "graphemes"
 harness = false
-[dev-dependencies.bencher]
-version = "0.1"
+
+[[bench]]
+name = "unicode_words"
+harness = false
+
+[[bench]]
+name = "word_bounds"
+harness = false
+[dev-dependencies.criterion]
+version = "0.3"
 
 [dev-dependencies.quickcheck]
 version = "0.7"
index 2f3bdca18ad4c85dce89f2d88d988531514cefca..a65c0e28ebabdb8e349b111f099c7b786d18e3dd 100644 (file)
@@ -38,7 +38,7 @@ to your `Cargo.toml`:
 
 ```toml
 [dependencies]
-unicode-segmentation = "1.7.1"
+unicode-segmentation = "1.8.0"
 ```
 
 # Change Log
index 5f14352f3ff7ed7a653758aa07c67bab7e468a37..8a7a379244cd8d2aa024f00d77c94727e5940d7c 100644 (file)
@@ -1,55 +1,54 @@
-#[macro_use]
-extern crate bencher;
-extern crate unicode_segmentation;
+use criterion::{black_box, criterion_group, criterion_main, Criterion};
+use unicode_segmentation;
 
-use bencher::Bencher;
-use unicode_segmentation::UnicodeSegmentation;
 use std::fs;
+use unicode_segmentation::UnicodeSegmentation;
 
-fn graphemes(bench: &mut Bencher, path: &str) {
+fn graphemes(c: &mut Criterion, lang: &str, path: &str) {
     let text = fs::read_to_string(path).unwrap();
-    bench.iter(|| {
-        for g in UnicodeSegmentation::graphemes(&*text, true) {
-            bencher::black_box(g);
-        }
-    });
 
-    bench.bytes = text.len() as u64;
+    c.bench_function(&format!("graphemes_{}",lang), |bench| {
+        bench.iter(|| {
+            for g in UnicodeSegmentation::graphemes(black_box(&*text), true) {
+                black_box(g);
+            }
+        })
+    });
 }
 
-fn graphemes_arabic(bench: &mut Bencher) {
-    graphemes(bench, "benches/texts/arabic.txt");
+fn graphemes_arabic(c: &mut Criterion) {
+    graphemes(c, "arabic" ,"benches/texts/arabic.txt");
 }
 
-fn graphemes_english(bench: &mut Bencher) {
-    graphemes(bench, "benches/texts/english.txt");
+fn graphemes_english(c: &mut Criterion) {
+    graphemes(c, "english" ,"benches/texts/english.txt");
 }
 
-fn graphemes_hindi(bench: &mut Bencher) {
-    graphemes(bench, "benches/texts/hindi.txt");
+fn graphemes_hindi(c: &mut Criterion) {
+    graphemes(c, "hindi" ,"benches/texts/hindi.txt");
 }
 
-fn graphemes_japanese(bench: &mut Bencher) {
-    graphemes(bench, "benches/texts/japanese.txt");
+fn graphemes_japanese(c: &mut Criterion) {
+    graphemes(c, "japanese" ,"benches/texts/japanese.txt");
 }
 
-fn graphemes_korean(bench: &mut Bencher) {
-    graphemes(bench, "benches/texts/korean.txt");
+fn graphemes_korean(c: &mut Criterion) {
+    graphemes(c, "korean" ,"benches/texts/korean.txt");
 }
 
-fn graphemes_mandarin(bench: &mut Bencher) {
-    graphemes(bench, "benches/texts/mandarin.txt");
+fn graphemes_mandarin(c: &mut Criterion) {
+    graphemes(c, "mandarin" ,"benches/texts/mandarin.txt");
 }
 
-fn graphemes_russian(bench: &mut Bencher) {
-    graphemes(bench, "benches/texts/russian.txt");
+fn graphemes_russian(c: &mut Criterion) {
+    graphemes(c, "russian" ,"benches/texts/russian.txt");
 }
 
-fn graphemes_source_code(bench: &mut Bencher) {
-    graphemes(bench, "benches/texts/source_code.txt");
+fn graphemes_source_code(c: &mut Criterion) {
+    graphemes(c, "source_code","benches/texts/source_code.txt");
 }
 
-benchmark_group!(
+criterion_group!(
     benches,
     graphemes_arabic,
     graphemes_english,
@@ -61,4 +60,4 @@ benchmark_group!(
     graphemes_source_code,
 );
 
-benchmark_main!(benches);
+criterion_main!(benches);
diff --git a/vendor/unicode-segmentation/benches/unicode_words.rs b/vendor/unicode-segmentation/benches/unicode_words.rs
new file mode 100644 (file)
index 0000000..731e325
--- /dev/null
@@ -0,0 +1,64 @@
+#[macro_use]
+extern crate bencher;
+extern crate unicode_segmentation;
+
+use bencher::Bencher;
+use unicode_segmentation::UnicodeSegmentation;
+use std::fs;
+
+fn unicode_words(bench: &mut Bencher, path: &str) {
+    let text = fs::read_to_string(path).unwrap();
+    bench.iter(|| {
+        for w in text.unicode_words() {
+            bencher::black_box(w);
+        }
+    });
+
+    bench.bytes = text.len() as u64;
+}
+
+fn unicode_words_arabic(bench: &mut Bencher) {
+    unicode_words(bench, "benches/texts/arabic.txt");
+}
+
+fn unicode_words_english(bench: &mut Bencher) {
+    unicode_words(bench, "benches/texts/english.txt");
+}
+
+fn unicode_words_hindi(bench: &mut Bencher) {
+    unicode_words(bench, "benches/texts/hindi.txt");
+}
+
+fn unicode_words_japanese(bench: &mut Bencher) {
+    unicode_words(bench, "benches/texts/japanese.txt");
+}
+
+fn unicode_words_korean(bench: &mut Bencher) {
+    unicode_words(bench, "benches/texts/korean.txt");
+}
+
+fn unicode_words_mandarin(bench: &mut Bencher) {
+    unicode_words(bench, "benches/texts/mandarin.txt");
+}
+
+fn unicode_words_russian(bench: &mut Bencher) {
+    unicode_words(bench, "benches/texts/russian.txt");
+}
+
+fn unicode_words_source_code(bench: &mut Bencher) {
+    unicode_words(bench, "benches/texts/source_code.txt");
+}
+
+benchmark_group!(
+    benches,
+    unicode_words_arabic,
+    unicode_words_english,
+    unicode_words_hindi,
+    unicode_words_japanese,
+    unicode_words_korean,
+    unicode_words_mandarin,
+    unicode_words_russian,
+    unicode_words_source_code,
+);
+
+benchmark_main!(benches);
diff --git a/vendor/unicode-segmentation/benches/word_bounds.rs b/vendor/unicode-segmentation/benches/word_bounds.rs
new file mode 100644 (file)
index 0000000..035f57e
--- /dev/null
@@ -0,0 +1,64 @@
+#[macro_use]
+extern crate bencher;
+extern crate unicode_segmentation;
+
+use bencher::Bencher;
+use unicode_segmentation::UnicodeSegmentation;
+use std::fs;
+
+fn word_bounds(bench: &mut Bencher, path: &str) {
+    let text = fs::read_to_string(path).unwrap();
+    bench.iter(|| {
+        for w in text.split_word_bounds() {
+            bencher::black_box(w);
+        }
+    });
+
+    bench.bytes = text.len() as u64;
+}
+
+fn word_bounds_arabic(bench: &mut Bencher) {
+    word_bounds(bench, "benches/texts/arabic.txt");
+}
+
+fn word_bounds_english(bench: &mut Bencher) {
+    word_bounds(bench, "benches/texts/english.txt");
+}
+
+fn word_bounds_hindi(bench: &mut Bencher) {
+    word_bounds(bench, "benches/texts/hindi.txt");
+}
+
+fn word_bounds_japanese(bench: &mut Bencher) {
+    word_bounds(bench, "benches/texts/japanese.txt");
+}
+
+fn word_bounds_korean(bench: &mut Bencher) {
+    word_bounds(bench, "benches/texts/korean.txt");
+}
+
+fn word_bounds_mandarin(bench: &mut Bencher) {
+    word_bounds(bench, "benches/texts/mandarin.txt");
+}
+
+fn word_bounds_russian(bench: &mut Bencher) {
+    word_bounds(bench, "benches/texts/russian.txt");
+}
+
+fn word_bounds_source_code(bench: &mut Bencher) {
+    word_bounds(bench, "benches/texts/source_code.txt");
+}
+
+benchmark_group!(
+    benches,
+    word_bounds_arabic,
+    word_bounds_english,
+    word_bounds_hindi,
+    word_bounds_japanese,
+    word_bounds_korean,
+    word_bounds_mandarin,
+    word_bounds_russian,
+    word_bounds_source_code,
+);
+
+benchmark_main!(benches);
index 1841e353022493802f365ac0c396740eee9d176f..16e321dd76ebc78f6b78162f261bff41c9ea3ce0 100644 (file)
@@ -229,7 +229,7 @@ pub mod util {
     #[inline]
     fn is_alphabetic(c: char) -> bool {
         match c {
-            'a' ... 'z' | 'A' ... 'Z' => true,
+            'a' ..= 'z' | 'A' ..= 'Z' => true,
             c if c > '\x7f' => super::derived_property::Alphabetic(c),
             _ => false,
         }
@@ -238,7 +238,7 @@ pub mod util {
     #[inline]
     fn is_numeric(c: char) -> bool {
         match c {
-            '0' ... '9' => true,
+            '0' ..= '9' => true,
             c if c > '\x7f' => super::general_category::N(c),
             _ => false,
         }
@@ -281,7 +281,6 @@ def emit_break_module(f, break_table, break_cats, name):
     f.write("""    }
 
     fn bsearch_range_value_table(c: char, r: &'static [(char, char, %sCat)]) -> (u32, u32, %sCat) {
-        use core;
         use core::cmp::Ordering::{Equal, Less, Greater};
         match r.binary_search_by(|&(lo, hi, _)| {
             if lo <= c && c <= hi { Equal }
index e95d47878479445ab6fb96d7a3d63bdb642e73da..190b86edb73e9de5c7f7d67d928a8325be0b5789 100644 (file)
@@ -10,7 +10,7 @@
 
 use core::cmp;
 
-use tables::grapheme::GraphemeCat;
+use crate::tables::grapheme::GraphemeCat;
 
 /// External iterator for grapheme clusters and byte offsets.
 ///
@@ -73,7 +73,7 @@ impl<'a> DoubleEndedIterator for GraphemeIndices<'a> {
 ///
 /// [`graphemes`]: trait.UnicodeSegmentation.html#tymethod.graphemes
 /// [`UnicodeSegmentation`]: trait.UnicodeSegmentation.html
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct Graphemes<'a> {
     string: &'a str,
     cursor: GraphemeCursor,
@@ -148,7 +148,7 @@ pub fn new_grapheme_indices<'b>(s: &'b str, is_extended: bool) -> GraphemeIndice
 
 // maybe unify with PairResult?
 // An enum describing information about a potential boundary.
-#[derive(PartialEq, Eq, Clone)]
+#[derive(PartialEq, Eq, Clone, Debug)]
 enum GraphemeState {
     // No information is known.
     Unknown,
@@ -165,7 +165,7 @@ enum GraphemeState {
 }
 
 /// Cursor-based segmenter for grapheme clusters.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct GraphemeCursor {
     // Current cursor position.
     offset: usize,
@@ -228,8 +228,9 @@ enum PairResult {
     Emoji,  // a break if preceded by emoji base and (Extend)*
 }
 
+#[inline]
 fn check_pair(before: GraphemeCat, after: GraphemeCat) -> PairResult {
-    use tables::grapheme::GraphemeCat::*;
+    use crate::tables::grapheme::GraphemeCat::*;
     use self::PairResult::*;
     match (before, after) {
         (GC_CR, GC_LF) => NotBreak,  // GB3
@@ -295,8 +296,8 @@ impl GraphemeCursor {
     }
 
     fn grapheme_category(&mut self, ch: char) -> GraphemeCat {
-        use tables::grapheme as gr;
-        use tables::grapheme::GraphemeCat::*;
+        use crate::tables::grapheme as gr;
+        use crate::tables::grapheme::GraphemeCat::*;
 
         if ch <= '\u{7e}' {
             // Special-case optimization for ascii, except U+007F.  This
@@ -387,7 +388,7 @@ impl GraphemeCursor {
     /// assert_eq!(cursor.is_boundary(&flags[8..], 8), Ok(true));
     /// ```
     pub fn provide_context(&mut self, chunk: &str, chunk_start: usize) {
-        use tables::grapheme as gr;
+        use crate::tables::grapheme as gr;
         assert!(chunk_start + chunk.len() == self.pre_context_offset.unwrap());
         self.pre_context_offset = None;
         if self.is_extended && chunk_start + chunk.len() == self.offset {
@@ -407,6 +408,7 @@ impl GraphemeCursor {
         }
     }
 
+    #[inline]
     fn decide(&mut self, is_break: bool) {
         self.state = if is_break {
             GraphemeState::Break
@@ -415,11 +417,13 @@ impl GraphemeCursor {
         };
     }
 
+    #[inline]
     fn decision(&mut self, is_break: bool) -> Result<bool, GraphemeIncomplete> {
         self.decide(is_break);
         Ok(is_break)
     }
 
+    #[inline]
     fn is_boundary_result(&self) -> Result<bool, GraphemeIncomplete> {
         if self.state == GraphemeState::Break {
             Ok(true)
@@ -432,8 +436,9 @@ impl GraphemeCursor {
         }
     }
 
+    #[inline]
     fn handle_regional(&mut self, chunk: &str, chunk_start: usize) {
-        use tables::grapheme as gr;
+        use crate::tables::grapheme as gr;
         let mut ris_count = self.ris_count.unwrap_or(0);
         for ch in chunk.chars().rev() {
             if self.grapheme_category(ch) != gr::GC_Regional_Indicator {
@@ -452,8 +457,9 @@ impl GraphemeCursor {
         self.state = GraphemeState::Regional;
     }
 
+    #[inline]
     fn handle_emoji(&mut self, chunk: &str, chunk_start: usize) {
-        use tables::grapheme as gr;
+        use crate::tables::grapheme as gr;
         let mut iter = chunk.chars().rev();
         if let Some(ch) = iter.next() {
             if self.grapheme_category(ch) != gr::GC_ZWJ {
@@ -482,6 +488,7 @@ impl GraphemeCursor {
         self.state = GraphemeState::Emoji;
     }
 
+    #[inline]
     /// Determine whether the current cursor location is a grapheme cluster boundary.
     /// Only a part of the string need be supplied. If `chunk_start` is nonzero or
     /// the length of `chunk` is not equal to `len` on creation, then this method
@@ -506,7 +513,7 @@ impl GraphemeCursor {
     /// assert_eq!(cursor.is_boundary(flags, 0), Ok(false));
     /// ```
     pub fn is_boundary(&mut self, chunk: &str, chunk_start: usize) -> Result<bool, GraphemeIncomplete> {
-        use tables::grapheme as gr;
+        use crate::tables::grapheme as gr;
         if self.state == GraphemeState::Break {
             return Ok(true)
         }
@@ -563,6 +570,7 @@ impl GraphemeCursor {
         }
     }
 
+    #[inline]
     /// Find the next boundary after the current cursor position. Only a part of
     /// the string need be supplied. If the chunk is incomplete, then this
     /// method might return `GraphemeIncomplete::PreContext` or
index b0ed2d1aa73d280a16ff8c2108dcbb0ea303b541..ed74f8fd67dfdeac7178cf7d2213f61741607a6f 100644 (file)
@@ -66,7 +66,7 @@ extern crate quickcheck;
 pub use grapheme::{Graphemes, GraphemeIndices};
 pub use grapheme::{GraphemeCursor, GraphemeIncomplete};
 pub use tables::UNICODE_VERSION;
-pub use word::{UWordBounds, UWordBoundIndices, UnicodeWords};
+pub use word::{UWordBounds, UWordBoundIndices, UnicodeWords, UnicodeWordIndices};
 pub use sentence::{USentenceBounds, USentenceBoundIndices, UnicodeSentences};
 
 mod grapheme;
@@ -146,6 +146,30 @@ pub trait UnicodeSegmentation {
     /// ```
     fn unicode_words<'a>(&'a self) -> UnicodeWords<'a>;
 
+    /// Returns an iterator over the words of `self`, separated on
+    /// [UAX#29 word boundaries](http://www.unicode.org/reports/tr29/#Word_Boundaries), and their
+    /// offsets.
+    ///
+    /// Here, "words" are just those substrings which, after splitting on
+    /// UAX#29 word boundaries, contain any alphanumeric characters. That is, the
+    /// substring must contain at least one character with the
+    /// [Alphabetic](http://unicode.org/reports/tr44/#Alphabetic)
+    /// property, or with
+    /// [General_Category=Number](http://unicode.org/reports/tr44/#General_Category_Values).
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # use self::unicode_segmentation::UnicodeSegmentation;
+    /// let uwis = "The quick (\"brown\") fox can't jump 32.3 feet, right?";
+    /// let uwi1 = uwis.unicode_word_indices().collect::<Vec<(usize, &str)>>();
+    /// let b: &[_] = &[(0, "The"), (4, "quick"), (12, "brown"), (20, "fox"), (24, "can't"),
+    ///                 (30, "jump"), (35, "32.3"), (40, "feet"), (46, "right")];
+    ///
+    /// assert_eq!(&uwi1[..], b);
+    /// ```
+    fn unicode_word_indices<'a>(&'a self) -> UnicodeWordIndices<'a>;
+
     /// Returns an iterator over substrings of `self` separated on
     /// [UAX#29 word boundaries](http://www.unicode.org/reports/tr29/#Word_Boundaries).
     ///
@@ -249,6 +273,11 @@ impl UnicodeSegmentation for str {
         word::new_unicode_words(self)
     }
 
+    #[inline]
+    fn unicode_word_indices(&self) -> UnicodeWordIndices {
+        word::new_unicode_word_indices(self)
+    }
+
     #[inline]
     fn split_word_bounds(&self) -> UWordBounds {
         word::new_word_bounds(self)
index 275da520f11fb44242d0a3b5c92c01384edc21e9..0a23abdb1073dd7864ed3e5e08c44892fa4cd3a3 100644 (file)
@@ -13,7 +13,7 @@ use core::iter::Filter;
 
 // All of the logic for forward iteration over sentences
 mod fwd {
-    use tables::sentence::SentenceCat;
+    use crate::tables::sentence::SentenceCat;
     use core::cmp;
 
     // Describe a parsed part of source string as described in this table:
@@ -111,7 +111,7 @@ mod fwd {
         if parts[idx] == StatePart::ClosePlus { idx -= 1 }
 
         if parts[idx] == StatePart::ATerm {
-            use tables::sentence as se;
+            use crate::tables::sentence as se;
 
             for next_char in ahead.chars() {
                 //( ¬(OLetter | Upper | Lower | ParaSep | SATerm) )* Lower
@@ -176,7 +176,7 @@ mod fwd {
 
         #[inline]
         fn next(&mut self) -> Option<usize> {
-            use tables::sentence as se;
+            use crate::tables::sentence as se;
 
             for next_char in self.string[self.pos..].chars() {
                 let position_before = self.pos;
@@ -331,7 +331,7 @@ pub fn new_sentence_bound_indices<'a>(source: &'a str) -> USentenceBoundIndices<
 #[inline]
 pub fn new_unicode_sentences<'b>(s: &'b str) -> UnicodeSentences<'b> {
     use super::UnicodeSegmentation;
-    use tables::util::is_alphanumeric;
+    use crate::tables::util::is_alphanumeric;
 
     fn has_alphanumeric(s: &&str) -> bool { s.chars().any(|c| is_alphanumeric(c)) }
     let has_alphanumeric: fn(&&str) -> bool = has_alphanumeric; // coerce to fn pointer
index 7062e36edb1074e3044e5069ffef2fe56f4acde6..6d09ea223690524dcbbef9ca13e904c581c5c260 100644 (file)
@@ -30,7 +30,7 @@ pub mod util {
     #[inline]
     fn is_alphabetic(c: char) -> bool {
         match c {
-            'a' ... 'z' | 'A' ... 'Z' => true,
+            'a' ..= 'z' | 'A' ..= 'Z' => true,
             c if c > '\7f' => super::derived_property::Alphabetic(c),
             _ => false,
         }
@@ -39,7 +39,7 @@ pub mod util {
     #[inline]
     fn is_numeric(c: char) -> bool {
         match c {
-            '0' ... '9' => true,
+            '0' ..= '9' => true,
             c if c > '\7f' => super::general_category::N(c),
             _ => false,
         }
@@ -352,7 +352,6 @@ pub mod grapheme {
     }
 
     fn bsearch_range_value_table(c: char, r: &'static [(char, char, GraphemeCat)]) -> (u32, u32, GraphemeCat) {
-        use core;
         use core::cmp::Ordering::{Equal, Less, Greater};
         match r.binary_search_by(|&(lo, hi, _)| {
             if lo <= c && c <= hi { Equal }
@@ -1003,7 +1002,6 @@ pub mod word {
     }
 
     fn bsearch_range_value_table(c: char, r: &'static [(char, char, WordCat)]) -> (u32, u32, WordCat) {
-        use core;
         use core::cmp::Ordering::{Equal, Less, Greater};
         match r.binary_search_by(|&(lo, hi, _)| {
             if lo <= c && c <= hi { Equal }
@@ -1479,7 +1477,6 @@ pub mod emoji {
     }
 
     fn bsearch_range_value_table(c: char, r: &'static [(char, char, EmojiCat)]) -> (u32, u32, EmojiCat) {
-        use core;
         use core::cmp::Ordering::{Equal, Less, Greater};
         match r.binary_search_by(|&(lo, hi, _)| {
             if lo <= c && c <= hi { Equal }
@@ -1583,7 +1580,6 @@ pub mod sentence {
     }
 
     fn bsearch_range_value_table(c: char, r: &'static [(char, char, SentenceCat)]) -> (u32, u32, SentenceCat) {
-        use core;
         use core::cmp::Ordering::{Equal, Less, Greater};
         match r.binary_search_by(|&(lo, hi, _)| {
             if lo <= c && c <= hi { Equal }
index 75b77c5aa76f92de7df13b1bec346852b97076b3..ae74c644fc9c34f2430385f1a16e47a4a48e8e9d 100644 (file)
@@ -14,7 +14,7 @@ use std::prelude::v1::*;
 
 #[test]
 fn test_graphemes() {
-    use testdata::{TEST_SAME, TEST_DIFF};
+    use crate::testdata::{TEST_SAME, TEST_DIFF};
 
     pub const EXTRA_DIFF: &'static [(&'static str,
                                      &'static [&'static str],
@@ -88,7 +88,7 @@ fn test_graphemes() {
 
 #[test]
 fn test_words() {
-    use testdata::TEST_WORD;
+    use crate::testdata::TEST_WORD;
 
     // Unicode's official tests don't really test longer chains of flag emoji
     // TODO This could be improved with more tests like flag emoji with interspersed Extend chars and ZWJ
@@ -144,7 +144,7 @@ fn test_words() {
 
 #[test]
 fn test_sentences() {
-    use testdata::TEST_SENTENCE;
+    use crate::testdata::TEST_SENTENCE;
 
     for &(s, w) in TEST_SENTENCE.iter() {
         macro_rules! assert_ {
index 179d122431e07bb6b614a9d9c3a00189e5ab558a..5cfde0d86ab08fbd8bb380a7b021558db55361bf 100644 (file)
@@ -11,7 +11,7 @@
 use core::cmp;
 use core::iter::Filter;
 
-use tables::word::WordCat;
+use crate::tables::word::WordCat;
 
 /// An iterator over the substrings of a string which, after splitting the string on
 /// [word boundaries](http://www.unicode.org/reports/tr29/#Word_Boundaries),
@@ -40,6 +40,34 @@ impl<'a> DoubleEndedIterator for UnicodeWords<'a> {
     fn next_back(&mut self) -> Option<&'a str> { self.inner.next_back() }
 }
 
+/// An iterator over the substrings of a string which, after splitting the string on
+/// [word boundaries](http://www.unicode.org/reports/tr29/#Word_Boundaries),
+/// contain any characters with the
+/// [Alphabetic](http://unicode.org/reports/tr44/#Alphabetic)
+/// property, or with
+/// [General_Category=Number](http://unicode.org/reports/tr44/#General_Category_Values).
+/// This iterator also provides the byte offsets for each substring.
+///
+/// This struct is created by the [`unicode_word_indices`] method on the [`UnicodeSegmentation`] trait. See
+/// its documentation for more.
+///
+/// [`unicode_word_indices`]: trait.UnicodeSegmentation.html#tymethod.unicode_word_indices
+/// [`UnicodeSegmentation`]: trait.UnicodeSegmentation.html
+pub struct UnicodeWordIndices<'a> {
+    inner: Filter<UWordBoundIndices<'a>, fn(&(usize, &str)) -> bool>,
+}
+
+impl<'a> Iterator for UnicodeWordIndices<'a> {
+    type Item = (usize, &'a str);
+
+    #[inline]
+    fn next(&mut self) -> Option<(usize, &'a str)> { self.inner.next() }
+}
+impl<'a> DoubleEndedIterator for UnicodeWordIndices<'a> {
+    #[inline]
+    fn next_back(&mut self) -> Option<(usize, &'a str)> { self.inner.next_back() }
+}
+
 /// External iterator for a string's
 /// [word boundaries](http://www.unicode.org/reports/tr29/#Word_Boundaries).
 ///
@@ -142,7 +170,7 @@ enum RegionalState {
 }
 
 fn is_emoji(ch: char) -> bool {
-    use tables::emoji;
+    use crate::tables::emoji;
     emoji::emoji_category(ch).2 == emoji::EmojiCat::EC_Extended_Pictographic
 }
 
@@ -159,7 +187,7 @@ impl<'a> Iterator for UWordBounds<'a> {
     fn next(&mut self) -> Option<&'a str> {
         use self::UWordBoundsState::*;
         use self::FormatExtendType::*;
-        use tables::word as wd;
+        use crate::tables::word as wd;
         if self.string.len() == 0 {
             return None;
         }
@@ -172,14 +200,13 @@ impl<'a> Iterator for UWordBounds<'a> {
         let mut cat = wd::WC_Any;
         let mut savecat = wd::WC_Any;
 
-        // Whether or not the previous category was ZWJ
-        // ZWJs get collapsed, so this handles precedence of WB3c over WB4
-        let mut prev_zwj;
         // If extend/format/zwj were skipped. Handles precedence of WB3d over WB4
         let mut skipped_format_extend = false;
         for (curr, ch) in self.string.char_indices() {
             idx = curr;
-            prev_zwj = cat == wd::WC_ZWJ;
+            // Whether or not the previous category was ZWJ
+            // ZWJs get collapsed, so this handles precedence of WB3c over WB4
+            let prev_zwj = cat == wd::WC_ZWJ;
             // if there's a category cached, grab it
             cat = match self.cat {
                 None => wd::word_category(ch).2,
@@ -386,7 +413,7 @@ impl<'a> DoubleEndedIterator for UWordBounds<'a> {
     fn next_back(&mut self) -> Option<&'a str> {
         use self::UWordBoundsState::*;
         use self::FormatExtendType::*;
-        use tables::word as wd;
+        use crate::tables::word as wd;
         if self.string.len() == 0 {
             return None;
         }
@@ -638,7 +665,7 @@ impl<'a> UWordBounds<'a> {
 
     #[inline]
     fn get_next_cat(&self, idx: usize) -> Option<WordCat> {
-        use tables::word as wd;
+        use crate::tables::word as wd;
         let nidx = idx + self.string[idx..].chars().next().unwrap().len_utf8();
         if nidx < self.string.len() {
             let nch = self.string[nidx..].chars().next().unwrap();
@@ -650,7 +677,7 @@ impl<'a> UWordBounds<'a> {
 
     #[inline]
     fn get_prev_cat(&self, idx: usize) -> Option<WordCat> {
-        use tables::word as wd;
+        use crate::tables::word as wd;
         if idx > 0 {
             let nch = self.string[..idx].chars().next_back().unwrap();
             Some(wd::word_category(nch).2)
@@ -670,13 +697,23 @@ pub fn new_word_bound_indices<'b>(s: &'b str) -> UWordBoundIndices<'b> {
     UWordBoundIndices { start_offset: s.as_ptr() as usize, iter: new_word_bounds(s) }
 }
 
+#[inline]
+fn has_alphanumeric(s: &&str) -> bool {
+    use crate::tables::util::is_alphanumeric;
+
+    s.chars().any(|c| is_alphanumeric(c))
+}
+
 #[inline]
 pub fn new_unicode_words<'b>(s: &'b str) -> UnicodeWords<'b> {
     use super::UnicodeSegmentation;
-    use tables::util::is_alphanumeric;
-
-    fn has_alphanumeric(s: &&str) -> bool { s.chars().any(|c| is_alphanumeric(c)) }
-    let has_alphanumeric: fn(&&str) -> bool = has_alphanumeric; // coerce to fn pointer
 
     UnicodeWords { inner: s.split_word_bounds().filter(has_alphanumeric) }
 }
+
+#[inline]
+pub fn new_unicode_word_indices<'b>(s: &'b str) -> UnicodeWordIndices<'b> {
+    use super::UnicodeSegmentation;
+
+    UnicodeWordIndices { inner: s.split_word_bound_indices().filter(|(_, c)| has_alphanumeric(c)) }
+}
diff --git a/version b/version
index e17110f15f11ee988227b07a86b5da1e16c44266..ac67661f07f5f59fd10a64cf2d5328650bb4a8b5 100644 (file)
--- a/version
+++ b/version
@@ -1 +1 @@
-1.54.0 (a178d0322 2021-07-26)
\ No newline at end of file
+1.55.0 (c8dfcfe04 2021-09-06)
\ No newline at end of file